diff options
author | Arik Nemtsov <arik@wizery.com> | 2011-07-07 14:25:23 +0300 |
---|---|---|
committer | Luciano Coelho <coelho@ti.com> | 2011-07-08 09:39:47 +0300 |
commit | f1a46384ad568f72c11edbe2a3ec284bf32f2dbd (patch) | |
tree | 2d303dfdcbf970db11aa858b1a02fb7d29ef4d4f /drivers/net/wireless/wl12xx/main.c | |
parent | 097f882153f0ec13617074fa3bdb683b8215e20c (diff) | |
download | blackbird-op-linux-f1a46384ad568f72c11edbe2a3ec284bf32f2dbd.tar.gz blackbird-op-linux-f1a46384ad568f72c11edbe2a3ec284bf32f2dbd.zip |
wl12xx: start/stop queues according to global per-AC counters
Split tx_queue_count to count per-AC skb's queued, instead of relying on
the skb-queue len. The skb queues used were only valid in STA-mode, as
AP-mode uses per-link queues.
This fixes a major regression in AP-mode, caused by the patch
"wl12xx: implement Tx watermarks per AC". With that patch applied, we
effectively had no regulation of Tx queues in AP-mode. Therefore a
sustained high rate of Tx could cause exhaustion of the skb memory pool.
Signed-off-by: Arik Nemtsov <arik@wizery.com>
Signed-off-by: Luciano Coelho <coelho@ti.com>
Diffstat (limited to 'drivers/net/wireless/wl12xx/main.c')
-rw-r--r-- | drivers/net/wireless/wl12xx/main.c | 13 |
1 files changed, 7 insertions, 6 deletions
diff --git a/drivers/net/wireless/wl12xx/main.c b/drivers/net/wireless/wl12xx/main.c index 526b1ac2dd80..e58c22d21e39 100644 --- a/drivers/net/wireless/wl12xx/main.c +++ b/drivers/net/wireless/wl12xx/main.c @@ -992,7 +992,7 @@ irqreturn_t wl1271_irq(int irq, void *cookie) /* Check if any tx blocks were freed */ spin_lock_irqsave(&wl->wl_lock, flags); if (!test_bit(WL1271_FLAG_FW_TX_BUSY, &wl->flags) && - wl->tx_queue_count) { + wl1271_tx_total_queue_count(wl) > 0) { spin_unlock_irqrestore(&wl->wl_lock, flags); /* * In order to avoid starvation of the TX path, @@ -1040,7 +1040,7 @@ out: /* In case TX was not handled here, queue TX work */ clear_bit(WL1271_FLAG_TX_PENDING, &wl->flags); if (!test_bit(WL1271_FLAG_FW_TX_BUSY, &wl->flags) && - wl->tx_queue_count) + wl1271_tx_total_queue_count(wl) > 0) ieee80211_queue_work(wl->hw, &wl->tx_work); spin_unlock_irqrestore(&wl->wl_lock, flags); @@ -1508,13 +1508,13 @@ static void wl1271_op_tx(struct ieee80211_hw *hw, struct sk_buff *skb) spin_lock_irqsave(&wl->wl_lock, flags); - wl->tx_queue_count++; + wl->tx_queue_count[q]++; /* * The workqueue is slow to process the tx_queue and we need stop * the queue here, otherwise the queue will get too long. */ - if (skb_queue_len(&wl->tx_queue[q]) >= WL1271_TX_QUEUE_HIGH_WATERMARK) { + if (wl->tx_queue_count[q] >= WL1271_TX_QUEUE_HIGH_WATERMARK) { wl1271_debug(DEBUG_TX, "op_tx: stopping queues for q %d", q); ieee80211_stop_queue(wl->hw, mapping); set_bit(q, &wl->stopped_queues_map); @@ -1543,10 +1543,11 @@ static void wl1271_op_tx(struct ieee80211_hw *hw, struct sk_buff *skb) int wl1271_tx_dummy_packet(struct wl1271 *wl) { unsigned long flags; + int q = wl1271_tx_get_queue(skb_get_queue_mapping(wl->dummy_packet)); spin_lock_irqsave(&wl->wl_lock, flags); set_bit(WL1271_FLAG_DUMMY_PACKET_PENDING, &wl->flags); - wl->tx_queue_count++; + wl->tx_queue_count[q]++; spin_unlock_irqrestore(&wl->wl_lock, flags); /* The FW is low on RX memory blocks, so send the dummy packet asap */ @@ -3752,7 +3753,7 @@ static bool wl1271_tx_frames_pending(struct ieee80211_hw *hw) goto out; /* packets are considered pending if in the TX queue or the FW */ - ret = (wl->tx_queue_count > 0) || (wl->tx_frames_cnt > 0); + ret = (wl1271_tx_total_queue_count(wl) > 0) || (wl->tx_frames_cnt > 0); /* the above is appropriate for STA mode for PS purposes */ WARN_ON(wl->bss_type != BSS_TYPE_STA_BSS); |