diff options
-rw-r--r-- | sys/dev/ic/r92creg.h | 71 | ||||
-rw-r--r-- | sys/dev/ic/rtwn.c | 30 | ||||
-rw-r--r-- | sys/dev/pci/if_rtwn.c | 96 |
3 files changed, 178 insertions, 19 deletions
diff --git a/sys/dev/ic/r92creg.h b/sys/dev/ic/r92creg.h index cfaedfbd42b..8550146b86d 100644 --- a/sys/dev/ic/r92creg.h +++ b/sys/dev/ic/r92creg.h @@ -1,4 +1,4 @@ -/* $OpenBSD: r92creg.h,v 1.5 2017/01/31 09:21:46 stsp Exp $ */ +/* $OpenBSD: r92creg.h,v 1.6 2017/02/01 12:46:40 stsp Exp $ */ /*- * Copyright (c) 2010 Damien Bergamini <damien.bergamini@free.fr> @@ -95,9 +95,9 @@ #define R92C_MBIST_START 0x174 #define R92C_MBIST_DONE 0x178 #define R92C_MBIST_FAIL 0x17c -#define R92C_C2HEVT_MSG_NORMAL 0x1a0 +#define R92C_C2HEVT_MSG 0x1a0 +#define R92C_C2HEVT_CLEAR 0x1af #define R92C_C2HEVT_MSG_TEST 0x1b8 -#define R92C_C2HEVT_CLEAR 0x1bf #define R92C_MCUTST_1 0x1c0 #define R92C_FMETHR 0x1c8 #define R92C_HMETFR 0x1cc @@ -1270,6 +1270,71 @@ struct r92c_tx_desc_usb { #define R92C_TXDW5_AGGNUM_S 24 /* + * C2H event structure. + */ +#define R92C_C2H_MSG_MAX_LEN 16 + +struct r92c_c2h_evt { + uint8_t evtb0; +#define R92C_C2H_EVTB0_ID_M 0x0f +#define R92C_C2H_EVTB0_ID_S 0 +#define R92C_C2H_EVTB0_LEN_M 0xf0 +#define R92C_C2H_EVTB0_LEN_S 4 + + uint8_t seq; + + /* Followed by payload (see below). */ +} __packed; + +/* Bits for R92C_C2HEVT_CLEAR. */ +#define R92C_C2HEVT_HOST_CLOSE 0x00 +#define R92C_C2HEVT_FW_CLOSE 0xff + +/* + * C2H event types. + */ +#define R92C_C2HEVT_DEBUG 0 +#define R92C_C2HEVT_TX_REPORT 3 +#define R92C_C2HEVT_EXT_RA_RPT 6 + +/* Structure for R92C_C2H_EVT_TX_REPORT event. */ +struct r92c_c2h_tx_rpt { + uint8_t rptb0; +#define R92C_RPTB0_RETRY_CNT_M 0x3f +#define R92C_RPTB0_RETRY_CNT_S 0 + + uint8_t rptb1; /* XXX junk */ +#define R92C_RPTB1_RTS_RETRY_CNT_M 0x3f +#define R92C_RPTB1_RTS_RETRY_CNT_S 0 + + uint8_t queue_time_low; + uint8_t queue_time_high; + uint8_t rptb4; +#define R92C_RPTB4_MISSED_PKT_NUM_M 0x1f +#define R92C_RPTB4_MISSED_PKT_NUM_S 0 + + uint8_t rptb5; +#define R92C_RPTB5_MACID_M 0x1f +#define R92C_RPTB5_MACID_S 0 +#define R92C_RPTB5_DES1_FRAGSSN_M 0xe0 +#define R92C_RPTB5_DES1_FRAGSSN_S 5 + + uint8_t rptb6; +#define R92C_RPTB6_RPT_PKT_NUM_M 0x1f +#define R92C_RPTB6_RPT_PKT_NUM_S 0 +#define R92C_RPTB6_PKT_DROP 0x20 +#define R92C_RPTB6_LIFE_EXPIRE 0x40 +#define R92C_RPTB6_RETRY_OVER 0x80 + + uint8_t rptb7; +#define R92C_RPTB7_EDCA_M 0x0f +#define R92C_RPTB7_EDCA_S 0 +#define R92C_RPTB7_BMC 0x20 +#define R92C_RPTB7_PKT_OK 0x40 +#define R92C_RPTB7_INT_CCX 0x80 +} __packed; + +/* * MAC initialization values. */ static const struct { diff --git a/sys/dev/ic/rtwn.c b/sys/dev/ic/rtwn.c index d623e0bb2cd..4ae3beb53fb 100644 --- a/sys/dev/ic/rtwn.c +++ b/sys/dev/ic/rtwn.c @@ -1,4 +1,4 @@ -/* $OpenBSD: rtwn.c,v 1.17 2017/01/31 15:15:13 stsp Exp $ */ +/* $OpenBSD: rtwn.c,v 1.18 2017/02/01 12:46:40 stsp Exp $ */ /*- * Copyright (c) 2010 Damien Bergamini <damien.bergamini@free.fr> @@ -642,7 +642,7 @@ rtwn_media_change(struct ifnet *ifp) } /* - * Initialize rate adaptation in firmware. + * Initialize rate adaptation. */ int rtwn_ra_init(struct rtwn_softc *sc) @@ -686,11 +686,11 @@ rtwn_ra_init(struct rtwn_softc *sc) /* Configure Automatic Rate Fallback Register. */ if (ic->ic_curmode == IEEE80211_MODE_11B) { if (rates & 0x0c) - rtwn_write_4(sc, R92C_ARFR(0), rates & 0x0d); + rtwn_write_4(sc, R92C_ARFR(0), rates & 0x05); else - rtwn_write_4(sc, R92C_ARFR(0), rates & 0x0f); + rtwn_write_4(sc, R92C_ARFR(0), rates & 0x07); } else - rtwn_write_4(sc, R92C_ARFR(0), rates & 0x0ff5); + rtwn_write_4(sc, R92C_ARFR(0), rates & 0x07f5); } if (sc->chip & RTWN_CHIP_88E) { @@ -699,14 +699,26 @@ rtwn_ra_init(struct rtwn_softc *sc) /* We use AMRR with this chip. Start with the lowest rate. */ ni->ni_txrate = 0; } else { - error = rtwn_r92c_ra_init(sc, mode, rates, maxrate, - basicrates, maxbasicrate); - /* No AMRR support yet. Indicate highest supported rate. */ - ni->ni_txrate = rs->rs_nrates - 1; + if (sc->chip & RTWN_CHIP_PCI) { + ni->ni_txrate = 0; /* AMRR will raise. */ + /* Set initial MRR rates. */ + rtwn_write_1(sc, + R92C_INIDATA_RATE_SEL(R92C_MACID_BC), maxbasicrate); + rtwn_write_1(sc, + R92C_INIDATA_RATE_SEL(R92C_MACID_BSS), 0); + } else { + error = rtwn_r92c_ra_init(sc, mode, rates, maxrate, + basicrates, maxbasicrate); + /* No AMRR support. Indicate highest supported rate. */ + ni->ni_txrate = rs->rs_nrates - 1; + } } return (error); } +/* + * Initialize rate adaptation in firmware. + */ int rtwn_r92c_ra_init(struct rtwn_softc *sc, u_int8_t mode, u_int32_t rates, int maxrate, uint32_t basicrates, int maxbasicrate) { diff --git a/sys/dev/pci/if_rtwn.c b/sys/dev/pci/if_rtwn.c index 37362808386..7cb3630586b 100644 --- a/sys/dev/pci/if_rtwn.c +++ b/sys/dev/pci/if_rtwn.c @@ -1,8 +1,9 @@ -/* $OpenBSD: if_rtwn.c,v 1.25 2017/01/22 10:17:38 dlg Exp $ */ +/* $OpenBSD: if_rtwn.c,v 1.26 2017/02/01 12:46:40 stsp Exp $ */ /*- * Copyright (c) 2010 Damien Bergamini <damien.bergamini@free.fr> * Copyright (c) 2015 Stefan Sperling <stsp@openbsd.org> + * Copyright (c) 2015-2016 Andriy Voskoboinyk <avos@FreeBSD.org> * * Permission to use, copy, modify, and distribute this software for any * purpose with or without fee is hereby granted, provided that the above @@ -49,6 +50,7 @@ #include <netinet/if_ether.h> #include <net80211/ieee80211_var.h> +#include <net80211/ieee80211_amrr.h> #include <net80211/ieee80211_radiotap.h> #include <dev/pci/pcireg.h> @@ -161,6 +163,9 @@ struct rtwn_pci_softc { bus_size_t sc_mapsize; int sc_cap_off; + struct ieee80211_amrr amrr; + struct ieee80211_amrr_node amn; + #if NBPFILTER > 0 caddr_t sc_drvbpf; @@ -241,6 +246,8 @@ void rtwn_scan_to(void *); void rtwn_pci_next_scan(void *); void rtwn_cancel_scan(void *); void rtwn_wait_async(void *); +void rtwn_poll_c2h_events(struct rtwn_pci_softc *); +void rtwn_tx_report(struct rtwn_pci_softc *, uint8_t *, int); /* Aliases. */ #define rtwn_bb_write rtwn_pci_write_4 @@ -337,6 +344,9 @@ rtwn_pci_attach(struct device *parent, struct device *self, void *aux) } } + sc->amrr.amrr_min_success_threshold = 1; + sc->amrr.amrr_max_success_threshold = 15; + /* Attach the bus-agnostic driver. */ sc->sc_sc.sc_ops.cookie = sc; sc->sc_sc.sc_ops.write_1 = rtwn_pci_write_1; @@ -989,6 +999,9 @@ rtwn_tx(void *cookie, struct mbuf *m, struct ieee80211_node *ni) SM(R92C_TXDW1_RAID, raid) | R92C_TXDW1_AGGBK); + /* Request TX status report for AMRR. */ + txd->txdw2 |= htole32(R92C_TXDW2_CCX_RPT); + if (m->m_pkthdr.len + IEEE80211_CRC_LEN > ic->ic_rtsthreshold) { txd->txdw4 |= htole32(R92C_TXDW4_RTSEN | R92C_TXDW4_HWRTSEN); @@ -1001,13 +1014,17 @@ rtwn_tx(void *cookie, struct mbuf *m, struct ieee80211_node *ni) R92C_TXDW4_HWRTSEN); } } - /* Send RTS at OFDM24. */ - txd->txdw4 |= htole32(SM(R92C_TXDW4_RTSRATE, 8)); + + if (ic->ic_curmode == IEEE80211_MODE_11B) + txd->txdw4 |= htole32(SM(R92C_TXDW4_RTSRATE, 0)); + else + txd->txdw4 |= htole32(SM(R92C_TXDW4_RTSRATE, 3)); txd->txdw5 |= htole32(SM(R92C_TXDW5_RTSRATE_FBLIMIT, 0xf)); - /* Send data at OFDM54. */ - txd->txdw5 |= htole32(SM(R92C_TXDW5_DATARATE, 11)); - txd->txdw5 |= htole32(SM(R92C_TXDW5_DATARATE_FBLIMIT, 0x1f)); + /* Use AMMR rate for data. */ + txd->txdw4 |= htole32(R92C_TXDW4_DRVRATE); + txd->txdw5 |= htole32(SM(R92C_TXDW5_DATARATE, ni->ni_txrate)); + txd->txdw5 |= htole32(SM(R92C_TXDW5_DATARATE_FBLIMIT, 0x1f)); } else { txd->txdw1 |= htole32( SM(R92C_TXDW1_MACID, 0) | @@ -1128,6 +1145,8 @@ rtwn_tx_done(struct rtwn_pci_softc *sc, int qid) sc->sc_sc.sc_tx_timer = 0; tx_ring->queued--; + + rtwn_poll_c2h_events(sc); } if (tx_ring->queued < (RTWN_TX_LIST_COUNT - 1)) @@ -1149,7 +1168,8 @@ rtwn_alloc_buffers(void *cookie) int rtwn_pci_init(void *cookie) { - /* nothing to do */ + struct rtwn_pci_softc *sc = cookie; + ieee80211_amrr_node_init(&sc->amrr, &sc->amn); return (0); } @@ -1661,6 +1681,12 @@ void rtwn_calib_to(void *arg) { struct rtwn_pci_softc *sc = arg; + struct ieee80211com *ic = &sc->sc_sc.sc_ic; + int s; + + s = splnet(); + ieee80211_amrr_choose(&sc->amrr, ic->ic_bss, &sc->amn); + splx(s); rtwn_calib(&sc->sc_sc); } @@ -1712,3 +1738,59 @@ rtwn_wait_async(void *cookie) { /* nothing to do */ } + +void +rtwn_tx_report(struct rtwn_pci_softc *sc, uint8_t *buf, int len) +{ + struct r92c_c2h_tx_rpt *rpt = (struct r92c_c2h_tx_rpt *)buf; + int packets, tries, tx_ok, drop, expire, over; + + if (len != sizeof(*rpt)) + return; + + packets = MS(rpt->rptb6, R92C_RPTB6_RPT_PKT_NUM); + tries = MS(rpt->rptb0, R92C_RPTB0_RETRY_CNT); + tx_ok = (rpt->rptb7 & R92C_RPTB7_PKT_OK); + drop = (rpt->rptb6 & R92C_RPTB6_PKT_DROP); + expire = (rpt->rptb6 & R92C_RPTB6_LIFE_EXPIRE); + over = (rpt->rptb6 & R92C_RPTB6_RETRY_OVER); + + if (packets > 0) { + if (tx_ok) + sc->amn.amn_txcnt += packets; + if (tries > 1 || drop || expire || over) + sc->amn.amn_retrycnt++; + } +} + +void +rtwn_poll_c2h_events(struct rtwn_pci_softc *sc) +{ + const uint16_t off = R92C_C2HEVT_MSG + sizeof(struct r92c_c2h_evt); + uint8_t buf[R92C_C2H_MSG_MAX_LEN]; + uint8_t id, len, status; + int i; + + /* Read current status. */ + status = rtwn_pci_read_1(sc, R92C_C2HEVT_CLEAR); + if (status == R92C_C2HEVT_HOST_CLOSE) + return; /* nothing to do */ + + if (status == R92C_C2HEVT_FW_CLOSE) { + len = rtwn_pci_read_1(sc, R92C_C2HEVT_MSG); + id = MS(len, R92C_C2H_EVTB0_ID); + len = MS(len, R92C_C2H_EVTB0_LEN); + + if (id == R92C_C2HEVT_TX_REPORT && len <= sizeof(buf)) { + memset(buf, 0, sizeof(buf)); + for (i = 0; i < len; i++) + buf[i] = rtwn_pci_read_1(sc, off + i); + rtwn_tx_report(sc, buf, len); + } else + DPRINTF(("unhandled C2H event %d (%d bytes)\n", + id, len)); + } + + /* Prepare for next event. */ + rtwn_pci_write_1(sc, R92C_C2HEVT_CLEAR, R92C_C2HEVT_HOST_CLOSE); +} |