diff options
Diffstat (limited to 'drivers/base/firmware_class.c')
-rw-r--r-- | drivers/base/firmware_class.c | 52 |
1 files changed, 40 insertions, 12 deletions
diff --git a/drivers/base/firmware_class.c b/drivers/base/firmware_class.c index 8945f4e489ed..d81460309182 100644 --- a/drivers/base/firmware_class.c +++ b/drivers/base/firmware_class.c | |||
@@ -143,7 +143,7 @@ struct fw_cache_entry { | |||
143 | }; | 143 | }; |
144 | 144 | ||
145 | struct firmware_priv { | 145 | struct firmware_priv { |
146 | struct timer_list timeout; | 146 | struct delayed_work timeout_work; |
147 | bool nowait; | 147 | bool nowait; |
148 | struct device dev; | 148 | struct device dev; |
149 | struct firmware_buf *buf; | 149 | struct firmware_buf *buf; |
@@ -246,7 +246,6 @@ static void __fw_free_buf(struct kref *ref) | |||
246 | __func__, buf->fw_id, buf, buf->data, | 246 | __func__, buf->fw_id, buf, buf->data, |
247 | (unsigned int)buf->size); | 247 | (unsigned int)buf->size); |
248 | 248 | ||
249 | spin_lock(&fwc->lock); | ||
250 | list_del(&buf->list); | 249 | list_del(&buf->list); |
251 | spin_unlock(&fwc->lock); | 250 | spin_unlock(&fwc->lock); |
252 | 251 | ||
@@ -263,19 +262,32 @@ static void __fw_free_buf(struct kref *ref) | |||
263 | 262 | ||
264 | static void fw_free_buf(struct firmware_buf *buf) | 263 | static void fw_free_buf(struct firmware_buf *buf) |
265 | { | 264 | { |
266 | kref_put(&buf->ref, __fw_free_buf); | 265 | struct firmware_cache *fwc = buf->fwc; |
266 | spin_lock(&fwc->lock); | ||
267 | if (!kref_put(&buf->ref, __fw_free_buf)) | ||
268 | spin_unlock(&fwc->lock); | ||
267 | } | 269 | } |
268 | 270 | ||
269 | /* direct firmware loading support */ | 271 | /* direct firmware loading support */ |
270 | static const char *fw_path[] = { | 272 | static char fw_path_para[256]; |
273 | static const char * const fw_path[] = { | ||
274 | fw_path_para, | ||
271 | "/lib/firmware/updates/" UTS_RELEASE, | 275 | "/lib/firmware/updates/" UTS_RELEASE, |
272 | "/lib/firmware/updates", | 276 | "/lib/firmware/updates", |
273 | "/lib/firmware/" UTS_RELEASE, | 277 | "/lib/firmware/" UTS_RELEASE, |
274 | "/lib/firmware" | 278 | "/lib/firmware" |
275 | }; | 279 | }; |
276 | 280 | ||
281 | /* | ||
282 | * Typical usage is that passing 'firmware_class.path=$CUSTOMIZED_PATH' | ||
283 | * from kernel command line because firmware_class is generally built in | ||
284 | * kernel instead of module. | ||
285 | */ | ||
286 | module_param_string(path, fw_path_para, sizeof(fw_path_para), 0644); | ||
287 | MODULE_PARM_DESC(path, "customized firmware image search path with a higher priority than default path"); | ||
288 | |||
277 | /* Don't inline this: 'struct kstat' is biggish */ | 289 | /* Don't inline this: 'struct kstat' is biggish */ |
278 | static noinline long fw_file_size(struct file *file) | 290 | static noinline_for_stack long fw_file_size(struct file *file) |
279 | { | 291 | { |
280 | struct kstat st; | 292 | struct kstat st; |
281 | if (vfs_getattr(file->f_path.mnt, file->f_path.dentry, &st)) | 293 | if (vfs_getattr(file->f_path.mnt, file->f_path.dentry, &st)) |
@@ -315,6 +327,11 @@ static bool fw_get_filesystem_firmware(struct firmware_buf *buf) | |||
315 | 327 | ||
316 | for (i = 0; i < ARRAY_SIZE(fw_path); i++) { | 328 | for (i = 0; i < ARRAY_SIZE(fw_path); i++) { |
317 | struct file *file; | 329 | struct file *file; |
330 | |||
331 | /* skip the unset customized path */ | ||
332 | if (!fw_path[i][0]) | ||
333 | continue; | ||
334 | |||
318 | snprintf(path, PATH_MAX, "%s/%s", fw_path[i], buf->fw_id); | 335 | snprintf(path, PATH_MAX, "%s/%s", fw_path[i], buf->fw_id); |
319 | 336 | ||
320 | file = filp_open(path, O_RDONLY, 0); | 337 | file = filp_open(path, O_RDONLY, 0); |
@@ -667,11 +684,18 @@ static struct bin_attribute firmware_attr_data = { | |||
667 | .write = firmware_data_write, | 684 | .write = firmware_data_write, |
668 | }; | 685 | }; |
669 | 686 | ||
670 | static void firmware_class_timeout(u_long data) | 687 | static void firmware_class_timeout_work(struct work_struct *work) |
671 | { | 688 | { |
672 | struct firmware_priv *fw_priv = (struct firmware_priv *) data; | 689 | struct firmware_priv *fw_priv = container_of(work, |
690 | struct firmware_priv, timeout_work.work); | ||
673 | 691 | ||
692 | mutex_lock(&fw_lock); | ||
693 | if (test_bit(FW_STATUS_DONE, &(fw_priv->buf->status))) { | ||
694 | mutex_unlock(&fw_lock); | ||
695 | return; | ||
696 | } | ||
674 | fw_load_abort(fw_priv); | 697 | fw_load_abort(fw_priv); |
698 | mutex_unlock(&fw_lock); | ||
675 | } | 699 | } |
676 | 700 | ||
677 | static struct firmware_priv * | 701 | static struct firmware_priv * |
@@ -690,8 +714,8 @@ fw_create_instance(struct firmware *firmware, const char *fw_name, | |||
690 | 714 | ||
691 | fw_priv->nowait = nowait; | 715 | fw_priv->nowait = nowait; |
692 | fw_priv->fw = firmware; | 716 | fw_priv->fw = firmware; |
693 | setup_timer(&fw_priv->timeout, | 717 | INIT_DELAYED_WORK(&fw_priv->timeout_work, |
694 | firmware_class_timeout, (u_long) fw_priv); | 718 | firmware_class_timeout_work); |
695 | 719 | ||
696 | f_dev = &fw_priv->dev; | 720 | f_dev = &fw_priv->dev; |
697 | 721 | ||
@@ -858,7 +882,9 @@ static int _request_firmware_load(struct firmware_priv *fw_priv, bool uevent, | |||
858 | dev_dbg(f_dev->parent, "firmware: direct-loading" | 882 | dev_dbg(f_dev->parent, "firmware: direct-loading" |
859 | " firmware %s\n", buf->fw_id); | 883 | " firmware %s\n", buf->fw_id); |
860 | 884 | ||
885 | mutex_lock(&fw_lock); | ||
861 | set_bit(FW_STATUS_DONE, &buf->status); | 886 | set_bit(FW_STATUS_DONE, &buf->status); |
887 | mutex_unlock(&fw_lock); | ||
862 | complete_all(&buf->completion); | 888 | complete_all(&buf->completion); |
863 | direct_load = 1; | 889 | direct_load = 1; |
864 | goto handle_fw; | 890 | goto handle_fw; |
@@ -894,15 +920,14 @@ static int _request_firmware_load(struct firmware_priv *fw_priv, bool uevent, | |||
894 | dev_set_uevent_suppress(f_dev, false); | 920 | dev_set_uevent_suppress(f_dev, false); |
895 | dev_dbg(f_dev, "firmware: requesting %s\n", buf->fw_id); | 921 | dev_dbg(f_dev, "firmware: requesting %s\n", buf->fw_id); |
896 | if (timeout != MAX_SCHEDULE_TIMEOUT) | 922 | if (timeout != MAX_SCHEDULE_TIMEOUT) |
897 | mod_timer(&fw_priv->timeout, | 923 | schedule_delayed_work(&fw_priv->timeout_work, timeout); |
898 | round_jiffies_up(jiffies + timeout)); | ||
899 | 924 | ||
900 | kobject_uevent(&fw_priv->dev.kobj, KOBJ_ADD); | 925 | kobject_uevent(&fw_priv->dev.kobj, KOBJ_ADD); |
901 | } | 926 | } |
902 | 927 | ||
903 | wait_for_completion(&buf->completion); | 928 | wait_for_completion(&buf->completion); |
904 | 929 | ||
905 | del_timer_sync(&fw_priv->timeout); | 930 | cancel_delayed_work_sync(&fw_priv->timeout_work); |
906 | 931 | ||
907 | handle_fw: | 932 | handle_fw: |
908 | mutex_lock(&fw_lock); | 933 | mutex_lock(&fw_lock); |
@@ -963,6 +988,9 @@ err_put_dev: | |||
963 | * firmware image for this or any other device. | 988 | * firmware image for this or any other device. |
964 | * | 989 | * |
965 | * Caller must hold the reference count of @device. | 990 | * Caller must hold the reference count of @device. |
991 | * | ||
992 | * The function can be called safely inside device's suspend and | ||
993 | * resume callback. | ||
966 | **/ | 994 | **/ |
967 | int | 995 | int |
968 | request_firmware(const struct firmware **firmware_p, const char *name, | 996 | request_firmware(const struct firmware **firmware_p, const char *name, |