From 1d4ca10a562b6d9eaec3aaa5f3905804070ae743 Mon Sep 17 00:00:00 2001 From: Felix Fietkau Date: Tue, 19 Jun 2018 09:58:38 +0200 Subject: [PATCH] mt76x2: track rssi for gain adjustment per station This preserves more sensitivity when weak stations are active Signed-off-by: Felix Fietkau --- mt76x2.h | 6 +++--- mt76x2_init.c | 1 - mt76x2_mac.c | 34 ++++++++++++++++++++---------- mt76x2_main.c | 2 ++ mt76x2_phy.c | 57 +++++++++++++++++++++++++++++++++++++++++++-------- 5 files changed, 76 insertions(+), 24 deletions(-) diff --git a/mt76x2.h b/mt76x2.h index ba17fbed..71fcfa44 100644 --- a/mt76x2.h +++ b/mt76x2.h @@ -69,9 +69,6 @@ struct mt76x2_rx_freq_cal { struct mt76x2_calibration { struct mt76x2_rx_freq_cal rx; - struct ewma_signal rssi; - u32 rssi_count; - u8 agc_gain_init[MT_MAX_CHAINS]; u8 agc_gain_cur[MT_MAX_CHAINS]; @@ -157,6 +154,9 @@ struct mt76x2_sta { struct mt76x2_vif *vif; struct mt76x2_tx_status status; int n_frames; + + struct ewma_signal rssi; + int inactive_count; }; static inline bool is_mt7612(struct mt76x2_dev *dev) diff --git a/mt76x2_init.c b/mt76x2_init.c index e597acec..143e53f3 100644 --- a/mt76x2_init.c +++ b/mt76x2_init.c @@ -657,7 +657,6 @@ struct mt76x2_dev *mt76x2_alloc_device(struct device *pdev) mdev->drv = &drv_ops; mutex_init(&dev->mutex); spin_lock_init(&dev->irq_lock); - ewma_signal_init(&dev->cal.rssi); return dev; } diff --git a/mt76x2_mac.c b/mt76x2_mac.c index b17a4b7a..30f4c87c 100644 --- a/mt76x2_mac.c +++ b/mt76x2_mac.c @@ -282,21 +282,31 @@ static void mt76x2_remove_hdr_pad(struct sk_buff *skb, int len) skb_pull(skb, len); } -static struct mt76_wcid * -mt76x2_rx_get_sta_wcid(struct mt76x2_dev *dev, u8 idx, bool unicast) +static struct mt76x2_sta * +mt76x2_rx_get_sta(struct mt76x2_dev *dev, u8 idx) { - struct mt76x2_sta *sta; struct mt76_wcid *wcid; if (idx >= ARRAY_SIZE(dev->wcid)) return NULL; wcid = rcu_dereference(dev->wcid[idx]); - if (unicast || !wcid) - return wcid; + if (!wcid) + return NULL; - sta = container_of(wcid, struct mt76x2_sta, wcid); - return &sta->vif->group_wcid; + return container_of(wcid, struct mt76x2_sta, wcid); +} + +static struct mt76_wcid * +mt76x2_rx_get_sta_wcid(struct mt76x2_dev *dev, struct mt76x2_sta *sta, bool unicast) +{ + if (!sta) + return NULL; + + if (unicast) + return &sta->wcid; + else + return &sta->vif->group_wcid; } int mt76x2_mac_process_rx(struct mt76x2_dev *dev, struct sk_buff *skb, @@ -304,6 +314,7 @@ int mt76x2_mac_process_rx(struct mt76x2_dev *dev, struct sk_buff *skb, { struct mt76_rx_status *status = (struct mt76_rx_status *) skb->cb; struct mt76x2_rxwi *rxwi = rxi; + struct mt76x2_sta *sta; u32 rxinfo = le32_to_cpu(rxwi->rxinfo); u32 ctl = le32_to_cpu(rxwi->ctl); u16 rate = le16_to_cpu(rxwi->rate); @@ -328,7 +339,8 @@ int mt76x2_mac_process_rx(struct mt76x2_dev *dev, struct sk_buff *skb, } wcid = FIELD_GET(MT_RXWI_CTL_WCID, ctl); - status->wcid = mt76x2_rx_get_sta_wcid(dev, wcid, unicast); + sta = mt76x2_rx_get_sta(dev, wcid); + status->wcid = mt76x2_rx_get_sta_wcid(dev, sta, unicast); len = FIELD_GET(MT_RXWI_CTL_MPDU_LEN, ctl); pn_len = FIELD_GET(MT_RXINFO_PN_LEN, rxinfo); @@ -374,9 +386,9 @@ int mt76x2_mac_process_rx(struct mt76x2_dev *dev, struct sk_buff *skb, status->tid = FIELD_GET(MT_RXWI_TID, tid_sn); status->seqno = FIELD_GET(MT_RXWI_SN, tid_sn); - if (status->wcid) { - ewma_signal_add(&dev->cal.rssi, status->signal); - dev->cal.rssi_count++; + if (sta) { + ewma_signal_add(&sta->rssi, status->signal); + sta->inactive_count = 0; } return mt76x2_mac_process_rate(status, rate); diff --git a/mt76x2_main.c b/mt76x2_main.c index e4e41faf..3c0ebe6d 100644 --- a/mt76x2_main.c +++ b/mt76x2_main.c @@ -294,6 +294,8 @@ mt76x2_sta_add(struct ieee80211_hw *hw, struct ieee80211_vif *vif, if (vif->type == NL80211_IFTYPE_AP) set_bit(MT_WCID_FLAG_CHECK_PS, &msta->wcid.flags); + ewma_signal_init(&msta->rssi); + rcu_assign_pointer(dev->wcid[idx], &msta->wcid); out: diff --git a/mt76x2_phy.c b/mt76x2_phy.c index 826e499e..20ffa6a4 100644 --- a/mt76x2_phy.c +++ b/mt76x2_phy.c @@ -500,6 +500,53 @@ mt76x2_phy_adjust_vga_gain(struct mt76x2_dev *dev) mt76x2_phy_set_gain_val(dev); } +static int +mt76x2_phy_get_min_avg_rssi(struct mt76x2_dev *dev) +{ + struct mt76x2_sta *sta; + struct mt76_wcid *wcid; + int i, j, min_rssi = 0; + s8 cur_rssi; + + local_bh_disable(); + rcu_read_lock(); + + for (i = 0; i < ARRAY_SIZE(dev->wcid_mask); i++) { + unsigned long mask = dev->wcid_mask[i]; + + if (!mask) + continue; + + for (j = i * BITS_PER_LONG; mask; j++, mask >>= 1) { + if (!(mask & 1)) + continue; + + wcid = rcu_dereference(dev->wcid[j]); + if (!wcid) + continue; + + sta = container_of(wcid, struct mt76x2_sta, wcid); + spin_lock(&dev->mt76.rx_lock); + if (sta->inactive_count++ < 5) + cur_rssi = ewma_signal_read(&sta->rssi); + else + cur_rssi = 0; + spin_unlock(&dev->mt76.rx_lock); + + if (cur_rssi < min_rssi) + min_rssi = cur_rssi; + } + } + + rcu_read_unlock(); + local_bh_enable(); + + if (!min_rssi) + return -75; + + return min_rssi; +} + static void mt76x2_phy_update_channel_gain(struct mt76x2_dev *dev) { @@ -507,17 +554,9 @@ mt76x2_phy_update_channel_gain(struct mt76x2_dev *dev) u8 low_gain_delta, gain_delta; bool gain_change; int low_gain; - u32 rssi_count; u32 val; - spin_lock_bh(&dev->mt76.rx_lock); - dev->cal.avg_rssi_all = ewma_signal_read(&dev->cal.rssi); - rssi_count = dev->cal.rssi_count; - dev->cal.rssi_count = 0; - spin_unlock_bh(&dev->mt76.rx_lock); - - if (!rssi_count) - dev->cal.avg_rssi_all = -75; + dev->cal.avg_rssi_all = mt76x2_phy_get_min_avg_rssi(dev); low_gain = (dev->cal.avg_rssi_all > mt76x2_get_rssi_gain_thresh(dev)) + (dev->cal.avg_rssi_all > mt76x2_get_low_rssi_gain_thresh(dev));