diff options
Diffstat (limited to 'drivers/base/firmware_class.c')
-rw-r--r-- | drivers/base/firmware_class.c | 27 |
1 files changed, 19 insertions, 8 deletions
diff --git a/drivers/base/firmware_class.c b/drivers/base/firmware_class.c index 8a267c42762..ddeb819c8f8 100644 --- a/drivers/base/firmware_class.c +++ b/drivers/base/firmware_class.c @@ -40,7 +40,7 @@ static int loading_timeout = 60; /* In seconds */ static DEFINE_MUTEX(fw_lock); struct firmware_priv { - char fw_id[FIRMWARE_NAME_MAX]; + char *fw_id; struct completion completion; struct bin_attribute attr_data; struct firmware *fw; @@ -355,8 +355,9 @@ static void fw_dev_release(struct device *dev) for (i = 0; i < fw_priv->nr_pages; i++) __free_page(fw_priv->pages[i]); kfree(fw_priv->pages); + kfree(fw_priv->fw_id); kfree(fw_priv); - kfree(dev); + put_device(dev); module_put(THIS_MODULE); } @@ -386,13 +387,19 @@ static int fw_register_device(struct device **dev_p, const char *fw_name, init_completion(&fw_priv->completion); fw_priv->attr_data = firmware_attr_data_tmpl; - strlcpy(fw_priv->fw_id, fw_name, FIRMWARE_NAME_MAX); + fw_priv->fw_id = kstrdup(fw_name, GFP_KERNEL); + if (!fw_priv->fw_id) { + dev_err(device, "%s: Firmware name allocation failed\n", + __func__); + retval = -ENOMEM; + goto error_kfree; + } fw_priv->timeout.function = firmware_class_timeout; fw_priv->timeout.data = (u_long) fw_priv; init_timer(&fw_priv->timeout); - dev_set_name(f_dev, dev_name(device)); + dev_set_name(f_dev, "%s", dev_name(device)); f_dev->parent = device; f_dev->class = &firmware_class; dev_set_drvdata(f_dev, fw_priv); @@ -400,14 +407,17 @@ static int fw_register_device(struct device **dev_p, const char *fw_name, retval = device_register(f_dev); if (retval) { dev_err(device, "%s: device_register failed\n", __func__); - goto error_kfree; + put_device(f_dev); + goto error_kfree_fw_id; } *dev_p = f_dev; return 0; +error_kfree_fw_id: + kfree(fw_priv->fw_id); error_kfree: - kfree(fw_priv); kfree(f_dev); + kfree(fw_priv); return retval; } @@ -615,8 +625,9 @@ request_firmware_work_func(void *arg) * @cont: function will be called asynchronously when the firmware * request is over. * - * Asynchronous variant of request_firmware() for contexts where - * it is not possible to sleep. + * Asynchronous variant of request_firmware() for user contexts where + * it is not possible to sleep for long time. It can't be called + * in atomic contexts. **/ int request_firmware_nowait( |