Hello Stefan,

many many thanks for this work!

I tested today with the latest snapshot from yesterday and a custom compiled 
kernel
from today's sources. AP is my APU1D4 and Client is my ThinkPad T530 with iwn:

AP:

athn0 at pci4 dev 0 function 0 "Atheros AR9281" rev 0x01: apic 2 int 19
athn0: AR9280 rev 2 (2T2R), ROM rev 22, address 04:f0:21:17:40:ba

athn0: flags=8947 mtu 1500
        lladdr 04:f0:21:17:40:ba
        index 4 priority 4 llprio 3
        groups: wlan
        media: IEEE802.11 autoselect (autoselect hostap)
        status: active
        ieee80211: nwid TEST chan 1 bssid 04:f0:21:17:40:ba wpakey XXX 
wpaprotos wpa2 wpaakms psk wpaciphers ccmp wpagroupcipher ccmp

athn0: sending auth to 6c:88:14:36:27:b0 on channel 1 mode auto
athn0: station 6c:88:14:36:27:b0 newly authenticated (open)
athn0: sending assoc_resp to 6c:88:14:36:27:b0 on channel 1 mode auto
athn0: sending msg 1/4 of the 4-way handshake to 6c:88:14:36:27:b0
athn0: received auth from 6c:88:14:36:27:b0 rssi 34 mode auto
athn0: received assoc_req from 6c:88:14:36:27:b0 rssi 33 mode auto
athn0: sending msg 1/4 of the 4-way handshake to 6c:88:14:36:27:b0
athn0: received msg 2/4 of the 4-way handshake from 6c:88:14:36:27:b0
athn0: sending msg 3/4 of the 4-way handshake to 6c:88:14:36:27:b0
athn0: received msg 4/4 of the 4-way handshake from 6c:88:14:36:27:b0

Client:

iwn0 at pci2 dev 0 function 0 "Intel Centrino Advanced-N 6205" rev 0x34: msi, 
MIMO 2T2R, MoW, address 6c:88:14:36:27:b0

iwn0: end active scan
iwn0: sending auth to 04:f0:21:17:40:ba on channel 1 mode 11g
iwn0: sending assoc_req to 04:f0:21:17:40:ba on channel 1 mode 11g
iwn0: received auth from 04:f0:21:17:40:ba rssi -20 mode 11g
iwn0: associated with 04:f0:21:17:40:ba ssid "TEST" channel 1 start MCS 0 short 
preamble long slot time HT enabled
iwn0: received assoc_resp from 04:f0:21:17:40:ba rssi -21 mode 11g
iwn0: received msg 1/4 of the 4-way handshake from 04:f0:21:17:40:ba
iwn0: sending msg 2/4 of the 4-way handshake to 04:f0:21:17:40:ba
iwn0: received msg 3/4 of the 4-way handshake from 04:f0:21:17:40:ba
iwn0: sending msg 4/4 of the 4-way handshake to 04:f0:21:17:40:ba

iwn0: flags=208847 mtu 1500
        lladdr 6c:88:14:36:27:b0
        index 2 priority 4 llprio 3
        groups: wlan egress
        media: IEEE802.11 autoselect mode 11n (HT-MCS2 mode 11n)
        status: active
        ieee80211: nwid TEST chan 1 bssid 04:f0:21:17:40:ba -20dBm wpakey XXX 
wpaprotos wpa2 wpaakms psk wpaciphers ccmp wpagroupcipher ccmp

Unfortunately the throughput is very low, only ~7 MBit. With mode 11g I get ~16 
MBit.


zarathustra:~# tcpbench apu01
  elapsed_ms          bytes         mbps   bwidth
        1004         748272        5.962  100.00%
Conn:   1 Mbps:        5.962 Peak Mbps:        5.962 Avg Mbps:        5.962
        2007         839664        6.697  100.00%
Conn:   1 Mbps:        6.697 Peak Mbps:        6.697 Avg Mbps:        6.697
        3010         818244        6.533  100.00%
Conn:   1 Mbps:        6.533 Peak Mbps:        6.697 Avg Mbps:        6.533
        4013         909636        7.255  100.00%
Conn:   1 Mbps:        7.255 Peak Mbps:        7.255 Avg Mbps:        7.255
        5014         856800        6.848  100.00%
Conn:   1 Mbps:        6.848 Peak Mbps:        7.255 Avg Mbps:        6.848
        6015         868224        6.946  100.00%
Conn:   1 Mbps:        6.946 Peak Mbps:        7.255 Avg Mbps:        6.946
        7021         872508        6.945  100.00%
Conn:   1 Mbps:        6.945 Peak Mbps:        7.255 Avg Mbps:        6.945
        8023         835380        6.670  100.00%
Conn:   1 Mbps:        6.670 Peak Mbps:        7.255 Avg Mbps:        6.670
        9025         848232        6.779  100.00%
Conn:   1 Mbps:        6.779 Peak Mbps:        7.255 Avg Mbps:        6.779
       10028         843948        6.731  100.00%
Conn:   1 Mbps:        6.731 Peak Mbps:        7.255 Avg Mbps:        6.731
       11036         831096        6.596  100.00%
Conn:   1 Mbps:        6.596 Peak Mbps:        7.255 Avg Mbps:        6.596

I'm now ready to test furhter.

Many thanks again!


Regards Uwe



