rtwn: enable periodic TX reporting support on RTL8188EU NICs.
The RTL8188E firmware doesn't have the "full" offload firmware rate control. Instead, the vendor driver has a bunch of logic in the driver for rate probing and selection. Part of this is the periodic TX report - which uploads a summary of multi-rate retries and drops per MAC. Using it drastically cuts down on the TX notifications - it's fired from a timer (defaulting to ~ 1.6 seconds) and is a single receive frame in the normal bulk RX path. I've not ported / reimplemented the whole vendor driver rate adaption code - instead, I'm just using the normal net80211 rate control APIs. It seems to behave OK - I get 25-30mbit down and 20mbit up using TCP/ speedtest. Locally tested: * RTL8188EU, STA mode Differential Revision: https://reviews.freebsd.org/D48088 Reviewed by: fuz, bz Obtained from: https://github.com/lwfinger/rtl8188eu/blob/master/hal/Hal8188ERateAdaptive.c
This commit is contained in:
@@ -401,6 +401,7 @@ struct rtwn_softc {
|
||||
uint16_t rx_dma_size;
|
||||
|
||||
int macid_limit;
|
||||
int macid_rpt2_max_num;
|
||||
int cam_entry_limit;
|
||||
int fwsize_limit;
|
||||
int temp_delta;
|
||||
|
||||
@@ -86,6 +86,7 @@ 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 *);
|
||||
void r88e_ratectl_tx_complete_periodic(struct rtwn_softc *, uint8_t *, int);
|
||||
|
||||
/* r88e_tx.c */
|
||||
void r88e_tx_enable_ampdu(void *, int);
|
||||
|
||||
@@ -232,3 +232,89 @@ r88e_get_rx_stats(struct rtwn_softc *sc, struct ieee80211_rx_stats *rxs,
|
||||
rxs->c_band = IEEE80211_CHAN_2GHZ;
|
||||
}
|
||||
}
|
||||
|
||||
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: 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_RA,
|
||||
"%s: mac bitmap: 0x%lx\n", __func__, mac_bitmap);
|
||||
|
||||
/*
|
||||
* Note: the RX reports aren't sparse - invalid entries (ie,
|
||||
* the bitmap has the macid set to 0) are just populated
|
||||
* with random data.
|
||||
*/
|
||||
for (macid = 0; (macid < 64) && (macid < sc->macid_rpt2_max_num) &&
|
||||
(len >= sizeof(struct r88e_fw_c2h_txreport2_entry)); macid++) {
|
||||
struct ieee80211_ratectl_tx_stats txs = { 0 };
|
||||
const struct r88e_fw_c2h_txreport2_entry *rpt;
|
||||
uint32_t ntotal, nsuccess, ndrop, nretry, nframes;
|
||||
|
||||
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);
|
||||
|
||||
if ((mac_bitmap & (1UL << macid)) == 0)
|
||||
continue;
|
||||
|
||||
txs.flags = IEEE80211_RATECTL_TX_STATS_NODE |
|
||||
IEEE80211_RATECTL_TX_STATS_RETRIES;
|
||||
|
||||
/* calculate all the various combinations of things */
|
||||
nframes = le16toh(rpt->retry0);
|
||||
ntotal = nframes + 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! That means the frame
|
||||
* transmits are all failing.
|
||||
*/
|
||||
nsuccess = ntotal - rpt->drop;
|
||||
ndrop = rpt->drop;
|
||||
nretry = rpt->retry1 + rpt->retry2 + rpt->retry3
|
||||
+ rpt->retry4;
|
||||
|
||||
txs.nretries = nretry + ndrop;
|
||||
txs.nsuccess = nsuccess;
|
||||
txs.nframes = ntotal;
|
||||
|
||||
RTWN_DPRINTF(sc, RTWN_DEBUG_RA,
|
||||
"%s: MAC %d rpt retries %d %d %d %d %d, "
|
||||
"drop %d\n",
|
||||
__func__,
|
||||
macid,
|
||||
le16toh(rpt->retry0),
|
||||
rpt->retry1,
|
||||
rpt->retry2,
|
||||
rpt->retry3,
|
||||
rpt->retry4,
|
||||
rpt->drop);
|
||||
if (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);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -81,6 +81,20 @@ struct r88e_tx_rpt_ccx {
|
||||
uint8_t rptb7;
|
||||
} __packed;
|
||||
|
||||
/*
|
||||
* The 8188E periodic TX report entries
|
||||
* (type 2 report.)
|
||||
*/
|
||||
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;
|
||||
|
||||
/* Interrupt message format. */
|
||||
/* XXX recheck */
|
||||
struct r88e_intr_msg {
|
||||
|
||||
@@ -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;
|
||||
@@ -212,6 +212,8 @@ r88eu_attach(struct rtwn_usb_softc *uc)
|
||||
sc->rx_dma_size = R88E_RX_DMA_BUFFER_SIZE;
|
||||
|
||||
sc->macid_limit = R88E_MACID_MAX + 1;
|
||||
/* XXX this limit may be expanded to R88E_MACID_MAX */
|
||||
sc->macid_rpt2_max_num = 2;
|
||||
sc->cam_entry_limit = R92C_CAM_ENTRY_COUNT;
|
||||
sc->fwsize_limit = R92C_MAX_FW_SIZE;
|
||||
sc->temp_delta = R88E_CALIB_THRESHOLD;
|
||||
|
||||
@@ -279,9 +279,22 @@ void
|
||||
r88eu_post_init(struct rtwn_softc *sc)
|
||||
{
|
||||
|
||||
/* Enable per-packet TX report. */
|
||||
/* Enable per-packet TX report (RPT1) */
|
||||
rtwn_setbits_1(sc, R88E_TX_RPT_CTRL, 0, R88E_TX_RPT1_ENA);
|
||||
|
||||
#ifndef RTWN_WITHOUT_UCODE
|
||||
/* Enable timer report (RPT2) if requested */
|
||||
if (sc->macid_rpt2_max_num > 0) {
|
||||
rtwn_setbits_1(sc, R88E_TX_RPT_CTRL, 0,
|
||||
R88E_TX_RPT2_ENA);
|
||||
|
||||
/* Configure how many TX RPT2 entries to populate */
|
||||
rtwn_write_1(sc, R88E_TX_RPT_MACID_MAX,
|
||||
sc->macid_rpt2_max_num);
|
||||
/* Enable periodic TX report; 32uS units */
|
||||
rtwn_write_2(sc, R88E_TX_RPT_TIME, 0xcdf0);
|
||||
}
|
||||
#endif
|
||||
/* Disable Tx if MACID is not associated. */
|
||||
rtwn_write_4(sc, R88E_MACID_NO_LINK, 0xffffffff);
|
||||
rtwn_write_4(sc, R88E_MACID_NO_LINK + 4, 0xffffffff);
|
||||
|
||||
@@ -236,6 +236,27 @@ r92c_calculate_tx_agg_window(struct rtwn_softc *sc,
|
||||
return (wnd);
|
||||
}
|
||||
|
||||
/*
|
||||
* Check whether to enable the per-packet TX CCX report.
|
||||
*
|
||||
* For chipsets that do the RPT2 reports, enabling the TX
|
||||
* CCX report results in the packet not being counted in
|
||||
* the RPT2 counts.
|
||||
*/
|
||||
static bool
|
||||
r92c_check_enable_ccx_report(struct rtwn_softc *sc, int macid)
|
||||
{
|
||||
if (sc->sc_ratectl != RTWN_RATECTL_NET80211)
|
||||
return false;
|
||||
|
||||
#ifndef RTWN_WITHOUT_UCODE
|
||||
if ((sc->macid_rpt2_max_num != 0) &&
|
||||
(macid < sc->macid_rpt2_max_num))
|
||||
return false;
|
||||
#endif
|
||||
return true;
|
||||
}
|
||||
|
||||
void
|
||||
r92c_fill_tx_desc(struct rtwn_softc *sc, struct ieee80211_node *ni,
|
||||
struct mbuf *m, void *buf, uint8_t ridx, int maxretry)
|
||||
@@ -298,7 +319,7 @@ r92c_fill_tx_desc(struct rtwn_softc *sc, struct ieee80211_node *ni,
|
||||
txd->txdw6 |= htole32(SM(R92C_TXDW6_MAX_AGG,
|
||||
r92c_calculate_tx_agg_window(sc, ni, tid)));
|
||||
}
|
||||
if (sc->sc_ratectl == RTWN_RATECTL_NET80211) {
|
||||
if (r92c_check_enable_ccx_report(sc, macid)) {
|
||||
txd->txdw2 |= htole32(R92C_TXDW2_CCX_RPT);
|
||||
sc->sc_tx_n_active++;
|
||||
#ifndef RTWN_WITHOUT_UCODE
|
||||
|
||||
Reference in New Issue
Block a user