Commit 9ebfbd45f9d4ee9cd72529cf99e5f300eb398e67

Authored by Johannes Berg
Committed by Greg Kroah-Hartman
1 parent 03d673e6af

firmware_class: make request_firmware_nowait more useful

Unfortunately, one cannot hold on to the struct firmware
that request_firmware_nowait() hands off, which is needed
in some cases. Allow this by requiring the callback to
free it (via release_firmware).

Additionally, give it a gfp_t parameter -- all the current
users call it from a GFP_KERNEL context so the GFP_ATOMIC
isn't necessary. This also marks an API break which is
useful in a sense, although that is obviously not the
primary purpose of this change.

Signed-off-by: Johannes Berg <johannes@sipsolutions.net>
Acked-by: Marcel Holtmann <marcel@holtmann.org>
Cc: Ming Lei <tom.leiming@gmail.com>
Cc: Catalin Marinas <catalin.marinas@arm.com>
Cc: David Woodhouse <David.Woodhouse@intel.com>
Cc: Pavel Roskin <proski@gnu.org>
Cc: Abhay Salunke <abhay_salunke@dell.com>
Signed-off-by: Greg Kroah-Hartman <gregkh@suse.de>

Showing 7 changed files with 33 additions and 20 deletions Side-by-side Diff

drivers/base/firmware_class.c
... ... @@ -601,12 +601,9 @@
601 601 }
602 602 ret = _request_firmware(&fw, fw_work->name, fw_work->device,
603 603 fw_work->uevent);
604   - if (ret < 0)
605   - fw_work->cont(NULL, fw_work->context);
606   - else {
607   - fw_work->cont(fw, fw_work->context);
608   - release_firmware(fw);
609   - }
  604 +
  605 + fw_work->cont(fw, fw_work->context);
  606 +
610 607 module_put(fw_work->module);
611 608 kfree(fw_work);
612 609 return ret;
... ... @@ -619,6 +616,7 @@
619 616 * is non-zero else the firmware copy must be done manually.
620 617 * @name: name of firmware file
621 618 * @device: device for which firmware is being loaded
  619 + * @gfp: allocation flags
622 620 * @context: will be passed over to @cont, and
623 621 * @fw may be %NULL if firmware request fails.
624 622 * @cont: function will be called asynchronously when the firmware
625 623  
... ... @@ -631,12 +629,12 @@
631 629 int
632 630 request_firmware_nowait(
633 631 struct module *module, int uevent,
634   - const char *name, struct device *device, void *context,
  632 + const char *name, struct device *device, gfp_t gfp, void *context,
635 633 void (*cont)(const struct firmware *fw, void *context))
636 634 {
637 635 struct task_struct *task;
638 636 struct firmware_work *fw_work = kmalloc(sizeof (struct firmware_work),
639   - GFP_ATOMIC);
  637 + gfp);
