Skip to content

Commit

Permalink
b43legacy: Load firmware from work queue instead of from probe routine
Browse files Browse the repository at this point in the history
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: Larry Finger <Larry.Finger@lwfinger.net>
Signed-off-by: John W. Linville <linville@tuxdriver.com>
  • Loading branch information
lwfinger authored and linvjw committed Mar 13, 2012
1 parent 843dc66 commit a3ea2c7
Show file tree
Hide file tree
Showing 2 changed files with 23 additions and 13 deletions.
3 changes: 3 additions & 0 deletions drivers/net/wireless/b43legacy/b43legacy.h
Original file line number Diff line number Diff line change
Expand Up @@ -581,6 +581,9 @@ struct b43legacy_wl {
struct mutex mutex; /* locks wireless core state */
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)
* at a time. General information about this interface follows.
*/
Expand Down
33 changes: 20 additions & 13 deletions drivers/net/wireless/b43legacy/main.c
Original file line number Diff line number Diff line change
Expand Up @@ -1557,8 +1557,15 @@ static int do_request_fw(struct b43legacy_wldev *dev,
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;
const u8 rev = dev->dev->id.revision;
const char *filename;
Expand Down Expand Up @@ -1624,8 +1631,14 @@ static int b43legacy_request_firmware(struct b43legacy_wldev *dev)
if (err)
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:
b43legacy_print_fw_helptext(dev->wl);
Expand All @@ -1639,7 +1652,7 @@ static int b43legacy_request_firmware(struct b43legacy_wldev *dev)

error:
b43legacy_release_firmware(dev);
return err;
return;
}

static int b43legacy_upload_microcode(struct b43legacy_wldev *dev)
Expand Down Expand Up @@ -2153,9 +2166,6 @@ static int b43legacy_chip_init(struct b43legacy_wldev *dev)
macctl |= B43legacy_MACCTL_INFRA;
b43legacy_write32(dev, B43legacy_MMIO_MACCTL, macctl);

err = b43legacy_request_firmware(dev);
if (err)
goto out;
err = b43legacy_upload_microcode(dev);
if (err)
goto out; /* firmware is released later */
Expand Down Expand Up @@ -3860,17 +3870,13 @@ static int b43legacy_probe(struct ssb_device *dev,
if (err)
goto err_wireless_exit;

if (first) {
err = ieee80211_register_hw(wl->hw);
if (err)
goto err_one_core_detach;
}
/* setup and start work to load firmware */
INIT_WORK(&wl->firmware_load, b43legacy_request_firmware);
schedule_work(&wl->firmware_load);

out:
return err;

err_one_core_detach:
b43legacy_one_core_detach(dev);
err_wireless_exit:
if (first)
b43legacy_wireless_exit(dev, wl);
Expand All @@ -3885,6 +3891,7 @@ static void b43legacy_remove(struct ssb_device *dev)
/* We must cancel any work here before unregistering from ieee80211,
* as the ieee80211 unreg will destroy the workqueue. */
cancel_work_sync(&wldev->restart_work);
cancel_work_sync(&wl->firmware_load);

B43legacy_WARN_ON(!wl);
if (wl->current_dev == wldev)
Expand Down

0 comments on commit a3ea2c7

Please sign in to comment.