diff options
Diffstat (limited to 'drivers/base/firmware_loader/fallback.c')
| -rw-r--r-- | drivers/base/firmware_loader/fallback.c | 55 | 
1 files changed, 40 insertions, 15 deletions
diff --git a/drivers/base/firmware_loader/fallback.c b/drivers/base/firmware_loader/fallback.c index 358354148dec..7f732744f0d3 100644 --- a/drivers/base/firmware_loader/fallback.c +++ b/drivers/base/firmware_loader/fallback.c @@ -125,7 +125,7 @@ static ssize_t timeout_show(struct class *class, struct class_attribute *attr,  }  /** - * firmware_timeout_store - set number of seconds to wait for firmware + * firmware_timeout_store() - set number of seconds to wait for firmware   * @class: device class pointer   * @attr: device attribute pointer   * @buf: buffer to scan for timeout value @@ -239,7 +239,7 @@ static int map_fw_priv_pages(struct fw_priv *fw_priv)  }  /** - * firmware_loading_store - set value in the 'loading' control file + * firmware_loading_store() - set value in the 'loading' control file   * @dev: device pointer   * @attr: device attribute pointer   * @buf: buffer to scan for loading control value @@ -403,7 +403,7 @@ static int fw_realloc_pages(struct fw_sysfs *fw_sysfs, int min_size)  					 fw_priv->page_array_size * 2);  		struct page **new_pages; -		new_pages = vmalloc(new_array_size * sizeof(void *)); +		new_pages = vmalloc(array_size(new_array_size, sizeof(void *)));  		if (!new_pages) {  			fw_load_abort(fw_sysfs);  			return -ENOMEM; @@ -431,7 +431,7 @@ static int fw_realloc_pages(struct fw_sysfs *fw_sysfs, int min_size)  }  /** - * firmware_data_write - write method for firmware + * firmware_data_write() - write method for firmware   * @filp: open sysfs file   * @kobj: kobject for the device   * @bin_attr: bin_attr structure @@ -512,7 +512,7 @@ static const struct attribute_group *fw_dev_attr_groups[] = {  static struct fw_sysfs *  fw_create_instance(struct firmware *firmware, const char *fw_name, -		   struct device *device, unsigned int opt_flags) +		   struct device *device, enum fw_opt opt_flags)  {  	struct fw_sysfs *fw_sysfs;  	struct device *f_dev; @@ -537,7 +537,7 @@ exit:  }  /** - * fw_load_sysfs_fallback - load a firmware via the sysfs fallback mechanism + * fw_load_sysfs_fallback() - load a firmware via the sysfs fallback mechanism   * @fw_sysfs: firmware sysfs information for the firmware to load   * @opt_flags: flags of options, FW_OPT_*   * @timeout: timeout to wait for the load @@ -545,7 +545,7 @@ exit:   * In charge of constructing a sysfs fallback interface for firmware loading.   **/  static int fw_load_sysfs_fallback(struct fw_sysfs *fw_sysfs, -				  unsigned int opt_flags, long timeout) +				  enum fw_opt opt_flags, long timeout)  {  	int retval = 0;  	struct device *f_dev = &fw_sysfs->dev; @@ -599,7 +599,7 @@ err_put_dev:  static int fw_load_from_user_helper(struct firmware *firmware,  				    const char *name, struct device *device, -				    unsigned int opt_flags) +				    enum fw_opt opt_flags)  {  	struct fw_sysfs *fw_sysfs;  	long timeout; @@ -640,7 +640,7 @@ out_unlock:  	return ret;  } -static bool fw_force_sysfs_fallback(unsigned int opt_flags) +static bool fw_force_sysfs_fallback(enum fw_opt opt_flags)  {  	if (fw_fallback_config.force_sysfs_fallback)  		return true; @@ -649,7 +649,7 @@ static bool fw_force_sysfs_fallback(unsigned int opt_flags)  	return true;  } -static bool fw_run_sysfs_fallback(unsigned int opt_flags) +static bool fw_run_sysfs_fallback(enum fw_opt opt_flags)  {  	if (fw_fallback_config.ignore_sysfs_fallback) {  		pr_info_once("Ignoring firmware sysfs fallback due to sysctl knob\n"); @@ -662,14 +662,39 @@ static bool fw_run_sysfs_fallback(unsigned int opt_flags)  	return fw_force_sysfs_fallback(opt_flags);  } -int fw_sysfs_fallback(struct firmware *fw, const char *name, -		      struct device *device, -		      unsigned int opt_flags, -		      int ret) +/** + * firmware_fallback_sysfs() - use the fallback mechanism to find firmware + * @fw: pointer to firmware image + * @name: name of firmware file to look for + * @device: device for which firmware is being loaded + * @opt_flags: options to control firmware loading behaviour + * @ret: return value from direct lookup which triggered the fallback mechanism + * + * This function is called if direct lookup for the firmware failed, it enables + * a fallback mechanism through userspace by exposing a sysfs loading + * interface. Userspace is in charge of loading the firmware through the syfs + * loading interface. This syfs fallback mechanism may be disabled completely + * on a system by setting the proc sysctl value ignore_sysfs_fallback to true. + * If this false we check if the internal API caller set the @FW_OPT_NOFALLBACK + * flag, if so it would also disable the fallback mechanism. A system may want + * to enfoce the sysfs fallback mechanism at all times, it can do this by + * setting ignore_sysfs_fallback to false and force_sysfs_fallback to true. + * Enabling force_sysfs_fallback is functionally equivalent to build a kernel + * with CONFIG_FW_LOADER_USER_HELPER_FALLBACK. + **/ +int firmware_fallback_sysfs(struct firmware *fw, const char *name, +			    struct device *device, +			    enum fw_opt opt_flags, +			    int ret)  {  	if (!fw_run_sysfs_fallback(opt_flags))  		return ret; -	dev_warn(device, "Falling back to user helper\n"); +	if (!(opt_flags & FW_OPT_NO_WARN)) +		dev_warn(device, "Falling back to syfs fallback for: %s\n", +				 name); +	else +		dev_dbg(device, "Falling back to sysfs fallback for: %s\n", +				name);  	return fw_load_from_user_helper(fw, name, device, opt_flags);  }  |