The branch main has been updated by adrian:

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

commit 00b4d712e2be54b8c87a7fd7f215ad5ef7845d5b
Author:     Adrian Chadd <[email protected]>
AuthorDate: 2025-11-13 04:33:52 +0000
Commit:     Adrian Chadd <[email protected]>
CommitDate: 2025-11-14 02:37:16 +0000

    iwx: clean up TX AMPDU session establishment and checking
    
    * Send a TX A-MPDU exchange successfully; we were allocating the
      A-MPDU TX queue but returning 0 to net80211 was telling it
      to not establish the TX A-MPDU session and none of the BA session
      tracking stuff would work.
    
    * Clean up the TX A-MPDU queue lookup in the transmit path - only
      QoS data frames are allowed, not qos null-data, cf/ack/etc frames;
      only send them if the A-MPDU session is established.
    
    * Tell net80211 that we've established the TX A-MPDU session once
      the firmware queue has been created.
    
    * Check to make sure we're not double (or more) creating TX AMDPU
      sessions - only allocate a qid if we're not doing A-MPDU yet.
    
    * Delete IWX_FLAG_A-MPDUTX - it's now being properly tracked!
    
    Locally tested:
    
    * AX210, STA mode - gets 50/50mbit on 2GHz HT20, and 100/100mbit on
      5GHz VHT/40.
    
    Differential Revision:  https://reviews.freebsd.org/D53725
    Reviewed by:    thj
---
 sys/dev/iwx/if_iwx.c       | 109 ++++++++++++++++++++++++++++++++++-----------
 sys/dev/iwx/if_iwx_debug.h |   3 +-
 sys/dev/iwx/if_iwxvar.h    |   1 -
 3 files changed, 85 insertions(+), 28 deletions(-)

diff --git a/sys/dev/iwx/if_iwx.c b/sys/dev/iwx/if_iwx.c
index dac1c563c593..e317ff9e271c 100644
--- a/sys/dev/iwx/if_iwx.c
+++ b/sys/dev/iwx/if_iwx.c
@@ -3429,6 +3429,14 @@ iwx_sta_rx_agg(struct iwx_softc *sc, struct 
ieee80211_node *ni, uint8_t tid,
                sc->sc_rx_ba_sessions--;
 }
 
+/**
+ * @brief Allocate an A-MPDU / aggregation session for the given node and TID.
+ *
+ * This allocates a TX queue specifically for that TID.
+ *
+ * Note that this routine currently doesn't return any status/errors,
+ * so the caller can't know if the aggregation session was setup or not.
+ */
 static void
 iwx_sta_tx_agg_start(struct iwx_softc *sc, struct ieee80211_node *ni,
     uint8_t tid)
@@ -3502,6 +3510,14 @@ iwx_ba_rx_task(void *arg, int npending __unused)
        IWX_UNLOCK(sc);
 }
 
+/**
+ * @brief Task called to setup a deferred block-ack session.
+ *
+ * This sets up any/all pending blockack sessions as defined
+ * in sc->ba_tx.start_tidmask.
+ *
+ * Note: the call to iwx_sta_tx_agg_start() isn't being error checked.
+ */
 static void
 iwx_ba_tx_task(void *arg, int npending __unused)
 {
@@ -3509,22 +3525,38 @@ iwx_ba_tx_task(void *arg, int npending __unused)
        struct ieee80211com *ic = &sc->sc_ic;
        struct ieee80211vap *vap = TAILQ_FIRST(&ic->ic_vaps);
        struct ieee80211_node *ni = vap->iv_bss;
+       uint32_t started_mask = 0;
        int tid;
 
        IWX_LOCK(sc);
        for (tid = 0; tid < IWX_MAX_TID_COUNT; tid++) {
+               const struct ieee80211_tx_ampdu *tap;
+
                if (sc->sc_flags & IWX_FLAG_SHUTDOWN)
                        break;
+               tap = &ni->ni_tx_ampdu[tid];
+               if (IEEE80211_AMPDU_RUNNING(tap))
+                       break;
                if (sc->ba_tx.start_tidmask & (1 << tid)) {
-                       DPRINTF(("%s: ampdu tx start for tid %i\n", __func__,
-                           tid));
+                       IWX_DPRINTF(sc, IWX_DEBUG_AMPDU_MGMT,
+                           "%s: ampdu tx start for tid %i\n", __func__, tid);
                        iwx_sta_tx_agg_start(sc, ni, tid);
                        sc->ba_tx.start_tidmask &= ~(1 << tid);
-                       sc->sc_flags |= IWX_FLAG_AMPDUTX;
+                       started_mask |= (1 << tid);
                }
        }
 
        IWX_UNLOCK(sc);
+
+       /* Iterate over the sessions we started; mark them as active */
+       for (tid = 0; tid < IWX_MAX_TID_COUNT; tid++) {
+               if (started_mask & (1 << tid)) {
+                       IWX_DPRINTF(sc, IWX_DEBUG_AMPDU_MGMT,
+                           "%s: informing net80211 to start ampdu on tid %i\n",
+                           __func__, tid);
+                       ieee80211_ampdu_tx_request_active_ext(ni, tid, 1);
+               }
+       }
 }
 
 static void
