[OpenWrt-Devel,ar71xx] ag71xx: add support for port mirroring

Message ID 1493242553-1595-1-git-send-email-milan.krstic@gmail.com
State New
Headers show

Commit Message

Milan Krstic April 26, 2017, 9:35 p.m.
This exposes hardware port mirroring in ag71xx driver (e.g. TL-WR841ND) via swconfig API.

Signed-off-by: Milan Krstic <milan.krstic@gmail.com>
---
 .../net/ethernet/atheros/ag71xx/ag71xx_ar7240.c    | 154 +++++++++++++++++++++
 1 file changed, 154 insertions(+)

Patch

diff --git a/target/linux/ar71xx/files/drivers/net/ethernet/atheros/ag71xx/ag71xx_ar7240.c b/target/linux/ar71xx/files/drivers/net/ethernet/atheros/ag71xx/ag71xx_ar7240.c
index c5aed0d..da9c0dd 100644
--- a/target/linux/ar71xx/files/drivers/net/ethernet/atheros/ag71xx/ag71xx_ar7240.c
+++ b/target/linux/ar71xx/files/drivers/net/ethernet/atheros/ag71xx/ag71xx_ar7240.c
@@ -77,6 +77,7 @@ 
 
 #define AR7240_REG_CPU_PORT		0x78
 #define AR7240_MIRROR_PORT_S		4
+#define AR7240_MIRROR_PORT_M		BITM(4)
 #define AR7240_CPU_PORT_EN		BIT(8)
 
 #define AR7240_REG_MIB_FUNCTION0	0x80
@@ -1013,6 +1014,134 @@  ar7240_get_port_stats(struct switch_dev *dev, int port,
 	return 0;
 }
 
+static int
+ar7240_set_mirror_monitor_port(struct switch_dev *dev,
+			       const struct switch_attr *attr,
+			       struct switch_val *val)
+{
+	struct ar7240sw *as = sw_to_ar7240(dev);
+	struct mii_bus *mii = as->mii_bus;
+
+	int port = val->value.i;
+
+	if (port > 15)
+		return -EINVAL;
+
+	ar7240sw_reg_rmw(mii, AR7240_REG_CPU_PORT,
+			AR7240_MIRROR_PORT_M << AR7240_MIRROR_PORT_S,
+			port << AR7240_MIRROR_PORT_S);
+
+	return 0;
+}
+
+static int
+ar7240_get_mirror_monitor_port(struct switch_dev *dev,
+			       const struct switch_attr *attr,
+			       struct switch_val *val)
+{
+	struct ar7240sw *as = sw_to_ar7240(dev);
+	struct mii_bus *mii = as->mii_bus;
+
+	u32 ret;
+
+	ret = ar7240sw_reg_read(mii, AR7240_REG_CPU_PORT);
+	val->value.i = (ret >> AR7240_MIRROR_PORT_S) & AR7240_MIRROR_PORT_M;
+
+	return 0;
+}
+
+static int
+ar7240_set_mirror_rx(struct switch_dev *dev, const struct switch_attr *attr,
+		     struct switch_val *val)
+{
+	struct ar7240sw *as = sw_to_ar7240(dev);
+	struct mii_bus *mii = as->mii_bus;
+
+	int port = val->port_vlan;
+
+	if (port >= dev->ports)
+		return -EINVAL;
+
+	if (val && val->value.i == 1)
+		ar7240sw_reg_set(mii, AR7240_REG_PORT_CTRL(port),
+			AR7240_PORT_CTRL_MIRROR_RX);
+	else
+		ar7240sw_reg_rmw(mii, AR7240_REG_PORT_CTRL(port),
+			AR7240_PORT_CTRL_MIRROR_RX, 0);
+
+	return 0;
+}
+
+static int
+ar7240_get_mirror_rx(struct switch_dev *dev, const struct switch_attr *attr,
+		     struct switch_val *val)
+{
+	struct ar7240sw *as = sw_to_ar7240(dev);
+	struct mii_bus *mii = as->mii_bus;
+
+	u32 ctrl;
+
+	int port = val->port_vlan;
+
+	if (port >= dev->ports)
+		return -EINVAL;
+
+	ctrl = ar7240sw_reg_read(mii, AR7240_REG_PORT_CTRL(port));
+
+	if ((ctrl & AR7240_PORT_CTRL_MIRROR_RX) == AR7240_PORT_CTRL_MIRROR_RX)
+		val->value.i = 1;
+	else
+		val->value.i = 0;
+
+	return 0;
+}
+
+static int
+ar7240_set_mirror_tx(struct switch_dev *dev, const struct switch_attr *attr,
+		     struct switch_val *val)
+{
+	struct ar7240sw *as = sw_to_ar7240(dev);
+	struct mii_bus *mii = as->mii_bus;
+
+	int port = val->port_vlan;
+
+	if (port >= dev->ports)
+		return -EINVAL;
+
+	if (val && val->value.i == 1)
+		ar7240sw_reg_set(mii, AR7240_REG_PORT_CTRL(port),
+			AR7240_PORT_CTRL_MIRROR_TX);
+	else
+		ar7240sw_reg_rmw(mii, AR7240_REG_PORT_CTRL(port),
+			AR7240_PORT_CTRL_MIRROR_TX, 0);
+
+	return 0;
+}
+
+static int
+ar7240_get_mirror_tx(struct switch_dev *dev, const struct switch_attr *attr,
+		     struct switch_val *val)
+{
+	struct ar7240sw *as = sw_to_ar7240(dev);
+	struct mii_bus *mii = as->mii_bus;
+
+	u32 ctrl;
+
+	int port = val->port_vlan;
+
+	if (port >= dev->ports)
+		return -EINVAL;
+
+	ctrl = ar7240sw_reg_read(mii, AR7240_REG_PORT_CTRL(port));
+
+	if ((ctrl & AR7240_PORT_CTRL_MIRROR_TX) == AR7240_PORT_CTRL_MIRROR_TX)
+		val->value.i = 1;
+	else
+		val->value.i = 0;
+
+	return 0;
+}
+
 static struct switch_attr ar7240_globals[] = {
 	{
 		.type = SWITCH_TYPE_INT,
@@ -1022,9 +1151,34 @@  static struct switch_attr ar7240_globals[] = {
 		.get = ar7240_get_vlan,
 		.max = 1
 	},
+	{
+		.type = SWITCH_TYPE_INT,
+		.name = "mirror_monitor_port",
+		.description = "Mirror monitor port",
+		.set = ar7240_set_mirror_monitor_port,
+		.get = ar7240_get_mirror_monitor_port,
+		.max = 15
+	},
 };
 
 static struct switch_attr ar7240_port[] = {
+	{
+		.type = SWITCH_TYPE_INT,
+		.name = "enable_mirror_rx",
+		.description = "Enable mirroring of RX packets",
+		.set = ar7240_set_mirror_rx,
+		.get = ar7240_get_mirror_rx,
+		.max = 1
+	},
+	{
+
+		.type = SWITCH_TYPE_INT,
+		.name = "enable_mirror_tx",
+		.description = "Enable mirroring of TX packets",
+		.set = ar7240_set_mirror_tx,
+		.get = ar7240_get_mirror_tx,
+		.max = 1
+	},
 };
 
 static struct switch_attr ar7240_vlan[] = {