/* * 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 }
/* * 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); }