diff options
author | Takashi Iwai <tiwai@suse.de> | 2013-12-02 09:38:16 -0500 |
---|---|---|
committer | Greg Kroah-Hartman <gregkh@linuxfoundation.org> | 2013-12-08 21:22:32 -0500 |
commit | bba3a87e982ad5992e776ca1fc409326915d6b44 (patch) | |
tree | 9149b3090514f8715f6899401a4977d3e1dc0d0c /drivers/base/firmware_class.c | |
parent | 020d30f17f196dcbf0c2c68a874345e8885a3149 (diff) |
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 <prarit@redhat.com>
Acked-by: Ming Lei <ming.lei@canonical.com>
Acked-by: Borislav Petkov <bp@suse.de>
Signed-off-by: Takashi Iwai <tiwai@suse.de>
Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
Diffstat (limited to 'drivers/base/firmware_class.c')
-rw-r--r-- | drivers/base/firmware_class.c | 41 |
1 files changed, 34 insertions, 7 deletions
diff --git a/drivers/base/firmware_class.c b/drivers/base/firmware_class.c index eb8fb94ae2c5..1af03648daf8 100644 --- a/drivers/base/firmware_class.c +++ b/drivers/base/firmware_class.c | |||
@@ -1061,7 +1061,7 @@ static int assign_firmware_buf(struct firmware *fw, struct device *device, | |||
1061 | /* called from request_firmware() and request_firmware_work_func() */ | 1061 | /* called from request_firmware() and request_firmware_work_func() */ |
1062 | static int | 1062 | static int |
1063 | _request_firmware(const struct firmware **firmware_p, const char *name, | 1063 | _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) |
1065 | { | 1065 | { |
1066 | struct firmware *fw; | 1066 | struct firmware *fw; |
1067 | long timeout; | 1067 | long timeout; |
@@ -1095,11 +1095,14 @@ _request_firmware(const struct firmware **firmware_p, const char *name, | |||
1095 | 1095 | ||
1096 | ret = fw_get_filesystem_firmware(device, fw->priv); | 1096 | ret = fw_get_filesystem_firmware(device, fw->priv); |
1097 | if (ret) { | 1097 | if (ret) { |
1098 | dev_warn(device, "Direct firmware load failed with error %d\n", | 1098 | if (fallback) { |
1099 | ret); | 1099 | dev_warn(device, |
1100 | dev_warn(device, "Falling back to user helper\n"); | 1100 | "Direct firmware load failed with error %d\n", |
1101 | ret = fw_load_from_user_helper(fw, name, device, | 1101 | ret); |
1102 | dev_warn(device, "Falling back to user helper\n"); | ||
1103 | ret = fw_load_from_user_helper(fw, name, device, | ||
1102 | uevent, nowait, timeout); | 1104 | uevent, nowait, timeout); |
1105 | } | ||
1103 | } | 1106 | } |
1104 | 1107 | ||
1105 | /* don't cache firmware handled without uevent */ | 1108 | /* don't cache firmware handled without uevent */ |
@@ -1146,12 +1149,36 @@ request_firmware(const struct firmware **firmware_p, const char *name, | |||
1146 | 1149 | ||
1147 | /* Need to pin this module until return */ | 1150 | /* Need to pin this module until return */ |
1148 | __module_get(THIS_MODULE); | 1151 | __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); |
1150 | module_put(THIS_MODULE); | 1153 | module_put(THIS_MODULE); |
1151 | return ret; | 1154 | return ret; |
1152 | } | 1155 | } |
1153 | EXPORT_SYMBOL(request_firmware); | 1156 | EXPORT_SYMBOL(request_firmware); |
1154 | 1157 | ||
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 | |||
1155 | /** | 1182 | /** |
1156 | * release_firmware: - release the resource associated with a firmware image | 1183 | * release_firmware: - release the resource associated with a firmware image |
1157 | * @fw: firmware resource to release | 1184 | * @fw: firmware resource to release |
@@ -1185,7 +1212,7 @@ static void request_firmware_work_func(struct work_struct *work) | |||
1185 | fw_work = container_of(work, struct firmware_work, work); | 1212 | fw_work = container_of(work, struct firmware_work, work); |
1186 | 1213 | ||
1187 | _request_firmware(&fw, fw_work->name, fw_work->device, | 1214 | _request_firmware(&fw, fw_work->name, fw_work->device, |
1188 | fw_work->uevent, true); | 1215 | fw_work->uevent, true, true); |
1189 | fw_work->cont(fw, fw_work->context); | 1216 | fw_work->cont(fw, fw_work->context); |
1190 | put_device(fw_work->device); /* taken in request_firmware_nowait() */ | 1217 | put_device(fw_work->device); /* taken in request_firmware_nowait() */ |
1191 | 1218 | ||