[ Upstream commits: a144c6a6c924aa1da04dd77fb84b89927354fdff caca9510ff4e5d842c0589110243d60927836222
squashed together into one.] Some drivers erroneously use request_firmware() from their ->resume() (or ->thaw(), or ->restore()) callbacks, which is not going to work unless the firmware has been built in. This causes system resume to stall until the firmware-loading timeout expires, which makes users think that the resume has failed and reboot their machines unnecessarily. For this reason, make _request_firmware() print a warning and return immediately with error code if it has been called when tasks are frozen and it's impossible to start any new usermode helpers. And put this check *after* checking if the firmware is built-in. Signed-off-by: Rafael J. Wysocki <[email protected]> Acked-by: Greg Kroah-Hartman <[email protected]> Reviewed-by: Valdis Kletnieks <[email protected]> Reported-by: James Cloos <[email protected]> Bisected-by: Elimar Riesebieter <[email protected]> Signed-off-by: Linus Torvalds <[email protected]> Signed-off-by: Srivatsa S. Bhat <[email protected]> --- drivers/base/firmware_class.c | 6 ++++++ include/linux/kmod.h | 6 +++++- kernel/kmod.c | 9 +++++++++ 3 files changed, 20 insertions(+), 1 deletions(-) diff --git a/drivers/base/firmware_class.c b/drivers/base/firmware_class.c index f6872f9..080e44e 100644 --- a/drivers/base/firmware_class.c +++ b/drivers/base/firmware_class.c @@ -508,6 +508,12 @@ _request_firmware(const struct firmware **firmware_p, const char *name, return 0; } + if (WARN_ON(usermodehelper_is_disabled())) { + dev_err(device, "firmware: %s will not be loaded\n", name); + retval = -EBUSY; + goto out; + } + if (uevent) dev_info(device, "firmware: requesting %s\n", name); diff --git a/include/linux/kmod.h b/include/linux/kmod.h index 384ca8b..ea44825 100644 --- a/include/linux/kmod.h +++ b/include/linux/kmod.h @@ -104,7 +104,11 @@ struct file; extern int call_usermodehelper_pipe(char *path, char *argv[], char *envp[], struct file **filp); +#ifdef CONFIG_PM_SLEEP extern int usermodehelper_disable(void); extern void usermodehelper_enable(void); - +extern bool usermodehelper_is_disabled(void); +#else +static inline bool usermodehelper_is_disabled(void) { return false; } +#endif #endif /* __LINUX_KMOD_H__ */ diff --git a/kernel/kmod.c b/kernel/kmod.c index d206078..163a919 100644 --- a/kernel/kmod.c +++ b/kernel/kmod.c @@ -337,6 +337,15 @@ void usermodehelper_enable(void) usermodehelper_disabled = 0; } +/** + * usermodehelper_is_disabled - check if new helpers are allowed to be started + */ +bool usermodehelper_is_disabled(void) +{ + return usermodehelper_disabled; +} +EXPORT_SYMBOL_GPL(usermodehelper_is_disabled); + static void helper_lock(void) { atomic_inc(&running_helpers); -- To unsubscribe from this list: send the line "unsubscribe stable" in the body of a message to [email protected] More majordomo info at http://vger.kernel.org/majordomo-info.html
