diff --git a/sys/dev/rtwn/if_rtwn.c b/sys/dev/rtwn/if_rtwn.c index be01ececf307..55c45a5331e0 100644 --- a/sys/dev/rtwn/if_rtwn.c +++ b/sys/dev/rtwn/if_rtwn.c @@ -351,7 +351,8 @@ rtwn_sysctlattach(struct rtwn_softc *sc) if (sc->sc_hwcrypto >= RTWN_CRYPTO_MAX) sc->sc_hwcrypto = RTWN_CRYPTO_FULL; - sc->sc_ratectl_sysctl = RTWN_RATECTL_NET80211; +// sc->sc_ratectl_sysctl = RTWN_RATECTL_NET80211; + sc->sc_ratectl_sysctl = RTWN_RATECTL_FW; SYSCTL_ADD_INT(ctx, SYSCTL_CHILDREN(tree), OID_AUTO, "ratectl", CTLFLAG_RDTUN, &sc->sc_ratectl_sysctl, sc->sc_ratectl_sysctl, "Select rate control mechanism: " @@ -1476,6 +1477,7 @@ rtwn_mac_init(struct rtwn_softc *sc) static void rtwn_mrr_init(struct rtwn_softc *sc) { +#if 0 int i; /* Drop rate index by 1 per retry. */ @@ -1483,6 +1485,16 @@ rtwn_mrr_init(struct rtwn_softc *sc) rtwn_write_1(sc, R92C_DARFRC + i, i + 1); rtwn_write_1(sc, R92C_RARFRC + i, i + 1); } +#else +// rtwn_write_4(sc, R92C_DARFRC, 0x0); +// rtwn_write_4(sc, R92C_DARFRC + 4, 0x10080404); +// rtwn_write_4(sc, R92C_RARFRC, 0x04030201); +// rtwn_write_4(sc, R92C_RARFRC + 4, 0x08070605); + rtwn_write_4(sc, R92C_DARFRC, 0x01020304); + rtwn_write_4(sc, R92C_DARFRC + 4, 0x05060708); + rtwn_write_4(sc, R92C_RARFRC, 0x01020304); + rtwn_write_4(sc, R92C_RARFRC + 4, 0x05060708); +#endif } static void @@ -1724,6 +1736,7 @@ rtwn_node_alloc(struct ieee80211vap *vap, un->id = RTWN_MACID_UNDEFINED; un->avg_pwdb = -1; + un->current_ra_level = RTWN_RA_LEVEL_OFF; return &un->ni; } diff --git a/sys/dev/rtwn/if_rtwn_fw.c b/sys/dev/rtwn/if_rtwn_fw.c index 551adbdb8704..0fc5bac75c82 100644 --- a/sys/dev/rtwn/if_rtwn_fw.c +++ b/sys/dev/rtwn/if_rtwn_fw.c @@ -141,7 +141,8 @@ rtwn_load_firmware(struct rtwn_softc *sc) sc->fwver = le16toh(hdr->version); RTWN_DPRINTF(sc, RTWN_DEBUG_FIRMWARE, - "FW V%u.%u %02u-%02u %02u:%02u\n", + "FW (%s) V%u.%u %02u-%02u %02u:%02u\n", + sc->fwname, le16toh(hdr->version), le16toh(hdr->subversion), hdr->month, hdr->date, hdr->hour, hdr->minute); ptr += sizeof(*hdr); diff --git a/sys/dev/rtwn/if_rtwn_rx.c b/sys/dev/rtwn/if_rtwn_rx.c index 977c1d17a08a..fabc169499dc 100644 --- a/sys/dev/rtwn/if_rtwn_rx.c +++ b/sys/dev/rtwn/if_rtwn_rx.c @@ -124,6 +124,10 @@ rtwn_set_basicrates(struct rtwn_softc *sc, uint32_t rates) RTWN_DPRINTF(sc, RTWN_DEBUG_RA, "%s: rates 0x%08X\n", __func__, rates); rtwn_setbits_4(sc, R92C_RRSR, R92C_RRSR_RATE_BITMAP_M, rates); + + /* TODO: R92C_INIRTS_RATE_SEL */ + /* XXX TODO: default to OFDM6? */ + rtwn_write_1(sc, R92C_INIRTS_RATE_SEL, RTWN_RIDX_OFDM6); } static void diff --git a/sys/dev/rtwn/if_rtwn_tx.c b/sys/dev/rtwn/if_rtwn_tx.c index bf45d14f7edc..4336bf64dbff 100644 --- a/sys/dev/rtwn/if_rtwn_tx.c +++ b/sys/dev/rtwn/if_rtwn_tx.c @@ -119,6 +119,7 @@ rtwn_tx_data(struct rtwn_softc *sc, struct ieee80211_node *ni, uint8_t rate, ridx, type; u_int cipher; int ismcast; + bool force_rate = false; RTWN_ASSERT_LOCKED(sc); @@ -129,13 +130,17 @@ rtwn_tx_data(struct rtwn_softc *sc, struct ieee80211_node *ni, /* Choose a TX rate index. */ if (type == IEEE80211_FC0_TYPE_MGT || type == IEEE80211_FC0_TYPE_CTL || - (m->m_flags & M_EAPOL) != 0) + (m->m_flags & M_EAPOL) != 0) { rate = tp->mgmtrate; - else if (ismcast) + force_rate = true; + } else if (ismcast) { rate = tp->mcastrate; - else if (tp->ucastrate != IEEE80211_FIXED_RATE_NONE) + force_rate = true; + } else if (tp->ucastrate != IEEE80211_FIXED_RATE_NONE) { + /* XXX TODO: fixed rate control should override FW rate control somehow */ rate = tp->ucastrate; - else { + force_rate = true; + } else { if (sc->sc_ratectl == RTWN_RATECTL_NET80211) { /* XXX pass pktlen */ (void) ieee80211_ratectl_rate(ni, NULL, 0); @@ -172,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, tp->maxretry); + rtwn_fill_tx_desc(sc, ni, m, txd, ridx, force_rate, tp->maxretry); if (ieee80211_radiotap_active_vap(vap)) { struct rtwn_tx_radiotap_header *tap = &sc->sc_txtap; diff --git a/sys/dev/rtwn/if_rtwnvar.h b/sys/dev/rtwn/if_rtwnvar.h index 3f14c05eb79d..98b892a9a6d4 100644 --- a/sys/dev/rtwn/if_rtwnvar.h +++ b/sys/dev/rtwn/if_rtwnvar.h @@ -95,12 +95,22 @@ struct rtwn_cmdq { }; #define RTWN_CMDQ_SIZE 16 +enum rtwn_ra_level { + RTWN_RA_LEVEL_OFF = 0, + RTWN_RA_LEVEL_LOW = 1, + RTWN_RA_LEVEL_MED = 2, + RTWN_RA_LEVEL_HI = 3, +}; + struct rtwn_node { struct ieee80211_node ni; /* must be the first */ int id; struct rtwn_tx_phystat last_physt; int avg_pwdb; + enum rtwn_ra_level current_ra_level; + uint32_t rate_mask; + uint32_t ht_rate_mask; }; #define RTWN_NODE(ni) ((struct rtwn_node *)(ni)) @@ -318,7 +328,7 @@ struct rtwn_softc { void (*sc_detach_private)(struct rtwn_softc *); void (*sc_fill_tx_desc)(struct rtwn_softc *, struct ieee80211_node *, struct mbuf *, - void *, uint8_t, int); + void *, uint8_t, bool, int); void (*sc_fill_tx_desc_raw)(struct rtwn_softc *, struct ieee80211_node *, struct mbuf *, void *, const struct ieee80211_bpf_params *); @@ -523,9 +533,9 @@ void rtwn_suspend(struct rtwn_softc *); #define rtwn_detach_private(_sc) \ (((_sc)->sc_detach_private)((_sc))) #define rtwn_fill_tx_desc(_sc, _ni, _m, \ - _buf, _ridx, _maxretry) \ + _buf, _ridx, _force_rate, _maxretry) \ (((_sc)->sc_fill_tx_desc)((_sc), (_ni), \ - (_m), (_buf), (_ridx), (_maxretry))) + (_m), (_buf), (_ridx), (_force_rate), (_maxretry))) #define rtwn_fill_tx_desc_raw(_sc, _ni, _m, \ _buf, _params) \ (((_sc)->sc_fill_tx_desc_raw)((_sc), (_ni), \ diff --git a/sys/dev/rtwn/rtl8192c/r92c.h b/sys/dev/rtwn/rtl8192c/r92c.h index c602f314825a..425647d0b6d0 100644 --- a/sys/dev/rtwn/rtl8192c/r92c.h +++ b/sys/dev/rtwn/rtl8192c/r92c.h @@ -116,7 +116,7 @@ void r92c_tx_enable_ampdu(void *, int); void r92c_tx_setup_hwseq(void *); void r92c_tx_setup_macid(void *, int); void r92c_fill_tx_desc(struct rtwn_softc *, struct ieee80211_node *, - struct mbuf *, void *, uint8_t, int); + struct mbuf *, void *, uint8_t, bool, int); void r92c_fill_tx_desc_raw(struct rtwn_softc *, struct ieee80211_node *, struct mbuf *, void *, const struct ieee80211_bpf_params *); void r92c_fill_tx_desc_null(struct rtwn_softc *, void *, int, int, int); diff --git a/sys/dev/rtwn/rtl8192c/r92c_chan.c b/sys/dev/rtwn/rtl8192c/r92c_chan.c index f93159a3c94e..eb6e1ac82b7a 100644 --- a/sys/dev/rtwn/rtl8192c/r92c_chan.c +++ b/sys/dev/rtwn/rtl8192c/r92c_chan.c @@ -316,7 +316,11 @@ r92c_set_bw40(struct rtwn_softc *sc, uint8_t chan, int prichlo) struct r92c_softc *rs = sc->sc_priv; rtwn_setbits_1(sc, R92C_BWOPMODE, R92C_BWOPMODE_20MHZ, 0); - rtwn_setbits_1(sc, R92C_RRSR + 2, 0x6f, (prichlo ? 1 : 2) << 5); + + /* This is specifically for the RTL8192C; different for the RTL8188E */ + /* TODO: triple / quadruple check this */ + rtwn_setbits_4(sc, R92C_RRSR, R92C_RRSR_RSC_SUBCHNL_MASK, + (prichlo ? R92C_RRSR_RSC_UPSUBCHNL : R92C_RRSR_RSC_LOWSUBCHNL)); rtwn_bb_setbits(sc, R92C_FPGA0_RFMOD, 0, R92C_RFMOD_40MHZ); rtwn_bb_setbits(sc, R92C_FPGA1_RFMOD, 0, R92C_RFMOD_40MHZ); diff --git a/sys/dev/rtwn/rtl8192c/r92c_fw.c b/sys/dev/rtwn/rtl8192c/r92c_fw.c index 5ab15cc0aa39..2e032a5ece8d 100644 --- a/sys/dev/rtwn/rtl8192c/r92c_fw.c +++ b/sys/dev/rtwn/rtl8192c/r92c_fw.c @@ -177,8 +177,15 @@ r92c_send_ra_cmd(struct rtwn_softc *sc, int macid, uint32_t rates, mode = R92C_RAID_11BG; else mode = R92C_RAID_11B; + + /* TODO: short-GI negotiation for this node / bandwidth */ cmd.macid = macid | R92C_CMD_MACID_VALID; - cmd.mask = htole32(mode << 28 | rates); + cmd.mask = (mode << 28) | (rates & 0x0fffffff); + + device_printf(sc->sc_dev, + "%s: macid=0x%02x, mask=0x%08x\n", + __func__, cmd.macid, cmd.mask); + error = r92c_fw_cmd(sc, R92C_CMD_MACID_CONFIG, &cmd, sizeof(cmd)); if (error != 0) { device_printf(sc->sc_dev, @@ -191,11 +198,61 @@ r92c_send_ra_cmd(struct rtwn_softc *sc, int macid, uint32_t rates, } #endif +static void +r92c_filter_rate_mask(struct rtwn_softc *sc, struct ieee80211_node *ni, + uint32_t *rates, uint32_t *htrates) +{ + struct rtwn_node *un = RTWN_NODE(ni); + + switch (un->current_ra_level) { + case RTWN_RA_LEVEL_OFF: + break; + case RTWN_RA_LEVEL_LOW: + /* Filter out everything except low rates */ + *rates &= (RTWN_RIDX_CCK1 | RTWN_RIDX_CCK2 | + RTWN_RIDX_OFDM6 | RTWN_RIDX_OFDM9 | RTWN_RIDX_OFDM12); + /* Allow MCS0-2, MCS8-10 */ + *htrates &= 0x0707; + break; + case RTWN_RA_LEVEL_MED: + /* Filter out high rates */ + *rates &= ~(RTWN_RIDX_CCK11 | + RTWN_RIDX_OFDM48 | RTWN_RIDX_OFDM54); + /* Allow MCS0-5, MCS8-13 */ + *htrates &= 0x1f1f; + break; + case RTWN_RA_LEVEL_HI: + /* Allow everything (filter out low rates to save time) */ + *rates &= ~(RTWN_RIDX_CCK1 | RTWN_RIDX_OFDM6); + /* Allow MCS4-7, 12-15 */ + *htrates &= 0xf0f0; + break; + } +} + +static uint8_t +r92c_recalculate_maxrate(struct rtwn_softc *sc, struct ieee80211_node *ni, + uint32_t rates, uint32_t ht_rates) +{ + int i; + uint8_t rate = 0; + uint32_t fw_rates; + + fw_rates = rates | ((ht_rates & 0xffff) << RTWN_RIDX_HT_MCS_SHIFT); + + for (i = 0; i < 32; i++) { + if ((1 << i) & fw_rates) + rate = i; + } + return rate; +} + static void r92c_init_ra(struct rtwn_softc *sc, int macid) { struct ieee80211_htrateset *rs_ht; struct ieee80211_node *ni; + struct rtwn_node *un; uint32_t rates, htrates; int maxrate; @@ -208,6 +265,7 @@ r92c_init_ra(struct rtwn_softc *sc, int macid) } ni = ieee80211_ref_node(sc->node_list[macid]); + un = RTWN_NODE(ni); if (ni->ni_flags & IEEE80211_NODE_HT) rs_ht = &ni->ni_htrates; else @@ -217,19 +275,33 @@ r92c_init_ra(struct rtwn_softc *sc, int macid) * firmware; and for this chipset 2-stream 11n support is enough. */ rtwn_get_rates(sc, &ni->ni_rates, rs_ht, &rates, &htrates, &maxrate, 0); + un->rate_mask = rates; + un->ht_rate_mask = htrates; RTWN_NT_UNLOCK(sc); + device_printf(sc->sc_dev, + "%s: rates=0x%08x, htrates=0x%08x, maxrate=%d\n", + __func__, rates, htrates, maxrate); + #ifndef RTWN_WITHOUT_UCODE if (sc->sc_ratectl == RTWN_RATECTL_FW) { uint32_t fw_rates; /* Add HT rates after normal rates; limit to MCS0..15 */ + r92c_filter_rate_mask(sc, ni, &rates, &htrates); + /* Re-calculate maxrate */ + maxrate = r92c_recalculate_maxrate(sc, ni, rates, htrates); fw_rates = rates | - ((htrates & 0xffff) < RTWN_RIDX_HT_MCS_SHIFT); + ((htrates & 0xffff) << RTWN_RIDX_HT_MCS_SHIFT); r92c_send_ra_cmd(sc, macid, fw_rates, maxrate); } #endif - rtwn_write_1(sc, R92C_INIDATA_RATE_SEL(macid), maxrate); + /* + * Note: vendor driver bit 6 set is "use short gi" + */ +// if (sc->sc_ratectl != RTWN_RATECTL_FW) + //rtwn_write_1(sc, R92C_INIDATA_RATE_SEL(macid), RTWN_RIDX_HT_MCS(5)); + //rtwn_write_1(sc, R92C_INIDATA_RATE_SEL(macid), 0); ieee80211_free_node(ni); } @@ -310,6 +382,49 @@ r92c_set_pwrmode(struct rtwn_softc *sc, struct ieee80211vap *vap, return (error); } +static enum rtwn_ra_level +r92c_calculate_new_ra_level(struct rtwn_softc *sc, struct ieee80211_node *ni) +{ + struct rtwn_node *rn = RTWN_NODE(ni); + + /* + * Switch based on current RA level too, so we can apply + * some hysteresis. + */ + switch (rn->current_ra_level) { + case RTWN_RA_LEVEL_OFF: + if (rn->avg_pwdb > 75) + return RTWN_RA_LEVEL_HI; + if (rn->avg_pwdb > 40) + return RTWN_RA_LEVEL_MED; + return RTWN_RA_LEVEL_LOW; + break; + case RTWN_RA_LEVEL_LOW: + if (rn->avg_pwdb > 70) + return RTWN_RA_LEVEL_HI; + else if (rn->avg_pwdb > 40) + return RTWN_RA_LEVEL_MED; + return RTWN_RA_LEVEL_LOW; + break; + case RTWN_RA_LEVEL_MED: + if (rn->avg_pwdb > 80) + return RTWN_RA_LEVEL_HI; + else if (rn->avg_pwdb > 50) + return RTWN_RA_LEVEL_MED; + return RTWN_RA_LEVEL_LOW; + break; + case RTWN_RA_LEVEL_HI: + if (rn->avg_pwdb > 70) + return RTWN_RA_LEVEL_HI; + if (rn->avg_pwdb > 50) + return RTWN_RA_LEVEL_MED; + return RTWN_RA_LEVEL_LOW; + break; + } + + return RTWN_RA_LEVEL_OFF; +} + void r92c_set_rssi(struct rtwn_softc *sc) { @@ -322,6 +437,7 @@ r92c_set_rssi(struct rtwn_softc *sc) RTWN_NT_LOCK(sc); for (i = 0; i < sc->macid_limit; i++) { + enum rtwn_ra_level new_ra_level; /* XXX optimize? */ ni = sc->node_list[i]; if (ni == NULL) @@ -330,12 +446,45 @@ r92c_set_rssi(struct rtwn_softc *sc) rn = RTWN_NODE(ni); cmd.macid = i; cmd.pwdb = rn->avg_pwdb; - RTWN_DPRINTF(sc, RTWN_DEBUG_RSSI, + + new_ra_level = r92c_calculate_new_ra_level(sc, ni); + + RTWN_DPRINTF(sc, RTWN_DEBUG_RSSI | RTWN_DEBUG_CALIB, "%s: sending RSSI command (macid %d, rssi %d)\n", __func__, i, rn->avg_pwdb); RTWN_NT_UNLOCK(sc); + /* + * Send RSSI command + */ r92c_fw_cmd(sc, R92C_CMD_RSSI_SETTING, &cmd, sizeof(cmd)); + + /* + * If the RA level has changed, send a new maskset. + */ + if (new_ra_level != rn->current_ra_level) { + uint32_t rates, htrates, fw_rates; + uint8_t maxrate, macid; + + macid = i; + + RTWN_DPRINTF(sc, RTWN_DEBUG_CALIB, + "%s: changing RA level from %d to %d\n", + __func__, + rn->current_ra_level, + new_ra_level); + rn->current_ra_level = new_ra_level; + + rates = rn->rate_mask; + htrates = rn->ht_rate_mask; + /* Add HT rates after normal rates; limit to MCS0..15 */ + r92c_filter_rate_mask(sc, ni, &rates, &htrates); + /* Re-calculate maxrate */ + maxrate = r92c_recalculate_maxrate(sc, ni, rates, htrates); + fw_rates = rates | + ((htrates & 0xffff) << RTWN_RIDX_HT_MCS_SHIFT); + r92c_send_ra_cmd(sc, macid, fw_rates, maxrate); + } RTWN_NT_LOCK(sc); } RTWN_NT_UNLOCK(sc); @@ -350,12 +499,14 @@ r92c_ratectl_tx_complete(struct rtwn_softc *sc, uint8_t *buf, int len) uint8_t macid; int ntries; +#if 0 if (sc->sc_ratectl != RTWN_RATECTL_NET80211) { /* shouldn't happen */ device_printf(sc->sc_dev, "%s called while ratectl = %d!\n", __func__, sc->sc_ratectl); return; } +#endif rpt = (struct r92c_c2h_tx_rpt *)buf; if (len != sizeof(*rpt)) { @@ -371,6 +522,12 @@ r92c_ratectl_tx_complete(struct rtwn_softc *sc, uint8_t *buf, int len) __func__, rpt->rptb0, rpt->rptb1, rpt->queue_time_low, rpt->queue_time_high, rpt->rptb4, rpt->rptb5, rpt->rptb6, rpt->rptb7); + RTWN_DPRINTF(sc, RTWN_DEBUG_INTR, + "%s: ok=%d life_expire=%d retry_over=%d\n", + __func__, + !! (rpt->rptb7 & R92C_RPTB7_PKT_OK), + !! (rpt->rptb6 & R92C_RPTB6_LIFE_EXPIRE), + !! (rpt->rptb6 & R92C_RPTB6_RETRY_OVER)); macid = MS(rpt->rptb5, R92C_RPTB5_MACID); if (macid > sc->macid_limit) { @@ -400,7 +557,8 @@ r92c_ratectl_tx_complete(struct rtwn_softc *sc, uint8_t *buf, int len) txs.status = IEEE80211_RATECTL_TX_FAIL_EXPIRED; else txs.status = IEEE80211_RATECTL_TX_FAIL_UNSPECIFIED; - ieee80211_ratectl_tx_complete(ni, &txs); + if (sc->sc_ratectl == RTWN_RATECTL_NET80211) + ieee80211_ratectl_tx_complete(ni, &txs); } else { RTWN_DPRINTF(sc, RTWN_DEBUG_INTR, "%s: macid %u, ni is NULL\n", __func__, macid); diff --git a/sys/dev/rtwn/rtl8192c/r92c_fw_cmd.h b/sys/dev/rtwn/rtl8192c/r92c_fw_cmd.h index b16e2819624f..e19c091fa54d 100644 --- a/sys/dev/rtwn/rtl8192c/r92c_fw_cmd.h +++ b/sys/dev/rtwn/rtl8192c/r92c_fw_cmd.h @@ -80,6 +80,7 @@ struct r92c_fw_cmd_macid_cfg { uint32_t mask; uint8_t macid; #define R92C_CMD_MACID_VALID 0x80 +#define R92C_CMD_MACID_SGI 0x20 } __packed; /* diff --git a/sys/dev/rtwn/rtl8192c/r92c_tx.c b/sys/dev/rtwn/rtl8192c/r92c_tx.c index 9583a7e1119e..01904cd4a940 100644 --- a/sys/dev/rtwn/rtl8192c/r92c_tx.c +++ b/sys/dev/rtwn/rtl8192c/r92c_tx.c @@ -61,11 +61,18 @@ r92c_tx_get_sco(struct rtwn_softc *sc, struct ieee80211_channel *c) return (R92C_TXDW4_SCO_SCB); } +/* + * TODO: this is only applicable for 8188EU (no rate control), or + * non-rate control config? + */ static void r92c_tx_set_ht40(struct rtwn_softc *sc, void *buf, struct ieee80211_node *ni) { struct r92c_tx_desc *txd = (struct r92c_tx_desc *)buf; + if (sc->sc_ratectl == RTWN_RATECTL_FW) + return; + if (ieee80211_ht_check_tx_ht40(ni)) { int extc_offset; @@ -77,17 +84,34 @@ r92c_tx_set_ht40(struct rtwn_softc *sc, void *buf, struct ieee80211_node *ni) static void r92c_tx_protection(struct rtwn_softc *sc, struct r92c_tx_desc *txd, - enum ieee80211_protmode mode, uint8_t ridx) + enum ieee80211_protmode mode, uint8_t ridx, bool force_ht) { +#if 0 struct ieee80211com *ic = &sc->sc_ic; uint8_t rate; +#endif + +#if 0 + device_printf(sc->sc_dev, + "%s: called; mode=%d, ridx=%d force_ht=%d\n", + __func__, + mode, ridx, force_ht); +#endif + + /* + * Note: for firmware rate control we don't know what rate is + * being transmitted, so for HT frames it should be bumped + * to something like OFDM24. + */ switch (mode) { case IEEE80211_PROT_CTSONLY: txd->txdw4 |= htole32(R92C_TXDW4_CTS2SELF); + txd->txdw4 |= htole32(R92C_TXDW4_HWRTSEN); break; case IEEE80211_PROT_RTSCTS: txd->txdw4 |= htole32(R92C_TXDW4_RTSEN); + txd->txdw4 |= htole32(R92C_TXDW4_HWRTSEN); break; default: break; @@ -95,19 +119,16 @@ r92c_tx_protection(struct rtwn_softc *sc, struct r92c_tx_desc *txd, if (mode == IEEE80211_PROT_CTSONLY || mode == IEEE80211_PROT_RTSCTS) { - if (RTWN_RATE_IS_HT(ridx)) - rate = rtwn_ctl_mcsrate(ic->ic_rt, ridx); - else - rate = ieee80211_ctl_rate(ic->ic_rt, ridx2rate[ridx]); - ridx = rate2ridx(IEEE80211_RV(rate)); - + ridx = RTWN_RIDX_OFDM24; txd->txdw4 |= htole32(SM(R92C_TXDW4_RTSRATE, ridx)); /* RTS rate fallback limit (max). */ txd->txdw5 |= htole32(SM(R92C_TXDW5_RTSRATE_FB_LMT, 0xf)); - - if (RTWN_RATE_IS_CCK(ridx) && ridx != RTWN_RIDX_CCK1 && +#if 0 + if (force_ht == false && RTWN_RATE_IS_CCK(ridx) + && ridx != RTWN_RIDX_CCK1 && (ic->ic_flags & IEEE80211_F_SHPREAMBLE)) txd->txdw4 |= htole32(R92C_TXDW4_RTS_SHORT); +#endif } } @@ -215,9 +236,11 @@ r92c_tx_setup_macid(void *buf, int id) /* XXX does not belong here */ /* XXX temporary (I hope) */ +#if 0 /* Force CCK1 for RTS / CTS frames (driver bug) */ txd->txdw4 &= ~htole32(SM(R92C_TXDW4_RTSRATE, R92C_TXDW4_RTSRATE_M)); txd->txdw4 &= ~htole32(R92C_TXDW4_RTS_SHORT); +#endif } static int @@ -244,7 +267,7 @@ r92c_calculate_tx_agg_window(struct rtwn_softc *sc, void r92c_fill_tx_desc(struct rtwn_softc *sc, struct ieee80211_node *ni, - struct mbuf *m, void *buf, uint8_t ridx, int maxretry) + struct mbuf *m, void *buf, uint8_t ridx, bool force_rate, int maxretry) { #ifndef RTWN_WITHOUT_UCODE struct r92c_softc *rs = sc->sc_priv; @@ -257,11 +280,13 @@ r92c_fill_tx_desc(struct rtwn_softc *sc, struct ieee80211_node *ni, enum ieee80211_protmode prot; uint8_t type, tid, qos, qsel; int hasqos, ismcast, macid; + bool ismgmt; wh = mtod(m, struct ieee80211_frame *); type = wh->i_fc[0] & IEEE80211_FC0_TYPE_MASK; hasqos = IEEE80211_QOS_HAS_SEQ(wh); ismcast = IEEE80211_IS_MULTICAST(wh->i_addr1); + ismgmt = IEEE80211_IS_MGMT(wh); /* Select TX ring for this frame. */ if (hasqos) { @@ -278,19 +303,44 @@ r92c_fill_tx_desc(struct rtwn_softc *sc, struct ieee80211_node *ni, if (ismcast) txd->flags0 |= R92C_FLAGS0_BMCAST; + if (ismgmt) { + txd->txdw5 |= htole32(R92C_TXDW5_RTY_LMT_ENA); + txd->txdw5 |= htole32(SM(R92C_TXDW5_RTY_LMT, + maxretry)); + } + + if (IEEE80211_IS_DATA(wh)) + txd->txdw4 |= htole32(R92C_TXDW4_QOS); + if (!ismcast) { /* Unicast frame, check if an ACK is expected. */ if (!qos || (qos & IEEE80211_QOS_ACKPOLICY) != IEEE80211_QOS_ACKPOLICY_NOACK) { - txd->txdw5 |= htole32(R92C_TXDW5_RTY_LMT_ENA); - txd->txdw5 |= htole32(SM(R92C_TXDW5_RTY_LMT, - maxretry)); } struct rtwn_node *un = RTWN_NODE(ni); macid = un->id; if (type == IEEE80211_FC0_TYPE_DATA) { + bool use_shpreamble = false; + bool use_ht = false; + + /* + * Calculate whether to use shared preamble / HT + * based on config if its firmware rate control, or + * rate if any other rate control. + */ + if (sc->sc_ratectl == RTWN_RATECTL_FW && force_rate == false) { + if (ic->ic_flags & IEEE80211_F_SHPREAMBLE) + use_shpreamble = true; + } else { + if (RTWN_RATE_IS_CCK(ridx) && ridx != RTWN_RIDX_CCK1 && + (ic->ic_flags & IEEE80211_F_SHPREAMBLE)) + use_shpreamble = true; + if (RTWN_RATE_IS_HT(ridx)) + use_ht = true; + } + qsel = tid % RTWN_MAX_TID; rtwn_r92c_tx_enable_ampdu(sc, buf, @@ -309,17 +359,20 @@ r92c_fill_tx_desc(struct rtwn_softc *sc, struct ieee80211_node *ni, #endif } - if (RTWN_RATE_IS_CCK(ridx) && ridx != RTWN_RIDX_CCK1 && - (ic->ic_flags & IEEE80211_F_SHPREAMBLE)) + if (use_shpreamble) txd->txdw4 |= htole32(R92C_TXDW4_DATA_SHPRE); prot = IEEE80211_PROT_NONE; - if (RTWN_RATE_IS_HT(ridx)) { + /* XXX better way to know whether to set SGI/HT40? */ + if (use_ht || m->m_flags & M_AMPDU_MPDU) { r92c_tx_set_ht40(sc, txd, ni); r92c_tx_set_sgi(sc, txd, ni); prot = ic->ic_htprotmode; - } else if (ic->ic_flags & IEEE80211_F_USEPROT) + } else if (ic->ic_flags & IEEE80211_F_USEPROT) { prot = ic->ic_protmode; + } else if (IEEE80211_IS_CHAN_HT(ni->ni_chan)) { + prot = ic->ic_htprotmode; + } /* XXX fix last comparison for A-MSDU (in net80211) */ /* XXX A-MPDU? */ @@ -330,7 +383,8 @@ r92c_fill_tx_desc(struct rtwn_softc *sc, struct ieee80211_node *ni, /* NB: checks for ht40 / short bits (set above). */ if (prot != IEEE80211_PROT_NONE) - r92c_tx_protection(sc, txd, prot, ridx); + r92c_tx_protection(sc, txd, prot, ridx, + !! (m->m_flags & M_AMPDU_MPDU)); } else /* IEEE80211_FC0_TYPE_MGT */ qsel = R92C_TXDW1_QSEL_MGNT; } else { @@ -341,21 +395,33 @@ r92c_fill_tx_desc(struct rtwn_softc *sc, struct ieee80211_node *ni, txd->txdw1 |= htole32(SM(R92C_TXDW1_QSEL, qsel)); rtwn_r92c_tx_setup_macid(sc, txd, macid); - txd->txdw5 |= htole32(SM(R92C_TXDW5_DATARATE, ridx)); + if (sc->sc_ratectl == RTWN_RATECTL_FW && force_rate == false) { +// txd->txdw5 |= htole32(SM(R92C_TXDW5_DATARATE, 0)); + txd->txdw5 |= htole32(SM(R92C_TXDW5_DATARATE, RTWN_RIDX_HT_MCS(5))); + } else { + txd->txdw5 |= htole32(SM(R92C_TXDW5_DATARATE, ridx)); + } + /* Data rate fallback limit (max). */ txd->txdw5 |= htole32(SM(R92C_TXDW5_DATARATE_FB_LMT, 0x1f)); txd->txdw4 |= htole32(SM(R92C_TXDW4_PORT_ID, uvp->id)); r92c_tx_raid(sc, txd, ni, ismcast); /* Force this rate if needed. */ - if (sc->sc_ratectl != RTWN_RATECTL_FW) + if (sc->sc_ratectl != RTWN_RATECTL_FW || force_rate == true) txd->txdw4 |= htole32(R92C_TXDW4_DRVRATE); + /* Note: 8188cu/8192cu/8723au doesn't set hardware seq */ + /* Note: TXDW4_SEQ_SEL is not a field? What's going on here */ +#if 0 if (!hasqos) { /* Use HW sequence numbering for non-QoS frames. */ rtwn_r92c_tx_setup_hwseq(sc, txd); txd->txdw4 |= htole32(SM(R92C_TXDW4_SEQ_SEL, uvp->id)); - } else { + } + else +#endif + { uint16_t seqno; if (m->m_flags & M_AMPDU_MPDU) { @@ -398,9 +464,11 @@ r92c_fill_tx_desc_raw(struct rtwn_softc *sc, struct ieee80211_node *ni, params->ibp_try0)); } if (params->ibp_flags & IEEE80211_BPF_RTS) - r92c_tx_protection(sc, txd, IEEE80211_PROT_RTSCTS, ridx); + r92c_tx_protection(sc, txd, IEEE80211_PROT_RTSCTS, ridx, + false); if (params->ibp_flags & IEEE80211_BPF_CTS) - r92c_tx_protection(sc, txd, IEEE80211_PROT_CTSONLY, ridx); + r92c_tx_protection(sc, txd, IEEE80211_PROT_CTSONLY, ridx, + false); rtwn_r92c_tx_setup_macid(sc, txd, RTWN_MACID_BC); txd->txdw1 |= htole32(SM(R92C_TXDW1_QSEL, R92C_TXDW1_QSEL_MGNT)); @@ -412,6 +480,9 @@ r92c_fill_tx_desc_raw(struct rtwn_softc *sc, struct ieee80211_node *ni, txd->txdw4 |= htole32(R92C_TXDW4_DRVRATE); r92c_tx_raid(sc, txd, ni, ismcast); + /* Get TX feedback */ + txd->txdw2 |= htole32(R92C_TXDW2_CCX_RPT); + if (!IEEE80211_QOS_HAS_SEQ(wh)) { /* Use HW sequence numbering for non-QoS frames. */ rtwn_r92c_tx_setup_hwseq(sc, txd); diff --git a/sys/dev/rtwn/rtl8192c/r92c_tx_desc.h b/sys/dev/rtwn/rtl8192c/r92c_tx_desc.h index 6e546c3da236..4ddaea25de71 100644 --- a/sys/dev/rtwn/rtl8192c/r92c_tx_desc.h +++ b/sys/dev/rtwn/rtl8192c/r92c_tx_desc.h @@ -69,8 +69,10 @@ struct r92c_tx_desc { uint32_t txdw4; #define R92C_TXDW4_RTSRATE_M 0x0000001f #define R92C_TXDW4_RTSRATE_S 0 +/* XXX what is this SUPPOSED to be */ #define R92C_TXDW4_SEQ_SEL_M 0x00000040 #define R92C_TXDW4_SEQ_SEL_S 6 +#define R92C_TXDW4_QOS 0x00000040 /* BIT(6) for 8188cu/8192cu/8723au */ #define R92C_TXDW4_HWSEQ_EN 0x00000080 #define R92C_TXDW4_DRVRATE 0x00000100 #define R92C_TXDW4_CTS2SELF 0x00000800 diff --git a/sys/dev/rtwn/rtl8192c/usb/r92cu_init.c b/sys/dev/rtwn/rtl8192c/usb/r92cu_init.c index 42e50ff9f8bd..9b752c303c92 100644 --- a/sys/dev/rtwn/rtl8192c/usb/r92cu_init.c +++ b/sys/dev/rtwn/rtl8192c/usb/r92cu_init.c @@ -375,11 +375,7 @@ r92cu_post_init(struct rtwn_softc *sc) if (sc->sc_flags & RTWN_FW_LOADED) { struct r92c_softc *rs = sc->sc_priv; - if (sc->sc_ratectl_sysctl == RTWN_RATECTL_FW) { - /* XXX firmware RA does not work yet */ - sc->sc_ratectl = RTWN_RATECTL_NET80211; - } else - sc->sc_ratectl = sc->sc_ratectl_sysctl; + sc->sc_ratectl = sc->sc_ratectl_sysctl; /* Start C2H event handling. */ callout_reset(&rs->rs_c2h_report, rs->rs_c2h_timeout, diff --git a/sys/dev/rtwn/rtl8812a/r12a.h b/sys/dev/rtwn/rtl8812a/r12a.h index 19dbd1569e6d..434e9a3e4206 100644 --- a/sys/dev/rtwn/rtl8812a/r12a.h +++ b/sys/dev/rtwn/rtl8812a/r12a.h @@ -1,4 +1,4 @@ -/*- +;/*2 * Copyright (c) 2016 Andriy Voskoboinyk * All rights reserved. * @@ -130,7 +130,7 @@ void r12a_get_rx_stats(struct rtwn_softc *, struct ieee80211_rx_stats *, /* r12a_tx.c */ void r12a_fill_tx_desc(struct rtwn_softc *, struct ieee80211_node *, - struct mbuf *, void *, uint8_t, int); + struct mbuf *, void *, uint8_t, bool, int); void r12a_fill_tx_desc_raw(struct rtwn_softc *, struct ieee80211_node *, struct mbuf *, void *, const struct ieee80211_bpf_params *); void r12a_fill_tx_desc_null(struct rtwn_softc *, void *, int, int, int); diff --git a/sys/dev/rtwn/rtl8812a/r12a_tx.c b/sys/dev/rtwn/rtl8812a/r12a_tx.c index 822416a09618..cc686668e4a2 100644 --- a/sys/dev/rtwn/rtl8812a/r12a_tx.c +++ b/sys/dev/rtwn/rtl8812a/r12a_tx.c @@ -261,7 +261,7 @@ r12a_calculate_tx_agg_window(struct rtwn_softc *sc, void r12a_fill_tx_desc(struct rtwn_softc *sc, struct ieee80211_node *ni, - struct mbuf *m, void *buf, uint8_t ridx, int maxretry) + struct mbuf *m, void *buf, uint8_t ridx, bool force_rate, int maxretry) { struct ieee80211com *ic = &sc->sc_ic; struct ieee80211vap *vap = ni->ni_vap;