[PATCH 1/2] firmware: Convert firmware path setup from an array to a list

From: Dimitris Papastamos
Date: Wed Oct 10 2012 - 06:58:52 EST


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 <dp@xxxxxxxxxxxxxxxxxxxxxxxxxxx>
---
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 majordomo@xxxxxxxxxxxxxxx
More majordomo info at http://vger.kernel.org/majordomo-info.html
Please read the FAQ at http://www.tux.org/lkml/