Skip to content

Commit

Permalink
---
Browse files Browse the repository at this point in the history
yaml
---
r: 202785
b: refs/heads/master
c: 781608c
h: refs/heads/master
i:
  202783: 975409c
v: v3
  • Loading branch information
Juuso Oikarinen authored and John W. Linville committed Jun 2, 2010
1 parent 0cdd020 commit fa26d45
Show file tree
Hide file tree
Showing 5 changed files with 46 additions and 5 deletions.
2 changes: 1 addition & 1 deletion [refs]
Original file line number Diff line number Diff line change
@@ -1,2 +1,2 @@
---
refs/heads/master: 0d58cbff2495fda8b2389719d30da694d3077a87
refs/heads/master: 781608c41386b560b501404233fc43d8ef100c71
1 change: 1 addition & 0 deletions trunk/drivers/net/wireless/wl12xx/wl1271.h
Original file line number Diff line number Diff line change
Expand Up @@ -396,6 +396,7 @@ struct wl1271 {

/* Pending TX frames */
struct sk_buff *tx_frames[ACX_TX_DESCRIPTORS];
int tx_frames_cnt;

/* Security sequence number counters */
u8 tx_security_last_seq;
Expand Down
11 changes: 10 additions & 1 deletion trunk/drivers/net/wireless/wl12xx/wl1271_main.c
Original file line number Diff line number Diff line change
Expand Up @@ -1051,7 +1051,7 @@ static void wl1271_op_remove_interface(struct ieee80211_hw *hw,
mutex_lock(&wl->mutex);

/* let's notify MAC80211 about the remaining pending TX frames */
wl1271_tx_flush(wl);
wl1271_tx_reset(wl);
wl1271_power_off(wl);

memset(wl->bssid, 0, ETH_ALEN);
Expand Down Expand Up @@ -1298,6 +1298,15 @@ static int wl1271_op_config(struct ieee80211_hw *hw, u32 changed)
conf->power_level,
conf->flags & IEEE80211_CONF_IDLE ? "idle" : "in use");

/*
* mac80211 will go to idle nearly immediately after transmitting some
* frames, such as the deauth. To make sure those frames reach the air,
* wait here until the TX queue is fully flushed.
*/
if ((changed & IEEE80211_CONF_CHANGE_IDLE) &&
(conf->flags & IEEE80211_CONF_IDLE))
wl1271_tx_flush(wl);

mutex_lock(&wl->mutex);

if (unlikely(wl->state == WL1271_STATE_OFF))
Expand Down
36 changes: 33 additions & 3 deletions trunk/drivers/net/wireless/wl12xx/wl1271_tx.c
Original file line number Diff line number Diff line change
Expand Up @@ -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;
}

Expand Down Expand Up @@ -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;
}
Expand Down Expand Up @@ -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 */
Expand Down Expand Up @@ -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;
Expand All @@ -421,14 +425,40 @@ 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);
}

for (i = 0; i < ACX_TX_DESCRIPTORS; i++)
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.");
}
1 change: 1 addition & 0 deletions trunk/drivers/net/wireless/wl12xx/wl1271_tx.h
Original file line number Diff line number Diff line change
Expand Up @@ -158,6 +158,7 @@ static inline int wl1271_tx_ac_to_tid(int ac)

void wl1271_tx_work(struct work_struct *work);
void wl1271_tx_complete(struct wl1271 *wl);
void wl1271_tx_reset(struct wl1271 *wl);
void wl1271_tx_flush(struct wl1271 *wl);
u8 wl1271_rate_to_idx(struct wl1271 *wl, int rate);
u32 wl1271_tx_enabled_rates_get(struct wl1271 *wl, u32 rate_set);
Expand Down

0 comments on commit fa26d45

Please sign in to comment.