Author: adrian
Date: Fri May 29 15:56:44 2020
New Revision: 361626
URL: https://svnweb.freebsd.org/changeset/base/361626

Log:
  [run] Add initial 802.11n support.
  
  * Enable self-generated 11n frames
  * add MCS rates for 1-stream and 2-stream rates; will do 3-stream
    once the rest of this tests out OK with other people.
  * Hard-code 1 stream for now
  * Add A-MPDU RX mbuf tagging
  * RTS/CTS if doing RTSCTS in HT protmode as well as legacy; they're
    separate configuration flags
  * Update the amrr rate index stuff - walk the rates array like others
    to find the right one - this now works for MCS and CCK/OFDM rates
  * Add support for atheros fast frames/AMSDU support as we can generate
    those in net80211.
  
  TODO:
  
  * HT40 isn't enabled yet
  * No A-MPDU support just yet; that requires some more firmware research
    and maybe porting some ath(4) A-MPDU support/tracking into net80211
  * Short preamble flags aren't set yet for MCS; need to check the linux
    driver and see what's going on there
  * Add 3x3 rates and set tx/rx stream configuration appropriately
  * More 5GHz testing; I have a 3x3 dual band USB NIC coming soon that'll
    let me test this.
  * Figure out why the RX path isn't performing as fast as it could -
    there's only a single buffer loaded at a time for the receive path
    in the USB bulk handler and this may not be super useful.
  
  Tested:
  
  * RT5390 usb, 1x1, RF5370 (2GHz radio), STA mode - A-MSDU TX, A-MPDU RX
  
  Submitted by: Ashish Gupta <ashis...@andrew.cmu.edu>
  Differential Revision:        https://reviews.freebsd.org/D22840

Modified:
  head/sys/dev/usb/wlan/if_run.c
  head/sys/dev/usb/wlan/if_runreg.h
  head/sys/dev/usb/wlan/if_runvar.h

Modified: head/sys/dev/usb/wlan/if_run.c
==============================================================================
--- head/sys/dev/usb/wlan/if_run.c      Fri May 29 13:07:52 2020        
(r361625)
+++ head/sys/dev/usb/wlan/if_run.c      Fri May 29 15:56:44 2020        
(r361626)
@@ -64,6 +64,9 @@ __FBSDID("$FreeBSD$");
 #include <net80211/ieee80211_regdomain.h>
 #include <net80211/ieee80211_radiotap.h>
 #include <net80211/ieee80211_ratectl.h>
+#ifdef IEEE80211_SUPPORT_SUPERG
+#include <net80211/ieee80211_superg.h>
+#endif
 
 #include <dev/usb/usb.h>
 #include <dev/usb/usbdi.h>
@@ -495,6 +498,9 @@ static void run_adjust_freq_offset(struct run_softc *)
 static void    run_init_locked(struct run_softc *);
 static void    run_stop(void *);
 static void    run_delay(struct run_softc *, u_int);
+static void    run_update_chw(struct ieee80211com *ic);
+static int     run_ampdu_enable(struct ieee80211_node *ni,
+                   struct ieee80211_tx_ampdu *tap);
 
 static eventhandler_tag run_etag;
 