@@ -5627,7 +5659,6 @@ iwx_tx(struct iwx_softc *sc, struct mbuf *m, struct 
ieee80211_node *ni)
        u_int hdrlen;
        uint32_t rate_n_flags;
        uint16_t num_tbs, flags, offload_assist = 0;
-       uint8_t type, subtype;
        int i, totlen, err, pad, qid;
 #define IWM_MAX_SCATTER 20
        bus_dma_segment_t *seg, segs[IWM_MAX_SCATTER];
@@ -5638,38 +5669,32 @@ iwx_tx(struct iwx_softc *sc, struct mbuf *m, struct 
ieee80211_node *ni)
        IWX_ASSERT_LOCKED(sc);
 
        wh = mtod(m, struct ieee80211_frame *);
-       type = wh->i_fc[0] & IEEE80211_FC0_TYPE_MASK;
-       subtype = wh->i_fc[0] & IEEE80211_FC0_SUBTYPE_MASK;
        hdrlen = ieee80211_anyhdrsize(wh);
 
        qid = sc->first_data_qid;
 
        /* Put QoS frames on the data queue which maps to their TID. */
-       if (IEEE80211_QOS_HAS_SEQ(wh) && (sc->sc_flags & IWX_FLAG_AMPDUTX)) {
+       if (IEEE80211_QOS_HAS_SEQ(wh)) {
                uint16_t qos = ieee80211_gettid(wh);
                uint8_t tid = qos & IEEE80211_QOS_TID;
-#if 0
+               struct ieee80211_tx_ampdu *tap = &ni->ni_tx_ampdu[tid];
+
                /*
-                * XXX-THJ: TODO when we enable ba we need to manage the
-                * mappings
+                * Note: we're currently putting all frames into one queue
+                * except for A-MPDU queues.  We should be able to choose
+                * other WME queues but first we need to verify they've been
+                * correctly setup for data.
                 */
-               struct ieee80211_tx_ba *ba;
-               ba = &ni->ni_tx_ba[tid];
 
-               if (!IEEE80211_IS_MULTICAST(wh->i_addr1) &&
-                   type == IEEE80211_FC0_TYPE_DATA &&
-                   subtype != IEEE80211_FC0_SUBTYPE_NODATA &&
-                   subtype != IEEE80211_FC0_SUBTYPE_BAR &&
-                   sc->aggqid[tid] != 0  /*&&
-                   ba->ba_state == IEEE80211_BA_AGREED*/) {
-                       qid = sc->aggqid[tid];
-#else
-               if (!IEEE80211_IS_MULTICAST(wh->i_addr1) &&
-                   type == IEEE80211_FC0_TYPE_DATA &&
-                   subtype != IEEE80211_FC0_SUBTYPE_NODATA &&
+               /*
+                * Only QoS data goes into an A-MPDU queue;
+                * don't add QoS null, the other data types, etc.
+                */
+               if (IEEE80211_AMPDU_RUNNING(tap) &&
+                   IEEE80211_IS_QOSDATA(wh) &&
+                   !IEEE80211_IS_MULTICAST(wh->i_addr1) &&
                    sc->aggqid[tid] != 0) {
                        qid = sc->aggqid[tid];
-#endif
                }
        }
 
@@ -10903,6 +10928,26 @@ iwx_ampdu_rx_stop(struct ieee80211_node *ni, struct 
ieee80211_rx_ampdu *rap)
        return;
 }
 
+/**
+ * @brief Called by net80211 to request an A-MPDU session be established.
+ *
+ * This is called by net80211 to see if an A-MPDU session can be established.
+ * However, the iwx(4) firmware will take care of establishing the BA
+ * session for us.  net80211 doesn't have to send any action frames here;
+ * it just needs to plumb up the ampdu session once the BA has been sent.
+ *
+ * If we return 0 here then the firmware will set up the state but net80211
+ * will not; so it's on us to actually complete it via a call to
+ * ieee80211_ampdu_tx_request_active_ext() .
+ *
+ * @param ni   ieee80211_node to establish A-MPDU session for
+ * @param tap  pointer to the per-TID state struct
+ * @param dialogtoken  dialogtoken field from the BA request
+ * @param baparamset   baparamset field from the BA request
+ * @param batimeout    batimeout field from the BA request
+ *
+ * @returns 0 so net80211 doesn't send the BA action frame to establish A-MPDU.
+ */
 static int
 iwx_addba_request(struct ieee80211_node *ni, struct ieee80211_tx_ampdu *tap,
     int dialogtoken, int baparamset, int batimeout)
@@ -10911,10 +10956,22 @@ iwx_addba_request(struct ieee80211_node *ni, struct 
ieee80211_tx_ampdu *tap,
        int tid;
 
        tid = _IEEE80211_MASKSHIFT(le16toh(baparamset), IEEE80211_BAPS_TID);
-       DPRINTF(("%s: tid=%i\n", __func__, tid));
+       IWX_DPRINTF(sc, IWX_DEBUG_AMPDU_MGMT,
+           "%s: queuing AMPDU start on tid %i\n", __func__, tid);
+
+       /* There's no nice way right now to tell net80211 that we're in the
+        * middle of an asynchronous ADDBA setup session.  So, bump the timeout
+        * to hz ticks, hopefully we'll get a response by then.
+        */
+       tap->txa_nextrequest = ticks + hz;
+
+       IWX_LOCK(sc);
        sc->ba_tx.start_tidmask |= (1 << tid);
+       IWX_UNLOCK(sc);
+
        taskqueue_enqueue(sc->sc_tq, &sc->ba_tx_task);
-       return 0;
+
+       return (0);
 }
 
 
diff --git a/sys/dev/iwx/if_iwx_debug.h b/sys/dev/iwx/if_iwx_debug.h
index ab8284a59e0f..5fc127d986a9 100644
--- a/sys/dev/iwx/if_iwx_debug.h
+++ b/sys/dev/iwx/if_iwx_debug.h
@@ -38,7 +38,8 @@ enum {
        IWX_DEBUG_LAR           = 0x00400000,   /* Location Aware Regulatory */
        IWX_DEBUG_TE            = 0x00800000,   /* Time Event handling */
        IWX_DEBUG_KEYMGMT       = 0x01000000,   /* Encryption key management */
-                                               /* 0x0e000000 are available */
+       IWX_DEBUG_AMPDU_MGMT    = 0x02000000,   /* AMPDU TX/RX management */
+                                               /* 0x0c000000 are available */
        IWX_DEBUG_NI            = 0x10000000,   /* Not Implemented  */
        IWX_DEBUG_REGISTER      = 0x20000000,   /* print chipset register */
        IWX_DEBUG_TRACE         = 0x40000000,   /* Print begin and start driver 
function */
diff --git a/sys/dev/iwx/if_iwxvar.h b/sys/dev/iwx/if_iwxvar.h
index 1ac0bc24577c..5ed749db631e 100644
--- a/sys/dev/iwx/if_iwxvar.h
+++ b/sys/dev/iwx/if_iwxvar.h
@@ -290,7 +290,6 @@ struct iwx_rx_ring {
 #define IWX_FLAG_BGSCAN                0x200   /* background scan in progress 
*/
 #define IWX_FLAG_TXFLUSH       0x400   /* Tx queue flushing in progress */
 #define IWX_FLAG_HW_INITED     0x800   /* Hardware initialized */
-#define        IWX_FLAG_AMPDUTX        0x1000
 
 struct iwx_ucode_status {
        uint32_t uc_lmac_error_event_table[2];

Reply via email to