diff options
author | Larry Finger <Larry.Finger@lwfinger.net> | 2012-03-08 23:27:46 -0500 |
---|---|---|
committer | John W. Linville <linville@tuxdriver.com> | 2012-03-13 14:54:16 -0400 |
commit | 6b6fa5868eec26bdc6a83543cebb8cf832a2645a (patch) | |
tree | 71f845d127ec1ff121b8a336ead86c6a6ac1c1bb | |
parent | a3ea2c76b193be5794e0de6aff66e14c21b904f8 (diff) |
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>
-rw-r--r-- | drivers/net/wireless/b43/b43.h | 3 | ||||
-rw-r--r-- | drivers/net/wireless/b43/main.c | 59 |
2 files changed, 35 insertions, 27 deletions
diff --git a/drivers/net/wireless/b43/b43.h b/drivers/net/wireless/b43/b43.h index 835462dc1206..67c13af6f206 100644 --- a/drivers/net/wireless/b43/b43.h +++ b/drivers/net/wireless/b43/b43.h | |||
@@ -932,6 +932,9 @@ struct b43_wl { | |||
932 | /* Flag that implement the queues stopping. */ | 932 | /* Flag that implement the queues stopping. */ |
933 | bool tx_queue_stopped[B43_QOS_QUEUE_NUM]; | 933 | bool tx_queue_stopped[B43_QOS_QUEUE_NUM]; |
934 | 934 | ||
935 | /* firmware loading work */ | ||
936 | struct work_struct firmware_load; | ||
937 | |||
935 | /* The device LEDs. */ | 938 | /* The device LEDs. */ |
936 | struct b43_leds leds; | 939 | struct b43_leds leds; |
937 | 940 | ||
diff --git a/drivers/net/wireless/b43/main.c b/drivers/net/wireless/b43/main.c index 1d633f3b3274..c79e6638c88d 100644 --- a/drivers/net/wireless/b43/main.c +++ b/drivers/net/wireless/b43/main.c | |||
@@ -2390,8 +2390,14 @@ error: | |||
2390 | return err; | 2390 | return err; |
2391 | } | 2391 | } |
2392 | 2392 | ||
2393 | static int b43_request_firmware(struct b43_wldev *dev) | 2393 | static int b43_one_core_attach(struct b43_bus_dev *dev, struct b43_wl *wl); |
2394 | static void b43_one_core_detach(struct b43_bus_dev *dev); | ||
2395 | |||
2396 | static void b43_request_firmware(struct work_struct *work) | ||
2394 | { | 2397 | { |
2398 | struct b43_wl *wl = container_of(work, | ||
2399 | struct b43_wl, firmware_load); | ||
2400 | struct b43_wldev *dev = wl->current_dev; | ||
2395 | struct b43_request_fw_context *ctx; | 2401 | struct b43_request_fw_context *ctx; |
2396 | unsigned int i; | 2402 | unsigned int i; |
2397 | int err; | 2403 | int err; |
@@ -2399,23 +2405,23 @@ static int b43_request_firmware(struct b43_wldev *dev) | |||
2399 | 2405 | ||
2400 | ctx = kzalloc(sizeof(*ctx), GFP_KERNEL); | 2406 | ctx = kzalloc(sizeof(*ctx), GFP_KERNEL); |
2401 | if (!ctx) | 2407 | if (!ctx) |
2402 | return -ENOMEM; | 2408 | return; |
2403 | ctx->dev = dev; | 2409 | ctx->dev = dev; |
2404 | 2410 | ||
2405 | ctx->req_type = B43_FWTYPE_PROPRIETARY; | 2411 | ctx->req_type = B43_FWTYPE_PROPRIETARY; |
2406 | err = b43_try_request_fw(ctx); | 2412 | err = b43_try_request_fw(ctx); |
2407 | if (!err) | 2413 | if (!err) |
2408 | goto out; /* Successfully loaded it. */ | 2414 | goto start_ieee80211; /* Successfully loaded it. */ |
2409 | err = ctx->fatal_failure; | 2415 | /* Was fw version known? */ |
2410 | if (err) | 2416 | if (ctx->fatal_failure) |
2411 | goto out; | 2417 | goto out; |
2412 | 2418 | ||
2419 | /* proprietary fw not found, try open source */ | ||
2413 | ctx->req_type = B43_FWTYPE_OPENSOURCE; | 2420 | ctx->req_type = B43_FWTYPE_OPENSOURCE; |
2414 | err = b43_try_request_fw(ctx); | 2421 | err = b43_try_request_fw(ctx); |
2415 | if (!err) | 2422 | if (!err) |
2416 | goto out; /* Successfully loaded it. */ | 2423 | goto start_ieee80211; /* Successfully loaded it. */ |
2417 | err = ctx->fatal_failure; | 2424 | if(ctx->fatal_failure) |
2418 | if (err) | ||
2419 | goto out; | 2425 | goto out; |
2420 | 2426 | ||
2421 | /* Could not find a usable firmware. Print the errors. */ | 2427 | /* Could not find a usable firmware. Print the errors. */ |
@@ -2425,11 +2431,20 @@ static int b43_request_firmware(struct b43_wldev *dev) | |||
2425 | b43err(dev->wl, errmsg); | 2431 | b43err(dev->wl, errmsg); |
2426 | } | 2432 | } |
2427 | b43_print_fw_helptext(dev->wl, 1); | 2433 | b43_print_fw_helptext(dev->wl, 1); |
2428 | err = -ENOENT; | 2434 | goto out; |
2435 | |||
2436 | start_ieee80211: | ||
2437 | err = ieee80211_register_hw(wl->hw); | ||
2438 | if (err) | ||
2439 | goto err_one_core_detach; | ||
2440 | b43_leds_register(wl->current_dev); | ||
2441 | goto out; | ||
2442 | |||
2443 | err_one_core_detach: | ||
2444 | b43_one_core_detach(dev->dev); | ||
2429 | 2445 | ||
2430 | out: | 2446 | out: |
2431 | kfree(ctx); | 2447 | kfree(ctx); |
2432 | return err; | ||
2433 | } | 2448 | } |
2434 | 2449 | ||
2435 | static int b43_upload_microcode(struct b43_wldev *dev) | 2450 | static int b43_upload_microcode(struct b43_wldev *dev) |
@@ -3023,9 +3038,6 @@ static int b43_chip_init(struct b43_wldev *dev) | |||
3023 | macctl |= B43_MACCTL_INFRA; | 3038 | macctl |= B43_MACCTL_INFRA; |
3024 | b43_write32(dev, B43_MMIO_MACCTL, macctl); | 3039 | b43_write32(dev, B43_MMIO_MACCTL, macctl); |
3025 | 3040 | ||
3026 | err = b43_request_firmware(dev); | ||
3027 | if (err) | ||
3028 | goto out; | ||
3029 | err = b43_upload_microcode(dev); | 3041 | err = b43_upload_microcode(dev); |
3030 | if (err) | 3042 | if (err) |
3031 | goto out; /* firmware is released later */ | 3043 | goto out; /* firmware is released later */ |
@@ -4155,6 +4167,7 @@ redo: | |||
4155 | mutex_unlock(&wl->mutex); | 4167 | mutex_unlock(&wl->mutex); |
4156 | cancel_delayed_work_sync(&dev->periodic_work); | 4168 | cancel_delayed_work_sync(&dev->periodic_work); |
4157 | cancel_work_sync(&wl->tx_work); | 4169 | cancel_work_sync(&wl->tx_work); |
4170 | cancel_work_sync(&wl->firmware_load); | ||
4158 | mutex_lock(&wl->mutex); | 4171 | mutex_lock(&wl->mutex); |
4159 | dev = wl->current_dev; | 4172 | dev = wl->current_dev; |
4160 | if (!dev || b43_status(dev) < B43_STAT_STARTED) { | 4173 | if (!dev || b43_status(dev) < B43_STAT_STARTED) { |
@@ -5314,16 +5327,13 @@ static int b43_bcma_probe(struct bcma_device *core) | |||
5314 | if (err) | 5327 | if (err) |
5315 | goto bcma_err_wireless_exit; | 5328 | goto bcma_err_wireless_exit; |
5316 | 5329 | ||
5317 | err = ieee80211_register_hw(wl->hw); | 5330 | /* setup and start work to load firmware */ |
5318 | if (err) | 5331 | INIT_WORK(&wl->firmware_load, b43_request_firmware); |
5319 | goto bcma_err_one_core_detach; | 5332 | schedule_work(&wl->firmware_load); |
5320 | b43_leds_register(wl->current_dev); | ||
5321 | 5333 | ||
5322 | bcma_out: | 5334 | bcma_out: |
5323 | return err; | 5335 | return err; |
5324 | 5336 | ||
5325 | bcma_err_one_core_detach: | ||
5326 | b43_one_core_detach(dev); | ||
5327 | bcma_err_wireless_exit: | 5337 | bcma_err_wireless_exit: |
5328 | ieee80211_free_hw(wl->hw); | 5338 | ieee80211_free_hw(wl->hw); |
5329 | return err; | 5339 | return err; |
@@ -5390,18 +5400,13 @@ int b43_ssb_probe(struct ssb_device *sdev, const struct ssb_device_id *id) | |||
5390 | if (err) | 5400 | if (err) |
5391 | goto err_wireless_exit; | 5401 | goto err_wireless_exit; |
5392 | 5402 | ||
5393 | if (first) { | 5403 | /* setup and start work to load firmware */ |
5394 | err = ieee80211_register_hw(wl->hw); | 5404 | INIT_WORK(&wl->firmware_load, b43_request_firmware); |
5395 | if (err) | 5405 | schedule_work(&wl->firmware_load); |
5396 | goto err_one_core_detach; | ||
5397 | b43_leds_register(wl->current_dev); | ||
5398 | } | ||
5399 | 5406 | ||
5400 | out: | 5407 | out: |
5401 | return err; | 5408 | return err; |
5402 | 5409 | ||
5403 | err_one_core_detach: | ||
5404 | b43_one_core_detach(dev); | ||
5405 | err_wireless_exit: | 5410 | err_wireless_exit: |
5406 | if (first) | 5411 | if (first) |
5407 | b43_wireless_exit(dev, wl); | 5412 | b43_wireless_exit(dev, wl); |