@@ -506,10 +512,13 @@ static const struct rt2860_rate {
        uint16_t        sp_ack_dur;
        uint16_t        lp_ack_dur;
 } rt2860_rates[] = {
+       /* CCK rates (11b) */
        {   2, 0, IEEE80211_T_DS,   0, 314, 314 },
        {   4, 1, IEEE80211_T_DS,   1, 258, 162 },
        {  11, 2, IEEE80211_T_DS,   2, 223, 127 },
        {  22, 3, IEEE80211_T_DS,   3, 213, 117 },
+
+       /* OFDM rates (11a / 11g) */
        {  12, 0, IEEE80211_T_OFDM, 4,  60,  60 },
        {  18, 1, IEEE80211_T_OFDM, 4,  52,  52 },
        {  24, 2, IEEE80211_T_OFDM, 6,  48,  48 },
@@ -517,9 +526,35 @@ static const struct rt2860_rate {
        {  48, 4, IEEE80211_T_OFDM, 8,  44,  44 },
        {  72, 5, IEEE80211_T_OFDM, 8,  40,  40 },
        {  96, 6, IEEE80211_T_OFDM, 8,  40,  40 },
-       { 108, 7, IEEE80211_T_OFDM, 8,  40,  40 }
+       { 108, 7, IEEE80211_T_OFDM, 8,  40,  40 },
+
+       /* MCS - single stream */
+       {  0x80, 0, IEEE80211_T_HT, 4, 60, 60 },
+       {  0x81, 1, IEEE80211_T_HT, 4, 60, 60 },
+       {  0x82, 2, IEEE80211_T_HT, 4, 60, 60 },
+       {  0x83, 3, IEEE80211_T_HT, 4, 60, 60 },
+       {  0x84, 4, IEEE80211_T_HT, 4, 60, 60 },
+       {  0x85, 5, IEEE80211_T_HT, 4, 60, 60 },
+       {  0x86, 6, IEEE80211_T_HT, 4, 60, 60 },
+       {  0x87, 7, IEEE80211_T_HT, 4, 60, 60 },
+       /* MCS - 2 streams */
+       {  0x88, 8, IEEE80211_T_HT, 4, 60, 60 },
+       {  0x89, 9, IEEE80211_T_HT, 4, 60, 60 },
+       {  0x8a, 10, IEEE80211_T_HT, 4, 60, 60 },
+       {  0x8b, 11, IEEE80211_T_HT, 4, 60, 60 },
+       {  0x8c, 12, IEEE80211_T_HT, 4, 60, 60 },
+       {  0x8d, 13, IEEE80211_T_HT, 4, 60, 60 },
+       {  0x8e, 14, IEEE80211_T_HT, 4, 60, 60 },
+       {  0x8f, 15, IEEE80211_T_HT, 4, 60, 60 },
 };
 
+/* These are indexes into the above rt2860_rates[] array */
+#define        RT2860_RIDX_CCK1                0
+#define        RT2860_RIDX_CCK11               3
+#define        RT2860_RIDX_OFDM6               4
+#define        RT2860_RIDX_MCS0                12
+#define        RT2860_RIDX_MAX                 28
+
 static const struct {
        uint16_t        reg;
        uint32_t        val;
@@ -807,9 +842,25 @@ run_attach(device_t self)
            IEEE80211_C_MBSS |
            IEEE80211_C_SHPREAMBLE |    /* short preamble supported */
            IEEE80211_C_SHSLOT |        /* short slot time supported */
+           IEEE80211_C_SWAMSDUTX |     /* Do software A-MSDU TX */
+           IEEE80211_C_FF |            /* Atheros fast-frames */
            IEEE80211_C_WME |           /* WME */
            IEEE80211_C_WPA;            /* WPA1|WPA2(RSN) */
 
+       ic->ic_htcaps =
+                   IEEE80211_HTC_HT |
+                   IEEE80211_HTC_AMPDU |
+                   IEEE80211_HTC_AMSDU |
+                   IEEE80211_HTCAP_MAXAMSDU_3839 |
+                   IEEE80211_HTCAP_SMPS_OFF;
+
+       /*
+        * For now, just do 1 stream.  Later on we'll figure out
+        * how many tx/rx streams a particular NIC supports.
+        */
+       ic->ic_rxstream = 1;
+       ic->ic_txstream = 1;
+
        ic->ic_cryptocaps =
            IEEE80211_CRYPTO_WEP |
            IEEE80211_CRYPTO_AES_CCM |
@@ -839,6 +890,8 @@ run_attach(device_t self)
        ic->ic_vap_delete = run_vap_delete;
        ic->ic_transmit = run_transmit;
        ic->ic_parent = run_parent;
+       ic->ic_update_chw = run_update_chw;
+       ic->ic_ampdu_enable = run_ampdu_enable;
 
        ieee80211_radiotap_attach(ic,
            &sc->sc_txtap.wt_ihdr, sizeof(sc->sc_txtap),
@@ -974,6 +1027,10 @@ run_vap_create(struct ieee80211com *ic, const char nam
 
        vap->iv_update_beacon = run_update_beacon;
        vap->iv_max_aid = RT2870_WCID_MAX;
+
+       vap->iv_ampdu_rxmax = IEEE80211_HTCAP_MAXRXAMPDU_64K;
+       vap->iv_ampdu_density = IEEE80211_HTCAP_MPDUDENSITY_2;
+
        /*
         * To delete the right key from h/w, we need wcid.
         * Luckily, there is unused space in ieee80211_key{}, wk_pad,
@@ -2059,11 +2116,13 @@ run_media_change(struct ifnet *ifp)
                struct ieee80211_node *ni;
                struct run_node *rn;
 
+               /* XXX TODO: methodize with MCS rates */
                rate = ic->ic_sup_rates[ic->ic_curmode].
                    rs_rates[tp->ucastrate] & IEEE80211_RATE_VAL;
                for (ridx = 0; ridx < RT2860_RIDX_MAX; ridx++)
                        if (rt2860_rates[ridx].rate == rate)
                                break;
+
                ni = ieee80211_ref_node(vap->iv_bss);
                rn = RUN_NODE(ni);
                rn->fix_ridx = ridx;
@@ -2605,7 +2664,7 @@ run_iter_func(void *arg, struct ieee80211_node *ni)
        struct run_node *rn = RUN_NODE(ni);
        union run_stats sta[2];
        uint16_t (*wstat)[3];
-       int error;
+       int error, ridx;
 
        RUN_LOCK(sc);
 
@@ -2656,12 +2715,17 @@ run_iter_func(void *arg, struct ieee80211_node *ni)
        }
 
        ieee80211_ratectl_tx_update(vap, txs);
-       rn->amrr_ridx = ieee80211_ratectl_rate(ni, NULL, 0);
+       ieee80211_ratectl_rate(ni, NULL, 0);
+       /* XXX TODO: methodize with MCS rates */
+       for (ridx = 0; ridx < RT2860_RIDX_MAX; ridx++)
+               if (rt2860_rates[ridx].rate == ni->ni_txrate)
+                       break;
+       rn->amrr_ridx = ridx;
 
 fail:
        RUN_UNLOCK(sc);
 
-       RUN_DPRINTF(sc, RUN_DEBUG_RATE, "ridx=%d\n", rn->amrr_ridx);
+       RUN_DPRINTF(sc, RUN_DEBUG_RATE, "rate=%d, ridx=%d\n", ni->ni_txrate, 
rn->amrr_ridx);
 }
 
 static void
@@ -2684,14 +2748,12 @@ static void
 run_newassoc(struct ieee80211_node *ni, int isnew)
 {
        struct run_node *rn = RUN_NODE(ni);
-       struct ieee80211_rateset *rs = &ni->ni_rates;
        struct ieee80211vap *vap = ni->ni_vap;
        struct ieee80211com *ic = vap->iv_ic;
        struct run_softc *sc = ic->ic_softc;
        uint8_t rate;
        uint8_t ridx;
        uint8_t wcid;
-       int i, j;
 
        wcid = (vap->iv_opmode == IEEE80211_M_STA) ?
            1 : RUN_AID2WCID(ni->ni_associd);
@@ -2721,31 +2783,8 @@ run_newassoc(struct ieee80211_node *ni, int isnew)
            "new assoc isnew=%d associd=%x addr=%s\n",
            isnew, ni->ni_associd, ether_sprintf(ni->ni_macaddr));
 
-       for (i = 0; i < rs->rs_nrates; i++) {
-               rate = rs->rs_rates[i] & IEEE80211_RATE_VAL;
-               /* convert 802.11 rate to hardware rate index */
-               for (ridx = 0; ridx < RT2860_RIDX_MAX; ridx++)
-                       if (rt2860_rates[ridx].rate == rate)
-                               break;
-               rn->ridx[i] = ridx;
-               /* determine rate of control response frames */
-               for (j = i; j >= 0; j--) {
-                       if ((rs->rs_rates[j] & IEEE80211_RATE_BASIC) &&
-                           rt2860_rates[rn->ridx[i]].phy ==
-                           rt2860_rates[rn->ridx[j]].phy)
-                               break;
-               }
-               if (j >= 0) {
-                       rn->ctl_ridx[i] = rn->ridx[j];
-               } else {
-                       /* no basic rate found, use mandatory one */
-                       rn->ctl_ridx[i] = rt2860_rates[ridx].ctl_ridx;
-               }
-               RUN_DPRINTF(sc, RUN_DEBUG_STATE | RUN_DEBUG_RATE,
-                   "rate=0x%02x ridx=%d ctl_ridx=%d\n",
-                   rs->rs_rates[i], rn->ridx[i], rn->ctl_ridx[i]);
-       }
        rate = vap->iv_txparms[ieee80211_chan2mode(ic->ic_curchan)].mgmtrate;
+       /* XXX TODO: methodize with MCS rates */
        for (ridx = 0; ridx < RT2860_RIDX_MAX; ridx++)
                if (rt2860_rates[ridx].rate == rate)
                        break;
@@ -2876,6 +2915,10 @@ run_rx_frame(struct run_softc *sc, struct mbuf *m, uin
        } else
                ni = NULL;
 
+       if(ni && ni->ni_flags & IEEE80211_NODE_HT) {
+               m->m_flags |= M_AMPDU;
+       }
+
        if (__predict_false(flags & RT2860_RX_MICERR)) {
                /* report MIC failures to net80211 for TKIP */
                if (ni != NULL)
@@ -3089,6 +3132,9 @@ tr_setup:
        /* make sure we free the source buffer, if any */
        m_freem(m);
 
+#ifdef IEEE80211_SUPPORT_SUPERG
+       ieee80211_ff_age_all(ic, 100);
+#endif
        RUN_LOCK(sc);
 }
 
@@ -3234,6 +3280,15 @@ tr_setup:
                }
                break;
        }
