aboutsummaryrefslogtreecommitdiffstats
path: root/drivers/net/wireless/wl12xx/wl1271_tx.c
diff options
context:
space:
mode:
authorJuuso Oikarinen <juuso.oikarinen@nokia.com>2010-05-24 04:18:17 -0400
committerJohn W. Linville <linville@tuxdriver.com>2010-06-02 16:13:35 -0400
commit781608c41386b560b501404233fc43d8ef100c71 (patch)
treec6e4e60c7cb9298afdd5f1e92696dc49a877bcf1 /drivers/net/wireless/wl12xx/wl1271_tx.c
parent0d58cbff2495fda8b2389719d30da694d3077a87 (diff)
wl1271: Flush TX buffers to air before going to idle
The mac80211 changes to idle almost immediately after transmitting some frames, such as deauth etc. When going to idle, the wl1271 is disconnected, which causes TX frames already on buffers, but not yet transmitted, to be deleted. To make sure deauth frames reach the air, allow the TX buffers to flush before proceeding to idle. Signed-off-by: Juuso Oikarinen <juuso.oikarinen@nokia.com> Reviewed-by: Teemu Paasikivi <ext-teemu.3.paasikivi@nokia.com> Signed-off-by: Luciano Coelho <luciano.coelho@nokia.com> Signed-off-by: John W. Linville <linville@tuxdriver.com>
Diffstat (limited to 'drivers/net/wireless/wl12xx/wl1271_tx.c')
-rw-r--r--drivers/net/wireless/wl12xx/wl1271_tx.c36
1 files changed, 33 insertions, 3 deletions
diff --git a/drivers/net/wireless/wl12xx/wl1271_tx.c b/drivers/net/wireless/wl12xx/wl1271_tx.c
index 62db79508ddf..c592cc2e9fe8 100644
--- a/drivers/net/wireless/wl12xx/wl1271_tx.c
+++ b/drivers/net/wireless/wl12xx/wl1271_tx.c
@@ -36,6 +36,7 @@ static int wl1271_tx_id(struct wl1271 *wl, struct sk_buff *skb)
36 for (i = 0; i < ACX_TX_DESCRIPTORS; i++) 36 for (i = 0; i < ACX_TX_DESCRIPTORS; i++)
37 if (wl->tx_frames[i] == NULL) { 37 if (wl->tx_frames[i] == NULL) {
38 wl->tx_frames[i] = skb; 38 wl->tx_frames[i] = skb;
39 wl->tx_frames_cnt++;
39 return i; 40 return i;
40 } 41 }
41 42
@@ -73,8 +74,10 @@ static int wl1271_tx_allocate(struct wl1271 *wl, struct sk_buff *skb, u32 extra)
73 wl1271_debug(DEBUG_TX, 74 wl1271_debug(DEBUG_TX,
74 "tx_allocate: size: %d, blocks: %d, id: %d", 75 "tx_allocate: size: %d, blocks: %d, id: %d",
75 total_len, total_blocks, id); 76 total_len, total_blocks, id);
76 } else 77 } else {
77 wl->tx_frames[id] = NULL; 78 wl->tx_frames[id] = NULL;
79 wl->tx_frames_cnt--;
80 }
78 81
79 return ret; 82 return ret;
80} 83}
@@ -358,6 +361,7 @@ static void wl1271_tx_complete_packet(struct wl1271 *wl,
358 /* return the packet to the stack */ 361 /* return the packet to the stack */
359 ieee80211_tx_status(wl->hw, skb); 362 ieee80211_tx_status(wl->hw, skb);
360 wl->tx_frames[result->id] = NULL; 363 wl->tx_frames[result->id] = NULL;
364 wl->tx_frames_cnt--;
361} 365}
362 366
363/* Called upon reception of a TX complete interrupt */ 367/* Called upon reception of a TX complete interrupt */
@@ -412,7 +416,7 @@ void wl1271_tx_complete(struct wl1271 *wl)
412} 416}
413 417
414/* caller must hold wl->mutex */ 418/* caller must hold wl->mutex */
415void wl1271_tx_flush(struct wl1271 *wl) 419void wl1271_tx_reset(struct wl1271 *wl)
416{ 420{
417 int i; 421 int i;
418 struct sk_buff *skb; 422 struct sk_buff *skb;
@@ -421,7 +425,7 @@ void wl1271_tx_flush(struct wl1271 *wl)
421/* control->flags = 0; FIXME */ 425/* control->flags = 0; FIXME */
422 426
423 while ((skb = skb_dequeue(&wl->tx_queue))) { 427 while ((skb = skb_dequeue(&wl->tx_queue))) {
424 wl1271_debug(DEBUG_TX, "flushing skb 0x%p", skb); 428 wl1271_debug(DEBUG_TX, "freeing skb 0x%p", skb);
425 ieee80211_tx_status(wl->hw, skb); 429 ieee80211_tx_status(wl->hw, skb);
426 } 430 }
427 431
@@ -429,6 +433,32 @@ void wl1271_tx_flush(struct wl1271 *wl)
429 if (wl->tx_frames[i] != NULL) { 433 if (wl->tx_frames[i] != NULL) {
430 skb = wl->tx_frames[i]; 434 skb = wl->tx_frames[i];
431 wl->tx_frames[i] = NULL; 435 wl->tx_frames[i] = NULL;
436 wl1271_debug(DEBUG_TX, "freeing skb 0x%p", skb);
432 ieee80211_tx_status(wl->hw, skb); 437 ieee80211_tx_status(wl->hw, skb);
433 } 438 }
439 wl->tx_frames_cnt = 0;
440}
441
442#define WL1271_TX_FLUSH_TIMEOUT 500000
443
444/* caller must *NOT* hold wl->mutex */
445void wl1271_tx_flush(struct wl1271 *wl)
446{
447 unsigned long timeout;
448 timeout = jiffies + usecs_to_jiffies(WL1271_TX_FLUSH_TIMEOUT);
449
450 while (!time_after(jiffies, timeout)) {
451 mutex_lock(&wl->mutex);
452 wl1271_debug(DEBUG_TX, "flushing tx buffer: %d",
453 wl->tx_frames_cnt);
454 if ((wl->tx_frames_cnt == 0) &&
455 skb_queue_empty(&wl->tx_queue)) {
456 mutex_unlock(&wl->mutex);
457 return;
458 }
459 mutex_unlock(&wl->mutex);
460 msleep(1);
461 }
462
463 wl1271_warning("Unable to flush all TX buffers, timed out.");
434} 464}