Skip to content

Commit bba3a87

Browse files
tiwaigregkh
authored andcommitted
firmware: Introduce request_firmware_direct()
When CONFIG_FW_LOADER_USER_HELPER is set, request_firmware() falls back to the usermode helper for loading via udev when the direct loading fails. But the recent udev takes way too long timeout (60 seconds) for non-existing firmware. This is unacceptable for the drivers like microcode loader where they load firmwares optionally, i.e. it's no error even if no requested file exists. This patch provides a new helper function, request_firmware_direct(). It behaves as same as request_firmware() except for that it doesn't fall back to usermode helper but returns an error immediately if the f/w can't be loaded directly in kernel. Without CONFIG_FW_LOADER_USER_HELPER=y, request_firmware_direct() is just an alias of request_firmware(), due to obvious reason. Tested-by: Prarit Bhargava <[email protected]> Acked-by: Ming Lei <[email protected]> Acked-by: Borislav Petkov <[email protected]> Signed-off-by: Takashi Iwai <[email protected]> Signed-off-by: Greg Kroah-Hartman <[email protected]>
1 parent 020d30f commit bba3a87

File tree

2 files changed

+41
-7
lines changed

2 files changed

+41
-7
lines changed

drivers/base/firmware_class.c

Lines changed: 34 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -1061,7 +1061,7 @@ static int assign_firmware_buf(struct firmware *fw, struct device *device,
10611061
/* called from request_firmware() and request_firmware_work_func() */
10621062
static int
10631063
_request_firmware(const struct firmware **firmware_p, const char *name,
1064-
struct device *device, bool uevent, bool nowait)
1064+
struct device *device, bool uevent, bool nowait, bool fallback)
10651065
{
10661066
struct firmware *fw;
10671067
long timeout;
@@ -1095,11 +1095,14 @@ _request_firmware(const struct firmware **firmware_p, const char *name,
10951095

10961096
ret = fw_get_filesystem_firmware(device, fw->priv);
10971097
if (ret) {
1098-
dev_warn(device, "Direct firmware load failed with error %d\n",
1099-
ret);
1100-
dev_warn(device, "Falling back to user helper\n");
1101-
ret = fw_load_from_user_helper(fw, name, device,
1098+
if (fallback) {
1099+
dev_warn(device,
1100+
"Direct firmware load failed with error %d\n",
1101+
ret);
1102+
dev_warn(device, "Falling back to user helper\n");
1103+
ret = fw_load_from_user_helper(fw, name, device,
11021104
uevent, nowait, timeout);
1105+
}
11031106
}
11041107

11051108
/* don't cache firmware handled without uevent */
@@ -1146,12 +1149,36 @@ request_firmware(const struct firmware **firmware_p, const char *name,
11461149

11471150
/* Need to pin this module until return */
11481151
__module_get(THIS_MODULE);
1149-
ret = _request_firmware(firmware_p, name, device, true, false);
1152+
ret = _request_firmware(firmware_p, name, device, true, false, true);
11501153
module_put(THIS_MODULE);
11511154
return ret;
11521155
}
11531156
EXPORT_SYMBOL(request_firmware);
11541157

1158+
#ifdef CONFIG_FW_LOADER_USER_HELPER
1159+
/**
1160+
* request_firmware: - load firmware directly without usermode helper
1161+
* @firmware_p: pointer to firmware image
1162+
* @name: name of firmware file
1163+
* @device: device for which firmware is being loaded
1164+
*
1165+
* This function works pretty much like request_firmware(), but this doesn't
1166+
* fall back to usermode helper even if the firmware couldn't be loaded
1167+
* directly from fs. Hence it's useful for loading optional firmwares, which
1168+
* aren't always present, without extra long timeouts of udev.
1169+
**/
1170+
int request_firmware_direct(const struct firmware **firmware_p,
1171+
const char *name, struct device *device)
1172+
{
1173+
int ret;
1174+
__module_get(THIS_MODULE);
1175+
ret = _request_firmware(firmware_p, name, device, true, false, false);
1176+
module_put(THIS_MODULE);
1177+
return ret;
1178+
}
1179+
EXPORT_SYMBOL_GPL(request_firmware_direct);
1180+
#endif
1181+
11551182
/**
11561183
* release_firmware: - release the resource associated with a firmware image
11571184
* @fw: firmware resource to release
@@ -1185,7 +1212,7 @@ static void request_firmware_work_func(struct work_struct *work)
11851212
fw_work = container_of(work, struct firmware_work, work);
11861213

11871214
_request_firmware(&fw, fw_work->name, fw_work->device,
1188-
fw_work->uevent, true);
1215+
fw_work->uevent, true, true);
11891216
fw_work->cont(fw, fw_work->context);
11901217
put_device(fw_work->device); /* taken in request_firmware_nowait() */
11911218

include/linux/firmware.h

Lines changed: 7 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -68,4 +68,11 @@ static inline void release_firmware(const struct firmware *fw)
6868

6969
#endif
7070

71+
#ifdef CONFIG_FW_LOADER_USER_HELPER
72+
int request_firmware_direct(const struct firmware **fw, const char *name,
73+
struct device *device);
74+
#else
75+
#define request_firmware_direct request_firmware
76+
#endif
77+
7178
#endif

0 commit comments

Comments
 (0)