+#ifdef IEEE80211_SUPPORT_SUPERG
+       /* XXX TODO: make this deferred rather than unlock/relock */
+       /* XXX TODO: should only do the QoS AC this belongs to */
+       if (pq->tx_nfree >= RUN_TX_RING_COUNT) {
+               RUN_UNLOCK(sc);
+               ieee80211_ff_flush_all(ic);
+               RUN_LOCK(sc);
+       }
+#endif
 }
 
 static void
@@ -3318,15 +3373,21 @@ run_set_tx_desc(struct run_softc *sc, struct run_tx_da
                if (ridx != RT2860_RIDX_CCK1 &&
                    (ic->ic_flags & IEEE80211_F_SHPREAMBLE))
                        mcs |= RT2860_PHY_SHPRE;
-       } else
+       } else if (rt2860_rates[ridx].phy == IEEE80211_T_OFDM) {
                mcs |= RT2860_PHY_OFDM;
+       } else if (rt2860_rates[ridx].phy == IEEE80211_T_HT) {
+               /* XXX TODO: [adrian] set short preamble for MCS? */
+               mcs |= RT2860_PHY_HT; /* Mixed, not greenfield */
+       }
        txwi->phy = htole16(mcs);
 
        /* check if RTS/CTS or CTS-to-self protection is required */
        if (!IEEE80211_IS_MULTICAST(wh->i_addr1) &&
-           (m->m_pkthdr.len + IEEE80211_CRC_LEN > vap->iv_rtsthreshold ||
+           ((m->m_pkthdr.len + IEEE80211_CRC_LEN > vap->iv_rtsthreshold) ||
             ((ic->ic_flags & IEEE80211_F_USEPROT) &&
-             rt2860_rates[ridx].phy == IEEE80211_T_OFDM)))
+             rt2860_rates[ridx].phy == IEEE80211_T_OFDM) ||
+            ((ic->ic_htprotmode == IEEE80211_PROT_RTSCTS) &&
+             rt2860_rates[ridx].phy == IEEE80211_T_HT)))
                txwi->txop |= RT2860_TX_TXOP_HT;
        else
                txwi->txop |= RT2860_TX_TXOP_BACKOFF;
