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>
diff --git a/drivers/base/firmware_class.c b/drivers/base/firmware_class.c
index 7376367..a950241 100644
--- a/drivers/base/firmware_class.c
+++ b/drivers/base/firmware_class.c
@@ -601,12 +601,9 @@
}
ret = _request_firmware(&fw, fw_work->name, fw_work->device,
fw_work->uevent);
- if (ret < 0)
- fw_work->cont(NULL, fw_work->context);
- else {
- fw_work->cont(fw, fw_work->context);
- release_firmware(fw);
- }
+
+ fw_work->cont(fw, fw_work->context);
+
module_put(fw_work->module);
kfree(fw_work);
return ret;
@@ -619,6 +616,7 @@
* is non-zero else the firmware copy must be done manually.
* @name: name of firmware file
* @device: device for which firmware is being loaded
+ * @gfp: allocation flags
* @context: will be passed over to @cont, and
* @fw may be %NULL if firmware request fails.
* @cont: function will be called asynchronously when the firmware
@@ -631,12 +629,12 @@
int
request_firmware_nowait(
struct module *module, int uevent,
- const char *name, struct device *device, void *context,
+ const char *name, struct device *device, gfp_t gfp, void *context,
void (*cont)(const struct firmware *fw, void *context))
{
struct task_struct *task;
struct firmware_work *fw_work = kmalloc(sizeof (struct firmware_work),
- GFP_ATOMIC);
+ gfp);
if (!fw_work)
return -ENOMEM;