aboutsummaryrefslogtreecommitdiffstats
path: root/drivers/net/wireless
diff options
context:
space:
mode:
authorJohannes Berg <johannes.berg@intel.com>2012-07-17 11:12:29 -0400
committerJohn W. Linville <linville@tuxdriver.com>2012-07-17 15:34:35 -0400
commit097b0e1bf18a00195cd89bb13565ddbc9b0df942 (patch)
tree0095ee2f3b924038be51545f62ea502a724a18e1 /drivers/net/wireless
parentd369f7b2b257ad6369b72d39e2f989833754a9ce (diff)
b43: fix crash with OpenFWWF
b43 with open firmware crashes mac80211 because it changes the number of queues at runtime which, while it was never really supported, now crashes mac80211 due to the new hardware queue logic. Fix this by detecting open vs. proprietary fw earlier and registering with mac80211 with the right number of queues. Tested-by: Stefan Lippers-Hollmann <s.l-h@gmx.de> Signed-off-by: Johannes Berg <johannes.berg@intel.com> Cc: stable@vger.kernel.org (depends on commit a6f38ac3) Signed-off-by: John W. Linville <linville@tuxdriver.com>
Diffstat (limited to 'drivers/net/wireless')
-rw-r--r--drivers/net/wireless/b43/b43.h7
-rw-r--r--drivers/net/wireless/b43/main.c32
2 files changed, 10 insertions, 29 deletions
diff --git a/drivers/net/wireless/b43/b43.h b/drivers/net/wireless/b43/b43.h
index c06b6cb5c91e..7c899fc7ddd0 100644
--- a/drivers/net/wireless/b43/b43.h
+++ b/drivers/net/wireless/b43/b43.h
@@ -870,13 +870,6 @@ struct b43_wl {
870 * handler, only. This basically is just the IRQ mask register. */ 870 * handler, only. This basically is just the IRQ mask register. */
871 spinlock_t hardirq_lock; 871 spinlock_t hardirq_lock;
872 872
873 /* The number of queues that were registered with the mac80211 subsystem
874 * initially. This is a backup copy of hw->queues in case hw->queues has
875 * to be dynamically lowered at runtime (Firmware does not support QoS).
876 * hw->queues has to be restored to the original value before unregistering
877 * from the mac80211 subsystem. */
878 u16 mac80211_initially_registered_queues;
879
880 /* Set this if we call ieee80211_register_hw() and check if we call 873 /* Set this if we call ieee80211_register_hw() and check if we call
881 * ieee80211_unregister_hw(). */ 874 * ieee80211_unregister_hw(). */
882 bool hw_registred; 875 bool hw_registred;
diff --git a/drivers/net/wireless/b43/main.c b/drivers/net/wireless/b43/main.c
index acd03a4f9730..3e5cd8d7d01f 100644
--- a/drivers/net/wireless/b43/main.c
+++ b/drivers/net/wireless/b43/main.c
@@ -2359,6 +2359,8 @@ static int b43_try_request_fw(struct b43_request_fw_context *ctx)
2359 if (err) 2359 if (err)
2360 goto err_load; 2360 goto err_load;
2361 2361
2362 fw->opensource = (ctx->req_type == B43_FWTYPE_OPENSOURCE);
2363
2362 return 0; 2364 return 0;
2363 2365
2364err_no_ucode: 2366err_no_ucode:
@@ -2434,6 +2436,10 @@ static void b43_request_firmware(struct work_struct *work)
2434 goto out; 2436 goto out;
2435 2437
2436start_ieee80211: 2438start_ieee80211:
2439 wl->hw->queues = B43_QOS_QUEUE_NUM;
2440 if (!modparam_qos || dev->fw.opensource)
2441 wl->hw->queues = 1;
2442
2437 err = ieee80211_register_hw(wl->hw); 2443 err = ieee80211_register_hw(wl->hw);
2438 if (err) 2444 if (err)
2439 goto err_one_core_detach; 2445 goto err_one_core_detach;
@@ -2537,11 +2543,9 @@ static int b43_upload_microcode(struct b43_wldev *dev)
2537 dev->fw.hdr_format = B43_FW_HDR_410; 2543 dev->fw.hdr_format = B43_FW_HDR_410;
2538 else 2544 else
2539 dev->fw.hdr_format = B43_FW_HDR_351; 2545 dev->fw.hdr_format = B43_FW_HDR_351;
2540 dev->fw.opensource = (fwdate == 0xFFFF); 2546 WARN_ON(dev->fw.opensource != (fwdate == 0xFFFF));
2541 2547
2542 /* Default to use-all-queues. */ 2548 dev->qos_enabled = dev->wl->hw->queues > 1;
2543 dev->wl->hw->queues = dev->wl->mac80211_initially_registered_queues;
2544 dev->qos_enabled = !!modparam_qos;
2545 /* Default to firmware/hardware crypto acceleration. */ 2549 /* Default to firmware/hardware crypto acceleration. */
2546 dev->hwcrypto_enabled = true; 2550 dev->hwcrypto_enabled = true;
2547 2551
@@ -2559,14 +2563,8 @@ static int b43_upload_microcode(struct b43_wldev *dev)
2559 /* Disable hardware crypto and fall back to software crypto. */ 2563 /* Disable hardware crypto and fall back to software crypto. */
2560 dev->hwcrypto_enabled = false; 2564 dev->hwcrypto_enabled = false;
2561 } 2565 }
2562 if (!(fwcapa & B43_FWCAPA_QOS)) { 2566 /* adding QoS support should use an offline discovery mechanism */
2563 b43info(dev->wl, "QoS not supported by firmware\n"); 2567 WARN(fwcapa & B43_FWCAPA_QOS, "QoS in OpenFW not supported\n");
2564 /* Disable QoS. Tweak hw->queues to 1. It will be restored before
2565 * ieee80211_unregister to make sure the networking core can
2566 * properly free possible resources. */
2567 dev->wl->hw->queues = 1;
2568 dev->qos_enabled = false;
2569 }
2570 } else { 2568 } else {
2571 b43info(dev->wl, "Loading firmware version %u.%u " 2569 b43info(dev->wl, "Loading firmware version %u.%u "
2572 "(20%.2i-%.2i-%.2i %.2i:%.2i:%.2i)\n", 2570 "(20%.2i-%.2i-%.2i %.2i:%.2i:%.2i)\n",
@@ -5298,8 +5296,6 @@ static struct b43_wl *b43_wireless_init(struct b43_bus_dev *dev)
5298 5296
5299 hw->wiphy->flags |= WIPHY_FLAG_IBSS_RSN; 5297 hw->wiphy->flags |= WIPHY_FLAG_IBSS_RSN;
5300 5298
5301 hw->queues = modparam_qos ? B43_QOS_QUEUE_NUM : 1;
5302 wl->mac80211_initially_registered_queues = hw->queues;
5303 wl->hw_registred = false; 5299 wl->hw_registred = false;
5304 hw->max_rates = 2; 5300 hw->max_rates = 2;
5305 SET_IEEE80211_DEV(hw, dev->dev); 5301 SET_IEEE80211_DEV(hw, dev->dev);
@@ -5374,10 +5370,6 @@ static void b43_bcma_remove(struct bcma_device *core)
5374 5370
5375 B43_WARN_ON(!wl); 5371 B43_WARN_ON(!wl);
5376 if (wl->current_dev == wldev && wl->hw_registred) { 5372 if (wl->current_dev == wldev && wl->hw_registred) {
5377 /* Restore the queues count before unregistering, because firmware detect
5378 * might have modified it. Restoring is important, so the networking
5379 * stack can properly free resources. */
5380 wl->hw->queues = wl->mac80211_initially_registered_queues;
5381 b43_leds_stop(wldev); 5373 b43_leds_stop(wldev);
5382 ieee80211_unregister_hw(wl->hw); 5374 ieee80211_unregister_hw(wl->hw);
5383 } 5375 }
@@ -5452,10 +5444,6 @@ static void b43_ssb_remove(struct ssb_device *sdev)
5452 5444
5453 B43_WARN_ON(!wl); 5445 B43_WARN_ON(!wl);
5454 if (wl->current_dev == wldev && wl->hw_registred) { 5446 if (wl->current_dev == wldev && wl->hw_registred) {
5455 /* Restore the queues count before unregistering, because firmware detect
5456 * might have modified it. Restoring is important, so the networking
5457 * stack can properly free resources. */
5458 wl->hw->queues = wl->mac80211_initially_registered_queues;
5459 b43_leds_stop(wldev); 5447 b43_leds_stop(wldev);
5460 ieee80211_unregister_hw(wl->hw); 5448 ieee80211_unregister_hw(wl->hw);
5461 } 5449 }