From nobody Tue Oct 7 17:48:35 2025 Received: from relmlie5.idc.renesas.com (relmlor1.renesas.com [210.160.252.171]) by smtp.subspace.kernel.org (Postfix) with ESMTP id 1BC592253E4; Tue, 8 Jul 2025 09:27:58 +0000 (UTC) Authentication-Results: smtp.subspace.kernel.org; arc=none smtp.client-ip=210.160.252.171 ARC-Seal: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1751966881; cv=none; b=C94WKAB1u6nJGEDkvkZCEyxgDT5q1jVO9luuI/pa9xtkEs2qpqOGm5fE0EQkYKtp8pWomRfs7adgW8xsJJt6YBVGOhqu+ArZg/wWzNeQtYTDP4ogrxZqQn7Q/xDHesWJBIV3yxLys1Er00ycMMfc04a0OqK0WKTcD2YV/GiyKtM= ARC-Message-Signature: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1751966881; c=relaxed/simple; bh=l4w4ScuC6+kKDFL0zv62ICBhy98vqkkl4tddPQXmdeU=; h=From:Date:Subject:MIME-Version:Content-Type:Message-Id:References: In-Reply-To:To:Cc; b=FMFKb8nBrFZwr8IZpDbMQwn1/RIc/W8BlK6jh2yk/AhzjZsYRUYE9S7e89qaw2Tnvmx0jAsh4xSNn2KaUqVUM8A+xVJLfOkb5DLlu8lShc49KzEBIqmWDXGXiadtigeSywQbAKpWbo3fqj0SOapDxzVi+4bvoHs9p95Zg1cD/To= ARC-Authentication-Results: i=1; smtp.subspace.kernel.org; dmarc=pass (p=none dis=none) header.from=renesas.com; spf=pass smtp.mailfrom=renesas.com; arc=none smtp.client-ip=210.160.252.171 Authentication-Results: smtp.subspace.kernel.org; dmarc=pass (p=none dis=none) header.from=renesas.com Authentication-Results: smtp.subspace.kernel.org; spf=pass smtp.mailfrom=renesas.com X-CSE-ConnectionGUID: Nclw74RMR7+LM6awX3QxxQ== X-CSE-MsgGUID: V2nIMrjjRKis5CxHPKUJyA== Received: from unknown (HELO relmlir5.idc.renesas.com) ([10.200.68.151]) by relmlie5.idc.renesas.com with ESMTP; 08 Jul 2025 18:27:53 +0900 Received: from [127.0.1.1] (unknown [10.226.78.19]) by relmlir5.idc.renesas.com (Postfix) with ESMTP id 82054400A8AD; Tue, 8 Jul 2025 18:27:50 +0900 (JST) From: Michael Dege Date: Tue, 08 Jul 2025 11:27:37 +0200 Subject: [PATCH v2 1/4] net: renesas: rswitch: rename rswitch.c to rswitch_main.c Precedence: bulk X-Mailing-List: linux-kernel@vger.kernel.org List-Id: List-Subscribe: List-Unsubscribe: MIME-Version: 1.0 Content-Type: text/plain; charset="utf-8" Content-Transfer-Encoding: quoted-printable Message-Id: <20250708-add_l2_switching-v2-1-f91f5556617a@renesas.com> References: <20250708-add_l2_switching-v2-0-f91f5556617a@renesas.com> In-Reply-To: <20250708-add_l2_switching-v2-0-f91f5556617a@renesas.com> To: Yoshihiro Shimoda , =?utf-8?q?Niklas_S=C3=B6derlund?= , Paul Barker , Andrew Lunn , "David S. Miller" , Eric Dumazet , Jakub Kicinski , Paolo Abeni Cc: netdev@vger.kernel.org, linux-renesas-soc@vger.kernel.org, linux-kernel@vger.kernel.org, Michael Dege , Nikita Yushchenko X-Mailer: b4 0.14.2 X-Developer-Signature: v=1; a=ed25519-sha256; t=1751966866; l=1175; i=michael.dege@renesas.com; s=20250523; h=from:subject:message-id; bh=l4w4ScuC6+kKDFL0zv62ICBhy98vqkkl4tddPQXmdeU=; b=VR3sQ3MOk7Nje9xJ1qdtyJO85uiGyd6rp2iK5sIziDYFO4ZEUOH0yomJMBaN82npDagM8CQFO MWbCqCX5eTwCXj33BWc5oyHWaBIrvdcK/J+Spx5ING/rqwXgCGgz10m X-Developer-Key: i=michael.dege@renesas.com; a=ed25519; pk=+gYTlVQ3/MlOju88OuKnXA7MlapP4lYqJn1F81HZGSo= Adding new functionality to the driver. Therefore splitting into multiple c files to keep them manageable. New functionality will be added to separate files. Signed-off-by: Michael Dege --- drivers/net/ethernet/renesas/Makefile | 1 + drivers/net/ethernet/renesas/{rswitch.c =3D> rswitch_main.c} | 0 2 files changed, 1 insertion(+) diff --git a/drivers/net/ethernet/renesas/Makefile b/drivers/net/ethernet/r= enesas/Makefile index f65fc76f8b4df8dd9f24af836b6dc0772965366f..6222298bb5582b7091cf8de76ac= b83ac7dd39c11 100644 --- a/drivers/net/ethernet/renesas/Makefile +++ b/drivers/net/ethernet/renesas/Makefile @@ -8,6 +8,7 @@ obj-$(CONFIG_SH_ETH) +=3D sh_eth.o ravb-objs :=3D ravb_main.o ravb_ptp.o obj-$(CONFIG_RAVB) +=3D ravb.o =20 +rswitch-objs :=3D rswitch_main.o obj-$(CONFIG_RENESAS_ETHER_SWITCH) +=3D rswitch.o =20 obj-$(CONFIG_RENESAS_GEN4_PTP) +=3D rcar_gen4_ptp.o diff --git a/drivers/net/ethernet/renesas/rswitch.c b/drivers/net/ethernet/= renesas/rswitch_main.c similarity index 100% rename from drivers/net/ethernet/renesas/rswitch.c rename to drivers/net/ethernet/renesas/rswitch_main.c --=20 2.49.0 From nobody Tue Oct 7 17:48:35 2025 Received: from relmlie5.idc.renesas.com (relmlor1.renesas.com [210.160.252.171]) by smtp.subspace.kernel.org (Postfix) with ESMTP id D1ECB22B8D0; Tue, 8 Jul 2025 09:28:00 +0000 (UTC) Authentication-Results: smtp.subspace.kernel.org; arc=none smtp.client-ip=210.160.252.171 ARC-Seal: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1751966883; cv=none; b=Z0evZUMv5GwWibP2xlHZWm7kKAaA0jLTPFSy0xnhnLL3IKmO45920B8zwFINOlE/DMXDQhkOOOBaVg9YNaXDgS/6GXE+yx8CQ6Pp3XKSTJFK0fsT1acpF9mlVnnMZY/aCA9JsT4mEcQIXjjLqimXo5rOhKfy21Z+dOGBcHT5/cg= ARC-Message-Signature: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1751966883; c=relaxed/simple; bh=KVrzRmQGG2cdaeFhNKeIxvEvNE+9YXP1pbh5qNJxgq8=; h=From:Date:Subject:MIME-Version:Content-Type:Message-Id:References: In-Reply-To:To:Cc; b=kpxQXikfcQelqT81F661StTWWqXPdhTfiPeQo7zYH9BDxxgkOo8ayZxUU4d8eAlt2CmNF1SxclbqJ2uInMHRlGYex3AM+ZFlO73xLVRq6+yZi64Wl+oQwP5uB2s628XctCiDWaW3F+e6J6OYWO60FWUIEUjzTEgickLQ3J5+Szk= ARC-Authentication-Results: i=1; smtp.subspace.kernel.org; dmarc=pass (p=none dis=none) header.from=renesas.com; spf=pass smtp.mailfrom=renesas.com; arc=none smtp.client-ip=210.160.252.171 Authentication-Results: smtp.subspace.kernel.org; dmarc=pass (p=none dis=none) header.from=renesas.com Authentication-Results: smtp.subspace.kernel.org; spf=pass smtp.mailfrom=renesas.com X-CSE-ConnectionGUID: il9EKbu7SK2cU6f8KfR/wQ== X-CSE-MsgGUID: Lben6mkeQcS2kDFHnXzE3Q== Received: from unknown (HELO relmlir5.idc.renesas.com) ([10.200.68.151]) by relmlie5.idc.renesas.com with ESMTP; 08 Jul 2025 18:27:57 +0900 Received: from [127.0.1.1] (unknown [10.226.78.19]) by relmlir5.idc.renesas.com (Postfix) with ESMTP id 5630B400A8B4; Tue, 8 Jul 2025 18:27:54 +0900 (JST) From: Michael Dege Date: Tue, 08 Jul 2025 11:27:38 +0200 Subject: [PATCH v2 2/4] net: renesas: rswitch: configure default ageing time Precedence: bulk X-Mailing-List: linux-kernel@vger.kernel.org List-Id: List-Subscribe: List-Unsubscribe: MIME-Version: 1.0 Content-Type: text/plain; charset="utf-8" Content-Transfer-Encoding: quoted-printable Message-Id: <20250708-add_l2_switching-v2-2-f91f5556617a@renesas.com> References: <20250708-add_l2_switching-v2-0-f91f5556617a@renesas.com> In-Reply-To: <20250708-add_l2_switching-v2-0-f91f5556617a@renesas.com> To: Yoshihiro Shimoda , =?utf-8?q?Niklas_S=C3=B6derlund?= , Paul Barker , Andrew Lunn , "David S. Miller" , Eric Dumazet , Jakub Kicinski , Paolo Abeni Cc: netdev@vger.kernel.org, linux-renesas-soc@vger.kernel.org, linux-kernel@vger.kernel.org, Michael Dege , Nikita Yushchenko X-Mailer: b4 0.14.2 X-Developer-Signature: v=1; a=ed25519-sha256; t=1751966866; l=2858; i=michael.dege@renesas.com; s=20250523; h=from:subject:message-id; bh=KVrzRmQGG2cdaeFhNKeIxvEvNE+9YXP1pbh5qNJxgq8=; b=TVnx45njwCp5BH422RmcAWnWYLfBWfhSbieDx2qYNcrjlsh8qsDkLLtd6co8er8O9ZfNhgnQU 0IBwPdg3H8lCbYhmqbCKrqcjihxRJfmovVNoPK2t8AmcQzhYmZNmn8V X-Developer-Key: i=michael.dege@renesas.com; a=ed25519; pk=+gYTlVQ3/MlOju88OuKnXA7MlapP4lYqJn1F81HZGSo= Enable MAC ageing by setting up the timer and setting the ageging time to the default of 300s. Signed-off-by: Michael Dege --- drivers/net/ethernet/renesas/rswitch.h | 13 ++++++++++++- drivers/net/ethernet/renesas/rswitch_main.c | 11 ++++++++++- 2 files changed, 22 insertions(+), 2 deletions(-) diff --git a/drivers/net/ethernet/renesas/rswitch.h b/drivers/net/ethernet/= renesas/rswitch.h index 532192cbca4b520e06a7e35653929d8364f1ccb2..feb62b99bceb50e1d68345ff9eb= a581f7c38edbe 100644 --- a/drivers/net/ethernet/renesas/rswitch.h +++ b/drivers/net/ethernet/renesas/rswitch.h @@ -1,7 +1,7 @@ /* SPDX-License-Identifier: GPL-2.0 */ /* Renesas Ethernet Switch device driver * - * Copyright (C) 2022 Renesas Electronics Corporation + * Copyright (C) 2022-2025 Renesas Electronics Corporation */ =20 #ifndef __RSWITCH_H__ @@ -826,6 +826,17 @@ enum rswitch_gwca_mode { =20 #define FWPBFCSDC(j, i) (FWPBFCSDC00 + (i) * 0x10 + (j) * 0x04) =20 +#define FWMACAGUSPC_MACAGUSP GENMASK(9, 0) +#define FWMACAGC_MACAGT GENMASK(15, 0) +#define FWMACAGC_MACAGE BIT(16) +#define FWMACAGC_MACAGSL BIT(17) +#define FWMACAGC_MACAGPM BIT(18) +#define FWMACAGC_MACDES BIT(24) +#define FWMACAGC_MACAGOG BIT(28) +#define FWMACAGC_MACDESOG BIT(29) + +#define RSW_AGEING_TIME 300 + /* TOP */ #define TPEMIMC7(queue) (TPEMIMC70 + (queue) * 4) =20 diff --git a/drivers/net/ethernet/renesas/rswitch_main.c b/drivers/net/ethe= rnet/renesas/rswitch_main.c index aba772e14555d30891dc74a5a123121dad77e92b..2474271cac7f057fffb472131f5= a7a72a0fa9a87 100644 --- a/drivers/net/ethernet/renesas/rswitch_main.c +++ b/drivers/net/ethernet/renesas/rswitch_main.c @@ -1,7 +1,7 @@ // SPDX-License-Identifier: GPL-2.0 /* Renesas Ethernet Switch device driver * - * Copyright (C) 2022 Renesas Electronics Corporation + * Copyright (C) 2022-2025 Renesas Electronics Corporation */ =20 #include @@ -113,6 +113,7 @@ static void rswitch_fwd_init(struct rswitch_private *pr= iv) { u32 all_ports_mask =3D GENMASK(RSWITCH_NUM_AGENTS - 1, 0); unsigned int i; + u32 reg_val; =20 /* Start with empty configuration */ for (i =3D 0; i < RSWITCH_NUM_AGENTS; i++) { @@ -128,6 +129,14 @@ static void rswitch_fwd_init(struct rswitch_private *p= riv) iowrite32(0, priv->addr + FWPBFC(i)); } =20 + /* Configure MAC table aging */ + rswitch_modify(priv->addr, FWMACAGUSPC, FWMACAGUSPC_MACAGUSP, + FIELD_PREP(FWMACAGUSPC_MACAGUSP, 0x140)); + + reg_val =3D FIELD_PREP(FWMACAGC_MACAGT, RSW_AGEING_TIME); + reg_val |=3D FWMACAGC_MACAGE | FWMACAGC_MACAGSL; + iowrite32(reg_val, priv->addr + FWMACAGC); + /* For enabled ETHA ports, setup port based forwarding */ rswitch_for_each_enabled_port(priv, i) { /* Port based forwarding from port i to GWCA port */ --=20 2.49.0 From nobody Tue Oct 7 17:48:35 2025 Received: from relmlie5.idc.renesas.com (relmlor1.renesas.com [210.160.252.171]) by smtp.subspace.kernel.org (Postfix) with ESMTP id 0DFC2263899; Tue, 8 Jul 2025 09:28:01 +0000 (UTC) Authentication-Results: smtp.subspace.kernel.org; arc=none smtp.client-ip=210.160.252.171 ARC-Seal: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1751966884; cv=none; b=qQPUlsfTnCpvBvtpguy/5qoG41yCvrn1f5tGkOG28mOMeoYH9Pb4VcnJ6dJtSJF5dvE4RYfpSwED97Ll+uIphUUAs6ZFZ2l4Wx+2dFB9fKulU6Pvj3T5B6fPmWuidJBMniMzc9gIVeyQbYgZpZNVhpyAJ74sNV1txQhpZbWvFp0= ARC-Message-Signature: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1751966884; c=relaxed/simple; bh=B9QUYWKydm00LUhWQwB4VyayUI8LgbxHagDVX97PLJs=; h=From:Date:Subject:MIME-Version:Content-Type:Message-Id:References: In-Reply-To:To:Cc; b=FQY4b1/dDOWr4NANtaaiZiYnqeLGEksGmSJXyKviyJ8Lvb54losxoLS3wJ+uTPLbeOdc+ujCmUOLs23xn6ssodt63VDoVynxM4jk81mDdCXiCKMlrDCRUc5p7j0eY/mlmv5qLxf7bO+0cJwyHewmfgQKA6sIeVmK6bGMnUl2y1U= ARC-Authentication-Results: i=1; smtp.subspace.kernel.org; dmarc=pass (p=none dis=none) header.from=renesas.com; spf=pass smtp.mailfrom=renesas.com; arc=none smtp.client-ip=210.160.252.171 Authentication-Results: smtp.subspace.kernel.org; dmarc=pass (p=none dis=none) header.from=renesas.com Authentication-Results: smtp.subspace.kernel.org; spf=pass smtp.mailfrom=renesas.com X-CSE-ConnectionGUID: Hevlegq0RJeSQl3xq8tCmA== X-CSE-MsgGUID: COWeINncQXy2thCFtLMgUg== Received: from unknown (HELO relmlir5.idc.renesas.com) ([10.200.68.151]) by relmlie5.idc.renesas.com with ESMTP; 08 Jul 2025 18:28:01 +0900 Received: from [127.0.1.1] (unknown [10.226.78.19]) by relmlir5.idc.renesas.com (Postfix) with ESMTP id 334E64009640; Tue, 8 Jul 2025 18:27:57 +0900 (JST) From: Michael Dege Date: Tue, 08 Jul 2025 11:27:39 +0200 Subject: [PATCH v2 3/4] net: renesas: rswitch: add offloading for L2 switching Precedence: bulk X-Mailing-List: linux-kernel@vger.kernel.org List-Id: List-Subscribe: List-Unsubscribe: MIME-Version: 1.0 Content-Type: text/plain; charset="utf-8" Content-Transfer-Encoding: quoted-printable Message-Id: <20250708-add_l2_switching-v2-3-f91f5556617a@renesas.com> References: <20250708-add_l2_switching-v2-0-f91f5556617a@renesas.com> In-Reply-To: <20250708-add_l2_switching-v2-0-f91f5556617a@renesas.com> To: Yoshihiro Shimoda , =?utf-8?q?Niklas_S=C3=B6derlund?= , Paul Barker , Andrew Lunn , "David S. Miller" , Eric Dumazet , Jakub Kicinski , Paolo Abeni Cc: netdev@vger.kernel.org, linux-renesas-soc@vger.kernel.org, linux-kernel@vger.kernel.org, Michael Dege , Nikita Yushchenko X-Mailer: b4 0.14.2 X-Developer-Signature: v=1; a=ed25519-sha256; t=1751966866; l=20701; i=michael.dege@renesas.com; s=20250523; h=from:subject:message-id; bh=B9QUYWKydm00LUhWQwB4VyayUI8LgbxHagDVX97PLJs=; b=epRKjedMAILrKVuVxn7cP7ZD+/bQbtiajfcGxXpilDzHEyXbXXd/w/VA7KmKIlnyHTSO0xa9u NVsJMvwnpY3CQIS9pIQLlWqLn4VCIXapqNSIMGwKLkcpNaVOddBPr70 X-Developer-Key: i=michael.dege@renesas.com; a=ed25519; pk=+gYTlVQ3/MlOju88OuKnXA7MlapP4lYqJn1F81HZGSo= This commit adds hardware offloading for L2 switching on R-Car S4. On S4 brdev is limited to one per-device (not per port). Reasoning is that hw L2 forwarding support lacks any sort of source port based filtering, which makes it unusable to offload more than one bridge device. Either you allow hardware to forward destination MAC to a port, or you have to send it to CPU. You can't make it forward only if src and dst ports are in the same brdev. Signed-off-by: Michael Dege Signed-off-by: Nikita Yushchenko --- drivers/net/ethernet/renesas/Makefile | 2 +- drivers/net/ethernet/renesas/rswitch.h | 29 ++- drivers/net/ethernet/renesas/rswitch_l2.c | 318 ++++++++++++++++++++++++= ++++ drivers/net/ethernet/renesas/rswitch_l2.h | 15 ++ drivers/net/ethernet/renesas/rswitch_main.c | 77 ++++++- 5 files changed, 436 insertions(+), 5 deletions(-) diff --git a/drivers/net/ethernet/renesas/Makefile b/drivers/net/ethernet/r= enesas/Makefile index 6222298bb5582b7091cf8de76acb83ac7dd39c11..d63e0c61bb68a9993d388967aea= 9e1d50f6a95be 100644 --- a/drivers/net/ethernet/renesas/Makefile +++ b/drivers/net/ethernet/renesas/Makefile @@ -8,7 +8,7 @@ obj-$(CONFIG_SH_ETH) +=3D sh_eth.o ravb-objs :=3D ravb_main.o ravb_ptp.o obj-$(CONFIG_RAVB) +=3D ravb.o =20 -rswitch-objs :=3D rswitch_main.o +rswitch-objs :=3D rswitch_main.o rswitch_l2.o obj-$(CONFIG_RENESAS_ETHER_SWITCH) +=3D rswitch.o =20 obj-$(CONFIG_RENESAS_GEN4_PTP) +=3D rcar_gen4_ptp.o diff --git a/drivers/net/ethernet/renesas/rswitch.h b/drivers/net/ethernet/= renesas/rswitch.h index feb62b99bceb50e1d68345ff9eba581f7c38edbe..faf6c53062fb339c2de6b1c77f3= 9ba1a884878c1 100644 --- a/drivers/net/ethernet/renesas/rswitch.h +++ b/drivers/net/ethernet/renesas/rswitch.h @@ -8,12 +8,18 @@ #define __RSWITCH_H__ =20 #include +#include + #include "rcar_gen4_ptp.h" =20 #define RSWITCH_MAX_NUM_QUEUES 128 =20 #define RSWITCH_NUM_AGENTS 5 #define RSWITCH_NUM_PORTS 3 + +#define rswitch_for_all_ports(_priv, _rdev) \ + list_for_each_entry(_rdev, &_priv->port_list, list) + #define rswitch_for_each_enabled_port(priv, i) \ for (i =3D 0; i < RSWITCH_NUM_PORTS; i++) \ if (priv->rdev[i]->disabled) \ @@ -809,7 +815,8 @@ enum rswitch_gwca_mode { #define FWPC0_IP4EA BIT(10) #define FWPC0_IPDSA BIT(12) #define FWPC0_IPHLA BIT(18) -#define FWPC0_MACSDA BIT(20) +#define FWPC0_MACDSA BIT(20) +#define FWPC0_MACSSA BIT(23) #define FWPC0_MACHLA BIT(26) #define FWPC0_MACHMA BIT(27) #define FWPC0_VLANSA BIT(28) @@ -820,12 +827,18 @@ enum rswitch_gwca_mode { =20 #define FWPC2(i) (FWPC20 + (i) * 0x10) #define FWCP2_LTWFW GENMASK(16 + (RSWITCH_NUM_AGENTS - 1), 16) +#define FWCP2_LTWFW_MASK GENMASK(16 + (RSWITCH_NUM_AGENTS - 1), 16) =20 #define FWPBFC(i) (FWPBFC0 + (i) * 0x10) #define FWPBFC_PBDV GENMASK(RSWITCH_NUM_AGENTS - 1, 0) =20 #define FWPBFCSDC(j, i) (FWPBFCSDC00 + (i) * 0x10 + (j) * 0x04) =20 +#define FWMACHEC_MACHMUE_MASK GENMASK(26, 16) + +#define FWMACTIM_MACTIOG BIT(0) +#define FWMACTIM_MACTR BIT(1) + #define FWMACAGUSPC_MACAGUSP GENMASK(9, 0) #define FWMACAGC_MACAGT GENMASK(15, 0) #define FWMACAGC_MACAGE BIT(16) @@ -1005,10 +1018,18 @@ struct rswitch_device { DECLARE_BITMAP(ts_skb_used, TS_TAGS_PER_PORT); bool disabled; =20 + struct list_head list; + int port; struct rswitch_etha *etha; struct device_node *np_port; struct phy *serdes; + + struct net_device *brdev; /* master bridge device */ + unsigned int learning_requested : 1; + unsigned int learning_offloaded : 1; + unsigned int forwarding_requested : 1; + unsigned int forwarding_offloaded : 1; }; =20 struct rswitch_mfwd_mac_table_entry { @@ -1033,11 +1054,17 @@ struct rswitch_private { struct rswitch_etha etha[RSWITCH_NUM_PORTS]; struct rswitch_mfwd mfwd; =20 + struct list_head port_list; + spinlock_t lock; /* lock interrupt registers' control */ struct clk *clk; =20 bool etha_no_runtime_change; bool gwca_halt; + struct net_device *offload_brdev; }; =20 +bool is_rdev(const struct net_device *ndev); +void rswitch_modify(void __iomem *addr, enum rswitch_reg reg, u32 clear, u= 32 set); + #endif /* #ifndef __RSWITCH_H__ */ diff --git a/drivers/net/ethernet/renesas/rswitch_l2.c b/drivers/net/ethern= et/renesas/rswitch_l2.c new file mode 100644 index 0000000000000000000000000000000000000000..4177601000016b61def64735710= 052ba25222ff2 --- /dev/null +++ b/drivers/net/ethernet/renesas/rswitch_l2.c @@ -0,0 +1,318 @@ +// SPDX-License-Identifier: GPL-2.0 +/* Renesas Ethernet Switch device driver + * + * Copyright (C) 2025 Renesas Electronics Corporation + */ + +#include +#include +#include +#include +#include + +#include "rswitch.h" +#include "rswitch_l2.h" + +static bool rdev_for_l2_offload(struct rswitch_device *rdev) +{ + return rdev->priv->offload_brdev && + rdev->brdev =3D=3D rdev->priv->offload_brdev && + (test_bit(rdev->port, rdev->priv->opened_ports)); +} + +void rswitch_update_l2_offload(struct rswitch_private *priv) +{ + bool learning_needed, forwarding_needed; + unsigned int all_ports_mask, fwd_mask; + struct rswitch_device *rdev; + + /* calculate fwd_mask with zeroes in bits corresponding to ports that + * shall participate in hardware forwarding + */ + all_ports_mask =3D GENMASK(RSWITCH_NUM_AGENTS - 1, 0); + fwd_mask =3D all_ports_mask; + + rswitch_for_all_ports(priv, rdev) { + if (rdev_for_l2_offload(rdev) && rdev->forwarding_requested) + fwd_mask &=3D ~BIT(rdev->port); + } + + rswitch_for_all_ports(priv, rdev) { + if (rdev_for_l2_offload(rdev)) { + learning_needed =3D rdev->learning_requested; + forwarding_needed =3D rdev->forwarding_requested; + } else { + learning_needed =3D false; + forwarding_needed =3D false; + } + + if (!rdev->learning_offloaded && learning_needed) { + rswitch_modify(priv->addr, FWPC0(rdev->port), + 0, + FWPC0_MACSSA | FWPC0_MACHLA | FWPC0_MACHMA); + + rdev->learning_offloaded =3D true; + netdev_info(rdev->ndev, "starting hw learning\n"); + } + + if (rdev->learning_offloaded && !learning_needed) { + rswitch_modify(priv->addr, FWPC0(rdev->port), + FWPC0_MACSSA | FWPC0_MACHLA | FWPC0_MACHMA, + 0); + + rdev->learning_offloaded =3D false; + netdev_info(rdev->ndev, "stopping hw learning\n"); + } + + if (forwarding_needed) { + /* Update allowed offload destinations even for ports + * with L2 offload enabled earlier. + * + * Do not allow L2 forwarding to self for hw port. + */ + iowrite32(FIELD_PREP(FWCP2_LTWFW_MASK, fwd_mask | BIT(rdev->port)), + priv->addr + FWPC2(rdev->port)); + + if (!rdev->forwarding_offloaded) { + rswitch_modify(priv->addr, FWPC0(rdev->port), + 0, + FWPC0_MACDSA); + + rdev->forwarding_offloaded =3D true; + netdev_info(rdev->ndev, + "starting hw forwarding\n"); + } + } else if (rdev->forwarding_offloaded) { + iowrite32(FIELD_PREP(FWCP2_LTWFW_MASK, fwd_mask | BIT(rdev->port)), + priv->addr + FWPC2(rdev->port)); + + rswitch_modify(priv->addr, FWPC0(rdev->port), + FWPC0_MACDSA, + 0); + + rdev->forwarding_offloaded =3D false; + netdev_info(rdev->ndev, "stopping hw forwarding\n"); + } + } +} + +static void rswitch_update_offload_brdev(struct rswitch_private *priv, + bool force_update_l2_offload) +{ + struct net_device *offload_brdev =3D NULL; + struct rswitch_device *rdev, *rdev2; + + rswitch_for_all_ports(priv, rdev) { + if (!rdev->brdev) + continue; + rswitch_for_all_ports(priv, rdev2) { + if (rdev2 =3D=3D rdev) + break; + if (rdev2->brdev =3D=3D rdev->brdev) { + offload_brdev =3D rdev->brdev; + break; + } + } + if (offload_brdev) + break; + } + + if (offload_brdev =3D=3D priv->offload_brdev) { + if (offload_brdev && force_update_l2_offload) + rswitch_update_l2_offload(priv); + return; + } + + if (offload_brdev && !priv->offload_brdev) + dev_dbg(&priv->pdev->dev, "starting l2 offload for %s\n", + netdev_name(offload_brdev)); + else if (!offload_brdev && priv->offload_brdev) + dev_dbg(&priv->pdev->dev, "stopping l2 offload for %s\n", + netdev_name(priv->offload_brdev)); + else + dev_dbg(&priv->pdev->dev, + "changing l2 offload from %s to %s\n", + netdev_name(priv->offload_brdev), + netdev_name(offload_brdev)); + + priv->offload_brdev =3D offload_brdev; + + rswitch_update_l2_offload(priv); +} + +static bool rswitch_port_check(const struct net_device *ndev) +{ + return is_rdev(ndev); +} + +static void rswitch_port_update_brdev(struct net_device *ndev, + struct net_device *brdev) +{ + struct rswitch_device *rdev; + + if (!is_rdev(ndev)) + return; + + rdev =3D netdev_priv(ndev); + rdev->brdev =3D brdev; + rswitch_update_offload_brdev(rdev->priv, false); +} + +static int rswitch_port_update_stp_state(struct net_device *ndev, u8 stp_s= tate) +{ + struct rswitch_device *rdev; + + if (!is_rdev(ndev)) + return -ENODEV; + + rdev =3D netdev_priv(ndev); + rdev->learning_requested =3D (stp_state =3D=3D BR_STATE_LEARNING || + stp_state =3D=3D BR_STATE_FORWARDING); + rdev->forwarding_requested =3D (stp_state =3D=3D BR_STATE_FORWARDING); + rswitch_update_l2_offload(rdev->priv); + + return 0; +} + +static int rswitch_netdevice_event(struct notifier_block *nb, + unsigned long event, void *ptr) +{ + struct net_device *ndev =3D netdev_notifier_info_to_dev(ptr); + struct netdev_notifier_changeupper_info *info; + struct net_device *brdev; + + if (!rswitch_port_check(ndev)) + return NOTIFY_DONE; + if (event !=3D NETDEV_CHANGEUPPER) + return NOTIFY_DONE; + + info =3D ptr; + + if (netif_is_bridge_master(info->upper_dev)) { + brdev =3D info->linking ? info->upper_dev : NULL; + rswitch_port_update_brdev(ndev, brdev); + } + + return NOTIFY_OK; +} + +static int rswitch_port_attr_set(struct net_device *ndev, const void *ctx, + const struct switchdev_attr *attr, + struct netlink_ext_ack *extack) +{ + switch (attr->id) { + case SWITCHDEV_ATTR_ID_PORT_STP_STATE: + return rswitch_port_update_stp_state(ndev, attr->u.stp_state); + default: + return -EOPNOTSUPP; + } +} + +static int rswitch_port_obj_add(struct net_device *ndev, const void *ctx, + const struct switchdev_obj *obj, + struct netlink_ext_ack *extack) +{ + return -EOPNOTSUPP; +} + +static int rswitch_port_obj_del(struct net_device *ndev, const void *ctx, + const struct switchdev_obj *obj) +{ + return -EOPNOTSUPP; +} + +static int rswitch_switchdev_event(struct notifier_block *nb, + unsigned long event, void *ptr) +{ + struct net_device *ndev =3D switchdev_notifier_info_to_dev(ptr); + int ret; + + if (event =3D=3D SWITCHDEV_PORT_ATTR_SET) { + ret =3D switchdev_handle_port_attr_set(ndev, ptr, + rswitch_port_check, + rswitch_port_attr_set); + return notifier_from_errno(ret); + } + + if (!rswitch_port_check(ndev)) + return NOTIFY_DONE; + + return notifier_from_errno(-EOPNOTSUPP); +} + +static int rswitch_switchdev_blocking_event(struct notifier_block *nb, + unsigned long event, void *ptr) +{ + struct net_device *ndev =3D switchdev_notifier_info_to_dev(ptr); + int ret; + + switch (event) { + case SWITCHDEV_PORT_OBJ_ADD: + ret =3D switchdev_handle_port_obj_add(ndev, ptr, + rswitch_port_check, + rswitch_port_obj_add); + break; + case SWITCHDEV_PORT_OBJ_DEL: + ret =3D switchdev_handle_port_obj_del(ndev, ptr, + rswitch_port_check, + rswitch_port_obj_del); + break; + case SWITCHDEV_PORT_ATTR_SET: + ret =3D switchdev_handle_port_attr_set(ndev, ptr, + rswitch_port_check, + rswitch_port_attr_set); + break; + default: + if (!rswitch_port_check(ndev)) + return NOTIFY_DONE; + ret =3D -EOPNOTSUPP; + } + + return notifier_from_errno(ret); +} + +static struct notifier_block rswitch_netdevice_nb =3D { + .notifier_call =3D rswitch_netdevice_event, +}; + +static struct notifier_block rswitch_switchdev_nb =3D { + .notifier_call =3D rswitch_switchdev_event, +}; + +static struct notifier_block rswitch_switchdev_blocking_nb =3D { + .notifier_call =3D rswitch_switchdev_blocking_event, +}; + +int rswitch_register_notifiers(void) +{ + int ret; + + ret =3D register_netdevice_notifier(&rswitch_netdevice_nb); + if (ret) + goto register_netdevice_notifier_failed; + + ret =3D register_switchdev_notifier(&rswitch_switchdev_nb); + if (ret) + goto register_switchdev_notifier_failed; + + ret =3D register_switchdev_blocking_notifier(&rswitch_switchdev_blocking_= nb); + if (ret) + goto register_switchdev_blocking_notifier_failed; + + return 0; + +register_switchdev_blocking_notifier_failed: + unregister_switchdev_notifier(&rswitch_switchdev_nb); +register_switchdev_notifier_failed: + unregister_netdevice_notifier(&rswitch_netdevice_nb); +register_netdevice_notifier_failed: + + return ret; +} + +void rswitch_unregister_notifiers(void) +{ + unregister_switchdev_blocking_notifier(&rswitch_switchdev_blocking_nb); + unregister_switchdev_notifier(&rswitch_switchdev_nb); + unregister_netdevice_notifier(&rswitch_netdevice_nb); +} diff --git a/drivers/net/ethernet/renesas/rswitch_l2.h b/drivers/net/ethern= et/renesas/rswitch_l2.h new file mode 100644 index 0000000000000000000000000000000000000000..57050ede8f31848cde5a497811a= 6ee1b60dedc65 --- /dev/null +++ b/drivers/net/ethernet/renesas/rswitch_l2.h @@ -0,0 +1,15 @@ +/* SPDX-License-Identifier: GPL-2.0 */ +/* Renesas Ethernet Switch device driver + * + * Copyright (C) 2025 Renesas Electronics Corporation + */ + +#ifndef __RSWITCH_L2_H__ +#define __RSWITCH_L2_H__ + +void rswitch_update_l2_offload(struct rswitch_private *priv); + +int rswitch_register_notifiers(void); +void rswitch_unregister_notifiers(void); + +#endif /* #ifndef __RSWITCH_L2_H__ */ diff --git a/drivers/net/ethernet/renesas/rswitch_main.c b/drivers/net/ethe= rnet/renesas/rswitch_main.c index 2474271cac7f057fffb472131f5a7a72a0fa9a87..7814bd08ee16ca32ba935a19ea2= a1cd1fd41a236 100644 --- a/drivers/net/ethernet/renesas/rswitch_main.c +++ b/drivers/net/ethernet/renesas/rswitch_main.c @@ -8,8 +8,11 @@ #include #include #include +#include +#include #include #include +#include #include #include #include @@ -25,6 +28,7 @@ #include =20 #include "rswitch.h" +#include "rswitch_l2.h" =20 static int rswitch_reg_wait(void __iomem *addr, u32 offs, u32 mask, u32 ex= pected) { @@ -34,7 +38,7 @@ static int rswitch_reg_wait(void __iomem *addr, u32 offs,= u32 mask, u32 expected 1, RSWITCH_TIMEOUT_US); } =20 -static void rswitch_modify(void __iomem *addr, enum rswitch_reg reg, u32 c= lear, u32 set) +void rswitch_modify(void __iomem *addr, enum rswitch_reg reg, u32 clear, u= 32 set) { iowrite32((ioread32(addr + reg) & ~clear) | set, addr + reg); } @@ -109,11 +113,12 @@ static void rswitch_top_init(struct rswitch_private *= priv) } =20 /* Forwarding engine block (MFWD) */ -static void rswitch_fwd_init(struct rswitch_private *priv) +static int rswitch_fwd_init(struct rswitch_private *priv) { u32 all_ports_mask =3D GENMASK(RSWITCH_NUM_AGENTS - 1, 0); unsigned int i; u32 reg_val; + int ret; =20 /* Start with empty configuration */ for (i =3D 0; i < RSWITCH_NUM_AGENTS; i++) { @@ -149,6 +154,17 @@ static void rswitch_fwd_init(struct rswitch_private *p= riv) =20 /* For GWCA port, allow direct descriptor forwarding */ rswitch_modify(priv->addr, FWPC1(priv->gwca.index), FWPC1_DDE, FWPC1_DDE); + + /* Initialize hardware L2 forwarding table */ + + /* Allow entire table to be used for "unsecure" entries */ + rswitch_modify(priv->addr, FWMACHEC, 0, FWMACHEC_MACHMUE_MASK); + + /* Initialize MAC hash table */ + iowrite32(FWMACTIM_MACTIOG, priv->addr + FWMACTIM); + ret =3D rswitch_reg_wait(priv->addr, FWMACTIM, FWMACTIM_MACTIOG, 0); + + return ret; } =20 /* Gateway CPU agent block (GWCA) */ @@ -1611,6 +1627,9 @@ static int rswitch_open(struct net_device *ndev) =20 netif_start_queue(ndev); =20 + if (rdev->brdev) + rswitch_update_l2_offload(rdev->priv); + return 0; }; =20 @@ -1633,6 +1652,9 @@ static int rswitch_stop(struct net_device *ndev) =20 napi_disable(&rdev->napi); =20 + if (rdev->brdev) + rswitch_update_l2_offload(rdev->priv); + if (bitmap_empty(rdev->priv->opened_ports, RSWITCH_NUM_PORTS)) iowrite32(GWCA_TS_IRQ_BIT, rdev->priv->addr + GWTSDID); =20 @@ -1859,16 +1881,46 @@ static int rswitch_eth_ioctl(struct net_device *nde= v, struct ifreq *req, int cmd } } =20 +static int rswitch_get_port_parent_id(struct net_device *ndev, + struct netdev_phys_item_id *ppid) +{ + struct rswitch_device *rdev =3D netdev_priv(ndev); + const char *name; + + name =3D dev_name(&rdev->priv->pdev->dev); + ppid->id_len =3D min_t(size_t, strlen(name), sizeof(ppid->id_len)); + memcpy(ppid->id, name, ppid->id_len); + + return 0; +} + +static int rswitch_get_phys_port_name(struct net_device *ndev, + char *name, size_t len) +{ + struct rswitch_device *rdev =3D netdev_priv(ndev); + + snprintf(name, len, "tsn%d", rdev->port); + + return 0; +} + static const struct net_device_ops rswitch_netdev_ops =3D { .ndo_open =3D rswitch_open, .ndo_stop =3D rswitch_stop, .ndo_start_xmit =3D rswitch_start_xmit, .ndo_get_stats =3D rswitch_get_stats, .ndo_eth_ioctl =3D rswitch_eth_ioctl, + .ndo_get_port_parent_id =3D rswitch_get_port_parent_id, + .ndo_get_phys_port_name =3D rswitch_get_phys_port_name, .ndo_validate_addr =3D eth_validate_addr, .ndo_set_mac_address =3D eth_mac_addr, }; =20 +bool is_rdev(const struct net_device *ndev) +{ + return (ndev->netdev_ops =3D=3D &rswitch_netdev_ops); +} + static int rswitch_get_ts_info(struct net_device *ndev, struct kernel_etht= ool_ts_info *info) { struct rswitch_device *rdev =3D netdev_priv(ndev); @@ -1968,6 +2020,8 @@ static int rswitch_device_alloc(struct rswitch_privat= e *priv, unsigned int index if (err < 0) goto out_txdmac; =20 + list_add_tail(&rdev->list, &priv->port_list); + return 0; =20 out_txdmac: @@ -1987,6 +2041,7 @@ static void rswitch_device_free(struct rswitch_privat= e *priv, unsigned int index struct rswitch_device *rdev =3D priv->rdev[index]; struct net_device *ndev =3D rdev->ndev; =20 + list_del(&rdev->list); rswitch_txdmac_free(ndev); rswitch_rxdmac_free(ndev); of_node_put(rdev->np_port); @@ -2033,7 +2088,9 @@ static int rswitch_init(struct rswitch_private *priv) } } =20 - rswitch_fwd_init(priv); + err =3D rswitch_fwd_init(priv); + if (err < 0) + goto err_fwd_init; =20 err =3D rcar_gen4_ptp_register(priv->ptp_priv, RCAR_GEN4_PTP_REG_LAYOUT, clk_get_rate(priv->clk)); @@ -2082,6 +2139,7 @@ static int rswitch_init(struct rswitch_private *priv) err_gwca_request_irq: rcar_gen4_ptp_unregister(priv->ptp_priv); =20 +err_fwd_init: err_ptp_register: for (i =3D 0; i < RSWITCH_NUM_PORTS; i++) rswitch_device_free(priv, i); @@ -2116,6 +2174,7 @@ static int renesas_eth_sw_probe(struct platform_devic= e *pdev) priv =3D devm_kzalloc(&pdev->dev, sizeof(*priv), GFP_KERNEL); if (!priv) return -ENOMEM; + spin_lock_init(&priv->lock); =20 priv->clk =3D devm_clk_get(&pdev->dev, NULL); @@ -2153,6 +2212,8 @@ static int renesas_eth_sw_probe(struct platform_devic= e *pdev) if (!priv->gwca.queues) return -ENOMEM; =20 + INIT_LIST_HEAD(&priv->port_list); + pm_runtime_enable(&pdev->dev); pm_runtime_get_sync(&pdev->dev); =20 @@ -2163,6 +2224,15 @@ static int renesas_eth_sw_probe(struct platform_devi= ce *pdev) return ret; } =20 + if (list_empty(&priv->port_list)) + dev_warn(&pdev->dev, "could not initialize any ports\n"); + + ret =3D rswitch_register_notifiers(); + if (ret) { + dev_err(&pdev->dev, "could not register notifiers\n"); + return ret; + } + device_set_wakeup_capable(&pdev->dev, 1); =20 return ret; @@ -2196,6 +2266,7 @@ static void renesas_eth_sw_remove(struct platform_dev= ice *pdev) { struct rswitch_private *priv =3D platform_get_drvdata(pdev); =20 + rswitch_unregister_notifiers(); rswitch_deinit(priv); =20 pm_runtime_put(&pdev->dev); --=20 2.49.0 From nobody Tue Oct 7 17:48:35 2025 Received: from relmlie5.idc.renesas.com (relmlor1.renesas.com [210.160.252.171]) by smtp.subspace.kernel.org (Postfix) with ESMTP id 179D0267B9B; Tue, 8 Jul 2025 09:28:06 +0000 (UTC) Authentication-Results: smtp.subspace.kernel.org; arc=none smtp.client-ip=210.160.252.171 ARC-Seal: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1751966888; cv=none; b=uLLuL8evQyVLtVruekyeJWZd+Ni8771r4kJQpAoioJ6BR0CZsiK3N5XS8whZ+H+c8vcpdVY289mpDm6/WAsTFYf8wkv3QZt9DOV2C/cJNSGB3wyKWnjsxO0j18OLNr/ZJCAC5hyQO/fsLlouiVlf5ml1Ep7qCRtlhkHnav9iZl8= ARC-Message-Signature: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1751966888; c=relaxed/simple; bh=sBbFMN6RILra4rzHuBM5P/MUPPZUf2xD4RniwCpXdjA=; h=From:Date:Subject:MIME-Version:Content-Type:Message-Id:References: In-Reply-To:To:Cc; b=QVdrxuj6T5Y5rXevenviut4nwJ3YyUPEJOd+QlQx109AXkqncMqScmAkBuFlylzTNAjNSPnsslu9vTyVVJtewcjuVNKcCZy6Z4caZJxY4qb+06oALLt7MVijouMEsfdOZmigFHOEhnwfHXgmARzlFlcBNg5KxpMh3o1hVmo0h2c= ARC-Authentication-Results: i=1; smtp.subspace.kernel.org; dmarc=pass (p=none dis=none) header.from=renesas.com; spf=pass smtp.mailfrom=renesas.com; arc=none smtp.client-ip=210.160.252.171 Authentication-Results: smtp.subspace.kernel.org; dmarc=pass (p=none dis=none) header.from=renesas.com Authentication-Results: smtp.subspace.kernel.org; spf=pass smtp.mailfrom=renesas.com X-CSE-ConnectionGUID: jXKrjl2hR0igmWBENkQuTQ== X-CSE-MsgGUID: iPszyIUlRnW924+v0TB4Fg== Received: from unknown (HELO relmlir5.idc.renesas.com) ([10.200.68.151]) by relmlie5.idc.renesas.com with ESMTP; 08 Jul 2025 18:28:05 +0900 Received: from [127.0.1.1] (unknown [10.226.78.19]) by relmlir5.idc.renesas.com (Postfix) with ESMTP id 3FAA54009640; Tue, 8 Jul 2025 18:28:02 +0900 (JST) From: Michael Dege Date: Tue, 08 Jul 2025 11:27:40 +0200 Subject: [PATCH v2 4/4] net: renesas: rswitch: add modifiable ageing time Precedence: bulk X-Mailing-List: linux-kernel@vger.kernel.org List-Id: List-Subscribe: List-Unsubscribe: MIME-Version: 1.0 Content-Type: text/plain; charset="utf-8" Content-Transfer-Encoding: quoted-printable Message-Id: <20250708-add_l2_switching-v2-4-f91f5556617a@renesas.com> References: <20250708-add_l2_switching-v2-0-f91f5556617a@renesas.com> In-Reply-To: <20250708-add_l2_switching-v2-0-f91f5556617a@renesas.com> To: Yoshihiro Shimoda , =?utf-8?q?Niklas_S=C3=B6derlund?= , Paul Barker , Andrew Lunn , "David S. Miller" , Eric Dumazet , Jakub Kicinski , Paolo Abeni Cc: netdev@vger.kernel.org, linux-renesas-soc@vger.kernel.org, linux-kernel@vger.kernel.org, Michael Dege , Nikita Yushchenko X-Mailer: b4 0.14.2 X-Developer-Signature: v=1; a=ed25519-sha256; t=1751966866; l=1737; i=michael.dege@renesas.com; s=20250523; h=from:subject:message-id; bh=sBbFMN6RILra4rzHuBM5P/MUPPZUf2xD4RniwCpXdjA=; b=tICA4vHrDtwTqshXj8EW7ZEi5o7qGvR8rH2UtRXivJQiqUpxmQ9p93nO1+kw3mm8OeODQ6Wz2 OsNwKtg2iNzDSR0imgSGJWbl0RiHt17RGmiHdCGjBEgj6MmEaK5VOUb X-Developer-Key: i=michael.dege@renesas.com; a=ed25519; pk=+gYTlVQ3/MlOju88OuKnXA7MlapP4lYqJn1F81HZGSo= This commit allows the setting of the MAC table aging in the R-Car S4 Rswitch using the SWITCHDEV_ATTR_ID_BRIDGE_AGEING_TIME attribute. Signed-off-by: Michael Dege --- drivers/net/ethernet/renesas/rswitch_l2.c | 21 +++++++++++++++++++++ 1 file changed, 21 insertions(+) diff --git a/drivers/net/ethernet/renesas/rswitch_l2.c b/drivers/net/ethern= et/renesas/rswitch_l2.c index 4177601000016b61def64735710052ba25222ff2..3d47ac668b4f5dfca87a192f2fc= 020597bef115d 100644 --- a/drivers/net/ethernet/renesas/rswitch_l2.c +++ b/drivers/net/ethernet/renesas/rswitch_l2.c @@ -196,6 +196,25 @@ static int rswitch_netdevice_event(struct notifier_blo= ck *nb, return NOTIFY_OK; } =20 +static int rswitch_update_ageing_time(struct net_device *ndev, clock_t tim= e) +{ + struct rswitch_device *rdev =3D netdev_priv(ndev); + u32 reg_val; + + if (!is_rdev(ndev)) + return -ENODEV; + + if (!FIELD_FIT(FWMACAGC_MACAGT, time)) + return -EINVAL; + + rdev =3D netdev_priv(ndev); + reg_val =3D FIELD_PREP(FWMACAGC_MACAGT, time); + reg_val |=3D FWMACAGC_MACAGE | FWMACAGC_MACAGSL; + iowrite32(reg_val, rdev->priv->addr + FWMACAGC); + + return 0; +} + static int rswitch_port_attr_set(struct net_device *ndev, const void *ctx, const struct switchdev_attr *attr, struct netlink_ext_ack *extack) @@ -203,6 +222,8 @@ static int rswitch_port_attr_set(struct net_device *nde= v, const void *ctx, switch (attr->id) { case SWITCHDEV_ATTR_ID_PORT_STP_STATE: return rswitch_port_update_stp_state(ndev, attr->u.stp_state); + case SWITCHDEV_ATTR_ID_BRIDGE_AGEING_TIME: + return rswitch_update_ageing_time(ndev, attr->u.ageing_time); default: return -EOPNOTSUPP; } --=20 2.49.0