diff options
Diffstat (limited to 'drivers/base/firmware_class.c')
| -rw-r--r-- | drivers/base/firmware_class.c | 38 | 
1 files changed, 25 insertions, 13 deletions
diff --git a/drivers/base/firmware_class.c b/drivers/base/firmware_class.c index 10a4467c63f1..eb8fb94ae2c5 100644 --- a/drivers/base/firmware_class.c +++ b/drivers/base/firmware_class.c @@ -282,31 +282,35 @@ static noinline_for_stack long fw_file_size(struct file *file)  	return st.size;  } -static bool fw_read_file_contents(struct file *file, struct firmware_buf *fw_buf) +static int fw_read_file_contents(struct file *file, struct firmware_buf *fw_buf)  {  	long size;  	char *buf; +	int rc;  	size = fw_file_size(file);  	if (size <= 0) -		return false; +		return -EINVAL;  	buf = vmalloc(size);  	if (!buf) -		return false; -	if (kernel_read(file, 0, buf, size) != size) { +		return -ENOMEM; +	rc = kernel_read(file, 0, buf, size); +	if (rc != size) { +		if (rc > 0) +			rc = -EIO;  		vfree(buf); -		return false; +		return rc;  	}  	fw_buf->data = buf;  	fw_buf->size = size; -	return true; +	return 0;  } -static bool fw_get_filesystem_firmware(struct device *device, +static int fw_get_filesystem_firmware(struct device *device,  				       struct firmware_buf *buf)  {  	int i; -	bool success = false; +	int rc = -ENOENT;  	char *path = __getname();  	for (i = 0; i < ARRAY_SIZE(fw_path); i++) { @@ -321,14 +325,17 @@ static bool fw_get_filesystem_firmware(struct device *device,  		file = filp_open(path, O_RDONLY, 0);  		if (IS_ERR(file))  			continue; -		success = fw_read_file_contents(file, buf); +		rc = fw_read_file_contents(file, buf);  		fput(file); -		if (success) +		if (rc) +			dev_warn(device, "firmware, attempted to load %s, but failed with error %d\n", +				path, rc); +		else  			break;  	}  	__putname(path); -	if (success) { +	if (!rc) {  		dev_dbg(device, "firmware: direct-loading firmware %s\n",  			buf->fw_id);  		mutex_lock(&fw_lock); @@ -337,7 +344,7 @@ static bool fw_get_filesystem_firmware(struct device *device,  		mutex_unlock(&fw_lock);  	} -	return success; +	return rc;  }  /* firmware holds the ownership of pages */ @@ -1086,9 +1093,14 @@ _request_firmware(const struct firmware **firmware_p, const char *name,  		}  	} -	if (!fw_get_filesystem_firmware(device, fw->priv)) +	ret = fw_get_filesystem_firmware(device, fw->priv); +	if (ret) { +		dev_warn(device, "Direct firmware load failed with error %d\n", +			 ret); +		dev_warn(device, "Falling back to user helper\n");  		ret = fw_load_from_user_helper(fw, name, device,  					       uevent, nowait, timeout); +	}  	/* don't cache firmware handled without uevent */  	if (!ret)  |