EN7581 or AN7583 SoCs support connecting multiple external SerDes (e.g.
Ethernet or USB SerDes) to GDM3 or GDM4 ports via a hw arbiter that
manages the traffic in a TDM manner. As a result multiple net_devices can
connect to the same GDM{3,4} port and there is a theoretical "1:n"
relation between GDM ports and net_devices.
┌─────────────────────────────────┐
│ │ ┌──────┐
│ P1 GDM1 ├────►MT7530│
│ │ └──────┘
│ │ ETH0 (DSA conduit)
│ │
│ PSE/FE │
│ │
│ │
│ │ ┌─────┐
│ P0 CDM1 ├────►QDMA0│
│ P4 P9 GDM4 │ └─────┘
└──┬─────────────────────────┬────┘
│ │
┌──▼──┐ ┌────▼────┐
│ PPE │ │ ARB │
└─────┘ └─┬─────┬─┘
│ │
┌──▼──┐┌─▼───┐
│ ETH ││ USB │
└─────┘└─────┘
ETH1 ETH2
This series introduces support for multiple net_devices connected to the
same Frame Engine (FE) GDM port (GDM3 or GDM4) via an external hw
arbiter. Please note GDM1 or GDM2 does not support the connection with
the external arbiter.
Signed-off-by: Lorenzo Bianconi <lorenzo@kernel.org>
Link: https://github.com/openwrt/openwrt/pull/23481
Signed-off-by: Christian Marangi <ansuelsmth@gmail.com>
175 lines
5.2 KiB
Diff
175 lines
5.2 KiB
Diff
From c4f3077948eda05a6b9d1a11304d82c3e0300151 Mon Sep 17 00:00:00 2001
|
|
Message-ID: <c4f3077948eda05a6b9d1a11304d82c3e0300151.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: Fri, 3 Apr 2026 12:07:27 +0200
|
|
Subject: [PATCH 08/13] net: airoha: Introduce WAN device flag
|
|
|
|
Introduce WAN flag to specify if a given device is used to transmit/receive
|
|
WAN or LAN traffic. Current codebase supports specifying LAN/WAN device
|
|
configuration in ndo_init() callback during device bootstrap.
|
|
In order to consider setups where LAN configuration is used even for
|
|
GDM3/GDM4 devices, check airoha_is_lan_gdm_dev() to select pse_port in
|
|
airoha_ppe_foe_entry_prepare().
|
|
Please note after this patch, it will be possible to specify multiple LAN
|
|
devices but just a single WAN one. Please note this change is not visible
|
|
to the user since airoha_eth driver currently supports just the internal
|
|
phy available via the MT7530 DSA switch and there are no WAN interfaces
|
|
officially supported since PCS/external phy is not merged mainline yet
|
|
(it will be posted with following patches).
|
|
|
|
Tested-by: Xuegang Lu <xuegang.lu@airoha.com>
|
|
Signed-off-by: Lorenzo Bianconi <lorenzo@kernel.org>
|
|
---
|
|
drivers/net/ethernet/airoha/airoha_eth.c | 72 +++++++++++++++++++-----
|
|
drivers/net/ethernet/airoha/airoha_eth.h | 13 ++---
|
|
drivers/net/ethernet/airoha/airoha_ppe.c | 2 +-
|
|
3 files changed, 65 insertions(+), 22 deletions(-)
|
|
|
|
--- a/drivers/net/ethernet/airoha/airoha_eth.c
|
|
+++ b/drivers/net/ethernet/airoha/airoha_eth.c
|
|
@@ -2049,36 +2049,80 @@ static int airoha_set_gdm2_loopback(stru
|
|
return 0;
|
|
}
|
|
|
|
-static int airoha_dev_init(struct net_device *netdev)
|
|
+static struct airoha_gdm_dev *
|
|
+airoha_get_wan_gdm_dev(struct airoha_eth *eth)
|
|
+{
|
|
+ int i;
|
|
+
|
|
+ for (i = 0; i < ARRAY_SIZE(eth->ports); i++) {
|
|
+ struct airoha_gdm_port *port = eth->ports[i];
|
|
+ int j;
|
|
+
|
|
+ if (!port)
|
|
+ continue;
|
|
+
|
|
+ for (j = 0; j < ARRAY_SIZE(port->devs); j++) {
|
|
+ struct airoha_gdm_dev *dev = port->devs[j];
|
|
+
|
|
+ if (dev && !airoha_is_lan_gdm_dev(dev))
|
|
+ return dev;
|
|
+ }
|
|
+ }
|
|
+
|
|
+ return NULL;
|
|
+}
|
|
+
|
|
+static void airoha_dev_set_qdma(struct airoha_gdm_dev *dev)
|
|
{
|
|
- struct airoha_gdm_dev *dev = netdev_priv(netdev);
|
|
- struct airoha_gdm_port *port = dev->port;
|
|
struct airoha_eth *eth = dev->eth;
|
|
int ppe_id;
|
|
|
|
/* QDMA0 is used for lan ports while QDMA1 is used for WAN ports */
|
|
dev->qdma = ð->qdma[!airoha_is_lan_gdm_dev(dev)];
|
|
dev->dev->irq = dev->qdma->irq_banks[0].irq;
|
|
- airoha_set_macaddr(dev, netdev->dev_addr);
|
|
+
|
|
+ ppe_id = !airoha_is_lan_gdm_dev(dev) && airoha_ppe_is_enabled(eth, 1);
|
|
+ airoha_ppe_set_cpu_port(dev, ppe_id, airoha_get_fe_port(dev));
|
|
+}
|
|
+
|
|
+static int airoha_dev_init(struct net_device *netdev)
|
|
+{
|
|
+ struct airoha_gdm_dev *dev = netdev_priv(netdev);
|
|
+ struct airoha_gdm_port *port = dev->port;
|
|
|
|
switch (port->id) {
|
|
case AIROHA_GDM3_IDX:
|
|
- case AIROHA_GDM4_IDX:
|
|
- /* If GDM2 is active we can't enable loopback */
|
|
- if (!eth->ports[1]) {
|
|
- int err;
|
|
-
|
|
- err = airoha_set_gdm2_loopback(dev);
|
|
- if (err)
|
|
- return err;
|
|
- }
|
|
+ case AIROHA_GDM4_IDX: {
|
|
+ struct airoha_eth *eth = dev->eth;
|
|
+
|
|
+ /* GDM2 supports a single net_device */
|
|
+ if (eth->ports[1] && eth->ports[1]->devs[0])
|
|
+ break;
|
|
+
|
|
+ if (airoha_get_wan_gdm_dev(eth))
|
|
+ break;
|
|
+
|
|
+ fallthrough;
|
|
+ }
|
|
+ case AIROHA_GDM2_IDX:
|
|
+ /* GDM2 is always used as wan */
|
|
+ dev->flags |= AIROHA_PRIV_F_WAN;
|
|
break;
|
|
default:
|
|
break;
|
|
}
|
|
|
|
- ppe_id = !airoha_is_lan_gdm_dev(dev) && airoha_ppe_is_enabled(eth, 1);
|
|
- airoha_ppe_set_cpu_port(dev, ppe_id, airoha_get_fe_port(dev));
|
|
+ airoha_dev_set_qdma(dev);
|
|
+ airoha_set_macaddr(dev, netdev->dev_addr);
|
|
+
|
|
+ if (!airoha_is_lan_gdm_dev(dev) &&
|
|
+ (port->id == AIROHA_GDM3_IDX || port->id == AIROHA_GDM4_IDX)) {
|
|
+ int err;
|
|
+
|
|
+ err = airoha_set_gdm2_loopback(dev);
|
|
+ if (err)
|
|
+ return err;
|
|
+ }
|
|
|
|
return 0;
|
|
}
|
|
--- a/drivers/net/ethernet/airoha/airoha_eth.h
|
|
+++ b/drivers/net/ethernet/airoha/airoha_eth.h
|
|
@@ -549,6 +549,10 @@ struct airoha_qdma {
|
|
DECLARE_BITMAP(qos_channel_map, AIROHA_NUM_QOS_CHANNELS);
|
|
};
|
|
|
|
+enum airoha_priv_flags {
|
|
+ AIROHA_PRIV_F_WAN = BIT(0),
|
|
+};
|
|
+
|
|
struct airoha_gdm_dev {
|
|
struct airoha_gdm_port *port;
|
|
struct airoha_qdma *qdma;
|
|
@@ -565,6 +569,7 @@ struct airoha_gdm_dev {
|
|
u64 cpu_tx_packets;
|
|
u64 fwd_tx_packets;
|
|
|
|
+ u32 flags;
|
|
int nbq;
|
|
};
|
|
|
|
@@ -671,13 +676,7 @@ static inline u16 airoha_qdma_get_txq(st
|
|
|
|
static inline bool airoha_is_lan_gdm_dev(struct airoha_gdm_dev *dev)
|
|
{
|
|
- struct airoha_gdm_port *port = dev->port;
|
|
-
|
|
- /* GDM1 port on EN7581 SoC is connected to the lan dsa switch.
|
|
- * GDM{2,3,4} can be used as wan port connected to an external
|
|
- * phy module.
|
|
- */
|
|
- return port->id == 1;
|
|
+ return !(dev->flags & AIROHA_PRIV_F_WAN);
|
|
}
|
|
|
|
static inline bool airoha_is_7581(struct airoha_eth *eth)
|
|
--- a/drivers/net/ethernet/airoha/airoha_ppe.c
|
|
+++ b/drivers/net/ethernet/airoha/airoha_ppe.c
|
|
@@ -351,7 +351,7 @@ static int airoha_ppe_foe_entry_prepare(
|
|
return -EINVAL;
|
|
|
|
port = dev->port;
|
|
- if (dsa_port >= 0 || eth->ports[1])
|
|
+ if (dsa_port >= 0 || airoha_is_lan_gdm_dev(dev))
|
|
pse_port = port->id == 4 ? FE_PSE_PORT_GDM4
|
|
: port->id;
|
|
else
|