Skip to content

Commit

Permalink
b43: Load firmware from a work queue and not from the 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 b43 has such a structure, it must be changed.
As this driver loads more than 1 firmware file, changing to the asynchronous routine
request_firmware_nowait() would be complicated. In this implementation, the probe
routine starts a 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 a3ea2c7 commit 6b6fa58
Show file tree
Hide file tree
Showing 2 changed files with 35 additions and 27 deletions.
3 changes: 3 additions & 0 deletions drivers/net/wireless/b43/b43.h
Original file line number Diff line number Diff line change
Expand Up @@ -932,6 +932,9 @@ struct b43_wl {
/* Flag that implement the queues stopping. */
bool tx_queue_stopped[B43_QOS_QUEUE_NUM];

/* firmware loading work */
struct work_struct firmware_load;

/* The device LEDs. */
struct b43_leds leds;

Expand Down
59 changes: 32 additions & 27 deletions drivers/net/wireless/b43/main.c
Original file line number Diff line number Diff line change
Expand Up @@ -2390,32 +2390,38 @@ static int b43_try_request_fw(struct b43_request_fw_context *ctx)
return err;
}

static int b43_request_firmware(struct b43_wldev *dev)
static int b43_one_core_attach(struct b43_bus_dev *dev, struct b43_wl *wl);
static void b43_one_core_detach(struct b43_bus_dev *dev);

static void b43_request_firmware(struct work_struct *work)
{
struct b43_wl *wl = container_of(work,
struct b43_wl, firmware_load);
struct b43_wldev *dev = wl->current_dev;
struct b43_request_fw_context *ctx;
unsigned int i;
int err;
const char *errmsg;

ctx = kzalloc(sizeof(*ctx), GFP_KERNEL);
if (!ctx)
return -ENOMEM;
return;
ctx->dev = dev;

ctx->req_type = B43_FWTYPE_PROPRIETARY;
err = b43_try_request_fw(ctx);
if (!err)
goto out; /* Successfully loaded it. */
err = ctx->fatal_failure;
if (err)
goto start_ieee80211; /* Successfully loaded it. */
/* Was fw version known? */
if (ctx->fatal_failure)
goto out;

/* proprietary fw not found, try open source */
ctx->req_type = B43_FWTYPE_OPENSOURCE;
err = b43_try_request_fw(ctx);
if (!err)
goto out; /* Successfully loaded it. */
err = ctx->fatal_failure;
if (err)
goto start_ieee80211; /* Successfully loaded it. */
if(ctx->fatal_failure)
goto out;

/* Could not find a usable firmware. Print the errors. */
Expand All @@ -2425,11 +2431,20 @@ static int b43_request_firmware(struct b43_wldev *dev)
b43err(dev->wl, errmsg);
}
b43_print_fw_helptext(dev->wl, 1);
err = -ENOENT;
goto out;

start_ieee80211:
err = ieee80211_register_hw(wl->hw);
if (err)
goto err_one_core_detach;
b43_leds_register(wl->current_dev);
goto out;

err_one_core_detach:
b43_one_core_detach(dev->dev);

out:
kfree(ctx);
return err;
}

static int b43_upload_microcode(struct b43_wldev *dev)
Expand Down Expand Up @@ -3023,9 +3038,6 @@ static int b43_chip_init(struct b43_wldev *dev)
macctl |= B43_MACCTL_INFRA;
b43_write32(dev, B43_MMIO_MACCTL, macctl);

err = b43_request_firmware(dev);
if (err)
goto out;
err = b43_upload_microcode(dev);
if (err)
goto out; /* firmware is released later */
Expand Down Expand Up @@ -4155,6 +4167,7 @@ static struct b43_wldev * b43_wireless_core_stop(struct b43_wldev *dev)
mutex_unlock(&wl->mutex);
cancel_delayed_work_sync(&dev->periodic_work);
cancel_work_sync(&wl->tx_work);
cancel_work_sync(&wl->firmware_load);
mutex_lock(&wl->mutex);
dev = wl->current_dev;
if (!dev || b43_status(dev) < B43_STAT_STARTED) {
Expand Down Expand Up @@ -5314,16 +5327,13 @@ static int b43_bcma_probe(struct bcma_device *core)
if (err)
goto bcma_err_wireless_exit;

err = ieee80211_register_hw(wl->hw);
if (err)
goto bcma_err_one_core_detach;
b43_leds_register(wl->current_dev);
/* setup and start work to load firmware */
INIT_WORK(&wl->firmware_load, b43_request_firmware);
schedule_work(&wl->firmware_load);

bcma_out:
return err;

bcma_err_one_core_detach:
b43_one_core_detach(dev);
bcma_err_wireless_exit:
ieee80211_free_hw(wl->hw);
return err;
Expand Down Expand Up @@ -5390,18 +5400,13 @@ int b43_ssb_probe(struct ssb_device *sdev, const struct ssb_device_id *id)
if (err)
goto err_wireless_exit;

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

out:
return err;

err_one_core_detach:
b43_one_core_detach(dev);
err_wireless_exit:
if (first)
b43_wireless_exit(dev, wl);
Expand Down

0 comments on commit 6b6fa58

Please sign in to comment.