The branch main has been updated by bz:

URL: 
https://cgit.FreeBSD.org/src/commit/?id=fb97712a7f13b85ca707f52f206a2944ee66cf2c

commit fb97712a7f13b85ca707f52f206a2944ee66cf2c
Author:     Bjoern A. Zeeb <[email protected]>
AuthorDate: 2026-04-26 19:58:08 +0000
Commit:     Bjoern A. Zeeb <[email protected]>
CommitDate: 2026-06-05 12:09:22 +0000

    LinuxKPI: 802.11: implement ieee80211_start_tx_ba_session()
    
    Implement ieee80211_start_tx_ba_session() as a start for rtw8x (and
    select mt76 chipsets) to support more throughput.
    
    Sponsored by:   The FreeBSD Foundation
    MFC after:      3 days
---
 sys/compat/linuxkpi/common/include/net/mac80211.h |   6 +-
 sys/compat/linuxkpi/common/src/linux_80211.c      | 102 ++++++++++++++++++++++
 2 files changed, 105 insertions(+), 3 deletions(-)

diff --git a/sys/compat/linuxkpi/common/include/net/mac80211.h 
b/sys/compat/linuxkpi/common/include/net/mac80211.h
index 3c783d1f3c8a..c77d37e72fd1 100644
--- a/sys/compat/linuxkpi/common/include/net/mac80211.h
+++ b/sys/compat/linuxkpi/common/include/net/mac80211.h
@@ -1197,6 +1197,7 @@ void linuxkpi_ieee80211_schedule_txq(struct ieee80211_hw 
*,
     struct ieee80211_txq *, bool);
 void linuxkpi_ieee80211_handle_wake_tx_queue(struct ieee80211_hw *,
        struct ieee80211_txq *);
+int linuxkpi_ieee80211_start_tx_ba_session(struct ieee80211_sta *, uint8_t, 
int);
 
 /* -------------------------------------------------------------------------- 
*/
 
@@ -2118,10 +2119,9 @@ ieee80211_sta_eosp(struct ieee80211_sta *sta)
 }
 
 static __inline int
-ieee80211_start_tx_ba_session(struct ieee80211_sta *sta, uint8_t tid, int x)
+ieee80211_start_tx_ba_session(struct ieee80211_sta *sta, uint8_t tid, int 
timeout)
 {
-       TODO("rtw8x");
-       return (-EINVAL);
+       return (linuxkpi_ieee80211_start_tx_ba_session(sta, tid, timeout));
 }
 
 static __inline int
diff --git a/sys/compat/linuxkpi/common/src/linux_80211.c 
b/sys/compat/linuxkpi/common/src/linux_80211.c
index 901c59702840..7e55e0912bb1 100644
--- a/sys/compat/linuxkpi/common/src/linux_80211.c
+++ b/sys/compat/linuxkpi/common/src/linux_80211.c
@@ -6441,6 +6441,108 @@ net80211_only:
 }
 #endif
 
+int
+linuxkpi_ieee80211_start_tx_ba_session(struct ieee80211_sta *sta, uint8_t tid,
+    int timeout)
+{
+       struct lkpi_sta *lsta;
+       struct ieee80211_hw *hw;
+       struct lkpi_hw *lhw;
+       struct ieee80211_tx_ampdu *tap;
+       int worked;
+
+       lsta = STA_TO_LSTA(sta);
+
+       /* If tid is out of range, fail gracefully. */
+       /* XXX-BZ are we limited to 8? */
+       if (tid >= IEEE80211_NUM_TIDS) {
+               net80211_vap_printf(lsta->ni->ni_vap, "%s: tid %u out of range "
+                   ">= %u\n", __func__, tid, IEEE80211_NUM_TIDS);
+               return (-EINVAL);
+       }
+
+       hw = lsta->hw;
+       lhw = HW_TO_LHW(hw);
+
+       /* No ampdu_action support, just error. */
+       if (lhw->ops->ampdu_action == NULL) {
+               net80211_vap_printf(lsta->ni->ni_vap, "%s: (*ampdu_action) "
+                   "not supported\n", __func__);
+               return (-ENOTSUPP);
+       }
+
+       /* Does HW allow us to set this up? */
+       if (!ieee80211_hw_check(hw, AMPDU_AGGREGATION)) {
+               net80211_vap_printf(lsta->ni->ni_vap, "%s: 
!AMPDU_AGGREGATION\n",
+                   __func__);
+               return (-ENOTSUPP);
+       }
+       if (ieee80211_hw_check(hw, TX_AMPDU_SETUP_IN_HW)) {
+               net80211_vap_printf(lsta->ni->ni_vap, "%s: 
TX_AMPDU_SETUP_IN_HW\n",
+                   __func__);
+               return (-EPERM);
+       }
+
+       /* We need at least HT or higher support enabled. */
+       if (!sta->deflink.ht_cap.ht_supported &&
+           !sta->deflink.vht_cap.vht_supported &&
+           !sta->deflink.he_cap.has_he &&
+           !sta->deflink.eht_cap.has_eht) {
+               net80211_vap_printf(lsta->ni->ni_vap, "%s: HT or later not "
+                   "supported\n", __func__);
+               return (-ENOTSUPP);
+       }
+
+#ifdef __notyet__
+       /*
+        * We need some rate limiting/disabling in case we try too hard and
+        * get NACKed over and over.
+        * XXX-BZ This check should likely go to addba_req along with a counter.
+        */
+       if (lsta->block_ba)
+               return (-EACCESS);
+#endif
+
+       /* XXX-BZ locking? */
+
+       /* Do we have a running session already? */
+       tap = &lsta->ni->ni_tx_ampdu[tid];
+       if (IEEE80211_AMPDU_REQUESTED(tap)) {
+               net80211_vap_printf(lsta->ni->ni_vap, "%s: "
+                   "AMPDU requested/running\n", __func__);
+               return (-EINPROGRESS);
+       }
+
+       /* Tell net80211 to setup an aggr sessions. */
+       /* XXX-BZ we have no way to carry the timeout forward easily. */
+       worked = ieee80211_ampdu_tx_request_ext(lsta->ni, tid);
+       TRACEOK("ieee80211_ampdu_tx_request_ext %d", worked);
+
+       if (worked != 1) {
+               net80211_vap_printf(lsta->ni->ni_vap, "%s: "
+                   "ieee80211_ampdu_tx_request_ext returned %d != 1\n",
+                   __func__, worked);
+               return (-EINVAL);
+       }
+
+       /*
+        * How do we make sure the EAPOL handshake has completed?
+        * Let ieee80211_output do it.
+        */
+       if (1) {
+               /* Immediately trigger the setup and output of the action 
frame. */
+               worked = ieee80211_ampdu_request(lsta->ni, tap);
+               if (worked != 1) {
+                       net80211_vap_printf(lsta->ni->ni_vap, "%s: "
+                           "ieee80211_ampdu_request returned %d != 1\n",
+                           __func__, worked);
+                       return (-EAGAIN);
+               }
+       }
+
+       return (0);
+}
+
 static void
 lkpi_ic_getradiocaps_ht(struct ieee80211com *ic, struct ieee80211_hw *hw,
     uint8_t *bands, int *chan_flags, enum nl80211_band band)

Reply via email to