public inbox for linux-wireless@vger.kernel.org
 help / color / mirror / Atom feed
* [PATCH 1/8] wifi: mt76: mt7996: revise TXS size
@ 2025-03-11 10:36 Felix Fietkau
  2025-03-11 10:36 ` [PATCH 2/8] wifi: mt76: mt7996: fix SER reset trigger on WED reset Felix Fietkau
                   ` (6 more replies)
  0 siblings, 7 replies; 13+ messages in thread
From: Felix Fietkau @ 2025-03-11 10:36 UTC (permalink / raw)
  To: linux-wireless

From: Benjamin Lin <benjamin-jw.lin@mediatek.com>

Size of MPDU/PPDU TXS is 12 DWs.
In mt7996/mt7992, last 4 DWs are reserved, so TXS size was mistakenly
considered to be 8 DWs. However, in mt7990, 9th DW of TXS starts to be used.

Signed-off-by: Benjamin Lin <benjamin-jw.lin@mediatek.com>
Signed-off-by: Felix Fietkau <nbd@nbd.name>
---
 drivers/net/wireless/mediatek/mt76/mt76_connac3_mac.h | 3 +++
 drivers/net/wireless/mediatek/mt76/mt7996/mac.c       | 4 ++--
 2 files changed, 5 insertions(+), 2 deletions(-)

