ramips: add MT7530 switch port-mirroring support
authorDeng Qingfang <dengqf6@mail2.sysu.edu.cn>
Sun, 16 Dec 2018 15:49:07 +0000 (23:49 +0800)
committerChuanhong Guo <gch981213@gmail.com>
Sun, 18 Aug 2019 14:08:42 +0000 (22:08 +0800)
Compile & run tested on MT7620, MT7621

Signed-off-by: Deng Qingfang <dengqf6@mail2.sysu.edu.cn>
[Tested on Phicomm PSG1218 rev.A, MediaTek MT7620A ver:2 eco:6]
Tested-by: MingHao Chen <cmheia@email.com>
target/linux/ramips/files-4.14/drivers/net/ethernet/mediatek/mt7530.c

index 5216cb5c6618d018c4075791037cf91bb0398795..9acea3bc8454522e111718eefe94826a1897be74 100644 (file)
 #define MT7621_PORT_MIB_RXB_ID 37      /* RxByte */
 
 /* registers */
+#define REG_ESW_WT_MAC_MFC             0x10
+
+#define REG_ESW_WT_MAC_MFC_MIRROR_ENABLE       BIT(3)
+#define REG_ESW_WT_MAC_MFC_MIRROR_DEST_MASK    0x07
+
 #define REG_ESW_VLAN_VTCR              0x90
 #define REG_ESW_VLAN_VAWD1             0x94
 #define REG_ESW_VLAN_VAWD2             0x98
