From mboxrd@z Thu Jan 1 00:00:00 1970 Return-Path: X-Spam-Checker-Version: SpamAssassin 3.4.0 (2014-02-07) on aws-us-west-2-korg-lkml-1.web.codeaurora.org Received: from bombadil.infradead.org (bombadil.infradead.org [198.137.202.133]) (using TLSv1.2 with cipher ECDHE-RSA-AES256-GCM-SHA384 (256/256 bits)) (No client certificate requested) by smtp.lore.kernel.org (Postfix) with ESMTPS id 53D8ECD4851 for ; Tue, 19 May 2026 08:59:02 +0000 (UTC) DKIM-Signature: v=1; a=rsa-sha256; q=dns/txt; c=relaxed/relaxed; d=lists.infradead.org; s=bombadil.20210309; h=Sender:List-Subscribe:List-Help :List-Post:List-Archive:List-Unsubscribe:List-Id:Cc:To:In-Reply-To:References :Message-Id:Content-Transfer-Encoding:Content-Type:MIME-Version:Subject:Date: From:Reply-To:Content-ID:Content-Description:Resent-Date:Resent-From: Resent-Sender:Resent-To:Resent-Cc:Resent-Message-ID:List-Owner; bh=1E2ImGYWsJpjvC3hIVC90B9twJKei/PQnia+pdh80iU=; b=3J1bi8zMppT6q9fEWC+bCqxg/i mOGtavFfSSuyahxVUZFGRMVaO0QKaFny/ui060lQGkj0LTZanXYQYnYCwnmayM6brVkJmaxBc02fj Y8OrtwkNiUDK8dU4eRKGjDR5dfowUnjqZ2s7yhtaKSp6eDnV9cpK2pLdff90IoqY7fxFqY6AZrb+m ZQs2piLt3f8sw1oc7Iu4b+p1c+MsoeUz4X1CozxILIFVtV7S8h/eqym6rfEYQAU3bjgmj9zVRijdj 7FGJvDwIGNGidGmzLdr9d8sse6SLcdgELGvCF1mTEMK9RTg4HwzyfxPJUUrii5Xmfi3tcJbe2n1gl er5jo8bg==; Received: from localhost ([::1] helo=bombadil.infradead.org) by bombadil.infradead.org with esmtp (Exim 4.99.1 #2 (Red Hat Linux)) id 1wPGI0-00000000n4R-429m; Tue, 19 May 2026 08:59:00 +0000 Received: from sea.source.kernel.org ([172.234.252.31]) by bombadil.infradead.org with esmtps (Exim 4.99.1 #2 (Red Hat Linux)) id 1wPGHm-00000000mme-2uwV; Tue, 19 May 2026 08:58:48 +0000 Received: from smtp.kernel.org (transwarp.subspace.kernel.org [100.75.92.58]) by sea.source.kernel.org (Postfix) with ESMTP id 5936240DFF; Tue, 19 May 2026 08:58:46 +0000 (UTC) Received: by smtp.kernel.org (Postfix) with ESMTPSA id A3DA6C2BCF5; Tue, 19 May 2026 08:58:45 +0000 (UTC) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/simple; d=kernel.org; s=k20201202; t=1779181126; bh=kIZ7hSTUwleZoENzPyp+m6OfOT2FDYmUobikUdJcGFc=; h=From:Date:Subject:References:In-Reply-To:To:Cc:From; b=jMb/JSaPqDZV6oxNIbKf9yWe5bo5/ol7/nzazi+OlaTPtwHG43EpIJRVrxDbpvTDq QwcCrmy8HD7TkGITgX8p5O9vrjt6c159m/RSVVJ671qJ4NmnuukYPXU9iT8e6g5RiH AuE5xRPHcB8CZ2fCbXFZ628zpN/gMzCb/i/gMj34zGr9JZP6lSUbEaf0AXNxNszIUK 6a6280pQhO1ylsSeX9KPEN3+TEUz2+YIcnhH0BaTK669y2ItXHY58MwZ8eLYMDNN9O IB+zOkRGplzCI6Y+zW3YUT3PHqTQNZXQZD6Qe3CAp0Z6uQpc6uDybNn4nprTH33Bv4 KDq/zFFty40lQ== From: Lorenzo Bianconi Date: Tue, 19 May 2026 10:57:53 +0200 Subject: [PATCH net-next v8 10/10] net: airoha: Support multiple LAN/WAN interfaces for hw MAC address configuration MIME-Version: 1.0 Content-Type: text/plain; charset="utf-8" Content-Transfer-Encoding: 7bit Message-Id: <20260519-airoha-eth-multi-serdes-v8-10-6bd70e329df6@kernel.org> References: <20260519-airoha-eth-multi-serdes-v8-0-6bd70e329df6@kernel.org> In-Reply-To: <20260519-airoha-eth-multi-serdes-v8-0-6bd70e329df6@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 X-CRM114-Version: 20100106-BlameMichelson ( TRE 0.9.0 (BSD) ) MR-646709E3 X-CRM114-CacheID: sfid-20260519_015846_810171_B05E7B98 X-CRM114-Status: GOOD ( 19.25 ) X-BeenThere: linux-mediatek@lists.infradead.org X-Mailman-Version: 2.1.34 Precedence: list List-Id: List-Unsubscribe: , List-Archive: List-Post: List-Help: List-Subscribe: , Sender: "Linux-mediatek" Errors-To: linux-mediatek-bounces+linux-mediatek=archiver.kernel.org@lists.infradead.org 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 | 77 +++++++++++++++++++++++++++----- drivers/net/ethernet/airoha/airoha_eth.h | 2 +- drivers/net/ethernet/airoha/airoha_ppe.c | 4 +- 3 files changed, 68 insertions(+), 15 deletions(-) diff --git a/drivers/net/ethernet/airoha/airoha_eth.c b/drivers/net/ethernet/airoha/airoha_eth.c index 328f94fef2e2..9ae1ba433309 100644 --- a/drivers/net/ethernet/airoha/airoha_eth.c +++ b/drivers/net/ethernet/airoha/airoha_eth.c @@ -71,20 +71,69 @@ 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) { + u8 ref_addr[ETH_ALEN] __aligned(2); struct airoha_eth *eth = dev->eth; - u32 val, reg; + u32 reg, val, lmin, lmax; + int i; + + eth_zero_addr(ref_addr); + 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. + */ + netdev_err(dev->dev, "wrong mac addr for shared GDM port\n"); + 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, @@ -1824,13 +1873,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; } @@ -1935,6 +1989,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: @@ -1959,12 +2014,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) return err; diff --git a/drivers/net/ethernet/airoha/airoha_eth.h b/drivers/net/ethernet/airoha/airoha_eth.h index a2241520f2e2..364ca76eb3a6 100644 --- a/drivers/net/ethernet/airoha/airoha_eth.h +++ b/drivers/net/ethernet/airoha/airoha_eth.h @@ -684,7 +684,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