1/*++
2Copyright (c) Realtek Semiconductor Corp. All rights reserved.
3
4Module Name:
5	RateAdaptive.c
6
7Abstract:
8	Implement Rate Adaptive functions for common operations.
9
10Major Change History:
11	When       Who               What
12	---------- ---------------   -------------------------------
13	2011-08-12 Page            Create.
14
15--*/
16#include "odm_precomp.h"
17
18/*  Rate adaptive parameters */
19
20static u8 RETRY_PENALTY[PERENTRY][RETRYSIZE+1] = {
21		{5, 4, 3, 2, 0, 3},      /* 92 , idx = 0 */
22		{6, 5, 4, 3, 0, 4},      /* 86 , idx = 1 */
23		{6, 5, 4, 2, 0, 4},      /* 81 , idx = 2 */
24		{8, 7, 6, 4, 0, 6},      /* 75 , idx = 3 */
25		{10, 9, 8, 6, 0, 8},     /* 71	, idx = 4 */
26		{10, 9, 8, 4, 0, 8},     /* 66	, idx = 5 */
27		{10, 9, 8, 2, 0, 8},     /* 62	, idx = 6 */
28		{10, 9, 8, 0, 0, 8},     /* 59	, idx = 7 */
29		{18, 17, 16, 8, 0, 16},  /* 53 , idx = 8 */
30		{26, 25, 24, 16, 0, 24}, /* 50	, idx = 9 */
31		{34, 33, 32, 24, 0, 32}, /* 47	, idx = 0x0a */
32		{34, 31, 28, 20, 0, 32}, /* 43	, idx = 0x0b */
33		{34, 31, 27, 18, 0, 32}, /* 40 , idx = 0x0c */
34		{34, 31, 26, 16, 0, 32}, /* 37 , idx = 0x0d */
35		{34, 30, 22, 16, 0, 32}, /* 32 , idx = 0x0e */
36		{34, 30, 24, 16, 0, 32}, /* 26 , idx = 0x0f */
37		{49, 46, 40, 16, 0, 48}, /* 20	, idx = 0x10 */
38		{49, 45, 32, 0, 0, 48},  /* 17 , idx = 0x11 */
39		{49, 45, 22, 18, 0, 48}, /* 15	, idx = 0x12 */
40		{49, 40, 24, 16, 0, 48}, /* 12	, idx = 0x13 */
41		{49, 32, 18, 12, 0, 48}, /* 9 , idx = 0x14 */
42		{49, 22, 18, 14, 0, 48}, /* 6 , idx = 0x15 */
43		{49, 16, 16, 0, 0, 48}
44	}; /* 3, idx = 0x16 */
45
46static u8 PT_PENALTY[RETRYSIZE+1] = {34, 31, 30, 24, 0, 32};
47
48/*  wilson modify */
49static u8 RETRY_PENALTY_IDX[2][RATESIZE] = {
50		{4, 4, 4, 5, 4, 4, 5, 7, 7, 7, 8, 0x0a,	       /*  SS>TH */
51		4, 4, 4, 4, 6, 0x0a, 0x0b, 0x0d,
52		5, 5, 7, 7, 8, 0x0b, 0x0d, 0x0f},			   /*  0329 R01 */
53		{0x0a, 0x0a, 0x0b, 0x0c, 0x0a,
54		0x0a, 0x0b, 0x0c, 0x0d, 0x10, 0x13, 0x14,	   /*  SS<TH */
55		0x0b, 0x0c, 0x0d, 0x0e, 0x0f, 0x11, 0x13, 0x15,
56		9, 9, 9, 9, 0x0c, 0x0e, 0x11, 0x13}
57	};
58
59static u8 RETRY_PENALTY_UP_IDX[RATESIZE] = {
60		0x0c, 0x0d, 0x0d, 0x0f, 0x0d, 0x0e,
61		0x0f, 0x0f, 0x10, 0x12, 0x13, 0x14,	       /*  SS>TH */
62		0x0f, 0x10, 0x10, 0x12, 0x12, 0x13, 0x14, 0x15,
63		0x11, 0x11, 0x12, 0x13, 0x13, 0x13, 0x14, 0x15};
64
65static u8 RSSI_THRESHOLD[RATESIZE] = {
66		0, 0, 0, 0,
67		0, 0, 0, 0, 0, 0x24, 0x26, 0x2a,
68		0x18, 0x1a, 0x1d, 0x1f, 0x21, 0x27, 0x29, 0x2a,
69		0, 0, 0, 0x1f, 0x23, 0x28, 0x2a, 0x2c};
70
71static u16 N_THRESHOLD_HIGH[RATESIZE] = {
72		4, 4, 8, 16,
73		24, 36, 48, 72, 96, 144, 192, 216,
74		60, 80, 100, 160, 240, 400, 560, 640,
75		300, 320, 480, 720, 1000, 1200, 1600, 2000};
76static u16 N_THRESHOLD_LOW[RATESIZE] = {
77		2, 2, 4, 8,
78		12, 18, 24, 36, 48, 72, 96, 108,
79		30, 40, 50, 80, 120, 200, 280, 320,
80		150, 160, 240, 360, 500, 600, 800, 1000};
81
82static u8 DROPING_NECESSARY[RATESIZE] = {
83		1, 1, 1, 1,
84		1, 2, 3, 4, 5, 6, 7, 8,
85		1, 2, 3, 4, 5, 6, 7, 8,
86		5, 6, 7, 8, 9, 10, 11, 12};
87
88static u8 PendingForRateUpFail[5] = {2, 10, 24, 40, 60};
89static u16 DynamicTxRPTTiming[6] = {
90	0x186a, 0x30d4, 0x493e, 0x61a8, 0x7a12 , 0x927c}; /*  200ms-1200ms */
91
92/*  End Rate adaptive parameters */
93
94static void odm_SetTxRPTTiming_8188E(
95		struct odm_dm_struct *dm_odm,
96		struct odm_ra_info *pRaInfo,
97		u8 extend
98	)
99{
100	u8 idx = 0;
101
102	for (idx = 0; idx < 5; idx++)
103		if (DynamicTxRPTTiming[idx] == pRaInfo->RptTime)
104			break;
105
106	if (extend == 0) { /*  back to default timing */
107		idx = 0;  /* 200ms */
108	} else if (extend == 1) {/*  increase the timing */
109		idx += 1;
110		if (idx > 5)
111			idx = 5;
112	} else if (extend == 2) {/*  decrease the timing */
113		if (idx != 0)
114			idx -= 1;
115	}
116	pRaInfo->RptTime = DynamicTxRPTTiming[idx];
117
118	ODM_RT_TRACE(dm_odm, ODM_COMP_RATE_ADAPTIVE, ODM_DBG_LOUD,
119			("pRaInfo->RptTime = 0x%x\n", pRaInfo->RptTime));
120}
121
122static int odm_RateDown_8188E(struct odm_dm_struct *dm_odm,
123				struct odm_ra_info *pRaInfo)
124{
125	u8 RateID, LowestRate, HighestRate;
126	u8 i;
127
128	ODM_RT_TRACE(dm_odm, ODM_COMP_RATE_ADAPTIVE,
129			ODM_DBG_TRACE, ("=====>odm_RateDown_8188E()\n"));
130	if (NULL == pRaInfo) {
131		ODM_RT_TRACE(dm_odm, ODM_COMP_RATE_ADAPTIVE, ODM_DBG_LOUD,
132				("odm_RateDown_8188E(): pRaInfo is NULL\n"));
133		return -1;
134	}
135	RateID = pRaInfo->PreRate;
136	LowestRate = pRaInfo->LowestRate;
137	HighestRate = pRaInfo->HighestRate;
138
139	ODM_RT_TRACE(dm_odm, ODM_COMP_RATE_ADAPTIVE, ODM_DBG_TRACE,
140		     (" RateID =%d LowestRate =%d HighestRate =%d RateSGI =%d\n",
141		     RateID, LowestRate, HighestRate, pRaInfo->RateSGI));
142	if (RateID > HighestRate) {
143		RateID = HighestRate;
144	} else if (pRaInfo->RateSGI) {
145		pRaInfo->RateSGI = 0;
146	} else if (RateID > LowestRate) {
147		if (RateID > 0) {
148			for (i = RateID-1; i > LowestRate; i--) {
149				if (pRaInfo->RAUseRate & BIT(i)) {
150					RateID = i;
151					goto RateDownFinish;
152				}
153			}
154		}
155	} else if (RateID <= LowestRate) {
156		RateID = LowestRate;
157	}
158RateDownFinish:
159	if (pRaInfo->RAWaitingCounter == 1) {
160		pRaInfo->RAWaitingCounter += 1;
161		pRaInfo->RAPendingCounter += 1;
162	} else if (pRaInfo->RAWaitingCounter == 0) {
163		;
164	} else {
165		pRaInfo->RAWaitingCounter = 0;
166		pRaInfo->RAPendingCounter = 0;
167	}
168
169	if (pRaInfo->RAPendingCounter >= 4)
170		pRaInfo->RAPendingCounter = 4;
171
172	pRaInfo->DecisionRate = RateID;
173	odm_SetTxRPTTiming_8188E(dm_odm, pRaInfo, 2);
174	ODM_RT_TRACE(dm_odm, ODM_COMP_RATE_ADAPTIVE,
175			ODM_DBG_LOUD, ("Rate down, RPT Timing default\n"));
176	ODM_RT_TRACE(dm_odm, ODM_COMP_RATE_ADAPTIVE, ODM_DBG_TRACE,
177			("RAWaitingCounter %d, RAPendingCounter %d",
178			 pRaInfo->RAWaitingCounter, pRaInfo->RAPendingCounter));
179	ODM_RT_TRACE(dm_odm, ODM_COMP_RATE_ADAPTIVE, ODM_DBG_LOUD,
180			("Rate down to RateID %d RateSGI %d\n", RateID, pRaInfo->RateSGI));
181	ODM_RT_TRACE(dm_odm, ODM_COMP_RATE_ADAPTIVE, ODM_DBG_TRACE,
182			("<===== odm_RateDown_8188E()\n"));
183	return 0;
184}
185
186static int odm_RateUp_8188E(
187		struct odm_dm_struct *dm_odm,
188		struct odm_ra_info *pRaInfo
189	)
190{
191	u8 RateID, HighestRate;
192	u8 i;
193
194	ODM_RT_TRACE(dm_odm, ODM_COMP_RATE_ADAPTIVE,
195			ODM_DBG_TRACE, ("=====>odm_RateUp_8188E()\n"));
196	if (NULL == pRaInfo) {
197		ODM_RT_TRACE(dm_odm, ODM_COMP_RATE_ADAPTIVE, ODM_DBG_LOUD,
198				("odm_RateUp_8188E(): pRaInfo is NULL\n"));
199		return -1;
200	}
201	RateID = pRaInfo->PreRate;
202	HighestRate = pRaInfo->HighestRate;
203	ODM_RT_TRACE(dm_odm, ODM_COMP_RATE_ADAPTIVE, ODM_DBG_TRACE,
204		     (" RateID =%d HighestRate =%d\n",
205		     RateID, HighestRate));
206	if (pRaInfo->RAWaitingCounter == 1) {
207		pRaInfo->RAWaitingCounter = 0;
208		pRaInfo->RAPendingCounter = 0;
209	} else if (pRaInfo->RAWaitingCounter > 1) {
210		pRaInfo->PreRssiStaRA = pRaInfo->RssiStaRA;
211		goto RateUpfinish;
212	}
213	odm_SetTxRPTTiming_8188E(dm_odm, pRaInfo, 0);
214	ODM_RT_TRACE(dm_odm, ODM_COMP_RATE_ADAPTIVE, ODM_DBG_LOUD,
215			("odm_RateUp_8188E():Decrease RPT Timing\n"));
216
217	if (RateID < HighestRate) {
218		for (i = RateID+1; i <= HighestRate; i++) {
219			if (pRaInfo->RAUseRate & BIT(i)) {
220				RateID = i;
221				goto RateUpfinish;
222			}
223		}
224	} else if (RateID == HighestRate) {
225		if (pRaInfo->SGIEnable && (pRaInfo->RateSGI != 1))
226			pRaInfo->RateSGI = 1;
227		else if ((pRaInfo->SGIEnable) != 1)
228			pRaInfo->RateSGI = 0;
229	} else {
230		RateID = HighestRate;
231	}
232RateUpfinish:
233	if (pRaInfo->RAWaitingCounter ==
234		(4+PendingForRateUpFail[pRaInfo->RAPendingCounter]))
235		pRaInfo->RAWaitingCounter = 0;
236	else
237		pRaInfo->RAWaitingCounter++;
238
239	pRaInfo->DecisionRate = RateID;
240	ODM_RT_TRACE(dm_odm, ODM_COMP_RATE_ADAPTIVE, ODM_DBG_LOUD,
241			("Rate up to RateID %d\n", RateID));
242	ODM_RT_TRACE(dm_odm, ODM_COMP_RATE_ADAPTIVE, ODM_DBG_TRACE,
243			("RAWaitingCounter %d, RAPendingCounter %d",
244			 pRaInfo->RAWaitingCounter, pRaInfo->RAPendingCounter));
245	ODM_RT_TRACE(dm_odm, ODM_COMP_RATE_ADAPTIVE,
246			ODM_DBG_TRACE, ("<===== odm_RateUp_8188E()\n"));
247	return 0;
248}
249
250static void odm_ResetRaCounter_8188E(struct odm_ra_info *pRaInfo)
251{
252	u8 RateID;
253
254	RateID = pRaInfo->DecisionRate;
255	pRaInfo->NscUp = (N_THRESHOLD_HIGH[RateID]+N_THRESHOLD_LOW[RateID])>>1;
256	pRaInfo->NscDown = (N_THRESHOLD_HIGH[RateID]+N_THRESHOLD_LOW[RateID])>>1;
257}
258
259static void odm_RateDecision_8188E(struct odm_dm_struct *dm_odm,
260		struct odm_ra_info *pRaInfo
261	)
262{
263	u8 RateID = 0, RtyPtID = 0, PenaltyID1 = 0, PenaltyID2 = 0, i = 0;
264	/* u32 pool_retry; */
265	static u8 DynamicTxRPTTimingCounter;
266
267	ODM_RT_TRACE(dm_odm, ODM_COMP_RATE_ADAPTIVE, ODM_DBG_TRACE,
268			("=====>odm_RateDecision_8188E()\n"));
269
270	if (pRaInfo->Active && (pRaInfo->TOTAL > 0)) { /*  STA used and data packet exits */
271		if ((pRaInfo->RssiStaRA < (pRaInfo->PreRssiStaRA - 3)) ||
272		    (pRaInfo->RssiStaRA > (pRaInfo->PreRssiStaRA + 3))) {
273			pRaInfo->RAWaitingCounter = 0;
274			pRaInfo->RAPendingCounter = 0;
275		}
276		/*  Start RA decision */
277		if (pRaInfo->PreRate > pRaInfo->HighestRate)
278			RateID = pRaInfo->HighestRate;
279		else
280			RateID = pRaInfo->PreRate;
281		if (pRaInfo->RssiStaRA > RSSI_THRESHOLD[RateID])
282			RtyPtID = 0;
283		else
284			RtyPtID = 1;
285		PenaltyID1 = RETRY_PENALTY_IDX[RtyPtID][RateID]; /* TODO by page */
286
287		ODM_RT_TRACE(dm_odm, ODM_COMP_RATE_ADAPTIVE, ODM_DBG_TRACE,
288			     (" NscDown init is %d\n", pRaInfo->NscDown));
289
290		for (i = 0 ; i <= 4 ; i++)
291			pRaInfo->NscDown += pRaInfo->RTY[i] * RETRY_PENALTY[PenaltyID1][i];
292
293		ODM_RT_TRACE(dm_odm, ODM_COMP_RATE_ADAPTIVE, ODM_DBG_TRACE,
294			     (" NscDown is %d, total*penalty[5] is %d\n", pRaInfo->NscDown,
295			      (pRaInfo->TOTAL * RETRY_PENALTY[PenaltyID1][5])));
296
297		if (pRaInfo->NscDown > (pRaInfo->TOTAL * RETRY_PENALTY[PenaltyID1][5]))
298			pRaInfo->NscDown -= pRaInfo->TOTAL * RETRY_PENALTY[PenaltyID1][5];
299		else
300			pRaInfo->NscDown = 0;
301
302		/*  rate up */
303		PenaltyID2 = RETRY_PENALTY_UP_IDX[RateID];
304		ODM_RT_TRACE(dm_odm, ODM_COMP_RATE_ADAPTIVE, ODM_DBG_TRACE,
305			     (" NscUp init is %d\n", pRaInfo->NscUp));
306
307		for (i = 0 ; i <= 4 ; i++)
308			pRaInfo->NscUp += pRaInfo->RTY[i] * RETRY_PENALTY[PenaltyID2][i];
309
310		ODM_RT_TRACE(dm_odm, ODM_COMP_RATE_ADAPTIVE, ODM_DBG_TRACE,
311			     ("NscUp is %d, total*up[5] is %d\n",
312			     pRaInfo->NscUp, (pRaInfo->TOTAL * RETRY_PENALTY[PenaltyID2][5])));
313
314		if (pRaInfo->NscUp > (pRaInfo->TOTAL * RETRY_PENALTY[PenaltyID2][5]))
315			pRaInfo->NscUp -= pRaInfo->TOTAL * RETRY_PENALTY[PenaltyID2][5];
316		else
317			pRaInfo->NscUp = 0;
318
319		ODM_RT_TRACE(dm_odm, ODM_COMP_RATE_ADAPTIVE|ODM_COMP_INIT, ODM_DBG_LOUD,
320			     (" RssiStaRa = %d RtyPtID =%d PenaltyID1 = 0x%x  PenaltyID2 = 0x%x RateID =%d NscDown =%d NscUp =%d SGI =%d\n",
321			     pRaInfo->RssiStaRA, RtyPtID, PenaltyID1, PenaltyID2, RateID, pRaInfo->NscDown, pRaInfo->NscUp, pRaInfo->RateSGI));
322		if ((pRaInfo->NscDown < N_THRESHOLD_LOW[RateID]) ||
323		    (pRaInfo->DROP > DROPING_NECESSARY[RateID]))
324			odm_RateDown_8188E(dm_odm, pRaInfo);
325		else if (pRaInfo->NscUp > N_THRESHOLD_HIGH[RateID])
326			odm_RateUp_8188E(dm_odm, pRaInfo);
327
328		if (pRaInfo->DecisionRate > pRaInfo->HighestRate)
329			pRaInfo->DecisionRate = pRaInfo->HighestRate;
330
331		if ((pRaInfo->DecisionRate) == (pRaInfo->PreRate))
332			DynamicTxRPTTimingCounter += 1;
333		else
334			DynamicTxRPTTimingCounter = 0;
335
336		if (DynamicTxRPTTimingCounter >= 4) {
337			odm_SetTxRPTTiming_8188E(dm_odm, pRaInfo, 1);
338			ODM_RT_TRACE(dm_odm, ODM_COMP_RATE_ADAPTIVE,
339				     ODM_DBG_LOUD, ("<===== Rate don't change 4 times, Extend RPT Timing\n"));
340			DynamicTxRPTTimingCounter = 0;
341		}
342
343		pRaInfo->PreRate = pRaInfo->DecisionRate;  /* YJ, add, 120120 */
344
345		odm_ResetRaCounter_8188E(pRaInfo);
346	}
347	ODM_RT_TRACE(dm_odm, ODM_COMP_RATE_ADAPTIVE, ODM_DBG_TRACE, ("<===== odm_RateDecision_8188E()\n"));
348}
349
350static int odm_ARFBRefresh_8188E(struct odm_dm_struct *dm_odm, struct odm_ra_info *pRaInfo)
351{  /*  Wilson 2011/10/26 */
352	struct adapter *adapt = dm_odm->Adapter;
353	u32 MaskFromReg;
354	s8 i;
355
356	switch (pRaInfo->RateID) {
357	case RATR_INX_WIRELESS_NGB:
358		pRaInfo->RAUseRate = (pRaInfo->RateMask)&0x0f8ff015;
359		break;
360	case RATR_INX_WIRELESS_NG:
361		pRaInfo->RAUseRate = (pRaInfo->RateMask)&0x0f8ff010;
362		break;
363	case RATR_INX_WIRELESS_NB:
364		pRaInfo->RAUseRate = (pRaInfo->RateMask)&0x0f8ff005;
365		break;
366	case RATR_INX_WIRELESS_N:
367		pRaInfo->RAUseRate = (pRaInfo->RateMask)&0x0f8ff000;
368		break;
369	case RATR_INX_WIRELESS_GB:
370		pRaInfo->RAUseRate = (pRaInfo->RateMask)&0x00000ff5;
371		break;
372	case RATR_INX_WIRELESS_G:
373		pRaInfo->RAUseRate = (pRaInfo->RateMask)&0x00000ff0;
374		break;
375	case RATR_INX_WIRELESS_B:
376		pRaInfo->RAUseRate = (pRaInfo->RateMask)&0x0000000d;
377		break;
378	case 12:
379		MaskFromReg = usb_read32(adapt, REG_ARFR0);
380		pRaInfo->RAUseRate = (pRaInfo->RateMask)&MaskFromReg;
381		break;
382	case 13:
383		MaskFromReg = usb_read32(adapt, REG_ARFR1);
384		pRaInfo->RAUseRate = (pRaInfo->RateMask)&MaskFromReg;
385		break;
386	case 14:
387		MaskFromReg = usb_read32(adapt, REG_ARFR2);
388		pRaInfo->RAUseRate = (pRaInfo->RateMask)&MaskFromReg;
389		break;
390	case 15:
391		MaskFromReg = usb_read32(adapt, REG_ARFR3);
392		pRaInfo->RAUseRate = (pRaInfo->RateMask)&MaskFromReg;
393		break;
394	default:
395		pRaInfo->RAUseRate = (pRaInfo->RateMask);
396		break;
397	}
398	/*  Highest rate */
399	if (pRaInfo->RAUseRate) {
400		for (i = RATESIZE; i >= 0; i--) {
401			if ((pRaInfo->RAUseRate)&BIT(i)) {
402				pRaInfo->HighestRate = i;
403				break;
404			}
405		}
406	} else {
407		pRaInfo->HighestRate = 0;
408	}
409	/*  Lowest rate */
410	if (pRaInfo->RAUseRate) {
411		for (i = 0; i < RATESIZE; i++) {
412			if ((pRaInfo->RAUseRate) & BIT(i)) {
413				pRaInfo->LowestRate = i;
414				break;
415			}
416		}
417	} else {
418		pRaInfo->LowestRate = 0;
419	}
420		if (pRaInfo->HighestRate > 0x13)
421			pRaInfo->PTModeSS = 3;
422		else if (pRaInfo->HighestRate > 0x0b)
423			pRaInfo->PTModeSS = 2;
424		else if (pRaInfo->HighestRate > 0x0b)
425			pRaInfo->PTModeSS = 1;
426		else
427			pRaInfo->PTModeSS = 0;
428	ODM_RT_TRACE(dm_odm, ODM_COMP_RATE_ADAPTIVE, ODM_DBG_LOUD,
429		     ("ODM_ARFBRefresh_8188E(): PTModeSS =%d\n", pRaInfo->PTModeSS));
430
431	if (pRaInfo->DecisionRate > pRaInfo->HighestRate)
432		pRaInfo->DecisionRate = pRaInfo->HighestRate;
433
434	ODM_RT_TRACE(dm_odm, ODM_COMP_RATE_ADAPTIVE, ODM_DBG_LOUD,
435		     ("ODM_ARFBRefresh_8188E(): RateID =%d RateMask =%8.8x RAUseRate =%8.8x HighestRate =%d, DecisionRate =%d\n",
436		     pRaInfo->RateID, pRaInfo->RateMask, pRaInfo->RAUseRate, pRaInfo->HighestRate, pRaInfo->DecisionRate));
437	return 0;
438}
439
440static void odm_PTTryState_8188E(struct odm_ra_info *pRaInfo)
441{
442	pRaInfo->PTTryState = 0;
443	switch (pRaInfo->PTModeSS) {
444	case 3:
445		if (pRaInfo->DecisionRate >= 0x19)
446			pRaInfo->PTTryState = 1;
447		break;
448	case 2:
449		if (pRaInfo->DecisionRate >= 0x11)
450			pRaInfo->PTTryState = 1;
451		break;
452	case 1:
453		if (pRaInfo->DecisionRate >= 0x0a)
454			pRaInfo->PTTryState = 1;
455		break;
456	case 0:
457		if (pRaInfo->DecisionRate >= 0x03)
458			pRaInfo->PTTryState = 1;
459		break;
460	default:
461		pRaInfo->PTTryState = 0;
462		break;
463	}
464
465	if (pRaInfo->RssiStaRA < 48) {
466		pRaInfo->PTStage = 0;
467	} else if (pRaInfo->PTTryState == 1) {
468		if ((pRaInfo->PTStopCount >= 10) ||
469		    (pRaInfo->PTPreRssi > pRaInfo->RssiStaRA + 5) ||
470		    (pRaInfo->PTPreRssi < pRaInfo->RssiStaRA - 5) ||
471		    (pRaInfo->DecisionRate != pRaInfo->PTPreRate)) {
472			if (pRaInfo->PTStage == 0)
473				pRaInfo->PTStage = 1;
474			else if (pRaInfo->PTStage == 1)
475				pRaInfo->PTStage = 3;
476			else
477				pRaInfo->PTStage = 5;
478
479			pRaInfo->PTPreRssi = pRaInfo->RssiStaRA;
480			pRaInfo->PTStopCount = 0;
481		} else {
482			pRaInfo->RAstage = 0;
483			pRaInfo->PTStopCount++;
484		}
485	} else {
486		pRaInfo->PTStage = 0;
487		pRaInfo->RAstage = 0;
488	}
489	pRaInfo->PTPreRate = pRaInfo->DecisionRate;
490}
491
492static void odm_PTDecision_8188E(struct odm_ra_info *pRaInfo)
493{
494	u8 j;
495	u8 temp_stage;
496	u32 numsc;
497	u32 num_total;
498	u8 stage_id;
499
500	numsc  = 0;
501	num_total = pRaInfo->TOTAL * PT_PENALTY[5];
502	for (j = 0; j <= 4; j++) {
503		numsc += pRaInfo->RTY[j] * PT_PENALTY[j];
504		if (numsc > num_total)
505			break;
506	}
507
508	j >>= 1;
509	temp_stage = (pRaInfo->PTStage + 1) >> 1;
510	if (temp_stage > j)
511		stage_id = temp_stage-j;
512	else
513		stage_id = 0;
514
515	pRaInfo->PTSmoothFactor = (pRaInfo->PTSmoothFactor>>1) + (pRaInfo->PTSmoothFactor>>2) + stage_id*16+2;
516	if (pRaInfo->PTSmoothFactor > 192)
517		pRaInfo->PTSmoothFactor = 192;
518	stage_id = pRaInfo->PTSmoothFactor >> 6;
519	temp_stage = stage_id*2;
520	if (temp_stage != 0)
521		temp_stage -= 1;
522	if (pRaInfo->DROP > 3)
523		temp_stage = 0;
524	pRaInfo->PTStage = temp_stage;
525}
526
527static void
528odm_RATxRPTTimerSetting(
529		struct odm_dm_struct *dm_odm,
530		u16 minRptTime
531)
532{
533	ODM_RT_TRACE(dm_odm, ODM_COMP_RATE_ADAPTIVE, ODM_DBG_TRACE, (" =====>odm_RATxRPTTimerSetting()\n"));
534
535	if (dm_odm->CurrminRptTime != minRptTime) {
536		ODM_RT_TRACE(dm_odm, ODM_COMP_RATE_ADAPTIVE, ODM_DBG_LOUD,
537			     (" CurrminRptTime = 0x%04x minRptTime = 0x%04x\n", dm_odm->CurrminRptTime, minRptTime));
538		rtw_rpt_timer_cfg_cmd(dm_odm->Adapter, minRptTime);
539		dm_odm->CurrminRptTime = minRptTime;
540	}
541	ODM_RT_TRACE(dm_odm, ODM_COMP_RATE_ADAPTIVE, ODM_DBG_TRACE, (" <===== odm_RATxRPTTimerSetting()\n"));
542}
543
544void
545ODM_RASupport_Init(
546		struct odm_dm_struct *dm_odm
547	)
548{
549	ODM_RT_TRACE(dm_odm, ODM_COMP_RATE_ADAPTIVE, ODM_DBG_LOUD, ("=====>ODM_RASupport_Init()\n"));
550
551	dm_odm->RaSupport88E = true;
552}
553
554int ODM_RAInfo_Init(struct odm_dm_struct *dm_odm, u8 macid)
555{
556	struct odm_ra_info *pRaInfo = &dm_odm->RAInfo[macid];
557	u8 WirelessMode = 0xFF; /* invalid value */
558	u8 max_rate_idx = 0x13; /* MCS7 */
559
560	if (dm_odm->pWirelessMode != NULL)
561		WirelessMode = *(dm_odm->pWirelessMode);
562
563	if (WirelessMode != 0xFF) {
564		if (WirelessMode & ODM_WM_N24G)
565			max_rate_idx = 0x13;
566		else if (WirelessMode & ODM_WM_G)
567			max_rate_idx = 0x0b;
568		else if (WirelessMode & ODM_WM_B)
569			max_rate_idx = 0x03;
570	}
571
572	ODM_RT_TRACE(dm_odm, ODM_COMP_RATE_ADAPTIVE, ODM_DBG_LOUD,
573		     ("ODM_RAInfo_Init(): WirelessMode:0x%08x , max_raid_idx:0x%02x\n",
574		     WirelessMode, max_rate_idx));
575
576	pRaInfo->DecisionRate = max_rate_idx;
577	pRaInfo->PreRate = max_rate_idx;
578	pRaInfo->HighestRate = max_rate_idx;
579	pRaInfo->LowestRate = 0;
580	pRaInfo->RateID = 0;
581	pRaInfo->RateMask = 0xffffffff;
582	pRaInfo->RssiStaRA = 0;
583	pRaInfo->PreRssiStaRA = 0;
584	pRaInfo->SGIEnable = 0;
585	pRaInfo->RAUseRate = 0xffffffff;
586	pRaInfo->NscDown = (N_THRESHOLD_HIGH[0x13]+N_THRESHOLD_LOW[0x13])/2;
587	pRaInfo->NscUp = (N_THRESHOLD_HIGH[0x13]+N_THRESHOLD_LOW[0x13])/2;
588	pRaInfo->RateSGI = 0;
589	pRaInfo->Active = 1;	/* Active is not used at present. by page, 110819 */
590	pRaInfo->RptTime = 0x927c;
591	pRaInfo->DROP = 0;
592	pRaInfo->RTY[0] = 0;
593	pRaInfo->RTY[1] = 0;
594	pRaInfo->RTY[2] = 0;
595	pRaInfo->RTY[3] = 0;
596	pRaInfo->RTY[4] = 0;
597	pRaInfo->TOTAL = 0;
598	pRaInfo->RAWaitingCounter = 0;
599	pRaInfo->RAPendingCounter = 0;
600	pRaInfo->PTActive = 1;   /*  Active when this STA is use */
601	pRaInfo->PTTryState = 0;
602	pRaInfo->PTStage = 5; /*  Need to fill into HW_PWR_STATUS */
603	pRaInfo->PTSmoothFactor = 192;
604	pRaInfo->PTStopCount = 0;
605	pRaInfo->PTPreRate = 0;
606	pRaInfo->PTPreRssi = 0;
607	pRaInfo->PTModeSS = 0;
608	pRaInfo->RAstage = 0;
609	return 0;
610}
611
612int ODM_RAInfo_Init_all(struct odm_dm_struct *dm_odm)
613{
614	u8 macid = 0;
615
616	ODM_RT_TRACE(dm_odm, ODM_COMP_RATE_ADAPTIVE, ODM_DBG_LOUD, ("=====>\n"));
617	dm_odm->CurrminRptTime = 0;
618
619	for (macid = 0; macid < ODM_ASSOCIATE_ENTRY_NUM; macid++)
620		ODM_RAInfo_Init(dm_odm, macid);
621
622	return 0;
623}
624
625u8 ODM_RA_GetShortGI_8188E(struct odm_dm_struct *dm_odm, u8 macid)
626{
627	if ((NULL == dm_odm) || (macid >= ASSOCIATE_ENTRY_NUM))
628		return 0;
629	ODM_RT_TRACE(dm_odm, ODM_COMP_RATE_ADAPTIVE, ODM_DBG_TRACE,
630		     ("macid =%d SGI =%d\n", macid, dm_odm->RAInfo[macid].RateSGI));
631	return dm_odm->RAInfo[macid].RateSGI;
632}
633
634u8 ODM_RA_GetDecisionRate_8188E(struct odm_dm_struct *dm_odm, u8 macid)
635{
636	u8 DecisionRate = 0;
637
638	if ((NULL == dm_odm) || (macid >= ASSOCIATE_ENTRY_NUM))
639		return 0;
640	DecisionRate = dm_odm->RAInfo[macid].DecisionRate;
641	ODM_RT_TRACE(dm_odm, ODM_COMP_RATE_ADAPTIVE, ODM_DBG_TRACE,
642		(" macid =%d DecisionRate = 0x%x\n", macid, DecisionRate));
643	return DecisionRate;
644}
645
646u8 ODM_RA_GetHwPwrStatus_8188E(struct odm_dm_struct *dm_odm, u8 macid)
647{
648	u8 PTStage = 5;
649
650	if ((NULL == dm_odm) || (macid >= ASSOCIATE_ENTRY_NUM))
651		return 0;
652	PTStage = dm_odm->RAInfo[macid].PTStage;
653	ODM_RT_TRACE(dm_odm, ODM_COMP_RATE_ADAPTIVE, ODM_DBG_TRACE,
654		     ("macid =%d PTStage = 0x%x\n", macid, PTStage));
655	return PTStage;
656}
657
658void ODM_RA_UpdateRateInfo_8188E(struct odm_dm_struct *dm_odm, u8 macid, u8 RateID, u32 RateMask, u8 SGIEnable)
659{
660	struct odm_ra_info *pRaInfo = NULL;
661
662	ODM_RT_TRACE(dm_odm, ODM_COMP_RATE_ADAPTIVE, ODM_DBG_LOUD,
663		     ("macid =%d RateID = 0x%x RateMask = 0x%x SGIEnable =%d\n",
664		     macid, RateID, RateMask, SGIEnable));
665	if ((NULL == dm_odm) || (macid >= ASSOCIATE_ENTRY_NUM))
666		return;
667
668	pRaInfo = &(dm_odm->RAInfo[macid]);
669	pRaInfo->RateID = RateID;
670	pRaInfo->RateMask = RateMask;
671	pRaInfo->SGIEnable = SGIEnable;
672	odm_ARFBRefresh_8188E(dm_odm, pRaInfo);
673}
674
675void ODM_RA_SetRSSI_8188E(struct odm_dm_struct *dm_odm, u8 macid, u8 Rssi)
676{
677	struct odm_ra_info *pRaInfo = NULL;
678
679	ODM_RT_TRACE(dm_odm, ODM_COMP_RATE_ADAPTIVE, ODM_DBG_TRACE,
680		     (" macid =%d Rssi =%d\n", macid, Rssi));
681	if ((NULL == dm_odm) || (macid >= ASSOCIATE_ENTRY_NUM))
682		return;
683
684	pRaInfo = &(dm_odm->RAInfo[macid]);
685	pRaInfo->RssiStaRA = Rssi;
686}
687
688void ODM_RA_Set_TxRPT_Time(struct odm_dm_struct *dm_odm, u16 minRptTime)
689{
690	struct adapter *adapt = dm_odm->Adapter;
691
692	usb_write16(adapt, REG_TX_RPT_TIME, minRptTime);
693}
694
695void ODM_RA_TxRPT2Handle_8188E(struct odm_dm_struct *dm_odm, u8 *TxRPT_Buf, u16 TxRPT_Len, u32 macid_entry0, u32 macid_entry1)
696{
697	struct odm_ra_info *pRAInfo = NULL;
698	u8 MacId = 0;
699	u8 *pBuffer = NULL;
700	u32 valid = 0, ItemNum = 0;
701	u16 minRptTime = 0x927c;
702
703	ODM_RT_TRACE(dm_odm, ODM_COMP_RATE_ADAPTIVE, ODM_DBG_LOUD,
704		     ("=====>ODM_RA_TxRPT2Handle_8188E(): valid0 =%d valid1 =%d BufferLength =%d\n",
705		     macid_entry0, macid_entry1, TxRPT_Len));
706
707	ItemNum = TxRPT_Len >> 3;
708	pBuffer = TxRPT_Buf;
709
710	do {
711		if (MacId >= ASSOCIATE_ENTRY_NUM)
712			valid = 0;
713		else if (MacId >= 32)
714			valid = (1 << (MacId - 32)) & macid_entry1;
715		else
716			valid = (1 << MacId) & macid_entry0;
717
718		pRAInfo = &(dm_odm->RAInfo[MacId]);
719		if (valid) {
720			pRAInfo->RTY[0] = (u16)GET_TX_REPORT_TYPE1_RERTY_0(pBuffer);
721			pRAInfo->RTY[1] = (u16)GET_TX_REPORT_TYPE1_RERTY_1(pBuffer);
722			pRAInfo->RTY[2] = (u16)GET_TX_REPORT_TYPE1_RERTY_2(pBuffer);
723			pRAInfo->RTY[3] = (u16)GET_TX_REPORT_TYPE1_RERTY_3(pBuffer);
724			pRAInfo->RTY[4] = (u16)GET_TX_REPORT_TYPE1_RERTY_4(pBuffer);
725			pRAInfo->DROP =   (u16)GET_TX_REPORT_TYPE1_DROP_0(pBuffer);
726			pRAInfo->TOTAL = pRAInfo->RTY[0] + pRAInfo->RTY[1] +
727					 pRAInfo->RTY[2] + pRAInfo->RTY[3] +
728					 pRAInfo->RTY[4] + pRAInfo->DROP;
729			if (pRAInfo->TOTAL != 0) {
730				ODM_RT_TRACE(dm_odm, ODM_COMP_RATE_ADAPTIVE, ODM_DBG_LOUD,
731					     ("macid =%d Total =%d R0 =%d R1 =%d R2 =%d R3 =%d R4 =%d D0 =%d valid0 =%x valid1 =%x\n",
732					     MacId, pRAInfo->TOTAL,
733					     pRAInfo->RTY[0], pRAInfo->RTY[1],
734					     pRAInfo->RTY[2], pRAInfo->RTY[3],
735					     pRAInfo->RTY[4], pRAInfo->DROP,
736					     macid_entry0 , macid_entry1));
737				if (pRAInfo->PTActive) {
738					if (pRAInfo->RAstage < 5)
739						odm_RateDecision_8188E(dm_odm, pRAInfo);
740					else if (pRAInfo->RAstage == 5) /*  Power training try state */
741						odm_PTTryState_8188E(pRAInfo);
742					else /*  RAstage == 6 */
743						odm_PTDecision_8188E(pRAInfo);
744
745					/*  Stage_RA counter */
746					if (pRAInfo->RAstage <= 5)
747						pRAInfo->RAstage++;
748					else
749						pRAInfo->RAstage = 0;
750				} else {
751					odm_RateDecision_8188E(dm_odm, pRAInfo);
752				}
753				ODM_RT_TRACE(dm_odm, ODM_COMP_INIT, ODM_DBG_LOUD,
754					     ("macid =%d R0 =%d R1 =%d R2 =%d R3 =%d R4 =%d drop =%d valid0 =%x RateID =%d SGI =%d\n",
755					     MacId,
756					     pRAInfo->RTY[0],
757					     pRAInfo->RTY[1],
758					     pRAInfo->RTY[2],
759					     pRAInfo->RTY[3],
760					     pRAInfo->RTY[4],
761					     pRAInfo->DROP,
762					     macid_entry0,
763					     pRAInfo->DecisionRate,
764					     pRAInfo->RateSGI));
765			} else {
766				ODM_RT_TRACE(dm_odm, ODM_COMP_RATE_ADAPTIVE, ODM_DBG_LOUD, (" TOTAL = 0!!!!\n"));
767			}
768		}
769
770		if (minRptTime > pRAInfo->RptTime)
771			minRptTime = pRAInfo->RptTime;
772
773		pBuffer += TX_RPT2_ITEM_SIZE;
774		MacId++;
775	} while (MacId < ItemNum);
776
777	odm_RATxRPTTimerSetting(dm_odm, minRptTime);
778
779	ODM_RT_TRACE(dm_odm, ODM_COMP_RATE_ADAPTIVE, ODM_DBG_LOUD, ("<===== ODM_RA_TxRPT2Handle_8188E()\n"));
780}
781