diff options
Diffstat (limited to 'drivers/net/wireless/ath/ath5k/pcu.c')
-rw-r--r-- | drivers/net/wireless/ath/ath5k/pcu.c | 379 |
1 files changed, 54 insertions, 325 deletions
diff --git a/drivers/net/wireless/ath/ath5k/pcu.c b/drivers/net/wireless/ath/ath5k/pcu.c index aefe84f9c04b..5212e275f1c7 100644 --- a/drivers/net/wireless/ath/ath5k/pcu.c +++ b/drivers/net/wireless/ath/ath5k/pcu.c | |||
@@ -39,16 +39,16 @@ | |||
39 | * ath5k_hw_set_opmode - Set PCU operating mode | 39 | * ath5k_hw_set_opmode - Set PCU operating mode |
40 | * | 40 | * |
41 | * @ah: The &struct ath5k_hw | 41 | * @ah: The &struct ath5k_hw |
42 | * @op_mode: &enum nl80211_iftype operating mode | ||
42 | * | 43 | * |
43 | * Initialize PCU for the various operating modes (AP/STA etc) | 44 | * Initialize PCU for the various operating modes (AP/STA etc) |
44 | * | ||
45 | * NOTE: ah->ah_op_mode must be set before calling this. | ||
46 | */ | 45 | */ |
47 | int ath5k_hw_set_opmode(struct ath5k_hw *ah) | 46 | int ath5k_hw_set_opmode(struct ath5k_hw *ah, enum nl80211_iftype op_mode) |
48 | { | 47 | { |
49 | struct ath_common *common = ath5k_hw_common(ah); | 48 | struct ath_common *common = ath5k_hw_common(ah); |
50 | u32 pcu_reg, beacon_reg, low_id, high_id; | 49 | u32 pcu_reg, beacon_reg, low_id, high_id; |
51 | 50 | ||
51 | ATH5K_DBG(ah->ah_sc, ATH5K_DEBUG_MODE, "mode %d\n", op_mode); | ||
52 | 52 | ||
53 | /* Preserve rest settings */ | 53 | /* Preserve rest settings */ |
54 | pcu_reg = ath5k_hw_reg_read(ah, AR5K_STA_ID1) & 0xffff0000; | 54 | pcu_reg = ath5k_hw_reg_read(ah, AR5K_STA_ID1) & 0xffff0000; |
@@ -61,7 +61,7 @@ int ath5k_hw_set_opmode(struct ath5k_hw *ah) | |||
61 | 61 | ||
62 | ATH5K_TRACE(ah->ah_sc); | 62 | ATH5K_TRACE(ah->ah_sc); |
63 | 63 | ||
64 | switch (ah->ah_op_mode) { | 64 | switch (op_mode) { |
65 | case NL80211_IFTYPE_ADHOC: | 65 | case NL80211_IFTYPE_ADHOC: |
66 | pcu_reg |= AR5K_STA_ID1_ADHOC | AR5K_STA_ID1_KEYSRCH_MODE; | 66 | pcu_reg |= AR5K_STA_ID1_ADHOC | AR5K_STA_ID1_KEYSRCH_MODE; |
67 | beacon_reg |= AR5K_BCR_ADHOC; | 67 | beacon_reg |= AR5K_BCR_ADHOC; |
@@ -113,39 +113,26 @@ int ath5k_hw_set_opmode(struct ath5k_hw *ah) | |||
113 | } | 113 | } |
114 | 114 | ||
115 | /** | 115 | /** |
116 | * ath5k_hw_update - Update mib counters (mac layer statistics) | 116 | * ath5k_hw_update - Update MIB counters (mac layer statistics) |
117 | * | 117 | * |
118 | * @ah: The &struct ath5k_hw | 118 | * @ah: The &struct ath5k_hw |
119 | * @stats: The &struct ieee80211_low_level_stats we use to track | ||
120 | * statistics on the driver | ||
121 | * | 119 | * |
122 | * Reads MIB counters from PCU and updates sw statistics. Must be | 120 | * Reads MIB counters from PCU and updates sw statistics. Is called after a |
123 | * called after a MIB interrupt. | 121 | * MIB interrupt, because one of these counters might have reached their maximum |
122 | * and triggered the MIB interrupt, to let us read and clear the counter. | ||
123 | * | ||
124 | * Is called in interrupt context! | ||
124 | */ | 125 | */ |
125 | void ath5k_hw_update_mib_counters(struct ath5k_hw *ah, | 126 | void ath5k_hw_update_mib_counters(struct ath5k_hw *ah) |
126 | struct ieee80211_low_level_stats *stats) | ||
127 | { | 127 | { |
128 | ATH5K_TRACE(ah->ah_sc); | 128 | struct ath5k_statistics *stats = &ah->ah_sc->stats; |
129 | 129 | ||
130 | /* Read-And-Clear */ | 130 | /* Read-And-Clear */ |
131 | stats->dot11ACKFailureCount += ath5k_hw_reg_read(ah, AR5K_ACK_FAIL); | 131 | stats->ack_fail += ath5k_hw_reg_read(ah, AR5K_ACK_FAIL); |
132 | stats->dot11RTSFailureCount += ath5k_hw_reg_read(ah, AR5K_RTS_FAIL); | 132 | stats->rts_fail += ath5k_hw_reg_read(ah, AR5K_RTS_FAIL); |
133 | stats->dot11RTSSuccessCount += ath5k_hw_reg_read(ah, AR5K_RTS_OK); | 133 | stats->rts_ok += ath5k_hw_reg_read(ah, AR5K_RTS_OK); |
134 | stats->dot11FCSErrorCount += ath5k_hw_reg_read(ah, AR5K_FCS_FAIL); | 134 | stats->fcs_error += ath5k_hw_reg_read(ah, AR5K_FCS_FAIL); |
135 | 135 | stats->beacons += ath5k_hw_reg_read(ah, AR5K_BEACON_CNT); | |
136 | /* XXX: Should we use this to track beacon count ? | ||
137 | * -we read it anyway to clear the register */ | ||
138 | ath5k_hw_reg_read(ah, AR5K_BEACON_CNT); | ||
139 | |||
140 | /* Reset profile count registers on 5212*/ | ||
141 | if (ah->ah_version == AR5K_AR5212) { | ||
142 | ath5k_hw_reg_write(ah, 0, AR5K_PROFCNT_TX); | ||
143 | ath5k_hw_reg_write(ah, 0, AR5K_PROFCNT_RX); | ||
144 | ath5k_hw_reg_write(ah, 0, AR5K_PROFCNT_RXCLR); | ||
145 | ath5k_hw_reg_write(ah, 0, AR5K_PROFCNT_CYCLE); | ||
146 | } | ||
147 | |||
148 | /* TODO: Handle ANI stats */ | ||
149 | } | 136 | } |
150 | 137 | ||
151 | /** | 138 | /** |
@@ -167,9 +154,9 @@ void ath5k_hw_set_ack_bitrate_high(struct ath5k_hw *ah, bool high) | |||
167 | else { | 154 | else { |
168 | u32 val = AR5K_STA_ID1_BASE_RATE_11B | AR5K_STA_ID1_ACKCTS_6MB; | 155 | u32 val = AR5K_STA_ID1_BASE_RATE_11B | AR5K_STA_ID1_ACKCTS_6MB; |
169 | if (high) | 156 | if (high) |
170 | AR5K_REG_ENABLE_BITS(ah, AR5K_STA_ID1, val); | ||
171 | else | ||
172 | AR5K_REG_DISABLE_BITS(ah, AR5K_STA_ID1, val); | 157 | AR5K_REG_DISABLE_BITS(ah, AR5K_STA_ID1, val); |
158 | else | ||
159 | AR5K_REG_ENABLE_BITS(ah, AR5K_STA_ID1, val); | ||
173 | } | 160 | } |
174 | } | 161 | } |
175 | 162 | ||
@@ -179,25 +166,12 @@ void ath5k_hw_set_ack_bitrate_high(struct ath5k_hw *ah, bool high) | |||
179 | \******************/ | 166 | \******************/ |
180 | 167 | ||
181 | /** | 168 | /** |
182 | * ath5k_hw_het_ack_timeout - Get ACK timeout from PCU in usec | ||
183 | * | ||
184 | * @ah: The &struct ath5k_hw | ||
185 | */ | ||
186 | unsigned int ath5k_hw_get_ack_timeout(struct ath5k_hw *ah) | ||
187 | { | ||
188 | ATH5K_TRACE(ah->ah_sc); | ||
189 | |||
190 | return ath5k_hw_clocktoh(ah, AR5K_REG_MS(ath5k_hw_reg_read(ah, | ||
191 | AR5K_TIME_OUT), AR5K_TIME_OUT_ACK)); | ||
192 | } | ||
193 | |||
194 | /** | ||
195 | * ath5k_hw_set_ack_timeout - Set ACK timeout on PCU | 169 | * ath5k_hw_set_ack_timeout - Set ACK timeout on PCU |
196 | * | 170 | * |
197 | * @ah: The &struct ath5k_hw | 171 | * @ah: The &struct ath5k_hw |
198 | * @timeout: Timeout in usec | 172 | * @timeout: Timeout in usec |
199 | */ | 173 | */ |
200 | int ath5k_hw_set_ack_timeout(struct ath5k_hw *ah, unsigned int timeout) | 174 | static int ath5k_hw_set_ack_timeout(struct ath5k_hw *ah, unsigned int timeout) |
201 | { | 175 | { |
202 | ATH5K_TRACE(ah->ah_sc); | 176 | ATH5K_TRACE(ah->ah_sc); |
203 | if (ath5k_hw_clocktoh(ah, AR5K_REG_MS(0xffffffff, AR5K_TIME_OUT_ACK)) | 177 | if (ath5k_hw_clocktoh(ah, AR5K_REG_MS(0xffffffff, AR5K_TIME_OUT_ACK)) |
@@ -211,24 +185,12 @@ int ath5k_hw_set_ack_timeout(struct ath5k_hw *ah, unsigned int timeout) | |||
211 | } | 185 | } |
212 | 186 | ||
213 | /** | 187 | /** |
214 | * ath5k_hw_get_cts_timeout - Get CTS timeout from PCU in usec | ||
215 | * | ||
216 | * @ah: The &struct ath5k_hw | ||
217 | */ | ||
218 | unsigned int ath5k_hw_get_cts_timeout(struct ath5k_hw *ah) | ||
219 | { | ||
220 | ATH5K_TRACE(ah->ah_sc); | ||
221 | return ath5k_hw_clocktoh(ah, AR5K_REG_MS(ath5k_hw_reg_read(ah, | ||
222 | AR5K_TIME_OUT), AR5K_TIME_OUT_CTS)); | ||
223 | } | ||
224 | |||
225 | /** | ||
226 | * ath5k_hw_set_cts_timeout - Set CTS timeout on PCU | 188 | * ath5k_hw_set_cts_timeout - Set CTS timeout on PCU |
227 | * | 189 | * |
228 | * @ah: The &struct ath5k_hw | 190 | * @ah: The &struct ath5k_hw |
229 | * @timeout: Timeout in usec | 191 | * @timeout: Timeout in usec |
230 | */ | 192 | */ |
231 | int ath5k_hw_set_cts_timeout(struct ath5k_hw *ah, unsigned int timeout) | 193 | static int ath5k_hw_set_cts_timeout(struct ath5k_hw *ah, unsigned int timeout) |
232 | { | 194 | { |
233 | ATH5K_TRACE(ah->ah_sc); | 195 | ATH5K_TRACE(ah->ah_sc); |
234 | if (ath5k_hw_clocktoh(ah, AR5K_REG_MS(0xffffffff, AR5K_TIME_OUT_CTS)) | 196 | if (ath5k_hw_clocktoh(ah, AR5K_REG_MS(0xffffffff, AR5K_TIME_OUT_CTS)) |
@@ -290,7 +252,7 @@ unsigned int ath5k_hw_get_clockrate(struct ath5k_hw *ah) | |||
290 | * | 252 | * |
291 | * @ah: The &struct ath5k_hw | 253 | * @ah: The &struct ath5k_hw |
292 | */ | 254 | */ |
293 | unsigned int ath5k_hw_get_default_slottime(struct ath5k_hw *ah) | 255 | static unsigned int ath5k_hw_get_default_slottime(struct ath5k_hw *ah) |
294 | { | 256 | { |
295 | struct ieee80211_channel *channel = ah->ah_current_channel; | 257 | struct ieee80211_channel *channel = ah->ah_current_channel; |
296 | 258 | ||
@@ -308,7 +270,7 @@ unsigned int ath5k_hw_get_default_slottime(struct ath5k_hw *ah) | |||
308 | * | 270 | * |
309 | * @ah: The &struct ath5k_hw | 271 | * @ah: The &struct ath5k_hw |
310 | */ | 272 | */ |
311 | unsigned int ath5k_hw_get_default_sifs(struct ath5k_hw *ah) | 273 | static unsigned int ath5k_hw_get_default_sifs(struct ath5k_hw *ah) |
312 | { | 274 | { |
313 | struct ieee80211_channel *channel = ah->ah_current_channel; | 275 | struct ieee80211_channel *channel = ah->ah_current_channel; |
314 | 276 | ||
@@ -417,7 +379,6 @@ void ath5k_hw_set_bssid_mask(struct ath5k_hw *ah, const u8 *mask) | |||
417 | * (ACK etc). | 379 | * (ACK etc). |
418 | * | 380 | * |
419 | * NOTE: RX DMA should be already enabled using ath5k_hw_start_rx_dma | 381 | * NOTE: RX DMA should be already enabled using ath5k_hw_start_rx_dma |
420 | * TODO: Init ANI here | ||
421 | */ | 382 | */ |
422 | void ath5k_hw_start_rx_pcu(struct ath5k_hw *ah) | 383 | void ath5k_hw_start_rx_pcu(struct ath5k_hw *ah) |
423 | { | 384 | { |
@@ -451,42 +412,6 @@ void ath5k_hw_set_mcast_filter(struct ath5k_hw *ah, u32 filter0, u32 filter1) | |||
451 | ath5k_hw_reg_write(ah, filter1, AR5K_MCAST_FILTER1); | 412 | ath5k_hw_reg_write(ah, filter1, AR5K_MCAST_FILTER1); |
452 | } | 413 | } |
453 | 414 | ||
454 | /* | ||
455 | * Set multicast filter by index | ||
456 | */ | ||
457 | int ath5k_hw_set_mcast_filter_idx(struct ath5k_hw *ah, u32 index) | ||
458 | { | ||
459 | |||
460 | ATH5K_TRACE(ah->ah_sc); | ||
461 | if (index >= 64) | ||
462 | return -EINVAL; | ||
463 | else if (index >= 32) | ||
464 | AR5K_REG_ENABLE_BITS(ah, AR5K_MCAST_FILTER1, | ||
465 | (1 << (index - 32))); | ||
466 | else | ||
467 | AR5K_REG_ENABLE_BITS(ah, AR5K_MCAST_FILTER0, (1 << index)); | ||
468 | |||
469 | return 0; | ||
470 | } | ||
471 | |||
472 | /* | ||
473 | * Clear Multicast filter by index | ||
474 | */ | ||
475 | int ath5k_hw_clear_mcast_filter_idx(struct ath5k_hw *ah, u32 index) | ||
476 | { | ||
477 | |||
478 | ATH5K_TRACE(ah->ah_sc); | ||
479 | if (index >= 64) | ||
480 | return -EINVAL; | ||
481 | else if (index >= 32) | ||
482 | AR5K_REG_DISABLE_BITS(ah, AR5K_MCAST_FILTER1, | ||
483 | (1 << (index - 32))); | ||
484 | else | ||
485 | AR5K_REG_DISABLE_BITS(ah, AR5K_MCAST_FILTER0, (1 << index)); | ||
486 | |||
487 | return 0; | ||
488 | } | ||
489 | |||
490 | /** | 415 | /** |
491 | * ath5k_hw_get_rx_filter - Get current rx filter | 416 | * ath5k_hw_get_rx_filter - Get current rx filter |
492 | * | 417 | * |
@@ -571,18 +496,7 @@ void ath5k_hw_set_rx_filter(struct ath5k_hw *ah, u32 filter) | |||
571 | * Beacon control * | 496 | * Beacon control * |
572 | \****************/ | 497 | \****************/ |
573 | 498 | ||
574 | /** | 499 | #define ATH5K_MAX_TSF_READ 10 |
575 | * ath5k_hw_get_tsf32 - Get a 32bit TSF | ||
576 | * | ||
577 | * @ah: The &struct ath5k_hw | ||
578 | * | ||
579 | * Returns lower 32 bits of current TSF | ||
580 | */ | ||
581 | u32 ath5k_hw_get_tsf32(struct ath5k_hw *ah) | ||
582 | { | ||
583 | ATH5K_TRACE(ah->ah_sc); | ||
584 | return ath5k_hw_reg_read(ah, AR5K_TSF_L32); | ||
585 | } | ||
586 | 500 | ||
587 | /** | 501 | /** |
588 | * ath5k_hw_get_tsf64 - Get the full 64bit TSF | 502 | * ath5k_hw_get_tsf64 - Get the full 64bit TSF |
@@ -593,10 +507,35 @@ u32 ath5k_hw_get_tsf32(struct ath5k_hw *ah) | |||
593 | */ | 507 | */ |
594 | u64 ath5k_hw_get_tsf64(struct ath5k_hw *ah) | 508 | u64 ath5k_hw_get_tsf64(struct ath5k_hw *ah) |
595 | { | 509 | { |
596 | u64 tsf = ath5k_hw_reg_read(ah, AR5K_TSF_U32); | 510 | u32 tsf_lower, tsf_upper1, tsf_upper2; |
511 | int i; | ||
512 | |||
513 | /* | ||
514 | * While reading TSF upper and then lower part, the clock is still | ||
515 | * counting (or jumping in case of IBSS merge) so we might get | ||
516 | * inconsistent values. To avoid this, we read the upper part again | ||
517 | * and check it has not been changed. We make the hypothesis that a | ||
518 | * maximum of 3 changes can happens in a row (we use 10 as a safe | ||
519 | * value). | ||
520 | * | ||
521 | * Impact on performance is pretty small, since in most cases, only | ||
522 | * 3 register reads are needed. | ||
523 | */ | ||
524 | |||
525 | tsf_upper1 = ath5k_hw_reg_read(ah, AR5K_TSF_U32); | ||
526 | for (i = 0; i < ATH5K_MAX_TSF_READ; i++) { | ||
527 | tsf_lower = ath5k_hw_reg_read(ah, AR5K_TSF_L32); | ||
528 | tsf_upper2 = ath5k_hw_reg_read(ah, AR5K_TSF_U32); | ||
529 | if (tsf_upper2 == tsf_upper1) | ||
530 | break; | ||
531 | tsf_upper1 = tsf_upper2; | ||
532 | } | ||
533 | |||
534 | WARN_ON( i == ATH5K_MAX_TSF_READ ); | ||
535 | |||
597 | ATH5K_TRACE(ah->ah_sc); | 536 | ATH5K_TRACE(ah->ah_sc); |
598 | 537 | ||
599 | return ath5k_hw_reg_read(ah, AR5K_TSF_L32) | (tsf << 32); | 538 | return (((u64)tsf_upper1 << 32) | tsf_lower); |
600 | } | 539 | } |
601 | 540 | ||
602 | /** | 541 | /** |
@@ -651,7 +590,7 @@ void ath5k_hw_init_beacon(struct ath5k_hw *ah, u32 next_beacon, u32 interval) | |||
651 | /* | 590 | /* |
652 | * Set the additional timers by mode | 591 | * Set the additional timers by mode |
653 | */ | 592 | */ |
654 | switch (ah->ah_op_mode) { | 593 | switch (ah->ah_sc->opmode) { |
655 | case NL80211_IFTYPE_MONITOR: | 594 | case NL80211_IFTYPE_MONITOR: |
656 | case NL80211_IFTYPE_STATION: | 595 | case NL80211_IFTYPE_STATION: |
657 | /* In STA mode timer1 is used as next wakeup | 596 | /* In STA mode timer1 is used as next wakeup |
@@ -688,8 +627,8 @@ void ath5k_hw_init_beacon(struct ath5k_hw *ah, u32 next_beacon, u32 interval) | |||
688 | * Set the beacon register and enable all timers. | 627 | * Set the beacon register and enable all timers. |
689 | */ | 628 | */ |
690 | /* When in AP or Mesh Point mode zero timer0 to start TSF */ | 629 | /* When in AP or Mesh Point mode zero timer0 to start TSF */ |
691 | if (ah->ah_op_mode == NL80211_IFTYPE_AP || | 630 | if (ah->ah_sc->opmode == NL80211_IFTYPE_AP || |
692 | ah->ah_op_mode == NL80211_IFTYPE_MESH_POINT) | 631 | ah->ah_sc->opmode == NL80211_IFTYPE_MESH_POINT) |
693 | ath5k_hw_reg_write(ah, 0, AR5K_TIMER0); | 632 | ath5k_hw_reg_write(ah, 0, AR5K_TIMER0); |
694 | 633 | ||
695 | ath5k_hw_reg_write(ah, next_beacon, AR5K_TIMER0); | 634 | ath5k_hw_reg_write(ah, next_beacon, AR5K_TIMER0); |
@@ -722,203 +661,6 @@ void ath5k_hw_init_beacon(struct ath5k_hw *ah, u32 next_beacon, u32 interval) | |||
722 | 661 | ||
723 | } | 662 | } |
724 | 663 | ||
725 | #if 0 | ||
726 | /* | ||
727 | * Set beacon timers | ||
728 | */ | ||
729 | int ath5k_hw_set_beacon_timers(struct ath5k_hw *ah, | ||
730 | const struct ath5k_beacon_state *state) | ||
731 | { | ||
732 | u32 cfp_period, next_cfp, dtim, interval, next_beacon; | ||
733 | |||
734 | /* | ||
735 | * TODO: should be changed through *state | ||
736 | * review struct ath5k_beacon_state struct | ||
737 | * | ||
738 | * XXX: These are used for cfp period bellow, are they | ||
739 | * ok ? Is it O.K. for tsf here to be 0 or should we use | ||
740 | * get_tsf ? | ||
741 | */ | ||
742 | u32 dtim_count = 0; /* XXX */ | ||
743 | u32 cfp_count = 0; /* XXX */ | ||
744 | u32 tsf = 0; /* XXX */ | ||
745 | |||
746 | ATH5K_TRACE(ah->ah_sc); | ||
747 | /* Return on an invalid beacon state */ | ||
748 | if (state->bs_interval < 1) | ||
749 | return -EINVAL; | ||
750 | |||
751 | interval = state->bs_interval; | ||
752 | dtim = state->bs_dtim_period; | ||
753 | |||
754 | /* | ||
755 | * PCF support? | ||
756 | */ | ||
757 | if (state->bs_cfp_period > 0) { | ||
758 | /* | ||
759 | * Enable PCF mode and set the CFP | ||
760 | * (Contention Free Period) and timer registers | ||
761 | */ | ||
762 | cfp_period = state->bs_cfp_period * state->bs_dtim_period * | ||
763 | state->bs_interval; | ||
764 | next_cfp = (cfp_count * state->bs_dtim_period + dtim_count) * | ||
765 | state->bs_interval; | ||
766 | |||
767 | AR5K_REG_ENABLE_BITS(ah, AR5K_STA_ID1, | ||
768 | AR5K_STA_ID1_DEFAULT_ANTENNA | | ||
769 | AR5K_STA_ID1_PCF); | ||
770 | ath5k_hw_reg_write(ah, cfp_period, AR5K_CFP_PERIOD); | ||
771 | ath5k_hw_reg_write(ah, state->bs_cfp_max_duration, | ||
772 | AR5K_CFP_DUR); | ||
773 | ath5k_hw_reg_write(ah, (tsf + (next_cfp == 0 ? cfp_period : | ||
774 | next_cfp)) << 3, AR5K_TIMER2); | ||
775 | } else { | ||
776 | /* Disable PCF mode */ | ||
777 | AR5K_REG_DISABLE_BITS(ah, AR5K_STA_ID1, | ||
778 | AR5K_STA_ID1_DEFAULT_ANTENNA | | ||
779 | AR5K_STA_ID1_PCF); | ||
780 | } | ||
781 | |||
782 | /* | ||
783 | * Enable the beacon timer register | ||
784 | */ | ||
785 | ath5k_hw_reg_write(ah, state->bs_next_beacon, AR5K_TIMER0); | ||
786 | |||
787 | /* | ||
788 | * Start the beacon timers | ||
789 | */ | ||
790 | ath5k_hw_reg_write(ah, (ath5k_hw_reg_read(ah, AR5K_BEACON) & | ||
791 | ~(AR5K_BEACON_PERIOD | AR5K_BEACON_TIM)) | | ||
792 | AR5K_REG_SM(state->bs_tim_offset ? state->bs_tim_offset + 4 : 0, | ||
793 | AR5K_BEACON_TIM) | AR5K_REG_SM(state->bs_interval, | ||
794 | AR5K_BEACON_PERIOD), AR5K_BEACON); | ||
795 | |||
796 | /* | ||
797 | * Write new beacon miss threshold, if it appears to be valid | ||
798 | * XXX: Figure out right values for min <= bs_bmiss_threshold <= max | ||
799 | * and return if its not in range. We can test this by reading value and | ||
800 | * setting value to a largest value and seeing which values register. | ||
801 | */ | ||
802 | |||
803 | AR5K_REG_WRITE_BITS(ah, AR5K_RSSI_THR, AR5K_RSSI_THR_BMISS, | ||
804 | state->bs_bmiss_threshold); | ||
805 | |||
806 | /* | ||
807 | * Set sleep control register | ||
808 | * XXX: Didn't find this in 5210 code but since this register | ||
809 | * exists also in ar5k's 5210 headers i leave it as common code. | ||
810 | */ | ||
811 | AR5K_REG_WRITE_BITS(ah, AR5K_SLEEP_CTL, AR5K_SLEEP_CTL_SLDUR, | ||
812 | (state->bs_sleep_duration - 3) << 3); | ||
813 | |||
814 | /* | ||
815 | * Set enhanced sleep registers on 5212 | ||
816 | */ | ||
817 | if (ah->ah_version == AR5K_AR5212) { | ||
818 | if (state->bs_sleep_duration > state->bs_interval && | ||
819 | roundup(state->bs_sleep_duration, interval) == | ||
820 | state->bs_sleep_duration) | ||
821 | interval = state->bs_sleep_duration; | ||
822 | |||
823 | if (state->bs_sleep_duration > dtim && (dtim == 0 || | ||
824 | roundup(state->bs_sleep_duration, dtim) == | ||
825 | state->bs_sleep_duration)) | ||
826 | dtim = state->bs_sleep_duration; | ||
827 | |||
828 | if (interval > dtim) | ||
829 | return -EINVAL; | ||
830 | |||
831 | next_beacon = interval == dtim ? state->bs_next_dtim : | ||
832 | state->bs_next_beacon; | ||
833 | |||
834 | ath5k_hw_reg_write(ah, | ||
835 | AR5K_REG_SM((state->bs_next_dtim - 3) << 3, | ||
836 | AR5K_SLEEP0_NEXT_DTIM) | | ||
837 | AR5K_REG_SM(10, AR5K_SLEEP0_CABTO) | | ||
838 | AR5K_SLEEP0_ENH_SLEEP_EN | | ||
839 | AR5K_SLEEP0_ASSUME_DTIM, AR5K_SLEEP0); | ||
840 | |||
841 | ath5k_hw_reg_write(ah, AR5K_REG_SM((next_beacon - 3) << 3, | ||
842 | AR5K_SLEEP1_NEXT_TIM) | | ||
843 | AR5K_REG_SM(10, AR5K_SLEEP1_BEACON_TO), AR5K_SLEEP1); | ||
844 | |||
845 | ath5k_hw_reg_write(ah, | ||
846 | AR5K_REG_SM(interval, AR5K_SLEEP2_TIM_PER) | | ||
847 | AR5K_REG_SM(dtim, AR5K_SLEEP2_DTIM_PER), AR5K_SLEEP2); | ||
848 | } | ||
849 | |||
850 | return 0; | ||
851 | } | ||
852 | |||
853 | /* | ||
854 | * Reset beacon timers | ||
855 | */ | ||
856 | void ath5k_hw_reset_beacon(struct ath5k_hw *ah) | ||
857 | { | ||
858 | ATH5K_TRACE(ah->ah_sc); | ||
859 | /* | ||
860 | * Disable beacon timer | ||
861 | */ | ||
862 | ath5k_hw_reg_write(ah, 0, AR5K_TIMER0); | ||
863 | |||
864 | /* | ||
865 | * Disable some beacon register values | ||
866 | */ | ||
867 | AR5K_REG_DISABLE_BITS(ah, AR5K_STA_ID1, | ||
868 | AR5K_STA_ID1_DEFAULT_ANTENNA | AR5K_STA_ID1_PCF); | ||
869 | ath5k_hw_reg_write(ah, AR5K_BEACON_PERIOD, AR5K_BEACON); | ||
870 | } | ||
871 | |||
872 | /* | ||
873 | * Wait for beacon queue to finish | ||
874 | */ | ||
875 | int ath5k_hw_beaconq_finish(struct ath5k_hw *ah, unsigned long phys_addr) | ||
876 | { | ||
877 | unsigned int i; | ||
878 | int ret; | ||
879 | |||
880 | ATH5K_TRACE(ah->ah_sc); | ||
881 | |||
882 | /* 5210 doesn't have QCU*/ | ||
883 | if (ah->ah_version == AR5K_AR5210) { | ||
884 | /* | ||
885 | * Wait for beaconn queue to finish by checking | ||
886 | * Control Register and Beacon Status Register. | ||
887 | */ | ||
888 | for (i = AR5K_TUNE_BEACON_INTERVAL / 2; i > 0; i--) { | ||
889 | if (!(ath5k_hw_reg_read(ah, AR5K_BSR) & AR5K_BSR_TXQ1F) | ||
890 | || | ||
891 | !(ath5k_hw_reg_read(ah, AR5K_CR) & AR5K_BSR_TXQ1F)) | ||
892 | break; | ||
893 | udelay(10); | ||
894 | } | ||
895 | |||
896 | /* Timeout... */ | ||
897 | if (i <= 0) { | ||
898 | /* | ||
899 | * Re-schedule the beacon queue | ||
900 | */ | ||
901 | ath5k_hw_reg_write(ah, phys_addr, AR5K_NOQCU_TXDP1); | ||
902 | ath5k_hw_reg_write(ah, AR5K_BCR_TQ1V | AR5K_BCR_BDMAE, | ||
903 | AR5K_BCR); | ||
904 | |||
905 | return -EIO; | ||
906 | } | ||
907 | ret = 0; | ||
908 | } else { | ||
909 | /*5211/5212*/ | ||
910 | ret = ath5k_hw_register_timeout(ah, | ||
911 | AR5K_QUEUE_STATUS(AR5K_TX_QUEUE_ID_BEACON), | ||
912 | AR5K_QCU_STS_FRMPENDCNT, 0, false); | ||
913 | |||
914 | if (AR5K_REG_READ_Q(ah, AR5K_QCU_TXE, AR5K_TX_QUEUE_ID_BEACON)) | ||
915 | return -EIO; | ||
916 | } | ||
917 | |||
918 | return ret; | ||
919 | } | ||
920 | #endif | ||
921 | |||
922 | 664 | ||
923 | /*********************\ | 665 | /*********************\ |
924 | * Key table functions * | 666 | * Key table functions * |
@@ -971,19 +713,6 @@ int ath5k_hw_reset_key(struct ath5k_hw *ah, u16 entry) | |||
971 | return 0; | 713 | return 0; |
972 | } | 714 | } |
973 | 715 | ||
974 | /* | ||
975 | * Check if a table entry is valid | ||
976 | */ | ||
977 | int ath5k_hw_is_key_valid(struct ath5k_hw *ah, u16 entry) | ||
978 | { | ||
979 | ATH5K_TRACE(ah->ah_sc); | ||
980 | AR5K_ASSERT_ENTRY(entry, AR5K_KEYTABLE_SIZE); | ||
981 | |||
982 | /* Check the validation flag at the end of the entry */ | ||
983 | return ath5k_hw_reg_read(ah, AR5K_KEYTABLE_MAC1(entry)) & | ||
984 | AR5K_KEYTABLE_VALID; | ||
985 | } | ||
986 | |||
987 | static | 716 | static |
988 | int ath5k_keycache_type(const struct ieee80211_key_conf *key) | 717 | int ath5k_keycache_type(const struct ieee80211_key_conf *key) |
989 | { | 718 | { |