@@ -72,6 +77,11 @@ enum {
 #define REG_ESW_PORT_PVC(x)    (0x2010 | ((x) << 8))
 #define REG_ESW_PORT_PPBV1(x)  (0x2014 | ((x) << 8))
 
+#define REG_ESW_PORT_PCR_MIRROR_SRC_RX_BIT     BIT(8)
+#define REG_ESW_PORT_PCR_MIRROR_SRC_TX_BIT     BIT(9)
+#define REG_ESW_PORT_PCR_MIRROR_SRC_RX_MASK    0x0100
+#define REG_ESW_PORT_PCR_MIRROR_SRC_TX_MASK    0x0200
+
 #define REG_HWTRAP             0x7804
 
 #define MIB_DESC(_s , _o, _n)   \
@@ -183,6 +193,8 @@ enum {
 
 struct mt7530_port_entry {
        u16     pvid;
+       bool    mirror_rx;
+       bool    mirror_tx;
 };
 
 struct mt7530_vlan_entry {
@@ -196,6 +208,8 @@ struct mt7530_priv {
        struct mii_bus          *bus;
        struct switch_dev       swdev;
 
+       u8                      mirror_src_port;
+       u8                      mirror_dest_port;
        bool                    global_vlan_enable;
        struct mt7530_vlan_entry        vlan_entries[MT7530_NUM_VLANS];
        struct mt7530_port_entry        port_entries[MT7530_NUM_PORTS];
@@ -505,6 +519,138 @@ mt7530_get_vid(struct switch_dev *dev, const struct switch_attr *attr,
        return 0;
 }
 
+static int
+mt7530_get_mirror_rx_enable(struct switch_dev *dev, const struct switch_attr *attr,
+               struct switch_val *val)
+{
+       struct mt7530_priv *priv = container_of(dev, struct mt7530_priv, swdev);
+
+       val->value.i = priv->port_entries[priv->mirror_src_port].mirror_rx;
+
+       return 0;
+}
+
+static int
+mt7530_set_mirror_rx_enable(struct switch_dev *dev, const struct switch_attr *attr,
+               struct switch_val *val)
+{
+       struct mt7530_priv *priv = container_of(dev, struct mt7530_priv, swdev);
+
+       priv->port_entries[priv->mirror_src_port].mirror_rx = val->value.i;
+
+       return 0;
+}
+
+static int
+mt7530_get_mirror_tx_enable(struct switch_dev *dev, const struct switch_attr *attr,
+               struct switch_val *val)
+{
+       struct mt7530_priv *priv = container_of(dev, struct mt7530_priv, swdev);
+
+       val->value.i = priv->port_entries[priv->mirror_src_port].mirror_tx;
+
+       return 0;
+}
+
+static int
+mt7530_set_mirror_tx_enable(struct switch_dev *dev, const struct switch_attr *attr,
+               struct switch_val *val)
+{
+       struct mt7530_priv *priv = container_of(dev, struct mt7530_priv, swdev);
+
+       priv->port_entries[priv->mirror_src_port].mirror_tx = val->value.i;
+
+       return 0;
+}
+
+static int
+mt7530_get_mirror_monitor_port(struct switch_dev *dev, const struct switch_attr *attr,
+               struct switch_val *val)
+{
+       struct mt7530_priv *priv = container_of(dev, struct mt7530_priv, swdev);
+
+       val->value.i = priv->mirror_dest_port;
+
+       return 0;
+}
+
+static int
+mt7530_set_mirror_monitor_port(struct switch_dev *dev, const struct switch_attr *attr,
+               struct switch_val *val)
+{
+       struct mt7530_priv *priv = container_of(dev, struct mt7530_priv, swdev);
+
+       priv->mirror_dest_port = val->value.i;
+
+       return 0;
+}
+
+static int
+mt7530_get_mirror_source_port(struct switch_dev *dev, const struct switch_attr *attr,
+               struct switch_val *val)
+{
+       struct mt7530_priv *priv = container_of(dev, struct mt7530_priv, swdev);
+
+       val->value.i = priv->mirror_src_port;
+
+       return 0;
+}
+
+static int
+mt7530_set_mirror_source_port(struct switch_dev *dev, const struct switch_attr *attr,
+               struct switch_val *val)
+{
+       struct mt7530_priv *priv = container_of(dev, struct mt7530_priv, swdev);
+
+       priv->mirror_src_port = val->value.i;
+
+       return 0;
+}
+
+static int
+mt7530_get_port_mirror_rx(struct switch_dev *dev, const struct switch_attr *attr,
+               struct switch_val *val)
+{
+       struct mt7530_priv *priv = container_of(dev, struct mt7530_priv, swdev);
+
+       val->value.i =  priv->port_entries[val->port_vlan].mirror_rx;
+
+       return 0;
+}
+
+static int
+mt7530_set_port_mirror_rx(struct switch_dev *dev, const struct switch_attr *attr,
+               struct switch_val *val)
+{
+       struct mt7530_priv *priv = container_of(dev, struct mt7530_priv, swdev);
+
+       priv->port_entries[val->port_vlan].mirror_rx = val->value.i;
+
+       return 0;
+}
+
+static int
+mt7530_get_port_mirror_tx(struct switch_dev *dev, const struct switch_attr *attr,
+               struct switch_val *val)
+{
+       struct mt7530_priv *priv = container_of(dev, struct mt7530_priv, swdev);
+
+       val->value.i =  priv->port_entries[val->port_vlan].mirror_tx;
+
+       return 0;
+}
+
+static int
+mt7530_set_port_mirror_tx(struct switch_dev *dev, const struct switch_attr *attr,
+               struct switch_val *val)
+{
+       struct mt7530_priv *priv = container_of(dev, struct mt7530_priv, swdev);
+
+       priv->port_entries[val->port_vlan].mirror_tx = val->value.i;
+
+       return 0;
+}
+
 static void
 mt7530_write_vlan_entry(struct mt7530_priv *priv, int vlan, u16 vid,
                            u8 ports, u8 etags)
@@ -558,6 +704,7 @@ mt7530_apply_config(struct switch_dev *dev)
        int i, j;
        u8 tag_ports;
        u8 untag_ports;
+       bool is_mirror = false;
 
        if (!priv->global_vlan_enable) {
                for (i = 0; i < MT7530_NUM_PORTS; i++)
@@ -637,6 +784,31 @@ mt7530_apply_config(struct switch_dev *dev)
                mt7530_w32(priv, REG_ESW_PORT_PPBV1(i), val);
        }
 
+       /* set mirroring source port */
+       for (i = 0; i < MT7530_NUM_PORTS; i++)  {
+               u32 val = mt7530_r32(priv, REG_ESW_PORT_PCR(i));
+               if (priv->port_entries[i].mirror_rx) {
+                       val |= REG_ESW_PORT_PCR_MIRROR_SRC_RX_BIT;
+                       is_mirror = true;
+               }
+
+               if (priv->port_entries[i].mirror_tx) {
+                       val |= REG_ESW_PORT_PCR_MIRROR_SRC_TX_BIT;
+                       is_mirror = true;
+               }
+
+               mt7530_w32(priv, REG_ESW_PORT_PCR(i), val);
+       }
+
+       /* set mirroring monitor port */
+       if (is_mirror) {
+               u32 val = mt7530_r32(priv, REG_ESW_WT_MAC_MFC);
+               val |= REG_ESW_WT_MAC_MFC_MIRROR_ENABLE;
+               val &= ~REG_ESW_WT_MAC_MFC_MIRROR_DEST_MASK;
+               val |= priv->mirror_dest_port;
+               mt7530_w32(priv, REG_ESW_WT_MAC_MFC, val);
+       }
+
        return 0;
 }
 
@@ -830,6 +1002,34 @@ static const struct switch_attr mt7530_global[] = {
                .description = "Get MIB counters for switch",
                .get = mt7530_sw_get_mib,
                .set = NULL,
+       }, {
+               .type = SWITCH_TYPE_INT,
+               .name = "enable_mirror_rx",
+               .description = "Enable mirroring of RX packets",
+               .set = mt7530_set_mirror_rx_enable,
+               .get = mt7530_get_mirror_rx_enable,
+               .max = 1
+       }, {
+               .type = SWITCH_TYPE_INT,
+               .name = "enable_mirror_tx",
+               .description = "Enable mirroring of TX packets",
+               .set = mt7530_set_mirror_tx_enable,
+               .get = mt7530_get_mirror_tx_enable,
+               .max = 1
+       }, {
+               .type = SWITCH_TYPE_INT,
+               .name = "mirror_monitor_port",
+               .description = "Mirror monitor port",
+               .set = mt7530_set_mirror_monitor_port,
+               .get = mt7530_get_mirror_monitor_port,
+               .max = MT7530_NUM_PORTS - 1
+       }, {
+               .type = SWITCH_TYPE_INT,
+               .name = "mirror_source_port",
+               .description = "Mirror source port",
+               .set = mt7530_set_mirror_source_port,
+               .get = mt7530_get_mirror_source_port,
+               .max = MT7530_NUM_PORTS - 1
        },
 };
 
@@ -840,6 +1040,20 @@ static const struct switch_attr mt7621_port[] = {
                .description = "Get MIB counters for port",
                .get = mt7621_sw_get_port_mib,
                .set = NULL,
+       }, {
+               .type = SWITCH_TYPE_INT,
+               .name = "enable_mirror_rx",
+               .description = "Enable mirroring of RX packets",
+               .set = mt7530_set_port_mirror_rx,
+               .get = mt7530_get_port_mirror_rx,
+               .max = 1,
+       }, {
+               .type = SWITCH_TYPE_INT,
+               .name = "enable_mirror_tx",
+               .description = "Enable mirroring of TX packets",
+               .set = mt7530_set_port_mirror_tx,
+               .get = mt7530_get_port_mirror_tx,
+               .max = 1,
        },
 };
 
@@ -861,6 +1075,20 @@ static const struct switch_attr mt7530_port[] = {
                .description = "Get MIB counters for port",
                .get = mt7530_sw_get_port_mib,
                .set = NULL,
+       }, {
+               .type = SWITCH_TYPE_INT,
+               .name = "enable_mirror_rx",
+               .description = "Enable mirroring of RX packets",
+               .set = mt7530_set_port_mirror_rx,
+               .get = mt7530_get_port_mirror_rx,
+               .max = 1,
+       }, {
+               .type = SWITCH_TYPE_INT,
+               .name = "enable_mirror_tx",
+               .description = "Enable mirroring of TX packets",
+               .set = mt7530_set_port_mirror_tx,
+               .get = mt7530_get_port_mirror_tx,
+               .max = 1,
        },
 };