Am 09.01.2017 13:54:55, schrieb Stefan Sperling:
> This diff adds 11n support to the athn(4) driver.
> Requires -current net80211 code from today.
> 
> Tested in hostap mode and client mode with:
> athn0 at pci1 dev 0 function 0 "Atheros AR9281" rev 0x01: apic 2 int 16
> athn0: AR9280 rev 2 (2T2R), ROM rev 22, adddress xx:xx:xx:xx:xx:xx
> 
> And in client mode with:
> athn0 at uhub1 port 2 configuration 1 interface 0 "ATHEROS USB2.0 WLAN" rev 
> 2.00/1.08 addr 2
> athn0: AR9271 rev 1 (1T1R), ROM rev 13, address xx:xx:xx:xx:xx:xx
> 
> Hostap performance is not perfect yet but should be no worse than
> 11a/b/g modes in the same environment.
> 
> For Linux clients a fix for WME params is needed which I also posted to tech@.
> 
> This diff does not modify the known-broken and disabled ar9003 code,
> apart from making sure it still builds.
> 
> I'm looking for both tests and OKs.
> 
> Index: dev/cardbus/if_athn_cardbus.c
> ===================================================================
> RCS file: /cvs/src/sys/dev/cardbus/if_athn_cardbus.c,v
> retrieving revision 1.14
> diff -u -p -r1.14 if_athn_cardbus.c
> --- dev/cardbus/if_athn_cardbus.c     24 Nov 2015 17:11:39 -0000      1.14
> +++ dev/cardbus/if_athn_cardbus.c     8 Jan 2017 09:31:28 -0000
> @@ -43,6 +43,7 @@
>  
>  #include 
>  #include 
> +#include 
>  #include 
>  
>  #include 
> Index: dev/ic/ar5008.c
> ===================================================================
> RCS file: /cvs/src/sys/dev/ic/ar5008.c,v
> retrieving revision 1.37
> diff -u -p -r1.37 ar5008.c
> --- dev/ic/ar5008.c   29 Nov 2016 10:22:30 -0000      1.37
> +++ dev/ic/ar5008.c   9 Jan 2017 10:14:41 -0000
> @@ -51,6 +51,7 @@
>  
>  #include 
>  #include 
> +#include 
>  #include 
>  
>  #include 
> @@ -217,7 +218,7 @@ ar5008_attach(struct athn_softc *sc)
>               sc->flags |= ATHN_FLAG_11A;
>       if (base->opCapFlags & AR_OPFLAGS_11G)
>               sc->flags |= ATHN_FLAG_11G;
> -     if (base->opCapFlags & AR_OPFLAGS_11N)
> +     if ((base->opCapFlags & AR_OPFLAGS_11N_DISABLED) == 0)
>               sc->flags |= ATHN_FLAG_11N;
>  
>       IEEE80211_ADDR_COPY(ic->ic_myaddr, base->macAddr);
> @@ -952,9 +953,11 @@ ar5008_tx_process(struct athn_softc *sc,
>       struct ifnet *ifp = &ic->ic_if;
>       struct athn_txq *txq = &sc->txq[qid];
>       struct athn_node *an;
> +     struct ieee80211_node *ni;
>       struct athn_tx_buf *bf;
>       struct ar_tx_desc *ds;
>       uint8_t failcnt;
> +     int txfail;
>  
>       bf = SIMPLEQ_FIRST(&txq->head);
>       if (bf == NULL)
> @@ -970,13 +973,16 @@ ar5008_tx_process(struct athn_softc *sc,
>  
>       sc->sc_tx_timer = 0;
>  
> -     if (ds->ds_status1 & AR_TXS1_EXCESSIVE_RETRIES)
> +     txfail = (ds->ds_status1 & AR_TXS1_EXCESSIVE_RETRIES);
> +     if (txfail)
>               ifp->if_oerrors++;
>  
>       if (ds->ds_status1 & AR_TXS1_UNDERRUN)
>               athn_inc_tx_trigger_level(sc);
>  
>       an = (struct athn_node *)bf->bf_ni;
> +     ni = (struct ieee80211_node *)bf->bf_ni;
> +
>       /*
>        * NB: the data fail count contains the number of un-acked tries
>        * for the final series used.  We must add the number of tries for
> @@ -987,10 +993,27 @@ ar5008_tx_process(struct athn_softc *sc,
>       failcnt += MS(ds->ds_status9, AR_TXS9_FINAL_IDX) * 2;
>  
>       /* Update rate control statistics. */
> -     an->amn.amn_txcnt++;
> -     if (failcnt > 0)
> -             an->amn.amn_retrycnt++;
> -
> +     if (ni->ni_flags & IEEE80211_NODE_HT) {
> +             an->mn.frames++;
> +             an->mn.ampdu_size = bf->bf_m->m_pkthdr.len + IEEE80211_CRC_LEN;
> +             an->mn.agglen = 1; /* XXX We do not yet support Tx agg. */
> +             if (failcnt > 0)
> +                     an->mn.retries++;
> +             if (txfail)
> +                     an->mn.txfail++;
> +             if ((ic->ic_opmode == IEEE80211_M_STA &&
> +                 ic->ic_state == IEEE80211_S_RUN)
> +#ifndef IEEE80211_STA_ONLY
> +                 || (ic->ic_opmode == IEEE80211_M_HOSTAP &&
> +                 ni->ni_state == IEEE80211_STA_ASSOC)
> +#endif
> +                 )
> +                     ieee80211_mira_choose(&an->mn, ic, ni);
> +     } else {
> +             an->amn.amn_txcnt++;
> +             if (failcnt > 0)
> +                     an->amn.amn_retrycnt++;
> +     }
>       DPRINTFN(5, ("Tx done qid=%d status1=%d fail count=%d\n",
>           qid, ds->ds_status1, failcnt));
>  
> @@ -1110,7 +1133,7 @@ ar5008_swba_intr(struct athn_softc *sc)
>       ds->ds_ctl2 = SM(AR_TXC2_XMIT_DATA_TRIES0, 1);
>  
>       /* Write Tx rate. */
> -     ridx = (ic->ic_curmode == IEEE80211_MODE_11A) ?
> +     ridx = IEEE80211_IS_CHAN_5GHZ(ni->ni_chan) ?
>           ATHN_RIDX_OFDM6 : ATHN_RIDX_CCK1;
>       hwrate = athn_rates[ridx].hwrate;
>       ds->ds_ctl3 = SM(AR_TXC3_XMIT_RATE0, hwrate);
> @@ -1315,15 +1338,25 @@ ar5008_tx(struct athn_softc *sc, struct 
>           IEEE80211_FC0_TYPE_DATA) {
>               /* Use lowest rate for all tries. */
>               ridx[0] = ridx[1] = ridx[2] = ridx[3] =
> -                 (ic->ic_curmode == IEEE80211_MODE_11A) ?
> -                     ATHN_RIDX_OFDM6 : ATHN_RIDX_CCK1;
> +                 (IEEE80211_IS_CHAN_5GHZ(ni->ni_chan) ?
> +                     ATHN_RIDX_OFDM6 : ATHN_RIDX_CCK1);
> +     } else if ((ni->ni_flags & IEEE80211_NODE_HT) &&
> +         ic->ic_fixed_mcs != -1) {
> +             /* Use same fixed rate for all tries. */
> +             ridx[0] = ridx[1] = ridx[2] = ridx[3] =
> +                 ATHN_RIDX_MCS0 + ic->ic_fixed_mcs;
>       } else if (ic->ic_fixed_rate != -1) {
>               /* Use same fixed rate for all tries. */
>               ridx[0] = ridx[1] = ridx[2] = ridx[3] =
>                   sc->fixed_ridx;
>       } else {
> -             int txrate = ni->ni_txrate;
>               /* Use fallback table of the node. */
> +             int txrate;
> +             
> +             if (ni->ni_flags & IEEE80211_NODE_HT)
> +                     txrate = ATHN_NUM_LEGACY_RATES + ni->ni_txmcs;
> +             else
> +                     txrate = ni->ni_txrate;
>               for (i = 0; i                           ridx[i] = 
> an->ridx[txrate];
>                       txrate = an->fallback[txrate];
> @@ -1337,7 +1370,10 @@ ar5008_tx(struct athn_softc *sc, struct 
>  
>               tap->wt_flags = 0;
>               /* Use initial transmit rate. */
> -             tap->wt_rate = athn_rates[ridx[0]].rate;
> +             if (athn_rates[ridx[0]].hwrate & 0x80) /* MCS */
> +                     tap->wt_rate = athn_rates[ridx[0]].hwrate;
> +             else
> +                     tap->wt_rate = athn_rates[ridx[0]].rate;
>               tap->wt_chan_freq = htole16(ic->ic_bss->ni_chan->ic_freq);
>               tap->wt_chan_flags = htole16(ic->ic_bss->ni_chan->ic_flags);
>               tap->wt_hwqueue = qid;
> @@ -1455,11 +1491,16 @@ ar5008_tx(struct athn_softc *sc, struct 
>  
>       /* Check if frame must be protected using RTS/CTS or CTS-to-self. */
>       if (!IEEE80211_IS_MULTICAST(wh->i_addr1)) {
> +             enum ieee80211_htprot htprot;
> +             
> +             htprot = (ic->ic_bss->ni_htop1 & IEEE80211_HTOP1_PROT_MASK);
>               /* NB: Group frames are sent using CCK in 802.11b/g. */
>               if (totlen > ic->ic_rtsthreshold) {
>                       ds->ds_ctl0 |= AR_TXC0_RTS_ENABLE;
> -             } else if ((ic->ic_flags & IEEE80211_F_USEPROT) &&
> -                 athn_rates[ridx[0]].phy == IEEE80211_T_OFDM) {
> +             } else if (((ic->ic_flags & IEEE80211_F_USEPROT) &&
> +                 athn_rates[ridx[0]].phy == IEEE80211_T_OFDM) ||
> +                 ((ic->ic_flags & IEEE80211_F_HTON) &&
> +                 htprot != IEEE80211_HTPROT_NONE)) {
>                       if (ic->ic_protmode == IEEE80211_PROT_RTSCTS)
>                               ds->ds_ctl0 |= AR_TXC0_RTS_ENABLE;
>                       else if (ic->ic_protmode == IEEE80211_PROT_CTSONLY)
> @@ -1523,9 +1564,10 @@ ar5008_tx(struct athn_softc *sc, struct 
>           SM(AR_TXC7_CHAIN_SEL1, sc->txchainmask) |
>           SM(AR_TXC7_CHAIN_SEL2, sc->txchainmask) |
>           SM(AR_TXC7_CHAIN_SEL3, sc->txchainmask);
> +
>  #ifdef notyet
>       /* Use the same short GI setting for all tries. */
> -     if (ic->ic_flags & IEEE80211_F_SHGI)
> +     if (ni->ni_htcaps & IEEE80211_HTCAP_SGI20)
>               ds->ds_ctl7 |= AR_TXC7_GI0123;
>       /* Use the same channel width for all tries. */
>       if (ic->ic_flags & IEEE80211_F_CBW40)
> @@ -1542,7 +1584,7 @@ ar5008_tx(struct athn_softc *sc, struct 
>                       ds->ds_ctl5 |= AR_TXC5_RTSCTS_QUAL23;
>               }
>               /* Select protection rate (suboptimal but ok). */
> -             protridx = (ic->ic_curmode == IEEE80211_MODE_11A) ?
> +             protridx = IEEE80211_IS_CHAN_5GHZ(ni->ni_chan) ?
>                   ATHN_RIDX_OFDM6 : ATHN_RIDX_CCK2;
>               if (ds->ds_ctl0 & AR_TXC0_RTS_ENABLE) {
>                       /* Account for CTS duration. */
> Index: dev/ic/ar5008reg.h
> ===================================================================
> RCS file: /cvs/src/sys/dev/ic/ar5008reg.h,v
> retrieving revision 1.3
> diff -u -p -r1.3 ar5008reg.h
> --- dev/ic/ar5008reg.h        31 Dec 2010 17:50:48 -0000      1.3
> +++ dev/ic/ar5008reg.h        8 Jan 2017 15:08:19 -0000
> @@ -950,12 +950,13 @@ struct ar_base_eep_header {
>       uint8_t         opCapFlags;
>  #define AR_OPFLAGS_11A                       0x01
>  #define AR_OPFLAGS_11G                       0x02
> +/* NB: If set, 11n is _disabled_ in the corresponding mode: */
>  #define AR_OPFLAGS_11N_5G40          0x04
>  #define AR_OPFLAGS_11N_2G40          0x08
>  #define AR_OPFLAGS_11N_5G20          0x10
>  #define AR_OPFLAGS_11N_2G20          0x20
> -/* Shortcut. */
> -#define AR_OPFLAGS_11N                       0x3c
> +/* Shortcut for "all of 11n is disabled". */
> +#define AR_OPFLAGS_11N_DISABLED              0x3c
>  
>       uint8_t         eepMisc;
>       uint16_t        regDmn[2];
> Index: dev/ic/ar5416.c
> ===================================================================
> RCS file: /cvs/src/sys/dev/ic/ar5416.c,v
> retrieving revision 1.19
> diff -u -p -r1.19 ar5416.c
> --- dev/ic/ar5416.c   5 Jan 2016 18:41:15 -0000       1.19
> +++ dev/ic/ar5416.c   8 Jan 2017 09:29:59 -0000
> @@ -51,6 +51,7 @@
>  
>  #include 
>  #include 
> +#include 
>  #include 
>  
>  #include 
> Index: dev/ic/ar9003.c
> ===================================================================
> RCS file: /cvs/src/sys/dev/ic/ar9003.c,v
> retrieving revision 1.41
> diff -u -p -r1.41 ar9003.c
> --- dev/ic/ar9003.c   29 Nov 2016 10:22:30 -0000      1.41
> +++ dev/ic/ar9003.c   8 Jan 2017 09:30:50 -0000
> @@ -51,6 +51,7 @@
>  
>  #include 
>  #include 
> +#include 
>  #include 
>  
>  #include 
> Index: dev/ic/ar9280.c
> ===================================================================
> RCS file: /cvs/src/sys/dev/ic/ar9280.c,v
> retrieving revision 1.25
> diff -u -p -r1.25 ar9280.c
> --- dev/ic/ar9280.c   5 Jan 2016 18:41:15 -0000       1.25
> +++ dev/ic/ar9280.c   8 Jan 2017 09:30:11 -0000
> @@ -51,6 +51,7 @@
>  
>  #include 
>  #include 
> +#include 
>  #include 
>  
>  #include 
> Index: dev/ic/ar9285.c
> ===================================================================
> RCS file: /cvs/src/sys/dev/ic/ar9285.c,v
> retrieving revision 1.26
> diff -u -p -r1.26 ar9285.c
> --- dev/ic/ar9285.c   5 Jan 2016 18:41:15 -0000       1.26
> +++ dev/ic/ar9285.c   8 Jan 2017 09:30:24 -0000
> @@ -52,6 +52,7 @@
>  
>  #include 
>  #include 
> +#include 
>  #include 
>  
>  #include 
> Index: dev/ic/ar9287.c
> ===================================================================
> RCS file: /cvs/src/sys/dev/ic/ar9287.c,v
> retrieving revision 1.24
> diff -u -p -r1.24 ar9287.c
> --- dev/ic/ar9287.c   5 Jan 2016 18:41:15 -0000       1.24
> +++ dev/ic/ar9287.c   8 Jan 2017 09:30:37 -0000
> @@ -51,6 +51,7 @@
>  
>  #include 
>  #include 
> +#include 
>  #include 
>  
>  #include 
> Index: dev/ic/ar9380.c
> ===================================================================
> RCS file: /cvs/src/sys/dev/ic/ar9380.c,v
> retrieving revision 1.24
> diff -u -p -r1.24 ar9380.c
> --- dev/ic/ar9380.c   5 Jan 2016 18:41:15 -0000       1.24
> +++ dev/ic/ar9380.c   8 Jan 2017 15:10:10 -0000
> @@ -49,6 +49,7 @@
>  
>  #include 
>  #include 
> +#include 
>  #include 
>  
>  #include 
> Index: dev/ic/athn.c
> ===================================================================
> RCS file: /cvs/src/sys/dev/ic/athn.c,v
> retrieving revision 1.93
> diff -u -p -r1.93 athn.c
> --- dev/ic/athn.c     13 Apr 2016 10:49:26 -0000      1.93
> +++ dev/ic/athn.c     9 Jan 2017 10:01:20 -0000
> @@ -53,6 +53,7 @@
>  
>  #include 
>  #include 
> +#include 
>  #include 
>  
>  #include 
> @@ -93,7 +94,7 @@ int         athn_set_key(struct ieee80211com *,
>                   struct ieee80211_key *);
>  void         athn_delete_key(struct ieee80211com *, struct ieee80211_node *,
>                   struct ieee80211_key *);
> -void         athn_iter_func(void *, struct ieee80211_node *);
> +void         athn_iter_calib(void *, struct ieee80211_node *);
>  void         athn_calib_to(void *);
>  int          athn_init_calib(struct athn_softc *,
>                   struct ieee80211_channel *, struct ieee80211_channel *);
> @@ -120,10 +121,12 @@ void            athn_init_qos(struct athn_softc *)
>  int          athn_hw_reset(struct athn_softc *, struct ieee80211_channel *,
>                   struct ieee80211_channel *, int);
>  struct               ieee80211_node *athn_node_alloc(struct ieee80211com *);
> +void         athn_node_free(struct ieee80211com *, struct ieee80211_node *);
>  void         athn_newassoc(struct ieee80211com *, struct ieee80211_node *,
>                   int);
>  int          athn_media_change(struct ifnet *);
>  void         athn_next_scan(void *);
> +void         athn_iter_newstate(void *, struct ieee80211_node *);
>  int          athn_newstate(struct ieee80211com *, enum ieee80211_state,
>                   int);
>  void         athn_updateedca(struct ieee80211com *);
> @@ -289,11 +292,15 @@ athn_attach(struct athn_softc *sc)
>               int i, ntxstreams, nrxstreams;
>  
>               /* Set HT capabilities. */
> -             ic->ic_htcaps =
> -                 IEEE80211_HTCAP_SMPS_DIS |
> -                 IEEE80211_HTCAP_CBW20_40 |
> +             ic->ic_htcaps = (IEEE80211_HTCAP_SMPS_DIS  +                
> IEEE80211_HTCAP_SMPS_SHIFT);
> +#ifdef notyet
> +             ic->ic_htcaps |= IEEE80211_HTCAP_CBW20_40 |
>                   IEEE80211_HTCAP_SGI40 |
>                   IEEE80211_HTCAP_DSSSCCK40;
> +#endif
> +             ic->ic_htxcaps = 0;
> +#ifdef notyet
>               if (AR_SREV_9271(sc) || AR_SREV_9287_10_OR_LATER(sc))
>                       ic->ic_htcaps |= IEEE80211_HTCAP_SGI20;
>               if (AR_SREV_9380_10_OR_LATER(sc))
> @@ -302,6 +309,7 @@ athn_attach(struct athn_softc *sc)
>                       ic->ic_htcaps |= IEEE80211_HTCAP_TXSTBC;
>                       ic->ic_htcaps |= 1              }
> +#endif
>               ntxstreams = sc->ntxchains;
>               nrxstreams = sc->nrxchains;
>               if (!AR_SREV_9380_10_OR_LATER(sc)) {
> @@ -316,6 +324,11 @@ athn_attach(struct athn_softc *sc)
>                       ic->ic_tx_mcs_set |= IEEE80211_TX_RX_MCS_NOT_EQUAL;
>                       ic->ic_tx_mcs_set |= (ntxstreams - 1)                   
> }
> +
> +             DPRINTF(("%s: htcaps=0x%x, MCS 0x%x%x%x%x\n",
> +                 sc->sc_dev.dv_xname, ic->ic_htcaps,
> +                 ic->ic_sup_mcs[0], ic->ic_sup_mcs[1],
> +                 ic->ic_sup_mcs[2], ic->ic_sup_mcs[3]));
>       }
>  
>       /* Set supported rates. */
> @@ -346,6 +359,8 @@ athn_attach(struct athn_softc *sc)
>       if_attach(ifp);
>       ieee80211_ifattach(ifp);
>       ic->ic_node_alloc = athn_node_alloc;
> +     sc->sc_node_free = ic->ic_node_free;
> +     ic->ic_node_free = athn_node_free;
>       ic->ic_newassoc = athn_newassoc;
>       ic->ic_updateslot = athn_updateslot;
>       ic->ic_updateedca = athn_updateedca;
> @@ -425,6 +440,9 @@ athn_get_chanlist(struct athn_softc *sc)
>                       ic->ic_channels[chan].ic_flags =
>                           IEEE80211_CHAN_CCK | IEEE80211_CHAN_OFDM |
>                           IEEE80211_CHAN_DYN | IEEE80211_CHAN_2GHZ;
> +                     if (sc->flags & ATHN_FLAG_11N)
> +                             ic->ic_channels[chan].ic_flags |=
> +                                 IEEE80211_CHAN_HT;
>               }
>       }
>       if (sc->flags & ATHN_FLAG_11A) {
> @@ -433,6 +451,9 @@ athn_get_chanlist(struct athn_softc *sc)
>                       ic->ic_channels[chan].ic_freq =
>                           ieee80211_ieee2mhz(chan, IEEE80211_CHAN_5GHZ);
>                       ic->ic_channels[chan].ic_flags = IEEE80211_CHAN_A;
> +                     if (sc->flags & ATHN_FLAG_11N)
> +                             ic->ic_channels[chan].ic_flags |=
> +                                 IEEE80211_CHAN_HT;
>               }
>       }
>  }
> @@ -1206,12 +1227,13 @@ athn_btcoex_disable(struct athn_softc *s
>  #endif
>  
>  void
> -athn_iter_func(void *arg, struct ieee80211_node *ni)
> +athn_iter_calib(void *arg, struct ieee80211_node *ni)
>  {
>       struct athn_softc *sc = arg;
>       struct athn_node *an = (struct athn_node *)ni;
>  
> -     ieee80211_amrr_choose(&sc->amrr, ni, &an->amn);
> +     if ((ni->ni_flags & IEEE80211_NODE_HT) == 0)
> +             ieee80211_amrr_choose(&sc->amrr, ni, &an->amn);
>  }
>  
>  void
> @@ -1251,9 +1273,9 @@ athn_calib_to(void *arg)
>  #endif
>       if (ic->ic_fixed_rate == -1) {
>               if (ic->ic_opmode == IEEE80211_M_STA)
> -                     athn_iter_func(sc, ic->ic_bss);
> +                     athn_iter_calib(sc, ic->ic_bss);
>               else
> -                     ieee80211_iterate_nodes(ic, athn_iter_func, sc);
> +                     ieee80211_iterate_nodes(ic, athn_iter_calib, sc);
>       }
>       timeout_add_msec(&sc->calib_to, 500);
>       splx(s);
> @@ -1377,7 +1399,7 @@ athn_ani_ofdm_err_trigger(struct athn_so
>                       ani->firstep_level++;
>                       ops->set_firstep_level(sc, ani->firstep_level);
>               }
> -     } else if (sc->sc_ic.ic_curmode != IEEE80211_MODE_11A) {
> +     } else if (IEEE80211_IS_CHAN_2GHZ(sc->sc_ic.ic_bss->ni_chan)) {
>               /*
>                * Beacon RSSI is low, if in b/g mode, turn off OFDM weak
>                * signal detection and zero first step level to maximize
> @@ -1427,7 +1449,7 @@ athn_ani_cck_err_trigger(struct athn_sof
>                       ani->firstep_level++;
>                       ops->set_firstep_level(sc, ani->firstep_level);
>               }
> -     } else if (sc->sc_ic.ic_curmode != IEEE80211_MODE_11A) {
> +     } else if (IEEE80211_IS_CHAN_2GHZ(sc->sc_ic.ic_bss->ni_chan)) {
>               /*
>                * Beacon RSSI is low, zero first step level to maximize
>                * CCK sensitivity.
> @@ -1790,11 +1812,17 @@ athn_stop_tx_dma(struct athn_softc *sc, 
>  int
>  athn_txtime(struct athn_softc *sc, int len, int ridx, u_int flags)
>  {
> +     struct ieee80211com *ic = &sc->sc_ic;
>  #define divround(a, b)       (((a) + (b) - 1) / (b))
>       int txtime;
>  
> -     /* XXX HT. */
> -     if (athn_rates[ridx].phy == IEEE80211_T_OFDM) {
> +     if (athn_rates[ridx].hwrate & 0x80) { /* MCS */
> +             /* Assumes a 20MHz channel, HT-mixed frame format, no STBC. */
> +             txtime = 8 + 8 + 4 + 4 + 4 * 4 + 8 /* HT PLCP */
> +                 + 4 * ((8 * len + 16 + 6) / (athn_rates[ridx].rate * 2));
> +             if (IEEE80211_IS_CHAN_2GHZ(ic->ic_bss->ni_chan))
> +                     txtime += 6; /* aSignalExtension */
> +     } else if (athn_rates[ridx].phy == IEEE80211_T_OFDM) {
>               txtime = divround(8 + 4 * len + 3, athn_rates[ridx].rate);
>               /* SIFS is 10us for 11g but Signal Extension adds 6us. */
>               txtime = 16 + 4 + 4 * txtime + 16;
> @@ -2310,6 +2338,19 @@ athn_node_alloc(struct ieee80211com *ic)
>  }
>  
>  void
> +athn_node_free(struct ieee80211com *ic, struct ieee80211_node *ni)
> +{
> +     struct athn_softc *sc = ic->ic_softc;
> +     struct athn_node *an = (void *)ni;
> +
> +     if ((ni->ni_flags & IEEE80211_NODE_HT) &&
> +         ic->ic_state == IEEE80211_S_RUN)
> +             ieee80211_mira_node_destroy(&an->mn);
> +
> +     sc->sc_node_free(ic, ni);
> +}
> +
> +void
>  athn_newassoc(struct ieee80211com *ic, struct ieee80211_node *ni, int isnew)
>  {
>       struct athn_softc *sc = ic->ic_softc;
> @@ -2318,7 +2359,11 @@ athn_newassoc(struct ieee80211com *ic, s
>       uint8_t rate;
>       int ridx, i, j;
>  
> -     ieee80211_amrr_node_init(&sc->amrr, &an->amn);
> +     if (ni->ni_flags & IEEE80211_NODE_HT)
> +             ieee80211_mira_node_init(&an->mn);
> +     else
> +             ieee80211_amrr_node_init(&sc->amrr, &an->amn);
> +
>       /* Start at lowest available bit-rate, AMRR will raise. */
>       ni->ni_txrate = 0;
>  
> @@ -2343,6 +2388,35 @@ athn_newassoc(struct ieee80211com *ic, s
>               }
>               DPRINTFN(2, ("%d fallbacks to %d\n", i, an->fallback[i]));
>       }
> +
> +     /* In 11n mode, start at lowest available bit-rate, MiRA will raise. */
> +     ni->ni_txmcs = 0;
> +
> +     for (i = 0; i  +                /* Map MCS index to HW rate index. */
> +             ridx = ATHN_NUM_LEGACY_RATES + i;
> +             an->ridx[ridx] = ATHN_RIDX_MCS0 + i;
> +
> +             DPRINTFN(2, ("mcs %d index %d ", i, ridx));
> +             /* Compute fallback rate for retries. */
> +             if (i == 0 || i == 8) {
> +                     /* MCS 0 and 8 fall back to the lowest legacy rate. */
> +                     if (IEEE80211_IS_CHAN_5GHZ(ni->ni_chan))
> +                             an->fallback[ridx] = ATHN_RIDX_OFDM6;
> +                     else
> +                             an->fallback[ridx] = ATHN_RIDX_CCK1;
> +             } else {
> +                     /* Other MCS fall back to next supported lower MCS. */
> +                     an->fallback[ridx] = ATHN_NUM_LEGACY_RATES + i;
> +                     for (j = i - 1; j >= 0; j--) {
> +                             if (!isset(ni->ni_rxmcs, j))
> +                                     continue;
> +                             an->fallback[ridx] = ATHN_NUM_LEGACY_RATES + j;
> +                             break;
> +                     }
> +             }
> +             DPRINTFN(2, (" fallback to %d\n", an->fallback[ridx]));
> +     }
>  }
>  
>  int
> @@ -2387,6 +2461,19 @@ athn_next_scan(void *arg)
>       splx(s);
>  }
>  
> +void
> +athn_iter_newstate(void *arg, struct ieee80211_node *ni)
> +{
> +     struct athn_softc *sc = arg;
> +     struct ieee80211com *ic = &sc->sc_ic;
> +     struct athn_node *an = (struct athn_node *)ni;
> +
> +     /* Destroy MiRA node when hopping out of RUN state. */
> +     if ((ni->ni_flags & IEEE80211_NODE_HT) &&
> +         ic->ic_state == IEEE80211_S_RUN)
> +             ieee80211_mira_node_destroy(&an->mn);
> +}
> +
>  int
>  athn_newstate(struct ieee80211com *ic, enum ieee80211_state nstate, int arg)
>  {
> @@ -2397,6 +2484,11 @@ athn_newstate(struct ieee80211com *ic, e
>  
>       timeout_del(&sc->calib_to);
>  
> +     if (ic->ic_opmode == IEEE80211_M_STA)
> +             athn_iter_newstate(sc, ic->ic_bss);
> +     else
> +             ieee80211_iterate_nodes(ic, athn_iter_newstate, sc);
> +
>       switch (nstate) {
>       case IEEE80211_S_INIT:
>               athn_set_led(sc, 0);
> @@ -2497,7 +2589,7 @@ athn_clock_rate(struct athn_softc *sc)
>       struct ieee80211com *ic = &sc->sc_ic;
>       int clockrate;  /* MHz. */
>  
> -     if (ic->ic_curmode == IEEE80211_MODE_11A) {
> +     if (IEEE80211_IS_CHAN_5GHZ(ic->ic_bss->ni_chan)) {
>               if (sc->flags & ATHN_FLAG_FAST_PLL_CLOCK)
>                       clockrate = AR_CLOCK_RATE_FAST_5GHZ_OFDM;
>               else
> Index: dev/ic/athnvar.h
> ===================================================================
> RCS file: /cvs/src/sys/dev/ic/athnvar.h,v
> retrieving revision 1.36
> diff -u -p -r1.36 athnvar.h
> --- dev/ic/athnvar.h  5 Jan 2016 18:41:15 -0000       1.36
> +++ dev/ic/athnvar.h  8 Jan 2017 22:41:47 -0000
> @@ -120,14 +120,18 @@ struct athn_rxq {
>  #define ATHN_RIDX_CCK2       1
>  #define ATHN_RIDX_OFDM6      4
>  #define ATHN_RIDX_MCS0       12
> +#define ATHN_RIDX_MCS8       (ATHN_RIDX_MCS0 + 8)
>  #define ATHN_RIDX_MCS15      27
>  #define ATHN_RIDX_MAX        27
> +#define ATHN_MCS_MAX 15
> +#define ATHN_NUM_MCS (ATHN_MCS_MAX + 1)
>  #define ATHN_IS_HT_RIDX(ridx)        ((ridx) >= ATHN_RIDX_MCS0)
> +#define ATHN_IS_MIMO_RIDX(ridx)      ((ridx) >= ATHN_RIDX_MCS8)
>  
>  static const struct athn_rate {
> -     uint8_t rate;           /* Rate in 500Kbps unit or MCS if 0x80. */
> -     uint8_t hwrate;         /* HW representation. */
> -     uint8_t rspridx;        /* Control Response Frame rate index. */
> +     uint16_t        rate;           /* Rate in 500Kbps unit. */
> +     uint8_t         hwrate;         /* HW representation. */
> +     uint8_t         rspridx;        /* Control Response Frame rate index. */
>       enum    ieee80211_phytype phy;
>  } athn_rates[] = {
>       {    2, 0x1b, 0, IEEE80211_T_DS },
> @@ -142,22 +146,22 @@ static const struct athn_rate {
>       {   72, 0x0d, 8, IEEE80211_T_OFDM },
>       {   96, 0x08, 8, IEEE80211_T_OFDM },
>       {  108, 0x0c, 8, IEEE80211_T_OFDM },
> -     { 0x80, 0x80, 8, IEEE80211_T_OFDM },
> -     { 0x81, 0x81, 8, IEEE80211_T_OFDM },
> -     { 0x82, 0x82, 8, IEEE80211_T_OFDM },
> -     { 0x83, 0x83, 8, IEEE80211_T_OFDM },
> -     { 0x84, 0x84, 8, IEEE80211_T_OFDM },
> -     { 0x85, 0x85, 8, IEEE80211_T_OFDM },
> -     { 0x86, 0x86, 8, IEEE80211_T_OFDM },
> -     { 0x87, 0x87, 8, IEEE80211_T_OFDM },
> -     { 0x88, 0x88, 8, IEEE80211_T_OFDM },
> -     { 0x89, 0x89, 8, IEEE80211_T_OFDM },
> -     { 0x8a, 0x8a, 8, IEEE80211_T_OFDM },
> -     { 0x8b, 0x8b, 8, IEEE80211_T_OFDM },
> -     { 0x8c, 0x8c, 8, IEEE80211_T_OFDM },
> -     { 0x8d, 0x8d, 8, IEEE80211_T_OFDM },
> -     { 0x8e, 0x8e, 8, IEEE80211_T_OFDM },
> -     { 0x8f, 0x8f, 8, IEEE80211_T_OFDM }
> +     {   13, 0x80, 4, IEEE80211_T_OFDM },
> +     {   26, 0x81, 6, IEEE80211_T_OFDM },
> +     {   39, 0x82, 6, IEEE80211_T_OFDM },
> +     {   52, 0x83, 8, IEEE80211_T_OFDM },
> +     {   78, 0x84, 8, IEEE80211_T_OFDM },
> +     {  104, 0x85, 8, IEEE80211_T_OFDM },
> +     {  117, 0x86, 8, IEEE80211_T_OFDM },
> +     {  130, 0x87, 8, IEEE80211_T_OFDM },
> +     {   26, 0x88, 4, IEEE80211_T_OFDM },
> +     {   52, 0x89, 6, IEEE80211_T_OFDM },
> +     {   78, 0x8a, 8, IEEE80211_T_OFDM },
> +     {  104, 0x8b, 8, IEEE80211_T_OFDM },
> +     {  156, 0x8c, 8, IEEE80211_T_OFDM },
> +     {  208, 0x8d, 8, IEEE80211_T_OFDM },
> +     {  234, 0x8e, 8, IEEE80211_T_OFDM },
> +     {  260, 0x8f, 8, IEEE80211_T_OFDM }
>  };
>  
>  struct athn_series {
> @@ -288,11 +292,14 @@ static const uint16_t ar_mcs_ndbps[][2] 
>  #define ATHN_POWER_OFDM_EXT  67
>  #define ATHN_POWER_COUNT     68
>  
> +#define ATHN_NUM_LEGACY_RATES        IEEE80211_RATE_MAXSIZE
> +#define ATHN_NUM_RATES               (ATHN_NUM_LEGACY_RATES + ATHN_NUM_MCS)
>  struct athn_node {
>       struct ieee80211_node           ni;
>       struct ieee80211_amrr_node      amn;
> -     uint8_t                         ridx[IEEE80211_RATE_MAXSIZE];
> -     uint8_t                         fallback[IEEE80211_RATE_MAXSIZE];
> +     struct ieee80211_mira_node      mn;
> +     uint8_t                         ridx[ATHN_NUM_RATES];
> +     uint8_t                         fallback[ATHN_NUM_RATES];
>       uint8_t                         sta_index;
>  };
>  
> @@ -429,6 +436,8 @@ struct athn_softc {
>  
>       int                             (*sc_newstate)(struct ieee80211com *,
>                                           enum ieee80211_state, int);
> +     void                            (*sc_node_free)(struct ieee80211com *,
> +                                         struct ieee80211_node *);
>  
>       bus_dma_tag_t                   sc_dmat;
>  
> Index: dev/pci/if_athn_pci.c
> ===================================================================
> RCS file: /cvs/src/sys/dev/pci/if_athn_pci.c,v
> retrieving revision 1.18
> diff -u -p -r1.18 if_athn_pci.c
> --- dev/pci/if_athn_pci.c     24 Nov 2015 17:11:39 -0000      1.18
> +++ dev/pci/if_athn_pci.c     8 Jan 2017 09:31:15 -0000
> @@ -43,6 +43,7 @@
>  
>  #include 
>  #include 
> +#include 
>  #include 
>  
>  #include 
> Index: dev/usb/if_athn_usb.c
> ===================================================================
> RCS file: /cvs/src/sys/dev/usb/if_athn_usb.c,v
> retrieving revision 1.43
> diff -u -p -r1.43 if_athn_usb.c
> --- dev/usb/if_athn_usb.c     29 Nov 2016 10:22:30 -0000      1.43
> +++ dev/usb/if_athn_usb.c     9 Jan 2017 10:57:15 -0000
> @@ -48,6 +48,7 @@
>  
>  #include 
>  #include 
> +#include 
>  #include 
>  
>  #include 
> @@ -1132,7 +1133,7 @@ athn_usb_newassoc_cb(struct athn_usb_sof
>  
>       s = splnet();
>       /* NB: Node may have left before we got scheduled. */
> -     if (ni->ni_associd != 0)
> +     if (ni->ni_associd != 0 && ni->ni_state == IEEE80211_STA_ASSOC)
>               (void)athn_usb_create_node(usc, ni);
>       ieee80211_release_node(ic, ni);
>       splx(s);
> @@ -1224,7 +1225,7 @@ athn_usb_create_node(struct athn_usb_sof
>       struct athn_node *an = (struct athn_node *)ni;
>       struct ar_htc_target_sta sta;
>       struct ar_htc_target_rate rate;
> -     int error;
> +     int error, i, j;
>  
>       /* Firmware cannot handle more than 8 STAs. */
>       if (usc->nnodes > AR_USB_MAX_STA)
> @@ -1257,8 +1258,16 @@ athn_usb_create_node(struct athn_usb_sof
>           ni->ni_rates.rs_nrates);
>       if (ni->ni_flags & IEEE80211_NODE_HT) {
>               rate.capflags |= htobe32(AR_RC_HT_FLAG);
> +             /* Setup HT rates. */
> +             for (i = 0, j = 0; i  +                 if 
> (!isset(ni->ni_rxmcs, i))
> +                             continue;
> +                     if (j >= AR_HTC_RATE_MAX)
> +                             break;
> +                     rate.ht_rates.rs_rates[j++] = i;
> +             }
> +             rate.ht_rates.rs_nrates = j;
>  #ifdef notyet
> -             /* XXX setup HT rates */
>               if (ni->ni_htcaps & IEEE80211_HTCAP_CBW20_40)
>                       rate.capflags |= htobe32(AR_RC_40_FLAG);
>               if (ni->ni_htcaps & IEEE80211_HTCAP_SGI40)
> 
> 

-- 
Sent with love from the Tine 2.0 email client ...
Please visit http://www.tine20.com

Reply via email to