diff options
-rw-r--r-- | net/mac80211/agg-tx.c | 95 |
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 | ||
126 | static 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 | |||
177 | timer_expired_exit: | ||
178 | rcu_read_unlock(); | ||
179 | } | 191 | } |
180 | 192 | ||
181 | int ieee80211_start_tx_ba_session(struct ieee80211_hw *hw, u8 *ra, u16 tid) | 193 | int 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 | |||
468 | stop_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 | } |
473 | EXPORT_SYMBOL(ieee80211_stop_tx_ba_session); | 476 | EXPORT_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 | } |