PM / OPP: Support adjusting OPP voltages at runtime
[firefly-linux-kernel-4.4.55.git] / drivers / base / firmware_class.c
index 30d575a09ad17e62f345a3520f2b480519c800c2..8524450e75bd15d8f97327af84662b4af32fc3a7 100644 (file)
@@ -28,6 +28,7 @@
 #include <linux/suspend.h>
 #include <linux/syscore_ops.h>
 #include <linux/reboot.h>
+#include <linux/security.h>
 
 #include <generated/utsrelease.h>
 
@@ -93,9 +94,24 @@ static int loading_timeout = 60;     /* In seconds */
 
 static inline long firmware_loading_timeout(void)
 {
-       return loading_timeout > 0 ? loading_timeout * HZ : MAX_SCHEDULE_TIMEOUT;
+       return loading_timeout > 0 ? loading_timeout * HZ : MAX_JIFFY_OFFSET;
 }
 
+/* firmware behavior options */
+#define FW_OPT_UEVENT  (1U << 0)
+#define FW_OPT_NOWAIT  (1U << 1)
+#ifdef CONFIG_FW_LOADER_USER_HELPER
+#define FW_OPT_USERHELPER      (1U << 2)
+#else
+#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 */
        spinlock_t lock;
@@ -128,22 +144,23 @@ struct firmware_buf {
        size_t size;
 #ifdef CONFIG_FW_LOADER_USER_HELPER
        bool is_paged_buf;
+       bool need_uevent;
        struct page **pages;
        int nr_pages;
        int page_array_size;
        struct list_head pending_list;
 #endif
-       char fw_id[];
+       const char *fw_id;
 };
 
 struct fw_cache_entry {
        struct list_head list;
-       char name[];
+       const char *name;
 };
 
 struct fw_name_devm {
        unsigned long magic;
-       char name[];
+       const char *name;
 };
 
 #define to_fwbuf(d) container_of(d, struct firmware_buf, ref)
