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,
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,
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;
}
}
- 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);
}
.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,
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);
.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,
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);
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);
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);
.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,
.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,
.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,