In preparation to support dynamic listing/updating of firmware
paths via procfs, this patch converts the firmware path configuration
from an array to a list.

Signed-off-by: Dimitris Papastamos <d...@opensource.wolfsonmicro.com>
---
 drivers/base/firmware_class.c | 72 ++++++++++++++++++++++++++++++++++++++-----
 1 file changed, 64 insertions(+), 8 deletions(-)

diff --git a/drivers/base/firmware_class.c b/drivers/base/firmware_class.c
index 8154145..2153eab 100644
--- a/drivers/base/firmware_class.c
+++ b/drivers/base/firmware_class.c
@@ -36,13 +36,13 @@ MODULE_AUTHOR("Manuel Estrada Sainz");
 MODULE_DESCRIPTION("Multi purpose firmware loading support");
 MODULE_LICENSE("GPL");
 
-static const char *fw_path[] = {
-       "/lib/firmware/updates/" UTS_RELEASE,
-       "/lib/firmware/updates",
-       "/lib/firmware/" UTS_RELEASE,
-       "/lib/firmware"
+struct fw_path_rec {
+       const char *name;
+       struct list_head list;
 };
 
+static LIST_HEAD(fw_path_list);
+
 /* Don't inline this: 'struct kstat' is biggish */
 static noinline long fw_file_size(struct file *file)
 {
@@ -78,13 +78,14 @@ static bool fw_read_file_contents(struct file *file, struct 
firmware *fw)
 
 static bool fw_get_filesystem_firmware(struct firmware *fw, const char *name)
 {
-       int i;
        bool success = false;
        char *path = __getname();
+       struct fw_path_rec *fwp;
 
-       for (i = 0; i < ARRAY_SIZE(fw_path); i++) {
+       list_for_each_entry(fwp, &fw_path_list, list) {
                struct file *file;
-               snprintf(path, PATH_MAX, "%s/%s", fw_path[i], name);
+               snprintf(path, PATH_MAX, "%s/%s", fwp->name,
+                        name);
 
                file = filp_open(path, O_RDONLY, 0);
                if (IS_ERR(file))
@@ -1385,6 +1386,50 @@ static int fw_cache_piggyback_on_request(const char 
*name)
 }
 #endif
 
+static void fw_free_path_list(void)
+{
+       struct fw_path_rec *fwp;
+
+       while (!list_empty(&fw_path_list)) {
+               fwp = list_first_entry(&fw_path_list,
+                                      struct fw_path_rec,
+                                      list);
+               kfree(fwp->name);
+               list_del(&fwp->list);
+               kfree(fwp);
+       }
+}
+
+static int fw_populate_path_list(void)
+{
+       int i;
+       struct fw_path_rec *fwp;
+       static const char *fw_path[] = {
+               "/lib/firmware/updates/" UTS_RELEASE,
+               "/lib/firmware/updates",
+               "/lib/firmware/" UTS_RELEASE,
+               "/lib/firmware"
+       };
+
+       for (i = 0; i < ARRAY_SIZE(fw_path); i++) {
+               fwp = kmalloc(sizeof(*fwp), GFP_KERNEL);
+               if (!fwp)
+                       goto err_fwp_alloc;
+               fwp->name = kstrdup(fw_path[i], GFP_KERNEL);
+               if (!fwp->name)
+                       goto err_fwp_name_alloc;
+               list_add_tail(&fwp->list, &fw_path_list);
+       }
+
+       return 0;
+
+err_fwp_name_alloc:
+       kfree(fwp);
+err_fwp_alloc:
+       fw_free_path_list();
+       return -ENOMEM;
+}
+
 static void __init fw_cache_init(void)
 {
        spin_lock_init(&fw_cache.lock);
@@ -1409,7 +1454,17 @@ static void __init fw_cache_init(void)
 
 static int __init firmware_class_init(void)
 {
+       int ret;
+
        fw_cache_init();
+
+       ret = fw_populate_path_list();
+       if (ret < 0) {
+               pr_err("%s: Failed to populate firmware path list: %d\n",
+                      __func__, ret);
+               return ret;
+       }
+
        return class_register(&firmware_class);
 }
 
@@ -1419,6 +1474,7 @@ static void __exit firmware_class_exit(void)
        unregister_syscore_ops(&fw_syscore_ops);
        unregister_pm_notifier(&fw_cache.pm_notify);
 #endif
+       fw_free_path_list();
        class_unregister(&firmware_class);
 }
 
-- 
1.7.12.2

--
To unsubscribe from this list: send the line "unsubscribe linux-kernel" in
the body of a message to majord...@vger.kernel.org
More majordomo info at  http://vger.kernel.org/majordomo-info.html
Please read the FAQ at  http://www.tux.org/lkml/

Reply via email to