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