aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorTakashi Iwai <tiwai@suse.de>2013-01-31 05:13:55 -0500
committerGreg Kroah-Hartman <gregkh@linuxfoundation.org>2013-02-03 20:57:40 -0500
commit7b1269f778782d2f42994a74bf4014d0cbebbf9f (patch)
treec6b76a1310fb7c6910a8450c2c6f13f703a2da86
parent4e0c92d015235d1dc65f9668a10cef2cea468ba2 (diff)
firmware: Make user-mode helper optional
This patch adds a new kconfig, CONFIG_FW_LOADER_USER_HELPER, and guards the user-helper codes in firmware_class.c with ifdefs. Yeah, yeah, there are lots of ifdefs in this patch. The further clean-up with code shuffling follows in the next. Acked-by: Ming Lei <ming.lei@canonical.com> Signed-off-by: Takashi Iwai <tiwai@suse.de> Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
-rw-r--r--drivers/base/Kconfig11
-rw-r--r--drivers/base/firmware_class.c57
2 files changed, 55 insertions, 13 deletions
diff --git a/drivers/base/Kconfig b/drivers/base/Kconfig
index c8b453939da2..07abd9d76f7f 100644
--- a/drivers/base/Kconfig
+++ b/drivers/base/Kconfig
@@ -145,6 +145,17 @@ config EXTRA_FIRMWARE_DIR
145 this option you can point it elsewhere, such as /lib/firmware/ or 145 this option you can point it elsewhere, such as /lib/firmware/ or
146 some other directory containing the firmware files. 146 some other directory containing the firmware files.
147 147
148config FW_LOADER_USER_HELPER
149 bool "Fallback user-helper invocation for firmware loading"
150 depends on FW_LOADER
151 default y
152 help
153 This option enables / disables the invocation of user-helper
154 (e.g. udev) for loading firmware files as a fallback after the
155 direct file loading in kernel fails. The user-mode helper is
156 no longer required unless you have a special firmware file that
157 resides in a non-standard path.
158
148config DEBUG_DRIVER 159config DEBUG_DRIVER
149 bool "Driver Core verbose debug messages" 160 bool "Driver Core verbose debug messages"
150 depends on DEBUG_KERNEL 161 depends on DEBUG_KERNEL
diff --git a/drivers/base/firmware_class.c b/drivers/base/firmware_class.c
index 40ec60affd8f..84b1c8d0ea56 100644
--- a/drivers/base/firmware_class.c
+++ b/drivers/base/firmware_class.c
@@ -88,10 +88,12 @@ enum {
88 FW_STATUS_ABORT, 88 FW_STATUS_ABORT,
89}; 89};
90 90
91#ifdef CONFIG_FW_LOADER_USER_HELPER
91enum fw_buf_fmt { 92enum fw_buf_fmt {
92 VMALLOC_BUF, /* used in direct loading */ 93 VMALLOC_BUF, /* used in direct loading */
93 PAGE_BUF, /* used in loading via userspace */ 94 PAGE_BUF, /* used in loading via userspace */
94}; 95};
96#endif /* CONFIG_FW_LOADER_USER_HELPER */
95 97
96static int loading_timeout = 60; /* In seconds */ 98static int loading_timeout = 60; /* In seconds */
97 99
@@ -128,12 +130,14 @@ struct firmware_buf {
128 struct completion completion; 130 struct completion completion;
129 struct firmware_cache *fwc; 131 struct firmware_cache *fwc;
130 unsigned long status; 132 unsigned long status;
131 enum fw_buf_fmt fmt;
132 void *data; 133 void *data;
133 size_t size; 134 size_t size;
135#ifdef CONFIG_FW_LOADER_USER_HELPER
136 enum fw_buf_fmt fmt;
134 struct page **pages; 137 struct page **pages;
135 int nr_pages; 138 int nr_pages;
136 int page_array_size; 139 int page_array_size;
140#endif
137 char fw_id[]; 141 char fw_id[];
138}; 142};
139 143
@@ -142,6 +146,7 @@ struct fw_cache_entry {
142 char name[]; 146 char name[];
143}; 147};
144 148
149#ifdef CONFIG_FW_LOADER_USER_HELPER
145struct firmware_priv { 150struct firmware_priv {
146 struct delayed_work timeout_work; 151 struct delayed_work timeout_work;
147 bool nowait; 152 bool nowait;
@@ -149,6 +154,7 @@ struct firmware_priv {
149 struct firmware_buf *buf; 154 struct firmware_buf *buf;
150 struct firmware *fw; 155 struct firmware *fw;
151}; 156};
157#endif
152 158
153struct fw_name_devm { 159struct fw_name_devm {
154 unsigned long magic; 160 unsigned long magic;
@@ -182,7 +188,9 @@ static struct firmware_buf *__allocate_fw_buf(const char *fw_name,
182 strcpy(buf->fw_id, fw_name); 188 strcpy(buf->fw_id, fw_name);
183 buf->fwc = fwc; 189 buf->fwc = fwc;
184 init_completion(&buf->completion); 190 init_completion(&buf->completion);
191#ifdef CONFIG_FW_LOADER_USER_HELPER
185 buf->fmt = VMALLOC_BUF; 192 buf->fmt = VMALLOC_BUF;
193#endif
186 194
187 pr_debug("%s: fw-%s buf=%p\n", __func__, fw_name, buf); 195 pr_debug("%s: fw-%s buf=%p\n", __func__, fw_name, buf);
188 196
@@ -240,7 +248,6 @@ static void __fw_free_buf(struct kref *ref)
240{ 248{
241 struct firmware_buf *buf = to_fwbuf(ref); 249 struct firmware_buf *buf = to_fwbuf(ref);
242 struct firmware_cache *fwc = buf->fwc; 250 struct firmware_cache *fwc = buf->fwc;
243 int i;
244 251
245 pr_debug("%s: fw-%s buf=%p data=%p size=%u\n", 252 pr_debug("%s: fw-%s buf=%p data=%p size=%u\n",
246 __func__, buf->fw_id, buf, buf->data, 253 __func__, buf->fw_id, buf, buf->data,
@@ -250,12 +257,15 @@ static void __fw_free_buf(struct kref *ref)
250 spin_unlock(&fwc->lock); 257 spin_unlock(&fwc->lock);
251 258
252 259
260#ifdef CONFIG_FW_LOADER_USER_HELPER
253 if (buf->fmt == PAGE_BUF) { 261 if (buf->fmt == PAGE_BUF) {
262 int i;
254 vunmap(buf->data); 263 vunmap(buf->data);
255 for (i = 0; i < buf->nr_pages; i++) 264 for (i = 0; i < buf->nr_pages; i++)
256 __free_page(buf->pages[i]); 265 __free_page(buf->pages[i]);
257 kfree(buf->pages); 266 kfree(buf->pages);
258 } else 267 } else
268#endif
259 vfree(buf->data); 269 vfree(buf->data);
260 kfree(buf); 270 kfree(buf);
261} 271}
@@ -357,6 +367,19 @@ static bool fw_get_filesystem_firmware(struct device *device,
357 return success; 367 return success;
358} 368}
359 369
370/* firmware holds the ownership of pages */
371static void firmware_free_data(const struct firmware *fw)
372{
373 /* Loaded directly? */
374 if (!fw->priv) {
375 vfree(fw->data);
376 return;
377 }
378 fw_free_buf(fw->priv);
379}
380
381#ifdef CONFIG_FW_LOADER_USER_HELPER
382
360static struct firmware_priv *to_firmware_priv(struct device *dev) 383static struct firmware_priv *to_firmware_priv(struct device *dev)
361{ 384{
362 return container_of(dev, struct firmware_priv, dev); 385 return container_of(dev, struct firmware_priv, dev);
@@ -446,17 +469,6 @@ static ssize_t firmware_loading_show(struct device *dev,
446 return sprintf(buf, "%d\n", loading); 469 return sprintf(buf, "%d\n", loading);
447} 470}
448 471
449/* firmware holds the ownership of pages */
450static void firmware_free_data(const struct firmware *fw)
451{
452 /* Loaded directly? */
453 if (!fw->priv) {
454 vfree(fw->data);
455 return;
456 }
457 fw_free_buf(fw->priv);
458}
459
460/* Some architectures don't have PAGE_KERNEL_RO */ 472/* Some architectures don't have PAGE_KERNEL_RO */
461#ifndef PAGE_KERNEL_RO 473#ifndef PAGE_KERNEL_RO
462#define PAGE_KERNEL_RO PAGE_KERNEL 474#define PAGE_KERNEL_RO PAGE_KERNEL
@@ -737,12 +749,15 @@ fw_create_instance(struct firmware *firmware, const char *fw_name,
737exit: 749exit:
738 return fw_priv; 750 return fw_priv;
739} 751}
752#endif /* CONFIG_FW_LOADER_USER_HELPER */
740 753
741/* store the pages buffer info firmware from buf */ 754/* store the pages buffer info firmware from buf */
742static void fw_set_page_data(struct firmware_buf *buf, struct firmware *fw) 755static void fw_set_page_data(struct firmware_buf *buf, struct firmware *fw)
743{ 756{
744 fw->priv = buf; 757 fw->priv = buf;
758#ifdef CONFIG_FW_LOADER_USER_HELPER
745 fw->pages = buf->pages; 759 fw->pages = buf->pages;
760#endif
746 fw->size = buf->size; 761 fw->size = buf->size;
747 fw->data = buf->data; 762 fw->data = buf->data;
748 763
@@ -906,6 +921,7 @@ static int assign_firmware_buf(struct firmware *fw, struct device *device)
906 return 0; 921 return 0;
907} 922}
908 923
924#ifdef CONFIG_FW_LOADER_USER_HELPER
909/* load a firmware via user helper */ 925/* load a firmware via user helper */
910static int _request_firmware_load(struct firmware_priv *fw_priv, bool uevent, 926static int _request_firmware_load(struct firmware_priv *fw_priv, bool uevent,
911 long timeout) 927 long timeout)
@@ -978,6 +994,15 @@ static int fw_load_from_user_helper(struct firmware *firmware,
978 fw_priv->buf = firmware->priv; 994 fw_priv->buf = firmware->priv;
979 return _request_firmware_load(fw_priv, uevent, timeout); 995 return _request_firmware_load(fw_priv, uevent, timeout);
980} 996}
997#else /* CONFIG_FW_LOADER_USER_HELPER */
998static inline int
999fw_load_from_user_helper(struct firmware *firmware, const char *name,
1000 struct device *device, bool uevent, bool nowait,
1001 long timeout)
1002{
1003 return -ENOENT;
1004}
1005#endif /* CONFIG_FW_LOADER_USER_HELPER */
981 1006
982/* called from request_firmware() and request_firmware_work_func() */ 1007/* called from request_firmware() and request_firmware_work_func() */
983static int 1008static int
@@ -1495,7 +1520,11 @@ static void __init fw_cache_init(void)
1495static int __init firmware_class_init(void) 1520static int __init firmware_class_init(void)
1496{ 1521{
1497 fw_cache_init(); 1522 fw_cache_init();
1523#ifdef CONFIG_FW_LOADER_USER_HELPER
1498 return class_register(&firmware_class); 1524 return class_register(&firmware_class);
1525#else
1526 return 0;
1527#endif
1499} 1528}
1500 1529
1501static void __exit firmware_class_exit(void) 1530static void __exit firmware_class_exit(void)
@@ -1504,7 +1533,9 @@ static void __exit firmware_class_exit(void)
1504 unregister_syscore_ops(&fw_syscore_ops); 1533 unregister_syscore_ops(&fw_syscore_ops);
1505 unregister_pm_notifier(&fw_cache.pm_notify); 1534 unregister_pm_notifier(&fw_cache.pm_notify);
1506#endif 1535#endif
1536#ifdef CONFIG_FW_LOADER_USER_HELPER
1507 class_unregister(&firmware_class); 1537 class_unregister(&firmware_class);
1538#endif
1508} 1539}
1509 1540
1510fs_initcall(firmware_class_init); 1541fs_initcall(firmware_class_init);