diff options
Diffstat (limited to 'drivers/net/wireless/ath/ath9k/ani.c')
-rw-r--r-- | drivers/net/wireless/ath/ath9k/ani.c | 217 |
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 | ||
19 | static int ath9k_hw_get_ani_channel_idx(struct ath_hw *ah, | 20 | static 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 | ||
40 | static 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 | |||
224 | static void ath9k_hw_update_mibstats(struct ath_hw *ah, | 41 | static 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 | ||
547 | void ath9k_hw_ani_monitor(struct ath_hw *ah, | 376 | void 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 | |||
821 | void 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 | } | ||