aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--drivers/net/wireless/b43/b43.h9
-rw-r--r--drivers/net/wireless/b43/dma.c15
-rw-r--r--drivers/net/wireless/b43/main.c55
3 files changed, 60 insertions, 19 deletions
diff --git a/drivers/net/wireless/b43/b43.h b/drivers/net/wireless/b43/b43.h
index 37110dfd2c96..f19605e8eb4c 100644
--- a/drivers/net/wireless/b43/b43.h
+++ b/drivers/net/wireless/b43/b43.h
@@ -667,6 +667,7 @@ struct b43_key {
667}; 667};
668 668
669/* SHM offsets to the QOS data structures for the 4 different queues. */ 669/* SHM offsets to the QOS data structures for the 4 different queues. */
670#define B43_QOS_QUEUE_NUM 4
670#define B43_QOS_PARAMS(queue) (B43_SHM_SH_EDCFQ + \ 671#define B43_QOS_PARAMS(queue) (B43_SHM_SH_EDCFQ + \
671 (B43_NR_QOSPARAMS * sizeof(u16) * (queue))) 672 (B43_NR_QOSPARAMS * sizeof(u16) * (queue)))
672#define B43_QOS_BACKGROUND B43_QOS_PARAMS(0) 673#define B43_QOS_BACKGROUND B43_QOS_PARAMS(0)
@@ -904,7 +905,7 @@ struct b43_wl {
904 struct work_struct beacon_update_trigger; 905 struct work_struct beacon_update_trigger;
905 906
906 /* The current QOS parameters for the 4 queues. */ 907 /* The current QOS parameters for the 4 queues. */
907 struct b43_qos_params qos_params[4]; 908 struct b43_qos_params qos_params[B43_QOS_QUEUE_NUM];
908 909
909 /* Work for adjustment of the transmission power. 910 /* Work for adjustment of the transmission power.
910 * This is scheduled when we determine that the actual TX output 911 * This is scheduled when we determine that the actual TX output
@@ -913,8 +914,12 @@ struct b43_wl {
913 914
914 /* Packet transmit work */ 915 /* Packet transmit work */
915 struct work_struct tx_work; 916 struct work_struct tx_work;
917
916 /* Queue of packets to be transmitted. */ 918 /* Queue of packets to be transmitted. */
917 struct sk_buff_head tx_queue; 919 struct sk_buff_head tx_queue[B43_QOS_QUEUE_NUM];
920
921 /* Flag that implement the queues stopping. */
922 bool tx_queue_stopped[B43_QOS_QUEUE_NUM];
918 923
919 /* The device LEDs. */ 924 /* The device LEDs. */
920 struct b43_leds leds; 925 struct b43_leds leds;
diff --git a/drivers/net/wireless/b43/dma.c b/drivers/net/wireless/b43/dma.c
index 5e45604f0f5d..56d37dc967aa 100644
--- a/drivers/net/wireless/b43/dma.c
+++ b/drivers/net/wireless/b43/dma.c
@@ -1465,7 +1465,9 @@ int b43_dma_tx(struct b43_wldev *dev, struct sk_buff *skb)
1465 if ((free_slots(ring) < TX_SLOTS_PER_FRAME) || 1465 if ((free_slots(ring) < TX_SLOTS_PER_FRAME) ||
1466 should_inject_overflow(ring)) { 1466 should_inject_overflow(ring)) {
1467 /* This TX ring is full. */ 1467 /* This TX ring is full. */
1468 ieee80211_stop_queue(dev->wl->hw, skb_get_queue_mapping(skb)); 1468 unsigned int skb_mapping = skb_get_queue_mapping(skb);
1469 ieee80211_stop_queue(dev->wl->hw, skb_mapping);
1470 dev->wl->tx_queue_stopped[skb_mapping] = 1;
1469 ring->stopped = 1; 1471 ring->stopped = 1;
1470 if (b43_debug(dev, B43_DBG_DMAVERBOSE)) { 1472 if (b43_debug(dev, B43_DBG_DMAVERBOSE)) {
1471 b43dbg(dev->wl, "Stopped TX ring %d\n", ring->index); 1473 b43dbg(dev->wl, "Stopped TX ring %d\n", ring->index);
@@ -1584,12 +1586,21 @@ void b43_dma_handle_txstatus(struct b43_wldev *dev,
1584 } 1586 }
1585 if (ring->stopped) { 1587 if (ring->stopped) {
1586 B43_WARN_ON(free_slots(ring) < TX_SLOTS_PER_FRAME); 1588 B43_WARN_ON(free_slots(ring) < TX_SLOTS_PER_FRAME);
1587 ieee80211_wake_queue(dev->wl->hw, ring->queue_prio);
1588 ring->stopped = 0; 1589 ring->stopped = 0;
1590 }
1591
1592 if (dev->wl->tx_queue_stopped[ring->queue_prio]) {
1593 dev->wl->tx_queue_stopped[ring->queue_prio] = 0;
1594 } else {
1595 /* If the driver queue is running wake the corresponding
1596 * mac80211 queue. */
1597 ieee80211_wake_queue(dev->wl->hw, ring->queue_prio);
1589 if (b43_debug(dev, B43_DBG_DMAVERBOSE)) { 1598 if (b43_debug(dev, B43_DBG_DMAVERBOSE)) {
1590 b43dbg(dev->wl, "Woke up TX ring %d\n", ring->index); 1599 b43dbg(dev->wl, "Woke up TX ring %d\n", ring->index);
1591 } 1600 }
1592 } 1601 }
1602 /* Add work to the queue. */
1603 ieee80211_queue_work(dev->wl->hw, &dev->wl->tx_work);
1593} 1604}
1594 1605
1595static void dma_rx(struct b43_dmaring *ring, int *slot) 1606static void dma_rx(struct b43_dmaring *ring, int *slot)
diff --git a/drivers/net/wireless/b43/main.c b/drivers/net/wireless/b43/main.c
index 5634d9a9965b..989f654de006 100644
--- a/drivers/net/wireless/b43/main.c
+++ b/drivers/net/wireless/b43/main.c
@@ -3378,6 +3378,7 @@ static void b43_tx_work(struct work_struct *work)
3378 struct b43_wl *wl = container_of(work, struct b43_wl, tx_work); 3378 struct b43_wl *wl = container_of(work, struct b43_wl, tx_work);
3379 struct b43_wldev *dev; 3379 struct b43_wldev *dev;
3380 struct sk_buff *skb; 3380 struct sk_buff *skb;
3381 int queue_num;
3381 int err = 0; 3382 int err = 0;
3382 3383
3383 mutex_lock(&wl->mutex); 3384 mutex_lock(&wl->mutex);
@@ -3387,15 +3388,26 @@ static void b43_tx_work(struct work_struct *work)
3387 return; 3388 return;
3388 } 3389 }
3389 3390
3390 while (skb_queue_len(&wl->tx_queue)) { 3391 for (queue_num = 0; queue_num < B43_QOS_QUEUE_NUM; queue_num++) {
3391 skb = skb_dequeue(&wl->tx_queue); 3392 while (skb_queue_len(&wl->tx_queue[queue_num])) {
3393 skb = skb_dequeue(&wl->tx_queue[queue_num]);
3394 if (b43_using_pio_transfers(dev))
3395 err = b43_pio_tx(dev, skb);
3396 else
3397 err = b43_dma_tx(dev, skb);
3398 if (err == -ENOSPC) {
3399 wl->tx_queue_stopped[queue_num] = 1;
3400 ieee80211_stop_queue(wl->hw, queue_num);
3401 skb_queue_head(&wl->tx_queue[queue_num], skb);
3402 break;
3403 }
3404 if (unlikely(err))
3405 dev_kfree_skb(skb); /* Drop it */
3406 err = 0;
3407 }
3392 3408
3393 if (b43_using_pio_transfers(dev)) 3409 if (!err)
3394 err = b43_pio_tx(dev, skb); 3410 wl->tx_queue_stopped[queue_num] = 0;
3395 else
3396 err = b43_dma_tx(dev, skb);
3397 if (unlikely(err))
3398 dev_kfree_skb(skb); /* Drop it */
3399 } 3411 }
3400 3412
3401#if B43_DEBUG 3413#if B43_DEBUG
@@ -3416,8 +3428,12 @@ static void b43_op_tx(struct ieee80211_hw *hw,
3416 } 3428 }
3417 B43_WARN_ON(skb_shinfo(skb)->nr_frags); 3429 B43_WARN_ON(skb_shinfo(skb)->nr_frags);
3418 3430
3419 skb_queue_tail(&wl->tx_queue, skb); 3431 skb_queue_tail(&wl->tx_queue[skb->queue_mapping], skb);
3420 ieee80211_queue_work(wl->hw, &wl->tx_work); 3432 if (!wl->tx_queue_stopped[skb->queue_mapping]) {
3433 ieee80211_queue_work(wl->hw, &wl->tx_work);
3434 } else {
3435 ieee80211_stop_queue(wl->hw, skb->queue_mapping);
3436 }
3421} 3437}
3422 3438
3423static void b43_qos_params_upload(struct b43_wldev *dev, 3439static void b43_qos_params_upload(struct b43_wldev *dev,
@@ -4147,6 +4163,7 @@ static struct b43_wldev * b43_wireless_core_stop(struct b43_wldev *dev)
4147 struct b43_wl *wl; 4163 struct b43_wl *wl;
4148 struct b43_wldev *orig_dev; 4164 struct b43_wldev *orig_dev;
4149 u32 mask; 4165 u32 mask;
4166 int queue_num;
4150 4167
4151 if (!dev) 4168 if (!dev)
4152 return NULL; 4169 return NULL;
@@ -4199,9 +4216,11 @@ redo:
4199 mask = b43_read32(dev, B43_MMIO_GEN_IRQ_MASK); 4216 mask = b43_read32(dev, B43_MMIO_GEN_IRQ_MASK);
4200 B43_WARN_ON(mask != 0xFFFFFFFF && mask); 4217 B43_WARN_ON(mask != 0xFFFFFFFF && mask);
4201 4218
4202 /* Drain the TX queue */ 4219 /* Drain all TX queues. */
4203 while (skb_queue_len(&wl->tx_queue)) 4220 for (queue_num = 0; queue_num < B43_QOS_QUEUE_NUM; queue_num++) {
4204 dev_kfree_skb(skb_dequeue(&wl->tx_queue)); 4221 while (skb_queue_len(&wl->tx_queue[queue_num]))
4222 dev_kfree_skb(skb_dequeue(&wl->tx_queue[queue_num]));
4223 }
4205 4224
4206 b43_mac_suspend(dev); 4225 b43_mac_suspend(dev);
4207 b43_leds_exit(dev); 4226 b43_leds_exit(dev);
@@ -5245,6 +5264,7 @@ static struct b43_wl *b43_wireless_init(struct b43_bus_dev *dev)
5245 struct ieee80211_hw *hw; 5264 struct ieee80211_hw *hw;
5246 struct b43_wl *wl; 5265 struct b43_wl *wl;
5247 char chip_name[6]; 5266 char chip_name[6];
5267 int queue_num;
5248 5268
5249 hw = ieee80211_alloc_hw(sizeof(*wl), &b43_hw_ops); 5269 hw = ieee80211_alloc_hw(sizeof(*wl), &b43_hw_ops);
5250 if (!hw) { 5270 if (!hw) {
@@ -5264,7 +5284,7 @@ static struct b43_wl *b43_wireless_init(struct b43_bus_dev *dev)
5264 BIT(NL80211_IFTYPE_WDS) | 5284 BIT(NL80211_IFTYPE_WDS) |
5265 BIT(NL80211_IFTYPE_ADHOC); 5285 BIT(NL80211_IFTYPE_ADHOC);
5266 5286
5267 hw->queues = modparam_qos ? 4 : 1; 5287 hw->queues = modparam_qos ? B43_QOS_QUEUE_NUM : 1;
5268 wl->mac80211_initially_registered_queues = hw->queues; 5288 wl->mac80211_initially_registered_queues = hw->queues;
5269 hw->max_rates = 2; 5289 hw->max_rates = 2;
5270 SET_IEEE80211_DEV(hw, dev->dev); 5290 SET_IEEE80211_DEV(hw, dev->dev);
@@ -5281,7 +5301,12 @@ static struct b43_wl *b43_wireless_init(struct b43_bus_dev *dev)
5281 INIT_WORK(&wl->beacon_update_trigger, b43_beacon_update_trigger_work); 5301 INIT_WORK(&wl->beacon_update_trigger, b43_beacon_update_trigger_work);
5282 INIT_WORK(&wl->txpower_adjust_work, b43_phy_txpower_adjust_work); 5302 INIT_WORK(&wl->txpower_adjust_work, b43_phy_txpower_adjust_work);
5283 INIT_WORK(&wl->tx_work, b43_tx_work); 5303 INIT_WORK(&wl->tx_work, b43_tx_work);
5284 skb_queue_head_init(&wl->tx_queue); 5304
5305 /* Initialize queues and flags. */
5306 for (queue_num = 0; queue_num < B43_QOS_QUEUE_NUM; queue_num++) {
5307 skb_queue_head_init(&wl->tx_queue[queue_num]);
5308 wl->tx_queue_stopped[queue_num] = 0;
5309 }
5285 5310
5286 snprintf(chip_name, ARRAY_SIZE(chip_name), 5311 snprintf(chip_name, ARRAY_SIZE(chip_name),
5287 (dev->chip_id > 0x9999) ? "%d" : "%04X", dev->chip_id); 5312 (dev->chip_id > 0x9999) ? "%d" : "%04X", dev->chip_id);