Merge branch 'next' of git://git.kernel.org/pub/scm/linux/kernel/git/jmorris/linux...
[cascardo/linux.git] / drivers / base / firmware_class.c
index 63f165c..bf42430 100644 (file)
@@ -101,10 +101,16 @@ static inline long firmware_loading_timeout(void)
 #define FW_OPT_UEVENT  (1U << 0)
 #define FW_OPT_NOWAIT  (1U << 1)
 #ifdef CONFIG_FW_LOADER_USER_HELPER
-#define FW_OPT_FALLBACK        (1U << 2)
+#define FW_OPT_USERHELPER      (1U << 2)
 #else
-#define FW_OPT_FALLBACK        0
+#define FW_OPT_USERHELPER      0
 #endif
+#ifdef CONFIG_FW_LOADER_USER_HELPER_FALLBACK
+#define FW_OPT_FALLBACK                FW_OPT_USERHELPER
+#else
+#define FW_OPT_FALLBACK                0
+#endif
+#define FW_OPT_NO_WARN (1U << 3)
 
 struct firmware_cache {
        /* firmware_buf instance will be added into the below list */
@@ -280,26 +286,15 @@ static const char * const fw_path[] = {
 module_param_string(path, fw_path_para, sizeof(fw_path_para), 0644);
 MODULE_PARM_DESC(path, "customized firmware image search path with a higher priority than default path");
 
-/* Don't inline this: 'struct kstat' is biggish */
-static noinline_for_stack int fw_file_size(struct file *file)
-{
-       struct kstat st;
-       if (vfs_getattr(&file->f_path, &st))
-               return -1;
-       if (!S_ISREG(st.mode))
-               return -1;
-       if (st.size != (int)st.size)
-               return -1;
-       return st.size;
-}
-
 static int fw_read_file_contents(struct file *file, struct firmware_buf *fw_buf)
 {
        int size;
        char *buf;
        int rc;
 
-       size = fw_file_size(file);
+       if (!S_ISREG(file_inode(file)->i_mode))
+               return -EINVAL;
+       size = i_size_read(file_inode(file));
        if (size <= 0)
                return -EINVAL;
        buf = vmalloc(size);
@@ -740,7 +735,7 @@ out:
 static int fw_realloc_buffer(struct firmware_priv *fw_priv, int min_size)
 {
        struct firmware_buf *buf = fw_priv->buf;
-       int pages_needed = ALIGN(min_size, PAGE_SIZE) >> PAGE_SHIFT;
+       int pages_needed = PAGE_ALIGN(min_size) >> PAGE_SHIFT;
 
        /* If the array of pages is too small, grow it... */
        if (buf->page_array_size < pages_needed) {
@@ -933,7 +928,9 @@ static int _request_firmware_load(struct firmware_priv *fw_priv,
        wait_for_completion(&buf->completion);
 
        cancel_delayed_work_sync(&fw_priv->timeout_work);
-       if (!buf->data)
+       if (is_fw_load_aborted(buf))
+               retval = -EAGAIN;
+       else if (!buf->data)
                retval = -ENOMEM;
 
        device_remove_file(f_dev, &dev_attr_loading);
@@ -1133,10 +1130,11 @@ _request_firmware(const struct firmware **firmware_p, const char *name,
 
        ret = fw_get_filesystem_firmware(device, fw->priv);
        if (ret) {
-               if (opt_flags & FW_OPT_FALLBACK) {
+               if (!(opt_flags & FW_OPT_NO_WARN))
                        dev_warn(device,
-                                "Direct firmware load failed with error %d\n",
-                                ret);
+                                "Direct firmware load for %s failed with error %d\n",
+                                name, ret);
+               if (opt_flags & FW_OPT_USERHELPER) {
                        dev_warn(device, "Falling back to user helper\n");
                        ret = fw_load_from_user_helper(fw, name, device,
                                                       opt_flags, timeout);
@@ -1193,7 +1191,6 @@ request_firmware(const struct firmware **firmware_p, const char *name,
 }
 EXPORT_SYMBOL(request_firmware);
 
-#ifdef CONFIG_FW_LOADER_USER_HELPER
 /**
  * request_firmware: - load firmware directly without usermode helper
  * @firmware_p: pointer to firmware image
@@ -1210,12 +1207,12 @@ int request_firmware_direct(const struct firmware **firmware_p,
 {
        int ret;
        __module_get(THIS_MODULE);
-       ret = _request_firmware(firmware_p, name, device, FW_OPT_UEVENT);
+       ret = _request_firmware(firmware_p, name, device,
+                               FW_OPT_UEVENT | FW_OPT_NO_WARN);
        module_put(THIS_MODULE);
        return ret;
 }
 EXPORT_SYMBOL_GPL(request_firmware_direct);
-#endif
 
 /**
  * release_firmware: - release the resource associated with a firmware image
@@ -1299,7 +1296,7 @@ request_firmware_nowait(
        fw_work->context = context;
        fw_work->cont = cont;
        fw_work->opt_flags = FW_OPT_NOWAIT | FW_OPT_FALLBACK |
-               (uevent ? FW_OPT_UEVENT : 0);
+               (uevent ? FW_OPT_UEVENT : FW_OPT_USERHELPER);
 
        if (!try_module_get(module)) {
                kfree(fw_work);