* [PATCH 1/3] cfg80211: add channel utilization stats to the survey command
@ 2010-10-09 0:39 Felix Fietkau
2010-10-09 0:39 ` [PATCH 2/3] ath9k: add compile time checking for the size of the channel list Felix Fietkau
2010-10-09 12:17 ` [PATCH 1/3] cfg80211: add channel utilization stats to the survey command Helmut Schaa
0 siblings, 2 replies; 9+ messages in thread
From: Felix Fietkau @ 2010-10-09 0:39 UTC (permalink / raw)
To: linux-wireless, linville; +Cc: lrodriguez, br1
Using these, user space can calculate a relative channel utilization
with arbitrary intervals by regularly taking snapshots of the survey
results.
Signed-off-by: Felix Fietkau <nbd@openwrt.org>
---
include/linux/nl80211.h | 15 +++++++++++++++
include/net/cfg80211.h | 20 ++++++++++++++++++++
net/wireless/nl80211.c | 15 +++++++++++++++
3 files changed, 50 insertions(+), 0 deletions(-)
diff --git a/include/linux/nl80211.h b/include/linux/nl80211.h
index c08709f..0edb256 100644
--- a/include/linux/nl80211.h
+++ b/include/linux/nl80211.h
@@ -1413,6 +1413,16 @@ enum nl80211_reg_rule_flags {
* @NL80211_SURVEY_INFO_FREQUENCY: center frequency of channel
* @NL80211_SURVEY_INFO_NOISE: noise level of channel (u8, dBm)
* @NL80211_SURVEY_INFO_IN_USE: channel is currently being used
+ * @NL80211_SURVEY_INFO_CHANNEL_TIME: amount of time (in ms) that the radio
+ * spent on this channel
+ * @NL80211_SURVEY_INFO_CHANNEL_TIME_BUSY: amount of the time the primary
+ * channel was sensed busy (either due to activity or energy detect)
+ * @NL80211_SURVEY_INFO_CHANNEL_TIME_EXT_BUSY: amount of time the extension
+ * channel was sensed busy
+ * @NL80211_SURVEY_INFO_CHANNEL_TIME_RX: amount of time the radio spent
+ * receiving data
+ * @NL80211_SURVEY_INFO_CHANNEL_TIME_TX: amount of time the radio spent
+ * transmitting data
* @NL80211_SURVEY_INFO_MAX: highest survey info attribute number
* currently defined
* @__NL80211_SURVEY_INFO_AFTER_LAST: internal use
@@ -1422,6 +1432,11 @@ enum nl80211_survey_info {
NL80211_SURVEY_INFO_FREQUENCY,
NL80211_SURVEY_INFO_NOISE,
NL80211_SURVEY_INFO_IN_USE,
+ NL80211_SURVEY_INFO_CHANNEL_TIME,
+ NL80211_SURVEY_INFO_CHANNEL_TIME_BUSY,
+ NL80211_SURVEY_INFO_CHANNEL_TIME_EXT_BUSY,
+ NL80211_SURVEY_INFO_CHANNEL_TIME_RX,
+ NL80211_SURVEY_INFO_CHANNEL_TIME_TX,
/* keep last */
__NL80211_SURVEY_INFO_AFTER_LAST,
diff --git a/include/net/cfg80211.h b/include/net/cfg80211.h
index 0778d04..a2cf04f 100644
--- a/include/net/cfg80211.h
+++ b/include/net/cfg80211.h
@@ -294,6 +294,11 @@ struct key_params {
*
* @SURVEY_INFO_NOISE_DBM: noise (in dBm) was filled in
* @SURVEY_INFO_IN_USE: channel is currently being used
+ * @SURVEY_INFO_CHANNEL_TIME: channel active time (in ms) was filled in
+ * @SURVEY_INFO_CHANNEL_TIME_BUSY: channel busy time was filled in
+ * @SURVEY_INFO_CHANNEL_TIME_EXT_BUSY: extension channel busy time was filled in
+ * @SURVEY_INFO_CHANNEL_TIME_RX: channel receive time was filled in
+ * @SURVEY_INFO_CHANNEL_TIME_TX: channel transmit time was filled in
*
* Used by the driver to indicate which info in &struct survey_info
* it has filled in during the get_survey().
@@ -301,6 +306,11 @@ struct key_params {
enum survey_info_flags {
SURVEY_INFO_NOISE_DBM = 1<<0,
SURVEY_INFO_IN_USE = 1<<1,
+ SURVEY_INFO_CHANNEL_TIME = 1<<2,
+ SURVEY_INFO_CHANNEL_TIME_BUSY = 1<<3,
+ SURVEY_INFO_CHANNEL_TIME_EXT_BUSY = 1<<4,
+ SURVEY_INFO_CHANNEL_TIME_RX = 1<<5,
+ SURVEY_INFO_CHANNEL_TIME_TX = 1<<6,
};
/**
@@ -310,6 +320,11 @@ enum survey_info_flags {
* @filled: bitflag of flags from &enum survey_info_flags
* @noise: channel noise in dBm. This and all following fields are
* optional
+ * @channel_time: amount of time in ms the radio spent on the channel
+ * @channel_time_busy: amount of time the primary channel was sensed busy
+ * @channel_time_ext_busy: amount of time the extension channel was sensed busy
+ * @channel_time_rx: amount of time the radio spent receiving data
+ * @channel_time_tx: amount of time the radio spent transmitting data
*
* Used by dump_survey() to report back per-channel survey information.
*
@@ -318,6 +333,11 @@ enum survey_info_flags {
*/
struct survey_info {
struct ieee80211_channel *channel;
+ u64 channel_time;
+ u64 channel_time_busy;
+ u64 channel_time_ext_busy;
+ u64 channel_time_rx;
+ u64 channel_time_tx;
u32 filled;
s8 noise;
};
diff --git a/net/wireless/nl80211.c b/net/wireless/nl80211.c
index 882dc92..c506241 100644
--- a/net/wireless/nl80211.c
+++ b/net/wireless/nl80211.c
@@ -3153,6 +3153,21 @@ static int nl80211_send_survey(struct sk_buff *msg, u32 pid, u32 seq,
survey->noise);
if (survey->filled & SURVEY_INFO_IN_USE)
NLA_PUT_FLAG(msg, NL80211_SURVEY_INFO_IN_USE);
+ if (survey->filled & SURVEY_INFO_CHANNEL_TIME)
+ NLA_PUT_U64(msg, NL80211_SURVEY_INFO_CHANNEL_TIME,
+ survey->channel_time);
+ if (survey->filled & SURVEY_INFO_CHANNEL_TIME_BUSY)
+ NLA_PUT_U64(msg, NL80211_SURVEY_INFO_CHANNEL_TIME_BUSY,
+ survey->channel_time_busy);
+ if (survey->filled & SURVEY_INFO_CHANNEL_TIME_EXT_BUSY)
+ NLA_PUT_U64(msg, NL80211_SURVEY_INFO_CHANNEL_TIME_EXT_BUSY,
+ survey->channel_time_ext_busy);
+ if (survey->filled & SURVEY_INFO_CHANNEL_TIME_RX)
+ NLA_PUT_U64(msg, NL80211_SURVEY_INFO_CHANNEL_TIME_RX,
+ survey->channel_time_rx);
+ if (survey->filled & SURVEY_INFO_CHANNEL_TIME_TX)
+ NLA_PUT_U64(msg, NL80211_SURVEY_INFO_CHANNEL_TIME_TX,
+ survey->channel_time_tx);
nla_nest_end(msg, infoattr);
--
1.7.2.2
^ permalink raw reply related [flat|nested] 9+ messages in thread* [PATCH 2/3] ath9k: add compile time checking for the size of the channel list
2010-10-09 0:39 [PATCH 1/3] cfg80211: add channel utilization stats to the survey command Felix Fietkau
@ 2010-10-09 0:39 ` Felix Fietkau
2010-10-09 0:39 ` [PATCH 3/3] ath9k: implement channel utilization stats for survey Felix Fietkau
2010-10-09 12:17 ` [PATCH 1/3] cfg80211: add channel utilization stats to the survey command Helmut Schaa
1 sibling, 1 reply; 9+ messages in thread
From: Felix Fietkau @ 2010-10-09 0:39 UTC (permalink / raw)
To: linux-wireless, linville; +Cc: lrodriguez, br1
This prevents random memory corruption if the number of channels ever gets
changed without an update to the internal channel array size.
Signed-off-by: Felix Fietkau <nbd@openwrt.org>
---
drivers/net/wireless/ath/ath9k/hw.h | 4 +++-
drivers/net/wireless/ath/ath9k/init.c | 4 ++++
2 files changed, 7 insertions(+), 1 deletions(-)
diff --git a/drivers/net/wireless/ath/ath9k/hw.h b/drivers/net/wireless/ath/ath9k/hw.h
index 7f696c8..6b92334 100644
--- a/drivers/net/wireless/ath/ath9k/hw.h
+++ b/drivers/net/wireless/ath/ath9k/hw.h
@@ -61,6 +61,8 @@
#define ATH9K_RSSI_BAD -128
+#define ATH9K_NUM_CHANNELS 38
+
/* Register read/write primitives */
#define REG_WRITE(_ah, _reg, _val) \
ath9k_hw_common(_ah)->ops->write((_ah), (_val), (_reg))
@@ -618,7 +620,7 @@ struct ath_hw {
struct ath9k_hw_version hw_version;
struct ath9k_ops_config config;
struct ath9k_hw_capabilities caps;
- struct ath9k_channel channels[38];
+ struct ath9k_channel channels[ATH9K_NUM_CHANNELS];
struct ath9k_channel *curchan;
union {
diff --git a/drivers/net/wireless/ath/ath9k/init.c b/drivers/net/wireless/ath/ath9k/init.c
index d76003c..a4c5ed4 100644
--- a/drivers/net/wireless/ath/ath9k/init.c
+++ b/drivers/net/wireless/ath/ath9k/init.c
@@ -481,6 +481,10 @@ static int ath9k_init_channels_rates(struct ath_softc *sc)
{
void *channels;
+ BUILD_BUG_ON(ARRAY_SIZE(ath9k_2ghz_chantable) +
+ ARRAY_SIZE(ath9k_5ghz_chantable) !=
+ ATH9K_NUM_CHANNELS);
+
if (test_bit(ATH9K_MODE_11G, sc->sc_ah->caps.wireless_modes)) {
channels = kmemdup(ath9k_2ghz_chantable,
sizeof(ath9k_2ghz_chantable), GFP_KERNEL);
--
1.7.2.2
^ permalink raw reply related [flat|nested] 9+ messages in thread* [PATCH 3/3] ath9k: implement channel utilization stats for survey
2010-10-09 0:39 ` [PATCH 2/3] ath9k: add compile time checking for the size of the channel list Felix Fietkau
@ 2010-10-09 0:39 ` Felix Fietkau
2010-10-10 16:21 ` [PATCH v2 " Felix Fietkau
0 siblings, 1 reply; 9+ messages in thread
From: Felix Fietkau @ 2010-10-09 0:39 UTC (permalink / raw)
To: linux-wireless, linville; +Cc: lrodriguez, br1
Results for the active channel are updated whenever a new survey dump
is requested, the old data is kept to allow multiple processes to
make their own channel utilization averages.
All other channels only contain the data for the last time that the
hardware was on the channel, i.e. the last scan result or other
off-channel activity.
Running a background scan does not clear the data for the active
channel.
Signed-off-by: Felix Fietkau <nbd@openwrt.org>
---
drivers/net/wireless/ath/ath9k/ath9k.h | 2 +
drivers/net/wireless/ath/ath9k/main.c | 103 +++++++++++++++++++++++++++----
2 files changed, 91 insertions(+), 14 deletions(-)
diff --git a/drivers/net/wireless/ath/ath9k/ath9k.h b/drivers/net/wireless/ath/ath9k/ath9k.h
index de2b18e..4e81fe3 100644
--- a/drivers/net/wireless/ath/ath9k/ath9k.h
+++ b/drivers/net/wireless/ath/ath9k/ath9k.h
@@ -593,6 +593,8 @@ struct ath_softc {
struct delayed_work wiphy_work;
unsigned long wiphy_scheduler_int;
int wiphy_scheduler_index;
+ struct survey_info *cur_survey;
+ struct survey_info survey[ATH9K_NUM_CHANNELS];
struct tasklet_struct intr_tq;
struct tasklet_struct bcon_tasklet;
diff --git a/drivers/net/wireless/ath/ath9k/main.c b/drivers/net/wireless/ath/ath9k/main.c
index 360c6f5..8094a51 100644
--- a/drivers/net/wireless/ath/ath9k/main.c
+++ b/drivers/net/wireless/ath/ath9k/main.c
@@ -175,6 +175,49 @@ static void ath_start_ani(struct ath_common *common)
msecs_to_jiffies((u32)ah->config.ani_poll_interval));
}
+static void ath_update_survey_nf(struct ath_softc *sc, int channel)
+{
+ struct ath_hw *ah = sc->sc_ah;
+ struct ath9k_channel *chan = &ah->channels[channel];
+ struct survey_info *survey = &sc->survey[channel];
+
+ if (chan->noisefloor) {
+ survey->filled |= SURVEY_INFO_NOISE_DBM;
+ survey->noise = chan->noisefloor;
+ }
+}
+
+static void ath_update_survey_stats(struct ath_softc *sc)
+{
+ struct ath_hw *ah = sc->sc_ah;
+ struct ath_common *common = ath9k_hw_common(ah);
+ int pos = ah->curchan - &ah->channels[0];
+ struct survey_info *survey = &sc->survey[pos];
+ struct ath_cycle_counters *cc = &common->cc_survey;
+ unsigned long flags;
+ unsigned int div = common->clockrate * 1000;
+
+ spin_lock_irqsave(&common->cc_lock, flags);
+
+ ath_hw_cycle_counters_update(common);
+
+ if (cc->cycles > 0) {
+ survey->filled |= SURVEY_INFO_CHANNEL_TIME |
+ SURVEY_INFO_CHANNEL_TIME_BUSY |
+ SURVEY_INFO_CHANNEL_TIME_RX |
+ SURVEY_INFO_CHANNEL_TIME_TX;
+ survey->channel_time += cc->cycles / div;
+ survey->channel_time_busy += cc->rx_busy / div;
+ survey->channel_time_rx += cc->rx_frame / div;
+ survey->channel_time_tx += cc->tx_frame / div;
+ }
+ memset(cc, 0, sizeof(*cc));
+
+ ath_update_survey_nf(sc, pos);
+
+ spin_unlock_irqrestore(&common->cc_lock, flags);
+}
+
/*
* Set/change channels. If the channel is really being changed, it's done
* by reseting the chip. To accomplish this we must first cleanup any pending
@@ -1532,7 +1575,8 @@ static int ath9k_config(struct ieee80211_hw *hw, u32 changed)
{
struct ath_wiphy *aphy = hw->priv;
struct ath_softc *sc = aphy->sc;
- struct ath_common *common = ath9k_hw_common(sc->sc_ah);
+ struct ath_hw *ah = sc->sc_ah;
+ struct ath_common *common = ath9k_hw_common(ah);
struct ieee80211_conf *conf = &hw->conf;
bool disable_radio;
@@ -1598,6 +1642,10 @@ static int ath9k_config(struct ieee80211_hw *hw, u32 changed)
if (changed & IEEE80211_CONF_CHANGE_CHANNEL) {
struct ieee80211_channel *curchan = hw->conf.channel;
int pos = curchan->hw_value;
+ int old_pos = -1;
+
+ if (ah->curchan)
+ old_pos = ah->curchan - &ah->channels[0];
aphy->chan_idx = pos;
aphy->chan_is_ht = conf_is_ht(conf);
@@ -1625,12 +1673,43 @@ static int ath9k_config(struct ieee80211_hw *hw, u32 changed)
ath_update_chainmask(sc, conf_is_ht(conf));
+ /* update survey stats for the old channel before switching */
+ ath_update_survey_stats(sc);
+
+ /*
+ * If the operating channel changes, change the survey in-use flags
+ * along with it.
+ * Reset the survey data for the new channel, unless we're switching
+ * back to the operating channel from an off-channel operation.
+ */
+ if (!(hw->conf.flags & IEEE80211_CONF_OFFCHANNEL) &&
+ sc->cur_survey != &sc->survey[pos]) {
+
+ if (sc->cur_survey)
+ sc->cur_survey->filled &= ~SURVEY_INFO_IN_USE;
+
+ sc->cur_survey = &sc->survey[pos];
+
+ memset(sc->cur_survey, 0, sizeof(struct survey_info));
+ sc->cur_survey->filled |= SURVEY_INFO_IN_USE;
+ } else if (!(sc->survey[pos].filled & SURVEY_INFO_IN_USE)) {
+ memset(&sc->survey[pos], 0, sizeof(struct survey_info));
+ }
+
if (ath_set_channel(sc, hw, &sc->sc_ah->channels[pos]) < 0) {
ath_print(common, ATH_DBG_FATAL,
"Unable to set channel\n");
mutex_unlock(&sc->mutex);
return -EINVAL;
}
+
+ /*
+ * The most recent snapshot of channel->noisefloor for the old
+ * channel is only available after the hardware reset. Copy it to
+ * the survey stats now.
+ */
+ if (old_pos >= 0)
+ ath_update_survey_nf(sc, old_pos);
}
skip_chan_change:
@@ -2000,9 +2079,12 @@ static int ath9k_get_survey(struct ieee80211_hw *hw, int idx,
{
struct ath_wiphy *aphy = hw->priv;
struct ath_softc *sc = aphy->sc;
- struct ath_hw *ah = sc->sc_ah;
struct ieee80211_supported_band *sband;
- struct ath9k_channel *chan;
+ struct ieee80211_channel *chan;
+ int pos;
+
+ if (idx == 0)
+ ath_update_survey_stats(sc);
sband = hw->wiphy->bands[IEEE80211_BAND_2GHZ];
if (sband && idx >= sband->n_channels) {
@@ -2016,17 +2098,10 @@ static int ath9k_get_survey(struct ieee80211_hw *hw, int idx,
if (!sband || idx >= sband->n_channels)
return -ENOENT;
- survey->channel = &sband->channels[idx];
- chan = &ah->channels[survey->channel->hw_value];
- survey->filled = 0;
-
- if (chan == ah->curchan)
- survey->filled |= SURVEY_INFO_IN_USE;
-
- if (chan->noisefloor) {
- survey->filled |= SURVEY_INFO_NOISE_DBM;
- survey->noise = chan->noisefloor;
- }
+ chan = &sband->channels[idx];
+ pos = chan->hw_value;
+ memcpy(survey, &sc->survey[pos], sizeof(*survey));
+ survey->channel = chan;
return 0;
}
--
1.7.2.2
^ permalink raw reply related [flat|nested] 9+ messages in thread* [PATCH v2 3/3] ath9k: implement channel utilization stats for survey
2010-10-09 0:39 ` [PATCH 3/3] ath9k: implement channel utilization stats for survey Felix Fietkau
@ 2010-10-10 16:21 ` Felix Fietkau
0 siblings, 0 replies; 9+ messages in thread
From: Felix Fietkau @ 2010-10-10 16:21 UTC (permalink / raw)
To: linux-wireless; +Cc: linville, lrodriguez, br1
Results for the active channel are updated whenever a new survey dump
is requested, the old data is kept to allow multiple processes to
make their own channel utilization averages.
All other channels only contain the data for the last time that the
hardware was on the channel, i.e. the last scan result or other
off-channel activity.
Running a background scan does not clear the data for the active
channel.
Signed-off-by: Felix Fietkau <nbd@openwrt.org>
---
v2: fix counter overflow by reading and clearing counters after the
ani monitor function. fix a survey data locking issue
--- a/drivers/net/wireless/ath/ath9k/ath9k.h
+++ b/drivers/net/wireless/ath/ath9k/ath9k.h
@@ -594,6 +594,8 @@ struct ath_softc {
struct delayed_work wiphy_work;
unsigned long wiphy_scheduler_int;
int wiphy_scheduler_index;
+ struct survey_info *cur_survey;
+ struct survey_info survey[ATH9K_NUM_CHANNELS];
struct tasklet_struct intr_tq;
struct tasklet_struct bcon_tasklet;
--- a/drivers/net/wireless/ath/ath9k/main.c
+++ b/drivers/net/wireless/ath/ath9k/main.c
@@ -176,6 +176,44 @@ static void ath_start_ani(struct ath_com
msecs_to_jiffies((u32)ah->config.ani_poll_interval));
}
+static void ath_update_survey_nf(struct ath_softc *sc, int channel)
+{
+ struct ath_hw *ah = sc->sc_ah;
+ struct ath9k_channel *chan = &ah->channels[channel];
+ struct survey_info *survey = &sc->survey[channel];
+
+ if (chan->noisefloor) {
+ survey->filled |= SURVEY_INFO_NOISE_DBM;
+ survey->noise = chan->noisefloor;
+ }
+}
+
+static void ath_update_survey_stats(struct ath_softc *sc)
+{
+ struct ath_hw *ah = sc->sc_ah;
+ struct ath_common *common = ath9k_hw_common(ah);
+ int pos = ah->curchan - &ah->channels[0];
+ struct survey_info *survey = &sc->survey[pos];
+ struct ath_cycle_counters *cc = &common->cc_survey;
+ unsigned int div = common->clockrate * 1000;
+
+ ath_hw_cycle_counters_update(common);
+
+ if (cc->cycles > 0) {
+ survey->filled |= SURVEY_INFO_CHANNEL_TIME |
+ SURVEY_INFO_CHANNEL_TIME_BUSY |
+ SURVEY_INFO_CHANNEL_TIME_RX |
+ SURVEY_INFO_CHANNEL_TIME_TX;
+ survey->channel_time += cc->cycles / div;
+ survey->channel_time_busy += cc->rx_busy / div;
+ survey->channel_time_rx += cc->rx_frame / div;
+ survey->channel_time_tx += cc->tx_frame / div;
+ }
+ memset(cc, 0, sizeof(*cc));
+
+ ath_update_survey_nf(sc, pos);
+}
+
/*
* Set/change channels. If the channel is really being changed, it's done
* by reseting the chip. To accomplish this we must first cleanup any pending
@@ -454,6 +492,7 @@ void ath_ani_calibrate(unsigned long dat
if (aniflag) {
spin_lock_irqsave(&common->cc_lock, flags);
ath9k_hw_ani_monitor(ah, ah->curchan);
+ ath_update_survey_stats(sc);
spin_unlock_irqrestore(&common->cc_lock, flags);
}
@@ -1533,7 +1572,8 @@ static int ath9k_config(struct ieee80211
{
struct ath_wiphy *aphy = hw->priv;
struct ath_softc *sc = aphy->sc;
- struct ath_common *common = ath9k_hw_common(sc->sc_ah);
+ struct ath_hw *ah = sc->sc_ah;
+ struct ath_common *common = ath9k_hw_common(ah);
struct ieee80211_conf *conf = &hw->conf;
bool disable_radio;
@@ -1599,6 +1639,11 @@ static int ath9k_config(struct ieee80211
if (changed & IEEE80211_CONF_CHANGE_CHANNEL) {
struct ieee80211_channel *curchan = hw->conf.channel;
int pos = curchan->hw_value;
+ int old_pos = -1;
+ unsigned long flags;
+
+ if (ah->curchan)
+ old_pos = ah->curchan - &ah->channels[0];
aphy->chan_idx = pos;
aphy->chan_is_ht = conf_is_ht(conf);
@@ -1626,12 +1671,45 @@ static int ath9k_config(struct ieee80211
ath_update_chainmask(sc, conf_is_ht(conf));
+ /* update survey stats for the old channel before switching */
+ spin_lock_irqsave(&common->cc_lock, flags);
+ ath_update_survey_stats(sc);
+ spin_unlock_irqrestore(&common->cc_lock, flags);
+
+ /*
+ * If the operating channel changes, change the survey in-use flags
+ * along with it.
+ * Reset the survey data for the new channel, unless we're switching
+ * back to the operating channel from an off-channel operation.
+ */
+ if (!(hw->conf.flags & IEEE80211_CONF_OFFCHANNEL) &&
+ sc->cur_survey != &sc->survey[pos]) {
+
+ if (sc->cur_survey)
+ sc->cur_survey->filled &= ~SURVEY_INFO_IN_USE;
+
+ sc->cur_survey = &sc->survey[pos];
+
+ memset(sc->cur_survey, 0, sizeof(struct survey_info));
+ sc->cur_survey->filled |= SURVEY_INFO_IN_USE;
+ } else if (!(sc->survey[pos].filled & SURVEY_INFO_IN_USE)) {
+ memset(&sc->survey[pos], 0, sizeof(struct survey_info));
+ }
+
if (ath_set_channel(sc, hw, &sc->sc_ah->channels[pos]) < 0) {
ath_print(common, ATH_DBG_FATAL,
"Unable to set channel\n");
mutex_unlock(&sc->mutex);
return -EINVAL;
}
+
+ /*
+ * The most recent snapshot of channel->noisefloor for the old
+ * channel is only available after the hardware reset. Copy it to
+ * the survey stats now.
+ */
+ if (old_pos >= 0)
+ ath_update_survey_nf(sc, old_pos);
}
skip_chan_change:
@@ -2001,9 +2079,15 @@ static int ath9k_get_survey(struct ieee8
{
struct ath_wiphy *aphy = hw->priv;
struct ath_softc *sc = aphy->sc;
- struct ath_hw *ah = sc->sc_ah;
+ struct ath_common *common = ath9k_hw_common(sc->sc_ah);
struct ieee80211_supported_band *sband;
- struct ath9k_channel *chan;
+ struct ieee80211_channel *chan;
+ unsigned long flags;
+ int pos;
+
+ spin_lock_irqsave(&common->cc_lock, flags);
+ if (idx == 0)
+ ath_update_survey_stats(sc);
sband = hw->wiphy->bands[IEEE80211_BAND_2GHZ];
if (sband && idx >= sband->n_channels) {
@@ -2014,21 +2098,17 @@ static int ath9k_get_survey(struct ieee8
if (!sband)
sband = hw->wiphy->bands[IEEE80211_BAND_5GHZ];
- if (!sband || idx >= sband->n_channels)
- return -ENOENT;
-
- survey->channel = &sband->channels[idx];
- chan = &ah->channels[survey->channel->hw_value];
- survey->filled = 0;
-
- if (chan == ah->curchan)
- survey->filled |= SURVEY_INFO_IN_USE;
-
- if (chan->noisefloor) {
- survey->filled |= SURVEY_INFO_NOISE_DBM;
- survey->noise = chan->noisefloor;
+ if (!sband || idx >= sband->n_channels) {
+ spin_unlock_irqrestore(&common->cc_lock, flags);
+ return -ENOENT;
}
+ chan = &sband->channels[idx];
+ pos = chan->hw_value;
+ memcpy(survey, &sc->survey[pos], sizeof(*survey));
+ survey->channel = chan;
+ spin_unlock_irqrestore(&common->cc_lock, flags);
+
return 0;
}
^ permalink raw reply [flat|nested] 9+ messages in thread
* Re: [PATCH 1/3] cfg80211: add channel utilization stats to the survey command
2010-10-09 0:39 [PATCH 1/3] cfg80211: add channel utilization stats to the survey command Felix Fietkau
2010-10-09 0:39 ` [PATCH 2/3] ath9k: add compile time checking for the size of the channel list Felix Fietkau
@ 2010-10-09 12:17 ` Helmut Schaa
2010-10-09 13:08 ` Felix Fietkau
1 sibling, 1 reply; 9+ messages in thread
From: Helmut Schaa @ 2010-10-09 12:17 UTC (permalink / raw)
To: Felix Fietkau; +Cc: linux-wireless, linville, lrodriguez, br1
Am Samstag 09 Oktober 2010 schrieb Felix Fietkau:
> Using these, user space can calculate a relative channel utilization
> with arbitrary intervals by regularly taking snapshots of the survey
> results.
What if you've got multiple consumers, wouldn't that mess up the
survey results?
I mean, for example mac80211 and/or hostapd might want to use the busy time
statistics for the BSS load IE while a different userspace process might
want to monitor the channel utilization in order to detect a worsening
channel condition.
If the consumers happen to use the same interval and request the survey
very soon after each other one consumer will get the values on a nice (close
to the query interval) time base while the other one will get the values
based on a very small interval (which might lower the value's
representativeness).
Helmut
^ permalink raw reply [flat|nested] 9+ messages in thread
* Re: [PATCH 1/3] cfg80211: add channel utilization stats to the survey command
2010-10-09 12:17 ` [PATCH 1/3] cfg80211: add channel utilization stats to the survey command Helmut Schaa
@ 2010-10-09 13:08 ` Felix Fietkau
2010-10-09 15:37 ` Helmut Schaa
0 siblings, 1 reply; 9+ messages in thread
From: Felix Fietkau @ 2010-10-09 13:08 UTC (permalink / raw)
To: Helmut Schaa; +Cc: linux-wireless, linville, lrodriguez, br1
On 2010-10-09 2:17 PM, Helmut Schaa wrote:
> Am Samstag 09 Oktober 2010 schrieb Felix Fietkau:
>> Using these, user space can calculate a relative channel utilization
>> with arbitrary intervals by regularly taking snapshots of the survey
>> results.
>
> What if you've got multiple consumers, wouldn't that mess up the
> survey results?
>
> I mean, for example mac80211 and/or hostapd might want to use the busy time
> statistics for the BSS load IE while a different userspace process might
> want to monitor the channel utilization in order to detect a worsening
> channel condition.
>
> If the consumers happen to use the same interval and request the survey
> very soon after each other one consumer will get the values on a nice (close
> to the query interval) time base while the other one will get the values
> based on a very small interval (which might lower the value's
> representativeness).
Multiple consumers work just fine, since the survey results are relative
to the time the hardware started using the channel, not relative to the
last request. Maybe my description was a bit unclear on that part.
- Felix
^ permalink raw reply [flat|nested] 9+ messages in thread
* Re: [PATCH 1/3] cfg80211: add channel utilization stats to the survey command
2010-10-09 13:08 ` Felix Fietkau
@ 2010-10-09 15:37 ` Helmut Schaa
2010-10-09 16:32 ` Felix Fietkau
0 siblings, 1 reply; 9+ messages in thread
From: Helmut Schaa @ 2010-10-09 15:37 UTC (permalink / raw)
To: Felix Fietkau; +Cc: linux-wireless, linville, lrodriguez, br1
Am Samstag 09 Oktober 2010 schrieb Felix Fietkau:
> On 2010-10-09 2:17 PM, Helmut Schaa wrote:
> > Am Samstag 09 Oktober 2010 schrieb Felix Fietkau:
> >> Using these, user space can calculate a relative channel utilization
> >> with arbitrary intervals by regularly taking snapshots of the survey
> >> results.
> >
> > What if you've got multiple consumers, wouldn't that mess up the
> > survey results?
> >
> > I mean, for example mac80211 and/or hostapd might want to use the busy time
> > statistics for the BSS load IE while a different userspace process might
> > want to monitor the channel utilization in order to detect a worsening
> > channel condition.
> >
> > If the consumers happen to use the same interval and request the survey
> > very soon after each other one consumer will get the values on a nice (close
> > to the query interval) time base while the other one will get the values
> > based on a very small interval (which might lower the value's
> > representativeness).
> Multiple consumers work just fine, since the survey results are relative
> to the time the hardware started using the channel, not relative to the
> last request. Maybe my description was a bit unclear on that part.
Ah, thanks Felix, I only read the comment, not the code :)
So, the busy time statistics for channel i are gathered starting with the
switch to i. Hence, if a user space process would like to measure multiple
channels it will just switch through all of them and call get survey right
before switching to the next one, right?
However, if we think about the BSS load IE we might want to measure the busy
times without switching the channel? But we'd like have a somewhat actual
value and not an average throughout the last minute/hour or so. Any ideas how
to integrate that into your approach?
Helmut
^ permalink raw reply [flat|nested] 9+ messages in thread
* Re: [PATCH 1/3] cfg80211: add channel utilization stats to the survey command
2010-10-09 15:37 ` Helmut Schaa
@ 2010-10-09 16:32 ` Felix Fietkau
2010-10-09 18:45 ` Helmut Schaa
0 siblings, 1 reply; 9+ messages in thread
From: Felix Fietkau @ 2010-10-09 16:32 UTC (permalink / raw)
To: Helmut Schaa; +Cc: linux-wireless, linville, lrodriguez, br1
On 2010-10-09 5:37 PM, Helmut Schaa wrote:
> Am Samstag 09 Oktober 2010 schrieb Felix Fietkau:
>> On 2010-10-09 2:17 PM, Helmut Schaa wrote:
>> > Am Samstag 09 Oktober 2010 schrieb Felix Fietkau:
>> >> Using these, user space can calculate a relative channel utilization
>> >> with arbitrary intervals by regularly taking snapshots of the survey
>> >> results.
>> >
>> > What if you've got multiple consumers, wouldn't that mess up the
>> > survey results?
>> >
>> > I mean, for example mac80211 and/or hostapd might want to use the busy time
>> > statistics for the BSS load IE while a different userspace process might
>> > want to monitor the channel utilization in order to detect a worsening
>> > channel condition.
>> >
>> > If the consumers happen to use the same interval and request the survey
>> > very soon after each other one consumer will get the values on a nice (close
>> > to the query interval) time base while the other one will get the values
>> > based on a very small interval (which might lower the value's
>> > representativeness).
>> Multiple consumers work just fine, since the survey results are relative
>> to the time the hardware started using the channel, not relative to the
>> last request. Maybe my description was a bit unclear on that part.
>
> Ah, thanks Felix, I only read the comment, not the code :)
>
> So, the busy time statistics for channel i are gathered starting with the
> switch to i. Hence, if a user space process would like to measure multiple
> channels it will just switch through all of them and call get survey right
> before switching to the next one, right?
In the current ath9k implementation that I posted, the stats are reset
immediately when switching to a channel, with one exception: switching
back to the operating channel after off-channel activity. That way, you
get sane, readable stats for all channels when dumping the survey list
after a scan.
> However, if we think about the BSS load IE we might want to measure the busy
> times without switching the channel? But we'd like have a somewhat actual
> value and not an average throughout the last minute/hour or so. Any ideas how
> to integrate that into your approach?
Just grab a survey dump when starting up, then another after a
minute/hour, and subtract the values of the last one.
Right now there's still an overflow issue in the internal counters in
the current ath9k implementation, so the stats are off unless you poll
survey stats regularly. I'll send a fix for that later.
- Felix
^ permalink raw reply [flat|nested] 9+ messages in thread
* Re: [PATCH 1/3] cfg80211: add channel utilization stats to the survey command
2010-10-09 16:32 ` Felix Fietkau
@ 2010-10-09 18:45 ` Helmut Schaa
0 siblings, 0 replies; 9+ messages in thread
From: Helmut Schaa @ 2010-10-09 18:45 UTC (permalink / raw)
To: Felix Fietkau; +Cc: linux-wireless, linville, lrodriguez, br1
Am Samstag 09 Oktober 2010 schrieb Felix Fietkau:
> On 2010-10-09 5:37 PM, Helmut Schaa wrote:
> > However, if we think about the BSS load IE we might want to measure the busy
> > times without switching the channel? But we'd like have a somewhat actual
> > value and not an average throughout the last minute/hour or so. Any ideas how
> > to integrate that into your approach?
> Just grab a survey dump when starting up, then another after a
> minute/hour, and subtract the values of the last one.
> Right now there's still an overflow issue in the internal counters in
> the current ath9k implementation, so the stats are off unless you poll
> survey stats regularly. I'll send a fix for that later.
Thanks, looks alright to me then. I'll try to add a similar implementation
for rt2800 once these patches go in.
Helmut
^ permalink raw reply [flat|nested] 9+ messages in thread
end of thread, other threads:[~2010-10-10 16:21 UTC | newest]
Thread overview: 9+ messages (download: mbox.gz follow: Atom feed
-- links below jump to the message on this page --
2010-10-09 0:39 [PATCH 1/3] cfg80211: add channel utilization stats to the survey command Felix Fietkau
2010-10-09 0:39 ` [PATCH 2/3] ath9k: add compile time checking for the size of the channel list Felix Fietkau
2010-10-09 0:39 ` [PATCH 3/3] ath9k: implement channel utilization stats for survey Felix Fietkau
2010-10-10 16:21 ` [PATCH v2 " Felix Fietkau
2010-10-09 12:17 ` [PATCH 1/3] cfg80211: add channel utilization stats to the survey command Helmut Schaa
2010-10-09 13:08 ` Felix Fietkau
2010-10-09 15:37 ` Helmut Schaa
2010-10-09 16:32 ` Felix Fietkau
2010-10-09 18:45 ` Helmut Schaa
This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox;
as well as URLs for NNTP newsgroup(s).