* [PATCH net-next 00/10] net: renesas: rswitch: R-Car S4 add HW offloading for layer 3 routing
@ 2025-11-06 12:55 Michael Dege
2025-11-06 12:55 ` [PATCH net-next 01/10] net: renesas: rswitch: cleanup MII settings Michael Dege
` (9 more replies)
0 siblings, 10 replies; 23+ messages in thread
From: Michael Dege @ 2025-11-06 12:55 UTC (permalink / raw)
To: Yoshihiro Shimoda, Andrew Lunn, David S. Miller, Eric Dumazet,
Jakub Kicinski, Paolo Abeni, Richard Cochran,
Niklas Söderlund, Paul Barker, Rob Herring,
Krzysztof Kozlowski, Conor Dooley, Geert Uytterhoeven,
Magnus Damm
Cc: netdev, linux-renesas-soc, linux-kernel, devicetree,
Nikita Yushchenko, Christophe JAILLET, Michael Dege
Hello!
The current R-Car S4 rswitch driver only supports port based fowarding
and L2 switching/bridgeing.
This patch set adds HW offloading for simple L3 routing.
1. Clean up MII settings.
2. enable Phy link status pin
3. renesas,r8a779f0-ether-switch.yaml: add optional property "link-pin"
4. r8a779f4-s4sk.dts add link-pin property
5. r8a779f0-spider-ethernet.dtsi add link-pin property
6. Add MAC address filtering.
7. Fix FWPCx register names in macros
8. Add bit access macros for forwarding engine.
9. Add the L3 driver extension in a separate file. The HW offloading
is automatically configured when a port is configured with an IP
address and set to up state.
10: Update error handling of probe function.
Usage example:
ip addr add 192.168.1.22/24 dev tsn0
ip addr add 192.168.10.22/24 dev tsn1
ip link set tsn0 up
ip link set tsn1 up
echo 1 > /proc/sys/net/ipv4/ip_forward
Layer 3 traffic is now routed by HW from port TSN0 to port TSN1.
Signed-off-by: Nikita Yushchenko <nikita.yoush@cogentembedded.com>
Signed-off-by: Christophe JAILLET <christophe.jaillet@wanadoo.fr>
Signed-off-by: Michael Dege <michael.dege@renesas.com>
---
Christophe JAILLET (1):
net: renesas: rswitch: update error handling of probe
Michael Dege (9):
net: renesas: rswitch: cleanup MII settings
net: renesas: rswitch: enable Phy link status pin
dt-bindings: net: renesas,r8a779f0-ether-switch.yaml: add optional property link-pin
arm64: dts: renesas: r8a779f4-s4sk.dts add link-pin property
arm64: dts: renesas: r8a779f0-spider-ethernet.dtsi add link-pin property
net: renesas: rswitch: add MAC address filtering
net: renesas: rswitch: fix FWPCx register names
net: renesas: rswitch: add bit access macros for forwarding engine
net: renesas: rswitch: add simple l3 routing
.../net/renesas,r8a779f0-ether-switch.yaml | 3 +
.../boot/dts/renesas/r8a779f0-spider-ethernet.dtsi | 3 +
arch/arm64/boot/dts/renesas/r8a779f4-s4sk.dts | 2 +
drivers/net/ethernet/renesas/Makefile | 2 +-
drivers/net/ethernet/renesas/rswitch.h | 230 ++++++-
drivers/net/ethernet/renesas/rswitch_l2.c | 2 +-
drivers/net/ethernet/renesas/rswitch_l3.c | 751 +++++++++++++++++++++
drivers/net/ethernet/renesas/rswitch_l3.h | 24 +
drivers/net/ethernet/renesas/rswitch_main.c | 156 ++++-
9 files changed, 1124 insertions(+), 49 deletions(-)
---
base-commit: 575742822dceb5c57ef25f5cd715e7d0a7b39e9c
change-id: 20250925-add_l3_routing-3cd5c02a499e
Best regards,
--
Michael Dege <michael.dege@renesas.com>
^ permalink raw reply [flat|nested] 23+ messages in thread* [PATCH net-next 01/10] net: renesas: rswitch: cleanup MII settings 2025-11-06 12:55 [PATCH net-next 00/10] net: renesas: rswitch: R-Car S4 add HW offloading for layer 3 routing Michael Dege @ 2025-11-06 12:55 ` Michael Dege 2025-11-06 12:55 ` [PATCH net-next 02/10] net: renesas: rswitch: enable Phy link status pin Michael Dege ` (8 subsequent siblings) 9 siblings, 0 replies; 23+ messages in thread From: Michael Dege @ 2025-11-06 12:55 UTC (permalink / raw) To: Yoshihiro Shimoda, Andrew Lunn, David S. Miller, Eric Dumazet, Jakub Kicinski, Paolo Abeni, Richard Cochran, Niklas Söderlund, Paul Barker, Rob Herring, Krzysztof Kozlowski, Conor Dooley, Geert Uytterhoeven, Magnus Damm Cc: netdev, linux-renesas-soc, linux-kernel, devicetree, Nikita Yushchenko, Christophe JAILLET, Michael Dege Add Phy interface modes and link speeds. Signed-off-by: Michael Dege <michael.dege@renesas.com> --- drivers/net/ethernet/renesas/rswitch.h | 21 ++++++++++++++++----- 1 file changed, 16 insertions(+), 5 deletions(-) diff --git a/drivers/net/ethernet/renesas/rswitch.h b/drivers/net/ethernet/renesas/rswitch.h index a1d4a877e5bd..8168c4cc83fe 100644 --- a/drivers/net/ethernet/renesas/rswitch.h +++ b/drivers/net/ethernet/renesas/rswitch.h @@ -732,15 +732,26 @@ enum rswitch_etha_mode { #define EAVCC_VEM_SC_TAG (0x3 << 16) #define MPIC_PIS GENMASK(2, 0) -#define MPIC_PIS_GMII 2 -#define MPIC_PIS_XGMII 4 #define MPIC_LSC GENMASK(5, 3) -#define MPIC_LSC_100M 1 -#define MPIC_LSC_1G 2 -#define MPIC_LSC_2_5G 3 +#define MPIC_PLSPP BIT(10) #define MPIC_PSMCS GENMASK(22, 16) #define MPIC_PSMHT GENMASK(26, 24) +enum phy_if_select { + MPIC_PIS_MII = 0, + MPIC_PIS_GMII = 2, + MPIC_PIS_XGMII = 4, +}; + +enum link_speed_conf { + MPIC_LSC_10M, + MPIC_LSC_100M, + MPIC_LSC_1G, + MPIC_LSC_2_5G, + MPIC_LSC_5G, + MPIC_LSC_10G, +}; + #define MPSM_PSME BIT(0) #define MPSM_MFF BIT(2) #define MPSM_MMF_C22 0 -- 2.43.0 ^ permalink raw reply related [flat|nested] 23+ messages in thread
* [PATCH net-next 02/10] net: renesas: rswitch: enable Phy link status pin 2025-11-06 12:55 [PATCH net-next 00/10] net: renesas: rswitch: R-Car S4 add HW offloading for layer 3 routing Michael Dege 2025-11-06 12:55 ` [PATCH net-next 01/10] net: renesas: rswitch: cleanup MII settings Michael Dege @ 2025-11-06 12:55 ` Michael Dege 2025-11-07 1:16 ` Andrew Lunn 2025-11-06 12:55 ` [PATCH net-next 03/10] dt-bindings: net: renesas,r8a779f0-ether-switch.yaml: add optional property link-pin Michael Dege ` (7 subsequent siblings) 9 siblings, 1 reply; 23+ messages in thread From: Michael Dege @ 2025-11-06 12:55 UTC (permalink / raw) To: Yoshihiro Shimoda, Andrew Lunn, David S. Miller, Eric Dumazet, Jakub Kicinski, Paolo Abeni, Richard Cochran, Niklas Söderlund, Paul Barker, Rob Herring, Krzysztof Kozlowski, Conor Dooley, Geert Uytterhoeven, Magnus Damm Cc: netdev, linux-renesas-soc, linux-kernel, devicetree, Nikita Yushchenko, Christophe JAILLET, Michael Dege Enable Phy link status pin for boards which support this feature. Signed-off-by: Michael Dege <michael.dege@renesas.com> --- drivers/net/ethernet/renesas/rswitch.h | 1 + drivers/net/ethernet/renesas/rswitch_main.c | 12 ++++++++++-- 2 files changed, 11 insertions(+), 2 deletions(-) diff --git a/drivers/net/ethernet/renesas/rswitch.h b/drivers/net/ethernet/renesas/rswitch.h index 8168c4cc83fe..a65ba10ae435 100644 --- a/drivers/net/ethernet/renesas/rswitch.h +++ b/drivers/net/ethernet/renesas/rswitch.h @@ -960,6 +960,7 @@ struct rswitch_etha { u8 mac_addr[MAX_ADDR_LEN]; int link; int speed; + bool link_pin; /* This hardware could not be initialized twice so that marked * this flag to avoid multiple initialization. diff --git a/drivers/net/ethernet/renesas/rswitch_main.c b/drivers/net/ethernet/renesas/rswitch_main.c index 8d8acc2124b8..dd9a0e7a9d74 100644 --- a/drivers/net/ethernet/renesas/rswitch_main.c +++ b/drivers/net/ethernet/renesas/rswitch_main.c @@ -1192,9 +1192,15 @@ static void rswitch_rmac_setting(struct rswitch_etha *etha, const u8 *mac) static void rswitch_etha_enable_mii(struct rswitch_etha *etha) { - rswitch_modify(etha->addr, MPIC, MPIC_PSMCS | MPIC_PSMHT, + /* PSMCT: PHY station Management capture adjustment in clk cycles */ + /* PSMHT: PHY Station Management Hold Time adjustment in clk cycles */ + /* PSMCS: PHY Station Management Clock selection (clk divider) */ + /* PLSPP: PHY Link Status Pin Plugged */ + + rswitch_modify(etha->addr, MPIC, MPIC_PSMCS | MPIC_PSMHT | MPIC_PLSPP, FIELD_PREP(MPIC_PSMCS, etha->psmcs) | - FIELD_PREP(MPIC_PSMHT, 0x06)); + FIELD_PREP(MPIC_PSMHT, 0x06) | + FIELD_PREP(MPIC_PLSPP, etha->link_pin)); } static int rswitch_etha_hw_init(struct rswitch_etha *etha, const u8 *mac) @@ -1338,6 +1344,8 @@ static int rswitch_etha_get_params(struct rswitch_device *rdev) if (err) return err; + rdev->etha->link_pin = of_property_read_bool(rdev->np_port, "link-pin"); + err = of_property_read_u32(rdev->np_port, "max-speed", &max_speed); if (!err) { rdev->etha->speed = max_speed; -- 2.43.0 ^ permalink raw reply related [flat|nested] 23+ messages in thread
* Re: [PATCH net-next 02/10] net: renesas: rswitch: enable Phy link status pin 2025-11-06 12:55 ` [PATCH net-next 02/10] net: renesas: rswitch: enable Phy link status pin Michael Dege @ 2025-11-07 1:16 ` Andrew Lunn 2025-11-07 13:37 ` Michael Dege 0 siblings, 1 reply; 23+ messages in thread From: Andrew Lunn @ 2025-11-07 1:16 UTC (permalink / raw) To: Michael Dege Cc: Yoshihiro Shimoda, Andrew Lunn, David S. Miller, Eric Dumazet, Jakub Kicinski, Paolo Abeni, Richard Cochran, Niklas Söderlund, Paul Barker, Rob Herring, Krzysztof Kozlowski, Conor Dooley, Geert Uytterhoeven, Magnus Damm, netdev, linux-renesas-soc, linux-kernel, devicetree, Nikita Yushchenko, Christophe JAILLET On Thu, Nov 06, 2025 at 01:55:26PM +0100, Michael Dege wrote: > Enable Phy link status pin for boards which support this feature. Probably repeating what others have said. Please zoom out and give us an idea what a link-status pin is? I don't remember seeing this term used before. Andrew ^ permalink raw reply [flat|nested] 23+ messages in thread
* RE: [PATCH net-next 02/10] net: renesas: rswitch: enable Phy link status pin 2025-11-07 1:16 ` Andrew Lunn @ 2025-11-07 13:37 ` Michael Dege 0 siblings, 0 replies; 23+ messages in thread From: Michael Dege @ 2025-11-07 13:37 UTC (permalink / raw) To: Andrew Lunn Cc: Yoshihiro Shimoda, Andrew Lunn, David S. Miller, Eric Dumazet, Jakub Kicinski, Paolo Abeni, Richard Cochran, niklas.soderlund, Paul Barker, Rob Herring, Krzysztof Kozlowski, Conor Dooley, Geert Uytterhoeven, magnus.damm, netdev@vger.kernel.org, linux-renesas-soc@vger.kernel.org, linux-kernel@vger.kernel.org, devicetree@vger.kernel.org, Nikita Yushchenko, Christophe JAILLET > -----Original Message----- > From: Andrew Lunn <andrew@lunn.ch> > Sent: Friday, November 7, 2025 2:16 AM > To: Michael Dege <michael.dege@renesas.com> > Cc: Yoshihiro Shimoda <yoshihiro.shimoda.uh@renesas.com>; Andrew Lunn <andrew+netdev@lunn.ch>; David > S. Miller <davem@davemloft.net>; Eric Dumazet <edumazet@google.com>; Jakub Kicinski <kuba@kernel.org>; > Paolo Abeni <pabeni@redhat.com>; Richard Cochran <richardcochran@gmail.com>; niklas.soderlund > <niklas.soderlund@ragnatech.se>; Paul Barker <paul@pbarker.dev>; Rob Herring <robh@kernel.org>; > Krzysztof Kozlowski <krzk+dt@kernel.org>; Conor Dooley <conor+dt@kernel.org>; Geert Uytterhoeven > <geert+renesas@glider.be>; magnus.damm <magnus.damm@gmail.com>; netdev@vger.kernel.org; linux-renesas- > soc@vger.kernel.org; linux-kernel@vger.kernel.org; devicetree@vger.kernel.org; Nikita Yushchenko > <nikita.yoush@cogentembedded.com>; Christophe JAILLET <christophe.jaillet@wanadoo.fr> > Subject: Re: [PATCH net-next 02/10] net: renesas: rswitch: enable Phy link status pin > > On Thu, Nov 06, 2025 at 01:55:26PM +0100, Michael Dege wrote: > > Enable Phy link status pin for boards which support this feature. > > Probably repeating what others have said. Please zoom out and give us an idea what a link-status pin > is? I don't remember seeing this term used before. > > Andrew Thank you for your comment I will add an explanation. Michael ________________________________ Renesas Electronics Europe GmbH Registered Office: Arcadiastrasse 10 DE-40472 Duesseldorf Commercial Registry: Duesseldorf, HRB 3708 Managing Director: Carsten Jauch VAT-No.: DE 14978647 Tax-ID-No: 105/5839/1793 Legal Disclaimer: This e-mail communication (and any attachment/s) is confidential and contains proprietary information, some or all of which may be legally privileged. It is intended solely for the use of the individual or entity to which it is addressed. Access to this email by anyone else is unauthorized. If you are not the intended recipient, any disclosure, copying, distribution or any action taken or omitted to be taken in reliance on it, is prohibited and may be unlawful. ^ permalink raw reply [flat|nested] 23+ messages in thread
* [PATCH net-next 03/10] dt-bindings: net: renesas,r8a779f0-ether-switch.yaml: add optional property link-pin 2025-11-06 12:55 [PATCH net-next 00/10] net: renesas: rswitch: R-Car S4 add HW offloading for layer 3 routing Michael Dege 2025-11-06 12:55 ` [PATCH net-next 01/10] net: renesas: rswitch: cleanup MII settings Michael Dege 2025-11-06 12:55 ` [PATCH net-next 02/10] net: renesas: rswitch: enable Phy link status pin Michael Dege @ 2025-11-06 12:55 ` Michael Dege 2025-11-06 13:41 ` Geert Uytterhoeven ` (2 more replies) 2025-11-06 12:55 ` [PATCH net-next 04/10] arm64: dts: renesas: r8a779f4-s4sk.dts add link-pin property Michael Dege ` (6 subsequent siblings) 9 siblings, 3 replies; 23+ messages in thread From: Michael Dege @ 2025-11-06 12:55 UTC (permalink / raw) To: Yoshihiro Shimoda, Andrew Lunn, David S. Miller, Eric Dumazet, Jakub Kicinski, Paolo Abeni, Richard Cochran, Niklas Söderlund, Paul Barker, Rob Herring, Krzysztof Kozlowski, Conor Dooley, Geert Uytterhoeven, Magnus Damm Cc: netdev, linux-renesas-soc, linux-kernel, devicetree, Nikita Yushchenko, Christophe JAILLET, Michael Dege Add optional ether-port property link-pin <empty> Signed-off-by: Michael Dege <michael.dege@renesas.com> --- .../devicetree/bindings/net/renesas,r8a779f0-ether-switch.yaml | 3 +++ 1 file changed, 3 insertions(+) diff --git a/Documentation/devicetree/bindings/net/renesas,r8a779f0-ether-switch.yaml b/Documentation/devicetree/bindings/net/renesas,r8a779f0-ether-switch.yaml index e933a1e48d67..54cd427d8ae5 100644 --- a/Documentation/devicetree/bindings/net/renesas,r8a779f0-ether-switch.yaml +++ b/Documentation/devicetree/bindings/net/renesas,r8a779f0-ether-switch.yaml @@ -126,6 +126,9 @@ properties: - phys - mdio + optional: + - link-pin + required: - compatible - reg -- 2.43.0 ^ permalink raw reply related [flat|nested] 23+ messages in thread
* Re: [PATCH net-next 03/10] dt-bindings: net: renesas,r8a779f0-ether-switch.yaml: add optional property link-pin 2025-11-06 12:55 ` [PATCH net-next 03/10] dt-bindings: net: renesas,r8a779f0-ether-switch.yaml: add optional property link-pin Michael Dege @ 2025-11-06 13:41 ` Geert Uytterhoeven 2025-11-06 14:19 ` Rob Herring (Arm) 2025-11-06 17:16 ` Conor Dooley 2 siblings, 0 replies; 23+ messages in thread From: Geert Uytterhoeven @ 2025-11-06 13:41 UTC (permalink / raw) To: Michael Dege Cc: Yoshihiro Shimoda, Andrew Lunn, David S. Miller, Eric Dumazet, Jakub Kicinski, Paolo Abeni, Richard Cochran, Niklas Söderlund, Paul Barker, Rob Herring, Krzysztof Kozlowski, Conor Dooley, Geert Uytterhoeven, Magnus Damm, netdev, linux-renesas-soc, linux-kernel, devicetree, Nikita Yushchenko, Christophe JAILLET Hi Michael, On Thu, 6 Nov 2025 at 13:56, Michael Dege <michael.dege@renesas.com> wrote: > Add optional ether-port property link-pin <empty> > > Signed-off-by: Michael Dege <michael.dege@renesas.com> Thanks for your patch! > --- a/Documentation/devicetree/bindings/net/renesas,r8a779f0-ether-switch.yaml > +++ b/Documentation/devicetree/bindings/net/renesas,r8a779f0-ether-switch.yaml > @@ -126,6 +126,9 @@ properties: > - phys > - mdio > > + optional: Doesn't look like valid syntax to me... $ make dt_binding_check DT_SCHEMA_FILES=Documentation/devicetree/bindings/net/renesas,r8a779f0-ether-switch.yaml SCHEMA Documentation/devicetree/bindings/processed-schema.json /scratch/geert/linux/linux-renesas/Documentation/devicetree/bindings/net/renesas,r8a779f0-ether-switch.yaml: ignoring, error parsing file CHKDT /scratch/geert/linux/linux-renesas/Documentation/devicetree/bindings /scratch/geert/linux/linux-renesas/Documentation/devicetree/bindings/net/renesas,r8a779f0-ether-switch.yaml:129:1: found a tab character that violates indentation LINT /scratch/geert/linux/linux-renesas/Documentation/devicetree/bindings /scratch/geert/linux/linux-renesas/Documentation/devicetree/bindings/net/renesas,r8a779f0-ether-switch.yaml:129:1: [error] syntax error: found character '\t' that cannot start any token (syntax) DTEX Documentation/devicetree/bindings/net/renesas,r8a779f0-ether-switch.example.dts /scratch/geert/linux/linux-renesas/Documentation/devicetree/bindings/net/renesas,r8a779f0-ether-switch.yaml:129:1: found a tab character that violates indentation > + - link-pin What does this mean? Description? > + > required: > - compatible > - reg > Gr{oetje,eeting}s, Geert -- Geert Uytterhoeven -- There's lots of Linux beyond ia32 -- geert@linux-m68k.org In personal conversations with technical people, I call myself a hacker. But when I'm talking to journalists I just say "programmer" or something like that. -- Linus Torvalds ^ permalink raw reply [flat|nested] 23+ messages in thread
* Re: [PATCH net-next 03/10] dt-bindings: net: renesas,r8a779f0-ether-switch.yaml: add optional property link-pin 2025-11-06 12:55 ` [PATCH net-next 03/10] dt-bindings: net: renesas,r8a779f0-ether-switch.yaml: add optional property link-pin Michael Dege 2025-11-06 13:41 ` Geert Uytterhoeven @ 2025-11-06 14:19 ` Rob Herring (Arm) 2025-11-06 17:16 ` Conor Dooley 2 siblings, 0 replies; 23+ messages in thread From: Rob Herring (Arm) @ 2025-11-06 14:19 UTC (permalink / raw) To: Michael Dege Cc: linux-kernel, linux-renesas-soc, Nikita Yushchenko, Christophe JAILLET, Richard Cochran, David S. Miller, devicetree, Conor Dooley, Geert Uytterhoeven, Krzysztof Kozlowski, Andrew Lunn, Yoshihiro Shimoda, Paolo Abeni, Paul Barker, Jakub Kicinski, Eric Dumazet, netdev, Niklas Söderlund, Magnus Damm On Thu, 06 Nov 2025 13:55:27 +0100, Michael Dege wrote: > Add optional ether-port property link-pin <empty> > > Signed-off-by: Michael Dege <michael.dege@renesas.com> > --- > .../devicetree/bindings/net/renesas,r8a779f0-ether-switch.yaml | 3 +++ > 1 file changed, 3 insertions(+) > My bot found errors running 'make dt_binding_check' on your patch: yamllint warnings/errors: ./Documentation/devicetree/bindings/net/renesas,r8a779f0-ether-switch.yaml:129:1: [error] syntax error: found character '\t' that cannot start any token (syntax) dtschema/dtc warnings/errors: /builds/robherring/dt-review-ci/linux/Documentation/devicetree/bindings/net/renesas,r8a779f0-ether-switch.yaml: ignoring, error parsing file ./Documentation/devicetree/bindings/net/renesas,r8a779f0-ether-switch.yaml:129:1: found character '\t' that cannot start any token make[2]: *** Deleting file 'Documentation/devicetree/bindings/net/renesas,r8a779f0-ether-switch.example.dts' Documentation/devicetree/bindings/net/renesas,r8a779f0-ether-switch.yaml:129:1: found character '\t' that cannot start any token make[2]: *** [Documentation/devicetree/bindings/Makefile:26: Documentation/devicetree/bindings/net/renesas,r8a779f0-ether-switch.example.dts] Error 1 make[2]: *** Waiting for unfinished jobs.... make[1]: *** [/builds/robherring/dt-review-ci/linux/Makefile:1547: dt_binding_check] Error 2 make: *** [Makefile:248: __sub-make] Error 2 doc reference errors (make refcheckdocs): See https://patchwork.ozlabs.org/project/devicetree-bindings/patch/20251106-add_l3_routing-v1-3-dcbb8368ca54@renesas.com The base for the series is generally the latest rc1. A different dependency should be noted in *this* patch. If you already ran 'make dt_binding_check' and didn't see the above error(s), then make sure 'yamllint' is installed and dt-schema is up to date: pip3 install dtschema --upgrade Please check and re-submit after running the above command yourself. Note that DT_SCHEMA_FILES can be set to your schema file to speed up checking your schema. However, it must be unset to test all examples with your schema. ^ permalink raw reply [flat|nested] 23+ messages in thread
* Re: [PATCH net-next 03/10] dt-bindings: net: renesas,r8a779f0-ether-switch.yaml: add optional property link-pin 2025-11-06 12:55 ` [PATCH net-next 03/10] dt-bindings: net: renesas,r8a779f0-ether-switch.yaml: add optional property link-pin Michael Dege 2025-11-06 13:41 ` Geert Uytterhoeven 2025-11-06 14:19 ` Rob Herring (Arm) @ 2025-11-06 17:16 ` Conor Dooley 2 siblings, 0 replies; 23+ messages in thread From: Conor Dooley @ 2025-11-06 17:16 UTC (permalink / raw) To: Michael Dege Cc: Yoshihiro Shimoda, Andrew Lunn, David S. Miller, Eric Dumazet, Jakub Kicinski, Paolo Abeni, Richard Cochran, Niklas Söderlund, Paul Barker, Rob Herring, Krzysztof Kozlowski, Conor Dooley, Geert Uytterhoeven, Magnus Damm, netdev, linux-renesas-soc, linux-kernel, devicetree, Nikita Yushchenko, Christophe JAILLET [-- Attachment #1: Type: text/plain, Size: 1162 bytes --] On Thu, Nov 06, 2025 at 01:55:27PM +0100, Michael Dege wrote: > Add optional ether-port property link-pin <empty> Whats this <empty> about? > Signed-off-by: Michael Dege <michael.dege@renesas.com> > --- > .../devicetree/bindings/net/renesas,r8a779f0-ether-switch.yaml | 3 +++ > 1 file changed, 3 insertions(+) > > diff --git a/Documentation/devicetree/bindings/net/renesas,r8a779f0-ether-switch.yaml b/Documentation/devicetree/bindings/net/renesas,r8a779f0-ether-switch.yaml > index e933a1e48d67..54cd427d8ae5 100644 > --- a/Documentation/devicetree/bindings/net/renesas,r8a779f0-ether-switch.yaml > +++ b/Documentation/devicetree/bindings/net/renesas,r8a779f0-ether-switch.yaml > @@ -126,6 +126,9 @@ properties: > - phys > - mdio > > + optional: > + - link-pin Missing a definition for the property. "optional:" isn't a thing, anything not required is optional. Clearly you didn't test this. Please look at what every other binding does for (what I assume is) a "boolean" or "flag" property. pw-bot: changes-requested > + > required: > - compatible > - reg > > -- > 2.43.0 > [-- Attachment #2: signature.asc --] [-- Type: application/pgp-signature, Size: 228 bytes --] ^ permalink raw reply [flat|nested] 23+ messages in thread
* [PATCH net-next 04/10] arm64: dts: renesas: r8a779f4-s4sk.dts add link-pin property 2025-11-06 12:55 [PATCH net-next 00/10] net: renesas: rswitch: R-Car S4 add HW offloading for layer 3 routing Michael Dege ` (2 preceding siblings ...) 2025-11-06 12:55 ` [PATCH net-next 03/10] dt-bindings: net: renesas,r8a779f0-ether-switch.yaml: add optional property link-pin Michael Dege @ 2025-11-06 12:55 ` Michael Dege 2025-11-06 12:55 ` [PATCH net-next 05/10] arm64: dts: renesas: r8a779f0-spider-ethernet.dtsi " Michael Dege ` (5 subsequent siblings) 9 siblings, 0 replies; 23+ messages in thread From: Michael Dege @ 2025-11-06 12:55 UTC (permalink / raw) To: Yoshihiro Shimoda, Andrew Lunn, David S. Miller, Eric Dumazet, Jakub Kicinski, Paolo Abeni, Richard Cochran, Niklas Söderlund, Paul Barker, Rob Herring, Krzysztof Kozlowski, Conor Dooley, Geert Uytterhoeven, Magnus Damm Cc: netdev, linux-renesas-soc, linux-kernel, devicetree, Nikita Yushchenko, Christophe JAILLET, Michael Dege Enable link-pin for S4SK board. Signed-off-by: Michael Dege <michael.dege@renesas.com> --- arch/arm64/boot/dts/renesas/r8a779f4-s4sk.dts | 2 ++ 1 file changed, 2 insertions(+) diff --git a/arch/arm64/boot/dts/renesas/r8a779f4-s4sk.dts b/arch/arm64/boot/dts/renesas/r8a779f4-s4sk.dts index 67b18f2bffbd..a4855c215d2f 100644 --- a/arch/arm64/boot/dts/renesas/r8a779f4-s4sk.dts +++ b/arch/arm64/boot/dts/renesas/r8a779f4-s4sk.dts @@ -185,6 +185,7 @@ &rswitch { &rswitch_port0 { reg = <0>; + link-pin; phy-handle = <&ic99>; phy-mode = "sgmii"; phys = <ð_serdes 0>; @@ -204,6 +205,7 @@ ic99: ethernet-phy@1 { &rswitch_port1 { reg = <1>; + link-pin; phy-handle = <&ic102>; phy-mode = "sgmii"; phys = <ð_serdes 1>; -- 2.43.0 ^ permalink raw reply related [flat|nested] 23+ messages in thread
* [PATCH net-next 05/10] arm64: dts: renesas: r8a779f0-spider-ethernet.dtsi add link-pin property 2025-11-06 12:55 [PATCH net-next 00/10] net: renesas: rswitch: R-Car S4 add HW offloading for layer 3 routing Michael Dege ` (3 preceding siblings ...) 2025-11-06 12:55 ` [PATCH net-next 04/10] arm64: dts: renesas: r8a779f4-s4sk.dts add link-pin property Michael Dege @ 2025-11-06 12:55 ` Michael Dege 2025-11-06 12:55 ` [PATCH net-next 06/10] net: renesas: rswitch: add MAC address filtering Michael Dege ` (4 subsequent siblings) 9 siblings, 0 replies; 23+ messages in thread From: Michael Dege @ 2025-11-06 12:55 UTC (permalink / raw) To: Yoshihiro Shimoda, Andrew Lunn, David S. Miller, Eric Dumazet, Jakub Kicinski, Paolo Abeni, Richard Cochran, Niklas Söderlund, Paul Barker, Rob Herring, Krzysztof Kozlowski, Conor Dooley, Geert Uytterhoeven, Magnus Damm Cc: netdev, linux-renesas-soc, linux-kernel, devicetree, Nikita Yushchenko, Christophe JAILLET, Michael Dege Enable link-pin for S4 Spider board. Signed-off-by: Michael Dege <michael.dege@renesas.com> --- arch/arm64/boot/dts/renesas/r8a779f0-spider-ethernet.dtsi | 3 +++ 1 file changed, 3 insertions(+) diff --git a/arch/arm64/boot/dts/renesas/r8a779f0-spider-ethernet.dtsi b/arch/arm64/boot/dts/renesas/r8a779f0-spider-ethernet.dtsi index ad2b0398d354..862a60705f53 100644 --- a/arch/arm64/boot/dts/renesas/r8a779f0-spider-ethernet.dtsi +++ b/arch/arm64/boot/dts/renesas/r8a779f0-spider-ethernet.dtsi @@ -54,6 +54,7 @@ &rswitch { &rswitch_port0 { reg = <0>; + link-pin; phy-handle = <&u101>; phy-mode = "sgmii"; phys = <ð_serdes 0>; @@ -73,6 +74,7 @@ u101: ethernet-phy@1 { &rswitch_port1 { reg = <1>; + link-pin; phy-handle = <&u201>; phy-mode = "sgmii"; phys = <ð_serdes 1>; @@ -92,6 +94,7 @@ u201: ethernet-phy@2 { &rswitch_port2 { reg = <2>; + link-pin; phy-handle = <&u301>; phy-mode = "sgmii"; phys = <ð_serdes 2>; -- 2.43.0 ^ permalink raw reply related [flat|nested] 23+ messages in thread
* [PATCH net-next 06/10] net: renesas: rswitch: add MAC address filtering 2025-11-06 12:55 [PATCH net-next 00/10] net: renesas: rswitch: R-Car S4 add HW offloading for layer 3 routing Michael Dege ` (4 preceding siblings ...) 2025-11-06 12:55 ` [PATCH net-next 05/10] arm64: dts: renesas: r8a779f0-spider-ethernet.dtsi " Michael Dege @ 2025-11-06 12:55 ` Michael Dege 2025-11-07 1:18 ` Andrew Lunn 2025-11-06 12:55 ` [PATCH net-next 07/10] net: renesas: rswitch: fix FWPCx register names Michael Dege ` (3 subsequent siblings) 9 siblings, 1 reply; 23+ messages in thread From: Michael Dege @ 2025-11-06 12:55 UTC (permalink / raw) To: Yoshihiro Shimoda, Andrew Lunn, David S. Miller, Eric Dumazet, Jakub Kicinski, Paolo Abeni, Richard Cochran, Niklas Söderlund, Paul Barker, Rob Herring, Krzysztof Kozlowski, Conor Dooley, Geert Uytterhoeven, Magnus Damm Cc: netdev, linux-renesas-soc, linux-kernel, devicetree, Nikita Yushchenko, Christophe JAILLET, Michael Dege Enable MAC address filtering in Rswitch HW. Signed-off-by: Nikita Yushchenko <nikita.yoush@cogentembedded.com> Signed-off-by: Michael Dege <michael.dege@renesas.com> --- drivers/net/ethernet/renesas/rswitch.h | 23 +++++++++++++++++++++++ drivers/net/ethernet/renesas/rswitch_main.c | 8 ++++++++ 2 files changed, 31 insertions(+) diff --git a/drivers/net/ethernet/renesas/rswitch.h b/drivers/net/ethernet/renesas/rswitch.h index a65ba10ae435..ac32091b7991 100644 --- a/drivers/net/ethernet/renesas/rswitch.h +++ b/drivers/net/ethernet/renesas/rswitch.h @@ -767,6 +767,29 @@ enum link_speed_conf { #define MLVC_PLV BIT(16) +#define MRAFC_MSRAREP BIT(26) +#define MRAFC_NSAREP BIT(25) +#define MRAFC_SDSFREP BIT(24) +#define MRAFC_NDAREP BIT(23) +#define MRAFC_BCACP BIT(22) +#define MRAFC_MCACP BIT(21) +#define MRAFC_BSTENP BIT(20) +#define MRAFC_MSTENP BIT(19) +#define MRAFC_BCENP BIT(18) +#define MRAFC_MCENP BIT(17) +#define MRAFC_UCENP BIT(16) +#define MRAFC_MSAREE BIT(10) +#define MRAFC_NSAREE BIT(9) +#define MRAFC_SDSFREE BIT(8) +#define MRAFC_NDAREE BIT(7) +#define MRAFC_BCADE BIT(6) +#define MRAFC_MCADE BIT(5) +#define MRAFC_BSTENE BIT(4) +#define MRAFC_MSTENE BIT(3) +#define MRAFC_BCENE BIT(2) +#define MRAFC_MCENE BIT(1) +#define MRAFC_UCENE BIT(0) + /* GWCA */ enum rswitch_gwca_mode { GWMC_OPC_RESET, diff --git a/drivers/net/ethernet/renesas/rswitch_main.c b/drivers/net/ethernet/renesas/rswitch_main.c index dd9a0e7a9d74..d32d4d18606d 100644 --- a/drivers/net/ethernet/renesas/rswitch_main.c +++ b/drivers/net/ethernet/renesas/rswitch_main.c @@ -1203,6 +1203,13 @@ static void rswitch_etha_enable_mii(struct rswitch_etha *etha) FIELD_PREP(MPIC_PLSPP, etha->link_pin)); } +static void rswitch_etha_set_MAC_addr_filter(struct rswitch_etha *etha) +{ + /* Enable broad-/multi-/uni-cast reception of eMAC and pMAC frames */ + iowrite32(MRAFC_BCENE | MRAFC_MCENE | MRAFC_UCENE | MRAFC_BCENP | + MRAFC_MCENP | MRAFC_UCENP, etha->addr + MRAFC); +} + static int rswitch_etha_hw_init(struct rswitch_etha *etha, const u8 *mac) { int err; @@ -1217,6 +1224,7 @@ static int rswitch_etha_hw_init(struct rswitch_etha *etha, const u8 *mac) iowrite32(EAVCC_VEM_SC_TAG, etha->addr + EAVCC); rswitch_rmac_setting(etha, mac); rswitch_etha_enable_mii(etha); + rswitch_etha_set_MAC_addr_filter(etha); err = rswitch_etha_wait_link_verification(etha); if (err < 0) -- 2.43.0 ^ permalink raw reply related [flat|nested] 23+ messages in thread
* Re: [PATCH net-next 06/10] net: renesas: rswitch: add MAC address filtering 2025-11-06 12:55 ` [PATCH net-next 06/10] net: renesas: rswitch: add MAC address filtering Michael Dege @ 2025-11-07 1:18 ` Andrew Lunn 0 siblings, 0 replies; 23+ messages in thread From: Andrew Lunn @ 2025-11-07 1:18 UTC (permalink / raw) To: Michael Dege Cc: Yoshihiro Shimoda, Andrew Lunn, David S. Miller, Eric Dumazet, Jakub Kicinski, Paolo Abeni, Richard Cochran, Niklas Söderlund, Paul Barker, Rob Herring, Krzysztof Kozlowski, Conor Dooley, Geert Uytterhoeven, Magnus Damm, netdev, linux-renesas-soc, linux-kernel, devicetree, Nikita Yushchenko, Christophe JAILLET On Thu, Nov 06, 2025 at 01:55:30PM +0100, Michael Dege wrote: > Enable MAC address filtering in Rswitch HW. Please try to answer the question "Why?" in the commit message, not "What?". Why would i want MAC address filtering? Why is it being enabled now, when it was not enabled before? Andrew --- pw-bot: cr ^ permalink raw reply [flat|nested] 23+ messages in thread
* [PATCH net-next 07/10] net: renesas: rswitch: fix FWPCx register names 2025-11-06 12:55 [PATCH net-next 00/10] net: renesas: rswitch: R-Car S4 add HW offloading for layer 3 routing Michael Dege ` (5 preceding siblings ...) 2025-11-06 12:55 ` [PATCH net-next 06/10] net: renesas: rswitch: add MAC address filtering Michael Dege @ 2025-11-06 12:55 ` Michael Dege 2025-11-06 12:55 ` [PATCH net-next 08/10] net: renesas: rswitch: add bit access macros for forwarding engine Michael Dege ` (2 subsequent siblings) 9 siblings, 0 replies; 23+ messages in thread From: Michael Dege @ 2025-11-06 12:55 UTC (permalink / raw) To: Yoshihiro Shimoda, Andrew Lunn, David S. Miller, Eric Dumazet, Jakub Kicinski, Paolo Abeni, Richard Cochran, Niklas Söderlund, Paul Barker, Rob Herring, Krzysztof Kozlowski, Conor Dooley, Geert Uytterhoeven, Magnus Damm Cc: netdev, linux-renesas-soc, linux-kernel, devicetree, Nikita Yushchenko, Christophe JAILLET, Michael Dege Some bit access macros had letters in the register name mixed up. Signed-off-by: Michael Dege <michael.dege@renesas.com> --- drivers/net/ethernet/renesas/rswitch.h | 6 +++--- drivers/net/ethernet/renesas/rswitch_l2.c | 2 +- drivers/net/ethernet/renesas/rswitch_main.c | 4 ++-- 3 files changed, 6 insertions(+), 6 deletions(-) diff --git a/drivers/net/ethernet/renesas/rswitch.h b/drivers/net/ethernet/renesas/rswitch.h index ac32091b7991..ef64bd6e5a75 100644 --- a/drivers/net/ethernet/renesas/rswitch.h +++ b/drivers/net/ethernet/renesas/rswitch.h @@ -856,12 +856,12 @@ enum rswitch_gwca_mode { #define FWPC0_VLANSA BIT(28) #define FWPC1(i) (FWPC10 + (i) * 0x10) -#define FWCP1_LTHFW GENMASK(16 + (RSWITCH_NUM_AGENTS - 1), 16) +#define FWPC1_LTHFW GENMASK(16 + (RSWITCH_NUM_AGENTS - 1), 16) #define FWPC1_DDE BIT(0) #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) +#define FWPC2_LTWFW GENMASK(16 + (RSWITCH_NUM_AGENTS - 1), 16) +#define FWPC2_LTWFW_MASK GENMASK(16 + (RSWITCH_NUM_AGENTS - 1), 16) #define FWPBFC(i) (FWPBFC0 + (i) * 0x10) #define FWPBFC_PBDV GENMASK(RSWITCH_NUM_AGENTS - 1, 0) diff --git a/drivers/net/ethernet/renesas/rswitch_l2.c b/drivers/net/ethernet/renesas/rswitch_l2.c index 4a69ec77d69c..b69859a0a42a 100644 --- a/drivers/net/ethernet/renesas/rswitch_l2.c +++ b/drivers/net/ethernet/renesas/rswitch_l2.c @@ -80,7 +80,7 @@ static void rswitch_update_l2_hw_forwarding(struct rswitch_private *priv) * * Do not allow L2 forwarding to self for hw port. */ - iowrite32(FIELD_PREP(FWCP2_LTWFW_MASK, fwd_mask | BIT(rdev->port)), + iowrite32(FIELD_PREP(FWPC2_LTWFW_MASK, fwd_mask | BIT(rdev->port)), priv->addr + FWPC2(rdev->port)); } diff --git a/drivers/net/ethernet/renesas/rswitch_main.c b/drivers/net/ethernet/renesas/rswitch_main.c index d32d4d18606d..e92b5cdffd10 100644 --- a/drivers/net/ethernet/renesas/rswitch_main.c +++ b/drivers/net/ethernet/renesas/rswitch_main.c @@ -124,10 +124,10 @@ static int rswitch_fwd_init(struct rswitch_private *priv) /* Disable all port features */ iowrite32(0, priv->addr + FWPC0(i)); /* Disallow L3 forwarding and direct descriptor forwarding */ - iowrite32(FIELD_PREP(FWCP1_LTHFW, all_ports_mask), + iowrite32(FIELD_PREP(FWPC1_LTHFW, all_ports_mask), priv->addr + FWPC1(i)); /* Disallow L2 forwarding */ - iowrite32(FIELD_PREP(FWCP2_LTWFW, all_ports_mask), + iowrite32(FIELD_PREP(FWPC2_LTWFW, all_ports_mask), priv->addr + FWPC2(i)); /* Disallow port based forwarding */ iowrite32(0, priv->addr + FWPBFC(i)); -- 2.43.0 ^ permalink raw reply related [flat|nested] 23+ messages in thread
* [PATCH net-next 08/10] net: renesas: rswitch: add bit access macros for forwarding engine 2025-11-06 12:55 [PATCH net-next 00/10] net: renesas: rswitch: R-Car S4 add HW offloading for layer 3 routing Michael Dege ` (6 preceding siblings ...) 2025-11-06 12:55 ` [PATCH net-next 07/10] net: renesas: rswitch: fix FWPCx register names Michael Dege @ 2025-11-06 12:55 ` Michael Dege 2025-11-06 12:55 ` [PATCH net-next 09/10] net: renesas: rswitch: add simple l3 routing Michael Dege 2025-11-06 12:55 ` [PATCH net-next 10/10] net: renesas: rswitch: update error handling of probe Michael Dege 9 siblings, 0 replies; 23+ messages in thread From: Michael Dege @ 2025-11-06 12:55 UTC (permalink / raw) To: Yoshihiro Shimoda, Andrew Lunn, David S. Miller, Eric Dumazet, Jakub Kicinski, Paolo Abeni, Richard Cochran, Niklas Söderlund, Paul Barker, Rob Herring, Krzysztof Kozlowski, Conor Dooley, Geert Uytterhoeven, Magnus Damm Cc: netdev, linux-renesas-soc, linux-kernel, devicetree, Nikita Yushchenko, Christophe JAILLET, Michael Dege Add bit access macros for the forwarding engine needed for L3 routing. Signed-off-by: Nikita Yushchenko <nikita.yoush@cogentembedded.com> Signed-off-by: Michael Dege <michael.dege@renesas.com> --- drivers/net/ethernet/renesas/rswitch.h | 113 ++++++++++++++++++++++++++++++++- 1 file changed, 112 insertions(+), 1 deletion(-) diff --git a/drivers/net/ethernet/renesas/rswitch.h b/drivers/net/ethernet/renesas/rswitch.h index ef64bd6e5a75..773bde67bebc 100644 --- a/drivers/net/ethernet/renesas/rswitch.h +++ b/drivers/net/ethernet/renesas/rswitch.h @@ -839,7 +839,7 @@ enum rswitch_gwca_mode { #define CABPPFLC_INIT_VALUE 0x00800080 -/* MFWD */ +/* MFWD forwarding engine */ #define FWPC0(i) (FWPC00 + (i) * 0x10) #define FWPC0_LTHTA BIT(0) #define FWPC0_IP4UE BIT(3) @@ -857,6 +857,7 @@ enum rswitch_gwca_mode { #define FWPC1(i) (FWPC10 + (i) * 0x10) #define FWPC1_LTHFW GENMASK(16 + (RSWITCH_NUM_AGENTS - 1), 16) +#define FWPC1_LTHFW_MASK GENMASK(16 + (RSWITCH_NUM_AGENTS - 1), 16) #define FWPC1_DDE BIT(0) #define FWPC2(i) (FWPC20 + (i) * 0x10) @@ -882,6 +883,116 @@ enum rswitch_gwca_mode { #define FWMACAGC_MACAGOG BIT(28) #define FWMACAGC_MACDESOG BIT(29) +#define FWIP4SC_IDPTS BIT(24) +#define FWIP4SC_IIDS BIT(23) +#define FWIP4SC_IISS BIT(22) +#define FWIP4SC_ICDS BIT(21) +#define FWIP4SC_ICPS BIT(20) +#define FWIP4SC_ICVS BIT(19) +#define FWIP4SC_ISDS BIT(18) +#define FWIP4SC_ISPS BIT(17) +#define FWIP4SC_ISVS BIT(16) +#define FWIP4SC_IDPTH BIT(8) +#define FWIP4SC_IIDH BIT(7) +#define FWIP4SC_IISH BIT(6) +#define FWIP4SC_ICDH BIT(5) +#define FWIP4SC_ICPH BIT(4) +#define FWIP4SC_ICVH BIT(3) +#define FWIP4SC_ISDH BIT(2) +#define FWIP4SC_ISPH BIT(1) +#define FWIP4SC_ISVH BIT(0) + +#define RSWITCH_MAX_NUM_RRULE 265 + +#define FWLTHHEC_HMUE GENMASK(26, 16) + +#define FWLTHTL0_ED BIT(16) +#define FWLTHTL0_SL BIT(8) + +#define FWLTHTL5_MSDUV BIT(31) +#define FWLTHTL5_MSDUN GENMASK(19, 16) +#define FWLTHTL5_GATEV BIT(15) +#define FWLTHTL5_GATEN GENMASK(2, 0) + +#define FWLTHTL6_MTRV BIT(31) +#define FWLTHTL6_MTRN GENMASK(20, 16) +#define FWLTHTL6_FRERV BIT(15) +#define FWLTHTL6_FRERN GENMASK(6, 0) + +#define FWLTHTL7_SLV GENMASK(16 + RSWITCH_NUM_AGENTS - 1, 16) +#define FWLTHTL7_RV BIT(15) +#define FWLTHTL7_RN GENMASK(7, 0) + +#define FWLTHTL8(i) (FWLTHTL80 + (i) * 4) +#define FWLTHTL8_CSD GENMASK(6, 0) + +#define FWLTHTL9_CME BIT(21) +#define FWLTHTL9_EME BIT(20) +#define FWLTHTL9_IPU BIT(19) +#define FWLTHTL9_IPV GENMASK(18, 16) +#define FWLTHTL9_DV GENMASK(RSWITCH_NUM_AGENTS - 1, 0) + +#define FWLTHTLR_L BIT(31) +#define FWLTHTLR_LCN GENMASK(25, 16) +#define FWLTHTLR_LO BIT(3) +#define FWLTHTLR_LEF BIT(2) +#define FWLTHTLR_LSF BIT(1) +#define FWLTHTLR_LF BIT(0) + +#define FWLTHTIM_TR BIT(1) +#define FWLTHTIM_TIOG BIT(0) + +#define FWMACTL0_ED BIT(16) +#define FWMACTL0_HLD BIT(10) +#define FWMACTL0_DE BIT(9) +#define FWMACTL0_SL BIT(8) + +#define FWMACTL3_DSLV GENMASK(16 + RSWITCH_NUM_AGENTS - 1, 16) +#define FWMACTL3_SSLV GENMASK(RSWITCH_NUM_HW - 1, 0) + +#define FWMACTL4(i) (FWMACTL40 + (i) * 4) + +#define FWMACTL5_CME BIT(21) +#define FWMACTL5_EME BIT(20) +#define FWMACTL5_IPU BIT(19) +#define FWMACTL5_IPV GENMASK(18, 16) +#define FWMACTL5_DV GENMASK(RSWITCH_NUM_AGENTS - 1, 0) + +#define FWMACTLR_L BIT(31) +#define FWMACTLR_LCN GENMASK(25, 16) +#define FWMACTLR_LO BIT(3) +#define FWMACTLR_LEF BIT(2) +#define FWMACTLR_LSF BIT(1) +#define FWMACTLR_LF BIT(0) + +#define FWL23URL0_PV GENMASK(16 + RSWITCH_NUM_AGENTS - 1, 16) +#define FWL23URL0_RN GENMASK(7, 0) + +#define FWL23URL1_RTU GENMASK(26, 25) +#define FWL23URL1_SDEIU BIT(24) +#define FWL23URL1_SPCPU BIT(23) +#define FWL23URL1_SVIDU BIT(22) +#define FWL23URL1_CDEIU BIT(21) +#define FWL23URL1_CPCPU BIT(20) +#define FWL23URL1_CVIDU BIT(19) +#define FWL23URL1_MSAU BIT(18) +#define FWL23URL1_MDAU BIT(17) +#define FWL23URL1_TTLU BIT(16) + +#define FWL23URL3_SDEI BIT(31) +#define FWL23URL3_SPCP GENMASK(30, 28) +#define FWL23URL3_SVID GENMASK(27, 16) +#define FWL23URL3_CDEI BIT(15) +#define FWL23URL3_CPCP GENMASK(14, 12) +#define FWL23URL3_CVID GENMASK(11, 0) + +#define FWL23URLR_L BIT(31) +#define FWL23URLR_LSF BIT(1) +#define FWL23URLR_LF BIT(0) + +#define FWL23UTIM_TR BIT(1) +#define FWL23UTIM_TIOG BIT(0) + #define RSW_AGEING_CLK_PER_US 0x140 #define RSW_AGEING_TIME 300 -- 2.43.0 ^ permalink raw reply related [flat|nested] 23+ messages in thread
* [PATCH net-next 09/10] net: renesas: rswitch: add simple l3 routing 2025-11-06 12:55 [PATCH net-next 00/10] net: renesas: rswitch: R-Car S4 add HW offloading for layer 3 routing Michael Dege ` (7 preceding siblings ...) 2025-11-06 12:55 ` [PATCH net-next 08/10] net: renesas: rswitch: add bit access macros for forwarding engine Michael Dege @ 2025-11-06 12:55 ` Michael Dege 2025-11-07 2:32 ` Andrew Lunn 2025-11-06 12:55 ` [PATCH net-next 10/10] net: renesas: rswitch: update error handling of probe Michael Dege 9 siblings, 1 reply; 23+ messages in thread From: Michael Dege @ 2025-11-06 12:55 UTC (permalink / raw) To: Yoshihiro Shimoda, Andrew Lunn, David S. Miller, Eric Dumazet, Jakub Kicinski, Paolo Abeni, Richard Cochran, Niklas Söderlund, Paul Barker, Rob Herring, Krzysztof Kozlowski, Conor Dooley, Geert Uytterhoeven, Magnus Damm Cc: netdev, linux-renesas-soc, linux-kernel, devicetree, Nikita Yushchenko, Christophe JAILLET, Michael Dege Add hardware offloading for L3 routing on R-Car S4. Signed-off-by: Nikita Yushchenko <nikita.yoush@cogentembedded.com> Signed-off-by: Michael Dege <michael.dege@renesas.com> --- drivers/net/ethernet/renesas/Makefile | 2 +- drivers/net/ethernet/renesas/rswitch.h | 66 ++- drivers/net/ethernet/renesas/rswitch_l3.c | 751 ++++++++++++++++++++++++++++ drivers/net/ethernet/renesas/rswitch_l3.h | 24 + drivers/net/ethernet/renesas/rswitch_main.c | 69 ++- 5 files changed, 906 insertions(+), 6 deletions(-) diff --git a/drivers/net/ethernet/renesas/Makefile b/drivers/net/ethernet/renesas/Makefile index d63e0c61bb68..ffe4e2dcb5d8 100644 --- a/drivers/net/ethernet/renesas/Makefile +++ b/drivers/net/ethernet/renesas/Makefile @@ -8,7 +8,7 @@ obj-$(CONFIG_SH_ETH) += sh_eth.o ravb-objs := ravb_main.o ravb_ptp.o obj-$(CONFIG_RAVB) += ravb.o -rswitch-objs := rswitch_main.o rswitch_l2.o +rswitch-objs := rswitch_main.o rswitch_l2.o rswitch_l3.o obj-$(CONFIG_RENESAS_ETHER_SWITCH) += rswitch.o obj-$(CONFIG_RENESAS_GEN4_PTP) += rcar_gen4_ptp.o diff --git a/drivers/net/ethernet/renesas/rswitch.h b/drivers/net/ethernet/renesas/rswitch.h index 773bde67bebc..6e57ca88e1f7 100644 --- a/drivers/net/ethernet/renesas/rswitch.h +++ b/drivers/net/ethernet/renesas/rswitch.h @@ -871,6 +871,9 @@ enum rswitch_gwca_mode { #define FWMACHEC_MACHMUE_MASK GENMASK(26, 16) +#define RSWITCH_LTH_STREAM_W 10 +#define RSWITCH_LTH_RRULE_W 8 + #define FWMACTIM_MACTIOG BIT(0) #define FWMACTIM_MACTR BIT(1) @@ -1152,8 +1155,20 @@ struct rswitch_gwca { u32 rx_irq_bits[RSWITCH_NUM_IRQ_REGS]; }; -#define NUM_QUEUES_PER_NDEV 2 -#define TS_TAGS_PER_PORT 256 +struct rswitch_route_monitor { + struct net_device *ndev; + + struct notifier_block fib_nb; + + struct list_head ipv4_local_route_list; + struct list_head ipv4_bcast_route_list; + struct list_head ipv4_ucast_route_list; + + spinlock_t lock; /* spinlock because fib notifier is atomic */ +}; + +#define NUM_QUEUES_PER_NDEV 2 +#define TS_TAGS_PER_PORT 256 struct rswitch_device { struct rswitch_private *priv; struct net_device *ndev; @@ -1173,10 +1188,14 @@ struct rswitch_device { struct phy *serdes; struct net_device *brdev; /* master bridge device */ + struct rswitch_route_monitor rmon; + unsigned int learning_requested : 1; unsigned int learning_offloaded : 1; unsigned int forwarding_requested : 1; unsigned int forwarding_offloaded : 1; + + unsigned int l3_offload_enabled : 1; }; struct rswitch_mfwd_mac_table_entry { @@ -1209,9 +1228,50 @@ struct rswitch_private { bool etha_no_runtime_change; bool gwca_halt; struct net_device *offload_brdev; + + spinlock_t l3_lock; /* lock L3 HW register access */ + DECLARE_BITMAP(l23_update_bitmap, RSWITCH_MAX_NUM_RRULE); + struct list_head l23_update_list; +}; + +struct rswitch_l23update_spec { + u8 dst_mac[ETH_ALEN]; +}; + +struct rswitch_l23update { + struct list_head list; + unsigned int use_count; + unsigned int index; + struct rswitch_l23update_spec spec; +}; + +struct rmon_ipv4_route { + struct list_head list; + __be32 addr; + __be32 mask; + __be32 gw_addr; + struct list_head offload_list; +}; + +struct rmon_ipv4_route_exception { + struct list_head list; + __be32 addr; +}; + +/* Hardware frame type identifiers (bits 130:128 of stream id) */ +#define RSWITCH_FRAME_TYPE_IPV4_TCP 3 +#define RSWITCH_FRAME_TYPE_IPV4_UDP 2 +#define RSWITCH_FRAME_TYPE_IPV4_OTHER 1 + +struct rmon_ipv4_dst_offload { + struct list_head list; + struct rswitch_l23update *update; + __be32 addr; + u8 types_offloaded; /* bits for RSWITCH_FRAME_TYPE_* */ }; -bool is_rdev(const struct net_device *ndev); void rswitch_modify(void __iomem *addr, enum rswitch_reg reg, u32 clear, u32 set); +int rswitch_reg_wait(void __iomem *addr, u32 offs, u32 mask, u32 expected); +bool is_rdev(const struct net_device *ndev); #endif /* #ifndef __RSWITCH_H__ */ diff --git a/drivers/net/ethernet/renesas/rswitch_l3.c b/drivers/net/ethernet/renesas/rswitch_l3.c new file mode 100644 index 000000000000..74b10c867bd1 --- /dev/null +++ b/drivers/net/ethernet/renesas/rswitch_l3.c @@ -0,0 +1,751 @@ +// SPDX-License-Identifier: GPL-2.0 +/* Renesas Ethernet Switch device driver L3 offloading + * + * Copyright (C) 2025 Renesas Electronics Corporation + */ + +#include <linux/err.h> +#include <linux/etherdevice.h> +#include <linux/ip.h> +#include <linux/kernel.h> +#include <linux/list.h> +#include <linux/spinlock.h> +#include <net/switchdev.h> + +#include "rswitch.h" +#include "rswitch_l3.h" + +static bool rdev_for_l3_offload(struct rswitch_device *rdev) +{ + return (test_bit(rdev->port, rdev->priv->opened_ports) && + !netdev_has_any_upper_dev(rdev->ndev)); +} + +void rswitch_update_l3_offload(struct rswitch_private *priv) +{ + u32 all_ports_mask = GENMASK(RSWITCH_NUM_AGENTS - 1, 0); + struct rswitch_device *rdev; + bool l3_offload_enable_cond; + u32 l3_rdev_count; + u32 l3_ports_mask; + + l3_ports_mask = all_ports_mask; + + l3_rdev_count = 0; + rswitch_for_all_ports(priv, rdev) { + if (rdev_for_l3_offload(rdev)) { + l3_rdev_count++; + l3_ports_mask &= ~BIT(rdev->port); + } + } + + l3_offload_enable_cond = (l3_rdev_count >= 2); + +#define FWPC0_L3_MASK (FWPC0_LTHTA | FWPC0_IP4UE | FWPC0_IP4TE | FWPC0_IP4OE) + rswitch_for_all_ports(priv, rdev) { + if (rdev_for_l3_offload(rdev) && l3_offload_enable_cond) { + /* Update allowed offload destinations even for ports + * with l3 offload enabled earlier. + * + * Allow offload routing to self for hw port. + */ + rswitch_modify(priv->addr, FWPC1(rdev->port), + FWPC1_LTHFW_MASK, + FIELD_PREP(FWPC1_LTHFW_MASK, l3_ports_mask)); + if (!rdev->l3_offload_enabled) { + rswitch_modify(priv->addr, FWPC0(rdev->port), + 0, + FWPC0_L3_MASK); + rdev->l3_offload_enabled = 1; + netdev_info(rdev->ndev, "starting l3 offload\n"); + } + } else if (rdev->l3_offload_enabled) { + rswitch_modify(priv->addr, FWPC0(rdev->port), + FWPC0_L3_MASK, + 0); + rswitch_modify(priv->addr, FWPC1(rdev->port), + FWPC1_LTHFW_MASK, + FIELD_PREP(FWPC1_LTHFW_MASK, all_ports_mask)); + + rdev->l3_offload_enabled = 0; + + /* cleanup any offloads at disable */ + rmon_cleanup_ipv4_offloads_all(&rdev->rmon); + + netdev_info(rdev->ndev, "stopping l3 offload\n"); + } + } +#undef FWPC0_L3_MASK +} + +static bool rswitch_l23update_matches_spec(struct rswitch_l23update *update, + struct rswitch_l23update_spec *spec) +{ + return ether_addr_equal(update->spec.dst_mac, spec->dst_mac); +} + +static bool rswitch_l23update_hw_op(struct rswitch_private *priv, + struct rswitch_l23update *update, + bool install) +{ + u8 *dst_mac = update->spec.dst_mac; + u32 val; + int ret; + + val = FIELD_PREP(FWL23URL0_RN, update->index) | + FIELD_PREP(FWL23URL0_PV, + install ? GENMASK(RSWITCH_NUM_AGENTS - 1, 0) : 0); + iowrite32(val, priv->addr + FWL23URL0); + + val = FWL23URL1_TTLU | + FWL23URL1_MSAU | + FWL23URL1_MDAU | + (dst_mac[0] << 8) | (dst_mac[1] << 0); + iowrite32(val, priv->addr + FWL23URL1); + + val = (dst_mac[2] << 24) | (dst_mac[3] << 16) | + (dst_mac[4] << 8) | (dst_mac[5] << 0); + iowrite32(val, priv->addr + FWL23URL2); + + iowrite32(0, priv->addr + FWL23URL3); + + /* Rule write starts after writing to FWL23URL3 */ + + ret = rswitch_reg_wait(priv->addr, FWL23URLR, FWL23URLR_L, 0); + if (ret) { + dev_err(&priv->pdev->dev, "timeout writing l23_update\n"); + return false; + } + + val = ioread32(priv->addr + FWL23URLR) & (FWL23URLR_LSF | FWL23URLR_LF); + if (val) { + dev_err(&priv->pdev->dev, + "writing l23_update failed (err %d)\n", val); + return false; + } + + return true; +} + +static struct rswitch_private * +rmon_to_rswitch_private(struct rswitch_route_monitor *rmon) +{ + struct rswitch_device *rdev; + + if (is_rdev(rmon->ndev)) { + rdev = netdev_priv(rmon->ndev); + return rdev->priv; + } + + WARN_ONCE(1, "net device not initialized, further operation unreliable"); + + return NULL; +} + +static bool rmon_ipv4_dst_offload_hw_op(struct rswitch_route_monitor *rmon, + struct rmon_ipv4_dst_offload *offload, + u8 frame_type, bool install) +{ + struct rswitch_private *priv = rmon_to_rswitch_private(rmon); + const char *frame_type_name[] = { + [RSWITCH_FRAME_TYPE_IPV4_TCP] = "TCP", + [RSWITCH_FRAME_TYPE_IPV4_UDP] = "UDP", + [RSWITCH_FRAME_TYPE_IPV4_OTHER] = "OTHER", + }; + char target[16] = "<undefined>"; + u32 val, err_flags, collisions; + struct rswitch_device *rdev; + int ret; + + if (!priv) + return false; + + spin_lock(&priv->l3_lock); + + val = (install ? 0 : FWLTHTL0_ED) | frame_type; + iowrite32(val, priv->addr + FWLTHTL0); + iowrite32(0, priv->addr + FWLTHTL1); + iowrite32(0, priv->addr + FWLTHTL2); + iowrite32(0, priv->addr + FWLTHTL3); + val = be32_to_cpu(offload->addr); + iowrite32(val, priv->addr + FWLTHTL4); + + /* accept from all ports in the table entry + * (non-particilating ports have l3 table disabled) + */ + val = FIELD_PREP(FWLTHTL7_SLV, + GENMASK(RSWITCH_NUM_AGENTS - 1, 0)) | + FWLTHTL7_RV | + FIELD_PREP(FWLTHTL7_RN, offload->update->index); + iowrite32(val, priv->addr + FWLTHTL7); + + if (is_rdev(rmon->ndev)) { + rdev = netdev_priv(rmon->ndev); + snprintf(target, sizeof(target), "port %d", rdev->port); + + iowrite32(0, priv->addr + FWLTHTL8(0)); + iowrite32(0, priv->addr + FWLTHTL8(1)); + + val = FIELD_PREP(FWLTHTL9_DV, + BIT(rdev->port)); + iowrite32(val, priv->addr + FWLTHTL9); + } + + /* Table entry write starts after writing to FWLTHTL9 */ + + ret = rswitch_reg_wait(priv->addr, FWLTHTLR, FWLTHTLR_L, 0); + val = ioread32(priv->addr + FWLTHTLR); + err_flags = val & (FWLTHTLR_LEF | FWLTHTLR_LSF | FWLTHTLR_LF); + collisions = FIELD_GET(FWLTHTLR_LCN, val); + + spin_unlock(&priv->l3_lock); + + if (ret) { + dev_err(&priv->pdev->dev, + "timeout writing l3 table entry\n"); + return false; + } + + if (err_flags) { + dev_err(&priv->pdev->dev, + "writing l3 table entry failed (flags %d)\n", + err_flags); + return false; + } + + if (install) + offload->types_offloaded |= BIT(frame_type); + else + offload->types_offloaded &= ~BIT(frame_type); + + dev_info(&priv->pdev->dev, + "%s IPv4/%s forwarding %pI4b -> %s, mac %pM; table collisions: %u\n", + install ? "added" : "removed", + frame_type_name[frame_type], + &offload->addr, + target, + offload->update->spec.dst_mac, + collisions); + + return true; +} + +static struct rswitch_l23update *rswitch_get_l23update(struct rswitch_private *priv, + struct rswitch_l23update_spec *spec) +{ + struct rswitch_l23update *update; + + spin_lock(&priv->l3_lock); + + list_for_each_entry(update, &priv->l23_update_list, list) { + if (rswitch_l23update_matches_spec(update, spec)) { + update->use_count++; + goto out; + } + } + + update = kzalloc(sizeof(*update), GFP_ATOMIC); + if (!update) + goto out; + + update->use_count = 1; + update->spec = *spec; + update->index = find_first_zero_bit(priv->l23_update_bitmap, + RSWITCH_MAX_NUM_RRULE); + if (update->index == RSWITCH_MAX_NUM_RRULE) { + dev_err_ratelimited(&priv->pdev->dev, + "out of l23_update entries\n"); + /* FIXME: trigger expire? */ + goto no_free_bit; + } + set_bit(update->index, priv->l23_update_bitmap); + + if (!rswitch_l23update_hw_op(priv, update, true)) + goto hw_op_failed; + + list_add(&update->list, &priv->l23_update_list); +out: + spin_unlock(&priv->l3_lock); + + return update; + +hw_op_failed: + clear_bit(update->index, priv->l23_update_bitmap); +no_free_bit: + kfree(update); + update = NULL; + goto out; +} + +static void rswitch_put_l23update(struct rswitch_private *priv, + struct rswitch_l23update *update) +{ + spin_lock(&priv->l3_lock); + + update->use_count--; + if (update->use_count == 0) { + list_del(&update->list); + rswitch_l23update_hw_op(priv, update, false); + clear_bit(update->index, priv->l23_update_bitmap); + kfree(update); + } + + spin_unlock(&priv->l3_lock); +} + +static inline bool addr4_in_range(__be32 addr, __be32 range_addr, + __be32 range_mask) +{ + return (addr & range_mask) == (range_addr & range_mask); +} + +static inline bool addr4_ranges_intersect(__be32 addr1, __be32 mask1, + __be32 addr2, __be32 mask2) +{ + /* Two addr/mask ranges intersect when their addrs ANDed + * with wider mask (=one with more zeroes) are the same + */ + __be32 wider_mask = mask1 & mask2; + + return (addr1 & wider_mask) == (addr2 & wider_mask); +} + +/* called under rmon lock (for rmon owning the list) */ +static inline bool addr4_in_exception_list(__be32 addr, struct list_head *list) +{ + struct rmon_ipv4_route_exception *entry; + + list_for_each_entry(entry, list, list) { + if (entry->addr == addr) + return true; + } + + return false; +} + +/* called under rmon lock */ +static struct rmon_ipv4_route * +rmon_lookup_ipv4_ucast_route(struct rswitch_route_monitor *rmon, __be32 addr) +{ + struct rmon_ipv4_route *route; + + list_for_each_entry(route, &rmon->ipv4_ucast_route_list, list) { + if (addr4_in_range(addr, route->addr, route->mask)) + return route; + } + + return NULL; +} + +/* called under rmon lock (for rmon owning the route) */ +static struct rmon_ipv4_dst_offload * +rmon_lookup_ipv4_dst_offload(struct rmon_ipv4_route *route, __be32 addr) +{ + struct rmon_ipv4_dst_offload *offload; + + list_for_each_entry(offload, &route->offload_list, list) { + if (offload->addr == addr) + return offload; + } + + return NULL; +} + +/* called under rmon lock (for rmon owning the route) */ +static struct rmon_ipv4_dst_offload * +rmon_add_ipv4_dst_offload(struct rswitch_route_monitor *rmon, + struct rmon_ipv4_route *route, + __be32 addr, + struct rswitch_l23update_spec *spec) +{ + struct rswitch_private *priv = rmon_to_rswitch_private(rmon); + struct rmon_ipv4_dst_offload *offload; + + if (!priv) + return NULL; + + offload = kzalloc(sizeof(*offload), GFP_ATOMIC); + if (!offload) + return NULL; + + offload->update = rswitch_get_l23update(priv, spec); + if (!offload->update) { + kfree(offload); + return NULL; + } + + offload->addr = addr; + list_add_tail(&offload->list, &route->offload_list); + return offload; +} + +/* called under rmon lock */ +static void rmon_remove_ipv4_dst_offload(struct rswitch_route_monitor *rmon, + struct rmon_ipv4_route *route, + struct rmon_ipv4_dst_offload *offload) +{ + struct rswitch_private *priv = rmon_to_rswitch_private(rmon); + unsigned long types_offloaded = offload->types_offloaded; + u8 frame_type; + + if (!priv) + return; + + for_each_set_bit(frame_type, &types_offloaded, BITS_PER_LONG) { + rmon_ipv4_dst_offload_hw_op(rmon, offload, frame_type, false); + } + if (offload->types_offloaded) { + /* FIXME: possible? what to do? rebuild l3 table? */ + netdev_err(rmon->ndev, "further operation unreliable\n"); + } + + list_del(&offload->list); + rswitch_put_l23update(priv, offload->update); + kfree(offload); +} + +/* called under rmon lock */ +void rmon_handle_l3_learning(struct rswitch_route_monitor *rmon, + struct sk_buff *skb) +{ + struct ethhdr *ethhdr = (struct ethhdr *)skb->data; + struct rmon_ipv4_dst_offload *offload; + struct rmon_ipv4_route *route; + __be32 src_addr, dst_addr; + struct iphdr *iphdr; + u8 frame_type; + + if (ethhdr->h_proto != cpu_to_be16(ETH_P_IP)) + return; + iphdr = (struct iphdr *)(ethhdr + 1); + src_addr = iphdr->saddr; + dst_addr = iphdr->daddr; + + /* Packets from local address are not subject for learning */ + if (addr4_in_exception_list(src_addr, &rmon->ipv4_local_route_list)) + return; + + /* Packet to local address? Why? */ + if (addr4_in_exception_list(dst_addr, &rmon->ipv4_local_route_list)) + return; + + /* Packets to broadcast destination are not subject for learning */ + if (addr4_in_exception_list(dst_addr, &rmon->ipv4_bcast_route_list)) + return; + + /* Lookup route to learn for */ + route = rmon_lookup_ipv4_ucast_route(rmon, dst_addr); + if (!route) + return; + + /* Packet is candidate for offload (and not offloaded yet) */ + + offload = rmon_lookup_ipv4_dst_offload(route, dst_addr); + + if (offload) { + /* TODO: verify that ethhdr->h_dest matches offload's */ + } else { + /* TODO: verify that ethhdr->h_dest matches neighbor table + * for route->gw_addr (if defined) or dst_addr + */ + struct rswitch_l23update_spec spec; + + ether_addr_copy(spec.dst_mac, ethhdr->h_dest); + offload = rmon_add_ipv4_dst_offload(rmon, route, + dst_addr, &spec); + if (!offload) + return; + } + + if (iphdr->protocol == IPPROTO_TCP) + frame_type = RSWITCH_FRAME_TYPE_IPV4_TCP; + else if (iphdr->protocol == IPPROTO_UDP) + frame_type = RSWITCH_FRAME_TYPE_IPV4_UDP; + else + frame_type = RSWITCH_FRAME_TYPE_IPV4_OTHER; + + if (offload->types_offloaded & BIT(frame_type)) + return; + + if (!rmon_ipv4_dst_offload_hw_op(rmon, offload, frame_type, true)) { + /* FIXME: what to do if failed? rebuild l3 table? */ + netdev_err(rmon->ndev, "further operation unreliable\n"); + } +} + +/* called under rmon lock */ +static void rmon_cleanup_ipv4_route_offloads(struct rswitch_route_monitor *rmon, + struct rmon_ipv4_route *route, + __be32 addr, __be32 mask) +{ + struct rmon_ipv4_dst_offload *offload, *tmp; + + list_for_each_entry_safe(offload, tmp, &route->offload_list, list) { + if (addr4_in_range(offload->addr, addr, mask)) + rmon_remove_ipv4_dst_offload(rmon, route, offload); + } +} + +/* called under rmon lock */ +static void rmon_cleanup_ipv4_offloads_from(struct rswitch_route_monitor *rmon, + struct list_head *pos, + __be32 addr, __be32 mask) +{ + struct rmon_ipv4_route *route; + + while (pos != &rmon->ipv4_ucast_route_list) { + route = list_entry(pos, typeof(*route), list); + if (addr4_ranges_intersect(addr, mask, + route->addr, route->mask)) + rmon_cleanup_ipv4_route_offloads(rmon, route, + addr, mask); + pos = pos->next; + } +} + +/* called under rmon lock */ +static void rmon_cleanup_ipv4_offloads_addr(struct rswitch_route_monitor *rmon, + __be32 addr) +{ + rmon_cleanup_ipv4_offloads_from(rmon, + rmon->ipv4_ucast_route_list.next, + addr, 0xffffffff); +} + +void rmon_cleanup_ipv4_offloads_all(struct rswitch_route_monitor *rmon) +{ + unsigned long flags; + + spin_lock_irqsave(&rmon->lock, flags); + rmon_cleanup_ipv4_offloads_from(rmon, + rmon->ipv4_ucast_route_list.next, + 0, 0); + spin_unlock_irqrestore(&rmon->lock, flags); +} + +/* called under rmon lock */ +static void rmon_update_ipv4_route(struct rswitch_route_monitor *rmon, + __be32 addr, __be32 mask, + __be32 gw_addr, bool keep) +{ + struct rmon_ipv4_route *route; + struct list_head *pos; + bool found = false; + + /* Find the route in the list, and/or location for the route */ + list_for_each(pos, &rmon->ipv4_ucast_route_list) { + route = list_entry(pos, typeof(*route), list); + if (route->addr == addr && route->mask == mask) { + found = true; + break; + } + + /* stop if got more generic masks */ + if (route->mask != mask && (route->mask & mask) == route->mask) + break; + } + + if (!found && !keep) + return; + + rmon_cleanup_ipv4_offloads_from(rmon, pos, addr, mask); + + if (found && !keep) { + if (!list_empty(&route->offload_list)) { + WARN_ONCE(1, "route found in offload list can't remove!"); + return; + } + list_del(&route->list); + kfree(route); + return; + } + + if (!found) { + route = kzalloc(sizeof(*route), GFP_ATOMIC); + if (!route) { + /* FIXME: what to do? disable l3 offload? */ + netdev_err(rmon->ndev, + "allocation failure, further operation unreliable\n"); + return; + } + INIT_LIST_HEAD(&route->offload_list); + list_add(&route->list, pos); + } + + route->addr = addr; + route->mask = mask; + route->gw_addr = gw_addr; +} + +/* called under rmon lock */ +static void rmon_update_ipv4_route_exception(struct rswitch_route_monitor *rmon, + struct list_head *list, __be32 addr, + bool keep) +{ + struct rmon_ipv4_route_exception *entry; + + list_for_each_entry(entry, list, list) { + if (entry->addr == addr) { + if (!keep) { + list_del(&entry->list); + kfree(entry); + } + /* there is/was entry => addr is not in any offloads */ + return; + } + } + + if (keep) { + entry = kzalloc(sizeof(*entry), GFP_ATOMIC); + if (!entry) { + /* FIXME: what to do? disable l3 offload? */ + netdev_err(rmon->ndev, + "allocation failure, further operation unreliable\n"); + return; + } + + entry->addr = addr; + list_add_tail(&entry->list, list); + + /* addr could be in existing offload */ + rmon_cleanup_ipv4_offloads_addr(rmon, addr); + } +} + +static void rmon_ipv4_fib_update(struct rswitch_route_monitor *rmon, + struct fib_notifier_info *info, bool keep) +{ + struct fib_entry_notifier_info *feni = + container_of(info, typeof(*feni), info); + struct fib_info *fib = feni->fi; + struct fib_nh *fib_nh; + unsigned long flags; + + /* FIXME: the below is far incomplete against what is possible */ + + if (fib->fib_nhs != 1 || fib->nh) + return; /* FIXME: what to do? */ + fib_nh = &fib->fib_nh[0]; + if (rmon->ndev != fib_nh->fib_nh_dev) + return; /* destination not on rmon's ndev */ + + spin_lock_irqsave(&rmon->lock, flags); + + if (fib->fib_type == RTN_UNICAST) { + __be32 addr = cpu_to_be32(feni->dst); + __be32 mask = cpu_to_be32(0xffffffff << (32 - feni->dst_len)); + __be32 gw_addr = fib_nh->fib_nh_gw4; + + netdev_info(rmon->ndev, + "%s ucast route info: addr %pI4b mask %pI4b gw %pI4b\n", + keep ? "set" : "unset", &addr, &mask, &gw_addr); + rmon_update_ipv4_route(rmon, addr, mask, gw_addr, keep); + } else if (fib->fib_type == RTN_LOCAL) { + __be32 addr = cpu_to_be32(feni->dst); + + netdev_info(rmon->ndev, "%s local route info: addr %pI4b\n", + keep ? "set" : "unset", &addr); + rmon_update_ipv4_route_exception(rmon, + &rmon->ipv4_local_route_list, + addr, keep); + } else if (fib->fib_type == RTN_BROADCAST) { + __be32 addr = cpu_to_be32(feni->dst); + + netdev_info(rmon->ndev, "%s bcast route info: addr %pI4b\n", + keep ? "set" : "unset", &addr); + rmon_update_ipv4_route_exception(rmon, + &rmon->ipv4_bcast_route_list, + addr, keep); + } + + spin_unlock_irqrestore(&rmon->lock, flags); +} + +static int rmon_fib_event(struct notifier_block *nb, + unsigned long event, void *ptr) +{ + struct rswitch_route_monitor *rmon = + container_of(nb, typeof(*rmon), fib_nb); + struct fib_notifier_info *info = ptr; + + /* Handle only IPv4 for now */ + if (info->family == AF_INET) { + if (event == FIB_EVENT_ENTRY_REPLACE) + rmon_ipv4_fib_update(rmon, info, true); + else if (event == FIB_EVENT_ENTRY_DEL) + rmon_ipv4_fib_update(rmon, info, false); + } + + return NOTIFY_DONE; +} + +int rmon_init(struct rswitch_route_monitor *rmon, + struct net_device *ndev) +{ + int ret; + + if (WARN_ON(!is_rdev(ndev))) + return -EOPNOTSUPP; + + rmon->ndev = ndev; + INIT_LIST_HEAD(&rmon->ipv4_local_route_list); + INIT_LIST_HEAD(&rmon->ipv4_bcast_route_list); + INIT_LIST_HEAD(&rmon->ipv4_ucast_route_list); + + spin_lock_init(&rmon->lock); + + rmon->fib_nb.notifier_call = rmon_fib_event; + ret = register_fib_notifier(&init_net, &rmon->fib_nb, NULL, NULL); + if (ret) + return ret; + + return 0; +} + +void rmon_cleanup(struct rswitch_route_monitor *rmon) +{ + /* Per experiment, on module unload path the route lists are not + * cleaned up via fib events. Thus have to clean explicitly. + * + * This runs when fib_notifier is already unregistered, which includes + * synchronization. No parallel route lists manipulation should be + * possible. Thus no locking needed. + */ + + struct rmon_ipv4_route_exception *exception, *tmp_expection; + struct rmon_ipv4_route *route, *tmp_route; + unsigned long flags; + + unregister_fib_notifier(&init_net, &rmon->fib_nb); + + /* Notifier unregister does not send any cleanup events, so clean up + * gathered information manually. + * + * For paranoid safety, still take the lock + */ + + spin_lock_irqsave(&rmon->lock, flags); + + list_for_each_entry_safe(exception, tmp_expection, + &rmon->ipv4_local_route_list, list) { + list_del(&exception->list); + kfree(exception); + } + + list_for_each_entry_safe(exception, tmp_expection, + &rmon->ipv4_bcast_route_list, list) { + list_del(&exception->list); + kfree(exception); + } + + list_for_each_entry_safe(route, tmp_route, + &rmon->ipv4_ucast_route_list, list) { + /* offloads must have been cleared at netdev close time */ + WARN_ON(!list_empty(&route->offload_list)); + + list_del(&route->list); + kfree(exception); + } + + spin_unlock_irqrestore(&rmon->lock, flags); +} diff --git a/drivers/net/ethernet/renesas/rswitch_l3.h b/drivers/net/ethernet/renesas/rswitch_l3.h new file mode 100644 index 000000000000..10866883220b --- /dev/null +++ b/drivers/net/ethernet/renesas/rswitch_l3.h @@ -0,0 +1,24 @@ +/* SPDX-License-Identifier: GPL-2.0 */ +/* Renesas Ethernet Switch device driver + * + * Copyright (C) 2025 Renesas Electronics Corporation + */ + +#ifndef __RSWITCH_L3_H__ +#define __RSWITCH_L3_H__ + +#include <linux/kernel.h> +#include <linux/list.h> +#include <linux/spinlock.h> + +void rswitch_update_l3_offload(struct rswitch_private *priv); + +void rmon_handle_l3_learning(struct rswitch_route_monitor *rmon, + struct sk_buff *skb); +void rmon_cleanup_ipv4_offloads_all(struct rswitch_route_monitor *rmon); + +int rmon_init(struct rswitch_route_monitor *rmon, struct net_device *ndev); + +void rmon_cleanup(struct rswitch_route_monitor *rmon); + +#endif /* #ifndef __RSWITCH3_L3_H__ */ diff --git a/drivers/net/ethernet/renesas/rswitch_main.c b/drivers/net/ethernet/renesas/rswitch_main.c index e92b5cdffd10..8d56ef037a8d 100644 --- a/drivers/net/ethernet/renesas/rswitch_main.c +++ b/drivers/net/ethernet/renesas/rswitch_main.c @@ -29,8 +29,9 @@ #include "rswitch.h" #include "rswitch_l2.h" +#include "rswitch_l3.h" -static int rswitch_reg_wait(void __iomem *addr, u32 offs, u32 mask, u32 expected) +int rswitch_reg_wait(void __iomem *addr, u32 offs, u32 mask, u32 expected) { u32 val; @@ -118,6 +119,7 @@ static int rswitch_fwd_init(struct rswitch_private *priv) u32 all_ports_mask = GENMASK(RSWITCH_NUM_AGENTS - 1, 0); unsigned int i; u32 reg_val; + int ret; /* Start with empty configuration */ for (i = 0; i < RSWITCH_NUM_AGENTS; i++) { @@ -162,7 +164,49 @@ static int rswitch_fwd_init(struct rswitch_private *priv) /* Initialize MAC hash table */ iowrite32(FWMACTIM_MACTIOG, priv->addr + FWMACTIM); - return rswitch_reg_wait(priv->addr, FWMACTIM, FWMACTIM_MACTIOG, 0); + ret = rswitch_reg_wait(priv->addr, FWMACTIM, FWMACTIM_MACTIOG, 0); + if (ret) + return ret; + + /* Initialize hardware L3 forwarding */ + + /* Allow entire stream table to be used for "non-secure" entries */ + rswitch_modify(priv->addr, FWLTHHEC, FWLTHHEC_HMUE, + FIELD_PREP(FWLTHHEC_HMUE, 1 << RSWITCH_LTH_STREAM_W)); + + /* Include only dst_ip (and frame type) in ipv4 stream id */ + iowrite32(FWIP4SC_IIDS, priv->addr + FWIP4SC); + + /* Initialize stream hash table */ + iowrite32(FWLTHTIM_TIOG, priv->addr + FWLTHTIM); + ret = rswitch_reg_wait(priv->addr, FWLTHTIM, FWLTHTIM_TR, FWLTHTIM_TR); + if (ret) + return ret; + + /* Allow access to frame update rules from "non-secure" APB */ + iowrite32(0xffffffff, priv->addr + FWSCR34); +#if RSWITCH_LTH_RRULE_W >= 6 + iowrite32(0xffffffff, priv->addr + FWSCR33); +#endif +#if RSWITCH_LTH_RRULE_W >= 7 + iowrite32(0xffffffff, priv->addr + FWSCR32); + iowrite32(0xffffffff, priv->addr + FWSCR31); +#endif +#if RSWITCH_LTH_RRULE_W >= 8 + iowrite32(0xffffffff, priv->addr + FWSCR30); + iowrite32(0xffffffff, priv->addr + FWSCR29); + iowrite32(0xffffffff, priv->addr + FWSCR28); + iowrite32(0xffffffff, priv->addr + FWSCR27); +#endif + + /* Initialize frame update rules table */ + iowrite32(FWL23UTIM_TIOG, priv->addr + FWL23UTIM); + ret = rswitch_reg_wait(priv->addr, FWL23UTIM, FWL23UTIM_TR, FWL23UTIM_TR); + if (ret) + return ret; + + return 0; + } /* Gateway CPU agent block (GWCA) */ @@ -1644,6 +1688,9 @@ static int rswitch_open(struct net_device *ndev) if (rdev->brdev) rswitch_update_l2_offload(rdev->priv); + if (!netdev_has_any_upper_dev(ndev)) + rswitch_update_l3_offload(rdev->priv); + return 0; } @@ -1669,6 +1716,9 @@ static int rswitch_stop(struct net_device *ndev) if (rdev->brdev) rswitch_update_l2_offload(rdev->priv); + if (!netdev_has_any_upper_dev(ndev)) + rswitch_update_l3_offload(rdev->priv); + if (bitmap_empty(rdev->priv->opened_ports, RSWITCH_NUM_PORTS)) iowrite32(GWCA_TS_IRQ_BIT, rdev->priv->addr + GWTSDID); @@ -1757,9 +1807,15 @@ static netdev_tx_t rswitch_start_xmit(struct sk_buff *skb, struct net_device *nd netdev_tx_t ret = NETDEV_TX_OK; struct rswitch_ext_desc *desc; unsigned int i, nr_desc; + unsigned long flags; u8 die_dt; u16 len; + spin_lock_irqsave(&rdev->rmon.lock, flags); + if (rdev->l3_offload_enabled) + rmon_handle_l3_learning(&rdev->rmon, skb); + spin_unlock_irqrestore(&rdev->rmon.lock, flags); + nr_desc = (skb->len - 1) / RSWITCH_DESC_BUF_SIZE + 1; if (rswitch_get_num_cur_queues(gq) >= gq->ring_size - nr_desc) { netif_stop_subqueue(ndev, 0); @@ -2024,6 +2080,10 @@ static int rswitch_device_alloc(struct rswitch_private *priv, unsigned int index if (err < 0) goto out_get_params; + err = rmon_init(&rdev->rmon, ndev); + if (err < 0) + goto out_rmon_init; + err = rswitch_rxdmac_alloc(ndev); if (err < 0) goto out_rxdmac; @@ -2039,6 +2099,7 @@ static int rswitch_device_alloc(struct rswitch_private *priv, unsigned int index out_txdmac: rswitch_rxdmac_free(ndev); +out_rmon_init: out_rxdmac: out_get_params: of_node_put(rdev->np_port); @@ -2054,6 +2115,7 @@ static void rswitch_device_free(struct rswitch_private *priv, unsigned int index struct net_device *ndev = rdev->ndev; list_del(&rdev->list); + rmon_cleanup(&rdev->rmon); rswitch_txdmac_free(ndev); rswitch_rxdmac_free(ndev); of_node_put(rdev->np_port); @@ -2187,6 +2249,9 @@ static int renesas_eth_sw_probe(struct platform_device *pdev) return -ENOMEM; spin_lock_init(&priv->lock); + spin_lock_init(&priv->l3_lock); + + INIT_LIST_HEAD(&priv->l23_update_list); priv->clk = devm_clk_get(&pdev->dev, NULL); if (IS_ERR(priv->clk)) -- 2.43.0 ^ permalink raw reply related [flat|nested] 23+ messages in thread
* Re: [PATCH net-next 09/10] net: renesas: rswitch: add simple l3 routing 2025-11-06 12:55 ` [PATCH net-next 09/10] net: renesas: rswitch: add simple l3 routing Michael Dege @ 2025-11-07 2:32 ` Andrew Lunn 2025-11-07 10:02 ` Nikita Yushchenko 2025-11-07 13:35 ` Michael Dege 0 siblings, 2 replies; 23+ messages in thread From: Andrew Lunn @ 2025-11-07 2:32 UTC (permalink / raw) To: Michael Dege Cc: Yoshihiro Shimoda, Andrew Lunn, David S. Miller, Eric Dumazet, Jakub Kicinski, Paolo Abeni, Richard Cochran, Niklas Söderlund, Paul Barker, Rob Herring, Krzysztof Kozlowski, Conor Dooley, Geert Uytterhoeven, Magnus Damm, netdev, linux-renesas-soc, linux-kernel, devicetree, Nikita Yushchenko, Christophe JAILLET > +void rswitch_update_l3_offload(struct rswitch_private *priv) > +{ > + u32 all_ports_mask = GENMASK(RSWITCH_NUM_AGENTS - 1, 0); > + struct rswitch_device *rdev; > + bool l3_offload_enable_cond; > + u32 l3_rdev_count; > + u32 l3_ports_mask; > + > + l3_ports_mask = all_ports_mask; > + > + l3_rdev_count = 0; > + rswitch_for_all_ports(priv, rdev) { > + if (rdev_for_l3_offload(rdev)) { > + l3_rdev_count++; > + l3_ports_mask &= ~BIT(rdev->port); > + } > + } > + > + l3_offload_enable_cond = (l3_rdev_count >= 2); > + > +#define FWPC0_L3_MASK (FWPC0_LTHTA | FWPC0_IP4UE | FWPC0_IP4TE | FWPC0_IP4OE) > + rswitch_for_all_ports(priv, rdev) { > + if (rdev_for_l3_offload(rdev) && l3_offload_enable_cond) { > + /* Update allowed offload destinations even for ports > + * with l3 offload enabled earlier. > + * > + * Allow offload routing to self for hw port. > + */ > + rswitch_modify(priv->addr, FWPC1(rdev->port), > + FWPC1_LTHFW_MASK, > + FIELD_PREP(FWPC1_LTHFW_MASK, l3_ports_mask)); > + if (!rdev->l3_offload_enabled) { > + rswitch_modify(priv->addr, FWPC0(rdev->port), > + 0, > + FWPC0_L3_MASK); > + rdev->l3_offload_enabled = 1; > + netdev_info(rdev->ndev, "starting l3 offload\n"); This, and the other netdev_info calls should probably be debug. > +static bool rswitch_l23update_hw_op(struct rswitch_private *priv, > + struct rswitch_l23update *update, > + bool install) > +{ > + u8 *dst_mac = update->spec.dst_mac; > + u32 val; > + int ret; > + > + val = FIELD_PREP(FWL23URL0_RN, update->index) | > + FIELD_PREP(FWL23URL0_PV, > + install ? GENMASK(RSWITCH_NUM_AGENTS - 1, 0) : 0); > + iowrite32(val, priv->addr + FWL23URL0); > + > + val = FWL23URL1_TTLU | > + FWL23URL1_MSAU | > + FWL23URL1_MDAU | > + (dst_mac[0] << 8) | (dst_mac[1] << 0); > + iowrite32(val, priv->addr + FWL23URL1); > + > + val = (dst_mac[2] << 24) | (dst_mac[3] << 16) | > + (dst_mac[4] << 8) | (dst_mac[5] << 0); > + iowrite32(val, priv->addr + FWL23URL2); > + > + iowrite32(0, priv->addr + FWL23URL3); > + > + /* Rule write starts after writing to FWL23URL3 */ > + > + ret = rswitch_reg_wait(priv->addr, FWL23URLR, FWL23URLR_L, 0); > + if (ret) { > + dev_err(&priv->pdev->dev, "timeout writing l23_update\n"); > + return false; Why not make this an int function and return -ETIMEDOUT? > +static bool rmon_ipv4_dst_offload_hw_op(struct rswitch_route_monitor *rmon, > + struct rmon_ipv4_dst_offload *offload, > + u8 frame_type, bool install) Why all this bool functions? Especially when you have calls returning error codes you are throwing away. > +static struct rswitch_l23update *rswitch_get_l23update(struct rswitch_private *priv, > + struct rswitch_l23update_spec *spec) > +{ > + struct rswitch_l23update *update; > + > + spin_lock(&priv->l3_lock); > + > + list_for_each_entry(update, &priv->l23_update_list, list) { > + if (rswitch_l23update_matches_spec(update, spec)) { > + update->use_count++; > + goto out; > + } > + } > + > + update = kzalloc(sizeof(*update), GFP_ATOMIC); > + if (!update) > + goto out; > + > + update->use_count = 1; > + update->spec = *spec; > + update->index = find_first_zero_bit(priv->l23_update_bitmap, > + RSWITCH_MAX_NUM_RRULE); > + if (update->index == RSWITCH_MAX_NUM_RRULE) { > + dev_err_ratelimited(&priv->pdev->dev, > + "out of l23_update entries\n"); > + /* FIXME: trigger expire? */ > + goto no_free_bit; > + } > + set_bit(update->index, priv->l23_update_bitmap); > + > + if (!rswitch_l23update_hw_op(priv, update, true)) > + goto hw_op_failed; > + > + list_add(&update->list, &priv->l23_update_list); > +out: > + spin_unlock(&priv->l3_lock); > + > + return update; > + > +hw_op_failed: > + clear_bit(update->index, priv->l23_update_bitmap); > +no_free_bit: > + kfree(update); > + update = NULL; > + goto out; It is pretty unusual to have a backwards goto, especially in error handling. This is one case where a scoped_guard() might make sense. Andrew ^ permalink raw reply [flat|nested] 23+ messages in thread
* Re: [PATCH net-next 09/10] net: renesas: rswitch: add simple l3 routing 2025-11-07 2:32 ` Andrew Lunn @ 2025-11-07 10:02 ` Nikita Yushchenko 2025-11-07 13:29 ` Michael Dege 2025-11-07 13:35 ` Michael Dege 1 sibling, 1 reply; 23+ messages in thread From: Nikita Yushchenko @ 2025-11-07 10:02 UTC (permalink / raw) To: Andrew Lunn, Michael Dege Cc: Yoshihiro Shimoda, Andrew Lunn, David S. Miller, Eric Dumazet, Jakub Kicinski, Paolo Abeni, Richard Cochran, Niklas Söderlund, Paul Barker, Rob Herring, Krzysztof Kozlowski, Conor Dooley, Geert Uytterhoeven, Magnus Damm, netdev, linux-renesas-soc, linux-kernel, devicetree, Christophe JAILLET >> +static bool rmon_ipv4_dst_offload_hw_op(struct rswitch_route_monitor *rmon, >> + struct rmon_ipv4_dst_offload *offload, >> + u8 frame_type, bool install) > > Why all this bool functions? Especially when you have calls returning > error codes you are throwing away. The original idea behind that was - this is "not success" from an optional optimization step, that is not exposed outside. If it fails to offload - then the stream will remain handled by software. But, there is a more interesting question about this patchset (that actually stopped me from submitting it when it was originally developed). What do people thing about the entire approach used to detect streams to offload? The situation is: - hardware is capable of doing L3 routing, with some (limited) packet update capabilities - rewrite DST MAC, decrease TTL, - there is interest to use that, because software L3 routing even at 1Gbps consumes significant CPU load, and for 5Gbps will likely not keep the speed at all (we did not have hw to try), - but - given the capabilities of hw are incomparably weaker than capabilities of linux networking, which approach to take to detect streams for offloading? Second question - how exactly to get the routing decision from the kernel stack, to apply it in hardware? I was not able to find any existing implementations of something similar... What the patchset actually implements is - maintains it's own shadow structures for (subset of) routing information, and generate offload rules based on that. This is definitely not elegant (because the same kernel where this code runs maintains full-scale routing structures). Also this is definitely breaking any complex cases - actually anything more complex than simple destination mask based routing. I was going to post this approach as RFC at some point, raising all these questions... but unfortunately I did not have a resource to complete that :( Nikita ^ permalink raw reply [flat|nested] 23+ messages in thread
* RE: [PATCH net-next 09/10] net: renesas: rswitch: add simple l3 routing 2025-11-07 10:02 ` Nikita Yushchenko @ 2025-11-07 13:29 ` Michael Dege 2025-11-07 13:46 ` Andrew Lunn 0 siblings, 1 reply; 23+ messages in thread From: Michael Dege @ 2025-11-07 13:29 UTC (permalink / raw) To: Nikita Yushchenko, Andrew Lunn Cc: Yoshihiro Shimoda, Andrew Lunn, David S. Miller, Eric Dumazet, Jakub Kicinski, Paolo Abeni, Richard Cochran, niklas.soderlund, Paul Barker, Rob Herring, Krzysztof Kozlowski, Conor Dooley, Geert Uytterhoeven, magnus.damm, netdev@vger.kernel.org, linux-renesas-soc@vger.kernel.org, linux-kernel@vger.kernel.org, devicetree@vger.kernel.org, Christophe JAILLET > -----Original Message----- > From: Nikita Yushchenko <nikita.yoush@cogentembedded.com> > Sent: Friday, November 7, 2025 11:02 AM > To: Andrew Lunn <andrew@lunn.ch>; Michael Dege <michael.dege@renesas.com> > Cc: Yoshihiro Shimoda <yoshihiro.shimoda.uh@renesas.com>; Andrew Lunn <andrew+netdev@lunn.ch>; David > S. Miller <davem@davemloft.net>; Eric Dumazet <edumazet@google.com>; Jakub Kicinski <kuba@kernel.org>; > Paolo Abeni <pabeni@redhat.com>; Richard Cochran <richardcochran@gmail.com>; niklas.soderlund > <niklas.soderlund@ragnatech.se>; Paul Barker <paul@pbarker.dev>; Rob Herring <robh@kernel.org>; > Krzysztof Kozlowski <krzk+dt@kernel.org>; Conor Dooley <conor+dt@kernel.org>; Geert Uytterhoeven > <geert+renesas@glider.be>; magnus.damm <magnus.damm@gmail.com>; netdev@vger.kernel.org; linux-renesas- > soc@vger.kernel.org; linux-kernel@vger.kernel.org; devicetree@vger.kernel.org; Christophe JAILLET > <christophe.jaillet@wanadoo.fr> > Subject: Re: [PATCH net-next 09/10] net: renesas: rswitch: add simple l3 routing > > >> +static bool rmon_ipv4_dst_offload_hw_op(struct rswitch_route_monitor *rmon, > >> + struct rmon_ipv4_dst_offload *offload, > >> + u8 frame_type, bool install) > > > > Why all this bool functions? Especially when you have calls returning > > error codes you are throwing away. > > The original idea behind that was - this is "not success" from an optional optimization step, that is > not exposed outside. If it fails to offload - then the stream will remain handled by software. > > > But, there is a more interesting question about this patchset (that actually stopped me from > submitting > it when it was originally developed). > > What do people thing about the entire approach used to detect streams to offload? > > The situation is: > - hardware is capable of doing L3 routing, with some (limited) packet update capabilities - rewrite > DST > MAC, decrease TTL, > - there is interest to use that, because software L3 routing even at 1Gbps consumes significant CPU > load, and for 5Gbps will likely not keep the speed at all (we did not have hw to try), > - but - given the capabilities of hw are incomparably weaker than capabilities of linux networking, > which approach to take to detect streams for offloading? > > Second question - how exactly to get the routing decision from the kernel stack, to apply it in > hardware? I was not able to find any existing implementations of something similar... > > What the patchset actually implements is - maintains it's own shadow structures for (subset of) > routing > information, and generate offload rules based on that. This is definitely not elegant (because the > same > kernel where this code runs maintains full-scale routing structures). Also this is definitely > breaking > any complex cases - actually anything more complex than simple destination mask based routing. > > I was going to post this approach as RFC at some point, raising all these questions... but > unfortunately I did not have a resource to complete that :( > > Nikita Hello Nikita, Thank you for stepping in and explaining the situation. Michael ________________________________ Renesas Electronics Europe GmbH Registered Office: Arcadiastrasse 10 DE-40472 Duesseldorf Commercial Registry: Duesseldorf, HRB 3708 Managing Director: Carsten Jauch VAT-No.: DE 14978647 Tax-ID-No: 105/5839/1793 Legal Disclaimer: This e-mail communication (and any attachment/s) is confidential and contains proprietary information, some or all of which may be legally privileged. It is intended solely for the use of the individual or entity to which it is addressed. Access to this email by anyone else is unauthorized. If you are not the intended recipient, any disclosure, copying, distribution or any action taken or omitted to be taken in reliance on it, is prohibited and may be unlawful. ^ permalink raw reply [flat|nested] 23+ messages in thread
* Re: [PATCH net-next 09/10] net: renesas: rswitch: add simple l3 routing 2025-11-07 13:29 ` Michael Dege @ 2025-11-07 13:46 ` Andrew Lunn 0 siblings, 0 replies; 23+ messages in thread From: Andrew Lunn @ 2025-11-07 13:46 UTC (permalink / raw) To: Michael Dege Cc: Nikita Yushchenko, Yoshihiro Shimoda, Andrew Lunn, David S. Miller, Eric Dumazet, Jakub Kicinski, Paolo Abeni, Richard Cochran, niklas.soderlund, Paul Barker, Rob Herring, Krzysztof Kozlowski, Conor Dooley, Geert Uytterhoeven, magnus.damm, netdev@vger.kernel.org, linux-renesas-soc@vger.kernel.org, linux-kernel@vger.kernel.org, devicetree@vger.kernel.org, Christophe JAILLET > > But, there is a more interesting question about this patchset (that actually stopped me from > > submitting > > it when it was originally developed). > > > > What do people thing about the entire approach used to detect streams to offload? > > > > The situation is: > > - hardware is capable of doing L3 routing, with some (limited) packet update capabilities - rewrite > > DST > > MAC, decrease TTL, > > - there is interest to use that, because software L3 routing even at 1Gbps consumes significant CPU > > load, and for 5Gbps will likely not keep the speed at all (we did not have hw to try), > > - but - given the capabilities of hw are incomparably weaker than capabilities of linux networking, > > which approach to take to detect streams for offloading? > > > > Second question - how exactly to get the routing decision from the kernel stack, to apply it in > > hardware? I was not able to find any existing implementations of something similar... You should probably look at how the mellanox switch does this. It is kind of the reference implementation. The sparx5 and prestera might have something, i don't remember their capabilities. Some of the mediatek devices also do interesting things with flows, but that is more for NAT, not necessarily L3 routing. Andrew ^ permalink raw reply [flat|nested] 23+ messages in thread
* RE: [PATCH net-next 09/10] net: renesas: rswitch: add simple l3 routing 2025-11-07 2:32 ` Andrew Lunn 2025-11-07 10:02 ` Nikita Yushchenko @ 2025-11-07 13:35 ` Michael Dege 1 sibling, 0 replies; 23+ messages in thread From: Michael Dege @ 2025-11-07 13:35 UTC (permalink / raw) To: Andrew Lunn Cc: Yoshihiro Shimoda, Andrew Lunn, David S. Miller, Eric Dumazet, Jakub Kicinski, Paolo Abeni, Richard Cochran, niklas.soderlund, Paul Barker, Rob Herring, Krzysztof Kozlowski, Conor Dooley, Geert Uytterhoeven, magnus.damm, netdev@vger.kernel.org, linux-renesas-soc@vger.kernel.org, linux-kernel@vger.kernel.org, devicetree@vger.kernel.org, Nikita Yushchenko, Christophe JAILLET > -----Original Message----- > From: Andrew Lunn <andrew@lunn.ch> > Sent: Friday, November 7, 2025 3:32 AM > To: Michael Dege <michael.dege@renesas.com> > Cc: Yoshihiro Shimoda <yoshihiro.shimoda.uh@renesas.com>; Andrew Lunn <andrew+netdev@lunn.ch>; David > S. Miller <davem@davemloft.net>; Eric Dumazet <edumazet@google.com>; Jakub Kicinski <kuba@kernel.org>; > Paolo Abeni <pabeni@redhat.com>; Richard Cochran <richardcochran@gmail.com>; niklas.soderlund > <niklas.soderlund@ragnatech.se>; Paul Barker <paul@pbarker.dev>; Rob Herring <robh@kernel.org>; > Krzysztof Kozlowski <krzk+dt@kernel.org>; Conor Dooley <conor+dt@kernel.org>; Geert Uytterhoeven > <geert+renesas@glider.be>; magnus.damm <magnus.damm@gmail.com>; netdev@vger.kernel.org; linux-renesas- > soc@vger.kernel.org; linux-kernel@vger.kernel.org; devicetree@vger.kernel.org; Nikita Yushchenko > <nikita.yoush@cogentembedded.com>; Christophe JAILLET <christophe.jaillet@wanadoo.fr> > Subject: Re: [PATCH net-next 09/10] net: renesas: rswitch: add simple l3 routing > > > +void rswitch_update_l3_offload(struct rswitch_private *priv) { > > + u32 all_ports_mask = GENMASK(RSWITCH_NUM_AGENTS - 1, 0); > > + struct rswitch_device *rdev; > > + bool l3_offload_enable_cond; > > + u32 l3_rdev_count; > > + u32 l3_ports_mask; > > + > > + l3_ports_mask = all_ports_mask; > > + > > + l3_rdev_count = 0; > > + rswitch_for_all_ports(priv, rdev) { > > + if (rdev_for_l3_offload(rdev)) { > > + l3_rdev_count++; > > + l3_ports_mask &= ~BIT(rdev->port); > > + } > > + } > > + > > + l3_offload_enable_cond = (l3_rdev_count >= 2); > > + > > +#define FWPC0_L3_MASK (FWPC0_LTHTA | FWPC0_IP4UE | FWPC0_IP4TE | FWPC0_IP4OE) > > + rswitch_for_all_ports(priv, rdev) { > > + if (rdev_for_l3_offload(rdev) && l3_offload_enable_cond) { > > + /* Update allowed offload destinations even for ports > > + * with l3 offload enabled earlier. > > + * > > + * Allow offload routing to self for hw port. > > + */ > > + rswitch_modify(priv->addr, FWPC1(rdev->port), > > + FWPC1_LTHFW_MASK, > > + FIELD_PREP(FWPC1_LTHFW_MASK, l3_ports_mask)); > > + if (!rdev->l3_offload_enabled) { > > + rswitch_modify(priv->addr, FWPC0(rdev->port), > > + 0, > > + FWPC0_L3_MASK); > > + rdev->l3_offload_enabled = 1; > > + netdev_info(rdev->ndev, "starting l3 offload\n"); > > This, and the other netdev_info calls should probably be debug. Thank you for the comment. I will update both places. > > > +static bool rswitch_l23update_hw_op(struct rswitch_private *priv, > > + struct rswitch_l23update *update, > > + bool install) > > +{ > > + u8 *dst_mac = update->spec.dst_mac; > > + u32 val; > > + int ret; > > + > > + val = FIELD_PREP(FWL23URL0_RN, update->index) | > > + FIELD_PREP(FWL23URL0_PV, > > + install ? GENMASK(RSWITCH_NUM_AGENTS - 1, 0) : 0); > > + iowrite32(val, priv->addr + FWL23URL0); > > + > > + val = FWL23URL1_TTLU | > > + FWL23URL1_MSAU | > > + FWL23URL1_MDAU | > > + (dst_mac[0] << 8) | (dst_mac[1] << 0); > > + iowrite32(val, priv->addr + FWL23URL1); > > + > > + val = (dst_mac[2] << 24) | (dst_mac[3] << 16) | > > + (dst_mac[4] << 8) | (dst_mac[5] << 0); > > + iowrite32(val, priv->addr + FWL23URL2); > > + > > + iowrite32(0, priv->addr + FWL23URL3); > > + > > + /* Rule write starts after writing to FWL23URL3 */ > > + > > + ret = rswitch_reg_wait(priv->addr, FWL23URLR, FWL23URLR_L, 0); > > + if (ret) { > > + dev_err(&priv->pdev->dev, "timeout writing l23_update\n"); > > + return false; > > Why not make this an int function and return -ETIMEDOUT? Good suggestion. I will rework the code accordingly. > > > +static bool rmon_ipv4_dst_offload_hw_op(struct rswitch_route_monitor *rmon, > > + struct rmon_ipv4_dst_offload *offload, > > + u8 frame_type, bool install) > > Why all this bool functions? Especially when you have calls returning error codes you are throwing > away. I will look at the code and make improvements. > > > +static struct rswitch_l23update *rswitch_get_l23update(struct rswitch_private *priv, > > + struct rswitch_l23update_spec *spec) { > > + struct rswitch_l23update *update; > > + > > + spin_lock(&priv->l3_lock); > > + > > + list_for_each_entry(update, &priv->l23_update_list, list) { > > + if (rswitch_l23update_matches_spec(update, spec)) { > > + update->use_count++; > > + goto out; > > + } > > + } > > + > > + update = kzalloc(sizeof(*update), GFP_ATOMIC); > > + if (!update) > > + goto out; > > + > > + update->use_count = 1; > > + update->spec = *spec; > > + update->index = find_first_zero_bit(priv->l23_update_bitmap, > > + RSWITCH_MAX_NUM_RRULE); > > + if (update->index == RSWITCH_MAX_NUM_RRULE) { > > + dev_err_ratelimited(&priv->pdev->dev, > > + "out of l23_update entries\n"); > > + /* FIXME: trigger expire? */ > > + goto no_free_bit; > > + } > > + set_bit(update->index, priv->l23_update_bitmap); > > + > > + if (!rswitch_l23update_hw_op(priv, update, true)) > > + goto hw_op_failed; > > + > > + list_add(&update->list, &priv->l23_update_list); > > +out: > > + spin_unlock(&priv->l3_lock); > > + > > + return update; > > + > > +hw_op_failed: > > + clear_bit(update->index, priv->l23_update_bitmap); > > +no_free_bit: > > + kfree(update); > > + update = NULL; > > + goto out; > > It is pretty unusual to have a backwards goto, especially in error handling. This is one case where a > scoped_guard() might make sense. Thank you for your comment I will investigate and rework it. Michael > > Andrew ________________________________ Renesas Electronics Europe GmbH Registered Office: Arcadiastrasse 10 DE-40472 Duesseldorf Commercial Registry: Duesseldorf, HRB 3708 Managing Director: Carsten Jauch VAT-No.: DE 14978647 Tax-ID-No: 105/5839/1793 Legal Disclaimer: This e-mail communication (and any attachment/s) is confidential and contains proprietary information, some or all of which may be legally privileged. It is intended solely for the use of the individual or entity to which it is addressed. Access to this email by anyone else is unauthorized. If you are not the intended recipient, any disclosure, copying, distribution or any action taken or omitted to be taken in reliance on it, is prohibited and may be unlawful. ^ permalink raw reply [flat|nested] 23+ messages in thread
* [PATCH net-next 10/10] net: renesas: rswitch: update error handling of probe 2025-11-06 12:55 [PATCH net-next 00/10] net: renesas: rswitch: R-Car S4 add HW offloading for layer 3 routing Michael Dege ` (8 preceding siblings ...) 2025-11-06 12:55 ` [PATCH net-next 09/10] net: renesas: rswitch: add simple l3 routing Michael Dege @ 2025-11-06 12:55 ` Michael Dege 2025-11-07 2:32 ` Andrew Lunn 9 siblings, 1 reply; 23+ messages in thread From: Michael Dege @ 2025-11-06 12:55 UTC (permalink / raw) To: Yoshihiro Shimoda, Andrew Lunn, David S. Miller, Eric Dumazet, Jakub Kicinski, Paolo Abeni, Richard Cochran, Niklas Söderlund, Paul Barker, Rob Herring, Krzysztof Kozlowski, Conor Dooley, Geert Uytterhoeven, Magnus Damm Cc: netdev, linux-renesas-soc, linux-kernel, devicetree, Nikita Yushchenko, Christophe JAILLET, Michael Dege From: Christophe JAILLET <christophe.jaillet@wanadoo.fr> Update error handling of probe function. Signed-off-by: Christophe JAILLET <christophe.jaillet@wanadoo.fr> Signed-off-by: Michael Dege <michael.dege@renesas.com> --- drivers/net/ethernet/renesas/rswitch_main.c | 63 ++++++++++++++++------------- 1 file changed, 34 insertions(+), 29 deletions(-) diff --git a/drivers/net/ethernet/renesas/rswitch_main.c b/drivers/net/ethernet/renesas/rswitch_main.c index 8d56ef037a8d..1d8f141a25d3 100644 --- a/drivers/net/ethernet/renesas/rswitch_main.c +++ b/drivers/net/ethernet/renesas/rswitch_main.c @@ -2231,6 +2231,30 @@ static const struct soc_device_attribute rswitch_soc_no_speed_change[] = { { /* Sentinel */ } }; +static void rswitch_deinit(struct rswitch_private *priv) +{ + unsigned int i; + + rswitch_gwca_hw_deinit(priv); + rcar_gen4_ptp_unregister(priv->ptp_priv); + + rswitch_for_each_enabled_port(priv, i) { + struct rswitch_device *rdev = priv->rdev[i]; + + unregister_netdev(rdev->ndev); + rswitch_ether_port_deinit_one(rdev); + phy_exit(priv->rdev[i]->serdes); + } + + for (i = 0; i < RSWITCH_NUM_PORTS; i++) + rswitch_device_free(priv, i); + + rswitch_gwca_ts_queue_free(priv); + rswitch_gwca_linkfix_free(priv); + + rswitch_clock_disable(priv); +} + static int renesas_eth_sw_probe(struct platform_device *pdev) { const struct soc_device_attribute *attr; @@ -2294,11 +2318,8 @@ static int renesas_eth_sw_probe(struct platform_device *pdev) pm_runtime_get_sync(&pdev->dev); ret = rswitch_init(priv); - if (ret < 0) { - pm_runtime_put(&pdev->dev); - pm_runtime_disable(&pdev->dev); - return ret; - } + if (ret < 0) + goto err_disable_pm_runtime; if (list_empty(&priv->port_list)) dev_warn(&pdev->dev, "could not initialize any ports\n"); @@ -2306,36 +2327,20 @@ static int renesas_eth_sw_probe(struct platform_device *pdev) ret = rswitch_register_notifiers(); if (ret) { dev_err(&pdev->dev, "could not register notifiers\n"); - return ret; + goto err_deinit_rswitch; } device_set_wakeup_capable(&pdev->dev, 1); - return ret; -} - -static void rswitch_deinit(struct rswitch_private *priv) -{ - unsigned int i; - - rswitch_gwca_hw_deinit(priv); - rcar_gen4_ptp_unregister(priv->ptp_priv); - - rswitch_for_each_enabled_port(priv, i) { - struct rswitch_device *rdev = priv->rdev[i]; - - unregister_netdev(rdev->ndev); - rswitch_ether_port_deinit_one(rdev); - phy_exit(priv->rdev[i]->serdes); - } - - for (i = 0; i < RSWITCH_NUM_PORTS; i++) - rswitch_device_free(priv, i); + return 0; - rswitch_gwca_ts_queue_free(priv); - rswitch_gwca_linkfix_free(priv); +err_deinit_rswitch: + rswitch_deinit(priv); +err_disable_pm_runtime: + pm_runtime_put(&pdev->dev); + pm_runtime_disable(&pdev->dev); - rswitch_clock_disable(priv); + return ret; } static void renesas_eth_sw_remove(struct platform_device *pdev) -- 2.43.0 ^ permalink raw reply related [flat|nested] 23+ messages in thread
* Re: [PATCH net-next 10/10] net: renesas: rswitch: update error handling of probe 2025-11-06 12:55 ` [PATCH net-next 10/10] net: renesas: rswitch: update error handling of probe Michael Dege @ 2025-11-07 2:32 ` Andrew Lunn 0 siblings, 0 replies; 23+ messages in thread From: Andrew Lunn @ 2025-11-07 2:32 UTC (permalink / raw) To: Michael Dege Cc: Yoshihiro Shimoda, Andrew Lunn, David S. Miller, Eric Dumazet, Jakub Kicinski, Paolo Abeni, Richard Cochran, Niklas Söderlund, Paul Barker, Rob Herring, Krzysztof Kozlowski, Conor Dooley, Geert Uytterhoeven, Magnus Damm, netdev, linux-renesas-soc, linux-kernel, devicetree, Nikita Yushchenko, Christophe JAILLET On Thu, Nov 06, 2025 at 01:55:34PM +0100, Michael Dege wrote: > From: Christophe JAILLET <christophe.jaillet@wanadoo.fr> > > Update error handling of probe function. What is wrong with it? Andrew ^ permalink raw reply [flat|nested] 23+ messages in thread
end of thread, other threads:[~2025-11-07 13:46 UTC | newest] Thread overview: 23+ messages (download: mbox.gz follow: Atom feed -- links below jump to the message on this page -- 2025-11-06 12:55 [PATCH net-next 00/10] net: renesas: rswitch: R-Car S4 add HW offloading for layer 3 routing Michael Dege 2025-11-06 12:55 ` [PATCH net-next 01/10] net: renesas: rswitch: cleanup MII settings Michael Dege 2025-11-06 12:55 ` [PATCH net-next 02/10] net: renesas: rswitch: enable Phy link status pin Michael Dege 2025-11-07 1:16 ` Andrew Lunn 2025-11-07 13:37 ` Michael Dege 2025-11-06 12:55 ` [PATCH net-next 03/10] dt-bindings: net: renesas,r8a779f0-ether-switch.yaml: add optional property link-pin Michael Dege 2025-11-06 13:41 ` Geert Uytterhoeven 2025-11-06 14:19 ` Rob Herring (Arm) 2025-11-06 17:16 ` Conor Dooley 2025-11-06 12:55 ` [PATCH net-next 04/10] arm64: dts: renesas: r8a779f4-s4sk.dts add link-pin property Michael Dege 2025-11-06 12:55 ` [PATCH net-next 05/10] arm64: dts: renesas: r8a779f0-spider-ethernet.dtsi " Michael Dege 2025-11-06 12:55 ` [PATCH net-next 06/10] net: renesas: rswitch: add MAC address filtering Michael Dege 2025-11-07 1:18 ` Andrew Lunn 2025-11-06 12:55 ` [PATCH net-next 07/10] net: renesas: rswitch: fix FWPCx register names Michael Dege 2025-11-06 12:55 ` [PATCH net-next 08/10] net: renesas: rswitch: add bit access macros for forwarding engine Michael Dege 2025-11-06 12:55 ` [PATCH net-next 09/10] net: renesas: rswitch: add simple l3 routing Michael Dege 2025-11-07 2:32 ` Andrew Lunn 2025-11-07 10:02 ` Nikita Yushchenko 2025-11-07 13:29 ` Michael Dege 2025-11-07 13:46 ` Andrew Lunn 2025-11-07 13:35 ` Michael Dege 2025-11-06 12:55 ` [PATCH net-next 10/10] net: renesas: rswitch: update error handling of probe Michael Dege 2025-11-07 2:32 ` Andrew Lunn
This is a public inbox, see mirroring instructions for how to clone and mirror all data and code used for this inbox; as well as URLs for NNTP newsgroup(s).