summaryrefslogtreecommitdiff
path: root/cleopatre/devkit/mt7601udrv/rate_ctrl/alg_ags.c
diff options
context:
space:
mode:
Diffstat (limited to 'cleopatre/devkit/mt7601udrv/rate_ctrl/alg_ags.c')
-rw-r--r--cleopatre/devkit/mt7601udrv/rate_ctrl/alg_ags.c1181
1 files changed, 1181 insertions, 0 deletions
diff --git a/cleopatre/devkit/mt7601udrv/rate_ctrl/alg_ags.c b/cleopatre/devkit/mt7601udrv/rate_ctrl/alg_ags.c
new file mode 100644
index 0000000000..bc8343f339
--- /dev/null
+++ b/cleopatre/devkit/mt7601udrv/rate_ctrl/alg_ags.c
@@ -0,0 +1,1181 @@
+/****************************************************************************
+ * Ralink Tech Inc.
+ * Taiwan, R.O.C.
+ *
+ * (c) Copyright 2002, Ralink Technology, Inc.
+ *
+ * All rights reserved. Ralink's source code is an unpublished work and the
+ * use of a copyright notice does not imply otherwise. This source code
+ * contains confidential trade secret material of Ralink Tech. Any attemp
+ * or participation in deciphering, decoding, reverse engineering or in any
+ * way altering the source code is stricitly prohibited, unless the prior
+ * written consent of Ralink Technology, Inc. is obtained.
+ ***************************************************************************/
+
+/****************************************************************************
+
+ Abstract:
+
+ All related AGS (Adaptive Group Switching) function body.
+
+***************************************************************************/
+
+#ifdef AGS_SUPPORT
+
+#include "rt_config.h"
+
+
+/*
+ HT Rate Table format
+ [Item no.] [Mode]* [Mode]** [CurrMCS] [TrainUp] [TrainDown] [downMCS] [upMCS3] [upMCS2] [upMCS1]
+
+ [Mode]*:
+ bit0: STBC -STBC_XXX
+ bit1: Short GI - GI_XXX
+ bit2~3: BW - BW_XXX
+ bit4~bit6: Mode (0:CCK, 1:OFDM, 2:HT Mix, 3:HT GF, 4: VHT) - MODE_XXX
+ bit7: Reserved
+
+ [Mode]**
+ bit0~1: Nss - NSS_XXX (VHT only)
+ bit2~7: Reserved
+*/
+
+/* AGS: 1x1 HT-capable rate table */
+UCHAR AGS1x1HTRateTable[] = {
+ 0x09, 0x08, 0, 0, 0, 0, 0, 0, 0, 0, /* Initial used item after association: the number of rate indexes, the initial mcs */
+ 0x00, 0x21, 0, 0, 30, 101, 0, 16, 8, 1, /* MCS 0 */
+ 0x01, 0x21, 0, 1, 20, 50, 0, 16, 9, 2, /* MCS 1 */
+ 0x02, 0x21, 0, 2, 20, 50, 1, 17, 9, 3, /* MCS 2 */
+ 0x03, 0x21, 0, 3, 15, 50, 2, 17, 10, 4, /* MCS 3 */
+ 0x04, 0x21, 0, 4, 15, 30, 3, 18, 11, 5, /* MCS 4 */
+ 0x05, 0x21, 0, 5, 10, 25, 4, 18, 12, 6, /* MCS 5 */
+ 0x06, 0x21, 0, 6, 8, 14, 5, 19, 12, 7, /* MCS 6 */
+ 0x07, 0x21, 0, 7, 8, 14, 6, 19, 12, 8, /* MCS 7 */
+ 0x08, 0x23, 0, 7, 8, 14, 7, 19, 12, 8, /* MCS 7 + Short GI */
+};
+
+
+/* AGS: 2x2 HT-capable rate table */
+UCHAR AGS2x2HTRateTable[] = {
+ 0x11, 0x10, 0, 0, 0, 0, 0, 0, 0, 0, /* Initial used item after association: the number of rate indexes, the initial mcs */
+ 0x00, 0x21, 0, 0, 30, 101, 0, 16, 8, 1, /* MCS 0 */
+ 0x01, 0x21, 0, 1, 20, 50, 0, 16, 9, 2, /* MCS 1 */
+ 0x02, 0x21, 0, 2, 20, 50, 1, 17, 9, 3, /* MCS 2 */
+ 0x03, 0x21, 0, 3, 15, 50, 2, 17, 10, 4, /* MCS 3 */
+ 0x04, 0x21, 0, 4, 15, 30, 3, 18, 11, 5, /* MCS 4 */
+ 0x05, 0x21, 0, 5, 10, 25, 4, 18, 12, 6, /* MCS 5 */
+ 0x06, 0x21, 0, 6, 8, 14, 5, 19, 12, 7, /* MCS 6 */
+ 0x07, 0x21, 0, 7, 8, 14, 6, 19, 12, 7, /* MCS 7 */
+ 0x08, 0x20, 0, 8, 30, 50, 0, 16, 9, 2, /* MCS 8 */
+ 0x09, 0x20, 0, 9, 20, 50, 8, 17, 10, 4, /* MCS 9 */
+ 0x0A, 0x20, 0, 10, 20, 50, 9, 18, 11, 5, /* MCS 10 */
+ 0x0B, 0x20, 0, 11, 15, 30, 10, 18, 12, 6, /* MCS 11 */
+ 0x0C, 0x20, 0, 12, 15, 30, 11, 20, 13, 12, /* MCS 12 */
+ 0x0D, 0x20, 0, 13, 8, 20, 12, 20, 14, 13, /* MCS 13 */
+ 0x0E, 0x20, 0, 14, 8, 18, 13, 21, 15, 14, /* MCS 14 */
+ 0x0F, 0x20, 0, 15, 8, 25, 14, 21, 16, 15, /* MCS 15 */
+ 0x10, 0x22, 0, 15, 8, 25, 15, 21, 16, 16, /* MCS 15 + Short GI */
+};
+
+
+/* AGS: 3x3 HT-capable rate table */
+UCHAR AGS3x3HTRateTable[] = {
+ 0x19, 0x18, 0, 0, 0, 0, 0, 0, 0, 0, /* Initial used item after association: the number of rate indexes, the initial mcs */
+ 0x00, 0x21, 0, 0, 30, 101, 0, 16, 8, 1, /* MCS 0 */
+ 0x01, 0x21, 0, 1, 20, 50, 0, 16, 9, 2, /* MCS 1 */
+ 0x02, 0x21, 0, 2, 20, 50, 1, 17, 9, 3, /* MCS 2 */
+ 0x03, 0x21, 0, 3, 15, 50, 2, 17, 10, 4, /* MCS 3 */
+ 0x04, 0x21, 0, 4, 15, 30, 3, 18, 11, 5, /* MCS 4 */
+ 0x05, 0x21, 0, 5, 10, 25, 4, 18, 12, 6, /* MCS 5 */
+ 0x06, 0x21, 0, 6, 8, 14, 5, 19, 12, 7, /* MCS 6 */
+ 0x07, 0x21, 0, 7, 8, 14, 6, 19, 12, 7, /* MCS 7 */
+ 0x08, 0x20, 0, 8, 30, 50, 0, 16, 9, 2, /* MCS 8 */
+ 0x09, 0x20, 0, 9, 20, 50, 8, 17, 10, 4, /* MCS 9 */
+ 0x0A, 0x20, 0, 10, 20, 50, 9, 18, 11, 5, /* MCS 10 */
+ 0x0B, 0x20, 0, 11, 15, 30, 10, 18, 12, 6, /* MCS 11 */
+ 0x0C, 0x20, 0, 12, 15, 30, 11, 20, 13, 12, /* MCS 12 */
+ 0x0D, 0x20, 0, 13, 8, 20, 12, 20, 14, 13, /* MCS 13 */
+ 0x0E, 0x20, 0, 14, 8, 18, 13, 21, 15, 14, /* MCS 14 */
+ 0x0F, 0x20, 0, 15, 8, 14, 14, 21, 15, 15, /* MCS 15 */
+ 0x10, 0x20, 0, 16, 30, 50, 8, 17, 9, 3, /* MCS 16 */
+ 0x11, 0x20, 0, 17, 20, 50, 16, 18, 11, 5, /* MCS 17 */
+ 0x12, 0x20, 0, 18, 20, 50, 17, 19, 12, 7, /* MCS 18 */
+ 0x13, 0x20, 0, 19, 15, 30, 18, 20, 13, 19, /* MCS 19 */
+ 0x14, 0x20, 0, 20, 15, 30, 19, 21, 15, 20, /* MCS 20 */
+ 0x15, 0x20, 0, 21, 8, 20, 20, 22, 21, 21, /* MCS 21 */
+ 0x16, 0x20, 0, 22, 8, 20, 21, 23, 22, 22, /* MCS 22 */
+ 0x17, 0x20, 0, 23, 6, 18, 22, 24, 23, 23, /* MCS 23 */
+ 0x18, 0x22, 0, 23, 6, 14, 23, 24, 24, 24, /* MCS 23 + Short GI */
+};
+
+
+#ifdef DOT11_VHT_AC
+
+#define NSS_1 0
+#define NSS_2 1
+/* RSSI Offset table for Ags rate tuning */
+UCHAR AgsRssiOffsetTable[3][4] =
+{
+ // [i][] MAX System spatial stream capability: 1*1, 2*2, 3*3
+ // [i][] MAX System Bandwidth: 20, 40, 80, 160
+ // ----------------------
+ {0, 2, 4, 6}, // For VHT 1*1: BW20, BW40, BW80, BW160
+ {2, 4, 6, 8}, // For VHT 2*2: BW20, BW40, BW80, BW160
+ {4, 6, 8, 10} // For VHT 3*3: BW20, BW40, BW80, BW160
+};
+
+
+/*
+ [Item no.] [Mode]* [Mode]** [CurrMCS] [TrainUp] [TrainDown] [downMCS] [upMCS3] [upMCS2] [upMCS1]
+
+ Note: downMCS, upMCS3, upMCS2 and upMCS1 are zero-based array index.
+
+ [Mode]*:
+ bit0: STBC -STBC_XXX
+ bit1: Short GI - GI_XXX
+ bit2~3: BW - BW_XXX
+ bit4~bit6: Mode (0:CCK, 1:OFDM, 2:HT Mix, 3:HT GF, 4: VHT) - MODE_XXX
+ bit7: Reserved
+
+ [Mode]**
+ bit0~1: Nss - NSS_XXX (VHT only)
+ bit2~7: Reserved
+*/
+
+/* AGS: 1x1 VHT-capable rate table */
+UCHAR Ags1x1VhtRateTable[] =
+{
+ // Initial used item after association: the number of rate indexes, the initial MCS (index)
+ 9, 0x08, 0x00, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0x41, 0x00, 0,/* VHT 1x1 MCS 0 */ 30, 101, 0, 0, 0, 1,
+ 1, 0x41, 0x00, 1,/* VHT 1x1 MCS 1 */ 20, 50, 0, 0, 0, 2,
+ 2, 0x41, 0x00, 2,/* VHT 1x1 MCS 2 */ 20, 50, 1, 0, 0, 3,
+ 3, 0x41, 0x00, 3,/* VHT 1x1 MCS 3 */ 15, 50, 2, 0, 0, 4,
+ 4, 0x41, 0x00, 4,/* VHT 1x1 MCS 4 */ 15, 30, 3, 0, 0, 5,
+ 5, 0x41, 0x00, 5,/* VHT 1x1 MCS 5 */ 10, 25, 4, 0, 0, 6,
+ 6, 0x41, 0x00, 6,/* VHT 1x1 MCS 6 */ 8, 14, 5, 0, 0, 7,
+ 7, 0x41, 0x00, 7,/* VHT 1x1 MCS 7 */ 8, 14, 6, 0, 0, 8,
+ 8, 0x43, 0x00, 7,/* VHT 1x1 MCS 7 + SGI */ 8, 14, 7, 0, 0, 8,
+};
+
+
+/* AGS: 2x2 VHT-capable rate table */
+UCHAR Ags2x2VhtRateTable[] = {
+ // row #1 is initial used item after association: the number of rate indexes, the initial MCS (index)
+ 17, 0x10, 0x00, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0x41, 0x00, 0, /* VHT 1x1 MCS 0 */ 30, 101, 0, 0, 8, 1,
+ 1, 0x41, 0x00, 1, /* VHT 1x1 MCS 1 */ 20, 50, 0, 0, 9, 2,
+ 2, 0x41, 0x00, 2, /* VHT 1x1 MCS 2 */ 20, 50, 1, 0, 9, 3,
+ 3, 0x41, 0x00, 3, /* VHT 1x1 MCS 3 */ 15, 50, 2, 0, 10, 4,
+ 4, 0x41, 0x00, 4, /* VHT 1x1 MCS 4 */ 15, 30, 3, 0, 11, 5,
+ 5, 0x41, 0x00, 5, /* VHT 1x1 MCS 5 */ 10, 25, 4, 0, 12, 6,
+ 6, 0x41, 0x00, 6, /* VHT 1x1 MCS 6 */ 8, 14, 5, 0, 12, 7,
+ 7, 0x41, 0x00, 7, /* VHT 1x1 MCS 7 */ 8, 14, 6, 0, 12, 7,
+ 8, 0x40, 0x01, 0, /* VHT 2x2 MCS 0 */ 30, 50, 0, 0, 9, 2,
+ 9, 0x40, 0x01, 1, /* VHT 2x2 MCS 1 */ 20, 50, 8, 0, 10, 4,
+ 10, 0x40, 0x01, 2, /* VHT 2x2 MCS 2 */ 20, 50, 9, 0, 11, 5,
+ 11, 0x40, 0x01, 3, /* VHT 2x2 MCS 3 */ 15, 30, 10, 0, 12, 6,
+ 12, 0x40, 0x01, 4, /* VHT 2x2 MCS 4 */ 15, 30, 11, 0, 13, 12,
+ 13, 0x40, 0x01, 5, /* VHT 2x2 MCS 5 */ 8, 20, 12, 0, 14, 13,
+ 14, 0x40, 0x01, 6, /* VHT 2x2 MCS 6 */ 8, 18, 13, 0, 15, 14,
+ 15, 0x40, 0x01, 7, /* VHT 2x2 MCS 7 */ 8, 25, 14, 0, 16, 15,
+ 16, 0x42, 0x01, 7, /* VHT 2x2 MCS 7 + SGI */ 8, 25, 15, 0, 16, 16,
+};
+#endif /* DOT11_VHT_AC */
+
+
+INT Show_AGS_Proc(
+ IN PRTMP_ADAPTER pAd,
+ IN PSTRING arg)
+{
+ MAC_TABLE_ENTRY *pEntry = &pAd->MacTab.Content[1];
+ UINT32 IdQuality;
+
+
+ DBGPRINT(RT_DEBUG_OFF, ("MCS Group\t\tMCS Index\n"));
+ DBGPRINT(RT_DEBUG_OFF, ("%d\t\t\t%d\n\n", pEntry->AGSCtrl.MCSGroup, pEntry->CurrTxRateIndex));
+
+ DBGPRINT(RT_DEBUG_OFF, ("MCS Quality:\n"));
+ for(IdQuality=0; IdQuality<=23; IdQuality++)
+ DBGPRINT(RT_DEBUG_OFF, ("%02d\t\t%d\n", IdQuality, pEntry->TxQuality[IdQuality]));
+
+ return TRUE;
+}
+
+
+
+
+#ifdef CONFIG_AP_SUPPORT
+/*
+ The dynamic Tx rate switching for AGS in VHT(Adaptive Group Switching)
+
+ Parameters
+ pAd: The adapter data structure
+
+ Return Value:
+ None
+*/
+VOID ApMlmeDynamicTxRateSwitchingAGS(
+ IN RTMP_ADAPTER *pAd,
+ IN INT idx)
+{
+ UCHAR *pTable, TableSize = 0;
+ MAC_TABLE_ENTRY *pEntry = &pAd->MacTab.Content[idx];
+ UCHAR UpRateIdx = 0, DownRateIdx = 0, CurrRateIdx = 0;
+ RTMP_RA_AGS_TB *pCurrTxRate = NULL;
+ RTMP_RA_LEGACY_TB *pNextTxRate = NULL;
+ BOOLEAN bTxRateChanged = TRUE, bUpgradeQuality = FALSE;
+ UCHAR TrainUp = 0, TrainDown = 0, next_grp;
+ CHAR RssiOffset = 0;
+ ULONG TxTotalCnt, TxErrorRatio = 0;
+ ULONG TxSuccess, TxRetransmit, TxFailCount;
+ AGS_STATISTICS_INFO AGSStatisticsInfo = {0};
+
+
+ DBGPRINT_RAW(RT_DEBUG_TRACE, ("AGS: ---> %s\n", __FUNCTION__));
+
+ if (pAd->MacTab.Size == 1)
+ {
+ TX_STA_CNT1_STRUC StaTx1;
+ TX_STA_CNT0_STRUC TxStaCnt0;
+
+ /* Update statistic counter */
+ NicGetTxRawCounters(pAd, &TxStaCnt0, &StaTx1);
+
+ TxRetransmit = StaTx1.field.TxRetransmit;
+ TxSuccess = StaTx1.field.TxSuccess;
+ TxFailCount = TxStaCnt0.field.TxFailCount;
+ TxTotalCnt = TxRetransmit + TxSuccess + TxFailCount;
+
+ if (TxTotalCnt)
+ TxErrorRatio = ((TxRetransmit + TxFailCount) * 100) / TxTotalCnt;
+ }
+ else
+ {
+ TxRetransmit = pEntry->OneSecTxRetryOkCount;
+ TxSuccess = pEntry->OneSecTxNoRetryOkCount;
+ TxFailCount = pEntry->OneSecTxFailCount;
+ TxTotalCnt = TxRetransmit + TxSuccess + TxFailCount;
+
+ if (TxTotalCnt)
+ TxErrorRatio = ((TxRetransmit + TxFailCount) * 100) / TxTotalCnt;
+
+#ifdef FIFO_EXT_SUPPORT
+ if (pEntry->Aid >= 1 && pEntry->Aid <= 8)
+ {
+ ULONG HwTxCnt, HwErrRatio;
+
+ NicGetMacFifoTxCnt(pAd, pEntry);
+ HwTxCnt = pEntry->fifoTxSucCnt + pEntry->fifoTxRtyCnt;
+ if (HwTxCnt)
+ HwErrRatio = (pEntry->fifoTxRtyCnt * 100) / HwTxCnt;
+ else
+ HwErrRatio = 0;
+ DBGPRINT(RT_DEBUG_INFO | DBG_FUNC_RA,("%s():Aid:%d, MCS:%d, TxErrRatio(Hw:0x%lx-0x%lx, Sw:0x%lx-%lx)\n",
+ __FUNCTION__, pEntry->Aid, pEntry->HTPhyMode.field.MCS,
+ HwTxCnt, HwErrRatio, TxTotalCnt, TxErrorRatio));
+
+ TxSuccess = pEntry->fifoTxSucCnt;
+ TxRetransmit = pEntry->fifoTxRtyCnt;
+ TxTotalCnt = HwTxCnt;
+ TxErrorRatio = HwErrRatio;
+ }
+#endif /* FIFO_EXT_SUPPORT */
+ }
+
+ AGSStatisticsInfo.RSSI = RTMPAvgRssi(pAd, &pEntry->RssiSample);;
+ AGSStatisticsInfo.TxErrorRatio = TxErrorRatio;
+ AGSStatisticsInfo.AccuTxTotalCnt = TxTotalCnt;
+ AGSStatisticsInfo.TxTotalCnt = TxTotalCnt;
+ AGSStatisticsInfo.TxSuccess = TxSuccess;
+ AGSStatisticsInfo.TxRetransmit = TxRetransmit;
+ AGSStatisticsInfo.TxFailCount = TxFailCount;
+
+ DBGPRINT(RT_DEBUG_INFO | DBG_FUNC_RA, ("%s: QuickAGS: AccuTxTotalCnt = %ld, TxSuccess = %ld, TxRetransmit = %ld, TxFailCount = %ld, TxErrorRatio = %ld\n",
+ __FUNCTION__,
+ AGSStatisticsInfo.AccuTxTotalCnt,
+ AGSStatisticsInfo.TxSuccess,
+ AGSStatisticsInfo.TxRetransmit,
+ AGSStatisticsInfo.TxFailCount,
+ AGSStatisticsInfo.TxErrorRatio));
+
+ pTable = pEntry->pTable;
+ TableSize = pTable[0];
+
+ CurrRateIdx = pEntry->CurrTxRateIndex;
+
+ if (CurrRateIdx >= TableSize)
+ CurrRateIdx = TableSize - 1;
+
+
+ pCurrTxRate = (RTMP_RA_AGS_TB *)(&pTable[(CurrRateIdx + 1) * SIZE_OF_AGS_RATE_TABLE_ENTRY]);
+
+ /* Select the next upgrade rate and the next downgrade rate, if any */
+ do
+ {
+ if (pTable == AGS3x3HTRateTable)
+ {
+ DBGPRINT_RAW(RT_DEBUG_INFO | DBG_FUNC_RA,
+ ("%s: AGS: pEntry->AGSCtrl.MCSGroup = %d, TxQuality2[%d] = %d, "
+ "TxQuality1[%d] = %d, TxQuality0[%d] = %d, pCurrTxRate->upMcs1 = %d, "
+ "pCurrTxRate->ItemNo = %d\n",
+ __FUNCTION__,
+ pEntry->AGSCtrl.MCSGroup,
+ pCurrTxRate->upMcs3,
+ pEntry->TxQuality[pCurrTxRate->upMcs3],
+ pCurrTxRate->upMcs2,
+ pEntry->TxQuality[pCurrTxRate->upMcs2],
+ pCurrTxRate->upMcs1,
+ pEntry->TxQuality[pCurrTxRate->upMcs1],
+ pCurrTxRate->upMcs1,
+ pCurrTxRate->ItemNo));
+
+ /* 3x3 */
+ /* for 3*3, pEntry->AGSCtrl.MCSGroup = 0, 3, 3, 3, ... */
+ next_grp = pEntry->AGSCtrl.MCSGroup;
+ switch (pEntry->AGSCtrl.MCSGroup)
+ {
+ case 0: /* MCS selection in round robin policy (different MCS group) */
+ {
+ UpRateIdx = pCurrTxRate->upMcs3;
+ next_grp = 3;
+
+ /* MCS group #2 has better Tx quality */
+ if ((pEntry->TxQuality[UpRateIdx] > pEntry->TxQuality[pCurrTxRate->upMcs2]) &&
+ (pCurrTxRate->upMcs2 != pCurrTxRate->ItemNo))
+ {
+ UpRateIdx = pCurrTxRate->upMcs2;
+ next_grp = 2;
+ }
+
+ /* MCS group #1 has better Tx quality */
+ if ((pEntry->TxQuality[UpRateIdx] > pEntry->TxQuality[pCurrTxRate->upMcs1]) &&
+ (pCurrTxRate->upMcs1 != pCurrTxRate->ItemNo))
+ {
+ UpRateIdx = pCurrTxRate->upMcs1;
+ next_grp = 1;
+ }
+ }
+ break;
+
+ case 3:
+ UpRateIdx = pCurrTxRate->upMcs3;
+ break;
+
+ case 2:
+ UpRateIdx = pCurrTxRate->upMcs2;
+ break;
+
+ case 1:
+ UpRateIdx = pCurrTxRate->upMcs1;
+ break;
+
+ default:
+ {
+ DBGPRINT_RAW(RT_DEBUG_ERROR,
+ ("%s: AGS: Incorrect MCS group, pEntry->AGSCtrl.MCSGroup = %d\n",
+ __FUNCTION__, pEntry->AGSCtrl.MCSGroup));
+ }
+ break;
+ }
+
+ DBGPRINT_RAW(RT_DEBUG_INFO | DBG_FUNC_RA,
+ ("AGS> Current Group:%d, Select UpRateIdx=%d in group %d\n",
+ pEntry->AGSCtrl.MCSGroup, UpRateIdx, next_grp));
+
+
+ if ((pEntry->AGSCtrl.MCSGroup == 0) &&
+ (((pEntry->TxQuality[pCurrTxRate->upMcs3] > pEntry->TxQuality[pCurrTxRate->upMcs2]) && (pCurrTxRate->upMcs2 != pCurrTxRate->ItemNo)) ||
+ ((pEntry->TxQuality[pCurrTxRate->upMcs3] > pEntry->TxQuality[pCurrTxRate->upMcs1]) && (pCurrTxRate->upMcs1 != pCurrTxRate->ItemNo))))
+ {
+ DBGPRINT_RAW(RT_DEBUG_INFO | DBG_FUNC_RA, ("%s: ##############\n", __FUNCTION__));
+
+ DBGPRINT_RAW(RT_DEBUG_INFO | DBG_FUNC_RA,
+ ("%s: AGS: [3x3 Before - "
+ "pEntry->AGSCtrl.MCSGroup = %d, TxQuality2[%d] = %d, "
+ "TxQuality1[%d] = %d, TxQuality0[%d] = %d\n",
+ __FUNCTION__,
+ pEntry->AGSCtrl.MCSGroup,
+ pCurrTxRate->upMcs3,
+ pEntry->TxQuality[pCurrTxRate->upMcs3],
+ pCurrTxRate->upMcs2,
+ pEntry->TxQuality[pCurrTxRate->upMcs2],
+ pCurrTxRate->upMcs1,
+ pEntry->TxQuality[pCurrTxRate->upMcs1]));
+ }
+ }
+ else if ((pTable == AGS2x2HTRateTable)
+#ifdef DOT11_VHT_AC
+ || (pTable == Ags2x2VhtRateTable)
+#endif /* DOT11_VHT_AC*/
+ )
+ {
+ DBGPRINT_RAW(RT_DEBUG_INFO | DBG_FUNC_RA,
+ ("%s: AGS: pEntry->AGSCtrl.MCSGroup = %d, TxQuality1[%d] = %d, "
+ "TxQuality0[%d] = %d, pCurrTxRate->upMcs1 = %d, "
+ "pCurrTxRate->ItemNo = %d\n",
+ __FUNCTION__,
+ pEntry->AGSCtrl.MCSGroup,
+ pCurrTxRate->upMcs2, pEntry->TxQuality[pCurrTxRate->upMcs2],
+ pCurrTxRate->upMcs1, pEntry->TxQuality[pCurrTxRate->upMcs1],
+ pCurrTxRate->upMcs1, pCurrTxRate->ItemNo));
+
+ /* 2x2 peer device (Adhoc, DLS or AP) */
+ switch (pEntry->AGSCtrl.MCSGroup)
+ {
+ case 0: /* MCS selection in round robin policy */
+ {
+ UpRateIdx = pCurrTxRate->upMcs2;
+ /* MCS group #1 has better Tx quality */
+ if ((pEntry->TxQuality[UpRateIdx] > pEntry->TxQuality[pCurrTxRate->upMcs1]) &&
+ (pCurrTxRate->upMcs1 != pCurrTxRate->ItemNo))
+ UpRateIdx = pCurrTxRate->upMcs1;
+ }
+ break;
+
+ case 2:
+ UpRateIdx = pCurrTxRate->upMcs2;
+ break;
+
+ case 1:
+ UpRateIdx = pCurrTxRate->upMcs1;
+ break;
+
+ default:
+ {
+ DBGPRINT_RAW(RT_DEBUG_ERROR,
+ ("%s: AGS: [2x2 peer device (Adhoc, DLS or AP)], "
+ "Incorrect MCS group, pEntry->AGSCtrl.MCSGroup = %d\n",
+ __FUNCTION__,
+ pEntry->AGSCtrl.MCSGroup));
+ }
+ break;
+ }
+
+ if ((pEntry->AGSCtrl.MCSGroup == 0) &&
+ ((pEntry->TxQuality[pCurrTxRate->upMcs2] > pEntry->TxQuality[pCurrTxRate->upMcs1]) &&
+ (pCurrTxRate->upMcs1 != pCurrTxRate->ItemNo)))
+ {
+ DBGPRINT_RAW(RT_DEBUG_INFO | DBG_FUNC_RA, ("%s: ###########\n", __FUNCTION__));
+
+ DBGPRINT_RAW(RT_DEBUG_INFO | DBG_FUNC_RA,
+ ("%s: AGS: [2x2 peer device (Adhoc, DLS or AP)], Before - "
+ "pEntry->AGSCtrl.MCSGroup = %d, TxQuality1[%d] = %d, "
+ "TxQuality0[%d] = %d\n",
+ __FUNCTION__,
+ pEntry->AGSCtrl.MCSGroup,
+ pCurrTxRate->upMcs2,
+ pEntry->TxQuality[pCurrTxRate->upMcs2],
+ pCurrTxRate->upMcs1,
+ pEntry->TxQuality[pCurrTxRate->upMcs1]));
+ }
+ }
+ else
+ {
+ /* 1x1 peer device (Adhoc, DLS or AP) */
+ switch (pEntry->AGSCtrl.MCSGroup)
+ {
+ case 1:
+ case 0:
+ UpRateIdx = pCurrTxRate->upMcs1;
+ break;
+
+ default:
+ {
+ DBGPRINT_RAW(RT_DEBUG_ERROR,
+ ("%s: AGS: [1x1 peer device (Adhoc, DLS or AP)], "
+ "Incorrect MCS group, pEntry->AGSCtrl.MCSGroup = %d\n",
+ __FUNCTION__,
+ pEntry->AGSCtrl.MCSGroup));
+ }
+ break;
+ }
+ }
+
+
+ /* The STA uses the best Tx rate at this moment. */
+ if (UpRateIdx == pEntry->CurrTxRateIndex)
+ {
+ /* current rate is the best one */
+ pEntry->AGSCtrl.MCSGroup = 0; /* Try to escape the local optima */
+
+ DBGPRINT_RAW(RT_DEBUG_INFO | DBG_FUNC_RA, ("ags> Current rate is the best one!\n"));
+ break;
+ }
+
+ if ((pEntry->TxQuality[UpRateIdx] > 0) && (pEntry->AGSCtrl.MCSGroup > 0))
+ {
+ /*
+ Quality of up rate is bad try to use lower group.
+ So continue to get the up rate index.
+ */
+ pEntry->AGSCtrl.MCSGroup--; /* Try to use the MCS of the lower MCS group */
+ }
+ else
+ {
+ break;
+ }
+ } while (1);
+
+ DownRateIdx = pCurrTxRate->downMcs;
+
+ DBGPRINT_RAW(RT_DEBUG_INFO | DBG_FUNC_RA,
+ ("ags> UpRateIdx = %d, DownRateIdx = %d\n",
+ UpRateIdx, DownRateIdx));
+
+#ifdef DOT11_N_SUPPORT
+ if ((AGSStatisticsInfo.RSSI > -65) && (pCurrTxRate->Mode >= MODE_HTMIX))
+ {
+ TrainUp = (pCurrTxRate->TrainUp + (pCurrTxRate->TrainUp >> 1));
+ TrainDown = (pCurrTxRate->TrainDown + (pCurrTxRate->TrainDown >> 1));
+ }
+ else
+#endif /* DOT11_N_SUPPORT */
+ {
+ TrainUp = pCurrTxRate->TrainUp;
+ TrainDown = pCurrTxRate->TrainDown;
+ }
+
+ /* Keep the TxRateChangeAction status */
+ pEntry->LastTimeTxRateChangeAction = pEntry->LastSecTxRateChangeAction;
+
+
+ DBGPRINT(RT_DEBUG_INFO | DBG_FUNC_RA, ("%s: AGS: Rssi = %d, TxSuccess = %lu, TxRetransmit = %lu, TxFailCount = %lu, TxErrorRatio = %lu\n",
+ __FUNCTION__,
+ AGSStatisticsInfo.RSSI,
+ AGSStatisticsInfo.TxSuccess,
+ AGSStatisticsInfo.TxRetransmit,
+ AGSStatisticsInfo.TxFailCount,
+ AGSStatisticsInfo.TxErrorRatio));
+
+ DBGPRINT_RAW(RT_DEBUG_INFO | DBG_FUNC_RA,
+ ("%s: AGS: Before - CurrTxRateIdx = %d, MCS = %d, STBC = %d, ShortGI = %d, Mode = %d, "
+ "TrainUp = %d, TrainDown = %d, NextUp = %d, NextDown = %d, "
+ "CurrMCS = %d, pEntry->AGSCtrl.MCSGroup = %d, PER = %lu%%, Retry = %lu, NoRetry = %lu\n",
+ __FUNCTION__,
+ CurrRateIdx,
+ pCurrTxRate->CurrMCS,
+ pCurrTxRate->STBC,
+ pCurrTxRate->ShortGI,
+ pCurrTxRate->Mode,
+ TrainUp,
+ TrainDown,
+ UpRateIdx,
+ DownRateIdx,
+ pEntry->HTPhyMode.field.MCS,
+ pEntry->AGSCtrl.MCSGroup,
+ AGSStatisticsInfo.TxErrorRatio,
+ AGSStatisticsInfo.TxRetransmit,
+ AGSStatisticsInfo.TxSuccess));
+
+ /* MCS selection based on the RSSI information when the Tx samples are fewer than 15. */
+ if (AGSStatisticsInfo.AccuTxTotalCnt <= 15)
+ {
+ CHAR idx = 0;
+ UCHAR TxRateIdx;
+ UCHAR MCS[24] = {0};
+ /* Check the existence and index of each needed MCS */
+
+#ifdef DOT11_VHT_AC
+ if ((pTable == Ags2x2VhtRateTable) || (pTable == Ags1x1VhtRateTable))
+ {
+ INT mcs_idx_offset;
+ while (idx < pTable[0])
+ {
+ pCurrTxRate = (RTMP_RA_AGS_TB *)(&pTable[(idx + 1) * SIZE_OF_AGS_RATE_TABLE_ENTRY]);
+ if (pCurrTxRate->Mode == MODE_VHT)
+ {
+ if (pCurrTxRate->Nss == NSS_1)
+ mcs_idx_offset = 0;
+ else if ((pCurrTxRate->Nss == NSS_2) && (pTable == Ags2x2VhtRateTable))
+ mcs_idx_offset = 8;
+ else {
+ DBGPRINT(RT_DEBUG_ERROR, ("%s():Invalid Nss(%d)\n", __FUNCTION__, pCurrTxRate->Nss));
+ mcs_idx_offset = 0;
+ }
+
+ if ((pCurrTxRate->CurrMCS <= MCS_7) /* && (pCurrTxRate->CurrMCS >= MCS_0) */)
+ MCS[pCurrTxRate->CurrMCS + mcs_idx_offset] = idx;
+ }
+ idx++;
+ }
+ }
+ else
+#endif /* DOT11_VHT_AC */
+ {
+ while (idx < pTable[0])
+ {
+ pCurrTxRate = (RTMP_RA_AGS_TB *)(&pTable[(idx + 1) * SIZE_OF_AGS_RATE_TABLE_ENTRY]);
+
+ if (pCurrTxRate->CurrMCS <= MCS_23 /* && pCurrTxRate->CurrMCS >= MCS_0 */)
+ MCS[pCurrTxRate->CurrMCS] = idx;
+ idx++;
+ }
+ }
+
+ /* peer device (Adhoc, DLS or AP) */
+ RssiOffset = 0;
+ if (pTable == AGS3x3HTRateTable)
+ {
+ if (MCS[23] && (AGSStatisticsInfo.RSSI > (-67 + RssiOffset)))
+ TxRateIdx = MCS[23];
+ else if (MCS[22] && (AGSStatisticsInfo.RSSI > (-69 + RssiOffset)))
+ TxRateIdx = MCS[22];
+ else if (MCS[21] && (AGSStatisticsInfo.RSSI > (-72 + RssiOffset)))
+ TxRateIdx = MCS[21];
+ else if (MCS[20] && (AGSStatisticsInfo.RSSI > (-74 + RssiOffset)))
+ TxRateIdx = MCS[20];
+ else if (MCS[19] && (AGSStatisticsInfo.RSSI > (-78 + RssiOffset)))
+ TxRateIdx = MCS[19];
+ else if (MCS[18] && (AGSStatisticsInfo.RSSI > (-80 + RssiOffset)))
+ TxRateIdx = MCS[18];
+ else if (MCS[17] && (AGSStatisticsInfo.RSSI > (-85 + RssiOffset)))
+ TxRateIdx = MCS[17];
+ else
+ TxRateIdx = MCS[16];
+
+ pEntry->AGSCtrl.MCSGroup = 3;
+
+ DBGPRINT_RAW(RT_DEBUG_INFO | DBG_FUNC_RA,
+ ("ags> Group3 RSSI = %d, TxRateIdx = %d\n",
+ AGSStatisticsInfo.RSSI, TxRateIdx));
+ }
+ else if ((pTable == AGS2x2HTRateTable)
+#ifdef DOT11_VHT_AC
+ || (pTable == Ags2x2VhtRateTable)
+#endif /* DOT11_VHT_AC */
+ )
+ {
+#ifdef DOT11_VHT_AC
+ if (pTable == Ags2x2VhtRateTable)
+ RssiOffset = AgsRssiOffsetTable[1][pAd->CommonCfg.BBPCurrentBW];
+#endif /* DOT11_VHT_AC */
+
+ DBGPRINT_RAW(RT_DEBUG_TRACE, ("%s: AGS: 2*2, RssiOffsetForAgs=%d\n", __FUNCTION__, RssiOffset));
+
+ if (MCS[15] && (AGSStatisticsInfo.RSSI > (-69 + RssiOffset)))
+ TxRateIdx = MCS[15];
+ else if (MCS[14] && (AGSStatisticsInfo.RSSI > (-71 + RssiOffset)))
+ TxRateIdx = MCS[14];
+ else if (MCS[13] && (AGSStatisticsInfo.RSSI > (-74 + RssiOffset)))
+ TxRateIdx = MCS[13];
+ else if (MCS[12] && (AGSStatisticsInfo.RSSI > (-76 + RssiOffset)))
+ TxRateIdx = MCS[12];
+ else if (MCS[11] && (AGSStatisticsInfo.RSSI > (-80 + RssiOffset)))
+ TxRateIdx = MCS[11];
+ else if (MCS[10] && (AGSStatisticsInfo.RSSI > (-82 + RssiOffset)))
+ TxRateIdx = MCS[10];
+ else if (MCS[9] && (AGSStatisticsInfo.RSSI > (-87 + RssiOffset)))
+ TxRateIdx = MCS[9];
+ else
+ TxRateIdx = MCS[8];
+
+ pEntry->AGSCtrl.MCSGroup = 2;
+ }
+ else
+ {
+#ifdef DOT11_VHT_AC
+ if (pTable == Ags1x1VhtRateTable)
+ RssiOffset = AgsRssiOffsetTable[0][pAd->CommonCfg.BBPCurrentBW];
+#endif /* DOT11_VHT_AC */
+ DBGPRINT_RAW(RT_DEBUG_INFO | DBG_FUNC_RA, ("%s: AGS: 1*1, RssiOffset=%d\n", __FUNCTION__, RssiOffset));
+
+ /* 1x1 peer device (Adhoc, DLS or AP) */
+ if (MCS[7] && (AGSStatisticsInfo.RSSI > (-71 + RssiOffset)))
+ TxRateIdx = MCS[7];
+ else if (MCS[6] && (AGSStatisticsInfo.RSSI > (-73 + RssiOffset)))
+ TxRateIdx = MCS[6];
+ else if (MCS[5] && (AGSStatisticsInfo.RSSI > (-76 + RssiOffset)))
+ TxRateIdx = MCS[5];
+ else if (MCS[4] && (AGSStatisticsInfo.RSSI > (-78 + RssiOffset)))
+ TxRateIdx = MCS[4];
+ else if (MCS[3] && (AGSStatisticsInfo.RSSI > (-82 + RssiOffset)))
+ TxRateIdx = MCS[3];
+ else if (MCS[2] && (AGSStatisticsInfo.RSSI > (-84 + RssiOffset)))
+ TxRateIdx = MCS[2];
+ else if (MCS[1] && (AGSStatisticsInfo.RSSI > (-89 + RssiOffset)))
+ TxRateIdx = MCS[1];
+ else
+ TxRateIdx = MCS[0];
+
+ pEntry->AGSCtrl.MCSGroup = 1;
+ }
+
+ pEntry->AGSCtrl.lastRateIdx = pEntry->CurrTxRateIndex;
+ pEntry->CurrTxRateIndex = TxRateIdx;
+
+ pNextTxRate = (RTMP_RA_LEGACY_TB *)(&pTable[(pEntry->CurrTxRateIndex + 1) * SIZE_OF_AGS_RATE_TABLE_ENTRY]);
+ APMlmeSetTxRate(pAd, pEntry, pNextTxRate);
+
+ RTMPZeroMemory(pEntry->TxQuality, (sizeof(USHORT) * (MAX_TX_RATE_INDEX+1)));
+ RTMPZeroMemory(pEntry->PER, (sizeof(UCHAR) * (MAX_TX_RATE_INDEX+1)));
+
+ pEntry->fLastSecAccordingRSSI = TRUE;
+ /* reset all OneSecTx counters */
+ RESET_ONE_SEC_TX_CNT(pEntry);
+ return;
+ }
+
+ /* The MCS selection is based on the RSSI and skips the rate tuning this time. */
+ if (pEntry->fLastSecAccordingRSSI == TRUE)
+ {
+ pEntry->fLastSecAccordingRSSI = FALSE;
+ pEntry->LastSecTxRateChangeAction = RATE_NO_CHANGE;
+
+ RESET_ONE_SEC_TX_CNT(pEntry);
+
+ DBGPRINT_RAW(RT_DEBUG_INFO | DBG_FUNC_RA, ("%s: AGS: The MCS selection base on RSSI\n", __FUNCTION__));
+
+ return;
+ }
+
+ DBGPRINT_RAW(RT_DEBUG_INFO | DBG_FUNC_RA, ("%s: AGS: TrainUp:%d, TrainDown:%d\n", __FUNCTION__, TrainUp, TrainDown));
+
+ do
+ {
+ BOOLEAN bTrainUpDown = FALSE;
+
+ DBGPRINT_RAW(RT_DEBUG_INFO | DBG_FUNC_RA,
+ ("%s: AGS: TxQuality[CurrRateIdx(%d)] = %d, UpPenalty:%d\n",
+ __FUNCTION__, CurrRateIdx,
+ pEntry->TxQuality[CurrRateIdx], pEntry->TxRateUpPenalty));
+
+ if (AGSStatisticsInfo.TxErrorRatio >= TrainDown) /* Poor quality */
+ {
+ /* error ratio too high, do rate down */
+ DBGPRINT_RAW(RT_DEBUG_INFO | DBG_FUNC_RA,
+ ("%s: AGS: (DOWN) TxErrorRatio >= TrainDown\n",__FUNCTION__));
+ bTrainUpDown = TRUE;
+ pEntry->TxQuality[CurrRateIdx] = AGS_TX_QUALITY_WORST_BOUND;
+ }
+ else if (AGSStatisticsInfo.TxErrorRatio <= TrainUp) /* Good quality */
+ {
+ bTrainUpDown = TRUE;
+ bUpgradeQuality = TRUE;
+
+ DBGPRINT_RAW(RT_DEBUG_INFO | DBG_FUNC_RA,
+ ("%s: AGS: (UP) pEntry->TxQuality[CurrRateIdx] = %d, pEntry->TxRateUpPenalty = %d\n",
+ __FUNCTION__,
+ pEntry->TxQuality[CurrRateIdx],
+ pEntry->TxRateUpPenalty));
+
+ if (pEntry->TxQuality[CurrRateIdx])
+ pEntry->TxQuality[CurrRateIdx]--; /* Good quality in the current Tx rate */
+
+ if (pEntry->TxRateUpPenalty)
+ pEntry->TxRateUpPenalty--; /* no use for the parameter */
+ else
+ {
+ if (pEntry->TxQuality[pCurrTxRate->upMcs3] && (pCurrTxRate->upMcs3 != CurrRateIdx))
+ pEntry->TxQuality[pCurrTxRate->upMcs3]--;
+
+ if (pEntry->TxQuality[pCurrTxRate->upMcs2] && (pCurrTxRate->upMcs2 != CurrRateIdx))
+ pEntry->TxQuality[pCurrTxRate->upMcs2]--;
+
+ if (pEntry->TxQuality[pCurrTxRate->upMcs1] && (pCurrTxRate->upMcs1 != CurrRateIdx))
+ pEntry->TxQuality[pCurrTxRate->upMcs1]--;
+ }
+ }
+ else if (pEntry->AGSCtrl.MCSGroup > 0) /* even if TxErrorRatio > TrainUp */
+ {
+ /* not bad and not good */
+ if (UpRateIdx != 0)
+ {
+ bTrainUpDown = FALSE;
+
+ /* Good quality in the current Tx rate */
+ if (pEntry->TxQuality[CurrRateIdx])
+ pEntry->TxQuality[CurrRateIdx]--;
+
+ /* It may improve next train-up Tx rate's quality */
+ if (pEntry->TxQuality[UpRateIdx])
+ pEntry->TxQuality[UpRateIdx]--;
+
+ DBGPRINT_RAW(RT_DEBUG_INFO | DBG_FUNC_RA, ("ags> not bad and not good\n"));
+ }
+ }
+
+ /* update error ratio for current MCS */
+ pEntry->PER[CurrRateIdx] = (UCHAR)(AGSStatisticsInfo.TxErrorRatio);
+
+ /* Update the current Tx rate */
+ if (bTrainUpDown)
+ {
+ /* need to rate up or down */
+ DBGPRINT_RAW(RT_DEBUG_INFO | DBG_FUNC_RA,
+ ("%s: AGS: bTrainUpDown = %d, CurrRateIdx = %d, DownRateIdx = %d, UpRateIdx = %d, pEntry->TxQuality[CurrRateIdx] = %d, pEntry->TxQuality[UpRateIdx] = %d\n",
+ __FUNCTION__,
+ bTrainUpDown, CurrRateIdx, DownRateIdx, UpRateIdx,
+ pEntry->TxQuality[CurrRateIdx], pEntry->TxQuality[UpRateIdx]));
+
+ /* Downgrade Tx rate */
+ if ((CurrRateIdx != DownRateIdx) &&
+ (pEntry->TxQuality[CurrRateIdx] >= AGS_TX_QUALITY_WORST_BOUND))
+ {
+ pEntry->CurrTxRateIndex = DownRateIdx;
+ pEntry->LastSecTxRateChangeAction = RATE_DOWN;
+ DBGPRINT_RAW(RT_DEBUG_INFO | DBG_FUNC_RA, ("ags> rate down!\n"));
+ }
+ else if ((CurrRateIdx != UpRateIdx) &&
+ (pEntry->TxQuality[UpRateIdx] <= 0)) /* Upgrade Tx rate */
+ {
+ pEntry->CurrTxRateIndex = UpRateIdx;
+ pEntry->LastSecTxRateChangeAction = RATE_UP;
+ DBGPRINT_RAW(RT_DEBUG_INFO | DBG_FUNC_RA, ("ags> rate up!\n"));
+ }
+ }
+ } while (FALSE);
+
+ DBGPRINT_RAW(RT_DEBUG_INFO | DBG_FUNC_RA, ("%s: AGS: pEntry->CurrTxRateIndex = %d, CurrRateIdx = %d, pEntry->LastSecTxRateChangeAction = %d\n",
+ __FUNCTION__,
+ pEntry->CurrTxRateIndex, CurrRateIdx,
+ pEntry->LastSecTxRateChangeAction));
+
+ /* rate up/down post handle */
+ if ((pEntry->CurrTxRateIndex != CurrRateIdx) &&
+ (pEntry->LastSecTxRateChangeAction == RATE_UP))
+ {
+ DBGPRINT_RAW(RT_DEBUG_INFO | DBG_FUNC_RA, ("%s: AGS: ++TX rate from %d to %d\n",
+ __FUNCTION__, CurrRateIdx, pEntry->CurrTxRateIndex));
+
+ pEntry->LastSecTxRateChangeAction = RATE_UP;
+ pEntry->TxRateUpPenalty = 0;
+ RTMPZeroMemory(pEntry->PER, sizeof(UCHAR) * (MAX_TX_RATE_INDEX+1));
+ pEntry->AGSCtrl.lastRateIdx = CurrRateIdx;
+
+ bTxRateChanged = TRUE;
+ }
+ else if ((pEntry->CurrTxRateIndex != CurrRateIdx) &&
+ (pEntry->LastSecTxRateChangeAction == RATE_DOWN))
+ {
+ DBGPRINT_RAW(RT_DEBUG_INFO | DBG_FUNC_RA, ("%s: AGS: --TX rate from %d to %d\n",
+ __FUNCTION__, CurrRateIdx, pEntry->CurrTxRateIndex));
+
+ pEntry->LastSecTxRateChangeAction = RATE_DOWN;
+ pEntry->TxRateUpPenalty = 0; /* No penalty */
+ pEntry->TxQuality[pEntry->CurrTxRateIndex] = 0;
+ pEntry->PER[pEntry->CurrTxRateIndex] = 0;
+ pEntry->AGSCtrl.lastRateIdx = CurrRateIdx;
+
+ bTxRateChanged = TRUE;
+ }
+ else /* Tx rate remains unchanged. */
+ {
+ pEntry->LastSecTxRateChangeAction = RATE_NO_CHANGE; /* Tx rate remains unchanged. */
+ bTxRateChanged = FALSE;
+ DBGPRINT_RAW(RT_DEBUG_INFO | DBG_FUNC_RA, ("ags> no rate up/down!\n"));
+ }
+
+ /* Tx rate fast train up/down */
+ if ((bTxRateChanged == TRUE) &&
+ (!pAd->ApCfg.ApQuickResponeForRateUpTimerRunning))
+ {
+ RTMPSetTimer(&pAd->ApCfg.ApQuickResponeForRateUpTimer, pAd->ra_fast_interval);
+ pAd->ApCfg.ApQuickResponeForRateUpTimerRunning = TRUE;
+ }
+ pEntry->LastTxOkCount = AGSStatisticsInfo.TxSuccess;
+
+ /* set new tx rate */
+ pNextTxRate = (RTMP_RA_LEGACY_TB *)(&pTable[(pEntry->CurrTxRateIndex + 1) * SIZE_OF_AGS_RATE_TABLE_ENTRY]);
+
+ if ((bTxRateChanged == TRUE) && (pNextTxRate != NULL))
+ {
+ DBGPRINT_RAW(RT_DEBUG_INFO | DBG_FUNC_RA,
+ ("ags> set new rate MCS = %d!\n", pEntry->CurrTxRateIndex));
+ APMlmeSetTxRate(pAd, pEntry, pNextTxRate);
+ }
+
+ /* reset all OneSecTx counters */
+ RESET_ONE_SEC_TX_CNT(pEntry);
+
+ DBGPRINT_RAW(RT_DEBUG_TRACE, ("AGS: <--- %s\n", __FUNCTION__));
+}
+
+
+/*
+ Auto Tx rate faster train up/down for AGS (Adaptive Group Switching)
+
+ Parameters
+ pAd: The adapter data structure
+ pEntry: Pointer to a caller-supplied variable in which points to a MAC table entry
+ pTable: Pointer to a caller-supplied variable in wich points to a Tx rate switching table
+ TableSize: The size, in bytes, of the specified Tx rate switching table
+ pAGSStatisticsInfo: Pointer to a caller-supplied variable in which points to the statistics information
+
+ Return Value:
+ None
+*/
+VOID ApQuickResponeForRateUpExecAGS(
+ IN RTMP_ADAPTER *pAd,
+ IN INT idx)
+{
+ UCHAR *pTable, TableSize = 0;
+ UCHAR UpRateIdx = 0, DownRateIdx = 0, CurrRateIdx = 0;
+ RTMP_RA_AGS_TB *pCurrTxRate = NULL;
+ RTMP_RA_LEGACY_TB *pNextTxRate = NULL;
+ BOOLEAN bTxRateChanged = TRUE;
+ UCHAR TrainUp = 0, TrainDown = 0;
+ CHAR ratio = 0;
+ ULONG OneSecTxNoRetryOKRationCount = 0;
+ MAC_TABLE_ENTRY *pEntry;
+ AGS_STATISTICS_INFO AGSStatisticsInfo = {0};
+ ULONG TxTotalCnt, TxErrorRatio = 0;
+ ULONG TxSuccess, TxRetransmit, TxFailCount;
+
+
+ DBGPRINT_RAW(RT_DEBUG_TRACE, ("QuickAGS: ---> %s\n", __FUNCTION__));
+ pAd->ApCfg.ApQuickResponeForRateUpTimerRunning = FALSE;
+
+ pEntry = &pAd->MacTab.Content[idx]; /* point to information of the individual station */
+ pTable = pEntry->pTable;
+ TableSize = pTable[0];
+
+ if (pAd->MacTab.Size == 1)
+ {
+ TX_STA_CNT1_STRUC StaTx1;
+ TX_STA_CNT0_STRUC TxStaCnt0;
+
+ /* Update statistic counter */
+ NicGetTxRawCounters(pAd, &TxStaCnt0, &StaTx1);
+
+ TxRetransmit = StaTx1.field.TxRetransmit;
+ TxSuccess = StaTx1.field.TxSuccess;
+ TxFailCount = TxStaCnt0.field.TxFailCount;
+ TxTotalCnt = TxRetransmit + TxSuccess + TxFailCount;
+
+ if (TxTotalCnt)
+ TxErrorRatio = ((TxRetransmit + TxFailCount) * 100) / TxTotalCnt;
+ }
+ else
+ {
+ TxRetransmit = pEntry->OneSecTxRetryOkCount;
+ TxSuccess = pEntry->OneSecTxNoRetryOkCount;
+ TxFailCount = pEntry->OneSecTxFailCount;
+ TxTotalCnt = TxRetransmit + TxSuccess + TxFailCount;
+
+ if (TxTotalCnt)
+ TxErrorRatio = ((TxRetransmit + TxFailCount) * 100) / TxTotalCnt;
+
+#ifdef FIFO_EXT_SUPPORT
+ if (pEntry->Aid >= 1 && pEntry->Aid <= 8)
+ {
+ ULONG HwTxCnt, HwErrRatio;
+
+ NicGetMacFifoTxCnt(pAd, pEntry);
+ HwTxCnt = pEntry->fifoTxSucCnt + pEntry->fifoTxRtyCnt;
+ if (HwTxCnt)
+ HwErrRatio = (pEntry->fifoTxRtyCnt * 100) / HwTxCnt;
+ else
+ HwErrRatio = 0;
+ DBGPRINT(RT_DEBUG_INFO | DBG_FUNC_RA,("%s():Aid:%d, MCS:%d, TxErrRatio(Hw:0x%lx-0x%lx, Sw:0x%lx-%lx)\n",
+ __FUNCTION__, pEntry->Aid, pEntry->HTPhyMode.field.MCS,
+ HwTxCnt, HwErrRatio, TxTotalCnt, TxErrorRatio));
+
+ TxSuccess = pEntry->fifoTxSucCnt;
+ TxRetransmit = pEntry->fifoTxRtyCnt;
+ TxTotalCnt = HwTxCnt;
+ TxErrorRatio = HwErrRatio;
+ }
+#endif /* FIFO_EXT_SUPPORT */
+ }
+
+ DBGPRINT(RT_DEBUG_INFO | DBG_FUNC_RA,
+ ("%s: QuickAGS: AccuTxTotalCnt = %lu, TxSuccess = %lu, "
+ "TxRetransmit = %lu, TxFailCount = %lu, TxErrorRatio = %lu\n",
+ __FUNCTION__,
+ AGSStatisticsInfo.AccuTxTotalCnt,
+ AGSStatisticsInfo.TxSuccess,
+ AGSStatisticsInfo.TxRetransmit,
+ AGSStatisticsInfo.TxFailCount,
+ AGSStatisticsInfo.TxErrorRatio));
+
+ CurrRateIdx = pEntry->CurrTxRateIndex;
+
+ if (CurrRateIdx >= TableSize)
+ CurrRateIdx = TableSize - 1;
+
+ UpRateIdx = DownRateIdx = pEntry->AGSCtrl.lastRateIdx;
+
+ pCurrTxRate = (RTMP_RA_AGS_TB *)(&pTable[(CurrRateIdx + 1) * SIZE_OF_AGS_RATE_TABLE_ENTRY]);
+
+ if ((AGSStatisticsInfo.RSSI > -65) && (pCurrTxRate->Mode >= MODE_HTMIX))
+ {
+ TrainUp = (pCurrTxRate->TrainUp + (pCurrTxRate->TrainUp >> 1));
+ TrainDown = (pCurrTxRate->TrainDown + (pCurrTxRate->TrainDown >> 1));
+ }
+ else
+ {
+ TrainUp = pCurrTxRate->TrainUp;
+ TrainDown = pCurrTxRate->TrainDown;
+ }
+
+ /* MCS selection based on the RSSI information when the Tx samples are fewer than 15. */
+ if (AGSStatisticsInfo.AccuTxTotalCnt <= 15)
+ {
+ RTMPZeroMemory(pEntry->TxQuality, sizeof(USHORT) * (MAX_TX_RATE_INDEX+1));
+ RTMPZeroMemory(pEntry->PER, sizeof(UCHAR) * (MAX_TX_RATE_INDEX+1));
+
+ if ((pEntry->LastSecTxRateChangeAction == 1) && (CurrRateIdx != DownRateIdx))
+ {
+ pEntry->CurrTxRateIndex = DownRateIdx;
+ pEntry->TxQuality[CurrRateIdx] = AGS_TX_QUALITY_WORST_BOUND;
+ }
+ else if ((pEntry->LastSecTxRateChangeAction == 2) && (CurrRateIdx != UpRateIdx))
+ {
+ pEntry->CurrTxRateIndex = UpRateIdx;
+ }
+
+ DBGPRINT_RAW(RT_DEBUG_INFO | DBG_FUNC_RA,
+ ("%s: QuickAGS: AccuTxTotalCnt <= 15, train back to original rate\n",
+ __FUNCTION__));
+
+ return;
+ }
+
+ do
+ {
+ if (pEntry->LastTimeTxRateChangeAction == 0)
+ ratio = 5;
+ else
+ ratio = 4;
+
+ if (AGSStatisticsInfo.TxErrorRatio >= TrainDown) /* Poor quality */
+ pEntry->TxQuality[CurrRateIdx] = AGS_TX_QUALITY_WORST_BOUND;
+
+ pEntry->PER[CurrRateIdx] = (UCHAR)(AGSStatisticsInfo.TxErrorRatio);
+
+ OneSecTxNoRetryOKRationCount = (AGSStatisticsInfo.TxSuccess * ratio);
+
+ /* Tx rate down */
+ if ((pEntry->LastSecTxRateChangeAction == 1) && (CurrRateIdx != DownRateIdx))
+ {
+ // Change Auto Rate tuning rule 1: Change from tx_ok to PER
+ if (AGSStatisticsInfo.TxErrorRatio > TrainDown) /* Poor quality */
+ {
+ pEntry->CurrTxRateIndex = DownRateIdx;
+ pEntry->TxQuality[CurrRateIdx] = AGS_TX_QUALITY_WORST_BOUND;
+
+ DBGPRINT_RAW(RT_DEBUG_INFO | DBG_FUNC_RA,
+ ("%s: QuickAGS: (UP) bad Tx ok count (Current PER:%ld, NewMcs's TrainDown:%d)\n",
+ __FUNCTION__, AGSStatisticsInfo.TxErrorRatio, TrainDown));
+ }
+ else /* Good quality */
+ {
+ DBGPRINT_RAW(RT_DEBUG_INFO | DBG_FUNC_RA,
+ ("%s: QuickAGS: (UP) keep rate-up (Current PER:%ld, NewMcs's TrainDown:%d)\n",
+ __FUNCTION__, AGSStatisticsInfo.TxErrorRatio, TrainDown));
+
+ RTMPZeroMemory(pEntry->TxQuality, sizeof(USHORT) * (MAX_TX_RATE_INDEX+1));
+
+ if (pEntry->AGSCtrl.MCSGroup == 0)
+ {
+ if (pTable == AGS3x3HTRateTable)
+ pEntry->AGSCtrl.MCSGroup = 3;
+ else if ((pTable == AGS2x2HTRateTable) ||
+ (pTable == Ags2x2VhtRateTable))
+ pEntry->AGSCtrl.MCSGroup = 2;
+ else
+ pEntry->AGSCtrl.MCSGroup = 1;
+ }
+ }
+ }
+ else if ((pEntry->LastSecTxRateChangeAction == 2) && (CurrRateIdx != UpRateIdx)) // Tx rate up
+ {
+
+// Don't quick check within train down case
+ }
+ }while (FALSE);
+
+ DBGPRINT_RAW(RT_DEBUG_INFO | DBG_FUNC_RA,
+ ("ags> new group = %d\n", pEntry->AGSCtrl.MCSGroup));
+
+ /* Last action is rate-up */
+ if (pEntry->LastSecTxRateChangeAction == 1)
+ {
+ /* looking for the next group with valid MCS */
+ if ((pEntry->CurrTxRateIndex != CurrRateIdx) && (pEntry->AGSCtrl.MCSGroup > 0))
+ {
+ pEntry->AGSCtrl.MCSGroup--; /* Try to use the MCS of the lower MCS group */
+ pCurrTxRate = (RTMP_RA_AGS_TB *)(&pTable[(DownRateIdx + 1) * SIZE_OF_AGS_RATE_TABLE_ENTRY]);
+ }
+
+ /* UpRateIdx is for temp use in this section */
+ switch (pEntry->AGSCtrl.MCSGroup)
+ {
+ case 3:
+ UpRateIdx = pCurrTxRate->upMcs3;
+ break;
+
+ case 2:
+ UpRateIdx = pCurrTxRate->upMcs2;
+ break;
+
+ case 1:
+ UpRateIdx = pCurrTxRate->upMcs1;
+ break;
+
+ case 0:
+ UpRateIdx = CurrRateIdx;
+ break;
+
+ default:
+ {
+ DBGPRINT_RAW(RT_DEBUG_INFO | DBG_FUNC_RA, ("%s: QuickAGS: Incorrect MCS group, pEntry->AGSCtrl.MCSGroup = %d\n",
+ __FUNCTION__,
+ pEntry->AGSCtrl.MCSGroup));
+ }
+ break;
+ }
+
+ /* Try to escape the local optima */
+ if (UpRateIdx == pEntry->CurrTxRateIndex)
+ pEntry->AGSCtrl.MCSGroup = 0;
+
+ DBGPRINT_RAW(RT_DEBUG_INFO | DBG_FUNC_RA, ("%s: QuickAGS: next MCS group, pEntry->AGSCtrl.MCSGroup = %d\n",
+ __FUNCTION__, pEntry->AGSCtrl.MCSGroup));
+ }
+
+ if ((pEntry->CurrTxRateIndex != CurrRateIdx) &&
+ (pEntry->LastSecTxRateChangeAction == 2)) /* Tx rate up */
+ {
+ DBGPRINT_RAW(RT_DEBUG_INFO | DBG_FUNC_RA, ("%s: QuickAGS: ++TX rate from %d to %d\n",
+ __FUNCTION__, CurrRateIdx, pEntry->CurrTxRateIndex));
+
+ pEntry->TxRateUpPenalty = 0;
+ pEntry->TxQuality[pEntry->CurrTxRateIndex] = 0; /*restore the TxQuality from max to 0 */
+ RTMPZeroMemory(pEntry->PER, sizeof(UCHAR) * (MAX_TX_RATE_INDEX+1));
+ }
+ else if ((pEntry->CurrTxRateIndex != CurrRateIdx) &&
+ (pEntry->LastSecTxRateChangeAction == 1)) /* Tx rate down */
+ {
+ DBGPRINT_RAW(RT_DEBUG_INFO | DBG_FUNC_RA, ("%s: QuickAGS: --TX rate from %d to %d\n",
+ __FUNCTION__, CurrRateIdx, pEntry->CurrTxRateIndex));
+
+ pEntry->TxRateUpPenalty = 0; /* No penalty */
+ pEntry->TxQuality[pEntry->CurrTxRateIndex] = 0;
+ pEntry->PER[pEntry->CurrTxRateIndex] = 0;
+ }
+ else
+ {
+ bTxRateChanged = FALSE;
+ DBGPRINT_RAW(RT_DEBUG_INFO | DBG_FUNC_RA, ("%s: QuickAGS: rate is not changed\n", __FUNCTION__));
+ }
+
+ pNextTxRate = (RTMP_RA_LEGACY_TB *)(&pTable[(pEntry->CurrTxRateIndex + 1) * SIZE_OF_AGS_RATE_TABLE_ENTRY]);
+ if ((bTxRateChanged == TRUE) && (pNextTxRate != NULL))
+ {
+ DBGPRINT_RAW(RT_DEBUG_INFO | DBG_FUNC_RA, ("ags> confirm current rate MCS = %d!\n", pEntry->CurrTxRateIndex));
+
+ APMlmeSetTxRate(pAd, pEntry, pNextTxRate);
+ }
+
+ /* reset all OneSecTx counters */
+ RESET_ONE_SEC_TX_CNT(pEntry);
+
+ DBGPRINT_RAW(RT_DEBUG_TRACE, ("QuickAGS: <--- %s\n", __FUNCTION__));
+}
+#endif /* CONFIG_AP_SUPPORT */
+
+#endif /* AGS_SUPPORT */
+