diff options
| author | Lorenzo Bianconi <lorenzo@kernel.org> | 2026-06-03 09:00:19 +0300 |
|---|---|---|
| committer | Jakub Kicinski <kuba@kernel.org> | 2026-06-06 04:46:54 +0300 |
| commit | 7758cb462ff72b10d71e72bca8cf65179a1264e8 (patch) | |
| tree | 33fc6c2a8833b5e4b00915cc5cd04e458c34e3c5 | |
| parent | 99b9d095d71e5cb84121dacce2ac217aad9b174f (diff) | |
| download | linux-7758cb462ff72b10d71e72bca8cf65179a1264e8.tar.xz | |
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>
Link: https://patch.msgid.link/20260603-airoha-eth-multi-serdes-v9-5-5d476bc2f426@kernel.org
Signed-off-by: Jakub Kicinski <kuba@kernel.org>
| -rw-r--r-- | drivers/net/ethernet/airoha/airoha_eth.c | 73 | ||||
| -rw-r--r-- | drivers/net/ethernet/airoha/airoha_eth.h | 13 | ||||
| -rw-r--r-- | drivers/net/ethernet/airoha/airoha_ppe.c | 2 |
3 files changed, 66 insertions, 22 deletions
diff --git a/drivers/net/ethernet/airoha/airoha_eth.c b/drivers/net/ethernet/airoha/airoha_eth.c index 4509281c3c7b..402aa1d33d33 100644 --- a/drivers/net/ethernet/airoha/airoha_eth.c +++ b/drivers/net/ethernet/airoha/airoha_eth.c @@ -1899,36 +1899,81 @@ static int airoha_enable_gdm2_loopback(struct airoha_gdm_dev *dev) 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) { - struct airoha_gdm_dev *dev = netdev_priv(netdev); - struct airoha_gdm_port *port = dev->port; + 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 net_device *netdev = netdev_from_priv(dev); 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)]; netdev->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; + case AIROHA_GDM4_IDX: { + struct airoha_eth *eth = dev->eth; - err = airoha_enable_gdm2_loopback(dev); - if (err) - return err; - } + /* 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_enable_gdm2_loopback(dev); + if (err) + return err; + } return 0; } diff --git a/drivers/net/ethernet/airoha/airoha_eth.h b/drivers/net/ethernet/airoha/airoha_eth.h index 666e9246e70e..3e8262f583a7 100644 --- a/drivers/net/ethernet/airoha/airoha_eth.h +++ b/drivers/net/ethernet/airoha/airoha_eth.h @@ -538,6 +538,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; @@ -548,6 +552,7 @@ struct airoha_gdm_dev { u64 cpu_tx_packets; u64 fwd_tx_packets; + u32 flags; int nbq; }; @@ -654,13 +659,7 @@ static inline u16 airoha_qdma_get_txq(struct airoha_qdma *qdma, u16 qid) 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) diff --git a/drivers/net/ethernet/airoha/airoha_ppe.c b/drivers/net/ethernet/airoha/airoha_ppe.c index 96abf451fdac..f54622904733 100644 --- a/drivers/net/ethernet/airoha/airoha_ppe.c +++ b/drivers/net/ethernet/airoha/airoha_ppe.c @@ -355,7 +355,7 @@ static int airoha_ppe_foe_entry_prepare(struct airoha_eth *eth, 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 |
