The direct firmware loading interface is a bit quiet about failures. Failures
that occur during loading are masked if firmware exists in multiple locations,
and may be masked entirely in the event that we fall back to the user mode
helper code. It would be nice to see some of the more unexpected errors get
logged, so in the event that you expect the direct firmware loader to work (like
if CONFIG_FW_LOADER_USER_HELPER is enabled), and something goes wrong, you can
figure out what happened.
Signed-off-by: Neil Horman <nhorman@tuxdriver.com>
Acked-by: Ming Lei <ming.lei@canonical.com>
Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
-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)
size = fw_file_size(file);
if (size <= 0)
size = fw_file_size(file);
if (size <= 0)
buf = vmalloc(size);
if (!buf)
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;
}
fw_buf->data = buf;
fw_buf->size = size;
}
fw_buf->data = buf;
fw_buf->size = size;
-static bool fw_get_filesystem_firmware(struct device *device,
+static int fw_get_filesystem_firmware(struct device *device,
struct firmware_buf *buf)
{
int i;
struct firmware_buf *buf)
{
int i;
char *path = __getname();
for (i = 0; i < ARRAY_SIZE(fw_path); i++) {
char *path = __getname();
for (i = 0; i < ARRAY_SIZE(fw_path); i++) {
file = filp_open(path, O_RDONLY, 0);
if (IS_ERR(file))
continue;
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);
+ if (rc)
+ dev_warn(device, "firmware, attempted to load %s, but failed with error %d\n",
+ path, rc);
+ else
break;
}
__putname(path);
break;
}
__putname(path);
dev_dbg(device, "firmware: direct-loading firmware %s\n",
buf->fw_id);
mutex_lock(&fw_lock);
dev_dbg(device, "firmware: direct-loading firmware %s\n",
buf->fw_id);
mutex_lock(&fw_lock);
mutex_unlock(&fw_lock);
}
mutex_unlock(&fw_lock);
}
}
/* firmware holds the ownership of pages */
}
/* firmware holds the ownership of pages */
- 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);
ret = fw_load_from_user_helper(fw, name, device,
uevent, nowait, timeout);
/* don't cache firmware handled without uevent */
if (!ret)
/* don't cache firmware handled without uevent */
if (!ret)