diff options
| author | Dmitry Torokhov <[email protected]> | 2023-08-30 16:06:38 -0700 | 
|---|---|---|
| committer | Dmitry Torokhov <[email protected]> | 2023-08-30 16:06:38 -0700 | 
| commit | 1ac731c529cd4d6adbce134754b51ff7d822b145 (patch) | |
| tree | 143ab3f35ca5f3b69f583c84e6964b17139c2ec1 /drivers/net/ethernet/microchip | |
| parent | 07b4c950f27bef0362dc6ad7ee713aab61d58149 (diff) | |
| parent | 54116d442e001e1b6bd482122043b1870998a1f3 (diff) | |
Merge branch 'next' into for-linus
Prepare input updates for 6.6 merge window.
Diffstat (limited to 'drivers/net/ethernet/microchip')
23 files changed, 2814 insertions, 169 deletions
diff --git a/drivers/net/ethernet/microchip/lan743x_main.c b/drivers/net/ethernet/microchip/lan743x_main.c index 7e0871b631e4..957d96a91a8a 100644 --- a/drivers/net/ethernet/microchip/lan743x_main.c +++ b/drivers/net/ethernet/microchip/lan743x_main.c @@ -1466,7 +1466,6 @@ static void lan743x_phy_close(struct lan743x_adapter *adapter)  	phy_stop(netdev->phydev);  	phy_disconnect(netdev->phydev); -	netdev->phydev = NULL;  }  static void lan743x_phy_interface_select(struct lan743x_adapter *adapter) diff --git a/drivers/net/ethernet/microchip/lan966x/Kconfig b/drivers/net/ethernet/microchip/lan966x/Kconfig index 8bcd60f17d6d..571e6d4da1e9 100644 --- a/drivers/net/ethernet/microchip/lan966x/Kconfig +++ b/drivers/net/ethernet/microchip/lan966x/Kconfig @@ -6,7 +6,6 @@ config LAN966X_SWITCH  	depends on NET_SWITCHDEV  	depends on BRIDGE || BRIDGE=n  	select PHYLINK -	select PACKING  	select PAGE_POOL  	select VCAP  	help diff --git a/drivers/net/ethernet/microchip/lan966x/lan966x_fdma.c b/drivers/net/ethernet/microchip/lan966x/lan966x_fdma.c index 55b484b10562..bd72fbc2220f 100644 --- a/drivers/net/ethernet/microchip/lan966x/lan966x_fdma.c +++ b/drivers/net/ethernet/microchip/lan966x/lan966x_fdma.c @@ -390,6 +390,7 @@ static void lan966x_fdma_stop_netdev(struct lan966x *lan966x)  static void lan966x_fdma_tx_clear_buf(struct lan966x *lan966x, int weight)  {  	struct lan966x_tx *tx = &lan966x->tx; +	struct lan966x_rx *rx = &lan966x->rx;  	struct lan966x_tx_dcb_buf *dcb_buf;  	struct xdp_frame_bulk bq;  	struct lan966x_db *db; @@ -432,7 +433,8 @@ static void lan966x_fdma_tx_clear_buf(struct lan966x *lan966x, int weight)  			if (dcb_buf->xdp_ndo)  				xdp_return_frame_bulk(dcb_buf->data.xdpf, &bq);  			else -				xdp_return_frame_rx_napi(dcb_buf->data.xdpf); +				page_pool_recycle_direct(rx->page_pool, +							 dcb_buf->data.page);  		}  		clear = true; @@ -517,7 +519,7 @@ static struct sk_buff *lan966x_fdma_rx_get_frame(struct lan966x_rx *rx,  	if (likely(!(skb->dev->features & NETIF_F_RXFCS)))  		skb_trim(skb, skb->len - ETH_FCS_LEN); -	lan966x_ptp_rxtstamp(lan966x, skb, timestamp); +	lan966x_ptp_rxtstamp(lan966x, skb, src_port, timestamp);  	skb->protocol = eth_type_trans(skb, skb->dev);  	if (lan966x->bridge_mask & BIT(src_port)) { @@ -699,15 +701,14 @@ static void lan966x_fdma_tx_start(struct lan966x_tx *tx, int next_to_use)  	tx->last_in_use = next_to_use;  } -int lan966x_fdma_xmit_xdpf(struct lan966x_port *port, -			   struct xdp_frame *xdpf, -			   struct page *page, -			   bool dma_map) +int lan966x_fdma_xmit_xdpf(struct lan966x_port *port, void *ptr, u32 len)  {  	struct lan966x *lan966x = port->lan966x;  	struct lan966x_tx_dcb_buf *next_dcb_buf;  	struct lan966x_tx *tx = &lan966x->tx; +	struct xdp_frame *xdpf;  	dma_addr_t dma_addr; +	struct page *page;  	int next_to_use;  	__be32 *ifh;  	int ret = 0; @@ -722,8 +723,13 @@ int lan966x_fdma_xmit_xdpf(struct lan966x_port *port,  		goto out;  	} +	/* Get the next buffer */ +	next_dcb_buf = &tx->dcbs_buf[next_to_use]; +  	/* Generate new IFH */ -	if (dma_map) { +	if (!len) { +		xdpf = ptr; +  		if (xdpf->headroom < IFH_LEN_BYTES) {  			ret = NETDEV_TX_OK;  			goto out; @@ -743,11 +749,16 @@ int lan966x_fdma_xmit_xdpf(struct lan966x_port *port,  			goto out;  		} +		next_dcb_buf->data.xdpf = xdpf; +		next_dcb_buf->len = xdpf->len + IFH_LEN_BYTES; +  		/* Setup next dcb */  		lan966x_fdma_tx_setup_dcb(tx, next_to_use,  					  xdpf->len + IFH_LEN_BYTES,  					  dma_addr);  	} else { +		page = ptr; +  		ifh = page_address(page) + XDP_PACKET_HEADROOM;  		memset(ifh, 0x0, sizeof(__be32) * IFH_LEN);  		lan966x_ifh_set_bypass(ifh, 1); @@ -756,21 +767,21 @@ int lan966x_fdma_xmit_xdpf(struct lan966x_port *port,  		dma_addr = page_pool_get_dma_addr(page);  		dma_sync_single_for_device(lan966x->dev,  					   dma_addr + XDP_PACKET_HEADROOM, -					   xdpf->len + IFH_LEN_BYTES, +					   len + IFH_LEN_BYTES,  					   DMA_TO_DEVICE); +		next_dcb_buf->data.page = page; +		next_dcb_buf->len = len + IFH_LEN_BYTES; +  		/* Setup next dcb */  		lan966x_fdma_tx_setup_dcb(tx, next_to_use, -					  xdpf->len + IFH_LEN_BYTES, +					  len + IFH_LEN_BYTES,  					  dma_addr + XDP_PACKET_HEADROOM);  	}  	/* Fill up the buffer */ -	next_dcb_buf = &tx->dcbs_buf[next_to_use];  	next_dcb_buf->use_skb = false; -	next_dcb_buf->data.xdpf = xdpf; -	next_dcb_buf->xdp_ndo = dma_map; -	next_dcb_buf->len = xdpf->len + IFH_LEN_BYTES; +	next_dcb_buf->xdp_ndo = !len;  	next_dcb_buf->dma_addr = dma_addr;  	next_dcb_buf->used = true;  	next_dcb_buf->ptp = false; diff --git a/drivers/net/ethernet/microchip/lan966x/lan966x_main.c b/drivers/net/ethernet/microchip/lan966x/lan966x_main.c index 685e8cd7658c..ee2698698d71 100644 --- a/drivers/net/ethernet/microchip/lan966x/lan966x_main.c +++ b/drivers/net/ethernet/microchip/lan966x/lan966x_main.c @@ -7,7 +7,6 @@  #include <linux/ip.h>  #include <linux/of_platform.h>  #include <linux/of_net.h> -#include <linux/packing.h>  #include <linux/phy/phy.h>  #include <linux/reset.h>  #include <net/addrconf.h> @@ -305,46 +304,57 @@ err:  	return NETDEV_TX_BUSY;  } +static void lan966x_ifh_set(u8 *ifh, size_t val, size_t pos, size_t length) +{ +	int i = 0; + +	do { +		u8 p = IFH_LEN_BYTES - (pos + i) / 8 - 1; +		u8 v = val >> i & 0xff; + +		/* There is no need to check for limits of the array, as these +		 * will never be written +		 */ +		ifh[p] |= v << ((pos + i) % 8); +		ifh[p - 1] |= v >> (8 - (pos + i) % 8); + +		i += 8; +	} while (i < length); +} +  void lan966x_ifh_set_bypass(void *ifh, u64 bypass)  { -	packing(ifh, &bypass, IFH_POS_BYPASS + IFH_WID_BYPASS - 1, -		IFH_POS_BYPASS, IFH_LEN * 4, PACK, 0); +	lan966x_ifh_set(ifh, bypass, IFH_POS_BYPASS, IFH_WID_BYPASS);  } -void lan966x_ifh_set_port(void *ifh, u64 bypass) +void lan966x_ifh_set_port(void *ifh, u64 port)  { -	packing(ifh, &bypass, IFH_POS_DSTS + IFH_WID_DSTS - 1, -		IFH_POS_DSTS, IFH_LEN * 4, PACK, 0); +	lan966x_ifh_set(ifh, port, IFH_POS_DSTS, IFH_WID_DSTS);  } -static void lan966x_ifh_set_qos_class(void *ifh, u64 bypass) +static void lan966x_ifh_set_qos_class(void *ifh, u64 qos)  { -	packing(ifh, &bypass, IFH_POS_QOS_CLASS + IFH_WID_QOS_CLASS - 1, -		IFH_POS_QOS_CLASS, IFH_LEN * 4, PACK, 0); +	lan966x_ifh_set(ifh, qos, IFH_POS_QOS_CLASS, IFH_WID_QOS_CLASS);  } -static void lan966x_ifh_set_ipv(void *ifh, u64 bypass) +static void lan966x_ifh_set_ipv(void *ifh, u64 ipv)  { -	packing(ifh, &bypass, IFH_POS_IPV + IFH_WID_IPV - 1, -		IFH_POS_IPV, IFH_LEN * 4, PACK, 0); +	lan966x_ifh_set(ifh, ipv, IFH_POS_IPV, IFH_WID_IPV);  }  static void lan966x_ifh_set_vid(void *ifh, u64 vid)  { -	packing(ifh, &vid, IFH_POS_TCI + IFH_WID_TCI - 1, -		IFH_POS_TCI, IFH_LEN * 4, PACK, 0); +	lan966x_ifh_set(ifh, vid, IFH_POS_TCI, IFH_WID_TCI);  }  static void lan966x_ifh_set_rew_op(void *ifh, u64 rew_op)  { -	packing(ifh, &rew_op, IFH_POS_REW_CMD + IFH_WID_REW_CMD - 1, -		IFH_POS_REW_CMD, IFH_LEN * 4, PACK, 0); +	lan966x_ifh_set(ifh, rew_op, IFH_POS_REW_CMD, IFH_WID_REW_CMD);  }  static void lan966x_ifh_set_timestamp(void *ifh, u64 timestamp)  { -	packing(ifh, ×tamp, IFH_POS_TIMESTAMP + IFH_WID_TIMESTAMP - 1, -		IFH_POS_TIMESTAMP, IFH_LEN * 4, PACK, 0); +	lan966x_ifh_set(ifh, timestamp, IFH_POS_TIMESTAMP, IFH_WID_TIMESTAMP);  }  static netdev_tx_t lan966x_port_xmit(struct sk_buff *skb, @@ -582,22 +592,38 @@ static int lan966x_rx_frame_word(struct lan966x *lan966x, u8 grp, u32 *rval)  	}  } +static u64 lan966x_ifh_get(u8 *ifh, size_t pos, size_t length) +{ +	u64 val = 0; +	u8 v; + +	for (int i = 0; i < length ; i++) { +		int j = pos + i; +		int k = j % 8; + +		if (i == 0 || k == 0) +			v = ifh[IFH_LEN_BYTES - (j / 8) - 1]; + +		if (v & (1 << k)) +			val |= (1ULL << i); +	} + +	return val; +} +  void lan966x_ifh_get_src_port(void *ifh, u64 *src_port)  { -	packing(ifh, src_port, IFH_POS_SRCPORT + IFH_WID_SRCPORT - 1, -		IFH_POS_SRCPORT, IFH_LEN * 4, UNPACK, 0); +	*src_port = lan966x_ifh_get(ifh, IFH_POS_SRCPORT, IFH_WID_SRCPORT);  }  static void lan966x_ifh_get_len(void *ifh, u64 *len)  { -	packing(ifh, len, IFH_POS_LEN + IFH_WID_LEN - 1, -		IFH_POS_LEN, IFH_LEN * 4, UNPACK, 0); +	*len = lan966x_ifh_get(ifh, IFH_POS_LEN, IFH_WID_LEN);  }  void lan966x_ifh_get_timestamp(void *ifh, u64 *timestamp)  { -	packing(ifh, timestamp, IFH_POS_TIMESTAMP + IFH_WID_TIMESTAMP - 1, -		IFH_POS_TIMESTAMP, IFH_LEN * 4, UNPACK, 0); +	*timestamp = lan966x_ifh_get(ifh, IFH_POS_TIMESTAMP, IFH_WID_TIMESTAMP);  }  static irqreturn_t lan966x_xtr_irq_handler(int irq, void *args) @@ -668,7 +694,7 @@ static irqreturn_t lan966x_xtr_irq_handler(int irq, void *args)  			*buf = val;  		} -		lan966x_ptp_rxtstamp(lan966x, skb, timestamp); +		lan966x_ptp_rxtstamp(lan966x, skb, src_port, timestamp);  		skb->protocol = eth_type_trans(skb, dev);  		if (lan966x->bridge_mask & BIT(src_port)) { @@ -1013,6 +1039,16 @@ static int lan966x_reset_switch(struct lan966x *lan966x)  	reset_control_reset(switch_reset); +	/* Don't reinitialize the switch core, if it is already initialized. In +	 * case it is initialized twice, some pointers inside the queue system +	 * in HW will get corrupted and then after a while the queue system gets +	 * full and no traffic is passing through the switch. The issue is seen +	 * when loading and unloading the driver and sending traffic through the +	 * switch. +	 */ +	if (lan_rd(lan966x, SYS_RESET_CFG) & SYS_RESET_CFG_CORE_ENA) +		return 0; +  	lan_wr(SYS_RESET_CFG_CORE_ENA_SET(0), lan966x, SYS_RESET_CFG);  	lan_wr(SYS_RAM_INIT_RAM_INIT_SET(1), lan966x, SYS_RAM_INIT);  	ret = readx_poll_timeout(lan966x_ram_init, lan966x, diff --git a/drivers/net/ethernet/microchip/lan966x/lan966x_main.h b/drivers/net/ethernet/microchip/lan966x/lan966x_main.h index 49f5159afbf3..c977c70abc3d 100644 --- a/drivers/net/ethernet/microchip/lan966x/lan966x_main.h +++ b/drivers/net/ethernet/microchip/lan966x/lan966x_main.h @@ -92,6 +92,11 @@  #define SE_IDX_QUEUE			0  /* 0-79 : Queue scheduler elements */  #define SE_IDX_PORT			80 /* 80-89 : Port schedular elements */ +#define LAN966X_VCAP_CID_IS1_L0 VCAP_CID_INGRESS_L0 /* IS1 lookup 0 */ +#define LAN966X_VCAP_CID_IS1_L1 VCAP_CID_INGRESS_L1 /* IS1 lookup 1 */ +#define LAN966X_VCAP_CID_IS1_L2 VCAP_CID_INGRESS_L2 /* IS1 lookup 2 */ +#define LAN966X_VCAP_CID_IS1_MAX (VCAP_CID_INGRESS_L3 - 1) /* IS1 Max */ +  #define LAN966X_VCAP_CID_IS2_L0 VCAP_CID_INGRESS_STAGE2_L0 /* IS2 lookup 0 */  #define LAN966X_VCAP_CID_IS2_L1 VCAP_CID_INGRESS_STAGE2_L1 /* IS2 lookup 1 */  #define LAN966X_VCAP_CID_IS2_MAX (VCAP_CID_INGRESS_STAGE2_L2 - 1) /* IS2 Max */ @@ -139,6 +144,39 @@ enum vcap_is2_port_sel_ipv6 {  	VCAP_IS2_PS_IPV6_MAC_ETYPE,  }; +enum vcap_is1_port_sel_other { +	VCAP_IS1_PS_OTHER_NORMAL, +	VCAP_IS1_PS_OTHER_7TUPLE, +	VCAP_IS1_PS_OTHER_DBL_VID, +	VCAP_IS1_PS_OTHER_DMAC_VID, +}; + +enum vcap_is1_port_sel_ipv4 { +	VCAP_IS1_PS_IPV4_NORMAL, +	VCAP_IS1_PS_IPV4_7TUPLE, +	VCAP_IS1_PS_IPV4_5TUPLE_IP4, +	VCAP_IS1_PS_IPV4_DBL_VID, +	VCAP_IS1_PS_IPV4_DMAC_VID, +}; + +enum vcap_is1_port_sel_ipv6 { +	VCAP_IS1_PS_IPV6_NORMAL, +	VCAP_IS1_PS_IPV6_7TUPLE, +	VCAP_IS1_PS_IPV6_5TUPLE_IP4, +	VCAP_IS1_PS_IPV6_NORMAL_IP6, +	VCAP_IS1_PS_IPV6_5TUPLE_IP6, +	VCAP_IS1_PS_IPV6_DBL_VID, +	VCAP_IS1_PS_IPV6_DMAC_VID, +}; + +enum vcap_is1_port_sel_rt { +	VCAP_IS1_PS_RT_NORMAL, +	VCAP_IS1_PS_RT_7TUPLE, +	VCAP_IS1_PS_RT_DBL_VID, +	VCAP_IS1_PS_RT_DMAC_VID, +	VCAP_IS1_PS_RT_FOLLOW_OTHER = 7, +}; +  struct lan966x_port;  struct lan966x_db { @@ -205,6 +243,7 @@ struct lan966x_tx_dcb_buf {  	union {  		struct sk_buff *skb;  		struct xdp_frame *xdpf; +		struct page *page;  	} data;  	u32 len;  	u32 used : 1; @@ -369,7 +408,8 @@ struct lan966x_port {  	struct phy *serdes;  	struct fwnode_handle *fwnode; -	u8 ptp_cmd; +	u8 ptp_tx_cmd; +	bool ptp_rx_cmd;  	u16 ts_id;  	struct sk_buff_head tx_skbs; @@ -489,7 +529,7 @@ void lan966x_ptp_deinit(struct lan966x *lan966x);  int lan966x_ptp_hwtstamp_set(struct lan966x_port *port, struct ifreq *ifr);  int lan966x_ptp_hwtstamp_get(struct lan966x_port *port, struct ifreq *ifr);  void lan966x_ptp_rxtstamp(struct lan966x *lan966x, struct sk_buff *skb, -			  u64 timestamp); +			  u64 src_port, u64 timestamp);  int lan966x_ptp_txtstamp_request(struct lan966x_port *port,  				 struct sk_buff *skb);  void lan966x_ptp_txtstamp_release(struct lan966x_port *port, @@ -502,10 +542,7 @@ int lan966x_ptp_setup_traps(struct lan966x_port *port, struct ifreq *ifr);  int lan966x_ptp_del_traps(struct lan966x_port *port);  int lan966x_fdma_xmit(struct sk_buff *skb, __be32 *ifh, struct net_device *dev); -int lan966x_fdma_xmit_xdpf(struct lan966x_port *port, -			   struct xdp_frame *frame, -			   struct page *page, -			   bool dma_map); +int lan966x_fdma_xmit_xdpf(struct lan966x_port *port, void *ptr, u32 len);  int lan966x_fdma_change_mtu(struct lan966x *lan966x);  void lan966x_fdma_netdev_init(struct lan966x *lan966x, struct net_device *dev);  void lan966x_fdma_netdev_deinit(struct lan966x *lan966x, struct net_device *dev); diff --git a/drivers/net/ethernet/microchip/lan966x/lan966x_police.c b/drivers/net/ethernet/microchip/lan966x/lan966x_police.c index 7d66fe75cd3b..7302df2300fd 100644 --- a/drivers/net/ethernet/microchip/lan966x/lan966x_police.c +++ b/drivers/net/ethernet/microchip/lan966x/lan966x_police.c @@ -49,8 +49,7 @@ static int lan966x_police_add(struct lan966x_port *port,  	return 0;  } -static int lan966x_police_del(struct lan966x_port *port, -			      u16 pol_idx) +static void lan966x_police_del(struct lan966x_port *port, u16 pol_idx)  {  	struct lan966x *lan966x = port->lan966x; @@ -67,8 +66,6 @@ static int lan966x_police_del(struct lan966x_port *port,  	lan_wr(ANA_POL_PIR_CFG_PIR_RATE_SET(GENMASK(14, 0)) |  	       ANA_POL_PIR_CFG_PIR_BURST_SET(0),  	       lan966x, ANA_POL_PIR_CFG(pol_idx)); - -	return 0;  }  static int lan966x_police_validate(struct lan966x_port *port, @@ -186,7 +183,6 @@ int lan966x_police_port_del(struct lan966x_port *port,  			    struct netlink_ext_ack *extack)  {  	struct lan966x *lan966x = port->lan966x; -	int err;  	if (port->tc.police_id != police_id) {  		NL_SET_ERR_MSG_MOD(extack, @@ -194,12 +190,7 @@ int lan966x_police_port_del(struct lan966x_port *port,  		return -EINVAL;  	} -	err = lan966x_police_del(port, POL_IDX_PORT + port->chip_port); -	if (err) { -		NL_SET_ERR_MSG_MOD(extack, -				   "Failed to add policer to port"); -		return err; -	} +	lan966x_police_del(port, POL_IDX_PORT + port->chip_port);  	lan_rmw(ANA_POL_CFG_PORT_POL_ENA_SET(0) |  		ANA_POL_CFG_POL_ORDER_SET(POL_ORDER), diff --git a/drivers/net/ethernet/microchip/lan966x/lan966x_ptp.c b/drivers/net/ethernet/microchip/lan966x/lan966x_ptp.c index 931e37b9a0ad..266a21a2d124 100644 --- a/drivers/net/ethernet/microchip/lan966x/lan966x_ptp.c +++ b/drivers/net/ethernet/microchip/lan966x/lan966x_ptp.c @@ -272,13 +272,13 @@ int lan966x_ptp_hwtstamp_set(struct lan966x_port *port, struct ifreq *ifr)  	switch (cfg.tx_type) {  	case HWTSTAMP_TX_ON: -		port->ptp_cmd = IFH_REW_OP_TWO_STEP_PTP; +		port->ptp_tx_cmd = IFH_REW_OP_TWO_STEP_PTP;  		break;  	case HWTSTAMP_TX_ONESTEP_SYNC: -		port->ptp_cmd = IFH_REW_OP_ONE_STEP_PTP; +		port->ptp_tx_cmd = IFH_REW_OP_ONE_STEP_PTP;  		break;  	case HWTSTAMP_TX_OFF: -		port->ptp_cmd = IFH_REW_OP_NOOP; +		port->ptp_tx_cmd = IFH_REW_OP_NOOP;  		break;  	default:  		return -ERANGE; @@ -286,6 +286,7 @@ int lan966x_ptp_hwtstamp_set(struct lan966x_port *port, struct ifreq *ifr)  	switch (cfg.rx_filter) {  	case HWTSTAMP_FILTER_NONE: +		port->ptp_rx_cmd = false;  		break;  	case HWTSTAMP_FILTER_ALL:  	case HWTSTAMP_FILTER_PTP_V1_L4_EVENT: @@ -301,6 +302,7 @@ int lan966x_ptp_hwtstamp_set(struct lan966x_port *port, struct ifreq *ifr)  	case HWTSTAMP_FILTER_PTP_V2_SYNC:  	case HWTSTAMP_FILTER_PTP_V2_DELAY_REQ:  	case HWTSTAMP_FILTER_NTP_ALL: +		port->ptp_rx_cmd = true;  		cfg.rx_filter = HWTSTAMP_FILTER_ALL;  		break;  	default: @@ -332,7 +334,7 @@ static int lan966x_ptp_classify(struct lan966x_port *port, struct sk_buff *skb)  	u8 msgtype;  	int type; -	if (port->ptp_cmd == IFH_REW_OP_NOOP) +	if (port->ptp_tx_cmd == IFH_REW_OP_NOOP)  		return IFH_REW_OP_NOOP;  	type = ptp_classify_raw(skb); @@ -343,7 +345,7 @@ static int lan966x_ptp_classify(struct lan966x_port *port, struct sk_buff *skb)  	if (!header)  		return IFH_REW_OP_NOOP; -	if (port->ptp_cmd == IFH_REW_OP_TWO_STEP_PTP) +	if (port->ptp_tx_cmd == IFH_REW_OP_TWO_STEP_PTP)  		return IFH_REW_OP_TWO_STEP_PTP;  	/* If it is sync and run 1 step then set the correct operation, @@ -1009,9 +1011,6 @@ static int lan966x_ptp_phc_init(struct lan966x *lan966x,  	phc->index = index;  	phc->lan966x = lan966x; -	/* PTP Rx stamping is always enabled.  */ -	phc->hwtstamp_config.rx_filter = HWTSTAMP_FILTER_PTP_V2_EVENT; -  	return 0;  } @@ -1088,14 +1087,15 @@ void lan966x_ptp_deinit(struct lan966x *lan966x)  }  void lan966x_ptp_rxtstamp(struct lan966x *lan966x, struct sk_buff *skb, -			  u64 timestamp) +			  u64 src_port, u64 timestamp)  {  	struct skb_shared_hwtstamps *shhwtstamps;  	struct lan966x_phc *phc;  	struct timespec64 ts;  	u64 full_ts_in_ns; -	if (!lan966x->ptp) +	if (!lan966x->ptp || +	    !lan966x->ports[src_port]->ptp_rx_cmd)  		return;  	phc = &lan966x->phc[LAN966X_PHC_PORT]; diff --git a/drivers/net/ethernet/microchip/lan966x/lan966x_regs.h b/drivers/net/ethernet/microchip/lan966x/lan966x_regs.h index 9767b5a1c958..f99f88b5caa8 100644 --- a/drivers/net/ethernet/microchip/lan966x/lan966x_regs.h +++ b/drivers/net/ethernet/microchip/lan966x/lan966x_regs.h @@ -316,6 +316,42 @@ enum lan966x_target {  #define ANA_DROP_CFG_DROP_MC_SMAC_ENA_GET(x)\  	FIELD_GET(ANA_DROP_CFG_DROP_MC_SMAC_ENA, x) +/*      ANA:PORT:VCAP_CFG */ +#define ANA_VCAP_CFG(g)           __REG(TARGET_ANA, 0, 1, 28672, g, 9, 128, 12, 0, 1, 4) + +#define ANA_VCAP_CFG_S1_ENA                      BIT(14) +#define ANA_VCAP_CFG_S1_ENA_SET(x)\ +	FIELD_PREP(ANA_VCAP_CFG_S1_ENA, x) +#define ANA_VCAP_CFG_S1_ENA_GET(x)\ +	FIELD_GET(ANA_VCAP_CFG_S1_ENA, x) + +/*      ANA:PORT:VCAP_S1_KEY_CFG */ +#define ANA_VCAP_S1_CFG(g, r)     __REG(TARGET_ANA, 0, 1, 28672, g, 9, 128, 16, r, 3, 4) + +#define ANA_VCAP_S1_CFG_KEY_RT_CFG               GENMASK(11, 9) +#define ANA_VCAP_S1_CFG_KEY_RT_CFG_SET(x)\ +	FIELD_PREP(ANA_VCAP_S1_CFG_KEY_RT_CFG, x) +#define ANA_VCAP_S1_CFG_KEY_RT_CFG_GET(x)\ +	FIELD_GET(ANA_VCAP_S1_CFG_KEY_RT_CFG, x) + +#define ANA_VCAP_S1_CFG_KEY_IP6_CFG              GENMASK(8, 6) +#define ANA_VCAP_S1_CFG_KEY_IP6_CFG_SET(x)\ +	FIELD_PREP(ANA_VCAP_S1_CFG_KEY_IP6_CFG, x) +#define ANA_VCAP_S1_CFG_KEY_IP6_CFG_GET(x)\ +	FIELD_GET(ANA_VCAP_S1_CFG_KEY_IP6_CFG, x) + +#define ANA_VCAP_S1_CFG_KEY_IP4_CFG              GENMASK(5, 3) +#define ANA_VCAP_S1_CFG_KEY_IP4_CFG_SET(x)\ +	FIELD_PREP(ANA_VCAP_S1_CFG_KEY_IP4_CFG, x) +#define ANA_VCAP_S1_CFG_KEY_IP4_CFG_GET(x)\ +	FIELD_GET(ANA_VCAP_S1_CFG_KEY_IP4_CFG, x) + +#define ANA_VCAP_S1_CFG_KEY_OTHER_CFG            GENMASK(2, 0) +#define ANA_VCAP_S1_CFG_KEY_OTHER_CFG_SET(x)\ +	FIELD_PREP(ANA_VCAP_S1_CFG_KEY_OTHER_CFG, x) +#define ANA_VCAP_S1_CFG_KEY_OTHER_CFG_GET(x)\ +	FIELD_GET(ANA_VCAP_S1_CFG_KEY_OTHER_CFG, x) +  /*      ANA:PORT:VCAP_S2_CFG */  #define ANA_VCAP_S2_CFG(g)        __REG(TARGET_ANA, 0, 1, 28672, g, 9, 128, 28, 0, 1, 4) diff --git a/drivers/net/ethernet/microchip/lan966x/lan966x_tc_flower.c b/drivers/net/ethernet/microchip/lan966x/lan966x_tc_flower.c index f960727ecaee..47b2f7579dd2 100644 --- a/drivers/net/ethernet/microchip/lan966x/lan966x_tc_flower.c +++ b/drivers/net/ethernet/microchip/lan966x/lan966x_tc_flower.c @@ -5,14 +5,34 @@  #include "vcap_api_client.h"  #include "vcap_tc.h" -static bool lan966x_tc_is_known_etype(u16 etype) +static bool lan966x_tc_is_known_etype(struct vcap_tc_flower_parse_usage *st, +				      u16 etype)  { -	switch (etype) { -	case ETH_P_ALL: -	case ETH_P_ARP: -	case ETH_P_IP: -	case ETH_P_IPV6: -		return true; +	switch (st->admin->vtype) { +	case VCAP_TYPE_IS1: +		switch (etype) { +		case ETH_P_ALL: +		case ETH_P_ARP: +		case ETH_P_IP: +		case ETH_P_IPV6: +			return true; +		} +		break; +	case VCAP_TYPE_IS2: +		switch (etype) { +		case ETH_P_ALL: +		case ETH_P_ARP: +		case ETH_P_IP: +		case ETH_P_IPV6: +		case ETH_P_SNAP: +		case ETH_P_802_2: +			return true; +		} +		break; +	default: +		NL_SET_ERR_MSG_MOD(st->fco->common.extack, +				   "VCAP type not supported"); +		return false;  	}  	return false; @@ -69,7 +89,7 @@ lan966x_tc_flower_handler_basic_usage(struct vcap_tc_flower_parse_usage *st)  	flow_rule_match_basic(st->frule, &match);  	if (match.mask->n_proto) {  		st->l3_proto = be16_to_cpu(match.key->n_proto); -		if (!lan966x_tc_is_known_etype(st->l3_proto)) { +		if (!lan966x_tc_is_known_etype(st, st->l3_proto)) {  			err = vcap_rule_add_key_u32(st->vrule, VCAP_KF_ETYPE,  						    st->l3_proto, ~0);  			if (err) @@ -79,18 +99,61 @@ lan966x_tc_flower_handler_basic_usage(struct vcap_tc_flower_parse_usage *st)  						    VCAP_BIT_1);  			if (err)  				goto out; +		} else if (st->l3_proto == ETH_P_IPV6 && +			   st->admin->vtype == VCAP_TYPE_IS1) { +			/* Don't set any keys in this case */ +		} else if (st->l3_proto == ETH_P_SNAP && +			   st->admin->vtype == VCAP_TYPE_IS1) { +			err = vcap_rule_add_key_bit(st->vrule, +						    VCAP_KF_ETYPE_LEN_IS, +						    VCAP_BIT_0); +			if (err) +				goto out; + +			err = vcap_rule_add_key_bit(st->vrule, +						    VCAP_KF_IP_SNAP_IS, +						    VCAP_BIT_1); +			if (err) +				goto out; +		} else if (st->admin->vtype == VCAP_TYPE_IS1) { +			err = vcap_rule_add_key_bit(st->vrule, +						    VCAP_KF_ETYPE_LEN_IS, +						    VCAP_BIT_1); +			if (err) +				goto out; + +			err = vcap_rule_add_key_u32(st->vrule, VCAP_KF_ETYPE, +						    st->l3_proto, ~0); +			if (err) +				goto out;  		}  	}  	if (match.mask->ip_proto) {  		st->l4_proto = match.key->ip_proto;  		if (st->l4_proto == IPPROTO_TCP) { +			if (st->admin->vtype == VCAP_TYPE_IS1) { +				err = vcap_rule_add_key_bit(st->vrule, +							    VCAP_KF_TCP_UDP_IS, +							    VCAP_BIT_1); +				if (err) +					goto out; +			} +  			err = vcap_rule_add_key_bit(st->vrule,  						    VCAP_KF_TCP_IS,  						    VCAP_BIT_1);  			if (err)  				goto out;  		} else if (st->l4_proto == IPPROTO_UDP) { +			if (st->admin->vtype == VCAP_TYPE_IS1) { +				err = vcap_rule_add_key_bit(st->vrule, +							    VCAP_KF_TCP_UDP_IS, +							    VCAP_BIT_1); +				if (err) +					goto out; +			} +  			err = vcap_rule_add_key_bit(st->vrule,  						    VCAP_KF_TCP_IS,  						    VCAP_BIT_0); @@ -113,11 +176,29 @@ out:  }  static int +lan966x_tc_flower_handler_cvlan_usage(struct vcap_tc_flower_parse_usage *st) +{ +	if (st->admin->vtype != VCAP_TYPE_IS1) { +		NL_SET_ERR_MSG_MOD(st->fco->common.extack, +				   "cvlan not supported in this VCAP"); +		return -EINVAL; +	} + +	return vcap_tc_flower_handler_cvlan_usage(st); +} + +static int  lan966x_tc_flower_handler_vlan_usage(struct vcap_tc_flower_parse_usage *st)  { -	return vcap_tc_flower_handler_vlan_usage(st, -						 VCAP_KF_8021Q_VID_CLS, -						 VCAP_KF_8021Q_PCP_CLS); +	enum vcap_key_field vid_key = VCAP_KF_8021Q_VID_CLS; +	enum vcap_key_field pcp_key = VCAP_KF_8021Q_PCP_CLS; + +	if (st->admin->vtype == VCAP_TYPE_IS1) { +		vid_key = VCAP_KF_8021Q_VID0; +		pcp_key = VCAP_KF_8021Q_PCP0; +	} + +	return vcap_tc_flower_handler_vlan_usage(st, vid_key, pcp_key);  }  static int @@ -128,6 +209,7 @@ static int  	[FLOW_DISSECTOR_KEY_CONTROL] = lan966x_tc_flower_handler_control_usage,  	[FLOW_DISSECTOR_KEY_PORTS] = vcap_tc_flower_handler_portnum_usage,  	[FLOW_DISSECTOR_KEY_BASIC] = lan966x_tc_flower_handler_basic_usage, +	[FLOW_DISSECTOR_KEY_CVLAN] = lan966x_tc_flower_handler_cvlan_usage,  	[FLOW_DISSECTOR_KEY_VLAN] = lan966x_tc_flower_handler_vlan_usage,  	[FLOW_DISSECTOR_KEY_TCP] = vcap_tc_flower_handler_tcp_usage,  	[FLOW_DISSECTOR_KEY_ARP] = vcap_tc_flower_handler_arp_usage, @@ -143,6 +225,7 @@ static int lan966x_tc_flower_use_dissectors(struct flow_cls_offload *f,  		.fco = f,  		.vrule = vrule,  		.l3_proto = ETH_P_ALL, +		.admin = admin,  	};  	int err = 0; @@ -221,6 +304,100 @@ static int lan966x_tc_flower_action_check(struct vcap_control *vctrl,  	return 0;  } +/* Add the actionset that is the default for the VCAP type */ +static int lan966x_tc_set_actionset(struct vcap_admin *admin, +				    struct vcap_rule *vrule) +{ +	enum vcap_actionfield_set aset; +	int err = 0; + +	switch (admin->vtype) { +	case VCAP_TYPE_IS1: +		aset = VCAP_AFS_S1; +		break; +	case VCAP_TYPE_IS2: +		aset = VCAP_AFS_BASE_TYPE; +		break; +	default: +		return -EINVAL; +	} + +	/* Do not overwrite any current actionset */ +	if (vrule->actionset == VCAP_AFS_NO_VALUE) +		err = vcap_set_rule_set_actionset(vrule, aset); + +	return err; +} + +static int lan966x_tc_add_rule_link_target(struct vcap_admin *admin, +					   struct vcap_rule *vrule, +					   int target_cid) +{ +	int link_val = target_cid % VCAP_CID_LOOKUP_SIZE; +	int err; + +	if (!link_val) +		return 0; + +	switch (admin->vtype) { +	case VCAP_TYPE_IS1: +		/* Choose IS1 specific NXT_IDX key (for chaining rules from IS1) */ +		err = vcap_rule_add_key_u32(vrule, VCAP_KF_LOOKUP_GEN_IDX_SEL, +					    1, ~0); +		if (err) +			return err; + +		return vcap_rule_add_key_u32(vrule, VCAP_KF_LOOKUP_GEN_IDX, +					     link_val, ~0); +	case VCAP_TYPE_IS2: +		/* Add IS2 specific PAG key (for chaining rules from IS1) */ +		return vcap_rule_add_key_u32(vrule, VCAP_KF_LOOKUP_PAG, +					     link_val, ~0); +	default: +		break; +	} +	return 0; +} + +static int lan966x_tc_add_rule_link(struct vcap_control *vctrl, +				    struct vcap_admin *admin, +				    struct vcap_rule *vrule, +				    struct flow_cls_offload *f, +				    int to_cid) +{ +	struct vcap_admin *to_admin = vcap_find_admin(vctrl, to_cid); +	int diff, err = 0; + +	if (!to_admin) { +		NL_SET_ERR_MSG_MOD(f->common.extack, +				   "Unknown destination chain"); +		return -EINVAL; +	} + +	diff = vcap_chain_offset(vctrl, f->common.chain_index, to_cid); +	if (!diff) +		return 0; + +	/* Between IS1 and IS2 the PAG value is used */ +	if (admin->vtype == VCAP_TYPE_IS1 && to_admin->vtype == VCAP_TYPE_IS2) { +		/* This works for IS1->IS2 */ +		err = vcap_rule_add_action_u32(vrule, VCAP_AF_PAG_VAL, diff); +		if (err) +			return err; + +		err = vcap_rule_add_action_u32(vrule, VCAP_AF_PAG_OVERRIDE_MASK, +					       0xff); +		if (err) +			return err; +	} else { +		NL_SET_ERR_MSG_MOD(f->common.extack, +				   "Unsupported chain destination"); +		return -EOPNOTSUPP; +	} + +	return err; +} +  static int lan966x_tc_flower_add(struct lan966x_port *port,  				 struct flow_cls_offload *f,  				 struct vcap_admin *admin, @@ -248,11 +425,23 @@ static int lan966x_tc_flower_add(struct lan966x_port *port,  	if (err)  		goto out; +	err = lan966x_tc_add_rule_link_target(admin, vrule, +					      f->common.chain_index); +	if (err) +		goto out; +  	frule = flow_cls_offload_flow_rule(f);  	flow_action_for_each(idx, act, &frule->action) {  		switch (act->id) {  		case FLOW_ACTION_TRAP: +			if (admin->vtype != VCAP_TYPE_IS2) { +				NL_SET_ERR_MSG_MOD(f->common.extack, +						   "Trap action not supported in this VCAP"); +				err = -EOPNOTSUPP; +				goto out; +			} +  			err = vcap_rule_add_action_bit(vrule,  						       VCAP_AF_CPU_COPY_ENA,  						       VCAP_BIT_1); @@ -266,6 +455,16 @@ static int lan966x_tc_flower_add(struct lan966x_port *port,  			break;  		case FLOW_ACTION_GOTO: +			err = lan966x_tc_set_actionset(admin, vrule); +			if (err) +				goto out; + +			err = lan966x_tc_add_rule_link(port->lan966x->vcap_ctrl, +						       admin, vrule, +						       f, act->chain_index); +			if (err) +				goto out; +  			break;  		default:  			NL_SET_ERR_MSG_MOD(f->common.extack, diff --git a/drivers/net/ethernet/microchip/lan966x/lan966x_vcap_ag_api.c b/drivers/net/ethernet/microchip/lan966x/lan966x_vcap_ag_api.c index 928e711960e6..66400a082d02 100644 --- a/drivers/net/ethernet/microchip/lan966x/lan966x_vcap_ag_api.c +++ b/drivers/net/ethernet/microchip/lan966x/lan966x_vcap_ag_api.c @@ -6,6 +6,965 @@  #include "lan966x_vcap_ag_api.h"  /* keyfields */ +static const struct vcap_field is1_normal_keyfield[] = { +	[VCAP_KF_TYPE] = { +		.type = VCAP_FIELD_BIT, +		.offset = 0, +		.width = 1, +	}, +	[VCAP_KF_LOOKUP_INDEX] = { +		.type = VCAP_FIELD_U32, +		.offset = 1, +		.width = 2, +	}, +	[VCAP_KF_IF_IGR_PORT_MASK] = { +		.type = VCAP_FIELD_U32, +		.offset = 3, +		.width = 9, +	}, +	[VCAP_KF_L2_MC_IS] = { +		.type = VCAP_FIELD_BIT, +		.offset = 12, +		.width = 1, +	}, +	[VCAP_KF_L2_BC_IS] = { +		.type = VCAP_FIELD_BIT, +		.offset = 13, +		.width = 1, +	}, +	[VCAP_KF_IP_MC_IS] = { +		.type = VCAP_FIELD_BIT, +		.offset = 14, +		.width = 1, +	}, +	[VCAP_KF_8021CB_R_TAGGED_IS] = { +		.type = VCAP_FIELD_BIT, +		.offset = 15, +		.width = 1, +	}, +	[VCAP_KF_8021Q_VLAN_TAGGED_IS] = { +		.type = VCAP_FIELD_BIT, +		.offset = 16, +		.width = 1, +	}, +	[VCAP_KF_8021Q_VLAN_DBL_TAGGED_IS] = { +		.type = VCAP_FIELD_BIT, +		.offset = 17, +		.width = 1, +	}, +	[VCAP_KF_8021Q_TPID0] = { +		.type = VCAP_FIELD_BIT, +		.offset = 18, +		.width = 1, +	}, +	[VCAP_KF_8021Q_VID0] = { +		.type = VCAP_FIELD_U32, +		.offset = 19, +		.width = 12, +	}, +	[VCAP_KF_8021Q_DEI0] = { +		.type = VCAP_FIELD_BIT, +		.offset = 31, +		.width = 1, +	}, +	[VCAP_KF_8021Q_PCP0] = { +		.type = VCAP_FIELD_U32, +		.offset = 32, +		.width = 3, +	}, +	[VCAP_KF_L2_SMAC] = { +		.type = VCAP_FIELD_U48, +		.offset = 35, +		.width = 48, +	}, +	[VCAP_KF_ETYPE_LEN_IS] = { +		.type = VCAP_FIELD_BIT, +		.offset = 83, +		.width = 1, +	}, +	[VCAP_KF_ETYPE] = { +		.type = VCAP_FIELD_U32, +		.offset = 84, +		.width = 16, +	}, +	[VCAP_KF_IP_SNAP_IS] = { +		.type = VCAP_FIELD_BIT, +		.offset = 100, +		.width = 1, +	}, +	[VCAP_KF_IP4_IS] = { +		.type = VCAP_FIELD_BIT, +		.offset = 101, +		.width = 1, +	}, +	[VCAP_KF_L3_FRAGMENT] = { +		.type = VCAP_FIELD_BIT, +		.offset = 102, +		.width = 1, +	}, +	[VCAP_KF_L3_FRAG_OFS_GT0] = { +		.type = VCAP_FIELD_BIT, +		.offset = 103, +		.width = 1, +	}, +	[VCAP_KF_L3_OPTIONS_IS] = { +		.type = VCAP_FIELD_BIT, +		.offset = 104, +		.width = 1, +	}, +	[VCAP_KF_L3_DSCP] = { +		.type = VCAP_FIELD_U32, +		.offset = 105, +		.width = 6, +	}, +	[VCAP_KF_L3_IP4_SIP] = { +		.type = VCAP_FIELD_U32, +		.offset = 111, +		.width = 32, +	}, +	[VCAP_KF_TCP_UDP_IS] = { +		.type = VCAP_FIELD_BIT, +		.offset = 143, +		.width = 1, +	}, +	[VCAP_KF_TCP_IS] = { +		.type = VCAP_FIELD_BIT, +		.offset = 144, +		.width = 1, +	}, +	[VCAP_KF_L4_SPORT] = { +		.type = VCAP_FIELD_U32, +		.offset = 145, +		.width = 16, +	}, +	[VCAP_KF_L4_RNG] = { +		.type = VCAP_FIELD_U32, +		.offset = 161, +		.width = 8, +	}, +}; + +static const struct vcap_field is1_5tuple_ip4_keyfield[] = { +	[VCAP_KF_TYPE] = { +		.type = VCAP_FIELD_BIT, +		.offset = 0, +		.width = 1, +	}, +	[VCAP_KF_LOOKUP_INDEX] = { +		.type = VCAP_FIELD_U32, +		.offset = 1, +		.width = 2, +	}, +	[VCAP_KF_IF_IGR_PORT_MASK] = { +		.type = VCAP_FIELD_U32, +		.offset = 3, +		.width = 9, +	}, +	[VCAP_KF_L2_MC_IS] = { +		.type = VCAP_FIELD_BIT, +		.offset = 12, +		.width = 1, +	}, +	[VCAP_KF_L2_BC_IS] = { +		.type = VCAP_FIELD_BIT, +		.offset = 13, +		.width = 1, +	}, +	[VCAP_KF_IP_MC_IS] = { +		.type = VCAP_FIELD_BIT, +		.offset = 14, +		.width = 1, +	}, +	[VCAP_KF_8021CB_R_TAGGED_IS] = { +		.type = VCAP_FIELD_BIT, +		.offset = 15, +		.width = 1, +	}, +	[VCAP_KF_8021Q_VLAN_TAGGED_IS] = { +		.type = VCAP_FIELD_BIT, +		.offset = 16, +		.width = 1, +	}, +	[VCAP_KF_8021Q_VLAN_DBL_TAGGED_IS] = { +		.type = VCAP_FIELD_BIT, +		.offset = 17, +		.width = 1, +	}, +	[VCAP_KF_8021Q_TPID0] = { +		.type = VCAP_FIELD_BIT, +		.offset = 18, +		.width = 1, +	}, +	[VCAP_KF_8021Q_VID0] = { +		.type = VCAP_FIELD_U32, +		.offset = 19, +		.width = 12, +	}, +	[VCAP_KF_8021Q_DEI0] = { +		.type = VCAP_FIELD_BIT, +		.offset = 31, +		.width = 1, +	}, +	[VCAP_KF_8021Q_PCP0] = { +		.type = VCAP_FIELD_U32, +		.offset = 32, +		.width = 3, +	}, +	[VCAP_KF_8021Q_TPID1] = { +		.type = VCAP_FIELD_BIT, +		.offset = 35, +		.width = 1, +	}, +	[VCAP_KF_8021Q_VID1] = { +		.type = VCAP_FIELD_U32, +		.offset = 36, +		.width = 12, +	}, +	[VCAP_KF_8021Q_DEI1] = { +		.type = VCAP_FIELD_BIT, +		.offset = 48, +		.width = 1, +	}, +	[VCAP_KF_8021Q_PCP1] = { +		.type = VCAP_FIELD_U32, +		.offset = 49, +		.width = 3, +	}, +	[VCAP_KF_IP4_IS] = { +		.type = VCAP_FIELD_BIT, +		.offset = 52, +		.width = 1, +	}, +	[VCAP_KF_L3_FRAGMENT] = { +		.type = VCAP_FIELD_BIT, +		.offset = 53, +		.width = 1, +	}, +	[VCAP_KF_L3_FRAG_OFS_GT0] = { +		.type = VCAP_FIELD_BIT, +		.offset = 54, +		.width = 1, +	}, +	[VCAP_KF_L3_OPTIONS_IS] = { +		.type = VCAP_FIELD_BIT, +		.offset = 55, +		.width = 1, +	}, +	[VCAP_KF_L3_DSCP] = { +		.type = VCAP_FIELD_U32, +		.offset = 56, +		.width = 6, +	}, +	[VCAP_KF_L3_IP4_DIP] = { +		.type = VCAP_FIELD_U32, +		.offset = 62, +		.width = 32, +	}, +	[VCAP_KF_L3_IP4_SIP] = { +		.type = VCAP_FIELD_U32, +		.offset = 94, +		.width = 32, +	}, +	[VCAP_KF_L3_IP_PROTO] = { +		.type = VCAP_FIELD_U32, +		.offset = 126, +		.width = 8, +	}, +	[VCAP_KF_TCP_UDP_IS] = { +		.type = VCAP_FIELD_BIT, +		.offset = 134, +		.width = 1, +	}, +	[VCAP_KF_TCP_IS] = { +		.type = VCAP_FIELD_BIT, +		.offset = 135, +		.width = 1, +	}, +	[VCAP_KF_L4_RNG] = { +		.type = VCAP_FIELD_U32, +		.offset = 136, +		.width = 8, +	}, +	[VCAP_KF_IP_PAYLOAD_5TUPLE] = { +		.type = VCAP_FIELD_U32, +		.offset = 144, +		.width = 32, +	}, +}; + +static const struct vcap_field is1_normal_ip6_keyfield[] = { +	[VCAP_KF_TYPE] = { +		.type = VCAP_FIELD_U32, +		.offset = 0, +		.width = 2, +	}, +	[VCAP_KF_LOOKUP_INDEX] = { +		.type = VCAP_FIELD_U32, +		.offset = 2, +		.width = 2, +	}, +	[VCAP_KF_IF_IGR_PORT_MASK] = { +		.type = VCAP_FIELD_U32, +		.offset = 4, +		.width = 9, +	}, +	[VCAP_KF_L2_MC_IS] = { +		.type = VCAP_FIELD_BIT, +		.offset = 13, +		.width = 1, +	}, +	[VCAP_KF_L2_BC_IS] = { +		.type = VCAP_FIELD_BIT, +		.offset = 14, +		.width = 1, +	}, +	[VCAP_KF_IP_MC_IS] = { +		.type = VCAP_FIELD_BIT, +		.offset = 15, +		.width = 1, +	}, +	[VCAP_KF_8021CB_R_TAGGED_IS] = { +		.type = VCAP_FIELD_BIT, +		.offset = 16, +		.width = 1, +	}, +	[VCAP_KF_8021Q_VLAN_TAGGED_IS] = { +		.type = VCAP_FIELD_BIT, +		.offset = 17, +		.width = 1, +	}, +	[VCAP_KF_8021Q_VLAN_DBL_TAGGED_IS] = { +		.type = VCAP_FIELD_BIT, +		.offset = 18, +		.width = 1, +	}, +	[VCAP_KF_8021Q_TPID0] = { +		.type = VCAP_FIELD_BIT, +		.offset = 19, +		.width = 1, +	}, +	[VCAP_KF_8021Q_VID0] = { +		.type = VCAP_FIELD_U32, +		.offset = 20, +		.width = 12, +	}, +	[VCAP_KF_8021Q_DEI0] = { +		.type = VCAP_FIELD_BIT, +		.offset = 32, +		.width = 1, +	}, +	[VCAP_KF_8021Q_PCP0] = { +		.type = VCAP_FIELD_U32, +		.offset = 33, +		.width = 3, +	}, +	[VCAP_KF_8021Q_TPID1] = { +		.type = VCAP_FIELD_BIT, +		.offset = 36, +		.width = 1, +	}, +	[VCAP_KF_8021Q_VID1] = { +		.type = VCAP_FIELD_U32, +		.offset = 37, +		.width = 12, +	}, +	[VCAP_KF_8021Q_DEI1] = { +		.type = VCAP_FIELD_BIT, +		.offset = 49, +		.width = 1, +	}, +	[VCAP_KF_8021Q_PCP1] = { +		.type = VCAP_FIELD_U32, +		.offset = 50, +		.width = 3, +	}, +	[VCAP_KF_L2_SMAC] = { +		.type = VCAP_FIELD_U48, +		.offset = 53, +		.width = 48, +	}, +	[VCAP_KF_L3_DSCP] = { +		.type = VCAP_FIELD_U32, +		.offset = 101, +		.width = 6, +	}, +	[VCAP_KF_L3_IP6_SIP] = { +		.type = VCAP_FIELD_U128, +		.offset = 107, +		.width = 128, +	}, +	[VCAP_KF_L3_IP_PROTO] = { +		.type = VCAP_FIELD_U32, +		.offset = 235, +		.width = 8, +	}, +	[VCAP_KF_TCP_UDP_IS] = { +		.type = VCAP_FIELD_BIT, +		.offset = 243, +		.width = 1, +	}, +	[VCAP_KF_L4_RNG] = { +		.type = VCAP_FIELD_U32, +		.offset = 244, +		.width = 8, +	}, +	[VCAP_KF_IP_PAYLOAD_S1_IP6] = { +		.type = VCAP_FIELD_U112, +		.offset = 252, +		.width = 112, +	}, +}; + +static const struct vcap_field is1_7tuple_keyfield[] = { +	[VCAP_KF_TYPE] = { +		.type = VCAP_FIELD_U32, +		.offset = 0, +		.width = 2, +	}, +	[VCAP_KF_LOOKUP_INDEX] = { +		.type = VCAP_FIELD_U32, +		.offset = 2, +		.width = 2, +	}, +	[VCAP_KF_IF_IGR_PORT_MASK] = { +		.type = VCAP_FIELD_U32, +		.offset = 4, +		.width = 9, +	}, +	[VCAP_KF_L2_MC_IS] = { +		.type = VCAP_FIELD_BIT, +		.offset = 13, +		.width = 1, +	}, +	[VCAP_KF_L2_BC_IS] = { +		.type = VCAP_FIELD_BIT, +		.offset = 14, +		.width = 1, +	}, +	[VCAP_KF_IP_MC_IS] = { +		.type = VCAP_FIELD_BIT, +		.offset = 15, +		.width = 1, +	}, +	[VCAP_KF_8021CB_R_TAGGED_IS] = { +		.type = VCAP_FIELD_BIT, +		.offset = 16, +		.width = 1, +	}, +	[VCAP_KF_8021Q_VLAN_TAGGED_IS] = { +		.type = VCAP_FIELD_BIT, +		.offset = 17, +		.width = 1, +	}, +	[VCAP_KF_8021Q_VLAN_DBL_TAGGED_IS] = { +		.type = VCAP_FIELD_BIT, +		.offset = 18, +		.width = 1, +	}, +	[VCAP_KF_8021Q_TPID0] = { +		.type = VCAP_FIELD_BIT, +		.offset = 19, +		.width = 1, +	}, +	[VCAP_KF_8021Q_VID0] = { +		.type = VCAP_FIELD_U32, +		.offset = 20, +		.width = 12, +	}, +	[VCAP_KF_8021Q_DEI0] = { +		.type = VCAP_FIELD_BIT, +		.offset = 32, +		.width = 1, +	}, +	[VCAP_KF_8021Q_PCP0] = { +		.type = VCAP_FIELD_U32, +		.offset = 33, +		.width = 3, +	}, +	[VCAP_KF_8021Q_TPID1] = { +		.type = VCAP_FIELD_BIT, +		.offset = 36, +		.width = 1, +	}, +	[VCAP_KF_8021Q_VID1] = { +		.type = VCAP_FIELD_U32, +		.offset = 37, +		.width = 12, +	}, +	[VCAP_KF_8021Q_DEI1] = { +		.type = VCAP_FIELD_BIT, +		.offset = 49, +		.width = 1, +	}, +	[VCAP_KF_8021Q_PCP1] = { +		.type = VCAP_FIELD_U32, +		.offset = 50, +		.width = 3, +	}, +	[VCAP_KF_L2_DMAC] = { +		.type = VCAP_FIELD_U48, +		.offset = 53, +		.width = 48, +	}, +	[VCAP_KF_L2_SMAC] = { +		.type = VCAP_FIELD_U48, +		.offset = 101, +		.width = 48, +	}, +	[VCAP_KF_ETYPE_LEN_IS] = { +		.type = VCAP_FIELD_BIT, +		.offset = 149, +		.width = 1, +	}, +	[VCAP_KF_ETYPE] = { +		.type = VCAP_FIELD_U32, +		.offset = 150, +		.width = 16, +	}, +	[VCAP_KF_IP_SNAP_IS] = { +		.type = VCAP_FIELD_BIT, +		.offset = 166, +		.width = 1, +	}, +	[VCAP_KF_IP4_IS] = { +		.type = VCAP_FIELD_BIT, +		.offset = 167, +		.width = 1, +	}, +	[VCAP_KF_L3_FRAGMENT] = { +		.type = VCAP_FIELD_BIT, +		.offset = 168, +		.width = 1, +	}, +	[VCAP_KF_L3_FRAG_OFS_GT0] = { +		.type = VCAP_FIELD_BIT, +		.offset = 169, +		.width = 1, +	}, +	[VCAP_KF_L3_OPTIONS_IS] = { +		.type = VCAP_FIELD_BIT, +		.offset = 170, +		.width = 1, +	}, +	[VCAP_KF_L3_DSCP] = { +		.type = VCAP_FIELD_U32, +		.offset = 171, +		.width = 6, +	}, +	[VCAP_KF_L3_IP6_DIP_MSB] = { +		.type = VCAP_FIELD_U32, +		.offset = 177, +		.width = 16, +	}, +	[VCAP_KF_L3_IP6_DIP] = { +		.type = VCAP_FIELD_U64, +		.offset = 193, +		.width = 64, +	}, +	[VCAP_KF_L3_IP6_SIP_MSB] = { +		.type = VCAP_FIELD_U32, +		.offset = 257, +		.width = 16, +	}, +	[VCAP_KF_L3_IP6_SIP] = { +		.type = VCAP_FIELD_U64, +		.offset = 273, +		.width = 64, +	}, +	[VCAP_KF_TCP_UDP_IS] = { +		.type = VCAP_FIELD_BIT, +		.offset = 337, +		.width = 1, +	}, +	[VCAP_KF_TCP_IS] = { +		.type = VCAP_FIELD_BIT, +		.offset = 338, +		.width = 1, +	}, +	[VCAP_KF_L4_SPORT] = { +		.type = VCAP_FIELD_U32, +		.offset = 339, +		.width = 16, +	}, +	[VCAP_KF_L4_RNG] = { +		.type = VCAP_FIELD_U32, +		.offset = 355, +		.width = 8, +	}, +}; + +static const struct vcap_field is1_5tuple_ip6_keyfield[] = { +	[VCAP_KF_TYPE] = { +		.type = VCAP_FIELD_U32, +		.offset = 0, +		.width = 2, +	}, +	[VCAP_KF_LOOKUP_INDEX] = { +		.type = VCAP_FIELD_U32, +		.offset = 2, +		.width = 2, +	}, +	[VCAP_KF_IF_IGR_PORT_MASK] = { +		.type = VCAP_FIELD_U32, +		.offset = 4, +		.width = 9, +	}, +	[VCAP_KF_L2_MC_IS] = { +		.type = VCAP_FIELD_BIT, +		.offset = 13, +		.width = 1, +	}, +	[VCAP_KF_L2_BC_IS] = { +		.type = VCAP_FIELD_BIT, +		.offset = 14, +		.width = 1, +	}, +	[VCAP_KF_IP_MC_IS] = { +		.type = VCAP_FIELD_BIT, +		.offset = 15, +		.width = 1, +	}, +	[VCAP_KF_8021CB_R_TAGGED_IS] = { +		.type = VCAP_FIELD_BIT, +		.offset = 16, +		.width = 1, +	}, +	[VCAP_KF_8021Q_VLAN_TAGGED_IS] = { +		.type = VCAP_FIELD_BIT, +		.offset = 17, +		.width = 1, +	}, +	[VCAP_KF_8021Q_VLAN_DBL_TAGGED_IS] = { +		.type = VCAP_FIELD_BIT, +		.offset = 18, +		.width = 1, +	}, +	[VCAP_KF_8021Q_TPID0] = { +		.type = VCAP_FIELD_BIT, +		.offset = 19, +		.width = 1, +	}, +	[VCAP_KF_8021Q_VID0] = { +		.type = VCAP_FIELD_U32, +		.offset = 20, +		.width = 12, +	}, +	[VCAP_KF_8021Q_DEI0] = { +		.type = VCAP_FIELD_BIT, +		.offset = 32, +		.width = 1, +	}, +	[VCAP_KF_8021Q_PCP0] = { +		.type = VCAP_FIELD_U32, +		.offset = 33, +		.width = 3, +	}, +	[VCAP_KF_8021Q_TPID1] = { +		.type = VCAP_FIELD_BIT, +		.offset = 36, +		.width = 1, +	}, +	[VCAP_KF_8021Q_VID1] = { +		.type = VCAP_FIELD_U32, +		.offset = 37, +		.width = 12, +	}, +	[VCAP_KF_8021Q_DEI1] = { +		.type = VCAP_FIELD_BIT, +		.offset = 49, +		.width = 1, +	}, +	[VCAP_KF_8021Q_PCP1] = { +		.type = VCAP_FIELD_U32, +		.offset = 50, +		.width = 3, +	}, +	[VCAP_KF_L3_DSCP] = { +		.type = VCAP_FIELD_U32, +		.offset = 53, +		.width = 6, +	}, +	[VCAP_KF_L3_IP6_DIP] = { +		.type = VCAP_FIELD_U128, +		.offset = 59, +		.width = 128, +	}, +	[VCAP_KF_L3_IP6_SIP] = { +		.type = VCAP_FIELD_U128, +		.offset = 187, +		.width = 128, +	}, +	[VCAP_KF_L3_IP_PROTO] = { +		.type = VCAP_FIELD_U32, +		.offset = 315, +		.width = 8, +	}, +	[VCAP_KF_TCP_UDP_IS] = { +		.type = VCAP_FIELD_BIT, +		.offset = 323, +		.width = 1, +	}, +	[VCAP_KF_L4_RNG] = { +		.type = VCAP_FIELD_U32, +		.offset = 324, +		.width = 8, +	}, +	[VCAP_KF_IP_PAYLOAD_5TUPLE] = { +		.type = VCAP_FIELD_U32, +		.offset = 332, +		.width = 32, +	}, +}; + +static const struct vcap_field is1_dbl_vid_keyfield[] = { +	[VCAP_KF_TYPE] = { +		.type = VCAP_FIELD_U32, +		.offset = 0, +		.width = 2, +	}, +	[VCAP_KF_LOOKUP_INDEX] = { +		.type = VCAP_FIELD_U32, +		.offset = 2, +		.width = 2, +	}, +	[VCAP_KF_IF_IGR_PORT_MASK] = { +		.type = VCAP_FIELD_U32, +		.offset = 4, +		.width = 9, +	}, +	[VCAP_KF_L2_MC_IS] = { +		.type = VCAP_FIELD_BIT, +		.offset = 13, +		.width = 1, +	}, +	[VCAP_KF_L2_BC_IS] = { +		.type = VCAP_FIELD_BIT, +		.offset = 14, +		.width = 1, +	}, +	[VCAP_KF_IP_MC_IS] = { +		.type = VCAP_FIELD_BIT, +		.offset = 15, +		.width = 1, +	}, +	[VCAP_KF_8021CB_R_TAGGED_IS] = { +		.type = VCAP_FIELD_BIT, +		.offset = 16, +		.width = 1, +	}, +	[VCAP_KF_8021Q_VLAN_TAGGED_IS] = { +		.type = VCAP_FIELD_BIT, +		.offset = 17, +		.width = 1, +	}, +	[VCAP_KF_8021Q_VLAN_DBL_TAGGED_IS] = { +		.type = VCAP_FIELD_BIT, +		.offset = 18, +		.width = 1, +	}, +	[VCAP_KF_8021Q_TPID0] = { +		.type = VCAP_FIELD_BIT, +		.offset = 19, +		.width = 1, +	}, +	[VCAP_KF_8021Q_VID0] = { +		.type = VCAP_FIELD_U32, +		.offset = 20, +		.width = 12, +	}, +	[VCAP_KF_8021Q_DEI0] = { +		.type = VCAP_FIELD_BIT, +		.offset = 32, +		.width = 1, +	}, +	[VCAP_KF_8021Q_PCP0] = { +		.type = VCAP_FIELD_U32, +		.offset = 33, +		.width = 3, +	}, +	[VCAP_KF_8021Q_TPID1] = { +		.type = VCAP_FIELD_BIT, +		.offset = 36, +		.width = 1, +	}, +	[VCAP_KF_8021Q_VID1] = { +		.type = VCAP_FIELD_U32, +		.offset = 37, +		.width = 12, +	}, +	[VCAP_KF_8021Q_DEI1] = { +		.type = VCAP_FIELD_BIT, +		.offset = 49, +		.width = 1, +	}, +	[VCAP_KF_8021Q_PCP1] = { +		.type = VCAP_FIELD_U32, +		.offset = 50, +		.width = 3, +	}, +	[VCAP_KF_ETYPE_LEN_IS] = { +		.type = VCAP_FIELD_BIT, +		.offset = 53, +		.width = 1, +	}, +	[VCAP_KF_ETYPE] = { +		.type = VCAP_FIELD_U32, +		.offset = 54, +		.width = 16, +	}, +	[VCAP_KF_IP_SNAP_IS] = { +		.type = VCAP_FIELD_BIT, +		.offset = 70, +		.width = 1, +	}, +	[VCAP_KF_IP4_IS] = { +		.type = VCAP_FIELD_BIT, +		.offset = 71, +		.width = 1, +	}, +	[VCAP_KF_L3_FRAGMENT] = { +		.type = VCAP_FIELD_BIT, +		.offset = 72, +		.width = 1, +	}, +	[VCAP_KF_L3_FRAG_OFS_GT0] = { +		.type = VCAP_FIELD_BIT, +		.offset = 73, +		.width = 1, +	}, +	[VCAP_KF_L3_OPTIONS_IS] = { +		.type = VCAP_FIELD_BIT, +		.offset = 74, +		.width = 1, +	}, +	[VCAP_KF_L3_DSCP] = { +		.type = VCAP_FIELD_U32, +		.offset = 75, +		.width = 6, +	}, +	[VCAP_KF_TCP_UDP_IS] = { +		.type = VCAP_FIELD_BIT, +		.offset = 81, +		.width = 1, +	}, +	[VCAP_KF_TCP_IS] = { +		.type = VCAP_FIELD_BIT, +		.offset = 82, +		.width = 1, +	}, +}; + +static const struct vcap_field is1_rt_keyfield[] = { +	[VCAP_KF_TYPE] = { +		.type = VCAP_FIELD_U32, +		.offset = 0, +		.width = 2, +	}, +	[VCAP_KF_LOOKUP_FIRST_IS] = { +		.type = VCAP_FIELD_BIT, +		.offset = 2, +		.width = 1, +	}, +	[VCAP_KF_IF_IGR_PORT] = { +		.type = VCAP_FIELD_U32, +		.offset = 3, +		.width = 3, +	}, +	[VCAP_KF_8021CB_R_TAGGED_IS] = { +		.type = VCAP_FIELD_BIT, +		.offset = 6, +		.width = 1, +	}, +	[VCAP_KF_8021Q_VLAN_TAGGED_IS] = { +		.type = VCAP_FIELD_BIT, +		.offset = 7, +		.width = 1, +	}, +	[VCAP_KF_8021Q_VLAN_DBL_TAGGED_IS] = { +		.type = VCAP_FIELD_BIT, +		.offset = 8, +		.width = 1, +	}, +	[VCAP_KF_L2_MAC] = { +		.type = VCAP_FIELD_U48, +		.offset = 9, +		.width = 48, +	}, +	[VCAP_KF_RT_VLAN_IDX] = { +		.type = VCAP_FIELD_U32, +		.offset = 57, +		.width = 3, +	}, +	[VCAP_KF_RT_TYPE] = { +		.type = VCAP_FIELD_U32, +		.offset = 60, +		.width = 2, +	}, +	[VCAP_KF_RT_FRMID] = { +		.type = VCAP_FIELD_U32, +		.offset = 62, +		.width = 32, +	}, +}; + +static const struct vcap_field is1_dmac_vid_keyfield[] = { +	[VCAP_KF_TYPE] = { +		.type = VCAP_FIELD_U32, +		.offset = 0, +		.width = 2, +	}, +	[VCAP_KF_LOOKUP_INDEX] = { +		.type = VCAP_FIELD_U32, +		.offset = 2, +		.width = 2, +	}, +	[VCAP_KF_IF_IGR_PORT_MASK] = { +		.type = VCAP_FIELD_U32, +		.offset = 4, +		.width = 9, +	}, +	[VCAP_KF_8021CB_R_TAGGED_IS] = { +		.type = VCAP_FIELD_BIT, +		.offset = 13, +		.width = 1, +	}, +	[VCAP_KF_8021Q_VLAN_TAGGED_IS] = { +		.type = VCAP_FIELD_BIT, +		.offset = 14, +		.width = 1, +	}, +	[VCAP_KF_8021Q_VLAN_DBL_TAGGED_IS] = { +		.type = VCAP_FIELD_BIT, +		.offset = 15, +		.width = 1, +	}, +	[VCAP_KF_8021Q_TPID0] = { +		.type = VCAP_FIELD_BIT, +		.offset = 16, +		.width = 1, +	}, +	[VCAP_KF_8021Q_VID0] = { +		.type = VCAP_FIELD_U32, +		.offset = 17, +		.width = 12, +	}, +	[VCAP_KF_8021Q_DEI0] = { +		.type = VCAP_FIELD_BIT, +		.offset = 29, +		.width = 1, +	}, +	[VCAP_KF_8021Q_PCP0] = { +		.type = VCAP_FIELD_U32, +		.offset = 30, +		.width = 3, +	}, +	[VCAP_KF_L2_DMAC] = { +		.type = VCAP_FIELD_U48, +		.offset = 33, +		.width = 48, +	}, +}; +  static const struct vcap_field is2_mac_etype_keyfield[] = {  	[VCAP_KF_TYPE] = {  		.type = VCAP_FIELD_U32, @@ -1163,6 +2122,49 @@ static const struct vcap_field is2_smac_sip6_keyfield[] = {  };  /* keyfield_set */ +static const struct vcap_set is1_keyfield_set[] = { +	[VCAP_KFS_NORMAL] = { +		.type_id = 0, +		.sw_per_item = 2, +		.sw_cnt = 2, +	}, +	[VCAP_KFS_5TUPLE_IP4] = { +		.type_id = 1, +		.sw_per_item = 2, +		.sw_cnt = 2, +	}, +	[VCAP_KFS_NORMAL_IP6] = { +		.type_id = 0, +		.sw_per_item = 4, +		.sw_cnt = 1, +	}, +	[VCAP_KFS_7TUPLE] = { +		.type_id = 1, +		.sw_per_item = 4, +		.sw_cnt = 1, +	}, +	[VCAP_KFS_5TUPLE_IP6] = { +		.type_id = 2, +		.sw_per_item = 4, +		.sw_cnt = 1, +	}, +	[VCAP_KFS_DBL_VID] = { +		.type_id = 0, +		.sw_per_item = 1, +		.sw_cnt = 4, +	}, +	[VCAP_KFS_RT] = { +		.type_id = 1, +		.sw_per_item = 1, +		.sw_cnt = 4, +	}, +	[VCAP_KFS_DMAC_VID] = { +		.type_id = 2, +		.sw_per_item = 1, +		.sw_cnt = 4, +	}, +}; +  static const struct vcap_set is2_keyfield_set[] = {  	[VCAP_KFS_MAC_ETYPE] = {  		.type_id = 0, @@ -1227,6 +2229,17 @@ static const struct vcap_set is2_keyfield_set[] = {  };  /* keyfield_set map */ +static const struct vcap_field *is1_keyfield_set_map[] = { +	[VCAP_KFS_NORMAL] = is1_normal_keyfield, +	[VCAP_KFS_5TUPLE_IP4] = is1_5tuple_ip4_keyfield, +	[VCAP_KFS_NORMAL_IP6] = is1_normal_ip6_keyfield, +	[VCAP_KFS_7TUPLE] = is1_7tuple_keyfield, +	[VCAP_KFS_5TUPLE_IP6] = is1_5tuple_ip6_keyfield, +	[VCAP_KFS_DBL_VID] = is1_dbl_vid_keyfield, +	[VCAP_KFS_RT] = is1_rt_keyfield, +	[VCAP_KFS_DMAC_VID] = is1_dmac_vid_keyfield, +}; +  static const struct vcap_field *is2_keyfield_set_map[] = {  	[VCAP_KFS_MAC_ETYPE] = is2_mac_etype_keyfield,  	[VCAP_KFS_MAC_LLC] = is2_mac_llc_keyfield, @@ -1243,6 +2256,17 @@ static const struct vcap_field *is2_keyfield_set_map[] = {  };  /* keyfield_set map sizes */ +static int is1_keyfield_set_map_size[] = { +	[VCAP_KFS_NORMAL] = ARRAY_SIZE(is1_normal_keyfield), +	[VCAP_KFS_5TUPLE_IP4] = ARRAY_SIZE(is1_5tuple_ip4_keyfield), +	[VCAP_KFS_NORMAL_IP6] = ARRAY_SIZE(is1_normal_ip6_keyfield), +	[VCAP_KFS_7TUPLE] = ARRAY_SIZE(is1_7tuple_keyfield), +	[VCAP_KFS_5TUPLE_IP6] = ARRAY_SIZE(is1_5tuple_ip6_keyfield), +	[VCAP_KFS_DBL_VID] = ARRAY_SIZE(is1_dbl_vid_keyfield), +	[VCAP_KFS_RT] = ARRAY_SIZE(is1_rt_keyfield), +	[VCAP_KFS_DMAC_VID] = ARRAY_SIZE(is1_dmac_vid_keyfield), +}; +  static int is2_keyfield_set_map_size[] = {  	[VCAP_KFS_MAC_ETYPE] = ARRAY_SIZE(is2_mac_etype_keyfield),  	[VCAP_KFS_MAC_LLC] = ARRAY_SIZE(is2_mac_llc_keyfield), @@ -1259,6 +2283,154 @@ static int is2_keyfield_set_map_size[] = {  };  /* actionfields */ +static const struct vcap_field is1_s1_actionfield[] = { +	[VCAP_AF_TYPE] = { +		.type = VCAP_FIELD_BIT, +		.offset = 0, +		.width = 1, +	}, +	[VCAP_AF_DSCP_ENA] = { +		.type = VCAP_FIELD_BIT, +		.offset = 1, +		.width = 1, +	}, +	[VCAP_AF_DSCP_VAL] = { +		.type = VCAP_FIELD_U32, +		.offset = 2, +		.width = 6, +	}, +	[VCAP_AF_QOS_ENA] = { +		.type = VCAP_FIELD_BIT, +		.offset = 8, +		.width = 1, +	}, +	[VCAP_AF_QOS_VAL] = { +		.type = VCAP_FIELD_U32, +		.offset = 9, +		.width = 3, +	}, +	[VCAP_AF_DP_ENA] = { +		.type = VCAP_FIELD_BIT, +		.offset = 12, +		.width = 1, +	}, +	[VCAP_AF_DP_VAL] = { +		.type = VCAP_FIELD_BIT, +		.offset = 13, +		.width = 1, +	}, +	[VCAP_AF_PAG_OVERRIDE_MASK] = { +		.type = VCAP_FIELD_U32, +		.offset = 14, +		.width = 8, +	}, +	[VCAP_AF_PAG_VAL] = { +		.type = VCAP_FIELD_U32, +		.offset = 22, +		.width = 8, +	}, +	[VCAP_AF_ISDX_REPLACE_ENA] = { +		.type = VCAP_FIELD_BIT, +		.offset = 30, +		.width = 1, +	}, +	[VCAP_AF_ISDX_ADD_VAL] = { +		.type = VCAP_FIELD_U32, +		.offset = 31, +		.width = 8, +	}, +	[VCAP_AF_VID_REPLACE_ENA] = { +		.type = VCAP_FIELD_BIT, +		.offset = 39, +		.width = 1, +	}, +	[VCAP_AF_VID_VAL] = { +		.type = VCAP_FIELD_U32, +		.offset = 40, +		.width = 12, +	}, +	[VCAP_AF_PCP_ENA] = { +		.type = VCAP_FIELD_BIT, +		.offset = 67, +		.width = 1, +	}, +	[VCAP_AF_PCP_VAL] = { +		.type = VCAP_FIELD_U32, +		.offset = 68, +		.width = 3, +	}, +	[VCAP_AF_DEI_ENA] = { +		.type = VCAP_FIELD_BIT, +		.offset = 71, +		.width = 1, +	}, +	[VCAP_AF_DEI_VAL] = { +		.type = VCAP_FIELD_BIT, +		.offset = 72, +		.width = 1, +	}, +	[VCAP_AF_VLAN_POP_CNT_ENA] = { +		.type = VCAP_FIELD_BIT, +		.offset = 73, +		.width = 1, +	}, +	[VCAP_AF_VLAN_POP_CNT] = { +		.type = VCAP_FIELD_U32, +		.offset = 74, +		.width = 2, +	}, +	[VCAP_AF_CUSTOM_ACE_TYPE_ENA] = { +		.type = VCAP_FIELD_U32, +		.offset = 76, +		.width = 4, +	}, +	[VCAP_AF_SFID_ENA] = { +		.type = VCAP_FIELD_BIT, +		.offset = 80, +		.width = 1, +	}, +	[VCAP_AF_SFID_VAL] = { +		.type = VCAP_FIELD_U32, +		.offset = 81, +		.width = 8, +	}, +	[VCAP_AF_SGID_ENA] = { +		.type = VCAP_FIELD_BIT, +		.offset = 89, +		.width = 1, +	}, +	[VCAP_AF_SGID_VAL] = { +		.type = VCAP_FIELD_U32, +		.offset = 90, +		.width = 8, +	}, +	[VCAP_AF_POLICE_ENA] = { +		.type = VCAP_FIELD_BIT, +		.offset = 98, +		.width = 1, +	}, +	[VCAP_AF_POLICE_IDX] = { +		.type = VCAP_FIELD_U32, +		.offset = 99, +		.width = 9, +	}, +	[VCAP_AF_OAM_SEL] = { +		.type = VCAP_FIELD_U32, +		.offset = 108, +		.width = 3, +	}, +	[VCAP_AF_MRP_SEL] = { +		.type = VCAP_FIELD_U32, +		.offset = 111, +		.width = 2, +	}, +	[VCAP_AF_DLR_SEL] = { +		.type = VCAP_FIELD_U32, +		.offset = 113, +		.width = 2, +	}, +}; +  static const struct vcap_field is2_base_type_actionfield[] = {  	[VCAP_AF_HIT_ME_ONCE] = {  		.type = VCAP_FIELD_BIT, @@ -1351,6 +2523,14 @@ static const struct vcap_field is2_smac_sip_actionfield[] = {  };  /* actionfield_set */ +static const struct vcap_set is1_actionfield_set[] = { +	[VCAP_AFS_S1] = { +		.type_id = 0, +		.sw_per_item = 1, +		.sw_cnt = 4, +	}, +}; +  static const struct vcap_set is2_actionfield_set[] = {  	[VCAP_AFS_BASE_TYPE] = {  		.type_id = -1, @@ -1365,18 +2545,73 @@ static const struct vcap_set is2_actionfield_set[] = {  };  /* actionfield_set map */ +static const struct vcap_field *is1_actionfield_set_map[] = { +	[VCAP_AFS_S1] = is1_s1_actionfield, +}; +  static const struct vcap_field *is2_actionfield_set_map[] = {  	[VCAP_AFS_BASE_TYPE] = is2_base_type_actionfield,  	[VCAP_AFS_SMAC_SIP] = is2_smac_sip_actionfield,  };  /* actionfield_set map size */ +static int is1_actionfield_set_map_size[] = { +	[VCAP_AFS_S1] = ARRAY_SIZE(is1_s1_actionfield), +}; +  static int is2_actionfield_set_map_size[] = {  	[VCAP_AFS_BASE_TYPE] = ARRAY_SIZE(is2_base_type_actionfield),  	[VCAP_AFS_SMAC_SIP] = ARRAY_SIZE(is2_smac_sip_actionfield),  };  /* Type Groups */ +static const struct vcap_typegroup is1_x4_keyfield_set_typegroups[] = { +	{ +		.offset = 0, +		.width = 3, +		.value = 4, +	}, +	{ +		.offset = 96, +		.width = 1, +		.value = 0, +	}, +	{ +		.offset = 192, +		.width = 2, +		.value = 0, +	}, +	{ +		.offset = 288, +		.width = 1, +		.value = 0, +	}, +	{} +}; + +static const struct vcap_typegroup is1_x2_keyfield_set_typegroups[] = { +	{ +		.offset = 0, +		.width = 2, +		.value = 2, +	}, +	{ +		.offset = 96, +		.width = 1, +		.value = 0, +	}, +	{} +}; + +static const struct vcap_typegroup is1_x1_keyfield_set_typegroups[] = { +	{ +		.offset = 0, +		.width = 1, +		.value = 1, +	}, +	{} +}; +  static const struct vcap_typegroup is2_x4_keyfield_set_typegroups[] = {  	{  		.offset = 0, @@ -1424,6 +2659,13 @@ static const struct vcap_typegroup is2_x1_keyfield_set_typegroups[] = {  	{}  }; +static const struct vcap_typegroup *is1_keyfield_set_typegroups[] = { +	[4] = is1_x4_keyfield_set_typegroups, +	[2] = is1_x2_keyfield_set_typegroups, +	[1] = is1_x1_keyfield_set_typegroups, +	[5] = NULL, +}; +  static const struct vcap_typegroup *is2_keyfield_set_typegroups[] = {  	[4] = is2_x4_keyfield_set_typegroups,  	[2] = is2_x2_keyfield_set_typegroups, @@ -1431,6 +2673,10 @@ static const struct vcap_typegroup *is2_keyfield_set_typegroups[] = {  	[5] = NULL,  }; +static const struct vcap_typegroup is1_x1_actionfield_set_typegroups[] = { +	{} +}; +  static const struct vcap_typegroup is2_x2_actionfield_set_typegroups[] = {  	{  		.offset = 0, @@ -1454,6 +2700,11 @@ static const struct vcap_typegroup is2_x1_actionfield_set_typegroups[] = {  	{}  }; +static const struct vcap_typegroup *is1_actionfield_set_typegroups[] = { +	[1] = is1_x1_actionfield_set_typegroups, +	[5] = NULL, +}; +  static const struct vcap_typegroup *is2_actionfield_set_typegroups[] = {  	[2] = is2_x2_actionfield_set_typegroups,  	[1] = is2_x1_actionfield_set_typegroups, @@ -1463,16 +2714,33 @@ static const struct vcap_typegroup *is2_actionfield_set_typegroups[] = {  /* Keyfieldset names */  static const char * const vcap_keyfield_set_names[] = {  	[VCAP_KFS_NO_VALUE]                      =  "(None)", +	[VCAP_KFS_5TUPLE_IP4]                    =  "VCAP_KFS_5TUPLE_IP4", +	[VCAP_KFS_5TUPLE_IP6]                    =  "VCAP_KFS_5TUPLE_IP6", +	[VCAP_KFS_7TUPLE]                        =  "VCAP_KFS_7TUPLE",  	[VCAP_KFS_ARP]                           =  "VCAP_KFS_ARP", +	[VCAP_KFS_DBL_VID]                       =  "VCAP_KFS_DBL_VID", +	[VCAP_KFS_DMAC_VID]                      =  "VCAP_KFS_DMAC_VID", +	[VCAP_KFS_ETAG]                          =  "VCAP_KFS_ETAG",  	[VCAP_KFS_IP4_OTHER]                     =  "VCAP_KFS_IP4_OTHER",  	[VCAP_KFS_IP4_TCP_UDP]                   =  "VCAP_KFS_IP4_TCP_UDP", +	[VCAP_KFS_IP4_VID]                       =  "VCAP_KFS_IP4_VID",  	[VCAP_KFS_IP6_OTHER]                     =  "VCAP_KFS_IP6_OTHER",  	[VCAP_KFS_IP6_STD]                       =  "VCAP_KFS_IP6_STD",  	[VCAP_KFS_IP6_TCP_UDP]                   =  "VCAP_KFS_IP6_TCP_UDP", +	[VCAP_KFS_IP6_VID]                       =  "VCAP_KFS_IP6_VID", +	[VCAP_KFS_IP_7TUPLE]                     =  "VCAP_KFS_IP_7TUPLE", +	[VCAP_KFS_ISDX]                          =  "VCAP_KFS_ISDX", +	[VCAP_KFS_LL_FULL]                       =  "VCAP_KFS_LL_FULL",  	[VCAP_KFS_MAC_ETYPE]                     =  "VCAP_KFS_MAC_ETYPE",  	[VCAP_KFS_MAC_LLC]                       =  "VCAP_KFS_MAC_LLC",  	[VCAP_KFS_MAC_SNAP]                      =  "VCAP_KFS_MAC_SNAP", +	[VCAP_KFS_NORMAL]                        =  "VCAP_KFS_NORMAL", +	[VCAP_KFS_NORMAL_5TUPLE_IP4]             =  "VCAP_KFS_NORMAL_5TUPLE_IP4", +	[VCAP_KFS_NORMAL_7TUPLE]                 =  "VCAP_KFS_NORMAL_7TUPLE", +	[VCAP_KFS_NORMAL_IP6]                    =  "VCAP_KFS_NORMAL_IP6",  	[VCAP_KFS_OAM]                           =  "VCAP_KFS_OAM", +	[VCAP_KFS_PURE_5TUPLE_IP4]               =  "VCAP_KFS_PURE_5TUPLE_IP4", +	[VCAP_KFS_RT]                            =  "VCAP_KFS_RT",  	[VCAP_KFS_SMAC_SIP4]                     =  "VCAP_KFS_SMAC_SIP4",  	[VCAP_KFS_SMAC_SIP6]                     =  "VCAP_KFS_SMAC_SIP6",  }; @@ -1481,16 +2749,42 @@ static const char * const vcap_keyfield_set_names[] = {  static const char * const vcap_actionfield_set_names[] = {  	[VCAP_AFS_NO_VALUE]                      =  "(None)",  	[VCAP_AFS_BASE_TYPE]                     =  "VCAP_AFS_BASE_TYPE", +	[VCAP_AFS_CLASSIFICATION]                =  "VCAP_AFS_CLASSIFICATION", +	[VCAP_AFS_CLASS_REDUCED]                 =  "VCAP_AFS_CLASS_REDUCED", +	[VCAP_AFS_FULL]                          =  "VCAP_AFS_FULL", +	[VCAP_AFS_S1]                            =  "VCAP_AFS_S1",  	[VCAP_AFS_SMAC_SIP]                      =  "VCAP_AFS_SMAC_SIP",  };  /* Keyfield names */  static const char * const vcap_keyfield_names[] = {  	[VCAP_KF_NO_VALUE]                       =  "(None)", +	[VCAP_KF_8021BR_ECID_BASE]               =  "8021BR_ECID_BASE", +	[VCAP_KF_8021BR_ECID_EXT]                =  "8021BR_ECID_EXT", +	[VCAP_KF_8021BR_E_TAGGED]                =  "8021BR_E_TAGGED", +	[VCAP_KF_8021BR_GRP]                     =  "8021BR_GRP", +	[VCAP_KF_8021BR_IGR_ECID_BASE]           =  "8021BR_IGR_ECID_BASE", +	[VCAP_KF_8021BR_IGR_ECID_EXT]            =  "8021BR_IGR_ECID_EXT", +	[VCAP_KF_8021CB_R_TAGGED_IS]             =  "8021CB_R_TAGGED_IS", +	[VCAP_KF_8021Q_DEI0]                     =  "8021Q_DEI0", +	[VCAP_KF_8021Q_DEI1]                     =  "8021Q_DEI1", +	[VCAP_KF_8021Q_DEI2]                     =  "8021Q_DEI2",  	[VCAP_KF_8021Q_DEI_CLS]                  =  "8021Q_DEI_CLS", +	[VCAP_KF_8021Q_PCP0]                     =  "8021Q_PCP0", +	[VCAP_KF_8021Q_PCP1]                     =  "8021Q_PCP1", +	[VCAP_KF_8021Q_PCP2]                     =  "8021Q_PCP2",  	[VCAP_KF_8021Q_PCP_CLS]                  =  "8021Q_PCP_CLS", +	[VCAP_KF_8021Q_TPID0]                    =  "8021Q_TPID0", +	[VCAP_KF_8021Q_TPID1]                    =  "8021Q_TPID1", +	[VCAP_KF_8021Q_TPID2]                    =  "8021Q_TPID2", +	[VCAP_KF_8021Q_VID0]                     =  "8021Q_VID0", +	[VCAP_KF_8021Q_VID1]                     =  "8021Q_VID1", +	[VCAP_KF_8021Q_VID2]                     =  "8021Q_VID2",  	[VCAP_KF_8021Q_VID_CLS]                  =  "8021Q_VID_CLS", +	[VCAP_KF_8021Q_VLAN_DBL_TAGGED_IS]       =  "8021Q_VLAN_DBL_TAGGED_IS",  	[VCAP_KF_8021Q_VLAN_TAGGED_IS]           =  "8021Q_VLAN_TAGGED_IS", +	[VCAP_KF_8021Q_VLAN_TAGS]                =  "8021Q_VLAN_TAGS", +	[VCAP_KF_ACL_GRP_ID]                     =  "ACL_GRP_ID",  	[VCAP_KF_ARP_ADDR_SPACE_OK_IS]           =  "ARP_ADDR_SPACE_OK_IS",  	[VCAP_KF_ARP_LEN_OK_IS]                  =  "ARP_LEN_OK_IS",  	[VCAP_KF_ARP_OPCODE]                     =  "ARP_OPCODE", @@ -1498,32 +2792,57 @@ static const char * const vcap_keyfield_names[] = {  	[VCAP_KF_ARP_PROTO_SPACE_OK_IS]          =  "ARP_PROTO_SPACE_OK_IS",  	[VCAP_KF_ARP_SENDER_MATCH_IS]            =  "ARP_SENDER_MATCH_IS",  	[VCAP_KF_ARP_TGT_MATCH_IS]               =  "ARP_TGT_MATCH_IS", +	[VCAP_KF_COSID_CLS]                      =  "COSID_CLS", +	[VCAP_KF_ES0_ISDX_KEY_ENA]               =  "ES0_ISDX_KEY_ENA",  	[VCAP_KF_ETYPE]                          =  "ETYPE", +	[VCAP_KF_ETYPE_LEN_IS]                   =  "ETYPE_LEN_IS",  	[VCAP_KF_HOST_MATCH]                     =  "HOST_MATCH", +	[VCAP_KF_IF_EGR_PORT_MASK]               =  "IF_EGR_PORT_MASK", +	[VCAP_KF_IF_EGR_PORT_MASK_RNG]           =  "IF_EGR_PORT_MASK_RNG",  	[VCAP_KF_IF_IGR_PORT]                    =  "IF_IGR_PORT",  	[VCAP_KF_IF_IGR_PORT_MASK]               =  "IF_IGR_PORT_MASK", +	[VCAP_KF_IF_IGR_PORT_MASK_L3]            =  "IF_IGR_PORT_MASK_L3", +	[VCAP_KF_IF_IGR_PORT_MASK_RNG]           =  "IF_IGR_PORT_MASK_RNG", +	[VCAP_KF_IF_IGR_PORT_MASK_SEL]           =  "IF_IGR_PORT_MASK_SEL", +	[VCAP_KF_IF_IGR_PORT_SEL]                =  "IF_IGR_PORT_SEL",  	[VCAP_KF_IP4_IS]                         =  "IP4_IS", +	[VCAP_KF_IP_MC_IS]                       =  "IP_MC_IS", +	[VCAP_KF_IP_PAYLOAD_5TUPLE]              =  "IP_PAYLOAD_5TUPLE", +	[VCAP_KF_IP_PAYLOAD_S1_IP6]              =  "IP_PAYLOAD_S1_IP6", +	[VCAP_KF_IP_SNAP_IS]                     =  "IP_SNAP_IS", +	[VCAP_KF_ISDX_CLS]                       =  "ISDX_CLS",  	[VCAP_KF_ISDX_GT0_IS]                    =  "ISDX_GT0_IS",  	[VCAP_KF_L2_BC_IS]                       =  "L2_BC_IS",  	[VCAP_KF_L2_DMAC]                        =  "L2_DMAC",  	[VCAP_KF_L2_FRM_TYPE]                    =  "L2_FRM_TYPE", +	[VCAP_KF_L2_FWD_IS]                      =  "L2_FWD_IS",  	[VCAP_KF_L2_LLC]                         =  "L2_LLC", +	[VCAP_KF_L2_MAC]                         =  "L2_MAC",  	[VCAP_KF_L2_MC_IS]                       =  "L2_MC_IS",  	[VCAP_KF_L2_PAYLOAD0]                    =  "L2_PAYLOAD0",  	[VCAP_KF_L2_PAYLOAD1]                    =  "L2_PAYLOAD1",  	[VCAP_KF_L2_PAYLOAD2]                    =  "L2_PAYLOAD2", +	[VCAP_KF_L2_PAYLOAD_ETYPE]               =  "L2_PAYLOAD_ETYPE",  	[VCAP_KF_L2_SMAC]                        =  "L2_SMAC",  	[VCAP_KF_L2_SNAP]                        =  "L2_SNAP",  	[VCAP_KF_L3_DIP_EQ_SIP_IS]               =  "L3_DIP_EQ_SIP_IS", +	[VCAP_KF_L3_DPL_CLS]                     =  "L3_DPL_CLS", +	[VCAP_KF_L3_DSCP]                        =  "L3_DSCP", +	[VCAP_KF_L3_DST_IS]                      =  "L3_DST_IS",  	[VCAP_KF_L3_FRAGMENT]                    =  "L3_FRAGMENT", +	[VCAP_KF_L3_FRAGMENT_TYPE]               =  "L3_FRAGMENT_TYPE", +	[VCAP_KF_L3_FRAG_INVLD_L4_LEN]           =  "L3_FRAG_INVLD_L4_LEN",  	[VCAP_KF_L3_FRAG_OFS_GT0]                =  "L3_FRAG_OFS_GT0",  	[VCAP_KF_L3_IP4_DIP]                     =  "L3_IP4_DIP",  	[VCAP_KF_L3_IP4_SIP]                     =  "L3_IP4_SIP",  	[VCAP_KF_L3_IP6_DIP]                     =  "L3_IP6_DIP", +	[VCAP_KF_L3_IP6_DIP_MSB]                 =  "L3_IP6_DIP_MSB",  	[VCAP_KF_L3_IP6_SIP]                     =  "L3_IP6_SIP", +	[VCAP_KF_L3_IP6_SIP_MSB]                 =  "L3_IP6_SIP_MSB",  	[VCAP_KF_L3_IP_PROTO]                    =  "L3_IP_PROTO",  	[VCAP_KF_L3_OPTIONS_IS]                  =  "L3_OPTIONS_IS",  	[VCAP_KF_L3_PAYLOAD]                     =  "L3_PAYLOAD", +	[VCAP_KF_L3_RT_IS]                       =  "L3_RT_IS",  	[VCAP_KF_L3_TOS]                         =  "L3_TOS",  	[VCAP_KF_L3_TTL_GT0]                     =  "L3_TTL_GT0",  	[VCAP_KF_L4_1588_DOM]                    =  "L4_1588_DOM", @@ -1531,6 +2850,7 @@ static const char * const vcap_keyfield_names[] = {  	[VCAP_KF_L4_ACK]                         =  "L4_ACK",  	[VCAP_KF_L4_DPORT]                       =  "L4_DPORT",  	[VCAP_KF_L4_FIN]                         =  "L4_FIN", +	[VCAP_KF_L4_PAYLOAD]                     =  "L4_PAYLOAD",  	[VCAP_KF_L4_PSH]                         =  "L4_PSH",  	[VCAP_KF_L4_RNG]                         =  "L4_RNG",  	[VCAP_KF_L4_RST]                         =  "L4_RST", @@ -1540,7 +2860,11 @@ static const char * const vcap_keyfield_names[] = {  	[VCAP_KF_L4_SYN]                         =  "L4_SYN",  	[VCAP_KF_L4_URG]                         =  "L4_URG",  	[VCAP_KF_LOOKUP_FIRST_IS]                =  "LOOKUP_FIRST_IS", +	[VCAP_KF_LOOKUP_GEN_IDX]                 =  "LOOKUP_GEN_IDX", +	[VCAP_KF_LOOKUP_GEN_IDX_SEL]             =  "LOOKUP_GEN_IDX_SEL", +	[VCAP_KF_LOOKUP_INDEX]                   =  "LOOKUP_INDEX",  	[VCAP_KF_LOOKUP_PAG]                     =  "LOOKUP_PAG", +	[VCAP_KF_MIRROR_PROBE]                   =  "MIRROR_PROBE",  	[VCAP_KF_OAM_CCM_CNTS_EQ0]               =  "OAM_CCM_CNTS_EQ0",  	[VCAP_KF_OAM_DETECTED]                   =  "OAM_DETECTED",  	[VCAP_KF_OAM_FLAGS]                      =  "OAM_FLAGS", @@ -1549,7 +2873,12 @@ static const char * const vcap_keyfield_names[] = {  	[VCAP_KF_OAM_OPCODE]                     =  "OAM_OPCODE",  	[VCAP_KF_OAM_VER]                        =  "OAM_VER",  	[VCAP_KF_OAM_Y1731_IS]                   =  "OAM_Y1731_IS", +	[VCAP_KF_PROT_ACTIVE]                    =  "PROT_ACTIVE", +	[VCAP_KF_RT_FRMID]                       =  "RT_FRMID", +	[VCAP_KF_RT_TYPE]                        =  "RT_TYPE", +	[VCAP_KF_RT_VLAN_IDX]                    =  "RT_VLAN_IDX",  	[VCAP_KF_TCP_IS]                         =  "TCP_IS", +	[VCAP_KF_TCP_UDP_IS]                     =  "TCP_UDP_IS",  	[VCAP_KF_TYPE]                           =  "TYPE",  }; @@ -1557,24 +2886,95 @@ static const char * const vcap_keyfield_names[] = {  static const char * const vcap_actionfield_names[] = {  	[VCAP_AF_NO_VALUE]                       =  "(None)",  	[VCAP_AF_ACL_ID]                         =  "ACL_ID", +	[VCAP_AF_CLS_VID_SEL]                    =  "CLS_VID_SEL", +	[VCAP_AF_CNT_ID]                         =  "CNT_ID", +	[VCAP_AF_COPY_PORT_NUM]                  =  "COPY_PORT_NUM", +	[VCAP_AF_COPY_QUEUE_NUM]                 =  "COPY_QUEUE_NUM",  	[VCAP_AF_CPU_COPY_ENA]                   =  "CPU_COPY_ENA",  	[VCAP_AF_CPU_QUEUE_NUM]                  =  "CPU_QUEUE_NUM", +	[VCAP_AF_CUSTOM_ACE_TYPE_ENA]            =  "CUSTOM_ACE_TYPE_ENA", +	[VCAP_AF_DEI_ENA]                        =  "DEI_ENA", +	[VCAP_AF_DEI_VAL]                        =  "DEI_VAL", +	[VCAP_AF_DLR_SEL]                        =  "DLR_SEL", +	[VCAP_AF_DP_ENA]                         =  "DP_ENA", +	[VCAP_AF_DP_VAL]                         =  "DP_VAL", +	[VCAP_AF_DSCP_ENA]                       =  "DSCP_ENA", +	[VCAP_AF_DSCP_VAL]                       =  "DSCP_VAL", +	[VCAP_AF_ES2_REW_CMD]                    =  "ES2_REW_CMD",  	[VCAP_AF_FWD_KILL_ENA]                   =  "FWD_KILL_ENA", +	[VCAP_AF_FWD_MODE]                       =  "FWD_MODE",  	[VCAP_AF_HIT_ME_ONCE]                    =  "HIT_ME_ONCE",  	[VCAP_AF_HOST_MATCH]                     =  "HOST_MATCH", +	[VCAP_AF_IGNORE_PIPELINE_CTRL]           =  "IGNORE_PIPELINE_CTRL", +	[VCAP_AF_INTR_ENA]                       =  "INTR_ENA", +	[VCAP_AF_ISDX_ADD_REPLACE_SEL]           =  "ISDX_ADD_REPLACE_SEL", +	[VCAP_AF_ISDX_ADD_VAL]                   =  "ISDX_ADD_VAL",  	[VCAP_AF_ISDX_ENA]                       =  "ISDX_ENA", +	[VCAP_AF_ISDX_REPLACE_ENA]               =  "ISDX_REPLACE_ENA", +	[VCAP_AF_ISDX_VAL]                       =  "ISDX_VAL",  	[VCAP_AF_LRN_DIS]                        =  "LRN_DIS", +	[VCAP_AF_MAP_IDX]                        =  "MAP_IDX", +	[VCAP_AF_MAP_KEY]                        =  "MAP_KEY", +	[VCAP_AF_MAP_LOOKUP_SEL]                 =  "MAP_LOOKUP_SEL",  	[VCAP_AF_MASK_MODE]                      =  "MASK_MODE", +	[VCAP_AF_MATCH_ID]                       =  "MATCH_ID", +	[VCAP_AF_MATCH_ID_MASK]                  =  "MATCH_ID_MASK",  	[VCAP_AF_MIRROR_ENA]                     =  "MIRROR_ENA", +	[VCAP_AF_MIRROR_PROBE]                   =  "MIRROR_PROBE", +	[VCAP_AF_MIRROR_PROBE_ID]                =  "MIRROR_PROBE_ID", +	[VCAP_AF_MRP_SEL]                        =  "MRP_SEL", +	[VCAP_AF_NXT_IDX]                        =  "NXT_IDX", +	[VCAP_AF_NXT_IDX_CTRL]                   =  "NXT_IDX_CTRL", +	[VCAP_AF_OAM_SEL]                        =  "OAM_SEL", +	[VCAP_AF_PAG_OVERRIDE_MASK]              =  "PAG_OVERRIDE_MASK", +	[VCAP_AF_PAG_VAL]                        =  "PAG_VAL", +	[VCAP_AF_PCP_ENA]                        =  "PCP_ENA", +	[VCAP_AF_PCP_VAL]                        =  "PCP_VAL", +	[VCAP_AF_PIPELINE_FORCE_ENA]             =  "PIPELINE_FORCE_ENA", +	[VCAP_AF_PIPELINE_PT]                    =  "PIPELINE_PT",  	[VCAP_AF_POLICE_ENA]                     =  "POLICE_ENA",  	[VCAP_AF_POLICE_IDX]                     =  "POLICE_IDX", +	[VCAP_AF_POLICE_REMARK]                  =  "POLICE_REMARK",  	[VCAP_AF_POLICE_VCAP_ONLY]               =  "POLICE_VCAP_ONLY",  	[VCAP_AF_PORT_MASK]                      =  "PORT_MASK", +	[VCAP_AF_QOS_ENA]                        =  "QOS_ENA", +	[VCAP_AF_QOS_VAL]                        =  "QOS_VAL",  	[VCAP_AF_REW_OP]                         =  "REW_OP", +	[VCAP_AF_RT_DIS]                         =  "RT_DIS", +	[VCAP_AF_SFID_ENA]                       =  "SFID_ENA", +	[VCAP_AF_SFID_VAL]                       =  "SFID_VAL", +	[VCAP_AF_SGID_ENA]                       =  "SGID_ENA", +	[VCAP_AF_SGID_VAL]                       =  "SGID_VAL", +	[VCAP_AF_TYPE]                           =  "TYPE", +	[VCAP_AF_VID_REPLACE_ENA]                =  "VID_REPLACE_ENA", +	[VCAP_AF_VID_VAL]                        =  "VID_VAL", +	[VCAP_AF_VLAN_POP_CNT]                   =  "VLAN_POP_CNT", +	[VCAP_AF_VLAN_POP_CNT_ENA]               =  "VLAN_POP_CNT_ENA",  };  /* VCAPs */  const struct vcap_info lan966x_vcaps[] = { +	[VCAP_TYPE_IS1] = { +		.name = "is1", +		.rows = 192, +		.sw_count = 4, +		.sw_width = 96, +		.sticky_width = 32, +		.act_width = 123, +		.default_cnt = 0, +		.require_cnt_dis = 1, +		.version = 1, +		.keyfield_set = is1_keyfield_set, +		.keyfield_set_size = ARRAY_SIZE(is1_keyfield_set), +		.actionfield_set = is1_actionfield_set, +		.actionfield_set_size = ARRAY_SIZE(is1_actionfield_set), +		.keyfield_set_map = is1_keyfield_set_map, +		.keyfield_set_map_size = is1_keyfield_set_map_size, +		.actionfield_set_map = is1_actionfield_set_map, +		.actionfield_set_map_size = is1_actionfield_set_map_size, +		.keyfield_set_typegroups = is1_keyfield_set_typegroups, +		.actionfield_set_typegroups = is1_actionfield_set_typegroups, +	},  	[VCAP_TYPE_IS2] = {  		.name = "is2",  		.rows = 64, @@ -1600,7 +3000,7 @@ const struct vcap_info lan966x_vcaps[] = {  const struct vcap_statistics lan966x_vcap_stats = {  	.name = "lan966x", -	.count = 1, +	.count = 2,  	.keyfield_set_names = vcap_keyfield_set_names,  	.actionfield_set_names = vcap_actionfield_set_names,  	.keyfield_names = vcap_keyfield_names, diff --git a/drivers/net/ethernet/microchip/lan966x/lan966x_vcap_debugfs.c b/drivers/net/ethernet/microchip/lan966x/lan966x_vcap_debugfs.c index 7a0db58f5513..d90c08cfcf14 100644 --- a/drivers/net/ethernet/microchip/lan966x/lan966x_vcap_debugfs.c +++ b/drivers/net/ethernet/microchip/lan966x/lan966x_vcap_debugfs.c @@ -5,9 +5,124 @@  #include "vcap_api.h"  #include "vcap_api_client.h" -static void lan966x_vcap_port_keys(struct lan966x_port *port, -				   struct vcap_admin *admin, -				   struct vcap_output_print *out) +static void lan966x_vcap_is1_port_keys(struct lan966x_port *port, +				       struct vcap_admin *admin, +				       struct vcap_output_print *out) +{ +	struct lan966x *lan966x = port->lan966x; +	u32 val; + +	out->prf(out->dst, "  port[%d] (%s): ", port->chip_port, +		 netdev_name(port->dev)); + +	val = lan_rd(lan966x, ANA_VCAP_CFG(port->chip_port)); +	out->prf(out->dst, "\n    state: "); +	if (ANA_VCAP_CFG_S1_ENA_GET(val)) +		out->prf(out->dst, "on"); +	else +		out->prf(out->dst, "off"); + +	for (int l = 0; l < admin->lookups; ++l) { +		out->prf(out->dst, "\n    Lookup %d: ", l); + +		out->prf(out->dst, "\n      other: "); +		switch (ANA_VCAP_S1_CFG_KEY_OTHER_CFG_GET(val)) { +		case VCAP_IS1_PS_OTHER_NORMAL: +			out->prf(out->dst, "normal"); +			break; +		case VCAP_IS1_PS_OTHER_7TUPLE: +			out->prf(out->dst, "7tuple"); +			break; +		case VCAP_IS1_PS_OTHER_DBL_VID: +			out->prf(out->dst, "dbl_vid"); +			break; +		case VCAP_IS1_PS_OTHER_DMAC_VID: +			out->prf(out->dst, "dmac_vid"); +			break; +		default: +			out->prf(out->dst, "-"); +			break; +		} + +		out->prf(out->dst, "\n      ipv4: "); +		switch (ANA_VCAP_S1_CFG_KEY_IP4_CFG_GET(val)) { +		case VCAP_IS1_PS_IPV4_NORMAL: +			out->prf(out->dst, "normal"); +			break; +		case VCAP_IS1_PS_IPV4_7TUPLE: +			out->prf(out->dst, "7tuple"); +			break; +		case VCAP_IS1_PS_IPV4_5TUPLE_IP4: +			out->prf(out->dst, "5tuple_ipv4"); +			break; +		case VCAP_IS1_PS_IPV4_DBL_VID: +			out->prf(out->dst, "dbl_vid"); +			break; +		case VCAP_IS1_PS_IPV4_DMAC_VID: +			out->prf(out->dst, "dmac_vid"); +			break; +		default: +			out->prf(out->dst, "-"); +			break; +		} + +		out->prf(out->dst, "\n      ipv6: "); +		switch (ANA_VCAP_S1_CFG_KEY_IP6_CFG_GET(val)) { +		case VCAP_IS1_PS_IPV6_NORMAL: +			out->prf(out->dst, "normal"); +			break; +		case VCAP_IS1_PS_IPV6_7TUPLE: +			out->prf(out->dst, "7tuple"); +			break; +		case VCAP_IS1_PS_IPV6_5TUPLE_IP4: +			out->prf(out->dst, "5tuple_ip4"); +			break; +		case VCAP_IS1_PS_IPV6_NORMAL_IP6: +			out->prf(out->dst, "normal_ip6"); +			break; +		case VCAP_IS1_PS_IPV6_5TUPLE_IP6: +			out->prf(out->dst, "5tuple_ip6"); +			break; +		case VCAP_IS1_PS_IPV6_DBL_VID: +			out->prf(out->dst, "dbl_vid"); +			break; +		case VCAP_IS1_PS_IPV6_DMAC_VID: +			out->prf(out->dst, "dmac_vid"); +			break; +		default: +			out->prf(out->dst, "-"); +			break; +		} + +		out->prf(out->dst, "\n      rt: "); +		switch (ANA_VCAP_S1_CFG_KEY_RT_CFG_GET(val)) { +		case VCAP_IS1_PS_RT_NORMAL: +			out->prf(out->dst, "normal"); +			break; +		case VCAP_IS1_PS_RT_7TUPLE: +			out->prf(out->dst, "7tuple"); +			break; +		case VCAP_IS1_PS_RT_DBL_VID: +			out->prf(out->dst, "dbl_vid"); +			break; +		case VCAP_IS1_PS_RT_DMAC_VID: +			out->prf(out->dst, "dmac_vid"); +			break; +		case VCAP_IS1_PS_RT_FOLLOW_OTHER: +			out->prf(out->dst, "follow_other"); +			break; +		default: +			out->prf(out->dst, "-"); +			break; +		} +	} + +	out->prf(out->dst, "\n"); +} + +static void lan966x_vcap_is2_port_keys(struct lan966x_port *port, +				       struct vcap_admin *admin, +				       struct vcap_output_print *out)  {  	struct lan966x *lan966x = port->lan966x;  	u32 val; @@ -88,7 +203,17 @@ int lan966x_vcap_port_info(struct net_device *dev,  	vcap = &vctrl->vcaps[admin->vtype];  	out->prf(out->dst, "%s:\n", vcap->name); -	lan966x_vcap_port_keys(port, admin, out); +	switch (admin->vtype) { +	case VCAP_TYPE_IS2: +		lan966x_vcap_is2_port_keys(port, admin, out); +		break; +	case VCAP_TYPE_IS1: +		lan966x_vcap_is1_port_keys(port, admin, out); +		break; +	default: +		out->prf(out->dst, "  no info\n"); +		break; +	}  	return 0;  } diff --git a/drivers/net/ethernet/microchip/lan966x/lan966x_vcap_impl.c b/drivers/net/ethernet/microchip/lan966x/lan966x_vcap_impl.c index 68f9d69fd37b..7ea8e8633609 100644 --- a/drivers/net/ethernet/microchip/lan966x/lan966x_vcap_impl.c +++ b/drivers/net/ethernet/microchip/lan966x/lan966x_vcap_impl.c @@ -8,6 +8,7 @@  #define STREAMSIZE (64 * 4) +#define LAN966X_IS1_LOOKUPS 3  #define LAN966X_IS2_LOOKUPS 2  static struct lan966x_vcap_inst { @@ -20,6 +21,15 @@ static struct lan966x_vcap_inst {  	bool ingress; /* is vcap in the ingress path */  } lan966x_vcap_inst_cfg[] = {  	{ +		.vtype = VCAP_TYPE_IS1, /* IS1-0 */ +		.tgt_inst = 1, +		.lookups = LAN966X_IS1_LOOKUPS, +		.first_cid = LAN966X_VCAP_CID_IS1_L0, +		.last_cid = LAN966X_VCAP_CID_IS1_MAX, +		.count = 768, +		.ingress = true, +	}, +	{  		.vtype = VCAP_TYPE_IS2, /* IS2-0 */  		.tgt_inst = 2,  		.lookups = LAN966X_IS2_LOOKUPS, @@ -72,7 +82,21 @@ static void __lan966x_vcap_range_init(struct lan966x *lan966x,  	lan966x_vcap_wait_update(lan966x, admin->tgt_inst);  } -static int lan966x_vcap_cid_to_lookup(int cid) +static int lan966x_vcap_is1_cid_to_lookup(int cid) +{ +	int lookup = 0; + +	if (cid >= LAN966X_VCAP_CID_IS1_L1 && +	    cid < LAN966X_VCAP_CID_IS1_L2) +		lookup = 1; +	else if (cid >= LAN966X_VCAP_CID_IS1_L2 && +		 cid < LAN966X_VCAP_CID_IS1_MAX) +		lookup = 2; + +	return lookup; +} + +static int lan966x_vcap_is2_cid_to_lookup(int cid)  {  	if (cid >= LAN966X_VCAP_CID_IS2_L1 &&  	    cid < LAN966X_VCAP_CID_IS2_MAX) @@ -81,6 +105,67 @@ static int lan966x_vcap_cid_to_lookup(int cid)  	return 0;  } +/* Return the list of keysets for the vcap port configuration */ +static int +lan966x_vcap_is1_get_port_keysets(struct net_device *ndev, int lookup, +				  struct vcap_keyset_list *keysetlist, +				  u16 l3_proto) +{ +	struct lan966x_port *port = netdev_priv(ndev); +	struct lan966x *lan966x = port->lan966x; +	u32 val; + +	val = lan_rd(lan966x, ANA_VCAP_S1_CFG(port->chip_port, lookup)); + +	/* Collect all keysets for the port in a list */ +	if (l3_proto == ETH_P_ALL || l3_proto == ETH_P_IP) { +		switch (ANA_VCAP_S1_CFG_KEY_IP4_CFG_GET(val)) { +		case VCAP_IS1_PS_IPV4_7TUPLE: +			vcap_keyset_list_add(keysetlist, VCAP_KFS_7TUPLE); +			break; +		case VCAP_IS1_PS_IPV4_5TUPLE_IP4: +			vcap_keyset_list_add(keysetlist, VCAP_KFS_5TUPLE_IP4); +			break; +		case VCAP_IS1_PS_IPV4_NORMAL: +			vcap_keyset_list_add(keysetlist, VCAP_KFS_NORMAL); +			break; +		} +	} + +	if (l3_proto == ETH_P_ALL || l3_proto == ETH_P_IPV6) { +		switch (ANA_VCAP_S1_CFG_KEY_IP6_CFG_GET(val)) { +		case VCAP_IS1_PS_IPV6_NORMAL: +		case VCAP_IS1_PS_IPV6_NORMAL_IP6: +			vcap_keyset_list_add(keysetlist, VCAP_KFS_NORMAL); +			vcap_keyset_list_add(keysetlist, VCAP_KFS_NORMAL_IP6); +			break; +		case VCAP_IS1_PS_IPV6_5TUPLE_IP6: +			vcap_keyset_list_add(keysetlist, VCAP_KFS_5TUPLE_IP6); +			break; +		case VCAP_IS1_PS_IPV6_7TUPLE: +			vcap_keyset_list_add(keysetlist, VCAP_KFS_7TUPLE); +			break; +		case VCAP_IS1_PS_IPV6_5TUPLE_IP4: +			vcap_keyset_list_add(keysetlist, VCAP_KFS_5TUPLE_IP4); +			break; +		case VCAP_IS1_PS_IPV6_DMAC_VID: +			vcap_keyset_list_add(keysetlist, VCAP_KFS_DMAC_VID); +			break; +		} +	} + +	switch (ANA_VCAP_S1_CFG_KEY_OTHER_CFG_GET(val)) { +	case VCAP_IS1_PS_OTHER_7TUPLE: +		vcap_keyset_list_add(keysetlist, VCAP_KFS_7TUPLE); +		break; +	case VCAP_IS1_PS_OTHER_NORMAL: +		vcap_keyset_list_add(keysetlist, VCAP_KFS_NORMAL); +		break; +	} + +	return 0; +} +  static int  lan966x_vcap_is2_get_port_keysets(struct net_device *dev, int lookup,  				  struct vcap_keyset_list *keysetlist, @@ -180,11 +265,26 @@ lan966x_vcap_validate_keyset(struct net_device *dev,  	if (!kslist || kslist->cnt == 0)  		return VCAP_KFS_NO_VALUE; -	lookup = lan966x_vcap_cid_to_lookup(rule->vcap_chain_id);  	keysetlist.max = ARRAY_SIZE(keysets);  	keysetlist.keysets = keysets; -	err = lan966x_vcap_is2_get_port_keysets(dev, lookup, &keysetlist, -						l3_proto); + +	switch (admin->vtype) { +	case VCAP_TYPE_IS1: +		lookup = lan966x_vcap_is1_cid_to_lookup(rule->vcap_chain_id); +		err = lan966x_vcap_is1_get_port_keysets(dev, lookup, &keysetlist, +							l3_proto); +		break; +	case VCAP_TYPE_IS2: +		lookup = lan966x_vcap_is2_cid_to_lookup(rule->vcap_chain_id); +		err = lan966x_vcap_is2_get_port_keysets(dev, lookup, &keysetlist, +							l3_proto); +		break; +	default: +		pr_err("vcap type: %s not supported\n", +		       lan966x_vcaps[admin->vtype].name); +		return VCAP_KFS_NO_VALUE; +	} +  	if (err)  		return VCAP_KFS_NO_VALUE; @@ -197,17 +297,32 @@ lan966x_vcap_validate_keyset(struct net_device *dev,  	return VCAP_KFS_NO_VALUE;  } -static bool lan966x_vcap_is_first_chain(struct vcap_rule *rule) +static bool lan966x_vcap_is2_is_first_chain(struct vcap_rule *rule)  {  	return (rule->vcap_chain_id >= LAN966X_VCAP_CID_IS2_L0 &&  		rule->vcap_chain_id < LAN966X_VCAP_CID_IS2_L1);  } -static void lan966x_vcap_add_default_fields(struct net_device *dev, -					    struct vcap_admin *admin, -					    struct vcap_rule *rule) +static void lan966x_vcap_is1_add_default_fields(struct lan966x_port *port, +						struct vcap_admin *admin, +						struct vcap_rule *rule) +{ +	u32 value, mask; +	u32 lookup; + +	if (vcap_rule_get_key_u32(rule, VCAP_KF_IF_IGR_PORT_MASK, +				  &value, &mask)) +		vcap_rule_add_key_u32(rule, VCAP_KF_IF_IGR_PORT_MASK, 0, +				      ~BIT(port->chip_port)); + +	lookup = lan966x_vcap_is1_cid_to_lookup(rule->vcap_chain_id); +	vcap_rule_add_key_u32(rule, VCAP_KF_LOOKUP_INDEX, lookup, 0x3); +} + +static void lan966x_vcap_is2_add_default_fields(struct lan966x_port *port, +						struct vcap_admin *admin, +						struct vcap_rule *rule)  { -	struct lan966x_port *port = netdev_priv(dev);  	u32 value, mask;  	if (vcap_rule_get_key_u32(rule, VCAP_KF_IF_IGR_PORT_MASK, @@ -215,7 +330,7 @@ static void lan966x_vcap_add_default_fields(struct net_device *dev,  		vcap_rule_add_key_u32(rule, VCAP_KF_IF_IGR_PORT_MASK, 0,  				      ~BIT(port->chip_port)); -	if (lan966x_vcap_is_first_chain(rule)) +	if (lan966x_vcap_is2_is_first_chain(rule))  		vcap_rule_add_key_bit(rule, VCAP_KF_LOOKUP_FIRST_IS,  				      VCAP_BIT_1);  	else @@ -223,6 +338,26 @@ static void lan966x_vcap_add_default_fields(struct net_device *dev,  				      VCAP_BIT_0);  } +static void lan966x_vcap_add_default_fields(struct net_device *dev, +					    struct vcap_admin *admin, +					    struct vcap_rule *rule) +{ +	struct lan966x_port *port = netdev_priv(dev); + +	switch (admin->vtype) { +	case VCAP_TYPE_IS1: +		lan966x_vcap_is1_add_default_fields(port, admin, rule); +		break; +	case VCAP_TYPE_IS2: +		lan966x_vcap_is2_add_default_fields(port, admin, rule); +		break; +	default: +		pr_err("vcap type: %s not supported\n", +		       lan966x_vcaps[admin->vtype].name); +		break; +	} +} +  static void lan966x_vcap_cache_erase(struct vcap_admin *admin)  {  	memset(admin->cache.keystream, 0, STREAMSIZE); @@ -464,8 +599,37 @@ static void lan966x_vcap_block_init(struct lan966x *lan966x,  static void lan966x_vcap_port_key_deselection(struct lan966x *lan966x,  					      struct vcap_admin *admin)  { -	for (int p = 0; p < lan966x->num_phys_ports; ++p) -		lan_wr(0, lan966x, ANA_VCAP_S2_CFG(p)); +	u32 val; + +	switch (admin->vtype) { +	case VCAP_TYPE_IS1: +		val = ANA_VCAP_S1_CFG_KEY_IP6_CFG_SET(VCAP_IS1_PS_IPV6_5TUPLE_IP6) | +		      ANA_VCAP_S1_CFG_KEY_IP4_CFG_SET(VCAP_IS1_PS_IPV4_5TUPLE_IP4) | +		      ANA_VCAP_S1_CFG_KEY_OTHER_CFG_SET(VCAP_IS1_PS_OTHER_NORMAL); + +		for (int p = 0; p < lan966x->num_phys_ports; ++p) { +			if (!lan966x->ports[p]) +				continue; + +			for (int l = 0; l < LAN966X_IS1_LOOKUPS; ++l) +				lan_wr(val, lan966x, ANA_VCAP_S1_CFG(p, l)); + +			lan_rmw(ANA_VCAP_CFG_S1_ENA_SET(true), +				ANA_VCAP_CFG_S1_ENA, lan966x, +				ANA_VCAP_CFG(p)); +		} + +		break; +	case VCAP_TYPE_IS2: +		for (int p = 0; p < lan966x->num_phys_ports; ++p) +			lan_wr(0, lan966x, ANA_VCAP_S2_CFG(p)); + +		break; +	default: +		pr_err("vcap type: %s not supported\n", +		       lan966x_vcaps[admin->vtype].name); +		break; +	}  }  int lan966x_vcap_init(struct lan966x *lan966x) @@ -506,6 +670,10 @@ int lan966x_vcap_init(struct lan966x *lan966x)  			lan_rmw(ANA_VCAP_S2_CFG_ENA_SET(true),  				ANA_VCAP_S2_CFG_ENA, lan966x,  				ANA_VCAP_S2_CFG(lan966x->ports[p]->chip_port)); + +			lan_rmw(ANA_VCAP_CFG_S1_ENA_SET(true), +				ANA_VCAP_CFG_S1_ENA, lan966x, +				ANA_VCAP_CFG(lan966x->ports[p]->chip_port));  		}  	} diff --git a/drivers/net/ethernet/microchip/lan966x/lan966x_xdp.c b/drivers/net/ethernet/microchip/lan966x/lan966x_xdp.c index 2e6f486ec67d..9ee61db8690b 100644 --- a/drivers/net/ethernet/microchip/lan966x/lan966x_xdp.c +++ b/drivers/net/ethernet/microchip/lan966x/lan966x_xdp.c @@ -62,7 +62,7 @@ int lan966x_xdp_xmit(struct net_device *dev,  		struct xdp_frame *xdpf = frames[i];  		int err; -		err = lan966x_fdma_xmit_xdpf(port, xdpf, NULL, true); +		err = lan966x_fdma_xmit_xdpf(port, xdpf, 0);  		if (err)  			break; @@ -76,7 +76,6 @@ int lan966x_xdp_run(struct lan966x_port *port, struct page *page, u32 data_len)  {  	struct bpf_prog *xdp_prog = port->xdp_prog;  	struct lan966x *lan966x = port->lan966x; -	struct xdp_frame *xdpf;  	struct xdp_buff xdp;  	u32 act; @@ -90,11 +89,8 @@ int lan966x_xdp_run(struct lan966x_port *port, struct page *page, u32 data_len)  	case XDP_PASS:  		return FDMA_PASS;  	case XDP_TX: -		xdpf = xdp_convert_buff_to_frame(&xdp); -		if (!xdpf) -			return FDMA_DROP; - -		return lan966x_fdma_xmit_xdpf(port, xdpf, page, false) ? +		return lan966x_fdma_xmit_xdpf(port, page, +					      data_len - IFH_LEN_BYTES) ?  		       FDMA_DROP : FDMA_TX;  	case XDP_REDIRECT:  		if (xdp_do_redirect(port->dev, &xdp, xdp_prog)) diff --git a/drivers/net/ethernet/microchip/sparx5/sparx5_main.c b/drivers/net/ethernet/microchip/sparx5/sparx5_main.c index 42b77ba9b572..a7edf524eedb 100644 --- a/drivers/net/ethernet/microchip/sparx5/sparx5_main.c +++ b/drivers/net/ethernet/microchip/sparx5/sparx5_main.c @@ -282,6 +282,7 @@ static int sparx5_create_port(struct sparx5 *sparx5,  	spx5_port->phylink_pcs.poll = true;  	spx5_port->phylink_pcs.ops = &sparx5_phylink_pcs_ops;  	spx5_port->is_mrouter = false; +	INIT_LIST_HEAD(&spx5_port->tc_templates);  	sparx5->ports[config->portno] = spx5_port;  	err = sparx5_port_init(sparx5, spx5_port, &config->conf); diff --git a/drivers/net/ethernet/microchip/sparx5/sparx5_main.h b/drivers/net/ethernet/microchip/sparx5/sparx5_main.h index 72e7928912eb..62c85463b634 100644 --- a/drivers/net/ethernet/microchip/sparx5/sparx5_main.h +++ b/drivers/net/ethernet/microchip/sparx5/sparx5_main.h @@ -192,6 +192,7 @@ struct sparx5_port {  	u16 ts_id;  	struct sk_buff_head tx_skbs;  	bool is_mrouter; +	struct list_head tc_templates; /* list of TC templates on this port */  };  enum sparx5_core_clockfreq { diff --git a/drivers/net/ethernet/microchip/sparx5/sparx5_tc_flower.c b/drivers/net/ethernet/microchip/sparx5/sparx5_tc_flower.c index b36819aafaca..3f87a5285a6d 100644 --- a/drivers/net/ethernet/microchip/sparx5/sparx5_tc_flower.c +++ b/drivers/net/ethernet/microchip/sparx5/sparx5_tc_flower.c @@ -28,6 +28,14 @@ struct sparx5_multiple_rules {  	struct sparx5_wildcard_rule rule[SPX5_MAX_RULE_SIZE];  }; +struct sparx5_tc_flower_template { +	struct list_head list; /* for insertion in the list of templates */ +	int cid; /* chain id */ +	enum vcap_keyfield_set orig; /* keyset used before the template */ +	enum vcap_keyfield_set keyset; /* new keyset used by template */ +	u16 l3_proto; /* protocol specified in the template */ +}; +  static int  sparx5_tc_flower_es0_tpid(struct vcap_tc_flower_parse_usage *st)  { @@ -382,7 +390,7 @@ static int sparx5_tc_select_protocol_keyset(struct net_device *ndev,  	/* Find the keysets that the rule can use */  	matches.keysets = keysets;  	matches.max = ARRAY_SIZE(keysets); -	if (vcap_rule_find_keysets(vrule, &matches) == 0) +	if (!vcap_rule_find_keysets(vrule, &matches))  		return -EINVAL;  	/* Find the keysets that the port configuration supports */ @@ -996,6 +1004,73 @@ static int sparx5_tc_action_vlan_push(struct vcap_admin *admin,  	return err;  } +/* Remove rule keys that may prevent templates from matching a keyset */ +static void sparx5_tc_flower_simplify_rule(struct vcap_admin *admin, +					   struct vcap_rule *vrule, +					   u16 l3_proto) +{ +	switch (admin->vtype) { +	case VCAP_TYPE_IS0: +		vcap_rule_rem_key(vrule, VCAP_KF_ETYPE); +		switch (l3_proto) { +		case ETH_P_IP: +			break; +		case ETH_P_IPV6: +			vcap_rule_rem_key(vrule, VCAP_KF_IP_SNAP_IS); +			break; +		default: +			break; +		} +		break; +	case VCAP_TYPE_ES2: +		switch (l3_proto) { +		case ETH_P_IP: +			if (vrule->keyset == VCAP_KFS_IP4_OTHER) +				vcap_rule_rem_key(vrule, VCAP_KF_TCP_IS); +			break; +		case ETH_P_IPV6: +			if (vrule->keyset == VCAP_KFS_IP6_STD) +				vcap_rule_rem_key(vrule, VCAP_KF_TCP_IS); +			vcap_rule_rem_key(vrule, VCAP_KF_IP4_IS); +			break; +		default: +			break; +		} +		break; +	case VCAP_TYPE_IS2: +		switch (l3_proto) { +		case ETH_P_IP: +		case ETH_P_IPV6: +			vcap_rule_rem_key(vrule, VCAP_KF_IP4_IS); +			break; +		default: +			break; +		} +		break; +	default: +		break; +	} +} + +static bool sparx5_tc_flower_use_template(struct net_device *ndev, +					  struct flow_cls_offload *fco, +					  struct vcap_admin *admin, +					  struct vcap_rule *vrule) +{ +	struct sparx5_port *port = netdev_priv(ndev); +	struct sparx5_tc_flower_template *ftp; + +	list_for_each_entry(ftp, &port->tc_templates, list) { +		if (ftp->cid != fco->common.chain_index) +			continue; + +		vcap_set_rule_set_keyset(vrule, ftp->keyset); +		sparx5_tc_flower_simplify_rule(admin, vrule, ftp->l3_proto); +		return true; +	} +	return false; +} +  static int sparx5_tc_flower_replace(struct net_device *ndev,  				    struct flow_cls_offload *fco,  				    struct vcap_admin *admin, @@ -1122,12 +1197,14 @@ static int sparx5_tc_flower_replace(struct net_device *ndev,  			goto out;  	} -	err = sparx5_tc_select_protocol_keyset(ndev, vrule, admin, -					       state.l3_proto, &multi); -	if (err) { -		NL_SET_ERR_MSG_MOD(fco->common.extack, -				   "No matching port keyset for filter protocol and keys"); -		goto out; +	if (!sparx5_tc_flower_use_template(ndev, fco, admin, vrule)) { +		err = sparx5_tc_select_protocol_keyset(ndev, vrule, admin, +						       state.l3_proto, &multi); +		if (err) { +			NL_SET_ERR_MSG_MOD(fco->common.extack, +					   "No matching port keyset for filter protocol and keys"); +			goto out; +		}  	}  	/* provide the l3 protocol to guide the keyset selection */ @@ -1259,6 +1336,120 @@ static int sparx5_tc_flower_stats(struct net_device *ndev,  	return err;  } +static int sparx5_tc_flower_template_create(struct net_device *ndev, +					    struct flow_cls_offload *fco, +					    struct vcap_admin *admin) +{ +	struct sparx5_port *port = netdev_priv(ndev); +	struct vcap_tc_flower_parse_usage state = { +		.fco = fco, +		.l3_proto = ETH_P_ALL, +		.admin = admin, +	}; +	struct sparx5_tc_flower_template *ftp; +	struct vcap_keyset_list kslist = {}; +	enum vcap_keyfield_set keysets[10]; +	struct vcap_control *vctrl; +	struct vcap_rule *vrule; +	int count, err; + +	if (admin->vtype == VCAP_TYPE_ES0) { +		pr_err("%s:%d: %s\n", __func__, __LINE__, +		       "VCAP does not support templates"); +		return -EINVAL; +	} + +	count = vcap_admin_rule_count(admin, fco->common.chain_index); +	if (count > 0) { +		pr_err("%s:%d: %s\n", __func__, __LINE__, +		       "Filters are already present"); +		return -EBUSY; +	} + +	ftp = kzalloc(sizeof(*ftp), GFP_KERNEL); +	if (!ftp) +		return -ENOMEM; + +	ftp->cid = fco->common.chain_index; +	ftp->orig = VCAP_KFS_NO_VALUE; +	ftp->keyset = VCAP_KFS_NO_VALUE; + +	vctrl = port->sparx5->vcap_ctrl; +	vrule = vcap_alloc_rule(vctrl, ndev, fco->common.chain_index, +				VCAP_USER_TC, fco->common.prio, 0); +	if (IS_ERR(vrule)) { +		err = PTR_ERR(vrule); +		goto err_rule; +	} + +	state.vrule = vrule; +	state.frule = flow_cls_offload_flow_rule(fco); +	err = sparx5_tc_use_dissectors(&state, admin, vrule); +	if (err) { +		pr_err("%s:%d: key error: %d\n", __func__, __LINE__, err); +		goto out; +	} + +	ftp->l3_proto = state.l3_proto; + +	sparx5_tc_flower_simplify_rule(admin, vrule, state.l3_proto); + +	/* Find the keysets that the rule can use */ +	kslist.keysets = keysets; +	kslist.max = ARRAY_SIZE(keysets); +	if (!vcap_rule_find_keysets(vrule, &kslist)) { +		pr_err("%s:%d: %s\n", __func__, __LINE__, +		       "Could not find a suitable keyset"); +		err = -ENOENT; +		goto out; +	} + +	ftp->keyset = vcap_select_min_rule_keyset(vctrl, admin->vtype, &kslist); +	kslist.cnt = 0; +	sparx5_vcap_set_port_keyset(ndev, admin, fco->common.chain_index, +				    state.l3_proto, +				    ftp->keyset, +				    &kslist); + +	if (kslist.cnt > 0) +		ftp->orig = kslist.keysets[0]; + +	/* Store new template */ +	list_add_tail(&ftp->list, &port->tc_templates); +	vcap_free_rule(vrule); +	return 0; + +out: +	vcap_free_rule(vrule); +err_rule: +	kfree(ftp); +	return err; +} + +static int sparx5_tc_flower_template_destroy(struct net_device *ndev, +					     struct flow_cls_offload *fco, +					     struct vcap_admin *admin) +{ +	struct sparx5_port *port = netdev_priv(ndev); +	struct sparx5_tc_flower_template *ftp, *tmp; +	int err = -ENOENT; + +	/* Rules using the template are removed by the tc framework */ +	list_for_each_entry_safe(ftp, tmp, &port->tc_templates, list) { +		if (ftp->cid != fco->common.chain_index) +			continue; + +		sparx5_vcap_set_port_keyset(ndev, admin, +					    fco->common.chain_index, +					    ftp->l3_proto, ftp->orig, +					    NULL); +		list_del(&ftp->list); +		kfree(ftp); +		break; +	} +	return err; +} +  int sparx5_tc_flower(struct net_device *ndev, struct flow_cls_offload *fco,  		     bool ingress)  { @@ -1282,6 +1473,10 @@ int sparx5_tc_flower(struct net_device *ndev, struct flow_cls_offload *fco,  		return sparx5_tc_flower_destroy(ndev, fco, admin);  	case FLOW_CLS_STATS:  		return sparx5_tc_flower_stats(ndev, fco, admin); +	case FLOW_CLS_TMPLT_CREATE: +		return sparx5_tc_flower_template_create(ndev, fco, admin); +	case FLOW_CLS_TMPLT_DESTROY: +		return sparx5_tc_flower_template_destroy(ndev, fco, admin);  	default:  		return -EOPNOTSUPP;  	} diff --git a/drivers/net/ethernet/microchip/sparx5/sparx5_vcap_debugfs.c b/drivers/net/ethernet/microchip/sparx5/sparx5_vcap_debugfs.c index 07b472c84a47..12722f728ef7 100644 --- a/drivers/net/ethernet/microchip/sparx5/sparx5_vcap_debugfs.c +++ b/drivers/net/ethernet/microchip/sparx5/sparx5_vcap_debugfs.c @@ -198,7 +198,7 @@ static void sparx5_vcap_is2_port_keys(struct sparx5 *sparx5,  			out->prf(out->dst, "ip6_std");  			break;  		case VCAP_IS2_PS_IPV6_MC_IP4_TCP_UDP_OTHER: -			out->prf(out->dst, "ip4_tcp_udp ipv4_other"); +			out->prf(out->dst, "ip4_tcp_udp ip4_other");  			break;  		}  		out->prf(out->dst, "\n      ipv6_uc: "); diff --git a/drivers/net/ethernet/microchip/sparx5/sparx5_vcap_impl.c b/drivers/net/ethernet/microchip/sparx5/sparx5_vcap_impl.c index d0d4e0385ac7..187efa1fc904 100644 --- a/drivers/net/ethernet/microchip/sparx5/sparx5_vcap_impl.c +++ b/drivers/net/ethernet/microchip/sparx5/sparx5_vcap_impl.c @@ -1519,6 +1519,276 @@ static struct vcap_operations sparx5_vcap_ops = {  	.port_info = sparx5_port_info,  }; +static u32 sparx5_vcap_is0_keyset_to_etype_ps(enum vcap_keyfield_set keyset) +{ +	switch (keyset) { +	case VCAP_KFS_NORMAL_7TUPLE: +		return VCAP_IS0_PS_ETYPE_NORMAL_7TUPLE; +	case VCAP_KFS_NORMAL_5TUPLE_IP4: +		return VCAP_IS0_PS_ETYPE_NORMAL_5TUPLE_IP4; +	default: +		return VCAP_IS0_PS_ETYPE_NORMAL_7TUPLE; +	} +} + +static void sparx5_vcap_is0_set_port_keyset(struct net_device *ndev, int lookup, +					    enum vcap_keyfield_set keyset, +					    int l3_proto) +{ +	struct sparx5_port *port = netdev_priv(ndev); +	struct sparx5 *sparx5 = port->sparx5; +	int portno = port->portno; +	u32 value; + +	switch (l3_proto) { +	case ETH_P_IP: +		value = sparx5_vcap_is0_keyset_to_etype_ps(keyset); +		spx5_rmw(ANA_CL_ADV_CL_CFG_IP4_CLM_KEY_SEL_SET(value), +			 ANA_CL_ADV_CL_CFG_IP4_CLM_KEY_SEL, +			 sparx5, +			 ANA_CL_ADV_CL_CFG(portno, lookup)); +		break; +	case ETH_P_IPV6: +		value = sparx5_vcap_is0_keyset_to_etype_ps(keyset); +		spx5_rmw(ANA_CL_ADV_CL_CFG_IP6_CLM_KEY_SEL_SET(value), +			 ANA_CL_ADV_CL_CFG_IP6_CLM_KEY_SEL, +			 sparx5, +			 ANA_CL_ADV_CL_CFG(portno, lookup)); +		break; +	default: +		value = sparx5_vcap_is0_keyset_to_etype_ps(keyset); +		spx5_rmw(ANA_CL_ADV_CL_CFG_ETYPE_CLM_KEY_SEL_SET(value), +			 ANA_CL_ADV_CL_CFG_ETYPE_CLM_KEY_SEL, +			 sparx5, +			 ANA_CL_ADV_CL_CFG(portno, lookup)); +		break; +	} +} + +static u32 sparx5_vcap_is2_keyset_to_arp_ps(enum vcap_keyfield_set keyset) +{ +	switch (keyset) { +	case VCAP_KFS_ARP: +		return VCAP_IS2_PS_ARP_ARP; +	default: +		return VCAP_IS2_PS_ARP_MAC_ETYPE; +	} +} + +static u32 sparx5_vcap_is2_keyset_to_ipv4_ps(enum vcap_keyfield_set keyset) +{ +	switch (keyset) { +	case VCAP_KFS_MAC_ETYPE: +		return VCAP_IS2_PS_IPV4_UC_MAC_ETYPE; +	case VCAP_KFS_IP4_OTHER: +	case VCAP_KFS_IP4_TCP_UDP: +		return VCAP_IS2_PS_IPV4_UC_IP4_TCP_UDP_OTHER; +	case VCAP_KFS_IP_7TUPLE: +		return VCAP_IS2_PS_IPV4_UC_IP_7TUPLE; +	default: +		return VCAP_KFS_NO_VALUE; +	} +} + +static u32 sparx5_vcap_is2_keyset_to_ipv6_uc_ps(enum vcap_keyfield_set keyset) +{ +	switch (keyset) { +	case VCAP_KFS_MAC_ETYPE: +		return VCAP_IS2_PS_IPV6_UC_MAC_ETYPE; +	case VCAP_KFS_IP4_OTHER: +	case VCAP_KFS_IP4_TCP_UDP: +		return VCAP_IS2_PS_IPV6_UC_IP4_TCP_UDP_OTHER; +	case VCAP_KFS_IP_7TUPLE: +		return VCAP_IS2_PS_IPV6_UC_IP_7TUPLE; +	default: +		return VCAP_KFS_NO_VALUE; +	} +} + +static u32 sparx5_vcap_is2_keyset_to_ipv6_mc_ps(enum vcap_keyfield_set keyset) +{ +	switch (keyset) { +	case VCAP_KFS_MAC_ETYPE: +		return VCAP_IS2_PS_IPV6_MC_MAC_ETYPE; +	case VCAP_KFS_IP4_OTHER: +	case VCAP_KFS_IP4_TCP_UDP: +		return VCAP_IS2_PS_IPV6_MC_IP4_TCP_UDP_OTHER; +	case VCAP_KFS_IP_7TUPLE: +		return VCAP_IS2_PS_IPV6_MC_IP_7TUPLE; +	default: +		return VCAP_KFS_NO_VALUE; +	} +} + +static void sparx5_vcap_is2_set_port_keyset(struct net_device *ndev, int lookup, +					    enum vcap_keyfield_set keyset, +					    int l3_proto) +{ +	struct sparx5_port *port = netdev_priv(ndev); +	struct sparx5 *sparx5 = port->sparx5; +	int portno = port->portno; +	u32 value; + +	switch (l3_proto) { +	case ETH_P_ARP: +		value = sparx5_vcap_is2_keyset_to_arp_ps(keyset); +		spx5_rmw(ANA_ACL_VCAP_S2_KEY_SEL_ARP_KEY_SEL_SET(value), +			 ANA_ACL_VCAP_S2_KEY_SEL_ARP_KEY_SEL, +			 sparx5, +			 ANA_ACL_VCAP_S2_KEY_SEL(portno, lookup)); +		break; +	case ETH_P_IP: +		value = sparx5_vcap_is2_keyset_to_ipv4_ps(keyset); +		spx5_rmw(ANA_ACL_VCAP_S2_KEY_SEL_IP4_UC_KEY_SEL_SET(value), +			 ANA_ACL_VCAP_S2_KEY_SEL_IP4_UC_KEY_SEL, +			 sparx5, +			 ANA_ACL_VCAP_S2_KEY_SEL(portno, lookup)); +		spx5_rmw(ANA_ACL_VCAP_S2_KEY_SEL_IP4_MC_KEY_SEL_SET(value), +			 ANA_ACL_VCAP_S2_KEY_SEL_IP4_MC_KEY_SEL, +			 sparx5, +			 ANA_ACL_VCAP_S2_KEY_SEL(portno, lookup)); +		break; +	case ETH_P_IPV6: +		value = sparx5_vcap_is2_keyset_to_ipv6_uc_ps(keyset); +		spx5_rmw(ANA_ACL_VCAP_S2_KEY_SEL_IP6_UC_KEY_SEL_SET(value), +			 ANA_ACL_VCAP_S2_KEY_SEL_IP6_UC_KEY_SEL, +			 sparx5, +			 ANA_ACL_VCAP_S2_KEY_SEL(portno, lookup)); +		value = sparx5_vcap_is2_keyset_to_ipv6_mc_ps(keyset); +		spx5_rmw(ANA_ACL_VCAP_S2_KEY_SEL_IP6_MC_KEY_SEL_SET(value), +			 ANA_ACL_VCAP_S2_KEY_SEL_IP6_MC_KEY_SEL, +			 sparx5, +			 ANA_ACL_VCAP_S2_KEY_SEL(portno, lookup)); +		break; +	default: +		value = VCAP_IS2_PS_NONETH_MAC_ETYPE; +		spx5_rmw(ANA_ACL_VCAP_S2_KEY_SEL_NON_ETH_KEY_SEL_SET(value), +			 ANA_ACL_VCAP_S2_KEY_SEL_NON_ETH_KEY_SEL, +			 sparx5, +			 ANA_ACL_VCAP_S2_KEY_SEL(portno, lookup)); +		break; +	} +} + +static u32 sparx5_vcap_es2_keyset_to_arp_ps(enum vcap_keyfield_set keyset) +{ +	switch (keyset) { +	case VCAP_KFS_ARP: +		return VCAP_ES2_PS_ARP_ARP; +	default: +		return VCAP_ES2_PS_ARP_MAC_ETYPE; +	} +} + +static u32 sparx5_vcap_es2_keyset_to_ipv4_ps(enum vcap_keyfield_set keyset) +{ +	switch (keyset) { +	case VCAP_KFS_MAC_ETYPE: +		return VCAP_ES2_PS_IPV4_MAC_ETYPE; +	case VCAP_KFS_IP_7TUPLE: +		return VCAP_ES2_PS_IPV4_IP_7TUPLE; +	case VCAP_KFS_IP4_TCP_UDP: +		return VCAP_ES2_PS_IPV4_IP4_TCP_UDP_OTHER; +	case VCAP_KFS_IP4_OTHER: +		return VCAP_ES2_PS_IPV4_IP4_OTHER; +	default: +		return VCAP_ES2_PS_IPV4_MAC_ETYPE; +	} +} + +static u32 sparx5_vcap_es2_keyset_to_ipv6_ps(enum vcap_keyfield_set keyset) +{ +	switch (keyset) { +	case VCAP_KFS_MAC_ETYPE: +		return VCAP_ES2_PS_IPV6_MAC_ETYPE; +	case VCAP_KFS_IP4_TCP_UDP: +	case VCAP_KFS_IP4_OTHER: +		return VCAP_ES2_PS_IPV6_IP4_DOWNGRADE; +	case VCAP_KFS_IP_7TUPLE: +		return VCAP_ES2_PS_IPV6_IP_7TUPLE; +	case VCAP_KFS_IP6_STD: +		return VCAP_ES2_PS_IPV6_IP6_STD; +	default: +		return VCAP_ES2_PS_IPV6_MAC_ETYPE; +	} +} + +static void sparx5_vcap_es2_set_port_keyset(struct net_device *ndev, int lookup, +					    enum vcap_keyfield_set keyset, +					    int l3_proto) +{ +	struct sparx5_port *port = netdev_priv(ndev); +	struct sparx5 *sparx5 = port->sparx5; +	int portno = port->portno; +	u32 value; + +	switch (l3_proto) { +	case ETH_P_IP: +		value = sparx5_vcap_es2_keyset_to_ipv4_ps(keyset); +		spx5_rmw(EACL_VCAP_ES2_KEY_SEL_IP4_KEY_SEL_SET(value), +			 EACL_VCAP_ES2_KEY_SEL_IP4_KEY_SEL, +			 sparx5, +			 EACL_VCAP_ES2_KEY_SEL(portno, lookup)); +		break; +	case ETH_P_IPV6: +		value = sparx5_vcap_es2_keyset_to_ipv6_ps(keyset); +		spx5_rmw(EACL_VCAP_ES2_KEY_SEL_IP6_KEY_SEL_SET(value), +			 EACL_VCAP_ES2_KEY_SEL_IP6_KEY_SEL, +			 sparx5, +			 EACL_VCAP_ES2_KEY_SEL(portno, lookup)); +		break; +	case ETH_P_ARP: +		value = sparx5_vcap_es2_keyset_to_arp_ps(keyset); +		spx5_rmw(EACL_VCAP_ES2_KEY_SEL_ARP_KEY_SEL_SET(value), +			 EACL_VCAP_ES2_KEY_SEL_ARP_KEY_SEL, +			 sparx5, +			 EACL_VCAP_ES2_KEY_SEL(portno, lookup)); +		break; +	} +} + +/* Change the port keyset for the lookup and protocol */ +void sparx5_vcap_set_port_keyset(struct net_device *ndev, +				 struct vcap_admin *admin, +				 int cid, +				 u16 l3_proto, +				 enum vcap_keyfield_set keyset, +				 struct vcap_keyset_list *orig) +{ +	struct sparx5_port *port; +	int lookup; + +	switch (admin->vtype) { +	case VCAP_TYPE_IS0: +		lookup = sparx5_vcap_is0_cid_to_lookup(cid); +		if (orig) +			sparx5_vcap_is0_get_port_keysets(ndev, lookup, orig, +							 l3_proto); +		sparx5_vcap_is0_set_port_keyset(ndev, lookup, keyset, l3_proto); +		break; +	case VCAP_TYPE_IS2: +		lookup = sparx5_vcap_is2_cid_to_lookup(cid); +		if (orig) +			sparx5_vcap_is2_get_port_keysets(ndev, lookup, orig, +							 l3_proto); +		sparx5_vcap_is2_set_port_keyset(ndev, lookup, keyset, l3_proto); +		break; +	case VCAP_TYPE_ES0: +		break; +	case VCAP_TYPE_ES2: +		lookup = sparx5_vcap_es2_cid_to_lookup(cid); +		if (orig) +			sparx5_vcap_es2_get_port_keysets(ndev, lookup, orig, +							 l3_proto); +		sparx5_vcap_es2_set_port_keyset(ndev, lookup, keyset, l3_proto); +		break; +	default: +		port = netdev_priv(ndev); +		sparx5_vcap_type_err(port->sparx5, admin, __func__); +		break; +	} +} +  /* Enable IS0 lookups per port and set the keyset generation */  static void sparx5_vcap_is0_port_key_selection(struct sparx5 *sparx5,  					       struct vcap_admin *admin) diff --git a/drivers/net/ethernet/microchip/sparx5/sparx5_vcap_impl.h b/drivers/net/ethernet/microchip/sparx5/sparx5_vcap_impl.h index 3260ab5e3a82..2684d9199b05 100644 --- a/drivers/net/ethernet/microchip/sparx5/sparx5_vcap_impl.h +++ b/drivers/net/ethernet/microchip/sparx5/sparx5_vcap_impl.h @@ -195,6 +195,12 @@ int sparx5_vcap_get_port_keyset(struct net_device *ndev,  				u16 l3_proto,  				struct vcap_keyset_list *kslist); +/* Change the port keyset for the lookup and protocol */ +void sparx5_vcap_set_port_keyset(struct net_device *ndev, +				 struct vcap_admin *admin, int cid, +				 u16 l3_proto, enum vcap_keyfield_set keyset, +				 struct vcap_keyset_list *orig); +  /* Check if the ethertype is supported by the vcap port classification */  bool sparx5_vcap_is_known_etype(struct vcap_admin *admin, u16 etype); diff --git a/drivers/net/ethernet/microchip/vcap/vcap_ag_api.h b/drivers/net/ethernet/microchip/vcap/vcap_ag_api.h index 0844fcaeee68..a556c4419986 100644 --- a/drivers/net/ethernet/microchip/vcap/vcap_ag_api.h +++ b/drivers/net/ethernet/microchip/vcap/vcap_ag_api.h @@ -3,8 +3,8 @@   * Microchip VCAP API   */ -/* This file is autogenerated by cml-utils 2023-02-10 11:15:56 +0100. - * Commit ID: c30fb4bf0281cd4a7133bdab6682f9e43c872ada +/* This file is autogenerated by cml-utils 2023-02-16 11:41:14 +0100. + * Commit ID: be85f176b3a151fa748dcaf97c8824a5c2e065f3   */  #ifndef __VCAP_AG_API__ @@ -14,6 +14,7 @@ enum vcap_type {  	VCAP_TYPE_ES0,  	VCAP_TYPE_ES2,  	VCAP_TYPE_IS0, +	VCAP_TYPE_IS1,  	VCAP_TYPE_IS2,  	VCAP_TYPE_MAX  }; @@ -21,7 +22,12 @@ enum vcap_type {  /* Keyfieldset names with origin information */  enum vcap_keyfield_set {  	VCAP_KFS_NO_VALUE,          /* initial value */ +	VCAP_KFS_5TUPLE_IP4,        /* lan966x is1 X2 */ +	VCAP_KFS_5TUPLE_IP6,        /* lan966x is1 X4 */ +	VCAP_KFS_7TUPLE,            /* lan966x is1 X4 */  	VCAP_KFS_ARP,               /* sparx5 is2 X6, sparx5 es2 X6, lan966x is2 X2 */ +	VCAP_KFS_DBL_VID,           /* lan966x is1 X1 */ +	VCAP_KFS_DMAC_VID,          /* lan966x is1 X1 */  	VCAP_KFS_ETAG,              /* sparx5 is0 X2 */  	VCAP_KFS_IP4_OTHER,         /* sparx5 is2 X6, sparx5 es2 X6, lan966x is2 X2 */  	VCAP_KFS_IP4_TCP_UDP,       /* sparx5 is2 X6, sparx5 es2 X6, lan966x is2 X2 */ @@ -36,10 +42,13 @@ enum vcap_keyfield_set {  	VCAP_KFS_MAC_ETYPE,         /* sparx5 is2 X6, sparx5 es2 X6, lan966x is2 X2 */  	VCAP_KFS_MAC_LLC,           /* lan966x is2 X2 */  	VCAP_KFS_MAC_SNAP,          /* lan966x is2 X2 */ +	VCAP_KFS_NORMAL,            /* lan966x is1 X2 */  	VCAP_KFS_NORMAL_5TUPLE_IP4,  /* sparx5 is0 X6 */  	VCAP_KFS_NORMAL_7TUPLE,     /* sparx5 is0 X12 */ +	VCAP_KFS_NORMAL_IP6,        /* lan966x is1 X4 */  	VCAP_KFS_OAM,               /* lan966x is2 X2 */  	VCAP_KFS_PURE_5TUPLE_IP4,   /* sparx5 is0 X3 */ +	VCAP_KFS_RT,                /* lan966x is1 X1 */  	VCAP_KFS_SMAC_SIP4,         /* lan966x is2 X1 */  	VCAP_KFS_SMAC_SIP6,         /* lan966x is2 X2 */  }; @@ -61,17 +70,20 @@ enum vcap_keyfield_set {   *   Used by 802.1BR Bridge Port Extension in an E-Tag   * VCAP_KF_8021BR_IGR_ECID_EXT: W8, sparx5: is0   *   Used by 802.1BR Bridge Port Extension in an E-Tag - * VCAP_KF_8021Q_DEI0: W1, sparx5: is0 + * VCAP_KF_8021CB_R_TAGGED_IS: W1, lan966x: is1 + *   Set if frame contains an RTAG: IEEE 802.1CB (FRER Redundancy tag, Ethertype + *   0xf1c1) + * VCAP_KF_8021Q_DEI0: W1, sparx5: is0, lan966x: is1   *   First DEI in multiple vlan tags (outer tag or default port tag) - * VCAP_KF_8021Q_DEI1: W1, sparx5: is0 + * VCAP_KF_8021Q_DEI1: W1, sparx5: is0, lan966x: is1   *   Second DEI in multiple vlan tags (inner tag)   * VCAP_KF_8021Q_DEI2: W1, sparx5: is0   *   Third DEI in multiple vlan tags (not always available)   * VCAP_KF_8021Q_DEI_CLS: W1, sparx5: is2/es2, lan966x: is2   *   Classified DEI - * VCAP_KF_8021Q_PCP0: W3, sparx5: is0 + * VCAP_KF_8021Q_PCP0: W3, sparx5: is0, lan966x: is1   *   First PCP in multiple vlan tags (outer tag or default port tag) - * VCAP_KF_8021Q_PCP1: W3, sparx5: is0 + * VCAP_KF_8021Q_PCP1: W3, sparx5: is0, lan966x: is1   *   Second PCP in multiple vlan tags (inner tag)   * VCAP_KF_8021Q_PCP2: W3, sparx5: is0   *   Third PCP in multiple vlan tags (not always available) @@ -79,22 +91,24 @@ enum vcap_keyfield_set {   *   Classified PCP   * VCAP_KF_8021Q_TPID: W3, sparx5: es0   *   TPID for outer tag: 0: Customer TPID 1: Service TPID (88A8 or programmable) - * VCAP_KF_8021Q_TPID0: W3, sparx5: is0 + * VCAP_KF_8021Q_TPID0: sparx5 is0 W3, lan966x is1 W1   *   First TPIC in multiple vlan tags (outer tag or default port tag) - * VCAP_KF_8021Q_TPID1: W3, sparx5: is0 + * VCAP_KF_8021Q_TPID1: sparx5 is0 W3, lan966x is1 W1   *   Second TPID in multiple vlan tags (inner tag)   * VCAP_KF_8021Q_TPID2: W3, sparx5: is0   *   Third TPID in multiple vlan tags (not always available) - * VCAP_KF_8021Q_VID0: W12, sparx5: is0 + * VCAP_KF_8021Q_VID0: W12, sparx5: is0, lan966x: is1   *   First VID in multiple vlan tags (outer tag or default port tag) - * VCAP_KF_8021Q_VID1: W12, sparx5: is0 + * VCAP_KF_8021Q_VID1: W12, sparx5: is0, lan966x: is1   *   Second VID in multiple vlan tags (inner tag)   * VCAP_KF_8021Q_VID2: W12, sparx5: is0   *   Third VID in multiple vlan tags (not always available)   * VCAP_KF_8021Q_VID_CLS: sparx5 is2 W13, sparx5 es0 W13, sparx5 es2 W13,   *   lan966x is2 W12   *   Classified VID - * VCAP_KF_8021Q_VLAN_TAGGED_IS: W1, sparx5: is2/es2, lan966x: is2 + * VCAP_KF_8021Q_VLAN_DBL_TAGGED_IS: W1, lan966x: is1 + *   Set if frame has two or more Q-tags. Independent of port VLAN awareness + * VCAP_KF_8021Q_VLAN_TAGGED_IS: W1, sparx5: is2/es2, lan966x: is1/is2   *   Sparx5: Set if frame was received with a VLAN tag, LAN966x: Set if frame has   *   one or more Q-tags. Independent of port VLAN awareness   * VCAP_KF_8021Q_VLAN_TAGS: W3, sparx5: is0 @@ -120,9 +134,9 @@ enum vcap_keyfield_set {   *   Class of service   * VCAP_KF_ES0_ISDX_KEY_ENA: W1, sparx5: es2   *   The value taken from the IFH .FWD.ES0_ISDX_KEY_ENA - * VCAP_KF_ETYPE: W16, sparx5: is0/is2/es2, lan966x: is2 + * VCAP_KF_ETYPE: W16, sparx5: is0/is2/es2, lan966x: is1/is2   *   Ethernet type - * VCAP_KF_ETYPE_LEN_IS: W1, sparx5: is0/is2/es2 + * VCAP_KF_ETYPE_LEN_IS: W1, sparx5: is0/is2/es2, lan966x: is1   *   Set if frame has EtherType >= 0x600   * VCAP_KF_HOST_MATCH: W1, lan966x: is2   *   The action from the SMAC_SIP4 or SMAC_SIP6 lookups. Used for IP source @@ -134,11 +148,12 @@ enum vcap_keyfield_set {   *   CPU queue)   * VCAP_KF_IF_EGR_PORT_NO: W7, sparx5: es0   *   Egress port number - * VCAP_KF_IF_IGR_PORT: sparx5 is0 W7, sparx5 es2 W9, lan966x is2 W4 + * VCAP_KF_IF_IGR_PORT: sparx5 is0 W7, sparx5 es2 W9, lan966x is1 W3, lan966x + *   is2 W4   *   Sparx5: Logical ingress port number retrieved from   *   ANA_CL::PORT_ID_CFG.LPORT_NUM or ERLEG, LAN966x: ingress port nunmber   * VCAP_KF_IF_IGR_PORT_MASK: sparx5 is0 W65, sparx5 is2 W32, sparx5 is2 W65, - *   lan966x is2 W9 + *   lan966x is1 W9, lan966x is2 W9   *   Ingress port mask, one bit per port/erleg   * VCAP_KF_IF_IGR_PORT_MASK_L3: W1, sparx5: is2   *   If set, IF_IGR_PORT_MASK, IF_IGR_PORT_MASK_RNG, and IF_IGR_PORT_MASK_SEL are @@ -151,24 +166,26 @@ enum vcap_keyfield_set {   *   Mapping: 0: DEFAULT 1: LOOPBACK 2: MASQUERADE 3: CPU_VD   * VCAP_KF_IF_IGR_PORT_SEL: W1, sparx5: es2   *   Selector for IF_IGR_PORT: physical port number or ERLEG - * VCAP_KF_IP4_IS: W1, sparx5: is0/is2/es2, lan966x: is2 + * VCAP_KF_IP4_IS: W1, sparx5: is0/is2/es2, lan966x: is1/is2   *   Set if frame has EtherType = 0x800 and IP version = 4 - * VCAP_KF_IP_MC_IS: W1, sparx5: is0 + * VCAP_KF_IP_MC_IS: W1, sparx5: is0, lan966x: is1   *   Set if frame is IPv4 frame and frame's destination MAC address is an IPv4   *   multicast address (0x01005E0 /25). Set if frame is IPv6 frame and frame's   *   destination MAC address is an IPv6 multicast address (0x3333/16). - * VCAP_KF_IP_PAYLOAD_5TUPLE: W32, sparx5: is0 + * VCAP_KF_IP_PAYLOAD_5TUPLE: W32, sparx5: is0, lan966x: is1   *   Payload bytes after IP header - * VCAP_KF_IP_SNAP_IS: W1, sparx5: is0 + * VCAP_KF_IP_PAYLOAD_S1_IP6: W112, lan966x: is1 + *   Payload after IPv6 header + * VCAP_KF_IP_SNAP_IS: W1, sparx5: is0, lan966x: is1   *   Set if frame is IPv4, IPv6, or SNAP frame   * VCAP_KF_ISDX_CLS: W12, sparx5: is2/es0/es2   *   Classified ISDX   * VCAP_KF_ISDX_GT0_IS: W1, sparx5: is2/es0/es2, lan966x: is2   *   Set if classified ISDX > 0 - * VCAP_KF_L2_BC_IS: W1, sparx5: is0/is2/es2, lan966x: is2 + * VCAP_KF_L2_BC_IS: W1, sparx5: is0/is2/es2, lan966x: is1/is2   *   Set if frame's destination MAC address is the broadcast address   *   (FF-FF-FF-FF-FF-FF). - * VCAP_KF_L2_DMAC: W48, sparx5: is0/is2/es2, lan966x: is2 + * VCAP_KF_L2_DMAC: W48, sparx5: is0/is2/es2, lan966x: is1/is2   *   Destination MAC address   * VCAP_KF_L2_FRM_TYPE: W4, lan966x: is2   *   Frame subtype for specific EtherTypes (MRP, DLR) @@ -176,7 +193,9 @@ enum vcap_keyfield_set {   *   Set if the frame is allowed to be forwarded to front ports   * VCAP_KF_L2_LLC: W40, lan966x: is2   *   LLC header and data after up to two VLAN tags and the type/length field - * VCAP_KF_L2_MC_IS: W1, sparx5: is0/is2/es2, lan966x: is2 + * VCAP_KF_L2_MAC: W48, lan966x: is1 + *   MAC address (FIRST=1: SMAC, FIRST=0: DMAC) + * VCAP_KF_L2_MC_IS: W1, sparx5: is0/is2/es2, lan966x: is1/is2   *   Set if frame's destination MAC address is a multicast address (bit 40 = 1).   * VCAP_KF_L2_PAYLOAD0: W16, lan966x: is2   *   Payload bytes 0-1 after the frame's EtherType @@ -188,7 +207,7 @@ enum vcap_keyfield_set {   *   specifically for PTP frames.   * VCAP_KF_L2_PAYLOAD_ETYPE: W64, sparx5: is2/es2   *   Byte 0-7 of L2 payload after Type/Len field and overloading for OAM - * VCAP_KF_L2_SMAC: W48, sparx5: is0/is2/es2, lan966x: is2 + * VCAP_KF_L2_SMAC: W48, sparx5: is0/is2/es2, lan966x: is1/is2   *   Source MAC address   * VCAP_KF_L2_SNAP: W40, lan966x: is2   *   SNAP header after LLC header (AA-AA-03) @@ -196,32 +215,38 @@ enum vcap_keyfield_set {   *   Set if Src IP matches Dst IP address   * VCAP_KF_L3_DPL_CLS: W1, sparx5: es0/es2   *   The frames drop precedence level - * VCAP_KF_L3_DSCP: W6, sparx5: is0 + * VCAP_KF_L3_DSCP: W6, sparx5: is0, lan966x: is1   *   Frame's DSCP value   * VCAP_KF_L3_DST_IS: W1, sparx5: is2   *   Set if lookup is done for egress router leg - * VCAP_KF_L3_FRAGMENT: W1, lan966x: is2 + * VCAP_KF_L3_FRAGMENT: W1, lan966x: is1/is2   *   Set if IPv4 frame is fragmented   * VCAP_KF_L3_FRAGMENT_TYPE: W2, sparx5: is0/is2/es2   *   L3 Fragmentation type (none, initial, suspicious, valid follow up)   * VCAP_KF_L3_FRAG_INVLD_L4_LEN: W1, sparx5: is0/is2   *   Set if frame's L4 length is less than ANA_CL:COMMON:CLM_FRAGMENT_CFG.L4_MIN_L   *   EN - * VCAP_KF_L3_FRAG_OFS_GT0: W1, lan966x: is2 + * VCAP_KF_L3_FRAG_OFS_GT0: W1, lan966x: is1/is2   *   Set if IPv4 frame is fragmented and it is not the first fragment - * VCAP_KF_L3_IP4_DIP: W32, sparx5: is0/is2/es2, lan966x: is2 + * VCAP_KF_L3_IP4_DIP: W32, sparx5: is0/is2/es2, lan966x: is1/is2   *   Destination IPv4 Address - * VCAP_KF_L3_IP4_SIP: W32, sparx5: is0/is2/es2, lan966x: is2 + * VCAP_KF_L3_IP4_SIP: W32, sparx5: is0/is2/es2, lan966x: is1/is2   *   Source IPv4 Address - * VCAP_KF_L3_IP6_DIP: W128, sparx5: is0/is2/es2, lan966x: is2 + * VCAP_KF_L3_IP6_DIP: sparx5 is0 W128, sparx5 is2 W128, sparx5 es2 W128, + *   lan966x is1 W64, lan966x is1 W128, lan966x is2 W128   *   Sparx5: Full IPv6 DIP, LAN966x: Either Full IPv6 DIP or a subset depending on   *   frame type - * VCAP_KF_L3_IP6_SIP: W128, sparx5: is0/is2/es2, lan966x: is2 + * VCAP_KF_L3_IP6_DIP_MSB: W16, lan966x: is1 + *   MS 16bits of IPv6 DIP + * VCAP_KF_L3_IP6_SIP: sparx5 is0 W128, sparx5 is2 W128, sparx5 es2 W128, + *   lan966x is1 W128, lan966x is1 W64, lan966x is2 W128   *   Sparx5: Full IPv6 SIP, LAN966x: Either Full IPv6 SIP or a subset depending on   *   frame type - * VCAP_KF_L3_IP_PROTO: W8, sparx5: is0/is2/es2, lan966x: is2 + * VCAP_KF_L3_IP6_SIP_MSB: W16, lan966x: is1 + *   MS 16bits of IPv6 DIP + * VCAP_KF_L3_IP_PROTO: W8, sparx5: is0/is2/es2, lan966x: is1/is2   *   IPv4 frames: IP protocol. IPv6 frames: Next header, same as for IPV4 - * VCAP_KF_L3_OPTIONS_IS: W1, sparx5: is0/is2/es2, lan966x: is2 + * VCAP_KF_L3_OPTIONS_IS: W1, sparx5: is0/is2/es2, lan966x: is1/is2   *   Set if IPv4 frame contains options (IP len > 5)   * VCAP_KF_L3_PAYLOAD: sparx5 is2 W96, sparx5 is2 W40, sparx5 es2 W96, sparx5   *   es2 W40, lan966x is2 W56 @@ -254,7 +279,8 @@ enum vcap_keyfield_set {   * VCAP_KF_L4_PSH: W1, sparx5: is2/es2, lan966x: is2   *   Sparx5: TCP flag PSH, LAN966x: TCP: TCP flag PSH. PTP over UDP: flagField bit   *   1 (twoStepFlag) - * VCAP_KF_L4_RNG: sparx5 is0 W8, sparx5 is2 W16, sparx5 es2 W16, lan966x is2 W8 + * VCAP_KF_L4_RNG: sparx5 is0 W8, sparx5 is2 W16, sparx5 es2 W16, lan966x is1 + *   W8, lan966x is2 W8   *   Range checker bitmask (one for each range checker). Input into range checkers   *   is taken from classified results (VID, DSCP) and frame (SPORT, DPORT, ETYPE,   *   outer VID, inner VID) @@ -264,7 +290,7 @@ enum vcap_keyfield_set {   * VCAP_KF_L4_SEQUENCE_EQ0_IS: W1, sparx5: is2/es2, lan966x: is2   *   Set if TCP sequence number is 0, LAN966x: Overlayed with PTP over UDP:   *   messageType bit 0 - * VCAP_KF_L4_SPORT: W16, sparx5: is0/is2/es2, lan966x: is2 + * VCAP_KF_L4_SPORT: W16, sparx5: is0/is2/es2, lan966x: is1/is2   *   TCP/UDP source port   * VCAP_KF_L4_SPORT_EQ_DPORT_IS: W1, sparx5: is2/es2, lan966x: is2   *   Set if UDP or TCP source port equals UDP or TCP destination port @@ -274,13 +300,16 @@ enum vcap_keyfield_set {   * VCAP_KF_L4_URG: W1, sparx5: is2/es2, lan966x: is2   *   Sparx5: TCP flag URG, LAN966x: TCP: TCP flag URG. PTP over UDP: flagField bit   *   7 (reserved) - * VCAP_KF_LOOKUP_FIRST_IS: W1, sparx5: is0/is2/es2, lan966x: is2 + * VCAP_KF_LOOKUP_FIRST_IS: W1, sparx5: is0/is2/es2, lan966x: is1/is2   *   Selects between entries relevant for first and second lookup. Set for first   *   lookup, cleared for second lookup.   * VCAP_KF_LOOKUP_GEN_IDX: W12, sparx5: is0   *   Generic index - for chaining CLM instances   * VCAP_KF_LOOKUP_GEN_IDX_SEL: W2, sparx5: is0   *   Select the mode of the Generic Index + * VCAP_KF_LOOKUP_INDEX: W2, lan966x: is1 + *   0: First lookup, 1: Second lookup, 2: Third lookup, Similar to VCAP_KF_FIRST + *   but with extra info   * VCAP_KF_LOOKUP_PAG: W8, sparx5: is2, lan966x: is2   *   Classified Policy Association Group: chains rules from IS1/CLM to IS2   * VCAP_KF_MIRROR_PROBE: W2, sparx5: es2 @@ -303,14 +332,22 @@ enum vcap_keyfield_set {   *   Set if frame's EtherType = 0x8902   * VCAP_KF_PROT_ACTIVE: W1, sparx5: es0/es2   *   Protection is active - * VCAP_KF_TCP_IS: W1, sparx5: is0/is2/es2, lan966x: is2 + * VCAP_KF_RT_FRMID: W32, lan966x: is1 + *   Profinet or OPC-UA FrameId + * VCAP_KF_RT_TYPE: W2, lan966x: is1 + *   Encoding of frame's EtherType: 0: Other, 1: Profinet, 2: OPC-UA, 3: Custom + *   (ANA::RT_CUSTOM) + * VCAP_KF_RT_VLAN_IDX: W3, lan966x: is1 + *   Real-time VLAN index from ANA::RT_VLAN_PCP + * VCAP_KF_TCP_IS: W1, sparx5: is0/is2/es2, lan966x: is1/is2   *   Set if frame is IPv4 TCP frame (IP protocol = 6) or IPv6 TCP frames (Next   *   header = 6) - * VCAP_KF_TCP_UDP_IS: W1, sparx5: is0/is2/es2 + * VCAP_KF_TCP_UDP_IS: W1, sparx5: is0/is2/es2, lan966x: is1   *   Set if frame is IPv4/IPv6 TCP or UDP frame (IP protocol/next header equals 6   *   or 17)   * VCAP_KF_TYPE: sparx5 is0 W2, sparx5 is0 W1, sparx5 is2 W4, sparx5 is2 W2, - *   sparx5 es0 W1, sparx5 es2 W3, lan966x is2 W4, lan966x is2 W2 + *   sparx5 es0 W1, sparx5 es2 W3, lan966x is1 W1, lan966x is1 W2, lan966x is2 W4, + *   lan966x is2 W2   *   Keyset type id - set by the API   */ @@ -323,6 +360,7 @@ enum vcap_key_field {  	VCAP_KF_8021BR_GRP,  	VCAP_KF_8021BR_IGR_ECID_BASE,  	VCAP_KF_8021BR_IGR_ECID_EXT, +	VCAP_KF_8021CB_R_TAGGED_IS,  	VCAP_KF_8021Q_DEI0,  	VCAP_KF_8021Q_DEI1,  	VCAP_KF_8021Q_DEI2, @@ -339,6 +377,7 @@ enum vcap_key_field {  	VCAP_KF_8021Q_VID1,  	VCAP_KF_8021Q_VID2,  	VCAP_KF_8021Q_VID_CLS, +	VCAP_KF_8021Q_VLAN_DBL_TAGGED_IS,  	VCAP_KF_8021Q_VLAN_TAGGED_IS,  	VCAP_KF_8021Q_VLAN_TAGS,  	VCAP_KF_ACL_GRP_ID, @@ -366,6 +405,7 @@ enum vcap_key_field {  	VCAP_KF_IP4_IS,  	VCAP_KF_IP_MC_IS,  	VCAP_KF_IP_PAYLOAD_5TUPLE, +	VCAP_KF_IP_PAYLOAD_S1_IP6,  	VCAP_KF_IP_SNAP_IS,  	VCAP_KF_ISDX_CLS,  	VCAP_KF_ISDX_GT0_IS, @@ -374,6 +414,7 @@ enum vcap_key_field {  	VCAP_KF_L2_FRM_TYPE,  	VCAP_KF_L2_FWD_IS,  	VCAP_KF_L2_LLC, +	VCAP_KF_L2_MAC,  	VCAP_KF_L2_MC_IS,  	VCAP_KF_L2_PAYLOAD0,  	VCAP_KF_L2_PAYLOAD1, @@ -392,7 +433,9 @@ enum vcap_key_field {  	VCAP_KF_L3_IP4_DIP,  	VCAP_KF_L3_IP4_SIP,  	VCAP_KF_L3_IP6_DIP, +	VCAP_KF_L3_IP6_DIP_MSB,  	VCAP_KF_L3_IP6_SIP, +	VCAP_KF_L3_IP6_SIP_MSB,  	VCAP_KF_L3_IP_PROTO,  	VCAP_KF_L3_OPTIONS_IS,  	VCAP_KF_L3_PAYLOAD, @@ -416,6 +459,7 @@ enum vcap_key_field {  	VCAP_KF_LOOKUP_FIRST_IS,  	VCAP_KF_LOOKUP_GEN_IDX,  	VCAP_KF_LOOKUP_GEN_IDX_SEL, +	VCAP_KF_LOOKUP_INDEX,  	VCAP_KF_LOOKUP_PAG,  	VCAP_KF_MIRROR_PROBE,  	VCAP_KF_OAM_CCM_CNTS_EQ0, @@ -427,6 +471,9 @@ enum vcap_key_field {  	VCAP_KF_OAM_VER,  	VCAP_KF_OAM_Y1731_IS,  	VCAP_KF_PROT_ACTIVE, +	VCAP_KF_RT_FRMID, +	VCAP_KF_RT_TYPE, +	VCAP_KF_RT_VLAN_IDX,  	VCAP_KF_TCP_IS,  	VCAP_KF_TCP_UDP_IS,  	VCAP_KF_TYPE, @@ -440,6 +487,7 @@ enum vcap_actionfield_set {  	VCAP_AFS_CLASS_REDUCED,     /* sparx5 is0 X1 */  	VCAP_AFS_ES0,               /* sparx5 es0 X1 */  	VCAP_AFS_FULL,              /* sparx5 is0 X3 */ +	VCAP_AFS_S1,                /* lan966x is1 X1 */  	VCAP_AFS_SMAC_SIP,          /* lan966x is2 X1 */  }; @@ -470,23 +518,31 @@ enum vcap_actionfield_set {   *   CPU extraction queue. Used when FWD_SEL >0 and PIPELINE_ACT = XTR.   * VCAP_AF_CPU_QUEUE_NUM: W3, sparx5: is2/es2, lan966x: is2   *   CPU queue number. Used when CPU_COPY_ENA is set. + * VCAP_AF_CUSTOM_ACE_TYPE_ENA: W4, lan966x: is1 + *   Enables use of custom keys in IS2. Bits 3:2 control second lookup in IS2 + *   while bits 1:0 control first lookup. Encoding per lookup: 0: Disabled.  1: + *   Extract 40 bytes after position corresponding to the location of the IPv4 + *   header and use as key.  2: Extract 40 bytes after SMAC and use as key   * VCAP_AF_DEI_A_VAL: W1, sparx5: es0   *   DEI used in ES0 tag A. See TAG_A_DEI_SEL.   * VCAP_AF_DEI_B_VAL: W1, sparx5: es0   *   DEI used in ES0 tag B. See TAG_B_DEI_SEL.   * VCAP_AF_DEI_C_VAL: W1, sparx5: es0   *   DEI used in ES0 tag C. See TAG_C_DEI_SEL. - * VCAP_AF_DEI_ENA: W1, sparx5: is0 + * VCAP_AF_DEI_ENA: W1, sparx5: is0, lan966x: is1   *   If set, use DEI_VAL as classified DEI value. Otherwise, DEI from basic   *   classification is used - * VCAP_AF_DEI_VAL: W1, sparx5: is0 + * VCAP_AF_DEI_VAL: W1, sparx5: is0, lan966x: is1   *   See DEI_ENA - * VCAP_AF_DP_ENA: W1, sparx5: is0 + * VCAP_AF_DLR_SEL: W2, lan966x: is1 + *   0: No changes to port-based selection in ANA:PORT:OAM_CFG.DLR_ENA.  1: Enable + *   DLR frame processing 2: Disable DLR processing + * VCAP_AF_DP_ENA: W1, sparx5: is0, lan966x: is1   *   If set, use DP_VAL as classified drop precedence level. Otherwise, drop   *   precedence level from basic classification is used. - * VCAP_AF_DP_VAL: W2, sparx5: is0 + * VCAP_AF_DP_VAL: sparx5 is0 W2, lan966x is1 W1   *   See DP_ENA. - * VCAP_AF_DSCP_ENA: W1, sparx5: is0 + * VCAP_AF_DSCP_ENA: W1, sparx5: is0, lan966x: is1   *   If set, use DSCP_VAL as classified DSCP value. Otherwise, DSCP value from   *   basic classification is used.   * VCAP_AF_DSCP_SEL: W3, sparx5: es0 @@ -495,7 +551,7 @@ enum vcap_actionfield_set {   *   table 0, otherwise use DSCP_VAL. 5: Mapped using mapping table 1, otherwise   *   use mapping table 0. 6: Mapped using mapping table 2, otherwise use DSCP_VAL.   *   7: Mapped using mapping table 3, otherwise use mapping table 2 - * VCAP_AF_DSCP_VAL: W6, sparx5: is0/es0 + * VCAP_AF_DSCP_VAL: W6, sparx5: is0/es0, lan966x: is1   *   See DSCP_ENA.   * VCAP_AF_ES2_REW_CMD: W3, sparx5: es2   *   Command forwarded to REW: 0: No action. 1: SWAP MAC addresses. 2: Do L2CP @@ -529,9 +585,16 @@ enum vcap_actionfield_set {   * VCAP_AF_ISDX_ADD_REPLACE_SEL: W1, sparx5: is0   *   Controls the classified ISDX. 0: New ISDX = old ISDX + ISDX_VAL. 1: New ISDX   *   = ISDX_VAL. + * VCAP_AF_ISDX_ADD_VAL: W8, lan966x: is1 + *   If ISDX_REPLACE_ENA is set, ISDX_ADD_VAL is used directly as the new ISDX. + *   Encoding: ISDX_REPLACE_ENA=0, ISDX_ADD_VAL=0: Disabled ISDX_EPLACE_ENA=0, + *   ISDX_ADD_VAL>0: Add value to classified ISDX. ISDX_REPLACE_ENA=1: Replace + *   with ISDX_ADD_VAL value.   * VCAP_AF_ISDX_ENA: W1, lan966x: is2   *   Setting this bit to 1 causes the classified ISDX to be set to the value of   *   POLICE_IDX[8:0]. + * VCAP_AF_ISDX_REPLACE_ENA: W1, lan966x: is1 + *   If set, classified ISDX is set to ISDX_ADD_VAL.   * VCAP_AF_ISDX_VAL: W12, sparx5: is0   *   See isdx_add_replace_sel   * VCAP_AF_LOOP_ENA: W1, sparx5: es0 @@ -572,14 +635,22 @@ enum vcap_actionfield_set {   * VCAP_AF_MIRROR_PROBE_ID: W2, sparx5: es2   *   Signals a mirror probe to be placed in the IFH. Only possible when FWD_MODE   *   is copy. 0: No mirroring. 1-3: Use mirror probe 0-2. + * VCAP_AF_MRP_SEL: W2, lan966x: is1 + *   0: No changes to port-based selection in ANA:PORT:OAM_CFG.MRP_ENA.  1: Enable + *   MRP frame processing 2: Disable MRP processing   * VCAP_AF_NXT_IDX: W12, sparx5: is0   *   Index used as part of key (field G_IDX) in the next lookup.   * VCAP_AF_NXT_IDX_CTRL: W3, sparx5: is0   *   Controls the generation of the G_IDX used in the VCAP CLM next lookup - * VCAP_AF_PAG_OVERRIDE_MASK: W8, sparx5: is0 + * VCAP_AF_OAM_SEL: W3, lan966x: is1 + *   0: No changes to port-based selection in ANA:PORT:OAM_CFG.OAM_CFG 1: Enable + *   OAM frame processing for untagged frames 2: Enable OAM frame processing for + *   single frames 3: Enable OAM frame processing for double frames 4: Disable OAM + *   frame processing + * VCAP_AF_PAG_OVERRIDE_MASK: W8, sparx5: is0, lan966x: is1   *   Bits set in this mask will override PAG_VAL from port profile. New PAG = (PAG   *   (input) AND ~PAG_OVERRIDE_MASK) OR (PAG_VAL AND PAG_OVERRIDE_MASK) - * VCAP_AF_PAG_VAL: W8, sparx5: is0 + * VCAP_AF_PAG_VAL: W8, sparx5: is0, lan966x: is1   *   See PAG_OVERRIDE_MASK.   * VCAP_AF_PCP_A_VAL: W3, sparx5: es0   *   PCP used in ES0 tag A. See TAG_A_PCP_SEL. @@ -587,10 +658,10 @@ enum vcap_actionfield_set {   *   PCP used in ES0 tag B. See TAG_B_PCP_SEL.   * VCAP_AF_PCP_C_VAL: W3, sparx5: es0   *   PCP used in ES0 tag C. See TAG_C_PCP_SEL. - * VCAP_AF_PCP_ENA: W1, sparx5: is0 + * VCAP_AF_PCP_ENA: W1, sparx5: is0, lan966x: is1   *   If set, use PCP_VAL as classified PCP value. Otherwise, PCP from basic   *   classification is used. - * VCAP_AF_PCP_VAL: W3, sparx5: is0 + * VCAP_AF_PCP_VAL: W3, sparx5: is0, lan966x: is1   *   See PCP_ENA.   * VCAP_AF_PIPELINE_ACT: W1, sparx5: es0   *   Pipeline action when FWD_SEL > 0. 0: XTR. CPU_QU selects CPU extraction queue @@ -600,11 +671,11 @@ enum vcap_actionfield_set {   *   PIPELINE_PT == NONE. Overrules previous settings of pipeline point.   * VCAP_AF_PIPELINE_PT: sparx5 is2 W5, sparx5 es0 W2   *   Pipeline point used if PIPELINE_FORCE_ENA is set - * VCAP_AF_POLICE_ENA: W1, sparx5: is2/es2, lan966x: is2 - *   Setting this bit to 1 causes frames that hit this action to be policed by the - *   ACL policer specified in POLICE_IDX. Only applies to the first lookup. - * VCAP_AF_POLICE_IDX: sparx5 is2 W6, sparx5 es2 W6, lan966x is2 W9 - *   Selects VCAP policer used when policing frames (POLICE_ENA) + * VCAP_AF_POLICE_ENA: W1, sparx5: is2/es2, lan966x: is1/is2 + *   If set, POLICE_IDX is used to lookup ANA::POL. + * VCAP_AF_POLICE_IDX: sparx5 is2 W6, sparx5 es2 W6, lan966x is1 W9, lan966x is2 + *   W9 + *   Policer index.   * VCAP_AF_POLICE_REMARK: W1, sparx5: es2   *   If set, frames exceeding policer rates are marked as yellow but not   *   discarded. @@ -628,16 +699,24 @@ enum vcap_actionfield_set {   *   port. 1: ES0 tag A: Push ES0 tag A. No port tag. 2: Force port tag: Always   *   push port tag. No ES0 tag A. 3: Force untag: Never push port tag or ES0 tag   *   A. - * VCAP_AF_QOS_ENA: W1, sparx5: is0 + * VCAP_AF_QOS_ENA: W1, sparx5: is0, lan966x: is1   *   If set, use QOS_VAL as classified QoS class. Otherwise, QoS class from basic   *   classification is used. - * VCAP_AF_QOS_VAL: W3, sparx5: is0 + * VCAP_AF_QOS_VAL: W3, sparx5: is0, lan966x: is1   *   See QOS_ENA.   * VCAP_AF_REW_OP: W16, lan966x: is2   *   Rewriter operation command.   * VCAP_AF_RT_DIS: W1, sparx5: is2   *   If set, routing is disallowed. Only applies when IS_INNER_ACL is 0. See also   *   IGR_ACL_ENA, EGR_ACL_ENA, and RLEG_STAT_IDX. + * VCAP_AF_SFID_ENA: W1, lan966x: is1 + *   If set, SFID_VAL is used to lookup ANA::SFID. + * VCAP_AF_SFID_VAL: W8, lan966x: is1 + *   Stream filter identifier. + * VCAP_AF_SGID_ENA: W1, lan966x: is1 + *   If set, SGID_VAL is used to lookup ANA::SGID. + * VCAP_AF_SGID_VAL: W8, lan966x: is1 + *   Stream gate identifier.   * VCAP_AF_SWAP_MACS_ENA: W1, sparx5: es0   *   This setting is only active when FWD_SEL = 1 or FWD_SEL = 2 and PIPELINE_ACT   *   = LBK_ASM. 0: No action. 1: Swap MACs and clear bit 40 in new SMAC. @@ -686,7 +765,7 @@ enum vcap_actionfield_set {   * VCAP_AF_TAG_C_VID_SEL: W2, sparx5: es0   *   Selects VID for ES0 tag C. The resulting VID is termed C-TAG.VID. 0:   *   Classified VID. 1: VID_C_VAL. 2: IFH.ENCAP.GVID. 3: Reserved. - * VCAP_AF_TYPE: W1, sparx5: is0 + * VCAP_AF_TYPE: W1, sparx5: is0, lan966x: is1   *   Actionset type id - Set by the API   * VCAP_AF_UNTAG_VID_ENA: W1, sparx5: es0   *   Controls insertion of tag C. Untag or insert mode can be selected. See @@ -697,8 +776,19 @@ enum vcap_actionfield_set {   *   VID used in ES0 tag B. See TAG_B_VID_SEL.   * VCAP_AF_VID_C_VAL: W12, sparx5: es0   *   VID used in ES0 tag C. See TAG_C_VID_SEL. - * VCAP_AF_VID_VAL: W13, sparx5: is0 + * VCAP_AF_VID_REPLACE_ENA: W1, lan966x: is1 + *   Controls the classified VID: VID_REPLACE_ENA=0: Add VID_ADD_VAL to basic + *   classified VID and use result as new classified VID. VID_REPLACE_ENA = 1: + *   Replace basic classified VID with VID_VAL value and use as new classified + *   VID. + * VCAP_AF_VID_VAL: sparx5 is0 W13, lan966x is1 W12   *   New VID Value + * VCAP_AF_VLAN_POP_CNT: W2, lan966x: is1 + *   See VLAN_POP_CNT_ENA + * VCAP_AF_VLAN_POP_CNT_ENA: W1, lan966x: is1 + *   If set, use VLAN_POP_CNT as the number of VLAN tags to pop from the incoming + *   frame. This number is used by the Rewriter. Otherwise, VLAN_POP_CNT from + *   ANA:PORT:VLAN_CFG.VLAN_POP_CNT is used   */  /* Actionfield names */ @@ -712,11 +802,13 @@ enum vcap_action_field {  	VCAP_AF_CPU_COPY_ENA,  	VCAP_AF_CPU_QU,  	VCAP_AF_CPU_QUEUE_NUM, +	VCAP_AF_CUSTOM_ACE_TYPE_ENA,  	VCAP_AF_DEI_A_VAL,  	VCAP_AF_DEI_B_VAL,  	VCAP_AF_DEI_C_VAL,  	VCAP_AF_DEI_ENA,  	VCAP_AF_DEI_VAL, +	VCAP_AF_DLR_SEL,  	VCAP_AF_DP_ENA,  	VCAP_AF_DP_VAL,  	VCAP_AF_DSCP_ENA, @@ -732,7 +824,9 @@ enum vcap_action_field {  	VCAP_AF_IGNORE_PIPELINE_CTRL,  	VCAP_AF_INTR_ENA,  	VCAP_AF_ISDX_ADD_REPLACE_SEL, +	VCAP_AF_ISDX_ADD_VAL,  	VCAP_AF_ISDX_ENA, +	VCAP_AF_ISDX_REPLACE_ENA,  	VCAP_AF_ISDX_VAL,  	VCAP_AF_LOOP_ENA,  	VCAP_AF_LRN_DIS, @@ -745,8 +839,10 @@ enum vcap_action_field {  	VCAP_AF_MIRROR_ENA,  	VCAP_AF_MIRROR_PROBE,  	VCAP_AF_MIRROR_PROBE_ID, +	VCAP_AF_MRP_SEL,  	VCAP_AF_NXT_IDX,  	VCAP_AF_NXT_IDX_CTRL, +	VCAP_AF_OAM_SEL,  	VCAP_AF_PAG_OVERRIDE_MASK,  	VCAP_AF_PAG_VAL,  	VCAP_AF_PCP_A_VAL, @@ -770,6 +866,10 @@ enum vcap_action_field {  	VCAP_AF_QOS_VAL,  	VCAP_AF_REW_OP,  	VCAP_AF_RT_DIS, +	VCAP_AF_SFID_ENA, +	VCAP_AF_SFID_VAL, +	VCAP_AF_SGID_ENA, +	VCAP_AF_SGID_VAL,  	VCAP_AF_SWAP_MACS_ENA,  	VCAP_AF_TAG_A_DEI_SEL,  	VCAP_AF_TAG_A_PCP_SEL, @@ -788,7 +888,10 @@ enum vcap_action_field {  	VCAP_AF_VID_A_VAL,  	VCAP_AF_VID_B_VAL,  	VCAP_AF_VID_C_VAL, +	VCAP_AF_VID_REPLACE_ENA,  	VCAP_AF_VID_VAL, +	VCAP_AF_VLAN_POP_CNT, +	VCAP_AF_VLAN_POP_CNT_ENA,  };  #endif /* __VCAP_AG_API__ */ diff --git a/drivers/net/ethernet/microchip/vcap/vcap_api.c b/drivers/net/ethernet/microchip/vcap/vcap_api.c index 4847d0d99ec9..5675b0962bc3 100644 --- a/drivers/net/ethernet/microchip/vcap/vcap_api.c +++ b/drivers/net/ethernet/microchip/vcap/vcap_api.c @@ -976,6 +976,25 @@ int vcap_lookup_rule_by_cookie(struct vcap_control *vctrl, u64 cookie)  }  EXPORT_SYMBOL_GPL(vcap_lookup_rule_by_cookie); +/* Get number of rules in a vcap instance lookup chain id range */ +int vcap_admin_rule_count(struct vcap_admin *admin, int cid) +{ +	int max_cid = roundup(cid + 1, VCAP_CID_LOOKUP_SIZE); +	int min_cid = rounddown(cid, VCAP_CID_LOOKUP_SIZE); +	struct vcap_rule_internal *elem; +	int count = 0; + +	list_for_each_entry(elem, &admin->rules, list) { +		mutex_lock(&admin->lock); +		if (elem->data.vcap_chain_id >= min_cid && +		    elem->data.vcap_chain_id < max_cid) +			++count; +		mutex_unlock(&admin->lock); +	} +	return count; +} +EXPORT_SYMBOL_GPL(vcap_admin_rule_count); +  /* Make a copy of the rule, shallow or full */  static struct vcap_rule_internal *vcap_dup_rule(struct vcap_rule_internal *ri,  						bool full) @@ -3403,6 +3422,25 @@ int vcap_rule_mod_key_u32(struct vcap_rule *rule, enum vcap_key_field key,  }  EXPORT_SYMBOL_GPL(vcap_rule_mod_key_u32); +/* Remove a key field with value and mask in the rule */ +int vcap_rule_rem_key(struct vcap_rule *rule, enum vcap_key_field key) +{ +	struct vcap_rule_internal *ri = to_intrule(rule); +	struct vcap_client_keyfield *field; + +	field = vcap_find_keyfield(rule, key); +	if (!field) { +		pr_err("%s:%d: key %s is not in the rule\n", +		       __func__, __LINE__, vcap_keyfield_name(ri->vctrl, key)); +		return -EINVAL; +	} +	/* Deallocate the key field */ +	list_del(&field->ctrl.list); +	kfree(field); +	return 0; +} +EXPORT_SYMBOL_GPL(vcap_rule_rem_key); +  static int vcap_rule_mod_action(struct vcap_rule *rule,  				enum vcap_action_field action,  				enum vcap_field_type ftype, @@ -3475,6 +3513,29 @@ int vcap_filter_rule_keys(struct vcap_rule *rule,  }  EXPORT_SYMBOL_GPL(vcap_filter_rule_keys); +/* Select the keyset from the list that results in the smallest rule size */ +enum vcap_keyfield_set +vcap_select_min_rule_keyset(struct vcap_control *vctrl, +			    enum vcap_type vtype, +			    struct vcap_keyset_list *kslist) +{ +	enum vcap_keyfield_set ret = VCAP_KFS_NO_VALUE; +	const struct vcap_set *kset; +	int max = 100, idx; + +	for (idx = 0; idx < kslist->cnt; ++idx) { +		kset = vcap_keyfieldset(vctrl, vtype, kslist->keysets[idx]); +		if (!kset) +			continue; +		if (kset->sw_per_item >= max) +			continue; +		max = kset->sw_per_item; +		ret = kslist->keysets[idx]; +	} +	return ret; +} +EXPORT_SYMBOL_GPL(vcap_select_min_rule_keyset); +  /* Make a full copy of an existing rule with a new rule id */  struct vcap_rule *vcap_copy_rule(struct vcap_rule *erule)  { diff --git a/drivers/net/ethernet/microchip/vcap/vcap_api_client.h b/drivers/net/ethernet/microchip/vcap/vcap_api_client.h index 417af9754bcc..d9d1f7c9d762 100644 --- a/drivers/net/ethernet/microchip/vcap/vcap_api_client.h +++ b/drivers/net/ethernet/microchip/vcap/vcap_api_client.h @@ -201,6 +201,9 @@ int vcap_rule_add_action_bit(struct vcap_rule *rule,  int vcap_rule_add_action_u32(struct vcap_rule *rule,  			     enum vcap_action_field action, u32 value); +/* Get number of rules in a vcap instance lookup chain id range */ +int vcap_admin_rule_count(struct vcap_admin *admin, int cid); +  /* VCAP rule counter operations */  int vcap_get_rule_count_by_cookie(struct vcap_control *vctrl,  				  struct vcap_counter *ctr, u64 cookie); @@ -269,6 +272,14 @@ int vcap_rule_mod_action_u32(struct vcap_rule *rule,  int vcap_rule_get_key_u32(struct vcap_rule *rule, enum vcap_key_field key,  			  u32 *value, u32 *mask); +/* Remove a key field with value and mask in the rule */ +int vcap_rule_rem_key(struct vcap_rule *rule, enum vcap_key_field key); + +/* Select the keyset from the list that results in the smallest rule size */ +enum vcap_keyfield_set +vcap_select_min_rule_keyset(struct vcap_control *vctrl, enum vcap_type vtype, +			    struct vcap_keyset_list *kslist); +  struct vcap_client_actionfield *  vcap_find_actionfield(struct vcap_rule *rule, enum vcap_action_field act);  #endif /* __VCAP_API_CLIENT__ */ diff --git a/drivers/net/ethernet/microchip/vcap/vcap_api_debugfs_kunit.c b/drivers/net/ethernet/microchip/vcap/vcap_api_debugfs_kunit.c index 0de3f677135a..b23c11b0647c 100644 --- a/drivers/net/ethernet/microchip/vcap/vcap_api_debugfs_kunit.c +++ b/drivers/net/ethernet/microchip/vcap/vcap_api_debugfs_kunit.c @@ -387,7 +387,7 @@ static const char * const test_admin_info_expect[] = {  	"default_cnt: 73\n",  	"require_cnt_dis: 0\n",  	"version: 1\n", -	"vtype: 3\n", +	"vtype: 4\n",  	"vinst: 0\n",  	"ingress: 1\n",  	"first_cid: 10000\n", @@ -435,7 +435,7 @@ static const char * const test_admin_expect[] = {  	"default_cnt: 73\n",  	"require_cnt_dis: 0\n",  	"version: 1\n", -	"vtype: 3\n", +	"vtype: 4\n",  	"vinst: 0\n",  	"ingress: 1\n",  	"first_cid: 8000000\n",  |