.. | .. |
---|
| 1 | +// SPDX-License-Identifier: GPL-2.0-only |
---|
1 | 2 | /* |
---|
2 | 3 | * HT handling |
---|
3 | 4 | * |
---|
.. | .. |
---|
8 | 9 | * Copyright 2007, Michael Wu <flamingice@sourmilk.net> |
---|
9 | 10 | * Copyright 2007-2010, Intel Corporation |
---|
10 | 11 | * Copyright(c) 2015-2017 Intel Deutschland GmbH |
---|
11 | | - * Copyright (C) 2018 - 2019 Intel Corporation |
---|
12 | | - * |
---|
13 | | - * This program is free software; you can redistribute it and/or modify |
---|
14 | | - * it under the terms of the GNU General Public License version 2 as |
---|
15 | | - * published by the Free Software Foundation. |
---|
| 12 | + * Copyright (C) 2018 - 2022 Intel Corporation |
---|
16 | 13 | */ |
---|
17 | 14 | |
---|
18 | 15 | #include <linux/ieee80211.h> |
---|
.. | .. |
---|
216 | 213 | struct ieee80211_txq *txq = sta->sta.txq[tid]; |
---|
217 | 214 | struct txq_info *txqi; |
---|
218 | 215 | |
---|
| 216 | + lockdep_assert_held(&sta->ampdu_mlme.mtx); |
---|
| 217 | + |
---|
219 | 218 | if (!txq) |
---|
220 | 219 | return; |
---|
221 | 220 | |
---|
.. | .. |
---|
229 | 228 | clear_bit(IEEE80211_TXQ_STOP, &txqi->flags); |
---|
230 | 229 | local_bh_disable(); |
---|
231 | 230 | rcu_read_lock(); |
---|
232 | | - drv_wake_tx_queue(sta->sdata->local, txqi); |
---|
| 231 | + schedule_and_wake_txq(sta->sdata->local, txqi); |
---|
233 | 232 | rcu_read_unlock(); |
---|
234 | 233 | local_bh_enable(); |
---|
235 | 234 | } |
---|
.. | .. |
---|
293 | 292 | ieee80211_assign_tid_tx(sta, tid, NULL); |
---|
294 | 293 | |
---|
295 | 294 | ieee80211_agg_splice_finish(sta->sdata, tid); |
---|
296 | | - ieee80211_agg_start_txq(sta, tid, false); |
---|
297 | 295 | |
---|
298 | 296 | kfree_rcu(tid_tx, rcu_head); |
---|
299 | 297 | } |
---|
.. | .. |
---|
451 | 449 | ieee80211_stop_tx_ba_session(&sta->sta, tid); |
---|
452 | 450 | } |
---|
453 | 451 | |
---|
454 | | -void ieee80211_tx_ba_session_handle_start(struct sta_info *sta, int tid) |
---|
| 452 | +static void ieee80211_send_addba_with_timeout(struct sta_info *sta, |
---|
| 453 | + struct tid_ampdu_tx *tid_tx) |
---|
455 | 454 | { |
---|
456 | | - struct tid_ampdu_tx *tid_tx; |
---|
457 | | - struct ieee80211_local *local = sta->local; |
---|
458 | 455 | struct ieee80211_sub_if_data *sdata = sta->sdata; |
---|
459 | | - struct ieee80211_ampdu_params params = { |
---|
460 | | - .sta = &sta->sta, |
---|
461 | | - .action = IEEE80211_AMPDU_TX_START, |
---|
462 | | - .tid = tid, |
---|
463 | | - .buf_size = 0, |
---|
464 | | - .amsdu = false, |
---|
465 | | - .timeout = 0, |
---|
466 | | - }; |
---|
467 | | - int ret; |
---|
| 456 | + struct ieee80211_local *local = sta->local; |
---|
| 457 | + u8 tid = tid_tx->tid; |
---|
468 | 458 | u16 buf_size; |
---|
469 | | - |
---|
470 | | - tid_tx = rcu_dereference_protected_tid_tx(sta, tid); |
---|
471 | | - |
---|
472 | | - /* |
---|
473 | | - * Start queuing up packets for this aggregation session. |
---|
474 | | - * We're going to release them once the driver is OK with |
---|
475 | | - * that. |
---|
476 | | - */ |
---|
477 | | - clear_bit(HT_AGG_STATE_WANT_START, &tid_tx->state); |
---|
478 | | - |
---|
479 | | - ieee80211_agg_stop_txq(sta, tid); |
---|
480 | | - |
---|
481 | | - /* |
---|
482 | | - * Make sure no packets are being processed. This ensures that |
---|
483 | | - * we have a valid starting sequence number and that in-flight |
---|
484 | | - * packets have been flushed out and no packets for this TID |
---|
485 | | - * will go into the driver during the ampdu_action call. |
---|
486 | | - */ |
---|
487 | | - synchronize_net(); |
---|
488 | | - |
---|
489 | | - params.ssn = sta->tid_seq[tid] >> 4; |
---|
490 | | - ret = drv_ampdu_action(local, sdata, ¶ms); |
---|
491 | | - if (ret) { |
---|
492 | | - ht_dbg(sdata, |
---|
493 | | - "BA request denied - HW unavailable for %pM tid %d\n", |
---|
494 | | - sta->sta.addr, tid); |
---|
495 | | - spin_lock_bh(&sta->lock); |
---|
496 | | - ieee80211_agg_splice_packets(sdata, tid_tx, tid); |
---|
497 | | - ieee80211_assign_tid_tx(sta, tid, NULL); |
---|
498 | | - ieee80211_agg_splice_finish(sdata, tid); |
---|
499 | | - spin_unlock_bh(&sta->lock); |
---|
500 | | - |
---|
501 | | - ieee80211_agg_start_txq(sta, tid, false); |
---|
502 | | - |
---|
503 | | - kfree_rcu(tid_tx, rcu_head); |
---|
504 | | - return; |
---|
505 | | - } |
---|
506 | 459 | |
---|
507 | 460 | /* activate the timer for the recipient's addBA response */ |
---|
508 | 461 | mod_timer(&tid_tx->addba_resp_timer, jiffies + ADDBA_RESP_INTERVAL); |
---|
.. | .. |
---|
528 | 481 | |
---|
529 | 482 | /* send AddBA request */ |
---|
530 | 483 | ieee80211_send_addba_request(sdata, sta->sta.addr, tid, |
---|
531 | | - tid_tx->dialog_token, params.ssn, |
---|
| 484 | + tid_tx->dialog_token, tid_tx->ssn, |
---|
532 | 485 | buf_size, tid_tx->timeout); |
---|
| 486 | + |
---|
| 487 | + WARN_ON(test_and_set_bit(HT_AGG_STATE_SENT_ADDBA, &tid_tx->state)); |
---|
| 488 | +} |
---|
| 489 | + |
---|
| 490 | +void ieee80211_tx_ba_session_handle_start(struct sta_info *sta, int tid) |
---|
| 491 | +{ |
---|
| 492 | + struct tid_ampdu_tx *tid_tx; |
---|
| 493 | + struct ieee80211_local *local = sta->local; |
---|
| 494 | + struct ieee80211_sub_if_data *sdata; |
---|
| 495 | + struct ieee80211_ampdu_params params = { |
---|
| 496 | + .sta = &sta->sta, |
---|
| 497 | + .action = IEEE80211_AMPDU_TX_START, |
---|
| 498 | + .tid = tid, |
---|
| 499 | + .buf_size = 0, |
---|
| 500 | + .amsdu = false, |
---|
| 501 | + .timeout = 0, |
---|
| 502 | + }; |
---|
| 503 | + int ret; |
---|
| 504 | + |
---|
| 505 | + tid_tx = rcu_dereference_protected_tid_tx(sta, tid); |
---|
| 506 | + |
---|
| 507 | + /* |
---|
| 508 | + * Start queuing up packets for this aggregation session. |
---|
| 509 | + * We're going to release them once the driver is OK with |
---|
| 510 | + * that. |
---|
| 511 | + */ |
---|
| 512 | + clear_bit(HT_AGG_STATE_WANT_START, &tid_tx->state); |
---|
| 513 | + |
---|
| 514 | + ieee80211_agg_stop_txq(sta, tid); |
---|
| 515 | + |
---|
| 516 | + /* |
---|
| 517 | + * Make sure no packets are being processed. This ensures that |
---|
| 518 | + * we have a valid starting sequence number and that in-flight |
---|
| 519 | + * packets have been flushed out and no packets for this TID |
---|
| 520 | + * will go into the driver during the ampdu_action call. |
---|
| 521 | + */ |
---|
| 522 | + synchronize_net(); |
---|
| 523 | + |
---|
| 524 | + sdata = sta->sdata; |
---|
| 525 | + params.ssn = sta->tid_seq[tid] >> 4; |
---|
| 526 | + ret = drv_ampdu_action(local, sdata, ¶ms); |
---|
| 527 | + tid_tx->ssn = params.ssn; |
---|
| 528 | + if (ret == IEEE80211_AMPDU_TX_START_DELAY_ADDBA) { |
---|
| 529 | + return; |
---|
| 530 | + } else if (ret == IEEE80211_AMPDU_TX_START_IMMEDIATE) { |
---|
| 531 | + /* |
---|
| 532 | + * We didn't send the request yet, so don't need to check |
---|
| 533 | + * here if we already got a response, just mark as driver |
---|
| 534 | + * ready immediately. |
---|
| 535 | + */ |
---|
| 536 | + set_bit(HT_AGG_STATE_DRV_READY, &tid_tx->state); |
---|
| 537 | + } else if (ret) { |
---|
| 538 | + if (!sdata) |
---|
| 539 | + return; |
---|
| 540 | + |
---|
| 541 | + ht_dbg(sdata, |
---|
| 542 | + "BA request denied - HW unavailable for %pM tid %d\n", |
---|
| 543 | + sta->sta.addr, tid); |
---|
| 544 | + spin_lock_bh(&sta->lock); |
---|
| 545 | + ieee80211_agg_splice_packets(sdata, tid_tx, tid); |
---|
| 546 | + ieee80211_assign_tid_tx(sta, tid, NULL); |
---|
| 547 | + ieee80211_agg_splice_finish(sdata, tid); |
---|
| 548 | + spin_unlock_bh(&sta->lock); |
---|
| 549 | + |
---|
| 550 | + ieee80211_agg_start_txq(sta, tid, false); |
---|
| 551 | + |
---|
| 552 | + kfree_rcu(tid_tx, rcu_head); |
---|
| 553 | + return; |
---|
| 554 | + } |
---|
| 555 | + |
---|
| 556 | + ieee80211_send_addba_with_timeout(sta, tid_tx); |
---|
533 | 557 | } |
---|
534 | 558 | |
---|
535 | 559 | /* |
---|
.. | .. |
---|
574 | 598 | "Requested to start BA session on reserved tid=%d", tid)) |
---|
575 | 599 | return -EINVAL; |
---|
576 | 600 | |
---|
577 | | - if (!pubsta->ht_cap.ht_supported) |
---|
| 601 | + if (!pubsta->ht_cap.ht_supported && |
---|
| 602 | + sta->sdata->vif.bss_conf.chandef.chan->band != NL80211_BAND_6GHZ) |
---|
578 | 603 | return -EINVAL; |
---|
579 | 604 | |
---|
580 | 605 | if (WARN_ON_ONCE(!local->ops->ampdu_action)) |
---|
.. | .. |
---|
601 | 626 | if (test_sta_flag(sta, WLAN_STA_BLOCK_BA)) { |
---|
602 | 627 | ht_dbg(sdata, |
---|
603 | 628 | "BA sessions blocked - Denying BA session request %pM tid %d\n", |
---|
| 629 | + sta->sta.addr, tid); |
---|
| 630 | + return -EINVAL; |
---|
| 631 | + } |
---|
| 632 | + |
---|
| 633 | + if (test_sta_flag(sta, WLAN_STA_MFP) && |
---|
| 634 | + !test_sta_flag(sta, WLAN_STA_AUTHORIZED)) { |
---|
| 635 | + ht_dbg(sdata, |
---|
| 636 | + "MFP STA not authorized - deny BA session request %pM tid %d\n", |
---|
604 | 637 | sta->sta.addr, tid); |
---|
605 | 638 | return -EINVAL; |
---|
606 | 639 | } |
---|
.. | .. |
---|
750 | 783 | if (WARN_ON(test_and_set_bit(HT_AGG_STATE_DRV_READY, &tid_tx->state))) |
---|
751 | 784 | return; |
---|
752 | 785 | |
---|
| 786 | + if (!test_bit(HT_AGG_STATE_SENT_ADDBA, &tid_tx->state)) { |
---|
| 787 | + ieee80211_send_addba_with_timeout(sta, tid_tx); |
---|
| 788 | + /* RESPONSE_RECEIVED state whould trigger the flow again */ |
---|
| 789 | + return; |
---|
| 790 | + } |
---|
| 791 | + |
---|
753 | 792 | if (test_bit(HT_AGG_STATE_RESPONSE_RECEIVED, &tid_tx->state)) |
---|
754 | 793 | ieee80211_agg_tx_operational(local, sta, tid); |
---|
755 | 794 | } |
---|
.. | .. |
---|
863 | 902 | { |
---|
864 | 903 | struct ieee80211_sub_if_data *sdata = sta->sdata; |
---|
865 | 904 | bool send_delba = false; |
---|
| 905 | + bool start_txq = false; |
---|
866 | 906 | |
---|
867 | 907 | ht_dbg(sdata, "Stopping Tx BA session for %pM tid %d\n", |
---|
868 | 908 | sta->sta.addr, tid); |
---|
.. | .. |
---|
880 | 920 | send_delba = true; |
---|
881 | 921 | |
---|
882 | 922 | ieee80211_remove_tid_tx(sta, tid); |
---|
| 923 | + start_txq = true; |
---|
883 | 924 | |
---|
884 | 925 | unlock_sta: |
---|
885 | 926 | spin_unlock_bh(&sta->lock); |
---|
886 | 927 | |
---|
| 928 | + if (start_txq) |
---|
| 929 | + ieee80211_agg_start_txq(sta, tid, false); |
---|
| 930 | + |
---|
887 | 931 | if (send_delba) |
---|
888 | 932 | ieee80211_send_delba(sdata, sta->sta.addr, tid, |
---|
889 | 933 | WLAN_BACK_INITIATOR, WLAN_REASON_QSTA_NOT_USE); |
---|