diff options
Diffstat (limited to 'freebsd/sys/dev/rtwn')
32 files changed, 451 insertions, 182 deletions
diff --git a/freebsd/sys/dev/rtwn/if_rtwn.c b/freebsd/sys/dev/rtwn/if_rtwn.c index a553814f..050d9960 100644 --- a/freebsd/sys/dev/rtwn/if_rtwn.c +++ b/freebsd/sys/dev/rtwn/if_rtwn.c @@ -123,9 +123,6 @@ static int rtwn_run(struct rtwn_softc *, static void rtwn_watchdog(void *); #endif static void rtwn_parent(struct ieee80211com *); -static int rtwn_llt_write(struct rtwn_softc *, uint32_t, - uint32_t); -static int rtwn_llt_init(struct rtwn_softc *); static int rtwn_dma_init(struct rtwn_softc *); static int rtwn_mac_init(struct rtwn_softc *); static void rtwn_mrr_init(struct rtwn_softc *); @@ -697,6 +694,7 @@ rtwn_ioctl_reset(struct ieee80211vap *vap, u_long cmd) case IEEE80211_IOC_RTSTHRESHOLD: case IEEE80211_IOC_PROTMODE: case IEEE80211_IOC_HTPROTMODE: + case IEEE80211_IOC_LDPC: error = 0; break; default: @@ -1384,54 +1382,6 @@ rtwn_parent(struct ieee80211com *ic) rtwn_stop(sc); } - -static int -rtwn_llt_write(struct rtwn_softc *sc, uint32_t addr, uint32_t data) -{ - int ntries, error; - - error = rtwn_write_4(sc, R92C_LLT_INIT, - SM(R92C_LLT_INIT_OP, R92C_LLT_INIT_OP_WRITE) | - SM(R92C_LLT_INIT_ADDR, addr) | - SM(R92C_LLT_INIT_DATA, data)); - if (error != 0) - return (error); - /* Wait for write operation to complete. */ - for (ntries = 0; ntries < 20; ntries++) { - if (MS(rtwn_read_4(sc, R92C_LLT_INIT), R92C_LLT_INIT_OP) == - R92C_LLT_INIT_OP_NO_ACTIVE) - return (0); - rtwn_delay(sc, 10); - } - return (ETIMEDOUT); -} - -static int -rtwn_llt_init(struct rtwn_softc *sc) -{ - int i, error; - - /* Reserve pages [0; page_count]. */ - for (i = 0; i < sc->page_count; i++) { - if ((error = rtwn_llt_write(sc, i, i + 1)) != 0) - return (error); - } - /* NB: 0xff indicates end-of-list. */ - if ((error = rtwn_llt_write(sc, i, 0xff)) != 0) - return (error); - /* - * Use pages [page_count + 1; pktbuf_count - 1] - * as ring buffer. - */ - for (++i; i < sc->pktbuf_count - 1; i++) { - if ((error = rtwn_llt_write(sc, i, i + 1)) != 0) - return (error); - } - /* Make the last page point to the beginning of the ring buffer. */ - error = rtwn_llt_write(sc, i, sc->page_count + 1); - return (error); -} - static int rtwn_dma_init(struct rtwn_softc *sc) { @@ -1770,13 +1720,13 @@ rtwn_node_alloc(struct ieee80211vap *vap, } static void -rtwn_newassoc(struct ieee80211_node *ni, int isnew) +rtwn_newassoc(struct ieee80211_node *ni, int isnew __unused) { struct rtwn_softc *sc = ni->ni_ic->ic_softc; struct rtwn_node *un = RTWN_NODE(ni); int id; - if (!isnew) + if (un->id != RTWN_MACID_UNDEFINED) return; RTWN_NT_LOCK(sc); @@ -2001,6 +1951,7 @@ rtwn_stop(struct rtwn_softc *sc) sc->fwver = 0; sc->thcal_temp = 0; sc->cur_bcnq_id = RTWN_VAP_ID_INVALID; + bzero(&sc->last_physt, sizeof(sc->last_physt)); #ifdef D4054 ieee80211_tx_watchdog_stop(&sc->sc_ic); diff --git a/freebsd/sys/dev/rtwn/if_rtwn_rx.c b/freebsd/sys/dev/rtwn/if_rtwn_rx.c index 8d103dc7..31ab7e69 100644 --- a/freebsd/sys/dev/rtwn/if_rtwn_rx.c +++ b/freebsd/sys/dev/rtwn/if_rtwn_rx.c @@ -119,18 +119,19 @@ rtwn_set_basicrates(struct rtwn_softc *sc, uint32_t rates) } static void -rtwn_update_avgrssi(struct rtwn_softc *sc, struct rtwn_node *un, int rate) +rtwn_update_avgrssi(struct rtwn_softc *sc, struct rtwn_node *un, int8_t rssi, + int is_cck) { int pwdb; /* Convert antenna signal to percentage. */ - if (un->last_rssi <= -100 || un->last_rssi >= 20) + if (rssi <= -100 || rssi >= 20) pwdb = 0; - else if (un->last_rssi >= 0) + else if (rssi >= 0) pwdb = 100; else - pwdb = 100 + un->last_rssi; - if (RTWN_RATE_IS_CCK(rate)) { + pwdb = 100 + rssi; + if (is_cck) { /* CCK gain is smaller than OFDM/MCS gain. */ pwdb += 6; if (pwdb > 100) @@ -157,11 +158,11 @@ rtwn_update_avgrssi(struct rtwn_softc *sc, struct rtwn_node *un, int rate) } static int8_t -rtwn_get_rssi(struct rtwn_softc *sc, int rate, void *physt) +rtwn_get_rssi(struct rtwn_softc *sc, void *physt, int is_cck) { int8_t rssi; - if (RTWN_RATE_IS_CCK(rate)) + if (is_cck) rssi = rtwn_get_rssi_cck(sc, physt); else /* OFDM/HT. */ rssi = rtwn_get_rssi_ofdm(sc, physt); @@ -190,81 +191,133 @@ rtwn_get_tsf(struct rtwn_softc *sc, uint64_t *buf, int id) *buf += rtwn_get_tsf_low(sc, id); } +static uint64_t +rtwn_extend_rx_tsf(struct rtwn_softc *sc, const struct r92c_rx_stat *stat) +{ + uint64_t tsft; + uint32_t rxdw3, tsfl, tsfl_curr; + int id; + + rxdw3 = le32toh(stat->rxdw3); + tsfl = le32toh(stat->tsf_low); + id = MS(rxdw3, R92C_RXDW3_BSSID_FIT); + + switch (id) { + case 1: + case 2: + id >>= 1; + tsfl_curr = rtwn_get_tsf_low(sc, id); + break; + default: + { + uint32_t tsfl0, tsfl1; + + tsfl0 = rtwn_get_tsf_low(sc, 0); + tsfl1 = rtwn_get_tsf_low(sc, 1); + + if (abs(tsfl0 - tsfl) < abs(tsfl1 - tsfl)) { + id = 0; + tsfl_curr = tsfl0; + } else { + id = 1; + tsfl_curr = tsfl1; + } + break; + } + } + + tsft = rtwn_get_tsf_high(sc, id); + if (tsfl > tsfl_curr && tsfl > 0xffff0000) + tsft--; + tsft <<= 32; + tsft += tsfl; + + return (tsft); +} + struct ieee80211_node * -rtwn_rx_common(struct rtwn_softc *sc, struct mbuf *m, void *desc, - int8_t *rssi) +rtwn_rx_common(struct rtwn_softc *sc, struct mbuf *m, void *desc) { struct ieee80211com *ic = &sc->sc_ic; struct ieee80211_node *ni; struct ieee80211_frame_min *wh; + struct ieee80211_rx_stats rxs; struct rtwn_node *un; struct r92c_rx_stat *stat; - uint32_t rxdw0, rxdw3; - int cipher, infosz, pktlen, rate, shift; + void *physt; + uint32_t rxdw0; + int8_t rssi; + int cipher, infosz, is_cck, pktlen, shift; stat = desc; rxdw0 = le32toh(stat->rxdw0); - rxdw3 = le32toh(stat->rxdw3); cipher = MS(rxdw0, R92C_RXDW0_CIPHER); infosz = MS(rxdw0, R92C_RXDW0_INFOSZ) * 8; pktlen = MS(rxdw0, R92C_RXDW0_PKTLEN); shift = MS(rxdw0, R92C_RXDW0_SHIFT); - rate = MS(rxdw3, R92C_RXDW3_RATE); wh = (struct ieee80211_frame_min *)(mtodo(m, shift + infosz)); if ((wh->i_fc[1] & IEEE80211_FC1_PROTECTED) && cipher != R92C_CAM_ALGO_NONE) m->m_flags |= M_WEP; - if (pktlen >= sizeof(*wh)) + if (pktlen >= sizeof(*wh)) { ni = ieee80211_find_rxnode(ic, wh); - else + if (ni != NULL && (ni->ni_flags & IEEE80211_NODE_HT)) + m->m_flags |= M_AMPDU; + } else ni = NULL; un = RTWN_NODE(ni); - /* Get RSSI from PHY status descriptor if present. */ - if (infosz != 0 && (rxdw0 & R92C_RXDW0_PHYST)) { - *rssi = rtwn_get_rssi(sc, rate, mtod(m, void *)); - RTWN_DPRINTF(sc, RTWN_DEBUG_RSSI, "%s: rssi %d, ridx %d\n", - __func__, *rssi, rate); + if (infosz != 0 && (rxdw0 & R92C_RXDW0_PHYST)) + physt = (void *)mtodo(m, shift); + else + physt = (un != NULL) ? &un->last_physt : &sc->last_physt; + + bzero(&rxs, sizeof(rxs)); + rtwn_get_rx_stats(sc, &rxs, desc, physt); + if (rxs.c_pktflags & IEEE80211_RX_F_AMPDU) { + /* Next MPDU will come without PHY info. */ + memcpy(&sc->last_physt, physt, sizeof(sc->last_physt)); + if (un != NULL) + memcpy(&un->last_physt, physt, sizeof(sc->last_physt)); + } - sc->last_rssi = *rssi; - if (un != NULL) { - un->last_rssi = *rssi; + /* Add some common bits. */ + /* NB: should not happen. */ + if (rxdw0 & R92C_RXDW0_CRCERR) + rxs.c_pktflags |= IEEE80211_RX_F_FAIL_FCSCRC; + + rxs.r_flags |= IEEE80211_R_TSF_START; /* XXX undocumented */ + rxs.r_flags |= IEEE80211_R_TSF64; + rxs.c_rx_tsf = rtwn_extend_rx_tsf(sc, stat); + + /* Get RSSI from PHY status descriptor. */ + is_cck = (rxs.c_pktflags & IEEE80211_RX_F_CCK) != 0; + rssi = rtwn_get_rssi(sc, physt, is_cck); + + /* XXX TODO: we really need a rate-to-string method */ + RTWN_DPRINTF(sc, RTWN_DEBUG_RSSI, "%s: rssi %d, rate %d\n", + __func__, rssi, rxs.c_rate); + if (un != NULL && infosz != 0 && (rxdw0 & R92C_RXDW0_PHYST)) { + /* Update our average RSSI. */ + rtwn_update_avgrssi(sc, un, rssi, is_cck); + } - /* Update our average RSSI. */ - rtwn_update_avgrssi(sc, un, rate); - } - } else - *rssi = (un != NULL) ? un->last_rssi : sc->last_rssi; + rxs.r_flags |= IEEE80211_R_NF | IEEE80211_R_RSSI; + rxs.c_nf = RTWN_NOISE_FLOOR; + rxs.c_rssi = rssi - rxs.c_nf; + (void) ieee80211_add_rx_params(m, &rxs); if (ieee80211_radiotap_active(ic)) { struct rtwn_rx_radiotap_header *tap = &sc->sc_rxtap; - int id = RTWN_VAP_ID_INVALID; - - if (ni != NULL) - id = RTWN_VAP(ni->ni_vap)->id; - if (id == RTWN_VAP_ID_INVALID) - id = 0; tap->wr_flags = rtwn_rx_radiotap_flags(sc, desc); - tap->wr_tsft = rtwn_get_tsf_high(sc, id); - if (le32toh(stat->tsf_low) > rtwn_get_tsf_low(sc, id)) - tap->wr_tsft--; - tap->wr_tsft = (uint64_t)htole32(tap->wr_tsft) << 32; - tap->wr_tsft += stat->tsf_low; - - /* XXX 20/40? */ - - /* Map HW rate index to 802.11 rate. */ - if (rate < RTWN_RIDX_MCS(0)) - tap->wr_rate = ridx2rate[rate]; - else /* MCS0~15. */ - tap->wr_rate = IEEE80211_RATE_MCS | (rate - 12); - - tap->wr_dbm_antsignal = *rssi; - tap->wr_dbm_antnoise = RTWN_NOISE_FLOOR; + tap->wr_tsft = htole64(rxs.c_rx_tsf); + tap->wr_rate = rxs.c_rate; + tap->wr_dbm_antsignal = rssi; + tap->wr_dbm_antnoise = rxs.c_nf; } /* Drop PHY descriptor. */ diff --git a/freebsd/sys/dev/rtwn/if_rtwn_rx.h b/freebsd/sys/dev/rtwn/if_rtwn_rx.h index dfdcc4bf..49897eb9 100644 --- a/freebsd/sys/dev/rtwn/if_rtwn_rx.h +++ b/freebsd/sys/dev/rtwn/if_rtwn_rx.h @@ -26,7 +26,7 @@ void rtwn_get_rates(struct rtwn_softc *, const struct ieee80211_rateset *, const struct ieee80211_htrateset *, uint32_t *, int *, int); void rtwn_set_basicrates(struct rtwn_softc *, uint32_t); struct ieee80211_node * rtwn_rx_common(struct rtwn_softc *, struct mbuf *, - void *, int8_t *); + void *); void rtwn_adhoc_recv_mgmt(struct ieee80211_node *, struct mbuf *, int, const struct ieee80211_rx_stats *, int, int); void rtwn_set_multi(struct rtwn_softc *); diff --git a/freebsd/sys/dev/rtwn/if_rtwn_tx.c b/freebsd/sys/dev/rtwn/if_rtwn_tx.c index 1ea9a766..c48e2e0e 100644 --- a/freebsd/sys/dev/rtwn/if_rtwn_tx.c +++ b/freebsd/sys/dev/rtwn/if_rtwn_tx.c @@ -114,17 +114,16 @@ static int rtwn_tx_data(struct rtwn_softc *sc, struct ieee80211_node *ni, struct mbuf *m) { - const struct ieee80211_txparam *tp; + const struct ieee80211_txparam *tp = ni->ni_txparms; struct ieee80211com *ic = &sc->sc_ic; struct ieee80211vap *vap = ni->ni_vap; struct ieee80211_key *k = NULL; - struct ieee80211_channel *chan; struct ieee80211_frame *wh; struct rtwn_tx_desc_common *txd; struct rtwn_tx_buf buf; uint8_t rate, ridx, type; u_int cipher; - int ismcast, maxretry; + int ismcast; RTWN_ASSERT_LOCKED(sc); @@ -132,20 +131,15 @@ rtwn_tx_data(struct rtwn_softc *sc, struct ieee80211_node *ni, type = wh->i_fc[0] & IEEE80211_FC0_TYPE_MASK; ismcast = IEEE80211_IS_MULTICAST(wh->i_addr1); - chan = (ni->ni_chan != IEEE80211_CHAN_ANYC) ? - ni->ni_chan : ic->ic_curchan; - tp = &vap->iv_txparms[ieee80211_chan2mode(chan)]; - maxretry = tp->maxretry; - /* Choose a TX rate index. */ - if (type == IEEE80211_FC0_TYPE_MGT) + if (type == IEEE80211_FC0_TYPE_MGT || + type == IEEE80211_FC0_TYPE_CTL || + (m->m_flags & M_EAPOL) != 0) rate = tp->mgmtrate; else if (ismcast) rate = tp->mcastrate; else if (tp->ucastrate != IEEE80211_FIXED_RATE_NONE) rate = tp->ucastrate; - else if (m->m_flags & M_EAPOL) - rate = tp->mgmtrate; else { if (sc->sc_ratectl == RTWN_RATECTL_NET80211) { /* XXX pass pktlen */ @@ -183,7 +177,7 @@ rtwn_tx_data(struct rtwn_softc *sc, struct ieee80211_node *ni, memset(txd, 0, sc->txdesc_len); txd->txdw1 = htole32(SM(RTWN_TXDW1_CIPHER, rtwn_get_cipher(cipher))); - rtwn_fill_tx_desc(sc, ni, m, txd, ridx, maxretry); + rtwn_fill_tx_desc(sc, ni, m, txd, ridx, tp->maxretry); if (ieee80211_radiotap_active_vap(vap)) { struct rtwn_tx_radiotap_header *tap = &sc->sc_txtap; diff --git a/freebsd/sys/dev/rtwn/if_rtwnvar.h b/freebsd/sys/dev/rtwn/if_rtwnvar.h index 0c010adb..d8754024 100644 --- a/freebsd/sys/dev/rtwn/if_rtwnvar.h +++ b/freebsd/sys/dev/rtwn/if_rtwnvar.h @@ -76,6 +76,12 @@ struct rtwn_tx_buf { uint8_t txd[RTWN_TX_DESC_SIZE]; } __attribute__((aligned(4))); +#define RTWN_PHY_STATUS_SIZE 32 +struct rtwn_tx_phystat { + uint32_t phydw[RTWN_PHY_STATUS_SIZE / sizeof(uint32_t)]; +}; + + struct rtwn_softc; union sec_param { @@ -95,7 +101,8 @@ struct rtwn_cmdq { struct rtwn_node { struct ieee80211_node ni; /* must be the first */ int id; - int8_t last_rssi; + + struct rtwn_tx_phystat last_physt; int avg_pwdb; }; #define RTWN_NODE(ni) ((struct rtwn_node *)(ni)) @@ -195,7 +202,7 @@ struct rtwn_softc { const char *name; int sc_ant; - int8_t last_rssi; + struct rtwn_tx_phystat last_physt; uint8_t thcal_temp; int cur_bcnq_id; @@ -301,6 +308,7 @@ struct rtwn_softc { void (*sc_fw_reset)(struct rtwn_softc *, int); void (*sc_fw_download_enable)(struct rtwn_softc *, int); #endif + int (*sc_llt_init)(struct rtwn_softc *); int (*sc_set_page_size)(struct rtwn_softc *); void (*sc_lc_calib)(struct rtwn_softc *); void (*sc_iq_calib)(struct rtwn_softc *); @@ -336,6 +344,9 @@ struct rtwn_softc { struct ieee80211vap *, int); void (*sc_set_rssi)(struct rtwn_softc *); #endif + void (*sc_get_rx_stats)(struct rtwn_softc *, + struct ieee80211_rx_stats *, const void *, + const void *); int8_t (*sc_get_rssi_cck)(struct rtwn_softc *, void *); int8_t (*sc_get_rssi_ofdm)(struct rtwn_softc *, void *); int (*sc_classify_intr)(struct rtwn_softc *, void *, int); @@ -462,8 +473,8 @@ void rtwn_suspend(struct rtwn_softc *); /* Aliases. */ #define rtwn_bb_write rtwn_write_4 -#define rtwn_bb_read rtwn_read_4 -#define rtwn_bb_setbits rtwn_setbits_4 +#define rtwn_bb_read rtwn_read_4 +#define rtwn_bb_setbits rtwn_setbits_4 /* Device-specific. */ #define rtwn_rf_read(_sc, _chain, _addr) \ @@ -478,6 +489,8 @@ void rtwn_suspend(struct rtwn_softc *); (((_sc)->sc_parse_rom)((_sc), (_rom))) #define rtwn_set_led(_sc, _led, _on) \ (((_sc)->sc_set_led)((_sc), (_led), (_on))) +#define rtwn_get_rx_stats(_sc, _rxs, _desc, _physt) \ + (((_sc)->sc_get_rx_stats((_sc), (_rxs), (_desc), (_physt)))) #define rtwn_get_rssi_cck(_sc, _physt) \ (((_sc)->sc_get_rssi_cck)((_sc), (_physt))) #define rtwn_get_rssi_ofdm(_sc, _physt) \ @@ -492,6 +505,8 @@ void rtwn_suspend(struct rtwn_softc *); #define rtwn_fw_download_enable(_sc, _enable) \ (((_sc)->sc_fw_download_enable)((_sc), (_enable))) #endif +#define rtwn_llt_init(_sc) \ + (((_sc)->sc_llt_init)((_sc))) #define rtwn_set_page_size(_sc) \ (((_sc)->sc_set_page_size)((_sc))) #define rtwn_lc_calib(_sc) \ diff --git a/freebsd/sys/dev/rtwn/pci/rtwn_pci_attach.c b/freebsd/sys/dev/rtwn/pci/rtwn_pci_attach.c index 5b28d27f..9813cb32 100644 --- a/freebsd/sys/dev/rtwn/pci/rtwn_pci_attach.c +++ b/freebsd/sys/dev/rtwn/pci/rtwn_pci_attach.c @@ -96,20 +96,31 @@ static void rtwn_pci_beacon_update_end(struct rtwn_softc *, static void rtwn_pci_attach_methods(struct rtwn_softc *); -static int matched_chip = RTWN_CHIP_MAX_PCI; +static const struct rtwn_pci_ident * +rtwn_pci_probe_sub(device_t dev) +{ + const struct rtwn_pci_ident *ident; + int vendor_id, device_id; + + vendor_id = pci_get_vendor(dev); + device_id = pci_get_device(dev); + + for (ident = rtwn_pci_ident_table; ident->name != NULL; ident++) + if (vendor_id == ident->vendor && device_id == ident->device) + return (ident); + + return (NULL); +} static int rtwn_pci_probe(device_t dev) { const struct rtwn_pci_ident *ident; - for (ident = rtwn_pci_ident_table; ident->name != NULL; ident++) { - if (pci_get_vendor(dev) == ident->vendor && - pci_get_device(dev) == ident->device) { - matched_chip = ident->chip; - device_set_desc(dev, ident->name); - return (BUS_PROBE_DEFAULT); - } + ident = rtwn_pci_probe_sub(dev); + if (ident != NULL) { + device_set_desc(dev, ident->name); + return (BUS_PROBE_DEFAULT); } return (ENXIO); } @@ -593,13 +604,15 @@ rtwn_pci_attach_methods(struct rtwn_softc *sc) static int rtwn_pci_attach(device_t dev) { + const struct rtwn_pci_ident *ident; struct rtwn_pci_softc *pc = device_get_softc(dev); struct rtwn_softc *sc = &pc->pc_sc; struct ieee80211com *ic = &sc->sc_ic; uint32_t lcsr; int cap_off, i, error, rid; - if (matched_chip >= RTWN_CHIP_MAX_PCI) + ident = rtwn_pci_probe_sub(dev); + if (ident == NULL) return (ENXIO); /* @@ -651,8 +664,7 @@ rtwn_pci_attach(device_t dev) mtx_init(&sc->sc_mtx, ic->ic_name, MTX_NETWORK_LOCK, MTX_DEF); rtwn_pci_attach_methods(sc); - /* XXX something similar to USB_GET_DRIVER_INFO() */ - rtwn_pci_attach_private(pc, matched_chip); + rtwn_pci_attach_private(pc, ident->chip); /* Allocate Tx/Rx buffers. */ error = rtwn_pci_alloc_rx_list(sc); diff --git a/freebsd/sys/dev/rtwn/pci/rtwn_pci_rx.c b/freebsd/sys/dev/rtwn/pci/rtwn_pci_rx.c index 8da0061b..292fb07f 100644 --- a/freebsd/sys/dev/rtwn/pci/rtwn_pci_rx.c +++ b/freebsd/sys/dev/rtwn/pci/rtwn_pci_rx.c @@ -97,7 +97,6 @@ rtwn_pci_rx_frame(struct rtwn_softc *sc, struct r92ce_rx_stat *rx_desc, struct ieee80211_node *ni; uint32_t rxdw0; struct mbuf *m, *m1; - int8_t rssi = 0, nf; int infosz, pktlen, shift, error; /* Dump Rx descriptor. */ @@ -164,12 +163,11 @@ rtwn_pci_rx_frame(struct rtwn_softc *sc, struct r92ce_rx_stat *rx_desc, rx_data->m = m1; m->m_pkthdr.len = m->m_len = pktlen + infosz + shift; - nf = RTWN_NOISE_FLOOR; - ni = rtwn_rx_common(sc, m, rx_desc, &rssi); + ni = rtwn_rx_common(sc, m, rx_desc); RTWN_DPRINTF(sc, RTWN_DEBUG_RECV, - "%s: Rx frame len %d, infosz %d, shift %d, rssi %d\n", - __func__, pktlen, infosz, shift, rssi); + "%s: Rx frame len %d, infosz %d, shift %d\n", + __func__, pktlen, infosz, shift); /* Update RX descriptor. */ rtwn_pci_setup_rx_desc(pc, rx_desc, rx_data->paddr, MJUMPAGESIZE, @@ -178,11 +176,11 @@ rtwn_pci_rx_frame(struct rtwn_softc *sc, struct r92ce_rx_stat *rx_desc, /* Send the frame to the 802.11 layer. */ RTWN_UNLOCK(sc); if (ni != NULL) { - (void)ieee80211_input(ni, m, rssi - nf, nf); + (void)ieee80211_input_mimo(ni, m); /* Node is no longer needed. */ ieee80211_free_node(ni); } else - (void)ieee80211_input_all(ic, m, rssi - nf, nf); + (void)ieee80211_input_mimo_all(ic, m); RTWN_LOCK(sc); @@ -284,17 +282,6 @@ rtwn_pci_rx_done(struct rtwn_softc *sc) ring->cur = (ring->cur + 1) % RTWN_PCI_RX_LIST_COUNT; } - - /* Finished receive; age anything left on the FF queue by a little bump */ - /* - * XXX TODO: just make this a callout timer schedule so we can - * flush the FF staging queue if we're approaching idle. - */ -#ifdef IEEE80211_SUPPORT_SUPERG - if (!(sc->sc_flags & RTWN_FW_LOADED) || - sc->sc_ratectl != RTWN_RATECTL_NET80211) - rtwn_cmd_sleepable(sc, NULL, 0, rtwn_ff_flush_all); -#endif } void diff --git a/freebsd/sys/dev/rtwn/rtl8188e/r88e.h b/freebsd/sys/dev/rtwn/rtl8188e/r88e.h index 999ab400..1c03ddd3 100644 --- a/freebsd/sys/dev/rtwn/rtl8188e/r88e.h +++ b/freebsd/sys/dev/rtwn/rtl8188e/r88e.h @@ -85,6 +85,8 @@ void r88e_ratectl_tx_complete(struct rtwn_softc *, uint8_t *, int); void r88e_handle_c2h_report(struct rtwn_softc *, uint8_t *, int); int8_t r88e_get_rssi_cck(struct rtwn_softc *, void *); int8_t r88e_get_rssi_ofdm(struct rtwn_softc *, void *); +void r88e_get_rx_stats(struct rtwn_softc *, struct ieee80211_rx_stats *, + const void *, const void *); /* r88e_tx.c */ void r88e_tx_enable_ampdu(void *, int); diff --git a/freebsd/sys/dev/rtwn/rtl8188e/r88e_fw.c b/freebsd/sys/dev/rtwn/rtl8188e/r88e_fw.c index 409084f6..fb7743ed 100644 --- a/freebsd/sys/dev/rtwn/rtl8188e/r88e_fw.c +++ b/freebsd/sys/dev/rtwn/rtl8188e/r88e_fw.c @@ -71,7 +71,7 @@ r88e_fw_cmd(struct rtwn_softc *sc, uint8_t id, const void *buf, int len) } /* Wait for current FW box to be empty. */ - for (ntries = 0; ntries < 50; ntries++) { + for (ntries = 0; ntries < 100; ntries++) { if (!(rtwn_read_1(sc, R92C_HMETFR) & (1 << sc->fwcur))) break; rtwn_delay(sc, 2000); diff --git a/freebsd/sys/dev/rtwn/rtl8188e/r88e_rx.c b/freebsd/sys/dev/rtwn/rtl8188e/r88e_rx.c index 464542b4..acffb40e 100644 --- a/freebsd/sys/dev/rtwn/rtl8188e/r88e_rx.c +++ b/freebsd/sys/dev/rtwn/rtl8188e/r88e_rx.c @@ -53,6 +53,7 @@ __FBSDID("$FreeBSD$"); #include <dev/rtwn/if_rtwn_debug.h> #include <dev/rtwn/if_rtwn_ridx.h> +#include <dev/rtwn/rtl8192c/r92c.h> #include <dev/rtwn/rtl8188e/r88e.h> #include <dev/rtwn/rtl8188e/r88e_rx_desc.h> @@ -211,3 +212,19 @@ r88e_get_rssi_ofdm(struct rtwn_softc *sc, void *physt) return (rssi); } + +void +r88e_get_rx_stats(struct rtwn_softc *sc, struct ieee80211_rx_stats *rxs, + const void *desc, const void *physt_ptr) +{ + const struct r88e_rx_phystat *physt = physt_ptr; + + r92c_get_rx_stats(sc, rxs, desc, physt_ptr); + + if (!sc->sc_ht40) { /* XXX center channel */ + rxs->r_flags |= IEEE80211_R_IEEE | IEEE80211_R_FREQ; + rxs->c_ieee = le16toh(physt->chan); + rxs->c_freq = ieee80211_ieee2mhz(rxs->c_ieee, + IEEE80211_CHAN_2GHZ); + } +} diff --git a/freebsd/sys/dev/rtwn/rtl8188e/usb/r88eu_attach.c b/freebsd/sys/dev/rtwn/rtl8188e/usb/r88eu_attach.c index 4d5452be..f834fb38 100644 --- a/freebsd/sys/dev/rtwn/rtl8188e/usb/r88eu_attach.c +++ b/freebsd/sys/dev/rtwn/rtl8188e/usb/r88eu_attach.c @@ -129,6 +129,7 @@ r88eu_attach(struct rtwn_usb_softc *uc) sc->sc_dump_tx_desc = r92cu_dump_tx_desc; sc->sc_tx_radiotap_flags = r92c_tx_radiotap_flags; sc->sc_rx_radiotap_flags = r92c_rx_radiotap_flags; + sc->sc_get_rx_stats = r88e_get_rx_stats; sc->sc_get_rssi_cck = r88e_get_rssi_cck; sc->sc_get_rssi_ofdm = r88e_get_rssi_ofdm; sc->sc_classify_intr = r88eu_classify_intr; @@ -147,6 +148,7 @@ r88eu_attach(struct rtwn_usb_softc *uc) sc->sc_fw_reset = r88e_fw_reset; sc->sc_fw_download_enable = r88e_fw_download_enable; #endif + sc->sc_llt_init = r92c_llt_init; sc->sc_set_page_size = r92c_set_page_size; sc->sc_lc_calib = r92c_lc_calib; sc->sc_iq_calib = r88e_iq_calib; /* XXX TODO */ diff --git a/freebsd/sys/dev/rtwn/rtl8192c/pci/r92ce_attach.c b/freebsd/sys/dev/rtwn/rtl8192c/pci/r92ce_attach.c index d53dbf98..225c69f5 100644 --- a/freebsd/sys/dev/rtwn/rtl8192c/pci/r92ce_attach.c +++ b/freebsd/sys/dev/rtwn/rtl8192c/pci/r92ce_attach.c @@ -174,6 +174,7 @@ r92ce_attach(struct rtwn_pci_softc *pc) sc->sc_dump_tx_desc = r92ce_dump_tx_desc; sc->sc_tx_radiotap_flags = r92c_tx_radiotap_flags; sc->sc_rx_radiotap_flags = r92c_rx_radiotap_flags; + sc->sc_get_rx_stats = r92c_get_rx_stats; sc->sc_get_rssi_cck = r92c_get_rssi_cck; sc->sc_get_rssi_ofdm = r92c_get_rssi_ofdm; sc->sc_classify_intr = r92ce_classify_intr; @@ -192,6 +193,7 @@ r92ce_attach(struct rtwn_pci_softc *pc) sc->sc_fw_reset = r92ce_fw_reset; sc->sc_fw_download_enable = r92c_fw_download_enable; #endif + sc->sc_llt_init = r92c_llt_init; sc->sc_set_page_size = r92c_set_page_size; sc->sc_lc_calib = r92c_lc_calib; sc->sc_iq_calib = r92ce_iq_calib; diff --git a/freebsd/sys/dev/rtwn/rtl8192c/r92c.h b/freebsd/sys/dev/rtwn/rtl8192c/r92c.h index 2b63179e..5ac666d0 100644 --- a/freebsd/sys/dev/rtwn/rtl8192c/r92c.h +++ b/freebsd/sys/dev/rtwn/rtl8192c/r92c.h @@ -77,6 +77,7 @@ void r92c_handle_c2h_report(void *); /* r92c_init.c */ int r92c_check_condition(struct rtwn_softc *, const uint8_t[]); +int r92c_llt_init(struct rtwn_softc *); int r92c_set_page_size(struct rtwn_softc *); void r92c_init_bb_common(struct rtwn_softc *); int r92c_init_rf_chain(struct rtwn_softc *, @@ -87,6 +88,9 @@ void r92c_init_ampdu(struct rtwn_softc *); void r92c_init_antsel(struct rtwn_softc *); void r92c_pa_bias_init(struct rtwn_softc *); +/* r92c_llt.c */ +int r92c_llt_write(struct rtwn_softc *, uint32_t, uint32_t); + /* r92c_rf.c */ uint32_t r92c_rf_read(struct rtwn_softc *, int, uint8_t); void r92c_rf_write(struct rtwn_softc *, int, uint8_t, uint32_t); @@ -99,6 +103,8 @@ void r92c_parse_rom(struct rtwn_softc *, uint8_t *); int8_t r92c_get_rssi_cck(struct rtwn_softc *, void *); int8_t r92c_get_rssi_ofdm(struct rtwn_softc *, void *); uint8_t r92c_rx_radiotap_flags(const void *); +void r92c_get_rx_stats(struct rtwn_softc *, struct ieee80211_rx_stats *, + const void *, const void *); /* r92c_tx.c */ void r92c_tx_enable_ampdu(void *, int); diff --git a/freebsd/sys/dev/rtwn/rtl8192c/r92c_fw.c b/freebsd/sys/dev/rtwn/rtl8192c/r92c_fw.c index 74c7d205..91bcfc0e 100644 --- a/freebsd/sys/dev/rtwn/rtl8192c/r92c_fw.c +++ b/freebsd/sys/dev/rtwn/rtl8192c/r92c_fw.c @@ -82,7 +82,7 @@ r92c_fw_cmd(struct rtwn_softc *sc, uint8_t id, const void *buf, int len) } /* Wait for current FW box to be empty. */ - for (ntries = 0; ntries < 50; ntries++) { + for (ntries = 0; ntries < 100; ntries++) { if (!(rtwn_read_1(sc, R92C_HMETFR) & (1 << sc->fwcur))) break; rtwn_delay(sc, 2000); diff --git a/freebsd/sys/dev/rtwn/rtl8192c/r92c_init.c b/freebsd/sys/dev/rtwn/rtl8192c/r92c_init.c index d8db0286..4ec44045 100644 --- a/freebsd/sys/dev/rtwn/rtl8192c/r92c_init.c +++ b/freebsd/sys/dev/rtwn/rtl8192c/r92c_init.c @@ -92,6 +92,32 @@ r92c_check_condition(struct rtwn_softc *sc, const uint8_t cond[]) } int +r92c_llt_init(struct rtwn_softc *sc) +{ + int i, error; + + /* Reserve pages [0; page_count]. */ + for (i = 0; i < sc->page_count; i++) { + if ((error = r92c_llt_write(sc, i, i + 1)) != 0) + return (error); + } + /* NB: 0xff indicates end-of-list. */ + if ((error = r92c_llt_write(sc, i, 0xff)) != 0) + return (error); + /* + * Use pages [page_count + 1; pktbuf_count - 1] + * as ring buffer. + */ + for (++i; i < sc->pktbuf_count - 1; i++) { + if ((error = r92c_llt_write(sc, i, i + 1)) != 0) + return (error); + } + /* Make the last page point to the beginning of the ring buffer. */ + error = r92c_llt_write(sc, i, sc->page_count + 1); + return (error); +} + +int r92c_set_page_size(struct rtwn_softc *sc) { return (rtwn_write_1(sc, R92C_PBP, SM(R92C_PBP_PSRX, R92C_PBP_128) | diff --git a/freebsd/sys/dev/rtwn/rtl8192c/r92c_reg.h b/freebsd/sys/dev/rtwn/rtl8192c/r92c_reg.h index ff03d191..34a4b80c 100644 --- a/freebsd/sys/dev/rtwn/rtl8192c/r92c_reg.h +++ b/freebsd/sys/dev/rtwn/rtl8192c/r92c_reg.h @@ -66,6 +66,7 @@ #define R92C_HSIMR 0x058 #define R92C_HSISR 0x05c #define R92C_MULTI_FUNC_CTRL 0x068 +#define R92C_LDO_SWR_CTRL 0x07c #define R92C_MCUFWDL 0x080 #define R92C_HMEBOX_EXT(idx) (0x088 + (idx) * 2) #define R92C_EFUSE_ACCESS 0x0cf @@ -115,6 +116,7 @@ #define R92C_TXDMA_OFFSET_CHK 0x20c #define R92C_TXDMA_STATUS 0x210 #define R92C_RQPN_NPQ 0x214 +#define R92C_AUTO_LLT 0x224 /* Rx DMA Configuration. */ #define R92C_RXDMA_AGG_PG_TH 0x280 #define R92C_RXPKT_NUM 0x284 @@ -297,6 +299,16 @@ #define R92C_SYS_CLKR_SYS_EN 0x00001000 #define R92C_SYS_CLKR_RING_EN 0x00002000 +/* Bits for R92C_RSV_CTRL. */ +#define R92C_RSV_CTRL_WLOCK_ALL 0x01 +#define R92C_RSV_CTRL_WLOCK_00 0x02 +#define R92C_RSV_CTRL_WLOCK_04 0x04 +#define R92C_RSV_CTRL_WLOCK_08 0x08 +#define R92C_RSV_CTRL_WLOCK_40 0x10 +#define R92C_RSV_CTRL_R_DIS_PRST_0 0x20 +#define R92C_RSV_CTRL_R_DIS_PRST_1 0x40 +#define R92C_RSV_CTRL_LOCK_ALL_EN 0x80 + /* Bits for R92C_RF_CTRL. */ #define R92C_RF_CTRL_EN 0x01 #define R92C_RF_CTRL_RSTB 0x02 @@ -339,6 +351,9 @@ /* Bits for R92C_LEDCFG0. */ #define R92C_LEDCFG0_DIS 0x08 +/* Bits for R92C_LEDCFG1. */ +#define R92C_LEDCFG1_DIS 0x80 + /* Bits for R92C_MULTI_FUNC_CTRL. */ #define R92C_MULTI_BT_FUNC_EN 0x00040000 @@ -420,6 +435,7 @@ #define R92C_PBP_1024 4 /* Bits for R92C_TRXDMA_CTRL. */ +#define R92C_TRXDMA_CTRL_RX_SHIFT_EN 0x0002 #define R92C_TRXDMA_CTRL_RXDMA_AGG_EN 0x0004 #define R92C_TRXDMA_CTRL_TXDMA_VOQ_MAP_M 0x0030 #define R92C_TRXDMA_CTRL_TXDMA_VOQ_MAP_S 4 @@ -476,6 +492,9 @@ /* Bits for R92C_TXDMA_OFFSET_CHK. */ #define R92C_TXDMA_OFFSET_DROP_DATA_EN 0x00000200 +/* Bits for R92C_AUTO_LLT. */ +#define R92C_AUTO_LLT_INIT 0x00010000 + /* Bits for R92C_FWHW_TXQ_CTRL. */ #define R92C_FWHW_TXQ_CTRL_AMPDU_RTY_NEW 0x80 #define R92C_FWHW_TXQ_CTRL_REAL_BEACON 0x400000 @@ -593,7 +612,8 @@ #define R92C_RCR_APPFCS 0x80000000 /* Bits for R92C_RX_DRVINFO_SZ. */ -#define R92C_RX_DRVINFO_SZ_DEF 4 /* XXX other values will not work */ +/* XXX other values will not work */ +#define R92C_RX_DRVINFO_SZ_DEF ((RTWN_PHY_STATUS_SIZE) / 8) /* Bits for R92C_WMAC_TRXPTCL_CTL. */ #define R92C_WMAC_TRXPTCL_SHPRE 0x00020000 @@ -681,6 +701,7 @@ #define R92C_OFDM0_TXIQIMBALANCE(chain) (0xc80 + (chain) * 8) #define R92C_OFDM0_TXAFE(chain) (0xc94 + (chain) * 8) #define R92C_OFDM0_RXIQEXTANTA 0xca0 +#define R92C_OFDM0_TXPSEUDONOISEWGT 0xce4 #define R92C_OFDM1_LSTF 0xd00 /* Bits for R92C_FPGA[01]_RFMOD. */ @@ -800,6 +821,9 @@ #define R92C_LSSI_READBACK_DATA_M 0x000fffff #define R92C_LSSI_READBACK_DATA_S 0 +/* Bits for R92C_CCK0_SYSTEM. */ +#define R92C_CCK0_SYSTEM_CCK_SIDEBAND 0x00000010 + /* Bits for R92C_OFDM0_AGCCORE1(i). */ #define R92C_OFDM0_AGCCORE1_GAIN_M 0x0000007f #define R92C_OFDM0_AGCCORE1_GAIN_S 0 diff --git a/freebsd/sys/dev/rtwn/rtl8192c/r92c_rx.c b/freebsd/sys/dev/rtwn/rtl8192c/r92c_rx.c index b77c76f6..70dff0f6 100644 --- a/freebsd/sys/dev/rtwn/rtl8192c/r92c_rx.c +++ b/freebsd/sys/dev/rtwn/rtl8192c/r92c_rx.c @@ -102,3 +102,47 @@ r92c_rx_radiotap_flags(const void *buf) flags = IEEE80211_RADIOTAP_F_SHORTGI; return (flags); } + +void +r92c_get_rx_stats(struct rtwn_softc *sc, struct ieee80211_rx_stats *rxs, + const void *desc, const void *physt_ptr) +{ + const struct r92c_rx_stat *stat = desc; + uint32_t rxdw1, rxdw3; + uint8_t rate; + + rxdw1 = le32toh(stat->rxdw1); + rxdw3 = le32toh(stat->rxdw3); + rate = MS(rxdw3, R92C_RXDW3_RATE); + + if (rxdw1 & R92C_RXDW1_AMPDU) + rxs->c_pktflags |= IEEE80211_RX_F_AMPDU; + else if (rxdw1 & R92C_RXDW1_AMPDU_MORE) + rxs->c_pktflags |= IEEE80211_RX_F_AMPDU_MORE; + if ((rxdw3 & R92C_RXDW3_SPLCP) && rate >= RTWN_RIDX_MCS(0)) + rxs->c_pktflags |= IEEE80211_RX_F_SHORTGI; + + if (rxdw3 & R92C_RXDW3_HT40) + rxs->c_width = IEEE80211_RX_FW_40MHZ; + else + rxs->c_width = IEEE80211_RX_FW_20MHZ; + + if (RTWN_RATE_IS_CCK(rate)) + rxs->c_phytype = IEEE80211_RX_FP_11B; + else if (rate < RTWN_RIDX_MCS(0)) + rxs->c_phytype = IEEE80211_RX_FP_11G; + else + rxs->c_phytype = IEEE80211_RX_FP_11NG; + + /* Map HW rate index to 802.11 rate. */ + if (rate < RTWN_RIDX_MCS(0)) { + rxs->c_rate = ridx2rate[rate]; + if (RTWN_RATE_IS_CCK(rate)) + rxs->c_pktflags |= IEEE80211_RX_F_CCK; + else + rxs->c_pktflags |= IEEE80211_RX_F_OFDM; + } else { /* MCS0~15. */ + rxs->c_rate = IEEE80211_RATE_MCS | (rate - 12); + rxs->c_pktflags |= IEEE80211_RX_F_HT; + } +} diff --git a/freebsd/sys/dev/rtwn/rtl8192c/r92c_rx_desc.h b/freebsd/sys/dev/rtwn/rtl8192c/r92c_rx_desc.h index 7fec70be..12dfd665 100644 --- a/freebsd/sys/dev/rtwn/rtl8192c/r92c_rx_desc.h +++ b/freebsd/sys/dev/rtwn/rtl8192c/r92c_rx_desc.h @@ -45,6 +45,9 @@ struct r92c_rx_stat { uint32_t rxdw1; #define R92C_RXDW1_MACID_M 0x0000001f #define R92C_RXDW1_MACID_S 0 +#define R92C_RXDW1_AMSDU 0x00002000 +#define R92C_RXDW1_AMPDU_MORE 0x00004000 +#define R92C_RXDW1_AMPDU 0x00008000 #define R92C_RXDW1_MC 0x40000000 #define R92C_RXDW1_BC 0x80000000 @@ -56,6 +59,8 @@ struct r92c_rx_stat { #define R92C_RXDW3_SPLCP 0x00000100 #define R92C_RXDW3_HT40 0x00000200 #define R92C_RXDW3_HTC 0x00000400 +#define R92C_RXDW3_BSSID_FIT_M 0x00003000 +#define R92C_RXDW3_BSSID_FIT_S 12 uint32_t rxdw4; uint32_t tsf_low; diff --git a/freebsd/sys/dev/rtwn/rtl8192c/r92c_tx_desc.h b/freebsd/sys/dev/rtwn/rtl8192c/r92c_tx_desc.h index 037ac0e2..c3bc87ca 100644 --- a/freebsd/sys/dev/rtwn/rtl8192c/r92c_tx_desc.h +++ b/freebsd/sys/dev/rtwn/rtl8192c/r92c_tx_desc.h @@ -68,7 +68,7 @@ struct r92c_tx_desc { uint16_t txdseq; uint32_t txdw4; -#define R92C_TXDW4_RTSRATE_M 0x0000003f +#define R92C_TXDW4_RTSRATE_M 0x0000001f #define R92C_TXDW4_RTSRATE_S 0 #define R92C_TXDW4_SEQ_SEL_M 0x00000040 #define R92C_TXDW4_SEQ_SEL_S 6 diff --git a/freebsd/sys/dev/rtwn/rtl8192c/usb/r92cu_attach.c b/freebsd/sys/dev/rtwn/rtl8192c/usb/r92cu_attach.c index ce3f7a1a..aa6f7067 100644 --- a/freebsd/sys/dev/rtwn/rtl8192c/usb/r92cu_attach.c +++ b/freebsd/sys/dev/rtwn/rtl8192c/usb/r92cu_attach.c @@ -167,6 +167,7 @@ r92cu_attach(struct rtwn_usb_softc *uc) sc->sc_dump_tx_desc = r92cu_dump_tx_desc; sc->sc_tx_radiotap_flags = r92c_tx_radiotap_flags; sc->sc_rx_radiotap_flags = r92c_rx_radiotap_flags; + sc->sc_get_rx_stats = r92c_get_rx_stats; sc->sc_get_rssi_cck = r92c_get_rssi_cck; sc->sc_get_rssi_ofdm = r92c_get_rssi_ofdm; sc->sc_classify_intr = r92cu_classify_intr; @@ -185,6 +186,7 @@ r92cu_attach(struct rtwn_usb_softc *uc) sc->sc_fw_reset = r92c_fw_reset; sc->sc_fw_download_enable = r92c_fw_download_enable; #endif + sc->sc_llt_init = r92c_llt_init; sc->sc_set_page_size = r92c_set_page_size; sc->sc_lc_calib = r92c_lc_calib; sc->sc_iq_calib = r92c_iq_calib; /* XXX TODO */ diff --git a/freebsd/sys/dev/rtwn/rtl8812a/r12a.h b/freebsd/sys/dev/rtwn/rtl8812a/r12a.h index ec1d61e1..e8de45aa 100644 --- a/freebsd/sys/dev/rtwn/rtl8812a/r12a.h +++ b/freebsd/sys/dev/rtwn/rtl8812a/r12a.h @@ -128,6 +128,8 @@ void r12a_ratectl_tx_complete(struct rtwn_softc *, uint8_t *, int); void r12a_handle_c2h_report(struct rtwn_softc *, uint8_t *, int); int r12a_check_frame_checksum(struct rtwn_softc *, struct mbuf *); uint8_t r12a_rx_radiotap_flags(const void *); +void r12a_get_rx_stats(struct rtwn_softc *, struct ieee80211_rx_stats *, + const void *, const void *); /* r12a_tx.c */ void r12a_fill_tx_desc(struct rtwn_softc *, struct ieee80211_node *, diff --git a/freebsd/sys/dev/rtwn/rtl8812a/r12a_beacon.c b/freebsd/sys/dev/rtwn/rtl8812a/r12a_beacon.c index 37b1a183..67714442 100644 --- a/freebsd/sys/dev/rtwn/rtl8812a/r12a_beacon.c +++ b/freebsd/sys/dev/rtwn/rtl8812a/r12a_beacon.c @@ -79,6 +79,8 @@ r12a_beacon_init(struct rtwn_softc *sc, void *buf, int id) txd->txdw3 = htole32(R12A_TXDW3_DRVRATE); txd->txdw3 |= htole32(SM(R12A_TXDW3_SEQ_SEL, id)); + txd->txdw4 = htole32(SM(R12A_TXDW4_DATARATE, RTWN_RIDX_CCK1)); + txd->txdw6 = htole32(SM(R21A_TXDW6_MBSSID, id)); } diff --git a/freebsd/sys/dev/rtwn/rtl8812a/r12a_fw.c b/freebsd/sys/dev/rtwn/rtl8812a/r12a_fw.c index 12a3d855..f3bbc099 100644 --- a/freebsd/sys/dev/rtwn/rtl8812a/r12a_fw.c +++ b/freebsd/sys/dev/rtwn/rtl8812a/r12a_fw.c @@ -70,14 +70,14 @@ void r12a_fw_reset(struct rtwn_softc *sc, int reason) { /* Reset MCU IO wrapper. */ - rtwn_setbits_1(sc, R92C_RSV_CTRL, 0x02, 0); + rtwn_setbits_1(sc, R92C_RSV_CTRL, R92C_RSV_CTRL_WLOCK_00, 0); rtwn_setbits_1(sc, R92C_RSV_CTRL + 1, 0x08, 0); rtwn_setbits_1_shift(sc, R92C_SYS_FUNC_EN, R92C_SYS_FUNC_EN_CPUEN, 0, 1); /* Enable MCU IO wrapper. */ - rtwn_setbits_1(sc, R92C_RSV_CTRL, 0x02, 0); + rtwn_setbits_1(sc, R92C_RSV_CTRL, R92C_RSV_CTRL_WLOCK_00, 0); rtwn_setbits_1(sc, R92C_RSV_CTRL + 1, 0, 0x08); rtwn_setbits_1_shift(sc, R92C_SYS_FUNC_EN, diff --git a/freebsd/sys/dev/rtwn/rtl8812a/r12a_rx.c b/freebsd/sys/dev/rtwn/rtl8812a/r12a_rx.c index 049717a4..b9c3bbf8 100644 --- a/freebsd/sys/dev/rtwn/rtl8812a/r12a_rx.c +++ b/freebsd/sys/dev/rtwn/rtl8812a/r12a_rx.c @@ -231,10 +231,99 @@ r12a_rx_radiotap_flags(const void *buf) if (!(stat->rxdw4 & htole32(R12A_RXDW4_SPLCP))) return (0); - rate = MS(le32toh(stat->rxdw3), R92C_RXDW3_RATE); + rate = MS(le32toh(stat->rxdw3), R12A_RXDW3_RATE); if (RTWN_RATE_IS_CCK(rate)) flags = IEEE80211_RADIOTAP_F_SHORTPRE; else flags = IEEE80211_RADIOTAP_F_SHORTGI; return (flags); } + +void +r12a_get_rx_stats(struct rtwn_softc *sc, struct ieee80211_rx_stats *rxs, + const void *desc, const void *physt_ptr) +{ + const struct r92c_rx_stat *stat = desc; + const struct r12a_rx_phystat *physt = physt_ptr; + uint32_t rxdw0, rxdw1, rxdw3, rxdw4; + uint8_t rate; + + rxdw0 = le32toh(stat->rxdw0); + rxdw1 = le32toh(stat->rxdw1); + rxdw3 = le32toh(stat->rxdw3); + rxdw4 = le32toh(stat->rxdw4); + rate = MS(rxdw3, R12A_RXDW3_RATE); + + /* TODO: STBC */ + if (rxdw4 & R12A_RXDW4_LDPC) + rxs->c_pktflags |= IEEE80211_RX_F_LDPC; + if (rxdw1 & R12A_RXDW1_AMPDU) { + if (rxdw0 & R92C_RXDW0_PHYST) + rxs->c_pktflags |= IEEE80211_RX_F_AMPDU; + else + rxs->c_pktflags |= IEEE80211_RX_F_AMPDU_MORE; + } + + if ((rxdw4 & R12A_RXDW4_SPLCP) && rate >= RTWN_RIDX_MCS(0)) + rxs->c_pktflags |= IEEE80211_RX_F_SHORTGI; + + switch (MS(rxdw4, R12A_RXDW4_BW)) { + case R12A_RXDW4_BW20: + rxs->c_width = IEEE80211_RX_FW_20MHZ; + break; + case R12A_RXDW4_BW40: + rxs->c_width = IEEE80211_RX_FW_40MHZ; + break; + case R12A_RXDW4_BW80: + rxs->c_width = IEEE80211_RX_FW_80MHZ; + break; + default: + break; + } + + if (RTWN_RATE_IS_CCK(rate)) + rxs->c_phytype = IEEE80211_RX_FP_11B; + else { + int is5ghz; + + /* XXX magic */ + /* XXX check with RTL8812AU */ + is5ghz = (physt->cfosho[2] != 0x01); + + if (rate < RTWN_RIDX_MCS(0)) { + if (is5ghz) + rxs->c_phytype = IEEE80211_RX_FP_11A; + else + rxs->c_phytype = IEEE80211_RX_FP_11G; + } else { + if (is5ghz) + rxs->c_phytype = IEEE80211_RX_FP_11NA; + else + rxs->c_phytype = IEEE80211_RX_FP_11NG; + } + } + + /* Map HW rate index to 802.11 rate. */ + if (rate < RTWN_RIDX_MCS(0)) { + rxs->c_rate = ridx2rate[rate]; + if (RTWN_RATE_IS_CCK(rate)) + rxs->c_pktflags |= IEEE80211_RX_F_CCK; + else + rxs->c_pktflags |= IEEE80211_RX_F_OFDM; + } else { /* MCS0~15. */ + /* TODO: VHT rates */ + rxs->c_rate = IEEE80211_RATE_MCS | (rate - 12); + rxs->c_pktflags |= IEEE80211_RX_F_HT; + } + + /* + * XXX always zero for RTL8821AU + * (vendor driver does not check this field) + */ +#if 0 + rxs->r_flags |= IEEE80211_R_IEEE | IEEE80211_R_FREQ; + rxs->c_ieee = MS(le16toh(physt->phyw1), R12A_PHYW1_CHAN); + rxs->c_freq = ieee80211_ieee2mhz(rxs->c_ieee, + (rxs->c_ieee < 36) ? IEEE80211_CHAN_2GHZ : IEEE80211_CHAN_5GHZ); +#endif +} diff --git a/freebsd/sys/dev/rtwn/rtl8812a/r12a_rx_desc.h b/freebsd/sys/dev/rtwn/rtl8812a/r12a_rx_desc.h index 8642ca85..c3d19527 100644 --- a/freebsd/sys/dev/rtwn/rtl8812a/r12a_rx_desc.h +++ b/freebsd/sys/dev/rtwn/rtl8812a/r12a_rx_desc.h @@ -34,18 +34,26 @@ /* Rx MAC descriptor defines (chip-specific). */ /* Rx dword 1 */ #define R12A_RXDW1_AMSDU 0x00002000 +#define R12A_RXDW1_AMPDU 0x00008000 #define R12A_RXDW1_CKSUM_ERR 0x00100000 #define R12A_RXDW1_IPV6 0x00200000 #define R12A_RXDW1_UDP 0x00400000 #define R12A_RXDW1_CKSUM 0x00800000 /* Rx dword 2 */ #define R12A_RXDW2_RPT_C2H 0x10000000 +/* Rx dword 3 */ +#define R12A_RXDW3_RATE_M 0x0000007f +#define R12A_RXDW3_RATE_S 0 /* Rx dword 4 */ #define R12A_RXDW4_SPLCP 0x00000001 #define R12A_RXDW4_LDPC 0x00000002 #define R12A_RXDW4_STBC 0x00000004 #define R12A_RXDW4_BW_M 0x00000030 #define R12A_RXDW4_BW_S 4 +#define R12A_RXDW4_BW20 0 +#define R12A_RXDW4_BW40 1 +#define R12A_RXDW4_BW80 2 +#define R12A_RXDW4_BW160 3 /* Rx PHY descriptor. */ struct r12a_rx_phystat { diff --git a/freebsd/sys/dev/rtwn/rtl8812a/r12a_tx.c b/freebsd/sys/dev/rtwn/rtl8812a/r12a_tx.c index f7bd3a8e..40d54634 100644 --- a/freebsd/sys/dev/rtwn/rtl8812a/r12a_tx.c +++ b/freebsd/sys/dev/rtwn/rtl8812a/r12a_tx.c @@ -216,6 +216,17 @@ r12a_tx_set_sgi(struct rtwn_softc *sc, void *buf, struct ieee80211_node *ni) txd->txdw5 |= htole32(R12A_TXDW5_DATA_SHORT); } +static void +r12a_tx_set_ldpc(struct rtwn_softc *sc, struct r12a_tx_desc *txd, + struct ieee80211_node *ni) +{ + struct ieee80211vap *vap = ni->ni_vap; + + if ((vap->iv_flags_ht & IEEE80211_FHT_LDPC_TX) && + (ni->ni_htcap & IEEE80211_HTCAP_LDPC)) + txd->txdw5 |= htole32(R12A_TXDW5_DATA_LDPC); +} + void r12a_fill_tx_desc(struct rtwn_softc *sc, struct ieee80211_node *ni, struct mbuf *m, void *buf, uint8_t ridx, int maxretry) @@ -286,6 +297,7 @@ r12a_fill_tx_desc(struct rtwn_softc *sc, struct ieee80211_node *ni, if (ridx >= RTWN_RIDX_MCS(0)) { r12a_tx_set_ht40(sc, txd, ni); r12a_tx_set_sgi(sc, txd, ni); + r12a_tx_set_ldpc(sc, txd, ni); prot = ic->ic_htprotmode; } else if (ic->ic_flags & IEEE80211_F_USEPROT) prot = ic->ic_protmode; diff --git a/freebsd/sys/dev/rtwn/rtl8812a/usb/r12au_attach.c b/freebsd/sys/dev/rtwn/rtl8812a/usb/r12au_attach.c index 684076eb..97d966f0 100644 --- a/freebsd/sys/dev/rtwn/rtl8812a/usb/r12au_attach.c +++ b/freebsd/sys/dev/rtwn/rtl8812a/usb/r12au_attach.c @@ -170,7 +170,15 @@ r12a_read_chipid_vendor(struct rtwn_softc *sc, uint32_t reg_sys_cfg) static void r12au_adj_devcaps(struct rtwn_softc *sc) { - /* TODO: LDPC, STBC etc */ + struct r12a_softc *rs = sc->sc_priv; + struct ieee80211com *ic = &sc->sc_ic; + + if (rs->chip & R12A_CHIP_C_CUT) { + ic->ic_htcaps |= IEEE80211_HTCAP_LDPC | + IEEE80211_HTC_TXLDPC; + } + + /* TODO: STBC, VHT etc */ } void @@ -192,6 +200,7 @@ r12au_attach(struct rtwn_usb_softc *uc) sc->sc_dump_tx_desc = r12au_dump_tx_desc; sc->sc_tx_radiotap_flags = r12a_tx_radiotap_flags; sc->sc_rx_radiotap_flags = r12a_rx_radiotap_flags; + sc->sc_get_rx_stats = r12a_get_rx_stats; sc->sc_get_rssi_cck = r88e_get_rssi_cck; sc->sc_get_rssi_ofdm = r88e_get_rssi_ofdm; sc->sc_classify_intr = r12au_classify_intr; @@ -208,6 +217,7 @@ r12au_attach(struct rtwn_usb_softc *uc) sc->sc_fw_reset = r12a_fw_reset; sc->sc_fw_download_enable = r12a_fw_download_enable; #endif + sc->sc_llt_init = r92c_llt_init; sc->sc_set_page_size = r12a_set_page_size; sc->sc_lc_calib = r12a_lc_calib; sc->sc_iq_calib = r12a_iq_calib; diff --git a/freebsd/sys/dev/rtwn/rtl8821a/r21a_init.c b/freebsd/sys/dev/rtwn/rtl8821a/r21a_init.c index a3bcde77..e2c3972f 100644 --- a/freebsd/sys/dev/rtwn/rtl8821a/r21a_init.c +++ b/freebsd/sys/dev/rtwn/rtl8821a/r21a_init.c @@ -176,7 +176,7 @@ r21a_power_on(struct rtwn_softc *sc) R92C_CR_CALTMR_EN)); if (rtwn_read_4(sc, R92C_SYS_CFG) & R92C_SYS_CFG_TRP_BT_EN) - RTWN_CHK(rtwn_setbits_1(sc, 0x07C, 0, 0x40)); + RTWN_CHK(rtwn_setbits_1(sc, R92C_LDO_SWR_CTRL, 0, 0x40)); return (0); #undef RTWN_CHK diff --git a/freebsd/sys/dev/rtwn/rtl8821a/usb/r21au_attach.c b/freebsd/sys/dev/rtwn/rtl8821a/usb/r21au_attach.c index 6f7129f8..145aca21 100644 --- a/freebsd/sys/dev/rtwn/rtl8821a/usb/r21au_attach.c +++ b/freebsd/sys/dev/rtwn/rtl8821a/usb/r21au_attach.c @@ -159,10 +159,11 @@ r21au_adj_devcaps(struct rtwn_softc *sc) struct ieee80211com *ic = &sc->sc_ic; struct r12a_softc *rs = sc->sc_priv; + ic->ic_htcaps |= IEEE80211_HTC_TXLDPC; if (rs->rs_radar != 0) ic->ic_caps |= IEEE80211_C_DFS; - /* TODO: LDPC etc */ + /* TODO: VHT */ } void @@ -184,6 +185,7 @@ r21au_attach(struct rtwn_usb_softc *uc) sc->sc_dump_tx_desc = r12au_dump_tx_desc; sc->sc_tx_radiotap_flags = r12a_tx_radiotap_flags; sc->sc_rx_radiotap_flags = r12a_rx_radiotap_flags; + sc->sc_get_rx_stats = r12a_get_rx_stats; sc->sc_get_rssi_cck = r21a_get_rssi_cck; sc->sc_get_rssi_ofdm = r88e_get_rssi_ofdm; sc->sc_classify_intr = r12au_classify_intr; @@ -201,6 +203,7 @@ r21au_attach(struct rtwn_usb_softc *uc) sc->sc_fw_reset = r21a_fw_reset; sc->sc_fw_download_enable = r12a_fw_download_enable; #endif + sc->sc_llt_init = r92c_llt_init; sc->sc_set_page_size = rtwn_nop_int_softc; sc->sc_lc_calib = rtwn_nop_softc; /* XXX not used */ sc->sc_iq_calib = r12a_iq_calib; diff --git a/freebsd/sys/dev/rtwn/usb/rtwn_usb_attach.h b/freebsd/sys/dev/rtwn/usb/rtwn_usb_attach.h index 48a4d6e5..ee6d9137 100644 --- a/freebsd/sys/dev/rtwn/usb/rtwn_usb_attach.h +++ b/freebsd/sys/dev/rtwn/usb/rtwn_usb_attach.h @@ -21,12 +21,14 @@ */ void r92cu_attach(struct rtwn_usb_softc *); +void r92eu_attach(struct rtwn_usb_softc *); void r88eu_attach(struct rtwn_usb_softc *); void r12au_attach(struct rtwn_usb_softc *); void r21au_attach(struct rtwn_usb_softc *); enum { RTWN_CHIP_RTL8192CU, + RTWN_CHIP_RTL8192EU, RTWN_CHIP_RTL8188EU, RTWN_CHIP_RTL8812AU, RTWN_CHIP_RTL8821AU, @@ -92,7 +94,6 @@ static const STRUCT_USB_HOST_ID rtwn_devs[] = { RTWN_RTL8192CU_DEV(REALTEK, RTL8191CU), RTWN_RTL8192CU_DEV(REALTEK, RTL8192CE), RTWN_RTL8192CU_DEV(REALTEK, RTL8192CU), - RTWN_RTL8192CU_DEV(REALTEK, RTL8192CU_1), RTWN_RTL8192CU_DEV(SITECOMEU, RTL8188CU_1), RTWN_RTL8192CU_DEV(SITECOMEU, RTL8188CU_2), RTWN_RTL8192CU_DEV(SITECOMEU, RTL8192CU), @@ -101,6 +102,15 @@ static const STRUCT_USB_HOST_ID rtwn_devs[] = { RTWN_RTL8192CU_DEV(ZYXEL, RTL8192CU), #undef RTWN_RTL8192CU_DEV + /* RTL8192EU */ +#define RTWN_RTL8192EU_DEV(v,p) \ + { USB_VPI(USB_VENDOR_##v, USB_PRODUCT_##v##_##p, RTWN_CHIP_RTL8192EU) } + RTWN_RTL8192EU_DEV(DLINK, DWA131E1), + RTWN_RTL8192EU_DEV(REALTEK, RTL8192EU), + RTWN_RTL8192EU_DEV(TPLINK, WN822NV4), + RTWN_RTL8192EU_DEV(TPLINK, WN823NV2), +#undef RTWN_RTL8192EU_DEV + /* RTL8188EU */ #define RTWN_RTL8188EU_DEV(v,p) \ { USB_VPI(USB_VENDOR_##v, USB_PRODUCT_##v##_##p, RTWN_CHIP_RTL8188EU) } @@ -148,6 +158,7 @@ typedef void (*chip_usb_attach)(struct rtwn_usb_softc *); static const chip_usb_attach rtwn_chip_usb_attach[RTWN_CHIP_MAX_USB] = { [RTWN_CHIP_RTL8192CU] = r92cu_attach, + [RTWN_CHIP_RTL8192EU] = r92eu_attach, [RTWN_CHIP_RTL8188EU] = r88eu_attach, [RTWN_CHIP_RTL8812AU] = r12au_attach, [RTWN_CHIP_RTL8821AU] = r21au_attach diff --git a/freebsd/sys/dev/rtwn/usb/rtwn_usb_ep.c b/freebsd/sys/dev/rtwn/usb/rtwn_usb_ep.c index a1fafb46..b75aa3b9 100644 --- a/freebsd/sys/dev/rtwn/usb/rtwn_usb_ep.c +++ b/freebsd/sys/dev/rtwn/usb/rtwn_usb_ep.c @@ -60,7 +60,7 @@ __FBSDID("$FreeBSD$"); #include <dev/rtwn/rtl8192c/usb/r92cu_reg.h> -static struct usb_config rtwn_config[RTWN_N_TRANSFER] = { +static const struct usb_config rtwn_config_common[RTWN_N_TRANSFER] = { [RTWN_BULK_RX] = { .type = UE_BULK, .endpoint = UE_ADDR_ANY, @@ -163,6 +163,7 @@ rtwn_usb_setup_queues(struct rtwn_usb_softc *uc) int rtwn_usb_setup_endpoints(struct rtwn_usb_softc *uc) { + struct usb_config *rtwn_config; struct rtwn_softc *sc = &uc->uc_sc; const uint8_t iface_index = RTWN_IFACE_INDEX; struct usb_endpoint *ep, *ep_end; @@ -199,6 +200,9 @@ rtwn_usb_setup_endpoints(struct rtwn_usb_softc *uc) return (EINVAL); } + rtwn_config = malloc(sizeof(rtwn_config_common), M_TEMP, M_WAITOK); + memcpy(rtwn_config, rtwn_config_common, sizeof(rtwn_config_common)); + /* NB: keep in sync with rtwn_dma_init(). */ rtwn_config[RTWN_BULK_TX_VO].endpoint = addr[0]; switch (uc->ntx) { @@ -226,6 +230,8 @@ rtwn_usb_setup_endpoints(struct rtwn_usb_softc *uc) rtwn_config[RTWN_BULK_RX].bufsize = sc->rx_dma_size + 1024; error = usbd_transfer_setup(uc->uc_udev, &iface_index, uc->uc_xfer, rtwn_config, RTWN_N_TRANSFER, uc, &sc->sc_mtx); + free(rtwn_config, M_TEMP); + if (error) { device_printf(sc->sc_dev, "could not allocate USB transfers, " "err=%s\n", usbd_errstr(error)); diff --git a/freebsd/sys/dev/rtwn/usb/rtwn_usb_rx.c b/freebsd/sys/dev/rtwn/usb/rtwn_usb_rx.c index 8795e16d..4afa71af 100644 --- a/freebsd/sys/dev/rtwn/usb/rtwn_usb_rx.c +++ b/freebsd/sys/dev/rtwn/usb/rtwn_usb_rx.c @@ -238,7 +238,7 @@ rtwn_report_intr(struct rtwn_usb_softc *uc, struct usb_xfer *xfer, } static struct ieee80211_node * -rtwn_rx_frame(struct rtwn_softc *sc, struct mbuf *m, int8_t *rssi) +rtwn_rx_frame(struct rtwn_softc *sc, struct mbuf *m) { struct r92c_rx_stat stat; @@ -246,7 +246,7 @@ rtwn_rx_frame(struct rtwn_softc *sc, struct mbuf *m, int8_t *rssi) m_copydata(m, 0, sizeof(struct r92c_rx_stat), (caddr_t)&stat); m_adj(m, sizeof(struct r92c_rx_stat)); - return (rtwn_rx_common(sc, m, &stat, rssi)); + return (rtwn_rx_common(sc, m, &stat)); } void @@ -258,7 +258,6 @@ rtwn_bulk_rx_callback(struct usb_xfer *xfer, usb_error_t error) struct ieee80211_node *ni; struct mbuf *m = NULL, *next; struct rtwn_data *data; - int8_t nf, rssi; RTWN_ASSERT_LOCKED(sc); @@ -293,19 +292,15 @@ tr_setup: next = m->m_next; m->m_next = NULL; - ni = rtwn_rx_frame(sc, m, &rssi); + ni = rtwn_rx_frame(sc, m); RTWN_UNLOCK(sc); - nf = RTWN_NOISE_FLOOR; if (ni != NULL) { - if (ni->ni_flags & IEEE80211_NODE_HT) - m->m_flags |= M_AMPDU; - (void)ieee80211_input(ni, m, rssi - nf, nf); + (void)ieee80211_input_mimo(ni, m); ieee80211_free_node(ni); } else { - (void)ieee80211_input_all(ic, m, - rssi - nf, nf); + (void)ieee80211_input_mimo_all(ic, m); } RTWN_LOCK(sc); m = next; @@ -326,17 +321,6 @@ tr_setup: break; } finish: - /* Finished receive; age anything left on the FF queue by a little bump */ - /* - * XXX TODO: just make this a callout timer schedule so we can - * flush the FF staging queue if we're approaching idle. - */ -#ifdef IEEE80211_SUPPORT_SUPERG - if (!(sc->sc_flags & RTWN_FW_LOADED) || - sc->sc_ratectl != RTWN_RATECTL_NET80211) - rtwn_cmd_sleepable(sc, NULL, 0, rtwn_ff_flush_all); -#endif - /* Kick-start more transmit in case we stalled */ rtwn_start(sc); } |