aboutsummaryrefslogtreecommitdiffstats
path: root/drivers/base/firmware_class.c
diff options
context:
space:
mode:
authorRafael J. Wysocki <rjw@sisk.pl>2012-03-28 17:30:02 -0400
committerRafael J. Wysocki <rjw@sisk.pl>2012-03-28 17:30:02 -0400
commit9b78c1da60b3c62ccdd1509f0902ad19ceaf776b (patch)
tree1e662bb29f04c2b875207d907db917476ddce60b /drivers/base/firmware_class.c
parent811fa4004485dec8977176bf605a5b0508ee206c (diff)
firmware_class: Do not warn that system is not ready from async loads
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> Cc: stable@vger.kernel.org
Diffstat (limited to 'drivers/base/firmware_class.c')
-rw-r--r--drivers/base/firmware_class.c51
1 files changed, 30 insertions, 21 deletions
diff --git a/drivers/base/firmware_class.c b/drivers/base/firmware_class.c
index 60290671f04a..72c644b191a4 100644
--- a/drivers/base/firmware_class.c
+++ b/drivers/base/firmware_class.c
@@ -81,6 +81,11 @@ enum {
81 81
82static int loading_timeout = 60; /* In seconds */ 82static int loading_timeout = 60; /* In seconds */
83 83
84static inline long firmware_loading_timeout(void)
85{
86 return loading_timeout > 0 ? loading_timeout * HZ : MAX_SCHEDULE_TIMEOUT;
87}
88
84/* fw_lock could be moved to 'struct firmware_priv' but since it is just 89/* fw_lock could be moved to 'struct firmware_priv' but since it is just
85 * guarding for corner cases a global lock should be OK */ 90 * guarding for corner cases a global lock should be OK */
86static DEFINE_MUTEX(fw_lock); 91static DEFINE_MUTEX(fw_lock);
@@ -541,31 +546,22 @@ static void _request_firmware_cleanup(const struct firmware **firmware_p)
541 546
542static int _request_firmware(const struct firmware *firmware, 547static int _request_firmware(const struct firmware *firmware,
543 const char *name, struct device *device, 548 const char *name, struct device *device,
544 bool uevent, bool nowait) 549 bool uevent, bool nowait, long timeout)
545{ 550{
546 struct firmware_priv *fw_priv; 551 struct firmware_priv *fw_priv;
547 int retval; 552 int retval = 0;
548
549 retval = usermodehelper_read_trylock();
550 if (WARN_ON(retval)) {
551 dev_err(device, "firmware: %s will not be loaded\n", name);
552 return retval;
553 }
554 553
555 if (uevent) 554 if (uevent)
556 dev_dbg(device, "firmware: requesting %s\n", name); 555 dev_dbg(device, "firmware: requesting %s\n", name);
557 556
558 fw_priv = fw_create_instance(firmware, name, device, uevent, nowait); 557 fw_priv = fw_create_instance(firmware, name, device, uevent, nowait);
559 if (IS_ERR(fw_priv)) { 558 if (IS_ERR(fw_priv))
560 retval = PTR_ERR(fw_priv); 559 return PTR_ERR(fw_priv);
561 goto out;
562 }
563 560
564 if (uevent) { 561 if (uevent) {
565 if (loading_timeout > 0) 562 if (timeout != MAX_SCHEDULE_TIMEOUT)
566 mod_timer(&fw_priv->timeout, 563 mod_timer(&fw_priv->timeout,
567 round_jiffies_up(jiffies + 564 round_jiffies_up(jiffies + timeout));
568 loading_timeout * HZ));
569 565
570 kobject_uevent(&fw_priv->dev.kobj, KOBJ_ADD); 566 kobject_uevent(&fw_priv->dev.kobj, KOBJ_ADD);
571 } 567 }
@@ -582,9 +578,6 @@ static int _request_firmware(const struct firmware *firmware,
582 mutex_unlock(&fw_lock); 578 mutex_unlock(&fw_lock);
583 579
584 fw_destroy_instance(fw_priv); 580 fw_destroy_instance(fw_priv);
585
586out:
587 usermodehelper_read_unlock();
588 return retval; 581 return retval;
589} 582}
590 583
@@ -613,7 +606,14 @@ request_firmware(const struct firmware **firmware_p, const char *name,
613 if (ret <= 0) 606 if (ret <= 0)
614 return ret; 607 return ret;
615 608
616 ret = _request_firmware(*firmware_p, name, device, true, false); 609 ret = usermodehelper_read_trylock();
610 if (WARN_ON(ret)) {
611 dev_err(device, "firmware: %s will not be loaded\n", name);
612 } else {
613 ret = _request_firmware(*firmware_p, name, device, true, false,
614 firmware_loading_timeout());
615 usermodehelper_read_unlock();
616 }
617 if (ret) 617 if (ret)
618 _request_firmware_cleanup(firmware_p); 618 _request_firmware_cleanup(firmware_p);
619 619
@@ -648,6 +648,7 @@ static int request_firmware_work_func(void *arg)
648{ 648{
649 struct firmware_work *fw_work = arg; 649 struct firmware_work *fw_work = arg;
650 const struct firmware *fw; 650 const struct firmware *fw;
651 long timeout;
651 int ret; 652 int ret;
652 653
653 if (!arg) { 654 if (!arg) {
@@ -659,8 +660,16 @@ static int request_firmware_work_func(void *arg)
659 if (ret <= 0) 660 if (ret <= 0)
660 goto out; 661 goto out;
661 662
662 ret = _request_firmware(fw, fw_work->name, fw_work->device, 663 timeout = usermodehelper_read_lock_wait(firmware_loading_timeout());
663 fw_work->uevent, true); 664 if (timeout) {
665 ret = _request_firmware(fw, fw_work->name, fw_work->device,
666 fw_work->uevent, true, timeout);
667 usermodehelper_read_unlock();
668 } else {
669 dev_dbg(fw_work->device, "firmware: %s loading timed out\n",
670 fw_work->name);
671 ret = -EAGAIN;
672 }
664 if (ret) 673 if (ret)
665 _request_firmware_cleanup(&fw); 674 _request_firmware_cleanup(&fw);
666 675