Donate to e Foundation | Murena handsets with /e/OS | Own a part of Murena! Learn more

Commit 6e3eaab0 authored by Abhay Salunke's avatar Abhay Salunke Committed by Linus Torvalds
Browse files

[PATCH] modified firmware_class.c to support no hotplug



Upgrade the request_firmware_nowait function to not start the hotplug
action on a firmware update.

This patch is tested along with dell_rbu driver on i386 and x86-64 systems.

Signed-off-by: default avatarAbhay Salunke <Abhay_Salunke@dell.com>
Cc: Greg KH <greg@kroah.com>
Signed-off-by: default avatarAndrew Morton <akpm@osdl.org>
Signed-off-by: default avatarLinus Torvalds <torvalds@osdl.org>
parent f3ef6f63
Loading
Loading
Loading
Loading
+50 −29
Original line number Diff line number Diff line
@@ -28,6 +28,7 @@ enum {
	FW_STATUS_DONE,
	FW_STATUS_ABORT,
	FW_STATUS_READY,
	FW_STATUS_READY_NOHOTPLUG,
};

static int loading_timeout = 10;	/* In seconds */
@@ -344,7 +345,7 @@ fw_register_class_device(struct class_device **class_dev_p,

static int
fw_setup_class_device(struct firmware *fw, struct class_device **class_dev_p,
		      const char *fw_name, struct device *device)
		      const char *fw_name, struct device *device, int hotplug)
{
	struct class_device *class_dev;
	struct firmware_priv *fw_priv;
@@ -376,7 +377,10 @@ fw_setup_class_device(struct firmware *fw, struct class_device **class_dev_p,
		goto error_unreg;
	}

	if (hotplug)
                set_bit(FW_STATUS_READY, &fw_priv->status);
        else
                set_bit(FW_STATUS_READY_NOHOTPLUG, &fw_priv->status);
	*class_dev_p = class_dev;
	goto out;

@@ -386,21 +390,9 @@ fw_setup_class_device(struct firmware *fw, struct class_device **class_dev_p,
	return retval;
}

/**
 * request_firmware: - request firmware to hotplug and wait for it
 * Description:
 *	@firmware will be used to return a firmware image by the name
 *	of @name for device @device.
 *
 *	Should be called from user context where sleeping is allowed.
 *
 *	@name will be use as $FIRMWARE in the hotplug environment and
 *	should be distinctive enough not to be confused with any other
 *	firmware image for this or any other device.
 **/
int
request_firmware(const struct firmware **firmware_p, const char *name,
		 struct device *device)
static int
_request_firmware(const struct firmware **firmware_p, const char *name,
		 struct device *device, int hotplug)
{
	struct class_device *class_dev;
	struct firmware_priv *fw_priv;
@@ -419,12 +411,14 @@ request_firmware(const struct firmware **firmware_p, const char *name,
	}
	memset(firmware, 0, sizeof (*firmware));

	retval = fw_setup_class_device(firmware, &class_dev, name, device);
	retval = fw_setup_class_device(firmware, &class_dev, name, device,
		hotplug);
	if (retval)
		goto error_kfree_fw;

	fw_priv = class_get_devdata(class_dev);

	if (hotplug) {
		if (loading_timeout > 0) {
			fw_priv->timeout.expires = jiffies + loading_timeout * HZ;
			add_timer(&fw_priv->timeout);
@@ -433,8 +427,9 @@ request_firmware(const struct firmware **firmware_p, const char *name,
		kobject_hotplug(&class_dev->kobj, KOBJ_ADD);
		wait_for_completion(&fw_priv->completion);
		set_bit(FW_STATUS_DONE, &fw_priv->status);

		del_timer_sync(&fw_priv->timeout);
	} else
		wait_for_completion(&fw_priv->completion);

	down(&fw_lock);
	if (!fw_priv->fw->size || test_bit(FW_STATUS_ABORT, &fw_priv->status)) {
@@ -454,6 +449,26 @@ request_firmware(const struct firmware **firmware_p, const char *name,
	return retval;
}

/**
 * request_firmware: - request firmware to hotplug and wait for it
 * Description:
 *      @firmware will be used to return a firmware image by the name
 *      of @name for device @device.
 *
 *      Should be called from user context where sleeping is allowed.
 *
 *      @name will be use as $FIRMWARE in the hotplug environment and
 *      should be distinctive enough not to be confused with any other
 *      firmware image for this or any other device.
 **/
int
request_firmware(const struct firmware **firmware_p, const char *name,
                 struct device *device)
{
        int hotplug = 1;
        return _request_firmware(firmware_p, name, device, hotplug);
}

/**
 * release_firmware: - release the resource associated with a firmware image
 **/
@@ -491,6 +506,7 @@ struct firmware_work {
	struct device *device;
	void *context;
	void (*cont)(const struct firmware *fw, void *context);
	int hotplug;
};

static int
@@ -503,7 +519,8 @@ request_firmware_work_func(void *arg)
		return 0;
	}
	daemonize("%s/%s", "firmware", fw_work->name);
	request_firmware(&fw, fw_work->name, fw_work->device);
	_request_firmware(&fw, fw_work->name, fw_work->device,
		fw_work->hotplug);
	fw_work->cont(fw, fw_work->context);
	release_firmware(fw);
	module_put(fw_work->module);
@@ -518,6 +535,9 @@ request_firmware_work_func(void *arg)
 *	Asynchronous variant of request_firmware() for contexts where
 *	it is not possible to sleep.
 *
 *      @hotplug invokes hotplug event to copy the firmware image if this flag
 *      is non-zero else the firmware copy must be done manually.
 *
 *	@cont will be called asynchronously when the firmware request is over.
 *
 *	@context will be passed over to @cont.
@@ -527,7 +547,7 @@ request_firmware_work_func(void *arg)
 **/
int
request_firmware_nowait(
	struct module *module,
	struct module *module, int hotplug,
	const char *name, struct device *device, void *context,
	void (*cont)(const struct firmware *fw, void *context))
{
@@ -548,6 +568,7 @@ request_firmware_nowait(
		.device = device,
		.context = context,
		.cont = cont,
		.hotplug = hotplug,
	};

	ret = kernel_thread(request_firmware_work_func, fw_work,
+4 −1
Original line number Diff line number Diff line
@@ -3,6 +3,9 @@
#include <linux/module.h>
#include <linux/types.h>
#define FIRMWARE_NAME_MAX 30 
#define FW_ACTION_NOHOTPLUG 0
#define FW_ACTION_HOTPLUG 1

struct firmware {
	size_t size;
	u8 *data;
@@ -11,7 +14,7 @@ struct device;
int request_firmware(const struct firmware **fw, const char *name,
		     struct device *device);
int request_firmware_nowait(
	struct module *module,
	struct module *module, int hotplug,
	const char *name, struct device *device, void *context,
	void (*cont)(const struct firmware *fw, void *context));