mirror of
https://github.com/openwrt/openwrt.git
synced 2026-06-17 12:40:16 +04:00
d22ceb8d24
Add hardware TCP Large Receive Offload (LRO) support to the airoha_eth driver, leveraging the EN7581/AN7583 SoC's 8 dedicated LRO hardware queues mapped to RX queues 24–31. LRO hw offloading does not support Scatter-Gather (SG) so it is required to increase the page_pool allocation order to 2 for RX queues 24–31 (LRO queues). Performance comparison between GRO and hw LRO has been carried out using a 10Gbps NIC: GRO: ~2.7 Gbps LRO: ~8.1 Gbps Tested-by: Madhur Agrawal <madhur.agrawal@airoha.com> Signed-off-by: Lorenzo Bianconi <lorenzo@kernel.org> Link: https://github.com/openwrt/openwrt/pull/23530 Signed-off-by: Christian Marangi <ansuelsmth@gmail.com>
224 lines
7.7 KiB
Diff
224 lines
7.7 KiB
Diff
From 99e204d255c9b47a188dd79762b9406d9c5fed9b Mon Sep 17 00:00:00 2001
|
|
Message-ID: <99e204d255c9b47a188dd79762b9406d9c5fed9b.1779348625.git.lorenzo@kernel.org>
|
|
In-Reply-To: <e15783f7c987e199ecf80b3d858ed5a86d33c508.1779348625.git.lorenzo@kernel.org>
|
|
References: <e15783f7c987e199ecf80b3d858ed5a86d33c508.1779348625.git.lorenzo@kernel.org>
|
|
From: Lorenzo Bianconi <lorenzo@kernel.org>
|
|
Date: Wed, 20 May 2026 17:16:39 +0200
|
|
Subject: [PATCH 13/13] net: airoha: Rework MTU configuration
|
|
|
|
Signed-off-by: Lorenzo Bianconi <lorenzo@kernel.org>
|
|
---
|
|
drivers/net/ethernet/airoha/airoha_eth.c | 85 +++++++++++------------
|
|
drivers/net/ethernet/airoha/airoha_eth.h | 1 +
|
|
drivers/net/ethernet/airoha/airoha_ppe.c | 8 +--
|
|
drivers/net/ethernet/airoha/airoha_regs.h | 9 ++-
|
|
4 files changed, 49 insertions(+), 54 deletions(-)
|
|
|
|
--- a/drivers/net/ethernet/airoha/airoha_eth.c
|
|
+++ b/drivers/net/ethernet/airoha/airoha_eth.c
|
|
@@ -185,10 +185,15 @@ static void airoha_fe_maccr_init(struct
|
|
{
|
|
int p;
|
|
|
|
- for (p = 1; p <= ARRAY_SIZE(eth->ports); p++)
|
|
+ for (p = 1; p <= ARRAY_SIZE(eth->ports); p++) {
|
|
airoha_fe_set(eth, REG_GDM_FWD_CFG(p),
|
|
GDM_TCP_CKSUM_MASK | GDM_UDP_CKSUM_MASK |
|
|
GDM_IP4_CKSUM_MASK | GDM_DROP_CRC_ERR_MASK);
|
|
+ airoha_fe_rmw(eth, REG_GDM_LEN_CFG(p),
|
|
+ GDM_SHORT_LEN_MASK | GDM_LONG_LEN_MASK,
|
|
+ FIELD_PREP(GDM_SHORT_LEN_MASK, 60) |
|
|
+ FIELD_PREP(GDM_LONG_LEN_MASK, AIROHA_MAX_MTU));
|
|
+ }
|
|
|
|
airoha_fe_rmw(eth, REG_CDM_VLAN_CTRL(1), CDM_VLAN_MASK,
|
|
FIELD_PREP(CDM_VLAN_MASK, 0x8100));
|
|
@@ -1907,13 +1912,37 @@ static void airoha_update_hw_stats(struc
|
|
spin_unlock(&port->stats.lock);
|
|
}
|
|
|
|
+void airoha_set_port_mtu(struct airoha_eth *eth, struct airoha_gdm_port *port)
|
|
+{
|
|
+ u32 mtu = 0, index;
|
|
+ int i;
|
|
+
|
|
+ for (i = 0; i < ARRAY_SIZE(port->devs); i++) {
|
|
+ struct airoha_gdm_dev *dev = port->devs[i];
|
|
+ struct net_device *netdev;
|
|
+
|
|
+ if (!dev)
|
|
+ continue;
|
|
+
|
|
+ netdev = dev->dev;
|
|
+ if (netif_running(netdev))
|
|
+ mtu = max_t(u32, mtu, netdev->mtu);
|
|
+ }
|
|
+
|
|
+ index = port->id == AIROHA_GDM4_IDX ? 7 : port->id;
|
|
+ for (i = 0; i < eth->soc->num_ppe; i++)
|
|
+ airoha_fe_rmw(eth, REG_PPE_MTU(i, index),
|
|
+ FP_EGRESS_MTU_MASK(index),
|
|
+ __field_prep(FP_EGRESS_MTU_MASK(index), mtu));
|
|
+}
|
|
+
|
|
static int airoha_dev_open(struct net_device *netdev)
|
|
{
|
|
- int err, len = ETH_HLEN + netdev->mtu + ETH_FCS_LEN;
|
|
struct airoha_gdm_dev *dev = netdev_priv(netdev);
|
|
struct airoha_gdm_port *port = dev->port;
|
|
- u32 cur_len, pse_port = FE_PSE_PORT_PPE1;
|
|
struct airoha_qdma *qdma = dev->qdma;
|
|
+ u32 pse_port = FE_PSE_PORT_PPE1;
|
|
+ int err;
|
|
|
|
if (port->id == AIROHA_GDM2_IDX && airoha_is_lan_gdm_dev(dev)) {
|
|
/* GDM2 can be used just as wan */
|
|
@@ -1946,19 +1975,12 @@ static int airoha_dev_open(struct net_de
|
|
airoha_fe_clear(qdma->eth, REG_GDM_INGRESS_CFG(port->id),
|
|
GDM_STAG_EN_MASK);
|
|
|
|
- cur_len = airoha_fe_get(qdma->eth, REG_GDM_LEN_CFG(port->id),
|
|
- GDM_LONG_LEN_MASK);
|
|
- if (!port->users || len > cur_len) {
|
|
- /* Opening a sibling net_device with a larger MTU updates the
|
|
- * MTU of already running devices. This is required to allow
|
|
- * multiple net_devices with different MTUs to share the same
|
|
- * GDM port.
|
|
- */
|
|
- airoha_fe_rmw(qdma->eth, REG_GDM_LEN_CFG(port->id),
|
|
- GDM_SHORT_LEN_MASK | GDM_LONG_LEN_MASK,
|
|
- FIELD_PREP(GDM_SHORT_LEN_MASK, 60) |
|
|
- FIELD_PREP(GDM_LONG_LEN_MASK, len));
|
|
- }
|
|
+ airoha_set_port_mtu(qdma->eth, port);
|
|
+ if (!airoha_is_lan_gdm_dev(dev))
|
|
+ airoha_fe_rmw(qdma->eth, REG_WAN_MTU0,
|
|
+ WAN_MTU0_MASK,
|
|
+ FIELD_PREP(WAN_MTU0_MASK, netdev->mtu));
|
|
+
|
|
port->users++;
|
|
|
|
airoha_qdma_set(qdma, REG_QDMA_GLOBAL_CFG,
|
|
@@ -1975,30 +1997,6 @@ static int airoha_dev_open(struct net_de
|
|
return 0;
|
|
}
|
|
|
|
-static void airoha_set_port_mtu(struct airoha_eth *eth,
|
|
- struct airoha_gdm_port *port)
|
|
-{
|
|
- u32 len = 0;
|
|
- int i;
|
|
-
|
|
- for (i = 0; i < ARRAY_SIZE(port->devs); i++) {
|
|
- struct airoha_gdm_dev *dev = port->devs[i];
|
|
- struct net_device *netdev;
|
|
-
|
|
- if (!dev)
|
|
- continue;
|
|
-
|
|
- netdev = dev->dev;
|
|
- if (netif_running(netdev))
|
|
- len = max_t(u32, len, netdev->mtu);
|
|
- }
|
|
- len += ETH_HLEN + ETH_FCS_LEN;
|
|
-
|
|
- airoha_fe_rmw(eth, REG_GDM_LEN_CFG(port->id),
|
|
- GDM_LONG_LEN_MASK,
|
|
- FIELD_PREP(GDM_LONG_LEN_MASK, len));
|
|
-}
|
|
-
|
|
static int airoha_dev_stop(struct net_device *netdev)
|
|
{
|
|
struct airoha_gdm_dev *dev = netdev_priv(netdev);
|
|
@@ -2082,10 +2080,6 @@ static int airoha_enable_gdm2_loopback(s
|
|
FIELD_PREP(LPBK_CHAN_MASK, chan) |
|
|
LBK_GAP_MODE_MASK | LBK_LEN_MODE_MASK |
|
|
LBK_CHAN_MODE_MASK | LPBK_EN_MASK);
|
|
- airoha_fe_rmw(eth, REG_GDM_LEN_CFG(AIROHA_GDM2_IDX),
|
|
- GDM_SHORT_LEN_MASK | GDM_LONG_LEN_MASK,
|
|
- FIELD_PREP(GDM_SHORT_LEN_MASK, 60) |
|
|
- FIELD_PREP(GDM_LONG_LEN_MASK, AIROHA_MAX_MTU));
|
|
/* Forward the traffic to the proper GDM port */
|
|
pse_port = port->id == AIROHA_GDM3_IDX ? FE_PSE_PORT_GDM3
|
|
: FE_PSE_PORT_GDM4;
|
|
@@ -2612,6 +2606,9 @@ static int airoha_dev_set_wan_flag(struc
|
|
default:
|
|
return -EOPNOTSUPP;
|
|
}
|
|
+ airoha_fe_rmw(eth, REG_WAN_MTU0,
|
|
+ WAN_MTU0_MASK,
|
|
+ FIELD_PREP(WAN_MTU0_MASK, netdev->mtu));
|
|
} else {
|
|
switch (port->id) {
|
|
case AIROHA_GDM3_IDX:
|
|
--- a/drivers/net/ethernet/airoha/airoha_eth.h
|
|
+++ b/drivers/net/ethernet/airoha/airoha_eth.h
|
|
@@ -706,6 +706,7 @@ int airoha_get_fe_port(struct airoha_gdm
|
|
bool airoha_is_valid_gdm_dev(struct airoha_eth *eth,
|
|
struct airoha_gdm_dev *dev);
|
|
|
|
+void airoha_set_port_mtu(struct airoha_eth *eth, struct airoha_gdm_port *port);
|
|
void airoha_ppe_set_cpu_port(struct airoha_gdm_dev *dev, u8 ppe_id, u8 fport);
|
|
bool airoha_ppe_is_enabled(struct airoha_eth *eth, int index);
|
|
void airoha_ppe_check_skb(struct airoha_ppe_dev *dev, struct sk_buff *skb,
|
|
--- a/drivers/net/ethernet/airoha/airoha_ppe.c
|
|
+++ b/drivers/net/ethernet/airoha/airoha_ppe.c
|
|
@@ -116,8 +116,6 @@ static void airoha_ppe_hw_init(struct ai
|
|
PPE_RAM_NUM_ENTRIES_SHIFT(sram_ppe_num_data_entries);
|
|
|
|
for (i = 0; i < eth->soc->num_ppe; i++) {
|
|
- int p;
|
|
-
|
|
airoha_fe_wr(eth, REG_PPE_TB_BASE(i),
|
|
ppe->foe_dma + sram_tb_size);
|
|
|
|
@@ -167,15 +165,6 @@ static void airoha_ppe_hw_init(struct ai
|
|
airoha_fe_wr(eth, REG_PPE_HASH_SEED(i), PPE_HASH_SEED);
|
|
airoha_fe_clear(eth, REG_PPE_PPE_FLOW_CFG(i),
|
|
PPE_FLOW_CFG_IP6_6RD_MASK);
|
|
-
|
|
- for (p = 0; p < ARRAY_SIZE(eth->ports); p++)
|
|
- airoha_fe_rmw(eth, REG_PPE_MTU(i, p),
|
|
- FP0_EGRESS_MTU_MASK |
|
|
- FP1_EGRESS_MTU_MASK,
|
|
- FIELD_PREP(FP0_EGRESS_MTU_MASK,
|
|
- AIROHA_MAX_MTU) |
|
|
- FIELD_PREP(FP1_EGRESS_MTU_MASK,
|
|
- AIROHA_MAX_MTU));
|
|
}
|
|
|
|
for (i = 0; i < ARRAY_SIZE(eth->ports); i++) {
|
|
@@ -185,6 +174,7 @@ static void airoha_ppe_hw_init(struct ai
|
|
if (!port)
|
|
continue;
|
|
|
|
+ airoha_set_port_mtu(eth, port);
|
|
for (j = 0; j < ARRAY_SIZE(port->devs); j++) {
|
|
struct airoha_gdm_dev *dev = port->devs[j];
|
|
u8 fport;
|
|
--- a/drivers/net/ethernet/airoha/airoha_regs.h
|
|
+++ b/drivers/net/ethernet/airoha/airoha_regs.h
|
|
@@ -341,9 +341,8 @@
|
|
#define PPE_SRAM_TABLE_EN_MASK BIT(0)
|
|
|
|
#define REG_PPE_MTU_BASE(_n) (((_n) ? PPE2_BASE : PPE1_BASE) + 0x304)
|
|
-#define REG_PPE_MTU(_m, _n) (REG_PPE_MTU_BASE(_m) + ((_n) << 2))
|
|
-#define FP1_EGRESS_MTU_MASK GENMASK(29, 16)
|
|
-#define FP0_EGRESS_MTU_MASK GENMASK(13, 0)
|
|
+#define REG_PPE_MTU(_m, _n) (REG_PPE_MTU_BASE(_m) + (((_n) / 2) << 2))
|
|
+#define FP_EGRESS_MTU_MASK(_n) GENMASK(13 + (((_n) % 2) << 4), ((_n) % 2) << 4)
|
|
|
|
#define REG_PPE_RAM_CTRL(_n) (((_n) ? PPE2_BASE : PPE1_BASE) + 0x31c)
|
|
#define PPE_SRAM_CTRL_ACK_MASK BIT(31)
|
|
@@ -404,6 +403,10 @@
|
|
#define FC_ID_OF_SRC_PORT_MASK(_n) GENMASK(4 + ((_n) << 3), ((_n) << 3))
|
|
#define FC_MAP6_DEF_VALUE 0x1b1a1918
|
|
|
|
+#define REG_WAN_MTU0 0x2300
|
|
+#define WAN_MTU1_MASK GENMASK(29, 16)
|
|
+#define WAN_MTU0_MASK GENMASK(13, 0)
|
|
+
|
|
#define REG_CDM5_RX_OQ1_DROP_CNT 0x29d4
|
|
|
|
/* QDMA */
|