diff options
author | Arik Nemtsov <arik@wizery.com> | 2011-07-07 07:25:23 -0400 |
---|---|---|
committer | Luciano Coelho <coelho@ti.com> | 2011-07-08 02:39:47 -0400 |
commit | f1a46384ad568f72c11edbe2a3ec284bf32f2dbd (patch) | |
tree | 2d303dfdcbf970db11aa858b1a02fb7d29ef4d4f /drivers/net | |
parent | 097f882153f0ec13617074fa3bdb683b8215e20c (diff) |
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')
-rw-r--r-- | drivers/net/wireless/wl12xx/debugfs.c | 8 | ||||
-rw-r--r-- | drivers/net/wireless/wl12xx/main.c | 13 | ||||
-rw-r--r-- | drivers/net/wireless/wl12xx/ps.c | 9 | ||||
-rw-r--r-- | drivers/net/wireless/wl12xx/tx.c | 33 | ||||
-rw-r--r-- | drivers/net/wireless/wl12xx/tx.h | 10 | ||||
-rw-r--r-- | drivers/net/wireless/wl12xx/wl12xx.h | 2 |
6 files changed, 51 insertions, 24 deletions
diff --git a/drivers/net/wireless/wl12xx/debugfs.c b/drivers/net/wireless/wl12xx/debugfs.c index 4d9c8cc076ec..37934b5601cd 100644 --- a/drivers/net/wireless/wl12xx/debugfs.c +++ b/drivers/net/wireless/wl12xx/debugfs.c | |||
@@ -30,6 +30,7 @@ | |||
30 | #include "acx.h" | 30 | #include "acx.h" |
31 | #include "ps.h" | 31 | #include "ps.h" |
32 | #include "io.h" | 32 | #include "io.h" |
33 | #include "tx.h" | ||
33 | 34 | ||
34 | /* ms */ | 35 | /* ms */ |
35 | #define WL1271_DEBUGFS_STATS_LIFETIME 1000 | 36 | #define WL1271_DEBUGFS_STATS_LIFETIME 1000 |
@@ -233,7 +234,7 @@ static ssize_t tx_queue_len_read(struct file *file, char __user *userbuf, | |||
233 | char buf[20]; | 234 | char buf[20]; |
234 | int res; | 235 | int res; |
235 | 236 | ||
236 | queue_len = wl->tx_queue_count; | 237 | queue_len = wl1271_tx_total_queue_count(wl); |
237 | 238 | ||
238 | res = scnprintf(buf, sizeof(buf), "%u\n", queue_len); | 239 | res = scnprintf(buf, sizeof(buf), "%u\n", queue_len); |
239 | return simple_read_from_buffer(userbuf, count, ppos, buf, res); | 240 | return simple_read_from_buffer(userbuf, count, ppos, buf, res); |
@@ -344,7 +345,10 @@ static ssize_t driver_state_read(struct file *file, char __user *user_buf, | |||
344 | DRIVER_STATE_PRINT_INT(tx_allocated_blocks[3]); | 345 | DRIVER_STATE_PRINT_INT(tx_allocated_blocks[3]); |
345 | DRIVER_STATE_PRINT_INT(tx_frames_cnt); | 346 | DRIVER_STATE_PRINT_INT(tx_frames_cnt); |
346 | DRIVER_STATE_PRINT_LHEX(tx_frames_map[0]); | 347 | DRIVER_STATE_PRINT_LHEX(tx_frames_map[0]); |
347 | DRIVER_STATE_PRINT_INT(tx_queue_count); | 348 | DRIVER_STATE_PRINT_INT(tx_queue_count[0]); |
349 | DRIVER_STATE_PRINT_INT(tx_queue_count[1]); | ||
350 | DRIVER_STATE_PRINT_INT(tx_queue_count[2]); | ||
351 | DRIVER_STATE_PRINT_INT(tx_queue_count[3]); | ||
348 | DRIVER_STATE_PRINT_INT(tx_packets_count); | 352 | DRIVER_STATE_PRINT_INT(tx_packets_count); |
349 | DRIVER_STATE_PRINT_INT(tx_results_count); | 353 | DRIVER_STATE_PRINT_INT(tx_results_count); |
350 | DRIVER_STATE_PRINT_LHEX(flags); | 354 | DRIVER_STATE_PRINT_LHEX(flags); |
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) | |||
992 | /* Check if any tx blocks were freed */ | 992 | /* Check if any tx blocks were freed */ |
993 | spin_lock_irqsave(&wl->wl_lock, flags); | 993 | spin_lock_irqsave(&wl->wl_lock, flags); |
994 | if (!test_bit(WL1271_FLAG_FW_TX_BUSY, &wl->flags) && | 994 | if (!test_bit(WL1271_FLAG_FW_TX_BUSY, &wl->flags) && |
995 | wl->tx_queue_count) { | 995 | wl1271_tx_total_queue_count(wl) > 0) { |
996 | spin_unlock_irqrestore(&wl->wl_lock, flags); | 996 | spin_unlock_irqrestore(&wl->wl_lock, flags); |
997 | /* | 997 | /* |
998 | * In order to avoid starvation of the TX path, | 998 | * In order to avoid starvation of the TX path, |
@@ -1040,7 +1040,7 @@ out: | |||
1040 | /* In case TX was not handled here, queue TX work */ | 1040 | /* In case TX was not handled here, queue TX work */ |
1041 | clear_bit(WL1271_FLAG_TX_PENDING, &wl->flags); | 1041 | clear_bit(WL1271_FLAG_TX_PENDING, &wl->flags); |
1042 | if (!test_bit(WL1271_FLAG_FW_TX_BUSY, &wl->flags) && | 1042 | if (!test_bit(WL1271_FLAG_FW_TX_BUSY, &wl->flags) && |
1043 | wl->tx_queue_count) | 1043 | wl1271_tx_total_queue_count(wl) > 0) |
1044 | ieee80211_queue_work(wl->hw, &wl->tx_work); | 1044 | ieee80211_queue_work(wl->hw, &wl->tx_work); |
1045 | spin_unlock_irqrestore(&wl->wl_lock, flags); | 1045 | spin_unlock_irqrestore(&wl->wl_lock, flags); |
1046 | 1046 | ||
@@ -1508,13 +1508,13 @@ static void wl1271_op_tx(struct ieee80211_hw *hw, struct sk_buff *skb) | |||
1508 | 1508 | ||
1509 | spin_lock_irqsave(&wl->wl_lock, flags); | 1509 | spin_lock_irqsave(&wl->wl_lock, flags); |
1510 | 1510 | ||
1511 | wl->tx_queue_count++; | 1511 | wl->tx_queue_count[q]++; |
1512 | 1512 | ||
1513 | /* | 1513 | /* |
1514 | * The workqueue is slow to process the tx_queue and we need stop | 1514 | * The workqueue is slow to process the tx_queue and we need stop |
1515 | * the queue here, otherwise the queue will get too long. | 1515 | * the queue here, otherwise the queue will get too long. |
1516 | */ | 1516 | */ |
1517 | if (skb_queue_len(&wl->tx_queue[q]) >= WL1271_TX_QUEUE_HIGH_WATERMARK) { | 1517 | if (wl->tx_queue_count[q] >= WL1271_TX_QUEUE_HIGH_WATERMARK) { |
1518 | wl1271_debug(DEBUG_TX, "op_tx: stopping queues for q %d", q); | 1518 | wl1271_debug(DEBUG_TX, "op_tx: stopping queues for q %d", q); |
1519 | ieee80211_stop_queue(wl->hw, mapping); | 1519 | ieee80211_stop_queue(wl->hw, mapping); |
1520 | set_bit(q, &wl->stopped_queues_map); | 1520 | set_bit(q, &wl->stopped_queues_map); |
@@ -1543,10 +1543,11 @@ static void wl1271_op_tx(struct ieee80211_hw *hw, struct sk_buff *skb) | |||
1543 | int wl1271_tx_dummy_packet(struct wl1271 *wl) | 1543 | int wl1271_tx_dummy_packet(struct wl1271 *wl) |
1544 | { | 1544 | { |
1545 | unsigned long flags; | 1545 | unsigned long flags; |
1546 | int q = wl1271_tx_get_queue(skb_get_queue_mapping(wl->dummy_packet)); | ||
1546 | 1547 | ||
1547 | spin_lock_irqsave(&wl->wl_lock, flags); | 1548 | spin_lock_irqsave(&wl->wl_lock, flags); |
1548 | set_bit(WL1271_FLAG_DUMMY_PACKET_PENDING, &wl->flags); | 1549 | set_bit(WL1271_FLAG_DUMMY_PACKET_PENDING, &wl->flags); |
1549 | wl->tx_queue_count++; | 1550 | wl->tx_queue_count[q]++; |
1550 | spin_unlock_irqrestore(&wl->wl_lock, flags); | 1551 | spin_unlock_irqrestore(&wl->wl_lock, flags); |
1551 | 1552 | ||
1552 | /* The FW is low on RX memory blocks, so send the dummy packet asap */ | 1553 | /* 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) | |||
3752 | goto out; | 3753 | goto out; |
3753 | 3754 | ||
3754 | /* packets are considered pending if in the TX queue or the FW */ | 3755 | /* packets are considered pending if in the TX queue or the FW */ |
3755 | ret = (wl->tx_queue_count > 0) || (wl->tx_frames_cnt > 0); | 3756 | ret = (wl1271_tx_total_queue_count(wl) > 0) || (wl->tx_frames_cnt > 0); |
3756 | 3757 | ||
3757 | /* the above is appropriate for STA mode for PS purposes */ | 3758 | /* the above is appropriate for STA mode for PS purposes */ |
3758 | WARN_ON(wl->bss_type != BSS_TYPE_STA_BSS); | 3759 | WARN_ON(wl->bss_type != BSS_TYPE_STA_BSS); |
diff --git a/drivers/net/wireless/wl12xx/ps.c b/drivers/net/wireless/wl12xx/ps.c index 3e68a664c9de..3548377ab9c2 100644 --- a/drivers/net/wireless/wl12xx/ps.c +++ b/drivers/net/wireless/wl12xx/ps.c | |||
@@ -193,24 +193,27 @@ int wl1271_ps_set_mode(struct wl1271 *wl, enum wl1271_cmd_ps_mode mode, | |||
193 | 193 | ||
194 | static void wl1271_ps_filter_frames(struct wl1271 *wl, u8 hlid) | 194 | static void wl1271_ps_filter_frames(struct wl1271 *wl, u8 hlid) |
195 | { | 195 | { |
196 | int i, filtered = 0; | 196 | int i; |
197 | struct sk_buff *skb; | 197 | struct sk_buff *skb; |
198 | struct ieee80211_tx_info *info; | 198 | struct ieee80211_tx_info *info; |
199 | unsigned long flags; | 199 | unsigned long flags; |
200 | int filtered[NUM_TX_QUEUES]; | ||
200 | 201 | ||
201 | /* filter all frames currently the low level queus for this hlid */ | 202 | /* filter all frames currently the low level queus for this hlid */ |
202 | for (i = 0; i < NUM_TX_QUEUES; i++) { | 203 | for (i = 0; i < NUM_TX_QUEUES; i++) { |
204 | filtered[i] = 0; | ||
203 | while ((skb = skb_dequeue(&wl->links[hlid].tx_queue[i]))) { | 205 | while ((skb = skb_dequeue(&wl->links[hlid].tx_queue[i]))) { |
204 | info = IEEE80211_SKB_CB(skb); | 206 | info = IEEE80211_SKB_CB(skb); |
205 | info->flags |= IEEE80211_TX_STAT_TX_FILTERED; | 207 | info->flags |= IEEE80211_TX_STAT_TX_FILTERED; |
206 | info->status.rates[0].idx = -1; | 208 | info->status.rates[0].idx = -1; |
207 | ieee80211_tx_status_ni(wl->hw, skb); | 209 | ieee80211_tx_status_ni(wl->hw, skb); |
208 | filtered++; | 210 | filtered[i]++; |
209 | } | 211 | } |
210 | } | 212 | } |
211 | 213 | ||
212 | spin_lock_irqsave(&wl->wl_lock, flags); | 214 | spin_lock_irqsave(&wl->wl_lock, flags); |
213 | wl->tx_queue_count -= filtered; | 215 | for (i = 0; i < NUM_TX_QUEUES; i++) |
216 | wl->tx_queue_count[i] -= filtered[i]; | ||
214 | spin_unlock_irqrestore(&wl->wl_lock, flags); | 217 | spin_unlock_irqrestore(&wl->wl_lock, flags); |
215 | 218 | ||
216 | wl1271_handle_tx_low_watermark(wl); | 219 | wl1271_handle_tx_low_watermark(wl); |
diff --git a/drivers/net/wireless/wl12xx/tx.c b/drivers/net/wireless/wl12xx/tx.c index 75984dc81a8d..48fde96ce0d4 100644 --- a/drivers/net/wireless/wl12xx/tx.c +++ b/drivers/net/wireless/wl12xx/tx.c | |||
@@ -448,8 +448,7 @@ void wl1271_handle_tx_low_watermark(struct wl1271 *wl) | |||
448 | 448 | ||
449 | for (i = 0; i < NUM_TX_QUEUES; i++) { | 449 | for (i = 0; i < NUM_TX_QUEUES; i++) { |
450 | if (test_bit(i, &wl->stopped_queues_map) && | 450 | if (test_bit(i, &wl->stopped_queues_map) && |
451 | skb_queue_len(&wl->tx_queue[i]) <= | 451 | wl->tx_queue_count[i] <= WL1271_TX_QUEUE_LOW_WATERMARK) { |
452 | WL1271_TX_QUEUE_LOW_WATERMARK) { | ||
453 | /* firmware buffer has space, restart queues */ | 452 | /* firmware buffer has space, restart queues */ |
454 | spin_lock_irqsave(&wl->wl_lock, flags); | 453 | spin_lock_irqsave(&wl->wl_lock, flags); |
455 | ieee80211_wake_queue(wl->hw, | 454 | ieee80211_wake_queue(wl->hw, |
@@ -498,8 +497,9 @@ static struct sk_buff *wl1271_sta_skb_dequeue(struct wl1271 *wl) | |||
498 | 497 | ||
499 | out: | 498 | out: |
500 | if (skb) { | 499 | if (skb) { |
500 | int q = wl1271_tx_get_queue(skb_get_queue_mapping(skb)); | ||
501 | spin_lock_irqsave(&wl->wl_lock, flags); | 501 | spin_lock_irqsave(&wl->wl_lock, flags); |
502 | wl->tx_queue_count--; | 502 | wl->tx_queue_count[q]--; |
503 | spin_unlock_irqrestore(&wl->wl_lock, flags); | 503 | spin_unlock_irqrestore(&wl->wl_lock, flags); |
504 | } | 504 | } |
505 | 505 | ||
@@ -535,9 +535,10 @@ static struct sk_buff *wl1271_ap_skb_dequeue(struct wl1271 *wl) | |||
535 | } | 535 | } |
536 | 536 | ||
537 | if (skb) { | 537 | if (skb) { |
538 | int q = wl1271_tx_get_queue(skb_get_queue_mapping(skb)); | ||
538 | wl->last_tx_hlid = h; | 539 | wl->last_tx_hlid = h; |
539 | spin_lock_irqsave(&wl->wl_lock, flags); | 540 | spin_lock_irqsave(&wl->wl_lock, flags); |
540 | wl->tx_queue_count--; | 541 | wl->tx_queue_count[q]--; |
541 | spin_unlock_irqrestore(&wl->wl_lock, flags); | 542 | spin_unlock_irqrestore(&wl->wl_lock, flags); |
542 | } else { | 543 | } else { |
543 | wl->last_tx_hlid = 0; | 544 | wl->last_tx_hlid = 0; |
@@ -558,9 +559,12 @@ static struct sk_buff *wl1271_skb_dequeue(struct wl1271 *wl) | |||
558 | 559 | ||
559 | if (!skb && | 560 | if (!skb && |
560 | test_and_clear_bit(WL1271_FLAG_DUMMY_PACKET_PENDING, &wl->flags)) { | 561 | test_and_clear_bit(WL1271_FLAG_DUMMY_PACKET_PENDING, &wl->flags)) { |
562 | int q; | ||
563 | |||
561 | skb = wl->dummy_packet; | 564 | skb = wl->dummy_packet; |
565 | q = wl1271_tx_get_queue(skb_get_queue_mapping(skb)); | ||
562 | spin_lock_irqsave(&wl->wl_lock, flags); | 566 | spin_lock_irqsave(&wl->wl_lock, flags); |
563 | wl->tx_queue_count--; | 567 | wl->tx_queue_count[q]--; |
564 | spin_unlock_irqrestore(&wl->wl_lock, flags); | 568 | spin_unlock_irqrestore(&wl->wl_lock, flags); |
565 | } | 569 | } |
566 | 570 | ||
@@ -585,7 +589,7 @@ static void wl1271_skb_queue_head(struct wl1271 *wl, struct sk_buff *skb) | |||
585 | } | 589 | } |
586 | 590 | ||
587 | spin_lock_irqsave(&wl->wl_lock, flags); | 591 | spin_lock_irqsave(&wl->wl_lock, flags); |
588 | wl->tx_queue_count++; | 592 | wl->tx_queue_count[q]++; |
589 | spin_unlock_irqrestore(&wl->wl_lock, flags); | 593 | spin_unlock_irqrestore(&wl->wl_lock, flags); |
590 | } | 594 | } |
591 | 595 | ||
@@ -813,23 +817,26 @@ void wl1271_tx_complete(struct wl1271 *wl) | |||
813 | void wl1271_tx_reset_link_queues(struct wl1271 *wl, u8 hlid) | 817 | void wl1271_tx_reset_link_queues(struct wl1271 *wl, u8 hlid) |
814 | { | 818 | { |
815 | struct sk_buff *skb; | 819 | struct sk_buff *skb; |
816 | int i, total = 0; | 820 | int i; |
817 | unsigned long flags; | 821 | unsigned long flags; |
818 | struct ieee80211_tx_info *info; | 822 | struct ieee80211_tx_info *info; |
823 | int total[NUM_TX_QUEUES]; | ||
819 | 824 | ||
820 | for (i = 0; i < NUM_TX_QUEUES; i++) { | 825 | for (i = 0; i < NUM_TX_QUEUES; i++) { |
826 | total[i] = 0; | ||
821 | while ((skb = skb_dequeue(&wl->links[hlid].tx_queue[i]))) { | 827 | while ((skb = skb_dequeue(&wl->links[hlid].tx_queue[i]))) { |
822 | wl1271_debug(DEBUG_TX, "link freeing skb 0x%p", skb); | 828 | wl1271_debug(DEBUG_TX, "link freeing skb 0x%p", skb); |
823 | info = IEEE80211_SKB_CB(skb); | 829 | info = IEEE80211_SKB_CB(skb); |
824 | info->status.rates[0].idx = -1; | 830 | info->status.rates[0].idx = -1; |
825 | info->status.rates[0].count = 0; | 831 | info->status.rates[0].count = 0; |
826 | ieee80211_tx_status_ni(wl->hw, skb); | 832 | ieee80211_tx_status_ni(wl->hw, skb); |
827 | total++; | 833 | total[i]++; |
828 | } | 834 | } |
829 | } | 835 | } |
830 | 836 | ||
831 | spin_lock_irqsave(&wl->wl_lock, flags); | 837 | spin_lock_irqsave(&wl->wl_lock, flags); |
832 | wl->tx_queue_count -= total; | 838 | for (i = 0; i < NUM_TX_QUEUES; i++) |
839 | wl->tx_queue_count[i] -= total[i]; | ||
833 | spin_unlock_irqrestore(&wl->wl_lock, flags); | 840 | spin_unlock_irqrestore(&wl->wl_lock, flags); |
834 | 841 | ||
835 | wl1271_handle_tx_low_watermark(wl); | 842 | wl1271_handle_tx_low_watermark(wl); |
@@ -864,10 +871,10 @@ void wl1271_tx_reset(struct wl1271 *wl, bool reset_tx_queues) | |||
864 | ieee80211_tx_status_ni(wl->hw, skb); | 871 | ieee80211_tx_status_ni(wl->hw, skb); |
865 | } | 872 | } |
866 | } | 873 | } |
874 | wl->tx_queue_count[i] = 0; | ||
867 | } | 875 | } |
868 | } | 876 | } |
869 | 877 | ||
870 | wl->tx_queue_count = 0; | ||
871 | wl->stopped_queues_map = 0; | 878 | wl->stopped_queues_map = 0; |
872 | 879 | ||
873 | /* | 880 | /* |
@@ -921,8 +928,10 @@ void wl1271_tx_flush(struct wl1271 *wl) | |||
921 | while (!time_after(jiffies, timeout)) { | 928 | while (!time_after(jiffies, timeout)) { |
922 | mutex_lock(&wl->mutex); | 929 | mutex_lock(&wl->mutex); |
923 | wl1271_debug(DEBUG_TX, "flushing tx buffer: %d %d", | 930 | wl1271_debug(DEBUG_TX, "flushing tx buffer: %d %d", |
924 | wl->tx_frames_cnt, wl->tx_queue_count); | 931 | wl->tx_frames_cnt, |
925 | if ((wl->tx_frames_cnt == 0) && (wl->tx_queue_count == 0)) { | 932 | wl1271_tx_total_queue_count(wl)); |
933 | if ((wl->tx_frames_cnt == 0) && | ||
934 | (wl1271_tx_total_queue_count(wl) == 0)) { | ||
926 | mutex_unlock(&wl->mutex); | 935 | mutex_unlock(&wl->mutex); |
927 | return; | 936 | return; |
928 | } | 937 | } |
diff --git a/drivers/net/wireless/wl12xx/tx.h b/drivers/net/wireless/wl12xx/tx.h index 6b7bf3150ec4..5d719b5a3d1d 100644 --- a/drivers/net/wireless/wl12xx/tx.h +++ b/drivers/net/wireless/wl12xx/tx.h | |||
@@ -198,6 +198,16 @@ static inline int wl1271_tx_get_mac80211_queue(int queue) | |||
198 | } | 198 | } |
199 | } | 199 | } |
200 | 200 | ||
201 | static inline int wl1271_tx_total_queue_count(struct wl1271 *wl) | ||
202 | { | ||
203 | int i, count = 0; | ||
204 | |||
205 | for (i = 0; i < NUM_TX_QUEUES; i++) | ||
206 | count += wl->tx_queue_count[i]; | ||
207 | |||
208 | return count; | ||
209 | } | ||
210 | |||
201 | void wl1271_tx_work(struct work_struct *work); | 211 | void wl1271_tx_work(struct work_struct *work); |
202 | void wl1271_tx_work_locked(struct wl1271 *wl); | 212 | void wl1271_tx_work_locked(struct wl1271 *wl); |
203 | void wl1271_tx_complete(struct wl1271 *wl); | 213 | void wl1271_tx_complete(struct wl1271 *wl); |
diff --git a/drivers/net/wireless/wl12xx/wl12xx.h b/drivers/net/wireless/wl12xx/wl12xx.h index 94bfc0a25d57..1a8751eb8140 100644 --- a/drivers/net/wireless/wl12xx/wl12xx.h +++ b/drivers/net/wireless/wl12xx/wl12xx.h | |||
@@ -438,7 +438,7 @@ struct wl1271 { | |||
438 | 438 | ||
439 | /* Frames scheduled for transmission, not handled yet */ | 439 | /* Frames scheduled for transmission, not handled yet */ |
440 | struct sk_buff_head tx_queue[NUM_TX_QUEUES]; | 440 | struct sk_buff_head tx_queue[NUM_TX_QUEUES]; |
441 | int tx_queue_count; | 441 | int tx_queue_count[NUM_TX_QUEUES]; |
442 | long stopped_queues_map; | 442 | long stopped_queues_map; |
443 | 443 | ||
444 | /* Frames received, not handled yet by mac80211 */ | 444 | /* Frames received, not handled yet by mac80211 */ |