fw_mgmt
return fw_mgmt;
static int fw_mgmt_interface_fw_version_operation(struct fw_mgmt *fw_mgmt,
struct gb_connection *connection = fw_mgmt->connection;
dev_err(fw_mgmt->parent,
dev_err(fw_mgmt->parent,
static int fw_mgmt_load_and_validate_operation(struct fw_mgmt *fw_mgmt,
dev_err(fw_mgmt->parent,
dev_err(fw_mgmt->parent,
ret = ida_alloc_range(&fw_mgmt->id_map, 1, 255, GFP_KERNEL);
dev_err(fw_mgmt->parent, "failed to allocate request id (%d)\n",
fw_mgmt->intf_fw_request_id = ret;
fw_mgmt->intf_fw_loaded = false;
ret = gb_operation_sync(fw_mgmt->connection,
ida_free(&fw_mgmt->id_map, fw_mgmt->intf_fw_request_id);
fw_mgmt->intf_fw_request_id = 0;
dev_err(fw_mgmt->parent,
struct fw_mgmt *fw_mgmt = gb_connection_get_data(connection);
if (!fw_mgmt->intf_fw_request_id) {
dev_err(fw_mgmt->parent,
dev_err(fw_mgmt->parent, "illegal size of firmware loaded request (%zu != %zu)\n",
if (request->request_id != fw_mgmt->intf_fw_request_id) {
dev_err(fw_mgmt->parent, "invalid request id for firmware loaded request (%02u != %02u)\n",
fw_mgmt->intf_fw_request_id, request->request_id);
ida_free(&fw_mgmt->id_map, fw_mgmt->intf_fw_request_id);
fw_mgmt->intf_fw_request_id = 0;
fw_mgmt->intf_fw_status = request->status;
fw_mgmt->intf_fw_major = le16_to_cpu(request->major);
fw_mgmt->intf_fw_minor = le16_to_cpu(request->minor);
if (fw_mgmt->intf_fw_status == GB_FW_LOAD_STATUS_FAILED)
dev_err(fw_mgmt->parent,
fw_mgmt->intf_fw_status);
else if (fw_mgmt->intf_fw_status == GB_FW_LOAD_STATUS_VALIDATION_FAILED)
dev_err(fw_mgmt->parent,
fw_mgmt->intf_fw_status);
fw_mgmt->intf_fw_loaded = true;
complete(&fw_mgmt->completion);
static int fw_mgmt_backend_fw_version_operation(struct fw_mgmt *fw_mgmt,
struct gb_connection *connection = fw_mgmt->connection;
dev_err(fw_mgmt->parent,
dev_err(fw_mgmt->parent, "failed to get version of %s backend firmware (%d)\n",
dev_err(fw_mgmt->parent,
dev_err(fw_mgmt->parent, "Invalid status received: %u\n",
static int fw_mgmt_backend_fw_update_operation(struct fw_mgmt *fw_mgmt,
dev_err(fw_mgmt->parent,
ret = ida_alloc_range(&fw_mgmt->id_map, 1, 255, GFP_KERNEL);
dev_err(fw_mgmt->parent, "failed to allocate request id (%d)\n",
fw_mgmt->backend_fw_request_id = ret;
ret = gb_operation_sync(fw_mgmt->connection,
ida_free(&fw_mgmt->id_map, fw_mgmt->backend_fw_request_id);
fw_mgmt->backend_fw_request_id = 0;
dev_err(fw_mgmt->parent,
struct fw_mgmt *fw_mgmt = gb_connection_get_data(connection);
if (!fw_mgmt->backend_fw_request_id) {
dev_err(fw_mgmt->parent, "unexpected backend firmware updated request received\n");
dev_err(fw_mgmt->parent, "illegal size of backend firmware updated request (%zu != %zu)\n",
if (request->request_id != fw_mgmt->backend_fw_request_id) {
dev_err(fw_mgmt->parent, "invalid request id for backend firmware updated request (%02u != %02u)\n",
fw_mgmt->backend_fw_request_id, request->request_id);
ida_free(&fw_mgmt->id_map, fw_mgmt->backend_fw_request_id);
fw_mgmt->backend_fw_request_id = 0;
fw_mgmt->backend_fw_status = request->status;
if ((fw_mgmt->backend_fw_status != GB_FW_BACKEND_FW_STATUS_SUCCESS) &&
(fw_mgmt->backend_fw_status != GB_FW_BACKEND_FW_STATUS_RETRY))
dev_err(fw_mgmt->parent,
fw_mgmt->backend_fw_status);
complete(&fw_mgmt->completion);
struct fw_mgmt *fw_mgmt = get_fw_mgmt(inode->i_cdev);
if (fw_mgmt) {
file->private_data = fw_mgmt;
struct fw_mgmt *fw_mgmt = file->private_data;
put_fw_mgmt(fw_mgmt);
static int fw_mgmt_ioctl(struct fw_mgmt *fw_mgmt, unsigned int cmd,
if (fw_mgmt->mode_switch_started)
ret = fw_mgmt_interface_fw_version_operation(fw_mgmt,
ret = fw_mgmt_backend_fw_version_operation(fw_mgmt,
ret = fw_mgmt_load_and_validate_operation(fw_mgmt,
if (!wait_for_completion_timeout(&fw_mgmt->completion,
fw_mgmt->timeout_jiffies)) {
dev_err(fw_mgmt->parent, "timed out waiting for firmware load and validation to finish\n");
intf_load.status = fw_mgmt->intf_fw_status;
intf_load.major = fw_mgmt->intf_fw_major;
intf_load.minor = fw_mgmt->intf_fw_minor;
ret = fw_mgmt_backend_fw_update_operation(fw_mgmt,
if (!wait_for_completion_timeout(&fw_mgmt->completion,
fw_mgmt->timeout_jiffies)) {
dev_err(fw_mgmt->parent, "timed out waiting for backend firmware update to finish\n");
backend_update.status = fw_mgmt->backend_fw_status;
dev_err(fw_mgmt->parent, "timeout can't be zero\n");
fw_mgmt->timeout_jiffies = msecs_to_jiffies(timeout);
if (!fw_mgmt->intf_fw_loaded) {
dev_err(fw_mgmt->parent,
fw_mgmt->mode_switch_started = true;
ret = gb_interface_request_mode_switch(fw_mgmt->connection->intf);
dev_err(fw_mgmt->parent, "Mode-switch failed: %d\n",
fw_mgmt->mode_switch_started = false;
struct fw_mgmt *fw_mgmt = file->private_data;
struct gb_bundle *bundle = fw_mgmt->connection->bundle;
mutex_lock(&fw_mgmt->mutex);
if (!fw_mgmt->disabled) {
ret = fw_mgmt_ioctl(fw_mgmt, cmd, (void __user *)arg);
mutex_unlock(&fw_mgmt->mutex);
struct fw_mgmt *fw_mgmt;
fw_mgmt = kzalloc_obj(*fw_mgmt);
if (!fw_mgmt)
fw_mgmt->parent = &connection->bundle->dev;
fw_mgmt->timeout_jiffies = msecs_to_jiffies(FW_MGMT_TIMEOUT_MS);
fw_mgmt->connection = connection;
gb_connection_set_data(connection, fw_mgmt);
init_completion(&fw_mgmt->completion);
ida_init(&fw_mgmt->id_map);
mutex_init(&fw_mgmt->mutex);
kref_init(&fw_mgmt->kref);
list_add(&fw_mgmt->node, &fw_mgmt_list);
fw_mgmt->dev_num = MKDEV(MAJOR(fw_mgmt_dev_num), minor);
cdev_init(&fw_mgmt->cdev, &fw_mgmt_fops);
ret = cdev_add(&fw_mgmt->cdev, fw_mgmt->dev_num, 1);
fw_mgmt->class_device = device_create(&fw_mgmt_class, fw_mgmt->parent,
fw_mgmt->dev_num, NULL,
if (IS_ERR(fw_mgmt->class_device)) {
ret = PTR_ERR(fw_mgmt->class_device);
cdev_del(&fw_mgmt->cdev);
list_del(&fw_mgmt->node);
put_fw_mgmt(fw_mgmt);
struct fw_mgmt *fw_mgmt;
fw_mgmt = gb_connection_get_data(connection);
device_destroy(&fw_mgmt_class, fw_mgmt->dev_num);
cdev_del(&fw_mgmt->cdev);
ida_free(&fw_mgmt_minors_map, MINOR(fw_mgmt->dev_num));
mutex_lock(&fw_mgmt->mutex);
fw_mgmt->disabled = true;
mutex_unlock(&fw_mgmt->mutex);
gb_connection_disable(fw_mgmt->connection);
list_del(&fw_mgmt->node);
put_fw_mgmt(fw_mgmt);
struct fw_mgmt *fw_mgmt = container_of(kref, struct fw_mgmt, kref);
ida_destroy(&fw_mgmt->id_map);
kfree(fw_mgmt);
static void put_fw_mgmt(struct fw_mgmt *fw_mgmt)
kref_put(&fw_mgmt->kref, fw_mgmt_kref_release);
static struct fw_mgmt *get_fw_mgmt(struct cdev *cdev)
struct fw_mgmt *fw_mgmt;
list_for_each_entry(fw_mgmt, &fw_mgmt_list, node) {
if (&fw_mgmt->cdev == cdev) {
kref_get(&fw_mgmt->kref);
fw_mgmt = NULL;