ath9k: fix RTS/CTS handling
authorFelix Fietkau <nbd@openwrt.org>
Sun, 17 Jan 2010 20:08:50 +0000 (21:08 +0100)
committerJohn W. Linville <linville@tuxdriver.com>
Tue, 19 Jan 2010 21:43:09 +0000 (16:43 -0500)
The Tx DMA descriptor has two kinds of flags that select RTS/CTS usage.
The first one (global for the frame) selects whether RTS/CTS or
CTS-to-self should be used, the second one enables RTS/CTS or
CTS-to-self usage for an individual multi-rate-retry entry.
Previously the code preparing the descriptor only enabled the global
flag, if the first MRR series selected the local one.
Fix this by enabling the global flag if any of the MRR entries need it.
With this patch, rate control can properly select the use of RTS/CTS
for all MRR entries except the first one, which is the default behavior.

Signed-off-by: Felix Fietkau <nbd@openwrt.org>
Signed-off-by: John W. Linville <linville@tuxdriver.com>
drivers/net/wireless/ath/ath9k/xmit.c

index a821bb6..a6893cf 100644 (file)
@@ -1498,26 +1498,6 @@ static void ath_buf_set_rate(struct ath_softc *sc, struct ath_buf *bf)
        if (sc->sc_flags & SC_OP_PREAMBLE_SHORT)
                ctsrate |= rate->hw_value_short;
 
-       /*
-        * ATH9K_TXDESC_RTSENA and ATH9K_TXDESC_CTSENA are mutually exclusive.
-        * Check the first rate in the series to decide whether RTS/CTS
-        * or CTS-to-self has to be used.
-        */
-       if (rates[0].flags & IEEE80211_TX_RC_USE_CTS_PROTECT)
-               flags = ATH9K_TXDESC_CTSENA;
-       else if (rates[0].flags & IEEE80211_TX_RC_USE_RTS_CTS)
-               flags = ATH9K_TXDESC_RTSENA;
-
-       /* FIXME: Handle aggregation protection */
-       if (sc->config.ath_aggr_prot &&
-           (!bf_isaggr(bf) || (bf_isaggr(bf) && bf->bf_al < 8192))) {
-               flags = ATH9K_TXDESC_RTSENA;
-       }
-
-       /* For AR5416 - RTS cannot be followed by a frame larger than 8K */
-       if (bf_isaggr(bf) && (bf->bf_al > sc->sc_ah->caps.rts_aggr_limit))
-               flags &= ~(ATH9K_TXDESC_RTSENA);
-
        for (i = 0; i < 4; i++) {
                bool is_40, is_sgi, is_sp;
                int phy;
@@ -1529,8 +1509,15 @@ static void ath_buf_set_rate(struct ath_softc *sc, struct ath_buf *bf)
                series[i].Tries = rates[i].count;
                series[i].ChSel = common->tx_chainmask;
 
-               if (rates[i].flags & IEEE80211_TX_RC_USE_RTS_CTS)
+               if ((sc->config.ath_aggr_prot && bf_isaggr(bf)) ||
+                   (rates[i].flags & IEEE80211_TX_RC_USE_RTS_CTS)) {
                        series[i].RateFlags |= ATH9K_RATESERIES_RTS_CTS;
+                       flags |= ATH9K_TXDESC_RTSENA;
+               } else if (rates[i].flags & IEEE80211_TX_RC_USE_CTS_PROTECT) {
+                       series[i].RateFlags |= ATH9K_RATESERIES_RTS_CTS;
+                       flags |= ATH9K_TXDESC_CTSENA;
+               }
+
                if (rates[i].flags & IEEE80211_TX_RC_40_MHZ_WIDTH)
                        series[i].RateFlags |= ATH9K_RATESERIES_2040;
                if (rates[i].flags & IEEE80211_TX_RC_SHORT_GI)
@@ -1568,6 +1555,14 @@ static void ath_buf_set_rate(struct ath_softc *sc, struct ath_buf *bf)
                        phy, rate->bitrate * 100, bf->bf_frmlen, rix, is_sp);
        }
 
+       /* For AR5416 - RTS cannot be followed by a frame larger than 8K */
+       if (bf_isaggr(bf) && (bf->bf_al > sc->sc_ah->caps.rts_aggr_limit))
+               flags &= ~ATH9K_TXDESC_RTSENA;
+
+       /* ATH9K_TXDESC_RTSENA and ATH9K_TXDESC_CTSENA are mutually exclusive. */
+       if (flags & ATH9K_TXDESC_RTSENA)
+               flags &= ~ATH9K_TXDESC_CTSENA;
+
        /* set dur_update_en for l-sig computation except for PS-Poll frames */
        ath9k_hw_set11n_ratescenario(sc->sc_ah, bf->bf_desc,
                                     bf->bf_lastbf->bf_desc,