Exemple #1
0
/*
 *  Update the SIB's rate control information
 *
 *  This should be called when the supported rates change
 *  (e.g. SME operation, wireless mode change)
 *
 *  It will determine which rates are valid for use.
 */
void
rcSibUpdate(struct atheros_softc *asc, struct atheros_node *pSib,
            int keepState, struct ieee80211_rateset *pRateSet,
            enum ieee80211_phymode curmode)
{
#define N(a)    (sizeof(a)/sizeof(a[0]))
    const RATE_TABLE    *pRateTable;
    struct TxRateCtrl_s *pRc        = &pSib->txRateCtrl;
    A_UINT8             i, j, hi = 0, count;
    A_INT8              k;
    int                 rateCount, numInfo;
    HAL_BOOL            bFoundDot11Rate_11, bFoundDot11Rate_22;

    pRateTable = asc->hwRateTable[curmode];

    /* Initial rate table size. Will change depending on the working rate set */
    pRc->rateTableSize = MAX_TX_RATE_TBL;
    numInfo = N(pRateTable->info);

    /* Initialize thresholds according to the global rate table */
    for (i = 0 ; (i < pRc->rateTableSize) && (!keepState) && (i < pRateTable->rateCount); i++) {
        if (i < numInfo) {
            pRc->state[i].rssiThres = pRateTable->info[i].rssiAckValidMin;
        }
        pRc->state[i].per       = 0;
#if ATH_SUPPORT_VOWEXT /* for RCA */
        pRc->state[i].maxAggrSize = MAX_AGGR_LIMIT;
#endif
    }

    /* Determine the valid rates */
    rcInitValidTxMask(pRc);
    rateCount = pRateTable->rateCount;
#ifdef notyet
    if (wlanIs5211Channel14(pSib)) {
        rateCount = 2;
    }
#endif

    count = 0;
    if (!pRateSet->rs_nrates) {
        /* No working rate, use valid rates */
        for (i = 0; i < rateCount; i++) {
            /*
             * If the rate is:
             * 1. not valid, or
             * 2. this is an uapsd node but the rate is not an uapsd rate
             * skip it.
             */
            if (pRateTable->info[i].valid != TRUE) {
                continue;
            }
#ifdef ATH_SUPPORT_UAPSD_RATE_CONTROL
            if ((pSib->uapsd) && (pRateTable->info[i].validUAPSD != TRUE)) {
                continue;
            }
#endif /* ATH_SUPPORT_UAPSD_RATE_CONTROL */

            pRc->validRateIndex[count] = i;
            /*
             * Copy the static rate series for the correspondig rate
             * from static rate table to TxRateCtrl_s.
             */
            OS_MEMCPY(pRc->validRateSeries[count],
                      &(pRateTable->info[i].normalSched), MAX_SCHED_TBL);
            count ++;
            rcSetValidTxMask(pRc, i, TRUE);
            hi = A_MAX(hi, i);
            pSib->rixMap[i] = 0;
        }

        pRc->maxValidRate = count;
        pRc->maxValidTurboRate = pRateTable->numTurboRates;
    } else {
        A_UINT8  turboCount;
        A_UINT64 mask;

        bFoundDot11Rate_11 = FALSE;
        bFoundDot11Rate_22 = FALSE;
        for(k = 0; k < pRateSet->rs_nrates; k++) {
            // Look for 5.5 mbps
            if((pRateSet->rs_rates[k] & 0x7F) == 11) {
                bFoundDot11Rate_11 = TRUE;
            }
            // Look for 11 mbps
            if((pRateSet->rs_rates[k] & 0x7F) == 22) {
                bFoundDot11Rate_22 = TRUE;
            }
        }

        /*
         * Use intersection of working rates and valid rates.
         * if working rates has 6 OFDM and does not have 5.5 and 11 CCKM, use 6.
         * if working rates has 9 OFDM and does not has 11 CCKM, use 9.
         */
        turboCount = 0;
        for (i = 0; i < pRateSet->rs_nrates; i++) {
            for (j = 0; j < rateCount; j++) {
                if ((pRateSet->rs_rates[i] & 0x7F) ==
                        (pRateTable->info[j].dot11Rate & 0x7F)) {
#ifdef ATH_SUPPORT_UAPSD_RATE_CONTROL
                    /*
                     * If this is an uapsd node but the rate is not an uapsd rate
                     * skip it.
                     */
                    if ((pSib->uapsd) && (pRateTable->info[j].validUAPSD != TRUE)) {
                        continue;
                    }
#endif /* ATH_SUPPORT_UAPSD_RATE_CONTROL */

                    if(pRateTable->info[j].valid == TRUE) {
                        rcSetValidTxMask(pRc, j, TRUE);
                        hi = A_MAX(hi, j);
                        pSib->rixMap[j] = i;
                    } else {
                        //To keep rate monotonicity
                        if(pRateTable->info[j].phy == WLAN_PHY_OFDM &&
                                ((((pRateSet->rs_rates[i] & 0x7F) == 12) &&
                                  (!bFoundDot11Rate_11) && (!bFoundDot11Rate_22)) ||
                                 (((pRateSet->rs_rates[i] & 0x7F) == 18) && !bFoundDot11Rate_22)))
                        {
                            rcSetValidTxMask(pRc, j, TRUE);
                            hi = A_MAX(hi, j);
                            pSib->rixMap[j] = i;
                        }
                    }
                }
            }
        }

        /* Get actually valid rate index, previous we get it from rate table,
         * now get rate table which include all working rate, so we need make
         * sure our valid rate table align with working rate */
        mask = pRc->validTxRateMask;
        for (i = 0; i < pRc->rateTableSize; i ++) {
            if (mask & ((A_UINT64)1 << i)) {
                pRc->validRateIndex[count] = i;
                /*
                 * Copy the static rate series for the correspondig rate
                 * from static rate table to TxRateCtrl_s.
                 */
                OS_MEMCPY(pRc->validRateSeries[count],
                          &(pRateTable->info[i].normalSched), MAX_SCHED_TBL);
                count ++;
                if (pRateTable->info[i].phy == WLAN_PHY_TURBO) {
                    turboCount ++;
                }
            }
        }
        pRc->maxValidRate = count;
        pRc->maxValidTurboRate = turboCount;
    }
    /*
     * Modify the static rate series in TxRateCtrl_s with respect to intersection
     * rate table.
     */
    for(i = 0 ; i < pRc->maxValidRate; i ++) {
        k = i;
        for (j = 5; j < MAX_SCHED_TBL; j ++) {
            if(j % 8 == 0) {
                k = i;
                j = j + 4;
                continue;
            }
            for (; k >= 0; k --) {
                if(pRc->validRateSeries[i][j] == pRateTable->info[k].rateCode) {
                    break;
                }
            }
            if (k == -1) {
                pRc->validRateSeries[i][j] = pRc->validRateSeries[i][j-1];
            }
        }
    }
    pRc->rateTableSize = hi + 1;
    pRc->rateMax = A_MIN(hi, pRateTable->initialRateMax);

