diff options
Diffstat (limited to 'drivers')
-rw-r--r-- | drivers/net/wireless/wl12xx/debugfs.c | 2 | ||||
-rw-r--r-- | drivers/net/wireless/wl12xx/main.c | 12 | ||||
-rw-r--r-- | drivers/net/wireless/wl12xx/tx.c | 60 | ||||
-rw-r--r-- | drivers/net/wireless/wl12xx/wl12xx.h | 3 |
4 files changed, 60 insertions, 17 deletions
diff --git a/drivers/net/wireless/wl12xx/debugfs.c b/drivers/net/wireless/wl12xx/debugfs.c index c2cd58074372..ec6077760157 100644 --- a/drivers/net/wireless/wl12xx/debugfs.c +++ b/drivers/net/wireless/wl12xx/debugfs.c | |||
@@ -225,7 +225,7 @@ static ssize_t tx_queue_len_read(struct file *file, char __user *userbuf, | |||
225 | char buf[20]; | 225 | char buf[20]; |
226 | int res; | 226 | int res; |
227 | 227 | ||
228 | queue_len = skb_queue_len(&wl->tx_queue); | 228 | queue_len = wl->tx_queue_count; |
229 | 229 | ||
230 | res = scnprintf(buf, sizeof(buf), "%u\n", queue_len); | 230 | res = scnprintf(buf, sizeof(buf), "%u\n", queue_len); |
231 | return simple_read_from_buffer(userbuf, count, ppos, buf, res); | 231 | return simple_read_from_buffer(userbuf, count, ppos, buf, res); |
diff --git a/drivers/net/wireless/wl12xx/main.c b/drivers/net/wireless/wl12xx/main.c index 8c50d3b3fabb..062247ef3ad2 100644 --- a/drivers/net/wireless/wl12xx/main.c +++ b/drivers/net/wireless/wl12xx/main.c | |||
@@ -570,7 +570,7 @@ static void wl1271_irq_work(struct work_struct *work) | |||
570 | 570 | ||
571 | /* Check if any tx blocks were freed */ | 571 | /* Check if any tx blocks were freed */ |
572 | if (!test_bit(WL1271_FLAG_FW_TX_BUSY, &wl->flags) && | 572 | if (!test_bit(WL1271_FLAG_FW_TX_BUSY, &wl->flags) && |
573 | !skb_queue_empty(&wl->tx_queue)) { | 573 | wl->tx_queue_count) { |
574 | /* | 574 | /* |
575 | * In order to avoid starvation of the TX path, | 575 | * In order to avoid starvation of the TX path, |
576 | * call the work function directly. | 576 | * call the work function directly. |
@@ -891,6 +891,7 @@ static int wl1271_op_tx(struct ieee80211_hw *hw, struct sk_buff *skb) | |||
891 | struct ieee80211_tx_info *txinfo = IEEE80211_SKB_CB(skb); | 891 | struct ieee80211_tx_info *txinfo = IEEE80211_SKB_CB(skb); |
892 | struct ieee80211_sta *sta = txinfo->control.sta; | 892 | struct ieee80211_sta *sta = txinfo->control.sta; |
893 | unsigned long flags; | 893 | unsigned long flags; |
894 | int q; | ||
894 | 895 | ||
895 | /* | 896 | /* |
896 | * peek into the rates configured in the STA entry. | 897 | * peek into the rates configured in the STA entry. |
@@ -918,10 +919,12 @@ static int wl1271_op_tx(struct ieee80211_hw *hw, struct sk_buff *skb) | |||
918 | set_bit(WL1271_FLAG_STA_RATES_CHANGED, &wl->flags); | 919 | set_bit(WL1271_FLAG_STA_RATES_CHANGED, &wl->flags); |
919 | } | 920 | } |
920 | #endif | 921 | #endif |
922 | wl->tx_queue_count++; | ||
921 | spin_unlock_irqrestore(&wl->wl_lock, flags); | 923 | spin_unlock_irqrestore(&wl->wl_lock, flags); |
922 | 924 | ||
923 | /* queue the packet */ | 925 | /* queue the packet */ |
924 | skb_queue_tail(&wl->tx_queue, skb); | 926 | q = wl1271_tx_get_queue(skb_get_queue_mapping(skb)); |
927 | skb_queue_tail(&wl->tx_queue[q], skb); | ||
925 | 928 | ||
926 | /* | 929 | /* |
927 | * The chip specific setup must run before the first TX packet - | 930 | * The chip specific setup must run before the first TX packet - |
@@ -935,7 +938,7 @@ static int wl1271_op_tx(struct ieee80211_hw *hw, struct sk_buff *skb) | |||
935 | * The workqueue is slow to process the tx_queue and we need stop | 938 | * The workqueue is slow to process the tx_queue and we need stop |
936 | * the queue here, otherwise the queue will get too long. | 939 | * the queue here, otherwise the queue will get too long. |
937 | */ | 940 | */ |
938 | if (skb_queue_len(&wl->tx_queue) >= WL1271_TX_QUEUE_HIGH_WATERMARK) { | 941 | if (wl->tx_queue_count >= WL1271_TX_QUEUE_HIGH_WATERMARK) { |
939 | wl1271_debug(DEBUG_TX, "op_tx: stopping queues"); | 942 | wl1271_debug(DEBUG_TX, "op_tx: stopping queues"); |
940 | 943 | ||
941 | spin_lock_irqsave(&wl->wl_lock, flags); | 944 | spin_lock_irqsave(&wl->wl_lock, flags); |
@@ -2719,7 +2722,8 @@ struct ieee80211_hw *wl1271_alloc_hw(void) | |||
2719 | wl->hw = hw; | 2722 | wl->hw = hw; |
2720 | wl->plat_dev = plat_dev; | 2723 | wl->plat_dev = plat_dev; |
2721 | 2724 | ||
2722 | skb_queue_head_init(&wl->tx_queue); | 2725 | for (i = 0; i < NUM_TX_QUEUES; i++) |
2726 | skb_queue_head_init(&wl->tx_queue[i]); | ||
2723 | 2727 | ||
2724 | INIT_DELAYED_WORK(&wl->elp_work, wl1271_elp_work); | 2728 | INIT_DELAYED_WORK(&wl->elp_work, wl1271_elp_work); |
2725 | INIT_DELAYED_WORK(&wl->pspoll_work, wl1271_pspoll_work); | 2729 | INIT_DELAYED_WORK(&wl->pspoll_work, wl1271_pspoll_work); |
diff --git a/drivers/net/wireless/wl12xx/tx.c b/drivers/net/wireless/wl12xx/tx.c index d332b3f6d0fa..b44c75cd8c1e 100644 --- a/drivers/net/wireless/wl12xx/tx.c +++ b/drivers/net/wireless/wl12xx/tx.c | |||
@@ -125,7 +125,6 @@ static void wl1271_tx_fill_hdr(struct wl1271 *wl, struct sk_buff *skb, | |||
125 | /* queue (we use same identifiers for tid's and ac's */ | 125 | /* queue (we use same identifiers for tid's and ac's */ |
126 | ac = wl1271_tx_get_queue(skb_get_queue_mapping(skb)); | 126 | ac = wl1271_tx_get_queue(skb_get_queue_mapping(skb)); |
127 | desc->tid = ac; | 127 | desc->tid = ac; |
128 | |||
129 | desc->aid = TX_HW_DEFAULT_AID; | 128 | desc->aid = TX_HW_DEFAULT_AID; |
130 | desc->reserved = 0; | 129 | desc->reserved = 0; |
131 | 130 | ||
@@ -228,7 +227,7 @@ static void handle_tx_low_watermark(struct wl1271 *wl) | |||
228 | unsigned long flags; | 227 | unsigned long flags; |
229 | 228 | ||
230 | if (test_bit(WL1271_FLAG_TX_QUEUE_STOPPED, &wl->flags) && | 229 | if (test_bit(WL1271_FLAG_TX_QUEUE_STOPPED, &wl->flags) && |
231 | skb_queue_len(&wl->tx_queue) <= WL1271_TX_QUEUE_LOW_WATERMARK) { | 230 | wl->tx_queue_count <= WL1271_TX_QUEUE_LOW_WATERMARK) { |
232 | /* firmware buffer has space, restart queues */ | 231 | /* firmware buffer has space, restart queues */ |
233 | spin_lock_irqsave(&wl->wl_lock, flags); | 232 | spin_lock_irqsave(&wl->wl_lock, flags); |
234 | ieee80211_wake_queues(wl->hw); | 233 | ieee80211_wake_queues(wl->hw); |
@@ -237,6 +236,43 @@ static void handle_tx_low_watermark(struct wl1271 *wl) | |||
237 | } | 236 | } |
238 | } | 237 | } |
239 | 238 | ||
239 | static struct sk_buff *wl1271_skb_dequeue(struct wl1271 *wl) | ||
240 | { | ||
241 | struct sk_buff *skb = NULL; | ||
242 | unsigned long flags; | ||
243 | |||
244 | skb = skb_dequeue(&wl->tx_queue[CONF_TX_AC_VO]); | ||
245 | if (skb) | ||
246 | goto out; | ||
247 | skb = skb_dequeue(&wl->tx_queue[CONF_TX_AC_VI]); | ||
248 | if (skb) | ||
249 | goto out; | ||
250 | skb = skb_dequeue(&wl->tx_queue[CONF_TX_AC_BE]); | ||
251 | if (skb) | ||
252 | goto out; | ||
253 | skb = skb_dequeue(&wl->tx_queue[CONF_TX_AC_BK]); | ||
254 | |||
255 | out: | ||
256 | if (skb) { | ||
257 | spin_lock_irqsave(&wl->wl_lock, flags); | ||
258 | wl->tx_queue_count--; | ||
259 | spin_unlock_irqrestore(&wl->wl_lock, flags); | ||
260 | } | ||
261 | |||
262 | return skb; | ||
263 | } | ||
264 | |||
265 | static void wl1271_skb_queue_head(struct wl1271 *wl, struct sk_buff *skb) | ||
266 | { | ||
267 | unsigned long flags; | ||
268 | int q = wl1271_tx_get_queue(skb_get_queue_mapping(skb)); | ||
269 | |||
270 | skb_queue_head(&wl->tx_queue[q], skb); | ||
271 | spin_lock_irqsave(&wl->wl_lock, flags); | ||
272 | wl->tx_queue_count++; | ||
273 | spin_unlock_irqrestore(&wl->wl_lock, flags); | ||
274 | } | ||
275 | |||
240 | void wl1271_tx_work_locked(struct wl1271 *wl) | 276 | void wl1271_tx_work_locked(struct wl1271 *wl) |
241 | { | 277 | { |
242 | struct sk_buff *skb; | 278 | struct sk_buff *skb; |
@@ -270,7 +306,7 @@ void wl1271_tx_work_locked(struct wl1271 *wl) | |||
270 | wl1271_acx_rate_policies(wl); | 306 | wl1271_acx_rate_policies(wl); |
271 | } | 307 | } |
272 | 308 | ||
273 | while ((skb = skb_dequeue(&wl->tx_queue))) { | 309 | while ((skb = wl1271_skb_dequeue(wl))) { |
274 | if (!woken_up) { | 310 | if (!woken_up) { |
275 | ret = wl1271_ps_elp_wakeup(wl, false); | 311 | ret = wl1271_ps_elp_wakeup(wl, false); |
276 | if (ret < 0) | 312 | if (ret < 0) |
@@ -284,9 +320,9 @@ void wl1271_tx_work_locked(struct wl1271 *wl) | |||
284 | * Aggregation buffer is full. | 320 | * Aggregation buffer is full. |
285 | * Flush buffer and try again. | 321 | * Flush buffer and try again. |
286 | */ | 322 | */ |
287 | skb_queue_head(&wl->tx_queue, skb); | 323 | wl1271_skb_queue_head(wl, skb); |
288 | wl1271_write(wl, WL1271_SLV_MEM_DATA, wl->aggr_buf, | 324 | wl1271_write(wl, WL1271_SLV_MEM_DATA, wl->aggr_buf, |
289 | buf_offset, true); | 325 | buf_offset, true); |
290 | sent_packets = true; | 326 | sent_packets = true; |
291 | buf_offset = 0; | 327 | buf_offset = 0; |
292 | continue; | 328 | continue; |
@@ -295,7 +331,7 @@ void wl1271_tx_work_locked(struct wl1271 *wl) | |||
295 | * Firmware buffer is full. | 331 | * Firmware buffer is full. |
296 | * Queue back last skb, and stop aggregating. | 332 | * Queue back last skb, and stop aggregating. |
297 | */ | 333 | */ |
298 | skb_queue_head(&wl->tx_queue, skb); | 334 | wl1271_skb_queue_head(wl, skb); |
299 | /* No work left, avoid scheduling redundant tx work */ | 335 | /* No work left, avoid scheduling redundant tx work */ |
300 | set_bit(WL1271_FLAG_FW_TX_BUSY, &wl->flags); | 336 | set_bit(WL1271_FLAG_FW_TX_BUSY, &wl->flags); |
301 | goto out_ack; | 337 | goto out_ack; |
@@ -440,10 +476,13 @@ void wl1271_tx_reset(struct wl1271 *wl) | |||
440 | struct sk_buff *skb; | 476 | struct sk_buff *skb; |
441 | 477 | ||
442 | /* TX failure */ | 478 | /* TX failure */ |
443 | while ((skb = skb_dequeue(&wl->tx_queue))) { | 479 | for (i = 0; i < NUM_TX_QUEUES; i++) { |
444 | wl1271_debug(DEBUG_TX, "freeing skb 0x%p", skb); | 480 | while ((skb = skb_dequeue(&wl->tx_queue[i]))) { |
445 | ieee80211_tx_status(wl->hw, skb); | 481 | wl1271_debug(DEBUG_TX, "freeing skb 0x%p", skb); |
482 | ieee80211_tx_status(wl->hw, skb); | ||
483 | } | ||
446 | } | 484 | } |
485 | wl->tx_queue_count = 0; | ||
447 | 486 | ||
448 | /* | 487 | /* |
449 | * Make sure the driver is at a consistent state, in case this | 488 | * Make sure the driver is at a consistent state, in case this |
@@ -472,8 +511,7 @@ void wl1271_tx_flush(struct wl1271 *wl) | |||
472 | mutex_lock(&wl->mutex); | 511 | mutex_lock(&wl->mutex); |
473 | wl1271_debug(DEBUG_TX, "flushing tx buffer: %d", | 512 | wl1271_debug(DEBUG_TX, "flushing tx buffer: %d", |
474 | wl->tx_frames_cnt); | 513 | wl->tx_frames_cnt); |
475 | if ((wl->tx_frames_cnt == 0) && | 514 | if ((wl->tx_frames_cnt == 0) && (wl->tx_queue_count == 0)) { |
476 | skb_queue_empty(&wl->tx_queue)) { | ||
477 | mutex_unlock(&wl->mutex); | 515 | mutex_unlock(&wl->mutex); |
478 | return; | 516 | return; |
479 | } | 517 | } |
diff --git a/drivers/net/wireless/wl12xx/wl12xx.h b/drivers/net/wireless/wl12xx/wl12xx.h index 07c2297b89a2..ce3d31f98c55 100644 --- a/drivers/net/wireless/wl12xx/wl12xx.h +++ b/drivers/net/wireless/wl12xx/wl12xx.h | |||
@@ -292,7 +292,8 @@ struct wl1271 { | |||
292 | int session_counter; | 292 | int session_counter; |
293 | 293 | ||
294 | /* Frames scheduled for transmission, not handled yet */ | 294 | /* Frames scheduled for transmission, not handled yet */ |
295 | struct sk_buff_head tx_queue; | 295 | struct sk_buff_head tx_queue[NUM_TX_QUEUES]; |
296 | int tx_queue_count; | ||
296 | 297 | ||
297 | struct work_struct tx_work; | 298 | struct work_struct tx_work; |
298 | 299 | ||