* [PATCH net-next v2 1/5] net: dsa: realtek: rtl83xx: Make learning optional in join/leave
2026-06-30 11:19 [PATCH net-next v2 0/5] net: dsa: realtek: rtl8366rb: Use generic RTL83xx code Linus Walleij
@ 2026-06-30 11:19 ` Linus Walleij
2026-07-03 13:13 ` Luiz Angelo Daros de Luca
2026-06-30 11:19 ` [PATCH net-next v2 2/5] net: dsa: realtek: rtl8366rb: Switch to generic port_bridge* handlers Linus Walleij
` (4 subsequent siblings)
5 siblings, 1 reply; 13+ messages in thread
From: Linus Walleij @ 2026-06-30 11:19 UTC (permalink / raw)
To: Luiz Angelo Daros de Luca, Alvin Šipraga, Andrew Lunn,
Vladimir Oltean, David S. Miller, Eric Dumazet, Jakub Kicinski,
Paolo Abeni
Cc: netdev, Linus Walleij
Mostly to make it possible to add rtl83xx support piece by piece,
make the port learning callback optional in rtl83xx_port_bridge_join()
and rtl83xx_port_bridge_leave().
Signed-off-by: Linus Walleij <linusw@kernel.org>
---
drivers/net/dsa/realtek/rtl83xx.c | 26 ++++++++++++--------------
1 file changed, 12 insertions(+), 14 deletions(-)
diff --git a/drivers/net/dsa/realtek/rtl83xx.c b/drivers/net/dsa/realtek/rtl83xx.c
index 71124ecca92f..90843d52c5a8 100644
--- a/drivers/net/dsa/realtek/rtl83xx.c
+++ b/drivers/net/dsa/realtek/rtl83xx.c
@@ -356,9 +356,6 @@ int rtl83xx_port_bridge_join(struct dsa_switch *ds, int port,
if (!priv->ops->port_add_isolation)
return -EOPNOTSUPP;
- if (!priv->ops->port_set_learning)
- return -EOPNOTSUPP;
-
dev_dbg(priv->dev, "bridge %d join port %d\n", bridge.num, port);
/* Add this port to the isolation group of every other port
@@ -396,9 +393,11 @@ int rtl83xx_port_bridge_join(struct dsa_switch *ds, int port,
goto undo_self_isolation;
}
- ret = priv->ops->port_set_learning(priv, port, true);
- if (ret)
- goto undo_efid;
+ if (priv->ops->port_set_learning) {
+ ret = priv->ops->port_set_learning(priv, port, true);
+ if (ret)
+ goto undo_efid;
+ }
return 0;
@@ -443,9 +442,6 @@ void rtl83xx_port_bridge_leave(struct dsa_switch *ds, int port,
if (!priv->ops->port_remove_isolation)
return;
- if (!priv->ops->port_set_learning)
- return;
-
dev_dbg(priv->dev, "bridge %d leave port %d\n", bridge.num, port);
/* Remove this port from the isolation group of every other
@@ -474,11 +470,13 @@ void rtl83xx_port_bridge_leave(struct dsa_switch *ds, int port,
* downstream DSA ports from the isolation group.
*/
- ret = priv->ops->port_set_learning(priv, port, false);
- if (ret)
- dev_err(priv->dev,
- "failed to disable learning on port %d: %pe\n",
- port, ERR_PTR(ret));
+ if (priv->ops->port_set_learning) {
+ ret = priv->ops->port_set_learning(priv, port, false);
+ if (ret)
+ dev_err(priv->dev,
+ "failed to disable learning on port %d: %pe\n",
+ port, ERR_PTR(ret));
+ }
/* Remove those ports from the isolation group of this port */
ret = priv->ops->port_remove_isolation(priv, port, mask);
--
2.54.0
^ permalink raw reply related [flat|nested] 13+ messages in thread* [PATCH net-next v2 2/5] net: dsa: realtek: rtl8366rb: Switch to generic port_bridge* handlers
2026-06-30 11:19 [PATCH net-next v2 0/5] net: dsa: realtek: rtl8366rb: Use generic RTL83xx code Linus Walleij
2026-06-30 11:19 ` [PATCH net-next v2 1/5] net: dsa: realtek: rtl83xx: Make learning optional in join/leave Linus Walleij
@ 2026-06-30 11:19 ` Linus Walleij
2026-07-03 13:15 ` Luiz Angelo Daros de Luca
2026-07-03 13:24 ` Luiz Angelo Daros de Luca
2026-06-30 11:19 ` [PATCH net-next v2 3/5] net: dsa: realtek: rtl8366rb: Use DSA port iterators Linus Walleij
` (3 subsequent siblings)
5 siblings, 2 replies; 13+ messages in thread
From: Linus Walleij @ 2026-06-30 11:19 UTC (permalink / raw)
To: Luiz Angelo Daros de Luca, Alvin Šipraga, Andrew Lunn,
Vladimir Oltean, David S. Miller, Eric Dumazet, Jakub Kicinski,
Paolo Abeni
Cc: netdev, Linus Walleij
The RTL8366RB is using its own sub-standard port isolation code.
Implement the required isolation helpers, use these directly in
the port setup callback, and switch over to the standard port
isolation code.
Signed-off-by: Linus Walleij <linusw@kernel.org>
---
drivers/net/dsa/realtek/rtl8366rb.c | 108 ++++++++++++------------------------
1 file changed, 36 insertions(+), 72 deletions(-)
diff --git a/drivers/net/dsa/realtek/rtl8366rb.c b/drivers/net/dsa/realtek/rtl8366rb.c
index 103039fe3086..8b57ef3bf03a 100644
--- a/drivers/net/dsa/realtek/rtl8366rb.c
+++ b/drivers/net/dsa/realtek/rtl8366rb.c
@@ -791,6 +791,35 @@ static int rtl8366rb_setup_all_leds_off(struct realtek_priv *priv)
return ret;
}
+static int rtl8366rb_port_set_isolation(struct realtek_priv *priv, int port,
+ u32 mask)
+{
+ /* Bit 0 enables isolation so set this if we enable isolation
+ * any of the ports an clear it if we disable on all of them.
+ */
+ if (mask)
+ mask = RTL8366RB_PORT_ISO_PORTS(mask) | RTL8366RB_PORT_ISO_EN;
+
+ return regmap_write(priv->map, RTL8366RB_PORT_ISO(port),
+ mask);
+}
+
+static int rtl8366rb_port_add_isolation(struct realtek_priv *priv, int port,
+ u32 mask)
+{
+ /* We assume isolation bit is on */
+ return regmap_update_bits(priv->map, RTL8366RB_PORT_ISO(port),
+ RTL8366RB_PORT_ISO_PORTS(mask),
+ RTL8366RB_PORT_ISO_PORTS(mask));
+}
+
+static int rtl8366rb_port_remove_isolation(struct realtek_priv *priv, int port,
+ u32 mask)
+{
+ return regmap_update_bits(priv->map, RTL8366RB_PORT_ISO(port),
+ RTL8366RB_PORT_ISO_PORTS(mask), 0);
+}
+
static int rtl8366rb_setup(struct dsa_switch *ds)
{
struct realtek_priv *priv = ds->priv;
@@ -868,16 +897,13 @@ static int rtl8366rb_setup(struct dsa_switch *ds)
/* Isolate all user ports so they can only send packets to itself and the CPU port */
for (i = 0; i < RTL8366RB_PORT_NUM_CPU; i++) {
- ret = regmap_write(priv->map, RTL8366RB_PORT_ISO(i),
- RTL8366RB_PORT_ISO_PORTS(BIT(RTL8366RB_PORT_NUM_CPU)) |
- RTL8366RB_PORT_ISO_EN);
+ ret = rtl8366rb_port_set_isolation(priv, i, BIT(RTL8366RB_PORT_NUM_CPU));
if (ret)
return ret;
}
/* CPU port can send packets to all ports */
- ret = regmap_write(priv->map, RTL8366RB_PORT_ISO(RTL8366RB_PORT_NUM_CPU),
- RTL8366RB_PORT_ISO_PORTS(dsa_user_ports(ds)) |
- RTL8366RB_PORT_ISO_EN);
+ ret = rtl8366rb_port_set_isolation(priv, RTL8366RB_PORT_NUM_CPU,
+ dsa_user_ports(ds));
if (ret)
return ret;
@@ -1184,70 +1210,6 @@ rtl8366rb_port_disable(struct dsa_switch *ds, int port)
return;
}
-static int
-rtl8366rb_port_bridge_join(struct dsa_switch *ds, int port,
- struct dsa_bridge bridge,
- bool *tx_fwd_offload,
- struct netlink_ext_ack *extack)
-{
- struct realtek_priv *priv = ds->priv;
- unsigned int port_bitmap = 0;
- int ret, i;
-
- /* Loop over all other ports than the current one */
- for (i = 0; i < RTL8366RB_PORT_NUM_CPU; i++) {
- /* Current port handled last */
- if (i == port)
- continue;
- /* Not on this bridge */
- if (!dsa_port_offloads_bridge(dsa_to_port(ds, i), &bridge))
- continue;
- /* Join this port to each other port on the bridge */
- ret = regmap_update_bits(priv->map, RTL8366RB_PORT_ISO(i),
- RTL8366RB_PORT_ISO_PORTS(BIT(port)),
- RTL8366RB_PORT_ISO_PORTS(BIT(port)));
- if (ret)
- dev_err(priv->dev, "failed to join port %d\n", port);
-
- port_bitmap |= BIT(i);
- }
-
- /* Set the bits for the ports we can access */
- return regmap_update_bits(priv->map, RTL8366RB_PORT_ISO(port),
- RTL8366RB_PORT_ISO_PORTS(port_bitmap),
- RTL8366RB_PORT_ISO_PORTS(port_bitmap));
-}
-
-static void
-rtl8366rb_port_bridge_leave(struct dsa_switch *ds, int port,
- struct dsa_bridge bridge)
-{
- struct realtek_priv *priv = ds->priv;
- unsigned int port_bitmap = 0;
- int ret, i;
-
- /* Loop over all other ports than this one */
- for (i = 0; i < RTL8366RB_PORT_NUM_CPU; i++) {
- /* Current port handled last */
- if (i == port)
- continue;
- /* Not on this bridge */
- if (!dsa_port_offloads_bridge(dsa_to_port(ds, i), &bridge))
- continue;
- /* Remove this port from any other port on the bridge */
- ret = regmap_update_bits(priv->map, RTL8366RB_PORT_ISO(i),
- RTL8366RB_PORT_ISO_PORTS(BIT(port)), 0);
- if (ret)
- dev_err(priv->dev, "failed to leave port %d\n", port);
-
- port_bitmap |= BIT(i);
- }
-
- /* Clear the bits for the ports we can not access, leave ourselves */
- regmap_update_bits(priv->map, RTL8366RB_PORT_ISO(port),
- RTL8366RB_PORT_ISO_PORTS(port_bitmap), 0);
-}
-
/**
* rtl8366rb_drop_untagged() - make the switch drop untagged and C-tagged frames
* @priv: SMI state container
@@ -1801,8 +1763,8 @@ static const struct dsa_switch_ops rtl8366rb_switch_ops = {
.get_strings = rtl8366_get_strings,
.get_ethtool_stats = rtl8366_get_ethtool_stats,
.get_sset_count = rtl8366_get_sset_count,
- .port_bridge_join = rtl8366rb_port_bridge_join,
- .port_bridge_leave = rtl8366rb_port_bridge_leave,
+ .port_bridge_join = rtl83xx_port_bridge_join,
+ .port_bridge_leave = rtl83xx_port_bridge_leave,
.port_vlan_filtering = rtl8366rb_vlan_filtering,
.port_vlan_add = rtl8366_vlan_add,
.port_vlan_del = rtl8366_vlan_del,
@@ -1830,6 +1792,8 @@ static const struct realtek_ops rtl8366rb_ops = {
.is_vlan_valid = rtl8366rb_is_vlan_valid,
.enable_vlan = rtl8366rb_enable_vlan,
.enable_vlan4k = rtl8366rb_enable_vlan4k,
+ .port_add_isolation = rtl8366rb_port_add_isolation,
+ .port_remove_isolation = rtl8366rb_port_remove_isolation,
.phy_read = rtl8366rb_phy_read,
.phy_write = rtl8366rb_phy_write,
};
--
2.54.0
^ permalink raw reply related [flat|nested] 13+ messages in thread* Re: [PATCH net-next v2 2/5] net: dsa: realtek: rtl8366rb: Switch to generic port_bridge* handlers
2026-06-30 11:19 ` [PATCH net-next v2 2/5] net: dsa: realtek: rtl8366rb: Switch to generic port_bridge* handlers Linus Walleij
@ 2026-07-03 13:15 ` Luiz Angelo Daros de Luca
2026-07-03 13:24 ` Luiz Angelo Daros de Luca
1 sibling, 0 replies; 13+ messages in thread
From: Luiz Angelo Daros de Luca @ 2026-07-03 13:15 UTC (permalink / raw)
To: Linus Walleij
Cc: Alvin Šipraga, Andrew Lunn, Vladimir Oltean, David S. Miller,
Eric Dumazet, Jakub Kicinski, Paolo Abeni, netdev
Em ter., 30 de jun. de 2026 às 08:19, Linus Walleij
<linusw@kernel.org> escreveu:
>
> The RTL8366RB is using its own sub-standard port isolation code.
>
> Implement the required isolation helpers, use these directly in
> the port setup callback, and switch over to the standard port
> isolation code.
>
> Signed-off-by: Linus Walleij <linusw@kernel.org>
Reviewed-by: Luiz Angelo Daros de Luca <luizluca@gmail.com>
^ permalink raw reply [flat|nested] 13+ messages in thread
* Re: [PATCH net-next v2 2/5] net: dsa: realtek: rtl8366rb: Switch to generic port_bridge* handlers
2026-06-30 11:19 ` [PATCH net-next v2 2/5] net: dsa: realtek: rtl8366rb: Switch to generic port_bridge* handlers Linus Walleij
2026-07-03 13:15 ` Luiz Angelo Daros de Luca
@ 2026-07-03 13:24 ` Luiz Angelo Daros de Luca
2026-07-03 21:17 ` Linus Walleij
1 sibling, 1 reply; 13+ messages in thread
From: Luiz Angelo Daros de Luca @ 2026-07-03 13:24 UTC (permalink / raw)
To: Linus Walleij
Cc: Alvin Šipraga, Andrew Lunn, Vladimir Oltean, David S. Miller,
Eric Dumazet, Jakub Kicinski, Paolo Abeni, netdev
> +static int rtl8366rb_port_set_isolation(struct realtek_priv *priv, int port,
> + u32 mask)
> +{
> + /* Bit 0 enables isolation so set this if we enable isolation
> + * any of the ports an clear it if we disable on all of them.
> + */
> + if (mask)
> + mask = RTL8366RB_PORT_ISO_PORTS(mask) | RTL8366RB_PORT_ISO_EN;
> +
> + return regmap_write(priv->map, RTL8366RB_PORT_ISO(port),
> + mask);
> +}
As sashiko pointed out, set_insolation(...,0) actually disables it
instead of completely isolating it.
I would unconditionally isolate the ports as we will never need to disable it.
Regards,
Luiz
^ permalink raw reply [flat|nested] 13+ messages in thread* Re: [PATCH net-next v2 2/5] net: dsa: realtek: rtl8366rb: Switch to generic port_bridge* handlers
2026-07-03 13:24 ` Luiz Angelo Daros de Luca
@ 2026-07-03 21:17 ` Linus Walleij
0 siblings, 0 replies; 13+ messages in thread
From: Linus Walleij @ 2026-07-03 21:17 UTC (permalink / raw)
To: Luiz Angelo Daros de Luca
Cc: Alvin Šipraga, Andrew Lunn, Vladimir Oltean, David S. Miller,
Eric Dumazet, Jakub Kicinski, Paolo Abeni, netdev
On Fri, Jul 3, 2026 at 3:24 PM Luiz Angelo Daros de Luca
<luizluca@gmail.com> wrote:
> > +static int rtl8366rb_port_set_isolation(struct realtek_priv *priv, int port,
> > + u32 mask)
> > +{
> > + /* Bit 0 enables isolation so set this if we enable isolation
> > + * any of the ports an clear it if we disable on all of them.
> > + */
> > + if (mask)
> > + mask = RTL8366RB_PORT_ISO_PORTS(mask) | RTL8366RB_PORT_ISO_EN;
> > +
> > + return regmap_write(priv->map, RTL8366RB_PORT_ISO(port),
> > + mask);
> > +}
>
> As sashiko pointed out, set_insolation(...,0) actually disables it
> instead of completely isolating it.
> I would unconditionally isolate the ports as we will never need to disable it.
Yeah, I'm working on a follow-up patch to fix this!
Thanks,
Linus Walleij
^ permalink raw reply [flat|nested] 13+ messages in thread
* [PATCH net-next v2 3/5] net: dsa: realtek: rtl8366rb: Use DSA port iterators
2026-06-30 11:19 [PATCH net-next v2 0/5] net: dsa: realtek: rtl8366rb: Use generic RTL83xx code Linus Walleij
2026-06-30 11:19 ` [PATCH net-next v2 1/5] net: dsa: realtek: rtl83xx: Make learning optional in join/leave Linus Walleij
2026-06-30 11:19 ` [PATCH net-next v2 2/5] net: dsa: realtek: rtl8366rb: Switch to generic port_bridge* handlers Linus Walleij
@ 2026-06-30 11:19 ` Linus Walleij
2026-07-02 9:31 ` Paolo Abeni
2026-06-30 11:19 ` [PATCH net-next v2 4/5] net: dsa: realtek: rtl8366rb: Disable STP learning on all ports in setup Linus Walleij
` (2 subsequent siblings)
5 siblings, 1 reply; 13+ messages in thread
From: Linus Walleij @ 2026-06-30 11:19 UTC (permalink / raw)
To: Luiz Angelo Daros de Luca, Alvin Šipraga, Andrew Lunn,
Vladimir Oltean, David S. Miller, Eric Dumazet, Jakub Kicinski,
Paolo Abeni
Cc: netdev, Linus Walleij
Instead of custom loops for intializing the ports (including the
CPU port) use the DSA helpers dsa_switch_for_each_port() and
dsa_switch_for_each_cpu_port() following the pattern in RTL8365MB by
accumulatong masks for the upstream and downstream ports.
This gives us similar enough code to the RTL8365MB that we
can start using more generic rtl83xx helpers.
Reviewed-by: Luiz Angelo Daros de Luca <luizluca@gmail.com>
Signed-off-by: Linus Walleij <linusw@kernel.org>
---
drivers/net/dsa/realtek/rtl8366rb.c | 49 +++++++++++++++++++++++++++++++------
1 file changed, 41 insertions(+), 8 deletions(-)
diff --git a/drivers/net/dsa/realtek/rtl8366rb.c b/drivers/net/dsa/realtek/rtl8366rb.c
index 8b57ef3bf03a..64215a0d5d6d 100644
--- a/drivers/net/dsa/realtek/rtl8366rb.c
+++ b/drivers/net/dsa/realtek/rtl8366rb.c
@@ -824,7 +824,10 @@ static int rtl8366rb_setup(struct dsa_switch *ds)
{
struct realtek_priv *priv = ds->priv;
const struct rtl8366rb_jam_tbl_entry *jam_table;
+ u32 downports_mask = 0;
struct rtl8366rb *rb;
+ u32 upports_mask = 0;
+ struct dsa_port *dp;
u32 chip_ver = 0;
u32 chip_id = 0;
int jam_size;
@@ -895,17 +898,47 @@ static int rtl8366rb_setup(struct dsa_switch *ds)
if (ret)
return ret;
- /* Isolate all user ports so they can only send packets to itself and the CPU port */
- for (i = 0; i < RTL8366RB_PORT_NUM_CPU; i++) {
- ret = rtl8366rb_port_set_isolation(priv, i, BIT(RTL8366RB_PORT_NUM_CPU));
+ /* Start with all ports blocked, including unused ports */
+ dsa_switch_for_each_port(dp, ds) {
+ /* Start with all ports completely isolated */
+ ret = rtl8366rb_port_set_isolation(priv, dp->index, 0);
+ if (ret)
+ return ret;
+
+ /* Collect CPU ports. If we support cascade switches, it should
+ * also include the upstream DSA ports.
+ */
+ if (!dsa_port_is_cpu(dp))
+ continue;
+
+ upports_mask |= BIT(dp->index);
+ }
+
+ /* Configure user ports */
+ dsa_switch_for_each_port(dp, ds) {
+ if (!dsa_port_is_user(dp))
+ continue;
+
+ /* Forward only to the CPU */
+ ret = rtl8366rb_port_set_isolation(priv, dp->index, upports_mask);
+ if (ret)
+ return ret;
+
+ /* If we support cascade switches, it should also include the
+ * downstream DSA ports.
+ */
+ downports_mask |= BIT(dp->index);
+ }
+
+ /* Configure CPU ports. If we support cascade switches, this will also
+ * include DSA ports.
+ */
+ dsa_switch_for_each_cpu_port(dp, ds) {
+ /* Forward to all user ports */
+ ret = rtl8366rb_port_set_isolation(priv, dp->index, downports_mask);
if (ret)
return ret;
}
- /* CPU port can send packets to all ports */
- ret = rtl8366rb_port_set_isolation(priv, RTL8366RB_PORT_NUM_CPU,
- dsa_user_ports(ds));
- if (ret)
- return ret;
/* Set up the "green ethernet" feature */
ret = rtl8366rb_jam_table(rtl8366rb_green_jam,
--
2.54.0
^ permalink raw reply related [flat|nested] 13+ messages in thread* Re: [PATCH net-next v2 3/5] net: dsa: realtek: rtl8366rb: Use DSA port iterators
2026-06-30 11:19 ` [PATCH net-next v2 3/5] net: dsa: realtek: rtl8366rb: Use DSA port iterators Linus Walleij
@ 2026-07-02 9:31 ` Paolo Abeni
0 siblings, 0 replies; 13+ messages in thread
From: Paolo Abeni @ 2026-07-02 9:31 UTC (permalink / raw)
To: Linus Walleij, Luiz Angelo Daros de Luca, Alvin Šipraga,
Andrew Lunn, Vladimir Oltean, David S. Miller, Eric Dumazet,
Jakub Kicinski
Cc: netdev
On 6/30/26 1:19 PM, Linus Walleij wrote:
> @@ -895,17 +898,47 @@ static int rtl8366rb_setup(struct dsa_switch *ds)
> if (ret)
> return ret;
>
> - /* Isolate all user ports so they can only send packets to itself and the CPU port */
> - for (i = 0; i < RTL8366RB_PORT_NUM_CPU; i++) {
> - ret = rtl8366rb_port_set_isolation(priv, i, BIT(RTL8366RB_PORT_NUM_CPU));
> + /* Start with all ports blocked, including unused ports */
> + dsa_switch_for_each_port(dp, ds) {
> + /* Start with all ports completely isolated */
> + ret = rtl8366rb_port_set_isolation(priv, dp->index, 0);
Sashiko (sigh!) noted that the above actually disables isolation entirely.
Since I guess/think/hope there will be at least a CPU port and an user
port per DSA, and later loops will finalize the setup correctly in such
a case, I think this is better handled as a follow-up.
/P
^ permalink raw reply [flat|nested] 13+ messages in thread
* [PATCH net-next v2 4/5] net: dsa: realtek: rtl8366rb: Disable STP learning on all ports in setup
2026-06-30 11:19 [PATCH net-next v2 0/5] net: dsa: realtek: rtl8366rb: Use generic RTL83xx code Linus Walleij
` (2 preceding siblings ...)
2026-06-30 11:19 ` [PATCH net-next v2 3/5] net: dsa: realtek: rtl8366rb: Use DSA port iterators Linus Walleij
@ 2026-06-30 11:19 ` Linus Walleij
2026-06-30 11:19 ` [PATCH net-next v2 5/5] net: dsa: realtek: rtl8366rb: Switch to generic learning enablement Linus Walleij
2026-07-02 9:40 ` [PATCH net-next v2 0/5] net: dsa: realtek: rtl8366rb: Use generic RTL83xx code patchwork-bot+netdevbpf
5 siblings, 0 replies; 13+ messages in thread
From: Linus Walleij @ 2026-06-30 11:19 UTC (permalink / raw)
To: Luiz Angelo Daros de Luca, Alvin Šipraga, Andrew Lunn,
Vladimir Oltean, David S. Miller, Eric Dumazet, Jakub Kicinski,
Paolo Abeni
Cc: netdev, Linus Walleij
When we loop over all ports in the switch .setup() callback,
make sure to disable learning on all user ports. This is what
is normally expected and what the RTL8365MB is doing.
Move the code around to accommodate for the new call.
Reviewed-by: Luiz Angelo Daros de Luca <luizluca@gmail.com>
Signed-off-by: Linus Walleij <linusw@kernel.org>
---
drivers/net/dsa/realtek/rtl8366rb.c | 74 ++++++++++++++++++++-----------------
1 file changed, 40 insertions(+), 34 deletions(-)
diff --git a/drivers/net/dsa/realtek/rtl8366rb.c b/drivers/net/dsa/realtek/rtl8366rb.c
index 64215a0d5d6d..155bf0010d5f 100644
--- a/drivers/net/dsa/realtek/rtl8366rb.c
+++ b/drivers/net/dsa/realtek/rtl8366rb.c
@@ -820,6 +820,40 @@ static int rtl8366rb_port_remove_isolation(struct realtek_priv *priv, int port,
RTL8366RB_PORT_ISO_PORTS(mask), 0);
}
+static void
+rtl8366rb_port_stp_state_set(struct dsa_switch *ds, int port, u8 state)
+{
+ struct realtek_priv *priv = ds->priv;
+ u32 val;
+ int i;
+
+ switch (state) {
+ case BR_STATE_DISABLED:
+ val = RTL8366RB_STP_STATE_DISABLED;
+ break;
+ case BR_STATE_BLOCKING:
+ case BR_STATE_LISTENING:
+ val = RTL8366RB_STP_STATE_BLOCKING;
+ break;
+ case BR_STATE_LEARNING:
+ val = RTL8366RB_STP_STATE_LEARNING;
+ break;
+ case BR_STATE_FORWARDING:
+ val = RTL8366RB_STP_STATE_FORWARDING;
+ break;
+ default:
+ dev_err(priv->dev, "unknown bridge state requested\n");
+ return;
+ }
+
+ /* Set the same status for the port on all the FIDs */
+ for (i = 0; i < RTL8366RB_NUM_FIDS; i++) {
+ regmap_update_bits(priv->map, RTL8366RB_STP_STATE_BASE + i,
+ RTL8366RB_STP_STATE_MASK(port),
+ RTL8366RB_STP_STATE(port, val));
+ }
+}
+
static int rtl8366rb_setup(struct dsa_switch *ds)
{
struct realtek_priv *priv = ds->priv;
@@ -900,6 +934,12 @@ static int rtl8366rb_setup(struct dsa_switch *ds)
/* Start with all ports blocked, including unused ports */
dsa_switch_for_each_port(dp, ds) {
+ /* Set the initial STP state of all ports to DISABLED, otherwise
+ * ports will still forward frames to the CPU despite being
+ * administratively down by default.
+ */
+ rtl8366rb_port_stp_state_set(ds, dp->index, BR_STATE_DISABLED);
+
/* Start with all ports completely isolated */
ret = rtl8366rb_port_set_isolation(priv, dp->index, 0);
if (ret)
@@ -1320,40 +1360,6 @@ rtl8366rb_port_bridge_flags(struct dsa_switch *ds, int port,
return 0;
}
-static void
-rtl8366rb_port_stp_state_set(struct dsa_switch *ds, int port, u8 state)
-{
- struct realtek_priv *priv = ds->priv;
- u32 val;
- int i;
-
- switch (state) {
- case BR_STATE_DISABLED:
- val = RTL8366RB_STP_STATE_DISABLED;
- break;
- case BR_STATE_BLOCKING:
- case BR_STATE_LISTENING:
- val = RTL8366RB_STP_STATE_BLOCKING;
- break;
- case BR_STATE_LEARNING:
- val = RTL8366RB_STP_STATE_LEARNING;
- break;
- case BR_STATE_FORWARDING:
- val = RTL8366RB_STP_STATE_FORWARDING;
- break;
- default:
- dev_err(priv->dev, "unknown bridge state requested\n");
- return;
- }
-
- /* Set the same status for the port on all the FIDs */
- for (i = 0; i < RTL8366RB_NUM_FIDS; i++) {
- regmap_update_bits(priv->map, RTL8366RB_STP_STATE_BASE + i,
- RTL8366RB_STP_STATE_MASK(port),
- RTL8366RB_STP_STATE(port, val));
- }
-}
-
static void
rtl8366rb_port_fast_age(struct dsa_switch *ds, int port)
{
--
2.54.0
^ permalink raw reply related [flat|nested] 13+ messages in thread* [PATCH net-next v2 5/5] net: dsa: realtek: rtl8366rb: Switch to generic learning enablement
2026-06-30 11:19 [PATCH net-next v2 0/5] net: dsa: realtek: rtl8366rb: Use generic RTL83xx code Linus Walleij
` (3 preceding siblings ...)
2026-06-30 11:19 ` [PATCH net-next v2 4/5] net: dsa: realtek: rtl8366rb: Disable STP learning on all ports in setup Linus Walleij
@ 2026-06-30 11:19 ` Linus Walleij
2026-07-03 13:31 ` Luiz Angelo Daros de Luca
2026-07-02 9:40 ` [PATCH net-next v2 0/5] net: dsa: realtek: rtl8366rb: Use generic RTL83xx code patchwork-bot+netdevbpf
5 siblings, 1 reply; 13+ messages in thread
From: Linus Walleij @ 2026-06-30 11:19 UTC (permalink / raw)
To: Luiz Angelo Daros de Luca, Alvin Šipraga, Andrew Lunn,
Vladimir Oltean, David S. Miller, Eric Dumazet, Jakub Kicinski,
Paolo Abeni
Cc: netdev, Linus Walleij
Instead of just writing the learning disablement register in setup
and a custom handling of BR_LEARNING, implement the generic RTL83xx
.port_set_learning() callback for setting learning on a port, and
call this in the per-port loop in .setup().
Instead of the custom rtl83366rb_port_bridge_flags() function for
setting learning mode on each port, use the RTL83xx generic
rtl83xx_port_bridge_flags() callback.
Signed-off-by: Linus Walleij <linusw@kernel.org>
---
drivers/net/dsa/realtek/rtl8366rb.c | 43 +++++++++++++++----------------------
1 file changed, 17 insertions(+), 26 deletions(-)
diff --git a/drivers/net/dsa/realtek/rtl8366rb.c b/drivers/net/dsa/realtek/rtl8366rb.c
index 155bf0010d5f..d2fa8ff6a5d0 100644
--- a/drivers/net/dsa/realtek/rtl8366rb.c
+++ b/drivers/net/dsa/realtek/rtl8366rb.c
@@ -854,6 +854,16 @@ rtl8366rb_port_stp_state_set(struct dsa_switch *ds, int port, u8 state)
}
}
+static int rtl8366rb_port_set_learning(struct realtek_priv *priv, int port,
+ bool enable)
+{
+ /* Notice inverted semantics in this register: setting a bit disables
+ * learning instead of enabling it.
+ */
+ return regmap_update_bits(priv->map, RTL8366RB_PORT_LEARNDIS_CTRL,
+ BIT(port), enable ? 0 : BIT(port));
+}
+
static int rtl8366rb_setup(struct dsa_switch *ds)
{
struct realtek_priv *priv = ds->priv;
@@ -945,6 +955,11 @@ static int rtl8366rb_setup(struct dsa_switch *ds)
if (ret)
return ret;
+ /* Disable learning */
+ ret = rtl8366rb_port_set_learning(priv, dp->index, false);
+ if (ret)
+ return ret;
+
/* Collect CPU ports. If we support cascade switches, it should
* also include the upstream DSA ports.
*/
@@ -1037,12 +1052,6 @@ static int rtl8366rb_setup(struct dsa_switch *ds)
rb->max_mtu[i] = ETH_DATA_LEN;
}
- /* Disable learning for all ports */
- ret = regmap_write(priv->map, RTL8366RB_PORT_LEARNDIS_CTRL,
- RTL8366RB_PORT_ALL);
- if (ret)
- return ret;
-
/* Enable auto ageing for all ports */
ret = regmap_write(priv->map, RTL8366RB_SECURITY_CTRL, 0);
if (ret)
@@ -1341,25 +1350,6 @@ rtl8366rb_port_pre_bridge_flags(struct dsa_switch *ds, int port,
return 0;
}
-static int
-rtl8366rb_port_bridge_flags(struct dsa_switch *ds, int port,
- struct switchdev_brport_flags flags,
- struct netlink_ext_ack *extack)
-{
- struct realtek_priv *priv = ds->priv;
- int ret;
-
- if (flags.mask & BR_LEARNING) {
- ret = regmap_update_bits(priv->map, RTL8366RB_PORT_LEARNDIS_CTRL,
- BIT(port),
- (flags.val & BR_LEARNING) ? 0 : BIT(port));
- if (ret)
- return ret;
- }
-
- return 0;
-}
-
static void
rtl8366rb_port_fast_age(struct dsa_switch *ds, int port)
{
@@ -1810,7 +1800,7 @@ static const struct dsa_switch_ops rtl8366rb_switch_ops = {
.port_enable = rtl8366rb_port_enable,
.port_disable = rtl8366rb_port_disable,
.port_pre_bridge_flags = rtl8366rb_port_pre_bridge_flags,
- .port_bridge_flags = rtl8366rb_port_bridge_flags,
+ .port_bridge_flags = rtl83xx_port_bridge_flags,
.port_stp_state_set = rtl8366rb_port_stp_state_set,
.port_fast_age = rtl8366rb_port_fast_age,
.port_change_mtu = rtl8366rb_change_mtu,
@@ -1833,6 +1823,7 @@ static const struct realtek_ops rtl8366rb_ops = {
.enable_vlan4k = rtl8366rb_enable_vlan4k,
.port_add_isolation = rtl8366rb_port_add_isolation,
.port_remove_isolation = rtl8366rb_port_remove_isolation,
+ .port_set_learning = rtl8366rb_port_set_learning,
.phy_read = rtl8366rb_phy_read,
.phy_write = rtl8366rb_phy_write,
};
--
2.54.0
^ permalink raw reply related [flat|nested] 13+ messages in thread* Re: [PATCH net-next v2 5/5] net: dsa: realtek: rtl8366rb: Switch to generic learning enablement
2026-06-30 11:19 ` [PATCH net-next v2 5/5] net: dsa: realtek: rtl8366rb: Switch to generic learning enablement Linus Walleij
@ 2026-07-03 13:31 ` Luiz Angelo Daros de Luca
0 siblings, 0 replies; 13+ messages in thread
From: Luiz Angelo Daros de Luca @ 2026-07-03 13:31 UTC (permalink / raw)
To: Linus Walleij
Cc: Alvin Šipraga, Andrew Lunn, Vladimir Oltean, David S. Miller,
Eric Dumazet, Jakub Kicinski, Paolo Abeni, netdev
> Instead of just writing the learning disablement register in setup
> and a custom handling of BR_LEARNING, implement the generic RTL83xx
> .port_set_learning() callback for setting learning on a port, and
> call this in the per-port loop in .setup().
>
> Instead of the custom rtl83366rb_port_bridge_flags() function for
> setting learning mode on each port, use the RTL83xx generic
> rtl83xx_port_bridge_flags() callback.
>
> Signed-off-by: Linus Walleij <linusw@kernel.org>
Reviewed-by: Luiz Angelo Daros de Luca <luizluca@gmail.com>
^ permalink raw reply [flat|nested] 13+ messages in thread
* Re: [PATCH net-next v2 0/5] net: dsa: realtek: rtl8366rb: Use generic RTL83xx code
2026-06-30 11:19 [PATCH net-next v2 0/5] net: dsa: realtek: rtl8366rb: Use generic RTL83xx code Linus Walleij
` (4 preceding siblings ...)
2026-06-30 11:19 ` [PATCH net-next v2 5/5] net: dsa: realtek: rtl8366rb: Switch to generic learning enablement Linus Walleij
@ 2026-07-02 9:40 ` patchwork-bot+netdevbpf
5 siblings, 0 replies; 13+ messages in thread
From: patchwork-bot+netdevbpf @ 2026-07-02 9:40 UTC (permalink / raw)
To: Linus Walleij
Cc: luizluca, alsi, andrew, olteanv, davem, edumazet, kuba, pabeni,
netdev
Hello:
This series was applied to netdev/net-next.git (main)
by Paolo Abeni <pabeni@redhat.com>:
On Tue, 30 Jun 2026 13:19:40 +0200 you wrote:
> As a follow-up to Luiz's and Alvin's series improvining the
> generic handling of the Realtek DSA switches, this small
> series brings the RTL8366RB closer to the way things are done
> in the RTL8365MB driver.
>
> This patch series switches over to using the generic helpers
> for:
>
> [...]
Here is the summary with links:
- [net-next,v2,1/5] net: dsa: realtek: rtl83xx: Make learning optional in join/leave
https://git.kernel.org/netdev/net-next/c/69bf497cfa79
- [net-next,v2,2/5] net: dsa: realtek: rtl8366rb: Switch to generic port_bridge* handlers
https://git.kernel.org/netdev/net-next/c/82ddf181448b
- [net-next,v2,3/5] net: dsa: realtek: rtl8366rb: Use DSA port iterators
https://git.kernel.org/netdev/net-next/c/cc61d5d7c205
- [net-next,v2,4/5] net: dsa: realtek: rtl8366rb: Disable STP learning on all ports in setup
https://git.kernel.org/netdev/net-next/c/e058ab0c4616
- [net-next,v2,5/5] net: dsa: realtek: rtl8366rb: Switch to generic learning enablement
https://git.kernel.org/netdev/net-next/c/b269a0596191
You are awesome, thank you!
--
Deet-doot-dot, I am a bot.
https://korg.docs.kernel.org/patchwork/pwbot.html
^ permalink raw reply [flat|nested] 13+ messages in thread