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

b43: Load firmware from a work queue and not from the probe routine

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: default avatarLarry Finger <Larry.Finger@lwfinger.net>
Signed-off-by: default avatarJohn W. Linville <linville@tuxdriver.com>
parent a3ea2c76
...@@ -932,6 +932,9 @@ struct b43_wl { ...@@ -932,6 +932,9 @@ struct b43_wl {
/* Flag that implement the queues stopping. */ /* Flag that implement the queues stopping. */
bool tx_queue_stopped[B43_QOS_QUEUE_NUM]; bool tx_queue_stopped[B43_QOS_QUEUE_NUM];
/* firmware loading work */
struct work_struct firmware_load;
/* The device LEDs. */ /* The device LEDs. */
struct b43_leds leds; struct b43_leds leds;
......
...@@ -2390,8 +2390,14 @@ static int b43_try_request_fw(struct b43_request_fw_context *ctx) ...@@ -2390,8 +2390,14 @@ static int b43_try_request_fw(struct b43_request_fw_context *ctx)
return err; 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; struct b43_request_fw_context *ctx;
unsigned int i; unsigned int i;
int err; int err;
...@@ -2399,23 +2405,23 @@ static int b43_request_firmware(struct b43_wldev *dev) ...@@ -2399,23 +2405,23 @@ static int b43_request_firmware(struct b43_wldev *dev)
ctx = kzalloc(sizeof(*ctx), GFP_KERNEL); ctx = kzalloc(sizeof(*ctx), GFP_KERNEL);
if (!ctx) if (!ctx)
return -ENOMEM; return;
ctx->dev = dev; ctx->dev = dev;
ctx->req_type = B43_FWTYPE_PROPRIETARY; ctx->req_type = B43_FWTYPE_PROPRIETARY;
err = b43_try_request_fw(ctx); err = b43_try_request_fw(ctx);
if (!err) if (!err)
goto out; /* Successfully loaded it. */ goto start_ieee80211; /* Successfully loaded it. */
err = ctx->fatal_failure; /* Was fw version known? */
if (err) if (ctx->fatal_failure)
goto out; goto out;
/* proprietary fw not found, try open source */
ctx->req_type = B43_FWTYPE_OPENSOURCE; ctx->req_type = B43_FWTYPE_OPENSOURCE;
err = b43_try_request_fw(ctx); err = b43_try_request_fw(ctx);
if (!err) if (!err)
goto out; /* Successfully loaded it. */ goto start_ieee80211; /* Successfully loaded it. */
err = ctx->fatal_failure; if(ctx->fatal_failure)
if (err)
goto out; goto out;
/* Could not find a usable firmware. Print the errors. */ /* Could not find a usable firmware. Print the errors. */
...@@ -2425,11 +2431,20 @@ static int b43_request_firmware(struct b43_wldev *dev) ...@@ -2425,11 +2431,20 @@ static int b43_request_firmware(struct b43_wldev *dev)
b43err(dev->wl, errmsg); b43err(dev->wl, errmsg);
} }
b43_print_fw_helptext(dev->wl, 1); 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: out:
kfree(ctx); kfree(ctx);
return err;
} }
static int b43_upload_microcode(struct b43_wldev *dev) static int b43_upload_microcode(struct b43_wldev *dev)
...@@ -3023,9 +3038,6 @@ static int b43_chip_init(struct b43_wldev *dev) ...@@ -3023,9 +3038,6 @@ static int b43_chip_init(struct b43_wldev *dev)
macctl |= B43_MACCTL_INFRA; macctl |= B43_MACCTL_INFRA;
b43_write32(dev, B43_MMIO_MACCTL, macctl); b43_write32(dev, B43_MMIO_MACCTL, macctl);
err = b43_request_firmware(dev);
if (err)
goto out;
err = b43_upload_microcode(dev); err = b43_upload_microcode(dev);
if (err) if (err)
goto out; /* firmware is released later */ goto out; /* firmware is released later */
...@@ -4155,6 +4167,7 @@ static struct b43_wldev * b43_wireless_core_stop(struct b43_wldev *dev) ...@@ -4155,6 +4167,7 @@ static struct b43_wldev * b43_wireless_core_stop(struct b43_wldev *dev)
mutex_unlock(&wl->mutex); mutex_unlock(&wl->mutex);
cancel_delayed_work_sync(&dev->periodic_work); cancel_delayed_work_sync(&dev->periodic_work);
cancel_work_sync(&wl->tx_work); cancel_work_sync(&wl->tx_work);
cancel_work_sync(&wl->firmware_load);
mutex_lock(&wl->mutex); mutex_lock(&wl->mutex);
dev = wl->current_dev; dev = wl->current_dev;
if (!dev || b43_status(dev) < B43_STAT_STARTED) { if (!dev || b43_status(dev) < B43_STAT_STARTED) {
...@@ -5314,16 +5327,13 @@ static int b43_bcma_probe(struct bcma_device *core) ...@@ -5314,16 +5327,13 @@ static int b43_bcma_probe(struct bcma_device *core)
if (err) if (err)
goto bcma_err_wireless_exit; goto bcma_err_wireless_exit;
err = ieee80211_register_hw(wl->hw); /* setup and start work to load firmware */
if (err) INIT_WORK(&wl->firmware_load, b43_request_firmware);
goto bcma_err_one_core_detach; schedule_work(&wl->firmware_load);
b43_leds_register(wl->current_dev);
bcma_out: bcma_out:
return err; return err;
bcma_err_one_core_detach:
b43_one_core_detach(dev);
bcma_err_wireless_exit: bcma_err_wireless_exit:
ieee80211_free_hw(wl->hw); ieee80211_free_hw(wl->hw);
return err; return err;
...@@ -5390,18 +5400,13 @@ int b43_ssb_probe(struct ssb_device *sdev, const struct ssb_device_id *id) ...@@ -5390,18 +5400,13 @@ int b43_ssb_probe(struct ssb_device *sdev, const struct ssb_device_id *id)
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, b43_request_firmware);
if (err) schedule_work(&wl->firmware_load);
goto err_one_core_detach;
b43_leds_register(wl->current_dev);
}
out: out:
return err; return err;
err_one_core_detach:
b43_one_core_detach(dev);
err_wireless_exit: err_wireless_exit:
if (first) if (first)
b43_wireless_exit(dev, wl); b43_wireless_exit(dev, wl);
......
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