firmware: ensure the firmware cache is not used on incompatible calls
request_firmware_into_buf() explicitly disables the firmware cache, meanwhile the firmware cache cannot be used when request_firmware_nowait() is used without the uevent. Enforce a sanity check for this to avoid future issues undocumented behaviours should misuses of the firmware cache happen later. One of the reasons we want to enforce this is the firmware cache is used for helping with suspend/resume, and if incompatible calls use it they can stall suspend. Signed-off-by: Luis R. Rodriguez <mcgrof@kernel.org> Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
This commit is contained in:
Родитель
9952db75e0
Коммит
995e8695f6
|
@ -431,6 +431,11 @@ static int fw_add_devm_name(struct device *dev, const char *name)
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
#else
|
#else
|
||||||
|
static bool fw_cache_is_setup(struct device *dev, const char *name)
|
||||||
|
{
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
static int fw_add_devm_name(struct device *dev, const char *name)
|
static int fw_add_devm_name(struct device *dev, const char *name)
|
||||||
{
|
{
|
||||||
return 0;
|
return 0;
|
||||||
|
@ -672,6 +677,9 @@ request_firmware_into_buf(const struct firmware **firmware_p, const char *name,
|
||||||
{
|
{
|
||||||
int ret;
|
int ret;
|
||||||
|
|
||||||
|
if (fw_cache_is_setup(device, name))
|
||||||
|
return -EOPNOTSUPP;
|
||||||
|
|
||||||
__module_get(THIS_MODULE);
|
__module_get(THIS_MODULE);
|
||||||
ret = _request_firmware(firmware_p, name, device, buf, size,
|
ret = _request_firmware(firmware_p, name, device, buf, size,
|
||||||
FW_OPT_UEVENT | FW_OPT_NOCACHE);
|
FW_OPT_UEVENT | FW_OPT_NOCACHE);
|
||||||
|
@ -769,6 +777,12 @@ request_firmware_nowait(
|
||||||
fw_work->opt_flags = FW_OPT_NOWAIT |
|
fw_work->opt_flags = FW_OPT_NOWAIT |
|
||||||
(uevent ? FW_OPT_UEVENT : FW_OPT_USERHELPER);
|
(uevent ? FW_OPT_UEVENT : FW_OPT_USERHELPER);
|
||||||
|
|
||||||
|
if (!uevent && fw_cache_is_setup(device, name)) {
|
||||||
|
kfree_const(fw_work->name);
|
||||||
|
kfree(fw_work);
|
||||||
|
return -EOPNOTSUPP;
|
||||||
|
}
|
||||||
|
|
||||||
if (!try_module_get(module)) {
|
if (!try_module_get(module)) {
|
||||||
kfree_const(fw_work->name);
|
kfree_const(fw_work->name);
|
||||||
kfree(fw_work);
|
kfree(fw_work);
|
||||||
|
|
Загрузка…
Ссылка в новой задаче