aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorLarry Finger <Larry.Finger@lwfinger.net>2012-12-06 22:55:16 -0500
committerJohn W. Linville <linville@tuxdriver.com>2012-12-10 15:47:29 -0500
commit576d28a7c73013717311cfcb514dbcae27c82eeb (patch)
tree9d74550687b6fa12bb92a005aee042ba71500f6c
parent6f80f01483d122174d9aa7864a8ac4050ba6daaa (diff)
b43legacy: Fix firmware loading when driver is built into the kernel
Recent versions of udev cause synchronous firmware loading from the probe routine to fail because the request to user space times out. The original fix for b43legacy (commit a3ea2c7) moved the firmware load from the probe routine to a work queue, but it still used synchronous firmware loading. This method is OK when b43legacy is built as a module; however, it fails when the driver is compiled into the kernel. This version changes the code to load the initial firmware file using request_firmware_nowait(). A completion event is used to hold the work queue until that file is available. The remaining firmware files are read synchronously. Signed-off-by: Larry Finger <Larry.Finger@lwfinger.net> Cc: Stable <stable@vger.kernel.org> (V3.4+) Signed-off-by: John W. Linville <linville@tuxdriver.com>
-rw-r--r--drivers/net/wireless/b43legacy/b43legacy.h5
-rw-r--r--drivers/net/wireless/b43legacy/main.c37
2 files changed, 36 insertions, 6 deletions
diff --git a/drivers/net/wireless/b43legacy/b43legacy.h b/drivers/net/wireless/b43legacy/b43legacy.h
index a29da674e69d..482476fdb1f3 100644
--- a/drivers/net/wireless/b43legacy/b43legacy.h
+++ b/drivers/net/wireless/b43legacy/b43legacy.h
@@ -13,6 +13,7 @@
13 13
14#include <linux/ssb/ssb.h> 14#include <linux/ssb/ssb.h>
15#include <linux/ssb/ssb_driver_chipcommon.h> 15#include <linux/ssb/ssb_driver_chipcommon.h>
16#include <linux/completion.h>
16 17
17#include <net/mac80211.h> 18#include <net/mac80211.h>
18 19
@@ -733,6 +734,10 @@ struct b43legacy_wldev {
733 734
734 /* Firmware data */ 735 /* Firmware data */
735 struct b43legacy_firmware fw; 736 struct b43legacy_firmware fw;
737 const struct firmware *fwp; /* needed to pass fw pointer */
738
739 /* completion struct for firmware loading */
740 struct completion fw_load_complete;
736 741
737 /* Devicelist in struct b43legacy_wl (all 802.11 cores) */ 742 /* Devicelist in struct b43legacy_wl (all 802.11 cores) */
738 struct list_head list; 743 struct list_head list;
diff --git a/drivers/net/wireless/b43legacy/main.c b/drivers/net/wireless/b43legacy/main.c
index 18e208e3eca1..8c3f70e1a013 100644
--- a/drivers/net/wireless/b43legacy/main.c
+++ b/drivers/net/wireless/b43legacy/main.c
@@ -1513,9 +1513,17 @@ static void b43legacy_print_fw_helptext(struct b43legacy_wl *wl)
1513 "and download the correct firmware (version 3).\n"); 1513 "and download the correct firmware (version 3).\n");
1514} 1514}
1515 1515
1516static void b43legacy_fw_cb(const struct firmware *firmware, void *context)
1517{
1518 struct b43legacy_wldev *dev = context;
1519
1520 dev->fwp = firmware;
1521 complete(&dev->fw_load_complete);
1522}
1523
1516static int do_request_fw(struct b43legacy_wldev *dev, 1524static int do_request_fw(struct b43legacy_wldev *dev,
1517 const char *name, 1525 const char *name,
1518 const struct firmware **fw) 1526 const struct firmware **fw, bool async)
1519{ 1527{
1520 char path[sizeof(modparam_fwpostfix) + 32]; 1528 char path[sizeof(modparam_fwpostfix) + 32];
1521 struct b43legacy_fw_header *hdr; 1529 struct b43legacy_fw_header *hdr;
@@ -1528,7 +1536,24 @@ static int do_request_fw(struct b43legacy_wldev *dev,
1528 snprintf(path, ARRAY_SIZE(path), 1536 snprintf(path, ARRAY_SIZE(path),
1529 "b43legacy%s/%s.fw", 1537 "b43legacy%s/%s.fw",
1530 modparam_fwpostfix, name); 1538 modparam_fwpostfix, name);
1531 err = request_firmware(fw, path, dev->dev->dev); 1539 b43legacyinfo(dev->wl, "Loading firmware %s\n", path);
1540 if (async) {
1541 init_completion(&dev->fw_load_complete);
1542 err = request_firmware_nowait(THIS_MODULE, 1, path,
1543 dev->dev->dev, GFP_KERNEL,
1544 dev, b43legacy_fw_cb);
1545 if (err) {
1546 b43legacyerr(dev->wl, "Unable to load firmware\n");
1547 return err;
1548 }
1549 /* stall here until fw ready */
1550 wait_for_completion(&dev->fw_load_complete);
1551 if (!dev->fwp)
1552 err = -EINVAL;
1553 *fw = dev->fwp;
1554 } else {
1555 err = request_firmware(fw, path, dev->dev->dev);
1556 }
1532 if (err) { 1557 if (err) {
1533 b43legacyerr(dev->wl, "Firmware file \"%s\" not found " 1558 b43legacyerr(dev->wl, "Firmware file \"%s\" not found "
1534 "or load failed.\n", path); 1559 "or load failed.\n", path);
@@ -1580,7 +1605,7 @@ static void b43legacy_request_firmware(struct work_struct *work)
1580 filename = "ucode4"; 1605 filename = "ucode4";
1581 else 1606 else
1582 filename = "ucode5"; 1607 filename = "ucode5";
1583 err = do_request_fw(dev, filename, &fw->ucode); 1608 err = do_request_fw(dev, filename, &fw->ucode, true);
1584 if (err) 1609 if (err)
1585 goto err_load; 1610 goto err_load;
1586 } 1611 }
@@ -1589,7 +1614,7 @@ static void b43legacy_request_firmware(struct work_struct *work)
1589 filename = "pcm4"; 1614 filename = "pcm4";
1590 else 1615 else
1591 filename = "pcm5"; 1616 filename = "pcm5";
1592 err = do_request_fw(dev, filename, &fw->pcm); 1617 err = do_request_fw(dev, filename, &fw->pcm, false);
1593 if (err) 1618 if (err)
1594 goto err_load; 1619 goto err_load;
1595 } 1620 }
@@ -1607,7 +1632,7 @@ static void b43legacy_request_firmware(struct work_struct *work)
1607 default: 1632 default:
1608 goto err_no_initvals; 1633 goto err_no_initvals;
1609 } 1634 }
1610 err = do_request_fw(dev, filename, &fw->initvals); 1635 err = do_request_fw(dev, filename, &fw->initvals, false);
1611 if (err) 1636 if (err)
1612 goto err_load; 1637 goto err_load;
1613 } 1638 }
@@ -1627,7 +1652,7 @@ static void b43legacy_request_firmware(struct work_struct *work)
1627 default: 1652 default:
1628 goto err_no_initvals; 1653 goto err_no_initvals;
1629 } 1654 }
1630 err = do_request_fw(dev, filename, &fw->initvals_band); 1655 err = do_request_fw(dev, filename, &fw->initvals_band, false);
1631 if (err) 1656 if (err)
1632 goto err_load; 1657 goto err_load;
1633 } 1658 }