diff options
Diffstat (limited to 'drivers/base/firmware_class.c')
-rw-r--r-- | drivers/base/firmware_class.c | 93 |
1 files changed, 66 insertions, 27 deletions
diff --git a/drivers/base/firmware_class.c b/drivers/base/firmware_class.c index eb8fb94ae2c5..8a97ddfa6122 100644 --- a/drivers/base/firmware_class.c +++ b/drivers/base/firmware_class.c | |||
@@ -96,6 +96,15 @@ static inline long firmware_loading_timeout(void) | |||
96 | return loading_timeout > 0 ? loading_timeout * HZ : MAX_SCHEDULE_TIMEOUT; | 96 | return loading_timeout > 0 ? loading_timeout * HZ : MAX_SCHEDULE_TIMEOUT; |
97 | } | 97 | } |
98 | 98 | ||
99 | /* firmware behavior options */ | ||
100 | #define FW_OPT_UEVENT (1U << 0) | ||
101 | #define FW_OPT_NOWAIT (1U << 1) | ||
102 | #ifdef CONFIG_FW_LOADER_USER_HELPER | ||
103 | #define FW_OPT_FALLBACK (1U << 2) | ||
104 | #else | ||
105 | #define FW_OPT_FALLBACK 0 | ||
106 | #endif | ||
107 | |||
99 | struct firmware_cache { | 108 | struct firmware_cache { |
100 | /* firmware_buf instance will be added into the below list */ | 109 | /* firmware_buf instance will be added into the below list */ |
101 | spinlock_t lock; | 110 | spinlock_t lock; |
@@ -219,6 +228,7 @@ static int fw_lookup_and_allocate_buf(const char *fw_name, | |||
219 | } | 228 | } |
220 | 229 | ||
221 | static void __fw_free_buf(struct kref *ref) | 230 | static void __fw_free_buf(struct kref *ref) |
231 | __releases(&fwc->lock) | ||
222 | { | 232 | { |
223 | struct firmware_buf *buf = to_fwbuf(ref); | 233 | struct firmware_buf *buf = to_fwbuf(ref); |
224 | struct firmware_cache *fwc = buf->fwc; | 234 | struct firmware_cache *fwc = buf->fwc; |
@@ -270,21 +280,21 @@ module_param_string(path, fw_path_para, sizeof(fw_path_para), 0644); | |||
270 | MODULE_PARM_DESC(path, "customized firmware image search path with a higher priority than default path"); | 280 | MODULE_PARM_DESC(path, "customized firmware image search path with a higher priority than default path"); |
271 | 281 | ||
272 | /* Don't inline this: 'struct kstat' is biggish */ | 282 | /* Don't inline this: 'struct kstat' is biggish */ |
273 | static noinline_for_stack long fw_file_size(struct file *file) | 283 | static noinline_for_stack int fw_file_size(struct file *file) |
274 | { | 284 | { |
275 | struct kstat st; | 285 | struct kstat st; |
276 | if (vfs_getattr(&file->f_path, &st)) | 286 | if (vfs_getattr(&file->f_path, &st)) |
277 | return -1; | 287 | return -1; |
278 | if (!S_ISREG(st.mode)) | 288 | if (!S_ISREG(st.mode)) |
279 | return -1; | 289 | return -1; |
280 | if (st.size != (long)st.size) | 290 | if (st.size != (int)st.size) |
281 | return -1; | 291 | return -1; |
282 | return st.size; | 292 | return st.size; |
283 | } | 293 | } |
284 | 294 | ||
285 | static int fw_read_file_contents(struct file *file, struct firmware_buf *fw_buf) | 295 | static int fw_read_file_contents(struct file *file, struct firmware_buf *fw_buf) |
286 | { | 296 | { |
287 | long size; | 297 | int size; |
288 | char *buf; | 298 | char *buf; |
289 | int rc; | 299 | int rc; |
290 | 300 | ||
@@ -820,7 +830,7 @@ static void firmware_class_timeout_work(struct work_struct *work) | |||
820 | 830 | ||
821 | static struct firmware_priv * | 831 | static struct firmware_priv * |
822 | fw_create_instance(struct firmware *firmware, const char *fw_name, | 832 | fw_create_instance(struct firmware *firmware, const char *fw_name, |
823 | struct device *device, bool uevent, bool nowait) | 833 | struct device *device, unsigned int opt_flags) |
824 | { | 834 | { |
825 | struct firmware_priv *fw_priv; | 835 | struct firmware_priv *fw_priv; |
826 | struct device *f_dev; | 836 | struct device *f_dev; |
@@ -832,7 +842,7 @@ fw_create_instance(struct firmware *firmware, const char *fw_name, | |||
832 | goto exit; | 842 | goto exit; |
833 | } | 843 | } |
834 | 844 | ||
835 | fw_priv->nowait = nowait; | 845 | fw_priv->nowait = !!(opt_flags & FW_OPT_NOWAIT); |
836 | fw_priv->fw = firmware; | 846 | fw_priv->fw = firmware; |
837 | INIT_DELAYED_WORK(&fw_priv->timeout_work, | 847 | INIT_DELAYED_WORK(&fw_priv->timeout_work, |
838 | firmware_class_timeout_work); | 848 | firmware_class_timeout_work); |
@@ -848,8 +858,8 @@ exit: | |||
848 | } | 858 | } |
849 | 859 | ||
850 | /* load a firmware via user helper */ | 860 | /* load a firmware via user helper */ |
851 | static int _request_firmware_load(struct firmware_priv *fw_priv, bool uevent, | 861 | static int _request_firmware_load(struct firmware_priv *fw_priv, |
852 | long timeout) | 862 | unsigned int opt_flags, long timeout) |
853 | { | 863 | { |
854 | int retval = 0; | 864 | int retval = 0; |
855 | struct device *f_dev = &fw_priv->dev; | 865 | struct device *f_dev = &fw_priv->dev; |
@@ -885,7 +895,7 @@ static int _request_firmware_load(struct firmware_priv *fw_priv, bool uevent, | |||
885 | goto err_del_bin_attr; | 895 | goto err_del_bin_attr; |
886 | } | 896 | } |
887 | 897 | ||
888 | if (uevent) { | 898 | if (opt_flags & FW_OPT_UEVENT) { |
889 | buf->need_uevent = true; | 899 | buf->need_uevent = true; |
890 | dev_set_uevent_suppress(f_dev, false); | 900 | dev_set_uevent_suppress(f_dev, false); |
891 | dev_dbg(f_dev, "firmware: requesting %s\n", buf->fw_id); | 901 | dev_dbg(f_dev, "firmware: requesting %s\n", buf->fw_id); |
@@ -911,16 +921,16 @@ err_put_dev: | |||
911 | 921 | ||
912 | static int fw_load_from_user_helper(struct firmware *firmware, | 922 | static int fw_load_from_user_helper(struct firmware *firmware, |
913 | const char *name, struct device *device, | 923 | const char *name, struct device *device, |
914 | bool uevent, bool nowait, long timeout) | 924 | unsigned int opt_flags, long timeout) |
915 | { | 925 | { |
916 | struct firmware_priv *fw_priv; | 926 | struct firmware_priv *fw_priv; |
917 | 927 | ||
918 | fw_priv = fw_create_instance(firmware, name, device, uevent, nowait); | 928 | fw_priv = fw_create_instance(firmware, name, device, opt_flags); |
919 | if (IS_ERR(fw_priv)) | 929 | if (IS_ERR(fw_priv)) |
920 | return PTR_ERR(fw_priv); | 930 | return PTR_ERR(fw_priv); |
921 | 931 | ||
922 | fw_priv->buf = firmware->priv; | 932 | fw_priv->buf = firmware->priv; |
923 | return _request_firmware_load(fw_priv, uevent, timeout); | 933 | return _request_firmware_load(fw_priv, opt_flags, timeout); |
924 | } | 934 | } |
925 | 935 | ||
926 | #ifdef CONFIG_PM_SLEEP | 936 | #ifdef CONFIG_PM_SLEEP |
@@ -942,7 +952,7 @@ static void kill_requests_without_uevent(void) | |||
942 | #else /* CONFIG_FW_LOADER_USER_HELPER */ | 952 | #else /* CONFIG_FW_LOADER_USER_HELPER */ |
943 | static inline int | 953 | static inline int |
944 | fw_load_from_user_helper(struct firmware *firmware, const char *name, | 954 | fw_load_from_user_helper(struct firmware *firmware, const char *name, |
945 | struct device *device, bool uevent, bool nowait, | 955 | struct device *device, unsigned int opt_flags, |
946 | long timeout) | 956 | long timeout) |
947 | { | 957 | { |
948 | return -ENOENT; | 958 | return -ENOENT; |
@@ -1023,7 +1033,7 @@ _request_firmware_prepare(struct firmware **firmware_p, const char *name, | |||
1023 | } | 1033 | } |
1024 | 1034 | ||
1025 | static int assign_firmware_buf(struct firmware *fw, struct device *device, | 1035 | static int assign_firmware_buf(struct firmware *fw, struct device *device, |
1026 | bool skip_cache) | 1036 | unsigned int opt_flags) |
1027 | { | 1037 | { |
1028 | struct firmware_buf *buf = fw->priv; | 1038 | struct firmware_buf *buf = fw->priv; |
1029 | 1039 | ||
@@ -1040,7 +1050,8 @@ static int assign_firmware_buf(struct firmware *fw, struct device *device, | |||
1040 | * device may has been deleted already, but the problem | 1050 | * device may has been deleted already, but the problem |
1041 | * should be fixed in devres or driver core. | 1051 | * should be fixed in devres or driver core. |
1042 | */ | 1052 | */ |
1043 | if (device && !skip_cache) | 1053 | /* don't cache firmware handled without uevent */ |
1054 | if (device && (opt_flags & FW_OPT_UEVENT)) | ||
1044 | fw_add_devm_name(device, buf->fw_id); | 1055 | fw_add_devm_name(device, buf->fw_id); |
1045 | 1056 | ||
1046 | /* | 1057 | /* |
@@ -1061,7 +1072,7 @@ static int assign_firmware_buf(struct firmware *fw, struct device *device, | |||
1061 | /* called from request_firmware() and request_firmware_work_func() */ | 1072 | /* called from request_firmware() and request_firmware_work_func() */ |
1062 | static int | 1073 | static int |
1063 | _request_firmware(const struct firmware **firmware_p, const char *name, | 1074 | _request_firmware(const struct firmware **firmware_p, const char *name, |
1064 | struct device *device, bool uevent, bool nowait) | 1075 | struct device *device, unsigned int opt_flags) |
1065 | { | 1076 | { |
1066 | struct firmware *fw; | 1077 | struct firmware *fw; |
1067 | long timeout; | 1078 | long timeout; |
@@ -1076,7 +1087,7 @@ _request_firmware(const struct firmware **firmware_p, const char *name, | |||
1076 | 1087 | ||
1077 | ret = 0; | 1088 | ret = 0; |
1078 | timeout = firmware_loading_timeout(); | 1089 | timeout = firmware_loading_timeout(); |
1079 | if (nowait) { | 1090 | if (opt_flags & FW_OPT_NOWAIT) { |
1080 | timeout = usermodehelper_read_lock_wait(timeout); | 1091 | timeout = usermodehelper_read_lock_wait(timeout); |
1081 | if (!timeout) { | 1092 | if (!timeout) { |
1082 | dev_dbg(device, "firmware: %s loading timed out\n", | 1093 | dev_dbg(device, "firmware: %s loading timed out\n", |
@@ -1095,16 +1106,18 @@ _request_firmware(const struct firmware **firmware_p, const char *name, | |||
1095 | 1106 | ||
1096 | ret = fw_get_filesystem_firmware(device, fw->priv); | 1107 | ret = fw_get_filesystem_firmware(device, fw->priv); |
1097 | if (ret) { | 1108 | if (ret) { |
1098 | dev_warn(device, "Direct firmware load failed with error %d\n", | 1109 | if (opt_flags & FW_OPT_FALLBACK) { |
1099 | ret); | 1110 | dev_warn(device, |
1100 | dev_warn(device, "Falling back to user helper\n"); | 1111 | "Direct firmware load failed with error %d\n", |
1101 | ret = fw_load_from_user_helper(fw, name, device, | 1112 | ret); |
1102 | uevent, nowait, timeout); | 1113 | dev_warn(device, "Falling back to user helper\n"); |
1114 | ret = fw_load_from_user_helper(fw, name, device, | ||
1115 | opt_flags, timeout); | ||
1116 | } | ||
1103 | } | 1117 | } |
1104 | 1118 | ||
1105 | /* don't cache firmware handled without uevent */ | ||
1106 | if (!ret) | 1119 | if (!ret) |
1107 | ret = assign_firmware_buf(fw, device, !uevent); | 1120 | ret = assign_firmware_buf(fw, device, opt_flags); |
1108 | 1121 | ||
1109 | usermodehelper_read_unlock(); | 1122 | usermodehelper_read_unlock(); |
1110 | 1123 | ||
@@ -1146,12 +1159,37 @@ request_firmware(const struct firmware **firmware_p, const char *name, | |||
1146 | 1159 | ||
1147 | /* Need to pin this module until return */ | 1160 | /* Need to pin this module until return */ |
1148 | __module_get(THIS_MODULE); | 1161 | __module_get(THIS_MODULE); |
1149 | ret = _request_firmware(firmware_p, name, device, true, false); | 1162 | ret = _request_firmware(firmware_p, name, device, |
1163 | FW_OPT_UEVENT | FW_OPT_FALLBACK); | ||
1150 | module_put(THIS_MODULE); | 1164 | module_put(THIS_MODULE); |
1151 | return ret; | 1165 | return ret; |
1152 | } | 1166 | } |
1153 | EXPORT_SYMBOL(request_firmware); | 1167 | EXPORT_SYMBOL(request_firmware); |
1154 | 1168 | ||
1169 | #ifdef CONFIG_FW_LOADER_USER_HELPER | ||
1170 | /** | ||
1171 | * request_firmware: - load firmware directly without usermode helper | ||
1172 | * @firmware_p: pointer to firmware image | ||
1173 | * @name: name of firmware file | ||
1174 | * @device: device for which firmware is being loaded | ||
1175 | * | ||
1176 | * This function works pretty much like request_firmware(), but this doesn't | ||
1177 | * fall back to usermode helper even if the firmware couldn't be loaded | ||
1178 | * directly from fs. Hence it's useful for loading optional firmwares, which | ||
1179 | * aren't always present, without extra long timeouts of udev. | ||
1180 | **/ | ||
1181 | int request_firmware_direct(const struct firmware **firmware_p, | ||
1182 | const char *name, struct device *device) | ||
1183 | { | ||
1184 | int ret; | ||
1185 | __module_get(THIS_MODULE); | ||
1186 | ret = _request_firmware(firmware_p, name, device, FW_OPT_UEVENT); | ||
1187 | module_put(THIS_MODULE); | ||
1188 | return ret; | ||
1189 | } | ||
1190 | EXPORT_SYMBOL_GPL(request_firmware_direct); | ||
1191 | #endif | ||
1192 | |||
1155 | /** | 1193 | /** |
1156 | * release_firmware: - release the resource associated with a firmware image | 1194 | * release_firmware: - release the resource associated with a firmware image |
1157 | * @fw: firmware resource to release | 1195 | * @fw: firmware resource to release |
@@ -1174,7 +1212,7 @@ struct firmware_work { | |||
1174 | struct device *device; | 1212 | struct device *device; |
1175 | void *context; | 1213 | void *context; |
1176 | void (*cont)(const struct firmware *fw, void *context); | 1214 | void (*cont)(const struct firmware *fw, void *context); |
1177 | bool uevent; | 1215 | unsigned int opt_flags; |
1178 | }; | 1216 | }; |
1179 | 1217 | ||
1180 | static void request_firmware_work_func(struct work_struct *work) | 1218 | static void request_firmware_work_func(struct work_struct *work) |
@@ -1185,7 +1223,7 @@ static void request_firmware_work_func(struct work_struct *work) | |||
1185 | fw_work = container_of(work, struct firmware_work, work); | 1223 | fw_work = container_of(work, struct firmware_work, work); |
1186 | 1224 | ||
1187 | _request_firmware(&fw, fw_work->name, fw_work->device, | 1225 | _request_firmware(&fw, fw_work->name, fw_work->device, |
1188 | fw_work->uevent, true); | 1226 | fw_work->opt_flags); |
1189 | fw_work->cont(fw, fw_work->context); | 1227 | fw_work->cont(fw, fw_work->context); |
1190 | put_device(fw_work->device); /* taken in request_firmware_nowait() */ | 1228 | put_device(fw_work->device); /* taken in request_firmware_nowait() */ |
1191 | 1229 | ||
@@ -1233,7 +1271,8 @@ request_firmware_nowait( | |||
1233 | fw_work->device = device; | 1271 | fw_work->device = device; |
1234 | fw_work->context = context; | 1272 | fw_work->context = context; |
1235 | fw_work->cont = cont; | 1273 | fw_work->cont = cont; |
1236 | fw_work->uevent = uevent; | 1274 | fw_work->opt_flags = FW_OPT_NOWAIT | FW_OPT_FALLBACK | |
1275 | (uevent ? FW_OPT_UEVENT : 0); | ||
1237 | 1276 | ||
1238 | if (!try_module_get(module)) { | 1277 | if (!try_module_get(module)) { |
1239 | kfree(fw_work); | 1278 | kfree(fw_work); |