diff options
Diffstat (limited to 'drivers/net/ethernet/mscc')
| -rw-r--r-- | drivers/net/ethernet/mscc/ocelot.c | 224 | ||||
| -rw-r--r-- | drivers/net/ethernet/mscc/ocelot.h | 12 | ||||
| -rw-r--r-- | drivers/net/ethernet/mscc/ocelot_ace.c | 619 | ||||
| -rw-r--r-- | drivers/net/ethernet/mscc/ocelot_ace.h | 30 | ||||
| -rw-r--r-- | drivers/net/ethernet/mscc/ocelot_board.c | 163 | ||||
| -rw-r--r-- | drivers/net/ethernet/mscc/ocelot_flower.c | 272 | ||||
| -rw-r--r-- | drivers/net/ethernet/mscc/ocelot_police.c | 27 | ||||
| -rw-r--r-- | drivers/net/ethernet/mscc/ocelot_police.h | 11 | ||||
| -rw-r--r-- | drivers/net/ethernet/mscc/ocelot_regs.c | 1 | ||||
| -rw-r--r-- | drivers/net/ethernet/mscc/ocelot_tc.c | 24 | ||||
| -rw-r--r-- | drivers/net/ethernet/mscc/ocelot_vcap.h | 403 | 
11 files changed, 761 insertions, 1025 deletions
| diff --git a/drivers/net/ethernet/mscc/ocelot.c b/drivers/net/ethernet/mscc/ocelot.c index d3b7373c5961..02350c3d9d01 100644 --- a/drivers/net/ethernet/mscc/ocelot.c +++ b/drivers/net/ethernet/mscc/ocelot.c @@ -183,44 +183,47 @@ static void ocelot_vlan_mode(struct ocelot *ocelot, int port,  	ocelot_write(ocelot, val, ANA_VLANMASK);  } -void ocelot_port_vlan_filtering(struct ocelot *ocelot, int port, -				bool vlan_aware) +static int ocelot_port_set_native_vlan(struct ocelot *ocelot, int port, +				       u16 vid)  {  	struct ocelot_port *ocelot_port = ocelot->ports[port]; -	u32 val; +	u32 val = 0; -	if (vlan_aware) -		val = ANA_PORT_VLAN_CFG_VLAN_AWARE_ENA | -		      ANA_PORT_VLAN_CFG_VLAN_POP_CNT(1); -	else -		val = 0; -	ocelot_rmw_gix(ocelot, val, -		       ANA_PORT_VLAN_CFG_VLAN_AWARE_ENA | -		       ANA_PORT_VLAN_CFG_VLAN_POP_CNT_M, -		       ANA_PORT_VLAN_CFG, port); +	if (ocelot_port->vid != vid) { +		/* Always permit deleting the native VLAN (vid = 0) */ +		if (ocelot_port->vid && vid) { +			dev_err(ocelot->dev, +				"Port already has a native VLAN: %d\n", +				ocelot_port->vid); +			return -EBUSY; +		} +		ocelot_port->vid = vid; +	} + +	ocelot_rmw_gix(ocelot, REW_PORT_VLAN_CFG_PORT_VID(vid), +		       REW_PORT_VLAN_CFG_PORT_VID_M, +		       REW_PORT_VLAN_CFG, port); -	if (vlan_aware && !ocelot_port->vid) +	if (ocelot_port->vlan_aware && !ocelot_port->vid)  		/* If port is vlan-aware and tagged, drop untagged and priority  		 * tagged frames.  		 */  		val = ANA_PORT_DROP_CFG_DROP_UNTAGGED_ENA |  		      ANA_PORT_DROP_CFG_DROP_PRIO_S_TAGGED_ENA |  		      ANA_PORT_DROP_CFG_DROP_PRIO_C_TAGGED_ENA; -	else -		val = 0;  	ocelot_rmw_gix(ocelot, val,  		       ANA_PORT_DROP_CFG_DROP_UNTAGGED_ENA |  		       ANA_PORT_DROP_CFG_DROP_PRIO_S_TAGGED_ENA |  		       ANA_PORT_DROP_CFG_DROP_PRIO_C_TAGGED_ENA,  		       ANA_PORT_DROP_CFG, port); -	if (vlan_aware) { +	if (ocelot_port->vlan_aware) {  		if (ocelot_port->vid)  			/* Tag all frames except when VID == DEFAULT_VLAN */ -			val |= REW_TAG_CFG_TAG_CFG(1); +			val = REW_TAG_CFG_TAG_CFG(1);  		else  			/* Tag all frames */ -			val |= REW_TAG_CFG_TAG_CFG(3); +			val = REW_TAG_CFG_TAG_CFG(3);  	} else {  		/* Port tagging disabled. */  		val = REW_TAG_CFG_TAG_CFG(0); @@ -228,31 +231,31 @@ void ocelot_port_vlan_filtering(struct ocelot *ocelot, int port,  	ocelot_rmw_gix(ocelot, val,  		       REW_TAG_CFG_TAG_CFG_M,  		       REW_TAG_CFG, port); + +	return 0;  } -EXPORT_SYMBOL(ocelot_port_vlan_filtering); -static int ocelot_port_set_native_vlan(struct ocelot *ocelot, int port, -				       u16 vid) +void ocelot_port_vlan_filtering(struct ocelot *ocelot, int port, +				bool vlan_aware)  {  	struct ocelot_port *ocelot_port = ocelot->ports[port]; +	u32 val; -	if (ocelot_port->vid != vid) { -		/* Always permit deleting the native VLAN (vid = 0) */ -		if (ocelot_port->vid && vid) { -			dev_err(ocelot->dev, -				"Port already has a native VLAN: %d\n", -				ocelot_port->vid); -			return -EBUSY; -		} -		ocelot_port->vid = vid; -	} +	ocelot_port->vlan_aware = vlan_aware; -	ocelot_rmw_gix(ocelot, REW_PORT_VLAN_CFG_PORT_VID(vid), -		       REW_PORT_VLAN_CFG_PORT_VID_M, -		       REW_PORT_VLAN_CFG, port); +	if (vlan_aware) +		val = ANA_PORT_VLAN_CFG_VLAN_AWARE_ENA | +		      ANA_PORT_VLAN_CFG_VLAN_POP_CNT(1); +	else +		val = 0; +	ocelot_rmw_gix(ocelot, val, +		       ANA_PORT_VLAN_CFG_VLAN_AWARE_ENA | +		       ANA_PORT_VLAN_CFG_VLAN_POP_CNT_M, +		       ANA_PORT_VLAN_CFG, port); -	return 0; +	ocelot_port_set_native_vlan(ocelot, port, ocelot_port->vid);  } +EXPORT_SYMBOL(ocelot_port_vlan_filtering);  /* Default vlan to clasify for untagged frames (may be zero) */  static void ocelot_port_set_pvid(struct ocelot *ocelot, int port, u16 pvid) @@ -442,8 +445,23 @@ void ocelot_adjust_link(struct ocelot *ocelot, int port,  	ocelot_port_writel(ocelot_port, DEV_MAC_MODE_CFG_FDX_ENA |  			   mode, DEV_MAC_MODE_CFG); -	if (ocelot->ops->pcs_init) -		ocelot->ops->pcs_init(ocelot, port); +	/* Disable HDX fast control */ +	ocelot_port_writel(ocelot_port, DEV_PORT_MISC_HDX_FAST_DIS, +			   DEV_PORT_MISC); + +	/* SGMII only for now */ +	ocelot_port_writel(ocelot_port, PCS1G_MODE_CFG_SGMII_MODE_ENA, +			   PCS1G_MODE_CFG); +	ocelot_port_writel(ocelot_port, PCS1G_SD_CFG_SD_SEL, PCS1G_SD_CFG); + +	/* Enable PCS */ +	ocelot_port_writel(ocelot_port, PCS1G_CFG_PCS_ENA, PCS1G_CFG); + +	/* No aneg on SGMII */ +	ocelot_port_writel(ocelot_port, 0, PCS1G_ANEG_CFG); + +	/* No loopback */ +	ocelot_port_writel(ocelot_port, 0, PCS1G_LB_CFG);  	/* Enable MAC module */  	ocelot_port_writel(ocelot_port, DEV_MAC_ENA_CFG_RX_ENA | @@ -858,12 +876,12 @@ static void ocelot_get_stats64(struct net_device *dev,  }  int ocelot_fdb_add(struct ocelot *ocelot, int port, -		   const unsigned char *addr, u16 vid, bool vlan_aware) +		   const unsigned char *addr, u16 vid)  {  	struct ocelot_port *ocelot_port = ocelot->ports[port];  	if (!vid) { -		if (!vlan_aware) +		if (!ocelot_port->vlan_aware)  			/* If the bridge is not VLAN aware and no VID was  			 * provided, set it to pvid to ensure the MAC entry  			 * matches incoming untagged packets @@ -890,7 +908,7 @@ static int ocelot_port_fdb_add(struct ndmsg *ndm, struct nlattr *tb[],  	struct ocelot *ocelot = priv->port.ocelot;  	int port = priv->chip_port; -	return ocelot_fdb_add(ocelot, port, addr, vid, priv->vlan_aware); +	return ocelot_fdb_add(ocelot, port, addr, vid);  }  int ocelot_fdb_del(struct ocelot *ocelot, int port, @@ -1013,10 +1031,8 @@ int ocelot_fdb_dump(struct ocelot *ocelot, int port,  {  	int i, j; -	/* Loop through all the mac tables entries. There are 1024 rows of 4 -	 * entries. -	 */ -	for (i = 0; i < 1024; i++) { +	/* Loop through all the mac tables entries. */ +	for (i = 0; i < ocelot->num_mact_rows; i++) {  		for (j = 0; j < 4; j++) {  			struct ocelot_mact_entry entry;  			bool is_static; @@ -1398,7 +1414,7 @@ void ocelot_bridge_stp_state_set(struct ocelot *ocelot, int port, u8 state)  	 * a source for the other ports.  	 */  	for (p = 0; p < ocelot->num_phys_ports; p++) { -		if (p == ocelot->cpu || (ocelot->bridge_fwd_mask & BIT(p))) { +		if (ocelot->bridge_fwd_mask & BIT(p)) {  			unsigned long mask = ocelot->bridge_fwd_mask & ~BIT(p);  			for (i = 0; i < ocelot->num_phys_ports; i++) { @@ -1413,18 +1429,10 @@ void ocelot_bridge_stp_state_set(struct ocelot *ocelot, int port, u8 state)  				}  			} -			/* Avoid the NPI port from looping back to itself */ -			if (p != ocelot->cpu) -				mask |= BIT(ocelot->cpu); -  			ocelot_write_rix(ocelot, mask,  					 ANA_PGID_PGID, PGID_SRC + p);  		} else { -			/* Only the CPU port, this is compatible with link -			 * aggregation. -			 */ -			ocelot_write_rix(ocelot, -					 BIT(ocelot->cpu), +			ocelot_write_rix(ocelot, 0,  					 ANA_PGID_PGID, PGID_SRC + p);  		}  	} @@ -1443,8 +1451,15 @@ static void ocelot_port_attr_stp_state_set(struct ocelot *ocelot, int port,  void ocelot_set_ageing_time(struct ocelot *ocelot, unsigned int msecs)  { -	ocelot_write(ocelot, ANA_AUTOAGE_AGE_PERIOD(msecs / 2), -		     ANA_AUTOAGE); +	unsigned int age_period = ANA_AUTOAGE_AGE_PERIOD(msecs / 2000); + +	/* Setting AGE_PERIOD to zero effectively disables automatic aging, +	 * which is clearly not what our intention is. So avoid that. +	 */ +	if (!age_period) +		age_period = 1; + +	ocelot_rmw(ocelot, age_period, ANA_AUTOAGE_AGE_PERIOD_M, ANA_AUTOAGE);  }  EXPORT_SYMBOL(ocelot_set_ageing_time); @@ -1489,8 +1504,8 @@ static int ocelot_port_attr_set(struct net_device *dev,  		ocelot_port_attr_ageing_set(ocelot, port, attr->u.ageing_time);  		break;  	case SWITCHDEV_ATTR_ID_BRIDGE_VLAN_FILTERING: -		priv->vlan_aware = attr->u.vlan_filtering; -		ocelot_port_vlan_filtering(ocelot, port, priv->vlan_aware); +		ocelot_port_vlan_filtering(ocelot, port, +					   attr->u.vlan_filtering);  		break;  	case SWITCHDEV_ATTR_ID_BRIDGE_MC_DISABLED:  		ocelot_port_attr_mc_set(ocelot, port, !attr->u.mc_disabled); @@ -1861,7 +1876,6 @@ static int ocelot_netdevice_port_event(struct net_device *dev,  			} else {  				err = ocelot_port_bridge_leave(ocelot, port,  							       info->upper_dev); -				priv->vlan_aware = false;  			}  		}  		if (netif_is_lag_master(info->upper_dev)) { @@ -2178,13 +2192,25 @@ static int ocelot_init_timestamp(struct ocelot *ocelot)  /* Configure the maximum SDU (L2 payload) on RX to the value specified in @sdu.   * The length of VLAN tags is accounted for automatically via DEV_MAC_TAGS_CFG. + * In the special case that it's the NPI port that we're configuring, the + * length of the tag and optional prefix needs to be accounted for privately, + * in order to be able to sustain communication at the requested @sdu.   */ -static void ocelot_port_set_maxlen(struct ocelot *ocelot, int port, size_t sdu) +void ocelot_port_set_maxlen(struct ocelot *ocelot, int port, size_t sdu)  {  	struct ocelot_port *ocelot_port = ocelot->ports[port];  	int maxlen = sdu + ETH_HLEN + ETH_FCS_LEN;  	int atop_wm; +	if (port == ocelot->npi) { +		maxlen += OCELOT_TAG_LEN; + +		if (ocelot->inj_prefix == OCELOT_TAG_PREFIX_SHORT) +			maxlen += OCELOT_SHORT_PREFIX_LEN; +		else if (ocelot->inj_prefix == OCELOT_TAG_PREFIX_LONG) +			maxlen += OCELOT_LONG_PREFIX_LEN; +	} +  	ocelot_port_writel(ocelot_port, maxlen, DEV_MAC_MAXLEN_CFG);  	/* Set Pause WM hysteresis @@ -2202,6 +2228,24 @@ static void ocelot_port_set_maxlen(struct ocelot *ocelot, int port, size_t sdu)  			 SYS_ATOP, port);  	ocelot_write(ocelot, ocelot_wm_enc(atop_wm), SYS_ATOP_TOT_CFG);  } +EXPORT_SYMBOL(ocelot_port_set_maxlen); + +int ocelot_get_max_mtu(struct ocelot *ocelot, int port) +{ +	int max_mtu = 65535 - ETH_HLEN - ETH_FCS_LEN; + +	if (port == ocelot->npi) { +		max_mtu -= OCELOT_TAG_LEN; + +		if (ocelot->inj_prefix == OCELOT_TAG_PREFIX_SHORT) +			max_mtu -= OCELOT_SHORT_PREFIX_LEN; +		else if (ocelot->inj_prefix == OCELOT_TAG_PREFIX_LONG) +			max_mtu -= OCELOT_LONG_PREFIX_LEN; +	} + +	return max_mtu; +} +EXPORT_SYMBOL(ocelot_get_max_mtu);  void ocelot_init_port(struct ocelot *ocelot, int port)  { @@ -2299,42 +2343,57 @@ int ocelot_probe_port(struct ocelot *ocelot, u8 port,  }  EXPORT_SYMBOL(ocelot_probe_port); -void ocelot_set_cpu_port(struct ocelot *ocelot, int cpu, -			 enum ocelot_tag_prefix injection, -			 enum ocelot_tag_prefix extraction) +/* Configure and enable the CPU port module, which is a set of queues. + * If @npi contains a valid port index, the CPU port module is connected + * to the Node Processor Interface (NPI). This is the mode through which + * frames can be injected from and extracted to an external CPU, + * over Ethernet. + */ +void ocelot_configure_cpu(struct ocelot *ocelot, int npi, +			  enum ocelot_tag_prefix injection, +			  enum ocelot_tag_prefix extraction)  { -	/* Configure and enable the CPU port. */ +	int cpu = ocelot->num_phys_ports; + +	ocelot->npi = npi; +	ocelot->inj_prefix = injection; +	ocelot->xtr_prefix = extraction; + +	/* The unicast destination PGID for the CPU port module is unused */  	ocelot_write_rix(ocelot, 0, ANA_PGID_PGID, cpu); +	/* Instead set up a multicast destination PGID for traffic copied to +	 * the CPU. Whitelisted MAC addresses like the port netdevice MAC +	 * addresses will be copied to the CPU via this PGID. +	 */  	ocelot_write_rix(ocelot, BIT(cpu), ANA_PGID_PGID, PGID_CPU);  	ocelot_write_gix(ocelot, ANA_PORT_PORT_CFG_RECV_ENA |  			 ANA_PORT_PORT_CFG_PORTID_VAL(cpu),  			 ANA_PORT_PORT_CFG, cpu); -	/* If the CPU port is a physical port, set up the port in Node -	 * Processor Interface (NPI) mode. This is the mode through which -	 * frames can be injected from and extracted to an external CPU. -	 * Only one port can be an NPI at the same time. -	 */ -	if (cpu < ocelot->num_phys_ports) { -		int sdu = ETH_DATA_LEN + OCELOT_TAG_LEN; - +	if (npi >= 0 && npi < ocelot->num_phys_ports) {  		ocelot_write(ocelot, QSYS_EXT_CPU_CFG_EXT_CPUQ_MSK_M | -			     QSYS_EXT_CPU_CFG_EXT_CPU_PORT(cpu), +			     QSYS_EXT_CPU_CFG_EXT_CPU_PORT(npi),  			     QSYS_EXT_CPU_CFG); -		if (injection == OCELOT_TAG_PREFIX_SHORT) -			sdu += OCELOT_SHORT_PREFIX_LEN; -		else if (injection == OCELOT_TAG_PREFIX_LONG) -			sdu += OCELOT_LONG_PREFIX_LEN; - -		ocelot_port_set_maxlen(ocelot, cpu, sdu); +		/* Enable NPI port */ +		ocelot_write_rix(ocelot, +				 QSYS_SWITCH_PORT_MODE_INGRESS_DROP_MODE | +				 QSYS_SWITCH_PORT_MODE_SCH_NEXT_CFG(1) | +				 QSYS_SWITCH_PORT_MODE_PORT_ENA, +				 QSYS_SWITCH_PORT_MODE, npi); +		/* NPI port Injection/Extraction configuration */ +		ocelot_write_rix(ocelot, +				 SYS_PORT_MODE_INCL_XTR_HDR(extraction) | +				 SYS_PORT_MODE_INCL_INJ_HDR(injection), +				 SYS_PORT_MODE, npi);  	} -	/* CPU port Injection/Extraction configuration */ +	/* Enable CPU port module */  	ocelot_write_rix(ocelot, QSYS_SWITCH_PORT_MODE_INGRESS_DROP_MODE |  			 QSYS_SWITCH_PORT_MODE_SCH_NEXT_CFG(1) |  			 QSYS_SWITCH_PORT_MODE_PORT_ENA,  			 QSYS_SWITCH_PORT_MODE, cpu); +	/* CPU port Injection/Extraction configuration */  	ocelot_write_rix(ocelot, SYS_PORT_MODE_INCL_XTR_HDR(extraction) |  			 SYS_PORT_MODE_INCL_INJ_HDR(injection),  			 SYS_PORT_MODE, cpu); @@ -2344,10 +2403,8 @@ void ocelot_set_cpu_port(struct ocelot *ocelot, int cpu,  				 ANA_PORT_VLAN_CFG_VLAN_AWARE_ENA |  				 ANA_PORT_VLAN_CFG_VLAN_POP_CNT(1),  			 ANA_PORT_VLAN_CFG, cpu); - -	ocelot->cpu = cpu;  } -EXPORT_SYMBOL(ocelot_set_cpu_port); +EXPORT_SYMBOL(ocelot_configure_cpu);  int ocelot_init(struct ocelot *ocelot)  { @@ -2499,7 +2556,6 @@ void ocelot_deinit(struct ocelot *ocelot)  	cancel_delayed_work(&ocelot->stats_work);  	destroy_workqueue(ocelot->stats_queue);  	mutex_destroy(&ocelot->stats_lock); -	ocelot_ace_deinit();  	if (ocelot->ptp_clock)  		ptp_clock_unregister(ocelot->ptp_clock); diff --git a/drivers/net/ethernet/mscc/ocelot.h b/drivers/net/ethernet/mscc/ocelot.h index 04372ba72fec..641af929497f 100644 --- a/drivers/net/ethernet/mscc/ocelot.h +++ b/drivers/net/ethernet/mscc/ocelot.h @@ -28,16 +28,6 @@  #include "ocelot_tc.h"  #include "ocelot_ptp.h" -#define PGID_AGGR    64 -#define PGID_SRC     80 - -/* Reserved PGIDs */ -#define PGID_CPU     (PGID_AGGR - 5) -#define PGID_UC      (PGID_AGGR - 4) -#define PGID_MC      (PGID_AGGR - 3) -#define PGID_MCIPV4  (PGID_AGGR - 2) -#define PGID_MCIPV6  (PGID_AGGR - 1) -  #define OCELOT_BUFFER_CELL_SZ 60  #define OCELOT_STATS_CHECK_DELAY (2 * HZ) @@ -66,8 +56,6 @@ struct ocelot_port_private {  	struct phy_device *phy;  	u8 chip_port; -	u8 vlan_aware; -  	struct phy *serdes;  	struct ocelot_port_tc tc; diff --git a/drivers/net/ethernet/mscc/ocelot_ace.c b/drivers/net/ethernet/mscc/ocelot_ace.c index 86fc6e6b46dd..3bd286044480 100644 --- a/drivers/net/ethernet/mscc/ocelot_ace.c +++ b/drivers/net/ethernet/mscc/ocelot_ace.c @@ -6,60 +6,13 @@  #include <linux/iopoll.h>  #include <linux/proc_fs.h> +#include <soc/mscc/ocelot_vcap.h> +#include "ocelot_police.h"  #include "ocelot_ace.h" -#include "ocelot_vcap.h"  #include "ocelot_s2.h"  #define OCELOT_POLICER_DISCARD 0x17f - -static struct ocelot_acl_block *acl_block; - -struct vcap_props { -	const char *name; /* Symbolic name */ -	u16 tg_width; /* Type-group width (in bits) */ -	u16 sw_count; /* Sub word count */ -	u16 entry_count; /* Entry count */ -	u16 entry_words; /* Number of entry words */ -	u16 entry_width; /* Entry width (in bits) */ -	u16 action_count; /* Action count */ -	u16 action_words; /* Number of action words */ -	u16 action_width; /* Action width (in bits) */ -	u16 action_type_width; /* Action type width (in bits) */ -	struct { -		u16 width; /* Action type width (in bits) */ -		u16 count; /* Action type sub word count */ -	} action_table[2]; -	u16 counter_words; /* Number of counter words */ -	u16 counter_width; /* Counter width (in bits) */ -}; -  #define ENTRY_WIDTH 32 -#define BITS_TO_32BIT(x) (1 + (((x) - 1) / ENTRY_WIDTH)) - -static const struct vcap_props vcap_is2 = { -	.name = "IS2", -	.tg_width = 2, -	.sw_count = 4, -	.entry_count = VCAP_IS2_CNT, -	.entry_words = BITS_TO_32BIT(VCAP_IS2_ENTRY_WIDTH), -	.entry_width = VCAP_IS2_ENTRY_WIDTH, -	.action_count = (VCAP_IS2_CNT + VCAP_PORT_CNT + 2), -	.action_words = BITS_TO_32BIT(VCAP_IS2_ACTION_WIDTH), -	.action_width = (VCAP_IS2_ACTION_WIDTH), -	.action_type_width = 1, -	.action_table = { -		{ -			.width = (IS2_AO_ACL_ID + IS2_AL_ACL_ID), -			.count = 2 -		}, -		{ -			.width = 6, -			.count = 4 -		}, -	}, -	.counter_words = BITS_TO_32BIT(4 * ENTRY_WIDTH), -	.counter_width = ENTRY_WIDTH, -};  enum vcap_sel {  	VCAP_SEL_ENTRY = 0x1, @@ -95,18 +48,20 @@ struct vcap_data {  	u32 tg_mask; /* Current type-group mask */  }; -static u32 vcap_s2_read_update_ctrl(struct ocelot *oc) +static u32 vcap_s2_read_update_ctrl(struct ocelot *ocelot)  { -	return ocelot_read(oc, S2_CORE_UPDATE_CTRL); +	return ocelot_read(ocelot, S2_CORE_UPDATE_CTRL);  } -static void vcap_cmd(struct ocelot *oc, u16 ix, int cmd, int sel) +static void vcap_cmd(struct ocelot *ocelot, u16 ix, int cmd, int sel)  { +	const struct vcap_props *vcap_is2 = &ocelot->vcap[VCAP_IS2]; +  	u32 value = (S2_CORE_UPDATE_CTRL_UPDATE_CMD(cmd) |  		     S2_CORE_UPDATE_CTRL_UPDATE_ADDR(ix) |  		     S2_CORE_UPDATE_CTRL_UPDATE_SHOT); -	if ((sel & VCAP_SEL_ENTRY) && ix >= vcap_is2.entry_count) +	if ((sel & VCAP_SEL_ENTRY) && ix >= vcap_is2->entry_count)  		return;  	if (!(sel & VCAP_SEL_ENTRY)) @@ -118,83 +73,101 @@ static void vcap_cmd(struct ocelot *oc, u16 ix, int cmd, int sel)  	if (!(sel & VCAP_SEL_COUNTER))  		value |= S2_CORE_UPDATE_CTRL_UPDATE_CNT_DIS; -	ocelot_write(oc, value, S2_CORE_UPDATE_CTRL); -	readx_poll_timeout(vcap_s2_read_update_ctrl, oc, value, +	ocelot_write(ocelot, value, S2_CORE_UPDATE_CTRL); +	readx_poll_timeout(vcap_s2_read_update_ctrl, ocelot, value,  				(value & S2_CORE_UPDATE_CTRL_UPDATE_SHOT) == 0,  				10, 100000);  }  /* Convert from 0-based row to VCAP entry row and run command */ -static void vcap_row_cmd(struct ocelot *oc, u32 row, int cmd, int sel) +static void vcap_row_cmd(struct ocelot *ocelot, u32 row, int cmd, int sel)  { -	vcap_cmd(oc, vcap_is2.entry_count - row - 1, cmd, sel); +	const struct vcap_props *vcap_is2 = &ocelot->vcap[VCAP_IS2]; + +	vcap_cmd(ocelot, vcap_is2->entry_count - row - 1, cmd, sel);  } -static void vcap_entry2cache(struct ocelot *oc, struct vcap_data *data) +static void vcap_entry2cache(struct ocelot *ocelot, struct vcap_data *data)  { -	u32 i; +	const struct vcap_props *vcap_is2 = &ocelot->vcap[VCAP_IS2]; +	u32 entry_words, i; -	for (i = 0; i < vcap_is2.entry_words; i++) { -		ocelot_write_rix(oc, data->entry[i], S2_CACHE_ENTRY_DAT, i); -		ocelot_write_rix(oc, ~data->mask[i], S2_CACHE_MASK_DAT, i); +	entry_words = DIV_ROUND_UP(vcap_is2->entry_width, ENTRY_WIDTH); + +	for (i = 0; i < entry_words; i++) { +		ocelot_write_rix(ocelot, data->entry[i], S2_CACHE_ENTRY_DAT, i); +		ocelot_write_rix(ocelot, ~data->mask[i], S2_CACHE_MASK_DAT, i);  	} -	ocelot_write(oc, data->tg, S2_CACHE_TG_DAT); +	ocelot_write(ocelot, data->tg, S2_CACHE_TG_DAT);  } -static void vcap_cache2entry(struct ocelot *oc, struct vcap_data *data) +static void vcap_cache2entry(struct ocelot *ocelot, struct vcap_data *data)  { -	u32 i; +	const struct vcap_props *vcap_is2 = &ocelot->vcap[VCAP_IS2]; +	u32 entry_words, i; + +	entry_words = DIV_ROUND_UP(vcap_is2->entry_width, ENTRY_WIDTH); -	for (i = 0; i < vcap_is2.entry_words; i++) { -		data->entry[i] = ocelot_read_rix(oc, S2_CACHE_ENTRY_DAT, i); +	for (i = 0; i < entry_words; i++) { +		data->entry[i] = ocelot_read_rix(ocelot, S2_CACHE_ENTRY_DAT, i);  		// Invert mask -		data->mask[i] = ~ocelot_read_rix(oc, S2_CACHE_MASK_DAT, i); +		data->mask[i] = ~ocelot_read_rix(ocelot, S2_CACHE_MASK_DAT, i);  	} -	data->tg = ocelot_read(oc, S2_CACHE_TG_DAT); +	data->tg = ocelot_read(ocelot, S2_CACHE_TG_DAT);  } -static void vcap_action2cache(struct ocelot *oc, struct vcap_data *data) +static void vcap_action2cache(struct ocelot *ocelot, struct vcap_data *data)  { -	u32 i, width, mask; +	const struct vcap_props *vcap_is2 = &ocelot->vcap[VCAP_IS2]; +	u32 action_words, i, width, mask;  	/* Encode action type */ -	width = vcap_is2.action_type_width; +	width = vcap_is2->action_type_width;  	if (width) {  		mask = GENMASK(width, 0);  		data->action[0] = ((data->action[0] & ~mask) | data->type);  	} -	for (i = 0; i < vcap_is2.action_words; i++) -		ocelot_write_rix(oc, data->action[i], S2_CACHE_ACTION_DAT, i); +	action_words = DIV_ROUND_UP(vcap_is2->action_width, ENTRY_WIDTH); -	for (i = 0; i < vcap_is2.counter_words; i++) -		ocelot_write_rix(oc, data->counter[i], S2_CACHE_CNT_DAT, i); +	for (i = 0; i < action_words; i++) +		ocelot_write_rix(ocelot, data->action[i], S2_CACHE_ACTION_DAT, +				 i); + +	for (i = 0; i < vcap_is2->counter_words; i++) +		ocelot_write_rix(ocelot, data->counter[i], S2_CACHE_CNT_DAT, i);  } -static void vcap_cache2action(struct ocelot *oc, struct vcap_data *data) +static void vcap_cache2action(struct ocelot *ocelot, struct vcap_data *data)  { -	u32 i, width; +	const struct vcap_props *vcap_is2 = &ocelot->vcap[VCAP_IS2]; +	u32 action_words, i, width; + +	action_words = DIV_ROUND_UP(vcap_is2->action_width, ENTRY_WIDTH); -	for (i = 0; i < vcap_is2.action_words; i++) -		data->action[i] = ocelot_read_rix(oc, S2_CACHE_ACTION_DAT, i); +	for (i = 0; i < action_words; i++) +		data->action[i] = ocelot_read_rix(ocelot, S2_CACHE_ACTION_DAT, +						  i); -	for (i = 0; i < vcap_is2.counter_words; i++) -		data->counter[i] = ocelot_read_rix(oc, S2_CACHE_CNT_DAT, i); +	for (i = 0; i < vcap_is2->counter_words; i++) +		data->counter[i] = ocelot_read_rix(ocelot, S2_CACHE_CNT_DAT, i);  	/* Extract action type */ -	width = vcap_is2.action_type_width; +	width = vcap_is2->action_type_width;  	data->type = (width ? (data->action[0] & GENMASK(width, 0)) : 0);  }  /* Calculate offsets for entry */ -static void is2_data_get(struct vcap_data *data, int ix) +static void is2_data_get(struct ocelot *ocelot, struct vcap_data *data, int ix)  { -	u32 i, col, offset, count, cnt, base, width = vcap_is2.tg_width; +	const struct vcap_props *vcap_is2 = &ocelot->vcap[VCAP_IS2]; +	u32 i, col, offset, count, cnt, base; +	u32 width = vcap_is2->tg_width;  	count = (data->tg_sw == VCAP_TG_HALF ? 2 : 4);  	col = (ix % 2); -	cnt = (vcap_is2.sw_count / count); -	base = (vcap_is2.sw_count - col * cnt - cnt); +	cnt = (vcap_is2->sw_count / count); +	base = (vcap_is2->sw_count - col * cnt - cnt);  	data->tg_value = 0;  	data->tg_mask = 0;  	for (i = 0; i < cnt; i++) { @@ -205,13 +178,13 @@ static void is2_data_get(struct vcap_data *data, int ix)  	/* Calculate key/action/counter offsets */  	col = (count - col - 1); -	data->key_offset = (base * vcap_is2.entry_width) / vcap_is2.sw_count; -	data->counter_offset = (cnt * col * vcap_is2.counter_width); +	data->key_offset = (base * vcap_is2->entry_width) / vcap_is2->sw_count; +	data->counter_offset = (cnt * col * vcap_is2->counter_width);  	i = data->type; -	width = vcap_is2.action_table[i].width; -	cnt = vcap_is2.action_table[i].count; +	width = vcap_is2->action_table[i].width; +	cnt = vcap_is2->action_table[i].count;  	data->action_offset = -		(((cnt * col * width) / count) + vcap_is2.action_type_width); +		(((cnt * col * width) / count) + vcap_is2->action_type_width);  }  static void vcap_data_set(u32 *data, u32 offset, u32 len, u32 value) @@ -242,22 +215,39 @@ static u32 vcap_data_get(u32 *data, u32 offset, u32 len)  	return value;  } -static void vcap_key_set(struct vcap_data *data, u32 offset, u32 width, -			 u32 value, u32 mask) +static void vcap_key_field_set(struct vcap_data *data, u32 offset, u32 width, +			       u32 value, u32 mask)  {  	vcap_data_set(data->entry, offset + data->key_offset, width, value);  	vcap_data_set(data->mask, offset + data->key_offset, width, mask);  } -static void vcap_key_bytes_set(struct vcap_data *data, u32 offset, u8 *val, -			       u8 *msk, u32 count) +static void vcap_key_set(struct ocelot *ocelot, struct vcap_data *data, +			 enum vcap_is2_half_key_field field, +			 u32 value, u32 mask)  { +	u32 offset = ocelot->vcap_is2_keys[field].offset; +	u32 length = ocelot->vcap_is2_keys[field].length; + +	vcap_key_field_set(data, offset, length, value, mask); +} + +static void vcap_key_bytes_set(struct ocelot *ocelot, struct vcap_data *data, +			       enum vcap_is2_half_key_field field, +			       u8 *val, u8 *msk) +{ +	u32 offset = ocelot->vcap_is2_keys[field].offset; +	u32 count  = ocelot->vcap_is2_keys[field].length;  	u32 i, j, n = 0, value = 0, mask = 0; +	WARN_ON(count % 8); +  	/* Data wider than 32 bits are split up in chunks of maximum 32 bits.  	 * The 32 LSB of the data are written to the 32 MSB of the TCAM.  	 */ -	offset += (count * 8); +	offset += count; +	count /= 8; +  	for (i = 0; i < count; i++) {  		j = (count - i - 1);  		value += (val[j] << n); @@ -265,7 +255,7 @@ static void vcap_key_bytes_set(struct vcap_data *data, u32 offset, u8 *val,  		n += 8;  		if (n == ENTRY_WIDTH || (i + 1) == count) {  			offset -= n; -			vcap_key_set(data, offset, n, value, mask); +			vcap_key_field_set(data, offset, n, value, mask);  			n = 0;  			value = 0;  			mask = 0; @@ -273,55 +263,71 @@ static void vcap_key_bytes_set(struct vcap_data *data, u32 offset, u8 *val,  	}  } -static void vcap_key_l4_port_set(struct vcap_data *data, u32 offset, +static void vcap_key_l4_port_set(struct ocelot *ocelot, struct vcap_data *data, +				 enum vcap_is2_half_key_field field,  				 struct ocelot_vcap_udp_tcp *port)  { -	vcap_key_set(data, offset, 16, port->value, port->mask); +	u32 offset = ocelot->vcap_is2_keys[field].offset; +	u32 length = ocelot->vcap_is2_keys[field].length; + +	WARN_ON(length != 16); + +	vcap_key_field_set(data, offset, length, port->value, port->mask);  } -static void vcap_key_bit_set(struct vcap_data *data, u32 offset, +static void vcap_key_bit_set(struct ocelot *ocelot, struct vcap_data *data, +			     enum vcap_is2_half_key_field field,  			     enum ocelot_vcap_bit val)  { -	vcap_key_set(data, offset, 1, val == OCELOT_VCAP_BIT_1 ? 1 : 0, -		     val == OCELOT_VCAP_BIT_ANY ? 0 : 1); -} +	u32 offset = ocelot->vcap_is2_keys[field].offset; +	u32 length = ocelot->vcap_is2_keys[field].length; +	u32 value = (val == OCELOT_VCAP_BIT_1 ? 1 : 0); +	u32 msk = (val == OCELOT_VCAP_BIT_ANY ? 0 : 1); -#define VCAP_KEY_SET(fld, val, msk) \ -	vcap_key_set(&data, IS2_HKO_##fld, IS2_HKL_##fld, val, msk) -#define VCAP_KEY_ANY_SET(fld) \ -	vcap_key_set(&data, IS2_HKO_##fld, IS2_HKL_##fld, 0, 0) -#define VCAP_KEY_BIT_SET(fld, val) vcap_key_bit_set(&data, IS2_HKO_##fld, val) -#define VCAP_KEY_BYTES_SET(fld, val, msk) \ -	vcap_key_bytes_set(&data, IS2_HKO_##fld, val, msk, IS2_HKL_##fld / 8) +	WARN_ON(length != 1); -static void vcap_action_set(struct vcap_data *data, u32 offset, u32 width, -			    u32 value) -{ -	vcap_data_set(data->action, offset + data->action_offset, width, value); +	vcap_key_field_set(data, offset, length, value, msk);  } -#define VCAP_ACT_SET(fld, val) \ -	vcap_action_set(data, IS2_AO_##fld, IS2_AL_##fld, val) +static void vcap_action_set(struct ocelot *ocelot, struct vcap_data *data, +			    enum vcap_is2_action_field field, u32 value) +{ +	int offset = ocelot->vcap_is2_actions[field].offset; +	int length = ocelot->vcap_is2_actions[field].length; + +	vcap_data_set(data->action, offset + data->action_offset, length, +		      value); +} -static void is2_action_set(struct vcap_data *data, -			   enum ocelot_ace_action action) +static void is2_action_set(struct ocelot *ocelot, struct vcap_data *data, +			   struct ocelot_ace_rule *ace)  { -	switch (action) { +	switch (ace->action) {  	case OCELOT_ACL_ACTION_DROP: -		VCAP_ACT_SET(PORT_MASK, 0x0); -		VCAP_ACT_SET(MASK_MODE, 0x1); -		VCAP_ACT_SET(POLICE_ENA, 0x1); -		VCAP_ACT_SET(POLICE_IDX, OCELOT_POLICER_DISCARD); -		VCAP_ACT_SET(CPU_QU_NUM, 0x0); -		VCAP_ACT_SET(CPU_COPY_ENA, 0x0); +		vcap_action_set(ocelot, data, VCAP_IS2_ACT_PORT_MASK, 0); +		vcap_action_set(ocelot, data, VCAP_IS2_ACT_MASK_MODE, 1); +		vcap_action_set(ocelot, data, VCAP_IS2_ACT_POLICE_ENA, 1); +		vcap_action_set(ocelot, data, VCAP_IS2_ACT_POLICE_IDX, +				OCELOT_POLICER_DISCARD); +		vcap_action_set(ocelot, data, VCAP_IS2_ACT_CPU_QU_NUM, 0); +		vcap_action_set(ocelot, data, VCAP_IS2_ACT_CPU_COPY_ENA, 0);  		break;  	case OCELOT_ACL_ACTION_TRAP: -		VCAP_ACT_SET(PORT_MASK, 0x0); -		VCAP_ACT_SET(MASK_MODE, 0x1); -		VCAP_ACT_SET(POLICE_ENA, 0x0); -		VCAP_ACT_SET(POLICE_IDX, 0x0); -		VCAP_ACT_SET(CPU_QU_NUM, 0x0); -		VCAP_ACT_SET(CPU_COPY_ENA, 0x1); +		vcap_action_set(ocelot, data, VCAP_IS2_ACT_PORT_MASK, 0); +		vcap_action_set(ocelot, data, VCAP_IS2_ACT_MASK_MODE, 1); +		vcap_action_set(ocelot, data, VCAP_IS2_ACT_POLICE_ENA, 0); +		vcap_action_set(ocelot, data, VCAP_IS2_ACT_POLICE_IDX, 0); +		vcap_action_set(ocelot, data, VCAP_IS2_ACT_CPU_QU_NUM, 0); +		vcap_action_set(ocelot, data, VCAP_IS2_ACT_CPU_COPY_ENA, 1); +		break; +	case OCELOT_ACL_ACTION_POLICE: +		vcap_action_set(ocelot, data, VCAP_IS2_ACT_PORT_MASK, 0); +		vcap_action_set(ocelot, data, VCAP_IS2_ACT_MASK_MODE, 0); +		vcap_action_set(ocelot, data, VCAP_IS2_ACT_POLICE_ENA, 1); +		vcap_action_set(ocelot, data, VCAP_IS2_ACT_POLICE_IDX, +				ace->pol_ix); +		vcap_action_set(ocelot, data, VCAP_IS2_ACT_CPU_QU_NUM, 0); +		vcap_action_set(ocelot, data, VCAP_IS2_ACT_CPU_COPY_ENA, 0);  		break;  	}  } @@ -329,6 +335,7 @@ static void is2_action_set(struct vcap_data *data,  static void is2_entry_set(struct ocelot *ocelot, int ix,  			  struct ocelot_ace_rule *ace)  { +	const struct vcap_props *vcap_is2 = &ocelot->vcap[VCAP_IS2];  	u32 val, msk, type, type_mask = 0xf, i, count;  	struct ocelot_ace_vlan *tag = &ace->vlan;  	struct ocelot_vcap_u64 payload; @@ -344,60 +351,76 @@ static void is2_entry_set(struct ocelot *ocelot, int ix,  	vcap_cache2action(ocelot, &data);  	data.tg_sw = VCAP_TG_HALF; -	is2_data_get(&data, ix); +	is2_data_get(ocelot, &data, ix);  	data.tg = (data.tg & ~data.tg_mask);  	if (ace->prio != 0)  		data.tg |= data.tg_value;  	data.type = IS2_ACTION_TYPE_NORMAL; -	VCAP_KEY_ANY_SET(PAG); -	VCAP_KEY_SET(IGR_PORT_MASK, 0, ~BIT(ace->chip_port)); -	VCAP_KEY_BIT_SET(FIRST, OCELOT_VCAP_BIT_1); -	VCAP_KEY_BIT_SET(HOST_MATCH, OCELOT_VCAP_BIT_ANY); -	VCAP_KEY_BIT_SET(L2_MC, ace->dmac_mc); -	VCAP_KEY_BIT_SET(L2_BC, ace->dmac_bc); -	VCAP_KEY_BIT_SET(VLAN_TAGGED, tag->tagged); -	VCAP_KEY_SET(VID, tag->vid.value, tag->vid.mask); -	VCAP_KEY_SET(PCP, tag->pcp.value[0], tag->pcp.mask[0]); -	VCAP_KEY_BIT_SET(DEI, tag->dei); +	vcap_key_set(ocelot, &data, VCAP_IS2_HK_PAG, 0, 0); +	vcap_key_set(ocelot, &data, VCAP_IS2_HK_IGR_PORT_MASK, 0, +		     ~ace->ingress_port_mask); +	vcap_key_bit_set(ocelot, &data, VCAP_IS2_HK_FIRST, OCELOT_VCAP_BIT_1); +	vcap_key_bit_set(ocelot, &data, VCAP_IS2_HK_HOST_MATCH, +			 OCELOT_VCAP_BIT_ANY); +	vcap_key_bit_set(ocelot, &data, VCAP_IS2_HK_L2_MC, ace->dmac_mc); +	vcap_key_bit_set(ocelot, &data, VCAP_IS2_HK_L2_BC, ace->dmac_bc); +	vcap_key_bit_set(ocelot, &data, VCAP_IS2_HK_VLAN_TAGGED, tag->tagged); +	vcap_key_set(ocelot, &data, VCAP_IS2_HK_VID, +		     tag->vid.value, tag->vid.mask); +	vcap_key_set(ocelot, &data, VCAP_IS2_HK_PCP, +		     tag->pcp.value[0], tag->pcp.mask[0]); +	vcap_key_bit_set(ocelot, &data, VCAP_IS2_HK_DEI, tag->dei);  	switch (ace->type) {  	case OCELOT_ACE_TYPE_ETYPE: {  		struct ocelot_ace_frame_etype *etype = &ace->frame.etype;  		type = IS2_TYPE_ETYPE; -		VCAP_KEY_BYTES_SET(L2_DMAC, etype->dmac.value, -				   etype->dmac.mask); -		VCAP_KEY_BYTES_SET(L2_SMAC, etype->smac.value, -				   etype->smac.mask); -		VCAP_KEY_BYTES_SET(MAC_ETYPE_ETYPE, etype->etype.value, -				   etype->etype.mask); -		VCAP_KEY_ANY_SET(MAC_ETYPE_L2_PAYLOAD); // Clear unused bits -		vcap_key_bytes_set(&data, IS2_HKO_MAC_ETYPE_L2_PAYLOAD, -				   etype->data.value, etype->data.mask, 2); +		vcap_key_bytes_set(ocelot, &data, VCAP_IS2_HK_L2_DMAC, +				   etype->dmac.value, etype->dmac.mask); +		vcap_key_bytes_set(ocelot, &data, VCAP_IS2_HK_L2_SMAC, +				   etype->smac.value, etype->smac.mask); +		vcap_key_bytes_set(ocelot, &data, VCAP_IS2_HK_MAC_ETYPE_ETYPE, +				   etype->etype.value, etype->etype.mask); +		/* Clear unused bits */ +		vcap_key_set(ocelot, &data, VCAP_IS2_HK_MAC_ETYPE_L2_PAYLOAD0, +			     0, 0); +		vcap_key_set(ocelot, &data, VCAP_IS2_HK_MAC_ETYPE_L2_PAYLOAD1, +			     0, 0); +		vcap_key_set(ocelot, &data, VCAP_IS2_HK_MAC_ETYPE_L2_PAYLOAD2, +			     0, 0); +		vcap_key_bytes_set(ocelot, &data, +				   VCAP_IS2_HK_MAC_ETYPE_L2_PAYLOAD0, +				   etype->data.value, etype->data.mask);  		break;  	}  	case OCELOT_ACE_TYPE_LLC: {  		struct ocelot_ace_frame_llc *llc = &ace->frame.llc;  		type = IS2_TYPE_LLC; -		VCAP_KEY_BYTES_SET(L2_DMAC, llc->dmac.value, llc->dmac.mask); -		VCAP_KEY_BYTES_SET(L2_SMAC, llc->smac.value, llc->smac.mask); +		vcap_key_bytes_set(ocelot, &data, VCAP_IS2_HK_L2_DMAC, +				   llc->dmac.value, llc->dmac.mask); +		vcap_key_bytes_set(ocelot, &data, VCAP_IS2_HK_L2_SMAC, +				   llc->smac.value, llc->smac.mask);  		for (i = 0; i < 4; i++) {  			payload.value[i] = llc->llc.value[i];  			payload.mask[i] = llc->llc.mask[i];  		} -		VCAP_KEY_BYTES_SET(MAC_LLC_L2_LLC, payload.value, payload.mask); +		vcap_key_bytes_set(ocelot, &data, VCAP_IS2_HK_MAC_LLC_L2_LLC, +				   payload.value, payload.mask);  		break;  	}  	case OCELOT_ACE_TYPE_SNAP: {  		struct ocelot_ace_frame_snap *snap = &ace->frame.snap;  		type = IS2_TYPE_SNAP; -		VCAP_KEY_BYTES_SET(L2_DMAC, snap->dmac.value, snap->dmac.mask); -		VCAP_KEY_BYTES_SET(L2_SMAC, snap->smac.value, snap->smac.mask); -		VCAP_KEY_BYTES_SET(MAC_SNAP_L2_SNAP, +		vcap_key_bytes_set(ocelot, &data, VCAP_IS2_HK_L2_DMAC, +				   snap->dmac.value, snap->dmac.mask); +		vcap_key_bytes_set(ocelot, &data, VCAP_IS2_HK_L2_SMAC, +				   snap->smac.value, snap->smac.mask); +		vcap_key_bytes_set(ocelot, &data, VCAP_IS2_HK_MAC_SNAP_L2_SNAP,  				   ace->frame.snap.snap.value,  				   ace->frame.snap.snap.mask);  		break; @@ -406,26 +429,42 @@ static void is2_entry_set(struct ocelot *ocelot, int ix,  		struct ocelot_ace_frame_arp *arp = &ace->frame.arp;  		type = IS2_TYPE_ARP; -		VCAP_KEY_BYTES_SET(MAC_ARP_L2_SMAC, arp->smac.value, -				   arp->smac.mask); -		VCAP_KEY_BIT_SET(MAC_ARP_ARP_ADDR_SPACE_OK, arp->ethernet); -		VCAP_KEY_BIT_SET(MAC_ARP_ARP_PROTO_SPACE_OK, arp->ip); -		VCAP_KEY_BIT_SET(MAC_ARP_ARP_LEN_OK, arp->length); -		VCAP_KEY_BIT_SET(MAC_ARP_ARP_TGT_MATCH, arp->dmac_match); -		VCAP_KEY_BIT_SET(MAC_ARP_ARP_SENDER_MATCH, arp->smac_match); -		VCAP_KEY_BIT_SET(MAC_ARP_ARP_OPCODE_UNKNOWN, arp->unknown); +		vcap_key_bytes_set(ocelot, &data, VCAP_IS2_HK_MAC_ARP_SMAC, +				   arp->smac.value, arp->smac.mask); +		vcap_key_bit_set(ocelot, &data, +				 VCAP_IS2_HK_MAC_ARP_ADDR_SPACE_OK, +				 arp->ethernet); +		vcap_key_bit_set(ocelot, &data, +				 VCAP_IS2_HK_MAC_ARP_PROTO_SPACE_OK, +				 arp->ip); +		vcap_key_bit_set(ocelot, &data, +				 VCAP_IS2_HK_MAC_ARP_LEN_OK, +				 arp->length); +		vcap_key_bit_set(ocelot, &data, +				 VCAP_IS2_HK_MAC_ARP_TARGET_MATCH, +				 arp->dmac_match); +		vcap_key_bit_set(ocelot, &data, +				 VCAP_IS2_HK_MAC_ARP_SENDER_MATCH, +				 arp->smac_match); +		vcap_key_bit_set(ocelot, &data, +				 VCAP_IS2_HK_MAC_ARP_OPCODE_UNKNOWN, +				 arp->unknown);  		/* OPCODE is inverse, bit 0 is reply flag, bit 1 is RARP flag */  		val = ((arp->req == OCELOT_VCAP_BIT_0 ? 1 : 0) |  		       (arp->arp == OCELOT_VCAP_BIT_0 ? 2 : 0));  		msk = ((arp->req == OCELOT_VCAP_BIT_ANY ? 0 : 1) |  		       (arp->arp == OCELOT_VCAP_BIT_ANY ? 0 : 2)); -		VCAP_KEY_SET(MAC_ARP_ARP_OPCODE, val, msk); -		vcap_key_bytes_set(&data, IS2_HKO_MAC_ARP_L3_IP4_DIP, -				   arp->dip.value.addr, arp->dip.mask.addr, 4); -		vcap_key_bytes_set(&data, IS2_HKO_MAC_ARP_L3_IP4_SIP, -				   arp->sip.value.addr, arp->sip.mask.addr, 4); -		VCAP_KEY_ANY_SET(MAC_ARP_DIP_EQ_SIP); +		vcap_key_set(ocelot, &data, VCAP_IS2_HK_MAC_ARP_OPCODE, +			     val, msk); +		vcap_key_bytes_set(ocelot, &data, +				   VCAP_IS2_HK_MAC_ARP_L3_IP4_DIP, +				   arp->dip.value.addr, arp->dip.mask.addr); +		vcap_key_bytes_set(ocelot, &data, +				   VCAP_IS2_HK_MAC_ARP_L3_IP4_SIP, +				   arp->sip.value.addr, arp->sip.mask.addr); +		vcap_key_set(ocelot, &data, VCAP_IS2_HK_MAC_ARP_DIP_EQ_SIP, +			     0, 0);  		break;  	}  	case OCELOT_ACE_TYPE_IPV4: @@ -493,18 +532,23 @@ static void is2_entry_set(struct ocelot *ocelot, int ix,  			seq_zero = ipv6->seq_zero;  		} -		VCAP_KEY_BIT_SET(IP4, +		vcap_key_bit_set(ocelot, &data, VCAP_IS2_HK_IP4,  				 ipv4 ? OCELOT_VCAP_BIT_1 : OCELOT_VCAP_BIT_0); -		VCAP_KEY_BIT_SET(L3_FRAGMENT, fragment); -		VCAP_KEY_ANY_SET(L3_FRAG_OFS_GT0); -		VCAP_KEY_BIT_SET(L3_OPTIONS, options); -		VCAP_KEY_BIT_SET(L3_TTL_GT0, ttl); -		VCAP_KEY_BYTES_SET(L3_TOS, ds.value, ds.mask); -		vcap_key_bytes_set(&data, IS2_HKO_L3_IP4_DIP, dip.value.addr, -				   dip.mask.addr, 4); -		vcap_key_bytes_set(&data, IS2_HKO_L3_IP4_SIP, sip.value.addr, -				   sip.mask.addr, 4); -		VCAP_KEY_BIT_SET(DIP_EQ_SIP, sip_eq_dip); +		vcap_key_bit_set(ocelot, &data, VCAP_IS2_HK_L3_FRAGMENT, +				 fragment); +		vcap_key_set(ocelot, &data, VCAP_IS2_HK_L3_FRAG_OFS_GT0, 0, 0); +		vcap_key_bit_set(ocelot, &data, VCAP_IS2_HK_L3_OPTIONS, +				 options); +		vcap_key_bit_set(ocelot, &data, VCAP_IS2_HK_IP4_L3_TTL_GT0, +				 ttl); +		vcap_key_bytes_set(ocelot, &data, VCAP_IS2_HK_L3_TOS, +				   ds.value, ds.mask); +		vcap_key_bytes_set(ocelot, &data, VCAP_IS2_HK_L3_IP4_DIP, +				   dip.value.addr, dip.mask.addr); +		vcap_key_bytes_set(ocelot, &data, VCAP_IS2_HK_L3_IP4_SIP, +				   sip.value.addr, sip.mask.addr); +		vcap_key_bit_set(ocelot, &data, VCAP_IS2_HK_DIP_EQ_SIP, +				 sip_eq_dip);  		val = proto.value[0];  		msk = proto.mask[0];  		type = IS2_TYPE_IP_UDP_TCP; @@ -512,25 +556,34 @@ static void is2_entry_set(struct ocelot *ocelot, int ix,  			/* UDP/TCP protocol match */  			tcp = (val == 6 ?  			       OCELOT_VCAP_BIT_1 : OCELOT_VCAP_BIT_0); -			VCAP_KEY_BIT_SET(IP4_TCP_UDP_TCP, tcp); -			vcap_key_l4_port_set(&data, -					     IS2_HKO_IP4_TCP_UDP_L4_DPORT, -					     dport); -			vcap_key_l4_port_set(&data, -					     IS2_HKO_IP4_TCP_UDP_L4_SPORT, -					     sport); -			VCAP_KEY_ANY_SET(IP4_TCP_UDP_L4_RNG); -			VCAP_KEY_BIT_SET(IP4_TCP_UDP_SPORT_EQ_DPORT, +			vcap_key_bit_set(ocelot, &data, VCAP_IS2_HK_TCP, tcp); +			vcap_key_l4_port_set(ocelot, &data, +					     VCAP_IS2_HK_L4_DPORT, dport); +			vcap_key_l4_port_set(ocelot, &data, +					     VCAP_IS2_HK_L4_SPORT, sport); +			vcap_key_set(ocelot, &data, VCAP_IS2_HK_L4_RNG, 0, 0); +			vcap_key_bit_set(ocelot, &data, +					 VCAP_IS2_HK_L4_SPORT_EQ_DPORT,  					 sport_eq_dport); -			VCAP_KEY_BIT_SET(IP4_TCP_UDP_SEQUENCE_EQ0, seq_zero); -			VCAP_KEY_BIT_SET(IP4_TCP_UDP_L4_FIN, tcp_fin); -			VCAP_KEY_BIT_SET(IP4_TCP_UDP_L4_SYN, tcp_syn); -			VCAP_KEY_BIT_SET(IP4_TCP_UDP_L4_RST, tcp_rst); -			VCAP_KEY_BIT_SET(IP4_TCP_UDP_L4_PSH, tcp_psh); -			VCAP_KEY_BIT_SET(IP4_TCP_UDP_L4_ACK, tcp_ack); -			VCAP_KEY_BIT_SET(IP4_TCP_UDP_L4_URG, tcp_urg); -			VCAP_KEY_ANY_SET(IP4_TCP_UDP_L4_1588_DOM); -			VCAP_KEY_ANY_SET(IP4_TCP_UDP_L4_1588_VER); +			vcap_key_bit_set(ocelot, &data, +					 VCAP_IS2_HK_L4_SEQUENCE_EQ0, +					 seq_zero); +			vcap_key_bit_set(ocelot, &data, VCAP_IS2_HK_L4_FIN, +					 tcp_fin); +			vcap_key_bit_set(ocelot, &data, VCAP_IS2_HK_L4_SYN, +					 tcp_syn); +			vcap_key_bit_set(ocelot, &data, VCAP_IS2_HK_L4_RST, +					 tcp_rst); +			vcap_key_bit_set(ocelot, &data, VCAP_IS2_HK_L4_PSH, +					 tcp_psh); +			vcap_key_bit_set(ocelot, &data, VCAP_IS2_HK_L4_ACK, +					 tcp_ack); +			vcap_key_bit_set(ocelot, &data, VCAP_IS2_HK_L4_URG, +					 tcp_urg); +			vcap_key_set(ocelot, &data, VCAP_IS2_HK_L4_1588_DOM, +				     0, 0); +			vcap_key_set(ocelot, &data, VCAP_IS2_HK_L4_1588_VER, +				     0, 0);  		} else {  			if (msk == 0) {  				/* Any IP protocol match */ @@ -543,10 +596,12 @@ static void is2_entry_set(struct ocelot *ocelot, int ix,  					payload.mask[i] = ip_data->mask[i];  				}  			} -			VCAP_KEY_BYTES_SET(IP4_OTHER_L3_PROTO, proto.value, -					   proto.mask); -			VCAP_KEY_BYTES_SET(IP4_OTHER_L3_PAYLOAD, payload.value, -					   payload.mask); +			vcap_key_bytes_set(ocelot, &data, +					   VCAP_IS2_HK_IP4_L3_PROTO, +					   proto.value, proto.mask); +			vcap_key_bytes_set(ocelot, &data, +					   VCAP_IS2_HK_L3_PAYLOAD, +					   payload.value, payload.mask);  		}  		break;  	} @@ -554,19 +609,21 @@ static void is2_entry_set(struct ocelot *ocelot, int ix,  	default:  		type = 0;  		type_mask = 0; -		count = (vcap_is2.entry_width / 2); -		for (i = (IS2_HKO_PCP + IS2_HKL_PCP); i < count; -		     i += ENTRY_WIDTH) { -			/* Clear entry data */ -			vcap_key_set(&data, i, min(32u, count - i), 0, 0); +		count = vcap_is2->entry_width / 2; +		/* Iterate over the non-common part of the key and +		 * clear entry data +		 */ +		for (i = ocelot->vcap_is2_keys[VCAP_IS2_HK_L2_DMAC].offset; +		     i < count; i += ENTRY_WIDTH) { +			vcap_key_field_set(&data, i, min(32u, count - i), 0, 0);  		}  		break;  	} -	VCAP_KEY_SET(TYPE, type, type_mask); -	is2_action_set(&data, ace->action); -	vcap_data_set(data.counter, data.counter_offset, vcap_is2.counter_width, -		      ace->stats.pkts); +	vcap_key_set(ocelot, &data, VCAP_IS2_TYPE, type, type_mask); +	is2_action_set(ocelot, &data, ace); +	vcap_data_set(data.counter, data.counter_offset, +		      vcap_is2->counter_width, ace->stats.pkts);  	/* Write row */  	vcap_entry2cache(ocelot, &data); @@ -574,29 +631,37 @@ static void is2_entry_set(struct ocelot *ocelot, int ix,  	vcap_row_cmd(ocelot, row, VCAP_CMD_WRITE, VCAP_SEL_ALL);  } -static void is2_entry_get(struct ocelot_ace_rule *rule, int ix) +static void is2_entry_get(struct ocelot *ocelot, struct ocelot_ace_rule *rule, +			  int ix)  { -	struct ocelot *op = rule->port->ocelot; +	const struct vcap_props *vcap_is2 = &ocelot->vcap[VCAP_IS2];  	struct vcap_data data;  	int row = (ix / 2);  	u32 cnt; -	vcap_row_cmd(op, row, VCAP_CMD_READ, VCAP_SEL_COUNTER); -	vcap_cache2action(op, &data); +	vcap_row_cmd(ocelot, row, VCAP_CMD_READ, VCAP_SEL_COUNTER); +	vcap_cache2action(ocelot, &data);  	data.tg_sw = VCAP_TG_HALF; -	is2_data_get(&data, ix); +	is2_data_get(ocelot, &data, ix);  	cnt = vcap_data_get(data.counter, data.counter_offset, -			    vcap_is2.counter_width); +			    vcap_is2->counter_width);  	rule->stats.pkts = cnt;  } -static void ocelot_ace_rule_add(struct ocelot_acl_block *block, +static void ocelot_ace_rule_add(struct ocelot *ocelot, +				struct ocelot_acl_block *block,  				struct ocelot_ace_rule *rule)  {  	struct ocelot_ace_rule *tmp;  	struct list_head *pos, *n; +	if (rule->action == OCELOT_ACL_ACTION_POLICE) { +		block->pol_lpr--; +		rule->pol_ix = block->pol_lpr; +		ocelot_ace_policer_add(ocelot, rule->pol_ix, &rule->pol); +	} +  	block->count++;  	if (list_empty(&block->rules)) { @@ -641,29 +706,57 @@ ocelot_ace_rule_get_rule_index(struct ocelot_acl_block *block, int index)  	return NULL;  } -int ocelot_ace_rule_offload_add(struct ocelot_ace_rule *rule) +int ocelot_ace_rule_offload_add(struct ocelot *ocelot, +				struct ocelot_ace_rule *rule)  { +	struct ocelot_acl_block *block = &ocelot->acl_block;  	struct ocelot_ace_rule *ace;  	int i, index;  	/* Add rule to the linked list */ -	ocelot_ace_rule_add(acl_block, rule); +	ocelot_ace_rule_add(ocelot, block, rule);  	/* Get the index of the inserted rule */ -	index = ocelot_ace_rule_get_index_id(acl_block, rule); +	index = ocelot_ace_rule_get_index_id(block, rule);  	/* Move down the rules to make place for the new rule */ -	for (i = acl_block->count - 1; i > index; i--) { -		ace = ocelot_ace_rule_get_rule_index(acl_block, i); -		is2_entry_set(rule->port->ocelot, i, ace); +	for (i = block->count - 1; i > index; i--) { +		ace = ocelot_ace_rule_get_rule_index(block, i); +		is2_entry_set(ocelot, i, ace);  	}  	/* Now insert the new rule */ -	is2_entry_set(rule->port->ocelot, index, rule); +	is2_entry_set(ocelot, index, rule);  	return 0;  } -static void ocelot_ace_rule_del(struct ocelot_acl_block *block, +static void ocelot_ace_police_del(struct ocelot *ocelot, +				  struct ocelot_acl_block *block, +				  u32 ix) +{ +	struct ocelot_ace_rule *ace; +	int index = -1; + +	if (ix < block->pol_lpr) +		return; + +	list_for_each_entry(ace, &block->rules, list) { +		index++; +		if (ace->action == OCELOT_ACL_ACTION_POLICE && +		    ace->pol_ix < ix) { +			ace->pol_ix += 1; +			ocelot_ace_policer_add(ocelot, ace->pol_ix, +					       &ace->pol); +			is2_entry_set(ocelot, index, ace); +		} +	} + +	ocelot_ace_policer_del(ocelot, block->pol_lpr); +	block->pol_lpr++; +} + +static void ocelot_ace_rule_del(struct ocelot *ocelot, +				struct ocelot_acl_block *block,  				struct ocelot_ace_rule *rule)  {  	struct ocelot_ace_rule *tmp; @@ -672,6 +765,10 @@ static void ocelot_ace_rule_del(struct ocelot_acl_block *block,  	list_for_each_safe(pos, q, &block->rules) {  		tmp = list_entry(pos, struct ocelot_ace_rule, list);  		if (tmp->id == rule->id) { +			if (tmp->action == OCELOT_ACL_ACTION_POLICE) +				ocelot_ace_police_del(ocelot, block, +						      tmp->pol_ix); +  			list_del(pos);  			kfree(tmp);  		} @@ -680,8 +777,10 @@ static void ocelot_ace_rule_del(struct ocelot_acl_block *block,  	block->count--;  } -int ocelot_ace_rule_offload_del(struct ocelot_ace_rule *rule) +int ocelot_ace_rule_offload_del(struct ocelot *ocelot, +				struct ocelot_ace_rule *rule)  { +	struct ocelot_acl_block *block = &ocelot->acl_block;  	struct ocelot_ace_rule del_ace;  	struct ocelot_ace_rule *ace;  	int i, index; @@ -689,70 +788,55 @@ int ocelot_ace_rule_offload_del(struct ocelot_ace_rule *rule)  	memset(&del_ace, 0, sizeof(del_ace));  	/* Gets index of the rule */ -	index = ocelot_ace_rule_get_index_id(acl_block, rule); +	index = ocelot_ace_rule_get_index_id(block, rule);  	/* Delete rule */ -	ocelot_ace_rule_del(acl_block, rule); +	ocelot_ace_rule_del(ocelot, block, rule);  	/* Move up all the blocks over the deleted rule */ -	for (i = index; i < acl_block->count; i++) { -		ace = ocelot_ace_rule_get_rule_index(acl_block, i); -		is2_entry_set(rule->port->ocelot, i, ace); +	for (i = index; i < block->count; i++) { +		ace = ocelot_ace_rule_get_rule_index(block, i); +		is2_entry_set(ocelot, i, ace);  	}  	/* Now delete the last rule, because it is duplicated */ -	is2_entry_set(rule->port->ocelot, acl_block->count, &del_ace); +	is2_entry_set(ocelot, block->count, &del_ace);  	return 0;  } -int ocelot_ace_rule_stats_update(struct ocelot_ace_rule *rule) +int ocelot_ace_rule_stats_update(struct ocelot *ocelot, +				 struct ocelot_ace_rule *rule)  { +	struct ocelot_acl_block *block = &ocelot->acl_block;  	struct ocelot_ace_rule *tmp;  	int index; -	index = ocelot_ace_rule_get_index_id(acl_block, rule); -	is2_entry_get(rule, index); +	index = ocelot_ace_rule_get_index_id(block, rule); +	is2_entry_get(ocelot, rule, index);  	/* After we get the result we need to clear the counters */ -	tmp = ocelot_ace_rule_get_rule_index(acl_block, index); +	tmp = ocelot_ace_rule_get_rule_index(block, index);  	tmp->stats.pkts = 0; -	is2_entry_set(rule->port->ocelot, index, tmp); +	is2_entry_set(ocelot, index, tmp);  	return 0;  } -static struct ocelot_acl_block *ocelot_acl_block_create(struct ocelot *ocelot) -{ -	struct ocelot_acl_block *block; - -	block = kzalloc(sizeof(*block), GFP_KERNEL); -	if (!block) -		return NULL; - -	INIT_LIST_HEAD(&block->rules); -	block->count = 0; -	block->ocelot = ocelot; - -	return block; -} - -static void ocelot_acl_block_destroy(struct ocelot_acl_block *block) -{ -	kfree(block); -} -  int ocelot_ace_init(struct ocelot *ocelot)  { +	const struct vcap_props *vcap_is2 = &ocelot->vcap[VCAP_IS2]; +	struct ocelot_acl_block *block = &ocelot->acl_block;  	struct vcap_data data;  	memset(&data, 0, sizeof(data)); +  	vcap_entry2cache(ocelot, &data); -	ocelot_write(ocelot, vcap_is2.entry_count, S2_CORE_MV_CFG); +	ocelot_write(ocelot, vcap_is2->entry_count, S2_CORE_MV_CFG);  	vcap_cmd(ocelot, 0, VCAP_CMD_INITIALIZE, VCAP_SEL_ENTRY);  	vcap_action2cache(ocelot, &data); -	ocelot_write(ocelot, vcap_is2.action_count, S2_CORE_MV_CFG); +	ocelot_write(ocelot, vcap_is2->action_count, S2_CORE_MV_CFG);  	vcap_cmd(ocelot, 0, VCAP_CMD_INITIALIZE,  		 VCAP_SEL_ACTION | VCAP_SEL_COUNTER); @@ -771,12 +855,9 @@ int ocelot_ace_init(struct ocelot *ocelot)  	ocelot_write_gix(ocelot, 0x3fffff, ANA_POL_CIR_STATE,  			 OCELOT_POLICER_DISCARD); -	acl_block = ocelot_acl_block_create(ocelot); +	block->pol_lpr = OCELOT_POLICER_DISCARD - 1; -	return 0; -} +	INIT_LIST_HEAD(&ocelot->acl_block.rules); -void ocelot_ace_deinit(void) -{ -	ocelot_acl_block_destroy(acl_block); +	return 0;  } diff --git a/drivers/net/ethernet/mscc/ocelot_ace.h b/drivers/net/ethernet/mscc/ocelot_ace.h index c08e3e8482e7..29d22c566786 100644 --- a/drivers/net/ethernet/mscc/ocelot_ace.h +++ b/drivers/net/ethernet/mscc/ocelot_ace.h @@ -7,6 +7,7 @@  #define _MSCC_OCELOT_ACE_H_  #include "ocelot.h" +#include "ocelot_police.h"  #include <net/sch_generic.h>  #include <net/pkt_cls.h> @@ -176,6 +177,7 @@ struct ocelot_ace_frame_ipv6 {  enum ocelot_ace_action {  	OCELOT_ACL_ACTION_DROP,  	OCELOT_ACL_ACTION_TRAP, +	OCELOT_ACL_ACTION_POLICE,  };  struct ocelot_ace_stats { @@ -186,14 +188,13 @@ struct ocelot_ace_stats {  struct ocelot_ace_rule {  	struct list_head list; -	struct ocelot_port *port;  	u16 prio;  	u32 id;  	enum ocelot_ace_action action;  	struct ocelot_ace_stats stats; -	int chip_port; +	u16 ingress_port_mask;  	enum ocelot_vcap_bit dmac_mc;  	enum ocelot_vcap_bit dmac_bc; @@ -209,24 +210,21 @@ struct ocelot_ace_rule {  		struct ocelot_ace_frame_ipv4 ipv4;  		struct ocelot_ace_frame_ipv6 ipv6;  	} frame; +	struct ocelot_policer pol; +	u32 pol_ix;  }; -struct ocelot_acl_block { -	struct list_head rules; -	struct ocelot *ocelot; -	int count; -}; - -int ocelot_ace_rule_offload_add(struct ocelot_ace_rule *rule); -int ocelot_ace_rule_offload_del(struct ocelot_ace_rule *rule); -int ocelot_ace_rule_stats_update(struct ocelot_ace_rule *rule); +int ocelot_ace_rule_offload_add(struct ocelot *ocelot, +				struct ocelot_ace_rule *rule); +int ocelot_ace_rule_offload_del(struct ocelot *ocelot, +				struct ocelot_ace_rule *rule); +int ocelot_ace_rule_stats_update(struct ocelot *ocelot, +				 struct ocelot_ace_rule *rule);  int ocelot_ace_init(struct ocelot *ocelot); -void ocelot_ace_deinit(void); -int ocelot_setup_tc_block_flower_bind(struct ocelot_port_private *priv, -				      struct flow_block_offload *f); -void ocelot_setup_tc_block_flower_unbind(struct ocelot_port_private *priv, -					 struct flow_block_offload *f); +int ocelot_setup_tc_cls_flower(struct ocelot_port_private *priv, +			       struct flow_cls_offload *f, +			       bool ingress);  #endif /* _MSCC_OCELOT_ACE_H_ */ diff --git a/drivers/net/ethernet/mscc/ocelot_board.c b/drivers/net/ethernet/mscc/ocelot_board.c index 1135a18019c7..0ac9fbf77a01 100644 --- a/drivers/net/ethernet/mscc/ocelot_board.c +++ b/drivers/net/ethernet/mscc/ocelot_board.c @@ -14,9 +14,14 @@  #include <linux/skbuff.h>  #include <net/switchdev.h> +#include <soc/mscc/ocelot_vcap.h>  #include "ocelot.h"  #define IFH_EXTRACT_BITFIELD64(x, o, w) (((x) >> (o)) & GENMASK_ULL((w) - 1, 0)) +#define VSC7514_VCAP_IS2_CNT 64 +#define VSC7514_VCAP_IS2_ENTRY_WIDTH 376 +#define VSC7514_VCAP_IS2_ACTION_WIDTH 99 +#define VSC7514_VCAP_PORT_CNT 11  static int ocelot_parse_ifh(u32 *_ifh, struct frame_info *info)  { @@ -211,29 +216,6 @@ static const struct of_device_id mscc_ocelot_match[] = {  };  MODULE_DEVICE_TABLE(of, mscc_ocelot_match); -static void ocelot_port_pcs_init(struct ocelot *ocelot, int port) -{ -	struct ocelot_port *ocelot_port = ocelot->ports[port]; - -	/* Disable HDX fast control */ -	ocelot_port_writel(ocelot_port, DEV_PORT_MISC_HDX_FAST_DIS, -			   DEV_PORT_MISC); - -	/* SGMII only for now */ -	ocelot_port_writel(ocelot_port, PCS1G_MODE_CFG_SGMII_MODE_ENA, -			   PCS1G_MODE_CFG); -	ocelot_port_writel(ocelot_port, PCS1G_SD_CFG_SD_SEL, PCS1G_SD_CFG); - -	/* Enable PCS */ -	ocelot_port_writel(ocelot_port, PCS1G_CFG_PCS_ENA, PCS1G_CFG); - -	/* No aneg on SGMII */ -	ocelot_port_writel(ocelot_port, 0, PCS1G_ANEG_CFG); - -	/* No loopback */ -	ocelot_port_writel(ocelot_port, 0, PCS1G_LB_CFG); -} -  static int ocelot_reset(struct ocelot *ocelot)  {  	int retries = 100; @@ -258,10 +240,132 @@ static int ocelot_reset(struct ocelot *ocelot)  }  static const struct ocelot_ops ocelot_ops = { -	.pcs_init		= ocelot_port_pcs_init,  	.reset			= ocelot_reset,  }; +static const struct vcap_field vsc7514_vcap_is2_keys[] = { +	/* Common: 46 bits */ +	[VCAP_IS2_TYPE]				= {  0,   4}, +	[VCAP_IS2_HK_FIRST]			= {  4,   1}, +	[VCAP_IS2_HK_PAG]			= {  5,   8}, +	[VCAP_IS2_HK_IGR_PORT_MASK]		= { 13,  12}, +	[VCAP_IS2_HK_RSV2]			= { 25,   1}, +	[VCAP_IS2_HK_HOST_MATCH]		= { 26,   1}, +	[VCAP_IS2_HK_L2_MC]			= { 27,   1}, +	[VCAP_IS2_HK_L2_BC]			= { 28,   1}, +	[VCAP_IS2_HK_VLAN_TAGGED]		= { 29,   1}, +	[VCAP_IS2_HK_VID]			= { 30,  12}, +	[VCAP_IS2_HK_DEI]			= { 42,   1}, +	[VCAP_IS2_HK_PCP]			= { 43,   3}, +	/* MAC_ETYPE / MAC_LLC / MAC_SNAP / OAM common */ +	[VCAP_IS2_HK_L2_DMAC]			= { 46,  48}, +	[VCAP_IS2_HK_L2_SMAC]			= { 94,  48}, +	/* MAC_ETYPE (TYPE=000) */ +	[VCAP_IS2_HK_MAC_ETYPE_ETYPE]		= {142,  16}, +	[VCAP_IS2_HK_MAC_ETYPE_L2_PAYLOAD0]	= {158,  16}, +	[VCAP_IS2_HK_MAC_ETYPE_L2_PAYLOAD1]	= {174,   8}, +	[VCAP_IS2_HK_MAC_ETYPE_L2_PAYLOAD2]	= {182,   3}, +	/* MAC_LLC (TYPE=001) */ +	[VCAP_IS2_HK_MAC_LLC_L2_LLC]		= {142,  40}, +	/* MAC_SNAP (TYPE=010) */ +	[VCAP_IS2_HK_MAC_SNAP_L2_SNAP]		= {142,  40}, +	/* MAC_ARP (TYPE=011) */ +	[VCAP_IS2_HK_MAC_ARP_SMAC]		= { 46,  48}, +	[VCAP_IS2_HK_MAC_ARP_ADDR_SPACE_OK]	= { 94,   1}, +	[VCAP_IS2_HK_MAC_ARP_PROTO_SPACE_OK]	= { 95,   1}, +	[VCAP_IS2_HK_MAC_ARP_LEN_OK]		= { 96,   1}, +	[VCAP_IS2_HK_MAC_ARP_TARGET_MATCH]	= { 97,   1}, +	[VCAP_IS2_HK_MAC_ARP_SENDER_MATCH]	= { 98,   1}, +	[VCAP_IS2_HK_MAC_ARP_OPCODE_UNKNOWN]	= { 99,   1}, +	[VCAP_IS2_HK_MAC_ARP_OPCODE]		= {100,   2}, +	[VCAP_IS2_HK_MAC_ARP_L3_IP4_DIP]	= {102,  32}, +	[VCAP_IS2_HK_MAC_ARP_L3_IP4_SIP]	= {134,  32}, +	[VCAP_IS2_HK_MAC_ARP_DIP_EQ_SIP]	= {166,   1}, +	/* IP4_TCP_UDP / IP4_OTHER common */ +	[VCAP_IS2_HK_IP4]			= { 46,   1}, +	[VCAP_IS2_HK_L3_FRAGMENT]		= { 47,   1}, +	[VCAP_IS2_HK_L3_FRAG_OFS_GT0]		= { 48,   1}, +	[VCAP_IS2_HK_L3_OPTIONS]		= { 49,   1}, +	[VCAP_IS2_HK_IP4_L3_TTL_GT0]		= { 50,   1}, +	[VCAP_IS2_HK_L3_TOS]			= { 51,   8}, +	[VCAP_IS2_HK_L3_IP4_DIP]		= { 59,  32}, +	[VCAP_IS2_HK_L3_IP4_SIP]		= { 91,  32}, +	[VCAP_IS2_HK_DIP_EQ_SIP]		= {123,   1}, +	/* IP4_TCP_UDP (TYPE=100) */ +	[VCAP_IS2_HK_TCP]			= {124,   1}, +	[VCAP_IS2_HK_L4_SPORT]			= {125,  16}, +	[VCAP_IS2_HK_L4_DPORT]			= {141,  16}, +	[VCAP_IS2_HK_L4_RNG]			= {157,   8}, +	[VCAP_IS2_HK_L4_SPORT_EQ_DPORT]		= {165,   1}, +	[VCAP_IS2_HK_L4_SEQUENCE_EQ0]		= {166,   1}, +	[VCAP_IS2_HK_L4_URG]			= {167,   1}, +	[VCAP_IS2_HK_L4_ACK]			= {168,   1}, +	[VCAP_IS2_HK_L4_PSH]			= {169,   1}, +	[VCAP_IS2_HK_L4_RST]			= {170,   1}, +	[VCAP_IS2_HK_L4_SYN]			= {171,   1}, +	[VCAP_IS2_HK_L4_FIN]			= {172,   1}, +	[VCAP_IS2_HK_L4_1588_DOM]		= {173,   8}, +	[VCAP_IS2_HK_L4_1588_VER]		= {181,   4}, +	/* IP4_OTHER (TYPE=101) */ +	[VCAP_IS2_HK_IP4_L3_PROTO]		= {124,   8}, +	[VCAP_IS2_HK_L3_PAYLOAD]		= {132,  56}, +	/* IP6_STD (TYPE=110) */ +	[VCAP_IS2_HK_IP6_L3_TTL_GT0]		= { 46,   1}, +	[VCAP_IS2_HK_L3_IP6_SIP]		= { 47, 128}, +	[VCAP_IS2_HK_IP6_L3_PROTO]		= {175,   8}, +	/* OAM (TYPE=111) */ +	[VCAP_IS2_HK_OAM_MEL_FLAGS]		= {142,   7}, +	[VCAP_IS2_HK_OAM_VER]			= {149,   5}, +	[VCAP_IS2_HK_OAM_OPCODE]		= {154,   8}, +	[VCAP_IS2_HK_OAM_FLAGS]			= {162,   8}, +	[VCAP_IS2_HK_OAM_MEPID]			= {170,  16}, +	[VCAP_IS2_HK_OAM_CCM_CNTS_EQ0]		= {186,   1}, +	[VCAP_IS2_HK_OAM_IS_Y1731]		= {187,   1}, +}; + +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}, +	[VCAP_IS2_ACT_MASK_MODE]		= {  5,  2}, +	[VCAP_IS2_ACT_MIRROR_ENA]		= {  7,  1}, +	[VCAP_IS2_ACT_LRN_DIS]			= {  8,  1}, +	[VCAP_IS2_ACT_POLICE_ENA]		= {  9,  1}, +	[VCAP_IS2_ACT_POLICE_IDX]		= { 10,  9}, +	[VCAP_IS2_ACT_POLICE_VCAP_ONLY]		= { 19,  1}, +	[VCAP_IS2_ACT_PORT_MASK]		= { 20, 11}, +	[VCAP_IS2_ACT_REW_OP]			= { 31,  9}, +	[VCAP_IS2_ACT_SMAC_REPLACE_ENA]		= { 40,  1}, +	[VCAP_IS2_ACT_RSV]			= { 41,  2}, +	[VCAP_IS2_ACT_ACL_ID]			= { 43,  6}, +	[VCAP_IS2_ACT_HIT_CNT]			= { 49, 32}, +}; + +static const struct vcap_props vsc7514_vcap_props[] = { +	[VCAP_IS2] = { +		.tg_width = 2, +		.sw_count = 4, +		.entry_count = VSC7514_VCAP_IS2_CNT, +		.entry_width = VSC7514_VCAP_IS2_ENTRY_WIDTH, +		.action_count = VSC7514_VCAP_IS2_CNT + +				VSC7514_VCAP_PORT_CNT + 2, +		.action_width = 99, +		.action_type_width = 1, +		.action_table = { +			[IS2_ACTION_TYPE_NORMAL] = { +				.width = 49, +				.count = 2 +			}, +			[IS2_ACTION_TYPE_SMAC_SIP] = { +				.width = 6, +				.count = 4 +			}, +		}, +		.counter_words = 4, +		.counter_width = 32, +	}, +}; +  static int mscc_ocelot_probe(struct platform_device *pdev)  {  	struct device_node *np = pdev->dev.of_node; @@ -349,8 +453,6 @@ static int mscc_ocelot_probe(struct platform_device *pdev)  		ocelot->ptp = 1;  	} -	ocelot->num_cpu_ports = 1; /* 1 port on the switch, two groups */ -  	ports = of_get_child_by_name(np, "ethernet-ports");  	if (!ports) {  		dev_err(&pdev->dev, "no ethernet-ports child node found\n"); @@ -362,9 +464,14 @@ static int mscc_ocelot_probe(struct platform_device *pdev)  	ocelot->ports = devm_kcalloc(&pdev->dev, ocelot->num_phys_ports,  				     sizeof(struct ocelot_port *), GFP_KERNEL); +	ocelot->vcap_is2_keys = vsc7514_vcap_is2_keys; +	ocelot->vcap_is2_actions = vsc7514_vcap_is2_actions; +	ocelot->vcap = vsc7514_vcap_props; +  	ocelot_init(ocelot); -	ocelot_set_cpu_port(ocelot, ocelot->num_phys_ports, -			    OCELOT_TAG_PREFIX_NONE, OCELOT_TAG_PREFIX_NONE); +	/* No NPI port */ +	ocelot_configure_cpu(ocelot, -1, OCELOT_TAG_PREFIX_NONE, +			     OCELOT_TAG_PREFIX_NONE);  	for_each_available_child_of_node(ports, portnp) {  		struct ocelot_port_private *priv; diff --git a/drivers/net/ethernet/mscc/ocelot_flower.c b/drivers/net/ethernet/mscc/ocelot_flower.c index 3d65b99b9734..341923311fec 100644 --- a/drivers/net/ethernet/mscc/ocelot_flower.c +++ b/drivers/net/ethernet/mscc/ocelot_flower.c @@ -8,27 +8,35 @@  #include "ocelot_ace.h" -struct ocelot_port_block { -	struct ocelot_acl_block *block; -	struct ocelot_port_private *priv; -}; -  static int ocelot_flower_parse_action(struct flow_cls_offload *f, -				      struct ocelot_ace_rule *rule) +				      struct ocelot_ace_rule *ace)  {  	const struct flow_action_entry *a; +	s64 burst; +	u64 rate;  	int i; -	if (f->rule->action.num_entries != 1) +	if (!flow_offload_has_one_action(&f->rule->action)) +		return -EOPNOTSUPP; + +	if (!flow_action_basic_hw_stats_check(&f->rule->action, +					      f->common.extack))  		return -EOPNOTSUPP;  	flow_action_for_each(i, a, &f->rule->action) {  		switch (a->id) {  		case FLOW_ACTION_DROP: -			rule->action = OCELOT_ACL_ACTION_DROP; +			ace->action = OCELOT_ACL_ACTION_DROP;  			break;  		case FLOW_ACTION_TRAP: -			rule->action = OCELOT_ACL_ACTION_TRAP; +			ace->action = OCELOT_ACL_ACTION_TRAP; +			break; +		case FLOW_ACTION_POLICE: +			ace->action = OCELOT_ACL_ACTION_POLICE; +			rate = a->police.rate_bytes_ps; +			ace->pol.rate = div_u64(rate, 1000) * 8; +			burst = rate * PSCHED_NS2TICKS(a->police.burst); +			ace->pol.burst = div_u64(burst, PSCHED_TICKS_PER_SEC);  			break;  		default:  			return -EOPNOTSUPP; @@ -39,7 +47,7 @@ static int ocelot_flower_parse_action(struct flow_cls_offload *f,  }  static int ocelot_flower_parse(struct flow_cls_offload *f, -			       struct ocelot_ace_rule *ocelot_rule) +			       struct ocelot_ace_rule *ace)  {  	struct flow_rule *rule = flow_cls_offload_flow_rule(f);  	struct flow_dissector *dissector = rule->match.dissector; @@ -84,14 +92,14 @@ static int ocelot_flower_parse(struct flow_cls_offload *f,  			return -EOPNOTSUPP;  		flow_rule_match_eth_addrs(rule, &match); -		ocelot_rule->type = OCELOT_ACE_TYPE_ETYPE; -		ether_addr_copy(ocelot_rule->frame.etype.dmac.value, +		ace->type = OCELOT_ACE_TYPE_ETYPE; +		ether_addr_copy(ace->frame.etype.dmac.value,  				match.key->dst); -		ether_addr_copy(ocelot_rule->frame.etype.smac.value, +		ether_addr_copy(ace->frame.etype.smac.value,  				match.key->src); -		ether_addr_copy(ocelot_rule->frame.etype.dmac.mask, +		ether_addr_copy(ace->frame.etype.dmac.mask,  				match.mask->dst); -		ether_addr_copy(ocelot_rule->frame.etype.smac.mask, +		ether_addr_copy(ace->frame.etype.smac.mask,  				match.mask->src);  		goto finished_key_parsing;  	} @@ -101,17 +109,17 @@ static int ocelot_flower_parse(struct flow_cls_offload *f,  		flow_rule_match_basic(rule, &match);  		if (ntohs(match.key->n_proto) == ETH_P_IP) { -			ocelot_rule->type = OCELOT_ACE_TYPE_IPV4; -			ocelot_rule->frame.ipv4.proto.value[0] = +			ace->type = OCELOT_ACE_TYPE_IPV4; +			ace->frame.ipv4.proto.value[0] =  				match.key->ip_proto; -			ocelot_rule->frame.ipv4.proto.mask[0] = +			ace->frame.ipv4.proto.mask[0] =  				match.mask->ip_proto;  		}  		if (ntohs(match.key->n_proto) == ETH_P_IPV6) { -			ocelot_rule->type = OCELOT_ACE_TYPE_IPV6; -			ocelot_rule->frame.ipv6.proto.value[0] = +			ace->type = OCELOT_ACE_TYPE_IPV6; +			ace->frame.ipv6.proto.value[0] =  				match.key->ip_proto; -			ocelot_rule->frame.ipv6.proto.mask[0] = +			ace->frame.ipv6.proto.mask[0] =  				match.mask->ip_proto;  		}  	} @@ -122,16 +130,16 @@ static int ocelot_flower_parse(struct flow_cls_offload *f,  		u8 *tmp;  		flow_rule_match_ipv4_addrs(rule, &match); -		tmp = &ocelot_rule->frame.ipv4.sip.value.addr[0]; +		tmp = &ace->frame.ipv4.sip.value.addr[0];  		memcpy(tmp, &match.key->src, 4); -		tmp = &ocelot_rule->frame.ipv4.sip.mask.addr[0]; +		tmp = &ace->frame.ipv4.sip.mask.addr[0];  		memcpy(tmp, &match.mask->src, 4); -		tmp = &ocelot_rule->frame.ipv4.dip.value.addr[0]; +		tmp = &ace->frame.ipv4.dip.value.addr[0];  		memcpy(tmp, &match.key->dst, 4); -		tmp = &ocelot_rule->frame.ipv4.dip.mask.addr[0]; +		tmp = &ace->frame.ipv4.dip.mask.addr[0];  		memcpy(tmp, &match.mask->dst, 4);  	} @@ -144,213 +152,111 @@ static int ocelot_flower_parse(struct flow_cls_offload *f,  		struct flow_match_ports match;  		flow_rule_match_ports(rule, &match); -		ocelot_rule->frame.ipv4.sport.value = ntohs(match.key->src); -		ocelot_rule->frame.ipv4.sport.mask = ntohs(match.mask->src); -		ocelot_rule->frame.ipv4.dport.value = ntohs(match.key->dst); -		ocelot_rule->frame.ipv4.dport.mask = ntohs(match.mask->dst); +		ace->frame.ipv4.sport.value = ntohs(match.key->src); +		ace->frame.ipv4.sport.mask = ntohs(match.mask->src); +		ace->frame.ipv4.dport.value = ntohs(match.key->dst); +		ace->frame.ipv4.dport.mask = ntohs(match.mask->dst);  	}  	if (flow_rule_match_key(rule, FLOW_DISSECTOR_KEY_VLAN)) {  		struct flow_match_vlan match;  		flow_rule_match_vlan(rule, &match); -		ocelot_rule->type = OCELOT_ACE_TYPE_ANY; -		ocelot_rule->vlan.vid.value = match.key->vlan_id; -		ocelot_rule->vlan.vid.mask = match.mask->vlan_id; -		ocelot_rule->vlan.pcp.value[0] = match.key->vlan_priority; -		ocelot_rule->vlan.pcp.mask[0] = match.mask->vlan_priority; +		ace->type = OCELOT_ACE_TYPE_ANY; +		ace->vlan.vid.value = match.key->vlan_id; +		ace->vlan.vid.mask = match.mask->vlan_id; +		ace->vlan.pcp.value[0] = match.key->vlan_priority; +		ace->vlan.pcp.mask[0] = match.mask->vlan_priority;  	}  finished_key_parsing: -	ocelot_rule->prio = f->common.prio; -	ocelot_rule->id = f->cookie; -	return ocelot_flower_parse_action(f, ocelot_rule); +	ace->prio = f->common.prio; +	ace->id = f->cookie; +	return ocelot_flower_parse_action(f, ace);  }  static -struct ocelot_ace_rule *ocelot_ace_rule_create(struct flow_cls_offload *f, -					       struct ocelot_port_block *block) +struct ocelot_ace_rule *ocelot_ace_rule_create(struct ocelot *ocelot, int port, +					       struct flow_cls_offload *f)  { -	struct ocelot_ace_rule *rule; +	struct ocelot_ace_rule *ace; -	rule = kzalloc(sizeof(*rule), GFP_KERNEL); -	if (!rule) +	ace = kzalloc(sizeof(*ace), GFP_KERNEL); +	if (!ace)  		return NULL; -	rule->port = &block->priv->port; -	rule->chip_port = block->priv->chip_port; -	return rule; +	ace->ingress_port_mask = BIT(port); +	return ace;  } -static int ocelot_flower_replace(struct flow_cls_offload *f, -				 struct ocelot_port_block *port_block) +int ocelot_cls_flower_replace(struct ocelot *ocelot, int port, +			      struct flow_cls_offload *f, bool ingress)  { -	struct ocelot_ace_rule *rule; +	struct ocelot_ace_rule *ace;  	int ret; -	rule = ocelot_ace_rule_create(f, port_block); -	if (!rule) +	ace = ocelot_ace_rule_create(ocelot, port, f); +	if (!ace)  		return -ENOMEM; -	ret = ocelot_flower_parse(f, rule); +	ret = ocelot_flower_parse(f, ace);  	if (ret) { -		kfree(rule); +		kfree(ace);  		return ret;  	} -	ret = ocelot_ace_rule_offload_add(rule); -	if (ret) -		return ret; - -	port_block->priv->tc.offload_cnt++; -	return 0; +	return ocelot_ace_rule_offload_add(ocelot, ace);  } +EXPORT_SYMBOL_GPL(ocelot_cls_flower_replace); -static int ocelot_flower_destroy(struct flow_cls_offload *f, -				 struct ocelot_port_block *port_block) +int ocelot_cls_flower_destroy(struct ocelot *ocelot, int port, +			      struct flow_cls_offload *f, bool ingress)  { -	struct ocelot_ace_rule rule; -	int ret; - -	rule.prio = f->common.prio; -	rule.port = &port_block->priv->port; -	rule.id = f->cookie; +	struct ocelot_ace_rule ace; -	ret = ocelot_ace_rule_offload_del(&rule); -	if (ret) -		return ret; +	ace.prio = f->common.prio; +	ace.id = f->cookie; -	port_block->priv->tc.offload_cnt--; -	return 0; +	return ocelot_ace_rule_offload_del(ocelot, &ace);  } +EXPORT_SYMBOL_GPL(ocelot_cls_flower_destroy); -static int ocelot_flower_stats_update(struct flow_cls_offload *f, -				      struct ocelot_port_block *port_block) +int ocelot_cls_flower_stats(struct ocelot *ocelot, int port, +			    struct flow_cls_offload *f, bool ingress)  { -	struct ocelot_ace_rule rule; +	struct ocelot_ace_rule ace;  	int ret; -	rule.prio = f->common.prio; -	rule.port = &port_block->priv->port; -	rule.id = f->cookie; -	ret = ocelot_ace_rule_stats_update(&rule); +	ace.prio = f->common.prio; +	ace.id = f->cookie; +	ret = ocelot_ace_rule_stats_update(ocelot, &ace);  	if (ret)  		return ret; -	flow_stats_update(&f->stats, 0x0, rule.stats.pkts, 0x0); +	flow_stats_update(&f->stats, 0x0, ace.stats.pkts, 0x0, +			  FLOW_ACTION_HW_STATS_IMMEDIATE);  	return 0;  } +EXPORT_SYMBOL_GPL(ocelot_cls_flower_stats); -static int ocelot_setup_tc_cls_flower(struct flow_cls_offload *f, -				      struct ocelot_port_block *port_block) +int ocelot_setup_tc_cls_flower(struct ocelot_port_private *priv, +			       struct flow_cls_offload *f, +			       bool ingress)  { +	struct ocelot *ocelot = priv->port.ocelot; +	int port = priv->chip_port; + +	if (!ingress) +		return -EOPNOTSUPP; +  	switch (f->command) {  	case FLOW_CLS_REPLACE: -		return ocelot_flower_replace(f, port_block); +		return ocelot_cls_flower_replace(ocelot, port, f, ingress);  	case FLOW_CLS_DESTROY: -		return ocelot_flower_destroy(f, port_block); +		return ocelot_cls_flower_destroy(ocelot, port, f, ingress);  	case FLOW_CLS_STATS: -		return ocelot_flower_stats_update(f, port_block); -	default: -		return -EOPNOTSUPP; -	} -} - -static int ocelot_setup_tc_block_cb_flower(enum tc_setup_type type, -					   void *type_data, void *cb_priv) -{ -	struct ocelot_port_block *port_block = cb_priv; - -	if (!tc_cls_can_offload_and_chain0(port_block->priv->dev, type_data)) -		return -EOPNOTSUPP; - -	switch (type) { -	case TC_SETUP_CLSFLOWER: -		return ocelot_setup_tc_cls_flower(type_data, cb_priv); -	case TC_SETUP_CLSMATCHALL: -		return 0; +		return ocelot_cls_flower_stats(ocelot, port, f, ingress);  	default:  		return -EOPNOTSUPP;  	}  } - -static struct ocelot_port_block* -ocelot_port_block_create(struct ocelot_port_private *priv) -{ -	struct ocelot_port_block *port_block; - -	port_block = kzalloc(sizeof(*port_block), GFP_KERNEL); -	if (!port_block) -		return NULL; - -	port_block->priv = priv; - -	return port_block; -} - -static void ocelot_port_block_destroy(struct ocelot_port_block *block) -{ -	kfree(block); -} - -static void ocelot_tc_block_unbind(void *cb_priv) -{ -	struct ocelot_port_block *port_block = cb_priv; - -	ocelot_port_block_destroy(port_block); -} - -int ocelot_setup_tc_block_flower_bind(struct ocelot_port_private *priv, -				      struct flow_block_offload *f) -{ -	struct ocelot_port_block *port_block; -	struct flow_block_cb *block_cb; -	int ret; - -	if (f->binder_type == FLOW_BLOCK_BINDER_TYPE_CLSACT_EGRESS) -		return -EOPNOTSUPP; - -	block_cb = flow_block_cb_lookup(f->block, -					ocelot_setup_tc_block_cb_flower, priv); -	if (!block_cb) { -		port_block = ocelot_port_block_create(priv); -		if (!port_block) -			return -ENOMEM; - -		block_cb = flow_block_cb_alloc(ocelot_setup_tc_block_cb_flower, -					       priv, port_block, -					       ocelot_tc_block_unbind); -		if (IS_ERR(block_cb)) { -			ret = PTR_ERR(block_cb); -			goto err_cb_register; -		} -		flow_block_cb_add(block_cb, f); -		list_add_tail(&block_cb->driver_list, f->driver_block_list); -	} else { -		port_block = flow_block_cb_priv(block_cb); -	} - -	flow_block_cb_incref(block_cb); -	return 0; - -err_cb_register: -	ocelot_port_block_destroy(port_block); - -	return ret; -} - -void ocelot_setup_tc_block_flower_unbind(struct ocelot_port_private *priv, -					 struct flow_block_offload *f) -{ -	struct flow_block_cb *block_cb; - -	block_cb = flow_block_cb_lookup(f->block, -					ocelot_setup_tc_block_cb_flower, priv); -	if (!block_cb) -		return; - -	if (!flow_block_cb_decref(block_cb)) { -		flow_block_cb_remove(block_cb, f); -		list_del(&block_cb->driver_list); -	} -} diff --git a/drivers/net/ethernet/mscc/ocelot_police.c b/drivers/net/ethernet/mscc/ocelot_police.c index faddce43f2e3..2e1d8e187332 100644 --- a/drivers/net/ethernet/mscc/ocelot_police.c +++ b/drivers/net/ethernet/mscc/ocelot_police.c @@ -4,6 +4,7 @@   * Copyright (c) 2019 Microsemi Corporation   */ +#include <soc/mscc/ocelot.h>  #include "ocelot_police.h"  enum mscc_qos_rate_mode { @@ -203,6 +204,7 @@ int ocelot_port_policer_add(struct ocelot *ocelot, int port,  	return 0;  } +EXPORT_SYMBOL(ocelot_port_policer_add);  int ocelot_port_policer_del(struct ocelot *ocelot, int port)  { @@ -225,3 +227,28 @@ int ocelot_port_policer_del(struct ocelot *ocelot, int port)  	return 0;  } +EXPORT_SYMBOL(ocelot_port_policer_del); + +int ocelot_ace_policer_add(struct ocelot *ocelot, u32 pol_ix, +			   struct ocelot_policer *pol) +{ +	struct qos_policer_conf pp = { 0 }; + +	if (!pol) +		return -EINVAL; + +	pp.mode = MSCC_QOS_RATE_MODE_DATA; +	pp.pir = pol->rate; +	pp.pbs = pol->burst; + +	return qos_policer_conf_set(ocelot, 0, pol_ix, &pp); +} + +int ocelot_ace_policer_del(struct ocelot *ocelot, u32 pol_ix) +{ +	struct qos_policer_conf pp = { 0 }; + +	pp.mode = MSCC_QOS_RATE_MODE_DISABLED; + +	return qos_policer_conf_set(ocelot, 0, pol_ix, &pp); +} diff --git a/drivers/net/ethernet/mscc/ocelot_police.h b/drivers/net/ethernet/mscc/ocelot_police.h index ae9509229463..792abd28010a 100644 --- a/drivers/net/ethernet/mscc/ocelot_police.h +++ b/drivers/net/ethernet/mscc/ocelot_police.h @@ -9,14 +9,9 @@  #include "ocelot.h" -struct ocelot_policer { -	u32 rate; /* kilobit per second */ -	u32 burst; /* bytes */ -}; +int ocelot_ace_policer_add(struct ocelot *ocelot, u32 pol_ix, +			   struct ocelot_policer *pol); -int ocelot_port_policer_add(struct ocelot *ocelot, int port, -			    struct ocelot_policer *pol); - -int ocelot_port_policer_del(struct ocelot *ocelot, int port); +int ocelot_ace_policer_del(struct ocelot *ocelot, u32 pol_ix);  #endif /* _MSCC_OCELOT_POLICE_H_ */ diff --git a/drivers/net/ethernet/mscc/ocelot_regs.c b/drivers/net/ethernet/mscc/ocelot_regs.c index b88b5899b227..7d4fd1b6adda 100644 --- a/drivers/net/ethernet/mscc/ocelot_regs.c +++ b/drivers/net/ethernet/mscc/ocelot_regs.c @@ -431,6 +431,7 @@ int ocelot_chip_init(struct ocelot *ocelot, const struct ocelot_ops *ops)  	ocelot->stats_layout = ocelot_stats_layout;  	ocelot->num_stats = ARRAY_SIZE(ocelot_stats_layout);  	ocelot->shared_queue_sz = 224 * 1024; +	ocelot->num_mact_rows = 1024;  	ocelot->ops = ops;  	ret = ocelot_regfields_init(ocelot, ocelot_regfields); diff --git a/drivers/net/ethernet/mscc/ocelot_tc.c b/drivers/net/ethernet/mscc/ocelot_tc.c index a4f7fbd76507..d326e231f0ad 100644 --- a/drivers/net/ethernet/mscc/ocelot_tc.c +++ b/drivers/net/ethernet/mscc/ocelot_tc.c @@ -4,8 +4,8 @@   * Copyright (c) 2019 Microsemi Corporation   */ +#include <soc/mscc/ocelot.h>  #include "ocelot_tc.h" -#include "ocelot_police.h"  #include "ocelot_ace.h"  #include <net/pkt_cls.h> @@ -20,9 +20,6 @@ static int ocelot_setup_tc_cls_matchall(struct ocelot_port_private *priv,  	int port = priv->chip_port;  	int err; -	netdev_dbg(priv->dev, "%s: port %u command %d cookie %lu\n", -		   __func__, port, f->command, f->cookie); -  	if (!ingress) {  		NL_SET_ERR_MSG_MOD(extack, "Only ingress is supported");  		return -EOPNOTSUPP; @@ -99,17 +96,10 @@ static int ocelot_setup_tc_block_cb(enum tc_setup_type type,  	switch (type) {  	case TC_SETUP_CLSMATCHALL: -		netdev_dbg(priv->dev, "tc_block_cb: TC_SETUP_CLSMATCHALL %s\n", -			   ingress ? "ingress" : "egress"); -  		return ocelot_setup_tc_cls_matchall(priv, type_data, ingress);  	case TC_SETUP_CLSFLOWER: -		return 0; +		return ocelot_setup_tc_cls_flower(priv, type_data, ingress);  	default: -		netdev_dbg(priv->dev, "tc_block_cb: type %d %s\n", -			   type, -			   ingress ? "ingress" : "egress"); -  		return -EOPNOTSUPP;  	}  } @@ -137,10 +127,6 @@ static int ocelot_setup_tc_block(struct ocelot_port_private *priv,  {  	struct flow_block_cb *block_cb;  	flow_setup_cb_t *cb; -	int err; - -	netdev_dbg(priv->dev, "tc_block command %d, binder_type %d\n", -		   f->command, f->binder_type);  	if (f->binder_type == FLOW_BLOCK_BINDER_TYPE_CLSACT_INGRESS) {  		cb = ocelot_setup_tc_block_cb_ig; @@ -162,11 +148,6 @@ static int ocelot_setup_tc_block(struct ocelot_port_private *priv,  		if (IS_ERR(block_cb))  			return PTR_ERR(block_cb); -		err = ocelot_setup_tc_block_flower_bind(priv, f); -		if (err < 0) { -			flow_block_cb_free(block_cb); -			return err; -		}  		flow_block_cb_add(block_cb, f);  		list_add_tail(&block_cb->driver_list, f->driver_block_list);  		return 0; @@ -175,7 +156,6 @@ static int ocelot_setup_tc_block(struct ocelot_port_private *priv,  		if (!block_cb)  			return -ENOENT; -		ocelot_setup_tc_block_flower_unbind(priv, f);  		flow_block_cb_remove(block_cb, f);  		list_del(&block_cb->driver_list);  		return 0; diff --git a/drivers/net/ethernet/mscc/ocelot_vcap.h b/drivers/net/ethernet/mscc/ocelot_vcap.h deleted file mode 100644 index e22eac1da783..000000000000 --- a/drivers/net/ethernet/mscc/ocelot_vcap.h +++ /dev/null @@ -1,403 +0,0 @@ -/* SPDX-License-Identifier: (GPL-2.0 OR MIT) - * Microsemi Ocelot Switch driver - * Copyright (c) 2019 Microsemi Corporation - */ - -#ifndef _OCELOT_VCAP_H_ -#define _OCELOT_VCAP_H_ - -/* ================================================================= - *  VCAP Common - * ================================================================= - */ - -/* VCAP Type-Group values */ -#define VCAP_TG_NONE 0 /* Entry is invalid */ -#define VCAP_TG_FULL 1 /* Full entry */ -#define VCAP_TG_HALF 2 /* Half entry */ -#define VCAP_TG_QUARTER 3 /* Quarter entry */ - -/* ================================================================= - *  VCAP IS2 - * ================================================================= - */ - -#define VCAP_IS2_CNT 64 -#define VCAP_IS2_ENTRY_WIDTH 376 -#define VCAP_IS2_ACTION_WIDTH 99 -#define VCAP_PORT_CNT 11 - -/* IS2 half key types */ -#define IS2_TYPE_ETYPE 0 -#define IS2_TYPE_LLC 1 -#define IS2_TYPE_SNAP 2 -#define IS2_TYPE_ARP 3 -#define IS2_TYPE_IP_UDP_TCP 4 -#define IS2_TYPE_IP_OTHER 5 -#define IS2_TYPE_IPV6 6 -#define IS2_TYPE_OAM 7 -#define IS2_TYPE_SMAC_SIP6 8 -#define IS2_TYPE_ANY 100 /* Pseudo type */ - -/* IS2 half key type mask for matching any IP */ -#define IS2_TYPE_MASK_IP_ANY 0xe - -/* IS2 action types */ -#define IS2_ACTION_TYPE_NORMAL 0 -#define IS2_ACTION_TYPE_SMAC_SIP 1 - -/* IS2 MASK_MODE values */ -#define IS2_ACT_MASK_MODE_NONE 0 -#define IS2_ACT_MASK_MODE_FILTER 1 -#define IS2_ACT_MASK_MODE_POLICY 2 -#define IS2_ACT_MASK_MODE_REDIR 3 - -/* IS2 REW_OP values */ -#define IS2_ACT_REW_OP_NONE 0 -#define IS2_ACT_REW_OP_PTP_ONE 2 -#define IS2_ACT_REW_OP_PTP_TWO 3 -#define IS2_ACT_REW_OP_SPECIAL 8 -#define IS2_ACT_REW_OP_PTP_ORG 9 -#define IS2_ACT_REW_OP_PTP_ONE_SUB_DELAY_1 (IS2_ACT_REW_OP_PTP_ONE | (1 << 3)) -#define IS2_ACT_REW_OP_PTP_ONE_SUB_DELAY_2 (IS2_ACT_REW_OP_PTP_ONE | (2 << 3)) -#define IS2_ACT_REW_OP_PTP_ONE_ADD_DELAY (IS2_ACT_REW_OP_PTP_ONE | (1 << 5)) -#define IS2_ACT_REW_OP_PTP_ONE_ADD_SUB BIT(7) - -#define VCAP_PORT_WIDTH 4 - -/* IS2 quarter key - SMAC_SIP4 */ -#define IS2_QKO_IGR_PORT 0 -#define IS2_QKL_IGR_PORT VCAP_PORT_WIDTH -#define IS2_QKO_L2_SMAC (IS2_QKO_IGR_PORT + IS2_QKL_IGR_PORT) -#define IS2_QKL_L2_SMAC 48 -#define IS2_QKO_L3_IP4_SIP (IS2_QKO_L2_SMAC + IS2_QKL_L2_SMAC) -#define IS2_QKL_L3_IP4_SIP 32 - -/* IS2 half key - common */ -#define IS2_HKO_TYPE 0 -#define IS2_HKL_TYPE 4 -#define IS2_HKO_FIRST (IS2_HKO_TYPE + IS2_HKL_TYPE) -#define IS2_HKL_FIRST 1 -#define IS2_HKO_PAG (IS2_HKO_FIRST + IS2_HKL_FIRST) -#define IS2_HKL_PAG 8 -#define IS2_HKO_IGR_PORT_MASK (IS2_HKO_PAG + IS2_HKL_PAG) -#define IS2_HKL_IGR_PORT_MASK (VCAP_PORT_CNT + 1) -#define IS2_HKO_SERVICE_FRM (IS2_HKO_IGR_PORT_MASK + IS2_HKL_IGR_PORT_MASK) -#define IS2_HKL_SERVICE_FRM 1 -#define IS2_HKO_HOST_MATCH (IS2_HKO_SERVICE_FRM + IS2_HKL_SERVICE_FRM) -#define IS2_HKL_HOST_MATCH 1 -#define IS2_HKO_L2_MC (IS2_HKO_HOST_MATCH + IS2_HKL_HOST_MATCH) -#define IS2_HKL_L2_MC 1 -#define IS2_HKO_L2_BC (IS2_HKO_L2_MC + IS2_HKL_L2_MC) -#define IS2_HKL_L2_BC 1 -#define IS2_HKO_VLAN_TAGGED (IS2_HKO_L2_BC + IS2_HKL_L2_BC) -#define IS2_HKL_VLAN_TAGGED 1 -#define IS2_HKO_VID (IS2_HKO_VLAN_TAGGED + IS2_HKL_VLAN_TAGGED) -#define IS2_HKL_VID 12 -#define IS2_HKO_DEI (IS2_HKO_VID + IS2_HKL_VID) -#define IS2_HKL_DEI 1 -#define IS2_HKO_PCP (IS2_HKO_DEI + IS2_HKL_DEI) -#define IS2_HKL_PCP 3 - -/* IS2 half key - MAC_ETYPE/MAC_LLC/MAC_SNAP/OAM common */ -#define IS2_HKO_L2_DMAC (IS2_HKO_PCP + IS2_HKL_PCP) -#define IS2_HKL_L2_DMAC 48 -#define IS2_HKO_L2_SMAC (IS2_HKO_L2_DMAC + IS2_HKL_L2_DMAC) -#define IS2_HKL_L2_SMAC 48 - -/* IS2 half key - MAC_ETYPE */ -#define IS2_HKO_MAC_ETYPE_ETYPE (IS2_HKO_L2_SMAC + IS2_HKL_L2_SMAC) -#define IS2_HKL_MAC_ETYPE_ETYPE 16 -#define IS2_HKO_MAC_ETYPE_L2_PAYLOAD                                           \ -	(IS2_HKO_MAC_ETYPE_ETYPE + IS2_HKL_MAC_ETYPE_ETYPE) -#define IS2_HKL_MAC_ETYPE_L2_PAYLOAD 27 - -/* IS2 half key - MAC_LLC */ -#define IS2_HKO_MAC_LLC_L2_LLC IS2_HKO_MAC_ETYPE_ETYPE -#define IS2_HKL_MAC_LLC_L2_LLC 40 - -/* IS2 half key - MAC_SNAP */ -#define IS2_HKO_MAC_SNAP_L2_SNAP IS2_HKO_MAC_ETYPE_ETYPE -#define IS2_HKL_MAC_SNAP_L2_SNAP 40 - -/* IS2 half key - ARP */ -#define IS2_HKO_MAC_ARP_L2_SMAC IS2_HKO_L2_DMAC -#define IS2_HKL_MAC_ARP_L2_SMAC 48 -#define IS2_HKO_MAC_ARP_ARP_ADDR_SPACE_OK                                      \ -	(IS2_HKO_MAC_ARP_L2_SMAC + IS2_HKL_MAC_ARP_L2_SMAC) -#define IS2_HKL_MAC_ARP_ARP_ADDR_SPACE_OK 1 -#define IS2_HKO_MAC_ARP_ARP_PROTO_SPACE_OK                                     \ -	(IS2_HKO_MAC_ARP_ARP_ADDR_SPACE_OK + IS2_HKL_MAC_ARP_ARP_ADDR_SPACE_OK) -#define IS2_HKL_MAC_ARP_ARP_PROTO_SPACE_OK 1 -#define IS2_HKO_MAC_ARP_ARP_LEN_OK                                             \ -	(IS2_HKO_MAC_ARP_ARP_PROTO_SPACE_OK +                                  \ -	 IS2_HKL_MAC_ARP_ARP_PROTO_SPACE_OK) -#define IS2_HKL_MAC_ARP_ARP_LEN_OK 1 -#define IS2_HKO_MAC_ARP_ARP_TGT_MATCH                                          \ -	(IS2_HKO_MAC_ARP_ARP_LEN_OK + IS2_HKL_MAC_ARP_ARP_LEN_OK) -#define IS2_HKL_MAC_ARP_ARP_TGT_MATCH 1 -#define IS2_HKO_MAC_ARP_ARP_SENDER_MATCH                                       \ -	(IS2_HKO_MAC_ARP_ARP_TGT_MATCH + IS2_HKL_MAC_ARP_ARP_TGT_MATCH) -#define IS2_HKL_MAC_ARP_ARP_SENDER_MATCH 1 -#define IS2_HKO_MAC_ARP_ARP_OPCODE_UNKNOWN                                     \ -	(IS2_HKO_MAC_ARP_ARP_SENDER_MATCH + IS2_HKL_MAC_ARP_ARP_SENDER_MATCH) -#define IS2_HKL_MAC_ARP_ARP_OPCODE_UNKNOWN 1 -#define IS2_HKO_MAC_ARP_ARP_OPCODE                                             \ -	(IS2_HKO_MAC_ARP_ARP_OPCODE_UNKNOWN +                                  \ -	 IS2_HKL_MAC_ARP_ARP_OPCODE_UNKNOWN) -#define IS2_HKL_MAC_ARP_ARP_OPCODE 2 -#define IS2_HKO_MAC_ARP_L3_IP4_DIP                                             \ -	(IS2_HKO_MAC_ARP_ARP_OPCODE + IS2_HKL_MAC_ARP_ARP_OPCODE) -#define IS2_HKL_MAC_ARP_L3_IP4_DIP 32 -#define IS2_HKO_MAC_ARP_L3_IP4_SIP                                             \ -	(IS2_HKO_MAC_ARP_L3_IP4_DIP + IS2_HKL_MAC_ARP_L3_IP4_DIP) -#define IS2_HKL_MAC_ARP_L3_IP4_SIP 32 -#define IS2_HKO_MAC_ARP_DIP_EQ_SIP                                             \ -	(IS2_HKO_MAC_ARP_L3_IP4_SIP + IS2_HKL_MAC_ARP_L3_IP4_SIP) -#define IS2_HKL_MAC_ARP_DIP_EQ_SIP 1 - -/* IS2 half key - IP4_TCP_UDP/IP4_OTHER common */ -#define IS2_HKO_IP4 IS2_HKO_L2_DMAC -#define IS2_HKL_IP4 1 -#define IS2_HKO_L3_FRAGMENT (IS2_HKO_IP4 + IS2_HKL_IP4) -#define IS2_HKL_L3_FRAGMENT 1 -#define IS2_HKO_L3_FRAG_OFS_GT0 (IS2_HKO_L3_FRAGMENT + IS2_HKL_L3_FRAGMENT) -#define IS2_HKL_L3_FRAG_OFS_GT0 1 -#define IS2_HKO_L3_OPTIONS (IS2_HKO_L3_FRAG_OFS_GT0 + IS2_HKL_L3_FRAG_OFS_GT0) -#define IS2_HKL_L3_OPTIONS 1 -#define IS2_HKO_L3_TTL_GT0 (IS2_HKO_L3_OPTIONS + IS2_HKL_L3_OPTIONS) -#define IS2_HKL_L3_TTL_GT0 1 -#define IS2_HKO_L3_TOS (IS2_HKO_L3_TTL_GT0 + IS2_HKL_L3_TTL_GT0) -#define IS2_HKL_L3_TOS 8 -#define IS2_HKO_L3_IP4_DIP (IS2_HKO_L3_TOS + IS2_HKL_L3_TOS) -#define IS2_HKL_L3_IP4_DIP 32 -#define IS2_HKO_L3_IP4_SIP (IS2_HKO_L3_IP4_DIP + IS2_HKL_L3_IP4_DIP) -#define IS2_HKL_L3_IP4_SIP 32 -#define IS2_HKO_DIP_EQ_SIP (IS2_HKO_L3_IP4_SIP + IS2_HKL_L3_IP4_SIP) -#define IS2_HKL_DIP_EQ_SIP 1 - -/* IS2 half key - IP4_TCP_UDP */ -#define IS2_HKO_IP4_TCP_UDP_TCP (IS2_HKO_DIP_EQ_SIP + IS2_HKL_DIP_EQ_SIP) -#define IS2_HKL_IP4_TCP_UDP_TCP 1 -#define IS2_HKO_IP4_TCP_UDP_L4_DPORT                                           \ -	(IS2_HKO_IP4_TCP_UDP_TCP + IS2_HKL_IP4_TCP_UDP_TCP) -#define IS2_HKL_IP4_TCP_UDP_L4_DPORT 16 -#define IS2_HKO_IP4_TCP_UDP_L4_SPORT                                           \ -	(IS2_HKO_IP4_TCP_UDP_L4_DPORT + IS2_HKL_IP4_TCP_UDP_L4_DPORT) -#define IS2_HKL_IP4_TCP_UDP_L4_SPORT 16 -#define IS2_HKO_IP4_TCP_UDP_L4_RNG                                             \ -	(IS2_HKO_IP4_TCP_UDP_L4_SPORT + IS2_HKL_IP4_TCP_UDP_L4_SPORT) -#define IS2_HKL_IP4_TCP_UDP_L4_RNG 8 -#define IS2_HKO_IP4_TCP_UDP_SPORT_EQ_DPORT                                     \ -	(IS2_HKO_IP4_TCP_UDP_L4_RNG + IS2_HKL_IP4_TCP_UDP_L4_RNG) -#define IS2_HKL_IP4_TCP_UDP_SPORT_EQ_DPORT 1 -#define IS2_HKO_IP4_TCP_UDP_SEQUENCE_EQ0                                       \ -	(IS2_HKO_IP4_TCP_UDP_SPORT_EQ_DPORT +                                  \ -	 IS2_HKL_IP4_TCP_UDP_SPORT_EQ_DPORT) -#define IS2_HKL_IP4_TCP_UDP_SEQUENCE_EQ0 1 -#define IS2_HKO_IP4_TCP_UDP_L4_FIN                                             \ -	(IS2_HKO_IP4_TCP_UDP_SEQUENCE_EQ0 + IS2_HKL_IP4_TCP_UDP_SEQUENCE_EQ0) -#define IS2_HKL_IP4_TCP_UDP_L4_FIN 1 -#define IS2_HKO_IP4_TCP_UDP_L4_SYN                                             \ -	(IS2_HKO_IP4_TCP_UDP_L4_FIN + IS2_HKL_IP4_TCP_UDP_L4_FIN) -#define IS2_HKL_IP4_TCP_UDP_L4_SYN 1 -#define IS2_HKO_IP4_TCP_UDP_L4_RST                                             \ -	(IS2_HKO_IP4_TCP_UDP_L4_SYN + IS2_HKL_IP4_TCP_UDP_L4_SYN) -#define IS2_HKL_IP4_TCP_UDP_L4_RST 1 -#define IS2_HKO_IP4_TCP_UDP_L4_PSH                                             \ -	(IS2_HKO_IP4_TCP_UDP_L4_RST + IS2_HKL_IP4_TCP_UDP_L4_RST) -#define IS2_HKL_IP4_TCP_UDP_L4_PSH 1 -#define IS2_HKO_IP4_TCP_UDP_L4_ACK                                             \ -	(IS2_HKO_IP4_TCP_UDP_L4_PSH + IS2_HKL_IP4_TCP_UDP_L4_PSH) -#define IS2_HKL_IP4_TCP_UDP_L4_ACK 1 -#define IS2_HKO_IP4_TCP_UDP_L4_URG                                             \ -	(IS2_HKO_IP4_TCP_UDP_L4_ACK + IS2_HKL_IP4_TCP_UDP_L4_ACK) -#define IS2_HKL_IP4_TCP_UDP_L4_URG 1 -#define IS2_HKO_IP4_TCP_UDP_L4_1588_DOM                                        \ -	(IS2_HKO_IP4_TCP_UDP_L4_URG + IS2_HKL_IP4_TCP_UDP_L4_URG) -#define IS2_HKL_IP4_TCP_UDP_L4_1588_DOM 8 -#define IS2_HKO_IP4_TCP_UDP_L4_1588_VER                                        \ -	(IS2_HKO_IP4_TCP_UDP_L4_1588_DOM + IS2_HKL_IP4_TCP_UDP_L4_1588_DOM) -#define IS2_HKL_IP4_TCP_UDP_L4_1588_VER 4 - -/* IS2 half key - IP4_OTHER */ -#define IS2_HKO_IP4_OTHER_L3_PROTO IS2_HKO_IP4_TCP_UDP_TCP -#define IS2_HKL_IP4_OTHER_L3_PROTO 8 -#define IS2_HKO_IP4_OTHER_L3_PAYLOAD                                           \ -	(IS2_HKO_IP4_OTHER_L3_PROTO + IS2_HKL_IP4_OTHER_L3_PROTO) -#define IS2_HKL_IP4_OTHER_L3_PAYLOAD 56 - -/* IS2 half key - IP6_STD */ -#define IS2_HKO_IP6_STD_L3_TTL_GT0 IS2_HKO_L2_DMAC -#define IS2_HKL_IP6_STD_L3_TTL_GT0 1 -#define IS2_HKO_IP6_STD_L3_IP6_SIP                                             \ -	(IS2_HKO_IP6_STD_L3_TTL_GT0 + IS2_HKL_IP6_STD_L3_TTL_GT0) -#define IS2_HKL_IP6_STD_L3_IP6_SIP 128 -#define IS2_HKO_IP6_STD_L3_PROTO                                               \ -	(IS2_HKO_IP6_STD_L3_IP6_SIP + IS2_HKL_IP6_STD_L3_IP6_SIP) -#define IS2_HKL_IP6_STD_L3_PROTO 8 - -/* IS2 half key - OAM */ -#define IS2_HKO_OAM_OAM_MEL_FLAGS IS2_HKO_MAC_ETYPE_ETYPE -#define IS2_HKL_OAM_OAM_MEL_FLAGS 7 -#define IS2_HKO_OAM_OAM_VER                                                    \ -	(IS2_HKO_OAM_OAM_MEL_FLAGS + IS2_HKL_OAM_OAM_MEL_FLAGS) -#define IS2_HKL_OAM_OAM_VER 5 -#define IS2_HKO_OAM_OAM_OPCODE (IS2_HKO_OAM_OAM_VER + IS2_HKL_OAM_OAM_VER) -#define IS2_HKL_OAM_OAM_OPCODE 8 -#define IS2_HKO_OAM_OAM_FLAGS (IS2_HKO_OAM_OAM_OPCODE + IS2_HKL_OAM_OAM_OPCODE) -#define IS2_HKL_OAM_OAM_FLAGS 8 -#define IS2_HKO_OAM_OAM_MEPID (IS2_HKO_OAM_OAM_FLAGS + IS2_HKL_OAM_OAM_FLAGS) -#define IS2_HKL_OAM_OAM_MEPID 16 -#define IS2_HKO_OAM_OAM_CCM_CNTS_EQ0                                           \ -	(IS2_HKO_OAM_OAM_MEPID + IS2_HKL_OAM_OAM_MEPID) -#define IS2_HKL_OAM_OAM_CCM_CNTS_EQ0 1 - -/* IS2 half key - SMAC_SIP6 */ -#define IS2_HKO_SMAC_SIP6_IGR_PORT IS2_HKL_TYPE -#define IS2_HKL_SMAC_SIP6_IGR_PORT VCAP_PORT_WIDTH -#define IS2_HKO_SMAC_SIP6_L2_SMAC                                              \ -	(IS2_HKO_SMAC_SIP6_IGR_PORT + IS2_HKL_SMAC_SIP6_IGR_PORT) -#define IS2_HKL_SMAC_SIP6_L2_SMAC 48 -#define IS2_HKO_SMAC_SIP6_L3_IP6_SIP                                           \ -	(IS2_HKO_SMAC_SIP6_L2_SMAC + IS2_HKL_SMAC_SIP6_L2_SMAC) -#define IS2_HKL_SMAC_SIP6_L3_IP6_SIP 128 - -/* IS2 full key - common */ -#define IS2_FKO_TYPE 0 -#define IS2_FKL_TYPE 2 -#define IS2_FKO_FIRST (IS2_FKO_TYPE + IS2_FKL_TYPE) -#define IS2_FKL_FIRST 1 -#define IS2_FKO_PAG (IS2_FKO_FIRST + IS2_FKL_FIRST) -#define IS2_FKL_PAG 8 -#define IS2_FKO_IGR_PORT_MASK (IS2_FKO_PAG + IS2_FKL_PAG) -#define IS2_FKL_IGR_PORT_MASK (VCAP_PORT_CNT + 1) -#define IS2_FKO_SERVICE_FRM (IS2_FKO_IGR_PORT_MASK + IS2_FKL_IGR_PORT_MASK) -#define IS2_FKL_SERVICE_FRM 1 -#define IS2_FKO_HOST_MATCH (IS2_FKO_SERVICE_FRM + IS2_FKL_SERVICE_FRM) -#define IS2_FKL_HOST_MATCH 1 -#define IS2_FKO_L2_MC (IS2_FKO_HOST_MATCH + IS2_FKL_HOST_MATCH) -#define IS2_FKL_L2_MC 1 -#define IS2_FKO_L2_BC (IS2_FKO_L2_MC + IS2_FKL_L2_MC) -#define IS2_FKL_L2_BC 1 -#define IS2_FKO_VLAN_TAGGED (IS2_FKO_L2_BC + IS2_FKL_L2_BC) -#define IS2_FKL_VLAN_TAGGED 1 -#define IS2_FKO_VID (IS2_FKO_VLAN_TAGGED + IS2_FKL_VLAN_TAGGED) -#define IS2_FKL_VID 12 -#define IS2_FKO_DEI (IS2_FKO_VID + IS2_FKL_VID) -#define IS2_FKL_DEI 1 -#define IS2_FKO_PCP (IS2_FKO_DEI + IS2_FKL_DEI) -#define IS2_FKL_PCP 3 - -/* IS2 full key - IP6_TCP_UDP/IP6_OTHER common */ -#define IS2_FKO_L3_TTL_GT0 (IS2_FKO_PCP + IS2_FKL_PCP) -#define IS2_FKL_L3_TTL_GT0 1 -#define IS2_FKO_L3_TOS (IS2_FKO_L3_TTL_GT0 + IS2_FKL_L3_TTL_GT0) -#define IS2_FKL_L3_TOS 8 -#define IS2_FKO_L3_IP6_DIP (IS2_FKO_L3_TOS + IS2_FKL_L3_TOS) -#define IS2_FKL_L3_IP6_DIP 128 -#define IS2_FKO_L3_IP6_SIP (IS2_FKO_L3_IP6_DIP + IS2_FKL_L3_IP6_DIP) -#define IS2_FKL_L3_IP6_SIP 128 -#define IS2_FKO_DIP_EQ_SIP (IS2_FKO_L3_IP6_SIP + IS2_FKL_L3_IP6_SIP) -#define IS2_FKL_DIP_EQ_SIP 1 - -/* IS2 full key - IP6_TCP_UDP */ -#define IS2_FKO_IP6_TCP_UDP_TCP (IS2_FKO_DIP_EQ_SIP + IS2_FKL_DIP_EQ_SIP) -#define IS2_FKL_IP6_TCP_UDP_TCP 1 -#define IS2_FKO_IP6_TCP_UDP_L4_DPORT                                           \ -	(IS2_FKO_IP6_TCP_UDP_TCP + IS2_FKL_IP6_TCP_UDP_TCP) -#define IS2_FKL_IP6_TCP_UDP_L4_DPORT 16 -#define IS2_FKO_IP6_TCP_UDP_L4_SPORT                                           \ -	(IS2_FKO_IP6_TCP_UDP_L4_DPORT + IS2_FKL_IP6_TCP_UDP_L4_DPORT) -#define IS2_FKL_IP6_TCP_UDP_L4_SPORT 16 -#define IS2_FKO_IP6_TCP_UDP_L4_RNG                                             \ -	(IS2_FKO_IP6_TCP_UDP_L4_SPORT + IS2_FKL_IP6_TCP_UDP_L4_SPORT) -#define IS2_FKL_IP6_TCP_UDP_L4_RNG 8 -#define IS2_FKO_IP6_TCP_UDP_SPORT_EQ_DPORT                                     \ -	(IS2_FKO_IP6_TCP_UDP_L4_RNG + IS2_FKL_IP6_TCP_UDP_L4_RNG) -#define IS2_FKL_IP6_TCP_UDP_SPORT_EQ_DPORT 1 -#define IS2_FKO_IP6_TCP_UDP_SEQUENCE_EQ0                                       \ -	(IS2_FKO_IP6_TCP_UDP_SPORT_EQ_DPORT +                                  \ -	 IS2_FKL_IP6_TCP_UDP_SPORT_EQ_DPORT) -#define IS2_FKL_IP6_TCP_UDP_SEQUENCE_EQ0 1 -#define IS2_FKO_IP6_TCP_UDP_L4_FIN                                             \ -	(IS2_FKO_IP6_TCP_UDP_SEQUENCE_EQ0 + IS2_FKL_IP6_TCP_UDP_SEQUENCE_EQ0) -#define IS2_FKL_IP6_TCP_UDP_L4_FIN 1 -#define IS2_FKO_IP6_TCP_UDP_L4_SYN                                             \ -	(IS2_FKO_IP6_TCP_UDP_L4_FIN + IS2_FKL_IP6_TCP_UDP_L4_FIN) -#define IS2_FKL_IP6_TCP_UDP_L4_SYN 1 -#define IS2_FKO_IP6_TCP_UDP_L4_RST                                             \ -	(IS2_FKO_IP6_TCP_UDP_L4_SYN + IS2_FKL_IP6_TCP_UDP_L4_SYN) -#define IS2_FKL_IP6_TCP_UDP_L4_RST 1 -#define IS2_FKO_IP6_TCP_UDP_L4_PSH                                             \ -	(IS2_FKO_IP6_TCP_UDP_L4_RST + IS2_FKL_IP6_TCP_UDP_L4_RST) -#define IS2_FKL_IP6_TCP_UDP_L4_PSH 1 -#define IS2_FKO_IP6_TCP_UDP_L4_ACK                                             \ -	(IS2_FKO_IP6_TCP_UDP_L4_PSH + IS2_FKL_IP6_TCP_UDP_L4_PSH) -#define IS2_FKL_IP6_TCP_UDP_L4_ACK 1 -#define IS2_FKO_IP6_TCP_UDP_L4_URG                                             \ -	(IS2_FKO_IP6_TCP_UDP_L4_ACK + IS2_FKL_IP6_TCP_UDP_L4_ACK) -#define IS2_FKL_IP6_TCP_UDP_L4_URG 1 -#define IS2_FKO_IP6_TCP_UDP_L4_1588_DOM                                        \ -	(IS2_FKO_IP6_TCP_UDP_L4_URG + IS2_FKL_IP6_TCP_UDP_L4_URG) -#define IS2_FKL_IP6_TCP_UDP_L4_1588_DOM 8 -#define IS2_FKO_IP6_TCP_UDP_L4_1588_VER                                        \ -	(IS2_FKO_IP6_TCP_UDP_L4_1588_DOM + IS2_FKL_IP6_TCP_UDP_L4_1588_DOM) -#define IS2_FKL_IP6_TCP_UDP_L4_1588_VER 4 - -/* IS2 full key - IP6_OTHER */ -#define IS2_FKO_IP6_OTHER_L3_PROTO IS2_FKO_IP6_TCP_UDP_TCP -#define IS2_FKL_IP6_OTHER_L3_PROTO 8 -#define IS2_FKO_IP6_OTHER_L3_PAYLOAD                                           \ -	(IS2_FKO_IP6_OTHER_L3_PROTO + IS2_FKL_IP6_OTHER_L3_PROTO) -#define IS2_FKL_IP6_OTHER_L3_PAYLOAD 56 - -/* IS2 full key - CUSTOM */ -#define IS2_FKO_CUSTOM_CUSTOM_TYPE IS2_FKO_L3_TTL_GT0 -#define IS2_FKL_CUSTOM_CUSTOM_TYPE 1 -#define IS2_FKO_CUSTOM_CUSTOM                                                  \ -	(IS2_FKO_CUSTOM_CUSTOM_TYPE + IS2_FKL_CUSTOM_CUSTOM_TYPE) -#define IS2_FKL_CUSTOM_CUSTOM 320 - -/* IS2 action - BASE_TYPE */ -#define IS2_AO_HIT_ME_ONCE 0 -#define IS2_AL_HIT_ME_ONCE 1 -#define IS2_AO_CPU_COPY_ENA (IS2_AO_HIT_ME_ONCE + IS2_AL_HIT_ME_ONCE) -#define IS2_AL_CPU_COPY_ENA 1 -#define IS2_AO_CPU_QU_NUM (IS2_AO_CPU_COPY_ENA + IS2_AL_CPU_COPY_ENA) -#define IS2_AL_CPU_QU_NUM 3 -#define IS2_AO_MASK_MODE (IS2_AO_CPU_QU_NUM + IS2_AL_CPU_QU_NUM) -#define IS2_AL_MASK_MODE 2 -#define IS2_AO_MIRROR_ENA (IS2_AO_MASK_MODE + IS2_AL_MASK_MODE) -#define IS2_AL_MIRROR_ENA 1 -#define IS2_AO_LRN_DIS (IS2_AO_MIRROR_ENA + IS2_AL_MIRROR_ENA) -#define IS2_AL_LRN_DIS 1 -#define IS2_AO_POLICE_ENA (IS2_AO_LRN_DIS + IS2_AL_LRN_DIS) -#define IS2_AL_POLICE_ENA 1 -#define IS2_AO_POLICE_IDX (IS2_AO_POLICE_ENA + IS2_AL_POLICE_ENA) -#define IS2_AL_POLICE_IDX 9 -#define IS2_AO_POLICE_VCAP_ONLY (IS2_AO_POLICE_IDX + IS2_AL_POLICE_IDX) -#define IS2_AL_POLICE_VCAP_ONLY 1 -#define IS2_AO_PORT_MASK (IS2_AO_POLICE_VCAP_ONLY + IS2_AL_POLICE_VCAP_ONLY) -#define IS2_AL_PORT_MASK VCAP_PORT_CNT -#define IS2_AO_REW_OP (IS2_AO_PORT_MASK + IS2_AL_PORT_MASK) -#define IS2_AL_REW_OP 9 -#define IS2_AO_LM_CNT_DIS (IS2_AO_REW_OP + IS2_AL_REW_OP) -#define IS2_AL_LM_CNT_DIS 1 -#define IS2_AO_ISDX_ENA                                                        \ -	(IS2_AO_LM_CNT_DIS + IS2_AL_LM_CNT_DIS + 1) /* Reserved bit */ -#define IS2_AL_ISDX_ENA 1 -#define IS2_AO_ACL_ID (IS2_AO_ISDX_ENA + IS2_AL_ISDX_ENA) -#define IS2_AL_ACL_ID 6 - -/* IS2 action - SMAC_SIP */ -#define IS2_AO_SMAC_SIP_CPU_COPY_ENA 0 -#define IS2_AL_SMAC_SIP_CPU_COPY_ENA 1 -#define IS2_AO_SMAC_SIP_CPU_QU_NUM 1 -#define IS2_AL_SMAC_SIP_CPU_QU_NUM 3 -#define IS2_AO_SMAC_SIP_FWD_KILL_ENA 4 -#define IS2_AL_SMAC_SIP_FWD_KILL_ENA 1 -#define IS2_AO_SMAC_SIP_HOST_MATCH 5 -#define IS2_AL_SMAC_SIP_HOST_MATCH 1 - -#endif /* _OCELOT_VCAP_H_ */ |