1
0
Fork 0
forked from mirror/openwrt

Revert "kernel: improve mtk_eth_soc performance"

This reverts commit 3e6d5be3d9, until
stability issues have been figured out.

Signed-off-by: Felix Fietkau <nbd@nbd.name>
This commit is contained in:
Felix Fietkau 2025-09-05 18:18:54 +02:00
parent 5e231cc2f0
commit 79d3db7447
22 changed files with 170 additions and 2272 deletions

View file

@ -13,7 +13,7 @@ Signed-off-by: Bo-Cun Chen <bc-bocun.chen@mediatek.com>
--- a/drivers/net/ethernet/mediatek/mtk_eth_soc.c
+++ b/drivers/net/ethernet/mediatek/mtk_eth_soc.c
@@ -74,6 +74,7 @@ static const struct mtk_reg_map mtk_reg_
@@ -66,6 +66,7 @@ static const struct mtk_reg_map mtk_reg_
.rx_ptr = 0x1900,
.rx_cnt_cfg = 0x1904,
.qcrx_ptr = 0x1908,
@ -21,7 +21,7 @@ Signed-off-by: Bo-Cun Chen <bc-bocun.chen@mediatek.com>
.glo_cfg = 0x1a04,
.rst_idx = 0x1a08,
.delay_irq = 0x1a0c,
@@ -140,6 +141,7 @@ static const struct mtk_reg_map mt7986_r
@@ -132,6 +133,7 @@ static const struct mtk_reg_map mt7986_r
.rx_ptr = 0x4500,
.rx_cnt_cfg = 0x4504,
.qcrx_ptr = 0x4508,
@ -29,7 +29,7 @@ Signed-off-by: Bo-Cun Chen <bc-bocun.chen@mediatek.com>
.glo_cfg = 0x4604,
.rst_idx = 0x4608,
.delay_irq = 0x460c,
@@ -191,6 +193,7 @@ static const struct mtk_reg_map mt7988_r
@@ -183,6 +185,7 @@ static const struct mtk_reg_map mt7988_r
.rx_ptr = 0x4500,
.rx_cnt_cfg = 0x4504,
.qcrx_ptr = 0x4508,
@ -37,7 +37,7 @@ Signed-off-by: Bo-Cun Chen <bc-bocun.chen@mediatek.com>
.glo_cfg = 0x4604,
.rst_idx = 0x4608,
.delay_irq = 0x460c,
@@ -4061,6 +4064,56 @@ static void mtk_set_mcr_max_rx(struct mt
@@ -3909,6 +3912,56 @@ static void mtk_set_mcr_max_rx(struct mt
mtk_w32(mac->hw, mcr_new, MTK_MAC_MCR(mac->id));
}
@ -94,7 +94,7 @@ Signed-off-by: Bo-Cun Chen <bc-bocun.chen@mediatek.com>
static void mtk_hw_reset(struct mtk_eth *eth)
{
u32 val;
@@ -4540,6 +4593,8 @@ static void mtk_pending_work(struct work
@@ -4388,6 +4441,8 @@ static void mtk_pending_work(struct work
rtnl_lock();
set_bit(MTK_RESETTING, &eth->state);
@ -105,7 +105,7 @@ Signed-off-by: Bo-Cun Chen <bc-bocun.chen@mediatek.com>
/* Run again reset preliminary configuration in order to avoid any
--- a/drivers/net/ethernet/mediatek/mtk_eth_soc.h
+++ b/drivers/net/ethernet/mediatek/mtk_eth_soc.h
@@ -1185,6 +1185,7 @@ struct mtk_reg_map {
@@ -1191,6 +1191,7 @@ struct mtk_reg_map {
u32 rx_ptr; /* rx base pointer */
u32 rx_cnt_cfg; /* rx max count configuration */
u32 qcrx_ptr; /* rx cpu pointer */

View file

@ -13,7 +13,7 @@ Signed-off-by: Bo-Cun Chen <bc-bocun.chen@mediatek.com>
--- a/drivers/net/ethernet/mediatek/mtk_eth_soc.c
+++ b/drivers/net/ethernet/mediatek/mtk_eth_soc.c
@@ -71,6 +71,7 @@ static const struct mtk_reg_map mtk_reg_
@@ -66,6 +66,7 @@ static const struct mtk_reg_map mtk_reg_
.rx_ptr = 0x1900,
.rx_cnt_cfg = 0x1904,
.qcrx_ptr = 0x1908,
@ -21,7 +21,7 @@ Signed-off-by: Bo-Cun Chen <bc-bocun.chen@mediatek.com>
.glo_cfg = 0x1a04,
.rst_idx = 0x1a08,
.delay_irq = 0x1a0c,
@@ -137,6 +138,7 @@ static const struct mtk_reg_map mt7986_r
@@ -132,6 +133,7 @@ static const struct mtk_reg_map mt7986_r
.rx_ptr = 0x4500,
.rx_cnt_cfg = 0x4504,
.qcrx_ptr = 0x4508,
@ -29,7 +29,7 @@ Signed-off-by: Bo-Cun Chen <bc-bocun.chen@mediatek.com>
.glo_cfg = 0x4604,
.rst_idx = 0x4608,
.delay_irq = 0x460c,
@@ -188,6 +190,7 @@ static const struct mtk_reg_map mt7988_r
@@ -183,6 +185,7 @@ static const struct mtk_reg_map mt7988_r
.rx_ptr = 0x4500,
.rx_cnt_cfg = 0x4504,
.qcrx_ptr = 0x4508,
@ -37,7 +37,7 @@ Signed-off-by: Bo-Cun Chen <bc-bocun.chen@mediatek.com>
.glo_cfg = 0x4604,
.rst_idx = 0x4608,
.delay_irq = 0x460c,
@@ -3946,6 +3949,56 @@ static void mtk_set_mcr_max_rx(struct mt
@@ -3907,6 +3910,56 @@ static void mtk_set_mcr_max_rx(struct mt
mtk_w32(mac->hw, mcr_new, MTK_MAC_MCR(mac->id));
}
@ -94,7 +94,7 @@ Signed-off-by: Bo-Cun Chen <bc-bocun.chen@mediatek.com>
static void mtk_hw_reset(struct mtk_eth *eth)
{
u32 val;
@@ -4421,6 +4474,8 @@ static void mtk_pending_work(struct work
@@ -4382,6 +4435,8 @@ static void mtk_pending_work(struct work
rtnl_lock();
set_bit(MTK_RESETTING, &eth->state);
@ -105,7 +105,7 @@ Signed-off-by: Bo-Cun Chen <bc-bocun.chen@mediatek.com>
/* Run again reset preliminary configuration in order to avoid any
--- a/drivers/net/ethernet/mediatek/mtk_eth_soc.h
+++ b/drivers/net/ethernet/mediatek/mtk_eth_soc.h
@@ -1185,6 +1185,7 @@ struct mtk_reg_map {
@@ -1191,6 +1191,7 @@ struct mtk_reg_map {
u32 rx_ptr; /* rx base pointer */
u32 rx_cnt_cfg; /* rx max count configuration */
u32 qcrx_ptr; /* rx cpu pointer */

View file

@ -0,0 +1,21 @@
From: Felix Fietkau <nbd@nbd.name>
Date: Fri, 28 Oct 2022 12:54:48 +0200
Subject: [PATCH] net: ethernet: mtk_eth_soc: set NETIF_F_ALL_TSO
Significantly improves performance by avoiding unnecessary segmentation
Signed-off-by: Felix Fietkau <nbd@nbd.name>
---
--- a/drivers/net/ethernet/mediatek/mtk_eth_soc.h
+++ b/drivers/net/ethernet/mediatek/mtk_eth_soc.h
@@ -49,8 +49,7 @@
#define MTK_HW_FEATURES (NETIF_F_IP_CSUM | \
NETIF_F_RXCSUM | \
NETIF_F_HW_VLAN_CTAG_TX | \
- 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)

View file

@ -1,542 +0,0 @@
From: Felix Fietkau <nbd@nbd.name>
Date: Tue, 15 Oct 2024 12:52:56 +0200
Subject: [PATCH] net: ethernet: mtk_eth_soc: optimize dma ring address/index
calculation
Since DMA descriptor sizes are all power of 2, we can avoid costly integer
division in favor or simple shifts.
Signed-off-by: Felix Fietkau <nbd@nbd.name>
---
--- a/drivers/net/ethernet/mediatek/mtk_eth_soc.c
+++ b/drivers/net/ethernet/mediatek/mtk_eth_soc.c
@@ -43,6 +43,11 @@ MODULE_PARM_DESC(msg_level, "Message lev
offsetof(struct mtk_hw_stats, xdp_stats.x) / \
sizeof(u64) }
+#define RX_DESC_OFS(eth, i) \
+ ((i) << (eth)->soc->rx.desc_shift)
+#define TX_DESC_OFS(eth, i) \
+ ((i) << (eth)->soc->tx.desc_shift)
+
static const struct mtk_reg_map mtk_reg_map = {
.tx_irq_mask = 0x1a1c,
.tx_irq_status = 0x1a18,
@@ -1151,23 +1156,28 @@ static void *mtk_max_lro_buf_alloc(gfp_t
static int mtk_init_fq_dma(struct mtk_eth *eth)
{
const struct mtk_soc_data *soc = eth->soc;
- dma_addr_t phy_ring_tail;
+ dma_addr_t phy_ring_tail, phy_ring_addr;
int cnt = soc->tx.fq_dma_size;
dma_addr_t dma_addr;
+ void *ring_addr;
+ u32 desc_size;
int i, j, len;
if (MTK_HAS_CAPS(eth->soc->caps, MTK_SRAM))
eth->scratch_ring = eth->sram_base;
else
eth->scratch_ring = dma_alloc_coherent(eth->dma_dev,
- cnt * soc->tx.desc_size,
+ TX_DESC_OFS(eth, cnt),
&eth->phy_scratch_ring,
GFP_KERNEL);
if (unlikely(!eth->scratch_ring))
return -ENOMEM;
- phy_ring_tail = eth->phy_scratch_ring + soc->tx.desc_size * (cnt - 1);
+ phy_ring_tail = eth->phy_scratch_ring + TX_DESC_OFS(eth, cnt - 1);
+ ring_addr = eth->scratch_ring;
+ phy_ring_addr = eth->phy_scratch_ring;
+ desc_size = TX_DESC_OFS(eth, 1);
for (j = 0; j < DIV_ROUND_UP(soc->tx.fq_dma_size, MTK_FQ_DMA_LENGTH); j++) {
len = min_t(int, cnt - j * MTK_FQ_DMA_LENGTH, MTK_FQ_DMA_LENGTH);
@@ -1186,11 +1196,12 @@ static int mtk_init_fq_dma(struct mtk_et
for (i = 0; i < len; i++) {
struct mtk_tx_dma_v2 *txd;
- txd = eth->scratch_ring + (j * MTK_FQ_DMA_LENGTH + i) * soc->tx.desc_size;
+ txd = ring_addr;
+ ring_addr += desc_size;
+ phy_ring_addr += desc_size;
txd->txd1 = dma_addr + i * MTK_QDMA_PAGE_SIZE;
if (j * MTK_FQ_DMA_LENGTH + i < cnt)
- txd->txd2 = eth->phy_scratch_ring +
- (j * MTK_FQ_DMA_LENGTH + i + 1) * soc->tx.desc_size;
+ txd->txd2 = eth->phy_scratch_ring + phy_ring_addr;
txd->txd3 = TX_DMA_PLEN0(MTK_QDMA_PAGE_SIZE);
if (MTK_HAS_CAPS(soc->caps, MTK_36BIT_DMA))
@@ -1220,9 +1231,9 @@ static void *mtk_qdma_phys_to_virt(struc
}
static struct mtk_tx_buf *mtk_desc_to_tx_buf(struct mtk_tx_ring *ring,
- void *txd, u32 txd_size)
+ void *txd, u32 txd_shift)
{
- int idx = (txd - ring->dma) / txd_size;
+ int idx = (txd - ring->dma) >> txd_shift;
return &ring->buf[idx];
}
@@ -1233,9 +1244,9 @@ static struct mtk_tx_dma *qdma_to_pdma(s
return ring->dma_pdma - (struct mtk_tx_dma *)ring->dma + dma;
}
-static int txd_to_idx(struct mtk_tx_ring *ring, void *dma, u32 txd_size)
+static int txd_to_idx(struct mtk_tx_ring *ring, void *dma, u32 txd_shift)
{
- return (dma - ring->dma) / txd_size;
+ return (dma - ring->dma) >> txd_shift;
}
static void mtk_tx_unmap(struct mtk_eth *eth, struct mtk_tx_buf *tx_buf,
@@ -1443,7 +1454,7 @@ static int mtk_tx_map(struct sk_buff *sk
if (itxd == ring->last_free)
return -ENOMEM;
- itx_buf = mtk_desc_to_tx_buf(ring, itxd, soc->tx.desc_size);
+ itx_buf = mtk_desc_to_tx_buf(ring, itxd, soc->tx.desc_shift);
memset(itx_buf, 0, sizeof(*itx_buf));
txd_info.addr = dma_map_single(eth->dma_dev, skb->data, txd_info.size,
@@ -1497,7 +1508,7 @@ static int mtk_tx_map(struct sk_buff *sk
mtk_tx_set_dma_desc(dev, txd, &txd_info);
tx_buf = mtk_desc_to_tx_buf(ring, txd,
- soc->tx.desc_size);
+ soc->tx.desc_shift);
if (new_desc)
memset(tx_buf, 0, sizeof(*tx_buf));
tx_buf->data = (void *)MTK_DMA_DUMMY_DESC;
@@ -1540,7 +1551,7 @@ static int mtk_tx_map(struct sk_buff *sk
} else {
int next_idx;
- next_idx = NEXT_DESP_IDX(txd_to_idx(ring, txd, soc->tx.desc_size),
+ next_idx = NEXT_DESP_IDX(txd_to_idx(ring, txd, soc->tx.desc_shift),
ring->dma_size);
mtk_w32(eth, next_idx, MT7628_TX_CTX_IDX0);
}
@@ -1549,7 +1560,7 @@ static int mtk_tx_map(struct sk_buff *sk
err_dma:
do {
- tx_buf = mtk_desc_to_tx_buf(ring, itxd, soc->tx.desc_size);
+ tx_buf = mtk_desc_to_tx_buf(ring, itxd, soc->tx.desc_shift);
/* unmap dma */
mtk_tx_unmap(eth, tx_buf, NULL, false);
@@ -1715,7 +1726,7 @@ static struct mtk_rx_ring *mtk_get_rx_ri
ring = &eth->rx_ring[i];
idx = NEXT_DESP_IDX(ring->calc_idx, ring->dma_size);
- rxd = ring->dma + idx * eth->soc->rx.desc_size;
+ rxd = ring->dma + RX_DESC_OFS(eth, idx);
if (rxd->rxd2 & RX_DMA_DONE) {
ring->calc_idx_update = true;
return ring;
@@ -1883,7 +1894,7 @@ static int mtk_xdp_submit_frame(struct m
}
htxd = txd;
- tx_buf = mtk_desc_to_tx_buf(ring, txd, soc->tx.desc_size);
+ tx_buf = mtk_desc_to_tx_buf(ring, txd, soc->tx.desc_shift);
memset(tx_buf, 0, sizeof(*tx_buf));
htx_buf = tx_buf;
@@ -1902,7 +1913,7 @@ static int mtk_xdp_submit_frame(struct m
goto unmap;
tx_buf = mtk_desc_to_tx_buf(ring, txd,
- soc->tx.desc_size);
+ soc->tx.desc_shift);
memset(tx_buf, 0, sizeof(*tx_buf));
n_desc++;
}
@@ -1940,7 +1951,7 @@ static int mtk_xdp_submit_frame(struct m
} else {
int idx;
- idx = txd_to_idx(ring, txd, soc->tx.desc_size);
+ idx = txd_to_idx(ring, txd, soc->tx.desc_shift);
mtk_w32(eth, NEXT_DESP_IDX(idx, ring->dma_size),
MT7628_TX_CTX_IDX0);
}
@@ -1951,7 +1962,7 @@ static int mtk_xdp_submit_frame(struct m
unmap:
while (htxd != txd) {
- tx_buf = mtk_desc_to_tx_buf(ring, htxd, soc->tx.desc_size);
+ tx_buf = mtk_desc_to_tx_buf(ring, htxd, soc->tx.desc_shift);
mtk_tx_unmap(eth, tx_buf, NULL, false);
htxd->txd3 = TX_DMA_LS0 | TX_DMA_OWNER_CPU;
@@ -2083,7 +2094,7 @@ static int mtk_poll_rx(struct napi_struc
goto rx_done;
idx = NEXT_DESP_IDX(ring->calc_idx, ring->dma_size);
- rxd = ring->dma + idx * eth->soc->rx.desc_size;
+ rxd = ring->dma + RX_DESC_OFS(eth, idx);
data = ring->data[idx];
if (!mtk_rx_get_desc(eth, &trxd, rxd))
@@ -2347,7 +2358,7 @@ static int mtk_poll_tx_qdma(struct mtk_e
break;
tx_buf = mtk_desc_to_tx_buf(ring, desc,
- eth->soc->tx.desc_size);
+ eth->soc->tx.desc_shift);
if (!tx_buf->data)
break;
@@ -2398,7 +2409,7 @@ static int mtk_poll_tx_pdma(struct mtk_e
}
mtk_tx_unmap(eth, tx_buf, &bq, true);
- desc = ring->dma + cpu * eth->soc->tx.desc_size;
+ desc = ring->dma + TX_DESC_OFS(eth, cpu);
ring->last_free = desc;
atomic_inc(&ring->free_count);
@@ -2516,10 +2527,13 @@ static int mtk_tx_alloc(struct mtk_eth *
{
const struct mtk_soc_data *soc = eth->soc;
struct mtk_tx_ring *ring = &eth->tx_ring;
- int i, sz = soc->tx.desc_size;
struct mtk_tx_dma_v2 *txd;
+ dma_addr_t desc_phys;
+ void *desc_addr;
+ u32 desc_size;
int ring_size;
u32 ofs, val;
+ int i;
if (MTK_HAS_CAPS(soc->caps, MTK_QDMA))
ring_size = MTK_QDMA_RING_SIZE;
@@ -2532,22 +2546,24 @@ static int mtk_tx_alloc(struct mtk_eth *
goto no_tx_mem;
if (MTK_HAS_CAPS(soc->caps, MTK_SRAM)) {
- ring->dma = eth->sram_base + soc->tx.fq_dma_size * sz;
- ring->phys = eth->phy_scratch_ring + soc->tx.fq_dma_size * (dma_addr_t)sz;
+ ring->dma = eth->sram_base + TX_DESC_OFS(eth, soc->tx.fq_dma_size);
+ ring->phys = eth->phy_scratch_ring + TX_DESC_OFS(eth, soc->tx.fq_dma_size);
} else {
- ring->dma = dma_alloc_coherent(eth->dma_dev, ring_size * sz,
+ ring->dma = dma_alloc_coherent(eth->dma_dev, TX_DESC_OFS(eth, ring_size),
&ring->phys, GFP_KERNEL);
}
if (!ring->dma)
goto no_tx_mem;
+ desc_addr = ring->dma;
+ desc_phys = ring->phys;
+ desc_size = TX_DESC_OFS(eth, 1);
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;
- txd->txd2 = next_ptr;
+ txd = desc_addr;
+ desc_addr += desc_size;
+ desc_phys += desc_size;
+ txd->txd2 = desc_phys;
txd->txd3 = TX_DMA_LS0 | TX_DMA_OWNER_CPU;
txd->txd4 = 0;
if (mtk_is_netsys_v2_or_greater(eth)) {
@@ -2563,7 +2579,7 @@ static int mtk_tx_alloc(struct mtk_eth *
* descriptors in ring->dma_pdma.
*/
if (!MTK_HAS_CAPS(soc->caps, MTK_QDMA)) {
- ring->dma_pdma = dma_alloc_coherent(eth->dma_dev, ring_size * sz,
+ ring->dma_pdma = dma_alloc_coherent(eth->dma_dev, TX_DESC_OFS(eth, ring_size),
&ring->phys_pdma, GFP_KERNEL);
if (!ring->dma_pdma)
goto no_tx_mem;
@@ -2578,7 +2594,7 @@ static int mtk_tx_alloc(struct mtk_eth *
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 + ((ring_size - 1) * sz));
+ ring->last_free_ptr = (u32)(ring->phys + TX_DESC_OFS(eth, ring_size - 1));
ring->thresh = MAX_SKB_FRAGS;
/* make sure that all changes to the dma ring are flushed before we
@@ -2590,7 +2606,7 @@ static int mtk_tx_alloc(struct mtk_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 + ((ring_size - 1) * sz),
+ ring->phys + TX_DESC_OFS(eth, ring_size - 1),
soc->reg_map->qdma.crx_ptr);
mtk_w32(eth, ring->last_free_ptr, soc->reg_map->qdma.drx_ptr);
@@ -2639,14 +2655,14 @@ static void mtk_tx_clean(struct mtk_eth
}
if (!MTK_HAS_CAPS(soc->caps, MTK_SRAM) && ring->dma) {
dma_free_coherent(eth->dma_dev,
- ring->dma_size * soc->tx.desc_size,
+ TX_DESC_OFS(eth, ring->dma_size),
ring->dma, ring->phys);
ring->dma = NULL;
}
if (ring->dma_pdma) {
dma_free_coherent(eth->dma_dev,
- ring->dma_size * soc->tx.desc_size,
+ TX_DESC_OFS(eth, ring->dma_size),
ring->dma_pdma, ring->phys_pdma);
ring->dma_pdma = NULL;
}
@@ -2702,15 +2718,13 @@ static int mtk_rx_alloc(struct mtk_eth *
if (!MTK_HAS_CAPS(eth->soc->caps, MTK_SRAM) ||
rx_flag != MTK_RX_FLAGS_NORMAL) {
ring->dma = dma_alloc_coherent(eth->dma_dev,
- rx_dma_size * eth->soc->rx.desc_size,
+ RX_DESC_OFS(eth, rx_dma_size),
&ring->phys, GFP_KERNEL);
} else {
struct mtk_tx_ring *tx_ring = &eth->tx_ring;
- ring->dma = tx_ring->dma + tx_ring_size *
- eth->soc->tx.desc_size * (ring_no + 1);
- ring->phys = tx_ring->phys + tx_ring_size *
- eth->soc->tx.desc_size * (ring_no + 1);
+ ring->dma = tx_ring->dma + TX_DESC_OFS(eth, tx_ring_size * (ring_no + 1));
+ ring->phys = tx_ring->phys + TX_DESC_OFS(eth, tx_ring_size * (ring_no + 1));
}
if (!ring->dma)
@@ -2721,7 +2735,7 @@ static int mtk_rx_alloc(struct mtk_eth *
dma_addr_t dma_addr;
void *data;
- rxd = ring->dma + i * eth->soc->rx.desc_size;
+ rxd = ring->dma + RX_DESC_OFS(eth, i);
if (ring->page_pool) {
data = mtk_page_pool_get_buff(ring->page_pool,
&dma_addr, GFP_KERNEL);
@@ -2812,7 +2826,7 @@ static void mtk_rx_clean(struct mtk_eth
if (!ring->data[i])
continue;
- rxd = ring->dma + i * eth->soc->rx.desc_size;
+ rxd = ring->dma + RX_DESC_OFS(eth, i);
if (!rxd->rxd1)
continue;
@@ -2829,7 +2843,7 @@ static void mtk_rx_clean(struct mtk_eth
if (!in_sram && ring->dma) {
dma_free_coherent(eth->dma_dev,
- ring->dma_size * eth->soc->rx.desc_size,
+ RX_DESC_OFS(eth, ring->dma_size),
ring->dma, ring->phys);
ring->dma = NULL;
}
@@ -3200,7 +3214,7 @@ static void mtk_dma_free(struct mtk_eth
if (!MTK_HAS_CAPS(soc->caps, MTK_SRAM) && eth->scratch_ring) {
dma_free_coherent(eth->dma_dev,
- MTK_QDMA_RING_SIZE * soc->tx.desc_size,
+ TX_DESC_OFS(eth, MTK_QDMA_RING_SIZE),
eth->scratch_ring, eth->phy_scratch_ring);
eth->scratch_ring = NULL;
eth->phy_scratch_ring = 0;
@@ -5228,6 +5242,9 @@ static void mtk_remove(struct platform_d
mtk_mdio_cleanup(eth);
}
+#define DESC_SIZE(struct_name) \
+ .desc_shift = const_ilog2(sizeof(struct_name))
+
static const struct mtk_soc_data mt2701_data = {
.reg_map = &mtk_reg_map,
.caps = MT7623_CAPS | MTK_HWLRO,
@@ -5236,14 +5253,14 @@ static const struct mtk_soc_data mt2701_
.required_pctl = true,
.version = 1,
.tx = {
- .desc_size = sizeof(struct mtk_tx_dma),
+ DESC_SIZE(struct mtk_tx_dma),
.dma_max_len = MTK_TX_DMA_BUF_LEN,
.dma_len_offset = 16,
.dma_size = MTK_DMA_SIZE(2K),
.fq_dma_size = MTK_DMA_SIZE(2K),
},
.rx = {
- .desc_size = sizeof(struct mtk_rx_dma),
+ DESC_SIZE(struct mtk_rx_dma),
.irq_done_mask = MTK_RX_DONE_INT,
.dma_l4_valid = RX_DMA_L4_VALID,
.dma_size = MTK_DMA_SIZE(2K),
@@ -5264,14 +5281,14 @@ static const struct mtk_soc_data mt7621_
.hash_offset = 2,
.foe_entry_size = MTK_FOE_ENTRY_V1_SIZE,
.tx = {
- .desc_size = sizeof(struct mtk_tx_dma),
+ DESC_SIZE(struct mtk_tx_dma),
.dma_max_len = MTK_TX_DMA_BUF_LEN,
.dma_len_offset = 16,
.dma_size = MTK_DMA_SIZE(2K),
.fq_dma_size = MTK_DMA_SIZE(2K),
},
.rx = {
- .desc_size = sizeof(struct mtk_rx_dma),
+ DESC_SIZE(struct mtk_rx_dma),
.irq_done_mask = MTK_RX_DONE_INT,
.dma_l4_valid = RX_DMA_L4_VALID,
.dma_size = MTK_DMA_SIZE(2K),
@@ -5294,14 +5311,14 @@ static const struct mtk_soc_data mt7622_
.has_accounting = true,
.foe_entry_size = MTK_FOE_ENTRY_V1_SIZE,
.tx = {
- .desc_size = sizeof(struct mtk_tx_dma),
+ DESC_SIZE(struct mtk_tx_dma),
.dma_max_len = MTK_TX_DMA_BUF_LEN,
.dma_len_offset = 16,
.dma_size = MTK_DMA_SIZE(2K),
.fq_dma_size = MTK_DMA_SIZE(2K),
},
.rx = {
- .desc_size = sizeof(struct mtk_rx_dma),
+ DESC_SIZE(struct mtk_rx_dma),
.irq_done_mask = MTK_RX_DONE_INT,
.dma_l4_valid = RX_DMA_L4_VALID,
.dma_size = MTK_DMA_SIZE(2K),
@@ -5323,14 +5340,14 @@ static const struct mtk_soc_data mt7623_
.foe_entry_size = MTK_FOE_ENTRY_V1_SIZE,
.disable_pll_modes = true,
.tx = {
- .desc_size = sizeof(struct mtk_tx_dma),
+ DESC_SIZE(struct mtk_tx_dma),
.dma_max_len = MTK_TX_DMA_BUF_LEN,
.dma_len_offset = 16,
.dma_size = MTK_DMA_SIZE(2K),
.fq_dma_size = MTK_DMA_SIZE(2K),
},
.rx = {
- .desc_size = sizeof(struct mtk_rx_dma),
+ DESC_SIZE(struct mtk_rx_dma),
.irq_done_mask = MTK_RX_DONE_INT,
.dma_l4_valid = RX_DMA_L4_VALID,
.dma_size = MTK_DMA_SIZE(2K),
@@ -5349,14 +5366,14 @@ static const struct mtk_soc_data mt7629_
.has_accounting = true,
.version = 1,
.tx = {
- .desc_size = sizeof(struct mtk_tx_dma),
+ DESC_SIZE(struct mtk_tx_dma),
.dma_max_len = MTK_TX_DMA_BUF_LEN,
.dma_len_offset = 16,
.dma_size = MTK_DMA_SIZE(2K),
.fq_dma_size = MTK_DMA_SIZE(2K),
},
.rx = {
- .desc_size = sizeof(struct mtk_rx_dma),
+ DESC_SIZE(struct mtk_rx_dma),
.irq_done_mask = MTK_RX_DONE_INT,
.dma_l4_valid = RX_DMA_L4_VALID,
.dma_size = MTK_DMA_SIZE(2K),
@@ -5379,14 +5396,14 @@ static const struct mtk_soc_data mt7981_
.has_accounting = true,
.foe_entry_size = MTK_FOE_ENTRY_V2_SIZE,
.tx = {
- .desc_size = sizeof(struct mtk_tx_dma_v2),
+ DESC_SIZE(struct mtk_tx_dma_v2),
.dma_max_len = MTK_TX_DMA_BUF_LEN_V2,
.dma_len_offset = 8,
.dma_size = MTK_DMA_SIZE(2K),
.fq_dma_size = MTK_DMA_SIZE(2K),
},
.rx = {
- .desc_size = sizeof(struct mtk_rx_dma),
+ DESC_SIZE(struct mtk_rx_dma),
.irq_done_mask = MTK_RX_DONE_INT,
.dma_l4_valid = RX_DMA_L4_VALID_V2,
.dma_max_len = MTK_TX_DMA_BUF_LEN,
@@ -5409,14 +5426,14 @@ static const struct mtk_soc_data mt7986_
.has_accounting = true,
.foe_entry_size = MTK_FOE_ENTRY_V2_SIZE,
.tx = {
- .desc_size = sizeof(struct mtk_tx_dma_v2),
+ DESC_SIZE(struct mtk_tx_dma_v2),
.dma_max_len = MTK_TX_DMA_BUF_LEN_V2,
.dma_len_offset = 8,
.dma_size = MTK_DMA_SIZE(2K),
.fq_dma_size = MTK_DMA_SIZE(2K),
},
.rx = {
- .desc_size = sizeof(struct mtk_rx_dma),
+ DESC_SIZE(struct mtk_rx_dma),
.irq_done_mask = MTK_RX_DONE_INT,
.dma_l4_valid = RX_DMA_L4_VALID_V2,
.dma_max_len = MTK_TX_DMA_BUF_LEN,
@@ -5439,14 +5456,14 @@ static const struct mtk_soc_data mt7988_
.has_accounting = true,
.foe_entry_size = MTK_FOE_ENTRY_V3_SIZE,
.tx = {
- .desc_size = sizeof(struct mtk_tx_dma_v2),
+ DESC_SIZE(struct mtk_tx_dma_v2),
.dma_max_len = MTK_TX_DMA_BUF_LEN_V2,
.dma_len_offset = 8,
.dma_size = MTK_DMA_SIZE(2K),
.fq_dma_size = MTK_DMA_SIZE(4K),
},
.rx = {
- .desc_size = sizeof(struct mtk_rx_dma_v2),
+ DESC_SIZE(struct mtk_rx_dma_v2),
.irq_done_mask = MTK_RX_DONE_INT_V2,
.dma_l4_valid = RX_DMA_L4_VALID_V2,
.dma_max_len = MTK_TX_DMA_BUF_LEN_V2,
@@ -5463,13 +5480,13 @@ static const struct mtk_soc_data rt5350_
.required_pctl = false,
.version = 1,
.tx = {
- .desc_size = sizeof(struct mtk_tx_dma),
+ DESC_SIZE(struct mtk_tx_dma),
.dma_max_len = MTK_TX_DMA_BUF_LEN,
.dma_len_offset = 16,
.dma_size = MTK_DMA_SIZE(2K),
},
.rx = {
- .desc_size = sizeof(struct mtk_rx_dma),
+ DESC_SIZE(struct mtk_rx_dma),
.irq_done_mask = MTK_RX_DONE_INT,
.dma_l4_valid = RX_DMA_L4_VALID_PDMA,
.dma_max_len = MTK_TX_DMA_BUF_LEN,
--- a/drivers/net/ethernet/mediatek/mtk_eth_soc.h
+++ b/drivers/net/ethernet/mediatek/mtk_eth_soc.h
@@ -1160,7 +1160,7 @@ struct mtk_reg_map {
* @foe_entry_size Foe table entry size.
* @has_accounting Bool indicating support for accounting of
* offloaded flows.
- * @desc_size Tx/Rx DMA descriptor size.
+ * @desc_shift Tx/Rx DMA descriptor size (in power-of-2).
* @irq_done_mask Rx irq done register mask.
* @dma_l4_valid Rx DMA valid register mask.
* @dma_max_len Max DMA tx/rx buffer length.
@@ -1181,14 +1181,14 @@ struct mtk_soc_data {
bool has_accounting;
bool disable_pll_modes;
struct {
- u32 desc_size;
+ u32 desc_shift;
u32 dma_max_len;
u32 dma_len_offset;
u32 dma_size;
u32 fq_dma_size;
} tx;
struct {
- u32 desc_size;
+ u32 desc_shift;
u32 irq_done_mask;
u32 dma_l4_valid;
u32 dma_max_len;

View file

@ -1,124 +0,0 @@
From: Felix Fietkau <nbd@nbd.name>
Date: Mon, 14 Jul 2025 10:52:59 +0200
Subject: [PATCH] net: ethernet: mtk_eth_soc: shrink struct mtk_tx_buf
There is no need to track the difference between dma_map_page
and dma_map_single, since they're unmapped in exactly the same way.
Also reorder fields in order to avoid padding.
Signed-off-by: Felix Fietkau <nbd@nbd.name>
---
--- a/drivers/net/ethernet/mediatek/mtk_eth_soc.c
+++ b/drivers/net/ethernet/mediatek/mtk_eth_soc.c
@@ -1252,32 +1252,19 @@ static int txd_to_idx(struct mtk_tx_ring
static void mtk_tx_unmap(struct mtk_eth *eth, struct mtk_tx_buf *tx_buf,
struct xdp_frame_bulk *bq, bool napi)
{
- if (MTK_HAS_CAPS(eth->soc->caps, MTK_QDMA)) {
- if (tx_buf->flags & MTK_TX_FLAGS_SINGLE0) {
- dma_unmap_single(eth->dma_dev,
- dma_unmap_addr(tx_buf, dma_addr0),
- dma_unmap_len(tx_buf, dma_len0),
- DMA_TO_DEVICE);
- } else if (tx_buf->flags & MTK_TX_FLAGS_PAGE0) {
- dma_unmap_page(eth->dma_dev,
- dma_unmap_addr(tx_buf, dma_addr0),
- dma_unmap_len(tx_buf, dma_len0),
- DMA_TO_DEVICE);
- }
- } else {
- if (dma_unmap_len(tx_buf, dma_len0)) {
- dma_unmap_page(eth->dma_dev,
- dma_unmap_addr(tx_buf, dma_addr0),
- dma_unmap_len(tx_buf, dma_len0),
- DMA_TO_DEVICE);
- }
+ if (dma_unmap_len(tx_buf, dma_len0)) {
+ dma_unmap_page(eth->dma_dev,
+ dma_unmap_addr(tx_buf, dma_addr0),
+ dma_unmap_len(tx_buf, dma_len0),
+ DMA_TO_DEVICE);
+ }
- if (dma_unmap_len(tx_buf, dma_len1)) {
- dma_unmap_page(eth->dma_dev,
- dma_unmap_addr(tx_buf, dma_addr1),
- dma_unmap_len(tx_buf, dma_len1),
- DMA_TO_DEVICE);
- }
+ if (!MTK_HAS_CAPS(eth->soc->caps, MTK_QDMA) &&
+ dma_unmap_len(tx_buf, dma_len1)) {
+ dma_unmap_page(eth->dma_dev,
+ dma_unmap_addr(tx_buf, dma_addr1),
+ dma_unmap_len(tx_buf, dma_len1),
+ DMA_TO_DEVICE);
}
if (tx_buf->data && tx_buf->data != (void *)MTK_DMA_DUMMY_DESC) {
@@ -1299,7 +1286,6 @@ static void mtk_tx_unmap(struct mtk_eth
xdp_return_frame(xdpf);
}
}
- tx_buf->flags = 0;
tx_buf->data = NULL;
}
@@ -1464,7 +1450,6 @@ static int mtk_tx_map(struct sk_buff *sk
mtk_tx_set_dma_desc(dev, itxd, &txd_info);
- itx_buf->flags |= MTK_TX_FLAGS_SINGLE0;
itx_buf->mac_id = mac->id;
setup_tx_buf(eth, itx_buf, itxd_pdma, txd_info.addr, txd_info.size,
k++);
@@ -1512,7 +1497,6 @@ static int mtk_tx_map(struct sk_buff *sk
if (new_desc)
memset(tx_buf, 0, sizeof(*tx_buf));
tx_buf->data = (void *)MTK_DMA_DUMMY_DESC;
- tx_buf->flags |= MTK_TX_FLAGS_PAGE0;
tx_buf->mac_id = mac->id;
setup_tx_buf(eth, tx_buf, txd_pdma, txd_info.addr,
@@ -1837,8 +1821,6 @@ static int mtk_xdp_frame_map(struct mtk_
txd_info->size, DMA_TO_DEVICE);
if (unlikely(dma_mapping_error(eth->dma_dev, txd_info->addr)))
return -ENOMEM;
-
- tx_buf->flags |= MTK_TX_FLAGS_SINGLE0;
} else {
struct page *page = virt_to_head_page(data);
--- a/drivers/net/ethernet/mediatek/mtk_eth_soc.h
+++ b/drivers/net/ethernet/mediatek/mtk_eth_soc.h
@@ -701,14 +701,6 @@ struct mtk_hw_stats {
struct u64_stats_sync syncp;
};
-enum mtk_tx_flags {
- /* PDMA descriptor can point at 1-2 segments. This enum allows us to
- * track how memory was allocated so that it can be freed properly.
- */
- MTK_TX_FLAGS_SINGLE0 = 0x01,
- MTK_TX_FLAGS_PAGE0 = 0x02,
-};
-
/* This enum allows us to identify how the clock is defined on the array of the
* clock in the order
*/
@@ -881,13 +873,12 @@ enum mtk_tx_buf_type {
*/
struct mtk_tx_buf {
enum mtk_tx_buf_type type;
+ u16 mac_id;
void *data;
- u16 mac_id;
- u16 flags;
DEFINE_DMA_UNMAP_ADDR(dma_addr0);
- DEFINE_DMA_UNMAP_LEN(dma_len0);
DEFINE_DMA_UNMAP_ADDR(dma_addr1);
+ DEFINE_DMA_UNMAP_LEN(dma_len0);
DEFINE_DMA_UNMAP_LEN(dma_len1);
};

View file

@ -1,509 +0,0 @@
From: Felix Fietkau <nbd@nbd.name>
Date: Mon, 14 Jul 2025 10:41:27 +0200
Subject: [PATCH] net: ethernet: mtk_eth_soc: add support for sending
fraglist GSO packets
When primarily forwarding traffic, TCP fraglist GRO can be noticeably more
efficient than regular TCP GRO. In order to avoid the overhead of
unnecessary segmentation on ethernet tx, add support for sending fraglist
GRO packets.
Signed-off-by: Felix Fietkau <nbd@nbd.name>
---
--- a/drivers/net/ethernet/mediatek/mtk_eth_soc.c
+++ b/drivers/net/ethernet/mediatek/mtk_eth_soc.c
@@ -18,6 +18,8 @@
#include <linux/if_vlan.h>
#include <linux/reset.h>
#include <linux/tcp.h>
+#include <linux/ip.h>
+#include <linux/ipv6.h>
#include <linux/interrupt.h>
#include <linux/pinctrl/devinfo.h>
#include <linux/phylink.h>
@@ -27,6 +29,7 @@
#include <net/dsa.h>
#include <net/dst_metadata.h>
#include <net/gso.h>
+#include <net/checksum.h>
#include <net/page_pool/helpers.h>
#include "mtk_eth_soc.h"
@@ -1410,119 +1413,244 @@ static void mtk_tx_set_dma_desc(struct n
mtk_tx_set_dma_desc_v1(dev, txd, info);
}
+struct mtk_tx_map_state {
+ struct mtk_tx_dma *txd, *txd_pdma;
+ struct mtk_tx_buf *tx_buf;
+ int nbuf;
+ int ndesc;
+};
+
+static void
+mtk_tx_map_set_txd(struct mtk_tx_map_state *state, struct mtk_tx_ring *ring,
+ const struct mtk_soc_data *soc, struct mtk_tx_dma *txd)
+{
+ state->txd = txd;
+ state->txd_pdma = qdma_to_pdma(ring, txd);
+ state->tx_buf = mtk_desc_to_tx_buf(ring, txd, soc->tx.desc_shift);
+ memset(state->tx_buf, 0, sizeof(*state->tx_buf));
+}
+
+static int
+mtk_tx_map_info(struct mtk_eth *eth, struct mtk_tx_ring *ring,
+ struct net_device *dev, struct mtk_tx_map_state *state,
+ struct mtk_tx_dma_desc_info *txd_info)
+{
+ const struct mtk_soc_data *soc = eth->soc;
+ struct mtk_tx_buf *tx_buf = state->tx_buf;
+ struct mtk_tx_dma *txd = state->txd;
+ struct mtk_mac *mac = netdev_priv(dev);
+
+ if (state->nbuf &&
+ (MTK_HAS_CAPS(soc->caps, MTK_QDMA) || (state->nbuf & 1) == 0)) {
+ txd = mtk_qdma_phys_to_virt(ring, txd->txd2);
+ if (txd == ring->last_free)
+ return -1;
+
+ mtk_tx_map_set_txd(state, ring, soc, txd);
+ state->ndesc++;
+ }
+
+ mtk_tx_set_dma_desc(dev, txd, txd_info);
+ tx_buf = state->tx_buf;
+ tx_buf->data = (void *)MTK_DMA_DUMMY_DESC;
+ tx_buf->mac_id = mac->id;
+
+ setup_tx_buf(eth, tx_buf, state->txd_pdma, txd_info->addr,
+ txd_info->size, state->nbuf++);
+ return 0;
+}
+
+static void
+mtk_tx_update_ipaddr(struct sk_buff *skb,
+ struct iphdr *iph, struct tcphdr *th,
+ __be32 *old_ip, __be32 new_ip)
+{
+ if (*old_ip == new_ip)
+ return;
+
+ inet_proto_csum_replace4(&th->check, skb, *old_ip, new_ip, true);
+ csum_replace4(&iph->check, *old_ip, new_ip);
+ *old_ip = new_ip;
+}
+
+static void
+mtk_tx_update_ip6addr(struct sk_buff *skb, struct ipv6hdr *iph,
+ struct tcphdr *th, struct in6_addr *old_ip,
+ const struct in6_addr *new_ip)
+{
+ if (ipv6_addr_equal(old_ip, new_ip))
+ return;
+
+ inet_proto_csum_replace16(&th->check, skb, old_ip->s6_addr32,
+ new_ip->s6_addr32, true);
+ *old_ip = *new_ip;
+}
+
+static void
+mtk_tx_update_port(struct sk_buff *skb, struct tcphdr *th,
+ __be16 *old_port, __be16 new_port)
+{
+ if (*old_port == new_port)
+ return;
+
+ inet_proto_csum_replace2(&th->check, skb, *old_port, new_port, false);
+ *old_port = new_port;
+}
+
static int mtk_tx_map(struct sk_buff *skb, struct net_device *dev,
- int tx_num, struct mtk_tx_ring *ring, bool gso)
+ int tx_num, struct mtk_tx_ring *ring, bool gso,
+ unsigned int header_len)
{
- struct mtk_tx_dma_desc_info txd_info = {
- .size = skb_headlen(skb),
- .gso = gso,
- .csum = skb->ip_summed == CHECKSUM_PARTIAL,
- .vlan = skb_vlan_tag_present(skb),
- .qid = skb_get_queue_mapping(skb),
- .vlan_tci = skb_vlan_tag_get(skb),
- .first = true,
- .last = !skb_is_nonlinear(skb),
+ struct mtk_tx_dma_desc_info txd_info;
+ struct mtk_tx_map_state state = {
+ .ndesc = 1,
};
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;
- struct mtk_tx_dma *itxd, *txd;
- struct mtk_tx_dma *itxd_pdma, *txd_pdma;
- struct mtk_tx_buf *itx_buf, *tx_buf;
- int i, n_desc = 1;
+ struct mtk_tx_dma *itxd;
+ struct sk_buff *cur_skb, *next_skb;
int queue = skb_get_queue_mapping(skb);
- int k = 0;
+ int offset = 0;
+ int i, frag_size;
+ bool gso_v4;
txq = netdev_get_tx_queue(dev, queue);
itxd = ring->next_free;
- itxd_pdma = qdma_to_pdma(ring, itxd);
if (itxd == ring->last_free)
return -ENOMEM;
- itx_buf = mtk_desc_to_tx_buf(ring, itxd, soc->tx.desc_shift);
- memset(itx_buf, 0, sizeof(*itx_buf));
+ cur_skb = skb;
+ next_skb = skb_shinfo(skb)->frag_list;
+ mtk_tx_map_set_txd(&state, ring, soc, itxd);
+ gso_v4 = skb_shinfo(skb)->gso_type & SKB_GSO_TCPV4;
- txd_info.addr = dma_map_single(eth->dma_dev, skb->data, txd_info.size,
- DMA_TO_DEVICE);
- if (unlikely(dma_mapping_error(eth->dma_dev, txd_info.addr)))
- return -ENOMEM;
+next:
+ txd_info = (struct mtk_tx_dma_desc_info){
+ .gso = gso,
+ .qid = queue,
+ .csum = cur_skb->ip_summed == CHECKSUM_PARTIAL || gso,
+ .vlan = skb_vlan_tag_present(skb),
+ .vlan_tci = skb_vlan_tag_get(skb),
+ .first = true,
+ };
+
+ offset = 0;
+ frag_size = skb_headlen(cur_skb);
+ if (cur_skb != skb) {
+ struct tcphdr *th, *th2;
+
+ if (skb_cow_head(cur_skb, header_len))
+ goto err_dma;
+
+ memcpy(cur_skb->data - header_len, skb->data,
+ skb_network_offset(skb));
+
+ th = tcp_hdr(cur_skb);
+ th2 = tcp_hdr(skb);
+ if (gso_v4) {
+ struct iphdr *iph = ip_hdr(cur_skb);
+ struct iphdr *iph2 = ip_hdr(skb);
+
+ mtk_tx_update_ipaddr(skb, iph, th, &iph->saddr,
+ iph2->saddr);
+ mtk_tx_update_ipaddr(skb, iph, th, &iph->daddr,
+ iph2->daddr);
+ } else {
+ struct ipv6hdr *iph = ipv6_hdr(cur_skb);
+ struct ipv6hdr *iph2 = ipv6_hdr(skb);
- mtk_tx_set_dma_desc(dev, itxd, &txd_info);
+ mtk_tx_update_ip6addr(skb, iph, th, &iph->saddr,
+ &iph2->saddr);
+ mtk_tx_update_ip6addr(skb, iph, th, &iph->daddr,
+ &iph2->daddr);
+ }
- itx_buf->mac_id = mac->id;
- setup_tx_buf(eth, itx_buf, itxd_pdma, txd_info.addr, txd_info.size,
- k++);
-
- /* TX SG offload */
- txd = itxd;
- txd_pdma = qdma_to_pdma(ring, txd);
-
- for (i = 0; i < skb_shinfo(skb)->nr_frags; i++) {
- skb_frag_t *frag = &skb_shinfo(skb)->frags[i];
- unsigned int offset = 0;
- int frag_size = skb_frag_size(frag);
+ mtk_tx_update_port(skb, th, &th->source, th2->source);
+ mtk_tx_update_port(skb, th, &th->dest, th2->dest);
- while (frag_size) {
- bool new_desc = true;
+ offset = -header_len;
+ frag_size += header_len;
+ } else if (next_skb) {
+ unsigned int ip_len = skb_pagelen(skb) - skb_network_offset(skb);
+ if (gso_v4) {
+ struct iphdr *iph = ip_hdr(cur_skb);
+ __be16 ip_len_val = cpu_to_be16(ip_len);
- if (MTK_HAS_CAPS(soc->caps, MTK_QDMA) ||
- (i & 0x1)) {
- txd = mtk_qdma_phys_to_virt(ring, txd->txd2);
- txd_pdma = qdma_to_pdma(ring, txd);
- if (txd == ring->last_free)
- goto err_dma;
+ csum_replace2(&iph->check, iph->tot_len, ip_len_val);
+ iph->tot_len = ip_len_val;
+ } else {
+ struct ipv6hdr *iph = ipv6_hdr(cur_skb);
+ __be16 ip_len_val = cpu_to_be16(ip_len - sizeof(*iph));
- n_desc++;
- } else {
- new_desc = false;
- }
+ iph->payload_len = ip_len_val;
+ }
+ }
- memset(&txd_info, 0, sizeof(struct mtk_tx_dma_desc_info));
+ while (frag_size) {
+ txd_info.size = min_t(unsigned int, frag_size,
+ soc->tx.dma_max_len);
+ txd_info.addr = dma_map_single(eth->dma_dev, cur_skb->data + offset,
+ txd_info.size, DMA_TO_DEVICE);
+ if (unlikely(dma_mapping_error(eth->dma_dev, txd_info.addr)))
+ goto err_dma;
+
+ frag_size -= txd_info.size;
+ offset += txd_info.size;
+ txd_info.last = !frag_size && !skb_shinfo(cur_skb)->nr_frags;
+ if (mtk_tx_map_info(eth, ring, dev, &state, &txd_info) < 0)
+ goto err_dma;
+ }
+
+ for (i = 0; i < skb_shinfo(cur_skb)->nr_frags; i++) {
+ skb_frag_t *frag = &skb_shinfo(cur_skb)->frags[i];
+
+ frag_size = skb_frag_size(frag);
+ memset(&txd_info, 0, sizeof(struct mtk_tx_dma_desc_info));
+ txd_info.qid = queue;
+ offset = 0;
+ while (frag_size) {
txd_info.size = min_t(unsigned int, frag_size,
soc->tx.dma_max_len);
- 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,
- offset, txd_info.size,
- DMA_TO_DEVICE);
+ txd_info.addr = skb_frag_dma_map(eth->dma_dev, frag, offset,
+ txd_info.size, DMA_TO_DEVICE);
if (unlikely(dma_mapping_error(eth->dma_dev, txd_info.addr)))
goto err_dma;
- mtk_tx_set_dma_desc(dev, txd, &txd_info);
-
- tx_buf = mtk_desc_to_tx_buf(ring, txd,
- soc->tx.desc_shift);
- if (new_desc)
- memset(tx_buf, 0, sizeof(*tx_buf));
- tx_buf->data = (void *)MTK_DMA_DUMMY_DESC;
- tx_buf->mac_id = mac->id;
-
- setup_tx_buf(eth, tx_buf, txd_pdma, txd_info.addr,
- txd_info.size, k++);
-
frag_size -= txd_info.size;
offset += txd_info.size;
+ txd_info.last = i == skb_shinfo(cur_skb)->nr_frags - 1 &&
+ !frag_size;
+ if (mtk_tx_map_info(eth, ring, dev, &state, &txd_info) < 0)
+ goto err_dma;
}
}
- /* store skb to cleanup */
- itx_buf->type = MTK_TYPE_SKB;
- itx_buf->data = skb;
-
if (!MTK_HAS_CAPS(soc->caps, MTK_QDMA)) {
- if (k & 0x1)
- txd_pdma->txd2 |= TX_DMA_LS0;
- else
- txd_pdma->txd2 |= TX_DMA_LS1;
+ if (state.nbuf & 0x1) {
+ state.txd_pdma->txd2 |= TX_DMA_LS0;
+ state.nbuf++;
+ } else {
+ state.txd_pdma->txd2 |= TX_DMA_LS1;
+ }
}
+ if (next_skb) {
+ cur_skb = next_skb;
+ next_skb = cur_skb->next;
+ goto next;
+ }
+
+ /* store skb to cleanup */
+ state.tx_buf->type = MTK_TYPE_SKB;
+ state.tx_buf->data = skb;
+
netdev_tx_sent_queue(txq, skb->len);
skb_tx_timestamp(skb);
- ring->next_free = mtk_qdma_phys_to_virt(ring, txd->txd2);
- atomic_sub(n_desc, &ring->free_count);
+ ring->next_free = mtk_qdma_phys_to_virt(ring, state.txd->txd2);
+ atomic_sub(state.ndesc, &ring->free_count);
/* make sure that all changes to the dma ring are flushed before we
* continue
@@ -1531,11 +1659,11 @@ static int mtk_tx_map(struct sk_buff *sk
if (MTK_HAS_CAPS(soc->caps, MTK_QDMA)) {
if (netif_xmit_stopped(txq) || !netdev_xmit_more())
- mtk_w32(eth, txd->txd2, soc->reg_map->qdma.ctx_ptr);
+ mtk_w32(eth, state.txd->txd2, soc->reg_map->qdma.ctx_ptr);
} else {
int next_idx;
- next_idx = NEXT_DESP_IDX(txd_to_idx(ring, txd, soc->tx.desc_shift),
+ next_idx = NEXT_DESP_IDX(txd_to_idx(ring, state.txd, soc->tx.desc_shift),
ring->dma_size);
mtk_w32(eth, next_idx, MT7628_TX_CTX_IDX0);
}
@@ -1544,18 +1672,20 @@ static int mtk_tx_map(struct sk_buff *sk
err_dma:
do {
- tx_buf = mtk_desc_to_tx_buf(ring, itxd, soc->tx.desc_shift);
+ struct mtk_tx_dma *itxd_pdma = qdma_to_pdma(ring, itxd);
+ struct mtk_tx_buf *itx_buf;
+
+ itx_buf = mtk_desc_to_tx_buf(ring, itxd, soc->tx.desc_shift);
/* unmap dma */
- mtk_tx_unmap(eth, tx_buf, NULL, false);
+ mtk_tx_unmap(eth, itx_buf, NULL, false);
itxd->txd3 = TX_DMA_LS0 | TX_DMA_OWNER_CPU;
if (!MTK_HAS_CAPS(soc->caps, MTK_QDMA))
itxd_pdma->txd2 = TX_DMA_DESP2_DEF;
itxd = mtk_qdma_phys_to_virt(ring, itxd->txd2);
- itxd_pdma = qdma_to_pdma(ring, itxd);
- } while (itxd != txd);
+ } while (itxd != state.txd);
return -ENOMEM;
}
@@ -1575,6 +1705,9 @@ static int mtk_cal_txd_req(struct mtk_et
nfrags += skb_shinfo(skb)->nr_frags;
}
+ for (skb = skb_shinfo(skb)->frag_list; skb; skb = skb->next)
+ nfrags += mtk_cal_txd_req(eth, skb) + 1;
+
return nfrags;
}
@@ -1615,9 +1748,26 @@ static bool mtk_skb_has_small_frag(struc
if (skb_frag_size(&skb_shinfo(skb)->frags[i]) < min_size)
return true;
+ for (skb = skb_shinfo(skb)->frag_list; skb; skb = skb->next)
+ if (mtk_skb_has_small_frag(skb))
+ return true;
+
return false;
}
+static bool mtk_skb_valid_gso(struct mtk_eth *eth, struct sk_buff *skb,
+ unsigned int header_len)
+{
+ if (mtk_is_netsys_v1(eth) && mtk_skb_has_small_frag(skb))
+ return false;
+
+ if (!(skb_shinfo(skb)->gso_type & SKB_GSO_FRAGLIST))
+ return true;
+
+ return skb_pagelen(skb) - header_len == skb_shinfo(skb)->gso_size &&
+ skb_headlen(skb) > header_len;
+}
+
static netdev_tx_t mtk_start_xmit(struct sk_buff *skb, struct net_device *dev)
{
struct mtk_mac *mac = netdev_priv(dev);
@@ -1625,6 +1775,7 @@ static netdev_tx_t mtk_start_xmit(struct
struct mtk_tx_ring *ring = &eth->tx_ring;
struct net_device_stats *stats = &dev->stats;
struct sk_buff *segs, *next;
+ unsigned int header_len = 0;
bool gso = false;
int tx_num;
@@ -1646,37 +1797,42 @@ static netdev_tx_t mtk_start_xmit(struct
return NETDEV_TX_BUSY;
}
- if (mtk_is_netsys_v1(eth) &&
- 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)) {
- netif_warn(eth, tx_err, dev,
- "GSO expand head fail.\n");
- goto drop;
+ header_len = skb_tcp_all_headers(skb);
+ if (!mtk_skb_valid_gso(eth, skb, header_len)) {
+ segs = skb_gso_segment(skb, dev->features & ~NETIF_F_ALL_TSO);
+ if (IS_ERR(segs))
+ goto drop;
+
+ if (segs) {
+ consume_skb(skb);
+ skb = segs;
+ }
+ goto send;
}
+ if ((skb_shinfo(skb)->gso_type & SKB_GSO_FRAGLIST))
+ goto send;
+
if (skb_shinfo(skb)->gso_type &
(SKB_GSO_TCPV4 | SKB_GSO_TCPV6)) {
+ /* TSO: fill MSS info in tcp checksum field */
gso = true;
+ if (skb_cow_head(skb, 0)) {
+ netif_warn(eth, tx_err, dev,
+ "GSO expand head fail.\n");
+ goto drop;
+ }
+
tcp_hdr(skb)->check = htons(skb_shinfo(skb)->gso_size);
}
}
+send:
skb_list_walk_safe(skb, skb, next) {
if ((mtk_is_netsys_v1(eth) &&
mtk_skb_has_small_frag(skb) && skb_linearize(skb)) ||
- mtk_tx_map(skb, dev, tx_num, ring, gso) < 0) {
+ mtk_tx_map(skb, dev, tx_num, ring, gso, header_len) < 0) {
stats->tx_dropped++;
dev_kfree_skb_any(skb);
}
--- a/drivers/net/ethernet/mediatek/mtk_eth_soc.h
+++ b/drivers/net/ethernet/mediatek/mtk_eth_soc.h
@@ -51,6 +51,8 @@
NETIF_F_HW_VLAN_CTAG_TX | \
NETIF_F_SG | NETIF_F_TSO | \
NETIF_F_TSO6 | \
+ NETIF_F_FRAGLIST | \
+ NETIF_F_GSO_FRAGLIST | \
NETIF_F_IPV6_CSUM |\
NETIF_F_HW_TC)
#define MTK_HW_FEATURES_MT7628 (NETIF_F_SG | NETIF_F_RXCSUM)

View file

@ -10,7 +10,7 @@ Signed-off-by: Felix Fietkau <nbd@nbd.name>
--- a/drivers/net/ethernet/mediatek/mtk_eth_soc.c
+++ b/drivers/net/ethernet/mediatek/mtk_eth_soc.c
@@ -2300,7 +2300,7 @@ static int mtk_poll_rx(struct napi_struc
@@ -2151,7 +2151,7 @@ static int mtk_poll_rx(struct napi_struc
if (ret != XDP_PASS)
goto skip_rx;
@ -19,7 +19,7 @@ Signed-off-by: Felix Fietkau <nbd@nbd.name>
if (unlikely(!skb)) {
page_pool_put_full_page(ring->page_pool,
page, true);
@@ -2338,7 +2338,7 @@ static int mtk_poll_rx(struct napi_struc
@@ -2189,7 +2189,7 @@ static int mtk_poll_rx(struct napi_struc
dma_unmap_single(eth->dma_dev, ((u64)trxd.rxd1 | addr64),
ring->buf_size, DMA_FROM_DEVICE);

View file

@ -15,7 +15,7 @@ Signed-off-by: Chad Monroe <chad@monroe.io>
--- a/drivers/net/ethernet/mediatek/mtk_eth_soc.h
+++ b/drivers/net/ethernet/mediatek/mtk_eth_soc.h
@@ -282,6 +282,7 @@
@@ -279,6 +279,7 @@
#define MTK_WCOMP_EN BIT(24)
#define MTK_RESV_BUF (0x80 << 16)
#define MTK_MUTLI_CNT (0x4 << 12)
@ -25,7 +25,7 @@ Signed-off-by: Chad Monroe <chad@monroe.io>
/* QDMA Flow Control Register */
--- a/drivers/net/ethernet/mediatek/mtk_eth_soc.c
+++ b/drivers/net/ethernet/mediatek/mtk_eth_soc.c
@@ -3476,12 +3476,14 @@ static int mtk_start_dma(struct mtk_eth
@@ -3324,12 +3324,14 @@ static int mtk_start_dma(struct mtk_eth
MTK_TX_BT_32DWORDS | MTK_NDP_CO_PRO |
MTK_RX_2B_OFFSET | MTK_TX_WB_DDONE;

View file

@ -205,7 +205,7 @@ Signed-off-by: Daniel Golle <daniel@makrotopia.org>
return mtk_eth_mux_setup(eth, path);
--- a/drivers/net/ethernet/mediatek/mtk_eth_soc.c
+++ b/drivers/net/ethernet/mediatek/mtk_eth_soc.c
@@ -24,6 +24,8 @@
@@ -22,6 +22,8 @@
#include <linux/pinctrl/devinfo.h>
#include <linux/phylink.h>
#include <linux/pcs/pcs-mtk-lynxi.h>
@ -214,7 +214,7 @@ Signed-off-by: Daniel Golle <daniel@makrotopia.org>
#include <linux/jhash.h>
#include <linux/bitfield.h>
#include <net/dsa.h>
@@ -522,6 +524,30 @@ static void mtk_setup_bridge_switch(stru
@@ -514,6 +516,30 @@ static void mtk_setup_bridge_switch(stru
MTK_GSW_CFG);
}
@ -245,7 +245,7 @@ Signed-off-by: Daniel Golle <daniel@makrotopia.org>
static struct phylink_pcs *mtk_mac_select_pcs(struct phylink_config *config,
phy_interface_t interface)
{
@@ -530,6 +556,21 @@ static struct phylink_pcs *mtk_mac_selec
@@ -522,6 +548,21 @@ static struct phylink_pcs *mtk_mac_selec
struct mtk_eth *eth = mac->hw;
unsigned int sid;
@ -267,7 +267,7 @@ Signed-off-by: Daniel Golle <daniel@makrotopia.org>
if (interface == PHY_INTERFACE_MODE_SGMII ||
phy_interface_mode_is_8023z(interface)) {
sid = (MTK_HAS_CAPS(eth->soc->caps, MTK_SHARED_SGMII)) ?
@@ -581,7 +622,22 @@ static void mtk_mac_config(struct phylin
@@ -573,7 +614,22 @@ static void mtk_mac_config(struct phylin
goto init_err;
}
break;
@ -290,7 +290,7 @@ Signed-off-by: Daniel Golle <daniel@makrotopia.org>
break;
default:
goto err_phy;
@@ -628,8 +684,6 @@ static void mtk_mac_config(struct phylin
@@ -620,8 +676,6 @@ static void mtk_mac_config(struct phylin
val &= ~SYSCFG0_GE_MODE(SYSCFG0_GE_MASK, mac->id);
val |= SYSCFG0_GE_MODE(ge_mode, mac->id);
regmap_write(eth->ethsys, ETHSYS_SYSCFG0, val);
@ -299,7 +299,7 @@ Signed-off-by: Daniel Golle <daniel@makrotopia.org>
}
/* SGMII */
@@ -646,21 +700,40 @@ static void mtk_mac_config(struct phylin
@@ -638,21 +692,40 @@ static void mtk_mac_config(struct phylin
/* Save the syscfg0 value for mac_finish */
mac->syscfg0 = val;
@ -347,7 +347,7 @@ Signed-off-by: Daniel Golle <daniel@makrotopia.org>
return;
err_phy:
@@ -673,6 +746,18 @@ init_err:
@@ -665,6 +738,18 @@ init_err:
mac->id, phy_modes(state->interface), err);
}
@ -366,7 +366,7 @@ Signed-off-by: Daniel Golle <daniel@makrotopia.org>
static int mtk_mac_finish(struct phylink_config *config, unsigned int mode,
phy_interface_t interface)
{
@@ -681,6 +766,10 @@ static int mtk_mac_finish(struct phylink
@@ -673,6 +758,10 @@ static int mtk_mac_finish(struct phylink
struct mtk_eth *eth = mac->hw;
u32 mcr_cur, mcr_new;
@ -377,7 +377,7 @@ Signed-off-by: Daniel Golle <daniel@makrotopia.org>
/* Enable SGMII */
if (interface == PHY_INTERFACE_MODE_SGMII ||
phy_interface_mode_is_8023z(interface))
@@ -705,10 +794,14 @@ static void mtk_mac_link_down(struct phy
@@ -697,10 +786,14 @@ static void mtk_mac_link_down(struct phy
{
struct mtk_mac *mac = container_of(config, struct mtk_mac,
phylink_config);
@ -395,7 +395,7 @@ Signed-off-by: Daniel Golle <daniel@makrotopia.org>
}
static void mtk_set_queue_speed(struct mtk_eth *eth, unsigned int idx,
@@ -780,13 +873,11 @@ static void mtk_set_queue_speed(struct m
@@ -772,13 +865,11 @@ static void mtk_set_queue_speed(struct m
mtk_w32(eth, val, soc->reg_map->qdma.qtx_sch + ofs);
}
@ -413,7 +413,7 @@ Signed-off-by: Daniel Golle <daniel@makrotopia.org>
u32 mcr;
mcr = mtk_r32(mac->hw, MTK_MAC_MCR(mac->id));
@@ -830,9 +921,63 @@ static void mtk_mac_link_up(struct phyli
@@ -822,9 +913,63 @@ static void mtk_mac_link_up(struct phyli
mtk_w32(mac->hw, mcr, MTK_MAC_MCR(mac->id));
}
@ -477,7 +477,7 @@ Signed-off-by: Daniel Golle <daniel@makrotopia.org>
.mac_finish = mtk_mac_finish,
.mac_link_down = mtk_mac_link_down,
.mac_link_up = mtk_mac_link_up,
@@ -3584,6 +3729,9 @@ static int mtk_open(struct net_device *d
@@ -3432,6 +3577,9 @@ static int mtk_open(struct net_device *d
ppe_num = eth->soc->ppe_num;
@ -487,7 +487,7 @@ Signed-off-by: Daniel Golle <daniel@makrotopia.org>
err = phylink_of_phy_connect(mac->phylink, mac->of_node, 0);
if (err) {
netdev_err(dev, "%s: could not attach PHY: %d\n", __func__,
@@ -3731,6 +3879,9 @@ static int mtk_stop(struct net_device *d
@@ -3579,6 +3727,9 @@ static int mtk_stop(struct net_device *d
for (i = 0; i < ARRAY_SIZE(eth->ppe); i++)
mtk_ppe_stop(eth->ppe[i]);
@ -497,7 +497,7 @@ Signed-off-by: Daniel Golle <daniel@makrotopia.org>
return 0;
}
@@ -4821,6 +4972,7 @@ static const struct net_device_ops mtk_n
@@ -4669,6 +4820,7 @@ static const struct net_device_ops mtk_n
static int mtk_add_mac(struct mtk_eth *eth, struct device_node *np)
{
const __be32 *_id = of_get_property(np, "reg", NULL);
@ -505,7 +505,7 @@ Signed-off-by: Daniel Golle <daniel@makrotopia.org>
phy_interface_t phy_mode;
struct phylink *phylink;
struct mtk_mac *mac;
@@ -4859,16 +5011,41 @@ static int mtk_add_mac(struct mtk_eth *e
@@ -4707,16 +4859,41 @@ static int mtk_add_mac(struct mtk_eth *e
mac->id = id;
mac->hw = eth;
mac->of_node = np;
@ -555,7 +555,7 @@ Signed-off-by: Daniel Golle <daniel@makrotopia.org>
}
memset(mac->hwlro_ip, 0, sizeof(mac->hwlro_ip));
@@ -4951,8 +5128,21 @@ static int mtk_add_mac(struct mtk_eth *e
@@ -4799,8 +4976,21 @@ static int mtk_add_mac(struct mtk_eth *e
phy_interface_zero(mac->phylink_config.supported_interfaces);
__set_bit(PHY_INTERFACE_MODE_INTERNAL,
mac->phylink_config.supported_interfaces);
@ -577,7 +577,7 @@ Signed-off-by: Daniel Golle <daniel@makrotopia.org>
phylink = phylink_create(&mac->phylink_config,
of_fwnode_handle(mac->of_node),
phy_mode, &mtk_phylink_ops);
@@ -5003,6 +5193,26 @@ free_netdev:
@@ -4851,6 +5041,26 @@ free_netdev:
return err;
}
@ -604,7 +604,7 @@ Signed-off-by: Daniel Golle <daniel@makrotopia.org>
void mtk_eth_set_dma_device(struct mtk_eth *eth, struct device *dma_dev)
{
struct net_device *dev, *tmp;
@@ -5149,7 +5359,8 @@ static int mtk_probe(struct platform_dev
@@ -4997,7 +5207,8 @@ static int mtk_probe(struct platform_dev
regmap_write(cci, 0, 3);
}
@ -614,7 +614,7 @@ Signed-off-by: Daniel Golle <daniel@makrotopia.org>
err = mtk_sgmii_init(eth);
if (err)
@@ -5260,6 +5471,24 @@ static int mtk_probe(struct platform_dev
@@ -5108,6 +5319,24 @@ static int mtk_probe(struct platform_dev
}
}
@ -639,7 +639,7 @@ Signed-off-by: Daniel Golle <daniel@makrotopia.org>
if (MTK_HAS_CAPS(eth->soc->caps, MTK_SHARED_INT)) {
err = devm_request_irq(eth->dev, eth->irq[0],
mtk_handle_irq, 0,
@@ -5370,6 +5599,11 @@ static void mtk_remove(struct platform_d
@@ -5218,6 +5447,11 @@ static void mtk_remove(struct platform_d
mtk_stop(eth->netdev[i]);
mac = netdev_priv(eth->netdev[i]);
phylink_disconnect_phy(mac->phylink);
@ -661,7 +661,7 @@ Signed-off-by: Daniel Golle <daniel@makrotopia.org>
#include <linux/rhashtable.h>
#include <linux/dim.h>
#include <linux/bitfield.h>
@@ -527,6 +528,21 @@
@@ -524,6 +525,21 @@
#define INTF_MODE_RGMII_1000 (TRGMII_MODE | TRGMII_CENTRAL_ALIGNED)
#define INTF_MODE_RGMII_10_100 0
@ -683,7 +683,7 @@ Signed-off-by: Daniel Golle <daniel@makrotopia.org>
/* GPIO port control registers for GMAC 2*/
#define GPIO_OD33_CTRL8 0x4c0
#define GPIO_BIAS_CTRL 0xed0
@@ -552,6 +568,7 @@
@@ -549,6 +565,7 @@
#define SYSCFG0_SGMII_GMAC2 ((3 << 8) & SYSCFG0_SGMII_MASK)
#define SYSCFG0_SGMII_GMAC1_V2 BIT(9)
#define SYSCFG0_SGMII_GMAC2_V2 BIT(8)
@ -691,7 +691,7 @@ Signed-off-by: Daniel Golle <daniel@makrotopia.org>
/* ethernet subsystem clock register */
@@ -590,6 +607,11 @@
@@ -587,6 +604,11 @@
#define GEPHY_MAC_SEL BIT(1)
/* Top misc registers */
@ -703,7 +703,7 @@ Signed-off-by: Daniel Golle <daniel@makrotopia.org>
#define USB_PHY_SWITCH_REG 0x218
#define QPHY_SEL_MASK GENMASK(1, 0)
#define SGMII_QPHY_SEL 0x2
@@ -614,6 +636,8 @@
@@ -611,6 +633,8 @@
#define MT7628_SDM_RBCNT (MT7628_SDM_OFFSET + 0x10c)
#define MT7628_SDM_CS_ERR (MT7628_SDM_OFFSET + 0x110)
@ -712,7 +712,7 @@ Signed-off-by: Daniel Golle <daniel@makrotopia.org>
#define MTK_FE_CDM1_FSM 0x220
#define MTK_FE_CDM2_FSM 0x224
#define MTK_FE_CDM3_FSM 0x238
@@ -622,6 +646,11 @@
@@ -619,6 +643,11 @@
#define MTK_FE_CDM6_FSM 0x328
#define MTK_FE_GDM1_FSM 0x228
#define MTK_FE_GDM2_FSM 0x22C
@ -724,7 +724,7 @@ Signed-off-by: Daniel Golle <daniel@makrotopia.org>
#define MTK_MAC_FSM(x) (0x1010C + ((x) * 0x100))
@@ -945,6 +974,8 @@ enum mkt_eth_capabilities {
@@ -951,6 +980,8 @@ enum mkt_eth_capabilities {
MTK_RGMII_BIT = 0,
MTK_TRGMII_BIT,
MTK_SGMII_BIT,
@ -733,7 +733,7 @@ Signed-off-by: Daniel Golle <daniel@makrotopia.org>
MTK_ESW_BIT,
MTK_GEPHY_BIT,
MTK_MUX_BIT,
@@ -965,8 +996,11 @@ enum mkt_eth_capabilities {
@@ -971,8 +1002,11 @@ enum mkt_eth_capabilities {
MTK_ETH_MUX_GDM1_TO_GMAC1_ESW_BIT,
MTK_ETH_MUX_GMAC2_GMAC0_TO_GEPHY_BIT,
MTK_ETH_MUX_U3_GMAC2_TO_QPHY_BIT,
@ -745,7 +745,7 @@ Signed-off-by: Daniel Golle <daniel@makrotopia.org>
/* PATH BITS */
MTK_ETH_PATH_GMAC1_RGMII_BIT,
@@ -974,14 +1008,21 @@ enum mkt_eth_capabilities {
@@ -980,14 +1014,21 @@ enum mkt_eth_capabilities {
MTK_ETH_PATH_GMAC1_SGMII_BIT,
MTK_ETH_PATH_GMAC2_RGMII_BIT,
MTK_ETH_PATH_GMAC2_SGMII_BIT,
@ -767,7 +767,7 @@ Signed-off-by: Daniel Golle <daniel@makrotopia.org>
#define MTK_ESW BIT_ULL(MTK_ESW_BIT)
#define MTK_GEPHY BIT_ULL(MTK_GEPHY_BIT)
#define MTK_MUX BIT_ULL(MTK_MUX_BIT)
@@ -1004,10 +1045,16 @@ enum mkt_eth_capabilities {
@@ -1010,10 +1051,16 @@ enum mkt_eth_capabilities {
BIT_ULL(MTK_ETH_MUX_GMAC2_GMAC0_TO_GEPHY_BIT)
#define MTK_ETH_MUX_U3_GMAC2_TO_QPHY \
BIT_ULL(MTK_ETH_MUX_U3_GMAC2_TO_QPHY_BIT)
@ -784,7 +784,7 @@ Signed-off-by: Daniel Golle <daniel@makrotopia.org>
/* Supported path present on SoCs */
#define MTK_ETH_PATH_GMAC1_RGMII BIT_ULL(MTK_ETH_PATH_GMAC1_RGMII_BIT)
@@ -1015,8 +1062,13 @@ enum mkt_eth_capabilities {
@@ -1021,8 +1068,13 @@ enum mkt_eth_capabilities {
#define MTK_ETH_PATH_GMAC1_SGMII BIT_ULL(MTK_ETH_PATH_GMAC1_SGMII_BIT)
#define MTK_ETH_PATH_GMAC2_RGMII BIT_ULL(MTK_ETH_PATH_GMAC2_RGMII_BIT)
#define MTK_ETH_PATH_GMAC2_SGMII BIT_ULL(MTK_ETH_PATH_GMAC2_SGMII_BIT)
@ -798,7 +798,7 @@ Signed-off-by: Daniel Golle <daniel@makrotopia.org>
#define MTK_GMAC1_RGMII (MTK_ETH_PATH_GMAC1_RGMII | MTK_RGMII)
#define MTK_GMAC1_TRGMII (MTK_ETH_PATH_GMAC1_TRGMII | MTK_TRGMII)
@@ -1024,7 +1076,12 @@ enum mkt_eth_capabilities {
@@ -1030,7 +1082,12 @@ enum mkt_eth_capabilities {
#define MTK_GMAC2_RGMII (MTK_ETH_PATH_GMAC2_RGMII | MTK_RGMII)
#define MTK_GMAC2_SGMII (MTK_ETH_PATH_GMAC2_SGMII | MTK_SGMII)
#define MTK_GMAC2_GEPHY (MTK_ETH_PATH_GMAC2_GEPHY | MTK_GEPHY)
@ -811,7 +811,7 @@ Signed-off-by: Daniel Golle <daniel@makrotopia.org>
/* MUXes present on SoCs */
/* 0: GDM1 -> GMAC1, 1: GDM1 -> ESW */
@@ -1043,10 +1100,20 @@ enum mkt_eth_capabilities {
@@ -1049,10 +1106,20 @@ enum mkt_eth_capabilities {
(MTK_ETH_MUX_GMAC1_GMAC2_TO_SGMII_RGMII | MTK_MUX | \
MTK_SHARED_SGMII)
@ -832,7 +832,7 @@ Signed-off-by: Daniel Golle <daniel@makrotopia.org>
#define MTK_HAS_CAPS(caps, _x) (((caps) & (_x)) == (_x))
#define MT7621_CAPS (MTK_GMAC1_RGMII | MTK_GMAC1_TRGMII | \
@@ -1078,8 +1145,12 @@ enum mkt_eth_capabilities {
@@ -1084,8 +1151,12 @@ enum mkt_eth_capabilities {
MTK_MUX_GMAC12_TO_GEPHY_SGMII | MTK_QDMA | \
MTK_RSTCTRL_PPE1 | MTK_SRAM)
@ -847,7 +847,7 @@ Signed-off-by: Daniel Golle <daniel@makrotopia.org>
struct mtk_tx_dma_desc_info {
dma_addr_t addr;
@@ -1327,6 +1398,9 @@ struct mtk_mac {
@@ -1333,6 +1404,9 @@ struct mtk_mac {
struct device_node *of_node;
struct phylink *phylink;
struct phylink_config phylink_config;
@ -857,7 +857,7 @@ Signed-off-by: Daniel Golle <daniel@makrotopia.org>
struct mtk_eth *hw;
struct mtk_hw_stats *hw_stats;
__be32 hwlro_ip[MTK_MAX_LRO_IP_CNT];
@@ -1450,6 +1524,19 @@ static inline u32 mtk_get_ib2_multicast_
@@ -1456,6 +1530,19 @@ static inline u32 mtk_get_ib2_multicast_
return MTK_FOE_IB2_MULTICAST;
}
@ -877,7 +877,7 @@ Signed-off-by: Daniel Golle <daniel@makrotopia.org>
/* read the hardware status register */
void mtk_stats_update_mac(struct mtk_mac *mac);
@@ -1458,8 +1545,10 @@ u32 mtk_r32(struct mtk_eth *eth, unsigne
@@ -1464,8 +1551,10 @@ u32 mtk_r32(struct mtk_eth *eth, unsigne
u32 mtk_m32(struct mtk_eth *eth, u32 mask, u32 set, unsigned int reg);
int mtk_gmac_sgmii_path_setup(struct mtk_eth *eth, int mac_id);

View file

@ -30,8 +30,8 @@ Signed-off-by: Felix Fietkau <nbd@nbd.name>
--- a/drivers/net/ethernet/mediatek/mtk_eth_soc.c
+++ b/drivers/net/ethernet/mediatek/mtk_eth_soc.c
@@ -5637,7 +5637,7 @@ static const struct mtk_soc_data mt2701_
DESC_SIZE(struct mtk_rx_dma),
@@ -5482,7 +5482,7 @@ static const struct mtk_soc_data mt2701_
.desc_size = sizeof(struct mtk_rx_dma),
.irq_done_mask = MTK_RX_DONE_INT,
.dma_l4_valid = RX_DMA_L4_VALID,
- .dma_size = MTK_DMA_SIZE(2K),
@ -39,8 +39,8 @@ Signed-off-by: Felix Fietkau <nbd@nbd.name>
.dma_max_len = MTK_TX_DMA_BUF_LEN,
.dma_len_offset = 16,
},
@@ -5665,7 +5665,7 @@ static const struct mtk_soc_data mt7621_
DESC_SIZE(struct mtk_rx_dma),
@@ -5510,7 +5510,7 @@ static const struct mtk_soc_data mt7621_
.desc_size = sizeof(struct mtk_rx_dma),
.irq_done_mask = MTK_RX_DONE_INT,
.dma_l4_valid = RX_DMA_L4_VALID,
- .dma_size = MTK_DMA_SIZE(2K),
@ -48,8 +48,8 @@ Signed-off-by: Felix Fietkau <nbd@nbd.name>
.dma_max_len = MTK_TX_DMA_BUF_LEN,
.dma_len_offset = 16,
},
@@ -5695,7 +5695,7 @@ static const struct mtk_soc_data mt7622_
DESC_SIZE(struct mtk_rx_dma),
@@ -5540,7 +5540,7 @@ static const struct mtk_soc_data mt7622_
.desc_size = sizeof(struct mtk_rx_dma),
.irq_done_mask = MTK_RX_DONE_INT,
.dma_l4_valid = RX_DMA_L4_VALID,
- .dma_size = MTK_DMA_SIZE(2K),
@ -57,8 +57,8 @@ Signed-off-by: Felix Fietkau <nbd@nbd.name>
.dma_max_len = MTK_TX_DMA_BUF_LEN,
.dma_len_offset = 16,
},
@@ -5724,7 +5724,7 @@ static const struct mtk_soc_data mt7623_
DESC_SIZE(struct mtk_rx_dma),
@@ -5569,7 +5569,7 @@ static const struct mtk_soc_data mt7623_
.desc_size = sizeof(struct mtk_rx_dma),
.irq_done_mask = MTK_RX_DONE_INT,
.dma_l4_valid = RX_DMA_L4_VALID,
- .dma_size = MTK_DMA_SIZE(2K),
@ -66,8 +66,8 @@ Signed-off-by: Felix Fietkau <nbd@nbd.name>
.dma_max_len = MTK_TX_DMA_BUF_LEN,
.dma_len_offset = 16,
},
@@ -5750,7 +5750,7 @@ static const struct mtk_soc_data mt7629_
DESC_SIZE(struct mtk_rx_dma),
@@ -5595,7 +5595,7 @@ static const struct mtk_soc_data mt7629_
.desc_size = sizeof(struct mtk_rx_dma),
.irq_done_mask = MTK_RX_DONE_INT,
.dma_l4_valid = RX_DMA_L4_VALID,
- .dma_size = MTK_DMA_SIZE(2K),
@ -75,7 +75,7 @@ Signed-off-by: Felix Fietkau <nbd@nbd.name>
.dma_max_len = MTK_TX_DMA_BUF_LEN,
.dma_len_offset = 16,
},
@@ -5782,7 +5782,7 @@ static const struct mtk_soc_data mt7981_
@@ -5627,7 +5627,7 @@ static const struct mtk_soc_data mt7981_
.dma_l4_valid = RX_DMA_L4_VALID_V2,
.dma_max_len = MTK_TX_DMA_BUF_LEN,
.dma_len_offset = 16,
@ -84,7 +84,7 @@ Signed-off-by: Felix Fietkau <nbd@nbd.name>
},
};
@@ -5812,7 +5812,7 @@ static const struct mtk_soc_data mt7986_
@@ -5657,7 +5657,7 @@ static const struct mtk_soc_data mt7986_
.dma_l4_valid = RX_DMA_L4_VALID_V2,
.dma_max_len = MTK_TX_DMA_BUF_LEN,
.dma_len_offset = 16,
@ -93,7 +93,7 @@ Signed-off-by: Felix Fietkau <nbd@nbd.name>
},
};
@@ -5865,7 +5865,7 @@ static const struct mtk_soc_data rt5350_
@@ -5710,7 +5710,7 @@ static const struct mtk_soc_data rt5350_
.dma_l4_valid = RX_DMA_L4_VALID_PDMA,
.dma_max_len = MTK_TX_DMA_BUF_LEN,
.dma_len_offset = 16,

View file

@ -25,7 +25,7 @@ Signed-off-by: Felix Fietkau <nbd@nbd.name>
help
--- a/drivers/net/ethernet/mediatek/mtk_eth_soc.c
+++ b/drivers/net/ethernet/mediatek/mtk_eth_soc.c
@@ -4740,6 +4740,7 @@ static int mtk_get_sset_count(struct net
@@ -4588,6 +4588,7 @@ static int mtk_get_sset_count(struct net
static void mtk_ethtool_pp_stats(struct mtk_eth *eth, u64 *data)
{
@ -33,7 +33,7 @@ Signed-off-by: Felix Fietkau <nbd@nbd.name>
struct page_pool_stats stats = {};
int i;
@@ -4752,6 +4753,7 @@ static void mtk_ethtool_pp_stats(struct
@@ -4600,6 +4601,7 @@ static void mtk_ethtool_pp_stats(struct
page_pool_get_stats(ring->page_pool, &stats);
}
page_pool_ethtool_stats_get(data, &stats);

View file

@ -12,7 +12,7 @@ Signed-off-by: Felix Fietkau <nbd@nbd.name>
--- a/drivers/net/ethernet/mediatek/mtk_eth_soc.c
+++ b/drivers/net/ethernet/mediatek/mtk_eth_soc.c
@@ -1924,6 +1924,13 @@ static netdev_tx_t mtk_start_xmit(struct
@@ -1778,6 +1778,13 @@ static netdev_tx_t mtk_start_xmit(struct
bool gso = false;
int tx_num;
@ -26,7 +26,7 @@ Signed-off-by: Felix Fietkau <nbd@nbd.name>
/* normally we can rely on the stack not calling this more than once,
* however we have 2 queues running on the same ring so we need to lock
* the ring access
@@ -1992,8 +1999,9 @@ send:
@@ -1841,8 +1848,9 @@ static netdev_tx_t mtk_start_xmit(struct
drop:
spin_unlock(&eth->page_lock);

View file

@ -0,0 +1,21 @@
From: Felix Fietkau <nbd@nbd.name>
Date: Fri, 28 Oct 2022 12:54:48 +0200
Subject: [PATCH] net: ethernet: mtk_eth_soc: set NETIF_F_ALL_TSO
Significantly improves performance by avoiding unnecessary segmentation
Signed-off-by: Felix Fietkau <nbd@nbd.name>
---
--- a/drivers/net/ethernet/mediatek/mtk_eth_soc.h
+++ b/drivers/net/ethernet/mediatek/mtk_eth_soc.h
@@ -49,8 +49,7 @@
#define MTK_HW_FEATURES (NETIF_F_IP_CSUM | \
NETIF_F_RXCSUM | \
NETIF_F_HW_VLAN_CTAG_TX | \
- 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)

View file

@ -1,542 +0,0 @@
From: Felix Fietkau <nbd@nbd.name>
Date: Tue, 15 Oct 2024 12:52:56 +0200
Subject: [PATCH] net: ethernet: mtk_eth_soc: optimize dma ring address/index
calculation
Since DMA descriptor sizes are all power of 2, we can avoid costly integer
division in favor or simple shifts.
Signed-off-by: Felix Fietkau <nbd@nbd.name>
---
--- a/drivers/net/ethernet/mediatek/mtk_eth_soc.c
+++ b/drivers/net/ethernet/mediatek/mtk_eth_soc.c
@@ -43,6 +43,11 @@ MODULE_PARM_DESC(msg_level, "Message lev
offsetof(struct mtk_hw_stats, xdp_stats.x) / \
sizeof(u64) }
+#define RX_DESC_OFS(eth, i) \
+ ((i) << (eth)->soc->rx.desc_shift)
+#define TX_DESC_OFS(eth, i) \
+ ((i) << (eth)->soc->tx.desc_shift)
+
static const struct mtk_reg_map mtk_reg_map = {
.tx_irq_mask = 0x1a1c,
.tx_irq_status = 0x1a18,
@@ -1150,23 +1155,28 @@ static void *mtk_max_lro_buf_alloc(gfp_t
static int mtk_init_fq_dma(struct mtk_eth *eth)
{
const struct mtk_soc_data *soc = eth->soc;
- dma_addr_t phy_ring_tail;
+ dma_addr_t phy_ring_tail, phy_ring_addr;
int cnt = soc->tx.fq_dma_size;
dma_addr_t dma_addr;
+ void *ring_addr;
+ u32 desc_size;
int i, j, len;
if (MTK_HAS_CAPS(eth->soc->caps, MTK_SRAM))
eth->scratch_ring = eth->sram_base;
else
eth->scratch_ring = dma_alloc_coherent(eth->dma_dev,
- cnt * soc->tx.desc_size,
+ TX_DESC_OFS(eth, cnt),
&eth->phy_scratch_ring,
GFP_KERNEL);
if (unlikely(!eth->scratch_ring))
return -ENOMEM;
- phy_ring_tail = eth->phy_scratch_ring + soc->tx.desc_size * (cnt - 1);
+ phy_ring_tail = eth->phy_scratch_ring + TX_DESC_OFS(eth, cnt - 1);
+ ring_addr = eth->scratch_ring;
+ phy_ring_addr = eth->phy_scratch_ring;
+ desc_size = TX_DESC_OFS(eth, 1);
for (j = 0; j < DIV_ROUND_UP(soc->tx.fq_dma_size, MTK_FQ_DMA_LENGTH); j++) {
len = min_t(int, cnt - j * MTK_FQ_DMA_LENGTH, MTK_FQ_DMA_LENGTH);
@@ -1185,11 +1195,12 @@ static int mtk_init_fq_dma(struct mtk_et
for (i = 0; i < len; i++) {
struct mtk_tx_dma_v2 *txd;
- txd = eth->scratch_ring + (j * MTK_FQ_DMA_LENGTH + i) * soc->tx.desc_size;
+ txd = ring_addr;
+ ring_addr += desc_size;
+ phy_ring_addr += desc_size;
txd->txd1 = dma_addr + i * MTK_QDMA_PAGE_SIZE;
if (j * MTK_FQ_DMA_LENGTH + i < cnt)
- txd->txd2 = eth->phy_scratch_ring +
- (j * MTK_FQ_DMA_LENGTH + i + 1) * soc->tx.desc_size;
+ txd->txd2 = eth->phy_scratch_ring + phy_ring_addr;
txd->txd3 = TX_DMA_PLEN0(MTK_QDMA_PAGE_SIZE);
if (MTK_HAS_CAPS(soc->caps, MTK_36BIT_DMA))
@@ -1219,9 +1230,9 @@ static void *mtk_qdma_phys_to_virt(struc
}
static struct mtk_tx_buf *mtk_desc_to_tx_buf(struct mtk_tx_ring *ring,
- void *txd, u32 txd_size)
+ void *txd, u32 txd_shift)
{
- int idx = (txd - ring->dma) / txd_size;
+ int idx = (txd - ring->dma) >> txd_shift;
return &ring->buf[idx];
}
@@ -1232,9 +1243,9 @@ static struct mtk_tx_dma *qdma_to_pdma(s
return ring->dma_pdma - (struct mtk_tx_dma *)ring->dma + dma;
}
-static int txd_to_idx(struct mtk_tx_ring *ring, void *dma, u32 txd_size)
+static int txd_to_idx(struct mtk_tx_ring *ring, void *dma, u32 txd_shift)
{
- return (dma - ring->dma) / txd_size;
+ return (dma - ring->dma) >> txd_shift;
}
static void mtk_tx_unmap(struct mtk_eth *eth, struct mtk_tx_buf *tx_buf,
@@ -1442,7 +1453,7 @@ static int mtk_tx_map(struct sk_buff *sk
if (itxd == ring->last_free)
return -ENOMEM;
- itx_buf = mtk_desc_to_tx_buf(ring, itxd, soc->tx.desc_size);
+ itx_buf = mtk_desc_to_tx_buf(ring, itxd, soc->tx.desc_shift);
memset(itx_buf, 0, sizeof(*itx_buf));
txd_info.addr = dma_map_single(eth->dma_dev, skb->data, txd_info.size,
@@ -1496,7 +1507,7 @@ static int mtk_tx_map(struct sk_buff *sk
mtk_tx_set_dma_desc(dev, txd, &txd_info);
tx_buf = mtk_desc_to_tx_buf(ring, txd,
- soc->tx.desc_size);
+ soc->tx.desc_shift);
if (new_desc)
memset(tx_buf, 0, sizeof(*tx_buf));
tx_buf->data = (void *)MTK_DMA_DUMMY_DESC;
@@ -1539,7 +1550,7 @@ static int mtk_tx_map(struct sk_buff *sk
} else {
int next_idx;
- next_idx = NEXT_DESP_IDX(txd_to_idx(ring, txd, soc->tx.desc_size),
+ next_idx = NEXT_DESP_IDX(txd_to_idx(ring, txd, soc->tx.desc_shift),
ring->dma_size);
mtk_w32(eth, next_idx, MT7628_TX_CTX_IDX0);
}
@@ -1548,7 +1559,7 @@ static int mtk_tx_map(struct sk_buff *sk
err_dma:
do {
- tx_buf = mtk_desc_to_tx_buf(ring, itxd, soc->tx.desc_size);
+ tx_buf = mtk_desc_to_tx_buf(ring, itxd, soc->tx.desc_shift);
/* unmap dma */
mtk_tx_unmap(eth, tx_buf, NULL, false);
@@ -1714,7 +1725,7 @@ static struct mtk_rx_ring *mtk_get_rx_ri
ring = &eth->rx_ring[i];
idx = NEXT_DESP_IDX(ring->calc_idx, ring->dma_size);
- rxd = ring->dma + idx * eth->soc->rx.desc_size;
+ rxd = ring->dma + RX_DESC_OFS(eth, idx);
if (rxd->rxd2 & RX_DMA_DONE) {
ring->calc_idx_update = true;
return ring;
@@ -1882,7 +1893,7 @@ static int mtk_xdp_submit_frame(struct m
}
htxd = txd;
- tx_buf = mtk_desc_to_tx_buf(ring, txd, soc->tx.desc_size);
+ tx_buf = mtk_desc_to_tx_buf(ring, txd, soc->tx.desc_shift);
memset(tx_buf, 0, sizeof(*tx_buf));
htx_buf = tx_buf;
@@ -1901,7 +1912,7 @@ static int mtk_xdp_submit_frame(struct m
goto unmap;
tx_buf = mtk_desc_to_tx_buf(ring, txd,
- soc->tx.desc_size);
+ soc->tx.desc_shift);
memset(tx_buf, 0, sizeof(*tx_buf));
n_desc++;
}
@@ -1939,7 +1950,7 @@ static int mtk_xdp_submit_frame(struct m
} else {
int idx;
- idx = txd_to_idx(ring, txd, soc->tx.desc_size);
+ idx = txd_to_idx(ring, txd, soc->tx.desc_shift);
mtk_w32(eth, NEXT_DESP_IDX(idx, ring->dma_size),
MT7628_TX_CTX_IDX0);
}
@@ -1950,7 +1961,7 @@ static int mtk_xdp_submit_frame(struct m
unmap:
while (htxd != txd) {
- tx_buf = mtk_desc_to_tx_buf(ring, htxd, soc->tx.desc_size);
+ tx_buf = mtk_desc_to_tx_buf(ring, htxd, soc->tx.desc_shift);
mtk_tx_unmap(eth, tx_buf, NULL, false);
htxd->txd3 = TX_DMA_LS0 | TX_DMA_OWNER_CPU;
@@ -2082,7 +2093,7 @@ static int mtk_poll_rx(struct napi_struc
goto rx_done;
idx = NEXT_DESP_IDX(ring->calc_idx, ring->dma_size);
- rxd = ring->dma + idx * eth->soc->rx.desc_size;
+ rxd = ring->dma + RX_DESC_OFS(eth, idx);
data = ring->data[idx];
if (!mtk_rx_get_desc(eth, &trxd, rxd))
@@ -2346,7 +2357,7 @@ static int mtk_poll_tx_qdma(struct mtk_e
break;
tx_buf = mtk_desc_to_tx_buf(ring, desc,
- eth->soc->tx.desc_size);
+ eth->soc->tx.desc_shift);
if (!tx_buf->data)
break;
@@ -2397,7 +2408,7 @@ static int mtk_poll_tx_pdma(struct mtk_e
}
mtk_tx_unmap(eth, tx_buf, &bq, true);
- desc = ring->dma + cpu * eth->soc->tx.desc_size;
+ desc = ring->dma + TX_DESC_OFS(eth, cpu);
ring->last_free = desc;
atomic_inc(&ring->free_count);
@@ -2515,10 +2526,13 @@ static int mtk_tx_alloc(struct mtk_eth *
{
const struct mtk_soc_data *soc = eth->soc;
struct mtk_tx_ring *ring = &eth->tx_ring;
- int i, sz = soc->tx.desc_size;
struct mtk_tx_dma_v2 *txd;
+ dma_addr_t desc_phys;
+ void *desc_addr;
+ u32 desc_size;
int ring_size;
u32 ofs, val;
+ int i;
if (MTK_HAS_CAPS(soc->caps, MTK_QDMA))
ring_size = MTK_QDMA_RING_SIZE;
@@ -2531,22 +2545,24 @@ static int mtk_tx_alloc(struct mtk_eth *
goto no_tx_mem;
if (MTK_HAS_CAPS(soc->caps, MTK_SRAM)) {
- ring->dma = eth->sram_base + soc->tx.fq_dma_size * sz;
- ring->phys = eth->phy_scratch_ring + soc->tx.fq_dma_size * (dma_addr_t)sz;
+ ring->dma = eth->sram_base + TX_DESC_OFS(eth, soc->tx.fq_dma_size);
+ ring->phys = eth->phy_scratch_ring + TX_DESC_OFS(eth, soc->tx.fq_dma_size);
} else {
- ring->dma = dma_alloc_coherent(eth->dma_dev, ring_size * sz,
+ ring->dma = dma_alloc_coherent(eth->dma_dev, TX_DESC_OFS(eth, ring_size),
&ring->phys, GFP_KERNEL);
}
if (!ring->dma)
goto no_tx_mem;
+ desc_addr = ring->dma;
+ desc_phys = ring->phys;
+ desc_size = TX_DESC_OFS(eth, 1);
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;
- txd->txd2 = next_ptr;
+ txd = desc_addr;
+ desc_addr += desc_size;
+ desc_phys += desc_size;
+ txd->txd2 = desc_phys;
txd->txd3 = TX_DMA_LS0 | TX_DMA_OWNER_CPU;
txd->txd4 = 0;
if (mtk_is_netsys_v2_or_greater(eth)) {
@@ -2562,7 +2578,7 @@ static int mtk_tx_alloc(struct mtk_eth *
* descriptors in ring->dma_pdma.
*/
if (!MTK_HAS_CAPS(soc->caps, MTK_QDMA)) {
- ring->dma_pdma = dma_alloc_coherent(eth->dma_dev, ring_size * sz,
+ ring->dma_pdma = dma_alloc_coherent(eth->dma_dev, TX_DESC_OFS(eth, ring_size),
&ring->phys_pdma, GFP_KERNEL);
if (!ring->dma_pdma)
goto no_tx_mem;
@@ -2577,7 +2593,7 @@ static int mtk_tx_alloc(struct mtk_eth *
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 + ((ring_size - 1) * sz));
+ ring->last_free_ptr = (u32)(ring->phys + TX_DESC_OFS(eth, ring_size - 1));
ring->thresh = MAX_SKB_FRAGS;
/* make sure that all changes to the dma ring are flushed before we
@@ -2589,7 +2605,7 @@ static int mtk_tx_alloc(struct mtk_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 + ((ring_size - 1) * sz),
+ ring->phys + TX_DESC_OFS(eth, ring_size - 1),
soc->reg_map->qdma.crx_ptr);
mtk_w32(eth, ring->last_free_ptr, soc->reg_map->qdma.drx_ptr);
@@ -2638,14 +2654,14 @@ static void mtk_tx_clean(struct mtk_eth
}
if (!MTK_HAS_CAPS(soc->caps, MTK_SRAM) && ring->dma) {
dma_free_coherent(eth->dma_dev,
- ring->dma_size * soc->tx.desc_size,
+ TX_DESC_OFS(eth, ring->dma_size),
ring->dma, ring->phys);
ring->dma = NULL;
}
if (ring->dma_pdma) {
dma_free_coherent(eth->dma_dev,
- ring->dma_size * soc->tx.desc_size,
+ TX_DESC_OFS(eth, ring->dma_size),
ring->dma_pdma, ring->phys_pdma);
ring->dma_pdma = NULL;
}
@@ -2701,15 +2717,13 @@ static int mtk_rx_alloc(struct mtk_eth *
if (!MTK_HAS_CAPS(eth->soc->caps, MTK_SRAM) ||
rx_flag != MTK_RX_FLAGS_NORMAL) {
ring->dma = dma_alloc_coherent(eth->dma_dev,
- rx_dma_size * eth->soc->rx.desc_size,
+ RX_DESC_OFS(eth, rx_dma_size),
&ring->phys, GFP_KERNEL);
} else {
struct mtk_tx_ring *tx_ring = &eth->tx_ring;
- ring->dma = tx_ring->dma + tx_ring_size *
- eth->soc->tx.desc_size * (ring_no + 1);
- ring->phys = tx_ring->phys + tx_ring_size *
- eth->soc->tx.desc_size * (ring_no + 1);
+ ring->dma = tx_ring->dma + TX_DESC_OFS(eth, tx_ring_size * (ring_no + 1));
+ ring->phys = tx_ring->phys + TX_DESC_OFS(eth, tx_ring_size * (ring_no + 1));
}
if (!ring->dma)
@@ -2720,7 +2734,7 @@ static int mtk_rx_alloc(struct mtk_eth *
dma_addr_t dma_addr;
void *data;
- rxd = ring->dma + i * eth->soc->rx.desc_size;
+ rxd = ring->dma + RX_DESC_OFS(eth, i);
if (ring->page_pool) {
data = mtk_page_pool_get_buff(ring->page_pool,
&dma_addr, GFP_KERNEL);
@@ -2811,7 +2825,7 @@ static void mtk_rx_clean(struct mtk_eth
if (!ring->data[i])
continue;
- rxd = ring->dma + i * eth->soc->rx.desc_size;
+ rxd = ring->dma + RX_DESC_OFS(eth, i);
if (!rxd->rxd1)
continue;
@@ -2828,7 +2842,7 @@ static void mtk_rx_clean(struct mtk_eth
if (!in_sram && ring->dma) {
dma_free_coherent(eth->dma_dev,
- ring->dma_size * eth->soc->rx.desc_size,
+ RX_DESC_OFS(eth, ring->dma_size),
ring->dma, ring->phys);
ring->dma = NULL;
}
@@ -3199,7 +3213,7 @@ static void mtk_dma_free(struct mtk_eth
if (!MTK_HAS_CAPS(soc->caps, MTK_SRAM) && eth->scratch_ring) {
dma_free_coherent(eth->dma_dev,
- MTK_QDMA_RING_SIZE * soc->tx.desc_size,
+ TX_DESC_OFS(eth, MTK_QDMA_RING_SIZE),
eth->scratch_ring, eth->phy_scratch_ring);
eth->scratch_ring = NULL;
eth->phy_scratch_ring = 0;
@@ -5220,6 +5234,9 @@ static int mtk_remove(struct platform_de
return 0;
}
+#define DESC_SIZE(struct_name) \
+ .desc_shift = const_ilog2(sizeof(struct_name))
+
static const struct mtk_soc_data mt2701_data = {
.reg_map = &mtk_reg_map,
.caps = MT7623_CAPS | MTK_HWLRO,
@@ -5228,14 +5245,14 @@ static const struct mtk_soc_data mt2701_
.required_pctl = true,
.version = 1,
.tx = {
- .desc_size = sizeof(struct mtk_tx_dma),
+ DESC_SIZE(struct mtk_tx_dma),
.dma_max_len = MTK_TX_DMA_BUF_LEN,
.dma_len_offset = 16,
.dma_size = MTK_DMA_SIZE(2K),
.fq_dma_size = MTK_DMA_SIZE(2K),
},
.rx = {
- .desc_size = sizeof(struct mtk_rx_dma),
+ DESC_SIZE(struct mtk_rx_dma),
.irq_done_mask = MTK_RX_DONE_INT,
.dma_l4_valid = RX_DMA_L4_VALID,
.dma_size = MTK_DMA_SIZE(2K),
@@ -5256,14 +5273,14 @@ static const struct mtk_soc_data mt7621_
.hash_offset = 2,
.foe_entry_size = MTK_FOE_ENTRY_V1_SIZE,
.tx = {
- .desc_size = sizeof(struct mtk_tx_dma),
+ DESC_SIZE(struct mtk_tx_dma),
.dma_max_len = MTK_TX_DMA_BUF_LEN,
.dma_len_offset = 16,
.dma_size = MTK_DMA_SIZE(2K),
.fq_dma_size = MTK_DMA_SIZE(2K),
},
.rx = {
- .desc_size = sizeof(struct mtk_rx_dma),
+ DESC_SIZE(struct mtk_rx_dma),
.irq_done_mask = MTK_RX_DONE_INT,
.dma_l4_valid = RX_DMA_L4_VALID,
.dma_size = MTK_DMA_SIZE(2K),
@@ -5286,14 +5303,14 @@ static const struct mtk_soc_data mt7622_
.has_accounting = true,
.foe_entry_size = MTK_FOE_ENTRY_V1_SIZE,
.tx = {
- .desc_size = sizeof(struct mtk_tx_dma),
+ DESC_SIZE(struct mtk_tx_dma),
.dma_max_len = MTK_TX_DMA_BUF_LEN,
.dma_len_offset = 16,
.dma_size = MTK_DMA_SIZE(2K),
.fq_dma_size = MTK_DMA_SIZE(2K),
},
.rx = {
- .desc_size = sizeof(struct mtk_rx_dma),
+ DESC_SIZE(struct mtk_rx_dma),
.irq_done_mask = MTK_RX_DONE_INT,
.dma_l4_valid = RX_DMA_L4_VALID,
.dma_size = MTK_DMA_SIZE(2K),
@@ -5315,14 +5332,14 @@ static const struct mtk_soc_data mt7623_
.foe_entry_size = MTK_FOE_ENTRY_V1_SIZE,
.disable_pll_modes = true,
.tx = {
- .desc_size = sizeof(struct mtk_tx_dma),
+ DESC_SIZE(struct mtk_tx_dma),
.dma_max_len = MTK_TX_DMA_BUF_LEN,
.dma_len_offset = 16,
.dma_size = MTK_DMA_SIZE(2K),
.fq_dma_size = MTK_DMA_SIZE(2K),
},
.rx = {
- .desc_size = sizeof(struct mtk_rx_dma),
+ DESC_SIZE(struct mtk_rx_dma),
.irq_done_mask = MTK_RX_DONE_INT,
.dma_l4_valid = RX_DMA_L4_VALID,
.dma_size = MTK_DMA_SIZE(2K),
@@ -5341,14 +5358,14 @@ static const struct mtk_soc_data mt7629_
.has_accounting = true,
.version = 1,
.tx = {
- .desc_size = sizeof(struct mtk_tx_dma),
+ DESC_SIZE(struct mtk_tx_dma),
.dma_max_len = MTK_TX_DMA_BUF_LEN,
.dma_len_offset = 16,
.dma_size = MTK_DMA_SIZE(2K),
.fq_dma_size = MTK_DMA_SIZE(2K),
},
.rx = {
- .desc_size = sizeof(struct mtk_rx_dma),
+ DESC_SIZE(struct mtk_rx_dma),
.irq_done_mask = MTK_RX_DONE_INT,
.dma_l4_valid = RX_DMA_L4_VALID,
.dma_size = MTK_DMA_SIZE(2K),
@@ -5371,14 +5388,14 @@ static const struct mtk_soc_data mt7981_
.has_accounting = true,
.foe_entry_size = MTK_FOE_ENTRY_V2_SIZE,
.tx = {
- .desc_size = sizeof(struct mtk_tx_dma_v2),
+ DESC_SIZE(struct mtk_tx_dma_v2),
.dma_max_len = MTK_TX_DMA_BUF_LEN_V2,
.dma_len_offset = 8,
.dma_size = MTK_DMA_SIZE(2K),
.fq_dma_size = MTK_DMA_SIZE(2K),
},
.rx = {
- .desc_size = sizeof(struct mtk_rx_dma),
+ DESC_SIZE(struct mtk_rx_dma),
.irq_done_mask = MTK_RX_DONE_INT,
.dma_l4_valid = RX_DMA_L4_VALID_V2,
.dma_max_len = MTK_TX_DMA_BUF_LEN,
@@ -5401,14 +5418,14 @@ static const struct mtk_soc_data mt7986_
.has_accounting = true,
.foe_entry_size = MTK_FOE_ENTRY_V2_SIZE,
.tx = {
- .desc_size = sizeof(struct mtk_tx_dma_v2),
+ DESC_SIZE(struct mtk_tx_dma_v2),
.dma_max_len = MTK_TX_DMA_BUF_LEN_V2,
.dma_len_offset = 8,
.dma_size = MTK_DMA_SIZE(2K),
.fq_dma_size = MTK_DMA_SIZE(2K),
},
.rx = {
- .desc_size = sizeof(struct mtk_rx_dma),
+ DESC_SIZE(struct mtk_rx_dma),
.irq_done_mask = MTK_RX_DONE_INT,
.dma_l4_valid = RX_DMA_L4_VALID_V2,
.dma_max_len = MTK_TX_DMA_BUF_LEN,
@@ -5431,14 +5448,14 @@ static const struct mtk_soc_data mt7988_
.has_accounting = true,
.foe_entry_size = MTK_FOE_ENTRY_V3_SIZE,
.tx = {
- .desc_size = sizeof(struct mtk_tx_dma_v2),
+ DESC_SIZE(struct mtk_tx_dma_v2),
.dma_max_len = MTK_TX_DMA_BUF_LEN_V2,
.dma_len_offset = 8,
.dma_size = MTK_DMA_SIZE(2K),
.fq_dma_size = MTK_DMA_SIZE(4K),
},
.rx = {
- .desc_size = sizeof(struct mtk_rx_dma_v2),
+ DESC_SIZE(struct mtk_rx_dma_v2),
.irq_done_mask = MTK_RX_DONE_INT_V2,
.dma_l4_valid = RX_DMA_L4_VALID_V2,
.dma_max_len = MTK_TX_DMA_BUF_LEN_V2,
@@ -5455,13 +5472,13 @@ static const struct mtk_soc_data rt5350_
.required_pctl = false,
.version = 1,
.tx = {
- .desc_size = sizeof(struct mtk_tx_dma),
+ DESC_SIZE(struct mtk_tx_dma),
.dma_max_len = MTK_TX_DMA_BUF_LEN,
.dma_len_offset = 16,
.dma_size = MTK_DMA_SIZE(2K),
},
.rx = {
- .desc_size = sizeof(struct mtk_rx_dma),
+ DESC_SIZE(struct mtk_rx_dma),
.irq_done_mask = MTK_RX_DONE_INT,
.dma_l4_valid = RX_DMA_L4_VALID_PDMA,
.dma_max_len = MTK_TX_DMA_BUF_LEN,
--- a/drivers/net/ethernet/mediatek/mtk_eth_soc.h
+++ b/drivers/net/ethernet/mediatek/mtk_eth_soc.h
@@ -1174,7 +1174,7 @@ struct mtk_reg_map {
* @foe_entry_size Foe table entry size.
* @has_accounting Bool indicating support for accounting of
* offloaded flows.
- * @desc_size Tx/Rx DMA descriptor size.
+ * @desc_shift Tx/Rx DMA descriptor size (in power-of-2).
* @irq_done_mask Rx irq done register mask.
* @dma_l4_valid Rx DMA valid register mask.
* @dma_max_len Max DMA tx/rx buffer length.
@@ -1195,14 +1195,14 @@ struct mtk_soc_data {
bool has_accounting;
bool disable_pll_modes;
struct {
- u32 desc_size;
+ u32 desc_shift;
u32 dma_max_len;
u32 dma_len_offset;
u32 dma_size;
u32 fq_dma_size;
} tx;
struct {
- u32 desc_size;
+ u32 desc_shift;
u32 irq_done_mask;
u32 dma_l4_valid;
u32 dma_max_len;

View file

@ -1,124 +0,0 @@
From: Felix Fietkau <nbd@nbd.name>
Date: Mon, 14 Jul 2025 10:52:59 +0200
Subject: [PATCH] net: ethernet: mtk_eth_soc: shrink struct mtk_tx_buf
There is no need to track the difference between dma_map_page
and dma_map_single, since they're unmapped in exactly the same way.
Also reorder fields in order to avoid padding.
Signed-off-by: Felix Fietkau <nbd@nbd.name>
---
--- a/drivers/net/ethernet/mediatek/mtk_eth_soc.c
+++ b/drivers/net/ethernet/mediatek/mtk_eth_soc.c
@@ -1251,32 +1251,19 @@ static int txd_to_idx(struct mtk_tx_ring
static void mtk_tx_unmap(struct mtk_eth *eth, struct mtk_tx_buf *tx_buf,
struct xdp_frame_bulk *bq, bool napi)
{
- if (MTK_HAS_CAPS(eth->soc->caps, MTK_QDMA)) {
- if (tx_buf->flags & MTK_TX_FLAGS_SINGLE0) {
- dma_unmap_single(eth->dma_dev,
- dma_unmap_addr(tx_buf, dma_addr0),
- dma_unmap_len(tx_buf, dma_len0),
- DMA_TO_DEVICE);
- } else if (tx_buf->flags & MTK_TX_FLAGS_PAGE0) {
- dma_unmap_page(eth->dma_dev,
- dma_unmap_addr(tx_buf, dma_addr0),
- dma_unmap_len(tx_buf, dma_len0),
- DMA_TO_DEVICE);
- }
- } else {
- if (dma_unmap_len(tx_buf, dma_len0)) {
- dma_unmap_page(eth->dma_dev,
- dma_unmap_addr(tx_buf, dma_addr0),
- dma_unmap_len(tx_buf, dma_len0),
- DMA_TO_DEVICE);
- }
+ if (dma_unmap_len(tx_buf, dma_len0)) {
+ dma_unmap_page(eth->dma_dev,
+ dma_unmap_addr(tx_buf, dma_addr0),
+ dma_unmap_len(tx_buf, dma_len0),
+ DMA_TO_DEVICE);
+ }
- if (dma_unmap_len(tx_buf, dma_len1)) {
- dma_unmap_page(eth->dma_dev,
- dma_unmap_addr(tx_buf, dma_addr1),
- dma_unmap_len(tx_buf, dma_len1),
- DMA_TO_DEVICE);
- }
+ if (!MTK_HAS_CAPS(eth->soc->caps, MTK_QDMA) &&
+ dma_unmap_len(tx_buf, dma_len1)) {
+ dma_unmap_page(eth->dma_dev,
+ dma_unmap_addr(tx_buf, dma_addr1),
+ dma_unmap_len(tx_buf, dma_len1),
+ DMA_TO_DEVICE);
}
if (tx_buf->data && tx_buf->data != (void *)MTK_DMA_DUMMY_DESC) {
@@ -1298,7 +1285,6 @@ static void mtk_tx_unmap(struct mtk_eth
xdp_return_frame(xdpf);
}
}
- tx_buf->flags = 0;
tx_buf->data = NULL;
}
@@ -1463,7 +1449,6 @@ static int mtk_tx_map(struct sk_buff *sk
mtk_tx_set_dma_desc(dev, itxd, &txd_info);
- itx_buf->flags |= MTK_TX_FLAGS_SINGLE0;
itx_buf->mac_id = mac->id;
setup_tx_buf(eth, itx_buf, itxd_pdma, txd_info.addr, txd_info.size,
k++);
@@ -1511,7 +1496,6 @@ static int mtk_tx_map(struct sk_buff *sk
if (new_desc)
memset(tx_buf, 0, sizeof(*tx_buf));
tx_buf->data = (void *)MTK_DMA_DUMMY_DESC;
- tx_buf->flags |= MTK_TX_FLAGS_PAGE0;
tx_buf->mac_id = mac->id;
setup_tx_buf(eth, tx_buf, txd_pdma, txd_info.addr,
@@ -1836,8 +1820,6 @@ static int mtk_xdp_frame_map(struct mtk_
txd_info->size, DMA_TO_DEVICE);
if (unlikely(dma_mapping_error(eth->dma_dev, txd_info->addr)))
return -ENOMEM;
-
- tx_buf->flags |= MTK_TX_FLAGS_SINGLE0;
} else {
struct page *page = virt_to_head_page(data);
--- a/drivers/net/ethernet/mediatek/mtk_eth_soc.h
+++ b/drivers/net/ethernet/mediatek/mtk_eth_soc.h
@@ -701,14 +701,6 @@ struct mtk_hw_stats {
struct u64_stats_sync syncp;
};
-enum mtk_tx_flags {
- /* PDMA descriptor can point at 1-2 segments. This enum allows us to
- * track how memory was allocated so that it can be freed properly.
- */
- MTK_TX_FLAGS_SINGLE0 = 0x01,
- MTK_TX_FLAGS_PAGE0 = 0x02,
-};
-
/* This enum allows us to identify how the clock is defined on the array of the
* clock in the order
*/
@@ -895,13 +887,12 @@ enum mtk_tx_buf_type {
*/
struct mtk_tx_buf {
enum mtk_tx_buf_type type;
+ u16 mac_id;
void *data;
- u16 mac_id;
- u16 flags;
DEFINE_DMA_UNMAP_ADDR(dma_addr0);
- DEFINE_DMA_UNMAP_LEN(dma_len0);
DEFINE_DMA_UNMAP_ADDR(dma_addr1);
+ DEFINE_DMA_UNMAP_LEN(dma_len0);
DEFINE_DMA_UNMAP_LEN(dma_len1);
};

View file

@ -1,303 +0,0 @@
From: Felix Fietkau <nbd@nbd.name>
Date: Mon, 14 Jul 2025 10:41:27 +0200
Subject: [PATCH] net: ethernet: mtk_eth_soc: add support for sending
fraglist GSO packets
When primarily forwarding traffic, TCP fraglist GRO can be noticeably more
efficient than regular TCP GRO. In order to avoid the overhead of
unnecessary segmentation on ethernet tx, add support for sending fraglist
GRO packets.
Signed-off-by: Felix Fietkau <nbd@nbd.name>
---
--- a/drivers/net/ethernet/mediatek/mtk_eth_soc.c
+++ b/drivers/net/ethernet/mediatek/mtk_eth_soc.c
@@ -1409,29 +1409,70 @@ static void mtk_tx_set_dma_desc(struct n
mtk_tx_set_dma_desc_v1(dev, txd, info);
}
+struct mtk_tx_map_state {
+ struct mtk_tx_dma *txd, *txd_pdma;
+ struct mtk_tx_buf *tx_buf;
+ int nbuf;
+ int ndesc;
+};
+
+static int
+mtk_tx_map_info(struct mtk_eth *eth, struct mtk_tx_ring *ring,
+ struct net_device *dev, struct mtk_tx_map_state *state,
+ struct mtk_tx_dma_desc_info *txd_info)
+{
+ const struct mtk_soc_data *soc = eth->soc;
+ struct mtk_tx_dma *txd_pdma = state->txd_pdma;
+ struct mtk_tx_buf *tx_buf = state->tx_buf;
+ struct mtk_tx_dma *txd = state->txd;
+ struct mtk_mac *mac = netdev_priv(dev);
+
+ if (state->nbuf &&
+ (MTK_HAS_CAPS(soc->caps, MTK_QDMA) || (state->nbuf & 1) == 0)) {
+ txd = state->txd = mtk_qdma_phys_to_virt(ring, txd->txd2);
+ txd_pdma = state->txd_pdma = qdma_to_pdma(ring, txd);
+ if (state->txd == ring->last_free)
+ return -1;
+
+ tx_buf = mtk_desc_to_tx_buf(ring, state->txd,
+ soc->tx.desc_shift);
+ state->tx_buf = tx_buf;
+ memset(tx_buf, 0, sizeof(*tx_buf));
+ state->ndesc++;
+ }
+
+ mtk_tx_set_dma_desc(dev, txd, txd_info);
+ tx_buf->data = (void *)MTK_DMA_DUMMY_DESC;
+ tx_buf->mac_id = mac->id;
+
+ setup_tx_buf(eth, tx_buf, txd_pdma, txd_info->addr,
+ txd_info->size, state->nbuf++);
+ return 0;
+}
+
static int mtk_tx_map(struct sk_buff *skb, struct net_device *dev,
int tx_num, struct mtk_tx_ring *ring, bool gso)
{
struct mtk_tx_dma_desc_info txd_info = {
- .size = skb_headlen(skb),
.gso = gso,
- .csum = skb->ip_summed == CHECKSUM_PARTIAL,
+ .csum = skb->ip_summed == CHECKSUM_PARTIAL || gso,
.vlan = skb_vlan_tag_present(skb),
- .qid = skb_get_queue_mapping(skb),
.vlan_tci = skb_vlan_tag_get(skb),
.first = true,
- .last = !skb_is_nonlinear(skb),
+ };
+ struct mtk_tx_map_state state = {
+ .ndesc = 1,
};
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;
- struct mtk_tx_dma *itxd, *txd;
- struct mtk_tx_dma *itxd_pdma, *txd_pdma;
- struct mtk_tx_buf *itx_buf, *tx_buf;
- int i, n_desc = 1;
+ struct mtk_tx_dma *itxd, *itxd_pdma;
+ struct mtk_tx_buf *itx_buf;
+ struct sk_buff *cur_skb, *next_skb;
int queue = skb_get_queue_mapping(skb);
- int k = 0;
+ unsigned int offset = 0;
+ int i, frag_size;
txq = netdev_get_tx_queue(dev, queue);
itxd = ring->next_free;
@@ -1442,86 +1483,81 @@ static int mtk_tx_map(struct sk_buff *sk
itx_buf = mtk_desc_to_tx_buf(ring, itxd, soc->tx.desc_shift);
memset(itx_buf, 0, sizeof(*itx_buf));
- txd_info.addr = dma_map_single(eth->dma_dev, skb->data, txd_info.size,
- DMA_TO_DEVICE);
- if (unlikely(dma_mapping_error(eth->dma_dev, txd_info.addr)))
- return -ENOMEM;
-
- mtk_tx_set_dma_desc(dev, itxd, &txd_info);
-
- itx_buf->mac_id = mac->id;
- setup_tx_buf(eth, itx_buf, itxd_pdma, txd_info.addr, txd_info.size,
- k++);
-
- /* TX SG offload */
- txd = itxd;
- txd_pdma = qdma_to_pdma(ring, txd);
-
- for (i = 0; i < skb_shinfo(skb)->nr_frags; i++) {
- skb_frag_t *frag = &skb_shinfo(skb)->frags[i];
- unsigned int offset = 0;
- int frag_size = skb_frag_size(frag);
-
+ cur_skb = skb;
+ next_skb = skb_shinfo(skb)->frag_list;
+ state.txd = itxd;
+ state.txd_pdma = itxd_pdma;
+ state.tx_buf = itx_buf;
+
+next:
+ txd_info.qid = queue;
+ frag_size = skb_headlen(cur_skb);
+
+ while (frag_size) {
+ txd_info.size = min_t(unsigned int, frag_size,
+ soc->tx.dma_max_len);
+ txd_info.addr = dma_map_single(eth->dma_dev, cur_skb->data + offset,
+ txd_info.size, DMA_TO_DEVICE);
+ if (unlikely(dma_mapping_error(eth->dma_dev, txd_info.addr)))
+ goto err_dma;
+
+ frag_size -= txd_info.size;
+ offset += txd_info.size;
+ txd_info.last = !skb_is_nonlinear(cur_skb) && !next_skb &&
+ !frag_size;
+ if (mtk_tx_map_info(eth, ring, dev, &state, &txd_info) < 0)
+ goto err_dma;
+
+ txd_info.first = false;
+ }
+
+ for (i = 0; i < skb_shinfo(cur_skb)->nr_frags; i++) {
+ skb_frag_t *frag = &skb_shinfo(cur_skb)->frags[i];
+
+ frag_size = skb_frag_size(frag);
+ memset(&txd_info, 0, sizeof(struct mtk_tx_dma_desc_info));
+ txd_info.qid = queue;
+ offset = 0;
while (frag_size) {
- bool new_desc = true;
-
- if (MTK_HAS_CAPS(soc->caps, MTK_QDMA) ||
- (i & 0x1)) {
- txd = mtk_qdma_phys_to_virt(ring, txd->txd2);
- txd_pdma = qdma_to_pdma(ring, txd);
- if (txd == ring->last_free)
- goto err_dma;
-
- n_desc++;
- } else {
- new_desc = false;
- }
-
- memset(&txd_info, 0, sizeof(struct mtk_tx_dma_desc_info));
txd_info.size = min_t(unsigned int, frag_size,
soc->tx.dma_max_len);
- 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,
- offset, txd_info.size,
- DMA_TO_DEVICE);
+ txd_info.addr = skb_frag_dma_map(eth->dma_dev, frag, offset,
+ txd_info.size, DMA_TO_DEVICE);
if (unlikely(dma_mapping_error(eth->dma_dev, txd_info.addr)))
goto err_dma;
- mtk_tx_set_dma_desc(dev, txd, &txd_info);
-
- tx_buf = mtk_desc_to_tx_buf(ring, txd,
- soc->tx.desc_shift);
- if (new_desc)
- memset(tx_buf, 0, sizeof(*tx_buf));
- tx_buf->data = (void *)MTK_DMA_DUMMY_DESC;
- tx_buf->mac_id = mac->id;
-
- setup_tx_buf(eth, tx_buf, txd_pdma, txd_info.addr,
- txd_info.size, k++);
-
frag_size -= txd_info.size;
offset += txd_info.size;
+ txd_info.last = i == skb_shinfo(cur_skb)->nr_frags - 1 &&
+ !frag_size && !next_skb;
+ if (mtk_tx_map_info(eth, ring, dev, &state, &txd_info) < 0)
+ goto err_dma;
}
}
+ if (next_skb) {
+ cur_skb = next_skb;
+ next_skb = cur_skb->next;
+ memset(&txd_info, 0, sizeof(txd_info));
+ goto next;
+ }
+
/* store skb to cleanup */
itx_buf->type = MTK_TYPE_SKB;
itx_buf->data = skb;
if (!MTK_HAS_CAPS(soc->caps, MTK_QDMA)) {
- if (k & 0x1)
- txd_pdma->txd2 |= TX_DMA_LS0;
+ if (state.nbuf & 0x1)
+ state.txd_pdma->txd2 |= TX_DMA_LS0;
else
- txd_pdma->txd2 |= TX_DMA_LS1;
+ state.txd_pdma->txd2 |= TX_DMA_LS1;
}
netdev_tx_sent_queue(txq, skb->len);
skb_tx_timestamp(skb);
- ring->next_free = mtk_qdma_phys_to_virt(ring, txd->txd2);
- atomic_sub(n_desc, &ring->free_count);
+ ring->next_free = mtk_qdma_phys_to_virt(ring, state.txd->txd2);
+ atomic_sub(state.ndesc, &ring->free_count);
/* make sure that all changes to the dma ring are flushed before we
* continue
@@ -1530,11 +1566,11 @@ static int mtk_tx_map(struct sk_buff *sk
if (MTK_HAS_CAPS(soc->caps, MTK_QDMA)) {
if (netif_xmit_stopped(txq) || !netdev_xmit_more())
- mtk_w32(eth, txd->txd2, soc->reg_map->qdma.ctx_ptr);
+ mtk_w32(eth, state.txd->txd2, soc->reg_map->qdma.ctx_ptr);
} else {
int next_idx;
- next_idx = NEXT_DESP_IDX(txd_to_idx(ring, txd, soc->tx.desc_shift),
+ next_idx = NEXT_DESP_IDX(txd_to_idx(ring, state.txd, soc->tx.desc_shift),
ring->dma_size);
mtk_w32(eth, next_idx, MT7628_TX_CTX_IDX0);
}
@@ -1543,10 +1579,10 @@ static int mtk_tx_map(struct sk_buff *sk
err_dma:
do {
- tx_buf = mtk_desc_to_tx_buf(ring, itxd, soc->tx.desc_shift);
+ itx_buf = mtk_desc_to_tx_buf(ring, itxd, soc->tx.desc_shift);
/* unmap dma */
- mtk_tx_unmap(eth, tx_buf, NULL, false);
+ mtk_tx_unmap(eth, itx_buf, NULL, false);
itxd->txd3 = TX_DMA_LS0 | TX_DMA_OWNER_CPU;
if (!MTK_HAS_CAPS(soc->caps, MTK_QDMA))
@@ -1554,7 +1590,7 @@ err_dma:
itxd = mtk_qdma_phys_to_virt(ring, itxd->txd2);
itxd_pdma = qdma_to_pdma(ring, itxd);
- } while (itxd != txd);
+ } while (itxd != state.txd);
return -ENOMEM;
}
@@ -1574,6 +1610,9 @@ static int mtk_cal_txd_req(struct mtk_et
nfrags += skb_shinfo(skb)->nr_frags;
}
+ for (skb = skb_shinfo(skb)->frag_list; skb; skb = skb->next)
+ nfrags += mtk_cal_txd_req(eth, skb);
+
return nfrags;
}
@@ -1614,6 +1653,10 @@ static bool mtk_skb_has_small_frag(struc
if (skb_frag_size(&skb_shinfo(skb)->frags[i]) < min_size)
return true;
+ for (skb = skb_shinfo(skb)->frag_list; skb; skb = skb->next)
+ if (mtk_skb_has_small_frag(skb))
+ return true;
+
return false;
}
--- a/drivers/net/ethernet/mediatek/mtk_eth_soc.h
+++ b/drivers/net/ethernet/mediatek/mtk_eth_soc.h
@@ -51,6 +51,8 @@
NETIF_F_HW_VLAN_CTAG_TX | \
NETIF_F_SG | NETIF_F_TSO | \
NETIF_F_TSO6 | \
+ NETIF_F_FRAGLIST | \
+ NETIF_F_GSO_FRAGLIST | \
NETIF_F_IPV6_CSUM |\
NETIF_F_HW_TC)
#define MTK_HW_FEATURES_MT7628 (NETIF_F_SG | NETIF_F_RXCSUM)

View file

@ -10,7 +10,7 @@ Signed-off-by: Felix Fietkau <nbd@nbd.name>
--- a/drivers/net/ethernet/mediatek/mtk_eth_soc.c
+++ b/drivers/net/ethernet/mediatek/mtk_eth_soc.c
@@ -2186,7 +2186,7 @@ static int mtk_poll_rx(struct napi_struc
@@ -2150,7 +2150,7 @@ static int mtk_poll_rx(struct napi_struc
if (ret != XDP_PASS)
goto skip_rx;
@ -19,7 +19,7 @@ Signed-off-by: Felix Fietkau <nbd@nbd.name>
if (unlikely(!skb)) {
page_pool_put_full_page(ring->page_pool,
page, true);
@@ -2224,7 +2224,7 @@ static int mtk_poll_rx(struct napi_struc
@@ -2188,7 +2188,7 @@ static int mtk_poll_rx(struct napi_struc
dma_unmap_single(eth->dma_dev, ((u64)trxd.rxd1 | addr64),
ring->buf_size, DMA_FROM_DEVICE);

View file

@ -15,7 +15,7 @@ Signed-off-by: Chad Monroe <chad@monroe.io>
--- a/drivers/net/ethernet/mediatek/mtk_eth_soc.h
+++ b/drivers/net/ethernet/mediatek/mtk_eth_soc.h
@@ -282,6 +282,7 @@
@@ -279,6 +279,7 @@
#define MTK_WCOMP_EN BIT(24)
#define MTK_RESV_BUF (0x80 << 16)
#define MTK_MUTLI_CNT (0x4 << 12)
@ -25,7 +25,7 @@ Signed-off-by: Chad Monroe <chad@monroe.io>
/* QDMA Flow Control Register */
--- a/drivers/net/ethernet/mediatek/mtk_eth_soc.c
+++ b/drivers/net/ethernet/mediatek/mtk_eth_soc.c
@@ -3362,12 +3362,14 @@ static int mtk_start_dma(struct mtk_eth
@@ -3323,12 +3323,14 @@ static int mtk_start_dma(struct mtk_eth
MTK_TX_BT_32DWORDS | MTK_NDP_CO_PRO |
MTK_RX_2B_OFFSET | MTK_TX_WB_DDONE;

View file

@ -214,7 +214,7 @@ Signed-off-by: Daniel Golle <daniel@makrotopia.org>
#include <linux/jhash.h>
#include <linux/bitfield.h>
#include <net/dsa.h>
@@ -275,12 +277,8 @@ static const char * const mtk_clks_sourc
@@ -270,12 +272,8 @@ static const char * const mtk_clks_sourc
"ethwarp_wocpu2",
"ethwarp_wocpu1",
"ethwarp_wocpu0",
@ -227,7 +227,7 @@ Signed-off-by: Daniel Golle <daniel@makrotopia.org>
"top_eth_gmii_sel",
"top_eth_refck_50m_sel",
"top_eth_sys_200m_sel",
@@ -523,6 +521,30 @@ static void mtk_setup_bridge_switch(stru
@@ -518,6 +516,30 @@ static void mtk_setup_bridge_switch(stru
MTK_GSW_CFG);
}
@ -258,7 +258,7 @@ Signed-off-by: Daniel Golle <daniel@makrotopia.org>
static struct phylink_pcs *mtk_mac_select_pcs(struct phylink_config *config,
phy_interface_t interface)
{
@@ -531,6 +553,21 @@ static struct phylink_pcs *mtk_mac_selec
@@ -526,6 +548,21 @@ static struct phylink_pcs *mtk_mac_selec
struct mtk_eth *eth = mac->hw;
unsigned int sid;
@ -280,7 +280,7 @@ Signed-off-by: Daniel Golle <daniel@makrotopia.org>
if (interface == PHY_INTERFACE_MODE_SGMII ||
phy_interface_mode_is_8023z(interface)) {
sid = (MTK_HAS_CAPS(eth->soc->caps, MTK_SHARED_SGMII)) ?
@@ -582,7 +619,22 @@ static void mtk_mac_config(struct phylin
@@ -577,7 +614,22 @@ static void mtk_mac_config(struct phylin
goto init_err;
}
break;
@ -303,7 +303,7 @@ Signed-off-by: Daniel Golle <daniel@makrotopia.org>
break;
default:
goto err_phy;
@@ -629,8 +681,6 @@ static void mtk_mac_config(struct phylin
@@ -624,8 +676,6 @@ static void mtk_mac_config(struct phylin
val &= ~SYSCFG0_GE_MODE(SYSCFG0_GE_MASK, mac->id);
val |= SYSCFG0_GE_MODE(ge_mode, mac->id);
regmap_write(eth->ethsys, ETHSYS_SYSCFG0, val);
@ -312,7 +312,7 @@ Signed-off-by: Daniel Golle <daniel@makrotopia.org>
}
/* SGMII */
@@ -647,21 +697,40 @@ static void mtk_mac_config(struct phylin
@@ -642,21 +692,40 @@ static void mtk_mac_config(struct phylin
/* Save the syscfg0 value for mac_finish */
mac->syscfg0 = val;
@ -360,7 +360,7 @@ Signed-off-by: Daniel Golle <daniel@makrotopia.org>
return;
err_phy:
@@ -674,6 +743,18 @@ init_err:
@@ -669,6 +738,18 @@ init_err:
mac->id, phy_modes(state->interface), err);
}
@ -379,7 +379,7 @@ Signed-off-by: Daniel Golle <daniel@makrotopia.org>
static int mtk_mac_finish(struct phylink_config *config, unsigned int mode,
phy_interface_t interface)
{
@@ -682,6 +763,10 @@ static int mtk_mac_finish(struct phylink
@@ -677,6 +758,10 @@ static int mtk_mac_finish(struct phylink
struct mtk_eth *eth = mac->hw;
u32 mcr_cur, mcr_new;
@ -390,7 +390,7 @@ Signed-off-by: Daniel Golle <daniel@makrotopia.org>
/* Enable SGMII */
if (interface == PHY_INTERFACE_MODE_SGMII ||
phy_interface_mode_is_8023z(interface))
@@ -706,10 +791,14 @@ static void mtk_mac_link_down(struct phy
@@ -701,10 +786,14 @@ static void mtk_mac_link_down(struct phy
{
struct mtk_mac *mac = container_of(config, struct mtk_mac,
phylink_config);
@ -408,7 +408,7 @@ Signed-off-by: Daniel Golle <daniel@makrotopia.org>
}
static void mtk_set_queue_speed(struct mtk_eth *eth, unsigned int idx,
@@ -781,13 +870,11 @@ static void mtk_set_queue_speed(struct m
@@ -776,13 +865,11 @@ static void mtk_set_queue_speed(struct m
mtk_w32(eth, val, soc->reg_map->qdma.qtx_sch + ofs);
}
@ -426,7 +426,7 @@ Signed-off-by: Daniel Golle <daniel@makrotopia.org>
u32 mcr;
mcr = mtk_r32(mac->hw, MTK_MAC_MCR(mac->id));
@@ -831,9 +918,63 @@ static void mtk_mac_link_up(struct phyli
@@ -826,9 +913,63 @@ static void mtk_mac_link_up(struct phyli
mtk_w32(mac->hw, mcr, MTK_MAC_MCR(mac->id));
}
@ -490,7 +490,7 @@ Signed-off-by: Daniel Golle <daniel@makrotopia.org>
.mac_finish = mtk_mac_finish,
.mac_link_down = mtk_mac_link_down,
.mac_link_up = mtk_mac_link_up,
@@ -3470,6 +3611,9 @@ static int mtk_open(struct net_device *d
@@ -3431,6 +3572,9 @@ static int mtk_open(struct net_device *d
ppe_num = eth->soc->ppe_num;
@ -500,7 +500,7 @@ Signed-off-by: Daniel Golle <daniel@makrotopia.org>
err = phylink_of_phy_connect(mac->phylink, mac->of_node, 0);
if (err) {
netdev_err(dev, "%s: could not attach PHY: %d\n", __func__,
@@ -3620,6 +3764,9 @@ static int mtk_stop(struct net_device *d
@@ -3581,6 +3725,9 @@ static int mtk_stop(struct net_device *d
for (i = 0; i < ARRAY_SIZE(eth->ppe); i++)
mtk_ppe_stop(eth->ppe[i]);
@ -510,7 +510,7 @@ Signed-off-by: Daniel Golle <daniel@makrotopia.org>
return 0;
}
@@ -4706,6 +4853,7 @@ static const struct net_device_ops mtk_n
@@ -4667,6 +4814,7 @@ static const struct net_device_ops mtk_n
static int mtk_add_mac(struct mtk_eth *eth, struct device_node *np)
{
const __be32 *_id = of_get_property(np, "reg", NULL);
@ -518,7 +518,7 @@ Signed-off-by: Daniel Golle <daniel@makrotopia.org>
phy_interface_t phy_mode;
struct phylink *phylink;
struct mtk_mac *mac;
@@ -4744,16 +4892,41 @@ static int mtk_add_mac(struct mtk_eth *e
@@ -4705,16 +4853,41 @@ static int mtk_add_mac(struct mtk_eth *e
mac->id = id;
mac->hw = eth;
mac->of_node = np;
@ -568,7 +568,7 @@ Signed-off-by: Daniel Golle <daniel@makrotopia.org>
}
memset(mac->hwlro_ip, 0, sizeof(mac->hwlro_ip));
@@ -4836,8 +5009,21 @@ static int mtk_add_mac(struct mtk_eth *e
@@ -4797,8 +4970,21 @@ static int mtk_add_mac(struct mtk_eth *e
phy_interface_zero(mac->phylink_config.supported_interfaces);
__set_bit(PHY_INTERFACE_MODE_INTERNAL,
mac->phylink_config.supported_interfaces);
@ -590,7 +590,7 @@ Signed-off-by: Daniel Golle <daniel@makrotopia.org>
phylink = phylink_create(&mac->phylink_config,
of_fwnode_handle(mac->of_node),
phy_mode, &mtk_phylink_ops);
@@ -4888,6 +5074,26 @@ free_netdev:
@@ -4849,6 +5035,26 @@ free_netdev:
return err;
}
@ -617,7 +617,7 @@ Signed-off-by: Daniel Golle <daniel@makrotopia.org>
void mtk_eth_set_dma_device(struct mtk_eth *eth, struct device *dma_dev)
{
struct net_device *dev, *tmp;
@@ -5034,7 +5240,8 @@ static int mtk_probe(struct platform_dev
@@ -4995,7 +5201,8 @@ static int mtk_probe(struct platform_dev
regmap_write(cci, 0, 3);
}
@ -627,7 +627,7 @@ Signed-off-by: Daniel Golle <daniel@makrotopia.org>
err = mtk_sgmii_init(eth);
if (err)
@@ -5145,6 +5352,24 @@ static int mtk_probe(struct platform_dev
@@ -5106,6 +5313,24 @@ static int mtk_probe(struct platform_dev
}
}
@ -652,7 +652,7 @@ Signed-off-by: Daniel Golle <daniel@makrotopia.org>
if (MTK_HAS_CAPS(eth->soc->caps, MTK_SHARED_INT)) {
err = devm_request_irq(eth->dev, eth->irq[0],
mtk_handle_irq, 0,
@@ -5248,6 +5473,11 @@ static int mtk_remove(struct platform_de
@@ -5209,6 +5434,11 @@ static int mtk_remove(struct platform_de
mtk_stop(eth->netdev[i]);
mac = netdev_priv(eth->netdev[i]);
phylink_disconnect_phy(mac->phylink);
@ -674,7 +674,7 @@ Signed-off-by: Daniel Golle <daniel@makrotopia.org>
#include <linux/rhashtable.h>
#include <linux/dim.h>
#include <linux/bitfield.h>
@@ -527,6 +528,21 @@
@@ -524,6 +525,21 @@
#define INTF_MODE_RGMII_1000 (TRGMII_MODE | TRGMII_CENTRAL_ALIGNED)
#define INTF_MODE_RGMII_10_100 0
@ -696,7 +696,7 @@ Signed-off-by: Daniel Golle <daniel@makrotopia.org>
/* GPIO port control registers for GMAC 2*/
#define GPIO_OD33_CTRL8 0x4c0
#define GPIO_BIAS_CTRL 0xed0
@@ -552,6 +568,7 @@
@@ -549,6 +565,7 @@
#define SYSCFG0_SGMII_GMAC2 ((3 << 8) & SYSCFG0_SGMII_MASK)
#define SYSCFG0_SGMII_GMAC1_V2 BIT(9)
#define SYSCFG0_SGMII_GMAC2_V2 BIT(8)
@ -704,7 +704,7 @@ Signed-off-by: Daniel Golle <daniel@makrotopia.org>
/* ethernet subsystem clock register */
@@ -590,6 +607,11 @@
@@ -587,6 +604,11 @@
#define GEPHY_MAC_SEL BIT(1)
/* Top misc registers */
@ -716,7 +716,7 @@ Signed-off-by: Daniel Golle <daniel@makrotopia.org>
#define USB_PHY_SWITCH_REG 0x218
#define QPHY_SEL_MASK GENMASK(1, 0)
#define SGMII_QPHY_SEL 0x2
@@ -614,6 +636,8 @@
@@ -611,6 +633,8 @@
#define MT7628_SDM_RBCNT (MT7628_SDM_OFFSET + 0x10c)
#define MT7628_SDM_CS_ERR (MT7628_SDM_OFFSET + 0x110)
@ -725,7 +725,7 @@ Signed-off-by: Daniel Golle <daniel@makrotopia.org>
#define MTK_FE_CDM1_FSM 0x220
#define MTK_FE_CDM2_FSM 0x224
#define MTK_FE_CDM3_FSM 0x238
@@ -622,6 +646,11 @@
@@ -619,6 +643,11 @@
#define MTK_FE_CDM6_FSM 0x328
#define MTK_FE_GDM1_FSM 0x228
#define MTK_FE_GDM2_FSM 0x22C
@ -737,7 +737,7 @@ Signed-off-by: Daniel Golle <daniel@makrotopia.org>
#define MTK_MAC_FSM(x) (0x1010C + ((x) * 0x100))
@@ -738,12 +767,8 @@ enum mtk_clks_map {
@@ -743,12 +772,8 @@ enum mtk_clks_map {
MTK_CLK_ETHWARP_WOCPU2,
MTK_CLK_ETHWARP_WOCPU1,
MTK_CLK_ETHWARP_WOCPU0,
@ -750,7 +750,7 @@ Signed-off-by: Daniel Golle <daniel@makrotopia.org>
MTK_CLK_TOP_ETH_GMII_SEL,
MTK_CLK_TOP_ETH_REFCK_50M_SEL,
MTK_CLK_TOP_ETH_SYS_200M_SEL,
@@ -814,19 +839,9 @@ enum mtk_clks_map {
@@ -819,19 +844,9 @@ enum mtk_clks_map {
BIT_ULL(MTK_CLK_GP3) | BIT_ULL(MTK_CLK_XGP1) | \
BIT_ULL(MTK_CLK_XGP2) | BIT_ULL(MTK_CLK_XGP3) | \
BIT_ULL(MTK_CLK_CRYPTO) | \
@ -770,7 +770,7 @@ Signed-off-by: Daniel Golle <daniel@makrotopia.org>
BIT_ULL(MTK_CLK_TOP_ETH_GMII_SEL) | \
BIT_ULL(MTK_CLK_TOP_ETH_REFCK_50M_SEL) | \
BIT_ULL(MTK_CLK_TOP_ETH_SYS_200M_SEL) | \
@@ -959,6 +974,8 @@ enum mkt_eth_capabilities {
@@ -965,6 +980,8 @@ enum mkt_eth_capabilities {
MTK_RGMII_BIT = 0,
MTK_TRGMII_BIT,
MTK_SGMII_BIT,
@ -779,7 +779,7 @@ Signed-off-by: Daniel Golle <daniel@makrotopia.org>
MTK_ESW_BIT,
MTK_GEPHY_BIT,
MTK_MUX_BIT,
@@ -979,8 +996,11 @@ enum mkt_eth_capabilities {
@@ -985,8 +1002,11 @@ enum mkt_eth_capabilities {
MTK_ETH_MUX_GDM1_TO_GMAC1_ESW_BIT,
MTK_ETH_MUX_GMAC2_GMAC0_TO_GEPHY_BIT,
MTK_ETH_MUX_U3_GMAC2_TO_QPHY_BIT,
@ -791,7 +791,7 @@ Signed-off-by: Daniel Golle <daniel@makrotopia.org>
/* PATH BITS */
MTK_ETH_PATH_GMAC1_RGMII_BIT,
@@ -988,14 +1008,21 @@ enum mkt_eth_capabilities {
@@ -994,14 +1014,21 @@ enum mkt_eth_capabilities {
MTK_ETH_PATH_GMAC1_SGMII_BIT,
MTK_ETH_PATH_GMAC2_RGMII_BIT,
MTK_ETH_PATH_GMAC2_SGMII_BIT,
@ -813,7 +813,7 @@ Signed-off-by: Daniel Golle <daniel@makrotopia.org>
#define MTK_ESW BIT_ULL(MTK_ESW_BIT)
#define MTK_GEPHY BIT_ULL(MTK_GEPHY_BIT)
#define MTK_MUX BIT_ULL(MTK_MUX_BIT)
@@ -1018,10 +1045,16 @@ enum mkt_eth_capabilities {
@@ -1024,10 +1051,16 @@ enum mkt_eth_capabilities {
BIT_ULL(MTK_ETH_MUX_GMAC2_GMAC0_TO_GEPHY_BIT)
#define MTK_ETH_MUX_U3_GMAC2_TO_QPHY \
BIT_ULL(MTK_ETH_MUX_U3_GMAC2_TO_QPHY_BIT)
@ -830,7 +830,7 @@ Signed-off-by: Daniel Golle <daniel@makrotopia.org>
/* Supported path present on SoCs */
#define MTK_ETH_PATH_GMAC1_RGMII BIT_ULL(MTK_ETH_PATH_GMAC1_RGMII_BIT)
@@ -1029,8 +1062,13 @@ enum mkt_eth_capabilities {
@@ -1035,8 +1068,13 @@ enum mkt_eth_capabilities {
#define MTK_ETH_PATH_GMAC1_SGMII BIT_ULL(MTK_ETH_PATH_GMAC1_SGMII_BIT)
#define MTK_ETH_PATH_GMAC2_RGMII BIT_ULL(MTK_ETH_PATH_GMAC2_RGMII_BIT)
#define MTK_ETH_PATH_GMAC2_SGMII BIT_ULL(MTK_ETH_PATH_GMAC2_SGMII_BIT)
@ -844,7 +844,7 @@ Signed-off-by: Daniel Golle <daniel@makrotopia.org>
#define MTK_GMAC1_RGMII (MTK_ETH_PATH_GMAC1_RGMII | MTK_RGMII)
#define MTK_GMAC1_TRGMII (MTK_ETH_PATH_GMAC1_TRGMII | MTK_TRGMII)
@@ -1038,7 +1076,12 @@ enum mkt_eth_capabilities {
@@ -1044,7 +1082,12 @@ enum mkt_eth_capabilities {
#define MTK_GMAC2_RGMII (MTK_ETH_PATH_GMAC2_RGMII | MTK_RGMII)
#define MTK_GMAC2_SGMII (MTK_ETH_PATH_GMAC2_SGMII | MTK_SGMII)
#define MTK_GMAC2_GEPHY (MTK_ETH_PATH_GMAC2_GEPHY | MTK_GEPHY)
@ -857,7 +857,7 @@ Signed-off-by: Daniel Golle <daniel@makrotopia.org>
/* MUXes present on SoCs */
/* 0: GDM1 -> GMAC1, 1: GDM1 -> ESW */
@@ -1057,10 +1100,20 @@ enum mkt_eth_capabilities {
@@ -1063,10 +1106,20 @@ enum mkt_eth_capabilities {
(MTK_ETH_MUX_GMAC1_GMAC2_TO_SGMII_RGMII | MTK_MUX | \
MTK_SHARED_SGMII)
@ -878,7 +878,7 @@ Signed-off-by: Daniel Golle <daniel@makrotopia.org>
#define MTK_HAS_CAPS(caps, _x) (((caps) & (_x)) == (_x))
#define MT7621_CAPS (MTK_GMAC1_RGMII | MTK_GMAC1_TRGMII | \
@@ -1092,8 +1145,12 @@ enum mkt_eth_capabilities {
@@ -1098,8 +1151,12 @@ enum mkt_eth_capabilities {
MTK_MUX_GMAC12_TO_GEPHY_SGMII | MTK_QDMA | \
MTK_RSTCTRL_PPE1 | MTK_SRAM)
@ -893,7 +893,7 @@ Signed-off-by: Daniel Golle <daniel@makrotopia.org>
struct mtk_tx_dma_desc_info {
dma_addr_t addr;
@@ -1340,6 +1397,9 @@ struct mtk_mac {
@@ -1346,6 +1403,9 @@ struct mtk_mac {
struct device_node *of_node;
struct phylink *phylink;
struct phylink_config phylink_config;
@ -903,7 +903,7 @@ Signed-off-by: Daniel Golle <daniel@makrotopia.org>
struct mtk_eth *hw;
struct mtk_hw_stats *hw_stats;
__be32 hwlro_ip[MTK_MAX_LRO_IP_CNT];
@@ -1463,6 +1523,19 @@ static inline u32 mtk_get_ib2_multicast_
@@ -1469,6 +1529,19 @@ static inline u32 mtk_get_ib2_multicast_
return MTK_FOE_IB2_MULTICAST;
}
@ -923,7 +923,7 @@ Signed-off-by: Daniel Golle <daniel@makrotopia.org>
/* read the hardware status register */
void mtk_stats_update_mac(struct mtk_mac *mac);
@@ -1471,8 +1544,10 @@ u32 mtk_r32(struct mtk_eth *eth, unsigne
@@ -1477,8 +1550,10 @@ u32 mtk_r32(struct mtk_eth *eth, unsigne
u32 mtk_m32(struct mtk_eth *eth, u32 mask, u32 set, unsigned int reg);
int mtk_gmac_sgmii_path_setup(struct mtk_eth *eth, int mac_id);

View file

@ -30,8 +30,8 @@ Signed-off-by: Felix Fietkau <nbd@nbd.name>
--- a/drivers/net/ethernet/mediatek/mtk_eth_soc.c
+++ b/drivers/net/ethernet/mediatek/mtk_eth_soc.c
@@ -5512,7 +5512,7 @@ static const struct mtk_soc_data mt2701_
DESC_SIZE(struct mtk_rx_dma),
@@ -5470,7 +5470,7 @@ static const struct mtk_soc_data mt2701_
.desc_size = sizeof(struct mtk_rx_dma),
.irq_done_mask = MTK_RX_DONE_INT,
.dma_l4_valid = RX_DMA_L4_VALID,
- .dma_size = MTK_DMA_SIZE(2K),
@ -39,8 +39,8 @@ Signed-off-by: Felix Fietkau <nbd@nbd.name>
.dma_max_len = MTK_TX_DMA_BUF_LEN,
.dma_len_offset = 16,
},
@@ -5540,7 +5540,7 @@ static const struct mtk_soc_data mt7621_
DESC_SIZE(struct mtk_rx_dma),
@@ -5498,7 +5498,7 @@ static const struct mtk_soc_data mt7621_
.desc_size = sizeof(struct mtk_rx_dma),
.irq_done_mask = MTK_RX_DONE_INT,
.dma_l4_valid = RX_DMA_L4_VALID,
- .dma_size = MTK_DMA_SIZE(2K),
@ -48,8 +48,8 @@ Signed-off-by: Felix Fietkau <nbd@nbd.name>
.dma_max_len = MTK_TX_DMA_BUF_LEN,
.dma_len_offset = 16,
},
@@ -5570,7 +5570,7 @@ static const struct mtk_soc_data mt7622_
DESC_SIZE(struct mtk_rx_dma),
@@ -5528,7 +5528,7 @@ static const struct mtk_soc_data mt7622_
.desc_size = sizeof(struct mtk_rx_dma),
.irq_done_mask = MTK_RX_DONE_INT,
.dma_l4_valid = RX_DMA_L4_VALID,
- .dma_size = MTK_DMA_SIZE(2K),
@ -57,8 +57,8 @@ Signed-off-by: Felix Fietkau <nbd@nbd.name>
.dma_max_len = MTK_TX_DMA_BUF_LEN,
.dma_len_offset = 16,
},
@@ -5599,7 +5599,7 @@ static const struct mtk_soc_data mt7623_
DESC_SIZE(struct mtk_rx_dma),
@@ -5557,7 +5557,7 @@ static const struct mtk_soc_data mt7623_
.desc_size = sizeof(struct mtk_rx_dma),
.irq_done_mask = MTK_RX_DONE_INT,
.dma_l4_valid = RX_DMA_L4_VALID,
- .dma_size = MTK_DMA_SIZE(2K),
@ -66,8 +66,8 @@ Signed-off-by: Felix Fietkau <nbd@nbd.name>
.dma_max_len = MTK_TX_DMA_BUF_LEN,
.dma_len_offset = 16,
},
@@ -5625,7 +5625,7 @@ static const struct mtk_soc_data mt7629_
DESC_SIZE(struct mtk_rx_dma),
@@ -5583,7 +5583,7 @@ static const struct mtk_soc_data mt7629_
.desc_size = sizeof(struct mtk_rx_dma),
.irq_done_mask = MTK_RX_DONE_INT,
.dma_l4_valid = RX_DMA_L4_VALID,
- .dma_size = MTK_DMA_SIZE(2K),
@ -75,7 +75,7 @@ Signed-off-by: Felix Fietkau <nbd@nbd.name>
.dma_max_len = MTK_TX_DMA_BUF_LEN,
.dma_len_offset = 16,
},
@@ -5657,7 +5657,7 @@ static const struct mtk_soc_data mt7981_
@@ -5615,7 +5615,7 @@ static const struct mtk_soc_data mt7981_
.dma_l4_valid = RX_DMA_L4_VALID_V2,
.dma_max_len = MTK_TX_DMA_BUF_LEN,
.dma_len_offset = 16,
@ -84,7 +84,7 @@ Signed-off-by: Felix Fietkau <nbd@nbd.name>
},
};
@@ -5687,7 +5687,7 @@ static const struct mtk_soc_data mt7986_
@@ -5645,7 +5645,7 @@ static const struct mtk_soc_data mt7986_
.dma_l4_valid = RX_DMA_L4_VALID_V2,
.dma_max_len = MTK_TX_DMA_BUF_LEN,
.dma_len_offset = 16,
@ -93,7 +93,7 @@ Signed-off-by: Felix Fietkau <nbd@nbd.name>
},
};
@@ -5740,7 +5740,7 @@ static const struct mtk_soc_data rt5350_
@@ -5698,7 +5698,7 @@ static const struct mtk_soc_data rt5350_
.dma_l4_valid = RX_DMA_L4_VALID_PDMA,
.dma_max_len = MTK_TX_DMA_BUF_LEN,
.dma_len_offset = 16,

View file

@ -25,7 +25,7 @@ Signed-off-by: Felix Fietkau <nbd@nbd.name>
help
--- a/drivers/net/ethernet/mediatek/mtk_eth_soc.c
+++ b/drivers/net/ethernet/mediatek/mtk_eth_soc.c
@@ -4621,6 +4621,7 @@ static int mtk_get_sset_count(struct net
@@ -4582,6 +4582,7 @@ static int mtk_get_sset_count(struct net
static void mtk_ethtool_pp_stats(struct mtk_eth *eth, u64 *data)
{
@ -33,7 +33,7 @@ Signed-off-by: Felix Fietkau <nbd@nbd.name>
struct page_pool_stats stats = {};
int i;
@@ -4633,6 +4634,7 @@ static void mtk_ethtool_pp_stats(struct
@@ -4594,6 +4595,7 @@ static void mtk_ethtool_pp_stats(struct
page_pool_get_stats(ring->page_pool, &stats);
}
page_pool_ethtool_stats_get(data, &stats);

View file

@ -12,7 +12,7 @@ Signed-off-by: Felix Fietkau <nbd@nbd.name>
--- a/drivers/net/ethernet/mediatek/mtk_eth_soc.c
+++ b/drivers/net/ethernet/mediatek/mtk_eth_soc.c
@@ -1811,6 +1811,13 @@ static netdev_tx_t mtk_start_xmit(struct
@@ -1773,6 +1773,13 @@ static netdev_tx_t mtk_start_xmit(struct
bool gso = false;
int tx_num;
@ -26,7 +26,7 @@ Signed-off-by: Felix Fietkau <nbd@nbd.name>
/* normally we can rely on the stack not calling this more than once,
* however we have 2 queues running on the same ring so we need to lock
* the ring access
@@ -1874,8 +1881,9 @@ static netdev_tx_t mtk_start_xmit(struct
@@ -1836,8 +1843,9 @@ static netdev_tx_t mtk_start_xmit(struct
drop:
spin_unlock(&eth->page_lock);