diff options
Diffstat (limited to 'drivers/base/firmware_class.c')
-rw-r--r-- | drivers/base/firmware_class.c | 47 |
1 files changed, 22 insertions, 25 deletions
diff --git a/drivers/base/firmware_class.c b/drivers/base/firmware_class.c index d276e33880be..da77791793f1 100644 --- a/drivers/base/firmware_class.c +++ b/drivers/base/firmware_class.c | |||
@@ -100,10 +100,16 @@ static inline long firmware_loading_timeout(void) | |||
100 | #define FW_OPT_UEVENT (1U << 0) | 100 | #define FW_OPT_UEVENT (1U << 0) |
101 | #define FW_OPT_NOWAIT (1U << 1) | 101 | #define FW_OPT_NOWAIT (1U << 1) |
102 | #ifdef CONFIG_FW_LOADER_USER_HELPER | 102 | #ifdef CONFIG_FW_LOADER_USER_HELPER |
103 | #define FW_OPT_FALLBACK (1U << 2) | 103 | #define FW_OPT_USERHELPER (1U << 2) |
104 | #else | 104 | #else |
105 | #define FW_OPT_FALLBACK 0 | 105 | #define FW_OPT_USERHELPER 0 |
106 | #endif | 106 | #endif |
107 | #ifdef CONFIG_FW_LOADER_USER_HELPER_FALLBACK | ||
108 | #define FW_OPT_FALLBACK FW_OPT_USERHELPER | ||
109 | #else | ||
110 | #define FW_OPT_FALLBACK 0 | ||
111 | #endif | ||
112 | #define FW_OPT_NO_WARN (1U << 3) | ||
107 | 113 | ||
108 | struct firmware_cache { | 114 | struct firmware_cache { |
109 | /* firmware_buf instance will be added into the below list */ | 115 | /* firmware_buf instance will be added into the below list */ |
@@ -279,26 +285,15 @@ static const char * const fw_path[] = { | |||
279 | module_param_string(path, fw_path_para, sizeof(fw_path_para), 0644); | 285 | module_param_string(path, fw_path_para, sizeof(fw_path_para), 0644); |
280 | MODULE_PARM_DESC(path, "customized firmware image search path with a higher priority than default path"); | 286 | MODULE_PARM_DESC(path, "customized firmware image search path with a higher priority than default path"); |
281 | 287 | ||
282 | /* Don't inline this: 'struct kstat' is biggish */ | ||
283 | static noinline_for_stack int fw_file_size(struct file *file) | ||
284 | { | ||
285 | struct kstat st; | ||
286 | if (vfs_getattr(&file->f_path, &st)) | ||
287 | return -1; | ||
288 | if (!S_ISREG(st.mode)) | ||
289 | return -1; | ||
290 | if (st.size != (int)st.size) | ||
291 | return -1; | ||
292 | return st.size; | ||
293 | } | ||
294 | |||
295 | static int fw_read_file_contents(struct file *file, struct firmware_buf *fw_buf) | 288 | static int fw_read_file_contents(struct file *file, struct firmware_buf *fw_buf) |
296 | { | 289 | { |
297 | int size; | 290 | int size; |
298 | char *buf; | 291 | char *buf; |
299 | int rc; | 292 | int rc; |
300 | 293 | ||
301 | size = fw_file_size(file); | 294 | if (!S_ISREG(file_inode(file)->i_mode)) |
295 | return -EINVAL; | ||
296 | size = i_size_read(file_inode(file)); | ||
302 | if (size <= 0) | 297 | if (size <= 0) |
303 | return -EINVAL; | 298 | return -EINVAL; |
304 | buf = vmalloc(size); | 299 | buf = vmalloc(size); |
@@ -718,7 +713,7 @@ out: | |||
718 | static int fw_realloc_buffer(struct firmware_priv *fw_priv, int min_size) | 713 | static int fw_realloc_buffer(struct firmware_priv *fw_priv, int min_size) |
719 | { | 714 | { |
720 | struct firmware_buf *buf = fw_priv->buf; | 715 | struct firmware_buf *buf = fw_priv->buf; |
721 | int pages_needed = ALIGN(min_size, PAGE_SIZE) >> PAGE_SHIFT; | 716 | int pages_needed = PAGE_ALIGN(min_size) >> PAGE_SHIFT; |
722 | 717 | ||
723 | /* If the array of pages is too small, grow it... */ | 718 | /* If the array of pages is too small, grow it... */ |
724 | if (buf->page_array_size < pages_needed) { | 719 | if (buf->page_array_size < pages_needed) { |
@@ -911,7 +906,9 @@ static int _request_firmware_load(struct firmware_priv *fw_priv, | |||
911 | wait_for_completion(&buf->completion); | 906 | wait_for_completion(&buf->completion); |
912 | 907 | ||
913 | cancel_delayed_work_sync(&fw_priv->timeout_work); | 908 | cancel_delayed_work_sync(&fw_priv->timeout_work); |
914 | if (!buf->data) | 909 | if (is_fw_load_aborted(buf)) |
910 | retval = -EAGAIN; | ||
911 | else if (!buf->data) | ||
915 | retval = -ENOMEM; | 912 | retval = -ENOMEM; |
916 | 913 | ||
917 | device_remove_file(f_dev, &dev_attr_loading); | 914 | device_remove_file(f_dev, &dev_attr_loading); |
@@ -1111,10 +1108,11 @@ _request_firmware(const struct firmware **firmware_p, const char *name, | |||
1111 | 1108 | ||
1112 | ret = fw_get_filesystem_firmware(device, fw->priv); | 1109 | ret = fw_get_filesystem_firmware(device, fw->priv); |
1113 | if (ret) { | 1110 | if (ret) { |
1114 | if (opt_flags & FW_OPT_FALLBACK) { | 1111 | if (!(opt_flags & FW_OPT_NO_WARN)) |
1115 | dev_warn(device, | 1112 | dev_warn(device, |
1116 | "Direct firmware load failed with error %d\n", | 1113 | "Direct firmware load for %s failed with error %d\n", |
1117 | ret); | 1114 | name, ret); |
1115 | if (opt_flags & FW_OPT_USERHELPER) { | ||
1118 | dev_warn(device, "Falling back to user helper\n"); | 1116 | dev_warn(device, "Falling back to user helper\n"); |
1119 | ret = fw_load_from_user_helper(fw, name, device, | 1117 | ret = fw_load_from_user_helper(fw, name, device, |
1120 | opt_flags, timeout); | 1118 | opt_flags, timeout); |
@@ -1171,7 +1169,6 @@ request_firmware(const struct firmware **firmware_p, const char *name, | |||
1171 | } | 1169 | } |
1172 | EXPORT_SYMBOL(request_firmware); | 1170 | EXPORT_SYMBOL(request_firmware); |
1173 | 1171 | ||
1174 | #ifdef CONFIG_FW_LOADER_USER_HELPER | ||
1175 | /** | 1172 | /** |
1176 | * request_firmware: - load firmware directly without usermode helper | 1173 | * request_firmware: - load firmware directly without usermode helper |
1177 | * @firmware_p: pointer to firmware image | 1174 | * @firmware_p: pointer to firmware image |
@@ -1188,12 +1185,12 @@ int request_firmware_direct(const struct firmware **firmware_p, | |||
1188 | { | 1185 | { |
1189 | int ret; | 1186 | int ret; |
1190 | __module_get(THIS_MODULE); | 1187 | __module_get(THIS_MODULE); |
1191 | ret = _request_firmware(firmware_p, name, device, FW_OPT_UEVENT); | 1188 | ret = _request_firmware(firmware_p, name, device, |
1189 | FW_OPT_UEVENT | FW_OPT_NO_WARN); | ||
1192 | module_put(THIS_MODULE); | 1190 | module_put(THIS_MODULE); |
1193 | return ret; | 1191 | return ret; |
1194 | } | 1192 | } |
1195 | EXPORT_SYMBOL_GPL(request_firmware_direct); | 1193 | EXPORT_SYMBOL_GPL(request_firmware_direct); |
1196 | #endif | ||
1197 | 1194 | ||
1198 | /** | 1195 | /** |
1199 | * release_firmware: - release the resource associated with a firmware image | 1196 | * release_firmware: - release the resource associated with a firmware image |
@@ -1277,7 +1274,7 @@ request_firmware_nowait( | |||
1277 | fw_work->context = context; | 1274 | fw_work->context = context; |
1278 | fw_work->cont = cont; | 1275 | fw_work->cont = cont; |
1279 | fw_work->opt_flags = FW_OPT_NOWAIT | FW_OPT_FALLBACK | | 1276 | fw_work->opt_flags = FW_OPT_NOWAIT | FW_OPT_FALLBACK | |
1280 | (uevent ? FW_OPT_UEVENT : 0); | 1277 | (uevent ? FW_OPT_UEVENT : FW_OPT_USERHELPER); |
1281 | 1278 | ||
1282 | if (!try_module_get(module)) { | 1279 | if (!try_module_get(module)) { |
1283 | kfree(fw_work); | 1280 | kfree(fw_work); |