Skip to content

Commit

Permalink
---
Browse files Browse the repository at this point in the history
yaml
---
r: 215297
b: refs/heads/master
c: 3430098
h: refs/heads/master
i:
  215295: 55b3d53
v: v3
  • Loading branch information
Felix Fietkau authored and John W. Linville committed Oct 11, 2010
1 parent 6748919 commit c8c919a
Show file tree
Hide file tree
Showing 3 changed files with 99 additions and 17 deletions.
2 changes: 1 addition & 1 deletion [refs]
Original file line number Diff line number Diff line change
@@ -1,2 +1,2 @@
---
refs/heads/master: cac4220b2e93e6344f987581d52d5bd71ff2cc0e
refs/heads/master: 3430098ae463e31ab16926ac3eb295368a3ca5d9
2 changes: 2 additions & 0 deletions trunk/drivers/net/wireless/ath/ath9k/ath9k.h
Original file line number Diff line number Diff line change
Expand Up @@ -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;
Expand Down
112 changes: 96 additions & 16 deletions trunk/drivers/net/wireless/ath/ath9k/main.c
Original file line number Diff line number Diff line change
Expand Up @@ -175,6 +175,44 @@ 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 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
Expand Down Expand Up @@ -453,6 +491,7 @@ void ath_ani_calibrate(unsigned long data)
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);
}

Expand Down Expand Up @@ -1532,7 +1571,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;

Expand Down Expand Up @@ -1598,6 +1638,11 @@ 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;
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);
Expand Down Expand Up @@ -1625,12 +1670,45 @@ 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 */
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:
Expand Down Expand Up @@ -2000,9 +2078,15 @@ 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 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) {
Expand All @@ -2013,21 +2097,17 @@ static int ath9k_get_survey(struct ieee80211_hw *hw, int idx,
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;
}

Expand Down

0 comments on commit c8c919a

Please sign in to comment.