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);
}
Esempio n. 2
0
/*
 * 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;
    }
}