diff options
author | John W. Linville <linville@tuxdriver.com> | 2012-01-05 10:12:45 -0500 |
---|---|---|
committer | John W. Linville <linville@tuxdriver.com> | 2012-01-05 10:13:24 -0500 |
commit | 1032c736e81cdf490ae62f86da7efe67c3c3e61d (patch) | |
tree | a0c3919849f97dbbc5ea7c6a9ac1d7a639e44a73 /drivers/net/wireless/b43legacy | |
parent | 117ff42fd43e92d24c6aa6f3e4f0f1e1edada140 (diff) | |
parent | cb00ec382b57d35b955c085198cd54a0c1fcdc94 (diff) |
Merge branch 'master' of git://git.kernel.org/pub/scm/linux/kernel/git/linville/wireless-next into for-davem
Conflicts:
drivers/net/wireless/b43legacy/dma.c
Diffstat (limited to 'drivers/net/wireless/b43legacy')
-rw-r--r-- | drivers/net/wireless/b43legacy/b43legacy.h | 20 | ||||
-rw-r--r-- | drivers/net/wireless/b43legacy/dma.c | 65 | ||||
-rw-r--r-- | drivers/net/wireless/b43legacy/dma.h | 5 | ||||
-rw-r--r-- | drivers/net/wireless/b43legacy/main.c | 86 |
4 files changed, 126 insertions, 50 deletions
diff --git a/drivers/net/wireless/b43legacy/b43legacy.h b/drivers/net/wireless/b43legacy/b43legacy.h index 1d4fc9db7f5e..98e3d44400c6 100644 --- a/drivers/net/wireless/b43legacy/b43legacy.h +++ b/drivers/net/wireless/b43legacy/b43legacy.h | |||
@@ -560,8 +560,16 @@ struct b43legacy_key { | |||
560 | u8 algorithm; | 560 | u8 algorithm; |
561 | }; | 561 | }; |
562 | 562 | ||
563 | #define B43legacy_QOS_QUEUE_NUM 4 | ||
564 | |||
563 | struct b43legacy_wldev; | 565 | struct b43legacy_wldev; |
564 | 566 | ||
567 | /* QOS parameters for a queue. */ | ||
568 | struct b43legacy_qos_params { | ||
569 | /* The QOS parameters */ | ||
570 | struct ieee80211_tx_queue_params p; | ||
571 | }; | ||
572 | |||
565 | /* Data structure for the WLAN parts (802.11 cores) of the b43legacy chip. */ | 573 | /* Data structure for the WLAN parts (802.11 cores) of the b43legacy chip. */ |
566 | struct b43legacy_wl { | 574 | struct b43legacy_wl { |
567 | /* Pointer to the active wireless device on this chip */ | 575 | /* Pointer to the active wireless device on this chip */ |
@@ -611,6 +619,18 @@ struct b43legacy_wl { | |||
611 | bool beacon1_uploaded; | 619 | bool beacon1_uploaded; |
612 | bool beacon_templates_virgin; /* Never wrote the templates? */ | 620 | bool beacon_templates_virgin; /* Never wrote the templates? */ |
613 | struct work_struct beacon_update_trigger; | 621 | struct work_struct beacon_update_trigger; |
622 | /* The current QOS parameters for the 4 queues. */ | ||
623 | struct b43legacy_qos_params qos_params[B43legacy_QOS_QUEUE_NUM]; | ||
624 | |||
625 | /* Packet transmit work */ | ||
626 | struct work_struct tx_work; | ||
627 | |||
628 | /* Queue of packets to be transmitted. */ | ||
629 | struct sk_buff_head tx_queue[B43legacy_QOS_QUEUE_NUM]; | ||
630 | |||
631 | /* Flag that implement the queues stopping. */ | ||
632 | bool tx_queue_stopped[B43legacy_QOS_QUEUE_NUM]; | ||
633 | |||
614 | }; | 634 | }; |
615 | 635 | ||
616 | /* Pointers to the firmware data and meta information about it. */ | 636 | /* Pointers to the firmware data and meta information about it. */ |
diff --git a/drivers/net/wireless/b43legacy/dma.c b/drivers/net/wireless/b43legacy/dma.c index 1ee31c55c7ba..f1f8bd09bd87 100644 --- a/drivers/net/wireless/b43legacy/dma.c +++ b/drivers/net/wireless/b43legacy/dma.c | |||
@@ -727,7 +727,6 @@ struct b43legacy_dmaring *b43legacy_setup_dmaring(struct b43legacy_wldev *dev, | |||
727 | } else | 727 | } else |
728 | B43legacy_WARN_ON(1); | 728 | B43legacy_WARN_ON(1); |
729 | } | 729 | } |
730 | spin_lock_init(&ring->lock); | ||
731 | #ifdef CONFIG_B43LEGACY_DEBUG | 730 | #ifdef CONFIG_B43LEGACY_DEBUG |
732 | ring->last_injected_overflow = jiffies; | 731 | ring->last_injected_overflow = jiffies; |
733 | #endif | 732 | #endif |
@@ -1144,10 +1143,8 @@ int b43legacy_dma_tx(struct b43legacy_wldev *dev, | |||
1144 | { | 1143 | { |
1145 | struct b43legacy_dmaring *ring; | 1144 | struct b43legacy_dmaring *ring; |
1146 | int err = 0; | 1145 | int err = 0; |
1147 | unsigned long flags; | ||
1148 | 1146 | ||
1149 | ring = priority_to_txring(dev, skb_get_queue_mapping(skb)); | 1147 | ring = priority_to_txring(dev, skb_get_queue_mapping(skb)); |
1150 | spin_lock_irqsave(&ring->lock, flags); | ||
1151 | B43legacy_WARN_ON(!ring->tx); | 1148 | B43legacy_WARN_ON(!ring->tx); |
1152 | 1149 | ||
1153 | if (unlikely(ring->stopped)) { | 1150 | if (unlikely(ring->stopped)) { |
@@ -1157,16 +1154,14 @@ int b43legacy_dma_tx(struct b43legacy_wldev *dev, | |||
1157 | * For now, just refuse the transmit. */ | 1154 | * For now, just refuse the transmit. */ |
1158 | if (b43legacy_debug(dev, B43legacy_DBG_DMAVERBOSE)) | 1155 | if (b43legacy_debug(dev, B43legacy_DBG_DMAVERBOSE)) |
1159 | b43legacyerr(dev->wl, "Packet after queue stopped\n"); | 1156 | b43legacyerr(dev->wl, "Packet after queue stopped\n"); |
1160 | err = -ENOSPC; | 1157 | return -ENOSPC; |
1161 | goto out_unlock; | ||
1162 | } | 1158 | } |
1163 | 1159 | ||
1164 | if (unlikely(WARN_ON(free_slots(ring) < SLOTS_PER_PACKET))) { | 1160 | if (unlikely(WARN_ON(free_slots(ring) < SLOTS_PER_PACKET))) { |
1165 | /* If we get here, we have a real error with the queue | 1161 | /* If we get here, we have a real error with the queue |
1166 | * full, but queues not stopped. */ | 1162 | * full, but queues not stopped. */ |
1167 | b43legacyerr(dev->wl, "DMA queue overflow\n"); | 1163 | b43legacyerr(dev->wl, "DMA queue overflow\n"); |
1168 | err = -ENOSPC; | 1164 | return -ENOSPC; |
1169 | goto out_unlock; | ||
1170 | } | 1165 | } |
1171 | 1166 | ||
1172 | /* dma_tx_fragment might reallocate the skb, so invalidate pointers pointing | 1167 | /* dma_tx_fragment might reallocate the skb, so invalidate pointers pointing |
@@ -1176,25 +1171,23 @@ int b43legacy_dma_tx(struct b43legacy_wldev *dev, | |||
1176 | /* Drop this packet, as we don't have the encryption key | 1171 | /* Drop this packet, as we don't have the encryption key |
1177 | * anymore and must not transmit it unencrypted. */ | 1172 | * anymore and must not transmit it unencrypted. */ |
1178 | dev_kfree_skb_any(skb); | 1173 | dev_kfree_skb_any(skb); |
1179 | err = 0; | 1174 | return 0; |
1180 | goto out_unlock; | ||
1181 | } | 1175 | } |
1182 | if (unlikely(err)) { | 1176 | if (unlikely(err)) { |
1183 | b43legacyerr(dev->wl, "DMA tx mapping failure\n"); | 1177 | b43legacyerr(dev->wl, "DMA tx mapping failure\n"); |
1184 | goto out_unlock; | 1178 | return err; |
1185 | } | 1179 | } |
1186 | if ((free_slots(ring) < SLOTS_PER_PACKET) || | 1180 | if ((free_slots(ring) < SLOTS_PER_PACKET) || |
1187 | should_inject_overflow(ring)) { | 1181 | should_inject_overflow(ring)) { |
1188 | /* This TX ring is full. */ | 1182 | /* This TX ring is full. */ |
1189 | ieee80211_stop_queue(dev->wl->hw, txring_to_priority(ring)); | 1183 | unsigned int skb_mapping = skb_get_queue_mapping(skb); |
1184 | ieee80211_stop_queue(dev->wl->hw, skb_mapping); | ||
1185 | dev->wl->tx_queue_stopped[skb_mapping] = 1; | ||
1190 | ring->stopped = true; | 1186 | ring->stopped = true; |
1191 | if (b43legacy_debug(dev, B43legacy_DBG_DMAVERBOSE)) | 1187 | if (b43legacy_debug(dev, B43legacy_DBG_DMAVERBOSE)) |
1192 | b43legacydbg(dev->wl, "Stopped TX ring %d\n", | 1188 | b43legacydbg(dev->wl, "Stopped TX ring %d\n", |
1193 | ring->index); | 1189 | ring->index); |
1194 | } | 1190 | } |
1195 | out_unlock: | ||
1196 | spin_unlock_irqrestore(&ring->lock, flags); | ||
1197 | |||
1198 | return err; | 1191 | return err; |
1199 | } | 1192 | } |
1200 | 1193 | ||
@@ -1205,14 +1198,29 @@ void b43legacy_dma_handle_txstatus(struct b43legacy_wldev *dev, | |||
1205 | struct b43legacy_dmadesc_meta *meta; | 1198 | struct b43legacy_dmadesc_meta *meta; |
1206 | int retry_limit; | 1199 | int retry_limit; |
1207 | int slot; | 1200 | int slot; |
1201 | int firstused; | ||
1208 | 1202 | ||
1209 | ring = parse_cookie(dev, status->cookie, &slot); | 1203 | ring = parse_cookie(dev, status->cookie, &slot); |
1210 | if (unlikely(!ring)) | 1204 | if (unlikely(!ring)) |
1211 | return; | 1205 | return; |
1212 | B43legacy_WARN_ON(!irqs_disabled()); | ||
1213 | spin_lock(&ring->lock); | ||
1214 | |||
1215 | B43legacy_WARN_ON(!ring->tx); | 1206 | B43legacy_WARN_ON(!ring->tx); |
1207 | |||
1208 | /* Sanity check: TX packets are processed in-order on one ring. | ||
1209 | * Check if the slot deduced from the cookie really is the first | ||
1210 | * used slot. */ | ||
1211 | firstused = ring->current_slot - ring->used_slots + 1; | ||
1212 | if (firstused < 0) | ||
1213 | firstused = ring->nr_slots + firstused; | ||
1214 | if (unlikely(slot != firstused)) { | ||
1215 | /* This possibly is a firmware bug and will result in | ||
1216 | * malfunction, memory leaks and/or stall of DMA functionality. | ||
1217 | */ | ||
1218 | b43legacydbg(dev->wl, "Out of order TX status report on DMA " | ||
1219 | "ring %d. Expected %d, but got %d\n", | ||
1220 | ring->index, firstused, slot); | ||
1221 | return; | ||
1222 | } | ||
1223 | |||
1216 | while (1) { | 1224 | while (1) { |
1217 | B43legacy_WARN_ON(!(slot >= 0 && slot < ring->nr_slots)); | 1225 | B43legacy_WARN_ON(!(slot >= 0 && slot < ring->nr_slots)); |
1218 | op32_idx2desc(ring, slot, &meta); | 1226 | op32_idx2desc(ring, slot, &meta); |
@@ -1285,14 +1293,21 @@ void b43legacy_dma_handle_txstatus(struct b43legacy_wldev *dev, | |||
1285 | dev->stats.last_tx = jiffies; | 1293 | dev->stats.last_tx = jiffies; |
1286 | if (ring->stopped) { | 1294 | if (ring->stopped) { |
1287 | B43legacy_WARN_ON(free_slots(ring) < SLOTS_PER_PACKET); | 1295 | B43legacy_WARN_ON(free_slots(ring) < SLOTS_PER_PACKET); |
1288 | ieee80211_wake_queue(dev->wl->hw, txring_to_priority(ring)); | ||
1289 | ring->stopped = false; | 1296 | ring->stopped = false; |
1297 | } | ||
1298 | |||
1299 | if (dev->wl->tx_queue_stopped[ring->queue_prio]) { | ||
1300 | dev->wl->tx_queue_stopped[ring->queue_prio] = 0; | ||
1301 | } else { | ||
1302 | /* If the driver queue is running wake the corresponding | ||
1303 | * mac80211 queue. */ | ||
1304 | ieee80211_wake_queue(dev->wl->hw, ring->queue_prio); | ||
1290 | if (b43legacy_debug(dev, B43legacy_DBG_DMAVERBOSE)) | 1305 | if (b43legacy_debug(dev, B43legacy_DBG_DMAVERBOSE)) |
1291 | b43legacydbg(dev->wl, "Woke up TX ring %d\n", | 1306 | b43legacydbg(dev->wl, "Woke up TX ring %d\n", |
1292 | ring->index); | 1307 | ring->index); |
1293 | } | 1308 | } |
1294 | 1309 | /* Add work to the queue. */ | |
1295 | spin_unlock(&ring->lock); | 1310 | ieee80211_queue_work(dev->wl->hw, &dev->wl->tx_work); |
1296 | } | 1311 | } |
1297 | 1312 | ||
1298 | static void dma_rx(struct b43legacy_dmaring *ring, | 1313 | static void dma_rx(struct b43legacy_dmaring *ring, |
@@ -1415,22 +1430,14 @@ void b43legacy_dma_rx(struct b43legacy_dmaring *ring) | |||
1415 | 1430 | ||
1416 | static void b43legacy_dma_tx_suspend_ring(struct b43legacy_dmaring *ring) | 1431 | static void b43legacy_dma_tx_suspend_ring(struct b43legacy_dmaring *ring) |
1417 | { | 1432 | { |
1418 | unsigned long flags; | ||
1419 | |||
1420 | spin_lock_irqsave(&ring->lock, flags); | ||
1421 | B43legacy_WARN_ON(!ring->tx); | 1433 | B43legacy_WARN_ON(!ring->tx); |
1422 | op32_tx_suspend(ring); | 1434 | op32_tx_suspend(ring); |
1423 | spin_unlock_irqrestore(&ring->lock, flags); | ||
1424 | } | 1435 | } |
1425 | 1436 | ||
1426 | static void b43legacy_dma_tx_resume_ring(struct b43legacy_dmaring *ring) | 1437 | static void b43legacy_dma_tx_resume_ring(struct b43legacy_dmaring *ring) |
1427 | { | 1438 | { |
1428 | unsigned long flags; | ||
1429 | |||
1430 | spin_lock_irqsave(&ring->lock, flags); | ||
1431 | B43legacy_WARN_ON(!ring->tx); | 1439 | B43legacy_WARN_ON(!ring->tx); |
1432 | op32_tx_resume(ring); | 1440 | op32_tx_resume(ring); |
1433 | spin_unlock_irqrestore(&ring->lock, flags); | ||
1434 | } | 1441 | } |
1435 | 1442 | ||
1436 | void b43legacy_dma_tx_suspend(struct b43legacy_wldev *dev) | 1443 | void b43legacy_dma_tx_suspend(struct b43legacy_wldev *dev) |
diff --git a/drivers/net/wireless/b43legacy/dma.h b/drivers/net/wireless/b43legacy/dma.h index 504a58767e95..c3282f906bc7 100644 --- a/drivers/net/wireless/b43legacy/dma.h +++ b/drivers/net/wireless/b43legacy/dma.h | |||
@@ -150,8 +150,9 @@ struct b43legacy_dmaring { | |||
150 | enum b43legacy_dmatype type; | 150 | enum b43legacy_dmatype type; |
151 | /* Boolean. Is this ring stopped at ieee80211 level? */ | 151 | /* Boolean. Is this ring stopped at ieee80211 level? */ |
152 | bool stopped; | 152 | bool stopped; |
153 | /* Lock, only used for TX. */ | 153 | /* The QOS priority assigned to this ring. Only used for TX rings. |
154 | spinlock_t lock; | 154 | * This is the mac80211 "queue" value. */ |
155 | u8 queue_prio; | ||
155 | struct b43legacy_wldev *dev; | 156 | struct b43legacy_wldev *dev; |
156 | #ifdef CONFIG_B43LEGACY_DEBUG | 157 | #ifdef CONFIG_B43LEGACY_DEBUG |
157 | /* Maximum number of used slots. */ | 158 | /* Maximum number of used slots. */ |
diff --git a/drivers/net/wireless/b43legacy/main.c b/drivers/net/wireless/b43legacy/main.c index 200138cdb030..75e70bce40f6 100644 --- a/drivers/net/wireless/b43legacy/main.c +++ b/drivers/net/wireless/b43legacy/main.c | |||
@@ -2440,30 +2440,64 @@ static int b43legacy_rng_init(struct b43legacy_wl *wl) | |||
2440 | return err; | 2440 | return err; |
2441 | } | 2441 | } |
2442 | 2442 | ||
2443 | static void b43legacy_tx_work(struct work_struct *work) | ||
2444 | { | ||
2445 | struct b43legacy_wl *wl = container_of(work, struct b43legacy_wl, | ||
2446 | tx_work); | ||
2447 | struct b43legacy_wldev *dev; | ||
2448 | struct sk_buff *skb; | ||
2449 | int queue_num; | ||
2450 | int err = 0; | ||
2451 | |||
2452 | mutex_lock(&wl->mutex); | ||
2453 | dev = wl->current_dev; | ||
2454 | if (unlikely(!dev || b43legacy_status(dev) < B43legacy_STAT_STARTED)) { | ||
2455 | mutex_unlock(&wl->mutex); | ||
2456 | return; | ||
2457 | } | ||
2458 | |||
2459 | for (queue_num = 0; queue_num < B43legacy_QOS_QUEUE_NUM; queue_num++) { | ||
2460 | while (skb_queue_len(&wl->tx_queue[queue_num])) { | ||
2461 | skb = skb_dequeue(&wl->tx_queue[queue_num]); | ||
2462 | if (b43legacy_using_pio(dev)) | ||
2463 | err = b43legacy_pio_tx(dev, skb); | ||
2464 | else | ||
2465 | err = b43legacy_dma_tx(dev, skb); | ||
2466 | if (err == -ENOSPC) { | ||
2467 | wl->tx_queue_stopped[queue_num] = 1; | ||
2468 | ieee80211_stop_queue(wl->hw, queue_num); | ||
2469 | skb_queue_head(&wl->tx_queue[queue_num], skb); | ||
2470 | break; | ||
2471 | } | ||
2472 | if (unlikely(err)) | ||
2473 | dev_kfree_skb(skb); /* Drop it */ | ||
2474 | err = 0; | ||
2475 | } | ||
2476 | |||
2477 | if (!err) | ||
2478 | wl->tx_queue_stopped[queue_num] = 0; | ||
2479 | } | ||
2480 | |||
2481 | mutex_unlock(&wl->mutex); | ||
2482 | } | ||
2483 | |||
2443 | static void b43legacy_op_tx(struct ieee80211_hw *hw, | 2484 | static void b43legacy_op_tx(struct ieee80211_hw *hw, |
2444 | struct sk_buff *skb) | 2485 | struct sk_buff *skb) |
2445 | { | 2486 | { |
2446 | struct b43legacy_wl *wl = hw_to_b43legacy_wl(hw); | 2487 | struct b43legacy_wl *wl = hw_to_b43legacy_wl(hw); |
2447 | struct b43legacy_wldev *dev = wl->current_dev; | ||
2448 | int err = -ENODEV; | ||
2449 | unsigned long flags; | ||
2450 | 2488 | ||
2451 | if (unlikely(!dev)) | 2489 | if (unlikely(skb->len < 2 + 2 + 6)) { |
2452 | goto out; | 2490 | /* Too short, this can't be a valid frame. */ |
2453 | if (unlikely(b43legacy_status(dev) < B43legacy_STAT_STARTED)) | ||
2454 | goto out; | ||
2455 | /* DMA-TX is done without a global lock. */ | ||
2456 | if (b43legacy_using_pio(dev)) { | ||
2457 | spin_lock_irqsave(&wl->irq_lock, flags); | ||
2458 | err = b43legacy_pio_tx(dev, skb); | ||
2459 | spin_unlock_irqrestore(&wl->irq_lock, flags); | ||
2460 | } else | ||
2461 | err = b43legacy_dma_tx(dev, skb); | ||
2462 | out: | ||
2463 | if (unlikely(err)) { | ||
2464 | /* Drop the packet. */ | ||
2465 | dev_kfree_skb_any(skb); | 2491 | dev_kfree_skb_any(skb); |
2492 | return; | ||
2466 | } | 2493 | } |
2494 | B43legacy_WARN_ON(skb_shinfo(skb)->nr_frags); | ||
2495 | |||
2496 | skb_queue_tail(&wl->tx_queue[skb->queue_mapping], skb); | ||
2497 | if (!wl->tx_queue_stopped[skb->queue_mapping]) | ||
2498 | ieee80211_queue_work(wl->hw, &wl->tx_work); | ||
2499 | else | ||
2500 | ieee80211_stop_queue(wl->hw, skb->queue_mapping); | ||
2467 | } | 2501 | } |
2468 | 2502 | ||
2469 | static int b43legacy_op_conf_tx(struct ieee80211_hw *hw, | 2503 | static int b43legacy_op_conf_tx(struct ieee80211_hw *hw, |
@@ -2879,6 +2913,7 @@ static void b43legacy_wireless_core_stop(struct b43legacy_wldev *dev) | |||
2879 | { | 2913 | { |
2880 | struct b43legacy_wl *wl = dev->wl; | 2914 | struct b43legacy_wl *wl = dev->wl; |
2881 | unsigned long flags; | 2915 | unsigned long flags; |
2916 | int queue_num; | ||
2882 | 2917 | ||
2883 | if (b43legacy_status(dev) < B43legacy_STAT_STARTED) | 2918 | if (b43legacy_status(dev) < B43legacy_STAT_STARTED) |
2884 | return; | 2919 | return; |
@@ -2898,11 +2933,16 @@ static void b43legacy_wireless_core_stop(struct b43legacy_wldev *dev) | |||
2898 | /* Must unlock as it would otherwise deadlock. No races here. | 2933 | /* Must unlock as it would otherwise deadlock. No races here. |
2899 | * Cancel the possibly running self-rearming periodic work. */ | 2934 | * Cancel the possibly running self-rearming periodic work. */ |
2900 | cancel_delayed_work_sync(&dev->periodic_work); | 2935 | cancel_delayed_work_sync(&dev->periodic_work); |
2936 | cancel_work_sync(&wl->tx_work); | ||
2901 | mutex_lock(&wl->mutex); | 2937 | mutex_lock(&wl->mutex); |
2902 | 2938 | ||
2903 | ieee80211_stop_queues(wl->hw); /* FIXME this could cause a deadlock */ | 2939 | /* Drain all TX queues. */ |
2940 | for (queue_num = 0; queue_num < B43legacy_QOS_QUEUE_NUM; queue_num++) { | ||
2941 | while (skb_queue_len(&wl->tx_queue[queue_num])) | ||
2942 | dev_kfree_skb(skb_dequeue(&wl->tx_queue[queue_num])); | ||
2943 | } | ||
2904 | 2944 | ||
2905 | b43legacy_mac_suspend(dev); | 2945 | b43legacy_mac_suspend(dev); |
2906 | free_irq(dev->dev->irq, dev); | 2946 | free_irq(dev->dev->irq, dev); |
2907 | b43legacydbg(wl, "Wireless interface stopped\n"); | 2947 | b43legacydbg(wl, "Wireless interface stopped\n"); |
2908 | } | 2948 | } |
@@ -3748,6 +3788,7 @@ static int b43legacy_wireless_init(struct ssb_device *dev) | |||
3748 | struct ieee80211_hw *hw; | 3788 | struct ieee80211_hw *hw; |
3749 | struct b43legacy_wl *wl; | 3789 | struct b43legacy_wl *wl; |
3750 | int err = -ENOMEM; | 3790 | int err = -ENOMEM; |
3791 | int queue_num; | ||
3751 | 3792 | ||
3752 | b43legacy_sprom_fixup(dev->bus); | 3793 | b43legacy_sprom_fixup(dev->bus); |
3753 | 3794 | ||
@@ -3782,6 +3823,13 @@ static int b43legacy_wireless_init(struct ssb_device *dev) | |||
3782 | mutex_init(&wl->mutex); | 3823 | mutex_init(&wl->mutex); |
3783 | INIT_LIST_HEAD(&wl->devlist); | 3824 | INIT_LIST_HEAD(&wl->devlist); |
3784 | INIT_WORK(&wl->beacon_update_trigger, b43legacy_beacon_update_trigger_work); | 3825 | INIT_WORK(&wl->beacon_update_trigger, b43legacy_beacon_update_trigger_work); |
3826 | INIT_WORK(&wl->tx_work, b43legacy_tx_work); | ||
3827 | |||
3828 | /* Initialize queues and flags. */ | ||
3829 | for (queue_num = 0; queue_num < B43legacy_QOS_QUEUE_NUM; queue_num++) { | ||
3830 | skb_queue_head_init(&wl->tx_queue[queue_num]); | ||
3831 | wl->tx_queue_stopped[queue_num] = 0; | ||
3832 | } | ||
3785 | 3833 | ||
3786 | ssb_set_devtypedata(dev, wl); | 3834 | ssb_set_devtypedata(dev, wl); |
3787 | b43legacyinfo(wl, "Broadcom %04X WLAN found (core revision %u)\n", | 3835 | b43legacyinfo(wl, "Broadcom %04X WLAN found (core revision %u)\n", |