Commit 96f5e66e8a79810e2982cdcfa28e554f3d97da21

Authored by Johannes Berg
Committed by John W. Linville
1 parent f3734ee6df

mac80211: fix aggregation for hardware with ampdu queues

Hardware with AMPDU queues currently has broken aggregation.

This patch fixes it by making all A-MPDUs go over the regular AC queues,
but keeping track of the hardware queues in mac80211. As a first rough
version, it actually stops the AC queue for extended periods of time,
which can be removed by adding buffering internal to mac80211, but is
currently not a huge problem because people rarely use multiple TIDs
that are in the same AC (and iwlwifi currently doesn't operate as AP).

This is a short-term fix, my current medium-term plan, which I hope to
execute soon as well, but am not sure can finish before .30, looks like
this:
 1) rework the internal queuing layer in mac80211 that we use for
    fragments if the driver stopped queue in the middle of a fragmented
    frame to be able to queue more frames at once (rather than just a
    single frame with its fragments)
 2) instead of stopping the entire AC queue, queue up the frames in a
    per-station/per-TID queue during aggregation session initiation,
    when the session has come up take all those frames and put them
    onto the queue from 1)
 3) push the ampdu queue layer abstraction this patch introduces in
    mac80211 into the driver, and remove the virtual queue stuff from
    mac80211 again

This plan will probably also affect ath9k in that mac80211 queues the
frames instead of passing them down, even when there are no ampdu queues.

Signed-off-by: Johannes Berg <johannes@sipsolutions.net>
Signed-off-by: John W. Linville <linville@tuxdriver.com>

Showing 10 changed files with 241 additions and 258 deletions Side-by-side Diff

include/net/mac80211.h
... ... @@ -1022,11 +1022,6 @@
1022 1022 return hw->queues;
1023 1023 }
1024 1024  
1025   -static inline int ieee80211_num_queues(struct ieee80211_hw *hw)
1026   -{
1027   - return hw->queues + hw->ampdu_queues;
1028   -}
1029   -
1030 1025 static inline struct ieee80211_rate *
1031 1026 ieee80211_get_tx_rate(const struct ieee80211_hw *hw,
1032 1027 const struct ieee80211_tx_info *c)
net/mac80211/agg-tx.c
... ... @@ -132,9 +132,24 @@
132 132  
133 133 state = &sta->ampdu_mlme.tid_state_tx[tid];
134 134  
135   - if (local->hw.ampdu_queues)
136   - ieee80211_stop_queue(&local->hw, sta->tid_to_tx_q[tid]);
  135 + if (local->hw.ampdu_queues) {
  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 153 *state = HT_AGG_STATE_REQ_STOP_BA_MSK |
139 154 (initiator << HT_AGG_STATE_INITIATOR_SHIFT);
140 155  
... ... @@ -144,8 +159,6 @@
144 159 /* HW shall not deny going back to legacy */
145 160 if (WARN_ON(ret)) {
146 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 164 return ret;
152 165  
153 166  
... ... @@ -189,14 +202,19 @@
189 202 spin_unlock_bh(&sta->lock);
190 203 }
191 204  
  205 +static inline int ieee80211_ac_from_tid(int tid)
  206 +{
  207 + return ieee802_1d_to_ac[tid & 7];
  208 +}
  209 +
192 210 int ieee80211_start_tx_ba_session(struct ieee80211_hw *hw, u8 *ra, u16 tid)
193 211 {
194 212 struct ieee80211_local *local = hw_to_local(hw);
195 213 struct sta_info *sta;
196 214 struct ieee80211_sub_if_data *sdata;
197   - u16 start_seq_num;
198 215 u8 *state;
199   - int ret = 0;
  216 + int i, qn = -1, ret = 0;
  217 + u16 start_seq_num;
200 218  
201 219 if (WARN_ON(!local->ops->ampdu_action))
202 220 return -EINVAL;
... ... @@ -209,6 +227,13 @@
209 227 ra, tid);
210 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 237 rcu_read_lock();
213 238  
214 239 sta = sta_info_get(local, ra);
... ... @@ -217,7 +242,7 @@
217 242 printk(KERN_DEBUG "Could not find the station\n");
218 243 #endif
219 244 ret = -ENOENT;
220   - goto exit;
  245 + goto unlock;
221 246 }
222 247  
223 248 /*
224 249  
... ... @@ -230,11 +255,13 @@
230 255 sta->sdata->vif.type != NL80211_IFTYPE_AP_VLAN &&
231 256 sta->sdata->vif.type != NL80211_IFTYPE_AP) {
232 257 ret = -EINVAL;
233   - goto exit;
  258 + goto unlock;
234 259 }
235 260  
236 261 spin_lock_bh(&sta->lock);
237 262  
  263 + sdata = sta->sdata;
  264 +
238 265 /* we have tried too many times, receiver does not want A-MPDU */
239 266 if (sta->ampdu_mlme.addba_req_num[tid] > HT_AGG_MAX_RETRIES) {
240 267 ret = -EBUSY;
... ... @@ -252,6 +279,42 @@
252 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 318 /* prepare A-MPDU MLME for Tx aggregation */
256 319 sta->ampdu_mlme.tid_tx[tid] =
257 320 kmalloc(sizeof(struct tid_ampdu_tx), GFP_ATOMIC);
258 321  
... ... @@ -262,8 +325,9 @@
262 325 tid);
263 326 #endif
264 327 ret = -ENOMEM;
265   - goto err_unlock_sta;
  328 + goto err_return_queue;
