The branch main has been updated by adrian:

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

commit 785edcc2af5ae32c24f5caf5b9552f62bdae33ee
Author:     Adrian Chadd <[email protected]>
AuthorDate: 2025-06-10 04:22:10 +0000
Commit:     Adrian Chadd <[email protected]>
CommitDate: 2025-09-20 00:42:45 +0000

    net80211: convert the rest of the native net80211 drivers to SEQNO_OFFLOAD
    
    * Convert the rest of the drivers to implement driver/offloaded sequence
      number handling.
    
    * For drivers that implement their own sequence number space handling
      for A-MPDU, only call ieee80211_output_seqno_assign() if the frame
      isn't tagged with M_AMPDU_MPDU, which mirrors the original net80211
      sequence number behaviour.  (Except of course, the assignment is
      now happening during final encap/transmit, not early in encap.)
    
    Locally tested (sta mode):
    
    * ath
    * iwn
    * bwi
    * bwn
    * iwm
    * otus
    * ral
    
    Differential Revision:  https://reviews.freebsd.org/D50772
    Okayed by: bz
---
 sys/dev/ath/if_ath.c    |  3 +++
 sys/dev/ath/if_ath_tx.c | 10 ++++++++++
 sys/dev/bwi/if_bwi.c    |  4 ++++
 sys/dev/bwn/if_bwn.c    |  2 ++
 sys/dev/ipw/if_ipw.c    |  3 +++
 sys/dev/iwi/if_iwi.c    |  4 ++++
 sys/dev/iwm/if_iwm.c    |  3 ++-
 sys/dev/iwn/if_iwn.c    | 10 ++++++++++
 sys/dev/malo/if_malo.c  |  4 ++++
 sys/dev/mwl/if_mwl.c    |  4 ++++
 sys/dev/otus/if_otus.c  | 11 +++++++++++
 sys/dev/ral/rt2560.c    |  4 ++++
 sys/dev/ral/rt2661.c    |  4 +++-
 sys/dev/ral/rt2860.c    |  3 +++
 14 files changed, 67 insertions(+), 2 deletions(-)

diff --git a/sys/dev/ath/if_ath.c b/sys/dev/ath/if_ath.c
index 934024ddfbcf..1304b597c545 100644
--- a/sys/dev/ath/if_ath.c
+++ b/sys/dev/ath/if_ath.c
@@ -924,6 +924,9 @@ ath_attach(u_int16_t devid, struct ath_softc *sc)
                | IEEE80211_C_PMGT              /* Station side power mgmt */
                | IEEE80211_C_SWSLEEP
                ;
+
+       ic->ic_flags_ext |= IEEE80211_FEXT_SEQNO_OFFLOAD;
+
        /*
         * Query the hal to figure out h/w crypto support.
         */
