summaryrefslogtreecommitdiff
path: root/drivers/net/wireless/wl12xx/wl1271_tx.c
diff options
context:
space:
mode:
Diffstat (limited to 'drivers/net/wireless/wl12xx/wl1271_tx.c')
-rw-r--r--drivers/net/wireless/wl12xx/wl1271_tx.c40
1 files changed, 35 insertions, 5 deletions
diff --git a/drivers/net/wireless/wl12xx/wl1271_tx.c b/drivers/net/wireless/wl12xx/wl1271_tx.c
index 62db79508ddf..dc0b46c93c4b 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)
for (i = 0; i < ACX_TX_DESCRIPTORS; i++)
if (wl->tx_frames[i] == NULL) {
wl->tx_frames[i] = skb;
+ wl->tx_frames_cnt++;
return i;
}
@@ -73,8 +74,10 @@ static int wl1271_tx_allocate(struct wl1271 *wl, struct sk_buff *skb, u32 extra)
wl1271_debug(DEBUG_TX,
"tx_allocate: size: %d, blocks: %d, id: %d",
total_len, total_blocks, id);
- } else
+ } else {
wl->tx_frames[id] = NULL;
+ wl->tx_frames_cnt--;
+ }
return ret;
}
@@ -190,7 +193,7 @@ static int wl1271_tx_frame(struct wl1271 *wl, struct sk_buff *skb)
info = IEEE80211_SKB_CB(skb);
if (info->control.hw_key &&
- info->control.hw_key->alg == ALG_TKIP)
+ info->control.hw_key->cipher == WLAN_CIPHER_SUITE_TKIP)
extra = WL1271_TKIP_IV_SPACE;
if (info->control.hw_key) {
@@ -344,7 +347,7 @@ static void wl1271_tx_complete_packet(struct wl1271 *wl,
/* remove TKIP header space if present */
if (info->control.hw_key &&
- info->control.hw_key->alg == ALG_TKIP) {
+ info->control.hw_key->cipher == WLAN_CIPHER_SUITE_TKIP) {
int hdrlen = ieee80211_get_hdrlen_from_skb(skb);
memmove(skb->data + WL1271_TKIP_IV_SPACE, skb->data, hdrlen);
skb_pull(skb, WL1271_TKIP_IV_SPACE);
@@ -358,6 +361,7 @@ static void wl1271_tx_complete_packet(struct wl1271 *wl,
/* return the packet to the stack */
ieee80211_tx_status(wl->hw, skb);
wl->tx_frames[result->id] = NULL;
+ wl->tx_frames_cnt--;
}
/* Called upon reception of a TX complete interrupt */
@@ -412,7 +416,7 @@ void wl1271_tx_complete(struct wl1271 *wl)
}
/* caller must hold wl->mutex */
-void wl1271_tx_flush(struct wl1271 *wl)
+void wl1271_tx_reset(struct wl1271 *wl)
{
int i;
struct sk_buff *skb;
@@ -421,7 +425,7 @@ void wl1271_tx_flush(struct wl1271 *wl)
/* control->flags = 0; FIXME */
while ((skb = skb_dequeue(&wl->tx_queue))) {
- wl1271_debug(DEBUG_TX, "flushing skb 0x%p", skb);
+ wl1271_debug(DEBUG_TX, "freeing skb 0x%p", skb);
ieee80211_tx_status(wl->hw, skb);
}
@@ -429,6 +433,32 @@ void wl1271_tx_flush(struct wl1271 *wl)
if (wl->tx_frames[i] != NULL) {
skb = wl->tx_frames[i];
wl->tx_frames[i] = NULL;
+ wl1271_debug(DEBUG_TX, "freeing skb 0x%p", skb);
ieee80211_tx_status(wl->hw, skb);
}
+ wl->tx_frames_cnt = 0;
+}
+
+#define WL1271_TX_FLUSH_TIMEOUT 500000
+
+/* caller must *NOT* hold wl->mutex */
+void wl1271_tx_flush(struct wl1271 *wl)
+{
+ unsigned long timeout;
+ timeout = jiffies + usecs_to_jiffies(WL1271_TX_FLUSH_TIMEOUT);
+
+ while (!time_after(jiffies, timeout)) {
+ mutex_lock(&wl->mutex);
+ wl1271_debug(DEBUG_TX, "flushing tx buffer: %d",
+ wl->tx_frames_cnt);
+ if ((wl->tx_frames_cnt == 0) &&
+ skb_queue_empty(&wl->tx_queue)) {
+ mutex_unlock(&wl->mutex);
+ return;
+ }
+ mutex_unlock(&wl->mutex);
+ msleep(1);
+ }
+
+ wl1271_warning("Unable to flush all TX buffers, timed out.");
}