From fce1cea4c717a5b0a97095dc170e52b66611a882 Mon Sep 17 00:00:00 2001 From: Senthil Balasubramanian Date: Fri, 22 May 2009 10:43:07 +0530 Subject: [PATCH] ath9k: Manipulate and report the correct RSSI RSSI reported by the RX descriptor requires little manipulation. Manipulate and report the correct RSSI to the stack. This will fix the improper signal levels reported by iwconfig iw dev wlanX station dump. Signed-off-by: Senthil Balasubramanian Signed-off-by: Vasanthakumar Thiagarajan --- drivers/net/wireless/ath/ath9k/ath9k.h | 15 +++++++++++++++ drivers/net/wireless/ath/ath9k/main.c | 2 ++ drivers/net/wireless/ath/ath9k/recv.c | 20 +++++++++++++++++++- 3 files changed, 36 insertions(+), 1 deletions(-) diff --git a/drivers/net/wireless/ath/ath9k/ath9k.h b/drivers/net/wireless/ath/ath9k/ath9k.h index aaef870..c8a9a98 100644 --- a/drivers/net/wireless/ath/ath9k/ath9k.h +++ b/drivers/net/wireless/ath/ath9k/ath9k.h @@ -297,12 +297,27 @@ struct ath_tx_control { #define ATH_TX_XRETRY 0x02 #define ATH_TX_BAR 0x04 +#define ATH_RSSI_LPF_LEN 10 +#define RSSI_LPF_THRESHOLD -20 +#define ATH_RSSI_EP_MULTIPLIER (1<<7) +#define ATH_EP_MUL(x, mul) ((x) * (mul)) +#define ATH_RSSI_IN(x) (ATH_EP_MUL((x), ATH_RSSI_EP_MULTIPLIER)) +#define ATH_LPF_RSSI(x, y, len) \ + ((x != ATH_RSSI_DUMMY_MARKER) ? (((x) * ((len) - 1) + (y)) / (len)) : (y)) +#define ATH_RSSI_LPF(x, y) do { \ + if ((y) >= RSSI_LPF_THRESHOLD) \ + x = ATH_LPF_RSSI((x), ATH_RSSI_IN((y)), ATH_RSSI_LPF_LEN); \ +} while (0) +#define ATH_EP_RND(x, mul) \ + ((((x)%(mul)) >= ((mul)/2)) ? ((x) + ((mul) - 1)) / (mul) : (x)/(mul)) + struct ath_node { struct ath_softc *an_sc; struct ath_atx_tid tid[WME_NUM_TID]; struct ath_atx_ac ac[WME_NUM_AC]; u16 maxampdu; u8 mpdudensity; + int last_rssi; }; struct ath_tx { diff --git a/drivers/net/wireless/ath/ath9k/main.c b/drivers/net/wireless/ath/ath9k/main.c index c161b75..8f2e455 100644 --- a/drivers/net/wireless/ath/ath9k/main.c +++ b/drivers/net/wireless/ath/ath9k/main.c @@ -440,6 +440,8 @@ static void ath_node_attach(struct ath_softc *sc, struct ieee80211_sta *sta) sta->ht_cap.ampdu_factor); an->mpdudensity = parse_mpdudensity(sta->ht_cap.ampdu_density); } + + an->last_rssi = ATH_RSSI_DUMMY_MARKER; } static void ath_node_detach(struct ath_softc *sc, struct ieee80211_sta *sta) diff --git a/drivers/net/wireless/ath/ath9k/recv.c b/drivers/net/wireless/ath/ath9k/recv.c index 5567517..205e5e2 100644 --- a/drivers/net/wireless/ath/ath9k/recv.c +++ b/drivers/net/wireless/ath/ath9k/recv.c @@ -145,6 +145,8 @@ static int ath_rx_prepare(struct sk_buff *skb, struct ath_desc *ds, u8 ratecode; __le16 fc; struct ieee80211_hw *hw; + struct ieee80211_sta *sta; + struct ath_node *an; hdr = (struct ieee80211_hdr *)skb->data; fc = hdr->frame_control; @@ -229,10 +231,26 @@ static int ath_rx_prepare(struct sk_buff *skb, struct ath_desc *ds, } } + rcu_read_lock(); + + sta = ieee80211_find_sta(sc->hw, hdr->addr2); + if (sta) { + an = (struct ath_node *) sta->drv_priv; + ATH_RSSI_LPF(an->last_rssi, ds->ds_rxstat.rs_rssi); + if (likely(an->last_rssi != ATH_RSSI_DUMMY_MARKER)) + ds->ds_rxstat.rs_rssi = ATH_EP_RND(an->last_rssi, + ATH_RSSI_EP_MULTIPLIER); + if(ds->ds_rxstat.rs_rssi < 0) + ds->ds_rxstat.rs_rssi = 0; + else if(ds->ds_rxstat.rs_rssi > 127) + ds->ds_rxstat.rs_rssi = 127; + } + rcu_read_unlock(); + rx_status->mactime = ath_extend_tsf(sc, ds->ds_rxstat.rs_tstamp); rx_status->band = hw->conf.channel->band; rx_status->freq = hw->conf.channel->center_freq; - rx_status->noise = sc->ani.noise_floor; + rx_status->noise = ATH_DEFAULT_NOISE_FLOOR; rx_status->signal = rx_status->noise + ds->ds_rxstat.rs_rssi; rx_status->antenna = ds->ds_rxstat.rs_antenna; -- 1.6.2