diff --git a/sys/dev/ath/if_ath_tx.c b/sys/dev/ath/if_ath_tx.c
index 1559b66a7c7d..deadd63c3d18 100644
--- a/sys/dev/ath/if_ath_tx.c
+++ b/sys/dev/ath/if_ath_tx.c
@@ -1588,6 +1588,10 @@ ath_tx_normal_setup(struct ath_softc *sc, struct 
ieee80211_node *ni,
         */
        pktlen = m0->m_pkthdr.len - (hdrlen & 3);
 
+       /* seqno allocate, only if AMPDU isn't running */
+       if ((m0->m_flags & M_AMPDU_MPDU) == 0)
+               ieee80211_output_seqno_assign(ni, -1, m0);
+
        /* Handle encryption twiddling if needed */
        if (! ath_tx_tag_crypto(sc, ni, m0, iswep, isfrag, &hdrlen,
            &pktlen, &keyix)) {
@@ -2201,6 +2205,10 @@ ath_tx_raw_start(struct ath_softc *sc, struct 
ieee80211_node *ni,
         * for QoS frames.
         */
 
+       /* seqno allocate, only if AMPDU isn't running */
+       if ((m0->m_flags & M_AMPDU_MPDU) == 0)
+               ieee80211_output_seqno_assign(ni, -1, m0);
+
        /* Handle encryption twiddling if needed */
        if (! ath_tx_tag_crypto(sc, ni,
            m0, params->ibp_flags & IEEE80211_BPF_CRYPTO, 0,
@@ -2981,6 +2989,8 @@ ath_tx_tid_seqno_assign(struct ath_softc *sc, struct 
ieee80211_node *ni,
 
        ATH_TX_LOCK_ASSERT(sc);
 
+       /* TODO: can this use ieee80211_output_seqno_assign() now? */
+
        /*
         * Is it a QOS NULL Data frame? Give it a sequence number from
         * the default TID (IEEE80211_NONQOS_TID.)
diff --git a/sys/dev/bwi/if_bwi.c b/sys/dev/bwi/if_bwi.c
index 1087ca813d65..85146d4c4010 100644
--- a/sys/dev/bwi/if_bwi.c
+++ b/sys/dev/bwi/if_bwi.c
@@ -498,6 +498,9 @@ bwi_attach(struct bwi_softc *sc)
                      IEEE80211_C_BGSCAN |
                      IEEE80211_C_MONITOR;
        ic->ic_opmode = IEEE80211_M_STA;
+
+       ic->ic_flags_ext |= IEEE80211_FEXT_SEQNO_OFFLOAD;
+
        ieee80211_ifattach(ic);
 
        ic->ic_headroom = sizeof(struct bwi_txbuf_hdr);
@@ -1361,6 +1364,7 @@ bwi_start_locked(struct bwi_softc *sc)
            (m = mbufq_dequeue(&sc->sc_snd)) != NULL) {
                ni = (struct ieee80211_node *) m->m_pkthdr.rcvif;
                wh = mtod(m, struct ieee80211_frame *);
+               ieee80211_output_seqno_assign(ni, -1, m);
                if ((wh->i_fc[1] & IEEE80211_FC1_PROTECTED) != 0 &&
                    ieee80211_crypto_encap(ni, m) == NULL) {
                        if_inc_counter(ni->ni_vap->iv_ifp,
diff --git a/sys/dev/bwn/if_bwn.c b/sys/dev/bwn/if_bwn.c
index 38bf6f5d31a3..ec9d56661034 100644
--- a/sys/dev/bwn/if_bwn.c
+++ b/sys/dev/bwn/if_bwn.c
@@ -774,6 +774,7 @@ bwn_attach_post(struct bwn_softc *sc)
                ;
 
        ic->ic_flags_ext |= IEEE80211_FEXT_SWBMISS;     /* s/w bmiss */
+       ic->ic_flags_ext |= IEEE80211_FEXT_SEQNO_OFFLOAD;
 
        /* Determine the NVRAM variable containing our MAC address */
        core_unit = bhnd_get_core_unit(sc->sc_dev);
@@ -999,6 +1000,7 @@ bwn_start(struct bwn_softc *sc)
                        continue;
                }
                wh = mtod(m, struct ieee80211_frame *);
+               ieee80211_output_seqno_assign(ni, -1, m);
                if (wh->i_fc[1] & IEEE80211_FC1_PROTECTED) {
                        k = ieee80211_crypto_encap(ni, m);
                        if (k == NULL) {
diff --git a/sys/dev/ipw/if_ipw.c b/sys/dev/ipw/if_ipw.c
index 01d713cdae18..9db562669487 100644
--- a/sys/dev/ipw/if_ipw.c
+++ b/sys/dev/ipw/if_ipw.c
@@ -283,6 +283,8 @@ ipw_attach(device_t dev)
                | IEEE80211_C_WPA               /* 802.11i supported */
                ;
 
+       ic->ic_flags_ext |= IEEE80211_FEXT_SEQNO_OFFLOAD;
+
        /* read MAC address from EEPROM */
        val = ipw_read_prom_word(sc, IPW_EEPROM_MAC + 0);
        ic->ic_macaddr[0] = val >> 8;
@@ -1557,6 +1559,7 @@ ipw_tx_start(struct ipw_softc *sc, struct mbuf *m0, 
struct ieee80211_node *ni)
 
        wh = mtod(m0, struct ieee80211_frame *);
 
+       ieee80211_output_seqno_assign(ni, -1, m0);
        if (wh->i_fc[1] & IEEE80211_FC1_PROTECTED) {
                k = ieee80211_crypto_encap(ni, m0);
                if (k == NULL) {
diff --git a/sys/dev/iwi/if_iwi.c b/sys/dev/iwi/if_iwi.c
index 3a410a5cbf2c..26b8037186a6 100644
--- a/sys/dev/iwi/if_iwi.c
+++ b/sys/dev/iwi/if_iwi.c
@@ -371,6 +371,8 @@ iwi_attach(device_t dev)
 #endif
            ;
 
+       ic->ic_flags_ext |= IEEE80211_FEXT_SEQNO_OFFLOAD;
+
        /* read MAC address from EEPROM */
        val = iwi_read_prom_word(sc, IWI_EEPROM_MAC + 0);
        ic->ic_macaddr[0] = val & 0xff;
@@ -1834,6 +1836,8 @@ iwi_tx_start(struct iwi_softc *sc, struct mbuf *m0, 
struct ieee80211_node *ni,
        } else
                staid = 0;
 
+       ieee80211_output_seqno_assign(ni, -1, m0);
+
        if (wh->i_fc[1] & IEEE80211_FC1_PROTECTED) {
                k = ieee80211_crypto_encap(ni, m0);
                if (k == NULL) {
diff --git a/sys/dev/iwm/if_iwm.c b/sys/dev/iwm/if_iwm.c
index 1e9090310ece..9f590f11864c 100644
--- a/sys/dev/iwm/if_iwm.c
+++ b/sys/dev/iwm/if_iwm.c
@@ -6142,7 +6142,8 @@ iwm_attach(device_t dev)
 //         IEEE80211_C_BGSCAN          /* capable of bg scanning */
            ;
        /* Advertise full-offload scanning */
-       ic->ic_flags_ext = IEEE80211_FEXT_SCAN_OFFLOAD;
+       ic->ic_flags_ext |= IEEE80211_FEXT_SCAN_OFFLOAD;
+       ic->ic_flags_ext |= IEEE80211_FEXT_SEQNO_OFFLOAD;
        for (i = 0; i < nitems(sc->sc_phyctxt); i++) {
                sc->sc_phyctxt[i].id = i;
                sc->sc_phyctxt[i].color = 0;
diff --git a/sys/dev/iwn/if_iwn.c b/sys/dev/iwn/if_iwn.c
index b7c452a4f074..6270de3627e6 100644
--- a/sys/dev/iwn/if_iwn.c
+++ b/sys/dev/iwn/if_iwn.c
@@ -584,6 +584,9 @@ iwn_attach(device_t dev)
                | IEEE80211_C_PMGT              /* Station-side power mgmt */
                ;
 
+       /* Driver / firmware assigned sequence numbers */
+       ic->ic_flags_ext |= IEEE80211_FEXT_SEQNO_OFFLOAD;
+
        /* Read MAC address, channels, etc from EEPROM. */
        if ((error = iwn_read_eeprom(sc, ic->ic_macaddr)) != 0) {
                device_printf(dev, "could not read EEPROM, error %d\n",
@@ -4577,6 +4580,9 @@ iwn_tx_data(struct iwn_softc *sc, struct mbuf *m, struct 
ieee80211_node *ni)
         * XXX TODO: Group addressed frames aren't aggregated and must
         * go to the normal non-aggregation queue, and have a NONQOS TID
         * assigned from net80211.
+        *
+        * TODO: same with NULL QOS frames, which we shouldn't be sending
+        * anyway ourselves (and should stub out / warn / etc.)
         */
 
        ac = M_WME_GETAC(m);
@@ -4589,6 +4595,10 @@ iwn_tx_data(struct iwn_softc *sc, struct mbuf *m, struct 
ieee80211_node *ni)
                ac = *(int *)tap->txa_private;
        }
 
+       /* Only assign if not A-MPDU; the A-MPDU TX path will do its own */
+       if ((m->m_flags & M_AMPDU_MPDU) == 0)
+               ieee80211_output_seqno_assign(ni, -1, m);
+
        /* Encrypt the frame if need be. */
        if (wh->i_fc[1] & IEEE80211_FC1_PROTECTED) {
                /* Retrieve key for TX. */
diff --git a/sys/dev/malo/if_malo.c b/sys/dev/malo/if_malo.c
index 79a3213c6802..2e4f3967ace4 100644
--- a/sys/dev/malo/if_malo.c
+++ b/sys/dev/malo/if_malo.c
@@ -263,6 +263,8 @@ malo_attach(uint16_t devid, struct malo_softc *sc)
            ;
        IEEE80211_ADDR_COPY(ic->ic_macaddr, sc->malo_hwspecs.macaddr);
 
+       ic->ic_flags_ext |= IEEE80211_FEXT_SEQNO_OFFLOAD;
+
        /*
         * Transmit requires space in the packet for a special format transmit
         * record and optional padding between this record and the payload.
@@ -1040,6 +1042,8 @@ malo_tx_start(struct malo_softc *sc, struct 
ieee80211_node *ni,
        } else
                qos = 0;
 
+       ieee80211_output_seqno_assign(ni, -1, m0);
+
        if (iswep) {
                struct ieee80211_key *k;
 
diff --git a/sys/dev/mwl/if_mwl.c b/sys/dev/mwl/if_mwl.c
index c885968dfe15..9f3d34f4f50d 100644
--- a/sys/dev/mwl/if_mwl.c
+++ b/sys/dev/mwl/if_mwl.c
@@ -433,6 +433,8 @@ mwl_attach(uint16_t devid, struct mwl_softc *sc)
                | IEEE80211_HTC_SMPS            /* SMPS available */
                ;
 
+       ic->ic_flags_ext |= IEEE80211_FEXT_SEQNO_OFFLOAD;
+
        /*
         * Mark h/w crypto support.
         * XXX no way to query h/w support.
@@ -3087,6 +3089,8 @@ mwl_tx_start(struct mwl_softc *sc, struct ieee80211_node 
*ni, struct mwl_txbuf *
        } else
                qos = 0;
 
+       ieee80211_output_seqno_assign(ni, -1, m0);
+
        if (iswep) {
                const struct ieee80211_cipher *cip;
                struct ieee80211_key *k;
diff --git a/sys/dev/otus/if_otus.c b/sys/dev/otus/if_otus.c
index 5919e75a59cf..f6c4a0118b68 100644
--- a/sys/dev/otus/if_otus.c
+++ b/sys/dev/otus/if_otus.c
@@ -728,6 +728,12 @@ otus_attachhook(struct otus_softc *sc)
            IEEE80211_C_SWAMSDUTX |     /* Do software A-MSDU TX */
            IEEE80211_C_WPA;            /* WPA/RSN. */
 
+       /*
+        * Although A-MPDU RX is fine, A-MPDU TX apparently has some
+        * hardware bugs.  Looking at Linux carl9170, it has a work-around
+        * that forces all frames into the AC_BE queue regardless of
+        * the actual QoS queue.
+        */
        ic->ic_htcaps =
            IEEE80211_HTC_HT |
 #if 0
@@ -737,6 +743,8 @@ otus_attachhook(struct otus_softc *sc)
            IEEE80211_HTCAP_MAXAMSDU_3839 |
            IEEE80211_HTCAP_SMPS_OFF;
 
+       ic->ic_flags_ext |= IEEE80211_FEXT_SEQNO_OFFLOAD;
+
        otus_getradiocaps(ic, IEEE80211_CHAN_MAX, &ic->ic_nchans,
            ic->ic_channels);
 
@@ -2232,6 +2240,9 @@ otus_tx(struct otus_softc *sc, struct ieee80211_node *ni, 
struct mbuf *m,
        int hasqos, xferlen, type, ismcast;
 
        wh = mtod(m, struct ieee80211_frame *);
+
+       ieee80211_output_seqno_assign(ni, -1, m);
+
        if (wh->i_fc[1] & IEEE80211_FC1_PROTECTED) {
                k = ieee80211_crypto_encap(ni, m);
                if (k == NULL) {
diff --git a/sys/dev/ral/rt2560.c b/sys/dev/ral/rt2560.c
index 09b01ea55be9..7feb324eb21d 100644
--- a/sys/dev/ral/rt2560.c
+++ b/sys/dev/ral/rt2560.c
@@ -281,6 +281,8 @@ rt2560_attach(device_t dev, int id)
 #endif
                ;
 
+       ic->ic_flags_ext |= IEEE80211_FEXT_SEQNO_OFFLOAD;
+
        rt2560_getradiocaps(ic, IEEE80211_CHAN_MAX, &ic->ic_nchans,
            ic->ic_channels);
 
@@ -1516,6 +1518,8 @@ rt2560_tx_mgt(struct rt2560_softc *sc, struct mbuf *m0,
 
        wh = mtod(m0, struct ieee80211_frame *);
 
+       ieee80211_output_seqno_assign(ni, -1, m0);
+
        if (wh->i_fc[1] & IEEE80211_FC1_PROTECTED) {
                k = ieee80211_crypto_encap(ni, m0);
                if (k == NULL) {
diff --git a/sys/dev/ral/rt2661.c b/sys/dev/ral/rt2661.c
index 38cd99d899ed..c9c86d4f089a 100644
--- a/sys/dev/ral/rt2661.c
+++ b/sys/dev/ral/rt2661.c
@@ -282,6 +282,8 @@ rt2661_attach(device_t dev, int id)
 #endif
                ;
 
+       ic->ic_flags_ext |= IEEE80211_FEXT_SEQNO_OFFLOAD;
+
        rt2661_getradiocaps(ic, IEEE80211_CHAN_MAX, &ic->ic_nchans,
            ic->ic_channels);
 
@@ -1284,7 +1286,7 @@ rt2661_tx_mgt(struct rt2661_softc *sc, struct mbuf *m0,
        rate = ni->ni_txparms->mgmtrate;
 
        wh = mtod(m0, struct ieee80211_frame *);
-
+       ieee80211_output_seqno_assign(ni, -1, m0);
        if (wh->i_fc[1] & IEEE80211_FC1_PROTECTED) {
                k = ieee80211_crypto_encap(ni, m0);
                if (k == NULL) {
diff --git a/sys/dev/ral/rt2860.c b/sys/dev/ral/rt2860.c
index 1449df683a93..76fe4652839d 100644
--- a/sys/dev/ral/rt2860.c
+++ b/sys/dev/ral/rt2860.c
@@ -323,6 +323,8 @@ rt2860_attach(device_t dev, int id)
                | IEEE80211_C_WME               /* 802.11e */
                ;
 
+       ic->ic_flags_ext |= IEEE80211_FEXT_SEQNO_OFFLOAD;
+
        rt2860_getradiocaps(ic, IEEE80211_CHAN_MAX, &ic->ic_nchans,
            ic->ic_channels);
 
@@ -1471,6 +1473,7 @@ rt2860_tx(struct rt2860_softc *sc, struct mbuf *m, struct 
ieee80211_node *ni)
 
        wh = mtod(m, struct ieee80211_frame *);
 
+       ieee80211_output_seqno_assign(ni, -1, m);
        if (wh->i_fc[1] & IEEE80211_FC1_PROTECTED) {
                k = ieee80211_crypto_encap(ni, m);
                if (k == NULL) {

Reply via email to