| From srivatsa.bhat@linux.vnet.ibm.com Thu Mar 1 13:30:46 2012 |
| From: "Srivatsa S. Bhat" <srivatsa.bhat@linux.vnet.ibm.com> |
| Date: Wed, 29 Feb 2012 12:22:41 +0530 |
| Subject: PM: Print a warning if firmware is requested when tasks are frozen |
| To: gregkh@linuxfoundation.org |
| Cc: stable@vger.kernel.org, rjw@sisk.pl, valdis.kletnieks@vt.edu, cloos@hjcloos.com, riesebie@lxtec.de, torvalds@linux-foundation.org, penguin-kernel@i-love.sakura.ne.jp, srivatsa.bhat@linux.vnet.ibm.com |
| Message-ID: <20120229065115.4761.59767.stgit@srivatsabhat.in.ibm.com> |
| |
| |
| From: Rafael J. Wysocki <rjw@sisk.pl> |
| |
| [ Upstream commit a144c6a6c924aa1da04dd77fb84b89927354fdff ] |
| |
| 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. |
| |
| Signed-off-by: Rafael J. Wysocki <rjw@sisk.pl> |
| Acked-by: Greg Kroah-Hartman <gregkh@suse.de> |
| Reviewed-by: Valdis Kletnieks <valdis.kletnieks@vt.edu> |
| Signed-off-by: Srivatsa S. Bhat <srivatsa.bhat@linux.vnet.ibm.com> |
| Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org> |
| --- |
| |
| drivers/base/firmware_class.c | 5 +++++ |
| include/linux/kmod.h | 5 +++++ |
| kernel/kmod.c | 9 +++++++++ |
| 3 files changed, 19 insertions(+) |
| |
| --- a/drivers/base/firmware_class.c |
| +++ b/drivers/base/firmware_class.c |
| @@ -489,6 +489,11 @@ _request_firmware(const struct firmware |
| if (!firmware_p) |
| return -EINVAL; |
| |
| + if (WARN_ON(usermodehelper_is_disabled())) { |
| + dev_err(device, "firmware: %s will not be loaded\n", name); |
| + return -EBUSY; |
| + } |
| + |
| *firmware_p = firmware = kzalloc(sizeof(*firmware), GFP_KERNEL); |
| if (!firmware) { |
| dev_err(device, "%s: kmalloc(struct firmware) failed\n", |
| --- a/include/linux/kmod.h |
| +++ b/include/linux/kmod.h |
| @@ -104,7 +104,12 @@ 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__ */ |
| --- 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); |