linux-kernel.vger.kernel.org archive mirror
 help / color / mirror / Atom feed
* [PATCH 01/14] net: ethernet: mtk_eth_soc: account for vlan in rx header length
@ 2022-11-07 18:54 Felix Fietkau
  2022-11-07 18:54 ` [PATCH 02/14] net: ethernet: mtk_eth_soc: increase tx ring side for QDMA devices Felix Fietkau
                   ` (13 more replies)
  0 siblings, 14 replies; 37+ messages in thread
From: Felix Fietkau @ 2022-11-07 18:54 UTC (permalink / raw)
  To: netdev, John Crispin, Sean Wang, Mark Lee, David S. Miller,
	Eric Dumazet, Jakub Kicinski, Paolo Abeni, Matthias Brugger
  Cc: linux-arm-kernel, linux-mediatek, linux-kernel

This may be needed for correct MTU settings on devices using DSA

Signed-off-by: Felix Fietkau <nbd@nbd.name>
---
 drivers/net/ethernet/mediatek/mtk_eth_soc.h | 2 +-
 1 file changed, 1 insertion(+), 1 deletion(-)

diff --git a/drivers/net/ethernet/mediatek/mtk_eth_soc.h b/drivers/net/ethernet/mediatek/mtk_eth_soc.h
index 589f27ddc401..dcf2a0d5da33 100644
--- a/drivers/net/ethernet/mediatek/mtk_eth_soc.h
+++ b/drivers/net/ethernet/mediatek/mtk_eth_soc.h
@@ -29,7 +29,7 @@
 #define MTK_TX_DMA_BUF_LEN_V2	0xffff
 #define MTK_DMA_SIZE		512
 #define MTK_MAC_COUNT		2
-#define MTK_RX_ETH_HLEN		(ETH_HLEN + ETH_FCS_LEN)
+#define MTK_RX_ETH_HLEN		(VLAN_ETH_HLEN + ETH_HLEN + ETH_FCS_LEN)
 #define MTK_RX_HLEN		(NET_SKB_PAD + MTK_RX_ETH_HLEN + NET_IP_ALIGN)
 #define MTK_DMA_DUMMY_DESC	0xffffffff
 #define MTK_DEFAULT_MSG_ENABLE	(NETIF_MSG_DRV | \
-- 
2.38.1


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

* [PATCH 02/14] net: ethernet: mtk_eth_soc: increase tx ring side for QDMA devices
  2022-11-07 18:54 [PATCH 01/14] net: ethernet: mtk_eth_soc: account for vlan in rx header length Felix Fietkau
@ 2022-11-07 18:54 ` Felix Fietkau
  2022-11-07 18:54 ` [PATCH 03/14] net: ethernet: mtk_eth_soc: avoid port_mg assignment on MT7622 and newer Felix Fietkau
                   ` (12 subsequent siblings)
  13 siblings, 0 replies; 37+ messages in thread
From: Felix Fietkau @ 2022-11-07 18:54 UTC (permalink / raw)
  To: netdev, John Crispin, Sean Wang, Mark Lee, David S. Miller,
	Eric Dumazet, Jakub Kicinski, Paolo Abeni, Matthias Brugger
  Cc: linux-arm-kernel, linux-mediatek, linux-kernel

In order to use the hardware traffic shaper feature, a larger tx ring is
needed, especially for the scratch ring, which the hardware shaper uses to
reorder packets.

Signed-off-by: Felix Fietkau <nbd@nbd.name>
---
 drivers/net/ethernet/mediatek/mtk_eth_soc.c | 38 ++++++++++++---------
 drivers/net/ethernet/mediatek/mtk_eth_soc.h |  1 +
 2 files changed, 23 insertions(+), 16 deletions(-)

diff --git a/drivers/net/ethernet/mediatek/mtk_eth_soc.c b/drivers/net/ethernet/mediatek/mtk_eth_soc.c
index 789268b15106..02a57729db28 100644
--- a/drivers/net/ethernet/mediatek/mtk_eth_soc.c
+++ b/drivers/net/ethernet/mediatek/mtk_eth_soc.c
@@ -938,7 +938,7 @@ static int mtk_init_fq_dma(struct mtk_eth *eth)
 {
 	const struct mtk_soc_data *soc = eth->soc;
 	dma_addr_t phy_ring_tail;
-	int cnt = MTK_DMA_SIZE;
+	int cnt = MTK_QDMA_RING_SIZE;
 	dma_addr_t dma_addr;
 	int i;
 
@@ -2202,19 +2202,25 @@ static int mtk_tx_alloc(struct mtk_eth *eth)
 	struct mtk_tx_ring *ring = &eth->tx_ring;
 	int i, sz = soc->txrx.txd_size;
 	struct mtk_tx_dma_v2 *txd;
+	int ring_size;
 
-	ring->buf = kcalloc(MTK_DMA_SIZE, sizeof(*ring->buf),
+	if (MTK_HAS_CAPS(soc->caps, MTK_QDMA))
+		ring_size = MTK_QDMA_RING_SIZE;
+	else
+		ring_size = MTK_DMA_SIZE;
+
+	ring->buf = kcalloc(ring_size, sizeof(*ring->buf),
 			       GFP_KERNEL);
 	if (!ring->buf)
 		goto no_tx_mem;
 
-	ring->dma = dma_alloc_coherent(eth->dma_dev, MTK_DMA_SIZE * sz,
+	ring->dma = dma_alloc_coherent(eth->dma_dev, ring_size * sz,
 				       &ring->phys, GFP_KERNEL);
 	if (!ring->dma)
 		goto no_tx_mem;
 
-	for (i = 0; i < MTK_DMA_SIZE; i++) {
-		int next = (i + 1) % MTK_DMA_SIZE;
+	for (i = 0; i < ring_size; i++) {
+		int next = (i + 1) % ring_size;
 		u32 next_ptr = ring->phys + next * sz;
 
 		txd = ring->dma + i * sz;
@@ -2234,22 +2240,22 @@ static int mtk_tx_alloc(struct mtk_eth *eth)
 	 * descriptors in ring->dma_pdma.
 	 */
 	if (!MTK_HAS_CAPS(soc->caps, MTK_QDMA)) {
-		ring->dma_pdma = dma_alloc_coherent(eth->dma_dev, MTK_DMA_SIZE * sz,
+		ring->dma_pdma = dma_alloc_coherent(eth->dma_dev, ring_size * sz,
 						    &ring->phys_pdma, GFP_KERNEL);
 		if (!ring->dma_pdma)
 			goto no_tx_mem;
 
-		for (i = 0; i < MTK_DMA_SIZE; i++) {
+		for (i = 0; i < ring_size; i++) {
 			ring->dma_pdma[i].txd2 = TX_DMA_DESP2_DEF;
 			ring->dma_pdma[i].txd4 = 0;
 		}
 	}
 
-	ring->dma_size = MTK_DMA_SIZE;
-	atomic_set(&ring->free_count, MTK_DMA_SIZE - 2);
+	ring->dma_size = ring_size;
+	atomic_set(&ring->free_count, ring_size - 2);
 	ring->next_free = ring->dma;
 	ring->last_free = (void *)txd;
-	ring->last_free_ptr = (u32)(ring->phys + ((MTK_DMA_SIZE - 1) * sz));
+	ring->last_free_ptr = (u32)(ring->phys + ((ring_size - 1) * sz));
 	ring->thresh = MAX_SKB_FRAGS;
 
 	/* make sure that all changes to the dma ring are flushed before we
@@ -2261,14 +2267,14 @@ static int mtk_tx_alloc(struct mtk_eth *eth)
 		mtk_w32(eth, ring->phys, soc->reg_map->qdma.ctx_ptr);
 		mtk_w32(eth, ring->phys, soc->reg_map->qdma.dtx_ptr);
 		mtk_w32(eth,
-			ring->phys + ((MTK_DMA_SIZE - 1) * sz),
+			ring->phys + ((ring_size - 1) * sz),
 			soc->reg_map->qdma.crx_ptr);
 		mtk_w32(eth, ring->last_free_ptr, soc->reg_map->qdma.drx_ptr);
 		mtk_w32(eth, (QDMA_RES_THRES << 8) | QDMA_RES_THRES,
 			soc->reg_map->qdma.qtx_cfg);
 	} else {
 		mtk_w32(eth, ring->phys_pdma, MT7628_TX_BASE_PTR0);
-		mtk_w32(eth, MTK_DMA_SIZE, MT7628_TX_MAX_CNT0);
+		mtk_w32(eth, ring_size, MT7628_TX_MAX_CNT0);
 		mtk_w32(eth, 0, MT7628_TX_CTX_IDX0);
 		mtk_w32(eth, MT7628_PST_DTX_IDX0, soc->reg_map->pdma.rst_idx);
 	}
@@ -2286,7 +2292,7 @@ static void mtk_tx_clean(struct mtk_eth *eth)
 	int i;
 
 	if (ring->buf) {
-		for (i = 0; i < MTK_DMA_SIZE; i++)
+		for (i = 0; i < ring->dma_size; i++)
 			mtk_tx_unmap(eth, &ring->buf[i], NULL, false);
 		kfree(ring->buf);
 		ring->buf = NULL;
@@ -2294,14 +2300,14 @@ static void mtk_tx_clean(struct mtk_eth *eth)
 
 	if (ring->dma) {
 		dma_free_coherent(eth->dma_dev,
-				  MTK_DMA_SIZE * soc->txrx.txd_size,
+				  ring->dma_size * soc->txrx.txd_size,
 				  ring->dma, ring->phys);
 		ring->dma = NULL;
 	}
 
 	if (ring->dma_pdma) {
 		dma_free_coherent(eth->dma_dev,
-				  MTK_DMA_SIZE * soc->txrx.txd_size,
+				  ring->dma_size * soc->txrx.txd_size,
 				  ring->dma_pdma, ring->phys_pdma);
 		ring->dma_pdma = NULL;
 	}
@@ -2821,7 +2827,7 @@ static void mtk_dma_free(struct mtk_eth *eth)
 			netdev_reset_queue(eth->netdev[i]);
 	if (eth->scratch_ring) {
 		dma_free_coherent(eth->dma_dev,
-				  MTK_DMA_SIZE * soc->txrx.txd_size,
+				  MTK_QDMA_RING_SIZE * soc->txrx.txd_size,
 				  eth->scratch_ring, eth->phy_scratch_ring);
 		eth->scratch_ring = NULL;
 		eth->phy_scratch_ring = 0;
diff --git a/drivers/net/ethernet/mediatek/mtk_eth_soc.h b/drivers/net/ethernet/mediatek/mtk_eth_soc.h
index dcf2a0d5da33..7c0b6c0c05d8 100644
--- a/drivers/net/ethernet/mediatek/mtk_eth_soc.h
+++ b/drivers/net/ethernet/mediatek/mtk_eth_soc.h
@@ -27,6 +27,7 @@
 #define MTK_MAX_RX_LENGTH_2K	2048
 #define MTK_TX_DMA_BUF_LEN	0x3fff
 #define MTK_TX_DMA_BUF_LEN_V2	0xffff
+#define MTK_QDMA_RING_SIZE	2048
 #define MTK_DMA_SIZE		512
 #define MTK_MAC_COUNT		2
 #define MTK_RX_ETH_HLEN		(VLAN_ETH_HLEN + ETH_HLEN + ETH_FCS_LEN)
-- 
2.38.1


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

* [PATCH 03/14] net: ethernet: mtk_eth_soc: avoid port_mg assignment on MT7622 and newer
  2022-11-07 18:54 [PATCH 01/14] net: ethernet: mtk_eth_soc: account for vlan in rx header length Felix Fietkau
  2022-11-07 18:54 ` [PATCH 02/14] net: ethernet: mtk_eth_soc: increase tx ring side for QDMA devices Felix Fietkau
@ 2022-11-07 18:54 ` Felix Fietkau
  2022-11-07 18:54 ` [PATCH 04/14] net: ethernet: mtk_eth_soc: implement multi-queue support for per-port queues Felix Fietkau
                   ` (11 subsequent siblings)
  13 siblings, 0 replies; 37+ messages in thread
From: Felix Fietkau @ 2022-11-07 18:54 UTC (permalink / raw)
  To: netdev, John Crispin, Sean Wang, Mark Lee, David S. Miller,
	Eric Dumazet, Jakub Kicinski, Paolo Abeni, Matthias Brugger
  Cc: linux-arm-kernel, linux-mediatek, linux-kernel

On newer chips, this field is unused and contains some bits related to queue
assignment. Initialize it to 0 in those cases.
Fix offload_version on MT7621 and MT7623, which still need the previous value.

Signed-off-by: Felix Fietkau <nbd@nbd.name>
---
 drivers/net/ethernet/mediatek/mtk_eth_soc.c | 4 ++--
 drivers/net/ethernet/mediatek/mtk_ppe.c     | 4 +++-
 2 files changed, 5 insertions(+), 3 deletions(-)

diff --git a/drivers/net/ethernet/mediatek/mtk_eth_soc.c b/drivers/net/ethernet/mediatek/mtk_eth_soc.c
index 02a57729db28..9f607c80f49c 100644
--- a/drivers/net/ethernet/mediatek/mtk_eth_soc.c
+++ b/drivers/net/ethernet/mediatek/mtk_eth_soc.c
@@ -4243,7 +4243,7 @@ static const struct mtk_soc_data mt7621_data = {
 	.hw_features = MTK_HW_FEATURES,
 	.required_clks = MT7621_CLKS_BITMAP,
 	.required_pctl = false,
-	.offload_version = 2,
+	.offload_version = 1,
 	.hash_offset = 2,
 	.foe_entry_size = sizeof(struct mtk_foe_entry) - 16,
 	.txrx = {
@@ -4282,7 +4282,7 @@ static const struct mtk_soc_data mt7623_data = {
 	.hw_features = MTK_HW_FEATURES,
 	.required_clks = MT7623_CLKS_BITMAP,
 	.required_pctl = true,
-	.offload_version = 2,
+	.offload_version = 1,
 	.hash_offset = 2,
 	.foe_entry_size = sizeof(struct mtk_foe_entry) - 16,
 	.txrx = {
diff --git a/drivers/net/ethernet/mediatek/mtk_ppe.c b/drivers/net/ethernet/mediatek/mtk_ppe.c
index 2d8ca99f2467..3ee2bf53f9e5 100644
--- a/drivers/net/ethernet/mediatek/mtk_ppe.c
+++ b/drivers/net/ethernet/mediatek/mtk_ppe.c
@@ -175,6 +175,8 @@ int mtk_foe_entry_prepare(struct mtk_eth *eth, struct mtk_foe_entry *entry,
 		val = FIELD_PREP(MTK_FOE_IB2_DEST_PORT_V2, pse_port) |
 		      FIELD_PREP(MTK_FOE_IB2_PORT_AG_V2, 0xf);
 	} else {
+		int port_mg = eth->soc->offload_version > 1 ? 0 : 0x3f;
+
 		val = FIELD_PREP(MTK_FOE_IB1_STATE, MTK_FOE_STATE_BIND) |
 		      FIELD_PREP(MTK_FOE_IB1_PACKET_TYPE, type) |
 		      FIELD_PREP(MTK_FOE_IB1_UDP, l4proto == IPPROTO_UDP) |
@@ -182,7 +184,7 @@ int mtk_foe_entry_prepare(struct mtk_eth *eth, struct mtk_foe_entry *entry,
 		entry->ib1 = val;
 
 		val = FIELD_PREP(MTK_FOE_IB2_DEST_PORT, pse_port) |
-		      FIELD_PREP(MTK_FOE_IB2_PORT_MG, 0x3f) |
+		      FIELD_PREP(MTK_FOE_IB2_PORT_MG, port_mg) |
 		      FIELD_PREP(MTK_FOE_IB2_PORT_AG, 0x1f);
 	}
 
-- 
2.38.1


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

* [PATCH 04/14] net: ethernet: mtk_eth_soc: implement multi-queue support for per-port queues
  2022-11-07 18:54 [PATCH 01/14] net: ethernet: mtk_eth_soc: account for vlan in rx header length Felix Fietkau
  2022-11-07 18:54 ` [PATCH 02/14] net: ethernet: mtk_eth_soc: increase tx ring side for QDMA devices Felix Fietkau
  2022-11-07 18:54 ` [PATCH 03/14] net: ethernet: mtk_eth_soc: avoid port_mg assignment on MT7622 and newer Felix Fietkau
@ 2022-11-07 18:54 ` Felix Fietkau
  2022-11-07 18:54 ` [PATCH 05/14] net: dsa: tag_mtk: assign " Felix Fietkau
                   ` (10 subsequent siblings)
  13 siblings, 0 replies; 37+ messages in thread
From: Felix Fietkau @ 2022-11-07 18:54 UTC (permalink / raw)
  To: netdev, John Crispin, Sean Wang, Mark Lee, David S. Miller,
	Eric Dumazet, Jakub Kicinski, Paolo Abeni, Matthias Brugger,
	Russell King
  Cc: linux-arm-kernel, linux-mediatek, linux-kernel

When sending traffic to multiple ports with different link speeds, queued
packets to one port can drown out tx to other ports.
In order to better handle transmission to multiple ports, use the hardware
shaper feature to implement weighted fair queueing between ports.
Weight and maximum rate are automatically adjusted based on the link speed
of the port.
The first 3 queues are unrestricted and reserved for non-DSA direct tx on
GMAC ports. The following queues are automatically assigned by the MTK DSA
tag driver based on the target port number.
The PPE offload code configures the queues for offloaded traffic in the same
way.
This feature is only supported on devices supporting QDMA. All queues still
share the same DMA ring and descriptor pool.

Signed-off-by: Felix Fietkau <nbd@nbd.name>
---
 drivers/net/ethernet/mediatek/mtk_eth_soc.c | 282 ++++++++++++++++----
 drivers/net/ethernet/mediatek/mtk_eth_soc.h |  26 +-
 2 files changed, 259 insertions(+), 49 deletions(-)

