1 #include <adf_os_types.h>
2 #include <adf_os_dma.h>
3 #include <adf_os_timer.h>
4 #include <adf_os_lock.h>
6 #include <adf_os_mem.h>
7 #include <adf_os_module.h>
8 #include <adf_os_pci.h>
9 #include <adf_os_util.h>
10 #include <adf_os_stdtypes.h>
11 #include <adf_os_defer.h>
12 #include <adf_os_atomic.h>
15 #include <adf_net_types.h>
17 #include <ieee80211_var.h>
19 #include <if_athvar.h>
23 #include "ratectrl11n.h"
25 INLINE A_RSSI median(A_RSSI a, A_RSSI b, A_RSSI c);
27 static void ath_rate_newassoc_11n(struct ath_softc_tgt *sc, struct ath_node_target *an, int isnew,
28 unsigned int capflag, struct ieee80211_rate *rs);
31 static void ath_rate_tx_complete_11n(struct ath_softc_tgt *sc, struct ath_node_target *an,
32 struct ath_tx_desc *ds,
33 struct ath_rc_series rcs[], int nframes,
36 static void ath_rate_findrate_11n(struct ath_softc_tgt *sc,
37 struct ath_node_target *an,
43 struct ath_rc_series series[],
47 rcSortValidRates(const RATE_TABLE_11N *pRateTable, TX_RATE_CTRL *pRc)
51 for (i=pRc->maxValidRate-1; i > 0; i--) {
52 for (j=0; j <= i-1; j++) {
54 if (pRateTable->info[pRc->validRateIndex[j]].rateKbps >
55 pRateTable->info[pRc->validRateIndex[j+1]].rateKbps)
58 if (pRateTable->info[pRc->validRateIndex[j]].userRateKbps >
59 pRateTable->info[pRc->validRateIndex[j+1]].userRateKbps)
63 tmp = pRc->validRateIndex[j];
64 pRc->validRateIndex[j] = pRc->validRateIndex[j+1];
65 pRc->validRateIndex[j+1] = tmp;
71 /* Access functions for validTxRateMask */
74 rcInitValidTxMask(TX_RATE_CTRL *pRc)
78 for (i = 0; i < pRc->rateTableSize; i++) {
79 pRc->validRateIndex[i] = FALSE;
84 rcSetValidTxMask(TX_RATE_CTRL *pRc, A_UINT8 index, A_BOOL validTxRate)
86 ASSERT(index < pRc->rateTableSize);
87 pRc->validRateIndex[index] = validTxRate ? TRUE : FALSE;
92 rcIsValidTxMask(TX_RATE_CTRL *pRc, A_UINT8 index)
94 ASSERT(index < pRc->rateTableSize);
95 return (pRc->validRateIndex[index]);
98 /* Iterators for validTxRateMask */
100 rcGetNextValidTxRate(const RATE_TABLE_11N *pRateTable, TX_RATE_CTRL *pRc,
101 A_UINT8 curValidTxRate, A_UINT8 *pNextIndex)
105 for (i = 0; i < pRc->maxValidRate-1; i++) {
106 if (pRc->validRateIndex[i] == curValidTxRate) {
107 *pNextIndex = pRc->validRateIndex[i+1];
112 /* No more valid rates */
119 rcGetNextLowerValidTxRate(const RATE_TABLE_11N *pRateTable, TX_RATE_CTRL *pRc,
120 A_UINT8 curValidTxRate, A_UINT8 *pNextIndex)
124 for (i = 1; i < pRc->maxValidRate ; i++) {
125 if (pRc->validRateIndex[i] == curValidTxRate) {
126 *pNextIndex = pRc->validRateIndex[i-1];
134 /* Return true only for single stream */
137 rcIsValidPhyRate(A_UINT32 phy, A_UINT32 capflag, A_BOOL ignoreCW)
139 if (WLAN_RC_PHY_HT(phy) && !(capflag & WLAN_RC_HT_FLAG)) {
143 if (WLAN_RC_PHY_DS(phy) && !(capflag & WLAN_RC_DS_FLAG)) {
146 if (WLAN_RC_PHY_SGI(phy) && !(capflag & WLAN_RC_HT40_SGI_FLAG)) {
150 if (!ignoreCW && WLAN_RC_PHY_HT(phy)) {
151 if (WLAN_RC_PHY_40(phy) && !(capflag & WLAN_RC_40_FLAG)) {
155 if (!WLAN_RC_PHY_40(phy) && (capflag & WLAN_RC_40_FLAG)) {
164 * Initialize the Valid Rate Index from valid entries in Rate Table
166 static A_UINT8 rcSibInitValidRates(const RATE_TABLE_11N *pRateTable,
169 PHY_STATE_CTRL *pPhyStateCtrl)
172 A_UINT8 singleStream = (capflag & WLAN_RC_DS_FLAG) ? 0 : 1;
175 for (i = 0; i < pRateTable->rateCount; i++) {
177 valid = pRateTable->info[i].validSingleStream;
179 valid = pRateTable->info[i].valid;
183 A_UINT32 phy = pRateTable->info[i].phy;
185 if (!rcIsValidPhyRate(phy, capflag, FALSE))
188 pPhyStateCtrl->validPhyRateIndex[phy][pPhyStateCtrl->validPhyRateCount[phy]] = i;
189 pPhyStateCtrl->validPhyRateCount[phy] += 1;
191 rcSetValidTxMask(pRc, i, TRUE);
201 * Initialize the Valid Rate Index from Rate Set
204 rcSibSetValidRates(const RATE_TABLE_11N *pRateTable,
206 struct ieee80211_rateset *pRateSet,
208 struct ath_node_target *an,
209 PHY_STATE_CTRL *pPhyStateCtrl)
211 A_UINT8 i, j, hi = 0;
212 A_UINT8 singleStream = (capflag & WLAN_RC_DS_FLAG) ? 0 : 1;
214 struct atheros_node *pSib = ATH_NODE_ATHEROS(an);
216 /* Use intersection of working rates and valid rates */
217 for (i = 0; i < pRateSet->rs_nrates; i++) {
218 for (j = 0; j < pRateTable->rateCount; j++) {
219 A_UINT32 phy = pRateTable->info[j].phy;
223 valid = pRateTable->info[j].validSTBC;
224 } else if (singleStream) {
228 valid = pRateTable->info[j].validSingleStream;
230 valid = pRateTable->info[j].valid;
234 * We allow a rate only if its valid and the capflag matches one of
235 * the validity (TRUE/TRUE_20/TRUE_40) flags
238 if (((pRateSet->rs_rates[i] & 0x7F) ==
239 (pRateTable->info[j].dot11Rate & 0x7F))
240 && ((valid & WLAN_RC_CAP_MODE(capflag)) ==
241 WLAN_RC_CAP_MODE(capflag)) && !WLAN_RC_PHY_HT(phy)) {
242 if (!rcIsValidPhyRate(phy, capflag, FALSE))
245 pPhyStateCtrl->validPhyRateIndex[phy][pPhyStateCtrl->validPhyRateCount[phy]] = j;
246 pPhyStateCtrl->validPhyRateCount[phy] += 1;
248 rcSetValidTxMask(pRc, j, TRUE);
258 rcSibSetValidHtRates(const RATE_TABLE_11N *pRateTable,
262 struct ath_node_target *an,
263 PHY_STATE_CTRL *pPhyStateCtrl)
265 A_UINT8 i, j, hi = 0;
266 A_UINT8 singleStream = (capflag & WLAN_RC_DS_FLAG) ? 0 : 1;
268 struct atheros_node *pSib = ATH_NODE_ATHEROS(an);
270 /* Use intersection of working rates and valid rates */
271 for (i = 0; i < ((struct ieee80211_rateset *)pMcsSet)->rs_nrates; i++) {
272 for (j = 0; j < pRateTable->rateCount; j++) {
273 A_UINT32 phy = pRateTable->info[j].phy;
277 valid = pRateTable->info[j].validSTBC;
278 } else if (singleStream) {
282 valid = pRateTable->info[j].validSingleStream;
284 valid = pRateTable->info[j].valid;
287 if (((((struct ieee80211_rateset *)pMcsSet)->rs_rates[i] & 0x7F)
288 != (pRateTable->info[j].dot11Rate & 0x7F))
289 || !WLAN_RC_PHY_HT(phy)
290 || !WLAN_RC_PHY_HT_VALID(valid, capflag)
291 || ((pRateTable->info[j].dot11Rate == 15) &&
293 (capflag & WLAN_RC_WEP_TKIP_FLAG)) )
298 if (!rcIsValidPhyRate(phy, capflag, FALSE))
301 pPhyStateCtrl->validPhyRateIndex[phy][pPhyStateCtrl->validPhyRateCount[phy]] = j;
302 pPhyStateCtrl->validPhyRateCount[phy] += 1;
304 rcSetValidTxMask(pRc, j, TRUE);
313 * Update the SIB's rate control information
315 * This should be called when the supported rates change
316 * (e.g. SME operation, wireless mode change)
318 * It will determine which rates are valid for use.
321 rcSibUpdate_ht(struct ath_softc_tgt *sc, struct ath_node_target *an,
322 A_UINT32 capflag, A_BOOL keepState, struct ieee80211_rate *pRateSet)
324 RATE_TABLE_11N *pRateTable = 0;
325 struct atheros_node *pSib = ATH_NODE_ATHEROS(an);
326 struct atheros_softc *asc = (struct atheros_softc*)sc->sc_rc;
327 A_UINT8 *phtMcs = (A_UINT8*)&pRateSet->htrates;
328 TX_RATE_CTRL *pRc = (TX_RATE_CTRL *)(pSib);
329 PHY_STATE_CTRL mPhyCtrlState;
331 A_UINT8 i, j, k, hi = 0, htHi = 0;
333 pRateTable = (RATE_TABLE_11N*)asc->hwRateTable[sc->sc_curmode];
335 /* Initial rate table size. Will change depending on the working rate set */
336 pRc->rateTableSize = MAX_TX_RATE_TBL;
338 /* Initialize thresholds according to the global rate table */
339 for (i = 0 ; (i < pRc->rateTableSize) && (!keepState); i++) {
340 pRc->state[i].per = 0;
343 /* Determine the valid rates */
344 rcInitValidTxMask(pRc);
346 for (i = 0; i < WLAN_RC_PHY_MAX; i++) {
347 for (j = 0; j < MAX_TX_RATE_PHY; j++) {
348 mPhyCtrlState.validPhyRateIndex[i][j] = 0;
350 mPhyCtrlState.validPhyRateCount[i] = 0;
353 pRc->rcPhyMode = (capflag & WLAN_RC_40_FLAG);
355 if (pRateSet == NULL || !pRateSet->rates.rs_nrates) {
356 /* No working rate, just initialize valid rates */
357 hi = rcSibInitValidRates(pRateTable, pRc, capflag, &mPhyCtrlState);
359 /* Use intersection of working rates and valid rates */
360 hi = rcSibSetValidRates(pRateTable, pRc, &(pRateSet->rates),
361 capflag, an, &mPhyCtrlState);
363 if (capflag & WLAN_RC_HT_FLAG) {
364 htHi = rcSibSetValidHtRates(pRateTable, pRc, phtMcs,
365 capflag, an, &mPhyCtrlState);
368 hi = A_MAX(hi, htHi);
371 pRc->rateTableSize = hi + 1;
374 ASSERT(pRc->rateTableSize <= MAX_TX_RATE_TBL);
376 for (i = 0, k = 0; i < WLAN_RC_PHY_MAX; i++) {
377 for (j = 0; j < mPhyCtrlState.validPhyRateCount[i]; j++) {
378 pRc->validRateIndex[k++] = mPhyCtrlState.validPhyRateIndex[i][j];
381 if (!rcIsValidPhyRate(i, pRateTable->initialRateMax, TRUE) ||
382 !mPhyCtrlState.validPhyRateCount[i])
385 pRc->rateMaxPhy = mPhyCtrlState.validPhyRateIndex[i][j-1];
388 ASSERT(pRc->rateTableSize <= MAX_TX_RATE_TBL);
389 ASSERT(k <= MAX_TX_RATE_TBL);
391 pRc->rateMaxPhy = pRc->validRateIndex[k-4];
392 pRc->maxValidRate = k;
394 rcSortValidRates(pRateTable, pRc);
398 rcSibUpdate_11n(struct ath_softc_tgt *sc, struct ath_node_target *pSib,
399 A_UINT32 capflag, A_BOOL keepState, struct ieee80211_rate *pRateSet)
403 ((capflag & ATH_RC_DS_FLAG) ? WLAN_RC_DS_FLAG : 0) |
404 ((capflag & ATH_RC_HT40_SGI_FLAG) ? WLAN_RC_HT40_SGI_FLAG : 0) |
405 ((capflag & ATH_RC_HT_FLAG) ? WLAN_RC_HT_FLAG : 0) |
406 ((capflag & ATH_RC_CW40_FLAG) ? WLAN_RC_40_FLAG : 0) |
407 ((capflag & ATH_RC_TX_STBC_FLAG) ? WLAN_RC_STBC_FLAG : 0),
413 * Return the median of three numbers
415 INLINE A_RSSI median(A_RSSI a, A_RSSI b, A_RSSI c)
437 rcRateFind_ht(struct ath_softc_tgt *sc, struct atheros_node *pSib,
438 const RATE_TABLE_11N *pRateTable, A_BOOL probeAllowed, A_BOOL *isProbing)
441 A_UINT32 bestThruput, thisThruput;
443 A_UINT8 rate, nextRate, bestRate;
444 A_RSSI rssiLast, rssiReduce = 0;
445 A_UINT8 maxIndex, minIndex;
447 TX_RATE_CTRL *pRc = NULL;
449 pRc = (TX_RATE_CTRL *)(pSib ? (pSib) : NULL);
454 * Age (reduce) last ack rssi based on how old it is.
455 * The bizarre numbers are so the delta is 160msec,
456 * meaning we divide by 16.
457 * 0msec <= dt <= 25msec: don't derate
458 * 25msec <= dt <= 185msec: derate linearly from 0 to 10dB
459 * 185msec <= dt: derate by 10dB
462 nowMsec = A_MS_TICKGET();
463 dt = nowMsec - pRc->rssiTime;
466 * Now look up the rate in the rssi table and return it.
467 * If no rates match then we return 0 (lowest rate)
471 maxIndex = pRc->maxValidRate-1;
477 * Try the higher rate first. It will reduce memory moving time
478 * if we have very good channel characteristics.
480 for (index = maxIndex; index >= minIndex ; index--) {
483 rate = pRc->validRateIndex[index];
484 if (rate > pRc->rateMaxPhy) {
488 /* if the best throughput is already larger than the userRateKbps..
489 * then we could skip of rest of calculation..
491 if( bestThruput >= pRateTable->info[rate].userRateKbps)
495 * For TCP the average collision rate is around 11%,
496 * so we ignore PERs less than this. This is to
497 * prevent the rate we are currently using (whose
498 * PER might be in the 10-15 range because of TCP
499 * collisions) looking worse than the next lower
500 * rate whose PER has decayed close to 0. If we
501 * used to next lower rate, its PER would grow to
502 * 10-15 and we would be worse off then staying
503 * at the current rate.
505 perThres = pRc->state[rate].per;
506 if ( perThres < 12 ) {
510 thisThruput = pRateTable->info[rate].userRateKbps * (100 - perThres);
511 if (bestThruput <= thisThruput) {
512 bestThruput = thisThruput;
520 * Must check the actual rate (rateKbps) to account for non-monoticity of
524 if (rate >= pRc->rateMaxPhy && probeAllowed) {
525 rate = pRc->rateMaxPhy;
527 /* Probe the next allowed phy state */
528 /* FIXME: Check to make sure ratMax is checked properly */
529 if (rcGetNextValidTxRate( pRateTable, pRc, rate, &nextRate) &&
530 (nowMsec - pRc->probeTime > pRateTable->probeInterval) &&
531 (pRc->hwMaxRetryPktCnt >= 1))
534 pRc->probeRate = rate;
535 pRc->probeTime = nowMsec;
536 pRc->hwMaxRetryPktCnt = 0;
543 * Make sure rate is not higher than the allowed maximum.
544 * We should also enforce the min, but I suspect the min is
545 * normally 1 rather than 0 because of the rate 9 vs 6 issue
548 if (rate > (pRc->rateTableSize - 1)) {
549 rate = pRc->rateTableSize - 1;
552 /* record selected rate, which is used to decide if we want to do fast frame */
553 if (!(*isProbing) && pSib) {
554 pSib->lastRateKbps = pRateTable->info[rate].rateKbps;
555 ((struct atheros_softc*)sc->sc_rc)->currentTxRateKbps = pSib->lastRateKbps;
556 ((struct atheros_softc*)sc->sc_rc)->currentTxRateIndex = rate;
563 rcRateSetseries(const RATE_TABLE_11N *pRateTable ,
564 struct ath_rc_series *series,
565 A_UINT8 tries, A_UINT8 rix,
566 A_BOOL rtsctsenable, A_UINT32 chainmask,int stbc)
568 series->tries = tries;
569 series->flags = (rtsctsenable? ATH_RC_RTSCTS_FLAG : 0) |
570 (WLAN_RC_PHY_DS(pRateTable->info[rix].phy) ? ATH_RC_DS_FLAG : 0) |
571 (WLAN_RC_PHY_40(pRateTable->info[rix].phy) ? ATH_RC_CW40_FLAG : 0) |
572 (WLAN_RC_PHY_SGI(pRateTable->info[rix].phy) ? ATH_RC_HT40_SGI_FLAG : 0);
575 /* For now, only single stream STBC is supported */
576 if (pRateTable->info[rix].rateCode >= 0x80 &&
577 pRateTable->info[rix].rateCode <= 0x87)
579 series->flags |= ATH_RC_TX_STBC_FLAG;
583 series->rix = pRateTable->info[rix].baseIndex;
584 series->max4msframelen = pRateTable->info[rix].max4msframelen;
585 series->txrateKbps = pRateTable->info[rix].rateKbps;
587 /* If the hardware is capable of multiple transmit chains (chainmask is 3, 5 or 7),
588 * then choose the number of transmit chains dynamically based on entries in the rate table.
590 #ifndef ATH_ENABLE_WLAN_FOR_K2
592 series->tx_chainmask = pRateTable->info[rix].txChainMask_3ch;
593 else if(chainmask == 1)
594 series->tx_chainmask = 1;
596 series->tx_chainmask = pRateTable->info[rix].txChainMask_2ch; /*Chainmask is 3 or 5*/
598 series->tx_chainmask = 1;
603 rcRateGetIndex(struct ath_softc_tgt *sc, struct ath_node_target *an,
604 const RATE_TABLE_11N *pRateTable ,
605 A_UINT8 rix, A_UINT16 stepDown, A_UINT16 minRate)
609 struct atheros_node *pSib = ATH_NODE_ATHEROS(an);
610 TX_RATE_CTRL *pRc = (TX_RATE_CTRL *)(pSib);
613 for (j = RATE_TABLE_11N_SIZE; j > 0; j-- ) {
614 if (rcGetNextLowerValidTxRate(pRateTable, pRc, rix, &nextIndex)) {
621 for (j = stepDown; j > 0; j-- ) {
622 if (rcGetNextLowerValidTxRate(pRateTable, pRc, rix, &nextIndex)) {
633 void rcRateFind_11n(struct ath_softc_tgt *sc, struct ath_node_target *an,
634 int numTries, int numRates, int stepDnInc,
635 unsigned int rcflag, struct ath_rc_series series[], int *isProbe)
638 A_UINT8 tryPerRate = 0;
639 struct atheros_softc *asc = (struct atheros_softc*)sc->sc_rc;
640 RATE_TABLE_11N *pRateTable = (RATE_TABLE_11N *)asc->hwRateTable[sc->sc_curmode];
641 struct atheros_node *asn = ATH_NODE_ATHEROS(an);
647 rix = rcRateFind_ht(sc, asn, pRateTable, (rcflag & ATH_RC_PROBE_ALLOWED) ? 1 : 0,
651 if ((rcflag & ATH_RC_PROBE_ALLOWED) && (*isProbe)) {
652 /* set one try for probe rates. For the probes don't enable rts */
653 rcRateSetseries(pRateTable, &series[i++], 1, nrix,
654 FALSE, asc->tx_chainmask, asn->stbc);
657 * Get the next tried/allowed rate. No RTS for the next series
658 * after the probe rate
660 nrix = rcRateGetIndex( sc, an, pRateTable, nrix, 1, FALSE);
663 tryPerRate = (numTries/numRates);
665 /* Set the choosen rate. No RTS for first series entry. */
666 rcRateSetseries(pRateTable, &series[i++], tryPerRate,
667 nrix, FALSE, asc->tx_chainmask, asn->stbc);
669 /* Fill in the other rates for multirate retry */
670 for (; i < numRates; i++) {
674 tryNum = ((i + 1) == numRates) ? numTries - (tryPerRate * i) : tryPerRate ;
675 minRate = (((i + 1) == numRates) && (rcflag & ATH_RC_MINRATE_LASTRATE)) ? 1 : 0;
677 nrix = rcRateGetIndex(sc, an, pRateTable, nrix, stepDnInc, minRate);
679 /* All other rates in the series have RTS enabled */
680 rcRateSetseries(pRateTable, &series[i], tryNum,
681 nrix, TRUE, asc->tx_chainmask, asn->stbc);
686 * Change rate series to enable aggregation when operating at lower MCS rates.
687 * When first rate in series is MCS2 in HT40 @ 2.4GHz, series should look like:
688 * {MCS2, MCS1, MCS0, MCS0}.
689 * When first rate in series is MCS3 in HT20 @ 2.4GHz, series should look like:
690 * {MCS3, MCS2, MCS1, MCS1}
691 * So, set fourth rate in series to be same as third one for above conditions.
693 if (sc->sc_curmode == IEEE80211_MODE_11NG) {
694 dot11Rate = pRateTable->info[rix].dot11Rate;
695 phy = pRateTable->info[rix].phy;
697 ((dot11Rate == 2 && phy == WLAN_RC_PHY_HT_40_SS) ||
698 (dot11Rate == 3 && phy == WLAN_RC_PHY_HT_20_SS)))
700 series[3].rix = series[2].rix;
701 series[3].flags = series[2].flags;
702 series[3].max4msframelen = series[2].max4msframelen;
708 * AP91 Kite: NetGear OTA location-4 downlink.
709 * Enable RTS/CTS at MCS 3-0 for downlink throughput.
711 if (sc->sc_curmode == IEEE80211_MODE_11NG) {
712 dot11Rate = pRateTable->info[rix].dot11Rate;
713 if (dot11Rate <= 3 ) {
714 series[0].flags |= ATH_RC_RTSCTS_FLAG;
720 rcUpdate_ht(struct ath_softc_tgt *sc, struct ath_node_target *an, int txRate,
721 A_BOOL Xretries, int retries, A_UINT8 curTxAnt,
722 A_UINT16 nFrames, A_UINT16 nBad)
725 A_UINT32 nowMsec = A_MS_TICKGET();
726 A_BOOL stateChange = FALSE;
729 struct atheros_node *pSib = ATH_NODE_ATHEROS(an);
730 struct atheros_softc *asc = (struct atheros_softc*)sc->sc_rc;
731 RATE_TABLE_11N *pRateTable = (RATE_TABLE_11N *)asc->hwRateTable[sc->sc_curmode];
732 u_int32_t txRateKbps;
734 static A_UINT32 nRetry2PerLookup[10] = {
750 pRc = (TX_RATE_CTRL *)(pSib);
752 ASSERT(retries >= 0 && retries < MAX_TX_RETRIES);
759 lastPer = pRc->state[txRate].per;
762 /* Update the PER. */
764 pRc->state[txRate].per += 30;
765 if (pRc->state[txRate].per > 100) {
766 pRc->state[txRate].per = 100;
771 count = sizeof(nRetry2PerLookup) / sizeof(nRetry2PerLookup[0]);
772 if (retries >= count) {
776 /* new_PER = 7/8*old_PER + 1/8*(currentPER) */
777 pRc->state[txRate].per = (A_UINT8)(pRc->state[txRate].per -
778 (pRc->state[txRate].per / 8) + ((100) / 8));
781 /* Xretries == 1 or 2 */
783 if (pRc->probeRate == txRate)
789 * Update the PER. Make sure it doesn't index out of array's bounds.
791 count = sizeof(nRetry2PerLookup) / sizeof(nRetry2PerLookup[0]);
792 if (retries >= count) {
797 /* new_PER = 7/8*old_PER + 1/8*(currentPER) */
799 * Assuming that nFrames is not 0. The current PER
800 * from the retries is 100 * retries / (retries+1),
801 * since the first retries attempts failed, and the
802 * next one worked. For the one that worked, nBad
803 * subframes out of nFrames wored, so the PER for
804 * that part is 100 * nBad / nFrames, and it contributes
805 * 100 * nBad / (nFrames * (retries+1)) to the above
806 * PER. The expression below is a simplified version
807 * of the sum of these two terms.
810 pRc->state[txRate].per = (A_UINT8)(pRc->state[txRate].per -
811 (pRc->state[txRate].per / 8) +
812 ((100*(retries*nFrames + nBad)/(nFrames*(retries+1))) / 8));
814 /* new_PER = 7/8*old_PER + 1/8*(currentPER) */
816 pRc->state[txRate].per = (A_UINT8)(pRc->state[txRate].per -
817 (pRc->state[txRate].per / 8) + (nRetry2PerLookup[retries] / 8));
821 * If we got at most one retry then increase the max rate if
822 * this was a probe. Otherwise, ignore the probe.
825 if (pRc->probeRate && pRc->probeRate == txRate) {
826 if (retries > 0 || 2 * nBad > nFrames) {
828 * Since we probed with just a single attempt,
829 * any retries means the probe failed. Also,
830 * if the attempt worked, but more than half
831 * the subframes were bad then also consider
832 * the probe a failure.
836 pRc->rateMaxPhy = pRc->probeRate;
838 if (pRc->state[pRc->probeRate].per > 30) {
839 pRc->state[pRc->probeRate].per = 20;
845 * Since this probe succeeded, we allow the next probe
846 * twice as soon. This allows the maxRate to move up
847 * faster if the probes are succesful.
849 pRc->probeTime = nowMsec - pRateTable->probeInterval / 2;
855 * Don't update anything. We don't know if this was because
856 * of collisions or poor signal.
858 * Later: if rssiAck is close to pRc->state[txRate].rssiThres
859 * and we see lots of retries, then we could increase
860 * pRc->state[txRate].rssiThres.
862 pRc->hwMaxRetryPktCnt = 0;
865 * It worked with no retries. First ignore bogus (small)
868 if (txRate == pRc->rateMaxPhy && pRc->hwMaxRetryPktCnt < 255) {
869 pRc->hwMaxRetryPktCnt++;
877 ASSERT((pRc->rateMaxPhy >= 0 && pRc->rateMaxPhy <= pRc->rateTableSize &&
878 pRc->rateMaxPhy != INVALID_RATE_MAX));
881 * If this rate looks bad (high PER) then stop using it for
882 * a while (except if we are probing).
884 if (pRc->state[txRate].per >= 55 && txRate > 0 &&
885 pRateTable->info[txRate].rateKbps <=
886 pRateTable->info[pRc->rateMaxPhy].rateKbps)
888 rcGetNextLowerValidTxRate(pRateTable, pRc, (A_UINT8) txRate,
891 /* Don't probe for a little while. */
892 pRc->probeTime = nowMsec;
895 /* Make sure the rates below this have lower PER */
896 /* Monotonicity is kept only for rates below the current rate. */
897 if (pRc->state[txRate].per < lastPer) {
898 for (rate = txRate - 1; rate >= 0; rate--) {
899 if (pRateTable->info[rate].phy != pRateTable->info[txRate].phy) {
903 if (pRc->state[rate].per > pRc->state[rate+1].per) {
904 pRc->state[rate].per = pRc->state[rate+1].per;
909 /* Maintain monotonicity for rates above the current rate*/
910 for (rate = txRate; rate < pRc->rateTableSize - 1; rate++) {
911 if (pRc->state[rate+1].per < pRc->state[rate].per) {
912 pRc->state[rate+1].per = pRc->state[rate].per;
916 /* Every so often, we reduce the thresholds and PER (different for CCK and OFDM). */
917 if (nowMsec - pRc->perDownTime >= pRateTable->rssiReduceInterval) {
918 for (rate = 0; rate < pRc->rateTableSize; rate++) {
919 pRc->state[rate].per = 7*pRc->state[rate].per/8;
922 pRc->perDownTime = nowMsec;
927 * This routine is called by the Tx interrupt service routine to give
928 * the status of previous frames.
930 void rcUpdate_11n(struct ath_softc_tgt *sc, struct ath_node_target *an,
932 int finalTSIdx, int Xretries,
933 struct ath_rc_series rcs[], int nFrames,
934 int nBad, int long_retry)
938 struct atheros_softc *asc = (struct atheros_softc*)sc->sc_rc;
939 RATE_TABLE_11N *pRateTable = (RATE_TABLE_11N *)asc->hwRateTable[sc->sc_curmode];
940 struct atheros_node *pSib = ATH_NODE_ATHEROS(an);
941 TX_RATE_CTRL *pRc = (TX_RATE_CTRL *)(pSib);
949 ASSERT (rcs[0].tries != 0);
952 * If the first rate is not the final index, there are intermediate rate failures
955 if (finalTSIdx != 0) {
957 /* Process intermediate rates that failed.*/
958 for (series = 0; series < finalTSIdx ; series++) {
959 if (rcs[series].tries != 0) {
960 flags = rcs[series].flags;
961 /* If HT40 and we have switched mode from 40 to 20 => don't update */
962 if ((flags & ATH_RC_CW40_FLAG) &&
963 (pRc->rcPhyMode != (flags & ATH_RC_CW40_FLAG))) {
966 if ((flags & ATH_RC_CW40_FLAG) && (flags & ATH_RC_HT40_SGI_FLAG)) {
967 rix = pRateTable->info[rcs[series].rix].htIndex;
968 } else if (flags & ATH_RC_HT40_SGI_FLAG) {
969 rix = pRateTable->info[rcs[series].rix].sgiIndex;
970 } else if (flags & ATH_RC_CW40_FLAG) {
971 rix = pRateTable->info[rcs[series].rix].cw40Index;
973 rix = pRateTable->info[rcs[series].rix].baseIndex;
976 /* FIXME:XXXX, too many args! */
977 rcUpdate_ht(sc, an, rix, Xretries? 1 : 2, rcs[series].tries,
978 curTxAnt, nFrames, nFrames);
983 * Handle the special case of MIMO PS burst, where the second aggregate is sent
984 * out with only one rate and one try. Treating it as an excessive retry penalizes
985 * the rate inordinately.
987 if (rcs[0].tries == 1 && Xretries == 1) {
992 flags = rcs[series].flags;
993 /* If HT40 and we have switched mode from 40 to 20 => don't update */
994 if ((flags & ATH_RC_CW40_FLAG) &&
995 (pRc->rcPhyMode != (flags & ATH_RC_CW40_FLAG))) {
998 if ((flags & ATH_RC_CW40_FLAG) && (flags & ATH_RC_HT40_SGI_FLAG)) {
999 rix = pRateTable->info[rcs[series].rix].htIndex;
1000 } else if (flags & ATH_RC_HT40_SGI_FLAG) {
1001 rix = pRateTable->info[rcs[series].rix].sgiIndex;
1002 } else if (flags & ATH_RC_CW40_FLAG) {
1003 rix = pRateTable->info[rcs[series].rix].cw40Index;
1005 rix = pRateTable->info[rcs[series].rix].baseIndex;
1008 /* FIXME:XXXX, too many args! */
1009 rcUpdate_ht(sc, an, rix, Xretries, long_retry, curTxAnt,
1013 void ath_tx_status_update_rate(struct ath_softc_tgt *sc,
1014 struct ath_rc_series rcs[],
1016 WMI_TXSTATUS_EVENT *txs)
1018 struct atheros_softc *asc = (struct atheros_softc*)sc->sc_rc;
1019 RATE_TABLE_11N *pRateTable = (RATE_TABLE_11N *)asc->hwRateTable[sc->sc_curmode];
1022 if (pRateTable->info[rcs[series].rix].rateCode & 0x80) {
1023 txs->txstatus[txs->cnt].ts_rate |= SM(pRateTable->info[rcs[series].rix].dot11Rate,
1024 ATH9K_HTC_TXSTAT_RATE);
1025 txs->txstatus[txs->cnt].ts_flags |= ATH9K_HTC_TXSTAT_MCS;
1027 if (rcs[series].flags & ATH_RC_CW40_FLAG)
1028 txs->txstatus[txs->cnt].ts_flags |= ATH9K_HTC_TXSTAT_CW40;
1030 if (rcs[series].flags & ATH_RC_HT40_SGI_FLAG)
1031 txs->txstatus[txs->cnt].ts_flags |= ATH9K_HTC_TXSTAT_SGI;
1034 txs->txstatus[txs->cnt].ts_rate |= SM(rcs[series].rix, ATH9K_HTC_TXSTAT_RATE);
1037 if (rcs[series].flags & ATH_RC_RTSCTS_FLAG)
1038 txs->txstatus[txs->cnt].ts_flags |= ATH9K_HTC_TXSTAT_RTC_CTS;
1042 struct ath_ratectrl *
1043 ath_rate_attach(struct ath_softc_tgt *sc)
1045 struct atheros_softc *asc;
1047 asc = adf_os_mem_alloc(sizeof(struct atheros_softc));
1051 adf_os_mem_set(asc, 0, sizeof(struct atheros_softc));
1052 asc->arc.arc_space = sizeof(struct atheros_node);
1054 ar5416AttachRateTables(asc);
1056 asc->tx_chainmask = 1;
1062 ath_rate_detach(struct ath_ratectrl *rc)
1064 adf_os_mem_free(rc);
1068 ath_rate_findrate(struct ath_softc_tgt *sc,
1069 struct ath_node_target *an,
1075 unsigned int rcflag,
1076 struct ath_rc_series series[],
1079 struct ieee80211vap *vap = an->ni.ni_vap;
1080 struct atheros_node *oan = ATH_NODE_ATHEROS(an);
1081 struct atheros_softc *asc = (struct atheros_softc *) sc->sc_rc;
1082 RATE_TABLE *pRateTable = (RATE_TABLE *)asc->hwRateTable[sc->sc_curmode];
1083 u_int32_t *retrySched;
1087 if (!numRates || !numTries) {
1091 ath_rate_findrate_11n(sc, an, frameLen, numTries, numRates, stepDnInc,
1092 rcflag, series, isProbe);
1095 #define MS(_v, _f) (((_v) & _f) >> _f##_S)
1098 ath_rate_tx_complete(struct ath_softc_tgt *sc,
1099 struct ath_node_target *an,
1100 struct ath_tx_desc *ds,
1101 struct ath_rc_series rcs[],
1102 int nframes, int nbad)
1104 struct atheros_softc *asc = (struct atheros_softc *) sc->sc_rc;
1105 const RATE_TABLE *pRateTable = (RATE_TABLE *)asc->hwRateTable[sc->sc_curmode];
1106 u_int8_t txRate = ds->ds_txstat.ts_rate &~ HAL_TXSTAT_ALTRATE;
1108 ath_rate_tx_complete_11n(sc, an, ds, rcs, nframes, nbad);
1112 ath_rate_newassoc(struct ath_softc_tgt *sc, struct ath_node_target *an, int isnew,
1113 unsigned int capflag, struct ieee80211_rate *rs)
1115 ath_rate_newassoc_11n(sc, an, isnew, capflag, rs);
1118 void ath_rate_node_update(struct ath_softc_tgt *sc,
1119 struct ath_node_target *an,
1122 struct ieee80211_rate *rs)
1124 struct ieee80211_node_target *ni = &an->ni;
1126 ath_rate_newassoc(sc, ATH_NODE_TARGET(ni), isnew, capflag, rs);
1129 static int init_ath_rate_atheros(void);
1130 static void exit_ath_rate_atheros(void);
1133 ath_rate_newstate(struct ath_softc_tgt *sc,
1134 struct ieee80211vap_target *vap,
1135 enum ieee80211_state state,
1137 struct ieee80211_rate *rs)
1139 struct ieee80211_node_target *ni = vap->iv_bss;
1140 struct atheros_softc *asc = (struct atheros_softc *) sc->sc_rc;
1142 asc->tx_chainmask = sc->sc_ic.ic_tx_chainmask;
1143 ath_rate_newassoc(sc, ni, 1, capflag, rs);
1147 ath_rate_findrate_11n(struct ath_softc_tgt *sc,
1148 struct ath_node_target *an,
1153 unsigned int rcflag,
1154 struct ath_rc_series series[],
1157 struct ieee80211vap *vap = an->ni.ni_vap;
1158 struct atheros_node *oan = ATH_NODE_ATHEROS(an);
1161 if (!numRates || !numTries) {
1165 rcRateFind_11n(sc, an, numTries, numRates, stepDnInc, rcflag, series, isProbe);
1169 ath_rate_tx_complete_11n(struct ath_softc_tgt *sc,
1170 struct ath_node_target *an,
1171 struct ath_tx_desc *ds,
1172 struct ath_rc_series rcs[],
1173 int nframes, int nbad)
1175 int finalTSIdx = ds->ds_txstat.ts_rate;
1178 if ((ds->ds_txstat.ts_status & HAL_TXERR_XRETRY) ||
1179 (ds->ds_txstat.ts_status & HAL_TXERR_FIFO) ||
1180 (ds->ds_txstat.ts_flags & HAL_TX_DATA_UNDERRUN) ||
1181 (ds->ds_txstat.ts_flags & HAL_TX_DELIM_UNDERRUN)) {
1185 rcUpdate_11n(sc, an,
1186 ds->ds_txstat.ts_antenna, finalTSIdx,
1187 tx_status, rcs, nframes , nbad,
1188 ds->ds_txstat.ts_longretry);
1192 ath_rate_newassoc_11n(struct ath_softc_tgt *sc, struct ath_node_target *an, int isnew,
1193 unsigned int capflag, struct ieee80211_rate *rs)
1195 struct ieee80211vap *vap = an->ni.ni_vap;
1198 struct atheros_node *oan = ATH_NODE_ATHEROS(an);
1200 oan->htcap = ((capflag & ATH_RC_DS_FLAG) ? WLAN_RC_DS_FLAG : 0) |
1201 ((capflag & ATH_RC_HT40_SGI_FLAG) ? WLAN_RC_HT40_SGI_FLAG : 0) |
1202 ((capflag & ATH_RC_HT_FLAG) ? WLAN_RC_HT_FLAG : 0) |
1203 ((capflag & ATH_RC_CW40_FLAG) ? WLAN_RC_40_FLAG : 0) |
1204 ((capflag & ATH_RC_WEP_TKIP_FLAG) ? WLAN_RC_WEP_TKIP_FLAG : 0);
1206 #ifdef MAGPIE_MERLIN
1207 /* Rx STBC is a 2-bit mask. Needs to convert from ath definition to wlan definition. */
1209 oan->htcap |= (((capflag & ATH_RC_RX_STBC_FLAG) >> ATH_RC_RX_STBC_FLAG_S)
1210 << WLAN_RC_STBC_FLAG_S);
1212 /* If only one chain is enabled, do not do stbc. */
1213 if (sc->sc_txstbcsupport) {
1214 oan->stbc = (capflag & ATH_RC_RX_STBC_FLAG) >> ATH_RC_RX_STBC_FLAG_S;
1220 rcSibUpdate_11n(sc, an, oan->htcap, 0, rs);
1224 void ath_rate_mcs2rate(struct ath_softc_tgt *sc,a_uint8_t sgi, a_uint8_t ht40,
1225 a_uint8_t rateCode, a_uint32_t *txrate, a_uint32_t *rxrate)
1228 struct atheros_softc *asc = (struct atheros_softc*)sc->sc_rc;
1229 RATE_TABLE_11N *pRateTable = (RATE_TABLE_11N *)asc->hwRateTable[sc->sc_curmode];
1230 a_uint32_t rateKbps = 0;
1232 *txrate = asc->currentTxRateKbps;
1234 /* look 11NA table for rateKbps*/
1235 for (idx = 0; idx < pRateTable->rateCount && !rateKbps; ++idx) {
1236 if (pRateTable->info[idx].rateCode == rateCode) {
1238 if(pRateTable->info[idx].valid == TRUE_40 &&
1239 pRateTable->info[idx].phy == WLAN_RC_PHY_HT_40_DS_HGI)
1240 rateKbps = pRateTable->info[idx].rateKbps;
1242 if (pRateTable->info[idx].valid == TRUE_40)/* HT40 only*/
1243 rateKbps = pRateTable->info[idx].rateKbps;
1245 if (pRateTable->info[idx].valid != FALSE)
1246 rateKbps = pRateTable->info[idx].rateKbps;