| From 5c74c54ce6fff719999ff48f128cf4150ee4ff59 Mon Sep 17 00:00:00 2001 |
| From: Iwan R Timmer <irtimmer@gmail.com> |
| 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 <irtimmer@gmail.com> |
| Reviewed-by: Andrew Lunn <andrew@lunn.ch> |
| Signed-off-by: David S. Miller <davem@davemloft.net> |
| --- |
| 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 |
| @@ -2384,7 +2384,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 |
| @@ -294,7 +294,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; |
| @@ -303,11 +305,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); |
| } |
| @@ -341,17 +352,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 |
| @@ -289,8 +289,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); |