diff --git a/target/linux/generic/backport-5.4/745-v5.7-net-dsa-mt7530-add-support-for-port-mirroring.patch b/target/linux/generic/backport-5.4/745-v5.7-net-dsa-mt7530-add-support-for-port-mirroring.patch new file mode 100644 index 0000000000..39e351e279 --- /dev/null +++ b/target/linux/generic/backport-5.4/745-v5.7-net-dsa-mt7530-add-support-for-port-mirroring.patch @@ -0,0 +1,123 @@ +From 37feab6076aa816ed72fe836759a485353241916 Mon Sep 17 00:00:00 2001 +From: DENG Qingfang +Date: Fri, 6 Mar 2020 20:35:35 +0800 +Subject: net: dsa: mt7530: 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. +MT7530 supports one monitor port and multiple mirrored ports. + +Signed-off-by: DENG Qingfang +Signed-off-by: David S. Miller +--- + drivers/net/dsa/mt7530.c | 60 ++++++++++++++++++++++++++++++++++++++++++++++++ + drivers/net/dsa/mt7530.h | 7 ++++++ + 2 files changed, 67 insertions(+) + +--- a/drivers/net/dsa/mt7530.c ++++ b/drivers/net/dsa/mt7530.c +@@ -1222,6 +1222,64 @@ mt7530_port_vlan_del(struct dsa_switch *ds, int port, + return 0; + } + ++static int mt7530_port_mirror_add(struct dsa_switch *ds, int port, ++ struct dsa_mall_mirror_tc_entry *mirror, ++ bool ingress) ++{ ++ struct mt7530_priv *priv = ds->priv; ++ u32 val; ++ ++ /* Check for existent entry */ ++ if ((ingress ? priv->mirror_rx : priv->mirror_tx) & BIT(port)) ++ return -EEXIST; ++ ++ val = mt7530_read(priv, MT7530_MFC); ++ ++ /* MT7530 only supports one monitor port */ ++ if (val & MIRROR_EN && MIRROR_PORT(val) != mirror->to_local_port) ++ return -EEXIST; ++ ++ val |= MIRROR_EN; ++ val &= ~MIRROR_MASK; ++ val |= mirror->to_local_port; ++ mt7530_write(priv, MT7530_MFC, val); ++ ++ val = mt7530_read(priv, MT7530_PCR_P(port)); ++ if (ingress) { ++ val |= PORT_RX_MIR; ++ priv->mirror_rx |= BIT(port); ++ } else { ++ val |= PORT_TX_MIR; ++ priv->mirror_tx |= BIT(port); ++ } ++ mt7530_write(priv, MT7530_PCR_P(port), val); ++ ++ return 0; ++} ++ ++static void mt7530_port_mirror_del(struct dsa_switch *ds, int port, ++ struct dsa_mall_mirror_tc_entry *mirror) ++{ ++ struct mt7530_priv *priv = ds->priv; ++ u32 val; ++ ++ val = mt7530_read(priv, MT7530_PCR_P(port)); ++ if (mirror->ingress) { ++ val &= ~PORT_RX_MIR; ++ priv->mirror_rx &= ~BIT(port); ++ } else { ++ val &= ~PORT_TX_MIR; ++ priv->mirror_tx &= ~BIT(port); ++ } ++ mt7530_write(priv, MT7530_PCR_P(port), val); ++ ++ if (!priv->mirror_rx && !priv->mirror_tx) { ++ val = mt7530_read(priv, MT7530_MFC); ++ val &= ~MIRROR_EN; ++ mt7530_write(priv, MT7530_MFC, val); ++ } ++} ++ + static enum dsa_tag_protocol + mtk_get_tag_protocol(struct dsa_switch *ds, int port, + enum dsa_tag_protocol mp) +@@ -1613,6 +1671,8 @@ static const struct dsa_switch_ops mt7530_switch_ops = { + .port_vlan_prepare = mt7530_port_vlan_prepare, + .port_vlan_add = mt7530_port_vlan_add, + .port_vlan_del = mt7530_port_vlan_del, ++ .port_mirror_add = mt7530_port_mirror_add, ++ .port_mirror_del = mt7530_port_mirror_del, + .phylink_validate = mt7530_phylink_validate, + .phylink_mac_link_state = mt7530_phylink_mac_link_state, + .phylink_mac_config = mt7530_phylink_mac_config, +--- a/drivers/net/dsa/mt7530.h ++++ b/drivers/net/dsa/mt7530.h +@@ -36,6 +36,9 @@ enum { + #define CPU_EN BIT(7) + #define CPU_PORT(x) ((x) << 4) + #define CPU_MASK (0xf << 4) ++#define MIRROR_EN BIT(3) ++#define MIRROR_PORT(x) ((x) & 0x7) ++#define MIRROR_MASK 0x7 + + /* Registers for address table access */ + #define MT7530_ATA1 0x74 +@@ -141,6 +144,8 @@ enum mt7530_stp_state { + + /* Register for port control */ + #define MT7530_PCR_P(x) (0x2004 + ((x) * 0x100)) ++#define PORT_TX_MIR BIT(9) ++#define PORT_RX_MIR BIT(8) + #define PORT_VLAN(x) ((x) & 0x3) + + enum mt7530_port_mode { +@@ -460,6 +465,8 @@ struct mt7530_priv { + phy_interface_t p6_interface; + phy_interface_t p5_interface; + unsigned int p5_intf_sel; ++ u8 mirror_rx; ++ u8 mirror_tx; + + struct mt7530_port ports[MT7530_NUM_PORTS]; + /* protect among processes for registers access*/