@@ -3390,7 +3451,8 @@ run_tx(struct run_softc *sc, struct mbuf *m, struct ie
        /* pickup a rate index */
        if (IEEE80211_IS_MULTICAST(wh->i_addr1) ||
            type != IEEE80211_FC0_TYPE_DATA || m->m_flags & M_EAPOL) {
-               ridx = (ic->ic_curmode == IEEE80211_MODE_11A) ?
+               /* XXX TODO: methodize for 11n; use MCS0 for 11NA/11NG */
+               ridx = (ic->ic_curmode == IEEE80211_MODE_11A || ic->ic_curmode 
== IEEE80211_MODE_11NA) ?
                    RT2860_RIDX_OFDM6 : RT2860_RIDX_CCK1;
                ctl_ridx = rt2860_rates[ridx].ctl_ridx;
        } else {
@@ -3609,6 +3671,7 @@ run_sendprot(struct run_softc *sc,
        data->m = mprot;
        data->ni = ieee80211_ref_node(ni);
 
+       /* XXX TODO: methodize with MCS rates */
        for (ridx = 0; ridx < RT2860_RIDX_MAX; ridx++)
                if (rt2860_rates[ridx].rate == protrate)
                        break;
@@ -3684,6 +3747,7 @@ run_tx_param(struct run_softc *sc, struct mbuf *m, str
 
         data->m = m;
         data->ni = ni;
+       /* XXX TODO: methodize with MCS rates */
        for (ridx = 0; ridx < RT2860_RIDX_MAX; ridx++)
                if (rt2860_rates[ridx].rate == rate)
                        break;
@@ -4856,12 +4920,17 @@ run_getradiocaps(struct ieee80211com *ic,
        memset(bands, 0, sizeof(bands));
        setbit(bands, IEEE80211_MODE_11B);
        setbit(bands, IEEE80211_MODE_11G);
+       setbit(bands, IEEE80211_MODE_11NG);
+
+       /* Note: for now, only support HT20 channels */
        ieee80211_add_channels_default_2ghz(chans, maxchans, nchans, bands, 0);
 
        if (sc->rf_rev == RT2860_RF_2750 || sc->rf_rev == RT2860_RF_2850 ||
            sc->rf_rev == RT3070_RF_3052 || sc->rf_rev == RT3593_RF_3053 ||
            sc->rf_rev == RT5592_RF_5592) {
                setbit(bands, IEEE80211_MODE_11A);
+               setbit(bands, IEEE80211_MODE_11NA);
+               /* Note: for now, only support HT20 channels */
                ieee80211_add_channel_list_5ghz(chans, maxchans, nchans,
                    run_chan_5ghz, nitems(run_chan_5ghz), bands, 0);
        }
@@ -6205,6 +6274,10 @@ run_init_locked(struct run_softc *sc)
        /* turn radio LED on */
        run_set_leds(sc, RT2860_LED_RADIO);
 
+       /* Set up AUTO_RSP_CFG register for auto response */
+       run_write(sc, RT2860_AUTO_RSP_CFG, RT2860_AUTO_RSP_EN |
+           RT2860_BAC_ACKPOLICY_EN | RT2860_CTS_40M_MODE_EN);
+
        sc->sc_flags |= RUN_RUNNING;
        sc->cmdq_run = RUN_CMDQ_GO;
 
@@ -6309,6 +6382,22 @@ run_delay(struct run_softc *sc, u_int ms)
 {
        usb_pause_mtx(mtx_owned(&sc->sc_mtx) ? 
            &sc->sc_mtx : NULL, USB_MS_TO_TICKS(ms));
+}
+
+
+static void
+run_update_chw(struct ieee80211com *ic)
+{
+
+       printf("%s: TODO\n", __func__);
+}
+
+static int
+run_ampdu_enable(struct ieee80211_node *ni, struct ieee80211_tx_ampdu *tap)
+{
+
+       /* For now, no A-MPDU TX support in the driver */
+       return (0);
 }
 
 static device_method_t run_methods[] = {

Modified: head/sys/dev/usb/wlan/if_runreg.h
==============================================================================
--- head/sys/dev/usb/wlan/if_runreg.h   Fri May 29 13:07:52 2020        
(r361625)
+++ head/sys/dev/usb/wlan/if_runreg.h   Fri May 29 15:56:44 2020        
(r361626)
@@ -955,11 +955,6 @@ struct rt2860_rxwi {
 #define        RT5390_EEPROM_IQ_GAIN_CAL_TX1_CH140_TO_CH165_5GHZ       0x14e
 #define        RT5390_EEPROM_IQ_PHASE_CAL_TX1_CH140_TO_CH165_5GHZ      0x14f
 
-#define        RT2860_RIDX_CCK1         0
-#define        RT2860_RIDX_CCK11        3
-#define        RT2860_RIDX_OFDM6        4
-#define        RT2860_RIDX_MAX         12
-
 /*
  * EEPROM access macro.
  */

Modified: head/sys/dev/usb/wlan/if_runvar.h
==============================================================================
--- head/sys/dev/usb/wlan/if_runvar.h   Fri May 29 13:07:52 2020        
(r361625)
+++ head/sys/dev/usb/wlan/if_runvar.h   Fri May 29 15:56:44 2020        
(r361626)
@@ -97,8 +97,6 @@ STAILQ_HEAD(run_tx_data_head, run_tx_data);
 
 struct run_node {
        struct ieee80211_node   ni;
-       uint8_t                 ridx[IEEE80211_RATE_MAXSIZE];
-       uint8_t                 ctl_ridx[IEEE80211_RATE_MAXSIZE];
        uint8_t                 amrr_ridx;
        uint8_t                 mgt_ridx;
        uint8_t                 fix_ridx;
_______________________________________________
svn-src-all@freebsd.org mailing list
https://lists.freebsd.org/mailman/listinfo/svn-src-all
To unsubscribe, send any mail to "svn-src-all-unsubscr...@freebsd.org"

Reply via email to