Commit 0d4dafac authored by Rex Lu's avatar Rex Lu Committed by Felix Fietkau
Browse files

wifi: mt76: mt7996: Enable WED for MT7992 chipset



Introduce WED offload support for MT7992 chipset in MT7996 driver.

Co-developed-by: default avatarSujuan Chen <sujuan.chen@mediatek.com>
Signed-off-by: default avatarSujuan Chen <sujuan.chen@mediatek.com>
Co-developed-by: default avatarBenjamin Lin <benjamin-jw.lin@mediatek.com>
Signed-off-by: default avatarBenjamin Lin <benjamin-jw.lin@mediatek.com>
Signed-off-by: default avatarRex Lu <rex.lu@mediatek.com>
Co-developed-by: default avatarLorenzo Bianconi <lorenzo@kernel.org>
Signed-off-by: default avatarLorenzo Bianconi <lorenzo@kernel.org>
Link: https://patch.msgid.link/20250909-mt7996-rro-rework-v5-10-7d66f6eb7795@kernel.org


Signed-off-by: default avatarFelix Fietkau <nbd@nbd.name>
parent cffed52d
Loading
Loading
Loading
Loading
+25 −1
Original line number Diff line number Diff line
@@ -17,7 +17,7 @@ int mt7996_init_tx_queues(struct mt7996_phy *phy, int idx, int n_desc,
		ring_base += MT_TXQ_ID(0) * MT_RING_SIZE;
		idx -= MT_TXQ_ID(0);

		if (phy->mt76->band_idx == MT_BAND2)
		if (wed == &dev->mt76.mmio.wed_hif2)
			flags = MT_WED_Q_TX(0);
		else
			flags = MT_WED_Q_TX(idx);
@@ -429,6 +429,30 @@ static void mt7996_dma_enable(struct mt7996_dev *dev, bool reset)
		mt76_rmw(dev, MT_WFDMA_AXI_R2A_CTRL,
			 MT_WFDMA_AXI_R2A_CTRL_OUTSTAND_MASK, 0x14);

		if (dev->hif2->speed < PCIE_SPEED_5_0GT ||
		    (dev->hif2->speed == PCIE_SPEED_5_0GT &&
		     dev->hif2->width < PCIE_LNK_X2)) {
			mt76_rmw(dev, WF_WFDMA0_GLO_CFG_EXT0 + hif1_ofs,
				 WF_WFDMA0_GLO_CFG_EXT0_OUTSTAND_MASK,
				 FIELD_PREP(WF_WFDMA0_GLO_CFG_EXT0_OUTSTAND_MASK,
					    0x1));
			mt76_rmw(dev, MT_WFDMA_AXI_R2A_CTRL2,
				 MT_WFDMA_AXI_R2A_CTRL2_OUTSTAND_MASK,
				 FIELD_PREP(MT_WFDMA_AXI_R2A_CTRL2_OUTSTAND_MASK,
					    0x1));
		} else if (dev->hif2->speed < PCIE_SPEED_8_0GT ||
			   (dev->hif2->speed == PCIE_SPEED_8_0GT &&
			    dev->hif2->width < PCIE_LNK_X2)) {
			mt76_rmw(dev, WF_WFDMA0_GLO_CFG_EXT0 + hif1_ofs,
				 WF_WFDMA0_GLO_CFG_EXT0_OUTSTAND_MASK,
				 FIELD_PREP(WF_WFDMA0_GLO_CFG_EXT0_OUTSTAND_MASK,
					    0x2));
			mt76_rmw(dev, MT_WFDMA_AXI_R2A_CTRL2,
				 MT_WFDMA_AXI_R2A_CTRL2_OUTSTAND_MASK,
				 FIELD_PREP(MT_WFDMA_AXI_R2A_CTRL2_OUTSTAND_MASK,
					    0x2));
		}

		/* WFDMA rx threshold */
		mt76_wr(dev, MT_WFDMA0_PAUSE_RX_Q_45_TH + hif1_ofs, 0xc000c);
		mt76_wr(dev, MT_WFDMA0_PAUSE_RX_Q_67_TH + hif1_ofs, 0x10008);
+6 −5
Original line number Diff line number Diff line
@@ -666,7 +666,9 @@ static int mt7996_register_phy(struct mt7996_dev *dev, enum mt76_band_id band)
	if (!mt7996_band_valid(dev, band))
		return 0;

	if (is_mt7996(&dev->mt76) && band == MT_BAND2 && dev->hif2) {
	if (dev->hif2 &&
	    ((is_mt7996(&dev->mt76) && band == MT_BAND2) ||
	     (is_mt7992(&dev->mt76) && band == MT_BAND1))) {
		hif1_ofs = MT_WFDMA0_PCIE1(0) - MT_WFDMA0(0);
		wed = &dev->mt76.mmio.wed_hif2;
	}
@@ -724,10 +726,9 @@ static int mt7996_register_phy(struct mt7996_dev *dev, enum mt76_band_id band)
		goto error;

	if (wed == &dev->mt76.mmio.wed_hif2 && mtk_wed_device_active(wed)) {
		u32 irq_mask = dev->mt76.mmio.irqmask | MT_INT_TX_DONE_BAND2;

		mt76_wr(dev, MT_INT1_MASK_CSR, irq_mask);
		mtk_wed_device_start(&dev->mt76.mmio.wed_hif2, irq_mask);
		mt76_wr(dev, MT_INT_PCIE1_MASK_CSR, MT_INT_TX_RX_DONE_EXT);
		mtk_wed_device_start(&dev->mt76.mmio.wed_hif2,
				     MT_INT_TX_RX_DONE_EXT);
	}

	return 0;
+8 −9
Original line number Diff line number Diff line
@@ -2158,9 +2158,7 @@ mt7996_net_fill_forward_path(struct ieee80211_hw *hw,
	struct mt7996_dev *dev = mt7996_hw_dev(hw);
	struct mtk_wed_device *wed = &dev->mt76.mmio.wed;
	struct mt7996_sta_link *msta_link;
	struct mt7996_vif_link *link;
	struct mt76_vif_link *mlink;
	struct mt7996_phy *phy;

	mlink = rcu_dereference(mvif->mt76.link[msta->deflink_id]);
	if (!mlink)
@@ -2173,12 +2171,9 @@ mt7996_net_fill_forward_path(struct ieee80211_hw *hw,
	if (!msta_link->wcid.sta || msta_link->wcid.idx > MT7996_WTBL_STA)
		return -EIO;

	link = (struct mt7996_vif_link *)mlink;
	phy = mt7996_vif_link_phy(link);
	if (!phy)
		return -ENODEV;

	if (phy != &dev->phy && phy->mt76->band_idx == MT_BAND2)
	if (dev->hif2 &&
	    ((is_mt7996(&dev->mt76) && msta_link->wcid.phy_idx == MT_BAND2) ||
	     (is_mt7992(&dev->mt76) && msta_link->wcid.phy_idx == MT_BAND1)))
		wed = &dev->mt76.mmio.wed_hif2;

	if (!mtk_wed_device_active(wed))
@@ -2191,7 +2186,11 @@ mt7996_net_fill_forward_path(struct ieee80211_hw *hw,
	path->mtk_wdma.queue = 0;
	path->mtk_wdma.wcid = msta_link->wcid.idx;

	path->mtk_wdma.amsdu = mtk_wed_is_amsdu_supported(wed);
	if (ieee80211_hw_check(hw, SUPPORTS_AMSDU_IN_AMPDU) &&
	    mtk_wed_is_amsdu_supported(wed))
		path->mtk_wdma.amsdu = msta_link->wcid.amsdu;
	else
		path->mtk_wdma.amsdu = 0;
	ctx->dev = NULL;

	return 0;
+53 −19
Original line number Diff line number Diff line
@@ -459,14 +459,14 @@ int mt7996_mmio_wed_init(struct mt7996_dev *dev, void *pdev_ptr,
#ifdef CONFIG_NET_MEDIATEK_SOC_WED
	struct mtk_wed_device *wed = &dev->mt76.mmio.wed;
	struct pci_dev *pci_dev = pdev_ptr;
	u32 hif1_ofs = 0;
	u32 hif1_ofs;

	if (!wed_enable)
		return 0;

	dev->has_rro = true;

	hif1_ofs = MT_WFDMA0_PCIE1(0) - MT_WFDMA0(0);
	hif1_ofs = dev->hif2 ? MT_WFDMA0_PCIE1(0) - MT_WFDMA0(0) : 0;

	if (hif2)
		wed = &dev->mt76.mmio.wed_hif2;
@@ -491,10 +491,17 @@ int mt7996_mmio_wed_init(struct mt7996_dev *dev, void *pdev_ptr,
					     MT_TXQ_RING_BASE(0) +
					     MT7996_TXQ_BAND2 * MT_RING_SIZE;
		if (dev->has_rro) {
			if (is_mt7996(&dev->mt76)) {
				wed->wlan.txfree_tbit = ffs(MT_INT_RX_TXFREE_EXT) - 1;
				wed->wlan.wpdma_txfree = wed->wlan.phy_base + hif1_ofs +
							 MT_RXQ_RING_BASE(0) +
							 MT7996_RXQ_TXFREE2 * MT_RING_SIZE;
			wed->wlan.txfree_tbit = ffs(MT_INT_RX_TXFREE_EXT) - 1;
			} else {
				wed->wlan.txfree_tbit = ffs(MT_INT_RX_TXFREE_BAND1_EXT) - 1;
				wed->wlan.wpdma_txfree = wed->wlan.phy_base + hif1_ofs +
							 MT_RXQ_RING_BASE(0) +
							 MT7996_RXQ_MCU_WA_EXT * MT_RING_SIZE;
			}
		} else {
			wed->wlan.wpdma_txfree = wed->wlan.phy_base + hif1_ofs +
						 MT_RXQ_RING_BASE(0) +
@@ -504,8 +511,8 @@ int mt7996_mmio_wed_init(struct mt7996_dev *dev, void *pdev_ptr,

		wed->wlan.wpdma_rx_glo = wed->wlan.phy_base + hif1_ofs + MT_WFDMA0_GLO_CFG;
		wed->wlan.wpdma_rx[0] = wed->wlan.phy_base + hif1_ofs +
					MT_RXQ_RING_BASE(MT7996_RXQ_BAND0) +
					MT7996_RXQ_BAND0 * MT_RING_SIZE;
					MT_RXQ_RING_BASE(MT7996_RXQ_BAND2) +
					MT7996_RXQ_BAND2 * MT_RING_SIZE;

		wed->wlan.id = MT7996_DEVICE_ID_2;
		wed->wlan.tx_tbit[0] = ffs(MT_INT_TX_DONE_BAND2) - 1;
@@ -525,9 +532,19 @@ int mt7996_mmio_wed_init(struct mt7996_dev *dev, void *pdev_ptr,
		wed->wlan.wpdma_rx_rro[0] = wed->wlan.phy_base +
					    MT_RXQ_RING_BASE(MT7996_RXQ_RRO_BAND0) +
					    MT7996_RXQ_RRO_BAND0 * MT_RING_SIZE;
		if (is_mt7996(&dev->mt76)) {
			wed->wlan.wpdma_rx_rro[1] = wed->wlan.phy_base + hif1_ofs +
						    MT_RXQ_RING_BASE(MT7996_RXQ_RRO_BAND2) +
						    MT7996_RXQ_RRO_BAND2 * MT_RING_SIZE;
		} else {
			wed->wlan.wpdma_rx_rro[1] = wed->wlan.phy_base + hif1_ofs +
						    MT_RXQ_RING_BASE(MT7996_RXQ_RRO_BAND1) +
						    MT7996_RXQ_RRO_BAND1 * MT_RING_SIZE;
			wed->wlan.wpdma_rx[1] = wed->wlan.phy_base + hif1_ofs +
						MT_RXQ_RING_BASE(MT7996_RXQ_BAND1) +
						MT7996_RXQ_BAND1 * MT_RING_SIZE;
		}

		wed->wlan.wpdma_rx_pg = wed->wlan.phy_base +
					MT_RXQ_RING_BASE(MT7996_RXQ_MSDU_PG_BAND0) +
					MT7996_RXQ_MSDU_PG_BAND0 * MT_RING_SIZE;
@@ -537,10 +554,14 @@ int mt7996_mmio_wed_init(struct mt7996_dev *dev, void *pdev_ptr,
		wed->wlan.rx_size = SKB_WITH_OVERHEAD(MT_RX_BUF_SIZE);

		wed->wlan.rx_tbit[0] = ffs(MT_INT_RX_DONE_BAND0) - 1;
		wed->wlan.rx_tbit[1] = ffs(MT_INT_RX_DONE_BAND2) - 1;

		wed->wlan.rro_rx_tbit[0] = ffs(MT_INT_RX_DONE_RRO_BAND0) - 1;
		if (is_mt7996(&dev->mt76)) {
			wed->wlan.rx_tbit[1] = ffs(MT_INT_RX_DONE_BAND2) - 1;
			wed->wlan.rro_rx_tbit[1] = ffs(MT_INT_RX_DONE_RRO_BAND2) - 1;
		} else {
			wed->wlan.rx_tbit[1] = ffs(MT_INT_RX_DONE_BAND1) - 1;
			wed->wlan.rro_rx_tbit[1] = ffs(MT_INT_RX_DONE_RRO_BAND1) - 1;
		}

		wed->wlan.rx_pg_tbit[0] = ffs(MT_INT_RX_DONE_MSDU_PG_BAND0) - 1;
		wed->wlan.rx_pg_tbit[1] = ffs(MT_INT_RX_DONE_MSDU_PG_BAND1) - 1;
@@ -548,16 +569,27 @@ int mt7996_mmio_wed_init(struct mt7996_dev *dev, void *pdev_ptr,

		wed->wlan.tx_tbit[0] = ffs(MT_INT_TX_DONE_BAND0) - 1;
		wed->wlan.tx_tbit[1] = ffs(MT_INT_TX_DONE_BAND1) - 1;
		if (is_mt7996(&dev->mt76)) {
			if (dev->has_rro) {
			wed->wlan.wpdma_txfree = wed->wlan.phy_base + MT_RXQ_RING_BASE(0) +
				wed->wlan.wpdma_txfree = wed->wlan.phy_base +
							 MT_RXQ_RING_BASE(0) +
							 MT7996_RXQ_TXFREE0 * MT_RING_SIZE;
				wed->wlan.txfree_tbit = ffs(MT_INT_RX_TXFREE_MAIN) - 1;
			} else {
				wed->wlan.wpdma_txfree = wed->wlan.phy_base +
							 MT_RXQ_RING_BASE(0) +
							 MT7996_RXQ_MCU_WA_MAIN * MT_RING_SIZE;
				wed->wlan.txfree_tbit = ffs(MT_INT_RX_DONE_WA_MAIN) - 1;
			}
		} else {
			wed->wlan.txfree_tbit = ffs(MT_INT_RX_DONE_WA_MAIN) - 1;
			wed->wlan.wpdma_txfree = wed->wlan.phy_base + MT_RXQ_RING_BASE(0) +
						  MT7996_RXQ_MCU_WA_MAIN * MT_RING_SIZE;
		}
		dev->mt76.rx_token_size = MT7996_TOKEN_SIZE + wed->wlan.rx_npkt;

		if (dev->hif2 && is_mt7992(&dev->mt76))
			wed->wlan.id = 0x7992;
	}

	wed->wlan.nbuf = MT7996_HW_TOKEN_SIZE;
@@ -576,8 +608,10 @@ int mt7996_mmio_wed_init(struct mt7996_dev *dev, void *pdev_ptr,
		wed->wlan.reset_complete = mt76_wed_reset_complete;
	}

	if (mtk_wed_device_attach(wed))
	if (mtk_wed_device_attach(wed)) {
		dev->has_rro = false;
		return 0;
	}

	*irq = wed->irq;
	dev->mt76.dma_dev = wed->dev;
+3 −0
Original line number Diff line number Diff line
@@ -280,6 +280,9 @@ struct mt7996_hif {
	struct device *dev;
	void __iomem *regs;
	int irq;

	enum pci_bus_speed speed;
	enum pcie_link_width width;
};

struct mt7996_wed_rro_addr {
Loading