@ -120,6 +120,12 @@ struct ar8xxx_priv {
u8 vlan_table [ AR8X16_MAX_VLANS ] ;
u8 vlan_tagged ;
u16 pvid [ AR8X16_MAX_PORTS ] ;
/* mirroring */
bool mirror_rx ;
bool mirror_tx ;
int source_port ;
int monitor_port ;
} ;
# define MIB_DESC(_s , _o, _n) \
@ -1457,6 +1463,98 @@ ar8xxx_sw_set_ports(struct switch_dev *dev, struct switch_val *val)
return 0 ;
}
static void
ar8327_set_mirror_regs ( struct ar8xxx_priv * priv )
{
int port ;
/* reset all mirror registers */
ar8xxx_rmw ( priv , AR8327_REG_FWD_CTRL0 ,
AR8327_FWD_CTRL0_MIRROR_PORT ,
( 0xF < < AR8327_FWD_CTRL0_MIRROR_PORT_S ) ) ;
for ( port = 0 ; port < AR8327_NUM_PORTS ; port + + ) {
ar8xxx_rmw ( priv , AR8327_REG_PORT_LOOKUP ( port ) ,
AR8327_PORT_LOOKUP_ING_MIRROR_EN ,
0 ) ;
ar8xxx_rmw ( priv , AR8327_REG_PORT_HOL_CTRL1 ( port ) ,
AR8327_PORT_HOL_CTRL1_EG_MIRROR_EN ,
0 ) ;
}
/* now enable mirroring if necessary */
if ( priv - > source_port > = AR8327_NUM_PORTS | |
priv - > monitor_port > = AR8327_NUM_PORTS | |
priv - > source_port = = priv - > monitor_port ) {
return ;
}
ar8xxx_rmw ( priv , AR8327_REG_FWD_CTRL0 ,
AR8327_FWD_CTRL0_MIRROR_PORT ,
( priv - > monitor_port < < AR8327_FWD_CTRL0_MIRROR_PORT_S ) ) ;
if ( priv - > mirror_rx )
ar8xxx_rmw ( priv , AR8327_REG_PORT_LOOKUP ( priv - > source_port ) ,
AR8327_PORT_LOOKUP_ING_MIRROR_EN ,
AR8327_PORT_LOOKUP_ING_MIRROR_EN ) ;
if ( priv - > mirror_tx )
ar8xxx_rmw ( priv , AR8327_REG_PORT_HOL_CTRL1 ( priv - > source_port ) ,
AR8327_PORT_HOL_CTRL1_EG_MIRROR_EN ,
AR8327_PORT_HOL_CTRL1_EG_MIRROR_EN ) ;
}
static void
ar8216_set_mirror_regs ( struct ar8xxx_priv * priv )
{
int port ;
/* reset all mirror registers */
ar8xxx_rmw ( priv , AR8216_REG_GLOBAL_CPUPORT ,
AR8216_GLOBAL_CPUPORT_MIRROR_PORT ,
( 0xF < < AR8216_GLOBAL_CPUPORT_MIRROR_PORT_S ) ) ;
for ( port = 0 ; port < AR8216_NUM_PORTS ; port + + ) {
ar8xxx_rmw ( priv , AR8216_REG_PORT_CTRL ( port ) ,
AR8216_PORT_CTRL_MIRROR_RX ,
0 ) ;
ar8xxx_rmw ( priv , AR8216_REG_PORT_CTRL ( port ) ,
AR8216_PORT_CTRL_MIRROR_TX ,
0 ) ;
}
/* now enable mirroring if necessary */
if ( priv - > source_port > = AR8216_NUM_PORTS | |
priv - > monitor_port > = AR8216_NUM_PORTS | |
priv - > source_port = = priv - > monitor_port ) {
return ;
}
ar8xxx_rmw ( priv , AR8216_REG_GLOBAL_CPUPORT ,
AR8216_GLOBAL_CPUPORT_MIRROR_PORT ,
( priv - > monitor_port < < AR8216_GLOBAL_CPUPORT_MIRROR_PORT_S ) ) ;
if ( priv - > mirror_rx )
ar8xxx_rmw ( priv , AR8216_REG_PORT_CTRL ( priv - > source_port ) ,
AR8216_PORT_CTRL_MIRROR_RX ,
AR8216_PORT_CTRL_MIRROR_RX ) ;
if ( priv - > mirror_tx )
ar8xxx_rmw ( priv , AR8216_REG_PORT_CTRL ( priv - > source_port ) ,
AR8216_PORT_CTRL_MIRROR_TX ,
AR8216_PORT_CTRL_MIRROR_TX ) ;
}
static void
ar8xxx_set_mirror_regs ( struct ar8xxx_priv * priv )
{
if ( chip_is_ar8327 ( priv ) ) {
ar8327_set_mirror_regs ( priv ) ;
} else {
ar8216_set_mirror_regs ( priv ) ;
}
}
static int
ar8xxx_sw_hw_apply ( struct switch_dev * dev )
{
@ -1520,6 +1618,9 @@ ar8xxx_sw_hw_apply(struct switch_dev *dev)
priv - > chip - > setup_port ( priv , i , egress , ingress , portmask [ i ] ,
pvid ) ;
}
ar8xxx_set_mirror_regs ( priv ) ;
mutex_unlock ( & priv - > reg_mutex ) ;
return 0 ;
}
@ -1541,7 +1642,13 @@ ar8xxx_sw_reset_switch(struct switch_dev *dev)
for ( i = 0 ; i < dev - > ports ; i + + )
priv - > chip - > init_port ( priv , i ) ;
priv - > mirror_rx = false ;
priv - > mirror_tx = false ;
priv - > source_port = 0 ;
priv - > monitor_port = 0 ;
priv - > chip - > init_globals ( priv ) ;
mutex_unlock ( & priv - > reg_mutex ) ;
return ar8xxx_sw_hw_apply ( dev ) ;
@ -1575,6 +1682,106 @@ unlock:
return ret ;
}
static int
ar8xxx_sw_set_mirror_rx_enable ( struct switch_dev * dev ,
const struct switch_attr * attr ,
struct switch_val * val )
{
struct ar8xxx_priv * priv = swdev_to_ar8xxx ( dev ) ;
mutex_lock ( & priv - > reg_mutex ) ;
priv - > mirror_rx = ! ! val - > value . i ;
ar8xxx_set_mirror_regs ( priv ) ;
mutex_unlock ( & priv - > reg_mutex ) ;
return 0 ;
}
static int
ar8xxx_sw_get_mirror_rx_enable ( struct switch_dev * dev ,
const struct switch_attr * attr ,
struct switch_val * val )
{
struct ar8xxx_priv * priv = swdev_to_ar8xxx ( dev ) ;
val - > value . i = priv - > mirror_rx ;
return 0 ;
}
static int
ar8xxx_sw_set_mirror_tx_enable ( struct switch_dev * dev ,
const struct switch_attr * attr ,
struct switch_val * val )
{
struct ar8xxx_priv * priv = swdev_to_ar8xxx ( dev ) ;
mutex_lock ( & priv - > reg_mutex ) ;
priv - > mirror_tx = ! ! val - > value . i ;
ar8xxx_set_mirror_regs ( priv ) ;
mutex_unlock ( & priv - > reg_mutex ) ;
return 0 ;
}
static int
ar8xxx_sw_get_mirror_tx_enable ( struct switch_dev * dev ,
const struct switch_attr * attr ,
struct switch_val * val )
{
struct ar8xxx_priv * priv = swdev_to_ar8xxx ( dev ) ;
val - > value . i = priv - > mirror_tx ;
return 0 ;
}
static int
ar8xxx_sw_set_mirror_monitor_port ( struct switch_dev * dev ,
const struct switch_attr * attr ,
struct switch_val * val )
{
struct ar8xxx_priv * priv = swdev_to_ar8xxx ( dev ) ;
mutex_lock ( & priv - > reg_mutex ) ;
priv - > monitor_port = val - > value . i ;
ar8xxx_set_mirror_regs ( priv ) ;
mutex_unlock ( & priv - > reg_mutex ) ;
return 0 ;
}
static int
ar8xxx_sw_get_mirror_monitor_port ( struct switch_dev * dev ,
const struct switch_attr * attr ,
struct switch_val * val )
{
struct ar8xxx_priv * priv = swdev_to_ar8xxx ( dev ) ;
val - > value . i = priv - > monitor_port ;
return 0 ;
}
static int
ar8xxx_sw_set_mirror_source_port ( struct switch_dev * dev ,
const struct switch_attr * attr ,
struct switch_val * val )
{
struct ar8xxx_priv * priv = swdev_to_ar8xxx ( dev ) ;
mutex_lock ( & priv - > reg_mutex ) ;
priv - > source_port = val - > value . i ;
ar8xxx_set_mirror_regs ( priv ) ;
mutex_unlock ( & priv - > reg_mutex ) ;
return 0 ;
}
static int
ar8xxx_sw_get_mirror_source_port ( struct switch_dev * dev ,
const struct switch_attr * attr ,
struct switch_val * val )
{
struct ar8xxx_priv * priv = swdev_to_ar8xxx ( dev ) ;
val - > value . i = priv - > source_port ;
return 0 ;
}
static int
ar8xxx_sw_set_port_reset_mib ( struct switch_dev * dev ,
const struct switch_attr * attr ,
@ -1668,7 +1875,87 @@ static struct switch_attr ar8xxx_sw_attr_globals[] = {
. description = " Reset all MIB counters " ,
. set = ar8xxx_sw_set_reset_mibs ,
} ,
{
. type = SWITCH_TYPE_INT ,
. name = " enable_mirror_rx " ,
. description = " Enable mirroring of RX packets " ,
. set = ar8xxx_sw_set_mirror_rx_enable ,
. get = ar8xxx_sw_get_mirror_rx_enable ,
. max = 1
} ,
{
. type = SWITCH_TYPE_INT ,
. name = " enable_mirror_tx " ,
. description = " Enable mirroring of TX packets " ,
. set = ar8xxx_sw_set_mirror_tx_enable ,
. get = ar8xxx_sw_get_mirror_tx_enable ,
. max = 1
} ,
{
. type = SWITCH_TYPE_INT ,
. name = " mirror_monitor_port " ,
. description = " Mirror monitor port " ,
. set = ar8xxx_sw_set_mirror_monitor_port ,
. get = ar8xxx_sw_get_mirror_monitor_port ,
. max = AR8216_NUM_PORTS - 1
} ,
{
. type = SWITCH_TYPE_INT ,
. name = " mirror_source_port " ,
. description = " Mirror source port " ,
. set = ar8xxx_sw_set_mirror_source_port ,
. get = ar8xxx_sw_get_mirror_source_port ,
. max = AR8216_NUM_PORTS - 1
} ,
} ;
static struct switch_attr ar8327_sw_attr_globals [ ] = {
{
. type = SWITCH_TYPE_INT ,
. name = " enable_vlan " ,
. description = " Enable VLAN mode " ,
. set = ar8xxx_sw_set_vlan ,
. get = ar8xxx_sw_get_vlan ,
. max = 1
} ,
{
. type = SWITCH_TYPE_NOVAL ,
. name = " reset_mibs " ,
. description = " Reset all MIB counters " ,
. set = ar8xxx_sw_set_reset_mibs ,
} ,
{
. type = SWITCH_TYPE_INT ,
. name = " enable_mirror_rx " ,
. description = " Enable mirroring of RX packets " ,
. set = ar8xxx_sw_set_mirror_rx_enable ,
. get = ar8xxx_sw_get_mirror_rx_enable ,
. max = 1
} ,
{
. type = SWITCH_TYPE_INT ,
. name = " enable_mirror_tx " ,
. description = " Enable mirroring of TX packets " ,
. set = ar8xxx_sw_set_mirror_tx_enable ,
. get = ar8xxx_sw_get_mirror_tx_enable ,
. max = 1
} ,
{
. type = SWITCH_TYPE_INT ,
. name = " mirror_monitor_port " ,
. description = " Mirror monitor port " ,
. set = ar8xxx_sw_set_mirror_monitor_port ,
. get = ar8xxx_sw_get_mirror_monitor_port ,
. max = AR8327_NUM_PORTS - 1
} ,
{
. type = SWITCH_TYPE_INT ,
. name = " mirror_source_port " ,
. description = " Mirror source port " ,
. set = ar8xxx_sw_set_mirror_source_port ,
. get = ar8xxx_sw_get_mirror_source_port ,
. max = AR8327_NUM_PORTS - 1
} ,
} ;
static struct switch_attr ar8xxx_sw_attr_port [ ] = {
@ -1720,6 +2007,28 @@ static const struct switch_dev_ops ar8xxx_sw_ops = {
. get_port_link = ar8xxx_sw_get_port_link ,
} ;
static const struct switch_dev_ops ar8327_sw_ops = {
. attr_global = {
. attr = ar8327_sw_attr_globals ,
. n_attr = ARRAY_SIZE ( ar8327_sw_attr_globals ) ,
} ,
. attr_port = {
. attr = ar8xxx_sw_attr_port ,
. n_attr = ARRAY_SIZE ( ar8xxx_sw_attr_port ) ,
} ,
. attr_vlan = {
. attr = ar8xxx_sw_attr_vlan ,
. n_attr = ARRAY_SIZE ( ar8xxx_sw_attr_vlan ) ,
} ,
. get_port_pvid = ar8xxx_sw_get_pvid ,
. set_port_pvid = ar8xxx_sw_set_pvid ,
. get_vlan_ports = ar8xxx_sw_get_ports ,
. set_vlan_ports = ar8xxx_sw_set_ports ,
. apply_config = ar8xxx_sw_hw_apply ,
. reset_switch = ar8xxx_sw_reset_switch ,
. get_port_link = ar8xxx_sw_get_port_link ,
} ;
static int
ar8xxx_id_chip ( struct ar8xxx_priv * priv )
{
@ -1900,6 +2209,7 @@ ar8xxx_probe_switch(struct ar8xxx_priv *priv)
swdev - > name = " Atheros AR8327 " ;
swdev - > vlans = AR8X16_MAX_VLANS ;
swdev - > ports = AR8327_NUM_PORTS ;
swdev - > ops = & ar8327_sw_ops ;
} else {
swdev - > name = " Atheros AR8216 " ;
swdev - > vlans = AR8216_NUM_VLANS ;