diff options
Diffstat (limited to 'drivers/base/firmware_class.c')
-rw-r--r-- | drivers/base/firmware_class.c | 132 |
1 files changed, 97 insertions, 35 deletions
diff --git a/drivers/base/firmware_class.c b/drivers/base/firmware_class.c index 01e21037d8fe..a439602ea919 100644 --- a/drivers/base/firmware_class.c +++ b/drivers/base/firmware_class.c | |||
@@ -27,6 +27,7 @@ | |||
27 | #include <linux/pm.h> | 27 | #include <linux/pm.h> |
28 | #include <linux/suspend.h> | 28 | #include <linux/suspend.h> |
29 | #include <linux/syscore_ops.h> | 29 | #include <linux/syscore_ops.h> |
30 | #include <linux/reboot.h> | ||
30 | 31 | ||
31 | #include <generated/utsrelease.h> | 32 | #include <generated/utsrelease.h> |
32 | 33 | ||
@@ -127,9 +128,11 @@ struct firmware_buf { | |||
127 | size_t size; | 128 | size_t size; |
128 | #ifdef CONFIG_FW_LOADER_USER_HELPER | 129 | #ifdef CONFIG_FW_LOADER_USER_HELPER |
129 | bool is_paged_buf; | 130 | bool is_paged_buf; |
131 | bool need_uevent; | ||
130 | struct page **pages; | 132 | struct page **pages; |
131 | int nr_pages; | 133 | int nr_pages; |
132 | int page_array_size; | 134 | int page_array_size; |
135 | struct list_head pending_list; | ||
133 | #endif | 136 | #endif |
134 | char fw_id[]; | 137 | char fw_id[]; |
135 | }; | 138 | }; |
@@ -171,6 +174,9 @@ static struct firmware_buf *__allocate_fw_buf(const char *fw_name, | |||
171 | strcpy(buf->fw_id, fw_name); | 174 | strcpy(buf->fw_id, fw_name); |
172 | buf->fwc = fwc; | 175 | buf->fwc = fwc; |
173 | init_completion(&buf->completion); | 176 | init_completion(&buf->completion); |
177 | #ifdef CONFIG_FW_LOADER_USER_HELPER | ||
178 | INIT_LIST_HEAD(&buf->pending_list); | ||
179 | #endif | ||
174 | 180 | ||
175 | pr_debug("%s: fw-%s buf=%p\n", __func__, fw_name, buf); | 181 | pr_debug("%s: fw-%s buf=%p\n", __func__, fw_name, buf); |
176 | 182 | ||
@@ -212,18 +218,6 @@ static int fw_lookup_and_allocate_buf(const char *fw_name, | |||
212 | return tmp ? 0 : -ENOMEM; | 218 | return tmp ? 0 : -ENOMEM; |
213 | } | 219 | } |
214 | 220 | ||
215 | static struct firmware_buf *fw_lookup_buf(const char *fw_name) | ||
216 | { | ||
217 | struct firmware_buf *tmp; | ||
218 | struct firmware_cache *fwc = &fw_cache; | ||
219 | |||
220 | spin_lock(&fwc->lock); | ||
221 | tmp = __fw_lookup_buf(fw_name); | ||
222 | spin_unlock(&fwc->lock); | ||
223 | |||
224 | return tmp; | ||
225 | } | ||
226 | |||
227 | static void __fw_free_buf(struct kref *ref) | 221 | static void __fw_free_buf(struct kref *ref) |
228 | { | 222 | { |
229 | struct firmware_buf *buf = to_fwbuf(ref); | 223 | struct firmware_buf *buf = to_fwbuf(ref); |
@@ -446,10 +440,8 @@ static struct firmware_priv *to_firmware_priv(struct device *dev) | |||
446 | return container_of(dev, struct firmware_priv, dev); | 440 | return container_of(dev, struct firmware_priv, dev); |
447 | } | 441 | } |
448 | 442 | ||
449 | static void fw_load_abort(struct firmware_priv *fw_priv) | 443 | static void __fw_load_abort(struct firmware_buf *buf) |
450 | { | 444 | { |
451 | struct firmware_buf *buf = fw_priv->buf; | ||
452 | |||
453 | /* | 445 | /* |
454 | * There is a small window in which user can write to 'loading' | 446 | * There is a small window in which user can write to 'loading' |
455 | * between loading done and disappearance of 'loading' | 447 | * between loading done and disappearance of 'loading' |
@@ -457,8 +449,16 @@ static void fw_load_abort(struct firmware_priv *fw_priv) | |||
457 | if (test_bit(FW_STATUS_DONE, &buf->status)) | 449 | if (test_bit(FW_STATUS_DONE, &buf->status)) |
458 | return; | 450 | return; |
459 | 451 | ||
452 | list_del_init(&buf->pending_list); | ||
460 | set_bit(FW_STATUS_ABORT, &buf->status); | 453 | set_bit(FW_STATUS_ABORT, &buf->status); |
461 | complete_all(&buf->completion); | 454 | complete_all(&buf->completion); |
455 | } | ||
456 | |||
457 | static void fw_load_abort(struct firmware_priv *fw_priv) | ||
458 | { | ||
459 | struct firmware_buf *buf = fw_priv->buf; | ||
460 | |||
461 | __fw_load_abort(buf); | ||
462 | 462 | ||
463 | /* avoid user action after loading abort */ | 463 | /* avoid user action after loading abort */ |
464 | fw_priv->buf = NULL; | 464 | fw_priv->buf = NULL; |
@@ -467,6 +467,25 @@ static void fw_load_abort(struct firmware_priv *fw_priv) | |||
467 | #define is_fw_load_aborted(buf) \ | 467 | #define is_fw_load_aborted(buf) \ |
468 | test_bit(FW_STATUS_ABORT, &(buf)->status) | 468 | test_bit(FW_STATUS_ABORT, &(buf)->status) |
469 | 469 | ||
470 | static LIST_HEAD(pending_fw_head); | ||
471 | |||
472 | /* reboot notifier for avoid deadlock with usermode_lock */ | ||
473 | static int fw_shutdown_notify(struct notifier_block *unused1, | ||
474 | unsigned long unused2, void *unused3) | ||
475 | { | ||
476 | mutex_lock(&fw_lock); | ||
477 | while (!list_empty(&pending_fw_head)) | ||
478 | __fw_load_abort(list_first_entry(&pending_fw_head, | ||
479 | struct firmware_buf, | ||
480 | pending_list)); | ||
481 | mutex_unlock(&fw_lock); | ||
482 | return NOTIFY_DONE; | ||
483 | } | ||
484 | |||
485 | static struct notifier_block fw_shutdown_nb = { | ||
486 | .notifier_call = fw_shutdown_notify, | ||
487 | }; | ||
488 | |||
470 | static ssize_t firmware_timeout_show(struct class *class, | 489 | static ssize_t firmware_timeout_show(struct class *class, |
471 | struct class_attribute *attr, | 490 | struct class_attribute *attr, |
472 | char *buf) | 491 | char *buf) |
@@ -509,8 +528,6 @@ static void fw_dev_release(struct device *dev) | |||
509 | struct firmware_priv *fw_priv = to_firmware_priv(dev); | 528 | struct firmware_priv *fw_priv = to_firmware_priv(dev); |
510 | 529 | ||
511 | kfree(fw_priv); | 530 | kfree(fw_priv); |
512 | |||
513 | module_put(THIS_MODULE); | ||
514 | } | 531 | } |
515 | 532 | ||
516 | static int firmware_uevent(struct device *dev, struct kobj_uevent_env *env) | 533 | static int firmware_uevent(struct device *dev, struct kobj_uevent_env *env) |
@@ -619,6 +636,7 @@ static ssize_t firmware_loading_store(struct device *dev, | |||
619 | * is completed. | 636 | * is completed. |
620 | * */ | 637 | * */ |
621 | fw_map_pages_buf(fw_buf); | 638 | fw_map_pages_buf(fw_buf); |
639 | list_del_init(&fw_buf->pending_list); | ||
622 | complete_all(&fw_buf->completion); | 640 | complete_all(&fw_buf->completion); |
623 | break; | 641 | break; |
624 | } | 642 | } |
@@ -838,9 +856,6 @@ static int _request_firmware_load(struct firmware_priv *fw_priv, bool uevent, | |||
838 | 856 | ||
839 | dev_set_uevent_suppress(f_dev, true); | 857 | dev_set_uevent_suppress(f_dev, true); |
840 | 858 | ||
841 | /* Need to pin this module until class device is destroyed */ | ||
842 | __module_get(THIS_MODULE); | ||
843 | |||
844 | retval = device_add(f_dev); | 859 | retval = device_add(f_dev); |
845 | if (retval) { | 860 | if (retval) { |
846 | dev_err(f_dev, "%s: device_register failed\n", __func__); | 861 | dev_err(f_dev, "%s: device_register failed\n", __func__); |
@@ -860,6 +875,7 @@ static int _request_firmware_load(struct firmware_priv *fw_priv, bool uevent, | |||
860 | } | 875 | } |
861 | 876 | ||
862 | if (uevent) { | 877 | if (uevent) { |
878 | buf->need_uevent = true; | ||
863 | dev_set_uevent_suppress(f_dev, false); | 879 | dev_set_uevent_suppress(f_dev, false); |
864 | dev_dbg(f_dev, "firmware: requesting %s\n", buf->fw_id); | 880 | dev_dbg(f_dev, "firmware: requesting %s\n", buf->fw_id); |
865 | if (timeout != MAX_SCHEDULE_TIMEOUT) | 881 | if (timeout != MAX_SCHEDULE_TIMEOUT) |
@@ -868,6 +884,10 @@ static int _request_firmware_load(struct firmware_priv *fw_priv, bool uevent, | |||
868 | kobject_uevent(&fw_priv->dev.kobj, KOBJ_ADD); | 884 | kobject_uevent(&fw_priv->dev.kobj, KOBJ_ADD); |
869 | } | 885 | } |
870 | 886 | ||
887 | mutex_lock(&fw_lock); | ||
888 | list_add(&buf->pending_list, &pending_fw_head); | ||
889 | mutex_unlock(&fw_lock); | ||
890 | |||
871 | wait_for_completion(&buf->completion); | 891 | wait_for_completion(&buf->completion); |
872 | 892 | ||
873 | cancel_delayed_work_sync(&fw_priv->timeout_work); | 893 | cancel_delayed_work_sync(&fw_priv->timeout_work); |
@@ -895,6 +915,23 @@ static int fw_load_from_user_helper(struct firmware *firmware, | |||
895 | fw_priv->buf = firmware->priv; | 915 | fw_priv->buf = firmware->priv; |
896 | return _request_firmware_load(fw_priv, uevent, timeout); | 916 | return _request_firmware_load(fw_priv, uevent, timeout); |
897 | } | 917 | } |
918 | |||
919 | #ifdef CONFIG_PM_SLEEP | ||
920 | /* kill pending requests without uevent to avoid blocking suspend */ | ||
921 | static void kill_requests_without_uevent(void) | ||
922 | { | ||
923 | struct firmware_buf *buf; | ||
924 | struct firmware_buf *next; | ||
925 | |||
926 | mutex_lock(&fw_lock); | ||
927 | list_for_each_entry_safe(buf, next, &pending_fw_head, pending_list) { | ||
928 | if (!buf->need_uevent) | ||
929 | __fw_load_abort(buf); | ||
930 | } | ||
931 | mutex_unlock(&fw_lock); | ||
932 | } | ||
933 | #endif | ||
934 | |||
898 | #else /* CONFIG_FW_LOADER_USER_HELPER */ | 935 | #else /* CONFIG_FW_LOADER_USER_HELPER */ |
899 | static inline int | 936 | static inline int |
900 | fw_load_from_user_helper(struct firmware *firmware, const char *name, | 937 | fw_load_from_user_helper(struct firmware *firmware, const char *name, |
@@ -907,6 +944,10 @@ fw_load_from_user_helper(struct firmware *firmware, const char *name, | |||
907 | /* No abort during direct loading */ | 944 | /* No abort during direct loading */ |
908 | #define is_fw_load_aborted(buf) false | 945 | #define is_fw_load_aborted(buf) false |
909 | 946 | ||
947 | #ifdef CONFIG_PM_SLEEP | ||
948 | static inline void kill_requests_without_uevent(void) { } | ||
949 | #endif | ||
950 | |||
910 | #endif /* CONFIG_FW_LOADER_USER_HELPER */ | 951 | #endif /* CONFIG_FW_LOADER_USER_HELPER */ |
911 | 952 | ||
912 | 953 | ||
@@ -974,7 +1015,8 @@ _request_firmware_prepare(struct firmware **firmware_p, const char *name, | |||
974 | return 1; /* need to load */ | 1015 | return 1; /* need to load */ |
975 | } | 1016 | } |
976 | 1017 | ||
977 | static int assign_firmware_buf(struct firmware *fw, struct device *device) | 1018 | static int assign_firmware_buf(struct firmware *fw, struct device *device, |
1019 | bool skip_cache) | ||
978 | { | 1020 | { |
979 | struct firmware_buf *buf = fw->priv; | 1021 | struct firmware_buf *buf = fw->priv; |
980 | 1022 | ||
@@ -991,7 +1033,7 @@ static int assign_firmware_buf(struct firmware *fw, struct device *device) | |||
991 | * device may has been deleted already, but the problem | 1033 | * device may has been deleted already, but the problem |
992 | * should be fixed in devres or driver core. | 1034 | * should be fixed in devres or driver core. |
993 | */ | 1035 | */ |
994 | if (device) | 1036 | if (device && !skip_cache) |
995 | fw_add_devm_name(device, buf->fw_id); | 1037 | fw_add_devm_name(device, buf->fw_id); |
996 | 1038 | ||
997 | /* | 1039 | /* |
@@ -1047,8 +1089,10 @@ _request_firmware(const struct firmware **firmware_p, const char *name, | |||
1047 | if (!fw_get_filesystem_firmware(device, fw->priv)) | 1089 | if (!fw_get_filesystem_firmware(device, fw->priv)) |
1048 | ret = fw_load_from_user_helper(fw, name, device, | 1090 | ret = fw_load_from_user_helper(fw, name, device, |
1049 | uevent, nowait, timeout); | 1091 | uevent, nowait, timeout); |
1092 | |||
1093 | /* don't cache firmware handled without uevent */ | ||
1050 | if (!ret) | 1094 | if (!ret) |
1051 | ret = assign_firmware_buf(fw, device); | 1095 | ret = assign_firmware_buf(fw, device, !uevent); |
1052 | 1096 | ||
1053 | usermodehelper_read_unlock(); | 1097 | usermodehelper_read_unlock(); |
1054 | 1098 | ||
@@ -1086,8 +1130,15 @@ int | |||
1086 | request_firmware(const struct firmware **firmware_p, const char *name, | 1130 | request_firmware(const struct firmware **firmware_p, const char *name, |
1087 | struct device *device) | 1131 | struct device *device) |
1088 | { | 1132 | { |
1089 | return _request_firmware(firmware_p, name, device, true, false); | 1133 | int ret; |
1134 | |||
1135 | /* Need to pin this module until return */ | ||
1136 | __module_get(THIS_MODULE); | ||
1137 | ret = _request_firmware(firmware_p, name, device, true, false); | ||
1138 | module_put(THIS_MODULE); | ||
1139 | return ret; | ||
1090 | } | 1140 | } |
1141 | EXPORT_SYMBOL(request_firmware); | ||
1091 | 1142 | ||
1092 | /** | 1143 | /** |
1093 | * release_firmware: - release the resource associated with a firmware image | 1144 | * release_firmware: - release the resource associated with a firmware image |
@@ -1101,6 +1152,7 @@ void release_firmware(const struct firmware *fw) | |||
1101 | kfree(fw); | 1152 | kfree(fw); |
1102 | } | 1153 | } |
1103 | } | 1154 | } |
1155 | EXPORT_SYMBOL(release_firmware); | ||
1104 | 1156 | ||
1105 | /* Async support */ | 1157 | /* Async support */ |
1106 | struct firmware_work { | 1158 | struct firmware_work { |
@@ -1181,6 +1233,10 @@ request_firmware_nowait( | |||
1181 | schedule_work(&fw_work->work); | 1233 | schedule_work(&fw_work->work); |
1182 | return 0; | 1234 | return 0; |
1183 | } | 1235 | } |
1236 | EXPORT_SYMBOL(request_firmware_nowait); | ||
1237 | |||
1238 | #ifdef CONFIG_PM_SLEEP | ||
1239 | static ASYNC_DOMAIN_EXCLUSIVE(fw_cache_domain); | ||
1184 | 1240 | ||
1185 | /** | 1241 | /** |
1186 | * cache_firmware - cache one firmware image in kernel memory space | 1242 | * cache_firmware - cache one firmware image in kernel memory space |
@@ -1196,7 +1252,7 @@ request_firmware_nowait( | |||
1196 | * Return !0 otherwise | 1252 | * Return !0 otherwise |
1197 | * | 1253 | * |
1198 | */ | 1254 | */ |
1199 | int cache_firmware(const char *fw_name) | 1255 | static int cache_firmware(const char *fw_name) |
1200 | { | 1256 | { |
1201 | int ret; | 1257 | int ret; |
1202 | const struct firmware *fw; | 1258 | const struct firmware *fw; |
@@ -1212,6 +1268,18 @@ int cache_firmware(const char *fw_name) | |||
1212 | return ret; | 1268 | return ret; |
1213 | } | 1269 | } |
1214 | 1270 | ||
1271 | static struct firmware_buf *fw_lookup_buf(const char *fw_name) | ||
1272 | { | ||
1273 | struct firmware_buf *tmp; | ||
1274 | struct firmware_cache *fwc = &fw_cache; | ||
1275 | |||
1276 | spin_lock(&fwc->lock); | ||
1277 | tmp = __fw_lookup_buf(fw_name); | ||
1278 | spin_unlock(&fwc->lock); | ||
1279 | |||
1280 | return tmp; | ||
1281 | } | ||
1282 | |||
1215 | /** | 1283 | /** |
1216 | * uncache_firmware - remove one cached firmware image | 1284 | * uncache_firmware - remove one cached firmware image |
1217 | * @fw_name: the firmware image name | 1285 | * @fw_name: the firmware image name |
@@ -1223,7 +1291,7 @@ int cache_firmware(const char *fw_name) | |||
1223 | * Return !0 otherwise | 1291 | * Return !0 otherwise |
1224 | * | 1292 | * |
1225 | */ | 1293 | */ |
1226 | int uncache_firmware(const char *fw_name) | 1294 | static int uncache_firmware(const char *fw_name) |
1227 | { | 1295 | { |
1228 | struct firmware_buf *buf; | 1296 | struct firmware_buf *buf; |
1229 | struct firmware fw; | 1297 | struct firmware fw; |
@@ -1242,9 +1310,6 @@ int uncache_firmware(const char *fw_name) | |||
1242 | return -EINVAL; | 1310 | return -EINVAL; |
1243 | } | 1311 | } |
1244 | 1312 | ||
1245 | #ifdef CONFIG_PM_SLEEP | ||
1246 | static ASYNC_DOMAIN_EXCLUSIVE(fw_cache_domain); | ||
1247 | |||
1248 | static struct fw_cache_entry *alloc_fw_cache_entry(const char *name) | 1313 | static struct fw_cache_entry *alloc_fw_cache_entry(const char *name) |
1249 | { | 1314 | { |
1250 | struct fw_cache_entry *fce; | 1315 | struct fw_cache_entry *fce; |
@@ -1464,6 +1529,7 @@ static int fw_pm_notify(struct notifier_block *notify_block, | |||
1464 | switch (mode) { | 1529 | switch (mode) { |
1465 | case PM_HIBERNATION_PREPARE: | 1530 | case PM_HIBERNATION_PREPARE: |
1466 | case PM_SUSPEND_PREPARE: | 1531 | case PM_SUSPEND_PREPARE: |
1532 | kill_requests_without_uevent(); | ||
1467 | device_cache_fw_images(); | 1533 | device_cache_fw_images(); |
1468 | break; | 1534 | break; |
1469 | 1535 | ||
@@ -1526,6 +1592,7 @@ static int __init firmware_class_init(void) | |||
1526 | { | 1592 | { |
1527 | fw_cache_init(); | 1593 | fw_cache_init(); |
1528 | #ifdef CONFIG_FW_LOADER_USER_HELPER | 1594 | #ifdef CONFIG_FW_LOADER_USER_HELPER |
1595 | register_reboot_notifier(&fw_shutdown_nb); | ||
1529 | return class_register(&firmware_class); | 1596 | return class_register(&firmware_class); |
1530 | #else | 1597 | #else |
1531 | return 0; | 1598 | return 0; |
@@ -1539,15 +1606,10 @@ static void __exit firmware_class_exit(void) | |||
1539 | unregister_pm_notifier(&fw_cache.pm_notify); | 1606 | unregister_pm_notifier(&fw_cache.pm_notify); |
1540 | #endif | 1607 | #endif |
1541 | #ifdef CONFIG_FW_LOADER_USER_HELPER | 1608 | #ifdef CONFIG_FW_LOADER_USER_HELPER |
1609 | unregister_reboot_notifier(&fw_shutdown_nb); | ||
1542 | class_unregister(&firmware_class); | 1610 | class_unregister(&firmware_class); |
1543 | #endif | 1611 | #endif |
1544 | } | 1612 | } |
1545 | 1613 | ||
1546 | fs_initcall(firmware_class_init); | 1614 | fs_initcall(firmware_class_init); |
1547 | module_exit(firmware_class_exit); | 1615 | module_exit(firmware_class_exit); |
1548 | |||
1549 | EXPORT_SYMBOL(release_firmware); | ||
1550 | EXPORT_SYMBOL(request_firmware); | ||
1551 | EXPORT_SYMBOL(request_firmware_nowait); | ||
1552 | EXPORT_SYMBOL_GPL(cache_firmware); | ||
1553 | EXPORT_SYMBOL_GPL(uncache_firmware); | ||