@@ -164,13 +181,17 @@ static struct firmware_buf *__allocate_fw_buf(const char *fw_name,
 {
        struct firmware_buf *buf;
 
-       buf = kzalloc(sizeof(*buf) + strlen(fw_name) + 1 , GFP_ATOMIC);
-
+       buf = kzalloc(sizeof(*buf), GFP_ATOMIC);
        if (!buf)
-               return buf;
+               return NULL;
+
+       buf->fw_id = kstrdup_const(fw_name, GFP_ATOMIC);
+       if (!buf->fw_id) {
+               kfree(buf);
+               return NULL;
+       }
 
        kref_init(&buf->ref);
-       strcpy(buf->fw_id, fw_name);
        buf->fwc = fwc;
        init_completion(&buf->completion);
 #ifdef CONFIG_FW_LOADER_USER_HELPER
@@ -217,19 +238,8 @@ static int fw_lookup_and_allocate_buf(const char *fw_name,
        return tmp ? 0 : -ENOMEM;
 }
 
-static struct firmware_buf *fw_lookup_buf(const char *fw_name)
-{
-       struct firmware_buf *tmp;
-       struct firmware_cache *fwc = &fw_cache;
-
-       spin_lock(&fwc->lock);
-       tmp = __fw_lookup_buf(fw_name);
-       spin_unlock(&fwc->lock);
-
-       return tmp;
-}
-
 static void __fw_free_buf(struct kref *ref)
+       __releases(&fwc->lock)
 {
        struct firmware_buf *buf = to_fwbuf(ref);
        struct firmware_cache *fwc = buf->fwc;
@@ -251,6 +261,7 @@ static void __fw_free_buf(struct kref *ref)
        } else
 #endif
                vfree(buf->data);
+       kfree_const(buf->fw_id);
        kfree(buf);
 }
 
@@ -280,45 +291,47 @@ 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 long fw_file_size(struct file *file)
+static int fw_read_file_contents(struct file *file, struct firmware_buf *fw_buf)
 {
-       struct kstat st;
-       if (vfs_getattr(&file->f_path, &st))
-               return -1;
-       if (!S_ISREG(st.mode))
-               return -1;
-       if (st.size != (long)st.size)
-               return -1;
-       return st.size;
-}
-
-static bool fw_read_file_contents(struct file *file, struct firmware_buf *fw_buf)
-{
-       long size;
+       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 false;
+               return -EINVAL;
        buf = vmalloc(size);
        if (!buf)
-               return false;
-       if (kernel_read(file, 0, buf, size) != size) {
-               vfree(buf);
-               return false;
+               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 true;
+       return 0;
+fail:
+       vfree(buf);
+       return rc;
 }
 
-static bool fw_get_filesystem_firmware(struct device *device,
+static int fw_get_filesystem_firmware(struct device *device,
                                       struct firmware_buf *buf)
 {
-       int i;
-       bool success = false;
-       char *path = __getname();
+       int i, len;
+       int rc = -ENOENT;
+       char *path;
+
+       path = __getname();
+       if (!path)
+               return -ENOMEM;
 
        for (i = 0; i < ARRAY_SIZE(fw_path); i++) {
                struct file *file;
@@ -327,19 +340,27 @@ static bool fw_get_filesystem_firmware(struct device *device,
                if (!fw_path[i][0])
                        continue;
 
-               snprintf(path, PATH_MAX, "%s/%s", fw_path[i], buf->fw_id);
+               len = snprintf(path, PATH_MAX, "%s/%s",
+                              fw_path[i], buf->fw_id);
+               if (len >= PATH_MAX) {
+                       rc = -ENAMETOOLONG;
+                       break;
+               }
 
                file = filp_open(path, O_RDONLY, 0);
                if (IS_ERR(file))
                        continue;
-               success = fw_read_file_contents(file, buf);
+               rc = fw_read_file_contents(file, buf);
                fput(file);
-               if (success)
+               if (rc)
+                       dev_warn(device, "firmware, attempted to load %s, but failed with error %d\n",
+                               path, rc);
+               else
                        break;
        }
        __putname(path);
 
-       if (success) {
+       if (!rc) {
                dev_dbg(device, "firmware: direct-loading firmware %s\n",
                        buf->fw_id);
                mutex_lock(&fw_lock);
@@ -348,7 +369,7 @@ static bool fw_get_filesystem_firmware(struct device *device,
                mutex_unlock(&fw_lock);
        }
 
-       return success;
+       return rc;
 }
 
 /* firmware holds the ownership of pages */
@@ -385,6 +406,7 @@ static void fw_name_devm_release(struct device *dev, void *res)
        if (fwn->magic == (unsigned long)&fw_cache)
                pr_debug("%s: fw_name-%s devm-%p released\n",
                                __func__, fwn->name, res);
+       kfree_const(fwn->name);
 }
 
 static int fw_devm_match(struct device *dev, void *res,
@@ -415,13 +437,17 @@ static int fw_add_devm_name(struct device *dev, const char *name)
        if (fwn)
                return 1;
 
-       fwn = devres_alloc(fw_name_devm_release, sizeof(struct fw_name_devm) +
-                          strlen(name) + 1, GFP_KERNEL);
+       fwn = devres_alloc(fw_name_devm_release, sizeof(struct fw_name_devm),
+                          GFP_KERNEL);
        if (!fwn)
                return -ENOMEM;
+       fwn->name = kstrdup_const(name, GFP_KERNEL);
+       if (!fwn->name) {
+               devres_free(fwn);
+               return -ENOMEM;
+       }
 
        fwn->magic = (unsigned long)&fw_cache;
-       strcpy(fwn->name, name);
        devres_add(dev, fwn);
 
        return 0;
@@ -439,7 +465,6 @@ static int fw_add_devm_name(struct device *dev, const char *name)
  */
 #ifdef CONFIG_FW_LOADER_USER_HELPER
 struct firmware_priv {
-       struct delayed_work timeout_work;
        bool nowait;
        struct device dev;
        struct firmware_buf *buf;
@@ -497,9 +522,8 @@ static struct notifier_block fw_shutdown_nb = {
        .notifier_call = fw_shutdown_notify,
 };
 
-static ssize_t firmware_timeout_show(struct class *class,
-                                    struct class_attribute *attr,
-                                    char *buf)
+static ssize_t timeout_show(struct class *class, struct class_attribute *attr,
+                           char *buf)
 {
        return sprintf(buf, "%d\n", loading_timeout);
 }
@@ -517,9 +541,8 @@ static ssize_t firmware_timeout_show(struct class *class,
  *
  *     Note: zero means 'wait forever'.
  **/
-static ssize_t firmware_timeout_store(struct class *class,
-                                     struct class_attribute *attr,
-                                     const char *buf, size_t count)
+static ssize_t timeout_store(struct class *class, struct class_attribute *attr,
+                            const char *buf, size_t count)
 {
        loading_timeout = simple_strtol(buf, NULL, 10);
        if (loading_timeout < 0)
@@ -529,8 +552,7 @@ static ssize_t firmware_timeout_store(struct class *class,
 }
 
 static struct class_attribute firmware_class_attrs[] = {
-       __ATTR(timeout, S_IWUSR | S_IRUGO,
-               firmware_timeout_show, firmware_timeout_store),
+       __ATTR_RW(timeout),
        __ATTR_NULL
 };
 
@@ -539,8 +561,6 @@ static void fw_dev_release(struct device *dev)
        struct firmware_priv *fw_priv = to_firmware_priv(dev);
 
        kfree(fw_priv);
-
-       module_put(THIS_MODULE);
 }
 
 static int do_firmware_uevent(struct firmware_priv *fw_priv, struct kobj_uevent_env *env)
@@ -599,8 +619,7 @@ static int fw_map_pages_buf(struct firmware_buf *buf)
        if (!buf->is_paged_buf)
                return 0;
 
-       if (buf->data)
-               vunmap(buf->data);
+       vunmap(buf->data);
        buf->data = vmap(buf->pages, buf->nr_pages, 0, PAGE_KERNEL_RO);
        if (!buf->data)
                return -ENOMEM;
@@ -626,6 +645,7 @@ static ssize_t firmware_loading_store(struct device *dev,
 {
        struct firmware_priv *fw_priv = to_firmware_priv(dev);
        struct firmware_buf *fw_buf;
+       ssize_t written = count;
        int loading = simple_strtol(buf, NULL, 10);
        int i;
 
@@ -649,6 +669,8 @@ static ssize_t firmware_loading_store(struct device *dev,
                break;
        case 0:
                if (test_bit(FW_STATUS_LOADING, &fw_buf->status)) {
+                       int rc;
+
                        set_bit(FW_STATUS_DONE, &fw_buf->status);
                        clear_bit(FW_STATUS_LOADING, &fw_buf->status);
 
@@ -658,8 +680,23 @@ static ssize_t firmware_loading_store(struct device *dev,
                         * see the mapped 'buf->data' once the loading
                         * is completed.
                         * */
-                       fw_map_pages_buf(fw_buf);
+                       rc = fw_map_pages_buf(fw_buf);
+                       if (rc)
+                               dev_err(dev, "%s: map pages failed\n",
+                                       __func__);
+                       else
+                               rc = security_kernel_fw_from_file(NULL,
+                                               fw_buf->data, fw_buf->size);
+
+                       /*
+                        * Same logic as fw_load_abort, only the DONE bit
+                        * is ignored and we set ABORT only on failure.
+                        */
                        list_del_init(&fw_buf->pending_list);
+                       if (rc) {
+                               set_bit(FW_STATUS_ABORT, &fw_buf->status);
+                               written = rc;
+                       }
                        complete_all(&fw_buf->completion);
                        break;
                }
@@ -673,7 +710,7 @@ static ssize_t firmware_loading_store(struct device *dev,
        }
 out:
        mutex_unlock(&fw_lock);
-       return count;
+       return written;
 }
 
 static DEVICE_ATTR(loading, 0644, firmware_loading_show, firmware_loading_store);
@@ -725,7 +762,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) {
@@ -827,48 +864,55 @@ static struct bin_attribute firmware_attr_data = {
        .write = firmware_data_write,
 };
 
-static void firmware_class_timeout_work(struct work_struct *work)
-{
-       struct firmware_priv *fw_priv = container_of(work,
-                       struct firmware_priv, timeout_work.work);
+static struct attribute *fw_dev_attrs[] = {
+       &dev_attr_loading.attr,
+       NULL
+};
 
-       mutex_lock(&fw_lock);
-       fw_load_abort(fw_priv);
-       mutex_unlock(&fw_lock);
-}
+static struct bin_attribute *fw_dev_bin_attrs[] = {
+       &firmware_attr_data,
+       NULL
+};
+
+static const struct attribute_group fw_dev_attr_group = {
+       .attrs = fw_dev_attrs,
+       .bin_attrs = fw_dev_bin_attrs,
+};
+
+static const struct attribute_group *fw_dev_attr_groups[] = {
+       &fw_dev_attr_group,
+       NULL
+};
 
 static struct firmware_priv *
 fw_create_instance(struct firmware *firmware, const char *fw_name,
-                  struct device *device, bool uevent, bool nowait)
+                  struct device *device, unsigned int opt_flags)
 {
        struct firmware_priv *fw_priv;
        struct device *f_dev;
 
        fw_priv = kzalloc(sizeof(*fw_priv), GFP_KERNEL);
        if (!fw_priv) {
-               dev_err(device, "%s: kmalloc failed\n", __func__);
                fw_priv = ERR_PTR(-ENOMEM);
                goto exit;
        }
 
-       fw_priv->nowait = nowait;
+       fw_priv->nowait = !!(opt_flags & FW_OPT_NOWAIT);
        fw_priv->fw = firmware;
-       INIT_DELAYED_WORK(&fw_priv->timeout_work,
-               firmware_class_timeout_work);
-
        f_dev = &fw_priv->dev;
 
        device_initialize(f_dev);
        dev_set_name(f_dev, "%s", fw_name);
        f_dev->parent = device;
        f_dev->class = &firmware_class;
+       f_dev->groups = fw_dev_attr_groups;
 exit:
        return fw_priv;
 }
 
 /* load a firmware via user helper */
-static int _request_firmware_load(struct firmware_priv *fw_priv, bool uevent,
-                                 long timeout)
+static int _request_firmware_load(struct firmware_priv *fw_priv,
+                                 unsigned int opt_flags, long timeout)
 {
        int retval = 0;
        struct device *f_dev = &fw_priv->dev;
@@ -879,51 +923,40 @@ static int _request_firmware_load(struct firmware_priv *fw_priv, bool uevent,
 
        dev_set_uevent_suppress(f_dev, true);
 
-       /* Need to pin this module until class device is destroyed */
-       __module_get(THIS_MODULE);
-
        retval = device_add(f_dev);
        if (retval) {
                dev_err(f_dev, "%s: device_register failed\n", __func__);
                goto err_put_dev;
        }
 
-       retval = device_create_bin_file(f_dev, &firmware_attr_data);
-       if (retval) {
-               dev_err(f_dev, "%s: sysfs_create_bin_file failed\n", __func__);
-               goto err_del_dev;
-       }
-
        mutex_lock(&fw_lock);
        list_add(&buf->pending_list, &pending_fw_head);
        mutex_unlock(&fw_lock);
 
-       retval = device_create_file(f_dev, &dev_attr_loading);
-       if (retval) {
-               mutex_lock(&fw_lock);
-               list_del_init(&buf->pending_list);
-               mutex_unlock(&fw_lock);
-               dev_err(f_dev, "%s: device_create_file failed\n", __func__);
-               goto err_del_bin_attr;
-       }
-
-       if (uevent) {
+       if (opt_flags & FW_OPT_UEVENT) {
+               buf->need_uevent = true;
                dev_set_uevent_suppress(f_dev, false);
                dev_dbg(f_dev, "firmware: requesting %s\n", buf->fw_id);
-               if (timeout != MAX_SCHEDULE_TIMEOUT)
-                       schedule_delayed_work(&fw_priv->timeout_work, timeout);
-
                kobject_uevent(&fw_priv->dev.kobj, KOBJ_ADD);
+       } else {
+               timeout = MAX_JIFFY_OFFSET;
        }
 
-       wait_for_completion(&buf->completion);
+       retval = wait_for_completion_interruptible_timeout(&buf->completion,
+                       timeout);
+       if (retval == -ERESTARTSYS || !retval) {
+               mutex_lock(&fw_lock);
+               fw_load_abort(fw_priv);
+               mutex_unlock(&fw_lock);
+       } else if (retval > 0) {
+               retval = 0;
+       }
 
-       cancel_delayed_work_sync(&fw_priv->timeout_work);
+       if (is_fw_load_aborted(buf))
+               retval = -EAGAIN;
+       else if (!buf->data)
+               retval = -ENOMEM;
 
-       device_remove_file(f_dev, &dev_attr_loading);
-err_del_bin_attr:
-       device_remove_bin_file(f_dev, &firmware_attr_data);
-err_del_dev:
        device_del(f_dev);
 err_put_dev:
        put_device(f_dev);
@@ -932,21 +965,38 @@ err_put_dev:
 
 static int fw_load_from_user_helper(struct firmware *firmware,
                                    const char *name, struct device *device,
-                                   bool uevent, bool nowait, long timeout)
+                                   unsigned int opt_flags, long timeout)
 {
        struct firmware_priv *fw_priv;
 
-       fw_priv = fw_create_instance(firmware, name, device, uevent, nowait);
+       fw_priv = fw_create_instance(firmware, name, device, opt_flags);
        if (IS_ERR(fw_priv))
                return PTR_ERR(fw_priv);
 
        fw_priv->buf = firmware->priv;
-       return _request_firmware_load(fw_priv, uevent, timeout);
+       return _request_firmware_load(fw_priv, opt_flags, timeout);
+}
+
+#ifdef CONFIG_PM_SLEEP
+/* kill pending requests without uevent to avoid blocking suspend */
+static void kill_requests_without_uevent(void)
+{
+       struct firmware_buf *buf;
+       struct firmware_buf *next;
+
+       mutex_lock(&fw_lock);
+       list_for_each_entry_safe(buf, next, &pending_fw_head, pending_list) {
+               if (!buf->need_uevent)
+                        __fw_load_abort(buf);
+       }
+       mutex_unlock(&fw_lock);
 }
+#endif
+
 #else /* CONFIG_FW_LOADER_USER_HELPER */
 static inline int
 fw_load_from_user_helper(struct firmware *firmware, const char *name,
-                        struct device *device, bool uevent, bool nowait,
+                        struct device *device, unsigned int opt_flags,
                         long timeout)
 {
        return -ENOENT;
@@ -955,6 +1005,10 @@ fw_load_from_user_helper(struct firmware *firmware, const char *name,
 /* No abort during direct loading */
 #define is_fw_load_aborted(buf) false
 
+#ifdef CONFIG_PM_SLEEP
+static inline void kill_requests_without_uevent(void) { }
+#endif
+
 #endif /* CONFIG_FW_LOADER_USER_HELPER */
 
 
@@ -970,7 +1024,7 @@ static int sync_cached_firmware_buf(struct firmware_buf *buf)
                        break;
                }
                mutex_unlock(&fw_lock);
-               wait_for_completion(&buf->completion);
+               ret = wait_for_completion_interruptible(&buf->completion);
                mutex_lock(&fw_lock);
        }
        mutex_unlock(&fw_lock);
@@ -1022,7 +1076,8 @@ _request_firmware_prepare(struct firmware **firmware_p, const char *name,
        return 1; /* need to load */
 }
 
-static int assign_firmware_buf(struct firmware *fw, struct device *device)
+static int assign_firmware_buf(struct firmware *fw, struct device *device,
+                              unsigned int opt_flags)
 {
        struct firmware_buf *buf = fw->priv;
 
@@ -1039,7 +1094,8 @@ static int assign_firmware_buf(struct firmware *fw, struct device *device)
         * device may has been deleted already, but the problem
         * should be fixed in devres or driver core.
         */
-       if (device)
+       /* don't cache firmware handled without uevent */
+       if (device && (opt_flags & FW_OPT_UEVENT))
                fw_add_devm_name(device, buf->fw_id);
 
        /*
@@ -1060,7 +1116,7 @@ static int assign_firmware_buf(struct firmware *fw, struct device *device)
 /* called from request_firmware() and request_firmware_work_func() */
 static int
 _request_firmware(const struct firmware **firmware_p, const char *name,
-                 struct device *device, bool uevent, bool nowait)
+                 struct device *device, unsigned int opt_flags)
 {
        struct firmware *fw;
        long timeout;
@@ -1078,7 +1134,7 @@ _request_firmware(const struct firmware **firmware_p, const char *name,
 
        ret = 0;
        timeout = firmware_loading_timeout();
-       if (nowait) {
+       if (opt_flags & FW_OPT_NOWAIT) {
                timeout = usermodehelper_read_lock_wait(timeout);
                if (!timeout) {
                        dev_dbg(device, "firmware: %s loading timed out\n",
@@ -1095,11 +1151,21 @@ _request_firmware(const struct firmware **firmware_p, const char *name,
                }
        }
 
-       if (!fw_get_filesystem_firmware(device, fw->priv))
-               ret = fw_load_from_user_helper(fw, name, device,
-                                              uevent, nowait, timeout);
+       ret = fw_get_filesystem_firmware(device, fw->priv);
+       if (ret) {
+               if (!(opt_flags & FW_OPT_NO_WARN))
+                       dev_warn(device,
+                                "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);
+               }
+       }
+
        if (!ret)
-               ret = assign_firmware_buf(fw, device);
+               ret = assign_firmware_buf(fw, device, opt_flags);
 
        usermodehelper_read_unlock();
 
@@ -1135,10 +1201,42 @@ _request_firmware(const struct firmware **firmware_p, const char *name,
  **/
 int
 request_firmware(const struct firmware **firmware_p, const char *name,
-                 struct device *device)
+                struct device *device)
 {
-       return _request_firmware(firmware_p, name, device, true, false);
+       int ret;
+
+       /* Need to pin this module until return */
+       __module_get(THIS_MODULE);
+       ret = _request_firmware(firmware_p, name, device,
+                               FW_OPT_UEVENT | FW_OPT_FALLBACK);
+       module_put(THIS_MODULE);
+       return ret;
 }
+EXPORT_SYMBOL(request_firmware);
+
+/**
+ * request_firmware_direct: - load firmware directly without usermode helper
+ * @firmware_p: pointer to firmware image
+ * @name: name of firmware file
+ * @device: device for which firmware is being loaded
+ *
+ * This function works pretty much like request_firmware(), but this doesn't
+ * fall back to usermode helper even if the firmware couldn't be loaded
+ * directly from fs.  Hence it's useful for loading optional firmwares, which
+ * aren't always present, without extra long timeouts of udev.
+ **/
+int request_firmware_direct(const struct firmware **firmware_p,
+                           const char *name, struct device *device)
+{
+       int ret;
+
+       __module_get(THIS_MODULE);
+       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);
 
 /**
  * release_firmware: - release the resource associated with a firmware image
@@ -1152,6 +1250,7 @@ void release_firmware(const struct firmware *fw)
                kfree(fw);
        }
 }
+EXPORT_SYMBOL(release_firmware);
 
 /* Async support */
 struct firmware_work {
@@ -1161,7 +1260,7 @@ struct firmware_work {
        struct device *device;
        void *context;
        void (*cont)(const struct firmware *fw, void *context);
-       bool uevent;
+       unsigned int opt_flags;
 };
 
 static void request_firmware_work_func(struct work_struct *work)
@@ -1172,11 +1271,12 @@ static void request_firmware_work_func(struct work_struct *work)
        fw_work = container_of(work, struct firmware_work, work);
 
        _request_firmware(&fw, fw_work->name, fw_work->device,
-                         fw_work->uevent, true);
+                         fw_work->opt_flags);
        fw_work->cont(fw, fw_work->context);
        put_device(fw_work->device); /* taken in request_firmware_nowait() */
 
        module_put(fw_work->module);
+       kfree_const(fw_work->name);
        kfree(fw_work);
 }
 
@@ -1211,18 +1311,24 @@ request_firmware_nowait(
 {
        struct firmware_work *fw_work;
 
-       fw_work = kzalloc(sizeof (struct firmware_work), gfp);
+       fw_work = kzalloc(sizeof(struct firmware_work), gfp);
        if (!fw_work)
                return -ENOMEM;
 
        fw_work->module = module;
-       fw_work->name = name;
+       fw_work->name = kstrdup_const(name, gfp);
+       if (!fw_work->name) {
+               kfree(fw_work);
+               return -ENOMEM;
+       }
        fw_work->device = device;
        fw_work->context = context;
        fw_work->cont = cont;
-       fw_work->uevent = uevent;
+       fw_work->opt_flags = FW_OPT_NOWAIT | FW_OPT_FALLBACK |
+               (uevent ? FW_OPT_UEVENT : FW_OPT_USERHELPER);
 
        if (!try_module_get(module)) {
+               kfree_const(fw_work->name);
                kfree(fw_work);
                return -EFAULT;
        }
@@ -1232,6 +1338,10 @@ request_firmware_nowait(
        schedule_work(&fw_work->work);
        return 0;
 }
+EXPORT_SYMBOL(request_firmware_nowait);
+
+#ifdef CONFIG_PM_SLEEP
+static ASYNC_DOMAIN_EXCLUSIVE(fw_cache_domain);
 
 /**
  * cache_firmware - cache one firmware image in kernel memory space
@@ -1247,7 +1357,7 @@ request_firmware_nowait(
  * Return !0 otherwise
  *
  */
-int cache_firmware(const char *fw_name)
+static int cache_firmware(const char *fw_name)
 {
        int ret;
        const struct firmware *fw;
@@ -1263,6 +1373,18 @@ int cache_firmware(const char *fw_name)
        return ret;
 }
 
+static struct firmware_buf *fw_lookup_buf(const char *fw_name)
+{
+       struct firmware_buf *tmp;
+       struct firmware_cache *fwc = &fw_cache;
+
+       spin_lock(&fwc->lock);
+       tmp = __fw_lookup_buf(fw_name);
+       spin_unlock(&fwc->lock);
+
+       return tmp;
+}
+
 /**
  * uncache_firmware - remove one cached firmware image
  * @fw_name: the firmware image name
@@ -1274,7 +1396,7 @@ int cache_firmware(const char *fw_name)
  * Return !0 otherwise
  *
  */
-int uncache_firmware(const char *fw_name)
+static int uncache_firmware(const char *fw_name)
 {
        struct firmware_buf *buf;
        struct firmware fw;
@@ -1293,18 +1415,20 @@ int uncache_firmware(const char *fw_name)
        return -EINVAL;
 }
 
-#ifdef CONFIG_PM_SLEEP
-static ASYNC_DOMAIN_EXCLUSIVE(fw_cache_domain);
-
 static struct fw_cache_entry *alloc_fw_cache_entry(const char *name)
 {
        struct fw_cache_entry *fce;
 
-       fce = kzalloc(sizeof(*fce) + strlen(name) + 1, GFP_ATOMIC);
+       fce = kzalloc(sizeof(*fce), GFP_ATOMIC);
        if (!fce)
                goto exit;
 
-       strcpy(fce->name, name);
+       fce->name = kstrdup_const(name, GFP_ATOMIC);
+       if (!fce->name) {
+               kfree(fce);
+               fce = NULL;
+               goto exit;
+       }
 exit:
        return fce;
 }
@@ -1344,6 +1468,7 @@ found:
 
 static void free_fw_cache_entry(struct fw_cache_entry *fce)
 {
+       kfree_const(fce->name);
        kfree(fce);
 }
 
@@ -1505,8 +1630,8 @@ static void device_uncache_fw_images_work(struct work_struct *work)
  */
 static void device_uncache_fw_images_delay(unsigned long delay)
 {
-       schedule_delayed_work(&fw_cache.work,
-                       msecs_to_jiffies(delay));
+       queue_delayed_work(system_power_efficient_wq, &fw_cache.work,
+                          msecs_to_jiffies(delay));
 }
 
 static int fw_pm_notify(struct notifier_block *notify_block,
@@ -1515,6 +1640,8 @@ static int fw_pm_notify(struct notifier_block *notify_block,
        switch (mode) {
        case PM_HIBERNATION_PREPARE:
        case PM_SUSPEND_PREPARE:
+       case PM_RESTORE_PREPARE:
+               kill_requests_without_uevent();
                device_cache_fw_images();
                break;
 
@@ -1598,9 +1725,3 @@ static void __exit firmware_class_exit(void)
 
 fs_initcall(firmware_class_init);
 module_exit(firmware_class_exit);
-
-EXPORT_SYMBOL(release_firmware);
-EXPORT_SYMBOL(request_firmware);
-EXPORT_SYMBOL(request_firmware_nowait);
-EXPORT_SYMBOL_GPL(cache_firmware);
-EXPORT_SYMBOL_GPL(uncache_firmware);