diff options
author | John W. Linville <linville@tuxdriver.com> | 2010-04-23 14:43:45 -0400 |
---|---|---|
committer | John W. Linville <linville@tuxdriver.com> | 2010-04-23 14:43:45 -0400 |
commit | 3b51cc996e81d8a113416d8094fa4a88f8360a51 (patch) | |
tree | e75b98b228bb4e456c30673fcc4b56ffa1d09cf5 /drivers/net/wireless/ath/ath5k | |
parent | c68ed255265968c3948fa2678bf59d15c471b055 (diff) | |
parent | 672724403b42da1d276c6cf811e8e34d15efd964 (diff) |
Merge branch 'master' into for-davem
Conflicts:
drivers/net/wireless/ath/ath9k/phy.c
drivers/net/wireless/iwlwifi/iwl-6000.c
drivers/net/wireless/iwlwifi/iwl-debugfs.c
Diffstat (limited to 'drivers/net/wireless/ath/ath5k')
-rw-r--r-- | drivers/net/wireless/ath/ath5k/base.c | 19 | ||||
-rw-r--r-- | drivers/net/wireless/ath/ath5k/pcu.c | 31 |
2 files changed, 48 insertions, 2 deletions
diff --git a/drivers/net/wireless/ath/ath5k/base.c b/drivers/net/wireless/ath/ath5k/base.c index 93005f1d326d..c274979ada3a 100644 --- a/drivers/net/wireless/ath/ath5k/base.c +++ b/drivers/net/wireless/ath/ath5k/base.c | |||
@@ -242,6 +242,8 @@ static int ath5k_set_key(struct ieee80211_hw *hw, | |||
242 | struct ieee80211_key_conf *key); | 242 | struct ieee80211_key_conf *key); |
243 | static int ath5k_get_stats(struct ieee80211_hw *hw, | 243 | static int ath5k_get_stats(struct ieee80211_hw *hw, |
244 | struct ieee80211_low_level_stats *stats); | 244 | struct ieee80211_low_level_stats *stats); |
245 | static int ath5k_get_survey(struct ieee80211_hw *hw, | ||
246 | int idx, struct survey_info *survey); | ||
245 | static u64 ath5k_get_tsf(struct ieee80211_hw *hw); | 247 | static u64 ath5k_get_tsf(struct ieee80211_hw *hw); |
246 | static void ath5k_set_tsf(struct ieee80211_hw *hw, u64 tsf); | 248 | static void ath5k_set_tsf(struct ieee80211_hw *hw, u64 tsf); |
247 | static void ath5k_reset_tsf(struct ieee80211_hw *hw); | 249 | static void ath5k_reset_tsf(struct ieee80211_hw *hw); |
@@ -267,6 +269,7 @@ static const struct ieee80211_ops ath5k_hw_ops = { | |||
267 | .configure_filter = ath5k_configure_filter, | 269 | .configure_filter = ath5k_configure_filter, |
268 | .set_key = ath5k_set_key, | 270 | .set_key = ath5k_set_key, |
269 | .get_stats = ath5k_get_stats, | 271 | .get_stats = ath5k_get_stats, |
272 | .get_survey = ath5k_get_survey, | ||
270 | .conf_tx = NULL, | 273 | .conf_tx = NULL, |
271 | .get_tsf = ath5k_get_tsf, | 274 | .get_tsf = ath5k_get_tsf, |
272 | .set_tsf = ath5k_set_tsf, | 275 | .set_tsf = ath5k_set_tsf, |
@@ -3292,6 +3295,22 @@ ath5k_get_stats(struct ieee80211_hw *hw, | |||
3292 | return 0; | 3295 | return 0; |
3293 | } | 3296 | } |
3294 | 3297 | ||
3298 | static int ath5k_get_survey(struct ieee80211_hw *hw, int idx, | ||
3299 | struct survey_info *survey) | ||
3300 | { | ||
3301 | struct ath5k_softc *sc = hw->priv; | ||
3302 | struct ieee80211_conf *conf = &hw->conf; | ||
3303 | |||
3304 | if (idx != 0) | ||
3305 | return -ENOENT; | ||
3306 | |||
3307 | survey->channel = conf->channel; | ||
3308 | survey->filled = SURVEY_INFO_NOISE_DBM; | ||
3309 | survey->noise = sc->ah->ah_noise_floor; | ||
3310 | |||
3311 | return 0; | ||
3312 | } | ||
3313 | |||
3295 | static u64 | 3314 | static u64 |
3296 | ath5k_get_tsf(struct ieee80211_hw *hw) | 3315 | ath5k_get_tsf(struct ieee80211_hw *hw) |
3297 | { | 3316 | { |
diff --git a/drivers/net/wireless/ath/ath5k/pcu.c b/drivers/net/wireless/ath/ath5k/pcu.c index 174412fc81f8..5212e275f1c7 100644 --- a/drivers/net/wireless/ath/ath5k/pcu.c +++ b/drivers/net/wireless/ath/ath5k/pcu.c | |||
@@ -496,6 +496,8 @@ void ath5k_hw_set_rx_filter(struct ath5k_hw *ah, u32 filter) | |||
496 | * Beacon control * | 496 | * Beacon control * |
497 | \****************/ | 497 | \****************/ |
498 | 498 | ||
499 | #define ATH5K_MAX_TSF_READ 10 | ||
500 | |||
499 | /** | 501 | /** |
500 | * ath5k_hw_get_tsf64 - Get the full 64bit TSF | 502 | * ath5k_hw_get_tsf64 - Get the full 64bit TSF |
501 | * | 503 | * |
@@ -505,10 +507,35 @@ void ath5k_hw_set_rx_filter(struct ath5k_hw *ah, u32 filter) | |||
505 | */ | 507 | */ |
506 | u64 ath5k_hw_get_tsf64(struct ath5k_hw *ah) | 508 | u64 ath5k_hw_get_tsf64(struct ath5k_hw *ah) |
507 | { | 509 | { |
508 | 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 | |||
509 | ATH5K_TRACE(ah->ah_sc); | 536 | ATH5K_TRACE(ah->ah_sc); |
510 | 537 | ||
511 | return ath5k_hw_reg_read(ah, AR5K_TSF_L32) | (tsf << 32); | 538 | return (((u64)tsf_upper1 << 32) | tsf_lower); |
512 | } | 539 | } |
513 | 540 | ||
514 | /** | 541 | /** |