diff mbox series

[RFC,net-next,6/6] net: dsa: mv88e6xxx add cross-chip mirroring

Message ID cacf47599957ac92edddfa372bac5ac9890e4e85.1704449760.git.ante.knezic@helmholz.de (mailing list archive)
State RFC
Delegated to: Netdev Maintainers
Headers show
Series add dsa cross-chip port mirroring | expand

Checks

Context Check Description
netdev/series_format success Posting correctly formatted
netdev/tree_selection success Clearly marked for net-next
netdev/ynl success Generated files up to date; no warnings/errors; no diff in generated;
netdev/fixes_present success Fixes tag not required for -next series
netdev/header_inline success No static functions without inline keyword in header files
netdev/build_32bit success Errors and warnings before: 1113 this patch: 1113
netdev/cc_maintainers success CCed 0 of 0 maintainers
netdev/build_clang success Errors and warnings before: 1140 this patch: 1140
netdev/verify_signedoff success Signed-off-by tag matches author and committer
netdev/deprecated_api success None detected
netdev/check_selftest success No net selftest shell script
netdev/verify_fixes success No Fixes tag
netdev/build_allmodconfig_warn success Errors and warnings before: 1140 this patch: 1140
netdev/checkpatch warning WARNING: line length of 81 exceeds 80 columns WARNING: line length of 82 exceeds 80 columns WARNING: line length of 90 exceeds 80 columns
netdev/build_clang_rust success No Rust files in patch. Skipping build
netdev/kdoc success Errors and warnings before: 0 this patch: 0
netdev/source_inline success Was 0 now: 0

Commit Message

Ante Knezic Jan. 5, 2024, 10:46 a.m. UTC
modify mv88e6xxx port mirroring to support cross-chip mirroring.
Remove mirror_ingress and mirror_egress as they are no longer
needed.
Do not allow setting dsa ports as mirror source port as
recommended by the Switch Functional Specification.

Signed-off-by: Ante Knezic <ante.knezic@helmholz.de>
---
 drivers/net/dsa/mv88e6xxx/chip.c | 77 +++++++++++++++++++++++++---------------
 drivers/net/dsa/mv88e6xxx/chip.h |  2 --
 drivers/net/dsa/mv88e6xxx/port.c |  5 ---
 3 files changed, 48 insertions(+), 36 deletions(-)
diff mbox series

Patch

diff --git a/drivers/net/dsa/mv88e6xxx/chip.c b/drivers/net/dsa/mv88e6xxx/chip.c
index ce3a5d61edb4..fab92c3cb511 100644
--- a/drivers/net/dsa/mv88e6xxx/chip.c
+++ b/drivers/net/dsa/mv88e6xxx/chip.c
@@ -3568,6 +3568,28 @@  static int mv88e6xxx_stats_setup(struct mv88e6xxx_chip *chip)
 	return mv88e6xxx_g1_stats_clear(chip);
 }
 
