ani.c 33 KB

1234567891011121314151617181920212223242526272829303132333435363738394041424344454647484950515253545556575859606162636465666768697071727374757677787980818283848586878889909192939495969798991001011021031041051061071081091101111121131141151161171181191201211221231241251261271281291301311321331341351361371381391401411421431441451461471481491501511521531541551561571581591601611621631641651661671681691701711721731741751761771781791801811821831841851861871881891901911921931941951961971981992002012022032042052062072082092102112122132142152162172182192202212222232242252262272282292302312322332342352362372382392402412422432442452462472482492502512522532542552562572582592602612622632642652662672682692702712722732742752762772782792802812822832842852862872882892902912922932942952962972982993003013023033043053063073083093103113123133143153163173183193203213223233243253263273283293303313323333343353363373383393403413423433443453463473483493503513523533543553563573583593603613623633643653663673683693703713723733743753763773783793803813823833843853863873883893903913923933943953963973983994004014024034044054064074084094104114124134144154164174184194204214224234244254264274284294304314324334344354364374384394404414424434444454464474484494504514524534544554564574584594604614624634644654664674684694704714724734744754764774784794804814824834844854864874884894904914924934944954964974984995005015025035045055065075085095105115125135145155165175185195205215225235245255265275285295305315325335345355365375385395405415425435445455465475485495505515525535545555565575585595605615625635645655665675685695705715725735745755765775785795805815825835845855865875885895905915925935945955965975985996006016026036046056066076086096106116126136146156166176186196206216226236246256266276286296306316326336346356366376386396406416426436446456466476486496506516526536546556566576586596606616626636646656666676686696706716726736746756766776786796806816826836846856866876886896906916926936946956966976986997007017027037047057067077087097107117127137147157167177187197207217227237247257267277287297307317327337347357367377387397407417427437447457467477487497507517527537547557567577587597607617627637647657667677687697707717727737747757767777787797807817827837847857867877887897907917927937947957967977987998008018028038048058068078088098108118128138148158168178188198208218228238248258268278288298308318328338348358368378388398408418428438448458468478488498508518528538548558568578588598608618628638648658668678688698708718728738748758768778788798808818828838848858868878888898908918928938948958968978988999009019029039049059069079089099109119129139149159169179189199209219229239249259269279289299309319329339349359369379389399409419429439449459469479489499509519529539549559569579589599609619629639649659669679689699709719729739749759769779789799809819829839849859869879889899909919929939949959969979989991000100110021003100410051006100710081009101010111012101310141015101610171018101910201021102210231024102510261027102810291030103110321033103410351036103710381039104010411042104310441045104610471048104910501051105210531054105510561057105810591060106110621063106410651066106710681069107010711072107310741075107610771078107910801081108210831084108510861087108810891090109110921093109410951096109710981099110011011102110311041105110611071108110911101111111211131114111511161117111811191120112111221123112411251126112711281129113011311132113311341135113611371138113911401141114211431144114511461147114811491150115111521153115411551156115711581159116011611162116311641165
  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. #include <linux/kernel.h>
  17. #include "hw.h"
  18. #include "hw-ops.h"
  19. struct ani_ofdm_level_entry {
  20. int spur_immunity_level;
  21. int fir_step_level;
  22. int ofdm_weak_signal_on;
  23. };
  24. /* values here are relative to the INI */
  25. /*
  26. * Legend:
  27. *
  28. * SI: Spur immunity
  29. * FS: FIR Step
  30. * WS: OFDM / CCK Weak Signal detection
  31. * MRC-CCK: Maximal Ratio Combining for CCK
  32. */
  33. static const struct ani_ofdm_level_entry ofdm_level_table[] = {
  34. /* SI FS WS */
  35. { 0, 0, 1 }, /* lvl 0 */
  36. { 1, 1, 1 }, /* lvl 1 */
  37. { 2, 2, 1 }, /* lvl 2 */
  38. { 3, 2, 1 }, /* lvl 3 (default) */
  39. { 4, 3, 1 }, /* lvl 4 */
  40. { 5, 4, 1 }, /* lvl 5 */
  41. { 6, 5, 1 }, /* lvl 6 */
  42. { 7, 6, 1 }, /* lvl 7 */
  43. { 7, 7, 1 }, /* lvl 8 */
  44. { 7, 8, 0 } /* lvl 9 */
  45. };
  46. #define ATH9K_ANI_OFDM_NUM_LEVEL \
  47. ARRAY_SIZE(ofdm_level_table)
  48. #define ATH9K_ANI_OFDM_MAX_LEVEL \
  49. (ATH9K_ANI_OFDM_NUM_LEVEL-1)
  50. #define ATH9K_ANI_OFDM_DEF_LEVEL \
  51. 3 /* default level - matches the INI settings */
  52. /*
  53. * MRC (Maximal Ratio Combining) has always been used with multi-antenna ofdm.
  54. * With OFDM for single stream you just add up all antenna inputs, you're
  55. * only interested in what you get after FFT. Signal aligment is also not
  56. * required for OFDM because any phase difference adds up in the frequency
  57. * domain.
  58. *
  59. * MRC requires extra work for use with CCK. You need to align the antenna
  60. * signals from the different antenna before you can add the signals together.
  61. * You need aligment of signals as CCK is in time domain, so addition can cancel
  62. * your signal completely if phase is 180 degrees (think of adding sine waves).
  63. * You also need to remove noise before the addition and this is where ANI
  64. * MRC CCK comes into play. One of the antenna inputs may be stronger but
  65. * lower SNR, so just adding after alignment can be dangerous.
  66. *
  67. * Regardless of alignment in time, the antenna signals add constructively after
  68. * FFT and improve your reception. For more information:
  69. *
  70. * http://en.wikipedia.org/wiki/Maximal-ratio_combining
  71. */
  72. struct ani_cck_level_entry {
  73. int fir_step_level;
  74. int mrc_cck_on;
  75. };
  76. static const struct ani_cck_level_entry cck_level_table[] = {
  77. /* FS MRC-CCK */
  78. { 0, 1 }, /* lvl 0 */
  79. { 1, 1 }, /* lvl 1 */
  80. { 2, 1 }, /* lvl 2 (default) */
  81. { 3, 1 }, /* lvl 3 */
  82. { 4, 0 }, /* lvl 4 */
  83. { 5, 0 }, /* lvl 5 */
  84. { 6, 0 }, /* lvl 6 */
  85. { 7, 0 }, /* lvl 7 (only for high rssi) */
  86. { 8, 0 } /* lvl 8 (only for high rssi) */
  87. };
  88. #define ATH9K_ANI_CCK_NUM_LEVEL \
  89. ARRAY_SIZE(cck_level_table)
  90. #define ATH9K_ANI_CCK_MAX_LEVEL \
  91. (ATH9K_ANI_CCK_NUM_LEVEL-1)
  92. #define ATH9K_ANI_CCK_MAX_LEVEL_LOW_RSSI \
  93. (ATH9K_ANI_CCK_NUM_LEVEL-3)
  94. #define ATH9K_ANI_CCK_DEF_LEVEL \
  95. 2 /* default level - matches the INI settings */
  96. /* Private to ani.c */
  97. static void ath9k_hw_ani_lower_immunity(struct ath_hw *ah)
  98. {
  99. ath9k_hw_private_ops(ah)->ani_lower_immunity(ah);
  100. }
  101. static bool use_new_ani(struct ath_hw *ah)
  102. {
  103. return AR_SREV_9300_20_OR_LATER(ah) || modparam_force_new_ani;
  104. }
  105. static void ath9k_hw_update_mibstats(struct ath_hw *ah,
  106. struct ath9k_mib_stats *stats)
  107. {
  108. stats->ackrcv_bad += REG_READ(ah, AR_ACK_FAIL);
  109. stats->rts_bad += REG_READ(ah, AR_RTS_FAIL);
  110. stats->fcs_bad += REG_READ(ah, AR_FCS_FAIL);
  111. stats->rts_good += REG_READ(ah, AR_RTS_OK);
  112. stats->beacons += REG_READ(ah, AR_BEACON_CNT);
  113. }
  114. static void ath9k_ani_restart(struct ath_hw *ah)
  115. {
  116. struct ar5416AniState *aniState;
  117. struct ath_common *common = ath9k_hw_common(ah);
  118. u32 ofdm_base = 0, cck_base = 0;
  119. if (!DO_ANI(ah))
  120. return;
  121. aniState = &ah->curchan->ani;
  122. aniState->listenTime = 0;
  123. if (!use_new_ani(ah)) {
  124. ofdm_base = AR_PHY_COUNTMAX - ah->config.ofdm_trig_high;
  125. cck_base = AR_PHY_COUNTMAX - ah->config.cck_trig_high;
  126. }
  127. ath_print(common, ATH_DBG_ANI,
  128. "Writing ofdmbase=%u cckbase=%u\n", ofdm_base, cck_base);
  129. ENABLE_REGWRITE_BUFFER(ah);
  130. REG_WRITE(ah, AR_PHY_ERR_1, ofdm_base);
  131. REG_WRITE(ah, AR_PHY_ERR_2, cck_base);
  132. REG_WRITE(ah, AR_PHY_ERR_MASK_1, AR_PHY_ERR_OFDM_TIMING);
  133. REG_WRITE(ah, AR_PHY_ERR_MASK_2, AR_PHY_ERR_CCK_TIMING);
  134. REGWRITE_BUFFER_FLUSH(ah);
  135. ath9k_hw_update_mibstats(ah, &ah->ah_mibStats);
  136. aniState->ofdmPhyErrCount = 0;
  137. aniState->cckPhyErrCount = 0;
  138. }
  139. static void ath9k_hw_ani_ofdm_err_trigger_old(struct ath_hw *ah)
  140. {
  141. struct ieee80211_conf *conf = &ath9k_hw_common(ah)->hw->conf;
  142. struct ar5416AniState *aniState;
  143. int32_t rssi;
  144. if (!DO_ANI(ah))
  145. return;
  146. aniState = &ah->curchan->ani;
  147. if (aniState->noiseImmunityLevel < HAL_NOISE_IMMUNE_MAX) {
  148. if (ath9k_hw_ani_control(ah, ATH9K_ANI_NOISE_IMMUNITY_LEVEL,
  149. aniState->noiseImmunityLevel + 1)) {
  150. return;
  151. }
  152. }
  153. if (aniState->spurImmunityLevel < HAL_SPUR_IMMUNE_MAX) {
  154. if (ath9k_hw_ani_control(ah, ATH9K_ANI_SPUR_IMMUNITY_LEVEL,
  155. aniState->spurImmunityLevel + 1)) {
  156. return;
  157. }
  158. }
  159. if (ah->opmode == NL80211_IFTYPE_AP) {
  160. if (aniState->firstepLevel < HAL_FIRST_STEP_MAX) {
  161. ath9k_hw_ani_control(ah, ATH9K_ANI_FIRSTEP_LEVEL,
  162. aniState->firstepLevel + 1);
  163. }
  164. return;
  165. }
  166. rssi = BEACON_RSSI(ah);
  167. if (rssi > aniState->rssiThrHigh) {
  168. if (!aniState->ofdmWeakSigDetectOff) {
  169. if (ath9k_hw_ani_control(ah,
  170. ATH9K_ANI_OFDM_WEAK_SIGNAL_DETECTION,
  171. false)) {
  172. ath9k_hw_ani_control(ah,
  173. ATH9K_ANI_SPUR_IMMUNITY_LEVEL, 0);
  174. return;
  175. }
  176. }
  177. if (aniState->firstepLevel < HAL_FIRST_STEP_MAX) {
  178. ath9k_hw_ani_control(ah, ATH9K_ANI_FIRSTEP_LEVEL,
  179. aniState->firstepLevel + 1);
  180. return;
  181. }
  182. } else if (rssi > aniState->rssiThrLow) {
  183. if (aniState->ofdmWeakSigDetectOff)
  184. ath9k_hw_ani_control(ah,
  185. ATH9K_ANI_OFDM_WEAK_SIGNAL_DETECTION,
  186. true);
  187. if (aniState->firstepLevel < HAL_FIRST_STEP_MAX)
  188. ath9k_hw_ani_control(ah, ATH9K_ANI_FIRSTEP_LEVEL,
  189. aniState->firstepLevel + 1);
  190. return;
  191. } else {
  192. if ((conf->channel->band == IEEE80211_BAND_2GHZ) &&
  193. !conf_is_ht(conf)) {
  194. if (!aniState->ofdmWeakSigDetectOff)
  195. ath9k_hw_ani_control(ah,
  196. ATH9K_ANI_OFDM_WEAK_SIGNAL_DETECTION,
  197. false);
  198. if (aniState->firstepLevel > 0)
  199. ath9k_hw_ani_control(ah,
  200. ATH9K_ANI_FIRSTEP_LEVEL, 0);
  201. return;
  202. }
  203. }
  204. }
  205. static void ath9k_hw_ani_cck_err_trigger_old(struct ath_hw *ah)
  206. {
  207. struct ieee80211_conf *conf = &ath9k_hw_common(ah)->hw->conf;
  208. struct ar5416AniState *aniState;
  209. int32_t rssi;
  210. if (!DO_ANI(ah))
  211. return;
  212. aniState = &ah->curchan->ani;
  213. if (aniState->noiseImmunityLevel < HAL_NOISE_IMMUNE_MAX) {
  214. if (ath9k_hw_ani_control(ah, ATH9K_ANI_NOISE_IMMUNITY_LEVEL,
  215. aniState->noiseImmunityLevel + 1)) {
  216. return;
  217. }
  218. }
  219. if (ah->opmode == NL80211_IFTYPE_AP) {
  220. if (aniState->firstepLevel < HAL_FIRST_STEP_MAX) {
  221. ath9k_hw_ani_control(ah, ATH9K_ANI_FIRSTEP_LEVEL,
  222. aniState->firstepLevel + 1);
  223. }
  224. return;
  225. }
  226. rssi = BEACON_RSSI(ah);
  227. if (rssi > aniState->rssiThrLow) {
  228. if (aniState->firstepLevel < HAL_FIRST_STEP_MAX)
  229. ath9k_hw_ani_control(ah, ATH9K_ANI_FIRSTEP_LEVEL,
  230. aniState->firstepLevel + 1);
  231. } else {
  232. if ((conf->channel->band == IEEE80211_BAND_2GHZ) &&
  233. !conf_is_ht(conf)) {
  234. if (aniState->firstepLevel > 0)
  235. ath9k_hw_ani_control(ah,
  236. ATH9K_ANI_FIRSTEP_LEVEL, 0);
  237. }
  238. }
  239. }
  240. /* Adjust the OFDM Noise Immunity Level */
  241. static void ath9k_hw_set_ofdm_nil(struct ath_hw *ah, u8 immunityLevel)
  242. {
  243. struct ar5416AniState *aniState = &ah->curchan->ani;
  244. struct ath_common *common = ath9k_hw_common(ah);
  245. const struct ani_ofdm_level_entry *entry_ofdm;
  246. const struct ani_cck_level_entry *entry_cck;
  247. aniState->noiseFloor = BEACON_RSSI(ah);
  248. ath_print(common, ATH_DBG_ANI,
  249. "**** ofdmlevel %d=>%d, rssi=%d[lo=%d hi=%d]\n",
  250. aniState->ofdmNoiseImmunityLevel,
  251. immunityLevel, aniState->noiseFloor,
  252. aniState->rssiThrLow, aniState->rssiThrHigh);
  253. aniState->ofdmNoiseImmunityLevel = immunityLevel;
  254. entry_ofdm = &ofdm_level_table[aniState->ofdmNoiseImmunityLevel];
  255. entry_cck = &cck_level_table[aniState->cckNoiseImmunityLevel];
  256. if (aniState->spurImmunityLevel != entry_ofdm->spur_immunity_level)
  257. ath9k_hw_ani_control(ah,
  258. ATH9K_ANI_SPUR_IMMUNITY_LEVEL,
  259. entry_ofdm->spur_immunity_level);
  260. if (aniState->firstepLevel != entry_ofdm->fir_step_level &&
  261. entry_ofdm->fir_step_level >= entry_cck->fir_step_level)
  262. ath9k_hw_ani_control(ah,
  263. ATH9K_ANI_FIRSTEP_LEVEL,
  264. entry_ofdm->fir_step_level);
  265. if ((ah->opmode != NL80211_IFTYPE_STATION &&
  266. ah->opmode != NL80211_IFTYPE_ADHOC) ||
  267. aniState->noiseFloor <= aniState->rssiThrHigh) {
  268. if (aniState->ofdmWeakSigDetectOff)
  269. /* force on ofdm weak sig detect */
  270. ath9k_hw_ani_control(ah,
  271. ATH9K_ANI_OFDM_WEAK_SIGNAL_DETECTION,
  272. true);
  273. else if (aniState->ofdmWeakSigDetectOff ==
  274. entry_ofdm->ofdm_weak_signal_on)
  275. ath9k_hw_ani_control(ah,
  276. ATH9K_ANI_OFDM_WEAK_SIGNAL_DETECTION,
  277. entry_ofdm->ofdm_weak_signal_on);
  278. }
  279. }
  280. static void ath9k_hw_ani_ofdm_err_trigger_new(struct ath_hw *ah)
  281. {
  282. struct ar5416AniState *aniState;
  283. if (!DO_ANI(ah))
  284. return;
  285. aniState = &ah->curchan->ani;
  286. if (aniState->ofdmNoiseImmunityLevel < ATH9K_ANI_OFDM_MAX_LEVEL)
  287. ath9k_hw_set_ofdm_nil(ah, aniState->ofdmNoiseImmunityLevel + 1);
  288. }
  289. /*
  290. * Set the ANI settings to match an CCK level.
  291. */
  292. static void ath9k_hw_set_cck_nil(struct ath_hw *ah, u_int8_t immunityLevel)
  293. {
  294. struct ar5416AniState *aniState = &ah->curchan->ani;
  295. struct ath_common *common = ath9k_hw_common(ah);
  296. const struct ani_ofdm_level_entry *entry_ofdm;
  297. const struct ani_cck_level_entry *entry_cck;
  298. aniState->noiseFloor = BEACON_RSSI(ah);
  299. ath_print(common, ATH_DBG_ANI,
  300. "**** ccklevel %d=>%d, rssi=%d[lo=%d hi=%d]\n",
  301. aniState->cckNoiseImmunityLevel, immunityLevel,
  302. aniState->noiseFloor, aniState->rssiThrLow,
  303. aniState->rssiThrHigh);
  304. if ((ah->opmode == NL80211_IFTYPE_STATION ||
  305. ah->opmode == NL80211_IFTYPE_ADHOC) &&
  306. aniState->noiseFloor <= aniState->rssiThrLow &&
  307. immunityLevel > ATH9K_ANI_CCK_MAX_LEVEL_LOW_RSSI)
  308. immunityLevel = ATH9K_ANI_CCK_MAX_LEVEL_LOW_RSSI;
  309. aniState->cckNoiseImmunityLevel = immunityLevel;
  310. entry_ofdm = &ofdm_level_table[aniState->ofdmNoiseImmunityLevel];
  311. entry_cck = &cck_level_table[aniState->cckNoiseImmunityLevel];
  312. if (aniState->firstepLevel != entry_cck->fir_step_level &&
  313. entry_cck->fir_step_level >= entry_ofdm->fir_step_level)
  314. ath9k_hw_ani_control(ah,
  315. ATH9K_ANI_FIRSTEP_LEVEL,
  316. entry_cck->fir_step_level);
  317. /* Skip MRC CCK for pre AR9003 families */
  318. if (!AR_SREV_9300_20_OR_LATER(ah))
  319. return;
  320. if (aniState->mrcCCKOff == entry_cck->mrc_cck_on)
  321. ath9k_hw_ani_control(ah,
  322. ATH9K_ANI_MRC_CCK,
  323. entry_cck->mrc_cck_on);
  324. }
  325. static void ath9k_hw_ani_cck_err_trigger_new(struct ath_hw *ah)
  326. {
  327. struct ar5416AniState *aniState;
  328. if (!DO_ANI(ah))
  329. return;
  330. aniState = &ah->curchan->ani;
  331. if (aniState->cckNoiseImmunityLevel < ATH9K_ANI_CCK_MAX_LEVEL)
  332. ath9k_hw_set_cck_nil(ah, aniState->cckNoiseImmunityLevel + 1);
  333. }
  334. static void ath9k_hw_ani_lower_immunity_old(struct ath_hw *ah)
  335. {
  336. struct ar5416AniState *aniState;
  337. int32_t rssi;
  338. aniState = &ah->curchan->ani;
  339. if (ah->opmode == NL80211_IFTYPE_AP) {
  340. if (aniState->firstepLevel > 0) {
  341. if (ath9k_hw_ani_control(ah, ATH9K_ANI_FIRSTEP_LEVEL,
  342. aniState->firstepLevel - 1))
  343. return;
  344. }
  345. } else {
  346. rssi = BEACON_RSSI(ah);
  347. if (rssi > aniState->rssiThrHigh) {
  348. /* XXX: Handle me */
  349. } else if (rssi > aniState->rssiThrLow) {
  350. if (aniState->ofdmWeakSigDetectOff) {
  351. if (ath9k_hw_ani_control(ah,
  352. ATH9K_ANI_OFDM_WEAK_SIGNAL_DETECTION,
  353. true) == true)
  354. return;
  355. }
  356. if (aniState->firstepLevel > 0) {
  357. if (ath9k_hw_ani_control(ah,
  358. ATH9K_ANI_FIRSTEP_LEVEL,
  359. aniState->firstepLevel - 1) == true)
  360. return;
  361. }
  362. } else {
  363. if (aniState->firstepLevel > 0) {
  364. if (ath9k_hw_ani_control(ah,
  365. ATH9K_ANI_FIRSTEP_LEVEL,
  366. aniState->firstepLevel - 1) == true)
  367. return;
  368. }
  369. }
  370. }
  371. if (aniState->spurImmunityLevel > 0) {
  372. if (ath9k_hw_ani_control(ah, ATH9K_ANI_SPUR_IMMUNITY_LEVEL,
  373. aniState->spurImmunityLevel - 1))
  374. return;
  375. }
  376. if (aniState->noiseImmunityLevel > 0) {
  377. ath9k_hw_ani_control(ah, ATH9K_ANI_NOISE_IMMUNITY_LEVEL,
  378. aniState->noiseImmunityLevel - 1);
  379. return;
  380. }
  381. }
  382. /*
  383. * only lower either OFDM or CCK errors per turn
  384. * we lower the other one next time
  385. */
  386. static void ath9k_hw_ani_lower_immunity_new(struct ath_hw *ah)
  387. {
  388. struct ar5416AniState *aniState;
  389. aniState = &ah->curchan->ani;
  390. /* lower OFDM noise immunity */
  391. if (aniState->ofdmNoiseImmunityLevel > 0 &&
  392. (aniState->ofdmsTurn || aniState->cckNoiseImmunityLevel == 0)) {
  393. ath9k_hw_set_ofdm_nil(ah, aniState->ofdmNoiseImmunityLevel - 1);
  394. return;
  395. }
  396. /* lower CCK noise immunity */
  397. if (aniState->cckNoiseImmunityLevel > 0)
  398. ath9k_hw_set_cck_nil(ah, aniState->cckNoiseImmunityLevel - 1);
  399. }
  400. static u8 ath9k_hw_chan_2_clockrate_mhz(struct ath_hw *ah)
  401. {
  402. struct ath9k_channel *chan = ah->curchan;
  403. struct ieee80211_conf *conf = &ath9k_hw_common(ah)->hw->conf;
  404. u8 clockrate; /* in MHz */
  405. if (!ah->curchan) /* should really check for CCK instead */
  406. clockrate = ATH9K_CLOCK_RATE_CCK;
  407. else if (conf->channel->band == IEEE80211_BAND_2GHZ)
  408. clockrate = ATH9K_CLOCK_RATE_2GHZ_OFDM;
  409. else if (IS_CHAN_A_FAST_CLOCK(ah, chan))
  410. clockrate = ATH9K_CLOCK_FAST_RATE_5GHZ_OFDM;
  411. else
  412. clockrate = ATH9K_CLOCK_RATE_5GHZ_OFDM;
  413. if (conf_is_ht40(conf))
  414. return clockrate * 2;
  415. return clockrate;
  416. }
  417. static int32_t ath9k_hw_ani_get_listen_time(struct ath_hw *ah)
  418. {
  419. int32_t listen_time;
  420. int32_t clock_rate;
  421. ath9k_hw_update_cycle_counters(ah);
  422. clock_rate = ath9k_hw_chan_2_clockrate_mhz(ah) * 1000;
  423. listen_time = ah->listen_time / clock_rate;
  424. ah->listen_time = 0;
  425. return listen_time;
  426. }
  427. static void ath9k_ani_reset_old(struct ath_hw *ah, bool is_scanning)
  428. {
  429. struct ar5416AniState *aniState;
  430. struct ath9k_channel *chan = ah->curchan;
  431. struct ath_common *common = ath9k_hw_common(ah);
  432. if (!DO_ANI(ah))
  433. return;
  434. aniState = &ah->curchan->ani;
  435. if (ah->opmode != NL80211_IFTYPE_STATION
  436. && ah->opmode != NL80211_IFTYPE_ADHOC) {
  437. ath_print(common, ATH_DBG_ANI,
  438. "Reset ANI state opmode %u\n", ah->opmode);
  439. ah->stats.ast_ani_reset++;
  440. if (ah->opmode == NL80211_IFTYPE_AP) {
  441. /*
  442. * ath9k_hw_ani_control() will only process items set on
  443. * ah->ani_function
  444. */
  445. if (IS_CHAN_2GHZ(chan))
  446. ah->ani_function = (ATH9K_ANI_SPUR_IMMUNITY_LEVEL |
  447. ATH9K_ANI_FIRSTEP_LEVEL);
  448. else
  449. ah->ani_function = 0;
  450. }
  451. ath9k_hw_ani_control(ah, ATH9K_ANI_NOISE_IMMUNITY_LEVEL, 0);
  452. ath9k_hw_ani_control(ah, ATH9K_ANI_SPUR_IMMUNITY_LEVEL, 0);
  453. ath9k_hw_ani_control(ah, ATH9K_ANI_FIRSTEP_LEVEL, 0);
  454. ath9k_hw_ani_control(ah, ATH9K_ANI_OFDM_WEAK_SIGNAL_DETECTION,
  455. !ATH9K_ANI_USE_OFDM_WEAK_SIG);
  456. ath9k_hw_ani_control(ah, ATH9K_ANI_CCK_WEAK_SIGNAL_THR,
  457. ATH9K_ANI_CCK_WEAK_SIG_THR);
  458. ath9k_hw_setrxfilter(ah, ath9k_hw_getrxfilter(ah) |
  459. ATH9K_RX_FILTER_PHYERR);
  460. ath9k_ani_restart(ah);
  461. return;
  462. }
  463. if (aniState->noiseImmunityLevel != 0)
  464. ath9k_hw_ani_control(ah, ATH9K_ANI_NOISE_IMMUNITY_LEVEL,
  465. aniState->noiseImmunityLevel);
  466. if (aniState->spurImmunityLevel != 0)
  467. ath9k_hw_ani_control(ah, ATH9K_ANI_SPUR_IMMUNITY_LEVEL,
  468. aniState->spurImmunityLevel);
  469. if (aniState->ofdmWeakSigDetectOff)
  470. ath9k_hw_ani_control(ah, ATH9K_ANI_OFDM_WEAK_SIGNAL_DETECTION,
  471. !aniState->ofdmWeakSigDetectOff);
  472. if (aniState->cckWeakSigThreshold)
  473. ath9k_hw_ani_control(ah, ATH9K_ANI_CCK_WEAK_SIGNAL_THR,
  474. aniState->cckWeakSigThreshold);
  475. if (aniState->firstepLevel != 0)
  476. ath9k_hw_ani_control(ah, ATH9K_ANI_FIRSTEP_LEVEL,
  477. aniState->firstepLevel);
  478. ath9k_hw_setrxfilter(ah, ath9k_hw_getrxfilter(ah) &
  479. ~ATH9K_RX_FILTER_PHYERR);
  480. ath9k_ani_restart(ah);
  481. ENABLE_REGWRITE_BUFFER(ah);
  482. REG_WRITE(ah, AR_PHY_ERR_MASK_1, AR_PHY_ERR_OFDM_TIMING);
  483. REG_WRITE(ah, AR_PHY_ERR_MASK_2, AR_PHY_ERR_CCK_TIMING);
  484. REGWRITE_BUFFER_FLUSH(ah);
  485. }
  486. /*
  487. * Restore the ANI parameters in the HAL and reset the statistics.
  488. * This routine should be called for every hardware reset and for
  489. * every channel change.
  490. */
  491. static void ath9k_ani_reset_new(struct ath_hw *ah, bool is_scanning)
  492. {
  493. struct ar5416AniState *aniState = &ah->curchan->ani;
  494. struct ath9k_channel *chan = ah->curchan;
  495. struct ath_common *common = ath9k_hw_common(ah);
  496. if (!DO_ANI(ah))
  497. return;
  498. BUG_ON(aniState == NULL);
  499. ah->stats.ast_ani_reset++;
  500. /* only allow a subset of functions in AP mode */
  501. if (ah->opmode == NL80211_IFTYPE_AP) {
  502. if (IS_CHAN_2GHZ(chan)) {
  503. ah->ani_function = (ATH9K_ANI_SPUR_IMMUNITY_LEVEL |
  504. ATH9K_ANI_FIRSTEP_LEVEL);
  505. if (AR_SREV_9300_20_OR_LATER(ah))
  506. ah->ani_function |= ATH9K_ANI_MRC_CCK;
  507. } else
  508. ah->ani_function = 0;
  509. }
  510. /* always allow mode (on/off) to be controlled */
  511. ah->ani_function |= ATH9K_ANI_MODE;
  512. if (is_scanning ||
  513. (ah->opmode != NL80211_IFTYPE_STATION &&
  514. ah->opmode != NL80211_IFTYPE_ADHOC)) {
  515. /*
  516. * If we're scanning or in AP mode, the defaults (ini)
  517. * should be in place. For an AP we assume the historical
  518. * levels for this channel are probably outdated so start
  519. * from defaults instead.
  520. */
  521. if (aniState->ofdmNoiseImmunityLevel !=
  522. ATH9K_ANI_OFDM_DEF_LEVEL ||
  523. aniState->cckNoiseImmunityLevel !=
  524. ATH9K_ANI_CCK_DEF_LEVEL) {
  525. ath_print(common, ATH_DBG_ANI,
  526. "Restore defaults: opmode %u "
  527. "chan %d Mhz/0x%x is_scanning=%d "
  528. "ofdm:%d cck:%d\n",
  529. ah->opmode,
  530. chan->channel,
  531. chan->channelFlags,
  532. is_scanning,
  533. aniState->ofdmNoiseImmunityLevel,
  534. aniState->cckNoiseImmunityLevel);
  535. ath9k_hw_set_ofdm_nil(ah, ATH9K_ANI_OFDM_DEF_LEVEL);
  536. ath9k_hw_set_cck_nil(ah, ATH9K_ANI_CCK_DEF_LEVEL);
  537. }
  538. } else {
  539. /*
  540. * restore historical levels for this channel
  541. */
  542. ath_print(common, ATH_DBG_ANI,
  543. "Restore history: opmode %u "
  544. "chan %d Mhz/0x%x is_scanning=%d "
  545. "ofdm:%d cck:%d\n",
  546. ah->opmode,
  547. chan->channel,
  548. chan->channelFlags,
  549. is_scanning,
  550. aniState->ofdmNoiseImmunityLevel,
  551. aniState->cckNoiseImmunityLevel);
  552. ath9k_hw_set_ofdm_nil(ah,
  553. aniState->ofdmNoiseImmunityLevel);
  554. ath9k_hw_set_cck_nil(ah,
  555. aniState->cckNoiseImmunityLevel);
  556. }
  557. /*
  558. * enable phy counters if hw supports or if not, enable phy
  559. * interrupts (so we can count each one)
  560. */
  561. ath9k_ani_restart(ah);
  562. ENABLE_REGWRITE_BUFFER(ah);
  563. REG_WRITE(ah, AR_PHY_ERR_MASK_1, AR_PHY_ERR_OFDM_TIMING);
  564. REG_WRITE(ah, AR_PHY_ERR_MASK_2, AR_PHY_ERR_CCK_TIMING);
  565. REGWRITE_BUFFER_FLUSH(ah);
  566. }
  567. static void ath9k_hw_ani_monitor_old(struct ath_hw *ah,
  568. struct ath9k_channel *chan)
  569. {
  570. struct ar5416AniState *aniState;
  571. struct ath_common *common = ath9k_hw_common(ah);
  572. int32_t listenTime;
  573. u32 phyCnt1, phyCnt2;
  574. u32 ofdmPhyErrCnt, cckPhyErrCnt;
  575. u32 ofdm_base = AR_PHY_COUNTMAX - ah->config.ofdm_trig_high;
  576. u32 cck_base = AR_PHY_COUNTMAX - ah->config.cck_trig_high;
  577. if (!DO_ANI(ah))
  578. return;
  579. aniState = &ah->curchan->ani;
  580. listenTime = ath9k_hw_ani_get_listen_time(ah);
  581. if (listenTime < 0) {
  582. ah->stats.ast_ani_lneg++;
  583. ath9k_ani_restart(ah);
  584. return;
  585. }
  586. aniState->listenTime += listenTime;
  587. ath9k_hw_update_mibstats(ah, &ah->ah_mibStats);
  588. phyCnt1 = REG_READ(ah, AR_PHY_ERR_1);
  589. phyCnt2 = REG_READ(ah, AR_PHY_ERR_2);
  590. if (phyCnt1 < ofdm_base || phyCnt2 < cck_base) {
  591. if (phyCnt1 < ofdm_base) {
  592. ath_print(common, ATH_DBG_ANI,
  593. "phyCnt1 0x%x, resetting "
  594. "counter value to 0x%x\n",
  595. phyCnt1, ofdm_base);
  596. REG_WRITE(ah, AR_PHY_ERR_1, ofdm_base);
  597. REG_WRITE(ah, AR_PHY_ERR_MASK_1,
  598. AR_PHY_ERR_OFDM_TIMING);
  599. }
  600. if (phyCnt2 < cck_base) {
  601. ath_print(common, ATH_DBG_ANI,
  602. "phyCnt2 0x%x, resetting "
  603. "counter value to 0x%x\n",
  604. phyCnt2, cck_base);
  605. REG_WRITE(ah, AR_PHY_ERR_2, cck_base);
  606. REG_WRITE(ah, AR_PHY_ERR_MASK_2,
  607. AR_PHY_ERR_CCK_TIMING);
  608. }
  609. return;
  610. }
  611. ofdmPhyErrCnt = phyCnt1 - ofdm_base;
  612. ah->stats.ast_ani_ofdmerrs +=
  613. ofdmPhyErrCnt - aniState->ofdmPhyErrCount;
  614. aniState->ofdmPhyErrCount = ofdmPhyErrCnt;
  615. cckPhyErrCnt = phyCnt2 - cck_base;
  616. ah->stats.ast_ani_cckerrs +=
  617. cckPhyErrCnt - aniState->cckPhyErrCount;
  618. aniState->cckPhyErrCount = cckPhyErrCnt;
  619. if (aniState->listenTime > 5 * ah->aniperiod) {
  620. if (aniState->ofdmPhyErrCount <= aniState->listenTime *
  621. ah->config.ofdm_trig_low / 1000 &&
  622. aniState->cckPhyErrCount <= aniState->listenTime *
  623. ah->config.cck_trig_low / 1000)
  624. ath9k_hw_ani_lower_immunity(ah);
  625. ath9k_ani_restart(ah);
  626. } else if (aniState->listenTime > ah->aniperiod) {
  627. if (aniState->ofdmPhyErrCount > aniState->listenTime *
  628. ah->config.ofdm_trig_high / 1000) {
  629. ath9k_hw_ani_ofdm_err_trigger_old(ah);
  630. ath9k_ani_restart(ah);
  631. } else if (aniState->cckPhyErrCount >
  632. aniState->listenTime * ah->config.cck_trig_high /
  633. 1000) {
  634. ath9k_hw_ani_cck_err_trigger_old(ah);
  635. ath9k_ani_restart(ah);
  636. }
  637. }
  638. }
  639. static void ath9k_hw_ani_monitor_new(struct ath_hw *ah,
  640. struct ath9k_channel *chan)
  641. {
  642. struct ar5416AniState *aniState;
  643. struct ath_common *common = ath9k_hw_common(ah);
  644. int32_t listenTime;
  645. u32 ofdmPhyErrCnt, cckPhyErrCnt;
  646. u32 ofdmPhyErrRate, cckPhyErrRate;
  647. if (!DO_ANI(ah))
  648. return;
  649. aniState = &ah->curchan->ani;
  650. if (WARN_ON(!aniState))
  651. return;
  652. listenTime = ath9k_hw_ani_get_listen_time(ah);
  653. if (listenTime <= 0) {
  654. ah->stats.ast_ani_lneg++;
  655. /* restart ANI period if listenTime is invalid */
  656. ath_print(common, ATH_DBG_ANI,
  657. "listenTime=%d - on new ani monitor\n",
  658. listenTime);
  659. ath9k_ani_restart(ah);
  660. return;
  661. }
  662. aniState->listenTime += listenTime;
  663. ath9k_hw_update_mibstats(ah, &ah->ah_mibStats);
  664. ofdmPhyErrCnt = REG_READ(ah, AR_PHY_ERR_1);
  665. cckPhyErrCnt = REG_READ(ah, AR_PHY_ERR_2);
  666. ah->stats.ast_ani_ofdmerrs +=
  667. ofdmPhyErrCnt - aniState->ofdmPhyErrCount;
  668. aniState->ofdmPhyErrCount = ofdmPhyErrCnt;
  669. ah->stats.ast_ani_cckerrs +=
  670. cckPhyErrCnt - aniState->cckPhyErrCount;
  671. aniState->cckPhyErrCount = cckPhyErrCnt;
  672. ath_print(common, ATH_DBG_ANI,
  673. "Errors: OFDM=%d, CCK=%d\n",
  674. ofdmPhyErrCnt, cckPhyErrCnt);
  675. ofdmPhyErrRate = aniState->ofdmPhyErrCount * 1000 /
  676. aniState->listenTime;
  677. cckPhyErrRate = aniState->cckPhyErrCount * 1000 /
  678. aniState->listenTime;
  679. ath_print(common, ATH_DBG_ANI,
  680. "listenTime=%d OFDM:%d errs=%d/s CCK:%d "
  681. "errs=%d/s ofdm_turn=%d\n",
  682. listenTime, aniState->ofdmNoiseImmunityLevel,
  683. ofdmPhyErrRate, aniState->cckNoiseImmunityLevel,
  684. cckPhyErrRate, aniState->ofdmsTurn);
  685. if (aniState->listenTime > 5 * ah->aniperiod) {
  686. if (ofdmPhyErrRate <= ah->config.ofdm_trig_low &&
  687. cckPhyErrRate <= ah->config.cck_trig_low) {
  688. ath_print(common, ATH_DBG_ANI,
  689. "1. listenTime=%d OFDM:%d errs=%d/s(<%d) "
  690. "CCK:%d errs=%d/s(<%d) -> "
  691. "ath9k_hw_ani_lower_immunity()\n",
  692. aniState->listenTime,
  693. aniState->ofdmNoiseImmunityLevel,
  694. ofdmPhyErrRate,
  695. ah->config.ofdm_trig_low,
  696. aniState->cckNoiseImmunityLevel,
  697. cckPhyErrRate,
  698. ah->config.cck_trig_low);
  699. ath9k_hw_ani_lower_immunity(ah);
  700. aniState->ofdmsTurn = !aniState->ofdmsTurn;
  701. }
  702. ath_print(common, ATH_DBG_ANI,
  703. "1 listenTime=%d ofdm=%d/s cck=%d/s - "
  704. "calling ath9k_ani_restart()\n",
  705. aniState->listenTime, ofdmPhyErrRate, cckPhyErrRate);
  706. ath9k_ani_restart(ah);
  707. } else if (aniState->listenTime > ah->aniperiod) {
  708. /* check to see if need to raise immunity */
  709. if (ofdmPhyErrRate > ah->config.ofdm_trig_high &&
  710. (cckPhyErrRate <= ah->config.cck_trig_high ||
  711. aniState->ofdmsTurn)) {
  712. ath_print(common, ATH_DBG_ANI,
  713. "2 listenTime=%d OFDM:%d errs=%d/s(>%d) -> "
  714. "ath9k_hw_ani_ofdm_err_trigger_new()\n",
  715. aniState->listenTime,
  716. aniState->ofdmNoiseImmunityLevel,
  717. ofdmPhyErrRate,
  718. ah->config.ofdm_trig_high);
  719. ath9k_hw_ani_ofdm_err_trigger_new(ah);
  720. ath9k_ani_restart(ah);
  721. aniState->ofdmsTurn = false;
  722. } else if (cckPhyErrRate > ah->config.cck_trig_high) {
  723. ath_print(common, ATH_DBG_ANI,
  724. "3 listenTime=%d CCK:%d errs=%d/s(>%d) -> "
  725. "ath9k_hw_ani_cck_err_trigger_new()\n",
  726. aniState->listenTime,
  727. aniState->cckNoiseImmunityLevel,
  728. cckPhyErrRate,
  729. ah->config.cck_trig_high);
  730. ath9k_hw_ani_cck_err_trigger_new(ah);
  731. ath9k_ani_restart(ah);
  732. aniState->ofdmsTurn = true;
  733. }
  734. }
  735. }
  736. void ath9k_enable_mib_counters(struct ath_hw *ah)
  737. {
  738. struct ath_common *common = ath9k_hw_common(ah);
  739. ath_print(common, ATH_DBG_ANI, "Enable MIB counters\n");
  740. ath9k_hw_update_mibstats(ah, &ah->ah_mibStats);
  741. ENABLE_REGWRITE_BUFFER(ah);
  742. REG_WRITE(ah, AR_FILT_OFDM, 0);
  743. REG_WRITE(ah, AR_FILT_CCK, 0);
  744. REG_WRITE(ah, AR_MIBC,
  745. ~(AR_MIBC_COW | AR_MIBC_FMC | AR_MIBC_CMC | AR_MIBC_MCS)
  746. & 0x0f);
  747. REG_WRITE(ah, AR_PHY_ERR_MASK_1, AR_PHY_ERR_OFDM_TIMING);
  748. REG_WRITE(ah, AR_PHY_ERR_MASK_2, AR_PHY_ERR_CCK_TIMING);
  749. REGWRITE_BUFFER_FLUSH(ah);
  750. }
  751. /* Freeze the MIB counters, get the stats and then clear them */
  752. void ath9k_hw_disable_mib_counters(struct ath_hw *ah)
  753. {
  754. struct ath_common *common = ath9k_hw_common(ah);
  755. ath_print(common, ATH_DBG_ANI, "Disable MIB counters\n");
  756. REG_WRITE(ah, AR_MIBC, AR_MIBC_FMC);
  757. ath9k_hw_update_mibstats(ah, &ah->ah_mibStats);
  758. REG_WRITE(ah, AR_MIBC, AR_MIBC_CMC);
  759. REG_WRITE(ah, AR_FILT_OFDM, 0);
  760. REG_WRITE(ah, AR_FILT_CCK, 0);
  761. }
  762. EXPORT_SYMBOL(ath9k_hw_disable_mib_counters);
  763. void ath9k_hw_update_cycle_counters(struct ath_hw *ah)
  764. {
  765. struct ath_cycle_counters cc;
  766. bool clear;
  767. memcpy(&cc, &ah->cc, sizeof(cc));
  768. /* freeze counters */
  769. REG_WRITE(ah, AR_MIBC, AR_MIBC_FMC);
  770. ah->cc.cycles = REG_READ(ah, AR_CCCNT);
  771. if (ah->cc.cycles < cc.cycles) {
  772. clear = true;
  773. goto skip;
  774. }
  775. ah->cc.rx_clear = REG_READ(ah, AR_RCCNT);
  776. ah->cc.rx_frame = REG_READ(ah, AR_RFCNT);
  777. ah->cc.tx_frame = REG_READ(ah, AR_TFCNT);
  778. /* prevent wraparound */
  779. if (ah->cc.cycles & BIT(31))
  780. clear = true;
  781. #define CC_DELTA(_field, _reg) ah->cc_delta._field += ah->cc._field - cc._field
  782. CC_DELTA(cycles, AR_CCCNT);
  783. CC_DELTA(rx_frame, AR_RFCNT);
  784. CC_DELTA(rx_clear, AR_RCCNT);
  785. CC_DELTA(tx_frame, AR_TFCNT);
  786. #undef CC_DELTA
  787. ah->listen_time += (ah->cc.cycles - cc.cycles) -
  788. ((ah->cc.rx_frame - cc.rx_frame) +
  789. (ah->cc.tx_frame - cc.tx_frame));
  790. skip:
  791. if (clear) {
  792. REG_WRITE(ah, AR_CCCNT, 0);
  793. REG_WRITE(ah, AR_RFCNT, 0);
  794. REG_WRITE(ah, AR_RCCNT, 0);
  795. REG_WRITE(ah, AR_TFCNT, 0);
  796. memset(&ah->cc, 0, sizeof(ah->cc));
  797. }
  798. /* unfreeze counters */
  799. REG_WRITE(ah, AR_MIBC, 0);
  800. }
  801. /*
  802. * Process a MIB interrupt. We may potentially be invoked because
  803. * any of the MIB counters overflow/trigger so don't assume we're
  804. * here because a PHY error counter triggered.
  805. */
  806. static void ath9k_hw_proc_mib_event_old(struct ath_hw *ah)
  807. {
  808. u32 ofdm_base = AR_PHY_COUNTMAX - ah->config.ofdm_trig_high;
  809. u32 cck_base = AR_PHY_COUNTMAX - ah->config.cck_trig_high;
  810. u32 phyCnt1, phyCnt2;
  811. /* Reset these counters regardless */
  812. REG_WRITE(ah, AR_FILT_OFDM, 0);
  813. REG_WRITE(ah, AR_FILT_CCK, 0);
  814. if (!(REG_READ(ah, AR_SLP_MIB_CTRL) & AR_SLP_MIB_PENDING))
  815. REG_WRITE(ah, AR_SLP_MIB_CTRL, AR_SLP_MIB_CLEAR);
  816. /* Clear the mib counters and save them in the stats */
  817. ath9k_hw_update_mibstats(ah, &ah->ah_mibStats);
  818. if (!DO_ANI(ah)) {
  819. /*
  820. * We must always clear the interrupt cause by
  821. * resetting the phy error regs.
  822. */
  823. REG_WRITE(ah, AR_PHY_ERR_1, 0);
  824. REG_WRITE(ah, AR_PHY_ERR_2, 0);
  825. return;
  826. }
  827. /* NB: these are not reset-on-read */
  828. phyCnt1 = REG_READ(ah, AR_PHY_ERR_1);
  829. phyCnt2 = REG_READ(ah, AR_PHY_ERR_2);
  830. if (((phyCnt1 & AR_MIBCNT_INTRMASK) == AR_MIBCNT_INTRMASK) ||
  831. ((phyCnt2 & AR_MIBCNT_INTRMASK) == AR_MIBCNT_INTRMASK)) {
  832. struct ar5416AniState *aniState = &ah->curchan->ani;
  833. u32 ofdmPhyErrCnt, cckPhyErrCnt;
  834. /* NB: only use ast_ani_*errs with AH_PRIVATE_DIAG */
  835. ofdmPhyErrCnt = phyCnt1 - ofdm_base;
  836. ah->stats.ast_ani_ofdmerrs +=
  837. ofdmPhyErrCnt - aniState->ofdmPhyErrCount;
  838. aniState->ofdmPhyErrCount = ofdmPhyErrCnt;
  839. cckPhyErrCnt = phyCnt2 - cck_base;
  840. ah->stats.ast_ani_cckerrs +=
  841. cckPhyErrCnt - aniState->cckPhyErrCount;
  842. aniState->cckPhyErrCount = cckPhyErrCnt;
  843. /*
  844. * NB: figure out which counter triggered. If both
  845. * trigger we'll only deal with one as the processing
  846. * clobbers the error counter so the trigger threshold
  847. * check will never be true.
  848. */
  849. if (aniState->ofdmPhyErrCount > ah->config.ofdm_trig_high)
  850. ath9k_hw_ani_ofdm_err_trigger_new(ah);
  851. if (aniState->cckPhyErrCount > ah->config.cck_trig_high)
  852. ath9k_hw_ani_cck_err_trigger_old(ah);
  853. /* NB: always restart to insure the h/w counters are reset */
  854. ath9k_ani_restart(ah);
  855. }
  856. }
  857. /*
  858. * Process a MIB interrupt. We may potentially be invoked because
  859. * any of the MIB counters overflow/trigger so don't assume we're
  860. * here because a PHY error counter triggered.
  861. */
  862. static void ath9k_hw_proc_mib_event_new(struct ath_hw *ah)
  863. {
  864. u32 phyCnt1, phyCnt2;
  865. /* Reset these counters regardless */
  866. REG_WRITE(ah, AR_FILT_OFDM, 0);
  867. REG_WRITE(ah, AR_FILT_CCK, 0);
  868. if (!(REG_READ(ah, AR_SLP_MIB_CTRL) & AR_SLP_MIB_PENDING))
  869. REG_WRITE(ah, AR_SLP_MIB_CTRL, AR_SLP_MIB_CLEAR);
  870. /* Clear the mib counters and save them in the stats */
  871. ath9k_hw_update_mibstats(ah, &ah->ah_mibStats);
  872. if (!DO_ANI(ah)) {
  873. /*
  874. * We must always clear the interrupt cause by
  875. * resetting the phy error regs.
  876. */
  877. REG_WRITE(ah, AR_PHY_ERR_1, 0);
  878. REG_WRITE(ah, AR_PHY_ERR_2, 0);
  879. return;
  880. }
  881. /* NB: these are not reset-on-read */
  882. phyCnt1 = REG_READ(ah, AR_PHY_ERR_1);
  883. phyCnt2 = REG_READ(ah, AR_PHY_ERR_2);
  884. /* NB: always restart to insure the h/w counters are reset */
  885. if (((phyCnt1 & AR_MIBCNT_INTRMASK) == AR_MIBCNT_INTRMASK) ||
  886. ((phyCnt2 & AR_MIBCNT_INTRMASK) == AR_MIBCNT_INTRMASK))
  887. ath9k_ani_restart(ah);
  888. }
  889. void ath9k_hw_ani_setup(struct ath_hw *ah)
  890. {
  891. int i;
  892. const int totalSizeDesired[] = { -55, -55, -55, -55, -62 };
  893. const int coarseHigh[] = { -14, -14, -14, -14, -12 };
  894. const int coarseLow[] = { -64, -64, -64, -64, -70 };
  895. const int firpwr[] = { -78, -78, -78, -78, -80 };
  896. for (i = 0; i < 5; i++) {
  897. ah->totalSizeDesired[i] = totalSizeDesired[i];
  898. ah->coarse_high[i] = coarseHigh[i];
  899. ah->coarse_low[i] = coarseLow[i];
  900. ah->firpwr[i] = firpwr[i];
  901. }
  902. }
  903. void ath9k_hw_ani_init(struct ath_hw *ah)
  904. {
  905. struct ath_common *common = ath9k_hw_common(ah);
  906. int i;
  907. ath_print(common, ATH_DBG_ANI, "Initialize ANI\n");
  908. if (use_new_ani(ah)) {
  909. ah->config.ofdm_trig_high = ATH9K_ANI_OFDM_TRIG_HIGH_NEW;
  910. ah->config.ofdm_trig_low = ATH9K_ANI_OFDM_TRIG_LOW_NEW;
  911. ah->config.cck_trig_high = ATH9K_ANI_CCK_TRIG_HIGH_NEW;
  912. ah->config.cck_trig_low = ATH9K_ANI_CCK_TRIG_LOW_NEW;
  913. } else {
  914. ah->config.ofdm_trig_high = ATH9K_ANI_OFDM_TRIG_HIGH_OLD;
  915. ah->config.ofdm_trig_low = ATH9K_ANI_OFDM_TRIG_LOW_OLD;
  916. ah->config.cck_trig_high = ATH9K_ANI_CCK_TRIG_HIGH_OLD;
  917. ah->config.cck_trig_low = ATH9K_ANI_CCK_TRIG_LOW_OLD;
  918. }
  919. for (i = 0; i < ARRAY_SIZE(ah->channels); i++) {
  920. struct ath9k_channel *chan = &ah->channels[i];
  921. struct ar5416AniState *ani = &chan->ani;
  922. if (use_new_ani(ah)) {
  923. ani->spurImmunityLevel =
  924. ATH9K_ANI_SPUR_IMMUNE_LVL_NEW;
  925. ani->firstepLevel = ATH9K_ANI_FIRSTEP_LVL_NEW;
  926. if (AR_SREV_9300_20_OR_LATER(ah))
  927. ani->mrcCCKOff =
  928. !ATH9K_ANI_ENABLE_MRC_CCK;
  929. else
  930. ani->mrcCCKOff = true;
  931. ani->ofdmsTurn = true;
  932. } else {
  933. ani->spurImmunityLevel =
  934. ATH9K_ANI_SPUR_IMMUNE_LVL_OLD;
  935. ani->firstepLevel = ATH9K_ANI_FIRSTEP_LVL_OLD;
  936. ani->cckWeakSigThreshold =
  937. ATH9K_ANI_CCK_WEAK_SIG_THR;
  938. }
  939. ani->rssiThrHigh = ATH9K_ANI_RSSI_THR_HIGH;
  940. ani->rssiThrLow = ATH9K_ANI_RSSI_THR_LOW;
  941. ani->ofdmWeakSigDetectOff =
  942. !ATH9K_ANI_USE_OFDM_WEAK_SIG;
  943. ani->cckNoiseImmunityLevel = ATH9K_ANI_CCK_DEF_LEVEL;
  944. }
  945. /*
  946. * since we expect some ongoing maintenance on the tables, let's sanity
  947. * check here default level should not modify INI setting.
  948. */
  949. if (use_new_ani(ah)) {
  950. const struct ani_ofdm_level_entry *entry_ofdm;
  951. const struct ani_cck_level_entry *entry_cck;
  952. entry_ofdm = &ofdm_level_table[ATH9K_ANI_OFDM_DEF_LEVEL];
  953. entry_cck = &cck_level_table[ATH9K_ANI_CCK_DEF_LEVEL];
  954. ah->aniperiod = ATH9K_ANI_PERIOD_NEW;
  955. ah->config.ani_poll_interval = ATH9K_ANI_POLLINTERVAL_NEW;
  956. } else {
  957. ah->aniperiod = ATH9K_ANI_PERIOD_OLD;
  958. ah->config.ani_poll_interval = ATH9K_ANI_POLLINTERVAL_OLD;
  959. }
  960. if (ah->config.enable_ani)
  961. ah->proc_phyerr |= HAL_PROCESS_ANI;
  962. ath9k_ani_restart(ah);
  963. ath9k_enable_mib_counters(ah);
  964. }
  965. void ath9k_hw_attach_ani_ops_old(struct ath_hw *ah)
  966. {
  967. struct ath_hw_private_ops *priv_ops = ath9k_hw_private_ops(ah);
  968. struct ath_hw_ops *ops = ath9k_hw_ops(ah);
  969. priv_ops->ani_reset = ath9k_ani_reset_old;
  970. priv_ops->ani_lower_immunity = ath9k_hw_ani_lower_immunity_old;
  971. ops->ani_proc_mib_event = ath9k_hw_proc_mib_event_old;
  972. ops->ani_monitor = ath9k_hw_ani_monitor_old;
  973. ath_print(ath9k_hw_common(ah), ATH_DBG_ANY, "Using ANI v1\n");
  974. }
  975. void ath9k_hw_attach_ani_ops_new(struct ath_hw *ah)
  976. {
  977. struct ath_hw_private_ops *priv_ops = ath9k_hw_private_ops(ah);
  978. struct ath_hw_ops *ops = ath9k_hw_ops(ah);
  979. priv_ops->ani_reset = ath9k_ani_reset_new;
  980. priv_ops->ani_lower_immunity = ath9k_hw_ani_lower_immunity_new;
  981. ops->ani_proc_mib_event = ath9k_hw_proc_mib_event_new;
  982. ops->ani_monitor = ath9k_hw_ani_monitor_new;
  983. ath_print(ath9k_hw_common(ah), ATH_DBG_ANY, "Using ANI v2\n");
  984. }