All of lore.kernel.org
 help / color / mirror / Atom feed
* [PATCH 1/4] mt76: mt7615: measure channel noise and report it via survey
@ 2019-12-22 15:07 Felix Fietkau
  2019-12-22 15:07 ` [PATCH 2/4] mt76: mt7615: increase MCU command timeout Felix Fietkau
                   ` (2 more replies)
  0 siblings, 3 replies; 4+ messages in thread
From: Felix Fietkau @ 2019-12-22 15:07 UTC (permalink / raw)
  To: linux-wireless

Read measurements every 100 ms and build a simple moving average

Signed-off-by: Felix Fietkau <nbd@nbd.name>
---
 drivers/net/wireless/mediatek/mt76/mac80211.c |  4 ++
 drivers/net/wireless/mediatek/mt76/mt76.h     |  2 +
 .../net/wireless/mediatek/mt76/mt7615/mac.c   | 42 +++++++++++++++++++
 .../net/wireless/mediatek/mt76/mt7615/main.c  |  3 ++
 .../wireless/mediatek/mt76/mt7615/mt7615.h    |  3 ++
 .../net/wireless/mediatek/mt76/mt7615/regs.h  |  6 +++
 6 files changed, 60 insertions(+)

diff --git a/drivers/net/wireless/mediatek/mt76/mac80211.c b/drivers/net/wireless/mediatek/mt76/mac80211.c
index 0c71d671f29a..cd9a3882cb9d 100644
--- a/drivers/net/wireless/mediatek/mt76/mac80211.c
+++ b/drivers/net/wireless/mediatek/mt76/mac80211.c
@@ -617,6 +617,9 @@ int mt76_get_survey(struct ieee80211_hw *hw, int idx,
 	survey->channel = chan;
 	survey->filled = SURVEY_INFO_TIME | SURVEY_INFO_TIME_BUSY;
 	survey->filled |= dev->drv->survey_flags;
+	if (state->noise)
+		survey->filled |= SURVEY_INFO_NOISE_DBM;
+
 	if (chan == phy->main_chan) {
 		survey->filled |= SURVEY_INFO_IN_USE;
 
@@ -627,6 +630,7 @@ int mt76_get_survey(struct ieee80211_hw *hw, int idx,
 	survey->time_busy = div_u64(state->cc_busy, 1000);
 	survey->time_rx = div_u64(state->cc_rx, 1000);
 	survey->time = div_u64(state->cc_active, 1000);
+	survey->noise = state->noise;
 
 	spin_lock_bh(&dev->cc_lock);
 	survey->time_bss_rx = div_u64(state->cc_bss_rx, 1000);
diff --git a/drivers/net/wireless/mediatek/mt76/mt76.h b/drivers/net/wireless/mediatek/mt76/mt76.h
index f819d9e4ff5f..217f8c5ad201 100644
--- a/drivers/net/wireless/mediatek/mt76/mt76.h
+++ b/drivers/net/wireless/mediatek/mt76/mt76.h
@@ -328,6 +328,8 @@ struct mt76_channel_state {
 	u64 cc_rx;
 	u64 cc_bss_rx;
 	u64 cc_tx;
+
+	s8 noise;
 };
 
 struct mt76_sband {
diff --git a/drivers/net/wireless/mediatek/mt76/mt7615/mac.c b/drivers/net/wireless/mediatek/mt76/mt7615/mac.c
index 903b8395a446..1b52d8b79496 100644
--- a/drivers/net/wireless/mediatek/mt76/mt7615/mac.c
+++ b/drivers/net/wireless/mediatek/mt76/mt7615/mac.c
@@ -1379,6 +1379,19 @@ void mt7615_mac_set_scs(struct mt7615_dev *dev, bool enable)
 	mutex_unlock(&dev->mt76.mutex);
 }
 
+void mt7615_mac_enable_nf(struct mt7615_dev *dev, bool ext_phy)
+{
+	u32 rxtd;
+
+	if (ext_phy)
+		rxtd = MT_WF_PHY_RXTD2(10);
+	else
+		rxtd = MT_WF_PHY_RXTD(12);
+
+	mt76_set(dev, rxtd, BIT(18) | BIT(29));
+	mt76_set(dev, MT_WF_PHY_R0_PHYMUX_5(ext_phy), 0x5 << 12);
+}
+
 void mt7615_mac_cca_stats_reset(struct mt7615_phy *phy)
 {
 	struct mt7615_dev *dev = phy->dev;
@@ -1511,13 +1524,35 @@ mt7615_mac_scs_check(struct mt7615_phy *phy)
 		mt7615_mac_set_default_sensitivity(phy);
 }
 
+static u8
+mt7615_phy_get_nf(struct mt7615_dev *dev, int idx)
+{
+	static const u8 nf_power[] = { 92, 89, 86, 83, 80, 75, 70, 65, 60, 55, 52 };
+	u32 reg = idx ? MT_WF_PHY_RXTD2(17) : MT_WF_PHY_RXTD(20);
+	u32 val, sum = 0, n = 0;
+	int i;
+
+	for (i = 0; i < ARRAY_SIZE(nf_power); i++, reg += 4) {
+		val = mt76_rr(dev, reg);
+		sum += val * nf_power[i];
+		n += val;
+	}
+
+	if (!n)
+		return 0;
+
+	return sum / n;
+}
+
 static void
 mt7615_phy_update_channel(struct mt76_phy *mphy, int idx)
 {
 	struct mt7615_dev *dev = container_of(mphy->dev, struct mt7615_dev, mt76);
+	struct mt7615_phy *phy = mphy->priv;
 	struct mt76_channel_state *state;
 	u64 busy_time, tx_time, rx_time, obss_time;
 	u32 obss_reg = idx ? MT_WF_RMAC_MIB_TIME6 : MT_WF_RMAC_MIB_TIME5;
+	int nf;
 
 	busy_time = mt76_get_field(dev, MT_MIB_SDR9(idx),
 				   MT_MIB_SDR9_BUSY_MASK);
@@ -1527,11 +1562,18 @@ mt7615_phy_update_channel(struct mt76_phy *mphy, int idx)
 				 MT_MIB_SDR37_RXTIME_MASK);
 	obss_time = mt76_get_field(dev, obss_reg, MT_MIB_OBSSTIME_MASK);
 
+	nf = mt7615_phy_get_nf(dev, idx);
+	if (!phy->noise)
+		phy->noise = nf << 4;
+	else if (nf)
+		phy->noise += nf - (phy->noise >> 4);
+
 	state = mphy->chan_state;
 	state->cc_busy += busy_time;
 	state->cc_tx += tx_time;
 	state->cc_rx += rx_time + obss_time;
 	state->cc_bss_rx += rx_time;
+	state->noise = -(phy->noise >> 4);
 }
 
 void mt7615_update_channel(struct mt76_dev *mdev)
diff --git a/drivers/net/wireless/mediatek/mt76/mt7615/main.c b/drivers/net/wireless/mediatek/mt76/mt7615/main.c
index 4ffa920d4f4d..2a85859da754 100644
--- a/drivers/net/wireless/mediatek/mt76/mt7615/main.c
+++ b/drivers/net/wireless/mediatek/mt76/mt7615/main.c
@@ -40,11 +40,13 @@ static int mt7615_start(struct ieee80211_hw *hw)
 	if (!running) {
 		mt7615_mcu_ctrl_pm_state(dev, 0, 0);
 		mt7615_mcu_set_mac_enable(dev, 0, true);
+		mt7615_mac_enable_nf(dev, 0);
 	}
 
 	if (phy != &dev->phy) {
 		mt7615_mcu_ctrl_pm_state(dev, 1, 0);
 		mt7615_mcu_set_mac_enable(dev, 1, true);
+		mt7615_mac_enable_nf(dev, 1);
 	}
 
 	set_bit(MT76_STATE_RUNNING, &phy->mt76->state);
@@ -238,6 +240,7 @@ static int mt7615_set_channel(struct mt7615_phy *phy)
 	mt7615_mac_cca_stats_reset(phy);
 
 	mt7615_mac_reset_counters(dev);
+	phy->noise = 0;
 
 out:
 	clear_bit(MT76_RESET, &phy->mt76->state);
diff --git a/drivers/net/wireless/mediatek/mt76/mt7615/mt7615.h b/drivers/net/wireless/mediatek/mt76/mt7615/mt7615.h
index 48810eda1cd6..eaafae9cc279 100644
--- a/drivers/net/wireless/mediatek/mt76/mt7615/mt7615.h
+++ b/drivers/net/wireless/mediatek/mt76/mt7615/mt7615.h
@@ -94,6 +94,8 @@ struct mt7615_phy {
 	u32 rxfilter;
 	u32 omac_mask;
 
+	u16 noise;
+
 	unsigned long last_cca_adj;
 	int false_cca_ofdm, false_cca_cck;
 	s8 ofdm_sensitivity;
@@ -288,6 +290,7 @@ bool mt7615_mac_wtbl_update(struct mt7615_dev *dev, int idx, u32 mask);
 void mt7615_mac_reset_counters(struct mt7615_dev *dev);
 void mt7615_mac_cca_stats_reset(struct mt7615_phy *phy);
 void mt7615_mac_set_scs(struct mt7615_dev *dev, bool enable);
+void mt7615_mac_enable_nf(struct mt7615_dev *dev, bool ext_phy);
 void mt7615_mac_sta_poll(struct mt7615_dev *dev);
 int mt7615_mac_write_txwi(struct mt7615_dev *dev, __le32 *txwi,
 			  struct sk_buff *skb, struct mt76_wcid *wcid,
diff --git a/drivers/net/wireless/mediatek/mt76/mt7615/regs.h b/drivers/net/wireless/mediatek/mt76/mt7615/regs.h
index 26d121646787..46db0faae93d 100644
--- a/drivers/net/wireless/mediatek/mt76/mt7615/regs.h
+++ b/drivers/net/wireless/mediatek/mt76/mt7615/regs.h
@@ -104,6 +104,9 @@
 #define MT_WF_PHY_B1_PD_OFDM(v)		((v) << 16)
 #define MT_WF_PHY_B1_PD_BLK		BIT(25)
 
+#define MT_WF_PHY_RXTD_BASE		MT_WF_PHY(0x2200)
+#define MT_WF_PHY_RXTD(_n)		(MT_WF_PHY_RXTD_BASE + ((_n) << 2))
+
 #define MT_WF_PHY_B0_RXTD_CCK_PD	MT_WF_PHY(0x2310)
 #define MT_WF_PHY_B0_PD_CCK_MASK	GENMASK(8, 1)
 #define MT_WF_PHY_B0_PD_CCK(v)		((v) << 1)
@@ -112,6 +115,9 @@
 #define MT_WF_PHY_B1_PD_CCK_MASK	GENMASK(31, 24)
 #define MT_WF_PHY_B1_PD_CCK(v)		((v) << 24)
 
+#define MT_WF_PHY_RXTD2_BASE		MT_WF_PHY(0x2a00)
+#define MT_WF_PHY_RXTD2(_n)		(MT_WF_PHY_RXTD2_BASE + ((_n) << 2))
+
 #define MT_WF_CFG_BASE			0x20200
 #define MT_WF_CFG(ofs)			(MT_WF_CFG_BASE + (ofs))
 
-- 
2.24.0


^ permalink raw reply related	[flat|nested] 4+ messages in thread

* [PATCH 2/4] mt76: mt7615: increase MCU command timeout
  2019-12-22 15:07 [PATCH 1/4] mt76: mt7615: measure channel noise and report it via survey Felix Fietkau
@ 2019-12-22 15:07 ` Felix Fietkau
  2019-12-22 15:07 ` [PATCH 3/4] mt76: mt7603: fix input validation issues for powersave-filtered frames Felix Fietkau
  2019-12-22 15:07 ` [PATCH 4/4] mt76: clear skb pointers from rx aggregation reorder buffer during cleanup Felix Fietkau
  2 siblings, 0 replies; 4+ messages in thread
From: Felix Fietkau @ 2019-12-22 15:07 UTC (permalink / raw)
  To: linux-wireless

MCU_EXT_CMD_EFUSE_BUFFER_MODE needs more time on initialization, and
with only 10 seconds it sometimes runs into timeouts.

Signed-off-by: Felix Fietkau <nbd@nbd.name>
---
 drivers/net/wireless/mediatek/mt76/mt7615/mcu.c | 2 +-
 1 file changed, 1 insertion(+), 1 deletion(-)

diff --git a/drivers/net/wireless/mediatek/mt76/mt7615/mcu.c b/drivers/net/wireless/mediatek/mt76/mt7615/mcu.c
index fc091278d9e5..c8d6a36f5d0a 100644
--- a/drivers/net/wireless/mediatek/mt76/mt7615/mcu.c
+++ b/drivers/net/wireless/mediatek/mt76/mt7615/mcu.c
@@ -144,7 +144,7 @@ mt7615_mcu_msg_send(struct mt76_dev *mdev, int cmd, const void *data,
 		    int len, bool wait_resp)
 {
 	struct mt7615_dev *dev = container_of(mdev, struct mt7615_dev, mt76);
-	unsigned long expires = jiffies + 10 * HZ;
+	unsigned long expires = jiffies + 20 * HZ;
 	struct sk_buff *skb;
 	int ret, seq;
 
-- 
2.24.0


^ permalink raw reply related	[flat|nested] 4+ messages in thread

* [PATCH 3/4] mt76: mt7603: fix input validation issues for powersave-filtered frames
  2019-12-22 15:07 [PATCH 1/4] mt76: mt7615: measure channel noise and report it via survey Felix Fietkau
  2019-12-22 15:07 ` [PATCH 2/4] mt76: mt7615: increase MCU command timeout Felix Fietkau
@ 2019-12-22 15:07 ` Felix Fietkau
  2019-12-22 15:07 ` [PATCH 4/4] mt76: clear skb pointers from rx aggregation reorder buffer during cleanup Felix Fietkau
  2 siblings, 0 replies; 4+ messages in thread
From: Felix Fietkau @ 2019-12-22 15:07 UTC (permalink / raw)
  To: linux-wireless

Before extracting the tid out of the packet, check if it was qos-data.
Only accept tid values 0-7
Also, avoid accepting the hardware queue as skb queue mapping, it could
lead to an overrun. Instead, derive the hardware queue from the tid number,
in order to avoid issues with packets being filtered multiple times.
This also fixes a mismatch between hardware and software queue indexes.

Signed-off-by: Felix Fietkau <nbd@nbd.name>
---
 .../net/wireless/mediatek/mt76/mt7603/dma.c   | 19 +++++++++++++++----
 1 file changed, 15 insertions(+), 4 deletions(-)

diff --git a/drivers/net/wireless/mediatek/mt76/mt7603/dma.c b/drivers/net/wireless/mediatek/mt76/mt7603/dma.c
index a6ab73060aad..57428467fe96 100644
--- a/drivers/net/wireless/mediatek/mt76/mt7603/dma.c
+++ b/drivers/net/wireless/mediatek/mt76/mt7603/dma.c
@@ -30,6 +30,16 @@ mt7603_init_tx_queue(struct mt7603_dev *dev, struct mt76_sw_queue *q,
 static void
 mt7603_rx_loopback_skb(struct mt7603_dev *dev, struct sk_buff *skb)
 {
+	static const u8 tid_to_ac[8] = {
+		IEEE80211_AC_BE,
+		IEEE80211_AC_BK,
+		IEEE80211_AC_BK,
+		IEEE80211_AC_BE,
+		IEEE80211_AC_VI,
+		IEEE80211_AC_VI,
+		IEEE80211_AC_VO,
+		IEEE80211_AC_VO
+	};
 	__le32 *txd = (__le32 *)skb->data;
 	struct ieee80211_hdr *hdr;
 	struct ieee80211_sta *sta;
@@ -38,7 +48,7 @@ mt7603_rx_loopback_skb(struct mt7603_dev *dev, struct sk_buff *skb)
 	void *priv;
 	int idx;
 	u32 val;
-	u8 tid;
+	u8 tid = 0;
 
 	if (skb->len < MT_TXD_SIZE + sizeof(struct ieee80211_hdr))
 		goto free;
@@ -56,15 +66,16 @@ mt7603_rx_loopback_skb(struct mt7603_dev *dev, struct sk_buff *skb)
 
 	priv = msta = container_of(wcid, struct mt7603_sta, wcid);
 	val = le32_to_cpu(txd[0]);
-	skb_set_queue_mapping(skb, FIELD_GET(MT_TXD0_Q_IDX, val));
-
 	val &= ~(MT_TXD0_P_IDX | MT_TXD0_Q_IDX);
 	val |= FIELD_PREP(MT_TXD0_Q_IDX, MT_TX_HW_QUEUE_MGMT);
 	txd[0] = cpu_to_le32(val);
 
 	sta = container_of(priv, struct ieee80211_sta, drv_priv);
 	hdr = (struct ieee80211_hdr *)&skb->data[MT_TXD_SIZE];
-	tid = *ieee80211_get_qos_ctl(hdr) & IEEE80211_QOS_CTL_TID_MASK;
+	if (ieee80211_is_data_qos(hdr->frame_control))
+		tid = *ieee80211_get_qos_ctl(hdr) &
+		      IEEE80211_QOS_CTL_TAG1D_MASK;
+	skb_set_queue_mapping(skb, tid_to_ac[tid]);
 	ieee80211_sta_set_buffered(sta, tid, true);
 
 	spin_lock_bh(&dev->ps_lock);
-- 
2.24.0


^ permalink raw reply related	[flat|nested] 4+ messages in thread

* [PATCH 4/4] mt76: clear skb pointers from rx aggregation reorder buffer during cleanup
  2019-12-22 15:07 [PATCH 1/4] mt76: mt7615: measure channel noise and report it via survey Felix Fietkau
  2019-12-22 15:07 ` [PATCH 2/4] mt76: mt7615: increase MCU command timeout Felix Fietkau
  2019-12-22 15:07 ` [PATCH 3/4] mt76: mt7603: fix input validation issues for powersave-filtered frames Felix Fietkau
@ 2019-12-22 15:07 ` Felix Fietkau
  2 siblings, 0 replies; 4+ messages in thread
From: Felix Fietkau @ 2019-12-22 15:07 UTC (permalink / raw)
  To: linux-wireless

During the cleanup of the aggregation session, a rx handler (or release timer)
on another CPU might still hold a pointer to the reorder buffer and could
attempt to release some packets.
Clearing pointers during cleanup avoids a theoretical use-after-free bug here.

Signed-off-by: Felix Fietkau <nbd@nbd.name>
---
 drivers/net/wireless/mediatek/mt76/agg-rx.c | 1 +
 1 file changed, 1 insertion(+)

diff --git a/drivers/net/wireless/mediatek/mt76/agg-rx.c b/drivers/net/wireless/mediatek/mt76/agg-rx.c
index 6d64c2c4a159..3815d28a32ea 100644
--- a/drivers/net/wireless/mediatek/mt76/agg-rx.c
+++ b/drivers/net/wireless/mediatek/mt76/agg-rx.c
@@ -276,6 +276,7 @@ static void mt76_rx_aggr_shutdown(struct mt76_dev *dev, struct mt76_rx_tid *tid)
 		if (!skb)
 			continue;
 
+		tid->reorder_buf[i] = NULL;
 		tid->nframes--;
 		dev_kfree_skb(skb);
 	}
-- 
2.24.0


^ permalink raw reply related	[flat|nested] 4+ messages in thread

end of thread, other threads:[~2019-12-22 15:07 UTC | newest]

Thread overview: 4+ messages (download: mbox.gz / follow: Atom feed)
-- links below jump to the message on this page --
2019-12-22 15:07 [PATCH 1/4] mt76: mt7615: measure channel noise and report it via survey Felix Fietkau
2019-12-22 15:07 ` [PATCH 2/4] mt76: mt7615: increase MCU command timeout Felix Fietkau
2019-12-22 15:07 ` [PATCH 3/4] mt76: mt7603: fix input validation issues for powersave-filtered frames Felix Fietkau
2019-12-22 15:07 ` [PATCH 4/4] mt76: clear skb pointers from rx aggregation reorder buffer during cleanup Felix Fietkau

This is an external index of several public inboxes,
see mirroring instructions on how to clone and mirror
all data and code used by this external index.