]> git.ipfire.org Git - thirdparty/openwrt.git/commitdiff
realtek: dsa: Keep HW specific mirror code in SoC helper
authorSven Eckelmann <se@simonwunderlich.de>
Tue, 15 Jul 2025 17:48:05 +0000 (19:48 +0200)
committerRobert Marko <robimarko@gmail.com>
Fri, 3 Oct 2025 17:25:26 +0000 (19:25 +0200)
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 <markus.stockhausen@gmx.de>
Signed-off-by: Sven Eckelmann <se@simonwunderlich.de>
Link: https://github.com/openwrt/openwrt/pull/20264
Signed-off-by: Robert Marko <robimarko@gmail.com>
target/linux/realtek/files-6.12/drivers/net/dsa/rtl83xx/debugfs.c
target/linux/realtek/files-6.12/drivers/net/dsa/rtl83xx/dsa.c
target/linux/realtek/files-6.12/drivers/net/dsa/rtl83xx/rtl838x.c
target/linux/realtek/files-6.12/drivers/net/dsa/rtl83xx/rtl838x.h
target/linux/realtek/files-6.12/drivers/net/dsa/rtl83xx/rtl839x.c
target/linux/realtek/files-6.12/drivers/net/dsa/rtl83xx/rtl930x.c
target/linux/realtek/files-6.12/drivers/net/dsa/rtl83xx/rtl931x.c

index 7e6918df202487b7ba774ade03480ef89c5c22d9..00f2642624ab932bb170612520d011cec90da131 100644 (file)
@@ -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,
index eee3479aea961dca7ce9686d9e6c70eea24c329a..288e5361e45c973a398ab2c34752785ef763bb0a 100644 (file)
@@ -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,
index 92bb3e951220be16d4e6e16bbfbef585be8627e6..a76558c6d5921aa9eddb5eb494e33a3cca7e3286 100644 (file)
@@ -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,
index 469246f0f8fbcf17526bece1636de5c075625724..01f83d727156a45bb64a5545a35b8099fd2f9d51 100644 (file)
@@ -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);
index 9a325b396be8fcd98187a55f09333bc9272a594d..2745f4f339b27a7fbd422490da437313cada1858 100644 (file)
@@ -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,
index 0ac77092480d366ed046d414afc08b26b493dd85..5ca29e56b11c1710d092cf20ec7653f586fba002 100644 (file)
@@ -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,
index 28602151c0c5bf34460d450429eaf512a6485754..54f2dc9720ec1c24f627e5ed2f9f44e77abc2cfe 100644 (file)
@@ -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,