summaryrefslogtreecommitdiff
path: root/sys/dev/pci
diff options
context:
space:
mode:
authorStefan Sperling <stsp@cvs.openbsd.org>2016-12-07 15:48:45 +0000
committerStefan Sperling <stsp@cvs.openbsd.org>2016-12-07 15:48:45 +0000
commite6def949b2f88bb86568ddd073367de1e7edb866 (patch)
treec7ee2e27ff484dd8a1416579db88e01002e61ccb /sys/dev/pci
parente55daf08e0d26143d478c767611bad0ccc87c144 (diff)
Add mira support to iwn(4).
Please let me know about any regressions. Tested by myself, tb@, okan@, jca@, naddy@, mlarkin@ ok tb@ jca@
Diffstat (limited to 'sys/dev/pci')
-rw-r--r--sys/dev/pci/if_iwn.c71
-rw-r--r--sys/dev/pci/if_iwnvar.h4
2 files changed, 57 insertions, 18 deletions
diff --git a/sys/dev/pci/if_iwn.c b/sys/dev/pci/if_iwn.c
index 4140cd89612..685eebbb524 100644
--- a/sys/dev/pci/if_iwn.c
+++ b/sys/dev/pci/if_iwn.c
@@ -1,4 +1,4 @@
-/* $OpenBSD: if_iwn.c,v 1.176 2016/11/30 10:52:10 stsp Exp $ */
+/* $OpenBSD: if_iwn.c,v 1.177 2016/12/07 15:48:44 stsp Exp $ */
/*-
* Copyright (c) 2007-2010 Damien Bergamini <damien.bergamini@free.fr>
@@ -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_desc *,
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, struct ieee80211_node *ni, int isnew)
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, enum ieee80211_state nstate, int arg)
{
struct ifnet *ifp = &ic->ic_if;
struct iwn_softc *sc = ifp->if_softc;
+ struct ieee80211_node *ni = ic->ic_bss;
+ struct iwn_node *wn = (void *)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. */
@@ -1803,9 +1812,10 @@ void
iwn_iter_func(void *arg, struct ieee80211_node *ni)
{
struct iwn_softc *sc = arg;
- struct iwn_node *wn = (struct iwn_node *)ni;
+ struct iwn_node *wn = (void *)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,15 @@ iwn4965_tx_done(struct iwn_softc *sc, struct iwn_rx_desc *desc,
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 +2353,43 @@ iwn5000_tx_done(struct iwn_softc *sc, struct iwn_rx_desc *desc,
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;
+ struct iwn_node *wn = (void *)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;
+ }
+ if (ic->ic_state == IEEE80211_S_RUN)
+ 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 *m, struct ieee80211_node *ni)
totlen += IEEE80211_CCMP_HDRLEN;
}
+ data->totlen = totlen;
+
/* Prepare TX firmware command. */
cmd = &ring->cmd[ring->cur];
cmd->code = IWN_CMD_TX_DATA;
@@ -4981,6 +5013,11 @@ iwn_run(struct iwn_softc *sc)
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);
return 0;
diff --git a/sys/dev/pci/if_iwnvar.h b/sys/dev/pci/if_iwnvar.h
index fe8b325300e..019ca96f8bd 100644
--- a/sys/dev/pci/if_iwnvar.h
+++ b/sys/dev/pci/if_iwnvar.h
@@ -1,4 +1,4 @@
-/* $OpenBSD: if_iwnvar.h,v 1.31 2016/09/05 08:18:18 tedu Exp $ */
+/* $OpenBSD: if_iwnvar.h,v 1.32 2016/12/07 15:48:44 stsp Exp $ */
/*-
* Copyright (c) 2007, 2008
@@ -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];