Skip to content

Commit

Permalink
ath9k: fix RTS/CTS handling
Browse files Browse the repository at this point in the history
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>
  • Loading branch information
Felix Fietkau authored and John W. Linville committed Jan 19, 2010
1 parent 5f2aa25 commit 2703205
Showing 1 changed file with 16 additions and 21 deletions.
37 changes: 16 additions & 21 deletions drivers/net/wireless/ath/ath9k/xmit.c
Original file line number Diff line number Diff line change
Expand Up @@ -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;
Expand All @@ -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)
Expand Down Expand Up @@ -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,
Expand Down

0 comments on commit 2703205

Please sign in to comment.