ath9k_hw: clean up register write buffering
[pandora-kernel.git] / drivers / net / wireless / ath / ath9k / ani.c
1 /*
2  * Copyright (c) 2008-2010 Atheros Communications Inc.
3  *
4  * Permission to use, copy, modify, and/or distribute this software for any
5  * purpose with or without fee is hereby granted, provided that the above
6  * copyright notice and this permission notice appear in all copies.
7  *
8  * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
9  * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
10  * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
11  * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
12  * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
13  * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
14  * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
15  */
16
17 #include <linux/kernel.h>
18 #include "hw.h"
19 #include "hw-ops.h"
20
21 struct ani_ofdm_level_entry {
22         int spur_immunity_level;
23         int fir_step_level;
24         int ofdm_weak_signal_on;
25 };
26
27 /* values here are relative to the INI */
28
29 /*
30  * Legend:
31  *
32  * SI: Spur immunity
33  * FS: FIR Step
34  * WS: OFDM / CCK Weak Signal detection
35  * MRC-CCK: Maximal Ratio Combining for CCK
36  */
37
38 static const struct ani_ofdm_level_entry ofdm_level_table[] = {
39         /* SI  FS  WS */
40         {  0,  0,  1  }, /* lvl 0 */
41         {  1,  1,  1  }, /* lvl 1 */
42         {  2,  2,  1  }, /* lvl 2 */
43         {  3,  2,  1  }, /* lvl 3  (default) */
44         {  4,  3,  1  }, /* lvl 4 */
45         {  5,  4,  1  }, /* lvl 5 */
46         {  6,  5,  1  }, /* lvl 6 */
47         {  7,  6,  1  }, /* lvl 7 */
48         {  7,  7,  1  }, /* lvl 8 */
49         {  7,  8,  0  }  /* lvl 9 */
50 };
51 #define ATH9K_ANI_OFDM_NUM_LEVEL \
52         ARRAY_SIZE(ofdm_level_table)
53 #define ATH9K_ANI_OFDM_MAX_LEVEL \
54         (ATH9K_ANI_OFDM_NUM_LEVEL-1)
55 #define ATH9K_ANI_OFDM_DEF_LEVEL \
56         3 /* default level - matches the INI settings */
57
58 /*
59  * MRC (Maximal Ratio Combining) has always been used with multi-antenna ofdm.
60  * With OFDM for single stream you just add up all antenna inputs, you're
61  * only interested in what you get after FFT. Signal aligment is also not
62  * required for OFDM because any phase difference adds up in the frequency
63  * domain.
64  *
65  * MRC requires extra work for use with CCK. You need to align the antenna
66  * signals from the different antenna before you can add the signals together.
67  * You need aligment of signals as CCK is in time domain, so addition can cancel
68  * your signal completely if phase is 180 degrees (think of adding sine waves).
69  * You also need to remove noise before the addition and this is where ANI
70  * MRC CCK comes into play. One of the antenna inputs may be stronger but
71  * lower SNR, so just adding after alignment can be dangerous.
72  *
73  * Regardless of alignment in time, the antenna signals add constructively after
74  * FFT and improve your reception. For more information:
75  *
76  * http://en.wikipedia.org/wiki/Maximal-ratio_combining
77  */
78
79 struct ani_cck_level_entry {
80         int fir_step_level;
81         int mrc_cck_on;
82 };
83
84 static const struct ani_cck_level_entry cck_level_table[] = {
85         /* FS  MRC-CCK  */
86         {  0,  1  }, /* lvl 0 */
87         {  1,  1  }, /* lvl 1 */
88         {  2,  1  }, /* lvl 2  (default) */
89         {  3,  1  }, /* lvl 3 */
90         {  4,  0  }, /* lvl 4 */
91         {  5,  0  }, /* lvl 5 */
92         {  6,  0  }, /* lvl 6 */
93         {  7,  0  }, /* lvl 7 (only for high rssi) */
94         {  8,  0  }  /* lvl 8 (only for high rssi) */
95 };
96
97 #define ATH9K_ANI_CCK_NUM_LEVEL \
98         ARRAY_SIZE(cck_level_table)
99 #define ATH9K_ANI_CCK_MAX_LEVEL \
100         (ATH9K_ANI_CCK_NUM_LEVEL-1)
101 #define ATH9K_ANI_CCK_MAX_LEVEL_LOW_RSSI \
102         (ATH9K_ANI_CCK_NUM_LEVEL-3)
103 #define ATH9K_ANI_CCK_DEF_LEVEL \
104         2 /* default level - matches the INI settings */
105
106 /* Private to ani.c */
107 static void ath9k_hw_ani_lower_immunity(struct ath_hw *ah)
108 {
109         ath9k_hw_private_ops(ah)->ani_lower_immunity(ah);
110 }
111
112 int ath9k_hw_get_ani_channel_idx(struct ath_hw *ah,
113                                  struct ath9k_channel *chan)
114 {
115         int i;
116
117         for (i = 0; i < ARRAY_SIZE(ah->ani); i++) {
118                 if (ah->ani[i].c &&
119                     ah->ani[i].c->channel == chan->channel)
120                         return i;
121                 if (ah->ani[i].c == NULL) {
122                         ah->ani[i].c = chan;
123                         return i;
124                 }
125         }
126
127         ath_print(ath9k_hw_common(ah), ATH_DBG_ANI,
128                   "No more channel states left. Using channel 0\n");
129
130         return 0;
131 }
132
133 static void ath9k_hw_update_mibstats(struct ath_hw *ah,
134                                      struct ath9k_mib_stats *stats)
135 {
136         stats->ackrcv_bad += REG_READ(ah, AR_ACK_FAIL);
137         stats->rts_bad += REG_READ(ah, AR_RTS_FAIL);
138         stats->fcs_bad += REG_READ(ah, AR_FCS_FAIL);
139         stats->rts_good += REG_READ(ah, AR_RTS_OK);
140         stats->beacons += REG_READ(ah, AR_BEACON_CNT);
141 }
142
143 static void ath9k_ani_restart_old(struct ath_hw *ah)
144 {
145         struct ar5416AniState *aniState;
146         struct ath_common *common = ath9k_hw_common(ah);
147
148         if (!DO_ANI(ah))
149                 return;
150
151         aniState = ah->curani;
152         aniState->listenTime = 0;
153
154         if (aniState->ofdmTrigHigh > AR_PHY_COUNTMAX) {
155                 aniState->ofdmPhyErrBase = 0;
156                 ath_print(common, ATH_DBG_ANI,
157                           "OFDM Trigger is too high for hw counters\n");
158         } else {
159                 aniState->ofdmPhyErrBase =
160                         AR_PHY_COUNTMAX - aniState->ofdmTrigHigh;
161         }
162         if (aniState->cckTrigHigh > AR_PHY_COUNTMAX) {
163                 aniState->cckPhyErrBase = 0;
164                 ath_print(common, ATH_DBG_ANI,
165                           "CCK Trigger is too high for hw counters\n");
166         } else {
167                 aniState->cckPhyErrBase =
168                         AR_PHY_COUNTMAX - aniState->cckTrigHigh;
169         }
170         ath_print(common, ATH_DBG_ANI,
171                   "Writing ofdmbase=%u   cckbase=%u\n",
172                   aniState->ofdmPhyErrBase,
173                   aniState->cckPhyErrBase);
174
175         ENABLE_REGWRITE_BUFFER(ah);
176
177         REG_WRITE(ah, AR_PHY_ERR_1, aniState->ofdmPhyErrBase);
178         REG_WRITE(ah, AR_PHY_ERR_2, aniState->cckPhyErrBase);
179         REG_WRITE(ah, AR_PHY_ERR_MASK_1, AR_PHY_ERR_OFDM_TIMING);
180         REG_WRITE(ah, AR_PHY_ERR_MASK_2, AR_PHY_ERR_CCK_TIMING);
181
182         REGWRITE_BUFFER_FLUSH(ah);
183
184         ath9k_hw_update_mibstats(ah, &ah->ah_mibStats);
185
186         aniState->ofdmPhyErrCount = 0;
187         aniState->cckPhyErrCount = 0;
188 }
189
190 static void ath9k_ani_restart_new(struct ath_hw *ah)
191 {
192         struct ar5416AniState *aniState;
193         struct ath_common *common = ath9k_hw_common(ah);
194
195         if (!DO_ANI(ah))
196                 return;
197
198         aniState = ah->curani;
199         aniState->listenTime = 0;
200
201         aniState->ofdmPhyErrBase = 0;
202         aniState->cckPhyErrBase = 0;
203
204         ath_print(common, ATH_DBG_ANI,
205                   "Writing ofdmbase=%08x   cckbase=%08x\n",
206                   aniState->ofdmPhyErrBase,
207                   aniState->cckPhyErrBase);
208
209         ENABLE_REGWRITE_BUFFER(ah);
210
211         REG_WRITE(ah, AR_PHY_ERR_1, aniState->ofdmPhyErrBase);
212         REG_WRITE(ah, AR_PHY_ERR_2, aniState->cckPhyErrBase);
213         REG_WRITE(ah, AR_PHY_ERR_MASK_1, AR_PHY_ERR_OFDM_TIMING);
214         REG_WRITE(ah, AR_PHY_ERR_MASK_2, AR_PHY_ERR_CCK_TIMING);
215
216         REGWRITE_BUFFER_FLUSH(ah);
217
218         ath9k_hw_update_mibstats(ah, &ah->ah_mibStats);
219
220         aniState->ofdmPhyErrCount = 0;
221         aniState->cckPhyErrCount = 0;
222 }
223
224 static void ath9k_hw_ani_ofdm_err_trigger_old(struct ath_hw *ah)
225 {
226         struct ieee80211_conf *conf = &ath9k_hw_common(ah)->hw->conf;
227         struct ar5416AniState *aniState;
228         int32_t rssi;
229
230         if (!DO_ANI(ah))
231                 return;
232
233         aniState = ah->curani;
234
235         if (aniState->noiseImmunityLevel < HAL_NOISE_IMMUNE_MAX) {
236                 if (ath9k_hw_ani_control(ah, ATH9K_ANI_NOISE_IMMUNITY_LEVEL,
237                                          aniState->noiseImmunityLevel + 1)) {
238                         return;
239                 }
240         }
241
242         if (aniState->spurImmunityLevel < HAL_SPUR_IMMUNE_MAX) {
243                 if (ath9k_hw_ani_control(ah, ATH9K_ANI_SPUR_IMMUNITY_LEVEL,
244                                          aniState->spurImmunityLevel + 1)) {
245                         return;
246                 }
247         }
248
249         if (ah->opmode == NL80211_IFTYPE_AP) {
250                 if (aniState->firstepLevel < HAL_FIRST_STEP_MAX) {
251                         ath9k_hw_ani_control(ah, ATH9K_ANI_FIRSTEP_LEVEL,
252                                              aniState->firstepLevel + 1);
253                 }
254                 return;
255         }
256         rssi = BEACON_RSSI(ah);
257         if (rssi > aniState->rssiThrHigh) {
258                 if (!aniState->ofdmWeakSigDetectOff) {
259                         if (ath9k_hw_ani_control(ah,
260                                          ATH9K_ANI_OFDM_WEAK_SIGNAL_DETECTION,
261                                          false)) {
262                                 ath9k_hw_ani_control(ah,
263                                         ATH9K_ANI_SPUR_IMMUNITY_LEVEL, 0);
264                                 return;
265                         }
266                 }
267                 if (aniState->firstepLevel < HAL_FIRST_STEP_MAX) {
268                         ath9k_hw_ani_control(ah, ATH9K_ANI_FIRSTEP_LEVEL,
269                                              aniState->firstepLevel + 1);
270                         return;
271                 }
272         } else if (rssi > aniState->rssiThrLow) {
273                 if (aniState->ofdmWeakSigDetectOff)
274                         ath9k_hw_ani_control(ah,
275                                      ATH9K_ANI_OFDM_WEAK_SIGNAL_DETECTION,
276                                      true);
277                 if (aniState->firstepLevel < HAL_FIRST_STEP_MAX)
278                         ath9k_hw_ani_control(ah, ATH9K_ANI_FIRSTEP_LEVEL,
279                                              aniState->firstepLevel + 1);
280                 return;
281         } else {
282                 if ((conf->channel->band == IEEE80211_BAND_2GHZ) &&
283                     !conf_is_ht(conf)) {
284                         if (!aniState->ofdmWeakSigDetectOff)
285                                 ath9k_hw_ani_control(ah,
286                                      ATH9K_ANI_OFDM_WEAK_SIGNAL_DETECTION,
287                                      false);
288                         if (aniState->firstepLevel > 0)
289                                 ath9k_hw_ani_control(ah,
290                                              ATH9K_ANI_FIRSTEP_LEVEL, 0);
291                         return;
292                 }
293         }
294 }
295
296 static void ath9k_hw_ani_cck_err_trigger_old(struct ath_hw *ah)
297 {
298         struct ieee80211_conf *conf = &ath9k_hw_common(ah)->hw->conf;
299         struct ar5416AniState *aniState;
300         int32_t rssi;
301
302         if (!DO_ANI(ah))
303                 return;
304
305         aniState = ah->curani;
306         if (aniState->noiseImmunityLevel < HAL_NOISE_IMMUNE_MAX) {
307                 if (ath9k_hw_ani_control(ah, ATH9K_ANI_NOISE_IMMUNITY_LEVEL,
308                                          aniState->noiseImmunityLevel + 1)) {
309                         return;
310                 }
311         }
312         if (ah->opmode == NL80211_IFTYPE_AP) {
313                 if (aniState->firstepLevel < HAL_FIRST_STEP_MAX) {
314                         ath9k_hw_ani_control(ah, ATH9K_ANI_FIRSTEP_LEVEL,
315                                              aniState->firstepLevel + 1);
316                 }
317                 return;
318         }
319         rssi = BEACON_RSSI(ah);
320         if (rssi > aniState->rssiThrLow) {
321                 if (aniState->firstepLevel < HAL_FIRST_STEP_MAX)
322                         ath9k_hw_ani_control(ah, ATH9K_ANI_FIRSTEP_LEVEL,
323                                              aniState->firstepLevel + 1);
324         } else {
325                 if ((conf->channel->band == IEEE80211_BAND_2GHZ) &&
326                     !conf_is_ht(conf)) {
327                         if (aniState->firstepLevel > 0)
328                                 ath9k_hw_ani_control(ah,
329                                              ATH9K_ANI_FIRSTEP_LEVEL, 0);
330                 }
331         }
332 }
333
334 /* Adjust the OFDM Noise Immunity Level */
335 static void ath9k_hw_set_ofdm_nil(struct ath_hw *ah, u8 immunityLevel)
336 {
337         struct ar5416AniState *aniState = ah->curani;
338         struct ath_common *common = ath9k_hw_common(ah);
339         const struct ani_ofdm_level_entry *entry_ofdm;
340         const struct ani_cck_level_entry *entry_cck;
341
342         aniState->noiseFloor = BEACON_RSSI(ah);
343
344         ath_print(common, ATH_DBG_ANI,
345                   "**** ofdmlevel %d=>%d, rssi=%d[lo=%d hi=%d]\n",
346                   aniState->ofdmNoiseImmunityLevel,
347                   immunityLevel, aniState->noiseFloor,
348                   aniState->rssiThrLow, aniState->rssiThrHigh);
349
350         aniState->ofdmNoiseImmunityLevel = immunityLevel;
351
352         entry_ofdm = &ofdm_level_table[aniState->ofdmNoiseImmunityLevel];
353         entry_cck = &cck_level_table[aniState->cckNoiseImmunityLevel];
354
355         if (aniState->spurImmunityLevel != entry_ofdm->spur_immunity_level)
356                 ath9k_hw_ani_control(ah,
357                                      ATH9K_ANI_SPUR_IMMUNITY_LEVEL,
358                                      entry_ofdm->spur_immunity_level);
359
360         if (aniState->firstepLevel != entry_ofdm->fir_step_level &&
361             entry_ofdm->fir_step_level >= entry_cck->fir_step_level)
362                 ath9k_hw_ani_control(ah,
363                                      ATH9K_ANI_FIRSTEP_LEVEL,
364                                      entry_ofdm->fir_step_level);
365
366         if ((ah->opmode != NL80211_IFTYPE_STATION &&
367              ah->opmode != NL80211_IFTYPE_ADHOC) ||
368             aniState->noiseFloor <= aniState->rssiThrHigh) {
369                 if (aniState->ofdmWeakSigDetectOff)
370                         /* force on ofdm weak sig detect */
371                         ath9k_hw_ani_control(ah,
372                                 ATH9K_ANI_OFDM_WEAK_SIGNAL_DETECTION,
373                                              true);
374                 else if (aniState->ofdmWeakSigDetectOff ==
375                          entry_ofdm->ofdm_weak_signal_on)
376                         ath9k_hw_ani_control(ah,
377                                 ATH9K_ANI_OFDM_WEAK_SIGNAL_DETECTION,
378                                 entry_ofdm->ofdm_weak_signal_on);
379         }
380 }
381
382 static void ath9k_hw_ani_ofdm_err_trigger_new(struct ath_hw *ah)
383 {
384         struct ar5416AniState *aniState;
385
386         if (!DO_ANI(ah))
387                 return;
388
389         aniState = ah->curani;
390
391         if (aniState->ofdmNoiseImmunityLevel < ATH9K_ANI_OFDM_MAX_LEVEL)
392                 ath9k_hw_set_ofdm_nil(ah, aniState->ofdmNoiseImmunityLevel + 1);
393 }
394
395 /*
396  * Set the ANI settings to match an CCK level.
397  */
398 static void ath9k_hw_set_cck_nil(struct ath_hw *ah, u_int8_t immunityLevel)
399 {
400         struct ar5416AniState *aniState = ah->curani;
401         struct ath_common *common = ath9k_hw_common(ah);
402         const struct ani_ofdm_level_entry *entry_ofdm;
403         const struct ani_cck_level_entry *entry_cck;
404
405         aniState->noiseFloor = BEACON_RSSI(ah);
406         ath_print(common, ATH_DBG_ANI,
407                   "**** ccklevel %d=>%d, rssi=%d[lo=%d hi=%d]\n",
408                   aniState->cckNoiseImmunityLevel, immunityLevel,
409                   aniState->noiseFloor, aniState->rssiThrLow,
410                   aniState->rssiThrHigh);
411
412         if ((ah->opmode == NL80211_IFTYPE_STATION ||
413              ah->opmode == NL80211_IFTYPE_ADHOC) &&
414             aniState->noiseFloor <= aniState->rssiThrLow &&
415             immunityLevel > ATH9K_ANI_CCK_MAX_LEVEL_LOW_RSSI)
416                 immunityLevel = ATH9K_ANI_CCK_MAX_LEVEL_LOW_RSSI;
417
418         aniState->cckNoiseImmunityLevel = immunityLevel;
419
420         entry_ofdm = &ofdm_level_table[aniState->ofdmNoiseImmunityLevel];
421         entry_cck = &cck_level_table[aniState->cckNoiseImmunityLevel];
422
423         if (aniState->firstepLevel != entry_cck->fir_step_level &&
424             entry_cck->fir_step_level >= entry_ofdm->fir_step_level)
425                 ath9k_hw_ani_control(ah,
426                                      ATH9K_ANI_FIRSTEP_LEVEL,
427                                      entry_cck->fir_step_level);
428
429         /* Skip MRC CCK for pre AR9003 families */
430         if (!AR_SREV_9300_20_OR_LATER(ah))
431                 return;
432
433         if (aniState->mrcCCKOff == entry_cck->mrc_cck_on)
434                 ath9k_hw_ani_control(ah,
435                                      ATH9K_ANI_MRC_CCK,
436                                      entry_cck->mrc_cck_on);
437 }
438
439 static void ath9k_hw_ani_cck_err_trigger_new(struct ath_hw *ah)
440 {
441         struct ar5416AniState *aniState;
442
443         if (!DO_ANI(ah))
444                 return;
445
446         aniState = ah->curani;
447
448         if (aniState->cckNoiseImmunityLevel < ATH9K_ANI_CCK_MAX_LEVEL)
449                 ath9k_hw_set_cck_nil(ah, aniState->cckNoiseImmunityLevel + 1);
450 }
451
452 static void ath9k_hw_ani_lower_immunity_old(struct ath_hw *ah)
453 {
454         struct ar5416AniState *aniState;
455         int32_t rssi;
456
457         aniState = ah->curani;
458
459         if (ah->opmode == NL80211_IFTYPE_AP) {
460                 if (aniState->firstepLevel > 0) {
461                         if (ath9k_hw_ani_control(ah, ATH9K_ANI_FIRSTEP_LEVEL,
462                                                  aniState->firstepLevel - 1))
463                                 return;
464                 }
465         } else {
466                 rssi = BEACON_RSSI(ah);
467                 if (rssi > aniState->rssiThrHigh) {
468                         /* XXX: Handle me */
469                 } else if (rssi > aniState->rssiThrLow) {
470                         if (aniState->ofdmWeakSigDetectOff) {
471                                 if (ath9k_hw_ani_control(ah,
472                                          ATH9K_ANI_OFDM_WEAK_SIGNAL_DETECTION,
473                                          true) == true)
474                                         return;
475                         }
476                         if (aniState->firstepLevel > 0) {
477                                 if (ath9k_hw_ani_control(ah,
478                                          ATH9K_ANI_FIRSTEP_LEVEL,
479                                          aniState->firstepLevel - 1) == true)
480                                         return;
481                         }
482                 } else {
483                         if (aniState->firstepLevel > 0) {
484                                 if (ath9k_hw_ani_control(ah,
485                                          ATH9K_ANI_FIRSTEP_LEVEL,
486                                          aniState->firstepLevel - 1) == true)
487                                         return;
488                         }
489                 }
490         }
491
492         if (aniState->spurImmunityLevel > 0) {
493                 if (ath9k_hw_ani_control(ah, ATH9K_ANI_SPUR_IMMUNITY_LEVEL,
494                                          aniState->spurImmunityLevel - 1))
495                         return;
496         }
497
498         if (aniState->noiseImmunityLevel > 0) {
499                 ath9k_hw_ani_control(ah, ATH9K_ANI_NOISE_IMMUNITY_LEVEL,
500                                      aniState->noiseImmunityLevel - 1);
501                 return;
502         }
503 }
504
505 /*
506  * only lower either OFDM or CCK errors per turn
507  * we lower the other one next time
508  */
509 static void ath9k_hw_ani_lower_immunity_new(struct ath_hw *ah)
510 {
511         struct ar5416AniState *aniState;
512
513         aniState = ah->curani;
514
515         /* lower OFDM noise immunity */
516         if (aniState->ofdmNoiseImmunityLevel > 0 &&
517             (aniState->ofdmsTurn || aniState->cckNoiseImmunityLevel == 0)) {
518                 ath9k_hw_set_ofdm_nil(ah, aniState->ofdmNoiseImmunityLevel - 1);
519                 return;
520         }
521
522         /* lower CCK noise immunity */
523         if (aniState->cckNoiseImmunityLevel > 0)
524                 ath9k_hw_set_cck_nil(ah, aniState->cckNoiseImmunityLevel - 1);
525 }
526
527 static u8 ath9k_hw_chan_2_clockrate_mhz(struct ath_hw *ah)
528 {
529         struct ath9k_channel *chan = ah->curchan;
530         struct ieee80211_conf *conf = &ath9k_hw_common(ah)->hw->conf;
531         u8 clockrate; /* in MHz */
532
533         if (!ah->curchan) /* should really check for CCK instead */
534                 clockrate = ATH9K_CLOCK_RATE_CCK;
535         else if (conf->channel->band == IEEE80211_BAND_2GHZ)
536                 clockrate = ATH9K_CLOCK_RATE_2GHZ_OFDM;
537         else if (IS_CHAN_A_FAST_CLOCK(ah, chan))
538                 clockrate = ATH9K_CLOCK_FAST_RATE_5GHZ_OFDM;
539         else
540                 clockrate = ATH9K_CLOCK_RATE_5GHZ_OFDM;
541
542         if (conf_is_ht40(conf))
543                 return clockrate * 2;
544
545         return clockrate;
546 }
547
548 static int32_t ath9k_hw_ani_get_listen_time(struct ath_hw *ah)
549 {
550         int32_t listen_time;
551         int32_t clock_rate;
552
553         ath9k_hw_update_cycle_counters(ah);
554         clock_rate = ath9k_hw_chan_2_clockrate_mhz(ah) * 1000;
555         listen_time = ah->listen_time / clock_rate;
556         ah->listen_time = 0;
557
558         return listen_time;
559 }
560
561 static void ath9k_ani_reset_old(struct ath_hw *ah, bool is_scanning)
562 {
563         struct ar5416AniState *aniState;
564         struct ath9k_channel *chan = ah->curchan;
565         struct ath_common *common = ath9k_hw_common(ah);
566         int index;
567
568         if (!DO_ANI(ah))
569                 return;
570
571         index = ath9k_hw_get_ani_channel_idx(ah, chan);
572         aniState = &ah->ani[index];
573         ah->curani = aniState;
574
575         if (DO_ANI(ah) && ah->opmode != NL80211_IFTYPE_STATION
576             && ah->opmode != NL80211_IFTYPE_ADHOC) {
577                 ath_print(common, ATH_DBG_ANI,
578                           "Reset ANI state opmode %u\n", ah->opmode);
579                 ah->stats.ast_ani_reset++;
580
581                 if (ah->opmode == NL80211_IFTYPE_AP) {
582                         /*
583                          * ath9k_hw_ani_control() will only process items set on
584                          * ah->ani_function
585                          */
586                         if (IS_CHAN_2GHZ(chan))
587                                 ah->ani_function = (ATH9K_ANI_SPUR_IMMUNITY_LEVEL |
588                                                     ATH9K_ANI_FIRSTEP_LEVEL);
589                         else
590                                 ah->ani_function = 0;
591                 }
592
593                 ath9k_hw_ani_control(ah, ATH9K_ANI_NOISE_IMMUNITY_LEVEL, 0);
594                 ath9k_hw_ani_control(ah, ATH9K_ANI_SPUR_IMMUNITY_LEVEL, 0);
595                 ath9k_hw_ani_control(ah, ATH9K_ANI_FIRSTEP_LEVEL, 0);
596                 ath9k_hw_ani_control(ah, ATH9K_ANI_OFDM_WEAK_SIGNAL_DETECTION,
597                                      !ATH9K_ANI_USE_OFDM_WEAK_SIG);
598                 ath9k_hw_ani_control(ah, ATH9K_ANI_CCK_WEAK_SIGNAL_THR,
599                                      ATH9K_ANI_CCK_WEAK_SIG_THR);
600
601                 ath9k_hw_setrxfilter(ah, ath9k_hw_getrxfilter(ah) |
602                                      ATH9K_RX_FILTER_PHYERR);
603
604                 if (ah->opmode == NL80211_IFTYPE_AP) {
605                         ah->curani->ofdmTrigHigh =
606                                 ah->config.ofdm_trig_high;
607                         ah->curani->ofdmTrigLow =
608                                 ah->config.ofdm_trig_low;
609                         ah->curani->cckTrigHigh =
610                                 ah->config.cck_trig_high;
611                         ah->curani->cckTrigLow =
612                                 ah->config.cck_trig_low;
613                 }
614                 ath9k_ani_restart_old(ah);
615                 return;
616         }
617
618         if (aniState->noiseImmunityLevel != 0)
619                 ath9k_hw_ani_control(ah, ATH9K_ANI_NOISE_IMMUNITY_LEVEL,
620                                      aniState->noiseImmunityLevel);
621         if (aniState->spurImmunityLevel != 0)
622                 ath9k_hw_ani_control(ah, ATH9K_ANI_SPUR_IMMUNITY_LEVEL,
623                                      aniState->spurImmunityLevel);
624         if (aniState->ofdmWeakSigDetectOff)
625                 ath9k_hw_ani_control(ah, ATH9K_ANI_OFDM_WEAK_SIGNAL_DETECTION,
626                                      !aniState->ofdmWeakSigDetectOff);
627         if (aniState->cckWeakSigThreshold)
628                 ath9k_hw_ani_control(ah, ATH9K_ANI_CCK_WEAK_SIGNAL_THR,
629                                      aniState->cckWeakSigThreshold);
630         if (aniState->firstepLevel != 0)
631                 ath9k_hw_ani_control(ah, ATH9K_ANI_FIRSTEP_LEVEL,
632                                      aniState->firstepLevel);
633
634         ath9k_hw_setrxfilter(ah, ath9k_hw_getrxfilter(ah) &
635                              ~ATH9K_RX_FILTER_PHYERR);
636         ath9k_ani_restart_old(ah);
637
638         ENABLE_REGWRITE_BUFFER(ah);
639
640         REG_WRITE(ah, AR_PHY_ERR_MASK_1, AR_PHY_ERR_OFDM_TIMING);
641         REG_WRITE(ah, AR_PHY_ERR_MASK_2, AR_PHY_ERR_CCK_TIMING);
642
643         REGWRITE_BUFFER_FLUSH(ah);
644 }
645
646 /*
647  * Restore the ANI parameters in the HAL and reset the statistics.
648  * This routine should be called for every hardware reset and for
649  * every channel change.
650  */
651 static void ath9k_ani_reset_new(struct ath_hw *ah, bool is_scanning)
652 {
653         struct ar5416AniState *aniState = ah->curani;
654         struct ath9k_channel *chan = ah->curchan;
655         struct ath_common *common = ath9k_hw_common(ah);
656
657         if (!DO_ANI(ah))
658                 return;
659
660         BUG_ON(aniState == NULL);
661         ah->stats.ast_ani_reset++;
662
663         /* only allow a subset of functions in AP mode */
664         if (ah->opmode == NL80211_IFTYPE_AP) {
665                 if (IS_CHAN_2GHZ(chan)) {
666                         ah->ani_function = (ATH9K_ANI_SPUR_IMMUNITY_LEVEL |
667                                             ATH9K_ANI_FIRSTEP_LEVEL);
668                         if (AR_SREV_9300_20_OR_LATER(ah))
669                                 ah->ani_function |= ATH9K_ANI_MRC_CCK;
670                 } else
671                         ah->ani_function = 0;
672         }
673
674         /* always allow mode (on/off) to be controlled */
675         ah->ani_function |= ATH9K_ANI_MODE;
676
677         if (is_scanning ||
678             (ah->opmode != NL80211_IFTYPE_STATION &&
679              ah->opmode != NL80211_IFTYPE_ADHOC)) {
680                 /*
681                  * If we're scanning or in AP mode, the defaults (ini)
682                  * should be in place. For an AP we assume the historical
683                  * levels for this channel are probably outdated so start
684                  * from defaults instead.
685                  */
686                 if (aniState->ofdmNoiseImmunityLevel !=
687                     ATH9K_ANI_OFDM_DEF_LEVEL ||
688                     aniState->cckNoiseImmunityLevel !=
689                     ATH9K_ANI_CCK_DEF_LEVEL) {
690                         ath_print(common, ATH_DBG_ANI,
691                                   "Restore defaults: opmode %u "
692                                   "chan %d Mhz/0x%x is_scanning=%d "
693                                   "ofdm:%d cck:%d\n",
694                                   ah->opmode,
695                                   chan->channel,
696                                   chan->channelFlags,
697                                   is_scanning,
698                                   aniState->ofdmNoiseImmunityLevel,
699                                   aniState->cckNoiseImmunityLevel);
700
701                         ath9k_hw_set_ofdm_nil(ah, ATH9K_ANI_OFDM_DEF_LEVEL);
702                         ath9k_hw_set_cck_nil(ah, ATH9K_ANI_CCK_DEF_LEVEL);
703                 }
704         } else {
705                 /*
706                  * restore historical levels for this channel
707                  */
708                 ath_print(common, ATH_DBG_ANI,
709                           "Restore history: opmode %u "
710                           "chan %d Mhz/0x%x is_scanning=%d "
711                           "ofdm:%d cck:%d\n",
712                           ah->opmode,
713                           chan->channel,
714                           chan->channelFlags,
715                           is_scanning,
716                           aniState->ofdmNoiseImmunityLevel,
717                           aniState->cckNoiseImmunityLevel);
718
719                         ath9k_hw_set_ofdm_nil(ah,
720                                               aniState->ofdmNoiseImmunityLevel);
721                         ath9k_hw_set_cck_nil(ah,
722                                              aniState->cckNoiseImmunityLevel);
723         }
724
725         /*
726          * enable phy counters if hw supports or if not, enable phy
727          * interrupts (so we can count each one)
728          */
729         ath9k_ani_restart_new(ah);
730
731         ENABLE_REGWRITE_BUFFER(ah);
732
733         REG_WRITE(ah, AR_PHY_ERR_MASK_1, AR_PHY_ERR_OFDM_TIMING);
734         REG_WRITE(ah, AR_PHY_ERR_MASK_2, AR_PHY_ERR_CCK_TIMING);
735
736         REGWRITE_BUFFER_FLUSH(ah);
737 }
738
739 static void ath9k_hw_ani_monitor_old(struct ath_hw *ah,
740                                      struct ath9k_channel *chan)
741 {
742         struct ar5416AniState *aniState;
743         struct ath_common *common = ath9k_hw_common(ah);
744         int32_t listenTime;
745         u32 phyCnt1, phyCnt2;
746         u32 ofdmPhyErrCnt, cckPhyErrCnt;
747
748         if (!DO_ANI(ah))
749                 return;
750
751         aniState = ah->curani;
752
753         listenTime = ath9k_hw_ani_get_listen_time(ah);
754         if (listenTime < 0) {
755                 ah->stats.ast_ani_lneg++;
756                 ath9k_ani_restart_old(ah);
757                 return;
758         }
759
760         aniState->listenTime += listenTime;
761
762         ath9k_hw_update_mibstats(ah, &ah->ah_mibStats);
763
764         phyCnt1 = REG_READ(ah, AR_PHY_ERR_1);
765         phyCnt2 = REG_READ(ah, AR_PHY_ERR_2);
766
767         if (phyCnt1 < aniState->ofdmPhyErrBase ||
768             phyCnt2 < aniState->cckPhyErrBase) {
769                 if (phyCnt1 < aniState->ofdmPhyErrBase) {
770                         ath_print(common, ATH_DBG_ANI,
771                                   "phyCnt1 0x%x, resetting "
772                                   "counter value to 0x%x\n",
773                                   phyCnt1,
774                                   aniState->ofdmPhyErrBase);
775                         REG_WRITE(ah, AR_PHY_ERR_1,
776                                   aniState->ofdmPhyErrBase);
777                         REG_WRITE(ah, AR_PHY_ERR_MASK_1,
778                                   AR_PHY_ERR_OFDM_TIMING);
779                 }
780                 if (phyCnt2 < aniState->cckPhyErrBase) {
781                         ath_print(common, ATH_DBG_ANI,
782                                   "phyCnt2 0x%x, resetting "
783                                   "counter value to 0x%x\n",
784                                   phyCnt2,
785                                   aniState->cckPhyErrBase);
786                         REG_WRITE(ah, AR_PHY_ERR_2,
787                                   aniState->cckPhyErrBase);
788                         REG_WRITE(ah, AR_PHY_ERR_MASK_2,
789                                   AR_PHY_ERR_CCK_TIMING);
790                 }
791                 return;
792         }
793
794         ofdmPhyErrCnt = phyCnt1 - aniState->ofdmPhyErrBase;
795         ah->stats.ast_ani_ofdmerrs +=
796                 ofdmPhyErrCnt - aniState->ofdmPhyErrCount;
797         aniState->ofdmPhyErrCount = ofdmPhyErrCnt;
798
799         cckPhyErrCnt = phyCnt2 - aniState->cckPhyErrBase;
800         ah->stats.ast_ani_cckerrs +=
801                 cckPhyErrCnt - aniState->cckPhyErrCount;
802         aniState->cckPhyErrCount = cckPhyErrCnt;
803
804         if (aniState->listenTime > 5 * ah->aniperiod) {
805                 if (aniState->ofdmPhyErrCount <= aniState->listenTime *
806                     aniState->ofdmTrigLow / 1000 &&
807                     aniState->cckPhyErrCount <= aniState->listenTime *
808                     aniState->cckTrigLow / 1000)
809                         ath9k_hw_ani_lower_immunity(ah);
810                 ath9k_ani_restart_old(ah);
811         } else if (aniState->listenTime > ah->aniperiod) {
812                 if (aniState->ofdmPhyErrCount > aniState->listenTime *
813                     aniState->ofdmTrigHigh / 1000) {
814                         ath9k_hw_ani_ofdm_err_trigger_old(ah);
815                         ath9k_ani_restart_old(ah);
816                 } else if (aniState->cckPhyErrCount >
817                            aniState->listenTime * aniState->cckTrigHigh /
818                            1000) {
819                         ath9k_hw_ani_cck_err_trigger_old(ah);
820                         ath9k_ani_restart_old(ah);
821                 }
822         }
823 }
824
825 static void ath9k_hw_ani_monitor_new(struct ath_hw *ah,
826                                      struct ath9k_channel *chan)
827 {
828         struct ar5416AniState *aniState;
829         struct ath_common *common = ath9k_hw_common(ah);
830         int32_t listenTime;
831         u32 phyCnt1, phyCnt2;
832         u32 ofdmPhyErrCnt, cckPhyErrCnt;
833         u32 ofdmPhyErrRate, cckPhyErrRate;
834
835         if (!DO_ANI(ah))
836                 return;
837
838         aniState = ah->curani;
839         if (WARN_ON(!aniState))
840                 return;
841
842         listenTime = ath9k_hw_ani_get_listen_time(ah);
843         if (listenTime <= 0) {
844                 ah->stats.ast_ani_lneg++;
845                 /* restart ANI period if listenTime is invalid */
846                 ath_print(common, ATH_DBG_ANI,
847                           "listenTime=%d - on new ani monitor\n",
848                           listenTime);
849                 ath9k_ani_restart_new(ah);
850                 return;
851         }
852
853         aniState->listenTime += listenTime;
854
855         ath9k_hw_update_mibstats(ah, &ah->ah_mibStats);
856
857         phyCnt1 = REG_READ(ah, AR_PHY_ERR_1);
858         phyCnt2 = REG_READ(ah, AR_PHY_ERR_2);
859
860         if (phyCnt1 < aniState->ofdmPhyErrBase ||
861             phyCnt2 < aniState->cckPhyErrBase) {
862                 if (phyCnt1 < aniState->ofdmPhyErrBase) {
863                         ath_print(common, ATH_DBG_ANI,
864                                   "phyCnt1 0x%x, resetting "
865                                   "counter value to 0x%x\n",
866                                   phyCnt1,
867                                   aniState->ofdmPhyErrBase);
868                         REG_WRITE(ah, AR_PHY_ERR_1,
869                                   aniState->ofdmPhyErrBase);
870                         REG_WRITE(ah, AR_PHY_ERR_MASK_1,
871                                   AR_PHY_ERR_OFDM_TIMING);
872                 }
873                 if (phyCnt2 < aniState->cckPhyErrBase) {
874                         ath_print(common, ATH_DBG_ANI,
875                                   "phyCnt2 0x%x, resetting "
876                                   "counter value to 0x%x\n",
877                                   phyCnt2,
878                                   aniState->cckPhyErrBase);
879                         REG_WRITE(ah, AR_PHY_ERR_2,
880                                   aniState->cckPhyErrBase);
881                         REG_WRITE(ah, AR_PHY_ERR_MASK_2,
882                                   AR_PHY_ERR_CCK_TIMING);
883                 }
884                 return;
885         }
886
887         ofdmPhyErrCnt = phyCnt1 - aniState->ofdmPhyErrBase;
888         ah->stats.ast_ani_ofdmerrs +=
889                 ofdmPhyErrCnt - aniState->ofdmPhyErrCount;
890         aniState->ofdmPhyErrCount = ofdmPhyErrCnt;
891
892         cckPhyErrCnt = phyCnt2 - aniState->cckPhyErrBase;
893         ah->stats.ast_ani_cckerrs +=
894                 cckPhyErrCnt - aniState->cckPhyErrCount;
895         aniState->cckPhyErrCount = cckPhyErrCnt;
896
897         ath_print(common, ATH_DBG_ANI,
898                   "Errors: OFDM=0x%08x-0x%08x=%d   "
899                   "CCK=0x%08x-0x%08x=%d\n",
900                   phyCnt1,
901                   aniState->ofdmPhyErrBase,
902                   ofdmPhyErrCnt,
903                   phyCnt2,
904                   aniState->cckPhyErrBase,
905                   cckPhyErrCnt);
906
907         ofdmPhyErrRate = aniState->ofdmPhyErrCount * 1000 /
908                          aniState->listenTime;
909         cckPhyErrRate =  aniState->cckPhyErrCount * 1000 /
910                          aniState->listenTime;
911
912         ath_print(common, ATH_DBG_ANI,
913                   "listenTime=%d OFDM:%d errs=%d/s CCK:%d "
914                   "errs=%d/s ofdm_turn=%d\n",
915                   listenTime, aniState->ofdmNoiseImmunityLevel,
916                   ofdmPhyErrRate, aniState->cckNoiseImmunityLevel,
917                   cckPhyErrRate, aniState->ofdmsTurn);
918
919         if (aniState->listenTime > 5 * ah->aniperiod) {
920                 if (ofdmPhyErrRate <= aniState->ofdmTrigLow &&
921                     cckPhyErrRate <= aniState->cckTrigLow) {
922                         ath_print(common, ATH_DBG_ANI,
923                                   "1. listenTime=%d OFDM:%d errs=%d/s(<%d)  "
924                                   "CCK:%d errs=%d/s(<%d) -> "
925                                   "ath9k_hw_ani_lower_immunity()\n",
926                                   aniState->listenTime,
927                                   aniState->ofdmNoiseImmunityLevel,
928                                   ofdmPhyErrRate,
929                                   aniState->ofdmTrigLow,
930                                   aniState->cckNoiseImmunityLevel,
931                                   cckPhyErrRate,
932                                   aniState->cckTrigLow);
933                         ath9k_hw_ani_lower_immunity(ah);
934                         aniState->ofdmsTurn = !aniState->ofdmsTurn;
935                 }
936                 ath_print(common, ATH_DBG_ANI,
937                           "1 listenTime=%d ofdm=%d/s cck=%d/s - "
938                           "calling ath9k_ani_restart_new()\n",
939                           aniState->listenTime, ofdmPhyErrRate, cckPhyErrRate);
940                 ath9k_ani_restart_new(ah);
941         } else if (aniState->listenTime > ah->aniperiod) {
942                 /* check to see if need to raise immunity */
943                 if (ofdmPhyErrRate > aniState->ofdmTrigHigh &&
944                     (cckPhyErrRate <= aniState->cckTrigHigh ||
945                      aniState->ofdmsTurn)) {
946                         ath_print(common, ATH_DBG_ANI,
947                                   "2 listenTime=%d OFDM:%d errs=%d/s(>%d) -> "
948                                   "ath9k_hw_ani_ofdm_err_trigger_new()\n",
949                                   aniState->listenTime,
950                                   aniState->ofdmNoiseImmunityLevel,
951                                   ofdmPhyErrRate,
952                                   aniState->ofdmTrigHigh);
953                         ath9k_hw_ani_ofdm_err_trigger_new(ah);
954                         ath9k_ani_restart_new(ah);
955                         aniState->ofdmsTurn = false;
956                 } else if (cckPhyErrRate > aniState->cckTrigHigh) {
957                         ath_print(common, ATH_DBG_ANI,
958                                  "3 listenTime=%d CCK:%d errs=%d/s(>%d) -> "
959                                  "ath9k_hw_ani_cck_err_trigger_new()\n",
960                                  aniState->listenTime,
961                                  aniState->cckNoiseImmunityLevel,
962                                  cckPhyErrRate,
963                                  aniState->cckTrigHigh);
964                         ath9k_hw_ani_cck_err_trigger_new(ah);
965                         ath9k_ani_restart_new(ah);
966                         aniState->ofdmsTurn = true;
967                 }
968         }
969 }
970
971 void ath9k_enable_mib_counters(struct ath_hw *ah)
972 {
973         struct ath_common *common = ath9k_hw_common(ah);
974
975         ath_print(common, ATH_DBG_ANI, "Enable MIB counters\n");
976
977         ath9k_hw_update_mibstats(ah, &ah->ah_mibStats);
978
979         ENABLE_REGWRITE_BUFFER(ah);
980
981         REG_WRITE(ah, AR_FILT_OFDM, 0);
982         REG_WRITE(ah, AR_FILT_CCK, 0);
983         REG_WRITE(ah, AR_MIBC,
984                   ~(AR_MIBC_COW | AR_MIBC_FMC | AR_MIBC_CMC | AR_MIBC_MCS)
985                   & 0x0f);
986         REG_WRITE(ah, AR_PHY_ERR_MASK_1, AR_PHY_ERR_OFDM_TIMING);
987         REG_WRITE(ah, AR_PHY_ERR_MASK_2, AR_PHY_ERR_CCK_TIMING);
988
989         REGWRITE_BUFFER_FLUSH(ah);
990 }
991
992 /* Freeze the MIB counters, get the stats and then clear them */
993 void ath9k_hw_disable_mib_counters(struct ath_hw *ah)
994 {
995         struct ath_common *common = ath9k_hw_common(ah);
996
997         ath_print(common, ATH_DBG_ANI, "Disable MIB counters\n");
998
999         REG_WRITE(ah, AR_MIBC, AR_MIBC_FMC);
1000         ath9k_hw_update_mibstats(ah, &ah->ah_mibStats);
1001         REG_WRITE(ah, AR_MIBC, AR_MIBC_CMC);
1002         REG_WRITE(ah, AR_FILT_OFDM, 0);
1003         REG_WRITE(ah, AR_FILT_CCK, 0);
1004 }
1005 EXPORT_SYMBOL(ath9k_hw_disable_mib_counters);
1006
1007 void ath9k_hw_update_cycle_counters(struct ath_hw *ah)
1008 {
1009         struct ath_cycle_counters cc;
1010         bool clear;
1011
1012         memcpy(&cc, &ah->cc, sizeof(cc));
1013
1014         /* freeze counters */
1015         REG_WRITE(ah, AR_MIBC, AR_MIBC_FMC);
1016
1017         ah->cc.cycles = REG_READ(ah, AR_CCCNT);
1018         if (ah->cc.cycles < cc.cycles) {
1019                 clear = true;
1020                 goto skip;
1021         }
1022
1023         ah->cc.rx_clear = REG_READ(ah, AR_RCCNT);
1024         ah->cc.rx_frame = REG_READ(ah, AR_RFCNT);
1025         ah->cc.tx_frame = REG_READ(ah, AR_TFCNT);
1026
1027         /* prevent wraparound */
1028         if (ah->cc.cycles & BIT(31))
1029                 clear = true;
1030
1031 #define CC_DELTA(_field, _reg) ah->cc_delta._field += ah->cc._field - cc._field
1032         CC_DELTA(cycles, AR_CCCNT);
1033         CC_DELTA(rx_frame, AR_RFCNT);
1034         CC_DELTA(rx_clear, AR_RCCNT);
1035         CC_DELTA(tx_frame, AR_TFCNT);
1036 #undef CC_DELTA
1037
1038         ah->listen_time += (ah->cc.cycles - cc.cycles) -
1039                  ((ah->cc.rx_frame - cc.rx_frame) +
1040                   (ah->cc.tx_frame - cc.tx_frame));
1041
1042 skip:
1043         if (clear) {
1044                 REG_WRITE(ah, AR_CCCNT, 0);
1045                 REG_WRITE(ah, AR_RFCNT, 0);
1046                 REG_WRITE(ah, AR_RCCNT, 0);
1047                 REG_WRITE(ah, AR_TFCNT, 0);
1048                 memset(&ah->cc, 0, sizeof(ah->cc));
1049         }
1050
1051         /* unfreeze counters */
1052         REG_WRITE(ah, AR_MIBC, 0);
1053 }
1054
1055 /*
1056  * Process a MIB interrupt.  We may potentially be invoked because
1057  * any of the MIB counters overflow/trigger so don't assume we're
1058  * here because a PHY error counter triggered.
1059  */
1060 static void ath9k_hw_proc_mib_event_old(struct ath_hw *ah)
1061 {
1062         u32 phyCnt1, phyCnt2;
1063
1064         /* Reset these counters regardless */
1065         REG_WRITE(ah, AR_FILT_OFDM, 0);
1066         REG_WRITE(ah, AR_FILT_CCK, 0);
1067         if (!(REG_READ(ah, AR_SLP_MIB_CTRL) & AR_SLP_MIB_PENDING))
1068                 REG_WRITE(ah, AR_SLP_MIB_CTRL, AR_SLP_MIB_CLEAR);
1069
1070         /* Clear the mib counters and save them in the stats */
1071         ath9k_hw_update_mibstats(ah, &ah->ah_mibStats);
1072
1073         if (!DO_ANI(ah)) {
1074                 /*
1075                  * We must always clear the interrupt cause by
1076                  * resetting the phy error regs.
1077                  */
1078                 REG_WRITE(ah, AR_PHY_ERR_1, 0);
1079                 REG_WRITE(ah, AR_PHY_ERR_2, 0);
1080                 return;
1081         }
1082
1083         /* NB: these are not reset-on-read */
1084         phyCnt1 = REG_READ(ah, AR_PHY_ERR_1);
1085         phyCnt2 = REG_READ(ah, AR_PHY_ERR_2);
1086         if (((phyCnt1 & AR_MIBCNT_INTRMASK) == AR_MIBCNT_INTRMASK) ||
1087             ((phyCnt2 & AR_MIBCNT_INTRMASK) == AR_MIBCNT_INTRMASK)) {
1088                 struct ar5416AniState *aniState = ah->curani;
1089                 u32 ofdmPhyErrCnt, cckPhyErrCnt;
1090
1091                 /* NB: only use ast_ani_*errs with AH_PRIVATE_DIAG */
1092                 ofdmPhyErrCnt = phyCnt1 - aniState->ofdmPhyErrBase;
1093                 ah->stats.ast_ani_ofdmerrs +=
1094                         ofdmPhyErrCnt - aniState->ofdmPhyErrCount;
1095                 aniState->ofdmPhyErrCount = ofdmPhyErrCnt;
1096
1097                 cckPhyErrCnt = phyCnt2 - aniState->cckPhyErrBase;
1098                 ah->stats.ast_ani_cckerrs +=
1099                         cckPhyErrCnt - aniState->cckPhyErrCount;
1100                 aniState->cckPhyErrCount = cckPhyErrCnt;
1101
1102                 /*
1103                  * NB: figure out which counter triggered.  If both
1104                  * trigger we'll only deal with one as the processing
1105                  * clobbers the error counter so the trigger threshold
1106                  * check will never be true.
1107                  */
1108                 if (aniState->ofdmPhyErrCount > aniState->ofdmTrigHigh)
1109                         ath9k_hw_ani_ofdm_err_trigger_new(ah);
1110                 if (aniState->cckPhyErrCount > aniState->cckTrigHigh)
1111                         ath9k_hw_ani_cck_err_trigger_old(ah);
1112                 /* NB: always restart to insure the h/w counters are reset */
1113                 ath9k_ani_restart_old(ah);
1114         }
1115 }
1116
1117 /*
1118  * Process a MIB interrupt.  We may potentially be invoked because
1119  * any of the MIB counters overflow/trigger so don't assume we're
1120  * here because a PHY error counter triggered.
1121  */
1122 static void ath9k_hw_proc_mib_event_new(struct ath_hw *ah)
1123 {
1124         u32 phyCnt1, phyCnt2;
1125
1126         /* Reset these counters regardless */
1127         REG_WRITE(ah, AR_FILT_OFDM, 0);
1128         REG_WRITE(ah, AR_FILT_CCK, 0);
1129         if (!(REG_READ(ah, AR_SLP_MIB_CTRL) & AR_SLP_MIB_PENDING))
1130                 REG_WRITE(ah, AR_SLP_MIB_CTRL, AR_SLP_MIB_CLEAR);
1131
1132         /* Clear the mib counters and save them in the stats */
1133         ath9k_hw_update_mibstats(ah, &ah->ah_mibStats);
1134
1135         if (!DO_ANI(ah)) {
1136                 /*
1137                  * We must always clear the interrupt cause by
1138                  * resetting the phy error regs.
1139                  */
1140                 REG_WRITE(ah, AR_PHY_ERR_1, 0);
1141                 REG_WRITE(ah, AR_PHY_ERR_2, 0);
1142                 return;
1143         }
1144
1145         /* NB: these are not reset-on-read */
1146         phyCnt1 = REG_READ(ah, AR_PHY_ERR_1);
1147         phyCnt2 = REG_READ(ah, AR_PHY_ERR_2);
1148
1149         /* NB: always restart to insure the h/w counters are reset */
1150         if (((phyCnt1 & AR_MIBCNT_INTRMASK) == AR_MIBCNT_INTRMASK) ||
1151             ((phyCnt2 & AR_MIBCNT_INTRMASK) == AR_MIBCNT_INTRMASK))
1152                 ath9k_ani_restart_new(ah);
1153 }
1154
1155 void ath9k_hw_ani_setup(struct ath_hw *ah)
1156 {
1157         int i;
1158
1159         const int totalSizeDesired[] = { -55, -55, -55, -55, -62 };
1160         const int coarseHigh[] = { -14, -14, -14, -14, -12 };
1161         const int coarseLow[] = { -64, -64, -64, -64, -70 };
1162         const int firpwr[] = { -78, -78, -78, -78, -80 };
1163
1164         for (i = 0; i < 5; i++) {
1165                 ah->totalSizeDesired[i] = totalSizeDesired[i];
1166                 ah->coarse_high[i] = coarseHigh[i];
1167                 ah->coarse_low[i] = coarseLow[i];
1168                 ah->firpwr[i] = firpwr[i];
1169         }
1170 }
1171
1172 void ath9k_hw_ani_init(struct ath_hw *ah)
1173 {
1174         struct ath_common *common = ath9k_hw_common(ah);
1175         int i;
1176
1177         ath_print(common, ATH_DBG_ANI, "Initialize ANI\n");
1178
1179         memset(ah->ani, 0, sizeof(ah->ani));
1180         for (i = 0; i < ARRAY_SIZE(ah->ani); i++) {
1181                 if (AR_SREV_9300_20_OR_LATER(ah) || modparam_force_new_ani) {
1182                         ah->ani[i].ofdmTrigHigh = ATH9K_ANI_OFDM_TRIG_HIGH_NEW;
1183                         ah->ani[i].ofdmTrigLow = ATH9K_ANI_OFDM_TRIG_LOW_NEW;
1184
1185                         ah->ani[i].cckTrigHigh = ATH9K_ANI_CCK_TRIG_HIGH_NEW;
1186                         ah->ani[i].cckTrigLow = ATH9K_ANI_CCK_TRIG_LOW_NEW;
1187
1188                         ah->ani[i].spurImmunityLevel =
1189                                 ATH9K_ANI_SPUR_IMMUNE_LVL_NEW;
1190
1191                         ah->ani[i].firstepLevel = ATH9K_ANI_FIRSTEP_LVL_NEW;
1192
1193                         ah->ani[i].ofdmPhyErrBase = 0;
1194                         ah->ani[i].cckPhyErrBase = 0;
1195
1196                         if (AR_SREV_9300_20_OR_LATER(ah))
1197                                 ah->ani[i].mrcCCKOff =
1198                                         !ATH9K_ANI_ENABLE_MRC_CCK;
1199                         else
1200                                 ah->ani[i].mrcCCKOff = true;
1201
1202                         ah->ani[i].ofdmsTurn = true;
1203                 } else {
1204                         ah->ani[i].ofdmTrigHigh = ATH9K_ANI_OFDM_TRIG_HIGH_OLD;
1205                         ah->ani[i].ofdmTrigLow = ATH9K_ANI_OFDM_TRIG_LOW_OLD;
1206
1207                         ah->ani[i].cckTrigHigh = ATH9K_ANI_CCK_TRIG_HIGH_OLD;
1208                         ah->ani[i].cckTrigLow = ATH9K_ANI_CCK_TRIG_LOW_OLD;
1209
1210                         ah->ani[i].spurImmunityLevel =
1211                                 ATH9K_ANI_SPUR_IMMUNE_LVL_OLD;
1212                         ah->ani[i].firstepLevel = ATH9K_ANI_FIRSTEP_LVL_OLD;
1213
1214                         ah->ani[i].ofdmPhyErrBase =
1215                                 AR_PHY_COUNTMAX - ATH9K_ANI_OFDM_TRIG_HIGH_OLD;
1216                         ah->ani[i].cckPhyErrBase =
1217                                 AR_PHY_COUNTMAX - ATH9K_ANI_CCK_TRIG_HIGH_OLD;
1218                         ah->ani[i].cckWeakSigThreshold =
1219                                 ATH9K_ANI_CCK_WEAK_SIG_THR;
1220                 }
1221
1222                 ah->ani[i].rssiThrHigh = ATH9K_ANI_RSSI_THR_HIGH;
1223                 ah->ani[i].rssiThrLow = ATH9K_ANI_RSSI_THR_LOW;
1224                 ah->ani[i].ofdmWeakSigDetectOff =
1225                         !ATH9K_ANI_USE_OFDM_WEAK_SIG;
1226                 ah->ani[i].cckNoiseImmunityLevel = ATH9K_ANI_CCK_DEF_LEVEL;
1227         }
1228
1229         /*
1230          * since we expect some ongoing maintenance on the tables, let's sanity
1231          * check here default level should not modify INI setting.
1232          */
1233         if (AR_SREV_9300_20_OR_LATER(ah) || modparam_force_new_ani) {
1234                 const struct ani_ofdm_level_entry *entry_ofdm;
1235                 const struct ani_cck_level_entry *entry_cck;
1236
1237                 entry_ofdm = &ofdm_level_table[ATH9K_ANI_OFDM_DEF_LEVEL];
1238                 entry_cck = &cck_level_table[ATH9K_ANI_CCK_DEF_LEVEL];
1239
1240                 ah->aniperiod = ATH9K_ANI_PERIOD_NEW;
1241                 ah->config.ani_poll_interval = ATH9K_ANI_POLLINTERVAL_NEW;
1242         } else {
1243                 ah->aniperiod = ATH9K_ANI_PERIOD_OLD;
1244                 ah->config.ani_poll_interval = ATH9K_ANI_POLLINTERVAL_OLD;
1245         }
1246
1247         ath_print(common, ATH_DBG_ANI,
1248                   "Setting OfdmErrBase = 0x%08x\n",
1249                   ah->ani[0].ofdmPhyErrBase);
1250         ath_print(common, ATH_DBG_ANI, "Setting cckErrBase = 0x%08x\n",
1251                   ah->ani[0].cckPhyErrBase);
1252
1253         ENABLE_REGWRITE_BUFFER(ah);
1254
1255         REG_WRITE(ah, AR_PHY_ERR_1, ah->ani[0].ofdmPhyErrBase);
1256         REG_WRITE(ah, AR_PHY_ERR_2, ah->ani[0].cckPhyErrBase);
1257
1258         REGWRITE_BUFFER_FLUSH(ah);
1259
1260         ath9k_enable_mib_counters(ah);
1261
1262         if (ah->config.enable_ani)
1263                 ah->proc_phyerr |= HAL_PROCESS_ANI;
1264 }
1265
1266 void ath9k_hw_attach_ani_ops_old(struct ath_hw *ah)
1267 {
1268         struct ath_hw_private_ops *priv_ops = ath9k_hw_private_ops(ah);
1269         struct ath_hw_ops *ops = ath9k_hw_ops(ah);
1270
1271         priv_ops->ani_reset = ath9k_ani_reset_old;
1272         priv_ops->ani_lower_immunity = ath9k_hw_ani_lower_immunity_old;
1273
1274         ops->ani_proc_mib_event = ath9k_hw_proc_mib_event_old;
1275         ops->ani_monitor = ath9k_hw_ani_monitor_old;
1276
1277         ath_print(ath9k_hw_common(ah), ATH_DBG_ANY, "Using ANI v1\n");
1278 }
1279
1280 void ath9k_hw_attach_ani_ops_new(struct ath_hw *ah)
1281 {
1282         struct ath_hw_private_ops *priv_ops = ath9k_hw_private_ops(ah);
1283         struct ath_hw_ops *ops = ath9k_hw_ops(ah);
1284
1285         priv_ops->ani_reset = ath9k_ani_reset_new;
1286         priv_ops->ani_lower_immunity = ath9k_hw_ani_lower_immunity_new;
1287
1288         ops->ani_proc_mib_event = ath9k_hw_proc_mib_event_new;
1289         ops->ani_monitor = ath9k_hw_ani_monitor_new;
1290
1291         ath_print(ath9k_hw_common(ah), ATH_DBG_ANY, "Using ANI v2\n");
1292 }