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 2018-12-16 23:49:07 +08:00 committed by Chuanhong Guo
parent a6da3f9ef7
commit fd4804ce33
1 changed files with 228 additions and 0 deletions

View File

@ -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,
},
};