From 8e2284857d386200cde05a34d934815896c44a8e Mon Sep 17 00:00:00 2001 From: Sven Eckelmann Date: Tue, 15 Jul 2025 19:48:05 +0200 Subject: [PATCH] realtek: dsa: Keep HW specific mirror code in SoC helper Instead of using a lot of if-else blocks in the port mirror code, provide SoC specific function which calculates the SoC specific portions. The generic part of the port mirroring code can then simply operate on the calculated register addresses and values. Suggested-by: Markus Stockhausen Signed-off-by: Sven Eckelmann Link: https://github.com/openwrt/openwrt/pull/20264 Signed-off-by: Robert Marko --- .../drivers/net/dsa/rtl83xx/debugfs.c | 8 +- .../files-6.12/drivers/net/dsa/rtl83xx/dsa.c | 101 ++++++++++-------- .../drivers/net/dsa/rtl83xx/rtl838x.c | 21 +++- .../drivers/net/dsa/rtl83xx/rtl838x.h | 21 +++- .../drivers/net/dsa/rtl83xx/rtl839x.c | 18 +++- .../drivers/net/dsa/rtl83xx/rtl930x.c | 3 - .../drivers/net/dsa/rtl83xx/rtl931x.c | 3 - 7 files changed, 111 insertions(+), 64 deletions(-) diff --git a/target/linux/realtek/files-6.12/drivers/net/dsa/rtl83xx/debugfs.c b/target/linux/realtek/files-6.12/drivers/net/dsa/rtl83xx/debugfs.c index 7e6918df202..00f2642624a 100644 --- a/target/linux/realtek/files-6.12/drivers/net/dsa/rtl83xx/debugfs.c +++ b/target/linux/realtek/files-6.12/drivers/net/dsa/rtl83xx/debugfs.c @@ -631,9 +631,9 @@ void rtl838x_dbgfs_init(struct rtl838x_switch_priv *priv) debugfs_create_x32("ctrl", 0644, mirror_dir, (u32 *)(RTL838X_SW_BASE + RTL838X_MIR_CTRL + i * 4)); debugfs_create_x32("ingress_pm", 0644, mirror_dir, - (u32 *)(RTL838X_SW_BASE + priv->r->mir_spm + i * 4)); + (u32 *)(RTL838X_SW_BASE + RTL838X_MIR_SPM_CTRL + i * 4)); debugfs_create_x32("egress_pm", 0644, mirror_dir, - (u32 *)(RTL838X_SW_BASE + priv->r->mir_dpm + i * 4)); + (u32 *)(RTL838X_SW_BASE + RTL838X_MIR_DPM_CTRL + i * 4)); debugfs_create_x32("qid", 0644, mirror_dir, (u32 *)(RTL838X_SW_BASE + RTL838X_MIR_QID_CTRL(i))); debugfs_create_x32("rspan_vlan", 0644, mirror_dir, @@ -650,9 +650,9 @@ void rtl838x_dbgfs_init(struct rtl838x_switch_priv *priv) debugfs_create_x32("ctrl", 0644, mirror_dir, (u32 *)(RTL838X_SW_BASE + RTL839X_MIR_CTRL + i * 4)); debugfs_create_x64("ingress_pm", 0644, mirror_dir, - (u64 *)(RTL838X_SW_BASE + priv->r->mir_spm + i * 8)); + (u64 *)(RTL838X_SW_BASE + RTL839X_MIR_SPM_CTRL + i * 8)); debugfs_create_x64("egress_pm", 0644, mirror_dir, - (u64 *)(RTL838X_SW_BASE + priv->r->mir_dpm + i * 8)); + (u64 *)(RTL838X_SW_BASE + RTL839X_MIR_DPM_CTRL + i * 8)); debugfs_create_x32("rspan_vlan", 0644, mirror_dir, (u32 *)(RTL838X_SW_BASE + RTL839X_MIR_RSPAN_VLAN_CTRL(i))); debugfs_create_x32("rspan_tx", 0644, mirror_dir, diff --git a/target/linux/realtek/files-6.12/drivers/net/dsa/rtl83xx/dsa.c b/target/linux/realtek/files-6.12/drivers/net/dsa/rtl83xx/dsa.c index eee3479aea9..288e5361e45 100644 --- a/target/linux/realtek/files-6.12/drivers/net/dsa/rtl83xx/dsa.c +++ b/target/linux/realtek/files-6.12/drivers/net/dsa/rtl83xx/dsa.c @@ -2269,17 +2269,25 @@ out: return err; } -static int rtl83xx_port_mirror_add(struct dsa_switch *ds, int port, - struct dsa_mall_mirror_tc_entry *mirror, - bool ingress, struct netlink_ext_ack *extack) +static int rtldsa_port_mirror_add(struct dsa_switch *ds, int port, + struct dsa_mall_mirror_tc_entry *mirror, + bool ingress, struct netlink_ext_ack *extack) { /* We support 4 mirror groups, one destination port per group */ - int group; struct rtl838x_switch_priv *priv = ds->priv; - int ctrl_reg, dpm_reg, spm_reg; + struct rtldsa_mirror_config config; + int err = 0; + int pm_reg; + int group; + int r; + + if (!priv->r->get_mirror_config) + return -EOPNOTSUPP; pr_debug("In %s\n", __func__); + mutex_lock(&priv->reg_mutex); + for (group = 0; group < 4; group++) { if (priv->mirror_group_ports[group] == mirror->to_local_port) break; @@ -2291,77 +2299,80 @@ static int rtl83xx_port_mirror_add(struct dsa_switch *ds, int port, } } - if (group >= 4) - return -ENOSPC; - - ctrl_reg = priv->r->mir_ctrl + group * 4; - dpm_reg = priv->r->mir_dpm + group * 4 * priv->port_width; - spm_reg = priv->r->mir_spm + group * 4 * priv->port_width; + if (group >= 4) { + err = -ENOSPC; + goto out_unlock; + } pr_debug("Using group %d\n", group); - mutex_lock(&priv->reg_mutex); - - if (priv->family_id == RTL8380_FAMILY_ID) { - /* Enable mirroring to port across VLANs (bit 11) */ - sw_w32(1 << 11 | (mirror->to_local_port << 4) | 1, ctrl_reg); - } else { - /* Enable mirroring to destination port */ - sw_w32((mirror->to_local_port << 4) | 1, ctrl_reg); - } - if (ingress && (priv->r->get_port_reg_be(spm_reg) & (1ULL << port))) { - mutex_unlock(&priv->reg_mutex); - return -EEXIST; - } - if ((!ingress) && (priv->r->get_port_reg_be(dpm_reg) & (1ULL << port))) { - mutex_unlock(&priv->reg_mutex); - return -EEXIST; + r = priv->r->get_mirror_config(&config, group, mirror->to_local_port); + if (r < 0) { + err = r; + goto out_unlock; } if (ingress) - priv->r->mask_port_reg_be(0, 1ULL << port, spm_reg); + pm_reg = config.spm; else - priv->r->mask_port_reg_be(0, 1ULL << port, dpm_reg); + pm_reg = config.dpm; + sw_w32(config.val, config.ctrl); + + if (priv->r->get_port_reg_be(pm_reg) & (1ULL << port)) { + err = -EEXIST; + goto out_unlock; + } + + priv->r->mask_port_reg_be(0, 1ULL << port, pm_reg); priv->mirror_group_ports[group] = mirror->to_local_port; + +out_unlock: mutex_unlock(&priv->reg_mutex); - return 0; + return err; } -static void rtl83xx_port_mirror_del(struct dsa_switch *ds, int port, - struct dsa_mall_mirror_tc_entry *mirror) +static void rtldsa_port_mirror_del(struct dsa_switch *ds, int port, + struct dsa_mall_mirror_tc_entry *mirror) { - int group = 0; struct rtl838x_switch_priv *priv = ds->priv; - int ctrl_reg, dpm_reg, spm_reg; + struct rtldsa_mirror_config config; + int group = 0; + int r; + + if (!priv->r->get_mirror_config) + return; pr_debug("In %s\n", __func__); + + mutex_lock(&priv->reg_mutex); + for (group = 0; group < 4; group++) { if (priv->mirror_group_ports[group] == mirror->to_local_port) break; } if (group >= 4) - return; + goto out_unlock; - ctrl_reg = priv->r->mir_ctrl + group * 4; - dpm_reg = priv->r->mir_dpm + group * 4 * priv->port_width; - spm_reg = priv->r->mir_spm + group * 4 * priv->port_width; + r = priv->r->get_mirror_config(&config, group, mirror->to_local_port); + if (r < 0) + goto out_unlock; - mutex_lock(&priv->reg_mutex); if (mirror->ingress) { /* Ingress, clear source port matrix */ - priv->r->mask_port_reg_be(1ULL << port, 0, spm_reg); + priv->r->mask_port_reg_be(1ULL << port, 0, config.spm); } else { /* Egress, clear destination port matrix */ - priv->r->mask_port_reg_be(1ULL << port, 0, dpm_reg); + priv->r->mask_port_reg_be(1ULL << port, 0, config.dpm); } - if (!(sw_r32(spm_reg) || sw_r32(dpm_reg))) { + if (!(sw_r32(config.spm) || sw_r32(config.dpm))) { priv->mirror_group_ports[group] = -1; - sw_w32(0, ctrl_reg); + sw_w32(0, config.ctrl); } +out_unlock: mutex_unlock(&priv->reg_mutex); } @@ -2579,8 +2590,8 @@ const struct dsa_switch_ops rtl83xx_switch_ops = { .port_mdb_add = rtl83xx_port_mdb_add, .port_mdb_del = rtl83xx_port_mdb_del, - .port_mirror_add = rtl83xx_port_mirror_add, - .port_mirror_del = rtl83xx_port_mirror_del, + .port_mirror_add = rtldsa_port_mirror_add, + .port_mirror_del = rtldsa_port_mirror_del, .port_lag_change = rtl83xx_port_lag_change, .port_lag_join = rtl83xx_port_lag_join, diff --git a/target/linux/realtek/files-6.12/drivers/net/dsa/rtl83xx/rtl838x.c b/target/linux/realtek/files-6.12/drivers/net/dsa/rtl83xx/rtl838x.c index 92bb3e95122..a76558c6d59 100644 --- a/target/linux/realtek/files-6.12/drivers/net/dsa/rtl83xx/rtl838x.c +++ b/target/linux/realtek/files-6.12/drivers/net/dsa/rtl83xx/rtl838x.c @@ -261,6 +261,23 @@ static inline int rtl838x_l2_port_new_sa_fwd(int p) return RTL838X_L2_PORT_NEW_SA_FWD(p); } +static int rtldsa_838x_get_mirror_config(struct rtldsa_mirror_config *config, + int group, int port) +{ + config->ctrl = RTL838X_MIR_CTRL + group * 4; + config->spm = RTL838X_MIR_SPM_CTRL + group * 4; + config->dpm = RTL838X_MIR_DPM_CTRL + group * 4; + + /* Enable mirroring to destination port */ + config->val = BIT(0); + config->val |= port << 4; + + /* Enable mirroring to port across VLANs */ + config->val |= BIT(11); + + return 0; +} + inline static int rtl838x_trk_mbr_ctr(int group) { return RTL838X_TRK_MBR_CTR + (group << 2); @@ -1698,9 +1715,7 @@ const struct rtl838x_reg rtl838x_reg = { .mac_port_ctrl = rtl838x_mac_port_ctrl, .l2_port_new_salrn = rtl838x_l2_port_new_salrn, .l2_port_new_sa_fwd = rtl838x_l2_port_new_sa_fwd, - .mir_ctrl = RTL838X_MIR_CTRL, - .mir_dpm = RTL838X_MIR_DPM_CTRL, - .mir_spm = RTL838X_MIR_SPM_CTRL, + .get_mirror_config = rtldsa_838x_get_mirror_config, .read_l2_entry_using_hash = rtl838x_read_l2_entry_using_hash, .write_l2_entry_using_hash = rtl838x_write_l2_entry_using_hash, .read_cam = rtl838x_read_cam, diff --git a/target/linux/realtek/files-6.12/drivers/net/dsa/rtl83xx/rtl838x.h b/target/linux/realtek/files-6.12/drivers/net/dsa/rtl83xx/rtl838x.h index 469246f0f8f..01f83d72715 100644 --- a/target/linux/realtek/files-6.12/drivers/net/dsa/rtl83xx/rtl838x.h +++ b/target/linux/realtek/files-6.12/drivers/net/dsa/rtl83xx/rtl838x.h @@ -997,6 +997,23 @@ struct rtl83xx_route { struct rtl93xx_route_attr attr; }; +/** + * struct rtldsa_mirror_config - Mirror configuration for specific group and port + */ +struct rtldsa_mirror_config { + /** @ctrl: control register for mirroring group */ + int ctrl; + + /** @spm: register for the destination port members */ + int spm; + + /** @dpm: register for the source port members */ + int dpm; + + /** @val: @ctrl register settings to enable mirroring */ + u32 val; +}; + struct rtl838x_reg { void (*mask_port_reg_be)(u64 clear, u64 set, int reg); void (*set_port_reg_be)(u64 set, int reg); @@ -1047,9 +1064,7 @@ struct rtl838x_reg { int (*l2_port_new_salrn)(int port); int (*l2_port_new_sa_fwd)(int port); int (*set_ageing_time)(unsigned long msec); - int mir_ctrl; - int mir_dpm; - int mir_spm; + int (*get_mirror_config)(struct rtldsa_mirror_config *config, int group, int port); u64 (*read_l2_entry_using_hash)(u32 hash, u32 position, struct rtl838x_l2_entry *e); void (*write_l2_entry_using_hash)(u32 hash, u32 pos, struct rtl838x_l2_entry *e); u64 (*read_cam)(int idx, struct rtl838x_l2_entry *e); diff --git a/target/linux/realtek/files-6.12/drivers/net/dsa/rtl83xx/rtl839x.c b/target/linux/realtek/files-6.12/drivers/net/dsa/rtl83xx/rtl839x.c index 9a325b396be..2745f4f339b 100644 --- a/target/linux/realtek/files-6.12/drivers/net/dsa/rtl83xx/rtl839x.c +++ b/target/linux/realtek/files-6.12/drivers/net/dsa/rtl83xx/rtl839x.c @@ -293,6 +293,20 @@ static inline int rtl839x_l2_port_new_sa_fwd(int p) return RTL839X_L2_PORT_NEW_SA_FWD(p); } +static int rtldsa_839x_get_mirror_config(struct rtldsa_mirror_config *config, + int group, int port) +{ + config->ctrl = RTL839X_MIR_CTRL + group * 4; + config->spm = RTL839X_MIR_SPM_CTRL + group * 8; + config->dpm = RTL839X_MIR_DPM_CTRL + group * 8; + + /* Enable mirroring to destination port */ + config->val = BIT(0); + config->val |= port << 4; + + return 0; +} + static inline int rtl839x_trk_mbr_ctr(int group) { return RTL839X_TRK_MBR_CTR + (group << 3); @@ -1678,9 +1692,7 @@ const struct rtl838x_reg rtl839x_reg = { .mac_port_ctrl = rtl839x_mac_port_ctrl, .l2_port_new_salrn = rtl839x_l2_port_new_salrn, .l2_port_new_sa_fwd = rtl839x_l2_port_new_sa_fwd, - .mir_ctrl = RTL839X_MIR_CTRL, - .mir_dpm = RTL839X_MIR_DPM_CTRL, - .mir_spm = RTL839X_MIR_SPM_CTRL, + .get_mirror_config = rtldsa_839x_get_mirror_config, .read_l2_entry_using_hash = rtl839x_read_l2_entry_using_hash, .write_l2_entry_using_hash = rtl839x_write_l2_entry_using_hash, .read_cam = rtl839x_read_cam, diff --git a/target/linux/realtek/files-6.12/drivers/net/dsa/rtl83xx/rtl930x.c b/target/linux/realtek/files-6.12/drivers/net/dsa/rtl83xx/rtl930x.c index 0ac77092480..5ca29e56b11 100644 --- a/target/linux/realtek/files-6.12/drivers/net/dsa/rtl83xx/rtl930x.c +++ b/target/linux/realtek/files-6.12/drivers/net/dsa/rtl83xx/rtl930x.c @@ -2446,9 +2446,6 @@ const struct rtl838x_reg rtl930x_reg = { .mac_port_ctrl = rtl930x_mac_port_ctrl, .l2_port_new_salrn = rtl930x_l2_port_new_salrn, .l2_port_new_sa_fwd = rtl930x_l2_port_new_sa_fwd, - .mir_ctrl = RTL930X_MIR_CTRL, - .mir_dpm = RTL930X_MIR_DPM_CTRL, - .mir_spm = RTL930X_MIR_SPM_CTRL, .read_l2_entry_using_hash = rtl930x_read_l2_entry_using_hash, .write_l2_entry_using_hash = rtl930x_write_l2_entry_using_hash, .read_cam = rtl930x_read_cam, diff --git a/target/linux/realtek/files-6.12/drivers/net/dsa/rtl83xx/rtl931x.c b/target/linux/realtek/files-6.12/drivers/net/dsa/rtl83xx/rtl931x.c index 28602151c0c..54f2dc9720e 100644 --- a/target/linux/realtek/files-6.12/drivers/net/dsa/rtl83xx/rtl931x.c +++ b/target/linux/realtek/files-6.12/drivers/net/dsa/rtl83xx/rtl931x.c @@ -1561,9 +1561,6 @@ const struct rtl838x_reg rtl931x_reg = { .mac_port_ctrl = rtl931x_mac_port_ctrl, .l2_port_new_salrn = rtl931x_l2_port_new_salrn, .l2_port_new_sa_fwd = rtl931x_l2_port_new_sa_fwd, - .mir_ctrl = RTL931X_MIR_CTRL, - .mir_dpm = RTL931X_MIR_DPM_CTRL, - .mir_spm = RTL931X_MIR_SPM_CTRL, .read_l2_entry_using_hash = rtl931x_read_l2_entry_using_hash, .write_l2_entry_using_hash = rtl931x_write_l2_entry_using_hash, .read_cam = rtl931x_read_cam, -- 2.47.3