diff --git a/sys/dev/rtwn/rtl8192c/r92c_tx.c b/sys/dev/rtwn/rtl8192c/r92c_tx.c --- a/sys/dev/rtwn/rtl8192c/r92c_tx.c +++ b/sys/dev/rtwn/rtl8192c/r92c_tx.c @@ -77,11 +77,20 @@ 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_rate) { struct ieee80211com *ic = &sc->sc_ic; uint8_t rate; + /* + * For now, disable setting TX protection if firmware rate control + * is enabled and we're not forcing a rate. Some further + * logic will be needed here to determine which CCK/OFDM + * rate to use for the RTS/CTS / CTS-to-self. + */ + if (sc->sc_ratectl == RTWN_RATECTL_FW && force_rate == false) + return; + switch (mode) { case IEEE80211_PROT_CTSONLY: txd->txdw4 |= htole32(R92C_TXDW4_CTS2SELF); @@ -285,6 +294,41 @@ txd->txdw4 |= htole32(R92C_TXDW4_DATA_SHPRE); } +static enum ieee80211_protmode +r92c_tx_get_protmode(struct rtwn_softc *sc, const struct ieee80211vap *vap, + const struct mbuf *m, + uint8_t ridx, bool force_rate) +{ + const struct ieee80211com *ic = &sc->sc_ic; + enum ieee80211_protmode prot; + + /* + * For now don't enable RTS/CTS when doing firmware rate control. + * + * The r92c_tx_protection() routine above needs to grow the ability + * to figure out what to do (ie, a CCK or OFDM RTS/CTS rate) without + * an explicit ridx being set. + */ + if (sc->sc_ratectl == RTWN_RATECTL_FW && force_rate == false) + return (IEEE80211_PROT_NONE); + + prot = IEEE80211_PROT_NONE; + + if (RTWN_RATE_IS_HT(ridx)) + prot = ic->ic_htprotmode; + else if (ic->ic_flags & IEEE80211_F_USEPROT) + prot = ic->ic_protmode; + + /* XXX fix last comparison for A-MSDU (in net80211) */ + /* XXX A-MPDU? */ + if (m->m_pkthdr.len + IEEE80211_CRC_LEN > + vap->iv_rtsthreshold && + vap->iv_rtsthreshold != IEEE80211_RTS_MAX) + prot = IEEE80211_PROT_RTSCTS; + + return (prot); +} + void r92c_fill_tx_desc(struct rtwn_softc *sc, struct ieee80211_node *ni, struct mbuf *m, void *buf, uint8_t ridx, bool force_rate, int maxretry) @@ -292,7 +336,6 @@ #ifndef RTWN_WITHOUT_UCODE struct r92c_softc *rs = sc->sc_priv; #endif - struct ieee80211com *ic = &sc->sc_ic; struct ieee80211vap *vap = ni->ni_vap; struct rtwn_vap *uvp = RTWN_VAP(vap); struct ieee80211_frame *wh; @@ -357,24 +400,22 @@ r92c_fill_tx_desc_shpreamble(sc, txd, ridx, force_rate); - prot = IEEE80211_PROT_NONE; - if (RTWN_RATE_IS_HT(ridx)) { + prot = r92c_tx_get_protmode(sc, vap, m, ridx, + force_rate); + + /* + * Note: Firmware rate control will enable short-GI + * based on the configured rate mask, however HT40 + * may not be enabled. + */ + if (sc->sc_ratectl != RTWN_RATECTL_FW && + RTWN_RATE_IS_HT(ridx)) { 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) - prot = ic->ic_protmode; - - /* XXX fix last comparison for A-MSDU (in net80211) */ - /* XXX A-MPDU? */ - if (m->m_pkthdr.len + IEEE80211_CRC_LEN > - vap->iv_rtsthreshold && - vap->iv_rtsthreshold != IEEE80211_RTS_MAX) - prot = IEEE80211_PROT_RTSCTS; + } /* 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, force_rate); } else /* IEEE80211_FC0_TYPE_MGT */ qsel = R92C_TXDW1_QSEL_MGNT; } else { @@ -438,9 +479,11 @@ 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, + true); 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, + true); rtwn_r92c_tx_setup_macid(sc, txd, RTWN_MACID_BC); txd->txdw1 |= htole32(SM(R92C_TXDW1_QSEL, R92C_TXDW1_QSEL_MGNT));