From 4b8af1958290cd2ffc1e693c0310dfebd737b6b6 Mon Sep 17 00:00:00 2001 From: Markus Stockhausen Date: Fri, 24 Apr 2026 12:52:55 +0200 Subject: [PATCH] realtek: dsa: remove family_id check from xstp_state_set() The rtldsa_port_xstp_state_set() function offers a generic interface to its callers to set the bridge state of one port. While it calls device specific helpers in the background it runs the data mapping for each architecture with a family_id check on its own. So the hardware abstraction is done in two places - rtldsa_port_xstp_state_set() translates one half - its helper translate the other half Convert the signature of the device specific helpers so that this function does not need to know any hardware details. Instead move the table/offset/bit calculations into the helpers. This way the code path uses a consistent hardware abstraction. - rtldsa_port_xstp_state_set() calls the helpers - helpers do the hardware translation Signed-off-by: Markus Stockhausen Link: https://github.com/openwrt/openwrt/pull/23080 Signed-off-by: Hauke Mehrtens --- .../files-6.18/drivers/net/dsa/rtl83xx/dsa.c | 49 ++++++------------- .../drivers/net/dsa/rtl83xx/rtl-otto.h | 2 +- .../drivers/net/dsa/rtl83xx/rtl838x.c | 8 +-- .../drivers/net/dsa/rtl83xx/rtl839x.c | 8 +-- .../drivers/net/dsa/rtl83xx/rtl930x.c | 8 +-- .../drivers/net/dsa/rtl83xx/rtl931x.c | 8 +-- 6 files changed, 35 insertions(+), 48 deletions(-) diff --git a/target/linux/realtek/files-6.18/drivers/net/dsa/rtl83xx/dsa.c b/target/linux/realtek/files-6.18/drivers/net/dsa/rtl83xx/dsa.c index c41172a4ed..7b28c6f4e8 100644 --- a/target/linux/realtek/files-6.18/drivers/net/dsa/rtl83xx/dsa.c +++ b/target/linux/realtek/files-6.18/drivers/net/dsa/rtl83xx/dsa.c @@ -1452,52 +1452,31 @@ static void rtldsa_port_xstp_state_set(struct rtl838x_switch_priv *priv, int por u8 state, u16 mst_slot) __must_hold(&priv->reg_mutex) { - /* 838x/930x have 28 ports and 2 bit fields other devices 4 bit fields. */ - int n = priv->r->cpu_port == RTL838X_CPU_PORT ? 2 : 4; - u32 port_state[4]; - int index, bit; - int pos = port; + int hw_state; - /* Ports above or equal CPU port can never be configured */ if (port >= priv->r->cpu_port) return; - /* For the RTL839x and following, the bits are left-aligned, 838x and 930x - * have 64 bit fields, 839x and 931x have 128 bit fields - */ - if (priv->family_id == RTL8390_FAMILY_ID) - pos += 12; - if (priv->family_id == RTL9300_FAMILY_ID) - pos += 3; - if (priv->family_id == RTL9310_FAMILY_ID) - pos += 8; - - index = n - (pos >> 4) - 1; - bit = (pos << 1) % 32; - - priv->r->stp_get(priv, mst_slot, port, port_state); - - pr_debug("Current state, port %d: %d\n", port, (port_state[index] >> bit) & 3); - port_state[index] &= ~(3 << bit); - switch (state) { - case BR_STATE_DISABLED: /* 0 */ - port_state[index] |= (0 << bit); + case BR_STATE_DISABLED: + hw_state = 0; break; - case BR_STATE_BLOCKING: /* 4 */ - case BR_STATE_LISTENING: /* 1 */ - port_state[index] |= (1 << bit); + case BR_STATE_BLOCKING: + case BR_STATE_LISTENING: + hw_state = 1; break; - case BR_STATE_LEARNING: /* 2 */ - port_state[index] |= (2 << bit); + case BR_STATE_LEARNING: + hw_state = 2; + break; + case BR_STATE_FORWARDING: + hw_state = 3; break; - case BR_STATE_FORWARDING: /* 3 */ - port_state[index] |= (3 << bit); default: - break; + dev_err(priv->dev, "stp state %d not supported\n", state); + return; } - priv->r->stp_set(priv, mst_slot, port_state); + priv->r->stp_set(priv, mst_slot, port, hw_state); } void rtldsa_port_stp_state_set(struct dsa_switch *ds, int port, u8 state) diff --git a/target/linux/realtek/files-6.18/drivers/net/dsa/rtl83xx/rtl-otto.h b/target/linux/realtek/files-6.18/drivers/net/dsa/rtl83xx/rtl-otto.h index 460f542a6e..744dc0ec14 100644 --- a/target/linux/realtek/files-6.18/drivers/net/dsa/rtl83xx/rtl-otto.h +++ b/target/linux/realtek/files-6.18/drivers/net/dsa/rtl83xx/rtl-otto.h @@ -1440,7 +1440,7 @@ struct rtldsa_config { void (*enable_bcast_flood)(int port, bool enable); void (*set_static_move_action)(int port, bool forward); int (*stp_get)(struct rtl838x_switch_priv *priv, u16 msti, int port, u32 port_state[]); - void (*stp_set)(struct rtl838x_switch_priv *priv, u16 msti, u32 port_state[]); + void (*stp_set)(struct rtl838x_switch_priv *priv, u16 msti, int port, int state); int mac_link_sts; int (*mac_force_mode_ctrl)(int port); int (*mac_port_ctrl)(int port); diff --git a/target/linux/realtek/files-6.18/drivers/net/dsa/rtl83xx/rtl838x.c b/target/linux/realtek/files-6.18/drivers/net/dsa/rtl83xx/rtl838x.c index f043b0c577..03b9b7cdcd 100644 --- a/target/linux/realtek/files-6.18/drivers/net/dsa/rtl83xx/rtl838x.c +++ b/target/linux/realtek/files-6.18/drivers/net/dsa/rtl83xx/rtl838x.c @@ -655,12 +655,14 @@ static int rtldsa_838x_stp_get(struct rtl838x_switch_priv *priv, u16 msti, int p return (port_state[idx] >> bit) & 3; } -static void rtl838x_stp_set(struct rtl838x_switch_priv *priv, u16 msti, u32 port_state[]) +static void rtl838x_stp_set(struct rtl838x_switch_priv *priv, u16 msti, int port, int state) { struct table_reg *r = rtl_table_get(RTL8380_TBL_0, 2); + int idx = 1 - (port / 16); + int bit = 2 * (port % 16); - for (int i = 0; i < 2; i++) - sw_w32(port_state[i], rtl_table_data(r, i)); + rtl_table_read(r, msti); + sw_w32_mask(0x3 << bit, state << bit, rtl_table_data(r, idx)); rtl_table_write(r, msti); rtl_table_release(r); } diff --git a/target/linux/realtek/files-6.18/drivers/net/dsa/rtl83xx/rtl839x.c b/target/linux/realtek/files-6.18/drivers/net/dsa/rtl83xx/rtl839x.c index 6af0422abf..f44f8567a7 100644 --- a/target/linux/realtek/files-6.18/drivers/net/dsa/rtl83xx/rtl839x.c +++ b/target/linux/realtek/files-6.18/drivers/net/dsa/rtl83xx/rtl839x.c @@ -722,12 +722,14 @@ static int rtldsa_839x_stp_get(struct rtl838x_switch_priv *priv, u16 msti, int p return (port_state[idx] >> bit) & 3; } -static void rtl839x_stp_set(struct rtl838x_switch_priv *priv, u16 msti, u32 port_state[]) +static void rtl839x_stp_set(struct rtl838x_switch_priv *priv, u16 msti, int port, int state) { struct table_reg *r = rtl_table_get(RTL8390_TBL_0, 5); + int idx = 3 - ((port + 12) / 16); + int bit = 2 * ((port + 12) % 16); - for (int i = 0; i < 4; i++) - sw_w32(port_state[i], rtl_table_data(r, i)); + rtl_table_read(r, msti); + sw_w32_mask(0x3 << bit, state << bit, rtl_table_data(r, idx)); rtl_table_write(r, msti); rtl_table_release(r); } diff --git a/target/linux/realtek/files-6.18/drivers/net/dsa/rtl83xx/rtl930x.c b/target/linux/realtek/files-6.18/drivers/net/dsa/rtl83xx/rtl930x.c index 505fd7200d..90dcee3179 100644 --- a/target/linux/realtek/files-6.18/drivers/net/dsa/rtl83xx/rtl930x.c +++ b/target/linux/realtek/files-6.18/drivers/net/dsa/rtl83xx/rtl930x.c @@ -641,12 +641,14 @@ static int rtldsa_930x_stp_get(struct rtl838x_switch_priv *priv, u16 msti, int p return (port_state[idx] >> bit) & 3; } -static void rtl930x_stp_set(struct rtl838x_switch_priv *priv, u16 msti, u32 port_state[]) +static void rtl930x_stp_set(struct rtl838x_switch_priv *priv, u16 msti, int port, int state) { struct table_reg *r = rtl_table_get(RTL9300_TBL_0, 4); + int idx = 1 - ((port + 3) / 16); + int bit = 2 * ((port + 3) % 16); - for (int i = 0; i < 2; i++) - sw_w32(port_state[i], rtl_table_data(r, i)); + rtl_table_read(r, msti); + sw_w32_mask(0x3 << bit, state << bit, rtl_table_data(r, idx)); rtl_table_write(r, msti); rtl_table_release(r); } diff --git a/target/linux/realtek/files-6.18/drivers/net/dsa/rtl83xx/rtl931x.c b/target/linux/realtek/files-6.18/drivers/net/dsa/rtl83xx/rtl931x.c index b116f1e29c..b205f2b7a9 100644 --- a/target/linux/realtek/files-6.18/drivers/net/dsa/rtl83xx/rtl931x.c +++ b/target/linux/realtek/files-6.18/drivers/net/dsa/rtl83xx/rtl931x.c @@ -264,12 +264,14 @@ static int rtldsa_931x_stp_get(struct rtl838x_switch_priv *priv, u16 msti, int p return (port_state[idx] >> bit) & 3; } -static void rtl931x_stp_set(struct rtl838x_switch_priv *priv, u16 msti, u32 port_state[]) +static void rtl931x_stp_set(struct rtl838x_switch_priv *priv, u16 msti, int port, int state) { struct table_reg *r = rtl_table_get(RTL9310_TBL_0, 5); + int idx = 3 - ((port + 8) / 16); + int bit = 2 * ((port + 8) % 16); - for (int i = 0; i < 4; i++) - sw_w32(port_state[i], rtl_table_data(r, i)); + rtl_table_read(r, msti); + sw_w32_mask(0x3 << bit, state << bit, rtl_table_data(r, idx)); rtl_table_write(r, msti); rtl_table_release(r); }