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: Larry Finger <Larry.Finger@lwfinger.net> Signed-off-by: John W. Linville <linville@tuxdriver.com>
This commit is contained in:
parent
a3ea2c76b1
commit
6b6fa5868e
@ -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 @@ error:
|
|||||||
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)
|
|||||||
|
|
||||||
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)
|
|||||||
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)
|
|||||||
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 @@ redo:
|
|||||||
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)
|
|||||||
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)
|
|||||||
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);
|
||||||
|
Loading…
Reference in New Issue
Block a user