diff --git a/drivers/net/ethernet/mediatek/mtk_eth_soc.c b/drivers/net/ethernet/mediatek/mtk_eth_soc.c
index 9f607c80f49c..ab31dda2cd66 100644
--- a/drivers/net/ethernet/mediatek/mtk_eth_soc.c
+++ b/drivers/net/ethernet/mediatek/mtk_eth_soc.c
@@ -54,6 +54,7 @@ static const struct mtk_reg_map mtk_reg_map = {
 	},
 	.qdma = {
 		.qtx_cfg	= 0x1800,
+		.qtx_sch	= 0x1804,
 		.rx_ptr		= 0x1900,
 		.rx_cnt_cfg	= 0x1904,
 		.qcrx_ptr	= 0x1908,
@@ -61,6 +62,7 @@ static const struct mtk_reg_map mtk_reg_map = {
 		.rst_idx	= 0x1a08,
 		.delay_irq	= 0x1a0c,
 		.fc_th		= 0x1a10,
+		.tx_sch_rate	= 0x1a14,
 		.int_grp	= 0x1a20,
 		.hred		= 0x1a44,
 		.ctx_ptr	= 0x1b00,
@@ -113,6 +115,7 @@ static const struct mtk_reg_map mt7986_reg_map = {
 	},
 	.qdma = {
 		.qtx_cfg	= 0x4400,
+		.qtx_sch	= 0x4404,
 		.rx_ptr		= 0x4500,
 		.rx_cnt_cfg	= 0x4504,
 		.qcrx_ptr	= 0x4508,
@@ -130,6 +133,7 @@ static const struct mtk_reg_map mt7986_reg_map = {
 		.fq_tail	= 0x4724,
 		.fq_count	= 0x4728,
 		.fq_blen	= 0x472c,
+		.tx_sch_rate	= 0x4798,
 	},
 	.gdm1_cnt		= 0x1c00,
 	.gdma_to_ppe		= 0x3333,
@@ -613,6 +617,75 @@ static void mtk_mac_link_down(struct phylink_config *config, unsigned int mode,
 	mtk_w32(mac->hw, mcr, MTK_MAC_MCR(mac->id));
 }
 
+static void mtk_set_queue_speed(struct mtk_eth *eth, unsigned int idx,
+				int speed)
+{
+	const struct mtk_soc_data *soc = eth->soc;
+	u32 ofs, val;
+
+	if (!MTK_HAS_CAPS(soc->caps, MTK_QDMA))
+		return;
+
+	val = MTK_QTX_SCH_MIN_RATE_EN |
+	      /* minimum: 10 Mbps */
+	      FIELD_PREP(MTK_QTX_SCH_MIN_RATE_MAN, 1) |
+	      FIELD_PREP(MTK_QTX_SCH_MIN_RATE_EXP, 4) |
+	      MTK_QTX_SCH_LEAKY_BUCKET_SIZE;
+	if (!MTK_HAS_CAPS(eth->soc->caps, MTK_NETSYS_V2))
+		val |= MTK_QTX_SCH_LEAKY_BUCKET_EN;
+
+	if (IS_ENABLED(CONFIG_SOC_MT7621)) {
+		switch (speed) {
+		case SPEED_10:
+			val |= MTK_QTX_SCH_MAX_RATE_EN |
+			       FIELD_PREP(MTK_QTX_SCH_MAX_RATE_MAN, 103) |
+			       FIELD_PREP(MTK_QTX_SCH_MAX_RATE_EXP, 2) |
+			       FIELD_PREP(MTK_QTX_SCH_MAX_RATE_WEIGHT, 1);
+			break;
+		case SPEED_100:
+			val |= MTK_QTX_SCH_MAX_RATE_EN |
+			       FIELD_PREP(MTK_QTX_SCH_MAX_RATE_MAN, 103) |
+			       FIELD_PREP(MTK_QTX_SCH_MAX_RATE_EXP, 3);
+			       FIELD_PREP(MTK_QTX_SCH_MAX_RATE_WEIGHT, 1);
+			break;
+		case SPEED_1000:
+			val |= MTK_QTX_SCH_MAX_RATE_EN |
+			       FIELD_PREP(MTK_QTX_SCH_MAX_RATE_MAN, 105) |
+			       FIELD_PREP(MTK_QTX_SCH_MAX_RATE_EXP, 4) |
+			       FIELD_PREP(MTK_QTX_SCH_MAX_RATE_WEIGHT, 10);
+			break;
+		default:
+			break;
+		}
+	} else {
+		switch (speed) {
+		case SPEED_10:
+			val |= MTK_QTX_SCH_MAX_RATE_EN |
+			       FIELD_PREP(MTK_QTX_SCH_MAX_RATE_MAN, 1) |
+			       FIELD_PREP(MTK_QTX_SCH_MAX_RATE_EXP, 4) |
+			       FIELD_PREP(MTK_QTX_SCH_MAX_RATE_WEIGHT, 1);
+			break;
+		case SPEED_100:
+			val |= MTK_QTX_SCH_MAX_RATE_EN |
+			       FIELD_PREP(MTK_QTX_SCH_MAX_RATE_MAN, 1) |
+			       FIELD_PREP(MTK_QTX_SCH_MAX_RATE_EXP, 5);
+			       FIELD_PREP(MTK_QTX_SCH_MAX_RATE_WEIGHT, 1);
+			break;
+		case SPEED_1000:
+			val |= MTK_QTX_SCH_MAX_RATE_EN |
+			       FIELD_PREP(MTK_QTX_SCH_MAX_RATE_MAN, 10) |
+			       FIELD_PREP(MTK_QTX_SCH_MAX_RATE_EXP, 5) |
+			       FIELD_PREP(MTK_QTX_SCH_MAX_RATE_WEIGHT, 10);
+			break;
+		default:
+			break;
+		}
+	}
+
+	ofs = MTK_QTX_OFFSET * idx;
+	mtk_w32(eth, val, soc->reg_map->qdma.qtx_sch + ofs);
+}
+
 static void mtk_mac_link_up(struct phylink_config *config,
 			    struct phy_device *phy,
 			    unsigned int mode, phy_interface_t interface,
@@ -638,6 +711,8 @@ static void mtk_mac_link_up(struct phylink_config *config,
 		break;
 	}
 
+	mtk_set_queue_speed(mac->hw, mac->id, speed);
+
 	/* Configure duplex */
 	if (duplex == DUPLEX_FULL)
 		mcr |= MAC_MCR_FORCE_DPX;
@@ -1099,7 +1174,8 @@ static void mtk_tx_set_dma_desc_v1(struct net_device *dev, void *txd,
 
 	WRITE_ONCE(desc->txd1, info->addr);
 
-	data = TX_DMA_SWC | TX_DMA_PLEN0(info->size);
+	data = TX_DMA_SWC | TX_DMA_PLEN0(info->size) |
+	       FIELD_PREP(TX_DMA_PQID, info->qid);
 	if (info->last)
 		data |= TX_DMA_LS0;
 	WRITE_ONCE(desc->txd3, data);
@@ -1133,9 +1209,6 @@ static void mtk_tx_set_dma_desc_v2(struct net_device *dev, void *txd,
 		data |= TX_DMA_LS0;
 	WRITE_ONCE(desc->txd3, data);
 
-	if (!info->qid && mac->id)
-		info->qid = MTK_QDMA_GMAC2_QID;
-
 	data = (mac->id + 1) << TX_DMA_FPORT_SHIFT_V2; /* forward port */
 	data |= TX_DMA_SWC_V2 | QID_BITS_V2(info->qid);
 	WRITE_ONCE(desc->txd4, data);
@@ -1179,11 +1252,12 @@ static int mtk_tx_map(struct sk_buff *skb, struct net_device *dev,
 		.gso = gso,
 		.csum = skb->ip_summed == CHECKSUM_PARTIAL,
 		.vlan = skb_vlan_tag_present(skb),
-		.qid = skb->mark & MTK_QDMA_TX_MASK,
+		.qid = skb_get_queue_mapping(skb),
 		.vlan_tci = skb_vlan_tag_get(skb),
 		.first = true,
 		.last = !skb_is_nonlinear(skb),
 	};
+	struct netdev_queue *txq;
 	struct mtk_mac *mac = netdev_priv(dev);
 	struct mtk_eth *eth = mac->hw;
 	const struct mtk_soc_data *soc = eth->soc;
@@ -1191,8 +1265,10 @@ static int mtk_tx_map(struct sk_buff *skb, struct net_device *dev,
 	struct mtk_tx_dma *itxd_pdma, *txd_pdma;
 	struct mtk_tx_buf *itx_buf, *tx_buf;
 	int i, n_desc = 1;
+	int queue = skb_get_queue_mapping(skb);
 	int k = 0;
 
+	txq = netdev_get_tx_queue(dev, queue);
 	itxd = ring->next_free;
 	itxd_pdma = qdma_to_pdma(ring, itxd);
 	if (itxd == ring->last_free)
@@ -1241,7 +1317,7 @@ static int mtk_tx_map(struct sk_buff *skb, struct net_device *dev,
 			memset(&txd_info, 0, sizeof(struct mtk_tx_dma_desc_info));
 			txd_info.size = min_t(unsigned int, frag_size,
 					      soc->txrx.dma_max_len);
-			txd_info.qid = skb->mark & MTK_QDMA_TX_MASK;
+			txd_info.qid = queue;
 			txd_info.last = i == skb_shinfo(skb)->nr_frags - 1 &&
 					!(frag_size - txd_info.size);
 			txd_info.addr = skb_frag_dma_map(eth->dma_dev, frag,
@@ -1280,7 +1356,7 @@ static int mtk_tx_map(struct sk_buff *skb, struct net_device *dev,
 			txd_pdma->txd2 |= TX_DMA_LS1;
 	}
 
-	netdev_sent_queue(dev, skb->len);
+	netdev_tx_sent_queue(txq, skb->len);
 	skb_tx_timestamp(skb);
 
 	ring->next_free = mtk_qdma_phys_to_virt(ring, txd->txd2);
@@ -1292,8 +1368,7 @@ static int mtk_tx_map(struct sk_buff *skb, struct net_device *dev,
 	wmb();
 
 	if (MTK_HAS_CAPS(soc->caps, MTK_QDMA)) {
-		if (netif_xmit_stopped(netdev_get_tx_queue(dev, 0)) ||
-		    !netdev_xmit_more())
+		if (netif_xmit_stopped(txq) || !netdev_xmit_more())
 			mtk_w32(eth, txd->txd2, soc->reg_map->qdma.ctx_ptr);
 	} else {
 		int next_idx;
@@ -1362,7 +1437,7 @@ static void mtk_wake_queue(struct mtk_eth *eth)
 	for (i = 0; i < MTK_MAC_COUNT; i++) {
 		if (!eth->netdev[i])
 			continue;
-		netif_wake_queue(eth->netdev[i]);
+		netif_tx_wake_all_queues(eth->netdev[i]);
 	}
 }
 
@@ -1386,7 +1461,7 @@ static netdev_tx_t mtk_start_xmit(struct sk_buff *skb, struct net_device *dev)
 
 	tx_num = mtk_cal_txd_req(eth, skb);
 	if (unlikely(atomic_read(&ring->free_count) <= tx_num)) {
-		netif_stop_queue(dev);
+		netif_tx_stop_all_queues(dev);
 		netif_err(eth, tx_queued, dev,
 			  "Tx Ring full when queue awake!\n");
 		spin_unlock(&eth->page_lock);
@@ -1412,7 +1487,7 @@ static netdev_tx_t mtk_start_xmit(struct sk_buff *skb, struct net_device *dev)
 		goto drop;
 
 	if (unlikely(atomic_read(&ring->free_count) <= ring->thresh))
-		netif_stop_queue(dev);
+		netif_tx_stop_all_queues(dev);
 
 	spin_unlock(&eth->page_lock);
 
@@ -1579,10 +1654,12 @@ static int mtk_xdp_submit_frame(struct mtk_eth *eth, struct xdp_frame *xdpf,
 	struct skb_shared_info *sinfo = xdp_get_shared_info_from_frame(xdpf);
 	const struct mtk_soc_data *soc = eth->soc;
 	struct mtk_tx_ring *ring = &eth->tx_ring;
+	struct mtk_mac *mac = netdev_priv(dev);
 	struct mtk_tx_dma_desc_info txd_info = {
 		.size	= xdpf->len,
 		.first	= true,
 		.last	= !xdp_frame_has_frags(xdpf),
+		.qid	= mac->id,
 	};
 	int err, index = 0, n_desc = 1, nr_frags;
 	struct mtk_tx_buf *htx_buf, *tx_buf;
@@ -1632,6 +1709,7 @@ static int mtk_xdp_submit_frame(struct mtk_eth *eth, struct xdp_frame *xdpf,
 		memset(&txd_info, 0, sizeof(struct mtk_tx_dma_desc_info));
 		txd_info.size = skb_frag_size(&sinfo->frags[index]);
 		txd_info.last = index + 1 == nr_frags;
+		txd_info.qid = mac->id;
 		data = skb_frag_address(&sinfo->frags[index]);
 
 		index++;
@@ -1986,8 +2064,46 @@ static int mtk_poll_rx(struct napi_struct *napi, int budget,
 	return done;
 }
 
+struct mtk_poll_state {
+    struct netdev_queue *txq;
+    unsigned int total;
+    unsigned int done;
+    unsigned int bytes;
+};
+
+static void
+mtk_poll_tx_done(struct mtk_eth *eth, struct mtk_poll_state *state, u8 mac,
+		 struct sk_buff *skb)
+{
+	struct netdev_queue *txq;
+	struct net_device *dev;
+	unsigned int bytes = skb->len;
+
+	state->total++;
+	eth->tx_packets++;
+	eth->tx_bytes += bytes;
+
+	dev = eth->netdev[mac];
+	if (!dev)
+		return;
+
+	txq = netdev_get_tx_queue(dev, skb_get_queue_mapping(skb));
+	if (state->txq == txq) {
+		state->done++;
+		state->bytes += bytes;
+		return;
+	}
+
+	if (state->txq)
+		netdev_tx_completed_queue(state->txq, state->done, state->bytes);
+
+	state->txq = txq;
+	state->done = 1;
+	state->bytes = bytes;
+}
+
 static int mtk_poll_tx_qdma(struct mtk_eth *eth, int budget,
-			    unsigned int *done, unsigned int *bytes)
+			    struct mtk_poll_state *state)
 {
 	const struct mtk_reg_map *reg_map = eth->soc->reg_map;
 	struct mtk_tx_ring *ring = &eth->tx_ring;
@@ -2019,12 +2135,9 @@ static int mtk_poll_tx_qdma(struct mtk_eth *eth, int budget,
 			break;
 
 		if (tx_buf->data != (void *)MTK_DMA_DUMMY_DESC) {
-			if (tx_buf->type == MTK_TYPE_SKB) {
-				struct sk_buff *skb = tx_buf->data;
+			if (tx_buf->type == MTK_TYPE_SKB)
+				mtk_poll_tx_done(eth, state, mac, tx_buf->data);
 
-				bytes[mac] += skb->len;
-				done[mac]++;
-			}
 			budget--;
 		}
 		mtk_tx_unmap(eth, tx_buf, &bq, true);
@@ -2043,7 +2156,7 @@ static int mtk_poll_tx_qdma(struct mtk_eth *eth, int budget,
 }
 
 static int mtk_poll_tx_pdma(struct mtk_eth *eth, int budget,
-			    unsigned int *done, unsigned int *bytes)
+			    struct mtk_poll_state *state)
 {
 	struct mtk_tx_ring *ring = &eth->tx_ring;
 	struct mtk_tx_buf *tx_buf;
@@ -2061,12 +2174,8 @@ static int mtk_poll_tx_pdma(struct mtk_eth *eth, int budget,
 			break;
 
 		if (tx_buf->data != (void *)MTK_DMA_DUMMY_DESC) {
-			if (tx_buf->type == MTK_TYPE_SKB) {
-				struct sk_buff *skb = tx_buf->data;
-
-				bytes[0] += skb->len;
-				done[0]++;
-			}
+			if (tx_buf->type == MTK_TYPE_SKB)
+				mtk_poll_tx_done(eth, state, 0, tx_buf->data);
 			budget--;
 		}
 		mtk_tx_unmap(eth, tx_buf, &bq, true);
@@ -2088,26 +2197,15 @@ static int mtk_poll_tx(struct mtk_eth *eth, int budget)
 {
 	struct mtk_tx_ring *ring = &eth->tx_ring;
 	struct dim_sample dim_sample = {};
-	unsigned int done[MTK_MAX_DEVS];
-	unsigned int bytes[MTK_MAX_DEVS];
-	int total = 0, i;
-
-	memset(done, 0, sizeof(done));
-	memset(bytes, 0, sizeof(bytes));
+	struct mtk_poll_state state = {};
 
 	if (MTK_HAS_CAPS(eth->soc->caps, MTK_QDMA))
-		budget = mtk_poll_tx_qdma(eth, budget, done, bytes);
+		budget = mtk_poll_tx_qdma(eth, budget, &state);
 	else
-		budget = mtk_poll_tx_pdma(eth, budget, done, bytes);
+		budget = mtk_poll_tx_pdma(eth, budget, &state);
 
-	for (i = 0; i < MTK_MAC_COUNT; i++) {
-		if (!eth->netdev[i] || !done[i])
-			continue;
-		netdev_completed_queue(eth->netdev[i], done[i], bytes[i]);
-		total += done[i];
-		eth->tx_packets += done[i];
-		eth->tx_bytes += bytes[i];
-	}
+	if (state.txq)
+		netdev_tx_completed_queue(state.txq, state.done, state.bytes);
 
 	dim_update_sample(eth->tx_events, eth->tx_packets, eth->tx_bytes,
 			  &dim_sample);
@@ -2117,7 +2215,7 @@ static int mtk_poll_tx(struct mtk_eth *eth, int budget)
 	    (atomic_read(&ring->free_count) > ring->thresh))
 		mtk_wake_queue(eth);
 
-	return total;
+	return state.total;
 }
 
 static void mtk_handle_status_irq(struct mtk_eth *eth)
@@ -2203,6 +2301,7 @@ static int mtk_tx_alloc(struct mtk_eth *eth)
 	int i, sz = soc->txrx.txd_size;
 	struct mtk_tx_dma_v2 *txd;
 	int ring_size;
+	u32 ofs, val;
 
 	if (MTK_HAS_CAPS(soc->caps, MTK_QDMA))
 		ring_size = MTK_QDMA_RING_SIZE;
@@ -2270,8 +2369,25 @@ static int mtk_tx_alloc(struct mtk_eth *eth)
 			ring->phys + ((ring_size - 1) * sz),
 			soc->reg_map->qdma.crx_ptr);
 		mtk_w32(eth, ring->last_free_ptr, soc->reg_map->qdma.drx_ptr);
-		mtk_w32(eth, (QDMA_RES_THRES << 8) | QDMA_RES_THRES,
-			soc->reg_map->qdma.qtx_cfg);
+
+		for (i = 0, ofs = 0; i < MTK_QDMA_NUM_QUEUES; i++) {
+			val = (QDMA_RES_THRES << 8) | QDMA_RES_THRES;
+			mtk_w32(eth, val, soc->reg_map->qdma.qtx_cfg + ofs);
+
+			val = MTK_QTX_SCH_MIN_RATE_EN |
+			      /* minimum: 10 Mbps */
+			      FIELD_PREP(MTK_QTX_SCH_MIN_RATE_MAN, 1) |
+			      FIELD_PREP(MTK_QTX_SCH_MIN_RATE_EXP, 4) |
+			      MTK_QTX_SCH_LEAKY_BUCKET_SIZE;
+			if (!MTK_HAS_CAPS(eth->soc->caps, MTK_NETSYS_V2))
+				val |= MTK_QTX_SCH_LEAKY_BUCKET_EN;
+			mtk_w32(eth, val, soc->reg_map->qdma.qtx_sch + ofs);
+			ofs += MTK_QTX_OFFSET;
+		}
+		val = MTK_QDMA_TX_SCH_MAX_WFQ | (MTK_QDMA_TX_SCH_MAX_WFQ << 16);
+		mtk_w32(eth, val, soc->reg_map->qdma.tx_sch_rate);
+		if (MTK_HAS_CAPS(eth->soc->caps, MTK_NETSYS_V2))
+			mtk_w32(eth, val, soc->reg_map->qdma.tx_sch_rate + 4);
 	} else {
 		mtk_w32(eth, ring->phys_pdma, MT7628_TX_BASE_PTR0);
 		mtk_w32(eth, ring_size, MT7628_TX_MAX_CNT0);
@@ -2936,7 +3052,7 @@ static int mtk_start_dma(struct mtk_eth *eth)
 		if (MTK_HAS_CAPS(eth->soc->caps, MTK_NETSYS_V2))
 			val |= MTK_MUTLI_CNT | MTK_RESV_BUF |
 			       MTK_WCOMP_EN | MTK_DMAD_WR_WDONE |
-			       MTK_CHK_DDONE_EN;
+			       MTK_CHK_DDONE_EN | MTK_LEAKY_BUCKET_EN;
 		else
 			val |= MTK_RX_BT_32DWORDS;
 		mtk_w32(eth, val, reg_map->qdma.glo_cfg);
@@ -2982,6 +3098,45 @@ static void mtk_gdm_config(struct mtk_eth *eth, u32 config)
 	mtk_w32(eth, 0, MTK_RST_GL);
 }
 
+static int mtk_device_event(struct notifier_block *n, unsigned long event, void *ptr)
+{
+	struct mtk_mac *mac = container_of(n, struct mtk_mac, device_notifier);
+	struct mtk_eth *eth = mac->hw;
+	struct net_device *dev = netdev_notifier_info_to_dev(ptr);
+	struct ethtool_link_ksettings s;
+	struct net_device *ldev;
+	struct list_head *iter;
+	struct dsa_port *dp;
+
+	if (event != NETDEV_CHANGE)
+		return NOTIFY_DONE;
+
+	netdev_for_each_lower_dev(dev, ldev, iter) {
+		if (netdev_priv(ldev) == mac)
+			goto found;
+	}
+
+	return NOTIFY_DONE;
+
+found:
+	if (!dsa_slave_dev_check(dev))
+		return NOTIFY_DONE;
+
+	if (__ethtool_get_link_ksettings(dev, &s))
+		return NOTIFY_DONE;
+
+	if (s.base.speed == 0 || s.base.speed == ((__u32)-1))
+		return NOTIFY_DONE;
+
+	dp = dsa_port_from_netdev(dev);
+	if (dp->index >= MTK_QDMA_NUM_QUEUES)
+		return NOTIFY_DONE;
+
+	mtk_set_queue_speed(eth, dp->index + 3, s.base.speed);
+
+	return NOTIFY_DONE;
+}
+
 static int mtk_open(struct net_device *dev)
 {
 	struct mtk_mac *mac = netdev_priv(dev);
@@ -3022,7 +3177,8 @@ static int mtk_open(struct net_device *dev)
 		refcount_inc(&eth->dma_refcnt);
 
 	phylink_start(mac->phylink);
-	netif_start_queue(dev);
+	netif_tx_start_all_queues(dev);
+
 	return 0;
 }
 
@@ -3538,8 +3694,12 @@ static int mtk_unreg_dev(struct mtk_eth *eth)
 	int i;
 
 	for (i = 0; i < MTK_MAC_COUNT; i++) {
+		struct mtk_mac *mac;
 		if (!eth->netdev[i])
 			continue;
+		mac = netdev_priv(eth->netdev[i]);
+		if (MTK_HAS_CAPS(eth->soc->caps, MTK_QDMA))
+			unregister_netdevice_notifier(&mac->device_notifier);
 		unregister_netdev(eth->netdev[i]);
 	}
 
@@ -3755,6 +3915,24 @@ static int mtk_set_rxnfc(struct net_device *dev, struct ethtool_rxnfc *cmd)
 	return ret;
 }
 
+static u16 mtk_select_queue(struct net_device *dev, struct sk_buff *skb,
+			    struct net_device *sb_dev)
+{
+	struct mtk_mac *mac = netdev_priv(dev);
+	unsigned int queue = 0;
+
+	if (netdev_uses_dsa(dev))
+		queue = skb_get_queue_mapping(skb);
+
+	if (!queue)
+		queue = mac->id;
+
+	if (queue >= dev->num_tx_queues)
+		queue = 0;
+
+	return queue;
+}
+
 static const struct ethtool_ops mtk_ethtool_ops = {
 	.get_link_ksettings	= mtk_get_link_ksettings,
 	.set_link_ksettings	= mtk_set_link_ksettings,
@@ -3790,6 +3968,7 @@ static const struct net_device_ops mtk_netdev_ops = {
 	.ndo_setup_tc		= mtk_eth_setup_tc,
 	.ndo_bpf		= mtk_xdp,
 	.ndo_xdp_xmit		= mtk_xdp_xmit,
+	.ndo_select_queue	= mtk_select_queue,
 };
 
 static int mtk_add_mac(struct mtk_eth *eth, struct device_node *np)
@@ -3799,6 +3978,7 @@ static int mtk_add_mac(struct mtk_eth *eth, struct device_node *np)
 	struct phylink *phylink;
 	struct mtk_mac *mac;
 	int id, err;
+	int txqs = 1;
 
 	if (!_id) {
 		dev_err(eth->dev, "missing mac id\n");
@@ -3816,7 +3996,10 @@ static int mtk_add_mac(struct mtk_eth *eth, struct device_node *np)
 		return -EINVAL;
 	}
 
-	eth->netdev[id] = alloc_etherdev(sizeof(*mac));
+	if (MTK_HAS_CAPS(eth->soc->caps, MTK_QDMA))
+		txqs = MTK_QDMA_NUM_QUEUES;
+
+	eth->netdev[id] = alloc_etherdev_mqs(sizeof(*mac), txqs, 1);
 	if (!eth->netdev[id]) {
 		dev_err(eth->dev, "alloc_etherdev failed\n");
 		return -ENOMEM;
@@ -3913,6 +4096,11 @@ static int mtk_add_mac(struct mtk_eth *eth, struct device_node *np)
 	else
 		eth->netdev[id]->max_mtu = MTK_MAX_RX_LENGTH_2K - MTK_RX_ETH_HLEN;
 
+	if (MTK_HAS_CAPS(eth->soc->caps, MTK_QDMA)) {
+		mac->device_notifier.notifier_call = mtk_device_event;
+		register_netdevice_notifier(&mac->device_notifier);
+	}
+
 	return 0;
 
 free_netdev:
diff --git a/drivers/net/ethernet/mediatek/mtk_eth_soc.h b/drivers/net/ethernet/mediatek/mtk_eth_soc.h
index 7c0b6c0c05d8..8123a646ba0a 100644
--- a/drivers/net/ethernet/mediatek/mtk_eth_soc.h
+++ b/drivers/net/ethernet/mediatek/mtk_eth_soc.h
@@ -22,6 +22,7 @@
 #include <linux/bpf_trace.h>
 #include "mtk_ppe.h"
 
+#define MTK_QDMA_NUM_QUEUES	16
 #define MTK_QDMA_PAGE_SIZE	2048
 #define MTK_MAX_RX_LENGTH	1536
 #define MTK_MAX_RX_LENGTH_2K	2048
@@ -203,8 +204,26 @@
 #define MTK_RING_MAX_AGG_CNT_H		((MTK_HW_LRO_MAX_AGG_CNT >> 6) & 0x3)
 
 /* QDMA TX Queue Configuration Registers */
+#define MTK_QTX_OFFSET		0x10
 #define QDMA_RES_THRES		4
 
+/* QDMA Tx Queue Scheduler Configuration Registers */
+#define MTK_QTX_SCH_TX_SEL		BIT(31)
+#define MTK_QTX_SCH_TX_SEL_V2		GENMASK(31, 30)
+
+#define MTK_QTX_SCH_LEAKY_BUCKET_EN	BIT(30)
+#define MTK_QTX_SCH_LEAKY_BUCKET_SIZE	GENMASK(29, 28)
+#define MTK_QTX_SCH_MIN_RATE_EN		BIT(27)
+#define MTK_QTX_SCH_MIN_RATE_MAN	GENMASK(26, 20)
+#define MTK_QTX_SCH_MIN_RATE_EXP	GENMASK(19, 16)
+#define MTK_QTX_SCH_MAX_RATE_WEIGHT	GENMASK(15, 12)
+#define MTK_QTX_SCH_MAX_RATE_EN		BIT(11)
+#define MTK_QTX_SCH_MAX_RATE_MAN	GENMASK(10, 4)
+#define MTK_QTX_SCH_MAX_RATE_EXP	GENMASK(3, 0)
+
+/* QDMA TX Scheduler Rate Control Register */
+#define MTK_QDMA_TX_SCH_MAX_WFQ		BIT(15)
+
 /* QDMA Global Configuration Register */
 #define MTK_RX_2B_OFFSET	BIT(31)
 #define MTK_RX_BT_32DWORDS	(3 << 11)
@@ -223,6 +242,7 @@
 #define MTK_WCOMP_EN		BIT(24)
 #define MTK_RESV_BUF		(0x40 << 16)
 #define MTK_MUTLI_CNT		(0x4 << 12)
+#define MTK_LEAKY_BUCKET_EN	BIT(11)
 
 /* QDMA Flow Control Register */
 #define FC_THRES_DROP_MODE	BIT(20)
@@ -251,8 +271,6 @@
 #define MTK_STAT_OFFSET		0x40
 
 /* QDMA TX NUM */
-#define MTK_QDMA_TX_NUM		16
-#define MTK_QDMA_TX_MASK	(MTK_QDMA_TX_NUM - 1)
 #define QID_BITS_V2(x)		(((x) & 0x3f) << 16)
 #define MTK_QDMA_GMAC2_QID	8
 
@@ -282,6 +300,7 @@
 #define TX_DMA_PLEN0(x)		(((x) & eth->soc->txrx.dma_max_len) << eth->soc->txrx.dma_len_offset)
 #define TX_DMA_PLEN1(x)		((x) & eth->soc->txrx.dma_max_len)
 #define TX_DMA_SWC		BIT(14)
+#define TX_DMA_PQID		GENMASK(3, 0)
 
 /* PDMA on MT7628 */
 #define TX_DMA_DONE		BIT(31)
@@ -940,6 +959,7 @@ struct mtk_reg_map {
 	} pdma;
 	struct {
 		u32	qtx_cfg;	/* tx queue configuration */
+		u32	qtx_sch;	/* tx queue scheduler configuration */
 		u32	rx_ptr;		/* rx base pointer */
 		u32	rx_cnt_cfg;	/* rx max count configuration */
 		u32	qcrx_ptr;	/* rx cpu pointer */
@@ -957,6 +977,7 @@ struct mtk_reg_map {
 		u32	fq_tail;	/* fq tail pointer */
 		u32	fq_count;	/* fq free page count */
 		u32	fq_blen;	/* fq free page buffer length */
+		u32	tx_sch_rate;	/* tx scheduler rate control registers */
 	} qdma;
 	u32	gdm1_cnt;
 	u32	gdma_to_ppe;
@@ -1148,6 +1169,7 @@ struct mtk_mac {
 	__be32				hwlro_ip[MTK_MAX_LRO_IP_CNT];
 	int				hwlro_ip_cnt;
 	unsigned int			syscfg0;
+	struct notifier_block		device_notifier;
 };
 
 /* the struct describing the SoC. these are declared in the soc_xyz.c files */
-- 
2.38.1


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

* [PATCH 05/14] net: dsa: tag_mtk: assign per-port queues
  2022-11-07 18:54 [PATCH 01/14] net: ethernet: mtk_eth_soc: account for vlan in rx header length Felix Fietkau
                   ` (2 preceding siblings ...)
  2022-11-07 18:54 ` [PATCH 04/14] net: ethernet: mtk_eth_soc: implement multi-queue support for per-port queues Felix Fietkau
@ 2022-11-07 18:54 ` Felix Fietkau
  2022-11-07 20:40   ` Vladimir Oltean
  2022-11-07 21:22   ` Vladimir Oltean
  2022-11-07 18:54 ` [PATCH 06/14] net: ethernet: mediatek: ppe: assign per-port queues for offloaded traffic Felix Fietkau
                   ` (9 subsequent siblings)
  13 siblings, 2 replies; 37+ messages in thread
From: Felix Fietkau @ 2022-11-07 18:54 UTC (permalink / raw)
  To: netdev, Sean Wang, Landen Chao, DENG Qingfang, Andrew Lunn,
	Vivien Didelot, Florian Fainelli, Vladimir Oltean,
	David S. Miller, Eric Dumazet, Jakub Kicinski, Paolo Abeni,
	Matthias Brugger
  Cc: linux-arm-kernel, linux-mediatek, linux-kernel

Keeps traffic sent to the switch within link speed limits

Signed-off-by: Felix Fietkau <nbd@nbd.name>
---
 net/dsa/tag_mtk.c | 3 +++
 1 file changed, 3 insertions(+)

diff --git a/net/dsa/tag_mtk.c b/net/dsa/tag_mtk.c
index 415d8ece242a..445d6113227f 100644
--- a/net/dsa/tag_mtk.c
+++ b/net/dsa/tag_mtk.c
@@ -25,6 +25,9 @@ static struct sk_buff *mtk_tag_xmit(struct sk_buff *skb,
 	u8 xmit_tpid;
 	u8 *mtk_tag;
 
+	/* Reserve the first three queues for packets not passed through DSA */
+	skb_set_queue_mapping(skb, 3 + dp->index);
+
 	/* Build the special tag after the MAC Source Address. If VLAN header
 	 * is present, it's required that VLAN header and special tag is
 	 * being combined. Only in this way we can allow the switch can parse
-- 
2.38.1


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

* [PATCH 06/14] net: ethernet: mediatek: ppe: assign per-port queues for offloaded traffic
  2022-11-07 18:54 [PATCH 01/14] net: ethernet: mtk_eth_soc: account for vlan in rx header length Felix Fietkau
                   ` (3 preceding siblings ...)
  2022-11-07 18:54 ` [PATCH 05/14] net: dsa: tag_mtk: assign " Felix Fietkau
@ 2022-11-07 18:54 ` Felix Fietkau
  2022-11-07 18:54 ` [PATCH 07/14] net: ethernet: mtk_eth_soc: compile out netsys v2 code on mt7621 Felix Fietkau
                   ` (8 subsequent siblings)
  13 siblings, 0 replies; 37+ messages in thread
From: Felix Fietkau @ 2022-11-07 18:54 UTC (permalink / raw)
  To: netdev, John Crispin, Sean Wang, Mark Lee, David S. Miller,
	Eric Dumazet, Jakub Kicinski, Paolo Abeni, Matthias Brugger
  Cc: linux-arm-kernel, linux-mediatek, linux-kernel

Keeps traffic sent to the switch within link speed limits

Signed-off-by: Felix Fietkau <nbd@nbd.name>
---
 drivers/net/ethernet/mediatek/mtk_ppe.c        | 18 ++++++++++++++++++
 drivers/net/ethernet/mediatek/mtk_ppe.h        |  4 ++++
 .../net/ethernet/mediatek/mtk_ppe_offload.c    | 12 +++++++++---
 3 files changed, 31 insertions(+), 3 deletions(-)

diff --git a/drivers/net/ethernet/mediatek/mtk_ppe.c b/drivers/net/ethernet/mediatek/mtk_ppe.c
index 3ee2bf53f9e5..96ad0a9b79b4 100644
--- a/drivers/net/ethernet/mediatek/mtk_ppe.c
+++ b/drivers/net/ethernet/mediatek/mtk_ppe.c
@@ -399,6 +399,24 @@ int mtk_foe_entry_set_wdma(struct mtk_eth *eth, struct mtk_foe_entry *entry,
 	return 0;
 }
 
+int mtk_foe_entry_set_queue(struct mtk_eth *eth, struct mtk_foe_entry *entry,
+			    unsigned int queue)
+{
+	u32 *ib2 = mtk_foe_entry_ib2(eth, entry);
+
+	if (MTK_HAS_CAPS(eth->soc->caps, MTK_NETSYS_V2)) {
+		*ib2 &= ~MTK_FOE_IB2_QID_V2;
+		*ib2 |= FIELD_PREP(MTK_FOE_IB2_QID_V2, queue);
+		*ib2 |= MTK_FOE_IB2_PSE_QOS_V2;
+	} else {
+		*ib2 &= ~MTK_FOE_IB2_QID;
+		*ib2 |= FIELD_PREP(MTK_FOE_IB2_QID, queue);
+		*ib2 |= MTK_FOE_IB2_PSE_QOS;
+	}
+
+	return 0;
+}
+
 static bool
 mtk_flow_entry_match(struct mtk_eth *eth, struct mtk_flow_entry *entry,
 		     struct mtk_foe_entry *data)
diff --git a/drivers/net/ethernet/mediatek/mtk_ppe.h b/drivers/net/ethernet/mediatek/mtk_ppe.h
index 0b7a67a958e4..be635864bb96 100644
--- a/drivers/net/ethernet/mediatek/mtk_ppe.h
+++ b/drivers/net/ethernet/mediatek/mtk_ppe.h
@@ -68,7 +68,9 @@ enum {
 #define MTK_FOE_IB2_DSCP		GENMASK(31, 24)
 
 /* CONFIG_MEDIATEK_NETSYS_V2 */
+#define MTK_FOE_IB2_QID_V2			GENMASK(6, 0)
 #define MTK_FOE_IB2_PORT_MG_V2		BIT(7)
+#define MTK_FOE_IB2_PSE_QOS_V2		BIT(8)
 #define MTK_FOE_IB2_DEST_PORT_V2	GENMASK(12, 9)
 #define MTK_FOE_IB2_MULTICAST_V2	BIT(13)
 #define MTK_FOE_IB2_WDMA_WINFO_V2	BIT(19)
@@ -350,6 +352,8 @@ int mtk_foe_entry_set_pppoe(struct mtk_eth *eth, struct mtk_foe_entry *entry,
 			    int sid);
 int mtk_foe_entry_set_wdma(struct mtk_eth *eth, struct mtk_foe_entry *entry,
 			   int wdma_idx, int txq, int bss, int wcid);
+int mtk_foe_entry_set_queue(struct mtk_eth *eth, struct mtk_foe_entry *entry,
+			    unsigned int queue);
 int mtk_foe_entry_commit(struct mtk_ppe *ppe, struct mtk_flow_entry *entry);
 void mtk_foe_entry_clear(struct mtk_ppe *ppe, struct mtk_flow_entry *entry);
 int mtk_foe_entry_idle_time(struct mtk_ppe *ppe, struct mtk_flow_entry *entry);
diff --git a/drivers/net/ethernet/mediatek/mtk_ppe_offload.c b/drivers/net/ethernet/mediatek/mtk_ppe_offload.c
index 28bbd1df3e30..81afd5ee3fbf 100644
--- a/drivers/net/ethernet/mediatek/mtk_ppe_offload.c
+++ b/drivers/net/ethernet/mediatek/mtk_ppe_offload.c
@@ -188,7 +188,7 @@ mtk_flow_set_output_device(struct mtk_eth *eth, struct mtk_foe_entry *foe,
 			   int *wed_index)
 {
 	struct mtk_wdma_info info = {};
-	int pse_port, dsa_port;
+	int pse_port, dsa_port, queue;
 
 	if (mtk_flow_get_wdma_info(dev, dest_mac, &info) == 0) {
 		mtk_foe_entry_set_wdma(eth, foe, info.wdma_idx, info.queue,
@@ -212,8 +212,6 @@ mtk_flow_set_output_device(struct mtk_eth *eth, struct mtk_foe_entry *foe,
 	}
 
 	dsa_port = mtk_flow_get_dsa_port(&dev);
-	if (dsa_port >= 0)
-		mtk_foe_entry_set_dsa(eth, foe, dsa_port);
 
 	if (dev == eth->netdev[0])
 		pse_port = 1;
@@ -222,6 +220,14 @@ mtk_flow_set_output_device(struct mtk_eth *eth, struct mtk_foe_entry *foe,
 	else
 		return -EOPNOTSUPP;
 
+	if (dsa_port >= 0) {
+		mtk_foe_entry_set_dsa(eth, foe, dsa_port);
+		queue = 3 + dsa_port;
+	} else {
+		queue = pse_port - 1;
+	}
+	mtk_foe_entry_set_queue(eth, foe, queue);
+
 out:
 	mtk_foe_entry_set_pse_port(eth, foe, pse_port);
 
-- 
2.38.1


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

* [PATCH 07/14] net: ethernet: mtk_eth_soc: compile out netsys v2 code on mt7621
  2022-11-07 18:54 [PATCH 01/14] net: ethernet: mtk_eth_soc: account for vlan in rx header length Felix Fietkau
                   ` (4 preceding siblings ...)
  2022-11-07 18:54 ` [PATCH 06/14] net: ethernet: mediatek: ppe: assign per-port queues for offloaded traffic Felix Fietkau
@ 2022-11-07 18:54 ` Felix Fietkau
  2022-11-07 18:54 ` [PATCH 08/14] net: vlan: remove invalid VLAN protocol warning Felix Fietkau
                   ` (7 subsequent siblings)
  13 siblings, 0 replies; 37+ messages in thread
From: Felix Fietkau @ 2022-11-07 18:54 UTC (permalink / raw)
  To: netdev, John Crispin, Sean Wang, Mark Lee, David S. Miller,
	Eric Dumazet, Jakub Kicinski, Paolo Abeni, Matthias Brugger
  Cc: linux-arm-kernel, linux-mediatek, linux-kernel

Avoid some branches in the hot path on low-end devices with limited CPU power,
and reduce code size

Signed-off-by: Felix Fietkau <nbd@nbd.name>
---
 drivers/net/ethernet/mediatek/mtk_eth_soc.h | 8 +++++++-
 1 file changed, 7 insertions(+), 1 deletion(-)

diff --git a/drivers/net/ethernet/mediatek/mtk_eth_soc.h b/drivers/net/ethernet/mediatek/mtk_eth_soc.h
index 8123a646ba0a..e09b2483c70c 100644
--- a/drivers/net/ethernet/mediatek/mtk_eth_soc.h
+++ b/drivers/net/ethernet/mediatek/mtk_eth_soc.h
@@ -905,7 +905,13 @@ enum mkt_eth_capabilities {
 #define MTK_MUX_GMAC12_TO_GEPHY_SGMII   \
 	(MTK_ETH_MUX_GMAC12_TO_GEPHY_SGMII | MTK_MUX)
 
-#define MTK_HAS_CAPS(caps, _x)		(((caps) & (_x)) == (_x))
+#ifdef CONFIG_SOC_MT7621
+#define MTK_CAP_MASK MTK_NETSYS_V2
+#else
+#define MTK_CAP_MASK 0
+#endif
+
+#define MTK_HAS_CAPS(caps, _x)		(((caps) & (_x) & ~(MTK_CAP_MASK)) == (_x))
 
 #define MT7621_CAPS  (MTK_GMAC1_RGMII | MTK_GMAC1_TRGMII | \
 		      MTK_GMAC2_RGMII | MTK_SHARED_INT | \
-- 
2.38.1


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

* [PATCH 08/14] net: vlan: remove invalid VLAN protocol warning
  2022-11-07 18:54 [PATCH 01/14] net: ethernet: mtk_eth_soc: account for vlan in rx header length Felix Fietkau
                   ` (5 preceding siblings ...)
  2022-11-07 18:54 ` [PATCH 07/14] net: ethernet: mtk_eth_soc: compile out netsys v2 code on mt7621 Felix Fietkau
@ 2022-11-07 18:54 ` Felix Fietkau
  2022-11-07 21:57   ` Vladimir Oltean
  2022-11-07 18:54 ` [PATCH 09/14] flow_dissector: detect DSA using skb->protocol even when VLAN tag is present Felix Fietkau
                   ` (6 subsequent siblings)
  13 siblings, 1 reply; 37+ messages in thread
From: Felix Fietkau @ 2022-11-07 18:54 UTC (permalink / raw)
  To: netdev, David S. Miller, Eric Dumazet, Jakub Kicinski, Paolo Abeni
  Cc: linux-kernel

On MTK SoC ethernet, using NETIF_F_HW_VLAN_CTAG_RX in combination with hardware
special tag parsing can pass the special tag port metadata as VLAN protocol ID.
When the results is added as a skb hwaccel VLAN tag, it triggers a warning from
vlan_do_receive before calling the DSA tag receive function.
Remove this warning in order to properly pass the tag to the DSA receive function,
which will parse and clear it.

Signed-off-by: Felix Fietkau <nbd@nbd.name>
---
 net/8021q/vlan.h | 1 -
 1 file changed, 1 deletion(-)

diff --git a/net/8021q/vlan.h b/net/8021q/vlan.h
index 5eaf38875554..3f9c0406b266 100644
--- a/net/8021q/vlan.h
+++ b/net/8021q/vlan.h
@@ -44,7 +44,6 @@ static inline int vlan_proto_idx(__be16 proto)
 	case htons(ETH_P_8021AD):
 		return VLAN_PROTO_8021AD;
 	default:
-		WARN(1, "invalid VLAN protocol: 0x%04x\n", ntohs(proto));
 		return -EINVAL;
 	}
 }
-- 
2.38.1


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

* [PATCH 09/14] flow_dissector: detect DSA using skb->protocol even when VLAN tag is present
  2022-11-07 18:54 [PATCH 01/14] net: ethernet: mtk_eth_soc: account for vlan in rx header length Felix Fietkau
                   ` (6 preceding siblings ...)
  2022-11-07 18:54 ` [PATCH 08/14] net: vlan: remove invalid VLAN protocol warning Felix Fietkau
@ 2022-11-07 18:54 ` Felix Fietkau
  2022-11-07 18:54 ` [PATCH 10/14] net: dsa: tag_mtk: parse hwaccel VLAN tags Felix Fietkau
                   ` (5 subsequent siblings)
  13 siblings, 0 replies; 37+ messages in thread
From: Felix Fietkau @ 2022-11-07 18:54 UTC (permalink / raw)
  To: netdev, David S. Miller, Eric Dumazet, Jakub Kicinski, Paolo Abeni
  Cc: linux-kernel

Fixes flow dissection with ethernet devices that can combine VLAN rx hwaccel
with DSA, since skb->protocol is set to htons(ETH_P_XDSA) by the network stack.

Signed-off-by: Felix Fietkau <nbd@nbd.name>
---
 net/core/flow_dissector.c | 2 +-
 1 file changed, 1 insertion(+), 1 deletion(-)

diff --git a/net/core/flow_dissector.c b/net/core/flow_dissector.c
index 25cd35f5922e..43f6bbca7447 100644
--- a/net/core/flow_dissector.c
+++ b/net/core/flow_dissector.c
@@ -970,7 +970,7 @@ bool __skb_flow_dissect(const struct net *net,
 		hlen = skb_headlen(skb);
 #if IS_ENABLED(CONFIG_NET_DSA)
 		if (unlikely(skb->dev && netdev_uses_dsa(skb->dev) &&
-			     proto == htons(ETH_P_XDSA))) {
+			     skb->protocol == htons(ETH_P_XDSA))) {
 			const struct dsa_device_ops *ops;
 			int offset = 0;
 
-- 
2.38.1


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

* [PATCH 10/14] net: dsa: tag_mtk: parse hwaccel VLAN tags
  2022-11-07 18:54 [PATCH 01/14] net: ethernet: mtk_eth_soc: account for vlan in rx header length Felix Fietkau
                   ` (7 preceding siblings ...)
  2022-11-07 18:54 ` [PATCH 09/14] flow_dissector: detect DSA using skb->protocol even when VLAN tag is present Felix Fietkau
@ 2022-11-07 18:54 ` Felix Fietkau
  2022-11-07 18:54 ` [PATCH 11/14] net: ethernet: mtk_eth_soc: fix VLAN rx hardware acceleration Felix Fietkau
                   ` (4 subsequent siblings)
  13 siblings, 0 replies; 37+ messages in thread
From: Felix Fietkau @ 2022-11-07 18:54 UTC (permalink / raw)
  To: netdev, Sean Wang, Landen Chao, DENG Qingfang, Andrew Lunn,
	Vivien Didelot, Florian Fainelli, Vladimir Oltean,
	David S. Miller, Eric Dumazet, Jakub Kicinski, Paolo Abeni,
	Matthias Brugger
  Cc: linux-arm-kernel, linux-mediatek, linux-kernel

Pull the port information from the VLAN protocol ID field

Signed-off-by: Felix Fietkau <nbd@nbd.name>
---
 net/dsa/tag_mtk.c | 26 +++++++++++++++++++++-----
 1 file changed, 21 insertions(+), 5 deletions(-)

diff --git a/net/dsa/tag_mtk.c b/net/dsa/tag_mtk.c
index 445d6113227f..0dfa2354f77d 100644
--- a/net/dsa/tag_mtk.c
+++ b/net/dsa/tag_mtk.c
@@ -73,13 +73,18 @@ static struct sk_buff *mtk_tag_rcv(struct sk_buff *skb, struct net_device *dev)
 	if (unlikely(!pskb_may_pull(skb, MTK_HDR_LEN)))
 		return NULL;
 
-	phdr = dsa_etype_header_pos_rx(skb);
-	hdr = ntohs(*phdr);
+	if (skb_vlan_tag_present(skb)) {
+		hdr = ntohs(skb->vlan_proto);
+		__vlan_hwaccel_clear_tag(skb);
+	} else {
+		phdr = dsa_etype_header_pos_rx(skb);
+		hdr = ntohs(*phdr);
 
-	/* Remove MTK tag and recalculate checksum. */
-	skb_pull_rcsum(skb, MTK_HDR_LEN);
+		/* Remove MTK tag and recalculate checksum. */
+		skb_pull_rcsum(skb, MTK_HDR_LEN);
 
-	dsa_strip_etype_header(skb, MTK_HDR_LEN);
+		dsa_strip_etype_header(skb, MTK_HDR_LEN);
+	}
 
 	/* Get source port information */
 	port = (hdr & MTK_HDR_RECV_SOURCE_PORT_MASK);
@@ -93,11 +98,22 @@ static struct sk_buff *mtk_tag_rcv(struct sk_buff *skb, struct net_device *dev)
 	return skb;
 }
 
+static void mtk_tag_flow_dissect(const struct sk_buff *skb, __be16 *proto,
+				 int *offset)
+{
+	if (!skb_vlan_tag_present(skb))
+		return dsa_tag_generic_flow_dissect(skb, proto, offset);
+
+	*offset = 0;
+	*proto = ((__be16 *)skb->data)[-1];
+}
+
 static const struct dsa_device_ops mtk_netdev_ops = {
 	.name		= "mtk",
 	.proto		= DSA_TAG_PROTO_MTK,
 	.xmit		= mtk_tag_xmit,
 	.rcv		= mtk_tag_rcv,
+	.flow_dissect	= mtk_tag_flow_dissect,
 	.needed_headroom = MTK_HDR_LEN,
 };
 
-- 
2.38.1


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

* [PATCH 11/14] net: ethernet: mtk_eth_soc: fix VLAN rx hardware acceleration
  2022-11-07 18:54 [PATCH 01/14] net: ethernet: mtk_eth_soc: account for vlan in rx header length Felix Fietkau
                   ` (8 preceding siblings ...)
  2022-11-07 18:54 ` [PATCH 10/14] net: dsa: tag_mtk: parse hwaccel VLAN tags Felix Fietkau
@ 2022-11-07 18:54 ` Felix Fietkau
  2022-11-07 23:32   ` Vladimir Oltean
  2022-11-07 18:54 ` [PATCH 12/14] net: ethernet: mtk_eth_soc: work around issue with sending small fragments Felix Fietkau
                   ` (3 subsequent siblings)
  13 siblings, 1 reply; 37+ messages in thread
From: Felix Fietkau @ 2022-11-07 18:54 UTC (permalink / raw)
  To: netdev, John Crispin, Sean Wang, Mark Lee, David S. Miller,
	Eric Dumazet, Jakub Kicinski, Paolo Abeni, Matthias Brugger,
	Russell King
  Cc: linux-arm-kernel, linux-mediatek, linux-kernel

- enable VLAN untagging for PDMA rx
- make it possible to disable the feature via ethtool
- pass VLAN tag to the DSA driver
- untag special tag on PDMA only if no non-DSA devices are in use
- disable special tag untagging on 7986 for now, since it's not working yet

Signed-off-by: Felix Fietkau <nbd@nbd.name>
---
 drivers/net/ethernet/mediatek/mtk_eth_soc.c | 36 +++++++++++++--------
 drivers/net/ethernet/mediatek/mtk_eth_soc.h |  3 ++
 2 files changed, 25 insertions(+), 14 deletions(-)

diff --git a/drivers/net/ethernet/mediatek/mtk_eth_soc.c b/drivers/net/ethernet/mediatek/mtk_eth_soc.c
index ab31dda2cd66..3b8995a483aa 100644
--- a/drivers/net/ethernet/mediatek/mtk_eth_soc.c
+++ b/drivers/net/ethernet/mediatek/mtk_eth_soc.c
@@ -2015,16 +2015,9 @@ static int mtk_poll_rx(struct napi_struct *napi, int budget,
 						htons(RX_DMA_VPID(trxd.rxd4)),
 						RX_DMA_VID(trxd.rxd4));
 			} else if (trxd.rxd2 & RX_DMA_VTAG) {
-				__vlan_hwaccel_put_tag(skb, htons(ETH_P_8021Q),
+				__vlan_hwaccel_put_tag(skb, htons(RX_DMA_VPID(trxd.rxd3)),
 						       RX_DMA_VID(trxd.rxd3));
 			}
-
-			/* If the device is attached to a dsa switch, the special
-			 * tag inserted in VLAN field by hw switch can * be offloaded
-			 * by RX HW VLAN offload. Clear vlan info.
-			 */
-			if (netdev_uses_dsa(netdev))
-				__vlan_hwaccel_clear_tag(skb);
 		}
 
 		skb_record_rx_queue(skb, 0);
@@ -2847,15 +2840,17 @@ static netdev_features_t mtk_fix_features(struct net_device *dev,
 
 static int mtk_set_features(struct net_device *dev, netdev_features_t features)
 {
-	int err = 0;
-
-	if (!((dev->features ^ features) & NETIF_F_LRO))
-		return 0;
+	struct mtk_mac *mac = netdev_priv(dev);
+	struct mtk_eth *eth = mac->hw;
+	netdev_features_t diff = dev->features ^ features;
 
-	if (!(features & NETIF_F_LRO))
+	if ((diff & NETIF_F_LRO) && !(features & NETIF_F_LRO))
 		mtk_hwlro_netdev_disable(dev);
 
-	return err;
+	/* Set RX VLAN offloading */
+	mtk_w32(eth, !!(features & NETIF_F_HW_VLAN_CTAG_RX), MTK_CDMP_EG_CTRL);
+
+	return 0;
 }
 
 /* wait for DMA to finish whatever it is doing before we start using it again */
@@ -3176,6 +3171,15 @@ static int mtk_open(struct net_device *dev)
 	else
 		refcount_inc(&eth->dma_refcnt);
 
+	/* Hardware special tag parsing needs to be disabled if at least
+	 * one MAC does not use DSA.
+	 */
+	if (!netdev_uses_dsa(dev)) {
+		u32 val = mtk_r32(eth, MTK_CDMP_IG_CTRL);
+		val &= ~MTK_CDMP_STAG_EN;
+		mtk_w32(eth, val, MTK_CDMP_IG_CTRL);
+	}
+
 	phylink_start(mac->phylink);
 	netif_tx_start_all_queues(dev);
 
@@ -3469,6 +3473,10 @@ static int mtk_hw_init(struct mtk_eth *eth)
 	 */
 	val = mtk_r32(eth, MTK_CDMQ_IG_CTRL);
 	mtk_w32(eth, val | MTK_CDMQ_STAG_EN, MTK_CDMQ_IG_CTRL);
+	if (MTK_HAS_CAPS(eth->soc->caps, MTK_NETSYS_V2)) {
+		val = mtk_r32(eth, MTK_CDMP_IG_CTRL);
+		mtk_w32(eth, val | MTK_CDMP_STAG_EN, MTK_CDMP_IG_CTRL);
+	}
 
 	/* Enable RX VLan Offloading */
 	mtk_w32(eth, 1, MTK_CDMP_EG_CTRL);
diff --git a/drivers/net/ethernet/mediatek/mtk_eth_soc.h b/drivers/net/ethernet/mediatek/mtk_eth_soc.h
index e09b2483c70c..26b2323185ef 100644
--- a/drivers/net/ethernet/mediatek/mtk_eth_soc.h
+++ b/drivers/net/ethernet/mediatek/mtk_eth_soc.h
@@ -93,6 +93,9 @@
 #define MTK_CDMQ_IG_CTRL	0x1400
 #define MTK_CDMQ_STAG_EN	BIT(0)
 
+/* CDMQ Exgress Control Register */
+#define MTK_CDMQ_EG_CTRL	0x1404
+
 /* CDMP Ingress Control Register */
 #define MTK_CDMP_IG_CTRL	0x400
 #define MTK_CDMP_STAG_EN	BIT(0)
-- 
2.38.1


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

* [PATCH 12/14] net: ethernet: mtk_eth_soc: work around issue with sending small fragments
  2022-11-07 18:54 [PATCH 01/14] net: ethernet: mtk_eth_soc: account for vlan in rx header length Felix Fietkau
                   ` (9 preceding siblings ...)
  2022-11-07 18:54 ` [PATCH 11/14] net: ethernet: mtk_eth_soc: fix VLAN rx hardware acceleration Felix Fietkau
@ 2022-11-07 18:54 ` Felix Fietkau
  2022-11-07 18:54 ` [PATCH 13/14] net: ethernet: mtk_eth_soc: set NETIF_F_ALL_TSO Felix Fietkau
                   ` (2 subsequent siblings)
  13 siblings, 0 replies; 37+ messages in thread
From: Felix Fietkau @ 2022-11-07 18:54 UTC (permalink / raw)
  To: netdev, John Crispin, Sean Wang, Mark Lee, David S. Miller,
	Eric Dumazet, Jakub Kicinski, Paolo Abeni, Matthias Brugger
  Cc: linux-arm-kernel, linux-mediatek, linux-kernel

When frames are sent with very small fragments, the DMA engine appears to
lock up and transmit attempts time out. Fix this by detecting the presence
of small fragments and use skb_gso_segment + skb_linearize to deal with
them

Signed-off-by: Felix Fietkau <nbd@nbd.name>
---
 drivers/net/ethernet/mediatek/mtk_eth_soc.c | 36 +++++++++++++++++++--
 1 file changed, 34 insertions(+), 2 deletions(-)

diff --git a/drivers/net/ethernet/mediatek/mtk_eth_soc.c b/drivers/net/ethernet/mediatek/mtk_eth_soc.c
index 3b8995a483aa..50756c8aa871 100644
--- a/drivers/net/ethernet/mediatek/mtk_eth_soc.c
+++ b/drivers/net/ethernet/mediatek/mtk_eth_soc.c
@@ -1441,12 +1441,28 @@ static void mtk_wake_queue(struct mtk_eth *eth)
 	}
 }
 
+static bool mtk_skb_has_small_frag(struct sk_buff *skb)
+{
+	int min_size = 16;
+	int i;
+
+	if (skb_headlen(skb) < min_size)
+		return true;
+
+	for (i = 0; i < skb_shinfo(skb)->nr_frags; i++)
+		if (skb_frag_size(&skb_shinfo(skb)->frags[i]) < min_size)
+			return true;
+
+	return false;
+}
+
 static netdev_tx_t mtk_start_xmit(struct sk_buff *skb, struct net_device *dev)
 {
 	struct mtk_mac *mac = netdev_priv(dev);
 	struct mtk_eth *eth = mac->hw;
 	struct mtk_tx_ring *ring = &eth->tx_ring;
 	struct net_device_stats *stats = &dev->stats;
+	struct sk_buff *segs, *next;
 	bool gso = false;
 	int tx_num;
 
@@ -1468,6 +1484,17 @@ static netdev_tx_t mtk_start_xmit(struct sk_buff *skb, struct net_device *dev)
 		return NETDEV_TX_BUSY;
 	}
 
+	if (skb_is_gso(skb) && mtk_skb_has_small_frag(skb)) {
+		segs = skb_gso_segment(skb, dev->features & ~NETIF_F_ALL_TSO);
+		if (IS_ERR(segs))
+			goto drop;
+
+		if (segs) {
+			consume_skb(skb);
+			skb = segs;
+		}
+	}
+
 	/* TSO: fill MSS info in tcp checksum field */
 	if (skb_is_gso(skb)) {
 		if (skb_cow_head(skb, 0)) {
@@ -1483,8 +1510,13 @@ static netdev_tx_t mtk_start_xmit(struct sk_buff *skb, struct net_device *dev)
 		}
 	}
 
-	if (mtk_tx_map(skb, dev, tx_num, ring, gso) < 0)
-		goto drop;
+	skb_list_walk_safe(skb, skb, next) {
+		if ((mtk_skb_has_small_frag(skb) && skb_linearize(skb)) ||
+		    mtk_tx_map(skb, dev, tx_num, ring, gso) < 0) {
+			stats->tx_dropped++;
+			dev_kfree_skb_any(skb);
+		}
+	}
 
 	if (unlikely(atomic_read(&ring->free_count) <= ring->thresh))
 		netif_tx_stop_all_queues(dev);
-- 
2.38.1


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

* [PATCH 13/14] net: ethernet: mtk_eth_soc: set NETIF_F_ALL_TSO
  2022-11-07 18:54 [PATCH 01/14] net: ethernet: mtk_eth_soc: account for vlan in rx header length Felix Fietkau
                   ` (10 preceding siblings ...)
  2022-11-07 18:54 ` [PATCH 12/14] net: ethernet: mtk_eth_soc: work around issue with sending small fragments Felix Fietkau
@ 2022-11-07 18:54 ` Felix Fietkau
  2022-11-07 18:54 ` [PATCH 14/14] net: ethernet: mtk_eth_soc: drop packets to WDMA if the ring is full Felix Fietkau
  2022-11-07 20:55 ` [PATCH 01/14] net: ethernet: mtk_eth_soc: account for vlan in rx header length Vladimir Oltean
  13 siblings, 0 replies; 37+ messages in thread
From: Felix Fietkau @ 2022-11-07 18:54 UTC (permalink / raw)
  To: netdev, John Crispin, Sean Wang, Mark Lee, David S. Miller,
	Eric Dumazet, Jakub Kicinski, Paolo Abeni, Matthias Brugger
  Cc: linux-arm-kernel, linux-mediatek, linux-kernel

Significantly improves performance by avoiding unnecessary segmentation

Signed-off-by: Felix Fietkau <nbd@nbd.name>
---
 drivers/net/ethernet/mediatek/mtk_eth_soc.h | 3 +--
 1 file changed, 1 insertion(+), 2 deletions(-)

diff --git a/drivers/net/ethernet/mediatek/mtk_eth_soc.h b/drivers/net/ethernet/mediatek/mtk_eth_soc.h
index 26b2323185ef..bf8c7d11df9f 100644
--- a/drivers/net/ethernet/mediatek/mtk_eth_soc.h
+++ b/drivers/net/ethernet/mediatek/mtk_eth_soc.h
@@ -46,8 +46,7 @@
 				 NETIF_F_RXCSUM | \
 				 NETIF_F_HW_VLAN_CTAG_TX | \
 				 NETIF_F_HW_VLAN_CTAG_RX | \
-				 NETIF_F_SG | NETIF_F_TSO | \
-				 NETIF_F_TSO6 | \
+				 NETIF_F_SG | NETIF_F_ALL_TSO | \
 				 NETIF_F_IPV6_CSUM |\
 				 NETIF_F_HW_TC)
 #define MTK_HW_FEATURES_MT7628	(NETIF_F_SG | NETIF_F_RXCSUM)
-- 
2.38.1


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

* [PATCH 14/14] net: ethernet: mtk_eth_soc: drop packets to WDMA if the ring is full
  2022-11-07 18:54 [PATCH 01/14] net: ethernet: mtk_eth_soc: account for vlan in rx header length Felix Fietkau
                   ` (11 preceding siblings ...)
  2022-11-07 18:54 ` [PATCH 13/14] net: ethernet: mtk_eth_soc: set NETIF_F_ALL_TSO Felix Fietkau
@ 2022-11-07 18:54 ` Felix Fietkau
  2022-11-07 20:55 ` [PATCH 01/14] net: ethernet: mtk_eth_soc: account for vlan in rx header length Vladimir Oltean
  13 siblings, 0 replies; 37+ messages in thread
From: Felix Fietkau @ 2022-11-07 18:54 UTC (permalink / raw)
  To: netdev, John Crispin, Sean Wang, Mark Lee, David S. Miller,
	Eric Dumazet, Jakub Kicinski, Paolo Abeni, Matthias Brugger
  Cc: linux-arm-kernel, linux-mediatek, linux-kernel

Improves handling of DMA ring overflow.
Clarify other WDMA drop related comment.

Signed-off-by: Felix Fietkau <nbd@nbd.name>
---
 drivers/net/ethernet/mediatek/mtk_eth_soc.c | 5 ++++-
 drivers/net/ethernet/mediatek/mtk_eth_soc.h | 1 +
 2 files changed, 5 insertions(+), 1 deletion(-)

diff --git a/drivers/net/ethernet/mediatek/mtk_eth_soc.c b/drivers/net/ethernet/mediatek/mtk_eth_soc.c
index 50756c8aa871..4bd06ab1a2b5 100644
--- a/drivers/net/ethernet/mediatek/mtk_eth_soc.c
+++ b/drivers/net/ethernet/mediatek/mtk_eth_soc.c
@@ -3529,9 +3529,12 @@ static int mtk_hw_init(struct mtk_eth *eth)
 	mtk_w32(eth, 0x21021000, MTK_FE_INT_GRP);
 
 	if (MTK_HAS_CAPS(eth->soc->caps, MTK_NETSYS_V2)) {
-		/* PSE should not drop port8 and port9 packets */
+		/* PSE should not drop port8 and port9 packets from WDMA Tx */
 		mtk_w32(eth, 0x00000300, PSE_DROP_CFG);
 
+		/* PSE should drop packets to port 8/9 on WDMA Rx ring full */
+		mtk_w32(eth, 0x00000300, PSE_PPE0_DROP);
+
 		/* PSE Free Queue Flow Control  */
 		mtk_w32(eth, 0x01fa01f4, PSE_FQFC_CFG2);
 
diff --git a/drivers/net/ethernet/mediatek/mtk_eth_soc.h b/drivers/net/ethernet/mediatek/mtk_eth_soc.h
index bf8c7d11df9f..226022346369 100644
--- a/drivers/net/ethernet/mediatek/mtk_eth_soc.h
+++ b/drivers/net/ethernet/mediatek/mtk_eth_soc.h
@@ -124,6 +124,7 @@
 #define PSE_FQFC_CFG1		0x100
 #define PSE_FQFC_CFG2		0x104
 #define PSE_DROP_CFG		0x108
+#define PSE_PPE0_DROP		0x110
 
 /* PSE Input Queue Reservation Register*/
 #define PSE_IQ_REV(x)		(0x140 + (((x) - 1) << 2))
-- 
2.38.1


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

* Re: [PATCH 05/14] net: dsa: tag_mtk: assign per-port queues
  2022-11-07 18:54 ` [PATCH 05/14] net: dsa: tag_mtk: assign " Felix Fietkau
@ 2022-11-07 20:40   ` Vladimir Oltean
  2022-11-08  6:18     ` Felix Fietkau
  2022-11-07 21:22   ` Vladimir Oltean
  1 sibling, 1 reply; 37+ messages in thread
From: Vladimir Oltean @ 2022-11-07 20:40 UTC (permalink / raw)
  To: Felix Fietkau
  Cc: netdev, Sean Wang, Landen Chao, DENG Qingfang, Andrew Lunn,
	Vivien Didelot, Florian Fainelli, David S. Miller, Eric Dumazet,
	Jakub Kicinski, Paolo Abeni, Matthias Brugger, linux-arm-kernel,
	linux-mediatek, linux-kernel

Hi Felix,

On Mon, Nov 07, 2022 at 07:54:43PM +0100, Felix Fietkau wrote:
> Keeps traffic sent to the switch within link speed limits
> 
> Signed-off-by: Felix Fietkau <nbd@nbd.name>
> ---

Do you have a patch 00/14 that explains what you're up to? I'm only
copied on 05/14 and 10/14, hard to get an idea.

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

* Re: [PATCH 01/14] net: ethernet: mtk_eth_soc: account for vlan in rx header length
  2022-11-07 18:54 [PATCH 01/14] net: ethernet: mtk_eth_soc: account for vlan in rx header length Felix Fietkau
                   ` (12 preceding siblings ...)
  2022-11-07 18:54 ` [PATCH 14/14] net: ethernet: mtk_eth_soc: drop packets to WDMA if the ring is full Felix Fietkau
@ 2022-11-07 20:55 ` Vladimir Oltean
  2022-11-08  6:18   ` Felix Fietkau
  13 siblings, 1 reply; 37+ messages in thread
From: Vladimir Oltean @ 2022-11-07 20:55 UTC (permalink / raw)
  To: Felix Fietkau
  Cc: netdev, John Crispin, Sean Wang, Mark Lee, David S. Miller,
	Eric Dumazet, Jakub Kicinski, Paolo Abeni, Matthias Brugger,
	linux-arm-kernel, linux-mediatek, linux-kernel

On Mon, Nov 07, 2022 at 07:54:39PM +0100, Felix Fietkau wrote:
> This may be needed for correct MTU settings on devices using DSA
> 
> Signed-off-by: Felix Fietkau <nbd@nbd.name>
> ---
>  drivers/net/ethernet/mediatek/mtk_eth_soc.h | 2 +-
>  1 file changed, 1 insertion(+), 1 deletion(-)
> 
> diff --git a/drivers/net/ethernet/mediatek/mtk_eth_soc.h b/drivers/net/ethernet/mediatek/mtk_eth_soc.h
> index 589f27ddc401..dcf2a0d5da33 100644
> --- a/drivers/net/ethernet/mediatek/mtk_eth_soc.h
> +++ b/drivers/net/ethernet/mediatek/mtk_eth_soc.h
> @@ -29,7 +29,7 @@
>  #define MTK_TX_DMA_BUF_LEN_V2	0xffff
>  #define MTK_DMA_SIZE		512
>  #define MTK_MAC_COUNT		2
> -#define MTK_RX_ETH_HLEN		(ETH_HLEN + ETH_FCS_LEN)
> +#define MTK_RX_ETH_HLEN		(VLAN_ETH_HLEN + ETH_HLEN + ETH_FCS_LEN)

Commit title says account for VLAN (VLAN_HLEN, 4 bytes), code says add
VLAN_ETH_HLEN (18) more bytes.

Also, why is DSA mentioned in the commit message? Is accounting for VLAN
hlen not needed if DSA is not used? Why?

>  #define MTK_RX_HLEN		(NET_SKB_PAD + MTK_RX_ETH_HLEN + NET_IP_ALIGN)
>  #define MTK_DMA_DUMMY_DESC	0xffffffff
>  #define MTK_DEFAULT_MSG_ENABLE	(NETIF_MSG_DRV | \
> -- 
> 2.38.1
> 

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

* Re: [PATCH 05/14] net: dsa: tag_mtk: assign per-port queues
  2022-11-07 18:54 ` [PATCH 05/14] net: dsa: tag_mtk: assign " Felix Fietkau
  2022-11-07 20:40   ` Vladimir Oltean
@ 2022-11-07 21:22   ` Vladimir Oltean
  2022-11-08  6:01     ` Felix Fietkau
  1 sibling, 1 reply; 37+ messages in thread
From: Vladimir Oltean @ 2022-11-07 21:22 UTC (permalink / raw)
  To: Felix Fietkau
  Cc: netdev, Sean Wang, Landen Chao, DENG Qingfang, Andrew Lunn,
	Vivien Didelot, Florian Fainelli, David S. Miller, Eric Dumazet,
	Jakub Kicinski, Paolo Abeni, Matthias Brugger, linux-arm-kernel,
	linux-mediatek, linux-kernel

On Mon, Nov 07, 2022 at 07:54:43PM +0100, Felix Fietkau wrote:
> Keeps traffic sent to the switch within link speed limits
> 
> Signed-off-by: Felix Fietkau <nbd@nbd.name>
> ---
>  net/dsa/tag_mtk.c | 3 +++
>  1 file changed, 3 insertions(+)
> 
> diff --git a/net/dsa/tag_mtk.c b/net/dsa/tag_mtk.c
> index 415d8ece242a..445d6113227f 100644
> --- a/net/dsa/tag_mtk.c
> +++ b/net/dsa/tag_mtk.c
> @@ -25,6 +25,9 @@ static struct sk_buff *mtk_tag_xmit(struct sk_buff *skb,
>  	u8 xmit_tpid;
>  	u8 *mtk_tag;
>  
> +	/* Reserve the first three queues for packets not passed through DSA */
> +	skb_set_queue_mapping(skb, 3 + dp->index);
> +

Should DSA have to care about this detail, or could you rework your
mtk_select_queue() procedure to adjust the queue mapping as needed?

>  	/* Build the special tag after the MAC Source Address. If VLAN header
>  	 * is present, it's required that VLAN header and special tag is
>  	 * being combined. Only in this way we can allow the switch can parse
> -- 
> 2.38.1
> 

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

* Re: [PATCH 08/14] net: vlan: remove invalid VLAN protocol warning
  2022-11-07 18:54 ` [PATCH 08/14] net: vlan: remove invalid VLAN protocol warning Felix Fietkau
@ 2022-11-07 21:57   ` Vladimir Oltean
  2022-11-08  6:08     ` Felix Fietkau
  0 siblings, 1 reply; 37+ messages in thread
From: Vladimir Oltean @ 2022-11-07 21:57 UTC (permalink / raw)
  To: Felix Fietkau
  Cc: netdev, David S. Miller, Eric Dumazet, Jakub Kicinski,
	Paolo Abeni, linux-kernel

On Mon, Nov 07, 2022 at 07:54:46PM +0100, Felix Fietkau wrote:
> On MTK SoC ethernet, using NETIF_F_HW_VLAN_CTAG_RX in combination with hardware
> special tag parsing can pass the special tag port metadata as VLAN protocol ID.
> When the results is added as a skb hwaccel VLAN tag, it triggers a warning from
> vlan_do_receive before calling the DSA tag receive function.
> Remove this warning in order to properly pass the tag to the DSA receive function,
> which will parse and clear it.
> 
> Signed-off-by: Felix Fietkau <nbd@nbd.name>
> ---
>  net/8021q/vlan.h | 1 -
>  1 file changed, 1 deletion(-)
> 
> diff --git a/net/8021q/vlan.h b/net/8021q/vlan.h
> index 5eaf38875554..3f9c0406b266 100644
> --- a/net/8021q/vlan.h
> +++ b/net/8021q/vlan.h
> @@ -44,7 +44,6 @@ static inline int vlan_proto_idx(__be16 proto)
>  	case htons(ETH_P_8021AD):
>  		return VLAN_PROTO_8021AD;
>  	default:
> -		WARN(1, "invalid VLAN protocol: 0x%04x\n", ntohs(proto));

Why would you ever want to remove a warning that's telling you you're
doing something wrong?

Aren't you calling __vlan_hwaccel_put_tag() with the wrong thing (i.e.
htons(RX_DMA_VPID()) as opposed to VPID translated to something
digestible by the rest of the network stack.. ETH_P_8021Q, ETH_P_8021AD
etc)?

>  		return -EINVAL;
>  	}
>  }
> -- 
> 2.38.1
> 

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

* Re: [PATCH 11/14] net: ethernet: mtk_eth_soc: fix VLAN rx hardware acceleration
  2022-11-07 18:54 ` [PATCH 11/14] net: ethernet: mtk_eth_soc: fix VLAN rx hardware acceleration Felix Fietkau
@ 2022-11-07 23:32   ` Vladimir Oltean
  2022-11-08  6:17     ` Felix Fietkau
  0 siblings, 1 reply; 37+ messages in thread
From: Vladimir Oltean @ 2022-11-07 23:32 UTC (permalink / raw)
  To: Felix Fietkau
  Cc: netdev, John Crispin, Sean Wang, Mark Lee, David S. Miller,
	Eric Dumazet, Jakub Kicinski, Paolo Abeni, Matthias Brugger,
	Russell King, linux-arm-kernel, linux-mediatek, linux-kernel

On Mon, Nov 07, 2022 at 07:54:49PM +0100, Felix Fietkau wrote:
> - enable VLAN untagging for PDMA rx
> - make it possible to disable the feature via ethtool
> - pass VLAN tag to the DSA driver
> - untag special tag on PDMA only if no non-DSA devices are in use
> - disable special tag untagging on 7986 for now, since it's not working yet

What is the downside of not enabling VLAN RX offloading, is it a
performance or a functional need to have it?

> 
> Signed-off-by: Felix Fietkau <nbd@nbd.name>
> ---
>  drivers/net/ethernet/mediatek/mtk_eth_soc.c | 36 +++++++++++++--------
>  drivers/net/ethernet/mediatek/mtk_eth_soc.h |  3 ++
>  2 files changed, 25 insertions(+), 14 deletions(-)
> 
> diff --git a/drivers/net/ethernet/mediatek/mtk_eth_soc.c b/drivers/net/ethernet/mediatek/mtk_eth_soc.c
> index ab31dda2cd66..3b8995a483aa 100644
> --- a/drivers/net/ethernet/mediatek/mtk_eth_soc.c
> +++ b/drivers/net/ethernet/mediatek/mtk_eth_soc.c
> @@ -2015,16 +2015,9 @@ static int mtk_poll_rx(struct napi_struct *napi, int budget,
>  						htons(RX_DMA_VPID(trxd.rxd4)),
>  						RX_DMA_VID(trxd.rxd4));
>  			} else if (trxd.rxd2 & RX_DMA_VTAG) {
> -				__vlan_hwaccel_put_tag(skb, htons(ETH_P_8021Q),
> +				__vlan_hwaccel_put_tag(skb, htons(RX_DMA_VPID(trxd.rxd3)),

Why make this change? The network stack doesn't like it when you feed it
non-standard VLAN protocols, as you've noticed.

>  						       RX_DMA_VID(trxd.rxd3));
>  			}
> -
> -			/* If the device is attached to a dsa switch, the special
> -			 * tag inserted in VLAN field by hw switch can * be offloaded
> -			 * by RX HW VLAN offload. Clear vlan info.

What is the format of this special tag, what does it contain? The same
thing as what mtk_tag_rcv() parses?

> -			 */
> -			if (netdev_uses_dsa(netdev))
> -				__vlan_hwaccel_clear_tag(skb);

If the DSA switch information is present in the VLAN hwaccel, and the
VLAN hwaccel is cleared, and that up until this change,
NETIF_F_HW_VLAN_CTAG_RX was not configurable, it means that every
mtk_soc_data with MTK_HW_FEATURES would be broken as a DSA master?

>  		}
>  
>  		skb_record_rx_queue(skb, 0);
> @@ -2847,15 +2840,17 @@ static netdev_features_t mtk_fix_features(struct net_device *dev,
>  
>  static int mtk_set_features(struct net_device *dev, netdev_features_t features)
>  {
> -	int err = 0;
> -
> -	if (!((dev->features ^ features) & NETIF_F_LRO))
> -		return 0;
> +	struct mtk_mac *mac = netdev_priv(dev);
> +	struct mtk_eth *eth = mac->hw;
> +	netdev_features_t diff = dev->features ^ features;
>  
> -	if (!(features & NETIF_F_LRO))
> +	if ((diff & NETIF_F_LRO) && !(features & NETIF_F_LRO))
>  		mtk_hwlro_netdev_disable(dev);
>  
> -	return err;
> +	/* Set RX VLAN offloading */
> +	mtk_w32(eth, !!(features & NETIF_F_HW_VLAN_CTAG_RX), MTK_CDMP_EG_CTRL);

Nit: do this only if (diff & NETIF_F_HW_VLAN_CTAG_RX).

> +
> +	return 0;
>  }
>  
>  /* wait for DMA to finish whatever it is doing before we start using it again */
> @@ -3176,6 +3171,15 @@ static int mtk_open(struct net_device *dev)
>  	else
>  		refcount_inc(&eth->dma_refcnt);
>  
> +	/* Hardware special tag parsing needs to be disabled if at least
> +	 * one MAC does not use DSA.
> +	 */

Don't understand why, sorry.

> +	if (!netdev_uses_dsa(dev)) {
> +		u32 val = mtk_r32(eth, MTK_CDMP_IG_CTRL);
> +		val &= ~MTK_CDMP_STAG_EN;
> +		mtk_w32(eth, val, MTK_CDMP_IG_CTRL);
> +	}
> +
>  	phylink_start(mac->phylink);
>  	netif_tx_start_all_queues(dev);
>  
> @@ -3469,6 +3473,10 @@ static int mtk_hw_init(struct mtk_eth *eth)
>  	 */
>  	val = mtk_r32(eth, MTK_CDMQ_IG_CTRL);
>  	mtk_w32(eth, val | MTK_CDMQ_STAG_EN, MTK_CDMQ_IG_CTRL);
> +	if (MTK_HAS_CAPS(eth->soc->caps, MTK_NETSYS_V2)) {
> +		val = mtk_r32(eth, MTK_CDMP_IG_CTRL);
> +		mtk_w32(eth, val | MTK_CDMP_STAG_EN, MTK_CDMP_IG_CTRL);
> +	}
>  
>  	/* Enable RX VLan Offloading */
>  	mtk_w32(eth, 1, MTK_CDMP_EG_CTRL);
> diff --git a/drivers/net/ethernet/mediatek/mtk_eth_soc.h b/drivers/net/ethernet/mediatek/mtk_eth_soc.h
> index e09b2483c70c..26b2323185ef 100644
> --- a/drivers/net/ethernet/mediatek/mtk_eth_soc.h
> +++ b/drivers/net/ethernet/mediatek/mtk_eth_soc.h
> @@ -93,6 +93,9 @@
>  #define MTK_CDMQ_IG_CTRL	0x1400
>  #define MTK_CDMQ_STAG_EN	BIT(0)
>  
> +/* CDMQ Exgress Control Register */
> +#define MTK_CDMQ_EG_CTRL	0x1404
> +
>  /* CDMP Ingress Control Register */
>  #define MTK_CDMP_IG_CTRL	0x400
>  #define MTK_CDMP_STAG_EN	BIT(0)
> -- 
> 2.38.1
> 

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

* Re: [PATCH 05/14] net: dsa: tag_mtk: assign per-port queues
  2022-11-07 21:22   ` Vladimir Oltean
@ 2022-11-08  6:01     ` Felix Fietkau
  2022-11-08  7:58       ` Vladimir Oltean
  0 siblings, 1 reply; 37+ messages in thread
From: Felix Fietkau @ 2022-11-08  6:01 UTC (permalink / raw)
  To: Vladimir Oltean
  Cc: netdev, Sean Wang, Landen Chao, DENG Qingfang, Andrew Lunn,
	Vivien Didelot, Florian Fainelli, David S. Miller, Eric Dumazet,
	Jakub Kicinski, Paolo Abeni, Matthias Brugger, linux-arm-kernel,
	linux-mediatek, linux-kernel

On 07.11.22 22:22, Vladimir Oltean wrote:
> On Mon, Nov 07, 2022 at 07:54:43PM +0100, Felix Fietkau wrote:
>> Keeps traffic sent to the switch within link speed limits
>> 
>> Signed-off-by: Felix Fietkau <nbd@nbd.name>
>> ---
>>  net/dsa/tag_mtk.c | 3 +++
>>  1 file changed, 3 insertions(+)
>> 
>> diff --git a/net/dsa/tag_mtk.c b/net/dsa/tag_mtk.c
>> index 415d8ece242a..445d6113227f 100644
>> --- a/net/dsa/tag_mtk.c
>> +++ b/net/dsa/tag_mtk.c
>> @@ -25,6 +25,9 @@ static struct sk_buff *mtk_tag_xmit(struct sk_buff *skb,
>>  	u8 xmit_tpid;
>>  	u8 *mtk_tag;
>>  
>> +	/* Reserve the first three queues for packets not passed through DSA */
>> +	skb_set_queue_mapping(skb, 3 + dp->index);
>> +
> 
> Should DSA have to care about this detail, or could you rework your
> mtk_select_queue() procedure to adjust the queue mapping as needed?
I'm setting the queue here so that I don't have to add the extra 
overhead of parsing the payload in the ethernet driver.
For passing the queue, I used a similar approach as tag_brcm.c and
drivers/net/ethernet/broadcom/bcmsysport.c

- Felix

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

* Re: [PATCH 08/14] net: vlan: remove invalid VLAN protocol warning
  2022-11-07 21:57   ` Vladimir Oltean
@ 2022-11-08  6:08     ` Felix Fietkau
  2022-11-08  9:00       ` Vladimir Oltean
  0 siblings, 1 reply; 37+ messages in thread
From: Felix Fietkau @ 2022-11-08  6:08 UTC (permalink / raw)
  To: Vladimir Oltean
  Cc: netdev, David S. Miller, Eric Dumazet, Jakub Kicinski,
	Paolo Abeni, linux-kernel

On 07.11.22 22:57, Vladimir Oltean wrote:
> On Mon, Nov 07, 2022 at 07:54:46PM +0100, Felix Fietkau wrote:
>> On MTK SoC ethernet, using NETIF_F_HW_VLAN_CTAG_RX in combination with hardware
>> special tag parsing can pass the special tag port metadata as VLAN protocol ID.
>> When the results is added as a skb hwaccel VLAN tag, it triggers a warning from
>> vlan_do_receive before calling the DSA tag receive function.
>> Remove this warning in order to properly pass the tag to the DSA receive function,
>> which will parse and clear it.
>> 
>> Signed-off-by: Felix Fietkau <nbd@nbd.name>
>> ---
>>  net/8021q/vlan.h | 1 -
>>  1 file changed, 1 deletion(-)
>> 
>> diff --git a/net/8021q/vlan.h b/net/8021q/vlan.h
>> index 5eaf38875554..3f9c0406b266 100644
>> --- a/net/8021q/vlan.h
>> +++ b/net/8021q/vlan.h
>> @@ -44,7 +44,6 @@ static inline int vlan_proto_idx(__be16 proto)
>>  	case htons(ETH_P_8021AD):
>>  		return VLAN_PROTO_8021AD;
>>  	default:
>> -		WARN(1, "invalid VLAN protocol: 0x%04x\n", ntohs(proto));
> 
> Why would you ever want to remove a warning that's telling you you're
> doing something wrong?
> 
> Aren't you calling __vlan_hwaccel_put_tag() with the wrong thing (i.e.
> htons(RX_DMA_VPID()) as opposed to VPID translated to something
> digestible by the rest of the network stack.. ETH_P_8021Q, ETH_P_8021AD
> etc)?
The MTK ethernet hardware treats the DSA special tag as a VLAN tag and 
reports it as such. The ethernet driver passes this on as a hwaccel tag, 
and the MTK DSA tag parser consumes it. The only thing that's sitting in 
the middle looking at the tag is the VLAN device lookup with that warning.

Whenever DSA is not being used, the MTK ethernet device can also process 
regular VLAN tags. For those tags, htons(RX_DMA_VPID()) will contain the 
correct VPID.

- Felix

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

* Re: [PATCH 11/14] net: ethernet: mtk_eth_soc: fix VLAN rx hardware acceleration
  2022-11-07 23:32   ` Vladimir Oltean
@ 2022-11-08  6:17     ` Felix Fietkau
  0 siblings, 0 replies; 37+ messages in thread
From: Felix Fietkau @ 2022-11-08  6:17 UTC (permalink / raw)
  To: Vladimir Oltean
  Cc: netdev, John Crispin, Sean Wang, Mark Lee, David S. Miller,
	Eric Dumazet, Jakub Kicinski, Paolo Abeni, Matthias Brugger,
	Russell King, linux-arm-kernel, linux-mediatek, linux-kernel

On 08.11.22 00:32, Vladimir Oltean wrote:
> On Mon, Nov 07, 2022 at 07:54:49PM +0100, Felix Fietkau wrote:
>> - enable VLAN untagging for PDMA rx
>> - make it possible to disable the feature via ethtool
>> - pass VLAN tag to the DSA driver
>> - untag special tag on PDMA only if no non-DSA devices are in use
>> - disable special tag untagging on 7986 for now, since it's not working yet
> 
> What is the downside of not enabling VLAN RX offloading, is it a
> performance or a functional need to have it?
> 
>> 
>> Signed-off-by: Felix Fietkau <nbd@nbd.name>
>> ---
>>  drivers/net/ethernet/mediatek/mtk_eth_soc.c | 36 +++++++++++++--------
>>  drivers/net/ethernet/mediatek/mtk_eth_soc.h |  3 ++
>>  2 files changed, 25 insertions(+), 14 deletions(-)
>> 
>> diff --git a/drivers/net/ethernet/mediatek/mtk_eth_soc.c b/drivers/net/ethernet/mediatek/mtk_eth_soc.c
>> index ab31dda2cd66..3b8995a483aa 100644
>> --- a/drivers/net/ethernet/mediatek/mtk_eth_soc.c
>> +++ b/drivers/net/ethernet/mediatek/mtk_eth_soc.c
>> @@ -2015,16 +2015,9 @@ static int mtk_poll_rx(struct napi_struct *napi, int budget,
>>  						htons(RX_DMA_VPID(trxd.rxd4)),
>>  						RX_DMA_VID(trxd.rxd4));
>>  			} else if (trxd.rxd2 & RX_DMA_VTAG) {
>> -				__vlan_hwaccel_put_tag(skb, htons(ETH_P_8021Q),
>> +				__vlan_hwaccel_put_tag(skb, htons(RX_DMA_VPID(trxd.rxd3)),
> 
> Why make this change? The network stack doesn't like it when you feed it
> non-standard VLAN protocols, as you've noticed.
To make the hardware untag the DSA special tag, which is faster than 
doing it in the DSA tag driver.

>>  						       RX_DMA_VID(trxd.rxd3));
>>  			}
>> -
>> -			/* If the device is attached to a dsa switch, the special
>> -			 * tag inserted in VLAN field by hw switch can * be offloaded
>> -			 * by RX HW VLAN offload. Clear vlan info.
> 
> What is the format of this special tag, what does it contain? The same
> thing as what mtk_tag_rcv() parses?
Yes

>> -			 */
>> -			if (netdev_uses_dsa(netdev))
>> -				__vlan_hwaccel_clear_tag(skb);
> 
> If the DSA switch information is present in the VLAN hwaccel, and the
> VLAN hwaccel is cleared, and that up until this change,
> NETIF_F_HW_VLAN_CTAG_RX was not configurable, it means that every
> mtk_soc_data with MTK_HW_FEATURES would be broken as a DSA master?Before my change, the hardware wasn't actually untagging packets with 
the DSA special tag. Because of that, the code that I'm removing here 
was never used.

>>  		}
>>  
>>  		skb_record_rx_queue(skb, 0);
>> @@ -2847,15 +2840,17 @@ static netdev_features_t mtk_fix_features(struct net_device *dev,
>>  
>>  static int mtk_set_features(struct net_device *dev, netdev_features_t features)
>>  {
>> -	int err = 0;
>> -
>> -	if (!((dev->features ^ features) & NETIF_F_LRO))
>> -		return 0;
>> +	struct mtk_mac *mac = netdev_priv(dev);
>> +	struct mtk_eth *eth = mac->hw;
>> +	netdev_features_t diff = dev->features ^ features;
>>  
>> -	if (!(features & NETIF_F_LRO))
>> +	if ((diff & NETIF_F_LRO) && !(features & NETIF_F_LRO))
>>  		mtk_hwlro_netdev_disable(dev);
>>  
>> -	return err;
>> +	/* Set RX VLAN offloading */
>> +	mtk_w32(eth, !!(features & NETIF_F_HW_VLAN_CTAG_RX), MTK_CDMP_EG_CTRL);
> 
> Nit: do this only if (diff & NETIF_F_HW_VLAN_CTAG_RX).
Will fix that in v2.
> 
>> +
>> +	return 0;
>>  }
>>  
>>  /* wait for DMA to finish whatever it is doing before we start using it again */
>> @@ -3176,6 +3171,15 @@ static int mtk_open(struct net_device *dev)
>>  	else
>>  		refcount_inc(&eth->dma_refcnt);
>>  
>> +	/* Hardware special tag parsing needs to be disabled if at least
>> +	 * one MAC does not use DSA.
>> +	 */
> 
> Don't understand why, sorry.
The hardware has multiple ethernet MACs connected to the same DMA ring. 
The parsing flag can't be turned off per MAC and it makes the hardware 
assume that a DSA special tag is present.

>> +	if (!netdev_uses_dsa(dev)) {
>> +		u32 val = mtk_r32(eth, MTK_CDMP_IG_CTRL);
>> +		val &= ~MTK_CDMP_STAG_EN;
>> +		mtk_w32(eth, val, MTK_CDMP_IG_CTRL);
>> +	}
>> +
>>  	phylink_start(mac->phylink);
>>  	netif_tx_start_all_queues(dev);
>>  

- Felix

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

* Re: [PATCH 01/14] net: ethernet: mtk_eth_soc: account for vlan in rx header length
  2022-11-07 20:55 ` [PATCH 01/14] net: ethernet: mtk_eth_soc: account for vlan in rx header length Vladimir Oltean
@ 2022-11-08  6:18   ` Felix Fietkau
  0 siblings, 0 replies; 37+ messages in thread
From: Felix Fietkau @ 2022-11-08  6:18 UTC (permalink / raw)
  To: Vladimir Oltean
  Cc: netdev, John Crispin, Sean Wang, Mark Lee, David S. Miller,
	Eric Dumazet, Jakub Kicinski, Paolo Abeni, Matthias Brugger,
	linux-arm-kernel, linux-mediatek, linux-kernel

On 07.11.22 21:55, Vladimir Oltean wrote:
> On Mon, Nov 07, 2022 at 07:54:39PM +0100, Felix Fietkau wrote:
>> This may be needed for correct MTU settings on devices using DSA
>> 
>> Signed-off-by: Felix Fietkau <nbd@nbd.name>
>> ---
>>  drivers/net/ethernet/mediatek/mtk_eth_soc.h | 2 +-
>>  1 file changed, 1 insertion(+), 1 deletion(-)
>> 
>> diff --git a/drivers/net/ethernet/mediatek/mtk_eth_soc.h b/drivers/net/ethernet/mediatek/mtk_eth_soc.h
>> index 589f27ddc401..dcf2a0d5da33 100644
>> --- a/drivers/net/ethernet/mediatek/mtk_eth_soc.h
>> +++ b/drivers/net/ethernet/mediatek/mtk_eth_soc.h
>> @@ -29,7 +29,7 @@
>>  #define MTK_TX_DMA_BUF_LEN_V2	0xffff
>>  #define MTK_DMA_SIZE		512
>>  #define MTK_MAC_COUNT		2
>> -#define MTK_RX_ETH_HLEN		(ETH_HLEN + ETH_FCS_LEN)
>> +#define MTK_RX_ETH_HLEN		(VLAN_ETH_HLEN + ETH_HLEN + ETH_FCS_LEN)
> 
> Commit title says account for VLAN (VLAN_HLEN, 4 bytes), code says add
> VLAN_ETH_HLEN (18) more bytes.
> 
> Also, why is DSA mentioned in the commit message? Is accounting for VLAN
> hlen not needed if DSA is not used? Why?
Will fix the code and improve the comments in v2.

- Felix


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

* Re: [PATCH 05/14] net: dsa: tag_mtk: assign per-port queues
  2022-11-07 20:40   ` Vladimir Oltean
@ 2022-11-08  6:18     ` Felix Fietkau
  0 siblings, 0 replies; 37+ messages in thread
From: Felix Fietkau @ 2022-11-08  6:18 UTC (permalink / raw)
  To: Vladimir Oltean
  Cc: netdev, Sean Wang, Landen Chao, DENG Qingfang, Andrew Lunn,
	Vivien Didelot, Florian Fainelli, David S. Miller, Eric Dumazet,
	Jakub Kicinski, Paolo Abeni, Matthias Brugger, linux-arm-kernel,
	linux-mediatek, linux-kernel

On 07.11.22 21:40, Vladimir Oltean wrote:
> Hi Felix,
> 
> On Mon, Nov 07, 2022 at 07:54:43PM +0100, Felix Fietkau wrote:
>> Keeps traffic sent to the switch within link speed limits
>> 
>> Signed-off-by: Felix Fietkau <nbd@nbd.name>
>> ---
> 
> Do you have a patch 00/14 that explains what you're up to? I'm only
> copied on 05/14 and 10/14, hard to get an idea.
I will add it in v2

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

* Re: [PATCH 05/14] net: dsa: tag_mtk: assign per-port queues
  2022-11-08  6:01     ` Felix Fietkau
@ 2022-11-08  7:58       ` Vladimir Oltean
  2022-11-08  9:20         ` Felix Fietkau
  0 siblings, 1 reply; 37+ messages in thread
From: Vladimir Oltean @ 2022-11-08  7:58 UTC (permalink / raw)
  To: Felix Fietkau
  Cc: netdev, Sean Wang, Landen Chao, DENG Qingfang, Andrew Lunn,
	Vivien Didelot, Florian Fainelli, David S. Miller, Eric Dumazet,
	Jakub Kicinski, Paolo Abeni, Matthias Brugger, linux-arm-kernel,
	linux-mediatek, linux-kernel

On Tue, Nov 08, 2022 at 07:01:29AM +0100, Felix Fietkau wrote:
> On 07.11.22 22:22, Vladimir Oltean wrote:
> > On Mon, Nov 07, 2022 at 07:54:43PM +0100, Felix Fietkau wrote:
> > > Keeps traffic sent to the switch within link speed limits
> > > 
> > > Signed-off-by: Felix Fietkau <nbd@nbd.name>
> > > ---
> > >  net/dsa/tag_mtk.c | 3 +++
> > >  1 file changed, 3 insertions(+)
> > > 
> > > diff --git a/net/dsa/tag_mtk.c b/net/dsa/tag_mtk.c
> > > index 415d8ece242a..445d6113227f 100644
> > > --- a/net/dsa/tag_mtk.c
> > > +++ b/net/dsa/tag_mtk.c
> > > @@ -25,6 +25,9 @@ static struct sk_buff *mtk_tag_xmit(struct sk_buff *skb,
> > >  	u8 xmit_tpid;
> > >  	u8 *mtk_tag;
> > > +	/* Reserve the first three queues for packets not passed through DSA */
> > > +	skb_set_queue_mapping(skb, 3 + dp->index);
> > > +
> > 
> > Should DSA have to care about this detail, or could you rework your
> > mtk_select_queue() procedure to adjust the queue mapping as needed?
> I'm setting the queue here so that I don't have to add the extra overhead of
> parsing the payload in the ethernet driver.
> For passing the queue, I used a similar approach as tag_brcm.c and
> drivers/net/ethernet/broadcom/bcmsysport.c

I was just asking if you can't add the 3 elsewhere, since the DSA
tagging protocol shouldn't care how many MAC IDs the DSA master has.

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

* Re: [PATCH 08/14] net: vlan: remove invalid VLAN protocol warning
  2022-11-08  6:08     ` Felix Fietkau
@ 2022-11-08  9:00       ` Vladimir Oltean
  2022-11-08  9:20         ` Felix Fietkau
  0 siblings, 1 reply; 37+ messages in thread
From: Vladimir Oltean @ 2022-11-08  9:00 UTC (permalink / raw)
  To: Felix Fietkau
  Cc: netdev, David S. Miller, Eric Dumazet, Jakub Kicinski,
	Paolo Abeni, linux-kernel

On Tue, Nov 08, 2022 at 07:08:46AM +0100, Felix Fietkau wrote:
> On 07.11.22 22:57, Vladimir Oltean wrote:
> > Aren't you calling __vlan_hwaccel_put_tag() with the wrong thing (i.e.
> > htons(RX_DMA_VPID()) as opposed to VPID translated to something
> > digestible by the rest of the network stack.. ETH_P_8021Q, ETH_P_8021AD
> > etc)?
> 
> The MTK ethernet hardware treats the DSA special tag as a VLAN tag and
> reports it as such. The ethernet driver passes this on as a hwaccel tag, and
> the MTK DSA tag parser consumes it. The only thing that's sitting in the
> middle looking at the tag is the VLAN device lookup with that warning.
> 
> Whenever DSA is not being used, the MTK ethernet device can also process
> regular VLAN tags. For those tags, htons(RX_DMA_VPID()) will contain the
> correct VPID.

So I don't object to the overall theme of having the DSA master offload
the parsing and removal of the DSA tag, but you knock down a bit too
many fences if you carry the DSA tag in skb->vlan_present (not only VLAN
upper device lookup, but also the flow dissector).

What other information will be present in the offloaded DSA headers
except source port information? Maxime Chevallier is also working on a
similar problem for qca8k, except in that case, the RX DSA offload seems
to not be optional for him.

https://patchwork.kernel.org/project/netdevbpf/patch/20221104174151.439008-4-maxime.chevallier@bootlin.com/

Would a solution based on METADATA_HW_PORT_MUX and dst_metadata that
point to refcounted, preallocated structs work for Mediatek SoCs with
DSA, or would more information be necessary?

Meaning: mtk_eth_soc attaches the dst_metadata to the skb, tag_mtk.c
retrieves and removes it.

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

* Re: [PATCH 05/14] net: dsa: tag_mtk: assign per-port queues
  2022-11-08  7:58       ` Vladimir Oltean
@ 2022-11-08  9:20         ` Felix Fietkau
  0 siblings, 0 replies; 37+ messages in thread
From: Felix Fietkau @ 2022-11-08  9:20 UTC (permalink / raw)
  To: Vladimir Oltean
  Cc: netdev, Sean Wang, Landen Chao, DENG Qingfang, Andrew Lunn,
	Vivien Didelot, Florian Fainelli, David S. Miller, Eric Dumazet,
	Jakub Kicinski, Paolo Abeni, Matthias Brugger, linux-arm-kernel,
	linux-mediatek, linux-kernel

On 08.11.22 08:58, Vladimir Oltean wrote:
> On Tue, Nov 08, 2022 at 07:01:29AM +0100, Felix Fietkau wrote:
>> On 07.11.22 22:22, Vladimir Oltean wrote:
>> > On Mon, Nov 07, 2022 at 07:54:43PM +0100, Felix Fietkau wrote:
>> > > Keeps traffic sent to the switch within link speed limits
>> > > 
>> > > Signed-off-by: Felix Fietkau <nbd@nbd.name>
>> > > ---
>> > >  net/dsa/tag_mtk.c | 3 +++
>> > >  1 file changed, 3 insertions(+)
>> > > 
>> > > diff --git a/net/dsa/tag_mtk.c b/net/dsa/tag_mtk.c
>> > > index 415d8ece242a..445d6113227f 100644
>> > > --- a/net/dsa/tag_mtk.c
>> > > +++ b/net/dsa/tag_mtk.c
>> > > @@ -25,6 +25,9 @@ static struct sk_buff *mtk_tag_xmit(struct sk_buff *skb,
>> > >  	u8 xmit_tpid;
>> > >  	u8 *mtk_tag;
>> > > +	/* Reserve the first three queues for packets not passed through DSA */
>> > > +	skb_set_queue_mapping(skb, 3 + dp->index);
>> > > +
>> > 
>> > Should DSA have to care about this detail, or could you rework your
>> > mtk_select_queue() procedure to adjust the queue mapping as needed?
>> I'm setting the queue here so that I don't have to add the extra overhead of
>> parsing the payload in the ethernet driver.
>> For passing the queue, I used a similar approach as tag_brcm.c and
>> drivers/net/ethernet/broadcom/bcmsysport.c
> 
> I was just asking if you can't add the 3 elsewhere, since the DSA
> tagging protocol shouldn't care how many MAC IDs the DSA master has.
Sure, that would work. I'll change it in v2.

- Felix

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

* Re: [PATCH 08/14] net: vlan: remove invalid VLAN protocol warning
  2022-11-08  9:00       ` Vladimir Oltean
@ 2022-11-08  9:20         ` Felix Fietkau
  2022-11-08  9:40           ` Vladimir Oltean
  0 siblings, 1 reply; 37+ messages in thread
From: Felix Fietkau @ 2022-11-08  9:20 UTC (permalink / raw)
  To: Vladimir Oltean
  Cc: netdev, David S. Miller, Eric Dumazet, Jakub Kicinski,
	Paolo Abeni, linux-kernel

On 08.11.22 10:00, Vladimir Oltean wrote:
> On Tue, Nov 08, 2022 at 07:08:46AM +0100, Felix Fietkau wrote:
>> On 07.11.22 22:57, Vladimir Oltean wrote:
>> > Aren't you calling __vlan_hwaccel_put_tag() with the wrong thing (i.e.
>> > htons(RX_DMA_VPID()) as opposed to VPID translated to something
>> > digestible by the rest of the network stack.. ETH_P_8021Q, ETH_P_8021AD
>> > etc)?
>> 
>> The MTK ethernet hardware treats the DSA special tag as a VLAN tag and
>> reports it as such. The ethernet driver passes this on as a hwaccel tag, and
>> the MTK DSA tag parser consumes it. The only thing that's sitting in the
>> middle looking at the tag is the VLAN device lookup with that warning.
>> 
>> Whenever DSA is not being used, the MTK ethernet device can also process
>> regular VLAN tags. For those tags, htons(RX_DMA_VPID()) will contain the
>> correct VPID.
> 
> So I don't object to the overall theme of having the DSA master offload
> the parsing and removal of the DSA tag, but you knock down a bit too
> many fences if you carry the DSA tag in skb->vlan_present (not only VLAN
> upper device lookup, but also the flow dissector).
> 
> What other information will be present in the offloaded DSA headers
> except source port information? Maxime Chevallier is also working on a
> similar problem for qca8k, except in that case, the RX DSA offload seems
> to not be optional for him.
> 
> https://patchwork.kernel.org/project/netdevbpf/patch/20221104174151.439008-4-maxime.chevallier@bootlin.com/
> 
> Would a solution based on METADATA_HW_PORT_MUX and dst_metadata that
> point to refcounted, preallocated structs work for Mediatek SoCs with
> DSA, or would more information be necessary?
> 
> Meaning: mtk_eth_soc attaches the dst_metadata to the skb, tag_mtk.c
> retrieves and removes it.
I need to look into how METADATA_HW_PORT_MUX works, but I think it could 
work.

- Felix

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

* Re: [PATCH 08/14] net: vlan: remove invalid VLAN protocol warning
  2022-11-08  9:20         ` Felix Fietkau
@ 2022-11-08  9:40           ` Vladimir Oltean
  2022-11-08  9:46             ` Felix Fietkau
  0 siblings, 1 reply; 37+ messages in thread
From: Vladimir Oltean @ 2022-11-08  9:40 UTC (permalink / raw)
  To: Felix Fietkau
  Cc: netdev, David S. Miller, Eric Dumazet, Jakub Kicinski,
	Paolo Abeni, linux-kernel

On Tue, Nov 08, 2022 at 10:20:44AM +0100, Felix Fietkau wrote:
> I need to look into how METADATA_HW_PORT_MUX works, but I think it could
> work.

Could you please coordinate with Maxime to come up with something
common? Currently he proposes a generic "oob" tagger, while you propose
that we stay with the "mtk"/"qca" taggers, but they are taught to look
after offloaded metadata rather than in the packet. IMO your proposal
sounds better; the name of the tagging protocol is already exposed to
user space via /sys/class/net/<dsa-master>/dsa/tagging and therefore ABI.
It's just that we need a way to figure out how to make the flow
dissector and other layers not adjust for DSA header length if the DSA
tag is offloaded and not present in the packet.

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

* Re: [PATCH 08/14] net: vlan: remove invalid VLAN protocol warning
  2022-11-08  9:40           ` Vladimir Oltean
@ 2022-11-08  9:46             ` Felix Fietkau
  2022-11-08 10:08               ` Vladimir Oltean
  0 siblings, 1 reply; 37+ messages in thread
From: Felix Fietkau @ 2022-11-08  9:46 UTC (permalink / raw)
  To: Vladimir Oltean
  Cc: netdev, David S. Miller, Eric Dumazet, Jakub Kicinski,
	Paolo Abeni, linux-kernel

On 08.11.22 10:40, Vladimir Oltean wrote:
> On Tue, Nov 08, 2022 at 10:20:44AM +0100, Felix Fietkau wrote:
>> I need to look into how METADATA_HW_PORT_MUX works, but I think it could
>> work.
> 
> Could you please coordinate with Maxime to come up with something
> common? Currently he proposes a generic "oob" tagger, while you propose
> that we stay with the "mtk"/"qca" taggers, but they are taught to look
> after offloaded metadata rather than in the packet. IMO your proposal
> sounds better; the name of the tagging protocol is already exposed to
> user space via /sys/class/net/<dsa-master>/dsa/tagging and therefore ABI.
> It's just that we need a way to figure out how to make the flow
> dissector and other layers not adjust for DSA header length if the DSA
> tag is offloaded and not present in the packet.
I think it depends on the hardware. If you can rely on the hardware 
always reporting the port out-of-band, a generic "oob" tagger would be 
fine.
In my case, it depends on whether a second non-DSA ethernet MAC is 
active on the same device, so I do need to continue using the "mtk" tag 
driver.
The flow dissector part is already solved: I simply used the existing 
.flow_dissect() tag op.

- Felix

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

* Re: [PATCH 08/14] net: vlan: remove invalid VLAN protocol warning
  2022-11-08  9:46             ` Felix Fietkau
@ 2022-11-08 10:08               ` Vladimir Oltean
  2022-11-08 10:24                 ` Felix Fietkau
  0 siblings, 1 reply; 37+ messages in thread
From: Vladimir Oltean @ 2022-11-08 10:08 UTC (permalink / raw)
  To: Felix Fietkau
  Cc: netdev, David S. Miller, Eric Dumazet, Jakub Kicinski,
	Paolo Abeni, linux-kernel

On Tue, Nov 08, 2022 at 10:46:54AM +0100, Felix Fietkau wrote:
> I think it depends on the hardware. If you can rely on the hardware always
> reporting the port out-of-band, a generic "oob" tagger would be fine.
> In my case, it depends on whether a second non-DSA ethernet MAC is active on
> the same device, so I do need to continue using the "mtk" tag driver.

It's not only about the time dimension (always OOB, vs sometimes OOB),
but also about what is conveyed through the OOB tag. I can see 2 vendors
agreeing today on a common "oob" tagger only to diverge in the future
when they'll need to convey more information than just port id. What do
you do with the tagging protocol string names then. Gotta make them
unique from the get go, can't export "oob" to user space IMO.

> The flow dissector part is already solved: I simply used the existing
> .flow_dissect() tag op.

Yes, well this seems like a generic enough case (DSA offload tag present
=> don't shift network header because it's where it should be) to treat
it in the generic flow dissector and not have to invoke any tagger-specific
fixup method.

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

* Re: [PATCH 08/14] net: vlan: remove invalid VLAN protocol warning
  2022-11-08 10:08               ` Vladimir Oltean
@ 2022-11-08 10:24                 ` Felix Fietkau
  2022-11-08 10:33                   ` Vladimir Oltean
  0 siblings, 1 reply; 37+ messages in thread
From: Felix Fietkau @ 2022-11-08 10:24 UTC (permalink / raw)
  To: Vladimir Oltean
  Cc: netdev, David S. Miller, Eric Dumazet, Jakub Kicinski,
	Paolo Abeni, linux-kernel

On 08.11.22 11:08, Vladimir Oltean wrote:
> On Tue, Nov 08, 2022 at 10:46:54AM +0100, Felix Fietkau wrote:
>> I think it depends on the hardware. If you can rely on the hardware always
>> reporting the port out-of-band, a generic "oob" tagger would be fine.
>> In my case, it depends on whether a second non-DSA ethernet MAC is active on
>> the same device, so I do need to continue using the "mtk" tag driver.
> 
> It's not only about the time dimension (always OOB, vs sometimes OOB),
> but also about what is conveyed through the OOB tag. I can see 2 vendors
> agreeing today on a common "oob" tagger only to diverge in the future
> when they'll need to convey more information than just port id. What do
> you do with the tagging protocol string names then. Gotta make them
> unique from the get go, can't export "oob" to user space IMO.
> 
>> The flow dissector part is already solved: I simply used the existing
>> .flow_dissect() tag op.
> 
> Yes, well this seems like a generic enough case (DSA offload tag present
> => don't shift network header because it's where it should be) to treat
> it in the generic flow dissector and not have to invoke any tagger-specific
> fixup method.
In that case I think we shouldn't use METADATA_HW_PORT_MUX, since it is 
already used for other purposes. I will add a new metadata type 
METADATA_DSA instead.

- Felix

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

* Re: [PATCH 08/14] net: vlan: remove invalid VLAN protocol warning
  2022-11-08 10:24                 ` Felix Fietkau
@ 2022-11-08 10:33                   ` Vladimir Oltean
  2022-11-08 10:42                     ` Felix Fietkau
  0 siblings, 1 reply; 37+ messages in thread
From: Vladimir Oltean @ 2022-11-08 10:33 UTC (permalink / raw)
  To: Felix Fietkau
  Cc: netdev, David S. Miller, Eric Dumazet, Jakub Kicinski,
	Paolo Abeni, linux-kernel

On Tue, Nov 08, 2022 at 11:24:51AM +0100, Felix Fietkau wrote:
> On 08.11.22 11:08, Vladimir Oltean wrote:
> > On Tue, Nov 08, 2022 at 10:46:54AM +0100, Felix Fietkau wrote:
> > > I think it depends on the hardware. If you can rely on the hardware always
> > > reporting the port out-of-band, a generic "oob" tagger would be fine.
> > > In my case, it depends on whether a second non-DSA ethernet MAC is active on
> > > the same device, so I do need to continue using the "mtk" tag driver.
> > 
> > It's not only about the time dimension (always OOB, vs sometimes OOB),
> > but also about what is conveyed through the OOB tag. I can see 2 vendors
> > agreeing today on a common "oob" tagger only to diverge in the future
> > when they'll need to convey more information than just port id. What do
> > you do with the tagging protocol string names then. Gotta make them
> > unique from the get go, can't export "oob" to user space IMO.
> > 
> > > The flow dissector part is already solved: I simply used the existing
> > > .flow_dissect() tag op.
> > 
> > Yes, well this seems like a generic enough case (DSA offload tag present
> > => don't shift network header because it's where it should be) to treat
> > it in the generic flow dissector and not have to invoke any tagger-specific
> > fixup method.
> 
> In that case I think we shouldn't use METADATA_HW_PORT_MUX, since it is
> already used for other purposes. I will add a new metadata type METADATA_DSA
> instead.

Which case, flow dissector figuring out that DSA offload tag is present?
Well, the skb can only carry one dst pointer ATM, so if it's METADATA_HW_PORT_MUX
but it belongs to SR-IOV on the DSA master, we have bigger problems anyway.
So, proto == ETH_P_XDSA && have METADATA_HW_PORT_MUX should be pretty
good indication that DSA offload tag is present.

Anyway I raised this concern as well to Jakub as well. Seems to be
theoretical at the moment. Using METADATA_HW_PORT_MUX seems to be fine
right now. Can be changed later if needed; it's not ABI.

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

* Re: [PATCH 08/14] net: vlan: remove invalid VLAN protocol warning
  2022-11-08 10:33                   ` Vladimir Oltean
@ 2022-11-08 10:42                     ` Felix Fietkau
  2022-11-08 10:52                       ` Vladimir Oltean
  0 siblings, 1 reply; 37+ messages in thread
From: Felix Fietkau @ 2022-11-08 10:42 UTC (permalink / raw)
  To: Vladimir Oltean
  Cc: netdev, David S. Miller, Eric Dumazet, Jakub Kicinski,
	Paolo Abeni, linux-kernel

On 08.11.22 11:33, Vladimir Oltean wrote:
> On Tue, Nov 08, 2022 at 11:24:51AM +0100, Felix Fietkau wrote:
>> On 08.11.22 11:08, Vladimir Oltean wrote:
>> > On Tue, Nov 08, 2022 at 10:46:54AM +0100, Felix Fietkau wrote:
>> > > I think it depends on the hardware. If you can rely on the hardware always
>> > > reporting the port out-of-band, a generic "oob" tagger would be fine.
>> > > In my case, it depends on whether a second non-DSA ethernet MAC is active on
>> > > the same device, so I do need to continue using the "mtk" tag driver.
>> > 
>> > It's not only about the time dimension (always OOB, vs sometimes OOB),
>> > but also about what is conveyed through the OOB tag. I can see 2 vendors
>> > agreeing today on a common "oob" tagger only to diverge in the future
>> > when they'll need to convey more information than just port id. What do
>> > you do with the tagging protocol string names then. Gotta make them
>> > unique from the get go, can't export "oob" to user space IMO.
>> > 
>> > > The flow dissector part is already solved: I simply used the existing
>> > > .flow_dissect() tag op.
>> > 
>> > Yes, well this seems like a generic enough case (DSA offload tag present
>> > => don't shift network header because it's where it should be) to treat
>> > it in the generic flow dissector and not have to invoke any tagger-specific
>> > fixup method.
>> 
>> In that case I think we shouldn't use METADATA_HW_PORT_MUX, since it is
>> already used for other purposes. I will add a new metadata type METADATA_DSA
>> instead.
> 
> Which case, flow dissector figuring out that DSA offload tag is present?
> Well, the skb can only carry one dst pointer ATM, so if it's METADATA_HW_PORT_MUX
> but it belongs to SR-IOV on the DSA master, we have bigger problems anyway.
> So, proto == ETH_P_XDSA && have METADATA_HW_PORT_MUX should be pretty
> good indication that DSA offload tag is present.
> 
> Anyway I raised this concern as well to Jakub as well. Seems to be
> theoretical at the moment. Using METADATA_HW_PORT_MUX seems to be fine
> right now. Can be changed later if needed; it's not ABI.
Okay, I will stick with METADATA_HW_PORT_MUX for now. If we use it in 
the flow dissector to avoid the tagger specific fixup, we might as well 
use it in DSA to skip the tag proto receive call. What do you think?

- Felix

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

* Re: [PATCH 08/14] net: vlan: remove invalid VLAN protocol warning
  2022-11-08 10:42                     ` Felix Fietkau
@ 2022-11-08 10:52                       ` Vladimir Oltean
  2022-11-08 10:56                         ` Felix Fietkau
  0 siblings, 1 reply; 37+ messages in thread
From: Vladimir Oltean @ 2022-11-08 10:52 UTC (permalink / raw)
  To: Felix Fietkau
  Cc: netdev, David S. Miller, Eric Dumazet, Jakub Kicinski,
	Paolo Abeni, linux-kernel

On Tue, Nov 08, 2022 at 11:42:09AM +0100, Felix Fietkau wrote:
> Okay, I will stick with METADATA_HW_PORT_MUX for now. If we use it in the
> flow dissector to avoid the tagger specific fixup, we might as well use it
> in DSA to skip the tag proto receive call. What do you think?

I suppose that dsa_switch_rcv() could test for the presence of a metadata_dst
and treat that generically if present, without unnecessarily calling down into
the tagging protocol ->rcv() call. The assumption being that the metadata_dst
is always formatted (by the DSA master) in a vendor-agnostic way.

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

* Re: [PATCH 08/14] net: vlan: remove invalid VLAN protocol warning
  2022-11-08 10:52                       ` Vladimir Oltean
@ 2022-11-08 10:56                         ` Felix Fietkau
  2022-11-08 11:23                           ` Vladimir Oltean
  0 siblings, 1 reply; 37+ messages in thread
From: Felix Fietkau @ 2022-11-08 10:56 UTC (permalink / raw)
  To: Vladimir Oltean
  Cc: netdev, David S. Miller, Eric Dumazet, Jakub Kicinski,
	Paolo Abeni, linux-kernel

On 08.11.22 11:52, Vladimir Oltean wrote:
> On Tue, Nov 08, 2022 at 11:42:09AM +0100, Felix Fietkau wrote:
>> Okay, I will stick with METADATA_HW_PORT_MUX for now. If we use it in the
>> flow dissector to avoid the tagger specific fixup, we might as well use it
>> in DSA to skip the tag proto receive call. What do you think?
> 
> I suppose that dsa_switch_rcv() could test for the presence of a metadata_dst
> and treat that generically if present, without unnecessarily calling down into
> the tagging protocol ->rcv() call. The assumption being that the metadata_dst
> is always formatted (by the DSA master) in a vendor-agnostic way.
Right. The assumption is that if we use METADATA_HW_PORT_MUX, the field 
md_dst->u.port_info.port_id will contain the index of the DSA port.

- Felix

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

* Re: [PATCH 08/14] net: vlan: remove invalid VLAN protocol warning
  2022-11-08 10:56                         ` Felix Fietkau
@ 2022-11-08 11:23                           ` Vladimir Oltean
  0 siblings, 0 replies; 37+ messages in thread
From: Vladimir Oltean @ 2022-11-08 11:23 UTC (permalink / raw)
  To: Felix Fietkau
  Cc: netdev, David S. Miller, Eric Dumazet, Jakub Kicinski,
	Paolo Abeni, linux-kernel

On Tue, Nov 08, 2022 at 11:56:52AM +0100, Felix Fietkau wrote:
> On 08.11.22 11:52, Vladimir Oltean wrote:
> > On Tue, Nov 08, 2022 at 11:42:09AM +0100, Felix Fietkau wrote:
> > > Okay, I will stick with METADATA_HW_PORT_MUX for now. If we use it in the
> > > flow dissector to avoid the tagger specific fixup, we might as well use it
> > > in DSA to skip the tag proto receive call. What do you think?
> > 
> > I suppose that dsa_switch_rcv() could test for the presence of a metadata_dst
> > and treat that generically if present, without unnecessarily calling down into
> > the tagging protocol ->rcv() call. The assumption being that the metadata_dst
> > is always formatted (by the DSA master) in a vendor-agnostic way.
> 
> Right. The assumption is that if we use METADATA_HW_PORT_MUX, the field
> md_dst->u.port_info.port_id will contain the index of the DSA port.

Yes. Please coordinate with Maxime, see if it's possible to do something
similar (generic) on TX, depending on whether the DSA master reports it
can interpret metadata_dst as offloaded DSA tags. You didn't copy too
many folks to this patch set, so others might have missed it.

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

end of thread, other threads:[~2022-11-08 11:23 UTC | newest]

Thread overview: 37+ messages (download: mbox.gz / follow: Atom feed)
-- links below jump to the message on this page --
2022-11-07 18:54 [PATCH 01/14] net: ethernet: mtk_eth_soc: account for vlan in rx header length Felix Fietkau
2022-11-07 18:54 ` [PATCH 02/14] net: ethernet: mtk_eth_soc: increase tx ring side for QDMA devices Felix Fietkau
2022-11-07 18:54 ` [PATCH 03/14] net: ethernet: mtk_eth_soc: avoid port_mg assignment on MT7622 and newer Felix Fietkau
2022-11-07 18:54 ` [PATCH 04/14] net: ethernet: mtk_eth_soc: implement multi-queue support for per-port queues Felix Fietkau
2022-11-07 18:54 ` [PATCH 05/14] net: dsa: tag_mtk: assign " Felix Fietkau
2022-11-07 20:40   ` Vladimir Oltean
2022-11-08  6:18     ` Felix Fietkau
2022-11-07 21:22   ` Vladimir Oltean
2022-11-08  6:01     ` Felix Fietkau
2022-11-08  7:58       ` Vladimir Oltean
2022-11-08  9:20         ` Felix Fietkau
2022-11-07 18:54 ` [PATCH 06/14] net: ethernet: mediatek: ppe: assign per-port queues for offloaded traffic Felix Fietkau
2022-11-07 18:54 ` [PATCH 07/14] net: ethernet: mtk_eth_soc: compile out netsys v2 code on mt7621 Felix Fietkau
2022-11-07 18:54 ` [PATCH 08/14] net: vlan: remove invalid VLAN protocol warning Felix Fietkau
2022-11-07 21:57   ` Vladimir Oltean
2022-11-08  6:08     ` Felix Fietkau
2022-11-08  9:00       ` Vladimir Oltean
2022-11-08  9:20         ` Felix Fietkau
2022-11-08  9:40           ` Vladimir Oltean
2022-11-08  9:46             ` Felix Fietkau
2022-11-08 10:08               ` Vladimir Oltean
2022-11-08 10:24                 ` Felix Fietkau
2022-11-08 10:33                   ` Vladimir Oltean
2022-11-08 10:42                     ` Felix Fietkau
2022-11-08 10:52                       ` Vladimir Oltean
2022-11-08 10:56                         ` Felix Fietkau
2022-11-08 11:23                           ` Vladimir Oltean
2022-11-07 18:54 ` [PATCH 09/14] flow_dissector: detect DSA using skb->protocol even when VLAN tag is present Felix Fietkau
2022-11-07 18:54 ` [PATCH 10/14] net: dsa: tag_mtk: parse hwaccel VLAN tags Felix Fietkau
2022-11-07 18:54 ` [PATCH 11/14] net: ethernet: mtk_eth_soc: fix VLAN rx hardware acceleration Felix Fietkau
2022-11-07 23:32   ` Vladimir Oltean
2022-11-08  6:17     ` Felix Fietkau
2022-11-07 18:54 ` [PATCH 12/14] net: ethernet: mtk_eth_soc: work around issue with sending small fragments Felix Fietkau
2022-11-07 18:54 ` [PATCH 13/14] net: ethernet: mtk_eth_soc: set NETIF_F_ALL_TSO Felix Fietkau
2022-11-07 18:54 ` [PATCH 14/14] net: ethernet: mtk_eth_soc: drop packets to WDMA if the ring is full Felix Fietkau
2022-11-07 20:55 ` [PATCH 01/14] net: ethernet: mtk_eth_soc: account for vlan in rx header length Vladimir Oltean
2022-11-08  6:18   ` Felix Fietkau

This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox;
as well as URLs for NNTP newsgroup(s).