Skip to content

Commit

Permalink
---
Browse files Browse the repository at this point in the history
yaml
---
r: 194216
b: refs/heads/master
c: 098a607
h: refs/heads/master
v: v3
  • Loading branch information
Johannes Berg authored and John W. Linville committed Apr 7, 2010
1 parent 49246ae commit 03255d7
Show file tree
Hide file tree
Showing 7 changed files with 41 additions and 89 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: 618f356b95e37ca0c30b3b513898fda54abd52a6
refs/heads/master: 098a607091426e79178b9a6c318d993fea131791
1 change: 0 additions & 1 deletion trunk/include/linux/ieee80211.h
Original file line number Diff line number Diff line change
Expand Up @@ -1324,7 +1324,6 @@ enum ieee80211_back_actioncode {
enum ieee80211_back_parties {
WLAN_BACK_RECIPIENT = 0,
WLAN_BACK_INITIATOR = 1,
WLAN_BACK_TIMER = 2,
};

/* SA Query action */
Expand Down
48 changes: 21 additions & 27 deletions trunk/net/mac80211/agg-rx.c
Original file line number Diff line number Diff line change
Expand Up @@ -22,19 +22,20 @@ void __ieee80211_stop_rx_ba_session(struct sta_info *sta, u16 tid,
u16 initiator, u16 reason)
{
struct ieee80211_local *local = sta->local;
struct tid_ampdu_rx *tid_rx;
int i;

/* check if TID is in operational state */
spin_lock_bh(&sta->lock);
if (sta->ampdu_mlme.tid_state_rx[tid] != HT_AGG_STATE_OPERATIONAL) {

/* check if TID is in operational state */
if (!sta->ampdu_mlme.tid_active_rx[tid]) {
spin_unlock_bh(&sta->lock);
return;
}

sta->ampdu_mlme.tid_state_rx[tid] =
HT_AGG_STATE_REQ_STOP_BA_MSK |
(initiator << HT_AGG_STATE_INITIATOR_SHIFT);
spin_unlock_bh(&sta->lock);
sta->ampdu_mlme.tid_active_rx[tid] = false;

tid_rx = sta->ampdu_mlme.tid_rx[tid];

#ifdef CONFIG_MAC80211_HT_DEBUG
printk(KERN_DEBUG "Rx BA session stop requested for %pM tid %u\n",
Expand All @@ -46,37 +47,30 @@ void __ieee80211_stop_rx_ba_session(struct sta_info *sta, u16 tid,
printk(KERN_DEBUG "HW problem - can not stop rx "
"aggregation for tid %d\n", tid);

/* shutdown timer has not expired */
if (initiator != WLAN_BACK_TIMER)
del_timer_sync(&sta->ampdu_mlme.tid_rx[tid]->session_timer);

/* check if this is a self generated aggregation halt */
if (initiator == WLAN_BACK_RECIPIENT || initiator == WLAN_BACK_TIMER)
if (initiator == WLAN_BACK_RECIPIENT)
ieee80211_send_delba(sta->sdata, sta->sta.addr,
tid, 0, reason);

/* free the reordering buffer */
for (i = 0; i < sta->ampdu_mlme.tid_rx[tid]->buf_size; i++) {
if (sta->ampdu_mlme.tid_rx[tid]->reorder_buf[i]) {
for (i = 0; i < tid_rx->buf_size; i++) {
if (tid_rx->reorder_buf[i]) {
/* release the reordered frames */
dev_kfree_skb(sta->ampdu_mlme.tid_rx[tid]->reorder_buf[i]);
sta->ampdu_mlme.tid_rx[tid]->stored_mpdu_num--;
sta->ampdu_mlme.tid_rx[tid]->reorder_buf[i] = NULL;
dev_kfree_skb(tid_rx->reorder_buf[i]);
tid_rx->stored_mpdu_num--;
tid_rx->reorder_buf[i] = NULL;
}
}

spin_lock_bh(&sta->lock);
/* free resources */
kfree(sta->ampdu_mlme.tid_rx[tid]->reorder_buf);
kfree(sta->ampdu_mlme.tid_rx[tid]->reorder_time);

if (!sta->ampdu_mlme.tid_rx[tid]->shutdown) {
kfree(sta->ampdu_mlme.tid_rx[tid]);
sta->ampdu_mlme.tid_rx[tid] = NULL;
}
kfree(tid_rx->reorder_buf);
kfree(tid_rx->reorder_time);
sta->ampdu_mlme.tid_rx[tid] = NULL;

sta->ampdu_mlme.tid_state_rx[tid] = HT_AGG_STATE_IDLE;
spin_unlock_bh(&sta->lock);

del_timer_sync(&tid_rx->session_timer);
kfree(tid_rx);
}

/*
Expand Down Expand Up @@ -211,7 +205,7 @@ void ieee80211_process_addba_request(struct ieee80211_local *local,
/* examine state machine */
spin_lock_bh(&sta->lock);

if (sta->ampdu_mlme.tid_state_rx[tid] != HT_AGG_STATE_IDLE) {
if (sta->ampdu_mlme.tid_active_rx[tid]) {
#ifdef CONFIG_MAC80211_HT_DEBUG
if (net_ratelimit())
printk(KERN_DEBUG "unexpected AddBA Req from "
Expand Down Expand Up @@ -273,7 +267,7 @@ void ieee80211_process_addba_request(struct ieee80211_local *local,
}

/* change state and send addba resp */
sta->ampdu_mlme.tid_state_rx[tid] = HT_AGG_STATE_OPERATIONAL;
sta->ampdu_mlme.tid_active_rx[tid] = true;
tid_agg_rx->dialog_token = dialog_token;
tid_agg_rx->ssn = start_seq_num;
tid_agg_rx->head_seq_num = start_seq_num;
Expand Down
10 changes: 5 additions & 5 deletions trunk/net/mac80211/debugfs_sta.c
Original file line number Diff line number Diff line change
Expand Up @@ -119,24 +119,24 @@ STA_OPS(last_seq_ctrl);
static ssize_t sta_agg_status_read(struct file *file, char __user *userbuf,
size_t count, loff_t *ppos)
{
char buf[64 + STA_TID_NUM * 40], *p = buf;
char buf[71 + STA_TID_NUM * 40], *p = buf;
int i;
struct sta_info *sta = file->private_data;

spin_lock_bh(&sta->lock);
p += scnprintf(p, sizeof(buf) + buf - p, "next dialog_token: %#02x\n",
sta->ampdu_mlme.dialog_token_allocator + 1);
p += scnprintf(p, sizeof(buf) + buf - p,
"TID\t\tRX\tDTKN\tSSN\t\tTX\tDTKN\tSSN\tpending\n");
"TID\t\tRX active\tDTKN\tSSN\t\tTX\tDTKN\tSSN\tpending\n");
for (i = 0; i < STA_TID_NUM; i++) {
p += scnprintf(p, sizeof(buf) + buf - p, "%02d", i);
p += scnprintf(p, sizeof(buf) + buf - p, "\t\t%x",
sta->ampdu_mlme.tid_state_rx[i]);
sta->ampdu_mlme.tid_active_rx[i]);
p += scnprintf(p, sizeof(buf) + buf - p, "\t%#.2x",
sta->ampdu_mlme.tid_state_rx[i] ?
sta->ampdu_mlme.tid_active_rx[i] ?
sta->ampdu_mlme.tid_rx[i]->dialog_token : 0);
p += scnprintf(p, sizeof(buf) + buf - p, "\t%#.3x",
sta->ampdu_mlme.tid_state_rx[i] ?
sta->ampdu_mlme.tid_active_rx[i] ?
sta->ampdu_mlme.tid_rx[i]->ssn : 0);

p += scnprintf(p, sizeof(buf) + buf - p, "\t\t%x",
Expand Down
5 changes: 2 additions & 3 deletions trunk/net/mac80211/rx.c
Original file line number Diff line number Diff line change
Expand Up @@ -720,7 +720,7 @@ static void ieee80211_rx_reorder_ampdu(struct ieee80211_rx_data *rx,

tid = *ieee80211_get_qos_ctl(hdr) & IEEE80211_QOS_CTL_TID_MASK;

if (sta->ampdu_mlme.tid_state_rx[tid] != HT_AGG_STATE_OPERATIONAL)
if (!sta->ampdu_mlme.tid_active_rx[tid])
goto dont_reorder;

tid_agg_rx = sta->ampdu_mlme.tid_rx[tid];
Expand Down Expand Up @@ -1805,8 +1805,7 @@ ieee80211_rx_h_ctrl(struct ieee80211_rx_data *rx, struct sk_buff_head *frames)
if (!rx->sta)
return RX_DROP_MONITOR;
tid = le16_to_cpu(bar->control) >> 12;
if (rx->sta->ampdu_mlme.tid_state_rx[tid]
!= HT_AGG_STATE_OPERATIONAL)
if (!rx->sta->ampdu_mlme.tid_active_rx[tid])
return RX_DROP_MONITOR;
tid_agg_rx = rx->sta->ampdu_mlme.tid_rx[tid];

Expand Down
58 changes: 10 additions & 48 deletions trunk/net/mac80211/sta_info.c
Original file line number Diff line number Diff line change
Expand Up @@ -238,9 +238,6 @@ struct sta_info *sta_info_alloc(struct ieee80211_sub_if_data *sdata,
* enable session_timer's data differentiation. refer to
* sta_rx_agg_session_timer_expired for useage */
sta->timer_to_tid[i] = i;
/* rx */
sta->ampdu_mlme.tid_state_rx[i] = HT_AGG_STATE_IDLE;
sta->ampdu_mlme.tid_rx[i] = NULL;
/* tx */
sta->ampdu_mlme.tid_state_tx[i] = HT_AGG_STATE_IDLE;
sta->ampdu_mlme.tid_tx[i] = NULL;
Expand Down Expand Up @@ -606,7 +603,7 @@ static int __must_check __sta_info_destroy(struct sta_info *sta)
struct ieee80211_sub_if_data *sdata;
struct sk_buff *skb;
unsigned long flags;
int ret, i;
int ret;

might_sleep();

Expand All @@ -616,6 +613,15 @@ static int __must_check __sta_info_destroy(struct sta_info *sta)
local = sta->local;
sdata = sta->sdata;

/*
* Before removing the station from the driver and
* rate control, it might still start new aggregation
* sessions -- block that to make sure the tear-down
* will be sufficient.
*/
set_sta_flags(sta, WLAN_STA_BLOCK_BA);
ieee80211_sta_tear_down_BA_sessions(sta);

spin_lock_irqsave(&local->sta_lock, flags);
ret = sta_info_hash_del(local, sta);
/* this might still be the pending list ... which is fine */
Expand Down Expand Up @@ -700,50 +706,6 @@ static int __must_check __sta_info_destroy(struct sta_info *sta)
while ((skb = skb_dequeue(&sta->tx_filtered)) != NULL)
dev_kfree_skb_any(skb);

for (i = 0; i < STA_TID_NUM; i++) {
struct tid_ampdu_rx *tid_rx;
struct tid_ampdu_tx *tid_tx;

spin_lock_bh(&sta->lock);
tid_rx = sta->ampdu_mlme.tid_rx[i];
/* Make sure timer won't free the tid_rx struct, see below */
if (tid_rx)
tid_rx->shutdown = true;

spin_unlock_bh(&sta->lock);

/*
* Outside spinlock - shutdown is true now so that the timer
* won't free tid_rx, we have to do that now. Can't let the
* timer do it because we have to sync the timer outside the
* lock that it takes itself.
*/
if (tid_rx) {
del_timer_sync(&tid_rx->session_timer);
kfree(tid_rx);
}

/*
* No need to do such complications for TX agg sessions, the
* path leading to freeing the tid_tx struct goes via a call
* from the driver, and thus needs to look up the sta struct
* again, which cannot be found when we get here. Hence, we
* just need to delete the timer and free the aggregation
* info; we won't be telling the peer about it then but that
* doesn't matter if we're not talking to it again anyway.
*/
tid_tx = sta->ampdu_mlme.tid_tx[i];
if (tid_tx) {
del_timer_sync(&tid_tx->addba_resp_timer);
/*
* STA removed while aggregation session being
* started? Bit odd, but purge frames anyway.
*/
skb_queue_purge(&tid_tx->pending);
kfree(tid_tx);
}
}

__sta_info_free(local, sta);

return 0;
Expand Down
6 changes: 2 additions & 4 deletions trunk/net/mac80211/sta_info.h
Original file line number Diff line number Diff line change
Expand Up @@ -36,7 +36,7 @@
* frame to this station is transmitted.
* @WLAN_STA_MFP: Management frame protection is used with this STA.
* @WLAN_STA_BLOCK_BA: Used to deny ADDBA requests (both TX and RX)
* during suspend/resume.
* during suspend/resume and station removal.
* @WLAN_STA_PS_DRIVER: driver requires keeping this station in
* power-save mode logically to flush frames that might still
* be in the queues
Expand Down Expand Up @@ -106,7 +106,6 @@ struct tid_ampdu_tx {
* @buf_size: buffer size for incoming A-MPDUs
* @timeout: reset timer value (in TUs).
* @dialog_token: dialog token for aggregation session
* @shutdown: this session is being shut down due to STA removal
*/
struct tid_ampdu_rx {
struct sk_buff **reorder_buf;
Expand All @@ -118,7 +117,6 @@ struct tid_ampdu_rx {
u16 buf_size;
u16 timeout;
u8 dialog_token;
bool shutdown;
};

/**
Expand Down Expand Up @@ -156,7 +154,7 @@ enum plink_state {
*/
struct sta_ampdu_mlme {
/* rx */
u8 tid_state_rx[STA_TID_NUM];
bool tid_active_rx[STA_TID_NUM];
struct tid_ampdu_rx *tid_rx[STA_TID_NUM];
/* tx */
u8 tid_state_tx[STA_TID_NUM];
Expand Down

0 comments on commit 03255d7

Please sign in to comment.