diff options
Diffstat (limited to 'drivers/base/firmware_class.c')
-rw-r--r-- | drivers/base/firmware_class.c | 33 |
1 files changed, 31 insertions, 2 deletions
diff --git a/drivers/base/firmware_class.c b/drivers/base/firmware_class.c index 264b3a2cd860..b0be1d18fee2 100644 --- a/drivers/base/firmware_class.c +++ b/drivers/base/firmware_class.c | |||
@@ -49,6 +49,14 @@ struct firmware_priv { | |||
49 | struct timer_list timeout; | 49 | struct timer_list timeout; |
50 | }; | 50 | }; |
51 | 51 | ||
52 | #ifdef CONFIG_FW_LOADER | ||
53 | extern struct builtin_fw __start_builtin_fw[]; | ||
54 | extern struct builtin_fw __end_builtin_fw[]; | ||
55 | #else /* Module case. Avoid ifdefs later; it'll all optimise out */ | ||
56 | static struct builtin_fw *__start_builtin_fw; | ||
57 | static struct builtin_fw *__end_builtin_fw; | ||
58 | #endif | ||
59 | |||
52 | static void | 60 | static void |
53 | fw_load_abort(struct firmware_priv *fw_priv) | 61 | fw_load_abort(struct firmware_priv *fw_priv) |
54 | { | 62 | { |
@@ -391,13 +399,12 @@ _request_firmware(const struct firmware **firmware_p, const char *name, | |||
391 | struct device *f_dev; | 399 | struct device *f_dev; |
392 | struct firmware_priv *fw_priv; | 400 | struct firmware_priv *fw_priv; |
393 | struct firmware *firmware; | 401 | struct firmware *firmware; |
402 | struct builtin_fw *builtin; | ||
394 | int retval; | 403 | int retval; |
395 | 404 | ||
396 | if (!firmware_p) | 405 | if (!firmware_p) |
397 | return -EINVAL; | 406 | return -EINVAL; |
398 | 407 | ||
399 | printk(KERN_INFO "firmware: requesting %s\n", name); | ||
400 | |||
401 | *firmware_p = firmware = kzalloc(sizeof(*firmware), GFP_KERNEL); | 408 | *firmware_p = firmware = kzalloc(sizeof(*firmware), GFP_KERNEL); |
402 | if (!firmware) { | 409 | if (!firmware) { |
403 | printk(KERN_ERR "%s: kmalloc(struct firmware) failed\n", | 410 | printk(KERN_ERR "%s: kmalloc(struct firmware) failed\n", |
@@ -406,6 +413,20 @@ _request_firmware(const struct firmware **firmware_p, const char *name, | |||
406 | goto out; | 413 | goto out; |
407 | } | 414 | } |
408 | 415 | ||
416 | for (builtin = __start_builtin_fw; builtin != __end_builtin_fw; | ||
417 | builtin++) { | ||
418 | if (strcmp(name, builtin->name)) | ||
419 | continue; | ||
420 | printk(KERN_INFO "firmware: using built-in firmware %s\n", | ||
421 | name); | ||
422 | firmware->size = builtin->size; | ||
423 | firmware->data = builtin->data; | ||
424 | return 0; | ||
425 | } | ||
426 | |||
427 | if (uevent) | ||
428 | printk(KERN_INFO "firmware: requesting %s\n", name); | ||
429 | |||
409 | retval = fw_setup_device(firmware, &f_dev, name, device, uevent); | 430 | retval = fw_setup_device(firmware, &f_dev, name, device, uevent); |
410 | if (retval) | 431 | if (retval) |
411 | goto error_kfree_fw; | 432 | goto error_kfree_fw; |
@@ -473,8 +494,16 @@ request_firmware(const struct firmware **firmware_p, const char *name, | |||
473 | void | 494 | void |
474 | release_firmware(const struct firmware *fw) | 495 | release_firmware(const struct firmware *fw) |
475 | { | 496 | { |
497 | struct builtin_fw *builtin; | ||
498 | |||
476 | if (fw) { | 499 | if (fw) { |
500 | for (builtin = __start_builtin_fw; builtin != __end_builtin_fw; | ||
501 | builtin++) { | ||
502 | if (fw->data == builtin->data) | ||
503 | goto free_fw; | ||
504 | } | ||
477 | vfree(fw->data); | 505 | vfree(fw->data); |
506 | free_fw: | ||
478 | kfree(fw); | 507 | kfree(fw); |
479 | } | 508 | } |
480 | } | 509 | } |