diff --git a/sys/dev/rtwn/if_rtwn.c b/sys/dev/rtwn/if_rtwn.c index d4b45aa9eea7..33159b7d1b9c 100644 --- a/sys/dev/rtwn/if_rtwn.c +++ b/sys/dev/rtwn/if_rtwn.c @@ -1866,6 +1866,10 @@ rtwn_init(struct rtwn_softc *sc) rtwn_init_beacon_reg(sc); /* Init A-MPDU parameters. */ + /* + * XXX TODO: this needs to be updated after negotiating with the + * peer! (in STA mode ofc.) + */ rtwn_init_ampdu(sc); /* Init MACTXEN / MACRXEN after setting RxFF boundary. */ diff --git a/sys/dev/rtwn/rtl8188e/r88e.h b/sys/dev/rtwn/rtl8188e/r88e.h index 33c6fa3432f5..acdf2d28fd55 100644 --- a/sys/dev/rtwn/rtl8188e/r88e.h +++ b/sys/dev/rtwn/rtl8188e/r88e.h @@ -80,6 +80,7 @@ void r88e_parse_rom(struct rtwn_softc *, uint8_t *); /* r88e_rx.c */ int r88e_classify_intr(struct rtwn_softc *, void *, int); void r88e_ratectl_tx_complete(struct rtwn_softc *, uint8_t *, int); +void r88e_ratectl_tx_complete_periodic(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 *); diff --git a/sys/dev/rtwn/rtl8188e/r88e_fw_cmd.h b/sys/dev/rtwn/rtl8188e/r88e_fw_cmd.h index 2a43a07a31f3..aac4a9b06cfa 100644 --- a/sys/dev/rtwn/rtl8188e/r88e_fw_cmd.h +++ b/sys/dev/rtwn/rtl8188e/r88e_fw_cmd.h @@ -80,4 +80,17 @@ struct r88e_fw_cmd_pwrmode { #define R88E_PWRMODE_STATE_ALLON 0x0c } __packed; +/* + * The 8188E periodic TX report entries: + */ +struct r88e_fw_c2h_txreport2_entry { + uint16_t retry0; + uint8_t retry1; + uint8_t retry2; + uint8_t retry3; + uint8_t retry4; + uint8_t drop; + uint8_t reserved; +} __packed; + #endif /* R88E_FW_CMD_H */ diff --git a/sys/dev/rtwn/rtl8188e/r88e_rx.c b/sys/dev/rtwn/rtl8188e/r88e_rx.c index 287869885b86..163ed96bf320 100644 --- a/sys/dev/rtwn/rtl8188e/r88e_rx.c +++ b/sys/dev/rtwn/rtl8188e/r88e_rx.c @@ -52,6 +52,7 @@ #include #include #include +#include /* XXX */ int r88e_classify_intr(struct rtwn_softc *sc, void *buf, int len) @@ -73,6 +74,104 @@ r88e_classify_intr(struct rtwn_softc *sc, void *buf, int len) } } +void +r88e_ratectl_tx_complete_periodic(struct rtwn_softc *sc, uint8_t *buf, int len) +{ + const struct r92c_rx_stat *rxs; + uint64_t mac_bitmap; + int macid; + if (len < sizeof(struct r92c_rx_stat)) + return; + + rxs = (const struct r92c_rx_stat *) buf; + + /* Skip Rx descriptor. */ + buf += sizeof(struct r92c_rx_stat); + len -= sizeof(struct r92c_rx_stat); + + /* Note: Each entry is 8 bytes */ + /* + * Note: the valid macid bitmap is rx_desc[5] << 32 | rx_desc[4]; + * Note: rx_desc[5] is the TSF, which isn't valid for this report! + */ + mac_bitmap = ((uint64_t) le32toh(rxs->tsf_low) << 32) + | le32toh(rxs->rxdw4); + + RTWN_DPRINTF(sc, RTWN_DEBUG_INTR, + "%s: mac bitmap: %lx\n", __func__, mac_bitmap); + + /* + * uint16_t retry0 + * uint8_t retry1, retry2, retry3, retry4, retry5 + * uint8_t drop + */ + macid = 0; + while (len >= sizeof(struct r88e_fw_c2h_txreport2_entry)) { + struct ieee80211_ratectl_tx_stats txs = { 0 }; + const struct r88e_fw_c2h_txreport2_entry *rpt; + bool valid = false; + uint32_t ntotal, nsuccess, ndrop, nretry, nframes; + + if (macid < 64) + valid = mac_bitmap & (1 << macid); + + txs.flags = IEEE80211_RATECTL_TX_STATS_NODE | + IEEE80211_RATECTL_TX_STATS_RETRIES; + + rpt = (const struct r88e_fw_c2h_txreport2_entry *) buf; + + buf += sizeof(struct r88e_fw_c2h_txreport2_entry); + len -= sizeof(struct r88e_fw_c2h_txreport2_entry); + + /* calculate all the various combinations of things */ + ntotal = le16toh(rpt->retry0) + rpt->retry1 + rpt->retry2 + + rpt->retry3 + rpt->retry4 + rpt->drop; + /* + * note: sometimes this is zero or 1, but the retries + * are all capped out at 255! eep! + */ + nframes = le16toh(rpt->retry0); + nsuccess = ntotal - rpt->drop; + ndrop = rpt->drop; + nretry = rpt->retry1 + rpt->retry2 * 2 + + rpt->retry3 * 3 + rpt->retry4 * 4; + + txs.nretries = nretry + ndrop; + txs.nsuccess = nsuccess; + txs.nframes = ntotal; + (void) ndrop; + (void) ntotal; + (void) nretry; + (void) ntotal; + (void) nframes; + + RTWN_DPRINTF(sc, RTWN_DEBUG_INTR, + "%s: MAC %d valid %d rpt retries %d %d %d %d %d, drop %d\n", + __func__, + macid, + valid, + le16toh(rpt->retry0), + rpt->retry1, + rpt->retry2, + rpt->retry3, + rpt->retry4, + rpt->drop); + + if (valid && sc->node_list[macid] != NULL) { + struct ieee80211_node *ni; + ni = sc->node_list[macid]; + txs.ni = ni; + ieee80211_ratectl_tx_update(ni->ni_vap, &txs); + } else { + RTWN_DPRINTF(sc, RTWN_DEBUG_INTR, + "%s: no node found for macid %d\n", + __func__, + macid); + } + macid++; + } +} + void r88e_ratectl_tx_complete(struct rtwn_softc *sc, uint8_t *buf, int len) { diff --git a/sys/dev/rtwn/rtl8188e/usb/r88eu_attach.c b/sys/dev/rtwn/rtl8188e/usb/r88eu_attach.c index fcd26cd9a212..62af2059e34b 100644 --- a/sys/dev/rtwn/rtl8188e/usb/r88eu_attach.c +++ b/sys/dev/rtwn/rtl8188e/usb/r88eu_attach.c @@ -138,7 +138,7 @@ r88eu_attach(struct rtwn_usb_softc *uc) sc->sc_get_rssi_ofdm = r88e_get_rssi_ofdm; sc->sc_classify_intr = r88e_classify_intr; sc->sc_handle_tx_report = r88e_ratectl_tx_complete; - sc->sc_handle_tx_report2 = rtwn_nop_softc_uint8_int; + sc->sc_handle_tx_report2 = r88e_ratectl_tx_complete_periodic; sc->sc_handle_c2h_report = r88e_handle_c2h_report; sc->sc_check_frame = rtwn_nop_int_softc_mbuf; sc->sc_rf_read = r92c_rf_read; @@ -176,7 +176,7 @@ r88eu_attach(struct rtwn_usb_softc *uc) sc->sc_temp_read = r88e_temp_read; sc->sc_init_tx_agg = r92cu_init_tx_agg; sc->sc_init_rx_agg = r88eu_init_rx_agg; - sc->sc_init_ampdu = rtwn_nop_softc; + sc->sc_init_ampdu = r92c_init_ampdu; sc->sc_init_intr = r88eu_init_intr; sc->sc_init_edca = r92c_init_edca; sc->sc_init_bb = r88eu_init_bb; diff --git a/sys/dev/rtwn/rtl8188e/usb/r88eu_init.c b/sys/dev/rtwn/rtl8188e/usb/r88eu_init.c index f4f936493cda..fef910a5c23f 100644 --- a/sys/dev/rtwn/rtl8188e/usb/r88eu_init.c +++ b/sys/dev/rtwn/rtl8188e/usb/r88eu_init.c @@ -279,8 +279,15 @@ void r88eu_post_init(struct rtwn_softc *sc) { - /* Enable per-packet TX report. */ - rtwn_setbits_1(sc, R88E_TX_RPT_CTRL, 0, R88E_TX_RPT1_ENA); + /* Enable per-packet TX report (RPT1) and timer report (RPT2). */ + rtwn_setbits_1(sc, R88E_TX_RPT_CTRL, 0, + R88E_TX_RPT1_ENA | R88E_TX_RPT2_ENA); + + /* Set Max RPT MACID */ + rtwn_write_1(sc, R88E_TX_RPT_MACID_MAX, 0x02); + + /* Enable periodic TX report; 32uS units */ + rtwn_write_2(sc, R88E_TX_RPT_TIME, 0xcdf0); /* Disable Tx if MACID is not associated. */ rtwn_write_4(sc, R88E_MACID_NO_LINK, 0xffffffff); diff --git a/sys/dev/rtwn/rtl8192c/r92c_init.c b/sys/dev/rtwn/rtl8192c/r92c_init.c index 8697c526ec06..497d70979a08 100644 --- a/sys/dev/rtwn/rtl8192c/r92c_init.c +++ b/sys/dev/rtwn/rtl8192c/r92c_init.c @@ -300,11 +300,39 @@ r92c_init_edca(struct rtwn_softc *sc) void r92c_init_ampdu(struct rtwn_softc *sc) { + uint8_t vals[4] = { 0x41, 0xa8, 0x72, 0xb9 }; + int i, ampdu_factor; + uint8_t reg; + + ampdu_factor = 1; /* 16k */ + + ampdu_factor = 1 << (ampdu_factor + 2); + if (ampdu_factor > 0x0f) + ampdu_factor = 0x0f; + + for (i = 0; i < 4; i++) { + if ((vals[i] & 0xf0) > (ampdu_factor << 4)) + vals[i] = (vals[i] & 0x0f) | (ampdu_factor << 4); + + if ((vals[i] & 0x0f) > ampdu_factor) + vals[i] = (vals[i] & 0xf0) | ampdu_factor; + + rtwn_write_1(sc, R92C_AGGLEN_LMT + i, vals[i]); + } /* Setup AMPDU aggregation. */ - rtwn_write_4(sc, R92C_AGGLEN_LMT, 0x99997631); /* MCS7~0 */ +// rtwn_write_4(sc, R92C_AGGLEN_LMT, 0x99997631); /* MCS7~0 */ + /* note: ref driver doesn't set this? */ rtwn_write_1(sc, R92C_AGGR_BREAK_TIME, 0x16); - rtwn_write_2(sc, R92C_MAX_AGGR_NUM, 0x0708); + /* ref driver has max aggr as 0x0b0b for PCI, and 0x0707 for USB */ + rtwn_write_2(sc, R92C_MAX_AGGR_NUM, 0x0707); + + /* Denisity parameter - set to 7 for now (16 uS) */ + + reg = rtwn_read_1(sc, R92C_AMPDU_MIN_SPACE); + reg &= 0xf8; + reg |= 7; + rtwn_write_1(sc, R92C_AMPDU_MIN_SPACE, reg); } void diff --git a/sys/dev/rtwn/rtl8192c/r92c_tx.c b/sys/dev/rtwn/rtl8192c/r92c_tx.c index 9583a7e1119e..ac606f1fa329 100644 --- a/sys/dev/rtwn/rtl8192c/r92c_tx.c +++ b/sys/dev/rtwn/rtl8192c/r92c_tx.c @@ -302,7 +302,7 @@ r92c_fill_tx_desc(struct rtwn_softc *sc, struct ieee80211_node *ni, r92c_calculate_tx_agg_window(sc, ni, tid))); } if (sc->sc_ratectl == RTWN_RATECTL_NET80211) { - txd->txdw2 |= htole32(R92C_TXDW2_CCX_RPT); +// txd->txdw2 |= htole32(R92C_TXDW2_CCX_RPT); sc->sc_tx_n_active++; #ifndef RTWN_WITHOUT_UCODE rs->rs_c2h_pending++;