From mboxrd@z Thu Jan 1 00:00:00 1970 Received: from smtp.kernel.org (aws-us-west-2-korg-mail-1.web.codeaurora.org [10.30.226.201]) (using TLSv1.2 with cipher ECDHE-RSA-AES256-GCM-SHA384 (256/256 bits)) (No client certificate requested) by smtp.subspace.kernel.org (Postfix) with ESMTPS id 8F9651C5D59; Sat, 9 May 2026 13:06:23 +0000 (UTC) Authentication-Results: smtp.subspace.kernel.org; arc=none smtp.client-ip=10.30.226.201 ARC-Seal:i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1778331983; cv=none; b=VWwOt42ArN4cuzWo5v6Y8HXS0K+dsfB67ybM0zP9aHTNX9u1eK6UeLsXYuI/3mCpw+HxAH+SIYUekDaJdue29AJ8gIhluHD06T1vnyWRqcb2+HCv3IgT20liia4ExjzMyNEhGPm+6UAaWXRi5yzqo5YhHdvBBfE1T4vKyLcwyhw= ARC-Message-Signature:i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1778331983; c=relaxed/simple; bh=cK1fia3EzhBFu/WA70CWg7XNRfwVE9hiVkk4QccYxqw=; h=From:Date:Subject:MIME-Version:Content-Type:Message-Id:References: In-Reply-To:To:Cc; b=P3eh9DQ2OOvWCPPrToGf73/JuOs5pg7Ed0klYWy1o8FfoNA+NanQpiXWXkvhZhKD5uyM4EcnT+jgNL1fToLHuqP22YBd5ZgiwnN6ZiiJZbcQaPiwq5OqLSuz5W5U7iZlC6gih2JuPnI0efpehIxhpKElaADqGszVMqlvoCXIkhs= ARC-Authentication-Results:i=1; smtp.subspace.kernel.org; dkim=pass (2048-bit key) header.d=kernel.org header.i=@kernel.org header.b=uFlTs1p7; arc=none smtp.client-ip=10.30.226.201 Authentication-Results: smtp.subspace.kernel.org; dkim=pass (2048-bit key) header.d=kernel.org header.i=@kernel.org header.b="uFlTs1p7" Received: by smtp.kernel.org (Postfix) with ESMTPSA id 89663C2BCF6; Sat, 9 May 2026 13:06:22 +0000 (UTC) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/simple; d=kernel.org; s=k20201202; t=1778331982; bh=cK1fia3EzhBFu/WA70CWg7XNRfwVE9hiVkk4QccYxqw=; h=From:Date:Subject:References:In-Reply-To:To:Cc:From; b=uFlTs1p73qKBnEXopbVwx3lcPWzpB0qLMqvpuxalTGuKc97r49pYy3F+IpIt6x88A F8an6cxexdQepK24mSNZ5t05Mq7J169ZhIy2LofsCZw2c4WUNEDMKorwuKN+qAPBIU VNJMq+BTBs4D/U4ajLreuf7/F+svHPw4oXghKEUFdWhf41PMTusBvuHv3EAEV9esQb Gi87T4FyhAFw5NP65n0NJKVSpIKdvtmAp9rScabH7lMPvI8tfepngQNQZ3m/TWzD3Y 86wDHJh/fkT9Yj/kI155UzybkVVE3wzddr4SAzKaOjo1muC+/UOC0VzlguMxcHjzk/ kuLK1Oj4qF37Q== From: Lorenzo Bianconi Date: Sat, 09 May 2026 15:05:36 +0200 Subject: [PATCH net-next v5 11/12] net: airoha: Support multiple LAN/WAN interfaces for hw MAC address configuration Precedence: bulk X-Mailing-List: devicetree@vger.kernel.org List-Id: List-Subscribe: List-Unsubscribe: MIME-Version: 1.0 Content-Type: text/plain; charset="utf-8" Content-Transfer-Encoding: 7bit Message-Id: <20260509-airoha-eth-multi-serdes-v5-11-805e38edc2aa@kernel.org> References: <20260509-airoha-eth-multi-serdes-v5-0-805e38edc2aa@kernel.org> In-Reply-To: <20260509-airoha-eth-multi-serdes-v5-0-805e38edc2aa@kernel.org> To: Andrew Lunn , "David S. Miller" , Eric Dumazet , Jakub Kicinski , Paolo Abeni , Rob Herring , Krzysztof Kozlowski , Conor Dooley , Lorenzo Bianconi Cc: Christian Marangi , Benjamin Larsson , linux-arm-kernel@lists.infradead.org, linux-mediatek@lists.infradead.org, netdev@vger.kernel.org, devicetree@vger.kernel.org, Madhur Agrawal X-Mailer: b4 0.14.3 The EN7581 and AN7583 SoCs provide registers to configure hardware LAN/WAN MAC addresses, used to determine whether received traffic is destined for this host or should be forwarded to another device. The SoC hardware design assumes all interfaces configured as LAN (or WAN) share a common upper MAC address, which is programmed into the REG_FE_{LAN,WAN}_MAC_H register. The lower bytes of 'local' addresses can be expressed as a range via the REG_FE_MAC_LMIN and REG_FE_MAC_LMAX registers. Previously, only a single interface was considered when programming these registers. Extend the logic to derive the correct minimum and maximum values for REG_FE_MAC_LMIN/REG_FE_MAC_LMAX when two or more interfaces are configured as LAN or WAN. Tested-by: Madhur Agrawal Signed-off-by: Lorenzo Bianconi --- drivers/net/ethernet/airoha/airoha_eth.c | 75 +++++++++++++++++++++++++++----- drivers/net/ethernet/airoha/airoha_eth.h | 2 +- drivers/net/ethernet/airoha/airoha_ppe.c | 4 +- 3 files changed, 66 insertions(+), 15 deletions(-) diff --git a/drivers/net/ethernet/airoha/airoha_eth.c b/drivers/net/ethernet/airoha/airoha_eth.c index fa37dbd76d57..623cac42dfb7 100644 --- a/drivers/net/ethernet/airoha/airoha_eth.c +++ b/drivers/net/ethernet/airoha/airoha_eth.c @@ -71,20 +71,67 @@ static void airoha_qdma_irq_disable(struct airoha_irq_bank *irq_bank, airoha_qdma_set_irqmask(irq_bank, index, mask, 0); } -static void airoha_set_macaddr(struct airoha_gdm_dev *dev, const u8 *addr) +static int airoha_set_macaddr(struct airoha_gdm_dev *dev, const u8 *addr) { struct airoha_eth *eth = dev->eth; - u32 val, reg; + u8 ref_addr[ETH_ALEN] = {}; + u32 reg, val, lmin, lmax; + int i; + + lmin = (addr[3] << 16) | (addr[4] << 8) | addr[5]; + lmax = lmin; + + 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 *iter_dev; + struct net_device *netdev; + + iter_dev = port->devs[j]; + if (!iter_dev || iter_dev == dev) + continue; + + if (airoha_is_lan_gdm_dev(iter_dev) != + airoha_is_lan_gdm_dev(dev)) + continue; + + netdev = iter_dev->dev; + if (netdev->reg_state != NETREG_REGISTERED) + continue; + + ether_addr_copy(ref_addr, netdev->dev_addr); + val = (netdev->dev_addr[3] << 16) | + (netdev->dev_addr[4] << 8) | netdev->dev_addr[5]; + if (val < lmin) + lmin = val; + if (val > lmax) + lmax = val; + } + } + + if (!is_zero_ether_addr(ref_addr) && memcmp(ref_addr, addr, 3)) { + /* According to the HW design, hw mac address MS bits + * must be the same for each net_device with the same + * LAN/WAN configuration. + */ + return -EINVAL; + } reg = airoha_is_lan_gdm_dev(dev) ? REG_FE_LAN_MAC_H : REG_FE_WAN_MAC_H; val = (addr[0] << 16) | (addr[1] << 8) | addr[2]; airoha_fe_wr(eth, reg, val); - val = (addr[3] << 16) | (addr[4] << 8) | addr[5]; - airoha_fe_wr(eth, REG_FE_MAC_LMIN(reg), val); - airoha_fe_wr(eth, REG_FE_MAC_LMAX(reg), val); + airoha_fe_wr(eth, REG_FE_MAC_LMIN(reg), lmin); + airoha_fe_wr(eth, REG_FE_MAC_LMAX(reg), lmax); - airoha_ppe_init_upd_mem(dev); + airoha_ppe_init_upd_mem(dev, addr); + + return 0; } static void airoha_set_gdm_port_fwd_cfg(struct airoha_eth *eth, u32 addr, @@ -1800,13 +1847,18 @@ static int airoha_dev_stop(struct net_device *netdev) static int airoha_dev_set_macaddr(struct net_device *netdev, void *p) { struct airoha_gdm_dev *dev = netdev_priv(netdev); + struct sockaddr *addr = p; int err; - err = eth_mac_addr(netdev, p); + err = eth_prepare_mac_addr_change(netdev, p); if (err) return err; - airoha_set_macaddr(dev, netdev->dev_addr); + err = airoha_set_macaddr(dev, addr->sa_data); + if (err) + return err; + + eth_commit_mac_addr_change(netdev, p); return 0; } @@ -1911,6 +1963,7 @@ static int airoha_dev_init(struct net_device *netdev) { struct airoha_gdm_dev *dev = netdev_priv(netdev); struct airoha_gdm_port *port = dev->port; + int err; switch (port->id) { case AIROHA_GDM3_IDX: @@ -1935,12 +1988,12 @@ static int airoha_dev_init(struct net_device *netdev) } airoha_dev_set_qdma(dev); - airoha_set_macaddr(dev, netdev->dev_addr); + err = airoha_set_macaddr(dev, netdev->dev_addr); + if (err) + return err; 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) { dev->flags &= ~AIROHA_PRIV_F_WAN; diff --git a/drivers/net/ethernet/airoha/airoha_eth.h b/drivers/net/ethernet/airoha/airoha_eth.h index 4972dffc9c62..4564a581d138 100644 --- a/drivers/net/ethernet/airoha/airoha_eth.h +++ b/drivers/net/ethernet/airoha/airoha_eth.h @@ -683,7 +683,7 @@ void airoha_ppe_check_skb(struct airoha_ppe_dev *dev, struct sk_buff *skb, int airoha_ppe_setup_tc_block_cb(struct airoha_ppe_dev *dev, void *type_data); int airoha_ppe_init(struct airoha_eth *eth); void airoha_ppe_deinit(struct airoha_eth *eth); -void airoha_ppe_init_upd_mem(struct airoha_gdm_dev *dev); +void airoha_ppe_init_upd_mem(struct airoha_gdm_dev *dev, const u8 *addr); u32 airoha_ppe_get_total_num_entries(struct airoha_ppe *ppe); struct airoha_foe_entry *airoha_ppe_foe_get_entry(struct airoha_ppe *ppe, u32 hash); diff --git a/drivers/net/ethernet/airoha/airoha_ppe.c b/drivers/net/ethernet/airoha/airoha_ppe.c index 194cd50b2c74..531ce33528b9 100644 --- a/drivers/net/ethernet/airoha/airoha_ppe.c +++ b/drivers/net/ethernet/airoha/airoha_ppe.c @@ -1482,12 +1482,10 @@ void airoha_ppe_check_skb(struct airoha_ppe_dev *dev, struct sk_buff *skb, airoha_ppe_foe_insert_entry(ppe, skb, hash, rx_wlan); } -void airoha_ppe_init_upd_mem(struct airoha_gdm_dev *dev) +void airoha_ppe_init_upd_mem(struct airoha_gdm_dev *dev, const u8 *addr) { struct airoha_gdm_port *port = dev->port; - struct net_device *netdev = dev->dev; struct airoha_eth *eth = dev->eth; - const u8 *addr = netdev->dev_addr; u32 val; val = (addr[2] << 24) | (addr[3] << 16) | (addr[4] << 8) | addr[5]; -- 2.54.0