aboutsummaryrefslogtreecommitdiffstats
path: root/drivers/net/wireless/ath/ath9k/ani.c
diff options
context:
space:
mode:
Diffstat (limited to 'drivers/net/wireless/ath/ath9k/ani.c')
-rw-r--r--drivers/net/wireless/ath/ath9k/ani.c217
1 files changed, 24 insertions, 193 deletions
diff --git a/drivers/net/wireless/ath/ath9k/ani.c b/drivers/net/wireless/ath/ath9k/ani.c
index 2a0cd64c2bfb..ba8b20f01594 100644
--- a/drivers/net/wireless/ath/ath9k/ani.c
+++ b/drivers/net/wireless/ath/ath9k/ani.c
@@ -15,6 +15,7 @@
15 */ 15 */
16 16
17#include "hw.h" 17#include "hw.h"
18#include "hw-ops.h"
18 19
19static int ath9k_hw_get_ani_channel_idx(struct ath_hw *ah, 20static int ath9k_hw_get_ani_channel_idx(struct ath_hw *ah,
20 struct ath9k_channel *chan) 21 struct ath9k_channel *chan)
@@ -37,190 +38,6 @@ static int ath9k_hw_get_ani_channel_idx(struct ath_hw *ah,
37 return 0; 38 return 0;
38} 39}
39 40
40static bool ath9k_hw_ani_control(struct ath_hw *ah,
41 enum ath9k_ani_cmd cmd, int param)
42{
43 struct ar5416AniState *aniState = ah->curani;
44 struct ath_common *common = ath9k_hw_common(ah);
45
46 switch (cmd & ah->ani_function) {
47 case ATH9K_ANI_NOISE_IMMUNITY_LEVEL:{
48 u32 level = param;
49
50 if (level >= ARRAY_SIZE(ah->totalSizeDesired)) {
51 ath_print(common, ATH_DBG_ANI,
52 "level out of range (%u > %u)\n",
53 level,
54 (unsigned)ARRAY_SIZE(ah->totalSizeDesired));
55 return false;
56 }
57
58 REG_RMW_FIELD(ah, AR_PHY_DESIRED_SZ,
59 AR_PHY_DESIRED_SZ_TOT_DES,
60 ah->totalSizeDesired[level]);
61 REG_RMW_FIELD(ah, AR_PHY_AGC_CTL1,
62 AR_PHY_AGC_CTL1_COARSE_LOW,
63 ah->coarse_low[level]);
64 REG_RMW_FIELD(ah, AR_PHY_AGC_CTL1,
65 AR_PHY_AGC_CTL1_COARSE_HIGH,
66 ah->coarse_high[level]);
67 REG_RMW_FIELD(ah, AR_PHY_FIND_SIG,
68 AR_PHY_FIND_SIG_FIRPWR,
69 ah->firpwr[level]);
70
71 if (level > aniState->noiseImmunityLevel)
72 ah->stats.ast_ani_niup++;
73 else if (level < aniState->noiseImmunityLevel)
74 ah->stats.ast_ani_nidown++;
75 aniState->noiseImmunityLevel = level;
76 break;
77 }
78 case ATH9K_ANI_OFDM_WEAK_SIGNAL_DETECTION:{
79 const int m1ThreshLow[] = { 127, 50 };
80 const int m2ThreshLow[] = { 127, 40 };
81 const int m1Thresh[] = { 127, 0x4d };
82 const int m2Thresh[] = { 127, 0x40 };
83 const int m2CountThr[] = { 31, 16 };
84 const int m2CountThrLow[] = { 63, 48 };
85 u32 on = param ? 1 : 0;
86
87 REG_RMW_FIELD(ah, AR_PHY_SFCORR_LOW,
88 AR_PHY_SFCORR_LOW_M1_THRESH_LOW,
89 m1ThreshLow[on]);
90 REG_RMW_FIELD(ah, AR_PHY_SFCORR_LOW,
91 AR_PHY_SFCORR_LOW_M2_THRESH_LOW,
92 m2ThreshLow[on]);
93 REG_RMW_FIELD(ah, AR_PHY_SFCORR,
94 AR_PHY_SFCORR_M1_THRESH,
95 m1Thresh[on]);
96 REG_RMW_FIELD(ah, AR_PHY_SFCORR,
97 AR_PHY_SFCORR_M2_THRESH,
98 m2Thresh[on]);
99 REG_RMW_FIELD(ah, AR_PHY_SFCORR,
100 AR_PHY_SFCORR_M2COUNT_THR,
101 m2CountThr[on]);
102 REG_RMW_FIELD(ah, AR_PHY_SFCORR_LOW,
103 AR_PHY_SFCORR_LOW_M2COUNT_THR_LOW,
104 m2CountThrLow[on]);
105
106 REG_RMW_FIELD(ah, AR_PHY_SFCORR_EXT,
107 AR_PHY_SFCORR_EXT_M1_THRESH_LOW,
108 m1ThreshLow[on]);
109 REG_RMW_FIELD(ah, AR_PHY_SFCORR_EXT,
110 AR_PHY_SFCORR_EXT_M2_THRESH_LOW,
111 m2ThreshLow[on]);
112 REG_RMW_FIELD(ah, AR_PHY_SFCORR_EXT,
113 AR_PHY_SFCORR_EXT_M1_THRESH,
114 m1Thresh[on]);
115 REG_RMW_FIELD(ah, AR_PHY_SFCORR_EXT,
116 AR_PHY_SFCORR_EXT_M2_THRESH,
117 m2Thresh[on]);
118
119 if (on)
120 REG_SET_BIT(ah, AR_PHY_SFCORR_LOW,
121 AR_PHY_SFCORR_LOW_USE_SELF_CORR_LOW);
122 else
123 REG_CLR_BIT(ah, AR_PHY_SFCORR_LOW,
124 AR_PHY_SFCORR_LOW_USE_SELF_CORR_LOW);
125
126 if (!on != aniState->ofdmWeakSigDetectOff) {
127 if (on)
128 ah->stats.ast_ani_ofdmon++;
129 else
130 ah->stats.ast_ani_ofdmoff++;
131 aniState->ofdmWeakSigDetectOff = !on;
132 }
133 break;
134 }
135 case ATH9K_ANI_CCK_WEAK_SIGNAL_THR:{
136 const int weakSigThrCck[] = { 8, 6 };
137 u32 high = param ? 1 : 0;
138
139 REG_RMW_FIELD(ah, AR_PHY_CCK_DETECT,
140 AR_PHY_CCK_DETECT_WEAK_SIG_THR_CCK,
141 weakSigThrCck[high]);
142 if (high != aniState->cckWeakSigThreshold) {
143 if (high)
144 ah->stats.ast_ani_cckhigh++;
145 else
146 ah->stats.ast_ani_ccklow++;
147 aniState->cckWeakSigThreshold = high;
148 }
149 break;
150 }
151 case ATH9K_ANI_FIRSTEP_LEVEL:{
152 const int firstep[] = { 0, 4, 8 };
153 u32 level = param;
154
155 if (level >= ARRAY_SIZE(firstep)) {
156 ath_print(common, ATH_DBG_ANI,
157 "level out of range (%u > %u)\n",
158 level,
159 (unsigned) ARRAY_SIZE(firstep));
160 return false;
161 }
162 REG_RMW_FIELD(ah, AR_PHY_FIND_SIG,
163 AR_PHY_FIND_SIG_FIRSTEP,
164 firstep[level]);
165 if (level > aniState->firstepLevel)
166 ah->stats.ast_ani_stepup++;
167 else if (level < aniState->firstepLevel)
168 ah->stats.ast_ani_stepdown++;
169 aniState->firstepLevel = level;
170 break;
171 }
172 case ATH9K_ANI_SPUR_IMMUNITY_LEVEL:{
173 const int cycpwrThr1[] =
174 { 2, 4, 6, 8, 10, 12, 14, 16 };
175 u32 level = param;
176
177 if (level >= ARRAY_SIZE(cycpwrThr1)) {
178 ath_print(common, ATH_DBG_ANI,
179 "level out of range (%u > %u)\n",
180 level,
181 (unsigned) ARRAY_SIZE(cycpwrThr1));
182 return false;
183 }
184 REG_RMW_FIELD(ah, AR_PHY_TIMING5,
185 AR_PHY_TIMING5_CYCPWR_THR1,
186 cycpwrThr1[level]);
187 if (level > aniState->spurImmunityLevel)
188 ah->stats.ast_ani_spurup++;
189 else if (level < aniState->spurImmunityLevel)
190 ah->stats.ast_ani_spurdown++;
191 aniState->spurImmunityLevel = level;
192 break;
193 }
194 case ATH9K_ANI_PRESENT:
195 break;
196 default:
197 ath_print(common, ATH_DBG_ANI,
198 "invalid cmd %u\n", cmd);
199 return false;
200 }
201
202 ath_print(common, ATH_DBG_ANI, "ANI parameters:\n");
203 ath_print(common, ATH_DBG_ANI,
204 "noiseImmunityLevel=%d, spurImmunityLevel=%d, "
205 "ofdmWeakSigDetectOff=%d\n",
206 aniState->noiseImmunityLevel,
207 aniState->spurImmunityLevel,
208 !aniState->ofdmWeakSigDetectOff);
209 ath_print(common, ATH_DBG_ANI,
210 "cckWeakSigThreshold=%d, "
211 "firstepLevel=%d, listenTime=%d\n",
212 aniState->cckWeakSigThreshold,
213 aniState->firstepLevel,
214 aniState->listenTime);
215 ath_print(common, ATH_DBG_ANI,
216 "cycleCount=%d, ofdmPhyErrCount=%d, cckPhyErrCount=%d\n\n",
217 aniState->cycleCount,
218 aniState->ofdmPhyErrCount,
219 aniState->cckPhyErrCount);
220
221 return true;
222}
223
224static void ath9k_hw_update_mibstats(struct ath_hw *ah, 41static void ath9k_hw_update_mibstats(struct ath_hw *ah,
225 struct ath9k_mib_stats *stats) 42 struct ath9k_mib_stats *stats)
226{ 43{
@@ -262,11 +79,17 @@ static void ath9k_ani_restart(struct ath_hw *ah)
262 "Writing ofdmbase=%u cckbase=%u\n", 79 "Writing ofdmbase=%u cckbase=%u\n",
263 aniState->ofdmPhyErrBase, 80 aniState->ofdmPhyErrBase,
264 aniState->cckPhyErrBase); 81 aniState->cckPhyErrBase);
82
83 ENABLE_REGWRITE_BUFFER(ah);
84
265 REG_WRITE(ah, AR_PHY_ERR_1, aniState->ofdmPhyErrBase); 85 REG_WRITE(ah, AR_PHY_ERR_1, aniState->ofdmPhyErrBase);
266 REG_WRITE(ah, AR_PHY_ERR_2, aniState->cckPhyErrBase); 86 REG_WRITE(ah, AR_PHY_ERR_2, aniState->cckPhyErrBase);
267 REG_WRITE(ah, AR_PHY_ERR_MASK_1, AR_PHY_ERR_OFDM_TIMING); 87 REG_WRITE(ah, AR_PHY_ERR_MASK_1, AR_PHY_ERR_OFDM_TIMING);
268 REG_WRITE(ah, AR_PHY_ERR_MASK_2, AR_PHY_ERR_CCK_TIMING); 88 REG_WRITE(ah, AR_PHY_ERR_MASK_2, AR_PHY_ERR_CCK_TIMING);
269 89
90 REGWRITE_BUFFER_FLUSH(ah);
91 DISABLE_REGWRITE_BUFFER(ah);
92
270 ath9k_hw_update_mibstats(ah, &ah->ah_mibStats); 93 ath9k_hw_update_mibstats(ah, &ah->ah_mibStats);
271 94
272 aniState->ofdmPhyErrCount = 0; 95 aniState->ofdmPhyErrCount = 0;
@@ -540,8 +363,14 @@ void ath9k_ani_reset(struct ath_hw *ah)
540 ath9k_hw_setrxfilter(ah, ath9k_hw_getrxfilter(ah) & 363 ath9k_hw_setrxfilter(ah, ath9k_hw_getrxfilter(ah) &
541 ~ATH9K_RX_FILTER_PHYERR); 364 ~ATH9K_RX_FILTER_PHYERR);
542 ath9k_ani_restart(ah); 365 ath9k_ani_restart(ah);
366
367 ENABLE_REGWRITE_BUFFER(ah);
368
543 REG_WRITE(ah, AR_PHY_ERR_MASK_1, AR_PHY_ERR_OFDM_TIMING); 369 REG_WRITE(ah, AR_PHY_ERR_MASK_1, AR_PHY_ERR_OFDM_TIMING);
544 REG_WRITE(ah, AR_PHY_ERR_MASK_2, AR_PHY_ERR_CCK_TIMING); 370 REG_WRITE(ah, AR_PHY_ERR_MASK_2, AR_PHY_ERR_CCK_TIMING);
371
372 REGWRITE_BUFFER_FLUSH(ah);
373 DISABLE_REGWRITE_BUFFER(ah);
545} 374}
546 375
547void ath9k_hw_ani_monitor(struct ath_hw *ah, 376void ath9k_hw_ani_monitor(struct ath_hw *ah,
@@ -639,6 +468,8 @@ void ath9k_enable_mib_counters(struct ath_hw *ah)
639 468
640 ath9k_hw_update_mibstats(ah, &ah->ah_mibStats); 469 ath9k_hw_update_mibstats(ah, &ah->ah_mibStats);
641 470
471 ENABLE_REGWRITE_BUFFER(ah);
472
642 REG_WRITE(ah, AR_FILT_OFDM, 0); 473 REG_WRITE(ah, AR_FILT_OFDM, 0);
643 REG_WRITE(ah, AR_FILT_CCK, 0); 474 REG_WRITE(ah, AR_FILT_CCK, 0);
644 REG_WRITE(ah, AR_MIBC, 475 REG_WRITE(ah, AR_MIBC,
@@ -646,6 +477,9 @@ void ath9k_enable_mib_counters(struct ath_hw *ah)
646 & 0x0f); 477 & 0x0f);
647 REG_WRITE(ah, AR_PHY_ERR_MASK_1, AR_PHY_ERR_OFDM_TIMING); 478 REG_WRITE(ah, AR_PHY_ERR_MASK_1, AR_PHY_ERR_OFDM_TIMING);
648 REG_WRITE(ah, AR_PHY_ERR_MASK_2, AR_PHY_ERR_CCK_TIMING); 479 REG_WRITE(ah, AR_PHY_ERR_MASK_2, AR_PHY_ERR_CCK_TIMING);
480
481 REGWRITE_BUFFER_FLUSH(ah);
482 DISABLE_REGWRITE_BUFFER(ah);
649} 483}
650 484
651/* Freeze the MIB counters, get the stats and then clear them */ 485/* Freeze the MIB counters, get the stats and then clear them */
@@ -809,20 +643,17 @@ void ath9k_hw_ani_init(struct ath_hw *ah)
809 ath_print(common, ATH_DBG_ANI, "Setting cckErrBase = 0x%08x\n", 643 ath_print(common, ATH_DBG_ANI, "Setting cckErrBase = 0x%08x\n",
810 ah->ani[0].cckPhyErrBase); 644 ah->ani[0].cckPhyErrBase);
811 645
646 ENABLE_REGWRITE_BUFFER(ah);
647
812 REG_WRITE(ah, AR_PHY_ERR_1, ah->ani[0].ofdmPhyErrBase); 648 REG_WRITE(ah, AR_PHY_ERR_1, ah->ani[0].ofdmPhyErrBase);
813 REG_WRITE(ah, AR_PHY_ERR_2, ah->ani[0].cckPhyErrBase); 649 REG_WRITE(ah, AR_PHY_ERR_2, ah->ani[0].cckPhyErrBase);
650
651 REGWRITE_BUFFER_FLUSH(ah);
652 DISABLE_REGWRITE_BUFFER(ah);
653
814 ath9k_enable_mib_counters(ah); 654 ath9k_enable_mib_counters(ah);
815 655
816 ah->aniperiod = ATH9K_ANI_PERIOD; 656 ah->aniperiod = ATH9K_ANI_PERIOD;
817 if (ah->config.enable_ani) 657 if (ah->config.enable_ani)
818 ah->proc_phyerr |= HAL_PROCESS_ANI; 658 ah->proc_phyerr |= HAL_PROCESS_ANI;
819} 659}
820
821void ath9k_hw_ani_disable(struct ath_hw *ah)
822{
823 ath_print(ath9k_hw_common(ah), ATH_DBG_ANI, "Disabling ANI\n");
824
825 ath9k_hw_disable_mib_counters(ah);
826 REG_WRITE(ah, AR_PHY_ERR_1, 0);
827 REG_WRITE(ah, AR_PHY_ERR_2, 0);
828}