ramips: add MT7530 switch port-mirroring support
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>
This commit is contained in:
		 Deng Qingfang
					Deng Qingfang
				
			
				
					committed by
					
						 Chuanhong Guo
						Chuanhong Guo
					
				
			
			
				
	
			
			
			 Chuanhong Guo
						Chuanhong Guo
					
				
			
						parent
						
							a6da3f9ef7
						
					
				
				
					commit
					fd4804ce33
				
			| @@ -51,6 +51,11 @@ | |||||||
| #define MT7621_PORT_MIB_RXB_ID	37	/* RxByte */ | #define MT7621_PORT_MIB_RXB_ID	37	/* RxByte */ | ||||||
|  |  | ||||||
| /* registers */ | /* 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_VTCR		0x90 | ||||||
| #define REG_ESW_VLAN_VAWD1		0x94 | #define REG_ESW_VLAN_VAWD1		0x94 | ||||||
| #define REG_ESW_VLAN_VAWD2		0x98 | #define REG_ESW_VLAN_VAWD2		0x98 | ||||||
| @@ -72,6 +77,11 @@ enum { | |||||||
| #define REG_ESW_PORT_PVC(x)	(0x2010 | ((x) << 8)) | #define REG_ESW_PORT_PVC(x)	(0x2010 | ((x) << 8)) | ||||||
| #define REG_ESW_PORT_PPBV1(x)	(0x2014 | ((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 REG_HWTRAP		0x7804 | ||||||
|  |  | ||||||
| #define MIB_DESC(_s , _o, _n)   \ | #define MIB_DESC(_s , _o, _n)   \ | ||||||
| @@ -183,6 +193,8 @@ enum { | |||||||
|  |  | ||||||
| struct mt7530_port_entry { | struct mt7530_port_entry { | ||||||
| 	u16	pvid; | 	u16	pvid; | ||||||
|  | 	bool	mirror_rx; | ||||||
|  | 	bool	mirror_tx; | ||||||
| }; | }; | ||||||
|  |  | ||||||
| struct mt7530_vlan_entry { | struct mt7530_vlan_entry { | ||||||
| @@ -196,6 +208,8 @@ struct mt7530_priv { | |||||||
| 	struct mii_bus		*bus; | 	struct mii_bus		*bus; | ||||||
| 	struct switch_dev	swdev; | 	struct switch_dev	swdev; | ||||||
|  |  | ||||||
|  | 	u8			mirror_src_port; | ||||||
|  | 	u8			mirror_dest_port; | ||||||
| 	bool			global_vlan_enable; | 	bool			global_vlan_enable; | ||||||
| 	struct mt7530_vlan_entry	vlan_entries[MT7530_NUM_VLANS]; | 	struct mt7530_vlan_entry	vlan_entries[MT7530_NUM_VLANS]; | ||||||
| 	struct mt7530_port_entry	port_entries[MT7530_NUM_PORTS]; | 	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; | 	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 | static void | ||||||
| mt7530_write_vlan_entry(struct mt7530_priv *priv, int vlan, u16 vid, | mt7530_write_vlan_entry(struct mt7530_priv *priv, int vlan, u16 vid, | ||||||
| 	                    u8 ports, u8 etags) | 	                    u8 ports, u8 etags) | ||||||
| @@ -558,6 +704,7 @@ mt7530_apply_config(struct switch_dev *dev) | |||||||
| 	int i, j; | 	int i, j; | ||||||
| 	u8 tag_ports; | 	u8 tag_ports; | ||||||
| 	u8 untag_ports; | 	u8 untag_ports; | ||||||
|  | 	bool is_mirror = false; | ||||||
|  |  | ||||||
| 	if (!priv->global_vlan_enable) { | 	if (!priv->global_vlan_enable) { | ||||||
| 		for (i = 0; i < MT7530_NUM_PORTS; i++) | 		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); | 		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; | 	return 0; | ||||||
| } | } | ||||||
|  |  | ||||||
| @@ -830,6 +1002,34 @@ static const struct switch_attr mt7530_global[] = { | |||||||
| 		.description = "Get MIB counters for switch", | 		.description = "Get MIB counters for switch", | ||||||
| 		.get = mt7530_sw_get_mib, | 		.get = mt7530_sw_get_mib, | ||||||
| 		.set = NULL, | 		.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", | 		.description = "Get MIB counters for port", | ||||||
| 		.get = mt7621_sw_get_port_mib, | 		.get = mt7621_sw_get_port_mib, | ||||||
| 		.set = NULL, | 		.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", | 		.description = "Get MIB counters for port", | ||||||
| 		.get = mt7530_sw_get_port_mib, | 		.get = mt7530_sw_get_port_mib, | ||||||
| 		.set = NULL, | 		.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, | ||||||
| 	}, | 	}, | ||||||
| }; | }; | ||||||
|  |  | ||||||
|   | |||||||
		Reference in New Issue
	
	Block a user