diff --git a/drivers/net/wireless/mediatek/mt76/mt76_connac3_mac.h b/drivers/net/wireless/mediatek/mt76/mt76_connac3_mac.h
index db0c29e65185..487ad716f872 100644
--- a/drivers/net/wireless/mediatek/mt76/mt76_connac3_mac.h
+++ b/drivers/net/wireless/mediatek/mt76/mt76_connac3_mac.h
@@ -314,6 +314,9 @@ enum tx_frag_idx {
 #define MT_TXFREE_INFO_COUNT		GENMASK(27, 24)
 #define MT_TXFREE_INFO_STAT		GENMASK(29, 28)
 
+#define MT_TXS_HDR_SIZE			4 /* Unit: DW */
+#define MT_TXS_SIZE			12 /* Unit: DW */
+
 #define MT_TXS0_BW			GENMASK(31, 29)
 #define MT_TXS0_TID			GENMASK(28, 26)
 #define MT_TXS0_AMPDU			BIT(25)
diff --git a/drivers/net/wireless/mediatek/mt76/mt7996/mac.c b/drivers/net/wireless/mediatek/mt76/mt7996/mac.c
index 019c925ae600..33a8049d3356 100644
--- a/drivers/net/wireless/mediatek/mt76/mt7996/mac.c
+++ b/drivers/net/wireless/mediatek/mt76/mt7996/mac.c
@@ -1399,7 +1399,7 @@ bool mt7996_rx_check(struct mt76_dev *mdev, void *data, int len)
 		mt7996_mac_tx_free(dev, data, len);
 		return false;
 	case PKT_TYPE_TXS:
-		for (rxd += 4; rxd + 8 <= end; rxd += 8)
+		for (rxd += MT_TXS_HDR_SIZE; rxd + MT_TXS_SIZE <= end; rxd += MT_TXS_SIZE)
 			mt7996_mac_add_txs(dev, rxd);
 		return false;
 	case PKT_TYPE_RX_FW_MONITOR:
@@ -1442,7 +1442,7 @@ void mt7996_queue_rx_skb(struct mt76_dev *mdev, enum mt76_rxq_id q,
 		mt7996_mcu_rx_event(dev, skb);
 		break;
 	case PKT_TYPE_TXS:
-		for (rxd += 4; rxd + 8 <= end; rxd += 8)
+		for (rxd += MT_TXS_HDR_SIZE; rxd + MT_TXS_SIZE <= end; rxd += MT_TXS_SIZE)
 			mt7996_mac_add_txs(dev, rxd);
 		dev_kfree_skb(skb);
 		break;
-- 
2.47.1


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

* [PATCH 2/8] wifi: mt76: mt7996: fix SER reset trigger on WED reset
  2025-03-11 10:36 [PATCH 1/8] wifi: mt76: mt7996: revise TXS size Felix Fietkau
@ 2025-03-11 10:36 ` Felix Fietkau
  2025-03-11 10:36 ` [PATCH 3/8] wifi: mt76: mt7996: remove unnecessary key->cipher check for BIP frames Felix Fietkau
                   ` (5 subsequent siblings)
  6 siblings, 0 replies; 13+ messages in thread
From: Felix Fietkau @ 2025-03-11 10:36 UTC (permalink / raw)
  To: linux-wireless

From: Rex Lu <rex.lu@mediatek.com>

The firmware needs a specific trigger when WED is being reset due to an
ethernet reset condition. This helps prevent further L1 SER failure.

Signed-off-by: Rex Lu <rex.lu@mediatek.com>
Signed-off-by: Felix Fietkau <nbd@nbd.name>
---
 drivers/net/wireless/mediatek/mt76/mt7996/mcu.h  | 3 ++-
 drivers/net/wireless/mediatek/mt76/mt7996/mmio.c | 2 +-
 2 files changed, 3 insertions(+), 2 deletions(-)

diff --git a/drivers/net/wireless/mediatek/mt76/mt7996/mcu.h b/drivers/net/wireless/mediatek/mt76/mt7996/mcu.h
index bd1ba00e1bc6..5fdc47dad28c 100644
--- a/drivers/net/wireless/mediatek/mt76/mt7996/mcu.h
+++ b/drivers/net/wireless/mediatek/mt76/mt7996/mcu.h
@@ -896,7 +896,8 @@ enum {
 	UNI_CMD_SER_SET_RECOVER_L3_TX_DISABLE,
 	UNI_CMD_SER_SET_RECOVER_L3_BF,
 	UNI_CMD_SER_SET_RECOVER_L4_MDP,
-	UNI_CMD_SER_SET_RECOVER_FULL,
+	UNI_CMD_SER_SET_RECOVER_FROM_ETH,
+	UNI_CMD_SER_SET_RECOVER_FULL = 8,
 	UNI_CMD_SER_SET_SYSTEM_ASSERT,
 	/* action */
 	UNI_CMD_SER_ENABLE = 1,
diff --git a/drivers/net/wireless/mediatek/mt76/mt7996/mmio.c b/drivers/net/wireless/mediatek/mt76/mt7996/mmio.c
index 7a8ee6c75cf2..9d37f8238746 100644
--- a/drivers/net/wireless/mediatek/mt76/mt7996/mmio.c
+++ b/drivers/net/wireless/mediatek/mt76/mt7996/mmio.c
@@ -281,7 +281,7 @@ static int mt7996_mmio_wed_reset(struct mtk_wed_device *wed)
 	if (test_and_set_bit(MT76_STATE_WED_RESET, &mphy->state))
 		return -EBUSY;
 
-	ret = mt7996_mcu_set_ser(dev, UNI_CMD_SER_TRIGGER, UNI_CMD_SER_SET_RECOVER_L1,
+	ret = mt7996_mcu_set_ser(dev, UNI_CMD_SER_TRIGGER, UNI_CMD_SER_SET_RECOVER_FROM_ETH,
 				 mphy->band_idx);
 	if (ret)
 		goto out;
-- 
2.47.1


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

* [PATCH 3/8] wifi: mt76: mt7996: remove unnecessary key->cipher check for BIP frames
  2025-03-11 10:36 [PATCH 1/8] wifi: mt76: mt7996: revise TXS size Felix Fietkau
  2025-03-11 10:36 ` [PATCH 2/8] wifi: mt76: mt7996: fix SER reset trigger on WED reset Felix Fietkau
@ 2025-03-11 10:36 ` Felix Fietkau
  2025-03-11 10:36 ` [PATCH 4/8] wifi: mt76: scan: set vif offchannel link for scanning/roc Felix Fietkau
                   ` (4 subsequent siblings)
  6 siblings, 0 replies; 13+ messages in thread
From: Felix Fietkau @ 2025-03-11 10:36 UTC (permalink / raw)
  To: linux-wireless

From: Michael-CY Lee <michael-cy.lee@mediatek.com>

The cipher type check is redundant, and there is no need to dereference the
key struct here.

Signed-off-by: Michael-CY Lee <michael-cy.lee@mediatek.com>
Signed-off-by: Felix Fietkau <nbd@nbd.name>
---
 drivers/net/wireless/mediatek/mt76/mt7996/mac.c | 3 +--
 1 file changed, 1 insertion(+), 2 deletions(-)

diff --git a/drivers/net/wireless/mediatek/mt76/mt7996/mac.c b/drivers/net/wireless/mediatek/mt76/mt7996/mac.c
index 33a8049d3356..162d1552602e 100644
--- a/drivers/net/wireless/mediatek/mt76/mt7996/mac.c
+++ b/drivers/net/wireless/mediatek/mt76/mt7996/mac.c
@@ -773,8 +773,7 @@ mt7996_mac_write_txwi_80211(struct mt7996_dev *dev, __le32 *txwi,
 	    info->flags & IEEE80211_TX_CTL_USE_MINRATE)
 		val |= MT_TXD1_FIXED_RATE;
 
-	if (key && multicast && ieee80211_is_robust_mgmt_frame(skb) &&
-	    key->cipher == WLAN_CIPHER_SUITE_AES_CMAC) {
+	if (key && multicast && ieee80211_is_robust_mgmt_frame(skb)) {
 		val |= MT_TXD1_BIP;
 		txwi[3] &= ~cpu_to_le32(MT_TXD3_PROTECT_FRAME);
 	}
-- 
2.47.1


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

* [PATCH 4/8] wifi: mt76: scan: set vif offchannel link for scanning/roc
  2025-03-11 10:36 [PATCH 1/8] wifi: mt76: mt7996: revise TXS size Felix Fietkau
  2025-03-11 10:36 ` [PATCH 2/8] wifi: mt76: mt7996: fix SER reset trigger on WED reset Felix Fietkau
  2025-03-11 10:36 ` [PATCH 3/8] wifi: mt76: mt7996: remove unnecessary key->cipher check for BIP frames Felix Fietkau
@ 2025-03-11 10:36 ` Felix Fietkau
  2025-03-11 10:36 ` [PATCH 5/8] wifi: mt76: mt7996: use the correct vif " Felix Fietkau
                   ` (3 subsequent siblings)
  6 siblings, 0 replies; 13+ messages in thread
From: Felix Fietkau @ 2025-03-11 10:36 UTC (permalink / raw)
  To: linux-wireless

The driver needs to know what vif link to use

Signed-off-by: Felix Fietkau <nbd@nbd.name>
---
 drivers/net/wireless/mediatek/mt76/channel.c | 3 +++
 drivers/net/wireless/mediatek/mt76/mt76.h    | 2 ++
 2 files changed, 5 insertions(+)

diff --git a/drivers/net/wireless/mediatek/mt76/channel.c b/drivers/net/wireless/mediatek/mt76/channel.c
index 6a35c6ebd823..e7b839e74290 100644
--- a/drivers/net/wireless/mediatek/mt76/channel.c
+++ b/drivers/net/wireless/mediatek/mt76/channel.c
@@ -293,6 +293,7 @@ struct mt76_vif_link *mt76_get_vif_phy_link(struct mt76_phy *phy,
 		kfree(mlink);
 		return ERR_PTR(ret);
 	}
+	rcu_assign_pointer(mvif->offchannel_link, mlink);
 
 	return mlink;
 }
@@ -301,10 +302,12 @@ void mt76_put_vif_phy_link(struct mt76_phy *phy, struct ieee80211_vif *vif,
 			   struct mt76_vif_link *mlink)
 {
 	struct mt76_dev *dev = phy->dev;
+	struct mt76_vif_data *mvif = mlink->mvif;
 
 	if (IS_ERR_OR_NULL(mlink) || !mlink->offchannel)
 		return;
 
+	rcu_assign_pointer(mvif->offchannel_link, NULL);
 	dev->drv->vif_link_remove(phy, vif, &vif->bss_conf, mlink);
 	kfree(mlink);
 }
diff --git a/drivers/net/wireless/mediatek/mt76/mt76.h b/drivers/net/wireless/mediatek/mt76/mt76.h
index 7596191252dc..c16a6743ad64 100644
--- a/drivers/net/wireless/mediatek/mt76/mt76.h
+++ b/drivers/net/wireless/mediatek/mt76/mt76.h
@@ -351,6 +351,7 @@ struct mt76_wcid {
 	u8 hw_key_idx;
 	u8 hw_key_idx2;
 
+	u8 offchannel:1;
 	u8 sta:1;
 	u8 sta_disabled:1;
 	u8 amsdu:1;
@@ -787,6 +788,7 @@ struct mt76_vif_link {
 
 struct mt76_vif_data {
 	struct mt76_vif_link __rcu *link[IEEE80211_MLD_MAX_NUM_LINKS];
+	struct mt76_vif_link __rcu *offchannel_link;
 
 	struct mt76_phy *roc_phy;
 	u16 valid_links;
-- 
2.47.1


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

* [PATCH 5/8] wifi: mt76: mt7996: use the correct vif link for scanning/roc
  2025-03-11 10:36 [PATCH 1/8] wifi: mt76: mt7996: revise TXS size Felix Fietkau
                   ` (2 preceding siblings ...)
  2025-03-11 10:36 ` [PATCH 4/8] wifi: mt76: scan: set vif offchannel link for scanning/roc Felix Fietkau
@ 2025-03-11 10:36 ` Felix Fietkau
  2025-03-12  2:08   ` Ping-Ke Shih
  2025-03-11 10:36 ` [PATCH 6/8] mt76: only mark tx-status-failed frames as ACKed on mt76x0/2 Felix Fietkau
                   ` (2 subsequent siblings)
  6 siblings, 1 reply; 13+ messages in thread
From: Felix Fietkau @ 2025-03-11 10:36 UTC (permalink / raw)
  To: linux-wireless

Use the newly added offchannel_link pointer in vif data

Signed-off-by: Felix Fietkau <nbd@nbd.name>
---
 .../net/wireless/mediatek/mt76/mt7996/mac.c   | 40 +++++++++++++------
 .../net/wireless/mediatek/mt76/mt7996/main.c  |  1 +
 2 files changed, 28 insertions(+), 13 deletions(-)

diff --git a/drivers/net/wireless/mediatek/mt76/mt7996/mac.c b/drivers/net/wireless/mediatek/mt76/mt7996/mac.c
index 162d1552602e..9dfc8106ebec 100644
--- a/drivers/net/wireless/mediatek/mt76/mt7996/mac.c
+++ b/drivers/net/wireless/mediatek/mt76/mt7996/mac.c
@@ -831,7 +831,8 @@ void mt7996_mac_write_txwi(struct mt7996_dev *dev, __le32 *txwi,
 	u8 band_idx = (info->hw_queue & MT_TX_HW_QUEUE_PHY) >> 2;
 	u8 p_fmt, q_idx, omac_idx = 0, wmm_idx = 0;
 	bool is_8023 = info->flags & IEEE80211_TX_CTL_HW_80211_ENCAP;
-	struct mt76_vif_link *mvif;
+	struct mt76_vif_link *mlink = NULL;
+	struct mt7996_vif *mvif;
 	u16 tx_count = 15;
 	u32 val;
 	bool inband_disc = !!(changed & (BSS_CHANGED_UNSOL_BCAST_PROBE_RESP |
@@ -839,11 +840,18 @@ void mt7996_mac_write_txwi(struct mt7996_dev *dev, __le32 *txwi,
 	bool beacon = !!(changed & (BSS_CHANGED_BEACON |
 				    BSS_CHANGED_BEACON_ENABLED)) && (!inband_disc);
 
-	mvif = vif ? (struct mt76_vif_link *)vif->drv_priv : NULL;
-	if (mvif) {
-		omac_idx = mvif->omac_idx;
-		wmm_idx = mvif->wmm_idx;
-		band_idx = mvif->band_idx;
+	if (vif) {
+		mvif = (struct mt7996_vif *)vif->drv_priv;
+		if (wcid->offchannel)
+			mlink = rcu_dereference(mvif->mt76.offchannel_link);
+		if (!mlink)
+			mlink = &mvif->deflink.mt76;
+	}
+
+	if (mlink) {
+		omac_idx = mlink->omac_idx;
+		wmm_idx = mlink->wmm_idx;
+		band_idx = mlink->band_idx;
 	}
 
 	if (inband_disc) {
@@ -909,13 +917,13 @@ void mt7996_mac_write_txwi(struct mt7996_dev *dev, __le32 *txwi,
 			     is_multicast_ether_addr(hdr->addr1);
 		u8 idx = MT7996_BASIC_RATES_TBL;
 
-		if (mvif) {
-			if (mcast && mvif->mcast_rates_idx)
-				idx = mvif->mcast_rates_idx;
-			else if (beacon && mvif->beacon_rates_idx)
-				idx = mvif->beacon_rates_idx;
+		if (mlink) {
+			if (mcast && mlink->mcast_rates_idx)
+				idx = mlink->mcast_rates_idx;
+			else if (beacon && mlink->beacon_rates_idx)
+				idx = mlink->beacon_rates_idx;
 			else
-				idx = mvif->basic_rates_idx;
+				idx = mlink->basic_rates_idx;
 		}
 
 		val = FIELD_PREP(MT_TXD6_TX_RATE, idx) | MT_TXD6_FIXED_BW;
@@ -983,8 +991,14 @@ int mt7996_tx_prepare_skb(struct mt76_dev *mdev, void *txwi_ptr,
 
 	if (vif) {
 		struct mt7996_vif *mvif = (struct mt7996_vif *)vif->drv_priv;
+		struct mt76_vif_link *mlink = NULL;
 
-		txp->fw.bss_idx = mvif->deflink.mt76.idx;
+		if (wcid->offchannel)
+			mlink = rcu_dereference(mvif->mt76.offchannel_link);
+		if (!mlink)
+			mlink = &mvif->deflink.mt76;
+
+		txp->fw.bss_idx = mlink->idx;
 	}
 
 	txp->fw.token = cpu_to_le16(id);
diff --git a/drivers/net/wireless/mediatek/mt76/mt7996/main.c b/drivers/net/wireless/mediatek/mt76/mt7996/main.c
index 69dd565d8319..886b6ef3462b 100644
--- a/drivers/net/wireless/mediatek/mt76/mt7996/main.c
+++ b/drivers/net/wireless/mediatek/mt76/mt7996/main.c
@@ -249,6 +249,7 @@ int mt7996_vif_link_add(struct mt76_phy *mphy, struct ieee80211_vif *vif,
 	mlink->band_idx = band_idx;
 	mlink->wmm_idx = vif->type == NL80211_IFTYPE_AP ? 0 : 3;
 	mlink->wcid = &link->sta.wcid;
+	mlink->wcid->offchannel = mlink->offchannel;
 
 	ret = mt7996_mcu_add_dev_info(phy, vif, link_conf, mlink, true);
 	if (ret)
-- 
2.47.1


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

* [PATCH 6/8] mt76: only mark tx-status-failed frames as ACKed on mt76x0/2
  2025-03-11 10:36 [PATCH 1/8] wifi: mt76: mt7996: revise TXS size Felix Fietkau
                   ` (3 preceding siblings ...)
  2025-03-11 10:36 ` [PATCH 5/8] wifi: mt76: mt7996: use the correct vif " Felix Fietkau
@ 2025-03-11 10:36 ` Felix Fietkau
  2025-03-11 10:47   ` Felix Fietkau
  2025-03-11 10:36 ` [PATCH 7/8] wifi: mt76: mt7996: implement driver specific get_txpower function Felix Fietkau
  2025-03-11 10:36 ` [PATCH 8/8] wifi: mt76: scan: fix setting tx_info fields Felix Fietkau
  6 siblings, 1 reply; 13+ messages in thread
From: Felix Fietkau @ 2025-03-11 10:36 UTC (permalink / raw)
  To: linux-wireless

The interrupt status polling is unreliable, which can cause status events
to get lost. On all newer chips, txs-timeout is an indication that the
packet was either never sent, or never acked.
Fixes issues with inactivity polling.

Signed-off-by: Felix Fietkau <nbd@nbd.name>
---
 drivers/net/wireless/mediatek/mt76/mt76.h       | 1 +
 drivers/net/wireless/mediatek/mt76/mt76x0/pci.c | 3 ++-
 drivers/net/wireless/mediatek/mt76/mt76x0/usb.c | 3 ++-
 drivers/net/wireless/mediatek/mt76/mt76x2/pci.c | 3 ++-
 drivers/net/wireless/mediatek/mt76/mt76x2/usb.c | 3 ++-
 drivers/net/wireless/mediatek/mt76/tx.c         | 3 ++-
 6 files changed, 11 insertions(+), 5 deletions(-)

diff --git a/drivers/net/wireless/mediatek/mt76/mt76.h b/drivers/net/wireless/mediatek/mt76/mt76.h
index c16a6743ad64..b461273c3306 100644
--- a/drivers/net/wireless/mediatek/mt76/mt76.h
+++ b/drivers/net/wireless/mediatek/mt76/mt76.h
@@ -492,6 +492,7 @@ struct mt76_hw_cap {
 #define MT_DRV_RX_DMA_HDR		BIT(3)
 #define MT_DRV_HW_MGMT_TXQ		BIT(4)
 #define MT_DRV_AMSDU_OFFLOAD		BIT(5)
+#define MT_DRV_IGNORE_TXS_FAILED	BIT(6)
 
 struct mt76_driver_ops {
 	u32 drv_flags;
diff --git a/drivers/net/wireless/mediatek/mt76/mt76x0/pci.c b/drivers/net/wireless/mediatek/mt76/mt76x0/pci.c
index b456ccd00d58..11c16d1fc70f 100644
--- a/drivers/net/wireless/mediatek/mt76/mt76x0/pci.c
+++ b/drivers/net/wireless/mediatek/mt76/mt76x0/pci.c
@@ -156,7 +156,8 @@ mt76x0e_probe(struct pci_dev *pdev, const struct pci_device_id *id)
 	static const struct mt76_driver_ops drv_ops = {
 		.txwi_size = sizeof(struct mt76x02_txwi),
 		.drv_flags = MT_DRV_TX_ALIGNED4_SKBS |
-			     MT_DRV_SW_RX_AIRTIME,
+			     MT_DRV_SW_RX_AIRTIME |
+			     MT_DRV_IGNORE_TXS_FAILED,
 		.survey_flags = SURVEY_INFO_TIME_TX,
 		.update_survey = mt76x02_update_channel,
 		.set_channel = mt76x0_set_channel,
diff --git a/drivers/net/wireless/mediatek/mt76/mt76x0/usb.c b/drivers/net/wireless/mediatek/mt76/mt76x0/usb.c
index b031c500b741..90e5666c0857 100644
--- a/drivers/net/wireless/mediatek/mt76/mt76x0/usb.c
+++ b/drivers/net/wireless/mediatek/mt76/mt76x0/usb.c
@@ -214,7 +214,8 @@ static int mt76x0u_probe(struct usb_interface *usb_intf,
 			 const struct usb_device_id *id)
 {
 	static const struct mt76_driver_ops drv_ops = {
-		.drv_flags = MT_DRV_SW_RX_AIRTIME,
+		.drv_flags = MT_DRV_SW_RX_AIRTIME |
+			     MT_DRV_IGNORE_TXS_FAILED,
 		.survey_flags = SURVEY_INFO_TIME_TX,
 		.update_survey = mt76x02_update_channel,
 		.set_channel = mt76x0_set_channel,
diff --git a/drivers/net/wireless/mediatek/mt76/mt76x2/pci.c b/drivers/net/wireless/mediatek/mt76/mt76x2/pci.c
index 727bfdd00b40..2303019670e2 100644
--- a/drivers/net/wireless/mediatek/mt76/mt76x2/pci.c
+++ b/drivers/net/wireless/mediatek/mt76/mt76x2/pci.c
@@ -22,7 +22,8 @@ mt76x2e_probe(struct pci_dev *pdev, const struct pci_device_id *id)
 	static const struct mt76_driver_ops drv_ops = {
 		.txwi_size = sizeof(struct mt76x02_txwi),
 		.drv_flags = MT_DRV_TX_ALIGNED4_SKBS |
-			     MT_DRV_SW_RX_AIRTIME,
+			     MT_DRV_SW_RX_AIRTIME |
+			     MT_DRV_IGNORE_TXS_FAILED,
 		.survey_flags = SURVEY_INFO_TIME_TX,
 		.update_survey = mt76x02_update_channel,
 		.set_channel = mt76x2e_set_channel,
diff --git a/drivers/net/wireless/mediatek/mt76/mt76x2/usb.c b/drivers/net/wireless/mediatek/mt76/mt76x2/usb.c
index e832ad53e239..3747f9ed31e6 100644
--- a/drivers/net/wireless/mediatek/mt76/mt76x2/usb.c
+++ b/drivers/net/wireless/mediatek/mt76/mt76x2/usb.c
@@ -29,7 +29,8 @@ static int mt76x2u_probe(struct usb_interface *intf,
 			 const struct usb_device_id *id)
 {
 	static const struct mt76_driver_ops drv_ops = {
-		.drv_flags = MT_DRV_SW_RX_AIRTIME,
+		.drv_flags = MT_DRV_SW_RX_AIRTIME |
+			     MT_DRV_IGNORE_TXS_FAILED,
 		.survey_flags = SURVEY_INFO_TIME_TX,
 		.update_survey = mt76x02_update_channel,
 		.set_channel = mt76x2u_set_channel,
diff --git a/drivers/net/wireless/mediatek/mt76/tx.c b/drivers/net/wireless/mediatek/mt76/tx.c
index af0c50c983ec..513916469ca2 100644
--- a/drivers/net/wireless/mediatek/mt76/tx.c
+++ b/drivers/net/wireless/mediatek/mt76/tx.c
@@ -100,7 +100,8 @@ __mt76_tx_status_skb_done(struct mt76_dev *dev, struct sk_buff *skb, u8 flags,
 		return;
 
 	/* Tx status can be unreliable. if it fails, mark the frame as ACKed */
-	if (flags & MT_TX_CB_TXS_FAILED) {
+	if (flags & MT_TX_CB_TXS_FAILED &&
+	    (dev->drv->drv_flags & MT_DRV_IGNORE_TXS_FAILED)) {
 		info->status.rates[0].count = 0;
 		info->status.rates[0].idx = -1;
 		info->flags |= IEEE80211_TX_STAT_ACK;
-- 
2.47.1


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

* [PATCH 7/8] wifi: mt76: mt7996: implement driver specific get_txpower function
  2025-03-11 10:36 [PATCH 1/8] wifi: mt76: mt7996: revise TXS size Felix Fietkau
                   ` (4 preceding siblings ...)
  2025-03-11 10:36 ` [PATCH 6/8] mt76: only mark tx-status-failed frames as ACKed on mt76x0/2 Felix Fietkau
@ 2025-03-11 10:36 ` Felix Fietkau
  2025-03-11 13:55   ` Lorenzo Bianconi
  2025-03-11 10:36 ` [PATCH 8/8] wifi: mt76: scan: fix setting tx_info fields Felix Fietkau
  6 siblings, 1 reply; 13+ messages in thread
From: Felix Fietkau @ 2025-03-11 10:36 UTC (permalink / raw)
  To: linux-wireless

Fixes reporting tx power for vifs that don't have a channel context
assigned. Report the tx power of a phy that is covered by the vif's
radio mask.

Signed-off-by: Felix Fietkau <nbd@nbd.name>
---
 .../net/wireless/mediatek/mt76/mt7996/main.c  | 27 ++++++++++++++++++-
 1 file changed, 26 insertions(+), 1 deletion(-)

diff --git a/drivers/net/wireless/mediatek/mt76/mt7996/main.c b/drivers/net/wireless/mediatek/mt76/mt7996/main.c
index 886b6ef3462b..89fc3f102555 100644
--- a/drivers/net/wireless/mediatek/mt76/mt7996/main.c
+++ b/drivers/net/wireless/mediatek/mt76/mt7996/main.c
@@ -602,6 +602,31 @@ static void mt7996_configure_filter(struct ieee80211_hw *hw,
 	mutex_unlock(&dev->mt76.mutex);
 }
 
+static int
+mt7996_get_txpower(struct ieee80211_hw *hw, struct ieee80211_vif *vif, int *dbm)
+{
+	struct mt7996_vif *mvif = (struct mt7996_vif *)vif->drv_priv;
+	struct mt7996_phy *phy = mt7996_vif_link_phy(&mvif->deflink);
+	struct mt7996_dev *dev = mt7996_hw_dev(hw);
+	struct wireless_dev *wdev;
+	int n_chains, delta, i;
+
+	if (!phy) {
+		wdev = ieee80211_vif_to_wdev(vif);
+		for (i = 0; i < hw->wiphy->n_radio; i++)
+			if (wdev->radio_mask & BIT(i))
+				phy = dev->radio_phy[i];
+
+		if (!phy)
+			return -EINVAL;
+	}
+
+	n_chains = hweight16(phy->mt76->chainmask);
+	delta = mt76_tx_power_nss_delta(n_chains);
+	*dbm = DIV_ROUND_UP(phy->mt76->txpower_cur + delta, 2);
+
+	return 0;
+}
 static u8
 mt7996_get_rates_table(struct mt7996_phy *phy, struct ieee80211_bss_conf *conf,
 		       bool beacon, bool mcast)
@@ -1651,7 +1676,7 @@ const struct ieee80211_ops mt7996_ops = {
 	.remain_on_channel = mt76_remain_on_channel,
 	.cancel_remain_on_channel = mt76_cancel_remain_on_channel,
 	.release_buffered_frames = mt76_release_buffered_frames,
-	.get_txpower = mt76_get_txpower,
+	.get_txpower = mt7996_get_txpower,
 	.channel_switch_beacon = mt7996_channel_switch_beacon,
 	.get_stats = mt7996_get_stats,
 	.get_et_sset_count = mt7996_get_et_sset_count,
-- 
2.47.1


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

* [PATCH 8/8] wifi: mt76: scan: fix setting tx_info fields
  2025-03-11 10:36 [PATCH 1/8] wifi: mt76: mt7996: revise TXS size Felix Fietkau
                   ` (5 preceding siblings ...)
  2025-03-11 10:36 ` [PATCH 7/8] wifi: mt76: mt7996: implement driver specific get_txpower function Felix Fietkau
@ 2025-03-11 10:36 ` Felix Fietkau
  6 siblings, 0 replies; 13+ messages in thread
From: Felix Fietkau @ 2025-03-11 10:36 UTC (permalink / raw)
  To: linux-wireless

ieee80211_tx_prepare_skb initializes the skb cb, so fields need to be set
afterwards.

Signed-off-by: Felix Fietkau <nbd@nbd.name>
---
 drivers/net/wireless/mediatek/mt76/scan.c | 21 +++++++++++++--------
 1 file changed, 13 insertions(+), 8 deletions(-)

diff --git a/drivers/net/wireless/mediatek/mt76/scan.c b/drivers/net/wireless/mediatek/mt76/scan.c
index 1c4f9deaaada..9b20ccbeb8cf 100644
--- a/drivers/net/wireless/mediatek/mt76/scan.c
+++ b/drivers/net/wireless/mediatek/mt76/scan.c
@@ -52,11 +52,6 @@ mt76_scan_send_probe(struct mt76_dev *dev, struct cfg80211_ssid *ssid)
 		ether_addr_copy(hdr->addr3, req->bssid);
 	}
 
-	info = IEEE80211_SKB_CB(skb);
-	if (req->no_cck)
-		info->flags |= IEEE80211_TX_CTL_NO_CCK_RATE;
-	info->control.flags |= IEEE80211_TX_CTRL_DONT_USE_RATE_MASK;
-
 	if (req->ie_len)
 		skb_put_data(skb, req->ie, req->ie_len);
 
@@ -64,10 +59,20 @@ mt76_scan_send_probe(struct mt76_dev *dev, struct cfg80211_ssid *ssid)
 	skb_set_queue_mapping(skb, IEEE80211_AC_VO);
 
 	rcu_read_lock();
-	if (ieee80211_tx_prepare_skb(phy->hw, vif, skb, band, NULL))
-		mt76_tx(phy, NULL, mvif->wcid, skb);
-	else
+
+	if (!ieee80211_tx_prepare_skb(phy->hw, vif, skb, band, NULL)) {
 		ieee80211_free_txskb(phy->hw, skb);
+		goto out;
+	}
+
+	info = IEEE80211_SKB_CB(skb);
+	if (req->no_cck)
+		info->flags |= IEEE80211_TX_CTL_NO_CCK_RATE;
+	info->control.flags |= IEEE80211_TX_CTRL_DONT_USE_RATE_MASK;
+
+	mt76_tx(phy, NULL, mvif->wcid, skb);
+
+out:
 	rcu_read_unlock();
 }
 
-- 
2.47.1


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

* Re: [PATCH 6/8] mt76: only mark tx-status-failed frames as ACKed on mt76x0/2
  2025-03-11 10:36 ` [PATCH 6/8] mt76: only mark tx-status-failed frames as ACKed on mt76x0/2 Felix Fietkau
@ 2025-03-11 10:47   ` Felix Fietkau
  0 siblings, 0 replies; 13+ messages in thread
From: Felix Fietkau @ 2025-03-11 10:47 UTC (permalink / raw)
  To: linux-wireless

On 11.03.25 11:36, Felix Fietkau wrote:
> The interrupt status polling is unreliable, which can cause status events
> to get lost. On all newer chips, txs-timeout is an indication that the
> packet was either never sent, or never acked.
> Fixes issues with inactivity polling.
> 
> Signed-off-by: Felix Fietkau <nbd@nbd.name>

Forgot the wifi: prefix in the subject here - I will add it when I apply 
the patch.

- Felix

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

* Re: [PATCH 7/8] wifi: mt76: mt7996: implement driver specific get_txpower function
  2025-03-11 10:36 ` [PATCH 7/8] wifi: mt76: mt7996: implement driver specific get_txpower function Felix Fietkau
@ 2025-03-11 13:55   ` Lorenzo Bianconi
  2025-03-11 14:01     ` Felix Fietkau
  0 siblings, 1 reply; 13+ messages in thread
From: Lorenzo Bianconi @ 2025-03-11 13:55 UTC (permalink / raw)
  To: Felix Fietkau; +Cc: linux-wireless

[-- Attachment #1: Type: text/plain, Size: 2383 bytes --]

On Mar 11, Felix Fietkau wrote:
> Fixes reporting tx power for vifs that don't have a channel context
> assigned. Report the tx power of a phy that is covered by the vif's
> radio mask.
> 
> Signed-off-by: Felix Fietkau <nbd@nbd.name>
> ---
>  .../net/wireless/mediatek/mt76/mt7996/main.c  | 27 ++++++++++++++++++-
>  1 file changed, 26 insertions(+), 1 deletion(-)
> 
> diff --git a/drivers/net/wireless/mediatek/mt76/mt7996/main.c b/drivers/net/wireless/mediatek/mt76/mt7996/main.c
> index 886b6ef3462b..89fc3f102555 100644
> --- a/drivers/net/wireless/mediatek/mt76/mt7996/main.c
> +++ b/drivers/net/wireless/mediatek/mt76/mt7996/main.c
> @@ -602,6 +602,31 @@ static void mt7996_configure_filter(struct ieee80211_hw *hw,
>  	mutex_unlock(&dev->mt76.mutex);
>  }
>  
> +static int
> +mt7996_get_txpower(struct ieee80211_hw *hw, struct ieee80211_vif *vif, int *dbm)

I guess the signature here should be:

static int
mt7996_get_txpower(struct ieee80211_hw *hw, struct ieee80211_vif *vif, 
		   unsigned int link_id, int *dbm)
{
}

Regards,
Lorenzo

> +{
> +	struct mt7996_vif *mvif = (struct mt7996_vif *)vif->drv_priv;
> +	struct mt7996_phy *phy = mt7996_vif_link_phy(&mvif->deflink);
> +	struct mt7996_dev *dev = mt7996_hw_dev(hw);
> +	struct wireless_dev *wdev;
> +	int n_chains, delta, i;
> +
> +	if (!phy) {
> +		wdev = ieee80211_vif_to_wdev(vif);
> +		for (i = 0; i < hw->wiphy->n_radio; i++)
> +			if (wdev->radio_mask & BIT(i))
> +				phy = dev->radio_phy[i];
> +
> +		if (!phy)
> +			return -EINVAL;
> +	}
> +
> +	n_chains = hweight16(phy->mt76->chainmask);
> +	delta = mt76_tx_power_nss_delta(n_chains);
> +	*dbm = DIV_ROUND_UP(phy->mt76->txpower_cur + delta, 2);
> +
> +	return 0;
> +}
>  static u8
>  mt7996_get_rates_table(struct mt7996_phy *phy, struct ieee80211_bss_conf *conf,
>  		       bool beacon, bool mcast)
> @@ -1651,7 +1676,7 @@ const struct ieee80211_ops mt7996_ops = {
>  	.remain_on_channel = mt76_remain_on_channel,
>  	.cancel_remain_on_channel = mt76_cancel_remain_on_channel,
>  	.release_buffered_frames = mt76_release_buffered_frames,
> -	.get_txpower = mt76_get_txpower,
> +	.get_txpower = mt7996_get_txpower,
>  	.channel_switch_beacon = mt7996_channel_switch_beacon,
>  	.get_stats = mt7996_get_stats,
>  	.get_et_sset_count = mt7996_get_et_sset_count,
> -- 
> 2.47.1
> 
> 

[-- Attachment #2: signature.asc --]
[-- Type: application/pgp-signature, Size: 228 bytes --]

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

* Re: [PATCH 7/8] wifi: mt76: mt7996: implement driver specific get_txpower function
  2025-03-11 13:55   ` Lorenzo Bianconi
@ 2025-03-11 14:01     ` Felix Fietkau
  0 siblings, 0 replies; 13+ messages in thread
From: Felix Fietkau @ 2025-03-11 14:01 UTC (permalink / raw)
  To: Lorenzo Bianconi; +Cc: linux-wireless

On 11.03.25 14:55, Lorenzo Bianconi wrote:
> On Mar 11, Felix Fietkau wrote:
>> Fixes reporting tx power for vifs that don't have a channel context
>> assigned. Report the tx power of a phy that is covered by the vif's
>> radio mask.
>> 
>> Signed-off-by: Felix Fietkau <nbd@nbd.name>
>> ---
>>  .../net/wireless/mediatek/mt76/mt7996/main.c  | 27 ++++++++++++++++++-
>>  1 file changed, 26 insertions(+), 1 deletion(-)
>> 
>> diff --git a/drivers/net/wireless/mediatek/mt76/mt7996/main.c b/drivers/net/wireless/mediatek/mt76/mt7996/main.c
>> index 886b6ef3462b..89fc3f102555 100644
>> --- a/drivers/net/wireless/mediatek/mt76/mt7996/main.c
>> +++ b/drivers/net/wireless/mediatek/mt76/mt7996/main.c
>> @@ -602,6 +602,31 @@ static void mt7996_configure_filter(struct ieee80211_hw *hw,
>>  	mutex_unlock(&dev->mt76.mutex);
>>  }
>>  
>> +static int
>> +mt7996_get_txpower(struct ieee80211_hw *hw, struct ieee80211_vif *vif, int *dbm)
> 
> I guess the signature here should be:
> 
> static int
> mt7996_get_txpower(struct ieee80211_hw *hw, struct ieee80211_vif *vif,
> 		   unsigned int link_id, int *dbm)
> {
> }

Will fix, thanks.

- Felix

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

* RE: [PATCH 5/8] wifi: mt76: mt7996: use the correct vif link for scanning/roc
  2025-03-11 10:36 ` [PATCH 5/8] wifi: mt76: mt7996: use the correct vif " Felix Fietkau
@ 2025-03-12  2:08   ` Ping-Ke Shih
  2025-03-12  9:06     ` Felix Fietkau
  0 siblings, 1 reply; 13+ messages in thread
From: Ping-Ke Shih @ 2025-03-12  2:08 UTC (permalink / raw)
  To: Felix Fietkau, linux-wireless@vger.kernel.org

> @@ -839,11 +840,18 @@ void mt7996_mac_write_txwi(struct mt7996_dev *dev, __le32 *txwi,
>         bool beacon = !!(changed & (BSS_CHANGED_BEACON |
>                                     BSS_CHANGED_BEACON_ENABLED)) && (!inband_disc);
> 
> -       mvif = vif ? (struct mt76_vif_link *)vif->drv_priv : NULL;
> -       if (mvif) {
> -               omac_idx = mvif->omac_idx;
> -               wmm_idx = mvif->wmm_idx;
> -               band_idx = mvif->band_idx;
> +       if (vif) {
> +               mvif = (struct mt7996_vif *)vif->drv_priv;
> +               if (wcid->offchannel)
> +                       mlink = rcu_dereference(mvif->mt76.offchannel_link);

need a RCU read lock?

> +               if (!mlink)
> +                       mlink = &mvif->deflink.mt76;
> +       }
> +
> +       if (mlink) {
> +               omac_idx = mlink->omac_idx;
> +               wmm_idx = mlink->wmm_idx;
> +               band_idx = mlink->band_idx;
>         }
> 
>         if (inband_disc) {



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

* Re: [PATCH 5/8] wifi: mt76: mt7996: use the correct vif link for scanning/roc
  2025-03-12  2:08   ` Ping-Ke Shih
@ 2025-03-12  9:06     ` Felix Fietkau
  0 siblings, 0 replies; 13+ messages in thread
From: Felix Fietkau @ 2025-03-12  9:06 UTC (permalink / raw)
  To: Ping-Ke Shih, linux-wireless@vger.kernel.org

On 12.03.25 03:08, Ping-Ke Shih wrote:
>> @@ -839,11 +840,18 @@ void mt7996_mac_write_txwi(struct mt7996_dev *dev, __le32 *txwi,
>>         bool beacon = !!(changed & (BSS_CHANGED_BEACON |
>>                                     BSS_CHANGED_BEACON_ENABLED)) && (!inband_disc);
>> 
>> -       mvif = vif ? (struct mt76_vif_link *)vif->drv_priv : NULL;
>> -       if (mvif) {
>> -               omac_idx = mvif->omac_idx;
>> -               wmm_idx = mvif->wmm_idx;
>> -               band_idx = mvif->band_idx;
>> +       if (vif) {
>> +               mvif = (struct mt7996_vif *)vif->drv_priv;
>> +               if (wcid->offchannel)
>> +                       mlink = rcu_dereference(mvif->mt76.offchannel_link);
> 
> need a RCU read lock?

This path can only be reached from code that already holds the RCU lock.

- Felix

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

end of thread, other threads:[~2025-03-12  9:06 UTC | newest]

Thread overview: 13+ messages (download: mbox.gz follow: Atom feed
-- links below jump to the message on this page --
2025-03-11 10:36 [PATCH 1/8] wifi: mt76: mt7996: revise TXS size Felix Fietkau
2025-03-11 10:36 ` [PATCH 2/8] wifi: mt76: mt7996: fix SER reset trigger on WED reset Felix Fietkau
2025-03-11 10:36 ` [PATCH 3/8] wifi: mt76: mt7996: remove unnecessary key->cipher check for BIP frames Felix Fietkau
2025-03-11 10:36 ` [PATCH 4/8] wifi: mt76: scan: set vif offchannel link for scanning/roc Felix Fietkau
2025-03-11 10:36 ` [PATCH 5/8] wifi: mt76: mt7996: use the correct vif " Felix Fietkau
2025-03-12  2:08   ` Ping-Ke Shih
2025-03-12  9:06     ` Felix Fietkau
2025-03-11 10:36 ` [PATCH 6/8] mt76: only mark tx-status-failed frames as ACKed on mt76x0/2 Felix Fietkau
2025-03-11 10:47   ` Felix Fietkau
2025-03-11 10:36 ` [PATCH 7/8] wifi: mt76: mt7996: implement driver specific get_txpower function Felix Fietkau
2025-03-11 13:55   ` Lorenzo Bianconi
2025-03-11 14:01     ` Felix Fietkau
2025-03-11 10:36 ` [PATCH 8/8] wifi: mt76: scan: fix setting tx_info fields Felix Fietkau

This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox