/* * Setup a 11n rate series structure * * This should be called for both legacy and MCS rates. * * It, along with ath_buf_set_rate, must be called -after- a burst * or aggregate is setup. */ static void ath_rateseries_setup(struct ath_softc *sc, struct ieee80211_node *ni, struct ath_buf *bf, HAL_11N_RATE_SERIES *series) { #define HT_RC_2_STREAMS(_rc) ((((_rc) & 0x78) >> 3) + 1) struct ieee80211com *ic = ni->ni_ic; struct ath_hal *ah = sc->sc_ah; HAL_BOOL shortPreamble = AH_FALSE; const HAL_RATE_TABLE *rt = sc->sc_currates; int i; int pktlen; int flags = bf->bf_state.bfs_txflags; struct ath_rc_series *rc = bf->bf_state.bfs_rc; if ((ic->ic_flags & IEEE80211_F_SHPREAMBLE) && (ni->ni_capinfo & IEEE80211_CAPINFO_SHORT_PREAMBLE)) shortPreamble = AH_TRUE; /* * If this is the first frame in an aggregate series, * use the aggregate length. */ if (bf->bf_state.bfs_aggr) pktlen = bf->bf_state.bfs_al; else pktlen = bf->bf_state.bfs_pktlen; /* * XXX TODO: modify this routine to use the bfs_rc[x].flags * XXX fields. */ memset(series, 0, sizeof(HAL_11N_RATE_SERIES) * 4); for (i = 0; i < 4; i++) { /* Only set flags for actual TX attempts */ if (rc[i].tries == 0) continue; series[i].Tries = rc[i].tries; /* * XXX this isn't strictly correct - sc_txchainmask * XXX isn't the currently active chainmask; * XXX it's the interface chainmask at startup. * XXX It's overridden in the HAL rate scenario function * XXX for now. */ series[i].ChSel = sc->sc_txchainmask; if (flags & (HAL_TXDESC_RTSENA | HAL_TXDESC_CTSENA)) series[i].RateFlags |= HAL_RATESERIES_RTS_CTS; /* * Transmit 40MHz frames only if the node has negotiated * it rather than whether the node is capable of it or not. * It's subtly different in the hostap case. */ if (ni->ni_chw == 40) series[i].RateFlags |= HAL_RATESERIES_2040; /* * Set short-GI only if the node has advertised it * the channel width is suitable, and we support it. * We don't currently have a "negotiated" set of bits - * ni_htcap is what the remote end sends, not what this * node is capable of. */ if (ni->ni_chw == 40 && ic->ic_htcaps & IEEE80211_HTCAP_SHORTGI40 && ni->ni_htcap & IEEE80211_HTCAP_SHORTGI40) series[i].RateFlags |= HAL_RATESERIES_HALFGI; if (ni->ni_chw == 20 && ic->ic_htcaps & IEEE80211_HTCAP_SHORTGI20 && ni->ni_htcap & IEEE80211_HTCAP_SHORTGI20) series[i].RateFlags |= HAL_RATESERIES_HALFGI; series[i].Rate = rt->info[rc[i].rix].rateCode; /* PktDuration doesn't include slot, ACK, RTS, etc timing - it's just the packet duration */ if (series[i].Rate & IEEE80211_RATE_MCS) { series[i].PktDuration = ath_computedur_ht(pktlen , series[i].Rate , HT_RC_2_STREAMS(series[i].Rate) , series[i].RateFlags & HAL_RATESERIES_2040 , series[i].RateFlags & HAL_RATESERIES_HALFGI); } else { if (shortPreamble) series[i].Rate |= rt->info[rc[i].rix].shortPreamble; series[i].PktDuration = ath_hal_computetxtime(ah, rt, pktlen, rc[i].rix, shortPreamble); } } #undef HT_RC_2_STREAMS }
/* * Setup a 11n rate series structure * * This should be called for both legacy and MCS rates. * * This uses the rate series stuf from ath_tx_rate_fill_rcflags(). * * It, along with ath_buf_set_rate, must be called -after- a burst * or aggregate is setup. */ static void ath_rateseries_setup(struct ath_softc *sc, struct ieee80211_node *ni, struct ath_buf *bf, HAL_11N_RATE_SERIES *series) { struct ieee80211com *ic = ni->ni_ic; struct ath_hal *ah = sc->sc_ah; HAL_BOOL shortPreamble = AH_FALSE; const HAL_RATE_TABLE *rt = sc->sc_currates; int i; int pktlen; struct ath_rc_series *rc = bf->bf_state.bfs_rc; if ((ic->ic_flags & IEEE80211_F_SHPREAMBLE) && (ni->ni_capinfo & IEEE80211_CAPINFO_SHORT_PREAMBLE)) shortPreamble = AH_TRUE; /* * If this is the first frame in an aggregate series, * use the aggregate length. */ if (bf->bf_state.bfs_aggr) pktlen = bf->bf_state.bfs_al; else pktlen = bf->bf_state.bfs_pktlen; /* * XXX TODO: modify this routine to use the bfs_rc[x].flags * XXX fields. */ memset(series, 0, sizeof(HAL_11N_RATE_SERIES) * 4); for (i = 0; i < ATH_RC_NUM; i++) { /* Only set flags for actual TX attempts */ if (rc[i].tries == 0) continue; series[i].Tries = rc[i].tries; /* * XXX TODO: When the NIC is capable of three stream TX, * transmit 1/2 stream rates on two streams. * * This reduces the power consumption of the NIC and * keeps it within the PCIe slot power limits. */ series[i].ChSel = sc->sc_cur_txchainmask; /* * Setup rate and TX power cap for this series. */ series[i].Rate = rt->info[rc[i].rix].rateCode; series[i].RateIndex = rc[i].rix; series[i].tx_power_cap = rc[i].tx_power_cap; /* * Enable RTS/CTS as appropriate. */ if (rc[i].flags & ATH_RC_RTSCTS_FLAG) series[i].RateFlags |= HAL_RATESERIES_RTS_CTS; /* * 11n rate? Update 11n flags. */ if (rc[i].flags & ATH_RC_HT_FLAG) { if (rc[i].flags & ATH_RC_CW40_FLAG) series[i].RateFlags |= HAL_RATESERIES_2040; if (rc[i].flags & ATH_RC_SGI_FLAG) series[i].RateFlags |= HAL_RATESERIES_HALFGI; if (rc[i].flags & ATH_RC_STBC_FLAG) series[i].RateFlags |= HAL_RATESERIES_STBC; } /* * TODO: If we're all doing 11n rates then we can set LDPC. * If we've been asked to /do/ LDPC but we are handed a * legacy rate, then we should complain. Loudly. */ /* * PktDuration doesn't include slot, ACK, RTS, etc timing - * it's just the packet duration */ if (rc[i].flags & ATH_RC_HT_FLAG) { series[i].PktDuration = ath_computedur_ht(pktlen , series[i].Rate , HT_RC_2_STREAMS(series[i].Rate) , series[i].RateFlags & HAL_RATESERIES_2040 , series[i].RateFlags & HAL_RATESERIES_HALFGI); } else { if (shortPreamble) series[i].Rate |= rt->info[rc[i].rix].shortPreamble; series[i].PktDuration = ath_hal_computetxtime(ah, rt, pktlen, rc[i].rix, shortPreamble); } } }