aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--net/mac80211/agg-tx.c95
1 files changed, 48 insertions, 47 deletions
diff --git a/net/mac80211/agg-tx.c b/net/mac80211/agg-tx.c
index 61bb7db04808..a49b76f61da3 100644
--- a/net/mac80211/agg-tx.c
+++ b/net/mac80211/agg-tx.c
@@ -123,6 +123,34 @@ void ieee80211_send_bar(struct ieee80211_sub_if_data *sdata, u8 *ra, u16 tid, u1
123 ieee80211_tx_skb(sdata, skb, 0); 123 ieee80211_tx_skb(sdata, skb, 0);
124} 124}
125 125
126static int __ieee80211_stop_tx_ba_session(struct ieee80211_local *local,
127 struct sta_info *sta, u16 tid,
128 enum ieee80211_back_parties initiator)
129{
130 int ret;
131 u8 *state;
132
133 state = &sta->ampdu_mlme.tid_state_tx[tid];
134
135 if (local->hw.ampdu_queues)
136 ieee80211_stop_queue(&local->hw, sta->tid_to_tx_q[tid]);
137
138 *state = HT_AGG_STATE_REQ_STOP_BA_MSK |
139 (initiator << HT_AGG_STATE_INITIATOR_SHIFT);
140
141 ret = local->ops->ampdu_action(&local->hw, IEEE80211_AMPDU_TX_STOP,
142 &sta->sta, tid, NULL);
143
144 /* HW shall not deny going back to legacy */
145 if (WARN_ON(ret)) {
146 *state = HT_AGG_STATE_OPERATIONAL;
147 if (local->hw.ampdu_queues)
148 ieee80211_wake_queue(&local->hw, sta->tid_to_tx_q[tid]);
149 }
150
151 return ret;
152}
153
126/* 154/*
127 * After sending add Block Ack request we activated a timer until 155 * After sending add Block Ack request we activated a timer until
128 * add Block Ack response will arrive from the recipient. 156 * add Block Ack response will arrive from the recipient.
@@ -135,23 +163,13 @@ static void sta_addba_resp_timer_expired(unsigned long data)
135 * flow in sta_info_create gives the TID as data, while the timer_to_id 163 * flow in sta_info_create gives the TID as data, while the timer_to_id
136 * array gives the sta through container_of */ 164 * array gives the sta through container_of */
137 u16 tid = *(u8 *)data; 165 u16 tid = *(u8 *)data;
138 struct sta_info *temp_sta = container_of((void *)data, 166 struct sta_info *sta = container_of((void *)data,
139 struct sta_info, timer_to_tid[tid]); 167 struct sta_info, timer_to_tid[tid]);
140 168 struct ieee80211_local *local = sta->local;
141 struct ieee80211_local *local = temp_sta->local;
142 struct ieee80211_hw *hw = &local->hw;
143 struct sta_info *sta;
144 u8 *state; 169 u8 *state;
145 170
146 rcu_read_lock();
147
148 sta = sta_info_get(local, temp_sta->sta.addr);
149 if (!sta) {
150 rcu_read_unlock();
151 return;
152 }
153
154 state = &sta->ampdu_mlme.tid_state_tx[tid]; 171 state = &sta->ampdu_mlme.tid_state_tx[tid];
172
155 /* check if the TID waits for addBA response */ 173 /* check if the TID waits for addBA response */
156 spin_lock_bh(&sta->lock); 174 spin_lock_bh(&sta->lock);
157 if (!(*state & HT_ADDBA_REQUESTED_MSK)) { 175 if (!(*state & HT_ADDBA_REQUESTED_MSK)) {
@@ -161,21 +179,15 @@ static void sta_addba_resp_timer_expired(unsigned long data)
161 printk(KERN_DEBUG "timer expired on tid %d but we are not " 179 printk(KERN_DEBUG "timer expired on tid %d but we are not "
162 "expecting addBA response there", tid); 180 "expecting addBA response there", tid);
163#endif 181#endif
164 goto timer_expired_exit; 182 return;
165 } 183 }
166 184
167#ifdef CONFIG_MAC80211_HT_DEBUG 185#ifdef CONFIG_MAC80211_HT_DEBUG
168 printk(KERN_DEBUG "addBA response timer expired on tid %d\n", tid); 186 printk(KERN_DEBUG "addBA response timer expired on tid %d\n", tid);
169#endif 187#endif
170 188
171 /* go through the state check in stop_BA_session */ 189 __ieee80211_stop_tx_ba_session(local, sta, tid, WLAN_BACK_INITIATOR);
172 *state = HT_AGG_STATE_OPERATIONAL;
173 spin_unlock_bh(&sta->lock); 190 spin_unlock_bh(&sta->lock);
174 ieee80211_stop_tx_ba_session(hw, temp_sta->sta.addr, tid,
175 WLAN_BACK_INITIATOR);
176
177timer_expired_exit:
178 rcu_read_unlock();
179} 191}
180 192
181int ieee80211_start_tx_ba_session(struct ieee80211_hw *hw, u8 *ra, u16 tid) 193int ieee80211_start_tx_ba_session(struct ieee80211_hw *hw, u8 *ra, u16 tid)
@@ -187,6 +199,9 @@ int ieee80211_start_tx_ba_session(struct ieee80211_hw *hw, u8 *ra, u16 tid)
187 u8 *state; 199 u8 *state;
188 int ret = 0; 200 int ret = 0;
189 201
202 if (WARN_ON(!local->ops->ampdu_action))
203 return -EINVAL;
204
190 if ((tid >= STA_TID_NUM) || !(hw->flags & IEEE80211_HW_AMPDU_AGGREGATION)) 205 if ((tid >= STA_TID_NUM) || !(hw->flags & IEEE80211_HW_AMPDU_AGGREGATION))
191 return -EINVAL; 206 return -EINVAL;
192 207
@@ -280,9 +295,8 @@ int ieee80211_start_tx_ba_session(struct ieee80211_hw *hw, u8 *ra, u16 tid)
280 /* This is slightly racy because the queue isn't stopped */ 295 /* This is slightly racy because the queue isn't stopped */
281 start_seq_num = sta->tid_seq[tid]; 296 start_seq_num = sta->tid_seq[tid];
282 297
283 if (local->ops->ampdu_action) 298 ret = local->ops->ampdu_action(hw, IEEE80211_AMPDU_TX_START,
284 ret = local->ops->ampdu_action(hw, IEEE80211_AMPDU_TX_START, 299 &sta->sta, tid, &start_seq_num);
285 &sta->sta, tid, &start_seq_num);
286 300
287 if (ret) { 301 if (ret) {
288 /* No need to requeue the packets in the agg queue, since we 302 /* No need to requeue the packets in the agg queue, since we
@@ -423,6 +437,9 @@ int ieee80211_stop_tx_ba_session(struct ieee80211_hw *hw,
423 u8 *state; 437 u8 *state;
424 int ret = 0; 438 int ret = 0;
425 439
440 if (WARN_ON(!local->ops->ampdu_action))
441 return -EINVAL;
442
426 if (tid >= STA_TID_NUM) 443 if (tid >= STA_TID_NUM)
427 return -EINVAL; 444 return -EINVAL;
428 445
@@ -439,7 +456,7 @@ int ieee80211_stop_tx_ba_session(struct ieee80211_hw *hw,
439 456
440 if (*state != HT_AGG_STATE_OPERATIONAL) { 457 if (*state != HT_AGG_STATE_OPERATIONAL) {
441 ret = -ENOENT; 458 ret = -ENOENT;
442 goto stop_BA_exit; 459 goto unlock;
443 } 460 }
444 461
445#ifdef CONFIG_MAC80211_HT_DEBUG 462#ifdef CONFIG_MAC80211_HT_DEBUG
@@ -447,27 +464,13 @@ int ieee80211_stop_tx_ba_session(struct ieee80211_hw *hw,
447 ra, tid); 464 ra, tid);
448#endif /* CONFIG_MAC80211_HT_DEBUG */ 465#endif /* CONFIG_MAC80211_HT_DEBUG */
449 466
450 if (hw->ampdu_queues) 467 ret = __ieee80211_stop_tx_ba_session(local, sta, tid, initiator);
451 ieee80211_stop_queue(hw, sta->tid_to_tx_q[tid]);
452
453 *state = HT_AGG_STATE_REQ_STOP_BA_MSK |
454 (initiator << HT_AGG_STATE_INITIATOR_SHIFT);
455 468
456 if (local->ops->ampdu_action) 469 unlock:
457 ret = local->ops->ampdu_action(hw, IEEE80211_AMPDU_TX_STOP,
458 &sta->sta, tid, NULL);
459
460 /* HW shall not deny going back to legacy */
461 if (WARN_ON(ret)) {
462 *state = HT_AGG_STATE_OPERATIONAL;
463 if (hw->ampdu_queues)
464 ieee80211_wake_queue(hw, sta->tid_to_tx_q[tid]);
465 goto stop_BA_exit;
466 }
467
468stop_BA_exit:
469 spin_unlock_bh(&sta->lock); 470 spin_unlock_bh(&sta->lock);
471
470 rcu_read_unlock(); 472 rcu_read_unlock();
473
471 return ret; 474 return ret;
472} 475}
473EXPORT_SYMBOL(ieee80211_stop_tx_ba_session); 476EXPORT_SYMBOL(ieee80211_stop_tx_ba_session);
@@ -623,10 +626,8 @@ void ieee80211_process_addba_resp(struct ieee80211_local *local,
623 spin_unlock_bh(&sta->lock); 626 spin_unlock_bh(&sta->lock);
624 } else { 627 } else {
625 sta->ampdu_mlme.addba_req_num[tid]++; 628 sta->ampdu_mlme.addba_req_num[tid]++;
626 /* this will allow the state check in stop_BA_session */ 629 __ieee80211_stop_tx_ba_session(local, sta, tid,
627 *state = HT_AGG_STATE_OPERATIONAL; 630 WLAN_BACK_INITIATOR);
628 spin_unlock_bh(&sta->lock); 631 spin_unlock_bh(&sta->lock);
629 ieee80211_stop_tx_ba_session(hw, sta->sta.addr, tid,
630 WLAN_BACK_INITIATOR);
631 } 632 }
632} 633}