+static int mv88e6xxx_mirror_setup(struct mv88e6xxx_chip *chip)
+{
+	int err, port, i;
+	const enum mv88e6xxx_egress_direction direction[] = {
+		MV88E6XXX_EGRESS_DIR_INGRESS, MV88E6XXX_EGRESS_DIR_EGRESS};
+
+	for (i = 0; i < ARRAY_SIZE(direction); i++) {
+		err = mv88e6xxx_set_egress_port(chip, i,
+						MV88E6XXX_EGRESS_DEST_DISABLE);
+		if (err)
+			return err;
+
+		for (port = 0; port < mv88e6xxx_num_ports(chip); port++) {
+			err = mv88e6xxx_port_set_mirror(chip, port, i, false);
+			if (err)
+				return err;
+		}
+	}
+
+	return 0;
+}
+
 /* Check if the errata has already been applied. */
 static bool mv88e6390_setup_errata_applied(struct mv88e6xxx_chip *chip)
 {
@@ -3966,6 +3988,10 @@  static int mv88e6xxx_setup(struct dsa_switch *ds)
 	if (err)
 		goto unlock;
 
+	err = mv88e6xxx_mirror_setup(chip);
+	if (err)
+		goto unlock;
+
 unlock:
 	mv88e6xxx_reg_unlock(chip);
 
@@ -6488,31 +6514,26 @@  static int mv88e6xxx_port_mirror_add(struct dsa_switch *ds, int from_port,
 						MV88E6XXX_EGRESS_DIR_INGRESS :
 						MV88E6XXX_EGRESS_DIR_EGRESS;
 	struct mv88e6xxx_chip *chip = ds->priv;
-	bool other_mirrors = false;
-	int i;
+	int *dest_port;
 	int err;
 
 	mutex_lock(&chip->reg_lock);
-	if ((ingress ? chip->ingress_dest_port : chip->egress_dest_port) !=
-	    to_port) {
-		for (i = 0; i < mv88e6xxx_num_ports(chip); i++)
-			other_mirrors |= ingress ?
-					 chip->ports[i].mirror_ingress :
-					 chip->ports[i].mirror_egress;
-
-		/* Can't change egress port when other mirror is active */
-		if (other_mirrors) {
-			err = -EBUSY;
-			goto out;
-		}
+	dest_port = ingress ? &chip->ingress_dest_port : &chip->egress_dest_port;
 
-		err = mv88e6xxx_set_egress_port(chip, direction,
-						to_port);
-		if (err)
-			goto out;
+	/* Can't change egress port when mirroring is active */
+	if (*dest_port != MV88E6XXX_EGRESS_DEST_DISABLE &&
+	    *dest_port != to_port) {
+		err = -EBUSY;
+		goto out;
 	}
 
-	err = mv88e6xxx_port_set_mirror(chip, from_port, direction, true);
+	err = mv88e6xxx_set_egress_port(chip, direction, to_port);
+	if (err)
+		goto out;
+
+	if (dsa_port_is_user(dsa_to_port(ds, from_port)))
+		err = mv88e6xxx_port_set_mirror(chip, from_port, direction, true);
+
 out:
 	mutex_unlock(&chip->reg_lock);
 
@@ -6527,20 +6548,18 @@  static void mv88e6xxx_port_mirror_del(struct dsa_switch *ds, int from_port,
 						MV88E6XXX_EGRESS_DIR_INGRESS :
 						MV88E6XXX_EGRESS_DIR_EGRESS;
 	struct mv88e6xxx_chip *chip = ds->priv;
-	bool other_mirrors = false;
-	int i;
+	int *dest_port;
 
 	mutex_lock(&chip->reg_lock);
-	if (mv88e6xxx_port_set_mirror(chip, from_port, direction, false))
-		dev_err(ds->dev, "p%d: failed to disable mirroring\n", from_port);
+	dest_port = ingress ? &chip->ingress_dest_port : &chip->egress_dest_port;
 
-	for (i = 0; i < mv88e6xxx_num_ports(chip); i++)
-		other_mirrors |= ingress ?
-				 chip->ports[i].mirror_ingress :
-				 chip->ports[i].mirror_egress;
+	if (!(route_status & DSA_ROUTE_SRC_PORT_BUSY)) {
+		if (mv88e6xxx_port_set_mirror(chip, from_port, direction, false))
+			dev_err(ds->dev, "p%d: failed to disable mirroring\n", from_port);
+	}
 
-	/* Reset egress port when no other mirror is active */
-	if (!other_mirrors) {
+	if (!(route_status & DSA_ROUTE_DEST_PORT_BUSY) &&
+	    *dest_port == to_port) {
 		if (mv88e6xxx_set_egress_port(chip, direction,
 					      MV88E6XXX_EGRESS_DEST_DISABLE))
 			dev_err(ds->dev, "failed to set egress port\n");
diff --git a/drivers/net/dsa/mv88e6xxx/chip.h b/drivers/net/dsa/mv88e6xxx/chip.h
index a73da4e965ec..0000a7aa3fbc 100644
--- a/drivers/net/dsa/mv88e6xxx/chip.h
+++ b/drivers/net/dsa/mv88e6xxx/chip.h
@@ -284,8 +284,6 @@  struct mv88e6xxx_port {
 	u64 vtu_miss_violation;
 	phy_interface_t interface;
 	u8 cmode;
-	bool mirror_ingress;
-	bool mirror_egress;
 	struct devlink_region *region;
 	void *pcs_private;
 
diff --git a/drivers/net/dsa/mv88e6xxx/port.c b/drivers/net/dsa/mv88e6xxx/port.c
index 5394a8cf7bf1..777515ee722b 100644
--- a/drivers/net/dsa/mv88e6xxx/port.c
+++ b/drivers/net/dsa/mv88e6xxx/port.c
@@ -1183,7 +1183,6 @@  int mv88e6xxx_port_set_mirror(struct mv88e6xxx_chip *chip, int port,
 			      enum mv88e6xxx_egress_direction direction,
 			      bool mirror)
 {
-	bool *mirror_port;
 	u16 reg;
 	u16 bit;
 	int err;
@@ -1195,11 +1194,9 @@  int mv88e6xxx_port_set_mirror(struct mv88e6xxx_chip *chip, int port,
 	switch (direction) {
 	case MV88E6XXX_EGRESS_DIR_INGRESS:
 		bit = MV88E6XXX_PORT_CTL2_INGRESS_MONITOR;
-		mirror_port = &chip->ports[port].mirror_ingress;
 		break;
 	case MV88E6XXX_EGRESS_DIR_EGRESS:
 		bit = MV88E6XXX_PORT_CTL2_EGRESS_MONITOR;
-		mirror_port = &chip->ports[port].mirror_egress;
 		break;
 	default:
 		return -EINVAL;
@@ -1210,8 +1207,6 @@  int mv88e6xxx_port_set_mirror(struct mv88e6xxx_chip *chip, int port,
 		reg |= bit;
 
 	err = mv88e6xxx_port_write(chip, port, MV88E6XXX_PORT_CTL2, reg);
-	if (!err)
-		*mirror_port = mirror;
 
 	return err;
 }