Browse Source

ramips: add MT7530 switch port-mirroring support

Compile & run tested on MT7620, MT7621

Signed-off-by: Deng Qingfang <[email protected]>
[Tested on Phicomm PSG1218 rev.A, MediaTek MT7620A ver:2 eco:6]
Tested-by: MingHao Chen <[email protected]>
Deng Qingfang 6 years ago
parent
commit
fd4804ce33
1 changed files with 228 additions and 0 deletions
  1. 228 0
      target/linux/ramips/files-4.14/drivers/net/ethernet/mediatek/mt7530.c

+ 228 - 0
target/linux/ramips/files-4.14/drivers/net/ethernet/mediatek/mt7530.c

@@ -51,6 +51,11 @@
 #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,
 	},
 };