This diff adds mira support to the iwn(4) driver. I have tested this with: iwn0 at pci2 dev 0 function 0 "Intel WiFi Link 5100" rev 0x00: msi, MIMO 1T2R When reporting test results please mention which device was tested.
There's a little hack for 4965 hardware because it does not report the number of bytes transmitted. I tested this hack in the 5000 code path and it works there. I did find an actual 4965 device in my pile but it seems to be broken (never shows up in dmesg). Tests on 4965 hardware would be very much appreciated. Index: if_iwn.c =================================================================== RCS file: /cvs/src/sys/dev/pci/if_iwn.c,v retrieving revision 1.176 diff -u -p -r1.176 if_iwn.c --- if_iwn.c 30 Nov 2016 10:52:10 -0000 1.176 +++ if_iwn.c 1 Dec 2016 18:40:38 -0000 @@ -55,6 +55,7 @@ #include <net80211/ieee80211_var.h> #include <net80211/ieee80211_amrr.h> +#include <net80211/ieee80211_mira.h> #include <net80211/ieee80211_radiotap.h> #include <dev/pci/if_iwnreg.h> @@ -164,8 +165,8 @@ void iwn4965_tx_done(struct iwn_softc * struct iwn_rx_data *); void iwn5000_tx_done(struct iwn_softc *, struct iwn_rx_desc *, struct iwn_rx_data *); -void iwn_tx_done(struct iwn_softc *, struct iwn_rx_desc *, int, - uint8_t); +void iwn_tx_done(struct iwn_softc *, struct iwn_rx_desc *, + uint8_t, uint8_t, uint8_t, uint16_t); void iwn_cmd_done(struct iwn_softc *, struct iwn_rx_desc *); void iwn_notif_intr(struct iwn_softc *); void iwn_wakeup_intr(struct iwn_softc *); @@ -1694,8 +1695,10 @@ iwn_newassoc(struct ieee80211com *ic, st uint8_t rate; int ridx, i; - ieee80211_amrr_node_init(&sc->amrr, &wn->amn); - /* Start at lowest available bit-rate, AMRR will raise. */ + if ((ni->ni_flags & IEEE80211_NODE_HT) == 0) + ieee80211_amrr_node_init(&sc->amrr, &wn->amn); + + /* Start at lowest available bit-rate, AMRR/MiRA will raise. */ ni->ni_txrate = 0; ni->ni_txmcs = 0; @@ -1749,10 +1752,16 @@ iwn_newstate(struct ieee80211com *ic, en { struct ifnet *ifp = &ic->ic_if; struct iwn_softc *sc = ifp->if_softc; + struct ieee80211_node *ni = ic->ic_bss; + struct iwn_node *wn = (struct iwn_node *)ni; int error; timeout_del(&sc->calib_to); + if (ic->ic_state == IEEE80211_S_RUN && + (ni->ni_flags & IEEE80211_NODE_HT)) + ieee80211_mira_node_destroy(&wn->mn); + switch (nstate) { case IEEE80211_S_SCAN: /* Make the link LED blink while we're scanning. */ @@ -1805,7 +1814,8 @@ iwn_iter_func(void *arg, struct ieee8021 struct iwn_softc *sc = arg; struct iwn_node *wn = (struct iwn_node *)ni; - ieee80211_amrr_choose(&sc->amrr, ni, &wn->amn); + if ((ni->ni_flags & IEEE80211_NODE_HT) == 0) + ieee80211_amrr_choose(&sc->amrr, ni, &wn->amn); } void @@ -2319,10 +2329,16 @@ iwn4965_tx_done(struct iwn_softc *sc, st struct iwn_rx_data *data) { struct iwn4965_tx_stat *stat = (struct iwn4965_tx_stat *)(desc + 1); + struct iwn_tx_ring *ring = &sc->txq[desc->qid & 0xf]; + struct iwn_tx_data *txdata = &ring->data[desc->idx]; + /* XXX 4965 does not report byte count */ + uint16_t len = txdata->totlen + IEEE80211_CRC_LEN; bus_dmamap_sync(sc->sc_dmat, data->map, sizeof (*desc), sizeof (*stat), BUS_DMASYNC_POSTREAD); - iwn_tx_done(sc, desc, stat->ackfailcnt, letoh32(stat->status) & 0xff); + + iwn_tx_done(sc, desc, stat->nframes, stat->ackfailcnt, + letoh32(stat->status) & 0xff, len); } void @@ -2338,28 +2354,42 @@ iwn5000_tx_done(struct iwn_softc *sc, st bus_dmamap_sync(sc->sc_dmat, data->map, sizeof (*desc), sizeof (*stat), BUS_DMASYNC_POSTREAD); - iwn_tx_done(sc, desc, stat->ackfailcnt, letoh16(stat->status) & 0xff); + iwn_tx_done(sc, desc, stat->nframes, stat->ackfailcnt, + letoh16(stat->status) & 0xff, letoh16(stat->len)); } /* * Adapter-independent backend for TX_DONE firmware notifications. */ void -iwn_tx_done(struct iwn_softc *sc, struct iwn_rx_desc *desc, int ackfailcnt, - uint8_t status) +iwn_tx_done(struct iwn_softc *sc, struct iwn_rx_desc *desc, uint8_t nframes, + uint8_t ackfailcnt, uint8_t status, uint16_t len) { struct ieee80211com *ic = &sc->sc_ic; struct ifnet *ifp = &ic->ic_if; struct iwn_tx_ring *ring = &sc->txq[desc->qid & 0xf]; struct iwn_tx_data *data = &ring->data[desc->idx]; struct iwn_node *wn = (struct iwn_node *)data->ni; + int txfail = (status != 1 && status != 2); - /* Update rate control statistics. */ - wn->amn.amn_txcnt++; - if (ackfailcnt > 0) - wn->amn.amn_retrycnt++; + KASSERT(nframes == 1); /* We don't support aggregation yet. */ - if (status != 1 && status != 2) { + /* Update rate control statistics. */ + if (data->ni->ni_flags & IEEE80211_NODE_HT) { + wn->mn.frames += nframes; + wn->mn.ampdu_size = len; + wn->mn.agglen = nframes; + if (txfail) { + wn->mn.retries += ackfailcnt; + wn->mn.txfail += nframes; + } + ieee80211_mira_choose(&wn->mn, ic, data->ni); + } else { + wn->amn.amn_txcnt++; + if (ackfailcnt > 0) + wn->amn.amn_retrycnt++; + } + if (txfail) { DPRINTF(("%s: status=0x%x\n", __func__, status)); ifp->if_oerrors++; } else @@ -2921,6 +2951,8 @@ iwn_tx(struct iwn_softc *sc, struct mbuf totlen += IEEE80211_CCMP_HDRLEN; } + data->totlen = totlen; + /* Prepare TX firmware command. */ cmd = &ring->cmd[ring->cur]; cmd->code = IWN_CMD_TX_DATA; @@ -4980,6 +5012,11 @@ iwn_run(struct iwn_softc *sc) sc->calib.state = IWN_CALIB_STATE_ASSOC; sc->calib_cnt = 0; timeout_add_msec(&sc->calib_to, 500); + + if (ni->ni_flags & IEEE80211_NODE_HT) { + struct iwn_node *wn = (void *)ni; + ieee80211_mira_node_init(&wn->mn); + } /* Link LED always on while associated. */ iwn_set_led(sc, IWN_LED_LINK, 0, 1); Index: if_iwnvar.h =================================================================== RCS file: /cvs/src/sys/dev/pci/if_iwnvar.h,v retrieving revision 1.31 diff -u -p -r1.31 if_iwnvar.h --- if_iwnvar.h 5 Sep 2016 08:18:18 -0000 1.31 +++ if_iwnvar.h 1 Dec 2016 18:25:59 -0000 @@ -66,6 +66,7 @@ struct iwn_tx_data { bus_addr_t scratch_paddr; struct mbuf *m; struct ieee80211_node *ni; + int totlen; }; struct iwn_tx_ring { @@ -98,6 +99,7 @@ struct iwn_rx_ring { struct iwn_node { struct ieee80211_node ni; /* must be the first */ struct ieee80211_amrr_node amn; + struct ieee80211_mira_node mn; uint16_t disable_tid; uint8_t id; uint8_t ridx[IEEE80211_RATE_MAXSIZE];