diff options
author | Johannes Berg <johannes@sipsolutions.net> | 2009-10-29 07:36:02 -0400 |
---|---|---|
committer | Greg Kroah-Hartman <gregkh@suse.de> | 2009-12-11 14:24:52 -0500 |
commit | 9ebfbd45f9d4ee9cd72529cf99e5f300eb398e67 (patch) | |
tree | 6ad661c4b38d0fad8a88c4a0d28997e9303632f2 /drivers | |
parent | 03d673e6af6490371aaf64dfe1f84c658c48b71d (diff) |
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>
Diffstat (limited to 'drivers')
-rw-r--r-- | drivers/base/firmware_class.c | 14 | ||||
-rw-r--r-- | drivers/firmware/dell_rbu.c | 9 | ||||
-rw-r--r-- | drivers/serial/ucc_uart.c | 8 | ||||
-rw-r--r-- | drivers/staging/comedi/drivers/usbdux.c | 5 | ||||
-rw-r--r-- | drivers/staging/comedi/drivers/usbduxfast.c | 5 | ||||
-rw-r--r-- | drivers/usb/atm/ueagle-atm.c | 7 |
6 files changed, 30 insertions, 18 deletions
diff --git a/drivers/base/firmware_class.c b/drivers/base/firmware_class.c index 7376367bcb80..a95024166b66 100644 --- a/drivers/base/firmware_class.c +++ b/drivers/base/firmware_class.c | |||
@@ -601,12 +601,9 @@ request_firmware_work_func(void *arg) | |||
601 | } | 601 | } |
602 | ret = _request_firmware(&fw, fw_work->name, fw_work->device, | 602 | ret = _request_firmware(&fw, fw_work->name, fw_work->device, |
603 | fw_work->uevent); | 603 | fw_work->uevent); |
604 | if (ret < 0) | 604 | |
605 | fw_work->cont(NULL, fw_work->context); | 605 | fw_work->cont(fw, fw_work->context); |
606 | else { | 606 | |
607 | fw_work->cont(fw, fw_work->context); | ||
608 | release_firmware(fw); | ||
609 | } | ||
610 | module_put(fw_work->module); | 607 | module_put(fw_work->module); |
611 | kfree(fw_work); | 608 | kfree(fw_work); |
612 | return ret; | 609 | return ret; |
@@ -619,6 +616,7 @@ request_firmware_work_func(void *arg) | |||
619 | * is non-zero else the firmware copy must be done manually. | 616 | * is non-zero else the firmware copy must be done manually. |
620 | * @name: name of firmware file | 617 | * @name: name of firmware file |
621 | * @device: device for which firmware is being loaded | 618 | * @device: device for which firmware is being loaded |
619 | * @gfp: allocation flags | ||
622 | * @context: will be passed over to @cont, and | 620 | * @context: will be passed over to @cont, and |
623 | * @fw may be %NULL if firmware request fails. | 621 | * @fw may be %NULL if firmware request fails. |
624 | * @cont: function will be called asynchronously when the firmware | 622 | * @cont: function will be called asynchronously when the firmware |
@@ -631,12 +629,12 @@ request_firmware_work_func(void *arg) | |||
631 | int | 629 | int |
632 | request_firmware_nowait( | 630 | request_firmware_nowait( |
633 | struct module *module, int uevent, | 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 | void (*cont)(const struct firmware *fw, void *context)) | 633 | void (*cont)(const struct firmware *fw, void *context)) |
636 | { | 634 | { |
637 | struct task_struct *task; | 635 | struct task_struct *task; |
638 | struct firmware_work *fw_work = kmalloc(sizeof (struct firmware_work), | 636 | struct firmware_work *fw_work = kmalloc(sizeof (struct firmware_work), |
639 | GFP_ATOMIC); | 637 | gfp); |
640 | 638 | ||
641 | if (!fw_work) | 639 | if (!fw_work) |
642 | return -ENOMEM; | 640 | return -ENOMEM; |
diff --git a/drivers/firmware/dell_rbu.c b/drivers/firmware/dell_rbu.c index b4704e150b28..b3a0cf57442e 100644 --- a/drivers/firmware/dell_rbu.c +++ b/drivers/firmware/dell_rbu.c | |||
@@ -544,9 +544,12 @@ static void callbackfn_rbu(const struct firmware *fw, void *context) | |||
544 | { | 544 | { |
545 | rbu_data.entry_created = 0; | 545 | rbu_data.entry_created = 0; |
546 | 546 | ||
547 | if (!fw || !fw->size) | 547 | if (!fw) |
548 | return; | 548 | return; |
549 | 549 | ||
550 | if (!fw->size) | ||
551 | goto out; | ||
552 | |||
550 | spin_lock(&rbu_data.lock); | 553 | spin_lock(&rbu_data.lock); |
551 | if (!strcmp(image_type, "mono")) { | 554 | if (!strcmp(image_type, "mono")) { |
552 | if (!img_update_realloc(fw->size)) | 555 | if (!img_update_realloc(fw->size)) |
@@ -568,6 +571,8 @@ static void callbackfn_rbu(const struct firmware *fw, void *context) | |||
568 | } else | 571 | } else |
569 | pr_debug("invalid image type specified.\n"); | 572 | pr_debug("invalid image type specified.\n"); |
570 | spin_unlock(&rbu_data.lock); | 573 | spin_unlock(&rbu_data.lock); |
574 | out: | ||
575 | release_firmware(fw); | ||
571 | } | 576 | } |
572 | 577 | ||
573 | static ssize_t read_rbu_image_type(struct kobject *kobj, | 578 | static ssize_t read_rbu_image_type(struct kobject *kobj, |
@@ -615,7 +620,7 @@ static ssize_t write_rbu_image_type(struct kobject *kobj, | |||
615 | spin_unlock(&rbu_data.lock); | 620 | spin_unlock(&rbu_data.lock); |
616 | req_firm_rc = request_firmware_nowait(THIS_MODULE, | 621 | req_firm_rc = request_firmware_nowait(THIS_MODULE, |
617 | FW_ACTION_NOHOTPLUG, "dell_rbu", | 622 | FW_ACTION_NOHOTPLUG, "dell_rbu", |
618 | &rbu_device->dev, &context, | 623 | &rbu_device->dev, GFP_KERNEL, &context, |
619 | callbackfn_rbu); | 624 | callbackfn_rbu); |
620 | if (req_firm_rc) { | 625 | if (req_firm_rc) { |
621 | printk(KERN_ERR | 626 | printk(KERN_ERR |
diff --git a/drivers/serial/ucc_uart.c b/drivers/serial/ucc_uart.c index 46de564aaea0..465f2fae1025 100644 --- a/drivers/serial/ucc_uart.c +++ b/drivers/serial/ucc_uart.c | |||
@@ -1179,16 +1179,18 @@ static void uart_firmware_cont(const struct firmware *fw, void *context) | |||
1179 | 1179 | ||
1180 | if (firmware->header.length != fw->size) { | 1180 | if (firmware->header.length != fw->size) { |
1181 | dev_err(dev, "invalid firmware\n"); | 1181 | dev_err(dev, "invalid firmware\n"); |
1182 | return; | 1182 | goto out; |
1183 | } | 1183 | } |
1184 | 1184 | ||
1185 | ret = qe_upload_firmware(firmware); | 1185 | ret = qe_upload_firmware(firmware); |
1186 | if (ret) { | 1186 | if (ret) { |
1187 | dev_err(dev, "could not load firmware\n"); | 1187 | dev_err(dev, "could not load firmware\n"); |
1188 | return; | 1188 | goto out; |
1189 | } | 1189 | } |
1190 | 1190 | ||
1191 | firmware_loaded = 1; | 1191 | firmware_loaded = 1; |
1192 | out: | ||
1193 | release_firmware(fw); | ||
1192 | } | 1194 | } |
1193 | 1195 | ||
1194 | static int ucc_uart_probe(struct of_device *ofdev, | 1196 | static int ucc_uart_probe(struct of_device *ofdev, |
@@ -1247,7 +1249,7 @@ static int ucc_uart_probe(struct of_device *ofdev, | |||
1247 | */ | 1249 | */ |
1248 | ret = request_firmware_nowait(THIS_MODULE, | 1250 | ret = request_firmware_nowait(THIS_MODULE, |
1249 | FW_ACTION_HOTPLUG, filename, &ofdev->dev, | 1251 | FW_ACTION_HOTPLUG, filename, &ofdev->dev, |
1250 | &ofdev->dev, uart_firmware_cont); | 1252 | GFP_KERNEL, &ofdev->dev, uart_firmware_cont); |
1251 | if (ret) { | 1253 | if (ret) { |
1252 | dev_err(&ofdev->dev, | 1254 | dev_err(&ofdev->dev, |
1253 | "could not load firmware %s\n", | 1255 | "could not load firmware %s\n", |
diff --git a/drivers/staging/comedi/drivers/usbdux.c b/drivers/staging/comedi/drivers/usbdux.c index cca4e869f0ec..dfcd12bec86b 100644 --- a/drivers/staging/comedi/drivers/usbdux.c +++ b/drivers/staging/comedi/drivers/usbdux.c | |||
@@ -2327,9 +2327,11 @@ static void usbdux_firmware_request_complete_handler(const struct firmware *fw, | |||
2327 | if (ret) { | 2327 | if (ret) { |
2328 | dev_err(&usbdev->dev, | 2328 | dev_err(&usbdev->dev, |
2329 | "Could not upload firmware (err=%d)\n", ret); | 2329 | "Could not upload firmware (err=%d)\n", ret); |
2330 | return; | 2330 | goto out; |
2331 | } | 2331 | } |
2332 | comedi_usb_auto_config(usbdev, BOARDNAME); | 2332 | comedi_usb_auto_config(usbdev, BOARDNAME); |
2333 | out: | ||
2334 | release_firmware(fw); | ||
2333 | } | 2335 | } |
2334 | 2336 | ||
2335 | /* allocate memory for the urbs and initialise them */ | 2337 | /* allocate memory for the urbs and initialise them */ |
@@ -2580,6 +2582,7 @@ static int usbduxsub_probe(struct usb_interface *uinterf, | |||
2580 | FW_ACTION_HOTPLUG, | 2582 | FW_ACTION_HOTPLUG, |
2581 | "usbdux_firmware.bin", | 2583 | "usbdux_firmware.bin", |
2582 | &udev->dev, | 2584 | &udev->dev, |
2585 | GFP_KERNEL, | ||
2583 | usbduxsub + index, | 2586 | usbduxsub + index, |
2584 | usbdux_firmware_request_complete_handler); | 2587 | usbdux_firmware_request_complete_handler); |
2585 | 2588 | ||
diff --git a/drivers/staging/comedi/drivers/usbduxfast.c b/drivers/staging/comedi/drivers/usbduxfast.c index d143222579c2..2e675cce7dbf 100644 --- a/drivers/staging/comedi/drivers/usbduxfast.c +++ b/drivers/staging/comedi/drivers/usbduxfast.c | |||
@@ -1451,10 +1451,12 @@ static void usbduxfast_firmware_request_complete_handler(const struct firmware | |||
1451 | if (ret) { | 1451 | if (ret) { |
1452 | dev_err(&usbdev->dev, | 1452 | dev_err(&usbdev->dev, |
1453 | "Could not upload firmware (err=%d)\n", ret); | 1453 | "Could not upload firmware (err=%d)\n", ret); |
1454 | return; | 1454 | goto out; |
1455 | } | 1455 | } |
1456 | 1456 | ||
1457 | comedi_usb_auto_config(usbdev, BOARDNAME); | 1457 | comedi_usb_auto_config(usbdev, BOARDNAME); |
1458 | out: | ||
1459 | release_firmware(fw); | ||
1458 | } | 1460 | } |
1459 | 1461 | ||
1460 | /* | 1462 | /* |
@@ -1569,6 +1571,7 @@ static int usbduxfastsub_probe(struct usb_interface *uinterf, | |||
1569 | FW_ACTION_HOTPLUG, | 1571 | FW_ACTION_HOTPLUG, |
1570 | "usbduxfast_firmware.bin", | 1572 | "usbduxfast_firmware.bin", |
1571 | &udev->dev, | 1573 | &udev->dev, |
1574 | GFP_KERNEL, | ||
1572 | usbduxfastsub + index, | 1575 | usbduxfastsub + index, |
1573 | usbduxfast_firmware_request_complete_handler); | 1576 | usbduxfast_firmware_request_complete_handler); |
1574 | 1577 | ||
diff --git a/drivers/usb/atm/ueagle-atm.c b/drivers/usb/atm/ueagle-atm.c index bba4d3eabe0f..c5395246886d 100644 --- a/drivers/usb/atm/ueagle-atm.c +++ b/drivers/usb/atm/ueagle-atm.c | |||
@@ -667,12 +667,12 @@ static void uea_upload_pre_firmware(const struct firmware *fw_entry, void *conte | |||
667 | else | 667 | else |
668 | uea_info(usb, "firmware uploaded\n"); | 668 | uea_info(usb, "firmware uploaded\n"); |
669 | 669 | ||
670 | uea_leaves(usb); | 670 | goto err; |
671 | return; | ||
672 | 671 | ||
673 | err_fw_corrupted: | 672 | err_fw_corrupted: |
674 | uea_err(usb, "firmware is corrupted\n"); | 673 | uea_err(usb, "firmware is corrupted\n"); |
675 | err: | 674 | err: |
675 | release_firmware(fw_entry); | ||
676 | uea_leaves(usb); | 676 | uea_leaves(usb); |
677 | } | 677 | } |
678 | 678 | ||
@@ -705,7 +705,8 @@ static int uea_load_firmware(struct usb_device *usb, unsigned int ver) | |||
705 | break; | 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 | if (ret) | 710 | if (ret) |
710 | uea_err(usb, "firmware %s is not available\n", fw_name); | 711 | uea_err(usb, "firmware %s is not available\n", fw_name); |
711 | else | 712 | else |