void ath_rate_findrate(struct ath_softc_tgt *sc, struct ath_node_target *an, int shortPreamble, size_t frameLen, int numTries, int numRates, int stepDnInc, unsigned int rcflag, struct ath_rc_series series[], int *isProbe) { struct ieee80211vap *vap = an->ni.ni_vap; struct atheros_node *oan = ATH_NODE_ATHEROS(an); struct atheros_softc *asc = (struct atheros_softc *) sc->sc_rc; RATE_TABLE *pRateTable = (RATE_TABLE *)asc->hwRateTable[sc->sc_curmode]; u_int32_t *retrySched; *isProbe = 0; if (!numRates || !numTries) { return; } ath_rate_findrate_11n(sc, an, frameLen, numTries, numRates, stepDnInc, rcflag, series, isProbe); }
/* * Return the next series 0 transmit rate and setup for a callback * to install the multi-rate transmit data if appropriate. We cannot * install the multi-rate transmit data here because the caller is * going to initialize the tx descriptor and so would clobber whatever * we write. Note that we choose an arbitrary series 0 try count to * insure we get called back; this permits us to defer calculating * the actual number of tries until the callback at which time we * can just copy the pre-calculated series data. */ void ath_rate_findrate(struct ath_softc *sc, struct ath_node *an, int shortPreamble, u_int32_t frameLen, int numTries, unsigned int rcflag, u_int8_t ac, struct ath_rc_series rcs[], int *isProbe, int isretry,u_int32_t bf_flags) { struct atheros_node *oan = an->an_rc_node; struct atheros_softc *asc = oan->asc; struct atheros_vap *avap = oan->avp; struct ath_vap *avp = oan->avp->athdev_vap; const RATE_TABLE *pRateTable = avap->rateTable; u_int8_t *retrySched; int i; u_int8_t fixedratecode; u_int32_t old_av_fixed_rateset; u_int32_t old_av_fixed_retryset; ASSERT(rcs != NULL); if (sc->sc_ah->ah_magic == 0x19641014 || sc->sc_ah->ah_magic == 0x19741014) { #ifdef ATH_SUPPORT_TxBF // set calibration and sounding indicator #define MS(_v, _f) (((_v) & _f) >> _f##_S) sc->sc_txbfsounding = 0; oan->txbf_sounding = 0; sc->sc_txbfcalibrating = 0; if ((MS(bf_flags,HAL_TXDESC_TXBF_SOUND)==HAL_TXDESC_STAG_SOUND) ||(MS(bf_flags,HAL_TXDESC_TXBF_SOUND)== HAL_TXDESC_SOUND)){ sc->sc_txbfsounding = 1; oan->txbf_sounding = 1; } if (bf_flags & HAL_TXDESC_CAL) { sc->sc_txbfcalibrating = 1; } #endif /* store the previous values */ old_av_fixed_rateset = avp->av_config.av_fixed_rateset; old_av_fixed_retryset = avp->av_config.av_fixed_retryset; /* If fixed node rate is enabled, we fixed the link rate */ if (an->an_fixedrate_enable) { fixedratecode = an->an_fixedratecode; avp->av_config.av_fixed_rateset = 0; for (i=0; i<4; i++) { avp->av_config.av_fixed_rateset <<= 8; avp->av_config.av_fixed_rateset |= fixedratecode; } avp->av_config.av_fixed_retryset = 0x03030303; } ath_rate_findrate_11n(sc, an, frameLen, numTries, 4, rcflag, ac, rcs, isProbe, isretry); /* restore the previous values */ avp->av_config.av_fixed_rateset = old_av_fixed_rateset; avp->av_config.av_fixed_retryset = old_av_fixed_retryset; return; } if (asc->fixedrix == IEEE80211_FIXED_RATE_NONE) { rcs[0].rix = rcRateFind(sc, oan, frameLen, pRateTable, &sc->sc_curchan, isretry); /* multi-rate support implied */ rcs[0].tries = ATH_TXMAXTRY-1; /* anything != ATH_TXMAXTRY */ } else { rcs[0].rix = asc->fixedrix; rcs[0].tries = ATH_TXMAXTRY; } /* If fixed node rate is enabled, we fixed the link rate */ if (an->an_fixedrate_enable) { rcs[0].rix = an->an_fixedrix; rcs[0].tries = ATH_TXMAXTRY; } ASSERT(rcs[0].rix != (u_int8_t)-1); /* get the corresponding index for the choosen rate in txRateCtrl */ for (i = 0; oan->txRateCtrl.validRateIndex[i] != rcs[0].rix && i < oan->txRateCtrl.maxValidRate ; i++); ASSERT(asc->fixedrix != IEEE80211_FIXED_RATE_NONE || i != oan->txRateCtrl.maxValidRate); if (rcs[0].tries != ATH_TXMAXTRY) { /* NB: only called for data frames */ if (oan->txRateCtrl.probeRate) { retrySched = shortPreamble ? (u_int8_t *)&(oan->txRateCtrl.validRateSeries[i][24]) : (u_int8_t *)&(oan->txRateCtrl.validRateSeries[i][16]); } else { retrySched = shortPreamble ? (u_int8_t *)&(oan->txRateCtrl.validRateSeries[i][8]) : (u_int8_t *)&(oan->txRateCtrl.validRateSeries[i][0]); } #ifdef ATH_SUPPORT_UAPSD_RATE_CONTROL if (oan->uapsd) { retrySched = shortPreamble ? (u_int8_t *)&(oan->txRateCtrl.validRateSeries[i][40]) : (u_int8_t *)&(oan->txRateCtrl.validRateSeries[i][32]); } #endif /* ATH_SUPPORT_UAPSD_RATE_CONTROL */ /* Update rate seies based on retry schedule */ rcs[0].tries = retrySched[0]; rcs[1].tries = retrySched[1]; rcs[2].tries = retrySched[2]; rcs[3].tries = retrySched[3]; if (!IS_CHAN_TURBO(&sc->sc_curchan)) ASSERT(rcs[0].rix == pRateTable->rateCodeToIndex[retrySched[4]]); /* * Retry scheduler assumes that all the rates below max rate in the * intersection rate table are present and so it takes the next possible * lower rates for the retries, which is not correct. So check them * before filling the retry rates. */ rcs[1].rix = pRateTable->rateCodeToIndex[retrySched[5]]; rcs[2].rix = pRateTable->rateCodeToIndex[retrySched[6]]; rcs[3].rix = pRateTable->rateCodeToIndex[retrySched[7]]; if (sc->sc_curchan.privFlags & CHANNEL_4MS_LIMIT) { u_int32_t prevrix = rcs[0].rix; for (i=1; i<4; i++) { if (rcs[i].tries) { if (pRateTable->info[rcs[i].rix].max4msFrameLen < frameLen) { rcs[i].rix = prevrix; } else { prevrix = rcs[i].rix; } } else { /* Retries are 0 from here */ break; } } } } if (sc->sc_ieee_ops->update_txrate) { sc->sc_ieee_ops->update_txrate(an->an_node, oan->rixMap[rcs[0].rix]); } #if ATH_SUPERG_DYNTURBO /* XXX map from merged table to split for driver */ if (IS_CHAN_TURBO(&sc->sc_curchan) && rcs[0].rix >= (pRateTable->rateCount - pRateTable->numTurboRates)) { u_int32_t numCCKRates = 5; u_int32_t i; rcs[0].rix -= (pRateTable->rateCount-pRateTable->numTurboRates); if (IS_CHAN_2GHZ(&sc->sc_curchan)) { for (i=1;i<=3;i++) { /*Mapping for retry rates from merged table to split table*/ if (rcs[i].rix >= numCCKRates) { rcs[i].rix -= numCCKRates; } else { /* For 6Mbps Turbo rate */ rcs[i].rix -= numCCKRates-1; } } } } #endif if (oan->txRateCtrl.consecRtsFailCount > MAX_CONSEC_RTS_FAILED_FRAMES) { rcs[0].flags |= ATH_RC_RTSCTS_FLAG; rcs[1].rix = rcs[2].rix = rcs[3].rix = 0; rcs[1].tries = rcs[2].tries = rcs[3].tries = 0; } }