aboutsummaryrefslogtreecommitdiffstats
path: root/drivers/net/wireless/ath/ath5k
diff options
context:
space:
mode:
authorJohn W. Linville <linville@tuxdriver.com>2010-04-23 14:43:45 -0400
committerJohn W. Linville <linville@tuxdriver.com>2010-04-23 14:43:45 -0400
commit3b51cc996e81d8a113416d8094fa4a88f8360a51 (patch)
treee75b98b228bb4e456c30673fcc4b56ffa1d09cf5 /drivers/net/wireless/ath/ath5k
parentc68ed255265968c3948fa2678bf59d15c471b055 (diff)
parent672724403b42da1d276c6cf811e8e34d15efd964 (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.c19
-rw-r--r--drivers/net/wireless/ath/ath5k/pcu.c31
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);
243static int ath5k_get_stats(struct ieee80211_hw *hw, 243static int ath5k_get_stats(struct ieee80211_hw *hw,
244 struct ieee80211_low_level_stats *stats); 244 struct ieee80211_low_level_stats *stats);
245static int ath5k_get_survey(struct ieee80211_hw *hw,
246 int idx, struct survey_info *survey);
245static u64 ath5k_get_tsf(struct ieee80211_hw *hw); 247static u64 ath5k_get_tsf(struct ieee80211_hw *hw);
246static void ath5k_set_tsf(struct ieee80211_hw *hw, u64 tsf); 248static void ath5k_set_tsf(struct ieee80211_hw *hw, u64 tsf);
247static void ath5k_reset_tsf(struct ieee80211_hw *hw); 249static 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
3298static 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
3295static u64 3314static u64
3296ath5k_get_tsf(struct ieee80211_hw *hw) 3315ath5k_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 */
506u64 ath5k_hw_get_tsf64(struct ath5k_hw *ah) 508u64 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/**