aboutsummaryrefslogtreecommitdiffstats
path: root/net/mac80211/agg-tx.c
diff options
context:
space:
mode:
Diffstat (limited to 'net/mac80211/agg-tx.c')
-rw-r--r--net/mac80211/agg-tx.c186
1 files changed, 126 insertions, 60 deletions
diff --git a/net/mac80211/agg-tx.c b/net/mac80211/agg-tx.c
index 1232d9f01ca9..0217b68c47ca 100644
--- a/net/mac80211/agg-tx.c
+++ b/net/mac80211/agg-tx.c
@@ -132,9 +132,24 @@ static int ___ieee80211_stop_tx_ba_session(struct sta_info *sta, u16 tid,
132 132
133 state = &sta->ampdu_mlme.tid_state_tx[tid]; 133 state = &sta->ampdu_mlme.tid_state_tx[tid];
134 134
135 if (local->hw.ampdu_queues) 135 if (local->hw.ampdu_queues) {
136 ieee80211_stop_queue(&local->hw, sta->tid_to_tx_q[tid]); 136 if (initiator) {
137 /*
138 * Stop the AC queue to avoid issues where we send
139 * unaggregated frames already before the delba.
140 */
141 ieee80211_stop_queue_by_reason(&local->hw,
142 local->hw.queues + sta->tid_to_tx_q[tid],
143 IEEE80211_QUEUE_STOP_REASON_AGGREGATION);
144 }
137 145
146 /*
147 * Pretend the driver woke the queue, just in case
148 * it disabled it before the session was stopped.
149 */
150 ieee80211_wake_queue(
151 &local->hw, local->hw.queues + sta->tid_to_tx_q[tid]);
152 }
138 *state = HT_AGG_STATE_REQ_STOP_BA_MSK | 153 *state = HT_AGG_STATE_REQ_STOP_BA_MSK |
139 (initiator << HT_AGG_STATE_INITIATOR_SHIFT); 154 (initiator << HT_AGG_STATE_INITIATOR_SHIFT);
140 155
@@ -144,8 +159,6 @@ static int ___ieee80211_stop_tx_ba_session(struct sta_info *sta, u16 tid,
144 /* HW shall not deny going back to legacy */ 159 /* HW shall not deny going back to legacy */
145 if (WARN_ON(ret)) { 160 if (WARN_ON(ret)) {
146 *state = HT_AGG_STATE_OPERATIONAL; 161 *state = HT_AGG_STATE_OPERATIONAL;
147 if (local->hw.ampdu_queues)
148 ieee80211_wake_queue(&local->hw, sta->tid_to_tx_q[tid]);
149 } 162 }
150 163
151 return ret; 164 return ret;
@@ -189,14 +202,19 @@ static void sta_addba_resp_timer_expired(unsigned long data)
189 spin_unlock_bh(&sta->lock); 202 spin_unlock_bh(&sta->lock);
190} 203}
191 204
205static inline int ieee80211_ac_from_tid(int tid)
206{
207 return ieee802_1d_to_ac[tid & 7];
208}
209
192int ieee80211_start_tx_ba_session(struct ieee80211_hw *hw, u8 *ra, u16 tid) 210int ieee80211_start_tx_ba_session(struct ieee80211_hw *hw, u8 *ra, u16 tid)
193{ 211{
194 struct ieee80211_local *local = hw_to_local(hw); 212 struct ieee80211_local *local = hw_to_local(hw);
195 struct sta_info *sta; 213 struct sta_info *sta;
196 struct ieee80211_sub_if_data *sdata; 214 struct ieee80211_sub_if_data *sdata;
197 u16 start_seq_num;
198 u8 *state; 215 u8 *state;
199 int ret = 0; 216 int i, qn = -1, ret = 0;
217 u16 start_seq_num;
200 218
201 if (WARN_ON(!local->ops->ampdu_action)) 219 if (WARN_ON(!local->ops->ampdu_action))
202 return -EINVAL; 220 return -EINVAL;
@@ -209,6 +227,13 @@ int ieee80211_start_tx_ba_session(struct ieee80211_hw *hw, u8 *ra, u16 tid)
209 ra, tid); 227 ra, tid);
210#endif /* CONFIG_MAC80211_HT_DEBUG */ 228#endif /* CONFIG_MAC80211_HT_DEBUG */
211 229
230 if (hw->ampdu_queues && ieee80211_ac_from_tid(tid) == 0) {
231#ifdef CONFIG_MAC80211_HT_DEBUG
232 printk(KERN_DEBUG "rejecting on voice AC\n");
233#endif
234 return -EINVAL;
235 }
236
212 rcu_read_lock(); 237 rcu_read_lock();
213 238
214 sta = sta_info_get(local, ra); 239 sta = sta_info_get(local, ra);
@@ -217,7 +242,7 @@ int ieee80211_start_tx_ba_session(struct ieee80211_hw *hw, u8 *ra, u16 tid)
217 printk(KERN_DEBUG "Could not find the station\n"); 242 printk(KERN_DEBUG "Could not find the station\n");
218#endif 243#endif
219 ret = -ENOENT; 244 ret = -ENOENT;
220 goto exit; 245 goto unlock;
221 } 246 }
222 247
223 /* 248 /*
@@ -230,11 +255,13 @@ int ieee80211_start_tx_ba_session(struct ieee80211_hw *hw, u8 *ra, u16 tid)
230 sta->sdata->vif.type != NL80211_IFTYPE_AP_VLAN && 255 sta->sdata->vif.type != NL80211_IFTYPE_AP_VLAN &&
231 sta->sdata->vif.type != NL80211_IFTYPE_AP) { 256 sta->sdata->vif.type != NL80211_IFTYPE_AP) {
232 ret = -EINVAL; 257 ret = -EINVAL;
233 goto exit; 258 goto unlock;
234 } 259 }
235 260
236 spin_lock_bh(&sta->lock); 261 spin_lock_bh(&sta->lock);
237 262
263 sdata = sta->sdata;
264
238 /* we have tried too many times, receiver does not want A-MPDU */ 265 /* we have tried too many times, receiver does not want A-MPDU */
239 if (sta->ampdu_mlme.addba_req_num[tid] > HT_AGG_MAX_RETRIES) { 266 if (sta->ampdu_mlme.addba_req_num[tid] > HT_AGG_MAX_RETRIES) {
240 ret = -EBUSY; 267 ret = -EBUSY;
@@ -252,6 +279,42 @@ int ieee80211_start_tx_ba_session(struct ieee80211_hw *hw, u8 *ra, u16 tid)
252 goto err_unlock_sta; 279 goto err_unlock_sta;
253 } 280 }
254 281
282 if (hw->ampdu_queues) {
283 spin_lock(&local->queue_stop_reason_lock);
284 /* reserve a new queue for this session */
285 for (i = 0; i < local->hw.ampdu_queues; i++) {
286 if (local->ampdu_ac_queue[i] < 0) {
287 qn = i;
288 local->ampdu_ac_queue[qn] =
289 ieee80211_ac_from_tid(tid);
290 break;
291 }
292 }
293 spin_unlock(&local->queue_stop_reason_lock);
294
295 if (qn < 0) {
296#ifdef CONFIG_MAC80211_HT_DEBUG
297 printk(KERN_DEBUG "BA request denied - "
298 "queue unavailable for tid %d\n", tid);
299#endif /* CONFIG_MAC80211_HT_DEBUG */
300 ret = -ENOSPC;
301 goto err_unlock_sta;
302 }
303
304 /*
305 * If we successfully allocate the session, we can't have
306 * anything going on on the queue this TID maps into, so
307 * stop it for now. This is a "virtual" stop using the same
308 * mechanism that drivers will use.
309 *
310 * XXX: queue up frames for this session in the sta_info
311 * struct instead to avoid hitting all other STAs.
312 */
313 ieee80211_stop_queue_by_reason(
314 &local->hw, hw->queues + qn,
315 IEEE80211_QUEUE_STOP_REASON_AGGREGATION);
316 }
317
255 /* prepare A-MPDU MLME for Tx aggregation */ 318 /* prepare A-MPDU MLME for Tx aggregation */
256 sta->ampdu_mlme.tid_tx[tid] = 319 sta->ampdu_mlme.tid_tx[tid] =
257 kmalloc(sizeof(struct tid_ampdu_tx), GFP_ATOMIC); 320 kmalloc(sizeof(struct tid_ampdu_tx), GFP_ATOMIC);
@@ -262,8 +325,9 @@ int ieee80211_start_tx_ba_session(struct ieee80211_hw *hw, u8 *ra, u16 tid)
262 tid); 325 tid);
263#endif 326#endif
264 ret = -ENOMEM; 327 ret = -ENOMEM;
265 goto err_unlock_sta; 328 goto err_return_queue;
266 } 329 }
330
267 /* Tx timer */ 331 /* Tx timer */
268 sta->ampdu_mlme.tid_tx[tid]->addba_resp_timer.function = 332 sta->ampdu_mlme.tid_tx[tid]->addba_resp_timer.function =
269 sta_addba_resp_timer_expired; 333 sta_addba_resp_timer_expired;
@@ -271,49 +335,25 @@ int ieee80211_start_tx_ba_session(struct ieee80211_hw *hw, u8 *ra, u16 tid)
271 (unsigned long)&sta->timer_to_tid[tid]; 335 (unsigned long)&sta->timer_to_tid[tid];
272 init_timer(&sta->ampdu_mlme.tid_tx[tid]->addba_resp_timer); 336 init_timer(&sta->ampdu_mlme.tid_tx[tid]->addba_resp_timer);
273 337
274 if (hw->ampdu_queues) {
275 /* create a new queue for this aggregation */
276 ret = ieee80211_ht_agg_queue_add(local, sta, tid);
277
278 /* case no queue is available to aggregation
279 * don't switch to aggregation */
280 if (ret) {
281#ifdef CONFIG_MAC80211_HT_DEBUG
282 printk(KERN_DEBUG "BA request denied - "
283 "queue unavailable for tid %d\n", tid);
284#endif /* CONFIG_MAC80211_HT_DEBUG */
285 goto err_unlock_queue;
286 }
287 }
288 sdata = sta->sdata;
289
290 /* Ok, the Addba frame hasn't been sent yet, but if the driver calls the 338 /* Ok, the Addba frame hasn't been sent yet, but if the driver calls the
291 * call back right away, it must see that the flow has begun */ 339 * call back right away, it must see that the flow has begun */
292 *state |= HT_ADDBA_REQUESTED_MSK; 340 *state |= HT_ADDBA_REQUESTED_MSK;
293 341
294 /* This is slightly racy because the queue isn't stopped */
295 start_seq_num = sta->tid_seq[tid]; 342 start_seq_num = sta->tid_seq[tid];
296 343
297 ret = local->ops->ampdu_action(hw, IEEE80211_AMPDU_TX_START, 344 ret = local->ops->ampdu_action(hw, IEEE80211_AMPDU_TX_START,
298 &sta->sta, tid, &start_seq_num); 345 &sta->sta, tid, &start_seq_num);
299 346
300 if (ret) { 347 if (ret) {
301 /* No need to requeue the packets in the agg queue, since we
302 * held the tx lock: no packet could be enqueued to the newly
303 * allocated queue */
304 if (hw->ampdu_queues)
305 ieee80211_ht_agg_queue_remove(local, sta, tid, 0);
306#ifdef CONFIG_MAC80211_HT_DEBUG 348#ifdef CONFIG_MAC80211_HT_DEBUG
307 printk(KERN_DEBUG "BA request denied - HW unavailable for" 349 printk(KERN_DEBUG "BA request denied - HW unavailable for"
308 " tid %d\n", tid); 350 " tid %d\n", tid);
309#endif /* CONFIG_MAC80211_HT_DEBUG */ 351#endif /* CONFIG_MAC80211_HT_DEBUG */
310 *state = HT_AGG_STATE_IDLE; 352 *state = HT_AGG_STATE_IDLE;
311 goto err_unlock_queue; 353 goto err_free;
312 } 354 }
355 sta->tid_to_tx_q[tid] = qn;
313 356
314 /* Will put all the packets in the new SW queue */
315 if (hw->ampdu_queues)
316 ieee80211_requeue(local, ieee802_1d_to_ac[tid]);
317 spin_unlock_bh(&sta->lock); 357 spin_unlock_bh(&sta->lock);
318 358
319 /* send an addBA request */ 359 /* send an addBA request */
@@ -322,7 +362,6 @@ int ieee80211_start_tx_ba_session(struct ieee80211_hw *hw, u8 *ra, u16 tid)
322 sta->ampdu_mlme.dialog_token_allocator; 362 sta->ampdu_mlme.dialog_token_allocator;
323 sta->ampdu_mlme.tid_tx[tid]->ssn = start_seq_num; 363 sta->ampdu_mlme.tid_tx[tid]->ssn = start_seq_num;
324 364
325
326 ieee80211_send_addba_request(sta->sdata, ra, tid, 365 ieee80211_send_addba_request(sta->sdata, ra, tid,
327 sta->ampdu_mlme.tid_tx[tid]->dialog_token, 366 sta->ampdu_mlme.tid_tx[tid]->dialog_token,
328 sta->ampdu_mlme.tid_tx[tid]->ssn, 367 sta->ampdu_mlme.tid_tx[tid]->ssn,
@@ -334,15 +373,24 @@ int ieee80211_start_tx_ba_session(struct ieee80211_hw *hw, u8 *ra, u16 tid)
334#ifdef CONFIG_MAC80211_HT_DEBUG 373#ifdef CONFIG_MAC80211_HT_DEBUG
335 printk(KERN_DEBUG "activated addBA response timer on tid %d\n", tid); 374 printk(KERN_DEBUG "activated addBA response timer on tid %d\n", tid);
336#endif 375#endif
337 goto exit; 376 goto unlock;
338 377
339err_unlock_queue: 378 err_free:
340 kfree(sta->ampdu_mlme.tid_tx[tid]); 379 kfree(sta->ampdu_mlme.tid_tx[tid]);
341 sta->ampdu_mlme.tid_tx[tid] = NULL; 380 sta->ampdu_mlme.tid_tx[tid] = NULL;
342 ret = -EBUSY; 381 err_return_queue:
343err_unlock_sta: 382 if (qn >= 0) {
383 /* We failed, so start queue again right away. */
384 ieee80211_wake_queue_by_reason(hw, hw->queues + qn,
385 IEEE80211_QUEUE_STOP_REASON_AGGREGATION);
386 /* give queue back to pool */
387 spin_lock(&local->queue_stop_reason_lock);
388 local->ampdu_ac_queue[qn] = -1;
389 spin_unlock(&local->queue_stop_reason_lock);
390 }
391 err_unlock_sta:
344 spin_unlock_bh(&sta->lock); 392 spin_unlock_bh(&sta->lock);
345exit: 393 unlock:
346 rcu_read_unlock(); 394 rcu_read_unlock();
347 return ret; 395 return ret;
348} 396}
@@ -375,7 +423,7 @@ void ieee80211_start_tx_ba_cb(struct ieee80211_hw *hw, u8 *ra, u16 tid)
375 state = &sta->ampdu_mlme.tid_state_tx[tid]; 423 state = &sta->ampdu_mlme.tid_state_tx[tid];
376 spin_lock_bh(&sta->lock); 424 spin_lock_bh(&sta->lock);
377 425
378 if (!(*state & HT_ADDBA_REQUESTED_MSK)) { 426 if (WARN_ON(!(*state & HT_ADDBA_REQUESTED_MSK))) {
379#ifdef CONFIG_MAC80211_HT_DEBUG 427#ifdef CONFIG_MAC80211_HT_DEBUG
380 printk(KERN_DEBUG "addBA was not requested yet, state is %d\n", 428 printk(KERN_DEBUG "addBA was not requested yet, state is %d\n",
381 *state); 429 *state);
@@ -385,7 +433,8 @@ void ieee80211_start_tx_ba_cb(struct ieee80211_hw *hw, u8 *ra, u16 tid)
385 return; 433 return;
386 } 434 }
387 435
388 WARN_ON_ONCE(*state & HT_ADDBA_DRV_READY_MSK); 436 if (WARN_ON(*state & HT_ADDBA_DRV_READY_MSK))
437 goto out;
389 438
390 *state |= HT_ADDBA_DRV_READY_MSK; 439 *state |= HT_ADDBA_DRV_READY_MSK;
391 440
@@ -393,9 +442,18 @@ void ieee80211_start_tx_ba_cb(struct ieee80211_hw *hw, u8 *ra, u16 tid)
393#ifdef CONFIG_MAC80211_HT_DEBUG 442#ifdef CONFIG_MAC80211_HT_DEBUG
394 printk(KERN_DEBUG "Aggregation is on for tid %d \n", tid); 443 printk(KERN_DEBUG "Aggregation is on for tid %d \n", tid);
395#endif 444#endif
396 if (hw->ampdu_queues) 445 if (hw->ampdu_queues) {
397 ieee80211_wake_queue(hw, sta->tid_to_tx_q[tid]); 446 /*
447 * Wake up this queue, we stopped it earlier,
448 * this will in turn wake the entire AC.
449 */
450 ieee80211_wake_queue_by_reason(hw,
451 hw->queues + sta->tid_to_tx_q[tid],
452 IEEE80211_QUEUE_STOP_REASON_AGGREGATION);
453 }
398 } 454 }
455
456 out:
399 spin_unlock_bh(&sta->lock); 457 spin_unlock_bh(&sta->lock);
400 rcu_read_unlock(); 458 rcu_read_unlock();
401} 459}
@@ -485,7 +543,6 @@ void ieee80211_stop_tx_ba_cb(struct ieee80211_hw *hw, u8 *ra, u8 tid)
485 struct ieee80211_local *local = hw_to_local(hw); 543 struct ieee80211_local *local = hw_to_local(hw);
486 struct sta_info *sta; 544 struct sta_info *sta;
487 u8 *state; 545 u8 *state;
488 int agg_queue;
489 546
490 if (tid >= STA_TID_NUM) { 547 if (tid >= STA_TID_NUM) {
491#ifdef CONFIG_MAC80211_HT_DEBUG 548#ifdef CONFIG_MAC80211_HT_DEBUG
@@ -527,19 +584,19 @@ void ieee80211_stop_tx_ba_cb(struct ieee80211_hw *hw, u8 *ra, u8 tid)
527 ieee80211_send_delba(sta->sdata, ra, tid, 584 ieee80211_send_delba(sta->sdata, ra, tid,
528 WLAN_BACK_INITIATOR, WLAN_REASON_QSTA_NOT_USE); 585 WLAN_BACK_INITIATOR, WLAN_REASON_QSTA_NOT_USE);
529 586
530 if (hw->ampdu_queues) { 587 spin_lock_bh(&sta->lock);
531 agg_queue = sta->tid_to_tx_q[tid];
532 ieee80211_ht_agg_queue_remove(local, sta, tid, 1);
533 588
534 /* We just requeued the all the frames that were in the 589 if (*state & HT_AGG_STATE_INITIATOR_MSK &&
535 * removed queue, and since we might miss a softirq we do 590 hw->ampdu_queues) {
536 * netif_schedule_queue. ieee80211_wake_queue is not used 591 /*
537 * here as this queue is not necessarily stopped 592 * Wake up this queue, we stopped it earlier,
593 * this will in turn wake the entire AC.
538 */ 594 */
539 netif_schedule_queue(netdev_get_tx_queue(local->mdev, 595 ieee80211_wake_queue_by_reason(hw,
540 agg_queue)); 596 hw->queues + sta->tid_to_tx_q[tid],
597 IEEE80211_QUEUE_STOP_REASON_AGGREGATION);
541 } 598 }
542 spin_lock_bh(&sta->lock); 599
543 *state = HT_AGG_STATE_IDLE; 600 *state = HT_AGG_STATE_IDLE;
544 sta->ampdu_mlme.addba_req_num[tid] = 0; 601 sta->ampdu_mlme.addba_req_num[tid] = 0;
545 kfree(sta->ampdu_mlme.tid_tx[tid]); 602 kfree(sta->ampdu_mlme.tid_tx[tid]);
@@ -613,12 +670,21 @@ void ieee80211_process_addba_resp(struct ieee80211_local *local,
613#endif /* CONFIG_MAC80211_HT_DEBUG */ 670#endif /* CONFIG_MAC80211_HT_DEBUG */
614 if (le16_to_cpu(mgmt->u.action.u.addba_resp.status) 671 if (le16_to_cpu(mgmt->u.action.u.addba_resp.status)
615 == WLAN_STATUS_SUCCESS) { 672 == WLAN_STATUS_SUCCESS) {
673 u8 curstate = *state;
674
616 *state |= HT_ADDBA_RECEIVED_MSK; 675 *state |= HT_ADDBA_RECEIVED_MSK;
617 sta->ampdu_mlme.addba_req_num[tid] = 0;
618 676
619 if (*state == HT_AGG_STATE_OPERATIONAL && 677 if (hw->ampdu_queues && *state != curstate &&
620 local->hw.ampdu_queues) 678 *state == HT_AGG_STATE_OPERATIONAL) {
621 ieee80211_wake_queue(hw, sta->tid_to_tx_q[tid]); 679 /*
680 * Wake up this queue, we stopped it earlier,
681 * this will in turn wake the entire AC.
682 */
683 ieee80211_wake_queue_by_reason(hw,
684 hw->queues + sta->tid_to_tx_q[tid],
685 IEEE80211_QUEUE_STOP_REASON_AGGREGATION);
686 }
687 sta->ampdu_mlme.addba_req_num[tid] = 0;
622 688
623 if (local->ops->ampdu_action) { 689 if (local->ops->ampdu_action) {
624 (void)local->ops->ampdu_action(hw, 690 (void)local->ops->ampdu_action(hw,