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 <markus.stockhausen@gmx.de>
Link: https://github.com/openwrt/openwrt/pull/23080
Signed-off-by: Hauke Mehrtens <hauke@hauke-m.de>
This commit is contained in:
Markus Stockhausen 2026-04-24 12:52:55 +02:00 committed by Hauke Mehrtens
parent 9a6c754d7d
commit 4b8af19582
6 changed files with 35 additions and 48 deletions

View File

@ -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)

View File

@ -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);

View File

@ -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);
}

View File

@ -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);
}

View File

@ -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);
}

View File

@ -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);
}