266 329 }
  330 +
267 331 /* Tx timer */
268 332 sta->ampdu_mlme.tid_tx[tid]->addba_resp_timer.function =
269 333 sta_addba_resp_timer_expired;
270 334  
271 335  
272 336  
273 337  
274 338  
... ... @@ -271,49 +335,25 @@
271 335 (unsigned long)&sta->timer_to_tid[tid];
272 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 338 /* Ok, the Addba frame hasn't been sent yet, but if the driver calls the
291 339 * call back right away, it must see that the flow has begun */
292 340 *state |= HT_ADDBA_REQUESTED_MSK;
293 341  
294   - /* This is slightly racy because the queue isn't stopped */
295 342 start_seq_num = sta->tid_seq[tid];
296 343  
297 344 ret = local->ops->ampdu_action(hw, IEEE80211_AMPDU_TX_START,
298 345 &sta->sta, tid, &start_seq_num);
299 346  
300 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 348 #ifdef CONFIG_MAC80211_HT_DEBUG
307 349 printk(KERN_DEBUG "BA request denied - HW unavailable for"
308 350 " tid %d\n", tid);
309 351 #endif /* CONFIG_MAC80211_HT_DEBUG */
310 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 357 spin_unlock_bh(&sta->lock);
318 358  
319 359 /* send an addBA request */
... ... @@ -322,7 +362,6 @@
322 362 sta->ampdu_mlme.dialog_token_allocator;
323 363 sta->ampdu_mlme.tid_tx[tid]->ssn = start_seq_num;
324 364  
325   -
326 365 ieee80211_send_addba_request(sta->sdata, ra, tid,
327 366 sta->ampdu_mlme.tid_tx[tid]->dialog_token,
328 367 sta->ampdu_mlme.tid_tx[tid]->ssn,
329 368  
330 369  
331 370  
... ... @@ -334,15 +373,24 @@
334 373 #ifdef CONFIG_MAC80211_HT_DEBUG
335 374 printk(KERN_DEBUG "activated addBA response timer on tid %d\n", tid);
336 375 #endif
337   - goto exit;
  376 + goto unlock;
338 377  
339   -err_unlock_queue:
  378 + err_free:
340 379 kfree(sta->ampdu_mlme.tid_tx[tid]);
341 380 sta->ampdu_mlme.tid_tx[tid] = NULL;
342   - ret = -EBUSY;
343   -err_unlock_sta:
  381 + err_return_queue:
  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 392 spin_unlock_bh(&sta->lock);
345   -exit:
  393 + unlock:
346 394 rcu_read_unlock();
347 395 return ret;
348 396 }
... ... @@ -375,7 +423,7 @@
375 423 state = &sta->ampdu_mlme.tid_state_tx[tid];
376 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 427 #ifdef CONFIG_MAC80211_HT_DEBUG
380 428 printk(KERN_DEBUG "addBA was not requested yet, state is %d\n",
381 429 *state);
... ... @@ -385,7 +433,8 @@
385 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 439 *state |= HT_ADDBA_DRV_READY_MSK;
391 440  
392 441  
... ... @@ -393,9 +442,18 @@
393 442 #ifdef CONFIG_MAC80211_HT_DEBUG
394 443 printk(KERN_DEBUG "Aggregation is on for tid %d \n", tid);
395 444 #endif
396   - if (hw->ampdu_queues)
397   - ieee80211_wake_queue(hw, sta->tid_to_tx_q[tid]);
  445 + if (hw->ampdu_queues) {
  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 457 spin_unlock_bh(&sta->lock);
400 458 rcu_read_unlock();
401 459 }
... ... @@ -485,7 +543,6 @@
485 543 struct ieee80211_local *local = hw_to_local(hw);
486 544 struct sta_info *sta;
487 545 u8 *state;
488   - int agg_queue;
489 546  
490 547 if (tid >= STA_TID_NUM) {
491 548 #ifdef CONFIG_MAC80211_HT_DEBUG
492 549  
493 550  
494 551  
... ... @@ -527,19 +584,19 @@
527 584 ieee80211_send_delba(sta->sdata, ra, tid,
528 585 WLAN_BACK_INITIATOR, WLAN_REASON_QSTA_NOT_USE);
529 586  
530   - if (hw->ampdu_queues) {
531   - agg_queue = sta->tid_to_tx_q[tid];
532   - ieee80211_ht_agg_queue_remove(local, sta, tid, 1);
  587 + spin_lock_bh(&sta->lock);
533 588  
534   - /* We just requeued the all the frames that were in the
535   - * removed queue, and since we might miss a softirq we do
536   - * netif_schedule_queue. ieee80211_wake_queue is not used
537   - * here as this queue is not necessarily stopped
  589 + if (*state & HT_AGG_STATE_INITIATOR_MSK &&
  590 + hw->ampdu_queues) {
  591 + /*
  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,
540   - agg_queue));
  595 + ieee80211_wake_queue_by_reason(hw,
  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 600 *state = HT_AGG_STATE_IDLE;
544 601 sta->ampdu_mlme.addba_req_num[tid] = 0;
545 602 kfree(sta->ampdu_mlme.tid_tx[tid]);
546 603  
547 604  
... ... @@ -613,12 +670,21 @@
613 670 #endif /* CONFIG_MAC80211_HT_DEBUG */
614 671 if (le16_to_cpu(mgmt->u.action.u.addba_resp.status)
615 672 == WLAN_STATUS_SUCCESS) {
  673 + u8 curstate = *state;
  674 +
616 675 *state |= HT_ADDBA_RECEIVED_MSK;
617   - sta->ampdu_mlme.addba_req_num[tid] = 0;
618 676  
619   - if (*state == HT_AGG_STATE_OPERATIONAL &&
620   - local->hw.ampdu_queues)
621   - ieee80211_wake_queue(hw, sta->tid_to_tx_q[tid]);
  677 + if (hw->ampdu_queues && *state != curstate &&
  678 + *state == HT_AGG_STATE_OPERATIONAL) {
  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 689 if (local->ops->ampdu_action) {
624 690 (void)local->ops->ampdu_action(hw,
net/mac80211/ieee80211_i.h
... ... @@ -564,12 +564,10 @@
564 564 enum queue_stop_reason {
565 565 IEEE80211_QUEUE_STOP_REASON_DRIVER,
566 566 IEEE80211_QUEUE_STOP_REASON_PS,
567   - IEEE80211_QUEUE_STOP_REASON_CSA
  567 + IEEE80211_QUEUE_STOP_REASON_CSA,
  568 + IEEE80211_QUEUE_STOP_REASON_AGGREGATION,
568 569 };
569 570  
570   -/* maximum number of hardware queues we support. */
571   -#define QD_MAX_QUEUES (IEEE80211_MAX_AMPDU_QUEUES + IEEE80211_MAX_QUEUES)
572   -
573 571 struct ieee80211_master_priv {
574 572 struct ieee80211_local *local;
575 573 };
576 574  
... ... @@ -582,9 +580,15 @@
582 580  
583 581 const struct ieee80211_ops *ops;
584 582  
585   - unsigned long queue_pool[BITS_TO_LONGS(QD_MAX_QUEUES)];
586   - unsigned long queue_stop_reasons[IEEE80211_MAX_QUEUES];
  583 + /* AC queue corresponding to each AMPDU queue */
  584 + s8 ampdu_ac_queue[IEEE80211_MAX_AMPDU_QUEUES];
  585 + unsigned int amdpu_ac_stop_refcnt[IEEE80211_MAX_AMPDU_QUEUES];
  586 +
  587 + unsigned long queue_stop_reasons[IEEE80211_MAX_QUEUES +
  588 + IEEE80211_MAX_AMPDU_QUEUES];
  589 + /* also used to protect ampdu_ac_queue and amdpu_ac_stop_refcnt */
587 590 spinlock_t queue_stop_reason_lock;
  591 +
588 592 struct net_device *mdev; /* wmaster# - "master" 802.11 device */
589 593 int open_count;
590 594 int monitors, cooked_mntrs;
... ... @@ -1042,6 +1046,10 @@
1042 1046 enum queue_stop_reason reason);
1043 1047 void ieee80211_stop_queues_by_reason(struct ieee80211_hw *hw,
1044 1048 enum queue_stop_reason reason);
  1049 +void ieee80211_wake_queue_by_reason(struct ieee80211_hw *hw, int queue,
  1050 + enum queue_stop_reason reason);
  1051 +void ieee80211_stop_queue_by_reason(struct ieee80211_hw *hw, int queue,
  1052 + enum queue_stop_reason reason);
1045 1053  
1046 1054 #ifdef CONFIG_MAC80211_NOINLINE
1047 1055 #define debug_noinline noinline
... ... @@ -705,7 +705,7 @@
705 705 const struct ieee80211_ops *ops)
706 706 {
707 707 struct ieee80211_local *local;
708   - int priv_size;
  708 + int priv_size, i;
709 709 struct wiphy *wiphy;
710 710  
711 711 /* Ensure 32-byte alignment of our private data and hw private data.
... ... @@ -779,6 +779,11 @@
779 779 setup_timer(&local->dynamic_ps_timer,
780 780 ieee80211_dynamic_ps_timer, (unsigned long) local);
781 781  
  782 + for (i = 0; i < IEEE80211_MAX_AMPDU_QUEUES; i++)
  783 + local->ampdu_ac_queue[i] = -1;
  784 + /* using an s8 won't work with more than that */
  785 + BUILD_BUG_ON(IEEE80211_MAX_AMPDU_QUEUES > 127);
  786 +
782 787 sta_info_init(local);
783 788  
784 789 tasklet_init(&local->tx_pending_tasklet, ieee80211_tx_pending,
... ... @@ -872,7 +877,7 @@
872 877  
873 878 mdev = alloc_netdev_mq(sizeof(struct ieee80211_master_priv),
874 879 "wmaster%d", ieee80211_master_setup,
875   - ieee80211_num_queues(hw));
  880 + hw->queues);
876 881 if (!mdev)
877 882 goto fail_mdev_alloc;
878 883  
net/mac80211/sta_info.c
... ... @@ -202,6 +202,18 @@
202 202 /* Make sure timer won't free the tid_rx struct, see below */
203 203 if (tid_rx)
204 204 tid_rx->shutdown = true;
  205 +
  206 + /*
  207 + * The stop callback cannot find this station any more, but
  208 + * it didn't complete its work -- start the queue if necessary
  209 + */
  210 + if (sta->ampdu_mlme.tid_state_tx[i] & HT_AGG_STATE_INITIATOR_MSK &&
  211 + sta->ampdu_mlme.tid_state_tx[i] & HT_AGG_STATE_REQ_STOP_BA_MSK &&
  212 + local->hw.ampdu_queues)
  213 + ieee80211_wake_queue_by_reason(&local->hw,
  214 + local->hw.queues + sta->tid_to_tx_q[i],
  215 + IEEE80211_QUEUE_STOP_REASON_AGGREGATION);
  216 +
205 217 spin_unlock_bh(&sta->lock);
206 218  
207 219 /*
... ... @@ -275,8 +287,7 @@
275 287 * enable session_timer's data differentiation. refer to
276 288 * sta_rx_agg_session_timer_expired for useage */
277 289 sta->timer_to_tid[i] = i;
278   - /* tid to tx queue: initialize according to HW (0 is valid) */
279   - sta->tid_to_tx_q[i] = ieee80211_num_queues(&local->hw);
  290 + sta->tid_to_tx_q[i] = -1;
280 291 /* rx */
281 292 sta->ampdu_mlme.tid_state_rx[i] = HT_AGG_STATE_IDLE;
282 293 sta->ampdu_mlme.tid_rx[i] = NULL;
net/mac80211/sta_info.h
... ... @@ -200,7 +200,7 @@
200 200 * @tid_seq: per-TID sequence numbers for sending to this STA
201 201 * @ampdu_mlme: A-MPDU state machine state
202 202 * @timer_to_tid: identity mapping to ID timers
203   - * @tid_to_tx_q: map tid to tx queue
  203 + * @tid_to_tx_q: map tid to tx queue (invalid == negative values)
204 204 * @llid: Local link ID
205 205 * @plid: Peer link ID
206 206 * @reason: Cancel reason on PLINK_HOLDING state
... ... @@ -275,7 +275,7 @@
275 275 */
276 276 struct sta_ampdu_mlme ampdu_mlme;
277 277 u8 timer_to_tid[STA_TID_NUM];
278   - u8 tid_to_tx_q[STA_TID_NUM];
  278 + s8 tid_to_tx_q[STA_TID_NUM];
279 279  
280 280 #ifdef CONFIG_MAC80211_MESH
281 281 /*
... ... @@ -876,7 +876,6 @@
876 876 return TX_CONTINUE;
877 877 }
878 878  
879   -
880 879 /* actual transmit path */
881 880  
882 881 /*
883 882  
884 883  
885 884  
... ... @@ -1016,12 +1015,20 @@
1016 1015 tx->sta = sta_info_get(local, hdr->addr1);
1017 1016  
1018 1017 if (tx->sta && ieee80211_is_data_qos(hdr->frame_control)) {
  1018 + unsigned long flags;
1019 1019 qc = ieee80211_get_qos_ctl(hdr);
1020 1020 tid = *qc & IEEE80211_QOS_CTL_TID_MASK;
1021 1021  
  1022 + spin_lock_irqsave(&tx->sta->lock, flags);
1022 1023 state = &tx->sta->ampdu_mlme.tid_state_tx[tid];
1023   - if (*state == HT_AGG_STATE_OPERATIONAL)
  1024 + if (*state == HT_AGG_STATE_OPERATIONAL) {
1024 1025 info->flags |= IEEE80211_TX_CTL_AMPDU;
  1026 + if (local->hw.ampdu_queues)
  1027 + skb_set_queue_mapping(
  1028 + skb, tx->local->hw.queues +
  1029 + tx->sta->tid_to_tx_q[tid]);
  1030 + }
  1031 + spin_unlock_irqrestore(&tx->sta->lock, flags);
1025 1032 }
1026 1033  
1027 1034 if (is_multicast_ether_addr(hdr->addr1)) {
... ... @@ -1085,7 +1092,8 @@
1085 1092 int ret, i;
1086 1093  
1087 1094 if (skb) {
1088   - if (netif_subqueue_stopped(local->mdev, skb))
  1095 + if (ieee80211_queue_stopped(&local->hw,
  1096 + skb_get_queue_mapping(skb)))
1089 1097 return IEEE80211_TX_PENDING;
1090 1098  
1091 1099 ret = local->ops->tx(local_to_hw(local), skb);
... ... @@ -1101,8 +1109,8 @@
1101 1109 info = IEEE80211_SKB_CB(tx->extra_frag[i]);
1102 1110 info->flags &= ~(IEEE80211_TX_CTL_CLEAR_PS_FILT |
1103 1111 IEEE80211_TX_CTL_FIRST_FRAGMENT);
1104   - if (netif_subqueue_stopped(local->mdev,
1105   - tx->extra_frag[i]))
  1112 + if (ieee80211_queue_stopped(&local->hw,
  1113 + skb_get_queue_mapping(tx->extra_frag[i])))
1106 1114 return IEEE80211_TX_FRAG_AGAIN;
1107 1115  
1108 1116 ret = local->ops->tx(local_to_hw(local),
... ... @@ -344,15 +344,36 @@
344 344 {
345 345 struct ieee80211_local *local = hw_to_local(hw);
346 346  
347   - /* we don't need to track ampdu queues */
348   - if (queue < ieee80211_num_regular_queues(hw)) {
349   - __clear_bit(reason, &local->queue_stop_reasons[queue]);
  347 + if (queue >= hw->queues) {
  348 + if (local->ampdu_ac_queue[queue - hw->queues] < 0)
  349 + return;
350 350  
351   - if (local->queue_stop_reasons[queue] != 0)
352   - /* someone still has this queue stopped */
  351 + /*
  352 + * for virtual aggregation queues, we need to refcount the
  353 + * internal mac80211 disable (multiple times!), keep track of
  354 + * driver disable _and_ make sure the regular queue is
  355 + * actually enabled.
  356 + */
  357 + if (reason == IEEE80211_QUEUE_STOP_REASON_AGGREGATION)
  358 + local->amdpu_ac_stop_refcnt[queue - hw->queues]--;
  359 + else
  360 + __clear_bit(reason, &local->queue_stop_reasons[queue]);
  361 +
  362 + if (local->queue_stop_reasons[queue] ||
  363 + local->amdpu_ac_stop_refcnt[queue - hw->queues])
353 364 return;
  365 +
  366 + /* now go on to treat the corresponding regular queue */
  367 + queue = local->ampdu_ac_queue[queue - hw->queues];
  368 + reason = IEEE80211_QUEUE_STOP_REASON_AGGREGATION;
354 369 }
355 370  
  371 + __clear_bit(reason, &local->queue_stop_reasons[queue]);
  372 +
  373 + if (local->queue_stop_reasons[queue] != 0)
  374 + /* someone still has this queue stopped */
  375 + return;
  376 +
356 377 if (test_bit(queue, local->queues_pending)) {
357 378 set_bit(queue, local->queues_pending_run);
358 379 tasklet_schedule(&local->tx_pending_tasklet);
... ... @@ -361,8 +382,8 @@
361 382 }
362 383 }
363 384  
364   -static void ieee80211_wake_queue_by_reason(struct ieee80211_hw *hw, int queue,
365   - enum queue_stop_reason reason)
  385 +void ieee80211_wake_queue_by_reason(struct ieee80211_hw *hw, int queue,
  386 + enum queue_stop_reason reason)
366 387 {
367 388 struct ieee80211_local *local = hw_to_local(hw);
368 389 unsigned long flags;
369 390  
370 391  
... ... @@ -384,15 +405,33 @@
384 405 {
385 406 struct ieee80211_local *local = hw_to_local(hw);
386 407  
387   - /* we don't need to track ampdu queues */
388   - if (queue < ieee80211_num_regular_queues(hw))
389   - __set_bit(reason, &local->queue_stop_reasons[queue]);
  408 + if (queue >= hw->queues) {
  409 + if (local->ampdu_ac_queue[queue - hw->queues] < 0)
  410 + return;
390 411  
  412 + /*
  413 + * for virtual aggregation queues, we need to refcount the
  414 + * internal mac80211 disable (multiple times!), keep track of
  415 + * driver disable _and_ make sure the regular queue is
  416 + * actually enabled.
  417 + */
  418 + if (reason == IEEE80211_QUEUE_STOP_REASON_AGGREGATION)
  419 + local->amdpu_ac_stop_refcnt[queue - hw->queues]++;
  420 + else
  421 + __set_bit(reason, &local->queue_stop_reasons[queue]);
  422 +
  423 + /* now go on to treat the corresponding regular queue */
  424 + queue = local->ampdu_ac_queue[queue - hw->queues];
  425 + reason = IEEE80211_QUEUE_STOP_REASON_AGGREGATION;
  426 + }
  427 +
  428 + __set_bit(reason, &local->queue_stop_reasons[queue]);
  429 +
391 430 netif_stop_subqueue(local->mdev, queue);
392 431 }
393 432  
394   -static void ieee80211_stop_queue_by_reason(struct ieee80211_hw *hw, int queue,
395   - enum queue_stop_reason reason)
  433 +void ieee80211_stop_queue_by_reason(struct ieee80211_hw *hw, int queue,
  434 + enum queue_stop_reason reason)
396 435 {
397 436 struct ieee80211_local *local = hw_to_local(hw);
398 437 unsigned long flags;
... ... @@ -418,7 +457,7 @@
418 457  
419 458 spin_lock_irqsave(&local->queue_stop_reason_lock, flags);
420 459  
421   - for (i = 0; i < ieee80211_num_queues(hw); i++)
  460 + for (i = 0; i < hw->queues; i++)
422 461 __ieee80211_stop_queue(hw, i, reason);
423 462  
424 463 spin_unlock_irqrestore(&local->queue_stop_reason_lock, flags);
... ... @@ -434,6 +473,16 @@
434 473 int ieee80211_queue_stopped(struct ieee80211_hw *hw, int queue)
435 474 {
436 475 struct ieee80211_local *local = hw_to_local(hw);
  476 + unsigned long flags;
  477 +
  478 + if (queue >= hw->queues) {
  479 + spin_lock_irqsave(&local->queue_stop_reason_lock, flags);
  480 + queue = local->ampdu_ac_queue[queue - hw->queues];
  481 + spin_unlock_irqrestore(&local->queue_stop_reason_lock, flags);
  482 + if (queue < 0)
  483 + return true;
  484 + }
  485 +
437 486 return __netif_subqueue_stopped(local->mdev, queue);
438 487 }
439 488 EXPORT_SYMBOL(ieee80211_queue_stopped);
... ... @@ -114,9 +114,7 @@
114 114 {
115 115 struct ieee80211_master_priv *mpriv = netdev_priv(dev);
116 116 struct ieee80211_local *local = mpriv->local;
117   - struct ieee80211_hw *hw = &local->hw;
118 117 struct ieee80211_hdr *hdr = (struct ieee80211_hdr *) skb->data;
119   - struct sta_info *sta;
120 118 u16 queue;
121 119 u8 tid;
122 120  
123 121  
... ... @@ -124,29 +122,11 @@
124 122 if (unlikely(queue >= local->hw.queues))
125 123 queue = local->hw.queues - 1;
126 124  
127   - if (skb->requeue) {
128   - if (!hw->ampdu_queues)
129   - return queue;
130   -
131   - rcu_read_lock();
132   - sta = sta_info_get(local, hdr->addr1);
133   - tid = skb->priority & IEEE80211_QOS_CTL_TAG1D_MASK;
134   - if (sta) {
135   - int ampdu_queue = sta->tid_to_tx_q[tid];
136   -
137   - if ((ampdu_queue < ieee80211_num_queues(hw)) &&
138   - test_bit(ampdu_queue, local->queue_pool))
139   - queue = ampdu_queue;
140   - }
141   - rcu_read_unlock();
142   -
143   - return queue;
144   - }
145   -
146   - /* Now we know the 1d priority, fill in the QoS header if
147   - * there is one.
  125 + /*
  126 + * Now we know the 1d priority, fill in the QoS header if
  127 + * there is one (and we haven't done this before).
148 128 */
149   - if (ieee80211_is_data_qos(hdr->frame_control)) {
  129 + if (!skb->requeue && ieee80211_is_data_qos(hdr->frame_control)) {
150 130 u8 *p = ieee80211_get_qos_ctl(hdr);
151 131 u8 ack_policy = 0;
152 132 tid = skb->priority & IEEE80211_QOS_CTL_TAG1D_MASK;
153 133  
... ... @@ -156,141 +136,8 @@
156 136 /* qos header is 2 bytes, second reserved */
157 137 *p++ = ack_policy | tid;
158 138 *p = 0;
159   -
160   - if (!hw->ampdu_queues)
161   - return queue;
162   -
163   - rcu_read_lock();
164   -
165   - sta = sta_info_get(local, hdr->addr1);
166   - if (sta) {
167   - int ampdu_queue = sta->tid_to_tx_q[tid];
168   -
169   - if ((ampdu_queue < ieee80211_num_queues(hw)) &&
170   - test_bit(ampdu_queue, local->queue_pool))
171   - queue = ampdu_queue;
172   - }
173   -
174   - rcu_read_unlock();
175 139 }
176 140  
177 141 return queue;
178   -}
179   -
180   -int ieee80211_ht_agg_queue_add(struct ieee80211_local *local,
181   - struct sta_info *sta, u16 tid)
182   -{
183   - int i;
184   -
185   - /* XXX: currently broken due to cb/requeue use */
186   - return -EPERM;
187   -
188   - /* prepare the filter and save it for the SW queue
189   - * matching the received HW queue */
190   -
191   - if (!local->hw.ampdu_queues)
192   - return -EPERM;
193   -
194   - /* try to get a Qdisc from the pool */
195   - for (i = local->hw.queues; i < ieee80211_num_queues(&local->hw); i++)
196   - if (!test_and_set_bit(i, local->queue_pool)) {
197   - ieee80211_stop_queue(local_to_hw(local), i);
198   - sta->tid_to_tx_q[tid] = i;
199   -
200   - /* IF there are already pending packets
201   - * on this tid first we need to drain them
202   - * on the previous queue
203   - * since HT is strict in order */
204   -#ifdef CONFIG_MAC80211_HT_DEBUG
205   - if (net_ratelimit())
206   - printk(KERN_DEBUG "allocated aggregation queue"
207   - " %d tid %d addr %pM pool=0x%lX\n",
208   - i, tid, sta->sta.addr,
209   - local->queue_pool[0]);
210   -#endif /* CONFIG_MAC80211_HT_DEBUG */
211   - return 0;
212   - }
213   -
214   - return -EAGAIN;
215   -}
216   -
217   -/**
218   - * the caller needs to hold netdev_get_tx_queue(local->mdev, X)->lock
219   - */
220   -void ieee80211_ht_agg_queue_remove(struct ieee80211_local *local,
221   - struct sta_info *sta, u16 tid,
222   - u8 requeue)
223   -{
224   - int agg_queue = sta->tid_to_tx_q[tid];
225   - struct ieee80211_hw *hw = &local->hw;
226   -
227   - /* return the qdisc to the pool */
228   - clear_bit(agg_queue, local->queue_pool);
229   - sta->tid_to_tx_q[tid] = ieee80211_num_queues(hw);
230   -
231   - if (requeue) {
232   - ieee80211_requeue(local, agg_queue);
233   - } else {
234   - struct netdev_queue *txq;
235   - spinlock_t *root_lock;
236   - struct Qdisc *q;
237   -
238   - txq = netdev_get_tx_queue(local->mdev, agg_queue);
239   - q = rcu_dereference(txq->qdisc);
240   - root_lock = qdisc_lock(q);
241   -
242   - spin_lock_bh(root_lock);
243   - qdisc_reset(q);
244   - spin_unlock_bh(root_lock);
245   - }
246   -}
247   -
248   -void ieee80211_requeue(struct ieee80211_local *local, int queue)
249   -{
250   - struct netdev_queue *txq = netdev_get_tx_queue(local->mdev, queue);
251   - struct sk_buff_head list;
252   - spinlock_t *root_lock;
253   - struct Qdisc *qdisc;
254   - u32 len;
255   -
256   - rcu_read_lock_bh();
257   -
258   - qdisc = rcu_dereference(txq->qdisc);
259   - if (!qdisc || !qdisc->dequeue)
260   - goto out_unlock;
261   -
262   - skb_queue_head_init(&list);
263   -
264   - root_lock = qdisc_root_lock(qdisc);
265   - spin_lock(root_lock);
266   - for (len = qdisc->q.qlen; len > 0; len--) {
267   - struct sk_buff *skb = qdisc->dequeue(qdisc);
268   -
269   - if (skb)
270   - __skb_queue_tail(&list, skb);
271   - }
272   - spin_unlock(root_lock);
273   -
274   - for (len = list.qlen; len > 0; len--) {
275   - struct sk_buff *skb = __skb_dequeue(&list);
276   - u16 new_queue;
277   -
278   - BUG_ON(!skb);
279   - new_queue = ieee80211_select_queue(local->mdev, skb);
280   - skb_set_queue_mapping(skb, new_queue);
281   -
282   - txq = netdev_get_tx_queue(local->mdev, new_queue);
283   -
284   -
285   - qdisc = rcu_dereference(txq->qdisc);
286   - root_lock = qdisc_root_lock(qdisc);
287   -
288   - spin_lock(root_lock);
289   - qdisc_enqueue_root(skb, qdisc);
290   - spin_unlock(root_lock);
291   - }
292   -
293   -out_unlock:
294   - rcu_read_unlock_bh();
295 142 }
... ... @@ -21,12 +21,6 @@
21 21 extern const int ieee802_1d_to_ac[8];
22 22  
23 23 u16 ieee80211_select_queue(struct net_device *dev, struct sk_buff *skb);
24   -int ieee80211_ht_agg_queue_add(struct ieee80211_local *local,
25   - struct sta_info *sta, u16 tid);
26   -void ieee80211_ht_agg_queue_remove(struct ieee80211_local *local,
27   - struct sta_info *sta, u16 tid,
28   - u8 requeue);
29   -void ieee80211_requeue(struct ieee80211_local *local, int queue);
30 24  
31 25 #endif /* _WME_H */