640 638  
641 639 if (!fw_work)
642 640 return -ENOMEM;
drivers/firmware/dell_rbu.c
... ... @@ -544,9 +544,12 @@
544 544 {
545 545 rbu_data.entry_created = 0;
546 546  
547   - if (!fw || !fw->size)
  547 + if (!fw)
548 548 return;
549 549  
  550 + if (!fw->size)
  551 + goto out;
  552 +
550 553 spin_lock(&rbu_data.lock);
551 554 if (!strcmp(image_type, "mono")) {
552 555 if (!img_update_realloc(fw->size))
... ... @@ -568,6 +571,8 @@
568 571 } else
569 572 pr_debug("invalid image type specified.\n");
570 573 spin_unlock(&rbu_data.lock);
  574 + out:
  575 + release_firmware(fw);
571 576 }
572 577  
573 578 static ssize_t read_rbu_image_type(struct kobject *kobj,
... ... @@ -615,7 +620,7 @@
615 620 spin_unlock(&rbu_data.lock);
616 621 req_firm_rc = request_firmware_nowait(THIS_MODULE,
617 622 FW_ACTION_NOHOTPLUG, "dell_rbu",
618   - &rbu_device->dev, &context,
  623 + &rbu_device->dev, GFP_KERNEL, &context,
619 624 callbackfn_rbu);
620 625 if (req_firm_rc) {
621 626 printk(KERN_ERR
drivers/serial/ucc_uart.c
... ... @@ -1179,16 +1179,18 @@
1179 1179  
1180 1180 if (firmware->header.length != fw->size) {
1181 1181 dev_err(dev, "invalid firmware\n");
1182   - return;
  1182 + goto out;
1183 1183 }
1184 1184  
1185 1185 ret = qe_upload_firmware(firmware);
1186 1186 if (ret) {
1187 1187 dev_err(dev, "could not load firmware\n");
1188   - return;
  1188 + goto out;
1189 1189 }
1190 1190  
1191 1191 firmware_loaded = 1;
  1192 + out:
  1193 + release_firmware(fw);
1192 1194 }
1193 1195  
1194 1196 static int ucc_uart_probe(struct of_device *ofdev,
... ... @@ -1247,7 +1249,7 @@
1247 1249 */
1248 1250 ret = request_firmware_nowait(THIS_MODULE,
1249 1251 FW_ACTION_HOTPLUG, filename, &ofdev->dev,
1250   - &ofdev->dev, uart_firmware_cont);
  1252 + GFP_KERNEL, &ofdev->dev, uart_firmware_cont);
1251 1253 if (ret) {
1252 1254 dev_err(&ofdev->dev,
1253 1255 "could not load firmware %s\n",
drivers/staging/comedi/drivers/usbdux.c
... ... @@ -2327,9 +2327,11 @@
2327 2327 if (ret) {
2328 2328 dev_err(&usbdev->dev,
2329 2329 "Could not upload firmware (err=%d)\n", ret);
2330   - return;
  2330 + goto out;
2331 2331 }
2332 2332 comedi_usb_auto_config(usbdev, BOARDNAME);
  2333 + out:
  2334 + release_firmware(fw);
2333 2335 }
2334 2336  
2335 2337 /* allocate memory for the urbs and initialise them */
... ... @@ -2580,6 +2582,7 @@
2580 2582 FW_ACTION_HOTPLUG,
2581 2583 "usbdux_firmware.bin",
2582 2584 &udev->dev,
  2585 + GFP_KERNEL,
2583 2586 usbduxsub + index,
2584 2587 usbdux_firmware_request_complete_handler);
2585 2588  
drivers/staging/comedi/drivers/usbduxfast.c
... ... @@ -1451,10 +1451,12 @@
1451 1451 if (ret) {
1452 1452 dev_err(&usbdev->dev,
1453 1453 "Could not upload firmware (err=%d)\n", ret);
1454   - return;
  1454 + goto out;
1455 1455 }
1456 1456  
1457 1457 comedi_usb_auto_config(usbdev, BOARDNAME);
  1458 + out:
  1459 + release_firmware(fw);
1458 1460 }
1459 1461  
1460 1462 /*
... ... @@ -1569,6 +1571,7 @@
1569 1571 FW_ACTION_HOTPLUG,
1570 1572 "usbduxfast_firmware.bin",
1571 1573 &udev->dev,
  1574 + GFP_KERNEL,
1572 1575 usbduxfastsub + index,
1573 1576 usbduxfast_firmware_request_complete_handler);
1574 1577  
drivers/usb/atm/ueagle-atm.c
... ... @@ -667,12 +667,12 @@
667 667 else
668 668 uea_info(usb, "firmware uploaded\n");
669 669  
670   - uea_leaves(usb);
671   - return;
  670 + goto err;
672 671  
673 672 err_fw_corrupted:
674 673 uea_err(usb, "firmware is corrupted\n");
675 674 err:
  675 + release_firmware(fw_entry);
676 676 uea_leaves(usb);
677 677 }
678 678  
... ... @@ -705,7 +705,8 @@
705 705 break;
706 706 }
707 707  
708   - ret = request_firmware_nowait(THIS_MODULE, 1, fw_name, &usb->dev, usb, uea_upload_pre_firmware);
  708 + ret = request_firmware_nowait(THIS_MODULE, 1, fw_name, &usb->dev,
  709 + GFP_KERNEL, usb, uea_upload_pre_firmware);
709 710 if (ret)
710 711 uea_err(usb, "firmware %s is not available\n", fw_name);
711 712 else
include/linux/firmware.h
... ... @@ -4,6 +4,7 @@
4 4 #include <linux/module.h>
5 5 #include <linux/types.h>
6 6 #include <linux/compiler.h>
  7 +#include <linux/gfp.h>
7 8  
8 9 #define FW_ACTION_NOHOTPLUG 0
9 10 #define FW_ACTION_HOTPLUG 1
... ... @@ -38,7 +39,7 @@
38 39 struct device *device);
39 40 int request_firmware_nowait(
40 41 struct module *module, int uevent,
41   - const char *name, struct device *device, void *context,
  42 + const char *name, struct device *device, gfp_t gfp, void *context,
42 43 void (*cont)(const struct firmware *fw, void *context));
43 44  
44 45 void release_firmware(const struct firmware *fw);
... ... @@ -51,7 +52,7 @@
51 52 }
52 53 static inline int request_firmware_nowait(
53 54 struct module *module, int uevent,
54   - const char *name, struct device *device, void *context,
  55 + const char *name, struct device *device, gfp_t gfp, void *context,
55 56 void (*cont)(const struct firmware *fw, void *context))
56 57 {
57 58 return -EINVAL;