    ASSERT(pRc->rateTableSize <= MAX_TX_RATE_TBL);
#undef N
}
Exemple #2
0
/*
 *  Update the SIB's rate control information
 *
 *  This should be called when the supported rates change
 *  (e.g. SME operation, wireless mode change)
 *
 *  It will determine which rates are valid for use.
 */
void
rcSibUpdate(struct ath_softc *sc, struct ath_node *an, A_BOOL keepState)
{
    struct atheros_node	*pSib	    = ATH_NODE_ATHEROS(an);
    struct atheros_softc *asc	    = (struct atheros_softc *) sc->sc_rc;
    const RATE_TABLE    *pRateTable = asc->hwRateTable[sc->sc_curmode];
    struct ieee80211_rateset *pRateSet = &an->an_node.ni_rates;
    struct TxRateCtrl_s *pRc        = &pSib->txRateCtrl;
    A_UINT8             i, j, hi = 0,count;
    int                 rateCount;

    /* Initial rate table size. Will change depending on the working rate set */
    pRc->rateTableSize = MAX_TX_RATE_TBL;

    /* Initialize thresholds according to the global rate table */
    for (i = 0 ; (i < pRc->rateTableSize) && (!keepState); i++) {
        pRc->state[i].rssiThres = pRateTable->info[i].rssiAckValidMin;
        pRc->state[i].per       = 0;
    }

    /* Determine the valid rates */
    rcInitValidTxMask(pRc);
    rateCount = pRateTable->rateCount;
#ifdef notyet
    if (wlanIs5211Channel14(pSib)) {
        rateCount = 2;
    }
#endif

    count = 0;
    if (!pRateSet->rs_nrates) {
        /* No working rate, use valid rates */
        for (i = 0; i < rateCount; i++) {
            if (pRateTable->info[i].valid == TRUE) {
                pRc->validRateIndex[count] = i;
                count ++;
                rcSetValidTxMask(pRc, i, TRUE);
                hi = A_MAX(hi, i);
		pSib->rixMap[i] = 0;
            }
        }

        pRc->maxValidRate = count;
        pRc->maxValidTurboRate = pRateTable->numTurboRates;
    } else {
        A_UINT8  turboCount;
        A_UINT32 mask;

        /* Use intersection of working rates and valid rates */
        turboCount = 0;
        for (i = 0; i < pRateSet->rs_nrates; i++) {
            for (j = 0; j < rateCount; j++) {
                if (((pRateSet->rs_rates[i] & 0x7F) == (pRateTable->info[j].dot11Rate & 0x7F)) &&
                    (pRateTable->info[j].valid == TRUE))
                {
                    rcSetValidTxMask(pRc, j, TRUE);
                    hi = A_MAX(hi, j);
		    pSib->rixMap[j] = i;
                }
            }
        }

        /* Get actually valid rate index, previous we get it from rate table,
         * now get rate table which include all working rate, so we need make
         * sure our valid rate table align with working rate */
        mask = pRc->validTxRateMask;
        for (i = 0; i < pRc->rateTableSize; i ++) {
            if (mask & (1 << i)) {
                pRc->validRateIndex[count] = i;
                count ++;
                if (pRateTable->info[i].phy == WLAN_PHY_TURBO) {
                    turboCount ++;
                }
            }
        }

        pRc->maxValidRate = count;
        pRc->maxValidTurboRate = turboCount;
    }

    pRc->rateTableSize = hi + 1;
    pRc->rateMax = A_MIN(hi, pRateTable->initialRateMax);

    ASSERT(pRc->rateTableSize <= MAX_TX_RATE_TBL);
}