summaryrefslogtreecommitdiff
path: root/kernel
diff options
context:
space:
mode:
authorRafael J. Wysocki <rjw@sisk.pl>2012-03-28 23:30:02 +0200
committerGreg Kroah-Hartman <gregkh@linuxfoundation.org>2012-04-13 09:13:53 -0700
commit91cb632cd8d0a1649d088a50e752459d1e8b3d79 (patch)
tree61f3b27100b1b5204e52584a89c5467ca9a720b5 /kernel
parent4aaf8189db4a00e133afbb0e538e8c4f5551a833 (diff)
downloadlwn-91cb632cd8d0a1649d088a50e752459d1e8b3d79.tar.gz
lwn-91cb632cd8d0a1649d088a50e752459d1e8b3d79.zip
firmware_class: Do not warn that system is not ready from async loads
commit 9b78c1da60b3c62ccdd1509f0902ad19ceaf776b upstream. If firmware is requested asynchronously, by calling request_firmware_nowait(), there is no reason to fail the request (and warn the user) when the system is (presumably temporarily) unready to handle it (because user space is not available yet or frozen). For this reason, introduce an alternative routine for read-locking umhelper_sem, usermodehelper_read_lock_wait(), that will wait for usermodehelper_disabled to be unset (possibly with a timeout) and make request_firmware_work_func() use it instead of usermodehelper_read_trylock(). Accordingly, modify request_firmware() so that it uses usermodehelper_read_trylock() to acquire umhelper_sem and remove the code related to that lock from _request_firmware(). Signed-off-by: Rafael J. Wysocki <rjw@sisk.pl> Acked-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org> Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
Diffstat (limited to 'kernel')
-rw-r--r--kernel/kmod.c58
1 files changed, 45 insertions, 13 deletions
diff --git a/kernel/kmod.c b/kernel/kmod.c
index 3973cde0cabf..75f76b66da6d 100644
--- a/kernel/kmod.c
+++ b/kernel/kmod.c
@@ -291,6 +291,12 @@ static atomic_t running_helpers = ATOMIC_INIT(0);
static DECLARE_WAIT_QUEUE_HEAD(running_helpers_waitq);
/*
+ * Used by usermodehelper_read_lock_wait() to wait for usermodehelper_disabled
+ * to become 'false'.
+ */
+static DECLARE_WAIT_QUEUE_HEAD(usermodehelper_disabled_waitq);
+
+/*
* Time to wait for running_helpers to become zero before the setting of
* usermodehelper_disabled in usermodehelper_disable() fails
*/
@@ -309,6 +315,33 @@ int usermodehelper_read_trylock(void)
}
EXPORT_SYMBOL_GPL(usermodehelper_read_trylock);
+long usermodehelper_read_lock_wait(long timeout)
+{
+ DEFINE_WAIT(wait);
+
+ if (timeout < 0)
+ return -EINVAL;
+
+ down_read(&umhelper_sem);
+ for (;;) {
+ prepare_to_wait(&usermodehelper_disabled_waitq, &wait,
+ TASK_UNINTERRUPTIBLE);
+ if (!usermodehelper_disabled)
+ break;
+
+ up_read(&umhelper_sem);
+
+ timeout = schedule_timeout(timeout);
+ if (!timeout)
+ break;
+
+ down_read(&umhelper_sem);
+ }
+ finish_wait(&usermodehelper_disabled_waitq, &wait);
+ return timeout;
+}
+EXPORT_SYMBOL_GPL(usermodehelper_read_lock_wait);
+
void usermodehelper_read_unlock(void)
{
up_read(&umhelper_sem);
@@ -316,6 +349,17 @@ void usermodehelper_read_unlock(void)
EXPORT_SYMBOL_GPL(usermodehelper_read_unlock);
/**
+ * usermodehelper_enable - allow new helpers to be started again
+ */
+void usermodehelper_enable(void)
+{
+ down_write(&umhelper_sem);
+ usermodehelper_disabled = 0;
+ wake_up(&usermodehelper_disabled_waitq);
+ up_write(&umhelper_sem);
+}
+
+/**
* usermodehelper_disable - prevent new helpers from being started
*/
int usermodehelper_disable(void)
@@ -338,22 +382,10 @@ int usermodehelper_disable(void)
if (retval)
return 0;
- down_write(&umhelper_sem);
- usermodehelper_disabled = 0;
- up_write(&umhelper_sem);
+ usermodehelper_enable();
return -EAGAIN;
}
-/**
- * usermodehelper_enable - allow new helpers to be started again
- */
-void usermodehelper_enable(void)
-{
- down_write(&umhelper_sem);
- usermodehelper_disabled = 0;
- up_write(&umhelper_sem);
-}
-
static void helper_lock(void)
{
atomic_inc(&running_helpers);