* Multiqueue support for mtk_eth_soc
@ 2022-11-16 8:07 Felix Fietkau
2022-11-16 8:07 ` [PATCH net-next 1/6] net: ethernet: mtk_eth_soc: increase tx ring size for QDMA devices Felix Fietkau
` (5 more replies)
0 siblings, 6 replies; 11+ messages in thread
From: Felix Fietkau @ 2022-11-16 8:07 UTC (permalink / raw)
To: netdev, Matthias Brugger; +Cc: linux-arm-kernel, linux-mediatek
This series implements multiqueue support on devices with QDMA (MT7621 and newer)
by using the SoC's traffic shaper function, which is part of the QDMA engine.
The driver exposes traffic shaper queues as network stack queues and configures
them to the link speed limit.
This fixes an issue where traffic to slower ports would drown out traffic to
faster ports. It also fixes packet drops and jitter when running hardware
offloaded traffic alongside traffic from the CPU.
Felix Fietkau (6):
net: ethernet: mtk_eth_soc: increase tx ring size for QDMA devices
net: ethernet: mtk_eth_soc: drop packets to WDMA if the ring is full
net: ethernet: mtk_eth_soc: avoid port_mg assignment on MT7622 and
newer
net: ethernet: mtk_eth_soc: implement multi-queue support for per-port
queues
net: dsa: tag_mtk: assign per-port queues
net: ethernet: mediatek: ppe: assign per-port queues for offloaded
traffic
drivers/net/ethernet/mediatek/mtk_eth_soc.c | 328 ++++++++++++++----
drivers/net/ethernet/mediatek/mtk_eth_soc.h | 28 +-
drivers/net/ethernet/mediatek/mtk_ppe.c | 22 +-
drivers/net/ethernet/mediatek/mtk_ppe.h | 4 +
.../net/ethernet/mediatek/mtk_ppe_offload.c | 12 +-
net/dsa/tag_mtk.c | 2 +
6 files changed, 324 insertions(+), 72 deletions(-)
--
2.38.1
^ permalink raw reply [flat|nested] 11+ messages in thread
* [PATCH net-next 1/6] net: ethernet: mtk_eth_soc: increase tx ring size for QDMA devices
2022-11-16 8:07 Multiqueue support for mtk_eth_soc Felix Fietkau
@ 2022-11-16 8:07 ` Felix Fietkau
2022-11-19 3:50 ` patchwork-bot+netdevbpf
2022-11-16 8:07 ` [PATCH net-next 2/6] net: ethernet: mtk_eth_soc: drop packets to WDMA if the ring is full Felix Fietkau
` (4 subsequent siblings)
5 siblings, 1 reply; 11+ messages in thread
From: Felix Fietkau @ 2022-11-16 8:07 UTC (permalink / raw)
To: netdev, John Crispin, Sean Wang, Mark Lee, Lorenzo Bianconi,
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 3e9f5536f0f3..a9a6b53b4286 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;
@@ -2208,19 +2208,25 @@ static int mtk_tx_alloc(struct mtk_eth *eth)
struct mtk_tx_ring *ring = ð->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;
@@ -2240,22 +2246,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
@@ -2267,14 +2273,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);
}
@@ -2292,7 +2298,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;
@@ -2300,14 +2306,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;
}
@@ -2842,7 +2848,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 a572416e25de..72d3bfc2323d 100644
--- a/drivers/net/ethernet/mediatek/mtk_eth_soc.h
+++ b/drivers/net/ethernet/mediatek/mtk_eth_soc.h
@@ -30,6 +30,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 (ETH_HLEN + ETH_FCS_LEN)
--
2.38.1
^ permalink raw reply related [flat|nested] 11+ messages in thread
* [PATCH net-next 2/6] net: ethernet: mtk_eth_soc: drop packets to WDMA if the ring is full
2022-11-16 8:07 Multiqueue support for mtk_eth_soc Felix Fietkau
2022-11-16 8:07 ` [PATCH net-next 1/6] net: ethernet: mtk_eth_soc: increase tx ring size for QDMA devices Felix Fietkau
@ 2022-11-16 8:07 ` Felix Fietkau
2022-11-16 8:07 ` [PATCH net-next 3/6] net: ethernet: mtk_eth_soc: avoid port_mg assignment on MT7622 and newer Felix Fietkau
` (3 subsequent siblings)
5 siblings, 0 replies; 11+ messages in thread
From: Felix Fietkau @ 2022-11-16 8:07 UTC (permalink / raw)
To: netdev, John Crispin, Sean Wang, Mark Lee, Lorenzo Bianconi,
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 a9a6b53b4286..fbfc23923bf5 100644
--- a/drivers/net/ethernet/mediatek/mtk_eth_soc.c
+++ b/drivers/net/ethernet/mediatek/mtk_eth_soc.c
@@ -3393,9 +3393,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 72d3bfc2323d..eaaa0c67ef2a 100644
--- a/drivers/net/ethernet/mediatek/mtk_eth_soc.h
+++ b/drivers/net/ethernet/mediatek/mtk_eth_soc.h
@@ -127,6 +127,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] 11+ messages in thread
* [PATCH net-next 3/6] net: ethernet: mtk_eth_soc: avoid port_mg assignment on MT7622 and newer
2022-11-16 8:07 Multiqueue support for mtk_eth_soc Felix Fietkau
2022-11-16 8:07 ` [PATCH net-next 1/6] net: ethernet: mtk_eth_soc: increase tx ring size for QDMA devices Felix Fietkau
2022-11-16 8:07 ` [PATCH net-next 2/6] net: ethernet: mtk_eth_soc: drop packets to WDMA if the ring is full Felix Fietkau
@ 2022-11-16 8:07 ` Felix Fietkau
2022-11-16 8:07 ` [PATCH net-next 4/6] net: ethernet: mtk_eth_soc: implement multi-queue support for per-port queues Felix Fietkau
` (2 subsequent siblings)
5 siblings, 0 replies; 11+ messages in thread
From: Felix Fietkau @ 2022-11-16 8:07 UTC (permalink / raw)
To: netdev, John Crispin, Sean Wang, Mark Lee, Lorenzo Bianconi,
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 fbfc23923bf5..9e5545242216 100644
--- a/drivers/net/ethernet/mediatek/mtk_eth_soc.c
+++ b/drivers/net/ethernet/mediatek/mtk_eth_soc.c
@@ -4312,7 +4312,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 = {
@@ -4351,7 +4351,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] 11+ messages in thread
* [PATCH net-next 4/6] net: ethernet: mtk_eth_soc: implement multi-queue support for per-port queues
2022-11-16 8:07 Multiqueue support for mtk_eth_soc Felix Fietkau
` (2 preceding siblings ...)
2022-11-16 8:07 ` [PATCH net-next 3/6] net: ethernet: mtk_eth_soc: avoid port_mg assignment on MT7622 and newer Felix Fietkau
@ 2022-11-16 8:07 ` Felix Fietkau
2022-11-18 15:13 ` Alexander 'lynxis' Couzens
2022-11-16 8:07 ` [PATCH net-next 5/6] net: dsa: tag_mtk: assign " Felix Fietkau
2022-11-16 8:07 ` [PATCH net-next 6/6] net: ethernet: mediatek: ppe: assign per-port queues for offloaded traffic Felix Fietkau
5 siblings, 1 reply; 11+ messages in thread
From: Felix Fietkau @ 2022-11-16 8:07 UTC (permalink / raw)
To: netdev, John Crispin, Sean Wang, Mark Lee, Lorenzo Bianconi,
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 | 281 ++++++++++++++++----
drivers/net/ethernet/mediatek/mtk_eth_soc.h | 26 +-
2 files changed, 258 insertions(+), 49 deletions(-)
diff --git a/drivers/net/ethernet/mediatek/mtk_eth_soc.c b/drivers/net/ethernet/mediatek/mtk_eth_soc.c
index 9e5545242216..e1cc813bbb6f 100644
--- a/drivers/net/ethernet/mediatek/mtk_eth_soc.c
+++ b/drivers/net/ethernet/mediatek/mtk_eth_soc.c
@@ -55,6 +55,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,
@@ -62,6 +63,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,
@@ -114,6 +116,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,
@@ -131,6 +134,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,
@@ -614,6 +618,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,
@@ -639,6 +712,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(ð->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(ð->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 = ð->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++;
@@ -1992,8 +2070,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 = ð->tx_ring;
@@ -2025,12 +2141,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);
@@ -2049,7 +2162,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 = ð->tx_ring;
struct mtk_tx_buf *tx_buf;
@@ -2067,12 +2180,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);
@@ -2094,26 +2203,15 @@ static int mtk_poll_tx(struct mtk_eth *eth, int budget)
{
struct mtk_tx_ring *ring = ð->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);
@@ -2123,7 +2221,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)
@@ -2209,6 +2307,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;
@@ -2276,8 +2375,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);
@@ -2957,7 +3073,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);
@@ -3014,6 +3130,45 @@ static bool mtk_uses_dsa(struct net_device *dev)
#endif
}
+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);
@@ -3078,7 +3233,8 @@ static int mtk_open(struct net_device *dev)
refcount_inc(ð->dma_refcnt);
phylink_start(mac->phylink);
- netif_start_queue(dev);
+ netif_tx_start_all_queues(dev);
+
return 0;
}
@@ -3607,8 +3763,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]);
}
@@ -3824,6 +3984,23 @@ 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) + 3;
+ else
+ 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,
@@ -3859,6 +4036,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)
@@ -3868,6 +4046,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");
@@ -3885,7 +4064,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;
@@ -3982,6 +4164,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 eaaa0c67ef2a..1581eba053ab 100644
--- a/drivers/net/ethernet/mediatek/mtk_eth_soc.h
+++ b/drivers/net/ethernet/mediatek/mtk_eth_soc.h
@@ -25,6 +25,7 @@
#define MTK_MAX_DSA_PORTS 7
#define MTK_DSA_PORT_MASK GENMASK(2, 0)
+#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
@@ -210,8 +211,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)
@@ -230,6 +249,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)
@@ -258,8 +278,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
@@ -289,6 +307,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)
@@ -947,6 +966,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 */
@@ -964,6 +984,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;
@@ -1157,6 +1178,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] 11+ messages in thread
* [PATCH net-next 5/6] net: dsa: tag_mtk: assign per-port queues
2022-11-16 8:07 Multiqueue support for mtk_eth_soc Felix Fietkau
` (3 preceding siblings ...)
2022-11-16 8:07 ` [PATCH net-next 4/6] net: ethernet: mtk_eth_soc: implement multi-queue support for per-port queues Felix Fietkau
@ 2022-11-16 8:07 ` Felix Fietkau
2022-11-16 18:26 ` Florian Fainelli
2022-11-16 8:07 ` [PATCH net-next 6/6] net: ethernet: mediatek: ppe: assign per-port queues for offloaded traffic Felix Fietkau
5 siblings, 1 reply; 11+ messages in thread
From: Felix Fietkau @ 2022-11-16 8:07 UTC (permalink / raw)
To: netdev, Sean Wang, Landen Chao, DENG Qingfang, Andrew Lunn,
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 | 2 ++
1 file changed, 2 insertions(+)
diff --git a/net/dsa/tag_mtk.c b/net/dsa/tag_mtk.c
index 415d8ece242a..5953356b829d 100644
--- a/net/dsa/tag_mtk.c
+++ b/net/dsa/tag_mtk.c
@@ -25,6 +25,8 @@ static struct sk_buff *mtk_tag_xmit(struct sk_buff *skb,
u8 xmit_tpid;
u8 *mtk_tag;
+ skb_set_queue_mapping(skb, 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] 11+ messages in thread
* [PATCH net-next 6/6] net: ethernet: mediatek: ppe: assign per-port queues for offloaded traffic
2022-11-16 8:07 Multiqueue support for mtk_eth_soc Felix Fietkau
` (4 preceding siblings ...)
2022-11-16 8:07 ` [PATCH net-next 5/6] net: dsa: tag_mtk: assign " Felix Fietkau
@ 2022-11-16 8:07 ` Felix Fietkau
5 siblings, 0 replies; 11+ messages in thread
From: Felix Fietkau @ 2022-11-16 8:07 UTC (permalink / raw)
To: netdev, John Crispin, Sean Wang, Mark Lee, Lorenzo Bianconi,
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] 11+ messages in thread
* Re: [PATCH net-next 5/6] net: dsa: tag_mtk: assign per-port queues
2022-11-16 8:07 ` [PATCH net-next 5/6] net: dsa: tag_mtk: assign " Felix Fietkau
@ 2022-11-16 18:26 ` Florian Fainelli
0 siblings, 0 replies; 11+ messages in thread
From: Florian Fainelli @ 2022-11-16 18:26 UTC (permalink / raw)
To: Felix Fietkau, netdev, Sean Wang, Landen Chao, DENG Qingfang,
Andrew Lunn, Vladimir Oltean, David S. Miller, Eric Dumazet,
Jakub Kicinski, Paolo Abeni, Matthias Brugger
Cc: linux-arm-kernel, linux-mediatek, linux-kernel
On 11/16/2022 12:07 AM, Felix Fietkau wrote:
> Keeps traffic sent to the switch within link speed limits
>
> Signed-off-by: Felix Fietkau <nbd@nbd.name>
Reviewed-by: Florian Fainelli <f.fainelli@gmail.com>
--
Florian
^ permalink raw reply [flat|nested] 11+ messages in thread
* Re: [PATCH net-next 4/6] net: ethernet: mtk_eth_soc: implement multi-queue support for per-port queues
2022-11-16 8:07 ` [PATCH net-next 4/6] net: ethernet: mtk_eth_soc: implement multi-queue support for per-port queues Felix Fietkau
@ 2022-11-18 15:13 ` Alexander 'lynxis' Couzens
2022-11-18 16:30 ` Felix Fietkau
0 siblings, 1 reply; 11+ messages in thread
From: Alexander 'lynxis' Couzens @ 2022-11-18 15:13 UTC (permalink / raw)
To: Felix Fietkau
Cc: netdev, John Crispin, Sean Wang, Mark Lee, Lorenzo Bianconi,
David S. Miller, Eric Dumazet, Jakub Kicinski, Paolo Abeni,
Matthias Brugger, Russell King, linux-arm-kernel, linux-mediatek,
linux-kernel
Hi Felix,
On Wed, 16 Nov 2022 09:07:32 +0100
Felix Fietkau <nbd@nbd.name> wrote:
> @@ -614,6 +618,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,
> @@ -639,6 +712,8 @@ static void mtk_mac_link_up(struct phylink_config *config,
What's happening to 2.5Gbit ports (e.g. on mt7622)? Should be SPEED_2500 also in the switch/case?
E.g. a direct connected 2.5Gbit phy to GMAC0.
Or a mt7622 GMAC0 to mt7531 port 6 and a 2.5Gbit phy to port 5.
^ permalink raw reply [flat|nested] 11+ messages in thread
* Re: [PATCH net-next 4/6] net: ethernet: mtk_eth_soc: implement multi-queue support for per-port queues
2022-11-18 15:13 ` Alexander 'lynxis' Couzens
@ 2022-11-18 16:30 ` Felix Fietkau
0 siblings, 0 replies; 11+ messages in thread
From: Felix Fietkau @ 2022-11-18 16:30 UTC (permalink / raw)
To: Alexander 'lynxis' Couzens
Cc: netdev, John Crispin, Sean Wang, Mark Lee, Lorenzo Bianconi,
David S. Miller, Eric Dumazet, Jakub Kicinski, Paolo Abeni,
Matthias Brugger, Russell King, linux-arm-kernel, linux-mediatek,
linux-kernel
> On 18. Nov 2022, at 16:13, Alexander 'lynxis' Couzens <lynxis@fe80.eu> wrote:
>
> Hi Felix,
>
>> On Wed, 16 Nov 2022 09:07:32 +0100
>> Felix Fietkau <nbd@nbd.name> wrote:
>>
>> @@ -614,6 +618,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,
>> @@ -639,6 +712,8 @@ static void mtk_mac_link_up(struct phylink_config *config,
>
>
> What's happening to 2.5Gbit ports (e.g. on mt7622)? Should be SPEED_2500 also in the switch/case?
> E.g. a direct connected 2.5Gbit phy to GMAC0.
> Or a mt7622 GMAC0 to mt7531 port 6 and a 2.5Gbit phy to port 5.
On 2.5 Gbit/s, the code disables rate limiting, since it’s not needed. That’s why it’s not handled here
- Felix
^ permalink raw reply [flat|nested] 11+ messages in thread
* Re: [PATCH net-next 1/6] net: ethernet: mtk_eth_soc: increase tx ring size for QDMA devices
2022-11-16 8:07 ` [PATCH net-next 1/6] net: ethernet: mtk_eth_soc: increase tx ring size for QDMA devices Felix Fietkau
@ 2022-11-19 3:50 ` patchwork-bot+netdevbpf
0 siblings, 0 replies; 11+ messages in thread
From: patchwork-bot+netdevbpf @ 2022-11-19 3:50 UTC (permalink / raw)
To: Felix Fietkau
Cc: netdev, john, sean.wang, Mark-MC.Lee, lorenzo, davem, edumazet,
kuba, pabeni, matthias.bgg, linux-arm-kernel, linux-mediatek,
linux-kernel
Hello:
This series was applied to netdev/net-next.git (master)
by Jakub Kicinski <kuba@kernel.org>:
On Wed, 16 Nov 2022 09:07:29 +0100 you wrote:
> 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(-)
Here is the summary with links:
- [net-next,1/6] net: ethernet: mtk_eth_soc: increase tx ring size for QDMA devices
https://git.kernel.org/netdev/net-next/c/c30e0b9b88b3
- [net-next,2/6] net: ethernet: mtk_eth_soc: drop packets to WDMA if the ring is full
https://git.kernel.org/netdev/net-next/c/f4b2fa2c25e1
- [net-next,3/6] net: ethernet: mtk_eth_soc: avoid port_mg assignment on MT7622 and newer
https://git.kernel.org/netdev/net-next/c/71ba8e4891c7
- [net-next,4/6] net: ethernet: mtk_eth_soc: implement multi-queue support for per-port queues
https://git.kernel.org/netdev/net-next/c/f63959c7eec3
- [net-next,5/6] net: dsa: tag_mtk: assign per-port queues
https://git.kernel.org/netdev/net-next/c/d169ecb536e4
- [net-next,6/6] net: ethernet: mediatek: ppe: assign per-port queues for offloaded traffic
https://git.kernel.org/netdev/net-next/c/8bd8dcc5e47f
You are awesome, thank you!
--
Deet-doot-dot, I am a bot.
https://korg.docs.kernel.org/patchwork/pwbot.html
^ permalink raw reply [flat|nested] 11+ messages in thread
end of thread, other threads:[~2022-11-19 3:55 UTC | newest]
Thread overview: 11+ messages (download: mbox.gz / follow: Atom feed)
-- links below jump to the message on this page --
2022-11-16 8:07 Multiqueue support for mtk_eth_soc Felix Fietkau
2022-11-16 8:07 ` [PATCH net-next 1/6] net: ethernet: mtk_eth_soc: increase tx ring size for QDMA devices Felix Fietkau
2022-11-19 3:50 ` patchwork-bot+netdevbpf
2022-11-16 8:07 ` [PATCH net-next 2/6] net: ethernet: mtk_eth_soc: drop packets to WDMA if the ring is full Felix Fietkau
2022-11-16 8:07 ` [PATCH net-next 3/6] net: ethernet: mtk_eth_soc: avoid port_mg assignment on MT7622 and newer Felix Fietkau
2022-11-16 8:07 ` [PATCH net-next 4/6] net: ethernet: mtk_eth_soc: implement multi-queue support for per-port queues Felix Fietkau
2022-11-18 15:13 ` Alexander 'lynxis' Couzens
2022-11-18 16:30 ` Felix Fietkau
2022-11-16 8:07 ` [PATCH net-next 5/6] net: dsa: tag_mtk: assign " Felix Fietkau
2022-11-16 18:26 ` Florian Fainelli
2022-11-16 8:07 ` [PATCH net-next 6/6] net: ethernet: mediatek: ppe: assign per-port queues for offloaded traffic 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).