コード例 #1
0
ファイル: ratectrl.c プロジェクト: KHATEEBNSIT/AP
/*
 *  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
}
コード例 #2
0
/* 
 * Initialize the Valid Rate Index from Rate Set 
 */
static A_UINT8
rcSibSetValidRates(const RATE_TABLE_11N *pRateTable,
		   TX_RATE_CTRL *pRc, 
                   struct ieee80211_rateset *pRateSet,
		   A_UINT32 capflag,
		   struct ath_node_target *an,
		   PHY_STATE_CTRL *pPhyStateCtrl)
{
	A_UINT8 i, j, hi = 0;
	A_UINT8 singleStream = (capflag & WLAN_RC_DS_FLAG) ? 0 : 1;
	A_UINT32 valid;
	struct atheros_node *pSib = ATH_NODE_ATHEROS(an);
       
	/* Use intersection of working rates and valid rates */
	for (i = 0; i < pRateSet->rs_nrates; i++) {
		for (j = 0; j < pRateTable->rateCount; j++) {
			A_UINT32 phy = pRateTable->info[j].phy;

#ifdef MAGPIE_MERLIN
			if (pSib->stbc) {
				valid = pRateTable->info[j].validSTBC;
			} else if (singleStream) {
#else
			if (singleStream) {
#endif            
				valid = pRateTable->info[j].validSingleStream;
			} else {
				valid = pRateTable->info[j].valid;
			}
        
			/*
			 * We allow a rate only if its valid and the capflag matches one of
			 * the validity (TRUE/TRUE_20/TRUE_40) flags
			 */

			if (((pRateSet->rs_rates[i] & 0x7F) == 
			     (pRateTable->info[j].dot11Rate & 0x7F))
			    && ((valid & WLAN_RC_CAP_MODE(capflag)) == 
				WLAN_RC_CAP_MODE(capflag)) && !WLAN_RC_PHY_HT(phy)) {
				if (!rcIsValidPhyRate(phy, capflag, FALSE)) 
					continue;

				pPhyStateCtrl->validPhyRateIndex[phy][pPhyStateCtrl->validPhyRateCount[phy]] = j;
				pPhyStateCtrl->validPhyRateCount[phy] += 1;

				rcSetValidTxMask(pRc, j, TRUE);
				hi = A_MAX(hi, j);
			}
		}
	}
  
	return hi;
}

static A_UINT8
rcSibSetValidHtRates(const RATE_TABLE_11N *pRateTable,
		     TX_RATE_CTRL *pRc, 
                     A_UINT8 *pMcsSet,
		     A_UINT32 capflag,
		     struct ath_node_target *an,
		     PHY_STATE_CTRL *pPhyStateCtrl)
{
	A_UINT8 i, j, hi = 0;
	A_UINT8 singleStream = (capflag & WLAN_RC_DS_FLAG) ? 0 : 1;
	A_UINT8 valid;
	struct atheros_node *pSib = ATH_NODE_ATHEROS(an);
    
	/* Use intersection of working rates and valid rates */
	for (i = 0; i <  ((struct ieee80211_rateset *)pMcsSet)->rs_nrates; i++) {
		for (j = 0; j < pRateTable->rateCount; j++) {
			A_UINT32 phy = pRateTable->info[j].phy;

#ifdef MAGPIE_MERLIN
			if (pSib->stbc) {
				valid = pRateTable->info[j].validSTBC;
			} else if (singleStream) {
#else
			if (singleStream) {
#endif
				valid = pRateTable->info[j].validSingleStream;
			} else {
				valid = pRateTable->info[j].valid;
			}
                           
			if (((((struct ieee80211_rateset *)pMcsSet)->rs_rates[i] & 0x7F) 
			     != (pRateTable->info[j].dot11Rate & 0x7F)) 
			    || !WLAN_RC_PHY_HT(phy) 
			    || !WLAN_RC_PHY_HT_VALID(valid, capflag)
			    || ((pRateTable->info[j].dot11Rate == 15) && 
				(valid & TRUE_20) && 
				(capflag & WLAN_RC_WEP_TKIP_FLAG)) )
			{
				continue;
			}
    
			if (!rcIsValidPhyRate(phy, capflag, FALSE)) 
				continue;
    
			pPhyStateCtrl->validPhyRateIndex[phy][pPhyStateCtrl->validPhyRateCount[phy]] = j;
			pPhyStateCtrl->validPhyRateCount[phy] += 1;

			rcSetValidTxMask(pRc, j, TRUE);
			hi = A_MAX(hi, j);
		}
	}

	return hi;
}

/*
 *  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.
 */
static void
rcSibUpdate_ht(struct ath_softc_tgt *sc, struct ath_node_target *an,
	       A_UINT32 capflag, A_BOOL keepState, struct ieee80211_rate  *pRateSet)
{
	RATE_TABLE_11N *pRateTable = 0;
	struct atheros_node *pSib = ATH_NODE_ATHEROS(an);
	struct atheros_softc *asc = (struct atheros_softc*)sc->sc_rc;
	A_UINT8 *phtMcs = (A_UINT8*)&pRateSet->htrates;
	TX_RATE_CTRL *pRc = (TX_RATE_CTRL *)(pSib);
	PHY_STATE_CTRL mPhyCtrlState;  

	A_UINT8 i, j, k, hi = 0, htHi = 0;

	pRateTable = (RATE_TABLE_11N*)asc->hwRateTable[sc->sc_curmode];

	/* 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].per       = 0;
	}

	/* Determine the valid rates */
	rcInitValidTxMask(pRc);

	for (i = 0; i < WLAN_RC_PHY_MAX; i++) {
		for (j = 0; j < MAX_TX_RATE_PHY; j++) {
			mPhyCtrlState.validPhyRateIndex[i][j] = 0;
		}   
		mPhyCtrlState.validPhyRateCount[i] = 0;
	}

	pRc->rcPhyMode = (capflag & WLAN_RC_40_FLAG);

	if (pRateSet == NULL || !pRateSet->rates.rs_nrates) {
		/* No working rate, just initialize valid rates */
		hi = rcSibInitValidRates(pRateTable, pRc, capflag, &mPhyCtrlState);
	} else {
		/* Use intersection of working rates and valid rates */
		hi = rcSibSetValidRates(pRateTable, pRc, &(pRateSet->rates),
					capflag, an, &mPhyCtrlState);

		if (capflag & WLAN_RC_HT_FLAG) {
			htHi = rcSibSetValidHtRates(pRateTable, pRc, phtMcs,
						    capflag, an, &mPhyCtrlState);
		}

		hi = A_MAX(hi, htHi);
	}

	pRc->rateTableSize = hi + 1;
	pRc->rateMaxPhy    = 0;
    
	ASSERT(pRc->rateTableSize <= MAX_TX_RATE_TBL);

	for (i = 0, k = 0; i < WLAN_RC_PHY_MAX; i++) {
		for (j = 0; j < mPhyCtrlState.validPhyRateCount[i]; j++) {
			pRc->validRateIndex[k++] = mPhyCtrlState.validPhyRateIndex[i][j];
		}   

		if (!rcIsValidPhyRate(i, pRateTable->initialRateMax, TRUE) ||
		    !mPhyCtrlState.validPhyRateCount[i]) 
			continue;

		pRc->rateMaxPhy = mPhyCtrlState.validPhyRateIndex[i][j-1];	
	}
    
	ASSERT(pRc->rateTableSize <= MAX_TX_RATE_TBL);
	ASSERT(k <= MAX_TX_RATE_TBL);

	pRc->rateMaxPhy = pRc->validRateIndex[k-4];
	pRc->maxValidRate = k;

	rcSortValidRates(pRateTable, pRc);
}
コード例 #3
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);
}