diff options
| author | Rafael J. Wysocki <rjw@sisk.pl> | 2012-03-28 23:29:55 +0200 | 
|---|---|---|
| committer | Rafael J. Wysocki <rjw@sisk.pl> | 2012-03-28 23:29:55 +0200 | 
| commit | 811fa4004485dec8977176bf605a5b0508ee206c (patch) | |
| tree | afa0924a75f217a27f7438e34758747413ba635a /drivers/base/firmware_class.c | |
| parent | fe2e39d8782d885755139304d8dba0b3e5bfa878 (diff) | |
| download | olio-linux-3.10-811fa4004485dec8977176bf605a5b0508ee206c.tar.xz olio-linux-3.10-811fa4004485dec8977176bf605a5b0508ee206c.zip  | |
firmware_class: Split _request_firmware() into three functions, v2
Split _request_firmware() into three functions,
_request_firmware_prepare() doing preparatory work that need not be
done under umhelper_sem, _request_firmware_cleanup() doing the
post-error cleanup and _request_firmware() carrying out the remaining
operations.
This change is requisite for moving the acquisition of umhelper_sem
from _request_firmware() to the callers, which is going to be done
subsequently.
Signed-off-by: Rafael J. Wysocki <rjw@sisk.pl>
Acked-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
Reviewed-by: Stephen Boyd <sboyd@codeaurora.org>
Cc: stable@vger.kernel.org
Diffstat (limited to 'drivers/base/firmware_class.c')
| -rw-r--r-- | drivers/base/firmware_class.c | 58 | 
1 files changed, 41 insertions, 17 deletions
diff --git a/drivers/base/firmware_class.c b/drivers/base/firmware_class.c index deee871e509..60290671f04 100644 --- a/drivers/base/firmware_class.c +++ b/drivers/base/firmware_class.c @@ -435,7 +435,7 @@ static void firmware_class_timeout(u_long data)  }  static struct firmware_priv * -fw_create_instance(struct firmware *firmware, const char *fw_name, +fw_create_instance(const struct firmware *firmware, const char *fw_name,  		   struct device *device, bool uevent, bool nowait)  {  	struct firmware_priv *fw_priv; @@ -449,7 +449,7 @@ fw_create_instance(struct firmware *firmware, const char *fw_name,  		goto err_out;  	} -	fw_priv->fw = firmware; +	fw_priv->fw = (struct firmware *)firmware;  	fw_priv->nowait = nowait;  	strcpy(fw_priv->fw_id, fw_name);  	init_completion(&fw_priv->completion); @@ -510,13 +510,10 @@ static void fw_destroy_instance(struct firmware_priv *fw_priv)  	device_unregister(f_dev);  } -static int _request_firmware(const struct firmware **firmware_p, -			     const char *name, struct device *device, -			     bool uevent, bool nowait) +static int _request_firmware_prepare(const struct firmware **firmware_p, +				     const char *name, struct device *device)  { -	struct firmware_priv *fw_priv;  	struct firmware *firmware; -	int retval = 0;  	if (!firmware_p)  		return -EINVAL; @@ -533,10 +530,26 @@ static int _request_firmware(const struct firmware **firmware_p,  		return 0;  	} +	return 1; +} + +static void _request_firmware_cleanup(const struct firmware **firmware_p) +{ +	release_firmware(*firmware_p); +	*firmware_p = NULL; +} + +static int _request_firmware(const struct firmware *firmware, +			     const char *name, struct device *device, +			     bool uevent, bool nowait) +{ +	struct firmware_priv *fw_priv; +	int retval; +  	retval = usermodehelper_read_trylock();  	if (WARN_ON(retval)) {  		dev_err(device, "firmware: %s will not be loaded\n", name); -		goto out_nolock; +		return retval;  	}  	if (uevent) @@ -572,13 +585,6 @@ static int _request_firmware(const struct firmware **firmware_p,  out:  	usermodehelper_read_unlock(); - -out_nolock: -	if (retval) { -		release_firmware(firmware); -		*firmware_p = NULL; -	} -  	return retval;  } @@ -601,7 +607,17 @@ int  request_firmware(const struct firmware **firmware_p, const char *name,                   struct device *device)  { -        return _request_firmware(firmware_p, name, device, true, false); +	int ret; + +	ret = _request_firmware_prepare(firmware_p, name, device); +	if (ret <= 0) +		return ret; + +	ret = _request_firmware(*firmware_p, name, device, true, false); +	if (ret) +		_request_firmware_cleanup(firmware_p); + +	return ret;  }  /** @@ -639,8 +655,16 @@ static int request_firmware_work_func(void *arg)  		return 0;  	} -	ret = _request_firmware(&fw, fw_work->name, fw_work->device, +	ret = _request_firmware_prepare(&fw, fw_work->name, fw_work->device); +	if (ret <= 0) +		goto out; + +	ret = _request_firmware(fw, fw_work->name, fw_work->device,  				fw_work->uevent, true); +	if (ret) +		_request_firmware_cleanup(&fw); + + out:  	fw_work->cont(fw, fw_work->context);  	module_put(fw_work->module);  |