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>
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: /* 3 */
- port_state[index] |= (3 << bit);
- default:
+ case BR_STATE_FORWARDING:
+ hw_state = 3;
break;
+ default:
+ 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)
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);
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);
}
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);
}
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);
}
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);
}