diff --git a/sys/dev/rtwn/if_rtwn.c b/sys/dev/rtwn/if_rtwn.c index d4b45aa9eea7..917d63606bb7 100644 --- a/sys/dev/rtwn/if_rtwn.c +++ b/sys/dev/rtwn/if_rtwn.c @@ -350,7 +350,7 @@ 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_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: " diff --git a/sys/dev/rtwn/rtl8192c/r92c_fw.c b/sys/dev/rtwn/rtl8192c/r92c_fw.c index e611e5addeb3..0a0715b05c2b 100644 --- a/sys/dev/rtwn/rtl8192c/r92c_fw.c +++ b/sys/dev/rtwn/rtl8192c/r92c_fw.c @@ -91,11 +91,22 @@ r92c_fw_cmd(struct rtwn_softc *sc, uint8_t id, const void *buf, int len) cmd.id = id; if (len > 3) { /* Ext command: [id : byte2 : byte3 : byte4 : byte0 : byte1] */ - cmd.id |= R92C_CMD_FLAG_EXT; memcpy(cmd.msg, (const uint8_t *)buf + 2, len - 2); memcpy(cmd.msg + 3, buf, 2); - } else + cmd.id |= R92C_CMD_FLAG_EXT; + } else { memcpy(cmd.msg, buf, len); + } + + device_printf(sc->sc_dev, "%s: fwcur=%d, id=0x%02x, len=%d bytes 0x%x 0x%x 0x%x 0x%x 0x%x 0x%x 0x%x\n", + __func__, sc->fwcur, cmd.id, len, + cmd.id, + cmd.msg[0], + cmd.msg[1], + cmd.msg[2], + cmd.msg[3], + cmd.msg[4], + cmd.msg[5]); /* Write the first word last since that will trigger the FW. */ if (len > 3) { @@ -160,6 +171,8 @@ r92c_fw_download_enable(struct rtwn_softc *sc, int enable) /* * Initialize firmware rate adaptation. + * + * This is for RTL8188E, RTL8192C, RTL8723A. */ #ifndef RTWN_WITHOUT_UCODE static int @@ -167,42 +180,32 @@ r92c_send_ra_cmd(struct rtwn_softc *sc, int macid, uint32_t rates, int maxrate) { struct r92c_fw_cmd_macid_cfg cmd; - uint8_t mode; int error = 0; + uint8_t mode; - /* XXX should be called directly from iv_newstate() for MACID_BC */ - /* XXX joinbss, not send_ra_cmd() */ -#ifdef RTWN_TODO - /* NB: group addressed frames are done at 11bg rates for now */ - if (ic->ic_curmode == IEEE80211_MODE_11B) - mode = R92C_RAID_11B; - else - mode = R92C_RAID_11BG; - /* XXX misleading 'mode' value here for unicast frames */ - RTWN_DPRINTF(sc, RTWN_DEBUG_RA, - "%s: mode 0x%x, rates 0x%08x, basicrates 0x%08x\n", __func__, - mode, rates, basicrates); - - /* Set rates mask for group addressed frames. */ - cmd.macid = RTWN_MACID_BC | R92C_CMD_MACID_VALID; - cmd.mask = htole32(mode << 28 | basicrates); - error = rtwn_fw_cmd(sc, R92C_CMD_MACID_CONFIG, &cmd, sizeof(cmd)); - if (error != 0) { - device_printf(sc->sc_dev, - "could not set RA mask for broadcast station\n"); - return (error); - } -#endif - - /* Set rates mask for unicast frames. */ if (RTWN_RATE_IS_HT(maxrate)) mode = R92C_RAID_11GN; else if (RTWN_RATE_IS_OFDM(maxrate)) mode = R92C_RAID_11BG; else mode = R92C_RAID_11B; + + rates = rates | ((uint32_t) mode << 28); + + /* Set rates mask for unicast frames. */ + memset(&cmd, 0, sizeof(cmd)); + + cmd.mask = htole32(rates); cmd.macid = macid | R92C_CMD_MACID_VALID; - cmd.mask = htole32(mode << 28 | rates); + /* TODO: if this STA will use short-GI, arg |= 0x20; */ + + device_printf(sc->sc_dev, + "%s: rates=0x%08x, mask=0x%08x, macid=0x%02x\n", + __func__, + rates, + cmd.mask, + cmd.macid); + error = r92c_fw_cmd(sc, R92C_CMD_MACID_CONFIG, &cmd, sizeof(cmd)); if (error != 0) { device_printf(sc->sc_dev, @@ -220,7 +223,7 @@ r92c_init_ra(struct rtwn_softc *sc, int macid) { struct ieee80211_htrateset *rs_ht; struct ieee80211_node *ni; - uint32_t rates; + uint32_t rates, reg; int maxrate; RTWN_NT_LOCK(sc); @@ -246,7 +249,16 @@ r92c_init_ra(struct rtwn_softc *sc, int macid) } #endif - rtwn_write_1(sc, R92C_INIDATA_RATE_SEL(macid), maxrate); + /* XXX this register also controls HT40, look where else its written! and the upper/lower stufF (hit up bitterblue) */ + + /* This sets basic rates */ + reg = rtwn_read_4(sc, R92C_RRSR); + reg |= SM(R92C_RRSR_RATE_BITMAP, rates); + rtwn_write_4(sc, R92C_RRSR, reg); + + //rtwn_write_1(sc, R92C_INIDATA_RATE_SEL(macid), maxrate); + rtwn_write_1(sc, R92C_INIDATA_RATE_SEL(macid), 0x4); /* OFDM6 */ + rtwn_write_1(sc, R92C_INIRTS_RATE_SEL, 0x4); /* OFDM6 */ ieee80211_free_node(ni); } diff --git a/sys/dev/rtwn/rtl8192c/r92c_fw_cmd.h b/sys/dev/rtwn/rtl8192c/r92c_fw_cmd.h index b16e2819624f..9cea3b1c1363 100644 --- a/sys/dev/rtwn/rtl8192c/r92c_fw_cmd.h +++ b/sys/dev/rtwn/rtl8192c/r92c_fw_cmd.h @@ -77,9 +77,10 @@ struct r92c_fw_cmd_rssi { /* Structure for R92C_CMD_MACID_CONFIG. */ struct r92c_fw_cmd_macid_cfg { - uint32_t mask; - uint8_t macid; + uint32_t mask; + uint8_t macid; #define R92C_CMD_MACID_VALID 0x80 +#define R92C_CMD_MACID_SHORTGI 0x20 } __packed; /* diff --git a/sys/dev/rtwn/rtl8192c/r92c_tx.c b/sys/dev/rtwn/rtl8192c/r92c_tx.c index 9583a7e1119e..b17049529621 100644 --- a/sys/dev/rtwn/rtl8192c/r92c_tx.c +++ b/sys/dev/rtwn/rtl8192c/r92c_tx.c @@ -92,6 +92,7 @@ r92c_tx_protection(struct rtwn_softc *sc, struct r92c_tx_desc *txd, default: break; } + txd->txdw4 |= htole32(R92C_TXDW4_HWRTSEN); if (mode == IEEE80211_PROT_CTSONLY || mode == IEEE80211_PROT_RTSCTS) { @@ -215,9 +216,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 @@ -256,12 +259,13 @@ r92c_fill_tx_desc(struct rtwn_softc *sc, struct ieee80211_node *ni, struct r92c_tx_desc *txd; enum ieee80211_protmode prot; uint8_t type, tid, qos, qsel; - int hasqos, ismcast, macid; + int hasqos, ismcast, macid, 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) { @@ -325,12 +329,32 @@ r92c_fill_tx_desc(struct rtwn_softc *sc, struct ieee80211_node *ni, /* XXX A-MPDU? */ if (m->m_pkthdr.len + IEEE80211_CRC_LEN > vap->iv_rtsthreshold && - vap->iv_rtsthreshold != IEEE80211_RTS_MAX) + vap->iv_rtsthreshold != IEEE80211_RTS_MAX) { prot = IEEE80211_PROT_RTSCTS; + } + + /* + * If we're doing firmware rate control, we need + * to configure RTS/CTS based on the port config + * rather than the rate config. + * + * The rate lookup will unfortunately be sub-optimal + * ridx = 0 and treats it as CCK, so instead + * just set it to OFDM24. + */ + if (sc->sc_ratectl != RTWN_RATECTL_FW) { + if (IEEE80211_IS_CHAN_HT(ni->ni_chan)) { + prot = ic->ic_htprotmode; + } else { + prot = ic->ic_protmode; + } + } /* 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, + (sc->sc_ratectl == RTWN_RATECTL_NET80211 ? ridx : RTWN_RIDX_OFDM24)); + } else /* IEEE80211_FC0_TYPE_MGT */ qsel = R92C_TXDW1_QSEL_MGNT; } else { @@ -341,15 +365,23 @@ 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)); + /* 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); + if (IEEE80211_IS_QOSDATA(wh) || IEEE80211_IS_DATA(wh)) { + txd->txdw5 |= htole32(SM(R92C_TXDW5_DATARATE_FB_LMT, 0x1f)); + } /* Force this rate if needed. */ - if (sc->sc_ratectl != RTWN_RATECTL_FW) + if ((sc->sc_ratectl != RTWN_RATECTL_FW) || ismgmt) { + txd->txdw5 |= htole32(SM(R92C_TXDW5_DATARATE, ridx)); txd->txdw4 |= htole32(R92C_TXDW4_DRVRATE); + txd->txdw5 |= htole32(SM(R92C_TXDW5_RTY_LMT, 6)); + txd->txdw5 |= htole32(R92C_TXDW5_RTY_LMT_ENA); + /* XXX what's this? */ + txd->txdw4 |= htole32(SM(R92C_TXDW4_PORT_ID, uvp->id)); + } + + r92c_tx_raid(sc, txd, ni, ismcast); if (!hasqos) { /* Use HW sequence numbering for non-QoS frames. */ diff --git a/sys/dev/rtwn/rtl8192c/usb/r92cu_init.c b/sys/dev/rtwn/rtl8192c/usb/r92cu_init.c index 42e50ff9f8bd..8ace27f5f787 100644 --- a/sys/dev/rtwn/rtl8192c/usb/r92cu_init.c +++ b/sys/dev/rtwn/rtl8192c/usb/r92cu_init.c @@ -164,6 +164,7 @@ r92cu_power_on(struct rtwn_softc *sc) RTWN_CHK(rtwn_setbits_2(sc, R92C_CR, 0, R92C_CR_HCI_TXDMA_EN | R92C_CR_TXDMA_EN | R92C_CR_HCI_RXDMA_EN | R92C_CR_RXDMA_EN | + R92C_CR_MACRXEN | R92C_CR_MACTXEN | R92C_CR_PROTOCOL_EN | R92C_CR_SCHEDULE_EN | ((sc->sc_hwcrypto != RTWN_CRYPTO_SW) ? R92C_CR_ENSEC : 0) | R92C_CR_CALTMR_EN)); @@ -374,13 +375,7 @@ r92cu_post_init(struct rtwn_softc *sc) #ifndef RTWN_WITHOUT_UCODE 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, r92c_handle_c2h_report, sc);