From: DENG Qingfang Date: Sun, 19 Apr 2020 08:04:06 +0000 (+0800) Subject: generic: backport mv88e6xxx port mirroring support X-Git-Url: http://git.cdn.openwrt.org/?a=commitdiff_plain;h=24410595e91cf99f1c1e347ccff3a3504c221795;p=openwrt%2Fstaging%2Flinusw.git generic: backport mv88e6xxx port mirroring support Backport port mirroring support for mv88e6xxx Signed-off-by: DENG Qingfang --- diff --git a/target/linux/generic/backport-5.4/746-v5.5-net-dsa-mv88e6xxx-Split-monitor-port-configuration.patch b/target/linux/generic/backport-5.4/746-v5.5-net-dsa-mv88e6xxx-Split-monitor-port-configuration.patch new file mode 100644 index 0000000000..73dbcbe352 --- /dev/null +++ b/target/linux/generic/backport-5.4/746-v5.5-net-dsa-mv88e6xxx-Split-monitor-port-configuration.patch @@ -0,0 +1,149 @@ +From 5c74c54ce6fff719999ff48f128cf4150ee4ff59 Mon Sep 17 00:00:00 2001 +From: Iwan R Timmer +Date: Thu, 7 Nov 2019 22:11:13 +0100 +Subject: [PATCH] net: dsa: mv88e6xxx: Split monitor port configuration + +Separate the configuration of the egress and ingress monitor port. +This allows the port mirror functionality to do ingress and egress +port mirroring to separate ports. + +Signed-off-by: Iwan R Timmer +Reviewed-by: Andrew Lunn +Signed-off-by: David S. Miller +--- + drivers/net/dsa/mv88e6xxx/chip.c | 9 ++++++- + drivers/net/dsa/mv88e6xxx/chip.h | 9 ++++++- + drivers/net/dsa/mv88e6xxx/global1.c | 42 ++++++++++++++++++++--------- + drivers/net/dsa/mv88e6xxx/global1.h | 8 ++++-- + 4 files changed, 52 insertions(+), 16 deletions(-) + +--- a/drivers/net/dsa/mv88e6xxx/chip.c ++++ b/drivers/net/dsa/mv88e6xxx/chip.c +@@ -2378,7 +2378,14 @@ static int mv88e6xxx_setup_upstream_port + + if (chip->info->ops->set_egress_port) { + err = chip->info->ops->set_egress_port(chip, +- upstream_port); ++ MV88E6XXX_EGRESS_DIR_INGRESS, ++ upstream_port); ++ if (err) ++ return err; ++ ++ err = chip->info->ops->set_egress_port(chip, ++ MV88E6XXX_EGRESS_DIR_EGRESS, ++ upstream_port); + if (err) + return err; + } +--- a/drivers/net/dsa/mv88e6xxx/chip.h ++++ b/drivers/net/dsa/mv88e6xxx/chip.h +@@ -33,6 +33,11 @@ enum mv88e6xxx_egress_mode { + MV88E6XXX_EGRESS_MODE_ETHERTYPE, + }; + ++enum mv88e6xxx_egress_direction { ++ MV88E6XXX_EGRESS_DIR_INGRESS, ++ MV88E6XXX_EGRESS_DIR_EGRESS, ++}; ++ + enum mv88e6xxx_frame_mode { + MV88E6XXX_FRAME_MODE_NORMAL, + MV88E6XXX_FRAME_MODE_DSA, +@@ -464,7 +469,9 @@ struct mv88e6xxx_ops { + int (*stats_get_stats)(struct mv88e6xxx_chip *chip, int port, + uint64_t *data); + int (*set_cpu_port)(struct mv88e6xxx_chip *chip, int port); +- int (*set_egress_port)(struct mv88e6xxx_chip *chip, int port); ++ int (*set_egress_port)(struct mv88e6xxx_chip *chip, ++ enum mv88e6xxx_egress_direction direction, ++ int port); + + #define MV88E6XXX_CASCADE_PORT_NONE 0xe + #define MV88E6XXX_CASCADE_PORT_MULTIPLE 0xf +--- a/drivers/net/dsa/mv88e6xxx/global1.c ++++ b/drivers/net/dsa/mv88e6xxx/global1.c +@@ -263,7 +263,9 @@ int mv88e6250_g1_ieee_pri_map(struct mv8 + /* Offset 0x1a: Monitor Control */ + /* Offset 0x1a: Monitor & MGMT Control on some devices */ + +-int mv88e6095_g1_set_egress_port(struct mv88e6xxx_chip *chip, int port) ++int mv88e6095_g1_set_egress_port(struct mv88e6xxx_chip *chip, ++ enum mv88e6xxx_egress_direction direction, ++ int port) + { + u16 reg; + int err; +@@ -272,11 +274,20 @@ int mv88e6095_g1_set_egress_port(struct + if (err) + return err; + +- reg &= ~(MV88E6185_G1_MONITOR_CTL_INGRESS_DEST_MASK | +- MV88E6185_G1_MONITOR_CTL_EGRESS_DEST_MASK); +- +- reg |= port << __bf_shf(MV88E6185_G1_MONITOR_CTL_INGRESS_DEST_MASK) | +- port << __bf_shf(MV88E6185_G1_MONITOR_CTL_EGRESS_DEST_MASK); ++ switch (direction) { ++ case MV88E6XXX_EGRESS_DIR_INGRESS: ++ reg &= MV88E6185_G1_MONITOR_CTL_INGRESS_DEST_MASK; ++ reg |= port << ++ __bf_shf(MV88E6185_G1_MONITOR_CTL_INGRESS_DEST_MASK); ++ break; ++ case MV88E6XXX_EGRESS_DIR_EGRESS: ++ reg &= MV88E6185_G1_MONITOR_CTL_EGRESS_DEST_MASK; ++ reg |= port << ++ __bf_shf(MV88E6185_G1_MONITOR_CTL_EGRESS_DEST_MASK); ++ break; ++ default: ++ return -EINVAL; ++ } + + return mv88e6xxx_g1_write(chip, MV88E6185_G1_MONITOR_CTL, reg); + } +@@ -310,17 +321,24 @@ static int mv88e6390_g1_monitor_write(st + return mv88e6xxx_g1_write(chip, MV88E6390_G1_MONITOR_MGMT_CTL, reg); + } + +-int mv88e6390_g1_set_egress_port(struct mv88e6xxx_chip *chip, int port) ++int mv88e6390_g1_set_egress_port(struct mv88e6xxx_chip *chip, ++ enum mv88e6xxx_egress_direction direction, ++ int port) + { + u16 ptr; + int err; + +- ptr = MV88E6390_G1_MONITOR_MGMT_CTL_PTR_INGRESS_DEST; +- err = mv88e6390_g1_monitor_write(chip, ptr, port); +- if (err) +- return err; ++ switch (direction) { ++ case MV88E6XXX_EGRESS_DIR_INGRESS: ++ ptr = MV88E6390_G1_MONITOR_MGMT_CTL_PTR_INGRESS_DEST; ++ break; ++ case MV88E6XXX_EGRESS_DIR_EGRESS: ++ ptr = MV88E6390_G1_MONITOR_MGMT_CTL_PTR_EGRESS_DEST; ++ break; ++ default: ++ return -EINVAL; ++ } + +- ptr = MV88E6390_G1_MONITOR_MGMT_CTL_PTR_EGRESS_DEST; + err = mv88e6390_g1_monitor_write(chip, ptr, port); + if (err) + return err; +--- a/drivers/net/dsa/mv88e6xxx/global1.h ++++ b/drivers/net/dsa/mv88e6xxx/global1.h +@@ -288,8 +288,12 @@ int mv88e6095_g1_stats_set_histogram(str + int mv88e6390_g1_stats_set_histogram(struct mv88e6xxx_chip *chip); + void mv88e6xxx_g1_stats_read(struct mv88e6xxx_chip *chip, int stat, u32 *val); + int mv88e6xxx_g1_stats_clear(struct mv88e6xxx_chip *chip); +-int mv88e6095_g1_set_egress_port(struct mv88e6xxx_chip *chip, int port); +-int mv88e6390_g1_set_egress_port(struct mv88e6xxx_chip *chip, int port); ++int mv88e6095_g1_set_egress_port(struct mv88e6xxx_chip *chip, ++ enum mv88e6xxx_egress_direction direction, ++ int port); ++int mv88e6390_g1_set_egress_port(struct mv88e6xxx_chip *chip, ++ enum mv88e6xxx_egress_direction direction, ++ int port); + int mv88e6095_g1_set_cpu_port(struct mv88e6xxx_chip *chip, int port); + int mv88e6390_g1_set_cpu_port(struct mv88e6xxx_chip *chip, int port); + int mv88e6390_g1_mgmt_rsvd2cpu(struct mv88e6xxx_chip *chip); diff --git a/target/linux/generic/backport-5.4/747-v5.5-net-dsa-mv88e6xxx-Add-support-for-port-mirroring.patch b/target/linux/generic/backport-5.4/747-v5.5-net-dsa-mv88e6xxx-Add-support-for-port-mirroring.patch new file mode 100644 index 0000000000..23c9bddf07 --- /dev/null +++ b/target/linux/generic/backport-5.4/747-v5.5-net-dsa-mv88e6xxx-Add-support-for-port-mirroring.patch @@ -0,0 +1,266 @@ +From f0942e00a1abb6404ca4302c66497fc623676c11 Mon Sep 17 00:00:00 2001 +From: Iwan R Timmer +Date: Thu, 7 Nov 2019 22:11:14 +0100 +Subject: [PATCH] net: dsa: mv88e6xxx: Add support for port mirroring + +Add support for configuring port mirroring through the cls_matchall +classifier. We do a full ingress and/or egress capture towards a +capture port. It allows setting a different capture port for ingress +and egress traffic. + +It keeps track of the mirrored ports and the destination ports to +prevent changes to the capture port while other ports are being +mirrored. + +Signed-off-by: Iwan R Timmer +Reviewed-by: Andrew Lunn +Signed-off-by: David S. Miller +--- + drivers/net/dsa/mv88e6xxx/chip.c | 76 +++++++++++++++++++++++++++++ + drivers/net/dsa/mv88e6xxx/chip.h | 6 +++ + drivers/net/dsa/mv88e6xxx/global1.c | 18 +++++-- + drivers/net/dsa/mv88e6xxx/port.c | 37 ++++++++++++++ + drivers/net/dsa/mv88e6xxx/port.h | 3 ++ + 5 files changed, 136 insertions(+), 4 deletions(-) + +--- a/drivers/net/dsa/mv88e6xxx/chip.c ++++ b/drivers/net/dsa/mv88e6xxx/chip.c +@@ -4921,6 +4921,80 @@ static int mv88e6xxx_port_mdb_del(struct + return err; + } + ++static int mv88e6xxx_port_mirror_add(struct dsa_switch *ds, int port, ++ struct dsa_mall_mirror_tc_entry *mirror, ++ bool ingress) ++{ ++ enum mv88e6xxx_egress_direction direction = ingress ? ++ MV88E6XXX_EGRESS_DIR_INGRESS : ++ MV88E6XXX_EGRESS_DIR_EGRESS; ++ struct mv88e6xxx_chip *chip = ds->priv; ++ bool other_mirrors = false; ++ int i; ++ int err; ++ ++ if (!chip->info->ops->set_egress_port) ++ return -EOPNOTSUPP; ++ ++ mutex_lock(&chip->reg_lock); ++ if ((ingress ? chip->ingress_dest_port : chip->egress_dest_port) != ++ mirror->to_local_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; ++ } ++ ++ err = chip->info->ops->set_egress_port(chip, ++ direction, ++ mirror->to_local_port); ++ if (err) ++ goto out; ++ } ++ ++ err = mv88e6xxx_port_set_mirror(chip, port, direction, true); ++out: ++ mutex_unlock(&chip->reg_lock); ++ ++ return err; ++} ++ ++static void mv88e6xxx_port_mirror_del(struct dsa_switch *ds, int port, ++ struct dsa_mall_mirror_tc_entry *mirror) ++{ ++ enum mv88e6xxx_egress_direction direction = mirror->ingress ? ++ MV88E6XXX_EGRESS_DIR_INGRESS : ++ MV88E6XXX_EGRESS_DIR_EGRESS; ++ struct mv88e6xxx_chip *chip = ds->priv; ++ bool other_mirrors = false; ++ int i; ++ ++ mutex_lock(&chip->reg_lock); ++ if (mv88e6xxx_port_set_mirror(chip, port, direction, false)) ++ dev_err(ds->dev, "p%d: failed to disable mirroring\n", port); ++ ++ for (i = 0; i < mv88e6xxx_num_ports(chip); i++) ++ other_mirrors |= mirror->ingress ? ++ chip->ports[i].mirror_ingress : ++ chip->ports[i].mirror_egress; ++ ++ /* Reset egress port when no other mirror is active */ ++ if (!other_mirrors) { ++ if (chip->info->ops->set_egress_port(chip, ++ direction, ++ dsa_upstream_port(ds, ++ port))); ++ dev_err(ds->dev, "failed to set egress port\n"); ++ } ++ ++ mutex_unlock(&chip->reg_lock); ++} ++ + static int mv88e6xxx_port_egress_floods(struct dsa_switch *ds, int port, + bool unicast, bool multicast) + { +@@ -4975,6 +5049,8 @@ static const struct dsa_switch_ops mv88e + .port_mdb_prepare = mv88e6xxx_port_mdb_prepare, + .port_mdb_add = mv88e6xxx_port_mdb_add, + .port_mdb_del = mv88e6xxx_port_mdb_del, ++ .port_mirror_add = mv88e6xxx_port_mirror_add, ++ .port_mirror_del = mv88e6xxx_port_mirror_del, + .crosschip_bridge_join = mv88e6xxx_crosschip_bridge_join, + .crosschip_bridge_leave = mv88e6xxx_crosschip_bridge_leave, + .port_hwtstamp_set = mv88e6xxx_port_hwtstamp_set, +--- a/drivers/net/dsa/mv88e6xxx/chip.h ++++ b/drivers/net/dsa/mv88e6xxx/chip.h +@@ -232,6 +232,8 @@ struct mv88e6xxx_port { + u64 vtu_member_violation; + u64 vtu_miss_violation; + u8 cmode; ++ bool mirror_ingress; ++ bool mirror_egress; + unsigned int serdes_irq; + }; + +@@ -315,6 +317,10 @@ struct mv88e6xxx_chip { + u16 evcap_config; + u16 enable_count; + ++ /* Current ingress and egress monitor ports */ ++ int egress_dest_port; ++ int ingress_dest_port; ++ + /* Per-port timestamping resources. */ + struct mv88e6xxx_port_hwtstamp port_hwtstamp[DSA_MAX_PORTS]; + +--- a/drivers/net/dsa/mv88e6xxx/global1.c ++++ b/drivers/net/dsa/mv88e6xxx/global1.c +@@ -267,6 +267,7 @@ int mv88e6095_g1_set_egress_port(struct + enum mv88e6xxx_egress_direction direction, + int port) + { ++ int *dest_port_chip; + u16 reg; + int err; + +@@ -276,11 +277,13 @@ int mv88e6095_g1_set_egress_port(struct + + switch (direction) { + case MV88E6XXX_EGRESS_DIR_INGRESS: ++ dest_port_chip = &chip->ingress_dest_port; + reg &= MV88E6185_G1_MONITOR_CTL_INGRESS_DEST_MASK; + reg |= port << + __bf_shf(MV88E6185_G1_MONITOR_CTL_INGRESS_DEST_MASK); + break; + case MV88E6XXX_EGRESS_DIR_EGRESS: ++ dest_port_chip = &chip->egress_dest_port; + reg &= MV88E6185_G1_MONITOR_CTL_EGRESS_DEST_MASK; + reg |= port << + __bf_shf(MV88E6185_G1_MONITOR_CTL_EGRESS_DEST_MASK); +@@ -289,7 +292,11 @@ int mv88e6095_g1_set_egress_port(struct + return -EINVAL; + } + +- return mv88e6xxx_g1_write(chip, MV88E6185_G1_MONITOR_CTL, reg); ++ err = mv88e6xxx_g1_write(chip, MV88E6185_G1_MONITOR_CTL, reg); ++ if (!err) ++ *dest_port_chip = port; ++ ++ return err; + } + + /* Older generations also call this the ARP destination. It has been +@@ -325,14 +332,17 @@ int mv88e6390_g1_set_egress_port(struct + enum mv88e6xxx_egress_direction direction, + int port) + { ++ int *dest_port_chip; + u16 ptr; + int err; + + switch (direction) { + case MV88E6XXX_EGRESS_DIR_INGRESS: ++ dest_port_chip = &chip->ingress_dest_port; + ptr = MV88E6390_G1_MONITOR_MGMT_CTL_PTR_INGRESS_DEST; + break; + case MV88E6XXX_EGRESS_DIR_EGRESS: ++ dest_port_chip = &chip->egress_dest_port; + ptr = MV88E6390_G1_MONITOR_MGMT_CTL_PTR_EGRESS_DEST; + break; + default: +@@ -340,10 +350,10 @@ int mv88e6390_g1_set_egress_port(struct + } + + err = mv88e6390_g1_monitor_write(chip, ptr, port); +- if (err) +- return err; ++ if (!err) ++ *dest_port_chip = port; + +- return 0; ++ return err; + } + + int mv88e6390_g1_set_cpu_port(struct mv88e6xxx_chip *chip, int port) +--- a/drivers/net/dsa/mv88e6xxx/port.c ++++ b/drivers/net/dsa/mv88e6xxx/port.c +@@ -1181,6 +1181,43 @@ int mv88e6095_port_set_upstream_port(str + return mv88e6xxx_port_write(chip, port, MV88E6XXX_PORT_CTL2, reg); + } + ++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; ++ ++ err = mv88e6xxx_port_read(chip, port, MV88E6XXX_PORT_CTL2, ®); ++ if (err) ++ return err; ++ ++ 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; ++ } ++ ++ reg &= ~bit; ++ if (mirror) ++ reg |= bit; ++ ++ err = mv88e6xxx_port_write(chip, port, MV88E6XXX_PORT_CTL2, reg); ++ if (!err) ++ *mirror_port = mirror; ++ ++ return err; ++} ++ + int mv88e6xxx_port_set_8021q_mode(struct mv88e6xxx_chip *chip, int port, + u16 mode) + { +--- a/drivers/net/dsa/mv88e6xxx/port.h ++++ b/drivers/net/dsa/mv88e6xxx/port.h +@@ -368,6 +368,9 @@ int mv88e6352_port_link_state(struct mv8 + int mv88e6xxx_port_set_map_da(struct mv88e6xxx_chip *chip, int port); + int mv88e6095_port_set_upstream_port(struct mv88e6xxx_chip *chip, int port, + int upstream_port); ++int mv88e6xxx_port_set_mirror(struct mv88e6xxx_chip *chip, int port, ++ enum mv88e6xxx_egress_direction direction, ++ bool mirror); + + int mv88e6xxx_port_disable_learn_limit(struct mv88e6xxx_chip *chip, int port); + int mv88e6xxx_port_disable_pri_override(struct mv88e6xxx_chip *chip, int port); diff --git a/target/linux/generic/backport-5.4/748-v5.5-net-dsa-mv88e6xxx-fix-broken-if-statement-because-of.patch b/target/linux/generic/backport-5.4/748-v5.5-net-dsa-mv88e6xxx-fix-broken-if-statement-because-of.patch new file mode 100644 index 0000000000..d9d5a5fd7c --- /dev/null +++ b/target/linux/generic/backport-5.4/748-v5.5-net-dsa-mv88e6xxx-fix-broken-if-statement-because-of.patch @@ -0,0 +1,30 @@ +From 4e4637b10374ede3cd33d7e1b389e6cea6343ea3 Mon Sep 17 00:00:00 2001 +From: Colin Ian King +Date: Tue, 12 Nov 2019 13:05:23 +0000 +Subject: [PATCH] net: dsa: mv88e6xxx: fix broken if statement because of a + stray semicolon + +There is a stray semicolon in an if statement that will cause a dev_err +message to be printed unconditionally. Fix this by removing the stray +semicolon. + +Addresses-Coverity: ("Stay semicolon") +Fixes: f0942e00a1ab ("net: dsa: mv88e6xxx: Add support for port mirroring") +Signed-off-by: Colin Ian King +Reviewed-by: Andrew Lunn +Signed-off-by: David S. Miller +--- + drivers/net/dsa/mv88e6xxx/chip.c | 2 +- + 1 file changed, 1 insertion(+), 1 deletion(-) + +--- a/drivers/net/dsa/mv88e6xxx/chip.c ++++ b/drivers/net/dsa/mv88e6xxx/chip.c +@@ -4988,7 +4988,7 @@ static void mv88e6xxx_port_mirror_del(st + if (chip->info->ops->set_egress_port(chip, + direction, + dsa_upstream_port(ds, +- port))); ++ port))) + dev_err(ds->dev, "failed to set egress port\n"); + } + diff --git a/target/linux/generic/backport-5.4/749-v5.5-net-dsa-mv88e6xxx-Fix-masking-of-egress-port.patch b/target/linux/generic/backport-5.4/749-v5.5-net-dsa-mv88e6xxx-Fix-masking-of-egress-port.patch new file mode 100644 index 0000000000..50f655c0d2 --- /dev/null +++ b/target/linux/generic/backport-5.4/749-v5.5-net-dsa-mv88e6xxx-Fix-masking-of-egress-port.patch @@ -0,0 +1,34 @@ +From 3ee339eb28959629db33aaa2b8cde4c63c6289eb Mon Sep 17 00:00:00 2001 +From: Andrew Lunn +Date: Thu, 27 Feb 2020 21:20:49 +0100 +Subject: [PATCH] net: dsa: mv88e6xxx: Fix masking of egress port + +Add missing ~ to the usage of the mask. + +Reported-by: Kevin Benson +Reported-by: Chris Healy +Fixes: 5c74c54ce6ff ("net: dsa: mv88e6xxx: Split monitor port configuration") +Signed-off-by: Andrew Lunn +Signed-off-by: David S. Miller +--- + drivers/net/dsa/mv88e6xxx/global1.c | 4 ++-- + 1 file changed, 2 insertions(+), 2 deletions(-) + +--- a/drivers/net/dsa/mv88e6xxx/global1.c ++++ b/drivers/net/dsa/mv88e6xxx/global1.c +@@ -278,13 +278,13 @@ int mv88e6095_g1_set_egress_port(struct + switch (direction) { + case MV88E6XXX_EGRESS_DIR_INGRESS: + dest_port_chip = &chip->ingress_dest_port; +- reg &= MV88E6185_G1_MONITOR_CTL_INGRESS_DEST_MASK; ++ reg &= ~MV88E6185_G1_MONITOR_CTL_INGRESS_DEST_MASK; + reg |= port << + __bf_shf(MV88E6185_G1_MONITOR_CTL_INGRESS_DEST_MASK); + break; + case MV88E6XXX_EGRESS_DIR_EGRESS: + dest_port_chip = &chip->egress_dest_port; +- reg &= MV88E6185_G1_MONITOR_CTL_EGRESS_DEST_MASK; ++ reg &= ~MV88E6185_G1_MONITOR_CTL_EGRESS_DEST_MASK; + reg |= port << + __bf_shf(MV88E6185_G1_MONITOR_CTL_EGRESS_DEST_MASK); + break;