Merge tag 'char-misc-4.6-rc1' of git://git.kernel.org/pub/scm/linux/kernel/git/gregkh...
[linux-2.6-block.git] / drivers / base / firmware_class.c
index a7f4aa3f6b32ad4e548c6f75d8a272e3f1c9c5f0..773fc30997697711c2ff926ab49ed88d272cdbcc 100644 (file)
@@ -23,6 +23,7 @@
 #include <linux/sched.h>
 #include <linux/file.h>
 #include <linux/list.h>
+#include <linux/fs.h>
 #include <linux/async.h>
 #include <linux/pm.h>
 #include <linux/suspend.h>
@@ -291,40 +292,19 @@ 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");
 
-static int fw_read_file_contents(struct file *file, struct firmware_buf *fw_buf)
+static void fw_finish_direct_load(struct device *device,
+                                 struct firmware_buf *buf)
 {
-       int size;
-       char *buf;
-       int rc;
-
-       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);
-       if (!buf)
-               return -ENOMEM;
-       rc = kernel_read(file, 0, buf, size);
-       if (rc != size) {
-               if (rc > 0)
-                       rc = -EIO;
-               goto fail;
-       }
-       rc = security_kernel_fw_from_file(file, buf, size);
-       if (rc)
-               goto fail;
-       fw_buf->data = buf;
-       fw_buf->size = size;
-       return 0;
-fail:
-       vfree(buf);
-       return rc;
+       mutex_lock(&fw_lock);
+       set_bit(FW_STATUS_DONE, &buf->status);
+       complete_all(&buf->completion);
+       mutex_unlock(&fw_lock);
 }
 
 static int fw_get_filesystem_firmware(struct device *device,
                                       struct firmware_buf *buf)
 {
+       loff_t size;
        int i, len;
        int rc = -ENOENT;
        char *path;
@@ -334,8 +314,6 @@ static int fw_get_filesystem_firmware(struct device *device,
                return -ENOMEM;
 
        for (i = 0; i < ARRAY_SIZE(fw_path); i++) {
-               struct file *file;
-
                /* skip the unset customized path */
                if (!fw_path[i][0])
                        continue;
@@ -347,28 +325,25 @@ static int fw_get_filesystem_firmware(struct device *device,
                        break;
                }
 
-               file = filp_open(path, O_RDONLY, 0);
-               if (IS_ERR(file))
+               buf->size = 0;
+               rc = kernel_read_file_from_path(path, &buf->data, &size,
+                                               INT_MAX, READING_FIRMWARE);
+               if (rc) {
+                       if (rc == -ENOENT)
+                               dev_dbg(device, "loading %s failed with error %d\n",
+                                        path, rc);
+                       else
+                               dev_warn(device, "loading %s failed with error %d\n",
+                                        path, rc);
                        continue;
-               rc = fw_read_file_contents(file, buf);
-               fput(file);
-               if (rc)
-                       dev_warn(device, "loading %s failed with error %d\n",
-                                path, rc);
-               else
-                       break;
+               }
+               dev_dbg(device, "direct-loading %s\n", buf->fw_id);
+               buf->size = size;
+               fw_finish_direct_load(device, buf);
+               break;
        }
        __putname(path);
 
-       if (!rc) {
-               dev_dbg(device, "direct-loading %s\n",
-                       buf->fw_id);
-               mutex_lock(&fw_lock);
-               set_bit(FW_STATUS_DONE, &buf->status);
-               complete_all(&buf->completion);
-               mutex_unlock(&fw_lock);
-       }
-
        return rc;
 }
 
@@ -685,8 +660,9 @@ static ssize_t firmware_loading_store(struct device *dev,
                                dev_err(dev, "%s: map pages failed\n",
                                        __func__);
                        else
-                               rc = security_kernel_fw_from_file(NULL,
-                                               fw_buf->data, fw_buf->size);
+                               rc = security_kernel_post_read_file(NULL,
+                                               fw_buf->data, fw_buf->size,
+                                               READING_FIRMWARE);
 
                        /*
                         * Same logic as fw_load_abort, only the DONE bit