diff options
author | Kalle Valo <kvalo@qca.qualcomm.com> | 2011-12-16 14:10:39 -0500 |
---|---|---|
committer | Kalle Valo <kvalo@qca.qualcomm.com> | 2011-12-16 14:10:39 -0500 |
commit | 7e95e365d5399647a41e10059e4b09826b82d78b (patch) | |
tree | 305c9968798adae3d9484657339fa39d2a5fdaac /drivers/net/wireless/ath | |
parent | 3ca9d1fc9aa64077645a26c396de9399b49ea226 (diff) | |
parent | 5bd5e9a6ae5137a61d0b5c277eac61892d89fc4f (diff) |
Merge remote branch 'wireless-next/master' into ath6kl-next
Conflicts:
drivers/net/wireless/ath/ath6kl/init.c
Diffstat (limited to 'drivers/net/wireless/ath')
78 files changed, 6166 insertions, 1412 deletions
diff --git a/drivers/net/wireless/ath/Kconfig b/drivers/net/wireless/ath/Kconfig index 073548836413..09602241901b 100644 --- a/drivers/net/wireless/ath/Kconfig +++ b/drivers/net/wireless/ath/Kconfig | |||
@@ -1,6 +1,6 @@ | |||
1 | menuconfig ATH_COMMON | 1 | menuconfig ATH_COMMON |
2 | tristate "Atheros Wireless Cards" | 2 | tristate "Atheros Wireless Cards" |
3 | depends on CFG80211 | 3 | depends on CFG80211 && (!UML || BROKEN) |
4 | ---help--- | 4 | ---help--- |
5 | This will enable the support for the Atheros wireless drivers. | 5 | This will enable the support for the Atheros wireless drivers. |
6 | ath5k, ath9k, ath9k_htc and ar9170 drivers share some common code, this option | 6 | ath5k, ath9k, ath9k_htc and ar9170 drivers share some common code, this option |
diff --git a/drivers/net/wireless/ath/ath.h b/drivers/net/wireless/ath/ath.h index fe4bf4da255f..c1d699fd5717 100644 --- a/drivers/net/wireless/ath/ath.h +++ b/drivers/net/wireless/ath/ath.h | |||
@@ -152,6 +152,7 @@ struct ath_common { | |||
152 | struct ath_cycle_counters cc_survey; | 152 | struct ath_cycle_counters cc_survey; |
153 | 153 | ||
154 | struct ath_regulatory regulatory; | 154 | struct ath_regulatory regulatory; |
155 | struct ath_regulatory reg_world_copy; | ||
155 | const struct ath_ops *ops; | 156 | const struct ath_ops *ops; |
156 | const struct ath_bus_ops *bus_ops; | 157 | const struct ath_bus_ops *bus_ops; |
157 | 158 | ||
@@ -173,8 +174,7 @@ bool ath_hw_keyreset(struct ath_common *common, u16 entry); | |||
173 | void ath_hw_cycle_counters_update(struct ath_common *common); | 174 | void ath_hw_cycle_counters_update(struct ath_common *common); |
174 | int32_t ath_hw_get_listen_time(struct ath_common *common); | 175 | int32_t ath_hw_get_listen_time(struct ath_common *common); |
175 | 176 | ||
176 | extern __attribute__((format (printf, 2, 3))) | 177 | extern __printf(2, 3) void ath_printk(const char *level, const char *fmt, ...); |
177 | void ath_printk(const char *level, const char *fmt, ...); | ||
178 | 178 | ||
179 | #define _ath_printk(level, common, fmt, ...) \ | 179 | #define _ath_printk(level, common, fmt, ...) \ |
180 | do { \ | 180 | do { \ |
@@ -215,6 +215,10 @@ do { \ | |||
215 | * @ATH_DBG_HWTIMER: hardware timer handling | 215 | * @ATH_DBG_HWTIMER: hardware timer handling |
216 | * @ATH_DBG_BTCOEX: bluetooth coexistance | 216 | * @ATH_DBG_BTCOEX: bluetooth coexistance |
217 | * @ATH_DBG_BSTUCK: stuck beacons | 217 | * @ATH_DBG_BSTUCK: stuck beacons |
218 | * @ATH_DBG_MCI: Message Coexistence Interface, a private protocol | ||
219 | * used exclusively for WLAN-BT coexistence starting from | ||
220 | * AR9462. | ||
221 | * @ATH_DBG_DFS: radar datection | ||
218 | * @ATH_DBG_ANY: enable all debugging | 222 | * @ATH_DBG_ANY: enable all debugging |
219 | * | 223 | * |
220 | * The debug level is used to control the amount and type of debugging output | 224 | * The debug level is used to control the amount and type of debugging output |
@@ -241,6 +245,7 @@ enum ATH_DEBUG { | |||
241 | ATH_DBG_WMI = 0x00004000, | 245 | ATH_DBG_WMI = 0x00004000, |
242 | ATH_DBG_BSTUCK = 0x00008000, | 246 | ATH_DBG_BSTUCK = 0x00008000, |
243 | ATH_DBG_MCI = 0x00010000, | 247 | ATH_DBG_MCI = 0x00010000, |
248 | ATH_DBG_DFS = 0x00020000, | ||
244 | ATH_DBG_ANY = 0xffffffff | 249 | ATH_DBG_ANY = 0xffffffff |
245 | }; | 250 | }; |
246 | 251 | ||
@@ -259,7 +264,7 @@ do { \ | |||
259 | 264 | ||
260 | #else | 265 | #else |
261 | 266 | ||
262 | static inline __attribute__((format (printf, 3, 4))) | 267 | static inline __attribute__ ((format (printf, 3, 4))) |
263 | void ath_dbg(struct ath_common *common, enum ATH_DEBUG dbg_mask, | 268 | void ath_dbg(struct ath_common *common, enum ATH_DEBUG dbg_mask, |
264 | const char *fmt, ...) | 269 | const char *fmt, ...) |
265 | { | 270 | { |
diff --git a/drivers/net/wireless/ath/ath5k/ahb.c b/drivers/net/wireless/ath/ath5k/ahb.c index e5be7e701816..ee7ea572b065 100644 --- a/drivers/net/wireless/ath/ath5k/ahb.c +++ b/drivers/net/wireless/ath/ath5k/ahb.c | |||
@@ -166,7 +166,9 @@ static int ath_ahb_probe(struct platform_device *pdev) | |||
166 | if (to_platform_device(ah->dev)->id == 0 && | 166 | if (to_platform_device(ah->dev)->id == 0 && |
167 | (bcfg->config->flags & (BD_WLAN0 | BD_WLAN1)) == | 167 | (bcfg->config->flags & (BD_WLAN0 | BD_WLAN1)) == |
168 | (BD_WLAN1 | BD_WLAN0)) | 168 | (BD_WLAN1 | BD_WLAN0)) |
169 | __set_bit(ATH_STAT_2G_DISABLED, ah->status); | 169 | ah->ah_capabilities.cap_needs_2GHz_ovr = true; |
170 | else | ||
171 | ah->ah_capabilities.cap_needs_2GHz_ovr = false; | ||
170 | } | 172 | } |
171 | 173 | ||
172 | ret = ath5k_init_ah(ah, &ath_ahb_bus_ops); | 174 | ret = ath5k_init_ah(ah, &ath_ahb_bus_ops); |
diff --git a/drivers/net/wireless/ath/ath5k/ani.c b/drivers/net/wireless/ath/ath5k/ani.c index bea90e6be70e..bf674161a217 100644 --- a/drivers/net/wireless/ath/ath5k/ani.c +++ b/drivers/net/wireless/ath/ath5k/ani.c | |||
@@ -27,15 +27,21 @@ | |||
27 | * or reducing sensitivity as necessary. | 27 | * or reducing sensitivity as necessary. |
28 | * | 28 | * |
29 | * The parameters are: | 29 | * The parameters are: |
30 | * | ||
30 | * - "noise immunity" | 31 | * - "noise immunity" |
32 | * | ||
31 | * - "spur immunity" | 33 | * - "spur immunity" |
34 | * | ||
32 | * - "firstep level" | 35 | * - "firstep level" |
36 | * | ||
33 | * - "OFDM weak signal detection" | 37 | * - "OFDM weak signal detection" |
38 | * | ||
34 | * - "CCK weak signal detection" | 39 | * - "CCK weak signal detection" |
35 | * | 40 | * |
36 | * Basically we look at the amount of ODFM and CCK timing errors we get and then | 41 | * Basically we look at the amount of ODFM and CCK timing errors we get and then |
37 | * raise or lower immunity accordingly by setting one or more of these | 42 | * raise or lower immunity accordingly by setting one or more of these |
38 | * parameters. | 43 | * parameters. |
44 | * | ||
39 | * Newer chipsets have PHY error counters in hardware which will generate a MIB | 45 | * Newer chipsets have PHY error counters in hardware which will generate a MIB |
40 | * interrupt when they overflow. Older hardware has too enable PHY error frames | 46 | * interrupt when they overflow. Older hardware has too enable PHY error frames |
41 | * by setting a RX flag and then count every single PHY error. When a specified | 47 | * by setting a RX flag and then count every single PHY error. When a specified |
@@ -45,11 +51,13 @@ | |||
45 | */ | 51 | */ |
46 | 52 | ||
47 | 53 | ||
48 | /*** ANI parameter control ***/ | 54 | /***********************\ |
55 | * ANI parameter control * | ||
56 | \***********************/ | ||
49 | 57 | ||
50 | /** | 58 | /** |
51 | * ath5k_ani_set_noise_immunity_level() - Set noise immunity level | 59 | * ath5k_ani_set_noise_immunity_level() - Set noise immunity level |
52 | * | 60 | * @ah: The &struct ath5k_hw |
53 | * @level: level between 0 and @ATH5K_ANI_MAX_NOISE_IMM_LVL | 61 | * @level: level between 0 and @ATH5K_ANI_MAX_NOISE_IMM_LVL |
54 | */ | 62 | */ |
55 | void | 63 | void |
@@ -91,12 +99,11 @@ ath5k_ani_set_noise_immunity_level(struct ath5k_hw *ah, int level) | |||
91 | ATH5K_DBG_UNLIMIT(ah, ATH5K_DEBUG_ANI, "new level %d", level); | 99 | ATH5K_DBG_UNLIMIT(ah, ATH5K_DEBUG_ANI, "new level %d", level); |
92 | } | 100 | } |
93 | 101 | ||
94 | |||
95 | /** | 102 | /** |
96 | * ath5k_ani_set_spur_immunity_level() - Set spur immunity level | 103 | * ath5k_ani_set_spur_immunity_level() - Set spur immunity level |
97 | * | 104 | * @ah: The &struct ath5k_hw |
98 | * @level: level between 0 and @max_spur_level (the maximum level is dependent | 105 | * @level: level between 0 and @max_spur_level (the maximum level is dependent |
99 | * on the chip revision). | 106 | * on the chip revision). |
100 | */ | 107 | */ |
101 | void | 108 | void |
102 | ath5k_ani_set_spur_immunity_level(struct ath5k_hw *ah, int level) | 109 | ath5k_ani_set_spur_immunity_level(struct ath5k_hw *ah, int level) |
@@ -117,10 +124,9 @@ ath5k_ani_set_spur_immunity_level(struct ath5k_hw *ah, int level) | |||
117 | ATH5K_DBG_UNLIMIT(ah, ATH5K_DEBUG_ANI, "new level %d", level); | 124 | ATH5K_DBG_UNLIMIT(ah, ATH5K_DEBUG_ANI, "new level %d", level); |
118 | } | 125 | } |
119 | 126 | ||
120 | |||
121 | /** | 127 | /** |
122 | * ath5k_ani_set_firstep_level() - Set "firstep" level | 128 | * ath5k_ani_set_firstep_level() - Set "firstep" level |
123 | * | 129 | * @ah: The &struct ath5k_hw |
124 | * @level: level between 0 and @ATH5K_ANI_MAX_FIRSTEP_LVL | 130 | * @level: level between 0 and @ATH5K_ANI_MAX_FIRSTEP_LVL |
125 | */ | 131 | */ |
126 | void | 132 | void |
@@ -140,11 +146,9 @@ ath5k_ani_set_firstep_level(struct ath5k_hw *ah, int level) | |||
140 | ATH5K_DBG_UNLIMIT(ah, ATH5K_DEBUG_ANI, "new level %d", level); | 146 | ATH5K_DBG_UNLIMIT(ah, ATH5K_DEBUG_ANI, "new level %d", level); |
141 | } | 147 | } |
142 | 148 | ||
143 | |||
144 | /** | 149 | /** |
145 | * ath5k_ani_set_ofdm_weak_signal_detection() - Control OFDM weak signal | 150 | * ath5k_ani_set_ofdm_weak_signal_detection() - Set OFDM weak signal detection |
146 | * detection | 151 | * @ah: The &struct ath5k_hw |
147 | * | ||
148 | * @on: turn on or off | 152 | * @on: turn on or off |
149 | */ | 153 | */ |
150 | void | 154 | void |
@@ -182,10 +186,9 @@ ath5k_ani_set_ofdm_weak_signal_detection(struct ath5k_hw *ah, bool on) | |||
182 | on ? "on" : "off"); | 186 | on ? "on" : "off"); |
183 | } | 187 | } |
184 | 188 | ||
185 | |||
186 | /** | 189 | /** |
187 | * ath5k_ani_set_cck_weak_signal_detection() - control CCK weak signal detection | 190 | * ath5k_ani_set_cck_weak_signal_detection() - Set CCK weak signal detection |
188 | * | 191 | * @ah: The &struct ath5k_hw |
189 | * @on: turn on or off | 192 | * @on: turn on or off |
190 | */ | 193 | */ |
191 | void | 194 | void |
@@ -200,13 +203,16 @@ ath5k_ani_set_cck_weak_signal_detection(struct ath5k_hw *ah, bool on) | |||
200 | } | 203 | } |
201 | 204 | ||
202 | 205 | ||
203 | /*** ANI algorithm ***/ | 206 | /***************\ |
207 | * ANI algorithm * | ||
208 | \***************/ | ||
204 | 209 | ||
205 | /** | 210 | /** |
206 | * ath5k_ani_raise_immunity() - Increase noise immunity | 211 | * ath5k_ani_raise_immunity() - Increase noise immunity |
207 | * | 212 | * @ah: The &struct ath5k_hw |
213 | * @as: The &struct ath5k_ani_state | ||
208 | * @ofdm_trigger: If this is true we are called because of too many OFDM errors, | 214 | * @ofdm_trigger: If this is true we are called because of too many OFDM errors, |
209 | * the algorithm will tune more parameters then. | 215 | * the algorithm will tune more parameters then. |
210 | * | 216 | * |
211 | * Try to raise noise immunity (=decrease sensitivity) in several steps | 217 | * Try to raise noise immunity (=decrease sensitivity) in several steps |
212 | * depending on the average RSSI of the beacons we received. | 218 | * depending on the average RSSI of the beacons we received. |
@@ -290,9 +296,10 @@ ath5k_ani_raise_immunity(struct ath5k_hw *ah, struct ath5k_ani_state *as, | |||
290 | */ | 296 | */ |
291 | } | 297 | } |
292 | 298 | ||
293 | |||
294 | /** | 299 | /** |
295 | * ath5k_ani_lower_immunity() - Decrease noise immunity | 300 | * ath5k_ani_lower_immunity() - Decrease noise immunity |
301 | * @ah: The &struct ath5k_hw | ||
302 | * @as: The &struct ath5k_ani_state | ||
296 | * | 303 | * |
297 | * Try to lower noise immunity (=increase sensitivity) in several steps | 304 | * Try to lower noise immunity (=increase sensitivity) in several steps |
298 | * depending on the average RSSI of the beacons we received. | 305 | * depending on the average RSSI of the beacons we received. |
@@ -352,9 +359,10 @@ ath5k_ani_lower_immunity(struct ath5k_hw *ah, struct ath5k_ani_state *as) | |||
352 | } | 359 | } |
353 | } | 360 | } |
354 | 361 | ||
355 | |||
356 | /** | 362 | /** |
357 | * ath5k_hw_ani_get_listen_time() - Update counters and return listening time | 363 | * ath5k_hw_ani_get_listen_time() - Update counters and return listening time |
364 | * @ah: The &struct ath5k_hw | ||
365 | * @as: The &struct ath5k_ani_state | ||
358 | * | 366 | * |
359 | * Return an approximation of the time spent "listening" in milliseconds (ms) | 367 | * Return an approximation of the time spent "listening" in milliseconds (ms) |
360 | * since the last call of this function. | 368 | * since the last call of this function. |
@@ -379,9 +387,10 @@ ath5k_hw_ani_get_listen_time(struct ath5k_hw *ah, struct ath5k_ani_state *as) | |||
379 | return listen; | 387 | return listen; |
380 | } | 388 | } |
381 | 389 | ||
382 | |||
383 | /** | 390 | /** |
384 | * ath5k_ani_save_and_clear_phy_errors() - Clear and save PHY error counters | 391 | * ath5k_ani_save_and_clear_phy_errors() - Clear and save PHY error counters |
392 | * @ah: The &struct ath5k_hw | ||
393 | * @as: The &struct ath5k_ani_state | ||
385 | * | 394 | * |
386 | * Clear the PHY error counters as soon as possible, since this might be called | 395 | * Clear the PHY error counters as soon as possible, since this might be called |
387 | * from a MIB interrupt and we want to make sure we don't get interrupted again. | 396 | * from a MIB interrupt and we want to make sure we don't get interrupted again. |
@@ -429,14 +438,14 @@ ath5k_ani_save_and_clear_phy_errors(struct ath5k_hw *ah, | |||
429 | return 1; | 438 | return 1; |
430 | } | 439 | } |
431 | 440 | ||
432 | |||
433 | /** | 441 | /** |
434 | * ath5k_ani_period_restart() - Restart ANI period | 442 | * ath5k_ani_period_restart() - Restart ANI period |
443 | * @as: The &struct ath5k_ani_state | ||
435 | * | 444 | * |
436 | * Just reset counters, so they are clear for the next "ani period". | 445 | * Just reset counters, so they are clear for the next "ani period". |
437 | */ | 446 | */ |
438 | static void | 447 | static void |
439 | ath5k_ani_period_restart(struct ath5k_hw *ah, struct ath5k_ani_state *as) | 448 | ath5k_ani_period_restart(struct ath5k_ani_state *as) |
440 | { | 449 | { |
441 | /* keep last values for debugging */ | 450 | /* keep last values for debugging */ |
442 | as->last_ofdm_errors = as->ofdm_errors; | 451 | as->last_ofdm_errors = as->ofdm_errors; |
@@ -448,9 +457,9 @@ ath5k_ani_period_restart(struct ath5k_hw *ah, struct ath5k_ani_state *as) | |||
448 | as->listen_time = 0; | 457 | as->listen_time = 0; |
449 | } | 458 | } |
450 | 459 | ||
451 | |||
452 | /** | 460 | /** |
453 | * ath5k_ani_calibration() - The main ANI calibration function | 461 | * ath5k_ani_calibration() - The main ANI calibration function |
462 | * @ah: The &struct ath5k_hw | ||
454 | * | 463 | * |
455 | * We count OFDM and CCK errors relative to the time where we did not send or | 464 | * We count OFDM and CCK errors relative to the time where we did not send or |
456 | * receive ("listen" time) and raise or lower immunity accordingly. | 465 | * receive ("listen" time) and raise or lower immunity accordingly. |
@@ -492,7 +501,7 @@ ath5k_ani_calibration(struct ath5k_hw *ah) | |||
492 | /* too many PHY errors - we have to raise immunity */ | 501 | /* too many PHY errors - we have to raise immunity */ |
493 | bool ofdm_flag = as->ofdm_errors > ofdm_high ? true : false; | 502 | bool ofdm_flag = as->ofdm_errors > ofdm_high ? true : false; |
494 | ath5k_ani_raise_immunity(ah, as, ofdm_flag); | 503 | ath5k_ani_raise_immunity(ah, as, ofdm_flag); |
495 | ath5k_ani_period_restart(ah, as); | 504 | ath5k_ani_period_restart(as); |
496 | 505 | ||
497 | } else if (as->listen_time > 5 * ATH5K_ANI_LISTEN_PERIOD) { | 506 | } else if (as->listen_time > 5 * ATH5K_ANI_LISTEN_PERIOD) { |
498 | /* If more than 5 (TODO: why 5?) periods have passed and we got | 507 | /* If more than 5 (TODO: why 5?) periods have passed and we got |
@@ -504,15 +513,18 @@ ath5k_ani_calibration(struct ath5k_hw *ah) | |||
504 | if (as->ofdm_errors <= ofdm_low && as->cck_errors <= cck_low) | 513 | if (as->ofdm_errors <= ofdm_low && as->cck_errors <= cck_low) |
505 | ath5k_ani_lower_immunity(ah, as); | 514 | ath5k_ani_lower_immunity(ah, as); |
506 | 515 | ||
507 | ath5k_ani_period_restart(ah, as); | 516 | ath5k_ani_period_restart(as); |
508 | } | 517 | } |
509 | } | 518 | } |
510 | 519 | ||
511 | 520 | ||
512 | /*** INTERRUPT HANDLER ***/ | 521 | /*******************\ |
522 | * Interrupt handler * | ||
523 | \*******************/ | ||
513 | 524 | ||
514 | /** | 525 | /** |
515 | * ath5k_ani_mib_intr() - Interrupt handler for ANI MIB counters | 526 | * ath5k_ani_mib_intr() - Interrupt handler for ANI MIB counters |
527 | * @ah: The &struct ath5k_hw | ||
516 | * | 528 | * |
517 | * Just read & reset the registers quickly, so they don't generate more | 529 | * Just read & reset the registers quickly, so they don't generate more |
518 | * interrupts, save the counters and schedule the tasklet to decide whether | 530 | * interrupts, save the counters and schedule the tasklet to decide whether |
@@ -549,9 +561,11 @@ ath5k_ani_mib_intr(struct ath5k_hw *ah) | |||
549 | tasklet_schedule(&ah->ani_tasklet); | 561 | tasklet_schedule(&ah->ani_tasklet); |
550 | } | 562 | } |
551 | 563 | ||
552 | |||
553 | /** | 564 | /** |
554 | * ath5k_ani_phy_error_report() - Used by older HW to report PHY errors | 565 | * ath5k_ani_phy_error_report - Used by older HW to report PHY errors |
566 | * | ||
567 | * @ah: The &struct ath5k_hw | ||
568 | * @phyerr: One of enum ath5k_phy_error_code | ||
555 | * | 569 | * |
556 | * This is used by hardware without PHY error counters to report PHY errors | 570 | * This is used by hardware without PHY error counters to report PHY errors |
557 | * on a frame-by-frame basis, instead of the interrupt. | 571 | * on a frame-by-frame basis, instead of the interrupt. |
@@ -574,10 +588,13 @@ ath5k_ani_phy_error_report(struct ath5k_hw *ah, | |||
574 | } | 588 | } |
575 | 589 | ||
576 | 590 | ||
577 | /*** INIT ***/ | 591 | /****************\ |
592 | * Initialization * | ||
593 | \****************/ | ||
578 | 594 | ||
579 | /** | 595 | /** |
580 | * ath5k_enable_phy_err_counters() - Enable PHY error counters | 596 | * ath5k_enable_phy_err_counters() - Enable PHY error counters |
597 | * @ah: The &struct ath5k_hw | ||
581 | * | 598 | * |
582 | * Enable PHY error counters for OFDM and CCK timing errors. | 599 | * Enable PHY error counters for OFDM and CCK timing errors. |
583 | */ | 600 | */ |
@@ -596,9 +613,9 @@ ath5k_enable_phy_err_counters(struct ath5k_hw *ah) | |||
596 | ath5k_hw_reg_write(ah, 0, AR5K_CCK_FIL_CNT); | 613 | ath5k_hw_reg_write(ah, 0, AR5K_CCK_FIL_CNT); |
597 | } | 614 | } |
598 | 615 | ||
599 | |||
600 | /** | 616 | /** |
601 | * ath5k_disable_phy_err_counters() - Disable PHY error counters | 617 | * ath5k_disable_phy_err_counters() - Disable PHY error counters |
618 | * @ah: The &struct ath5k_hw | ||
602 | * | 619 | * |
603 | * Disable PHY error counters for OFDM and CCK timing errors. | 620 | * Disable PHY error counters for OFDM and CCK timing errors. |
604 | */ | 621 | */ |
@@ -615,10 +632,10 @@ ath5k_disable_phy_err_counters(struct ath5k_hw *ah) | |||
615 | ath5k_hw_reg_write(ah, 0, AR5K_CCK_FIL_CNT); | 632 | ath5k_hw_reg_write(ah, 0, AR5K_CCK_FIL_CNT); |
616 | } | 633 | } |
617 | 634 | ||
618 | |||
619 | /** | 635 | /** |
620 | * ath5k_ani_init() - Initialize ANI | 636 | * ath5k_ani_init() - Initialize ANI |
621 | * @mode: Which mode to use (auto, manual high, manual low, off) | 637 | * @ah: The &struct ath5k_hw |
638 | * @mode: One of enum ath5k_ani_mode | ||
622 | * | 639 | * |
623 | * Initialize ANI according to mode. | 640 | * Initialize ANI according to mode. |
624 | */ | 641 | */ |
@@ -695,10 +712,18 @@ ath5k_ani_init(struct ath5k_hw *ah, enum ath5k_ani_mode mode) | |||
695 | } | 712 | } |
696 | 713 | ||
697 | 714 | ||
698 | /*** DEBUG ***/ | 715 | /**************\ |
716 | * Debug output * | ||
717 | \**************/ | ||
699 | 718 | ||
700 | #ifdef CONFIG_ATH5K_DEBUG | 719 | #ifdef CONFIG_ATH5K_DEBUG |
701 | 720 | ||
721 | /** | ||
722 | * ath5k_ani_print_counters() - Print ANI counters | ||
723 | * @ah: The &struct ath5k_hw | ||
724 | * | ||
725 | * Used for debugging ANI | ||
726 | */ | ||
702 | void | 727 | void |
703 | ath5k_ani_print_counters(struct ath5k_hw *ah) | 728 | ath5k_ani_print_counters(struct ath5k_hw *ah) |
704 | { | 729 | { |
diff --git a/drivers/net/wireless/ath/ath5k/ani.h b/drivers/net/wireless/ath/ath5k/ani.h index 7358b6c83c6c..21aa355460bb 100644 --- a/drivers/net/wireless/ath/ath5k/ani.h +++ b/drivers/net/wireless/ath/ath5k/ani.h | |||
@@ -40,13 +40,13 @@ enum ath5k_phy_error_code; | |||
40 | * enum ath5k_ani_mode - mode for ANI / noise sensitivity | 40 | * enum ath5k_ani_mode - mode for ANI / noise sensitivity |
41 | * | 41 | * |
42 | * @ATH5K_ANI_MODE_OFF: Turn ANI off. This can be useful to just stop the ANI | 42 | * @ATH5K_ANI_MODE_OFF: Turn ANI off. This can be useful to just stop the ANI |
43 | * algorithm after it has been on auto mode. | 43 | * algorithm after it has been on auto mode. |
44 | * ATH5K_ANI_MODE_MANUAL_LOW: Manually set all immunity parameters to low, | 44 | * @ATH5K_ANI_MODE_MANUAL_LOW: Manually set all immunity parameters to low, |
45 | * maximizing sensitivity. ANI will not run. | 45 | * maximizing sensitivity. ANI will not run. |
46 | * ATH5K_ANI_MODE_MANUAL_HIGH: Manually set all immunity parameters to high, | 46 | * @ATH5K_ANI_MODE_MANUAL_HIGH: Manually set all immunity parameters to high, |
47 | * minimizing sensitivity. ANI will not run. | 47 | * minimizing sensitivity. ANI will not run. |
48 | * ATH5K_ANI_MODE_AUTO: Automatically control immunity parameters based on the | 48 | * @ATH5K_ANI_MODE_AUTO: Automatically control immunity parameters based on the |
49 | * amount of OFDM and CCK frame errors (default). | 49 | * amount of OFDM and CCK frame errors (default). |
50 | */ | 50 | */ |
51 | enum ath5k_ani_mode { | 51 | enum ath5k_ani_mode { |
52 | ATH5K_ANI_MODE_OFF = 0, | 52 | ATH5K_ANI_MODE_OFF = 0, |
@@ -58,8 +58,22 @@ enum ath5k_ani_mode { | |||
58 | 58 | ||
59 | /** | 59 | /** |
60 | * struct ath5k_ani_state - ANI state and associated counters | 60 | * struct ath5k_ani_state - ANI state and associated counters |
61 | * | 61 | * @ani_mode: One of enum ath5k_ani_mode |
62 | * @max_spur_level: the maximum spur level is chip dependent | 62 | * @noise_imm_level: Noise immunity level |
63 | * @spur_level: Spur immunity level | ||
64 | * @firstep_level: FIRstep level | ||
65 | * @ofdm_weak_sig: OFDM weak signal detection state (on/off) | ||
66 | * @cck_weak_sig: CCK weak signal detection state (on/off) | ||
67 | * @max_spur_level: Max spur immunity level (chip specific) | ||
68 | * @listen_time: Listen time | ||
69 | * @ofdm_errors: OFDM timing error count | ||
70 | * @cck_errors: CCK timing error count | ||
71 | * @last_cc: The &struct ath_cycle_counters (for stats) | ||
72 | * @last_listen: Listen time from previous run (for stats) | ||
73 | * @last_ofdm_errors: OFDM timing error count from previous run (for tats) | ||
74 | * @last_cck_errors: CCK timing error count from previous run (for stats) | ||
75 | * @sum_ofdm_errors: Sum of OFDM timing errors (for stats) | ||
76 | * @sum_cck_errors: Sum of all CCK timing errors (for stats) | ||
63 | */ | 77 | */ |
64 | struct ath5k_ani_state { | 78 | struct ath5k_ani_state { |
65 | enum ath5k_ani_mode ani_mode; | 79 | enum ath5k_ani_mode ani_mode; |
diff --git a/drivers/net/wireless/ath/ath5k/ath5k.h b/drivers/net/wireless/ath/ath5k/ath5k.h index fecbcd9a4259..e564e585b221 100644 --- a/drivers/net/wireless/ath/ath5k/ath5k.h +++ b/drivers/net/wireless/ath/ath5k/ath5k.h | |||
@@ -187,10 +187,9 @@ | |||
187 | #define AR5K_TUNE_MAX_TXPOWER 63 | 187 | #define AR5K_TUNE_MAX_TXPOWER 63 |
188 | #define AR5K_TUNE_DEFAULT_TXPOWER 25 | 188 | #define AR5K_TUNE_DEFAULT_TXPOWER 25 |
189 | #define AR5K_TUNE_TPC_TXPOWER false | 189 | #define AR5K_TUNE_TPC_TXPOWER false |
190 | #define ATH5K_TUNE_CALIBRATION_INTERVAL_FULL 10000 /* 10 sec */ | 190 | #define ATH5K_TUNE_CALIBRATION_INTERVAL_FULL 60000 /* 60 sec */ |
191 | #define ATH5K_TUNE_CALIBRATION_INTERVAL_SHORT 10000 /* 10 sec */ | ||
191 | #define ATH5K_TUNE_CALIBRATION_INTERVAL_ANI 1000 /* 1 sec */ | 192 | #define ATH5K_TUNE_CALIBRATION_INTERVAL_ANI 1000 /* 1 sec */ |
192 | #define ATH5K_TUNE_CALIBRATION_INTERVAL_NF 60000 /* 60 sec */ | ||
193 | |||
194 | #define ATH5K_TX_COMPLETE_POLL_INT 3000 /* 3 sec */ | 193 | #define ATH5K_TX_COMPLETE_POLL_INT 3000 /* 3 sec */ |
195 | 194 | ||
196 | #define AR5K_INIT_CARR_SENSE_EN 1 | 195 | #define AR5K_INIT_CARR_SENSE_EN 1 |
@@ -262,16 +261,34 @@ | |||
262 | #define AR5K_AGC_SETTLING_TURBO 37 | 261 | #define AR5K_AGC_SETTLING_TURBO 37 |
263 | 262 | ||
264 | 263 | ||
265 | /* GENERIC CHIPSET DEFINITIONS */ | ||
266 | 264 | ||
267 | /* MAC Chips */ | 265 | /*****************************\ |
266 | * GENERIC CHIPSET DEFINITIONS * | ||
267 | \*****************************/ | ||
268 | |||
269 | /** | ||
270 | * enum ath5k_version - MAC Chips | ||
271 | * @AR5K_AR5210: AR5210 (Crete) | ||
272 | * @AR5K_AR5211: AR5211 (Oahu/Maui) | ||
273 | * @AR5K_AR5212: AR5212 (Venice) and newer | ||
274 | */ | ||
268 | enum ath5k_version { | 275 | enum ath5k_version { |
269 | AR5K_AR5210 = 0, | 276 | AR5K_AR5210 = 0, |
270 | AR5K_AR5211 = 1, | 277 | AR5K_AR5211 = 1, |
271 | AR5K_AR5212 = 2, | 278 | AR5K_AR5212 = 2, |
272 | }; | 279 | }; |
273 | 280 | ||
274 | /* PHY Chips */ | 281 | /** |
282 | * enum ath5k_radio - PHY Chips | ||
283 | * @AR5K_RF5110: RF5110 (Fez) | ||
284 | * @AR5K_RF5111: RF5111 (Sombrero) | ||
285 | * @AR5K_RF5112: RF2112/5112(A) (Derby/Derby2) | ||
286 | * @AR5K_RF2413: RF2413/2414 (Griffin/Griffin-Lite) | ||
287 | * @AR5K_RF5413: RF5413/5414/5424 (Eagle/Condor) | ||
288 | * @AR5K_RF2316: RF2315/2316 (Cobra SoC) | ||
289 | * @AR5K_RF2317: RF2317 (Spider SoC) | ||
290 | * @AR5K_RF2425: RF2425/2417 (Swan/Nalla) | ||
291 | */ | ||
275 | enum ath5k_radio { | 292 | enum ath5k_radio { |
276 | AR5K_RF5110 = 0, | 293 | AR5K_RF5110 = 0, |
277 | AR5K_RF5111 = 1, | 294 | AR5K_RF5111 = 1, |
@@ -303,11 +320,11 @@ enum ath5k_radio { | |||
303 | #define AR5K_SREV_AR5213A 0x59 /* Hainan */ | 320 | #define AR5K_SREV_AR5213A 0x59 /* Hainan */ |
304 | #define AR5K_SREV_AR2413 0x78 /* Griffin lite */ | 321 | #define AR5K_SREV_AR2413 0x78 /* Griffin lite */ |
305 | #define AR5K_SREV_AR2414 0x70 /* Griffin */ | 322 | #define AR5K_SREV_AR2414 0x70 /* Griffin */ |
306 | #define AR5K_SREV_AR2315_R6 0x86 /* AP51-Light */ | 323 | #define AR5K_SREV_AR2315_R6 0x86 /* AP51-Light */ |
307 | #define AR5K_SREV_AR2315_R7 0x87 /* AP51-Full */ | 324 | #define AR5K_SREV_AR2315_R7 0x87 /* AP51-Full */ |
308 | #define AR5K_SREV_AR5424 0x90 /* Condor */ | 325 | #define AR5K_SREV_AR5424 0x90 /* Condor */ |
309 | #define AR5K_SREV_AR2317_R1 0x90 /* AP61-Light */ | 326 | #define AR5K_SREV_AR2317_R1 0x90 /* AP61-Light */ |
310 | #define AR5K_SREV_AR2317_R2 0x91 /* AP61-Full */ | 327 | #define AR5K_SREV_AR2317_R2 0x91 /* AP61-Full */ |
311 | #define AR5K_SREV_AR5413 0xa4 /* Eagle lite */ | 328 | #define AR5K_SREV_AR5413 0xa4 /* Eagle lite */ |
312 | #define AR5K_SREV_AR5414 0xa0 /* Eagle */ | 329 | #define AR5K_SREV_AR5414 0xa0 /* Eagle */ |
313 | #define AR5K_SREV_AR2415 0xb0 /* Talon */ | 330 | #define AR5K_SREV_AR2415 0xb0 /* Talon */ |
@@ -344,32 +361,40 @@ enum ath5k_radio { | |||
344 | 361 | ||
345 | /* TODO add support to mac80211 for vendor-specific rates and modes */ | 362 | /* TODO add support to mac80211 for vendor-specific rates and modes */ |
346 | 363 | ||
347 | /* | 364 | /** |
365 | * DOC: Atheros XR | ||
366 | * | ||
348 | * Some of this information is based on Documentation from: | 367 | * Some of this information is based on Documentation from: |
349 | * | 368 | * |
350 | * http://madwifi-project.org/wiki/ChipsetFeatures/SuperAG | 369 | * http://madwifi-project.org/wiki/ChipsetFeatures/SuperAG |
351 | * | 370 | * |
352 | * Modulation for Atheros' eXtended Range - range enhancing extension that is | 371 | * Atheros' eXtended Range - range enhancing extension is a modulation scheme |
353 | * supposed to double the distance an Atheros client device can keep a | 372 | * that is supposed to double the link distance between an Atheros XR-enabled |
354 | * connection with an Atheros access point. This is achieved by increasing | 373 | * client device with an Atheros XR-enabled access point. This is achieved |
355 | * the receiver sensitivity up to, -105dBm, which is about 20dB above what | 374 | * by increasing the receiver sensitivity up to, -105dBm, which is about 20dB |
356 | * the 802.11 specifications demand. In addition, new (proprietary) data rates | 375 | * above what the 802.11 specifications demand. In addition, new (proprietary) |
357 | * are introduced: 3, 2, 1, 0.5 and 0.25 MBit/s. | 376 | * data rates are introduced: 3, 2, 1, 0.5 and 0.25 MBit/s. |
358 | * | 377 | * |
359 | * Please note that can you either use XR or TURBO but you cannot use both, | 378 | * Please note that can you either use XR or TURBO but you cannot use both, |
360 | * they are exclusive. | 379 | * they are exclusive. |
361 | * | 380 | * |
381 | * Also note that we do not plan to support XR mode at least for now. You can | ||
382 | * get a mode similar to XR by using 5MHz bwmode. | ||
362 | */ | 383 | */ |
363 | #define MODULATION_XR 0x00000200 | 384 | |
364 | /* | 385 | |
365 | * Modulation for Atheros' Turbo G and Turbo A, its supposed to provide a | 386 | /** |
366 | * throughput transmission speed up to 40Mbit/s-60Mbit/s at a 108Mbit/s | 387 | * DOC: Atheros SuperAG |
367 | * signaling rate achieved through the bonding of two 54Mbit/s 802.11g | 388 | * |
368 | * channels. To use this feature your Access Point must also support it. | 389 | * In addition to XR we have another modulation scheme called TURBO mode |
390 | * that is supposed to provide a throughput transmission speed up to 40Mbit/s | ||
391 | * -60Mbit/s at a 108Mbit/s signaling rate achieved through the bonding of two | ||
392 | * 54Mbit/s 802.11g channels. To use this feature both ends must support it. | ||
369 | * There is also a distinction between "static" and "dynamic" turbo modes: | 393 | * There is also a distinction between "static" and "dynamic" turbo modes: |
370 | * | 394 | * |
371 | * - Static: is the dumb version: devices set to this mode stick to it until | 395 | * - Static: is the dumb version: devices set to this mode stick to it until |
372 | * the mode is turned off. | 396 | * the mode is turned off. |
397 | * | ||
373 | * - Dynamic: is the intelligent version, the network decides itself if it | 398 | * - Dynamic: is the intelligent version, the network decides itself if it |
374 | * is ok to use turbo. As soon as traffic is detected on adjacent channels | 399 | * is ok to use turbo. As soon as traffic is detected on adjacent channels |
375 | * (which would get used in turbo mode), or when a non-turbo station joins | 400 | * (which would get used in turbo mode), or when a non-turbo station joins |
@@ -383,24 +408,39 @@ enum ath5k_radio { | |||
383 | * | 408 | * |
384 | * http://www.pcworld.com/article/id,113428-page,1/article.html | 409 | * http://www.pcworld.com/article/id,113428-page,1/article.html |
385 | * | 410 | * |
386 | * The channel bonding seems to be driver specific though. In addition to | 411 | * The channel bonding seems to be driver specific though. |
387 | * deciding what channels will be used, these "Turbo" modes are accomplished | 412 | * |
388 | * by also enabling the following features: | 413 | * In addition to TURBO modes we also have the following features for even |
414 | * greater speed-up: | ||
389 | * | 415 | * |
390 | * - Bursting: allows multiple frames to be sent at once, rather than pausing | 416 | * - Bursting: allows multiple frames to be sent at once, rather than pausing |
391 | * after each frame. Bursting is a standards-compliant feature that can be | 417 | * after each frame. Bursting is a standards-compliant feature that can be |
392 | * used with any Access Point. | 418 | * used with any Access Point. |
419 | * | ||
393 | * - Fast frames: increases the amount of information that can be sent per | 420 | * - Fast frames: increases the amount of information that can be sent per |
394 | * frame, also resulting in a reduction of transmission overhead. It is a | 421 | * frame, also resulting in a reduction of transmission overhead. It is a |
395 | * proprietary feature that needs to be supported by the Access Point. | 422 | * proprietary feature that needs to be supported by the Access Point. |
423 | * | ||
396 | * - Compression: data frames are compressed in real time using a Lempel Ziv | 424 | * - Compression: data frames are compressed in real time using a Lempel Ziv |
397 | * algorithm. This is done transparently. Once this feature is enabled, | 425 | * algorithm. This is done transparently. Once this feature is enabled, |
398 | * compression and decompression takes place inside the chipset, without | 426 | * compression and decompression takes place inside the chipset, without |
399 | * putting additional load on the host CPU. | 427 | * putting additional load on the host CPU. |
400 | * | 428 | * |
429 | * As with XR we also don't plan to support SuperAG features for now. You can | ||
430 | * get a mode similar to TURBO by using 40MHz bwmode. | ||
401 | */ | 431 | */ |
402 | #define MODULATION_TURBO 0x00000080 | ||
403 | 432 | ||
433 | |||
434 | /** | ||
435 | * enum ath5k_driver_mode - PHY operation mode | ||
436 | * @AR5K_MODE_11A: 802.11a | ||
437 | * @AR5K_MODE_11B: 802.11b | ||
438 | * @AR5K_MODE_11G: 801.11g | ||
439 | * @AR5K_MODE_MAX: Used for boundary checks | ||
440 | * | ||
441 | * Do not change the order here, we use these as | ||
442 | * array indices and it also maps EEPROM structures. | ||
443 | */ | ||
404 | enum ath5k_driver_mode { | 444 | enum ath5k_driver_mode { |
405 | AR5K_MODE_11A = 0, | 445 | AR5K_MODE_11A = 0, |
406 | AR5K_MODE_11B = 1, | 446 | AR5K_MODE_11B = 1, |
@@ -408,30 +448,64 @@ enum ath5k_driver_mode { | |||
408 | AR5K_MODE_MAX = 3 | 448 | AR5K_MODE_MAX = 3 |
409 | }; | 449 | }; |
410 | 450 | ||
451 | /** | ||
452 | * enum ath5k_ant_mode - Antenna operation mode | ||
453 | * @AR5K_ANTMODE_DEFAULT: Default antenna setup | ||
454 | * @AR5K_ANTMODE_FIXED_A: Only antenna A is present | ||
455 | * @AR5K_ANTMODE_FIXED_B: Only antenna B is present | ||
456 | * @AR5K_ANTMODE_SINGLE_AP: STA locked on a single ap | ||
457 | * @AR5K_ANTMODE_SECTOR_AP: AP with tx antenna set on tx desc | ||
458 | * @AR5K_ANTMODE_SECTOR_STA: STA with tx antenna set on tx desc | ||
459 | * @AR5K_ANTMODE_DEBUG: Debug mode -A -> Rx, B-> Tx- | ||
460 | * @AR5K_ANTMODE_MAX: Used for boundary checks | ||
461 | * | ||
462 | * For more infos on antenna control check out phy.c | ||
463 | */ | ||
411 | enum ath5k_ant_mode { | 464 | enum ath5k_ant_mode { |
412 | AR5K_ANTMODE_DEFAULT = 0, /* default antenna setup */ | 465 | AR5K_ANTMODE_DEFAULT = 0, |
413 | AR5K_ANTMODE_FIXED_A = 1, /* only antenna A is present */ | 466 | AR5K_ANTMODE_FIXED_A = 1, |
414 | AR5K_ANTMODE_FIXED_B = 2, /* only antenna B is present */ | 467 | AR5K_ANTMODE_FIXED_B = 2, |
415 | AR5K_ANTMODE_SINGLE_AP = 3, /* sta locked on a single ap */ | 468 | AR5K_ANTMODE_SINGLE_AP = 3, |
416 | AR5K_ANTMODE_SECTOR_AP = 4, /* AP with tx antenna set on tx desc */ | 469 | AR5K_ANTMODE_SECTOR_AP = 4, |
417 | AR5K_ANTMODE_SECTOR_STA = 5, /* STA with tx antenna set on tx desc */ | 470 | AR5K_ANTMODE_SECTOR_STA = 5, |
418 | AR5K_ANTMODE_DEBUG = 6, /* Debug mode -A -> Rx, B-> Tx- */ | 471 | AR5K_ANTMODE_DEBUG = 6, |
419 | AR5K_ANTMODE_MAX, | 472 | AR5K_ANTMODE_MAX, |
420 | }; | 473 | }; |
421 | 474 | ||
475 | /** | ||
476 | * enum ath5k_bw_mode - Bandwidth operation mode | ||
477 | * @AR5K_BWMODE_DEFAULT: 20MHz, default operation | ||
478 | * @AR5K_BWMODE_5MHZ: Quarter rate | ||
479 | * @AR5K_BWMODE_10MHZ: Half rate | ||
480 | * @AR5K_BWMODE_40MHZ: Turbo | ||
481 | */ | ||
422 | enum ath5k_bw_mode { | 482 | enum ath5k_bw_mode { |
423 | AR5K_BWMODE_DEFAULT = 0, /* 20MHz, default operation */ | 483 | AR5K_BWMODE_DEFAULT = 0, |
424 | AR5K_BWMODE_5MHZ = 1, /* Quarter rate */ | 484 | AR5K_BWMODE_5MHZ = 1, |
425 | AR5K_BWMODE_10MHZ = 2, /* Half rate */ | 485 | AR5K_BWMODE_10MHZ = 2, |
426 | AR5K_BWMODE_40MHZ = 3 /* Turbo */ | 486 | AR5K_BWMODE_40MHZ = 3 |
427 | }; | 487 | }; |
428 | 488 | ||
489 | |||
490 | |||
429 | /****************\ | 491 | /****************\ |
430 | TX DEFINITIONS | 492 | TX DEFINITIONS |
431 | \****************/ | 493 | \****************/ |
432 | 494 | ||
433 | /* | 495 | /** |
434 | * TX Status descriptor | 496 | * struct ath5k_tx_status - TX Status descriptor |
497 | * @ts_seqnum: Sequence number | ||
498 | * @ts_tstamp: Timestamp | ||
499 | * @ts_status: Status code | ||
500 | * @ts_final_idx: Final transmission series index | ||
501 | * @ts_final_retry: Final retry count | ||
502 | * @ts_rssi: RSSI for received ACK | ||
503 | * @ts_shortretry: Short retry count | ||
504 | * @ts_virtcol: Virtual collision count | ||
505 | * @ts_antenna: Antenna used | ||
506 | * | ||
507 | * TX status descriptor gets filled by the hw | ||
508 | * on each transmission attempt. | ||
435 | */ | 509 | */ |
436 | struct ath5k_tx_status { | 510 | struct ath5k_tx_status { |
437 | u16 ts_seqnum; | 511 | u16 ts_seqnum; |
@@ -454,7 +528,6 @@ struct ath5k_tx_status { | |||
454 | * enum ath5k_tx_queue - Queue types used to classify tx queues. | 528 | * enum ath5k_tx_queue - Queue types used to classify tx queues. |
455 | * @AR5K_TX_QUEUE_INACTIVE: q is unused -- see ath5k_hw_release_tx_queue | 529 | * @AR5K_TX_QUEUE_INACTIVE: q is unused -- see ath5k_hw_release_tx_queue |
456 | * @AR5K_TX_QUEUE_DATA: A normal data queue | 530 | * @AR5K_TX_QUEUE_DATA: A normal data queue |
457 | * @AR5K_TX_QUEUE_XR_DATA: An XR-data queue | ||
458 | * @AR5K_TX_QUEUE_BEACON: The beacon queue | 531 | * @AR5K_TX_QUEUE_BEACON: The beacon queue |
459 | * @AR5K_TX_QUEUE_CAB: The after-beacon queue | 532 | * @AR5K_TX_QUEUE_CAB: The after-beacon queue |
460 | * @AR5K_TX_QUEUE_UAPSD: Unscheduled Automatic Power Save Delivery queue | 533 | * @AR5K_TX_QUEUE_UAPSD: Unscheduled Automatic Power Save Delivery queue |
@@ -462,7 +535,6 @@ struct ath5k_tx_status { | |||
462 | enum ath5k_tx_queue { | 535 | enum ath5k_tx_queue { |
463 | AR5K_TX_QUEUE_INACTIVE = 0, | 536 | AR5K_TX_QUEUE_INACTIVE = 0, |
464 | AR5K_TX_QUEUE_DATA, | 537 | AR5K_TX_QUEUE_DATA, |
465 | AR5K_TX_QUEUE_XR_DATA, | ||
466 | AR5K_TX_QUEUE_BEACON, | 538 | AR5K_TX_QUEUE_BEACON, |
467 | AR5K_TX_QUEUE_CAB, | 539 | AR5K_TX_QUEUE_CAB, |
468 | AR5K_TX_QUEUE_UAPSD, | 540 | AR5K_TX_QUEUE_UAPSD, |
@@ -471,36 +543,46 @@ enum ath5k_tx_queue { | |||
471 | #define AR5K_NUM_TX_QUEUES 10 | 543 | #define AR5K_NUM_TX_QUEUES 10 |
472 | #define AR5K_NUM_TX_QUEUES_NOQCU 2 | 544 | #define AR5K_NUM_TX_QUEUES_NOQCU 2 |
473 | 545 | ||
474 | /* | 546 | /** |
475 | * Queue syb-types to classify normal data queues. | 547 | * enum ath5k_tx_queue_subtype - Queue sub-types to classify normal data queues |
548 | * @AR5K_WME_AC_BK: Background traffic | ||
549 | * @AR5K_WME_AC_BE: Best-effort (normal) traffic | ||
550 | * @AR5K_WME_AC_VI: Video traffic | ||
551 | * @AR5K_WME_AC_VO: Voice traffic | ||
552 | * | ||
476 | * These are the 4 Access Categories as defined in | 553 | * These are the 4 Access Categories as defined in |
477 | * WME spec. 0 is the lowest priority and 4 is the | 554 | * WME spec. 0 is the lowest priority and 4 is the |
478 | * highest. Normal data that hasn't been classified | 555 | * highest. Normal data that hasn't been classified |
479 | * goes to the Best Effort AC. | 556 | * goes to the Best Effort AC. |
480 | */ | 557 | */ |
481 | enum ath5k_tx_queue_subtype { | 558 | enum ath5k_tx_queue_subtype { |
482 | AR5K_WME_AC_BK = 0, /*Background traffic*/ | 559 | AR5K_WME_AC_BK = 0, |
483 | AR5K_WME_AC_BE, /*Best-effort (normal) traffic*/ | 560 | AR5K_WME_AC_BE, |
484 | AR5K_WME_AC_VI, /*Video traffic*/ | 561 | AR5K_WME_AC_VI, |
485 | AR5K_WME_AC_VO, /*Voice traffic*/ | 562 | AR5K_WME_AC_VO, |
486 | }; | 563 | }; |
487 | 564 | ||
488 | /* | 565 | /** |
489 | * Queue ID numbers as returned by the hw functions, each number | 566 | * enum ath5k_tx_queue_id - Queue ID numbers as returned by the hw functions |
490 | * represents a hw queue. If hw does not support hw queues | 567 | * @AR5K_TX_QUEUE_ID_NOQCU_DATA: Data queue on AR5210 (no QCU available) |
491 | * (eg 5210) all data goes in one queue. These match | 568 | * @AR5K_TX_QUEUE_ID_NOQCU_BEACON: Beacon queue on AR5210 (no QCU available) |
492 | * d80211 definitions (net80211/MadWiFi don't use them). | 569 | * @AR5K_TX_QUEUE_ID_DATA_MIN: Data queue min index |
570 | * @AR5K_TX_QUEUE_ID_DATA_MAX: Data queue max index | ||
571 | * @AR5K_TX_QUEUE_ID_CAB: Content after beacon queue | ||
572 | * @AR5K_TX_QUEUE_ID_BEACON: Beacon queue | ||
573 | * @AR5K_TX_QUEUE_ID_UAPSD: Urgent Automatic Power Save Delivery, | ||
574 | * | ||
575 | * Each number represents a hw queue. If hw does not support hw queues | ||
576 | * (eg 5210) all data goes in one queue. | ||
493 | */ | 577 | */ |
494 | enum ath5k_tx_queue_id { | 578 | enum ath5k_tx_queue_id { |
495 | AR5K_TX_QUEUE_ID_NOQCU_DATA = 0, | 579 | AR5K_TX_QUEUE_ID_NOQCU_DATA = 0, |
496 | AR5K_TX_QUEUE_ID_NOQCU_BEACON = 1, | 580 | AR5K_TX_QUEUE_ID_NOQCU_BEACON = 1, |
497 | AR5K_TX_QUEUE_ID_DATA_MIN = 0, /*IEEE80211_TX_QUEUE_DATA0*/ | 581 | AR5K_TX_QUEUE_ID_DATA_MIN = 0, |
498 | AR5K_TX_QUEUE_ID_DATA_MAX = 3, /*IEEE80211_TX_QUEUE_DATA3*/ | 582 | AR5K_TX_QUEUE_ID_DATA_MAX = 3, |
499 | AR5K_TX_QUEUE_ID_DATA_SVP = 5, /*IEEE80211_TX_QUEUE_SVP - Spectralink Voice Protocol*/ | 583 | AR5K_TX_QUEUE_ID_UAPSD = 7, |
500 | AR5K_TX_QUEUE_ID_CAB = 6, /*IEEE80211_TX_QUEUE_AFTER_BEACON*/ | 584 | AR5K_TX_QUEUE_ID_CAB = 8, |
501 | AR5K_TX_QUEUE_ID_BEACON = 7, /*IEEE80211_TX_QUEUE_BEACON*/ | 585 | AR5K_TX_QUEUE_ID_BEACON = 9, |
502 | AR5K_TX_QUEUE_ID_UAPSD = 8, | ||
503 | AR5K_TX_QUEUE_ID_XR_DATA = 9, | ||
504 | }; | 586 | }; |
505 | 587 | ||
506 | /* | 588 | /* |
@@ -521,46 +603,70 @@ enum ath5k_tx_queue_id { | |||
521 | #define AR5K_TXQ_FLAG_POST_FR_BKOFF_DIS 0x1000 /* Disable backoff while bursting */ | 603 | #define AR5K_TXQ_FLAG_POST_FR_BKOFF_DIS 0x1000 /* Disable backoff while bursting */ |
522 | #define AR5K_TXQ_FLAG_COMPRESSION_ENABLE 0x2000 /* Enable hw compression -not implemented-*/ | 604 | #define AR5K_TXQ_FLAG_COMPRESSION_ENABLE 0x2000 /* Enable hw compression -not implemented-*/ |
523 | 605 | ||
524 | /* | 606 | /** |
525 | * Data transmit queue state. One of these exists for each | 607 | * struct ath5k_txq - Transmit queue state |
526 | * hardware transmit queue. Packets sent to us from above | 608 | * @qnum: Hardware q number |
527 | * are assigned to queues based on their priority. Not all | 609 | * @link: Link ptr in last TX desc |
528 | * devices support a complete set of hardware transmit queues. | 610 | * @q: Transmit queue (&struct list_head) |
529 | * For those devices the array sc_ac2q will map multiple | 611 | * @lock: Lock on q and link |
530 | * priorities to fewer hardware queues (typically all to one | 612 | * @setup: Is the queue configured |
531 | * hardware queue). | 613 | * @txq_len:Number of queued buffers |
614 | * @txq_max: Max allowed num of queued buffers | ||
615 | * @txq_poll_mark: Used to check if queue got stuck | ||
616 | * @txq_stuck: Queue stuck counter | ||
617 | * | ||
618 | * One of these exists for each hardware transmit queue. | ||
619 | * Packets sent to us from above are assigned to queues based | ||
620 | * on their priority. Not all devices support a complete set | ||
621 | * of hardware transmit queues. For those devices the array | ||
622 | * sc_ac2q will map multiple priorities to fewer hardware queues | ||
623 | * (typically all to one hardware queue). | ||
532 | */ | 624 | */ |
533 | struct ath5k_txq { | 625 | struct ath5k_txq { |
534 | unsigned int qnum; /* hardware q number */ | 626 | unsigned int qnum; |
535 | u32 *link; /* link ptr in last TX desc */ | 627 | u32 *link; |
536 | struct list_head q; /* transmit queue */ | 628 | struct list_head q; |
537 | spinlock_t lock; /* lock on q and link */ | 629 | spinlock_t lock; |
538 | bool setup; | 630 | bool setup; |
539 | int txq_len; /* number of queued buffers */ | 631 | int txq_len; |
540 | int txq_max; /* max allowed num of queued buffers */ | 632 | int txq_max; |
541 | bool txq_poll_mark; | 633 | bool txq_poll_mark; |
542 | unsigned int txq_stuck; /* informational counter */ | 634 | unsigned int txq_stuck; |
543 | }; | 635 | }; |
544 | 636 | ||
545 | /* | 637 | /** |
546 | * A struct to hold tx queue's parameters | 638 | * struct ath5k_txq_info - A struct to hold TX queue's parameters |
639 | * @tqi_type: One of enum ath5k_tx_queue | ||
640 | * @tqi_subtype: One of enum ath5k_tx_queue_subtype | ||
641 | * @tqi_flags: TX queue flags (see above) | ||
642 | * @tqi_aifs: Arbitrated Inter-frame Space | ||
643 | * @tqi_cw_min: Minimum Contention Window | ||
644 | * @tqi_cw_max: Maximum Contention Window | ||
645 | * @tqi_cbr_period: Constant bit rate period | ||
646 | * @tqi_ready_time: Time queue waits after an event when RDYTIME is enabled | ||
547 | */ | 647 | */ |
548 | struct ath5k_txq_info { | 648 | struct ath5k_txq_info { |
549 | enum ath5k_tx_queue tqi_type; | 649 | enum ath5k_tx_queue tqi_type; |
550 | enum ath5k_tx_queue_subtype tqi_subtype; | 650 | enum ath5k_tx_queue_subtype tqi_subtype; |
551 | u16 tqi_flags; /* Tx queue flags (see above) */ | 651 | u16 tqi_flags; |
552 | u8 tqi_aifs; /* Arbitrated Interframe Space */ | 652 | u8 tqi_aifs; |
553 | u16 tqi_cw_min; /* Minimum Contention Window */ | 653 | u16 tqi_cw_min; |
554 | u16 tqi_cw_max; /* Maximum Contention Window */ | 654 | u16 tqi_cw_max; |
555 | u32 tqi_cbr_period; /* Constant bit rate period */ | 655 | u32 tqi_cbr_period; |
556 | u32 tqi_cbr_overflow_limit; | 656 | u32 tqi_cbr_overflow_limit; |
557 | u32 tqi_burst_time; | 657 | u32 tqi_burst_time; |
558 | u32 tqi_ready_time; /* Time queue waits after an event */ | 658 | u32 tqi_ready_time; |
559 | }; | 659 | }; |
560 | 660 | ||
561 | /* | 661 | /** |
562 | * Transmit packet types. | 662 | * enum ath5k_pkt_type - Transmit packet types |
563 | * used on tx control descriptor | 663 | * @AR5K_PKT_TYPE_NORMAL: Normal data |
664 | * @AR5K_PKT_TYPE_ATIM: ATIM | ||
665 | * @AR5K_PKT_TYPE_PSPOLL: PS-Poll | ||
666 | * @AR5K_PKT_TYPE_BEACON: Beacon | ||
667 | * @AR5K_PKT_TYPE_PROBE_RESP: Probe response | ||
668 | * @AR5K_PKT_TYPE_PIFS: PIFS | ||
669 | * Used on tx control descriptor | ||
564 | */ | 670 | */ |
565 | enum ath5k_pkt_type { | 671 | enum ath5k_pkt_type { |
566 | AR5K_PKT_TYPE_NORMAL = 0, | 672 | AR5K_PKT_TYPE_NORMAL = 0, |
@@ -583,27 +689,23 @@ enum ath5k_pkt_type { | |||
583 | (ah->ah_txpower.txp_rates_power_table[(_r)] & 0x3f) << (_v) \ | 689 | (ah->ah_txpower.txp_rates_power_table[(_r)] & 0x3f) << (_v) \ |
584 | ) | 690 | ) |
585 | 691 | ||
586 | /* | ||
587 | * DMA size definitions (2^(n+2)) | ||
588 | */ | ||
589 | enum ath5k_dmasize { | ||
590 | AR5K_DMASIZE_4B = 0, | ||
591 | AR5K_DMASIZE_8B, | ||
592 | AR5K_DMASIZE_16B, | ||
593 | AR5K_DMASIZE_32B, | ||
594 | AR5K_DMASIZE_64B, | ||
595 | AR5K_DMASIZE_128B, | ||
596 | AR5K_DMASIZE_256B, | ||
597 | AR5K_DMASIZE_512B | ||
598 | }; | ||
599 | 692 | ||
600 | 693 | ||
601 | /****************\ | 694 | /****************\ |
602 | RX DEFINITIONS | 695 | RX DEFINITIONS |
603 | \****************/ | 696 | \****************/ |
604 | 697 | ||
605 | /* | 698 | /** |
606 | * RX Status descriptor | 699 | * struct ath5k_rx_status - RX Status descriptor |
700 | * @rs_datalen: Data length | ||
701 | * @rs_tstamp: Timestamp | ||
702 | * @rs_status: Status code | ||
703 | * @rs_phyerr: PHY error mask | ||
704 | * @rs_rssi: RSSI in 0.5dbm units | ||
705 | * @rs_keyix: Index to the key used for decrypting | ||
706 | * @rs_rate: Rate used to decode the frame | ||
707 | * @rs_antenna: Antenna used to receive the frame | ||
708 | * @rs_more: Indicates this is a frame fragment (Fast frames) | ||
607 | */ | 709 | */ |
608 | struct ath5k_rx_status { | 710 | struct ath5k_rx_status { |
609 | u16 rs_datalen; | 711 | u16 rs_datalen; |
@@ -645,10 +747,18 @@ struct ath5k_rx_status { | |||
645 | #define TSF_TO_TU(_tsf) (u32)((_tsf) >> 10) | 747 | #define TSF_TO_TU(_tsf) (u32)((_tsf) >> 10) |
646 | 748 | ||
647 | 749 | ||
750 | |||
648 | /*******************************\ | 751 | /*******************************\ |
649 | GAIN OPTIMIZATION DEFINITIONS | 752 | GAIN OPTIMIZATION DEFINITIONS |
650 | \*******************************/ | 753 | \*******************************/ |
651 | 754 | ||
755 | /** | ||
756 | * enum ath5k_rfgain - RF Gain optimization engine state | ||
757 | * @AR5K_RFGAIN_INACTIVE: Engine disabled | ||
758 | * @AR5K_RFGAIN_ACTIVE: Probe active | ||
759 | * @AR5K_RFGAIN_READ_REQUESTED: Probe requested | ||
760 | * @AR5K_RFGAIN_NEED_CHANGE: Gain_F needs change | ||
761 | */ | ||
652 | enum ath5k_rfgain { | 762 | enum ath5k_rfgain { |
653 | AR5K_RFGAIN_INACTIVE = 0, | 763 | AR5K_RFGAIN_INACTIVE = 0, |
654 | AR5K_RFGAIN_ACTIVE, | 764 | AR5K_RFGAIN_ACTIVE, |
@@ -656,6 +766,16 @@ enum ath5k_rfgain { | |||
656 | AR5K_RFGAIN_NEED_CHANGE, | 766 | AR5K_RFGAIN_NEED_CHANGE, |
657 | }; | 767 | }; |
658 | 768 | ||
769 | /** | ||
770 | * struct ath5k_gain - RF Gain optimization engine state data | ||
771 | * @g_step_idx: Current step index | ||
772 | * @g_current: Current gain | ||
773 | * @g_target: Target gain | ||
774 | * @g_low: Low gain boundary | ||
775 | * @g_high: High gain boundary | ||
776 | * @g_f_corr: Gain_F correction | ||
777 | * @g_state: One of enum ath5k_rfgain | ||
778 | */ | ||
659 | struct ath5k_gain { | 779 | struct ath5k_gain { |
660 | u8 g_step_idx; | 780 | u8 g_step_idx; |
661 | u8 g_current; | 781 | u8 g_current; |
@@ -666,6 +786,8 @@ struct ath5k_gain { | |||
666 | u8 g_state; | 786 | u8 g_state; |
667 | }; | 787 | }; |
668 | 788 | ||
789 | |||
790 | |||
669 | /********************\ | 791 | /********************\ |
670 | COMMON DEFINITIONS | 792 | COMMON DEFINITIONS |
671 | \********************/ | 793 | \********************/ |
@@ -674,9 +796,14 @@ struct ath5k_gain { | |||
674 | #define AR5K_SLOT_TIME_20 880 | 796 | #define AR5K_SLOT_TIME_20 880 |
675 | #define AR5K_SLOT_TIME_MAX 0xffff | 797 | #define AR5K_SLOT_TIME_MAX 0xffff |
676 | 798 | ||
677 | /* | 799 | /** |
678 | * The following structure is used to map 2GHz channels to | 800 | * struct ath5k_athchan_2ghz - 2GHz to 5GHZ map for RF5111 |
679 | * 5GHz Atheros channels. | 801 | * @a2_flags: Channel flags (internal) |
802 | * @a2_athchan: HW channel number (internal) | ||
803 | * | ||
804 | * This structure is used to map 2GHz channels to | ||
805 | * 5GHz Atheros channels on 2111 frequency converter | ||
806 | * that comes together with RF5111 | ||
680 | * TODO: Clean up | 807 | * TODO: Clean up |
681 | */ | 808 | */ |
682 | struct ath5k_athchan_2ghz { | 809 | struct ath5k_athchan_2ghz { |
@@ -684,36 +811,80 @@ struct ath5k_athchan_2ghz { | |||
684 | u16 a2_athchan; | 811 | u16 a2_athchan; |
685 | }; | 812 | }; |
686 | 813 | ||
814 | /** | ||
815 | * enum ath5k_dmasize - DMA size definitions (2^(n+2)) | ||
816 | * @AR5K_DMASIZE_4B: 4Bytes | ||
817 | * @AR5K_DMASIZE_8B: 8Bytes | ||
818 | * @AR5K_DMASIZE_16B: 16Bytes | ||
819 | * @AR5K_DMASIZE_32B: 32Bytes | ||
820 | * @AR5K_DMASIZE_64B: 64Bytes (Default) | ||
821 | * @AR5K_DMASIZE_128B: 128Bytes | ||
822 | * @AR5K_DMASIZE_256B: 256Bytes | ||
823 | * @AR5K_DMASIZE_512B: 512Bytes | ||
824 | * | ||
825 | * These are used to set DMA burst size on hw | ||
826 | * | ||
827 | * Note: Some platforms can't handle more than 4Bytes | ||
828 | * be careful on embedded boards. | ||
829 | */ | ||
830 | enum ath5k_dmasize { | ||
831 | AR5K_DMASIZE_4B = 0, | ||
832 | AR5K_DMASIZE_8B, | ||
833 | AR5K_DMASIZE_16B, | ||
834 | AR5K_DMASIZE_32B, | ||
835 | AR5K_DMASIZE_64B, | ||
836 | AR5K_DMASIZE_128B, | ||
837 | AR5K_DMASIZE_256B, | ||
838 | AR5K_DMASIZE_512B | ||
839 | }; | ||
840 | |||
841 | |||
687 | 842 | ||
688 | /******************\ | 843 | /******************\ |
689 | RATE DEFINITIONS | 844 | RATE DEFINITIONS |
690 | \******************/ | 845 | \******************/ |
691 | 846 | ||
692 | /** | 847 | /** |
848 | * DOC: Rate codes | ||
849 | * | ||
693 | * Seems the ar5xxx hardware supports up to 32 rates, indexed by 1-32. | 850 | * Seems the ar5xxx hardware supports up to 32 rates, indexed by 1-32. |
694 | * | 851 | * |
695 | * The rate code is used to get the RX rate or set the TX rate on the | 852 | * The rate code is used to get the RX rate or set the TX rate on the |
696 | * hardware descriptors. It is also used for internal modulation control | 853 | * hardware descriptors. It is also used for internal modulation control |
697 | * and settings. | 854 | * and settings. |
698 | * | 855 | * |
699 | * This is the hardware rate map we are aware of: | 856 | * This is the hardware rate map we are aware of (html unfriendly): |
700 | * | ||
701 | * rate_code 0x01 0x02 0x03 0x04 0x05 0x06 0x07 0x08 | ||
702 | * rate_kbps 3000 1000 ? ? ? 2000 500 48000 | ||
703 | * | ||
704 | * rate_code 0x09 0x0A 0x0B 0x0C 0x0D 0x0E 0x0F 0x10 | ||
705 | * rate_kbps 24000 12000 6000 54000 36000 18000 9000 ? | ||
706 | * | 857 | * |
707 | * rate_code 17 18 19 20 21 22 23 24 | 858 | * Rate code Rate (Kbps) |
708 | * rate_kbps ? ? ? ? ? ? ? 11000 | 859 | * --------- ----------- |
860 | * 0x01 3000 (XR) | ||
861 | * 0x02 1000 (XR) | ||
862 | * 0x03 250 (XR) | ||
863 | * 0x04 - 05 -Reserved- | ||
864 | * 0x06 2000 (XR) | ||
865 | * 0x07 500 (XR) | ||
866 | * 0x08 48000 (OFDM) | ||
867 | * 0x09 24000 (OFDM) | ||
868 | * 0x0A 12000 (OFDM) | ||
869 | * 0x0B 6000 (OFDM) | ||
870 | * 0x0C 54000 (OFDM) | ||
871 | * 0x0D 36000 (OFDM) | ||
872 | * 0x0E 18000 (OFDM) | ||
873 | * 0x0F 9000 (OFDM) | ||
874 | * 0x10 - 17 -Reserved- | ||
875 | * 0x18 11000L (CCK) | ||
876 | * 0x19 5500L (CCK) | ||
877 | * 0x1A 2000L (CCK) | ||
878 | * 0x1B 1000L (CCK) | ||
879 | * 0x1C 11000S (CCK) | ||
880 | * 0x1D 5500S (CCK) | ||
881 | * 0x1E 2000S (CCK) | ||
882 | * 0x1F -Reserved- | ||
709 | * | 883 | * |
710 | * rate_code 25 26 27 28 29 30 31 32 | 884 | * "S" indicates CCK rates with short preamble and "L" with long preamble. |
711 | * rate_kbps 5500 2000 1000 11000S 5500S 2000S ? ? | ||
712 | * | ||
713 | * "S" indicates CCK rates with short preamble. | ||
714 | * | 885 | * |
715 | * AR5211 has different rate codes for CCK (802.11B) rates. It only uses the | 886 | * AR5211 has different rate codes for CCK (802.11B) rates. It only uses the |
716 | * lowest 4 bits, so they are the same as below with a 0xF mask. | 887 | * lowest 4 bits, so they are the same as above with a 0xF mask. |
717 | * (0xB, 0xA, 0x9 and 0x8 for 1M, 2M, 5.5M and 11M). | 888 | * (0xB, 0xA, 0x9 and 0x8 for 1M, 2M, 5.5M and 11M). |
718 | * We handle this in ath5k_setup_bands(). | 889 | * We handle this in ath5k_setup_bands(). |
719 | */ | 890 | */ |
@@ -733,13 +904,9 @@ struct ath5k_athchan_2ghz { | |||
733 | #define ATH5K_RATE_CODE_36M 0x0D | 904 | #define ATH5K_RATE_CODE_36M 0x0D |
734 | #define ATH5K_RATE_CODE_48M 0x08 | 905 | #define ATH5K_RATE_CODE_48M 0x08 |
735 | #define ATH5K_RATE_CODE_54M 0x0C | 906 | #define ATH5K_RATE_CODE_54M 0x0C |
736 | /* XR */ | ||
737 | #define ATH5K_RATE_CODE_XR_500K 0x07 | ||
738 | #define ATH5K_RATE_CODE_XR_1M 0x02 | ||
739 | #define ATH5K_RATE_CODE_XR_2M 0x06 | ||
740 | #define ATH5K_RATE_CODE_XR_3M 0x01 | ||
741 | 907 | ||
742 | /* adding this flag to rate_code enables short preamble */ | 908 | /* Adding this flag to rate_code on B rates |
909 | * enables short preamble */ | ||
743 | #define AR5K_SET_SHORT_PREAMBLE 0x04 | 910 | #define AR5K_SET_SHORT_PREAMBLE 0x04 |
744 | 911 | ||
745 | /* | 912 | /* |
@@ -769,49 +936,65 @@ extern int ath5k_modparam_nohwcrypt; | |||
769 | 936 | ||
770 | /** | 937 | /** |
771 | * enum ath5k_int - Hardware interrupt masks helpers | 938 | * enum ath5k_int - Hardware interrupt masks helpers |
939 | * @AR5K_INT_RXOK: Frame successfully received | ||
940 | * @AR5K_INT_RXDESC: Request RX descriptor/Read RX descriptor | ||
941 | * @AR5K_INT_RXERR: Frame reception failed | ||
942 | * @AR5K_INT_RXNOFRM: No frame received within a specified time period | ||
943 | * @AR5K_INT_RXEOL: Reached "End Of List", means we need more RX descriptors | ||
944 | * @AR5K_INT_RXORN: Indicates we got RX FIFO overrun. Note that Rx overrun is | ||
945 | * not always fatal, on some chips we can continue operation | ||
946 | * without resetting the card, that's why %AR5K_INT_FATAL is not | ||
947 | * common for all chips. | ||
948 | * @AR5K_INT_RX_ALL: Mask to identify all RX related interrupts | ||
949 | * | ||
950 | * @AR5K_INT_TXOK: Frame transmission success | ||
951 | * @AR5K_INT_TXDESC: Request TX descriptor/Read TX status descriptor | ||
952 | * @AR5K_INT_TXERR: Frame transmission failure | ||
953 | * @AR5K_INT_TXEOL: Received End Of List for VEOL (Virtual End Of List). The | ||
954 | * Queue Control Unit (QCU) signals an EOL interrupt only if a | ||
955 | * descriptor's LinkPtr is NULL. For more details, refer to: | ||
956 | * "http://www.freepatentsonline.com/20030225739.html" | ||
957 | * @AR5K_INT_TXNOFRM: No frame was transmitted within a specified time period | ||
958 | * @AR5K_INT_TXURN: Indicates we got TX FIFO underrun. In such case we should | ||
959 | * increase the TX trigger threshold. | ||
960 | * @AR5K_INT_TX_ALL: Mask to identify all TX related interrupts | ||
772 | * | 961 | * |
773 | * @AR5K_INT_RX: mask to identify received frame interrupts, of type | ||
774 | * AR5K_ISR_RXOK or AR5K_ISR_RXERR | ||
775 | * @AR5K_INT_RXDESC: Request RX descriptor/Read RX descriptor (?) | ||
776 | * @AR5K_INT_RXNOFRM: No frame received (?) | ||
777 | * @AR5K_INT_RXEOL: received End Of List for VEOL (Virtual End Of List). The | ||
778 | * Queue Control Unit (QCU) signals an EOL interrupt only if a descriptor's | ||
779 | * LinkPtr is NULL. For more details, refer to: | ||
780 | * http://www.freepatentsonline.com/20030225739.html | ||
781 | * @AR5K_INT_RXORN: Indicates we got RX overrun (eg. no more descriptors). | ||
782 | * Note that Rx overrun is not always fatal, on some chips we can continue | ||
783 | * operation without resetting the card, that's why int_fatal is not | ||
784 | * common for all chips. | ||
785 | * @AR5K_INT_TX: mask to identify received frame interrupts, of type | ||
786 | * AR5K_ISR_TXOK or AR5K_ISR_TXERR | ||
787 | * @AR5K_INT_TXDESC: Request TX descriptor/Read TX status descriptor (?) | ||
788 | * @AR5K_INT_TXURN: received when we should increase the TX trigger threshold | ||
789 | * We currently do increments on interrupt by | ||
790 | * (AR5K_TUNE_MAX_TX_FIFO_THRES - current_trigger_level) / 2 | ||
791 | * @AR5K_INT_MIB: Indicates the either Management Information Base counters or | 962 | * @AR5K_INT_MIB: Indicates the either Management Information Base counters or |
792 | * one of the PHY error counters reached the maximum value and should be | 963 | * one of the PHY error counters reached the maximum value and |
793 | * read and cleared. | 964 | * should be read and cleared. |
965 | * @AR5K_INT_SWI: Software triggered interrupt. | ||
794 | * @AR5K_INT_RXPHY: RX PHY Error | 966 | * @AR5K_INT_RXPHY: RX PHY Error |
795 | * @AR5K_INT_RXKCM: RX Key cache miss | 967 | * @AR5K_INT_RXKCM: RX Key cache miss |
796 | * @AR5K_INT_SWBA: SoftWare Beacon Alert - indicates its time to send a | 968 | * @AR5K_INT_SWBA: SoftWare Beacon Alert - indicates its time to send a |
797 | * beacon that must be handled in software. The alternative is if you | 969 | * beacon that must be handled in software. The alternative is if |
798 | * have VEOL support, in that case you let the hardware deal with things. | 970 | * you have VEOL support, in that case you let the hardware deal |
971 | * with things. | ||
972 | * @AR5K_INT_BRSSI: Beacon received with an RSSI value below our threshold | ||
799 | * @AR5K_INT_BMISS: If in STA mode this indicates we have stopped seeing | 973 | * @AR5K_INT_BMISS: If in STA mode this indicates we have stopped seeing |
800 | * beacons from the AP have associated with, we should probably try to | 974 | * beacons from the AP have associated with, we should probably |
801 | * reassociate. When in IBSS mode this might mean we have not received | 975 | * try to reassociate. When in IBSS mode this might mean we have |
802 | * any beacons from any local stations. Note that every station in an | 976 | * not received any beacons from any local stations. Note that |
803 | * IBSS schedules to send beacons at the Target Beacon Transmission Time | 977 | * every station in an IBSS schedules to send beacons at the |
804 | * (TBTT) with a random backoff. | 978 | * Target Beacon Transmission Time (TBTT) with a random backoff. |
805 | * @AR5K_INT_BNR: Beacon Not Ready interrupt - ?? | 979 | * @AR5K_INT_BNR: Beacon queue got triggered (DMA beacon alert) while empty. |
806 | * @AR5K_INT_GPIO: GPIO interrupt is used for RF Kill, disabled for now | 980 | * @AR5K_INT_TIM: Beacon with local station's TIM bit set |
807 | * until properly handled | 981 | * @AR5K_INT_DTIM: Beacon with DTIM bit and zero DTIM count received |
808 | * @AR5K_INT_FATAL: Fatal errors were encountered, typically caused by DMA | 982 | * @AR5K_INT_DTIM_SYNC: DTIM sync lost |
809 | * errors. These types of errors we can enable seem to be of type | 983 | * @AR5K_INT_GPIO: GPIO interrupt is used for RF Kill switches connected to |
810 | * AR5K_SIMR2_MCABT, AR5K_SIMR2_SSERR and AR5K_SIMR2_DPERR. | 984 | * our GPIO pins. |
985 | * @AR5K_INT_BCN_TIMEOUT: Beacon timeout, we waited after TBTT but got noting | ||
986 | * @AR5K_INT_CAB_TIMEOUT: We waited for CAB traffic after the beacon but got | ||
987 | * nothing or an incomplete CAB frame sequence. | ||
988 | * @AR5K_INT_QCBRORN: A queue got it's CBR counter expired | ||
989 | * @AR5K_INT_QCBRURN: A queue got triggered wile empty | ||
990 | * @AR5K_INT_QTRIG: A queue got triggered | ||
991 | * | ||
992 | * @AR5K_INT_FATAL: Fatal errors were encountered, typically caused by bus/DMA | ||
993 | * errors. Indicates we need to reset the card. | ||
811 | * @AR5K_INT_GLOBAL: Used to clear and set the IER | 994 | * @AR5K_INT_GLOBAL: Used to clear and set the IER |
812 | * @AR5K_INT_NOCARD: signals the card has been removed | 995 | * @AR5K_INT_NOCARD: Signals the card has been removed |
813 | * @AR5K_INT_COMMON: common interrupts shared among MACs with the same | 996 | * @AR5K_INT_COMMON: Common interrupts shared among MACs with the same |
814 | * bit value | 997 | * bit value |
815 | * | 998 | * |
816 | * These are mapped to take advantage of some common bits | 999 | * These are mapped to take advantage of some common bits |
817 | * between the MACs, to be able to set intr properties | 1000 | * between the MACs, to be able to set intr properties |
@@ -847,15 +1030,15 @@ enum ath5k_int { | |||
847 | AR5K_INT_GPIO = 0x01000000, | 1030 | AR5K_INT_GPIO = 0x01000000, |
848 | AR5K_INT_BCN_TIMEOUT = 0x02000000, /* Non common */ | 1031 | AR5K_INT_BCN_TIMEOUT = 0x02000000, /* Non common */ |
849 | AR5K_INT_CAB_TIMEOUT = 0x04000000, /* Non common */ | 1032 | AR5K_INT_CAB_TIMEOUT = 0x04000000, /* Non common */ |
850 | AR5K_INT_RX_DOPPLER = 0x08000000, /* Non common */ | 1033 | AR5K_INT_QCBRORN = 0x08000000, /* Non common */ |
851 | AR5K_INT_QCBRORN = 0x10000000, /* Non common */ | 1034 | AR5K_INT_QCBRURN = 0x10000000, /* Non common */ |
852 | AR5K_INT_QCBRURN = 0x20000000, /* Non common */ | 1035 | AR5K_INT_QTRIG = 0x20000000, /* Non common */ |
853 | AR5K_INT_QTRIG = 0x40000000, /* Non common */ | ||
854 | AR5K_INT_GLOBAL = 0x80000000, | 1036 | AR5K_INT_GLOBAL = 0x80000000, |
855 | 1037 | ||
856 | AR5K_INT_TX_ALL = AR5K_INT_TXOK | 1038 | AR5K_INT_TX_ALL = AR5K_INT_TXOK |
857 | | AR5K_INT_TXDESC | 1039 | | AR5K_INT_TXDESC |
858 | | AR5K_INT_TXERR | 1040 | | AR5K_INT_TXERR |
1041 | | AR5K_INT_TXNOFRM | ||
859 | | AR5K_INT_TXEOL | 1042 | | AR5K_INT_TXEOL |
860 | | AR5K_INT_TXURN, | 1043 | | AR5K_INT_TXURN, |
861 | 1044 | ||
@@ -891,15 +1074,32 @@ enum ath5k_int { | |||
891 | AR5K_INT_NOCARD = 0xffffffff | 1074 | AR5K_INT_NOCARD = 0xffffffff |
892 | }; | 1075 | }; |
893 | 1076 | ||
894 | /* mask which calibration is active at the moment */ | 1077 | /** |
1078 | * enum ath5k_calibration_mask - Mask which calibration is active at the moment | ||
1079 | * @AR5K_CALIBRATION_FULL: Full calibration (AGC + SHORT) | ||
1080 | * @AR5K_CALIBRATION_SHORT: Short calibration (NF + I/Q) | ||
1081 | * @AR5K_CALIBRATION_NF: Noise Floor calibration | ||
1082 | * @AR5K_CALIBRATION_ANI: Adaptive Noise Immunity | ||
1083 | */ | ||
895 | enum ath5k_calibration_mask { | 1084 | enum ath5k_calibration_mask { |
896 | AR5K_CALIBRATION_FULL = 0x01, | 1085 | AR5K_CALIBRATION_FULL = 0x01, |
897 | AR5K_CALIBRATION_SHORT = 0x02, | 1086 | AR5K_CALIBRATION_SHORT = 0x02, |
898 | AR5K_CALIBRATION_ANI = 0x04, | 1087 | AR5K_CALIBRATION_NF = 0x04, |
1088 | AR5K_CALIBRATION_ANI = 0x08, | ||
899 | }; | 1089 | }; |
900 | 1090 | ||
901 | /* | 1091 | /** |
902 | * Power management | 1092 | * enum ath5k_power_mode - Power management modes |
1093 | * @AR5K_PM_UNDEFINED: Undefined | ||
1094 | * @AR5K_PM_AUTO: Allow card to sleep if possible | ||
1095 | * @AR5K_PM_AWAKE: Force card to wake up | ||
1096 | * @AR5K_PM_FULL_SLEEP: Force card to full sleep (DANGEROUS) | ||
1097 | * @AR5K_PM_NETWORK_SLEEP: Allow to sleep for a specified duration | ||
1098 | * | ||
1099 | * Currently only PM_AWAKE is used, FULL_SLEEP and NETWORK_SLEEP/AUTO | ||
1100 | * are also known to have problems on some cards. This is not a big | ||
1101 | * problem though because we can have almost the same effect as | ||
1102 | * FULL_SLEEP by putting card on warm reset (it's almost powered down). | ||
903 | */ | 1103 | */ |
904 | enum ath5k_power_mode { | 1104 | enum ath5k_power_mode { |
905 | AR5K_PM_UNDEFINED = 0, | 1105 | AR5K_PM_UNDEFINED = 0, |
@@ -957,6 +1157,8 @@ struct ath5k_capabilities { | |||
957 | } cap_queues; | 1157 | } cap_queues; |
958 | 1158 | ||
959 | bool cap_has_phyerr_counters; | 1159 | bool cap_has_phyerr_counters; |
1160 | bool cap_has_mrr_support; | ||
1161 | bool cap_needs_2GHz_ovr; | ||
960 | }; | 1162 | }; |
961 | 1163 | ||
962 | /* size of noise floor history (keep it a power of two) */ | 1164 | /* size of noise floor history (keep it a power of two) */ |
@@ -1072,13 +1274,11 @@ struct ath5k_hw { | |||
1072 | dma_addr_t desc_daddr; /* DMA (physical) address */ | 1274 | dma_addr_t desc_daddr; /* DMA (physical) address */ |
1073 | size_t desc_len; /* size of TX/RX descriptors */ | 1275 | size_t desc_len; /* size of TX/RX descriptors */ |
1074 | 1276 | ||
1075 | DECLARE_BITMAP(status, 6); | 1277 | DECLARE_BITMAP(status, 4); |
1076 | #define ATH_STAT_INVALID 0 /* disable hardware accesses */ | 1278 | #define ATH_STAT_INVALID 0 /* disable hardware accesses */ |
1077 | #define ATH_STAT_MRRETRY 1 /* multi-rate retry support */ | 1279 | #define ATH_STAT_PROMISC 1 |
1078 | #define ATH_STAT_PROMISC 2 | 1280 | #define ATH_STAT_LEDSOFT 2 /* enable LED gpio status */ |
1079 | #define ATH_STAT_LEDSOFT 3 /* enable LED gpio status */ | 1281 | #define ATH_STAT_STARTED 3 /* opened & irqs enabled */ |
1080 | #define ATH_STAT_STARTED 4 /* opened & irqs enabled */ | ||
1081 | #define ATH_STAT_2G_DISABLED 5 /* multiband radio without 2G */ | ||
1082 | 1282 | ||
1083 | unsigned int filter_flags; /* HW flags, AR5K_RX_FILTER_* */ | 1283 | unsigned int filter_flags; /* HW flags, AR5K_RX_FILTER_* */ |
1084 | struct ieee80211_channel *curchan; /* current h/w channel */ | 1284 | struct ieee80211_channel *curchan; /* current h/w channel */ |
@@ -1097,6 +1297,7 @@ struct ath5k_hw { | |||
1097 | led_on; /* pin setting for LED on */ | 1297 | led_on; /* pin setting for LED on */ |
1098 | 1298 | ||
1099 | struct work_struct reset_work; /* deferred chip reset */ | 1299 | struct work_struct reset_work; /* deferred chip reset */ |
1300 | struct work_struct calib_work; /* deferred phy calibration */ | ||
1100 | 1301 | ||
1101 | struct list_head rxbuf; /* receive buffer */ | 1302 | struct list_head rxbuf; /* receive buffer */ |
1102 | spinlock_t rxbuflock; | 1303 | spinlock_t rxbuflock; |
@@ -1113,8 +1314,6 @@ struct ath5k_hw { | |||
1113 | 1314 | ||
1114 | struct ath5k_rfkill rf_kill; | 1315 | struct ath5k_rfkill rf_kill; |
1115 | 1316 | ||
1116 | struct tasklet_struct calib; /* calibration tasklet */ | ||
1117 | |||
1118 | spinlock_t block; /* protects beacon */ | 1317 | spinlock_t block; /* protects beacon */ |
1119 | struct tasklet_struct beacontq; /* beacon intr tasklet */ | 1318 | struct tasklet_struct beacontq; /* beacon intr tasklet */ |
1120 | struct list_head bcbuf; /* beacon buffer */ | 1319 | struct list_head bcbuf; /* beacon buffer */ |
@@ -1144,7 +1343,7 @@ struct ath5k_hw { | |||
1144 | enum ath5k_int ah_imr; | 1343 | enum ath5k_int ah_imr; |
1145 | 1344 | ||
1146 | struct ieee80211_channel *ah_current_channel; | 1345 | struct ieee80211_channel *ah_current_channel; |
1147 | bool ah_calibration; | 1346 | bool ah_iq_cal_needed; |
1148 | bool ah_single_chip; | 1347 | bool ah_single_chip; |
1149 | 1348 | ||
1150 | enum ath5k_version ah_version; | 1349 | enum ath5k_version ah_version; |
@@ -1187,7 +1386,13 @@ struct ath5k_hw { | |||
1187 | u32 ah_txq_imr_cbrurn; | 1386 | u32 ah_txq_imr_cbrurn; |
1188 | u32 ah_txq_imr_qtrig; | 1387 | u32 ah_txq_imr_qtrig; |
1189 | u32 ah_txq_imr_nofrm; | 1388 | u32 ah_txq_imr_nofrm; |
1190 | u32 ah_txq_isr; | 1389 | |
1390 | u32 ah_txq_isr_txok_all; | ||
1391 | u32 ah_txq_isr_txurn; | ||
1392 | u32 ah_txq_isr_qcborn; | ||
1393 | u32 ah_txq_isr_qcburn; | ||
1394 | u32 ah_txq_isr_qtrig; | ||
1395 | |||
1191 | u32 *ah_rf_banks; | 1396 | u32 *ah_rf_banks; |
1192 | size_t ah_rf_banks_size; | 1397 | size_t ah_rf_banks_size; |
1193 | size_t ah_rf_regs_count; | 1398 | size_t ah_rf_regs_count; |
@@ -1228,8 +1433,8 @@ struct ath5k_hw { | |||
1228 | 1433 | ||
1229 | /* Calibration timestamp */ | 1434 | /* Calibration timestamp */ |
1230 | unsigned long ah_cal_next_full; | 1435 | unsigned long ah_cal_next_full; |
1436 | unsigned long ah_cal_next_short; | ||
1231 | unsigned long ah_cal_next_ani; | 1437 | unsigned long ah_cal_next_ani; |
1232 | unsigned long ah_cal_next_nf; | ||
1233 | 1438 | ||
1234 | /* Calibration mask */ | 1439 | /* Calibration mask */ |
1235 | u8 ah_cal_mask; | 1440 | u8 ah_cal_mask; |
@@ -1338,11 +1543,11 @@ void ath5k_hw_stop_rx_pcu(struct ath5k_hw *ah); | |||
1338 | u64 ath5k_hw_get_tsf64(struct ath5k_hw *ah); | 1543 | u64 ath5k_hw_get_tsf64(struct ath5k_hw *ah); |
1339 | void ath5k_hw_set_tsf64(struct ath5k_hw *ah, u64 tsf64); | 1544 | void ath5k_hw_set_tsf64(struct ath5k_hw *ah, u64 tsf64); |
1340 | void ath5k_hw_reset_tsf(struct ath5k_hw *ah); | 1545 | void ath5k_hw_reset_tsf(struct ath5k_hw *ah); |
1341 | void ath5k_hw_init_beacon(struct ath5k_hw *ah, u32 next_beacon, u32 interval); | 1546 | void ath5k_hw_init_beacon_timers(struct ath5k_hw *ah, u32 next_beacon, |
1547 | u32 interval); | ||
1342 | bool ath5k_hw_check_beacon_timers(struct ath5k_hw *ah, int intval); | 1548 | bool ath5k_hw_check_beacon_timers(struct ath5k_hw *ah, int intval); |
1343 | /* Init function */ | 1549 | /* Init function */ |
1344 | void ath5k_hw_pcu_init(struct ath5k_hw *ah, enum nl80211_iftype op_mode, | 1550 | void ath5k_hw_pcu_init(struct ath5k_hw *ah, enum nl80211_iftype op_mode); |
1345 | u8 mode); | ||
1346 | 1551 | ||
1347 | /* Queue Control Unit, DFS Control Unit Functions */ | 1552 | /* Queue Control Unit, DFS Control Unit Functions */ |
1348 | int ath5k_hw_get_tx_queueprops(struct ath5k_hw *ah, int queue, | 1553 | int ath5k_hw_get_tx_queueprops(struct ath5k_hw *ah, int queue, |
diff --git a/drivers/net/wireless/ath/ath5k/attach.c b/drivers/net/wireless/ath/ath5k/attach.c index 91627dd2c26a..d7114c75fe9b 100644 --- a/drivers/net/wireless/ath/ath5k/attach.c +++ b/drivers/net/wireless/ath/ath5k/attach.c | |||
@@ -27,8 +27,7 @@ | |||
27 | #include "debug.h" | 27 | #include "debug.h" |
28 | 28 | ||
29 | /** | 29 | /** |
30 | * ath5k_hw_post - Power On Self Test helper function | 30 | * ath5k_hw_post() - Power On Self Test helper function |
31 | * | ||
32 | * @ah: The &struct ath5k_hw | 31 | * @ah: The &struct ath5k_hw |
33 | */ | 32 | */ |
34 | static int ath5k_hw_post(struct ath5k_hw *ah) | 33 | static int ath5k_hw_post(struct ath5k_hw *ah) |
@@ -92,8 +91,7 @@ static int ath5k_hw_post(struct ath5k_hw *ah) | |||
92 | } | 91 | } |
93 | 92 | ||
94 | /** | 93 | /** |
95 | * ath5k_hw_init - Check if hw is supported and init the needed structs | 94 | * ath5k_hw_init() - Check if hw is supported and init the needed structs |
96 | * | ||
97 | * @ah: The &struct ath5k_hw associated with the device | 95 | * @ah: The &struct ath5k_hw associated with the device |
98 | * | 96 | * |
99 | * Check if the device is supported, perform a POST and initialize the needed | 97 | * Check if the device is supported, perform a POST and initialize the needed |
@@ -298,7 +296,7 @@ int ath5k_hw_init(struct ath5k_hw *ah) | |||
298 | 296 | ||
299 | /* Reset SERDES to load new settings */ | 297 | /* Reset SERDES to load new settings */ |
300 | ath5k_hw_reg_write(ah, 0x00000000, AR5K_PCIE_SERDES_RESET); | 298 | ath5k_hw_reg_write(ah, 0x00000000, AR5K_PCIE_SERDES_RESET); |
301 | mdelay(1); | 299 | usleep_range(1000, 1500); |
302 | } | 300 | } |
303 | 301 | ||
304 | /* Get misc capabilities */ | 302 | /* Get misc capabilities */ |
@@ -308,11 +306,6 @@ int ath5k_hw_init(struct ath5k_hw *ah) | |||
308 | goto err; | 306 | goto err; |
309 | } | 307 | } |
310 | 308 | ||
311 | if (test_bit(ATH_STAT_2G_DISABLED, ah->status)) { | ||
312 | __clear_bit(AR5K_MODE_11B, ah->ah_capabilities.cap_mode); | ||
313 | __clear_bit(AR5K_MODE_11G, ah->ah_capabilities.cap_mode); | ||
314 | } | ||
315 | |||
316 | /* Crypto settings */ | 309 | /* Crypto settings */ |
317 | common->keymax = (ah->ah_version == AR5K_AR5210 ? | 310 | common->keymax = (ah->ah_version == AR5K_AR5210 ? |
318 | AR5K_KEYTABLE_SIZE_5210 : AR5K_KEYTABLE_SIZE_5211); | 311 | AR5K_KEYTABLE_SIZE_5210 : AR5K_KEYTABLE_SIZE_5211); |
@@ -349,8 +342,7 @@ err: | |||
349 | } | 342 | } |
350 | 343 | ||
351 | /** | 344 | /** |
352 | * ath5k_hw_deinit - Free the ath5k_hw struct | 345 | * ath5k_hw_deinit() - Free the &struct ath5k_hw |
353 | * | ||
354 | * @ah: The &struct ath5k_hw | 346 | * @ah: The &struct ath5k_hw |
355 | */ | 347 | */ |
356 | void ath5k_hw_deinit(struct ath5k_hw *ah) | 348 | void ath5k_hw_deinit(struct ath5k_hw *ah) |
diff --git a/drivers/net/wireless/ath/ath5k/base.c b/drivers/net/wireless/ath/ath5k/base.c index b346d0492001..178a4dd10316 100644 --- a/drivers/net/wireless/ath/ath5k/base.c +++ b/drivers/net/wireless/ath/ath5k/base.c | |||
@@ -80,6 +80,11 @@ static int modparam_fastchanswitch; | |||
80 | module_param_named(fastchanswitch, modparam_fastchanswitch, bool, S_IRUGO); | 80 | module_param_named(fastchanswitch, modparam_fastchanswitch, bool, S_IRUGO); |
81 | MODULE_PARM_DESC(fastchanswitch, "Enable fast channel switching for AR2413/AR5413 radios."); | 81 | MODULE_PARM_DESC(fastchanswitch, "Enable fast channel switching for AR2413/AR5413 radios."); |
82 | 82 | ||
83 | static int ath5k_modparam_no_hw_rfkill_switch; | ||
84 | module_param_named(no_hw_rfkill_switch, ath5k_modparam_no_hw_rfkill_switch, | ||
85 | bool, S_IRUGO); | ||
86 | MODULE_PARM_DESC(no_hw_rfkill_switch, "Ignore the GPIO RFKill switch state"); | ||
87 | |||
83 | 88 | ||
84 | /* Module info */ | 89 | /* Module info */ |
85 | MODULE_AUTHOR("Jiri Slaby"); | 90 | MODULE_AUTHOR("Jiri Slaby"); |
@@ -183,7 +188,6 @@ static const struct ieee80211_rate ath5k_rates[] = { | |||
183 | { .bitrate = 540, | 188 | { .bitrate = 540, |
184 | .hw_value = ATH5K_RATE_CODE_54M, | 189 | .hw_value = ATH5K_RATE_CODE_54M, |
185 | .flags = 0 }, | 190 | .flags = 0 }, |
186 | /* XR missing */ | ||
187 | }; | 191 | }; |
188 | 192 | ||
189 | static inline u64 ath5k_extend_tsf(struct ath5k_hw *ah, u32 rstamp) | 193 | static inline u64 ath5k_extend_tsf(struct ath5k_hw *ah, u32 rstamp) |
@@ -721,21 +725,24 @@ ath5k_txbuf_setup(struct ath5k_hw *ah, struct ath5k_buf *bf, | |||
721 | if (ret) | 725 | if (ret) |
722 | goto err_unmap; | 726 | goto err_unmap; |
723 | 727 | ||
724 | memset(mrr_rate, 0, sizeof(mrr_rate)); | 728 | /* Set up MRR descriptor */ |
725 | memset(mrr_tries, 0, sizeof(mrr_tries)); | 729 | if (ah->ah_capabilities.cap_has_mrr_support) { |
726 | for (i = 0; i < 3; i++) { | 730 | memset(mrr_rate, 0, sizeof(mrr_rate)); |
727 | rate = ieee80211_get_alt_retry_rate(ah->hw, info, i); | 731 | memset(mrr_tries, 0, sizeof(mrr_tries)); |
728 | if (!rate) | 732 | for (i = 0; i < 3; i++) { |
729 | break; | 733 | rate = ieee80211_get_alt_retry_rate(ah->hw, info, i); |
734 | if (!rate) | ||
735 | break; | ||
730 | 736 | ||
731 | mrr_rate[i] = rate->hw_value; | 737 | mrr_rate[i] = rate->hw_value; |
732 | mrr_tries[i] = info->control.rates[i + 1].count; | 738 | mrr_tries[i] = info->control.rates[i + 1].count; |
733 | } | 739 | } |
734 | 740 | ||
735 | ath5k_hw_setup_mrr_tx_desc(ah, ds, | 741 | ath5k_hw_setup_mrr_tx_desc(ah, ds, |
736 | mrr_rate[0], mrr_tries[0], | 742 | mrr_rate[0], mrr_tries[0], |
737 | mrr_rate[1], mrr_tries[1], | 743 | mrr_rate[1], mrr_tries[1], |
738 | mrr_rate[2], mrr_tries[2]); | 744 | mrr_rate[2], mrr_tries[2]); |
745 | } | ||
739 | 746 | ||
740 | ds->ds_link = 0; | 747 | ds->ds_link = 0; |
741 | ds->ds_data = bf->skbaddr; | 748 | ds->ds_data = bf->skbaddr; |
@@ -1689,7 +1696,7 @@ ath5k_tasklet_tx(unsigned long data) | |||
1689 | struct ath5k_hw *ah = (void *)data; | 1696 | struct ath5k_hw *ah = (void *)data; |
1690 | 1697 | ||
1691 | for (i = 0; i < AR5K_NUM_TX_QUEUES; i++) | 1698 | for (i = 0; i < AR5K_NUM_TX_QUEUES; i++) |
1692 | if (ah->txqs[i].setup && (ah->ah_txq_isr & BIT(i))) | 1699 | if (ah->txqs[i].setup && (ah->ah_txq_isr_txok_all & BIT(i))) |
1693 | ath5k_tx_processq(ah, &ah->txqs[i]); | 1700 | ath5k_tx_processq(ah, &ah->txqs[i]); |
1694 | 1701 | ||
1695 | ah->tx_pending = false; | 1702 | ah->tx_pending = false; |
@@ -2005,7 +2012,7 @@ ath5k_beacon_update_timers(struct ath5k_hw *ah, u64 bc_tsf) | |||
2005 | ah->nexttbtt = nexttbtt; | 2012 | ah->nexttbtt = nexttbtt; |
2006 | 2013 | ||
2007 | intval |= AR5K_BEACON_ENA; | 2014 | intval |= AR5K_BEACON_ENA; |
2008 | ath5k_hw_init_beacon(ah, nexttbtt, intval); | 2015 | ath5k_hw_init_beacon_timers(ah, nexttbtt, intval); |
2009 | 2016 | ||
2010 | /* | 2017 | /* |
2011 | * debugging output last in order to preserve the time critical aspect | 2018 | * debugging output last in order to preserve the time critical aspect |
@@ -2112,16 +2119,29 @@ static void | |||
2112 | ath5k_intr_calibration_poll(struct ath5k_hw *ah) | 2119 | ath5k_intr_calibration_poll(struct ath5k_hw *ah) |
2113 | { | 2120 | { |
2114 | if (time_is_before_eq_jiffies(ah->ah_cal_next_ani) && | 2121 | if (time_is_before_eq_jiffies(ah->ah_cal_next_ani) && |
2115 | !(ah->ah_cal_mask & AR5K_CALIBRATION_FULL)) { | 2122 | !(ah->ah_cal_mask & AR5K_CALIBRATION_FULL) && |
2116 | /* run ANI only when full calibration is not active */ | 2123 | !(ah->ah_cal_mask & AR5K_CALIBRATION_SHORT)) { |
2124 | |||
2125 | /* Run ANI only when calibration is not active */ | ||
2126 | |||
2117 | ah->ah_cal_next_ani = jiffies + | 2127 | ah->ah_cal_next_ani = jiffies + |
2118 | msecs_to_jiffies(ATH5K_TUNE_CALIBRATION_INTERVAL_ANI); | 2128 | msecs_to_jiffies(ATH5K_TUNE_CALIBRATION_INTERVAL_ANI); |
2119 | tasklet_schedule(&ah->ani_tasklet); | 2129 | tasklet_schedule(&ah->ani_tasklet); |
2120 | 2130 | ||
2121 | } else if (time_is_before_eq_jiffies(ah->ah_cal_next_full)) { | 2131 | } else if (time_is_before_eq_jiffies(ah->ah_cal_next_short) && |
2122 | ah->ah_cal_next_full = jiffies + | 2132 | !(ah->ah_cal_mask & AR5K_CALIBRATION_FULL) && |
2123 | msecs_to_jiffies(ATH5K_TUNE_CALIBRATION_INTERVAL_FULL); | 2133 | !(ah->ah_cal_mask & AR5K_CALIBRATION_SHORT)) { |
2124 | tasklet_schedule(&ah->calib); | 2134 | |
2135 | /* Run calibration only when another calibration | ||
2136 | * is not running. | ||
2137 | * | ||
2138 | * Note: This is for both full/short calibration, | ||
2139 | * if it's time for a full one, ath5k_calibrate_work will deal | ||
2140 | * with it. */ | ||
2141 | |||
2142 | ah->ah_cal_next_short = jiffies + | ||
2143 | msecs_to_jiffies(ATH5K_TUNE_CALIBRATION_INTERVAL_SHORT); | ||
2144 | ieee80211_queue_work(ah->hw, &ah->calib_work); | ||
2125 | } | 2145 | } |
2126 | /* we could use SWI to generate enough interrupts to meet our | 2146 | /* we could use SWI to generate enough interrupts to meet our |
2127 | * calibration interval requirements, if necessary: | 2147 | * calibration interval requirements, if necessary: |
@@ -2149,69 +2169,110 @@ ath5k_intr(int irq, void *dev_id) | |||
2149 | enum ath5k_int status; | 2169 | enum ath5k_int status; |
2150 | unsigned int counter = 1000; | 2170 | unsigned int counter = 1000; |
2151 | 2171 | ||
2172 | |||
2173 | /* | ||
2174 | * If hw is not ready (or detached) and we get an | ||
2175 | * interrupt, or if we have no interrupts pending | ||
2176 | * (that means it's not for us) skip it. | ||
2177 | * | ||
2178 | * NOTE: Group 0/1 PCI interface registers are not | ||
2179 | * supported on WiSOCs, so we can't check for pending | ||
2180 | * interrupts (ISR belongs to another register group | ||
2181 | * so we are ok). | ||
2182 | */ | ||
2152 | if (unlikely(test_bit(ATH_STAT_INVALID, ah->status) || | 2183 | if (unlikely(test_bit(ATH_STAT_INVALID, ah->status) || |
2153 | ((ath5k_get_bus_type(ah) != ATH_AHB) && | 2184 | ((ath5k_get_bus_type(ah) != ATH_AHB) && |
2154 | !ath5k_hw_is_intr_pending(ah)))) | 2185 | !ath5k_hw_is_intr_pending(ah)))) |
2155 | return IRQ_NONE; | 2186 | return IRQ_NONE; |
2156 | 2187 | ||
2188 | /** Main loop **/ | ||
2157 | do { | 2189 | do { |
2158 | ath5k_hw_get_isr(ah, &status); /* NB: clears IRQ too */ | 2190 | ath5k_hw_get_isr(ah, &status); /* NB: clears IRQ too */ |
2191 | |||
2159 | ATH5K_DBG(ah, ATH5K_DEBUG_INTR, "status 0x%x/0x%x\n", | 2192 | ATH5K_DBG(ah, ATH5K_DEBUG_INTR, "status 0x%x/0x%x\n", |
2160 | status, ah->imask); | 2193 | status, ah->imask); |
2194 | |||
2195 | /* | ||
2196 | * Fatal hw error -> Log and reset | ||
2197 | * | ||
2198 | * Fatal errors are unrecoverable so we have to | ||
2199 | * reset the card. These errors include bus and | ||
2200 | * dma errors. | ||
2201 | */ | ||
2161 | if (unlikely(status & AR5K_INT_FATAL)) { | 2202 | if (unlikely(status & AR5K_INT_FATAL)) { |
2162 | /* | 2203 | |
2163 | * Fatal errors are unrecoverable. | ||
2164 | * Typically these are caused by DMA errors. | ||
2165 | */ | ||
2166 | ATH5K_DBG(ah, ATH5K_DEBUG_RESET, | 2204 | ATH5K_DBG(ah, ATH5K_DEBUG_RESET, |
2167 | "fatal int, resetting\n"); | 2205 | "fatal int, resetting\n"); |
2168 | ieee80211_queue_work(ah->hw, &ah->reset_work); | 2206 | ieee80211_queue_work(ah->hw, &ah->reset_work); |
2207 | |||
2208 | /* | ||
2209 | * RX Overrun -> Count and reset if needed | ||
2210 | * | ||
2211 | * Receive buffers are full. Either the bus is busy or | ||
2212 | * the CPU is not fast enough to process all received | ||
2213 | * frames. | ||
2214 | */ | ||
2169 | } else if (unlikely(status & AR5K_INT_RXORN)) { | 2215 | } else if (unlikely(status & AR5K_INT_RXORN)) { |
2216 | |||
2170 | /* | 2217 | /* |
2171 | * Receive buffers are full. Either the bus is busy or | ||
2172 | * the CPU is not fast enough to process all received | ||
2173 | * frames. | ||
2174 | * Older chipsets need a reset to come out of this | 2218 | * Older chipsets need a reset to come out of this |
2175 | * condition, but we treat it as RX for newer chips. | 2219 | * condition, but we treat it as RX for newer chips. |
2176 | * We don't know exactly which versions need a reset - | 2220 | * We don't know exactly which versions need a reset |
2177 | * this guess is copied from the HAL. | 2221 | * this guess is copied from the HAL. |
2178 | */ | 2222 | */ |
2179 | ah->stats.rxorn_intr++; | 2223 | ah->stats.rxorn_intr++; |
2224 | |||
2180 | if (ah->ah_mac_srev < AR5K_SREV_AR5212) { | 2225 | if (ah->ah_mac_srev < AR5K_SREV_AR5212) { |
2181 | ATH5K_DBG(ah, ATH5K_DEBUG_RESET, | 2226 | ATH5K_DBG(ah, ATH5K_DEBUG_RESET, |
2182 | "rx overrun, resetting\n"); | 2227 | "rx overrun, resetting\n"); |
2183 | ieee80211_queue_work(ah->hw, &ah->reset_work); | 2228 | ieee80211_queue_work(ah->hw, &ah->reset_work); |
2184 | } else | 2229 | } else |
2185 | ath5k_schedule_rx(ah); | 2230 | ath5k_schedule_rx(ah); |
2231 | |||
2186 | } else { | 2232 | } else { |
2233 | |||
2234 | /* Software Beacon Alert -> Schedule beacon tasklet */ | ||
2187 | if (status & AR5K_INT_SWBA) | 2235 | if (status & AR5K_INT_SWBA) |
2188 | tasklet_hi_schedule(&ah->beacontq); | 2236 | tasklet_hi_schedule(&ah->beacontq); |
2189 | 2237 | ||
2190 | if (status & AR5K_INT_RXEOL) { | 2238 | /* |
2191 | /* | 2239 | * No more RX descriptors -> Just count |
2192 | * NB: the hardware should re-read the link when | 2240 | * |
2193 | * RXE bit is written, but it doesn't work at | 2241 | * NB: the hardware should re-read the link when |
2194 | * least on older hardware revs. | 2242 | * RXE bit is written, but it doesn't work at |
2195 | */ | 2243 | * least on older hardware revs. |
2244 | */ | ||
2245 | if (status & AR5K_INT_RXEOL) | ||
2196 | ah->stats.rxeol_intr++; | 2246 | ah->stats.rxeol_intr++; |
2197 | } | 2247 | |
2198 | if (status & AR5K_INT_TXURN) { | 2248 | |
2199 | /* bump tx trigger level */ | 2249 | /* TX Underrun -> Bump tx trigger level */ |
2250 | if (status & AR5K_INT_TXURN) | ||
2200 | ath5k_hw_update_tx_triglevel(ah, true); | 2251 | ath5k_hw_update_tx_triglevel(ah, true); |
2201 | } | 2252 | |
2253 | /* RX -> Schedule rx tasklet */ | ||
2202 | if (status & (AR5K_INT_RXOK | AR5K_INT_RXERR)) | 2254 | if (status & (AR5K_INT_RXOK | AR5K_INT_RXERR)) |
2203 | ath5k_schedule_rx(ah); | 2255 | ath5k_schedule_rx(ah); |
2204 | if (status & (AR5K_INT_TXOK | AR5K_INT_TXDESC | 2256 | |
2205 | | AR5K_INT_TXERR | AR5K_INT_TXEOL)) | 2257 | /* TX -> Schedule tx tasklet */ |
2258 | if (status & (AR5K_INT_TXOK | ||
2259 | | AR5K_INT_TXDESC | ||
2260 | | AR5K_INT_TXERR | ||
2261 | | AR5K_INT_TXEOL)) | ||
2206 | ath5k_schedule_tx(ah); | 2262 | ath5k_schedule_tx(ah); |
2207 | if (status & AR5K_INT_BMISS) { | 2263 | |
2208 | /* TODO */ | 2264 | /* Missed beacon -> TODO |
2209 | } | 2265 | if (status & AR5K_INT_BMISS) |
2266 | */ | ||
2267 | |||
2268 | /* MIB event -> Update counters and notify ANI */ | ||
2210 | if (status & AR5K_INT_MIB) { | 2269 | if (status & AR5K_INT_MIB) { |
2211 | ah->stats.mib_intr++; | 2270 | ah->stats.mib_intr++; |
2212 | ath5k_hw_update_mib_counters(ah); | 2271 | ath5k_hw_update_mib_counters(ah); |
2213 | ath5k_ani_mib_intr(ah); | 2272 | ath5k_ani_mib_intr(ah); |
2214 | } | 2273 | } |
2274 | |||
2275 | /* GPIO -> Notify RFKill layer */ | ||
2215 | if (status & AR5K_INT_GPIO) | 2276 | if (status & AR5K_INT_GPIO) |
2216 | tasklet_schedule(&ah->rf_kill.toggleq); | 2277 | tasklet_schedule(&ah->rf_kill.toggleq); |
2217 | 2278 | ||
@@ -2222,12 +2283,19 @@ ath5k_intr(int irq, void *dev_id) | |||
2222 | 2283 | ||
2223 | } while (ath5k_hw_is_intr_pending(ah) && --counter > 0); | 2284 | } while (ath5k_hw_is_intr_pending(ah) && --counter > 0); |
2224 | 2285 | ||
2286 | /* | ||
2287 | * Until we handle rx/tx interrupts mask them on IMR | ||
2288 | * | ||
2289 | * NOTE: ah->(rx/tx)_pending are set when scheduling the tasklets | ||
2290 | * and unset after we 've handled the interrupts. | ||
2291 | */ | ||
2225 | if (ah->rx_pending || ah->tx_pending) | 2292 | if (ah->rx_pending || ah->tx_pending) |
2226 | ath5k_set_current_imask(ah); | 2293 | ath5k_set_current_imask(ah); |
2227 | 2294 | ||
2228 | if (unlikely(!counter)) | 2295 | if (unlikely(!counter)) |
2229 | ATH5K_WARN(ah, "too many interrupts, giving up for now\n"); | 2296 | ATH5K_WARN(ah, "too many interrupts, giving up for now\n"); |
2230 | 2297 | ||
2298 | /* Fire up calibration poll */ | ||
2231 | ath5k_intr_calibration_poll(ah); | 2299 | ath5k_intr_calibration_poll(ah); |
2232 | 2300 | ||
2233 | return IRQ_HANDLED; | 2301 | return IRQ_HANDLED; |
@@ -2238,41 +2306,58 @@ ath5k_intr(int irq, void *dev_id) | |||
2238 | * for temperature/environment changes. | 2306 | * for temperature/environment changes. |
2239 | */ | 2307 | */ |
2240 | static void | 2308 | static void |
2241 | ath5k_tasklet_calibrate(unsigned long data) | 2309 | ath5k_calibrate_work(struct work_struct *work) |
2242 | { | 2310 | { |
2243 | struct ath5k_hw *ah = (void *)data; | 2311 | struct ath5k_hw *ah = container_of(work, struct ath5k_hw, |
2312 | calib_work); | ||
2313 | |||
2314 | /* Should we run a full calibration ? */ | ||
2315 | if (time_is_before_eq_jiffies(ah->ah_cal_next_full)) { | ||
2316 | |||
2317 | ah->ah_cal_next_full = jiffies + | ||
2318 | msecs_to_jiffies(ATH5K_TUNE_CALIBRATION_INTERVAL_FULL); | ||
2319 | ah->ah_cal_mask |= AR5K_CALIBRATION_FULL; | ||
2320 | |||
2321 | ATH5K_DBG(ah, ATH5K_DEBUG_CALIBRATE, | ||
2322 | "running full calibration\n"); | ||
2323 | |||
2324 | if (ath5k_hw_gainf_calibrate(ah) == AR5K_RFGAIN_NEED_CHANGE) { | ||
2325 | /* | ||
2326 | * Rfgain is out of bounds, reset the chip | ||
2327 | * to load new gain values. | ||
2328 | */ | ||
2329 | ATH5K_DBG(ah, ATH5K_DEBUG_RESET, | ||
2330 | "got new rfgain, resetting\n"); | ||
2331 | ieee80211_queue_work(ah->hw, &ah->reset_work); | ||
2332 | } | ||
2333 | |||
2334 | /* TODO: On full calibration we should stop TX here, | ||
2335 | * so that it doesn't interfere (mostly due to gain_f | ||
2336 | * calibration that messes with tx packets -see phy.c). | ||
2337 | * | ||
2338 | * NOTE: Stopping the queues from above is not enough | ||
2339 | * to stop TX but saves us from disconecting (at least | ||
2340 | * we don't lose packets). */ | ||
2341 | ieee80211_stop_queues(ah->hw); | ||
2342 | } else | ||
2343 | ah->ah_cal_mask |= AR5K_CALIBRATION_SHORT; | ||
2244 | 2344 | ||
2245 | /* Only full calibration for now */ | ||
2246 | ah->ah_cal_mask |= AR5K_CALIBRATION_FULL; | ||
2247 | 2345 | ||
2248 | ATH5K_DBG(ah, ATH5K_DEBUG_CALIBRATE, "channel %u/%x\n", | 2346 | ATH5K_DBG(ah, ATH5K_DEBUG_CALIBRATE, "channel %u/%x\n", |
2249 | ieee80211_frequency_to_channel(ah->curchan->center_freq), | 2347 | ieee80211_frequency_to_channel(ah->curchan->center_freq), |
2250 | ah->curchan->hw_value); | 2348 | ah->curchan->hw_value); |
2251 | 2349 | ||
2252 | if (ath5k_hw_gainf_calibrate(ah) == AR5K_RFGAIN_NEED_CHANGE) { | ||
2253 | /* | ||
2254 | * Rfgain is out of bounds, reset the chip | ||
2255 | * to load new gain values. | ||
2256 | */ | ||
2257 | ATH5K_DBG(ah, ATH5K_DEBUG_RESET, "calibration, resetting\n"); | ||
2258 | ieee80211_queue_work(ah->hw, &ah->reset_work); | ||
2259 | } | ||
2260 | if (ath5k_hw_phy_calibrate(ah, ah->curchan)) | 2350 | if (ath5k_hw_phy_calibrate(ah, ah->curchan)) |
2261 | ATH5K_ERR(ah, "calibration of channel %u failed\n", | 2351 | ATH5K_ERR(ah, "calibration of channel %u failed\n", |
2262 | ieee80211_frequency_to_channel( | 2352 | ieee80211_frequency_to_channel( |
2263 | ah->curchan->center_freq)); | 2353 | ah->curchan->center_freq)); |
2264 | 2354 | ||
2265 | /* Noise floor calibration interrupts rx/tx path while I/Q calibration | 2355 | /* Clear calibration flags */ |
2266 | * doesn't. | 2356 | if (ah->ah_cal_mask & AR5K_CALIBRATION_FULL) { |
2267 | * TODO: We should stop TX here, so that it doesn't interfere. | 2357 | ieee80211_wake_queues(ah->hw); |
2268 | * Note that stopping the queues is not enough to stop TX! */ | 2358 | ah->ah_cal_mask &= ~AR5K_CALIBRATION_FULL; |
2269 | if (time_is_before_eq_jiffies(ah->ah_cal_next_nf)) { | 2359 | } else if (ah->ah_cal_mask & AR5K_CALIBRATION_SHORT) |
2270 | ah->ah_cal_next_nf = jiffies + | 2360 | ah->ah_cal_mask &= ~AR5K_CALIBRATION_SHORT; |
2271 | msecs_to_jiffies(ATH5K_TUNE_CALIBRATION_INTERVAL_NF); | ||
2272 | ath5k_hw_update_noise_floor(ah); | ||
2273 | } | ||
2274 | |||
2275 | ah->ah_cal_mask &= ~AR5K_CALIBRATION_FULL; | ||
2276 | } | 2361 | } |
2277 | 2362 | ||
2278 | 2363 | ||
@@ -2407,8 +2492,8 @@ ath5k_init_ah(struct ath5k_hw *ah, const struct ath_bus_ops *bus_ops) | |||
2407 | if (ret) | 2492 | if (ret) |
2408 | goto err_irq; | 2493 | goto err_irq; |
2409 | 2494 | ||
2410 | /* set up multi-rate retry capabilities */ | 2495 | /* Set up multi-rate retry capabilities */ |
2411 | if (ah->ah_version == AR5K_AR5212) { | 2496 | if (ah->ah_capabilities.cap_has_mrr_support) { |
2412 | hw->max_rates = 4; | 2497 | hw->max_rates = 4; |
2413 | hw->max_rate_tries = max(AR5K_INIT_RETRY_SHORT, | 2498 | hw->max_rate_tries = max(AR5K_INIT_RETRY_SHORT, |
2414 | AR5K_INIT_RETRY_LONG); | 2499 | AR5K_INIT_RETRY_LONG); |
@@ -2544,15 +2629,22 @@ int ath5k_start(struct ieee80211_hw *hw) | |||
2544 | * and then setup of the interrupt mask. | 2629 | * and then setup of the interrupt mask. |
2545 | */ | 2630 | */ |
2546 | ah->curchan = ah->hw->conf.channel; | 2631 | ah->curchan = ah->hw->conf.channel; |
2547 | ah->imask = AR5K_INT_RXOK | AR5K_INT_RXERR | AR5K_INT_RXEOL | | 2632 | ah->imask = AR5K_INT_RXOK |
2548 | AR5K_INT_RXORN | AR5K_INT_TXDESC | AR5K_INT_TXEOL | | 2633 | | AR5K_INT_RXERR |
2549 | AR5K_INT_FATAL | AR5K_INT_GLOBAL | AR5K_INT_MIB; | 2634 | | AR5K_INT_RXEOL |
2635 | | AR5K_INT_RXORN | ||
2636 | | AR5K_INT_TXDESC | ||
2637 | | AR5K_INT_TXEOL | ||
2638 | | AR5K_INT_FATAL | ||
2639 | | AR5K_INT_GLOBAL | ||
2640 | | AR5K_INT_MIB; | ||
2550 | 2641 | ||
2551 | ret = ath5k_reset(ah, NULL, false); | 2642 | ret = ath5k_reset(ah, NULL, false); |
2552 | if (ret) | 2643 | if (ret) |
2553 | goto done; | 2644 | goto done; |
2554 | 2645 | ||
2555 | ath5k_rfkill_hw_start(ah); | 2646 | if (!ath5k_modparam_no_hw_rfkill_switch) |
2647 | ath5k_rfkill_hw_start(ah); | ||
2556 | 2648 | ||
2557 | /* | 2649 | /* |
2558 | * Reset the key cache since some parts do not reset the | 2650 | * Reset the key cache since some parts do not reset the |
@@ -2585,7 +2677,6 @@ static void ath5k_stop_tasklets(struct ath5k_hw *ah) | |||
2585 | ah->tx_pending = false; | 2677 | ah->tx_pending = false; |
2586 | tasklet_kill(&ah->rxtq); | 2678 | tasklet_kill(&ah->rxtq); |
2587 | tasklet_kill(&ah->txtq); | 2679 | tasklet_kill(&ah->txtq); |
2588 | tasklet_kill(&ah->calib); | ||
2589 | tasklet_kill(&ah->beacontq); | 2680 | tasklet_kill(&ah->beacontq); |
2590 | tasklet_kill(&ah->ani_tasklet); | 2681 | tasklet_kill(&ah->ani_tasklet); |
2591 | } | 2682 | } |
@@ -2637,7 +2728,8 @@ void ath5k_stop(struct ieee80211_hw *hw) | |||
2637 | 2728 | ||
2638 | cancel_delayed_work_sync(&ah->tx_complete_work); | 2729 | cancel_delayed_work_sync(&ah->tx_complete_work); |
2639 | 2730 | ||
2640 | ath5k_rfkill_hw_stop(ah); | 2731 | if (!ath5k_modparam_no_hw_rfkill_switch) |
2732 | ath5k_rfkill_hw_stop(ah); | ||
2641 | } | 2733 | } |
2642 | 2734 | ||
2643 | /* | 2735 | /* |
@@ -2689,9 +2781,24 @@ ath5k_reset(struct ath5k_hw *ah, struct ieee80211_channel *chan, | |||
2689 | 2781 | ||
2690 | ath5k_ani_init(ah, ani_mode); | 2782 | ath5k_ani_init(ah, ani_mode); |
2691 | 2783 | ||
2692 | ah->ah_cal_next_full = jiffies + msecs_to_jiffies(100); | 2784 | /* |
2693 | ah->ah_cal_next_ani = jiffies; | 2785 | * Set calibration intervals |
2694 | ah->ah_cal_next_nf = jiffies; | 2786 | * |
2787 | * Note: We don't need to run calibration imediately | ||
2788 | * since some initial calibration is done on reset | ||
2789 | * even for fast channel switching. Also on scanning | ||
2790 | * this will get set again and again and it won't get | ||
2791 | * executed unless we connect somewhere and spend some | ||
2792 | * time on the channel (that's what calibration needs | ||
2793 | * anyway to be accurate). | ||
2794 | */ | ||
2795 | ah->ah_cal_next_full = jiffies + | ||
2796 | msecs_to_jiffies(ATH5K_TUNE_CALIBRATION_INTERVAL_FULL); | ||
2797 | ah->ah_cal_next_ani = jiffies + | ||
2798 | msecs_to_jiffies(ATH5K_TUNE_CALIBRATION_INTERVAL_ANI); | ||
2799 | ah->ah_cal_next_short = jiffies + | ||
2800 | msecs_to_jiffies(ATH5K_TUNE_CALIBRATION_INTERVAL_SHORT); | ||
2801 | |||
2695 | ewma_init(&ah->ah_beacon_rssi_avg, 1024, 8); | 2802 | ewma_init(&ah->ah_beacon_rssi_avg, 1024, 8); |
2696 | 2803 | ||
2697 | /* clear survey data and cycle counters */ | 2804 | /* clear survey data and cycle counters */ |
@@ -2745,20 +2852,6 @@ ath5k_init(struct ieee80211_hw *hw) | |||
2745 | 2852 | ||
2746 | 2853 | ||
2747 | /* | 2854 | /* |
2748 | * Check if the MAC has multi-rate retry support. | ||
2749 | * We do this by trying to setup a fake extended | ||
2750 | * descriptor. MACs that don't have support will | ||
2751 | * return false w/o doing anything. MACs that do | ||
2752 | * support it will return true w/o doing anything. | ||
2753 | */ | ||
2754 | ret = ath5k_hw_setup_mrr_tx_desc(ah, NULL, 0, 0, 0, 0, 0, 0); | ||
2755 | |||
2756 | if (ret < 0) | ||
2757 | goto err; | ||
2758 | if (ret > 0) | ||
2759 | __set_bit(ATH_STAT_MRRETRY, ah->status); | ||
2760 | |||
2761 | /* | ||
2762 | * Collect the channel list. The 802.11 layer | 2855 | * Collect the channel list. The 802.11 layer |
2763 | * is responsible for filtering this list based | 2856 | * is responsible for filtering this list based |
2764 | * on settings like the phy mode and regulatory | 2857 | * on settings like the phy mode and regulatory |
@@ -2841,11 +2934,11 @@ ath5k_init(struct ieee80211_hw *hw) | |||
2841 | 2934 | ||
2842 | tasklet_init(&ah->rxtq, ath5k_tasklet_rx, (unsigned long)ah); | 2935 | tasklet_init(&ah->rxtq, ath5k_tasklet_rx, (unsigned long)ah); |
2843 | tasklet_init(&ah->txtq, ath5k_tasklet_tx, (unsigned long)ah); | 2936 | tasklet_init(&ah->txtq, ath5k_tasklet_tx, (unsigned long)ah); |
2844 | tasklet_init(&ah->calib, ath5k_tasklet_calibrate, (unsigned long)ah); | ||
2845 | tasklet_init(&ah->beacontq, ath5k_tasklet_beacon, (unsigned long)ah); | 2937 | tasklet_init(&ah->beacontq, ath5k_tasklet_beacon, (unsigned long)ah); |
2846 | tasklet_init(&ah->ani_tasklet, ath5k_tasklet_ani, (unsigned long)ah); | 2938 | tasklet_init(&ah->ani_tasklet, ath5k_tasklet_ani, (unsigned long)ah); |
2847 | 2939 | ||
2848 | INIT_WORK(&ah->reset_work, ath5k_reset_work); | 2940 | INIT_WORK(&ah->reset_work, ath5k_reset_work); |
2941 | INIT_WORK(&ah->calib_work, ath5k_calibrate_work); | ||
2849 | INIT_DELAYED_WORK(&ah->tx_complete_work, ath5k_tx_complete_poll_work); | 2942 | INIT_DELAYED_WORK(&ah->tx_complete_work, ath5k_tx_complete_poll_work); |
2850 | 2943 | ||
2851 | ret = ath5k_hw_common(ah)->bus_ops->eeprom_read_mac(ah, mac); | 2944 | ret = ath5k_hw_common(ah)->bus_ops->eeprom_read_mac(ah, mac); |
diff --git a/drivers/net/wireless/ath/ath5k/caps.c b/drivers/net/wireless/ath/ath5k/caps.c index 810fba96702b..994169ad39cb 100644 --- a/drivers/net/wireless/ath/ath5k/caps.c +++ b/drivers/net/wireless/ath/ath5k/caps.c | |||
@@ -85,12 +85,19 @@ int ath5k_hw_set_capabilities(struct ath5k_hw *ah) | |||
85 | caps->cap_range.range_2ghz_min = 2412; | 85 | caps->cap_range.range_2ghz_min = 2412; |
86 | caps->cap_range.range_2ghz_max = 2732; | 86 | caps->cap_range.range_2ghz_max = 2732; |
87 | 87 | ||
88 | if (AR5K_EEPROM_HDR_11B(ee_header)) | 88 | /* Override 2GHz modes on SoCs that need it |
89 | __set_bit(AR5K_MODE_11B, caps->cap_mode); | 89 | * NOTE: cap_needs_2GHz_ovr gets set from |
90 | 90 | * ath_ahb_probe */ | |
91 | if (AR5K_EEPROM_HDR_11G(ee_header) && | 91 | if (!caps->cap_needs_2GHz_ovr) { |
92 | ah->ah_version != AR5K_AR5211) | 92 | if (AR5K_EEPROM_HDR_11B(ee_header)) |
93 | __set_bit(AR5K_MODE_11G, caps->cap_mode); | 93 | __set_bit(AR5K_MODE_11B, |
94 | caps->cap_mode); | ||
95 | |||
96 | if (AR5K_EEPROM_HDR_11G(ee_header) && | ||
97 | ah->ah_version != AR5K_AR5211) | ||
98 | __set_bit(AR5K_MODE_11G, | ||
99 | caps->cap_mode); | ||
100 | } | ||
94 | } | 101 | } |
95 | } | 102 | } |
96 | 103 | ||
@@ -103,12 +110,18 @@ int ath5k_hw_set_capabilities(struct ath5k_hw *ah) | |||
103 | else | 110 | else |
104 | caps->cap_queues.q_tx_num = AR5K_NUM_TX_QUEUES; | 111 | caps->cap_queues.q_tx_num = AR5K_NUM_TX_QUEUES; |
105 | 112 | ||
106 | /* newer hardware has PHY error counters */ | 113 | /* Newer hardware has PHY error counters */ |
107 | if (ah->ah_mac_srev >= AR5K_SREV_AR5213A) | 114 | if (ah->ah_mac_srev >= AR5K_SREV_AR5213A) |
108 | caps->cap_has_phyerr_counters = true; | 115 | caps->cap_has_phyerr_counters = true; |
109 | else | 116 | else |
110 | caps->cap_has_phyerr_counters = false; | 117 | caps->cap_has_phyerr_counters = false; |
111 | 118 | ||
119 | /* MACs since AR5212 have MRR support */ | ||
120 | if (ah->ah_version == AR5K_AR5212) | ||
121 | caps->cap_has_mrr_support = true; | ||
122 | else | ||
123 | caps->cap_has_mrr_support = false; | ||
124 | |||
112 | return 0; | 125 | return 0; |
113 | } | 126 | } |
114 | 127 | ||
diff --git a/drivers/net/wireless/ath/ath5k/debug.c b/drivers/net/wireless/ath/ath5k/debug.c index fce8c904eea9..8c5ce8b0c734 100644 --- a/drivers/net/wireless/ath/ath5k/debug.c +++ b/drivers/net/wireless/ath/ath5k/debug.c | |||
@@ -57,8 +57,9 @@ | |||
57 | * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF | 57 | * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF |
58 | * THE POSSIBILITY OF SUCH DAMAGES. | 58 | * THE POSSIBILITY OF SUCH DAMAGES. |
59 | */ | 59 | */ |
60 | #include <linux/export.h> | ||
61 | #include <linux/moduleparam.h> | ||
60 | 62 | ||
61 | #include <linux/module.h> | ||
62 | #include <linux/seq_file.h> | 63 | #include <linux/seq_file.h> |
63 | #include <linux/list.h> | 64 | #include <linux/list.h> |
64 | #include "debug.h" | 65 | #include "debug.h" |
diff --git a/drivers/net/wireless/ath/ath5k/debug.h b/drivers/net/wireless/ath/ath5k/debug.h index 7f37df3125fd..0a3f916a1ef3 100644 --- a/drivers/net/wireless/ath/ath5k/debug.h +++ b/drivers/net/wireless/ath/ath5k/debug.h | |||
@@ -141,10 +141,10 @@ ath5k_debug_printtxbuf(struct ath5k_hw *ah, struct ath5k_buf *bf); | |||
141 | 141 | ||
142 | #include <linux/compiler.h> | 142 | #include <linux/compiler.h> |
143 | 143 | ||
144 | static inline void __attribute__ ((format (printf, 3, 4))) | 144 | static inline __printf(3, 4) void |
145 | ATH5K_DBG(struct ath5k_hw *ah, unsigned int m, const char *fmt, ...) {} | 145 | ATH5K_DBG(struct ath5k_hw *ah, unsigned int m, const char *fmt, ...) {} |
146 | 146 | ||
147 | static inline void __attribute__ ((format (printf, 3, 4))) | 147 | static inline __printf(3, 4) void |
148 | ATH5K_DBG_UNLIMIT(struct ath5k_hw *ah, unsigned int m, const char *fmt, ...) | 148 | ATH5K_DBG_UNLIMIT(struct ath5k_hw *ah, unsigned int m, const char *fmt, ...) |
149 | {} | 149 | {} |
150 | 150 | ||
diff --git a/drivers/net/wireless/ath/ath5k/desc.c b/drivers/net/wireless/ath/ath5k/desc.c index 7e88dda82221..f8bfa3ac2af0 100644 --- a/drivers/net/wireless/ath/ath5k/desc.c +++ b/drivers/net/wireless/ath/ath5k/desc.c | |||
@@ -26,20 +26,61 @@ | |||
26 | #include "debug.h" | 26 | #include "debug.h" |
27 | 27 | ||
28 | 28 | ||
29 | /** | ||
30 | * DOC: Hardware descriptor functions | ||
31 | * | ||
32 | * Here we handle the processing of the low-level hw descriptors | ||
33 | * that hw reads and writes via DMA for each TX and RX attempt (that means | ||
34 | * we can also have descriptors for failed TX/RX tries). We have two kind of | ||
35 | * descriptors for RX and TX, control descriptors tell the hw how to send or | ||
36 | * receive a packet where to read/write it from/to etc and status descriptors | ||
37 | * that contain information about how the packet was sent or received (errors | ||
38 | * included). | ||
39 | * | ||
40 | * Descriptor format is not exactly the same for each MAC chip version so we | ||
41 | * have function pointers on &struct ath5k_hw we initialize at runtime based on | ||
42 | * the chip used. | ||
43 | */ | ||
44 | |||
45 | |||
29 | /************************\ | 46 | /************************\ |
30 | * TX Control descriptors * | 47 | * TX Control descriptors * |
31 | \************************/ | 48 | \************************/ |
32 | 49 | ||
33 | /* | 50 | /** |
34 | * Initialize the 2-word tx control descriptor on 5210/5211 | 51 | * ath5k_hw_setup_2word_tx_desc() - Initialize a 2-word tx control descriptor |
52 | * @ah: The &struct ath5k_hw | ||
53 | * @desc: The &struct ath5k_desc | ||
54 | * @pkt_len: Frame length in bytes | ||
55 | * @hdr_len: Header length in bytes (only used on AR5210) | ||
56 | * @padsize: Any padding we've added to the frame length | ||
57 | * @type: One of enum ath5k_pkt_type | ||
58 | * @tx_power: Tx power in 0.5dB steps | ||
59 | * @tx_rate0: HW idx for transmission rate | ||
60 | * @tx_tries0: Max number of retransmissions | ||
61 | * @key_index: Index on key table to use for encryption | ||
62 | * @antenna_mode: Which antenna to use (0 for auto) | ||
63 | * @flags: One of AR5K_TXDESC_* flags (desc.h) | ||
64 | * @rtscts_rate: HW idx for RTS/CTS transmission rate | ||
65 | * @rtscts_duration: What to put on duration field on the header of RTS/CTS | ||
66 | * | ||
67 | * Internal function to initialize a 2-Word TX control descriptor | ||
68 | * found on AR5210 and AR5211 MACs chips. | ||
69 | * | ||
70 | * Returns 0 on success or -EINVAL on false input | ||
35 | */ | 71 | */ |
36 | static int | 72 | static int |
37 | ath5k_hw_setup_2word_tx_desc(struct ath5k_hw *ah, struct ath5k_desc *desc, | 73 | ath5k_hw_setup_2word_tx_desc(struct ath5k_hw *ah, |
38 | unsigned int pkt_len, unsigned int hdr_len, int padsize, | 74 | struct ath5k_desc *desc, |
39 | enum ath5k_pkt_type type, | 75 | unsigned int pkt_len, unsigned int hdr_len, |
40 | unsigned int tx_power, unsigned int tx_rate0, unsigned int tx_tries0, | 76 | int padsize, |
41 | unsigned int key_index, unsigned int antenna_mode, unsigned int flags, | 77 | enum ath5k_pkt_type type, |
42 | unsigned int rtscts_rate, unsigned int rtscts_duration) | 78 | unsigned int tx_power, |
79 | unsigned int tx_rate0, unsigned int tx_tries0, | ||
80 | unsigned int key_index, | ||
81 | unsigned int antenna_mode, | ||
82 | unsigned int flags, | ||
83 | unsigned int rtscts_rate, unsigned int rtscts_duration) | ||
43 | { | 84 | { |
44 | u32 frame_type; | 85 | u32 frame_type; |
45 | struct ath5k_hw_2w_tx_ctl *tx_ctl; | 86 | struct ath5k_hw_2w_tx_ctl *tx_ctl; |
@@ -172,17 +213,40 @@ ath5k_hw_setup_2word_tx_desc(struct ath5k_hw *ah, struct ath5k_desc *desc, | |||
172 | return 0; | 213 | return 0; |
173 | } | 214 | } |
174 | 215 | ||
175 | /* | 216 | /** |
176 | * Initialize the 4-word tx control descriptor on 5212 | 217 | * ath5k_hw_setup_4word_tx_desc() - Initialize a 4-word tx control descriptor |
218 | * @ah: The &struct ath5k_hw | ||
219 | * @desc: The &struct ath5k_desc | ||
220 | * @pkt_len: Frame length in bytes | ||
221 | * @hdr_len: Header length in bytes (only used on AR5210) | ||
222 | * @padsize: Any padding we've added to the frame length | ||
223 | * @type: One of enum ath5k_pkt_type | ||
224 | * @tx_power: Tx power in 0.5dB steps | ||
225 | * @tx_rate0: HW idx for transmission rate | ||
226 | * @tx_tries0: Max number of retransmissions | ||
227 | * @key_index: Index on key table to use for encryption | ||
228 | * @antenna_mode: Which antenna to use (0 for auto) | ||
229 | * @flags: One of AR5K_TXDESC_* flags (desc.h) | ||
230 | * @rtscts_rate: HW idx for RTS/CTS transmission rate | ||
231 | * @rtscts_duration: What to put on duration field on the header of RTS/CTS | ||
232 | * | ||
233 | * Internal function to initialize a 4-Word TX control descriptor | ||
234 | * found on AR5212 and later MACs chips. | ||
235 | * | ||
236 | * Returns 0 on success or -EINVAL on false input | ||
177 | */ | 237 | */ |
178 | static int ath5k_hw_setup_4word_tx_desc(struct ath5k_hw *ah, | 238 | static int |
179 | struct ath5k_desc *desc, unsigned int pkt_len, unsigned int hdr_len, | 239 | ath5k_hw_setup_4word_tx_desc(struct ath5k_hw *ah, |
180 | int padsize, | 240 | struct ath5k_desc *desc, |
181 | enum ath5k_pkt_type type, unsigned int tx_power, unsigned int tx_rate0, | 241 | unsigned int pkt_len, unsigned int hdr_len, |
182 | unsigned int tx_tries0, unsigned int key_index, | 242 | int padsize, |
183 | unsigned int antenna_mode, unsigned int flags, | 243 | enum ath5k_pkt_type type, |
184 | unsigned int rtscts_rate, | 244 | unsigned int tx_power, |
185 | unsigned int rtscts_duration) | 245 | unsigned int tx_rate0, unsigned int tx_tries0, |
246 | unsigned int key_index, | ||
247 | unsigned int antenna_mode, | ||
248 | unsigned int flags, | ||
249 | unsigned int rtscts_rate, unsigned int rtscts_duration) | ||
186 | { | 250 | { |
187 | struct ath5k_hw_4w_tx_ctl *tx_ctl; | 251 | struct ath5k_hw_4w_tx_ctl *tx_ctl; |
188 | unsigned int frame_len; | 252 | unsigned int frame_len; |
@@ -292,13 +356,29 @@ static int ath5k_hw_setup_4word_tx_desc(struct ath5k_hw *ah, | |||
292 | return 0; | 356 | return 0; |
293 | } | 357 | } |
294 | 358 | ||
295 | /* | 359 | /** |
296 | * Initialize a 4-word multi rate retry tx control descriptor on 5212 | 360 | * ath5k_hw_setup_mrr_tx_desc() - Initialize an MRR tx control descriptor |
361 | * @ah: The &struct ath5k_hw | ||
362 | * @desc: The &struct ath5k_desc | ||
363 | * @tx_rate1: HW idx for rate used on transmission series 1 | ||
364 | * @tx_tries1: Max number of retransmissions for transmission series 1 | ||
365 | * @tx_rate2: HW idx for rate used on transmission series 2 | ||
366 | * @tx_tries2: Max number of retransmissions for transmission series 2 | ||
367 | * @tx_rate3: HW idx for rate used on transmission series 3 | ||
368 | * @tx_tries3: Max number of retransmissions for transmission series 3 | ||
369 | * | ||
370 | * Multi rate retry (MRR) tx control descriptors are available only on AR5212 | ||
371 | * MACs, they are part of the normal 4-word tx control descriptor (see above) | ||
372 | * but we handle them through a separate function for better abstraction. | ||
373 | * | ||
374 | * Returns 0 on success or -EINVAL on invalid input | ||
297 | */ | 375 | */ |
298 | int | 376 | int |
299 | ath5k_hw_setup_mrr_tx_desc(struct ath5k_hw *ah, struct ath5k_desc *desc, | 377 | ath5k_hw_setup_mrr_tx_desc(struct ath5k_hw *ah, |
300 | unsigned int tx_rate1, u_int tx_tries1, u_int tx_rate2, | 378 | struct ath5k_desc *desc, |
301 | u_int tx_tries2, unsigned int tx_rate3, u_int tx_tries3) | 379 | u_int tx_rate1, u_int tx_tries1, |
380 | u_int tx_rate2, u_int tx_tries2, | ||
381 | u_int tx_rate3, u_int tx_tries3) | ||
302 | { | 382 | { |
303 | struct ath5k_hw_4w_tx_ctl *tx_ctl; | 383 | struct ath5k_hw_4w_tx_ctl *tx_ctl; |
304 | 384 | ||
@@ -350,11 +430,16 @@ ath5k_hw_setup_mrr_tx_desc(struct ath5k_hw *ah, struct ath5k_desc *desc, | |||
350 | * TX Status descriptors * | 430 | * TX Status descriptors * |
351 | \***********************/ | 431 | \***********************/ |
352 | 432 | ||
353 | /* | 433 | /** |
354 | * Process the tx status descriptor on 5210/5211 | 434 | * ath5k_hw_proc_2word_tx_status() - Process a tx status descriptor on 5210/1 |
435 | * @ah: The &struct ath5k_hw | ||
436 | * @desc: The &struct ath5k_desc | ||
437 | * @ts: The &struct ath5k_tx_status | ||
355 | */ | 438 | */ |
356 | static int ath5k_hw_proc_2word_tx_status(struct ath5k_hw *ah, | 439 | static int |
357 | struct ath5k_desc *desc, struct ath5k_tx_status *ts) | 440 | ath5k_hw_proc_2word_tx_status(struct ath5k_hw *ah, |
441 | struct ath5k_desc *desc, | ||
442 | struct ath5k_tx_status *ts) | ||
358 | { | 443 | { |
359 | struct ath5k_hw_2w_tx_ctl *tx_ctl; | 444 | struct ath5k_hw_2w_tx_ctl *tx_ctl; |
360 | struct ath5k_hw_tx_status *tx_status; | 445 | struct ath5k_hw_tx_status *tx_status; |
@@ -399,11 +484,16 @@ static int ath5k_hw_proc_2word_tx_status(struct ath5k_hw *ah, | |||
399 | return 0; | 484 | return 0; |
400 | } | 485 | } |
401 | 486 | ||
402 | /* | 487 | /** |
403 | * Process a tx status descriptor on 5212 | 488 | * ath5k_hw_proc_4word_tx_status() - Process a tx status descriptor on 5212 |
489 | * @ah: The &struct ath5k_hw | ||
490 | * @desc: The &struct ath5k_desc | ||
491 | * @ts: The &struct ath5k_tx_status | ||
404 | */ | 492 | */ |
405 | static int ath5k_hw_proc_4word_tx_status(struct ath5k_hw *ah, | 493 | static int |
406 | struct ath5k_desc *desc, struct ath5k_tx_status *ts) | 494 | ath5k_hw_proc_4word_tx_status(struct ath5k_hw *ah, |
495 | struct ath5k_desc *desc, | ||
496 | struct ath5k_tx_status *ts) | ||
407 | { | 497 | { |
408 | struct ath5k_hw_4w_tx_ctl *tx_ctl; | 498 | struct ath5k_hw_4w_tx_ctl *tx_ctl; |
409 | struct ath5k_hw_tx_status *tx_status; | 499 | struct ath5k_hw_tx_status *tx_status; |
@@ -460,11 +550,17 @@ static int ath5k_hw_proc_4word_tx_status(struct ath5k_hw *ah, | |||
460 | * RX Descriptors * | 550 | * RX Descriptors * |
461 | \****************/ | 551 | \****************/ |
462 | 552 | ||
463 | /* | 553 | /** |
464 | * Initialize an rx control descriptor | 554 | * ath5k_hw_setup_rx_desc() - Initialize an rx control descriptor |
555 | * @ah: The &struct ath5k_hw | ||
556 | * @desc: The &struct ath5k_desc | ||
557 | * @size: RX buffer length in bytes | ||
558 | * @flags: One of AR5K_RXDESC_* flags | ||
465 | */ | 559 | */ |
466 | int ath5k_hw_setup_rx_desc(struct ath5k_hw *ah, struct ath5k_desc *desc, | 560 | int |
467 | u32 size, unsigned int flags) | 561 | ath5k_hw_setup_rx_desc(struct ath5k_hw *ah, |
562 | struct ath5k_desc *desc, | ||
563 | u32 size, unsigned int flags) | ||
468 | { | 564 | { |
469 | struct ath5k_hw_rx_ctl *rx_ctl; | 565 | struct ath5k_hw_rx_ctl *rx_ctl; |
470 | 566 | ||
@@ -491,11 +587,22 @@ int ath5k_hw_setup_rx_desc(struct ath5k_hw *ah, struct ath5k_desc *desc, | |||
491 | return 0; | 587 | return 0; |
492 | } | 588 | } |
493 | 589 | ||
494 | /* | 590 | /** |
495 | * Process the rx status descriptor on 5210/5211 | 591 | * ath5k_hw_proc_5210_rx_status() - Process the rx status descriptor on 5210/1 |
592 | * @ah: The &struct ath5k_hw | ||
593 | * @desc: The &struct ath5k_desc | ||
594 | * @rs: The &struct ath5k_rx_status | ||
595 | * | ||
596 | * Internal function used to process an RX status descriptor | ||
597 | * on AR5210/5211 MAC. | ||
598 | * | ||
599 | * Returns 0 on success or -EINPROGRESS in case we haven't received the who;e | ||
600 | * frame yet. | ||
496 | */ | 601 | */ |
497 | static int ath5k_hw_proc_5210_rx_status(struct ath5k_hw *ah, | 602 | static int |
498 | struct ath5k_desc *desc, struct ath5k_rx_status *rs) | 603 | ath5k_hw_proc_5210_rx_status(struct ath5k_hw *ah, |
604 | struct ath5k_desc *desc, | ||
605 | struct ath5k_rx_status *rs) | ||
499 | { | 606 | { |
500 | struct ath5k_hw_rx_status *rx_status; | 607 | struct ath5k_hw_rx_status *rx_status; |
501 | 608 | ||
@@ -574,12 +681,22 @@ static int ath5k_hw_proc_5210_rx_status(struct ath5k_hw *ah, | |||
574 | return 0; | 681 | return 0; |
575 | } | 682 | } |
576 | 683 | ||
577 | /* | 684 | /** |
578 | * Process the rx status descriptor on 5212 | 685 | * ath5k_hw_proc_5212_rx_status() - Process the rx status descriptor on 5212 |
686 | * @ah: The &struct ath5k_hw | ||
687 | * @desc: The &struct ath5k_desc | ||
688 | * @rs: The &struct ath5k_rx_status | ||
689 | * | ||
690 | * Internal function used to process an RX status descriptor | ||
691 | * on AR5212 and later MAC. | ||
692 | * | ||
693 | * Returns 0 on success or -EINPROGRESS in case we haven't received the who;e | ||
694 | * frame yet. | ||
579 | */ | 695 | */ |
580 | static int ath5k_hw_proc_5212_rx_status(struct ath5k_hw *ah, | 696 | static int |
581 | struct ath5k_desc *desc, | 697 | ath5k_hw_proc_5212_rx_status(struct ath5k_hw *ah, |
582 | struct ath5k_rx_status *rs) | 698 | struct ath5k_desc *desc, |
699 | struct ath5k_rx_status *rs) | ||
583 | { | 700 | { |
584 | struct ath5k_hw_rx_status *rx_status; | 701 | struct ath5k_hw_rx_status *rx_status; |
585 | u32 rxstat0, rxstat1; | 702 | u32 rxstat0, rxstat1; |
@@ -646,10 +763,16 @@ static int ath5k_hw_proc_5212_rx_status(struct ath5k_hw *ah, | |||
646 | * Attach * | 763 | * Attach * |
647 | \********/ | 764 | \********/ |
648 | 765 | ||
649 | /* | 766 | /** |
650 | * Init function pointers inside ath5k_hw struct | 767 | * ath5k_hw_init_desc_functions() - Init function pointers inside ah |
768 | * @ah: The &struct ath5k_hw | ||
769 | * | ||
770 | * Maps the internal descriptor functions to the function pointers on ah, used | ||
771 | * from above. This is used as an abstraction layer to handle the various chips | ||
772 | * the same way. | ||
651 | */ | 773 | */ |
652 | int ath5k_hw_init_desc_functions(struct ath5k_hw *ah) | 774 | int |
775 | ath5k_hw_init_desc_functions(struct ath5k_hw *ah) | ||
653 | { | 776 | { |
654 | if (ah->ah_version == AR5K_AR5212) { | 777 | if (ah->ah_version == AR5K_AR5212) { |
655 | ah->ah_setup_tx_desc = ath5k_hw_setup_4word_tx_desc; | 778 | ah->ah_setup_tx_desc = ath5k_hw_setup_4word_tx_desc; |
diff --git a/drivers/net/wireless/ath/ath5k/desc.h b/drivers/net/wireless/ath/ath5k/desc.h index cfd529b548f3..8d6c01a49ea3 100644 --- a/drivers/net/wireless/ath/ath5k/desc.h +++ b/drivers/net/wireless/ath/ath5k/desc.h | |||
@@ -20,25 +20,30 @@ | |||
20 | * RX/TX descriptor structures | 20 | * RX/TX descriptor structures |
21 | */ | 21 | */ |
22 | 22 | ||
23 | /* | 23 | /** |
24 | * Common hardware RX control descriptor | 24 | * struct ath5k_hw_rx_ctl - Common hardware RX control descriptor |
25 | * @rx_control_0: RX control word 0 | ||
26 | * @rx_control_1: RX control word 1 | ||
25 | */ | 27 | */ |
26 | struct ath5k_hw_rx_ctl { | 28 | struct ath5k_hw_rx_ctl { |
27 | u32 rx_control_0; /* RX control word 0 */ | 29 | u32 rx_control_0; |
28 | u32 rx_control_1; /* RX control word 1 */ | 30 | u32 rx_control_1; |
29 | } __packed __aligned(4); | 31 | } __packed __aligned(4); |
30 | 32 | ||
31 | /* RX control word 1 fields/flags */ | 33 | /* RX control word 1 fields/flags */ |
32 | #define AR5K_DESC_RX_CTL1_BUF_LEN 0x00000fff /* data buffer length */ | 34 | #define AR5K_DESC_RX_CTL1_BUF_LEN 0x00000fff /* data buffer length */ |
33 | #define AR5K_DESC_RX_CTL1_INTREQ 0x00002000 /* RX interrupt request */ | 35 | #define AR5K_DESC_RX_CTL1_INTREQ 0x00002000 /* RX interrupt request */ |
34 | 36 | ||
35 | /* | 37 | /** |
36 | * Common hardware RX status descriptor | 38 | * struct ath5k_hw_rx_status - Common hardware RX status descriptor |
39 | * @rx_status_0: RX status word 0 | ||
40 | * @rx_status_1: RX status word 1 | ||
41 | * | ||
37 | * 5210, 5211 and 5212 differ only in the fields and flags defined below | 42 | * 5210, 5211 and 5212 differ only in the fields and flags defined below |
38 | */ | 43 | */ |
39 | struct ath5k_hw_rx_status { | 44 | struct ath5k_hw_rx_status { |
40 | u32 rx_status_0; /* RX status word 0 */ | 45 | u32 rx_status_0; |
41 | u32 rx_status_1; /* RX status word 1 */ | 46 | u32 rx_status_1; |
42 | } __packed __aligned(4); | 47 | } __packed __aligned(4); |
43 | 48 | ||
44 | /* 5210/5211 */ | 49 | /* 5210/5211 */ |
@@ -98,17 +103,36 @@ struct ath5k_hw_rx_status { | |||
98 | 103 | ||
99 | /** | 104 | /** |
100 | * enum ath5k_phy_error_code - PHY Error codes | 105 | * enum ath5k_phy_error_code - PHY Error codes |
106 | * @AR5K_RX_PHY_ERROR_UNDERRUN: Transmit underrun, [5210] No error | ||
107 | * @AR5K_RX_PHY_ERROR_TIMING: Timing error | ||
108 | * @AR5K_RX_PHY_ERROR_PARITY: Illegal parity | ||
109 | * @AR5K_RX_PHY_ERROR_RATE: Illegal rate | ||
110 | * @AR5K_RX_PHY_ERROR_LENGTH: Illegal length | ||
111 | * @AR5K_RX_PHY_ERROR_RADAR: Radar detect, [5210] 64 QAM rate | ||
112 | * @AR5K_RX_PHY_ERROR_SERVICE: Illegal service | ||
113 | * @AR5K_RX_PHY_ERROR_TOR: Transmit override receive | ||
114 | * @AR5K_RX_PHY_ERROR_OFDM_TIMING: OFDM Timing error [5212+] | ||
115 | * @AR5K_RX_PHY_ERROR_OFDM_SIGNAL_PARITY: OFDM Signal parity error [5212+] | ||
116 | * @AR5K_RX_PHY_ERROR_OFDM_RATE_ILLEGAL: OFDM Illegal rate [5212+] | ||
117 | * @AR5K_RX_PHY_ERROR_OFDM_LENGTH_ILLEGAL: OFDM Illegal length [5212+] | ||
118 | * @AR5K_RX_PHY_ERROR_OFDM_POWER_DROP: OFDM Power drop [5212+] | ||
119 | * @AR5K_RX_PHY_ERROR_OFDM_SERVICE: OFDM Service (?) [5212+] | ||
120 | * @AR5K_RX_PHY_ERROR_OFDM_RESTART: OFDM Restart (?) [5212+] | ||
121 | * @AR5K_RX_PHY_ERROR_CCK_TIMING: CCK Timing error [5212+] | ||
122 | * @AR5K_RX_PHY_ERROR_CCK_HEADER_CRC: Header CRC error [5212+] | ||
123 | * @AR5K_RX_PHY_ERROR_CCK_RATE_ILLEGAL: Illegal rate [5212+] | ||
124 | * @AR5K_RX_PHY_ERROR_CCK_SERVICE: CCK Service (?) [5212+] | ||
125 | * @AR5K_RX_PHY_ERROR_CCK_RESTART: CCK Restart (?) [5212+] | ||
101 | */ | 126 | */ |
102 | enum ath5k_phy_error_code { | 127 | enum ath5k_phy_error_code { |
103 | AR5K_RX_PHY_ERROR_UNDERRUN = 0, /* Transmit underrun, [5210] No error */ | 128 | AR5K_RX_PHY_ERROR_UNDERRUN = 0, |
104 | AR5K_RX_PHY_ERROR_TIMING = 1, /* Timing error */ | 129 | AR5K_RX_PHY_ERROR_TIMING = 1, |
105 | AR5K_RX_PHY_ERROR_PARITY = 2, /* Illegal parity */ | 130 | AR5K_RX_PHY_ERROR_PARITY = 2, |
106 | AR5K_RX_PHY_ERROR_RATE = 3, /* Illegal rate */ | 131 | AR5K_RX_PHY_ERROR_RATE = 3, |
107 | AR5K_RX_PHY_ERROR_LENGTH = 4, /* Illegal length */ | 132 | AR5K_RX_PHY_ERROR_LENGTH = 4, |
108 | AR5K_RX_PHY_ERROR_RADAR = 5, /* Radar detect, [5210] 64 QAM rate */ | 133 | AR5K_RX_PHY_ERROR_RADAR = 5, |
109 | AR5K_RX_PHY_ERROR_SERVICE = 6, /* Illegal service */ | 134 | AR5K_RX_PHY_ERROR_SERVICE = 6, |
110 | AR5K_RX_PHY_ERROR_TOR = 7, /* Transmit override receive */ | 135 | AR5K_RX_PHY_ERROR_TOR = 7, |
111 | /* these are specific to the 5212 */ | ||
112 | AR5K_RX_PHY_ERROR_OFDM_TIMING = 17, | 136 | AR5K_RX_PHY_ERROR_OFDM_TIMING = 17, |
113 | AR5K_RX_PHY_ERROR_OFDM_SIGNAL_PARITY = 18, | 137 | AR5K_RX_PHY_ERROR_OFDM_SIGNAL_PARITY = 18, |
114 | AR5K_RX_PHY_ERROR_OFDM_RATE_ILLEGAL = 19, | 138 | AR5K_RX_PHY_ERROR_OFDM_RATE_ILLEGAL = 19, |
@@ -123,12 +147,14 @@ enum ath5k_phy_error_code { | |||
123 | AR5K_RX_PHY_ERROR_CCK_RESTART = 31, | 147 | AR5K_RX_PHY_ERROR_CCK_RESTART = 31, |
124 | }; | 148 | }; |
125 | 149 | ||
126 | /* | 150 | /** |
127 | * 5210/5211 hardware 2-word TX control descriptor | 151 | * struct ath5k_hw_2w_tx_ctl - 5210/5211 hardware 2-word TX control descriptor |
152 | * @tx_control_0: TX control word 0 | ||
153 | * @tx_control_1: TX control word 1 | ||
128 | */ | 154 | */ |
129 | struct ath5k_hw_2w_tx_ctl { | 155 | struct ath5k_hw_2w_tx_ctl { |
130 | u32 tx_control_0; /* TX control word 0 */ | 156 | u32 tx_control_0; |
131 | u32 tx_control_1; /* TX control word 1 */ | 157 | u32 tx_control_1; |
132 | } __packed __aligned(4); | 158 | } __packed __aligned(4); |
133 | 159 | ||
134 | /* TX control word 0 fields/flags */ | 160 | /* TX control word 0 fields/flags */ |
@@ -177,14 +203,18 @@ struct ath5k_hw_2w_tx_ctl { | |||
177 | #define AR5K_AR5210_TX_DESC_FRAME_TYPE_PIFS 4 | 203 | #define AR5K_AR5210_TX_DESC_FRAME_TYPE_PIFS 4 |
178 | #define AR5K_AR5211_TX_DESC_FRAME_TYPE_PRESP 4 | 204 | #define AR5K_AR5211_TX_DESC_FRAME_TYPE_PRESP 4 |
179 | 205 | ||
180 | /* | 206 | /** |
181 | * 5212 hardware 4-word TX control descriptor | 207 | * struct ath5k_hw_4w_tx_ctl - 5212 hardware 4-word TX control descriptor |
208 | * @tx_control_0: TX control word 0 | ||
209 | * @tx_control_1: TX control word 1 | ||
210 | * @tx_control_2: TX control word 2 | ||
211 | * @tx_control_3: TX control word 3 | ||
182 | */ | 212 | */ |
183 | struct ath5k_hw_4w_tx_ctl { | 213 | struct ath5k_hw_4w_tx_ctl { |
184 | u32 tx_control_0; /* TX control word 0 */ | 214 | u32 tx_control_0; |
185 | u32 tx_control_1; /* TX control word 1 */ | 215 | u32 tx_control_1; |
186 | u32 tx_control_2; /* TX control word 2 */ | 216 | u32 tx_control_2; |
187 | u32 tx_control_3; /* TX control word 3 */ | 217 | u32 tx_control_3; |
188 | } __packed __aligned(4); | 218 | } __packed __aligned(4); |
189 | 219 | ||
190 | /* TX control word 0 fields/flags */ | 220 | /* TX control word 0 fields/flags */ |
@@ -238,12 +268,14 @@ struct ath5k_hw_4w_tx_ctl { | |||
238 | #define AR5K_4W_TX_DESC_CTL3_RTS_CTS_RATE 0x01f00000 /* RTS or CTS rate */ | 268 | #define AR5K_4W_TX_DESC_CTL3_RTS_CTS_RATE 0x01f00000 /* RTS or CTS rate */ |
239 | #define AR5K_4W_TX_DESC_CTL3_RTS_CTS_RATE_S 20 | 269 | #define AR5K_4W_TX_DESC_CTL3_RTS_CTS_RATE_S 20 |
240 | 270 | ||
241 | /* | 271 | /** |
242 | * Common TX status descriptor | 272 | * struct ath5k_hw_tx_status - Common TX status descriptor |
273 | * @tx_status_0: TX status word 0 | ||
274 | * @tx_status_1: TX status word 1 | ||
243 | */ | 275 | */ |
244 | struct ath5k_hw_tx_status { | 276 | struct ath5k_hw_tx_status { |
245 | u32 tx_status_0; /* TX status word 0 */ | 277 | u32 tx_status_0; |
246 | u32 tx_status_1; /* TX status word 1 */ | 278 | u32 tx_status_1; |
247 | } __packed __aligned(4); | 279 | } __packed __aligned(4); |
248 | 280 | ||
249 | /* TX status word 0 fields/flags */ | 281 | /* TX status word 0 fields/flags */ |
@@ -276,37 +308,47 @@ struct ath5k_hw_tx_status { | |||
276 | #define AR5K_DESC_TX_STATUS1_COMP_SUCCESS_5212 0x00800000 /* [5212] compression status */ | 308 | #define AR5K_DESC_TX_STATUS1_COMP_SUCCESS_5212 0x00800000 /* [5212] compression status */ |
277 | #define AR5K_DESC_TX_STATUS1_XMIT_ANTENNA_5212 0x01000000 /* [5212] transmit antenna */ | 309 | #define AR5K_DESC_TX_STATUS1_XMIT_ANTENNA_5212 0x01000000 /* [5212] transmit antenna */ |
278 | 310 | ||
279 | /* | 311 | /** |
280 | * 5210/5211 hardware TX descriptor | 312 | * struct ath5k_hw_5210_tx_desc - 5210/5211 hardware TX descriptor |
313 | * @tx_ctl: The &struct ath5k_hw_2w_tx_ctl | ||
314 | * @tx_stat: The &struct ath5k_hw_tx_status | ||
281 | */ | 315 | */ |
282 | struct ath5k_hw_5210_tx_desc { | 316 | struct ath5k_hw_5210_tx_desc { |
283 | struct ath5k_hw_2w_tx_ctl tx_ctl; | 317 | struct ath5k_hw_2w_tx_ctl tx_ctl; |
284 | struct ath5k_hw_tx_status tx_stat; | 318 | struct ath5k_hw_tx_status tx_stat; |
285 | } __packed __aligned(4); | 319 | } __packed __aligned(4); |
286 | 320 | ||
287 | /* | 321 | /** |
288 | * 5212 hardware TX descriptor | 322 | * struct ath5k_hw_5212_tx_desc - 5212 hardware TX descriptor |
323 | * @tx_ctl: The &struct ath5k_hw_4w_tx_ctl | ||
324 | * @tx_stat: The &struct ath5k_hw_tx_status | ||
289 | */ | 325 | */ |
290 | struct ath5k_hw_5212_tx_desc { | 326 | struct ath5k_hw_5212_tx_desc { |
291 | struct ath5k_hw_4w_tx_ctl tx_ctl; | 327 | struct ath5k_hw_4w_tx_ctl tx_ctl; |
292 | struct ath5k_hw_tx_status tx_stat; | 328 | struct ath5k_hw_tx_status tx_stat; |
293 | } __packed __aligned(4); | 329 | } __packed __aligned(4); |
294 | 330 | ||
295 | /* | 331 | /** |
296 | * Common hardware RX descriptor | 332 | * struct ath5k_hw_all_rx_desc - Common hardware RX descriptor |
333 | * @rx_ctl: The &struct ath5k_hw_rx_ctl | ||
334 | * @rx_stat: The &struct ath5k_hw_rx_status | ||
297 | */ | 335 | */ |
298 | struct ath5k_hw_all_rx_desc { | 336 | struct ath5k_hw_all_rx_desc { |
299 | struct ath5k_hw_rx_ctl rx_ctl; | 337 | struct ath5k_hw_rx_ctl rx_ctl; |
300 | struct ath5k_hw_rx_status rx_stat; | 338 | struct ath5k_hw_rx_status rx_stat; |
301 | } __packed __aligned(4); | 339 | } __packed __aligned(4); |
302 | 340 | ||
303 | /* | 341 | /** |
304 | * Atheros hardware DMA descriptor | 342 | * struct ath5k_desc - Atheros hardware DMA descriptor |
343 | * @ds_link: Physical address of the next descriptor | ||
344 | * @ds_data: Physical address of data buffer (skb) | ||
345 | * @ud: Union containing hw_5xxx_tx_desc structs and hw_all_rx_desc | ||
346 | * | ||
305 | * This is read and written to by the hardware | 347 | * This is read and written to by the hardware |
306 | */ | 348 | */ |
307 | struct ath5k_desc { | 349 | struct ath5k_desc { |
308 | u32 ds_link; /* physical address of the next descriptor */ | 350 | u32 ds_link; |
309 | u32 ds_data; /* physical address of data buffer (skb) */ | 351 | u32 ds_data; |
310 | 352 | ||
311 | union { | 353 | union { |
312 | struct ath5k_hw_5210_tx_desc ds_tx5210; | 354 | struct ath5k_hw_5210_tx_desc ds_tx5210; |
diff --git a/drivers/net/wireless/ath/ath5k/dma.c b/drivers/net/wireless/ath/ath5k/dma.c index 2481f9c7f4b6..5cc9aa814697 100644 --- a/drivers/net/wireless/ath/ath5k/dma.c +++ b/drivers/net/wireless/ath/ath5k/dma.c | |||
@@ -20,16 +20,13 @@ | |||
20 | * DMA and interrupt masking functions * | 20 | * DMA and interrupt masking functions * |
21 | \*************************************/ | 21 | \*************************************/ |
22 | 22 | ||
23 | /* | 23 | /** |
24 | * dma.c - DMA and interrupt masking functions | 24 | * DOC: DMA and interrupt masking functions |
25 | * | 25 | * |
26 | * Here we setup descriptor pointers (rxdp/txdp) start/stop dma engine and | 26 | * Here we setup descriptor pointers (rxdp/txdp) start/stop dma engine and |
27 | * handle queue setup for 5210 chipset (rest are handled on qcu.c). | 27 | * handle queue setup for 5210 chipset (rest are handled on qcu.c). |
28 | * Also we setup interrupt mask register (IMR) and read the various interrupt | 28 | * Also we setup interrupt mask register (IMR) and read the various interrupt |
29 | * status registers (ISR). | 29 | * status registers (ISR). |
30 | * | ||
31 | * TODO: Handle SISR on 5211+ and introduce a function to return the queue | ||
32 | * number that resulted the interrupt. | ||
33 | */ | 30 | */ |
34 | 31 | ||
35 | #include "ath5k.h" | 32 | #include "ath5k.h" |
@@ -42,22 +39,22 @@ | |||
42 | \*********/ | 39 | \*********/ |
43 | 40 | ||
44 | /** | 41 | /** |
45 | * ath5k_hw_start_rx_dma - Start DMA receive | 42 | * ath5k_hw_start_rx_dma() - Start DMA receive |
46 | * | ||
47 | * @ah: The &struct ath5k_hw | 43 | * @ah: The &struct ath5k_hw |
48 | */ | 44 | */ |
49 | void ath5k_hw_start_rx_dma(struct ath5k_hw *ah) | 45 | void |
46 | ath5k_hw_start_rx_dma(struct ath5k_hw *ah) | ||
50 | { | 47 | { |
51 | ath5k_hw_reg_write(ah, AR5K_CR_RXE, AR5K_CR); | 48 | ath5k_hw_reg_write(ah, AR5K_CR_RXE, AR5K_CR); |
52 | ath5k_hw_reg_read(ah, AR5K_CR); | 49 | ath5k_hw_reg_read(ah, AR5K_CR); |
53 | } | 50 | } |
54 | 51 | ||
55 | /** | 52 | /** |
56 | * ath5k_hw_stop_rx_dma - Stop DMA receive | 53 | * ath5k_hw_stop_rx_dma() - Stop DMA receive |
57 | * | ||
58 | * @ah: The &struct ath5k_hw | 54 | * @ah: The &struct ath5k_hw |
59 | */ | 55 | */ |
60 | static int ath5k_hw_stop_rx_dma(struct ath5k_hw *ah) | 56 | static int |
57 | ath5k_hw_stop_rx_dma(struct ath5k_hw *ah) | ||
61 | { | 58 | { |
62 | unsigned int i; | 59 | unsigned int i; |
63 | 60 | ||
@@ -79,24 +76,24 @@ static int ath5k_hw_stop_rx_dma(struct ath5k_hw *ah) | |||
79 | } | 76 | } |
80 | 77 | ||
81 | /** | 78 | /** |
82 | * ath5k_hw_get_rxdp - Get RX Descriptor's address | 79 | * ath5k_hw_get_rxdp() - Get RX Descriptor's address |
83 | * | ||
84 | * @ah: The &struct ath5k_hw | 80 | * @ah: The &struct ath5k_hw |
85 | */ | 81 | */ |
86 | u32 ath5k_hw_get_rxdp(struct ath5k_hw *ah) | 82 | u32 |
83 | ath5k_hw_get_rxdp(struct ath5k_hw *ah) | ||
87 | { | 84 | { |
88 | return ath5k_hw_reg_read(ah, AR5K_RXDP); | 85 | return ath5k_hw_reg_read(ah, AR5K_RXDP); |
89 | } | 86 | } |
90 | 87 | ||
91 | /** | 88 | /** |
92 | * ath5k_hw_set_rxdp - Set RX Descriptor's address | 89 | * ath5k_hw_set_rxdp() - Set RX Descriptor's address |
93 | * | ||
94 | * @ah: The &struct ath5k_hw | 90 | * @ah: The &struct ath5k_hw |
95 | * @phys_addr: RX descriptor address | 91 | * @phys_addr: RX descriptor address |
96 | * | 92 | * |
97 | * Returns -EIO if rx is active | 93 | * Returns -EIO if rx is active |
98 | */ | 94 | */ |
99 | int ath5k_hw_set_rxdp(struct ath5k_hw *ah, u32 phys_addr) | 95 | int |
96 | ath5k_hw_set_rxdp(struct ath5k_hw *ah, u32 phys_addr) | ||
100 | { | 97 | { |
101 | if (ath5k_hw_reg_read(ah, AR5K_CR) & AR5K_CR_RXE) { | 98 | if (ath5k_hw_reg_read(ah, AR5K_CR) & AR5K_CR_RXE) { |
102 | ATH5K_DBG(ah, ATH5K_DEBUG_DMA, | 99 | ATH5K_DBG(ah, ATH5K_DEBUG_DMA, |
@@ -114,8 +111,7 @@ int ath5k_hw_set_rxdp(struct ath5k_hw *ah, u32 phys_addr) | |||
114 | \**********/ | 111 | \**********/ |
115 | 112 | ||
116 | /** | 113 | /** |
117 | * ath5k_hw_start_tx_dma - Start DMA transmit for a specific queue | 114 | * ath5k_hw_start_tx_dma() - Start DMA transmit for a specific queue |
118 | * | ||
119 | * @ah: The &struct ath5k_hw | 115 | * @ah: The &struct ath5k_hw |
120 | * @queue: The hw queue number | 116 | * @queue: The hw queue number |
121 | * | 117 | * |
@@ -128,7 +124,8 @@ int ath5k_hw_set_rxdp(struct ath5k_hw *ah, u32 phys_addr) | |||
128 | * NOTE: Must be called after setting up tx control descriptor for that | 124 | * NOTE: Must be called after setting up tx control descriptor for that |
129 | * queue (see below). | 125 | * queue (see below). |
130 | */ | 126 | */ |
131 | int ath5k_hw_start_tx_dma(struct ath5k_hw *ah, unsigned int queue) | 127 | int |
128 | ath5k_hw_start_tx_dma(struct ath5k_hw *ah, unsigned int queue) | ||
132 | { | 129 | { |
133 | u32 tx_queue; | 130 | u32 tx_queue; |
134 | 131 | ||
@@ -177,17 +174,16 @@ int ath5k_hw_start_tx_dma(struct ath5k_hw *ah, unsigned int queue) | |||
177 | } | 174 | } |
178 | 175 | ||
179 | /** | 176 | /** |
180 | * ath5k_hw_stop_tx_dma - Stop DMA transmit on a specific queue | 177 | * ath5k_hw_stop_tx_dma() - Stop DMA transmit on a specific queue |
181 | * | ||
182 | * @ah: The &struct ath5k_hw | 178 | * @ah: The &struct ath5k_hw |
183 | * @queue: The hw queue number | 179 | * @queue: The hw queue number |
184 | * | 180 | * |
185 | * Stop DMA transmit on a specific hw queue and drain queue so we don't | 181 | * Stop DMA transmit on a specific hw queue and drain queue so we don't |
186 | * have any pending frames. Returns -EBUSY if we still have pending frames, | 182 | * have any pending frames. Returns -EBUSY if we still have pending frames, |
187 | * -EINVAL if queue number is out of range or inactive. | 183 | * -EINVAL if queue number is out of range or inactive. |
188 | * | ||
189 | */ | 184 | */ |
190 | static int ath5k_hw_stop_tx_dma(struct ath5k_hw *ah, unsigned int queue) | 185 | static int |
186 | ath5k_hw_stop_tx_dma(struct ath5k_hw *ah, unsigned int queue) | ||
191 | { | 187 | { |
192 | unsigned int i = 40; | 188 | unsigned int i = 40; |
193 | u32 tx_queue, pending; | 189 | u32 tx_queue, pending; |
@@ -320,14 +316,14 @@ static int ath5k_hw_stop_tx_dma(struct ath5k_hw *ah, unsigned int queue) | |||
320 | } | 316 | } |
321 | 317 | ||
322 | /** | 318 | /** |
323 | * ath5k_hw_stop_beacon_queue - Stop beacon queue | 319 | * ath5k_hw_stop_beacon_queue() - Stop beacon queue |
324 | * | 320 | * @ah: The &struct ath5k_hw |
325 | * @ah The &struct ath5k_hw | 321 | * @queue: The queue number |
326 | * @queue The queue number | ||
327 | * | 322 | * |
328 | * Returns -EIO if queue didn't stop | 323 | * Returns -EIO if queue didn't stop |
329 | */ | 324 | */ |
330 | int ath5k_hw_stop_beacon_queue(struct ath5k_hw *ah, unsigned int queue) | 325 | int |
326 | ath5k_hw_stop_beacon_queue(struct ath5k_hw *ah, unsigned int queue) | ||
331 | { | 327 | { |
332 | int ret; | 328 | int ret; |
333 | ret = ath5k_hw_stop_tx_dma(ah, queue); | 329 | ret = ath5k_hw_stop_tx_dma(ah, queue); |
@@ -340,8 +336,7 @@ int ath5k_hw_stop_beacon_queue(struct ath5k_hw *ah, unsigned int queue) | |||
340 | } | 336 | } |
341 | 337 | ||
342 | /** | 338 | /** |
343 | * ath5k_hw_get_txdp - Get TX Descriptor's address for a specific queue | 339 | * ath5k_hw_get_txdp() - Get TX Descriptor's address for a specific queue |
344 | * | ||
345 | * @ah: The &struct ath5k_hw | 340 | * @ah: The &struct ath5k_hw |
346 | * @queue: The hw queue number | 341 | * @queue: The hw queue number |
347 | * | 342 | * |
@@ -352,7 +347,8 @@ int ath5k_hw_stop_beacon_queue(struct ath5k_hw *ah, unsigned int queue) | |||
352 | * | 347 | * |
353 | * XXX: Is TXDP read and clear ? | 348 | * XXX: Is TXDP read and clear ? |
354 | */ | 349 | */ |
355 | u32 ath5k_hw_get_txdp(struct ath5k_hw *ah, unsigned int queue) | 350 | u32 |
351 | ath5k_hw_get_txdp(struct ath5k_hw *ah, unsigned int queue) | ||
356 | { | 352 | { |
357 | u16 tx_reg; | 353 | u16 tx_reg; |
358 | 354 | ||
@@ -382,10 +378,10 @@ u32 ath5k_hw_get_txdp(struct ath5k_hw *ah, unsigned int queue) | |||
382 | } | 378 | } |
383 | 379 | ||
384 | /** | 380 | /** |
385 | * ath5k_hw_set_txdp - Set TX Descriptor's address for a specific queue | 381 | * ath5k_hw_set_txdp() - Set TX Descriptor's address for a specific queue |
386 | * | ||
387 | * @ah: The &struct ath5k_hw | 382 | * @ah: The &struct ath5k_hw |
388 | * @queue: The hw queue number | 383 | * @queue: The hw queue number |
384 | * @phys_addr: The physical address | ||
389 | * | 385 | * |
390 | * Set TX descriptor's address for a specific queue. For 5210 we ignore | 386 | * Set TX descriptor's address for a specific queue. For 5210 we ignore |
391 | * the queue number and we use tx queue type since we only have 2 queues | 387 | * the queue number and we use tx queue type since we only have 2 queues |
@@ -394,7 +390,8 @@ u32 ath5k_hw_get_txdp(struct ath5k_hw *ah, unsigned int queue) | |||
394 | * Returns -EINVAL if queue type is invalid for 5210 and -EIO if queue is still | 390 | * Returns -EINVAL if queue type is invalid for 5210 and -EIO if queue is still |
395 | * active. | 391 | * active. |
396 | */ | 392 | */ |
397 | int ath5k_hw_set_txdp(struct ath5k_hw *ah, unsigned int queue, u32 phys_addr) | 393 | int |
394 | ath5k_hw_set_txdp(struct ath5k_hw *ah, unsigned int queue, u32 phys_addr) | ||
398 | { | 395 | { |
399 | u16 tx_reg; | 396 | u16 tx_reg; |
400 | 397 | ||
@@ -435,8 +432,7 @@ int ath5k_hw_set_txdp(struct ath5k_hw *ah, unsigned int queue, u32 phys_addr) | |||
435 | } | 432 | } |
436 | 433 | ||
437 | /** | 434 | /** |
438 | * ath5k_hw_update_tx_triglevel - Update tx trigger level | 435 | * ath5k_hw_update_tx_triglevel() - Update tx trigger level |
439 | * | ||
440 | * @ah: The &struct ath5k_hw | 436 | * @ah: The &struct ath5k_hw |
441 | * @increase: Flag to force increase of trigger level | 437 | * @increase: Flag to force increase of trigger level |
442 | * | 438 | * |
@@ -444,15 +440,15 @@ int ath5k_hw_set_txdp(struct ath5k_hw *ah, unsigned int queue, u32 phys_addr) | |||
444 | * buffer (aka FIFO threshold) that is used to indicate when PCU flushes | 440 | * buffer (aka FIFO threshold) that is used to indicate when PCU flushes |
445 | * the buffer and transmits its data. Lowering this results sending small | 441 | * the buffer and transmits its data. Lowering this results sending small |
446 | * frames more quickly but can lead to tx underruns, raising it a lot can | 442 | * frames more quickly but can lead to tx underruns, raising it a lot can |
447 | * result other problems (i think bmiss is related). Right now we start with | 443 | * result other problems. Right now we start with the lowest possible |
448 | * the lowest possible (64Bytes) and if we get tx underrun we increase it using | 444 | * (64Bytes) and if we get tx underrun we increase it using the increase |
449 | * the increase flag. Returns -EIO if we have reached maximum/minimum. | 445 | * flag. Returns -EIO if we have reached maximum/minimum. |
450 | * | 446 | * |
451 | * XXX: Link this with tx DMA size ? | 447 | * XXX: Link this with tx DMA size ? |
452 | * XXX: Use it to save interrupts ? | 448 | * XXX2: Use it to save interrupts ? |
453 | * TODO: Needs testing, i think it's related to bmiss... | ||
454 | */ | 449 | */ |
455 | int ath5k_hw_update_tx_triglevel(struct ath5k_hw *ah, bool increase) | 450 | int |
451 | ath5k_hw_update_tx_triglevel(struct ath5k_hw *ah, bool increase) | ||
456 | { | 452 | { |
457 | u32 trigger_level, imr; | 453 | u32 trigger_level, imr; |
458 | int ret = -EIO; | 454 | int ret = -EIO; |
@@ -498,21 +494,20 @@ done: | |||
498 | \*******************/ | 494 | \*******************/ |
499 | 495 | ||
500 | /** | 496 | /** |
501 | * ath5k_hw_is_intr_pending - Check if we have pending interrupts | 497 | * ath5k_hw_is_intr_pending() - Check if we have pending interrupts |
502 | * | ||
503 | * @ah: The &struct ath5k_hw | 498 | * @ah: The &struct ath5k_hw |
504 | * | 499 | * |
505 | * Check if we have pending interrupts to process. Returns 1 if we | 500 | * Check if we have pending interrupts to process. Returns 1 if we |
506 | * have pending interrupts and 0 if we haven't. | 501 | * have pending interrupts and 0 if we haven't. |
507 | */ | 502 | */ |
508 | bool ath5k_hw_is_intr_pending(struct ath5k_hw *ah) | 503 | bool |
504 | ath5k_hw_is_intr_pending(struct ath5k_hw *ah) | ||
509 | { | 505 | { |
510 | return ath5k_hw_reg_read(ah, AR5K_INTPEND) == 1 ? 1 : 0; | 506 | return ath5k_hw_reg_read(ah, AR5K_INTPEND) == 1 ? 1 : 0; |
511 | } | 507 | } |
512 | 508 | ||
513 | /** | 509 | /** |
514 | * ath5k_hw_get_isr - Get interrupt status | 510 | * ath5k_hw_get_isr() - Get interrupt status |
515 | * | ||
516 | * @ah: The @struct ath5k_hw | 511 | * @ah: The @struct ath5k_hw |
517 | * @interrupt_mask: Driver's interrupt mask used to filter out | 512 | * @interrupt_mask: Driver's interrupt mask used to filter out |
518 | * interrupts in sw. | 513 | * interrupts in sw. |
@@ -523,62 +518,162 @@ bool ath5k_hw_is_intr_pending(struct ath5k_hw *ah) | |||
523 | * being mapped on some standard non hw-specific positions | 518 | * being mapped on some standard non hw-specific positions |
524 | * (check out &ath5k_int). | 519 | * (check out &ath5k_int). |
525 | * | 520 | * |
526 | * NOTE: We use read-and-clear register, so after this function is called ISR | 521 | * NOTE: We do write-to-clear, so the active PISR/SISR bits at the time this |
527 | * is zeroed. | 522 | * function gets called are cleared on return. |
528 | */ | 523 | */ |
529 | int ath5k_hw_get_isr(struct ath5k_hw *ah, enum ath5k_int *interrupt_mask) | 524 | int |
525 | ath5k_hw_get_isr(struct ath5k_hw *ah, enum ath5k_int *interrupt_mask) | ||
530 | { | 526 | { |
531 | u32 data; | 527 | u32 data = 0; |
532 | 528 | ||
533 | /* | 529 | /* |
534 | * Read interrupt status from the Interrupt Status register | 530 | * Read interrupt status from Primary Interrupt |
535 | * on 5210 | 531 | * Register. |
532 | * | ||
533 | * Note: PISR/SISR Not available on 5210 | ||
536 | */ | 534 | */ |
537 | if (ah->ah_version == AR5K_AR5210) { | 535 | if (ah->ah_version == AR5K_AR5210) { |
538 | data = ath5k_hw_reg_read(ah, AR5K_ISR); | 536 | u32 isr = 0; |
539 | if (unlikely(data == AR5K_INT_NOCARD)) { | 537 | isr = ath5k_hw_reg_read(ah, AR5K_ISR); |
540 | *interrupt_mask = data; | 538 | if (unlikely(isr == AR5K_INT_NOCARD)) { |
539 | *interrupt_mask = isr; | ||
541 | return -ENODEV; | 540 | return -ENODEV; |
542 | } | 541 | } |
543 | } else { | 542 | |
544 | /* | 543 | /* |
545 | * Read interrupt status from Interrupt | 544 | * Filter out the non-common bits from the interrupt |
546 | * Status Register shadow copy (Read And Clear) | 545 | * status. |
547 | * | ||
548 | * Note: PISR/SISR Not available on 5210 | ||
549 | */ | 546 | */ |
550 | data = ath5k_hw_reg_read(ah, AR5K_RAC_PISR); | 547 | *interrupt_mask = (isr & AR5K_INT_COMMON) & ah->ah_imr; |
551 | if (unlikely(data == AR5K_INT_NOCARD)) { | 548 | |
552 | *interrupt_mask = data; | 549 | /* Hanlde INT_FATAL */ |
550 | if (unlikely(isr & (AR5K_ISR_SSERR | AR5K_ISR_MCABT | ||
551 | | AR5K_ISR_DPERR))) | ||
552 | *interrupt_mask |= AR5K_INT_FATAL; | ||
553 | |||
554 | /* | ||
555 | * XXX: BMISS interrupts may occur after association. | ||
556 | * I found this on 5210 code but it needs testing. If this is | ||
557 | * true we should disable them before assoc and re-enable them | ||
558 | * after a successful assoc + some jiffies. | ||
559 | interrupt_mask &= ~AR5K_INT_BMISS; | ||
560 | */ | ||
561 | |||
562 | data = isr; | ||
563 | } else { | ||
564 | u32 pisr = 0; | ||
565 | u32 pisr_clear = 0; | ||
566 | u32 sisr0 = 0; | ||
567 | u32 sisr1 = 0; | ||
568 | u32 sisr2 = 0; | ||
569 | u32 sisr3 = 0; | ||
570 | u32 sisr4 = 0; | ||
571 | |||
572 | /* Read PISR and SISRs... */ | ||
573 | pisr = ath5k_hw_reg_read(ah, AR5K_PISR); | ||
574 | if (unlikely(pisr == AR5K_INT_NOCARD)) { | ||
575 | *interrupt_mask = pisr; | ||
553 | return -ENODEV; | 576 | return -ENODEV; |
554 | } | 577 | } |
555 | } | ||
556 | 578 | ||
557 | /* | 579 | sisr0 = ath5k_hw_reg_read(ah, AR5K_SISR0); |
558 | * Get abstract interrupt mask (driver-compatible) | 580 | sisr1 = ath5k_hw_reg_read(ah, AR5K_SISR1); |
559 | */ | 581 | sisr2 = ath5k_hw_reg_read(ah, AR5K_SISR2); |
560 | *interrupt_mask = (data & AR5K_INT_COMMON) & ah->ah_imr; | 582 | sisr3 = ath5k_hw_reg_read(ah, AR5K_SISR3); |
583 | sisr4 = ath5k_hw_reg_read(ah, AR5K_SISR4); | ||
561 | 584 | ||
562 | if (ah->ah_version != AR5K_AR5210) { | 585 | /* |
563 | u32 sisr2 = ath5k_hw_reg_read(ah, AR5K_RAC_SISR2); | 586 | * PISR holds the logical OR of interrupt bits |
587 | * from SISR registers: | ||
588 | * | ||
589 | * TXOK and TXDESC -> Logical OR of TXOK and TXDESC | ||
590 | * per-queue bits on SISR0 | ||
591 | * | ||
592 | * TXERR and TXEOL -> Logical OR of TXERR and TXEOL | ||
593 | * per-queue bits on SISR1 | ||
594 | * | ||
595 | * TXURN -> Logical OR of TXURN per-queue bits on SISR2 | ||
596 | * | ||
597 | * HIUERR -> Logical OR of MCABT, SSERR and DPER bits on SISR2 | ||
598 | * | ||
599 | * BCNMISC -> Logical OR of TIM, CAB_END, DTIM_SYNC | ||
600 | * BCN_TIMEOUT, CAB_TIMEOUT and DTIM | ||
601 | * (and TSFOOR ?) bits on SISR2 | ||
602 | * | ||
603 | * QCBRORN and QCBRURN -> Logical OR of QCBRORN and | ||
604 | * QCBRURN per-queue bits on SISR3 | ||
605 | * QTRIG -> Logical OR of QTRIG per-queue bits on SISR4 | ||
606 | * | ||
607 | * If we clean these bits on PISR we 'll also clear all | ||
608 | * related bits from SISRs, e.g. if we write the TXOK bit on | ||
609 | * PISR we 'll clean all TXOK bits from SISR0 so if a new TXOK | ||
610 | * interrupt got fired for another queue while we were reading | ||
611 | * the interrupt registers and we write back the TXOK bit on | ||
612 | * PISR we 'll lose it. So make sure that we don't write back | ||
613 | * on PISR any bits that come from SISRs. Clearing them from | ||
614 | * SISRs will also clear PISR so no need to worry here. | ||
615 | */ | ||
564 | 616 | ||
565 | /*HIU = Host Interface Unit (PCI etc)*/ | 617 | pisr_clear = pisr & ~AR5K_ISR_BITS_FROM_SISRS; |
566 | if (unlikely(data & (AR5K_ISR_HIUERR))) | ||
567 | *interrupt_mask |= AR5K_INT_FATAL; | ||
568 | 618 | ||
569 | /*Beacon Not Ready*/ | 619 | /* |
570 | if (unlikely(data & (AR5K_ISR_BNR))) | 620 | * Write to clear them... |
571 | *interrupt_mask |= AR5K_INT_BNR; | 621 | * Note: This means that each bit we write back |
622 | * to the registers will get cleared, leaving the | ||
623 | * rest unaffected. So this won't affect new interrupts | ||
624 | * we didn't catch while reading/processing, we 'll get | ||
625 | * them next time get_isr gets called. | ||
626 | */ | ||
627 | ath5k_hw_reg_write(ah, sisr0, AR5K_SISR0); | ||
628 | ath5k_hw_reg_write(ah, sisr1, AR5K_SISR1); | ||
629 | ath5k_hw_reg_write(ah, sisr2, AR5K_SISR2); | ||
630 | ath5k_hw_reg_write(ah, sisr3, AR5K_SISR3); | ||
631 | ath5k_hw_reg_write(ah, sisr4, AR5K_SISR4); | ||
632 | ath5k_hw_reg_write(ah, pisr_clear, AR5K_PISR); | ||
633 | /* Flush previous write */ | ||
634 | ath5k_hw_reg_read(ah, AR5K_PISR); | ||
572 | 635 | ||
573 | if (unlikely(sisr2 & (AR5K_SISR2_SSERR | | 636 | /* |
574 | AR5K_SISR2_DPERR | | 637 | * Filter out the non-common bits from the interrupt |
575 | AR5K_SISR2_MCABT))) | 638 | * status. |
576 | *interrupt_mask |= AR5K_INT_FATAL; | 639 | */ |
640 | *interrupt_mask = (pisr & AR5K_INT_COMMON) & ah->ah_imr; | ||
641 | |||
642 | |||
643 | /* We treat TXOK,TXDESC, TXERR and TXEOL | ||
644 | * the same way (schedule the tx tasklet) | ||
645 | * so we track them all together per queue */ | ||
646 | if (pisr & AR5K_ISR_TXOK) | ||
647 | ah->ah_txq_isr_txok_all |= AR5K_REG_MS(sisr0, | ||
648 | AR5K_SISR0_QCU_TXOK); | ||
577 | 649 | ||
578 | if (data & AR5K_ISR_TIM) | 650 | if (pisr & AR5K_ISR_TXDESC) |
651 | ah->ah_txq_isr_txok_all |= AR5K_REG_MS(sisr0, | ||
652 | AR5K_SISR0_QCU_TXDESC); | ||
653 | |||
654 | if (pisr & AR5K_ISR_TXERR) | ||
655 | ah->ah_txq_isr_txok_all |= AR5K_REG_MS(sisr1, | ||
656 | AR5K_SISR1_QCU_TXERR); | ||
657 | |||
658 | if (pisr & AR5K_ISR_TXEOL) | ||
659 | ah->ah_txq_isr_txok_all |= AR5K_REG_MS(sisr1, | ||
660 | AR5K_SISR1_QCU_TXEOL); | ||
661 | |||
662 | /* Currently this is not much usefull since we treat | ||
663 | * all queues the same way if we get a TXURN (update | ||
664 | * tx trigger level) but we might need it later on*/ | ||
665 | if (pisr & AR5K_ISR_TXURN) | ||
666 | ah->ah_txq_isr_txurn |= AR5K_REG_MS(sisr2, | ||
667 | AR5K_SISR2_QCU_TXURN); | ||
668 | |||
669 | /* Misc Beacon related interrupts */ | ||
670 | |||
671 | /* For AR5211 */ | ||
672 | if (pisr & AR5K_ISR_TIM) | ||
579 | *interrupt_mask |= AR5K_INT_TIM; | 673 | *interrupt_mask |= AR5K_INT_TIM; |
580 | 674 | ||
581 | if (data & AR5K_ISR_BCNMISC) { | 675 | /* For AR5212+ */ |
676 | if (pisr & AR5K_ISR_BCNMISC) { | ||
582 | if (sisr2 & AR5K_SISR2_TIM) | 677 | if (sisr2 & AR5K_SISR2_TIM) |
583 | *interrupt_mask |= AR5K_INT_TIM; | 678 | *interrupt_mask |= AR5K_INT_TIM; |
584 | if (sisr2 & AR5K_SISR2_DTIM) | 679 | if (sisr2 & AR5K_SISR2_DTIM) |
@@ -591,63 +686,39 @@ int ath5k_hw_get_isr(struct ath5k_hw *ah, enum ath5k_int *interrupt_mask) | |||
591 | *interrupt_mask |= AR5K_INT_CAB_TIMEOUT; | 686 | *interrupt_mask |= AR5K_INT_CAB_TIMEOUT; |
592 | } | 687 | } |
593 | 688 | ||
594 | if (data & AR5K_ISR_RXDOPPLER) | 689 | /* Below interrupts are unlikely to happen */ |
595 | *interrupt_mask |= AR5K_INT_RX_DOPPLER; | 690 | |
596 | if (data & AR5K_ISR_QCBRORN) { | 691 | /* HIU = Host Interface Unit (PCI etc) |
692 | * Can be one of MCABT, SSERR, DPERR from SISR2 */ | ||
693 | if (unlikely(pisr & (AR5K_ISR_HIUERR))) | ||
694 | *interrupt_mask |= AR5K_INT_FATAL; | ||
695 | |||
696 | /*Beacon Not Ready*/ | ||
697 | if (unlikely(pisr & (AR5K_ISR_BNR))) | ||
698 | *interrupt_mask |= AR5K_INT_BNR; | ||
699 | |||
700 | /* A queue got CBR overrun */ | ||
701 | if (unlikely(pisr & (AR5K_ISR_QCBRORN))) { | ||
597 | *interrupt_mask |= AR5K_INT_QCBRORN; | 702 | *interrupt_mask |= AR5K_INT_QCBRORN; |
598 | ah->ah_txq_isr |= AR5K_REG_MS( | 703 | ah->ah_txq_isr_qcborn |= AR5K_REG_MS(sisr3, |
599 | ath5k_hw_reg_read(ah, AR5K_RAC_SISR3), | 704 | AR5K_SISR3_QCBRORN); |
600 | AR5K_SISR3_QCBRORN); | ||
601 | } | 705 | } |
602 | if (data & AR5K_ISR_QCBRURN) { | 706 | |
707 | /* A queue got CBR underrun */ | ||
708 | if (unlikely(pisr & (AR5K_ISR_QCBRURN))) { | ||
603 | *interrupt_mask |= AR5K_INT_QCBRURN; | 709 | *interrupt_mask |= AR5K_INT_QCBRURN; |
604 | ah->ah_txq_isr |= AR5K_REG_MS( | 710 | ah->ah_txq_isr_qcburn |= AR5K_REG_MS(sisr3, |
605 | ath5k_hw_reg_read(ah, AR5K_RAC_SISR3), | 711 | AR5K_SISR3_QCBRURN); |
606 | AR5K_SISR3_QCBRURN); | ||
607 | } | 712 | } |
608 | if (data & AR5K_ISR_QTRIG) { | 713 | |
714 | /* A queue got triggered */ | ||
715 | if (unlikely(pisr & (AR5K_ISR_QTRIG))) { | ||
609 | *interrupt_mask |= AR5K_INT_QTRIG; | 716 | *interrupt_mask |= AR5K_INT_QTRIG; |
610 | ah->ah_txq_isr |= AR5K_REG_MS( | 717 | ah->ah_txq_isr_qtrig |= AR5K_REG_MS(sisr4, |
611 | ath5k_hw_reg_read(ah, AR5K_RAC_SISR4), | 718 | AR5K_SISR4_QTRIG); |
612 | AR5K_SISR4_QTRIG); | ||
613 | } | 719 | } |
614 | 720 | ||
615 | if (data & AR5K_ISR_TXOK) | 721 | data = pisr; |
616 | ah->ah_txq_isr |= AR5K_REG_MS( | ||
617 | ath5k_hw_reg_read(ah, AR5K_RAC_SISR0), | ||
618 | AR5K_SISR0_QCU_TXOK); | ||
619 | |||
620 | if (data & AR5K_ISR_TXDESC) | ||
621 | ah->ah_txq_isr |= AR5K_REG_MS( | ||
622 | ath5k_hw_reg_read(ah, AR5K_RAC_SISR0), | ||
623 | AR5K_SISR0_QCU_TXDESC); | ||
624 | |||
625 | if (data & AR5K_ISR_TXERR) | ||
626 | ah->ah_txq_isr |= AR5K_REG_MS( | ||
627 | ath5k_hw_reg_read(ah, AR5K_RAC_SISR1), | ||
628 | AR5K_SISR1_QCU_TXERR); | ||
629 | |||
630 | if (data & AR5K_ISR_TXEOL) | ||
631 | ah->ah_txq_isr |= AR5K_REG_MS( | ||
632 | ath5k_hw_reg_read(ah, AR5K_RAC_SISR1), | ||
633 | AR5K_SISR1_QCU_TXEOL); | ||
634 | |||
635 | if (data & AR5K_ISR_TXURN) | ||
636 | ah->ah_txq_isr |= AR5K_REG_MS( | ||
637 | ath5k_hw_reg_read(ah, AR5K_RAC_SISR2), | ||
638 | AR5K_SISR2_QCU_TXURN); | ||
639 | } else { | ||
640 | if (unlikely(data & (AR5K_ISR_SSERR | AR5K_ISR_MCABT | ||
641 | | AR5K_ISR_HIUERR | AR5K_ISR_DPERR))) | ||
642 | *interrupt_mask |= AR5K_INT_FATAL; | ||
643 | |||
644 | /* | ||
645 | * XXX: BMISS interrupts may occur after association. | ||
646 | * I found this on 5210 code but it needs testing. If this is | ||
647 | * true we should disable them before assoc and re-enable them | ||
648 | * after a successful assoc + some jiffies. | ||
649 | interrupt_mask &= ~AR5K_INT_BMISS; | ||
650 | */ | ||
651 | } | 722 | } |
652 | 723 | ||
653 | /* | 724 | /* |
@@ -661,8 +732,7 @@ int ath5k_hw_get_isr(struct ath5k_hw *ah, enum ath5k_int *interrupt_mask) | |||
661 | } | 732 | } |
662 | 733 | ||
663 | /** | 734 | /** |
664 | * ath5k_hw_set_imr - Set interrupt mask | 735 | * ath5k_hw_set_imr() - Set interrupt mask |
665 | * | ||
666 | * @ah: The &struct ath5k_hw | 736 | * @ah: The &struct ath5k_hw |
667 | * @new_mask: The new interrupt mask to be set | 737 | * @new_mask: The new interrupt mask to be set |
668 | * | 738 | * |
@@ -670,7 +740,8 @@ int ath5k_hw_get_isr(struct ath5k_hw *ah, enum ath5k_int *interrupt_mask) | |||
670 | * ath5k_int bits to hw-specific bits to remove abstraction and writing | 740 | * ath5k_int bits to hw-specific bits to remove abstraction and writing |
671 | * Interrupt Mask Register. | 741 | * Interrupt Mask Register. |
672 | */ | 742 | */ |
673 | enum ath5k_int ath5k_hw_set_imr(struct ath5k_hw *ah, enum ath5k_int new_mask) | 743 | enum ath5k_int |
744 | ath5k_hw_set_imr(struct ath5k_hw *ah, enum ath5k_int new_mask) | ||
674 | { | 745 | { |
675 | enum ath5k_int old_mask, int_mask; | 746 | enum ath5k_int old_mask, int_mask; |
676 | 747 | ||
@@ -697,16 +768,14 @@ enum ath5k_int ath5k_hw_set_imr(struct ath5k_hw *ah, enum ath5k_int new_mask) | |||
697 | u32 simr2 = ath5k_hw_reg_read(ah, AR5K_SIMR2) | 768 | u32 simr2 = ath5k_hw_reg_read(ah, AR5K_SIMR2) |
698 | & AR5K_SIMR2_QCU_TXURN; | 769 | & AR5K_SIMR2_QCU_TXURN; |
699 | 770 | ||
771 | /* Fatal interrupt abstraction for 5211+ */ | ||
700 | if (new_mask & AR5K_INT_FATAL) { | 772 | if (new_mask & AR5K_INT_FATAL) { |
701 | int_mask |= AR5K_IMR_HIUERR; | 773 | int_mask |= AR5K_IMR_HIUERR; |
702 | simr2 |= (AR5K_SIMR2_MCABT | AR5K_SIMR2_SSERR | 774 | simr2 |= (AR5K_SIMR2_MCABT | AR5K_SIMR2_SSERR |
703 | | AR5K_SIMR2_DPERR); | 775 | | AR5K_SIMR2_DPERR); |
704 | } | 776 | } |
705 | 777 | ||
706 | /*Beacon Not Ready*/ | 778 | /* Misc beacon related interrupts */ |
707 | if (new_mask & AR5K_INT_BNR) | ||
708 | int_mask |= AR5K_INT_BNR; | ||
709 | |||
710 | if (new_mask & AR5K_INT_TIM) | 779 | if (new_mask & AR5K_INT_TIM) |
711 | int_mask |= AR5K_IMR_TIM; | 780 | int_mask |= AR5K_IMR_TIM; |
712 | 781 | ||
@@ -721,8 +790,9 @@ enum ath5k_int ath5k_hw_set_imr(struct ath5k_hw *ah, enum ath5k_int new_mask) | |||
721 | if (new_mask & AR5K_INT_CAB_TIMEOUT) | 790 | if (new_mask & AR5K_INT_CAB_TIMEOUT) |
722 | simr2 |= AR5K_SISR2_CAB_TIMEOUT; | 791 | simr2 |= AR5K_SISR2_CAB_TIMEOUT; |
723 | 792 | ||
724 | if (new_mask & AR5K_INT_RX_DOPPLER) | 793 | /*Beacon Not Ready*/ |
725 | int_mask |= AR5K_IMR_RXDOPPLER; | 794 | if (new_mask & AR5K_INT_BNR) |
795 | int_mask |= AR5K_INT_BNR; | ||
726 | 796 | ||
727 | /* Note: Per queue interrupt masks | 797 | /* Note: Per queue interrupt masks |
728 | * are set via ath5k_hw_reset_tx_queue() (qcu.c) */ | 798 | * are set via ath5k_hw_reset_tx_queue() (qcu.c) */ |
@@ -730,10 +800,12 @@ enum ath5k_int ath5k_hw_set_imr(struct ath5k_hw *ah, enum ath5k_int new_mask) | |||
730 | ath5k_hw_reg_write(ah, simr2, AR5K_SIMR2); | 800 | ath5k_hw_reg_write(ah, simr2, AR5K_SIMR2); |
731 | 801 | ||
732 | } else { | 802 | } else { |
803 | /* Fatal interrupt abstraction for 5210 */ | ||
733 | if (new_mask & AR5K_INT_FATAL) | 804 | if (new_mask & AR5K_INT_FATAL) |
734 | int_mask |= (AR5K_IMR_SSERR | AR5K_IMR_MCABT | 805 | int_mask |= (AR5K_IMR_SSERR | AR5K_IMR_MCABT |
735 | | AR5K_IMR_HIUERR | AR5K_IMR_DPERR); | 806 | | AR5K_IMR_HIUERR | AR5K_IMR_DPERR); |
736 | 807 | ||
808 | /* Only common interrupts left for 5210 (no SIMRs) */ | ||
737 | ath5k_hw_reg_write(ah, int_mask, AR5K_IMR); | 809 | ath5k_hw_reg_write(ah, int_mask, AR5K_IMR); |
738 | } | 810 | } |
739 | 811 | ||
@@ -760,8 +832,7 @@ enum ath5k_int ath5k_hw_set_imr(struct ath5k_hw *ah, enum ath5k_int new_mask) | |||
760 | \********************/ | 832 | \********************/ |
761 | 833 | ||
762 | /** | 834 | /** |
763 | * ath5k_hw_dma_init - Initialize DMA unit | 835 | * ath5k_hw_dma_init() - Initialize DMA unit |
764 | * | ||
765 | * @ah: The &struct ath5k_hw | 836 | * @ah: The &struct ath5k_hw |
766 | * | 837 | * |
767 | * Set DMA size and pre-enable interrupts | 838 | * Set DMA size and pre-enable interrupts |
@@ -770,7 +841,8 @@ enum ath5k_int ath5k_hw_set_imr(struct ath5k_hw *ah, enum ath5k_int new_mask) | |||
770 | * | 841 | * |
771 | * XXX: Save/restore RXDP/TXDP registers ? | 842 | * XXX: Save/restore RXDP/TXDP registers ? |
772 | */ | 843 | */ |
773 | void ath5k_hw_dma_init(struct ath5k_hw *ah) | 844 | void |
845 | ath5k_hw_dma_init(struct ath5k_hw *ah) | ||
774 | { | 846 | { |
775 | /* | 847 | /* |
776 | * Set Rx/Tx DMA Configuration | 848 | * Set Rx/Tx DMA Configuration |
@@ -799,8 +871,7 @@ void ath5k_hw_dma_init(struct ath5k_hw *ah) | |||
799 | } | 871 | } |
800 | 872 | ||
801 | /** | 873 | /** |
802 | * ath5k_hw_dma_stop - stop DMA unit | 874 | * ath5k_hw_dma_stop() - stop DMA unit |
803 | * | ||
804 | * @ah: The &struct ath5k_hw | 875 | * @ah: The &struct ath5k_hw |
805 | * | 876 | * |
806 | * Stop tx/rx DMA and interrupts. Returns | 877 | * Stop tx/rx DMA and interrupts. Returns |
@@ -810,7 +881,8 @@ void ath5k_hw_dma_init(struct ath5k_hw *ah) | |||
810 | * stuck frames on tx queues, only a reset | 881 | * stuck frames on tx queues, only a reset |
811 | * can fix that. | 882 | * can fix that. |
812 | */ | 883 | */ |
813 | int ath5k_hw_dma_stop(struct ath5k_hw *ah) | 884 | int |
885 | ath5k_hw_dma_stop(struct ath5k_hw *ah) | ||
814 | { | 886 | { |
815 | int i, qmax, err; | 887 | int i, qmax, err; |
816 | err = 0; | 888 | err = 0; |
diff --git a/drivers/net/wireless/ath/ath5k/gpio.c b/drivers/net/wireless/ath/ath5k/gpio.c index 859297811914..73d3dd8a306a 100644 --- a/drivers/net/wireless/ath/ath5k/gpio.c +++ b/drivers/net/wireless/ath/ath5k/gpio.c | |||
@@ -24,10 +24,33 @@ | |||
24 | #include "reg.h" | 24 | #include "reg.h" |
25 | #include "debug.h" | 25 | #include "debug.h" |
26 | 26 | ||
27 | /* | 27 | |
28 | * Set led state | 28 | /** |
29 | * DOC: GPIO/LED functions | ||
30 | * | ||
31 | * Here we control the 6 bidirectional GPIO pins provided by the hw. | ||
32 | * We can set a GPIO pin to be an input or an output pin on GPIO control | ||
33 | * register and then read or set its status from GPIO data input/output | ||
34 | * registers. | ||
35 | * | ||
36 | * We also control the two LED pins provided by the hw, LED_0 is our | ||
37 | * "power" LED and LED_1 is our "network activity" LED but many scenarios | ||
38 | * are available from hw. Vendors might also provide LEDs connected to the | ||
39 | * GPIO pins, we handle them through the LED subsystem on led.c | ||
40 | */ | ||
41 | |||
42 | |||
43 | /** | ||
44 | * ath5k_hw_set_ledstate() - Set led state | ||
45 | * @ah: The &struct ath5k_hw | ||
46 | * @state: One of AR5K_LED_* | ||
47 | * | ||
48 | * Used to set the LED blinking state. This only | ||
49 | * works for the LED connected to the LED_0, LED_1 pins, | ||
50 | * not the GPIO based. | ||
29 | */ | 51 | */ |
30 | void ath5k_hw_set_ledstate(struct ath5k_hw *ah, unsigned int state) | 52 | void |
53 | ath5k_hw_set_ledstate(struct ath5k_hw *ah, unsigned int state) | ||
31 | { | 54 | { |
32 | u32 led; | 55 | u32 led; |
33 | /*5210 has different led mode handling*/ | 56 | /*5210 has different led mode handling*/ |
@@ -74,10 +97,13 @@ void ath5k_hw_set_ledstate(struct ath5k_hw *ah, unsigned int state) | |||
74 | AR5K_REG_ENABLE_BITS(ah, AR5K_PCICFG, led_5210); | 97 | AR5K_REG_ENABLE_BITS(ah, AR5K_PCICFG, led_5210); |
75 | } | 98 | } |
76 | 99 | ||
77 | /* | 100 | /** |
78 | * Set GPIO inputs | 101 | * ath5k_hw_set_gpio_input() - Set GPIO inputs |
102 | * @ah: The &struct ath5k_hw | ||
103 | * @gpio: GPIO pin to set as input | ||
79 | */ | 104 | */ |
80 | int ath5k_hw_set_gpio_input(struct ath5k_hw *ah, u32 gpio) | 105 | int |
106 | ath5k_hw_set_gpio_input(struct ath5k_hw *ah, u32 gpio) | ||
81 | { | 107 | { |
82 | if (gpio >= AR5K_NUM_GPIO) | 108 | if (gpio >= AR5K_NUM_GPIO) |
83 | return -EINVAL; | 109 | return -EINVAL; |
@@ -89,10 +115,13 @@ int ath5k_hw_set_gpio_input(struct ath5k_hw *ah, u32 gpio) | |||
89 | return 0; | 115 | return 0; |
90 | } | 116 | } |
91 | 117 | ||
92 | /* | 118 | /** |
93 | * Set GPIO outputs | 119 | * ath5k_hw_set_gpio_output() - Set GPIO outputs |
120 | * @ah: The &struct ath5k_hw | ||
121 | * @gpio: The GPIO pin to set as output | ||
94 | */ | 122 | */ |
95 | int ath5k_hw_set_gpio_output(struct ath5k_hw *ah, u32 gpio) | 123 | int |
124 | ath5k_hw_set_gpio_output(struct ath5k_hw *ah, u32 gpio) | ||
96 | { | 125 | { |
97 | if (gpio >= AR5K_NUM_GPIO) | 126 | if (gpio >= AR5K_NUM_GPIO) |
98 | return -EINVAL; | 127 | return -EINVAL; |
@@ -104,10 +133,13 @@ int ath5k_hw_set_gpio_output(struct ath5k_hw *ah, u32 gpio) | |||
104 | return 0; | 133 | return 0; |
105 | } | 134 | } |
106 | 135 | ||
107 | /* | 136 | /** |
108 | * Get GPIO state | 137 | * ath5k_hw_get_gpio() - Get GPIO state |
138 | * @ah: The &struct ath5k_hw | ||
139 | * @gpio: The GPIO pin to read | ||
109 | */ | 140 | */ |
110 | u32 ath5k_hw_get_gpio(struct ath5k_hw *ah, u32 gpio) | 141 | u32 |
142 | ath5k_hw_get_gpio(struct ath5k_hw *ah, u32 gpio) | ||
111 | { | 143 | { |
112 | if (gpio >= AR5K_NUM_GPIO) | 144 | if (gpio >= AR5K_NUM_GPIO) |
113 | return 0xffffffff; | 145 | return 0xffffffff; |
@@ -117,10 +149,14 @@ u32 ath5k_hw_get_gpio(struct ath5k_hw *ah, u32 gpio) | |||
117 | 0x1; | 149 | 0x1; |
118 | } | 150 | } |
119 | 151 | ||
120 | /* | 152 | /** |
121 | * Set GPIO state | 153 | * ath5k_hw_set_gpio() - Set GPIO state |
154 | * @ah: The &struct ath5k_hw | ||
155 | * @gpio: The GPIO pin to set | ||
156 | * @val: Value to set (boolean) | ||
122 | */ | 157 | */ |
123 | int ath5k_hw_set_gpio(struct ath5k_hw *ah, u32 gpio, u32 val) | 158 | int |
159 | ath5k_hw_set_gpio(struct ath5k_hw *ah, u32 gpio, u32 val) | ||
124 | { | 160 | { |
125 | u32 data; | 161 | u32 data; |
126 | 162 | ||
@@ -138,10 +174,19 @@ int ath5k_hw_set_gpio(struct ath5k_hw *ah, u32 gpio, u32 val) | |||
138 | return 0; | 174 | return 0; |
139 | } | 175 | } |
140 | 176 | ||
141 | /* | 177 | /** |
142 | * Initialize the GPIO interrupt (RFKill switch) | 178 | * ath5k_hw_set_gpio_intr() - Initialize the GPIO interrupt (RFKill switch) |
179 | * @ah: The &struct ath5k_hw | ||
180 | * @gpio: The GPIO pin to use | ||
181 | * @interrupt_level: True to generate interrupt on active pin (high) | ||
182 | * | ||
183 | * This function is used to set up the GPIO interrupt for the hw RFKill switch. | ||
184 | * That switch is connected to a GPIO pin and it's number is stored on EEPROM. | ||
185 | * It can either open or close the circuit to indicate that we should disable | ||
186 | * RF/Wireless to save power (we also get that from EEPROM). | ||
143 | */ | 187 | */ |
144 | void ath5k_hw_set_gpio_intr(struct ath5k_hw *ah, unsigned int gpio, | 188 | void |
189 | ath5k_hw_set_gpio_intr(struct ath5k_hw *ah, unsigned int gpio, | ||
145 | u32 interrupt_level) | 190 | u32 interrupt_level) |
146 | { | 191 | { |
147 | u32 data; | 192 | u32 data; |
diff --git a/drivers/net/wireless/ath/ath5k/initvals.c b/drivers/net/wireless/ath/ath5k/initvals.c index 1ffecc0fd3ed..a1ea78e05b47 100644 --- a/drivers/net/wireless/ath/ath5k/initvals.c +++ b/drivers/net/wireless/ath/ath5k/initvals.c | |||
@@ -23,24 +23,27 @@ | |||
23 | #include "reg.h" | 23 | #include "reg.h" |
24 | #include "debug.h" | 24 | #include "debug.h" |
25 | 25 | ||
26 | /* | 26 | /** |
27 | * Mode-independent initial register writes | 27 | * struct ath5k_ini - Mode-independent initial register writes |
28 | * @ini_register: Register address | ||
29 | * @ini_value: Default value | ||
30 | * @ini_mode: 0 to write 1 to read (and clear) | ||
28 | */ | 31 | */ |
29 | |||
30 | struct ath5k_ini { | 32 | struct ath5k_ini { |
31 | u16 ini_register; | 33 | u16 ini_register; |
32 | u32 ini_value; | 34 | u32 ini_value; |
33 | 35 | ||
34 | enum { | 36 | enum { |
35 | AR5K_INI_WRITE = 0, /* Default */ | 37 | AR5K_INI_WRITE = 0, /* Default */ |
36 | AR5K_INI_READ = 1, /* Cleared on read */ | 38 | AR5K_INI_READ = 1, |
37 | } ini_mode; | 39 | } ini_mode; |
38 | }; | 40 | }; |
39 | 41 | ||
40 | /* | 42 | /** |
41 | * Mode specific initial register values | 43 | * struct ath5k_ini_mode - Mode specific initial register values |
44 | * @mode_register: Register address | ||
45 | * @mode_value: Set of values for each enum ath5k_driver_mode | ||
42 | */ | 46 | */ |
43 | |||
44 | struct ath5k_ini_mode { | 47 | struct ath5k_ini_mode { |
45 | u16 mode_register; | 48 | u16 mode_register; |
46 | u32 mode_value[3]; | 49 | u32 mode_value[3]; |
@@ -386,11 +389,10 @@ static const struct ath5k_ini ar5211_ini[] = { | |||
386 | 389 | ||
387 | /* Initial mode-specific settings for AR5211 | 390 | /* Initial mode-specific settings for AR5211 |
388 | * 5211 supports OFDM-only g (draft g) but we | 391 | * 5211 supports OFDM-only g (draft g) but we |
389 | * need to test it ! | 392 | * need to test it ! */ |
390 | */ | ||
391 | static const struct ath5k_ini_mode ar5211_ini_mode[] = { | 393 | static const struct ath5k_ini_mode ar5211_ini_mode[] = { |
392 | { AR5K_TXCFG, | 394 | { AR5K_TXCFG, |
393 | /* A/XR B G */ | 395 | /* A B G */ |
394 | { 0x00000015, 0x0000001d, 0x00000015 } }, | 396 | { 0x00000015, 0x0000001d, 0x00000015 } }, |
395 | { AR5K_QUEUE_DFS_LOCAL_IFS(0), | 397 | { AR5K_QUEUE_DFS_LOCAL_IFS(0), |
396 | { 0x002ffc0f, 0x002ffc1f, 0x002ffc0f } }, | 398 | { 0x002ffc0f, 0x002ffc1f, 0x002ffc0f } }, |
@@ -460,7 +462,7 @@ static const struct ath5k_ini_mode ar5211_ini_mode[] = { | |||
460 | { 0x00000010, 0x00000010, 0x00000010 } }, | 462 | { 0x00000010, 0x00000010, 0x00000010 } }, |
461 | }; | 463 | }; |
462 | 464 | ||
463 | /* Initial register settings for AR5212 */ | 465 | /* Initial register settings for AR5212 and newer chips */ |
464 | static const struct ath5k_ini ar5212_ini_common_start[] = { | 466 | static const struct ath5k_ini ar5212_ini_common_start[] = { |
465 | { AR5K_RXDP, 0x00000000 }, | 467 | { AR5K_RXDP, 0x00000000 }, |
466 | { AR5K_RXCFG, 0x00000005 }, | 468 | { AR5K_RXCFG, 0x00000005 }, |
@@ -724,7 +726,8 @@ static const struct ath5k_ini_mode ar5212_ini_mode_start[] = { | |||
724 | { 0x00000000, 0x00000000, 0x00000108 } }, | 726 | { 0x00000000, 0x00000000, 0x00000108 } }, |
725 | }; | 727 | }; |
726 | 728 | ||
727 | /* Initial mode-specific settings for AR5212 + RF5111 (Written after ar5212_ini) */ | 729 | /* Initial mode-specific settings for AR5212 + RF5111 |
730 | * (Written after ar5212_ini) */ | ||
728 | static const struct ath5k_ini_mode rf5111_ini_mode_end[] = { | 731 | static const struct ath5k_ini_mode rf5111_ini_mode_end[] = { |
729 | { AR5K_TXCFG, | 732 | { AR5K_TXCFG, |
730 | /* A/XR B G */ | 733 | /* A/XR B G */ |
@@ -757,6 +760,7 @@ static const struct ath5k_ini_mode rf5111_ini_mode_end[] = { | |||
757 | { 0x1883800a, 0x1873800a, 0x1883800a } }, | 760 | { 0x1883800a, 0x1873800a, 0x1883800a } }, |
758 | }; | 761 | }; |
759 | 762 | ||
763 | /* Common for all modes */ | ||
760 | static const struct ath5k_ini rf5111_ini_common_end[] = { | 764 | static const struct ath5k_ini rf5111_ini_common_end[] = { |
761 | { AR5K_DCU_FP, 0x00000000 }, | 765 | { AR5K_DCU_FP, 0x00000000 }, |
762 | { AR5K_PHY_AGC, 0x00000000 }, | 766 | { AR5K_PHY_AGC, 0x00000000 }, |
@@ -774,7 +778,9 @@ static const struct ath5k_ini rf5111_ini_common_end[] = { | |||
774 | { 0xa23c, 0x13c889af }, | 778 | { 0xa23c, 0x13c889af }, |
775 | }; | 779 | }; |
776 | 780 | ||
777 | /* Initial mode-specific settings for AR5212 + RF5112 (Written after ar5212_ini) */ | 781 | |
782 | /* Initial mode-specific settings for AR5212 + RF5112 | ||
783 | * (Written after ar5212_ini) */ | ||
778 | static const struct ath5k_ini_mode rf5112_ini_mode_end[] = { | 784 | static const struct ath5k_ini_mode rf5112_ini_mode_end[] = { |
779 | { AR5K_TXCFG, | 785 | { AR5K_TXCFG, |
780 | /* A/XR B G */ | 786 | /* A/XR B G */ |
@@ -825,7 +831,9 @@ static const struct ath5k_ini rf5112_ini_common_end[] = { | |||
825 | { 0xa23c, 0x13c889af }, | 831 | { 0xa23c, 0x13c889af }, |
826 | }; | 832 | }; |
827 | 833 | ||
828 | /* Initial mode-specific settings for RF5413/5414 (Written after ar5212_ini) */ | 834 | |
835 | /* Initial mode-specific settings for RF5413/5414 | ||
836 | * (Written after ar5212_ini) */ | ||
829 | static const struct ath5k_ini_mode rf5413_ini_mode_end[] = { | 837 | static const struct ath5k_ini_mode rf5413_ini_mode_end[] = { |
830 | { AR5K_TXCFG, | 838 | { AR5K_TXCFG, |
831 | /* A/XR B G */ | 839 | /* A/XR B G */ |
@@ -963,7 +971,8 @@ static const struct ath5k_ini rf5413_ini_common_end[] = { | |||
963 | { 0xa384, 0xf3307ff0 }, | 971 | { 0xa384, 0xf3307ff0 }, |
964 | }; | 972 | }; |
965 | 973 | ||
966 | /* Initial mode-specific settings for RF2413/2414 (Written after ar5212_ini) */ | 974 | /* Initial mode-specific settings for RF2413/2414 |
975 | * (Written after ar5212_ini) */ | ||
967 | /* XXX: a mode ? */ | 976 | /* XXX: a mode ? */ |
968 | static const struct ath5k_ini_mode rf2413_ini_mode_end[] = { | 977 | static const struct ath5k_ini_mode rf2413_ini_mode_end[] = { |
969 | { AR5K_TXCFG, | 978 | { AR5K_TXCFG, |
@@ -1085,7 +1094,8 @@ static const struct ath5k_ini rf2413_ini_common_end[] = { | |||
1085 | { 0xa384, 0xf3307ff0 }, | 1094 | { 0xa384, 0xf3307ff0 }, |
1086 | }; | 1095 | }; |
1087 | 1096 | ||
1088 | /* Initial mode-specific settings for RF2425 (Written after ar5212_ini) */ | 1097 | /* Initial mode-specific settings for RF2425 |
1098 | * (Written after ar5212_ini) */ | ||
1089 | /* XXX: a mode ? */ | 1099 | /* XXX: a mode ? */ |
1090 | static const struct ath5k_ini_mode rf2425_ini_mode_end[] = { | 1100 | static const struct ath5k_ini_mode rf2425_ini_mode_end[] = { |
1091 | { AR5K_TXCFG, | 1101 | { AR5K_TXCFG, |
@@ -1357,10 +1367,15 @@ static const struct ath5k_ini rf5112_ini_bbgain[] = { | |||
1357 | }; | 1367 | }; |
1358 | 1368 | ||
1359 | 1369 | ||
1360 | /* | 1370 | /** |
1361 | * Write initial register dump | 1371 | * ath5k_hw_ini_registers() - Write initial register dump common for all modes |
1372 | * @ah: The &struct ath5k_hw | ||
1373 | * @size: Dump size | ||
1374 | * @ini_regs: The array of &struct ath5k_ini | ||
1375 | * @skip_pcu: Skip PCU registers | ||
1362 | */ | 1376 | */ |
1363 | static void ath5k_hw_ini_registers(struct ath5k_hw *ah, unsigned int size, | 1377 | static void |
1378 | ath5k_hw_ini_registers(struct ath5k_hw *ah, unsigned int size, | ||
1364 | const struct ath5k_ini *ini_regs, bool skip_pcu) | 1379 | const struct ath5k_ini *ini_regs, bool skip_pcu) |
1365 | { | 1380 | { |
1366 | unsigned int i; | 1381 | unsigned int i; |
@@ -1388,7 +1403,15 @@ static void ath5k_hw_ini_registers(struct ath5k_hw *ah, unsigned int size, | |||
1388 | } | 1403 | } |
1389 | } | 1404 | } |
1390 | 1405 | ||
1391 | static void ath5k_hw_ini_mode_registers(struct ath5k_hw *ah, | 1406 | /** |
1407 | * ath5k_hw_ini_mode_registers() - Write initial mode-specific register dump | ||
1408 | * @ah: The &struct ath5k_hw | ||
1409 | * @size: Dump size | ||
1410 | * @ini_mode: The array of &struct ath5k_ini_mode | ||
1411 | * @mode: One of enum ath5k_driver_mode | ||
1412 | */ | ||
1413 | static void | ||
1414 | ath5k_hw_ini_mode_registers(struct ath5k_hw *ah, | ||
1392 | unsigned int size, const struct ath5k_ini_mode *ini_mode, | 1415 | unsigned int size, const struct ath5k_ini_mode *ini_mode, |
1393 | u8 mode) | 1416 | u8 mode) |
1394 | { | 1417 | { |
@@ -1402,7 +1425,17 @@ static void ath5k_hw_ini_mode_registers(struct ath5k_hw *ah, | |||
1402 | 1425 | ||
1403 | } | 1426 | } |
1404 | 1427 | ||
1405 | int ath5k_hw_write_initvals(struct ath5k_hw *ah, u8 mode, bool skip_pcu) | 1428 | /** |
1429 | * ath5k_hw_write_initvals() - Write initial chip-specific register dump | ||
1430 | * @ah: The &struct ath5k_hw | ||
1431 | * @mode: One of enum ath5k_driver_mode | ||
1432 | * @skip_pcu: Skip PCU registers | ||
1433 | * | ||
1434 | * Write initial chip-specific register dump, to get the chipset on a | ||
1435 | * clean and ready-to-work state after warm reset. | ||
1436 | */ | ||
1437 | int | ||
1438 | ath5k_hw_write_initvals(struct ath5k_hw *ah, u8 mode, bool skip_pcu) | ||
1406 | { | 1439 | { |
1407 | /* | 1440 | /* |
1408 | * Write initial register settings | 1441 | * Write initial register settings |
diff --git a/drivers/net/wireless/ath/ath5k/pci.c b/drivers/net/wireless/ath/ath5k/pci.c index c1dff2ced044..849fa060ebc4 100644 --- a/drivers/net/wireless/ath/ath5k/pci.c +++ b/drivers/net/wireless/ath/ath5k/pci.c | |||
@@ -18,6 +18,7 @@ | |||
18 | #include <linux/pci.h> | 18 | #include <linux/pci.h> |
19 | #include <linux/pci-aspm.h> | 19 | #include <linux/pci-aspm.h> |
20 | #include <linux/etherdevice.h> | 20 | #include <linux/etherdevice.h> |
21 | #include <linux/module.h> | ||
21 | #include "../ath.h" | 22 | #include "../ath.h" |
22 | #include "ath5k.h" | 23 | #include "ath5k.h" |
23 | #include "debug.h" | 24 | #include "debug.h" |
@@ -97,7 +98,7 @@ ath5k_pci_eeprom_read(struct ath_common *common, u32 offset, u16 *data) | |||
97 | 0xffff); | 98 | 0xffff); |
98 | return true; | 99 | return true; |
99 | } | 100 | } |
100 | udelay(15); | 101 | usleep_range(15, 20); |
101 | } | 102 | } |
102 | 103 | ||
103 | return false; | 104 | return false; |
diff --git a/drivers/net/wireless/ath/ath5k/pcu.c b/drivers/net/wireless/ath/ath5k/pcu.c index a7eafa3edc21..cebfd6fd31d3 100644 --- a/drivers/net/wireless/ath/ath5k/pcu.c +++ b/drivers/net/wireless/ath/ath5k/pcu.c | |||
@@ -30,11 +30,47 @@ | |||
30 | #include "reg.h" | 30 | #include "reg.h" |
31 | #include "debug.h" | 31 | #include "debug.h" |
32 | 32 | ||
33 | /* | 33 | /** |
34 | * DOC: Protocol Control Unit (PCU) functions | ||
35 | * | ||
36 | * Protocol control unit is responsible to maintain various protocol | ||
37 | * properties before a frame is send and after a frame is received to/from | ||
38 | * baseband. To be more specific, PCU handles: | ||
39 | * | ||
40 | * - Buffering of RX and TX frames (after QCU/DCUs) | ||
41 | * | ||
42 | * - Encrypting and decrypting (using the built-in engine) | ||
43 | * | ||
44 | * - Generating ACKs, RTS/CTS frames | ||
45 | * | ||
46 | * - Maintaining TSF | ||
47 | * | ||
48 | * - FCS | ||
49 | * | ||
50 | * - Updating beacon data (with TSF etc) | ||
51 | * | ||
52 | * - Generating virtual CCA | ||
53 | * | ||
54 | * - RX/Multicast filtering | ||
55 | * | ||
56 | * - BSSID filtering | ||
57 | * | ||
58 | * - Various statistics | ||
59 | * | ||
60 | * -Different operating modes: AP, STA, IBSS | ||
61 | * | ||
62 | * Note: Most of these functions can be tweaked/bypassed so you can do | ||
63 | * them on sw above for debugging or research. For more infos check out PCU | ||
64 | * registers on reg.h. | ||
65 | */ | ||
66 | |||
67 | /** | ||
68 | * DOC: ACK rates | ||
69 | * | ||
34 | * AR5212+ can use higher rates for ack transmission | 70 | * AR5212+ can use higher rates for ack transmission |
35 | * based on current tx rate instead of the base rate. | 71 | * based on current tx rate instead of the base rate. |
36 | * It does this to better utilize channel usage. | 72 | * It does this to better utilize channel usage. |
37 | * This is a mapping between G rates (that cover both | 73 | * There is a mapping between G rates (that cover both |
38 | * CCK and OFDM) and ack rates that we use when setting | 74 | * CCK and OFDM) and ack rates that we use when setting |
39 | * rate -> duration table. This mapping is hw-based so | 75 | * rate -> duration table. This mapping is hw-based so |
40 | * don't change anything. | 76 | * don't change anything. |
@@ -63,17 +99,18 @@ static const unsigned int ack_rates_high[] = | |||
63 | \*******************/ | 99 | \*******************/ |
64 | 100 | ||
65 | /** | 101 | /** |
66 | * ath5k_hw_get_frame_duration - Get tx time of a frame | 102 | * ath5k_hw_get_frame_duration() - Get tx time of a frame |
67 | * | ||
68 | * @ah: The &struct ath5k_hw | 103 | * @ah: The &struct ath5k_hw |
69 | * @len: Frame's length in bytes | 104 | * @len: Frame's length in bytes |
70 | * @rate: The @struct ieee80211_rate | 105 | * @rate: The @struct ieee80211_rate |
106 | * @shortpre: Indicate short preample | ||
71 | * | 107 | * |
72 | * Calculate tx duration of a frame given it's rate and length | 108 | * Calculate tx duration of a frame given it's rate and length |
73 | * It extends ieee80211_generic_frame_duration for non standard | 109 | * It extends ieee80211_generic_frame_duration for non standard |
74 | * bwmodes. | 110 | * bwmodes. |
75 | */ | 111 | */ |
76 | int ath5k_hw_get_frame_duration(struct ath5k_hw *ah, | 112 | int |
113 | ath5k_hw_get_frame_duration(struct ath5k_hw *ah, | ||
77 | int len, struct ieee80211_rate *rate, bool shortpre) | 114 | int len, struct ieee80211_rate *rate, bool shortpre) |
78 | { | 115 | { |
79 | int sifs, preamble, plcp_bits, sym_time; | 116 | int sifs, preamble, plcp_bits, sym_time; |
@@ -129,11 +166,11 @@ int ath5k_hw_get_frame_duration(struct ath5k_hw *ah, | |||
129 | } | 166 | } |
130 | 167 | ||
131 | /** | 168 | /** |
132 | * ath5k_hw_get_default_slottime - Get the default slot time for current mode | 169 | * ath5k_hw_get_default_slottime() - Get the default slot time for current mode |
133 | * | ||
134 | * @ah: The &struct ath5k_hw | 170 | * @ah: The &struct ath5k_hw |
135 | */ | 171 | */ |
136 | unsigned int ath5k_hw_get_default_slottime(struct ath5k_hw *ah) | 172 | unsigned int |
173 | ath5k_hw_get_default_slottime(struct ath5k_hw *ah) | ||
137 | { | 174 | { |
138 | struct ieee80211_channel *channel = ah->ah_current_channel; | 175 | struct ieee80211_channel *channel = ah->ah_current_channel; |
139 | unsigned int slot_time; | 176 | unsigned int slot_time; |
@@ -160,11 +197,11 @@ unsigned int ath5k_hw_get_default_slottime(struct ath5k_hw *ah) | |||
160 | } | 197 | } |
161 | 198 | ||
162 | /** | 199 | /** |
163 | * ath5k_hw_get_default_sifs - Get the default SIFS for current mode | 200 | * ath5k_hw_get_default_sifs() - Get the default SIFS for current mode |
164 | * | ||
165 | * @ah: The &struct ath5k_hw | 201 | * @ah: The &struct ath5k_hw |
166 | */ | 202 | */ |
167 | unsigned int ath5k_hw_get_default_sifs(struct ath5k_hw *ah) | 203 | unsigned int |
204 | ath5k_hw_get_default_sifs(struct ath5k_hw *ah) | ||
168 | { | 205 | { |
169 | struct ieee80211_channel *channel = ah->ah_current_channel; | 206 | struct ieee80211_channel *channel = ah->ah_current_channel; |
170 | unsigned int sifs; | 207 | unsigned int sifs; |
@@ -191,17 +228,17 @@ unsigned int ath5k_hw_get_default_sifs(struct ath5k_hw *ah) | |||
191 | } | 228 | } |
192 | 229 | ||
193 | /** | 230 | /** |
194 | * ath5k_hw_update_mib_counters - Update MIB counters (mac layer statistics) | 231 | * ath5k_hw_update_mib_counters() - Update MIB counters (mac layer statistics) |
195 | * | ||
196 | * @ah: The &struct ath5k_hw | 232 | * @ah: The &struct ath5k_hw |
197 | * | 233 | * |
198 | * Reads MIB counters from PCU and updates sw statistics. Is called after a | 234 | * Reads MIB counters from PCU and updates sw statistics. Is called after a |
199 | * MIB interrupt, because one of these counters might have reached their maximum | 235 | * MIB interrupt, because one of these counters might have reached their maximum |
200 | * and triggered the MIB interrupt, to let us read and clear the counter. | 236 | * and triggered the MIB interrupt, to let us read and clear the counter. |
201 | * | 237 | * |
202 | * Is called in interrupt context! | 238 | * NOTE: Is called in interrupt context! |
203 | */ | 239 | */ |
204 | void ath5k_hw_update_mib_counters(struct ath5k_hw *ah) | 240 | void |
241 | ath5k_hw_update_mib_counters(struct ath5k_hw *ah) | ||
205 | { | 242 | { |
206 | struct ath5k_statistics *stats = &ah->stats; | 243 | struct ath5k_statistics *stats = &ah->stats; |
207 | 244 | ||
@@ -219,10 +256,8 @@ void ath5k_hw_update_mib_counters(struct ath5k_hw *ah) | |||
219 | \******************/ | 256 | \******************/ |
220 | 257 | ||
221 | /** | 258 | /** |
222 | * ath5k_hw_write_rate_duration - fill rate code to duration table | 259 | * ath5k_hw_write_rate_duration() - Fill rate code to duration table |
223 | * | 260 | * @ah: The &struct ath5k_hw |
224 | * @ah: the &struct ath5k_hw | ||
225 | * @mode: one of enum ath5k_driver_mode | ||
226 | * | 261 | * |
227 | * Write the rate code to duration table upon hw reset. This is a helper for | 262 | * Write the rate code to duration table upon hw reset. This is a helper for |
228 | * ath5k_hw_pcu_init(). It seems all this is doing is setting an ACK timeout on | 263 | * ath5k_hw_pcu_init(). It seems all this is doing is setting an ACK timeout on |
@@ -236,7 +271,8 @@ void ath5k_hw_update_mib_counters(struct ath5k_hw *ah) | |||
236 | * that include all OFDM and CCK rates. | 271 | * that include all OFDM and CCK rates. |
237 | * | 272 | * |
238 | */ | 273 | */ |
239 | static inline void ath5k_hw_write_rate_duration(struct ath5k_hw *ah) | 274 | static inline void |
275 | ath5k_hw_write_rate_duration(struct ath5k_hw *ah) | ||
240 | { | 276 | { |
241 | struct ieee80211_rate *rate; | 277 | struct ieee80211_rate *rate; |
242 | unsigned int i; | 278 | unsigned int i; |
@@ -280,12 +316,12 @@ static inline void ath5k_hw_write_rate_duration(struct ath5k_hw *ah) | |||
280 | } | 316 | } |
281 | 317 | ||
282 | /** | 318 | /** |
283 | * ath5k_hw_set_ack_timeout - Set ACK timeout on PCU | 319 | * ath5k_hw_set_ack_timeout() - Set ACK timeout on PCU |
284 | * | ||
285 | * @ah: The &struct ath5k_hw | 320 | * @ah: The &struct ath5k_hw |
286 | * @timeout: Timeout in usec | 321 | * @timeout: Timeout in usec |
287 | */ | 322 | */ |
288 | static int ath5k_hw_set_ack_timeout(struct ath5k_hw *ah, unsigned int timeout) | 323 | static int |
324 | ath5k_hw_set_ack_timeout(struct ath5k_hw *ah, unsigned int timeout) | ||
289 | { | 325 | { |
290 | if (ath5k_hw_clocktoh(ah, AR5K_REG_MS(0xffffffff, AR5K_TIME_OUT_ACK)) | 326 | if (ath5k_hw_clocktoh(ah, AR5K_REG_MS(0xffffffff, AR5K_TIME_OUT_ACK)) |
291 | <= timeout) | 327 | <= timeout) |
@@ -298,12 +334,12 @@ static int ath5k_hw_set_ack_timeout(struct ath5k_hw *ah, unsigned int timeout) | |||
298 | } | 334 | } |
299 | 335 | ||
300 | /** | 336 | /** |
301 | * ath5k_hw_set_cts_timeout - Set CTS timeout on PCU | 337 | * ath5k_hw_set_cts_timeout() - Set CTS timeout on PCU |
302 | * | ||
303 | * @ah: The &struct ath5k_hw | 338 | * @ah: The &struct ath5k_hw |
304 | * @timeout: Timeout in usec | 339 | * @timeout: Timeout in usec |
305 | */ | 340 | */ |
306 | static int ath5k_hw_set_cts_timeout(struct ath5k_hw *ah, unsigned int timeout) | 341 | static int |
342 | ath5k_hw_set_cts_timeout(struct ath5k_hw *ah, unsigned int timeout) | ||
307 | { | 343 | { |
308 | if (ath5k_hw_clocktoh(ah, AR5K_REG_MS(0xffffffff, AR5K_TIME_OUT_CTS)) | 344 | if (ath5k_hw_clocktoh(ah, AR5K_REG_MS(0xffffffff, AR5K_TIME_OUT_CTS)) |
309 | <= timeout) | 345 | <= timeout) |
@@ -321,14 +357,14 @@ static int ath5k_hw_set_cts_timeout(struct ath5k_hw *ah, unsigned int timeout) | |||
321 | \*******************/ | 357 | \*******************/ |
322 | 358 | ||
323 | /** | 359 | /** |
324 | * ath5k_hw_set_lladdr - Set station id | 360 | * ath5k_hw_set_lladdr() - Set station id |
325 | * | ||
326 | * @ah: The &struct ath5k_hw | 361 | * @ah: The &struct ath5k_hw |
327 | * @mac: The card's mac address | 362 | * @mac: The card's mac address (array of octets) |
328 | * | 363 | * |
329 | * Set station id on hw using the provided mac address | 364 | * Set station id on hw using the provided mac address |
330 | */ | 365 | */ |
331 | int ath5k_hw_set_lladdr(struct ath5k_hw *ah, const u8 *mac) | 366 | int |
367 | ath5k_hw_set_lladdr(struct ath5k_hw *ah, const u8 *mac) | ||
332 | { | 368 | { |
333 | struct ath_common *common = ath5k_hw_common(ah); | 369 | struct ath_common *common = ath5k_hw_common(ah); |
334 | u32 low_id, high_id; | 370 | u32 low_id, high_id; |
@@ -349,14 +385,14 @@ int ath5k_hw_set_lladdr(struct ath5k_hw *ah, const u8 *mac) | |||
349 | } | 385 | } |
350 | 386 | ||
351 | /** | 387 | /** |
352 | * ath5k_hw_set_bssid - Set current BSSID on hw | 388 | * ath5k_hw_set_bssid() - Set current BSSID on hw |
353 | * | ||
354 | * @ah: The &struct ath5k_hw | 389 | * @ah: The &struct ath5k_hw |
355 | * | 390 | * |
356 | * Sets the current BSSID and BSSID mask we have from the | 391 | * Sets the current BSSID and BSSID mask we have from the |
357 | * common struct into the hardware | 392 | * common struct into the hardware |
358 | */ | 393 | */ |
359 | void ath5k_hw_set_bssid(struct ath5k_hw *ah) | 394 | void |
395 | ath5k_hw_set_bssid(struct ath5k_hw *ah) | ||
360 | { | 396 | { |
361 | struct ath_common *common = ath5k_hw_common(ah); | 397 | struct ath_common *common = ath5k_hw_common(ah); |
362 | u16 tim_offset = 0; | 398 | u16 tim_offset = 0; |
@@ -389,7 +425,23 @@ void ath5k_hw_set_bssid(struct ath5k_hw *ah) | |||
389 | ath5k_hw_enable_pspoll(ah, NULL, 0); | 425 | ath5k_hw_enable_pspoll(ah, NULL, 0); |
390 | } | 426 | } |
391 | 427 | ||
392 | void ath5k_hw_set_bssid_mask(struct ath5k_hw *ah, const u8 *mask) | 428 | /** |
429 | * ath5k_hw_set_bssid_mask() - Filter out bssids we listen | ||
430 | * @ah: The &struct ath5k_hw | ||
431 | * @mask: The BSSID mask to set (array of octets) | ||
432 | * | ||
433 | * BSSID masking is a method used by AR5212 and newer hardware to inform PCU | ||
434 | * which bits of the interface's MAC address should be looked at when trying | ||
435 | * to decide which packets to ACK. In station mode and AP mode with a single | ||
436 | * BSS every bit matters since we lock to only one BSS. In AP mode with | ||
437 | * multiple BSSes (virtual interfaces) not every bit matters because hw must | ||
438 | * accept frames for all BSSes and so we tweak some bits of our mac address | ||
439 | * in order to have multiple BSSes. | ||
440 | * | ||
441 | * For more information check out ../hw.c of the common ath module. | ||
442 | */ | ||
443 | void | ||
444 | ath5k_hw_set_bssid_mask(struct ath5k_hw *ah, const u8 *mask) | ||
393 | { | 445 | { |
394 | struct ath_common *common = ath5k_hw_common(ah); | 446 | struct ath_common *common = ath5k_hw_common(ah); |
395 | 447 | ||
@@ -400,18 +452,21 @@ void ath5k_hw_set_bssid_mask(struct ath5k_hw *ah, const u8 *mask) | |||
400 | ath_hw_setbssidmask(common); | 452 | ath_hw_setbssidmask(common); |
401 | } | 453 | } |
402 | 454 | ||
403 | /* | 455 | /** |
404 | * Set multicast filter | 456 | * ath5k_hw_set_mcast_filter() - Set multicast filter |
457 | * @ah: The &struct ath5k_hw | ||
458 | * @filter0: Lower 32bits of muticast filter | ||
459 | * @filter1: Higher 16bits of multicast filter | ||
405 | */ | 460 | */ |
406 | void ath5k_hw_set_mcast_filter(struct ath5k_hw *ah, u32 filter0, u32 filter1) | 461 | void |
462 | ath5k_hw_set_mcast_filter(struct ath5k_hw *ah, u32 filter0, u32 filter1) | ||
407 | { | 463 | { |
408 | ath5k_hw_reg_write(ah, filter0, AR5K_MCAST_FILTER0); | 464 | ath5k_hw_reg_write(ah, filter0, AR5K_MCAST_FILTER0); |
409 | ath5k_hw_reg_write(ah, filter1, AR5K_MCAST_FILTER1); | 465 | ath5k_hw_reg_write(ah, filter1, AR5K_MCAST_FILTER1); |
410 | } | 466 | } |
411 | 467 | ||
412 | /** | 468 | /** |
413 | * ath5k_hw_get_rx_filter - Get current rx filter | 469 | * ath5k_hw_get_rx_filter() - Get current rx filter |
414 | * | ||
415 | * @ah: The &struct ath5k_hw | 470 | * @ah: The &struct ath5k_hw |
416 | * | 471 | * |
417 | * Returns the RX filter by reading rx filter and | 472 | * Returns the RX filter by reading rx filter and |
@@ -420,7 +475,8 @@ void ath5k_hw_set_mcast_filter(struct ath5k_hw *ah, u32 filter0, u32 filter1) | |||
420 | * and pass to the driver. For a list of frame types | 475 | * and pass to the driver. For a list of frame types |
421 | * check out reg.h. | 476 | * check out reg.h. |
422 | */ | 477 | */ |
423 | u32 ath5k_hw_get_rx_filter(struct ath5k_hw *ah) | 478 | u32 |
479 | ath5k_hw_get_rx_filter(struct ath5k_hw *ah) | ||
424 | { | 480 | { |
425 | u32 data, filter = 0; | 481 | u32 data, filter = 0; |
426 | 482 | ||
@@ -440,8 +496,7 @@ u32 ath5k_hw_get_rx_filter(struct ath5k_hw *ah) | |||
440 | } | 496 | } |
441 | 497 | ||
442 | /** | 498 | /** |
443 | * ath5k_hw_set_rx_filter - Set rx filter | 499 | * ath5k_hw_set_rx_filter() - Set rx filter |
444 | * | ||
445 | * @ah: The &struct ath5k_hw | 500 | * @ah: The &struct ath5k_hw |
446 | * @filter: RX filter mask (see reg.h) | 501 | * @filter: RX filter mask (see reg.h) |
447 | * | 502 | * |
@@ -449,7 +504,8 @@ u32 ath5k_hw_get_rx_filter(struct ath5k_hw *ah) | |||
449 | * register on 5212 and newer chips so that we have proper PHY | 504 | * register on 5212 and newer chips so that we have proper PHY |
450 | * error reporting. | 505 | * error reporting. |
451 | */ | 506 | */ |
452 | void ath5k_hw_set_rx_filter(struct ath5k_hw *ah, u32 filter) | 507 | void |
508 | ath5k_hw_set_rx_filter(struct ath5k_hw *ah, u32 filter) | ||
453 | { | 509 | { |
454 | u32 data = 0; | 510 | u32 data = 0; |
455 | 511 | ||
@@ -493,13 +549,13 @@ void ath5k_hw_set_rx_filter(struct ath5k_hw *ah, u32 filter) | |||
493 | #define ATH5K_MAX_TSF_READ 10 | 549 | #define ATH5K_MAX_TSF_READ 10 |
494 | 550 | ||
495 | /** | 551 | /** |
496 | * ath5k_hw_get_tsf64 - Get the full 64bit TSF | 552 | * ath5k_hw_get_tsf64() - Get the full 64bit TSF |
497 | * | ||
498 | * @ah: The &struct ath5k_hw | 553 | * @ah: The &struct ath5k_hw |
499 | * | 554 | * |
500 | * Returns the current TSF | 555 | * Returns the current TSF |
501 | */ | 556 | */ |
502 | u64 ath5k_hw_get_tsf64(struct ath5k_hw *ah) | 557 | u64 |
558 | ath5k_hw_get_tsf64(struct ath5k_hw *ah) | ||
503 | { | 559 | { |
504 | u32 tsf_lower, tsf_upper1, tsf_upper2; | 560 | u32 tsf_lower, tsf_upper1, tsf_upper2; |
505 | int i; | 561 | int i; |
@@ -536,28 +592,30 @@ u64 ath5k_hw_get_tsf64(struct ath5k_hw *ah) | |||
536 | return ((u64)tsf_upper1 << 32) | tsf_lower; | 592 | return ((u64)tsf_upper1 << 32) | tsf_lower; |
537 | } | 593 | } |
538 | 594 | ||
595 | #undef ATH5K_MAX_TSF_READ | ||
596 | |||
539 | /** | 597 | /** |
540 | * ath5k_hw_set_tsf64 - Set a new 64bit TSF | 598 | * ath5k_hw_set_tsf64() - Set a new 64bit TSF |
541 | * | ||
542 | * @ah: The &struct ath5k_hw | 599 | * @ah: The &struct ath5k_hw |
543 | * @tsf64: The new 64bit TSF | 600 | * @tsf64: The new 64bit TSF |
544 | * | 601 | * |
545 | * Sets the new TSF | 602 | * Sets the new TSF |
546 | */ | 603 | */ |
547 | void ath5k_hw_set_tsf64(struct ath5k_hw *ah, u64 tsf64) | 604 | void |
605 | ath5k_hw_set_tsf64(struct ath5k_hw *ah, u64 tsf64) | ||
548 | { | 606 | { |
549 | ath5k_hw_reg_write(ah, tsf64 & 0xffffffff, AR5K_TSF_L32); | 607 | ath5k_hw_reg_write(ah, tsf64 & 0xffffffff, AR5K_TSF_L32); |
550 | ath5k_hw_reg_write(ah, (tsf64 >> 32) & 0xffffffff, AR5K_TSF_U32); | 608 | ath5k_hw_reg_write(ah, (tsf64 >> 32) & 0xffffffff, AR5K_TSF_U32); |
551 | } | 609 | } |
552 | 610 | ||
553 | /** | 611 | /** |
554 | * ath5k_hw_reset_tsf - Force a TSF reset | 612 | * ath5k_hw_reset_tsf() - Force a TSF reset |
555 | * | ||
556 | * @ah: The &struct ath5k_hw | 613 | * @ah: The &struct ath5k_hw |
557 | * | 614 | * |
558 | * Forces a TSF reset on PCU | 615 | * Forces a TSF reset on PCU |
559 | */ | 616 | */ |
560 | void ath5k_hw_reset_tsf(struct ath5k_hw *ah) | 617 | void |
618 | ath5k_hw_reset_tsf(struct ath5k_hw *ah) | ||
561 | { | 619 | { |
562 | u32 val; | 620 | u32 val; |
563 | 621 | ||
@@ -573,10 +631,17 @@ void ath5k_hw_reset_tsf(struct ath5k_hw *ah) | |||
573 | ath5k_hw_reg_write(ah, val, AR5K_BEACON); | 631 | ath5k_hw_reg_write(ah, val, AR5K_BEACON); |
574 | } | 632 | } |
575 | 633 | ||
576 | /* | 634 | /** |
577 | * Initialize beacon timers | 635 | * ath5k_hw_init_beacon_timers() - Initialize beacon timers |
636 | * @ah: The &struct ath5k_hw | ||
637 | * @next_beacon: Next TBTT | ||
638 | * @interval: Current beacon interval | ||
639 | * | ||
640 | * This function is used to initialize beacon timers based on current | ||
641 | * operation mode and settings. | ||
578 | */ | 642 | */ |
579 | void ath5k_hw_init_beacon(struct ath5k_hw *ah, u32 next_beacon, u32 interval) | 643 | void |
644 | ath5k_hw_init_beacon_timers(struct ath5k_hw *ah, u32 next_beacon, u32 interval) | ||
580 | { | 645 | { |
581 | u32 timer1, timer2, timer3; | 646 | u32 timer1, timer2, timer3; |
582 | 647 | ||
@@ -655,8 +720,7 @@ void ath5k_hw_init_beacon(struct ath5k_hw *ah, u32 next_beacon, u32 interval) | |||
655 | } | 720 | } |
656 | 721 | ||
657 | /** | 722 | /** |
658 | * ath5k_check_timer_win - Check if timer B is timer A + window | 723 | * ath5k_check_timer_win() - Check if timer B is timer A + window |
659 | * | ||
660 | * @a: timer a (before b) | 724 | * @a: timer a (before b) |
661 | * @b: timer b (after a) | 725 | * @b: timer b (after a) |
662 | * @window: difference between a and b | 726 | * @window: difference between a and b |
@@ -686,12 +750,11 @@ ath5k_check_timer_win(int a, int b, int window, int intval) | |||
686 | } | 750 | } |
687 | 751 | ||
688 | /** | 752 | /** |
689 | * ath5k_hw_check_beacon_timers - Check if the beacon timers are correct | 753 | * ath5k_hw_check_beacon_timers() - Check if the beacon timers are correct |
690 | * | ||
691 | * @ah: The &struct ath5k_hw | 754 | * @ah: The &struct ath5k_hw |
692 | * @intval: beacon interval | 755 | * @intval: beacon interval |
693 | * | 756 | * |
694 | * This is a workaround for IBSS mode: | 757 | * This is a workaround for IBSS mode |
695 | * | 758 | * |
696 | * The need for this function arises from the fact that we have 4 separate | 759 | * The need for this function arises from the fact that we have 4 separate |
697 | * HW timer registers (TIMER0 - TIMER3), which are closely related to the | 760 | * HW timer registers (TIMER0 - TIMER3), which are closely related to the |
@@ -746,14 +809,14 @@ ath5k_hw_check_beacon_timers(struct ath5k_hw *ah, int intval) | |||
746 | } | 809 | } |
747 | 810 | ||
748 | /** | 811 | /** |
749 | * ath5k_hw_set_coverage_class - Set IEEE 802.11 coverage class | 812 | * ath5k_hw_set_coverage_class() - Set IEEE 802.11 coverage class |
750 | * | ||
751 | * @ah: The &struct ath5k_hw | 813 | * @ah: The &struct ath5k_hw |
752 | * @coverage_class: IEEE 802.11 coverage class number | 814 | * @coverage_class: IEEE 802.11 coverage class number |
753 | * | 815 | * |
754 | * Sets IFS intervals and ACK/CTS timeouts for given coverage class. | 816 | * Sets IFS intervals and ACK/CTS timeouts for given coverage class. |
755 | */ | 817 | */ |
756 | void ath5k_hw_set_coverage_class(struct ath5k_hw *ah, u8 coverage_class) | 818 | void |
819 | ath5k_hw_set_coverage_class(struct ath5k_hw *ah, u8 coverage_class) | ||
757 | { | 820 | { |
758 | /* As defined by IEEE 802.11-2007 17.3.8.6 */ | 821 | /* As defined by IEEE 802.11-2007 17.3.8.6 */ |
759 | int slot_time = ath5k_hw_get_default_slottime(ah) + 3 * coverage_class; | 822 | int slot_time = ath5k_hw_get_default_slottime(ah) + 3 * coverage_class; |
@@ -772,8 +835,7 @@ void ath5k_hw_set_coverage_class(struct ath5k_hw *ah, u8 coverage_class) | |||
772 | \***************************/ | 835 | \***************************/ |
773 | 836 | ||
774 | /** | 837 | /** |
775 | * ath5k_hw_start_rx_pcu - Start RX engine | 838 | * ath5k_hw_start_rx_pcu() - Start RX engine |
776 | * | ||
777 | * @ah: The &struct ath5k_hw | 839 | * @ah: The &struct ath5k_hw |
778 | * | 840 | * |
779 | * Starts RX engine on PCU so that hw can process RXed frames | 841 | * Starts RX engine on PCU so that hw can process RXed frames |
@@ -781,32 +843,33 @@ void ath5k_hw_set_coverage_class(struct ath5k_hw *ah, u8 coverage_class) | |||
781 | * | 843 | * |
782 | * NOTE: RX DMA should be already enabled using ath5k_hw_start_rx_dma | 844 | * NOTE: RX DMA should be already enabled using ath5k_hw_start_rx_dma |
783 | */ | 845 | */ |
784 | void ath5k_hw_start_rx_pcu(struct ath5k_hw *ah) | 846 | void |
847 | ath5k_hw_start_rx_pcu(struct ath5k_hw *ah) | ||
785 | { | 848 | { |
786 | AR5K_REG_DISABLE_BITS(ah, AR5K_DIAG_SW, AR5K_DIAG_SW_DIS_RX); | 849 | AR5K_REG_DISABLE_BITS(ah, AR5K_DIAG_SW, AR5K_DIAG_SW_DIS_RX); |
787 | } | 850 | } |
788 | 851 | ||
789 | /** | 852 | /** |
790 | * at5k_hw_stop_rx_pcu - Stop RX engine | 853 | * at5k_hw_stop_rx_pcu() - Stop RX engine |
791 | * | ||
792 | * @ah: The &struct ath5k_hw | 854 | * @ah: The &struct ath5k_hw |
793 | * | 855 | * |
794 | * Stops RX engine on PCU | 856 | * Stops RX engine on PCU |
795 | */ | 857 | */ |
796 | void ath5k_hw_stop_rx_pcu(struct ath5k_hw *ah) | 858 | void |
859 | ath5k_hw_stop_rx_pcu(struct ath5k_hw *ah) | ||
797 | { | 860 | { |
798 | AR5K_REG_ENABLE_BITS(ah, AR5K_DIAG_SW, AR5K_DIAG_SW_DIS_RX); | 861 | AR5K_REG_ENABLE_BITS(ah, AR5K_DIAG_SW, AR5K_DIAG_SW_DIS_RX); |
799 | } | 862 | } |
800 | 863 | ||
801 | /** | 864 | /** |
802 | * ath5k_hw_set_opmode - Set PCU operating mode | 865 | * ath5k_hw_set_opmode() - Set PCU operating mode |
803 | * | ||
804 | * @ah: The &struct ath5k_hw | 866 | * @ah: The &struct ath5k_hw |
805 | * @op_mode: &enum nl80211_iftype operating mode | 867 | * @op_mode: One of enum nl80211_iftype |
806 | * | 868 | * |
807 | * Configure PCU for the various operating modes (AP/STA etc) | 869 | * Configure PCU for the various operating modes (AP/STA etc) |
808 | */ | 870 | */ |
809 | int ath5k_hw_set_opmode(struct ath5k_hw *ah, enum nl80211_iftype op_mode) | 871 | int |
872 | ath5k_hw_set_opmode(struct ath5k_hw *ah, enum nl80211_iftype op_mode) | ||
810 | { | 873 | { |
811 | struct ath_common *common = ath5k_hw_common(ah); | 874 | struct ath_common *common = ath5k_hw_common(ah); |
812 | u32 pcu_reg, beacon_reg, low_id, high_id; | 875 | u32 pcu_reg, beacon_reg, low_id, high_id; |
@@ -873,8 +936,17 @@ int ath5k_hw_set_opmode(struct ath5k_hw *ah, enum nl80211_iftype op_mode) | |||
873 | return 0; | 936 | return 0; |
874 | } | 937 | } |
875 | 938 | ||
876 | void ath5k_hw_pcu_init(struct ath5k_hw *ah, enum nl80211_iftype op_mode, | 939 | /** |
877 | u8 mode) | 940 | * ath5k_hw_pcu_init() - Initialize PCU |
941 | * @ah: The &struct ath5k_hw | ||
942 | * @op_mode: One of enum nl80211_iftype | ||
943 | * @mode: One of enum ath5k_driver_mode | ||
944 | * | ||
945 | * This function is used to initialize PCU by setting current | ||
946 | * operation mode and various other settings. | ||
947 | */ | ||
948 | void | ||
949 | ath5k_hw_pcu_init(struct ath5k_hw *ah, enum nl80211_iftype op_mode) | ||
878 | { | 950 | { |
879 | /* Set bssid and bssid mask */ | 951 | /* Set bssid and bssid mask */ |
880 | ath5k_hw_set_bssid(ah); | 952 | ath5k_hw_set_bssid(ah); |
diff --git a/drivers/net/wireless/ath/ath5k/phy.c b/drivers/net/wireless/ath/ath5k/phy.c index 01cb72de44cb..e1f8613426a9 100644 --- a/drivers/net/wireless/ath/ath5k/phy.c +++ b/drivers/net/wireless/ath/ath5k/phy.c | |||
@@ -1,6 +1,4 @@ | |||
1 | /* | 1 | /* |
2 | * PHY functions | ||
3 | * | ||
4 | * Copyright (c) 2004-2007 Reyk Floeter <reyk@openbsd.org> | 2 | * Copyright (c) 2004-2007 Reyk Floeter <reyk@openbsd.org> |
5 | * Copyright (c) 2006-2009 Nick Kossifidis <mickflemm@gmail.com> | 3 | * Copyright (c) 2006-2009 Nick Kossifidis <mickflemm@gmail.com> |
6 | * Copyright (c) 2007-2008 Jiri Slaby <jirislaby@gmail.com> | 4 | * Copyright (c) 2007-2008 Jiri Slaby <jirislaby@gmail.com> |
@@ -20,6 +18,10 @@ | |||
20 | * | 18 | * |
21 | */ | 19 | */ |
22 | 20 | ||
21 | /***********************\ | ||
22 | * PHY related functions * | ||
23 | \***********************/ | ||
24 | |||
23 | #include <linux/delay.h> | 25 | #include <linux/delay.h> |
24 | #include <linux/slab.h> | 26 | #include <linux/slab.h> |
25 | #include <asm/unaligned.h> | 27 | #include <asm/unaligned.h> |
@@ -31,14 +33,53 @@ | |||
31 | #include "../regd.h" | 33 | #include "../regd.h" |
32 | 34 | ||
33 | 35 | ||
36 | /** | ||
37 | * DOC: PHY related functions | ||
38 | * | ||
39 | * Here we handle the low-level functions related to baseband | ||
40 | * and analog frontend (RF) parts. This is by far the most complex | ||
41 | * part of the hw code so make sure you know what you are doing. | ||
42 | * | ||
43 | * Here is a list of what this is all about: | ||
44 | * | ||
45 | * - Channel setting/switching | ||
46 | * | ||
47 | * - Automatic Gain Control (AGC) calibration | ||
48 | * | ||
49 | * - Noise Floor calibration | ||
50 | * | ||
51 | * - I/Q imbalance calibration (QAM correction) | ||
52 | * | ||
53 | * - Calibration due to thermal changes (gain_F) | ||
54 | * | ||
55 | * - Spur noise mitigation | ||
56 | * | ||
57 | * - RF/PHY initialization for the various operating modes and bwmodes | ||
58 | * | ||
59 | * - Antenna control | ||
60 | * | ||
61 | * - TX power control per channel/rate/packet type | ||
62 | * | ||
63 | * Also have in mind we never got documentation for most of these | ||
64 | * functions, what we have comes mostly from Atheros's code, reverse | ||
65 | * engineering and patent docs/presentations etc. | ||
66 | */ | ||
67 | |||
68 | |||
34 | /******************\ | 69 | /******************\ |
35 | * Helper functions * | 70 | * Helper functions * |
36 | \******************/ | 71 | \******************/ |
37 | 72 | ||
38 | /* | 73 | /** |
39 | * Get the PHY Chip revision | 74 | * ath5k_hw_radio_revision() - Get the PHY Chip revision |
75 | * @ah: The &struct ath5k_hw | ||
76 | * @band: One of enum ieee80211_band | ||
77 | * | ||
78 | * Returns the revision number of a 2GHz, 5GHz or single chip | ||
79 | * radio. | ||
40 | */ | 80 | */ |
41 | u16 ath5k_hw_radio_revision(struct ath5k_hw *ah, enum ieee80211_band band) | 81 | u16 |
82 | ath5k_hw_radio_revision(struct ath5k_hw *ah, enum ieee80211_band band) | ||
42 | { | 83 | { |
43 | unsigned int i; | 84 | unsigned int i; |
44 | u32 srev; | 85 | u32 srev; |
@@ -58,7 +99,7 @@ u16 ath5k_hw_radio_revision(struct ath5k_hw *ah, enum ieee80211_band band) | |||
58 | return 0; | 99 | return 0; |
59 | } | 100 | } |
60 | 101 | ||
61 | mdelay(2); | 102 | usleep_range(2000, 2500); |
62 | 103 | ||
63 | /* ...wait until PHY is ready and read the selected radio revision */ | 104 | /* ...wait until PHY is ready and read the selected radio revision */ |
64 | ath5k_hw_reg_write(ah, 0x00001c16, AR5K_PHY(0x34)); | 105 | ath5k_hw_reg_write(ah, 0x00001c16, AR5K_PHY(0x34)); |
@@ -81,10 +122,16 @@ u16 ath5k_hw_radio_revision(struct ath5k_hw *ah, enum ieee80211_band band) | |||
81 | return ret; | 122 | return ret; |
82 | } | 123 | } |
83 | 124 | ||
84 | /* | 125 | /** |
85 | * Check if a channel is supported | 126 | * ath5k_channel_ok() - Check if a channel is supported by the hw |
127 | * @ah: The &struct ath5k_hw | ||
128 | * @channel: The &struct ieee80211_channel | ||
129 | * | ||
130 | * Note: We don't do any regulatory domain checks here, it's just | ||
131 | * a sanity check. | ||
86 | */ | 132 | */ |
87 | bool ath5k_channel_ok(struct ath5k_hw *ah, struct ieee80211_channel *channel) | 133 | bool |
134 | ath5k_channel_ok(struct ath5k_hw *ah, struct ieee80211_channel *channel) | ||
88 | { | 135 | { |
89 | u16 freq = channel->center_freq; | 136 | u16 freq = channel->center_freq; |
90 | 137 | ||
@@ -101,7 +148,13 @@ bool ath5k_channel_ok(struct ath5k_hw *ah, struct ieee80211_channel *channel) | |||
101 | return false; | 148 | return false; |
102 | } | 149 | } |
103 | 150 | ||
104 | bool ath5k_hw_chan_has_spur_noise(struct ath5k_hw *ah, | 151 | /** |
152 | * ath5k_hw_chan_has_spur_noise() - Check if channel is sensitive to spur noise | ||
153 | * @ah: The &struct ath5k_hw | ||
154 | * @channel: The &struct ieee80211_channel | ||
155 | */ | ||
156 | bool | ||
157 | ath5k_hw_chan_has_spur_noise(struct ath5k_hw *ah, | ||
105 | struct ieee80211_channel *channel) | 158 | struct ieee80211_channel *channel) |
106 | { | 159 | { |
107 | u8 refclk_freq; | 160 | u8 refclk_freq; |
@@ -122,11 +175,20 @@ bool ath5k_hw_chan_has_spur_noise(struct ath5k_hw *ah, | |||
122 | return false; | 175 | return false; |
123 | } | 176 | } |
124 | 177 | ||
125 | /* | 178 | /** |
126 | * Used to modify RF Banks before writing them to AR5K_RF_BUFFER | 179 | * ath5k_hw_rfb_op() - Perform an operation on the given RF Buffer |
180 | * @ah: The &struct ath5k_hw | ||
181 | * @rf_regs: The struct ath5k_rf_reg | ||
182 | * @val: New value | ||
183 | * @reg_id: RF register ID | ||
184 | * @set: Indicate we need to swap data | ||
185 | * | ||
186 | * This is an internal function used to modify RF Banks before | ||
187 | * writing them to AR5K_RF_BUFFER. Check out rfbuffer.h for more | ||
188 | * infos. | ||
127 | */ | 189 | */ |
128 | static unsigned int ath5k_hw_rfb_op(struct ath5k_hw *ah, | 190 | static unsigned int |
129 | const struct ath5k_rf_reg *rf_regs, | 191 | ath5k_hw_rfb_op(struct ath5k_hw *ah, const struct ath5k_rf_reg *rf_regs, |
130 | u32 val, u8 reg_id, bool set) | 192 | u32 val, u8 reg_id, bool set) |
131 | { | 193 | { |
132 | const struct ath5k_rf_reg *rfreg = NULL; | 194 | const struct ath5k_rf_reg *rfreg = NULL; |
@@ -204,8 +266,7 @@ static unsigned int ath5k_hw_rfb_op(struct ath5k_hw *ah, | |||
204 | } | 266 | } |
205 | 267 | ||
206 | /** | 268 | /** |
207 | * ath5k_hw_write_ofdm_timings - set OFDM timings on AR5212 | 269 | * ath5k_hw_write_ofdm_timings() - set OFDM timings on AR5212 |
208 | * | ||
209 | * @ah: the &struct ath5k_hw | 270 | * @ah: the &struct ath5k_hw |
210 | * @channel: the currently set channel upon reset | 271 | * @channel: the currently set channel upon reset |
211 | * | 272 | * |
@@ -216,10 +277,11 @@ static unsigned int ath5k_hw_rfb_op(struct ath5k_hw *ah, | |||
216 | * mantissa and provide these values on hw. | 277 | * mantissa and provide these values on hw. |
217 | * | 278 | * |
218 | * For more infos i think this patent is related | 279 | * For more infos i think this patent is related |
219 | * http://www.freepatentsonline.com/7184495.html | 280 | * "http://www.freepatentsonline.com/7184495.html" |
220 | */ | 281 | */ |
221 | static inline int ath5k_hw_write_ofdm_timings(struct ath5k_hw *ah, | 282 | static inline int |
222 | struct ieee80211_channel *channel) | 283 | ath5k_hw_write_ofdm_timings(struct ath5k_hw *ah, |
284 | struct ieee80211_channel *channel) | ||
223 | { | 285 | { |
224 | /* Get exponent and mantissa and set it */ | 286 | /* Get exponent and mantissa and set it */ |
225 | u32 coef_scaled, coef_exp, coef_man, | 287 | u32 coef_scaled, coef_exp, coef_man, |
@@ -278,6 +340,10 @@ static inline int ath5k_hw_write_ofdm_timings(struct ath5k_hw *ah, | |||
278 | return 0; | 340 | return 0; |
279 | } | 341 | } |
280 | 342 | ||
343 | /** | ||
344 | * ath5k_hw_phy_disable() - Disable PHY | ||
345 | * @ah: The &struct ath5k_hw | ||
346 | */ | ||
281 | int ath5k_hw_phy_disable(struct ath5k_hw *ah) | 347 | int ath5k_hw_phy_disable(struct ath5k_hw *ah) |
282 | { | 348 | { |
283 | /*Just a try M.F.*/ | 349 | /*Just a try M.F.*/ |
@@ -286,10 +352,13 @@ int ath5k_hw_phy_disable(struct ath5k_hw *ah) | |||
286 | return 0; | 352 | return 0; |
287 | } | 353 | } |
288 | 354 | ||
289 | /* | 355 | /** |
290 | * Wait for synth to settle | 356 | * ath5k_hw_wait_for_synth() - Wait for synth to settle |
357 | * @ah: The &struct ath5k_hw | ||
358 | * @channel: The &struct ieee80211_channel | ||
291 | */ | 359 | */ |
292 | static void ath5k_hw_wait_for_synth(struct ath5k_hw *ah, | 360 | static void |
361 | ath5k_hw_wait_for_synth(struct ath5k_hw *ah, | ||
293 | struct ieee80211_channel *channel) | 362 | struct ieee80211_channel *channel) |
294 | { | 363 | { |
295 | /* | 364 | /* |
@@ -308,9 +377,9 @@ static void ath5k_hw_wait_for_synth(struct ath5k_hw *ah, | |||
308 | delay = delay << 2; | 377 | delay = delay << 2; |
309 | /* XXX: /2 on turbo ? Let's be safe | 378 | /* XXX: /2 on turbo ? Let's be safe |
310 | * for now */ | 379 | * for now */ |
311 | udelay(100 + delay); | 380 | usleep_range(100 + delay, 100 + (2 * delay)); |
312 | } else { | 381 | } else { |
313 | mdelay(1); | 382 | usleep_range(1000, 1500); |
314 | } | 383 | } |
315 | } | 384 | } |
316 | 385 | ||
@@ -319,7 +388,9 @@ static void ath5k_hw_wait_for_synth(struct ath5k_hw *ah, | |||
319 | * RF Gain optimization * | 388 | * RF Gain optimization * |
320 | \**********************/ | 389 | \**********************/ |
321 | 390 | ||
322 | /* | 391 | /** |
392 | * DOC: RF Gain optimization | ||
393 | * | ||
323 | * This code is used to optimize RF gain on different environments | 394 | * This code is used to optimize RF gain on different environments |
324 | * (temperature mostly) based on feedback from a power detector. | 395 | * (temperature mostly) based on feedback from a power detector. |
325 | * | 396 | * |
@@ -328,22 +399,22 @@ static void ath5k_hw_wait_for_synth(struct ath5k_hw *ah, | |||
328 | * no gain optimization ladder-. | 399 | * no gain optimization ladder-. |
329 | * | 400 | * |
330 | * For more infos check out this patent doc | 401 | * For more infos check out this patent doc |
331 | * http://www.freepatentsonline.com/7400691.html | 402 | * "http://www.freepatentsonline.com/7400691.html" |
332 | * | 403 | * |
333 | * This paper describes power drops as seen on the receiver due to | 404 | * This paper describes power drops as seen on the receiver due to |
334 | * probe packets | 405 | * probe packets |
335 | * http://www.cnri.dit.ie/publications/ICT08%20-%20Practical%20Issues | 406 | * "http://www.cnri.dit.ie/publications/ICT08%20-%20Practical%20Issues |
336 | * %20of%20Power%20Control.pdf | 407 | * %20of%20Power%20Control.pdf" |
337 | * | 408 | * |
338 | * And this is the MadWiFi bug entry related to the above | 409 | * And this is the MadWiFi bug entry related to the above |
339 | * http://madwifi-project.org/ticket/1659 | 410 | * "http://madwifi-project.org/ticket/1659" |
340 | * with various measurements and diagrams | 411 | * with various measurements and diagrams |
341 | * | ||
342 | * TODO: Deal with power drops due to probes by setting an appropriate | ||
343 | * tx power on the probe packets ! Make this part of the calibration process. | ||
344 | */ | 412 | */ |
345 | 413 | ||
346 | /* Initialize ah_gain during attach */ | 414 | /** |
415 | * ath5k_hw_rfgain_opt_init() - Initialize ah_gain during attach | ||
416 | * @ah: The &struct ath5k_hw | ||
417 | */ | ||
347 | int ath5k_hw_rfgain_opt_init(struct ath5k_hw *ah) | 418 | int ath5k_hw_rfgain_opt_init(struct ath5k_hw *ah) |
348 | { | 419 | { |
349 | /* Initialize the gain optimization values */ | 420 | /* Initialize the gain optimization values */ |
@@ -367,17 +438,21 @@ int ath5k_hw_rfgain_opt_init(struct ath5k_hw *ah) | |||
367 | return 0; | 438 | return 0; |
368 | } | 439 | } |
369 | 440 | ||
370 | /* Schedule a gain probe check on the next transmitted packet. | 441 | /** |
442 | * ath5k_hw_request_rfgain_probe() - Request a PAPD probe packet | ||
443 | * @ah: The &struct ath5k_hw | ||
444 | * | ||
445 | * Schedules a gain probe check on the next transmitted packet. | ||
371 | * That means our next packet is going to be sent with lower | 446 | * That means our next packet is going to be sent with lower |
372 | * tx power and a Peak to Average Power Detector (PAPD) will try | 447 | * tx power and a Peak to Average Power Detector (PAPD) will try |
373 | * to measure the gain. | 448 | * to measure the gain. |
374 | * | 449 | * |
375 | * XXX: How about forcing a tx packet (bypassing PCU arbitrator etc) | 450 | * TODO: Force a tx packet (bypassing PCU arbitrator etc) |
376 | * just after we enable the probe so that we don't mess with | 451 | * just after we enable the probe so that we don't mess with |
377 | * standard traffic ? Maybe it's time to use sw interrupts and | 452 | * standard traffic. |
378 | * a probe tasklet !!! | ||
379 | */ | 453 | */ |
380 | static void ath5k_hw_request_rfgain_probe(struct ath5k_hw *ah) | 454 | static void |
455 | ath5k_hw_request_rfgain_probe(struct ath5k_hw *ah) | ||
381 | { | 456 | { |
382 | 457 | ||
383 | /* Skip if gain calibration is inactive or | 458 | /* Skip if gain calibration is inactive or |
@@ -395,9 +470,15 @@ static void ath5k_hw_request_rfgain_probe(struct ath5k_hw *ah) | |||
395 | 470 | ||
396 | } | 471 | } |
397 | 472 | ||
398 | /* Calculate gain_F measurement correction | 473 | /** |
399 | * based on the current step for RF5112 rev. 2 */ | 474 | * ath5k_hw_rf_gainf_corr() - Calculate Gain_F measurement correction |
400 | static u32 ath5k_hw_rf_gainf_corr(struct ath5k_hw *ah) | 475 | * @ah: The &struct ath5k_hw |
476 | * | ||
477 | * Calculate Gain_F measurement correction | ||
478 | * based on the current step for RF5112 rev. 2 | ||
479 | */ | ||
480 | static u32 | ||
481 | ath5k_hw_rf_gainf_corr(struct ath5k_hw *ah) | ||
401 | { | 482 | { |
402 | u32 mix, step; | 483 | u32 mix, step; |
403 | u32 *rf; | 484 | u32 *rf; |
@@ -450,11 +531,19 @@ static u32 ath5k_hw_rf_gainf_corr(struct ath5k_hw *ah) | |||
450 | return ah->ah_gain.g_f_corr; | 531 | return ah->ah_gain.g_f_corr; |
451 | } | 532 | } |
452 | 533 | ||
453 | /* Check if current gain_F measurement is in the range of our | 534 | /** |
535 | * ath5k_hw_rf_check_gainf_readback() - Validate Gain_F feedback from detector | ||
536 | * @ah: The &struct ath5k_hw | ||
537 | * | ||
538 | * Check if current gain_F measurement is in the range of our | ||
454 | * power detector windows. If we get a measurement outside range | 539 | * power detector windows. If we get a measurement outside range |
455 | * we know it's not accurate (detectors can't measure anything outside | 540 | * we know it's not accurate (detectors can't measure anything outside |
456 | * their detection window) so we must ignore it */ | 541 | * their detection window) so we must ignore it. |
457 | static bool ath5k_hw_rf_check_gainf_readback(struct ath5k_hw *ah) | 542 | * |
543 | * Returns true if readback was O.K. or false on failure | ||
544 | */ | ||
545 | static bool | ||
546 | ath5k_hw_rf_check_gainf_readback(struct ath5k_hw *ah) | ||
458 | { | 547 | { |
459 | const struct ath5k_rf_reg *rf_regs; | 548 | const struct ath5k_rf_reg *rf_regs; |
460 | u32 step, mix_ovr, level[4]; | 549 | u32 step, mix_ovr, level[4]; |
@@ -506,9 +595,15 @@ static bool ath5k_hw_rf_check_gainf_readback(struct ath5k_hw *ah) | |||
506 | ah->ah_gain.g_current <= level[3]); | 595 | ah->ah_gain.g_current <= level[3]); |
507 | } | 596 | } |
508 | 597 | ||
509 | /* Perform gain_F adjustment by choosing the right set | 598 | /** |
510 | * of parameters from RF gain optimization ladder */ | 599 | * ath5k_hw_rf_gainf_adjust() - Perform Gain_F adjustment |
511 | static s8 ath5k_hw_rf_gainf_adjust(struct ath5k_hw *ah) | 600 | * @ah: The &struct ath5k_hw |
601 | * | ||
602 | * Choose the right target gain based on current gain | ||
603 | * and RF gain optimization ladder | ||
604 | */ | ||
605 | static s8 | ||
606 | ath5k_hw_rf_gainf_adjust(struct ath5k_hw *ah) | ||
512 | { | 607 | { |
513 | const struct ath5k_gain_opt *go; | 608 | const struct ath5k_gain_opt *go; |
514 | const struct ath5k_gain_opt_step *g_step; | 609 | const struct ath5k_gain_opt_step *g_step; |
@@ -572,13 +667,18 @@ done: | |||
572 | return ret; | 667 | return ret; |
573 | } | 668 | } |
574 | 669 | ||
575 | /* Main callback for thermal RF gain calibration engine | 670 | /** |
671 | * ath5k_hw_gainf_calibrate() - Do a gain_F calibration | ||
672 | * @ah: The &struct ath5k_hw | ||
673 | * | ||
674 | * Main callback for thermal RF gain calibration engine | ||
576 | * Check for a new gain reading and schedule an adjustment | 675 | * Check for a new gain reading and schedule an adjustment |
577 | * if needed. | 676 | * if needed. |
578 | * | 677 | * |
579 | * TODO: Use sw interrupt to schedule reset if gain_F needs | 678 | * Returns one of enum ath5k_rfgain codes |
580 | * adjustment */ | 679 | */ |
581 | enum ath5k_rfgain ath5k_hw_gainf_calibrate(struct ath5k_hw *ah) | 680 | enum ath5k_rfgain |
681 | ath5k_hw_gainf_calibrate(struct ath5k_hw *ah) | ||
582 | { | 682 | { |
583 | u32 data, type; | 683 | u32 data, type; |
584 | struct ath5k_eeprom_info *ee = &ah->ah_capabilities.cap_eeprom; | 684 | struct ath5k_eeprom_info *ee = &ah->ah_capabilities.cap_eeprom; |
@@ -638,10 +738,18 @@ done: | |||
638 | return ah->ah_gain.g_state; | 738 | return ah->ah_gain.g_state; |
639 | } | 739 | } |
640 | 740 | ||
641 | /* Write initial RF gain table to set the RF sensitivity | 741 | /** |
642 | * this one works on all RF chips and has nothing to do | 742 | * ath5k_hw_rfgain_init() - Write initial RF gain settings to hw |
643 | * with gain_F calibration */ | 743 | * @ah: The &struct ath5k_hw |
644 | static int ath5k_hw_rfgain_init(struct ath5k_hw *ah, enum ieee80211_band band) | 744 | * @band: One of enum ieee80211_band |
745 | * | ||
746 | * Write initial RF gain table to set the RF sensitivity. | ||
747 | * | ||
748 | * NOTE: This one works on all RF chips and has nothing to do | ||
749 | * with Gain_F calibration | ||
750 | */ | ||
751 | static int | ||
752 | ath5k_hw_rfgain_init(struct ath5k_hw *ah, enum ieee80211_band band) | ||
645 | { | 753 | { |
646 | const struct ath5k_ini_rfgain *ath5k_rfg; | 754 | const struct ath5k_ini_rfgain *ath5k_rfg; |
647 | unsigned int i, size, index; | 755 | unsigned int i, size, index; |
@@ -688,16 +796,23 @@ static int ath5k_hw_rfgain_init(struct ath5k_hw *ah, enum ieee80211_band band) | |||
688 | } | 796 | } |
689 | 797 | ||
690 | 798 | ||
691 | |||
692 | /********************\ | 799 | /********************\ |
693 | * RF Registers setup * | 800 | * RF Registers setup * |
694 | \********************/ | 801 | \********************/ |
695 | 802 | ||
696 | /* | 803 | /** |
697 | * Setup RF registers by writing RF buffer on hw | 804 | * ath5k_hw_rfregs_init() - Initialize RF register settings |
805 | * @ah: The &struct ath5k_hw | ||
806 | * @channel: The &struct ieee80211_channel | ||
807 | * @mode: One of enum ath5k_driver_mode | ||
808 | * | ||
809 | * Setup RF registers by writing RF buffer on hw. For | ||
810 | * more infos on this, check out rfbuffer.h | ||
698 | */ | 811 | */ |
699 | static int ath5k_hw_rfregs_init(struct ath5k_hw *ah, | 812 | static int |
700 | struct ieee80211_channel *channel, unsigned int mode) | 813 | ath5k_hw_rfregs_init(struct ath5k_hw *ah, |
814 | struct ieee80211_channel *channel, | ||
815 | unsigned int mode) | ||
701 | { | 816 | { |
702 | const struct ath5k_rf_reg *rf_regs; | 817 | const struct ath5k_rf_reg *rf_regs; |
703 | const struct ath5k_ini_rfbuffer *ini_rfb; | 818 | const struct ath5k_ini_rfbuffer *ini_rfb; |
@@ -1055,19 +1170,18 @@ static int ath5k_hw_rfregs_init(struct ath5k_hw *ah, | |||
1055 | PHY/RF channel functions | 1170 | PHY/RF channel functions |
1056 | \**************************/ | 1171 | \**************************/ |
1057 | 1172 | ||
1058 | /* | 1173 | /** |
1059 | * Conversion needed for RF5110 | 1174 | * ath5k_hw_rf5110_chan2athchan() - Convert channel freq on RF5110 |
1175 | * @channel: The &struct ieee80211_channel | ||
1176 | * | ||
1177 | * Map channel frequency to IEEE channel number and convert it | ||
1178 | * to an internal channel value used by the RF5110 chipset. | ||
1060 | */ | 1179 | */ |
1061 | static u32 ath5k_hw_rf5110_chan2athchan(struct ieee80211_channel *channel) | 1180 | static u32 |
1181 | ath5k_hw_rf5110_chan2athchan(struct ieee80211_channel *channel) | ||
1062 | { | 1182 | { |
1063 | u32 athchan; | 1183 | u32 athchan; |
1064 | 1184 | ||
1065 | /* | ||
1066 | * Convert IEEE channel/MHz to an internal channel value used | ||
1067 | * by the AR5210 chipset. This has not been verified with | ||
1068 | * newer chipsets like the AR5212A who have a completely | ||
1069 | * different RF/PHY part. | ||
1070 | */ | ||
1071 | athchan = (ath5k_hw_bitswap( | 1185 | athchan = (ath5k_hw_bitswap( |
1072 | (ieee80211_frequency_to_channel( | 1186 | (ieee80211_frequency_to_channel( |
1073 | channel->center_freq) - 24) / 2, 5) | 1187 | channel->center_freq) - 24) / 2, 5) |
@@ -1075,10 +1189,13 @@ static u32 ath5k_hw_rf5110_chan2athchan(struct ieee80211_channel *channel) | |||
1075 | return athchan; | 1189 | return athchan; |
1076 | } | 1190 | } |
1077 | 1191 | ||
1078 | /* | 1192 | /** |
1079 | * Set channel on RF5110 | 1193 | * ath5k_hw_rf5110_channel() - Set channel frequency on RF5110 |
1194 | * @ah: The &struct ath5k_hw | ||
1195 | * @channel: The &struct ieee80211_channel | ||
1080 | */ | 1196 | */ |
1081 | static int ath5k_hw_rf5110_channel(struct ath5k_hw *ah, | 1197 | static int |
1198 | ath5k_hw_rf5110_channel(struct ath5k_hw *ah, | ||
1082 | struct ieee80211_channel *channel) | 1199 | struct ieee80211_channel *channel) |
1083 | { | 1200 | { |
1084 | u32 data; | 1201 | u32 data; |
@@ -1089,15 +1206,23 @@ static int ath5k_hw_rf5110_channel(struct ath5k_hw *ah, | |||
1089 | data = ath5k_hw_rf5110_chan2athchan(channel); | 1206 | data = ath5k_hw_rf5110_chan2athchan(channel); |
1090 | ath5k_hw_reg_write(ah, data, AR5K_RF_BUFFER); | 1207 | ath5k_hw_reg_write(ah, data, AR5K_RF_BUFFER); |
1091 | ath5k_hw_reg_write(ah, 0, AR5K_RF_BUFFER_CONTROL_0); | 1208 | ath5k_hw_reg_write(ah, 0, AR5K_RF_BUFFER_CONTROL_0); |
1092 | mdelay(1); | 1209 | usleep_range(1000, 1500); |
1093 | 1210 | ||
1094 | return 0; | 1211 | return 0; |
1095 | } | 1212 | } |
1096 | 1213 | ||
1097 | /* | 1214 | /** |
1098 | * Conversion needed for 5111 | 1215 | * ath5k_hw_rf5111_chan2athchan() - Handle 2GHz channels on RF5111/2111 |
1216 | * @ieee: IEEE channel number | ||
1217 | * @athchan: The &struct ath5k_athchan_2ghz | ||
1218 | * | ||
1219 | * In order to enable the RF2111 frequency converter on RF5111/2111 setups | ||
1220 | * we need to add some offsets and extra flags to the data values we pass | ||
1221 | * on to the PHY. So for every 2GHz channel this function gets called | ||
1222 | * to do the conversion. | ||
1099 | */ | 1223 | */ |
1100 | static int ath5k_hw_rf5111_chan2athchan(unsigned int ieee, | 1224 | static int |
1225 | ath5k_hw_rf5111_chan2athchan(unsigned int ieee, | ||
1101 | struct ath5k_athchan_2ghz *athchan) | 1226 | struct ath5k_athchan_2ghz *athchan) |
1102 | { | 1227 | { |
1103 | int channel; | 1228 | int channel; |
@@ -1123,10 +1248,13 @@ static int ath5k_hw_rf5111_chan2athchan(unsigned int ieee, | |||
1123 | return 0; | 1248 | return 0; |
1124 | } | 1249 | } |
1125 | 1250 | ||
1126 | /* | 1251 | /** |
1127 | * Set channel on 5111 | 1252 | * ath5k_hw_rf5111_channel() - Set channel frequency on RF5111/2111 |
1253 | * @ah: The &struct ath5k_hw | ||
1254 | * @channel: The &struct ieee80211_channel | ||
1128 | */ | 1255 | */ |
1129 | static int ath5k_hw_rf5111_channel(struct ath5k_hw *ah, | 1256 | static int |
1257 | ath5k_hw_rf5111_channel(struct ath5k_hw *ah, | ||
1130 | struct ieee80211_channel *channel) | 1258 | struct ieee80211_channel *channel) |
1131 | { | 1259 | { |
1132 | struct ath5k_athchan_2ghz ath5k_channel_2ghz; | 1260 | struct ath5k_athchan_2ghz ath5k_channel_2ghz; |
@@ -1171,10 +1299,20 @@ static int ath5k_hw_rf5111_channel(struct ath5k_hw *ah, | |||
1171 | return 0; | 1299 | return 0; |
1172 | } | 1300 | } |
1173 | 1301 | ||
1174 | /* | 1302 | /** |
1175 | * Set channel on 5112 and newer | 1303 | * ath5k_hw_rf5112_channel() - Set channel frequency on 5112 and newer |
1304 | * @ah: The &struct ath5k_hw | ||
1305 | * @channel: The &struct ieee80211_channel | ||
1306 | * | ||
1307 | * On RF5112/2112 and newer we don't need to do any conversion. | ||
1308 | * We pass the frequency value after a few modifications to the | ||
1309 | * chip directly. | ||
1310 | * | ||
1311 | * NOTE: Make sure channel frequency given is within our range or else | ||
1312 | * we might damage the chip ! Use ath5k_channel_ok before calling this one. | ||
1176 | */ | 1313 | */ |
1177 | static int ath5k_hw_rf5112_channel(struct ath5k_hw *ah, | 1314 | static int |
1315 | ath5k_hw_rf5112_channel(struct ath5k_hw *ah, | ||
1178 | struct ieee80211_channel *channel) | 1316 | struct ieee80211_channel *channel) |
1179 | { | 1317 | { |
1180 | u32 data, data0, data1, data2; | 1318 | u32 data, data0, data1, data2; |
@@ -1183,17 +1321,37 @@ static int ath5k_hw_rf5112_channel(struct ath5k_hw *ah, | |||
1183 | data = data0 = data1 = data2 = 0; | 1321 | data = data0 = data1 = data2 = 0; |
1184 | c = channel->center_freq; | 1322 | c = channel->center_freq; |
1185 | 1323 | ||
1324 | /* My guess based on code: | ||
1325 | * 2GHz RF has 2 synth modes, one with a Local Oscillator | ||
1326 | * at 2224Hz and one with a LO at 2192Hz. IF is 1520Hz | ||
1327 | * (3040/2). data0 is used to set the PLL divider and data1 | ||
1328 | * selects synth mode. */ | ||
1186 | if (c < 4800) { | 1329 | if (c < 4800) { |
1330 | /* Channel 14 and all frequencies with 2Hz spacing | ||
1331 | * below/above (non-standard channels) */ | ||
1187 | if (!((c - 2224) % 5)) { | 1332 | if (!((c - 2224) % 5)) { |
1333 | /* Same as (c - 2224) / 5 */ | ||
1188 | data0 = ((2 * (c - 704)) - 3040) / 10; | 1334 | data0 = ((2 * (c - 704)) - 3040) / 10; |
1189 | data1 = 1; | 1335 | data1 = 1; |
1336 | /* Channel 1 and all frequencies with 5Hz spacing | ||
1337 | * below/above (standard channels without channel 14) */ | ||
1190 | } else if (!((c - 2192) % 5)) { | 1338 | } else if (!((c - 2192) % 5)) { |
1339 | /* Same as (c - 2192) / 5 */ | ||
1191 | data0 = ((2 * (c - 672)) - 3040) / 10; | 1340 | data0 = ((2 * (c - 672)) - 3040) / 10; |
1192 | data1 = 0; | 1341 | data1 = 0; |
1193 | } else | 1342 | } else |
1194 | return -EINVAL; | 1343 | return -EINVAL; |
1195 | 1344 | ||
1196 | data0 = ath5k_hw_bitswap((data0 << 2) & 0xff, 8); | 1345 | data0 = ath5k_hw_bitswap((data0 << 2) & 0xff, 8); |
1346 | /* This is more complex, we have a single synthesizer with | ||
1347 | * 4 reference clock settings (?) based on frequency spacing | ||
1348 | * and set using data2. LO is at 4800Hz and data0 is again used | ||
1349 | * to set some divider. | ||
1350 | * | ||
1351 | * NOTE: There is an old atheros presentation at Stanford | ||
1352 | * that mentions a method called dual direct conversion | ||
1353 | * with 1GHz sliding IF for RF5110. Maybe that's what we | ||
1354 | * have here, or an updated version. */ | ||
1197 | } else if ((c % 5) != 2 || c > 5435) { | 1355 | } else if ((c % 5) != 2 || c > 5435) { |
1198 | if (!(c % 20) && c >= 5120) { | 1356 | if (!(c % 20) && c >= 5120) { |
1199 | data0 = ath5k_hw_bitswap(((c - 4800) / 20 << 2), 8); | 1357 | data0 = ath5k_hw_bitswap(((c - 4800) / 20 << 2), 8); |
@@ -1219,10 +1377,16 @@ static int ath5k_hw_rf5112_channel(struct ath5k_hw *ah, | |||
1219 | return 0; | 1377 | return 0; |
1220 | } | 1378 | } |
1221 | 1379 | ||
1222 | /* | 1380 | /** |
1223 | * Set the channel on the RF2425 | 1381 | * ath5k_hw_rf2425_channel() - Set channel frequency on RF2425 |
1382 | * @ah: The &struct ath5k_hw | ||
1383 | * @channel: The &struct ieee80211_channel | ||
1384 | * | ||
1385 | * AR2425/2417 have a different 2GHz RF so code changes | ||
1386 | * a little bit from RF5112. | ||
1224 | */ | 1387 | */ |
1225 | static int ath5k_hw_rf2425_channel(struct ath5k_hw *ah, | 1388 | static int |
1389 | ath5k_hw_rf2425_channel(struct ath5k_hw *ah, | ||
1226 | struct ieee80211_channel *channel) | 1390 | struct ieee80211_channel *channel) |
1227 | { | 1391 | { |
1228 | u32 data, data0, data2; | 1392 | u32 data, data0, data2; |
@@ -1258,10 +1422,16 @@ static int ath5k_hw_rf2425_channel(struct ath5k_hw *ah, | |||
1258 | return 0; | 1422 | return 0; |
1259 | } | 1423 | } |
1260 | 1424 | ||
1261 | /* | 1425 | /** |
1262 | * Set a channel on the radio chip | 1426 | * ath5k_hw_channel() - Set a channel on the radio chip |
1427 | * @ah: The &struct ath5k_hw | ||
1428 | * @channel: The &struct ieee80211_channel | ||
1429 | * | ||
1430 | * This is the main function called to set a channel on the | ||
1431 | * radio chip based on the radio chip version. | ||
1263 | */ | 1432 | */ |
1264 | static int ath5k_hw_channel(struct ath5k_hw *ah, | 1433 | static int |
1434 | ath5k_hw_channel(struct ath5k_hw *ah, | ||
1265 | struct ieee80211_channel *channel) | 1435 | struct ieee80211_channel *channel) |
1266 | { | 1436 | { |
1267 | int ret; | 1437 | int ret; |
@@ -1313,11 +1483,46 @@ static int ath5k_hw_channel(struct ath5k_hw *ah, | |||
1313 | return 0; | 1483 | return 0; |
1314 | } | 1484 | } |
1315 | 1485 | ||
1486 | |||
1316 | /*****************\ | 1487 | /*****************\ |
1317 | PHY calibration | 1488 | PHY calibration |
1318 | \*****************/ | 1489 | \*****************/ |
1319 | 1490 | ||
1320 | static s32 ath5k_hw_read_measured_noise_floor(struct ath5k_hw *ah) | 1491 | /** |
1492 | * DOC: PHY Calibration routines | ||
1493 | * | ||
1494 | * Noise floor calibration: When we tell the hardware to | ||
1495 | * perform a noise floor calibration by setting the | ||
1496 | * AR5K_PHY_AGCCTL_NF bit on AR5K_PHY_AGCCTL, it will periodically | ||
1497 | * sample-and-hold the minimum noise level seen at the antennas. | ||
1498 | * This value is then stored in a ring buffer of recently measured | ||
1499 | * noise floor values so we have a moving window of the last few | ||
1500 | * samples. The median of the values in the history is then loaded | ||
1501 | * into the hardware for its own use for RSSI and CCA measurements. | ||
1502 | * This type of calibration doesn't interfere with traffic. | ||
1503 | * | ||
1504 | * AGC calibration: When we tell the hardware to perform | ||
1505 | * an AGC (Automatic Gain Control) calibration by setting the | ||
1506 | * AR5K_PHY_AGCCTL_CAL, hw disconnects the antennas and does | ||
1507 | * a calibration on the DC offsets of ADCs. During this period | ||
1508 | * rx/tx gets disabled so we have to deal with it on the driver | ||
1509 | * part. | ||
1510 | * | ||
1511 | * I/Q calibration: When we tell the hardware to perform | ||
1512 | * an I/Q calibration, it tries to correct I/Q imbalance and | ||
1513 | * fix QAM constellation by sampling data from rxed frames. | ||
1514 | * It doesn't interfere with traffic. | ||
1515 | * | ||
1516 | * For more infos on AGC and I/Q calibration check out patent doc | ||
1517 | * #03/094463. | ||
1518 | */ | ||
1519 | |||
1520 | /** | ||
1521 | * ath5k_hw_read_measured_noise_floor() - Read measured NF from hw | ||
1522 | * @ah: The &struct ath5k_hw | ||
1523 | */ | ||
1524 | static s32 | ||
1525 | ath5k_hw_read_measured_noise_floor(struct ath5k_hw *ah) | ||
1321 | { | 1526 | { |
1322 | s32 val; | 1527 | s32 val; |
1323 | 1528 | ||
@@ -1325,7 +1530,12 @@ static s32 ath5k_hw_read_measured_noise_floor(struct ath5k_hw *ah) | |||
1325 | return sign_extend32(AR5K_REG_MS(val, AR5K_PHY_NF_MINCCA_PWR), 8); | 1530 | return sign_extend32(AR5K_REG_MS(val, AR5K_PHY_NF_MINCCA_PWR), 8); |
1326 | } | 1531 | } |
1327 | 1532 | ||
1328 | void ath5k_hw_init_nfcal_hist(struct ath5k_hw *ah) | 1533 | /** |
1534 | * ath5k_hw_init_nfcal_hist() - Initialize NF calibration history buffer | ||
1535 | * @ah: The &struct ath5k_hw | ||
1536 | */ | ||
1537 | void | ||
1538 | ath5k_hw_init_nfcal_hist(struct ath5k_hw *ah) | ||
1329 | { | 1539 | { |
1330 | int i; | 1540 | int i; |
1331 | 1541 | ||
@@ -1334,6 +1544,11 @@ void ath5k_hw_init_nfcal_hist(struct ath5k_hw *ah) | |||
1334 | ah->ah_nfcal_hist.nfval[i] = AR5K_TUNE_CCA_MAX_GOOD_VALUE; | 1544 | ah->ah_nfcal_hist.nfval[i] = AR5K_TUNE_CCA_MAX_GOOD_VALUE; |
1335 | } | 1545 | } |
1336 | 1546 | ||
1547 | /** | ||
1548 | * ath5k_hw_update_nfcal_hist() - Update NF calibration history buffer | ||
1549 | * @ah: The &struct ath5k_hw | ||
1550 | * @noise_floor: The NF we got from hw | ||
1551 | */ | ||
1337 | static void ath5k_hw_update_nfcal_hist(struct ath5k_hw *ah, s16 noise_floor) | 1552 | static void ath5k_hw_update_nfcal_hist(struct ath5k_hw *ah, s16 noise_floor) |
1338 | { | 1553 | { |
1339 | struct ath5k_nfcal_hist *hist = &ah->ah_nfcal_hist; | 1554 | struct ath5k_nfcal_hist *hist = &ah->ah_nfcal_hist; |
@@ -1341,7 +1556,12 @@ static void ath5k_hw_update_nfcal_hist(struct ath5k_hw *ah, s16 noise_floor) | |||
1341 | hist->nfval[hist->index] = noise_floor; | 1556 | hist->nfval[hist->index] = noise_floor; |
1342 | } | 1557 | } |
1343 | 1558 | ||
1344 | static s16 ath5k_hw_get_median_noise_floor(struct ath5k_hw *ah) | 1559 | /** |
1560 | * ath5k_hw_get_median_noise_floor() - Get median NF from history buffer | ||
1561 | * @ah: The &struct ath5k_hw | ||
1562 | */ | ||
1563 | static s16 | ||
1564 | ath5k_hw_get_median_noise_floor(struct ath5k_hw *ah) | ||
1345 | { | 1565 | { |
1346 | s16 sort[ATH5K_NF_CAL_HIST_MAX]; | 1566 | s16 sort[ATH5K_NF_CAL_HIST_MAX]; |
1347 | s16 tmp; | 1567 | s16 tmp; |
@@ -1364,18 +1584,16 @@ static s16 ath5k_hw_get_median_noise_floor(struct ath5k_hw *ah) | |||
1364 | return sort[(ATH5K_NF_CAL_HIST_MAX - 1) / 2]; | 1584 | return sort[(ATH5K_NF_CAL_HIST_MAX - 1) / 2]; |
1365 | } | 1585 | } |
1366 | 1586 | ||
1367 | /* | 1587 | /** |
1368 | * When we tell the hardware to perform a noise floor calibration | 1588 | * ath5k_hw_update_noise_floor() - Update NF on hardware |
1369 | * by setting the AR5K_PHY_AGCCTL_NF bit, it will periodically | 1589 | * @ah: The &struct ath5k_hw |
1370 | * sample-and-hold the minimum noise level seen at the antennas. | ||
1371 | * This value is then stored in a ring buffer of recently measured | ||
1372 | * noise floor values so we have a moving window of the last few | ||
1373 | * samples. | ||
1374 | * | 1590 | * |
1375 | * The median of the values in the history is then loaded into the | 1591 | * This is the main function we call to perform a NF calibration, |
1376 | * hardware for its own use for RSSI and CCA measurements. | 1592 | * it reads NF from hardware, calculates the median and updates |
1593 | * NF on hw. | ||
1377 | */ | 1594 | */ |
1378 | void ath5k_hw_update_noise_floor(struct ath5k_hw *ah) | 1595 | void |
1596 | ath5k_hw_update_noise_floor(struct ath5k_hw *ah) | ||
1379 | { | 1597 | { |
1380 | struct ath5k_eeprom_info *ee = &ah->ah_capabilities.cap_eeprom; | 1598 | struct ath5k_eeprom_info *ee = &ah->ah_capabilities.cap_eeprom; |
1381 | u32 val; | 1599 | u32 val; |
@@ -1390,6 +1608,8 @@ void ath5k_hw_update_noise_floor(struct ath5k_hw *ah) | |||
1390 | return; | 1608 | return; |
1391 | } | 1609 | } |
1392 | 1610 | ||
1611 | ah->ah_cal_mask |= AR5K_CALIBRATION_NF; | ||
1612 | |||
1393 | ee_mode = ath5k_eeprom_mode_from_channel(ah->ah_current_channel); | 1613 | ee_mode = ath5k_eeprom_mode_from_channel(ah->ah_current_channel); |
1394 | 1614 | ||
1395 | /* completed NF calibration, test threshold */ | 1615 | /* completed NF calibration, test threshold */ |
@@ -1434,20 +1654,29 @@ void ath5k_hw_update_noise_floor(struct ath5k_hw *ah) | |||
1434 | 1654 | ||
1435 | ah->ah_noise_floor = nf; | 1655 | ah->ah_noise_floor = nf; |
1436 | 1656 | ||
1657 | ah->ah_cal_mask &= ~AR5K_CALIBRATION_NF; | ||
1658 | |||
1437 | ATH5K_DBG(ah, ATH5K_DEBUG_CALIBRATE, | 1659 | ATH5K_DBG(ah, ATH5K_DEBUG_CALIBRATE, |
1438 | "noise floor calibrated: %d\n", nf); | 1660 | "noise floor calibrated: %d\n", nf); |
1439 | } | 1661 | } |
1440 | 1662 | ||
1441 | /* | 1663 | /** |
1442 | * Perform a PHY calibration on RF5110 | 1664 | * ath5k_hw_rf5110_calibrate() - Perform a PHY calibration on RF5110 |
1443 | * -Fix BPSK/QAM Constellation (I/Q correction) | 1665 | * @ah: The &struct ath5k_hw |
1666 | * @channel: The &struct ieee80211_channel | ||
1667 | * | ||
1668 | * Do a complete PHY calibration (AGC + NF + I/Q) on RF5110 | ||
1444 | */ | 1669 | */ |
1445 | static int ath5k_hw_rf5110_calibrate(struct ath5k_hw *ah, | 1670 | static int |
1671 | ath5k_hw_rf5110_calibrate(struct ath5k_hw *ah, | ||
1446 | struct ieee80211_channel *channel) | 1672 | struct ieee80211_channel *channel) |
1447 | { | 1673 | { |
1448 | u32 phy_sig, phy_agc, phy_sat, beacon; | 1674 | u32 phy_sig, phy_agc, phy_sat, beacon; |
1449 | int ret; | 1675 | int ret; |
1450 | 1676 | ||
1677 | if (!(ah->ah_cal_mask & AR5K_CALIBRATION_FULL)) | ||
1678 | return 0; | ||
1679 | |||
1451 | /* | 1680 | /* |
1452 | * Disable beacons and RX/TX queues, wait | 1681 | * Disable beacons and RX/TX queues, wait |
1453 | */ | 1682 | */ |
@@ -1456,7 +1685,7 @@ static int ath5k_hw_rf5110_calibrate(struct ath5k_hw *ah, | |||
1456 | beacon = ath5k_hw_reg_read(ah, AR5K_BEACON_5210); | 1685 | beacon = ath5k_hw_reg_read(ah, AR5K_BEACON_5210); |
1457 | ath5k_hw_reg_write(ah, beacon & ~AR5K_BEACON_ENABLE, AR5K_BEACON_5210); | 1686 | ath5k_hw_reg_write(ah, beacon & ~AR5K_BEACON_ENABLE, AR5K_BEACON_5210); |
1458 | 1687 | ||
1459 | mdelay(2); | 1688 | usleep_range(2000, 2500); |
1460 | 1689 | ||
1461 | /* | 1690 | /* |
1462 | * Set the channel (with AGC turned off) | 1691 | * Set the channel (with AGC turned off) |
@@ -1469,7 +1698,7 @@ static int ath5k_hw_rf5110_calibrate(struct ath5k_hw *ah, | |||
1469 | * Activate PHY and wait | 1698 | * Activate PHY and wait |
1470 | */ | 1699 | */ |
1471 | ath5k_hw_reg_write(ah, AR5K_PHY_ACT_ENABLE, AR5K_PHY_ACT); | 1700 | ath5k_hw_reg_write(ah, AR5K_PHY_ACT_ENABLE, AR5K_PHY_ACT); |
1472 | mdelay(1); | 1701 | usleep_range(1000, 1500); |
1473 | 1702 | ||
1474 | AR5K_REG_DISABLE_BITS(ah, AR5K_PHY_AGC, AR5K_PHY_AGC_DISABLE); | 1703 | AR5K_REG_DISABLE_BITS(ah, AR5K_PHY_AGC, AR5K_PHY_AGC_DISABLE); |
1475 | 1704 | ||
@@ -1506,7 +1735,7 @@ static int ath5k_hw_rf5110_calibrate(struct ath5k_hw *ah, | |||
1506 | ath5k_hw_reg_write(ah, AR5K_PHY_RFSTG_DISABLE, AR5K_PHY_RFSTG); | 1735 | ath5k_hw_reg_write(ah, AR5K_PHY_RFSTG_DISABLE, AR5K_PHY_RFSTG); |
1507 | AR5K_REG_DISABLE_BITS(ah, AR5K_PHY_AGC, AR5K_PHY_AGC_DISABLE); | 1736 | AR5K_REG_DISABLE_BITS(ah, AR5K_PHY_AGC, AR5K_PHY_AGC_DISABLE); |
1508 | 1737 | ||
1509 | mdelay(1); | 1738 | usleep_range(1000, 1500); |
1510 | 1739 | ||
1511 | /* | 1740 | /* |
1512 | * Enable calibration and wait until completion | 1741 | * Enable calibration and wait until completion |
@@ -1537,8 +1766,9 @@ static int ath5k_hw_rf5110_calibrate(struct ath5k_hw *ah, | |||
1537 | return 0; | 1766 | return 0; |
1538 | } | 1767 | } |
1539 | 1768 | ||
1540 | /* | 1769 | /** |
1541 | * Perform I/Q calibration on RF5111/5112 and newer chips | 1770 | * ath5k_hw_rf511x_iq_calibrate() - Perform I/Q calibration on RF5111 and newer |
1771 | * @ah: The &struct ath5k_hw | ||
1542 | */ | 1772 | */ |
1543 | static int | 1773 | static int |
1544 | ath5k_hw_rf511x_iq_calibrate(struct ath5k_hw *ah) | 1774 | ath5k_hw_rf511x_iq_calibrate(struct ath5k_hw *ah) |
@@ -1547,12 +1777,19 @@ ath5k_hw_rf511x_iq_calibrate(struct ath5k_hw *ah) | |||
1547 | s32 iq_corr, i_coff, i_coffd, q_coff, q_coffd; | 1777 | s32 iq_corr, i_coff, i_coffd, q_coff, q_coffd; |
1548 | int i; | 1778 | int i; |
1549 | 1779 | ||
1550 | if (!ah->ah_calibration || | 1780 | /* Skip if I/Q calibration is not needed or if it's still running */ |
1551 | ath5k_hw_reg_read(ah, AR5K_PHY_IQ) & AR5K_PHY_IQ_RUN) | 1781 | if (!ah->ah_iq_cal_needed) |
1552 | return 0; | 1782 | return -EINVAL; |
1783 | else if (ath5k_hw_reg_read(ah, AR5K_PHY_IQ) & AR5K_PHY_IQ_RUN) { | ||
1784 | ATH5K_DBG_UNLIMIT(ah, ATH5K_DEBUG_CALIBRATE, | ||
1785 | "I/Q calibration still running"); | ||
1786 | return -EBUSY; | ||
1787 | } | ||
1553 | 1788 | ||
1554 | /* Calibration has finished, get the results and re-run */ | 1789 | /* Calibration has finished, get the results and re-run */ |
1555 | /* work around empty results which can apparently happen on 5212 */ | 1790 | |
1791 | /* Work around for empty results which can apparently happen on 5212: | ||
1792 | * Read registers up to 10 times until we get both i_pr and q_pwr */ | ||
1556 | for (i = 0; i <= 10; i++) { | 1793 | for (i = 0; i <= 10; i++) { |
1557 | iq_corr = ath5k_hw_reg_read(ah, AR5K_PHY_IQRES_CAL_CORR); | 1794 | iq_corr = ath5k_hw_reg_read(ah, AR5K_PHY_IQRES_CAL_CORR); |
1558 | i_pwr = ath5k_hw_reg_read(ah, AR5K_PHY_IQRES_CAL_PWR_I); | 1795 | i_pwr = ath5k_hw_reg_read(ah, AR5K_PHY_IQRES_CAL_PWR_I); |
@@ -1570,9 +1807,13 @@ ath5k_hw_rf511x_iq_calibrate(struct ath5k_hw *ah) | |||
1570 | else | 1807 | else |
1571 | q_coffd = q_pwr >> 7; | 1808 | q_coffd = q_pwr >> 7; |
1572 | 1809 | ||
1573 | /* protect against divide by 0 and loss of sign bits */ | 1810 | /* In case i_coffd became zero, cancel calibration |
1811 | * not only it's too small, it'll also result a divide | ||
1812 | * by zero later on. */ | ||
1574 | if (i_coffd == 0 || q_coffd < 2) | 1813 | if (i_coffd == 0 || q_coffd < 2) |
1575 | return 0; | 1814 | return -ECANCELED; |
1815 | |||
1816 | /* Protect against loss of sign bits */ | ||
1576 | 1817 | ||
1577 | i_coff = (-iq_corr) / i_coffd; | 1818 | i_coff = (-iq_corr) / i_coffd; |
1578 | i_coff = clamp(i_coff, -32, 31); /* signed 6 bit */ | 1819 | i_coff = clamp(i_coff, -32, 31); /* signed 6 bit */ |
@@ -1601,10 +1842,17 @@ ath5k_hw_rf511x_iq_calibrate(struct ath5k_hw *ah) | |||
1601 | return 0; | 1842 | return 0; |
1602 | } | 1843 | } |
1603 | 1844 | ||
1604 | /* | 1845 | /** |
1605 | * Perform a PHY calibration | 1846 | * ath5k_hw_phy_calibrate() - Perform a PHY calibration |
1847 | * @ah: The &struct ath5k_hw | ||
1848 | * @channel: The &struct ieee80211_channel | ||
1849 | * | ||
1850 | * The main function we call from above to perform | ||
1851 | * a short or full PHY calibration based on RF chip | ||
1852 | * and current channel | ||
1606 | */ | 1853 | */ |
1607 | int ath5k_hw_phy_calibrate(struct ath5k_hw *ah, | 1854 | int |
1855 | ath5k_hw_phy_calibrate(struct ath5k_hw *ah, | ||
1608 | struct ieee80211_channel *channel) | 1856 | struct ieee80211_channel *channel) |
1609 | { | 1857 | { |
1610 | int ret; | 1858 | int ret; |
@@ -1613,10 +1861,43 @@ int ath5k_hw_phy_calibrate(struct ath5k_hw *ah, | |||
1613 | return ath5k_hw_rf5110_calibrate(ah, channel); | 1861 | return ath5k_hw_rf5110_calibrate(ah, channel); |
1614 | 1862 | ||
1615 | ret = ath5k_hw_rf511x_iq_calibrate(ah); | 1863 | ret = ath5k_hw_rf511x_iq_calibrate(ah); |
1864 | if (ret) { | ||
1865 | ATH5K_DBG_UNLIMIT(ah, ATH5K_DEBUG_CALIBRATE, | ||
1866 | "No I/Q correction performed (%uMHz)\n", | ||
1867 | channel->center_freq); | ||
1868 | |||
1869 | /* Happens all the time if there is not much | ||
1870 | * traffic, consider it normal behaviour. */ | ||
1871 | ret = 0; | ||
1872 | } | ||
1873 | |||
1874 | /* On full calibration do an AGC calibration and | ||
1875 | * request a PAPD probe for gainf calibration if | ||
1876 | * needed */ | ||
1877 | if (ah->ah_cal_mask & AR5K_CALIBRATION_FULL) { | ||
1616 | 1878 | ||
1617 | if ((ah->ah_radio == AR5K_RF5111 || ah->ah_radio == AR5K_RF5112) && | 1879 | AR5K_REG_ENABLE_BITS(ah, AR5K_PHY_AGCCTL, |
1618 | (channel->hw_value != AR5K_MODE_11B)) | 1880 | AR5K_PHY_AGCCTL_CAL); |
1619 | ath5k_hw_request_rfgain_probe(ah); | 1881 | |
1882 | ret = ath5k_hw_register_timeout(ah, AR5K_PHY_AGCCTL, | ||
1883 | AR5K_PHY_AGCCTL_CAL | AR5K_PHY_AGCCTL_NF, | ||
1884 | 0, false); | ||
1885 | if (ret) { | ||
1886 | ATH5K_ERR(ah, | ||
1887 | "gain calibration timeout (%uMHz)\n", | ||
1888 | channel->center_freq); | ||
1889 | } | ||
1890 | |||
1891 | if ((ah->ah_radio == AR5K_RF5111 || | ||
1892 | ah->ah_radio == AR5K_RF5112) | ||
1893 | && (channel->hw_value != AR5K_MODE_11B)) | ||
1894 | ath5k_hw_request_rfgain_probe(ah); | ||
1895 | } | ||
1896 | |||
1897 | /* Update noise floor | ||
1898 | * XXX: Only do this after AGC calibration */ | ||
1899 | if (!(ah->ah_cal_mask & AR5K_CALIBRATION_NF)) | ||
1900 | ath5k_hw_update_noise_floor(ah); | ||
1620 | 1901 | ||
1621 | return ret; | 1902 | return ret; |
1622 | } | 1903 | } |
@@ -1626,6 +1907,16 @@ int ath5k_hw_phy_calibrate(struct ath5k_hw *ah, | |||
1626 | * Spur mitigation functions * | 1907 | * Spur mitigation functions * |
1627 | \***************************/ | 1908 | \***************************/ |
1628 | 1909 | ||
1910 | /** | ||
1911 | * ath5k_hw_set_spur_mitigation_filter() - Configure SPUR filter | ||
1912 | * @ah: The &struct ath5k_hw | ||
1913 | * @channel: The &struct ieee80211_channel | ||
1914 | * | ||
1915 | * This function gets called during PHY initialization to | ||
1916 | * configure the spur filter for the given channel. Spur is noise | ||
1917 | * generated due to "reflection" effects, for more information on this | ||
1918 | * method check out patent US7643810 | ||
1919 | */ | ||
1629 | static void | 1920 | static void |
1630 | ath5k_hw_set_spur_mitigation_filter(struct ath5k_hw *ah, | 1921 | ath5k_hw_set_spur_mitigation_filter(struct ath5k_hw *ah, |
1631 | struct ieee80211_channel *channel) | 1922 | struct ieee80211_channel *channel) |
@@ -1865,15 +2156,73 @@ ath5k_hw_set_spur_mitigation_filter(struct ath5k_hw *ah, | |||
1865 | * Antenna control * | 2156 | * Antenna control * |
1866 | \*****************/ | 2157 | \*****************/ |
1867 | 2158 | ||
1868 | static void /*TODO:Boundary check*/ | 2159 | /** |
2160 | * DOC: Antenna control | ||
2161 | * | ||
2162 | * Hw supports up to 14 antennas ! I haven't found any card that implements | ||
2163 | * that. The maximum number of antennas I've seen is up to 4 (2 for 2GHz and 2 | ||
2164 | * for 5GHz). Antenna 1 (MAIN) should be omnidirectional, 2 (AUX) | ||
2165 | * omnidirectional or sectorial and antennas 3-14 sectorial (or directional). | ||
2166 | * | ||
2167 | * We can have a single antenna for RX and multiple antennas for TX. | ||
2168 | * RX antenna is our "default" antenna (usually antenna 1) set on | ||
2169 | * DEFAULT_ANTENNA register and TX antenna is set on each TX control descriptor | ||
2170 | * (0 for automatic selection, 1 - 14 antenna number). | ||
2171 | * | ||
2172 | * We can let hw do all the work doing fast antenna diversity for both | ||
2173 | * tx and rx or we can do things manually. Here are the options we have | ||
2174 | * (all are bits of STA_ID1 register): | ||
2175 | * | ||
2176 | * AR5K_STA_ID1_DEFAULT_ANTENNA -> When 0 is set as the TX antenna on TX | ||
2177 | * control descriptor, use the default antenna to transmit or else use the last | ||
2178 | * antenna on which we received an ACK. | ||
2179 | * | ||
2180 | * AR5K_STA_ID1_DESC_ANTENNA -> Update default antenna after each TX frame to | ||
2181 | * the antenna on which we got the ACK for that frame. | ||
2182 | * | ||
2183 | * AR5K_STA_ID1_RTS_DEF_ANTENNA -> Use default antenna for RTS or else use the | ||
2184 | * one on the TX descriptor. | ||
2185 | * | ||
2186 | * AR5K_STA_ID1_SELFGEN_DEF_ANT -> Use default antenna for self generated frames | ||
2187 | * (ACKs etc), or else use current antenna (the one we just used for TX). | ||
2188 | * | ||
2189 | * Using the above we support the following scenarios: | ||
2190 | * | ||
2191 | * AR5K_ANTMODE_DEFAULT -> Hw handles antenna diversity etc automatically | ||
2192 | * | ||
2193 | * AR5K_ANTMODE_FIXED_A -> Only antenna A (MAIN) is present | ||
2194 | * | ||
2195 | * AR5K_ANTMODE_FIXED_B -> Only antenna B (AUX) is present | ||
2196 | * | ||
2197 | * AR5K_ANTMODE_SINGLE_AP -> Sta locked on a single ap | ||
2198 | * | ||
2199 | * AR5K_ANTMODE_SECTOR_AP -> AP with tx antenna set on tx desc | ||
2200 | * | ||
2201 | * AR5K_ANTMODE_SECTOR_STA -> STA with tx antenna set on tx desc | ||
2202 | * | ||
2203 | * AR5K_ANTMODE_DEBUG Debug mode -A -> Rx, B-> Tx- | ||
2204 | * | ||
2205 | * Also note that when setting antenna to F on tx descriptor card inverts | ||
2206 | * current tx antenna. | ||
2207 | */ | ||
2208 | |||
2209 | /** | ||
2210 | * ath5k_hw_set_def_antenna() - Set default rx antenna on AR5211/5212 and newer | ||
2211 | * @ah: The &struct ath5k_hw | ||
2212 | * @ant: Antenna number | ||
2213 | */ | ||
2214 | static void | ||
1869 | ath5k_hw_set_def_antenna(struct ath5k_hw *ah, u8 ant) | 2215 | ath5k_hw_set_def_antenna(struct ath5k_hw *ah, u8 ant) |
1870 | { | 2216 | { |
1871 | if (ah->ah_version != AR5K_AR5210) | 2217 | if (ah->ah_version != AR5K_AR5210) |
1872 | ath5k_hw_reg_write(ah, ant & 0x7, AR5K_DEFAULT_ANTENNA); | 2218 | ath5k_hw_reg_write(ah, ant & 0x7, AR5K_DEFAULT_ANTENNA); |
1873 | } | 2219 | } |
1874 | 2220 | ||
1875 | /* | 2221 | /** |
1876 | * Enable/disable fast rx antenna diversity | 2222 | * ath5k_hw_set_fast_div() - Enable/disable fast rx antenna diversity |
2223 | * @ah: The &struct ath5k_hw | ||
2224 | * @ee_mode: One of enum ath5k_driver_mode | ||
2225 | * @enable: True to enable, false to disable | ||
1877 | */ | 2226 | */ |
1878 | static void | 2227 | static void |
1879 | ath5k_hw_set_fast_div(struct ath5k_hw *ah, u8 ee_mode, bool enable) | 2228 | ath5k_hw_set_fast_div(struct ath5k_hw *ah, u8 ee_mode, bool enable) |
@@ -1913,6 +2262,14 @@ ath5k_hw_set_fast_div(struct ath5k_hw *ah, u8 ee_mode, bool enable) | |||
1913 | } | 2262 | } |
1914 | } | 2263 | } |
1915 | 2264 | ||
2265 | /** | ||
2266 | * ath5k_hw_set_antenna_switch() - Set up antenna switch table | ||
2267 | * @ah: The &struct ath5k_hw | ||
2268 | * @ee_mode: One of enum ath5k_driver_mode | ||
2269 | * | ||
2270 | * Switch table comes from EEPROM and includes information on controlling | ||
2271 | * the 2 antenna RX attenuators | ||
2272 | */ | ||
1916 | void | 2273 | void |
1917 | ath5k_hw_set_antenna_switch(struct ath5k_hw *ah, u8 ee_mode) | 2274 | ath5k_hw_set_antenna_switch(struct ath5k_hw *ah, u8 ee_mode) |
1918 | { | 2275 | { |
@@ -1944,8 +2301,10 @@ ath5k_hw_set_antenna_switch(struct ath5k_hw *ah, u8 ee_mode) | |||
1944 | AR5K_PHY_ANT_SWITCH_TABLE_1); | 2301 | AR5K_PHY_ANT_SWITCH_TABLE_1); |
1945 | } | 2302 | } |
1946 | 2303 | ||
1947 | /* | 2304 | /** |
1948 | * Set antenna operating mode | 2305 | * ath5k_hw_set_antenna_mode() - Set antenna operating mode |
2306 | * @ah: The &struct ath5k_hw | ||
2307 | * @ant_mode: One of enum ath5k_ant_mode | ||
1949 | */ | 2308 | */ |
1950 | void | 2309 | void |
1951 | ath5k_hw_set_antenna_mode(struct ath5k_hw *ah, u8 ant_mode) | 2310 | ath5k_hw_set_antenna_mode(struct ath5k_hw *ah, u8 ant_mode) |
@@ -2068,8 +2427,13 @@ ath5k_hw_set_antenna_mode(struct ath5k_hw *ah, u8 ant_mode) | |||
2068 | * Helper functions | 2427 | * Helper functions |
2069 | */ | 2428 | */ |
2070 | 2429 | ||
2071 | /* | 2430 | /** |
2072 | * Do linear interpolation between two given (x, y) points | 2431 | * ath5k_get_interpolated_value() - Get interpolated Y val between two points |
2432 | * @target: X value of the middle point | ||
2433 | * @x_left: X value of the left point | ||
2434 | * @x_right: X value of the right point | ||
2435 | * @y_left: Y value of the left point | ||
2436 | * @y_right: Y value of the right point | ||
2073 | */ | 2437 | */ |
2074 | static s16 | 2438 | static s16 |
2075 | ath5k_get_interpolated_value(s16 target, s16 x_left, s16 x_right, | 2439 | ath5k_get_interpolated_value(s16 target, s16 x_left, s16 x_right, |
@@ -2096,13 +2460,18 @@ ath5k_get_interpolated_value(s16 target, s16 x_left, s16 x_right, | |||
2096 | return result; | 2460 | return result; |
2097 | } | 2461 | } |
2098 | 2462 | ||
2099 | /* | 2463 | /** |
2100 | * Find vertical boundary (min pwr) for the linear PCDAC curve. | 2464 | * ath5k_get_linear_pcdac_min() - Find vertical boundary (min pwr) for the |
2465 | * linear PCDAC curve | ||
2466 | * @stepL: Left array with y values (pcdac steps) | ||
2467 | * @stepR: Right array with y values (pcdac steps) | ||
2468 | * @pwrL: Left array with x values (power steps) | ||
2469 | * @pwrR: Right array with x values (power steps) | ||
2101 | * | 2470 | * |
2102 | * Since we have the top of the curve and we draw the line below | 2471 | * Since we have the top of the curve and we draw the line below |
2103 | * until we reach 1 (1 pcdac step) we need to know which point | 2472 | * until we reach 1 (1 pcdac step) we need to know which point |
2104 | * (x value) that is so that we don't go below y axis and have negative | 2473 | * (x value) that is so that we don't go below x axis and have negative |
2105 | * pcdac values when creating the curve, or fill the table with zeroes. | 2474 | * pcdac values when creating the curve, or fill the table with zeros. |
2106 | */ | 2475 | */ |
2107 | static s16 | 2476 | static s16 |
2108 | ath5k_get_linear_pcdac_min(const u8 *stepL, const u8 *stepR, | 2477 | ath5k_get_linear_pcdac_min(const u8 *stepL, const u8 *stepR, |
@@ -2148,7 +2517,16 @@ ath5k_get_linear_pcdac_min(const u8 *stepL, const u8 *stepR, | |||
2148 | return max(min_pwrL, min_pwrR); | 2517 | return max(min_pwrL, min_pwrR); |
2149 | } | 2518 | } |
2150 | 2519 | ||
2151 | /* | 2520 | /** |
2521 | * ath5k_create_power_curve() - Create a Power to PDADC or PCDAC curve | ||
2522 | * @pmin: Minimum power value (xmin) | ||
2523 | * @pmax: Maximum power value (xmax) | ||
2524 | * @pwr: Array of power steps (x values) | ||
2525 | * @vpd: Array of matching PCDAC/PDADC steps (y values) | ||
2526 | * @num_points: Number of provided points | ||
2527 | * @vpd_table: Array to fill with the full PCDAC/PDADC values (y values) | ||
2528 | * @type: One of enum ath5k_powertable_type (eeprom.h) | ||
2529 | * | ||
2152 | * Interpolate (pwr,vpd) points to create a Power to PDADC or a | 2530 | * Interpolate (pwr,vpd) points to create a Power to PDADC or a |
2153 | * Power to PCDAC curve. | 2531 | * Power to PCDAC curve. |
2154 | * | 2532 | * |
@@ -2206,7 +2584,14 @@ ath5k_create_power_curve(s16 pmin, s16 pmax, | |||
2206 | } | 2584 | } |
2207 | } | 2585 | } |
2208 | 2586 | ||
2209 | /* | 2587 | /** |
2588 | * ath5k_get_chan_pcal_surrounding_piers() - Get surrounding calibration piers | ||
2589 | * for a given channel. | ||
2590 | * @ah: The &struct ath5k_hw | ||
2591 | * @channel: The &struct ieee80211_channel | ||
2592 | * @pcinfo_l: The &struct ath5k_chan_pcal_info to put the left cal. pier | ||
2593 | * @pcinfo_r: The &struct ath5k_chan_pcal_info to put the right cal. pier | ||
2594 | * | ||
2210 | * Get the surrounding per-channel power calibration piers | 2595 | * Get the surrounding per-channel power calibration piers |
2211 | * for a given frequency so that we can interpolate between | 2596 | * for a given frequency so that we can interpolate between |
2212 | * them and come up with an appropriate dataset for our current | 2597 | * them and come up with an appropriate dataset for our current |
@@ -2289,11 +2674,17 @@ done: | |||
2289 | *pcinfo_r = &pcinfo[idx_r]; | 2674 | *pcinfo_r = &pcinfo[idx_r]; |
2290 | } | 2675 | } |
2291 | 2676 | ||
2292 | /* | 2677 | /** |
2678 | * ath5k_get_rate_pcal_data() - Get the interpolated per-rate power | ||
2679 | * calibration data | ||
2680 | * @ah: The &struct ath5k_hw *ah, | ||
2681 | * @channel: The &struct ieee80211_channel | ||
2682 | * @rates: The &struct ath5k_rate_pcal_info to fill | ||
2683 | * | ||
2293 | * Get the surrounding per-rate power calibration data | 2684 | * Get the surrounding per-rate power calibration data |
2294 | * for a given frequency and interpolate between power | 2685 | * for a given frequency and interpolate between power |
2295 | * values to set max target power supported by hw for | 2686 | * values to set max target power supported by hw for |
2296 | * each rate. | 2687 | * each rate on this frequency. |
2297 | */ | 2688 | */ |
2298 | static void | 2689 | static void |
2299 | ath5k_get_rate_pcal_data(struct ath5k_hw *ah, | 2690 | ath5k_get_rate_pcal_data(struct ath5k_hw *ah, |
@@ -2381,7 +2772,11 @@ done: | |||
2381 | rpinfo[idx_r].target_power_54); | 2772 | rpinfo[idx_r].target_power_54); |
2382 | } | 2773 | } |
2383 | 2774 | ||
2384 | /* | 2775 | /** |
2776 | * ath5k_get_max_ctl_power() - Get max edge power for a given frequency | ||
2777 | * @ah: the &struct ath5k_hw | ||
2778 | * @channel: The &struct ieee80211_channel | ||
2779 | * | ||
2385 | * Get the max edge power for this channel if | 2780 | * Get the max edge power for this channel if |
2386 | * we have such data from EEPROM's Conformance Test | 2781 | * we have such data from EEPROM's Conformance Test |
2387 | * Limits (CTL), and limit max power if needed. | 2782 | * Limits (CTL), and limit max power if needed. |
@@ -2461,8 +2856,39 @@ ath5k_get_max_ctl_power(struct ath5k_hw *ah, | |||
2461 | * Power to PCDAC table functions | 2856 | * Power to PCDAC table functions |
2462 | */ | 2857 | */ |
2463 | 2858 | ||
2464 | /* | 2859 | /** |
2465 | * Fill Power to PCDAC table on RF5111 | 2860 | * DOC: Power to PCDAC table functions |
2861 | * | ||
2862 | * For RF5111 we have an XPD -eXternal Power Detector- curve | ||
2863 | * for each calibrated channel. Each curve has 0,5dB Power steps | ||
2864 | * on x axis and PCDAC steps (offsets) on y axis and looks like an | ||
2865 | * exponential function. To recreate the curve we read 11 points | ||
2866 | * from eeprom (eeprom.c) and interpolate here. | ||
2867 | * | ||
2868 | * For RF5112 we have 4 XPD -eXternal Power Detector- curves | ||
2869 | * for each calibrated channel on 0, -6, -12 and -18dBm but we only | ||
2870 | * use the higher (3) and the lower (0) curves. Each curve again has 0.5dB | ||
2871 | * power steps on x axis and PCDAC steps on y axis and looks like a | ||
2872 | * linear function. To recreate the curve and pass the power values | ||
2873 | * on hw, we get 4 points for xpd 0 (lower gain -> max power) | ||
2874 | * and 3 points for xpd 3 (higher gain -> lower power) from eeprom (eeprom.c) | ||
2875 | * and interpolate here. | ||
2876 | * | ||
2877 | * For a given channel we get the calibrated points (piers) for it or | ||
2878 | * -if we don't have calibration data for this specific channel- from the | ||
2879 | * available surrounding channels we have calibration data for, after we do a | ||
2880 | * linear interpolation between them. Then since we have our calibrated points | ||
2881 | * for this channel, we do again a linear interpolation between them to get the | ||
2882 | * whole curve. | ||
2883 | * | ||
2884 | * We finally write the Y values of the curve(s) (the PCDAC values) on hw | ||
2885 | */ | ||
2886 | |||
2887 | /** | ||
2888 | * ath5k_fill_pwr_to_pcdac_table() - Fill Power to PCDAC table on RF5111 | ||
2889 | * @ah: The &struct ath5k_hw | ||
2890 | * @table_min: Minimum power (x min) | ||
2891 | * @table_max: Maximum power (x max) | ||
2466 | * | 2892 | * |
2467 | * No further processing is needed for RF5111, the only thing we have to | 2893 | * No further processing is needed for RF5111, the only thing we have to |
2468 | * do is fill the values below and above calibration range since eeprom data | 2894 | * do is fill the values below and above calibration range since eeprom data |
@@ -2503,10 +2929,14 @@ ath5k_fill_pwr_to_pcdac_table(struct ath5k_hw *ah, s16* table_min, | |||
2503 | 2929 | ||
2504 | } | 2930 | } |
2505 | 2931 | ||
2506 | /* | 2932 | /** |
2507 | * Combine available XPD Curves and fill Linear Power to PCDAC table | 2933 | * ath5k_combine_linear_pcdac_curves() - Combine available PCDAC Curves |
2508 | * on RF5112 | 2934 | * @ah: The &struct ath5k_hw |
2935 | * @table_min: Minimum power (x min) | ||
2936 | * @table_max: Maximum power (x max) | ||
2937 | * @pdcurves: Number of pd curves | ||
2509 | * | 2938 | * |
2939 | * Combine available XPD Curves and fill Linear Power to PCDAC table on RF5112 | ||
2510 | * RFX112 can have up to 2 curves (one for low txpower range and one for | 2940 | * RFX112 can have up to 2 curves (one for low txpower range and one for |
2511 | * higher txpower range). We need to put them both on pcdac_out and place | 2941 | * higher txpower range). We need to put them both on pcdac_out and place |
2512 | * them in the correct location. In case we only have one curve available | 2942 | * them in the correct location. In case we only have one curve available |
@@ -2608,7 +3038,10 @@ ath5k_combine_linear_pcdac_curves(struct ath5k_hw *ah, s16* table_min, | |||
2608 | } | 3038 | } |
2609 | } | 3039 | } |
2610 | 3040 | ||
2611 | /* Write PCDAC values on hw */ | 3041 | /** |
3042 | * ath5k_write_pcdac_table() - Write the PCDAC values on hw | ||
3043 | * @ah: The &struct ath5k_hw | ||
3044 | */ | ||
2612 | static void | 3045 | static void |
2613 | ath5k_write_pcdac_table(struct ath5k_hw *ah) | 3046 | ath5k_write_pcdac_table(struct ath5k_hw *ah) |
2614 | { | 3047 | { |
@@ -2631,9 +3064,32 @@ ath5k_write_pcdac_table(struct ath5k_hw *ah) | |||
2631 | * Power to PDADC table functions | 3064 | * Power to PDADC table functions |
2632 | */ | 3065 | */ |
2633 | 3066 | ||
2634 | /* | 3067 | /** |
2635 | * Set the gain boundaries and create final Power to PDADC table | 3068 | * DOC: Power to PDADC table functions |
3069 | * | ||
3070 | * For RF2413 and later we have a Power to PDADC table (Power Detector) | ||
3071 | * instead of a PCDAC (Power Control) and 4 pd gain curves for each | ||
3072 | * calibrated channel. Each curve has power on x axis in 0.5 db steps and | ||
3073 | * PDADC steps on y axis and looks like an exponential function like the | ||
3074 | * RF5111 curve. | ||
3075 | * | ||
3076 | * To recreate the curves we read the points from eeprom (eeprom.c) | ||
3077 | * and interpolate here. Note that in most cases only 2 (higher and lower) | ||
3078 | * curves are used (like RF5112) but vendors have the opportunity to include | ||
3079 | * all 4 curves on eeprom. The final curve (higher power) has an extra | ||
3080 | * point for better accuracy like RF5112. | ||
2636 | * | 3081 | * |
3082 | * The process is similar to what we do above for RF5111/5112 | ||
3083 | */ | ||
3084 | |||
3085 | /** | ||
3086 | * ath5k_combine_pwr_to_pdadc_curves() - Combine the various PDADC curves | ||
3087 | * @ah: The &struct ath5k_hw | ||
3088 | * @pwr_min: Minimum power (x min) | ||
3089 | * @pwr_max: Maximum power (x max) | ||
3090 | * @pdcurves: Number of available curves | ||
3091 | * | ||
3092 | * Combine the various pd curves and create the final Power to PDADC table | ||
2637 | * We can have up to 4 pd curves, we need to do a similar process | 3093 | * We can have up to 4 pd curves, we need to do a similar process |
2638 | * as we do for RF5112. This time we don't have an edge_flag but we | 3094 | * as we do for RF5112. This time we don't have an edge_flag but we |
2639 | * set the gain boundaries on a separate register. | 3095 | * set the gain boundaries on a separate register. |
@@ -2757,7 +3213,11 @@ ath5k_combine_pwr_to_pdadc_curves(struct ath5k_hw *ah, | |||
2757 | 3213 | ||
2758 | } | 3214 | } |
2759 | 3215 | ||
2760 | /* Write PDADC values on hw */ | 3216 | /** |
3217 | * ath5k_write_pwr_to_pdadc_table() - Write the PDADC values on hw | ||
3218 | * @ah: The &struct ath5k_hw | ||
3219 | * @ee_mode: One of enum ath5k_driver_mode | ||
3220 | */ | ||
2761 | static void | 3221 | static void |
2762 | ath5k_write_pwr_to_pdadc_table(struct ath5k_hw *ah, u8 ee_mode) | 3222 | ath5k_write_pwr_to_pdadc_table(struct ath5k_hw *ah, u8 ee_mode) |
2763 | { | 3223 | { |
@@ -2814,7 +3274,13 @@ ath5k_write_pwr_to_pdadc_table(struct ath5k_hw *ah, u8 ee_mode) | |||
2814 | * Common code for PCDAC/PDADC tables | 3274 | * Common code for PCDAC/PDADC tables |
2815 | */ | 3275 | */ |
2816 | 3276 | ||
2817 | /* | 3277 | /** |
3278 | * ath5k_setup_channel_powertable() - Set up power table for this channel | ||
3279 | * @ah: The &struct ath5k_hw | ||
3280 | * @channel: The &struct ieee80211_channel | ||
3281 | * @ee_mode: One of enum ath5k_driver_mode | ||
3282 | * @type: One of enum ath5k_powertable_type (eeprom.h) | ||
3283 | * | ||
2818 | * This is the main function that uses all of the above | 3284 | * This is the main function that uses all of the above |
2819 | * to set PCDAC/PDADC table on hw for the current channel. | 3285 | * to set PCDAC/PDADC table on hw for the current channel. |
2820 | * This table is used for tx power calibration on the baseband, | 3286 | * This table is used for tx power calibration on the baseband, |
@@ -3012,7 +3478,12 @@ ath5k_setup_channel_powertable(struct ath5k_hw *ah, | |||
3012 | return 0; | 3478 | return 0; |
3013 | } | 3479 | } |
3014 | 3480 | ||
3015 | /* Write power table for current channel to hw */ | 3481 | /** |
3482 | * ath5k_write_channel_powertable() - Set power table for current channel on hw | ||
3483 | * @ah: The &struct ath5k_hw | ||
3484 | * @ee_mode: One of enum ath5k_driver_mode | ||
3485 | * @type: One of enum ath5k_powertable_type (eeprom.h) | ||
3486 | */ | ||
3016 | static void | 3487 | static void |
3017 | ath5k_write_channel_powertable(struct ath5k_hw *ah, u8 ee_mode, u8 type) | 3488 | ath5k_write_channel_powertable(struct ath5k_hw *ah, u8 ee_mode, u8 type) |
3018 | { | 3489 | { |
@@ -3022,28 +3493,36 @@ ath5k_write_channel_powertable(struct ath5k_hw *ah, u8 ee_mode, u8 type) | |||
3022 | ath5k_write_pcdac_table(ah); | 3493 | ath5k_write_pcdac_table(ah); |
3023 | } | 3494 | } |
3024 | 3495 | ||
3025 | /* | 3496 | |
3026 | * Per-rate tx power setting | 3497 | /** |
3498 | * DOC: Per-rate tx power setting | ||
3027 | * | 3499 | * |
3028 | * This is the code that sets the desired tx power (below | 3500 | * This is the code that sets the desired tx power limit (below |
3029 | * maximum) on hw for each rate (we also have TPC that sets | 3501 | * maximum) on hw for each rate (we also have TPC that sets |
3030 | * power per packet). We do that by providing an index on the | 3502 | * power per packet type). We do that by providing an index on the |
3031 | * PCDAC/PDADC table we set up. | 3503 | * PCDAC/PDADC table we set up above, for each rate. |
3032 | */ | ||
3033 | |||
3034 | /* | ||
3035 | * Set rate power table | ||
3036 | * | 3504 | * |
3037 | * For now we only limit txpower based on maximum tx power | 3505 | * For now we only limit txpower based on maximum tx power |
3038 | * supported by hw (what's inside rate_info). We need to limit | 3506 | * supported by hw (what's inside rate_info) + conformance test |
3039 | * this even more, based on regulatory domain etc. | 3507 | * limits. We need to limit this even more, based on regulatory domain |
3508 | * etc to be safe. Normally this is done from above so we don't care | ||
3509 | * here, all we care is that the tx power we set will be O.K. | ||
3510 | * for the hw (e.g. won't create noise on PA etc). | ||
3040 | * | 3511 | * |
3041 | * Rate power table contains indices to PCDAC/PDADC table (0.5dB steps) | 3512 | * Rate power table contains indices to PCDAC/PDADC table (0.5dB steps - |
3042 | * and is indexed as follows: | 3513 | * x values) and is indexed as follows: |
3043 | * rates[0] - rates[7] -> OFDM rates | 3514 | * rates[0] - rates[7] -> OFDM rates |
3044 | * rates[8] - rates[14] -> CCK rates | 3515 | * rates[8] - rates[14] -> CCK rates |
3045 | * rates[15] -> XR rates (they all have the same power) | 3516 | * rates[15] -> XR rates (they all have the same power) |
3046 | */ | 3517 | */ |
3518 | |||
3519 | /** | ||
3520 | * ath5k_setup_rate_powertable() - Set up rate power table for a given tx power | ||
3521 | * @ah: The &struct ath5k_hw | ||
3522 | * @max_pwr: The maximum tx power requested in 0.5dB steps | ||
3523 | * @rate_info: The &struct ath5k_rate_pcal_info to fill | ||
3524 | * @ee_mode: One of enum ath5k_driver_mode | ||
3525 | */ | ||
3047 | static void | 3526 | static void |
3048 | ath5k_setup_rate_powertable(struct ath5k_hw *ah, u16 max_pwr, | 3527 | ath5k_setup_rate_powertable(struct ath5k_hw *ah, u16 max_pwr, |
3049 | struct ath5k_rate_pcal_info *rate_info, | 3528 | struct ath5k_rate_pcal_info *rate_info, |
@@ -3114,8 +3593,14 @@ ath5k_setup_rate_powertable(struct ath5k_hw *ah, u16 max_pwr, | |||
3114 | } | 3593 | } |
3115 | 3594 | ||
3116 | 3595 | ||
3117 | /* | 3596 | /** |
3118 | * Set transmission power | 3597 | * ath5k_hw_txpower() - Set transmission power limit for a given channel |
3598 | * @ah: The &struct ath5k_hw | ||
3599 | * @channel: The &struct ieee80211_channel | ||
3600 | * @txpower: Requested tx power in 0.5dB steps | ||
3601 | * | ||
3602 | * Combines all of the above to set the requested tx power limit | ||
3603 | * on hw. | ||
3119 | */ | 3604 | */ |
3120 | static int | 3605 | static int |
3121 | ath5k_hw_txpower(struct ath5k_hw *ah, struct ieee80211_channel *channel, | 3606 | ath5k_hw_txpower(struct ath5k_hw *ah, struct ieee80211_channel *channel, |
@@ -3233,7 +3718,16 @@ ath5k_hw_txpower(struct ath5k_hw *ah, struct ieee80211_channel *channel, | |||
3233 | return 0; | 3718 | return 0; |
3234 | } | 3719 | } |
3235 | 3720 | ||
3236 | int ath5k_hw_set_txpower_limit(struct ath5k_hw *ah, u8 txpower) | 3721 | /** |
3722 | * ath5k_hw_set_txpower_limit() - Set txpower limit for the current channel | ||
3723 | * @ah: The &struct ath5k_hw | ||
3724 | * @txpower: The requested tx power limit in 0.5dB steps | ||
3725 | * | ||
3726 | * This function provides access to ath5k_hw_txpower to the driver in | ||
3727 | * case user or an application changes it while PHY is running. | ||
3728 | */ | ||
3729 | int | ||
3730 | ath5k_hw_set_txpower_limit(struct ath5k_hw *ah, u8 txpower) | ||
3237 | { | 3731 | { |
3238 | ATH5K_DBG(ah, ATH5K_DEBUG_TXPOWER, | 3732 | ATH5K_DBG(ah, ATH5K_DEBUG_TXPOWER, |
3239 | "changing txpower to %d\n", txpower); | 3733 | "changing txpower to %d\n", txpower); |
@@ -3241,11 +3735,26 @@ int ath5k_hw_set_txpower_limit(struct ath5k_hw *ah, u8 txpower) | |||
3241 | return ath5k_hw_txpower(ah, ah->ah_current_channel, txpower); | 3735 | return ath5k_hw_txpower(ah, ah->ah_current_channel, txpower); |
3242 | } | 3736 | } |
3243 | 3737 | ||
3738 | |||
3244 | /*************\ | 3739 | /*************\ |
3245 | Init function | 3740 | Init function |
3246 | \*************/ | 3741 | \*************/ |
3247 | 3742 | ||
3248 | int ath5k_hw_phy_init(struct ath5k_hw *ah, struct ieee80211_channel *channel, | 3743 | /** |
3744 | * ath5k_hw_phy_init() - Initialize PHY | ||
3745 | * @ah: The &struct ath5k_hw | ||
3746 | * @channel: The @struct ieee80211_channel | ||
3747 | * @mode: One of enum ath5k_driver_mode | ||
3748 | * @fast: Try a fast channel switch instead | ||
3749 | * | ||
3750 | * This is the main function used during reset to initialize PHY | ||
3751 | * or do a fast channel change if possible. | ||
3752 | * | ||
3753 | * NOTE: Do not call this one from the driver, it assumes PHY is in a | ||
3754 | * warm reset state ! | ||
3755 | */ | ||
3756 | int | ||
3757 | ath5k_hw_phy_init(struct ath5k_hw *ah, struct ieee80211_channel *channel, | ||
3249 | u8 mode, bool fast) | 3758 | u8 mode, bool fast) |
3250 | { | 3759 | { |
3251 | struct ieee80211_channel *curr_channel; | 3760 | struct ieee80211_channel *curr_channel; |
@@ -3355,7 +3864,7 @@ int ath5k_hw_phy_init(struct ath5k_hw *ah, struct ieee80211_channel *channel, | |||
3355 | if (ret) | 3864 | if (ret) |
3356 | return ret; | 3865 | return ret; |
3357 | 3866 | ||
3358 | mdelay(1); | 3867 | usleep_range(1000, 1500); |
3359 | 3868 | ||
3360 | /* | 3869 | /* |
3361 | * Write RF buffer | 3870 | * Write RF buffer |
@@ -3376,10 +3885,10 @@ int ath5k_hw_phy_init(struct ath5k_hw *ah, struct ieee80211_channel *channel, | |||
3376 | } | 3885 | } |
3377 | 3886 | ||
3378 | } else if (ah->ah_version == AR5K_AR5210) { | 3887 | } else if (ah->ah_version == AR5K_AR5210) { |
3379 | mdelay(1); | 3888 | usleep_range(1000, 1500); |
3380 | /* Disable phy and wait */ | 3889 | /* Disable phy and wait */ |
3381 | ath5k_hw_reg_write(ah, AR5K_PHY_ACT_DISABLE, AR5K_PHY_ACT); | 3890 | ath5k_hw_reg_write(ah, AR5K_PHY_ACT_DISABLE, AR5K_PHY_ACT); |
3382 | mdelay(1); | 3891 | usleep_range(1000, 1500); |
3383 | } | 3892 | } |
3384 | 3893 | ||
3385 | /* Set channel on PHY */ | 3894 | /* Set channel on PHY */ |
@@ -3405,7 +3914,7 @@ int ath5k_hw_phy_init(struct ath5k_hw *ah, struct ieee80211_channel *channel, | |||
3405 | for (i = 0; i <= 20; i++) { | 3914 | for (i = 0; i <= 20; i++) { |
3406 | if (!(ath5k_hw_reg_read(ah, AR5K_PHY_ADC_TEST) & 0x10)) | 3915 | if (!(ath5k_hw_reg_read(ah, AR5K_PHY_ADC_TEST) & 0x10)) |
3407 | break; | 3916 | break; |
3408 | udelay(200); | 3917 | usleep_range(200, 250); |
3409 | } | 3918 | } |
3410 | ath5k_hw_reg_write(ah, phy_tst1, AR5K_PHY_TST1); | 3919 | ath5k_hw_reg_write(ah, phy_tst1, AR5K_PHY_TST1); |
3411 | 3920 | ||
@@ -3433,9 +3942,9 @@ int ath5k_hw_phy_init(struct ath5k_hw *ah, struct ieee80211_channel *channel, | |||
3433 | 3942 | ||
3434 | /* At the same time start I/Q calibration for QAM constellation | 3943 | /* At the same time start I/Q calibration for QAM constellation |
3435 | * -no need for CCK- */ | 3944 | * -no need for CCK- */ |
3436 | ah->ah_calibration = false; | 3945 | ah->ah_iq_cal_needed = false; |
3437 | if (!(mode == AR5K_MODE_11B)) { | 3946 | if (!(mode == AR5K_MODE_11B)) { |
3438 | ah->ah_calibration = true; | 3947 | ah->ah_iq_cal_needed = true; |
3439 | AR5K_REG_WRITE_BITS(ah, AR5K_PHY_IQ, | 3948 | AR5K_REG_WRITE_BITS(ah, AR5K_PHY_IQ, |
3440 | AR5K_PHY_IQ_CAL_NUM_LOG_MAX, 15); | 3949 | AR5K_PHY_IQ_CAL_NUM_LOG_MAX, 15); |
3441 | AR5K_REG_ENABLE_BITS(ah, AR5K_PHY_IQ, | 3950 | AR5K_REG_ENABLE_BITS(ah, AR5K_PHY_IQ, |
diff --git a/drivers/net/wireless/ath/ath5k/qcu.c b/drivers/net/wireless/ath/ath5k/qcu.c index 776654228eaa..30b50f934172 100644 --- a/drivers/net/wireless/ath/ath5k/qcu.c +++ b/drivers/net/wireless/ath/ath5k/qcu.c | |||
@@ -17,23 +17,48 @@ | |||
17 | */ | 17 | */ |
18 | 18 | ||
19 | /********************************************\ | 19 | /********************************************\ |
20 | Queue Control Unit, DFS Control Unit Functions | 20 | Queue Control Unit, DCF Control Unit Functions |
21 | \********************************************/ | 21 | \********************************************/ |
22 | 22 | ||
23 | #include "ath5k.h" | 23 | #include "ath5k.h" |
24 | #include "reg.h" | 24 | #include "reg.h" |
25 | #include "debug.h" | 25 | #include "debug.h" |
26 | #include <linux/log2.h> | ||
27 | |||
28 | /** | ||
29 | * DOC: Queue Control Unit (QCU)/DCF Control Unit (DCU) functions | ||
30 | * | ||
31 | * Here we setup parameters for the 12 available TX queues. Note that | ||
32 | * on the various registers we can usually only map the first 10 of them so | ||
33 | * basically we have 10 queues to play with. Each queue has a matching | ||
34 | * QCU that controls when the queue will get triggered and multiple QCUs | ||
35 | * can be mapped to a single DCU that controls the various DFS parameters | ||
36 | * for the various queues. In our setup we have a 1:1 mapping between QCUs | ||
37 | * and DCUs allowing us to have different DFS settings for each queue. | ||
38 | * | ||
39 | * When a frame goes into a TX queue, QCU decides when it'll trigger a | ||
40 | * transmission based on various criteria (such as how many data we have inside | ||
41 | * it's buffer or -if it's a beacon queue- if it's time to fire up the queue | ||
42 | * based on TSF etc), DCU adds backoff, IFSes etc and then a scheduler | ||
43 | * (arbitrator) decides the priority of each QCU based on it's configuration | ||
44 | * (e.g. beacons are always transmitted when they leave DCU bypassing all other | ||
45 | * frames from other queues waiting to be transmitted). After a frame leaves | ||
46 | * the DCU it goes to PCU for further processing and then to PHY for | ||
47 | * the actual transmission. | ||
48 | */ | ||
26 | 49 | ||
27 | 50 | ||
28 | /******************\ | 51 | /******************\ |
29 | * Helper functions * | 52 | * Helper functions * |
30 | \******************/ | 53 | \******************/ |
31 | 54 | ||
32 | /* | 55 | /** |
33 | * Get number of pending frames | 56 | * ath5k_hw_num_tx_pending() - Get number of pending frames for a given queue |
34 | * for a specific queue [5211+] | 57 | * @ah: The &struct ath5k_hw |
58 | * @queue: One of enum ath5k_tx_queue_id | ||
35 | */ | 59 | */ |
36 | u32 ath5k_hw_num_tx_pending(struct ath5k_hw *ah, unsigned int queue) | 60 | u32 |
61 | ath5k_hw_num_tx_pending(struct ath5k_hw *ah, unsigned int queue) | ||
37 | { | 62 | { |
38 | u32 pending; | 63 | u32 pending; |
39 | AR5K_ASSERT_ENTRY(queue, ah->ah_capabilities.cap_queues.q_tx_num); | 64 | AR5K_ASSERT_ENTRY(queue, ah->ah_capabilities.cap_queues.q_tx_num); |
@@ -58,10 +83,13 @@ u32 ath5k_hw_num_tx_pending(struct ath5k_hw *ah, unsigned int queue) | |||
58 | return pending; | 83 | return pending; |
59 | } | 84 | } |
60 | 85 | ||
61 | /* | 86 | /** |
62 | * Set a transmit queue inactive | 87 | * ath5k_hw_release_tx_queue() - Set a transmit queue inactive |
88 | * @ah: The &struct ath5k_hw | ||
89 | * @queue: One of enum ath5k_tx_queue_id | ||
63 | */ | 90 | */ |
64 | void ath5k_hw_release_tx_queue(struct ath5k_hw *ah, unsigned int queue) | 91 | void |
92 | ath5k_hw_release_tx_queue(struct ath5k_hw *ah, unsigned int queue) | ||
65 | { | 93 | { |
66 | if (WARN_ON(queue >= ah->ah_capabilities.cap_queues.q_tx_num)) | 94 | if (WARN_ON(queue >= ah->ah_capabilities.cap_queues.q_tx_num)) |
67 | return; | 95 | return; |
@@ -72,34 +100,56 @@ void ath5k_hw_release_tx_queue(struct ath5k_hw *ah, unsigned int queue) | |||
72 | AR5K_Q_DISABLE_BITS(ah->ah_txq_status, queue); | 100 | AR5K_Q_DISABLE_BITS(ah->ah_txq_status, queue); |
73 | } | 101 | } |
74 | 102 | ||
75 | /* | 103 | /** |
104 | * ath5k_cw_validate() - Make sure the given cw is valid | ||
105 | * @cw_req: The contention window value to check | ||
106 | * | ||
76 | * Make sure cw is a power of 2 minus 1 and smaller than 1024 | 107 | * Make sure cw is a power of 2 minus 1 and smaller than 1024 |
77 | */ | 108 | */ |
78 | static u16 ath5k_cw_validate(u16 cw_req) | 109 | static u16 |
110 | ath5k_cw_validate(u16 cw_req) | ||
79 | { | 111 | { |
80 | u32 cw = 1; | ||
81 | cw_req = min(cw_req, (u16)1023); | 112 | cw_req = min(cw_req, (u16)1023); |
82 | 113 | ||
83 | while (cw < cw_req) | 114 | /* Check if cw_req + 1 a power of 2 */ |
84 | cw = (cw << 1) | 1; | 115 | if (is_power_of_2(cw_req + 1)) |
116 | return cw_req; | ||
85 | 117 | ||
86 | return cw; | 118 | /* Check if cw_req is a power of 2 */ |
119 | if (is_power_of_2(cw_req)) | ||
120 | return cw_req - 1; | ||
121 | |||
122 | /* If none of the above is correct | ||
123 | * find the closest power of 2 */ | ||
124 | cw_req = (u16) roundup_pow_of_two(cw_req) - 1; | ||
125 | |||
126 | return cw_req; | ||
87 | } | 127 | } |
88 | 128 | ||
89 | /* | 129 | /** |
90 | * Get properties for a transmit queue | 130 | * ath5k_hw_get_tx_queueprops() - Get properties for a transmit queue |
131 | * @ah: The &struct ath5k_hw | ||
132 | * @queue: One of enum ath5k_tx_queue_id | ||
133 | * @queue_info: The &struct ath5k_txq_info to fill | ||
91 | */ | 134 | */ |
92 | int ath5k_hw_get_tx_queueprops(struct ath5k_hw *ah, int queue, | 135 | int |
136 | ath5k_hw_get_tx_queueprops(struct ath5k_hw *ah, int queue, | ||
93 | struct ath5k_txq_info *queue_info) | 137 | struct ath5k_txq_info *queue_info) |
94 | { | 138 | { |
95 | memcpy(queue_info, &ah->ah_txq[queue], sizeof(struct ath5k_txq_info)); | 139 | memcpy(queue_info, &ah->ah_txq[queue], sizeof(struct ath5k_txq_info)); |
96 | return 0; | 140 | return 0; |
97 | } | 141 | } |
98 | 142 | ||
99 | /* | 143 | /** |
100 | * Set properties for a transmit queue | 144 | * ath5k_hw_set_tx_queueprops() - Set properties for a transmit queue |
145 | * @ah: The &struct ath5k_hw | ||
146 | * @queue: One of enum ath5k_tx_queue_id | ||
147 | * @qinfo: The &struct ath5k_txq_info to use | ||
148 | * | ||
149 | * Returns 0 on success or -EIO if queue is inactive | ||
101 | */ | 150 | */ |
102 | int ath5k_hw_set_tx_queueprops(struct ath5k_hw *ah, int queue, | 151 | int |
152 | ath5k_hw_set_tx_queueprops(struct ath5k_hw *ah, int queue, | ||
103 | const struct ath5k_txq_info *qinfo) | 153 | const struct ath5k_txq_info *qinfo) |
104 | { | 154 | { |
105 | struct ath5k_txq_info *qi; | 155 | struct ath5k_txq_info *qi; |
@@ -139,10 +189,16 @@ int ath5k_hw_set_tx_queueprops(struct ath5k_hw *ah, int queue, | |||
139 | return 0; | 189 | return 0; |
140 | } | 190 | } |
141 | 191 | ||
142 | /* | 192 | /** |
143 | * Initialize a transmit queue | 193 | * ath5k_hw_setup_tx_queue() - Initialize a transmit queue |
194 | * @ah: The &struct ath5k_hw | ||
195 | * @queue_type: One of enum ath5k_tx_queue | ||
196 | * @queue_info: The &struct ath5k_txq_info to use | ||
197 | * | ||
198 | * Returns 0 on success, -EINVAL on invalid arguments | ||
144 | */ | 199 | */ |
145 | int ath5k_hw_setup_tx_queue(struct ath5k_hw *ah, enum ath5k_tx_queue queue_type, | 200 | int |
201 | ath5k_hw_setup_tx_queue(struct ath5k_hw *ah, enum ath5k_tx_queue queue_type, | ||
146 | struct ath5k_txq_info *queue_info) | 202 | struct ath5k_txq_info *queue_info) |
147 | { | 203 | { |
148 | unsigned int queue; | 204 | unsigned int queue; |
@@ -217,10 +273,16 @@ int ath5k_hw_setup_tx_queue(struct ath5k_hw *ah, enum ath5k_tx_queue queue_type, | |||
217 | * Single QCU/DCU initialization * | 273 | * Single QCU/DCU initialization * |
218 | \*******************************/ | 274 | \*******************************/ |
219 | 275 | ||
220 | /* | 276 | /** |
221 | * Set tx retry limits on DCU | 277 | * ath5k_hw_set_tx_retry_limits() - Set tx retry limits on DCU |
278 | * @ah: The &struct ath5k_hw | ||
279 | * @queue: One of enum ath5k_tx_queue_id | ||
280 | * | ||
281 | * This function is used when initializing a queue, to set | ||
282 | * retry limits based on ah->ah_retry_* and the chipset used. | ||
222 | */ | 283 | */ |
223 | void ath5k_hw_set_tx_retry_limits(struct ath5k_hw *ah, | 284 | void |
285 | ath5k_hw_set_tx_retry_limits(struct ath5k_hw *ah, | ||
224 | unsigned int queue) | 286 | unsigned int queue) |
225 | { | 287 | { |
226 | /* Single data queue on AR5210 */ | 288 | /* Single data queue on AR5210 */ |
@@ -255,15 +317,15 @@ void ath5k_hw_set_tx_retry_limits(struct ath5k_hw *ah, | |||
255 | } | 317 | } |
256 | 318 | ||
257 | /** | 319 | /** |
258 | * ath5k_hw_reset_tx_queue - Initialize a single hw queue | 320 | * ath5k_hw_reset_tx_queue() - Initialize a single hw queue |
321 | * @ah: The &struct ath5k_hw | ||
322 | * @queue: One of enum ath5k_tx_queue_id | ||
259 | * | 323 | * |
260 | * @ah The &struct ath5k_hw | 324 | * Set DCF properties for the given transmit queue on DCU |
261 | * @queue The hw queue number | ||
262 | * | ||
263 | * Set DFS properties for the given transmit queue on DCU | ||
264 | * and configures all queue-specific parameters. | 325 | * and configures all queue-specific parameters. |
265 | */ | 326 | */ |
266 | int ath5k_hw_reset_tx_queue(struct ath5k_hw *ah, unsigned int queue) | 327 | int |
328 | ath5k_hw_reset_tx_queue(struct ath5k_hw *ah, unsigned int queue) | ||
267 | { | 329 | { |
268 | struct ath5k_txq_info *tq = &ah->ah_txq[queue]; | 330 | struct ath5k_txq_info *tq = &ah->ah_txq[queue]; |
269 | 331 | ||
@@ -491,10 +553,9 @@ int ath5k_hw_reset_tx_queue(struct ath5k_hw *ah, unsigned int queue) | |||
491 | \**************************/ | 553 | \**************************/ |
492 | 554 | ||
493 | /** | 555 | /** |
494 | * ath5k_hw_set_ifs_intervals - Set global inter-frame spaces on DCU | 556 | * ath5k_hw_set_ifs_intervals() - Set global inter-frame spaces on DCU |
495 | * | 557 | * @ah: The &struct ath5k_hw |
496 | * @ah The &struct ath5k_hw | 558 | * @slot_time: Slot time in us |
497 | * @slot_time Slot time in us | ||
498 | * | 559 | * |
499 | * Sets the global IFS intervals on DCU (also works on AR5210) for | 560 | * Sets the global IFS intervals on DCU (also works on AR5210) for |
500 | * the given slot time and the current bwmode. | 561 | * the given slot time and the current bwmode. |
@@ -597,7 +658,15 @@ int ath5k_hw_set_ifs_intervals(struct ath5k_hw *ah, unsigned int slot_time) | |||
597 | } | 658 | } |
598 | 659 | ||
599 | 660 | ||
600 | int ath5k_hw_init_queues(struct ath5k_hw *ah) | 661 | /** |
662 | * ath5k_hw_init_queues() - Initialize tx queues | ||
663 | * @ah: The &struct ath5k_hw | ||
664 | * | ||
665 | * Initializes all tx queues based on information on | ||
666 | * ah->ah_txq* set by the driver | ||
667 | */ | ||
668 | int | ||
669 | ath5k_hw_init_queues(struct ath5k_hw *ah) | ||
601 | { | 670 | { |
602 | int i, ret; | 671 | int i, ret; |
603 | 672 | ||
diff --git a/drivers/net/wireless/ath/ath5k/reg.h b/drivers/net/wireless/ath/ath5k/reg.h index f5c1000045d3..0ea1608b47fd 100644 --- a/drivers/net/wireless/ath/ath5k/reg.h +++ b/drivers/net/wireless/ath/ath5k/reg.h | |||
@@ -280,6 +280,10 @@ | |||
280 | * 5211/5212 we have one primary and 4 secondary registers. | 280 | * 5211/5212 we have one primary and 4 secondary registers. |
281 | * So we have AR5K_ISR for 5210 and AR5K_PISR /SISRx for 5211/5212. | 281 | * So we have AR5K_ISR for 5210 and AR5K_PISR /SISRx for 5211/5212. |
282 | * Most of these bits are common for all chipsets. | 282 | * Most of these bits are common for all chipsets. |
283 | * | ||
284 | * NOTE: On 5211+ TXOK, TXDESC, TXERR, TXEOL and TXURN contain | ||
285 | * the logical OR from per-queue interrupt bits found on SISR registers | ||
286 | * (see below). | ||
283 | */ | 287 | */ |
284 | #define AR5K_ISR 0x001c /* Register Address [5210] */ | 288 | #define AR5K_ISR 0x001c /* Register Address [5210] */ |
285 | #define AR5K_PISR 0x0080 /* Register Address [5211+] */ | 289 | #define AR5K_PISR 0x0080 /* Register Address [5211+] */ |
@@ -292,7 +296,10 @@ | |||
292 | #define AR5K_ISR_TXOK 0x00000040 /* Frame successfully transmitted */ | 296 | #define AR5K_ISR_TXOK 0x00000040 /* Frame successfully transmitted */ |
293 | #define AR5K_ISR_TXDESC 0x00000080 /* TX descriptor request */ | 297 | #define AR5K_ISR_TXDESC 0x00000080 /* TX descriptor request */ |
294 | #define AR5K_ISR_TXERR 0x00000100 /* Transmit error */ | 298 | #define AR5K_ISR_TXERR 0x00000100 /* Transmit error */ |
295 | #define AR5K_ISR_TXNOFRM 0x00000200 /* No frame transmitted (transmit timeout) */ | 299 | #define AR5K_ISR_TXNOFRM 0x00000200 /* No frame transmitted (transmit timeout) |
300 | * NOTE: We don't have per-queue info for this | ||
301 | * one, but we can enable it per-queue through | ||
302 | * TXNOFRM_QCU field on TXNOFRM register */ | ||
296 | #define AR5K_ISR_TXEOL 0x00000400 /* Empty TX descriptor */ | 303 | #define AR5K_ISR_TXEOL 0x00000400 /* Empty TX descriptor */ |
297 | #define AR5K_ISR_TXURN 0x00000800 /* Transmit FIFO underrun */ | 304 | #define AR5K_ISR_TXURN 0x00000800 /* Transmit FIFO underrun */ |
298 | #define AR5K_ISR_MIB 0x00001000 /* Update MIB counters */ | 305 | #define AR5K_ISR_MIB 0x00001000 /* Update MIB counters */ |
@@ -302,21 +309,29 @@ | |||
302 | #define AR5K_ISR_SWBA 0x00010000 /* Software beacon alert */ | 309 | #define AR5K_ISR_SWBA 0x00010000 /* Software beacon alert */ |
303 | #define AR5K_ISR_BRSSI 0x00020000 /* Beacon rssi below threshold (?) */ | 310 | #define AR5K_ISR_BRSSI 0x00020000 /* Beacon rssi below threshold (?) */ |
304 | #define AR5K_ISR_BMISS 0x00040000 /* Beacon missed */ | 311 | #define AR5K_ISR_BMISS 0x00040000 /* Beacon missed */ |
305 | #define AR5K_ISR_HIUERR 0x00080000 /* Host Interface Unit error [5211+] */ | 312 | #define AR5K_ISR_HIUERR 0x00080000 /* Host Interface Unit error [5211+] |
313 | * 'or' of MCABT, SSERR, DPERR from SISR2 */ | ||
306 | #define AR5K_ISR_BNR 0x00100000 /* Beacon not ready [5211+] */ | 314 | #define AR5K_ISR_BNR 0x00100000 /* Beacon not ready [5211+] */ |
307 | #define AR5K_ISR_MCABT 0x00100000 /* Master Cycle Abort [5210] */ | 315 | #define AR5K_ISR_MCABT 0x00100000 /* Master Cycle Abort [5210] */ |
308 | #define AR5K_ISR_RXCHIRP 0x00200000 /* CHIRP Received [5212+] */ | 316 | #define AR5K_ISR_RXCHIRP 0x00200000 /* CHIRP Received [5212+] */ |
309 | #define AR5K_ISR_SSERR 0x00200000 /* Signaled System Error [5210] */ | 317 | #define AR5K_ISR_SSERR 0x00200000 /* Signaled System Error [5210] */ |
310 | #define AR5K_ISR_DPERR 0x00400000 /* Det par Error (?) [5210] */ | 318 | #define AR5K_ISR_DPERR 0x00400000 /* Bus parity error [5210] */ |
311 | #define AR5K_ISR_RXDOPPLER 0x00400000 /* Doppler chirp received [5212+] */ | 319 | #define AR5K_ISR_RXDOPPLER 0x00400000 /* Doppler chirp received [5212+] */ |
312 | #define AR5K_ISR_TIM 0x00800000 /* [5211+] */ | 320 | #define AR5K_ISR_TIM 0x00800000 /* [5211+] */ |
313 | #define AR5K_ISR_BCNMISC 0x00800000 /* 'or' of TIM, CAB_END, DTIM_SYNC, BCN_TIMEOUT, | 321 | #define AR5K_ISR_BCNMISC 0x00800000 /* Misc beacon related interrupt |
314 | CAB_TIMEOUT and DTIM bits from SISR2 [5212+] */ | 322 | * 'or' of TIM, CAB_END, DTIM_SYNC, BCN_TIMEOUT, |
323 | * CAB_TIMEOUT and DTIM bits from SISR2 [5212+] */ | ||
315 | #define AR5K_ISR_GPIO 0x01000000 /* GPIO (rf kill) */ | 324 | #define AR5K_ISR_GPIO 0x01000000 /* GPIO (rf kill) */ |
316 | #define AR5K_ISR_QCBRORN 0x02000000 /* QCU CBR overrun [5211+] */ | 325 | #define AR5K_ISR_QCBRORN 0x02000000 /* QCU CBR overrun [5211+] */ |
317 | #define AR5K_ISR_QCBRURN 0x04000000 /* QCU CBR underrun [5211+] */ | 326 | #define AR5K_ISR_QCBRURN 0x04000000 /* QCU CBR underrun [5211+] */ |
318 | #define AR5K_ISR_QTRIG 0x08000000 /* QCU scheduling trigger [5211+] */ | 327 | #define AR5K_ISR_QTRIG 0x08000000 /* QCU scheduling trigger [5211+] */ |
319 | 328 | ||
329 | #define AR5K_ISR_BITS_FROM_SISRS (AR5K_ISR_TXOK | AR5K_ISR_TXDESC |\ | ||
330 | AR5K_ISR_TXERR | AR5K_ISR_TXEOL |\ | ||
331 | AR5K_ISR_TXURN | AR5K_ISR_HIUERR |\ | ||
332 | AR5K_ISR_BCNMISC | AR5K_ISR_QCBRORN |\ | ||
333 | AR5K_ISR_QCBRURN | AR5K_ISR_QTRIG) | ||
334 | |||
320 | /* | 335 | /* |
321 | * Secondary status registers [5211+] (0 - 4) | 336 | * Secondary status registers [5211+] (0 - 4) |
322 | * | 337 | * |
@@ -347,7 +362,7 @@ | |||
347 | #define AR5K_SISR2_BCN_TIMEOUT 0x08000000 /* Beacon Timeout [5212+] */ | 362 | #define AR5K_SISR2_BCN_TIMEOUT 0x08000000 /* Beacon Timeout [5212+] */ |
348 | #define AR5K_SISR2_CAB_TIMEOUT 0x10000000 /* CAB Timeout [5212+] */ | 363 | #define AR5K_SISR2_CAB_TIMEOUT 0x10000000 /* CAB Timeout [5212+] */ |
349 | #define AR5K_SISR2_DTIM 0x20000000 /* [5212+] */ | 364 | #define AR5K_SISR2_DTIM 0x20000000 /* [5212+] */ |
350 | #define AR5K_SISR2_TSFOOR 0x80000000 /* TSF OOR (?) */ | 365 | #define AR5K_SISR2_TSFOOR 0x80000000 /* TSF Out of range */ |
351 | 366 | ||
352 | #define AR5K_SISR3 0x0090 /* Register Address [5211+] */ | 367 | #define AR5K_SISR3 0x0090 /* Register Address [5211+] */ |
353 | #define AR5K_SISR3_QCBRORN 0x000003ff /* Mask for QCBRORN */ | 368 | #define AR5K_SISR3_QCBRORN 0x000003ff /* Mask for QCBRORN */ |
diff --git a/drivers/net/wireless/ath/ath5k/reset.c b/drivers/net/wireless/ath/ath5k/reset.c index 2abac257b4b4..4aed3a3ab109 100644 --- a/drivers/net/wireless/ath/ath5k/reset.c +++ b/drivers/net/wireless/ath/ath5k/reset.c | |||
@@ -19,9 +19,9 @@ | |||
19 | * | 19 | * |
20 | */ | 20 | */ |
21 | 21 | ||
22 | /*****************************\ | 22 | /****************************\ |
23 | Reset functions and helpers | 23 | Reset function and helpers |
24 | \*****************************/ | 24 | \****************************/ |
25 | 25 | ||
26 | #include <asm/unaligned.h> | 26 | #include <asm/unaligned.h> |
27 | 27 | ||
@@ -33,14 +33,36 @@ | |||
33 | #include "debug.h" | 33 | #include "debug.h" |
34 | 34 | ||
35 | 35 | ||
36 | /** | ||
37 | * DOC: Reset function and helpers | ||
38 | * | ||
39 | * Here we implement the main reset routine, used to bring the card | ||
40 | * to a working state and ready to receive. We also handle routines | ||
41 | * that don't fit on other places such as clock, sleep and power control | ||
42 | */ | ||
43 | |||
44 | |||
36 | /******************\ | 45 | /******************\ |
37 | * Helper functions * | 46 | * Helper functions * |
38 | \******************/ | 47 | \******************/ |
39 | 48 | ||
40 | /* | 49 | /** |
41 | * Check if a register write has been completed | 50 | * ath5k_hw_register_timeout() - Poll a register for a flag/field change |
51 | * @ah: The &struct ath5k_hw | ||
52 | * @reg: The register to read | ||
53 | * @flag: The flag/field to check on the register | ||
54 | * @val: The field value we expect (if we check a field) | ||
55 | * @is_set: Instead of checking if the flag got cleared, check if it got set | ||
56 | * | ||
57 | * Some registers contain flags that indicate that an operation is | ||
58 | * running. We use this function to poll these registers and check | ||
59 | * if these flags get cleared. We also use it to poll a register | ||
60 | * field (containing multiple flags) until it gets a specific value. | ||
61 | * | ||
62 | * Returns -EAGAIN if we exceeded AR5K_TUNE_REGISTER_TIMEOUT * 15us or 0 | ||
42 | */ | 63 | */ |
43 | int ath5k_hw_register_timeout(struct ath5k_hw *ah, u32 reg, u32 flag, u32 val, | 64 | int |
65 | ath5k_hw_register_timeout(struct ath5k_hw *ah, u32 reg, u32 flag, u32 val, | ||
44 | bool is_set) | 66 | bool is_set) |
45 | { | 67 | { |
46 | int i; | 68 | int i; |
@@ -64,35 +86,48 @@ int ath5k_hw_register_timeout(struct ath5k_hw *ah, u32 reg, u32 flag, u32 val, | |||
64 | \*************************/ | 86 | \*************************/ |
65 | 87 | ||
66 | /** | 88 | /** |
67 | * ath5k_hw_htoclock - Translate usec to hw clock units | 89 | * ath5k_hw_htoclock() - Translate usec to hw clock units |
68 | * | ||
69 | * @ah: The &struct ath5k_hw | 90 | * @ah: The &struct ath5k_hw |
70 | * @usec: value in microseconds | 91 | * @usec: value in microseconds |
92 | * | ||
93 | * Translate usecs to hw clock units based on the current | ||
94 | * hw clock rate. | ||
95 | * | ||
96 | * Returns number of clock units | ||
71 | */ | 97 | */ |
72 | unsigned int ath5k_hw_htoclock(struct ath5k_hw *ah, unsigned int usec) | 98 | unsigned int |
99 | ath5k_hw_htoclock(struct ath5k_hw *ah, unsigned int usec) | ||
73 | { | 100 | { |
74 | struct ath_common *common = ath5k_hw_common(ah); | 101 | struct ath_common *common = ath5k_hw_common(ah); |
75 | return usec * common->clockrate; | 102 | return usec * common->clockrate; |
76 | } | 103 | } |
77 | 104 | ||
78 | /** | 105 | /** |
79 | * ath5k_hw_clocktoh - Translate hw clock units to usec | 106 | * ath5k_hw_clocktoh() - Translate hw clock units to usec |
107 | * @ah: The &struct ath5k_hw | ||
80 | * @clock: value in hw clock units | 108 | * @clock: value in hw clock units |
109 | * | ||
110 | * Translate hw clock units to usecs based on the current | ||
111 | * hw clock rate. | ||
112 | * | ||
113 | * Returns number of usecs | ||
81 | */ | 114 | */ |
82 | unsigned int ath5k_hw_clocktoh(struct ath5k_hw *ah, unsigned int clock) | 115 | unsigned int |
116 | ath5k_hw_clocktoh(struct ath5k_hw *ah, unsigned int clock) | ||
83 | { | 117 | { |
84 | struct ath_common *common = ath5k_hw_common(ah); | 118 | struct ath_common *common = ath5k_hw_common(ah); |
85 | return clock / common->clockrate; | 119 | return clock / common->clockrate; |
86 | } | 120 | } |
87 | 121 | ||
88 | /** | 122 | /** |
89 | * ath5k_hw_init_core_clock - Initialize core clock | 123 | * ath5k_hw_init_core_clock() - Initialize core clock |
90 | * | 124 | * @ah: The &struct ath5k_hw |
91 | * @ah The &struct ath5k_hw | ||
92 | * | 125 | * |
93 | * Initialize core clock parameters (usec, usec32, latencies etc). | 126 | * Initialize core clock parameters (usec, usec32, latencies etc), |
127 | * based on current bwmode and chipset properties. | ||
94 | */ | 128 | */ |
95 | static void ath5k_hw_init_core_clock(struct ath5k_hw *ah) | 129 | static void |
130 | ath5k_hw_init_core_clock(struct ath5k_hw *ah) | ||
96 | { | 131 | { |
97 | struct ieee80211_channel *channel = ah->ah_current_channel; | 132 | struct ieee80211_channel *channel = ah->ah_current_channel; |
98 | struct ath_common *common = ath5k_hw_common(ah); | 133 | struct ath_common *common = ath5k_hw_common(ah); |
@@ -227,16 +262,21 @@ static void ath5k_hw_init_core_clock(struct ath5k_hw *ah) | |||
227 | } | 262 | } |
228 | } | 263 | } |
229 | 264 | ||
230 | /* | 265 | /** |
266 | * ath5k_hw_set_sleep_clock() - Setup sleep clock operation | ||
267 | * @ah: The &struct ath5k_hw | ||
268 | * @enable: Enable sleep clock operation (false to disable) | ||
269 | * | ||
231 | * If there is an external 32KHz crystal available, use it | 270 | * If there is an external 32KHz crystal available, use it |
232 | * as ref. clock instead of 32/40MHz clock and baseband clocks | 271 | * as ref. clock instead of 32/40MHz clock and baseband clocks |
233 | * to save power during sleep or restore normal 32/40MHz | 272 | * to save power during sleep or restore normal 32/40MHz |
234 | * operation. | 273 | * operation. |
235 | * | 274 | * |
236 | * XXX: When operating on 32KHz certain PHY registers (27 - 31, | 275 | * NOTE: When operating on 32KHz certain PHY registers (27 - 31, |
237 | * 123 - 127) require delay on access. | 276 | * 123 - 127) require delay on access. |
238 | */ | 277 | */ |
239 | static void ath5k_hw_set_sleep_clock(struct ath5k_hw *ah, bool enable) | 278 | static void |
279 | ath5k_hw_set_sleep_clock(struct ath5k_hw *ah, bool enable) | ||
240 | { | 280 | { |
241 | struct ath5k_eeprom_info *ee = &ah->ah_capabilities.cap_eeprom; | 281 | struct ath5k_eeprom_info *ee = &ah->ah_capabilities.cap_eeprom; |
242 | u32 scal, spending, sclock; | 282 | u32 scal, spending, sclock; |
@@ -340,10 +380,19 @@ static void ath5k_hw_set_sleep_clock(struct ath5k_hw *ah, bool enable) | |||
340 | * Reset/Sleep control * | 380 | * Reset/Sleep control * |
341 | \*********************/ | 381 | \*********************/ |
342 | 382 | ||
343 | /* | 383 | /** |
344 | * Reset chipset | 384 | * ath5k_hw_nic_reset() - Reset the various chipset units |
385 | * @ah: The &struct ath5k_hw | ||
386 | * @val: Mask to indicate what units to reset | ||
387 | * | ||
388 | * To reset the various chipset units we need to write | ||
389 | * the mask to AR5K_RESET_CTL and poll the register until | ||
390 | * all flags are cleared. | ||
391 | * | ||
392 | * Returns 0 if we are O.K. or -EAGAIN (from athk5_hw_register_timeout) | ||
345 | */ | 393 | */ |
346 | static int ath5k_hw_nic_reset(struct ath5k_hw *ah, u32 val) | 394 | static int |
395 | ath5k_hw_nic_reset(struct ath5k_hw *ah, u32 val) | ||
347 | { | 396 | { |
348 | int ret; | 397 | int ret; |
349 | u32 mask = val ? val : ~0U; | 398 | u32 mask = val ? val : ~0U; |
@@ -357,7 +406,7 @@ static int ath5k_hw_nic_reset(struct ath5k_hw *ah, u32 val) | |||
357 | ath5k_hw_reg_write(ah, val, AR5K_RESET_CTL); | 406 | ath5k_hw_reg_write(ah, val, AR5K_RESET_CTL); |
358 | 407 | ||
359 | /* Wait at least 128 PCI clocks */ | 408 | /* Wait at least 128 PCI clocks */ |
360 | udelay(15); | 409 | usleep_range(15, 20); |
361 | 410 | ||
362 | if (ah->ah_version == AR5K_AR5210) { | 411 | if (ah->ah_version == AR5K_AR5210) { |
363 | val &= AR5K_RESET_CTL_PCU | AR5K_RESET_CTL_DMA | 412 | val &= AR5K_RESET_CTL_PCU | AR5K_RESET_CTL_DMA |
@@ -382,12 +431,17 @@ static int ath5k_hw_nic_reset(struct ath5k_hw *ah, u32 val) | |||
382 | return ret; | 431 | return ret; |
383 | } | 432 | } |
384 | 433 | ||
385 | /* | 434 | /** |
386 | * Reset AHB chipset | 435 | * ath5k_hw_wisoc_reset() - Reset AHB chipset |
387 | * AR5K_RESET_CTL_PCU flag resets WMAC | 436 | * @ah: The &struct ath5k_hw |
388 | * AR5K_RESET_CTL_BASEBAND flag resets WBB | 437 | * @flags: Mask to indicate what units to reset |
438 | * | ||
439 | * Same as ath5k_hw_nic_reset but for AHB based devices | ||
440 | * | ||
441 | * Returns 0 if we are O.K. or -EAGAIN (from athk5_hw_register_timeout) | ||
389 | */ | 442 | */ |
390 | static int ath5k_hw_wisoc_reset(struct ath5k_hw *ah, u32 flags) | 443 | static int |
444 | ath5k_hw_wisoc_reset(struct ath5k_hw *ah, u32 flags) | ||
391 | { | 445 | { |
392 | u32 mask = flags ? flags : ~0U; | 446 | u32 mask = flags ? flags : ~0U; |
393 | u32 __iomem *reg; | 447 | u32 __iomem *reg; |
@@ -422,7 +476,7 @@ static int ath5k_hw_wisoc_reset(struct ath5k_hw *ah, u32 flags) | |||
422 | regval = __raw_readl(reg); | 476 | regval = __raw_readl(reg); |
423 | __raw_writel(regval | val, reg); | 477 | __raw_writel(regval | val, reg); |
424 | regval = __raw_readl(reg); | 478 | regval = __raw_readl(reg); |
425 | udelay(100); | 479 | usleep_range(100, 150); |
426 | 480 | ||
427 | /* Bring BB/MAC out of reset */ | 481 | /* Bring BB/MAC out of reset */ |
428 | __raw_writel(regval & ~val, reg); | 482 | __raw_writel(regval & ~val, reg); |
@@ -439,11 +493,23 @@ static int ath5k_hw_wisoc_reset(struct ath5k_hw *ah, u32 flags) | |||
439 | return 0; | 493 | return 0; |
440 | } | 494 | } |
441 | 495 | ||
442 | 496 | /** | |
443 | /* | 497 | * ath5k_hw_set_power_mode() - Set power mode |
444 | * Sleep control | 498 | * @ah: The &struct ath5k_hw |
499 | * @mode: One of enum ath5k_power_mode | ||
500 | * @set_chip: Set to true to write sleep control register | ||
501 | * @sleep_duration: How much time the device is allowed to sleep | ||
502 | * when sleep logic is enabled (in 128 microsecond increments). | ||
503 | * | ||
504 | * This function is used to configure sleep policy and allowed | ||
505 | * sleep modes. For more information check out the sleep control | ||
506 | * register on reg.h and STA_ID1. | ||
507 | * | ||
508 | * Returns 0 on success, -EIO if chip didn't wake up or -EINVAL if an invalid | ||
509 | * mode is requested. | ||
445 | */ | 510 | */ |
446 | static int ath5k_hw_set_power(struct ath5k_hw *ah, enum ath5k_power_mode mode, | 511 | static int |
512 | ath5k_hw_set_power_mode(struct ath5k_hw *ah, enum ath5k_power_mode mode, | ||
447 | bool set_chip, u16 sleep_duration) | 513 | bool set_chip, u16 sleep_duration) |
448 | { | 514 | { |
449 | unsigned int i; | 515 | unsigned int i; |
@@ -493,7 +559,7 @@ static int ath5k_hw_set_power(struct ath5k_hw *ah, enum ath5k_power_mode mode, | |||
493 | 559 | ||
494 | ath5k_hw_reg_write(ah, data | AR5K_SLEEP_CTL_SLE_WAKE, | 560 | ath5k_hw_reg_write(ah, data | AR5K_SLEEP_CTL_SLE_WAKE, |
495 | AR5K_SLEEP_CTL); | 561 | AR5K_SLEEP_CTL); |
496 | udelay(15); | 562 | usleep_range(15, 20); |
497 | 563 | ||
498 | for (i = 200; i > 0; i--) { | 564 | for (i = 200; i > 0; i--) { |
499 | /* Check if the chip did wake up */ | 565 | /* Check if the chip did wake up */ |
@@ -502,7 +568,7 @@ static int ath5k_hw_set_power(struct ath5k_hw *ah, enum ath5k_power_mode mode, | |||
502 | break; | 568 | break; |
503 | 569 | ||
504 | /* Wait a bit and retry */ | 570 | /* Wait a bit and retry */ |
505 | udelay(50); | 571 | usleep_range(50, 75); |
506 | ath5k_hw_reg_write(ah, data | AR5K_SLEEP_CTL_SLE_WAKE, | 572 | ath5k_hw_reg_write(ah, data | AR5K_SLEEP_CTL_SLE_WAKE, |
507 | AR5K_SLEEP_CTL); | 573 | AR5K_SLEEP_CTL); |
508 | } | 574 | } |
@@ -523,17 +589,20 @@ commit: | |||
523 | return 0; | 589 | return 0; |
524 | } | 590 | } |
525 | 591 | ||
526 | /* | 592 | /** |
527 | * Put device on hold | 593 | * ath5k_hw_on_hold() - Put device on hold |
594 | * @ah: The &struct ath5k_hw | ||
528 | * | 595 | * |
529 | * Put MAC and Baseband on warm reset and | 596 | * Put MAC and Baseband on warm reset and keep that state |
530 | * keep that state (don't clean sleep control | 597 | * (don't clean sleep control register). After this MAC |
531 | * register). After this MAC and Baseband are | 598 | * and Baseband are disabled and a full reset is needed |
532 | * disabled and a full reset is needed to come | 599 | * to come back. This way we save as much power as possible |
533 | * back. This way we save as much power as possible | ||
534 | * without putting the card on full sleep. | 600 | * without putting the card on full sleep. |
601 | * | ||
602 | * Returns 0 on success or -EIO on error | ||
535 | */ | 603 | */ |
536 | int ath5k_hw_on_hold(struct ath5k_hw *ah) | 604 | int |
605 | ath5k_hw_on_hold(struct ath5k_hw *ah) | ||
537 | { | 606 | { |
538 | struct pci_dev *pdev = ah->pdev; | 607 | struct pci_dev *pdev = ah->pdev; |
539 | u32 bus_flags; | 608 | u32 bus_flags; |
@@ -543,7 +612,7 @@ int ath5k_hw_on_hold(struct ath5k_hw *ah) | |||
543 | return 0; | 612 | return 0; |
544 | 613 | ||
545 | /* Make sure device is awake */ | 614 | /* Make sure device is awake */ |
546 | ret = ath5k_hw_set_power(ah, AR5K_PM_AWAKE, true, 0); | 615 | ret = ath5k_hw_set_power_mode(ah, AR5K_PM_AWAKE, true, 0); |
547 | if (ret) { | 616 | if (ret) { |
548 | ATH5K_ERR(ah, "failed to wakeup the MAC Chip\n"); | 617 | ATH5K_ERR(ah, "failed to wakeup the MAC Chip\n"); |
549 | return ret; | 618 | return ret; |
@@ -563,7 +632,7 @@ int ath5k_hw_on_hold(struct ath5k_hw *ah) | |||
563 | ret = ath5k_hw_nic_reset(ah, AR5K_RESET_CTL_PCU | | 632 | ret = ath5k_hw_nic_reset(ah, AR5K_RESET_CTL_PCU | |
564 | AR5K_RESET_CTL_MAC | AR5K_RESET_CTL_DMA | | 633 | AR5K_RESET_CTL_MAC | AR5K_RESET_CTL_DMA | |
565 | AR5K_RESET_CTL_PHY | AR5K_RESET_CTL_PCI); | 634 | AR5K_RESET_CTL_PHY | AR5K_RESET_CTL_PCI); |
566 | mdelay(2); | 635 | usleep_range(2000, 2500); |
567 | } else { | 636 | } else { |
568 | ret = ath5k_hw_nic_reset(ah, AR5K_RESET_CTL_PCU | | 637 | ret = ath5k_hw_nic_reset(ah, AR5K_RESET_CTL_PCU | |
569 | AR5K_RESET_CTL_BASEBAND | bus_flags); | 638 | AR5K_RESET_CTL_BASEBAND | bus_flags); |
@@ -575,7 +644,7 @@ int ath5k_hw_on_hold(struct ath5k_hw *ah) | |||
575 | } | 644 | } |
576 | 645 | ||
577 | /* ...wakeup again!*/ | 646 | /* ...wakeup again!*/ |
578 | ret = ath5k_hw_set_power(ah, AR5K_PM_AWAKE, true, 0); | 647 | ret = ath5k_hw_set_power_mode(ah, AR5K_PM_AWAKE, true, 0); |
579 | if (ret) { | 648 | if (ret) { |
580 | ATH5K_ERR(ah, "failed to put device on hold\n"); | 649 | ATH5K_ERR(ah, "failed to put device on hold\n"); |
581 | return ret; | 650 | return ret; |
@@ -584,11 +653,18 @@ int ath5k_hw_on_hold(struct ath5k_hw *ah) | |||
584 | return ret; | 653 | return ret; |
585 | } | 654 | } |
586 | 655 | ||
587 | /* | 656 | /** |
657 | * ath5k_hw_nic_wakeup() - Force card out of sleep | ||
658 | * @ah: The &struct ath5k_hw | ||
659 | * @channel: The &struct ieee80211_channel | ||
660 | * | ||
588 | * Bring up MAC + PHY Chips and program PLL | 661 | * Bring up MAC + PHY Chips and program PLL |
589 | * Channel is NULL for the initial wakeup. | 662 | * NOTE: Channel is NULL for the initial wakeup. |
663 | * | ||
664 | * Returns 0 on success, -EIO on hw failure or -EINVAL for false channel infos | ||
590 | */ | 665 | */ |
591 | int ath5k_hw_nic_wakeup(struct ath5k_hw *ah, struct ieee80211_channel *channel) | 666 | int |
667 | ath5k_hw_nic_wakeup(struct ath5k_hw *ah, struct ieee80211_channel *channel) | ||
592 | { | 668 | { |
593 | struct pci_dev *pdev = ah->pdev; | 669 | struct pci_dev *pdev = ah->pdev; |
594 | u32 turbo, mode, clock, bus_flags; | 670 | u32 turbo, mode, clock, bus_flags; |
@@ -600,7 +676,7 @@ int ath5k_hw_nic_wakeup(struct ath5k_hw *ah, struct ieee80211_channel *channel) | |||
600 | 676 | ||
601 | if ((ath5k_get_bus_type(ah) != ATH_AHB) || channel) { | 677 | if ((ath5k_get_bus_type(ah) != ATH_AHB) || channel) { |
602 | /* Wakeup the device */ | 678 | /* Wakeup the device */ |
603 | ret = ath5k_hw_set_power(ah, AR5K_PM_AWAKE, true, 0); | 679 | ret = ath5k_hw_set_power_mode(ah, AR5K_PM_AWAKE, true, 0); |
604 | if (ret) { | 680 | if (ret) { |
605 | ATH5K_ERR(ah, "failed to wakeup the MAC Chip\n"); | 681 | ATH5K_ERR(ah, "failed to wakeup the MAC Chip\n"); |
606 | return ret; | 682 | return ret; |
@@ -621,7 +697,7 @@ int ath5k_hw_nic_wakeup(struct ath5k_hw *ah, struct ieee80211_channel *channel) | |||
621 | ret = ath5k_hw_nic_reset(ah, AR5K_RESET_CTL_PCU | | 697 | ret = ath5k_hw_nic_reset(ah, AR5K_RESET_CTL_PCU | |
622 | AR5K_RESET_CTL_MAC | AR5K_RESET_CTL_DMA | | 698 | AR5K_RESET_CTL_MAC | AR5K_RESET_CTL_DMA | |
623 | AR5K_RESET_CTL_PHY | AR5K_RESET_CTL_PCI); | 699 | AR5K_RESET_CTL_PHY | AR5K_RESET_CTL_PCI); |
624 | mdelay(2); | 700 | usleep_range(2000, 2500); |
625 | } else { | 701 | } else { |
626 | if (ath5k_get_bus_type(ah) == ATH_AHB) | 702 | if (ath5k_get_bus_type(ah) == ATH_AHB) |
627 | ret = ath5k_hw_wisoc_reset(ah, AR5K_RESET_CTL_PCU | | 703 | ret = ath5k_hw_wisoc_reset(ah, AR5K_RESET_CTL_PCU | |
@@ -637,7 +713,7 @@ int ath5k_hw_nic_wakeup(struct ath5k_hw *ah, struct ieee80211_channel *channel) | |||
637 | } | 713 | } |
638 | 714 | ||
639 | /* ...wakeup again!...*/ | 715 | /* ...wakeup again!...*/ |
640 | ret = ath5k_hw_set_power(ah, AR5K_PM_AWAKE, true, 0); | 716 | ret = ath5k_hw_set_power_mode(ah, AR5K_PM_AWAKE, true, 0); |
641 | if (ret) { | 717 | if (ret) { |
642 | ATH5K_ERR(ah, "failed to resume the MAC Chip\n"); | 718 | ATH5K_ERR(ah, "failed to resume the MAC Chip\n"); |
643 | return ret; | 719 | return ret; |
@@ -739,7 +815,7 @@ int ath5k_hw_nic_wakeup(struct ath5k_hw *ah, struct ieee80211_channel *channel) | |||
739 | /* ...update PLL if needed */ | 815 | /* ...update PLL if needed */ |
740 | if (ath5k_hw_reg_read(ah, AR5K_PHY_PLL) != clock) { | 816 | if (ath5k_hw_reg_read(ah, AR5K_PHY_PLL) != clock) { |
741 | ath5k_hw_reg_write(ah, clock, AR5K_PHY_PLL); | 817 | ath5k_hw_reg_write(ah, clock, AR5K_PHY_PLL); |
742 | udelay(300); | 818 | usleep_range(300, 350); |
743 | } | 819 | } |
744 | 820 | ||
745 | /* ...set the PHY operating mode */ | 821 | /* ...set the PHY operating mode */ |
@@ -755,8 +831,19 @@ int ath5k_hw_nic_wakeup(struct ath5k_hw *ah, struct ieee80211_channel *channel) | |||
755 | * Post-initvals register modifications * | 831 | * Post-initvals register modifications * |
756 | \**************************************/ | 832 | \**************************************/ |
757 | 833 | ||
758 | /* TODO: Half/Quarter rate */ | 834 | /** |
759 | static void ath5k_hw_tweak_initval_settings(struct ath5k_hw *ah, | 835 | * ath5k_hw_tweak_initval_settings() - Tweak initial settings |
836 | * @ah: The &struct ath5k_hw | ||
837 | * @channel: The &struct ieee80211_channel | ||
838 | * | ||
839 | * Some settings are not handled on initvals, e.g. bwmode | ||
840 | * settings, some phy settings, workarounds etc that in general | ||
841 | * don't fit anywhere else or are too small to introduce a separate | ||
842 | * function for each one. So we have this function to handle | ||
843 | * them all during reset and complete card's initialization. | ||
844 | */ | ||
845 | static void | ||
846 | ath5k_hw_tweak_initval_settings(struct ath5k_hw *ah, | ||
760 | struct ieee80211_channel *channel) | 847 | struct ieee80211_channel *channel) |
761 | { | 848 | { |
762 | if (ah->ah_version == AR5K_AR5212 && | 849 | if (ah->ah_version == AR5K_AR5212 && |
@@ -875,7 +962,16 @@ static void ath5k_hw_tweak_initval_settings(struct ath5k_hw *ah, | |||
875 | } | 962 | } |
876 | } | 963 | } |
877 | 964 | ||
878 | static void ath5k_hw_commit_eeprom_settings(struct ath5k_hw *ah, | 965 | /** |
966 | * ath5k_hw_commit_eeprom_settings() - Commit settings from EEPROM | ||
967 | * @ah: The &struct ath5k_hw | ||
968 | * @channel: The &struct ieee80211_channel | ||
969 | * | ||
970 | * Use settings stored on EEPROM to properly initialize the card | ||
971 | * based on various infos and per-mode calibration data. | ||
972 | */ | ||
973 | static void | ||
974 | ath5k_hw_commit_eeprom_settings(struct ath5k_hw *ah, | ||
879 | struct ieee80211_channel *channel) | 975 | struct ieee80211_channel *channel) |
880 | { | 976 | { |
881 | struct ath5k_eeprom_info *ee = &ah->ah_capabilities.cap_eeprom; | 977 | struct ath5k_eeprom_info *ee = &ah->ah_capabilities.cap_eeprom; |
@@ -1029,7 +1125,23 @@ static void ath5k_hw_commit_eeprom_settings(struct ath5k_hw *ah, | |||
1029 | * Main reset function * | 1125 | * Main reset function * |
1030 | \*********************/ | 1126 | \*********************/ |
1031 | 1127 | ||
1032 | int ath5k_hw_reset(struct ath5k_hw *ah, enum nl80211_iftype op_mode, | 1128 | /** |
1129 | * ath5k_hw_reset() - The main reset function | ||
1130 | * @ah: The &struct ath5k_hw | ||
1131 | * @op_mode: One of enum nl80211_iftype | ||
1132 | * @channel: The &struct ieee80211_channel | ||
1133 | * @fast: Enable fast channel switching | ||
1134 | * @skip_pcu: Skip pcu initialization | ||
1135 | * | ||
1136 | * This is the function we call each time we want to (re)initialize the | ||
1137 | * card and pass new settings to hw. We also call it when hw runs into | ||
1138 | * trouble to make it come back to a working state. | ||
1139 | * | ||
1140 | * Returns 0 on success, -EINVAL on false op_mode or channel infos, or -EIO | ||
1141 | * on failure. | ||
1142 | */ | ||
1143 | int | ||
1144 | ath5k_hw_reset(struct ath5k_hw *ah, enum nl80211_iftype op_mode, | ||
1033 | struct ieee80211_channel *channel, bool fast, bool skip_pcu) | 1145 | struct ieee80211_channel *channel, bool fast, bool skip_pcu) |
1034 | { | 1146 | { |
1035 | u32 s_seq[10], s_led[3], tsf_up, tsf_lo; | 1147 | u32 s_seq[10], s_led[3], tsf_up, tsf_lo; |
@@ -1242,7 +1354,7 @@ int ath5k_hw_reset(struct ath5k_hw *ah, enum nl80211_iftype op_mode, | |||
1242 | /* | 1354 | /* |
1243 | * Initialize PCU | 1355 | * Initialize PCU |
1244 | */ | 1356 | */ |
1245 | ath5k_hw_pcu_init(ah, op_mode, mode); | 1357 | ath5k_hw_pcu_init(ah, op_mode); |
1246 | 1358 | ||
1247 | /* | 1359 | /* |
1248 | * Initialize PHY | 1360 | * Initialize PHY |
diff --git a/drivers/net/wireless/ath/ath5k/rfbuffer.h b/drivers/net/wireless/ath/ath5k/rfbuffer.h index 5d11c23b4297..aed34d9954c0 100644 --- a/drivers/net/wireless/ath/ath5k/rfbuffer.h +++ b/drivers/net/wireless/ath/ath5k/rfbuffer.h | |||
@@ -18,7 +18,9 @@ | |||
18 | */ | 18 | */ |
19 | 19 | ||
20 | 20 | ||
21 | /* | 21 | /** |
22 | * DOC: RF Buffer registers | ||
23 | * | ||
22 | * There are some special registers on the RF chip | 24 | * There are some special registers on the RF chip |
23 | * that control various operation settings related mostly to | 25 | * that control various operation settings related mostly to |
24 | * the analog parts (channel, gain adjustment etc). | 26 | * the analog parts (channel, gain adjustment etc). |
@@ -44,40 +46,63 @@ | |||
44 | */ | 46 | */ |
45 | 47 | ||
46 | 48 | ||
47 | /* | 49 | /** |
50 | * struct ath5k_ini_rfbuffer - Initial RF Buffer settings | ||
51 | * @rfb_bank: RF Bank number | ||
52 | * @rfb_ctrl_register: RF Buffer control register | ||
53 | * @rfb_mode_data: RF Buffer data for each mode | ||
54 | * | ||
48 | * Struct to hold default mode specific RF | 55 | * Struct to hold default mode specific RF |
49 | * register values (RF Banks) | 56 | * register values (RF Banks) for each chip. |
50 | */ | 57 | */ |
51 | struct ath5k_ini_rfbuffer { | 58 | struct ath5k_ini_rfbuffer { |
52 | u8 rfb_bank; /* RF Bank number */ | 59 | u8 rfb_bank; |
53 | u16 rfb_ctrl_register; /* RF Buffer control register */ | 60 | u16 rfb_ctrl_register; |
54 | u32 rfb_mode_data[3]; /* RF Buffer data for each mode */ | 61 | u32 rfb_mode_data[3]; |
55 | }; | 62 | }; |
56 | 63 | ||
57 | /* | 64 | /** |
65 | * struct ath5k_rfb_field - An RF Buffer field (register/value) | ||
66 | * @len: Field length | ||
67 | * @pos: Offset on the raw packet | ||
68 | * @col: Used for shifting | ||
69 | * | ||
58 | * Struct to hold RF Buffer field | 70 | * Struct to hold RF Buffer field |
59 | * infos used to access certain RF | 71 | * infos used to access certain RF |
60 | * analog registers | 72 | * analog registers |
61 | */ | 73 | */ |
62 | struct ath5k_rfb_field { | 74 | struct ath5k_rfb_field { |
63 | u8 len; /* Field length */ | 75 | u8 len; |
64 | u16 pos; /* Offset on the raw packet */ | 76 | u16 pos; |
65 | u8 col; /* Column -used for shifting */ | 77 | u8 col; |
66 | }; | 78 | }; |
67 | 79 | ||
68 | /* | 80 | /** |
69 | * RF analog register definition | 81 | * struct ath5k_rf_reg - RF analog register definition |
82 | * @bank: RF Buffer Bank number | ||
83 | * @index: Register's index on ath5k_rf_regx_idx | ||
84 | * @field: The &struct ath5k_rfb_field | ||
85 | * | ||
86 | * We use this struct to define the set of RF registers | ||
87 | * on each chip that we want to tweak. Some RF registers | ||
88 | * are common between different chip versions so this saves | ||
89 | * us space and complexity because we can refer to an rf | ||
90 | * register by it's index no matter what chip we work with | ||
91 | * as long as it has that register. | ||
70 | */ | 92 | */ |
71 | struct ath5k_rf_reg { | 93 | struct ath5k_rf_reg { |
72 | u8 bank; /* RF Buffer Bank number */ | 94 | u8 bank; |
73 | u8 index; /* Register's index on rf_regs_idx */ | 95 | u8 index; |
74 | struct ath5k_rfb_field field; /* RF Buffer field for this register */ | 96 | struct ath5k_rfb_field field; |
75 | }; | 97 | }; |
76 | 98 | ||
77 | /* Map RF registers to indexes | 99 | /** |
100 | * enum ath5k_rf_regs_idx - Map RF registers to indexes | ||
101 | * | ||
78 | * We do this to handle common bits and make our | 102 | * We do this to handle common bits and make our |
79 | * life easier by using an index for each register | 103 | * life easier by using an index for each register |
80 | * instead of a full rfb_field */ | 104 | * instead of a full rfb_field |
105 | */ | ||
81 | enum ath5k_rf_regs_idx { | 106 | enum ath5k_rf_regs_idx { |
82 | /* BANK 2 */ | 107 | /* BANK 2 */ |
83 | AR5K_RF_TURBO = 0, | 108 | AR5K_RF_TURBO = 0, |
diff --git a/drivers/net/wireless/ath/ath5k/rfgain.h b/drivers/net/wireless/ath/ath5k/rfgain.h index ebfae052d89e..4d21df0e5975 100644 --- a/drivers/net/wireless/ath/ath5k/rfgain.h +++ b/drivers/net/wireless/ath/ath5k/rfgain.h | |||
@@ -18,13 +18,17 @@ | |||
18 | * | 18 | * |
19 | */ | 19 | */ |
20 | 20 | ||
21 | /* | 21 | /** |
22 | * struct ath5k_ini_rfgain - RF Gain table | ||
23 | * @rfg_register: RF Gain register address | ||
24 | * @rfg_value: Register value for 5 and 2GHz | ||
25 | * | ||
22 | * Mode-specific RF Gain table (64bytes) for RF5111/5112 | 26 | * Mode-specific RF Gain table (64bytes) for RF5111/5112 |
23 | * (RF5110 only comes with AR5210 and only supports a/turbo a mode so initial | 27 | * (RF5110 only comes with AR5210 and only supports a/turbo a mode so initial |
24 | * RF Gain values are included in AR5K_AR5210_INI) | 28 | * RF Gain values are included in AR5K_AR5210_INI) |
25 | */ | 29 | */ |
26 | struct ath5k_ini_rfgain { | 30 | struct ath5k_ini_rfgain { |
27 | u16 rfg_register; /* RF Gain register address */ | 31 | u16 rfg_register; |
28 | u32 rfg_value[2]; /* [freq (see below)] */ | 32 | u32 rfg_value[2]; /* [freq (see below)] */ |
29 | }; | 33 | }; |
30 | 34 | ||
@@ -455,18 +459,31 @@ static const struct ath5k_ini_rfgain rfgain_2425[] = { | |||
455 | #define AR5K_GAIN_CHECK_ADJUST(_g) \ | 459 | #define AR5K_GAIN_CHECK_ADJUST(_g) \ |
456 | ((_g)->g_current <= (_g)->g_low || (_g)->g_current >= (_g)->g_high) | 460 | ((_g)->g_current <= (_g)->g_low || (_g)->g_current >= (_g)->g_high) |
457 | 461 | ||
462 | /** | ||
463 | * struct ath5k_gain_opt_step - An RF gain optimization step | ||
464 | * @gos_param: Set of parameters | ||
465 | * @gos_gain: Gain | ||
466 | */ | ||
458 | struct ath5k_gain_opt_step { | 467 | struct ath5k_gain_opt_step { |
459 | s8 gos_param[AR5K_GAIN_CRN_MAX_FIX_BITS]; | 468 | s8 gos_param[AR5K_GAIN_CRN_MAX_FIX_BITS]; |
460 | s8 gos_gain; | 469 | s8 gos_gain; |
461 | }; | 470 | }; |
462 | 471 | ||
472 | /** | ||
473 | * struct ath5k_gain_opt - RF Gain optimization ladder | ||
474 | * @go_default: The default step | ||
475 | * @go_steps_count: How many optimization steps | ||
476 | * @go_step: Array of &struct ath5k_gain_opt_step | ||
477 | */ | ||
463 | struct ath5k_gain_opt { | 478 | struct ath5k_gain_opt { |
464 | u8 go_default; | 479 | u8 go_default; |
465 | u8 go_steps_count; | 480 | u8 go_steps_count; |
466 | const struct ath5k_gain_opt_step go_step[AR5K_GAIN_STEP_COUNT]; | 481 | const struct ath5k_gain_opt_step go_step[AR5K_GAIN_STEP_COUNT]; |
467 | }; | 482 | }; |
468 | 483 | ||
484 | |||
469 | /* | 485 | /* |
486 | * RF5111 | ||
470 | * Parameters on gos_param: | 487 | * Parameters on gos_param: |
471 | * 1) Tx clip PHY register | 488 | * 1) Tx clip PHY register |
472 | * 2) PWD 90 RF register | 489 | * 2) PWD 90 RF register |
@@ -490,6 +507,7 @@ static const struct ath5k_gain_opt rfgain_opt_5111 = { | |||
490 | }; | 507 | }; |
491 | 508 | ||
492 | /* | 509 | /* |
510 | * RF5112 | ||
493 | * Parameters on gos_param: | 511 | * Parameters on gos_param: |
494 | * 1) Mixgain ovr RF register | 512 | * 1) Mixgain ovr RF register |
495 | * 2) PWD 138 RF register | 513 | * 2) PWD 138 RF register |
diff --git a/drivers/net/wireless/ath/ath6kl/cfg80211.c b/drivers/net/wireless/ath/ath6kl/cfg80211.c index abe3af3c6188..6c59a217b1a1 100644 --- a/drivers/net/wireless/ath/ath6kl/cfg80211.c +++ b/drivers/net/wireless/ath/ath6kl/cfg80211.c | |||
@@ -14,6 +14,8 @@ | |||
14 | * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. | 14 | * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. |
15 | */ | 15 | */ |
16 | 16 | ||
17 | #include <linux/moduleparam.h> | ||
18 | |||
17 | #include "core.h" | 19 | #include "core.h" |
18 | #include "cfg80211.h" | 20 | #include "cfg80211.h" |
19 | #include "debug.h" | 21 | #include "debug.h" |
diff --git a/drivers/net/wireless/ath/ath6kl/debug.c b/drivers/net/wireless/ath/ath6kl/debug.c index cf513a80b061..eb808b46f94c 100644 --- a/drivers/net/wireless/ath/ath6kl/debug.c +++ b/drivers/net/wireless/ath/ath6kl/debug.c | |||
@@ -19,6 +19,7 @@ | |||
19 | #include <linux/circ_buf.h> | 19 | #include <linux/circ_buf.h> |
20 | #include <linux/fs.h> | 20 | #include <linux/fs.h> |
21 | #include <linux/vmalloc.h> | 21 | #include <linux/vmalloc.h> |
22 | #include <linux/export.h> | ||
22 | 23 | ||
23 | #include "debug.h" | 24 | #include "debug.h" |
24 | #include "target.h" | 25 | #include "target.h" |
diff --git a/drivers/net/wireless/ath/ath6kl/debug.h b/drivers/net/wireless/ath/ath6kl/debug.h index 9b779aac83e7..e569c652e35c 100644 --- a/drivers/net/wireless/ath/ath6kl/debug.h +++ b/drivers/net/wireless/ath/ath6kl/debug.h | |||
@@ -46,8 +46,8 @@ enum ATH6K_DEBUG_MASK { | |||
46 | }; | 46 | }; |
47 | 47 | ||
48 | extern unsigned int debug_mask; | 48 | extern unsigned int debug_mask; |
49 | extern int ath6kl_printk(const char *level, const char *fmt, ...) | 49 | extern __printf(2, 3) |
50 | __attribute__ ((format (printf, 2, 3))); | 50 | int ath6kl_printk(const char *level, const char *fmt, ...); |
51 | 51 | ||
52 | #define ath6kl_info(fmt, ...) \ | 52 | #define ath6kl_info(fmt, ...) \ |
53 | ath6kl_printk(KERN_INFO, fmt, ##__VA_ARGS__) | 53 | ath6kl_printk(KERN_INFO, fmt, ##__VA_ARGS__) |
diff --git a/drivers/net/wireless/ath/ath6kl/init.c b/drivers/net/wireless/ath/ath6kl/init.c index c614049d7b2e..368ecbd172a3 100644 --- a/drivers/net/wireless/ath/ath6kl/init.c +++ b/drivers/net/wireless/ath/ath6kl/init.c | |||
@@ -1663,6 +1663,7 @@ int ath6kl_core_init(struct ath6kl *ar) | |||
1663 | 1663 | ||
1664 | ar->wiphy->flags |= WIPHY_FLAG_SUPPORTS_FW_ROAM | | 1664 | ar->wiphy->flags |= WIPHY_FLAG_SUPPORTS_FW_ROAM | |
1665 | WIPHY_FLAG_HAVE_AP_SME | | 1665 | WIPHY_FLAG_HAVE_AP_SME | |
1666 | WIPHY_FLAG_HAS_REMAIN_ON_CHANNEL | | ||
1666 | WIPHY_FLAG_AP_PROBE_RESP_OFFLOAD; | 1667 | WIPHY_FLAG_AP_PROBE_RESP_OFFLOAD; |
1667 | 1668 | ||
1668 | if (test_bit(ATH6KL_FW_CAPABILITY_SCHED_SCAN, ar->fw_capabilities)) | 1669 | if (test_bit(ATH6KL_FW_CAPABILITY_SCHED_SCAN, ar->fw_capabilities)) |
diff --git a/drivers/net/wireless/ath/ath6kl/sdio.c b/drivers/net/wireless/ath/ath6kl/sdio.c index 07903e6114d8..15c3f56caf4f 100644 --- a/drivers/net/wireless/ath/ath6kl/sdio.c +++ b/drivers/net/wireless/ath/ath6kl/sdio.c | |||
@@ -14,6 +14,7 @@ | |||
14 | * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. | 14 | * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. |
15 | */ | 15 | */ |
16 | 16 | ||
17 | #include <linux/module.h> | ||
17 | #include <linux/mmc/card.h> | 18 | #include <linux/mmc/card.h> |
18 | #include <linux/mmc/mmc.h> | 19 | #include <linux/mmc/mmc.h> |
19 | #include <linux/mmc/host.h> | 20 | #include <linux/mmc/host.h> |
diff --git a/drivers/net/wireless/ath/ath9k/Kconfig b/drivers/net/wireless/ath/ath9k/Kconfig index 7b4c074e12fa..1b4786ae00ac 100644 --- a/drivers/net/wireless/ath/ath9k/Kconfig +++ b/drivers/net/wireless/ath/ath9k/Kconfig | |||
@@ -2,6 +2,9 @@ config ATH9K_HW | |||
2 | tristate | 2 | tristate |
3 | config ATH9K_COMMON | 3 | config ATH9K_COMMON |
4 | tristate | 4 | tristate |
5 | config ATH9K_DFS_DEBUGFS | ||
6 | def_bool y | ||
7 | depends on ATH9K_DEBUGFS && ATH9K_DFS_CERTIFIED | ||
5 | 8 | ||
6 | config ATH9K | 9 | config ATH9K |
7 | tristate "Atheros 802.11n wireless cards support" | 10 | tristate "Atheros 802.11n wireless cards support" |
@@ -51,6 +54,25 @@ config ATH9K_DEBUGFS | |||
51 | 54 | ||
52 | Also required for changing debug message flags at run time. | 55 | Also required for changing debug message flags at run time. |
53 | 56 | ||
57 | config ATH9K_DFS_CERTIFIED | ||
58 | bool "Atheros DFS support for certified platforms" | ||
59 | depends on ATH9K && EXPERT | ||
60 | default n | ||
61 | ---help--- | ||
62 | This option enables DFS support for initiating radiation on | ||
63 | ath9k. There is no way to dynamically detect if a card was DFS | ||
64 | certified and as such this is left as a build time option. This | ||
65 | option should only be enabled by system integrators that can | ||
66 | guarantee that all the platforms that their kernel will run on | ||
67 | have obtained appropriate regulatory body certification for a | ||
68 | respective Atheros card by using ath9k on the target shipping | ||
69 | platforms. | ||
70 | |||
71 | This is currently only a placeholder for future DFS support, | ||
72 | as DFS support requires more components that still need to be | ||
73 | developed. At this point enabling this option won't do anything | ||
74 | except increase code size. | ||
75 | |||
54 | config ATH9K_RATE_CONTROL | 76 | config ATH9K_RATE_CONTROL |
55 | bool "Atheros ath9k rate control" | 77 | bool "Atheros ath9k rate control" |
56 | depends on ATH9K | 78 | depends on ATH9K |
diff --git a/drivers/net/wireless/ath/ath9k/Makefile b/drivers/net/wireless/ath/ath9k/Makefile index 49d3f25f509d..da02242499af 100644 --- a/drivers/net/wireless/ath/ath9k/Makefile +++ b/drivers/net/wireless/ath/ath9k/Makefile | |||
@@ -10,6 +10,8 @@ ath9k-$(CONFIG_ATH9K_RATE_CONTROL) += rc.o | |||
10 | ath9k-$(CONFIG_ATH9K_PCI) += pci.o | 10 | ath9k-$(CONFIG_ATH9K_PCI) += pci.o |
11 | ath9k-$(CONFIG_ATH9K_AHB) += ahb.o | 11 | ath9k-$(CONFIG_ATH9K_AHB) += ahb.o |
12 | ath9k-$(CONFIG_ATH9K_DEBUGFS) += debug.o | 12 | ath9k-$(CONFIG_ATH9K_DEBUGFS) += debug.o |
13 | ath9k-$(CONFIG_ATH9K_DFS_DEBUGFS) += dfs_debug.o | ||
14 | ath9k-$(CONFIG_ATH9K_DFS_CERTIFIED) += dfs.o | ||
13 | 15 | ||
14 | obj-$(CONFIG_ATH9K) += ath9k.o | 16 | obj-$(CONFIG_ATH9K) += ath9k.o |
15 | 17 | ||
@@ -34,7 +36,8 @@ ath9k_hw-y:= \ | |||
34 | ar9002_mac.o \ | 36 | ar9002_mac.o \ |
35 | ar9003_mac.o \ | 37 | ar9003_mac.o \ |
36 | ar9003_eeprom.o \ | 38 | ar9003_eeprom.o \ |
37 | ar9003_paprd.o | 39 | ar9003_paprd.o \ |
40 | ar9003_mci.o | ||
38 | 41 | ||
39 | obj-$(CONFIG_ATH9K_HW) += ath9k_hw.o | 42 | obj-$(CONFIG_ATH9K_HW) += ath9k_hw.o |
40 | 43 | ||
diff --git a/drivers/net/wireless/ath/ath9k/ahb.c b/drivers/net/wireless/ath/ath9k/ahb.c index 85a54cd2b083..5e47ca6d16a8 100644 --- a/drivers/net/wireless/ath/ath9k/ahb.c +++ b/drivers/net/wireless/ath/ath9k/ahb.c | |||
@@ -19,6 +19,7 @@ | |||
19 | #include <linux/nl80211.h> | 19 | #include <linux/nl80211.h> |
20 | #include <linux/platform_device.h> | 20 | #include <linux/platform_device.h> |
21 | #include <linux/ath9k_platform.h> | 21 | #include <linux/ath9k_platform.h> |
22 | #include <linux/module.h> | ||
22 | #include "ath9k.h" | 23 | #include "ath9k.h" |
23 | 24 | ||
24 | static const struct platform_device_id ath9k_platform_id_table[] = { | 25 | static const struct platform_device_id ath9k_platform_id_table[] = { |
diff --git a/drivers/net/wireless/ath/ath9k/ani.c b/drivers/net/wireless/ath/ath9k/ani.c index 2776c3c1f506..a639b94f7643 100644 --- a/drivers/net/wireless/ath/ath9k/ani.c +++ b/drivers/net/wireless/ath/ath9k/ani.c | |||
@@ -15,6 +15,7 @@ | |||
15 | */ | 15 | */ |
16 | 16 | ||
17 | #include <linux/kernel.h> | 17 | #include <linux/kernel.h> |
18 | #include <linux/export.h> | ||
18 | #include "hw.h" | 19 | #include "hw.h" |
19 | #include "hw-ops.h" | 20 | #include "hw-ops.h" |
20 | 21 | ||
diff --git a/drivers/net/wireless/ath/ath9k/ar9002_calib.c b/drivers/net/wireless/ath/ath9k/ar9002_calib.c index 88279e325dca..157337febc2b 100644 --- a/drivers/net/wireless/ath/ath9k/ar9002_calib.c +++ b/drivers/net/wireless/ath/ath9k/ar9002_calib.c | |||
@@ -203,7 +203,7 @@ static void ar9002_hw_iqcalibrate(struct ath_hw *ah, u8 numChains) | |||
203 | i); | 203 | i); |
204 | 204 | ||
205 | ath_dbg(common, ATH_DBG_CALIBRATE, | 205 | ath_dbg(common, ATH_DBG_CALIBRATE, |
206 | "Orignal: Chn %diq_corr_meas = 0x%08x\n", | 206 | "Original: Chn %d iq_corr_meas = 0x%08x\n", |
207 | i, ah->totalIqCorrMeas[i]); | 207 | i, ah->totalIqCorrMeas[i]); |
208 | 208 | ||
209 | iqCorrNeg = 0; | 209 | iqCorrNeg = 0; |
diff --git a/drivers/net/wireless/ath/ath9k/ar9002_hw.c b/drivers/net/wireless/ath/ath9k/ar9002_hw.c index 626d547d2f06..11f192a1ceb7 100644 --- a/drivers/net/wireless/ath/ath9k/ar9002_hw.c +++ b/drivers/net/wireless/ath/ath9k/ar9002_hw.c | |||
@@ -14,6 +14,7 @@ | |||
14 | * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. | 14 | * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. |
15 | */ | 15 | */ |
16 | 16 | ||
17 | #include <linux/moduleparam.h> | ||
17 | #include "hw.h" | 18 | #include "hw.h" |
18 | #include "ar5008_initvals.h" | 19 | #include "ar5008_initvals.h" |
19 | #include "ar9001_initvals.h" | 20 | #include "ar9001_initvals.h" |
diff --git a/drivers/net/wireless/ath/ath9k/ar9002_mac.c b/drivers/net/wireless/ath/ath9k/ar9002_mac.c index f7d8e516a2a9..b5920168606d 100644 --- a/drivers/net/wireless/ath/ath9k/ar9002_mac.c +++ b/drivers/net/wireless/ath/ath9k/ar9002_mac.c | |||
@@ -15,6 +15,7 @@ | |||
15 | */ | 15 | */ |
16 | 16 | ||
17 | #include "hw.h" | 17 | #include "hw.h" |
18 | #include <linux/export.h> | ||
18 | 19 | ||
19 | #define AR_BufLen 0x00000fff | 20 | #define AR_BufLen 0x00000fff |
20 | 21 | ||
diff --git a/drivers/net/wireless/ath/ath9k/ar9003_calib.c b/drivers/net/wireless/ath/ath9k/ar9003_calib.c index 12a730dcb500..23b3a6c57800 100644 --- a/drivers/net/wireless/ath/ath9k/ar9003_calib.c +++ b/drivers/net/wireless/ath/ath9k/ar9003_calib.c | |||
@@ -18,6 +18,7 @@ | |||
18 | #include "hw-ops.h" | 18 | #include "hw-ops.h" |
19 | #include "ar9003_phy.h" | 19 | #include "ar9003_phy.h" |
20 | #include "ar9003_rtt.h" | 20 | #include "ar9003_rtt.h" |
21 | #include "ar9003_mci.h" | ||
21 | 22 | ||
22 | #define MAX_MEASUREMENT MAX_IQCAL_MEASUREMENT | 23 | #define MAX_MEASUREMENT MAX_IQCAL_MEASUREMENT |
23 | #define MAX_MAG_DELTA 11 | 24 | #define MAX_MAG_DELTA 11 |
@@ -225,7 +226,7 @@ static void ar9003_hw_iqcalibrate(struct ath_hw *ah, u8 numChains) | |||
225 | i); | 226 | i); |
226 | 227 | ||
227 | ath_dbg(common, ATH_DBG_CALIBRATE, | 228 | ath_dbg(common, ATH_DBG_CALIBRATE, |
228 | "Orignal: Chn %diq_corr_meas = 0x%08x\n", | 229 | "Original: Chn %d iq_corr_meas = 0x%08x\n", |
229 | i, ah->totalIqCorrMeas[i]); | 230 | i, ah->totalIqCorrMeas[i]); |
230 | 231 | ||
231 | iqCorrNeg = 0; | 232 | iqCorrNeg = 0; |
@@ -824,7 +825,7 @@ static void ar9003_hw_tx_iq_cal_post_proc(struct ath_hw *ah, bool is_reusable) | |||
824 | chan_info_tab[i] + offset); | 825 | chan_info_tab[i] + offset); |
825 | 826 | ||
826 | ath_dbg(common, ATH_DBG_CALIBRATE, | 827 | ath_dbg(common, ATH_DBG_CALIBRATE, |
827 | "IQ RES[%d]=0x%x" | 828 | "IQ_RES[%d]=0x%x " |
828 | "IQ_RES[%d]=0x%x\n", | 829 | "IQ_RES[%d]=0x%x\n", |
829 | idx, iq_res[idx], idx + 1, | 830 | idx, iq_res[idx], idx + 1, |
830 | iq_res[idx + 1]); | 831 | iq_res[idx + 1]); |
@@ -934,10 +935,12 @@ static bool ar9003_hw_init_cal(struct ath_hw *ah, | |||
934 | { | 935 | { |
935 | struct ath_common *common = ath9k_hw_common(ah); | 936 | struct ath_common *common = ath9k_hw_common(ah); |
936 | struct ath9k_hw_cal_data *caldata = ah->caldata; | 937 | struct ath9k_hw_cal_data *caldata = ah->caldata; |
938 | struct ath9k_hw_mci *mci_hw = &ah->btcoex_hw.mci; | ||
937 | bool txiqcal_done = false, txclcal_done = false; | 939 | bool txiqcal_done = false, txclcal_done = false; |
938 | bool is_reusable = true, status = true; | 940 | bool is_reusable = true, status = true; |
939 | bool run_rtt_cal = false, run_agc_cal; | 941 | bool run_rtt_cal = false, run_agc_cal; |
940 | bool rtt = !!(ah->caps.hw_caps & ATH9K_HW_CAP_RTT); | 942 | bool rtt = !!(ah->caps.hw_caps & ATH9K_HW_CAP_RTT); |
943 | bool mci = !!(ah->caps.hw_caps & ATH9K_HW_CAP_MCI); | ||
941 | u32 agc_ctrl = 0, agc_supp_cals = AR_PHY_AGC_CONTROL_OFFSET_CAL | | 944 | u32 agc_ctrl = 0, agc_supp_cals = AR_PHY_AGC_CONTROL_OFFSET_CAL | |
942 | AR_PHY_AGC_CONTROL_FLTR_CAL | | 945 | AR_PHY_AGC_CONTROL_FLTR_CAL | |
943 | AR_PHY_AGC_CONTROL_PKDET_CAL; | 946 | AR_PHY_AGC_CONTROL_PKDET_CAL; |
@@ -1005,6 +1008,31 @@ static bool ar9003_hw_init_cal(struct ath_hw *ah, | |||
1005 | } else if (caldata && !caldata->done_txiqcal_once) | 1008 | } else if (caldata && !caldata->done_txiqcal_once) |
1006 | run_agc_cal = true; | 1009 | run_agc_cal = true; |
1007 | 1010 | ||
1011 | if (mci && IS_CHAN_2GHZ(chan) && | ||
1012 | (mci_hw->bt_state == MCI_BT_AWAKE) && | ||
1013 | run_agc_cal && | ||
1014 | !(mci_hw->config & ATH_MCI_CONFIG_DISABLE_MCI_CAL)) { | ||
1015 | |||
1016 | u32 pld[4] = {0, 0, 0, 0}; | ||
1017 | |||
1018 | /* send CAL_REQ only when BT is AWAKE. */ | ||
1019 | ath_dbg(common, ATH_DBG_MCI, "MCI send WLAN_CAL_REQ 0x%x\n", | ||
1020 | mci_hw->wlan_cal_seq); | ||
1021 | MCI_GPM_SET_CAL_TYPE(pld, MCI_GPM_WLAN_CAL_REQ); | ||
1022 | pld[MCI_GPM_WLAN_CAL_W_SEQUENCE] = mci_hw->wlan_cal_seq++; | ||
1023 | ar9003_mci_send_message(ah, MCI_GPM, 0, pld, 16, true, false); | ||
1024 | |||
1025 | /* Wait BT_CAL_GRANT for 50ms */ | ||
1026 | ath_dbg(common, ATH_DBG_MCI, "MCI wait for BT_CAL_GRANT"); | ||
1027 | |||
1028 | if (ar9003_mci_wait_for_gpm(ah, MCI_GPM_BT_CAL_GRANT, 0, 50000)) | ||
1029 | ath_dbg(common, ATH_DBG_MCI, "MCI got BT_CAL_GRANT"); | ||
1030 | else { | ||
1031 | is_reusable = false; | ||
1032 | ath_dbg(common, ATH_DBG_MCI, "\nMCI BT is not responding"); | ||
1033 | } | ||
1034 | } | ||
1035 | |||
1008 | txiqcal_done = ar9003_hw_tx_iq_cal_run(ah); | 1036 | txiqcal_done = ar9003_hw_tx_iq_cal_run(ah); |
1009 | REG_WRITE(ah, AR_PHY_ACTIVE, AR_PHY_ACTIVE_DIS); | 1037 | REG_WRITE(ah, AR_PHY_ACTIVE, AR_PHY_ACTIVE_DIS); |
1010 | udelay(5); | 1038 | udelay(5); |
@@ -1022,6 +1050,21 @@ skip_tx_iqcal: | |||
1022 | AR_PHY_AGC_CONTROL_CAL, | 1050 | AR_PHY_AGC_CONTROL_CAL, |
1023 | 0, AH_WAIT_TIMEOUT); | 1051 | 0, AH_WAIT_TIMEOUT); |
1024 | } | 1052 | } |
1053 | |||
1054 | if (mci && IS_CHAN_2GHZ(chan) && | ||
1055 | (mci_hw->bt_state == MCI_BT_AWAKE) && | ||
1056 | run_agc_cal && | ||
1057 | !(mci_hw->config & ATH_MCI_CONFIG_DISABLE_MCI_CAL)) { | ||
1058 | |||
1059 | u32 pld[4] = {0, 0, 0, 0}; | ||
1060 | |||
1061 | ath_dbg(common, ATH_DBG_MCI, "MCI Send WLAN_CAL_DONE 0x%x\n", | ||
1062 | mci_hw->wlan_cal_done); | ||
1063 | MCI_GPM_SET_CAL_TYPE(pld, MCI_GPM_WLAN_CAL_DONE); | ||
1064 | pld[MCI_GPM_WLAN_CAL_W_SEQUENCE] = mci_hw->wlan_cal_done++; | ||
1065 | ar9003_mci_send_message(ah, MCI_GPM, 0, pld, 16, true, false); | ||
1066 | } | ||
1067 | |||
1025 | if (rtt && !run_rtt_cal) { | 1068 | if (rtt && !run_rtt_cal) { |
1026 | agc_ctrl |= agc_supp_cals; | 1069 | agc_ctrl |= agc_supp_cals; |
1027 | REG_WRITE(ah, AR_PHY_AGC_CONTROL, agc_ctrl); | 1070 | REG_WRITE(ah, AR_PHY_AGC_CONTROL, agc_ctrl); |
diff --git a/drivers/net/wireless/ath/ath9k/ar9003_eeprom.c b/drivers/net/wireless/ath/ath9k/ar9003_eeprom.c index a93bd63ad23b..4ba6f52943a8 100644 --- a/drivers/net/wireless/ath/ath9k/ar9003_eeprom.c +++ b/drivers/net/wireless/ath/ath9k/ar9003_eeprom.c | |||
@@ -4779,7 +4779,7 @@ static void ar9003_hw_set_power_per_rate_table(struct ath_hw *ah, | |||
4779 | { | 4779 | { |
4780 | struct ath_common *common = ath9k_hw_common(ah); | 4780 | struct ath_common *common = ath9k_hw_common(ah); |
4781 | struct ar9300_eeprom *pEepData = &ah->eeprom.ar9300_eep; | 4781 | struct ar9300_eeprom *pEepData = &ah->eeprom.ar9300_eep; |
4782 | u16 twiceMaxEdgePower = MAX_RATE_POWER; | 4782 | u16 twiceMaxEdgePower; |
4783 | int i; | 4783 | int i; |
4784 | u16 scaledPower = 0, minCtlPower; | 4784 | u16 scaledPower = 0, minCtlPower; |
4785 | static const u16 ctlModesFor11a[] = { | 4785 | static const u16 ctlModesFor11a[] = { |
@@ -4880,6 +4880,7 @@ static void ar9003_hw_set_power_per_rate_table(struct ath_hw *ah, | |||
4880 | ctlNum = AR9300_NUM_CTLS_5G; | 4880 | ctlNum = AR9300_NUM_CTLS_5G; |
4881 | } | 4881 | } |
4882 | 4882 | ||
4883 | twiceMaxEdgePower = MAX_RATE_POWER; | ||
4883 | for (i = 0; (i < ctlNum) && ctlIndex[i]; i++) { | 4884 | for (i = 0; (i < ctlNum) && ctlIndex[i]; i++) { |
4884 | ath_dbg(common, ATH_DBG_REGULATORY, | 4885 | ath_dbg(common, ATH_DBG_REGULATORY, |
4885 | "LOOP-Ctlidx %d: cfgCtl 0x%2.2x pCtlMode 0x%2.2x ctlIndex 0x%2.2x chan %d\n", | 4886 | "LOOP-Ctlidx %d: cfgCtl 0x%2.2x pCtlMode 0x%2.2x ctlIndex 0x%2.2x chan %d\n", |
diff --git a/drivers/net/wireless/ath/ath9k/ar9003_mac.c b/drivers/net/wireless/ath/ath9k/ar9003_mac.c index b363cc06cfd9..631fe4f2e495 100644 --- a/drivers/net/wireless/ath/ath9k/ar9003_mac.c +++ b/drivers/net/wireless/ath/ath9k/ar9003_mac.c | |||
@@ -13,6 +13,7 @@ | |||
13 | * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF | 13 | * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF |
14 | * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. | 14 | * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. |
15 | */ | 15 | */ |
16 | #include <linux/export.h> | ||
16 | #include "hw.h" | 17 | #include "hw.h" |
17 | #include "ar9003_mac.h" | 18 | #include "ar9003_mac.h" |
18 | 19 | ||
@@ -174,20 +175,24 @@ static bool ar9003_hw_get_isr(struct ath_hw *ah, enum ath9k_int *masked) | |||
174 | u32 isr = 0; | 175 | u32 isr = 0; |
175 | u32 mask2 = 0; | 176 | u32 mask2 = 0; |
176 | struct ath9k_hw_capabilities *pCap = &ah->caps; | 177 | struct ath9k_hw_capabilities *pCap = &ah->caps; |
177 | u32 sync_cause = 0; | ||
178 | struct ath_common *common = ath9k_hw_common(ah); | 178 | struct ath_common *common = ath9k_hw_common(ah); |
179 | struct ath9k_hw_mci *mci = &ah->btcoex_hw.mci; | ||
180 | u32 sync_cause = 0, async_cause; | ||
179 | 181 | ||
180 | if (REG_READ(ah, AR_INTR_ASYNC_CAUSE) & AR_INTR_MAC_IRQ) { | 182 | async_cause = REG_READ(ah, AR_INTR_ASYNC_CAUSE); |
183 | |||
184 | if (async_cause & (AR_INTR_MAC_IRQ | AR_INTR_ASYNC_MASK_MCI)) { | ||
181 | if ((REG_READ(ah, AR_RTC_STATUS) & AR_RTC_STATUS_M) | 185 | if ((REG_READ(ah, AR_RTC_STATUS) & AR_RTC_STATUS_M) |
182 | == AR_RTC_STATUS_ON) | 186 | == AR_RTC_STATUS_ON) |
183 | isr = REG_READ(ah, AR_ISR); | 187 | isr = REG_READ(ah, AR_ISR); |
184 | } | 188 | } |
185 | 189 | ||
190 | |||
186 | sync_cause = REG_READ(ah, AR_INTR_SYNC_CAUSE) & AR_INTR_SYNC_DEFAULT; | 191 | sync_cause = REG_READ(ah, AR_INTR_SYNC_CAUSE) & AR_INTR_SYNC_DEFAULT; |
187 | 192 | ||
188 | *masked = 0; | 193 | *masked = 0; |
189 | 194 | ||
190 | if (!isr && !sync_cause) | 195 | if (!isr && !sync_cause && !async_cause) |
191 | return false; | 196 | return false; |
192 | 197 | ||
193 | if (isr) { | 198 | if (isr) { |
@@ -293,6 +298,35 @@ static bool ar9003_hw_get_isr(struct ath_hw *ah, enum ath9k_int *masked) | |||
293 | ar9003_hw_bb_watchdog_read(ah); | 298 | ar9003_hw_bb_watchdog_read(ah); |
294 | } | 299 | } |
295 | 300 | ||
301 | if (async_cause & AR_INTR_ASYNC_MASK_MCI) { | ||
302 | u32 raw_intr, rx_msg_intr; | ||
303 | |||
304 | rx_msg_intr = REG_READ(ah, AR_MCI_INTERRUPT_RX_MSG_RAW); | ||
305 | raw_intr = REG_READ(ah, AR_MCI_INTERRUPT_RAW); | ||
306 | |||
307 | if ((raw_intr == 0xdeadbeef) || (rx_msg_intr == 0xdeadbeef)) | ||
308 | ath_dbg(common, ATH_DBG_MCI, | ||
309 | "MCI gets 0xdeadbeef during MCI int processing" | ||
310 | "new raw_intr=0x%08x, new rx_msg_raw=0x%08x, " | ||
311 | "raw_intr=0x%08x, rx_msg_raw=0x%08x\n", | ||
312 | raw_intr, rx_msg_intr, mci->raw_intr, | ||
313 | mci->rx_msg_intr); | ||
314 | else { | ||
315 | mci->rx_msg_intr |= rx_msg_intr; | ||
316 | mci->raw_intr |= raw_intr; | ||
317 | *masked |= ATH9K_INT_MCI; | ||
318 | |||
319 | if (rx_msg_intr & AR_MCI_INTERRUPT_RX_MSG_CONT_INFO) | ||
320 | mci->cont_status = | ||
321 | REG_READ(ah, AR_MCI_CONT_STATUS); | ||
322 | |||
323 | REG_WRITE(ah, AR_MCI_INTERRUPT_RX_MSG_RAW, rx_msg_intr); | ||
324 | REG_WRITE(ah, AR_MCI_INTERRUPT_RAW, raw_intr); | ||
325 | ath_dbg(common, ATH_DBG_MCI, "AR_INTR_SYNC_MCI\n"); | ||
326 | |||
327 | } | ||
328 | } | ||
329 | |||
296 | if (sync_cause) { | 330 | if (sync_cause) { |
297 | if (sync_cause & AR_INTR_SYNC_RADM_CPL_TIMEOUT) { | 331 | if (sync_cause & AR_INTR_SYNC_RADM_CPL_TIMEOUT) { |
298 | REG_WRITE(ah, AR_RC, AR_RC_HOSTIF); | 332 | REG_WRITE(ah, AR_RC, AR_RC_HOSTIF); |
diff --git a/drivers/net/wireless/ath/ath9k/ar9003_mci.c b/drivers/net/wireless/ath/ath9k/ar9003_mci.c new file mode 100644 index 000000000000..8599822dc83f --- /dev/null +++ b/drivers/net/wireless/ath/ath9k/ar9003_mci.c | |||
@@ -0,0 +1,1464 @@ | |||
1 | /* | ||
2 | * Copyright (c) 2008-2011 Atheros Communications Inc. | ||
3 | * | ||
4 | * Permission to use, copy, modify, and/or distribute this software for any | ||
5 | * purpose with or without fee is hereby granted, provided that the above | ||
6 | * copyright notice and this permission notice appear in all copies. | ||
7 | * | ||
8 | * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES | ||
9 | * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF | ||
10 | * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR | ||
11 | * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES | ||
12 | * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN | ||
13 | * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF | ||
14 | * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. | ||
15 | */ | ||
16 | |||
17 | #include <linux/export.h> | ||
18 | #include "hw.h" | ||
19 | #include "ar9003_phy.h" | ||
20 | #include "ar9003_mci.h" | ||
21 | |||
22 | static void ar9003_mci_reset_req_wakeup(struct ath_hw *ah) | ||
23 | { | ||
24 | if (!AR_SREV_9462_20(ah)) | ||
25 | return; | ||
26 | |||
27 | REG_RMW_FIELD(ah, AR_MCI_COMMAND2, | ||
28 | AR_MCI_COMMAND2_RESET_REQ_WAKEUP, 1); | ||
29 | udelay(1); | ||
30 | REG_RMW_FIELD(ah, AR_MCI_COMMAND2, | ||
31 | AR_MCI_COMMAND2_RESET_REQ_WAKEUP, 0); | ||
32 | } | ||
33 | |||
34 | static int ar9003_mci_wait_for_interrupt(struct ath_hw *ah, u32 address, | ||
35 | u32 bit_position, int time_out) | ||
36 | { | ||
37 | struct ath_common *common = ath9k_hw_common(ah); | ||
38 | |||
39 | while (time_out) { | ||
40 | |||
41 | if (REG_READ(ah, address) & bit_position) { | ||
42 | |||
43 | REG_WRITE(ah, address, bit_position); | ||
44 | |||
45 | if (address == AR_MCI_INTERRUPT_RX_MSG_RAW) { | ||
46 | |||
47 | if (bit_position & | ||
48 | AR_MCI_INTERRUPT_RX_MSG_REQ_WAKE) | ||
49 | ar9003_mci_reset_req_wakeup(ah); | ||
50 | |||
51 | if (bit_position & | ||
52 | (AR_MCI_INTERRUPT_RX_MSG_SYS_SLEEPING | | ||
53 | AR_MCI_INTERRUPT_RX_MSG_SYS_WAKING)) | ||
54 | REG_WRITE(ah, AR_MCI_INTERRUPT_RAW, | ||
55 | AR_MCI_INTERRUPT_REMOTE_SLEEP_UPDATE); | ||
56 | |||
57 | REG_WRITE(ah, AR_MCI_INTERRUPT_RAW, | ||
58 | AR_MCI_INTERRUPT_RX_MSG); | ||
59 | } | ||
60 | break; | ||
61 | } | ||
62 | |||
63 | udelay(10); | ||
64 | time_out -= 10; | ||
65 | |||
66 | if (time_out < 0) | ||
67 | break; | ||
68 | } | ||
69 | |||
70 | if (time_out <= 0) { | ||
71 | ath_dbg(common, ATH_DBG_MCI, | ||
72 | "MCI Wait for Reg 0x%08x = 0x%08x timeout.\n", | ||
73 | address, bit_position); | ||
74 | ath_dbg(common, ATH_DBG_MCI, | ||
75 | "MCI INT_RAW = 0x%08x, RX_MSG_RAW = 0x%08x", | ||
76 | REG_READ(ah, AR_MCI_INTERRUPT_RAW), | ||
77 | REG_READ(ah, AR_MCI_INTERRUPT_RX_MSG_RAW)); | ||
78 | time_out = 0; | ||
79 | } | ||
80 | |||
81 | return time_out; | ||
82 | } | ||
83 | |||
84 | void ar9003_mci_remote_reset(struct ath_hw *ah, bool wait_done) | ||
85 | { | ||
86 | u32 payload[4] = { 0xffffffff, 0xffffffff, 0xffffffff, 0xffffff00}; | ||
87 | |||
88 | ar9003_mci_send_message(ah, MCI_REMOTE_RESET, 0, payload, 16, | ||
89 | wait_done, false); | ||
90 | udelay(5); | ||
91 | } | ||
92 | |||
93 | void ar9003_mci_send_lna_transfer(struct ath_hw *ah, bool wait_done) | ||
94 | { | ||
95 | u32 payload = 0x00000000; | ||
96 | |||
97 | ar9003_mci_send_message(ah, MCI_LNA_TRANS, 0, &payload, 1, | ||
98 | wait_done, false); | ||
99 | } | ||
100 | |||
101 | static void ar9003_mci_send_req_wake(struct ath_hw *ah, bool wait_done) | ||
102 | { | ||
103 | ar9003_mci_send_message(ah, MCI_REQ_WAKE, MCI_FLAG_DISABLE_TIMESTAMP, | ||
104 | NULL, 0, wait_done, false); | ||
105 | udelay(5); | ||
106 | } | ||
107 | |||
108 | void ar9003_mci_send_sys_waking(struct ath_hw *ah, bool wait_done) | ||
109 | { | ||
110 | ar9003_mci_send_message(ah, MCI_SYS_WAKING, MCI_FLAG_DISABLE_TIMESTAMP, | ||
111 | NULL, 0, wait_done, false); | ||
112 | } | ||
113 | |||
114 | static void ar9003_mci_send_lna_take(struct ath_hw *ah, bool wait_done) | ||
115 | { | ||
116 | u32 payload = 0x70000000; | ||
117 | |||
118 | ar9003_mci_send_message(ah, MCI_LNA_TAKE, 0, &payload, 1, | ||
119 | wait_done, false); | ||
120 | } | ||
121 | |||
122 | static void ar9003_mci_send_sys_sleeping(struct ath_hw *ah, bool wait_done) | ||
123 | { | ||
124 | ar9003_mci_send_message(ah, MCI_SYS_SLEEPING, | ||
125 | MCI_FLAG_DISABLE_TIMESTAMP, | ||
126 | NULL, 0, wait_done, false); | ||
127 | } | ||
128 | |||
129 | static void ar9003_mci_send_coex_version_query(struct ath_hw *ah, | ||
130 | bool wait_done) | ||
131 | { | ||
132 | struct ath_common *common = ath9k_hw_common(ah); | ||
133 | struct ath9k_hw_mci *mci = &ah->btcoex_hw.mci; | ||
134 | u32 payload[4] = {0, 0, 0, 0}; | ||
135 | |||
136 | if (!mci->bt_version_known && | ||
137 | (mci->bt_state != MCI_BT_SLEEP)) { | ||
138 | ath_dbg(common, ATH_DBG_MCI, "MCI Send Coex version query\n"); | ||
139 | MCI_GPM_SET_TYPE_OPCODE(payload, | ||
140 | MCI_GPM_COEX_AGENT, MCI_GPM_COEX_VERSION_QUERY); | ||
141 | ar9003_mci_send_message(ah, MCI_GPM, 0, payload, 16, | ||
142 | wait_done, true); | ||
143 | } | ||
144 | } | ||
145 | |||
146 | static void ar9003_mci_send_coex_version_response(struct ath_hw *ah, | ||
147 | bool wait_done) | ||
148 | { | ||
149 | struct ath_common *common = ath9k_hw_common(ah); | ||
150 | struct ath9k_hw_mci *mci = &ah->btcoex_hw.mci; | ||
151 | u32 payload[4] = {0, 0, 0, 0}; | ||
152 | |||
153 | ath_dbg(common, ATH_DBG_MCI, "MCI Send Coex version response\n"); | ||
154 | MCI_GPM_SET_TYPE_OPCODE(payload, MCI_GPM_COEX_AGENT, | ||
155 | MCI_GPM_COEX_VERSION_RESPONSE); | ||
156 | *(((u8 *)payload) + MCI_GPM_COEX_B_MAJOR_VERSION) = | ||
157 | mci->wlan_ver_major; | ||
158 | *(((u8 *)payload) + MCI_GPM_COEX_B_MINOR_VERSION) = | ||
159 | mci->wlan_ver_minor; | ||
160 | ar9003_mci_send_message(ah, MCI_GPM, 0, payload, 16, wait_done, true); | ||
161 | } | ||
162 | |||
163 | static void ar9003_mci_send_coex_wlan_channels(struct ath_hw *ah, | ||
164 | bool wait_done) | ||
165 | { | ||
166 | struct ath9k_hw_mci *mci = &ah->btcoex_hw.mci; | ||
167 | u32 *payload = &mci->wlan_channels[0]; | ||
168 | |||
169 | if ((mci->wlan_channels_update == true) && | ||
170 | (mci->bt_state != MCI_BT_SLEEP)) { | ||
171 | MCI_GPM_SET_TYPE_OPCODE(payload, | ||
172 | MCI_GPM_COEX_AGENT, MCI_GPM_COEX_WLAN_CHANNELS); | ||
173 | ar9003_mci_send_message(ah, MCI_GPM, 0, payload, 16, | ||
174 | wait_done, true); | ||
175 | MCI_GPM_SET_TYPE_OPCODE(payload, 0xff, 0xff); | ||
176 | } | ||
177 | } | ||
178 | |||
179 | static void ar9003_mci_send_coex_bt_status_query(struct ath_hw *ah, | ||
180 | bool wait_done, u8 query_type) | ||
181 | { | ||
182 | struct ath_common *common = ath9k_hw_common(ah); | ||
183 | struct ath9k_hw_mci *mci = &ah->btcoex_hw.mci; | ||
184 | u32 payload[4] = {0, 0, 0, 0}; | ||
185 | bool query_btinfo = !!(query_type & (MCI_GPM_COEX_QUERY_BT_ALL_INFO | | ||
186 | MCI_GPM_COEX_QUERY_BT_TOPOLOGY)); | ||
187 | |||
188 | if (mci->bt_state != MCI_BT_SLEEP) { | ||
189 | |||
190 | ath_dbg(common, ATH_DBG_MCI, | ||
191 | "MCI Send Coex BT Status Query 0x%02X\n", query_type); | ||
192 | |||
193 | MCI_GPM_SET_TYPE_OPCODE(payload, | ||
194 | MCI_GPM_COEX_AGENT, MCI_GPM_COEX_STATUS_QUERY); | ||
195 | |||
196 | *(((u8 *)payload) + MCI_GPM_COEX_B_BT_BITMAP) = query_type; | ||
197 | /* | ||
198 | * If bt_status_query message is not sent successfully, | ||
199 | * then need_flush_btinfo should be set again. | ||
200 | */ | ||
201 | if (!ar9003_mci_send_message(ah, MCI_GPM, 0, payload, 16, | ||
202 | wait_done, true)) { | ||
203 | if (query_btinfo) { | ||
204 | mci->need_flush_btinfo = true; | ||
205 | |||
206 | ath_dbg(common, ATH_DBG_MCI, | ||
207 | "MCI send bt_status_query fail, " | ||
208 | "set flush flag again\n"); | ||
209 | } | ||
210 | } | ||
211 | |||
212 | if (query_btinfo) | ||
213 | mci->query_bt = false; | ||
214 | } | ||
215 | } | ||
216 | |||
217 | void ar9003_mci_send_coex_halt_bt_gpm(struct ath_hw *ah, bool halt, | ||
218 | bool wait_done) | ||
219 | { | ||
220 | struct ath_common *common = ath9k_hw_common(ah); | ||
221 | struct ath9k_hw_mci *mci = &ah->btcoex_hw.mci; | ||
222 | u32 payload[4] = {0, 0, 0, 0}; | ||
223 | |||
224 | ath_dbg(common, ATH_DBG_MCI, "MCI Send Coex %s BT GPM.\n", | ||
225 | (halt) ? "halt" : "unhalt"); | ||
226 | |||
227 | MCI_GPM_SET_TYPE_OPCODE(payload, | ||
228 | MCI_GPM_COEX_AGENT, MCI_GPM_COEX_HALT_BT_GPM); | ||
229 | |||
230 | if (halt) { | ||
231 | mci->query_bt = true; | ||
232 | /* Send next unhalt no matter halt sent or not */ | ||
233 | mci->unhalt_bt_gpm = true; | ||
234 | mci->need_flush_btinfo = true; | ||
235 | *(((u8 *)payload) + MCI_GPM_COEX_B_HALT_STATE) = | ||
236 | MCI_GPM_COEX_BT_GPM_HALT; | ||
237 | } else | ||
238 | *(((u8 *)payload) + MCI_GPM_COEX_B_HALT_STATE) = | ||
239 | MCI_GPM_COEX_BT_GPM_UNHALT; | ||
240 | |||
241 | ar9003_mci_send_message(ah, MCI_GPM, 0, payload, 16, wait_done, true); | ||
242 | } | ||
243 | |||
244 | |||
245 | static void ar9003_mci_prep_interface(struct ath_hw *ah) | ||
246 | { | ||
247 | struct ath_common *common = ath9k_hw_common(ah); | ||
248 | struct ath9k_hw_mci *mci = &ah->btcoex_hw.mci; | ||
249 | u32 saved_mci_int_en; | ||
250 | u32 mci_timeout = 150; | ||
251 | |||
252 | mci->bt_state = MCI_BT_SLEEP; | ||
253 | saved_mci_int_en = REG_READ(ah, AR_MCI_INTERRUPT_EN); | ||
254 | |||
255 | REG_WRITE(ah, AR_MCI_INTERRUPT_EN, 0); | ||
256 | REG_WRITE(ah, AR_MCI_INTERRUPT_RX_MSG_RAW, | ||
257 | REG_READ(ah, AR_MCI_INTERRUPT_RX_MSG_RAW)); | ||
258 | REG_WRITE(ah, AR_MCI_INTERRUPT_RAW, | ||
259 | REG_READ(ah, AR_MCI_INTERRUPT_RAW)); | ||
260 | |||
261 | /* Remote Reset */ | ||
262 | ath_dbg(common, ATH_DBG_MCI, "MCI Reset sequence start\n"); | ||
263 | ath_dbg(common, ATH_DBG_MCI, "MCI send REMOTE_RESET\n"); | ||
264 | ar9003_mci_remote_reset(ah, true); | ||
265 | |||
266 | /* | ||
267 | * This delay is required for the reset delay worst case value 255 in | ||
268 | * MCI_COMMAND2 register | ||
269 | */ | ||
270 | |||
271 | if (AR_SREV_9462_10(ah)) | ||
272 | udelay(252); | ||
273 | |||
274 | ath_dbg(common, ATH_DBG_MCI, "MCI Send REQ_WAKE to remoter(BT)\n"); | ||
275 | ar9003_mci_send_req_wake(ah, true); | ||
276 | |||
277 | if (ar9003_mci_wait_for_interrupt(ah, AR_MCI_INTERRUPT_RX_MSG_RAW, | ||
278 | AR_MCI_INTERRUPT_RX_MSG_SYS_WAKING, 500)) { | ||
279 | |||
280 | ath_dbg(common, ATH_DBG_MCI, | ||
281 | "MCI SYS_WAKING from remote(BT)\n"); | ||
282 | mci->bt_state = MCI_BT_AWAKE; | ||
283 | |||
284 | if (AR_SREV_9462_10(ah)) | ||
285 | udelay(10); | ||
286 | /* | ||
287 | * we don't need to send more remote_reset at this moment. | ||
288 | * If BT receive first remote_reset, then BT HW will | ||
289 | * be cleaned up and will be able to receive req_wake | ||
290 | * and BT HW will respond sys_waking. | ||
291 | * In this case, WLAN will receive BT's HW sys_waking. | ||
292 | * Otherwise, if BT SW missed initial remote_reset, | ||
293 | * that remote_reset will still clean up BT MCI RX, | ||
294 | * and the req_wake will wake BT up, | ||
295 | * and BT SW will respond this req_wake with a remote_reset and | ||
296 | * sys_waking. In this case, WLAN will receive BT's SW | ||
297 | * sys_waking. In either case, BT's RX is cleaned up. So we | ||
298 | * don't need to reply BT's remote_reset now, if any. | ||
299 | * Similarly, if in any case, WLAN can receive BT's sys_waking, | ||
300 | * that means WLAN's RX is also fine. | ||
301 | */ | ||
302 | |||
303 | /* Send SYS_WAKING to BT */ | ||
304 | |||
305 | ath_dbg(common, ATH_DBG_MCI, | ||
306 | "MCI send SW SYS_WAKING to remote BT\n"); | ||
307 | |||
308 | ar9003_mci_send_sys_waking(ah, true); | ||
309 | udelay(10); | ||
310 | |||
311 | /* | ||
312 | * Set BT priority interrupt value to be 0xff to | ||
313 | * avoid having too many BT PRIORITY interrupts. | ||
314 | */ | ||
315 | |||
316 | REG_WRITE(ah, AR_MCI_BT_PRI0, 0xFFFFFFFF); | ||
317 | REG_WRITE(ah, AR_MCI_BT_PRI1, 0xFFFFFFFF); | ||
318 | REG_WRITE(ah, AR_MCI_BT_PRI2, 0xFFFFFFFF); | ||
319 | REG_WRITE(ah, AR_MCI_BT_PRI3, 0xFFFFFFFF); | ||
320 | REG_WRITE(ah, AR_MCI_BT_PRI, 0X000000FF); | ||
321 | |||
322 | /* | ||
323 | * A contention reset will be received after send out | ||
324 | * sys_waking. Also BT priority interrupt bits will be set. | ||
325 | * Clear those bits before the next step. | ||
326 | */ | ||
327 | |||
328 | REG_WRITE(ah, AR_MCI_INTERRUPT_RX_MSG_RAW, | ||
329 | AR_MCI_INTERRUPT_RX_MSG_CONT_RST); | ||
330 | REG_WRITE(ah, AR_MCI_INTERRUPT_RAW, | ||
331 | AR_MCI_INTERRUPT_BT_PRI); | ||
332 | |||
333 | if (AR_SREV_9462_10(ah) || mci->is_2g) { | ||
334 | /* Send LNA_TRANS */ | ||
335 | ath_dbg(common, ATH_DBG_MCI, | ||
336 | "MCI send LNA_TRANS to BT\n"); | ||
337 | ar9003_mci_send_lna_transfer(ah, true); | ||
338 | udelay(5); | ||
339 | } | ||
340 | |||
341 | if (AR_SREV_9462_10(ah) || (mci->is_2g && | ||
342 | !mci->update_2g5g)) { | ||
343 | if (ar9003_mci_wait_for_interrupt(ah, | ||
344 | AR_MCI_INTERRUPT_RX_MSG_RAW, | ||
345 | AR_MCI_INTERRUPT_RX_MSG_LNA_INFO, | ||
346 | mci_timeout)) | ||
347 | ath_dbg(common, ATH_DBG_MCI, | ||
348 | "MCI WLAN has control over the LNA & " | ||
349 | "BT obeys it\n"); | ||
350 | else | ||
351 | ath_dbg(common, ATH_DBG_MCI, | ||
352 | "MCI BT didn't respond to" | ||
353 | "LNA_TRANS\n"); | ||
354 | } | ||
355 | |||
356 | if (AR_SREV_9462_10(ah)) { | ||
357 | /* Send another remote_reset to deassert BT clk_req. */ | ||
358 | ath_dbg(common, ATH_DBG_MCI, | ||
359 | "MCI another remote_reset to " | ||
360 | "deassert clk_req\n"); | ||
361 | ar9003_mci_remote_reset(ah, true); | ||
362 | udelay(252); | ||
363 | } | ||
364 | } | ||
365 | |||
366 | /* Clear the extra redundant SYS_WAKING from BT */ | ||
367 | if ((mci->bt_state == MCI_BT_AWAKE) && | ||
368 | (REG_READ_FIELD(ah, AR_MCI_INTERRUPT_RX_MSG_RAW, | ||
369 | AR_MCI_INTERRUPT_RX_MSG_SYS_WAKING)) && | ||
370 | (REG_READ_FIELD(ah, AR_MCI_INTERRUPT_RX_MSG_RAW, | ||
371 | AR_MCI_INTERRUPT_RX_MSG_SYS_SLEEPING) == 0)) { | ||
372 | |||
373 | REG_WRITE(ah, AR_MCI_INTERRUPT_RX_MSG_RAW, | ||
374 | AR_MCI_INTERRUPT_RX_MSG_SYS_WAKING); | ||
375 | REG_WRITE(ah, AR_MCI_INTERRUPT_RAW, | ||
376 | AR_MCI_INTERRUPT_REMOTE_SLEEP_UPDATE); | ||
377 | } | ||
378 | |||
379 | REG_WRITE(ah, AR_MCI_INTERRUPT_EN, saved_mci_int_en); | ||
380 | } | ||
381 | |||
382 | void ar9003_mci_disable_interrupt(struct ath_hw *ah) | ||
383 | { | ||
384 | REG_WRITE(ah, AR_MCI_INTERRUPT_EN, 0); | ||
385 | REG_WRITE(ah, AR_MCI_INTERRUPT_RX_MSG_EN, 0); | ||
386 | } | ||
387 | |||
388 | void ar9003_mci_enable_interrupt(struct ath_hw *ah) | ||
389 | { | ||
390 | |||
391 | REG_WRITE(ah, AR_MCI_INTERRUPT_EN, AR_MCI_INTERRUPT_DEFAULT); | ||
392 | REG_WRITE(ah, AR_MCI_INTERRUPT_RX_MSG_EN, | ||
393 | AR_MCI_INTERRUPT_RX_MSG_DEFAULT); | ||
394 | } | ||
395 | |||
396 | bool ar9003_mci_check_int(struct ath_hw *ah, u32 ints) | ||
397 | { | ||
398 | u32 intr; | ||
399 | |||
400 | intr = REG_READ(ah, AR_MCI_INTERRUPT_RX_MSG_RAW); | ||
401 | return ((intr & ints) == ints); | ||
402 | } | ||
403 | |||
404 | void ar9003_mci_get_interrupt(struct ath_hw *ah, u32 *raw_intr, | ||
405 | u32 *rx_msg_intr) | ||
406 | { | ||
407 | struct ath9k_hw_mci *mci = &ah->btcoex_hw.mci; | ||
408 | *raw_intr = mci->raw_intr; | ||
409 | *rx_msg_intr = mci->rx_msg_intr; | ||
410 | |||
411 | /* Clean int bits after the values are read. */ | ||
412 | mci->raw_intr = 0; | ||
413 | mci->rx_msg_intr = 0; | ||
414 | } | ||
415 | EXPORT_SYMBOL(ar9003_mci_get_interrupt); | ||
416 | |||
417 | void ar9003_mci_2g5g_changed(struct ath_hw *ah, bool is_2g) | ||
418 | { | ||
419 | struct ath9k_hw_mci *mci = &ah->btcoex_hw.mci; | ||
420 | |||
421 | if (!mci->update_2g5g && | ||
422 | (mci->is_2g != is_2g)) | ||
423 | mci->update_2g5g = true; | ||
424 | |||
425 | mci->is_2g = is_2g; | ||
426 | } | ||
427 | |||
428 | static bool ar9003_mci_is_gpm_valid(struct ath_hw *ah, u32 msg_index) | ||
429 | { | ||
430 | struct ath_common *common = ath9k_hw_common(ah); | ||
431 | struct ath9k_hw_mci *mci = &ah->btcoex_hw.mci; | ||
432 | u32 *payload; | ||
433 | u32 recv_type, offset; | ||
434 | |||
435 | if (msg_index == MCI_GPM_INVALID) | ||
436 | return false; | ||
437 | |||
438 | offset = msg_index << 4; | ||
439 | |||
440 | payload = (u32 *)(mci->gpm_buf + offset); | ||
441 | recv_type = MCI_GPM_TYPE(payload); | ||
442 | |||
443 | if (recv_type == MCI_GPM_RSVD_PATTERN) { | ||
444 | ath_dbg(common, ATH_DBG_MCI, "MCI Skip RSVD GPM\n"); | ||
445 | return false; | ||
446 | } | ||
447 | |||
448 | return true; | ||
449 | } | ||
450 | |||
451 | static void ar9003_mci_observation_set_up(struct ath_hw *ah) | ||
452 | { | ||
453 | struct ath9k_hw_mci *mci = &ah->btcoex_hw.mci; | ||
454 | if (mci->config & ATH_MCI_CONFIG_MCI_OBS_MCI) { | ||
455 | |||
456 | ath9k_hw_cfg_output(ah, 3, | ||
457 | AR_GPIO_OUTPUT_MUX_AS_MCI_WLAN_DATA); | ||
458 | ath9k_hw_cfg_output(ah, 2, AR_GPIO_OUTPUT_MUX_AS_MCI_WLAN_CLK); | ||
459 | ath9k_hw_cfg_output(ah, 1, AR_GPIO_OUTPUT_MUX_AS_MCI_BT_DATA); | ||
460 | ath9k_hw_cfg_output(ah, 0, AR_GPIO_OUTPUT_MUX_AS_MCI_BT_CLK); | ||
461 | |||
462 | } else if (mci->config & ATH_MCI_CONFIG_MCI_OBS_TXRX) { | ||
463 | |||
464 | ath9k_hw_cfg_output(ah, 3, AR_GPIO_OUTPUT_MUX_AS_WL_IN_TX); | ||
465 | ath9k_hw_cfg_output(ah, 2, AR_GPIO_OUTPUT_MUX_AS_WL_IN_RX); | ||
466 | ath9k_hw_cfg_output(ah, 1, AR_GPIO_OUTPUT_MUX_AS_BT_IN_TX); | ||
467 | ath9k_hw_cfg_output(ah, 0, AR_GPIO_OUTPUT_MUX_AS_BT_IN_RX); | ||
468 | ath9k_hw_cfg_output(ah, 5, AR_GPIO_OUTPUT_MUX_AS_OUTPUT); | ||
469 | |||
470 | } else if (mci->config & ATH_MCI_CONFIG_MCI_OBS_BT) { | ||
471 | |||
472 | ath9k_hw_cfg_output(ah, 3, AR_GPIO_OUTPUT_MUX_AS_BT_IN_TX); | ||
473 | ath9k_hw_cfg_output(ah, 2, AR_GPIO_OUTPUT_MUX_AS_BT_IN_RX); | ||
474 | ath9k_hw_cfg_output(ah, 1, AR_GPIO_OUTPUT_MUX_AS_MCI_BT_DATA); | ||
475 | ath9k_hw_cfg_output(ah, 0, AR_GPIO_OUTPUT_MUX_AS_MCI_BT_CLK); | ||
476 | |||
477 | } else | ||
478 | return; | ||
479 | |||
480 | REG_SET_BIT(ah, AR_GPIO_INPUT_EN_VAL, AR_GPIO_JTAG_DISABLE); | ||
481 | |||
482 | if (AR_SREV_9462_20_OR_LATER(ah)) { | ||
483 | REG_RMW_FIELD(ah, AR_PHY_GLB_CONTROL, | ||
484 | AR_GLB_DS_JTAG_DISABLE, 1); | ||
485 | REG_RMW_FIELD(ah, AR_PHY_GLB_CONTROL, | ||
486 | AR_GLB_WLAN_UART_INTF_EN, 0); | ||
487 | REG_SET_BIT(ah, AR_GLB_GPIO_CONTROL, | ||
488 | ATH_MCI_CONFIG_MCI_OBS_GPIO); | ||
489 | } | ||
490 | |||
491 | REG_RMW_FIELD(ah, AR_BTCOEX_CTRL2, AR_BTCOEX_CTRL2_GPIO_OBS_SEL, 0); | ||
492 | REG_RMW_FIELD(ah, AR_BTCOEX_CTRL2, AR_BTCOEX_CTRL2_MAC_BB_OBS_SEL, 1); | ||
493 | REG_WRITE(ah, AR_OBS, 0x4b); | ||
494 | REG_RMW_FIELD(ah, AR_DIAG_SW, AR_DIAG_OBS_PT_SEL1, 0x03); | ||
495 | REG_RMW_FIELD(ah, AR_DIAG_SW, AR_DIAG_OBS_PT_SEL2, 0x01); | ||
496 | REG_RMW_FIELD(ah, AR_MACMISC, AR_MACMISC_MISC_OBS_BUS_LSB, 0x02); | ||
497 | REG_RMW_FIELD(ah, AR_MACMISC, AR_MACMISC_MISC_OBS_BUS_MSB, 0x03); | ||
498 | REG_RMW_FIELD(ah, AR_PHY_TEST_CTL_STATUS, | ||
499 | AR_PHY_TEST_CTL_DEBUGPORT_SEL, 0x07); | ||
500 | } | ||
501 | |||
502 | static bool ar9003_mci_send_coex_bt_flags(struct ath_hw *ah, bool wait_done, | ||
503 | u8 opcode, u32 bt_flags) | ||
504 | { | ||
505 | struct ath_common *common = ath9k_hw_common(ah); | ||
506 | u32 pld[4] = {0, 0, 0, 0}; | ||
507 | |||
508 | MCI_GPM_SET_TYPE_OPCODE(pld, | ||
509 | MCI_GPM_COEX_AGENT, MCI_GPM_COEX_BT_UPDATE_FLAGS); | ||
510 | |||
511 | *(((u8 *)pld) + MCI_GPM_COEX_B_BT_FLAGS_OP) = opcode; | ||
512 | *(((u8 *)pld) + MCI_GPM_COEX_W_BT_FLAGS + 0) = bt_flags & 0xFF; | ||
513 | *(((u8 *)pld) + MCI_GPM_COEX_W_BT_FLAGS + 1) = (bt_flags >> 8) & 0xFF; | ||
514 | *(((u8 *)pld) + MCI_GPM_COEX_W_BT_FLAGS + 2) = (bt_flags >> 16) & 0xFF; | ||
515 | *(((u8 *)pld) + MCI_GPM_COEX_W_BT_FLAGS + 3) = (bt_flags >> 24) & 0xFF; | ||
516 | |||
517 | ath_dbg(common, ATH_DBG_MCI, | ||
518 | "MCI BT_MCI_FLAGS: Send Coex BT Update Flags %s 0x%08x\n", | ||
519 | (opcode == MCI_GPM_COEX_BT_FLAGS_READ) ? "READ" : | ||
520 | ((opcode == MCI_GPM_COEX_BT_FLAGS_SET) ? "SET" : "CLEAR"), | ||
521 | bt_flags); | ||
522 | |||
523 | return ar9003_mci_send_message(ah, MCI_GPM, 0, pld, 16, | ||
524 | wait_done, true); | ||
525 | } | ||
526 | |||
527 | void ar9003_mci_reset(struct ath_hw *ah, bool en_int, bool is_2g, | ||
528 | bool is_full_sleep) | ||
529 | { | ||
530 | struct ath_common *common = ath9k_hw_common(ah); | ||
531 | struct ath9k_hw_mci *mci = &ah->btcoex_hw.mci; | ||
532 | u32 regval, thresh; | ||
533 | |||
534 | ath_dbg(common, ATH_DBG_MCI, "MCI full_sleep = %d, is_2g = %d\n", | ||
535 | is_full_sleep, is_2g); | ||
536 | |||
537 | /* | ||
538 | * GPM buffer and scheduling message buffer are not allocated | ||
539 | */ | ||
540 | |||
541 | if (!mci->gpm_addr && !mci->sched_addr) { | ||
542 | ath_dbg(common, ATH_DBG_MCI, | ||
543 | "MCI GPM and schedule buffers are not allocated"); | ||
544 | return; | ||
545 | } | ||
546 | |||
547 | if (REG_READ(ah, AR_BTCOEX_CTRL) == 0xdeadbeef) { | ||
548 | ath_dbg(common, ATH_DBG_MCI, | ||
549 | "MCI it's deadbeef, quit mci_reset\n"); | ||
550 | return; | ||
551 | } | ||
552 | |||
553 | /* Program MCI DMA related registers */ | ||
554 | REG_WRITE(ah, AR_MCI_GPM_0, mci->gpm_addr); | ||
555 | REG_WRITE(ah, AR_MCI_GPM_1, mci->gpm_len); | ||
556 | REG_WRITE(ah, AR_MCI_SCHD_TABLE_0, mci->sched_addr); | ||
557 | |||
558 | /* | ||
559 | * To avoid MCI state machine be affected by incoming remote MCI msgs, | ||
560 | * MCI mode will be enabled later, right before reset the MCI TX and RX. | ||
561 | */ | ||
562 | |||
563 | regval = SM(1, AR_BTCOEX_CTRL_AR9462_MODE) | | ||
564 | SM(1, AR_BTCOEX_CTRL_WBTIMER_EN) | | ||
565 | SM(1, AR_BTCOEX_CTRL_PA_SHARED) | | ||
566 | SM(1, AR_BTCOEX_CTRL_LNA_SHARED) | | ||
567 | SM(2, AR_BTCOEX_CTRL_NUM_ANTENNAS) | | ||
568 | SM(3, AR_BTCOEX_CTRL_RX_CHAIN_MASK) | | ||
569 | SM(0, AR_BTCOEX_CTRL_1_CHAIN_ACK) | | ||
570 | SM(0, AR_BTCOEX_CTRL_1_CHAIN_BCN) | | ||
571 | SM(0, AR_BTCOEX_CTRL_ONE_STEP_LOOK_AHEAD_EN); | ||
572 | |||
573 | if (is_2g && (AR_SREV_9462_20(ah)) && | ||
574 | !(mci->config & ATH_MCI_CONFIG_DISABLE_OSLA)) { | ||
575 | |||
576 | regval |= SM(1, AR_BTCOEX_CTRL_ONE_STEP_LOOK_AHEAD_EN); | ||
577 | ath_dbg(common, ATH_DBG_MCI, | ||
578 | "MCI sched one step look ahead\n"); | ||
579 | |||
580 | if (!(mci->config & | ||
581 | ATH_MCI_CONFIG_DISABLE_AGGR_THRESH)) { | ||
582 | |||
583 | thresh = MS(mci->config, | ||
584 | ATH_MCI_CONFIG_AGGR_THRESH); | ||
585 | thresh &= 7; | ||
586 | regval |= SM(1, | ||
587 | AR_BTCOEX_CTRL_TIME_TO_NEXT_BT_THRESH_EN); | ||
588 | regval |= SM(thresh, AR_BTCOEX_CTRL_AGGR_THRESH); | ||
589 | |||
590 | REG_RMW_FIELD(ah, AR_MCI_SCHD_TABLE_2, | ||
591 | AR_MCI_SCHD_TABLE_2_HW_BASED, 1); | ||
592 | REG_RMW_FIELD(ah, AR_MCI_SCHD_TABLE_2, | ||
593 | AR_MCI_SCHD_TABLE_2_MEM_BASED, 1); | ||
594 | |||
595 | } else | ||
596 | ath_dbg(common, ATH_DBG_MCI, | ||
597 | "MCI sched aggr thresh: off\n"); | ||
598 | } else | ||
599 | ath_dbg(common, ATH_DBG_MCI, | ||
600 | "MCI SCHED one step look ahead off\n"); | ||
601 | |||
602 | if (AR_SREV_9462_10(ah)) | ||
603 | regval |= SM(1, AR_BTCOEX_CTRL_SPDT_ENABLE_10); | ||
604 | |||
605 | REG_WRITE(ah, AR_BTCOEX_CTRL, regval); | ||
606 | |||
607 | if (AR_SREV_9462_20(ah)) { | ||
608 | REG_SET_BIT(ah, AR_PHY_GLB_CONTROL, | ||
609 | AR_BTCOEX_CTRL_SPDT_ENABLE); | ||
610 | REG_RMW_FIELD(ah, AR_BTCOEX_CTRL3, | ||
611 | AR_BTCOEX_CTRL3_CONT_INFO_TIMEOUT, 20); | ||
612 | } | ||
613 | |||
614 | REG_RMW_FIELD(ah, AR_BTCOEX_CTRL2, AR_BTCOEX_CTRL2_RX_DEWEIGHT, 1); | ||
615 | REG_RMW_FIELD(ah, AR_PCU_MISC, AR_PCU_BT_ANT_PREVENT_RX, 0); | ||
616 | |||
617 | thresh = MS(mci->config, ATH_MCI_CONFIG_CLK_DIV); | ||
618 | REG_RMW_FIELD(ah, AR_MCI_TX_CTRL, AR_MCI_TX_CTRL_CLK_DIV, thresh); | ||
619 | REG_SET_BIT(ah, AR_BTCOEX_CTRL, AR_BTCOEX_CTRL_MCI_MODE_EN); | ||
620 | |||
621 | /* Resetting the Rx and Tx paths of MCI */ | ||
622 | regval = REG_READ(ah, AR_MCI_COMMAND2); | ||
623 | regval |= SM(1, AR_MCI_COMMAND2_RESET_TX); | ||
624 | REG_WRITE(ah, AR_MCI_COMMAND2, regval); | ||
625 | |||
626 | udelay(1); | ||
627 | |||
628 | regval &= ~SM(1, AR_MCI_COMMAND2_RESET_TX); | ||
629 | REG_WRITE(ah, AR_MCI_COMMAND2, regval); | ||
630 | |||
631 | if (is_full_sleep) { | ||
632 | ar9003_mci_mute_bt(ah); | ||
633 | udelay(100); | ||
634 | } | ||
635 | |||
636 | regval |= SM(1, AR_MCI_COMMAND2_RESET_RX); | ||
637 | REG_WRITE(ah, AR_MCI_COMMAND2, regval); | ||
638 | udelay(1); | ||
639 | regval &= ~SM(1, AR_MCI_COMMAND2_RESET_RX); | ||
640 | REG_WRITE(ah, AR_MCI_COMMAND2, regval); | ||
641 | |||
642 | ar9003_mci_state(ah, MCI_STATE_INIT_GPM_OFFSET, NULL); | ||
643 | REG_WRITE(ah, AR_MCI_MSG_ATTRIBUTES_TABLE, | ||
644 | (SM(0xe801, AR_MCI_MSG_ATTRIBUTES_TABLE_INVALID_HDR) | | ||
645 | SM(0x0000, AR_MCI_MSG_ATTRIBUTES_TABLE_CHECKSUM))); | ||
646 | |||
647 | REG_CLR_BIT(ah, AR_MCI_TX_CTRL, | ||
648 | AR_MCI_TX_CTRL_DISABLE_LNA_UPDATE); | ||
649 | |||
650 | if (AR_SREV_9462_20_OR_LATER(ah)) | ||
651 | ar9003_mci_observation_set_up(ah); | ||
652 | |||
653 | mci->ready = true; | ||
654 | ar9003_mci_prep_interface(ah); | ||
655 | |||
656 | if (en_int) | ||
657 | ar9003_mci_enable_interrupt(ah); | ||
658 | } | ||
659 | |||
660 | void ar9003_mci_mute_bt(struct ath_hw *ah) | ||
661 | { | ||
662 | struct ath_common *common = ath9k_hw_common(ah); | ||
663 | |||
664 | /* disable all MCI messages */ | ||
665 | REG_WRITE(ah, AR_MCI_MSG_ATTRIBUTES_TABLE, 0xffff0000); | ||
666 | REG_WRITE(ah, AR_BTCOEX_WL_WEIGHTS0, 0xffffffff); | ||
667 | REG_WRITE(ah, AR_BTCOEX_WL_WEIGHTS1, 0xffffffff); | ||
668 | REG_WRITE(ah, AR_BTCOEX_WL_WEIGHTS2, 0xffffffff); | ||
669 | REG_WRITE(ah, AR_BTCOEX_WL_WEIGHTS3, 0xffffffff); | ||
670 | REG_SET_BIT(ah, AR_MCI_TX_CTRL, AR_MCI_TX_CTRL_DISABLE_LNA_UPDATE); | ||
671 | |||
672 | /* wait pending HW messages to flush out */ | ||
673 | udelay(10); | ||
674 | |||
675 | /* | ||
676 | * Send LNA_TAKE and SYS_SLEEPING when | ||
677 | * 1. reset not after resuming from full sleep | ||
678 | * 2. before reset MCI RX, to quiet BT and avoid MCI RX misalignment | ||
679 | */ | ||
680 | |||
681 | ath_dbg(common, ATH_DBG_MCI, "MCI Send LNA take\n"); | ||
682 | ar9003_mci_send_lna_take(ah, true); | ||
683 | |||
684 | udelay(5); | ||
685 | |||
686 | ath_dbg(common, ATH_DBG_MCI, "MCI Send sys sleeping\n"); | ||
687 | ar9003_mci_send_sys_sleeping(ah, true); | ||
688 | } | ||
689 | |||
690 | void ar9003_mci_sync_bt_state(struct ath_hw *ah) | ||
691 | { | ||
692 | struct ath_common *common = ath9k_hw_common(ah); | ||
693 | struct ath9k_hw_mci *mci = &ah->btcoex_hw.mci; | ||
694 | u32 cur_bt_state; | ||
695 | |||
696 | cur_bt_state = ar9003_mci_state(ah, MCI_STATE_REMOTE_SLEEP, NULL); | ||
697 | |||
698 | if (mci->bt_state != cur_bt_state) { | ||
699 | ath_dbg(common, ATH_DBG_MCI, | ||
700 | "MCI BT state mismatches. old: %d, new: %d\n", | ||
701 | mci->bt_state, cur_bt_state); | ||
702 | mci->bt_state = cur_bt_state; | ||
703 | } | ||
704 | |||
705 | if (mci->bt_state != MCI_BT_SLEEP) { | ||
706 | |||
707 | ar9003_mci_send_coex_version_query(ah, true); | ||
708 | ar9003_mci_send_coex_wlan_channels(ah, true); | ||
709 | |||
710 | if (mci->unhalt_bt_gpm == true) { | ||
711 | ath_dbg(common, ATH_DBG_MCI, "MCI unhalt BT GPM"); | ||
712 | ar9003_mci_send_coex_halt_bt_gpm(ah, false, true); | ||
713 | } | ||
714 | } | ||
715 | } | ||
716 | |||
717 | static void ar9003_mci_send_2g5g_status(struct ath_hw *ah, bool wait_done) | ||
718 | { | ||
719 | struct ath_common *common = ath9k_hw_common(ah); | ||
720 | struct ath9k_hw_mci *mci = &ah->btcoex_hw.mci; | ||
721 | u32 new_flags, to_set, to_clear; | ||
722 | |||
723 | if (AR_SREV_9462_20(ah) && | ||
724 | mci->update_2g5g && | ||
725 | (mci->bt_state != MCI_BT_SLEEP)) { | ||
726 | |||
727 | if (mci->is_2g) { | ||
728 | new_flags = MCI_2G_FLAGS; | ||
729 | to_clear = MCI_2G_FLAGS_CLEAR_MASK; | ||
730 | to_set = MCI_2G_FLAGS_SET_MASK; | ||
731 | } else { | ||
732 | new_flags = MCI_5G_FLAGS; | ||
733 | to_clear = MCI_5G_FLAGS_CLEAR_MASK; | ||
734 | to_set = MCI_5G_FLAGS_SET_MASK; | ||
735 | } | ||
736 | |||
737 | ath_dbg(common, ATH_DBG_MCI, | ||
738 | "MCI BT_MCI_FLAGS: %s 0x%08x clr=0x%08x, set=0x%08x\n", | ||
739 | mci->is_2g ? "2G" : "5G", new_flags, to_clear, to_set); | ||
740 | |||
741 | if (to_clear) | ||
742 | ar9003_mci_send_coex_bt_flags(ah, wait_done, | ||
743 | MCI_GPM_COEX_BT_FLAGS_CLEAR, to_clear); | ||
744 | |||
745 | if (to_set) | ||
746 | ar9003_mci_send_coex_bt_flags(ah, wait_done, | ||
747 | MCI_GPM_COEX_BT_FLAGS_SET, to_set); | ||
748 | } | ||
749 | |||
750 | if (AR_SREV_9462_10(ah) && (mci->bt_state != MCI_BT_SLEEP)) | ||
751 | mci->update_2g5g = false; | ||
752 | } | ||
753 | |||
754 | static void ar9003_mci_queue_unsent_gpm(struct ath_hw *ah, u8 header, | ||
755 | u32 *payload, bool queue) | ||
756 | { | ||
757 | struct ath_common *common = ath9k_hw_common(ah); | ||
758 | struct ath9k_hw_mci *mci = &ah->btcoex_hw.mci; | ||
759 | u8 type, opcode; | ||
760 | |||
761 | if (queue) { | ||
762 | |||
763 | if (payload) | ||
764 | ath_dbg(common, ATH_DBG_MCI, | ||
765 | "MCI ERROR: Send fail: %02x: %02x %02x %02x\n", | ||
766 | header, | ||
767 | *(((u8 *)payload) + 4), | ||
768 | *(((u8 *)payload) + 5), | ||
769 | *(((u8 *)payload) + 6)); | ||
770 | else | ||
771 | ath_dbg(common, ATH_DBG_MCI, | ||
772 | "MCI ERROR: Send fail: %02x\n", header); | ||
773 | } | ||
774 | |||
775 | /* check if the message is to be queued */ | ||
776 | if (header != MCI_GPM) | ||
777 | return; | ||
778 | |||
779 | type = MCI_GPM_TYPE(payload); | ||
780 | opcode = MCI_GPM_OPCODE(payload); | ||
781 | |||
782 | if (type != MCI_GPM_COEX_AGENT) | ||
783 | return; | ||
784 | |||
785 | switch (opcode) { | ||
786 | case MCI_GPM_COEX_BT_UPDATE_FLAGS: | ||
787 | |||
788 | if (AR_SREV_9462_10(ah)) | ||
789 | break; | ||
790 | |||
791 | if (*(((u8 *)payload) + MCI_GPM_COEX_B_BT_FLAGS_OP) == | ||
792 | MCI_GPM_COEX_BT_FLAGS_READ) | ||
793 | break; | ||
794 | |||
795 | mci->update_2g5g = queue; | ||
796 | |||
797 | if (queue) | ||
798 | ath_dbg(common, ATH_DBG_MCI, | ||
799 | "MCI BT_MCI_FLAGS: 2G5G status <queued> %s.\n", | ||
800 | mci->is_2g ? "2G" : "5G"); | ||
801 | else | ||
802 | ath_dbg(common, ATH_DBG_MCI, | ||
803 | "MCI BT_MCI_FLAGS: 2G5G status <sent> %s.\n", | ||
804 | mci->is_2g ? "2G" : "5G"); | ||
805 | |||
806 | break; | ||
807 | |||
808 | case MCI_GPM_COEX_WLAN_CHANNELS: | ||
809 | |||
810 | mci->wlan_channels_update = queue; | ||
811 | if (queue) | ||
812 | ath_dbg(common, ATH_DBG_MCI, | ||
813 | "MCI WLAN channel map <queued>\n"); | ||
814 | else | ||
815 | ath_dbg(common, ATH_DBG_MCI, | ||
816 | "MCI WLAN channel map <sent>\n"); | ||
817 | break; | ||
818 | |||
819 | case MCI_GPM_COEX_HALT_BT_GPM: | ||
820 | |||
821 | if (*(((u8 *)payload) + MCI_GPM_COEX_B_HALT_STATE) == | ||
822 | MCI_GPM_COEX_BT_GPM_UNHALT) { | ||
823 | |||
824 | mci->unhalt_bt_gpm = queue; | ||
825 | |||
826 | if (queue) | ||
827 | ath_dbg(common, ATH_DBG_MCI, | ||
828 | "MCI UNHALT BT GPM <queued>\n"); | ||
829 | else { | ||
830 | mci->halted_bt_gpm = false; | ||
831 | ath_dbg(common, ATH_DBG_MCI, | ||
832 | "MCI UNHALT BT GPM <sent>\n"); | ||
833 | } | ||
834 | } | ||
835 | |||
836 | if (*(((u8 *)payload) + MCI_GPM_COEX_B_HALT_STATE) == | ||
837 | MCI_GPM_COEX_BT_GPM_HALT) { | ||
838 | |||
839 | mci->halted_bt_gpm = !queue; | ||
840 | |||
841 | if (queue) | ||
842 | ath_dbg(common, ATH_DBG_MCI, | ||
843 | "MCI HALT BT GPM <not sent>\n"); | ||
844 | else | ||
845 | ath_dbg(common, ATH_DBG_MCI, | ||
846 | "MCI UNHALT BT GPM <sent>\n"); | ||
847 | } | ||
848 | |||
849 | break; | ||
850 | default: | ||
851 | break; | ||
852 | } | ||
853 | } | ||
854 | |||
855 | void ar9003_mci_2g5g_switch(struct ath_hw *ah, bool wait_done) | ||
856 | { | ||
857 | struct ath_common *common = ath9k_hw_common(ah); | ||
858 | struct ath9k_hw_mci *mci = &ah->btcoex_hw.mci; | ||
859 | |||
860 | if (mci->update_2g5g) { | ||
861 | if (mci->is_2g) { | ||
862 | |||
863 | ar9003_mci_send_2g5g_status(ah, true); | ||
864 | ath_dbg(common, ATH_DBG_MCI, "MCI Send LNA trans\n"); | ||
865 | ar9003_mci_send_lna_transfer(ah, true); | ||
866 | udelay(5); | ||
867 | |||
868 | REG_CLR_BIT(ah, AR_MCI_TX_CTRL, | ||
869 | AR_MCI_TX_CTRL_DISABLE_LNA_UPDATE); | ||
870 | |||
871 | if (AR_SREV_9462_20(ah)) { | ||
872 | REG_CLR_BIT(ah, AR_PHY_GLB_CONTROL, | ||
873 | AR_BTCOEX_CTRL_BT_OWN_SPDT_CTRL); | ||
874 | if (!(mci->config & | ||
875 | ATH_MCI_CONFIG_DISABLE_OSLA)) { | ||
876 | REG_SET_BIT(ah, AR_BTCOEX_CTRL, | ||
877 | AR_BTCOEX_CTRL_ONE_STEP_LOOK_AHEAD_EN); | ||
878 | } | ||
879 | } | ||
880 | } else { | ||
881 | ath_dbg(common, ATH_DBG_MCI, "MCI Send LNA take\n"); | ||
882 | ar9003_mci_send_lna_take(ah, true); | ||
883 | udelay(5); | ||
884 | |||
885 | REG_SET_BIT(ah, AR_MCI_TX_CTRL, | ||
886 | AR_MCI_TX_CTRL_DISABLE_LNA_UPDATE); | ||
887 | |||
888 | if (AR_SREV_9462_20(ah)) { | ||
889 | REG_SET_BIT(ah, AR_PHY_GLB_CONTROL, | ||
890 | AR_BTCOEX_CTRL_BT_OWN_SPDT_CTRL); | ||
891 | REG_CLR_BIT(ah, AR_BTCOEX_CTRL, | ||
892 | AR_BTCOEX_CTRL_ONE_STEP_LOOK_AHEAD_EN); | ||
893 | } | ||
894 | |||
895 | ar9003_mci_send_2g5g_status(ah, true); | ||
896 | } | ||
897 | } | ||
898 | } | ||
899 | |||
900 | bool ar9003_mci_send_message(struct ath_hw *ah, u8 header, u32 flag, | ||
901 | u32 *payload, u8 len, bool wait_done, | ||
902 | bool check_bt) | ||
903 | { | ||
904 | struct ath_common *common = ath9k_hw_common(ah); | ||
905 | struct ath9k_hw_mci *mci = &ah->btcoex_hw.mci; | ||
906 | bool msg_sent = false; | ||
907 | u32 regval; | ||
908 | u32 saved_mci_int_en; | ||
909 | int i; | ||
910 | |||
911 | saved_mci_int_en = REG_READ(ah, AR_MCI_INTERRUPT_EN); | ||
912 | regval = REG_READ(ah, AR_BTCOEX_CTRL); | ||
913 | |||
914 | if ((regval == 0xdeadbeef) || !(regval & AR_BTCOEX_CTRL_MCI_MODE_EN)) { | ||
915 | |||
916 | ath_dbg(common, ATH_DBG_MCI, | ||
917 | "MCI Not sending 0x%x. MCI is not enabled. " | ||
918 | "full_sleep = %d\n", header, | ||
919 | (ah->power_mode == ATH9K_PM_FULL_SLEEP) ? 1 : 0); | ||
920 | |||
921 | ar9003_mci_queue_unsent_gpm(ah, header, payload, true); | ||
922 | return false; | ||
923 | |||
924 | } else if (check_bt && (mci->bt_state == MCI_BT_SLEEP)) { | ||
925 | |||
926 | ath_dbg(common, ATH_DBG_MCI, | ||
927 | "MCI Don't send message 0x%x. BT is in sleep state\n", header); | ||
928 | |||
929 | ar9003_mci_queue_unsent_gpm(ah, header, payload, true); | ||
930 | return false; | ||
931 | } | ||
932 | |||
933 | if (wait_done) | ||
934 | REG_WRITE(ah, AR_MCI_INTERRUPT_EN, 0); | ||
935 | |||
936 | /* Need to clear SW_MSG_DONE raw bit before wait */ | ||
937 | |||
938 | REG_WRITE(ah, AR_MCI_INTERRUPT_RAW, | ||
939 | (AR_MCI_INTERRUPT_SW_MSG_DONE | | ||
940 | AR_MCI_INTERRUPT_MSG_FAIL_MASK)); | ||
941 | |||
942 | if (payload) { | ||
943 | for (i = 0; (i * 4) < len; i++) | ||
944 | REG_WRITE(ah, (AR_MCI_TX_PAYLOAD0 + i * 4), | ||
945 | *(payload + i)); | ||
946 | } | ||
947 | |||
948 | REG_WRITE(ah, AR_MCI_COMMAND0, | ||
949 | (SM((flag & MCI_FLAG_DISABLE_TIMESTAMP), | ||
950 | AR_MCI_COMMAND0_DISABLE_TIMESTAMP) | | ||
951 | SM(len, AR_MCI_COMMAND0_LEN) | | ||
952 | SM(header, AR_MCI_COMMAND0_HEADER))); | ||
953 | |||
954 | if (wait_done && | ||
955 | !(ar9003_mci_wait_for_interrupt(ah, AR_MCI_INTERRUPT_RAW, | ||
956 | AR_MCI_INTERRUPT_SW_MSG_DONE, 500))) | ||
957 | ar9003_mci_queue_unsent_gpm(ah, header, payload, true); | ||
958 | else { | ||
959 | ar9003_mci_queue_unsent_gpm(ah, header, payload, false); | ||
960 | msg_sent = true; | ||
961 | } | ||
962 | |||
963 | if (wait_done) | ||
964 | REG_WRITE(ah, AR_MCI_INTERRUPT_EN, saved_mci_int_en); | ||
965 | |||
966 | return msg_sent; | ||
967 | } | ||
968 | EXPORT_SYMBOL(ar9003_mci_send_message); | ||
969 | |||
970 | void ar9003_mci_setup(struct ath_hw *ah, u32 gpm_addr, void *gpm_buf, | ||
971 | u16 len, u32 sched_addr) | ||
972 | { | ||
973 | struct ath9k_hw_mci *mci = &ah->btcoex_hw.mci; | ||
974 | void *sched_buf = (void *)((char *) gpm_buf + (sched_addr - gpm_addr)); | ||
975 | |||
976 | mci->gpm_addr = gpm_addr; | ||
977 | mci->gpm_buf = gpm_buf; | ||
978 | mci->gpm_len = len; | ||
979 | mci->sched_addr = sched_addr; | ||
980 | mci->sched_buf = sched_buf; | ||
981 | |||
982 | ar9003_mci_reset(ah, true, true, true); | ||
983 | } | ||
984 | EXPORT_SYMBOL(ar9003_mci_setup); | ||
985 | |||
986 | void ar9003_mci_cleanup(struct ath_hw *ah) | ||
987 | { | ||
988 | struct ath_common *common = ath9k_hw_common(ah); | ||
989 | |||
990 | /* Turn off MCI and Jupiter mode. */ | ||
991 | REG_WRITE(ah, AR_BTCOEX_CTRL, 0x00); | ||
992 | ath_dbg(common, ATH_DBG_MCI, "MCI ar9003_mci_cleanup\n"); | ||
993 | ar9003_mci_disable_interrupt(ah); | ||
994 | } | ||
995 | EXPORT_SYMBOL(ar9003_mci_cleanup); | ||
996 | |||
997 | static void ar9003_mci_process_gpm_extra(struct ath_hw *ah, u8 gpm_type, | ||
998 | u8 gpm_opcode, u32 *p_gpm) | ||
999 | { | ||
1000 | struct ath_common *common = ath9k_hw_common(ah); | ||
1001 | struct ath9k_hw_mci *mci = &ah->btcoex_hw.mci; | ||
1002 | u8 *p_data = (u8 *) p_gpm; | ||
1003 | |||
1004 | if (gpm_type != MCI_GPM_COEX_AGENT) | ||
1005 | return; | ||
1006 | |||
1007 | switch (gpm_opcode) { | ||
1008 | case MCI_GPM_COEX_VERSION_QUERY: | ||
1009 | ath_dbg(common, ATH_DBG_MCI, | ||
1010 | "MCI Recv GPM COEX Version Query\n"); | ||
1011 | ar9003_mci_send_coex_version_response(ah, true); | ||
1012 | break; | ||
1013 | case MCI_GPM_COEX_VERSION_RESPONSE: | ||
1014 | ath_dbg(common, ATH_DBG_MCI, | ||
1015 | "MCI Recv GPM COEX Version Response\n"); | ||
1016 | mci->bt_ver_major = | ||
1017 | *(p_data + MCI_GPM_COEX_B_MAJOR_VERSION); | ||
1018 | mci->bt_ver_minor = | ||
1019 | *(p_data + MCI_GPM_COEX_B_MINOR_VERSION); | ||
1020 | mci->bt_version_known = true; | ||
1021 | ath_dbg(common, ATH_DBG_MCI, | ||
1022 | "MCI BT Coex version: %d.%d\n", | ||
1023 | mci->bt_ver_major, | ||
1024 | mci->bt_ver_minor); | ||
1025 | break; | ||
1026 | case MCI_GPM_COEX_STATUS_QUERY: | ||
1027 | ath_dbg(common, ATH_DBG_MCI, | ||
1028 | "MCI Recv GPM COEX Status Query = 0x%02X.\n", | ||
1029 | *(p_data + MCI_GPM_COEX_B_WLAN_BITMAP)); | ||
1030 | mci->wlan_channels_update = true; | ||
1031 | ar9003_mci_send_coex_wlan_channels(ah, true); | ||
1032 | break; | ||
1033 | case MCI_GPM_COEX_BT_PROFILE_INFO: | ||
1034 | mci->query_bt = true; | ||
1035 | ath_dbg(common, ATH_DBG_MCI, | ||
1036 | "MCI Recv GPM COEX BT_Profile_Info\n"); | ||
1037 | break; | ||
1038 | case MCI_GPM_COEX_BT_STATUS_UPDATE: | ||
1039 | mci->query_bt = true; | ||
1040 | ath_dbg(common, ATH_DBG_MCI, | ||
1041 | "MCI Recv GPM COEX BT_Status_Update " | ||
1042 | "SEQ=%d (drop&query)\n", *(p_gpm + 3)); | ||
1043 | break; | ||
1044 | default: | ||
1045 | break; | ||
1046 | } | ||
1047 | } | ||
1048 | |||
1049 | u32 ar9003_mci_wait_for_gpm(struct ath_hw *ah, u8 gpm_type, | ||
1050 | u8 gpm_opcode, int time_out) | ||
1051 | { | ||
1052 | struct ath_common *common = ath9k_hw_common(ah); | ||
1053 | struct ath9k_hw_mci *mci = &ah->btcoex_hw.mci; | ||
1054 | u32 *p_gpm = NULL, mismatch = 0, more_data; | ||
1055 | u32 offset; | ||
1056 | u8 recv_type = 0, recv_opcode = 0; | ||
1057 | bool b_is_bt_cal_done = (gpm_type == MCI_GPM_BT_CAL_DONE); | ||
1058 | |||
1059 | more_data = time_out ? MCI_GPM_NOMORE : MCI_GPM_MORE; | ||
1060 | |||
1061 | while (time_out > 0) { | ||
1062 | if (p_gpm) { | ||
1063 | MCI_GPM_RECYCLE(p_gpm); | ||
1064 | p_gpm = NULL; | ||
1065 | } | ||
1066 | |||
1067 | if (more_data != MCI_GPM_MORE) | ||
1068 | time_out = ar9003_mci_wait_for_interrupt(ah, | ||
1069 | AR_MCI_INTERRUPT_RX_MSG_RAW, | ||
1070 | AR_MCI_INTERRUPT_RX_MSG_GPM, | ||
1071 | time_out); | ||
1072 | |||
1073 | if (!time_out) | ||
1074 | break; | ||
1075 | |||
1076 | offset = ar9003_mci_state(ah, | ||
1077 | MCI_STATE_NEXT_GPM_OFFSET, &more_data); | ||
1078 | |||
1079 | if (offset == MCI_GPM_INVALID) | ||
1080 | continue; | ||
1081 | |||
1082 | p_gpm = (u32 *) (mci->gpm_buf + offset); | ||
1083 | recv_type = MCI_GPM_TYPE(p_gpm); | ||
1084 | recv_opcode = MCI_GPM_OPCODE(p_gpm); | ||
1085 | |||
1086 | if (MCI_GPM_IS_CAL_TYPE(recv_type)) { | ||
1087 | |||
1088 | if (recv_type == gpm_type) { | ||
1089 | |||
1090 | if ((gpm_type == MCI_GPM_BT_CAL_DONE) && | ||
1091 | !b_is_bt_cal_done) { | ||
1092 | gpm_type = MCI_GPM_BT_CAL_GRANT; | ||
1093 | ath_dbg(common, ATH_DBG_MCI, | ||
1094 | "MCI Recv BT_CAL_DONE" | ||
1095 | "wait BT_CAL_GRANT\n"); | ||
1096 | continue; | ||
1097 | } | ||
1098 | |||
1099 | break; | ||
1100 | } | ||
1101 | } else if ((recv_type == gpm_type) && | ||
1102 | (recv_opcode == gpm_opcode)) | ||
1103 | break; | ||
1104 | |||
1105 | /* not expected message */ | ||
1106 | |||
1107 | /* | ||
1108 | * check if it's cal_grant | ||
1109 | * | ||
1110 | * When we're waiting for cal_grant in reset routine, | ||
1111 | * it's possible that BT sends out cal_request at the | ||
1112 | * same time. Since BT's calibration doesn't happen | ||
1113 | * that often, we'll let BT completes calibration then | ||
1114 | * we continue to wait for cal_grant from BT. | ||
1115 | * Orginal: Wait BT_CAL_GRANT. | ||
1116 | * New: Receive BT_CAL_REQ -> send WLAN_CAL_GRANT->wait | ||
1117 | * BT_CAL_DONE -> Wait BT_CAL_GRANT. | ||
1118 | */ | ||
1119 | |||
1120 | if ((gpm_type == MCI_GPM_BT_CAL_GRANT) && | ||
1121 | (recv_type == MCI_GPM_BT_CAL_REQ)) { | ||
1122 | |||
1123 | u32 payload[4] = {0, 0, 0, 0}; | ||
1124 | |||
1125 | gpm_type = MCI_GPM_BT_CAL_DONE; | ||
1126 | ath_dbg(common, ATH_DBG_MCI, | ||
1127 | "MCI Rcv BT_CAL_REQ, send WLAN_CAL_GRANT\n"); | ||
1128 | |||
1129 | MCI_GPM_SET_CAL_TYPE(payload, | ||
1130 | MCI_GPM_WLAN_CAL_GRANT); | ||
1131 | |||
1132 | ar9003_mci_send_message(ah, MCI_GPM, 0, payload, 16, | ||
1133 | false, false); | ||
1134 | |||
1135 | ath_dbg(common, ATH_DBG_MCI, | ||
1136 | "MCI now wait for BT_CAL_DONE\n"); | ||
1137 | |||
1138 | continue; | ||
1139 | } else { | ||
1140 | ath_dbg(common, ATH_DBG_MCI, "MCI GPM subtype" | ||
1141 | "not match 0x%x\n", *(p_gpm + 1)); | ||
1142 | mismatch++; | ||
1143 | ar9003_mci_process_gpm_extra(ah, recv_type, | ||
1144 | recv_opcode, p_gpm); | ||
1145 | } | ||
1146 | } | ||
1147 | if (p_gpm) { | ||
1148 | MCI_GPM_RECYCLE(p_gpm); | ||
1149 | p_gpm = NULL; | ||
1150 | } | ||
1151 | |||
1152 | if (time_out <= 0) { | ||
1153 | time_out = 0; | ||
1154 | ath_dbg(common, ATH_DBG_MCI, | ||
1155 | "MCI GPM received timeout, mismatch = %d\n", mismatch); | ||
1156 | } else | ||
1157 | ath_dbg(common, ATH_DBG_MCI, | ||
1158 | "MCI Receive GPM type=0x%x, code=0x%x\n", | ||
1159 | gpm_type, gpm_opcode); | ||
1160 | |||
1161 | while (more_data == MCI_GPM_MORE) { | ||
1162 | |||
1163 | ath_dbg(common, ATH_DBG_MCI, "MCI discard remaining GPM\n"); | ||
1164 | offset = ar9003_mci_state(ah, MCI_STATE_NEXT_GPM_OFFSET, | ||
1165 | &more_data); | ||
1166 | |||
1167 | if (offset == MCI_GPM_INVALID) | ||
1168 | break; | ||
1169 | |||
1170 | p_gpm = (u32 *) (mci->gpm_buf + offset); | ||
1171 | recv_type = MCI_GPM_TYPE(p_gpm); | ||
1172 | recv_opcode = MCI_GPM_OPCODE(p_gpm); | ||
1173 | |||
1174 | if (!MCI_GPM_IS_CAL_TYPE(recv_type)) | ||
1175 | ar9003_mci_process_gpm_extra(ah, recv_type, | ||
1176 | recv_opcode, p_gpm); | ||
1177 | |||
1178 | MCI_GPM_RECYCLE(p_gpm); | ||
1179 | } | ||
1180 | |||
1181 | return time_out; | ||
1182 | } | ||
1183 | |||
1184 | u32 ar9003_mci_state(struct ath_hw *ah, u32 state_type, u32 *p_data) | ||
1185 | { | ||
1186 | struct ath_common *common = ath9k_hw_common(ah); | ||
1187 | struct ath9k_hw_mci *mci = &ah->btcoex_hw.mci; | ||
1188 | u32 value = 0, more_gpm = 0, gpm_ptr; | ||
1189 | u8 query_type; | ||
1190 | |||
1191 | switch (state_type) { | ||
1192 | case MCI_STATE_ENABLE: | ||
1193 | if (mci->ready) { | ||
1194 | |||
1195 | value = REG_READ(ah, AR_BTCOEX_CTRL); | ||
1196 | |||
1197 | if ((value == 0xdeadbeef) || (value == 0xffffffff)) | ||
1198 | value = 0; | ||
1199 | } | ||
1200 | value &= AR_BTCOEX_CTRL_MCI_MODE_EN; | ||
1201 | break; | ||
1202 | case MCI_STATE_INIT_GPM_OFFSET: | ||
1203 | value = MS(REG_READ(ah, AR_MCI_GPM_1), AR_MCI_GPM_WRITE_PTR); | ||
1204 | ath_dbg(common, ATH_DBG_MCI, | ||
1205 | "MCI GPM initial WRITE_PTR=%d\n", value); | ||
1206 | mci->gpm_idx = value; | ||
1207 | break; | ||
1208 | case MCI_STATE_NEXT_GPM_OFFSET: | ||
1209 | case MCI_STATE_LAST_GPM_OFFSET: | ||
1210 | /* | ||
1211 | * This could be useful to avoid new GPM message interrupt which | ||
1212 | * may lead to spurious interrupt after power sleep, or multiple | ||
1213 | * entry of ath_mci_intr(). | ||
1214 | * Adding empty GPM check by returning HAL_MCI_GPM_INVALID can | ||
1215 | * alleviate this effect, but clearing GPM RX interrupt bit is | ||
1216 | * safe, because whether this is called from hw or driver code | ||
1217 | * there must be an interrupt bit set/triggered initially | ||
1218 | */ | ||
1219 | REG_WRITE(ah, AR_MCI_INTERRUPT_RX_MSG_RAW, | ||
1220 | AR_MCI_INTERRUPT_RX_MSG_GPM); | ||
1221 | |||
1222 | gpm_ptr = MS(REG_READ(ah, AR_MCI_GPM_1), AR_MCI_GPM_WRITE_PTR); | ||
1223 | value = gpm_ptr; | ||
1224 | |||
1225 | if (value == 0) | ||
1226 | value = mci->gpm_len - 1; | ||
1227 | else if (value >= mci->gpm_len) { | ||
1228 | if (value != 0xFFFF) { | ||
1229 | value = 0; | ||
1230 | ath_dbg(common, ATH_DBG_MCI, "MCI GPM offset" | ||
1231 | "out of range\n"); | ||
1232 | } | ||
1233 | } else | ||
1234 | value--; | ||
1235 | |||
1236 | if (value == 0xFFFF) { | ||
1237 | value = MCI_GPM_INVALID; | ||
1238 | more_gpm = MCI_GPM_NOMORE; | ||
1239 | ath_dbg(common, ATH_DBG_MCI, "MCI GPM ptr invalid" | ||
1240 | "@ptr=%d, offset=%d, more=GPM_NOMORE\n", | ||
1241 | gpm_ptr, value); | ||
1242 | } else if (state_type == MCI_STATE_NEXT_GPM_OFFSET) { | ||
1243 | |||
1244 | if (gpm_ptr == mci->gpm_idx) { | ||
1245 | value = MCI_GPM_INVALID; | ||
1246 | more_gpm = MCI_GPM_NOMORE; | ||
1247 | |||
1248 | ath_dbg(common, ATH_DBG_MCI, "MCI GPM message" | ||
1249 | "not available @ptr=%d, @offset=%d," | ||
1250 | "more=GPM_NOMORE\n", gpm_ptr, value); | ||
1251 | } else { | ||
1252 | for (;;) { | ||
1253 | |||
1254 | u32 temp_index; | ||
1255 | |||
1256 | /* skip reserved GPM if any */ | ||
1257 | |||
1258 | if (value != mci->gpm_idx) | ||
1259 | more_gpm = MCI_GPM_MORE; | ||
1260 | else | ||
1261 | more_gpm = MCI_GPM_NOMORE; | ||
1262 | |||
1263 | temp_index = mci->gpm_idx; | ||
1264 | mci->gpm_idx++; | ||
1265 | |||
1266 | if (mci->gpm_idx >= | ||
1267 | mci->gpm_len) | ||
1268 | mci->gpm_idx = 0; | ||
1269 | |||
1270 | ath_dbg(common, ATH_DBG_MCI, | ||
1271 | "MCI GPM message got ptr=%d," | ||
1272 | "@offset=%d, more=%d\n", | ||
1273 | gpm_ptr, temp_index, | ||
1274 | (more_gpm == MCI_GPM_MORE)); | ||
1275 | |||
1276 | if (ar9003_mci_is_gpm_valid(ah, | ||
1277 | temp_index)) { | ||
1278 | value = temp_index; | ||
1279 | break; | ||
1280 | } | ||
1281 | |||
1282 | if (more_gpm == MCI_GPM_NOMORE) { | ||
1283 | value = MCI_GPM_INVALID; | ||
1284 | break; | ||
1285 | } | ||
1286 | } | ||
1287 | } | ||
1288 | if (p_data) | ||
1289 | *p_data = more_gpm; | ||
1290 | } | ||
1291 | |||
1292 | if (value != MCI_GPM_INVALID) | ||
1293 | value <<= 4; | ||
1294 | |||
1295 | break; | ||
1296 | case MCI_STATE_LAST_SCHD_MSG_OFFSET: | ||
1297 | value = MS(REG_READ(ah, AR_MCI_RX_STATUS), | ||
1298 | AR_MCI_RX_LAST_SCHD_MSG_INDEX); | ||
1299 | /* Make it in bytes */ | ||
1300 | value <<= 4; | ||
1301 | break; | ||
1302 | |||
1303 | case MCI_STATE_REMOTE_SLEEP: | ||
1304 | value = MS(REG_READ(ah, AR_MCI_RX_STATUS), | ||
1305 | AR_MCI_RX_REMOTE_SLEEP) ? | ||
1306 | MCI_BT_SLEEP : MCI_BT_AWAKE; | ||
1307 | break; | ||
1308 | |||
1309 | case MCI_STATE_CONT_RSSI_POWER: | ||
1310 | value = MS(mci->cont_status, AR_MCI_CONT_RSSI_POWER); | ||
1311 | break; | ||
1312 | |||
1313 | case MCI_STATE_CONT_PRIORITY: | ||
1314 | value = MS(mci->cont_status, AR_MCI_CONT_RRIORITY); | ||
1315 | break; | ||
1316 | |||
1317 | case MCI_STATE_CONT_TXRX: | ||
1318 | value = MS(mci->cont_status, AR_MCI_CONT_TXRX); | ||
1319 | break; | ||
1320 | |||
1321 | case MCI_STATE_BT: | ||
1322 | value = mci->bt_state; | ||
1323 | break; | ||
1324 | |||
1325 | case MCI_STATE_SET_BT_SLEEP: | ||
1326 | mci->bt_state = MCI_BT_SLEEP; | ||
1327 | break; | ||
1328 | |||
1329 | case MCI_STATE_SET_BT_AWAKE: | ||
1330 | mci->bt_state = MCI_BT_AWAKE; | ||
1331 | ar9003_mci_send_coex_version_query(ah, true); | ||
1332 | ar9003_mci_send_coex_wlan_channels(ah, true); | ||
1333 | |||
1334 | if (mci->unhalt_bt_gpm) { | ||
1335 | |||
1336 | ath_dbg(common, ATH_DBG_MCI, | ||
1337 | "MCI unhalt BT GPM\n"); | ||
1338 | ar9003_mci_send_coex_halt_bt_gpm(ah, false, true); | ||
1339 | } | ||
1340 | |||
1341 | ar9003_mci_2g5g_switch(ah, true); | ||
1342 | break; | ||
1343 | |||
1344 | case MCI_STATE_SET_BT_CAL_START: | ||
1345 | mci->bt_state = MCI_BT_CAL_START; | ||
1346 | break; | ||
1347 | |||
1348 | case MCI_STATE_SET_BT_CAL: | ||
1349 | mci->bt_state = MCI_BT_CAL; | ||
1350 | break; | ||
1351 | |||
1352 | case MCI_STATE_RESET_REQ_WAKE: | ||
1353 | ar9003_mci_reset_req_wakeup(ah); | ||
1354 | mci->update_2g5g = true; | ||
1355 | |||
1356 | if ((AR_SREV_9462_20_OR_LATER(ah)) && | ||
1357 | (mci->config & ATH_MCI_CONFIG_MCI_OBS_MASK)) { | ||
1358 | /* Check if we still have control of the GPIOs */ | ||
1359 | if ((REG_READ(ah, AR_GLB_GPIO_CONTROL) & | ||
1360 | ATH_MCI_CONFIG_MCI_OBS_GPIO) != | ||
1361 | ATH_MCI_CONFIG_MCI_OBS_GPIO) { | ||
1362 | |||
1363 | ath_dbg(common, ATH_DBG_MCI, | ||
1364 | "MCI reconfigure observation"); | ||
1365 | ar9003_mci_observation_set_up(ah); | ||
1366 | } | ||
1367 | } | ||
1368 | break; | ||
1369 | |||
1370 | case MCI_STATE_SEND_WLAN_COEX_VERSION: | ||
1371 | ar9003_mci_send_coex_version_response(ah, true); | ||
1372 | break; | ||
1373 | |||
1374 | case MCI_STATE_SET_BT_COEX_VERSION: | ||
1375 | |||
1376 | if (!p_data) | ||
1377 | ath_dbg(common, ATH_DBG_MCI, | ||
1378 | "MCI Set BT Coex version with NULL data!!\n"); | ||
1379 | else { | ||
1380 | mci->bt_ver_major = (*p_data >> 8) & 0xff; | ||
1381 | mci->bt_ver_minor = (*p_data) & 0xff; | ||
1382 | mci->bt_version_known = true; | ||
1383 | ath_dbg(common, ATH_DBG_MCI, | ||
1384 | "MCI BT version set: %d.%d\n", | ||
1385 | mci->bt_ver_major, | ||
1386 | mci->bt_ver_minor); | ||
1387 | } | ||
1388 | break; | ||
1389 | |||
1390 | case MCI_STATE_SEND_WLAN_CHANNELS: | ||
1391 | if (p_data) { | ||
1392 | if (((mci->wlan_channels[1] & 0xffff0000) == | ||
1393 | (*(p_data + 1) & 0xffff0000)) && | ||
1394 | (mci->wlan_channels[2] == *(p_data + 2)) && | ||
1395 | (mci->wlan_channels[3] == *(p_data + 3))) | ||
1396 | break; | ||
1397 | |||
1398 | mci->wlan_channels[0] = *p_data++; | ||
1399 | mci->wlan_channels[1] = *p_data++; | ||
1400 | mci->wlan_channels[2] = *p_data++; | ||
1401 | mci->wlan_channels[3] = *p_data++; | ||
1402 | } | ||
1403 | mci->wlan_channels_update = true; | ||
1404 | ar9003_mci_send_coex_wlan_channels(ah, true); | ||
1405 | break; | ||
1406 | |||
1407 | case MCI_STATE_SEND_VERSION_QUERY: | ||
1408 | ar9003_mci_send_coex_version_query(ah, true); | ||
1409 | break; | ||
1410 | |||
1411 | case MCI_STATE_SEND_STATUS_QUERY: | ||
1412 | query_type = (AR_SREV_9462_10(ah)) ? | ||
1413 | MCI_GPM_COEX_QUERY_BT_ALL_INFO : | ||
1414 | MCI_GPM_COEX_QUERY_BT_TOPOLOGY; | ||
1415 | |||
1416 | ar9003_mci_send_coex_bt_status_query(ah, true, query_type); | ||
1417 | break; | ||
1418 | |||
1419 | case MCI_STATE_NEED_FLUSH_BT_INFO: | ||
1420 | /* | ||
1421 | * btcoex_hw.mci.unhalt_bt_gpm means whether it's | ||
1422 | * needed to send UNHALT message. It's set whenever | ||
1423 | * there's a request to send HALT message. | ||
1424 | * mci_halted_bt_gpm means whether HALT message is sent | ||
1425 | * out successfully. | ||
1426 | * | ||
1427 | * Checking (mci_unhalt_bt_gpm == false) instead of | ||
1428 | * checking (ah->mci_halted_bt_gpm == false) will make | ||
1429 | * sure currently is in UNHALT-ed mode and BT can | ||
1430 | * respond to status query. | ||
1431 | */ | ||
1432 | value = (!mci->unhalt_bt_gpm && | ||
1433 | mci->need_flush_btinfo) ? 1 : 0; | ||
1434 | if (p_data) | ||
1435 | mci->need_flush_btinfo = | ||
1436 | (*p_data != 0) ? true : false; | ||
1437 | break; | ||
1438 | |||
1439 | case MCI_STATE_RECOVER_RX: | ||
1440 | |||
1441 | ath_dbg(common, ATH_DBG_MCI, "MCI hw RECOVER_RX\n"); | ||
1442 | ar9003_mci_prep_interface(ah); | ||
1443 | mci->query_bt = true; | ||
1444 | mci->need_flush_btinfo = true; | ||
1445 | ar9003_mci_send_coex_wlan_channels(ah, true); | ||
1446 | ar9003_mci_2g5g_switch(ah, true); | ||
1447 | break; | ||
1448 | |||
1449 | case MCI_STATE_NEED_FTP_STOMP: | ||
1450 | value = !(mci->config & ATH_MCI_CONFIG_DISABLE_FTP_STOMP); | ||
1451 | break; | ||
1452 | |||
1453 | case MCI_STATE_NEED_TUNING: | ||
1454 | value = !(mci->config & ATH_MCI_CONFIG_DISABLE_TUNING); | ||
1455 | break; | ||
1456 | |||
1457 | default: | ||
1458 | break; | ||
1459 | |||
1460 | } | ||
1461 | |||
1462 | return value; | ||
1463 | } | ||
1464 | EXPORT_SYMBOL(ar9003_mci_state); | ||
diff --git a/drivers/net/wireless/ath/ath9k/ar9003_mci.h b/drivers/net/wireless/ath/ath9k/ar9003_mci.h new file mode 100644 index 000000000000..798da116a44c --- /dev/null +++ b/drivers/net/wireless/ath/ath9k/ar9003_mci.h | |||
@@ -0,0 +1,102 @@ | |||
1 | /* | ||
2 | * Copyright (c) 2010-2011 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 | #ifndef AR9003_MCI_H | ||
18 | #define AR9003_MCI_H | ||
19 | |||
20 | #define MCI_FLAG_DISABLE_TIMESTAMP 0x00000001 /* Disable time stamp */ | ||
21 | |||
22 | /* Default remote BT device MCI COEX version */ | ||
23 | #define MCI_GPM_COEX_MAJOR_VERSION_DEFAULT 3 | ||
24 | #define MCI_GPM_COEX_MINOR_VERSION_DEFAULT 0 | ||
25 | |||
26 | /* Local WLAN MCI COEX version */ | ||
27 | #define MCI_GPM_COEX_MAJOR_VERSION_WLAN 3 | ||
28 | #define MCI_GPM_COEX_MINOR_VERSION_WLAN 0 | ||
29 | |||
30 | enum mci_gpm_coex_query_type { | ||
31 | MCI_GPM_COEX_QUERY_BT_ALL_INFO = BIT(0), | ||
32 | MCI_GPM_COEX_QUERY_BT_TOPOLOGY = BIT(1), | ||
33 | MCI_GPM_COEX_QUERY_BT_DEBUG = BIT(2), | ||
34 | }; | ||
35 | |||
36 | enum mci_gpm_coex_halt_bt_gpm { | ||
37 | MCI_GPM_COEX_BT_GPM_UNHALT, | ||
38 | MCI_GPM_COEX_BT_GPM_HALT | ||
39 | }; | ||
40 | |||
41 | enum mci_gpm_coex_bt_update_flags_op { | ||
42 | MCI_GPM_COEX_BT_FLAGS_READ, | ||
43 | MCI_GPM_COEX_BT_FLAGS_SET, | ||
44 | MCI_GPM_COEX_BT_FLAGS_CLEAR | ||
45 | }; | ||
46 | |||
47 | #define MCI_NUM_BT_CHANNELS 79 | ||
48 | |||
49 | #define MCI_BT_MCI_FLAGS_UPDATE_CORR 0x00000002 | ||
50 | #define MCI_BT_MCI_FLAGS_UPDATE_HDR 0x00000004 | ||
51 | #define MCI_BT_MCI_FLAGS_UPDATE_PLD 0x00000008 | ||
52 | #define MCI_BT_MCI_FLAGS_LNA_CTRL 0x00000010 | ||
53 | #define MCI_BT_MCI_FLAGS_DEBUG 0x00000020 | ||
54 | #define MCI_BT_MCI_FLAGS_SCHED_MSG 0x00000040 | ||
55 | #define MCI_BT_MCI_FLAGS_CONT_MSG 0x00000080 | ||
56 | #define MCI_BT_MCI_FLAGS_COEX_GPM 0x00000100 | ||
57 | #define MCI_BT_MCI_FLAGS_CPU_INT_MSG 0x00000200 | ||
58 | #define MCI_BT_MCI_FLAGS_MCI_MODE 0x00000400 | ||
59 | #define MCI_BT_MCI_FLAGS_AR9462_MODE 0x00001000 | ||
60 | #define MCI_BT_MCI_FLAGS_OTHER 0x00010000 | ||
61 | |||
62 | #define MCI_DEFAULT_BT_MCI_FLAGS 0x00011dde | ||
63 | |||
64 | #define MCI_TOGGLE_BT_MCI_FLAGS (MCI_BT_MCI_FLAGS_UPDATE_CORR | \ | ||
65 | MCI_BT_MCI_FLAGS_UPDATE_HDR | \ | ||
66 | MCI_BT_MCI_FLAGS_UPDATE_PLD | \ | ||
67 | MCI_BT_MCI_FLAGS_MCI_MODE) | ||
68 | |||
69 | #define MCI_2G_FLAGS_CLEAR_MASK 0x00000000 | ||
70 | #define MCI_2G_FLAGS_SET_MASK MCI_TOGGLE_BT_MCI_FLAGS | ||
71 | #define MCI_2G_FLAGS MCI_DEFAULT_BT_MCI_FLAGS | ||
72 | |||
73 | #define MCI_5G_FLAGS_CLEAR_MASK MCI_TOGGLE_BT_MCI_FLAGS | ||
74 | #define MCI_5G_FLAGS_SET_MASK 0x00000000 | ||
75 | #define MCI_5G_FLAGS (MCI_DEFAULT_BT_MCI_FLAGS & \ | ||
76 | ~MCI_TOGGLE_BT_MCI_FLAGS) | ||
77 | |||
78 | /* | ||
79 | * Default value for AR9462 is 0x00002201 | ||
80 | */ | ||
81 | #define ATH_MCI_CONFIG_CONCUR_TX 0x00000003 | ||
82 | #define ATH_MCI_CONFIG_MCI_OBS_MCI 0x00000004 | ||
83 | #define ATH_MCI_CONFIG_MCI_OBS_TXRX 0x00000008 | ||
84 | #define ATH_MCI_CONFIG_MCI_OBS_BT 0x00000010 | ||
85 | #define ATH_MCI_CONFIG_DISABLE_MCI_CAL 0x00000020 | ||
86 | #define ATH_MCI_CONFIG_DISABLE_OSLA 0x00000040 | ||
87 | #define ATH_MCI_CONFIG_DISABLE_FTP_STOMP 0x00000080 | ||
88 | #define ATH_MCI_CONFIG_AGGR_THRESH 0x00000700 | ||
89 | #define ATH_MCI_CONFIG_AGGR_THRESH_S 8 | ||
90 | #define ATH_MCI_CONFIG_DISABLE_AGGR_THRESH 0x00000800 | ||
91 | #define ATH_MCI_CONFIG_CLK_DIV 0x00003000 | ||
92 | #define ATH_MCI_CONFIG_CLK_DIV_S 12 | ||
93 | #define ATH_MCI_CONFIG_DISABLE_TUNING 0x00004000 | ||
94 | #define ATH_MCI_CONFIG_MCI_WEIGHT_DBG 0x40000000 | ||
95 | #define ATH_MCI_CONFIG_DISABLE_MCI 0x80000000 | ||
96 | |||
97 | #define ATH_MCI_CONFIG_MCI_OBS_MASK (ATH_MCI_CONFIG_MCI_OBS_MCI | \ | ||
98 | ATH_MCI_CONFIG_MCI_OBS_TXRX | \ | ||
99 | ATH_MCI_CONFIG_MCI_OBS_BT) | ||
100 | #define ATH_MCI_CONFIG_MCI_OBS_GPIO 0x0000002F | ||
101 | |||
102 | #endif | ||
diff --git a/drivers/net/wireless/ath/ath9k/ar9003_paprd.c b/drivers/net/wireless/ath/ath9k/ar9003_paprd.c index 0c462c904cbe..a4450cba0653 100644 --- a/drivers/net/wireless/ath/ath9k/ar9003_paprd.c +++ b/drivers/net/wireless/ath/ath9k/ar9003_paprd.c | |||
@@ -14,6 +14,7 @@ | |||
14 | * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. | 14 | * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. |
15 | */ | 15 | */ |
16 | 16 | ||
17 | #include <linux/export.h> | ||
17 | #include "hw.h" | 18 | #include "hw.h" |
18 | #include "ar9003_phy.h" | 19 | #include "ar9003_phy.h" |
19 | 20 | ||
diff --git a/drivers/net/wireless/ath/ath9k/ar9003_phy.c b/drivers/net/wireless/ath/ath9k/ar9003_phy.c index 04b060af5087..e41d26939ab8 100644 --- a/drivers/net/wireless/ath/ath9k/ar9003_phy.c +++ b/drivers/net/wireless/ath/ath9k/ar9003_phy.c | |||
@@ -14,6 +14,7 @@ | |||
14 | * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. | 14 | * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. |
15 | */ | 15 | */ |
16 | 16 | ||
17 | #include <linux/export.h> | ||
17 | #include "hw.h" | 18 | #include "hw.h" |
18 | #include "ar9003_phy.h" | 19 | #include "ar9003_phy.h" |
19 | 20 | ||
diff --git a/drivers/net/wireless/ath/ath9k/ar9003_phy.h b/drivers/net/wireless/ath/ath9k/ar9003_phy.h index 497d7461838a..ed64114571fc 100644 --- a/drivers/net/wireless/ath/ath9k/ar9003_phy.h +++ b/drivers/net/wireless/ath/ath9k/ar9003_phy.h | |||
@@ -490,6 +490,8 @@ | |||
490 | #define AR_PHY_TEST_CTL_TSTADC_EN_S 8 | 490 | #define AR_PHY_TEST_CTL_TSTADC_EN_S 8 |
491 | #define AR_PHY_TEST_CTL_RX_OBS_SEL 0x3C00 | 491 | #define AR_PHY_TEST_CTL_RX_OBS_SEL 0x3C00 |
492 | #define AR_PHY_TEST_CTL_RX_OBS_SEL_S 10 | 492 | #define AR_PHY_TEST_CTL_RX_OBS_SEL_S 10 |
493 | #define AR_PHY_TEST_CTL_DEBUGPORT_SEL 0xe0000000 | ||
494 | #define AR_PHY_TEST_CTL_DEBUGPORT_SEL_S 29 | ||
493 | 495 | ||
494 | 496 | ||
495 | #define AR_PHY_TSTDAC (AR_SM_BASE + 0x168) | 497 | #define AR_PHY_TSTDAC (AR_SM_BASE + 0x168) |
@@ -1001,6 +1003,7 @@ | |||
1001 | 1003 | ||
1002 | /* GLB Registers */ | 1004 | /* GLB Registers */ |
1003 | #define AR_GLB_BASE 0x20000 | 1005 | #define AR_GLB_BASE 0x20000 |
1006 | #define AR_GLB_GPIO_CONTROL (AR_GLB_BASE) | ||
1004 | #define AR_PHY_GLB_CONTROL (AR_GLB_BASE + 0x44) | 1007 | #define AR_PHY_GLB_CONTROL (AR_GLB_BASE + 0x44) |
1005 | #define AR_GLB_SCRATCH(_ah) (AR_GLB_BASE + \ | 1008 | #define AR_GLB_SCRATCH(_ah) (AR_GLB_BASE + \ |
1006 | (AR_SREV_9462_20(_ah) ? 0x4c : 0x50)) | 1009 | (AR_SREV_9462_20(_ah) ? 0x4c : 0x50)) |
diff --git a/drivers/net/wireless/ath/ath9k/ar9462_2p0_initvals.h b/drivers/net/wireless/ath/ath9k/ar9462_2p0_initvals.h index 259a6f312afb..dc2054f0378e 100644 --- a/drivers/net/wireless/ath/ath9k/ar9462_2p0_initvals.h +++ b/drivers/net/wireless/ath/ath9k/ar9462_2p0_initvals.h | |||
@@ -41,24 +41,24 @@ static const u32 ar9462_pciephy_clkreq_enable_L1_2p0[][2] = { | |||
41 | 41 | ||
42 | static const u32 ar9462_2p0_baseband_postamble[][5] = { | 42 | static const u32 ar9462_2p0_baseband_postamble[][5] = { |
43 | /* Addr 5G_HT20 5G_HT40 2G_HT40 2G_HT20 */ | 43 | /* Addr 5G_HT20 5G_HT40 2G_HT40 2G_HT20 */ |
44 | {0x00009810, 0xd00a8005, 0xd00a8005, 0xd00a8011, 0xd00a8011}, | 44 | {0x00009810, 0xd00a8005, 0xd00a8005, 0xd00a8011, 0xd00a800d}, |
45 | {0x00009820, 0x206a022e, 0x206a022e, 0x206a012e, 0x206a012e}, | 45 | {0x00009820, 0x206a022e, 0x206a022e, 0x206a012e, 0x206a01ae}, |
46 | {0x00009824, 0x5ac640de, 0x5ac640d0, 0x5ac640d0, 0x5ac640de}, | 46 | {0x00009824, 0x5ac640de, 0x5ac640d0, 0x5ac640d0, 0x63c640da}, |
47 | {0x00009828, 0x0796be89, 0x0696b081, 0x0696b881, 0x0796be89}, | 47 | {0x00009828, 0x0796be89, 0x0696b081, 0x0696b881, 0x09143e81}, |
48 | {0x0000982c, 0x05eea6d4, 0x05eea6d4, 0x05eea6d4, 0x05eea6d4}, | 48 | {0x0000982c, 0x05eea6d4, 0x05eea6d4, 0x05eea6d4, 0x05eea6d4}, |
49 | {0x00009830, 0x0000059c, 0x0000059c, 0x0000119c, 0x0000119c}, | 49 | {0x00009830, 0x0000059c, 0x0000059c, 0x0000119c, 0x0000119c}, |
50 | {0x00009c00, 0x000000c4, 0x000000c4, 0x000000c4, 0x000000c4}, | 50 | {0x00009c00, 0x000000c4, 0x000000c4, 0x000000c4, 0x000000c4}, |
51 | {0x00009e00, 0x0372111a, 0x0372111a, 0x037216a0, 0x037216a0}, | 51 | {0x00009e00, 0x0372111a, 0x0372111a, 0x037216a0, 0x037216a0}, |
52 | {0x00009e04, 0x001c2020, 0x001c2020, 0x001c2020, 0x001c2020}, | 52 | {0x00009e04, 0x001c2020, 0x001c2020, 0x001c2020, 0x001c2020}, |
53 | {0x00009e0c, 0x6c4000e2, 0x6d4000e2, 0x6d4000e2, 0x6c4000e2}, | 53 | {0x00009e0c, 0x6c4000e2, 0x6d4000e2, 0x6d4000e2, 0x6c4000d8}, |
54 | {0x00009e10, 0x92c88d2e, 0x7ec88d2e, 0x7ec84d2e, 0x92c84d2e}, | 54 | {0x00009e10, 0x92c88d2e, 0x7ec88d2e, 0x7ec84d2e, 0x7ec86d2e}, |
55 | {0x00009e14, 0x37b95d5e, 0x37b9605e, 0x3379605e, 0x33795d5e}, | 55 | {0x00009e14, 0x37b95d5e, 0x37b9605e, 0x3376605e, 0x33795d5e}, |
56 | {0x00009e18, 0x00000000, 0x00000000, 0x00000000, 0x00000000}, | 56 | {0x00009e18, 0x00000000, 0x00000000, 0x00000000, 0x00000000}, |
57 | {0x00009e1c, 0x0001cf9c, 0x0001cf9c, 0x00021f9c, 0x00021f9c}, | 57 | {0x00009e1c, 0x0001cf9c, 0x0001cf9c, 0x00021f9c, 0x00021f9c}, |
58 | {0x00009e20, 0x000003b5, 0x000003b5, 0x000003ce, 0x000003ce}, | 58 | {0x00009e20, 0x000003b5, 0x000003b5, 0x000003ce, 0x000003ce}, |
59 | {0x00009e2c, 0x0000001c, 0x0000001c, 0x00000021, 0x00000021}, | 59 | {0x00009e2c, 0x0000001c, 0x0000001c, 0x00000021, 0x00000021}, |
60 | {0x00009e3c, 0xcf946220, 0xcf946220, 0xcfd5c782, 0xcfd5c782}, | 60 | {0x00009e3c, 0xcf946220, 0xcf946220, 0xcfd5c782, 0xcfd5c282}, |
61 | {0x00009e44, 0xfe321e27, 0xfe321e27, 0xfe291e27, 0xfe291e27}, | 61 | {0x00009e44, 0x62321e27, 0x62321e27, 0xfe291e27, 0xfe291e27}, |
62 | {0x00009e48, 0x5030201a, 0x5030201a, 0x50302012, 0x50302012}, | 62 | {0x00009e48, 0x5030201a, 0x5030201a, 0x50302012, 0x50302012}, |
63 | {0x00009fc8, 0x0003f000, 0x0003f000, 0x0001a000, 0x0001a000}, | 63 | {0x00009fc8, 0x0003f000, 0x0003f000, 0x0001a000, 0x0001a000}, |
64 | {0x0000a204, 0x013187c0, 0x013187c4, 0x013187c4, 0x013187c0}, | 64 | {0x0000a204, 0x013187c0, 0x013187c4, 0x013187c4, 0x013187c0}, |
@@ -81,6 +81,15 @@ static const u32 ar9462_2p0_baseband_postamble[][5] = { | |||
81 | {0x0000a2d0, 0x00041981, 0x00041981, 0x00041981, 0x00041982}, | 81 | {0x0000a2d0, 0x00041981, 0x00041981, 0x00041981, 0x00041982}, |
82 | {0x0000a2d8, 0x7999a83b, 0x7999a83b, 0x7999a83b, 0x7999a83b}, | 82 | {0x0000a2d8, 0x7999a83b, 0x7999a83b, 0x7999a83b, 0x7999a83b}, |
83 | {0x0000a358, 0x00000000, 0x00000000, 0x00000000, 0x00000000}, | 83 | {0x0000a358, 0x00000000, 0x00000000, 0x00000000, 0x00000000}, |
84 | {0x0000a3a4, 0x00000010, 0x00000010, 0x00000000, 0x00000000}, | ||
85 | {0x0000a3a8, 0xaaaaaaaa, 0xaaaaaaaa, 0xaaaaaaaa, 0xaaaaaaaa}, | ||
86 | {0x0000a3ac, 0xaaaaaa00, 0xaaaaaa30, 0xaaaaaa00, 0xaaaaaa00}, | ||
87 | {0x0000a41c, 0x1ce739ce, 0x1ce739ce, 0x1ce739ce, 0x1ce739ce}, | ||
88 | {0x0000a420, 0x000001ce, 0x000001ce, 0x000001ce, 0x000001ce}, | ||
89 | {0x0000a424, 0x1ce739ce, 0x1ce739ce, 0x1ce739ce, 0x1ce739ce}, | ||
90 | {0x0000a428, 0x000001ce, 0x000001ce, 0x000001ce, 0x000001ce}, | ||
91 | {0x0000a42c, 0x1ce739ce, 0x1ce739ce, 0x1ce739ce, 0x1ce739ce}, | ||
92 | {0x0000a430, 0x1ce739ce, 0x1ce739ce, 0x1ce739ce, 0x1ce739ce}, | ||
84 | {0x0000a830, 0x0000019c, 0x0000019c, 0x0000019c, 0x0000019c}, | 93 | {0x0000a830, 0x0000019c, 0x0000019c, 0x0000019c, 0x0000019c}, |
85 | {0x0000ae04, 0x001c0000, 0x001c0000, 0x001c0000, 0x00100000}, | 94 | {0x0000ae04, 0x001c0000, 0x001c0000, 0x001c0000, 0x00100000}, |
86 | {0x0000ae18, 0x00000000, 0x00000000, 0x00000000, 0x00000000}, | 95 | {0x0000ae18, 0x00000000, 0x00000000, 0x00000000, 0x00000000}, |
@@ -1107,11 +1116,11 @@ static const u32 ar9462_2p0_baseband_core[][2] = { | |||
1107 | {0x00009e30, 0x06336f77}, | 1116 | {0x00009e30, 0x06336f77}, |
1108 | {0x00009e34, 0x6af6532f}, | 1117 | {0x00009e34, 0x6af6532f}, |
1109 | {0x00009e38, 0x0cc80c00}, | 1118 | {0x00009e38, 0x0cc80c00}, |
1110 | {0x00009e40, 0x0d261820}, | 1119 | {0x00009e40, 0x15262820}, |
1111 | {0x00009e4c, 0x00001004}, | 1120 | {0x00009e4c, 0x00001004}, |
1112 | {0x00009e50, 0x00ff03f1}, | 1121 | {0x00009e50, 0x00ff03f1}, |
1113 | {0x00009e54, 0xe4c355c7}, | 1122 | {0x00009e54, 0xe4c555c2}, |
1114 | {0x00009e58, 0xfd897735}, | 1123 | {0x00009e58, 0xfd857722}, |
1115 | {0x00009e5c, 0xe9198724}, | 1124 | {0x00009e5c, 0xe9198724}, |
1116 | {0x00009fc0, 0x803e4788}, | 1125 | {0x00009fc0, 0x803e4788}, |
1117 | {0x00009fc4, 0x0001efb5}, | 1126 | {0x00009fc4, 0x0001efb5}, |
@@ -1142,9 +1151,6 @@ static const u32 ar9462_2p0_baseband_core[][2] = { | |||
1142 | {0x0000a398, 0x001f0e0f}, | 1151 | {0x0000a398, 0x001f0e0f}, |
1143 | {0x0000a39c, 0x0075393f}, | 1152 | {0x0000a39c, 0x0075393f}, |
1144 | {0x0000a3a0, 0xb79f6427}, | 1153 | {0x0000a3a0, 0xb79f6427}, |
1145 | {0x0000a3a4, 0x00000000}, | ||
1146 | {0x0000a3a8, 0xaaaaaaaa}, | ||
1147 | {0x0000a3ac, 0x3c466478}, | ||
1148 | {0x0000a3c0, 0x20202020}, | 1154 | {0x0000a3c0, 0x20202020}, |
1149 | {0x0000a3c4, 0x22222220}, | 1155 | {0x0000a3c4, 0x22222220}, |
1150 | {0x0000a3c8, 0x20200020}, | 1156 | {0x0000a3c8, 0x20200020}, |
@@ -1167,12 +1173,6 @@ static const u32 ar9462_2p0_baseband_core[][2] = { | |||
1167 | {0x0000a40c, 0x00820820}, | 1173 | {0x0000a40c, 0x00820820}, |
1168 | {0x0000a414, 0x1ce739ce}, | 1174 | {0x0000a414, 0x1ce739ce}, |
1169 | {0x0000a418, 0x2d001dce}, | 1175 | {0x0000a418, 0x2d001dce}, |
1170 | {0x0000a41c, 0x1ce739ce}, | ||
1171 | {0x0000a420, 0x000001ce}, | ||
1172 | {0x0000a424, 0x1ce739ce}, | ||
1173 | {0x0000a428, 0x000001ce}, | ||
1174 | {0x0000a42c, 0x1ce739ce}, | ||
1175 | {0x0000a430, 0x1ce739ce}, | ||
1176 | {0x0000a434, 0x00000000}, | 1176 | {0x0000a434, 0x00000000}, |
1177 | {0x0000a438, 0x00001801}, | 1177 | {0x0000a438, 0x00001801}, |
1178 | {0x0000a43c, 0x00100000}, | 1178 | {0x0000a43c, 0x00100000}, |
diff --git a/drivers/net/wireless/ath/ath9k/ath9k.h b/drivers/net/wireless/ath/ath9k/ath9k.h index 93b45b4b3033..130e5dba9555 100644 --- a/drivers/net/wireless/ath/ath9k/ath9k.h +++ b/drivers/net/wireless/ath/ath9k/ath9k.h | |||
@@ -159,6 +159,9 @@ void ath_descdma_cleanup(struct ath_softc *sc, struct ath_descdma *dd, | |||
159 | /* return block-ack bitmap index given sequence and starting sequence */ | 159 | /* return block-ack bitmap index given sequence and starting sequence */ |
160 | #define ATH_BA_INDEX(_st, _seq) (((_seq) - (_st)) & (IEEE80211_SEQ_MAX - 1)) | 160 | #define ATH_BA_INDEX(_st, _seq) (((_seq) - (_st)) & (IEEE80211_SEQ_MAX - 1)) |
161 | 161 | ||
162 | /* return the seqno for _start + _offset */ | ||
163 | #define ATH_BA_INDEX2SEQ(_seq, _offset) (((_seq) + (_offset)) & (IEEE80211_SEQ_MAX - 1)) | ||
164 | |||
162 | /* returns delimiter padding required given the packet length */ | 165 | /* returns delimiter padding required given the packet length */ |
163 | #define ATH_AGGR_GET_NDELIM(_len) \ | 166 | #define ATH_AGGR_GET_NDELIM(_len) \ |
164 | (((_len) >= ATH_AGGR_MINPLEN) ? 0 : \ | 167 | (((_len) >= ATH_AGGR_MINPLEN) ? 0 : \ |
@@ -238,6 +241,7 @@ struct ath_atx_tid { | |||
238 | struct ath_node *an; | 241 | struct ath_node *an; |
239 | struct ath_atx_ac *ac; | 242 | struct ath_atx_ac *ac; |
240 | unsigned long tx_buf[BITS_TO_LONGS(ATH_TID_MAX_BUFS)]; | 243 | unsigned long tx_buf[BITS_TO_LONGS(ATH_TID_MAX_BUFS)]; |
244 | int bar_index; | ||
241 | u16 seq_start; | 245 | u16 seq_start; |
242 | u16 seq_next; | 246 | u16 seq_next; |
243 | u16 baw_size; | 247 | u16 baw_size; |
@@ -252,9 +256,9 @@ struct ath_atx_tid { | |||
252 | struct ath_node { | 256 | struct ath_node { |
253 | #ifdef CONFIG_ATH9K_DEBUGFS | 257 | #ifdef CONFIG_ATH9K_DEBUGFS |
254 | struct list_head list; /* for sc->nodes */ | 258 | struct list_head list; /* for sc->nodes */ |
259 | #endif | ||
255 | struct ieee80211_sta *sta; /* station struct we're part of */ | 260 | struct ieee80211_sta *sta; /* station struct we're part of */ |
256 | struct ieee80211_vif *vif; /* interface with which we're associated */ | 261 | struct ieee80211_vif *vif; /* interface with which we're associated */ |
257 | #endif | ||
258 | struct ath_atx_tid tid[WME_NUM_TID]; | 262 | struct ath_atx_tid tid[WME_NUM_TID]; |
259 | struct ath_atx_ac ac[WME_NUM_AC]; | 263 | struct ath_atx_ac ac[WME_NUM_AC]; |
260 | int ps_key; | 264 | int ps_key; |
@@ -276,7 +280,6 @@ struct ath_tx_control { | |||
276 | }; | 280 | }; |
277 | 281 | ||
278 | #define ATH_TX_ERROR 0x01 | 282 | #define ATH_TX_ERROR 0x01 |
279 | #define ATH_TX_BAR 0x02 | ||
280 | 283 | ||
281 | /** | 284 | /** |
282 | * @txq_map: Index is mac80211 queue number. This is | 285 | * @txq_map: Index is mac80211 queue number. This is |
@@ -462,7 +465,7 @@ void ath9k_btcoex_timer_pause(struct ath_softc *sc); | |||
462 | #define ATH_LED_PIN_9287 8 | 465 | #define ATH_LED_PIN_9287 8 |
463 | #define ATH_LED_PIN_9300 10 | 466 | #define ATH_LED_PIN_9300 10 |
464 | #define ATH_LED_PIN_9485 6 | 467 | #define ATH_LED_PIN_9485 6 |
465 | #define ATH_LED_PIN_9462 0 | 468 | #define ATH_LED_PIN_9462 4 |
466 | 469 | ||
467 | #ifdef CONFIG_MAC80211_LEDS | 470 | #ifdef CONFIG_MAC80211_LEDS |
468 | void ath_init_leds(struct ath_softc *sc); | 471 | void ath_init_leds(struct ath_softc *sc); |
@@ -542,7 +545,7 @@ struct ath_ant_comb { | |||
542 | #define DEFAULT_CACHELINE 32 | 545 | #define DEFAULT_CACHELINE 32 |
543 | #define ATH_REGCLASSIDS_MAX 10 | 546 | #define ATH_REGCLASSIDS_MAX 10 |
544 | #define ATH_CABQ_READY_TIME 80 /* % of beacon interval */ | 547 | #define ATH_CABQ_READY_TIME 80 /* % of beacon interval */ |
545 | #define ATH_MAX_SW_RETRIES 10 | 548 | #define ATH_MAX_SW_RETRIES 30 |
546 | #define ATH_CHAN_MAX 255 | 549 | #define ATH_CHAN_MAX 255 |
547 | 550 | ||
548 | #define ATH_TXPOWER_MAX 100 /* .5 dBm units */ | 551 | #define ATH_TXPOWER_MAX 100 /* .5 dBm units */ |
@@ -647,6 +650,7 @@ struct ath_softc { | |||
647 | struct delayed_work tx_complete_work; | 650 | struct delayed_work tx_complete_work; |
648 | struct delayed_work hw_pll_work; | 651 | struct delayed_work hw_pll_work; |
649 | struct ath_btcoex btcoex; | 652 | struct ath_btcoex btcoex; |
653 | struct ath_mci_coex mci_coex; | ||
650 | 654 | ||
651 | struct ath_descdma txsdma; | 655 | struct ath_descdma txsdma; |
652 | 656 | ||
diff --git a/drivers/net/wireless/ath/ath9k/btcoex.c b/drivers/net/wireless/ath/ath9k/btcoex.c index 5a6361da9818..bbb20810ec10 100644 --- a/drivers/net/wireless/ath/ath9k/btcoex.c +++ b/drivers/net/wireless/ath/ath9k/btcoex.c | |||
@@ -14,13 +14,14 @@ | |||
14 | * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. | 14 | * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. |
15 | */ | 15 | */ |
16 | 16 | ||
17 | #include <linux/export.h> | ||
17 | #include "hw.h" | 18 | #include "hw.h" |
18 | 19 | ||
19 | enum ath_bt_mode { | 20 | enum ath_bt_mode { |
20 | ATH_BT_COEX_MODE_LEGACY, /* legacy rx_clear mode */ | 21 | ATH_BT_COEX_MODE_LEGACY, /* legacy rx_clear mode */ |
21 | ATH_BT_COEX_MODE_UNSLOTTED, /* untimed/unslotted mode */ | 22 | ATH_BT_COEX_MODE_UNSLOTTED, /* untimed/unslotted mode */ |
22 | ATH_BT_COEX_MODE_SLOTTED, /* slotted mode */ | 23 | ATH_BT_COEX_MODE_SLOTTED, /* slotted mode */ |
23 | ATH_BT_COEX_MODE_DISALBED, /* coexistence disabled */ | 24 | ATH_BT_COEX_MODE_DISABLED, /* coexistence disabled */ |
24 | }; | 25 | }; |
25 | 26 | ||
26 | struct ath_btcoex_config { | 27 | struct ath_btcoex_config { |
diff --git a/drivers/net/wireless/ath/ath9k/btcoex.h b/drivers/net/wireless/ath/ath9k/btcoex.h index d5e5db1faad9..278361c867ca 100644 --- a/drivers/net/wireless/ath/ath9k/btcoex.h +++ b/drivers/net/wireless/ath/ath9k/btcoex.h | |||
@@ -54,8 +54,39 @@ enum ath_btcoex_scheme { | |||
54 | ATH_BTCOEX_CFG_MCI, | 54 | ATH_BTCOEX_CFG_MCI, |
55 | }; | 55 | }; |
56 | 56 | ||
57 | struct ath9k_hw_mci { | ||
58 | u32 raw_intr; | ||
59 | u32 rx_msg_intr; | ||
60 | u32 cont_status; | ||
61 | u32 gpm_addr; | ||
62 | u32 gpm_len; | ||
63 | u32 gpm_idx; | ||
64 | u32 sched_addr; | ||
65 | u32 wlan_channels[4]; | ||
66 | u32 wlan_cal_seq; | ||
67 | u32 wlan_cal_done; | ||
68 | u32 config; | ||
69 | u8 *gpm_buf; | ||
70 | u8 *sched_buf; | ||
71 | bool ready; | ||
72 | bool update_2g5g; | ||
73 | bool is_2g; | ||
74 | bool query_bt; | ||
75 | bool unhalt_bt_gpm; /* need send UNHALT */ | ||
76 | bool halted_bt_gpm; /* HALT sent */ | ||
77 | bool need_flush_btinfo; | ||
78 | bool bt_version_known; | ||
79 | bool wlan_channels_update; | ||
80 | u8 wlan_ver_major; | ||
81 | u8 wlan_ver_minor; | ||
82 | u8 bt_ver_major; | ||
83 | u8 bt_ver_minor; | ||
84 | u8 bt_state; | ||
85 | }; | ||
86 | |||
57 | struct ath_btcoex_hw { | 87 | struct ath_btcoex_hw { |
58 | enum ath_btcoex_scheme scheme; | 88 | enum ath_btcoex_scheme scheme; |
89 | struct ath9k_hw_mci mci; | ||
59 | bool enabled; | 90 | bool enabled; |
60 | u8 wlanactive_gpio; | 91 | u8 wlanactive_gpio; |
61 | u8 btactive_gpio; | 92 | u8 btactive_gpio; |
diff --git a/drivers/net/wireless/ath/ath9k/calib.c b/drivers/net/wireless/ath/ath9k/calib.c index ebaf304f464b..99538810a312 100644 --- a/drivers/net/wireless/ath/ath9k/calib.c +++ b/drivers/net/wireless/ath/ath9k/calib.c | |||
@@ -16,6 +16,7 @@ | |||
16 | 16 | ||
17 | #include "hw.h" | 17 | #include "hw.h" |
18 | #include "hw-ops.h" | 18 | #include "hw-ops.h" |
19 | #include <linux/export.h> | ||
19 | 20 | ||
20 | /* Common calibration code */ | 21 | /* Common calibration code */ |
21 | 22 | ||
diff --git a/drivers/net/wireless/ath/ath9k/debug.c b/drivers/net/wireless/ath/ath9k/debug.c index 8e7e57ccbe9a..68d972bf232d 100644 --- a/drivers/net/wireless/ath/ath9k/debug.c +++ b/drivers/net/wireless/ath/ath9k/debug.c | |||
@@ -16,6 +16,7 @@ | |||
16 | 16 | ||
17 | #include <linux/slab.h> | 17 | #include <linux/slab.h> |
18 | #include <linux/vmalloc.h> | 18 | #include <linux/vmalloc.h> |
19 | #include <linux/export.h> | ||
19 | #include <asm/unaligned.h> | 20 | #include <asm/unaligned.h> |
20 | 21 | ||
21 | #include "ath9k.h" | 22 | #include "ath9k.h" |
@@ -855,7 +856,7 @@ void ath_debug_stat_tx(struct ath_softc *sc, struct ath_buf *bf, | |||
855 | sc->debug.stats.txstats[qnum].tx_bytes_all += bf->bf_mpdu->len; | 856 | sc->debug.stats.txstats[qnum].tx_bytes_all += bf->bf_mpdu->len; |
856 | 857 | ||
857 | if (bf_isampdu(bf)) { | 858 | if (bf_isampdu(bf)) { |
858 | if (flags & ATH_TX_BAR) | 859 | if (flags & ATH_TX_ERROR) |
859 | TX_STAT_INC(qnum, a_xretries); | 860 | TX_STAT_INC(qnum, a_xretries); |
860 | else | 861 | else |
861 | TX_STAT_INC(qnum, a_completed); | 862 | TX_STAT_INC(qnum, a_completed); |
@@ -1629,6 +1630,9 @@ int ath9k_init_debug(struct ath_hw *ah) | |||
1629 | debugfs_create_file("debug", S_IRUSR | S_IWUSR, sc->debug.debugfs_phy, | 1630 | debugfs_create_file("debug", S_IRUSR | S_IWUSR, sc->debug.debugfs_phy, |
1630 | sc, &fops_debug); | 1631 | sc, &fops_debug); |
1631 | #endif | 1632 | #endif |
1633 | |||
1634 | ath9k_dfs_init_debug(sc); | ||
1635 | |||
1632 | debugfs_create_file("dma", S_IRUSR, sc->debug.debugfs_phy, sc, | 1636 | debugfs_create_file("dma", S_IRUSR, sc->debug.debugfs_phy, sc, |
1633 | &fops_dma); | 1637 | &fops_dma); |
1634 | debugfs_create_file("interrupt", S_IRUSR, sc->debug.debugfs_phy, sc, | 1638 | debugfs_create_file("interrupt", S_IRUSR, sc->debug.debugfs_phy, sc, |
diff --git a/drivers/net/wireless/ath/ath9k/debug.h b/drivers/net/wireless/ath/ath9k/debug.h index 356352ac2d6e..776a24ada600 100644 --- a/drivers/net/wireless/ath/ath9k/debug.h +++ b/drivers/net/wireless/ath/ath9k/debug.h | |||
@@ -19,6 +19,7 @@ | |||
19 | 19 | ||
20 | #include "hw.h" | 20 | #include "hw.h" |
21 | #include "rc.h" | 21 | #include "rc.h" |
22 | #include "dfs_debug.h" | ||
22 | 23 | ||
23 | struct ath_txq; | 24 | struct ath_txq; |
24 | struct ath_buf; | 25 | struct ath_buf; |
@@ -187,6 +188,7 @@ struct ath_stats { | |||
187 | struct ath_interrupt_stats istats; | 188 | struct ath_interrupt_stats istats; |
188 | struct ath_tx_stats txstats[ATH9K_NUM_TX_QUEUES]; | 189 | struct ath_tx_stats txstats[ATH9K_NUM_TX_QUEUES]; |
189 | struct ath_rx_stats rxstats; | 190 | struct ath_rx_stats rxstats; |
191 | struct ath_dfs_stats dfs_stats; | ||
190 | u32 reset[__RESET_TYPE_MAX]; | 192 | u32 reset[__RESET_TYPE_MAX]; |
191 | }; | 193 | }; |
192 | 194 | ||
diff --git a/drivers/net/wireless/ath/ath9k/dfs.c b/drivers/net/wireless/ath/ath9k/dfs.c new file mode 100644 index 000000000000..e4e84a9e6273 --- /dev/null +++ b/drivers/net/wireless/ath/ath9k/dfs.c | |||
@@ -0,0 +1,215 @@ | |||
1 | /* | ||
2 | * Copyright (c) 2008-2011 Atheros Communications Inc. | ||
3 | * Copyright (c) 2011 Neratec Solutions AG | ||
4 | * | ||
5 | * Permission to use, copy, modify, and/or distribute this software for any | ||
6 | * purpose with or without fee is hereby granted, provided that the above | ||
7 | * copyright notice and this permission notice appear in all copies. | ||
8 | * | ||
9 | * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES | ||
10 | * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF | ||
11 | * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR | ||
12 | * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES | ||
13 | * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN | ||
14 | * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF | ||
15 | * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. | ||
16 | */ | ||
17 | |||
18 | #include "hw.h" | ||
19 | #include "hw-ops.h" | ||
20 | #include "ath9k.h" | ||
21 | #include "dfs.h" | ||
22 | #include "dfs_debug.h" | ||
23 | |||
24 | /* | ||
25 | * TODO: move into or synchronize this with generic header | ||
26 | * as soon as IF is defined | ||
27 | */ | ||
28 | struct dfs_radar_pulse { | ||
29 | u16 freq; | ||
30 | u64 ts; | ||
31 | u32 width; | ||
32 | u8 rssi; | ||
33 | }; | ||
34 | |||
35 | /* internal struct to pass radar data */ | ||
36 | struct ath_radar_data { | ||
37 | u8 pulse_bw_info; | ||
38 | u8 rssi; | ||
39 | u8 ext_rssi; | ||
40 | u8 pulse_length_ext; | ||
41 | u8 pulse_length_pri; | ||
42 | }; | ||
43 | |||
44 | /* convert pulse duration to usecs, considering clock mode */ | ||
45 | static u32 dur_to_usecs(struct ath_hw *ah, u32 dur) | ||
46 | { | ||
47 | const u32 AR93X_NSECS_PER_DUR = 800; | ||
48 | const u32 AR93X_NSECS_PER_DUR_FAST = (8000 / 11); | ||
49 | u32 nsecs; | ||
50 | |||
51 | if (IS_CHAN_A_FAST_CLOCK(ah, ah->curchan)) | ||
52 | nsecs = dur * AR93X_NSECS_PER_DUR_FAST; | ||
53 | else | ||
54 | nsecs = dur * AR93X_NSECS_PER_DUR; | ||
55 | |||
56 | return (nsecs + 500) / 1000; | ||
57 | } | ||
58 | |||
59 | #define PRI_CH_RADAR_FOUND 0x01 | ||
60 | #define EXT_CH_RADAR_FOUND 0x02 | ||
61 | static bool | ||
62 | ath9k_postprocess_radar_event(struct ath_softc *sc, | ||
63 | struct ath_radar_data *are, | ||
64 | struct dfs_radar_pulse *drp) | ||
65 | { | ||
66 | u8 rssi; | ||
67 | u16 dur; | ||
68 | |||
69 | ath_dbg(ath9k_hw_common(sc->sc_ah), ATH_DBG_DFS, | ||
70 | "pulse_bw_info=0x%x, pri,ext len/rssi=(%u/%u, %u/%u)\n", | ||
71 | are->pulse_bw_info, | ||
72 | are->pulse_length_pri, are->rssi, | ||
73 | are->pulse_length_ext, are->ext_rssi); | ||
74 | |||
75 | /* | ||
76 | * Only the last 2 bits of the BW info are relevant, they indicate | ||
77 | * which channel the radar was detected in. | ||
78 | */ | ||
79 | are->pulse_bw_info &= 0x03; | ||
80 | |||
81 | switch (are->pulse_bw_info) { | ||
82 | case PRI_CH_RADAR_FOUND: | ||
83 | /* radar in ctrl channel */ | ||
84 | dur = are->pulse_length_pri; | ||
85 | DFS_STAT_INC(sc, pri_phy_errors); | ||
86 | /* | ||
87 | * cannot use ctrl channel RSSI | ||
88 | * if extension channel is stronger | ||
89 | */ | ||
90 | rssi = (are->ext_rssi >= (are->rssi + 3)) ? 0 : are->rssi; | ||
91 | break; | ||
92 | case EXT_CH_RADAR_FOUND: | ||
93 | /* radar in extension channel */ | ||
94 | dur = are->pulse_length_ext; | ||
95 | DFS_STAT_INC(sc, ext_phy_errors); | ||
96 | /* | ||
97 | * cannot use extension channel RSSI | ||
98 | * if control channel is stronger | ||
99 | */ | ||
100 | rssi = (are->rssi >= (are->ext_rssi + 12)) ? 0 : are->ext_rssi; | ||
101 | break; | ||
102 | case (PRI_CH_RADAR_FOUND | EXT_CH_RADAR_FOUND): | ||
103 | /* | ||
104 | * Conducted testing, when pulse is on DC, both pri and ext | ||
105 | * durations are reported to be same | ||
106 | * | ||
107 | * Radiated testing, when pulse is on DC, different pri and | ||
108 | * ext durations are reported, so take the larger of the two | ||
109 | */ | ||
110 | if (are->pulse_length_ext >= are->pulse_length_pri) | ||
111 | dur = are->pulse_length_ext; | ||
112 | else | ||
113 | dur = are->pulse_length_pri; | ||
114 | DFS_STAT_INC(sc, dc_phy_errors); | ||
115 | |||
116 | /* when both are present use stronger one */ | ||
117 | rssi = (are->rssi < are->ext_rssi) ? are->ext_rssi : are->rssi; | ||
118 | break; | ||
119 | default: | ||
120 | /* | ||
121 | * Bogus bandwidth info was received in descriptor, | ||
122 | * so ignore this PHY error | ||
123 | */ | ||
124 | DFS_STAT_INC(sc, bwinfo_discards); | ||
125 | return false; | ||
126 | } | ||
127 | |||
128 | if (rssi == 0) { | ||
129 | DFS_STAT_INC(sc, rssi_discards); | ||
130 | return false; | ||
131 | } | ||
132 | |||
133 | /* | ||
134 | * TODO: check chirping pulses | ||
135 | * checks for chirping are dependent on the DFS regulatory domain | ||
136 | * used, which is yet TBD | ||
137 | */ | ||
138 | |||
139 | /* convert duration to usecs */ | ||
140 | drp->width = dur_to_usecs(sc->sc_ah, dur); | ||
141 | drp->rssi = rssi; | ||
142 | |||
143 | DFS_STAT_INC(sc, pulses_detected); | ||
144 | return true; | ||
145 | } | ||
146 | #undef PRI_CH_RADAR_FOUND | ||
147 | #undef EXT_CH_RADAR_FOUND | ||
148 | |||
149 | /* | ||
150 | * DFS: check PHY-error for radar pulse and feed the detector | ||
151 | */ | ||
152 | void ath9k_dfs_process_phyerr(struct ath_softc *sc, void *data, | ||
153 | struct ath_rx_status *rs, u64 mactime) | ||
154 | { | ||
155 | struct ath_radar_data ard; | ||
156 | u16 datalen; | ||
157 | char *vdata_end; | ||
158 | struct dfs_radar_pulse drp; | ||
159 | struct ath_hw *ah = sc->sc_ah; | ||
160 | struct ath_common *common = ath9k_hw_common(ah); | ||
161 | |||
162 | if ((!(rs->rs_phyerr != ATH9K_PHYERR_RADAR)) && | ||
163 | (!(rs->rs_phyerr != ATH9K_PHYERR_FALSE_RADAR_EXT))) { | ||
164 | ath_dbg(common, ATH_DBG_DFS, | ||
165 | "Error: rs_phyer=0x%x not a radar error\n", | ||
166 | rs->rs_phyerr); | ||
167 | return; | ||
168 | } | ||
169 | |||
170 | datalen = rs->rs_datalen; | ||
171 | if (datalen == 0) { | ||
172 | DFS_STAT_INC(sc, datalen_discards); | ||
173 | return; | ||
174 | } | ||
175 | |||
176 | ard.rssi = rs->rs_rssi_ctl0; | ||
177 | ard.ext_rssi = rs->rs_rssi_ext0; | ||
178 | |||
179 | /* | ||
180 | * hardware stores this as 8 bit signed value. | ||
181 | * we will cap it at 0 if it is a negative number | ||
182 | */ | ||
183 | if (ard.rssi & 0x80) | ||
184 | ard.rssi = 0; | ||
185 | if (ard.ext_rssi & 0x80) | ||
186 | ard.ext_rssi = 0; | ||
187 | |||
188 | vdata_end = (char *)data + datalen; | ||
189 | ard.pulse_bw_info = vdata_end[-1]; | ||
190 | ard.pulse_length_ext = vdata_end[-2]; | ||
191 | ard.pulse_length_pri = vdata_end[-3]; | ||
192 | |||
193 | ath_dbg(common, ATH_DBG_DFS, | ||
194 | "bw_info=%d, length_pri=%d, length_ext=%d, " | ||
195 | "rssi_pri=%d, rssi_ext=%d\n", | ||
196 | ard.pulse_bw_info, ard.pulse_length_pri, ard.pulse_length_ext, | ||
197 | ard.rssi, ard.ext_rssi); | ||
198 | |||
199 | drp.freq = ah->curchan->channel; | ||
200 | drp.ts = mactime; | ||
201 | if (ath9k_postprocess_radar_event(sc, &ard, &drp)) { | ||
202 | static u64 last_ts; | ||
203 | ath_dbg(common, ATH_DBG_DFS, | ||
204 | "ath9k_dfs_process_phyerr: channel=%d, ts=%llu, " | ||
205 | "width=%d, rssi=%d, delta_ts=%llu\n", | ||
206 | drp.freq, drp.ts, drp.width, drp.rssi, drp.ts-last_ts); | ||
207 | last_ts = drp.ts; | ||
208 | /* | ||
209 | * TODO: forward pulse to pattern detector | ||
210 | * | ||
211 | * ieee80211_add_radar_pulse(drp.freq, drp.ts, | ||
212 | * drp.width, drp.rssi); | ||
213 | */ | ||
214 | } | ||
215 | } | ||
diff --git a/drivers/net/wireless/ath/ath9k/dfs.h b/drivers/net/wireless/ath/ath9k/dfs.h new file mode 100644 index 000000000000..c2412857f122 --- /dev/null +++ b/drivers/net/wireless/ath/ath9k/dfs.h | |||
@@ -0,0 +1,43 @@ | |||
1 | /* | ||
2 | * Copyright (c) 2008-2011 Atheros Communications Inc. | ||
3 | * Copyright (c) 2011 Neratec Solutions AG | ||
4 | * | ||
5 | * Permission to use, copy, modify, and/or distribute this software for any | ||
6 | * purpose with or without fee is hereby granted, provided that the above | ||
7 | * copyright notice and this permission notice appear in all copies. | ||
8 | * | ||
9 | * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES | ||
10 | * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF | ||
11 | * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR | ||
12 | * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES | ||
13 | * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN | ||
14 | * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF | ||
15 | * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. | ||
16 | */ | ||
17 | |||
18 | #ifndef ATH9K_DFS_H | ||
19 | #define ATH9K_DFS_H | ||
20 | |||
21 | #if defined(CONFIG_ATH9K_DFS_CERTIFIED) | ||
22 | /** | ||
23 | * ath9k_dfs_process_phyerr - process radar PHY error | ||
24 | * @sc: ath_softc | ||
25 | * @data: RX payload data | ||
26 | * @rs: RX status after processing descriptor | ||
27 | * @mactime: receive time | ||
28 | * | ||
29 | * This function is called whenever the HW DFS module detects a radar | ||
30 | * pulse and reports it as a PHY error. | ||
31 | * | ||
32 | * The radar information provided as raw payload data is validated and | ||
33 | * filtered for false pulses. Events passing all tests are forwarded to | ||
34 | * the upper layer for pattern detection. | ||
35 | */ | ||
36 | void ath9k_dfs_process_phyerr(struct ath_softc *sc, void *data, | ||
37 | struct ath_rx_status *rs, u64 mactime); | ||
38 | #else | ||
39 | static inline void ath9k_dfs_process_phyerr(struct ath_softc *sc, void *data, | ||
40 | struct ath_rx_status *rs, u64 mactime) { } | ||
41 | #endif | ||
42 | |||
43 | #endif /* ATH9K_DFS_H */ | ||
diff --git a/drivers/net/wireless/ath/ath9k/dfs_debug.c b/drivers/net/wireless/ath/ath9k/dfs_debug.c new file mode 100644 index 000000000000..106d031d834a --- /dev/null +++ b/drivers/net/wireless/ath/ath9k/dfs_debug.c | |||
@@ -0,0 +1,81 @@ | |||
1 | /* | ||
2 | * Copyright (c) 2008-2011 Atheros Communications Inc. | ||
3 | * Copyright (c) 2011 Neratec Solutions AG | ||
4 | * | ||
5 | * Permission to use, copy, modify, and/or distribute this software for any | ||
6 | * purpose with or without fee is hereby granted, provided that the above | ||
7 | * copyright notice and this permission notice appear in all copies. | ||
8 | * | ||
9 | * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES | ||
10 | * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF | ||
11 | * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR | ||
12 | * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES | ||
13 | * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN | ||
14 | * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF | ||
15 | * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. | ||
16 | */ | ||
17 | |||
18 | #include <linux/debugfs.h> | ||
19 | #include <linux/export.h> | ||
20 | |||
21 | #include "ath9k.h" | ||
22 | #include "dfs_debug.h" | ||
23 | |||
24 | #define ATH9K_DFS_STAT(s, p) \ | ||
25 | len += snprintf(buf + len, size - len, "%28s : %10u\n", s, \ | ||
26 | sc->debug.stats.dfs_stats.p); | ||
27 | |||
28 | static ssize_t read_file_dfs(struct file *file, char __user *user_buf, | ||
29 | size_t count, loff_t *ppos) | ||
30 | { | ||
31 | struct ath_softc *sc = file->private_data; | ||
32 | struct ath9k_hw_version *hw_ver = &sc->sc_ah->hw_version; | ||
33 | char *buf; | ||
34 | unsigned int len = 0, size = 8000; | ||
35 | ssize_t retval = 0; | ||
36 | |||
37 | buf = kzalloc(size, GFP_KERNEL); | ||
38 | if (buf == NULL) | ||
39 | return -ENOMEM; | ||
40 | |||
41 | len += snprintf(buf + len, size - len, "DFS support for " | ||
42 | "macVersion = 0x%x, macRev = 0x%x: %s\n", | ||
43 | hw_ver->macVersion, hw_ver->macRev, | ||
44 | (sc->sc_ah->caps.hw_caps & ATH9K_HW_CAP_DFS) ? | ||
45 | "enabled" : "disabled"); | ||
46 | ATH9K_DFS_STAT("DFS pulses detected ", pulses_detected); | ||
47 | ATH9K_DFS_STAT("Datalen discards ", datalen_discards); | ||
48 | ATH9K_DFS_STAT("RSSI discards ", rssi_discards); | ||
49 | ATH9K_DFS_STAT("BW info discards ", bwinfo_discards); | ||
50 | ATH9K_DFS_STAT("Primary channel pulses ", pri_phy_errors); | ||
51 | ATH9K_DFS_STAT("Secondary channel pulses", ext_phy_errors); | ||
52 | ATH9K_DFS_STAT("Dual channel pulses ", dc_phy_errors); | ||
53 | |||
54 | if (len > size) | ||
55 | len = size; | ||
56 | |||
57 | retval = simple_read_from_buffer(user_buf, count, ppos, buf, len); | ||
58 | kfree(buf); | ||
59 | |||
60 | return retval; | ||
61 | } | ||
62 | |||
63 | static int ath9k_dfs_debugfs_open(struct inode *inode, struct file *file) | ||
64 | { | ||
65 | file->private_data = inode->i_private; | ||
66 | |||
67 | return 0; | ||
68 | } | ||
69 | |||
70 | static const struct file_operations fops_dfs_stats = { | ||
71 | .read = read_file_dfs, | ||
72 | .open = ath9k_dfs_debugfs_open, | ||
73 | .owner = THIS_MODULE, | ||
74 | .llseek = default_llseek, | ||
75 | }; | ||
76 | |||
77 | void ath9k_dfs_init_debug(struct ath_softc *sc) | ||
78 | { | ||
79 | debugfs_create_file("dfs_stats", S_IRUSR, | ||
80 | sc->debug.debugfs_phy, sc, &fops_dfs_stats); | ||
81 | } | ||
diff --git a/drivers/net/wireless/ath/ath9k/dfs_debug.h b/drivers/net/wireless/ath/ath9k/dfs_debug.h new file mode 100644 index 000000000000..6e1e2a71659e --- /dev/null +++ b/drivers/net/wireless/ath/ath9k/dfs_debug.h | |||
@@ -0,0 +1,57 @@ | |||
1 | /* | ||
2 | * Copyright (c) 2008-2011 Atheros Communications Inc. | ||
3 | * Copyright (c) 2011 Neratec Solutions AG | ||
4 | * | ||
5 | * Permission to use, copy, modify, and/or distribute this software for any | ||
6 | * purpose with or without fee is hereby granted, provided that the above | ||
7 | * copyright notice and this permission notice appear in all copies. | ||
8 | * | ||
9 | * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES | ||
10 | * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF | ||
11 | * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR | ||
12 | * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES | ||
13 | * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN | ||
14 | * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF | ||
15 | * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. | ||
16 | */ | ||
17 | |||
18 | |||
19 | #ifndef DFS_DEBUG_H | ||
20 | #define DFS_DEBUG_H | ||
21 | |||
22 | #include "hw.h" | ||
23 | |||
24 | /** | ||
25 | * struct ath_dfs_stats - DFS Statistics | ||
26 | * | ||
27 | * @pulses_detected: No. of pulses detected so far | ||
28 | * @datalen_discards: No. of pulses discarded due to invalid datalen | ||
29 | * @rssi_discards: No. of pulses discarded due to invalid RSSI | ||
30 | * @bwinfo_discards: No. of pulses discarded due to invalid BW info | ||
31 | * @pri_phy_errors: No. of pulses reported for primary channel | ||
32 | * @ext_phy_errors: No. of pulses reported for extension channel | ||
33 | * @dc_phy_errors: No. of pulses reported for primary + extension channel | ||
34 | */ | ||
35 | struct ath_dfs_stats { | ||
36 | u32 pulses_detected; | ||
37 | u32 datalen_discards; | ||
38 | u32 rssi_discards; | ||
39 | u32 bwinfo_discards; | ||
40 | u32 pri_phy_errors; | ||
41 | u32 ext_phy_errors; | ||
42 | u32 dc_phy_errors; | ||
43 | }; | ||
44 | |||
45 | #if defined(CONFIG_ATH9K_DFS_DEBUGFS) | ||
46 | |||
47 | #define DFS_STAT_INC(sc, c) (sc->debug.stats.dfs_stats.c++) | ||
48 | void ath9k_dfs_init_debug(struct ath_softc *sc); | ||
49 | |||
50 | #else | ||
51 | |||
52 | #define DFS_STAT_INC(sc, c) do { } while (0) | ||
53 | static inline void ath9k_dfs_init_debug(struct ath_softc *sc) { } | ||
54 | |||
55 | #endif /* CONFIG_ATH9K_DFS_DEBUGFS */ | ||
56 | |||
57 | #endif /* DFS_DEBUG_H */ | ||
diff --git a/drivers/net/wireless/ath/ath9k/eeprom_4k.c b/drivers/net/wireless/ath/ath9k/eeprom_4k.c index 9a7520f987f0..61fcab0e2d76 100644 --- a/drivers/net/wireless/ath/ath9k/eeprom_4k.c +++ b/drivers/net/wireless/ath/ath9k/eeprom_4k.c | |||
@@ -473,7 +473,7 @@ static void ath9k_hw_set_4k_power_per_rate_table(struct ath_hw *ah, | |||
473 | 473 | ||
474 | int i; | 474 | int i; |
475 | u16 twiceMinEdgePower; | 475 | u16 twiceMinEdgePower; |
476 | u16 twiceMaxEdgePower = MAX_RATE_POWER; | 476 | u16 twiceMaxEdgePower; |
477 | u16 scaledPower = 0, minCtlPower; | 477 | u16 scaledPower = 0, minCtlPower; |
478 | u16 numCtlModes; | 478 | u16 numCtlModes; |
479 | const u16 *pCtlMode; | 479 | const u16 *pCtlMode; |
@@ -542,9 +542,7 @@ static void ath9k_hw_set_4k_power_per_rate_table(struct ath_hw *ah, | |||
542 | else | 542 | else |
543 | freq = centers.ctl_center; | 543 | freq = centers.ctl_center; |
544 | 544 | ||
545 | if (ah->eep_ops->get_eeprom_ver(ah) == 14 && | 545 | twiceMaxEdgePower = MAX_RATE_POWER; |
546 | ah->eep_ops->get_eeprom_rev(ah) <= 2) | ||
547 | twiceMaxEdgePower = MAX_RATE_POWER; | ||
548 | 546 | ||
549 | for (i = 0; (i < AR5416_EEP4K_NUM_CTLS) && | 547 | for (i = 0; (i < AR5416_EEP4K_NUM_CTLS) && |
550 | pEepData->ctlIndex[i]; i++) { | 548 | pEepData->ctlIndex[i]; i++) { |
diff --git a/drivers/net/wireless/ath/ath9k/eeprom_9287.c b/drivers/net/wireless/ath/ath9k/eeprom_9287.c index 4f5c50a87ce3..0981c073471d 100644 --- a/drivers/net/wireless/ath/ath9k/eeprom_9287.c +++ b/drivers/net/wireless/ath/ath9k/eeprom_9287.c | |||
@@ -569,7 +569,7 @@ static void ath9k_hw_set_ar9287_power_per_rate_table(struct ath_hw *ah, | |||
569 | #define REDUCE_SCALED_POWER_BY_TWO_CHAIN 6 | 569 | #define REDUCE_SCALED_POWER_BY_TWO_CHAIN 6 |
570 | #define REDUCE_SCALED_POWER_BY_THREE_CHAIN 10 | 570 | #define REDUCE_SCALED_POWER_BY_THREE_CHAIN 10 |
571 | 571 | ||
572 | u16 twiceMaxEdgePower = MAX_RATE_POWER; | 572 | u16 twiceMaxEdgePower; |
573 | int i; | 573 | int i; |
574 | struct cal_ctl_data_ar9287 *rep; | 574 | struct cal_ctl_data_ar9287 *rep; |
575 | struct cal_target_power_leg targetPowerOfdm = {0, {0, 0, 0, 0} }, | 575 | struct cal_target_power_leg targetPowerOfdm = {0, {0, 0, 0, 0} }, |
@@ -669,6 +669,7 @@ static void ath9k_hw_set_ar9287_power_per_rate_table(struct ath_hw *ah, | |||
669 | else | 669 | else |
670 | freq = centers.ctl_center; | 670 | freq = centers.ctl_center; |
671 | 671 | ||
672 | twiceMaxEdgePower = MAX_RATE_POWER; | ||
672 | /* Walk through the CTL indices stored in EEPROM */ | 673 | /* Walk through the CTL indices stored in EEPROM */ |
673 | for (i = 0; (i < AR9287_NUM_CTLS) && pEepData->ctlIndex[i]; i++) { | 674 | for (i = 0; (i < AR9287_NUM_CTLS) && pEepData->ctlIndex[i]; i++) { |
674 | struct cal_ctl_edges *pRdEdgesPower; | 675 | struct cal_ctl_edges *pRdEdgesPower; |
diff --git a/drivers/net/wireless/ath/ath9k/eeprom_def.c b/drivers/net/wireless/ath/ath9k/eeprom_def.c index 81e629671679..55a21d39167c 100644 --- a/drivers/net/wireless/ath/ath9k/eeprom_def.c +++ b/drivers/net/wireless/ath/ath9k/eeprom_def.c | |||
@@ -1000,7 +1000,7 @@ static void ath9k_hw_set_def_power_per_rate_table(struct ath_hw *ah, | |||
1000 | #define REDUCE_SCALED_POWER_BY_THREE_CHAIN 9 /* 10*log10(3)*2 */ | 1000 | #define REDUCE_SCALED_POWER_BY_THREE_CHAIN 9 /* 10*log10(3)*2 */ |
1001 | 1001 | ||
1002 | struct ar5416_eeprom_def *pEepData = &ah->eeprom.def; | 1002 | struct ar5416_eeprom_def *pEepData = &ah->eeprom.def; |
1003 | u16 twiceMaxEdgePower = MAX_RATE_POWER; | 1003 | u16 twiceMaxEdgePower; |
1004 | int i; | 1004 | int i; |
1005 | struct cal_ctl_data *rep; | 1005 | struct cal_ctl_data *rep; |
1006 | struct cal_target_power_leg targetPowerOfdm, targetPowerCck = { | 1006 | struct cal_target_power_leg targetPowerOfdm, targetPowerCck = { |
@@ -1121,9 +1121,7 @@ static void ath9k_hw_set_def_power_per_rate_table(struct ath_hw *ah, | |||
1121 | else | 1121 | else |
1122 | freq = centers.ctl_center; | 1122 | freq = centers.ctl_center; |
1123 | 1123 | ||
1124 | if (ah->eep_ops->get_eeprom_ver(ah) == 14 && | 1124 | twiceMaxEdgePower = MAX_RATE_POWER; |
1125 | ah->eep_ops->get_eeprom_rev(ah) <= 2) | ||
1126 | twiceMaxEdgePower = MAX_RATE_POWER; | ||
1127 | 1125 | ||
1128 | for (i = 0; (i < AR5416_NUM_CTLS) && pEepData->ctlIndex[i]; i++) { | 1126 | for (i = 0; (i < AR5416_NUM_CTLS) && pEepData->ctlIndex[i]; i++) { |
1129 | if ((((cfgCtl & ~CTL_MODE_M) | | 1127 | if ((((cfgCtl & ~CTL_MODE_M) | |
diff --git a/drivers/net/wireless/ath/ath9k/htc_drv_main.c b/drivers/net/wireless/ath/ath9k/htc_drv_main.c index 0b9a0e8a4958..f8ce4ea6f65c 100644 --- a/drivers/net/wireless/ath/ath9k/htc_drv_main.c +++ b/drivers/net/wireless/ath/ath9k/htc_drv_main.c | |||
@@ -808,7 +808,8 @@ void ath9k_htc_ani_work(struct work_struct *work) | |||
808 | } | 808 | } |
809 | 809 | ||
810 | /* Verify whether we must check ANI */ | 810 | /* Verify whether we must check ANI */ |
811 | if ((timestamp - common->ani.checkani_timer) >= ATH_ANI_POLLINTERVAL) { | 811 | if (ah->config.enable_ani && |
812 | (timestamp - common->ani.checkani_timer) >= ATH_ANI_POLLINTERVAL) { | ||
812 | aniflag = true; | 813 | aniflag = true; |
813 | common->ani.checkani_timer = timestamp; | 814 | common->ani.checkani_timer = timestamp; |
814 | } | 815 | } |
@@ -838,7 +839,7 @@ set_timer: | |||
838 | * short calibration and long calibration. | 839 | * short calibration and long calibration. |
839 | */ | 840 | */ |
840 | cal_interval = ATH_LONG_CALINTERVAL; | 841 | cal_interval = ATH_LONG_CALINTERVAL; |
841 | if (priv->ah->config.enable_ani) | 842 | if (ah->config.enable_ani) |
842 | cal_interval = min(cal_interval, (u32)ATH_ANI_POLLINTERVAL); | 843 | cal_interval = min(cal_interval, (u32)ATH_ANI_POLLINTERVAL); |
843 | if (!common->ani.caldone) | 844 | if (!common->ani.caldone) |
844 | cal_interval = min(cal_interval, (u32)short_cal_interval); | 845 | cal_interval = min(cal_interval, (u32)short_cal_interval); |
diff --git a/drivers/net/wireless/ath/ath9k/hw-ops.h b/drivers/net/wireless/ath/ath9k/hw-ops.h index e74c233757a2..c4ad0b06bdbc 100644 --- a/drivers/net/wireless/ath/ath9k/hw-ops.h +++ b/drivers/net/wireless/ath/ath9k/hw-ops.h | |||
@@ -212,4 +212,13 @@ static inline int ath9k_hw_fast_chan_change(struct ath_hw *ah, | |||
212 | return ath9k_hw_private_ops(ah)->fast_chan_change(ah, chan, | 212 | return ath9k_hw_private_ops(ah)->fast_chan_change(ah, chan, |
213 | ini_reloaded); | 213 | ini_reloaded); |
214 | } | 214 | } |
215 | |||
216 | static inline void ath9k_hw_set_radar_params(struct ath_hw *ah) | ||
217 | { | ||
218 | if (!ath9k_hw_private_ops(ah)->set_radar_params) | ||
219 | return; | ||
220 | |||
221 | ath9k_hw_private_ops(ah)->set_radar_params(ah, &ah->radar_conf); | ||
222 | } | ||
223 | |||
215 | #endif /* ATH9K_HW_OPS_H */ | 224 | #endif /* ATH9K_HW_OPS_H */ |
diff --git a/drivers/net/wireless/ath/ath9k/hw.c b/drivers/net/wireless/ath/ath9k/hw.c index 27471f80d8b2..8cda9a1513a7 100644 --- a/drivers/net/wireless/ath/ath9k/hw.c +++ b/drivers/net/wireless/ath/ath9k/hw.c | |||
@@ -16,6 +16,7 @@ | |||
16 | 16 | ||
17 | #include <linux/io.h> | 17 | #include <linux/io.h> |
18 | #include <linux/slab.h> | 18 | #include <linux/slab.h> |
19 | #include <linux/module.h> | ||
19 | #include <asm/unaligned.h> | 20 | #include <asm/unaligned.h> |
20 | 21 | ||
21 | #include "hw.h" | 22 | #include "hw.h" |
@@ -503,7 +504,7 @@ static int ath9k_hw_post_init(struct ath_hw *ah) | |||
503 | return ecode; | 504 | return ecode; |
504 | } | 505 | } |
505 | 506 | ||
506 | if (!AR_SREV_9100(ah) && !AR_SREV_9340(ah)) { | 507 | if (ah->config.enable_ani) { |
507 | ath9k_hw_ani_setup(ah); | 508 | ath9k_hw_ani_setup(ah); |
508 | ath9k_hw_ani_init(ah); | 509 | ath9k_hw_ani_init(ah); |
509 | } | 510 | } |
@@ -609,6 +610,10 @@ static int __ath9k_hw_init(struct ath_hw *ah) | |||
609 | if (!AR_SREV_9300_20_OR_LATER(ah)) | 610 | if (!AR_SREV_9300_20_OR_LATER(ah)) |
610 | ah->ani_function &= ~ATH9K_ANI_MRC_CCK; | 611 | ah->ani_function &= ~ATH9K_ANI_MRC_CCK; |
611 | 612 | ||
613 | /* disable ANI for 9340 */ | ||
614 | if (AR_SREV_9340(ah)) | ||
615 | ah->config.enable_ani = false; | ||
616 | |||
612 | ath9k_hw_init_mode_regs(ah); | 617 | ath9k_hw_init_mode_regs(ah); |
613 | 618 | ||
614 | if (!ah->is_pciexpress) | 619 | if (!ah->is_pciexpress) |
@@ -1349,6 +1354,7 @@ static bool ath9k_hw_set_reset_power_on(struct ath_hw *ah) | |||
1349 | 1354 | ||
1350 | static bool ath9k_hw_set_reset_reg(struct ath_hw *ah, u32 type) | 1355 | static bool ath9k_hw_set_reset_reg(struct ath_hw *ah, u32 type) |
1351 | { | 1356 | { |
1357 | bool ret = false; | ||
1352 | 1358 | ||
1353 | if (AR_SREV_9300_20_OR_LATER(ah)) { | 1359 | if (AR_SREV_9300_20_OR_LATER(ah)) { |
1354 | REG_WRITE(ah, AR_WA, ah->WARegVal); | 1360 | REG_WRITE(ah, AR_WA, ah->WARegVal); |
@@ -1360,13 +1366,20 @@ static bool ath9k_hw_set_reset_reg(struct ath_hw *ah, u32 type) | |||
1360 | 1366 | ||
1361 | switch (type) { | 1367 | switch (type) { |
1362 | case ATH9K_RESET_POWER_ON: | 1368 | case ATH9K_RESET_POWER_ON: |
1363 | return ath9k_hw_set_reset_power_on(ah); | 1369 | ret = ath9k_hw_set_reset_power_on(ah); |
1370 | break; | ||
1364 | case ATH9K_RESET_WARM: | 1371 | case ATH9K_RESET_WARM: |
1365 | case ATH9K_RESET_COLD: | 1372 | case ATH9K_RESET_COLD: |
1366 | return ath9k_hw_set_reset(ah, type); | 1373 | ret = ath9k_hw_set_reset(ah, type); |
1374 | break; | ||
1367 | default: | 1375 | default: |
1368 | return false; | 1376 | break; |
1369 | } | 1377 | } |
1378 | |||
1379 | if (ah->caps.hw_caps & ATH9K_HW_CAP_MCI) | ||
1380 | REG_WRITE(ah, AR_RTC_KEEP_AWAKE, 0x2); | ||
1381 | |||
1382 | return ret; | ||
1370 | } | 1383 | } |
1371 | 1384 | ||
1372 | static bool ath9k_hw_chip_reset(struct ath_hw *ah, | 1385 | static bool ath9k_hw_chip_reset(struct ath_hw *ah, |
@@ -1505,6 +1518,7 @@ int ath9k_hw_reset(struct ath_hw *ah, struct ath9k_channel *chan, | |||
1505 | struct ath9k_hw_cal_data *caldata, bool bChannelChange) | 1518 | struct ath9k_hw_cal_data *caldata, bool bChannelChange) |
1506 | { | 1519 | { |
1507 | struct ath_common *common = ath9k_hw_common(ah); | 1520 | struct ath_common *common = ath9k_hw_common(ah); |
1521 | struct ath9k_hw_mci *mci_hw = &ah->btcoex_hw.mci; | ||
1508 | u32 saveLedState; | 1522 | u32 saveLedState; |
1509 | struct ath9k_channel *curchan = ah->curchan; | 1523 | struct ath9k_channel *curchan = ah->curchan; |
1510 | u32 saveDefAntenna; | 1524 | u32 saveDefAntenna; |
@@ -1512,6 +1526,53 @@ int ath9k_hw_reset(struct ath_hw *ah, struct ath9k_channel *chan, | |||
1512 | u64 tsf = 0; | 1526 | u64 tsf = 0; |
1513 | int i, r; | 1527 | int i, r; |
1514 | bool allow_fbs = false; | 1528 | bool allow_fbs = false; |
1529 | bool mci = !!(ah->caps.hw_caps & ATH9K_HW_CAP_MCI); | ||
1530 | bool save_fullsleep = ah->chip_fullsleep; | ||
1531 | |||
1532 | if (mci) { | ||
1533 | |||
1534 | ar9003_mci_2g5g_changed(ah, IS_CHAN_2GHZ(chan)); | ||
1535 | |||
1536 | if (mci_hw->bt_state == MCI_BT_CAL_START) { | ||
1537 | u32 payload[4] = {0, 0, 0, 0}; | ||
1538 | |||
1539 | ath_dbg(common, ATH_DBG_MCI, "MCI stop rx for BT CAL"); | ||
1540 | |||
1541 | mci_hw->bt_state = MCI_BT_CAL; | ||
1542 | |||
1543 | /* | ||
1544 | * MCI FIX: disable mci interrupt here. This is to avoid | ||
1545 | * SW_MSG_DONE or RX_MSG bits to trigger MCI_INT and | ||
1546 | * lead to mci_intr reentry. | ||
1547 | */ | ||
1548 | |||
1549 | ar9003_mci_disable_interrupt(ah); | ||
1550 | |||
1551 | ath_dbg(common, ATH_DBG_MCI, "send WLAN_CAL_GRANT"); | ||
1552 | MCI_GPM_SET_CAL_TYPE(payload, MCI_GPM_WLAN_CAL_GRANT); | ||
1553 | ar9003_mci_send_message(ah, MCI_GPM, 0, payload, | ||
1554 | 16, true, false); | ||
1555 | |||
1556 | ath_dbg(common, ATH_DBG_MCI, "\nMCI BT is calibrating"); | ||
1557 | |||
1558 | /* Wait BT calibration to be completed for 25ms */ | ||
1559 | |||
1560 | if (ar9003_mci_wait_for_gpm(ah, MCI_GPM_BT_CAL_DONE, | ||
1561 | 0, 25000)) | ||
1562 | ath_dbg(common, ATH_DBG_MCI, | ||
1563 | "MCI got BT_CAL_DONE\n"); | ||
1564 | else | ||
1565 | ath_dbg(common, ATH_DBG_MCI, | ||
1566 | "MCI ### BT cal takes to long, force" | ||
1567 | "bt_state to be bt_awake\n"); | ||
1568 | mci_hw->bt_state = MCI_BT_AWAKE; | ||
1569 | /* MCI FIX: enable mci interrupt here */ | ||
1570 | ar9003_mci_enable_interrupt(ah); | ||
1571 | |||
1572 | return true; | ||
1573 | } | ||
1574 | } | ||
1575 | |||
1515 | 1576 | ||
1516 | if (!ath9k_hw_setpower(ah, ATH9K_PM_AWAKE)) | 1577 | if (!ath9k_hw_setpower(ah, ATH9K_PM_AWAKE)) |
1517 | return -EIO; | 1578 | return -EIO; |
@@ -1549,12 +1610,29 @@ int ath9k_hw_reset(struct ath_hw *ah, struct ath9k_channel *chan, | |||
1549 | if (ath9k_hw_channel_change(ah, chan)) { | 1610 | if (ath9k_hw_channel_change(ah, chan)) { |
1550 | ath9k_hw_loadnf(ah, ah->curchan); | 1611 | ath9k_hw_loadnf(ah, ah->curchan); |
1551 | ath9k_hw_start_nfcal(ah, true); | 1612 | ath9k_hw_start_nfcal(ah, true); |
1613 | if (mci && mci_hw->ready) | ||
1614 | ar9003_mci_2g5g_switch(ah, true); | ||
1615 | |||
1552 | if (AR_SREV_9271(ah)) | 1616 | if (AR_SREV_9271(ah)) |
1553 | ar9002_hw_load_ani_reg(ah, chan); | 1617 | ar9002_hw_load_ani_reg(ah, chan); |
1554 | return 0; | 1618 | return 0; |
1555 | } | 1619 | } |
1556 | } | 1620 | } |
1557 | 1621 | ||
1622 | if (mci) { | ||
1623 | ar9003_mci_disable_interrupt(ah); | ||
1624 | |||
1625 | if (mci_hw->ready && !save_fullsleep) { | ||
1626 | ar9003_mci_mute_bt(ah); | ||
1627 | udelay(20); | ||
1628 | REG_WRITE(ah, AR_BTCOEX_CTRL, 0); | ||
1629 | } | ||
1630 | |||
1631 | mci_hw->bt_state = MCI_BT_SLEEP; | ||
1632 | mci_hw->ready = false; | ||
1633 | } | ||
1634 | |||
1635 | |||
1558 | saveDefAntenna = REG_READ(ah, AR_DEF_ANTENNA); | 1636 | saveDefAntenna = REG_READ(ah, AR_DEF_ANTENNA); |
1559 | if (saveDefAntenna == 0) | 1637 | if (saveDefAntenna == 0) |
1560 | saveDefAntenna = 1; | 1638 | saveDefAntenna = 1; |
@@ -1610,6 +1688,9 @@ int ath9k_hw_reset(struct ath_hw *ah, struct ath9k_channel *chan, | |||
1610 | if (r) | 1688 | if (r) |
1611 | return r; | 1689 | return r; |
1612 | 1690 | ||
1691 | if (mci) | ||
1692 | ar9003_mci_reset(ah, false, IS_CHAN_2GHZ(chan), save_fullsleep); | ||
1693 | |||
1613 | /* | 1694 | /* |
1614 | * Some AR91xx SoC devices frequently fail to accept TSF writes | 1695 | * Some AR91xx SoC devices frequently fail to accept TSF writes |
1615 | * right after the chip reset. When that happens, write a new | 1696 | * right after the chip reset. When that happens, write a new |
@@ -1727,6 +1808,55 @@ int ath9k_hw_reset(struct ath_hw *ah, struct ath9k_channel *chan, | |||
1727 | ath9k_hw_loadnf(ah, chan); | 1808 | ath9k_hw_loadnf(ah, chan); |
1728 | ath9k_hw_start_nfcal(ah, true); | 1809 | ath9k_hw_start_nfcal(ah, true); |
1729 | 1810 | ||
1811 | if (mci && mci_hw->ready) { | ||
1812 | |||
1813 | if (IS_CHAN_2GHZ(chan) && | ||
1814 | (mci_hw->bt_state == MCI_BT_SLEEP)) { | ||
1815 | |||
1816 | if (ar9003_mci_check_int(ah, | ||
1817 | AR_MCI_INTERRUPT_RX_MSG_REMOTE_RESET) || | ||
1818 | ar9003_mci_check_int(ah, | ||
1819 | AR_MCI_INTERRUPT_RX_MSG_REQ_WAKE)) { | ||
1820 | |||
1821 | /* | ||
1822 | * BT is sleeping. Check if BT wakes up during | ||
1823 | * WLAN calibration. If BT wakes up during | ||
1824 | * WLAN calibration, need to go through all | ||
1825 | * message exchanges again and recal. | ||
1826 | */ | ||
1827 | |||
1828 | ath_dbg(common, ATH_DBG_MCI, "MCI BT wakes up" | ||
1829 | "during WLAN calibration\n"); | ||
1830 | |||
1831 | REG_WRITE(ah, AR_MCI_INTERRUPT_RX_MSG_RAW, | ||
1832 | AR_MCI_INTERRUPT_RX_MSG_REMOTE_RESET | | ||
1833 | AR_MCI_INTERRUPT_RX_MSG_REQ_WAKE); | ||
1834 | ath_dbg(common, ATH_DBG_MCI, "MCI send" | ||
1835 | "REMOTE_RESET\n"); | ||
1836 | ar9003_mci_remote_reset(ah, true); | ||
1837 | ar9003_mci_send_sys_waking(ah, true); | ||
1838 | udelay(1); | ||
1839 | if (IS_CHAN_2GHZ(chan)) | ||
1840 | ar9003_mci_send_lna_transfer(ah, true); | ||
1841 | |||
1842 | mci_hw->bt_state = MCI_BT_AWAKE; | ||
1843 | |||
1844 | ath_dbg(common, ATH_DBG_MCI, "MCI re-cal\n"); | ||
1845 | |||
1846 | if (caldata) { | ||
1847 | caldata->done_txiqcal_once = false; | ||
1848 | caldata->done_txclcal_once = false; | ||
1849 | caldata->rtt_hist.num_readings = 0; | ||
1850 | } | ||
1851 | |||
1852 | if (!ath9k_hw_init_cal(ah, chan)) | ||
1853 | return -EIO; | ||
1854 | |||
1855 | } | ||
1856 | } | ||
1857 | ar9003_mci_enable_interrupt(ah); | ||
1858 | } | ||
1859 | |||
1730 | ENABLE_REGWRITE_BUFFER(ah); | 1860 | ENABLE_REGWRITE_BUFFER(ah); |
1731 | 1861 | ||
1732 | ath9k_hw_restore_chainmask(ah); | 1862 | ath9k_hw_restore_chainmask(ah); |
@@ -1769,6 +1899,21 @@ int ath9k_hw_reset(struct ath_hw *ah, struct ath9k_channel *chan, | |||
1769 | if (ah->btcoex_hw.enabled) | 1899 | if (ah->btcoex_hw.enabled) |
1770 | ath9k_hw_btcoex_enable(ah); | 1900 | ath9k_hw_btcoex_enable(ah); |
1771 | 1901 | ||
1902 | if (mci && mci_hw->ready) { | ||
1903 | /* | ||
1904 | * check BT state again to make | ||
1905 | * sure it's not changed. | ||
1906 | */ | ||
1907 | |||
1908 | ar9003_mci_sync_bt_state(ah); | ||
1909 | ar9003_mci_2g5g_switch(ah, true); | ||
1910 | |||
1911 | if ((mci_hw->bt_state == MCI_BT_AWAKE) && | ||
1912 | (mci_hw->query_bt == true)) { | ||
1913 | mci_hw->need_flush_btinfo = true; | ||
1914 | } | ||
1915 | } | ||
1916 | |||
1772 | if (AR_SREV_9300_20_OR_LATER(ah)) { | 1917 | if (AR_SREV_9300_20_OR_LATER(ah)) { |
1773 | ar9003_hw_bb_watchdog_config(ah); | 1918 | ar9003_hw_bb_watchdog_config(ah); |
1774 | 1919 | ||
@@ -1826,7 +1971,8 @@ static void ath9k_set_power_sleep(struct ath_hw *ah, int setChip) | |||
1826 | } | 1971 | } |
1827 | 1972 | ||
1828 | /* Clear Bit 14 of AR_WA after putting chip into Full Sleep mode. */ | 1973 | /* Clear Bit 14 of AR_WA after putting chip into Full Sleep mode. */ |
1829 | REG_WRITE(ah, AR_WA, ah->WARegVal & ~AR_WA_D3_L1_DISABLE); | 1974 | if (AR_SREV_9300_20_OR_LATER(ah)) |
1975 | REG_WRITE(ah, AR_WA, ah->WARegVal & ~AR_WA_D3_L1_DISABLE); | ||
1830 | } | 1976 | } |
1831 | 1977 | ||
1832 | /* | 1978 | /* |
@@ -1932,6 +2078,7 @@ static bool ath9k_hw_set_power_awake(struct ath_hw *ah, int setChip) | |||
1932 | bool ath9k_hw_setpower(struct ath_hw *ah, enum ath9k_power_mode mode) | 2078 | bool ath9k_hw_setpower(struct ath_hw *ah, enum ath9k_power_mode mode) |
1933 | { | 2079 | { |
1934 | struct ath_common *common = ath9k_hw_common(ah); | 2080 | struct ath_common *common = ath9k_hw_common(ah); |
2081 | struct ath9k_hw_mci *mci = &ah->btcoex_hw.mci; | ||
1935 | int status = true, setChip = true; | 2082 | int status = true, setChip = true; |
1936 | static const char *modes[] = { | 2083 | static const char *modes[] = { |
1937 | "AWAKE", | 2084 | "AWAKE", |
@@ -1949,12 +2096,35 @@ bool ath9k_hw_setpower(struct ath_hw *ah, enum ath9k_power_mode mode) | |||
1949 | switch (mode) { | 2096 | switch (mode) { |
1950 | case ATH9K_PM_AWAKE: | 2097 | case ATH9K_PM_AWAKE: |
1951 | status = ath9k_hw_set_power_awake(ah, setChip); | 2098 | status = ath9k_hw_set_power_awake(ah, setChip); |
2099 | |||
2100 | if (ah->caps.hw_caps & ATH9K_HW_CAP_MCI) | ||
2101 | REG_WRITE(ah, AR_RTC_KEEP_AWAKE, 0x2); | ||
2102 | |||
1952 | break; | 2103 | break; |
1953 | case ATH9K_PM_FULL_SLEEP: | 2104 | case ATH9K_PM_FULL_SLEEP: |
2105 | |||
2106 | if (ah->caps.hw_caps & ATH9K_HW_CAP_MCI) { | ||
2107 | if (ar9003_mci_state(ah, MCI_STATE_ENABLE, NULL) && | ||
2108 | (mci->bt_state != MCI_BT_SLEEP) && | ||
2109 | !mci->halted_bt_gpm) { | ||
2110 | ath_dbg(common, ATH_DBG_MCI, "MCI halt BT GPM" | ||
2111 | "(full_sleep)"); | ||
2112 | ar9003_mci_send_coex_halt_bt_gpm(ah, | ||
2113 | true, true); | ||
2114 | } | ||
2115 | |||
2116 | mci->ready = false; | ||
2117 | REG_WRITE(ah, AR_RTC_KEEP_AWAKE, 0x2); | ||
2118 | } | ||
2119 | |||
1954 | ath9k_set_power_sleep(ah, setChip); | 2120 | ath9k_set_power_sleep(ah, setChip); |
1955 | ah->chip_fullsleep = true; | 2121 | ah->chip_fullsleep = true; |
1956 | break; | 2122 | break; |
1957 | case ATH9K_PM_NETWORK_SLEEP: | 2123 | case ATH9K_PM_NETWORK_SLEEP: |
2124 | |||
2125 | if (ah->caps.hw_caps & ATH9K_HW_CAP_MCI) | ||
2126 | REG_WRITE(ah, AR_RTC_KEEP_AWAKE, 0x2); | ||
2127 | |||
1958 | ath9k_set_power_network_sleep(ah, setChip); | 2128 | ath9k_set_power_network_sleep(ah, setChip); |
1959 | break; | 2129 | break; |
1960 | default: | 2130 | default: |
@@ -2107,6 +2277,30 @@ static u8 fixup_chainmask(u8 chip_chainmask, u8 eeprom_chainmask) | |||
2107 | return chip_chainmask; | 2277 | return chip_chainmask; |
2108 | } | 2278 | } |
2109 | 2279 | ||
2280 | /** | ||
2281 | * ath9k_hw_dfs_tested - checks if DFS has been tested with used chipset | ||
2282 | * @ah: the atheros hardware data structure | ||
2283 | * | ||
2284 | * We enable DFS support upstream on chipsets which have passed a series | ||
2285 | * of tests. The testing requirements are going to be documented. Desired | ||
2286 | * test requirements are documented at: | ||
2287 | * | ||
2288 | * http://wireless.kernel.org/en/users/Drivers/ath9k/dfs | ||
2289 | * | ||
2290 | * Once a new chipset gets properly tested an individual commit can be used | ||
2291 | * to document the testing for DFS for that chipset. | ||
2292 | */ | ||
2293 | static bool ath9k_hw_dfs_tested(struct ath_hw *ah) | ||
2294 | { | ||
2295 | |||
2296 | switch (ah->hw_version.macVersion) { | ||
2297 | /* AR9580 will likely be our first target to get testing on */ | ||
2298 | case AR_SREV_VERSION_9580: | ||
2299 | default: | ||
2300 | return false; | ||
2301 | } | ||
2302 | } | ||
2303 | |||
2110 | int ath9k_hw_fill_cap_info(struct ath_hw *ah) | 2304 | int ath9k_hw_fill_cap_info(struct ath_hw *ah) |
2111 | { | 2305 | { |
2112 | struct ath9k_hw_capabilities *pCap = &ah->caps; | 2306 | struct ath9k_hw_capabilities *pCap = &ah->caps; |
@@ -2147,6 +2341,8 @@ int ath9k_hw_fill_cap_info(struct ath_hw *ah) | |||
2147 | 2341 | ||
2148 | if (AR_SREV_9485(ah) || AR_SREV_9285(ah) || AR_SREV_9330(ah)) | 2342 | if (AR_SREV_9485(ah) || AR_SREV_9285(ah) || AR_SREV_9330(ah)) |
2149 | chip_chainmask = 1; | 2343 | chip_chainmask = 1; |
2344 | else if (AR_SREV_9462(ah)) | ||
2345 | chip_chainmask = 3; | ||
2150 | else if (!AR_SREV_9280_20_OR_LATER(ah)) | 2346 | else if (!AR_SREV_9280_20_OR_LATER(ah)) |
2151 | chip_chainmask = 7; | 2347 | chip_chainmask = 7; |
2152 | else if (!AR_SREV_9300_20_OR_LATER(ah) || AR_SREV_9340(ah)) | 2348 | else if (!AR_SREV_9300_20_OR_LATER(ah) || AR_SREV_9340(ah)) |
@@ -2203,12 +2399,10 @@ int ath9k_hw_fill_cap_info(struct ath_hw *ah) | |||
2203 | else | 2399 | else |
2204 | pCap->num_gpio_pins = AR_NUM_GPIO; | 2400 | pCap->num_gpio_pins = AR_NUM_GPIO; |
2205 | 2401 | ||
2206 | if (AR_SREV_9160_10_OR_LATER(ah) || AR_SREV_9100(ah)) { | 2402 | if (AR_SREV_9160_10_OR_LATER(ah) || AR_SREV_9100(ah)) |
2207 | pCap->hw_caps |= ATH9K_HW_CAP_CST; | ||
2208 | pCap->rts_aggr_limit = ATH_AMPDU_LIMIT_MAX; | 2403 | pCap->rts_aggr_limit = ATH_AMPDU_LIMIT_MAX; |
2209 | } else { | 2404 | else |
2210 | pCap->rts_aggr_limit = (8 * 1024); | 2405 | pCap->rts_aggr_limit = (8 * 1024); |
2211 | } | ||
2212 | 2406 | ||
2213 | #if defined(CONFIG_RFKILL) || defined(CONFIG_RFKILL_MODULE) | 2407 | #if defined(CONFIG_RFKILL) || defined(CONFIG_RFKILL_MODULE) |
2214 | ah->rfsilent = ah->eep_ops->get_eeprom(ah, EEP_RF_SILENT); | 2408 | ah->rfsilent = ah->eep_ops->get_eeprom(ah, EEP_RF_SILENT); |
@@ -2232,7 +2426,9 @@ int ath9k_hw_fill_cap_info(struct ath_hw *ah) | |||
2232 | pCap->hw_caps |= ATH9K_HW_CAP_4KB_SPLITTRANS; | 2426 | pCap->hw_caps |= ATH9K_HW_CAP_4KB_SPLITTRANS; |
2233 | 2427 | ||
2234 | if (common->btcoex_enabled) { | 2428 | if (common->btcoex_enabled) { |
2235 | if (AR_SREV_9300_20_OR_LATER(ah)) { | 2429 | if (AR_SREV_9462(ah)) |
2430 | btcoex_hw->scheme = ATH_BTCOEX_CFG_MCI; | ||
2431 | else if (AR_SREV_9300_20_OR_LATER(ah)) { | ||
2236 | btcoex_hw->scheme = ATH_BTCOEX_CFG_3WIRE; | 2432 | btcoex_hw->scheme = ATH_BTCOEX_CFG_3WIRE; |
2237 | btcoex_hw->btactive_gpio = ATH_BTACTIVE_GPIO_9300; | 2433 | btcoex_hw->btactive_gpio = ATH_BTACTIVE_GPIO_9300; |
2238 | btcoex_hw->wlanactive_gpio = ATH_WLANACTIVE_GPIO_9300; | 2434 | btcoex_hw->wlanactive_gpio = ATH_WLANACTIVE_GPIO_9300; |
@@ -2316,6 +2512,9 @@ int ath9k_hw_fill_cap_info(struct ath_hw *ah) | |||
2316 | pCap->pcie_lcr_offset = 0x80; | 2512 | pCap->pcie_lcr_offset = 0x80; |
2317 | } | 2513 | } |
2318 | 2514 | ||
2515 | if (ath9k_hw_dfs_tested(ah)) | ||
2516 | pCap->hw_caps |= ATH9K_HW_CAP_DFS; | ||
2517 | |||
2319 | tx_chainmask = pCap->tx_chainmask; | 2518 | tx_chainmask = pCap->tx_chainmask; |
2320 | rx_chainmask = pCap->rx_chainmask; | 2519 | rx_chainmask = pCap->rx_chainmask; |
2321 | while (tx_chainmask || rx_chainmask) { | 2520 | while (tx_chainmask || rx_chainmask) { |
@@ -2330,7 +2529,7 @@ int ath9k_hw_fill_cap_info(struct ath_hw *ah) | |||
2330 | 2529 | ||
2331 | if (AR_SREV_9300_20_OR_LATER(ah)) { | 2530 | if (AR_SREV_9300_20_OR_LATER(ah)) { |
2332 | ah->enabled_cals |= TX_IQ_CAL; | 2531 | ah->enabled_cals |= TX_IQ_CAL; |
2333 | if (!AR_SREV_9330(ah)) | 2532 | if (AR_SREV_9485_OR_LATER(ah)) |
2334 | ah->enabled_cals |= TX_IQ_ON_AGC_CAL; | 2533 | ah->enabled_cals |= TX_IQ_ON_AGC_CAL; |
2335 | } | 2534 | } |
2336 | if (AR_SREV_9462(ah)) | 2535 | if (AR_SREV_9462(ah)) |
diff --git a/drivers/net/wireless/ath/ath9k/hw.h b/drivers/net/wireless/ath/ath9k/hw.h index 3cb878c28ccf..615cc839f0de 100644 --- a/drivers/net/wireless/ath/ath9k/hw.h +++ b/drivers/net/wireless/ath/ath9k/hw.h | |||
@@ -126,6 +126,16 @@ | |||
126 | #define AR_GPIO_OUTPUT_MUX_AS_RX_CLEAR_EXTERNAL 4 | 126 | #define AR_GPIO_OUTPUT_MUX_AS_RX_CLEAR_EXTERNAL 4 |
127 | #define AR_GPIO_OUTPUT_MUX_AS_MAC_NETWORK_LED 5 | 127 | #define AR_GPIO_OUTPUT_MUX_AS_MAC_NETWORK_LED 5 |
128 | #define AR_GPIO_OUTPUT_MUX_AS_MAC_POWER_LED 6 | 128 | #define AR_GPIO_OUTPUT_MUX_AS_MAC_POWER_LED 6 |
129 | #define AR_GPIO_OUTPUT_MUX_AS_MCI_WLAN_DATA 0x16 | ||
130 | #define AR_GPIO_OUTPUT_MUX_AS_MCI_WLAN_CLK 0x17 | ||
131 | #define AR_GPIO_OUTPUT_MUX_AS_MCI_BT_DATA 0x18 | ||
132 | #define AR_GPIO_OUTPUT_MUX_AS_MCI_BT_CLK 0x19 | ||
133 | #define AR_GPIO_OUTPUT_MUX_AS_WL_IN_TX 0x14 | ||
134 | #define AR_GPIO_OUTPUT_MUX_AS_WL_IN_RX 0x13 | ||
135 | #define AR_GPIO_OUTPUT_MUX_AS_BT_IN_TX 9 | ||
136 | #define AR_GPIO_OUTPUT_MUX_AS_BT_IN_RX 8 | ||
137 | #define AR_GPIO_OUTPUT_MUX_AS_RUCKUS_STROBE 0x1d | ||
138 | #define AR_GPIO_OUTPUT_MUX_AS_RUCKUS_DATA 0x1e | ||
129 | 139 | ||
130 | #define AR_GPIOD_MASK 0x00001FFF | 140 | #define AR_GPIOD_MASK 0x00001FFF |
131 | #define AR_GPIO_BIT(_gpio) (1 << (_gpio)) | 141 | #define AR_GPIO_BIT(_gpio) (1 << (_gpio)) |
@@ -186,21 +196,21 @@ enum ath_ini_subsys { | |||
186 | enum ath9k_hw_caps { | 196 | enum ath9k_hw_caps { |
187 | ATH9K_HW_CAP_HT = BIT(0), | 197 | ATH9K_HW_CAP_HT = BIT(0), |
188 | ATH9K_HW_CAP_RFSILENT = BIT(1), | 198 | ATH9K_HW_CAP_RFSILENT = BIT(1), |
189 | ATH9K_HW_CAP_CST = BIT(2), | 199 | ATH9K_HW_CAP_AUTOSLEEP = BIT(2), |
190 | ATH9K_HW_CAP_AUTOSLEEP = BIT(4), | 200 | ATH9K_HW_CAP_4KB_SPLITTRANS = BIT(3), |
191 | ATH9K_HW_CAP_4KB_SPLITTRANS = BIT(5), | 201 | ATH9K_HW_CAP_EDMA = BIT(4), |
192 | ATH9K_HW_CAP_EDMA = BIT(6), | 202 | ATH9K_HW_CAP_RAC_SUPPORTED = BIT(5), |
193 | ATH9K_HW_CAP_RAC_SUPPORTED = BIT(7), | 203 | ATH9K_HW_CAP_LDPC = BIT(6), |
194 | ATH9K_HW_CAP_LDPC = BIT(8), | 204 | ATH9K_HW_CAP_FASTCLOCK = BIT(7), |
195 | ATH9K_HW_CAP_FASTCLOCK = BIT(9), | 205 | ATH9K_HW_CAP_SGI_20 = BIT(8), |
196 | ATH9K_HW_CAP_SGI_20 = BIT(10), | 206 | ATH9K_HW_CAP_PAPRD = BIT(9), |
197 | ATH9K_HW_CAP_PAPRD = BIT(11), | 207 | ATH9K_HW_CAP_ANT_DIV_COMB = BIT(10), |
198 | ATH9K_HW_CAP_ANT_DIV_COMB = BIT(12), | 208 | ATH9K_HW_CAP_2GHZ = BIT(11), |
199 | ATH9K_HW_CAP_2GHZ = BIT(13), | 209 | ATH9K_HW_CAP_5GHZ = BIT(12), |
200 | ATH9K_HW_CAP_5GHZ = BIT(14), | 210 | ATH9K_HW_CAP_APM = BIT(13), |
201 | ATH9K_HW_CAP_APM = BIT(15), | 211 | ATH9K_HW_CAP_RTT = BIT(14), |
202 | ATH9K_HW_CAP_RTT = BIT(16), | 212 | ATH9K_HW_CAP_MCI = BIT(15), |
203 | ATH9K_HW_CAP_MCI = BIT(17), | 213 | ATH9K_HW_CAP_DFS = BIT(16), |
204 | }; | 214 | }; |
205 | 215 | ||
206 | struct ath9k_hw_capabilities { | 216 | struct ath9k_hw_capabilities { |
@@ -266,6 +276,7 @@ enum ath9k_int { | |||
266 | ATH9K_INT_TX = 0x00000040, | 276 | ATH9K_INT_TX = 0x00000040, |
267 | ATH9K_INT_TXDESC = 0x00000080, | 277 | ATH9K_INT_TXDESC = 0x00000080, |
268 | ATH9K_INT_TIM_TIMER = 0x00000100, | 278 | ATH9K_INT_TIM_TIMER = 0x00000100, |
279 | ATH9K_INT_MCI = 0x00000200, | ||
269 | ATH9K_INT_BB_WATCHDOG = 0x00000400, | 280 | ATH9K_INT_BB_WATCHDOG = 0x00000400, |
270 | ATH9K_INT_TXURN = 0x00000800, | 281 | ATH9K_INT_TXURN = 0x00000800, |
271 | ATH9K_INT_MIB = 0x00001000, | 282 | ATH9K_INT_MIB = 0x00001000, |
@@ -417,6 +428,25 @@ enum ath9k_rx_qtype { | |||
417 | ATH9K_RX_QUEUE_MAX, | 428 | ATH9K_RX_QUEUE_MAX, |
418 | }; | 429 | }; |
419 | 430 | ||
431 | enum mci_message_header { /* length of payload */ | ||
432 | MCI_LNA_CTRL = 0x10, /* len = 0 */ | ||
433 | MCI_CONT_NACK = 0x20, /* len = 0 */ | ||
434 | MCI_CONT_INFO = 0x30, /* len = 4 */ | ||
435 | MCI_CONT_RST = 0x40, /* len = 0 */ | ||
436 | MCI_SCHD_INFO = 0x50, /* len = 16 */ | ||
437 | MCI_CPU_INT = 0x60, /* len = 4 */ | ||
438 | MCI_SYS_WAKING = 0x70, /* len = 0 */ | ||
439 | MCI_GPM = 0x80, /* len = 16 */ | ||
440 | MCI_LNA_INFO = 0x90, /* len = 1 */ | ||
441 | MCI_LNA_STATE = 0x94, | ||
442 | MCI_LNA_TAKE = 0x98, | ||
443 | MCI_LNA_TRANS = 0x9c, | ||
444 | MCI_SYS_SLEEPING = 0xa0, /* len = 0 */ | ||
445 | MCI_REQ_WAKE = 0xc0, /* len = 0 */ | ||
446 | MCI_DEBUG_16 = 0xfe, /* len = 2 */ | ||
447 | MCI_REMOTE_RESET = 0xff /* len = 16 */ | ||
448 | }; | ||
449 | |||
420 | enum ath_mci_gpm_coex_profile_type { | 450 | enum ath_mci_gpm_coex_profile_type { |
421 | MCI_GPM_COEX_PROFILE_UNKNOWN, | 451 | MCI_GPM_COEX_PROFILE_UNKNOWN, |
422 | MCI_GPM_COEX_PROFILE_RFCOMM, | 452 | MCI_GPM_COEX_PROFILE_RFCOMM, |
@@ -427,6 +457,132 @@ enum ath_mci_gpm_coex_profile_type { | |||
427 | MCI_GPM_COEX_PROFILE_MAX | 457 | MCI_GPM_COEX_PROFILE_MAX |
428 | }; | 458 | }; |
429 | 459 | ||
460 | /* MCI GPM/Coex opcode/type definitions */ | ||
461 | enum { | ||
462 | MCI_GPM_COEX_W_GPM_PAYLOAD = 1, | ||
463 | MCI_GPM_COEX_B_GPM_TYPE = 4, | ||
464 | MCI_GPM_COEX_B_GPM_OPCODE = 5, | ||
465 | /* MCI_GPM_WLAN_CAL_REQ, MCI_GPM_WLAN_CAL_DONE */ | ||
466 | MCI_GPM_WLAN_CAL_W_SEQUENCE = 2, | ||
467 | |||
468 | /* MCI_GPM_COEX_VERSION_QUERY */ | ||
469 | /* MCI_GPM_COEX_VERSION_RESPONSE */ | ||
470 | MCI_GPM_COEX_B_MAJOR_VERSION = 6, | ||
471 | MCI_GPM_COEX_B_MINOR_VERSION = 7, | ||
472 | /* MCI_GPM_COEX_STATUS_QUERY */ | ||
473 | MCI_GPM_COEX_B_BT_BITMAP = 6, | ||
474 | MCI_GPM_COEX_B_WLAN_BITMAP = 7, | ||
475 | /* MCI_GPM_COEX_HALT_BT_GPM */ | ||
476 | MCI_GPM_COEX_B_HALT_STATE = 6, | ||
477 | /* MCI_GPM_COEX_WLAN_CHANNELS */ | ||
478 | MCI_GPM_COEX_B_CHANNEL_MAP = 6, | ||
479 | /* MCI_GPM_COEX_BT_PROFILE_INFO */ | ||
480 | MCI_GPM_COEX_B_PROFILE_TYPE = 6, | ||
481 | MCI_GPM_COEX_B_PROFILE_LINKID = 7, | ||
482 | MCI_GPM_COEX_B_PROFILE_STATE = 8, | ||
483 | MCI_GPM_COEX_B_PROFILE_ROLE = 9, | ||
484 | MCI_GPM_COEX_B_PROFILE_RATE = 10, | ||
485 | MCI_GPM_COEX_B_PROFILE_VOTYPE = 11, | ||
486 | MCI_GPM_COEX_H_PROFILE_T = 12, | ||
487 | MCI_GPM_COEX_B_PROFILE_W = 14, | ||
488 | MCI_GPM_COEX_B_PROFILE_A = 15, | ||
489 | /* MCI_GPM_COEX_BT_STATUS_UPDATE */ | ||
490 | MCI_GPM_COEX_B_STATUS_TYPE = 6, | ||
491 | MCI_GPM_COEX_B_STATUS_LINKID = 7, | ||
492 | MCI_GPM_COEX_B_STATUS_STATE = 8, | ||
493 | /* MCI_GPM_COEX_BT_UPDATE_FLAGS */ | ||
494 | MCI_GPM_COEX_W_BT_FLAGS = 6, | ||
495 | MCI_GPM_COEX_B_BT_FLAGS_OP = 10 | ||
496 | }; | ||
497 | |||
498 | enum mci_gpm_subtype { | ||
499 | MCI_GPM_BT_CAL_REQ = 0, | ||
500 | MCI_GPM_BT_CAL_GRANT = 1, | ||
501 | MCI_GPM_BT_CAL_DONE = 2, | ||
502 | MCI_GPM_WLAN_CAL_REQ = 3, | ||
503 | MCI_GPM_WLAN_CAL_GRANT = 4, | ||
504 | MCI_GPM_WLAN_CAL_DONE = 5, | ||
505 | MCI_GPM_COEX_AGENT = 0x0c, | ||
506 | MCI_GPM_RSVD_PATTERN = 0xfe, | ||
507 | MCI_GPM_RSVD_PATTERN32 = 0xfefefefe, | ||
508 | MCI_GPM_BT_DEBUG = 0xff | ||
509 | }; | ||
510 | |||
511 | enum mci_bt_state { | ||
512 | MCI_BT_SLEEP, | ||
513 | MCI_BT_AWAKE, | ||
514 | MCI_BT_CAL_START, | ||
515 | MCI_BT_CAL | ||
516 | }; | ||
517 | |||
518 | /* Type of state query */ | ||
519 | enum mci_state_type { | ||
520 | MCI_STATE_ENABLE, | ||
521 | MCI_STATE_INIT_GPM_OFFSET, | ||
522 | MCI_STATE_NEXT_GPM_OFFSET, | ||
523 | MCI_STATE_LAST_GPM_OFFSET, | ||
524 | MCI_STATE_BT, | ||
525 | MCI_STATE_SET_BT_SLEEP, | ||
526 | MCI_STATE_SET_BT_AWAKE, | ||
527 | MCI_STATE_SET_BT_CAL_START, | ||
528 | MCI_STATE_SET_BT_CAL, | ||
529 | MCI_STATE_LAST_SCHD_MSG_OFFSET, | ||
530 | MCI_STATE_REMOTE_SLEEP, | ||
531 | MCI_STATE_CONT_RSSI_POWER, | ||
532 | MCI_STATE_CONT_PRIORITY, | ||
533 | MCI_STATE_CONT_TXRX, | ||
534 | MCI_STATE_RESET_REQ_WAKE, | ||
535 | MCI_STATE_SEND_WLAN_COEX_VERSION, | ||
536 | MCI_STATE_SET_BT_COEX_VERSION, | ||
537 | MCI_STATE_SEND_WLAN_CHANNELS, | ||
538 | MCI_STATE_SEND_VERSION_QUERY, | ||
539 | MCI_STATE_SEND_STATUS_QUERY, | ||
540 | MCI_STATE_NEED_FLUSH_BT_INFO, | ||
541 | MCI_STATE_SET_CONCUR_TX_PRI, | ||
542 | MCI_STATE_RECOVER_RX, | ||
543 | MCI_STATE_NEED_FTP_STOMP, | ||
544 | MCI_STATE_NEED_TUNING, | ||
545 | MCI_STATE_DEBUG, | ||
546 | MCI_STATE_MAX | ||
547 | }; | ||
548 | |||
549 | enum mci_gpm_coex_opcode { | ||
550 | MCI_GPM_COEX_VERSION_QUERY, | ||
551 | MCI_GPM_COEX_VERSION_RESPONSE, | ||
552 | MCI_GPM_COEX_STATUS_QUERY, | ||
553 | MCI_GPM_COEX_HALT_BT_GPM, | ||
554 | MCI_GPM_COEX_WLAN_CHANNELS, | ||
555 | MCI_GPM_COEX_BT_PROFILE_INFO, | ||
556 | MCI_GPM_COEX_BT_STATUS_UPDATE, | ||
557 | MCI_GPM_COEX_BT_UPDATE_FLAGS | ||
558 | }; | ||
559 | |||
560 | #define MCI_GPM_NOMORE 0 | ||
561 | #define MCI_GPM_MORE 1 | ||
562 | #define MCI_GPM_INVALID 0xffffffff | ||
563 | |||
564 | #define MCI_GPM_RECYCLE(_p_gpm) do { \ | ||
565 | *(((u32 *)_p_gpm) + MCI_GPM_COEX_W_GPM_PAYLOAD) = \ | ||
566 | MCI_GPM_RSVD_PATTERN32; \ | ||
567 | } while (0) | ||
568 | |||
569 | #define MCI_GPM_TYPE(_p_gpm) \ | ||
570 | (*(((u8 *)(_p_gpm)) + MCI_GPM_COEX_B_GPM_TYPE) & 0xff) | ||
571 | |||
572 | #define MCI_GPM_OPCODE(_p_gpm) \ | ||
573 | (*(((u8 *)(_p_gpm)) + MCI_GPM_COEX_B_GPM_OPCODE) & 0xff) | ||
574 | |||
575 | #define MCI_GPM_SET_CAL_TYPE(_p_gpm, _cal_type) do { \ | ||
576 | *(((u8 *)(_p_gpm)) + MCI_GPM_COEX_B_GPM_TYPE) = (_cal_type) & 0xff;\ | ||
577 | } while (0) | ||
578 | |||
579 | #define MCI_GPM_SET_TYPE_OPCODE(_p_gpm, _type, _opcode) do { \ | ||
580 | *(((u8 *)(_p_gpm)) + MCI_GPM_COEX_B_GPM_TYPE) = (_type) & 0xff; \ | ||
581 | *(((u8 *)(_p_gpm)) + MCI_GPM_COEX_B_GPM_OPCODE) = (_opcode) & 0xff;\ | ||
582 | } while (0) | ||
583 | |||
584 | #define MCI_GPM_IS_CAL_TYPE(_type) ((_type) <= MCI_GPM_WLAN_CAL_DONE) | ||
585 | |||
430 | struct ath9k_beacon_state { | 586 | struct ath9k_beacon_state { |
431 | u32 bs_nexttbtt; | 587 | u32 bs_nexttbtt; |
432 | u32 bs_nextdtim; | 588 | u32 bs_nextdtim; |
@@ -954,7 +1110,6 @@ bool ath9k_hw_disable(struct ath_hw *ah); | |||
954 | void ath9k_hw_set_txpowerlimit(struct ath_hw *ah, u32 limit, bool test); | 1110 | void ath9k_hw_set_txpowerlimit(struct ath_hw *ah, u32 limit, bool test); |
955 | void ath9k_hw_setopmode(struct ath_hw *ah); | 1111 | void ath9k_hw_setopmode(struct ath_hw *ah); |
956 | void ath9k_hw_setmcastfilter(struct ath_hw *ah, u32 filter0, u32 filter1); | 1112 | void ath9k_hw_setmcastfilter(struct ath_hw *ah, u32 filter0, u32 filter1); |
957 | void ath9k_hw_setbssidmask(struct ath_hw *ah); | ||
958 | void ath9k_hw_write_associd(struct ath_hw *ah); | 1113 | void ath9k_hw_write_associd(struct ath_hw *ah); |
959 | u32 ath9k_hw_gettsf32(struct ath_hw *ah); | 1114 | u32 ath9k_hw_gettsf32(struct ath_hw *ah); |
960 | u64 ath9k_hw_gettsf64(struct ath_hw *ah); | 1115 | u64 ath9k_hw_gettsf64(struct ath_hw *ah); |
@@ -1047,6 +1202,32 @@ void ath9k_ani_reset(struct ath_hw *ah, bool is_scanning); | |||
1047 | void ath9k_hw_proc_mib_event(struct ath_hw *ah); | 1202 | void ath9k_hw_proc_mib_event(struct ath_hw *ah); |
1048 | void ath9k_hw_ani_monitor(struct ath_hw *ah, struct ath9k_channel *chan); | 1203 | void ath9k_hw_ani_monitor(struct ath_hw *ah, struct ath9k_channel *chan); |
1049 | 1204 | ||
1205 | bool ar9003_mci_send_message(struct ath_hw *ah, u8 header, u32 flag, | ||
1206 | u32 *payload, u8 len, bool wait_done, | ||
1207 | bool check_bt); | ||
1208 | void ar9003_mci_mute_bt(struct ath_hw *ah); | ||
1209 | u32 ar9003_mci_state(struct ath_hw *ah, u32 state_type, u32 *p_data); | ||
1210 | void ar9003_mci_setup(struct ath_hw *ah, u32 gpm_addr, void *gpm_buf, | ||
1211 | u16 len, u32 sched_addr); | ||
1212 | void ar9003_mci_cleanup(struct ath_hw *ah); | ||
1213 | void ar9003_mci_send_coex_halt_bt_gpm(struct ath_hw *ah, bool halt, | ||
1214 | bool wait_done); | ||
1215 | u32 ar9003_mci_wait_for_gpm(struct ath_hw *ah, u8 gpm_type, | ||
1216 | u8 gpm_opcode, int time_out); | ||
1217 | void ar9003_mci_2g5g_changed(struct ath_hw *ah, bool is_2g); | ||
1218 | void ar9003_mci_disable_interrupt(struct ath_hw *ah); | ||
1219 | void ar9003_mci_enable_interrupt(struct ath_hw *ah); | ||
1220 | void ar9003_mci_2g5g_switch(struct ath_hw *ah, bool wait_done); | ||
1221 | void ar9003_mci_reset(struct ath_hw *ah, bool en_int, bool is_2g, | ||
1222 | bool is_full_sleep); | ||
1223 | bool ar9003_mci_check_int(struct ath_hw *ah, u32 ints); | ||
1224 | void ar9003_mci_remote_reset(struct ath_hw *ah, bool wait_done); | ||
1225 | void ar9003_mci_send_sys_waking(struct ath_hw *ah, bool wait_done); | ||
1226 | void ar9003_mci_send_lna_transfer(struct ath_hw *ah, bool wait_done); | ||
1227 | void ar9003_mci_sync_bt_state(struct ath_hw *ah); | ||
1228 | void ar9003_mci_get_interrupt(struct ath_hw *ah, u32 *raw_intr, | ||
1229 | u32 *rx_msg_intr); | ||
1230 | |||
1050 | #define ATH9K_CLOCK_RATE_CCK 22 | 1231 | #define ATH9K_CLOCK_RATE_CCK 22 |
1051 | #define ATH9K_CLOCK_RATE_5GHZ_OFDM 40 | 1232 | #define ATH9K_CLOCK_RATE_5GHZ_OFDM 40 |
1052 | #define ATH9K_CLOCK_RATE_2GHZ_OFDM 44 | 1233 | #define ATH9K_CLOCK_RATE_2GHZ_OFDM 44 |
diff --git a/drivers/net/wireless/ath/ath9k/init.c b/drivers/net/wireless/ath/ath9k/init.c index 5cb0599b01c2..c5df98139c4d 100644 --- a/drivers/net/wireless/ath/ath9k/init.c +++ b/drivers/net/wireless/ath/ath9k/init.c | |||
@@ -17,6 +17,7 @@ | |||
17 | #include <linux/dma-mapping.h> | 17 | #include <linux/dma-mapping.h> |
18 | #include <linux/slab.h> | 18 | #include <linux/slab.h> |
19 | #include <linux/ath9k_platform.h> | 19 | #include <linux/ath9k_platform.h> |
20 | #include <linux/module.h> | ||
20 | 21 | ||
21 | #include "ath9k.h" | 22 | #include "ath9k.h" |
22 | 23 | ||
@@ -257,6 +258,8 @@ static void setup_ht_cap(struct ath_softc *sc, | |||
257 | 258 | ||
258 | if (AR_SREV_9330(ah) || AR_SREV_9485(ah)) | 259 | if (AR_SREV_9330(ah) || AR_SREV_9485(ah)) |
259 | max_streams = 1; | 260 | max_streams = 1; |
261 | else if (AR_SREV_9462(ah)) | ||
262 | max_streams = 2; | ||
260 | else if (AR_SREV_9300_20_OR_LATER(ah)) | 263 | else if (AR_SREV_9300_20_OR_LATER(ah)) |
261 | max_streams = 3; | 264 | max_streams = 3; |
262 | else | 265 | else |
@@ -294,9 +297,22 @@ static int ath9k_reg_notifier(struct wiphy *wiphy, | |||
294 | { | 297 | { |
295 | struct ieee80211_hw *hw = wiphy_to_ieee80211_hw(wiphy); | 298 | struct ieee80211_hw *hw = wiphy_to_ieee80211_hw(wiphy); |
296 | struct ath_softc *sc = hw->priv; | 299 | struct ath_softc *sc = hw->priv; |
297 | struct ath_regulatory *reg = ath9k_hw_regulatory(sc->sc_ah); | 300 | struct ath_hw *ah = sc->sc_ah; |
301 | struct ath_regulatory *reg = ath9k_hw_regulatory(ah); | ||
302 | int ret; | ||
303 | |||
304 | ret = ath_reg_notifier_apply(wiphy, request, reg); | ||
305 | |||
306 | /* Set tx power */ | ||
307 | if (ah->curchan) { | ||
308 | sc->config.txpowlimit = 2 * ah->curchan->chan->max_power; | ||
309 | ath9k_ps_wakeup(sc); | ||
310 | ath9k_hw_set_txpowerlimit(ah, sc->config.txpowlimit, false); | ||
311 | sc->curtxpow = ath9k_hw_regulatory(ah)->power_limit; | ||
312 | ath9k_ps_restore(sc); | ||
313 | } | ||
298 | 314 | ||
299 | return ath_reg_notifier_apply(wiphy, request, reg); | 315 | return ret; |
300 | } | 316 | } |
301 | 317 | ||
302 | /* | 318 | /* |
@@ -407,6 +423,7 @@ fail: | |||
407 | static int ath9k_init_btcoex(struct ath_softc *sc) | 423 | static int ath9k_init_btcoex(struct ath_softc *sc) |
408 | { | 424 | { |
409 | struct ath_txq *txq; | 425 | struct ath_txq *txq; |
426 | struct ath_hw *ah = sc->sc_ah; | ||
410 | int r; | 427 | int r; |
411 | 428 | ||
412 | switch (sc->sc_ah->btcoex_hw.scheme) { | 429 | switch (sc->sc_ah->btcoex_hw.scheme) { |
@@ -423,8 +440,37 @@ static int ath9k_init_btcoex(struct ath_softc *sc) | |||
423 | txq = sc->tx.txq_map[WME_AC_BE]; | 440 | txq = sc->tx.txq_map[WME_AC_BE]; |
424 | ath9k_hw_init_btcoex_hw(sc->sc_ah, txq->axq_qnum); | 441 | ath9k_hw_init_btcoex_hw(sc->sc_ah, txq->axq_qnum); |
425 | sc->btcoex.bt_stomp_type = ATH_BTCOEX_STOMP_LOW; | 442 | sc->btcoex.bt_stomp_type = ATH_BTCOEX_STOMP_LOW; |
443 | break; | ||
444 | case ATH_BTCOEX_CFG_MCI: | ||
445 | sc->btcoex.bt_stomp_type = ATH_BTCOEX_STOMP_LOW; | ||
426 | sc->btcoex.duty_cycle = ATH_BTCOEX_DEF_DUTY_CYCLE; | 446 | sc->btcoex.duty_cycle = ATH_BTCOEX_DEF_DUTY_CYCLE; |
427 | INIT_LIST_HEAD(&sc->btcoex.mci.info); | 447 | INIT_LIST_HEAD(&sc->btcoex.mci.info); |
448 | |||
449 | r = ath_mci_setup(sc); | ||
450 | if (r) | ||
451 | return r; | ||
452 | |||
453 | if (sc->sc_ah->caps.hw_caps & ATH9K_HW_CAP_MCI) { | ||
454 | ah->btcoex_hw.mci.ready = false; | ||
455 | ah->btcoex_hw.mci.bt_state = 0; | ||
456 | ah->btcoex_hw.mci.bt_ver_major = 3; | ||
457 | ah->btcoex_hw.mci.bt_ver_minor = 0; | ||
458 | ah->btcoex_hw.mci.bt_version_known = false; | ||
459 | ah->btcoex_hw.mci.update_2g5g = true; | ||
460 | ah->btcoex_hw.mci.is_2g = true; | ||
461 | ah->btcoex_hw.mci.wlan_channels_update = false; | ||
462 | ah->btcoex_hw.mci.wlan_channels[0] = 0x00000000; | ||
463 | ah->btcoex_hw.mci.wlan_channels[1] = 0xffffffff; | ||
464 | ah->btcoex_hw.mci.wlan_channels[2] = 0xffffffff; | ||
465 | ah->btcoex_hw.mci.wlan_channels[3] = 0x7fffffff; | ||
466 | ah->btcoex_hw.mci.query_bt = true; | ||
467 | ah->btcoex_hw.mci.unhalt_bt_gpm = true; | ||
468 | ah->btcoex_hw.mci.halted_bt_gpm = false; | ||
469 | ah->btcoex_hw.mci.need_flush_btinfo = false; | ||
470 | ah->btcoex_hw.mci.wlan_cal_seq = 0; | ||
471 | ah->btcoex_hw.mci.wlan_cal_done = 0; | ||
472 | ah->btcoex_hw.mci.config = 0x2201; | ||
473 | } | ||
428 | break; | 474 | break; |
429 | default: | 475 | default: |
430 | WARN_ON(1); | 476 | WARN_ON(1); |
@@ -838,6 +884,9 @@ static void ath9k_deinit_softc(struct ath_softc *sc) | |||
838 | sc->sc_ah->btcoex_hw.scheme == ATH_BTCOEX_CFG_3WIRE) | 884 | sc->sc_ah->btcoex_hw.scheme == ATH_BTCOEX_CFG_3WIRE) |
839 | ath_gen_timer_free(sc->sc_ah, sc->btcoex.no_stomp_timer); | 885 | ath_gen_timer_free(sc->sc_ah, sc->btcoex.no_stomp_timer); |
840 | 886 | ||
887 | if (sc->sc_ah->btcoex_hw.scheme == ATH_BTCOEX_CFG_MCI) | ||
888 | ath_mci_cleanup(sc); | ||
889 | |||
841 | for (i = 0; i < ATH9K_NUM_TX_QUEUES; i++) | 890 | for (i = 0; i < ATH9K_NUM_TX_QUEUES; i++) |
842 | if (ATH_TXQ_SETUP(sc, i)) | 891 | if (ATH_TXQ_SETUP(sc, i)) |
843 | ath_tx_cleanupq(sc, &sc->tx.txq[i]); | 892 | ath_tx_cleanupq(sc, &sc->tx.txq[i]); |
diff --git a/drivers/net/wireless/ath/ath9k/mac.c b/drivers/net/wireless/ath/ath9k/mac.c index 6a8fdf33a527..0e4fbb3bea33 100644 --- a/drivers/net/wireless/ath/ath9k/mac.c +++ b/drivers/net/wireless/ath/ath9k/mac.c | |||
@@ -16,6 +16,7 @@ | |||
16 | 16 | ||
17 | #include "hw.h" | 17 | #include "hw.h" |
18 | #include "hw-ops.h" | 18 | #include "hw-ops.h" |
19 | #include <linux/export.h> | ||
19 | 20 | ||
20 | static void ath9k_hw_set_txq_interrupts(struct ath_hw *ah, | 21 | static void ath9k_hw_set_txq_interrupts(struct ath_hw *ah, |
21 | struct ath9k_tx_queue_info *qi) | 22 | struct ath9k_tx_queue_info *qi) |
@@ -759,7 +760,10 @@ bool ath9k_hw_intrpend(struct ath_hw *ah) | |||
759 | return true; | 760 | return true; |
760 | 761 | ||
761 | host_isr = REG_READ(ah, AR_INTR_ASYNC_CAUSE); | 762 | host_isr = REG_READ(ah, AR_INTR_ASYNC_CAUSE); |
762 | if ((host_isr & AR_INTR_MAC_IRQ) && (host_isr != AR_INTR_SPURIOUS)) | 763 | |
764 | if (((host_isr & AR_INTR_MAC_IRQ) || | ||
765 | (host_isr & AR_INTR_ASYNC_MASK_MCI)) && | ||
766 | (host_isr != AR_INTR_SPURIOUS)) | ||
763 | return true; | 767 | return true; |
764 | 768 | ||
765 | host_isr = REG_READ(ah, AR_INTR_SYNC_CAUSE); | 769 | host_isr = REG_READ(ah, AR_INTR_SYNC_CAUSE); |
@@ -797,6 +801,7 @@ void ath9k_hw_enable_interrupts(struct ath_hw *ah) | |||
797 | { | 801 | { |
798 | struct ath_common *common = ath9k_hw_common(ah); | 802 | struct ath_common *common = ath9k_hw_common(ah); |
799 | u32 sync_default = AR_INTR_SYNC_DEFAULT; | 803 | u32 sync_default = AR_INTR_SYNC_DEFAULT; |
804 | u32 async_mask; | ||
800 | 805 | ||
801 | if (!(ah->imask & ATH9K_INT_GLOBAL)) | 806 | if (!(ah->imask & ATH9K_INT_GLOBAL)) |
802 | return; | 807 | return; |
@@ -811,13 +816,16 @@ void ath9k_hw_enable_interrupts(struct ath_hw *ah) | |||
811 | if (AR_SREV_9340(ah)) | 816 | if (AR_SREV_9340(ah)) |
812 | sync_default &= ~AR_INTR_SYNC_HOST1_FATAL; | 817 | sync_default &= ~AR_INTR_SYNC_HOST1_FATAL; |
813 | 818 | ||
819 | async_mask = AR_INTR_MAC_IRQ; | ||
820 | |||
821 | if (ah->imask & ATH9K_INT_MCI) | ||
822 | async_mask |= AR_INTR_ASYNC_MASK_MCI; | ||
823 | |||
814 | ath_dbg(common, ATH_DBG_INTERRUPT, "enable IER\n"); | 824 | ath_dbg(common, ATH_DBG_INTERRUPT, "enable IER\n"); |
815 | REG_WRITE(ah, AR_IER, AR_IER_ENABLE); | 825 | REG_WRITE(ah, AR_IER, AR_IER_ENABLE); |
816 | if (!AR_SREV_9100(ah)) { | 826 | if (!AR_SREV_9100(ah)) { |
817 | REG_WRITE(ah, AR_INTR_ASYNC_ENABLE, | 827 | REG_WRITE(ah, AR_INTR_ASYNC_ENABLE, async_mask); |
818 | AR_INTR_MAC_IRQ); | 828 | REG_WRITE(ah, AR_INTR_ASYNC_MASK, async_mask); |
819 | REG_WRITE(ah, AR_INTR_ASYNC_MASK, AR_INTR_MAC_IRQ); | ||
820 | |||
821 | 829 | ||
822 | REG_WRITE(ah, AR_INTR_SYNC_ENABLE, sync_default); | 830 | REG_WRITE(ah, AR_INTR_SYNC_ENABLE, sync_default); |
823 | REG_WRITE(ah, AR_INTR_SYNC_MASK, sync_default); | 831 | REG_WRITE(ah, AR_INTR_SYNC_MASK, sync_default); |
diff --git a/drivers/net/wireless/ath/ath9k/main.c b/drivers/net/wireless/ath/ath9k/main.c index e43c41cff25b..7fbc4bdd4efe 100644 --- a/drivers/net/wireless/ath/ath9k/main.c +++ b/drivers/net/wireless/ath/ath9k/main.c | |||
@@ -118,7 +118,7 @@ void ath9k_ps_restore(struct ath_softc *sc) | |||
118 | if (--sc->ps_usecount != 0) | 118 | if (--sc->ps_usecount != 0) |
119 | goto unlock; | 119 | goto unlock; |
120 | 120 | ||
121 | if (sc->ps_idle) | 121 | if (sc->ps_idle && (sc->ps_flags & PS_WAIT_FOR_TX_ACK)) |
122 | mode = ATH9K_PM_FULL_SLEEP; | 122 | mode = ATH9K_PM_FULL_SLEEP; |
123 | else if (sc->ps_enabled && | 123 | else if (sc->ps_enabled && |
124 | !(sc->ps_flags & (PS_WAIT_FOR_BEACON | | 124 | !(sc->ps_flags & (PS_WAIT_FOR_BEACON | |
@@ -286,7 +286,7 @@ static bool ath_complete_reset(struct ath_softc *sc, bool start) | |||
286 | ath_start_ani(common); | 286 | ath_start_ani(common); |
287 | } | 287 | } |
288 | 288 | ||
289 | if (ath9k_hw_ops(ah)->antdiv_comb_conf_get && sc->ant_rx != 3) { | 289 | if ((ah->caps.hw_caps & ATH9K_HW_CAP_ANT_DIV_COMB) && sc->ant_rx != 3) { |
290 | struct ath_hw_antcomb_conf div_ant_conf; | 290 | struct ath_hw_antcomb_conf div_ant_conf; |
291 | u8 lna_conf; | 291 | u8 lna_conf; |
292 | 292 | ||
@@ -332,7 +332,8 @@ static int ath_reset_internal(struct ath_softc *sc, struct ath9k_channel *hchan, | |||
332 | hchan = ah->curchan; | 332 | hchan = ah->curchan; |
333 | } | 333 | } |
334 | 334 | ||
335 | if (fastcc && !ath9k_hw_check_alive(ah)) | 335 | if (fastcc && (ah->chip_fullsleep || |
336 | !ath9k_hw_check_alive(ah))) | ||
336 | fastcc = false; | 337 | fastcc = false; |
337 | 338 | ||
338 | if (!ath_prepare_reset(sc, retry_tx, flush)) | 339 | if (!ath_prepare_reset(sc, retry_tx, flush)) |
@@ -561,7 +562,6 @@ void ath_ani_calibrate(unsigned long data) | |||
561 | /* Long calibration runs independently of short calibration. */ | 562 | /* Long calibration runs independently of short calibration. */ |
562 | if ((timestamp - common->ani.longcal_timer) >= long_cal_interval) { | 563 | if ((timestamp - common->ani.longcal_timer) >= long_cal_interval) { |
563 | longcal = true; | 564 | longcal = true; |
564 | ath_dbg(common, ATH_DBG_ANI, "longcal @%lu\n", jiffies); | ||
565 | common->ani.longcal_timer = timestamp; | 565 | common->ani.longcal_timer = timestamp; |
566 | } | 566 | } |
567 | 567 | ||
@@ -569,8 +569,6 @@ void ath_ani_calibrate(unsigned long data) | |||
569 | if (!common->ani.caldone) { | 569 | if (!common->ani.caldone) { |
570 | if ((timestamp - common->ani.shortcal_timer) >= short_cal_interval) { | 570 | if ((timestamp - common->ani.shortcal_timer) >= short_cal_interval) { |
571 | shortcal = true; | 571 | shortcal = true; |
572 | ath_dbg(common, ATH_DBG_ANI, | ||
573 | "shortcal @%lu\n", jiffies); | ||
574 | common->ani.shortcal_timer = timestamp; | 572 | common->ani.shortcal_timer = timestamp; |
575 | common->ani.resetcal_timer = timestamp; | 573 | common->ani.resetcal_timer = timestamp; |
576 | } | 574 | } |
@@ -584,8 +582,9 @@ void ath_ani_calibrate(unsigned long data) | |||
584 | } | 582 | } |
585 | 583 | ||
586 | /* Verify whether we must check ANI */ | 584 | /* Verify whether we must check ANI */ |
587 | if ((timestamp - common->ani.checkani_timer) >= | 585 | if (sc->sc_ah->config.enable_ani |
588 | ah->config.ani_poll_interval) { | 586 | && (timestamp - common->ani.checkani_timer) >= |
587 | ah->config.ani_poll_interval) { | ||
589 | aniflag = true; | 588 | aniflag = true; |
590 | common->ani.checkani_timer = timestamp; | 589 | common->ani.checkani_timer = timestamp; |
591 | } | 590 | } |
@@ -605,6 +604,11 @@ void ath_ani_calibrate(unsigned long data) | |||
605 | ah->rxchainmask, longcal); | 604 | ah->rxchainmask, longcal); |
606 | } | 605 | } |
607 | 606 | ||
607 | ath_dbg(common, ATH_DBG_ANI, | ||
608 | "Calibration @%lu finished: %s %s %s, caldone: %s\n", jiffies, | ||
609 | longcal ? "long" : "", shortcal ? "short" : "", | ||
610 | aniflag ? "ani" : "", common->ani.caldone ? "true" : "false"); | ||
611 | |||
608 | ath9k_ps_restore(sc); | 612 | ath9k_ps_restore(sc); |
609 | 613 | ||
610 | set_timer: | 614 | set_timer: |
@@ -640,9 +644,9 @@ static void ath_node_attach(struct ath_softc *sc, struct ieee80211_sta *sta, | |||
640 | spin_lock(&sc->nodes_lock); | 644 | spin_lock(&sc->nodes_lock); |
641 | list_add(&an->list, &sc->nodes); | 645 | list_add(&an->list, &sc->nodes); |
642 | spin_unlock(&sc->nodes_lock); | 646 | spin_unlock(&sc->nodes_lock); |
647 | #endif | ||
643 | an->sta = sta; | 648 | an->sta = sta; |
644 | an->vif = vif; | 649 | an->vif = vif; |
645 | #endif | ||
646 | if (sc->sc_flags & SC_OP_TXAGGR) { | 650 | if (sc->sc_flags & SC_OP_TXAGGR) { |
647 | ath_tx_node_init(sc, an); | 651 | ath_tx_node_init(sc, an); |
648 | an->maxampdu = 1 << (IEEE80211_HT_MAX_AMPDU_FACTOR + | 652 | an->maxampdu = 1 << (IEEE80211_HT_MAX_AMPDU_FACTOR + |
@@ -742,6 +746,9 @@ void ath9k_tasklet(unsigned long data) | |||
742 | if (status & ATH9K_INT_GENTIMER) | 746 | if (status & ATH9K_INT_GENTIMER) |
743 | ath_gen_timer_isr(sc->sc_ah); | 747 | ath_gen_timer_isr(sc->sc_ah); |
744 | 748 | ||
749 | if (status & ATH9K_INT_MCI) | ||
750 | ath_mci_intr(sc); | ||
751 | |||
745 | out: | 752 | out: |
746 | /* re-enable hardware interrupt */ | 753 | /* re-enable hardware interrupt */ |
747 | ath9k_hw_enable_interrupts(ah); | 754 | ath9k_hw_enable_interrupts(ah); |
@@ -764,7 +771,8 @@ irqreturn_t ath_isr(int irq, void *dev) | |||
764 | ATH9K_INT_BMISS | \ | 771 | ATH9K_INT_BMISS | \ |
765 | ATH9K_INT_CST | \ | 772 | ATH9K_INT_CST | \ |
766 | ATH9K_INT_TSFOOR | \ | 773 | ATH9K_INT_TSFOOR | \ |
767 | ATH9K_INT_GENTIMER) | 774 | ATH9K_INT_GENTIMER | \ |
775 | ATH9K_INT_MCI) | ||
768 | 776 | ||
769 | struct ath_softc *sc = dev; | 777 | struct ath_softc *sc = dev; |
770 | struct ath_hw *ah = sc->sc_ah; | 778 | struct ath_hw *ah = sc->sc_ah; |
@@ -882,82 +890,6 @@ chip_reset: | |||
882 | #undef SCHED_INTR | 890 | #undef SCHED_INTR |
883 | } | 891 | } |
884 | 892 | ||
885 | static void ath_radio_enable(struct ath_softc *sc, struct ieee80211_hw *hw) | ||
886 | { | ||
887 | struct ath_hw *ah = sc->sc_ah; | ||
888 | struct ath_common *common = ath9k_hw_common(ah); | ||
889 | struct ieee80211_channel *channel = hw->conf.channel; | ||
890 | int r; | ||
891 | |||
892 | ath9k_ps_wakeup(sc); | ||
893 | spin_lock_bh(&sc->sc_pcu_lock); | ||
894 | atomic_set(&ah->intr_ref_cnt, -1); | ||
895 | |||
896 | ath9k_hw_configpcipowersave(ah, false); | ||
897 | |||
898 | if (!ah->curchan) | ||
899 | ah->curchan = ath9k_cmn_get_curchannel(sc->hw, ah); | ||
900 | |||
901 | r = ath9k_hw_reset(ah, ah->curchan, ah->caldata, false); | ||
902 | if (r) { | ||
903 | ath_err(common, | ||
904 | "Unable to reset channel (%u MHz), reset status %d\n", | ||
905 | channel->center_freq, r); | ||
906 | } | ||
907 | |||
908 | ath_complete_reset(sc, true); | ||
909 | |||
910 | /* Enable LED */ | ||
911 | ath9k_hw_cfg_output(ah, ah->led_pin, | ||
912 | AR_GPIO_OUTPUT_MUX_AS_OUTPUT); | ||
913 | ath9k_hw_set_gpio(ah, ah->led_pin, 0); | ||
914 | |||
915 | spin_unlock_bh(&sc->sc_pcu_lock); | ||
916 | |||
917 | ath9k_ps_restore(sc); | ||
918 | } | ||
919 | |||
920 | void ath_radio_disable(struct ath_softc *sc, struct ieee80211_hw *hw) | ||
921 | { | ||
922 | struct ath_hw *ah = sc->sc_ah; | ||
923 | struct ieee80211_channel *channel = hw->conf.channel; | ||
924 | int r; | ||
925 | |||
926 | ath9k_ps_wakeup(sc); | ||
927 | |||
928 | ath_cancel_work(sc); | ||
929 | |||
930 | spin_lock_bh(&sc->sc_pcu_lock); | ||
931 | |||
932 | /* | ||
933 | * Keep the LED on when the radio is disabled | ||
934 | * during idle unassociated state. | ||
935 | */ | ||
936 | if (!sc->ps_idle) { | ||
937 | ath9k_hw_set_gpio(ah, ah->led_pin, 1); | ||
938 | ath9k_hw_cfg_gpio_input(ah, ah->led_pin); | ||
939 | } | ||
940 | |||
941 | ath_prepare_reset(sc, false, true); | ||
942 | |||
943 | if (!ah->curchan) | ||
944 | ah->curchan = ath9k_cmn_get_curchannel(hw, ah); | ||
945 | |||
946 | r = ath9k_hw_reset(ah, ah->curchan, ah->caldata, false); | ||
947 | if (r) { | ||
948 | ath_err(ath9k_hw_common(sc->sc_ah), | ||
949 | "Unable to reset channel (%u MHz), reset status %d\n", | ||
950 | channel->center_freq, r); | ||
951 | } | ||
952 | |||
953 | ath9k_hw_phy_disable(ah); | ||
954 | |||
955 | ath9k_hw_configpcipowersave(ah, true); | ||
956 | |||
957 | spin_unlock_bh(&sc->sc_pcu_lock); | ||
958 | ath9k_ps_restore(sc); | ||
959 | } | ||
960 | |||
961 | static int ath_reset(struct ath_softc *sc, bool retry_tx) | 893 | static int ath_reset(struct ath_softc *sc, bool retry_tx) |
962 | { | 894 | { |
963 | int r; | 895 | int r; |
@@ -1093,6 +1025,9 @@ static int ath9k_start(struct ieee80211_hw *hw) | |||
1093 | * and then setup of the interrupt mask. | 1025 | * and then setup of the interrupt mask. |
1094 | */ | 1026 | */ |
1095 | spin_lock_bh(&sc->sc_pcu_lock); | 1027 | spin_lock_bh(&sc->sc_pcu_lock); |
1028 | |||
1029 | atomic_set(&ah->intr_ref_cnt, -1); | ||
1030 | |||
1096 | r = ath9k_hw_reset(ah, init_channel, ah->caldata, false); | 1031 | r = ath9k_hw_reset(ah, init_channel, ah->caldata, false); |
1097 | if (r) { | 1032 | if (r) { |
1098 | ath_err(common, | 1033 | ath_err(common, |
@@ -1119,6 +1054,9 @@ static int ath9k_start(struct ieee80211_hw *hw) | |||
1119 | if (ah->caps.hw_caps & ATH9K_HW_CAP_HT) | 1054 | if (ah->caps.hw_caps & ATH9K_HW_CAP_HT) |
1120 | ah->imask |= ATH9K_INT_CST; | 1055 | ah->imask |= ATH9K_INT_CST; |
1121 | 1056 | ||
1057 | if (ah->caps.hw_caps & ATH9K_HW_CAP_MCI) | ||
1058 | ah->imask |= ATH9K_INT_MCI; | ||
1059 | |||
1122 | sc->sc_flags &= ~SC_OP_INVALID; | 1060 | sc->sc_flags &= ~SC_OP_INVALID; |
1123 | sc->sc_ah->is_monitoring = false; | 1061 | sc->sc_ah->is_monitoring = false; |
1124 | 1062 | ||
@@ -1131,6 +1069,18 @@ static int ath9k_start(struct ieee80211_hw *hw) | |||
1131 | goto mutex_unlock; | 1069 | goto mutex_unlock; |
1132 | } | 1070 | } |
1133 | 1071 | ||
1072 | if (ah->led_pin >= 0) { | ||
1073 | ath9k_hw_cfg_output(ah, ah->led_pin, | ||
1074 | AR_GPIO_OUTPUT_MUX_AS_OUTPUT); | ||
1075 | ath9k_hw_set_gpio(ah, ah->led_pin, 0); | ||
1076 | } | ||
1077 | |||
1078 | /* | ||
1079 | * Reset key cache to sane defaults (all entries cleared) instead of | ||
1080 | * semi-random values after suspend/resume. | ||
1081 | */ | ||
1082 | ath9k_cmn_init_crypto(sc->sc_ah); | ||
1083 | |||
1134 | spin_unlock_bh(&sc->sc_pcu_lock); | 1084 | spin_unlock_bh(&sc->sc_pcu_lock); |
1135 | 1085 | ||
1136 | if ((ah->btcoex_hw.scheme != ATH_BTCOEX_CFG_NONE) && | 1086 | if ((ah->btcoex_hw.scheme != ATH_BTCOEX_CFG_NONE) && |
@@ -1176,6 +1126,13 @@ static void ath9k_tx(struct ieee80211_hw *hw, struct sk_buff *skb) | |||
1176 | } | 1126 | } |
1177 | } | 1127 | } |
1178 | 1128 | ||
1129 | /* | ||
1130 | * Cannot tx while the hardware is in full sleep, it first needs a full | ||
1131 | * chip reset to recover from that | ||
1132 | */ | ||
1133 | if (unlikely(sc->sc_ah->power_mode == ATH9K_PM_FULL_SLEEP)) | ||
1134 | goto exit; | ||
1135 | |||
1179 | if (unlikely(sc->sc_ah->power_mode != ATH9K_PM_AWAKE)) { | 1136 | if (unlikely(sc->sc_ah->power_mode != ATH9K_PM_AWAKE)) { |
1180 | /* | 1137 | /* |
1181 | * We are using PS-Poll and mac80211 can request TX while in | 1138 | * We are using PS-Poll and mac80211 can request TX while in |
@@ -1222,6 +1179,7 @@ static void ath9k_stop(struct ieee80211_hw *hw) | |||
1222 | struct ath_softc *sc = hw->priv; | 1179 | struct ath_softc *sc = hw->priv; |
1223 | struct ath_hw *ah = sc->sc_ah; | 1180 | struct ath_hw *ah = sc->sc_ah; |
1224 | struct ath_common *common = ath9k_hw_common(ah); | 1181 | struct ath_common *common = ath9k_hw_common(ah); |
1182 | bool prev_idle; | ||
1225 | 1183 | ||
1226 | mutex_lock(&sc->mutex); | 1184 | mutex_lock(&sc->mutex); |
1227 | 1185 | ||
@@ -1252,35 +1210,45 @@ static void ath9k_stop(struct ieee80211_hw *hw) | |||
1252 | * before setting the invalid flag. */ | 1210 | * before setting the invalid flag. */ |
1253 | ath9k_hw_disable_interrupts(ah); | 1211 | ath9k_hw_disable_interrupts(ah); |
1254 | 1212 | ||
1255 | if (!(sc->sc_flags & SC_OP_INVALID)) { | 1213 | spin_unlock_bh(&sc->sc_pcu_lock); |
1256 | ath_drain_all_txq(sc, false); | 1214 | |
1257 | ath_stoprecv(sc); | 1215 | /* we can now sync irq and kill any running tasklets, since we already |
1258 | ath9k_hw_phy_disable(ah); | 1216 | * disabled interrupts and not holding a spin lock */ |
1259 | } else | 1217 | synchronize_irq(sc->irq); |
1260 | sc->rx.rxlink = NULL; | 1218 | tasklet_kill(&sc->intr_tq); |
1219 | tasklet_kill(&sc->bcon_tasklet); | ||
1220 | |||
1221 | prev_idle = sc->ps_idle; | ||
1222 | sc->ps_idle = true; | ||
1223 | |||
1224 | spin_lock_bh(&sc->sc_pcu_lock); | ||
1225 | |||
1226 | if (ah->led_pin >= 0) { | ||
1227 | ath9k_hw_set_gpio(ah, ah->led_pin, 1); | ||
1228 | ath9k_hw_cfg_gpio_input(ah, ah->led_pin); | ||
1229 | } | ||
1230 | |||
1231 | ath_prepare_reset(sc, false, true); | ||
1261 | 1232 | ||
1262 | if (sc->rx.frag) { | 1233 | if (sc->rx.frag) { |
1263 | dev_kfree_skb_any(sc->rx.frag); | 1234 | dev_kfree_skb_any(sc->rx.frag); |
1264 | sc->rx.frag = NULL; | 1235 | sc->rx.frag = NULL; |
1265 | } | 1236 | } |
1266 | 1237 | ||
1267 | /* disable HAL and put h/w to sleep */ | 1238 | if (!ah->curchan) |
1268 | ath9k_hw_disable(ah); | 1239 | ah->curchan = ath9k_cmn_get_curchannel(hw, ah); |
1240 | |||
1241 | ath9k_hw_reset(ah, ah->curchan, ah->caldata, false); | ||
1242 | ath9k_hw_phy_disable(ah); | ||
1269 | 1243 | ||
1270 | spin_unlock_bh(&sc->sc_pcu_lock); | 1244 | ath9k_hw_configpcipowersave(ah, true); |
1271 | 1245 | ||
1272 | /* we can now sync irq and kill any running tasklets, since we already | 1246 | spin_unlock_bh(&sc->sc_pcu_lock); |
1273 | * disabled interrupts and not holding a spin lock */ | ||
1274 | synchronize_irq(sc->irq); | ||
1275 | tasklet_kill(&sc->intr_tq); | ||
1276 | tasklet_kill(&sc->bcon_tasklet); | ||
1277 | 1247 | ||
1278 | ath9k_ps_restore(sc); | 1248 | ath9k_ps_restore(sc); |
1279 | 1249 | ||
1280 | sc->ps_idle = true; | ||
1281 | ath_radio_disable(sc, hw); | ||
1282 | |||
1283 | sc->sc_flags |= SC_OP_INVALID; | 1250 | sc->sc_flags |= SC_OP_INVALID; |
1251 | sc->ps_idle = prev_idle; | ||
1284 | 1252 | ||
1285 | mutex_unlock(&sc->mutex); | 1253 | mutex_unlock(&sc->mutex); |
1286 | 1254 | ||
@@ -1620,8 +1588,8 @@ static int ath9k_config(struct ieee80211_hw *hw, u32 changed) | |||
1620 | struct ath_hw *ah = sc->sc_ah; | 1588 | struct ath_hw *ah = sc->sc_ah; |
1621 | struct ath_common *common = ath9k_hw_common(ah); | 1589 | struct ath_common *common = ath9k_hw_common(ah); |
1622 | struct ieee80211_conf *conf = &hw->conf; | 1590 | struct ieee80211_conf *conf = &hw->conf; |
1623 | bool disable_radio = false; | ||
1624 | 1591 | ||
1592 | ath9k_ps_wakeup(sc); | ||
1625 | mutex_lock(&sc->mutex); | 1593 | mutex_lock(&sc->mutex); |
1626 | 1594 | ||
1627 | /* | 1595 | /* |
@@ -1632,13 +1600,8 @@ static int ath9k_config(struct ieee80211_hw *hw, u32 changed) | |||
1632 | */ | 1600 | */ |
1633 | if (changed & IEEE80211_CONF_CHANGE_IDLE) { | 1601 | if (changed & IEEE80211_CONF_CHANGE_IDLE) { |
1634 | sc->ps_idle = !!(conf->flags & IEEE80211_CONF_IDLE); | 1602 | sc->ps_idle = !!(conf->flags & IEEE80211_CONF_IDLE); |
1635 | if (!sc->ps_idle) { | 1603 | if (sc->ps_idle) |
1636 | ath_radio_enable(sc, hw); | 1604 | ath_cancel_work(sc); |
1637 | ath_dbg(common, ATH_DBG_CONFIG, | ||
1638 | "not-idle: enabling radio\n"); | ||
1639 | } else { | ||
1640 | disable_radio = true; | ||
1641 | } | ||
1642 | } | 1605 | } |
1643 | 1606 | ||
1644 | /* | 1607 | /* |
@@ -1745,18 +1708,12 @@ static int ath9k_config(struct ieee80211_hw *hw, u32 changed) | |||
1745 | ath_dbg(common, ATH_DBG_CONFIG, | 1708 | ath_dbg(common, ATH_DBG_CONFIG, |
1746 | "Set power: %d\n", conf->power_level); | 1709 | "Set power: %d\n", conf->power_level); |
1747 | sc->config.txpowlimit = 2 * conf->power_level; | 1710 | sc->config.txpowlimit = 2 * conf->power_level; |
1748 | ath9k_ps_wakeup(sc); | ||
1749 | ath9k_cmn_update_txpow(ah, sc->curtxpow, | 1711 | ath9k_cmn_update_txpow(ah, sc->curtxpow, |
1750 | sc->config.txpowlimit, &sc->curtxpow); | 1712 | sc->config.txpowlimit, &sc->curtxpow); |
1751 | ath9k_ps_restore(sc); | ||
1752 | } | ||
1753 | |||
1754 | if (disable_radio) { | ||
1755 | ath_dbg(common, ATH_DBG_CONFIG, "idle: disabling radio\n"); | ||
1756 | ath_radio_disable(sc, hw); | ||
1757 | } | 1713 | } |
1758 | 1714 | ||
1759 | mutex_unlock(&sc->mutex); | 1715 | mutex_unlock(&sc->mutex); |
1716 | ath9k_ps_restore(sc); | ||
1760 | 1717 | ||
1761 | return 0; | 1718 | return 0; |
1762 | } | 1719 | } |
@@ -1916,7 +1873,8 @@ static int ath9k_set_key(struct ieee80211_hw *hw, | |||
1916 | if (ath9k_modparam_nohwcrypt) | 1873 | if (ath9k_modparam_nohwcrypt) |
1917 | return -ENOSPC; | 1874 | return -ENOSPC; |
1918 | 1875 | ||
1919 | if (vif->type == NL80211_IFTYPE_ADHOC && | 1876 | if ((vif->type == NL80211_IFTYPE_ADHOC || |
1877 | vif->type == NL80211_IFTYPE_MESH_POINT) && | ||
1920 | (key->cipher == WLAN_CIPHER_SUITE_TKIP || | 1878 | (key->cipher == WLAN_CIPHER_SUITE_TKIP || |
1921 | key->cipher == WLAN_CIPHER_SUITE_CCMP) && | 1879 | key->cipher == WLAN_CIPHER_SUITE_CCMP) && |
1922 | !(key->flags & IEEE80211_KEY_FLAG_PAIRWISE)) { | 1880 | !(key->flags & IEEE80211_KEY_FLAG_PAIRWISE)) { |
@@ -2324,9 +2282,6 @@ static void ath9k_flush(struct ieee80211_hw *hw, bool drop) | |||
2324 | return; | 2282 | return; |
2325 | } | 2283 | } |
2326 | 2284 | ||
2327 | if (drop) | ||
2328 | timeout = 1; | ||
2329 | |||
2330 | for (j = 0; j < timeout; j++) { | 2285 | for (j = 0; j < timeout; j++) { |
2331 | bool npend = false; | 2286 | bool npend = false; |
2332 | 2287 | ||
@@ -2344,21 +2299,22 @@ static void ath9k_flush(struct ieee80211_hw *hw, bool drop) | |||
2344 | } | 2299 | } |
2345 | 2300 | ||
2346 | if (!npend) | 2301 | if (!npend) |
2347 | goto out; | 2302 | break; |
2348 | } | 2303 | } |
2349 | 2304 | ||
2350 | ath9k_ps_wakeup(sc); | 2305 | if (drop) { |
2351 | spin_lock_bh(&sc->sc_pcu_lock); | 2306 | ath9k_ps_wakeup(sc); |
2352 | drain_txq = ath_drain_all_txq(sc, false); | 2307 | spin_lock_bh(&sc->sc_pcu_lock); |
2353 | spin_unlock_bh(&sc->sc_pcu_lock); | 2308 | drain_txq = ath_drain_all_txq(sc, false); |
2309 | spin_unlock_bh(&sc->sc_pcu_lock); | ||
2354 | 2310 | ||
2355 | if (!drain_txq) | 2311 | if (!drain_txq) |
2356 | ath_reset(sc, false); | 2312 | ath_reset(sc, false); |
2357 | 2313 | ||
2358 | ath9k_ps_restore(sc); | 2314 | ath9k_ps_restore(sc); |
2359 | ieee80211_wake_queues(hw); | 2315 | ieee80211_wake_queues(hw); |
2316 | } | ||
2360 | 2317 | ||
2361 | out: | ||
2362 | ieee80211_queue_delayed_work(hw, &sc->tx_complete_work, 0); | 2318 | ieee80211_queue_delayed_work(hw, &sc->tx_complete_work, 0); |
2363 | mutex_unlock(&sc->mutex); | 2319 | mutex_unlock(&sc->mutex); |
2364 | } | 2320 | } |
diff --git a/drivers/net/wireless/ath/ath9k/mci.c b/drivers/net/wireless/ath/ath9k/mci.c index 0fbb141bc302..691bf47906e2 100644 --- a/drivers/net/wireless/ath/ath9k/mci.c +++ b/drivers/net/wireless/ath/ath9k/mci.c | |||
@@ -14,6 +14,9 @@ | |||
14 | * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. | 14 | * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. |
15 | */ | 15 | */ |
16 | 16 | ||
17 | #include <linux/dma-mapping.h> | ||
18 | #include <linux/slab.h> | ||
19 | |||
17 | #include "ath9k.h" | 20 | #include "ath9k.h" |
18 | #include "mci.h" | 21 | #include "mci.h" |
19 | 22 | ||
@@ -181,8 +184,58 @@ static void ath_mci_update_scheme(struct ath_softc *sc) | |||
181 | ath9k_btcoex_timer_resume(sc); | 184 | ath9k_btcoex_timer_resume(sc); |
182 | } | 185 | } |
183 | 186 | ||
184 | void ath_mci_process_profile(struct ath_softc *sc, | 187 | |
185 | struct ath_mci_profile_info *info) | 188 | static void ath_mci_cal_msg(struct ath_softc *sc, u8 opcode, u8 *rx_payload) |
189 | { | ||
190 | struct ath_hw *ah = sc->sc_ah; | ||
191 | struct ath_common *common = ath9k_hw_common(ah); | ||
192 | u32 payload[4] = {0, 0, 0, 0}; | ||
193 | |||
194 | switch (opcode) { | ||
195 | case MCI_GPM_BT_CAL_REQ: | ||
196 | |||
197 | ath_dbg(common, ATH_DBG_MCI, "MCI received BT_CAL_REQ\n"); | ||
198 | |||
199 | if (ar9003_mci_state(ah, MCI_STATE_BT, NULL) == MCI_BT_AWAKE) { | ||
200 | ar9003_mci_state(ah, MCI_STATE_SET_BT_CAL_START, NULL); | ||
201 | ieee80211_queue_work(sc->hw, &sc->hw_reset_work); | ||
202 | } else | ||
203 | ath_dbg(common, ATH_DBG_MCI, | ||
204 | "MCI State mismatches: %d\n", | ||
205 | ar9003_mci_state(ah, MCI_STATE_BT, NULL)); | ||
206 | |||
207 | break; | ||
208 | |||
209 | case MCI_GPM_BT_CAL_DONE: | ||
210 | |||
211 | ath_dbg(common, ATH_DBG_MCI, "MCI received BT_CAL_DONE\n"); | ||
212 | |||
213 | if (ar9003_mci_state(ah, MCI_STATE_BT, NULL) == MCI_BT_CAL) | ||
214 | ath_dbg(common, ATH_DBG_MCI, "MCI error illegal!\n"); | ||
215 | else | ||
216 | ath_dbg(common, ATH_DBG_MCI, "MCI BT not in CAL state\n"); | ||
217 | |||
218 | break; | ||
219 | |||
220 | case MCI_GPM_BT_CAL_GRANT: | ||
221 | |||
222 | ath_dbg(common, ATH_DBG_MCI, "MCI received BT_CAL_GRANT\n"); | ||
223 | |||
224 | /* Send WLAN_CAL_DONE for now */ | ||
225 | ath_dbg(common, ATH_DBG_MCI, "MCI send WLAN_CAL_DONE\n"); | ||
226 | MCI_GPM_SET_CAL_TYPE(payload, MCI_GPM_WLAN_CAL_DONE); | ||
227 | ar9003_mci_send_message(sc->sc_ah, MCI_GPM, 0, payload, | ||
228 | 16, false, true); | ||
229 | break; | ||
230 | |||
231 | default: | ||
232 | ath_dbg(common, ATH_DBG_MCI, "MCI Unknown GPM CAL message\n"); | ||
233 | break; | ||
234 | } | ||
235 | } | ||
236 | |||
237 | static void ath_mci_process_profile(struct ath_softc *sc, | ||
238 | struct ath_mci_profile_info *info) | ||
186 | { | 239 | { |
187 | struct ath_common *common = ath9k_hw_common(sc->sc_ah); | 240 | struct ath_common *common = ath9k_hw_common(sc->sc_ah); |
188 | struct ath_btcoex *btcoex = &sc->btcoex; | 241 | struct ath_btcoex *btcoex = &sc->btcoex; |
@@ -208,8 +261,8 @@ void ath_mci_process_profile(struct ath_softc *sc, | |||
208 | ath_mci_update_scheme(sc); | 261 | ath_mci_update_scheme(sc); |
209 | } | 262 | } |
210 | 263 | ||
211 | void ath_mci_process_status(struct ath_softc *sc, | 264 | static void ath_mci_process_status(struct ath_softc *sc, |
212 | struct ath_mci_profile_status *status) | 265 | struct ath_mci_profile_status *status) |
213 | { | 266 | { |
214 | struct ath_common *common = ath9k_hw_common(sc->sc_ah); | 267 | struct ath_common *common = ath9k_hw_common(sc->sc_ah); |
215 | struct ath_btcoex *btcoex = &sc->btcoex; | 268 | struct ath_btcoex *btcoex = &sc->btcoex; |
@@ -252,3 +305,369 @@ void ath_mci_process_status(struct ath_softc *sc, | |||
252 | if (old_num_mgmt != mci->num_mgmt) | 305 | if (old_num_mgmt != mci->num_mgmt) |
253 | ath_mci_update_scheme(sc); | 306 | ath_mci_update_scheme(sc); |
254 | } | 307 | } |
308 | |||
309 | static void ath_mci_msg(struct ath_softc *sc, u8 opcode, u8 *rx_payload) | ||
310 | { | ||
311 | struct ath_hw *ah = sc->sc_ah; | ||
312 | struct ath_mci_profile_info profile_info; | ||
313 | struct ath_mci_profile_status profile_status; | ||
314 | struct ath_common *common = ath9k_hw_common(sc->sc_ah); | ||
315 | u32 version; | ||
316 | u8 major; | ||
317 | u8 minor; | ||
318 | u32 seq_num; | ||
319 | |||
320 | switch (opcode) { | ||
321 | |||
322 | case MCI_GPM_COEX_VERSION_QUERY: | ||
323 | ath_dbg(common, ATH_DBG_MCI, | ||
324 | "MCI Recv GPM COEX Version Query.\n"); | ||
325 | version = ar9003_mci_state(ah, | ||
326 | MCI_STATE_SEND_WLAN_COEX_VERSION, NULL); | ||
327 | break; | ||
328 | |||
329 | case MCI_GPM_COEX_VERSION_RESPONSE: | ||
330 | ath_dbg(common, ATH_DBG_MCI, | ||
331 | "MCI Recv GPM COEX Version Response.\n"); | ||
332 | major = *(rx_payload + MCI_GPM_COEX_B_MAJOR_VERSION); | ||
333 | minor = *(rx_payload + MCI_GPM_COEX_B_MINOR_VERSION); | ||
334 | ath_dbg(common, ATH_DBG_MCI, | ||
335 | "MCI BT Coex version: %d.%d\n", major, minor); | ||
336 | version = (major << 8) + minor; | ||
337 | version = ar9003_mci_state(ah, | ||
338 | MCI_STATE_SET_BT_COEX_VERSION, &version); | ||
339 | break; | ||
340 | |||
341 | case MCI_GPM_COEX_STATUS_QUERY: | ||
342 | ath_dbg(common, ATH_DBG_MCI, | ||
343 | "MCI Recv GPM COEX Status Query = 0x%02x.\n", | ||
344 | *(rx_payload + MCI_GPM_COEX_B_WLAN_BITMAP)); | ||
345 | ar9003_mci_state(ah, | ||
346 | MCI_STATE_SEND_WLAN_CHANNELS, NULL); | ||
347 | break; | ||
348 | |||
349 | case MCI_GPM_COEX_BT_PROFILE_INFO: | ||
350 | ath_dbg(common, ATH_DBG_MCI, | ||
351 | "MCI Recv GPM Coex BT profile info\n"); | ||
352 | memcpy(&profile_info, | ||
353 | (rx_payload + MCI_GPM_COEX_B_PROFILE_TYPE), 10); | ||
354 | |||
355 | if ((profile_info.type == MCI_GPM_COEX_PROFILE_UNKNOWN) | ||
356 | || (profile_info.type >= | ||
357 | MCI_GPM_COEX_PROFILE_MAX)) { | ||
358 | |||
359 | ath_dbg(common, ATH_DBG_MCI, | ||
360 | "illegal profile type = %d," | ||
361 | "state = %d\n", profile_info.type, | ||
362 | profile_info.start); | ||
363 | break; | ||
364 | } | ||
365 | |||
366 | ath_mci_process_profile(sc, &profile_info); | ||
367 | break; | ||
368 | |||
369 | case MCI_GPM_COEX_BT_STATUS_UPDATE: | ||
370 | profile_status.is_link = *(rx_payload + | ||
371 | MCI_GPM_COEX_B_STATUS_TYPE); | ||
372 | profile_status.conn_handle = *(rx_payload + | ||
373 | MCI_GPM_COEX_B_STATUS_LINKID); | ||
374 | profile_status.is_critical = *(rx_payload + | ||
375 | MCI_GPM_COEX_B_STATUS_STATE); | ||
376 | |||
377 | seq_num = *((u32 *)(rx_payload + 12)); | ||
378 | ath_dbg(common, ATH_DBG_MCI, | ||
379 | "MCI Recv GPM COEX BT_Status_Update: " | ||
380 | "is_link=%d, linkId=%d, state=%d, SEQ=%d\n", | ||
381 | profile_status.is_link, profile_status.conn_handle, | ||
382 | profile_status.is_critical, seq_num); | ||
383 | |||
384 | ath_mci_process_status(sc, &profile_status); | ||
385 | break; | ||
386 | |||
387 | default: | ||
388 | ath_dbg(common, ATH_DBG_MCI, | ||
389 | "MCI Unknown GPM COEX message = 0x%02x\n", opcode); | ||
390 | break; | ||
391 | } | ||
392 | } | ||
393 | |||
394 | static int ath_mci_buf_alloc(struct ath_softc *sc, struct ath_mci_buf *buf) | ||
395 | { | ||
396 | int error = 0; | ||
397 | |||
398 | buf->bf_addr = dma_alloc_coherent(sc->dev, buf->bf_len, | ||
399 | &buf->bf_paddr, GFP_KERNEL); | ||
400 | |||
401 | if (buf->bf_addr == NULL) { | ||
402 | error = -ENOMEM; | ||
403 | goto fail; | ||
404 | } | ||
405 | |||
406 | return 0; | ||
407 | |||
408 | fail: | ||
409 | memset(buf, 0, sizeof(*buf)); | ||
410 | return error; | ||
411 | } | ||
412 | |||
413 | static void ath_mci_buf_free(struct ath_softc *sc, struct ath_mci_buf *buf) | ||
414 | { | ||
415 | if (buf->bf_addr) { | ||
416 | dma_free_coherent(sc->dev, buf->bf_len, buf->bf_addr, | ||
417 | buf->bf_paddr); | ||
418 | memset(buf, 0, sizeof(*buf)); | ||
419 | } | ||
420 | } | ||
421 | |||
422 | int ath_mci_setup(struct ath_softc *sc) | ||
423 | { | ||
424 | struct ath_common *common = ath9k_hw_common(sc->sc_ah); | ||
425 | struct ath_mci_coex *mci = &sc->mci_coex; | ||
426 | int error = 0; | ||
427 | |||
428 | mci->sched_buf.bf_len = ATH_MCI_SCHED_BUF_SIZE + ATH_MCI_GPM_BUF_SIZE; | ||
429 | |||
430 | if (ath_mci_buf_alloc(sc, &mci->sched_buf)) { | ||
431 | ath_dbg(common, ATH_DBG_FATAL, "MCI buffer alloc failed\n"); | ||
432 | error = -ENOMEM; | ||
433 | goto fail; | ||
434 | } | ||
435 | |||
436 | mci->sched_buf.bf_len = ATH_MCI_SCHED_BUF_SIZE; | ||
437 | |||
438 | memset(mci->sched_buf.bf_addr, MCI_GPM_RSVD_PATTERN, | ||
439 | mci->sched_buf.bf_len); | ||
440 | |||
441 | mci->gpm_buf.bf_len = ATH_MCI_GPM_BUF_SIZE; | ||
442 | mci->gpm_buf.bf_addr = (u8 *)mci->sched_buf.bf_addr + | ||
443 | mci->sched_buf.bf_len; | ||
444 | mci->gpm_buf.bf_paddr = mci->sched_buf.bf_paddr + mci->sched_buf.bf_len; | ||
445 | |||
446 | /* initialize the buffer */ | ||
447 | memset(mci->gpm_buf.bf_addr, MCI_GPM_RSVD_PATTERN, mci->gpm_buf.bf_len); | ||
448 | |||
449 | ar9003_mci_setup(sc->sc_ah, mci->gpm_buf.bf_paddr, | ||
450 | mci->gpm_buf.bf_addr, (mci->gpm_buf.bf_len >> 4), | ||
451 | mci->sched_buf.bf_paddr); | ||
452 | fail: | ||
453 | return error; | ||
454 | } | ||
455 | |||
456 | void ath_mci_cleanup(struct ath_softc *sc) | ||
457 | { | ||
458 | struct ath_hw *ah = sc->sc_ah; | ||
459 | struct ath_mci_coex *mci = &sc->mci_coex; | ||
460 | |||
461 | /* | ||
462 | * both schedule and gpm buffers will be released | ||
463 | */ | ||
464 | ath_mci_buf_free(sc, &mci->sched_buf); | ||
465 | ar9003_mci_cleanup(ah); | ||
466 | } | ||
467 | |||
468 | void ath_mci_intr(struct ath_softc *sc) | ||
469 | { | ||
470 | struct ath_mci_coex *mci = &sc->mci_coex; | ||
471 | struct ath_hw *ah = sc->sc_ah; | ||
472 | struct ath_common *common = ath9k_hw_common(ah); | ||
473 | u32 mci_int, mci_int_rxmsg; | ||
474 | u32 offset, subtype, opcode; | ||
475 | u32 *pgpm; | ||
476 | u32 more_data = MCI_GPM_MORE; | ||
477 | bool skip_gpm = false; | ||
478 | |||
479 | ar9003_mci_get_interrupt(sc->sc_ah, &mci_int, &mci_int_rxmsg); | ||
480 | |||
481 | if (ar9003_mci_state(ah, MCI_STATE_ENABLE, NULL) == 0) { | ||
482 | |||
483 | ar9003_mci_state(sc->sc_ah, MCI_STATE_INIT_GPM_OFFSET, NULL); | ||
484 | ath_dbg(common, ATH_DBG_MCI, | ||
485 | "MCI interrupt but MCI disabled\n"); | ||
486 | |||
487 | ath_dbg(common, ATH_DBG_MCI, | ||
488 | "MCI interrupt: intr = 0x%x, intr_rxmsg = 0x%x\n", | ||
489 | mci_int, mci_int_rxmsg); | ||
490 | return; | ||
491 | } | ||
492 | |||
493 | if (mci_int_rxmsg & AR_MCI_INTERRUPT_RX_MSG_REQ_WAKE) { | ||
494 | u32 payload[4] = { 0xffffffff, 0xffffffff, | ||
495 | 0xffffffff, 0xffffff00}; | ||
496 | |||
497 | /* | ||
498 | * The following REMOTE_RESET and SYS_WAKING used to sent | ||
499 | * only when BT wake up. Now they are always sent, as a | ||
500 | * recovery method to reset BT MCI's RX alignment. | ||
501 | */ | ||
502 | ath_dbg(common, ATH_DBG_MCI, "MCI interrupt send REMOTE_RESET\n"); | ||
503 | |||
504 | ar9003_mci_send_message(ah, MCI_REMOTE_RESET, 0, | ||
505 | payload, 16, true, false); | ||
506 | ath_dbg(common, ATH_DBG_MCI, "MCI interrupt send SYS_WAKING\n"); | ||
507 | ar9003_mci_send_message(ah, MCI_SYS_WAKING, 0, | ||
508 | NULL, 0, true, false); | ||
509 | |||
510 | mci_int_rxmsg &= ~AR_MCI_INTERRUPT_RX_MSG_REQ_WAKE; | ||
511 | ar9003_mci_state(ah, MCI_STATE_RESET_REQ_WAKE, NULL); | ||
512 | |||
513 | /* | ||
514 | * always do this for recovery and 2G/5G toggling and LNA_TRANS | ||
515 | */ | ||
516 | ath_dbg(common, ATH_DBG_MCI, "MCI Set BT state to AWAKE.\n"); | ||
517 | ar9003_mci_state(ah, MCI_STATE_SET_BT_AWAKE, NULL); | ||
518 | } | ||
519 | |||
520 | /* Processing SYS_WAKING/SYS_SLEEPING */ | ||
521 | if (mci_int_rxmsg & AR_MCI_INTERRUPT_RX_MSG_SYS_WAKING) { | ||
522 | mci_int_rxmsg &= ~AR_MCI_INTERRUPT_RX_MSG_SYS_WAKING; | ||
523 | |||
524 | if (ar9003_mci_state(ah, MCI_STATE_BT, NULL) == MCI_BT_SLEEP) { | ||
525 | |||
526 | if (ar9003_mci_state(ah, MCI_STATE_REMOTE_SLEEP, NULL) | ||
527 | == MCI_BT_SLEEP) | ||
528 | ath_dbg(common, ATH_DBG_MCI, | ||
529 | "MCI BT stays in sleep mode\n"); | ||
530 | else { | ||
531 | ath_dbg(common, ATH_DBG_MCI, | ||
532 | "MCI Set BT state to AWAKE.\n"); | ||
533 | ar9003_mci_state(ah, | ||
534 | MCI_STATE_SET_BT_AWAKE, NULL); | ||
535 | } | ||
536 | } else | ||
537 | ath_dbg(common, ATH_DBG_MCI, | ||
538 | "MCI BT stays in AWAKE mode.\n"); | ||
539 | } | ||
540 | |||
541 | if (mci_int_rxmsg & AR_MCI_INTERRUPT_RX_MSG_SYS_SLEEPING) { | ||
542 | |||
543 | mci_int_rxmsg &= ~AR_MCI_INTERRUPT_RX_MSG_SYS_SLEEPING; | ||
544 | |||
545 | if (ar9003_mci_state(ah, MCI_STATE_BT, NULL) == MCI_BT_AWAKE) { | ||
546 | |||
547 | if (ar9003_mci_state(ah, MCI_STATE_REMOTE_SLEEP, NULL) | ||
548 | == MCI_BT_AWAKE) | ||
549 | ath_dbg(common, ATH_DBG_MCI, | ||
550 | "MCI BT stays in AWAKE mode.\n"); | ||
551 | else { | ||
552 | ath_dbg(common, ATH_DBG_MCI, | ||
553 | "MCI SetBT state to SLEEP\n"); | ||
554 | ar9003_mci_state(ah, MCI_STATE_SET_BT_SLEEP, | ||
555 | NULL); | ||
556 | } | ||
557 | } else | ||
558 | ath_dbg(common, ATH_DBG_MCI, | ||
559 | "MCI BT stays in SLEEP mode\n"); | ||
560 | } | ||
561 | |||
562 | if ((mci_int & AR_MCI_INTERRUPT_RX_INVALID_HDR) || | ||
563 | (mci_int & AR_MCI_INTERRUPT_CONT_INFO_TIMEOUT)) { | ||
564 | |||
565 | ath_dbg(common, ATH_DBG_MCI, "MCI RX broken, skip GPM msgs\n"); | ||
566 | ar9003_mci_state(ah, MCI_STATE_RECOVER_RX, NULL); | ||
567 | skip_gpm = true; | ||
568 | } | ||
569 | |||
570 | if (mci_int_rxmsg & AR_MCI_INTERRUPT_RX_MSG_SCHD_INFO) { | ||
571 | |||
572 | mci_int_rxmsg &= ~AR_MCI_INTERRUPT_RX_MSG_SCHD_INFO; | ||
573 | offset = ar9003_mci_state(ah, MCI_STATE_LAST_SCHD_MSG_OFFSET, | ||
574 | NULL); | ||
575 | } | ||
576 | |||
577 | if (mci_int_rxmsg & AR_MCI_INTERRUPT_RX_MSG_GPM) { | ||
578 | |||
579 | mci_int_rxmsg &= ~AR_MCI_INTERRUPT_RX_MSG_GPM; | ||
580 | |||
581 | while (more_data == MCI_GPM_MORE) { | ||
582 | |||
583 | pgpm = mci->gpm_buf.bf_addr; | ||
584 | offset = ar9003_mci_state(ah, | ||
585 | MCI_STATE_NEXT_GPM_OFFSET, &more_data); | ||
586 | |||
587 | if (offset == MCI_GPM_INVALID) | ||
588 | break; | ||
589 | |||
590 | pgpm += (offset >> 2); | ||
591 | |||
592 | /* | ||
593 | * The first dword is timer. | ||
594 | * The real data starts from 2nd dword. | ||
595 | */ | ||
596 | |||
597 | subtype = MCI_GPM_TYPE(pgpm); | ||
598 | opcode = MCI_GPM_OPCODE(pgpm); | ||
599 | |||
600 | if (!skip_gpm) { | ||
601 | |||
602 | if (MCI_GPM_IS_CAL_TYPE(subtype)) | ||
603 | ath_mci_cal_msg(sc, subtype, | ||
604 | (u8 *) pgpm); | ||
605 | else { | ||
606 | switch (subtype) { | ||
607 | case MCI_GPM_COEX_AGENT: | ||
608 | ath_mci_msg(sc, opcode, | ||
609 | (u8 *) pgpm); | ||
610 | break; | ||
611 | default: | ||
612 | break; | ||
613 | } | ||
614 | } | ||
615 | } | ||
616 | MCI_GPM_RECYCLE(pgpm); | ||
617 | } | ||
618 | } | ||
619 | |||
620 | if (mci_int_rxmsg & AR_MCI_INTERRUPT_RX_HW_MSG_MASK) { | ||
621 | |||
622 | if (mci_int_rxmsg & AR_MCI_INTERRUPT_RX_MSG_LNA_CONTROL) | ||
623 | mci_int_rxmsg &= ~AR_MCI_INTERRUPT_RX_MSG_LNA_CONTROL; | ||
624 | |||
625 | if (mci_int_rxmsg & AR_MCI_INTERRUPT_RX_MSG_LNA_INFO) { | ||
626 | mci_int_rxmsg &= ~AR_MCI_INTERRUPT_RX_MSG_LNA_INFO; | ||
627 | ath_dbg(common, ATH_DBG_MCI, "MCI LNA_INFO\n"); | ||
628 | } | ||
629 | |||
630 | if (mci_int_rxmsg & AR_MCI_INTERRUPT_RX_MSG_CONT_INFO) { | ||
631 | |||
632 | int value_dbm = ar9003_mci_state(ah, | ||
633 | MCI_STATE_CONT_RSSI_POWER, NULL); | ||
634 | |||
635 | mci_int_rxmsg &= ~AR_MCI_INTERRUPT_RX_MSG_CONT_INFO; | ||
636 | |||
637 | if (ar9003_mci_state(ah, MCI_STATE_CONT_TXRX, NULL)) | ||
638 | ath_dbg(common, ATH_DBG_MCI, | ||
639 | "MCI CONT_INFO: " | ||
640 | "(tx) pri = %d, pwr = %d dBm\n", | ||
641 | ar9003_mci_state(ah, | ||
642 | MCI_STATE_CONT_PRIORITY, NULL), | ||
643 | value_dbm); | ||
644 | else | ||
645 | ath_dbg(common, ATH_DBG_MCI, | ||
646 | "MCI CONT_INFO:" | ||
647 | "(rx) pri = %d,pwr = %d dBm\n", | ||
648 | ar9003_mci_state(ah, | ||
649 | MCI_STATE_CONT_PRIORITY, NULL), | ||
650 | value_dbm); | ||
651 | } | ||
652 | |||
653 | if (mci_int_rxmsg & AR_MCI_INTERRUPT_RX_MSG_CONT_NACK) { | ||
654 | mci_int_rxmsg &= ~AR_MCI_INTERRUPT_RX_MSG_CONT_NACK; | ||
655 | ath_dbg(common, ATH_DBG_MCI, "MCI CONT_NACK\n"); | ||
656 | } | ||
657 | |||
658 | if (mci_int_rxmsg & AR_MCI_INTERRUPT_RX_MSG_CONT_RST) { | ||
659 | mci_int_rxmsg &= ~AR_MCI_INTERRUPT_RX_MSG_CONT_RST; | ||
660 | ath_dbg(common, ATH_DBG_MCI, "MCI CONT_RST\n"); | ||
661 | } | ||
662 | } | ||
663 | |||
664 | if ((mci_int & AR_MCI_INTERRUPT_RX_INVALID_HDR) || | ||
665 | (mci_int & AR_MCI_INTERRUPT_CONT_INFO_TIMEOUT)) | ||
666 | mci_int &= ~(AR_MCI_INTERRUPT_RX_INVALID_HDR | | ||
667 | AR_MCI_INTERRUPT_CONT_INFO_TIMEOUT); | ||
668 | |||
669 | if (mci_int_rxmsg & 0xfffffffe) | ||
670 | ath_dbg(common, ATH_DBG_MCI, | ||
671 | "MCI not processed mci_int_rxmsg = 0x%x\n", | ||
672 | mci_int_rxmsg); | ||
673 | } | ||
diff --git a/drivers/net/wireless/ath/ath9k/mci.h b/drivers/net/wireless/ath/ath9k/mci.h index 9590c61822d1..29e3e51d078f 100644 --- a/drivers/net/wireless/ath/ath9k/mci.h +++ b/drivers/net/wireless/ath/ath9k/mci.h | |||
@@ -17,6 +17,9 @@ | |||
17 | #ifndef MCI_H | 17 | #ifndef MCI_H |
18 | #define MCI_H | 18 | #define MCI_H |
19 | 19 | ||
20 | #define ATH_MCI_SCHED_BUF_SIZE (16 * 16) /* 16 entries, 4 dword each */ | ||
21 | #define ATH_MCI_GPM_MAX_ENTRY 16 | ||
22 | #define ATH_MCI_GPM_BUF_SIZE (ATH_MCI_GPM_MAX_ENTRY * 16) | ||
20 | #define ATH_MCI_DEF_BT_PERIOD 40 | 23 | #define ATH_MCI_DEF_BT_PERIOD 40 |
21 | #define ATH_MCI_BDR_DUTY_CYCLE 20 | 24 | #define ATH_MCI_BDR_DUTY_CYCLE 20 |
22 | #define ATH_MCI_MAX_DUTY_CYCLE 90 | 25 | #define ATH_MCI_MAX_DUTY_CYCLE 90 |
@@ -110,9 +113,22 @@ struct ath_mci_profile { | |||
110 | u8 num_bdr; | 113 | u8 num_bdr; |
111 | }; | 114 | }; |
112 | 115 | ||
116 | |||
117 | struct ath_mci_buf { | ||
118 | void *bf_addr; /* virtual addr of desc */ | ||
119 | dma_addr_t bf_paddr; /* physical addr of buffer */ | ||
120 | u32 bf_len; /* len of data */ | ||
121 | }; | ||
122 | |||
123 | struct ath_mci_coex { | ||
124 | atomic_t mci_cal_flag; | ||
125 | struct ath_mci_buf sched_buf; | ||
126 | struct ath_mci_buf gpm_buf; | ||
127 | u32 bt_cal_start; | ||
128 | }; | ||
129 | |||
113 | void ath_mci_flush_profile(struct ath_mci_profile *mci); | 130 | void ath_mci_flush_profile(struct ath_mci_profile *mci); |
114 | void ath_mci_process_profile(struct ath_softc *sc, | 131 | int ath_mci_setup(struct ath_softc *sc); |
115 | struct ath_mci_profile_info *info); | 132 | void ath_mci_cleanup(struct ath_softc *sc); |
116 | void ath_mci_process_status(struct ath_softc *sc, | 133 | void ath_mci_intr(struct ath_softc *sc); |
117 | struct ath_mci_profile_status *status); | ||
118 | #endif | 134 | #endif |
diff --git a/drivers/net/wireless/ath/ath9k/pci.c b/drivers/net/wireless/ath/ath9k/pci.c index edb0b4b3da3a..a439edc5dc06 100644 --- a/drivers/net/wireless/ath/ath9k/pci.c +++ b/drivers/net/wireless/ath/ath9k/pci.c | |||
@@ -18,6 +18,7 @@ | |||
18 | #include <linux/pci.h> | 18 | #include <linux/pci.h> |
19 | #include <linux/pci-aspm.h> | 19 | #include <linux/pci-aspm.h> |
20 | #include <linux/ath9k_platform.h> | 20 | #include <linux/ath9k_platform.h> |
21 | #include <linux/module.h> | ||
21 | #include "ath9k.h" | 22 | #include "ath9k.h" |
22 | 23 | ||
23 | static DEFINE_PCI_DEVICE_TABLE(ath_pci_id_table) = { | 24 | static DEFINE_PCI_DEVICE_TABLE(ath_pci_id_table) = { |
@@ -306,12 +307,11 @@ static int ath_pci_suspend(struct device *device) | |||
306 | struct ieee80211_hw *hw = pci_get_drvdata(pdev); | 307 | struct ieee80211_hw *hw = pci_get_drvdata(pdev); |
307 | struct ath_softc *sc = hw->priv; | 308 | struct ath_softc *sc = hw->priv; |
308 | 309 | ||
309 | ath9k_hw_set_gpio(sc->sc_ah, sc->sc_ah->led_pin, 1); | ||
310 | |||
311 | /* The device has to be moved to FULLSLEEP forcibly. | 310 | /* The device has to be moved to FULLSLEEP forcibly. |
312 | * Otherwise the chip never moved to full sleep, | 311 | * Otherwise the chip never moved to full sleep, |
313 | * when no interface is up. | 312 | * when no interface is up. |
314 | */ | 313 | */ |
314 | ath9k_hw_disable(sc->sc_ah); | ||
315 | ath9k_hw_setpower(sc->sc_ah, ATH9K_PM_FULL_SLEEP); | 315 | ath9k_hw_setpower(sc->sc_ah, ATH9K_PM_FULL_SLEEP); |
316 | 316 | ||
317 | return 0; | 317 | return 0; |
@@ -320,8 +320,6 @@ static int ath_pci_suspend(struct device *device) | |||
320 | static int ath_pci_resume(struct device *device) | 320 | static int ath_pci_resume(struct device *device) |
321 | { | 321 | { |
322 | struct pci_dev *pdev = to_pci_dev(device); | 322 | struct pci_dev *pdev = to_pci_dev(device); |
323 | struct ieee80211_hw *hw = pci_get_drvdata(pdev); | ||
324 | struct ath_softc *sc = hw->priv; | ||
325 | u32 val; | 323 | u32 val; |
326 | 324 | ||
327 | /* | 325 | /* |
@@ -333,22 +331,6 @@ static int ath_pci_resume(struct device *device) | |||
333 | if ((val & 0x0000ff00) != 0) | 331 | if ((val & 0x0000ff00) != 0) |
334 | pci_write_config_dword(pdev, 0x40, val & 0xffff00ff); | 332 | pci_write_config_dword(pdev, 0x40, val & 0xffff00ff); |
335 | 333 | ||
336 | ath9k_ps_wakeup(sc); | ||
337 | /* Enable LED */ | ||
338 | ath9k_hw_cfg_output(sc->sc_ah, sc->sc_ah->led_pin, | ||
339 | AR_GPIO_OUTPUT_MUX_AS_OUTPUT); | ||
340 | ath9k_hw_set_gpio(sc->sc_ah, sc->sc_ah->led_pin, 0); | ||
341 | |||
342 | /* | ||
343 | * Reset key cache to sane defaults (all entries cleared) instead of | ||
344 | * semi-random values after suspend/resume. | ||
345 | */ | ||
346 | ath9k_cmn_init_crypto(sc->sc_ah); | ||
347 | ath9k_ps_restore(sc); | ||
348 | |||
349 | sc->ps_idle = true; | ||
350 | ath_radio_disable(sc, hw); | ||
351 | |||
352 | return 0; | 334 | return 0; |
353 | } | 335 | } |
354 | 336 | ||
diff --git a/drivers/net/wireless/ath/ath9k/rc.c b/drivers/net/wireless/ath/ath9k/rc.c index 8448281dd069..528d5f3e868c 100644 --- a/drivers/net/wireless/ath/ath9k/rc.c +++ b/drivers/net/wireless/ath/ath9k/rc.c | |||
@@ -16,6 +16,7 @@ | |||
16 | */ | 16 | */ |
17 | 17 | ||
18 | #include <linux/slab.h> | 18 | #include <linux/slab.h> |
19 | #include <linux/export.h> | ||
19 | 20 | ||
20 | #include "ath9k.h" | 21 | #include "ath9k.h" |
21 | 22 | ||
@@ -1270,7 +1271,9 @@ static void ath_rc_init(struct ath_softc *sc, | |||
1270 | 1271 | ||
1271 | ath_rc_priv->max_valid_rate = k; | 1272 | ath_rc_priv->max_valid_rate = k; |
1272 | ath_rc_sort_validrates(rate_table, ath_rc_priv); | 1273 | ath_rc_sort_validrates(rate_table, ath_rc_priv); |
1273 | ath_rc_priv->rate_max_phy = ath_rc_priv->valid_rate_index[k-4]; | 1274 | ath_rc_priv->rate_max_phy = (k > 4) ? |
1275 | ath_rc_priv->valid_rate_index[k-4] : | ||
1276 | ath_rc_priv->valid_rate_index[k-1]; | ||
1274 | ath_rc_priv->rate_table = rate_table; | 1277 | ath_rc_priv->rate_table = rate_table; |
1275 | 1278 | ||
1276 | ath_dbg(common, ATH_DBG_CONFIG, | 1279 | ath_dbg(common, ATH_DBG_CONFIG, |
diff --git a/drivers/net/wireless/ath/ath9k/recv.c b/drivers/net/wireless/ath/ath9k/recv.c index 67b862cdae6d..ad5176de07dc 100644 --- a/drivers/net/wireless/ath/ath9k/recv.c +++ b/drivers/net/wireless/ath/ath9k/recv.c | |||
@@ -475,7 +475,6 @@ u32 ath_calcrxfilter(struct ath_softc *sc) | |||
475 | 475 | ||
476 | return rfilt; | 476 | return rfilt; |
477 | 477 | ||
478 | #undef RX_FILTER_PRESERVE | ||
479 | } | 478 | } |
480 | 479 | ||
481 | int ath_startrecv(struct ath_softc *sc) | 480 | int ath_startrecv(struct ath_softc *sc) |
@@ -1824,6 +1823,7 @@ int ath_rx_tasklet(struct ath_softc *sc, int flush, bool hp) | |||
1824 | hdr = (struct ieee80211_hdr *) (hdr_skb->data + rx_status_len); | 1823 | hdr = (struct ieee80211_hdr *) (hdr_skb->data + rx_status_len); |
1825 | rxs = IEEE80211_SKB_RXCB(hdr_skb); | 1824 | rxs = IEEE80211_SKB_RXCB(hdr_skb); |
1826 | if (ieee80211_is_beacon(hdr->frame_control) && | 1825 | if (ieee80211_is_beacon(hdr->frame_control) && |
1826 | !is_zero_ether_addr(common->curbssid) && | ||
1827 | !compare_ether_addr(hdr->addr3, common->curbssid)) | 1827 | !compare_ether_addr(hdr->addr3, common->curbssid)) |
1828 | rs.is_mybeacon = true; | 1828 | rs.is_mybeacon = true; |
1829 | else | 1829 | else |
@@ -1838,11 +1838,6 @@ int ath_rx_tasklet(struct ath_softc *sc, int flush, bool hp) | |||
1838 | if (sc->sc_flags & SC_OP_RXFLUSH) | 1838 | if (sc->sc_flags & SC_OP_RXFLUSH) |
1839 | goto requeue_drop_frag; | 1839 | goto requeue_drop_frag; |
1840 | 1840 | ||
1841 | retval = ath9k_rx_skb_preprocess(common, hw, hdr, &rs, | ||
1842 | rxs, &decrypt_error); | ||
1843 | if (retval) | ||
1844 | goto requeue_drop_frag; | ||
1845 | |||
1846 | rxs->mactime = (tsf & ~0xffffffffULL) | rs.rs_tstamp; | 1841 | rxs->mactime = (tsf & ~0xffffffffULL) | rs.rs_tstamp; |
1847 | if (rs.rs_tstamp > tsf_lower && | 1842 | if (rs.rs_tstamp > tsf_lower && |
1848 | unlikely(rs.rs_tstamp - tsf_lower > 0x10000000)) | 1843 | unlikely(rs.rs_tstamp - tsf_lower > 0x10000000)) |
@@ -1852,6 +1847,11 @@ int ath_rx_tasklet(struct ath_softc *sc, int flush, bool hp) | |||
1852 | unlikely(tsf_lower - rs.rs_tstamp > 0x10000000)) | 1847 | unlikely(tsf_lower - rs.rs_tstamp > 0x10000000)) |
1853 | rxs->mactime += 0x100000000ULL; | 1848 | rxs->mactime += 0x100000000ULL; |
1854 | 1849 | ||
1850 | retval = ath9k_rx_skb_preprocess(common, hw, hdr, &rs, | ||
1851 | rxs, &decrypt_error); | ||
1852 | if (retval) | ||
1853 | goto requeue_drop_frag; | ||
1854 | |||
1855 | /* Ensure we always have an skb to requeue once we are done | 1855 | /* Ensure we always have an skb to requeue once we are done |
1856 | * processing the current buffer's skb */ | 1856 | * processing the current buffer's skb */ |
1857 | requeue_skb = ath_rxbuf_alloc(common, common->rx_bufsize, GFP_ATOMIC); | 1857 | requeue_skb = ath_rxbuf_alloc(common, common->rx_bufsize, GFP_ATOMIC); |
@@ -1923,15 +1923,20 @@ int ath_rx_tasklet(struct ath_softc *sc, int flush, bool hp) | |||
1923 | skb = hdr_skb; | 1923 | skb = hdr_skb; |
1924 | } | 1924 | } |
1925 | 1925 | ||
1926 | /* | 1926 | |
1927 | * change the default rx antenna if rx diversity chooses the | 1927 | if (ah->caps.hw_caps & ATH9K_HW_CAP_ANT_DIV_COMB) { |
1928 | * other antenna 3 times in a row. | 1928 | |
1929 | */ | 1929 | /* |
1930 | if (sc->rx.defant != rs.rs_antenna) { | 1930 | * change the default rx antenna if rx diversity |
1931 | if (++sc->rx.rxotherant >= 3) | 1931 | * chooses the other antenna 3 times in a row. |
1932 | ath_setdefantenna(sc, rs.rs_antenna); | 1932 | */ |
1933 | } else { | 1933 | if (sc->rx.defant != rs.rs_antenna) { |
1934 | sc->rx.rxotherant = 0; | 1934 | if (++sc->rx.rxotherant >= 3) |
1935 | ath_setdefantenna(sc, rs.rs_antenna); | ||
1936 | } else { | ||
1937 | sc->rx.rxotherant = 0; | ||
1938 | } | ||
1939 | |||
1935 | } | 1940 | } |
1936 | 1941 | ||
1937 | if (rxs->flag & RX_FLAG_MMIC_STRIPPED) | 1942 | if (rxs->flag & RX_FLAG_MMIC_STRIPPED) |
diff --git a/drivers/net/wireless/ath/ath9k/reg.h b/drivers/net/wireless/ath/ath9k/reg.h index 45910975d853..6e2f18861f5d 100644 --- a/drivers/net/wireless/ath/ath9k/reg.h +++ b/drivers/net/wireless/ath/ath9k/reg.h | |||
@@ -1006,6 +1006,8 @@ enum { | |||
1006 | #define AR_INTR_ASYNC_MASK (AR_SREV_9340(ah) ? 0x4018 : 0x4030) | 1006 | #define AR_INTR_ASYNC_MASK (AR_SREV_9340(ah) ? 0x4018 : 0x4030) |
1007 | #define AR_INTR_ASYNC_MASK_GPIO 0xFFFC0000 | 1007 | #define AR_INTR_ASYNC_MASK_GPIO 0xFFFC0000 |
1008 | #define AR_INTR_ASYNC_MASK_GPIO_S 18 | 1008 | #define AR_INTR_ASYNC_MASK_GPIO_S 18 |
1009 | #define AR_INTR_ASYNC_MASK_MCI 0x00000080 | ||
1010 | #define AR_INTR_ASYNC_MASK_MCI_S 7 | ||
1009 | 1011 | ||
1010 | #define AR_INTR_SYNC_MASK (AR_SREV_9340(ah) ? 0x401c : 0x4034) | 1012 | #define AR_INTR_SYNC_MASK (AR_SREV_9340(ah) ? 0x401c : 0x4034) |
1011 | #define AR_INTR_SYNC_MASK_GPIO 0xFFFC0000 | 1013 | #define AR_INTR_SYNC_MASK_GPIO 0xFFFC0000 |
@@ -1013,6 +1015,14 @@ enum { | |||
1013 | 1015 | ||
1014 | #define AR_INTR_ASYNC_CAUSE_CLR (AR_SREV_9340(ah) ? 0x4020 : 0x4038) | 1016 | #define AR_INTR_ASYNC_CAUSE_CLR (AR_SREV_9340(ah) ? 0x4020 : 0x4038) |
1015 | #define AR_INTR_ASYNC_CAUSE (AR_SREV_9340(ah) ? 0x4020 : 0x4038) | 1017 | #define AR_INTR_ASYNC_CAUSE (AR_SREV_9340(ah) ? 0x4020 : 0x4038) |
1018 | #define AR_INTR_ASYNC_CAUSE_MCI 0x00000080 | ||
1019 | #define AR_INTR_ASYNC_USED (AR_INTR_MAC_IRQ | \ | ||
1020 | AR_INTR_ASYNC_CAUSE_MCI) | ||
1021 | |||
1022 | /* Asynchronous Interrupt Enable Register */ | ||
1023 | #define AR_INTR_ASYNC_ENABLE_MCI 0x00000080 | ||
1024 | #define AR_INTR_ASYNC_ENABLE_MCI_S 7 | ||
1025 | |||
1016 | 1026 | ||
1017 | #define AR_INTR_ASYNC_ENABLE (AR_SREV_9340(ah) ? 0x4024 : 0x403c) | 1027 | #define AR_INTR_ASYNC_ENABLE (AR_SREV_9340(ah) ? 0x4024 : 0x403c) |
1018 | #define AR_INTR_ASYNC_ENABLE_GPIO 0xFFFC0000 | 1028 | #define AR_INTR_ASYNC_ENABLE_GPIO 0xFFFC0000 |
@@ -1269,6 +1279,8 @@ enum { | |||
1269 | #define AR_RTC_INTR_MASK \ | 1279 | #define AR_RTC_INTR_MASK \ |
1270 | ((AR_SREV_9100(ah)) ? (AR_RTC_BASE + 0x0058) : 0x7058) | 1280 | ((AR_SREV_9100(ah)) ? (AR_RTC_BASE + 0x0058) : 0x7058) |
1271 | 1281 | ||
1282 | #define AR_RTC_KEEP_AWAKE 0x7034 | ||
1283 | |||
1272 | /* RTC_DERIVED_* - only for AR9100 */ | 1284 | /* RTC_DERIVED_* - only for AR9100 */ |
1273 | 1285 | ||
1274 | #define AR_RTC_DERIVED_CLK \ | 1286 | #define AR_RTC_DERIVED_CLK \ |
@@ -1555,6 +1567,8 @@ enum { | |||
1555 | #define AR_DIAG_FRAME_NV0 0x00020000 | 1567 | #define AR_DIAG_FRAME_NV0 0x00020000 |
1556 | #define AR_DIAG_OBS_PT_SEL1 0x000C0000 | 1568 | #define AR_DIAG_OBS_PT_SEL1 0x000C0000 |
1557 | #define AR_DIAG_OBS_PT_SEL1_S 18 | 1569 | #define AR_DIAG_OBS_PT_SEL1_S 18 |
1570 | #define AR_DIAG_OBS_PT_SEL2 0x08000000 | ||
1571 | #define AR_DIAG_OBS_PT_SEL2_S 27 | ||
1558 | #define AR_DIAG_FORCE_RX_CLEAR 0x00100000 /* force rx_clear high */ | 1572 | #define AR_DIAG_FORCE_RX_CLEAR 0x00100000 /* force rx_clear high */ |
1559 | #define AR_DIAG_IGNORE_VIRT_CS 0x00200000 | 1573 | #define AR_DIAG_IGNORE_VIRT_CS 0x00200000 |
1560 | #define AR_DIAG_FORCE_CH_IDLE_HIGH 0x00400000 | 1574 | #define AR_DIAG_FORCE_CH_IDLE_HIGH 0x00400000 |
@@ -1929,37 +1943,277 @@ enum { | |||
1929 | #define AR_PHY_AGC_CONTROL_YCOK_MAX_S 6 | 1943 | #define AR_PHY_AGC_CONTROL_YCOK_MAX_S 6 |
1930 | 1944 | ||
1931 | /* MCI Registers */ | 1945 | /* MCI Registers */ |
1932 | #define AR_MCI_INTERRUPT_RX_MSG_EN 0x183c | 1946 | |
1933 | #define AR_MCI_INTERRUPT_RX_MSG_REMOTE_RESET 0x00000001 | 1947 | #define AR_MCI_COMMAND0 0x1800 |
1934 | #define AR_MCI_INTERRUPT_RX_MSG_REMOTE_RESET_S 0 | 1948 | #define AR_MCI_COMMAND0_HEADER 0xFF |
1935 | #define AR_MCI_INTERRUPT_RX_MSG_LNA_CONTROL 0x00000002 | 1949 | #define AR_MCI_COMMAND0_HEADER_S 0 |
1936 | #define AR_MCI_INTERRUPT_RX_MSG_LNA_CONTROL_S 1 | 1950 | #define AR_MCI_COMMAND0_LEN 0x1f00 |
1937 | #define AR_MCI_INTERRUPT_RX_MSG_CONT_NACK 0x00000004 | 1951 | #define AR_MCI_COMMAND0_LEN_S 8 |
1938 | #define AR_MCI_INTERRUPT_RX_MSG_CONT_NACK_S 2 | 1952 | #define AR_MCI_COMMAND0_DISABLE_TIMESTAMP 0x2000 |
1939 | #define AR_MCI_INTERRUPT_RX_MSG_CONT_INFO 0x00000008 | 1953 | #define AR_MCI_COMMAND0_DISABLE_TIMESTAMP_S 13 |
1940 | #define AR_MCI_INTERRUPT_RX_MSG_CONT_INFO_S 3 | 1954 | |
1941 | #define AR_MCI_INTERRUPT_RX_MSG_CONT_RST 0x00000010 | 1955 | #define AR_MCI_COMMAND1 0x1804 |
1942 | #define AR_MCI_INTERRUPT_RX_MSG_CONT_RST_S 4 | 1956 | |
1943 | #define AR_MCI_INTERRUPT_RX_MSG_SCHD_INFO 0x00000020 | 1957 | #define AR_MCI_COMMAND2 0x1808 |
1944 | #define AR_MCI_INTERRUPT_RX_MSG_SCHD_INFO_S 5 | 1958 | #define AR_MCI_COMMAND2_RESET_TX 0x01 |
1945 | #define AR_MCI_INTERRUPT_RX_MSG_CPU_INT 0x00000040 | 1959 | #define AR_MCI_COMMAND2_RESET_TX_S 0 |
1946 | #define AR_MCI_INTERRUPT_RX_MSG_CPU_INT_S 6 | 1960 | #define AR_MCI_COMMAND2_RESET_RX 0x02 |
1947 | #define AR_MCI_INTERRUPT_RX_MSG_GPM 0x00000100 | 1961 | #define AR_MCI_COMMAND2_RESET_RX_S 1 |
1948 | #define AR_MCI_INTERRUPT_RX_MSG_GPM_S 8 | 1962 | #define AR_MCI_COMMAND2_RESET_RX_NUM_CYCLES 0x3FC |
1949 | #define AR_MCI_INTERRUPT_RX_MSG_LNA_INFO 0x00000200 | 1963 | #define AR_MCI_COMMAND2_RESET_RX_NUM_CYCLES_S 2 |
1950 | #define AR_MCI_INTERRUPT_RX_MSG_LNA_INFO_S 9 | 1964 | #define AR_MCI_COMMAND2_RESET_REQ_WAKEUP 0x400 |
1951 | #define AR_MCI_INTERRUPT_RX_MSG_SYS_SLEEPING 0x00000400 | 1965 | #define AR_MCI_COMMAND2_RESET_REQ_WAKEUP_S 10 |
1952 | #define AR_MCI_INTERRUPT_RX_MSG_SYS_SLEEPING_S 10 | 1966 | |
1953 | #define AR_MCI_INTERRUPT_RX_MSG_SYS_WAKING 0x00000800 | 1967 | #define AR_MCI_RX_CTRL 0x180c |
1954 | #define AR_MCI_INTERRUPT_RX_MSG_SYS_WAKING_S 11 | 1968 | |
1955 | #define AR_MCI_INTERRUPT_RX_MSG_REQ_WAKE 0x00001000 | 1969 | #define AR_MCI_TX_CTRL 0x1810 |
1956 | #define AR_MCI_INTERRUPT_RX_MSG_REQ_WAKE_S 12 | 1970 | /* 0 = no division, 1 = divide by 2, 2 = divide by 4, 3 = divide by 8 */ |
1957 | #define AR_MCI_INTERRUPT_RX_HW_MSG_MASK (AR_MCI_INTERRUPT_RX_MSG_SCHD_INFO | \ | 1971 | #define AR_MCI_TX_CTRL_CLK_DIV 0x03 |
1972 | #define AR_MCI_TX_CTRL_CLK_DIV_S 0 | ||
1973 | #define AR_MCI_TX_CTRL_DISABLE_LNA_UPDATE 0x04 | ||
1974 | #define AR_MCI_TX_CTRL_DISABLE_LNA_UPDATE_S 2 | ||
1975 | #define AR_MCI_TX_CTRL_GAIN_UPDATE_FREQ 0xFFFFF8 | ||
1976 | #define AR_MCI_TX_CTRL_GAIN_UPDATE_FREQ_S 3 | ||
1977 | #define AR_MCI_TX_CTRL_GAIN_UPDATE_NUM 0xF000000 | ||
1978 | #define AR_MCI_TX_CTRL_GAIN_UPDATE_NUM_S 24 | ||
1979 | |||
1980 | #define AR_MCI_MSG_ATTRIBUTES_TABLE 0x1814 | ||
1981 | #define AR_MCI_MSG_ATTRIBUTES_TABLE_CHECKSUM 0xFFFF | ||
1982 | #define AR_MCI_MSG_ATTRIBUTES_TABLE_CHECKSUM_S 0 | ||
1983 | #define AR_MCI_MSG_ATTRIBUTES_TABLE_INVALID_HDR 0xFFFF0000 | ||
1984 | #define AR_MCI_MSG_ATTRIBUTES_TABLE_INVALID_HDR_S 16 | ||
1985 | |||
1986 | #define AR_MCI_SCHD_TABLE_0 0x1818 | ||
1987 | #define AR_MCI_SCHD_TABLE_1 0x181c | ||
1988 | #define AR_MCI_GPM_0 0x1820 | ||
1989 | #define AR_MCI_GPM_1 0x1824 | ||
1990 | #define AR_MCI_GPM_WRITE_PTR 0xFFFF0000 | ||
1991 | #define AR_MCI_GPM_WRITE_PTR_S 16 | ||
1992 | #define AR_MCI_GPM_BUF_LEN 0x0000FFFF | ||
1993 | #define AR_MCI_GPM_BUF_LEN_S 0 | ||
1994 | |||
1995 | #define AR_MCI_INTERRUPT_RAW 0x1828 | ||
1996 | #define AR_MCI_INTERRUPT_EN 0x182c | ||
1997 | #define AR_MCI_INTERRUPT_SW_MSG_DONE 0x00000001 | ||
1998 | #define AR_MCI_INTERRUPT_SW_MSG_DONE_S 0 | ||
1999 | #define AR_MCI_INTERRUPT_CPU_INT_MSG 0x00000002 | ||
2000 | #define AR_MCI_INTERRUPT_CPU_INT_MSG_S 1 | ||
2001 | #define AR_MCI_INTERRUPT_RX_CKSUM_FAIL 0x00000004 | ||
2002 | #define AR_MCI_INTERRUPT_RX_CKSUM_FAIL_S 2 | ||
2003 | #define AR_MCI_INTERRUPT_RX_INVALID_HDR 0x00000008 | ||
2004 | #define AR_MCI_INTERRUPT_RX_INVALID_HDR_S 3 | ||
2005 | #define AR_MCI_INTERRUPT_RX_HW_MSG_FAIL 0x00000010 | ||
2006 | #define AR_MCI_INTERRUPT_RX_HW_MSG_FAIL_S 4 | ||
2007 | #define AR_MCI_INTERRUPT_RX_SW_MSG_FAIL 0x00000020 | ||
2008 | #define AR_MCI_INTERRUPT_RX_SW_MSG_FAIL_S 5 | ||
2009 | #define AR_MCI_INTERRUPT_TX_HW_MSG_FAIL 0x00000080 | ||
2010 | #define AR_MCI_INTERRUPT_TX_HW_MSG_FAIL_S 7 | ||
2011 | #define AR_MCI_INTERRUPT_TX_SW_MSG_FAIL 0x00000100 | ||
2012 | #define AR_MCI_INTERRUPT_TX_SW_MSG_FAIL_S 8 | ||
2013 | #define AR_MCI_INTERRUPT_RX_MSG 0x00000200 | ||
2014 | #define AR_MCI_INTERRUPT_RX_MSG_S 9 | ||
2015 | #define AR_MCI_INTERRUPT_REMOTE_SLEEP_UPDATE 0x00000400 | ||
2016 | #define AR_MCI_INTERRUPT_REMOTE_SLEEP_UPDATE_S 10 | ||
2017 | #define AR_MCI_INTERRUPT_BT_PRI 0x07fff800 | ||
2018 | #define AR_MCI_INTERRUPT_BT_PRI_S 11 | ||
2019 | #define AR_MCI_INTERRUPT_BT_PRI_THRESH 0x08000000 | ||
2020 | #define AR_MCI_INTERRUPT_BT_PRI_THRESH_S 27 | ||
2021 | #define AR_MCI_INTERRUPT_BT_FREQ 0x10000000 | ||
2022 | #define AR_MCI_INTERRUPT_BT_FREQ_S 28 | ||
2023 | #define AR_MCI_INTERRUPT_BT_STOMP 0x20000000 | ||
2024 | #define AR_MCI_INTERRUPT_BT_STOMP_S 29 | ||
2025 | #define AR_MCI_INTERRUPT_BB_AIC_IRQ 0x40000000 | ||
2026 | #define AR_MCI_INTERRUPT_BB_AIC_IRQ_S 30 | ||
2027 | #define AR_MCI_INTERRUPT_CONT_INFO_TIMEOUT 0x80000000 | ||
2028 | #define AR_MCI_INTERRUPT_CONT_INFO_TIMEOUT_S 31 | ||
2029 | |||
2030 | #define AR_MCI_INTERRUPT_DEFAULT (AR_MCI_INTERRUPT_SW_MSG_DONE | \ | ||
2031 | AR_MCI_INTERRUPT_RX_INVALID_HDR | \ | ||
2032 | AR_MCI_INTERRUPT_RX_HW_MSG_FAIL | \ | ||
2033 | AR_MCI_INTERRUPT_RX_SW_MSG_FAIL | \ | ||
2034 | AR_MCI_INTERRUPT_TX_HW_MSG_FAIL | \ | ||
2035 | AR_MCI_INTERRUPT_TX_SW_MSG_FAIL | \ | ||
2036 | AR_MCI_INTERRUPT_RX_MSG | \ | ||
2037 | AR_MCI_INTERRUPT_REMOTE_SLEEP_UPDATE | \ | ||
2038 | AR_MCI_INTERRUPT_CONT_INFO_TIMEOUT) | ||
2039 | |||
2040 | #define AR_MCI_INTERRUPT_MSG_FAIL_MASK (AR_MCI_INTERRUPT_RX_HW_MSG_FAIL | \ | ||
2041 | AR_MCI_INTERRUPT_RX_SW_MSG_FAIL | \ | ||
2042 | AR_MCI_INTERRUPT_TX_HW_MSG_FAIL | \ | ||
2043 | AR_MCI_INTERRUPT_TX_SW_MSG_FAIL) | ||
2044 | |||
2045 | #define AR_MCI_REMOTE_CPU_INT 0x1830 | ||
2046 | #define AR_MCI_REMOTE_CPU_INT_EN 0x1834 | ||
2047 | #define AR_MCI_INTERRUPT_RX_MSG_RAW 0x1838 | ||
2048 | #define AR_MCI_INTERRUPT_RX_MSG_EN 0x183c | ||
2049 | #define AR_MCI_INTERRUPT_RX_MSG_REMOTE_RESET 0x00000001 | ||
2050 | #define AR_MCI_INTERRUPT_RX_MSG_REMOTE_RESET_S 0 | ||
2051 | #define AR_MCI_INTERRUPT_RX_MSG_LNA_CONTROL 0x00000002 | ||
2052 | #define AR_MCI_INTERRUPT_RX_MSG_LNA_CONTROL_S 1 | ||
2053 | #define AR_MCI_INTERRUPT_RX_MSG_CONT_NACK 0x00000004 | ||
2054 | #define AR_MCI_INTERRUPT_RX_MSG_CONT_NACK_S 2 | ||
2055 | #define AR_MCI_INTERRUPT_RX_MSG_CONT_INFO 0x00000008 | ||
2056 | #define AR_MCI_INTERRUPT_RX_MSG_CONT_INFO_S 3 | ||
2057 | #define AR_MCI_INTERRUPT_RX_MSG_CONT_RST 0x00000010 | ||
2058 | #define AR_MCI_INTERRUPT_RX_MSG_CONT_RST_S 4 | ||
2059 | #define AR_MCI_INTERRUPT_RX_MSG_SCHD_INFO 0x00000020 | ||
2060 | #define AR_MCI_INTERRUPT_RX_MSG_SCHD_INFO_S 5 | ||
2061 | #define AR_MCI_INTERRUPT_RX_MSG_CPU_INT 0x00000040 | ||
2062 | #define AR_MCI_INTERRUPT_RX_MSG_CPU_INT_S 6 | ||
2063 | #define AR_MCI_INTERRUPT_RX_MSG_GPM 0x00000100 | ||
2064 | #define AR_MCI_INTERRUPT_RX_MSG_GPM_S 8 | ||
2065 | #define AR_MCI_INTERRUPT_RX_MSG_LNA_INFO 0x00000200 | ||
2066 | #define AR_MCI_INTERRUPT_RX_MSG_LNA_INFO_S 9 | ||
2067 | #define AR_MCI_INTERRUPT_RX_MSG_SYS_SLEEPING 0x00000400 | ||
2068 | #define AR_MCI_INTERRUPT_RX_MSG_SYS_SLEEPING_S 10 | ||
2069 | #define AR_MCI_INTERRUPT_RX_MSG_SYS_WAKING 0x00000800 | ||
2070 | #define AR_MCI_INTERRUPT_RX_MSG_SYS_WAKING_S 11 | ||
2071 | #define AR_MCI_INTERRUPT_RX_MSG_REQ_WAKE 0x00001000 | ||
2072 | #define AR_MCI_INTERRUPT_RX_MSG_REQ_WAKE_S 12 | ||
2073 | #define AR_MCI_INTERRUPT_RX_HW_MSG_MASK (AR_MCI_INTERRUPT_RX_MSG_SCHD_INFO | \ | ||
1958 | AR_MCI_INTERRUPT_RX_MSG_LNA_CONTROL| \ | 2074 | AR_MCI_INTERRUPT_RX_MSG_LNA_CONTROL| \ |
1959 | AR_MCI_INTERRUPT_RX_MSG_LNA_INFO | \ | 2075 | AR_MCI_INTERRUPT_RX_MSG_LNA_INFO | \ |
1960 | AR_MCI_INTERRUPT_RX_MSG_CONT_NACK | \ | 2076 | AR_MCI_INTERRUPT_RX_MSG_CONT_NACK | \ |
1961 | AR_MCI_INTERRUPT_RX_MSG_CONT_INFO | \ | 2077 | AR_MCI_INTERRUPT_RX_MSG_CONT_INFO | \ |
1962 | AR_MCI_INTERRUPT_RX_MSG_CONT_RST) | 2078 | AR_MCI_INTERRUPT_RX_MSG_CONT_RST) |
1963 | 2079 | ||
2080 | #define AR_MCI_INTERRUPT_RX_MSG_DEFAULT (AR_MCI_INTERRUPT_RX_MSG_GPM | \ | ||
2081 | AR_MCI_INTERRUPT_RX_MSG_REMOTE_RESET| \ | ||
2082 | AR_MCI_INTERRUPT_RX_MSG_SYS_WAKING | \ | ||
2083 | AR_MCI_INTERRUPT_RX_MSG_SYS_SLEEPING| \ | ||
2084 | AR_MCI_INTERRUPT_RX_MSG_SCHD_INFO | \ | ||
2085 | AR_MCI_INTERRUPT_RX_MSG_LNA_CONTROL | \ | ||
2086 | AR_MCI_INTERRUPT_RX_MSG_LNA_INFO | \ | ||
2087 | AR_MCI_INTERRUPT_RX_MSG_CONT_NACK | \ | ||
2088 | AR_MCI_INTERRUPT_RX_MSG_CONT_INFO | \ | ||
2089 | AR_MCI_INTERRUPT_RX_MSG_CONT_RST | \ | ||
2090 | AR_MCI_INTERRUPT_RX_MSG_REQ_WAKE) | ||
2091 | |||
2092 | #define AR_MCI_CPU_INT 0x1840 | ||
2093 | |||
2094 | #define AR_MCI_RX_STATUS 0x1844 | ||
2095 | #define AR_MCI_RX_LAST_SCHD_MSG_INDEX 0x00000F00 | ||
2096 | #define AR_MCI_RX_LAST_SCHD_MSG_INDEX_S 8 | ||
2097 | #define AR_MCI_RX_REMOTE_SLEEP 0x00001000 | ||
2098 | #define AR_MCI_RX_REMOTE_SLEEP_S 12 | ||
2099 | #define AR_MCI_RX_MCI_CLK_REQ 0x00002000 | ||
2100 | #define AR_MCI_RX_MCI_CLK_REQ_S 13 | ||
2101 | |||
2102 | #define AR_MCI_CONT_STATUS 0x1848 | ||
2103 | #define AR_MCI_CONT_RSSI_POWER 0x000000FF | ||
2104 | #define AR_MCI_CONT_RSSI_POWER_S 0 | ||
2105 | #define AR_MCI_CONT_RRIORITY 0x0000FF00 | ||
2106 | #define AR_MCI_CONT_RRIORITY_S 8 | ||
2107 | #define AR_MCI_CONT_TXRX 0x00010000 | ||
2108 | #define AR_MCI_CONT_TXRX_S 16 | ||
2109 | |||
2110 | #define AR_MCI_BT_PRI0 0x184c | ||
2111 | #define AR_MCI_BT_PRI1 0x1850 | ||
2112 | #define AR_MCI_BT_PRI2 0x1854 | ||
2113 | #define AR_MCI_BT_PRI3 0x1858 | ||
2114 | #define AR_MCI_BT_PRI 0x185c | ||
2115 | #define AR_MCI_WL_FREQ0 0x1860 | ||
2116 | #define AR_MCI_WL_FREQ1 0x1864 | ||
2117 | #define AR_MCI_WL_FREQ2 0x1868 | ||
2118 | #define AR_MCI_GAIN 0x186c | ||
2119 | #define AR_MCI_WBTIMER1 0x1870 | ||
2120 | #define AR_MCI_WBTIMER2 0x1874 | ||
2121 | #define AR_MCI_WBTIMER3 0x1878 | ||
2122 | #define AR_MCI_WBTIMER4 0x187c | ||
2123 | #define AR_MCI_MAXGAIN 0x1880 | ||
2124 | #define AR_MCI_HW_SCHD_TBL_CTL 0x1884 | ||
2125 | #define AR_MCI_HW_SCHD_TBL_D0 0x1888 | ||
2126 | #define AR_MCI_HW_SCHD_TBL_D1 0x188c | ||
2127 | #define AR_MCI_HW_SCHD_TBL_D2 0x1890 | ||
2128 | #define AR_MCI_HW_SCHD_TBL_D3 0x1894 | ||
2129 | #define AR_MCI_TX_PAYLOAD0 0x1898 | ||
2130 | #define AR_MCI_TX_PAYLOAD1 0x189c | ||
2131 | #define AR_MCI_TX_PAYLOAD2 0x18a0 | ||
2132 | #define AR_MCI_TX_PAYLOAD3 0x18a4 | ||
2133 | #define AR_BTCOEX_WBTIMER 0x18a8 | ||
2134 | |||
2135 | #define AR_BTCOEX_CTRL 0x18ac | ||
2136 | #define AR_BTCOEX_CTRL_AR9462_MODE 0x00000001 | ||
2137 | #define AR_BTCOEX_CTRL_AR9462_MODE_S 0 | ||
2138 | #define AR_BTCOEX_CTRL_WBTIMER_EN 0x00000002 | ||
2139 | #define AR_BTCOEX_CTRL_WBTIMER_EN_S 1 | ||
2140 | #define AR_BTCOEX_CTRL_MCI_MODE_EN 0x00000004 | ||
2141 | #define AR_BTCOEX_CTRL_MCI_MODE_EN_S 2 | ||
2142 | #define AR_BTCOEX_CTRL_LNA_SHARED 0x00000008 | ||
2143 | #define AR_BTCOEX_CTRL_LNA_SHARED_S 3 | ||
2144 | #define AR_BTCOEX_CTRL_PA_SHARED 0x00000010 | ||
2145 | #define AR_BTCOEX_CTRL_PA_SHARED_S 4 | ||
2146 | #define AR_BTCOEX_CTRL_ONE_STEP_LOOK_AHEAD_EN 0x00000020 | ||
2147 | #define AR_BTCOEX_CTRL_ONE_STEP_LOOK_AHEAD_EN_S 5 | ||
2148 | #define AR_BTCOEX_CTRL_TIME_TO_NEXT_BT_THRESH_EN 0x00000040 | ||
2149 | #define AR_BTCOEX_CTRL_TIME_TO_NEXT_BT_THRESH_EN_S 6 | ||
2150 | #define AR_BTCOEX_CTRL_NUM_ANTENNAS 0x00000180 | ||
2151 | #define AR_BTCOEX_CTRL_NUM_ANTENNAS_S 7 | ||
2152 | #define AR_BTCOEX_CTRL_RX_CHAIN_MASK 0x00000E00 | ||
2153 | #define AR_BTCOEX_CTRL_RX_CHAIN_MASK_S 9 | ||
2154 | #define AR_BTCOEX_CTRL_AGGR_THRESH 0x00007000 | ||
2155 | #define AR_BTCOEX_CTRL_AGGR_THRESH_S 12 | ||
2156 | #define AR_BTCOEX_CTRL_1_CHAIN_BCN 0x00080000 | ||
2157 | #define AR_BTCOEX_CTRL_1_CHAIN_BCN_S 19 | ||
2158 | #define AR_BTCOEX_CTRL_1_CHAIN_ACK 0x00100000 | ||
2159 | #define AR_BTCOEX_CTRL_1_CHAIN_ACK_S 20 | ||
2160 | #define AR_BTCOEX_CTRL_WAIT_BA_MARGIN 0x1FE00000 | ||
2161 | #define AR_BTCOEX_CTRL_WAIT_BA_MARGIN_S 28 | ||
2162 | #define AR_BTCOEX_CTRL_REDUCE_TXPWR 0x20000000 | ||
2163 | #define AR_BTCOEX_CTRL_REDUCE_TXPWR_S 29 | ||
2164 | #define AR_BTCOEX_CTRL_SPDT_ENABLE_10 0x40000000 | ||
2165 | #define AR_BTCOEX_CTRL_SPDT_ENABLE_10_S 30 | ||
2166 | #define AR_BTCOEX_CTRL_SPDT_POLARITY 0x80000000 | ||
2167 | #define AR_BTCOEX_CTRL_SPDT_POLARITY_S 31 | ||
2168 | |||
2169 | #define AR_BTCOEX_WL_WEIGHTS0 0x18b0 | ||
2170 | #define AR_BTCOEX_WL_WEIGHTS1 0x18b4 | ||
2171 | #define AR_BTCOEX_WL_WEIGHTS2 0x18b8 | ||
2172 | #define AR_BTCOEX_WL_WEIGHTS3 0x18bc | ||
2173 | #define AR_BTCOEX_MAX_TXPWR(_x) (0x18c0 + ((_x) << 2)) | ||
2174 | #define AR_BTCOEX_WL_LNA 0x1940 | ||
2175 | #define AR_BTCOEX_RFGAIN_CTRL 0x1944 | ||
2176 | |||
2177 | #define AR_BTCOEX_CTRL2 0x1948 | ||
2178 | #define AR_BTCOEX_CTRL2_TXPWR_THRESH 0x0007F800 | ||
2179 | #define AR_BTCOEX_CTRL2_TXPWR_THRESH_S 11 | ||
2180 | #define AR_BTCOEX_CTRL2_TX_CHAIN_MASK 0x00380000 | ||
2181 | #define AR_BTCOEX_CTRL2_TX_CHAIN_MASK_S 19 | ||
2182 | #define AR_BTCOEX_CTRL2_RX_DEWEIGHT 0x00400000 | ||
2183 | #define AR_BTCOEX_CTRL2_RX_DEWEIGHT_S 22 | ||
2184 | #define AR_BTCOEX_CTRL2_GPIO_OBS_SEL 0x00800000 | ||
2185 | #define AR_BTCOEX_CTRL2_GPIO_OBS_SEL_S 23 | ||
2186 | #define AR_BTCOEX_CTRL2_MAC_BB_OBS_SEL 0x01000000 | ||
2187 | #define AR_BTCOEX_CTRL2_MAC_BB_OBS_SEL_S 24 | ||
2188 | #define AR_BTCOEX_CTRL2_DESC_BASED_TXPWR_ENABLE 0x02000000 | ||
2189 | #define AR_BTCOEX_CTRL2_DESC_BASED_TXPWR_ENABLE_S 25 | ||
2190 | |||
2191 | #define AR_BTCOEX_CTRL_SPDT_ENABLE 0x00000001 | ||
2192 | #define AR_BTCOEX_CTRL_SPDT_ENABLE_S 0 | ||
2193 | #define AR_BTCOEX_CTRL_BT_OWN_SPDT_CTRL 0x00000002 | ||
2194 | #define AR_BTCOEX_CTRL_BT_OWN_SPDT_CTRL_S 1 | ||
2195 | #define AR_BTCOEX_CTRL_USE_LATCHED_BT_ANT 0x00000004 | ||
2196 | #define AR_BTCOEX_CTRL_USE_LATCHED_BT_ANT_S 2 | ||
2197 | #define AR_GLB_WLAN_UART_INTF_EN 0x00020000 | ||
2198 | #define AR_GLB_WLAN_UART_INTF_EN_S 17 | ||
2199 | #define AR_GLB_DS_JTAG_DISABLE 0x00040000 | ||
2200 | #define AR_GLB_DS_JTAG_DISABLE_S 18 | ||
2201 | |||
2202 | #define AR_BTCOEX_RC 0x194c | ||
2203 | #define AR_BTCOEX_MAX_RFGAIN(_x) (0x1950 + ((_x) << 2)) | ||
2204 | #define AR_BTCOEX_DBG 0x1a50 | ||
2205 | #define AR_MCI_LAST_HW_MSG_HDR 0x1a54 | ||
2206 | #define AR_MCI_LAST_HW_MSG_BDY 0x1a58 | ||
2207 | |||
2208 | #define AR_MCI_SCHD_TABLE_2 0x1a5c | ||
2209 | #define AR_MCI_SCHD_TABLE_2_MEM_BASED 0x00000001 | ||
2210 | #define AR_MCI_SCHD_TABLE_2_MEM_BASED_S 0 | ||
2211 | #define AR_MCI_SCHD_TABLE_2_HW_BASED 0x00000002 | ||
2212 | #define AR_MCI_SCHD_TABLE_2_HW_BASED_S 1 | ||
2213 | |||
2214 | #define AR_BTCOEX_CTRL3 0x1a60 | ||
2215 | #define AR_BTCOEX_CTRL3_CONT_INFO_TIMEOUT 0x00000fff | ||
2216 | #define AR_BTCOEX_CTRL3_CONT_INFO_TIMEOUT_S 0 | ||
2217 | |||
1964 | 2218 | ||
1965 | #endif | 2219 | #endif |
diff --git a/drivers/net/wireless/ath/ath9k/xmit.c b/drivers/net/wireless/ath/ath9k/xmit.c index 55d077e7135d..23e80e63bca9 100644 --- a/drivers/net/wireless/ath/ath9k/xmit.c +++ b/drivers/net/wireless/ath/ath9k/xmit.c | |||
@@ -53,7 +53,7 @@ static void ath_tx_complete(struct ath_softc *sc, struct sk_buff *skb, | |||
53 | int tx_flags, struct ath_txq *txq); | 53 | int tx_flags, struct ath_txq *txq); |
54 | static void ath_tx_complete_buf(struct ath_softc *sc, struct ath_buf *bf, | 54 | static void ath_tx_complete_buf(struct ath_softc *sc, struct ath_buf *bf, |
55 | struct ath_txq *txq, struct list_head *bf_q, | 55 | struct ath_txq *txq, struct list_head *bf_q, |
56 | struct ath_tx_status *ts, int txok, int sendbar); | 56 | struct ath_tx_status *ts, int txok); |
57 | static void ath_tx_txqaddbuf(struct ath_softc *sc, struct ath_txq *txq, | 57 | static void ath_tx_txqaddbuf(struct ath_softc *sc, struct ath_txq *txq, |
58 | struct list_head *head, bool internal); | 58 | struct list_head *head, bool internal); |
59 | static void ath_tx_rc_status(struct ath_softc *sc, struct ath_buf *bf, | 59 | static void ath_tx_rc_status(struct ath_softc *sc, struct ath_buf *bf, |
@@ -150,6 +150,12 @@ static struct ath_frame_info *get_frame_info(struct sk_buff *skb) | |||
150 | return (struct ath_frame_info *) &tx_info->rate_driver_data[0]; | 150 | return (struct ath_frame_info *) &tx_info->rate_driver_data[0]; |
151 | } | 151 | } |
152 | 152 | ||
153 | static void ath_send_bar(struct ath_atx_tid *tid, u16 seqno) | ||
154 | { | ||
155 | ieee80211_send_bar(tid->an->vif, tid->an->sta->addr, tid->tidno, | ||
156 | seqno << IEEE80211_SEQ_SEQ_SHIFT); | ||
157 | } | ||
158 | |||
153 | static void ath_tx_flush_tid(struct ath_softc *sc, struct ath_atx_tid *tid) | 159 | static void ath_tx_flush_tid(struct ath_softc *sc, struct ath_atx_tid *tid) |
154 | { | 160 | { |
155 | struct ath_txq *txq = tid->ac->txq; | 161 | struct ath_txq *txq = tid->ac->txq; |
@@ -158,28 +164,33 @@ static void ath_tx_flush_tid(struct ath_softc *sc, struct ath_atx_tid *tid) | |||
158 | struct list_head bf_head; | 164 | struct list_head bf_head; |
159 | struct ath_tx_status ts; | 165 | struct ath_tx_status ts; |
160 | struct ath_frame_info *fi; | 166 | struct ath_frame_info *fi; |
167 | bool sendbar = false; | ||
161 | 168 | ||
162 | INIT_LIST_HEAD(&bf_head); | 169 | INIT_LIST_HEAD(&bf_head); |
163 | 170 | ||
164 | memset(&ts, 0, sizeof(ts)); | 171 | memset(&ts, 0, sizeof(ts)); |
165 | spin_lock_bh(&txq->axq_lock); | ||
166 | 172 | ||
167 | while ((skb = __skb_dequeue(&tid->buf_q))) { | 173 | while ((skb = __skb_dequeue(&tid->buf_q))) { |
168 | fi = get_frame_info(skb); | 174 | fi = get_frame_info(skb); |
169 | bf = fi->bf; | 175 | bf = fi->bf; |
170 | 176 | ||
171 | spin_unlock_bh(&txq->axq_lock); | ||
172 | if (bf && fi->retries) { | 177 | if (bf && fi->retries) { |
173 | list_add_tail(&bf->list, &bf_head); | 178 | list_add_tail(&bf->list, &bf_head); |
174 | ath_tx_update_baw(sc, tid, bf->bf_state.seqno); | 179 | ath_tx_update_baw(sc, tid, bf->bf_state.seqno); |
175 | ath_tx_complete_buf(sc, bf, txq, &bf_head, &ts, 0, 1); | 180 | ath_tx_complete_buf(sc, bf, txq, &bf_head, &ts, 0); |
181 | sendbar = true; | ||
176 | } else { | 182 | } else { |
177 | ath_tx_send_normal(sc, txq, NULL, skb); | 183 | ath_tx_send_normal(sc, txq, NULL, skb); |
178 | } | 184 | } |
179 | spin_lock_bh(&txq->axq_lock); | ||
180 | } | 185 | } |
181 | 186 | ||
182 | spin_unlock_bh(&txq->axq_lock); | 187 | if (tid->baw_head == tid->baw_tail) { |
188 | tid->state &= ~AGGR_ADDBA_COMPLETE; | ||
189 | tid->state &= ~AGGR_CLEANUP; | ||
190 | } | ||
191 | |||
192 | if (sendbar) | ||
193 | ath_send_bar(tid, tid->seq_start); | ||
183 | } | 194 | } |
184 | 195 | ||
185 | static void ath_tx_update_baw(struct ath_softc *sc, struct ath_atx_tid *tid, | 196 | static void ath_tx_update_baw(struct ath_softc *sc, struct ath_atx_tid *tid, |
@@ -195,6 +206,8 @@ static void ath_tx_update_baw(struct ath_softc *sc, struct ath_atx_tid *tid, | |||
195 | while (tid->baw_head != tid->baw_tail && !test_bit(tid->baw_head, tid->tx_buf)) { | 206 | while (tid->baw_head != tid->baw_tail && !test_bit(tid->baw_head, tid->tx_buf)) { |
196 | INCR(tid->seq_start, IEEE80211_SEQ_MAX); | 207 | INCR(tid->seq_start, IEEE80211_SEQ_MAX); |
197 | INCR(tid->baw_head, ATH_TID_MAX_BUFS); | 208 | INCR(tid->baw_head, ATH_TID_MAX_BUFS); |
209 | if (tid->bar_index >= 0) | ||
210 | tid->bar_index--; | ||
198 | } | 211 | } |
199 | } | 212 | } |
200 | 213 | ||
@@ -238,9 +251,7 @@ static void ath_tid_drain(struct ath_softc *sc, struct ath_txq *txq, | |||
238 | bf = fi->bf; | 251 | bf = fi->bf; |
239 | 252 | ||
240 | if (!bf) { | 253 | if (!bf) { |
241 | spin_unlock(&txq->axq_lock); | ||
242 | ath_tx_complete(sc, skb, ATH_TX_ERROR, txq); | 254 | ath_tx_complete(sc, skb, ATH_TX_ERROR, txq); |
243 | spin_lock(&txq->axq_lock); | ||
244 | continue; | 255 | continue; |
245 | } | 256 | } |
246 | 257 | ||
@@ -249,24 +260,26 @@ static void ath_tid_drain(struct ath_softc *sc, struct ath_txq *txq, | |||
249 | if (fi->retries) | 260 | if (fi->retries) |
250 | ath_tx_update_baw(sc, tid, bf->bf_state.seqno); | 261 | ath_tx_update_baw(sc, tid, bf->bf_state.seqno); |
251 | 262 | ||
252 | spin_unlock(&txq->axq_lock); | 263 | ath_tx_complete_buf(sc, bf, txq, &bf_head, &ts, 0); |
253 | ath_tx_complete_buf(sc, bf, txq, &bf_head, &ts, 0, 0); | ||
254 | spin_lock(&txq->axq_lock); | ||
255 | } | 264 | } |
256 | 265 | ||
257 | tid->seq_next = tid->seq_start; | 266 | tid->seq_next = tid->seq_start; |
258 | tid->baw_tail = tid->baw_head; | 267 | tid->baw_tail = tid->baw_head; |
268 | tid->bar_index = -1; | ||
259 | } | 269 | } |
260 | 270 | ||
261 | static void ath_tx_set_retry(struct ath_softc *sc, struct ath_txq *txq, | 271 | static void ath_tx_set_retry(struct ath_softc *sc, struct ath_txq *txq, |
262 | struct sk_buff *skb) | 272 | struct sk_buff *skb, int count) |
263 | { | 273 | { |
264 | struct ath_frame_info *fi = get_frame_info(skb); | 274 | struct ath_frame_info *fi = get_frame_info(skb); |
265 | struct ath_buf *bf = fi->bf; | 275 | struct ath_buf *bf = fi->bf; |
266 | struct ieee80211_hdr *hdr; | 276 | struct ieee80211_hdr *hdr; |
277 | int prev = fi->retries; | ||
267 | 278 | ||
268 | TX_STAT_INC(txq->axq_qnum, a_retries); | 279 | TX_STAT_INC(txq->axq_qnum, a_retries); |
269 | if (fi->retries++ > 0) | 280 | fi->retries += count; |
281 | |||
282 | if (prev > 0) | ||
270 | return; | 283 | return; |
271 | 284 | ||
272 | hdr = (struct ieee80211_hdr *)skb->data; | 285 | hdr = (struct ieee80211_hdr *)skb->data; |
@@ -365,7 +378,7 @@ static void ath_tx_complete_aggr(struct ath_softc *sc, struct ath_txq *txq, | |||
365 | struct ath_buf *bf_next, *bf_last = bf->bf_lastbf; | 378 | struct ath_buf *bf_next, *bf_last = bf->bf_lastbf; |
366 | struct list_head bf_head; | 379 | struct list_head bf_head; |
367 | struct sk_buff_head bf_pending; | 380 | struct sk_buff_head bf_pending; |
368 | u16 seq_st = 0, acked_cnt = 0, txfail_cnt = 0; | 381 | u16 seq_st = 0, acked_cnt = 0, txfail_cnt = 0, seq_first; |
369 | u32 ba[WME_BA_BMP_SIZE >> 5]; | 382 | u32 ba[WME_BA_BMP_SIZE >> 5]; |
370 | int isaggr, txfail, txpending, sendbar = 0, needreset = 0, nbad = 0; | 383 | int isaggr, txfail, txpending, sendbar = 0, needreset = 0, nbad = 0; |
371 | bool rc_update = true; | 384 | bool rc_update = true; |
@@ -374,6 +387,8 @@ static void ath_tx_complete_aggr(struct ath_softc *sc, struct ath_txq *txq, | |||
374 | int nframes; | 387 | int nframes; |
375 | u8 tidno; | 388 | u8 tidno; |
376 | bool flush = !!(ts->ts_status & ATH9K_TX_FLUSH); | 389 | bool flush = !!(ts->ts_status & ATH9K_TX_FLUSH); |
390 | int i, retries; | ||
391 | int bar_index = -1; | ||
377 | 392 | ||
378 | skb = bf->bf_mpdu; | 393 | skb = bf->bf_mpdu; |
379 | hdr = (struct ieee80211_hdr *)skb->data; | 394 | hdr = (struct ieee80211_hdr *)skb->data; |
@@ -382,6 +397,10 @@ static void ath_tx_complete_aggr(struct ath_softc *sc, struct ath_txq *txq, | |||
382 | 397 | ||
383 | memcpy(rates, tx_info->control.rates, sizeof(rates)); | 398 | memcpy(rates, tx_info->control.rates, sizeof(rates)); |
384 | 399 | ||
400 | retries = ts->ts_longretry + 1; | ||
401 | for (i = 0; i < ts->ts_rateindex; i++) | ||
402 | retries += rates[i].count; | ||
403 | |||
385 | rcu_read_lock(); | 404 | rcu_read_lock(); |
386 | 405 | ||
387 | sta = ieee80211_find_sta_by_ifaddr(hw, hdr->addr1, hdr->addr2); | 406 | sta = ieee80211_find_sta_by_ifaddr(hw, hdr->addr1, hdr->addr2); |
@@ -395,8 +414,7 @@ static void ath_tx_complete_aggr(struct ath_softc *sc, struct ath_txq *txq, | |||
395 | if (!bf->bf_stale || bf_next != NULL) | 414 | if (!bf->bf_stale || bf_next != NULL) |
396 | list_move_tail(&bf->list, &bf_head); | 415 | list_move_tail(&bf->list, &bf_head); |
397 | 416 | ||
398 | ath_tx_complete_buf(sc, bf, txq, &bf_head, ts, | 417 | ath_tx_complete_buf(sc, bf, txq, &bf_head, ts, 0); |
399 | 0, 0); | ||
400 | 418 | ||
401 | bf = bf_next; | 419 | bf = bf_next; |
402 | } | 420 | } |
@@ -406,6 +424,7 @@ static void ath_tx_complete_aggr(struct ath_softc *sc, struct ath_txq *txq, | |||
406 | an = (struct ath_node *)sta->drv_priv; | 424 | an = (struct ath_node *)sta->drv_priv; |
407 | tidno = ieee80211_get_qos_ctl(hdr)[0] & IEEE80211_QOS_CTL_TID_MASK; | 425 | tidno = ieee80211_get_qos_ctl(hdr)[0] & IEEE80211_QOS_CTL_TID_MASK; |
408 | tid = ATH_AN_2_TID(an, tidno); | 426 | tid = ATH_AN_2_TID(an, tidno); |
427 | seq_first = tid->seq_start; | ||
409 | 428 | ||
410 | /* | 429 | /* |
411 | * The hardware occasionally sends a tx status for the wrong TID. | 430 | * The hardware occasionally sends a tx status for the wrong TID. |
@@ -455,25 +474,25 @@ static void ath_tx_complete_aggr(struct ath_softc *sc, struct ath_txq *txq, | |||
455 | } else if (!isaggr && txok) { | 474 | } else if (!isaggr && txok) { |
456 | /* transmit completion */ | 475 | /* transmit completion */ |
457 | acked_cnt++; | 476 | acked_cnt++; |
477 | } else if ((tid->state & AGGR_CLEANUP) || !retry) { | ||
478 | /* | ||
479 | * cleanup in progress, just fail | ||
480 | * the un-acked sub-frames | ||
481 | */ | ||
482 | txfail = 1; | ||
483 | } else if (flush) { | ||
484 | txpending = 1; | ||
485 | } else if (fi->retries < ATH_MAX_SW_RETRIES) { | ||
486 | if (txok || !an->sleeping) | ||
487 | ath_tx_set_retry(sc, txq, bf->bf_mpdu, | ||
488 | retries); | ||
489 | |||
490 | txpending = 1; | ||
458 | } else { | 491 | } else { |
459 | if ((tid->state & AGGR_CLEANUP) || !retry) { | 492 | txfail = 1; |
460 | /* | 493 | txfail_cnt++; |
461 | * cleanup in progress, just fail | 494 | bar_index = max_t(int, bar_index, |
462 | * the un-acked sub-frames | 495 | ATH_BA_INDEX(seq_first, seqno)); |
463 | */ | ||
464 | txfail = 1; | ||
465 | } else if (flush) { | ||
466 | txpending = 1; | ||
467 | } else if (fi->retries < ATH_MAX_SW_RETRIES) { | ||
468 | if (txok || !an->sleeping) | ||
469 | ath_tx_set_retry(sc, txq, bf->bf_mpdu); | ||
470 | |||
471 | txpending = 1; | ||
472 | } else { | ||
473 | txfail = 1; | ||
474 | sendbar = 1; | ||
475 | txfail_cnt++; | ||
476 | } | ||
477 | } | 496 | } |
478 | 497 | ||
479 | /* | 498 | /* |
@@ -490,9 +509,7 @@ static void ath_tx_complete_aggr(struct ath_softc *sc, struct ath_txq *txq, | |||
490 | * complete the acked-ones/xretried ones; update | 509 | * complete the acked-ones/xretried ones; update |
491 | * block-ack window | 510 | * block-ack window |
492 | */ | 511 | */ |
493 | spin_lock_bh(&txq->axq_lock); | ||
494 | ath_tx_update_baw(sc, tid, seqno); | 512 | ath_tx_update_baw(sc, tid, seqno); |
495 | spin_unlock_bh(&txq->axq_lock); | ||
496 | 513 | ||
497 | if (rc_update && (acked_cnt == 1 || txfail_cnt == 1)) { | 514 | if (rc_update && (acked_cnt == 1 || txfail_cnt == 1)) { |
498 | memcpy(tx_info->control.rates, rates, sizeof(rates)); | 515 | memcpy(tx_info->control.rates, rates, sizeof(rates)); |
@@ -501,33 +518,30 @@ static void ath_tx_complete_aggr(struct ath_softc *sc, struct ath_txq *txq, | |||
501 | } | 518 | } |
502 | 519 | ||
503 | ath_tx_complete_buf(sc, bf, txq, &bf_head, ts, | 520 | ath_tx_complete_buf(sc, bf, txq, &bf_head, ts, |
504 | !txfail, sendbar); | 521 | !txfail); |
505 | } else { | 522 | } else { |
506 | /* retry the un-acked ones */ | 523 | /* retry the un-acked ones */ |
507 | if (!(sc->sc_ah->caps.hw_caps & ATH9K_HW_CAP_EDMA)) { | 524 | if (!(sc->sc_ah->caps.hw_caps & ATH9K_HW_CAP_EDMA) && |
508 | if (bf->bf_next == NULL && bf_last->bf_stale) { | 525 | bf->bf_next == NULL && bf_last->bf_stale) { |
509 | struct ath_buf *tbf; | 526 | struct ath_buf *tbf; |
510 | 527 | ||
511 | tbf = ath_clone_txbuf(sc, bf_last); | 528 | tbf = ath_clone_txbuf(sc, bf_last); |
512 | /* | 529 | /* |
513 | * Update tx baw and complete the | 530 | * Update tx baw and complete the |
514 | * frame with failed status if we | 531 | * frame with failed status if we |
515 | * run out of tx buf. | 532 | * run out of tx buf. |
516 | */ | 533 | */ |
517 | if (!tbf) { | 534 | if (!tbf) { |
518 | spin_lock_bh(&txq->axq_lock); | 535 | ath_tx_update_baw(sc, tid, seqno); |
519 | ath_tx_update_baw(sc, tid, seqno); | 536 | |
520 | spin_unlock_bh(&txq->axq_lock); | 537 | ath_tx_complete_buf(sc, bf, txq, |
521 | 538 | &bf_head, ts, 0); | |
522 | ath_tx_complete_buf(sc, bf, txq, | 539 | bar_index = max_t(int, bar_index, |
523 | &bf_head, | 540 | ATH_BA_INDEX(seq_first, seqno)); |
524 | ts, 0, | 541 | break; |
525 | !flush); | ||
526 | break; | ||
527 | } | ||
528 | |||
529 | fi->bf = tbf; | ||
530 | } | 542 | } |
543 | |||
544 | fi->bf = tbf; | ||
531 | } | 545 | } |
532 | 546 | ||
533 | /* | 547 | /* |
@@ -540,12 +554,18 @@ static void ath_tx_complete_aggr(struct ath_softc *sc, struct ath_txq *txq, | |||
540 | bf = bf_next; | 554 | bf = bf_next; |
541 | } | 555 | } |
542 | 556 | ||
557 | if (bar_index >= 0) { | ||
558 | u16 bar_seq = ATH_BA_INDEX2SEQ(seq_first, bar_index); | ||
559 | ath_send_bar(tid, ATH_BA_INDEX2SEQ(seq_first, bar_index + 1)); | ||
560 | if (BAW_WITHIN(tid->seq_start, tid->baw_size, bar_seq)) | ||
561 | tid->bar_index = ATH_BA_INDEX(tid->seq_start, bar_seq); | ||
562 | } | ||
563 | |||
543 | /* prepend un-acked frames to the beginning of the pending frame queue */ | 564 | /* prepend un-acked frames to the beginning of the pending frame queue */ |
544 | if (!skb_queue_empty(&bf_pending)) { | 565 | if (!skb_queue_empty(&bf_pending)) { |
545 | if (an->sleeping) | 566 | if (an->sleeping) |
546 | ieee80211_sta_set_buffered(sta, tid->tidno, true); | 567 | ieee80211_sta_set_buffered(sta, tid->tidno, true); |
547 | 568 | ||
548 | spin_lock_bh(&txq->axq_lock); | ||
549 | skb_queue_splice(&bf_pending, &tid->buf_q); | 569 | skb_queue_splice(&bf_pending, &tid->buf_q); |
550 | if (!an->sleeping) { | 570 | if (!an->sleeping) { |
551 | ath_tx_queue_tid(txq, tid); | 571 | ath_tx_queue_tid(txq, tid); |
@@ -553,18 +573,11 @@ static void ath_tx_complete_aggr(struct ath_softc *sc, struct ath_txq *txq, | |||
553 | if (ts->ts_status & ATH9K_TXERR_FILT) | 573 | if (ts->ts_status & ATH9K_TXERR_FILT) |
554 | tid->ac->clear_ps_filter = true; | 574 | tid->ac->clear_ps_filter = true; |
555 | } | 575 | } |
556 | spin_unlock_bh(&txq->axq_lock); | ||
557 | } | 576 | } |
558 | 577 | ||
559 | if (tid->state & AGGR_CLEANUP) { | 578 | if (tid->state & AGGR_CLEANUP) |
560 | ath_tx_flush_tid(sc, tid); | 579 | ath_tx_flush_tid(sc, tid); |
561 | 580 | ||
562 | if (tid->baw_head == tid->baw_tail) { | ||
563 | tid->state &= ~AGGR_ADDBA_COMPLETE; | ||
564 | tid->state &= ~AGGR_CLEANUP; | ||
565 | } | ||
566 | } | ||
567 | |||
568 | rcu_read_unlock(); | 581 | rcu_read_unlock(); |
569 | 582 | ||
570 | if (needreset) { | 583 | if (needreset) { |
@@ -618,24 +631,26 @@ static u32 ath_lookup_rate(struct ath_softc *sc, struct ath_buf *bf, | |||
618 | max_4ms_framelen = ATH_AMPDU_LIMIT_MAX; | 631 | max_4ms_framelen = ATH_AMPDU_LIMIT_MAX; |
619 | 632 | ||
620 | for (i = 0; i < 4; i++) { | 633 | for (i = 0; i < 4; i++) { |
621 | if (rates[i].count) { | 634 | int modeidx; |
622 | int modeidx; | ||
623 | if (!(rates[i].flags & IEEE80211_TX_RC_MCS)) { | ||
624 | legacy = 1; | ||
625 | break; | ||
626 | } | ||
627 | 635 | ||
628 | if (rates[i].flags & IEEE80211_TX_RC_40_MHZ_WIDTH) | 636 | if (!rates[i].count) |
629 | modeidx = MCS_HT40; | 637 | continue; |
630 | else | ||
631 | modeidx = MCS_HT20; | ||
632 | |||
633 | if (rates[i].flags & IEEE80211_TX_RC_SHORT_GI) | ||
634 | modeidx++; | ||
635 | 638 | ||
636 | frmlen = ath_max_4ms_framelen[modeidx][rates[i].idx]; | 639 | if (!(rates[i].flags & IEEE80211_TX_RC_MCS)) { |
637 | max_4ms_framelen = min(max_4ms_framelen, frmlen); | 640 | legacy = 1; |
641 | break; | ||
638 | } | 642 | } |
643 | |||
644 | if (rates[i].flags & IEEE80211_TX_RC_40_MHZ_WIDTH) | ||
645 | modeidx = MCS_HT40; | ||
646 | else | ||
647 | modeidx = MCS_HT20; | ||
648 | |||
649 | if (rates[i].flags & IEEE80211_TX_RC_SHORT_GI) | ||
650 | modeidx++; | ||
651 | |||
652 | frmlen = ath_max_4ms_framelen[modeidx][rates[i].idx]; | ||
653 | max_4ms_framelen = min(max_4ms_framelen, frmlen); | ||
639 | } | 654 | } |
640 | 655 | ||
641 | /* | 656 | /* |
@@ -771,8 +786,6 @@ static enum ATH_AGGR_STATUS ath_tx_form_aggr(struct ath_softc *sc, | |||
771 | 786 | ||
772 | bf->bf_state.bf_type = BUF_AMPDU | BUF_AGGR; | 787 | bf->bf_state.bf_type = BUF_AMPDU | BUF_AGGR; |
773 | seqno = bf->bf_state.seqno; | 788 | seqno = bf->bf_state.seqno; |
774 | if (!bf_first) | ||
775 | bf_first = bf; | ||
776 | 789 | ||
777 | /* do not step over block-ack window */ | 790 | /* do not step over block-ack window */ |
778 | if (!BAW_WITHIN(tid->seq_start, tid->baw_size, seqno)) { | 791 | if (!BAW_WITHIN(tid->seq_start, tid->baw_size, seqno)) { |
@@ -780,6 +793,21 @@ static enum ATH_AGGR_STATUS ath_tx_form_aggr(struct ath_softc *sc, | |||
780 | break; | 793 | break; |
781 | } | 794 | } |
782 | 795 | ||
796 | if (tid->bar_index > ATH_BA_INDEX(tid->seq_start, seqno)) { | ||
797 | struct ath_tx_status ts = {}; | ||
798 | struct list_head bf_head; | ||
799 | |||
800 | INIT_LIST_HEAD(&bf_head); | ||
801 | list_add(&bf->list, &bf_head); | ||
802 | __skb_unlink(skb, &tid->buf_q); | ||
803 | ath_tx_update_baw(sc, tid, seqno); | ||
804 | ath_tx_complete_buf(sc, bf, txq, &bf_head, &ts, 0); | ||
805 | continue; | ||
806 | } | ||
807 | |||
808 | if (!bf_first) | ||
809 | bf_first = bf; | ||
810 | |||
783 | if (!rl) { | 811 | if (!rl) { |
784 | aggr_limit = ath_lookup_rate(sc, bf, tid); | 812 | aggr_limit = ath_lookup_rate(sc, bf, tid); |
785 | rl = 1; | 813 | rl = 1; |
@@ -1122,6 +1150,7 @@ int ath_tx_aggr_start(struct ath_softc *sc, struct ieee80211_sta *sta, | |||
1122 | txtid->state |= AGGR_ADDBA_PROGRESS; | 1150 | txtid->state |= AGGR_ADDBA_PROGRESS; |
1123 | txtid->paused = true; | 1151 | txtid->paused = true; |
1124 | *ssn = txtid->seq_start = txtid->seq_next; | 1152 | *ssn = txtid->seq_start = txtid->seq_next; |
1153 | txtid->bar_index = -1; | ||
1125 | 1154 | ||
1126 | memset(txtid->tx_buf, 0, sizeof(txtid->tx_buf)); | 1155 | memset(txtid->tx_buf, 0, sizeof(txtid->tx_buf)); |
1127 | txtid->baw_head = txtid->baw_tail = 0; | 1156 | txtid->baw_head = txtid->baw_tail = 0; |
@@ -1156,9 +1185,9 @@ void ath_tx_aggr_stop(struct ath_softc *sc, struct ieee80211_sta *sta, u16 tid) | |||
1156 | txtid->state |= AGGR_CLEANUP; | 1185 | txtid->state |= AGGR_CLEANUP; |
1157 | else | 1186 | else |
1158 | txtid->state &= ~AGGR_ADDBA_COMPLETE; | 1187 | txtid->state &= ~AGGR_ADDBA_COMPLETE; |
1159 | spin_unlock_bh(&txq->axq_lock); | ||
1160 | 1188 | ||
1161 | ath_tx_flush_tid(sc, txtid); | 1189 | ath_tx_flush_tid(sc, txtid); |
1190 | spin_unlock_bh(&txq->axq_lock); | ||
1162 | } | 1191 | } |
1163 | 1192 | ||
1164 | void ath_tx_aggr_sleep(struct ieee80211_sta *sta, struct ath_softc *sc, | 1193 | void ath_tx_aggr_sleep(struct ieee80211_sta *sta, struct ath_softc *sc, |
@@ -1400,8 +1429,6 @@ static bool bf_is_ampdu_not_probing(struct ath_buf *bf) | |||
1400 | 1429 | ||
1401 | static void ath_drain_txq_list(struct ath_softc *sc, struct ath_txq *txq, | 1430 | static void ath_drain_txq_list(struct ath_softc *sc, struct ath_txq *txq, |
1402 | struct list_head *list, bool retry_tx) | 1431 | struct list_head *list, bool retry_tx) |
1403 | __releases(txq->axq_lock) | ||
1404 | __acquires(txq->axq_lock) | ||
1405 | { | 1432 | { |
1406 | struct ath_buf *bf, *lastbf; | 1433 | struct ath_buf *bf, *lastbf; |
1407 | struct list_head bf_head; | 1434 | struct list_head bf_head; |
@@ -1428,13 +1455,11 @@ static void ath_drain_txq_list(struct ath_softc *sc, struct ath_txq *txq, | |||
1428 | if (bf_is_ampdu_not_probing(bf)) | 1455 | if (bf_is_ampdu_not_probing(bf)) |
1429 | txq->axq_ampdu_depth--; | 1456 | txq->axq_ampdu_depth--; |
1430 | 1457 | ||
1431 | spin_unlock_bh(&txq->axq_lock); | ||
1432 | if (bf_isampdu(bf)) | 1458 | if (bf_isampdu(bf)) |
1433 | ath_tx_complete_aggr(sc, txq, bf, &bf_head, &ts, 0, | 1459 | ath_tx_complete_aggr(sc, txq, bf, &bf_head, &ts, 0, |
1434 | retry_tx); | 1460 | retry_tx); |
1435 | else | 1461 | else |
1436 | ath_tx_complete_buf(sc, bf, txq, &bf_head, &ts, 0, 0); | 1462 | ath_tx_complete_buf(sc, bf, txq, &bf_head, &ts, 0); |
1437 | spin_lock_bh(&txq->axq_lock); | ||
1438 | } | 1463 | } |
1439 | } | 1464 | } |
1440 | 1465 | ||
@@ -1561,11 +1586,9 @@ void ath_txq_schedule(struct ath_softc *sc, struct ath_txq *txq) | |||
1561 | break; | 1586 | break; |
1562 | } | 1587 | } |
1563 | 1588 | ||
1564 | if (!list_empty(&ac->tid_q)) { | 1589 | if (!list_empty(&ac->tid_q) && !ac->sched) { |
1565 | if (!ac->sched) { | 1590 | ac->sched = true; |
1566 | ac->sched = true; | 1591 | list_add_tail(&ac->list, &txq->axq_acq); |
1567 | list_add_tail(&ac->list, &txq->axq_acq); | ||
1568 | } | ||
1569 | } | 1592 | } |
1570 | 1593 | ||
1571 | if (ac == last_ac || | 1594 | if (ac == last_ac || |
@@ -1708,10 +1731,6 @@ static void ath_tx_send_normal(struct ath_softc *sc, struct ath_txq *txq, | |||
1708 | list_add_tail(&bf->list, &bf_head); | 1731 | list_add_tail(&bf->list, &bf_head); |
1709 | bf->bf_state.bf_type = 0; | 1732 | bf->bf_state.bf_type = 0; |
1710 | 1733 | ||
1711 | /* update starting sequence number for subsequent ADDBA request */ | ||
1712 | if (tid) | ||
1713 | INCR(tid->seq_start, IEEE80211_SEQ_MAX); | ||
1714 | |||
1715 | bf->bf_lastbf = bf; | 1734 | bf->bf_lastbf = bf; |
1716 | ath_tx_fill_desc(sc, bf, txq, fi->framelen); | 1735 | ath_tx_fill_desc(sc, bf, txq, fi->framelen); |
1717 | ath_tx_txqaddbuf(sc, txq, &bf_head, false); | 1736 | ath_tx_txqaddbuf(sc, txq, &bf_head, false); |
@@ -1819,7 +1838,6 @@ static void ath_tx_start_dma(struct ath_softc *sc, struct sk_buff *skb, | |||
1819 | struct ath_buf *bf; | 1838 | struct ath_buf *bf; |
1820 | u8 tidno; | 1839 | u8 tidno; |
1821 | 1840 | ||
1822 | spin_lock_bh(&txctl->txq->axq_lock); | ||
1823 | if ((sc->sc_flags & SC_OP_TXAGGR) && txctl->an && | 1841 | if ((sc->sc_flags & SC_OP_TXAGGR) && txctl->an && |
1824 | ieee80211_is_data_qos(hdr->frame_control)) { | 1842 | ieee80211_is_data_qos(hdr->frame_control)) { |
1825 | tidno = ieee80211_get_qos_ctl(hdr)[0] & | 1843 | tidno = ieee80211_get_qos_ctl(hdr)[0] & |
@@ -1838,7 +1856,7 @@ static void ath_tx_start_dma(struct ath_softc *sc, struct sk_buff *skb, | |||
1838 | } else { | 1856 | } else { |
1839 | bf = ath_tx_setup_buffer(sc, txctl->txq, tid, skb); | 1857 | bf = ath_tx_setup_buffer(sc, txctl->txq, tid, skb); |
1840 | if (!bf) | 1858 | if (!bf) |
1841 | goto out; | 1859 | return; |
1842 | 1860 | ||
1843 | bf->bf_state.bfs_paprd = txctl->paprd; | 1861 | bf->bf_state.bfs_paprd = txctl->paprd; |
1844 | 1862 | ||
@@ -1847,9 +1865,6 @@ static void ath_tx_start_dma(struct ath_softc *sc, struct sk_buff *skb, | |||
1847 | 1865 | ||
1848 | ath_tx_send_normal(sc, txctl->txq, tid, skb); | 1866 | ath_tx_send_normal(sc, txctl->txq, tid, skb); |
1849 | } | 1867 | } |
1850 | |||
1851 | out: | ||
1852 | spin_unlock_bh(&txctl->txq->axq_lock); | ||
1853 | } | 1868 | } |
1854 | 1869 | ||
1855 | /* Upon failure caller should free skb */ | 1870 | /* Upon failure caller should free skb */ |
@@ -1916,9 +1931,11 @@ int ath_tx_start(struct ieee80211_hw *hw, struct sk_buff *skb, | |||
1916 | ieee80211_stop_queue(sc->hw, q); | 1931 | ieee80211_stop_queue(sc->hw, q); |
1917 | txq->stopped = 1; | 1932 | txq->stopped = 1; |
1918 | } | 1933 | } |
1919 | spin_unlock_bh(&txq->axq_lock); | ||
1920 | 1934 | ||
1921 | ath_tx_start_dma(sc, skb, txctl); | 1935 | ath_tx_start_dma(sc, skb, txctl); |
1936 | |||
1937 | spin_unlock_bh(&txq->axq_lock); | ||
1938 | |||
1922 | return 0; | 1939 | return 0; |
1923 | } | 1940 | } |
1924 | 1941 | ||
@@ -1937,9 +1954,6 @@ static void ath_tx_complete(struct ath_softc *sc, struct sk_buff *skb, | |||
1937 | 1954 | ||
1938 | ath_dbg(common, ATH_DBG_XMIT, "TX complete: skb: %p\n", skb); | 1955 | ath_dbg(common, ATH_DBG_XMIT, "TX complete: skb: %p\n", skb); |
1939 | 1956 | ||
1940 | if (tx_flags & ATH_TX_BAR) | ||
1941 | tx_info->flags |= IEEE80211_TX_STAT_AMPDU_NO_BACK; | ||
1942 | |||
1943 | if (!(tx_flags & ATH_TX_ERROR)) | 1957 | if (!(tx_flags & ATH_TX_ERROR)) |
1944 | /* Frame was ACKed */ | 1958 | /* Frame was ACKed */ |
1945 | tx_info->flags |= IEEE80211_TX_STAT_ACK; | 1959 | tx_info->flags |= IEEE80211_TX_STAT_ACK; |
@@ -1955,7 +1969,7 @@ static void ath_tx_complete(struct ath_softc *sc, struct sk_buff *skb, | |||
1955 | skb_pull(skb, padsize); | 1969 | skb_pull(skb, padsize); |
1956 | } | 1970 | } |
1957 | 1971 | ||
1958 | if (sc->ps_flags & PS_WAIT_FOR_TX_ACK) { | 1972 | if ((sc->ps_flags & PS_WAIT_FOR_TX_ACK) && !txq->axq_depth) { |
1959 | sc->ps_flags &= ~PS_WAIT_FOR_TX_ACK; | 1973 | sc->ps_flags &= ~PS_WAIT_FOR_TX_ACK; |
1960 | ath_dbg(common, ATH_DBG_PS, | 1974 | ath_dbg(common, ATH_DBG_PS, |
1961 | "Going back to sleep after having received TX status (0x%lx)\n", | 1975 | "Going back to sleep after having received TX status (0x%lx)\n", |
@@ -1967,7 +1981,6 @@ static void ath_tx_complete(struct ath_softc *sc, struct sk_buff *skb, | |||
1967 | 1981 | ||
1968 | q = skb_get_queue_mapping(skb); | 1982 | q = skb_get_queue_mapping(skb); |
1969 | if (txq == sc->tx.txq_map[q]) { | 1983 | if (txq == sc->tx.txq_map[q]) { |
1970 | spin_lock_bh(&txq->axq_lock); | ||
1971 | if (WARN_ON(--txq->pending_frames < 0)) | 1984 | if (WARN_ON(--txq->pending_frames < 0)) |
1972 | txq->pending_frames = 0; | 1985 | txq->pending_frames = 0; |
1973 | 1986 | ||
@@ -1975,7 +1988,6 @@ static void ath_tx_complete(struct ath_softc *sc, struct sk_buff *skb, | |||
1975 | ieee80211_wake_queue(sc->hw, q); | 1988 | ieee80211_wake_queue(sc->hw, q); |
1976 | txq->stopped = 0; | 1989 | txq->stopped = 0; |
1977 | } | 1990 | } |
1978 | spin_unlock_bh(&txq->axq_lock); | ||
1979 | } | 1991 | } |
1980 | 1992 | ||
1981 | ieee80211_tx_status(hw, skb); | 1993 | ieee80211_tx_status(hw, skb); |
@@ -1983,16 +1995,13 @@ static void ath_tx_complete(struct ath_softc *sc, struct sk_buff *skb, | |||
1983 | 1995 | ||
1984 | static void ath_tx_complete_buf(struct ath_softc *sc, struct ath_buf *bf, | 1996 | static void ath_tx_complete_buf(struct ath_softc *sc, struct ath_buf *bf, |
1985 | struct ath_txq *txq, struct list_head *bf_q, | 1997 | struct ath_txq *txq, struct list_head *bf_q, |
1986 | struct ath_tx_status *ts, int txok, int sendbar) | 1998 | struct ath_tx_status *ts, int txok) |
1987 | { | 1999 | { |
1988 | struct sk_buff *skb = bf->bf_mpdu; | 2000 | struct sk_buff *skb = bf->bf_mpdu; |
1989 | struct ieee80211_tx_info *tx_info = IEEE80211_SKB_CB(skb); | 2001 | struct ieee80211_tx_info *tx_info = IEEE80211_SKB_CB(skb); |
1990 | unsigned long flags; | 2002 | unsigned long flags; |
1991 | int tx_flags = 0; | 2003 | int tx_flags = 0; |
1992 | 2004 | ||
1993 | if (sendbar) | ||
1994 | tx_flags = ATH_TX_BAR; | ||
1995 | |||
1996 | if (!txok) | 2005 | if (!txok) |
1997 | tx_flags |= ATH_TX_ERROR; | 2006 | tx_flags |= ATH_TX_ERROR; |
1998 | 2007 | ||
@@ -2084,8 +2093,6 @@ static void ath_tx_rc_status(struct ath_softc *sc, struct ath_buf *bf, | |||
2084 | static void ath_tx_process_buffer(struct ath_softc *sc, struct ath_txq *txq, | 2093 | static void ath_tx_process_buffer(struct ath_softc *sc, struct ath_txq *txq, |
2085 | struct ath_tx_status *ts, struct ath_buf *bf, | 2094 | struct ath_tx_status *ts, struct ath_buf *bf, |
2086 | struct list_head *bf_head) | 2095 | struct list_head *bf_head) |
2087 | __releases(txq->axq_lock) | ||
2088 | __acquires(txq->axq_lock) | ||
2089 | { | 2096 | { |
2090 | int txok; | 2097 | int txok; |
2091 | 2098 | ||
@@ -2095,16 +2102,12 @@ static void ath_tx_process_buffer(struct ath_softc *sc, struct ath_txq *txq, | |||
2095 | if (bf_is_ampdu_not_probing(bf)) | 2102 | if (bf_is_ampdu_not_probing(bf)) |
2096 | txq->axq_ampdu_depth--; | 2103 | txq->axq_ampdu_depth--; |
2097 | 2104 | ||
2098 | spin_unlock_bh(&txq->axq_lock); | ||
2099 | |||
2100 | if (!bf_isampdu(bf)) { | 2105 | if (!bf_isampdu(bf)) { |
2101 | ath_tx_rc_status(sc, bf, ts, 1, txok ? 0 : 1, txok); | 2106 | ath_tx_rc_status(sc, bf, ts, 1, txok ? 0 : 1, txok); |
2102 | ath_tx_complete_buf(sc, bf, txq, bf_head, ts, txok, 0); | 2107 | ath_tx_complete_buf(sc, bf, txq, bf_head, ts, txok); |
2103 | } else | 2108 | } else |
2104 | ath_tx_complete_aggr(sc, txq, bf, bf_head, ts, txok, true); | 2109 | ath_tx_complete_aggr(sc, txq, bf, bf_head, ts, txok, true); |
2105 | 2110 | ||
2106 | spin_lock_bh(&txq->axq_lock); | ||
2107 | |||
2108 | if (sc->sc_flags & SC_OP_TXAGGR) | 2111 | if (sc->sc_flags & SC_OP_TXAGGR) |
2109 | ath_txq_schedule(sc, txq); | 2112 | ath_txq_schedule(sc, txq); |
2110 | } | 2113 | } |
diff --git a/drivers/net/wireless/ath/carl9170/fw.c b/drivers/net/wireless/ath/carl9170/fw.c index f4cae1cccbff..cba9d0435dc4 100644 --- a/drivers/net/wireless/ath/carl9170/fw.c +++ b/drivers/net/wireless/ath/carl9170/fw.c | |||
@@ -23,6 +23,7 @@ | |||
23 | #include <linux/kernel.h> | 23 | #include <linux/kernel.h> |
24 | #include <linux/firmware.h> | 24 | #include <linux/firmware.h> |
25 | #include <linux/crc32.h> | 25 | #include <linux/crc32.h> |
26 | #include <linux/module.h> | ||
26 | #include "carl9170.h" | 27 | #include "carl9170.h" |
27 | #include "fwcmd.h" | 28 | #include "fwcmd.h" |
28 | #include "version.h" | 29 | #include "version.h" |
diff --git a/drivers/net/wireless/ath/carl9170/tx.c b/drivers/net/wireless/ath/carl9170/tx.c index 59472e1605cd..d19a9ee9d057 100644 --- a/drivers/net/wireless/ath/carl9170/tx.c +++ b/drivers/net/wireless/ath/carl9170/tx.c | |||
@@ -314,7 +314,7 @@ static void carl9170_tx_release(struct kref *ref) | |||
314 | * feedback either [CTL_REQ_TX_STATUS not set] | 314 | * feedback either [CTL_REQ_TX_STATUS not set] |
315 | */ | 315 | */ |
316 | 316 | ||
317 | dev_kfree_skb_any(skb); | 317 | ieee80211_free_txskb(ar->hw, skb); |
318 | return; | 318 | return; |
319 | } else { | 319 | } else { |
320 | /* | 320 | /* |
@@ -1432,7 +1432,7 @@ void carl9170_op_tx(struct ieee80211_hw *hw, struct sk_buff *skb) | |||
1432 | 1432 | ||
1433 | err_free: | 1433 | err_free: |
1434 | ar->tx_dropped++; | 1434 | ar->tx_dropped++; |
1435 | dev_kfree_skb_any(skb); | 1435 | ieee80211_free_txskb(ar->hw, skb); |
1436 | } | 1436 | } |
1437 | 1437 | ||
1438 | void carl9170_tx_scheduler(struct ar9170 *ar) | 1438 | void carl9170_tx_scheduler(struct ar9170 *ar) |
diff --git a/drivers/net/wireless/ath/debug.c b/drivers/net/wireless/ath/debug.c index 5367b1086e09..508eccf5d982 100644 --- a/drivers/net/wireless/ath/debug.c +++ b/drivers/net/wireless/ath/debug.c | |||
@@ -14,6 +14,7 @@ | |||
14 | * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. | 14 | * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. |
15 | */ | 15 | */ |
16 | 16 | ||
17 | #include <linux/export.h> | ||
17 | #include "ath.h" | 18 | #include "ath.h" |
18 | 19 | ||
19 | const char *ath_opmode_to_string(enum nl80211_iftype opmode) | 20 | const char *ath_opmode_to_string(enum nl80211_iftype opmode) |
diff --git a/drivers/net/wireless/ath/hw.c b/drivers/net/wireless/ath/hw.c index 3f508e59f146..19befb331073 100644 --- a/drivers/net/wireless/ath/hw.c +++ b/drivers/net/wireless/ath/hw.c | |||
@@ -14,6 +14,7 @@ | |||
14 | * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. | 14 | * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. |
15 | */ | 15 | */ |
16 | 16 | ||
17 | #include <linux/export.h> | ||
17 | #include <asm/unaligned.h> | 18 | #include <asm/unaligned.h> |
18 | 19 | ||
19 | #include "ath.h" | 20 | #include "ath.h" |
diff --git a/drivers/net/wireless/ath/key.c b/drivers/net/wireless/ath/key.c index 17b0efd86f9a..4cf7c5eb4813 100644 --- a/drivers/net/wireless/ath/key.c +++ b/drivers/net/wireless/ath/key.c | |||
@@ -15,6 +15,7 @@ | |||
15 | * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. | 15 | * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. |
16 | */ | 16 | */ |
17 | 17 | ||
18 | #include <linux/export.h> | ||
18 | #include <asm/unaligned.h> | 19 | #include <asm/unaligned.h> |
19 | #include <net/mac80211.h> | 20 | #include <net/mac80211.h> |
20 | 21 | ||
diff --git a/drivers/net/wireless/ath/regd.c b/drivers/net/wireless/ath/regd.c index f1be57f0f5bb..10dea37431b3 100644 --- a/drivers/net/wireless/ath/regd.c +++ b/drivers/net/wireless/ath/regd.c | |||
@@ -15,11 +15,14 @@ | |||
15 | */ | 15 | */ |
16 | 16 | ||
17 | #include <linux/kernel.h> | 17 | #include <linux/kernel.h> |
18 | #include <linux/export.h> | ||
18 | #include <net/cfg80211.h> | 19 | #include <net/cfg80211.h> |
19 | #include <net/mac80211.h> | 20 | #include <net/mac80211.h> |
20 | #include "regd.h" | 21 | #include "regd.h" |
21 | #include "regd_common.h" | 22 | #include "regd_common.h" |
22 | 23 | ||
24 | static int __ath_regd_init(struct ath_regulatory *reg); | ||
25 | |||
23 | /* | 26 | /* |
24 | * This is a set of common rules used by our world regulatory domains. | 27 | * This is a set of common rules used by our world regulatory domains. |
25 | * We have 12 world regulatory domains. To save space we consolidate | 28 | * We have 12 world regulatory domains. To save space we consolidate |
@@ -346,10 +349,26 @@ static void ath_reg_apply_world_flags(struct wiphy *wiphy, | |||
346 | } | 349 | } |
347 | } | 350 | } |
348 | 351 | ||
352 | static u16 ath_regd_find_country_by_name(char *alpha2) | ||
353 | { | ||
354 | unsigned int i; | ||
355 | |||
356 | for (i = 0; i < ARRAY_SIZE(allCountries); i++) { | ||
357 | if (!memcmp(allCountries[i].isoName, alpha2, 2)) | ||
358 | return allCountries[i].countryCode; | ||
359 | } | ||
360 | |||
361 | return -1; | ||
362 | } | ||
363 | |||
349 | int ath_reg_notifier_apply(struct wiphy *wiphy, | 364 | int ath_reg_notifier_apply(struct wiphy *wiphy, |
350 | struct regulatory_request *request, | 365 | struct regulatory_request *request, |
351 | struct ath_regulatory *reg) | 366 | struct ath_regulatory *reg) |
352 | { | 367 | { |
368 | struct ath_common *common = container_of(reg, struct ath_common, | ||
369 | regulatory); | ||
370 | u16 country_code; | ||
371 | |||
353 | /* We always apply this */ | 372 | /* We always apply this */ |
354 | ath_reg_apply_radar_flags(wiphy); | 373 | ath_reg_apply_radar_flags(wiphy); |
355 | 374 | ||
@@ -362,14 +381,37 @@ int ath_reg_notifier_apply(struct wiphy *wiphy, | |||
362 | return 0; | 381 | return 0; |
363 | 382 | ||
364 | switch (request->initiator) { | 383 | switch (request->initiator) { |
365 | case NL80211_REGDOM_SET_BY_DRIVER: | ||
366 | case NL80211_REGDOM_SET_BY_CORE: | 384 | case NL80211_REGDOM_SET_BY_CORE: |
385 | /* | ||
386 | * If common->reg_world_copy is world roaming it means we *were* | ||
387 | * world roaming... so we now have to restore that data. | ||
388 | */ | ||
389 | if (!ath_is_world_regd(&common->reg_world_copy)) | ||
390 | break; | ||
391 | |||
392 | memcpy(reg, &common->reg_world_copy, | ||
393 | sizeof(struct ath_regulatory)); | ||
394 | break; | ||
395 | case NL80211_REGDOM_SET_BY_DRIVER: | ||
367 | case NL80211_REGDOM_SET_BY_USER: | 396 | case NL80211_REGDOM_SET_BY_USER: |
368 | break; | 397 | break; |
369 | case NL80211_REGDOM_SET_BY_COUNTRY_IE: | 398 | case NL80211_REGDOM_SET_BY_COUNTRY_IE: |
370 | if (ath_is_world_regd(reg)) | 399 | if (!ath_is_world_regd(reg)) |
371 | ath_reg_apply_world_flags(wiphy, request->initiator, | 400 | break; |
372 | reg); | 401 | |
402 | country_code = ath_regd_find_country_by_name(request->alpha2); | ||
403 | if (country_code == (u16) -1) | ||
404 | break; | ||
405 | |||
406 | reg->current_rd = COUNTRY_ERD_FLAG; | ||
407 | reg->current_rd |= country_code; | ||
408 | |||
409 | printk(KERN_DEBUG "ath: regdomain 0x%0x updated by CountryIE\n", | ||
410 | reg->current_rd); | ||
411 | __ath_regd_init(reg); | ||
412 | |||
413 | ath_reg_apply_world_flags(wiphy, request->initiator, reg); | ||
414 | |||
373 | break; | 415 | break; |
374 | } | 416 | } |
375 | 417 | ||
@@ -507,11 +549,7 @@ static void ath_regd_sanitize(struct ath_regulatory *reg) | |||
507 | reg->current_rd = 0x64; | 549 | reg->current_rd = 0x64; |
508 | } | 550 | } |
509 | 551 | ||
510 | int | 552 | static int __ath_regd_init(struct ath_regulatory *reg) |
511 | ath_regd_init(struct ath_regulatory *reg, | ||
512 | struct wiphy *wiphy, | ||
513 | int (*reg_notifier)(struct wiphy *wiphy, | ||
514 | struct regulatory_request *request)) | ||
515 | { | 553 | { |
516 | struct country_code_to_enum_rd *country = NULL; | 554 | struct country_code_to_enum_rd *country = NULL; |
517 | u16 regdmn; | 555 | u16 regdmn; |
@@ -582,7 +620,29 @@ ath_regd_init(struct ath_regulatory *reg, | |||
582 | printk(KERN_DEBUG "ath: Regpair used: 0x%0x\n", | 620 | printk(KERN_DEBUG "ath: Regpair used: 0x%0x\n", |
583 | reg->regpair->regDmnEnum); | 621 | reg->regpair->regDmnEnum); |
584 | 622 | ||
623 | return 0; | ||
624 | } | ||
625 | |||
626 | int | ||
627 | ath_regd_init(struct ath_regulatory *reg, | ||
628 | struct wiphy *wiphy, | ||
629 | int (*reg_notifier)(struct wiphy *wiphy, | ||
630 | struct regulatory_request *request)) | ||
631 | { | ||
632 | struct ath_common *common = container_of(reg, struct ath_common, | ||
633 | regulatory); | ||
634 | int r; | ||
635 | |||
636 | r = __ath_regd_init(reg); | ||
637 | if (r) | ||
638 | return r; | ||
639 | |||
640 | if (ath_is_world_regd(reg)) | ||
641 | memcpy(&common->reg_world_copy, reg, | ||
642 | sizeof(struct ath_regulatory)); | ||
643 | |||
585 | ath_regd_init_wiphy(reg, wiphy, reg_notifier); | 644 | ath_regd_init_wiphy(reg, wiphy, reg_notifier); |
645 | |||
586 | return 0; | 646 | return 0; |
587 | } | 647 | } |
588 | EXPORT_SYMBOL(ath_regd_init); | 648 | EXPORT_SYMBOL(ath_regd_init); |