Commit a3ea2c76 authored by Larry Finger's avatar Larry Finger Committed by John W. Linville

b43legacy: Load firmware from work queue instead of from probe routine

Recent changes in udev are causing problems for drivers that load firmware
from the probe routine. As b43legacy has such a structure, it must be changed.
As this driver loads 3 or 4 firmware files, changing to the asynchronous routine
request_firmware_nowait() would be complicated. In this implementation, the probe
routine starts a work queue that calls the firmware loading routines.
Signed-off-by: default avatarLarry Finger <Larry.Finger@lwfinger.net>
Signed-off-by: default avatarJohn W. Linville <linville@tuxdriver.com>
parent 843dc664
...@@ -581,6 +581,9 @@ struct b43legacy_wl { ...@@ -581,6 +581,9 @@ struct b43legacy_wl {
struct mutex mutex; /* locks wireless core state */ struct mutex mutex; /* locks wireless core state */
spinlock_t leds_lock; /* lock for leds */ spinlock_t leds_lock; /* lock for leds */
/* firmware loading work */
struct work_struct firmware_load;
/* We can only have one operating interface (802.11 core) /* We can only have one operating interface (802.11 core)
* at a time. General information about this interface follows. * at a time. General information about this interface follows.
*/ */
......
...@@ -1557,8 +1557,15 @@ static int do_request_fw(struct b43legacy_wldev *dev, ...@@ -1557,8 +1557,15 @@ static int do_request_fw(struct b43legacy_wldev *dev,
return -EPROTO; return -EPROTO;
} }
static int b43legacy_request_firmware(struct b43legacy_wldev *dev) static int b43legacy_one_core_attach(struct ssb_device *dev,
struct b43legacy_wl *wl);
static void b43legacy_one_core_detach(struct ssb_device *dev);
static void b43legacy_request_firmware(struct work_struct *work)
{ {
struct b43legacy_wl *wl = container_of(work,
struct b43legacy_wl, firmware_load);
struct b43legacy_wldev *dev = wl->current_dev;
struct b43legacy_firmware *fw = &dev->fw; struct b43legacy_firmware *fw = &dev->fw;
const u8 rev = dev->dev->id.revision; const u8 rev = dev->dev->id.revision;
const char *filename; const char *filename;
...@@ -1624,8 +1631,14 @@ static int b43legacy_request_firmware(struct b43legacy_wldev *dev) ...@@ -1624,8 +1631,14 @@ static int b43legacy_request_firmware(struct b43legacy_wldev *dev)
if (err) if (err)
goto err_load; goto err_load;
} }
err = ieee80211_register_hw(wl->hw);
if (err)
goto err_one_core_detach;
return;
return 0; err_one_core_detach:
b43legacy_one_core_detach(dev->dev);
goto error;
err_load: err_load:
b43legacy_print_fw_helptext(dev->wl); b43legacy_print_fw_helptext(dev->wl);
...@@ -1639,7 +1652,7 @@ static int b43legacy_request_firmware(struct b43legacy_wldev *dev) ...@@ -1639,7 +1652,7 @@ static int b43legacy_request_firmware(struct b43legacy_wldev *dev)
error: error:
b43legacy_release_firmware(dev); b43legacy_release_firmware(dev);
return err; return;
} }
static int b43legacy_upload_microcode(struct b43legacy_wldev *dev) static int b43legacy_upload_microcode(struct b43legacy_wldev *dev)
...@@ -2153,9 +2166,6 @@ static int b43legacy_chip_init(struct b43legacy_wldev *dev) ...@@ -2153,9 +2166,6 @@ static int b43legacy_chip_init(struct b43legacy_wldev *dev)
macctl |= B43legacy_MACCTL_INFRA; macctl |= B43legacy_MACCTL_INFRA;
b43legacy_write32(dev, B43legacy_MMIO_MACCTL, macctl); b43legacy_write32(dev, B43legacy_MMIO_MACCTL, macctl);
err = b43legacy_request_firmware(dev);
if (err)
goto out;
err = b43legacy_upload_microcode(dev); err = b43legacy_upload_microcode(dev);
if (err) if (err)
goto out; /* firmware is released later */ goto out; /* firmware is released later */
...@@ -3860,17 +3870,13 @@ static int b43legacy_probe(struct ssb_device *dev, ...@@ -3860,17 +3870,13 @@ static int b43legacy_probe(struct ssb_device *dev,
if (err) if (err)
goto err_wireless_exit; goto err_wireless_exit;
if (first) { /* setup and start work to load firmware */
err = ieee80211_register_hw(wl->hw); INIT_WORK(&wl->firmware_load, b43legacy_request_firmware);
if (err) schedule_work(&wl->firmware_load);
goto err_one_core_detach;
}
out: out:
return err; return err;
err_one_core_detach:
b43legacy_one_core_detach(dev);
err_wireless_exit: err_wireless_exit:
if (first) if (first)
b43legacy_wireless_exit(dev, wl); b43legacy_wireless_exit(dev, wl);
...@@ -3885,6 +3891,7 @@ static void b43legacy_remove(struct ssb_device *dev) ...@@ -3885,6 +3891,7 @@ static void b43legacy_remove(struct ssb_device *dev)
/* We must cancel any work here before unregistering from ieee80211, /* We must cancel any work here before unregistering from ieee80211,
* as the ieee80211 unreg will destroy the workqueue. */ * as the ieee80211 unreg will destroy the workqueue. */
cancel_work_sync(&wldev->restart_work); cancel_work_sync(&wldev->restart_work);
cancel_work_sync(&wl->firmware_load);
B43legacy_WARN_ON(!wl); B43legacy_WARN_ON(!wl);
if (wl->current_dev == wldev) if (wl->current_dev == wldev)
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment