aboutsummaryrefslogtreecommitdiffstats
path: root/drivers
diff options
context:
space:
mode:
authorBruno Randolf <br1@einfach.org>2010-12-16 02:22:20 -0500
committerJohn W. Linville <linville@tuxdriver.com>2010-12-16 15:22:32 -0500
commitf15a4bb2637253680f09f0161d51e22446b6478f (patch)
treee3209fb59e2c7204f7d7dc74b8f3434bbd361e6a /drivers
parent4aea248dd7a67097d683a97f94a0aeaf0d248f3f (diff)
ath5k: Fix survey
The old survey implementation was broken and returned nonsense data. Clear cycle counters and survey data on reset. Since the cycle counters easily overflow it's better to keep a local version of collected survey data (in ms resolution, instead of clockrate) and update this every time survey is retrieved. If survey is retrieved often enough to avoid cycle counter overflows this works fine, otherwise we could update survey more often, like ath9k does. Still only the survey for the current channel is kept. Signed-off-by: Bruno Randolf <br1@einfach.org> Signed-off-by: John W. Linville <linville@tuxdriver.com>
Diffstat (limited to 'drivers')
-rw-r--r--drivers/net/wireless/ath/ath5k/base.c35
-rw-r--r--drivers/net/wireless/ath/ath5k/base.h2
2 files changed, 25 insertions, 12 deletions
diff --git a/drivers/net/wireless/ath/ath5k/base.c b/drivers/net/wireless/ath/ath5k/base.c
index 4e3b97c3d7c2..b3c7241a62a5 100644
--- a/drivers/net/wireless/ath/ath5k/base.c
+++ b/drivers/net/wireless/ath/ath5k/base.c
@@ -2654,6 +2654,7 @@ ath5k_reset(struct ath5k_softc *sc, struct ieee80211_channel *chan,
2654 bool skip_pcu) 2654 bool skip_pcu)
2655{ 2655{
2656 struct ath5k_hw *ah = sc->ah; 2656 struct ath5k_hw *ah = sc->ah;
2657 struct ath_common *common = ath5k_hw_common(ah);
2657 int ret, ani_mode; 2658 int ret, ani_mode;
2658 2659
2659 ATH5K_DBG(sc, ATH5K_DEBUG_RESET, "resetting\n"); 2660 ATH5K_DBG(sc, ATH5K_DEBUG_RESET, "resetting\n");
@@ -2696,6 +2697,14 @@ ath5k_reset(struct ath5k_softc *sc, struct ieee80211_channel *chan,
2696 ah->ah_cal_next_nf = jiffies; 2697 ah->ah_cal_next_nf = jiffies;
2697 ewma_init(&ah->ah_beacon_rssi_avg, 1024, 8); 2698 ewma_init(&ah->ah_beacon_rssi_avg, 1024, 8);
2698 2699
2700 /* clear survey data and cycle counters */
2701 memset(&sc->survey, 0, sizeof(sc->survey));
2702 spin_lock(&common->cc_lock);
2703 ath_hw_cycle_counters_update(common);
2704 memset(&common->cc_survey, 0, sizeof(common->cc_survey));
2705 memset(&common->cc_ani, 0, sizeof(common->cc_ani));
2706 spin_unlock(&common->cc_lock);
2707
2699 /* 2708 /*
2700 * Change channels and update the h/w rate map if we're switching; 2709 * Change channels and update the h/w rate map if we're switching;
2701 * e.g. 11a to 11b/g. 2710 * e.g. 11a to 11b/g.
@@ -3362,25 +3371,27 @@ static int ath5k_get_survey(struct ieee80211_hw *hw, int idx,
3362 if (idx != 0) 3371 if (idx != 0)
3363 return -ENOENT; 3372 return -ENOENT;
3364 3373
3365 survey->channel = conf->channel;
3366 survey->filled = SURVEY_INFO_NOISE_DBM;
3367 survey->noise = sc->ah->ah_noise_floor;
3368
3369 spin_lock_bh(&common->cc_lock); 3374 spin_lock_bh(&common->cc_lock);
3370 ath_hw_cycle_counters_update(common); 3375 ath_hw_cycle_counters_update(common);
3371 if (cc->cycles > 0) { 3376 if (cc->cycles > 0) {
3372 survey->filled |= SURVEY_INFO_CHANNEL_TIME | 3377 sc->survey.channel_time += cc->cycles / div;
3373 SURVEY_INFO_CHANNEL_TIME_BUSY | 3378 sc->survey.channel_time_busy += cc->rx_busy / div;
3374 SURVEY_INFO_CHANNEL_TIME_RX | 3379 sc->survey.channel_time_rx += cc->rx_frame / div;
3375 SURVEY_INFO_CHANNEL_TIME_TX; 3380 sc->survey.channel_time_tx += cc->tx_frame / div;
3376 survey->channel_time += cc->cycles / div;
3377 survey->channel_time_busy += cc->rx_busy / div;
3378 survey->channel_time_rx += cc->rx_frame / div;
3379 survey->channel_time_tx += cc->tx_frame / div;
3380 } 3381 }
3381 memset(cc, 0, sizeof(*cc)); 3382 memset(cc, 0, sizeof(*cc));
3382 spin_unlock_bh(&common->cc_lock); 3383 spin_unlock_bh(&common->cc_lock);
3383 3384
3385 memcpy(survey, &sc->survey, sizeof(*survey));
3386
3387 survey->channel = conf->channel;
3388 survey->noise = sc->ah->ah_noise_floor;
3389 survey->filled = SURVEY_INFO_NOISE_DBM |
3390 SURVEY_INFO_CHANNEL_TIME |
3391 SURVEY_INFO_CHANNEL_TIME_BUSY |
3392 SURVEY_INFO_CHANNEL_TIME_RX |
3393 SURVEY_INFO_CHANNEL_TIME_TX;
3394
3384 return 0; 3395 return 0;
3385} 3396}
3386 3397
diff --git a/drivers/net/wireless/ath/ath5k/base.h b/drivers/net/wireless/ath/ath5k/base.h
index aa6c32aafb59..6d511476e4d2 100644
--- a/drivers/net/wireless/ath/ath5k/base.h
+++ b/drivers/net/wireless/ath/ath5k/base.h
@@ -258,6 +258,8 @@ struct ath5k_softc {
258 struct tasklet_struct ani_tasklet; /* ANI calibration */ 258 struct tasklet_struct ani_tasklet; /* ANI calibration */
259 259
260 struct delayed_work tx_complete_work; 260 struct delayed_work tx_complete_work;
261
262 struct survey_info survey; /* collected survey info */
261}; 263};
262 264
263#define ath5k_hw_hasbssidmask(_ah) \ 265#define ath5k_hw_hasbssidmask(_ah) \