diff options
Diffstat (limited to 'drivers/net/ethernet/mscc')
| -rw-r--r-- | drivers/net/ethernet/mscc/Kconfig | 1 | ||||
| -rw-r--r-- | drivers/net/ethernet/mscc/Makefile | 1 | ||||
| -rw-r--r-- | drivers/net/ethernet/mscc/ocelot.c | 72 | ||||
| -rw-r--r-- | drivers/net/ethernet/mscc/ocelot.h | 2 | ||||
| -rw-r--r-- | drivers/net/ethernet/mscc/ocelot_devlink.c | 31 | ||||
| -rw-r--r-- | drivers/net/ethernet/mscc/ocelot_flower.c | 24 | ||||
| -rw-r--r-- | drivers/net/ethernet/mscc/ocelot_mm.c | 215 | ||||
| -rw-r--r-- | drivers/net/ethernet/mscc/ocelot_net.c | 12 | ||||
| -rw-r--r-- | drivers/net/ethernet/mscc/ocelot_ptp.c | 8 | ||||
| -rw-r--r-- | drivers/net/ethernet/mscc/ocelot_stats.c | 554 | ||||
| -rw-r--r-- | drivers/net/ethernet/mscc/ocelot_vsc7514.c | 204 | ||||
| -rw-r--r-- | drivers/net/ethernet/mscc/vsc7514_regs.c | 159 | 
12 files changed, 997 insertions, 286 deletions
diff --git a/drivers/net/ethernet/mscc/Kconfig b/drivers/net/ethernet/mscc/Kconfig index 8dd8c7f425d2..81e605691bb8 100644 --- a/drivers/net/ethernet/mscc/Kconfig +++ b/drivers/net/ethernet/mscc/Kconfig @@ -13,6 +13,7 @@ if NET_VENDOR_MICROSEMI  # Users should depend on NET_SWITCHDEV, HAS_IOMEM, BRIDGE  config MSCC_OCELOT_SWITCH_LIB +	depends on PTP_1588_CLOCK_OPTIONAL  	select NET_DEVLINK  	select REGMAP_MMIO  	select PACKING diff --git a/drivers/net/ethernet/mscc/Makefile b/drivers/net/ethernet/mscc/Makefile index 5d435a565d4c..16987b72dfc0 100644 --- a/drivers/net/ethernet/mscc/Makefile +++ b/drivers/net/ethernet/mscc/Makefile @@ -5,6 +5,7 @@ mscc_ocelot_switch_lib-y := \  	ocelot_devlink.o \  	ocelot_flower.o \  	ocelot_io.o \ +	ocelot_mm.o \  	ocelot_police.o \  	ocelot_ptp.o \  	ocelot_stats.o \ diff --git a/drivers/net/ethernet/mscc/ocelot.c b/drivers/net/ethernet/mscc/ocelot.c index 13b14110a060..08acb7b89086 100644 --- a/drivers/net/ethernet/mscc/ocelot.c +++ b/drivers/net/ethernet/mscc/ocelot.c @@ -6,12 +6,16 @@   */  #include <linux/dsa/ocelot.h>  #include <linux/if_bridge.h> +#include <linux/iopoll.h>  #include <soc/mscc/ocelot_vcap.h>  #include "ocelot.h"  #include "ocelot_vcap.h" -#define TABLE_UPDATE_SLEEP_US 10 -#define TABLE_UPDATE_TIMEOUT_US 100000 +#define TABLE_UPDATE_SLEEP_US	10 +#define TABLE_UPDATE_TIMEOUT_US	100000 +#define MEM_INIT_SLEEP_US	1000 +#define MEM_INIT_TIMEOUT_US	100000 +  #define OCELOT_RSV_VLAN_RANGE_START 4000  struct ocelot_mact_entry { @@ -872,10 +876,8 @@ void ocelot_phylink_mac_link_up(struct ocelot *ocelot, int port,  		return;  	} -	/* Handle RX pause in all cases, with 2500base-X this is used for rate -	 * adaptation. -	 */ -	mac_fc_cfg |= SYS_MAC_FC_CFG_RX_FC_ENA; +	if (rx_pause) +		mac_fc_cfg |= SYS_MAC_FC_CFG_RX_FC_ENA;  	if (tx_pause)  		mac_fc_cfg |= SYS_MAC_FC_CFG_TX_FC_ENA | @@ -2715,6 +2717,46 @@ static void ocelot_detect_features(struct ocelot *ocelot)  	ocelot->num_frame_refs = QSYS_MMGT_EQ_CTRL_FP_FREE_CNT(eq_ctrl);  } +static int ocelot_mem_init_status(struct ocelot *ocelot) +{ +	unsigned int val; +	int err; + +	err = regmap_field_read(ocelot->regfields[SYS_RESET_CFG_MEM_INIT], +				&val); + +	return err ?: val; +} + +int ocelot_reset(struct ocelot *ocelot) +{ +	int err; +	u32 val; + +	err = regmap_field_write(ocelot->regfields[SYS_RESET_CFG_MEM_INIT], 1); +	if (err) +		return err; + +	err = regmap_field_write(ocelot->regfields[SYS_RESET_CFG_MEM_ENA], 1); +	if (err) +		return err; + +	/* MEM_INIT is a self-clearing bit. Wait for it to be cleared (should be +	 * 100us) before enabling the switch core. +	 */ +	err = readx_poll_timeout(ocelot_mem_init_status, ocelot, val, !val, +				 MEM_INIT_SLEEP_US, MEM_INIT_TIMEOUT_US); +	if (err) +		return err; + +	err = regmap_field_write(ocelot->regfields[SYS_RESET_CFG_MEM_ENA], 1); +	if (err) +		return err; + +	return regmap_field_write(ocelot->regfields[SYS_RESET_CFG_CORE_ENA], 1); +} +EXPORT_SYMBOL(ocelot_reset); +  int ocelot_init(struct ocelot *ocelot)  {  	int i, ret; @@ -2740,10 +2782,8 @@ int ocelot_init(struct ocelot *ocelot)  		return -ENOMEM;  	ret = ocelot_stats_init(ocelot); -	if (ret) { -		destroy_workqueue(ocelot->owq); -		return ret; -	} +	if (ret) +		goto err_stats_init;  	INIT_LIST_HEAD(&ocelot->multicast);  	INIT_LIST_HEAD(&ocelot->pgids); @@ -2758,6 +2798,12 @@ int ocelot_init(struct ocelot *ocelot)  	if (ocelot->ops->psfp_init)  		ocelot->ops->psfp_init(ocelot); +	if (ocelot->mm_supported) { +		ret = ocelot_mm_init(ocelot); +		if (ret) +			goto err_mm_init; +	} +  	for (port = 0; port < ocelot->num_phys_ports; port++) {  		/* Clear all counters (5 groups) */  		ocelot_write(ocelot, SYS_STAT_CFG_STAT_VIEW(port) | @@ -2855,6 +2901,12 @@ int ocelot_init(struct ocelot *ocelot)  				 ANA_CPUQ_8021_CFG, i);  	return 0; + +err_mm_init: +	ocelot_stats_deinit(ocelot); +err_stats_init: +	destroy_workqueue(ocelot->owq); +	return ret;  }  EXPORT_SYMBOL(ocelot_init); diff --git a/drivers/net/ethernet/mscc/ocelot.h b/drivers/net/ethernet/mscc/ocelot.h index 70dbd9c4e512..e9a0179448bf 100644 --- a/drivers/net/ethernet/mscc/ocelot.h +++ b/drivers/net/ethernet/mscc/ocelot.h @@ -109,6 +109,8 @@ void ocelot_mirror_put(struct ocelot *ocelot);  int ocelot_stats_init(struct ocelot *ocelot);  void ocelot_stats_deinit(struct ocelot *ocelot); +int ocelot_mm_init(struct ocelot *ocelot); +  extern struct notifier_block ocelot_netdevice_nb;  extern struct notifier_block ocelot_switchdev_nb;  extern struct notifier_block ocelot_switchdev_blocking_nb; diff --git a/drivers/net/ethernet/mscc/ocelot_devlink.c b/drivers/net/ethernet/mscc/ocelot_devlink.c index b8737efd2a85..d9ea75a14f2f 100644 --- a/drivers/net/ethernet/mscc/ocelot_devlink.c +++ b/drivers/net/ethernet/mscc/ocelot_devlink.c @@ -487,6 +487,37 @@ static void ocelot_watermark_init(struct ocelot *ocelot)  	ocelot_setup_sharing_watermarks(ocelot);  } +/* Watermark encode + * Bit 8:   Unit; 0:1, 1:16 + * Bit 7-0: Value to be multiplied with unit + */ +u16 ocelot_wm_enc(u16 value) +{ +	WARN_ON(value >= 16 * BIT(8)); + +	if (value >= BIT(8)) +		return BIT(8) | (value / 16); + +	return value; +} +EXPORT_SYMBOL(ocelot_wm_enc); + +u16 ocelot_wm_dec(u16 wm) +{ +	if (wm & BIT(8)) +		return (wm & GENMASK(7, 0)) * 16; + +	return wm; +} +EXPORT_SYMBOL(ocelot_wm_dec); + +void ocelot_wm_stat(u32 val, u32 *inuse, u32 *maxuse) +{ +	*inuse = (val & GENMASK(23, 12)) >> 12; +	*maxuse = val & GENMASK(11, 0); +} +EXPORT_SYMBOL(ocelot_wm_stat); +  /* Pool size and type are fixed up at runtime. Keeping this structure to   * look up the cell size multipliers.   */ diff --git a/drivers/net/ethernet/mscc/ocelot_flower.c b/drivers/net/ethernet/mscc/ocelot_flower.c index 7c0897e779dc..ee052404eb55 100644 --- a/drivers/net/ethernet/mscc/ocelot_flower.c +++ b/drivers/net/ethernet/mscc/ocelot_flower.c @@ -605,6 +605,18 @@ ocelot_flower_parse_key(struct ocelot *ocelot, int port, bool ingress,  		flow_rule_match_control(rule, &match);  	} +	if (flow_rule_match_key(rule, FLOW_DISSECTOR_KEY_VLAN)) { +		struct flow_match_vlan match; + +		flow_rule_match_vlan(rule, &match); +		filter->key_type = OCELOT_VCAP_KEY_ANY; +		filter->vlan.vid.value = match.key->vlan_id; +		filter->vlan.vid.mask = match.mask->vlan_id; +		filter->vlan.pcp.value[0] = match.key->vlan_priority; +		filter->vlan.pcp.mask[0] = match.mask->vlan_priority; +		match_protocol = false; +	} +  	if (flow_rule_match_key(rule, FLOW_DISSECTOR_KEY_ETH_ADDRS)) {  		struct flow_match_eth_addrs match; @@ -737,18 +749,6 @@ ocelot_flower_parse_key(struct ocelot *ocelot, int port, bool ingress,  		match_protocol = false;  	} -	if (flow_rule_match_key(rule, FLOW_DISSECTOR_KEY_VLAN)) { -		struct flow_match_vlan match; - -		flow_rule_match_vlan(rule, &match); -		filter->key_type = OCELOT_VCAP_KEY_ANY; -		filter->vlan.vid.value = match.key->vlan_id; -		filter->vlan.vid.mask = match.mask->vlan_id; -		filter->vlan.pcp.value[0] = match.key->vlan_priority; -		filter->vlan.pcp.mask[0] = match.mask->vlan_priority; -		match_protocol = false; -	} -  finished_key_parsing:  	if (match_protocol && proto != ETH_P_ALL) {  		if (filter->block_id == VCAP_ES0) { diff --git a/drivers/net/ethernet/mscc/ocelot_mm.c b/drivers/net/ethernet/mscc/ocelot_mm.c new file mode 100644 index 000000000000..0a8f21ae23f0 --- /dev/null +++ b/drivers/net/ethernet/mscc/ocelot_mm.c @@ -0,0 +1,215 @@ +// SPDX-License-Identifier: (GPL-2.0 OR MIT) +/* + * Hardware library for MAC Merge Layer and Frame Preemption on TSN-capable + * switches (VSC9959) + * + * Copyright 2022-2023 NXP + */ +#include <linux/ethtool.h> +#include <soc/mscc/ocelot.h> +#include <soc/mscc/ocelot_dev.h> +#include <soc/mscc/ocelot_qsys.h> + +#include "ocelot.h" + +static const char * +mm_verify_state_to_string(enum ethtool_mm_verify_status state) +{ +	switch (state) { +	case ETHTOOL_MM_VERIFY_STATUS_INITIAL: +		return "INITIAL"; +	case ETHTOOL_MM_VERIFY_STATUS_VERIFYING: +		return "VERIFYING"; +	case ETHTOOL_MM_VERIFY_STATUS_SUCCEEDED: +		return "SUCCEEDED"; +	case ETHTOOL_MM_VERIFY_STATUS_FAILED: +		return "FAILED"; +	case ETHTOOL_MM_VERIFY_STATUS_DISABLED: +		return "DISABLED"; +	default: +		return "UNKNOWN"; +	} +} + +static enum ethtool_mm_verify_status ocelot_mm_verify_status(u32 val) +{ +	switch (DEV_MM_STAT_MM_STATUS_PRMPT_VERIFY_STATE_X(val)) { +	case 0: +		return ETHTOOL_MM_VERIFY_STATUS_INITIAL; +	case 1: +		return ETHTOOL_MM_VERIFY_STATUS_VERIFYING; +	case 2: +		return ETHTOOL_MM_VERIFY_STATUS_SUCCEEDED; +	case 3: +		return ETHTOOL_MM_VERIFY_STATUS_FAILED; +	case 4: +		return ETHTOOL_MM_VERIFY_STATUS_DISABLED; +	default: +		return ETHTOOL_MM_VERIFY_STATUS_UNKNOWN; +	} +} + +void ocelot_port_mm_irq(struct ocelot *ocelot, int port) +{ +	struct ocelot_port *ocelot_port = ocelot->ports[port]; +	struct ocelot_mm_state *mm = &ocelot->mm[port]; +	enum ethtool_mm_verify_status verify_status; +	u32 val; + +	mutex_lock(&mm->lock); + +	val = ocelot_port_readl(ocelot_port, DEV_MM_STATUS); + +	verify_status = ocelot_mm_verify_status(val); +	if (mm->verify_status != verify_status) { +		dev_dbg(ocelot->dev, +			"Port %d MAC Merge verification state %s\n", +			port, mm_verify_state_to_string(verify_status)); +		mm->verify_status = verify_status; +	} + +	if (val & DEV_MM_STAT_MM_STATUS_PRMPT_ACTIVE_STICKY) { +		mm->tx_active = !!(val & DEV_MM_STAT_MM_STATUS_PRMPT_ACTIVE_STATUS); + +		dev_dbg(ocelot->dev, "Port %d TX preemption %s\n", +			port, mm->tx_active ? "active" : "inactive"); +	} + +	if (val & DEV_MM_STAT_MM_STATUS_UNEXP_RX_PFRM_STICKY) { +		dev_err(ocelot->dev, +			"Unexpected P-frame received on port %d while verification was unsuccessful or not yet verified\n", +			port); +	} + +	if (val & DEV_MM_STAT_MM_STATUS_UNEXP_TX_PFRM_STICKY) { +		dev_err(ocelot->dev, +			"Unexpected P-frame requested to be transmitted on port %d while verification was unsuccessful or not yet verified, or MM_TX_ENA=0\n", +			port); +	} + +	ocelot_port_writel(ocelot_port, val, DEV_MM_STATUS); + +	mutex_unlock(&mm->lock); +} +EXPORT_SYMBOL_GPL(ocelot_port_mm_irq); + +int ocelot_port_set_mm(struct ocelot *ocelot, int port, +		       struct ethtool_mm_cfg *cfg, +		       struct netlink_ext_ack *extack) +{ +	struct ocelot_port *ocelot_port = ocelot->ports[port]; +	u32 mm_enable = 0, verify_disable = 0, add_frag_size; +	struct ocelot_mm_state *mm; +	int err; + +	if (!ocelot->mm_supported) +		return -EOPNOTSUPP; + +	mm = &ocelot->mm[port]; + +	err = ethtool_mm_frag_size_min_to_add(cfg->tx_min_frag_size, +					      &add_frag_size, extack); +	if (err) +		return err; + +	if (cfg->pmac_enabled) +		mm_enable |= DEV_MM_CONFIG_ENABLE_CONFIG_MM_RX_ENA; + +	if (cfg->tx_enabled) +		mm_enable |= DEV_MM_CONFIG_ENABLE_CONFIG_MM_TX_ENA; + +	if (!cfg->verify_enabled) +		verify_disable = DEV_MM_CONFIG_VERIF_CONFIG_PRM_VERIFY_DIS; + +	mutex_lock(&mm->lock); + +	ocelot_port_rmwl(ocelot_port, mm_enable, +			 DEV_MM_CONFIG_ENABLE_CONFIG_MM_TX_ENA | +			 DEV_MM_CONFIG_ENABLE_CONFIG_MM_RX_ENA, +			 DEV_MM_ENABLE_CONFIG); + +	ocelot_port_rmwl(ocelot_port, verify_disable | +			 DEV_MM_CONFIG_VERIF_CONFIG_PRM_VERIFY_TIME(cfg->verify_time), +			 DEV_MM_CONFIG_VERIF_CONFIG_PRM_VERIFY_DIS | +			 DEV_MM_CONFIG_VERIF_CONFIG_PRM_VERIFY_TIME_M, +			 DEV_MM_VERIF_CONFIG); + +	ocelot_rmw_rix(ocelot, +		       QSYS_PREEMPTION_CFG_MM_ADD_FRAG_SIZE(add_frag_size), +		       QSYS_PREEMPTION_CFG_MM_ADD_FRAG_SIZE_M, +		       QSYS_PREEMPTION_CFG, +		       port); + +	mutex_unlock(&mm->lock); + +	return 0; +} +EXPORT_SYMBOL_GPL(ocelot_port_set_mm); + +int ocelot_port_get_mm(struct ocelot *ocelot, int port, +		       struct ethtool_mm_state *state) +{ +	struct ocelot_port *ocelot_port = ocelot->ports[port]; +	struct ocelot_mm_state *mm; +	u32 val, add_frag_size; + +	if (!ocelot->mm_supported) +		return -EOPNOTSUPP; + +	mm = &ocelot->mm[port]; + +	mutex_lock(&mm->lock); + +	val = ocelot_port_readl(ocelot_port, DEV_MM_ENABLE_CONFIG); +	state->pmac_enabled = !!(val & DEV_MM_CONFIG_ENABLE_CONFIG_MM_RX_ENA); +	state->tx_enabled = !!(val & DEV_MM_CONFIG_ENABLE_CONFIG_MM_TX_ENA); + +	val = ocelot_port_readl(ocelot_port, DEV_MM_VERIF_CONFIG); +	state->verify_enabled = !(val & DEV_MM_CONFIG_VERIF_CONFIG_PRM_VERIFY_DIS); +	state->verify_time = DEV_MM_CONFIG_VERIF_CONFIG_PRM_VERIFY_TIME_X(val); +	state->max_verify_time = 128; + +	val = ocelot_read_rix(ocelot, QSYS_PREEMPTION_CFG, port); +	add_frag_size = QSYS_PREEMPTION_CFG_MM_ADD_FRAG_SIZE_X(val); +	state->tx_min_frag_size = ethtool_mm_frag_size_add_to_min(add_frag_size); +	state->rx_min_frag_size = ETH_ZLEN; + +	state->verify_status = mm->verify_status; +	state->tx_active = mm->tx_active; + +	mutex_unlock(&mm->lock); + +	return 0; +} +EXPORT_SYMBOL_GPL(ocelot_port_get_mm); + +int ocelot_mm_init(struct ocelot *ocelot) +{ +	struct ocelot_port *ocelot_port; +	struct ocelot_mm_state *mm; +	int port; + +	if (!ocelot->mm_supported) +		return 0; + +	ocelot->mm = devm_kcalloc(ocelot->dev, ocelot->num_phys_ports, +				  sizeof(*ocelot->mm), GFP_KERNEL); +	if (!ocelot->mm) +		return -ENOMEM; + +	for (port = 0; port < ocelot->num_phys_ports; port++) { +		u32 val; + +		mm = &ocelot->mm[port]; +		mutex_init(&mm->lock); +		ocelot_port = ocelot->ports[port]; + +		/* Update initial status variable for the +		 * verification state machine +		 */ +		val = ocelot_port_readl(ocelot_port, DEV_MM_STATUS); +		mm->verify_status = ocelot_mm_verify_status(val); +	} + +	return 0; +} diff --git a/drivers/net/ethernet/mscc/ocelot_net.c b/drivers/net/ethernet/mscc/ocelot_net.c index 50858cc10fef..ca4bde861397 100644 --- a/drivers/net/ethernet/mscc/ocelot_net.c +++ b/drivers/net/ethernet/mscc/ocelot_net.c @@ -194,15 +194,6 @@ void ocelot_port_devlink_teardown(struct ocelot *ocelot, int port)  	devlink_port_unregister(dlp);  } -static struct devlink_port *ocelot_get_devlink_port(struct net_device *dev) -{ -	struct ocelot_port_private *priv = netdev_priv(dev); -	struct ocelot *ocelot = priv->port.ocelot; -	int port = priv->port.index; - -	return &ocelot->devlink_ports[port]; -} -  int ocelot_setup_tc_cls_flower(struct ocelot_port_private *priv,  			       struct flow_cls_offload *f,  			       bool ingress) @@ -925,7 +916,6 @@ static const struct net_device_ops ocelot_port_netdev_ops = {  	.ndo_set_features		= ocelot_set_features,  	.ndo_setup_tc			= ocelot_setup_tc,  	.ndo_eth_ioctl			= ocelot_ioctl, -	.ndo_get_devlink_port		= ocelot_get_devlink_port,  };  struct net_device *ocelot_port_to_netdev(struct ocelot *ocelot, int port) @@ -1737,7 +1727,6 @@ static void vsc7514_phylink_mac_link_up(struct phylink_config *config,  }  static const struct phylink_mac_ops ocelot_phylink_ops = { -	.validate		= phylink_generic_validate,  	.mac_config		= vsc7514_phylink_mac_config,  	.mac_link_down		= vsc7514_phylink_mac_link_down,  	.mac_link_up		= vsc7514_phylink_mac_link_up, @@ -1873,6 +1862,7 @@ int ocelot_probe_port(struct ocelot *ocelot, int port, struct regmap *target,  	if (ocelot->fdma)  		ocelot_fdma_netdev_init(ocelot, dev); +	SET_NETDEV_DEVLINK_PORT(dev, &ocelot->devlink_ports[port]);  	err = register_netdev(dev);  	if (err) {  		dev_err(ocelot->dev, "register_netdev failed\n"); diff --git a/drivers/net/ethernet/mscc/ocelot_ptp.c b/drivers/net/ethernet/mscc/ocelot_ptp.c index 1a82f10c8853..2180ae94c744 100644 --- a/drivers/net/ethernet/mscc/ocelot_ptp.c +++ b/drivers/net/ethernet/mscc/ocelot_ptp.c @@ -335,8 +335,8 @@ static void  ocelot_populate_ipv6_ptp_event_trap_key(struct ocelot_vcap_filter *trap)  {  	trap->key_type = OCELOT_VCAP_KEY_IPV6; -	trap->key.ipv4.proto.value[0] = IPPROTO_UDP; -	trap->key.ipv4.proto.mask[0] = 0xff; +	trap->key.ipv6.proto.value[0] = IPPROTO_UDP; +	trap->key.ipv6.proto.mask[0] = 0xff;  	trap->key.ipv6.dport.value = PTP_EV_PORT;  	trap->key.ipv6.dport.mask = 0xffff;  } @@ -355,8 +355,8 @@ static void  ocelot_populate_ipv6_ptp_general_trap_key(struct ocelot_vcap_filter *trap)  {  	trap->key_type = OCELOT_VCAP_KEY_IPV6; -	trap->key.ipv4.proto.value[0] = IPPROTO_UDP; -	trap->key.ipv4.proto.mask[0] = 0xff; +	trap->key.ipv6.proto.value[0] = IPPROTO_UDP; +	trap->key.ipv6.proto.mask[0] = 0xff;  	trap->key.ipv6.dport.value = PTP_GEN_PORT;  	trap->key.ipv6.dport.mask = 0xffff;  } diff --git a/drivers/net/ethernet/mscc/ocelot_stats.c b/drivers/net/ethernet/mscc/ocelot_stats.c index dbd20b125cea..bdb893476832 100644 --- a/drivers/net/ethernet/mscc/ocelot_stats.c +++ b/drivers/net/ethernet/mscc/ocelot_stats.c @@ -4,11 +4,317 @@   * Copyright (c) 2017 Microsemi Corporation   * Copyright 2022 NXP   */ +#include <linux/ethtool_netlink.h>  #include <linux/spinlock.h>  #include <linux/mutex.h>  #include <linux/workqueue.h>  #include "ocelot.h" +enum ocelot_stat { +	OCELOT_STAT_RX_OCTETS, +	OCELOT_STAT_RX_UNICAST, +	OCELOT_STAT_RX_MULTICAST, +	OCELOT_STAT_RX_BROADCAST, +	OCELOT_STAT_RX_SHORTS, +	OCELOT_STAT_RX_FRAGMENTS, +	OCELOT_STAT_RX_JABBERS, +	OCELOT_STAT_RX_CRC_ALIGN_ERRS, +	OCELOT_STAT_RX_SYM_ERRS, +	OCELOT_STAT_RX_64, +	OCELOT_STAT_RX_65_127, +	OCELOT_STAT_RX_128_255, +	OCELOT_STAT_RX_256_511, +	OCELOT_STAT_RX_512_1023, +	OCELOT_STAT_RX_1024_1526, +	OCELOT_STAT_RX_1527_MAX, +	OCELOT_STAT_RX_PAUSE, +	OCELOT_STAT_RX_CONTROL, +	OCELOT_STAT_RX_LONGS, +	OCELOT_STAT_RX_CLASSIFIED_DROPS, +	OCELOT_STAT_RX_RED_PRIO_0, +	OCELOT_STAT_RX_RED_PRIO_1, +	OCELOT_STAT_RX_RED_PRIO_2, +	OCELOT_STAT_RX_RED_PRIO_3, +	OCELOT_STAT_RX_RED_PRIO_4, +	OCELOT_STAT_RX_RED_PRIO_5, +	OCELOT_STAT_RX_RED_PRIO_6, +	OCELOT_STAT_RX_RED_PRIO_7, +	OCELOT_STAT_RX_YELLOW_PRIO_0, +	OCELOT_STAT_RX_YELLOW_PRIO_1, +	OCELOT_STAT_RX_YELLOW_PRIO_2, +	OCELOT_STAT_RX_YELLOW_PRIO_3, +	OCELOT_STAT_RX_YELLOW_PRIO_4, +	OCELOT_STAT_RX_YELLOW_PRIO_5, +	OCELOT_STAT_RX_YELLOW_PRIO_6, +	OCELOT_STAT_RX_YELLOW_PRIO_7, +	OCELOT_STAT_RX_GREEN_PRIO_0, +	OCELOT_STAT_RX_GREEN_PRIO_1, +	OCELOT_STAT_RX_GREEN_PRIO_2, +	OCELOT_STAT_RX_GREEN_PRIO_3, +	OCELOT_STAT_RX_GREEN_PRIO_4, +	OCELOT_STAT_RX_GREEN_PRIO_5, +	OCELOT_STAT_RX_GREEN_PRIO_6, +	OCELOT_STAT_RX_GREEN_PRIO_7, +	OCELOT_STAT_RX_ASSEMBLY_ERRS, +	OCELOT_STAT_RX_SMD_ERRS, +	OCELOT_STAT_RX_ASSEMBLY_OK, +	OCELOT_STAT_RX_MERGE_FRAGMENTS, +	OCELOT_STAT_RX_PMAC_OCTETS, +	OCELOT_STAT_RX_PMAC_UNICAST, +	OCELOT_STAT_RX_PMAC_MULTICAST, +	OCELOT_STAT_RX_PMAC_BROADCAST, +	OCELOT_STAT_RX_PMAC_SHORTS, +	OCELOT_STAT_RX_PMAC_FRAGMENTS, +	OCELOT_STAT_RX_PMAC_JABBERS, +	OCELOT_STAT_RX_PMAC_CRC_ALIGN_ERRS, +	OCELOT_STAT_RX_PMAC_SYM_ERRS, +	OCELOT_STAT_RX_PMAC_64, +	OCELOT_STAT_RX_PMAC_65_127, +	OCELOT_STAT_RX_PMAC_128_255, +	OCELOT_STAT_RX_PMAC_256_511, +	OCELOT_STAT_RX_PMAC_512_1023, +	OCELOT_STAT_RX_PMAC_1024_1526, +	OCELOT_STAT_RX_PMAC_1527_MAX, +	OCELOT_STAT_RX_PMAC_PAUSE, +	OCELOT_STAT_RX_PMAC_CONTROL, +	OCELOT_STAT_RX_PMAC_LONGS, +	OCELOT_STAT_TX_OCTETS, +	OCELOT_STAT_TX_UNICAST, +	OCELOT_STAT_TX_MULTICAST, +	OCELOT_STAT_TX_BROADCAST, +	OCELOT_STAT_TX_COLLISION, +	OCELOT_STAT_TX_DROPS, +	OCELOT_STAT_TX_PAUSE, +	OCELOT_STAT_TX_64, +	OCELOT_STAT_TX_65_127, +	OCELOT_STAT_TX_128_255, +	OCELOT_STAT_TX_256_511, +	OCELOT_STAT_TX_512_1023, +	OCELOT_STAT_TX_1024_1526, +	OCELOT_STAT_TX_1527_MAX, +	OCELOT_STAT_TX_YELLOW_PRIO_0, +	OCELOT_STAT_TX_YELLOW_PRIO_1, +	OCELOT_STAT_TX_YELLOW_PRIO_2, +	OCELOT_STAT_TX_YELLOW_PRIO_3, +	OCELOT_STAT_TX_YELLOW_PRIO_4, +	OCELOT_STAT_TX_YELLOW_PRIO_5, +	OCELOT_STAT_TX_YELLOW_PRIO_6, +	OCELOT_STAT_TX_YELLOW_PRIO_7, +	OCELOT_STAT_TX_GREEN_PRIO_0, +	OCELOT_STAT_TX_GREEN_PRIO_1, +	OCELOT_STAT_TX_GREEN_PRIO_2, +	OCELOT_STAT_TX_GREEN_PRIO_3, +	OCELOT_STAT_TX_GREEN_PRIO_4, +	OCELOT_STAT_TX_GREEN_PRIO_5, +	OCELOT_STAT_TX_GREEN_PRIO_6, +	OCELOT_STAT_TX_GREEN_PRIO_7, +	OCELOT_STAT_TX_AGED, +	OCELOT_STAT_TX_MM_HOLD, +	OCELOT_STAT_TX_MERGE_FRAGMENTS, +	OCELOT_STAT_TX_PMAC_OCTETS, +	OCELOT_STAT_TX_PMAC_UNICAST, +	OCELOT_STAT_TX_PMAC_MULTICAST, +	OCELOT_STAT_TX_PMAC_BROADCAST, +	OCELOT_STAT_TX_PMAC_PAUSE, +	OCELOT_STAT_TX_PMAC_64, +	OCELOT_STAT_TX_PMAC_65_127, +	OCELOT_STAT_TX_PMAC_128_255, +	OCELOT_STAT_TX_PMAC_256_511, +	OCELOT_STAT_TX_PMAC_512_1023, +	OCELOT_STAT_TX_PMAC_1024_1526, +	OCELOT_STAT_TX_PMAC_1527_MAX, +	OCELOT_STAT_DROP_LOCAL, +	OCELOT_STAT_DROP_TAIL, +	OCELOT_STAT_DROP_YELLOW_PRIO_0, +	OCELOT_STAT_DROP_YELLOW_PRIO_1, +	OCELOT_STAT_DROP_YELLOW_PRIO_2, +	OCELOT_STAT_DROP_YELLOW_PRIO_3, +	OCELOT_STAT_DROP_YELLOW_PRIO_4, +	OCELOT_STAT_DROP_YELLOW_PRIO_5, +	OCELOT_STAT_DROP_YELLOW_PRIO_6, +	OCELOT_STAT_DROP_YELLOW_PRIO_7, +	OCELOT_STAT_DROP_GREEN_PRIO_0, +	OCELOT_STAT_DROP_GREEN_PRIO_1, +	OCELOT_STAT_DROP_GREEN_PRIO_2, +	OCELOT_STAT_DROP_GREEN_PRIO_3, +	OCELOT_STAT_DROP_GREEN_PRIO_4, +	OCELOT_STAT_DROP_GREEN_PRIO_5, +	OCELOT_STAT_DROP_GREEN_PRIO_6, +	OCELOT_STAT_DROP_GREEN_PRIO_7, +	OCELOT_NUM_STATS, +}; + +struct ocelot_stat_layout { +	u32 reg; +	char name[ETH_GSTRING_LEN]; +}; + +/* 32-bit counter checked for wraparound by ocelot_port_update_stats() + * and copied to ocelot->stats. + */ +#define OCELOT_STAT(kind) \ +	[OCELOT_STAT_ ## kind] = { .reg = SYS_COUNT_ ## kind } +/* Same as above, except also exported to ethtool -S. Standard counters should + * only be exposed to more specific interfaces rather than by their string name. + */ +#define OCELOT_STAT_ETHTOOL(kind, ethtool_name) \ +	[OCELOT_STAT_ ## kind] = { .reg = SYS_COUNT_ ## kind, .name = ethtool_name } + +#define OCELOT_COMMON_STATS \ +	OCELOT_STAT_ETHTOOL(RX_OCTETS, "rx_octets"), \ +	OCELOT_STAT_ETHTOOL(RX_UNICAST, "rx_unicast"), \ +	OCELOT_STAT_ETHTOOL(RX_MULTICAST, "rx_multicast"), \ +	OCELOT_STAT_ETHTOOL(RX_BROADCAST, "rx_broadcast"), \ +	OCELOT_STAT_ETHTOOL(RX_SHORTS, "rx_shorts"), \ +	OCELOT_STAT_ETHTOOL(RX_FRAGMENTS, "rx_fragments"), \ +	OCELOT_STAT_ETHTOOL(RX_JABBERS, "rx_jabbers"), \ +	OCELOT_STAT_ETHTOOL(RX_CRC_ALIGN_ERRS, "rx_crc_align_errs"), \ +	OCELOT_STAT_ETHTOOL(RX_SYM_ERRS, "rx_sym_errs"), \ +	OCELOT_STAT_ETHTOOL(RX_64, "rx_frames_below_65_octets"), \ +	OCELOT_STAT_ETHTOOL(RX_65_127, "rx_frames_65_to_127_octets"), \ +	OCELOT_STAT_ETHTOOL(RX_128_255, "rx_frames_128_to_255_octets"), \ +	OCELOT_STAT_ETHTOOL(RX_256_511, "rx_frames_256_to_511_octets"), \ +	OCELOT_STAT_ETHTOOL(RX_512_1023, "rx_frames_512_to_1023_octets"), \ +	OCELOT_STAT_ETHTOOL(RX_1024_1526, "rx_frames_1024_to_1526_octets"), \ +	OCELOT_STAT_ETHTOOL(RX_1527_MAX, "rx_frames_over_1526_octets"), \ +	OCELOT_STAT_ETHTOOL(RX_PAUSE, "rx_pause"), \ +	OCELOT_STAT_ETHTOOL(RX_CONTROL, "rx_control"), \ +	OCELOT_STAT_ETHTOOL(RX_LONGS, "rx_longs"), \ +	OCELOT_STAT_ETHTOOL(RX_CLASSIFIED_DROPS, "rx_classified_drops"), \ +	OCELOT_STAT_ETHTOOL(RX_RED_PRIO_0, "rx_red_prio_0"), \ +	OCELOT_STAT_ETHTOOL(RX_RED_PRIO_1, "rx_red_prio_1"), \ +	OCELOT_STAT_ETHTOOL(RX_RED_PRIO_2, "rx_red_prio_2"), \ +	OCELOT_STAT_ETHTOOL(RX_RED_PRIO_3, "rx_red_prio_3"), \ +	OCELOT_STAT_ETHTOOL(RX_RED_PRIO_4, "rx_red_prio_4"), \ +	OCELOT_STAT_ETHTOOL(RX_RED_PRIO_5, "rx_red_prio_5"), \ +	OCELOT_STAT_ETHTOOL(RX_RED_PRIO_6, "rx_red_prio_6"), \ +	OCELOT_STAT_ETHTOOL(RX_RED_PRIO_7, "rx_red_prio_7"), \ +	OCELOT_STAT_ETHTOOL(RX_YELLOW_PRIO_0, "rx_yellow_prio_0"), \ +	OCELOT_STAT_ETHTOOL(RX_YELLOW_PRIO_1, "rx_yellow_prio_1"), \ +	OCELOT_STAT_ETHTOOL(RX_YELLOW_PRIO_2, "rx_yellow_prio_2"), \ +	OCELOT_STAT_ETHTOOL(RX_YELLOW_PRIO_3, "rx_yellow_prio_3"), \ +	OCELOT_STAT_ETHTOOL(RX_YELLOW_PRIO_4, "rx_yellow_prio_4"), \ +	OCELOT_STAT_ETHTOOL(RX_YELLOW_PRIO_5, "rx_yellow_prio_5"), \ +	OCELOT_STAT_ETHTOOL(RX_YELLOW_PRIO_6, "rx_yellow_prio_6"), \ +	OCELOT_STAT_ETHTOOL(RX_YELLOW_PRIO_7, "rx_yellow_prio_7"), \ +	OCELOT_STAT_ETHTOOL(RX_GREEN_PRIO_0, "rx_green_prio_0"), \ +	OCELOT_STAT_ETHTOOL(RX_GREEN_PRIO_1, "rx_green_prio_1"), \ +	OCELOT_STAT_ETHTOOL(RX_GREEN_PRIO_2, "rx_green_prio_2"), \ +	OCELOT_STAT_ETHTOOL(RX_GREEN_PRIO_3, "rx_green_prio_3"), \ +	OCELOT_STAT_ETHTOOL(RX_GREEN_PRIO_4, "rx_green_prio_4"), \ +	OCELOT_STAT_ETHTOOL(RX_GREEN_PRIO_5, "rx_green_prio_5"), \ +	OCELOT_STAT_ETHTOOL(RX_GREEN_PRIO_6, "rx_green_prio_6"), \ +	OCELOT_STAT_ETHTOOL(RX_GREEN_PRIO_7, "rx_green_prio_7"), \ +	OCELOT_STAT_ETHTOOL(TX_OCTETS, "tx_octets"), \ +	OCELOT_STAT_ETHTOOL(TX_UNICAST, "tx_unicast"), \ +	OCELOT_STAT_ETHTOOL(TX_MULTICAST, "tx_multicast"), \ +	OCELOT_STAT_ETHTOOL(TX_BROADCAST, "tx_broadcast"), \ +	OCELOT_STAT_ETHTOOL(TX_COLLISION, "tx_collision"), \ +	OCELOT_STAT_ETHTOOL(TX_DROPS, "tx_drops"), \ +	OCELOT_STAT_ETHTOOL(TX_PAUSE, "tx_pause"), \ +	OCELOT_STAT_ETHTOOL(TX_64, "tx_frames_below_65_octets"), \ +	OCELOT_STAT_ETHTOOL(TX_65_127, "tx_frames_65_to_127_octets"), \ +	OCELOT_STAT_ETHTOOL(TX_128_255, "tx_frames_128_255_octets"), \ +	OCELOT_STAT_ETHTOOL(TX_256_511, "tx_frames_256_511_octets"), \ +	OCELOT_STAT_ETHTOOL(TX_512_1023, "tx_frames_512_1023_octets"), \ +	OCELOT_STAT_ETHTOOL(TX_1024_1526, "tx_frames_1024_1526_octets"), \ +	OCELOT_STAT_ETHTOOL(TX_1527_MAX, "tx_frames_over_1526_octets"), \ +	OCELOT_STAT_ETHTOOL(TX_YELLOW_PRIO_0, "tx_yellow_prio_0"), \ +	OCELOT_STAT_ETHTOOL(TX_YELLOW_PRIO_1, "tx_yellow_prio_1"), \ +	OCELOT_STAT_ETHTOOL(TX_YELLOW_PRIO_2, "tx_yellow_prio_2"), \ +	OCELOT_STAT_ETHTOOL(TX_YELLOW_PRIO_3, "tx_yellow_prio_3"), \ +	OCELOT_STAT_ETHTOOL(TX_YELLOW_PRIO_4, "tx_yellow_prio_4"), \ +	OCELOT_STAT_ETHTOOL(TX_YELLOW_PRIO_5, "tx_yellow_prio_5"), \ +	OCELOT_STAT_ETHTOOL(TX_YELLOW_PRIO_6, "tx_yellow_prio_6"), \ +	OCELOT_STAT_ETHTOOL(TX_YELLOW_PRIO_7, "tx_yellow_prio_7"), \ +	OCELOT_STAT_ETHTOOL(TX_GREEN_PRIO_0, "tx_green_prio_0"), \ +	OCELOT_STAT_ETHTOOL(TX_GREEN_PRIO_1, "tx_green_prio_1"), \ +	OCELOT_STAT_ETHTOOL(TX_GREEN_PRIO_2, "tx_green_prio_2"), \ +	OCELOT_STAT_ETHTOOL(TX_GREEN_PRIO_3, "tx_green_prio_3"), \ +	OCELOT_STAT_ETHTOOL(TX_GREEN_PRIO_4, "tx_green_prio_4"), \ +	OCELOT_STAT_ETHTOOL(TX_GREEN_PRIO_5, "tx_green_prio_5"), \ +	OCELOT_STAT_ETHTOOL(TX_GREEN_PRIO_6, "tx_green_prio_6"), \ +	OCELOT_STAT_ETHTOOL(TX_GREEN_PRIO_7, "tx_green_prio_7"), \ +	OCELOT_STAT_ETHTOOL(TX_AGED, "tx_aged"), \ +	OCELOT_STAT_ETHTOOL(DROP_LOCAL, "drop_local"), \ +	OCELOT_STAT_ETHTOOL(DROP_TAIL, "drop_tail"), \ +	OCELOT_STAT_ETHTOOL(DROP_YELLOW_PRIO_0, "drop_yellow_prio_0"), \ +	OCELOT_STAT_ETHTOOL(DROP_YELLOW_PRIO_1, "drop_yellow_prio_1"), \ +	OCELOT_STAT_ETHTOOL(DROP_YELLOW_PRIO_2, "drop_yellow_prio_2"), \ +	OCELOT_STAT_ETHTOOL(DROP_YELLOW_PRIO_3, "drop_yellow_prio_3"), \ +	OCELOT_STAT_ETHTOOL(DROP_YELLOW_PRIO_4, "drop_yellow_prio_4"), \ +	OCELOT_STAT_ETHTOOL(DROP_YELLOW_PRIO_5, "drop_yellow_prio_5"), \ +	OCELOT_STAT_ETHTOOL(DROP_YELLOW_PRIO_6, "drop_yellow_prio_6"), \ +	OCELOT_STAT_ETHTOOL(DROP_YELLOW_PRIO_7, "drop_yellow_prio_7"), \ +	OCELOT_STAT_ETHTOOL(DROP_GREEN_PRIO_0, "drop_green_prio_0"), \ +	OCELOT_STAT_ETHTOOL(DROP_GREEN_PRIO_1, "drop_green_prio_1"), \ +	OCELOT_STAT_ETHTOOL(DROP_GREEN_PRIO_2, "drop_green_prio_2"), \ +	OCELOT_STAT_ETHTOOL(DROP_GREEN_PRIO_3, "drop_green_prio_3"), \ +	OCELOT_STAT_ETHTOOL(DROP_GREEN_PRIO_4, "drop_green_prio_4"), \ +	OCELOT_STAT_ETHTOOL(DROP_GREEN_PRIO_5, "drop_green_prio_5"), \ +	OCELOT_STAT_ETHTOOL(DROP_GREEN_PRIO_6, "drop_green_prio_6"), \ +	OCELOT_STAT_ETHTOOL(DROP_GREEN_PRIO_7, "drop_green_prio_7") + +struct ocelot_stats_region { +	struct list_head node; +	u32 base; +	int count; +	u32 *buf; +}; + +static const struct ocelot_stat_layout ocelot_stats_layout[OCELOT_NUM_STATS] = { +	OCELOT_COMMON_STATS, +}; + +static const struct ocelot_stat_layout ocelot_mm_stats_layout[OCELOT_NUM_STATS] = { +	OCELOT_COMMON_STATS, +	OCELOT_STAT(RX_ASSEMBLY_ERRS), +	OCELOT_STAT(RX_SMD_ERRS), +	OCELOT_STAT(RX_ASSEMBLY_OK), +	OCELOT_STAT(RX_MERGE_FRAGMENTS), +	OCELOT_STAT(TX_MERGE_FRAGMENTS), +	OCELOT_STAT(RX_PMAC_OCTETS), +	OCELOT_STAT(RX_PMAC_UNICAST), +	OCELOT_STAT(RX_PMAC_MULTICAST), +	OCELOT_STAT(RX_PMAC_BROADCAST), +	OCELOT_STAT(RX_PMAC_SHORTS), +	OCELOT_STAT(RX_PMAC_FRAGMENTS), +	OCELOT_STAT(RX_PMAC_JABBERS), +	OCELOT_STAT(RX_PMAC_CRC_ALIGN_ERRS), +	OCELOT_STAT(RX_PMAC_SYM_ERRS), +	OCELOT_STAT(RX_PMAC_64), +	OCELOT_STAT(RX_PMAC_65_127), +	OCELOT_STAT(RX_PMAC_128_255), +	OCELOT_STAT(RX_PMAC_256_511), +	OCELOT_STAT(RX_PMAC_512_1023), +	OCELOT_STAT(RX_PMAC_1024_1526), +	OCELOT_STAT(RX_PMAC_1527_MAX), +	OCELOT_STAT(RX_PMAC_PAUSE), +	OCELOT_STAT(RX_PMAC_CONTROL), +	OCELOT_STAT(RX_PMAC_LONGS), +	OCELOT_STAT(TX_PMAC_OCTETS), +	OCELOT_STAT(TX_PMAC_UNICAST), +	OCELOT_STAT(TX_PMAC_MULTICAST), +	OCELOT_STAT(TX_PMAC_BROADCAST), +	OCELOT_STAT(TX_PMAC_PAUSE), +	OCELOT_STAT(TX_PMAC_64), +	OCELOT_STAT(TX_PMAC_65_127), +	OCELOT_STAT(TX_PMAC_128_255), +	OCELOT_STAT(TX_PMAC_256_511), +	OCELOT_STAT(TX_PMAC_512_1023), +	OCELOT_STAT(TX_PMAC_1024_1526), +	OCELOT_STAT(TX_PMAC_1527_MAX), +}; + +static const struct ocelot_stat_layout * +ocelot_get_stats_layout(struct ocelot *ocelot) +{ +	if (ocelot->mm_supported) +		return ocelot_mm_stats_layout; + +	return ocelot_stats_layout; +} +  /* Read the counters from hardware and keep them in region->buf.   * Caller must hold &ocelot->stat_view_lock.   */ @@ -87,17 +393,20 @@ static void ocelot_check_stats_work(struct work_struct *work)  void ocelot_get_strings(struct ocelot *ocelot, int port, u32 sset, u8 *data)  { +	const struct ocelot_stat_layout *layout;  	int i;  	if (sset != ETH_SS_STATS)  		return; +	layout = ocelot_get_stats_layout(ocelot); +  	for (i = 0; i < OCELOT_NUM_STATS; i++) { -		if (ocelot->stats_layout[i].name[0] == '\0') +		if (layout[i].name[0] == '\0')  			continue; -		memcpy(data + i * ETH_GSTRING_LEN, ocelot->stats_layout[i].name, -		       ETH_GSTRING_LEN); +		memcpy(data, layout[i].name, ETH_GSTRING_LEN); +		data += ETH_GSTRING_LEN;  	}  }  EXPORT_SYMBOL(ocelot_get_strings); @@ -131,13 +440,16 @@ out_unlock:  int ocelot_get_sset_count(struct ocelot *ocelot, int port, int sset)  { +	const struct ocelot_stat_layout *layout;  	int i, num_stats = 0;  	if (sset != ETH_SS_STATS)  		return -EOPNOTSUPP; +	layout = ocelot_get_stats_layout(ocelot); +  	for (i = 0; i < OCELOT_NUM_STATS; i++) -		if (ocelot->stats_layout[i].name[0] != '\0') +		if (layout[i].name[0] != '\0')  			num_stats++;  	return num_stats; @@ -147,14 +459,17 @@ EXPORT_SYMBOL(ocelot_get_sset_count);  static void ocelot_port_ethtool_stats_cb(struct ocelot *ocelot, int port,  					 void *priv)  { +	const struct ocelot_stat_layout *layout;  	u64 *data = priv;  	int i; +	layout = ocelot_get_stats_layout(ocelot); +  	/* Copy all supported counters */  	for (i = 0; i < OCELOT_NUM_STATS; i++) {  		int index = port * OCELOT_NUM_STATS + i; -		if (ocelot->stats_layout[i].name[0] == '\0') +		if (layout[i].name[0] == '\0')  			continue;  		*data++ = ocelot->stats[index]; @@ -176,14 +491,63 @@ static void ocelot_port_pause_stats_cb(struct ocelot *ocelot, int port, void *pr  	pause_stats->rx_pause_frames = s[OCELOT_STAT_RX_PAUSE];  } +static void ocelot_port_pmac_pause_stats_cb(struct ocelot *ocelot, int port, +					    void *priv) +{ +	u64 *s = &ocelot->stats[port * OCELOT_NUM_STATS]; +	struct ethtool_pause_stats *pause_stats = priv; + +	pause_stats->tx_pause_frames = s[OCELOT_STAT_TX_PMAC_PAUSE]; +	pause_stats->rx_pause_frames = s[OCELOT_STAT_RX_PMAC_PAUSE]; +} + +static void ocelot_port_mm_stats_cb(struct ocelot *ocelot, int port, +				    void *priv) +{ +	u64 *s = &ocelot->stats[port * OCELOT_NUM_STATS]; +	struct ethtool_mm_stats *stats = priv; + +	stats->MACMergeFrameAssErrorCount = s[OCELOT_STAT_RX_ASSEMBLY_ERRS]; +	stats->MACMergeFrameSmdErrorCount = s[OCELOT_STAT_RX_SMD_ERRS]; +	stats->MACMergeFrameAssOkCount = s[OCELOT_STAT_RX_ASSEMBLY_OK]; +	stats->MACMergeFragCountRx = s[OCELOT_STAT_RX_MERGE_FRAGMENTS]; +	stats->MACMergeFragCountTx = s[OCELOT_STAT_TX_MERGE_FRAGMENTS]; +	stats->MACMergeHoldCount = s[OCELOT_STAT_TX_MM_HOLD]; +} +  void ocelot_port_get_pause_stats(struct ocelot *ocelot, int port,  				 struct ethtool_pause_stats *pause_stats)  { -	ocelot_port_stats_run(ocelot, port, pause_stats, -			      ocelot_port_pause_stats_cb); +	struct net_device *dev; + +	switch (pause_stats->src) { +	case ETHTOOL_MAC_STATS_SRC_EMAC: +		ocelot_port_stats_run(ocelot, port, pause_stats, +				      ocelot_port_pause_stats_cb); +		break; +	case ETHTOOL_MAC_STATS_SRC_PMAC: +		if (ocelot->mm_supported) +			ocelot_port_stats_run(ocelot, port, pause_stats, +					      ocelot_port_pmac_pause_stats_cb); +		break; +	case ETHTOOL_MAC_STATS_SRC_AGGREGATE: +		dev = ocelot->ops->port_to_netdev(ocelot, port); +		ethtool_aggregate_pause_stats(dev, pause_stats); +		break; +	}  }  EXPORT_SYMBOL_GPL(ocelot_port_get_pause_stats); +void ocelot_port_get_mm_stats(struct ocelot *ocelot, int port, +			      struct ethtool_mm_stats *stats) +{ +	if (!ocelot->mm_supported) +		return; + +	ocelot_port_stats_run(ocelot, port, stats, ocelot_port_mm_stats_cb); +} +EXPORT_SYMBOL_GPL(ocelot_port_get_mm_stats); +  static const struct ethtool_rmon_hist_range ocelot_rmon_ranges[] = {  	{   64,    64 },  	{   65,   127 }, @@ -222,14 +586,57 @@ static void ocelot_port_rmon_stats_cb(struct ocelot *ocelot, int port, void *pri  	rmon_stats->hist_tx[6] = s[OCELOT_STAT_TX_1024_1526];  } +static void ocelot_port_pmac_rmon_stats_cb(struct ocelot *ocelot, int port, +					   void *priv) +{ +	u64 *s = &ocelot->stats[port * OCELOT_NUM_STATS]; +	struct ethtool_rmon_stats *rmon_stats = priv; + +	rmon_stats->undersize_pkts = s[OCELOT_STAT_RX_PMAC_SHORTS]; +	rmon_stats->oversize_pkts = s[OCELOT_STAT_RX_PMAC_LONGS]; +	rmon_stats->fragments = s[OCELOT_STAT_RX_PMAC_FRAGMENTS]; +	rmon_stats->jabbers = s[OCELOT_STAT_RX_PMAC_JABBERS]; + +	rmon_stats->hist[0] = s[OCELOT_STAT_RX_PMAC_64]; +	rmon_stats->hist[1] = s[OCELOT_STAT_RX_PMAC_65_127]; +	rmon_stats->hist[2] = s[OCELOT_STAT_RX_PMAC_128_255]; +	rmon_stats->hist[3] = s[OCELOT_STAT_RX_PMAC_256_511]; +	rmon_stats->hist[4] = s[OCELOT_STAT_RX_PMAC_512_1023]; +	rmon_stats->hist[5] = s[OCELOT_STAT_RX_PMAC_1024_1526]; +	rmon_stats->hist[6] = s[OCELOT_STAT_RX_PMAC_1527_MAX]; + +	rmon_stats->hist_tx[0] = s[OCELOT_STAT_TX_PMAC_64]; +	rmon_stats->hist_tx[1] = s[OCELOT_STAT_TX_PMAC_65_127]; +	rmon_stats->hist_tx[2] = s[OCELOT_STAT_TX_PMAC_128_255]; +	rmon_stats->hist_tx[3] = s[OCELOT_STAT_TX_PMAC_128_255]; +	rmon_stats->hist_tx[4] = s[OCELOT_STAT_TX_PMAC_256_511]; +	rmon_stats->hist_tx[5] = s[OCELOT_STAT_TX_PMAC_512_1023]; +	rmon_stats->hist_tx[6] = s[OCELOT_STAT_TX_PMAC_1024_1526]; +} +  void ocelot_port_get_rmon_stats(struct ocelot *ocelot, int port,  				struct ethtool_rmon_stats *rmon_stats,  				const struct ethtool_rmon_hist_range **ranges)  { +	struct net_device *dev; +  	*ranges = ocelot_rmon_ranges; -	ocelot_port_stats_run(ocelot, port, rmon_stats, -			      ocelot_port_rmon_stats_cb); +	switch (rmon_stats->src) { +	case ETHTOOL_MAC_STATS_SRC_EMAC: +		ocelot_port_stats_run(ocelot, port, rmon_stats, +				      ocelot_port_rmon_stats_cb); +		break; +	case ETHTOOL_MAC_STATS_SRC_PMAC: +		if (ocelot->mm_supported) +			ocelot_port_stats_run(ocelot, port, rmon_stats, +					      ocelot_port_pmac_rmon_stats_cb); +		break; +	case ETHTOOL_MAC_STATS_SRC_AGGREGATE: +		dev = ocelot->ops->port_to_netdev(ocelot, port); +		ethtool_aggregate_rmon_stats(dev, rmon_stats); +		break; +	}  }  EXPORT_SYMBOL_GPL(ocelot_port_get_rmon_stats); @@ -241,11 +648,35 @@ static void ocelot_port_ctrl_stats_cb(struct ocelot *ocelot, int port, void *pri  	ctrl_stats->MACControlFramesReceived = s[OCELOT_STAT_RX_CONTROL];  } +static void ocelot_port_pmac_ctrl_stats_cb(struct ocelot *ocelot, int port, +					   void *priv) +{ +	u64 *s = &ocelot->stats[port * OCELOT_NUM_STATS]; +	struct ethtool_eth_ctrl_stats *ctrl_stats = priv; + +	ctrl_stats->MACControlFramesReceived = s[OCELOT_STAT_RX_PMAC_CONTROL]; +} +  void ocelot_port_get_eth_ctrl_stats(struct ocelot *ocelot, int port,  				    struct ethtool_eth_ctrl_stats *ctrl_stats)  { -	ocelot_port_stats_run(ocelot, port, ctrl_stats, -			      ocelot_port_ctrl_stats_cb); +	struct net_device *dev; + +	switch (ctrl_stats->src) { +	case ETHTOOL_MAC_STATS_SRC_EMAC: +		ocelot_port_stats_run(ocelot, port, ctrl_stats, +				      ocelot_port_ctrl_stats_cb); +		break; +	case ETHTOOL_MAC_STATS_SRC_PMAC: +		if (ocelot->mm_supported) +			ocelot_port_stats_run(ocelot, port, ctrl_stats, +					      ocelot_port_pmac_ctrl_stats_cb); +		break; +	case ETHTOOL_MAC_STATS_SRC_AGGREGATE: +		dev = ocelot->ops->port_to_netdev(ocelot, port); +		ethtool_aggregate_ctrl_stats(dev, ctrl_stats); +		break; +	}  }  EXPORT_SYMBOL_GPL(ocelot_port_get_eth_ctrl_stats); @@ -291,11 +722,60 @@ static void ocelot_port_mac_stats_cb(struct ocelot *ocelot, int port, void *priv  	mac_stats->AlignmentErrors = s[OCELOT_STAT_RX_CRC_ALIGN_ERRS];  } +static void ocelot_port_pmac_mac_stats_cb(struct ocelot *ocelot, int port, +					  void *priv) +{ +	u64 *s = &ocelot->stats[port * OCELOT_NUM_STATS]; +	struct ethtool_eth_mac_stats *mac_stats = priv; + +	mac_stats->OctetsTransmittedOK = s[OCELOT_STAT_TX_PMAC_OCTETS]; +	mac_stats->FramesTransmittedOK = s[OCELOT_STAT_TX_PMAC_64] + +					 s[OCELOT_STAT_TX_PMAC_65_127] + +					 s[OCELOT_STAT_TX_PMAC_128_255] + +					 s[OCELOT_STAT_TX_PMAC_256_511] + +					 s[OCELOT_STAT_TX_PMAC_512_1023] + +					 s[OCELOT_STAT_TX_PMAC_1024_1526] + +					 s[OCELOT_STAT_TX_PMAC_1527_MAX]; +	mac_stats->OctetsReceivedOK = s[OCELOT_STAT_RX_PMAC_OCTETS]; +	mac_stats->FramesReceivedOK = s[OCELOT_STAT_RX_PMAC_64] + +				      s[OCELOT_STAT_RX_PMAC_65_127] + +				      s[OCELOT_STAT_RX_PMAC_128_255] + +				      s[OCELOT_STAT_RX_PMAC_256_511] + +				      s[OCELOT_STAT_RX_PMAC_512_1023] + +				      s[OCELOT_STAT_RX_PMAC_1024_1526] + +				      s[OCELOT_STAT_RX_PMAC_1527_MAX]; +	mac_stats->MulticastFramesXmittedOK = s[OCELOT_STAT_TX_PMAC_MULTICAST]; +	mac_stats->BroadcastFramesXmittedOK = s[OCELOT_STAT_TX_PMAC_BROADCAST]; +	mac_stats->MulticastFramesReceivedOK = s[OCELOT_STAT_RX_PMAC_MULTICAST]; +	mac_stats->BroadcastFramesReceivedOK = s[OCELOT_STAT_RX_PMAC_BROADCAST]; +	mac_stats->FrameTooLongErrors = s[OCELOT_STAT_RX_PMAC_LONGS]; +	/* Sadly, C_RX_CRC is the sum of FCS and alignment errors, they are not +	 * counted individually. +	 */ +	mac_stats->FrameCheckSequenceErrors = s[OCELOT_STAT_RX_PMAC_CRC_ALIGN_ERRS]; +	mac_stats->AlignmentErrors = s[OCELOT_STAT_RX_PMAC_CRC_ALIGN_ERRS]; +} +  void ocelot_port_get_eth_mac_stats(struct ocelot *ocelot, int port,  				   struct ethtool_eth_mac_stats *mac_stats)  { -	ocelot_port_stats_run(ocelot, port, mac_stats, -			      ocelot_port_mac_stats_cb); +	struct net_device *dev; + +	switch (mac_stats->src) { +	case ETHTOOL_MAC_STATS_SRC_EMAC: +		ocelot_port_stats_run(ocelot, port, mac_stats, +				      ocelot_port_mac_stats_cb); +		break; +	case ETHTOOL_MAC_STATS_SRC_PMAC: +		if (ocelot->mm_supported) +			ocelot_port_stats_run(ocelot, port, mac_stats, +					      ocelot_port_pmac_mac_stats_cb); +		break; +	case ETHTOOL_MAC_STATS_SRC_AGGREGATE: +		dev = ocelot->ops->port_to_netdev(ocelot, port); +		ethtool_aggregate_mac_stats(dev, mac_stats); +		break; +	}  }  EXPORT_SYMBOL_GPL(ocelot_port_get_eth_mac_stats); @@ -307,11 +787,35 @@ static void ocelot_port_phy_stats_cb(struct ocelot *ocelot, int port, void *priv  	phy_stats->SymbolErrorDuringCarrier = s[OCELOT_STAT_RX_SYM_ERRS];  } +static void ocelot_port_pmac_phy_stats_cb(struct ocelot *ocelot, int port, +					  void *priv) +{ +	u64 *s = &ocelot->stats[port * OCELOT_NUM_STATS]; +	struct ethtool_eth_phy_stats *phy_stats = priv; + +	phy_stats->SymbolErrorDuringCarrier = s[OCELOT_STAT_RX_PMAC_SYM_ERRS]; +} +  void ocelot_port_get_eth_phy_stats(struct ocelot *ocelot, int port,  				   struct ethtool_eth_phy_stats *phy_stats)  { -	ocelot_port_stats_run(ocelot, port, phy_stats, -			      ocelot_port_phy_stats_cb); +	struct net_device *dev; + +	switch (phy_stats->src) { +	case ETHTOOL_MAC_STATS_SRC_EMAC: +		ocelot_port_stats_run(ocelot, port, phy_stats, +				      ocelot_port_phy_stats_cb); +		break; +	case ETHTOOL_MAC_STATS_SRC_PMAC: +		if (ocelot->mm_supported) +			ocelot_port_stats_run(ocelot, port, phy_stats, +					      ocelot_port_pmac_phy_stats_cb); +		break; +	case ETHTOOL_MAC_STATS_SRC_AGGREGATE: +		dev = ocelot->ops->port_to_netdev(ocelot, port); +		ethtool_aggregate_phy_stats(dev, phy_stats); +		break; +	}  }  EXPORT_SYMBOL_GPL(ocelot_port_get_eth_phy_stats); @@ -383,16 +887,19 @@ EXPORT_SYMBOL(ocelot_port_get_stats64);  static int ocelot_prepare_stats_regions(struct ocelot *ocelot)  {  	struct ocelot_stats_region *region = NULL; -	unsigned int last; +	const struct ocelot_stat_layout *layout; +	unsigned int last = 0;  	int i;  	INIT_LIST_HEAD(&ocelot->stats_regions); +	layout = ocelot_get_stats_layout(ocelot); +  	for (i = 0; i < OCELOT_NUM_STATS; i++) { -		if (!ocelot->stats_layout[i].reg) +		if (!layout[i].reg)  			continue; -		if (region && ocelot->stats_layout[i].reg == last + 4) { +		if (region && layout[i].reg == last + 4) {  			region->count++;  		} else {  			region = devm_kzalloc(ocelot->dev, sizeof(*region), @@ -400,12 +907,18 @@ static int ocelot_prepare_stats_regions(struct ocelot *ocelot)  			if (!region)  				return -ENOMEM; -			region->base = ocelot->stats_layout[i].reg; +			/* enum ocelot_stat must be kept sorted in the same +			 * order as layout[i].reg in order to have efficient +			 * bulking +			 */ +			WARN_ON(last >= layout[i].reg); + +			region->base = layout[i].reg;  			region->count = 1;  			list_add_tail(®ion->node, &ocelot->stats_regions);  		} -		last = ocelot->stats_layout[i].reg; +		last = layout[i].reg;  	}  	list_for_each_entry(region, &ocelot->stats_regions, node) { @@ -456,3 +969,4 @@ void ocelot_stats_deinit(struct ocelot *ocelot)  	cancel_delayed_work(&ocelot->stats_work);  	destroy_workqueue(ocelot->stats_queue);  } + diff --git a/drivers/net/ethernet/mscc/ocelot_vsc7514.c b/drivers/net/ethernet/mscc/ocelot_vsc7514.c index 6f22aea08a64..7388c3b0535c 100644 --- a/drivers/net/ethernet/mscc/ocelot_vsc7514.c +++ b/drivers/net/ethernet/mscc/ocelot_vsc7514.c @@ -6,7 +6,6 @@   */  #include <linux/dsa/ocelot.h>  #include <linux/interrupt.h> -#include <linux/iopoll.h>  #include <linux/module.h>  #include <linux/of_net.h>  #include <linux/netdevice.h> @@ -17,6 +16,7 @@  #include <linux/skbuff.h>  #include <net/switchdev.h> +#include <soc/mscc/ocelot.h>  #include <soc/mscc/ocelot_vcap.h>  #include <soc/mscc/ocelot_hsio.h>  #include <soc/mscc/vsc7514_regs.h> @@ -26,84 +26,6 @@  #define VSC7514_VCAP_POLICER_BASE			128  #define VSC7514_VCAP_POLICER_MAX			191 -#define MEM_INIT_SLEEP_US				1000 -#define MEM_INIT_TIMEOUT_US				100000 - -static const u32 *ocelot_regmap[TARGET_MAX] = { -	[ANA] = vsc7514_ana_regmap, -	[QS] = vsc7514_qs_regmap, -	[QSYS] = vsc7514_qsys_regmap, -	[REW] = vsc7514_rew_regmap, -	[SYS] = vsc7514_sys_regmap, -	[S0] = vsc7514_vcap_regmap, -	[S1] = vsc7514_vcap_regmap, -	[S2] = vsc7514_vcap_regmap, -	[PTP] = vsc7514_ptp_regmap, -	[DEV_GMII] = vsc7514_dev_gmii_regmap, -}; - -static const struct reg_field ocelot_regfields[REGFIELD_MAX] = { -	[ANA_ADVLEARN_VLAN_CHK] = REG_FIELD(ANA_ADVLEARN, 11, 11), -	[ANA_ADVLEARN_LEARN_MIRROR] = REG_FIELD(ANA_ADVLEARN, 0, 10), -	[ANA_ANEVENTS_MSTI_DROP] = REG_FIELD(ANA_ANEVENTS, 27, 27), -	[ANA_ANEVENTS_ACLKILL] = REG_FIELD(ANA_ANEVENTS, 26, 26), -	[ANA_ANEVENTS_ACLUSED] = REG_FIELD(ANA_ANEVENTS, 25, 25), -	[ANA_ANEVENTS_AUTOAGE] = REG_FIELD(ANA_ANEVENTS, 24, 24), -	[ANA_ANEVENTS_VS2TTL1] = REG_FIELD(ANA_ANEVENTS, 23, 23), -	[ANA_ANEVENTS_STORM_DROP] = REG_FIELD(ANA_ANEVENTS, 22, 22), -	[ANA_ANEVENTS_LEARN_DROP] = REG_FIELD(ANA_ANEVENTS, 21, 21), -	[ANA_ANEVENTS_AGED_ENTRY] = REG_FIELD(ANA_ANEVENTS, 20, 20), -	[ANA_ANEVENTS_CPU_LEARN_FAILED] = REG_FIELD(ANA_ANEVENTS, 19, 19), -	[ANA_ANEVENTS_AUTO_LEARN_FAILED] = REG_FIELD(ANA_ANEVENTS, 18, 18), -	[ANA_ANEVENTS_LEARN_REMOVE] = REG_FIELD(ANA_ANEVENTS, 17, 17), -	[ANA_ANEVENTS_AUTO_LEARNED] = REG_FIELD(ANA_ANEVENTS, 16, 16), -	[ANA_ANEVENTS_AUTO_MOVED] = REG_FIELD(ANA_ANEVENTS, 15, 15), -	[ANA_ANEVENTS_DROPPED] = REG_FIELD(ANA_ANEVENTS, 14, 14), -	[ANA_ANEVENTS_CLASSIFIED_DROP] = REG_FIELD(ANA_ANEVENTS, 13, 13), -	[ANA_ANEVENTS_CLASSIFIED_COPY] = REG_FIELD(ANA_ANEVENTS, 12, 12), -	[ANA_ANEVENTS_VLAN_DISCARD] = REG_FIELD(ANA_ANEVENTS, 11, 11), -	[ANA_ANEVENTS_FWD_DISCARD] = REG_FIELD(ANA_ANEVENTS, 10, 10), -	[ANA_ANEVENTS_MULTICAST_FLOOD] = REG_FIELD(ANA_ANEVENTS, 9, 9), -	[ANA_ANEVENTS_UNICAST_FLOOD] = REG_FIELD(ANA_ANEVENTS, 8, 8), -	[ANA_ANEVENTS_DEST_KNOWN] = REG_FIELD(ANA_ANEVENTS, 7, 7), -	[ANA_ANEVENTS_BUCKET3_MATCH] = REG_FIELD(ANA_ANEVENTS, 6, 6), -	[ANA_ANEVENTS_BUCKET2_MATCH] = REG_FIELD(ANA_ANEVENTS, 5, 5), -	[ANA_ANEVENTS_BUCKET1_MATCH] = REG_FIELD(ANA_ANEVENTS, 4, 4), -	[ANA_ANEVENTS_BUCKET0_MATCH] = REG_FIELD(ANA_ANEVENTS, 3, 3), -	[ANA_ANEVENTS_CPU_OPERATION] = REG_FIELD(ANA_ANEVENTS, 2, 2), -	[ANA_ANEVENTS_DMAC_LOOKUP] = REG_FIELD(ANA_ANEVENTS, 1, 1), -	[ANA_ANEVENTS_SMAC_LOOKUP] = REG_FIELD(ANA_ANEVENTS, 0, 0), -	[ANA_TABLES_MACACCESS_B_DOM] = REG_FIELD(ANA_TABLES_MACACCESS, 18, 18), -	[ANA_TABLES_MACTINDX_BUCKET] = REG_FIELD(ANA_TABLES_MACTINDX, 10, 11), -	[ANA_TABLES_MACTINDX_M_INDEX] = REG_FIELD(ANA_TABLES_MACTINDX, 0, 9), -	[QSYS_TIMED_FRAME_ENTRY_TFRM_VLD] = REG_FIELD(QSYS_TIMED_FRAME_ENTRY, 20, 20), -	[QSYS_TIMED_FRAME_ENTRY_TFRM_FP] = REG_FIELD(QSYS_TIMED_FRAME_ENTRY, 8, 19), -	[QSYS_TIMED_FRAME_ENTRY_TFRM_PORTNO] = REG_FIELD(QSYS_TIMED_FRAME_ENTRY, 4, 7), -	[QSYS_TIMED_FRAME_ENTRY_TFRM_TM_SEL] = REG_FIELD(QSYS_TIMED_FRAME_ENTRY, 1, 3), -	[QSYS_TIMED_FRAME_ENTRY_TFRM_TM_T] = REG_FIELD(QSYS_TIMED_FRAME_ENTRY, 0, 0), -	[SYS_RESET_CFG_CORE_ENA] = REG_FIELD(SYS_RESET_CFG, 2, 2), -	[SYS_RESET_CFG_MEM_ENA] = REG_FIELD(SYS_RESET_CFG, 1, 1), -	[SYS_RESET_CFG_MEM_INIT] = REG_FIELD(SYS_RESET_CFG, 0, 0), -	/* Replicated per number of ports (12), register size 4 per port */ -	[QSYS_SWITCH_PORT_MODE_PORT_ENA] = REG_FIELD_ID(QSYS_SWITCH_PORT_MODE, 14, 14, 12, 4), -	[QSYS_SWITCH_PORT_MODE_SCH_NEXT_CFG] = REG_FIELD_ID(QSYS_SWITCH_PORT_MODE, 11, 13, 12, 4), -	[QSYS_SWITCH_PORT_MODE_YEL_RSRVD] = REG_FIELD_ID(QSYS_SWITCH_PORT_MODE, 10, 10, 12, 4), -	[QSYS_SWITCH_PORT_MODE_INGRESS_DROP_MODE] = REG_FIELD_ID(QSYS_SWITCH_PORT_MODE, 9, 9, 12, 4), -	[QSYS_SWITCH_PORT_MODE_TX_PFC_ENA] = REG_FIELD_ID(QSYS_SWITCH_PORT_MODE, 1, 8, 12, 4), -	[QSYS_SWITCH_PORT_MODE_TX_PFC_MODE] = REG_FIELD_ID(QSYS_SWITCH_PORT_MODE, 0, 0, 12, 4), -	[SYS_PORT_MODE_DATA_WO_TS] = REG_FIELD_ID(SYS_PORT_MODE, 5, 6, 12, 4), -	[SYS_PORT_MODE_INCL_INJ_HDR] = REG_FIELD_ID(SYS_PORT_MODE, 3, 4, 12, 4), -	[SYS_PORT_MODE_INCL_XTR_HDR] = REG_FIELD_ID(SYS_PORT_MODE, 1, 2, 12, 4), -	[SYS_PORT_MODE_INCL_HDR_ERR] = REG_FIELD_ID(SYS_PORT_MODE, 0, 0, 12, 4), -	[SYS_PAUSE_CFG_PAUSE_START] = REG_FIELD_ID(SYS_PAUSE_CFG, 10, 18, 12, 4), -	[SYS_PAUSE_CFG_PAUSE_STOP] = REG_FIELD_ID(SYS_PAUSE_CFG, 1, 9, 12, 4), -	[SYS_PAUSE_CFG_PAUSE_ENA] = REG_FIELD_ID(SYS_PAUSE_CFG, 0, 1, 12, 4), -}; - -static const struct ocelot_stat_layout ocelot_stats_layout[OCELOT_NUM_STATS] = { -	OCELOT_COMMON_STATS, -}; -  static void ocelot_pll5_init(struct ocelot *ocelot)  {  	/* Configure PLL5. This will need a proper CCF driver @@ -137,12 +59,11 @@ static int ocelot_chip_init(struct ocelot *ocelot, const struct ocelot_ops *ops)  {  	int ret; -	ocelot->map = ocelot_regmap; -	ocelot->stats_layout = ocelot_stats_layout; +	ocelot->map = vsc7514_regmap;  	ocelot->num_mact_rows = 1024;  	ocelot->ops = ops; -	ret = ocelot_regfields_init(ocelot, ocelot_regfields); +	ret = ocelot_regfields_init(ocelot, vsc7514_regfields);  	if (ret)  		return ret; @@ -195,73 +116,6 @@ static const struct of_device_id mscc_ocelot_match[] = {  };  MODULE_DEVICE_TABLE(of, mscc_ocelot_match); -static int ocelot_mem_init_status(struct ocelot *ocelot) -{ -	unsigned int val; -	int err; - -	err = regmap_field_read(ocelot->regfields[SYS_RESET_CFG_MEM_INIT], -				&val); - -	return err ?: val; -} - -static int ocelot_reset(struct ocelot *ocelot) -{ -	int err; -	u32 val; - -	err = regmap_field_write(ocelot->regfields[SYS_RESET_CFG_MEM_INIT], 1); -	if (err) -		return err; - -	err = regmap_field_write(ocelot->regfields[SYS_RESET_CFG_MEM_ENA], 1); -	if (err) -		return err; - -	/* MEM_INIT is a self-clearing bit. Wait for it to be cleared (should be -	 * 100us) before enabling the switch core. -	 */ -	err = readx_poll_timeout(ocelot_mem_init_status, ocelot, val, !val, -				 MEM_INIT_SLEEP_US, MEM_INIT_TIMEOUT_US); -	if (err) -		return err; - -	err = regmap_field_write(ocelot->regfields[SYS_RESET_CFG_MEM_ENA], 1); -	if (err) -		return err; - -	return regmap_field_write(ocelot->regfields[SYS_RESET_CFG_CORE_ENA], 1); -} - -/* Watermark encode - * Bit 8:   Unit; 0:1, 1:16 - * Bit 7-0: Value to be multiplied with unit - */ -static u16 ocelot_wm_enc(u16 value) -{ -	WARN_ON(value >= 16 * BIT(8)); - -	if (value >= BIT(8)) -		return BIT(8) | (value / 16); - -	return value; -} - -static u16 ocelot_wm_dec(u16 wm) -{ -	if (wm & BIT(8)) -		return (wm & GENMASK(7, 0)) * 16; - -	return wm; -} - -static void ocelot_wm_stat(u32 val, u32 *inuse, u32 *maxuse) -{ -	*inuse = (val & GENMASK(23, 12)) >> 12; -	*maxuse = val & GENMASK(11, 0); -} -  static const struct ocelot_ops ocelot_ops = {  	.reset			= ocelot_reset,  	.wm_enc			= ocelot_wm_enc, @@ -271,49 +125,6 @@ static const struct ocelot_ops ocelot_ops = {  	.netdev_to_port		= ocelot_netdev_to_port,  }; -static struct vcap_props vsc7514_vcap_props[] = { -	[VCAP_ES0] = { -		.action_type_width = 0, -		.action_table = { -			[ES0_ACTION_TYPE_NORMAL] = { -				.width = 73, /* HIT_STICKY not included */ -				.count = 1, -			}, -		}, -		.target = S0, -		.keys = vsc7514_vcap_es0_keys, -		.actions = vsc7514_vcap_es0_actions, -	}, -	[VCAP_IS1] = { -		.action_type_width = 0, -		.action_table = { -			[IS1_ACTION_TYPE_NORMAL] = { -				.width = 78, /* HIT_STICKY not included */ -				.count = 4, -			}, -		}, -		.target = S1, -		.keys = vsc7514_vcap_is1_keys, -		.actions = vsc7514_vcap_is1_actions, -	}, -	[VCAP_IS2] = { -		.action_type_width = 1, -		.action_table = { -			[IS2_ACTION_TYPE_NORMAL] = { -				.width = 49, -				.count = 2 -			}, -			[IS2_ACTION_TYPE_SMAC_SIP] = { -				.width = 6, -				.count = 4 -			}, -		}, -		.target = S2, -		.keys = vsc7514_vcap_is2_keys, -		.actions = vsc7514_vcap_is2_actions, -	}, -}; -  static struct ptp_clock_info ocelot_ptp_clock_info = {  	.owner		= THIS_MODULE,  	.name		= "ocelot ptp", @@ -377,9 +188,6 @@ static int mscc_ocelot_init_ports(struct platform_device *pdev,  		return -ENOMEM;  	for_each_available_child_of_node(ports, portnp) { -		struct ocelot_port_private *priv; -		struct ocelot_port *ocelot_port; -		struct devlink_port *dlp;  		struct regmap *target;  		struct resource *res;  		char res_name[8]; @@ -420,12 +228,6 @@ static int mscc_ocelot_init_ports(struct platform_device *pdev,  		}  		devlink_ports_registered |= BIT(port); - -		ocelot_port = ocelot->ports[port]; -		priv = container_of(ocelot_port, struct ocelot_port_private, -				    port); -		dlp = &ocelot->devlink_ports[port]; -		devlink_port_type_eth_set(dlp, priv->dev);  	}  	/* Initialize unused devlink ports at the end */ diff --git a/drivers/net/ethernet/mscc/vsc7514_regs.c b/drivers/net/ethernet/mscc/vsc7514_regs.c index 9d2d3e13cacf..ef6fd3f6be30 100644 --- a/drivers/net/ethernet/mscc/vsc7514_regs.c +++ b/drivers/net/ethernet/mscc/vsc7514_regs.c @@ -9,7 +9,66 @@  #include <soc/mscc/vsc7514_regs.h>  #include "ocelot.h" -const u32 vsc7514_ana_regmap[] = { +const struct reg_field vsc7514_regfields[REGFIELD_MAX] = { +	[ANA_ADVLEARN_VLAN_CHK] = REG_FIELD(ANA_ADVLEARN, 11, 11), +	[ANA_ADVLEARN_LEARN_MIRROR] = REG_FIELD(ANA_ADVLEARN, 0, 10), +	[ANA_ANEVENTS_MSTI_DROP] = REG_FIELD(ANA_ANEVENTS, 27, 27), +	[ANA_ANEVENTS_ACLKILL] = REG_FIELD(ANA_ANEVENTS, 26, 26), +	[ANA_ANEVENTS_ACLUSED] = REG_FIELD(ANA_ANEVENTS, 25, 25), +	[ANA_ANEVENTS_AUTOAGE] = REG_FIELD(ANA_ANEVENTS, 24, 24), +	[ANA_ANEVENTS_VS2TTL1] = REG_FIELD(ANA_ANEVENTS, 23, 23), +	[ANA_ANEVENTS_STORM_DROP] = REG_FIELD(ANA_ANEVENTS, 22, 22), +	[ANA_ANEVENTS_LEARN_DROP] = REG_FIELD(ANA_ANEVENTS, 21, 21), +	[ANA_ANEVENTS_AGED_ENTRY] = REG_FIELD(ANA_ANEVENTS, 20, 20), +	[ANA_ANEVENTS_CPU_LEARN_FAILED] = REG_FIELD(ANA_ANEVENTS, 19, 19), +	[ANA_ANEVENTS_AUTO_LEARN_FAILED] = REG_FIELD(ANA_ANEVENTS, 18, 18), +	[ANA_ANEVENTS_LEARN_REMOVE] = REG_FIELD(ANA_ANEVENTS, 17, 17), +	[ANA_ANEVENTS_AUTO_LEARNED] = REG_FIELD(ANA_ANEVENTS, 16, 16), +	[ANA_ANEVENTS_AUTO_MOVED] = REG_FIELD(ANA_ANEVENTS, 15, 15), +	[ANA_ANEVENTS_DROPPED] = REG_FIELD(ANA_ANEVENTS, 14, 14), +	[ANA_ANEVENTS_CLASSIFIED_DROP] = REG_FIELD(ANA_ANEVENTS, 13, 13), +	[ANA_ANEVENTS_CLASSIFIED_COPY] = REG_FIELD(ANA_ANEVENTS, 12, 12), +	[ANA_ANEVENTS_VLAN_DISCARD] = REG_FIELD(ANA_ANEVENTS, 11, 11), +	[ANA_ANEVENTS_FWD_DISCARD] = REG_FIELD(ANA_ANEVENTS, 10, 10), +	[ANA_ANEVENTS_MULTICAST_FLOOD] = REG_FIELD(ANA_ANEVENTS, 9, 9), +	[ANA_ANEVENTS_UNICAST_FLOOD] = REG_FIELD(ANA_ANEVENTS, 8, 8), +	[ANA_ANEVENTS_DEST_KNOWN] = REG_FIELD(ANA_ANEVENTS, 7, 7), +	[ANA_ANEVENTS_BUCKET3_MATCH] = REG_FIELD(ANA_ANEVENTS, 6, 6), +	[ANA_ANEVENTS_BUCKET2_MATCH] = REG_FIELD(ANA_ANEVENTS, 5, 5), +	[ANA_ANEVENTS_BUCKET1_MATCH] = REG_FIELD(ANA_ANEVENTS, 4, 4), +	[ANA_ANEVENTS_BUCKET0_MATCH] = REG_FIELD(ANA_ANEVENTS, 3, 3), +	[ANA_ANEVENTS_CPU_OPERATION] = REG_FIELD(ANA_ANEVENTS, 2, 2), +	[ANA_ANEVENTS_DMAC_LOOKUP] = REG_FIELD(ANA_ANEVENTS, 1, 1), +	[ANA_ANEVENTS_SMAC_LOOKUP] = REG_FIELD(ANA_ANEVENTS, 0, 0), +	[ANA_TABLES_MACACCESS_B_DOM] = REG_FIELD(ANA_TABLES_MACACCESS, 18, 18), +	[ANA_TABLES_MACTINDX_BUCKET] = REG_FIELD(ANA_TABLES_MACTINDX, 10, 11), +	[ANA_TABLES_MACTINDX_M_INDEX] = REG_FIELD(ANA_TABLES_MACTINDX, 0, 9), +	[QSYS_TIMED_FRAME_ENTRY_TFRM_VLD] = REG_FIELD(QSYS_TIMED_FRAME_ENTRY, 20, 20), +	[QSYS_TIMED_FRAME_ENTRY_TFRM_FP] = REG_FIELD(QSYS_TIMED_FRAME_ENTRY, 8, 19), +	[QSYS_TIMED_FRAME_ENTRY_TFRM_PORTNO] = REG_FIELD(QSYS_TIMED_FRAME_ENTRY, 4, 7), +	[QSYS_TIMED_FRAME_ENTRY_TFRM_TM_SEL] = REG_FIELD(QSYS_TIMED_FRAME_ENTRY, 1, 3), +	[QSYS_TIMED_FRAME_ENTRY_TFRM_TM_T] = REG_FIELD(QSYS_TIMED_FRAME_ENTRY, 0, 0), +	[SYS_RESET_CFG_CORE_ENA] = REG_FIELD(SYS_RESET_CFG, 2, 2), +	[SYS_RESET_CFG_MEM_ENA] = REG_FIELD(SYS_RESET_CFG, 1, 1), +	[SYS_RESET_CFG_MEM_INIT] = REG_FIELD(SYS_RESET_CFG, 0, 0), +	/* Replicated per number of ports (12), register size 4 per port */ +	[QSYS_SWITCH_PORT_MODE_PORT_ENA] = REG_FIELD_ID(QSYS_SWITCH_PORT_MODE, 14, 14, 12, 4), +	[QSYS_SWITCH_PORT_MODE_SCH_NEXT_CFG] = REG_FIELD_ID(QSYS_SWITCH_PORT_MODE, 11, 13, 12, 4), +	[QSYS_SWITCH_PORT_MODE_YEL_RSRVD] = REG_FIELD_ID(QSYS_SWITCH_PORT_MODE, 10, 10, 12, 4), +	[QSYS_SWITCH_PORT_MODE_INGRESS_DROP_MODE] = REG_FIELD_ID(QSYS_SWITCH_PORT_MODE, 9, 9, 12, 4), +	[QSYS_SWITCH_PORT_MODE_TX_PFC_ENA] = REG_FIELD_ID(QSYS_SWITCH_PORT_MODE, 1, 8, 12, 4), +	[QSYS_SWITCH_PORT_MODE_TX_PFC_MODE] = REG_FIELD_ID(QSYS_SWITCH_PORT_MODE, 0, 0, 12, 4), +	[SYS_PORT_MODE_DATA_WO_TS] = REG_FIELD_ID(SYS_PORT_MODE, 5, 6, 12, 4), +	[SYS_PORT_MODE_INCL_INJ_HDR] = REG_FIELD_ID(SYS_PORT_MODE, 3, 4, 12, 4), +	[SYS_PORT_MODE_INCL_XTR_HDR] = REG_FIELD_ID(SYS_PORT_MODE, 1, 2, 12, 4), +	[SYS_PORT_MODE_INCL_HDR_ERR] = REG_FIELD_ID(SYS_PORT_MODE, 0, 0, 12, 4), +	[SYS_PAUSE_CFG_PAUSE_START] = REG_FIELD_ID(SYS_PAUSE_CFG, 10, 18, 12, 4), +	[SYS_PAUSE_CFG_PAUSE_STOP] = REG_FIELD_ID(SYS_PAUSE_CFG, 1, 9, 12, 4), +	[SYS_PAUSE_CFG_PAUSE_ENA] = REG_FIELD_ID(SYS_PAUSE_CFG, 0, 1, 12, 4), +}; +EXPORT_SYMBOL(vsc7514_regfields); + +static const u32 vsc7514_ana_regmap[] = {  	REG(ANA_ADVLEARN,				0x009000),  	REG(ANA_VLANMASK,				0x009004),  	REG(ANA_PORT_B_DOMAIN,				0x009008), @@ -89,9 +148,8 @@ const u32 vsc7514_ana_regmap[] = {  	REG(ANA_POL_HYST,				0x008bec),  	REG(ANA_POL_MISC_CFG,				0x008bf0),  }; -EXPORT_SYMBOL(vsc7514_ana_regmap); -const u32 vsc7514_qs_regmap[] = { +static const u32 vsc7514_qs_regmap[] = {  	REG(QS_XTR_GRP_CFG,				0x000000),  	REG(QS_XTR_RD,					0x000008),  	REG(QS_XTR_FRM_PRUNING,				0x000010), @@ -105,9 +163,8 @@ const u32 vsc7514_qs_regmap[] = {  	REG(QS_INJ_ERR,					0x000040),  	REG(QS_INH_DBG,					0x000048),  }; -EXPORT_SYMBOL(vsc7514_qs_regmap); -const u32 vsc7514_qsys_regmap[] = { +static const u32 vsc7514_qsys_regmap[] = {  	REG(QSYS_PORT_MODE,				0x011200),  	REG(QSYS_SWITCH_PORT_MODE,			0x011234),  	REG(QSYS_STAT_CNT_CFG,				0x011264), @@ -150,9 +207,8 @@ const u32 vsc7514_qsys_regmap[] = {  	REG(QSYS_SE_STATE,				0x00004c),  	REG(QSYS_HSCH_MISC_CFG,				0x011388),  }; -EXPORT_SYMBOL(vsc7514_qsys_regmap); -const u32 vsc7514_rew_regmap[] = { +static const u32 vsc7514_rew_regmap[] = {  	REG(REW_PORT_VLAN_CFG,				0x000000),  	REG(REW_TAG_CFG,				0x000004),  	REG(REW_PORT_CFG,				0x000008), @@ -165,9 +221,8 @@ const u32 vsc7514_rew_regmap[] = {  	REG(REW_STAT_CFG,				0x000890),  	REG(REW_PPT,					0x000680),  }; -EXPORT_SYMBOL(vsc7514_rew_regmap); -const u32 vsc7514_sys_regmap[] = { +static const u32 vsc7514_sys_regmap[] = {  	REG(SYS_COUNT_RX_OCTETS,			0x000000),  	REG(SYS_COUNT_RX_UNICAST,			0x000004),  	REG(SYS_COUNT_RX_MULTICAST,			0x000008), @@ -288,9 +343,8 @@ const u32 vsc7514_sys_regmap[] = {  	REG(SYS_PTP_NXT,				0x0006c0),  	REG(SYS_PTP_CFG,				0x0006c4),  }; -EXPORT_SYMBOL(vsc7514_sys_regmap); -const u32 vsc7514_vcap_regmap[] = { +static const u32 vsc7514_vcap_regmap[] = {  	/* VCAP_CORE_CFG */  	REG(VCAP_CORE_UPDATE_CTRL,			0x000000),  	REG(VCAP_CORE_MV_CFG,				0x000004), @@ -312,9 +366,8 @@ const u32 vsc7514_vcap_regmap[] = {  	REG(VCAP_CONST_CORE_CNT,			0x0003b8),  	REG(VCAP_CONST_IF_CNT,				0x0003bc),  }; -EXPORT_SYMBOL(vsc7514_vcap_regmap); -const u32 vsc7514_ptp_regmap[] = { +static const u32 vsc7514_ptp_regmap[] = {  	REG(PTP_PIN_CFG,				0x000000),  	REG(PTP_PIN_TOD_SEC_MSB,			0x000004),  	REG(PTP_PIN_TOD_SEC_LSB,			0x000008), @@ -325,9 +378,8 @@ const u32 vsc7514_ptp_regmap[] = {  	REG(PTP_CLK_CFG_ADJ_CFG,			0x0000a4),  	REG(PTP_CLK_CFG_ADJ_FREQ,			0x0000a8),  }; -EXPORT_SYMBOL(vsc7514_ptp_regmap); -const u32 vsc7514_dev_gmii_regmap[] = { +static const u32 vsc7514_dev_gmii_regmap[] = {  	REG(DEV_CLOCK_CFG,				0x0),  	REG(DEV_PORT_MISC,				0x4),  	REG(DEV_EVENTS,					0x8), @@ -368,9 +420,22 @@ const u32 vsc7514_dev_gmii_regmap[] = {  	REG(DEV_PCS_FX100_CFG,				0x94),  	REG(DEV_PCS_FX100_STATUS,			0x98),  }; -EXPORT_SYMBOL(vsc7514_dev_gmii_regmap); -const struct vcap_field vsc7514_vcap_es0_keys[] = { +const u32 *vsc7514_regmap[TARGET_MAX] = { +	[ANA] = vsc7514_ana_regmap, +	[QS] = vsc7514_qs_regmap, +	[QSYS] = vsc7514_qsys_regmap, +	[REW] = vsc7514_rew_regmap, +	[SYS] = vsc7514_sys_regmap, +	[S0] = vsc7514_vcap_regmap, +	[S1] = vsc7514_vcap_regmap, +	[S2] = vsc7514_vcap_regmap, +	[PTP] = vsc7514_ptp_regmap, +	[DEV_GMII] = vsc7514_dev_gmii_regmap, +}; +EXPORT_SYMBOL(vsc7514_regmap); + +static const struct vcap_field vsc7514_vcap_es0_keys[] = {  	[VCAP_ES0_EGR_PORT]			= { 0,   4 },  	[VCAP_ES0_IGR_PORT]			= { 4,   4 },  	[VCAP_ES0_RSV]				= { 8,   2 }, @@ -380,9 +445,8 @@ const struct vcap_field vsc7514_vcap_es0_keys[] = {  	[VCAP_ES0_DP]				= { 24,  1 },  	[VCAP_ES0_PCP]				= { 25,  3 },  }; -EXPORT_SYMBOL(vsc7514_vcap_es0_keys); -const struct vcap_field vsc7514_vcap_es0_actions[]   = { +static const struct vcap_field vsc7514_vcap_es0_actions[]   = {  	[VCAP_ES0_ACT_PUSH_OUTER_TAG]		= { 0,   2 },  	[VCAP_ES0_ACT_PUSH_INNER_TAG]		= { 2,   1 },  	[VCAP_ES0_ACT_TAG_A_TPID_SEL]		= { 3,   2 }, @@ -402,9 +466,8 @@ const struct vcap_field vsc7514_vcap_es0_actions[]   = {  	[VCAP_ES0_ACT_RSV]			= { 49, 24 },  	[VCAP_ES0_ACT_HIT_STICKY]		= { 73,  1 },  }; -EXPORT_SYMBOL(vsc7514_vcap_es0_actions); -const struct vcap_field vsc7514_vcap_is1_keys[] = { +static const struct vcap_field vsc7514_vcap_is1_keys[] = {  	[VCAP_IS1_HK_TYPE]			= { 0,    1 },  	[VCAP_IS1_HK_LOOKUP]			= { 1,    2 },  	[VCAP_IS1_HK_IGR_PORT_MASK]		= { 3,   12 }, @@ -454,9 +517,8 @@ const struct vcap_field vsc7514_vcap_is1_keys[] = {  	[VCAP_IS1_HK_IP4_L4_RNG]		= { 148,  8 },  	[VCAP_IS1_HK_IP4_IP_PAYLOAD_S1_5TUPLE]	= { 156, 32 },  }; -EXPORT_SYMBOL(vsc7514_vcap_is1_keys); -const struct vcap_field vsc7514_vcap_is1_actions[] = { +static const struct vcap_field vsc7514_vcap_is1_actions[] = {  	[VCAP_IS1_ACT_DSCP_ENA]			= { 0,   1 },  	[VCAP_IS1_ACT_DSCP_VAL]			= { 1,   6 },  	[VCAP_IS1_ACT_QOS_ENA]			= { 7,   1 }, @@ -479,9 +541,8 @@ const struct vcap_field vsc7514_vcap_is1_actions[] = {  	[VCAP_IS1_ACT_CUSTOM_ACE_TYPE_ENA]	= { 74,  4 },  	[VCAP_IS1_ACT_HIT_STICKY]		= { 78,  1 },  }; -EXPORT_SYMBOL(vsc7514_vcap_is1_actions); -const struct vcap_field vsc7514_vcap_is2_keys[] = { +static const struct vcap_field vsc7514_vcap_is2_keys[] = {  	/* Common: 46 bits */  	[VCAP_IS2_TYPE]				= { 0,    4 },  	[VCAP_IS2_HK_FIRST]			= { 4,    1 }, @@ -560,9 +621,8 @@ const struct vcap_field vsc7514_vcap_is2_keys[] = {  	[VCAP_IS2_HK_OAM_CCM_CNTS_EQ0]		= { 186,  1 },  	[VCAP_IS2_HK_OAM_IS_Y1731]		= { 187,  1 },  }; -EXPORT_SYMBOL(vsc7514_vcap_is2_keys); -const struct vcap_field vsc7514_vcap_is2_actions[] = { +static const struct vcap_field vsc7514_vcap_is2_actions[] = {  	[VCAP_IS2_ACT_HIT_ME_ONCE]		= { 0,   1 },  	[VCAP_IS2_ACT_CPU_COPY_ENA]		= { 1,   1 },  	[VCAP_IS2_ACT_CPU_QU_NUM]		= { 2,   3 }, @@ -579,4 +639,47 @@ const struct vcap_field vsc7514_vcap_is2_actions[] = {  	[VCAP_IS2_ACT_ACL_ID]			= { 43,  6 },  	[VCAP_IS2_ACT_HIT_CNT]			= { 49, 32 },  }; -EXPORT_SYMBOL(vsc7514_vcap_is2_actions); + +struct vcap_props vsc7514_vcap_props[] = { +	[VCAP_ES0] = { +		.action_type_width = 0, +		.action_table = { +			[ES0_ACTION_TYPE_NORMAL] = { +				.width = 73, /* HIT_STICKY not included */ +				.count = 1, +			}, +		}, +		.target = S0, +		.keys = vsc7514_vcap_es0_keys, +		.actions = vsc7514_vcap_es0_actions, +	}, +	[VCAP_IS1] = { +		.action_type_width = 0, +		.action_table = { +			[IS1_ACTION_TYPE_NORMAL] = { +				.width = 78, /* HIT_STICKY not included */ +				.count = 4, +			}, +		}, +		.target = S1, +		.keys = vsc7514_vcap_is1_keys, +		.actions = vsc7514_vcap_is1_actions, +	}, +	[VCAP_IS2] = { +		.action_type_width = 1, +		.action_table = { +			[IS2_ACTION_TYPE_NORMAL] = { +				.width = 49, +				.count = 2 +			}, +			[IS2_ACTION_TYPE_SMAC_SIP] = { +				.width = 6, +				.count = 4 +			}, +		}, +		.target = S2, +		.keys = vsc7514_vcap_is2_keys, +		.actions = vsc7514_vcap_is2_actions, +	}, +}; +EXPORT_SYMBOL(vsc7514_vcap_props);  |