19c20346bSAnirudh Venkataramanan // SPDX-License-Identifier: GPL-2.0
29c20346bSAnirudh Venkataramanan /* Copyright (c) 2018, Intel Corporation. */
39c20346bSAnirudh Venkataramanan 
4348048e7SDave Ertman #include "ice_lib.h"
59c20346bSAnirudh Venkataramanan #include "ice_switch.h"
69c20346bSAnirudh Venkataramanan 
79daf8208SAnirudh Venkataramanan #define ICE_ETH_DA_OFFSET		0
89daf8208SAnirudh Venkataramanan #define ICE_ETH_ETHTYPE_OFFSET		12
99daf8208SAnirudh Venkataramanan #define ICE_ETH_VLAN_TCI_OFFSET		14
109daf8208SAnirudh Venkataramanan #define ICE_MAX_VLAN_ID			0xFFF
110f94570dSGrishma Kotecha #define ICE_IPV6_ETHER_ID		0x86DD
129daf8208SAnirudh Venkataramanan 
139daf8208SAnirudh Venkataramanan /* Dummy ethernet header needed in the ice_aqc_sw_rules_elem
149daf8208SAnirudh Venkataramanan  * struct to configure any switch filter rules.
159daf8208SAnirudh Venkataramanan  * {DA (6 bytes), SA(6 bytes),
169daf8208SAnirudh Venkataramanan  * Ether type (2 bytes for header without VLAN tag) OR
179daf8208SAnirudh Venkataramanan  * VLAN tag (4 bytes for header with VLAN tag) }
189daf8208SAnirudh Venkataramanan  *
199daf8208SAnirudh Venkataramanan  * Word on Hardcoded values
209daf8208SAnirudh Venkataramanan  * byte 0 = 0x2: to identify it as locally administered DA MAC
219daf8208SAnirudh Venkataramanan  * byte 6 = 0x2: to identify it as locally administered SA MAC
229daf8208SAnirudh Venkataramanan  * byte 12 = 0x81 & byte 13 = 0x00:
239daf8208SAnirudh Venkataramanan  *	In case of VLAN filter first two bytes defines ether type (0x8100)
24f9867df6SAnirudh Venkataramanan  *	and remaining two bytes are placeholder for programming a given VLAN ID
259daf8208SAnirudh Venkataramanan  *	In case of Ether type filter it is treated as header without VLAN tag
269daf8208SAnirudh Venkataramanan  *	and byte 12 and 13 is used to program a given Ether type instead
279daf8208SAnirudh Venkataramanan  */
289daf8208SAnirudh Venkataramanan #define DUMMY_ETH_HDR_LEN		16
299daf8208SAnirudh Venkataramanan static const u8 dummy_eth_header[DUMMY_ETH_HDR_LEN] = { 0x2, 0, 0, 0, 0, 0,
309daf8208SAnirudh Venkataramanan 							0x2, 0, 0, 0, 0, 0,
319daf8208SAnirudh Venkataramanan 							0x81, 0, 0, 0};
329daf8208SAnirudh Venkataramanan 
33e33163a4SAlexander Lobakin enum {
3426395726SMartyna Szapar-Mudlaw 	ICE_PKT_OUTER_IPV6	= BIT(0),
3526395726SMartyna Szapar-Mudlaw 	ICE_PKT_TUN_GTPC	= BIT(1),
3626395726SMartyna Szapar-Mudlaw 	ICE_PKT_TUN_GTPU	= BIT(2),
3726395726SMartyna Szapar-Mudlaw 	ICE_PKT_TUN_NVGRE	= BIT(3),
3826395726SMartyna Szapar-Mudlaw 	ICE_PKT_TUN_UDP		= BIT(4),
3926395726SMartyna Szapar-Mudlaw 	ICE_PKT_INNER_IPV6	= BIT(5),
4026395726SMartyna Szapar-Mudlaw 	ICE_PKT_INNER_TCP	= BIT(6),
4126395726SMartyna Szapar-Mudlaw 	ICE_PKT_INNER_UDP	= BIT(7),
4226395726SMartyna Szapar-Mudlaw 	ICE_PKT_GTP_NOPAY	= BIT(8),
4326395726SMartyna Szapar-Mudlaw 	ICE_PKT_KMALLOC		= BIT(9),
44cd8efeeeSMarcin Szycik 	ICE_PKT_PPPOE		= BIT(10),
45e33163a4SAlexander Lobakin };
46e33163a4SAlexander Lobakin 
470f94570dSGrishma Kotecha struct ice_dummy_pkt_offsets {
480f94570dSGrishma Kotecha 	enum ice_protocol_type type;
490f94570dSGrishma Kotecha 	u16 offset; /* ICE_PROTOCOL_LAST indicates end of list */
500f94570dSGrishma Kotecha };
510f94570dSGrishma Kotecha 
521b699f81SAlexander Lobakin struct ice_dummy_pkt_profile {
531b699f81SAlexander Lobakin 	const struct ice_dummy_pkt_offsets *offsets;
541b699f81SAlexander Lobakin 	const u8 *pkt;
55e33163a4SAlexander Lobakin 	u32 match;
561b699f81SAlexander Lobakin 	u16 pkt_len;
5726395726SMartyna Szapar-Mudlaw 	u16 offsets_len;
581b699f81SAlexander Lobakin };
591b699f81SAlexander Lobakin 
6007a28842SAlexander Lobakin #define ICE_DECLARE_PKT_OFFSETS(type)					\
6107a28842SAlexander Lobakin 	static const struct ice_dummy_pkt_offsets			\
6207a28842SAlexander Lobakin 	ice_dummy_##type##_packet_offsets[]
6307a28842SAlexander Lobakin 
6407a28842SAlexander Lobakin #define ICE_DECLARE_PKT_TEMPLATE(type)					\
6507a28842SAlexander Lobakin 	static const u8 ice_dummy_##type##_packet[]
6607a28842SAlexander Lobakin 
67e33163a4SAlexander Lobakin #define ICE_PKT_PROFILE(type, m) {					\
68e33163a4SAlexander Lobakin 	.match		= (m),						\
6907a28842SAlexander Lobakin 	.pkt		= ice_dummy_##type##_packet,			\
7007a28842SAlexander Lobakin 	.pkt_len	= sizeof(ice_dummy_##type##_packet),		\
7107a28842SAlexander Lobakin 	.offsets	= ice_dummy_##type##_packet_offsets,		\
7226395726SMartyna Szapar-Mudlaw 	.offsets_len	= sizeof(ice_dummy_##type##_packet_offsets),	\
73e33163a4SAlexander Lobakin }
741b699f81SAlexander Lobakin 
7526395726SMartyna Szapar-Mudlaw ICE_DECLARE_PKT_OFFSETS(vlan) = {
7626395726SMartyna Szapar-Mudlaw 	{ ICE_VLAN_OFOS,        12 },
7726395726SMartyna Szapar-Mudlaw };
7826395726SMartyna Szapar-Mudlaw 
7926395726SMartyna Szapar-Mudlaw ICE_DECLARE_PKT_TEMPLATE(vlan) = {
8026395726SMartyna Szapar-Mudlaw 	0x81, 0x00, 0x00, 0x00, /* ICE_VLAN_OFOS 12 */
8126395726SMartyna Szapar-Mudlaw };
8226395726SMartyna Szapar-Mudlaw 
8326395726SMartyna Szapar-Mudlaw ICE_DECLARE_PKT_OFFSETS(qinq) = {
8426395726SMartyna Szapar-Mudlaw 	{ ICE_VLAN_EX,          12 },
8526395726SMartyna Szapar-Mudlaw 	{ ICE_VLAN_IN,          16 },
8626395726SMartyna Szapar-Mudlaw };
8726395726SMartyna Szapar-Mudlaw 
8826395726SMartyna Szapar-Mudlaw ICE_DECLARE_PKT_TEMPLATE(qinq) = {
8926395726SMartyna Szapar-Mudlaw 	0x91, 0x00, 0x00, 0x00, /* ICE_VLAN_EX 12 */
9026395726SMartyna Szapar-Mudlaw 	0x81, 0x00, 0x00, 0x00, /* ICE_VLAN_IN 16 */
9126395726SMartyna Szapar-Mudlaw };
9226395726SMartyna Szapar-Mudlaw 
9307a28842SAlexander Lobakin ICE_DECLARE_PKT_OFFSETS(gre_tcp) = {
94f0a35040SMichal Swiatkowski 	{ ICE_MAC_OFOS,		0 },
95f0a35040SMichal Swiatkowski 	{ ICE_ETYPE_OL,		12 },
96f0a35040SMichal Swiatkowski 	{ ICE_IPV4_OFOS,	14 },
97f0a35040SMichal Swiatkowski 	{ ICE_NVGRE,		34 },
98f0a35040SMichal Swiatkowski 	{ ICE_MAC_IL,		42 },
9934a89775SMartyna Szapar-Mudlaw 	{ ICE_ETYPE_IL,		54 },
100f0a35040SMichal Swiatkowski 	{ ICE_IPV4_IL,		56 },
101f0a35040SMichal Swiatkowski 	{ ICE_TCP_IL,		76 },
102f0a35040SMichal Swiatkowski 	{ ICE_PROTOCOL_LAST,	0 },
103f0a35040SMichal Swiatkowski };
104f0a35040SMichal Swiatkowski 
10507a28842SAlexander Lobakin ICE_DECLARE_PKT_TEMPLATE(gre_tcp) = {
106f0a35040SMichal Swiatkowski 	0x00, 0x00, 0x00, 0x00,	/* ICE_MAC_OFOS 0 */
107f0a35040SMichal Swiatkowski 	0x00, 0x00, 0x00, 0x00,
108f0a35040SMichal Swiatkowski 	0x00, 0x00, 0x00, 0x00,
109f0a35040SMichal Swiatkowski 
110f0a35040SMichal Swiatkowski 	0x08, 0x00,		/* ICE_ETYPE_OL 12 */
111f0a35040SMichal Swiatkowski 
112f0a35040SMichal Swiatkowski 	0x45, 0x00, 0x00, 0x3E,	/* ICE_IPV4_OFOS 14 */
113f0a35040SMichal Swiatkowski 	0x00, 0x00, 0x00, 0x00,
114f0a35040SMichal Swiatkowski 	0x00, 0x2F, 0x00, 0x00,
115f0a35040SMichal Swiatkowski 	0x00, 0x00, 0x00, 0x00,
116f0a35040SMichal Swiatkowski 	0x00, 0x00, 0x00, 0x00,
117f0a35040SMichal Swiatkowski 
118f0a35040SMichal Swiatkowski 	0x80, 0x00, 0x65, 0x58,	/* ICE_NVGRE 34 */
119f0a35040SMichal Swiatkowski 	0x00, 0x00, 0x00, 0x00,
120f0a35040SMichal Swiatkowski 
121f0a35040SMichal Swiatkowski 	0x00, 0x00, 0x00, 0x00,	/* ICE_MAC_IL 42 */
122f0a35040SMichal Swiatkowski 	0x00, 0x00, 0x00, 0x00,
123f0a35040SMichal Swiatkowski 	0x00, 0x00, 0x00, 0x00,
12434a89775SMartyna Szapar-Mudlaw 
12534a89775SMartyna Szapar-Mudlaw 	0x08, 0x00,		/* ICE_ETYPE_IL 54 */
126f0a35040SMichal Swiatkowski 
127f0a35040SMichal Swiatkowski 	0x45, 0x00, 0x00, 0x14,	/* ICE_IPV4_IL 56 */
128f0a35040SMichal Swiatkowski 	0x00, 0x00, 0x00, 0x00,
129f0a35040SMichal Swiatkowski 	0x00, 0x06, 0x00, 0x00,
130f0a35040SMichal Swiatkowski 	0x00, 0x00, 0x00, 0x00,
131f0a35040SMichal Swiatkowski 	0x00, 0x00, 0x00, 0x00,
132f0a35040SMichal Swiatkowski 
133f0a35040SMichal Swiatkowski 	0x00, 0x00, 0x00, 0x00,	/* ICE_TCP_IL 76 */
134f0a35040SMichal Swiatkowski 	0x00, 0x00, 0x00, 0x00,
135f0a35040SMichal Swiatkowski 	0x00, 0x00, 0x00, 0x00,
136f0a35040SMichal Swiatkowski 	0x50, 0x02, 0x20, 0x00,
137f0a35040SMichal Swiatkowski 	0x00, 0x00, 0x00, 0x00
138f0a35040SMichal Swiatkowski };
139f0a35040SMichal Swiatkowski 
14007a28842SAlexander Lobakin ICE_DECLARE_PKT_OFFSETS(gre_udp) = {
141f0a35040SMichal Swiatkowski 	{ ICE_MAC_OFOS,		0 },
142f0a35040SMichal Swiatkowski 	{ ICE_ETYPE_OL,		12 },
143f0a35040SMichal Swiatkowski 	{ ICE_IPV4_OFOS,	14 },
144f0a35040SMichal Swiatkowski 	{ ICE_NVGRE,		34 },
145f0a35040SMichal Swiatkowski 	{ ICE_MAC_IL,		42 },
14634a89775SMartyna Szapar-Mudlaw 	{ ICE_ETYPE_IL,		54 },
147f0a35040SMichal Swiatkowski 	{ ICE_IPV4_IL,		56 },
148f0a35040SMichal Swiatkowski 	{ ICE_UDP_ILOS,		76 },
149f0a35040SMichal Swiatkowski 	{ ICE_PROTOCOL_LAST,	0 },
150f0a35040SMichal Swiatkowski };
151f0a35040SMichal Swiatkowski 
15207a28842SAlexander Lobakin ICE_DECLARE_PKT_TEMPLATE(gre_udp) = {
153f0a35040SMichal Swiatkowski 	0x00, 0x00, 0x00, 0x00,	/* ICE_MAC_OFOS 0 */
154f0a35040SMichal Swiatkowski 	0x00, 0x00, 0x00, 0x00,
155f0a35040SMichal Swiatkowski 	0x00, 0x00, 0x00, 0x00,
156f0a35040SMichal Swiatkowski 
157f0a35040SMichal Swiatkowski 	0x08, 0x00,		/* ICE_ETYPE_OL 12 */
158f0a35040SMichal Swiatkowski 
159f0a35040SMichal Swiatkowski 	0x45, 0x00, 0x00, 0x3E,	/* ICE_IPV4_OFOS 14 */
160f0a35040SMichal Swiatkowski 	0x00, 0x00, 0x00, 0x00,
161f0a35040SMichal Swiatkowski 	0x00, 0x2F, 0x00, 0x00,
162f0a35040SMichal Swiatkowski 	0x00, 0x00, 0x00, 0x00,
163f0a35040SMichal Swiatkowski 	0x00, 0x00, 0x00, 0x00,
164f0a35040SMichal Swiatkowski 
165f0a35040SMichal Swiatkowski 	0x80, 0x00, 0x65, 0x58,	/* ICE_NVGRE 34 */
166f0a35040SMichal Swiatkowski 	0x00, 0x00, 0x00, 0x00,
167f0a35040SMichal Swiatkowski 
168f0a35040SMichal Swiatkowski 	0x00, 0x00, 0x00, 0x00,	/* ICE_MAC_IL 42 */
169f0a35040SMichal Swiatkowski 	0x00, 0x00, 0x00, 0x00,
170f0a35040SMichal Swiatkowski 	0x00, 0x00, 0x00, 0x00,
17134a89775SMartyna Szapar-Mudlaw 
17234a89775SMartyna Szapar-Mudlaw 	0x08, 0x00,		/* ICE_ETYPE_IL 54 */
173f0a35040SMichal Swiatkowski 
174f0a35040SMichal Swiatkowski 	0x45, 0x00, 0x00, 0x14,	/* ICE_IPV4_IL 56 */
175f0a35040SMichal Swiatkowski 	0x00, 0x00, 0x00, 0x00,
176f0a35040SMichal Swiatkowski 	0x00, 0x11, 0x00, 0x00,
177f0a35040SMichal Swiatkowski 	0x00, 0x00, 0x00, 0x00,
178f0a35040SMichal Swiatkowski 	0x00, 0x00, 0x00, 0x00,
179f0a35040SMichal Swiatkowski 
180f0a35040SMichal Swiatkowski 	0x00, 0x00, 0x00, 0x00,	/* ICE_UDP_ILOS 76 */
181f0a35040SMichal Swiatkowski 	0x00, 0x08, 0x00, 0x00,
182f0a35040SMichal Swiatkowski };
183f0a35040SMichal Swiatkowski 
18407a28842SAlexander Lobakin ICE_DECLARE_PKT_OFFSETS(udp_tun_tcp) = {
1858b032a55SMichal Swiatkowski 	{ ICE_MAC_OFOS,		0 },
1868b032a55SMichal Swiatkowski 	{ ICE_ETYPE_OL,		12 },
1878b032a55SMichal Swiatkowski 	{ ICE_IPV4_OFOS,	14 },
1888b032a55SMichal Swiatkowski 	{ ICE_UDP_OF,		34 },
1898b032a55SMichal Swiatkowski 	{ ICE_VXLAN,		42 },
1908b032a55SMichal Swiatkowski 	{ ICE_GENEVE,		42 },
1918b032a55SMichal Swiatkowski 	{ ICE_VXLAN_GPE,	42 },
1928b032a55SMichal Swiatkowski 	{ ICE_MAC_IL,		50 },
19334a89775SMartyna Szapar-Mudlaw 	{ ICE_ETYPE_IL,		62 },
1948b032a55SMichal Swiatkowski 	{ ICE_IPV4_IL,		64 },
1958b032a55SMichal Swiatkowski 	{ ICE_TCP_IL,		84 },
1968b032a55SMichal Swiatkowski 	{ ICE_PROTOCOL_LAST,	0 },
1978b032a55SMichal Swiatkowski };
1988b032a55SMichal Swiatkowski 
19907a28842SAlexander Lobakin ICE_DECLARE_PKT_TEMPLATE(udp_tun_tcp) = {
2008b032a55SMichal Swiatkowski 	0x00, 0x00, 0x00, 0x00,  /* ICE_MAC_OFOS 0 */
2018b032a55SMichal Swiatkowski 	0x00, 0x00, 0x00, 0x00,
2028b032a55SMichal Swiatkowski 	0x00, 0x00, 0x00, 0x00,
2038b032a55SMichal Swiatkowski 
2048b032a55SMichal Swiatkowski 	0x08, 0x00,		/* ICE_ETYPE_OL 12 */
2058b032a55SMichal Swiatkowski 
2068b032a55SMichal Swiatkowski 	0x45, 0x00, 0x00, 0x5a, /* ICE_IPV4_OFOS 14 */
2078b032a55SMichal Swiatkowski 	0x00, 0x01, 0x00, 0x00,
2088b032a55SMichal Swiatkowski 	0x40, 0x11, 0x00, 0x00,
2098b032a55SMichal Swiatkowski 	0x00, 0x00, 0x00, 0x00,
2108b032a55SMichal Swiatkowski 	0x00, 0x00, 0x00, 0x00,
2118b032a55SMichal Swiatkowski 
2128b032a55SMichal Swiatkowski 	0x00, 0x00, 0x12, 0xb5, /* ICE_UDP_OF 34 */
2138b032a55SMichal Swiatkowski 	0x00, 0x46, 0x00, 0x00,
2148b032a55SMichal Swiatkowski 
2158b032a55SMichal Swiatkowski 	0x00, 0x00, 0x65, 0x58, /* ICE_VXLAN 42 */
2168b032a55SMichal Swiatkowski 	0x00, 0x00, 0x00, 0x00,
2178b032a55SMichal Swiatkowski 
2188b032a55SMichal Swiatkowski 	0x00, 0x00, 0x00, 0x00, /* ICE_MAC_IL 50 */
2198b032a55SMichal Swiatkowski 	0x00, 0x00, 0x00, 0x00,
2208b032a55SMichal Swiatkowski 	0x00, 0x00, 0x00, 0x00,
22134a89775SMartyna Szapar-Mudlaw 
22234a89775SMartyna Szapar-Mudlaw 	0x08, 0x00,		/* ICE_ETYPE_IL 62 */
2238b032a55SMichal Swiatkowski 
2248b032a55SMichal Swiatkowski 	0x45, 0x00, 0x00, 0x28, /* ICE_IPV4_IL 64 */
2258b032a55SMichal Swiatkowski 	0x00, 0x01, 0x00, 0x00,
2268b032a55SMichal Swiatkowski 	0x40, 0x06, 0x00, 0x00,
2278b032a55SMichal Swiatkowski 	0x00, 0x00, 0x00, 0x00,
2288b032a55SMichal Swiatkowski 	0x00, 0x00, 0x00, 0x00,
2298b032a55SMichal Swiatkowski 
2308b032a55SMichal Swiatkowski 	0x00, 0x00, 0x00, 0x00, /* ICE_TCP_IL 84 */
2318b032a55SMichal Swiatkowski 	0x00, 0x00, 0x00, 0x00,
2328b032a55SMichal Swiatkowski 	0x00, 0x00, 0x00, 0x00,
2338b032a55SMichal Swiatkowski 	0x50, 0x02, 0x20, 0x00,
2348b032a55SMichal Swiatkowski 	0x00, 0x00, 0x00, 0x00
2358b032a55SMichal Swiatkowski };
2368b032a55SMichal Swiatkowski 
23707a28842SAlexander Lobakin ICE_DECLARE_PKT_OFFSETS(udp_tun_udp) = {
2388b032a55SMichal Swiatkowski 	{ ICE_MAC_OFOS,		0 },
2398b032a55SMichal Swiatkowski 	{ ICE_ETYPE_OL,		12 },
2408b032a55SMichal Swiatkowski 	{ ICE_IPV4_OFOS,	14 },
2418b032a55SMichal Swiatkowski 	{ ICE_UDP_OF,		34 },
2428b032a55SMichal Swiatkowski 	{ ICE_VXLAN,		42 },
2438b032a55SMichal Swiatkowski 	{ ICE_GENEVE,		42 },
2448b032a55SMichal Swiatkowski 	{ ICE_VXLAN_GPE,	42 },
2458b032a55SMichal Swiatkowski 	{ ICE_MAC_IL,		50 },
24634a89775SMartyna Szapar-Mudlaw 	{ ICE_ETYPE_IL,		62 },
2478b032a55SMichal Swiatkowski 	{ ICE_IPV4_IL,		64 },
2488b032a55SMichal Swiatkowski 	{ ICE_UDP_ILOS,		84 },
2498b032a55SMichal Swiatkowski 	{ ICE_PROTOCOL_LAST,	0 },
2508b032a55SMichal Swiatkowski };
2518b032a55SMichal Swiatkowski 
25207a28842SAlexander Lobakin ICE_DECLARE_PKT_TEMPLATE(udp_tun_udp) = {
2538b032a55SMichal Swiatkowski 	0x00, 0x00, 0x00, 0x00,  /* ICE_MAC_OFOS 0 */
2548b032a55SMichal Swiatkowski 	0x00, 0x00, 0x00, 0x00,
2558b032a55SMichal Swiatkowski 	0x00, 0x00, 0x00, 0x00,
2568b032a55SMichal Swiatkowski 
2578b032a55SMichal Swiatkowski 	0x08, 0x00,		/* ICE_ETYPE_OL 12 */
2588b032a55SMichal Swiatkowski 
2598b032a55SMichal Swiatkowski 	0x45, 0x00, 0x00, 0x4e, /* ICE_IPV4_OFOS 14 */
2608b032a55SMichal Swiatkowski 	0x00, 0x01, 0x00, 0x00,
2618b032a55SMichal Swiatkowski 	0x00, 0x11, 0x00, 0x00,
2628b032a55SMichal Swiatkowski 	0x00, 0x00, 0x00, 0x00,
2638b032a55SMichal Swiatkowski 	0x00, 0x00, 0x00, 0x00,
2648b032a55SMichal Swiatkowski 
2658b032a55SMichal Swiatkowski 	0x00, 0x00, 0x12, 0xb5, /* ICE_UDP_OF 34 */
2668b032a55SMichal Swiatkowski 	0x00, 0x3a, 0x00, 0x00,
2678b032a55SMichal Swiatkowski 
2688b032a55SMichal Swiatkowski 	0x00, 0x00, 0x65, 0x58, /* ICE_VXLAN 42 */
2698b032a55SMichal Swiatkowski 	0x00, 0x00, 0x00, 0x00,
2708b032a55SMichal Swiatkowski 
2718b032a55SMichal Swiatkowski 	0x00, 0x00, 0x00, 0x00, /* ICE_MAC_IL 50 */
2728b032a55SMichal Swiatkowski 	0x00, 0x00, 0x00, 0x00,
2738b032a55SMichal Swiatkowski 	0x00, 0x00, 0x00, 0x00,
27434a89775SMartyna Szapar-Mudlaw 
27534a89775SMartyna Szapar-Mudlaw 	0x08, 0x00,		/* ICE_ETYPE_IL 62 */
2768b032a55SMichal Swiatkowski 
2778b032a55SMichal Swiatkowski 	0x45, 0x00, 0x00, 0x1c, /* ICE_IPV4_IL 64 */
2788b032a55SMichal Swiatkowski 	0x00, 0x01, 0x00, 0x00,
2798b032a55SMichal Swiatkowski 	0x00, 0x11, 0x00, 0x00,
2808b032a55SMichal Swiatkowski 	0x00, 0x00, 0x00, 0x00,
2818b032a55SMichal Swiatkowski 	0x00, 0x00, 0x00, 0x00,
2828b032a55SMichal Swiatkowski 
2838b032a55SMichal Swiatkowski 	0x00, 0x00, 0x00, 0x00, /* ICE_UDP_ILOS 84 */
2848b032a55SMichal Swiatkowski 	0x00, 0x08, 0x00, 0x00,
2858b032a55SMichal Swiatkowski };
2868b032a55SMichal Swiatkowski 
28707a28842SAlexander Lobakin ICE_DECLARE_PKT_OFFSETS(gre_ipv6_tcp) = {
28834a89775SMartyna Szapar-Mudlaw 	{ ICE_MAC_OFOS,		0 },
28934a89775SMartyna Szapar-Mudlaw 	{ ICE_ETYPE_OL,		12 },
29034a89775SMartyna Szapar-Mudlaw 	{ ICE_IPV4_OFOS,	14 },
29134a89775SMartyna Szapar-Mudlaw 	{ ICE_NVGRE,		34 },
29234a89775SMartyna Szapar-Mudlaw 	{ ICE_MAC_IL,		42 },
29334a89775SMartyna Szapar-Mudlaw 	{ ICE_ETYPE_IL,		54 },
29434a89775SMartyna Szapar-Mudlaw 	{ ICE_IPV6_IL,		56 },
29534a89775SMartyna Szapar-Mudlaw 	{ ICE_TCP_IL,		96 },
29634a89775SMartyna Szapar-Mudlaw 	{ ICE_PROTOCOL_LAST,	0 },
29734a89775SMartyna Szapar-Mudlaw };
29834a89775SMartyna Szapar-Mudlaw 
29907a28842SAlexander Lobakin ICE_DECLARE_PKT_TEMPLATE(gre_ipv6_tcp) = {
30034a89775SMartyna Szapar-Mudlaw 	0x00, 0x00, 0x00, 0x00, /* ICE_MAC_OFOS 0 */
30134a89775SMartyna Szapar-Mudlaw 	0x00, 0x00, 0x00, 0x00,
30234a89775SMartyna Szapar-Mudlaw 	0x00, 0x00, 0x00, 0x00,
30334a89775SMartyna Szapar-Mudlaw 
30434a89775SMartyna Szapar-Mudlaw 	0x08, 0x00,		/* ICE_ETYPE_OL 12 */
30534a89775SMartyna Szapar-Mudlaw 
30634a89775SMartyna Szapar-Mudlaw 	0x45, 0x00, 0x00, 0x66, /* ICE_IPV4_OFOS 14 */
30734a89775SMartyna Szapar-Mudlaw 	0x00, 0x00, 0x00, 0x00,
30834a89775SMartyna Szapar-Mudlaw 	0x00, 0x2F, 0x00, 0x00,
30934a89775SMartyna Szapar-Mudlaw 	0x00, 0x00, 0x00, 0x00,
31034a89775SMartyna Szapar-Mudlaw 	0x00, 0x00, 0x00, 0x00,
31134a89775SMartyna Szapar-Mudlaw 
31234a89775SMartyna Szapar-Mudlaw 	0x80, 0x00, 0x65, 0x58, /* ICE_NVGRE 34 */
31334a89775SMartyna Szapar-Mudlaw 	0x00, 0x00, 0x00, 0x00,
31434a89775SMartyna Szapar-Mudlaw 
31534a89775SMartyna Szapar-Mudlaw 	0x00, 0x00, 0x00, 0x00, /* ICE_MAC_IL 42 */
31634a89775SMartyna Szapar-Mudlaw 	0x00, 0x00, 0x00, 0x00,
31734a89775SMartyna Szapar-Mudlaw 	0x00, 0x00, 0x00, 0x00,
31834a89775SMartyna Szapar-Mudlaw 
31934a89775SMartyna Szapar-Mudlaw 	0x86, 0xdd,		/* ICE_ETYPE_IL 54 */
32034a89775SMartyna Szapar-Mudlaw 
32134a89775SMartyna Szapar-Mudlaw 	0x60, 0x00, 0x00, 0x00, /* ICE_IPV6_IL 56 */
32234a89775SMartyna Szapar-Mudlaw 	0x00, 0x08, 0x06, 0x40,
32334a89775SMartyna Szapar-Mudlaw 	0x00, 0x00, 0x00, 0x00,
32434a89775SMartyna Szapar-Mudlaw 	0x00, 0x00, 0x00, 0x00,
32534a89775SMartyna Szapar-Mudlaw 	0x00, 0x00, 0x00, 0x00,
32634a89775SMartyna Szapar-Mudlaw 	0x00, 0x00, 0x00, 0x00,
32734a89775SMartyna Szapar-Mudlaw 	0x00, 0x00, 0x00, 0x00,
32834a89775SMartyna Szapar-Mudlaw 	0x00, 0x00, 0x00, 0x00,
32934a89775SMartyna Szapar-Mudlaw 	0x00, 0x00, 0x00, 0x00,
33034a89775SMartyna Szapar-Mudlaw 	0x00, 0x00, 0x00, 0x00,
33134a89775SMartyna Szapar-Mudlaw 
33234a89775SMartyna Szapar-Mudlaw 	0x00, 0x00, 0x00, 0x00, /* ICE_TCP_IL 96 */
33334a89775SMartyna Szapar-Mudlaw 	0x00, 0x00, 0x00, 0x00,
33434a89775SMartyna Szapar-Mudlaw 	0x00, 0x00, 0x00, 0x00,
33534a89775SMartyna Szapar-Mudlaw 	0x50, 0x02, 0x20, 0x00,
33634a89775SMartyna Szapar-Mudlaw 	0x00, 0x00, 0x00, 0x00
33734a89775SMartyna Szapar-Mudlaw };
33834a89775SMartyna Szapar-Mudlaw 
33907a28842SAlexander Lobakin ICE_DECLARE_PKT_OFFSETS(gre_ipv6_udp) = {
34034a89775SMartyna Szapar-Mudlaw 	{ ICE_MAC_OFOS,		0 },
34134a89775SMartyna Szapar-Mudlaw 	{ ICE_ETYPE_OL,		12 },
34234a89775SMartyna Szapar-Mudlaw 	{ ICE_IPV4_OFOS,	14 },
34334a89775SMartyna Szapar-Mudlaw 	{ ICE_NVGRE,		34 },
34434a89775SMartyna Szapar-Mudlaw 	{ ICE_MAC_IL,		42 },
34534a89775SMartyna Szapar-Mudlaw 	{ ICE_ETYPE_IL,		54 },
34634a89775SMartyna Szapar-Mudlaw 	{ ICE_IPV6_IL,		56 },
34734a89775SMartyna Szapar-Mudlaw 	{ ICE_UDP_ILOS,		96 },
34834a89775SMartyna Szapar-Mudlaw 	{ ICE_PROTOCOL_LAST,	0 },
34934a89775SMartyna Szapar-Mudlaw };
35034a89775SMartyna Szapar-Mudlaw 
35107a28842SAlexander Lobakin ICE_DECLARE_PKT_TEMPLATE(gre_ipv6_udp) = {
35234a89775SMartyna Szapar-Mudlaw 	0x00, 0x00, 0x00, 0x00, /* ICE_MAC_OFOS 0 */
35334a89775SMartyna Szapar-Mudlaw 	0x00, 0x00, 0x00, 0x00,
35434a89775SMartyna Szapar-Mudlaw 	0x00, 0x00, 0x00, 0x00,
35534a89775SMartyna Szapar-Mudlaw 
35634a89775SMartyna Szapar-Mudlaw 	0x08, 0x00,		/* ICE_ETYPE_OL 12 */
35734a89775SMartyna Szapar-Mudlaw 
35834a89775SMartyna Szapar-Mudlaw 	0x45, 0x00, 0x00, 0x5a, /* ICE_IPV4_OFOS 14 */
35934a89775SMartyna Szapar-Mudlaw 	0x00, 0x00, 0x00, 0x00,
36034a89775SMartyna Szapar-Mudlaw 	0x00, 0x2F, 0x00, 0x00,
36134a89775SMartyna Szapar-Mudlaw 	0x00, 0x00, 0x00, 0x00,
36234a89775SMartyna Szapar-Mudlaw 	0x00, 0x00, 0x00, 0x00,
36334a89775SMartyna Szapar-Mudlaw 
36434a89775SMartyna Szapar-Mudlaw 	0x80, 0x00, 0x65, 0x58, /* ICE_NVGRE 34 */
36534a89775SMartyna Szapar-Mudlaw 	0x00, 0x00, 0x00, 0x00,
36634a89775SMartyna Szapar-Mudlaw 
36734a89775SMartyna Szapar-Mudlaw 	0x00, 0x00, 0x00, 0x00, /* ICE_MAC_IL 42 */
36834a89775SMartyna Szapar-Mudlaw 	0x00, 0x00, 0x00, 0x00,
36934a89775SMartyna Szapar-Mudlaw 	0x00, 0x00, 0x00, 0x00,
37034a89775SMartyna Szapar-Mudlaw 
37134a89775SMartyna Szapar-Mudlaw 	0x86, 0xdd,		/* ICE_ETYPE_IL 54 */
37234a89775SMartyna Szapar-Mudlaw 
37334a89775SMartyna Szapar-Mudlaw 	0x60, 0x00, 0x00, 0x00, /* ICE_IPV6_IL 56 */
37434a89775SMartyna Szapar-Mudlaw 	0x00, 0x08, 0x11, 0x40,
37534a89775SMartyna Szapar-Mudlaw 	0x00, 0x00, 0x00, 0x00,
37634a89775SMartyna Szapar-Mudlaw 	0x00, 0x00, 0x00, 0x00,
37734a89775SMartyna Szapar-Mudlaw 	0x00, 0x00, 0x00, 0x00,
37834a89775SMartyna Szapar-Mudlaw 	0x00, 0x00, 0x00, 0x00,
37934a89775SMartyna Szapar-Mudlaw 	0x00, 0x00, 0x00, 0x00,
38034a89775SMartyna Szapar-Mudlaw 	0x00, 0x00, 0x00, 0x00,
38134a89775SMartyna Szapar-Mudlaw 	0x00, 0x00, 0x00, 0x00,
38234a89775SMartyna Szapar-Mudlaw 	0x00, 0x00, 0x00, 0x00,
38334a89775SMartyna Szapar-Mudlaw 
38434a89775SMartyna Szapar-Mudlaw 	0x00, 0x00, 0x00, 0x00, /* ICE_UDP_ILOS 96 */
38534a89775SMartyna Szapar-Mudlaw 	0x00, 0x08, 0x00, 0x00,
38634a89775SMartyna Szapar-Mudlaw };
38734a89775SMartyna Szapar-Mudlaw 
38807a28842SAlexander Lobakin ICE_DECLARE_PKT_OFFSETS(udp_tun_ipv6_tcp) = {
38934a89775SMartyna Szapar-Mudlaw 	{ ICE_MAC_OFOS,		0 },
39034a89775SMartyna Szapar-Mudlaw 	{ ICE_ETYPE_OL,		12 },
39134a89775SMartyna Szapar-Mudlaw 	{ ICE_IPV4_OFOS,	14 },
39234a89775SMartyna Szapar-Mudlaw 	{ ICE_UDP_OF,		34 },
39334a89775SMartyna Szapar-Mudlaw 	{ ICE_VXLAN,		42 },
39434a89775SMartyna Szapar-Mudlaw 	{ ICE_GENEVE,		42 },
39534a89775SMartyna Szapar-Mudlaw 	{ ICE_VXLAN_GPE,	42 },
39634a89775SMartyna Szapar-Mudlaw 	{ ICE_MAC_IL,		50 },
39734a89775SMartyna Szapar-Mudlaw 	{ ICE_ETYPE_IL,		62 },
39834a89775SMartyna Szapar-Mudlaw 	{ ICE_IPV6_IL,		64 },
39934a89775SMartyna Szapar-Mudlaw 	{ ICE_TCP_IL,		104 },
40034a89775SMartyna Szapar-Mudlaw 	{ ICE_PROTOCOL_LAST,	0 },
40134a89775SMartyna Szapar-Mudlaw };
40234a89775SMartyna Szapar-Mudlaw 
40307a28842SAlexander Lobakin ICE_DECLARE_PKT_TEMPLATE(udp_tun_ipv6_tcp) = {
40434a89775SMartyna Szapar-Mudlaw 	0x00, 0x00, 0x00, 0x00,  /* ICE_MAC_OFOS 0 */
40534a89775SMartyna Szapar-Mudlaw 	0x00, 0x00, 0x00, 0x00,
40634a89775SMartyna Szapar-Mudlaw 	0x00, 0x00, 0x00, 0x00,
40734a89775SMartyna Szapar-Mudlaw 
40834a89775SMartyna Szapar-Mudlaw 	0x08, 0x00,		/* ICE_ETYPE_OL 12 */
40934a89775SMartyna Szapar-Mudlaw 
41034a89775SMartyna Szapar-Mudlaw 	0x45, 0x00, 0x00, 0x6e, /* ICE_IPV4_OFOS 14 */
41134a89775SMartyna Szapar-Mudlaw 	0x00, 0x01, 0x00, 0x00,
41234a89775SMartyna Szapar-Mudlaw 	0x40, 0x11, 0x00, 0x00,
41334a89775SMartyna Szapar-Mudlaw 	0x00, 0x00, 0x00, 0x00,
41434a89775SMartyna Szapar-Mudlaw 	0x00, 0x00, 0x00, 0x00,
41534a89775SMartyna Szapar-Mudlaw 
41634a89775SMartyna Szapar-Mudlaw 	0x00, 0x00, 0x12, 0xb5, /* ICE_UDP_OF 34 */
41734a89775SMartyna Szapar-Mudlaw 	0x00, 0x5a, 0x00, 0x00,
41834a89775SMartyna Szapar-Mudlaw 
41934a89775SMartyna Szapar-Mudlaw 	0x00, 0x00, 0x65, 0x58, /* ICE_VXLAN 42 */
42034a89775SMartyna Szapar-Mudlaw 	0x00, 0x00, 0x00, 0x00,
42134a89775SMartyna Szapar-Mudlaw 
42234a89775SMartyna Szapar-Mudlaw 	0x00, 0x00, 0x00, 0x00, /* ICE_MAC_IL 50 */
42334a89775SMartyna Szapar-Mudlaw 	0x00, 0x00, 0x00, 0x00,
42434a89775SMartyna Szapar-Mudlaw 	0x00, 0x00, 0x00, 0x00,
42534a89775SMartyna Szapar-Mudlaw 
42634a89775SMartyna Szapar-Mudlaw 	0x86, 0xdd,		/* ICE_ETYPE_IL 62 */
42734a89775SMartyna Szapar-Mudlaw 
42834a89775SMartyna Szapar-Mudlaw 	0x60, 0x00, 0x00, 0x00, /* ICE_IPV6_IL 64 */
42934a89775SMartyna Szapar-Mudlaw 	0x00, 0x08, 0x06, 0x40,
43034a89775SMartyna Szapar-Mudlaw 	0x00, 0x00, 0x00, 0x00,
43134a89775SMartyna Szapar-Mudlaw 	0x00, 0x00, 0x00, 0x00,
43234a89775SMartyna Szapar-Mudlaw 	0x00, 0x00, 0x00, 0x00,
43334a89775SMartyna Szapar-Mudlaw 	0x00, 0x00, 0x00, 0x00,
43434a89775SMartyna Szapar-Mudlaw 	0x00, 0x00, 0x00, 0x00,
43534a89775SMartyna Szapar-Mudlaw 	0x00, 0x00, 0x00, 0x00,
43634a89775SMartyna Szapar-Mudlaw 	0x00, 0x00, 0x00, 0x00,
43734a89775SMartyna Szapar-Mudlaw 	0x00, 0x00, 0x00, 0x00,
43834a89775SMartyna Szapar-Mudlaw 
43934a89775SMartyna Szapar-Mudlaw 	0x00, 0x00, 0x00, 0x00, /* ICE_TCP_IL 104 */
44034a89775SMartyna Szapar-Mudlaw 	0x00, 0x00, 0x00, 0x00,
44134a89775SMartyna Szapar-Mudlaw 	0x00, 0x00, 0x00, 0x00,
44234a89775SMartyna Szapar-Mudlaw 	0x50, 0x02, 0x20, 0x00,
44334a89775SMartyna Szapar-Mudlaw 	0x00, 0x00, 0x00, 0x00
44434a89775SMartyna Szapar-Mudlaw };
44534a89775SMartyna Szapar-Mudlaw 
44607a28842SAlexander Lobakin ICE_DECLARE_PKT_OFFSETS(udp_tun_ipv6_udp) = {
44734a89775SMartyna Szapar-Mudlaw 	{ ICE_MAC_OFOS,		0 },
44834a89775SMartyna Szapar-Mudlaw 	{ ICE_ETYPE_OL,		12 },
44934a89775SMartyna Szapar-Mudlaw 	{ ICE_IPV4_OFOS,	14 },
45034a89775SMartyna Szapar-Mudlaw 	{ ICE_UDP_OF,		34 },
45134a89775SMartyna Szapar-Mudlaw 	{ ICE_VXLAN,		42 },
45234a89775SMartyna Szapar-Mudlaw 	{ ICE_GENEVE,		42 },
45334a89775SMartyna Szapar-Mudlaw 	{ ICE_VXLAN_GPE,	42 },
45434a89775SMartyna Szapar-Mudlaw 	{ ICE_MAC_IL,		50 },
45534a89775SMartyna Szapar-Mudlaw 	{ ICE_ETYPE_IL,		62 },
45634a89775SMartyna Szapar-Mudlaw 	{ ICE_IPV6_IL,		64 },
45734a89775SMartyna Szapar-Mudlaw 	{ ICE_UDP_ILOS,		104 },
45834a89775SMartyna Szapar-Mudlaw 	{ ICE_PROTOCOL_LAST,	0 },
45934a89775SMartyna Szapar-Mudlaw };
46034a89775SMartyna Szapar-Mudlaw 
46107a28842SAlexander Lobakin ICE_DECLARE_PKT_TEMPLATE(udp_tun_ipv6_udp) = {
46234a89775SMartyna Szapar-Mudlaw 	0x00, 0x00, 0x00, 0x00,  /* ICE_MAC_OFOS 0 */
46334a89775SMartyna Szapar-Mudlaw 	0x00, 0x00, 0x00, 0x00,
46434a89775SMartyna Szapar-Mudlaw 	0x00, 0x00, 0x00, 0x00,
46534a89775SMartyna Szapar-Mudlaw 
46634a89775SMartyna Szapar-Mudlaw 	0x08, 0x00,		/* ICE_ETYPE_OL 12 */
46734a89775SMartyna Szapar-Mudlaw 
46834a89775SMartyna Szapar-Mudlaw 	0x45, 0x00, 0x00, 0x62, /* ICE_IPV4_OFOS 14 */
46934a89775SMartyna Szapar-Mudlaw 	0x00, 0x01, 0x00, 0x00,
47034a89775SMartyna Szapar-Mudlaw 	0x00, 0x11, 0x00, 0x00,
47134a89775SMartyna Szapar-Mudlaw 	0x00, 0x00, 0x00, 0x00,
47234a89775SMartyna Szapar-Mudlaw 	0x00, 0x00, 0x00, 0x00,
47334a89775SMartyna Szapar-Mudlaw 
47434a89775SMartyna Szapar-Mudlaw 	0x00, 0x00, 0x12, 0xb5, /* ICE_UDP_OF 34 */
47534a89775SMartyna Szapar-Mudlaw 	0x00, 0x4e, 0x00, 0x00,
47634a89775SMartyna Szapar-Mudlaw 
47734a89775SMartyna Szapar-Mudlaw 	0x00, 0x00, 0x65, 0x58, /* ICE_VXLAN 42 */
47834a89775SMartyna Szapar-Mudlaw 	0x00, 0x00, 0x00, 0x00,
47934a89775SMartyna Szapar-Mudlaw 
48034a89775SMartyna Szapar-Mudlaw 	0x00, 0x00, 0x00, 0x00, /* ICE_MAC_IL 50 */
48134a89775SMartyna Szapar-Mudlaw 	0x00, 0x00, 0x00, 0x00,
48234a89775SMartyna Szapar-Mudlaw 	0x00, 0x00, 0x00, 0x00,
48334a89775SMartyna Szapar-Mudlaw 
48434a89775SMartyna Szapar-Mudlaw 	0x86, 0xdd,		/* ICE_ETYPE_IL 62 */
48534a89775SMartyna Szapar-Mudlaw 
48634a89775SMartyna Szapar-Mudlaw 	0x60, 0x00, 0x00, 0x00, /* ICE_IPV6_IL 64 */
48734a89775SMartyna Szapar-Mudlaw 	0x00, 0x08, 0x11, 0x40,
48834a89775SMartyna Szapar-Mudlaw 	0x00, 0x00, 0x00, 0x00,
48934a89775SMartyna Szapar-Mudlaw 	0x00, 0x00, 0x00, 0x00,
49034a89775SMartyna Szapar-Mudlaw 	0x00, 0x00, 0x00, 0x00,
49134a89775SMartyna Szapar-Mudlaw 	0x00, 0x00, 0x00, 0x00,
49234a89775SMartyna Szapar-Mudlaw 	0x00, 0x00, 0x00, 0x00,
49334a89775SMartyna Szapar-Mudlaw 	0x00, 0x00, 0x00, 0x00,
49434a89775SMartyna Szapar-Mudlaw 	0x00, 0x00, 0x00, 0x00,
49534a89775SMartyna Szapar-Mudlaw 	0x00, 0x00, 0x00, 0x00,
49634a89775SMartyna Szapar-Mudlaw 
49734a89775SMartyna Szapar-Mudlaw 	0x00, 0x00, 0x00, 0x00, /* ICE_UDP_ILOS 104 */
49834a89775SMartyna Szapar-Mudlaw 	0x00, 0x08, 0x00, 0x00,
49934a89775SMartyna Szapar-Mudlaw };
50034a89775SMartyna Szapar-Mudlaw 
5010f94570dSGrishma Kotecha /* offset info for MAC + IPv4 + UDP dummy packet */
50207a28842SAlexander Lobakin ICE_DECLARE_PKT_OFFSETS(udp) = {
5030f94570dSGrishma Kotecha 	{ ICE_MAC_OFOS,		0 },
5040f94570dSGrishma Kotecha 	{ ICE_ETYPE_OL,		12 },
5050f94570dSGrishma Kotecha 	{ ICE_IPV4_OFOS,	14 },
5060f94570dSGrishma Kotecha 	{ ICE_UDP_ILOS,		34 },
5070f94570dSGrishma Kotecha 	{ ICE_PROTOCOL_LAST,	0 },
5080f94570dSGrishma Kotecha };
5090f94570dSGrishma Kotecha 
5100f94570dSGrishma Kotecha /* Dummy packet for MAC + IPv4 + UDP */
51107a28842SAlexander Lobakin ICE_DECLARE_PKT_TEMPLATE(udp) = {
5120f94570dSGrishma Kotecha 	0x00, 0x00, 0x00, 0x00, /* ICE_MAC_OFOS 0 */
5130f94570dSGrishma Kotecha 	0x00, 0x00, 0x00, 0x00,
5140f94570dSGrishma Kotecha 	0x00, 0x00, 0x00, 0x00,
5150f94570dSGrishma Kotecha 
5160f94570dSGrishma Kotecha 	0x08, 0x00,		/* ICE_ETYPE_OL 12 */
5170f94570dSGrishma Kotecha 
5180f94570dSGrishma Kotecha 	0x45, 0x00, 0x00, 0x1c, /* ICE_IPV4_OFOS 14 */
5190f94570dSGrishma Kotecha 	0x00, 0x01, 0x00, 0x00,
5200f94570dSGrishma Kotecha 	0x00, 0x11, 0x00, 0x00,
5210f94570dSGrishma Kotecha 	0x00, 0x00, 0x00, 0x00,
5220f94570dSGrishma Kotecha 	0x00, 0x00, 0x00, 0x00,
5230f94570dSGrishma Kotecha 
5240f94570dSGrishma Kotecha 	0x00, 0x00, 0x00, 0x00, /* ICE_UDP_ILOS 34 */
5250f94570dSGrishma Kotecha 	0x00, 0x08, 0x00, 0x00,
5260f94570dSGrishma Kotecha 
5270f94570dSGrishma Kotecha 	0x00, 0x00,	/* 2 bytes for 4 byte alignment */
5280f94570dSGrishma Kotecha };
5290f94570dSGrishma Kotecha 
5300f94570dSGrishma Kotecha /* offset info for MAC + IPv4 + TCP dummy packet */
53107a28842SAlexander Lobakin ICE_DECLARE_PKT_OFFSETS(tcp) = {
5320f94570dSGrishma Kotecha 	{ ICE_MAC_OFOS,		0 },
5330f94570dSGrishma Kotecha 	{ ICE_ETYPE_OL,		12 },
5340f94570dSGrishma Kotecha 	{ ICE_IPV4_OFOS,	14 },
5350f94570dSGrishma Kotecha 	{ ICE_TCP_IL,		34 },
5360f94570dSGrishma Kotecha 	{ ICE_PROTOCOL_LAST,	0 },
5370f94570dSGrishma Kotecha };
5380f94570dSGrishma Kotecha 
5390f94570dSGrishma Kotecha /* Dummy packet for MAC + IPv4 + TCP */
54007a28842SAlexander Lobakin ICE_DECLARE_PKT_TEMPLATE(tcp) = {
5410f94570dSGrishma Kotecha 	0x00, 0x00, 0x00, 0x00, /* ICE_MAC_OFOS 0 */
5420f94570dSGrishma Kotecha 	0x00, 0x00, 0x00, 0x00,
5430f94570dSGrishma Kotecha 	0x00, 0x00, 0x00, 0x00,
5440f94570dSGrishma Kotecha 
5450f94570dSGrishma Kotecha 	0x08, 0x00,		/* ICE_ETYPE_OL 12 */
5460f94570dSGrishma Kotecha 
5470f94570dSGrishma Kotecha 	0x45, 0x00, 0x00, 0x28, /* ICE_IPV4_OFOS 14 */
5480f94570dSGrishma Kotecha 	0x00, 0x01, 0x00, 0x00,
5490f94570dSGrishma Kotecha 	0x00, 0x06, 0x00, 0x00,
5500f94570dSGrishma Kotecha 	0x00, 0x00, 0x00, 0x00,
5510f94570dSGrishma Kotecha 	0x00, 0x00, 0x00, 0x00,
5520f94570dSGrishma Kotecha 
5530f94570dSGrishma Kotecha 	0x00, 0x00, 0x00, 0x00, /* ICE_TCP_IL 34 */
5540f94570dSGrishma Kotecha 	0x00, 0x00, 0x00, 0x00,
5550f94570dSGrishma Kotecha 	0x00, 0x00, 0x00, 0x00,
5560f94570dSGrishma Kotecha 	0x50, 0x00, 0x00, 0x00,
5570f94570dSGrishma Kotecha 	0x00, 0x00, 0x00, 0x00,
5580f94570dSGrishma Kotecha 
5590f94570dSGrishma Kotecha 	0x00, 0x00,	/* 2 bytes for 4 byte alignment */
5600f94570dSGrishma Kotecha };
5610f94570dSGrishma Kotecha 
56207a28842SAlexander Lobakin ICE_DECLARE_PKT_OFFSETS(tcp_ipv6) = {
5630f94570dSGrishma Kotecha 	{ ICE_MAC_OFOS,		0 },
5640f94570dSGrishma Kotecha 	{ ICE_ETYPE_OL,		12 },
5650f94570dSGrishma Kotecha 	{ ICE_IPV6_OFOS,	14 },
5660f94570dSGrishma Kotecha 	{ ICE_TCP_IL,		54 },
5670f94570dSGrishma Kotecha 	{ ICE_PROTOCOL_LAST,	0 },
5680f94570dSGrishma Kotecha };
5690f94570dSGrishma Kotecha 
57007a28842SAlexander Lobakin ICE_DECLARE_PKT_TEMPLATE(tcp_ipv6) = {
5710f94570dSGrishma Kotecha 	0x00, 0x00, 0x00, 0x00, /* ICE_MAC_OFOS 0 */
5720f94570dSGrishma Kotecha 	0x00, 0x00, 0x00, 0x00,
5730f94570dSGrishma Kotecha 	0x00, 0x00, 0x00, 0x00,
5740f94570dSGrishma Kotecha 
5750f94570dSGrishma Kotecha 	0x86, 0xDD,		/* ICE_ETYPE_OL 12 */
5760f94570dSGrishma Kotecha 
5770f94570dSGrishma Kotecha 	0x60, 0x00, 0x00, 0x00, /* ICE_IPV6_OFOS 40 */
5780f94570dSGrishma Kotecha 	0x00, 0x14, 0x06, 0x00, /* Next header is TCP */
5790f94570dSGrishma Kotecha 	0x00, 0x00, 0x00, 0x00,
5800f94570dSGrishma Kotecha 	0x00, 0x00, 0x00, 0x00,
5810f94570dSGrishma Kotecha 	0x00, 0x00, 0x00, 0x00,
5820f94570dSGrishma Kotecha 	0x00, 0x00, 0x00, 0x00,
5830f94570dSGrishma Kotecha 	0x00, 0x00, 0x00, 0x00,
5840f94570dSGrishma Kotecha 	0x00, 0x00, 0x00, 0x00,
5850f94570dSGrishma Kotecha 	0x00, 0x00, 0x00, 0x00,
5860f94570dSGrishma Kotecha 	0x00, 0x00, 0x00, 0x00,
5870f94570dSGrishma Kotecha 
5880f94570dSGrishma Kotecha 	0x00, 0x00, 0x00, 0x00, /* ICE_TCP_IL 54 */
5890f94570dSGrishma Kotecha 	0x00, 0x00, 0x00, 0x00,
5900f94570dSGrishma Kotecha 	0x00, 0x00, 0x00, 0x00,
5910f94570dSGrishma Kotecha 	0x50, 0x00, 0x00, 0x00,
5920f94570dSGrishma Kotecha 	0x00, 0x00, 0x00, 0x00,
5930f94570dSGrishma Kotecha 
5940f94570dSGrishma Kotecha 	0x00, 0x00, /* 2 bytes for 4 byte alignment */
5950f94570dSGrishma Kotecha };
5960f94570dSGrishma Kotecha 
5970f94570dSGrishma Kotecha /* IPv6 + UDP */
59807a28842SAlexander Lobakin ICE_DECLARE_PKT_OFFSETS(udp_ipv6) = {
5990f94570dSGrishma Kotecha 	{ ICE_MAC_OFOS,		0 },
6000f94570dSGrishma Kotecha 	{ ICE_ETYPE_OL,		12 },
6010f94570dSGrishma Kotecha 	{ ICE_IPV6_OFOS,	14 },
6020f94570dSGrishma Kotecha 	{ ICE_UDP_ILOS,		54 },
6030f94570dSGrishma Kotecha 	{ ICE_PROTOCOL_LAST,	0 },
6040f94570dSGrishma Kotecha };
6050f94570dSGrishma Kotecha 
6060f94570dSGrishma Kotecha /* IPv6 + UDP dummy packet */
60707a28842SAlexander Lobakin ICE_DECLARE_PKT_TEMPLATE(udp_ipv6) = {
6080f94570dSGrishma Kotecha 	0x00, 0x00, 0x00, 0x00, /* ICE_MAC_OFOS 0 */
6090f94570dSGrishma Kotecha 	0x00, 0x00, 0x00, 0x00,
6100f94570dSGrishma Kotecha 	0x00, 0x00, 0x00, 0x00,
6110f94570dSGrishma Kotecha 
6120f94570dSGrishma Kotecha 	0x86, 0xDD,		/* ICE_ETYPE_OL 12 */
6130f94570dSGrishma Kotecha 
6140f94570dSGrishma Kotecha 	0x60, 0x00, 0x00, 0x00, /* ICE_IPV6_OFOS 40 */
6150f94570dSGrishma Kotecha 	0x00, 0x10, 0x11, 0x00, /* Next header UDP */
6160f94570dSGrishma Kotecha 	0x00, 0x00, 0x00, 0x00,
6170f94570dSGrishma Kotecha 	0x00, 0x00, 0x00, 0x00,
6180f94570dSGrishma Kotecha 	0x00, 0x00, 0x00, 0x00,
6190f94570dSGrishma Kotecha 	0x00, 0x00, 0x00, 0x00,
6200f94570dSGrishma Kotecha 	0x00, 0x00, 0x00, 0x00,
6210f94570dSGrishma Kotecha 	0x00, 0x00, 0x00, 0x00,
6220f94570dSGrishma Kotecha 	0x00, 0x00, 0x00, 0x00,
6230f94570dSGrishma Kotecha 	0x00, 0x00, 0x00, 0x00,
6240f94570dSGrishma Kotecha 
6250f94570dSGrishma Kotecha 	0x00, 0x00, 0x00, 0x00, /* ICE_UDP_ILOS 54 */
6260f94570dSGrishma Kotecha 	0x00, 0x10, 0x00, 0x00,
6270f94570dSGrishma Kotecha 
6280f94570dSGrishma Kotecha 	0x00, 0x00, 0x00, 0x00, /* needed for ESP packets */
6290f94570dSGrishma Kotecha 	0x00, 0x00, 0x00, 0x00,
6300f94570dSGrishma Kotecha 
6310f94570dSGrishma Kotecha 	0x00, 0x00, /* 2 bytes for 4 byte alignment */
6320f94570dSGrishma Kotecha };
6330f94570dSGrishma Kotecha 
6349a225f81SMarcin Szycik /* Outer IPv4 + Outer UDP + GTP + Inner IPv4 + Inner TCP */
63507a28842SAlexander Lobakin ICE_DECLARE_PKT_OFFSETS(ipv4_gtpu_ipv4_tcp) = {
6369a225f81SMarcin Szycik 	{ ICE_MAC_OFOS,		0 },
6379a225f81SMarcin Szycik 	{ ICE_IPV4_OFOS,	14 },
6389a225f81SMarcin Szycik 	{ ICE_UDP_OF,		34 },
6399a225f81SMarcin Szycik 	{ ICE_GTP,		42 },
6409a225f81SMarcin Szycik 	{ ICE_IPV4_IL,		62 },
6419a225f81SMarcin Szycik 	{ ICE_TCP_IL,		82 },
6429a225f81SMarcin Szycik 	{ ICE_PROTOCOL_LAST,	0 },
6439a225f81SMarcin Szycik };
6449a225f81SMarcin Szycik 
64507a28842SAlexander Lobakin ICE_DECLARE_PKT_TEMPLATE(ipv4_gtpu_ipv4_tcp) = {
6469a225f81SMarcin Szycik 	0x00, 0x00, 0x00, 0x00, /* Ethernet 0 */
6479a225f81SMarcin Szycik 	0x00, 0x00, 0x00, 0x00,
6489a225f81SMarcin Szycik 	0x00, 0x00, 0x00, 0x00,
6499a225f81SMarcin Szycik 	0x08, 0x00,
6509a225f81SMarcin Szycik 
6519a225f81SMarcin Szycik 	0x45, 0x00, 0x00, 0x58, /* IP 14 */
6529a225f81SMarcin Szycik 	0x00, 0x00, 0x00, 0x00,
6539a225f81SMarcin Szycik 	0x00, 0x11, 0x00, 0x00,
6549a225f81SMarcin Szycik 	0x00, 0x00, 0x00, 0x00,
6559a225f81SMarcin Szycik 	0x00, 0x00, 0x00, 0x00,
6569a225f81SMarcin Szycik 
6579a225f81SMarcin Szycik 	0x00, 0x00, 0x08, 0x68, /* UDP 34 */
6589a225f81SMarcin Szycik 	0x00, 0x44, 0x00, 0x00,
6599a225f81SMarcin Szycik 
6609a225f81SMarcin Szycik 	0x34, 0xff, 0x00, 0x34, /* ICE_GTP Header 42 */
6619a225f81SMarcin Szycik 	0x00, 0x00, 0x00, 0x00,
6629a225f81SMarcin Szycik 	0x00, 0x00, 0x00, 0x85,
6639a225f81SMarcin Szycik 
6649a225f81SMarcin Szycik 	0x02, 0x00, 0x00, 0x00, /* GTP_PDUSession_ExtensionHeader 54 */
6659a225f81SMarcin Szycik 	0x00, 0x00, 0x00, 0x00,
6669a225f81SMarcin Szycik 
6679a225f81SMarcin Szycik 	0x45, 0x00, 0x00, 0x28, /* IP 62 */
6689a225f81SMarcin Szycik 	0x00, 0x00, 0x00, 0x00,
6699a225f81SMarcin Szycik 	0x00, 0x06, 0x00, 0x00,
6709a225f81SMarcin Szycik 	0x00, 0x00, 0x00, 0x00,
6719a225f81SMarcin Szycik 	0x00, 0x00, 0x00, 0x00,
6729a225f81SMarcin Szycik 
6739a225f81SMarcin Szycik 	0x00, 0x00, 0x00, 0x00, /* TCP 82 */
6749a225f81SMarcin Szycik 	0x00, 0x00, 0x00, 0x00,
6759a225f81SMarcin Szycik 	0x00, 0x00, 0x00, 0x00,
6769a225f81SMarcin Szycik 	0x50, 0x00, 0x00, 0x00,
6779a225f81SMarcin Szycik 	0x00, 0x00, 0x00, 0x00,
6789a225f81SMarcin Szycik 
6799a225f81SMarcin Szycik 	0x00, 0x00, /* 2 bytes for 4 byte alignment */
6809a225f81SMarcin Szycik };
6819a225f81SMarcin Szycik 
6829a225f81SMarcin Szycik /* Outer IPv4 + Outer UDP + GTP + Inner IPv4 + Inner UDP */
68307a28842SAlexander Lobakin ICE_DECLARE_PKT_OFFSETS(ipv4_gtpu_ipv4_udp) = {
6849a225f81SMarcin Szycik 	{ ICE_MAC_OFOS,		0 },
6859a225f81SMarcin Szycik 	{ ICE_IPV4_OFOS,	14 },
6869a225f81SMarcin Szycik 	{ ICE_UDP_OF,		34 },
6879a225f81SMarcin Szycik 	{ ICE_GTP,		42 },
6889a225f81SMarcin Szycik 	{ ICE_IPV4_IL,		62 },
6899a225f81SMarcin Szycik 	{ ICE_UDP_ILOS,		82 },
6909a225f81SMarcin Szycik 	{ ICE_PROTOCOL_LAST,	0 },
6919a225f81SMarcin Szycik };
6929a225f81SMarcin Szycik 
69307a28842SAlexander Lobakin ICE_DECLARE_PKT_TEMPLATE(ipv4_gtpu_ipv4_udp) = {
6949a225f81SMarcin Szycik 	0x00, 0x00, 0x00, 0x00, /* Ethernet 0 */
6959a225f81SMarcin Szycik 	0x00, 0x00, 0x00, 0x00,
6969a225f81SMarcin Szycik 	0x00, 0x00, 0x00, 0x00,
6979a225f81SMarcin Szycik 	0x08, 0x00,
6989a225f81SMarcin Szycik 
6999a225f81SMarcin Szycik 	0x45, 0x00, 0x00, 0x4c, /* IP 14 */
7009a225f81SMarcin Szycik 	0x00, 0x00, 0x00, 0x00,
7019a225f81SMarcin Szycik 	0x00, 0x11, 0x00, 0x00,
7029a225f81SMarcin Szycik 	0x00, 0x00, 0x00, 0x00,
7039a225f81SMarcin Szycik 	0x00, 0x00, 0x00, 0x00,
7049a225f81SMarcin Szycik 
7059a225f81SMarcin Szycik 	0x00, 0x00, 0x08, 0x68, /* UDP 34 */
7069a225f81SMarcin Szycik 	0x00, 0x38, 0x00, 0x00,
7079a225f81SMarcin Szycik 
7089a225f81SMarcin Szycik 	0x34, 0xff, 0x00, 0x28, /* ICE_GTP Header 42 */
7099a225f81SMarcin Szycik 	0x00, 0x00, 0x00, 0x00,
7109a225f81SMarcin Szycik 	0x00, 0x00, 0x00, 0x85,
7119a225f81SMarcin Szycik 
7129a225f81SMarcin Szycik 	0x02, 0x00, 0x00, 0x00, /* GTP_PDUSession_ExtensionHeader 54 */
7139a225f81SMarcin Szycik 	0x00, 0x00, 0x00, 0x00,
7149a225f81SMarcin Szycik 
7159a225f81SMarcin Szycik 	0x45, 0x00, 0x00, 0x1c, /* IP 62 */
7169a225f81SMarcin Szycik 	0x00, 0x00, 0x00, 0x00,
7179a225f81SMarcin Szycik 	0x00, 0x11, 0x00, 0x00,
7189a225f81SMarcin Szycik 	0x00, 0x00, 0x00, 0x00,
7199a225f81SMarcin Szycik 	0x00, 0x00, 0x00, 0x00,
7209a225f81SMarcin Szycik 
7219a225f81SMarcin Szycik 	0x00, 0x00, 0x00, 0x00, /* UDP 82 */
7229a225f81SMarcin Szycik 	0x00, 0x08, 0x00, 0x00,
7239a225f81SMarcin Szycik 
7249a225f81SMarcin Szycik 	0x00, 0x00, /* 2 bytes for 4 byte alignment */
7259a225f81SMarcin Szycik };
7269a225f81SMarcin Szycik 
7279a225f81SMarcin Szycik /* Outer IPv6 + Outer UDP + GTP + Inner IPv4 + Inner TCP */
72807a28842SAlexander Lobakin ICE_DECLARE_PKT_OFFSETS(ipv4_gtpu_ipv6_tcp) = {
7299a225f81SMarcin Szycik 	{ ICE_MAC_OFOS,		0 },
7309a225f81SMarcin Szycik 	{ ICE_IPV4_OFOS,	14 },
7319a225f81SMarcin Szycik 	{ ICE_UDP_OF,		34 },
7329a225f81SMarcin Szycik 	{ ICE_GTP,		42 },
7339a225f81SMarcin Szycik 	{ ICE_IPV6_IL,		62 },
7349a225f81SMarcin Szycik 	{ ICE_TCP_IL,		102 },
7359a225f81SMarcin Szycik 	{ ICE_PROTOCOL_LAST,	0 },
7369a225f81SMarcin Szycik };
7379a225f81SMarcin Szycik 
73807a28842SAlexander Lobakin ICE_DECLARE_PKT_TEMPLATE(ipv4_gtpu_ipv6_tcp) = {
7399a225f81SMarcin Szycik 	0x00, 0x00, 0x00, 0x00, /* Ethernet 0 */
7409a225f81SMarcin Szycik 	0x00, 0x00, 0x00, 0x00,
7419a225f81SMarcin Szycik 	0x00, 0x00, 0x00, 0x00,
7429a225f81SMarcin Szycik 	0x08, 0x00,
7439a225f81SMarcin Szycik 
7449a225f81SMarcin Szycik 	0x45, 0x00, 0x00, 0x6c, /* IP 14 */
7459a225f81SMarcin Szycik 	0x00, 0x00, 0x00, 0x00,
7469a225f81SMarcin Szycik 	0x00, 0x11, 0x00, 0x00,
7479a225f81SMarcin Szycik 	0x00, 0x00, 0x00, 0x00,
7489a225f81SMarcin Szycik 	0x00, 0x00, 0x00, 0x00,
7499a225f81SMarcin Szycik 
7509a225f81SMarcin Szycik 	0x00, 0x00, 0x08, 0x68, /* UDP 34 */
7519a225f81SMarcin Szycik 	0x00, 0x58, 0x00, 0x00,
7529a225f81SMarcin Szycik 
7539a225f81SMarcin Szycik 	0x34, 0xff, 0x00, 0x48, /* ICE_GTP Header 42 */
7549a225f81SMarcin Szycik 	0x00, 0x00, 0x00, 0x00,
7559a225f81SMarcin Szycik 	0x00, 0x00, 0x00, 0x85,
7569a225f81SMarcin Szycik 
7579a225f81SMarcin Szycik 	0x02, 0x00, 0x00, 0x00, /* GTP_PDUSession_ExtensionHeader 54 */
7589a225f81SMarcin Szycik 	0x00, 0x00, 0x00, 0x00,
7599a225f81SMarcin Szycik 
7609a225f81SMarcin Szycik 	0x60, 0x00, 0x00, 0x00, /* IPv6 62 */
7619a225f81SMarcin Szycik 	0x00, 0x14, 0x06, 0x00,
7629a225f81SMarcin Szycik 	0x00, 0x00, 0x00, 0x00,
7639a225f81SMarcin Szycik 	0x00, 0x00, 0x00, 0x00,
7649a225f81SMarcin Szycik 	0x00, 0x00, 0x00, 0x00,
7659a225f81SMarcin Szycik 	0x00, 0x00, 0x00, 0x00,
7669a225f81SMarcin Szycik 	0x00, 0x00, 0x00, 0x00,
7679a225f81SMarcin Szycik 	0x00, 0x00, 0x00, 0x00,
7689a225f81SMarcin Szycik 	0x00, 0x00, 0x00, 0x00,
7699a225f81SMarcin Szycik 	0x00, 0x00, 0x00, 0x00,
7709a225f81SMarcin Szycik 
7719a225f81SMarcin Szycik 	0x00, 0x00, 0x00, 0x00, /* TCP 102 */
7729a225f81SMarcin Szycik 	0x00, 0x00, 0x00, 0x00,
7739a225f81SMarcin Szycik 	0x00, 0x00, 0x00, 0x00,
7749a225f81SMarcin Szycik 	0x50, 0x00, 0x00, 0x00,
7759a225f81SMarcin Szycik 	0x00, 0x00, 0x00, 0x00,
7769a225f81SMarcin Szycik 
7779a225f81SMarcin Szycik 	0x00, 0x00, /* 2 bytes for 4 byte alignment */
7789a225f81SMarcin Szycik };
7799a225f81SMarcin Szycik 
78007a28842SAlexander Lobakin ICE_DECLARE_PKT_OFFSETS(ipv4_gtpu_ipv6_udp) = {
7819a225f81SMarcin Szycik 	{ ICE_MAC_OFOS,		0 },
7829a225f81SMarcin Szycik 	{ ICE_IPV4_OFOS,	14 },
7839a225f81SMarcin Szycik 	{ ICE_UDP_OF,		34 },
7849a225f81SMarcin Szycik 	{ ICE_GTP,		42 },
7859a225f81SMarcin Szycik 	{ ICE_IPV6_IL,		62 },
7869a225f81SMarcin Szycik 	{ ICE_UDP_ILOS,		102 },
7879a225f81SMarcin Szycik 	{ ICE_PROTOCOL_LAST,	0 },
7889a225f81SMarcin Szycik };
7899a225f81SMarcin Szycik 
79007a28842SAlexander Lobakin ICE_DECLARE_PKT_TEMPLATE(ipv4_gtpu_ipv6_udp) = {
7919a225f81SMarcin Szycik 	0x00, 0x00, 0x00, 0x00, /* Ethernet 0 */
7929a225f81SMarcin Szycik 	0x00, 0x00, 0x00, 0x00,
7939a225f81SMarcin Szycik 	0x00, 0x00, 0x00, 0x00,
7949a225f81SMarcin Szycik 	0x08, 0x00,
7959a225f81SMarcin Szycik 
7969a225f81SMarcin Szycik 	0x45, 0x00, 0x00, 0x60, /* IP 14 */
7979a225f81SMarcin Szycik 	0x00, 0x00, 0x00, 0x00,
7989a225f81SMarcin Szycik 	0x00, 0x11, 0x00, 0x00,
7999a225f81SMarcin Szycik 	0x00, 0x00, 0x00, 0x00,
8009a225f81SMarcin Szycik 	0x00, 0x00, 0x00, 0x00,
8019a225f81SMarcin Szycik 
8029a225f81SMarcin Szycik 	0x00, 0x00, 0x08, 0x68, /* UDP 34 */
8039a225f81SMarcin Szycik 	0x00, 0x4c, 0x00, 0x00,
8049a225f81SMarcin Szycik 
8059a225f81SMarcin Szycik 	0x34, 0xff, 0x00, 0x3c, /* ICE_GTP Header 42 */
8069a225f81SMarcin Szycik 	0x00, 0x00, 0x00, 0x00,
8079a225f81SMarcin Szycik 	0x00, 0x00, 0x00, 0x85,
8089a225f81SMarcin Szycik 
8099a225f81SMarcin Szycik 	0x02, 0x00, 0x00, 0x00, /* GTP_PDUSession_ExtensionHeader 54 */
8109a225f81SMarcin Szycik 	0x00, 0x00, 0x00, 0x00,
8119a225f81SMarcin Szycik 
8129a225f81SMarcin Szycik 	0x60, 0x00, 0x00, 0x00, /* IPv6 62 */
8139a225f81SMarcin Szycik 	0x00, 0x08, 0x11, 0x00,
8149a225f81SMarcin Szycik 	0x00, 0x00, 0x00, 0x00,
8159a225f81SMarcin Szycik 	0x00, 0x00, 0x00, 0x00,
8169a225f81SMarcin Szycik 	0x00, 0x00, 0x00, 0x00,
8179a225f81SMarcin Szycik 	0x00, 0x00, 0x00, 0x00,
8189a225f81SMarcin Szycik 	0x00, 0x00, 0x00, 0x00,
8199a225f81SMarcin Szycik 	0x00, 0x00, 0x00, 0x00,
8209a225f81SMarcin Szycik 	0x00, 0x00, 0x00, 0x00,
8219a225f81SMarcin Szycik 	0x00, 0x00, 0x00, 0x00,
8229a225f81SMarcin Szycik 
8239a225f81SMarcin Szycik 	0x00, 0x00, 0x00, 0x00, /* UDP 102 */
8249a225f81SMarcin Szycik 	0x00, 0x08, 0x00, 0x00,
8259a225f81SMarcin Szycik 
8269a225f81SMarcin Szycik 	0x00, 0x00, /* 2 bytes for 4 byte alignment */
8279a225f81SMarcin Szycik };
8289a225f81SMarcin Szycik 
82907a28842SAlexander Lobakin ICE_DECLARE_PKT_OFFSETS(ipv6_gtpu_ipv4_tcp) = {
8309a225f81SMarcin Szycik 	{ ICE_MAC_OFOS,		0 },
8319a225f81SMarcin Szycik 	{ ICE_IPV6_OFOS,	14 },
8329a225f81SMarcin Szycik 	{ ICE_UDP_OF,		54 },
8339a225f81SMarcin Szycik 	{ ICE_GTP,		62 },
8349a225f81SMarcin Szycik 	{ ICE_IPV4_IL,		82 },
8359a225f81SMarcin Szycik 	{ ICE_TCP_IL,		102 },
8369a225f81SMarcin Szycik 	{ ICE_PROTOCOL_LAST,	0 },
8379a225f81SMarcin Szycik };
8389a225f81SMarcin Szycik 
83907a28842SAlexander Lobakin ICE_DECLARE_PKT_TEMPLATE(ipv6_gtpu_ipv4_tcp) = {
8409a225f81SMarcin Szycik 	0x00, 0x00, 0x00, 0x00, /* Ethernet 0 */
8419a225f81SMarcin Szycik 	0x00, 0x00, 0x00, 0x00,
8429a225f81SMarcin Szycik 	0x00, 0x00, 0x00, 0x00,
8439a225f81SMarcin Szycik 	0x86, 0xdd,
8449a225f81SMarcin Szycik 
8459a225f81SMarcin Szycik 	0x60, 0x00, 0x00, 0x00, /* IPv6 14 */
8469a225f81SMarcin Szycik 	0x00, 0x44, 0x11, 0x00,
8479a225f81SMarcin Szycik 	0x00, 0x00, 0x00, 0x00,
8489a225f81SMarcin Szycik 	0x00, 0x00, 0x00, 0x00,
8499a225f81SMarcin Szycik 	0x00, 0x00, 0x00, 0x00,
8509a225f81SMarcin Szycik 	0x00, 0x00, 0x00, 0x00,
8519a225f81SMarcin Szycik 	0x00, 0x00, 0x00, 0x00,
8529a225f81SMarcin Szycik 	0x00, 0x00, 0x00, 0x00,
8539a225f81SMarcin Szycik 	0x00, 0x00, 0x00, 0x00,
8549a225f81SMarcin Szycik 	0x00, 0x00, 0x00, 0x00,
8559a225f81SMarcin Szycik 
8569a225f81SMarcin Szycik 	0x00, 0x00, 0x08, 0x68, /* UDP 54 */
8579a225f81SMarcin Szycik 	0x00, 0x44, 0x00, 0x00,
8589a225f81SMarcin Szycik 
8599a225f81SMarcin Szycik 	0x34, 0xff, 0x00, 0x34, /* ICE_GTP Header 62 */
8609a225f81SMarcin Szycik 	0x00, 0x00, 0x00, 0x00,
8619a225f81SMarcin Szycik 	0x00, 0x00, 0x00, 0x85,
8629a225f81SMarcin Szycik 
8639a225f81SMarcin Szycik 	0x02, 0x00, 0x00, 0x00, /* GTP_PDUSession_ExtensionHeader 74 */
8649a225f81SMarcin Szycik 	0x00, 0x00, 0x00, 0x00,
8659a225f81SMarcin Szycik 
8669a225f81SMarcin Szycik 	0x45, 0x00, 0x00, 0x28, /* IP 82 */
8679a225f81SMarcin Szycik 	0x00, 0x00, 0x00, 0x00,
8689a225f81SMarcin Szycik 	0x00, 0x06, 0x00, 0x00,
8699a225f81SMarcin Szycik 	0x00, 0x00, 0x00, 0x00,
8709a225f81SMarcin Szycik 	0x00, 0x00, 0x00, 0x00,
8719a225f81SMarcin Szycik 
8729a225f81SMarcin Szycik 	0x00, 0x00, 0x00, 0x00, /* TCP 102 */
8739a225f81SMarcin Szycik 	0x00, 0x00, 0x00, 0x00,
8749a225f81SMarcin Szycik 	0x00, 0x00, 0x00, 0x00,
8759a225f81SMarcin Szycik 	0x50, 0x00, 0x00, 0x00,
8769a225f81SMarcin Szycik 	0x00, 0x00, 0x00, 0x00,
8779a225f81SMarcin Szycik 
8789a225f81SMarcin Szycik 	0x00, 0x00, /* 2 bytes for 4 byte alignment */
8799a225f81SMarcin Szycik };
8809a225f81SMarcin Szycik 
88107a28842SAlexander Lobakin ICE_DECLARE_PKT_OFFSETS(ipv6_gtpu_ipv4_udp) = {
8829a225f81SMarcin Szycik 	{ ICE_MAC_OFOS,		0 },
8839a225f81SMarcin Szycik 	{ ICE_IPV6_OFOS,	14 },
8849a225f81SMarcin Szycik 	{ ICE_UDP_OF,		54 },
8859a225f81SMarcin Szycik 	{ ICE_GTP,		62 },
8869a225f81SMarcin Szycik 	{ ICE_IPV4_IL,		82 },
8879a225f81SMarcin Szycik 	{ ICE_UDP_ILOS,		102 },
8889a225f81SMarcin Szycik 	{ ICE_PROTOCOL_LAST,	0 },
8899a225f81SMarcin Szycik };
8909a225f81SMarcin Szycik 
89107a28842SAlexander Lobakin ICE_DECLARE_PKT_TEMPLATE(ipv6_gtpu_ipv4_udp) = {
8929a225f81SMarcin Szycik 	0x00, 0x00, 0x00, 0x00, /* Ethernet 0 */
8939a225f81SMarcin Szycik 	0x00, 0x00, 0x00, 0x00,
8949a225f81SMarcin Szycik 	0x00, 0x00, 0x00, 0x00,
8959a225f81SMarcin Szycik 	0x86, 0xdd,
8969a225f81SMarcin Szycik 
8979a225f81SMarcin Szycik 	0x60, 0x00, 0x00, 0x00, /* IPv6 14 */
8989a225f81SMarcin Szycik 	0x00, 0x38, 0x11, 0x00,
8999a225f81SMarcin Szycik 	0x00, 0x00, 0x00, 0x00,
9009a225f81SMarcin Szycik 	0x00, 0x00, 0x00, 0x00,
9019a225f81SMarcin Szycik 	0x00, 0x00, 0x00, 0x00,
9029a225f81SMarcin Szycik 	0x00, 0x00, 0x00, 0x00,
9039a225f81SMarcin Szycik 	0x00, 0x00, 0x00, 0x00,
9049a225f81SMarcin Szycik 	0x00, 0x00, 0x00, 0x00,
9059a225f81SMarcin Szycik 	0x00, 0x00, 0x00, 0x00,
9069a225f81SMarcin Szycik 	0x00, 0x00, 0x00, 0x00,
9079a225f81SMarcin Szycik 
9089a225f81SMarcin Szycik 	0x00, 0x00, 0x08, 0x68, /* UDP 54 */
9099a225f81SMarcin Szycik 	0x00, 0x38, 0x00, 0x00,
9109a225f81SMarcin Szycik 
9119a225f81SMarcin Szycik 	0x34, 0xff, 0x00, 0x28, /* ICE_GTP Header 62 */
9129a225f81SMarcin Szycik 	0x00, 0x00, 0x00, 0x00,
9139a225f81SMarcin Szycik 	0x00, 0x00, 0x00, 0x85,
9149a225f81SMarcin Szycik 
9159a225f81SMarcin Szycik 	0x02, 0x00, 0x00, 0x00, /* GTP_PDUSession_ExtensionHeader 74 */
9169a225f81SMarcin Szycik 	0x00, 0x00, 0x00, 0x00,
9179a225f81SMarcin Szycik 
9189a225f81SMarcin Szycik 	0x45, 0x00, 0x00, 0x1c, /* IP 82 */
9199a225f81SMarcin Szycik 	0x00, 0x00, 0x00, 0x00,
9209a225f81SMarcin Szycik 	0x00, 0x11, 0x00, 0x00,
9219a225f81SMarcin Szycik 	0x00, 0x00, 0x00, 0x00,
9229a225f81SMarcin Szycik 	0x00, 0x00, 0x00, 0x00,
9239a225f81SMarcin Szycik 
9249a225f81SMarcin Szycik 	0x00, 0x00, 0x00, 0x00, /* UDP 102 */
9259a225f81SMarcin Szycik 	0x00, 0x08, 0x00, 0x00,
9269a225f81SMarcin Szycik 
9279a225f81SMarcin Szycik 	0x00, 0x00, /* 2 bytes for 4 byte alignment */
9289a225f81SMarcin Szycik };
9299a225f81SMarcin Szycik 
93007a28842SAlexander Lobakin ICE_DECLARE_PKT_OFFSETS(ipv6_gtpu_ipv6_tcp) = {
9319a225f81SMarcin Szycik 	{ ICE_MAC_OFOS,		0 },
9329a225f81SMarcin Szycik 	{ ICE_IPV6_OFOS,	14 },
9339a225f81SMarcin Szycik 	{ ICE_UDP_OF,		54 },
9349a225f81SMarcin Szycik 	{ ICE_GTP,		62 },
9359a225f81SMarcin Szycik 	{ ICE_IPV6_IL,		82 },
9369a225f81SMarcin Szycik 	{ ICE_TCP_IL,		122 },
9379a225f81SMarcin Szycik 	{ ICE_PROTOCOL_LAST,	0 },
9389a225f81SMarcin Szycik };
9399a225f81SMarcin Szycik 
94007a28842SAlexander Lobakin ICE_DECLARE_PKT_TEMPLATE(ipv6_gtpu_ipv6_tcp) = {
9419a225f81SMarcin Szycik 	0x00, 0x00, 0x00, 0x00, /* Ethernet 0 */
9429a225f81SMarcin Szycik 	0x00, 0x00, 0x00, 0x00,
9439a225f81SMarcin Szycik 	0x00, 0x00, 0x00, 0x00,
9449a225f81SMarcin Szycik 	0x86, 0xdd,
9459a225f81SMarcin Szycik 
9469a225f81SMarcin Szycik 	0x60, 0x00, 0x00, 0x00, /* IPv6 14 */
9479a225f81SMarcin Szycik 	0x00, 0x58, 0x11, 0x00,
9489a225f81SMarcin Szycik 	0x00, 0x00, 0x00, 0x00,
9499a225f81SMarcin Szycik 	0x00, 0x00, 0x00, 0x00,
9509a225f81SMarcin Szycik 	0x00, 0x00, 0x00, 0x00,
9519a225f81SMarcin Szycik 	0x00, 0x00, 0x00, 0x00,
9529a225f81SMarcin Szycik 	0x00, 0x00, 0x00, 0x00,
9539a225f81SMarcin Szycik 	0x00, 0x00, 0x00, 0x00,
9549a225f81SMarcin Szycik 	0x00, 0x00, 0x00, 0x00,
9559a225f81SMarcin Szycik 	0x00, 0x00, 0x00, 0x00,
9569a225f81SMarcin Szycik 
9579a225f81SMarcin Szycik 	0x00, 0x00, 0x08, 0x68, /* UDP 54 */
9589a225f81SMarcin Szycik 	0x00, 0x58, 0x00, 0x00,
9599a225f81SMarcin Szycik 
9609a225f81SMarcin Szycik 	0x34, 0xff, 0x00, 0x48, /* ICE_GTP Header 62 */
9619a225f81SMarcin Szycik 	0x00, 0x00, 0x00, 0x00,
9629a225f81SMarcin Szycik 	0x00, 0x00, 0x00, 0x85,
9639a225f81SMarcin Szycik 
9649a225f81SMarcin Szycik 	0x02, 0x00, 0x00, 0x00, /* GTP_PDUSession_ExtensionHeader 74 */
9659a225f81SMarcin Szycik 	0x00, 0x00, 0x00, 0x00,
9669a225f81SMarcin Szycik 
9679a225f81SMarcin Szycik 	0x60, 0x00, 0x00, 0x00, /* IPv6 82 */
9689a225f81SMarcin Szycik 	0x00, 0x14, 0x06, 0x00,
9699a225f81SMarcin Szycik 	0x00, 0x00, 0x00, 0x00,
9709a225f81SMarcin Szycik 	0x00, 0x00, 0x00, 0x00,
9719a225f81SMarcin Szycik 	0x00, 0x00, 0x00, 0x00,
9729a225f81SMarcin Szycik 	0x00, 0x00, 0x00, 0x00,
9739a225f81SMarcin Szycik 	0x00, 0x00, 0x00, 0x00,
9749a225f81SMarcin Szycik 	0x00, 0x00, 0x00, 0x00,
9759a225f81SMarcin Szycik 	0x00, 0x00, 0x00, 0x00,
9769a225f81SMarcin Szycik 	0x00, 0x00, 0x00, 0x00,
9779a225f81SMarcin Szycik 
9789a225f81SMarcin Szycik 	0x00, 0x00, 0x00, 0x00, /* TCP 122 */
9799a225f81SMarcin Szycik 	0x00, 0x00, 0x00, 0x00,
9809a225f81SMarcin Szycik 	0x00, 0x00, 0x00, 0x00,
9819a225f81SMarcin Szycik 	0x50, 0x00, 0x00, 0x00,
9829a225f81SMarcin Szycik 	0x00, 0x00, 0x00, 0x00,
9839a225f81SMarcin Szycik 
9849a225f81SMarcin Szycik 	0x00, 0x00, /* 2 bytes for 4 byte alignment */
9859a225f81SMarcin Szycik };
9869a225f81SMarcin Szycik 
98707a28842SAlexander Lobakin ICE_DECLARE_PKT_OFFSETS(ipv6_gtpu_ipv6_udp) = {
9889a225f81SMarcin Szycik 	{ ICE_MAC_OFOS,		0 },
9899a225f81SMarcin Szycik 	{ ICE_IPV6_OFOS,	14 },
9909a225f81SMarcin Szycik 	{ ICE_UDP_OF,		54 },
9919a225f81SMarcin Szycik 	{ ICE_GTP,		62 },
9929a225f81SMarcin Szycik 	{ ICE_IPV6_IL,		82 },
9939a225f81SMarcin Szycik 	{ ICE_UDP_ILOS,		122 },
9949a225f81SMarcin Szycik 	{ ICE_PROTOCOL_LAST,	0 },
9959a225f81SMarcin Szycik };
9969a225f81SMarcin Szycik 
99707a28842SAlexander Lobakin ICE_DECLARE_PKT_TEMPLATE(ipv6_gtpu_ipv6_udp) = {
9989a225f81SMarcin Szycik 	0x00, 0x00, 0x00, 0x00, /* Ethernet 0 */
9999a225f81SMarcin Szycik 	0x00, 0x00, 0x00, 0x00,
10009a225f81SMarcin Szycik 	0x00, 0x00, 0x00, 0x00,
10019a225f81SMarcin Szycik 	0x86, 0xdd,
10029a225f81SMarcin Szycik 
10039a225f81SMarcin Szycik 	0x60, 0x00, 0x00, 0x00, /* IPv6 14 */
10049a225f81SMarcin Szycik 	0x00, 0x4c, 0x11, 0x00,
10059a225f81SMarcin Szycik 	0x00, 0x00, 0x00, 0x00,
10069a225f81SMarcin Szycik 	0x00, 0x00, 0x00, 0x00,
10079a225f81SMarcin Szycik 	0x00, 0x00, 0x00, 0x00,
10089a225f81SMarcin Szycik 	0x00, 0x00, 0x00, 0x00,
10099a225f81SMarcin Szycik 	0x00, 0x00, 0x00, 0x00,
10109a225f81SMarcin Szycik 	0x00, 0x00, 0x00, 0x00,
10119a225f81SMarcin Szycik 	0x00, 0x00, 0x00, 0x00,
10129a225f81SMarcin Szycik 	0x00, 0x00, 0x00, 0x00,
10139a225f81SMarcin Szycik 
10149a225f81SMarcin Szycik 	0x00, 0x00, 0x08, 0x68, /* UDP 54 */
10159a225f81SMarcin Szycik 	0x00, 0x4c, 0x00, 0x00,
10169a225f81SMarcin Szycik 
10179a225f81SMarcin Szycik 	0x34, 0xff, 0x00, 0x3c, /* ICE_GTP Header 62 */
10189a225f81SMarcin Szycik 	0x00, 0x00, 0x00, 0x00,
10199a225f81SMarcin Szycik 	0x00, 0x00, 0x00, 0x85,
10209a225f81SMarcin Szycik 
10219a225f81SMarcin Szycik 	0x02, 0x00, 0x00, 0x00, /* GTP_PDUSession_ExtensionHeader 74 */
10229a225f81SMarcin Szycik 	0x00, 0x00, 0x00, 0x00,
10239a225f81SMarcin Szycik 
10249a225f81SMarcin Szycik 	0x60, 0x00, 0x00, 0x00, /* IPv6 82 */
10259a225f81SMarcin Szycik 	0x00, 0x08, 0x11, 0x00,
10269a225f81SMarcin Szycik 	0x00, 0x00, 0x00, 0x00,
10279a225f81SMarcin Szycik 	0x00, 0x00, 0x00, 0x00,
10289a225f81SMarcin Szycik 	0x00, 0x00, 0x00, 0x00,
10299a225f81SMarcin Szycik 	0x00, 0x00, 0x00, 0x00,
10309a225f81SMarcin Szycik 	0x00, 0x00, 0x00, 0x00,
10319a225f81SMarcin Szycik 	0x00, 0x00, 0x00, 0x00,
10329a225f81SMarcin Szycik 	0x00, 0x00, 0x00, 0x00,
10339a225f81SMarcin Szycik 	0x00, 0x00, 0x00, 0x00,
10349a225f81SMarcin Szycik 
10359a225f81SMarcin Szycik 	0x00, 0x00, 0x00, 0x00, /* UDP 122 */
10369a225f81SMarcin Szycik 	0x00, 0x08, 0x00, 0x00,
10379a225f81SMarcin Szycik 
10389a225f81SMarcin Szycik 	0x00, 0x00, /* 2 bytes for 4 byte alignment */
10399a225f81SMarcin Szycik };
10409a225f81SMarcin Szycik 
104107a28842SAlexander Lobakin ICE_DECLARE_PKT_OFFSETS(ipv4_gtpu_ipv4) = {
10421b699f81SAlexander Lobakin 	{ ICE_MAC_OFOS,		0 },
10431b699f81SAlexander Lobakin 	{ ICE_IPV4_OFOS,	14 },
10441b699f81SAlexander Lobakin 	{ ICE_UDP_OF,		34 },
10451b699f81SAlexander Lobakin 	{ ICE_GTP_NO_PAY,	42 },
10461b699f81SAlexander Lobakin 	{ ICE_PROTOCOL_LAST,	0 },
10471b699f81SAlexander Lobakin };
10481b699f81SAlexander Lobakin 
104907a28842SAlexander Lobakin ICE_DECLARE_PKT_TEMPLATE(ipv4_gtpu_ipv4) = {
10509a225f81SMarcin Szycik 	0x00, 0x00, 0x00, 0x00, /* ICE_MAC_OFOS 0 */
10519a225f81SMarcin Szycik 	0x00, 0x00, 0x00, 0x00,
10529a225f81SMarcin Szycik 	0x00, 0x00, 0x00, 0x00,
10539a225f81SMarcin Szycik 	0x08, 0x00,
10549a225f81SMarcin Szycik 
10559a225f81SMarcin Szycik 	0x45, 0x00, 0x00, 0x44, /* ICE_IPV4_OFOS 14 */
10569a225f81SMarcin Szycik 	0x00, 0x00, 0x40, 0x00,
10579a225f81SMarcin Szycik 	0x40, 0x11, 0x00, 0x00,
10589a225f81SMarcin Szycik 	0x00, 0x00, 0x00, 0x00,
10599a225f81SMarcin Szycik 	0x00, 0x00, 0x00, 0x00,
10609a225f81SMarcin Szycik 
10619a225f81SMarcin Szycik 	0x08, 0x68, 0x08, 0x68, /* ICE_UDP_OF 34 */
10629a225f81SMarcin Szycik 	0x00, 0x00, 0x00, 0x00,
10639a225f81SMarcin Szycik 
10649a225f81SMarcin Szycik 	0x34, 0xff, 0x00, 0x28, /* ICE_GTP 42 */
10659a225f81SMarcin Szycik 	0x00, 0x00, 0x00, 0x00,
10669a225f81SMarcin Szycik 	0x00, 0x00, 0x00, 0x85,
10679a225f81SMarcin Szycik 
10689a225f81SMarcin Szycik 	0x02, 0x00, 0x00, 0x00, /* PDU Session extension header */
10699a225f81SMarcin Szycik 	0x00, 0x00, 0x00, 0x00,
10709a225f81SMarcin Szycik 
10719a225f81SMarcin Szycik 	0x45, 0x00, 0x00, 0x14, /* ICE_IPV4_IL 62 */
10729a225f81SMarcin Szycik 	0x00, 0x00, 0x40, 0x00,
10739a225f81SMarcin Szycik 	0x40, 0x00, 0x00, 0x00,
10749a225f81SMarcin Szycik 	0x00, 0x00, 0x00, 0x00,
10759a225f81SMarcin Szycik 	0x00, 0x00, 0x00, 0x00,
10769a225f81SMarcin Szycik 	0x00, 0x00,
10779a225f81SMarcin Szycik };
10789a225f81SMarcin Szycik 
107907a28842SAlexander Lobakin ICE_DECLARE_PKT_OFFSETS(ipv6_gtp) = {
10809a225f81SMarcin Szycik 	{ ICE_MAC_OFOS,		0 },
10819a225f81SMarcin Szycik 	{ ICE_IPV6_OFOS,	14 },
10829a225f81SMarcin Szycik 	{ ICE_UDP_OF,		54 },
10839a225f81SMarcin Szycik 	{ ICE_GTP_NO_PAY,	62 },
10849a225f81SMarcin Szycik 	{ ICE_PROTOCOL_LAST,	0 },
10859a225f81SMarcin Szycik };
10869a225f81SMarcin Szycik 
108707a28842SAlexander Lobakin ICE_DECLARE_PKT_TEMPLATE(ipv6_gtp) = {
10889a225f81SMarcin Szycik 	0x00, 0x00, 0x00, 0x00, /* ICE_MAC_OFOS 0 */
10899a225f81SMarcin Szycik 	0x00, 0x00, 0x00, 0x00,
10909a225f81SMarcin Szycik 	0x00, 0x00, 0x00, 0x00,
10919a225f81SMarcin Szycik 	0x86, 0xdd,
10929a225f81SMarcin Szycik 
10939a225f81SMarcin Szycik 	0x60, 0x00, 0x00, 0x00, /* ICE_IPV6_OFOS 14 */
10949a225f81SMarcin Szycik 	0x00, 0x6c, 0x11, 0x00, /* Next header UDP*/
10959a225f81SMarcin Szycik 	0x00, 0x00, 0x00, 0x00,
10969a225f81SMarcin Szycik 	0x00, 0x00, 0x00, 0x00,
10979a225f81SMarcin Szycik 	0x00, 0x00, 0x00, 0x00,
10989a225f81SMarcin Szycik 	0x00, 0x00, 0x00, 0x00,
10999a225f81SMarcin Szycik 	0x00, 0x00, 0x00, 0x00,
11009a225f81SMarcin Szycik 	0x00, 0x00, 0x00, 0x00,
11019a225f81SMarcin Szycik 	0x00, 0x00, 0x00, 0x00,
11029a225f81SMarcin Szycik 	0x00, 0x00, 0x00, 0x00,
11039a225f81SMarcin Szycik 
11049a225f81SMarcin Szycik 	0x08, 0x68, 0x08, 0x68, /* ICE_UDP_OF 54 */
11059a225f81SMarcin Szycik 	0x00, 0x00, 0x00, 0x00,
11069a225f81SMarcin Szycik 
11079a225f81SMarcin Szycik 	0x30, 0x00, 0x00, 0x28, /* ICE_GTP 62 */
11089a225f81SMarcin Szycik 	0x00, 0x00, 0x00, 0x00,
11099a225f81SMarcin Szycik 
11109a225f81SMarcin Szycik 	0x00, 0x00,
11119a225f81SMarcin Szycik };
11129a225f81SMarcin Szycik 
1113cd8efeeeSMarcin Szycik ICE_DECLARE_PKT_OFFSETS(pppoe_ipv4_tcp) = {
1114cd8efeeeSMarcin Szycik 	{ ICE_MAC_OFOS,		0 },
1115cd8efeeeSMarcin Szycik 	{ ICE_ETYPE_OL,		12 },
1116cd8efeeeSMarcin Szycik 	{ ICE_PPPOE,		14 },
1117cd8efeeeSMarcin Szycik 	{ ICE_IPV4_OFOS,	22 },
1118cd8efeeeSMarcin Szycik 	{ ICE_TCP_IL,		42 },
1119cd8efeeeSMarcin Szycik 	{ ICE_PROTOCOL_LAST,	0 },
1120cd8efeeeSMarcin Szycik };
1121cd8efeeeSMarcin Szycik 
1122cd8efeeeSMarcin Szycik ICE_DECLARE_PKT_TEMPLATE(pppoe_ipv4_tcp) = {
1123cd8efeeeSMarcin Szycik 	0x00, 0x00, 0x00, 0x00, /* ICE_MAC_OFOS 0 */
1124cd8efeeeSMarcin Szycik 	0x00, 0x00, 0x00, 0x00,
1125cd8efeeeSMarcin Szycik 	0x00, 0x00, 0x00, 0x00,
1126cd8efeeeSMarcin Szycik 
1127cd8efeeeSMarcin Szycik 	0x88, 0x64,		/* ICE_ETYPE_OL 12 */
1128cd8efeeeSMarcin Szycik 
1129cd8efeeeSMarcin Szycik 	0x11, 0x00, 0x00, 0x00, /* ICE_PPPOE 14 */
1130cd8efeeeSMarcin Szycik 	0x00, 0x16,
1131cd8efeeeSMarcin Szycik 
1132cd8efeeeSMarcin Szycik 	0x00, 0x21,		/* PPP Link Layer 20 */
1133cd8efeeeSMarcin Szycik 
1134cd8efeeeSMarcin Szycik 	0x45, 0x00, 0x00, 0x28, /* ICE_IPV4_OFOS 22 */
1135cd8efeeeSMarcin Szycik 	0x00, 0x01, 0x00, 0x00,
1136cd8efeeeSMarcin Szycik 	0x00, 0x06, 0x00, 0x00,
1137cd8efeeeSMarcin Szycik 	0x00, 0x00, 0x00, 0x00,
1138cd8efeeeSMarcin Szycik 	0x00, 0x00, 0x00, 0x00,
1139cd8efeeeSMarcin Szycik 
1140cd8efeeeSMarcin Szycik 	0x00, 0x00, 0x00, 0x00, /* ICE_TCP_IL 42 */
1141cd8efeeeSMarcin Szycik 	0x00, 0x00, 0x00, 0x00,
1142cd8efeeeSMarcin Szycik 	0x00, 0x00, 0x00, 0x00,
1143cd8efeeeSMarcin Szycik 	0x50, 0x00, 0x00, 0x00,
1144cd8efeeeSMarcin Szycik 	0x00, 0x00, 0x00, 0x00,
1145cd8efeeeSMarcin Szycik 
1146cd8efeeeSMarcin Szycik 	0x00, 0x00,		/* 2 bytes for 4 bytes alignment */
1147cd8efeeeSMarcin Szycik };
1148cd8efeeeSMarcin Szycik 
1149cd8efeeeSMarcin Szycik ICE_DECLARE_PKT_OFFSETS(pppoe_ipv4_udp) = {
1150cd8efeeeSMarcin Szycik 	{ ICE_MAC_OFOS,		0 },
1151cd8efeeeSMarcin Szycik 	{ ICE_ETYPE_OL,		12 },
1152cd8efeeeSMarcin Szycik 	{ ICE_PPPOE,		14 },
1153cd8efeeeSMarcin Szycik 	{ ICE_IPV4_OFOS,	22 },
1154cd8efeeeSMarcin Szycik 	{ ICE_UDP_ILOS,		42 },
1155cd8efeeeSMarcin Szycik 	{ ICE_PROTOCOL_LAST,	0 },
1156cd8efeeeSMarcin Szycik };
1157cd8efeeeSMarcin Szycik 
1158cd8efeeeSMarcin Szycik ICE_DECLARE_PKT_TEMPLATE(pppoe_ipv4_udp) = {
1159cd8efeeeSMarcin Szycik 	0x00, 0x00, 0x00, 0x00, /* ICE_MAC_OFOS 0 */
1160cd8efeeeSMarcin Szycik 	0x00, 0x00, 0x00, 0x00,
1161cd8efeeeSMarcin Szycik 	0x00, 0x00, 0x00, 0x00,
1162cd8efeeeSMarcin Szycik 
1163cd8efeeeSMarcin Szycik 	0x88, 0x64,		/* ICE_ETYPE_OL 12 */
1164cd8efeeeSMarcin Szycik 
1165cd8efeeeSMarcin Szycik 	0x11, 0x00, 0x00, 0x00, /* ICE_PPPOE 14 */
1166cd8efeeeSMarcin Szycik 	0x00, 0x16,
1167cd8efeeeSMarcin Szycik 
1168cd8efeeeSMarcin Szycik 	0x00, 0x21,		/* PPP Link Layer 20 */
1169cd8efeeeSMarcin Szycik 
1170cd8efeeeSMarcin Szycik 	0x45, 0x00, 0x00, 0x1c, /* ICE_IPV4_OFOS 22 */
1171cd8efeeeSMarcin Szycik 	0x00, 0x01, 0x00, 0x00,
1172cd8efeeeSMarcin Szycik 	0x00, 0x11, 0x00, 0x00,
1173cd8efeeeSMarcin Szycik 	0x00, 0x00, 0x00, 0x00,
1174cd8efeeeSMarcin Szycik 	0x00, 0x00, 0x00, 0x00,
1175cd8efeeeSMarcin Szycik 
1176cd8efeeeSMarcin Szycik 	0x00, 0x00, 0x00, 0x00, /* ICE_UDP_ILOS 42 */
1177cd8efeeeSMarcin Szycik 	0x00, 0x08, 0x00, 0x00,
1178cd8efeeeSMarcin Szycik 
1179cd8efeeeSMarcin Szycik 	0x00, 0x00,		/* 2 bytes for 4 bytes alignment */
1180cd8efeeeSMarcin Szycik };
1181cd8efeeeSMarcin Szycik 
1182cd8efeeeSMarcin Szycik ICE_DECLARE_PKT_OFFSETS(pppoe_ipv6_tcp) = {
1183cd8efeeeSMarcin Szycik 	{ ICE_MAC_OFOS,		0 },
1184cd8efeeeSMarcin Szycik 	{ ICE_ETYPE_OL,		12 },
1185cd8efeeeSMarcin Szycik 	{ ICE_PPPOE,		14 },
1186cd8efeeeSMarcin Szycik 	{ ICE_IPV6_OFOS,	22 },
1187cd8efeeeSMarcin Szycik 	{ ICE_TCP_IL,		62 },
1188cd8efeeeSMarcin Szycik 	{ ICE_PROTOCOL_LAST,	0 },
1189cd8efeeeSMarcin Szycik };
1190cd8efeeeSMarcin Szycik 
1191cd8efeeeSMarcin Szycik ICE_DECLARE_PKT_TEMPLATE(pppoe_ipv6_tcp) = {
1192cd8efeeeSMarcin Szycik 	0x00, 0x00, 0x00, 0x00, /* ICE_MAC_OFOS 0 */
1193cd8efeeeSMarcin Szycik 	0x00, 0x00, 0x00, 0x00,
1194cd8efeeeSMarcin Szycik 	0x00, 0x00, 0x00, 0x00,
1195cd8efeeeSMarcin Szycik 
1196cd8efeeeSMarcin Szycik 	0x88, 0x64,		/* ICE_ETYPE_OL 12 */
1197cd8efeeeSMarcin Szycik 
1198cd8efeeeSMarcin Szycik 	0x11, 0x00, 0x00, 0x00, /* ICE_PPPOE 14 */
1199cd8efeeeSMarcin Szycik 	0x00, 0x2a,
1200cd8efeeeSMarcin Szycik 
1201cd8efeeeSMarcin Szycik 	0x00, 0x57,		/* PPP Link Layer 20 */
1202cd8efeeeSMarcin Szycik 
1203cd8efeeeSMarcin Szycik 	0x60, 0x00, 0x00, 0x00, /* ICE_IPV6_OFOS 22 */
1204cd8efeeeSMarcin Szycik 	0x00, 0x14, 0x06, 0x00, /* Next header is TCP */
1205cd8efeeeSMarcin Szycik 	0x00, 0x00, 0x00, 0x00,
1206cd8efeeeSMarcin Szycik 	0x00, 0x00, 0x00, 0x00,
1207cd8efeeeSMarcin Szycik 	0x00, 0x00, 0x00, 0x00,
1208cd8efeeeSMarcin Szycik 	0x00, 0x00, 0x00, 0x00,
1209cd8efeeeSMarcin Szycik 	0x00, 0x00, 0x00, 0x00,
1210cd8efeeeSMarcin Szycik 	0x00, 0x00, 0x00, 0x00,
1211cd8efeeeSMarcin Szycik 	0x00, 0x00, 0x00, 0x00,
1212cd8efeeeSMarcin Szycik 	0x00, 0x00, 0x00, 0x00,
1213cd8efeeeSMarcin Szycik 
1214cd8efeeeSMarcin Szycik 	0x00, 0x00, 0x00, 0x00, /* ICE_TCP_IL 62 */
1215cd8efeeeSMarcin Szycik 	0x00, 0x00, 0x00, 0x00,
1216cd8efeeeSMarcin Szycik 	0x00, 0x00, 0x00, 0x00,
1217cd8efeeeSMarcin Szycik 	0x50, 0x00, 0x00, 0x00,
1218cd8efeeeSMarcin Szycik 	0x00, 0x00, 0x00, 0x00,
1219cd8efeeeSMarcin Szycik 
1220cd8efeeeSMarcin Szycik 	0x00, 0x00,		/* 2 bytes for 4 bytes alignment */
1221cd8efeeeSMarcin Szycik };
1222cd8efeeeSMarcin Szycik 
1223cd8efeeeSMarcin Szycik ICE_DECLARE_PKT_OFFSETS(pppoe_ipv6_udp) = {
1224cd8efeeeSMarcin Szycik 	{ ICE_MAC_OFOS,		0 },
1225cd8efeeeSMarcin Szycik 	{ ICE_ETYPE_OL,		12 },
1226cd8efeeeSMarcin Szycik 	{ ICE_PPPOE,		14 },
1227cd8efeeeSMarcin Szycik 	{ ICE_IPV6_OFOS,	22 },
1228cd8efeeeSMarcin Szycik 	{ ICE_UDP_ILOS,		62 },
1229cd8efeeeSMarcin Szycik 	{ ICE_PROTOCOL_LAST,	0 },
1230cd8efeeeSMarcin Szycik };
1231cd8efeeeSMarcin Szycik 
1232cd8efeeeSMarcin Szycik ICE_DECLARE_PKT_TEMPLATE(pppoe_ipv6_udp) = {
1233cd8efeeeSMarcin Szycik 	0x00, 0x00, 0x00, 0x00, /* ICE_MAC_OFOS 0 */
1234cd8efeeeSMarcin Szycik 	0x00, 0x00, 0x00, 0x00,
1235cd8efeeeSMarcin Szycik 	0x00, 0x00, 0x00, 0x00,
1236cd8efeeeSMarcin Szycik 
1237cd8efeeeSMarcin Szycik 	0x88, 0x64,		/* ICE_ETYPE_OL 12 */
1238cd8efeeeSMarcin Szycik 
1239cd8efeeeSMarcin Szycik 	0x11, 0x00, 0x00, 0x00, /* ICE_PPPOE 14 */
1240cd8efeeeSMarcin Szycik 	0x00, 0x2a,
1241cd8efeeeSMarcin Szycik 
1242cd8efeeeSMarcin Szycik 	0x00, 0x57,		/* PPP Link Layer 20 */
1243cd8efeeeSMarcin Szycik 
1244cd8efeeeSMarcin Szycik 	0x60, 0x00, 0x00, 0x00, /* ICE_IPV6_OFOS 22 */
1245cd8efeeeSMarcin Szycik 	0x00, 0x08, 0x11, 0x00, /* Next header UDP*/
1246cd8efeeeSMarcin Szycik 	0x00, 0x00, 0x00, 0x00,
1247cd8efeeeSMarcin Szycik 	0x00, 0x00, 0x00, 0x00,
1248cd8efeeeSMarcin Szycik 	0x00, 0x00, 0x00, 0x00,
1249cd8efeeeSMarcin Szycik 	0x00, 0x00, 0x00, 0x00,
1250cd8efeeeSMarcin Szycik 	0x00, 0x00, 0x00, 0x00,
1251cd8efeeeSMarcin Szycik 	0x00, 0x00, 0x00, 0x00,
1252cd8efeeeSMarcin Szycik 	0x00, 0x00, 0x00, 0x00,
1253cd8efeeeSMarcin Szycik 	0x00, 0x00, 0x00, 0x00,
1254cd8efeeeSMarcin Szycik 
1255cd8efeeeSMarcin Szycik 	0x00, 0x00, 0x00, 0x00, /* ICE_UDP_ILOS 62 */
1256cd8efeeeSMarcin Szycik 	0x00, 0x08, 0x00, 0x00,
1257cd8efeeeSMarcin Szycik 
1258cd8efeeeSMarcin Szycik 	0x00, 0x00,		/* 2 bytes for 4 bytes alignment */
1259cd8efeeeSMarcin Szycik };
1260cd8efeeeSMarcin Szycik 
1261e33163a4SAlexander Lobakin static const struct ice_dummy_pkt_profile ice_dummy_pkt_profiles[] = {
1262e33163a4SAlexander Lobakin 	ICE_PKT_PROFILE(ipv6_gtp, ICE_PKT_TUN_GTPU | ICE_PKT_OUTER_IPV6 |
1263e33163a4SAlexander Lobakin 				  ICE_PKT_GTP_NOPAY),
1264e33163a4SAlexander Lobakin 	ICE_PKT_PROFILE(ipv6_gtpu_ipv6_udp, ICE_PKT_TUN_GTPU |
1265e33163a4SAlexander Lobakin 					    ICE_PKT_OUTER_IPV6 |
1266e33163a4SAlexander Lobakin 					    ICE_PKT_INNER_IPV6 |
1267e33163a4SAlexander Lobakin 					    ICE_PKT_INNER_UDP),
1268e33163a4SAlexander Lobakin 	ICE_PKT_PROFILE(ipv6_gtpu_ipv6_tcp, ICE_PKT_TUN_GTPU |
1269e33163a4SAlexander Lobakin 					    ICE_PKT_OUTER_IPV6 |
1270e33163a4SAlexander Lobakin 					    ICE_PKT_INNER_IPV6),
1271e33163a4SAlexander Lobakin 	ICE_PKT_PROFILE(ipv6_gtpu_ipv4_udp, ICE_PKT_TUN_GTPU |
1272e33163a4SAlexander Lobakin 					    ICE_PKT_OUTER_IPV6 |
1273e33163a4SAlexander Lobakin 					    ICE_PKT_INNER_UDP),
1274e33163a4SAlexander Lobakin 	ICE_PKT_PROFILE(ipv6_gtpu_ipv4_tcp, ICE_PKT_TUN_GTPU |
1275e33163a4SAlexander Lobakin 					    ICE_PKT_OUTER_IPV6),
1276e33163a4SAlexander Lobakin 	ICE_PKT_PROFILE(ipv4_gtpu_ipv4, ICE_PKT_TUN_GTPU | ICE_PKT_GTP_NOPAY),
1277e33163a4SAlexander Lobakin 	ICE_PKT_PROFILE(ipv4_gtpu_ipv6_udp, ICE_PKT_TUN_GTPU |
1278e33163a4SAlexander Lobakin 					    ICE_PKT_INNER_IPV6 |
1279e33163a4SAlexander Lobakin 					    ICE_PKT_INNER_UDP),
1280e33163a4SAlexander Lobakin 	ICE_PKT_PROFILE(ipv4_gtpu_ipv6_tcp, ICE_PKT_TUN_GTPU |
1281e33163a4SAlexander Lobakin 					    ICE_PKT_INNER_IPV6),
1282e33163a4SAlexander Lobakin 	ICE_PKT_PROFILE(ipv4_gtpu_ipv4_udp, ICE_PKT_TUN_GTPU |
1283e33163a4SAlexander Lobakin 					    ICE_PKT_INNER_UDP),
1284e33163a4SAlexander Lobakin 	ICE_PKT_PROFILE(ipv4_gtpu_ipv4_tcp, ICE_PKT_TUN_GTPU),
1285e33163a4SAlexander Lobakin 	ICE_PKT_PROFILE(ipv6_gtp, ICE_PKT_TUN_GTPC | ICE_PKT_OUTER_IPV6),
1286e33163a4SAlexander Lobakin 	ICE_PKT_PROFILE(ipv4_gtpu_ipv4, ICE_PKT_TUN_GTPC),
1287cd8efeeeSMarcin Szycik 	ICE_PKT_PROFILE(pppoe_ipv6_udp, ICE_PKT_PPPOE | ICE_PKT_OUTER_IPV6 |
1288cd8efeeeSMarcin Szycik 					ICE_PKT_INNER_UDP),
1289cd8efeeeSMarcin Szycik 	ICE_PKT_PROFILE(pppoe_ipv6_tcp, ICE_PKT_PPPOE | ICE_PKT_OUTER_IPV6),
1290cd8efeeeSMarcin Szycik 	ICE_PKT_PROFILE(pppoe_ipv4_udp, ICE_PKT_PPPOE | ICE_PKT_INNER_UDP),
1291cd8efeeeSMarcin Szycik 	ICE_PKT_PROFILE(pppoe_ipv4_tcp, ICE_PKT_PPPOE),
1292e33163a4SAlexander Lobakin 	ICE_PKT_PROFILE(gre_ipv6_tcp, ICE_PKT_TUN_NVGRE | ICE_PKT_INNER_IPV6 |
1293e33163a4SAlexander Lobakin 				      ICE_PKT_INNER_TCP),
1294e33163a4SAlexander Lobakin 	ICE_PKT_PROFILE(gre_tcp, ICE_PKT_TUN_NVGRE | ICE_PKT_INNER_TCP),
1295e33163a4SAlexander Lobakin 	ICE_PKT_PROFILE(gre_ipv6_udp, ICE_PKT_TUN_NVGRE | ICE_PKT_INNER_IPV6),
1296e33163a4SAlexander Lobakin 	ICE_PKT_PROFILE(gre_udp, ICE_PKT_TUN_NVGRE),
1297e33163a4SAlexander Lobakin 	ICE_PKT_PROFILE(udp_tun_ipv6_tcp, ICE_PKT_TUN_UDP |
1298e33163a4SAlexander Lobakin 					  ICE_PKT_INNER_IPV6 |
1299e33163a4SAlexander Lobakin 					  ICE_PKT_INNER_TCP),
1300e33163a4SAlexander Lobakin 	ICE_PKT_PROFILE(udp_tun_tcp, ICE_PKT_TUN_UDP | ICE_PKT_INNER_TCP),
1301e33163a4SAlexander Lobakin 	ICE_PKT_PROFILE(udp_tun_ipv6_udp, ICE_PKT_TUN_UDP |
1302e33163a4SAlexander Lobakin 					  ICE_PKT_INNER_IPV6),
1303e33163a4SAlexander Lobakin 	ICE_PKT_PROFILE(udp_tun_udp, ICE_PKT_TUN_UDP),
1304e33163a4SAlexander Lobakin 	ICE_PKT_PROFILE(udp_ipv6, ICE_PKT_OUTER_IPV6 | ICE_PKT_INNER_UDP),
1305e33163a4SAlexander Lobakin 	ICE_PKT_PROFILE(udp, ICE_PKT_INNER_UDP),
1306e33163a4SAlexander Lobakin 	ICE_PKT_PROFILE(tcp_ipv6, ICE_PKT_OUTER_IPV6),
1307e33163a4SAlexander Lobakin 	ICE_PKT_PROFILE(tcp, 0),
1308e33163a4SAlexander Lobakin };
1309e33163a4SAlexander Lobakin 
13106e1ff618SAlexander Lobakin #define ICE_SW_RULE_RX_TX_HDR_SIZE(s, l)	struct_size((s), hdr_data, (l))
13116e1ff618SAlexander Lobakin #define ICE_SW_RULE_RX_TX_ETH_HDR_SIZE(s)	\
13126e1ff618SAlexander Lobakin 	ICE_SW_RULE_RX_TX_HDR_SIZE((s), DUMMY_ETH_HDR_LEN)
13136e1ff618SAlexander Lobakin #define ICE_SW_RULE_RX_TX_NO_HDR_SIZE(s)	\
13146e1ff618SAlexander Lobakin 	ICE_SW_RULE_RX_TX_HDR_SIZE((s), 0)
13156e1ff618SAlexander Lobakin #define ICE_SW_RULE_LG_ACT_SIZE(s, n)		struct_size((s), act, (n))
13166e1ff618SAlexander Lobakin #define ICE_SW_RULE_VSI_LIST_SIZE(s, n)		struct_size((s), vsi, (n))
13179daf8208SAnirudh Venkataramanan 
1318fd2a6b71SDan Nowlin /* this is a recipe to profile association bitmap */
1319fd2a6b71SDan Nowlin static DECLARE_BITMAP(recipe_to_profile[ICE_MAX_NUM_RECIPES],
1320fd2a6b71SDan Nowlin 			  ICE_MAX_NUM_PROFILES);
1321fd2a6b71SDan Nowlin 
1322fd2a6b71SDan Nowlin /* this is a profile to recipe association bitmap */
1323fd2a6b71SDan Nowlin static DECLARE_BITMAP(profile_to_recipe[ICE_MAX_NUM_PROFILES],
1324fd2a6b71SDan Nowlin 			  ICE_MAX_NUM_RECIPES);
1325fd2a6b71SDan Nowlin 
13269daf8208SAnirudh Venkataramanan /**
132780d144c9SAnirudh Venkataramanan  * ice_init_def_sw_recp - initialize the recipe book keeping tables
1328f9867df6SAnirudh Venkataramanan  * @hw: pointer to the HW struct
132980d144c9SAnirudh Venkataramanan  *
133080d144c9SAnirudh Venkataramanan  * Allocate memory for the entire recipe table and initialize the structures/
133180d144c9SAnirudh Venkataramanan  * entries corresponding to basic recipes.
133280d144c9SAnirudh Venkataramanan  */
13335e24d598STony Nguyen int ice_init_def_sw_recp(struct ice_hw *hw)
133480d144c9SAnirudh Venkataramanan {
133580d144c9SAnirudh Venkataramanan 	struct ice_sw_recipe *recps;
133680d144c9SAnirudh Venkataramanan 	u8 i;
133780d144c9SAnirudh Venkataramanan 
133880d144c9SAnirudh Venkataramanan 	recps = devm_kcalloc(ice_hw_to_dev(hw), ICE_MAX_NUM_RECIPES,
1339c6dfd690SBruce Allan 			     sizeof(*recps), GFP_KERNEL);
134080d144c9SAnirudh Venkataramanan 	if (!recps)
1341d54699e2STony Nguyen 		return -ENOMEM;
134280d144c9SAnirudh Venkataramanan 
1343450052a4SDan Nowlin 	for (i = 0; i < ICE_MAX_NUM_RECIPES; i++) {
134480d144c9SAnirudh Venkataramanan 		recps[i].root_rid = i;
134580d144c9SAnirudh Venkataramanan 		INIT_LIST_HEAD(&recps[i].filt_rules);
1346334cb062SAnirudh Venkataramanan 		INIT_LIST_HEAD(&recps[i].filt_replay_rules);
1347450052a4SDan Nowlin 		INIT_LIST_HEAD(&recps[i].rg_list);
134880d144c9SAnirudh Venkataramanan 		mutex_init(&recps[i].filt_rule_lock);
134980d144c9SAnirudh Venkataramanan 	}
135080d144c9SAnirudh Venkataramanan 
135180d144c9SAnirudh Venkataramanan 	hw->switch_info->recp_list = recps;
135280d144c9SAnirudh Venkataramanan 
135380d144c9SAnirudh Venkataramanan 	return 0;
135480d144c9SAnirudh Venkataramanan }
135580d144c9SAnirudh Venkataramanan 
135680d144c9SAnirudh Venkataramanan /**
13579c20346bSAnirudh Venkataramanan  * ice_aq_get_sw_cfg - get switch configuration
13589c20346bSAnirudh Venkataramanan  * @hw: pointer to the hardware structure
13599c20346bSAnirudh Venkataramanan  * @buf: pointer to the result buffer
13609c20346bSAnirudh Venkataramanan  * @buf_size: length of the buffer available for response
13619c20346bSAnirudh Venkataramanan  * @req_desc: pointer to requested descriptor
13629c20346bSAnirudh Venkataramanan  * @num_elems: pointer to number of elements
13639c20346bSAnirudh Venkataramanan  * @cd: pointer to command details structure or NULL
13649c20346bSAnirudh Venkataramanan  *
1365b3c38904SBruce Allan  * Get switch configuration (0x0200) to be placed in buf.
13669c20346bSAnirudh Venkataramanan  * This admin command returns information such as initial VSI/port number
13679c20346bSAnirudh Venkataramanan  * and switch ID it belongs to.
13689c20346bSAnirudh Venkataramanan  *
13699c20346bSAnirudh Venkataramanan  * NOTE: *req_desc is both an input/output parameter.
13709c20346bSAnirudh Venkataramanan  * The caller of this function first calls this function with *request_desc set
13719c20346bSAnirudh Venkataramanan  * to 0. If the response from f/w has *req_desc set to 0, all the switch
13729c20346bSAnirudh Venkataramanan  * configuration information has been returned; if non-zero (meaning not all
13739c20346bSAnirudh Venkataramanan  * the information was returned), the caller should call this function again
13749c20346bSAnirudh Venkataramanan  * with *req_desc set to the previous value returned by f/w to get the
13759c20346bSAnirudh Venkataramanan  * next block of switch configuration information.
13769c20346bSAnirudh Venkataramanan  *
13779c20346bSAnirudh Venkataramanan  * *num_elems is output only parameter. This reflects the number of elements
13789c20346bSAnirudh Venkataramanan  * in response buffer. The caller of this function to use *num_elems while
13799c20346bSAnirudh Venkataramanan  * parsing the response buffer.
13809c20346bSAnirudh Venkataramanan  */
13815e24d598STony Nguyen static int
1382b3c38904SBruce Allan ice_aq_get_sw_cfg(struct ice_hw *hw, struct ice_aqc_get_sw_cfg_resp_elem *buf,
13839c20346bSAnirudh Venkataramanan 		  u16 buf_size, u16 *req_desc, u16 *num_elems,
13849c20346bSAnirudh Venkataramanan 		  struct ice_sq_cd *cd)
13859c20346bSAnirudh Venkataramanan {
13869c20346bSAnirudh Venkataramanan 	struct ice_aqc_get_sw_cfg *cmd;
13879c20346bSAnirudh Venkataramanan 	struct ice_aq_desc desc;
13885e24d598STony Nguyen 	int status;
13899c20346bSAnirudh Venkataramanan 
13909c20346bSAnirudh Venkataramanan 	ice_fill_dflt_direct_cmd_desc(&desc, ice_aqc_opc_get_sw_cfg);
13919c20346bSAnirudh Venkataramanan 	cmd = &desc.params.get_sw_conf;
13929c20346bSAnirudh Venkataramanan 	cmd->element = cpu_to_le16(*req_desc);
13939c20346bSAnirudh Venkataramanan 
13949c20346bSAnirudh Venkataramanan 	status = ice_aq_send_cmd(hw, &desc, buf, buf_size, cd);
13959c20346bSAnirudh Venkataramanan 	if (!status) {
13969c20346bSAnirudh Venkataramanan 		*req_desc = le16_to_cpu(cmd->element);
13979c20346bSAnirudh Venkataramanan 		*num_elems = le16_to_cpu(cmd->num_elems);
13989c20346bSAnirudh Venkataramanan 	}
13999c20346bSAnirudh Venkataramanan 
14009c20346bSAnirudh Venkataramanan 	return status;
14019c20346bSAnirudh Venkataramanan }
14029c20346bSAnirudh Venkataramanan 
14033a858ba3SAnirudh Venkataramanan /**
14043a858ba3SAnirudh Venkataramanan  * ice_aq_add_vsi
1405f9867df6SAnirudh Venkataramanan  * @hw: pointer to the HW struct
14063a858ba3SAnirudh Venkataramanan  * @vsi_ctx: pointer to a VSI context struct
14073a858ba3SAnirudh Venkataramanan  * @cd: pointer to command details structure or NULL
14083a858ba3SAnirudh Venkataramanan  *
14093a858ba3SAnirudh Venkataramanan  * Add a VSI context to the hardware (0x0210)
14103a858ba3SAnirudh Venkataramanan  */
14115e24d598STony Nguyen static int
14123a858ba3SAnirudh Venkataramanan ice_aq_add_vsi(struct ice_hw *hw, struct ice_vsi_ctx *vsi_ctx,
14133a858ba3SAnirudh Venkataramanan 	       struct ice_sq_cd *cd)
14143a858ba3SAnirudh Venkataramanan {
14153a858ba3SAnirudh Venkataramanan 	struct ice_aqc_add_update_free_vsi_resp *res;
14163a858ba3SAnirudh Venkataramanan 	struct ice_aqc_add_get_update_free_vsi *cmd;
14173a858ba3SAnirudh Venkataramanan 	struct ice_aq_desc desc;
14185e24d598STony Nguyen 	int status;
14193a858ba3SAnirudh Venkataramanan 
14203a858ba3SAnirudh Venkataramanan 	cmd = &desc.params.vsi_cmd;
14210f9d5027SAnirudh Venkataramanan 	res = &desc.params.add_update_free_vsi_res;
14223a858ba3SAnirudh Venkataramanan 
14233a858ba3SAnirudh Venkataramanan 	ice_fill_dflt_direct_cmd_desc(&desc, ice_aqc_opc_add_vsi);
14243a858ba3SAnirudh Venkataramanan 
14253a858ba3SAnirudh Venkataramanan 	if (!vsi_ctx->alloc_from_pool)
14263a858ba3SAnirudh Venkataramanan 		cmd->vsi_num = cpu_to_le16(vsi_ctx->vsi_num |
14273a858ba3SAnirudh Venkataramanan 					   ICE_AQ_VSI_IS_VALID);
14281071a835SAnirudh Venkataramanan 	cmd->vf_id = vsi_ctx->vf_num;
14293a858ba3SAnirudh Venkataramanan 
14303a858ba3SAnirudh Venkataramanan 	cmd->vsi_flags = cpu_to_le16(vsi_ctx->flags);
14313a858ba3SAnirudh Venkataramanan 
14323a858ba3SAnirudh Venkataramanan 	desc.flags |= cpu_to_le16(ICE_AQ_FLAG_RD);
14333a858ba3SAnirudh Venkataramanan 
14343a858ba3SAnirudh Venkataramanan 	status = ice_aq_send_cmd(hw, &desc, &vsi_ctx->info,
14353a858ba3SAnirudh Venkataramanan 				 sizeof(vsi_ctx->info), cd);
14363a858ba3SAnirudh Venkataramanan 
14373a858ba3SAnirudh Venkataramanan 	if (!status) {
14383a858ba3SAnirudh Venkataramanan 		vsi_ctx->vsi_num = le16_to_cpu(res->vsi_num) & ICE_AQ_VSI_NUM_M;
14393a858ba3SAnirudh Venkataramanan 		vsi_ctx->vsis_allocd = le16_to_cpu(res->vsi_used);
14403a858ba3SAnirudh Venkataramanan 		vsi_ctx->vsis_unallocated = le16_to_cpu(res->vsi_free);
14413a858ba3SAnirudh Venkataramanan 	}
14423a858ba3SAnirudh Venkataramanan 
14433a858ba3SAnirudh Venkataramanan 	return status;
14443a858ba3SAnirudh Venkataramanan }
14453a858ba3SAnirudh Venkataramanan 
14463a858ba3SAnirudh Venkataramanan /**
14470f9d5027SAnirudh Venkataramanan  * ice_aq_free_vsi
1448f9867df6SAnirudh Venkataramanan  * @hw: pointer to the HW struct
14490f9d5027SAnirudh Venkataramanan  * @vsi_ctx: pointer to a VSI context struct
14500f9d5027SAnirudh Venkataramanan  * @keep_vsi_alloc: keep VSI allocation as part of this PF's resources
14510f9d5027SAnirudh Venkataramanan  * @cd: pointer to command details structure or NULL
14520f9d5027SAnirudh Venkataramanan  *
14530f9d5027SAnirudh Venkataramanan  * Free VSI context info from hardware (0x0213)
14540f9d5027SAnirudh Venkataramanan  */
14555e24d598STony Nguyen static int
14560f9d5027SAnirudh Venkataramanan ice_aq_free_vsi(struct ice_hw *hw, struct ice_vsi_ctx *vsi_ctx,
14570f9d5027SAnirudh Venkataramanan 		bool keep_vsi_alloc, struct ice_sq_cd *cd)
14580f9d5027SAnirudh Venkataramanan {
14590f9d5027SAnirudh Venkataramanan 	struct ice_aqc_add_update_free_vsi_resp *resp;
14600f9d5027SAnirudh Venkataramanan 	struct ice_aqc_add_get_update_free_vsi *cmd;
14610f9d5027SAnirudh Venkataramanan 	struct ice_aq_desc desc;
14625e24d598STony Nguyen 	int status;
14630f9d5027SAnirudh Venkataramanan 
14640f9d5027SAnirudh Venkataramanan 	cmd = &desc.params.vsi_cmd;
14650f9d5027SAnirudh Venkataramanan 	resp = &desc.params.add_update_free_vsi_res;
14660f9d5027SAnirudh Venkataramanan 
14670f9d5027SAnirudh Venkataramanan 	ice_fill_dflt_direct_cmd_desc(&desc, ice_aqc_opc_free_vsi);
14680f9d5027SAnirudh Venkataramanan 
14690f9d5027SAnirudh Venkataramanan 	cmd->vsi_num = cpu_to_le16(vsi_ctx->vsi_num | ICE_AQ_VSI_IS_VALID);
14700f9d5027SAnirudh Venkataramanan 	if (keep_vsi_alloc)
14710f9d5027SAnirudh Venkataramanan 		cmd->cmd_flags = cpu_to_le16(ICE_AQ_VSI_KEEP_ALLOC);
14720f9d5027SAnirudh Venkataramanan 
14730f9d5027SAnirudh Venkataramanan 	status = ice_aq_send_cmd(hw, &desc, NULL, 0, cd);
14740f9d5027SAnirudh Venkataramanan 	if (!status) {
14750f9d5027SAnirudh Venkataramanan 		vsi_ctx->vsis_allocd = le16_to_cpu(resp->vsi_used);
14760f9d5027SAnirudh Venkataramanan 		vsi_ctx->vsis_unallocated = le16_to_cpu(resp->vsi_free);
14770f9d5027SAnirudh Venkataramanan 	}
14780f9d5027SAnirudh Venkataramanan 
14790f9d5027SAnirudh Venkataramanan 	return status;
14800f9d5027SAnirudh Venkataramanan }
14810f9d5027SAnirudh Venkataramanan 
14820f9d5027SAnirudh Venkataramanan /**
14833a858ba3SAnirudh Venkataramanan  * ice_aq_update_vsi
1484f9867df6SAnirudh Venkataramanan  * @hw: pointer to the HW struct
14853a858ba3SAnirudh Venkataramanan  * @vsi_ctx: pointer to a VSI context struct
14863a858ba3SAnirudh Venkataramanan  * @cd: pointer to command details structure or NULL
14873a858ba3SAnirudh Venkataramanan  *
14883a858ba3SAnirudh Venkataramanan  * Update VSI context in the hardware (0x0211)
14893a858ba3SAnirudh Venkataramanan  */
14905e24d598STony Nguyen static int
14913a858ba3SAnirudh Venkataramanan ice_aq_update_vsi(struct ice_hw *hw, struct ice_vsi_ctx *vsi_ctx,
14923a858ba3SAnirudh Venkataramanan 		  struct ice_sq_cd *cd)
14933a858ba3SAnirudh Venkataramanan {
14943a858ba3SAnirudh Venkataramanan 	struct ice_aqc_add_update_free_vsi_resp *resp;
14953a858ba3SAnirudh Venkataramanan 	struct ice_aqc_add_get_update_free_vsi *cmd;
14963a858ba3SAnirudh Venkataramanan 	struct ice_aq_desc desc;
14975e24d598STony Nguyen 	int status;
14983a858ba3SAnirudh Venkataramanan 
14993a858ba3SAnirudh Venkataramanan 	cmd = &desc.params.vsi_cmd;
15000f9d5027SAnirudh Venkataramanan 	resp = &desc.params.add_update_free_vsi_res;
15013a858ba3SAnirudh Venkataramanan 
15023a858ba3SAnirudh Venkataramanan 	ice_fill_dflt_direct_cmd_desc(&desc, ice_aqc_opc_update_vsi);
15033a858ba3SAnirudh Venkataramanan 
15043a858ba3SAnirudh Venkataramanan 	cmd->vsi_num = cpu_to_le16(vsi_ctx->vsi_num | ICE_AQ_VSI_IS_VALID);
15053a858ba3SAnirudh Venkataramanan 
15063a858ba3SAnirudh Venkataramanan 	desc.flags |= cpu_to_le16(ICE_AQ_FLAG_RD);
15073a858ba3SAnirudh Venkataramanan 
15083a858ba3SAnirudh Venkataramanan 	status = ice_aq_send_cmd(hw, &desc, &vsi_ctx->info,
15093a858ba3SAnirudh Venkataramanan 				 sizeof(vsi_ctx->info), cd);
15103a858ba3SAnirudh Venkataramanan 
15113a858ba3SAnirudh Venkataramanan 	if (!status) {
15123a858ba3SAnirudh Venkataramanan 		vsi_ctx->vsis_allocd = le16_to_cpu(resp->vsi_used);
15133a858ba3SAnirudh Venkataramanan 		vsi_ctx->vsis_unallocated = le16_to_cpu(resp->vsi_free);
15143a858ba3SAnirudh Venkataramanan 	}
15153a858ba3SAnirudh Venkataramanan 
15163a858ba3SAnirudh Venkataramanan 	return status;
15173a858ba3SAnirudh Venkataramanan }
15183a858ba3SAnirudh Venkataramanan 
15193a858ba3SAnirudh Venkataramanan /**
15200f9d5027SAnirudh Venkataramanan  * ice_is_vsi_valid - check whether the VSI is valid or not
1521f9867df6SAnirudh Venkataramanan  * @hw: pointer to the HW struct
15220f9d5027SAnirudh Venkataramanan  * @vsi_handle: VSI handle
15230f9d5027SAnirudh Venkataramanan  *
15240f9d5027SAnirudh Venkataramanan  * check whether the VSI is valid or not
15250f9d5027SAnirudh Venkataramanan  */
15264fb33f31SAnirudh Venkataramanan bool ice_is_vsi_valid(struct ice_hw *hw, u16 vsi_handle)
15270f9d5027SAnirudh Venkataramanan {
15280f9d5027SAnirudh Venkataramanan 	return vsi_handle < ICE_MAX_VSI && hw->vsi_ctx[vsi_handle];
15290f9d5027SAnirudh Venkataramanan }
15300f9d5027SAnirudh Venkataramanan 
15310f9d5027SAnirudh Venkataramanan /**
1532f9867df6SAnirudh Venkataramanan  * ice_get_hw_vsi_num - return the HW VSI number
1533f9867df6SAnirudh Venkataramanan  * @hw: pointer to the HW struct
15340f9d5027SAnirudh Venkataramanan  * @vsi_handle: VSI handle
15350f9d5027SAnirudh Venkataramanan  *
1536f9867df6SAnirudh Venkataramanan  * return the HW VSI number
15370f9d5027SAnirudh Venkataramanan  * Caution: call this function only if VSI is valid (ice_is_vsi_valid)
15380f9d5027SAnirudh Venkataramanan  */
15394fb33f31SAnirudh Venkataramanan u16 ice_get_hw_vsi_num(struct ice_hw *hw, u16 vsi_handle)
15400f9d5027SAnirudh Venkataramanan {
15410f9d5027SAnirudh Venkataramanan 	return hw->vsi_ctx[vsi_handle]->vsi_num;
15420f9d5027SAnirudh Venkataramanan }
15430f9d5027SAnirudh Venkataramanan 
15440f9d5027SAnirudh Venkataramanan /**
15450f9d5027SAnirudh Venkataramanan  * ice_get_vsi_ctx - return the VSI context entry for a given VSI handle
1546f9867df6SAnirudh Venkataramanan  * @hw: pointer to the HW struct
15470f9d5027SAnirudh Venkataramanan  * @vsi_handle: VSI handle
15480f9d5027SAnirudh Venkataramanan  *
15490f9d5027SAnirudh Venkataramanan  * return the VSI context entry for a given VSI handle
15500f9d5027SAnirudh Venkataramanan  */
15514fb33f31SAnirudh Venkataramanan struct ice_vsi_ctx *ice_get_vsi_ctx(struct ice_hw *hw, u16 vsi_handle)
15520f9d5027SAnirudh Venkataramanan {
15530f9d5027SAnirudh Venkataramanan 	return (vsi_handle >= ICE_MAX_VSI) ? NULL : hw->vsi_ctx[vsi_handle];
15540f9d5027SAnirudh Venkataramanan }
15550f9d5027SAnirudh Venkataramanan 
15560f9d5027SAnirudh Venkataramanan /**
15570f9d5027SAnirudh Venkataramanan  * ice_save_vsi_ctx - save the VSI context for a given VSI handle
1558f9867df6SAnirudh Venkataramanan  * @hw: pointer to the HW struct
15590f9d5027SAnirudh Venkataramanan  * @vsi_handle: VSI handle
15600f9d5027SAnirudh Venkataramanan  * @vsi: VSI context pointer
15610f9d5027SAnirudh Venkataramanan  *
15620f9d5027SAnirudh Venkataramanan  * save the VSI context entry for a given VSI handle
15630f9d5027SAnirudh Venkataramanan  */
1564c8b7abddSBruce Allan static void
1565c8b7abddSBruce Allan ice_save_vsi_ctx(struct ice_hw *hw, u16 vsi_handle, struct ice_vsi_ctx *vsi)
15660f9d5027SAnirudh Venkataramanan {
15670f9d5027SAnirudh Venkataramanan 	hw->vsi_ctx[vsi_handle] = vsi;
15680f9d5027SAnirudh Venkataramanan }
15690f9d5027SAnirudh Venkataramanan 
15700f9d5027SAnirudh Venkataramanan /**
1571bb87ee0eSAnirudh Venkataramanan  * ice_clear_vsi_q_ctx - clear VSI queue contexts for all TCs
1572bb87ee0eSAnirudh Venkataramanan  * @hw: pointer to the HW struct
1573bb87ee0eSAnirudh Venkataramanan  * @vsi_handle: VSI handle
1574bb87ee0eSAnirudh Venkataramanan  */
1575bb87ee0eSAnirudh Venkataramanan static void ice_clear_vsi_q_ctx(struct ice_hw *hw, u16 vsi_handle)
1576bb87ee0eSAnirudh Venkataramanan {
1577bb87ee0eSAnirudh Venkataramanan 	struct ice_vsi_ctx *vsi;
1578bb87ee0eSAnirudh Venkataramanan 	u8 i;
1579bb87ee0eSAnirudh Venkataramanan 
1580bb87ee0eSAnirudh Venkataramanan 	vsi = ice_get_vsi_ctx(hw, vsi_handle);
1581bb87ee0eSAnirudh Venkataramanan 	if (!vsi)
1582bb87ee0eSAnirudh Venkataramanan 		return;
1583bb87ee0eSAnirudh Venkataramanan 	ice_for_each_traffic_class(i) {
1584bb87ee0eSAnirudh Venkataramanan 		if (vsi->lan_q_ctx[i]) {
1585bb87ee0eSAnirudh Venkataramanan 			devm_kfree(ice_hw_to_dev(hw), vsi->lan_q_ctx[i]);
1586bb87ee0eSAnirudh Venkataramanan 			vsi->lan_q_ctx[i] = NULL;
1587bb87ee0eSAnirudh Venkataramanan 		}
1588348048e7SDave Ertman 		if (vsi->rdma_q_ctx[i]) {
1589348048e7SDave Ertman 			devm_kfree(ice_hw_to_dev(hw), vsi->rdma_q_ctx[i]);
1590348048e7SDave Ertman 			vsi->rdma_q_ctx[i] = NULL;
1591348048e7SDave Ertman 		}
1592bb87ee0eSAnirudh Venkataramanan 	}
1593bb87ee0eSAnirudh Venkataramanan }
1594bb87ee0eSAnirudh Venkataramanan 
1595bb87ee0eSAnirudh Venkataramanan /**
15960f9d5027SAnirudh Venkataramanan  * ice_clear_vsi_ctx - clear the VSI context entry
1597f9867df6SAnirudh Venkataramanan  * @hw: pointer to the HW struct
15980f9d5027SAnirudh Venkataramanan  * @vsi_handle: VSI handle
15990f9d5027SAnirudh Venkataramanan  *
16000f9d5027SAnirudh Venkataramanan  * clear the VSI context entry
16010f9d5027SAnirudh Venkataramanan  */
16020f9d5027SAnirudh Venkataramanan static void ice_clear_vsi_ctx(struct ice_hw *hw, u16 vsi_handle)
16030f9d5027SAnirudh Venkataramanan {
16040f9d5027SAnirudh Venkataramanan 	struct ice_vsi_ctx *vsi;
16050f9d5027SAnirudh Venkataramanan 
16060f9d5027SAnirudh Venkataramanan 	vsi = ice_get_vsi_ctx(hw, vsi_handle);
16070f9d5027SAnirudh Venkataramanan 	if (vsi) {
1608bb87ee0eSAnirudh Venkataramanan 		ice_clear_vsi_q_ctx(hw, vsi_handle);
16090f9d5027SAnirudh Venkataramanan 		devm_kfree(ice_hw_to_dev(hw), vsi);
16100f9d5027SAnirudh Venkataramanan 		hw->vsi_ctx[vsi_handle] = NULL;
16110f9d5027SAnirudh Venkataramanan 	}
16120f9d5027SAnirudh Venkataramanan }
16130f9d5027SAnirudh Venkataramanan 
16140f9d5027SAnirudh Venkataramanan /**
161533e055fcSVictor Raj  * ice_clear_all_vsi_ctx - clear all the VSI context entries
1616f9867df6SAnirudh Venkataramanan  * @hw: pointer to the HW struct
161733e055fcSVictor Raj  */
161833e055fcSVictor Raj void ice_clear_all_vsi_ctx(struct ice_hw *hw)
161933e055fcSVictor Raj {
162033e055fcSVictor Raj 	u16 i;
162133e055fcSVictor Raj 
162233e055fcSVictor Raj 	for (i = 0; i < ICE_MAX_VSI; i++)
162333e055fcSVictor Raj 		ice_clear_vsi_ctx(hw, i);
162433e055fcSVictor Raj }
162533e055fcSVictor Raj 
162633e055fcSVictor Raj /**
16270f9d5027SAnirudh Venkataramanan  * ice_add_vsi - add VSI context to the hardware and VSI handle list
1628f9867df6SAnirudh Venkataramanan  * @hw: pointer to the HW struct
16290f9d5027SAnirudh Venkataramanan  * @vsi_handle: unique VSI handle provided by drivers
16300f9d5027SAnirudh Venkataramanan  * @vsi_ctx: pointer to a VSI context struct
16310f9d5027SAnirudh Venkataramanan  * @cd: pointer to command details structure or NULL
16320f9d5027SAnirudh Venkataramanan  *
16330f9d5027SAnirudh Venkataramanan  * Add a VSI context to the hardware also add it into the VSI handle list.
16340f9d5027SAnirudh Venkataramanan  * If this function gets called after reset for existing VSIs then update
16350f9d5027SAnirudh Venkataramanan  * with the new HW VSI number in the corresponding VSI handle list entry.
16360f9d5027SAnirudh Venkataramanan  */
16375e24d598STony Nguyen int
16380f9d5027SAnirudh Venkataramanan ice_add_vsi(struct ice_hw *hw, u16 vsi_handle, struct ice_vsi_ctx *vsi_ctx,
16390f9d5027SAnirudh Venkataramanan 	    struct ice_sq_cd *cd)
16400f9d5027SAnirudh Venkataramanan {
16410f9d5027SAnirudh Venkataramanan 	struct ice_vsi_ctx *tmp_vsi_ctx;
16425e24d598STony Nguyen 	int status;
16430f9d5027SAnirudh Venkataramanan 
16440f9d5027SAnirudh Venkataramanan 	if (vsi_handle >= ICE_MAX_VSI)
1645d54699e2STony Nguyen 		return -EINVAL;
16460f9d5027SAnirudh Venkataramanan 	status = ice_aq_add_vsi(hw, vsi_ctx, cd);
16470f9d5027SAnirudh Venkataramanan 	if (status)
16480f9d5027SAnirudh Venkataramanan 		return status;
16490f9d5027SAnirudh Venkataramanan 	tmp_vsi_ctx = ice_get_vsi_ctx(hw, vsi_handle);
16500f9d5027SAnirudh Venkataramanan 	if (!tmp_vsi_ctx) {
1651f9867df6SAnirudh Venkataramanan 		/* Create a new VSI context */
16520f9d5027SAnirudh Venkataramanan 		tmp_vsi_ctx = devm_kzalloc(ice_hw_to_dev(hw),
16530f9d5027SAnirudh Venkataramanan 					   sizeof(*tmp_vsi_ctx), GFP_KERNEL);
16540f9d5027SAnirudh Venkataramanan 		if (!tmp_vsi_ctx) {
16550f9d5027SAnirudh Venkataramanan 			ice_aq_free_vsi(hw, vsi_ctx, false, cd);
1656d54699e2STony Nguyen 			return -ENOMEM;
16570f9d5027SAnirudh Venkataramanan 		}
16580f9d5027SAnirudh Venkataramanan 		*tmp_vsi_ctx = *vsi_ctx;
16590f9d5027SAnirudh Venkataramanan 		ice_save_vsi_ctx(hw, vsi_handle, tmp_vsi_ctx);
16600f9d5027SAnirudh Venkataramanan 	} else {
16610f9d5027SAnirudh Venkataramanan 		/* update with new HW VSI num */
16620f9d5027SAnirudh Venkataramanan 		tmp_vsi_ctx->vsi_num = vsi_ctx->vsi_num;
16630f9d5027SAnirudh Venkataramanan 	}
16640f9d5027SAnirudh Venkataramanan 
16651b5c19c7SBruce Allan 	return 0;
16660f9d5027SAnirudh Venkataramanan }
16670f9d5027SAnirudh Venkataramanan 
16680f9d5027SAnirudh Venkataramanan /**
16690f9d5027SAnirudh Venkataramanan  * ice_free_vsi- free VSI context from hardware and VSI handle list
1670f9867df6SAnirudh Venkataramanan  * @hw: pointer to the HW struct
16710f9d5027SAnirudh Venkataramanan  * @vsi_handle: unique VSI handle
16723a858ba3SAnirudh Venkataramanan  * @vsi_ctx: pointer to a VSI context struct
16733a858ba3SAnirudh Venkataramanan  * @keep_vsi_alloc: keep VSI allocation as part of this PF's resources
16743a858ba3SAnirudh Venkataramanan  * @cd: pointer to command details structure or NULL
16753a858ba3SAnirudh Venkataramanan  *
16760f9d5027SAnirudh Venkataramanan  * Free VSI context info from hardware as well as from VSI handle list
16773a858ba3SAnirudh Venkataramanan  */
16785e24d598STony Nguyen int
16790f9d5027SAnirudh Venkataramanan ice_free_vsi(struct ice_hw *hw, u16 vsi_handle, struct ice_vsi_ctx *vsi_ctx,
16803a858ba3SAnirudh Venkataramanan 	     bool keep_vsi_alloc, struct ice_sq_cd *cd)
16813a858ba3SAnirudh Venkataramanan {
16825e24d598STony Nguyen 	int status;
16833a858ba3SAnirudh Venkataramanan 
16840f9d5027SAnirudh Venkataramanan 	if (!ice_is_vsi_valid(hw, vsi_handle))
1685d54699e2STony Nguyen 		return -EINVAL;
16860f9d5027SAnirudh Venkataramanan 	vsi_ctx->vsi_num = ice_get_hw_vsi_num(hw, vsi_handle);
16870f9d5027SAnirudh Venkataramanan 	status = ice_aq_free_vsi(hw, vsi_ctx, keep_vsi_alloc, cd);
16880f9d5027SAnirudh Venkataramanan 	if (!status)
16890f9d5027SAnirudh Venkataramanan 		ice_clear_vsi_ctx(hw, vsi_handle);
16903a858ba3SAnirudh Venkataramanan 	return status;
16913a858ba3SAnirudh Venkataramanan }
16923a858ba3SAnirudh Venkataramanan 
16939daf8208SAnirudh Venkataramanan /**
16945726ca0eSAnirudh Venkataramanan  * ice_update_vsi
1695f9867df6SAnirudh Venkataramanan  * @hw: pointer to the HW struct
16965726ca0eSAnirudh Venkataramanan  * @vsi_handle: unique VSI handle
16975726ca0eSAnirudh Venkataramanan  * @vsi_ctx: pointer to a VSI context struct
16985726ca0eSAnirudh Venkataramanan  * @cd: pointer to command details structure or NULL
16995726ca0eSAnirudh Venkataramanan  *
17005726ca0eSAnirudh Venkataramanan  * Update VSI context in the hardware
17015726ca0eSAnirudh Venkataramanan  */
17025e24d598STony Nguyen int
17035726ca0eSAnirudh Venkataramanan ice_update_vsi(struct ice_hw *hw, u16 vsi_handle, struct ice_vsi_ctx *vsi_ctx,
17045726ca0eSAnirudh Venkataramanan 	       struct ice_sq_cd *cd)
17055726ca0eSAnirudh Venkataramanan {
17065726ca0eSAnirudh Venkataramanan 	if (!ice_is_vsi_valid(hw, vsi_handle))
1707d54699e2STony Nguyen 		return -EINVAL;
17085726ca0eSAnirudh Venkataramanan 	vsi_ctx->vsi_num = ice_get_hw_vsi_num(hw, vsi_handle);
17095726ca0eSAnirudh Venkataramanan 	return ice_aq_update_vsi(hw, vsi_ctx, cd);
17105726ca0eSAnirudh Venkataramanan }
17115726ca0eSAnirudh Venkataramanan 
17125726ca0eSAnirudh Venkataramanan /**
1713348048e7SDave Ertman  * ice_cfg_rdma_fltr - enable/disable RDMA filtering on VSI
1714348048e7SDave Ertman  * @hw: pointer to HW struct
1715348048e7SDave Ertman  * @vsi_handle: VSI SW index
1716348048e7SDave Ertman  * @enable: boolean for enable/disable
1717348048e7SDave Ertman  */
1718348048e7SDave Ertman int
1719348048e7SDave Ertman ice_cfg_rdma_fltr(struct ice_hw *hw, u16 vsi_handle, bool enable)
1720348048e7SDave Ertman {
1721348048e7SDave Ertman 	struct ice_vsi_ctx *ctx;
1722348048e7SDave Ertman 
1723348048e7SDave Ertman 	ctx = ice_get_vsi_ctx(hw, vsi_handle);
1724348048e7SDave Ertman 	if (!ctx)
1725348048e7SDave Ertman 		return -EIO;
1726348048e7SDave Ertman 
1727348048e7SDave Ertman 	if (enable)
1728348048e7SDave Ertman 		ctx->info.q_opt_flags |= ICE_AQ_VSI_Q_OPT_PE_FLTR_EN;
1729348048e7SDave Ertman 	else
1730348048e7SDave Ertman 		ctx->info.q_opt_flags &= ~ICE_AQ_VSI_Q_OPT_PE_FLTR_EN;
1731348048e7SDave Ertman 
1732d54699e2STony Nguyen 	return ice_update_vsi(hw, vsi_handle, ctx, NULL);
1733348048e7SDave Ertman }
1734348048e7SDave Ertman 
1735348048e7SDave Ertman /**
17369daf8208SAnirudh Venkataramanan  * ice_aq_alloc_free_vsi_list
1737f9867df6SAnirudh Venkataramanan  * @hw: pointer to the HW struct
1738f9867df6SAnirudh Venkataramanan  * @vsi_list_id: VSI list ID returned or used for lookup
17399daf8208SAnirudh Venkataramanan  * @lkup_type: switch rule filter lookup type
17409daf8208SAnirudh Venkataramanan  * @opc: switch rules population command type - pass in the command opcode
17419daf8208SAnirudh Venkataramanan  *
17429daf8208SAnirudh Venkataramanan  * allocates or free a VSI list resource
17439daf8208SAnirudh Venkataramanan  */
17445e24d598STony Nguyen static int
17459daf8208SAnirudh Venkataramanan ice_aq_alloc_free_vsi_list(struct ice_hw *hw, u16 *vsi_list_id,
17469daf8208SAnirudh Venkataramanan 			   enum ice_sw_lkup_type lkup_type,
17479daf8208SAnirudh Venkataramanan 			   enum ice_adminq_opc opc)
17489daf8208SAnirudh Venkataramanan {
17499daf8208SAnirudh Venkataramanan 	struct ice_aqc_alloc_free_res_elem *sw_buf;
17509daf8208SAnirudh Venkataramanan 	struct ice_aqc_res_elem *vsi_ele;
17519daf8208SAnirudh Venkataramanan 	u16 buf_len;
17525518ac2aSTony Nguyen 	int status;
17539daf8208SAnirudh Venkataramanan 
175466486d89SBruce Allan 	buf_len = struct_size(sw_buf, elem, 1);
17559daf8208SAnirudh Venkataramanan 	sw_buf = devm_kzalloc(ice_hw_to_dev(hw), buf_len, GFP_KERNEL);
17569daf8208SAnirudh Venkataramanan 	if (!sw_buf)
1757d54699e2STony Nguyen 		return -ENOMEM;
17589daf8208SAnirudh Venkataramanan 	sw_buf->num_elems = cpu_to_le16(1);
17599daf8208SAnirudh Venkataramanan 
17609daf8208SAnirudh Venkataramanan 	if (lkup_type == ICE_SW_LKUP_MAC ||
17619daf8208SAnirudh Venkataramanan 	    lkup_type == ICE_SW_LKUP_MAC_VLAN ||
17629daf8208SAnirudh Venkataramanan 	    lkup_type == ICE_SW_LKUP_ETHERTYPE ||
17639daf8208SAnirudh Venkataramanan 	    lkup_type == ICE_SW_LKUP_ETHERTYPE_MAC ||
17649daf8208SAnirudh Venkataramanan 	    lkup_type == ICE_SW_LKUP_PROMISC ||
1765d7393425SMichal Wilczynski 	    lkup_type == ICE_SW_LKUP_PROMISC_VLAN ||
1766d7393425SMichal Wilczynski 	    lkup_type == ICE_SW_LKUP_DFLT) {
17679daf8208SAnirudh Venkataramanan 		sw_buf->res_type = cpu_to_le16(ICE_AQC_RES_TYPE_VSI_LIST_REP);
17689daf8208SAnirudh Venkataramanan 	} else if (lkup_type == ICE_SW_LKUP_VLAN) {
17699daf8208SAnirudh Venkataramanan 		sw_buf->res_type =
17709daf8208SAnirudh Venkataramanan 			cpu_to_le16(ICE_AQC_RES_TYPE_VSI_LIST_PRUNE);
17719daf8208SAnirudh Venkataramanan 	} else {
1772d54699e2STony Nguyen 		status = -EINVAL;
17739daf8208SAnirudh Venkataramanan 		goto ice_aq_alloc_free_vsi_list_exit;
17749daf8208SAnirudh Venkataramanan 	}
17759daf8208SAnirudh Venkataramanan 
17769daf8208SAnirudh Venkataramanan 	if (opc == ice_aqc_opc_free_res)
17779daf8208SAnirudh Venkataramanan 		sw_buf->elem[0].e.sw_resp = cpu_to_le16(*vsi_list_id);
17789daf8208SAnirudh Venkataramanan 
17799daf8208SAnirudh Venkataramanan 	status = ice_aq_alloc_free_res(hw, 1, sw_buf, buf_len, opc, NULL);
17809daf8208SAnirudh Venkataramanan 	if (status)
17819daf8208SAnirudh Venkataramanan 		goto ice_aq_alloc_free_vsi_list_exit;
17829daf8208SAnirudh Venkataramanan 
17839daf8208SAnirudh Venkataramanan 	if (opc == ice_aqc_opc_alloc_res) {
17849daf8208SAnirudh Venkataramanan 		vsi_ele = &sw_buf->elem[0];
17859daf8208SAnirudh Venkataramanan 		*vsi_list_id = le16_to_cpu(vsi_ele->e.sw_resp);
17869daf8208SAnirudh Venkataramanan 	}
17879daf8208SAnirudh Venkataramanan 
17889daf8208SAnirudh Venkataramanan ice_aq_alloc_free_vsi_list_exit:
17899daf8208SAnirudh Venkataramanan 	devm_kfree(ice_hw_to_dev(hw), sw_buf);
17909daf8208SAnirudh Venkataramanan 	return status;
17919daf8208SAnirudh Venkataramanan }
17929daf8208SAnirudh Venkataramanan 
17939daf8208SAnirudh Venkataramanan /**
17949daf8208SAnirudh Venkataramanan  * ice_aq_sw_rules - add/update/remove switch rules
1795f9867df6SAnirudh Venkataramanan  * @hw: pointer to the HW struct
17969daf8208SAnirudh Venkataramanan  * @rule_list: pointer to switch rule population list
17979daf8208SAnirudh Venkataramanan  * @rule_list_sz: total size of the rule list in bytes
17989daf8208SAnirudh Venkataramanan  * @num_rules: number of switch rules in the rule_list
17999daf8208SAnirudh Venkataramanan  * @opc: switch rules population command type - pass in the command opcode
18009daf8208SAnirudh Venkataramanan  * @cd: pointer to command details structure or NULL
18019daf8208SAnirudh Venkataramanan  *
18029daf8208SAnirudh Venkataramanan  * Add(0x02a0)/Update(0x02a1)/Remove(0x02a2) switch rules commands to firmware
18039daf8208SAnirudh Venkataramanan  */
18045e24d598STony Nguyen int
18059daf8208SAnirudh Venkataramanan ice_aq_sw_rules(struct ice_hw *hw, void *rule_list, u16 rule_list_sz,
18069daf8208SAnirudh Venkataramanan 		u8 num_rules, enum ice_adminq_opc opc, struct ice_sq_cd *cd)
18079daf8208SAnirudh Venkataramanan {
18089daf8208SAnirudh Venkataramanan 	struct ice_aq_desc desc;
18095e24d598STony Nguyen 	int status;
18109daf8208SAnirudh Venkataramanan 
18119daf8208SAnirudh Venkataramanan 	if (opc != ice_aqc_opc_add_sw_rules &&
18129daf8208SAnirudh Venkataramanan 	    opc != ice_aqc_opc_update_sw_rules &&
18139daf8208SAnirudh Venkataramanan 	    opc != ice_aqc_opc_remove_sw_rules)
1814d54699e2STony Nguyen 		return -EINVAL;
18159daf8208SAnirudh Venkataramanan 
18169daf8208SAnirudh Venkataramanan 	ice_fill_dflt_direct_cmd_desc(&desc, opc);
18179daf8208SAnirudh Venkataramanan 
18189daf8208SAnirudh Venkataramanan 	desc.flags |= cpu_to_le16(ICE_AQ_FLAG_RD);
18199daf8208SAnirudh Venkataramanan 	desc.params.sw_rules.num_rules_fltr_entry_index =
18209daf8208SAnirudh Venkataramanan 		cpu_to_le16(num_rules);
1821ca1fdb88SKiran Patil 	status = ice_aq_send_cmd(hw, &desc, rule_list, rule_list_sz, cd);
1822ca1fdb88SKiran Patil 	if (opc != ice_aqc_opc_add_sw_rules &&
1823ca1fdb88SKiran Patil 	    hw->adminq.sq_last_status == ICE_AQ_RC_ENOENT)
1824d54699e2STony Nguyen 		status = -ENOENT;
1825ca1fdb88SKiran Patil 
1826ca1fdb88SKiran Patil 	return status;
18279daf8208SAnirudh Venkataramanan }
18289daf8208SAnirudh Venkataramanan 
18297715ec32SGrishma Kotecha /**
18307715ec32SGrishma Kotecha  * ice_aq_add_recipe - add switch recipe
18317715ec32SGrishma Kotecha  * @hw: pointer to the HW struct
18327715ec32SGrishma Kotecha  * @s_recipe_list: pointer to switch rule population list
18337715ec32SGrishma Kotecha  * @num_recipes: number of switch recipes in the list
18347715ec32SGrishma Kotecha  * @cd: pointer to command details structure or NULL
18357715ec32SGrishma Kotecha  *
18367715ec32SGrishma Kotecha  * Add(0x0290)
18377715ec32SGrishma Kotecha  */
18385e24d598STony Nguyen static int
18397715ec32SGrishma Kotecha ice_aq_add_recipe(struct ice_hw *hw,
18407715ec32SGrishma Kotecha 		  struct ice_aqc_recipe_data_elem *s_recipe_list,
18417715ec32SGrishma Kotecha 		  u16 num_recipes, struct ice_sq_cd *cd)
18427715ec32SGrishma Kotecha {
18437715ec32SGrishma Kotecha 	struct ice_aqc_add_get_recipe *cmd;
18447715ec32SGrishma Kotecha 	struct ice_aq_desc desc;
18457715ec32SGrishma Kotecha 	u16 buf_size;
18467715ec32SGrishma Kotecha 
18477715ec32SGrishma Kotecha 	cmd = &desc.params.add_get_recipe;
18487715ec32SGrishma Kotecha 	ice_fill_dflt_direct_cmd_desc(&desc, ice_aqc_opc_add_recipe);
18497715ec32SGrishma Kotecha 
18507715ec32SGrishma Kotecha 	cmd->num_sub_recipes = cpu_to_le16(num_recipes);
18517715ec32SGrishma Kotecha 	desc.flags |= cpu_to_le16(ICE_AQ_FLAG_RD);
18527715ec32SGrishma Kotecha 
18537715ec32SGrishma Kotecha 	buf_size = num_recipes * sizeof(*s_recipe_list);
18547715ec32SGrishma Kotecha 
18557715ec32SGrishma Kotecha 	return ice_aq_send_cmd(hw, &desc, s_recipe_list, buf_size, cd);
18567715ec32SGrishma Kotecha }
18577715ec32SGrishma Kotecha 
18587715ec32SGrishma Kotecha /**
18597715ec32SGrishma Kotecha  * ice_aq_get_recipe - get switch recipe
18607715ec32SGrishma Kotecha  * @hw: pointer to the HW struct
18617715ec32SGrishma Kotecha  * @s_recipe_list: pointer to switch rule population list
18627715ec32SGrishma Kotecha  * @num_recipes: pointer to the number of recipes (input and output)
18637715ec32SGrishma Kotecha  * @recipe_root: root recipe number of recipe(s) to retrieve
18647715ec32SGrishma Kotecha  * @cd: pointer to command details structure or NULL
18657715ec32SGrishma Kotecha  *
18667715ec32SGrishma Kotecha  * Get(0x0292)
18677715ec32SGrishma Kotecha  *
18687715ec32SGrishma Kotecha  * On input, *num_recipes should equal the number of entries in s_recipe_list.
18697715ec32SGrishma Kotecha  * On output, *num_recipes will equal the number of entries returned in
18707715ec32SGrishma Kotecha  * s_recipe_list.
18717715ec32SGrishma Kotecha  *
18727715ec32SGrishma Kotecha  * The caller must supply enough space in s_recipe_list to hold all possible
18737715ec32SGrishma Kotecha  * recipes and *num_recipes must equal ICE_MAX_NUM_RECIPES.
18747715ec32SGrishma Kotecha  */
18755e24d598STony Nguyen static int
18767715ec32SGrishma Kotecha ice_aq_get_recipe(struct ice_hw *hw,
18777715ec32SGrishma Kotecha 		  struct ice_aqc_recipe_data_elem *s_recipe_list,
18787715ec32SGrishma Kotecha 		  u16 *num_recipes, u16 recipe_root, struct ice_sq_cd *cd)
18797715ec32SGrishma Kotecha {
18807715ec32SGrishma Kotecha 	struct ice_aqc_add_get_recipe *cmd;
18817715ec32SGrishma Kotecha 	struct ice_aq_desc desc;
18827715ec32SGrishma Kotecha 	u16 buf_size;
18835518ac2aSTony Nguyen 	int status;
18847715ec32SGrishma Kotecha 
18857715ec32SGrishma Kotecha 	if (*num_recipes != ICE_MAX_NUM_RECIPES)
1886d54699e2STony Nguyen 		return -EINVAL;
18877715ec32SGrishma Kotecha 
18887715ec32SGrishma Kotecha 	cmd = &desc.params.add_get_recipe;
18897715ec32SGrishma Kotecha 	ice_fill_dflt_direct_cmd_desc(&desc, ice_aqc_opc_get_recipe);
18907715ec32SGrishma Kotecha 
18917715ec32SGrishma Kotecha 	cmd->return_index = cpu_to_le16(recipe_root);
18927715ec32SGrishma Kotecha 	cmd->num_sub_recipes = 0;
18937715ec32SGrishma Kotecha 
18947715ec32SGrishma Kotecha 	buf_size = *num_recipes * sizeof(*s_recipe_list);
18957715ec32SGrishma Kotecha 
18967715ec32SGrishma Kotecha 	status = ice_aq_send_cmd(hw, &desc, s_recipe_list, buf_size, cd);
18977715ec32SGrishma Kotecha 	*num_recipes = le16_to_cpu(cmd->num_sub_recipes);
18987715ec32SGrishma Kotecha 
18997715ec32SGrishma Kotecha 	return status;
19007715ec32SGrishma Kotecha }
19017715ec32SGrishma Kotecha 
19027715ec32SGrishma Kotecha /**
1903a1ffafb0SBrett Creeley  * ice_update_recipe_lkup_idx - update a default recipe based on the lkup_idx
1904a1ffafb0SBrett Creeley  * @hw: pointer to the HW struct
1905a1ffafb0SBrett Creeley  * @params: parameters used to update the default recipe
1906a1ffafb0SBrett Creeley  *
1907a1ffafb0SBrett Creeley  * This function only supports updating default recipes and it only supports
1908a1ffafb0SBrett Creeley  * updating a single recipe based on the lkup_idx at a time.
1909a1ffafb0SBrett Creeley  *
1910a1ffafb0SBrett Creeley  * This is done as a read-modify-write operation. First, get the current recipe
1911a1ffafb0SBrett Creeley  * contents based on the recipe's ID. Then modify the field vector index and
1912a1ffafb0SBrett Creeley  * mask if it's valid at the lkup_idx. Finally, use the add recipe AQ to update
1913a1ffafb0SBrett Creeley  * the pre-existing recipe with the modifications.
1914a1ffafb0SBrett Creeley  */
1915a1ffafb0SBrett Creeley int
1916a1ffafb0SBrett Creeley ice_update_recipe_lkup_idx(struct ice_hw *hw,
1917a1ffafb0SBrett Creeley 			   struct ice_update_recipe_lkup_idx_params *params)
1918a1ffafb0SBrett Creeley {
1919a1ffafb0SBrett Creeley 	struct ice_aqc_recipe_data_elem *rcp_list;
1920a1ffafb0SBrett Creeley 	u16 num_recps = ICE_MAX_NUM_RECIPES;
1921a1ffafb0SBrett Creeley 	int status;
1922a1ffafb0SBrett Creeley 
1923a1ffafb0SBrett Creeley 	rcp_list = kcalloc(num_recps, sizeof(*rcp_list), GFP_KERNEL);
1924a1ffafb0SBrett Creeley 	if (!rcp_list)
1925a1ffafb0SBrett Creeley 		return -ENOMEM;
1926a1ffafb0SBrett Creeley 
1927a1ffafb0SBrett Creeley 	/* read current recipe list from firmware */
1928a1ffafb0SBrett Creeley 	rcp_list->recipe_indx = params->rid;
1929a1ffafb0SBrett Creeley 	status = ice_aq_get_recipe(hw, rcp_list, &num_recps, params->rid, NULL);
1930a1ffafb0SBrett Creeley 	if (status) {
1931a1ffafb0SBrett Creeley 		ice_debug(hw, ICE_DBG_SW, "Failed to get recipe %d, status %d\n",
1932a1ffafb0SBrett Creeley 			  params->rid, status);
1933a1ffafb0SBrett Creeley 		goto error_out;
1934a1ffafb0SBrett Creeley 	}
1935a1ffafb0SBrett Creeley 
1936a1ffafb0SBrett Creeley 	/* only modify existing recipe's lkup_idx and mask if valid, while
1937a1ffafb0SBrett Creeley 	 * leaving all other fields the same, then update the recipe firmware
1938a1ffafb0SBrett Creeley 	 */
1939a1ffafb0SBrett Creeley 	rcp_list->content.lkup_indx[params->lkup_idx] = params->fv_idx;
1940a1ffafb0SBrett Creeley 	if (params->mask_valid)
1941a1ffafb0SBrett Creeley 		rcp_list->content.mask[params->lkup_idx] =
1942a1ffafb0SBrett Creeley 			cpu_to_le16(params->mask);
1943a1ffafb0SBrett Creeley 
1944a1ffafb0SBrett Creeley 	if (params->ignore_valid)
1945a1ffafb0SBrett Creeley 		rcp_list->content.lkup_indx[params->lkup_idx] |=
1946a1ffafb0SBrett Creeley 			ICE_AQ_RECIPE_LKUP_IGNORE;
1947a1ffafb0SBrett Creeley 
1948a1ffafb0SBrett Creeley 	status = ice_aq_add_recipe(hw, &rcp_list[0], 1, NULL);
1949a1ffafb0SBrett Creeley 	if (status)
1950a1ffafb0SBrett Creeley 		ice_debug(hw, ICE_DBG_SW, "Failed to update recipe %d lkup_idx %d fv_idx %d mask %d mask_valid %s, status %d\n",
1951a1ffafb0SBrett Creeley 			  params->rid, params->lkup_idx, params->fv_idx,
1952a1ffafb0SBrett Creeley 			  params->mask, params->mask_valid ? "true" : "false",
1953a1ffafb0SBrett Creeley 			  status);
1954a1ffafb0SBrett Creeley 
1955a1ffafb0SBrett Creeley error_out:
1956a1ffafb0SBrett Creeley 	kfree(rcp_list);
1957a1ffafb0SBrett Creeley 	return status;
1958a1ffafb0SBrett Creeley }
1959a1ffafb0SBrett Creeley 
1960a1ffafb0SBrett Creeley /**
19617715ec32SGrishma Kotecha  * ice_aq_map_recipe_to_profile - Map recipe to packet profile
19627715ec32SGrishma Kotecha  * @hw: pointer to the HW struct
19637715ec32SGrishma Kotecha  * @profile_id: package profile ID to associate the recipe with
19647715ec32SGrishma Kotecha  * @r_bitmap: Recipe bitmap filled in and need to be returned as response
19657715ec32SGrishma Kotecha  * @cd: pointer to command details structure or NULL
19667715ec32SGrishma Kotecha  * Recipe to profile association (0x0291)
19677715ec32SGrishma Kotecha  */
19685e24d598STony Nguyen static int
19697715ec32SGrishma Kotecha ice_aq_map_recipe_to_profile(struct ice_hw *hw, u32 profile_id, u8 *r_bitmap,
19707715ec32SGrishma Kotecha 			     struct ice_sq_cd *cd)
19717715ec32SGrishma Kotecha {
19727715ec32SGrishma Kotecha 	struct ice_aqc_recipe_to_profile *cmd;
19737715ec32SGrishma Kotecha 	struct ice_aq_desc desc;
19747715ec32SGrishma Kotecha 
19757715ec32SGrishma Kotecha 	cmd = &desc.params.recipe_to_profile;
19767715ec32SGrishma Kotecha 	ice_fill_dflt_direct_cmd_desc(&desc, ice_aqc_opc_recipe_to_profile);
19777715ec32SGrishma Kotecha 	cmd->profile_id = cpu_to_le16(profile_id);
19787715ec32SGrishma Kotecha 	/* Set the recipe ID bit in the bitmask to let the device know which
19797715ec32SGrishma Kotecha 	 * profile we are associating the recipe to
19807715ec32SGrishma Kotecha 	 */
19817715ec32SGrishma Kotecha 	memcpy(cmd->recipe_assoc, r_bitmap, sizeof(cmd->recipe_assoc));
19827715ec32SGrishma Kotecha 
19837715ec32SGrishma Kotecha 	return ice_aq_send_cmd(hw, &desc, NULL, 0, cd);
19847715ec32SGrishma Kotecha }
19857715ec32SGrishma Kotecha 
19867715ec32SGrishma Kotecha /**
19877715ec32SGrishma Kotecha  * ice_aq_get_recipe_to_profile - Map recipe to packet profile
19887715ec32SGrishma Kotecha  * @hw: pointer to the HW struct
19897715ec32SGrishma Kotecha  * @profile_id: package profile ID to associate the recipe with
19907715ec32SGrishma Kotecha  * @r_bitmap: Recipe bitmap filled in and need to be returned as response
19917715ec32SGrishma Kotecha  * @cd: pointer to command details structure or NULL
19927715ec32SGrishma Kotecha  * Associate profile ID with given recipe (0x0293)
19937715ec32SGrishma Kotecha  */
19945e24d598STony Nguyen static int
19957715ec32SGrishma Kotecha ice_aq_get_recipe_to_profile(struct ice_hw *hw, u32 profile_id, u8 *r_bitmap,
19967715ec32SGrishma Kotecha 			     struct ice_sq_cd *cd)
19977715ec32SGrishma Kotecha {
19987715ec32SGrishma Kotecha 	struct ice_aqc_recipe_to_profile *cmd;
19997715ec32SGrishma Kotecha 	struct ice_aq_desc desc;
20005e24d598STony Nguyen 	int status;
20017715ec32SGrishma Kotecha 
20027715ec32SGrishma Kotecha 	cmd = &desc.params.recipe_to_profile;
20037715ec32SGrishma Kotecha 	ice_fill_dflt_direct_cmd_desc(&desc, ice_aqc_opc_get_recipe_to_profile);
20047715ec32SGrishma Kotecha 	cmd->profile_id = cpu_to_le16(profile_id);
20057715ec32SGrishma Kotecha 
20067715ec32SGrishma Kotecha 	status = ice_aq_send_cmd(hw, &desc, NULL, 0, cd);
20077715ec32SGrishma Kotecha 	if (!status)
20087715ec32SGrishma Kotecha 		memcpy(r_bitmap, cmd->recipe_assoc, sizeof(cmd->recipe_assoc));
20097715ec32SGrishma Kotecha 
20107715ec32SGrishma Kotecha 	return status;
20117715ec32SGrishma Kotecha }
20127715ec32SGrishma Kotecha 
20137715ec32SGrishma Kotecha /**
20147715ec32SGrishma Kotecha  * ice_alloc_recipe - add recipe resource
20157715ec32SGrishma Kotecha  * @hw: pointer to the hardware structure
20167715ec32SGrishma Kotecha  * @rid: recipe ID returned as response to AQ call
20177715ec32SGrishma Kotecha  */
20185e24d598STony Nguyen static int ice_alloc_recipe(struct ice_hw *hw, u16 *rid)
20197715ec32SGrishma Kotecha {
20207715ec32SGrishma Kotecha 	struct ice_aqc_alloc_free_res_elem *sw_buf;
20217715ec32SGrishma Kotecha 	u16 buf_len;
20225518ac2aSTony Nguyen 	int status;
20237715ec32SGrishma Kotecha 
20247715ec32SGrishma Kotecha 	buf_len = struct_size(sw_buf, elem, 1);
20257715ec32SGrishma Kotecha 	sw_buf = kzalloc(buf_len, GFP_KERNEL);
20267715ec32SGrishma Kotecha 	if (!sw_buf)
2027d54699e2STony Nguyen 		return -ENOMEM;
20287715ec32SGrishma Kotecha 
20297715ec32SGrishma Kotecha 	sw_buf->num_elems = cpu_to_le16(1);
20307715ec32SGrishma Kotecha 	sw_buf->res_type = cpu_to_le16((ICE_AQC_RES_TYPE_RECIPE <<
20317715ec32SGrishma Kotecha 					ICE_AQC_RES_TYPE_S) |
20327715ec32SGrishma Kotecha 					ICE_AQC_RES_TYPE_FLAG_SHARED);
20337715ec32SGrishma Kotecha 	status = ice_aq_alloc_free_res(hw, 1, sw_buf, buf_len,
20347715ec32SGrishma Kotecha 				       ice_aqc_opc_alloc_res, NULL);
20357715ec32SGrishma Kotecha 	if (!status)
20367715ec32SGrishma Kotecha 		*rid = le16_to_cpu(sw_buf->elem[0].e.sw_resp);
20377715ec32SGrishma Kotecha 	kfree(sw_buf);
20387715ec32SGrishma Kotecha 
20397715ec32SGrishma Kotecha 	return status;
20407715ec32SGrishma Kotecha }
20417715ec32SGrishma Kotecha 
2042fd2a6b71SDan Nowlin /**
2043fd2a6b71SDan Nowlin  * ice_get_recp_to_prof_map - updates recipe to profile mapping
2044fd2a6b71SDan Nowlin  * @hw: pointer to hardware structure
2045fd2a6b71SDan Nowlin  *
2046fd2a6b71SDan Nowlin  * This function is used to populate recipe_to_profile matrix where index to
2047fd2a6b71SDan Nowlin  * this array is the recipe ID and the element is the mapping of which profiles
2048fd2a6b71SDan Nowlin  * is this recipe mapped to.
2049fd2a6b71SDan Nowlin  */
2050fd2a6b71SDan Nowlin static void ice_get_recp_to_prof_map(struct ice_hw *hw)
2051fd2a6b71SDan Nowlin {
2052fd2a6b71SDan Nowlin 	DECLARE_BITMAP(r_bitmap, ICE_MAX_NUM_RECIPES);
2053fd2a6b71SDan Nowlin 	u16 i;
2054fd2a6b71SDan Nowlin 
2055fd2a6b71SDan Nowlin 	for (i = 0; i < hw->switch_info->max_used_prof_index + 1; i++) {
2056fd2a6b71SDan Nowlin 		u16 j;
2057fd2a6b71SDan Nowlin 
2058fd2a6b71SDan Nowlin 		bitmap_zero(profile_to_recipe[i], ICE_MAX_NUM_RECIPES);
2059fd2a6b71SDan Nowlin 		bitmap_zero(r_bitmap, ICE_MAX_NUM_RECIPES);
2060fd2a6b71SDan Nowlin 		if (ice_aq_get_recipe_to_profile(hw, i, (u8 *)r_bitmap, NULL))
2061fd2a6b71SDan Nowlin 			continue;
2062fd2a6b71SDan Nowlin 		bitmap_copy(profile_to_recipe[i], r_bitmap,
2063fd2a6b71SDan Nowlin 			    ICE_MAX_NUM_RECIPES);
2064fd2a6b71SDan Nowlin 		for_each_set_bit(j, r_bitmap, ICE_MAX_NUM_RECIPES)
2065fd2a6b71SDan Nowlin 			set_bit(i, recipe_to_profile[j]);
2066fd2a6b71SDan Nowlin 	}
2067fd2a6b71SDan Nowlin }
2068fd2a6b71SDan Nowlin 
2069fd2a6b71SDan Nowlin /**
2070fd2a6b71SDan Nowlin  * ice_collect_result_idx - copy result index values
2071fd2a6b71SDan Nowlin  * @buf: buffer that contains the result index
2072fd2a6b71SDan Nowlin  * @recp: the recipe struct to copy data into
2073fd2a6b71SDan Nowlin  */
2074fd2a6b71SDan Nowlin static void
2075fd2a6b71SDan Nowlin ice_collect_result_idx(struct ice_aqc_recipe_data_elem *buf,
2076fd2a6b71SDan Nowlin 		       struct ice_sw_recipe *recp)
2077fd2a6b71SDan Nowlin {
2078fd2a6b71SDan Nowlin 	if (buf->content.result_indx & ICE_AQ_RECIPE_RESULT_EN)
2079fd2a6b71SDan Nowlin 		set_bit(buf->content.result_indx & ~ICE_AQ_RECIPE_RESULT_EN,
2080fd2a6b71SDan Nowlin 			recp->res_idxs);
2081fd2a6b71SDan Nowlin }
2082fd2a6b71SDan Nowlin 
2083fd2a6b71SDan Nowlin /**
2084fd2a6b71SDan Nowlin  * ice_get_recp_frm_fw - update SW bookkeeping from FW recipe entries
2085fd2a6b71SDan Nowlin  * @hw: pointer to hardware structure
2086fd2a6b71SDan Nowlin  * @recps: struct that we need to populate
2087fd2a6b71SDan Nowlin  * @rid: recipe ID that we are populating
2088fd2a6b71SDan Nowlin  * @refresh_required: true if we should get recipe to profile mapping from FW
2089fd2a6b71SDan Nowlin  *
2090fd2a6b71SDan Nowlin  * This function is used to populate all the necessary entries into our
2091fd2a6b71SDan Nowlin  * bookkeeping so that we have a current list of all the recipes that are
2092fd2a6b71SDan Nowlin  * programmed in the firmware.
2093fd2a6b71SDan Nowlin  */
20945e24d598STony Nguyen static int
2095fd2a6b71SDan Nowlin ice_get_recp_frm_fw(struct ice_hw *hw, struct ice_sw_recipe *recps, u8 rid,
2096fd2a6b71SDan Nowlin 		    bool *refresh_required)
2097fd2a6b71SDan Nowlin {
2098fd2a6b71SDan Nowlin 	DECLARE_BITMAP(result_bm, ICE_MAX_FV_WORDS);
2099fd2a6b71SDan Nowlin 	struct ice_aqc_recipe_data_elem *tmp;
2100fd2a6b71SDan Nowlin 	u16 num_recps = ICE_MAX_NUM_RECIPES;
2101fd2a6b71SDan Nowlin 	struct ice_prot_lkup_ext *lkup_exts;
2102fd2a6b71SDan Nowlin 	u8 fv_word_idx = 0;
2103fd2a6b71SDan Nowlin 	u16 sub_recps;
21045518ac2aSTony Nguyen 	int status;
2105fd2a6b71SDan Nowlin 
2106fd2a6b71SDan Nowlin 	bitmap_zero(result_bm, ICE_MAX_FV_WORDS);
2107fd2a6b71SDan Nowlin 
2108fd2a6b71SDan Nowlin 	/* we need a buffer big enough to accommodate all the recipes */
2109fd2a6b71SDan Nowlin 	tmp = kcalloc(ICE_MAX_NUM_RECIPES, sizeof(*tmp), GFP_KERNEL);
2110fd2a6b71SDan Nowlin 	if (!tmp)
2111d54699e2STony Nguyen 		return -ENOMEM;
2112fd2a6b71SDan Nowlin 
2113fd2a6b71SDan Nowlin 	tmp[0].recipe_indx = rid;
2114fd2a6b71SDan Nowlin 	status = ice_aq_get_recipe(hw, tmp, &num_recps, rid, NULL);
2115fd2a6b71SDan Nowlin 	/* non-zero status meaning recipe doesn't exist */
2116fd2a6b71SDan Nowlin 	if (status)
2117fd2a6b71SDan Nowlin 		goto err_unroll;
2118fd2a6b71SDan Nowlin 
2119fd2a6b71SDan Nowlin 	/* Get recipe to profile map so that we can get the fv from lkups that
2120fd2a6b71SDan Nowlin 	 * we read for a recipe from FW. Since we want to minimize the number of
2121fd2a6b71SDan Nowlin 	 * times we make this FW call, just make one call and cache the copy
2122fd2a6b71SDan Nowlin 	 * until a new recipe is added. This operation is only required the
2123fd2a6b71SDan Nowlin 	 * first time to get the changes from FW. Then to search existing
2124fd2a6b71SDan Nowlin 	 * entries we don't need to update the cache again until another recipe
2125fd2a6b71SDan Nowlin 	 * gets added.
2126fd2a6b71SDan Nowlin 	 */
2127fd2a6b71SDan Nowlin 	if (*refresh_required) {
2128fd2a6b71SDan Nowlin 		ice_get_recp_to_prof_map(hw);
2129fd2a6b71SDan Nowlin 		*refresh_required = false;
2130fd2a6b71SDan Nowlin 	}
2131fd2a6b71SDan Nowlin 
2132fd2a6b71SDan Nowlin 	/* Start populating all the entries for recps[rid] based on lkups from
2133fd2a6b71SDan Nowlin 	 * firmware. Note that we are only creating the root recipe in our
2134fd2a6b71SDan Nowlin 	 * database.
2135fd2a6b71SDan Nowlin 	 */
2136fd2a6b71SDan Nowlin 	lkup_exts = &recps[rid].lkup_exts;
2137fd2a6b71SDan Nowlin 
2138fd2a6b71SDan Nowlin 	for (sub_recps = 0; sub_recps < num_recps; sub_recps++) {
2139fd2a6b71SDan Nowlin 		struct ice_aqc_recipe_data_elem root_bufs = tmp[sub_recps];
2140fd2a6b71SDan Nowlin 		struct ice_recp_grp_entry *rg_entry;
2141fd2a6b71SDan Nowlin 		u8 i, prof, idx, prot = 0;
2142fd2a6b71SDan Nowlin 		bool is_root;
2143fd2a6b71SDan Nowlin 		u16 off = 0;
2144fd2a6b71SDan Nowlin 
2145fd2a6b71SDan Nowlin 		rg_entry = devm_kzalloc(ice_hw_to_dev(hw), sizeof(*rg_entry),
2146fd2a6b71SDan Nowlin 					GFP_KERNEL);
2147fd2a6b71SDan Nowlin 		if (!rg_entry) {
2148d54699e2STony Nguyen 			status = -ENOMEM;
2149fd2a6b71SDan Nowlin 			goto err_unroll;
2150fd2a6b71SDan Nowlin 		}
2151fd2a6b71SDan Nowlin 
2152fd2a6b71SDan Nowlin 		idx = root_bufs.recipe_indx;
2153fd2a6b71SDan Nowlin 		is_root = root_bufs.content.rid & ICE_AQ_RECIPE_ID_IS_ROOT;
2154fd2a6b71SDan Nowlin 
2155fd2a6b71SDan Nowlin 		/* Mark all result indices in this chain */
2156fd2a6b71SDan Nowlin 		if (root_bufs.content.result_indx & ICE_AQ_RECIPE_RESULT_EN)
2157fd2a6b71SDan Nowlin 			set_bit(root_bufs.content.result_indx & ~ICE_AQ_RECIPE_RESULT_EN,
2158fd2a6b71SDan Nowlin 				result_bm);
2159fd2a6b71SDan Nowlin 
2160fd2a6b71SDan Nowlin 		/* get the first profile that is associated with rid */
2161fd2a6b71SDan Nowlin 		prof = find_first_bit(recipe_to_profile[idx],
2162fd2a6b71SDan Nowlin 				      ICE_MAX_NUM_PROFILES);
2163fd2a6b71SDan Nowlin 		for (i = 0; i < ICE_NUM_WORDS_RECIPE; i++) {
2164fd2a6b71SDan Nowlin 			u8 lkup_indx = root_bufs.content.lkup_indx[i + 1];
2165fd2a6b71SDan Nowlin 
2166fd2a6b71SDan Nowlin 			rg_entry->fv_idx[i] = lkup_indx;
2167fd2a6b71SDan Nowlin 			rg_entry->fv_mask[i] =
2168fd2a6b71SDan Nowlin 				le16_to_cpu(root_bufs.content.mask[i + 1]);
2169fd2a6b71SDan Nowlin 
2170fd2a6b71SDan Nowlin 			/* If the recipe is a chained recipe then all its
2171fd2a6b71SDan Nowlin 			 * child recipe's result will have a result index.
2172fd2a6b71SDan Nowlin 			 * To fill fv_words we should not use those result
2173fd2a6b71SDan Nowlin 			 * index, we only need the protocol ids and offsets.
2174fd2a6b71SDan Nowlin 			 * We will skip all the fv_idx which stores result
2175fd2a6b71SDan Nowlin 			 * index in them. We also need to skip any fv_idx which
2176fd2a6b71SDan Nowlin 			 * has ICE_AQ_RECIPE_LKUP_IGNORE or 0 since it isn't a
2177fd2a6b71SDan Nowlin 			 * valid offset value.
2178fd2a6b71SDan Nowlin 			 */
2179fd2a6b71SDan Nowlin 			if (test_bit(rg_entry->fv_idx[i], hw->switch_info->prof_res_bm[prof]) ||
2180fd2a6b71SDan Nowlin 			    rg_entry->fv_idx[i] & ICE_AQ_RECIPE_LKUP_IGNORE ||
2181fd2a6b71SDan Nowlin 			    rg_entry->fv_idx[i] == 0)
2182fd2a6b71SDan Nowlin 				continue;
2183fd2a6b71SDan Nowlin 
2184fd2a6b71SDan Nowlin 			ice_find_prot_off(hw, ICE_BLK_SW, prof,
2185fd2a6b71SDan Nowlin 					  rg_entry->fv_idx[i], &prot, &off);
2186fd2a6b71SDan Nowlin 			lkup_exts->fv_words[fv_word_idx].prot_id = prot;
2187fd2a6b71SDan Nowlin 			lkup_exts->fv_words[fv_word_idx].off = off;
2188fd2a6b71SDan Nowlin 			lkup_exts->field_mask[fv_word_idx] =
2189fd2a6b71SDan Nowlin 				rg_entry->fv_mask[i];
2190fd2a6b71SDan Nowlin 			fv_word_idx++;
2191fd2a6b71SDan Nowlin 		}
2192fd2a6b71SDan Nowlin 		/* populate rg_list with the data from the child entry of this
2193fd2a6b71SDan Nowlin 		 * recipe
2194fd2a6b71SDan Nowlin 		 */
2195fd2a6b71SDan Nowlin 		list_add(&rg_entry->l_entry, &recps[rid].rg_list);
2196fd2a6b71SDan Nowlin 
2197fd2a6b71SDan Nowlin 		/* Propagate some data to the recipe database */
2198fd2a6b71SDan Nowlin 		recps[idx].is_root = !!is_root;
2199fd2a6b71SDan Nowlin 		recps[idx].priority = root_bufs.content.act_ctrl_fwd_priority;
2200fd2a6b71SDan Nowlin 		bitmap_zero(recps[idx].res_idxs, ICE_MAX_FV_WORDS);
2201fd2a6b71SDan Nowlin 		if (root_bufs.content.result_indx & ICE_AQ_RECIPE_RESULT_EN) {
2202fd2a6b71SDan Nowlin 			recps[idx].chain_idx = root_bufs.content.result_indx &
2203fd2a6b71SDan Nowlin 				~ICE_AQ_RECIPE_RESULT_EN;
2204fd2a6b71SDan Nowlin 			set_bit(recps[idx].chain_idx, recps[idx].res_idxs);
2205fd2a6b71SDan Nowlin 		} else {
2206fd2a6b71SDan Nowlin 			recps[idx].chain_idx = ICE_INVAL_CHAIN_IND;
2207fd2a6b71SDan Nowlin 		}
2208fd2a6b71SDan Nowlin 
2209fd2a6b71SDan Nowlin 		if (!is_root)
2210fd2a6b71SDan Nowlin 			continue;
2211fd2a6b71SDan Nowlin 
2212fd2a6b71SDan Nowlin 		/* Only do the following for root recipes entries */
2213fd2a6b71SDan Nowlin 		memcpy(recps[idx].r_bitmap, root_bufs.recipe_bitmap,
2214fd2a6b71SDan Nowlin 		       sizeof(recps[idx].r_bitmap));
2215fd2a6b71SDan Nowlin 		recps[idx].root_rid = root_bufs.content.rid &
2216fd2a6b71SDan Nowlin 			~ICE_AQ_RECIPE_ID_IS_ROOT;
2217fd2a6b71SDan Nowlin 		recps[idx].priority = root_bufs.content.act_ctrl_fwd_priority;
2218fd2a6b71SDan Nowlin 	}
2219fd2a6b71SDan Nowlin 
2220fd2a6b71SDan Nowlin 	/* Complete initialization of the root recipe entry */
2221fd2a6b71SDan Nowlin 	lkup_exts->n_val_words = fv_word_idx;
2222fd2a6b71SDan Nowlin 	recps[rid].big_recp = (num_recps > 1);
2223fd2a6b71SDan Nowlin 	recps[rid].n_grp_count = (u8)num_recps;
2224fd2a6b71SDan Nowlin 	recps[rid].root_buf = devm_kmemdup(ice_hw_to_dev(hw), tmp,
2225fd2a6b71SDan Nowlin 					   recps[rid].n_grp_count * sizeof(*recps[rid].root_buf),
2226fd2a6b71SDan Nowlin 					   GFP_KERNEL);
2227c8e51a01SWang Hai 	if (!recps[rid].root_buf) {
2228d54699e2STony Nguyen 		status = -ENOMEM;
2229fd2a6b71SDan Nowlin 		goto err_unroll;
2230c8e51a01SWang Hai 	}
2231fd2a6b71SDan Nowlin 
2232fd2a6b71SDan Nowlin 	/* Copy result indexes */
2233fd2a6b71SDan Nowlin 	bitmap_copy(recps[rid].res_idxs, result_bm, ICE_MAX_FV_WORDS);
2234fd2a6b71SDan Nowlin 	recps[rid].recp_created = true;
2235fd2a6b71SDan Nowlin 
2236fd2a6b71SDan Nowlin err_unroll:
2237fd2a6b71SDan Nowlin 	kfree(tmp);
2238fd2a6b71SDan Nowlin 	return status;
2239fd2a6b71SDan Nowlin }
2240fd2a6b71SDan Nowlin 
22419c20346bSAnirudh Venkataramanan /* ice_init_port_info - Initialize port_info with switch configuration data
22429c20346bSAnirudh Venkataramanan  * @pi: pointer to port_info
22439c20346bSAnirudh Venkataramanan  * @vsi_port_num: VSI number or port number
22449c20346bSAnirudh Venkataramanan  * @type: Type of switch element (port or VSI)
22459c20346bSAnirudh Venkataramanan  * @swid: switch ID of the switch the element is attached to
22469c20346bSAnirudh Venkataramanan  * @pf_vf_num: PF or VF number
22479c20346bSAnirudh Venkataramanan  * @is_vf: true if the element is a VF, false otherwise
22489c20346bSAnirudh Venkataramanan  */
22499c20346bSAnirudh Venkataramanan static void
22509c20346bSAnirudh Venkataramanan ice_init_port_info(struct ice_port_info *pi, u16 vsi_port_num, u8 type,
22519c20346bSAnirudh Venkataramanan 		   u16 swid, u16 pf_vf_num, bool is_vf)
22529c20346bSAnirudh Venkataramanan {
22539c20346bSAnirudh Venkataramanan 	switch (type) {
22549c20346bSAnirudh Venkataramanan 	case ICE_AQC_GET_SW_CONF_RESP_PHYS_PORT:
22559c20346bSAnirudh Venkataramanan 		pi->lport = (u8)(vsi_port_num & ICE_LPORT_MASK);
22569c20346bSAnirudh Venkataramanan 		pi->sw_id = swid;
22579c20346bSAnirudh Venkataramanan 		pi->pf_vf_num = pf_vf_num;
22589c20346bSAnirudh Venkataramanan 		pi->is_vf = is_vf;
22599c20346bSAnirudh Venkataramanan 		break;
22609c20346bSAnirudh Venkataramanan 	default:
22619228d8b2SJacob Keller 		ice_debug(pi->hw, ICE_DBG_SW, "incorrect VSI/port type received\n");
22629c20346bSAnirudh Venkataramanan 		break;
22639c20346bSAnirudh Venkataramanan 	}
22649c20346bSAnirudh Venkataramanan }
22659c20346bSAnirudh Venkataramanan 
22669c20346bSAnirudh Venkataramanan /* ice_get_initial_sw_cfg - Get initial port and default VSI data
22679c20346bSAnirudh Venkataramanan  * @hw: pointer to the hardware structure
22689c20346bSAnirudh Venkataramanan  */
22695e24d598STony Nguyen int ice_get_initial_sw_cfg(struct ice_hw *hw)
22709c20346bSAnirudh Venkataramanan {
2271b3c38904SBruce Allan 	struct ice_aqc_get_sw_cfg_resp_elem *rbuf;
22729c20346bSAnirudh Venkataramanan 	u16 req_desc = 0;
22739c20346bSAnirudh Venkataramanan 	u16 num_elems;
22745518ac2aSTony Nguyen 	int status;
22759c20346bSAnirudh Venkataramanan 	u16 i;
22769c20346bSAnirudh Venkataramanan 
22779c20346bSAnirudh Venkataramanan 	rbuf = devm_kzalloc(ice_hw_to_dev(hw), ICE_SW_CFG_MAX_BUF_LEN,
22789c20346bSAnirudh Venkataramanan 			    GFP_KERNEL);
22799c20346bSAnirudh Venkataramanan 
22809c20346bSAnirudh Venkataramanan 	if (!rbuf)
2281d54699e2STony Nguyen 		return -ENOMEM;
22829c20346bSAnirudh Venkataramanan 
22839c20346bSAnirudh Venkataramanan 	/* Multiple calls to ice_aq_get_sw_cfg may be required
22849c20346bSAnirudh Venkataramanan 	 * to get all the switch configuration information. The need
22859c20346bSAnirudh Venkataramanan 	 * for additional calls is indicated by ice_aq_get_sw_cfg
22869c20346bSAnirudh Venkataramanan 	 * writing a non-zero value in req_desc
22879c20346bSAnirudh Venkataramanan 	 */
22889c20346bSAnirudh Venkataramanan 	do {
2289b3c38904SBruce Allan 		struct ice_aqc_get_sw_cfg_resp_elem *ele;
2290b3c38904SBruce Allan 
22919c20346bSAnirudh Venkataramanan 		status = ice_aq_get_sw_cfg(hw, rbuf, ICE_SW_CFG_MAX_BUF_LEN,
22929c20346bSAnirudh Venkataramanan 					   &req_desc, &num_elems, NULL);
22939c20346bSAnirudh Venkataramanan 
22949c20346bSAnirudh Venkataramanan 		if (status)
22959c20346bSAnirudh Venkataramanan 			break;
22969c20346bSAnirudh Venkataramanan 
2297b3c38904SBruce Allan 		for (i = 0, ele = rbuf; i < num_elems; i++, ele++) {
22989c20346bSAnirudh Venkataramanan 			u16 pf_vf_num, swid, vsi_port_num;
22999c20346bSAnirudh Venkataramanan 			bool is_vf = false;
23006dae8aa0SBruce Allan 			u8 res_type;
23019c20346bSAnirudh Venkataramanan 
23029c20346bSAnirudh Venkataramanan 			vsi_port_num = le16_to_cpu(ele->vsi_port_num) &
23039c20346bSAnirudh Venkataramanan 				ICE_AQC_GET_SW_CONF_RESP_VSI_PORT_NUM_M;
23049c20346bSAnirudh Venkataramanan 
23059c20346bSAnirudh Venkataramanan 			pf_vf_num = le16_to_cpu(ele->pf_vf_num) &
23069c20346bSAnirudh Venkataramanan 				ICE_AQC_GET_SW_CONF_RESP_FUNC_NUM_M;
23079c20346bSAnirudh Venkataramanan 
23089c20346bSAnirudh Venkataramanan 			swid = le16_to_cpu(ele->swid);
23099c20346bSAnirudh Venkataramanan 
23109c20346bSAnirudh Venkataramanan 			if (le16_to_cpu(ele->pf_vf_num) &
23119c20346bSAnirudh Venkataramanan 			    ICE_AQC_GET_SW_CONF_RESP_IS_VF)
23129c20346bSAnirudh Venkataramanan 				is_vf = true;
23139c20346bSAnirudh Venkataramanan 
231488865fc4SKarol Kolacinski 			res_type = (u8)(le16_to_cpu(ele->vsi_port_num) >>
231588865fc4SKarol Kolacinski 					ICE_AQC_GET_SW_CONF_RESP_TYPE_S);
23169c20346bSAnirudh Venkataramanan 
23176dae8aa0SBruce Allan 			if (res_type == ICE_AQC_GET_SW_CONF_RESP_VSI) {
23189c20346bSAnirudh Venkataramanan 				/* FW VSI is not needed. Just continue. */
23199c20346bSAnirudh Venkataramanan 				continue;
23209c20346bSAnirudh Venkataramanan 			}
23219c20346bSAnirudh Venkataramanan 
23229c20346bSAnirudh Venkataramanan 			ice_init_port_info(hw->port_info, vsi_port_num,
23236dae8aa0SBruce Allan 					   res_type, swid, pf_vf_num, is_vf);
23249c20346bSAnirudh Venkataramanan 		}
23259c20346bSAnirudh Venkataramanan 	} while (req_desc && !status);
23269c20346bSAnirudh Venkataramanan 
23277a63dae0SBruce Allan 	devm_kfree(ice_hw_to_dev(hw), rbuf);
23289c20346bSAnirudh Venkataramanan 	return status;
23299c20346bSAnirudh Venkataramanan }
23309daf8208SAnirudh Venkataramanan 
23319daf8208SAnirudh Venkataramanan /**
23329daf8208SAnirudh Venkataramanan  * ice_fill_sw_info - Helper function to populate lb_en and lan_en
23339daf8208SAnirudh Venkataramanan  * @hw: pointer to the hardware structure
23346a7e6993SYashaswini Raghuram Prathivadi Bhayankaram  * @fi: filter info structure to fill/update
23359daf8208SAnirudh Venkataramanan  *
23369daf8208SAnirudh Venkataramanan  * This helper function populates the lb_en and lan_en elements of the provided
23379daf8208SAnirudh Venkataramanan  * ice_fltr_info struct using the switch's type and characteristics of the
23389daf8208SAnirudh Venkataramanan  * switch rule being configured.
23399daf8208SAnirudh Venkataramanan  */
23406a7e6993SYashaswini Raghuram Prathivadi Bhayankaram static void ice_fill_sw_info(struct ice_hw *hw, struct ice_fltr_info *fi)
23419daf8208SAnirudh Venkataramanan {
23426a7e6993SYashaswini Raghuram Prathivadi Bhayankaram 	fi->lb_en = false;
23436a7e6993SYashaswini Raghuram Prathivadi Bhayankaram 	fi->lan_en = false;
23446a7e6993SYashaswini Raghuram Prathivadi Bhayankaram 	if ((fi->flag & ICE_FLTR_TX) &&
23456a7e6993SYashaswini Raghuram Prathivadi Bhayankaram 	    (fi->fltr_act == ICE_FWD_TO_VSI ||
23466a7e6993SYashaswini Raghuram Prathivadi Bhayankaram 	     fi->fltr_act == ICE_FWD_TO_VSI_LIST ||
23476a7e6993SYashaswini Raghuram Prathivadi Bhayankaram 	     fi->fltr_act == ICE_FWD_TO_Q ||
23486a7e6993SYashaswini Raghuram Prathivadi Bhayankaram 	     fi->fltr_act == ICE_FWD_TO_QGRP)) {
2349b58dafbcSChristopher N Bednarz 		/* Setting LB for prune actions will result in replicated
2350b58dafbcSChristopher N Bednarz 		 * packets to the internal switch that will be dropped.
2351b58dafbcSChristopher N Bednarz 		 */
2352b58dafbcSChristopher N Bednarz 		if (fi->lkup_type != ICE_SW_LKUP_VLAN)
23536a7e6993SYashaswini Raghuram Prathivadi Bhayankaram 			fi->lb_en = true;
2354b58dafbcSChristopher N Bednarz 
2355277b3a45SYashaswini Raghuram Prathivadi Bhayankaram 		/* Set lan_en to TRUE if
23566a7e6993SYashaswini Raghuram Prathivadi Bhayankaram 		 * 1. The switch is a VEB AND
23576a7e6993SYashaswini Raghuram Prathivadi Bhayankaram 		 * 2
235826069b44SYashaswini Raghuram Prathivadi Bhayankaram 		 * 2.1 The lookup is a directional lookup like ethertype,
2359f9867df6SAnirudh Venkataramanan 		 * promiscuous, ethertype-MAC, promiscuous-VLAN
236026069b44SYashaswini Raghuram Prathivadi Bhayankaram 		 * and default-port OR
236126069b44SYashaswini Raghuram Prathivadi Bhayankaram 		 * 2.2 The lookup is VLAN, OR
2362277b3a45SYashaswini Raghuram Prathivadi Bhayankaram 		 * 2.3 The lookup is MAC with mcast or bcast addr for MAC, OR
2363277b3a45SYashaswini Raghuram Prathivadi Bhayankaram 		 * 2.4 The lookup is MAC_VLAN with mcast or bcast addr for MAC.
23646a7e6993SYashaswini Raghuram Prathivadi Bhayankaram 		 *
2365277b3a45SYashaswini Raghuram Prathivadi Bhayankaram 		 * OR
2366277b3a45SYashaswini Raghuram Prathivadi Bhayankaram 		 *
2367277b3a45SYashaswini Raghuram Prathivadi Bhayankaram 		 * The switch is a VEPA.
2368277b3a45SYashaswini Raghuram Prathivadi Bhayankaram 		 *
2369277b3a45SYashaswini Raghuram Prathivadi Bhayankaram 		 * In all other cases, the LAN enable has to be set to false.
23706a7e6993SYashaswini Raghuram Prathivadi Bhayankaram 		 */
2371277b3a45SYashaswini Raghuram Prathivadi Bhayankaram 		if (hw->evb_veb) {
237226069b44SYashaswini Raghuram Prathivadi Bhayankaram 			if (fi->lkup_type == ICE_SW_LKUP_ETHERTYPE ||
237326069b44SYashaswini Raghuram Prathivadi Bhayankaram 			    fi->lkup_type == ICE_SW_LKUP_PROMISC ||
237426069b44SYashaswini Raghuram Prathivadi Bhayankaram 			    fi->lkup_type == ICE_SW_LKUP_ETHERTYPE_MAC ||
237526069b44SYashaswini Raghuram Prathivadi Bhayankaram 			    fi->lkup_type == ICE_SW_LKUP_PROMISC_VLAN ||
2376277b3a45SYashaswini Raghuram Prathivadi Bhayankaram 			    fi->lkup_type == ICE_SW_LKUP_DFLT ||
237726069b44SYashaswini Raghuram Prathivadi Bhayankaram 			    fi->lkup_type == ICE_SW_LKUP_VLAN ||
2378277b3a45SYashaswini Raghuram Prathivadi Bhayankaram 			    (fi->lkup_type == ICE_SW_LKUP_MAC &&
2379277b3a45SYashaswini Raghuram Prathivadi Bhayankaram 			     !is_unicast_ether_addr(fi->l_data.mac.mac_addr)) ||
23806a7e6993SYashaswini Raghuram Prathivadi Bhayankaram 			    (fi->lkup_type == ICE_SW_LKUP_MAC_VLAN &&
2381277b3a45SYashaswini Raghuram Prathivadi Bhayankaram 			     !is_unicast_ether_addr(fi->l_data.mac.mac_addr)))
23826a7e6993SYashaswini Raghuram Prathivadi Bhayankaram 				fi->lan_en = true;
2383277b3a45SYashaswini Raghuram Prathivadi Bhayankaram 		} else {
2384277b3a45SYashaswini Raghuram Prathivadi Bhayankaram 			fi->lan_en = true;
2385277b3a45SYashaswini Raghuram Prathivadi Bhayankaram 		}
23869daf8208SAnirudh Venkataramanan 	}
23879daf8208SAnirudh Venkataramanan }
23889daf8208SAnirudh Venkataramanan 
23899daf8208SAnirudh Venkataramanan /**
23909daf8208SAnirudh Venkataramanan  * ice_fill_sw_rule - Helper function to fill switch rule structure
23919daf8208SAnirudh Venkataramanan  * @hw: pointer to the hardware structure
23929daf8208SAnirudh Venkataramanan  * @f_info: entry containing packet forwarding information
23939daf8208SAnirudh Venkataramanan  * @s_rule: switch rule structure to be filled in based on mac_entry
23949daf8208SAnirudh Venkataramanan  * @opc: switch rules population command type - pass in the command opcode
23959daf8208SAnirudh Venkataramanan  */
23969daf8208SAnirudh Venkataramanan static void
23979daf8208SAnirudh Venkataramanan ice_fill_sw_rule(struct ice_hw *hw, struct ice_fltr_info *f_info,
23986e1ff618SAlexander Lobakin 		 struct ice_sw_rule_lkup_rx_tx *s_rule,
23996e1ff618SAlexander Lobakin 		 enum ice_adminq_opc opc)
24009daf8208SAnirudh Venkataramanan {
24019daf8208SAnirudh Venkataramanan 	u16 vlan_id = ICE_MAX_VLAN_ID + 1;
24022bfefa2dSBrett Creeley 	u16 vlan_tpid = ETH_P_8021Q;
24039daf8208SAnirudh Venkataramanan 	void *daddr = NULL;
240474118f7aSZhenning Xiao 	u16 eth_hdr_sz;
240574118f7aSZhenning Xiao 	u8 *eth_hdr;
24069daf8208SAnirudh Venkataramanan 	u32 act = 0;
24079daf8208SAnirudh Venkataramanan 	__be16 *off;
2408be8ff000SAnirudh Venkataramanan 	u8 q_rgn;
24099daf8208SAnirudh Venkataramanan 
24109daf8208SAnirudh Venkataramanan 	if (opc == ice_aqc_opc_remove_sw_rules) {
24116e1ff618SAlexander Lobakin 		s_rule->act = 0;
24126e1ff618SAlexander Lobakin 		s_rule->index = cpu_to_le16(f_info->fltr_rule_id);
24136e1ff618SAlexander Lobakin 		s_rule->hdr_len = 0;
24149daf8208SAnirudh Venkataramanan 		return;
24159daf8208SAnirudh Venkataramanan 	}
24169daf8208SAnirudh Venkataramanan 
241774118f7aSZhenning Xiao 	eth_hdr_sz = sizeof(dummy_eth_header);
24186e1ff618SAlexander Lobakin 	eth_hdr = s_rule->hdr_data;
241974118f7aSZhenning Xiao 
24209daf8208SAnirudh Venkataramanan 	/* initialize the ether header with a dummy header */
242174118f7aSZhenning Xiao 	memcpy(eth_hdr, dummy_eth_header, eth_hdr_sz);
24229daf8208SAnirudh Venkataramanan 	ice_fill_sw_info(hw, f_info);
24239daf8208SAnirudh Venkataramanan 
24249daf8208SAnirudh Venkataramanan 	switch (f_info->fltr_act) {
24259daf8208SAnirudh Venkataramanan 	case ICE_FWD_TO_VSI:
24265726ca0eSAnirudh Venkataramanan 		act |= (f_info->fwd_id.hw_vsi_id << ICE_SINGLE_ACT_VSI_ID_S) &
24279daf8208SAnirudh Venkataramanan 			ICE_SINGLE_ACT_VSI_ID_M;
24289daf8208SAnirudh Venkataramanan 		if (f_info->lkup_type != ICE_SW_LKUP_VLAN)
24299daf8208SAnirudh Venkataramanan 			act |= ICE_SINGLE_ACT_VSI_FORWARDING |
24309daf8208SAnirudh Venkataramanan 				ICE_SINGLE_ACT_VALID_BIT;
24319daf8208SAnirudh Venkataramanan 		break;
24329daf8208SAnirudh Venkataramanan 	case ICE_FWD_TO_VSI_LIST:
24339daf8208SAnirudh Venkataramanan 		act |= ICE_SINGLE_ACT_VSI_LIST;
24349daf8208SAnirudh Venkataramanan 		act |= (f_info->fwd_id.vsi_list_id <<
24359daf8208SAnirudh Venkataramanan 			ICE_SINGLE_ACT_VSI_LIST_ID_S) &
24369daf8208SAnirudh Venkataramanan 			ICE_SINGLE_ACT_VSI_LIST_ID_M;
24379daf8208SAnirudh Venkataramanan 		if (f_info->lkup_type != ICE_SW_LKUP_VLAN)
24389daf8208SAnirudh Venkataramanan 			act |= ICE_SINGLE_ACT_VSI_FORWARDING |
24399daf8208SAnirudh Venkataramanan 				ICE_SINGLE_ACT_VALID_BIT;
24409daf8208SAnirudh Venkataramanan 		break;
24419daf8208SAnirudh Venkataramanan 	case ICE_FWD_TO_Q:
24429daf8208SAnirudh Venkataramanan 		act |= ICE_SINGLE_ACT_TO_Q;
24439daf8208SAnirudh Venkataramanan 		act |= (f_info->fwd_id.q_id << ICE_SINGLE_ACT_Q_INDEX_S) &
24449daf8208SAnirudh Venkataramanan 			ICE_SINGLE_ACT_Q_INDEX_M;
24459daf8208SAnirudh Venkataramanan 		break;
24469daf8208SAnirudh Venkataramanan 	case ICE_DROP_PACKET:
2447be8ff000SAnirudh Venkataramanan 		act |= ICE_SINGLE_ACT_VSI_FORWARDING | ICE_SINGLE_ACT_DROP |
2448be8ff000SAnirudh Venkataramanan 			ICE_SINGLE_ACT_VALID_BIT;
2449be8ff000SAnirudh Venkataramanan 		break;
2450be8ff000SAnirudh Venkataramanan 	case ICE_FWD_TO_QGRP:
2451be8ff000SAnirudh Venkataramanan 		q_rgn = f_info->qgrp_size > 0 ?
2452be8ff000SAnirudh Venkataramanan 			(u8)ilog2(f_info->qgrp_size) : 0;
2453be8ff000SAnirudh Venkataramanan 		act |= ICE_SINGLE_ACT_TO_Q;
2454be8ff000SAnirudh Venkataramanan 		act |= (f_info->fwd_id.q_id << ICE_SINGLE_ACT_Q_INDEX_S) &
2455be8ff000SAnirudh Venkataramanan 			ICE_SINGLE_ACT_Q_INDEX_M;
2456be8ff000SAnirudh Venkataramanan 		act |= (q_rgn << ICE_SINGLE_ACT_Q_REGION_S) &
2457be8ff000SAnirudh Venkataramanan 			ICE_SINGLE_ACT_Q_REGION_M;
24589daf8208SAnirudh Venkataramanan 		break;
24599daf8208SAnirudh Venkataramanan 	default:
24609daf8208SAnirudh Venkataramanan 		return;
24619daf8208SAnirudh Venkataramanan 	}
24629daf8208SAnirudh Venkataramanan 
24639daf8208SAnirudh Venkataramanan 	if (f_info->lb_en)
24649daf8208SAnirudh Venkataramanan 		act |= ICE_SINGLE_ACT_LB_ENABLE;
24659daf8208SAnirudh Venkataramanan 	if (f_info->lan_en)
24669daf8208SAnirudh Venkataramanan 		act |= ICE_SINGLE_ACT_LAN_ENABLE;
24679daf8208SAnirudh Venkataramanan 
24689daf8208SAnirudh Venkataramanan 	switch (f_info->lkup_type) {
24699daf8208SAnirudh Venkataramanan 	case ICE_SW_LKUP_MAC:
24709daf8208SAnirudh Venkataramanan 		daddr = f_info->l_data.mac.mac_addr;
24719daf8208SAnirudh Venkataramanan 		break;
24729daf8208SAnirudh Venkataramanan 	case ICE_SW_LKUP_VLAN:
24739daf8208SAnirudh Venkataramanan 		vlan_id = f_info->l_data.vlan.vlan_id;
24742bfefa2dSBrett Creeley 		if (f_info->l_data.vlan.tpid_valid)
24752bfefa2dSBrett Creeley 			vlan_tpid = f_info->l_data.vlan.tpid;
24769daf8208SAnirudh Venkataramanan 		if (f_info->fltr_act == ICE_FWD_TO_VSI ||
24779daf8208SAnirudh Venkataramanan 		    f_info->fltr_act == ICE_FWD_TO_VSI_LIST) {
24789daf8208SAnirudh Venkataramanan 			act |= ICE_SINGLE_ACT_PRUNE;
24799daf8208SAnirudh Venkataramanan 			act |= ICE_SINGLE_ACT_EGRESS | ICE_SINGLE_ACT_INGRESS;
24809daf8208SAnirudh Venkataramanan 		}
24819daf8208SAnirudh Venkataramanan 		break;
24829daf8208SAnirudh Venkataramanan 	case ICE_SW_LKUP_ETHERTYPE_MAC:
24839daf8208SAnirudh Venkataramanan 		daddr = f_info->l_data.ethertype_mac.mac_addr;
24844e83fc93SBruce Allan 		fallthrough;
24859daf8208SAnirudh Venkataramanan 	case ICE_SW_LKUP_ETHERTYPE:
2486feee3cb3SBruce Allan 		off = (__force __be16 *)(eth_hdr + ICE_ETH_ETHTYPE_OFFSET);
24879daf8208SAnirudh Venkataramanan 		*off = cpu_to_be16(f_info->l_data.ethertype_mac.ethertype);
24889daf8208SAnirudh Venkataramanan 		break;
24899daf8208SAnirudh Venkataramanan 	case ICE_SW_LKUP_MAC_VLAN:
24909daf8208SAnirudh Venkataramanan 		daddr = f_info->l_data.mac_vlan.mac_addr;
24919daf8208SAnirudh Venkataramanan 		vlan_id = f_info->l_data.mac_vlan.vlan_id;
24929daf8208SAnirudh Venkataramanan 		break;
24939daf8208SAnirudh Venkataramanan 	case ICE_SW_LKUP_PROMISC_VLAN:
24949daf8208SAnirudh Venkataramanan 		vlan_id = f_info->l_data.mac_vlan.vlan_id;
24954e83fc93SBruce Allan 		fallthrough;
24969daf8208SAnirudh Venkataramanan 	case ICE_SW_LKUP_PROMISC:
24979daf8208SAnirudh Venkataramanan 		daddr = f_info->l_data.mac_vlan.mac_addr;
24989daf8208SAnirudh Venkataramanan 		break;
24999daf8208SAnirudh Venkataramanan 	default:
25009daf8208SAnirudh Venkataramanan 		break;
25019daf8208SAnirudh Venkataramanan 	}
25029daf8208SAnirudh Venkataramanan 
25036e1ff618SAlexander Lobakin 	s_rule->hdr.type = (f_info->flag & ICE_FLTR_RX) ?
25049daf8208SAnirudh Venkataramanan 		cpu_to_le16(ICE_AQC_SW_RULES_T_LKUP_RX) :
25059daf8208SAnirudh Venkataramanan 		cpu_to_le16(ICE_AQC_SW_RULES_T_LKUP_TX);
25069daf8208SAnirudh Venkataramanan 
25079daf8208SAnirudh Venkataramanan 	/* Recipe set depending on lookup type */
25086e1ff618SAlexander Lobakin 	s_rule->recipe_id = cpu_to_le16(f_info->lkup_type);
25096e1ff618SAlexander Lobakin 	s_rule->src = cpu_to_le16(f_info->src);
25106e1ff618SAlexander Lobakin 	s_rule->act = cpu_to_le32(act);
25119daf8208SAnirudh Venkataramanan 
25129daf8208SAnirudh Venkataramanan 	if (daddr)
251374118f7aSZhenning Xiao 		ether_addr_copy(eth_hdr + ICE_ETH_DA_OFFSET, daddr);
25149daf8208SAnirudh Venkataramanan 
25159daf8208SAnirudh Venkataramanan 	if (!(vlan_id > ICE_MAX_VLAN_ID)) {
2516feee3cb3SBruce Allan 		off = (__force __be16 *)(eth_hdr + ICE_ETH_VLAN_TCI_OFFSET);
25179daf8208SAnirudh Venkataramanan 		*off = cpu_to_be16(vlan_id);
25182bfefa2dSBrett Creeley 		off = (__force __be16 *)(eth_hdr + ICE_ETH_ETHTYPE_OFFSET);
25192bfefa2dSBrett Creeley 		*off = cpu_to_be16(vlan_tpid);
25209daf8208SAnirudh Venkataramanan 	}
25219daf8208SAnirudh Venkataramanan 
25229daf8208SAnirudh Venkataramanan 	/* Create the switch rule with the final dummy Ethernet header */
25239daf8208SAnirudh Venkataramanan 	if (opc != ice_aqc_opc_update_sw_rules)
25246e1ff618SAlexander Lobakin 		s_rule->hdr_len = cpu_to_le16(eth_hdr_sz);
25259daf8208SAnirudh Venkataramanan }
25269daf8208SAnirudh Venkataramanan 
25279daf8208SAnirudh Venkataramanan /**
25289daf8208SAnirudh Venkataramanan  * ice_add_marker_act
25299daf8208SAnirudh Venkataramanan  * @hw: pointer to the hardware structure
25309daf8208SAnirudh Venkataramanan  * @m_ent: the management entry for which sw marker needs to be added
25319daf8208SAnirudh Venkataramanan  * @sw_marker: sw marker to tag the Rx descriptor with
2532f9867df6SAnirudh Venkataramanan  * @l_id: large action resource ID
25339daf8208SAnirudh Venkataramanan  *
25349daf8208SAnirudh Venkataramanan  * Create a large action to hold software marker and update the switch rule
25359daf8208SAnirudh Venkataramanan  * entry pointed by m_ent with newly created large action
25369daf8208SAnirudh Venkataramanan  */
25375e24d598STony Nguyen static int
25389daf8208SAnirudh Venkataramanan ice_add_marker_act(struct ice_hw *hw, struct ice_fltr_mgmt_list_entry *m_ent,
25399daf8208SAnirudh Venkataramanan 		   u16 sw_marker, u16 l_id)
25409daf8208SAnirudh Venkataramanan {
25416e1ff618SAlexander Lobakin 	struct ice_sw_rule_lkup_rx_tx *rx_tx;
25426e1ff618SAlexander Lobakin 	struct ice_sw_rule_lg_act *lg_act;
25439daf8208SAnirudh Venkataramanan 	/* For software marker we need 3 large actions
25449daf8208SAnirudh Venkataramanan 	 * 1. FWD action: FWD TO VSI or VSI LIST
2545f9867df6SAnirudh Venkataramanan 	 * 2. GENERIC VALUE action to hold the profile ID
2546f9867df6SAnirudh Venkataramanan 	 * 3. GENERIC VALUE action to hold the software marker ID
25479daf8208SAnirudh Venkataramanan 	 */
25489daf8208SAnirudh Venkataramanan 	const u16 num_lg_acts = 3;
25499daf8208SAnirudh Venkataramanan 	u16 lg_act_size;
25509daf8208SAnirudh Venkataramanan 	u16 rules_size;
25515518ac2aSTony Nguyen 	int status;
25529daf8208SAnirudh Venkataramanan 	u32 act;
25535726ca0eSAnirudh Venkataramanan 	u16 id;
25549daf8208SAnirudh Venkataramanan 
25559daf8208SAnirudh Venkataramanan 	if (m_ent->fltr_info.lkup_type != ICE_SW_LKUP_MAC)
2556d54699e2STony Nguyen 		return -EINVAL;
25579daf8208SAnirudh Venkataramanan 
25589daf8208SAnirudh Venkataramanan 	/* Create two back-to-back switch rules and submit them to the HW using
25599daf8208SAnirudh Venkataramanan 	 * one memory buffer:
25609daf8208SAnirudh Venkataramanan 	 *    1. Large Action
2561d337f2afSAnirudh Venkataramanan 	 *    2. Look up Tx Rx
25629daf8208SAnirudh Venkataramanan 	 */
25636e1ff618SAlexander Lobakin 	lg_act_size = (u16)ICE_SW_RULE_LG_ACT_SIZE(lg_act, num_lg_acts);
25646e1ff618SAlexander Lobakin 	rules_size = lg_act_size + ICE_SW_RULE_RX_TX_ETH_HDR_SIZE(rx_tx);
25659daf8208SAnirudh Venkataramanan 	lg_act = devm_kzalloc(ice_hw_to_dev(hw), rules_size, GFP_KERNEL);
25669daf8208SAnirudh Venkataramanan 	if (!lg_act)
2567d54699e2STony Nguyen 		return -ENOMEM;
25689daf8208SAnirudh Venkataramanan 
25696e1ff618SAlexander Lobakin 	rx_tx = (typeof(rx_tx))((u8 *)lg_act + lg_act_size);
25709daf8208SAnirudh Venkataramanan 
25719daf8208SAnirudh Venkataramanan 	/* Fill in the first switch rule i.e. large action */
25726e1ff618SAlexander Lobakin 	lg_act->hdr.type = cpu_to_le16(ICE_AQC_SW_RULES_T_LG_ACT);
25736e1ff618SAlexander Lobakin 	lg_act->index = cpu_to_le16(l_id);
25746e1ff618SAlexander Lobakin 	lg_act->size = cpu_to_le16(num_lg_acts);
25759daf8208SAnirudh Venkataramanan 
25769daf8208SAnirudh Venkataramanan 	/* First action VSI forwarding or VSI list forwarding depending on how
25779daf8208SAnirudh Venkataramanan 	 * many VSIs
25789daf8208SAnirudh Venkataramanan 	 */
25795726ca0eSAnirudh Venkataramanan 	id = (m_ent->vsi_count > 1) ? m_ent->fltr_info.fwd_id.vsi_list_id :
25805726ca0eSAnirudh Venkataramanan 		m_ent->fltr_info.fwd_id.hw_vsi_id;
25819daf8208SAnirudh Venkataramanan 
25829daf8208SAnirudh Venkataramanan 	act = ICE_LG_ACT_VSI_FORWARDING | ICE_LG_ACT_VALID_BIT;
258366486d89SBruce Allan 	act |= (id << ICE_LG_ACT_VSI_LIST_ID_S) & ICE_LG_ACT_VSI_LIST_ID_M;
25849daf8208SAnirudh Venkataramanan 	if (m_ent->vsi_count > 1)
25859daf8208SAnirudh Venkataramanan 		act |= ICE_LG_ACT_VSI_LIST;
25866e1ff618SAlexander Lobakin 	lg_act->act[0] = cpu_to_le32(act);
25879daf8208SAnirudh Venkataramanan 
25889daf8208SAnirudh Venkataramanan 	/* Second action descriptor type */
25899daf8208SAnirudh Venkataramanan 	act = ICE_LG_ACT_GENERIC;
25909daf8208SAnirudh Venkataramanan 
25919daf8208SAnirudh Venkataramanan 	act |= (1 << ICE_LG_ACT_GENERIC_VALUE_S) & ICE_LG_ACT_GENERIC_VALUE_M;
25926e1ff618SAlexander Lobakin 	lg_act->act[1] = cpu_to_le32(act);
25939daf8208SAnirudh Venkataramanan 
25944381147dSAnirudh Venkataramanan 	act = (ICE_LG_ACT_GENERIC_OFF_RX_DESC_PROF_IDX <<
25954381147dSAnirudh Venkataramanan 	       ICE_LG_ACT_GENERIC_OFFSET_S) & ICE_LG_ACT_GENERIC_OFFSET_M;
25969daf8208SAnirudh Venkataramanan 
25979daf8208SAnirudh Venkataramanan 	/* Third action Marker value */
25989daf8208SAnirudh Venkataramanan 	act |= ICE_LG_ACT_GENERIC;
25999daf8208SAnirudh Venkataramanan 	act |= (sw_marker << ICE_LG_ACT_GENERIC_VALUE_S) &
26009daf8208SAnirudh Venkataramanan 		ICE_LG_ACT_GENERIC_VALUE_M;
26019daf8208SAnirudh Venkataramanan 
26026e1ff618SAlexander Lobakin 	lg_act->act[2] = cpu_to_le32(act);
26039daf8208SAnirudh Venkataramanan 
2604d337f2afSAnirudh Venkataramanan 	/* call the fill switch rule to fill the lookup Tx Rx structure */
26059daf8208SAnirudh Venkataramanan 	ice_fill_sw_rule(hw, &m_ent->fltr_info, rx_tx,
26069daf8208SAnirudh Venkataramanan 			 ice_aqc_opc_update_sw_rules);
26079daf8208SAnirudh Venkataramanan 
2608f9867df6SAnirudh Venkataramanan 	/* Update the action to point to the large action ID */
26096e1ff618SAlexander Lobakin 	rx_tx->act = cpu_to_le32(ICE_SINGLE_ACT_PTR |
26109daf8208SAnirudh Venkataramanan 				 ((l_id << ICE_SINGLE_ACT_PTR_VAL_S) &
26119daf8208SAnirudh Venkataramanan 				  ICE_SINGLE_ACT_PTR_VAL_M));
26129daf8208SAnirudh Venkataramanan 
2613f9867df6SAnirudh Venkataramanan 	/* Use the filter rule ID of the previously created rule with single
26149daf8208SAnirudh Venkataramanan 	 * act. Once the update happens, hardware will treat this as large
26159daf8208SAnirudh Venkataramanan 	 * action
26169daf8208SAnirudh Venkataramanan 	 */
26176e1ff618SAlexander Lobakin 	rx_tx->index = cpu_to_le16(m_ent->fltr_info.fltr_rule_id);
26189daf8208SAnirudh Venkataramanan 
26199daf8208SAnirudh Venkataramanan 	status = ice_aq_sw_rules(hw, lg_act, rules_size, 2,
26209daf8208SAnirudh Venkataramanan 				 ice_aqc_opc_update_sw_rules, NULL);
26219daf8208SAnirudh Venkataramanan 	if (!status) {
26229daf8208SAnirudh Venkataramanan 		m_ent->lg_act_idx = l_id;
26239daf8208SAnirudh Venkataramanan 		m_ent->sw_marker_id = sw_marker;
26249daf8208SAnirudh Venkataramanan 	}
26259daf8208SAnirudh Venkataramanan 
26269daf8208SAnirudh Venkataramanan 	devm_kfree(ice_hw_to_dev(hw), lg_act);
26279daf8208SAnirudh Venkataramanan 	return status;
26289daf8208SAnirudh Venkataramanan }
26299daf8208SAnirudh Venkataramanan 
26309daf8208SAnirudh Venkataramanan /**
26319daf8208SAnirudh Venkataramanan  * ice_create_vsi_list_map
26329daf8208SAnirudh Venkataramanan  * @hw: pointer to the hardware structure
26335726ca0eSAnirudh Venkataramanan  * @vsi_handle_arr: array of VSI handles to set in the VSI mapping
26345726ca0eSAnirudh Venkataramanan  * @num_vsi: number of VSI handles in the array
2635f9867df6SAnirudh Venkataramanan  * @vsi_list_id: VSI list ID generated as part of allocate resource
26369daf8208SAnirudh Venkataramanan  *
2637f9867df6SAnirudh Venkataramanan  * Helper function to create a new entry of VSI list ID to VSI mapping
2638f9867df6SAnirudh Venkataramanan  * using the given VSI list ID
26399daf8208SAnirudh Venkataramanan  */
26409daf8208SAnirudh Venkataramanan static struct ice_vsi_list_map_info *
26415726ca0eSAnirudh Venkataramanan ice_create_vsi_list_map(struct ice_hw *hw, u16 *vsi_handle_arr, u16 num_vsi,
26429daf8208SAnirudh Venkataramanan 			u16 vsi_list_id)
26439daf8208SAnirudh Venkataramanan {
26449daf8208SAnirudh Venkataramanan 	struct ice_switch_info *sw = hw->switch_info;
26459daf8208SAnirudh Venkataramanan 	struct ice_vsi_list_map_info *v_map;
26469daf8208SAnirudh Venkataramanan 	int i;
26479daf8208SAnirudh Venkataramanan 
264836ac7911SBruce Allan 	v_map = devm_kzalloc(ice_hw_to_dev(hw), sizeof(*v_map), GFP_KERNEL);
26499daf8208SAnirudh Venkataramanan 	if (!v_map)
26509daf8208SAnirudh Venkataramanan 		return NULL;
26519daf8208SAnirudh Venkataramanan 
26529daf8208SAnirudh Venkataramanan 	v_map->vsi_list_id = vsi_list_id;
26535726ca0eSAnirudh Venkataramanan 	v_map->ref_cnt = 1;
26549daf8208SAnirudh Venkataramanan 	for (i = 0; i < num_vsi; i++)
26555726ca0eSAnirudh Venkataramanan 		set_bit(vsi_handle_arr[i], v_map->vsi_map);
26569daf8208SAnirudh Venkataramanan 
26579daf8208SAnirudh Venkataramanan 	list_add(&v_map->list_entry, &sw->vsi_list_map_head);
26589daf8208SAnirudh Venkataramanan 	return v_map;
26599daf8208SAnirudh Venkataramanan }
26609daf8208SAnirudh Venkataramanan 
26619daf8208SAnirudh Venkataramanan /**
26629daf8208SAnirudh Venkataramanan  * ice_update_vsi_list_rule
26639daf8208SAnirudh Venkataramanan  * @hw: pointer to the hardware structure
26645726ca0eSAnirudh Venkataramanan  * @vsi_handle_arr: array of VSI handles to form a VSI list
26655726ca0eSAnirudh Venkataramanan  * @num_vsi: number of VSI handles in the array
2666f9867df6SAnirudh Venkataramanan  * @vsi_list_id: VSI list ID generated as part of allocate resource
26679daf8208SAnirudh Venkataramanan  * @remove: Boolean value to indicate if this is a remove action
26689daf8208SAnirudh Venkataramanan  * @opc: switch rules population command type - pass in the command opcode
26699daf8208SAnirudh Venkataramanan  * @lkup_type: lookup type of the filter
26709daf8208SAnirudh Venkataramanan  *
26719daf8208SAnirudh Venkataramanan  * Call AQ command to add a new switch rule or update existing switch rule
2672f9867df6SAnirudh Venkataramanan  * using the given VSI list ID
26739daf8208SAnirudh Venkataramanan  */
26745e24d598STony Nguyen static int
26755726ca0eSAnirudh Venkataramanan ice_update_vsi_list_rule(struct ice_hw *hw, u16 *vsi_handle_arr, u16 num_vsi,
26769daf8208SAnirudh Venkataramanan 			 u16 vsi_list_id, bool remove, enum ice_adminq_opc opc,
26779daf8208SAnirudh Venkataramanan 			 enum ice_sw_lkup_type lkup_type)
26789daf8208SAnirudh Venkataramanan {
26796e1ff618SAlexander Lobakin 	struct ice_sw_rule_vsi_list *s_rule;
26809daf8208SAnirudh Venkataramanan 	u16 s_rule_size;
26816dae8aa0SBruce Allan 	u16 rule_type;
26825518ac2aSTony Nguyen 	int status;
26839daf8208SAnirudh Venkataramanan 	int i;
26849daf8208SAnirudh Venkataramanan 
26859daf8208SAnirudh Venkataramanan 	if (!num_vsi)
2686d54699e2STony Nguyen 		return -EINVAL;
26879daf8208SAnirudh Venkataramanan 
26889daf8208SAnirudh Venkataramanan 	if (lkup_type == ICE_SW_LKUP_MAC ||
26899daf8208SAnirudh Venkataramanan 	    lkup_type == ICE_SW_LKUP_MAC_VLAN ||
26909daf8208SAnirudh Venkataramanan 	    lkup_type == ICE_SW_LKUP_ETHERTYPE ||
26919daf8208SAnirudh Venkataramanan 	    lkup_type == ICE_SW_LKUP_ETHERTYPE_MAC ||
26929daf8208SAnirudh Venkataramanan 	    lkup_type == ICE_SW_LKUP_PROMISC ||
2693d7393425SMichal Wilczynski 	    lkup_type == ICE_SW_LKUP_PROMISC_VLAN ||
2694d7393425SMichal Wilczynski 	    lkup_type == ICE_SW_LKUP_DFLT)
26956dae8aa0SBruce Allan 		rule_type = remove ? ICE_AQC_SW_RULES_T_VSI_LIST_CLEAR :
26969daf8208SAnirudh Venkataramanan 			ICE_AQC_SW_RULES_T_VSI_LIST_SET;
26979daf8208SAnirudh Venkataramanan 	else if (lkup_type == ICE_SW_LKUP_VLAN)
26986dae8aa0SBruce Allan 		rule_type = remove ? ICE_AQC_SW_RULES_T_PRUNE_LIST_CLEAR :
26999daf8208SAnirudh Venkataramanan 			ICE_AQC_SW_RULES_T_PRUNE_LIST_SET;
27009daf8208SAnirudh Venkataramanan 	else
2701d54699e2STony Nguyen 		return -EINVAL;
27029daf8208SAnirudh Venkataramanan 
27036e1ff618SAlexander Lobakin 	s_rule_size = (u16)ICE_SW_RULE_VSI_LIST_SIZE(s_rule, num_vsi);
27049daf8208SAnirudh Venkataramanan 	s_rule = devm_kzalloc(ice_hw_to_dev(hw), s_rule_size, GFP_KERNEL);
27059daf8208SAnirudh Venkataramanan 	if (!s_rule)
2706d54699e2STony Nguyen 		return -ENOMEM;
27075726ca0eSAnirudh Venkataramanan 	for (i = 0; i < num_vsi; i++) {
27085726ca0eSAnirudh Venkataramanan 		if (!ice_is_vsi_valid(hw, vsi_handle_arr[i])) {
2709d54699e2STony Nguyen 			status = -EINVAL;
27105726ca0eSAnirudh Venkataramanan 			goto exit;
27115726ca0eSAnirudh Venkataramanan 		}
27125726ca0eSAnirudh Venkataramanan 		/* AQ call requires hw_vsi_id(s) */
27136e1ff618SAlexander Lobakin 		s_rule->vsi[i] =
27145726ca0eSAnirudh Venkataramanan 			cpu_to_le16(ice_get_hw_vsi_num(hw, vsi_handle_arr[i]));
27155726ca0eSAnirudh Venkataramanan 	}
27169daf8208SAnirudh Venkataramanan 
27176e1ff618SAlexander Lobakin 	s_rule->hdr.type = cpu_to_le16(rule_type);
27186e1ff618SAlexander Lobakin 	s_rule->number_vsi = cpu_to_le16(num_vsi);
27196e1ff618SAlexander Lobakin 	s_rule->index = cpu_to_le16(vsi_list_id);
27209daf8208SAnirudh Venkataramanan 
27219daf8208SAnirudh Venkataramanan 	status = ice_aq_sw_rules(hw, s_rule, s_rule_size, 1, opc, NULL);
27229daf8208SAnirudh Venkataramanan 
27235726ca0eSAnirudh Venkataramanan exit:
27249daf8208SAnirudh Venkataramanan 	devm_kfree(ice_hw_to_dev(hw), s_rule);
27259daf8208SAnirudh Venkataramanan 	return status;
27269daf8208SAnirudh Venkataramanan }
27279daf8208SAnirudh Venkataramanan 
27289daf8208SAnirudh Venkataramanan /**
27299daf8208SAnirudh Venkataramanan  * ice_create_vsi_list_rule - Creates and populates a VSI list rule
2730f9867df6SAnirudh Venkataramanan  * @hw: pointer to the HW struct
27315726ca0eSAnirudh Venkataramanan  * @vsi_handle_arr: array of VSI handles to form a VSI list
27325726ca0eSAnirudh Venkataramanan  * @num_vsi: number of VSI handles in the array
27339daf8208SAnirudh Venkataramanan  * @vsi_list_id: stores the ID of the VSI list to be created
27349daf8208SAnirudh Venkataramanan  * @lkup_type: switch rule filter's lookup type
27359daf8208SAnirudh Venkataramanan  */
27365e24d598STony Nguyen static int
27375726ca0eSAnirudh Venkataramanan ice_create_vsi_list_rule(struct ice_hw *hw, u16 *vsi_handle_arr, u16 num_vsi,
27389daf8208SAnirudh Venkataramanan 			 u16 *vsi_list_id, enum ice_sw_lkup_type lkup_type)
27399daf8208SAnirudh Venkataramanan {
27405e24d598STony Nguyen 	int status;
27419daf8208SAnirudh Venkataramanan 
27429daf8208SAnirudh Venkataramanan 	status = ice_aq_alloc_free_vsi_list(hw, vsi_list_id, lkup_type,
27439daf8208SAnirudh Venkataramanan 					    ice_aqc_opc_alloc_res);
27449daf8208SAnirudh Venkataramanan 	if (status)
27459daf8208SAnirudh Venkataramanan 		return status;
27469daf8208SAnirudh Venkataramanan 
27479daf8208SAnirudh Venkataramanan 	/* Update the newly created VSI list to include the specified VSIs */
27485726ca0eSAnirudh Venkataramanan 	return ice_update_vsi_list_rule(hw, vsi_handle_arr, num_vsi,
27495726ca0eSAnirudh Venkataramanan 					*vsi_list_id, false,
27505726ca0eSAnirudh Venkataramanan 					ice_aqc_opc_add_sw_rules, lkup_type);
27519daf8208SAnirudh Venkataramanan }
27529daf8208SAnirudh Venkataramanan 
27539daf8208SAnirudh Venkataramanan /**
27549daf8208SAnirudh Venkataramanan  * ice_create_pkt_fwd_rule
27559daf8208SAnirudh Venkataramanan  * @hw: pointer to the hardware structure
27569daf8208SAnirudh Venkataramanan  * @f_entry: entry containing packet forwarding information
27579daf8208SAnirudh Venkataramanan  *
27589daf8208SAnirudh Venkataramanan  * Create switch rule with given filter information and add an entry
27599daf8208SAnirudh Venkataramanan  * to the corresponding filter management list to track this switch rule
27609daf8208SAnirudh Venkataramanan  * and VSI mapping
27619daf8208SAnirudh Venkataramanan  */
27625e24d598STony Nguyen static int
27639daf8208SAnirudh Venkataramanan ice_create_pkt_fwd_rule(struct ice_hw *hw,
27649daf8208SAnirudh Venkataramanan 			struct ice_fltr_list_entry *f_entry)
27659daf8208SAnirudh Venkataramanan {
27669daf8208SAnirudh Venkataramanan 	struct ice_fltr_mgmt_list_entry *fm_entry;
27676e1ff618SAlexander Lobakin 	struct ice_sw_rule_lkup_rx_tx *s_rule;
27689daf8208SAnirudh Venkataramanan 	enum ice_sw_lkup_type l_type;
276980d144c9SAnirudh Venkataramanan 	struct ice_sw_recipe *recp;
27705e24d598STony Nguyen 	int status;
27719daf8208SAnirudh Venkataramanan 
27729daf8208SAnirudh Venkataramanan 	s_rule = devm_kzalloc(ice_hw_to_dev(hw),
27736e1ff618SAlexander Lobakin 			      ICE_SW_RULE_RX_TX_ETH_HDR_SIZE(s_rule),
27746e1ff618SAlexander Lobakin 			      GFP_KERNEL);
27759daf8208SAnirudh Venkataramanan 	if (!s_rule)
2776d54699e2STony Nguyen 		return -ENOMEM;
27779daf8208SAnirudh Venkataramanan 	fm_entry = devm_kzalloc(ice_hw_to_dev(hw), sizeof(*fm_entry),
27789daf8208SAnirudh Venkataramanan 				GFP_KERNEL);
27799daf8208SAnirudh Venkataramanan 	if (!fm_entry) {
2780d54699e2STony Nguyen 		status = -ENOMEM;
27819daf8208SAnirudh Venkataramanan 		goto ice_create_pkt_fwd_rule_exit;
27829daf8208SAnirudh Venkataramanan 	}
27839daf8208SAnirudh Venkataramanan 
27849daf8208SAnirudh Venkataramanan 	fm_entry->fltr_info = f_entry->fltr_info;
27859daf8208SAnirudh Venkataramanan 
27869daf8208SAnirudh Venkataramanan 	/* Initialize all the fields for the management entry */
27879daf8208SAnirudh Venkataramanan 	fm_entry->vsi_count = 1;
27889daf8208SAnirudh Venkataramanan 	fm_entry->lg_act_idx = ICE_INVAL_LG_ACT_INDEX;
27899daf8208SAnirudh Venkataramanan 	fm_entry->sw_marker_id = ICE_INVAL_SW_MARKER_ID;
27909daf8208SAnirudh Venkataramanan 	fm_entry->counter_index = ICE_INVAL_COUNTER_ID;
27919daf8208SAnirudh Venkataramanan 
27929daf8208SAnirudh Venkataramanan 	ice_fill_sw_rule(hw, &fm_entry->fltr_info, s_rule,
27939daf8208SAnirudh Venkataramanan 			 ice_aqc_opc_add_sw_rules);
27949daf8208SAnirudh Venkataramanan 
27956e1ff618SAlexander Lobakin 	status = ice_aq_sw_rules(hw, s_rule,
27966e1ff618SAlexander Lobakin 				 ICE_SW_RULE_RX_TX_ETH_HDR_SIZE(s_rule), 1,
27979daf8208SAnirudh Venkataramanan 				 ice_aqc_opc_add_sw_rules, NULL);
27989daf8208SAnirudh Venkataramanan 	if (status) {
27999daf8208SAnirudh Venkataramanan 		devm_kfree(ice_hw_to_dev(hw), fm_entry);
28009daf8208SAnirudh Venkataramanan 		goto ice_create_pkt_fwd_rule_exit;
28019daf8208SAnirudh Venkataramanan 	}
28029daf8208SAnirudh Venkataramanan 
28036e1ff618SAlexander Lobakin 	f_entry->fltr_info.fltr_rule_id = le16_to_cpu(s_rule->index);
28046e1ff618SAlexander Lobakin 	fm_entry->fltr_info.fltr_rule_id = le16_to_cpu(s_rule->index);
28059daf8208SAnirudh Venkataramanan 
28069daf8208SAnirudh Venkataramanan 	/* The book keeping entries will get removed when base driver
28079daf8208SAnirudh Venkataramanan 	 * calls remove filter AQ command
28089daf8208SAnirudh Venkataramanan 	 */
28099daf8208SAnirudh Venkataramanan 	l_type = fm_entry->fltr_info.lkup_type;
281080d144c9SAnirudh Venkataramanan 	recp = &hw->switch_info->recp_list[l_type];
281180d144c9SAnirudh Venkataramanan 	list_add(&fm_entry->list_entry, &recp->filt_rules);
281280d144c9SAnirudh Venkataramanan 
28139daf8208SAnirudh Venkataramanan ice_create_pkt_fwd_rule_exit:
28149daf8208SAnirudh Venkataramanan 	devm_kfree(ice_hw_to_dev(hw), s_rule);
28159daf8208SAnirudh Venkataramanan 	return status;
28169daf8208SAnirudh Venkataramanan }
28179daf8208SAnirudh Venkataramanan 
28189daf8208SAnirudh Venkataramanan /**
28199daf8208SAnirudh Venkataramanan  * ice_update_pkt_fwd_rule
28209daf8208SAnirudh Venkataramanan  * @hw: pointer to the hardware structure
282180d144c9SAnirudh Venkataramanan  * @f_info: filter information for switch rule
28229daf8208SAnirudh Venkataramanan  *
28239daf8208SAnirudh Venkataramanan  * Call AQ command to update a previously created switch rule with a
2824f9867df6SAnirudh Venkataramanan  * VSI list ID
28259daf8208SAnirudh Venkataramanan  */
28265e24d598STony Nguyen static int
282780d144c9SAnirudh Venkataramanan ice_update_pkt_fwd_rule(struct ice_hw *hw, struct ice_fltr_info *f_info)
28289daf8208SAnirudh Venkataramanan {
28296e1ff618SAlexander Lobakin 	struct ice_sw_rule_lkup_rx_tx *s_rule;
28305e24d598STony Nguyen 	int status;
28319daf8208SAnirudh Venkataramanan 
28329daf8208SAnirudh Venkataramanan 	s_rule = devm_kzalloc(ice_hw_to_dev(hw),
28336e1ff618SAlexander Lobakin 			      ICE_SW_RULE_RX_TX_ETH_HDR_SIZE(s_rule),
28346e1ff618SAlexander Lobakin 			      GFP_KERNEL);
28359daf8208SAnirudh Venkataramanan 	if (!s_rule)
2836d54699e2STony Nguyen 		return -ENOMEM;
28379daf8208SAnirudh Venkataramanan 
283880d144c9SAnirudh Venkataramanan 	ice_fill_sw_rule(hw, f_info, s_rule, ice_aqc_opc_update_sw_rules);
28399daf8208SAnirudh Venkataramanan 
28406e1ff618SAlexander Lobakin 	s_rule->index = cpu_to_le16(f_info->fltr_rule_id);
28419daf8208SAnirudh Venkataramanan 
28429daf8208SAnirudh Venkataramanan 	/* Update switch rule with new rule set to forward VSI list */
28436e1ff618SAlexander Lobakin 	status = ice_aq_sw_rules(hw, s_rule,
28446e1ff618SAlexander Lobakin 				 ICE_SW_RULE_RX_TX_ETH_HDR_SIZE(s_rule), 1,
28459daf8208SAnirudh Venkataramanan 				 ice_aqc_opc_update_sw_rules, NULL);
28469daf8208SAnirudh Venkataramanan 
28479daf8208SAnirudh Venkataramanan 	devm_kfree(ice_hw_to_dev(hw), s_rule);
28489daf8208SAnirudh Venkataramanan 	return status;
28499daf8208SAnirudh Venkataramanan }
28509daf8208SAnirudh Venkataramanan 
28519daf8208SAnirudh Venkataramanan /**
2852b1edc14aSMd Fahad Iqbal Polash  * ice_update_sw_rule_bridge_mode
2853f9867df6SAnirudh Venkataramanan  * @hw: pointer to the HW struct
2854b1edc14aSMd Fahad Iqbal Polash  *
2855b1edc14aSMd Fahad Iqbal Polash  * Updates unicast switch filter rules based on VEB/VEPA mode
2856b1edc14aSMd Fahad Iqbal Polash  */
28575e24d598STony Nguyen int ice_update_sw_rule_bridge_mode(struct ice_hw *hw)
2858b1edc14aSMd Fahad Iqbal Polash {
2859b1edc14aSMd Fahad Iqbal Polash 	struct ice_switch_info *sw = hw->switch_info;
2860b1edc14aSMd Fahad Iqbal Polash 	struct ice_fltr_mgmt_list_entry *fm_entry;
2861b1edc14aSMd Fahad Iqbal Polash 	struct list_head *rule_head;
2862b1edc14aSMd Fahad Iqbal Polash 	struct mutex *rule_lock; /* Lock to protect filter rule list */
28635518ac2aSTony Nguyen 	int status = 0;
2864b1edc14aSMd Fahad Iqbal Polash 
2865b1edc14aSMd Fahad Iqbal Polash 	rule_lock = &sw->recp_list[ICE_SW_LKUP_MAC].filt_rule_lock;
2866b1edc14aSMd Fahad Iqbal Polash 	rule_head = &sw->recp_list[ICE_SW_LKUP_MAC].filt_rules;
2867b1edc14aSMd Fahad Iqbal Polash 
2868b1edc14aSMd Fahad Iqbal Polash 	mutex_lock(rule_lock);
2869b1edc14aSMd Fahad Iqbal Polash 	list_for_each_entry(fm_entry, rule_head, list_entry) {
2870b1edc14aSMd Fahad Iqbal Polash 		struct ice_fltr_info *fi = &fm_entry->fltr_info;
2871b1edc14aSMd Fahad Iqbal Polash 		u8 *addr = fi->l_data.mac.mac_addr;
2872b1edc14aSMd Fahad Iqbal Polash 
2873b1edc14aSMd Fahad Iqbal Polash 		/* Update unicast Tx rules to reflect the selected
2874b1edc14aSMd Fahad Iqbal Polash 		 * VEB/VEPA mode
2875b1edc14aSMd Fahad Iqbal Polash 		 */
2876b1edc14aSMd Fahad Iqbal Polash 		if ((fi->flag & ICE_FLTR_TX) && is_unicast_ether_addr(addr) &&
2877b1edc14aSMd Fahad Iqbal Polash 		    (fi->fltr_act == ICE_FWD_TO_VSI ||
2878b1edc14aSMd Fahad Iqbal Polash 		     fi->fltr_act == ICE_FWD_TO_VSI_LIST ||
2879b1edc14aSMd Fahad Iqbal Polash 		     fi->fltr_act == ICE_FWD_TO_Q ||
2880b1edc14aSMd Fahad Iqbal Polash 		     fi->fltr_act == ICE_FWD_TO_QGRP)) {
2881b1edc14aSMd Fahad Iqbal Polash 			status = ice_update_pkt_fwd_rule(hw, fi);
2882b1edc14aSMd Fahad Iqbal Polash 			if (status)
2883b1edc14aSMd Fahad Iqbal Polash 				break;
2884b1edc14aSMd Fahad Iqbal Polash 		}
2885b1edc14aSMd Fahad Iqbal Polash 	}
2886b1edc14aSMd Fahad Iqbal Polash 
2887b1edc14aSMd Fahad Iqbal Polash 	mutex_unlock(rule_lock);
2888b1edc14aSMd Fahad Iqbal Polash 
2889b1edc14aSMd Fahad Iqbal Polash 	return status;
2890b1edc14aSMd Fahad Iqbal Polash }
2891b1edc14aSMd Fahad Iqbal Polash 
2892b1edc14aSMd Fahad Iqbal Polash /**
289380d144c9SAnirudh Venkataramanan  * ice_add_update_vsi_list
28949daf8208SAnirudh Venkataramanan  * @hw: pointer to the hardware structure
28959daf8208SAnirudh Venkataramanan  * @m_entry: pointer to current filter management list entry
28969daf8208SAnirudh Venkataramanan  * @cur_fltr: filter information from the book keeping entry
28979daf8208SAnirudh Venkataramanan  * @new_fltr: filter information with the new VSI to be added
28989daf8208SAnirudh Venkataramanan  *
28999daf8208SAnirudh Venkataramanan  * Call AQ command to add or update previously created VSI list with new VSI.
29009daf8208SAnirudh Venkataramanan  *
29019daf8208SAnirudh Venkataramanan  * Helper function to do book keeping associated with adding filter information
2902d337f2afSAnirudh Venkataramanan  * The algorithm to do the book keeping is described below :
29039daf8208SAnirudh Venkataramanan  * When a VSI needs to subscribe to a given filter (MAC/VLAN/Ethtype etc.)
29049daf8208SAnirudh Venkataramanan  *	if only one VSI has been added till now
29059daf8208SAnirudh Venkataramanan  *		Allocate a new VSI list and add two VSIs
29069daf8208SAnirudh Venkataramanan  *		to this list using switch rule command
29079daf8208SAnirudh Venkataramanan  *		Update the previously created switch rule with the
2908f9867df6SAnirudh Venkataramanan  *		newly created VSI list ID
29099daf8208SAnirudh Venkataramanan  *	if a VSI list was previously created
29109daf8208SAnirudh Venkataramanan  *		Add the new VSI to the previously created VSI list set
29119daf8208SAnirudh Venkataramanan  *		using the update switch rule command
29129daf8208SAnirudh Venkataramanan  */
29135e24d598STony Nguyen static int
291480d144c9SAnirudh Venkataramanan ice_add_update_vsi_list(struct ice_hw *hw,
29159daf8208SAnirudh Venkataramanan 			struct ice_fltr_mgmt_list_entry *m_entry,
29169daf8208SAnirudh Venkataramanan 			struct ice_fltr_info *cur_fltr,
29179daf8208SAnirudh Venkataramanan 			struct ice_fltr_info *new_fltr)
29189daf8208SAnirudh Venkataramanan {
29199daf8208SAnirudh Venkataramanan 	u16 vsi_list_id = 0;
29205518ac2aSTony Nguyen 	int status = 0;
29219daf8208SAnirudh Venkataramanan 
29229daf8208SAnirudh Venkataramanan 	if ((cur_fltr->fltr_act == ICE_FWD_TO_Q ||
29239daf8208SAnirudh Venkataramanan 	     cur_fltr->fltr_act == ICE_FWD_TO_QGRP))
2924d54699e2STony Nguyen 		return -EOPNOTSUPP;
29259daf8208SAnirudh Venkataramanan 
29269daf8208SAnirudh Venkataramanan 	if ((new_fltr->fltr_act == ICE_FWD_TO_Q ||
29279daf8208SAnirudh Venkataramanan 	     new_fltr->fltr_act == ICE_FWD_TO_QGRP) &&
29289daf8208SAnirudh Venkataramanan 	    (cur_fltr->fltr_act == ICE_FWD_TO_VSI ||
29299daf8208SAnirudh Venkataramanan 	     cur_fltr->fltr_act == ICE_FWD_TO_VSI_LIST))
2930d54699e2STony Nguyen 		return -EOPNOTSUPP;
29319daf8208SAnirudh Venkataramanan 
29329daf8208SAnirudh Venkataramanan 	if (m_entry->vsi_count < 2 && !m_entry->vsi_list_info) {
29339daf8208SAnirudh Venkataramanan 		/* Only one entry existed in the mapping and it was not already
29349daf8208SAnirudh Venkataramanan 		 * a part of a VSI list. So, create a VSI list with the old and
29359daf8208SAnirudh Venkataramanan 		 * new VSIs.
29369daf8208SAnirudh Venkataramanan 		 */
293780d144c9SAnirudh Venkataramanan 		struct ice_fltr_info tmp_fltr;
29385726ca0eSAnirudh Venkataramanan 		u16 vsi_handle_arr[2];
29399daf8208SAnirudh Venkataramanan 
29409daf8208SAnirudh Venkataramanan 		/* A rule already exists with the new VSI being added */
29415726ca0eSAnirudh Venkataramanan 		if (cur_fltr->fwd_id.hw_vsi_id == new_fltr->fwd_id.hw_vsi_id)
2942d54699e2STony Nguyen 			return -EEXIST;
29439daf8208SAnirudh Venkataramanan 
29445726ca0eSAnirudh Venkataramanan 		vsi_handle_arr[0] = cur_fltr->vsi_handle;
29455726ca0eSAnirudh Venkataramanan 		vsi_handle_arr[1] = new_fltr->vsi_handle;
29465726ca0eSAnirudh Venkataramanan 		status = ice_create_vsi_list_rule(hw, &vsi_handle_arr[0], 2,
29479daf8208SAnirudh Venkataramanan 						  &vsi_list_id,
29489daf8208SAnirudh Venkataramanan 						  new_fltr->lkup_type);
29499daf8208SAnirudh Venkataramanan 		if (status)
29509daf8208SAnirudh Venkataramanan 			return status;
29519daf8208SAnirudh Venkataramanan 
295280d144c9SAnirudh Venkataramanan 		tmp_fltr = *new_fltr;
295380d144c9SAnirudh Venkataramanan 		tmp_fltr.fltr_rule_id = cur_fltr->fltr_rule_id;
295480d144c9SAnirudh Venkataramanan 		tmp_fltr.fltr_act = ICE_FWD_TO_VSI_LIST;
295580d144c9SAnirudh Venkataramanan 		tmp_fltr.fwd_id.vsi_list_id = vsi_list_id;
29569daf8208SAnirudh Venkataramanan 		/* Update the previous switch rule of "MAC forward to VSI" to
29579daf8208SAnirudh Venkataramanan 		 * "MAC fwd to VSI list"
29589daf8208SAnirudh Venkataramanan 		 */
295980d144c9SAnirudh Venkataramanan 		status = ice_update_pkt_fwd_rule(hw, &tmp_fltr);
29609daf8208SAnirudh Venkataramanan 		if (status)
29619daf8208SAnirudh Venkataramanan 			return status;
29629daf8208SAnirudh Venkataramanan 
29639daf8208SAnirudh Venkataramanan 		cur_fltr->fwd_id.vsi_list_id = vsi_list_id;
29649daf8208SAnirudh Venkataramanan 		cur_fltr->fltr_act = ICE_FWD_TO_VSI_LIST;
29659daf8208SAnirudh Venkataramanan 		m_entry->vsi_list_info =
29665726ca0eSAnirudh Venkataramanan 			ice_create_vsi_list_map(hw, &vsi_handle_arr[0], 2,
29679daf8208SAnirudh Venkataramanan 						vsi_list_id);
29689daf8208SAnirudh Venkataramanan 
29697a91d3f0SJacek Bułatek 		if (!m_entry->vsi_list_info)
2970d54699e2STony Nguyen 			return -ENOMEM;
29717a91d3f0SJacek Bułatek 
29729daf8208SAnirudh Venkataramanan 		/* If this entry was large action then the large action needs
29739daf8208SAnirudh Venkataramanan 		 * to be updated to point to FWD to VSI list
29749daf8208SAnirudh Venkataramanan 		 */
29759daf8208SAnirudh Venkataramanan 		if (m_entry->sw_marker_id != ICE_INVAL_SW_MARKER_ID)
29769daf8208SAnirudh Venkataramanan 			status =
29779daf8208SAnirudh Venkataramanan 			    ice_add_marker_act(hw, m_entry,
29789daf8208SAnirudh Venkataramanan 					       m_entry->sw_marker_id,
29799daf8208SAnirudh Venkataramanan 					       m_entry->lg_act_idx);
29809daf8208SAnirudh Venkataramanan 	} else {
29815726ca0eSAnirudh Venkataramanan 		u16 vsi_handle = new_fltr->vsi_handle;
29829daf8208SAnirudh Venkataramanan 		enum ice_adminq_opc opcode;
29839daf8208SAnirudh Venkataramanan 
2984f25dad19SBruce Allan 		if (!m_entry->vsi_list_info)
2985d54699e2STony Nguyen 			return -EIO;
2986f25dad19SBruce Allan 
29879daf8208SAnirudh Venkataramanan 		/* A rule already exists with the new VSI being added */
29885726ca0eSAnirudh Venkataramanan 		if (test_bit(vsi_handle, m_entry->vsi_list_info->vsi_map))
29899daf8208SAnirudh Venkataramanan 			return 0;
29909daf8208SAnirudh Venkataramanan 
29919daf8208SAnirudh Venkataramanan 		/* Update the previously created VSI list set with
2992f9867df6SAnirudh Venkataramanan 		 * the new VSI ID passed in
29939daf8208SAnirudh Venkataramanan 		 */
29949daf8208SAnirudh Venkataramanan 		vsi_list_id = cur_fltr->fwd_id.vsi_list_id;
29959daf8208SAnirudh Venkataramanan 		opcode = ice_aqc_opc_update_sw_rules;
29969daf8208SAnirudh Venkataramanan 
29975726ca0eSAnirudh Venkataramanan 		status = ice_update_vsi_list_rule(hw, &vsi_handle, 1,
29985726ca0eSAnirudh Venkataramanan 						  vsi_list_id, false, opcode,
29999daf8208SAnirudh Venkataramanan 						  new_fltr->lkup_type);
3000f9867df6SAnirudh Venkataramanan 		/* update VSI list mapping info with new VSI ID */
30019daf8208SAnirudh Venkataramanan 		if (!status)
30025726ca0eSAnirudh Venkataramanan 			set_bit(vsi_handle, m_entry->vsi_list_info->vsi_map);
30039daf8208SAnirudh Venkataramanan 	}
30049daf8208SAnirudh Venkataramanan 	if (!status)
30059daf8208SAnirudh Venkataramanan 		m_entry->vsi_count++;
30069daf8208SAnirudh Venkataramanan 	return status;
30079daf8208SAnirudh Venkataramanan }
30089daf8208SAnirudh Venkataramanan 
30099daf8208SAnirudh Venkataramanan /**
301080d144c9SAnirudh Venkataramanan  * ice_find_rule_entry - Search a rule entry
30119daf8208SAnirudh Venkataramanan  * @hw: pointer to the hardware structure
301280d144c9SAnirudh Venkataramanan  * @recp_id: lookup type for which the specified rule needs to be searched
301380d144c9SAnirudh Venkataramanan  * @f_info: rule information
30149daf8208SAnirudh Venkataramanan  *
301580d144c9SAnirudh Venkataramanan  * Helper function to search for a given rule entry
301680d144c9SAnirudh Venkataramanan  * Returns pointer to entry storing the rule if found
30179daf8208SAnirudh Venkataramanan  */
30189daf8208SAnirudh Venkataramanan static struct ice_fltr_mgmt_list_entry *
301980d144c9SAnirudh Venkataramanan ice_find_rule_entry(struct ice_hw *hw, u8 recp_id, struct ice_fltr_info *f_info)
30209daf8208SAnirudh Venkataramanan {
302180d144c9SAnirudh Venkataramanan 	struct ice_fltr_mgmt_list_entry *list_itr, *ret = NULL;
30229daf8208SAnirudh Venkataramanan 	struct ice_switch_info *sw = hw->switch_info;
302380d144c9SAnirudh Venkataramanan 	struct list_head *list_head;
30249daf8208SAnirudh Venkataramanan 
302580d144c9SAnirudh Venkataramanan 	list_head = &sw->recp_list[recp_id].filt_rules;
302680d144c9SAnirudh Venkataramanan 	list_for_each_entry(list_itr, list_head, list_entry) {
302780d144c9SAnirudh Venkataramanan 		if (!memcmp(&f_info->l_data, &list_itr->fltr_info.l_data,
302880d144c9SAnirudh Venkataramanan 			    sizeof(f_info->l_data)) &&
302980d144c9SAnirudh Venkataramanan 		    f_info->flag == list_itr->fltr_info.flag) {
303080d144c9SAnirudh Venkataramanan 			ret = list_itr;
30319daf8208SAnirudh Venkataramanan 			break;
30329daf8208SAnirudh Venkataramanan 		}
30339daf8208SAnirudh Venkataramanan 	}
303480d144c9SAnirudh Venkataramanan 	return ret;
30359daf8208SAnirudh Venkataramanan }
30369daf8208SAnirudh Venkataramanan 
30379daf8208SAnirudh Venkataramanan /**
30385726ca0eSAnirudh Venkataramanan  * ice_find_vsi_list_entry - Search VSI list map with VSI count 1
30395726ca0eSAnirudh Venkataramanan  * @hw: pointer to the hardware structure
30405726ca0eSAnirudh Venkataramanan  * @recp_id: lookup type for which VSI lists needs to be searched
30415726ca0eSAnirudh Venkataramanan  * @vsi_handle: VSI handle to be found in VSI list
3042f9867df6SAnirudh Venkataramanan  * @vsi_list_id: VSI list ID found containing vsi_handle
30435726ca0eSAnirudh Venkataramanan  *
30445726ca0eSAnirudh Venkataramanan  * Helper function to search a VSI list with single entry containing given VSI
30455726ca0eSAnirudh Venkataramanan  * handle element. This can be extended further to search VSI list with more
30465726ca0eSAnirudh Venkataramanan  * than 1 vsi_count. Returns pointer to VSI list entry if found.
30475726ca0eSAnirudh Venkataramanan  */
30485726ca0eSAnirudh Venkataramanan static struct ice_vsi_list_map_info *
30495726ca0eSAnirudh Venkataramanan ice_find_vsi_list_entry(struct ice_hw *hw, u8 recp_id, u16 vsi_handle,
30505726ca0eSAnirudh Venkataramanan 			u16 *vsi_list_id)
30515726ca0eSAnirudh Venkataramanan {
30525726ca0eSAnirudh Venkataramanan 	struct ice_vsi_list_map_info *map_info = NULL;
30535726ca0eSAnirudh Venkataramanan 	struct ice_switch_info *sw = hw->switch_info;
30545726ca0eSAnirudh Venkataramanan 	struct ice_fltr_mgmt_list_entry *list_itr;
30555726ca0eSAnirudh Venkataramanan 	struct list_head *list_head;
30565726ca0eSAnirudh Venkataramanan 
30575726ca0eSAnirudh Venkataramanan 	list_head = &sw->recp_list[recp_id].filt_rules;
30585726ca0eSAnirudh Venkataramanan 	list_for_each_entry(list_itr, list_head, list_entry) {
30595726ca0eSAnirudh Venkataramanan 		if (list_itr->vsi_count == 1 && list_itr->vsi_list_info) {
30605726ca0eSAnirudh Venkataramanan 			map_info = list_itr->vsi_list_info;
30615726ca0eSAnirudh Venkataramanan 			if (test_bit(vsi_handle, map_info->vsi_map)) {
30625726ca0eSAnirudh Venkataramanan 				*vsi_list_id = map_info->vsi_list_id;
30635726ca0eSAnirudh Venkataramanan 				return map_info;
30645726ca0eSAnirudh Venkataramanan 			}
30655726ca0eSAnirudh Venkataramanan 		}
30665726ca0eSAnirudh Venkataramanan 	}
30675726ca0eSAnirudh Venkataramanan 	return NULL;
30685726ca0eSAnirudh Venkataramanan }
30695726ca0eSAnirudh Venkataramanan 
30705726ca0eSAnirudh Venkataramanan /**
307180d144c9SAnirudh Venkataramanan  * ice_add_rule_internal - add rule for a given lookup type
30729daf8208SAnirudh Venkataramanan  * @hw: pointer to the hardware structure
3073f9867df6SAnirudh Venkataramanan  * @recp_id: lookup type (recipe ID) for which rule has to be added
30749daf8208SAnirudh Venkataramanan  * @f_entry: structure containing MAC forwarding information
30759daf8208SAnirudh Venkataramanan  *
307680d144c9SAnirudh Venkataramanan  * Adds or updates the rule lists for a given recipe
30779daf8208SAnirudh Venkataramanan  */
30785e24d598STony Nguyen static int
307980d144c9SAnirudh Venkataramanan ice_add_rule_internal(struct ice_hw *hw, u8 recp_id,
308080d144c9SAnirudh Venkataramanan 		      struct ice_fltr_list_entry *f_entry)
30819daf8208SAnirudh Venkataramanan {
308280d144c9SAnirudh Venkataramanan 	struct ice_switch_info *sw = hw->switch_info;
30839daf8208SAnirudh Venkataramanan 	struct ice_fltr_info *new_fltr, *cur_fltr;
30849daf8208SAnirudh Venkataramanan 	struct ice_fltr_mgmt_list_entry *m_entry;
308580d144c9SAnirudh Venkataramanan 	struct mutex *rule_lock; /* Lock to protect filter rule list */
30865e24d598STony Nguyen 	int status = 0;
30879daf8208SAnirudh Venkataramanan 
30885726ca0eSAnirudh Venkataramanan 	if (!ice_is_vsi_valid(hw, f_entry->fltr_info.vsi_handle))
3089d54699e2STony Nguyen 		return -EINVAL;
30905726ca0eSAnirudh Venkataramanan 	f_entry->fltr_info.fwd_id.hw_vsi_id =
30915726ca0eSAnirudh Venkataramanan 		ice_get_hw_vsi_num(hw, f_entry->fltr_info.vsi_handle);
30925726ca0eSAnirudh Venkataramanan 
309380d144c9SAnirudh Venkataramanan 	rule_lock = &sw->recp_list[recp_id].filt_rule_lock;
309480d144c9SAnirudh Venkataramanan 
309580d144c9SAnirudh Venkataramanan 	mutex_lock(rule_lock);
30969daf8208SAnirudh Venkataramanan 	new_fltr = &f_entry->fltr_info;
309780d144c9SAnirudh Venkataramanan 	if (new_fltr->flag & ICE_FLTR_RX)
309880d144c9SAnirudh Venkataramanan 		new_fltr->src = hw->port_info->lport;
309980d144c9SAnirudh Venkataramanan 	else if (new_fltr->flag & ICE_FLTR_TX)
31005726ca0eSAnirudh Venkataramanan 		new_fltr->src = f_entry->fltr_info.fwd_id.hw_vsi_id;
31019daf8208SAnirudh Venkataramanan 
310280d144c9SAnirudh Venkataramanan 	m_entry = ice_find_rule_entry(hw, recp_id, new_fltr);
310380d144c9SAnirudh Venkataramanan 	if (!m_entry) {
310480d144c9SAnirudh Venkataramanan 		mutex_unlock(rule_lock);
31059daf8208SAnirudh Venkataramanan 		return ice_create_pkt_fwd_rule(hw, f_entry);
310680d144c9SAnirudh Venkataramanan 	}
31079daf8208SAnirudh Venkataramanan 
31089daf8208SAnirudh Venkataramanan 	cur_fltr = &m_entry->fltr_info;
310980d144c9SAnirudh Venkataramanan 	status = ice_add_update_vsi_list(hw, m_entry, cur_fltr, new_fltr);
311080d144c9SAnirudh Venkataramanan 	mutex_unlock(rule_lock);
31119daf8208SAnirudh Venkataramanan 
311280d144c9SAnirudh Venkataramanan 	return status;
311380d144c9SAnirudh Venkataramanan }
311480d144c9SAnirudh Venkataramanan 
311580d144c9SAnirudh Venkataramanan /**
311680d144c9SAnirudh Venkataramanan  * ice_remove_vsi_list_rule
311780d144c9SAnirudh Venkataramanan  * @hw: pointer to the hardware structure
3118f9867df6SAnirudh Venkataramanan  * @vsi_list_id: VSI list ID generated as part of allocate resource
311980d144c9SAnirudh Venkataramanan  * @lkup_type: switch rule filter lookup type
312080d144c9SAnirudh Venkataramanan  *
312180d144c9SAnirudh Venkataramanan  * The VSI list should be emptied before this function is called to remove the
312280d144c9SAnirudh Venkataramanan  * VSI list.
312380d144c9SAnirudh Venkataramanan  */
31245e24d598STony Nguyen static int
312580d144c9SAnirudh Venkataramanan ice_remove_vsi_list_rule(struct ice_hw *hw, u16 vsi_list_id,
312680d144c9SAnirudh Venkataramanan 			 enum ice_sw_lkup_type lkup_type)
312780d144c9SAnirudh Venkataramanan {
31286e1ff618SAlexander Lobakin 	struct ice_sw_rule_vsi_list *s_rule;
312980d144c9SAnirudh Venkataramanan 	u16 s_rule_size;
31305518ac2aSTony Nguyen 	int status;
313180d144c9SAnirudh Venkataramanan 
31326e1ff618SAlexander Lobakin 	s_rule_size = (u16)ICE_SW_RULE_VSI_LIST_SIZE(s_rule, 0);
313380d144c9SAnirudh Venkataramanan 	s_rule = devm_kzalloc(ice_hw_to_dev(hw), s_rule_size, GFP_KERNEL);
313480d144c9SAnirudh Venkataramanan 	if (!s_rule)
3135d54699e2STony Nguyen 		return -ENOMEM;
313680d144c9SAnirudh Venkataramanan 
31376e1ff618SAlexander Lobakin 	s_rule->hdr.type = cpu_to_le16(ICE_AQC_SW_RULES_T_VSI_LIST_CLEAR);
31386e1ff618SAlexander Lobakin 	s_rule->index = cpu_to_le16(vsi_list_id);
313980d144c9SAnirudh Venkataramanan 
314080d144c9SAnirudh Venkataramanan 	/* Free the vsi_list resource that we allocated. It is assumed that the
314180d144c9SAnirudh Venkataramanan 	 * list is empty at this point.
314280d144c9SAnirudh Venkataramanan 	 */
314380d144c9SAnirudh Venkataramanan 	status = ice_aq_alloc_free_vsi_list(hw, &vsi_list_id, lkup_type,
314480d144c9SAnirudh Venkataramanan 					    ice_aqc_opc_free_res);
314580d144c9SAnirudh Venkataramanan 
314680d144c9SAnirudh Venkataramanan 	devm_kfree(ice_hw_to_dev(hw), s_rule);
314780d144c9SAnirudh Venkataramanan 	return status;
314880d144c9SAnirudh Venkataramanan }
314980d144c9SAnirudh Venkataramanan 
315080d144c9SAnirudh Venkataramanan /**
315180d144c9SAnirudh Venkataramanan  * ice_rem_update_vsi_list
315280d144c9SAnirudh Venkataramanan  * @hw: pointer to the hardware structure
31535726ca0eSAnirudh Venkataramanan  * @vsi_handle: VSI handle of the VSI to remove
315480d144c9SAnirudh Venkataramanan  * @fm_list: filter management entry for which the VSI list management needs to
315580d144c9SAnirudh Venkataramanan  *           be done
315680d144c9SAnirudh Venkataramanan  */
31575e24d598STony Nguyen static int
31585726ca0eSAnirudh Venkataramanan ice_rem_update_vsi_list(struct ice_hw *hw, u16 vsi_handle,
315980d144c9SAnirudh Venkataramanan 			struct ice_fltr_mgmt_list_entry *fm_list)
316080d144c9SAnirudh Venkataramanan {
316180d144c9SAnirudh Venkataramanan 	enum ice_sw_lkup_type lkup_type;
316280d144c9SAnirudh Venkataramanan 	u16 vsi_list_id;
31635518ac2aSTony Nguyen 	int status = 0;
316480d144c9SAnirudh Venkataramanan 
316580d144c9SAnirudh Venkataramanan 	if (fm_list->fltr_info.fltr_act != ICE_FWD_TO_VSI_LIST ||
316680d144c9SAnirudh Venkataramanan 	    fm_list->vsi_count == 0)
3167d54699e2STony Nguyen 		return -EINVAL;
316880d144c9SAnirudh Venkataramanan 
316980d144c9SAnirudh Venkataramanan 	/* A rule with the VSI being removed does not exist */
31705726ca0eSAnirudh Venkataramanan 	if (!test_bit(vsi_handle, fm_list->vsi_list_info->vsi_map))
3171d54699e2STony Nguyen 		return -ENOENT;
317280d144c9SAnirudh Venkataramanan 
317380d144c9SAnirudh Venkataramanan 	lkup_type = fm_list->fltr_info.lkup_type;
317480d144c9SAnirudh Venkataramanan 	vsi_list_id = fm_list->fltr_info.fwd_id.vsi_list_id;
31755726ca0eSAnirudh Venkataramanan 	status = ice_update_vsi_list_rule(hw, &vsi_handle, 1, vsi_list_id, true,
317680d144c9SAnirudh Venkataramanan 					  ice_aqc_opc_update_sw_rules,
317780d144c9SAnirudh Venkataramanan 					  lkup_type);
317880d144c9SAnirudh Venkataramanan 	if (status)
317980d144c9SAnirudh Venkataramanan 		return status;
318080d144c9SAnirudh Venkataramanan 
318180d144c9SAnirudh Venkataramanan 	fm_list->vsi_count--;
31825726ca0eSAnirudh Venkataramanan 	clear_bit(vsi_handle, fm_list->vsi_list_info->vsi_map);
318380d144c9SAnirudh Venkataramanan 
3184c60cdb13SBrett Creeley 	if (fm_list->vsi_count == 1 && lkup_type != ICE_SW_LKUP_VLAN) {
3185c60cdb13SBrett Creeley 		struct ice_fltr_info tmp_fltr_info = fm_list->fltr_info;
318680d144c9SAnirudh Venkataramanan 		struct ice_vsi_list_map_info *vsi_list_info =
318780d144c9SAnirudh Venkataramanan 			fm_list->vsi_list_info;
31885726ca0eSAnirudh Venkataramanan 		u16 rem_vsi_handle;
318980d144c9SAnirudh Venkataramanan 
31905726ca0eSAnirudh Venkataramanan 		rem_vsi_handle = find_first_bit(vsi_list_info->vsi_map,
319180d144c9SAnirudh Venkataramanan 						ICE_MAX_VSI);
31925726ca0eSAnirudh Venkataramanan 		if (!ice_is_vsi_valid(hw, rem_vsi_handle))
3193d54699e2STony Nguyen 			return -EIO;
3194c60cdb13SBrett Creeley 
3195c60cdb13SBrett Creeley 		/* Make sure VSI list is empty before removing it below */
31965726ca0eSAnirudh Venkataramanan 		status = ice_update_vsi_list_rule(hw, &rem_vsi_handle, 1,
319780d144c9SAnirudh Venkataramanan 						  vsi_list_id, true,
319880d144c9SAnirudh Venkataramanan 						  ice_aqc_opc_update_sw_rules,
319980d144c9SAnirudh Venkataramanan 						  lkup_type);
320080d144c9SAnirudh Venkataramanan 		if (status)
320180d144c9SAnirudh Venkataramanan 			return status;
320280d144c9SAnirudh Venkataramanan 
3203c60cdb13SBrett Creeley 		tmp_fltr_info.fltr_act = ICE_FWD_TO_VSI;
3204c60cdb13SBrett Creeley 		tmp_fltr_info.fwd_id.hw_vsi_id =
3205c60cdb13SBrett Creeley 			ice_get_hw_vsi_num(hw, rem_vsi_handle);
3206c60cdb13SBrett Creeley 		tmp_fltr_info.vsi_handle = rem_vsi_handle;
3207c60cdb13SBrett Creeley 		status = ice_update_pkt_fwd_rule(hw, &tmp_fltr_info);
3208c60cdb13SBrett Creeley 		if (status) {
32099228d8b2SJacob Keller 			ice_debug(hw, ICE_DBG_SW, "Failed to update pkt fwd rule to FWD_TO_VSI on HW VSI %d, error %d\n",
3210c60cdb13SBrett Creeley 				  tmp_fltr_info.fwd_id.hw_vsi_id, status);
3211c60cdb13SBrett Creeley 			return status;
3212c60cdb13SBrett Creeley 		}
3213c60cdb13SBrett Creeley 
3214c60cdb13SBrett Creeley 		fm_list->fltr_info = tmp_fltr_info;
3215c60cdb13SBrett Creeley 	}
3216c60cdb13SBrett Creeley 
3217c60cdb13SBrett Creeley 	if ((fm_list->vsi_count == 1 && lkup_type != ICE_SW_LKUP_VLAN) ||
3218c60cdb13SBrett Creeley 	    (fm_list->vsi_count == 0 && lkup_type == ICE_SW_LKUP_VLAN)) {
3219c60cdb13SBrett Creeley 		struct ice_vsi_list_map_info *vsi_list_info =
3220c60cdb13SBrett Creeley 			fm_list->vsi_list_info;
3221c60cdb13SBrett Creeley 
322280d144c9SAnirudh Venkataramanan 		/* Remove the VSI list since it is no longer used */
322380d144c9SAnirudh Venkataramanan 		status = ice_remove_vsi_list_rule(hw, vsi_list_id, lkup_type);
3224c60cdb13SBrett Creeley 		if (status) {
32259228d8b2SJacob Keller 			ice_debug(hw, ICE_DBG_SW, "Failed to remove VSI list %d, error %d\n",
3226c60cdb13SBrett Creeley 				  vsi_list_id, status);
322780d144c9SAnirudh Venkataramanan 			return status;
3228c60cdb13SBrett Creeley 		}
322980d144c9SAnirudh Venkataramanan 
323080d144c9SAnirudh Venkataramanan 		list_del(&vsi_list_info->list_entry);
323180d144c9SAnirudh Venkataramanan 		devm_kfree(ice_hw_to_dev(hw), vsi_list_info);
323280d144c9SAnirudh Venkataramanan 		fm_list->vsi_list_info = NULL;
323380d144c9SAnirudh Venkataramanan 	}
323480d144c9SAnirudh Venkataramanan 
323580d144c9SAnirudh Venkataramanan 	return status;
323680d144c9SAnirudh Venkataramanan }
323780d144c9SAnirudh Venkataramanan 
323880d144c9SAnirudh Venkataramanan /**
323980d144c9SAnirudh Venkataramanan  * ice_remove_rule_internal - Remove a filter rule of a given type
324080d144c9SAnirudh Venkataramanan  * @hw: pointer to the hardware structure
3241f9867df6SAnirudh Venkataramanan  * @recp_id: recipe ID for which the rule needs to removed
324280d144c9SAnirudh Venkataramanan  * @f_entry: rule entry containing filter information
324380d144c9SAnirudh Venkataramanan  */
32445e24d598STony Nguyen static int
324580d144c9SAnirudh Venkataramanan ice_remove_rule_internal(struct ice_hw *hw, u8 recp_id,
324680d144c9SAnirudh Venkataramanan 			 struct ice_fltr_list_entry *f_entry)
324780d144c9SAnirudh Venkataramanan {
324880d144c9SAnirudh Venkataramanan 	struct ice_switch_info *sw = hw->switch_info;
324980d144c9SAnirudh Venkataramanan 	struct ice_fltr_mgmt_list_entry *list_elem;
325080d144c9SAnirudh Venkataramanan 	struct mutex *rule_lock; /* Lock to protect filter rule list */
325180d144c9SAnirudh Venkataramanan 	bool remove_rule = false;
32525726ca0eSAnirudh Venkataramanan 	u16 vsi_handle;
32535518ac2aSTony Nguyen 	int status = 0;
32545726ca0eSAnirudh Venkataramanan 
32555726ca0eSAnirudh Venkataramanan 	if (!ice_is_vsi_valid(hw, f_entry->fltr_info.vsi_handle))
3256d54699e2STony Nguyen 		return -EINVAL;
32575726ca0eSAnirudh Venkataramanan 	f_entry->fltr_info.fwd_id.hw_vsi_id =
32585726ca0eSAnirudh Venkataramanan 		ice_get_hw_vsi_num(hw, f_entry->fltr_info.vsi_handle);
325980d144c9SAnirudh Venkataramanan 
326080d144c9SAnirudh Venkataramanan 	rule_lock = &sw->recp_list[recp_id].filt_rule_lock;
326180d144c9SAnirudh Venkataramanan 	mutex_lock(rule_lock);
326280d144c9SAnirudh Venkataramanan 	list_elem = ice_find_rule_entry(hw, recp_id, &f_entry->fltr_info);
326380d144c9SAnirudh Venkataramanan 	if (!list_elem) {
3264d54699e2STony Nguyen 		status = -ENOENT;
326580d144c9SAnirudh Venkataramanan 		goto exit;
326680d144c9SAnirudh Venkataramanan 	}
326780d144c9SAnirudh Venkataramanan 
326880d144c9SAnirudh Venkataramanan 	if (list_elem->fltr_info.fltr_act != ICE_FWD_TO_VSI_LIST) {
326980d144c9SAnirudh Venkataramanan 		remove_rule = true;
32705726ca0eSAnirudh Venkataramanan 	} else if (!list_elem->vsi_list_info) {
3271d54699e2STony Nguyen 		status = -ENOENT;
32725726ca0eSAnirudh Venkataramanan 		goto exit;
3273f9264dd6SJacob Keller 	} else if (list_elem->vsi_list_info->ref_cnt > 1) {
3274f9264dd6SJacob Keller 		/* a ref_cnt > 1 indicates that the vsi_list is being
3275f9264dd6SJacob Keller 		 * shared by multiple rules. Decrement the ref_cnt and
3276f9264dd6SJacob Keller 		 * remove this rule, but do not modify the list, as it
3277f9264dd6SJacob Keller 		 * is in-use by other rules.
3278f9264dd6SJacob Keller 		 */
32795726ca0eSAnirudh Venkataramanan 		list_elem->vsi_list_info->ref_cnt--;
3280f9264dd6SJacob Keller 		remove_rule = true;
3281f9264dd6SJacob Keller 	} else {
3282f9264dd6SJacob Keller 		/* a ref_cnt of 1 indicates the vsi_list is only used
3283f9264dd6SJacob Keller 		 * by one rule. However, the original removal request is only
3284f9264dd6SJacob Keller 		 * for a single VSI. Update the vsi_list first, and only
3285f9264dd6SJacob Keller 		 * remove the rule if there are no further VSIs in this list.
3286f9264dd6SJacob Keller 		 */
32875726ca0eSAnirudh Venkataramanan 		vsi_handle = f_entry->fltr_info.vsi_handle;
32885726ca0eSAnirudh Venkataramanan 		status = ice_rem_update_vsi_list(hw, vsi_handle, list_elem);
328980d144c9SAnirudh Venkataramanan 		if (status)
329080d144c9SAnirudh Venkataramanan 			goto exit;
3291f9867df6SAnirudh Venkataramanan 		/* if VSI count goes to zero after updating the VSI list */
329280d144c9SAnirudh Venkataramanan 		if (list_elem->vsi_count == 0)
329380d144c9SAnirudh Venkataramanan 			remove_rule = true;
329480d144c9SAnirudh Venkataramanan 	}
329580d144c9SAnirudh Venkataramanan 
329680d144c9SAnirudh Venkataramanan 	if (remove_rule) {
329780d144c9SAnirudh Venkataramanan 		/* Remove the lookup rule */
32986e1ff618SAlexander Lobakin 		struct ice_sw_rule_lkup_rx_tx *s_rule;
329980d144c9SAnirudh Venkataramanan 
330080d144c9SAnirudh Venkataramanan 		s_rule = devm_kzalloc(ice_hw_to_dev(hw),
33016e1ff618SAlexander Lobakin 				      ICE_SW_RULE_RX_TX_NO_HDR_SIZE(s_rule),
330280d144c9SAnirudh Venkataramanan 				      GFP_KERNEL);
330380d144c9SAnirudh Venkataramanan 		if (!s_rule) {
3304d54699e2STony Nguyen 			status = -ENOMEM;
330580d144c9SAnirudh Venkataramanan 			goto exit;
330680d144c9SAnirudh Venkataramanan 		}
330780d144c9SAnirudh Venkataramanan 
330880d144c9SAnirudh Venkataramanan 		ice_fill_sw_rule(hw, &list_elem->fltr_info, s_rule,
330980d144c9SAnirudh Venkataramanan 				 ice_aqc_opc_remove_sw_rules);
331080d144c9SAnirudh Venkataramanan 
331180d144c9SAnirudh Venkataramanan 		status = ice_aq_sw_rules(hw, s_rule,
33126e1ff618SAlexander Lobakin 					 ICE_SW_RULE_RX_TX_NO_HDR_SIZE(s_rule),
33136e1ff618SAlexander Lobakin 					 1, ice_aqc_opc_remove_sw_rules, NULL);
331480d144c9SAnirudh Venkataramanan 
331580d144c9SAnirudh Venkataramanan 		/* Remove a book keeping from the list */
331680d144c9SAnirudh Venkataramanan 		devm_kfree(ice_hw_to_dev(hw), s_rule);
331780d144c9SAnirudh Venkataramanan 
33188132e17dSJeb Cramer 		if (status)
33198132e17dSJeb Cramer 			goto exit;
33208132e17dSJeb Cramer 
332180d144c9SAnirudh Venkataramanan 		list_del(&list_elem->list_entry);
332280d144c9SAnirudh Venkataramanan 		devm_kfree(ice_hw_to_dev(hw), list_elem);
332380d144c9SAnirudh Venkataramanan 	}
332480d144c9SAnirudh Venkataramanan exit:
332580d144c9SAnirudh Venkataramanan 	mutex_unlock(rule_lock);
332680d144c9SAnirudh Venkataramanan 	return status;
33279daf8208SAnirudh Venkataramanan }
33289daf8208SAnirudh Venkataramanan 
33299daf8208SAnirudh Venkataramanan /**
33309fea7498SKiran Patil  * ice_mac_fltr_exist - does this MAC filter exist for given VSI
33319fea7498SKiran Patil  * @hw: pointer to the hardware structure
33329fea7498SKiran Patil  * @mac: MAC address to be checked (for MAC filter)
33339fea7498SKiran Patil  * @vsi_handle: check MAC filter for this VSI
33349fea7498SKiran Patil  */
33359fea7498SKiran Patil bool ice_mac_fltr_exist(struct ice_hw *hw, u8 *mac, u16 vsi_handle)
33369fea7498SKiran Patil {
33379fea7498SKiran Patil 	struct ice_fltr_mgmt_list_entry *entry;
33389fea7498SKiran Patil 	struct list_head *rule_head;
33399fea7498SKiran Patil 	struct ice_switch_info *sw;
33409fea7498SKiran Patil 	struct mutex *rule_lock; /* Lock to protect filter rule list */
33419fea7498SKiran Patil 	u16 hw_vsi_id;
33429fea7498SKiran Patil 
33439fea7498SKiran Patil 	if (!ice_is_vsi_valid(hw, vsi_handle))
33449fea7498SKiran Patil 		return false;
33459fea7498SKiran Patil 
33469fea7498SKiran Patil 	hw_vsi_id = ice_get_hw_vsi_num(hw, vsi_handle);
33479fea7498SKiran Patil 	sw = hw->switch_info;
33489fea7498SKiran Patil 	rule_head = &sw->recp_list[ICE_SW_LKUP_MAC].filt_rules;
33499fea7498SKiran Patil 	if (!rule_head)
33509fea7498SKiran Patil 		return false;
33519fea7498SKiran Patil 
33529fea7498SKiran Patil 	rule_lock = &sw->recp_list[ICE_SW_LKUP_MAC].filt_rule_lock;
33539fea7498SKiran Patil 	mutex_lock(rule_lock);
33549fea7498SKiran Patil 	list_for_each_entry(entry, rule_head, list_entry) {
33559fea7498SKiran Patil 		struct ice_fltr_info *f_info = &entry->fltr_info;
33569fea7498SKiran Patil 		u8 *mac_addr = &f_info->l_data.mac.mac_addr[0];
33579fea7498SKiran Patil 
33589fea7498SKiran Patil 		if (is_zero_ether_addr(mac_addr))
33599fea7498SKiran Patil 			continue;
33609fea7498SKiran Patil 
33619fea7498SKiran Patil 		if (f_info->flag != ICE_FLTR_TX ||
33629fea7498SKiran Patil 		    f_info->src_id != ICE_SRC_ID_VSI ||
33639fea7498SKiran Patil 		    f_info->lkup_type != ICE_SW_LKUP_MAC ||
33649fea7498SKiran Patil 		    f_info->fltr_act != ICE_FWD_TO_VSI ||
33659fea7498SKiran Patil 		    hw_vsi_id != f_info->fwd_id.hw_vsi_id)
33669fea7498SKiran Patil 			continue;
33679fea7498SKiran Patil 
33689fea7498SKiran Patil 		if (ether_addr_equal(mac, mac_addr)) {
33699fea7498SKiran Patil 			mutex_unlock(rule_lock);
33709fea7498SKiran Patil 			return true;
33719fea7498SKiran Patil 		}
33729fea7498SKiran Patil 	}
33739fea7498SKiran Patil 	mutex_unlock(rule_lock);
33749fea7498SKiran Patil 	return false;
33759fea7498SKiran Patil }
33769fea7498SKiran Patil 
33779fea7498SKiran Patil /**
33789fea7498SKiran Patil  * ice_vlan_fltr_exist - does this VLAN filter exist for given VSI
33799fea7498SKiran Patil  * @hw: pointer to the hardware structure
33809fea7498SKiran Patil  * @vlan_id: VLAN ID
33819fea7498SKiran Patil  * @vsi_handle: check MAC filter for this VSI
33829fea7498SKiran Patil  */
33839fea7498SKiran Patil bool ice_vlan_fltr_exist(struct ice_hw *hw, u16 vlan_id, u16 vsi_handle)
33849fea7498SKiran Patil {
33859fea7498SKiran Patil 	struct ice_fltr_mgmt_list_entry *entry;
33869fea7498SKiran Patil 	struct list_head *rule_head;
33879fea7498SKiran Patil 	struct ice_switch_info *sw;
33889fea7498SKiran Patil 	struct mutex *rule_lock; /* Lock to protect filter rule list */
33899fea7498SKiran Patil 	u16 hw_vsi_id;
33909fea7498SKiran Patil 
33919fea7498SKiran Patil 	if (vlan_id > ICE_MAX_VLAN_ID)
33929fea7498SKiran Patil 		return false;
33939fea7498SKiran Patil 
33949fea7498SKiran Patil 	if (!ice_is_vsi_valid(hw, vsi_handle))
33959fea7498SKiran Patil 		return false;
33969fea7498SKiran Patil 
33979fea7498SKiran Patil 	hw_vsi_id = ice_get_hw_vsi_num(hw, vsi_handle);
33989fea7498SKiran Patil 	sw = hw->switch_info;
33999fea7498SKiran Patil 	rule_head = &sw->recp_list[ICE_SW_LKUP_VLAN].filt_rules;
34009fea7498SKiran Patil 	if (!rule_head)
34019fea7498SKiran Patil 		return false;
34029fea7498SKiran Patil 
34039fea7498SKiran Patil 	rule_lock = &sw->recp_list[ICE_SW_LKUP_VLAN].filt_rule_lock;
34049fea7498SKiran Patil 	mutex_lock(rule_lock);
34059fea7498SKiran Patil 	list_for_each_entry(entry, rule_head, list_entry) {
34069fea7498SKiran Patil 		struct ice_fltr_info *f_info = &entry->fltr_info;
34079fea7498SKiran Patil 		u16 entry_vlan_id = f_info->l_data.vlan.vlan_id;
34089fea7498SKiran Patil 		struct ice_vsi_list_map_info *map_info;
34099fea7498SKiran Patil 
34109fea7498SKiran Patil 		if (entry_vlan_id > ICE_MAX_VLAN_ID)
34119fea7498SKiran Patil 			continue;
34129fea7498SKiran Patil 
34139fea7498SKiran Patil 		if (f_info->flag != ICE_FLTR_TX ||
34149fea7498SKiran Patil 		    f_info->src_id != ICE_SRC_ID_VSI ||
34159fea7498SKiran Patil 		    f_info->lkup_type != ICE_SW_LKUP_VLAN)
34169fea7498SKiran Patil 			continue;
34179fea7498SKiran Patil 
34189fea7498SKiran Patil 		/* Only allowed filter action are FWD_TO_VSI/_VSI_LIST */
34199fea7498SKiran Patil 		if (f_info->fltr_act != ICE_FWD_TO_VSI &&
34209fea7498SKiran Patil 		    f_info->fltr_act != ICE_FWD_TO_VSI_LIST)
34219fea7498SKiran Patil 			continue;
34229fea7498SKiran Patil 
34239fea7498SKiran Patil 		if (f_info->fltr_act == ICE_FWD_TO_VSI) {
34249fea7498SKiran Patil 			if (hw_vsi_id != f_info->fwd_id.hw_vsi_id)
34259fea7498SKiran Patil 				continue;
34269fea7498SKiran Patil 		} else if (f_info->fltr_act == ICE_FWD_TO_VSI_LIST) {
34279fea7498SKiran Patil 			/* If filter_action is FWD_TO_VSI_LIST, make sure
34289fea7498SKiran Patil 			 * that VSI being checked is part of VSI list
34299fea7498SKiran Patil 			 */
34309fea7498SKiran Patil 			if (entry->vsi_count == 1 &&
34319fea7498SKiran Patil 			    entry->vsi_list_info) {
34329fea7498SKiran Patil 				map_info = entry->vsi_list_info;
34339fea7498SKiran Patil 				if (!test_bit(vsi_handle, map_info->vsi_map))
34349fea7498SKiran Patil 					continue;
34359fea7498SKiran Patil 			}
34369fea7498SKiran Patil 		}
34379fea7498SKiran Patil 
34389fea7498SKiran Patil 		if (vlan_id == entry_vlan_id) {
34399fea7498SKiran Patil 			mutex_unlock(rule_lock);
34409fea7498SKiran Patil 			return true;
34419fea7498SKiran Patil 		}
34429fea7498SKiran Patil 	}
34439fea7498SKiran Patil 	mutex_unlock(rule_lock);
34449fea7498SKiran Patil 
34459fea7498SKiran Patil 	return false;
34469fea7498SKiran Patil }
34479fea7498SKiran Patil 
34489fea7498SKiran Patil /**
34499daf8208SAnirudh Venkataramanan  * ice_add_mac - Add a MAC address based filter rule
34509daf8208SAnirudh Venkataramanan  * @hw: pointer to the hardware structure
34519daf8208SAnirudh Venkataramanan  * @m_list: list of MAC addresses and forwarding information
34529daf8208SAnirudh Venkataramanan  *
34539daf8208SAnirudh Venkataramanan  * IMPORTANT: When the ucast_shared flag is set to false and m_list has
34549daf8208SAnirudh Venkataramanan  * multiple unicast addresses, the function assumes that all the
34559daf8208SAnirudh Venkataramanan  * addresses are unique in a given add_mac call. It doesn't
34569daf8208SAnirudh Venkataramanan  * check for duplicates in this case, removing duplicates from a given
34579daf8208SAnirudh Venkataramanan  * list should be taken care of in the caller of this function.
34589daf8208SAnirudh Venkataramanan  */
34595e24d598STony Nguyen int ice_add_mac(struct ice_hw *hw, struct list_head *m_list)
34609daf8208SAnirudh Venkataramanan {
34616e1ff618SAlexander Lobakin 	struct ice_sw_rule_lkup_rx_tx *s_rule, *r_iter;
34629daf8208SAnirudh Venkataramanan 	struct ice_fltr_list_entry *m_list_itr;
346380d144c9SAnirudh Venkataramanan 	struct list_head *rule_head;
346488865fc4SKarol Kolacinski 	u16 total_elem_left, s_rule_size;
346580d144c9SAnirudh Venkataramanan 	struct ice_switch_info *sw;
346680d144c9SAnirudh Venkataramanan 	struct mutex *rule_lock; /* Lock to protect filter rule list */
34679daf8208SAnirudh Venkataramanan 	u16 num_unicast = 0;
34685518ac2aSTony Nguyen 	int status = 0;
346988865fc4SKarol Kolacinski 	u8 elem_sent;
34709daf8208SAnirudh Venkataramanan 
34719daf8208SAnirudh Venkataramanan 	if (!m_list || !hw)
3472d54699e2STony Nguyen 		return -EINVAL;
34739daf8208SAnirudh Venkataramanan 
347480d144c9SAnirudh Venkataramanan 	s_rule = NULL;
347580d144c9SAnirudh Venkataramanan 	sw = hw->switch_info;
347680d144c9SAnirudh Venkataramanan 	rule_lock = &sw->recp_list[ICE_SW_LKUP_MAC].filt_rule_lock;
34779daf8208SAnirudh Venkataramanan 	list_for_each_entry(m_list_itr, m_list, list_entry) {
34789daf8208SAnirudh Venkataramanan 		u8 *add = &m_list_itr->fltr_info.l_data.mac.mac_addr[0];
34795726ca0eSAnirudh Venkataramanan 		u16 vsi_handle;
34805726ca0eSAnirudh Venkataramanan 		u16 hw_vsi_id;
34819daf8208SAnirudh Venkataramanan 
348280d144c9SAnirudh Venkataramanan 		m_list_itr->fltr_info.flag = ICE_FLTR_TX;
34835726ca0eSAnirudh Venkataramanan 		vsi_handle = m_list_itr->fltr_info.vsi_handle;
34845726ca0eSAnirudh Venkataramanan 		if (!ice_is_vsi_valid(hw, vsi_handle))
3485d54699e2STony Nguyen 			return -EINVAL;
34865726ca0eSAnirudh Venkataramanan 		hw_vsi_id = ice_get_hw_vsi_num(hw, vsi_handle);
34875726ca0eSAnirudh Venkataramanan 		m_list_itr->fltr_info.fwd_id.hw_vsi_id = hw_vsi_id;
3488f9867df6SAnirudh Venkataramanan 		/* update the src in case it is VSI num */
34895726ca0eSAnirudh Venkataramanan 		if (m_list_itr->fltr_info.src_id != ICE_SRC_ID_VSI)
3490d54699e2STony Nguyen 			return -EINVAL;
34915726ca0eSAnirudh Venkataramanan 		m_list_itr->fltr_info.src = hw_vsi_id;
349280d144c9SAnirudh Venkataramanan 		if (m_list_itr->fltr_info.lkup_type != ICE_SW_LKUP_MAC ||
349380d144c9SAnirudh Venkataramanan 		    is_zero_ether_addr(add))
3494d54699e2STony Nguyen 			return -EINVAL;
34959daf8208SAnirudh Venkataramanan 		if (is_unicast_ether_addr(add) && !hw->ucast_shared) {
34969daf8208SAnirudh Venkataramanan 			/* Don't overwrite the unicast address */
349780d144c9SAnirudh Venkataramanan 			mutex_lock(rule_lock);
349880d144c9SAnirudh Venkataramanan 			if (ice_find_rule_entry(hw, ICE_SW_LKUP_MAC,
349980d144c9SAnirudh Venkataramanan 						&m_list_itr->fltr_info)) {
350080d144c9SAnirudh Venkataramanan 				mutex_unlock(rule_lock);
3501d54699e2STony Nguyen 				return -EEXIST;
350280d144c9SAnirudh Venkataramanan 			}
350380d144c9SAnirudh Venkataramanan 			mutex_unlock(rule_lock);
35049daf8208SAnirudh Venkataramanan 			num_unicast++;
35059daf8208SAnirudh Venkataramanan 		} else if (is_multicast_ether_addr(add) ||
35069daf8208SAnirudh Venkataramanan 			   (is_unicast_ether_addr(add) && hw->ucast_shared)) {
350780d144c9SAnirudh Venkataramanan 			m_list_itr->status =
350880d144c9SAnirudh Venkataramanan 				ice_add_rule_internal(hw, ICE_SW_LKUP_MAC,
350980d144c9SAnirudh Venkataramanan 						      m_list_itr);
351080d144c9SAnirudh Venkataramanan 			if (m_list_itr->status)
351180d144c9SAnirudh Venkataramanan 				return m_list_itr->status;
35129daf8208SAnirudh Venkataramanan 		}
35139daf8208SAnirudh Venkataramanan 	}
35149daf8208SAnirudh Venkataramanan 
351580d144c9SAnirudh Venkataramanan 	mutex_lock(rule_lock);
35169daf8208SAnirudh Venkataramanan 	/* Exit if no suitable entries were found for adding bulk switch rule */
351780d144c9SAnirudh Venkataramanan 	if (!num_unicast) {
351880d144c9SAnirudh Venkataramanan 		status = 0;
351980d144c9SAnirudh Venkataramanan 		goto ice_add_mac_exit;
352080d144c9SAnirudh Venkataramanan 	}
352180d144c9SAnirudh Venkataramanan 
352280d144c9SAnirudh Venkataramanan 	rule_head = &sw->recp_list[ICE_SW_LKUP_MAC].filt_rules;
35239daf8208SAnirudh Venkataramanan 
35249daf8208SAnirudh Venkataramanan 	/* Allocate switch rule buffer for the bulk update for unicast */
35256e1ff618SAlexander Lobakin 	s_rule_size = ICE_SW_RULE_RX_TX_ETH_HDR_SIZE(s_rule);
35269daf8208SAnirudh Venkataramanan 	s_rule = devm_kcalloc(ice_hw_to_dev(hw), num_unicast, s_rule_size,
35279daf8208SAnirudh Venkataramanan 			      GFP_KERNEL);
352880d144c9SAnirudh Venkataramanan 	if (!s_rule) {
3529d54699e2STony Nguyen 		status = -ENOMEM;
353080d144c9SAnirudh Venkataramanan 		goto ice_add_mac_exit;
353180d144c9SAnirudh Venkataramanan 	}
35329daf8208SAnirudh Venkataramanan 
35339daf8208SAnirudh Venkataramanan 	r_iter = s_rule;
35349daf8208SAnirudh Venkataramanan 	list_for_each_entry(m_list_itr, m_list, list_entry) {
35359daf8208SAnirudh Venkataramanan 		struct ice_fltr_info *f_info = &m_list_itr->fltr_info;
353680d144c9SAnirudh Venkataramanan 		u8 *mac_addr = &f_info->l_data.mac.mac_addr[0];
35379daf8208SAnirudh Venkataramanan 
353880d144c9SAnirudh Venkataramanan 		if (is_unicast_ether_addr(mac_addr)) {
353980d144c9SAnirudh Venkataramanan 			ice_fill_sw_rule(hw, &m_list_itr->fltr_info, r_iter,
354080d144c9SAnirudh Venkataramanan 					 ice_aqc_opc_add_sw_rules);
35416e1ff618SAlexander Lobakin 			r_iter = (typeof(s_rule))((u8 *)r_iter + s_rule_size);
35429daf8208SAnirudh Venkataramanan 		}
35439daf8208SAnirudh Venkataramanan 	}
35449daf8208SAnirudh Venkataramanan 
35459daf8208SAnirudh Venkataramanan 	/* Call AQ bulk switch rule update for all unicast addresses */
35469daf8208SAnirudh Venkataramanan 	r_iter = s_rule;
35479daf8208SAnirudh Venkataramanan 	/* Call AQ switch rule in AQ_MAX chunk */
35489daf8208SAnirudh Venkataramanan 	for (total_elem_left = num_unicast; total_elem_left > 0;
35499daf8208SAnirudh Venkataramanan 	     total_elem_left -= elem_sent) {
35506e1ff618SAlexander Lobakin 		struct ice_sw_rule_lkup_rx_tx *entry = r_iter;
35519daf8208SAnirudh Venkataramanan 
355288865fc4SKarol Kolacinski 		elem_sent = min_t(u8, total_elem_left,
355388865fc4SKarol Kolacinski 				  (ICE_AQ_MAX_BUF_LEN / s_rule_size));
35549daf8208SAnirudh Venkataramanan 		status = ice_aq_sw_rules(hw, entry, elem_sent * s_rule_size,
35559daf8208SAnirudh Venkataramanan 					 elem_sent, ice_aqc_opc_add_sw_rules,
35569daf8208SAnirudh Venkataramanan 					 NULL);
35579daf8208SAnirudh Venkataramanan 		if (status)
35589daf8208SAnirudh Venkataramanan 			goto ice_add_mac_exit;
35596e1ff618SAlexander Lobakin 		r_iter = (typeof(s_rule))
35609daf8208SAnirudh Venkataramanan 			((u8 *)r_iter + (elem_sent * s_rule_size));
35619daf8208SAnirudh Venkataramanan 	}
35629daf8208SAnirudh Venkataramanan 
3563f9867df6SAnirudh Venkataramanan 	/* Fill up rule ID based on the value returned from FW */
35649daf8208SAnirudh Venkataramanan 	r_iter = s_rule;
35659daf8208SAnirudh Venkataramanan 	list_for_each_entry(m_list_itr, m_list, list_entry) {
35669daf8208SAnirudh Venkataramanan 		struct ice_fltr_info *f_info = &m_list_itr->fltr_info;
356780d144c9SAnirudh Venkataramanan 		u8 *mac_addr = &f_info->l_data.mac.mac_addr[0];
35689daf8208SAnirudh Venkataramanan 		struct ice_fltr_mgmt_list_entry *fm_entry;
35699daf8208SAnirudh Venkataramanan 
357080d144c9SAnirudh Venkataramanan 		if (is_unicast_ether_addr(mac_addr)) {
35716e1ff618SAlexander Lobakin 			f_info->fltr_rule_id = le16_to_cpu(r_iter->index);
35729daf8208SAnirudh Venkataramanan 			f_info->fltr_act = ICE_FWD_TO_VSI;
35739daf8208SAnirudh Venkataramanan 			/* Create an entry to track this MAC address */
35749daf8208SAnirudh Venkataramanan 			fm_entry = devm_kzalloc(ice_hw_to_dev(hw),
35759daf8208SAnirudh Venkataramanan 						sizeof(*fm_entry), GFP_KERNEL);
35769daf8208SAnirudh Venkataramanan 			if (!fm_entry) {
3577d54699e2STony Nguyen 				status = -ENOMEM;
35789daf8208SAnirudh Venkataramanan 				goto ice_add_mac_exit;
35799daf8208SAnirudh Venkataramanan 			}
35809daf8208SAnirudh Venkataramanan 			fm_entry->fltr_info = *f_info;
35819daf8208SAnirudh Venkataramanan 			fm_entry->vsi_count = 1;
35829daf8208SAnirudh Venkataramanan 			/* The book keeping entries will get removed when
35839daf8208SAnirudh Venkataramanan 			 * base driver calls remove filter AQ command
35849daf8208SAnirudh Venkataramanan 			 */
35859daf8208SAnirudh Venkataramanan 
358680d144c9SAnirudh Venkataramanan 			list_add(&fm_entry->list_entry, rule_head);
35876e1ff618SAlexander Lobakin 			r_iter = (typeof(s_rule))((u8 *)r_iter + s_rule_size);
35889daf8208SAnirudh Venkataramanan 		}
35899daf8208SAnirudh Venkataramanan 	}
35909daf8208SAnirudh Venkataramanan 
35919daf8208SAnirudh Venkataramanan ice_add_mac_exit:
359280d144c9SAnirudh Venkataramanan 	mutex_unlock(rule_lock);
359380d144c9SAnirudh Venkataramanan 	if (s_rule)
35949daf8208SAnirudh Venkataramanan 		devm_kfree(ice_hw_to_dev(hw), s_rule);
35959daf8208SAnirudh Venkataramanan 	return status;
35969daf8208SAnirudh Venkataramanan }
35979daf8208SAnirudh Venkataramanan 
35989daf8208SAnirudh Venkataramanan /**
3599d76a60baSAnirudh Venkataramanan  * ice_add_vlan_internal - Add one VLAN based filter rule
3600d76a60baSAnirudh Venkataramanan  * @hw: pointer to the hardware structure
3601d76a60baSAnirudh Venkataramanan  * @f_entry: filter entry containing one VLAN information
3602d76a60baSAnirudh Venkataramanan  */
36035e24d598STony Nguyen static int
3604d76a60baSAnirudh Venkataramanan ice_add_vlan_internal(struct ice_hw *hw, struct ice_fltr_list_entry *f_entry)
3605d76a60baSAnirudh Venkataramanan {
360680d144c9SAnirudh Venkataramanan 	struct ice_switch_info *sw = hw->switch_info;
3607d76a60baSAnirudh Venkataramanan 	struct ice_fltr_mgmt_list_entry *v_list_itr;
36085726ca0eSAnirudh Venkataramanan 	struct ice_fltr_info *new_fltr, *cur_fltr;
36095726ca0eSAnirudh Venkataramanan 	enum ice_sw_lkup_type lkup_type;
36105726ca0eSAnirudh Venkataramanan 	u16 vsi_list_id = 0, vsi_handle;
361180d144c9SAnirudh Venkataramanan 	struct mutex *rule_lock; /* Lock to protect filter rule list */
36125e24d598STony Nguyen 	int status = 0;
3613d76a60baSAnirudh Venkataramanan 
36145726ca0eSAnirudh Venkataramanan 	if (!ice_is_vsi_valid(hw, f_entry->fltr_info.vsi_handle))
3615d54699e2STony Nguyen 		return -EINVAL;
36165726ca0eSAnirudh Venkataramanan 
36175726ca0eSAnirudh Venkataramanan 	f_entry->fltr_info.fwd_id.hw_vsi_id =
36185726ca0eSAnirudh Venkataramanan 		ice_get_hw_vsi_num(hw, f_entry->fltr_info.vsi_handle);
3619d76a60baSAnirudh Venkataramanan 	new_fltr = &f_entry->fltr_info;
36205726ca0eSAnirudh Venkataramanan 
3621f9867df6SAnirudh Venkataramanan 	/* VLAN ID should only be 12 bits */
3622d76a60baSAnirudh Venkataramanan 	if (new_fltr->l_data.vlan.vlan_id > ICE_MAX_VLAN_ID)
3623d54699e2STony Nguyen 		return -EINVAL;
3624d76a60baSAnirudh Venkataramanan 
36255726ca0eSAnirudh Venkataramanan 	if (new_fltr->src_id != ICE_SRC_ID_VSI)
3626d54699e2STony Nguyen 		return -EINVAL;
36275726ca0eSAnirudh Venkataramanan 
36285726ca0eSAnirudh Venkataramanan 	new_fltr->src = new_fltr->fwd_id.hw_vsi_id;
36295726ca0eSAnirudh Venkataramanan 	lkup_type = new_fltr->lkup_type;
36305726ca0eSAnirudh Venkataramanan 	vsi_handle = new_fltr->vsi_handle;
363180d144c9SAnirudh Venkataramanan 	rule_lock = &sw->recp_list[ICE_SW_LKUP_VLAN].filt_rule_lock;
363280d144c9SAnirudh Venkataramanan 	mutex_lock(rule_lock);
363380d144c9SAnirudh Venkataramanan 	v_list_itr = ice_find_rule_entry(hw, ICE_SW_LKUP_VLAN, new_fltr);
3634d76a60baSAnirudh Venkataramanan 	if (!v_list_itr) {
36355726ca0eSAnirudh Venkataramanan 		struct ice_vsi_list_map_info *map_info = NULL;
3636d76a60baSAnirudh Venkataramanan 
3637d76a60baSAnirudh Venkataramanan 		if (new_fltr->fltr_act == ICE_FWD_TO_VSI) {
36385726ca0eSAnirudh Venkataramanan 			/* All VLAN pruning rules use a VSI list. Check if
36395726ca0eSAnirudh Venkataramanan 			 * there is already a VSI list containing VSI that we
36405726ca0eSAnirudh Venkataramanan 			 * want to add. If found, use the same vsi_list_id for
36415726ca0eSAnirudh Venkataramanan 			 * this new VLAN rule or else create a new list.
3642d76a60baSAnirudh Venkataramanan 			 */
36435726ca0eSAnirudh Venkataramanan 			map_info = ice_find_vsi_list_entry(hw, ICE_SW_LKUP_VLAN,
36445726ca0eSAnirudh Venkataramanan 							   vsi_handle,
36455726ca0eSAnirudh Venkataramanan 							   &vsi_list_id);
36465726ca0eSAnirudh Venkataramanan 			if (!map_info) {
36475726ca0eSAnirudh Venkataramanan 				status = ice_create_vsi_list_rule(hw,
36485726ca0eSAnirudh Venkataramanan 								  &vsi_handle,
36495726ca0eSAnirudh Venkataramanan 								  1,
3650d76a60baSAnirudh Venkataramanan 								  &vsi_list_id,
3651d76a60baSAnirudh Venkataramanan 								  lkup_type);
3652d76a60baSAnirudh Venkataramanan 				if (status)
365380d144c9SAnirudh Venkataramanan 					goto exit;
36545726ca0eSAnirudh Venkataramanan 			}
36555726ca0eSAnirudh Venkataramanan 			/* Convert the action to forwarding to a VSI list. */
3656d76a60baSAnirudh Venkataramanan 			new_fltr->fltr_act = ICE_FWD_TO_VSI_LIST;
3657d76a60baSAnirudh Venkataramanan 			new_fltr->fwd_id.vsi_list_id = vsi_list_id;
3658d76a60baSAnirudh Venkataramanan 		}
3659d76a60baSAnirudh Venkataramanan 
3660d76a60baSAnirudh Venkataramanan 		status = ice_create_pkt_fwd_rule(hw, f_entry);
36615726ca0eSAnirudh Venkataramanan 		if (!status) {
366280d144c9SAnirudh Venkataramanan 			v_list_itr = ice_find_rule_entry(hw, ICE_SW_LKUP_VLAN,
366380d144c9SAnirudh Venkataramanan 							 new_fltr);
366480d144c9SAnirudh Venkataramanan 			if (!v_list_itr) {
3665d54699e2STony Nguyen 				status = -ENOENT;
366680d144c9SAnirudh Venkataramanan 				goto exit;
366780d144c9SAnirudh Venkataramanan 			}
36685726ca0eSAnirudh Venkataramanan 			/* reuse VSI list for new rule and increment ref_cnt */
36695726ca0eSAnirudh Venkataramanan 			if (map_info) {
36705726ca0eSAnirudh Venkataramanan 				v_list_itr->vsi_list_info = map_info;
36715726ca0eSAnirudh Venkataramanan 				map_info->ref_cnt++;
36725726ca0eSAnirudh Venkataramanan 			} else {
3673d76a60baSAnirudh Venkataramanan 				v_list_itr->vsi_list_info =
36745726ca0eSAnirudh Venkataramanan 					ice_create_vsi_list_map(hw, &vsi_handle,
36755726ca0eSAnirudh Venkataramanan 								1, vsi_list_id);
3676d76a60baSAnirudh Venkataramanan 			}
36775726ca0eSAnirudh Venkataramanan 		}
36785726ca0eSAnirudh Venkataramanan 	} else if (v_list_itr->vsi_list_info->ref_cnt == 1) {
3679f9867df6SAnirudh Venkataramanan 		/* Update existing VSI list to add new VSI ID only if it used
36805726ca0eSAnirudh Venkataramanan 		 * by one VLAN rule.
36815726ca0eSAnirudh Venkataramanan 		 */
36825726ca0eSAnirudh Venkataramanan 		cur_fltr = &v_list_itr->fltr_info;
36835726ca0eSAnirudh Venkataramanan 		status = ice_add_update_vsi_list(hw, v_list_itr, cur_fltr,
36845726ca0eSAnirudh Venkataramanan 						 new_fltr);
36855726ca0eSAnirudh Venkataramanan 	} else {
36865726ca0eSAnirudh Venkataramanan 		/* If VLAN rule exists and VSI list being used by this rule is
36875726ca0eSAnirudh Venkataramanan 		 * referenced by more than 1 VLAN rule. Then create a new VSI
36885726ca0eSAnirudh Venkataramanan 		 * list appending previous VSI with new VSI and update existing
3689f9867df6SAnirudh Venkataramanan 		 * VLAN rule to point to new VSI list ID
36905726ca0eSAnirudh Venkataramanan 		 */
36915726ca0eSAnirudh Venkataramanan 		struct ice_fltr_info tmp_fltr;
36925726ca0eSAnirudh Venkataramanan 		u16 vsi_handle_arr[2];
36935726ca0eSAnirudh Venkataramanan 		u16 cur_handle;
3694d76a60baSAnirudh Venkataramanan 
36955726ca0eSAnirudh Venkataramanan 		/* Current implementation only supports reusing VSI list with
36965726ca0eSAnirudh Venkataramanan 		 * one VSI count. We should never hit below condition
36975726ca0eSAnirudh Venkataramanan 		 */
36985726ca0eSAnirudh Venkataramanan 		if (v_list_itr->vsi_count > 1 &&
36995726ca0eSAnirudh Venkataramanan 		    v_list_itr->vsi_list_info->ref_cnt > 1) {
37009228d8b2SJacob Keller 			ice_debug(hw, ICE_DBG_SW, "Invalid configuration: Optimization to reuse VSI list with more than one VSI is not being done yet\n");
3701d54699e2STony Nguyen 			status = -EIO;
370280d144c9SAnirudh Venkataramanan 			goto exit;
3703d76a60baSAnirudh Venkataramanan 		}
3704d76a60baSAnirudh Venkataramanan 
37055726ca0eSAnirudh Venkataramanan 		cur_handle =
37065726ca0eSAnirudh Venkataramanan 			find_first_bit(v_list_itr->vsi_list_info->vsi_map,
37075726ca0eSAnirudh Venkataramanan 				       ICE_MAX_VSI);
37085726ca0eSAnirudh Venkataramanan 
37095726ca0eSAnirudh Venkataramanan 		/* A rule already exists with the new VSI being added */
37105726ca0eSAnirudh Venkataramanan 		if (cur_handle == vsi_handle) {
3711d54699e2STony Nguyen 			status = -EEXIST;
37125726ca0eSAnirudh Venkataramanan 			goto exit;
37135726ca0eSAnirudh Venkataramanan 		}
37145726ca0eSAnirudh Venkataramanan 
37155726ca0eSAnirudh Venkataramanan 		vsi_handle_arr[0] = cur_handle;
37165726ca0eSAnirudh Venkataramanan 		vsi_handle_arr[1] = vsi_handle;
37175726ca0eSAnirudh Venkataramanan 		status = ice_create_vsi_list_rule(hw, &vsi_handle_arr[0], 2,
37185726ca0eSAnirudh Venkataramanan 						  &vsi_list_id, lkup_type);
37195726ca0eSAnirudh Venkataramanan 		if (status)
37205726ca0eSAnirudh Venkataramanan 			goto exit;
37215726ca0eSAnirudh Venkataramanan 
37225726ca0eSAnirudh Venkataramanan 		tmp_fltr = v_list_itr->fltr_info;
37235726ca0eSAnirudh Venkataramanan 		tmp_fltr.fltr_rule_id = v_list_itr->fltr_info.fltr_rule_id;
37245726ca0eSAnirudh Venkataramanan 		tmp_fltr.fwd_id.vsi_list_id = vsi_list_id;
37255726ca0eSAnirudh Venkataramanan 		tmp_fltr.fltr_act = ICE_FWD_TO_VSI_LIST;
37265726ca0eSAnirudh Venkataramanan 		/* Update the previous switch rule to a new VSI list which
3727df17b7e0SAnirudh Venkataramanan 		 * includes current VSI that is requested
37285726ca0eSAnirudh Venkataramanan 		 */
37295726ca0eSAnirudh Venkataramanan 		status = ice_update_pkt_fwd_rule(hw, &tmp_fltr);
37305726ca0eSAnirudh Venkataramanan 		if (status)
37315726ca0eSAnirudh Venkataramanan 			goto exit;
37325726ca0eSAnirudh Venkataramanan 
37335726ca0eSAnirudh Venkataramanan 		/* before overriding VSI list map info. decrement ref_cnt of
37345726ca0eSAnirudh Venkataramanan 		 * previous VSI list
37355726ca0eSAnirudh Venkataramanan 		 */
37365726ca0eSAnirudh Venkataramanan 		v_list_itr->vsi_list_info->ref_cnt--;
37375726ca0eSAnirudh Venkataramanan 
37385726ca0eSAnirudh Venkataramanan 		/* now update to newly created list */
37395726ca0eSAnirudh Venkataramanan 		v_list_itr->fltr_info.fwd_id.vsi_list_id = vsi_list_id;
37405726ca0eSAnirudh Venkataramanan 		v_list_itr->vsi_list_info =
37415726ca0eSAnirudh Venkataramanan 			ice_create_vsi_list_map(hw, &vsi_handle_arr[0], 2,
37425726ca0eSAnirudh Venkataramanan 						vsi_list_id);
37435726ca0eSAnirudh Venkataramanan 		v_list_itr->vsi_count++;
37445726ca0eSAnirudh Venkataramanan 	}
374580d144c9SAnirudh Venkataramanan 
374680d144c9SAnirudh Venkataramanan exit:
374780d144c9SAnirudh Venkataramanan 	mutex_unlock(rule_lock);
374880d144c9SAnirudh Venkataramanan 	return status;
3749d76a60baSAnirudh Venkataramanan }
3750d76a60baSAnirudh Venkataramanan 
3751d76a60baSAnirudh Venkataramanan /**
3752d76a60baSAnirudh Venkataramanan  * ice_add_vlan - Add VLAN based filter rule
3753d76a60baSAnirudh Venkataramanan  * @hw: pointer to the hardware structure
3754d76a60baSAnirudh Venkataramanan  * @v_list: list of VLAN entries and forwarding information
3755d76a60baSAnirudh Venkataramanan  */
37565e24d598STony Nguyen int ice_add_vlan(struct ice_hw *hw, struct list_head *v_list)
3757d76a60baSAnirudh Venkataramanan {
3758d76a60baSAnirudh Venkataramanan 	struct ice_fltr_list_entry *v_list_itr;
3759d76a60baSAnirudh Venkataramanan 
3760d76a60baSAnirudh Venkataramanan 	if (!v_list || !hw)
3761d54699e2STony Nguyen 		return -EINVAL;
3762d76a60baSAnirudh Venkataramanan 
3763d76a60baSAnirudh Venkataramanan 	list_for_each_entry(v_list_itr, v_list, list_entry) {
3764d76a60baSAnirudh Venkataramanan 		if (v_list_itr->fltr_info.lkup_type != ICE_SW_LKUP_VLAN)
3765d54699e2STony Nguyen 			return -EINVAL;
376680d144c9SAnirudh Venkataramanan 		v_list_itr->fltr_info.flag = ICE_FLTR_TX;
376780d144c9SAnirudh Venkataramanan 		v_list_itr->status = ice_add_vlan_internal(hw, v_list_itr);
376880d144c9SAnirudh Venkataramanan 		if (v_list_itr->status)
376980d144c9SAnirudh Venkataramanan 			return v_list_itr->status;
3770d76a60baSAnirudh Venkataramanan 	}
3771d76a60baSAnirudh Venkataramanan 	return 0;
3772d76a60baSAnirudh Venkataramanan }
3773d76a60baSAnirudh Venkataramanan 
3774d76a60baSAnirudh Venkataramanan /**
3775d95276ceSAkeem G Abodunrin  * ice_add_eth_mac - Add ethertype and MAC based filter rule
3776d95276ceSAkeem G Abodunrin  * @hw: pointer to the hardware structure
3777d95276ceSAkeem G Abodunrin  * @em_list: list of ether type MAC filter, MAC is optional
37782e0e6228SDave Ertman  *
37792e0e6228SDave Ertman  * This function requires the caller to populate the entries in
37802e0e6228SDave Ertman  * the filter list with the necessary fields (including flags to
37812e0e6228SDave Ertman  * indicate Tx or Rx rules).
3782d95276ceSAkeem G Abodunrin  */
37835518ac2aSTony Nguyen int ice_add_eth_mac(struct ice_hw *hw, struct list_head *em_list)
3784d95276ceSAkeem G Abodunrin {
3785d95276ceSAkeem G Abodunrin 	struct ice_fltr_list_entry *em_list_itr;
3786d95276ceSAkeem G Abodunrin 
3787d95276ceSAkeem G Abodunrin 	if (!em_list || !hw)
3788d54699e2STony Nguyen 		return -EINVAL;
3789d95276ceSAkeem G Abodunrin 
3790d95276ceSAkeem G Abodunrin 	list_for_each_entry(em_list_itr, em_list, list_entry) {
3791d95276ceSAkeem G Abodunrin 		enum ice_sw_lkup_type l_type =
3792d95276ceSAkeem G Abodunrin 			em_list_itr->fltr_info.lkup_type;
3793d95276ceSAkeem G Abodunrin 
3794d95276ceSAkeem G Abodunrin 		if (l_type != ICE_SW_LKUP_ETHERTYPE_MAC &&
3795d95276ceSAkeem G Abodunrin 		    l_type != ICE_SW_LKUP_ETHERTYPE)
3796d54699e2STony Nguyen 			return -EINVAL;
3797d95276ceSAkeem G Abodunrin 
3798d95276ceSAkeem G Abodunrin 		em_list_itr->status = ice_add_rule_internal(hw, l_type,
3799d95276ceSAkeem G Abodunrin 							    em_list_itr);
3800d95276ceSAkeem G Abodunrin 		if (em_list_itr->status)
3801d95276ceSAkeem G Abodunrin 			return em_list_itr->status;
3802d95276ceSAkeem G Abodunrin 	}
3803d95276ceSAkeem G Abodunrin 	return 0;
3804d95276ceSAkeem G Abodunrin }
3805d95276ceSAkeem G Abodunrin 
3806d95276ceSAkeem G Abodunrin /**
3807d95276ceSAkeem G Abodunrin  * ice_remove_eth_mac - Remove an ethertype (or MAC) based filter rule
3808d95276ceSAkeem G Abodunrin  * @hw: pointer to the hardware structure
3809d95276ceSAkeem G Abodunrin  * @em_list: list of ethertype or ethertype MAC entries
3810d95276ceSAkeem G Abodunrin  */
38115518ac2aSTony Nguyen int ice_remove_eth_mac(struct ice_hw *hw, struct list_head *em_list)
3812d95276ceSAkeem G Abodunrin {
3813d95276ceSAkeem G Abodunrin 	struct ice_fltr_list_entry *em_list_itr, *tmp;
3814d95276ceSAkeem G Abodunrin 
3815d95276ceSAkeem G Abodunrin 	if (!em_list || !hw)
3816d54699e2STony Nguyen 		return -EINVAL;
3817d95276ceSAkeem G Abodunrin 
3818d95276ceSAkeem G Abodunrin 	list_for_each_entry_safe(em_list_itr, tmp, em_list, list_entry) {
3819d95276ceSAkeem G Abodunrin 		enum ice_sw_lkup_type l_type =
3820d95276ceSAkeem G Abodunrin 			em_list_itr->fltr_info.lkup_type;
3821d95276ceSAkeem G Abodunrin 
3822d95276ceSAkeem G Abodunrin 		if (l_type != ICE_SW_LKUP_ETHERTYPE_MAC &&
3823d95276ceSAkeem G Abodunrin 		    l_type != ICE_SW_LKUP_ETHERTYPE)
3824d54699e2STony Nguyen 			return -EINVAL;
3825d95276ceSAkeem G Abodunrin 
3826d95276ceSAkeem G Abodunrin 		em_list_itr->status = ice_remove_rule_internal(hw, l_type,
3827d95276ceSAkeem G Abodunrin 							       em_list_itr);
3828d95276ceSAkeem G Abodunrin 		if (em_list_itr->status)
3829d95276ceSAkeem G Abodunrin 			return em_list_itr->status;
3830d95276ceSAkeem G Abodunrin 	}
3831d95276ceSAkeem G Abodunrin 	return 0;
3832d95276ceSAkeem G Abodunrin }
3833d95276ceSAkeem G Abodunrin 
3834d95276ceSAkeem G Abodunrin /**
38350f9d5027SAnirudh Venkataramanan  * ice_rem_sw_rule_info
38360f9d5027SAnirudh Venkataramanan  * @hw: pointer to the hardware structure
38370f9d5027SAnirudh Venkataramanan  * @rule_head: pointer to the switch list structure that we want to delete
38380f9d5027SAnirudh Venkataramanan  */
38390f9d5027SAnirudh Venkataramanan static void
38400f9d5027SAnirudh Venkataramanan ice_rem_sw_rule_info(struct ice_hw *hw, struct list_head *rule_head)
38410f9d5027SAnirudh Venkataramanan {
38420f9d5027SAnirudh Venkataramanan 	if (!list_empty(rule_head)) {
38430f9d5027SAnirudh Venkataramanan 		struct ice_fltr_mgmt_list_entry *entry;
38440f9d5027SAnirudh Venkataramanan 		struct ice_fltr_mgmt_list_entry *tmp;
38450f9d5027SAnirudh Venkataramanan 
38460f9d5027SAnirudh Venkataramanan 		list_for_each_entry_safe(entry, tmp, rule_head, list_entry) {
38470f9d5027SAnirudh Venkataramanan 			list_del(&entry->list_entry);
38480f9d5027SAnirudh Venkataramanan 			devm_kfree(ice_hw_to_dev(hw), entry);
38490f9d5027SAnirudh Venkataramanan 		}
38500f9d5027SAnirudh Venkataramanan 	}
38510f9d5027SAnirudh Venkataramanan }
38520f9d5027SAnirudh Venkataramanan 
38530f9d5027SAnirudh Venkataramanan /**
38548b8ef05bSVictor Raj  * ice_rem_adv_rule_info
38558b8ef05bSVictor Raj  * @hw: pointer to the hardware structure
38568b8ef05bSVictor Raj  * @rule_head: pointer to the switch list structure that we want to delete
38578b8ef05bSVictor Raj  */
38588b8ef05bSVictor Raj static void
38598b8ef05bSVictor Raj ice_rem_adv_rule_info(struct ice_hw *hw, struct list_head *rule_head)
38608b8ef05bSVictor Raj {
38618b8ef05bSVictor Raj 	struct ice_adv_fltr_mgmt_list_entry *tmp_entry;
38628b8ef05bSVictor Raj 	struct ice_adv_fltr_mgmt_list_entry *lst_itr;
38638b8ef05bSVictor Raj 
38648b8ef05bSVictor Raj 	if (list_empty(rule_head))
38658b8ef05bSVictor Raj 		return;
38668b8ef05bSVictor Raj 
38678b8ef05bSVictor Raj 	list_for_each_entry_safe(lst_itr, tmp_entry, rule_head, list_entry) {
38688b8ef05bSVictor Raj 		list_del(&lst_itr->list_entry);
38698b8ef05bSVictor Raj 		devm_kfree(ice_hw_to_dev(hw), lst_itr->lkups);
38708b8ef05bSVictor Raj 		devm_kfree(ice_hw_to_dev(hw), lst_itr);
38718b8ef05bSVictor Raj 	}
38728b8ef05bSVictor Raj }
38738b8ef05bSVictor Raj 
38748b8ef05bSVictor Raj /**
387580d144c9SAnirudh Venkataramanan  * ice_cfg_dflt_vsi - change state of VSI to set/clear default
3876d7393425SMichal Wilczynski  * @pi: pointer to the port_info structure
38775726ca0eSAnirudh Venkataramanan  * @vsi_handle: VSI handle to set as default
3878e94d4478SAnirudh Venkataramanan  * @set: true to add the above mentioned switch rule, false to remove it
3879e94d4478SAnirudh Venkataramanan  * @direction: ICE_FLTR_RX or ICE_FLTR_TX
388080d144c9SAnirudh Venkataramanan  *
388180d144c9SAnirudh Venkataramanan  * add filter rule to set/unset given VSI as default VSI for the switch
388280d144c9SAnirudh Venkataramanan  * (represented by swid)
3883e94d4478SAnirudh Venkataramanan  */
3884d7393425SMichal Wilczynski int
3885d7393425SMichal Wilczynski ice_cfg_dflt_vsi(struct ice_port_info *pi, u16 vsi_handle, bool set,
3886d7393425SMichal Wilczynski 		 u8 direction)
3887e94d4478SAnirudh Venkataramanan {
3888d7393425SMichal Wilczynski 	struct ice_fltr_list_entry f_list_entry;
3889e94d4478SAnirudh Venkataramanan 	struct ice_fltr_info f_info;
3890d7393425SMichal Wilczynski 	struct ice_hw *hw = pi->hw;
38915726ca0eSAnirudh Venkataramanan 	u16 hw_vsi_id;
38925518ac2aSTony Nguyen 	int status;
38935726ca0eSAnirudh Venkataramanan 
38945726ca0eSAnirudh Venkataramanan 	if (!ice_is_vsi_valid(hw, vsi_handle))
3895d54699e2STony Nguyen 		return -EINVAL;
3896d7393425SMichal Wilczynski 
38975726ca0eSAnirudh Venkataramanan 	hw_vsi_id = ice_get_hw_vsi_num(hw, vsi_handle);
3898e94d4478SAnirudh Venkataramanan 
3899e94d4478SAnirudh Venkataramanan 	memset(&f_info, 0, sizeof(f_info));
3900e94d4478SAnirudh Venkataramanan 
3901e94d4478SAnirudh Venkataramanan 	f_info.lkup_type = ICE_SW_LKUP_DFLT;
3902e94d4478SAnirudh Venkataramanan 	f_info.flag = direction;
3903e94d4478SAnirudh Venkataramanan 	f_info.fltr_act = ICE_FWD_TO_VSI;
39045726ca0eSAnirudh Venkataramanan 	f_info.fwd_id.hw_vsi_id = hw_vsi_id;
3905d7393425SMichal Wilczynski 	f_info.vsi_handle = vsi_handle;
3906e94d4478SAnirudh Venkataramanan 
3907e94d4478SAnirudh Venkataramanan 	if (f_info.flag & ICE_FLTR_RX) {
3908e94d4478SAnirudh Venkataramanan 		f_info.src = hw->port_info->lport;
39095726ca0eSAnirudh Venkataramanan 		f_info.src_id = ICE_SRC_ID_LPORT;
3910e94d4478SAnirudh Venkataramanan 	} else if (f_info.flag & ICE_FLTR_TX) {
39115726ca0eSAnirudh Venkataramanan 		f_info.src_id = ICE_SRC_ID_VSI;
39125726ca0eSAnirudh Venkataramanan 		f_info.src = hw_vsi_id;
3913e94d4478SAnirudh Venkataramanan 	}
3914d7393425SMichal Wilczynski 	f_list_entry.fltr_info = f_info;
3915e94d4478SAnirudh Venkataramanan 
3916e94d4478SAnirudh Venkataramanan 	if (set)
3917d7393425SMichal Wilczynski 		status = ice_add_rule_internal(hw, ICE_SW_LKUP_DFLT,
3918d7393425SMichal Wilczynski 					       &f_list_entry);
3919e94d4478SAnirudh Venkataramanan 	else
3920d7393425SMichal Wilczynski 		status = ice_remove_rule_internal(hw, ICE_SW_LKUP_DFLT,
3921d7393425SMichal Wilczynski 						  &f_list_entry);
3922e94d4478SAnirudh Venkataramanan 
3923e94d4478SAnirudh Venkataramanan 	return status;
3924e94d4478SAnirudh Venkataramanan }
3925e94d4478SAnirudh Venkataramanan 
3926e94d4478SAnirudh Venkataramanan /**
3927d7393425SMichal Wilczynski  * ice_vsi_uses_fltr - Determine if given VSI uses specified filter
3928d7393425SMichal Wilczynski  * @fm_entry: filter entry to inspect
3929d7393425SMichal Wilczynski  * @vsi_handle: VSI handle to compare with filter info
3930d7393425SMichal Wilczynski  */
3931d7393425SMichal Wilczynski static bool
3932d7393425SMichal Wilczynski ice_vsi_uses_fltr(struct ice_fltr_mgmt_list_entry *fm_entry, u16 vsi_handle)
3933d7393425SMichal Wilczynski {
3934d7393425SMichal Wilczynski 	return ((fm_entry->fltr_info.fltr_act == ICE_FWD_TO_VSI &&
3935d7393425SMichal Wilczynski 		 fm_entry->fltr_info.vsi_handle == vsi_handle) ||
3936d7393425SMichal Wilczynski 		(fm_entry->fltr_info.fltr_act == ICE_FWD_TO_VSI_LIST &&
3937d7393425SMichal Wilczynski 		 fm_entry->vsi_list_info &&
3938d7393425SMichal Wilczynski 		 (test_bit(vsi_handle, fm_entry->vsi_list_info->vsi_map))));
3939d7393425SMichal Wilczynski }
3940d7393425SMichal Wilczynski 
3941d7393425SMichal Wilczynski /**
3942d7393425SMichal Wilczynski  * ice_check_if_dflt_vsi - check if VSI is default VSI
3943d7393425SMichal Wilczynski  * @pi: pointer to the port_info structure
3944d7393425SMichal Wilczynski  * @vsi_handle: vsi handle to check for in filter list
3945d7393425SMichal Wilczynski  * @rule_exists: indicates if there are any VSI's in the rule list
3946d7393425SMichal Wilczynski  *
3947d7393425SMichal Wilczynski  * checks if the VSI is in a default VSI list, and also indicates
3948d7393425SMichal Wilczynski  * if the default VSI list is empty
3949d7393425SMichal Wilczynski  */
3950d7393425SMichal Wilczynski bool
3951d7393425SMichal Wilczynski ice_check_if_dflt_vsi(struct ice_port_info *pi, u16 vsi_handle,
3952d7393425SMichal Wilczynski 		      bool *rule_exists)
3953d7393425SMichal Wilczynski {
3954d7393425SMichal Wilczynski 	struct ice_fltr_mgmt_list_entry *fm_entry;
3955d7393425SMichal Wilczynski 	struct ice_sw_recipe *recp_list;
3956d7393425SMichal Wilczynski 	struct list_head *rule_head;
3957d7393425SMichal Wilczynski 	struct mutex *rule_lock; /* Lock to protect filter rule list */
3958d7393425SMichal Wilczynski 	bool ret = false;
3959d7393425SMichal Wilczynski 
3960d7393425SMichal Wilczynski 	recp_list = &pi->hw->switch_info->recp_list[ICE_SW_LKUP_DFLT];
3961d7393425SMichal Wilczynski 	rule_lock = &recp_list->filt_rule_lock;
3962d7393425SMichal Wilczynski 	rule_head = &recp_list->filt_rules;
3963d7393425SMichal Wilczynski 
3964d7393425SMichal Wilczynski 	mutex_lock(rule_lock);
3965d7393425SMichal Wilczynski 
3966d7393425SMichal Wilczynski 	if (rule_exists && !list_empty(rule_head))
3967d7393425SMichal Wilczynski 		*rule_exists = true;
3968d7393425SMichal Wilczynski 
3969d7393425SMichal Wilczynski 	list_for_each_entry(fm_entry, rule_head, list_entry) {
3970d7393425SMichal Wilczynski 		if (ice_vsi_uses_fltr(fm_entry, vsi_handle)) {
3971d7393425SMichal Wilczynski 			ret = true;
3972d7393425SMichal Wilczynski 			break;
3973d7393425SMichal Wilczynski 		}
3974d7393425SMichal Wilczynski 	}
3975d7393425SMichal Wilczynski 
3976d7393425SMichal Wilczynski 	mutex_unlock(rule_lock);
3977d7393425SMichal Wilczynski 
3978d7393425SMichal Wilczynski 	return ret;
3979d7393425SMichal Wilczynski }
3980d7393425SMichal Wilczynski 
3981d7393425SMichal Wilczynski /**
39828b2c8582SAkeem G Abodunrin  * ice_find_ucast_rule_entry - Search for a unicast MAC filter rule entry
39838b2c8582SAkeem G Abodunrin  * @hw: pointer to the hardware structure
39848b2c8582SAkeem G Abodunrin  * @recp_id: lookup type for which the specified rule needs to be searched
39858b2c8582SAkeem G Abodunrin  * @f_info: rule information
39868b2c8582SAkeem G Abodunrin  *
39878b2c8582SAkeem G Abodunrin  * Helper function to search for a unicast rule entry - this is to be used
39888b2c8582SAkeem G Abodunrin  * to remove unicast MAC filter that is not shared with other VSIs on the
39898b2c8582SAkeem G Abodunrin  * PF switch.
39908b2c8582SAkeem G Abodunrin  *
39918b2c8582SAkeem G Abodunrin  * Returns pointer to entry storing the rule if found
39928b2c8582SAkeem G Abodunrin  */
39938b2c8582SAkeem G Abodunrin static struct ice_fltr_mgmt_list_entry *
39948b2c8582SAkeem G Abodunrin ice_find_ucast_rule_entry(struct ice_hw *hw, u8 recp_id,
39958b2c8582SAkeem G Abodunrin 			  struct ice_fltr_info *f_info)
39968b2c8582SAkeem G Abodunrin {
39978b2c8582SAkeem G Abodunrin 	struct ice_switch_info *sw = hw->switch_info;
39988b2c8582SAkeem G Abodunrin 	struct ice_fltr_mgmt_list_entry *list_itr;
39998b2c8582SAkeem G Abodunrin 	struct list_head *list_head;
40008b2c8582SAkeem G Abodunrin 
40018b2c8582SAkeem G Abodunrin 	list_head = &sw->recp_list[recp_id].filt_rules;
40028b2c8582SAkeem G Abodunrin 	list_for_each_entry(list_itr, list_head, list_entry) {
40038b2c8582SAkeem G Abodunrin 		if (!memcmp(&f_info->l_data, &list_itr->fltr_info.l_data,
40048b2c8582SAkeem G Abodunrin 			    sizeof(f_info->l_data)) &&
40058b2c8582SAkeem G Abodunrin 		    f_info->fwd_id.hw_vsi_id ==
40068b2c8582SAkeem G Abodunrin 		    list_itr->fltr_info.fwd_id.hw_vsi_id &&
40078b2c8582SAkeem G Abodunrin 		    f_info->flag == list_itr->fltr_info.flag)
40088b2c8582SAkeem G Abodunrin 			return list_itr;
40098b2c8582SAkeem G Abodunrin 	}
40108b2c8582SAkeem G Abodunrin 	return NULL;
40118b2c8582SAkeem G Abodunrin }
40128b2c8582SAkeem G Abodunrin 
40138b2c8582SAkeem G Abodunrin /**
401480d144c9SAnirudh Venkataramanan  * ice_remove_mac - remove a MAC address based filter rule
4015d76a60baSAnirudh Venkataramanan  * @hw: pointer to the hardware structure
401680d144c9SAnirudh Venkataramanan  * @m_list: list of MAC addresses and forwarding information
401780d144c9SAnirudh Venkataramanan  *
401880d144c9SAnirudh Venkataramanan  * This function removes either a MAC filter rule or a specific VSI from a
401980d144c9SAnirudh Venkataramanan  * VSI list for a multicast MAC address.
402080d144c9SAnirudh Venkataramanan  *
40215518ac2aSTony Nguyen  * Returns -ENOENT if a given entry was not added by ice_add_mac. Caller should
40225518ac2aSTony Nguyen  * be aware that this call will only work if all the entries passed into m_list
40235518ac2aSTony Nguyen  * were added previously. It will not attempt to do a partial remove of entries
40245518ac2aSTony Nguyen  * that were found.
4025d76a60baSAnirudh Venkataramanan  */
40265e24d598STony Nguyen int ice_remove_mac(struct ice_hw *hw, struct list_head *m_list)
4027d76a60baSAnirudh Venkataramanan {
4028072f0c3dSDave Ertman 	struct ice_fltr_list_entry *list_itr, *tmp;
40298b2c8582SAkeem G Abodunrin 	struct mutex *rule_lock; /* Lock to protect filter rule list */
4030d76a60baSAnirudh Venkataramanan 
403180d144c9SAnirudh Venkataramanan 	if (!m_list)
4032d54699e2STony Nguyen 		return -EINVAL;
4033d76a60baSAnirudh Venkataramanan 
40348b2c8582SAkeem G Abodunrin 	rule_lock = &hw->switch_info->recp_list[ICE_SW_LKUP_MAC].filt_rule_lock;
4035072f0c3dSDave Ertman 	list_for_each_entry_safe(list_itr, tmp, m_list, list_entry) {
403680d144c9SAnirudh Venkataramanan 		enum ice_sw_lkup_type l_type = list_itr->fltr_info.lkup_type;
40378b2c8582SAkeem G Abodunrin 		u8 *add = &list_itr->fltr_info.l_data.mac.mac_addr[0];
40388b2c8582SAkeem G Abodunrin 		u16 vsi_handle;
403980d144c9SAnirudh Venkataramanan 
404080d144c9SAnirudh Venkataramanan 		if (l_type != ICE_SW_LKUP_MAC)
4041d54699e2STony Nguyen 			return -EINVAL;
40428b2c8582SAkeem G Abodunrin 
40438b2c8582SAkeem G Abodunrin 		vsi_handle = list_itr->fltr_info.vsi_handle;
40448b2c8582SAkeem G Abodunrin 		if (!ice_is_vsi_valid(hw, vsi_handle))
4045d54699e2STony Nguyen 			return -EINVAL;
40468b2c8582SAkeem G Abodunrin 
40478b2c8582SAkeem G Abodunrin 		list_itr->fltr_info.fwd_id.hw_vsi_id =
40488b2c8582SAkeem G Abodunrin 					ice_get_hw_vsi_num(hw, vsi_handle);
40498b2c8582SAkeem G Abodunrin 		if (is_unicast_ether_addr(add) && !hw->ucast_shared) {
40508b2c8582SAkeem G Abodunrin 			/* Don't remove the unicast address that belongs to
40518b2c8582SAkeem G Abodunrin 			 * another VSI on the switch, since it is not being
40528b2c8582SAkeem G Abodunrin 			 * shared...
40538b2c8582SAkeem G Abodunrin 			 */
40548b2c8582SAkeem G Abodunrin 			mutex_lock(rule_lock);
40558b2c8582SAkeem G Abodunrin 			if (!ice_find_ucast_rule_entry(hw, ICE_SW_LKUP_MAC,
40568b2c8582SAkeem G Abodunrin 						       &list_itr->fltr_info)) {
40578b2c8582SAkeem G Abodunrin 				mutex_unlock(rule_lock);
4058d54699e2STony Nguyen 				return -ENOENT;
40598b2c8582SAkeem G Abodunrin 			}
40608b2c8582SAkeem G Abodunrin 			mutex_unlock(rule_lock);
40618b2c8582SAkeem G Abodunrin 		}
406280d144c9SAnirudh Venkataramanan 		list_itr->status = ice_remove_rule_internal(hw,
406380d144c9SAnirudh Venkataramanan 							    ICE_SW_LKUP_MAC,
406480d144c9SAnirudh Venkataramanan 							    list_itr);
406580d144c9SAnirudh Venkataramanan 		if (list_itr->status)
406680d144c9SAnirudh Venkataramanan 			return list_itr->status;
406780d144c9SAnirudh Venkataramanan 	}
406880d144c9SAnirudh Venkataramanan 	return 0;
4069d76a60baSAnirudh Venkataramanan }
4070d76a60baSAnirudh Venkataramanan 
4071d76a60baSAnirudh Venkataramanan /**
4072d76a60baSAnirudh Venkataramanan  * ice_remove_vlan - Remove VLAN based filter rule
4073d76a60baSAnirudh Venkataramanan  * @hw: pointer to the hardware structure
4074d76a60baSAnirudh Venkataramanan  * @v_list: list of VLAN entries and forwarding information
4075d76a60baSAnirudh Venkataramanan  */
40765518ac2aSTony Nguyen int ice_remove_vlan(struct ice_hw *hw, struct list_head *v_list)
4077d76a60baSAnirudh Venkataramanan {
4078072f0c3dSDave Ertman 	struct ice_fltr_list_entry *v_list_itr, *tmp;
4079d76a60baSAnirudh Venkataramanan 
4080d76a60baSAnirudh Venkataramanan 	if (!v_list || !hw)
4081d54699e2STony Nguyen 		return -EINVAL;
4082d76a60baSAnirudh Venkataramanan 
4083072f0c3dSDave Ertman 	list_for_each_entry_safe(v_list_itr, tmp, v_list, list_entry) {
408480d144c9SAnirudh Venkataramanan 		enum ice_sw_lkup_type l_type = v_list_itr->fltr_info.lkup_type;
408580d144c9SAnirudh Venkataramanan 
408680d144c9SAnirudh Venkataramanan 		if (l_type != ICE_SW_LKUP_VLAN)
4087d54699e2STony Nguyen 			return -EINVAL;
408880d144c9SAnirudh Venkataramanan 		v_list_itr->status = ice_remove_rule_internal(hw,
408980d144c9SAnirudh Venkataramanan 							      ICE_SW_LKUP_VLAN,
409080d144c9SAnirudh Venkataramanan 							      v_list_itr);
409180d144c9SAnirudh Venkataramanan 		if (v_list_itr->status)
409280d144c9SAnirudh Venkataramanan 			return v_list_itr->status;
4093d76a60baSAnirudh Venkataramanan 	}
409480d144c9SAnirudh Venkataramanan 	return 0;
4095d76a60baSAnirudh Venkataramanan }
409680d144c9SAnirudh Venkataramanan 
409780d144c9SAnirudh Venkataramanan /**
409880d144c9SAnirudh Venkataramanan  * ice_add_entry_to_vsi_fltr_list - Add copy of fltr_list_entry to remove list
409980d144c9SAnirudh Venkataramanan  * @hw: pointer to the hardware structure
41005726ca0eSAnirudh Venkataramanan  * @vsi_handle: VSI handle to remove filters from
410180d144c9SAnirudh Venkataramanan  * @vsi_list_head: pointer to the list to add entry to
410280d144c9SAnirudh Venkataramanan  * @fi: pointer to fltr_info of filter entry to copy & add
410380d144c9SAnirudh Venkataramanan  *
410480d144c9SAnirudh Venkataramanan  * Helper function, used when creating a list of filters to remove from
410580d144c9SAnirudh Venkataramanan  * a specific VSI. The entry added to vsi_list_head is a COPY of the
410680d144c9SAnirudh Venkataramanan  * original filter entry, with the exception of fltr_info.fltr_act and
410780d144c9SAnirudh Venkataramanan  * fltr_info.fwd_id fields. These are set such that later logic can
410880d144c9SAnirudh Venkataramanan  * extract which VSI to remove the fltr from, and pass on that information.
410980d144c9SAnirudh Venkataramanan  */
41105e24d598STony Nguyen static int
41115726ca0eSAnirudh Venkataramanan ice_add_entry_to_vsi_fltr_list(struct ice_hw *hw, u16 vsi_handle,
411280d144c9SAnirudh Venkataramanan 			       struct list_head *vsi_list_head,
411380d144c9SAnirudh Venkataramanan 			       struct ice_fltr_info *fi)
411480d144c9SAnirudh Venkataramanan {
411580d144c9SAnirudh Venkataramanan 	struct ice_fltr_list_entry *tmp;
411680d144c9SAnirudh Venkataramanan 
411780d144c9SAnirudh Venkataramanan 	/* this memory is freed up in the caller function
411880d144c9SAnirudh Venkataramanan 	 * once filters for this VSI are removed
411980d144c9SAnirudh Venkataramanan 	 */
412080d144c9SAnirudh Venkataramanan 	tmp = devm_kzalloc(ice_hw_to_dev(hw), sizeof(*tmp), GFP_KERNEL);
412180d144c9SAnirudh Venkataramanan 	if (!tmp)
4122d54699e2STony Nguyen 		return -ENOMEM;
412380d144c9SAnirudh Venkataramanan 
412480d144c9SAnirudh Venkataramanan 	tmp->fltr_info = *fi;
412580d144c9SAnirudh Venkataramanan 
412680d144c9SAnirudh Venkataramanan 	/* Overwrite these fields to indicate which VSI to remove filter from,
412780d144c9SAnirudh Venkataramanan 	 * so find and remove logic can extract the information from the
412880d144c9SAnirudh Venkataramanan 	 * list entries. Note that original entries will still have proper
412980d144c9SAnirudh Venkataramanan 	 * values.
413080d144c9SAnirudh Venkataramanan 	 */
413180d144c9SAnirudh Venkataramanan 	tmp->fltr_info.fltr_act = ICE_FWD_TO_VSI;
41325726ca0eSAnirudh Venkataramanan 	tmp->fltr_info.vsi_handle = vsi_handle;
41335726ca0eSAnirudh Venkataramanan 	tmp->fltr_info.fwd_id.hw_vsi_id = ice_get_hw_vsi_num(hw, vsi_handle);
413480d144c9SAnirudh Venkataramanan 
413580d144c9SAnirudh Venkataramanan 	list_add(&tmp->list_entry, vsi_list_head);
413680d144c9SAnirudh Venkataramanan 
413780d144c9SAnirudh Venkataramanan 	return 0;
4138d76a60baSAnirudh Venkataramanan }
4139d76a60baSAnirudh Venkataramanan 
4140d76a60baSAnirudh Venkataramanan /**
41419daf8208SAnirudh Venkataramanan  * ice_add_to_vsi_fltr_list - Add VSI filters to the list
41429daf8208SAnirudh Venkataramanan  * @hw: pointer to the hardware structure
41435726ca0eSAnirudh Venkataramanan  * @vsi_handle: VSI handle to remove filters from
41449daf8208SAnirudh Venkataramanan  * @lkup_list_head: pointer to the list that has certain lookup type filters
41455726ca0eSAnirudh Venkataramanan  * @vsi_list_head: pointer to the list pertaining to VSI with vsi_handle
414680d144c9SAnirudh Venkataramanan  *
414780d144c9SAnirudh Venkataramanan  * Locates all filters in lkup_list_head that are used by the given VSI,
414880d144c9SAnirudh Venkataramanan  * and adds COPIES of those entries to vsi_list_head (intended to be used
414980d144c9SAnirudh Venkataramanan  * to remove the listed filters).
415080d144c9SAnirudh Venkataramanan  * Note that this means all entries in vsi_list_head must be explicitly
415180d144c9SAnirudh Venkataramanan  * deallocated by the caller when done with list.
41529daf8208SAnirudh Venkataramanan  */
41535e24d598STony Nguyen static int
41545726ca0eSAnirudh Venkataramanan ice_add_to_vsi_fltr_list(struct ice_hw *hw, u16 vsi_handle,
41559daf8208SAnirudh Venkataramanan 			 struct list_head *lkup_list_head,
41569daf8208SAnirudh Venkataramanan 			 struct list_head *vsi_list_head)
41579daf8208SAnirudh Venkataramanan {
41589daf8208SAnirudh Venkataramanan 	struct ice_fltr_mgmt_list_entry *fm_entry;
41595e24d598STony Nguyen 	int status = 0;
41609daf8208SAnirudh Venkataramanan 
4161f9867df6SAnirudh Venkataramanan 	/* check to make sure VSI ID is valid and within boundary */
41625726ca0eSAnirudh Venkataramanan 	if (!ice_is_vsi_valid(hw, vsi_handle))
4163d54699e2STony Nguyen 		return -EINVAL;
41649daf8208SAnirudh Venkataramanan 
41659daf8208SAnirudh Venkataramanan 	list_for_each_entry(fm_entry, lkup_list_head, list_entry) {
41667a91d3f0SJacek Bułatek 		if (!ice_vsi_uses_fltr(fm_entry, vsi_handle))
416780d144c9SAnirudh Venkataramanan 			continue;
41689daf8208SAnirudh Venkataramanan 
41695726ca0eSAnirudh Venkataramanan 		status = ice_add_entry_to_vsi_fltr_list(hw, vsi_handle,
41707a91d3f0SJacek Bułatek 							vsi_list_head,
41717a91d3f0SJacek Bułatek 							&fm_entry->fltr_info);
417280d144c9SAnirudh Venkataramanan 		if (status)
417380d144c9SAnirudh Venkataramanan 			return status;
41749daf8208SAnirudh Venkataramanan 	}
417580d144c9SAnirudh Venkataramanan 	return status;
41769daf8208SAnirudh Venkataramanan }
41779daf8208SAnirudh Venkataramanan 
41789daf8208SAnirudh Venkataramanan /**
41795eda8afdSAkeem G Abodunrin  * ice_determine_promisc_mask
41805eda8afdSAkeem G Abodunrin  * @fi: filter info to parse
41815eda8afdSAkeem G Abodunrin  *
41825eda8afdSAkeem G Abodunrin  * Helper function to determine which ICE_PROMISC_ mask corresponds
41835eda8afdSAkeem G Abodunrin  * to given filter into.
41845eda8afdSAkeem G Abodunrin  */
41855eda8afdSAkeem G Abodunrin static u8 ice_determine_promisc_mask(struct ice_fltr_info *fi)
41865eda8afdSAkeem G Abodunrin {
41875eda8afdSAkeem G Abodunrin 	u16 vid = fi->l_data.mac_vlan.vlan_id;
41885eda8afdSAkeem G Abodunrin 	u8 *macaddr = fi->l_data.mac.mac_addr;
41895eda8afdSAkeem G Abodunrin 	bool is_tx_fltr = false;
41905eda8afdSAkeem G Abodunrin 	u8 promisc_mask = 0;
41915eda8afdSAkeem G Abodunrin 
41925eda8afdSAkeem G Abodunrin 	if (fi->flag == ICE_FLTR_TX)
41935eda8afdSAkeem G Abodunrin 		is_tx_fltr = true;
41945eda8afdSAkeem G Abodunrin 
41955eda8afdSAkeem G Abodunrin 	if (is_broadcast_ether_addr(macaddr))
41965eda8afdSAkeem G Abodunrin 		promisc_mask |= is_tx_fltr ?
41975eda8afdSAkeem G Abodunrin 			ICE_PROMISC_BCAST_TX : ICE_PROMISC_BCAST_RX;
41985eda8afdSAkeem G Abodunrin 	else if (is_multicast_ether_addr(macaddr))
41995eda8afdSAkeem G Abodunrin 		promisc_mask |= is_tx_fltr ?
42005eda8afdSAkeem G Abodunrin 			ICE_PROMISC_MCAST_TX : ICE_PROMISC_MCAST_RX;
42015eda8afdSAkeem G Abodunrin 	else if (is_unicast_ether_addr(macaddr))
42025eda8afdSAkeem G Abodunrin 		promisc_mask |= is_tx_fltr ?
42035eda8afdSAkeem G Abodunrin 			ICE_PROMISC_UCAST_TX : ICE_PROMISC_UCAST_RX;
42045eda8afdSAkeem G Abodunrin 	if (vid)
42055eda8afdSAkeem G Abodunrin 		promisc_mask |= is_tx_fltr ?
42065eda8afdSAkeem G Abodunrin 			ICE_PROMISC_VLAN_TX : ICE_PROMISC_VLAN_RX;
42075eda8afdSAkeem G Abodunrin 
42085eda8afdSAkeem G Abodunrin 	return promisc_mask;
42095eda8afdSAkeem G Abodunrin }
42105eda8afdSAkeem G Abodunrin 
42115eda8afdSAkeem G Abodunrin /**
42125eda8afdSAkeem G Abodunrin  * ice_remove_promisc - Remove promisc based filter rules
42135eda8afdSAkeem G Abodunrin  * @hw: pointer to the hardware structure
4214f9867df6SAnirudh Venkataramanan  * @recp_id: recipe ID for which the rule needs to removed
42155eda8afdSAkeem G Abodunrin  * @v_list: list of promisc entries
42165eda8afdSAkeem G Abodunrin  */
42175e24d598STony Nguyen static int
42185518ac2aSTony Nguyen ice_remove_promisc(struct ice_hw *hw, u8 recp_id, struct list_head *v_list)
42195eda8afdSAkeem G Abodunrin {
42205eda8afdSAkeem G Abodunrin 	struct ice_fltr_list_entry *v_list_itr, *tmp;
42215eda8afdSAkeem G Abodunrin 
42225eda8afdSAkeem G Abodunrin 	list_for_each_entry_safe(v_list_itr, tmp, v_list, list_entry) {
42235eda8afdSAkeem G Abodunrin 		v_list_itr->status =
42245eda8afdSAkeem G Abodunrin 			ice_remove_rule_internal(hw, recp_id, v_list_itr);
42255eda8afdSAkeem G Abodunrin 		if (v_list_itr->status)
42265eda8afdSAkeem G Abodunrin 			return v_list_itr->status;
42275eda8afdSAkeem G Abodunrin 	}
42285eda8afdSAkeem G Abodunrin 	return 0;
42295eda8afdSAkeem G Abodunrin }
42305eda8afdSAkeem G Abodunrin 
42315eda8afdSAkeem G Abodunrin /**
42325eda8afdSAkeem G Abodunrin  * ice_clear_vsi_promisc - clear specified promiscuous mode(s) for given VSI
42335eda8afdSAkeem G Abodunrin  * @hw: pointer to the hardware structure
42345eda8afdSAkeem G Abodunrin  * @vsi_handle: VSI handle to clear mode
42355eda8afdSAkeem G Abodunrin  * @promisc_mask: mask of promiscuous config bits to clear
42365eda8afdSAkeem G Abodunrin  * @vid: VLAN ID to clear VLAN promiscuous
42375eda8afdSAkeem G Abodunrin  */
42385e24d598STony Nguyen int
42395eda8afdSAkeem G Abodunrin ice_clear_vsi_promisc(struct ice_hw *hw, u16 vsi_handle, u8 promisc_mask,
42405eda8afdSAkeem G Abodunrin 		      u16 vid)
42415eda8afdSAkeem G Abodunrin {
42425eda8afdSAkeem G Abodunrin 	struct ice_switch_info *sw = hw->switch_info;
42435eda8afdSAkeem G Abodunrin 	struct ice_fltr_list_entry *fm_entry, *tmp;
42445eda8afdSAkeem G Abodunrin 	struct list_head remove_list_head;
42455eda8afdSAkeem G Abodunrin 	struct ice_fltr_mgmt_list_entry *itr;
42465eda8afdSAkeem G Abodunrin 	struct list_head *rule_head;
42475eda8afdSAkeem G Abodunrin 	struct mutex *rule_lock;	/* Lock to protect filter rule list */
42485e24d598STony Nguyen 	int status = 0;
42495eda8afdSAkeem G Abodunrin 	u8 recipe_id;
42505eda8afdSAkeem G Abodunrin 
42515eda8afdSAkeem G Abodunrin 	if (!ice_is_vsi_valid(hw, vsi_handle))
4252d54699e2STony Nguyen 		return -EINVAL;
42535eda8afdSAkeem G Abodunrin 
42541bc7a4abSBrett Creeley 	if (promisc_mask & (ICE_PROMISC_VLAN_RX | ICE_PROMISC_VLAN_TX))
42555eda8afdSAkeem G Abodunrin 		recipe_id = ICE_SW_LKUP_PROMISC_VLAN;
42565eda8afdSAkeem G Abodunrin 	else
42575eda8afdSAkeem G Abodunrin 		recipe_id = ICE_SW_LKUP_PROMISC;
42585eda8afdSAkeem G Abodunrin 
42595eda8afdSAkeem G Abodunrin 	rule_head = &sw->recp_list[recipe_id].filt_rules;
42605eda8afdSAkeem G Abodunrin 	rule_lock = &sw->recp_list[recipe_id].filt_rule_lock;
42615eda8afdSAkeem G Abodunrin 
42625eda8afdSAkeem G Abodunrin 	INIT_LIST_HEAD(&remove_list_head);
42635eda8afdSAkeem G Abodunrin 
42645eda8afdSAkeem G Abodunrin 	mutex_lock(rule_lock);
42655eda8afdSAkeem G Abodunrin 	list_for_each_entry(itr, rule_head, list_entry) {
42661bc7a4abSBrett Creeley 		struct ice_fltr_info *fltr_info;
42675eda8afdSAkeem G Abodunrin 		u8 fltr_promisc_mask = 0;
42685eda8afdSAkeem G Abodunrin 
42695eda8afdSAkeem G Abodunrin 		if (!ice_vsi_uses_fltr(itr, vsi_handle))
42705eda8afdSAkeem G Abodunrin 			continue;
42711bc7a4abSBrett Creeley 		fltr_info = &itr->fltr_info;
42725eda8afdSAkeem G Abodunrin 
42731bc7a4abSBrett Creeley 		if (recipe_id == ICE_SW_LKUP_PROMISC_VLAN &&
42741bc7a4abSBrett Creeley 		    vid != fltr_info->l_data.mac_vlan.vlan_id)
42751bc7a4abSBrett Creeley 			continue;
42761bc7a4abSBrett Creeley 
42771bc7a4abSBrett Creeley 		fltr_promisc_mask |= ice_determine_promisc_mask(fltr_info);
42785eda8afdSAkeem G Abodunrin 
42795eda8afdSAkeem G Abodunrin 		/* Skip if filter is not completely specified by given mask */
42805eda8afdSAkeem G Abodunrin 		if (fltr_promisc_mask & ~promisc_mask)
42815eda8afdSAkeem G Abodunrin 			continue;
42825eda8afdSAkeem G Abodunrin 
42835eda8afdSAkeem G Abodunrin 		status = ice_add_entry_to_vsi_fltr_list(hw, vsi_handle,
42845eda8afdSAkeem G Abodunrin 							&remove_list_head,
42851bc7a4abSBrett Creeley 							fltr_info);
42865eda8afdSAkeem G Abodunrin 		if (status) {
42875eda8afdSAkeem G Abodunrin 			mutex_unlock(rule_lock);
42885eda8afdSAkeem G Abodunrin 			goto free_fltr_list;
42895eda8afdSAkeem G Abodunrin 		}
42905eda8afdSAkeem G Abodunrin 	}
42915eda8afdSAkeem G Abodunrin 	mutex_unlock(rule_lock);
42925eda8afdSAkeem G Abodunrin 
42935eda8afdSAkeem G Abodunrin 	status = ice_remove_promisc(hw, recipe_id, &remove_list_head);
42945eda8afdSAkeem G Abodunrin 
42955eda8afdSAkeem G Abodunrin free_fltr_list:
42965eda8afdSAkeem G Abodunrin 	list_for_each_entry_safe(fm_entry, tmp, &remove_list_head, list_entry) {
42975eda8afdSAkeem G Abodunrin 		list_del(&fm_entry->list_entry);
42985eda8afdSAkeem G Abodunrin 		devm_kfree(ice_hw_to_dev(hw), fm_entry);
42995eda8afdSAkeem G Abodunrin 	}
43005eda8afdSAkeem G Abodunrin 
43015eda8afdSAkeem G Abodunrin 	return status;
43025eda8afdSAkeem G Abodunrin }
43035eda8afdSAkeem G Abodunrin 
43045eda8afdSAkeem G Abodunrin /**
43055eda8afdSAkeem G Abodunrin  * ice_set_vsi_promisc - set given VSI to given promiscuous mode(s)
43065eda8afdSAkeem G Abodunrin  * @hw: pointer to the hardware structure
43075eda8afdSAkeem G Abodunrin  * @vsi_handle: VSI handle to configure
43085eda8afdSAkeem G Abodunrin  * @promisc_mask: mask of promiscuous config bits
43095eda8afdSAkeem G Abodunrin  * @vid: VLAN ID to set VLAN promiscuous
43105eda8afdSAkeem G Abodunrin  */
43115e24d598STony Nguyen int
43125eda8afdSAkeem G Abodunrin ice_set_vsi_promisc(struct ice_hw *hw, u16 vsi_handle, u8 promisc_mask, u16 vid)
43135eda8afdSAkeem G Abodunrin {
43145eda8afdSAkeem G Abodunrin 	enum { UCAST_FLTR = 1, MCAST_FLTR, BCAST_FLTR };
43155eda8afdSAkeem G Abodunrin 	struct ice_fltr_list_entry f_list_entry;
43165eda8afdSAkeem G Abodunrin 	struct ice_fltr_info new_fltr;
43175eda8afdSAkeem G Abodunrin 	bool is_tx_fltr;
43185518ac2aSTony Nguyen 	int status = 0;
43195eda8afdSAkeem G Abodunrin 	u16 hw_vsi_id;
43205eda8afdSAkeem G Abodunrin 	int pkt_type;
43215eda8afdSAkeem G Abodunrin 	u8 recipe_id;
43225eda8afdSAkeem G Abodunrin 
43235eda8afdSAkeem G Abodunrin 	if (!ice_is_vsi_valid(hw, vsi_handle))
4324d54699e2STony Nguyen 		return -EINVAL;
43255eda8afdSAkeem G Abodunrin 	hw_vsi_id = ice_get_hw_vsi_num(hw, vsi_handle);
43265eda8afdSAkeem G Abodunrin 
43275eda8afdSAkeem G Abodunrin 	memset(&new_fltr, 0, sizeof(new_fltr));
43285eda8afdSAkeem G Abodunrin 
43295eda8afdSAkeem G Abodunrin 	if (promisc_mask & (ICE_PROMISC_VLAN_RX | ICE_PROMISC_VLAN_TX)) {
43305eda8afdSAkeem G Abodunrin 		new_fltr.lkup_type = ICE_SW_LKUP_PROMISC_VLAN;
43315eda8afdSAkeem G Abodunrin 		new_fltr.l_data.mac_vlan.vlan_id = vid;
43325eda8afdSAkeem G Abodunrin 		recipe_id = ICE_SW_LKUP_PROMISC_VLAN;
43335eda8afdSAkeem G Abodunrin 	} else {
43345eda8afdSAkeem G Abodunrin 		new_fltr.lkup_type = ICE_SW_LKUP_PROMISC;
43355eda8afdSAkeem G Abodunrin 		recipe_id = ICE_SW_LKUP_PROMISC;
43365eda8afdSAkeem G Abodunrin 	}
43375eda8afdSAkeem G Abodunrin 
43385eda8afdSAkeem G Abodunrin 	/* Separate filters must be set for each direction/packet type
43395eda8afdSAkeem G Abodunrin 	 * combination, so we will loop over the mask value, store the
43405eda8afdSAkeem G Abodunrin 	 * individual type, and clear it out in the input mask as it
43415eda8afdSAkeem G Abodunrin 	 * is found.
43425eda8afdSAkeem G Abodunrin 	 */
43435eda8afdSAkeem G Abodunrin 	while (promisc_mask) {
43445eda8afdSAkeem G Abodunrin 		u8 *mac_addr;
43455eda8afdSAkeem G Abodunrin 
43465eda8afdSAkeem G Abodunrin 		pkt_type = 0;
43475eda8afdSAkeem G Abodunrin 		is_tx_fltr = false;
43485eda8afdSAkeem G Abodunrin 
43495eda8afdSAkeem G Abodunrin 		if (promisc_mask & ICE_PROMISC_UCAST_RX) {
43505eda8afdSAkeem G Abodunrin 			promisc_mask &= ~ICE_PROMISC_UCAST_RX;
43515eda8afdSAkeem G Abodunrin 			pkt_type = UCAST_FLTR;
43525eda8afdSAkeem G Abodunrin 		} else if (promisc_mask & ICE_PROMISC_UCAST_TX) {
43535eda8afdSAkeem G Abodunrin 			promisc_mask &= ~ICE_PROMISC_UCAST_TX;
43545eda8afdSAkeem G Abodunrin 			pkt_type = UCAST_FLTR;
43555eda8afdSAkeem G Abodunrin 			is_tx_fltr = true;
43565eda8afdSAkeem G Abodunrin 		} else if (promisc_mask & ICE_PROMISC_MCAST_RX) {
43575eda8afdSAkeem G Abodunrin 			promisc_mask &= ~ICE_PROMISC_MCAST_RX;
43585eda8afdSAkeem G Abodunrin 			pkt_type = MCAST_FLTR;
43595eda8afdSAkeem G Abodunrin 		} else if (promisc_mask & ICE_PROMISC_MCAST_TX) {
43605eda8afdSAkeem G Abodunrin 			promisc_mask &= ~ICE_PROMISC_MCAST_TX;
43615eda8afdSAkeem G Abodunrin 			pkt_type = MCAST_FLTR;
43625eda8afdSAkeem G Abodunrin 			is_tx_fltr = true;
43635eda8afdSAkeem G Abodunrin 		} else if (promisc_mask & ICE_PROMISC_BCAST_RX) {
43645eda8afdSAkeem G Abodunrin 			promisc_mask &= ~ICE_PROMISC_BCAST_RX;
43655eda8afdSAkeem G Abodunrin 			pkt_type = BCAST_FLTR;
43665eda8afdSAkeem G Abodunrin 		} else if (promisc_mask & ICE_PROMISC_BCAST_TX) {
43675eda8afdSAkeem G Abodunrin 			promisc_mask &= ~ICE_PROMISC_BCAST_TX;
43685eda8afdSAkeem G Abodunrin 			pkt_type = BCAST_FLTR;
43695eda8afdSAkeem G Abodunrin 			is_tx_fltr = true;
43705eda8afdSAkeem G Abodunrin 		}
43715eda8afdSAkeem G Abodunrin 
43725eda8afdSAkeem G Abodunrin 		/* Check for VLAN promiscuous flag */
43735eda8afdSAkeem G Abodunrin 		if (promisc_mask & ICE_PROMISC_VLAN_RX) {
43745eda8afdSAkeem G Abodunrin 			promisc_mask &= ~ICE_PROMISC_VLAN_RX;
43755eda8afdSAkeem G Abodunrin 		} else if (promisc_mask & ICE_PROMISC_VLAN_TX) {
43765eda8afdSAkeem G Abodunrin 			promisc_mask &= ~ICE_PROMISC_VLAN_TX;
43775eda8afdSAkeem G Abodunrin 			is_tx_fltr = true;
43785eda8afdSAkeem G Abodunrin 		}
43795eda8afdSAkeem G Abodunrin 
43805eda8afdSAkeem G Abodunrin 		/* Set filter DA based on packet type */
43815eda8afdSAkeem G Abodunrin 		mac_addr = new_fltr.l_data.mac.mac_addr;
43825eda8afdSAkeem G Abodunrin 		if (pkt_type == BCAST_FLTR) {
43835eda8afdSAkeem G Abodunrin 			eth_broadcast_addr(mac_addr);
43845eda8afdSAkeem G Abodunrin 		} else if (pkt_type == MCAST_FLTR ||
43855eda8afdSAkeem G Abodunrin 			   pkt_type == UCAST_FLTR) {
43865eda8afdSAkeem G Abodunrin 			/* Use the dummy ether header DA */
43875eda8afdSAkeem G Abodunrin 			ether_addr_copy(mac_addr, dummy_eth_header);
43885eda8afdSAkeem G Abodunrin 			if (pkt_type == MCAST_FLTR)
43895eda8afdSAkeem G Abodunrin 				mac_addr[0] |= 0x1;	/* Set multicast bit */
43905eda8afdSAkeem G Abodunrin 		}
43915eda8afdSAkeem G Abodunrin 
43925eda8afdSAkeem G Abodunrin 		/* Need to reset this to zero for all iterations */
43935eda8afdSAkeem G Abodunrin 		new_fltr.flag = 0;
43945eda8afdSAkeem G Abodunrin 		if (is_tx_fltr) {
43955eda8afdSAkeem G Abodunrin 			new_fltr.flag |= ICE_FLTR_TX;
43965eda8afdSAkeem G Abodunrin 			new_fltr.src = hw_vsi_id;
43975eda8afdSAkeem G Abodunrin 		} else {
43985eda8afdSAkeem G Abodunrin 			new_fltr.flag |= ICE_FLTR_RX;
43995eda8afdSAkeem G Abodunrin 			new_fltr.src = hw->port_info->lport;
44005eda8afdSAkeem G Abodunrin 		}
44015eda8afdSAkeem G Abodunrin 
44025eda8afdSAkeem G Abodunrin 		new_fltr.fltr_act = ICE_FWD_TO_VSI;
44035eda8afdSAkeem G Abodunrin 		new_fltr.vsi_handle = vsi_handle;
44045eda8afdSAkeem G Abodunrin 		new_fltr.fwd_id.hw_vsi_id = hw_vsi_id;
44055eda8afdSAkeem G Abodunrin 		f_list_entry.fltr_info = new_fltr;
44065eda8afdSAkeem G Abodunrin 
44075eda8afdSAkeem G Abodunrin 		status = ice_add_rule_internal(hw, recipe_id, &f_list_entry);
44085eda8afdSAkeem G Abodunrin 		if (status)
44095eda8afdSAkeem G Abodunrin 			goto set_promisc_exit;
44105eda8afdSAkeem G Abodunrin 	}
44115eda8afdSAkeem G Abodunrin 
44125eda8afdSAkeem G Abodunrin set_promisc_exit:
44135eda8afdSAkeem G Abodunrin 	return status;
44145eda8afdSAkeem G Abodunrin }
44155eda8afdSAkeem G Abodunrin 
44165eda8afdSAkeem G Abodunrin /**
44175eda8afdSAkeem G Abodunrin  * ice_set_vlan_vsi_promisc
44185eda8afdSAkeem G Abodunrin  * @hw: pointer to the hardware structure
44195eda8afdSAkeem G Abodunrin  * @vsi_handle: VSI handle to configure
44205eda8afdSAkeem G Abodunrin  * @promisc_mask: mask of promiscuous config bits
44215eda8afdSAkeem G Abodunrin  * @rm_vlan_promisc: Clear VLANs VSI promisc mode
44225eda8afdSAkeem G Abodunrin  *
44235eda8afdSAkeem G Abodunrin  * Configure VSI with all associated VLANs to given promiscuous mode(s)
44245eda8afdSAkeem G Abodunrin  */
44255e24d598STony Nguyen int
44265eda8afdSAkeem G Abodunrin ice_set_vlan_vsi_promisc(struct ice_hw *hw, u16 vsi_handle, u8 promisc_mask,
44275eda8afdSAkeem G Abodunrin 			 bool rm_vlan_promisc)
44285eda8afdSAkeem G Abodunrin {
44295eda8afdSAkeem G Abodunrin 	struct ice_switch_info *sw = hw->switch_info;
44305eda8afdSAkeem G Abodunrin 	struct ice_fltr_list_entry *list_itr, *tmp;
44315eda8afdSAkeem G Abodunrin 	struct list_head vsi_list_head;
44325eda8afdSAkeem G Abodunrin 	struct list_head *vlan_head;
44335eda8afdSAkeem G Abodunrin 	struct mutex *vlan_lock; /* Lock to protect filter rule list */
44345eda8afdSAkeem G Abodunrin 	u16 vlan_id;
44355518ac2aSTony Nguyen 	int status;
44365eda8afdSAkeem G Abodunrin 
44375eda8afdSAkeem G Abodunrin 	INIT_LIST_HEAD(&vsi_list_head);
44385eda8afdSAkeem G Abodunrin 	vlan_lock = &sw->recp_list[ICE_SW_LKUP_VLAN].filt_rule_lock;
44395eda8afdSAkeem G Abodunrin 	vlan_head = &sw->recp_list[ICE_SW_LKUP_VLAN].filt_rules;
44405eda8afdSAkeem G Abodunrin 	mutex_lock(vlan_lock);
44415eda8afdSAkeem G Abodunrin 	status = ice_add_to_vsi_fltr_list(hw, vsi_handle, vlan_head,
44425eda8afdSAkeem G Abodunrin 					  &vsi_list_head);
44435eda8afdSAkeem G Abodunrin 	mutex_unlock(vlan_lock);
44445eda8afdSAkeem G Abodunrin 	if (status)
44455eda8afdSAkeem G Abodunrin 		goto free_fltr_list;
44465eda8afdSAkeem G Abodunrin 
44475eda8afdSAkeem G Abodunrin 	list_for_each_entry(list_itr, &vsi_list_head, list_entry) {
4448ffa9ed86SGrzegorz Siwik 		/* Avoid enabling or disabling VLAN zero twice when in double
4449ffa9ed86SGrzegorz Siwik 		 * VLAN mode
4450ffa9ed86SGrzegorz Siwik 		 */
4451ffa9ed86SGrzegorz Siwik 		if (ice_is_dvm_ena(hw) &&
4452ffa9ed86SGrzegorz Siwik 		    list_itr->fltr_info.l_data.vlan.tpid == 0)
4453ffa9ed86SGrzegorz Siwik 			continue;
4454ffa9ed86SGrzegorz Siwik 
44555eda8afdSAkeem G Abodunrin 		vlan_id = list_itr->fltr_info.l_data.vlan.vlan_id;
44565eda8afdSAkeem G Abodunrin 		if (rm_vlan_promisc)
44575eda8afdSAkeem G Abodunrin 			status = ice_clear_vsi_promisc(hw, vsi_handle,
44585eda8afdSAkeem G Abodunrin 						       promisc_mask, vlan_id);
44595eda8afdSAkeem G Abodunrin 		else
44605eda8afdSAkeem G Abodunrin 			status = ice_set_vsi_promisc(hw, vsi_handle,
44615eda8afdSAkeem G Abodunrin 						     promisc_mask, vlan_id);
4462*11e551a2SGrzegorz Siwik 		if (status && status != -EEXIST)
44635eda8afdSAkeem G Abodunrin 			break;
44645eda8afdSAkeem G Abodunrin 	}
44655eda8afdSAkeem G Abodunrin 
44665eda8afdSAkeem G Abodunrin free_fltr_list:
44675eda8afdSAkeem G Abodunrin 	list_for_each_entry_safe(list_itr, tmp, &vsi_list_head, list_entry) {
44685eda8afdSAkeem G Abodunrin 		list_del(&list_itr->list_entry);
44695eda8afdSAkeem G Abodunrin 		devm_kfree(ice_hw_to_dev(hw), list_itr);
44705eda8afdSAkeem G Abodunrin 	}
44715eda8afdSAkeem G Abodunrin 	return status;
44725eda8afdSAkeem G Abodunrin }
44735eda8afdSAkeem G Abodunrin 
44745eda8afdSAkeem G Abodunrin /**
44759daf8208SAnirudh Venkataramanan  * ice_remove_vsi_lkup_fltr - Remove lookup type filters for a VSI
44769daf8208SAnirudh Venkataramanan  * @hw: pointer to the hardware structure
44775726ca0eSAnirudh Venkataramanan  * @vsi_handle: VSI handle to remove filters from
44789daf8208SAnirudh Venkataramanan  * @lkup: switch rule filter lookup type
44799daf8208SAnirudh Venkataramanan  */
44809daf8208SAnirudh Venkataramanan static void
44815726ca0eSAnirudh Venkataramanan ice_remove_vsi_lkup_fltr(struct ice_hw *hw, u16 vsi_handle,
44829daf8208SAnirudh Venkataramanan 			 enum ice_sw_lkup_type lkup)
44839daf8208SAnirudh Venkataramanan {
44849daf8208SAnirudh Venkataramanan 	struct ice_switch_info *sw = hw->switch_info;
44859daf8208SAnirudh Venkataramanan 	struct ice_fltr_list_entry *fm_entry;
44869daf8208SAnirudh Venkataramanan 	struct list_head remove_list_head;
448780d144c9SAnirudh Venkataramanan 	struct list_head *rule_head;
44889daf8208SAnirudh Venkataramanan 	struct ice_fltr_list_entry *tmp;
448980d144c9SAnirudh Venkataramanan 	struct mutex *rule_lock;	/* Lock to protect filter rule list */
44905e24d598STony Nguyen 	int status;
44919daf8208SAnirudh Venkataramanan 
44929daf8208SAnirudh Venkataramanan 	INIT_LIST_HEAD(&remove_list_head);
449380d144c9SAnirudh Venkataramanan 	rule_lock = &sw->recp_list[lkup].filt_rule_lock;
449480d144c9SAnirudh Venkataramanan 	rule_head = &sw->recp_list[lkup].filt_rules;
449580d144c9SAnirudh Venkataramanan 	mutex_lock(rule_lock);
44965726ca0eSAnirudh Venkataramanan 	status = ice_add_to_vsi_fltr_list(hw, vsi_handle, rule_head,
449780d144c9SAnirudh Venkataramanan 					  &remove_list_head);
449880d144c9SAnirudh Venkataramanan 	mutex_unlock(rule_lock);
449980d144c9SAnirudh Venkataramanan 	if (status)
4500b7eeb527SRobert Malz 		goto free_fltr_list;
450180d144c9SAnirudh Venkataramanan 
45029daf8208SAnirudh Venkataramanan 	switch (lkup) {
45039daf8208SAnirudh Venkataramanan 	case ICE_SW_LKUP_MAC:
45049daf8208SAnirudh Venkataramanan 		ice_remove_mac(hw, &remove_list_head);
45059daf8208SAnirudh Venkataramanan 		break;
45069daf8208SAnirudh Venkataramanan 	case ICE_SW_LKUP_VLAN:
4507d76a60baSAnirudh Venkataramanan 		ice_remove_vlan(hw, &remove_list_head);
4508d76a60baSAnirudh Venkataramanan 		break;
45095eda8afdSAkeem G Abodunrin 	case ICE_SW_LKUP_PROMISC:
45105eda8afdSAkeem G Abodunrin 	case ICE_SW_LKUP_PROMISC_VLAN:
45115eda8afdSAkeem G Abodunrin 		ice_remove_promisc(hw, lkup, &remove_list_head);
45125eda8afdSAkeem G Abodunrin 		break;
45139daf8208SAnirudh Venkataramanan 	case ICE_SW_LKUP_MAC_VLAN:
45149daf8208SAnirudh Venkataramanan 	case ICE_SW_LKUP_ETHERTYPE:
45159daf8208SAnirudh Venkataramanan 	case ICE_SW_LKUP_ETHERTYPE_MAC:
45169daf8208SAnirudh Venkataramanan 	case ICE_SW_LKUP_DFLT:
451780d144c9SAnirudh Venkataramanan 	case ICE_SW_LKUP_LAST:
451880d144c9SAnirudh Venkataramanan 	default:
451980d144c9SAnirudh Venkataramanan 		ice_debug(hw, ICE_DBG_SW, "Unsupported lookup type %d\n", lkup);
45209daf8208SAnirudh Venkataramanan 		break;
45219daf8208SAnirudh Venkataramanan 	}
45229daf8208SAnirudh Venkataramanan 
4523b7eeb527SRobert Malz free_fltr_list:
45249daf8208SAnirudh Venkataramanan 	list_for_each_entry_safe(fm_entry, tmp, &remove_list_head, list_entry) {
45259daf8208SAnirudh Venkataramanan 		list_del(&fm_entry->list_entry);
45269daf8208SAnirudh Venkataramanan 		devm_kfree(ice_hw_to_dev(hw), fm_entry);
45279daf8208SAnirudh Venkataramanan 	}
45289daf8208SAnirudh Venkataramanan }
45299daf8208SAnirudh Venkataramanan 
45309daf8208SAnirudh Venkataramanan /**
45319daf8208SAnirudh Venkataramanan  * ice_remove_vsi_fltr - Remove all filters for a VSI
45329daf8208SAnirudh Venkataramanan  * @hw: pointer to the hardware structure
45335726ca0eSAnirudh Venkataramanan  * @vsi_handle: VSI handle to remove filters from
45349daf8208SAnirudh Venkataramanan  */
45355726ca0eSAnirudh Venkataramanan void ice_remove_vsi_fltr(struct ice_hw *hw, u16 vsi_handle)
45369daf8208SAnirudh Venkataramanan {
45375726ca0eSAnirudh Venkataramanan 	ice_remove_vsi_lkup_fltr(hw, vsi_handle, ICE_SW_LKUP_MAC);
45385726ca0eSAnirudh Venkataramanan 	ice_remove_vsi_lkup_fltr(hw, vsi_handle, ICE_SW_LKUP_MAC_VLAN);
45395726ca0eSAnirudh Venkataramanan 	ice_remove_vsi_lkup_fltr(hw, vsi_handle, ICE_SW_LKUP_PROMISC);
45405726ca0eSAnirudh Venkataramanan 	ice_remove_vsi_lkup_fltr(hw, vsi_handle, ICE_SW_LKUP_VLAN);
45415726ca0eSAnirudh Venkataramanan 	ice_remove_vsi_lkup_fltr(hw, vsi_handle, ICE_SW_LKUP_DFLT);
45425726ca0eSAnirudh Venkataramanan 	ice_remove_vsi_lkup_fltr(hw, vsi_handle, ICE_SW_LKUP_ETHERTYPE);
45435726ca0eSAnirudh Venkataramanan 	ice_remove_vsi_lkup_fltr(hw, vsi_handle, ICE_SW_LKUP_ETHERTYPE_MAC);
45445726ca0eSAnirudh Venkataramanan 	ice_remove_vsi_lkup_fltr(hw, vsi_handle, ICE_SW_LKUP_PROMISC_VLAN);
45459daf8208SAnirudh Venkataramanan }
45460f9d5027SAnirudh Venkataramanan 
45470f9d5027SAnirudh Venkataramanan /**
4548148beb61SHenry Tieman  * ice_alloc_res_cntr - allocating resource counter
4549148beb61SHenry Tieman  * @hw: pointer to the hardware structure
4550148beb61SHenry Tieman  * @type: type of resource
4551148beb61SHenry Tieman  * @alloc_shared: if set it is shared else dedicated
4552148beb61SHenry Tieman  * @num_items: number of entries requested for FD resource type
4553148beb61SHenry Tieman  * @counter_id: counter index returned by AQ call
4554148beb61SHenry Tieman  */
45555e24d598STony Nguyen int
4556148beb61SHenry Tieman ice_alloc_res_cntr(struct ice_hw *hw, u8 type, u8 alloc_shared, u16 num_items,
4557148beb61SHenry Tieman 		   u16 *counter_id)
4558148beb61SHenry Tieman {
4559148beb61SHenry Tieman 	struct ice_aqc_alloc_free_res_elem *buf;
4560148beb61SHenry Tieman 	u16 buf_len;
45615518ac2aSTony Nguyen 	int status;
4562148beb61SHenry Tieman 
4563148beb61SHenry Tieman 	/* Allocate resource */
456466486d89SBruce Allan 	buf_len = struct_size(buf, elem, 1);
4565148beb61SHenry Tieman 	buf = kzalloc(buf_len, GFP_KERNEL);
4566148beb61SHenry Tieman 	if (!buf)
4567d54699e2STony Nguyen 		return -ENOMEM;
4568148beb61SHenry Tieman 
4569148beb61SHenry Tieman 	buf->num_elems = cpu_to_le16(num_items);
4570148beb61SHenry Tieman 	buf->res_type = cpu_to_le16(((type << ICE_AQC_RES_TYPE_S) &
4571148beb61SHenry Tieman 				      ICE_AQC_RES_TYPE_M) | alloc_shared);
4572148beb61SHenry Tieman 
4573148beb61SHenry Tieman 	status = ice_aq_alloc_free_res(hw, 1, buf, buf_len,
4574148beb61SHenry Tieman 				       ice_aqc_opc_alloc_res, NULL);
4575148beb61SHenry Tieman 	if (status)
4576148beb61SHenry Tieman 		goto exit;
4577148beb61SHenry Tieman 
4578148beb61SHenry Tieman 	*counter_id = le16_to_cpu(buf->elem[0].e.sw_resp);
4579148beb61SHenry Tieman 
4580148beb61SHenry Tieman exit:
4581148beb61SHenry Tieman 	kfree(buf);
4582148beb61SHenry Tieman 	return status;
4583148beb61SHenry Tieman }
4584148beb61SHenry Tieman 
4585148beb61SHenry Tieman /**
4586148beb61SHenry Tieman  * ice_free_res_cntr - free resource counter
4587148beb61SHenry Tieman  * @hw: pointer to the hardware structure
4588148beb61SHenry Tieman  * @type: type of resource
4589148beb61SHenry Tieman  * @alloc_shared: if set it is shared else dedicated
4590148beb61SHenry Tieman  * @num_items: number of entries to be freed for FD resource type
4591148beb61SHenry Tieman  * @counter_id: counter ID resource which needs to be freed
4592148beb61SHenry Tieman  */
45935e24d598STony Nguyen int
4594148beb61SHenry Tieman ice_free_res_cntr(struct ice_hw *hw, u8 type, u8 alloc_shared, u16 num_items,
4595148beb61SHenry Tieman 		  u16 counter_id)
4596148beb61SHenry Tieman {
4597148beb61SHenry Tieman 	struct ice_aqc_alloc_free_res_elem *buf;
4598148beb61SHenry Tieman 	u16 buf_len;
45995518ac2aSTony Nguyen 	int status;
4600148beb61SHenry Tieman 
4601148beb61SHenry Tieman 	/* Free resource */
460266486d89SBruce Allan 	buf_len = struct_size(buf, elem, 1);
4603148beb61SHenry Tieman 	buf = kzalloc(buf_len, GFP_KERNEL);
4604148beb61SHenry Tieman 	if (!buf)
4605d54699e2STony Nguyen 		return -ENOMEM;
4606148beb61SHenry Tieman 
4607148beb61SHenry Tieman 	buf->num_elems = cpu_to_le16(num_items);
4608148beb61SHenry Tieman 	buf->res_type = cpu_to_le16(((type << ICE_AQC_RES_TYPE_S) &
4609148beb61SHenry Tieman 				      ICE_AQC_RES_TYPE_M) | alloc_shared);
4610148beb61SHenry Tieman 	buf->elem[0].e.sw_resp = cpu_to_le16(counter_id);
4611148beb61SHenry Tieman 
4612148beb61SHenry Tieman 	status = ice_aq_alloc_free_res(hw, 1, buf, buf_len,
4613148beb61SHenry Tieman 				       ice_aqc_opc_free_res, NULL);
4614148beb61SHenry Tieman 	if (status)
46159228d8b2SJacob Keller 		ice_debug(hw, ICE_DBG_SW, "counter resource could not be freed\n");
4616148beb61SHenry Tieman 
4617148beb61SHenry Tieman 	kfree(buf);
4618148beb61SHenry Tieman 	return status;
4619148beb61SHenry Tieman }
4620148beb61SHenry Tieman 
4621fd2a6b71SDan Nowlin /* This is mapping table entry that maps every word within a given protocol
4622fd2a6b71SDan Nowlin  * structure to the real byte offset as per the specification of that
4623fd2a6b71SDan Nowlin  * protocol header.
4624fd2a6b71SDan Nowlin  * for example dst address is 3 words in ethertype header and corresponding
4625fd2a6b71SDan Nowlin  * bytes are 0, 2, 3 in the actual packet header and src address is at 4, 6, 8
4626fd2a6b71SDan Nowlin  * IMPORTANT: Every structure part of "ice_prot_hdr" union should have a
4627fd2a6b71SDan Nowlin  * matching entry describing its field. This needs to be updated if new
4628fd2a6b71SDan Nowlin  * structure is added to that union.
4629fd2a6b71SDan Nowlin  */
4630fd2a6b71SDan Nowlin static const struct ice_prot_ext_tbl_entry ice_prot_ext[ICE_PROTOCOL_LAST] = {
4631fd2a6b71SDan Nowlin 	{ ICE_MAC_OFOS,		{ 0, 2, 4, 6, 8, 10, 12 } },
4632fd2a6b71SDan Nowlin 	{ ICE_MAC_IL,		{ 0, 2, 4, 6, 8, 10, 12 } },
4633fd2a6b71SDan Nowlin 	{ ICE_ETYPE_OL,		{ 0 } },
463434a89775SMartyna Szapar-Mudlaw 	{ ICE_ETYPE_IL,		{ 0 } },
4635fd2a6b71SDan Nowlin 	{ ICE_VLAN_OFOS,	{ 2, 0 } },
4636fd2a6b71SDan Nowlin 	{ ICE_IPV4_OFOS,	{ 0, 2, 4, 6, 8, 10, 12, 14, 16, 18 } },
4637fd2a6b71SDan Nowlin 	{ ICE_IPV4_IL,		{ 0, 2, 4, 6, 8, 10, 12, 14, 16, 18 } },
4638fd2a6b71SDan Nowlin 	{ ICE_IPV6_OFOS,	{ 0, 2, 4, 6, 8, 10, 12, 14, 16, 18, 20, 22, 24,
4639fd2a6b71SDan Nowlin 				 26, 28, 30, 32, 34, 36, 38 } },
4640fd2a6b71SDan Nowlin 	{ ICE_IPV6_IL,		{ 0, 2, 4, 6, 8, 10, 12, 14, 16, 18, 20, 22, 24,
4641fd2a6b71SDan Nowlin 				 26, 28, 30, 32, 34, 36, 38 } },
4642fd2a6b71SDan Nowlin 	{ ICE_TCP_IL,		{ 0, 2 } },
4643fd2a6b71SDan Nowlin 	{ ICE_UDP_OF,		{ 0, 2 } },
4644fd2a6b71SDan Nowlin 	{ ICE_UDP_ILOS,		{ 0, 2 } },
46458b032a55SMichal Swiatkowski 	{ ICE_VXLAN,		{ 8, 10, 12, 14 } },
46468b032a55SMichal Swiatkowski 	{ ICE_GENEVE,		{ 8, 10, 12, 14 } },
4647f0a35040SMichal Swiatkowski 	{ ICE_NVGRE,		{ 0, 2, 4, 6 } },
46489a225f81SMarcin Szycik 	{ ICE_GTP,		{ 8, 10, 12, 14, 16, 18, 20, 22 } },
46499a225f81SMarcin Szycik 	{ ICE_GTP_NO_PAY,	{ 8, 10, 12, 14 } },
4650cd8efeeeSMarcin Szycik 	{ ICE_PPPOE,		{ 0, 2, 4, 6 } },
465106bca7c2SMartyna Szapar-Mudlaw 	{ ICE_VLAN_EX,          { 2, 0 } },
465206bca7c2SMartyna Szapar-Mudlaw 	{ ICE_VLAN_IN,          { 2, 0 } },
4653fd2a6b71SDan Nowlin };
4654fd2a6b71SDan Nowlin 
4655fd2a6b71SDan Nowlin static struct ice_protocol_entry ice_prot_id_tbl[ICE_PROTOCOL_LAST] = {
4656fd2a6b71SDan Nowlin 	{ ICE_MAC_OFOS,		ICE_MAC_OFOS_HW },
4657fd2a6b71SDan Nowlin 	{ ICE_MAC_IL,		ICE_MAC_IL_HW },
4658fd2a6b71SDan Nowlin 	{ ICE_ETYPE_OL,		ICE_ETYPE_OL_HW },
465934a89775SMartyna Szapar-Mudlaw 	{ ICE_ETYPE_IL,		ICE_ETYPE_IL_HW },
4660fd2a6b71SDan Nowlin 	{ ICE_VLAN_OFOS,	ICE_VLAN_OL_HW },
4661fd2a6b71SDan Nowlin 	{ ICE_IPV4_OFOS,	ICE_IPV4_OFOS_HW },
4662fd2a6b71SDan Nowlin 	{ ICE_IPV4_IL,		ICE_IPV4_IL_HW },
4663fd2a6b71SDan Nowlin 	{ ICE_IPV6_OFOS,	ICE_IPV6_OFOS_HW },
4664fd2a6b71SDan Nowlin 	{ ICE_IPV6_IL,		ICE_IPV6_IL_HW },
4665fd2a6b71SDan Nowlin 	{ ICE_TCP_IL,		ICE_TCP_IL_HW },
4666fd2a6b71SDan Nowlin 	{ ICE_UDP_OF,		ICE_UDP_OF_HW },
4667fd2a6b71SDan Nowlin 	{ ICE_UDP_ILOS,		ICE_UDP_ILOS_HW },
46688b032a55SMichal Swiatkowski 	{ ICE_VXLAN,		ICE_UDP_OF_HW },
46698b032a55SMichal Swiatkowski 	{ ICE_GENEVE,		ICE_UDP_OF_HW },
4670f0a35040SMichal Swiatkowski 	{ ICE_NVGRE,		ICE_GRE_OF_HW },
46719a225f81SMarcin Szycik 	{ ICE_GTP,		ICE_UDP_OF_HW },
46729a225f81SMarcin Szycik 	{ ICE_GTP_NO_PAY,	ICE_UDP_ILOS_HW },
4673cd8efeeeSMarcin Szycik 	{ ICE_PPPOE,		ICE_PPPOE_HW },
467406bca7c2SMartyna Szapar-Mudlaw 	{ ICE_VLAN_EX,          ICE_VLAN_OF_HW },
467506bca7c2SMartyna Szapar-Mudlaw 	{ ICE_VLAN_IN,          ICE_VLAN_OL_HW },
4676fd2a6b71SDan Nowlin };
4677fd2a6b71SDan Nowlin 
4678fd2a6b71SDan Nowlin /**
4679fd2a6b71SDan Nowlin  * ice_find_recp - find a recipe
4680fd2a6b71SDan Nowlin  * @hw: pointer to the hardware structure
4681fd2a6b71SDan Nowlin  * @lkup_exts: extension sequence to match
4682de6acd1cSMichal Swiatkowski  * @tun_type: type of recipe tunnel
4683fd2a6b71SDan Nowlin  *
4684fd2a6b71SDan Nowlin  * Returns index of matching recipe, or ICE_MAX_NUM_RECIPES if not found.
4685fd2a6b71SDan Nowlin  */
4686de6acd1cSMichal Swiatkowski static u16
4687de6acd1cSMichal Swiatkowski ice_find_recp(struct ice_hw *hw, struct ice_prot_lkup_ext *lkup_exts,
4688de6acd1cSMichal Swiatkowski 	      enum ice_sw_tunnel_type tun_type)
4689fd2a6b71SDan Nowlin {
4690fd2a6b71SDan Nowlin 	bool refresh_required = true;
4691fd2a6b71SDan Nowlin 	struct ice_sw_recipe *recp;
4692fd2a6b71SDan Nowlin 	u8 i;
4693fd2a6b71SDan Nowlin 
4694fd2a6b71SDan Nowlin 	/* Walk through existing recipes to find a match */
4695fd2a6b71SDan Nowlin 	recp = hw->switch_info->recp_list;
4696fd2a6b71SDan Nowlin 	for (i = 0; i < ICE_MAX_NUM_RECIPES; i++) {
4697fd2a6b71SDan Nowlin 		/* If recipe was not created for this ID, in SW bookkeeping,
4698fd2a6b71SDan Nowlin 		 * check if FW has an entry for this recipe. If the FW has an
4699fd2a6b71SDan Nowlin 		 * entry update it in our SW bookkeeping and continue with the
4700fd2a6b71SDan Nowlin 		 * matching.
4701fd2a6b71SDan Nowlin 		 */
4702fd2a6b71SDan Nowlin 		if (!recp[i].recp_created)
4703fd2a6b71SDan Nowlin 			if (ice_get_recp_frm_fw(hw,
4704fd2a6b71SDan Nowlin 						hw->switch_info->recp_list, i,
4705fd2a6b71SDan Nowlin 						&refresh_required))
4706fd2a6b71SDan Nowlin 				continue;
4707fd2a6b71SDan Nowlin 
4708fd2a6b71SDan Nowlin 		/* Skip inverse action recipes */
4709fd2a6b71SDan Nowlin 		if (recp[i].root_buf && recp[i].root_buf->content.act_ctrl &
4710fd2a6b71SDan Nowlin 		    ICE_AQ_RECIPE_ACT_INV_ACT)
4711fd2a6b71SDan Nowlin 			continue;
4712fd2a6b71SDan Nowlin 
4713fd2a6b71SDan Nowlin 		/* if number of words we are looking for match */
4714fd2a6b71SDan Nowlin 		if (lkup_exts->n_val_words == recp[i].lkup_exts.n_val_words) {
4715fd2a6b71SDan Nowlin 			struct ice_fv_word *ar = recp[i].lkup_exts.fv_words;
4716fd2a6b71SDan Nowlin 			struct ice_fv_word *be = lkup_exts->fv_words;
4717fd2a6b71SDan Nowlin 			u16 *cr = recp[i].lkup_exts.field_mask;
4718fd2a6b71SDan Nowlin 			u16 *de = lkup_exts->field_mask;
4719fd2a6b71SDan Nowlin 			bool found = true;
4720fd2a6b71SDan Nowlin 			u8 pe, qr;
4721fd2a6b71SDan Nowlin 
4722fd2a6b71SDan Nowlin 			/* ar, cr, and qr are related to the recipe words, while
4723fd2a6b71SDan Nowlin 			 * be, de, and pe are related to the lookup words
4724fd2a6b71SDan Nowlin 			 */
4725fd2a6b71SDan Nowlin 			for (pe = 0; pe < lkup_exts->n_val_words; pe++) {
4726fd2a6b71SDan Nowlin 				for (qr = 0; qr < recp[i].lkup_exts.n_val_words;
4727fd2a6b71SDan Nowlin 				     qr++) {
4728fd2a6b71SDan Nowlin 					if (ar[qr].off == be[pe].off &&
4729fd2a6b71SDan Nowlin 					    ar[qr].prot_id == be[pe].prot_id &&
4730fd2a6b71SDan Nowlin 					    cr[qr] == de[pe])
4731fd2a6b71SDan Nowlin 						/* Found the "pe"th word in the
4732fd2a6b71SDan Nowlin 						 * given recipe
4733fd2a6b71SDan Nowlin 						 */
4734fd2a6b71SDan Nowlin 						break;
4735fd2a6b71SDan Nowlin 				}
4736fd2a6b71SDan Nowlin 				/* After walking through all the words in the
4737fd2a6b71SDan Nowlin 				 * "i"th recipe if "p"th word was not found then
4738fd2a6b71SDan Nowlin 				 * this recipe is not what we are looking for.
4739fd2a6b71SDan Nowlin 				 * So break out from this loop and try the next
4740fd2a6b71SDan Nowlin 				 * recipe
4741fd2a6b71SDan Nowlin 				 */
4742fd2a6b71SDan Nowlin 				if (qr >= recp[i].lkup_exts.n_val_words) {
4743fd2a6b71SDan Nowlin 					found = false;
4744fd2a6b71SDan Nowlin 					break;
4745fd2a6b71SDan Nowlin 				}
4746fd2a6b71SDan Nowlin 			}
4747fd2a6b71SDan Nowlin 			/* If for "i"th recipe the found was never set to false
4748fd2a6b71SDan Nowlin 			 * then it means we found our match
4749de6acd1cSMichal Swiatkowski 			 * Also tun type of recipe needs to be checked
4750fd2a6b71SDan Nowlin 			 */
4751de6acd1cSMichal Swiatkowski 			if (found && recp[i].tun_type == tun_type)
4752fd2a6b71SDan Nowlin 				return i; /* Return the recipe ID */
4753fd2a6b71SDan Nowlin 		}
4754fd2a6b71SDan Nowlin 	}
4755fd2a6b71SDan Nowlin 	return ICE_MAX_NUM_RECIPES;
4756fd2a6b71SDan Nowlin }
4757fd2a6b71SDan Nowlin 
4758fd2a6b71SDan Nowlin /**
4759a1ffafb0SBrett Creeley  * ice_change_proto_id_to_dvm - change proto id in prot_id_tbl
4760a1ffafb0SBrett Creeley  *
4761a1ffafb0SBrett Creeley  * As protocol id for outer vlan is different in dvm and svm, if dvm is
4762a1ffafb0SBrett Creeley  * supported protocol array record for outer vlan has to be modified to
4763a1ffafb0SBrett Creeley  * reflect the value proper for DVM.
4764a1ffafb0SBrett Creeley  */
4765a1ffafb0SBrett Creeley void ice_change_proto_id_to_dvm(void)
4766a1ffafb0SBrett Creeley {
4767a1ffafb0SBrett Creeley 	u8 i;
4768a1ffafb0SBrett Creeley 
4769a1ffafb0SBrett Creeley 	for (i = 0; i < ARRAY_SIZE(ice_prot_id_tbl); i++)
4770a1ffafb0SBrett Creeley 		if (ice_prot_id_tbl[i].type == ICE_VLAN_OFOS &&
4771a1ffafb0SBrett Creeley 		    ice_prot_id_tbl[i].protocol_id != ICE_VLAN_OF_HW)
4772a1ffafb0SBrett Creeley 			ice_prot_id_tbl[i].protocol_id = ICE_VLAN_OF_HW;
4773a1ffafb0SBrett Creeley }
4774a1ffafb0SBrett Creeley 
4775a1ffafb0SBrett Creeley /**
4776fd2a6b71SDan Nowlin  * ice_prot_type_to_id - get protocol ID from protocol type
4777fd2a6b71SDan Nowlin  * @type: protocol type
4778fd2a6b71SDan Nowlin  * @id: pointer to variable that will receive the ID
4779fd2a6b71SDan Nowlin  *
4780fd2a6b71SDan Nowlin  * Returns true if found, false otherwise
4781fd2a6b71SDan Nowlin  */
4782fd2a6b71SDan Nowlin static bool ice_prot_type_to_id(enum ice_protocol_type type, u8 *id)
4783fd2a6b71SDan Nowlin {
4784fd2a6b71SDan Nowlin 	u8 i;
4785fd2a6b71SDan Nowlin 
4786fd2a6b71SDan Nowlin 	for (i = 0; i < ARRAY_SIZE(ice_prot_id_tbl); i++)
4787fd2a6b71SDan Nowlin 		if (ice_prot_id_tbl[i].type == type) {
4788fd2a6b71SDan Nowlin 			*id = ice_prot_id_tbl[i].protocol_id;
4789fd2a6b71SDan Nowlin 			return true;
4790fd2a6b71SDan Nowlin 		}
4791fd2a6b71SDan Nowlin 	return false;
4792fd2a6b71SDan Nowlin }
4793fd2a6b71SDan Nowlin 
4794fd2a6b71SDan Nowlin /**
4795fd2a6b71SDan Nowlin  * ice_fill_valid_words - count valid words
4796fd2a6b71SDan Nowlin  * @rule: advanced rule with lookup information
4797fd2a6b71SDan Nowlin  * @lkup_exts: byte offset extractions of the words that are valid
4798fd2a6b71SDan Nowlin  *
4799fd2a6b71SDan Nowlin  * calculate valid words in a lookup rule using mask value
4800fd2a6b71SDan Nowlin  */
4801fd2a6b71SDan Nowlin static u8
4802fd2a6b71SDan Nowlin ice_fill_valid_words(struct ice_adv_lkup_elem *rule,
4803fd2a6b71SDan Nowlin 		     struct ice_prot_lkup_ext *lkup_exts)
4804fd2a6b71SDan Nowlin {
4805fd2a6b71SDan Nowlin 	u8 j, word, prot_id, ret_val;
4806fd2a6b71SDan Nowlin 
4807fd2a6b71SDan Nowlin 	if (!ice_prot_type_to_id(rule->type, &prot_id))
4808fd2a6b71SDan Nowlin 		return 0;
4809fd2a6b71SDan Nowlin 
4810fd2a6b71SDan Nowlin 	word = lkup_exts->n_val_words;
4811fd2a6b71SDan Nowlin 
4812fd2a6b71SDan Nowlin 	for (j = 0; j < sizeof(rule->m_u) / sizeof(u16); j++)
4813fd2a6b71SDan Nowlin 		if (((u16 *)&rule->m_u)[j] &&
4814fd2a6b71SDan Nowlin 		    rule->type < ARRAY_SIZE(ice_prot_ext)) {
4815fd2a6b71SDan Nowlin 			/* No more space to accommodate */
4816fd2a6b71SDan Nowlin 			if (word >= ICE_MAX_CHAIN_WORDS)
4817fd2a6b71SDan Nowlin 				return 0;
4818fd2a6b71SDan Nowlin 			lkup_exts->fv_words[word].off =
4819fd2a6b71SDan Nowlin 				ice_prot_ext[rule->type].offs[j];
4820fd2a6b71SDan Nowlin 			lkup_exts->fv_words[word].prot_id =
4821fd2a6b71SDan Nowlin 				ice_prot_id_tbl[rule->type].protocol_id;
4822fd2a6b71SDan Nowlin 			lkup_exts->field_mask[word] =
4823fd2a6b71SDan Nowlin 				be16_to_cpu(((__force __be16 *)&rule->m_u)[j]);
4824fd2a6b71SDan Nowlin 			word++;
4825fd2a6b71SDan Nowlin 		}
4826fd2a6b71SDan Nowlin 
4827fd2a6b71SDan Nowlin 	ret_val = word - lkup_exts->n_val_words;
4828fd2a6b71SDan Nowlin 	lkup_exts->n_val_words = word;
4829fd2a6b71SDan Nowlin 
4830fd2a6b71SDan Nowlin 	return ret_val;
4831fd2a6b71SDan Nowlin }
4832fd2a6b71SDan Nowlin 
4833fd2a6b71SDan Nowlin /**
4834fd2a6b71SDan Nowlin  * ice_create_first_fit_recp_def - Create a recipe grouping
4835fd2a6b71SDan Nowlin  * @hw: pointer to the hardware structure
4836fd2a6b71SDan Nowlin  * @lkup_exts: an array of protocol header extractions
4837fd2a6b71SDan Nowlin  * @rg_list: pointer to a list that stores new recipe groups
4838fd2a6b71SDan Nowlin  * @recp_cnt: pointer to a variable that stores returned number of recipe groups
4839fd2a6b71SDan Nowlin  *
4840fd2a6b71SDan Nowlin  * Using first fit algorithm, take all the words that are still not done
4841fd2a6b71SDan Nowlin  * and start grouping them in 4-word groups. Each group makes up one
4842fd2a6b71SDan Nowlin  * recipe.
4843fd2a6b71SDan Nowlin  */
48445e24d598STony Nguyen static int
4845fd2a6b71SDan Nowlin ice_create_first_fit_recp_def(struct ice_hw *hw,
4846fd2a6b71SDan Nowlin 			      struct ice_prot_lkup_ext *lkup_exts,
4847fd2a6b71SDan Nowlin 			      struct list_head *rg_list,
4848fd2a6b71SDan Nowlin 			      u8 *recp_cnt)
4849fd2a6b71SDan Nowlin {
4850fd2a6b71SDan Nowlin 	struct ice_pref_recipe_group *grp = NULL;
4851fd2a6b71SDan Nowlin 	u8 j;
4852fd2a6b71SDan Nowlin 
4853fd2a6b71SDan Nowlin 	*recp_cnt = 0;
4854fd2a6b71SDan Nowlin 
4855fd2a6b71SDan Nowlin 	/* Walk through every word in the rule to check if it is not done. If so
4856fd2a6b71SDan Nowlin 	 * then this word needs to be part of a new recipe.
4857fd2a6b71SDan Nowlin 	 */
4858fd2a6b71SDan Nowlin 	for (j = 0; j < lkup_exts->n_val_words; j++)
4859fd2a6b71SDan Nowlin 		if (!test_bit(j, lkup_exts->done)) {
4860fd2a6b71SDan Nowlin 			if (!grp ||
4861fd2a6b71SDan Nowlin 			    grp->n_val_pairs == ICE_NUM_WORDS_RECIPE) {
4862fd2a6b71SDan Nowlin 				struct ice_recp_grp_entry *entry;
4863fd2a6b71SDan Nowlin 
4864fd2a6b71SDan Nowlin 				entry = devm_kzalloc(ice_hw_to_dev(hw),
4865fd2a6b71SDan Nowlin 						     sizeof(*entry),
4866fd2a6b71SDan Nowlin 						     GFP_KERNEL);
4867fd2a6b71SDan Nowlin 				if (!entry)
4868d54699e2STony Nguyen 					return -ENOMEM;
4869fd2a6b71SDan Nowlin 				list_add(&entry->l_entry, rg_list);
4870fd2a6b71SDan Nowlin 				grp = &entry->r_group;
4871fd2a6b71SDan Nowlin 				(*recp_cnt)++;
4872fd2a6b71SDan Nowlin 			}
4873fd2a6b71SDan Nowlin 
4874fd2a6b71SDan Nowlin 			grp->pairs[grp->n_val_pairs].prot_id =
4875fd2a6b71SDan Nowlin 				lkup_exts->fv_words[j].prot_id;
4876fd2a6b71SDan Nowlin 			grp->pairs[grp->n_val_pairs].off =
4877fd2a6b71SDan Nowlin 				lkup_exts->fv_words[j].off;
4878fd2a6b71SDan Nowlin 			grp->mask[grp->n_val_pairs] = lkup_exts->field_mask[j];
4879fd2a6b71SDan Nowlin 			grp->n_val_pairs++;
4880fd2a6b71SDan Nowlin 		}
4881fd2a6b71SDan Nowlin 
4882fd2a6b71SDan Nowlin 	return 0;
4883fd2a6b71SDan Nowlin }
4884fd2a6b71SDan Nowlin 
4885fd2a6b71SDan Nowlin /**
4886fd2a6b71SDan Nowlin  * ice_fill_fv_word_index - fill in the field vector indices for a recipe group
4887fd2a6b71SDan Nowlin  * @hw: pointer to the hardware structure
4888fd2a6b71SDan Nowlin  * @fv_list: field vector with the extraction sequence information
4889fd2a6b71SDan Nowlin  * @rg_list: recipe groupings with protocol-offset pairs
4890fd2a6b71SDan Nowlin  *
4891fd2a6b71SDan Nowlin  * Helper function to fill in the field vector indices for protocol-offset
4892fd2a6b71SDan Nowlin  * pairs. These indexes are then ultimately programmed into a recipe.
4893fd2a6b71SDan Nowlin  */
48945e24d598STony Nguyen static int
4895fd2a6b71SDan Nowlin ice_fill_fv_word_index(struct ice_hw *hw, struct list_head *fv_list,
4896fd2a6b71SDan Nowlin 		       struct list_head *rg_list)
4897fd2a6b71SDan Nowlin {
4898fd2a6b71SDan Nowlin 	struct ice_sw_fv_list_entry *fv;
4899fd2a6b71SDan Nowlin 	struct ice_recp_grp_entry *rg;
4900fd2a6b71SDan Nowlin 	struct ice_fv_word *fv_ext;
4901fd2a6b71SDan Nowlin 
4902fd2a6b71SDan Nowlin 	if (list_empty(fv_list))
4903fd2a6b71SDan Nowlin 		return 0;
4904fd2a6b71SDan Nowlin 
4905fd2a6b71SDan Nowlin 	fv = list_first_entry(fv_list, struct ice_sw_fv_list_entry,
4906fd2a6b71SDan Nowlin 			      list_entry);
4907fd2a6b71SDan Nowlin 	fv_ext = fv->fv_ptr->ew;
4908fd2a6b71SDan Nowlin 
4909fd2a6b71SDan Nowlin 	list_for_each_entry(rg, rg_list, l_entry) {
4910fd2a6b71SDan Nowlin 		u8 i;
4911fd2a6b71SDan Nowlin 
4912fd2a6b71SDan Nowlin 		for (i = 0; i < rg->r_group.n_val_pairs; i++) {
4913fd2a6b71SDan Nowlin 			struct ice_fv_word *pr;
4914fd2a6b71SDan Nowlin 			bool found = false;
4915fd2a6b71SDan Nowlin 			u16 mask;
4916fd2a6b71SDan Nowlin 			u8 j;
4917fd2a6b71SDan Nowlin 
4918fd2a6b71SDan Nowlin 			pr = &rg->r_group.pairs[i];
4919fd2a6b71SDan Nowlin 			mask = rg->r_group.mask[i];
4920fd2a6b71SDan Nowlin 
4921fd2a6b71SDan Nowlin 			for (j = 0; j < hw->blk[ICE_BLK_SW].es.fvw; j++)
4922fd2a6b71SDan Nowlin 				if (fv_ext[j].prot_id == pr->prot_id &&
4923fd2a6b71SDan Nowlin 				    fv_ext[j].off == pr->off) {
4924fd2a6b71SDan Nowlin 					found = true;
4925fd2a6b71SDan Nowlin 
4926fd2a6b71SDan Nowlin 					/* Store index of field vector */
4927fd2a6b71SDan Nowlin 					rg->fv_idx[i] = j;
4928fd2a6b71SDan Nowlin 					rg->fv_mask[i] = mask;
4929fd2a6b71SDan Nowlin 					break;
4930fd2a6b71SDan Nowlin 				}
4931fd2a6b71SDan Nowlin 
4932fd2a6b71SDan Nowlin 			/* Protocol/offset could not be found, caller gave an
4933fd2a6b71SDan Nowlin 			 * invalid pair
4934fd2a6b71SDan Nowlin 			 */
4935fd2a6b71SDan Nowlin 			if (!found)
4936d54699e2STony Nguyen 				return -EINVAL;
4937fd2a6b71SDan Nowlin 		}
4938fd2a6b71SDan Nowlin 	}
4939fd2a6b71SDan Nowlin 
4940fd2a6b71SDan Nowlin 	return 0;
4941fd2a6b71SDan Nowlin }
4942fd2a6b71SDan Nowlin 
4943fd2a6b71SDan Nowlin /**
4944fd2a6b71SDan Nowlin  * ice_find_free_recp_res_idx - find free result indexes for recipe
4945fd2a6b71SDan Nowlin  * @hw: pointer to hardware structure
4946fd2a6b71SDan Nowlin  * @profiles: bitmap of profiles that will be associated with the new recipe
4947fd2a6b71SDan Nowlin  * @free_idx: pointer to variable to receive the free index bitmap
4948fd2a6b71SDan Nowlin  *
4949fd2a6b71SDan Nowlin  * The algorithm used here is:
4950fd2a6b71SDan Nowlin  *	1. When creating a new recipe, create a set P which contains all
4951fd2a6b71SDan Nowlin  *	   Profiles that will be associated with our new recipe
4952fd2a6b71SDan Nowlin  *
4953fd2a6b71SDan Nowlin  *	2. For each Profile p in set P:
4954fd2a6b71SDan Nowlin  *	    a. Add all recipes associated with Profile p into set R
4955fd2a6b71SDan Nowlin  *	    b. Optional : PossibleIndexes &= profile[p].possibleIndexes
4956fd2a6b71SDan Nowlin  *		[initially PossibleIndexes should be 0xFFFFFFFFFFFFFFFF]
4957fd2a6b71SDan Nowlin  *		i. Or just assume they all have the same possible indexes:
4958fd2a6b71SDan Nowlin  *			44, 45, 46, 47
4959fd2a6b71SDan Nowlin  *			i.e., PossibleIndexes = 0x0000F00000000000
4960fd2a6b71SDan Nowlin  *
4961fd2a6b71SDan Nowlin  *	3. For each Recipe r in set R:
4962fd2a6b71SDan Nowlin  *	    a. UsedIndexes |= (bitwise or ) recipe[r].res_indexes
4963fd2a6b71SDan Nowlin  *	    b. FreeIndexes = UsedIndexes ^ PossibleIndexes
4964fd2a6b71SDan Nowlin  *
4965fd2a6b71SDan Nowlin  *	FreeIndexes will contain the bits indicating the indexes free for use,
4966fd2a6b71SDan Nowlin  *      then the code needs to update the recipe[r].used_result_idx_bits to
4967fd2a6b71SDan Nowlin  *      indicate which indexes were selected for use by this recipe.
4968fd2a6b71SDan Nowlin  */
4969fd2a6b71SDan Nowlin static u16
4970fd2a6b71SDan Nowlin ice_find_free_recp_res_idx(struct ice_hw *hw, const unsigned long *profiles,
4971fd2a6b71SDan Nowlin 			   unsigned long *free_idx)
4972fd2a6b71SDan Nowlin {
4973fd2a6b71SDan Nowlin 	DECLARE_BITMAP(possible_idx, ICE_MAX_FV_WORDS);
4974fd2a6b71SDan Nowlin 	DECLARE_BITMAP(recipes, ICE_MAX_NUM_RECIPES);
4975fd2a6b71SDan Nowlin 	DECLARE_BITMAP(used_idx, ICE_MAX_FV_WORDS);
4976fd2a6b71SDan Nowlin 	u16 bit;
4977fd2a6b71SDan Nowlin 
4978fd2a6b71SDan Nowlin 	bitmap_zero(recipes, ICE_MAX_NUM_RECIPES);
4979fd2a6b71SDan Nowlin 	bitmap_zero(used_idx, ICE_MAX_FV_WORDS);
4980fd2a6b71SDan Nowlin 
49812f7ee2a7SAlexander Lobakin 	bitmap_fill(possible_idx, ICE_MAX_FV_WORDS);
4982fd2a6b71SDan Nowlin 
4983fd2a6b71SDan Nowlin 	/* For each profile we are going to associate the recipe with, add the
4984fd2a6b71SDan Nowlin 	 * recipes that are associated with that profile. This will give us
4985fd2a6b71SDan Nowlin 	 * the set of recipes that our recipe may collide with. Also, determine
4986fd2a6b71SDan Nowlin 	 * what possible result indexes are usable given this set of profiles.
4987fd2a6b71SDan Nowlin 	 */
4988fd2a6b71SDan Nowlin 	for_each_set_bit(bit, profiles, ICE_MAX_NUM_PROFILES) {
4989fd2a6b71SDan Nowlin 		bitmap_or(recipes, recipes, profile_to_recipe[bit],
4990fd2a6b71SDan Nowlin 			  ICE_MAX_NUM_RECIPES);
4991fd2a6b71SDan Nowlin 		bitmap_and(possible_idx, possible_idx,
4992fd2a6b71SDan Nowlin 			   hw->switch_info->prof_res_bm[bit],
4993fd2a6b71SDan Nowlin 			   ICE_MAX_FV_WORDS);
4994fd2a6b71SDan Nowlin 	}
4995fd2a6b71SDan Nowlin 
4996fd2a6b71SDan Nowlin 	/* For each recipe that our new recipe may collide with, determine
4997fd2a6b71SDan Nowlin 	 * which indexes have been used.
4998fd2a6b71SDan Nowlin 	 */
4999fd2a6b71SDan Nowlin 	for_each_set_bit(bit, recipes, ICE_MAX_NUM_RECIPES)
5000fd2a6b71SDan Nowlin 		bitmap_or(used_idx, used_idx,
5001fd2a6b71SDan Nowlin 			  hw->switch_info->recp_list[bit].res_idxs,
5002fd2a6b71SDan Nowlin 			  ICE_MAX_FV_WORDS);
5003fd2a6b71SDan Nowlin 
5004fd2a6b71SDan Nowlin 	bitmap_xor(free_idx, used_idx, possible_idx, ICE_MAX_FV_WORDS);
5005fd2a6b71SDan Nowlin 
5006fd2a6b71SDan Nowlin 	/* return number of free indexes */
5007fd2a6b71SDan Nowlin 	return (u16)bitmap_weight(free_idx, ICE_MAX_FV_WORDS);
5008fd2a6b71SDan Nowlin }
5009fd2a6b71SDan Nowlin 
5010fd2a6b71SDan Nowlin /**
5011fd2a6b71SDan Nowlin  * ice_add_sw_recipe - function to call AQ calls to create switch recipe
5012fd2a6b71SDan Nowlin  * @hw: pointer to hardware structure
5013fd2a6b71SDan Nowlin  * @rm: recipe management list entry
5014fd2a6b71SDan Nowlin  * @profiles: bitmap of profiles that will be associated.
5015fd2a6b71SDan Nowlin  */
50165e24d598STony Nguyen static int
5017fd2a6b71SDan Nowlin ice_add_sw_recipe(struct ice_hw *hw, struct ice_sw_recipe *rm,
50188b032a55SMichal Swiatkowski 		  unsigned long *profiles)
5019fd2a6b71SDan Nowlin {
5020fd2a6b71SDan Nowlin 	DECLARE_BITMAP(result_idx_bm, ICE_MAX_FV_WORDS);
5021fd2a6b71SDan Nowlin 	struct ice_aqc_recipe_data_elem *tmp;
5022fd2a6b71SDan Nowlin 	struct ice_aqc_recipe_data_elem *buf;
5023fd2a6b71SDan Nowlin 	struct ice_recp_grp_entry *entry;
5024fd2a6b71SDan Nowlin 	u16 free_res_idx;
5025fd2a6b71SDan Nowlin 	u16 recipe_count;
5026fd2a6b71SDan Nowlin 	u8 chain_idx;
5027fd2a6b71SDan Nowlin 	u8 recps = 0;
50285518ac2aSTony Nguyen 	int status;
5029fd2a6b71SDan Nowlin 
5030fd2a6b71SDan Nowlin 	/* When more than one recipe are required, another recipe is needed to
5031fd2a6b71SDan Nowlin 	 * chain them together. Matching a tunnel metadata ID takes up one of
5032fd2a6b71SDan Nowlin 	 * the match fields in the chaining recipe reducing the number of
5033fd2a6b71SDan Nowlin 	 * chained recipes by one.
5034fd2a6b71SDan Nowlin 	 */
5035fd2a6b71SDan Nowlin 	 /* check number of free result indices */
5036fd2a6b71SDan Nowlin 	bitmap_zero(result_idx_bm, ICE_MAX_FV_WORDS);
5037fd2a6b71SDan Nowlin 	free_res_idx = ice_find_free_recp_res_idx(hw, profiles, result_idx_bm);
5038fd2a6b71SDan Nowlin 
5039fd2a6b71SDan Nowlin 	ice_debug(hw, ICE_DBG_SW, "Result idx slots: %d, need %d\n",
5040fd2a6b71SDan Nowlin 		  free_res_idx, rm->n_grp_count);
5041fd2a6b71SDan Nowlin 
5042fd2a6b71SDan Nowlin 	if (rm->n_grp_count > 1) {
5043fd2a6b71SDan Nowlin 		if (rm->n_grp_count > free_res_idx)
5044d54699e2STony Nguyen 			return -ENOSPC;
5045fd2a6b71SDan Nowlin 
5046fd2a6b71SDan Nowlin 		rm->n_grp_count++;
5047fd2a6b71SDan Nowlin 	}
5048fd2a6b71SDan Nowlin 
5049fd2a6b71SDan Nowlin 	if (rm->n_grp_count > ICE_MAX_CHAIN_RECIPE)
5050d54699e2STony Nguyen 		return -ENOSPC;
5051fd2a6b71SDan Nowlin 
5052fd2a6b71SDan Nowlin 	tmp = kcalloc(ICE_MAX_NUM_RECIPES, sizeof(*tmp), GFP_KERNEL);
5053fd2a6b71SDan Nowlin 	if (!tmp)
5054d54699e2STony Nguyen 		return -ENOMEM;
5055fd2a6b71SDan Nowlin 
5056fd2a6b71SDan Nowlin 	buf = devm_kcalloc(ice_hw_to_dev(hw), rm->n_grp_count, sizeof(*buf),
5057fd2a6b71SDan Nowlin 			   GFP_KERNEL);
5058fd2a6b71SDan Nowlin 	if (!buf) {
5059d54699e2STony Nguyen 		status = -ENOMEM;
5060fd2a6b71SDan Nowlin 		goto err_mem;
5061fd2a6b71SDan Nowlin 	}
5062fd2a6b71SDan Nowlin 
5063fd2a6b71SDan Nowlin 	bitmap_zero(rm->r_bitmap, ICE_MAX_NUM_RECIPES);
5064fd2a6b71SDan Nowlin 	recipe_count = ICE_MAX_NUM_RECIPES;
5065fd2a6b71SDan Nowlin 	status = ice_aq_get_recipe(hw, tmp, &recipe_count, ICE_SW_LKUP_MAC,
5066fd2a6b71SDan Nowlin 				   NULL);
5067fd2a6b71SDan Nowlin 	if (status || recipe_count == 0)
5068fd2a6b71SDan Nowlin 		goto err_unroll;
5069fd2a6b71SDan Nowlin 
5070fd2a6b71SDan Nowlin 	/* Allocate the recipe resources, and configure them according to the
5071fd2a6b71SDan Nowlin 	 * match fields from protocol headers and extracted field vectors.
5072fd2a6b71SDan Nowlin 	 */
5073fd2a6b71SDan Nowlin 	chain_idx = find_first_bit(result_idx_bm, ICE_MAX_FV_WORDS);
5074fd2a6b71SDan Nowlin 	list_for_each_entry(entry, &rm->rg_list, l_entry) {
5075fd2a6b71SDan Nowlin 		u8 i;
5076fd2a6b71SDan Nowlin 
5077fd2a6b71SDan Nowlin 		status = ice_alloc_recipe(hw, &entry->rid);
5078fd2a6b71SDan Nowlin 		if (status)
5079fd2a6b71SDan Nowlin 			goto err_unroll;
5080fd2a6b71SDan Nowlin 
5081fd2a6b71SDan Nowlin 		/* Clear the result index of the located recipe, as this will be
5082fd2a6b71SDan Nowlin 		 * updated, if needed, later in the recipe creation process.
5083fd2a6b71SDan Nowlin 		 */
5084fd2a6b71SDan Nowlin 		tmp[0].content.result_indx = 0;
5085fd2a6b71SDan Nowlin 
5086fd2a6b71SDan Nowlin 		buf[recps] = tmp[0];
5087fd2a6b71SDan Nowlin 		buf[recps].recipe_indx = (u8)entry->rid;
5088fd2a6b71SDan Nowlin 		/* if the recipe is a non-root recipe RID should be programmed
5089fd2a6b71SDan Nowlin 		 * as 0 for the rules to be applied correctly.
5090fd2a6b71SDan Nowlin 		 */
5091fd2a6b71SDan Nowlin 		buf[recps].content.rid = 0;
5092fd2a6b71SDan Nowlin 		memset(&buf[recps].content.lkup_indx, 0,
5093fd2a6b71SDan Nowlin 		       sizeof(buf[recps].content.lkup_indx));
5094fd2a6b71SDan Nowlin 
5095fd2a6b71SDan Nowlin 		/* All recipes use look-up index 0 to match switch ID. */
5096fd2a6b71SDan Nowlin 		buf[recps].content.lkup_indx[0] = ICE_AQ_SW_ID_LKUP_IDX;
5097fd2a6b71SDan Nowlin 		buf[recps].content.mask[0] =
5098fd2a6b71SDan Nowlin 			cpu_to_le16(ICE_AQ_SW_ID_LKUP_MASK);
5099fd2a6b71SDan Nowlin 		/* Setup lkup_indx 1..4 to INVALID/ignore and set the mask
5100fd2a6b71SDan Nowlin 		 * to be 0
5101fd2a6b71SDan Nowlin 		 */
5102fd2a6b71SDan Nowlin 		for (i = 1; i <= ICE_NUM_WORDS_RECIPE; i++) {
5103fd2a6b71SDan Nowlin 			buf[recps].content.lkup_indx[i] = 0x80;
5104fd2a6b71SDan Nowlin 			buf[recps].content.mask[i] = 0;
5105fd2a6b71SDan Nowlin 		}
5106fd2a6b71SDan Nowlin 
5107fd2a6b71SDan Nowlin 		for (i = 0; i < entry->r_group.n_val_pairs; i++) {
5108fd2a6b71SDan Nowlin 			buf[recps].content.lkup_indx[i + 1] = entry->fv_idx[i];
5109fd2a6b71SDan Nowlin 			buf[recps].content.mask[i + 1] =
5110fd2a6b71SDan Nowlin 				cpu_to_le16(entry->fv_mask[i]);
5111fd2a6b71SDan Nowlin 		}
5112fd2a6b71SDan Nowlin 
5113fd2a6b71SDan Nowlin 		if (rm->n_grp_count > 1) {
5114fd2a6b71SDan Nowlin 			/* Checks to see if there really is a valid result index
5115fd2a6b71SDan Nowlin 			 * that can be used.
5116fd2a6b71SDan Nowlin 			 */
5117fd2a6b71SDan Nowlin 			if (chain_idx >= ICE_MAX_FV_WORDS) {
5118fd2a6b71SDan Nowlin 				ice_debug(hw, ICE_DBG_SW, "No chain index available\n");
5119d54699e2STony Nguyen 				status = -ENOSPC;
5120fd2a6b71SDan Nowlin 				goto err_unroll;
5121fd2a6b71SDan Nowlin 			}
5122fd2a6b71SDan Nowlin 
5123fd2a6b71SDan Nowlin 			entry->chain_idx = chain_idx;
5124fd2a6b71SDan Nowlin 			buf[recps].content.result_indx =
5125fd2a6b71SDan Nowlin 				ICE_AQ_RECIPE_RESULT_EN |
5126fd2a6b71SDan Nowlin 				((chain_idx << ICE_AQ_RECIPE_RESULT_DATA_S) &
5127fd2a6b71SDan Nowlin 				 ICE_AQ_RECIPE_RESULT_DATA_M);
5128fd2a6b71SDan Nowlin 			clear_bit(chain_idx, result_idx_bm);
5129fd2a6b71SDan Nowlin 			chain_idx = find_first_bit(result_idx_bm,
5130fd2a6b71SDan Nowlin 						   ICE_MAX_FV_WORDS);
5131fd2a6b71SDan Nowlin 		}
5132fd2a6b71SDan Nowlin 
5133fd2a6b71SDan Nowlin 		/* fill recipe dependencies */
5134fd2a6b71SDan Nowlin 		bitmap_zero((unsigned long *)buf[recps].recipe_bitmap,
5135fd2a6b71SDan Nowlin 			    ICE_MAX_NUM_RECIPES);
5136fd2a6b71SDan Nowlin 		set_bit(buf[recps].recipe_indx,
5137fd2a6b71SDan Nowlin 			(unsigned long *)buf[recps].recipe_bitmap);
5138fd2a6b71SDan Nowlin 		buf[recps].content.act_ctrl_fwd_priority = rm->priority;
5139fd2a6b71SDan Nowlin 		recps++;
5140fd2a6b71SDan Nowlin 	}
5141fd2a6b71SDan Nowlin 
5142fd2a6b71SDan Nowlin 	if (rm->n_grp_count == 1) {
5143fd2a6b71SDan Nowlin 		rm->root_rid = buf[0].recipe_indx;
5144fd2a6b71SDan Nowlin 		set_bit(buf[0].recipe_indx, rm->r_bitmap);
5145fd2a6b71SDan Nowlin 		buf[0].content.rid = rm->root_rid | ICE_AQ_RECIPE_ID_IS_ROOT;
5146fd2a6b71SDan Nowlin 		if (sizeof(buf[0].recipe_bitmap) >= sizeof(rm->r_bitmap)) {
5147fd2a6b71SDan Nowlin 			memcpy(buf[0].recipe_bitmap, rm->r_bitmap,
5148fd2a6b71SDan Nowlin 			       sizeof(buf[0].recipe_bitmap));
5149fd2a6b71SDan Nowlin 		} else {
5150d54699e2STony Nguyen 			status = -EINVAL;
5151fd2a6b71SDan Nowlin 			goto err_unroll;
5152fd2a6b71SDan Nowlin 		}
5153fd2a6b71SDan Nowlin 		/* Applicable only for ROOT_RECIPE, set the fwd_priority for
5154fd2a6b71SDan Nowlin 		 * the recipe which is getting created if specified
5155fd2a6b71SDan Nowlin 		 * by user. Usually any advanced switch filter, which results
5156fd2a6b71SDan Nowlin 		 * into new extraction sequence, ended up creating a new recipe
5157fd2a6b71SDan Nowlin 		 * of type ROOT and usually recipes are associated with profiles
5158fd2a6b71SDan Nowlin 		 * Switch rule referreing newly created recipe, needs to have
5159fd2a6b71SDan Nowlin 		 * either/or 'fwd' or 'join' priority, otherwise switch rule
5160fd2a6b71SDan Nowlin 		 * evaluation will not happen correctly. In other words, if
5161fd2a6b71SDan Nowlin 		 * switch rule to be evaluated on priority basis, then recipe
5162fd2a6b71SDan Nowlin 		 * needs to have priority, otherwise it will be evaluated last.
5163fd2a6b71SDan Nowlin 		 */
5164fd2a6b71SDan Nowlin 		buf[0].content.act_ctrl_fwd_priority = rm->priority;
5165fd2a6b71SDan Nowlin 	} else {
5166fd2a6b71SDan Nowlin 		struct ice_recp_grp_entry *last_chain_entry;
5167fd2a6b71SDan Nowlin 		u16 rid, i;
5168fd2a6b71SDan Nowlin 
5169fd2a6b71SDan Nowlin 		/* Allocate the last recipe that will chain the outcomes of the
5170fd2a6b71SDan Nowlin 		 * other recipes together
5171fd2a6b71SDan Nowlin 		 */
5172fd2a6b71SDan Nowlin 		status = ice_alloc_recipe(hw, &rid);
5173fd2a6b71SDan Nowlin 		if (status)
5174fd2a6b71SDan Nowlin 			goto err_unroll;
5175fd2a6b71SDan Nowlin 
5176fd2a6b71SDan Nowlin 		buf[recps].recipe_indx = (u8)rid;
5177fd2a6b71SDan Nowlin 		buf[recps].content.rid = (u8)rid;
5178fd2a6b71SDan Nowlin 		buf[recps].content.rid |= ICE_AQ_RECIPE_ID_IS_ROOT;
5179fd2a6b71SDan Nowlin 		/* the new entry created should also be part of rg_list to
5180fd2a6b71SDan Nowlin 		 * make sure we have complete recipe
5181fd2a6b71SDan Nowlin 		 */
5182fd2a6b71SDan Nowlin 		last_chain_entry = devm_kzalloc(ice_hw_to_dev(hw),
5183fd2a6b71SDan Nowlin 						sizeof(*last_chain_entry),
5184fd2a6b71SDan Nowlin 						GFP_KERNEL);
5185fd2a6b71SDan Nowlin 		if (!last_chain_entry) {
5186d54699e2STony Nguyen 			status = -ENOMEM;
5187fd2a6b71SDan Nowlin 			goto err_unroll;
5188fd2a6b71SDan Nowlin 		}
5189fd2a6b71SDan Nowlin 		last_chain_entry->rid = rid;
5190fd2a6b71SDan Nowlin 		memset(&buf[recps].content.lkup_indx, 0,
5191fd2a6b71SDan Nowlin 		       sizeof(buf[recps].content.lkup_indx));
5192fd2a6b71SDan Nowlin 		/* All recipes use look-up index 0 to match switch ID. */
5193fd2a6b71SDan Nowlin 		buf[recps].content.lkup_indx[0] = ICE_AQ_SW_ID_LKUP_IDX;
5194fd2a6b71SDan Nowlin 		buf[recps].content.mask[0] =
5195fd2a6b71SDan Nowlin 			cpu_to_le16(ICE_AQ_SW_ID_LKUP_MASK);
5196fd2a6b71SDan Nowlin 		for (i = 1; i <= ICE_NUM_WORDS_RECIPE; i++) {
5197fd2a6b71SDan Nowlin 			buf[recps].content.lkup_indx[i] =
5198fd2a6b71SDan Nowlin 				ICE_AQ_RECIPE_LKUP_IGNORE;
5199fd2a6b71SDan Nowlin 			buf[recps].content.mask[i] = 0;
5200fd2a6b71SDan Nowlin 		}
5201fd2a6b71SDan Nowlin 
5202fd2a6b71SDan Nowlin 		i = 1;
5203fd2a6b71SDan Nowlin 		/* update r_bitmap with the recp that is used for chaining */
5204fd2a6b71SDan Nowlin 		set_bit(rid, rm->r_bitmap);
5205fd2a6b71SDan Nowlin 		/* this is the recipe that chains all the other recipes so it
5206fd2a6b71SDan Nowlin 		 * should not have a chaining ID to indicate the same
5207fd2a6b71SDan Nowlin 		 */
5208fd2a6b71SDan Nowlin 		last_chain_entry->chain_idx = ICE_INVAL_CHAIN_IND;
5209fd2a6b71SDan Nowlin 		list_for_each_entry(entry, &rm->rg_list, l_entry) {
5210fd2a6b71SDan Nowlin 			last_chain_entry->fv_idx[i] = entry->chain_idx;
5211fd2a6b71SDan Nowlin 			buf[recps].content.lkup_indx[i] = entry->chain_idx;
5212fd2a6b71SDan Nowlin 			buf[recps].content.mask[i++] = cpu_to_le16(0xFFFF);
5213fd2a6b71SDan Nowlin 			set_bit(entry->rid, rm->r_bitmap);
5214fd2a6b71SDan Nowlin 		}
5215fd2a6b71SDan Nowlin 		list_add(&last_chain_entry->l_entry, &rm->rg_list);
5216fd2a6b71SDan Nowlin 		if (sizeof(buf[recps].recipe_bitmap) >=
5217fd2a6b71SDan Nowlin 		    sizeof(rm->r_bitmap)) {
5218fd2a6b71SDan Nowlin 			memcpy(buf[recps].recipe_bitmap, rm->r_bitmap,
5219fd2a6b71SDan Nowlin 			       sizeof(buf[recps].recipe_bitmap));
5220fd2a6b71SDan Nowlin 		} else {
5221d54699e2STony Nguyen 			status = -EINVAL;
5222fd2a6b71SDan Nowlin 			goto err_unroll;
5223fd2a6b71SDan Nowlin 		}
5224fd2a6b71SDan Nowlin 		buf[recps].content.act_ctrl_fwd_priority = rm->priority;
5225fd2a6b71SDan Nowlin 
5226fd2a6b71SDan Nowlin 		recps++;
5227fd2a6b71SDan Nowlin 		rm->root_rid = (u8)rid;
5228fd2a6b71SDan Nowlin 	}
5229fd2a6b71SDan Nowlin 	status = ice_acquire_change_lock(hw, ICE_RES_WRITE);
5230fd2a6b71SDan Nowlin 	if (status)
5231fd2a6b71SDan Nowlin 		goto err_unroll;
5232fd2a6b71SDan Nowlin 
5233fd2a6b71SDan Nowlin 	status = ice_aq_add_recipe(hw, buf, rm->n_grp_count, NULL);
5234fd2a6b71SDan Nowlin 	ice_release_change_lock(hw);
5235fd2a6b71SDan Nowlin 	if (status)
5236fd2a6b71SDan Nowlin 		goto err_unroll;
5237fd2a6b71SDan Nowlin 
5238fd2a6b71SDan Nowlin 	/* Every recipe that just got created add it to the recipe
5239fd2a6b71SDan Nowlin 	 * book keeping list
5240fd2a6b71SDan Nowlin 	 */
5241fd2a6b71SDan Nowlin 	list_for_each_entry(entry, &rm->rg_list, l_entry) {
5242fd2a6b71SDan Nowlin 		struct ice_switch_info *sw = hw->switch_info;
5243fd2a6b71SDan Nowlin 		bool is_root, idx_found = false;
5244fd2a6b71SDan Nowlin 		struct ice_sw_recipe *recp;
5245fd2a6b71SDan Nowlin 		u16 idx, buf_idx = 0;
5246fd2a6b71SDan Nowlin 
5247fd2a6b71SDan Nowlin 		/* find buffer index for copying some data */
5248fd2a6b71SDan Nowlin 		for (idx = 0; idx < rm->n_grp_count; idx++)
5249fd2a6b71SDan Nowlin 			if (buf[idx].recipe_indx == entry->rid) {
5250fd2a6b71SDan Nowlin 				buf_idx = idx;
5251fd2a6b71SDan Nowlin 				idx_found = true;
5252fd2a6b71SDan Nowlin 			}
5253fd2a6b71SDan Nowlin 
5254fd2a6b71SDan Nowlin 		if (!idx_found) {
5255d54699e2STony Nguyen 			status = -EIO;
5256fd2a6b71SDan Nowlin 			goto err_unroll;
5257fd2a6b71SDan Nowlin 		}
5258fd2a6b71SDan Nowlin 
5259fd2a6b71SDan Nowlin 		recp = &sw->recp_list[entry->rid];
5260fd2a6b71SDan Nowlin 		is_root = (rm->root_rid == entry->rid);
5261fd2a6b71SDan Nowlin 		recp->is_root = is_root;
5262fd2a6b71SDan Nowlin 
5263fd2a6b71SDan Nowlin 		recp->root_rid = entry->rid;
5264fd2a6b71SDan Nowlin 		recp->big_recp = (is_root && rm->n_grp_count > 1);
5265fd2a6b71SDan Nowlin 
5266fd2a6b71SDan Nowlin 		memcpy(&recp->ext_words, entry->r_group.pairs,
5267fd2a6b71SDan Nowlin 		       entry->r_group.n_val_pairs * sizeof(struct ice_fv_word));
5268fd2a6b71SDan Nowlin 
5269fd2a6b71SDan Nowlin 		memcpy(recp->r_bitmap, buf[buf_idx].recipe_bitmap,
5270fd2a6b71SDan Nowlin 		       sizeof(recp->r_bitmap));
5271fd2a6b71SDan Nowlin 
5272fd2a6b71SDan Nowlin 		/* Copy non-result fv index values and masks to recipe. This
5273fd2a6b71SDan Nowlin 		 * call will also update the result recipe bitmask.
5274fd2a6b71SDan Nowlin 		 */
5275fd2a6b71SDan Nowlin 		ice_collect_result_idx(&buf[buf_idx], recp);
5276fd2a6b71SDan Nowlin 
5277fd2a6b71SDan Nowlin 		/* for non-root recipes, also copy to the root, this allows
5278fd2a6b71SDan Nowlin 		 * easier matching of a complete chained recipe
5279fd2a6b71SDan Nowlin 		 */
5280fd2a6b71SDan Nowlin 		if (!is_root)
5281fd2a6b71SDan Nowlin 			ice_collect_result_idx(&buf[buf_idx],
5282fd2a6b71SDan Nowlin 					       &sw->recp_list[rm->root_rid]);
5283fd2a6b71SDan Nowlin 
5284fd2a6b71SDan Nowlin 		recp->n_ext_words = entry->r_group.n_val_pairs;
5285fd2a6b71SDan Nowlin 		recp->chain_idx = entry->chain_idx;
5286fd2a6b71SDan Nowlin 		recp->priority = buf[buf_idx].content.act_ctrl_fwd_priority;
5287fd2a6b71SDan Nowlin 		recp->n_grp_count = rm->n_grp_count;
52888b032a55SMichal Swiatkowski 		recp->tun_type = rm->tun_type;
5289fd2a6b71SDan Nowlin 		recp->recp_created = true;
5290fd2a6b71SDan Nowlin 	}
5291fd2a6b71SDan Nowlin 	rm->root_buf = buf;
5292fd2a6b71SDan Nowlin 	kfree(tmp);
5293fd2a6b71SDan Nowlin 	return status;
5294fd2a6b71SDan Nowlin 
5295fd2a6b71SDan Nowlin err_unroll:
5296fd2a6b71SDan Nowlin err_mem:
5297fd2a6b71SDan Nowlin 	kfree(tmp);
5298fd2a6b71SDan Nowlin 	devm_kfree(ice_hw_to_dev(hw), buf);
5299fd2a6b71SDan Nowlin 	return status;
5300fd2a6b71SDan Nowlin }
5301fd2a6b71SDan Nowlin 
5302fd2a6b71SDan Nowlin /**
5303fd2a6b71SDan Nowlin  * ice_create_recipe_group - creates recipe group
5304fd2a6b71SDan Nowlin  * @hw: pointer to hardware structure
5305fd2a6b71SDan Nowlin  * @rm: recipe management list entry
5306fd2a6b71SDan Nowlin  * @lkup_exts: lookup elements
5307fd2a6b71SDan Nowlin  */
53085e24d598STony Nguyen static int
5309fd2a6b71SDan Nowlin ice_create_recipe_group(struct ice_hw *hw, struct ice_sw_recipe *rm,
5310fd2a6b71SDan Nowlin 			struct ice_prot_lkup_ext *lkup_exts)
5311fd2a6b71SDan Nowlin {
5312fd2a6b71SDan Nowlin 	u8 recp_count = 0;
53135518ac2aSTony Nguyen 	int status;
5314fd2a6b71SDan Nowlin 
5315fd2a6b71SDan Nowlin 	rm->n_grp_count = 0;
5316fd2a6b71SDan Nowlin 
5317fd2a6b71SDan Nowlin 	/* Create recipes for words that are marked not done by packing them
5318fd2a6b71SDan Nowlin 	 * as best fit.
5319fd2a6b71SDan Nowlin 	 */
5320fd2a6b71SDan Nowlin 	status = ice_create_first_fit_recp_def(hw, lkup_exts,
5321fd2a6b71SDan Nowlin 					       &rm->rg_list, &recp_count);
5322fd2a6b71SDan Nowlin 	if (!status) {
5323fd2a6b71SDan Nowlin 		rm->n_grp_count += recp_count;
5324fd2a6b71SDan Nowlin 		rm->n_ext_words = lkup_exts->n_val_words;
5325fd2a6b71SDan Nowlin 		memcpy(&rm->ext_words, lkup_exts->fv_words,
5326fd2a6b71SDan Nowlin 		       sizeof(rm->ext_words));
5327fd2a6b71SDan Nowlin 		memcpy(rm->word_masks, lkup_exts->field_mask,
5328fd2a6b71SDan Nowlin 		       sizeof(rm->word_masks));
5329fd2a6b71SDan Nowlin 	}
5330fd2a6b71SDan Nowlin 
5331fd2a6b71SDan Nowlin 	return status;
5332fd2a6b71SDan Nowlin }
5333fd2a6b71SDan Nowlin 
5334fd2a6b71SDan Nowlin /**
53358b032a55SMichal Swiatkowski  * ice_tun_type_match_word - determine if tun type needs a match mask
53368b032a55SMichal Swiatkowski  * @tun_type: tunnel type
53378b032a55SMichal Swiatkowski  * @mask: mask to be used for the tunnel
53388b032a55SMichal Swiatkowski  */
53398b032a55SMichal Swiatkowski static bool ice_tun_type_match_word(enum ice_sw_tunnel_type tun_type, u16 *mask)
53408b032a55SMichal Swiatkowski {
53418b032a55SMichal Swiatkowski 	switch (tun_type) {
53428b032a55SMichal Swiatkowski 	case ICE_SW_TUN_GENEVE:
53438b032a55SMichal Swiatkowski 	case ICE_SW_TUN_VXLAN:
5344f0a35040SMichal Swiatkowski 	case ICE_SW_TUN_NVGRE:
53459a225f81SMarcin Szycik 	case ICE_SW_TUN_GTPU:
53469a225f81SMarcin Szycik 	case ICE_SW_TUN_GTPC:
53478b032a55SMichal Swiatkowski 		*mask = ICE_TUN_FLAG_MASK;
53488b032a55SMichal Swiatkowski 		return true;
53498b032a55SMichal Swiatkowski 
53508b032a55SMichal Swiatkowski 	default:
53518b032a55SMichal Swiatkowski 		*mask = 0;
53528b032a55SMichal Swiatkowski 		return false;
53538b032a55SMichal Swiatkowski 	}
53548b032a55SMichal Swiatkowski }
53558b032a55SMichal Swiatkowski 
53568b032a55SMichal Swiatkowski /**
53578b032a55SMichal Swiatkowski  * ice_add_special_words - Add words that are not protocols, such as metadata
53588b032a55SMichal Swiatkowski  * @rinfo: other information regarding the rule e.g. priority and action info
53598b032a55SMichal Swiatkowski  * @lkup_exts: lookup word structure
5360ea71b967SMartyna Szapar-Mudlaw  * @dvm_ena: is double VLAN mode enabled
53618b032a55SMichal Swiatkowski  */
5362d54699e2STony Nguyen static int
53638b032a55SMichal Swiatkowski ice_add_special_words(struct ice_adv_rule_info *rinfo,
5364ea71b967SMartyna Szapar-Mudlaw 		      struct ice_prot_lkup_ext *lkup_exts, bool dvm_ena)
53658b032a55SMichal Swiatkowski {
53668b032a55SMichal Swiatkowski 	u16 mask;
53678b032a55SMichal Swiatkowski 
53688b032a55SMichal Swiatkowski 	/* If this is a tunneled packet, then add recipe index to match the
53698b032a55SMichal Swiatkowski 	 * tunnel bit in the packet metadata flags.
53708b032a55SMichal Swiatkowski 	 */
53718b032a55SMichal Swiatkowski 	if (ice_tun_type_match_word(rinfo->tun_type, &mask)) {
53728b032a55SMichal Swiatkowski 		if (lkup_exts->n_val_words < ICE_MAX_CHAIN_WORDS) {
53738b032a55SMichal Swiatkowski 			u8 word = lkup_exts->n_val_words++;
53748b032a55SMichal Swiatkowski 
53758b032a55SMichal Swiatkowski 			lkup_exts->fv_words[word].prot_id = ICE_META_DATA_ID_HW;
53768b032a55SMichal Swiatkowski 			lkup_exts->fv_words[word].off = ICE_TUN_FLAG_MDID_OFF;
53778b032a55SMichal Swiatkowski 			lkup_exts->field_mask[word] = mask;
53788b032a55SMichal Swiatkowski 		} else {
5379d54699e2STony Nguyen 			return -ENOSPC;
53808b032a55SMichal Swiatkowski 		}
53818b032a55SMichal Swiatkowski 	}
53828b032a55SMichal Swiatkowski 
5383ea71b967SMartyna Szapar-Mudlaw 	if (rinfo->vlan_type != 0 && dvm_ena) {
5384ea71b967SMartyna Szapar-Mudlaw 		if (lkup_exts->n_val_words < ICE_MAX_CHAIN_WORDS) {
5385ea71b967SMartyna Szapar-Mudlaw 			u8 word = lkup_exts->n_val_words++;
5386ea71b967SMartyna Szapar-Mudlaw 
5387ea71b967SMartyna Szapar-Mudlaw 			lkup_exts->fv_words[word].prot_id = ICE_META_DATA_ID_HW;
5388ea71b967SMartyna Szapar-Mudlaw 			lkup_exts->fv_words[word].off = ICE_VLAN_FLAG_MDID_OFF;
5389ea71b967SMartyna Szapar-Mudlaw 			lkup_exts->field_mask[word] =
5390ea71b967SMartyna Szapar-Mudlaw 					ICE_PKT_FLAGS_0_TO_15_VLAN_FLAGS_MASK;
5391ea71b967SMartyna Szapar-Mudlaw 		} else {
5392ea71b967SMartyna Szapar-Mudlaw 			return -ENOSPC;
5393ea71b967SMartyna Szapar-Mudlaw 		}
5394ea71b967SMartyna Szapar-Mudlaw 	}
5395ea71b967SMartyna Szapar-Mudlaw 
53968b032a55SMichal Swiatkowski 	return 0;
53978b032a55SMichal Swiatkowski }
53988b032a55SMichal Swiatkowski 
5399fd2a6b71SDan Nowlin /* ice_get_compat_fv_bitmap - Get compatible field vector bitmap for rule
5400fd2a6b71SDan Nowlin  * @hw: pointer to hardware structure
5401fd2a6b71SDan Nowlin  * @rinfo: other information regarding the rule e.g. priority and action info
5402fd2a6b71SDan Nowlin  * @bm: pointer to memory for returning the bitmap of field vectors
5403fd2a6b71SDan Nowlin  */
5404fd2a6b71SDan Nowlin static void
5405fd2a6b71SDan Nowlin ice_get_compat_fv_bitmap(struct ice_hw *hw, struct ice_adv_rule_info *rinfo,
5406fd2a6b71SDan Nowlin 			 unsigned long *bm)
5407fd2a6b71SDan Nowlin {
54088b032a55SMichal Swiatkowski 	enum ice_prof_type prof_type;
54098b032a55SMichal Swiatkowski 
5410fd2a6b71SDan Nowlin 	bitmap_zero(bm, ICE_MAX_NUM_PROFILES);
5411fd2a6b71SDan Nowlin 
54128b032a55SMichal Swiatkowski 	switch (rinfo->tun_type) {
54138b032a55SMichal Swiatkowski 	case ICE_NON_TUN:
54148b032a55SMichal Swiatkowski 		prof_type = ICE_PROF_NON_TUN;
54158b032a55SMichal Swiatkowski 		break;
54168b032a55SMichal Swiatkowski 	case ICE_ALL_TUNNELS:
54178b032a55SMichal Swiatkowski 		prof_type = ICE_PROF_TUN_ALL;
54188b032a55SMichal Swiatkowski 		break;
54198b032a55SMichal Swiatkowski 	case ICE_SW_TUN_GENEVE:
54208b032a55SMichal Swiatkowski 	case ICE_SW_TUN_VXLAN:
54218b032a55SMichal Swiatkowski 		prof_type = ICE_PROF_TUN_UDP;
54228b032a55SMichal Swiatkowski 		break;
5423f0a35040SMichal Swiatkowski 	case ICE_SW_TUN_NVGRE:
5424f0a35040SMichal Swiatkowski 		prof_type = ICE_PROF_TUN_GRE;
5425f0a35040SMichal Swiatkowski 		break;
54269a225f81SMarcin Szycik 	case ICE_SW_TUN_GTPU:
54279a225f81SMarcin Szycik 		prof_type = ICE_PROF_TUN_GTPU;
54289a225f81SMarcin Szycik 		break;
54299a225f81SMarcin Szycik 	case ICE_SW_TUN_GTPC:
54309a225f81SMarcin Szycik 		prof_type = ICE_PROF_TUN_GTPC;
54319a225f81SMarcin Szycik 		break;
5432b70bc066SWojciech Drewek 	case ICE_SW_TUN_AND_NON_TUN:
54338b032a55SMichal Swiatkowski 	default:
54348b032a55SMichal Swiatkowski 		prof_type = ICE_PROF_ALL;
54358b032a55SMichal Swiatkowski 		break;
54368b032a55SMichal Swiatkowski 	}
54378b032a55SMichal Swiatkowski 
54388b032a55SMichal Swiatkowski 	ice_get_sw_fv_bitmap(hw, prof_type, bm);
5439fd2a6b71SDan Nowlin }
5440fd2a6b71SDan Nowlin 
5441fd2a6b71SDan Nowlin /**
5442fd2a6b71SDan Nowlin  * ice_add_adv_recipe - Add an advanced recipe that is not part of the default
5443fd2a6b71SDan Nowlin  * @hw: pointer to hardware structure
5444fd2a6b71SDan Nowlin  * @lkups: lookup elements or match criteria for the advanced recipe, one
5445fd2a6b71SDan Nowlin  *  structure per protocol header
5446fd2a6b71SDan Nowlin  * @lkups_cnt: number of protocols
5447fd2a6b71SDan Nowlin  * @rinfo: other information regarding the rule e.g. priority and action info
5448fd2a6b71SDan Nowlin  * @rid: return the recipe ID of the recipe created
5449fd2a6b71SDan Nowlin  */
54505e24d598STony Nguyen static int
5451fd2a6b71SDan Nowlin ice_add_adv_recipe(struct ice_hw *hw, struct ice_adv_lkup_elem *lkups,
5452fd2a6b71SDan Nowlin 		   u16 lkups_cnt, struct ice_adv_rule_info *rinfo, u16 *rid)
5453fd2a6b71SDan Nowlin {
5454fd2a6b71SDan Nowlin 	DECLARE_BITMAP(fv_bitmap, ICE_MAX_NUM_PROFILES);
5455fd2a6b71SDan Nowlin 	DECLARE_BITMAP(profiles, ICE_MAX_NUM_PROFILES);
5456fd2a6b71SDan Nowlin 	struct ice_prot_lkup_ext *lkup_exts;
5457fd2a6b71SDan Nowlin 	struct ice_recp_grp_entry *r_entry;
5458fd2a6b71SDan Nowlin 	struct ice_sw_fv_list_entry *fvit;
5459fd2a6b71SDan Nowlin 	struct ice_recp_grp_entry *r_tmp;
5460fd2a6b71SDan Nowlin 	struct ice_sw_fv_list_entry *tmp;
5461fd2a6b71SDan Nowlin 	struct ice_sw_recipe *rm;
54625518ac2aSTony Nguyen 	int status = 0;
5463fd2a6b71SDan Nowlin 	u8 i;
5464fd2a6b71SDan Nowlin 
5465fd2a6b71SDan Nowlin 	if (!lkups_cnt)
5466d54699e2STony Nguyen 		return -EINVAL;
5467fd2a6b71SDan Nowlin 
5468fd2a6b71SDan Nowlin 	lkup_exts = kzalloc(sizeof(*lkup_exts), GFP_KERNEL);
5469fd2a6b71SDan Nowlin 	if (!lkup_exts)
5470d54699e2STony Nguyen 		return -ENOMEM;
5471fd2a6b71SDan Nowlin 
5472fd2a6b71SDan Nowlin 	/* Determine the number of words to be matched and if it exceeds a
5473fd2a6b71SDan Nowlin 	 * recipe's restrictions
5474fd2a6b71SDan Nowlin 	 */
5475fd2a6b71SDan Nowlin 	for (i = 0; i < lkups_cnt; i++) {
5476fd2a6b71SDan Nowlin 		u16 count;
5477fd2a6b71SDan Nowlin 
5478fd2a6b71SDan Nowlin 		if (lkups[i].type >= ICE_PROTOCOL_LAST) {
5479d54699e2STony Nguyen 			status = -EIO;
5480fd2a6b71SDan Nowlin 			goto err_free_lkup_exts;
5481fd2a6b71SDan Nowlin 		}
5482fd2a6b71SDan Nowlin 
5483fd2a6b71SDan Nowlin 		count = ice_fill_valid_words(&lkups[i], lkup_exts);
5484fd2a6b71SDan Nowlin 		if (!count) {
5485d54699e2STony Nguyen 			status = -EIO;
5486fd2a6b71SDan Nowlin 			goto err_free_lkup_exts;
5487fd2a6b71SDan Nowlin 		}
5488fd2a6b71SDan Nowlin 	}
5489fd2a6b71SDan Nowlin 
5490fd2a6b71SDan Nowlin 	rm = kzalloc(sizeof(*rm), GFP_KERNEL);
5491fd2a6b71SDan Nowlin 	if (!rm) {
5492d54699e2STony Nguyen 		status = -ENOMEM;
5493fd2a6b71SDan Nowlin 		goto err_free_lkup_exts;
5494fd2a6b71SDan Nowlin 	}
5495fd2a6b71SDan Nowlin 
5496fd2a6b71SDan Nowlin 	/* Get field vectors that contain fields extracted from all the protocol
5497fd2a6b71SDan Nowlin 	 * headers being programmed.
5498fd2a6b71SDan Nowlin 	 */
5499fd2a6b71SDan Nowlin 	INIT_LIST_HEAD(&rm->fv_list);
5500fd2a6b71SDan Nowlin 	INIT_LIST_HEAD(&rm->rg_list);
5501fd2a6b71SDan Nowlin 
5502fd2a6b71SDan Nowlin 	/* Get bitmap of field vectors (profiles) that are compatible with the
5503fd2a6b71SDan Nowlin 	 * rule request; only these will be searched in the subsequent call to
5504e5dd661bSMichal Swiatkowski 	 * ice_get_sw_fv_list.
5505fd2a6b71SDan Nowlin 	 */
5506fd2a6b71SDan Nowlin 	ice_get_compat_fv_bitmap(hw, rinfo, fv_bitmap);
5507fd2a6b71SDan Nowlin 
5508e5dd661bSMichal Swiatkowski 	status = ice_get_sw_fv_list(hw, lkup_exts, fv_bitmap, &rm->fv_list);
5509fd2a6b71SDan Nowlin 	if (status)
5510fd2a6b71SDan Nowlin 		goto err_unroll;
5511fd2a6b71SDan Nowlin 
55128b032a55SMichal Swiatkowski 	/* Create any special protocol/offset pairs, such as looking at tunnel
55138b032a55SMichal Swiatkowski 	 * bits by extracting metadata
55148b032a55SMichal Swiatkowski 	 */
5515ea71b967SMartyna Szapar-Mudlaw 	status = ice_add_special_words(rinfo, lkup_exts, ice_is_dvm_ena(hw));
55168b032a55SMichal Swiatkowski 	if (status)
55178b032a55SMichal Swiatkowski 		goto err_free_lkup_exts;
55188b032a55SMichal Swiatkowski 
5519fd2a6b71SDan Nowlin 	/* Group match words into recipes using preferred recipe grouping
5520fd2a6b71SDan Nowlin 	 * criteria.
5521fd2a6b71SDan Nowlin 	 */
5522fd2a6b71SDan Nowlin 	status = ice_create_recipe_group(hw, rm, lkup_exts);
5523fd2a6b71SDan Nowlin 	if (status)
5524fd2a6b71SDan Nowlin 		goto err_unroll;
5525fd2a6b71SDan Nowlin 
5526fd2a6b71SDan Nowlin 	/* set the recipe priority if specified */
5527fd2a6b71SDan Nowlin 	rm->priority = (u8)rinfo->priority;
5528fd2a6b71SDan Nowlin 
5529fd2a6b71SDan Nowlin 	/* Find offsets from the field vector. Pick the first one for all the
5530fd2a6b71SDan Nowlin 	 * recipes.
5531fd2a6b71SDan Nowlin 	 */
5532fd2a6b71SDan Nowlin 	status = ice_fill_fv_word_index(hw, &rm->fv_list, &rm->rg_list);
5533fd2a6b71SDan Nowlin 	if (status)
5534fd2a6b71SDan Nowlin 		goto err_unroll;
5535fd2a6b71SDan Nowlin 
5536fd2a6b71SDan Nowlin 	/* get bitmap of all profiles the recipe will be associated with */
5537fd2a6b71SDan Nowlin 	bitmap_zero(profiles, ICE_MAX_NUM_PROFILES);
5538fd2a6b71SDan Nowlin 	list_for_each_entry(fvit, &rm->fv_list, list_entry) {
5539fd2a6b71SDan Nowlin 		ice_debug(hw, ICE_DBG_SW, "profile: %d\n", fvit->profile_id);
5540fd2a6b71SDan Nowlin 		set_bit((u16)fvit->profile_id, profiles);
5541fd2a6b71SDan Nowlin 	}
5542fd2a6b71SDan Nowlin 
5543fd2a6b71SDan Nowlin 	/* Look for a recipe which matches our requested fv / mask list */
5544de6acd1cSMichal Swiatkowski 	*rid = ice_find_recp(hw, lkup_exts, rinfo->tun_type);
5545fd2a6b71SDan Nowlin 	if (*rid < ICE_MAX_NUM_RECIPES)
5546fd2a6b71SDan Nowlin 		/* Success if found a recipe that match the existing criteria */
5547fd2a6b71SDan Nowlin 		goto err_unroll;
5548fd2a6b71SDan Nowlin 
5549de6acd1cSMichal Swiatkowski 	rm->tun_type = rinfo->tun_type;
5550fd2a6b71SDan Nowlin 	/* Recipe we need does not exist, add a recipe */
55518b032a55SMichal Swiatkowski 	status = ice_add_sw_recipe(hw, rm, profiles);
5552fd2a6b71SDan Nowlin 	if (status)
5553fd2a6b71SDan Nowlin 		goto err_unroll;
5554fd2a6b71SDan Nowlin 
5555fd2a6b71SDan Nowlin 	/* Associate all the recipes created with all the profiles in the
5556fd2a6b71SDan Nowlin 	 * common field vector.
5557fd2a6b71SDan Nowlin 	 */
5558fd2a6b71SDan Nowlin 	list_for_each_entry(fvit, &rm->fv_list, list_entry) {
5559fd2a6b71SDan Nowlin 		DECLARE_BITMAP(r_bitmap, ICE_MAX_NUM_RECIPES);
5560fd2a6b71SDan Nowlin 		u16 j;
5561fd2a6b71SDan Nowlin 
5562fd2a6b71SDan Nowlin 		status = ice_aq_get_recipe_to_profile(hw, fvit->profile_id,
5563fd2a6b71SDan Nowlin 						      (u8 *)r_bitmap, NULL);
5564fd2a6b71SDan Nowlin 		if (status)
5565fd2a6b71SDan Nowlin 			goto err_unroll;
5566fd2a6b71SDan Nowlin 
5567fd2a6b71SDan Nowlin 		bitmap_or(r_bitmap, r_bitmap, rm->r_bitmap,
5568fd2a6b71SDan Nowlin 			  ICE_MAX_NUM_RECIPES);
5569fd2a6b71SDan Nowlin 		status = ice_acquire_change_lock(hw, ICE_RES_WRITE);
5570fd2a6b71SDan Nowlin 		if (status)
5571fd2a6b71SDan Nowlin 			goto err_unroll;
5572fd2a6b71SDan Nowlin 
5573fd2a6b71SDan Nowlin 		status = ice_aq_map_recipe_to_profile(hw, fvit->profile_id,
5574fd2a6b71SDan Nowlin 						      (u8 *)r_bitmap,
5575fd2a6b71SDan Nowlin 						      NULL);
5576fd2a6b71SDan Nowlin 		ice_release_change_lock(hw);
5577fd2a6b71SDan Nowlin 
5578fd2a6b71SDan Nowlin 		if (status)
5579fd2a6b71SDan Nowlin 			goto err_unroll;
5580fd2a6b71SDan Nowlin 
5581fd2a6b71SDan Nowlin 		/* Update profile to recipe bitmap array */
5582fd2a6b71SDan Nowlin 		bitmap_copy(profile_to_recipe[fvit->profile_id], r_bitmap,
5583fd2a6b71SDan Nowlin 			    ICE_MAX_NUM_RECIPES);
5584fd2a6b71SDan Nowlin 
5585fd2a6b71SDan Nowlin 		/* Update recipe to profile bitmap array */
5586fd2a6b71SDan Nowlin 		for_each_set_bit(j, rm->r_bitmap, ICE_MAX_NUM_RECIPES)
5587fd2a6b71SDan Nowlin 			set_bit((u16)fvit->profile_id, recipe_to_profile[j]);
5588fd2a6b71SDan Nowlin 	}
5589fd2a6b71SDan Nowlin 
5590fd2a6b71SDan Nowlin 	*rid = rm->root_rid;
5591fd2a6b71SDan Nowlin 	memcpy(&hw->switch_info->recp_list[*rid].lkup_exts, lkup_exts,
5592fd2a6b71SDan Nowlin 	       sizeof(*lkup_exts));
5593fd2a6b71SDan Nowlin err_unroll:
5594fd2a6b71SDan Nowlin 	list_for_each_entry_safe(r_entry, r_tmp, &rm->rg_list, l_entry) {
5595fd2a6b71SDan Nowlin 		list_del(&r_entry->l_entry);
5596fd2a6b71SDan Nowlin 		devm_kfree(ice_hw_to_dev(hw), r_entry);
5597fd2a6b71SDan Nowlin 	}
5598fd2a6b71SDan Nowlin 
5599fd2a6b71SDan Nowlin 	list_for_each_entry_safe(fvit, tmp, &rm->fv_list, list_entry) {
5600fd2a6b71SDan Nowlin 		list_del(&fvit->list_entry);
5601fd2a6b71SDan Nowlin 		devm_kfree(ice_hw_to_dev(hw), fvit);
5602fd2a6b71SDan Nowlin 	}
5603fd2a6b71SDan Nowlin 
5604fd2a6b71SDan Nowlin 	if (rm->root_buf)
5605fd2a6b71SDan Nowlin 		devm_kfree(ice_hw_to_dev(hw), rm->root_buf);
5606fd2a6b71SDan Nowlin 
5607fd2a6b71SDan Nowlin 	kfree(rm);
5608fd2a6b71SDan Nowlin 
5609fd2a6b71SDan Nowlin err_free_lkup_exts:
5610fd2a6b71SDan Nowlin 	kfree(lkup_exts);
5611fd2a6b71SDan Nowlin 
5612fd2a6b71SDan Nowlin 	return status;
5613fd2a6b71SDan Nowlin }
5614fd2a6b71SDan Nowlin 
5615148beb61SHenry Tieman /**
561626395726SMartyna Szapar-Mudlaw  * ice_dummy_packet_add_vlan - insert VLAN header to dummy pkt
561726395726SMartyna Szapar-Mudlaw  *
561826395726SMartyna Szapar-Mudlaw  * @dummy_pkt: dummy packet profile pattern to which VLAN tag(s) will be added
561926395726SMartyna Szapar-Mudlaw  * @num_vlan: number of VLAN tags
562026395726SMartyna Szapar-Mudlaw  */
562126395726SMartyna Szapar-Mudlaw static struct ice_dummy_pkt_profile *
562226395726SMartyna Szapar-Mudlaw ice_dummy_packet_add_vlan(const struct ice_dummy_pkt_profile *dummy_pkt,
562326395726SMartyna Szapar-Mudlaw 			  u32 num_vlan)
562426395726SMartyna Szapar-Mudlaw {
562526395726SMartyna Szapar-Mudlaw 	struct ice_dummy_pkt_profile *profile;
562626395726SMartyna Szapar-Mudlaw 	struct ice_dummy_pkt_offsets *offsets;
562726395726SMartyna Szapar-Mudlaw 	u32 buf_len, off, etype_off, i;
562826395726SMartyna Szapar-Mudlaw 	u8 *pkt;
562926395726SMartyna Szapar-Mudlaw 
563026395726SMartyna Szapar-Mudlaw 	if (num_vlan < 1 || num_vlan > 2)
563126395726SMartyna Szapar-Mudlaw 		return ERR_PTR(-EINVAL);
563226395726SMartyna Szapar-Mudlaw 
563326395726SMartyna Szapar-Mudlaw 	off = num_vlan * VLAN_HLEN;
563426395726SMartyna Szapar-Mudlaw 
563526395726SMartyna Szapar-Mudlaw 	buf_len = array_size(num_vlan, sizeof(ice_dummy_vlan_packet_offsets)) +
563626395726SMartyna Szapar-Mudlaw 		  dummy_pkt->offsets_len;
563726395726SMartyna Szapar-Mudlaw 	offsets = kzalloc(buf_len, GFP_KERNEL);
563826395726SMartyna Szapar-Mudlaw 	if (!offsets)
563926395726SMartyna Szapar-Mudlaw 		return ERR_PTR(-ENOMEM);
564026395726SMartyna Szapar-Mudlaw 
564126395726SMartyna Szapar-Mudlaw 	offsets[0] = dummy_pkt->offsets[0];
564226395726SMartyna Szapar-Mudlaw 	if (num_vlan == 2) {
564326395726SMartyna Szapar-Mudlaw 		offsets[1] = ice_dummy_qinq_packet_offsets[0];
564426395726SMartyna Szapar-Mudlaw 		offsets[2] = ice_dummy_qinq_packet_offsets[1];
564526395726SMartyna Szapar-Mudlaw 	} else if (num_vlan == 1) {
564626395726SMartyna Szapar-Mudlaw 		offsets[1] = ice_dummy_vlan_packet_offsets[0];
564726395726SMartyna Szapar-Mudlaw 	}
564826395726SMartyna Szapar-Mudlaw 
564926395726SMartyna Szapar-Mudlaw 	for (i = 1; dummy_pkt->offsets[i].type != ICE_PROTOCOL_LAST; i++) {
565026395726SMartyna Szapar-Mudlaw 		offsets[i + num_vlan].type = dummy_pkt->offsets[i].type;
565126395726SMartyna Szapar-Mudlaw 		offsets[i + num_vlan].offset =
565226395726SMartyna Szapar-Mudlaw 			dummy_pkt->offsets[i].offset + off;
565326395726SMartyna Szapar-Mudlaw 	}
565426395726SMartyna Szapar-Mudlaw 	offsets[i + num_vlan] = dummy_pkt->offsets[i];
565526395726SMartyna Szapar-Mudlaw 
565626395726SMartyna Szapar-Mudlaw 	etype_off = dummy_pkt->offsets[1].offset;
565726395726SMartyna Szapar-Mudlaw 
565826395726SMartyna Szapar-Mudlaw 	buf_len = array_size(num_vlan, sizeof(ice_dummy_vlan_packet)) +
565926395726SMartyna Szapar-Mudlaw 		  dummy_pkt->pkt_len;
566026395726SMartyna Szapar-Mudlaw 	pkt = kzalloc(buf_len, GFP_KERNEL);
566126395726SMartyna Szapar-Mudlaw 	if (!pkt) {
566226395726SMartyna Szapar-Mudlaw 		kfree(offsets);
566326395726SMartyna Szapar-Mudlaw 		return ERR_PTR(-ENOMEM);
566426395726SMartyna Szapar-Mudlaw 	}
566526395726SMartyna Szapar-Mudlaw 
566626395726SMartyna Szapar-Mudlaw 	memcpy(pkt, dummy_pkt->pkt, etype_off);
566726395726SMartyna Szapar-Mudlaw 	memcpy(pkt + etype_off,
566826395726SMartyna Szapar-Mudlaw 	       num_vlan == 2 ? ice_dummy_qinq_packet : ice_dummy_vlan_packet,
566926395726SMartyna Szapar-Mudlaw 	       off);
567026395726SMartyna Szapar-Mudlaw 	memcpy(pkt + etype_off + off, dummy_pkt->pkt + etype_off,
567126395726SMartyna Szapar-Mudlaw 	       dummy_pkt->pkt_len - etype_off);
567226395726SMartyna Szapar-Mudlaw 
567326395726SMartyna Szapar-Mudlaw 	profile = kzalloc(sizeof(*profile), GFP_KERNEL);
567426395726SMartyna Szapar-Mudlaw 	if (!profile) {
567526395726SMartyna Szapar-Mudlaw 		kfree(offsets);
567626395726SMartyna Szapar-Mudlaw 		kfree(pkt);
567726395726SMartyna Szapar-Mudlaw 		return ERR_PTR(-ENOMEM);
567826395726SMartyna Szapar-Mudlaw 	}
567926395726SMartyna Szapar-Mudlaw 
568026395726SMartyna Szapar-Mudlaw 	profile->offsets = offsets;
568126395726SMartyna Szapar-Mudlaw 	profile->pkt = pkt;
568226395726SMartyna Szapar-Mudlaw 	profile->pkt_len = buf_len;
568326395726SMartyna Szapar-Mudlaw 	profile->match |= ICE_PKT_KMALLOC;
568426395726SMartyna Szapar-Mudlaw 
568526395726SMartyna Szapar-Mudlaw 	return profile;
568626395726SMartyna Szapar-Mudlaw }
568726395726SMartyna Szapar-Mudlaw 
568826395726SMartyna Szapar-Mudlaw /**
56890f94570dSGrishma Kotecha  * ice_find_dummy_packet - find dummy packet
56900f94570dSGrishma Kotecha  *
56910f94570dSGrishma Kotecha  * @lkups: lookup elements or match criteria for the advanced recipe, one
56920f94570dSGrishma Kotecha  *	   structure per protocol header
56930f94570dSGrishma Kotecha  * @lkups_cnt: number of protocols
56948b032a55SMichal Swiatkowski  * @tun_type: tunnel type
56951b699f81SAlexander Lobakin  *
56961b699f81SAlexander Lobakin  * Returns the &ice_dummy_pkt_profile corresponding to these lookup params.
56970f94570dSGrishma Kotecha  */
5698e33163a4SAlexander Lobakin static const struct ice_dummy_pkt_profile *
56990f94570dSGrishma Kotecha ice_find_dummy_packet(struct ice_adv_lkup_elem *lkups, u16 lkups_cnt,
57001b699f81SAlexander Lobakin 		      enum ice_sw_tunnel_type tun_type)
57010f94570dSGrishma Kotecha {
5702e33163a4SAlexander Lobakin 	const struct ice_dummy_pkt_profile *ret = ice_dummy_pkt_profiles;
570326395726SMartyna Szapar-Mudlaw 	u32 match = 0, vlan_count = 0;
57040f94570dSGrishma Kotecha 	u16 i;
57050f94570dSGrishma Kotecha 
5706e33163a4SAlexander Lobakin 	switch (tun_type) {
5707e33163a4SAlexander Lobakin 	case ICE_SW_TUN_GTPC:
5708e33163a4SAlexander Lobakin 		match |= ICE_PKT_TUN_GTPC;
5709e33163a4SAlexander Lobakin 		break;
5710e33163a4SAlexander Lobakin 	case ICE_SW_TUN_GTPU:
5711e33163a4SAlexander Lobakin 		match |= ICE_PKT_TUN_GTPU;
5712e33163a4SAlexander Lobakin 		break;
5713e33163a4SAlexander Lobakin 	case ICE_SW_TUN_NVGRE:
5714e33163a4SAlexander Lobakin 		match |= ICE_PKT_TUN_NVGRE;
5715e33163a4SAlexander Lobakin 		break;
5716e33163a4SAlexander Lobakin 	case ICE_SW_TUN_GENEVE:
5717e33163a4SAlexander Lobakin 	case ICE_SW_TUN_VXLAN:
5718e33163a4SAlexander Lobakin 		match |= ICE_PKT_TUN_UDP;
5719e33163a4SAlexander Lobakin 		break;
5720e33163a4SAlexander Lobakin 	default:
5721e33163a4SAlexander Lobakin 		break;
5722e33163a4SAlexander Lobakin 	}
5723e33163a4SAlexander Lobakin 
57240f94570dSGrishma Kotecha 	for (i = 0; i < lkups_cnt; i++) {
57250f94570dSGrishma Kotecha 		if (lkups[i].type == ICE_UDP_ILOS)
5726e33163a4SAlexander Lobakin 			match |= ICE_PKT_INNER_UDP;
57270f94570dSGrishma Kotecha 		else if (lkups[i].type == ICE_TCP_IL)
5728e33163a4SAlexander Lobakin 			match |= ICE_PKT_INNER_TCP;
57290f94570dSGrishma Kotecha 		else if (lkups[i].type == ICE_IPV6_OFOS)
5730e33163a4SAlexander Lobakin 			match |= ICE_PKT_OUTER_IPV6;
573106bca7c2SMartyna Szapar-Mudlaw 		else if (lkups[i].type == ICE_VLAN_OFOS ||
573206bca7c2SMartyna Szapar-Mudlaw 			 lkups[i].type == ICE_VLAN_EX)
573326395726SMartyna Szapar-Mudlaw 			vlan_count++;
573406bca7c2SMartyna Szapar-Mudlaw 		else if (lkups[i].type == ICE_VLAN_IN)
573526395726SMartyna Szapar-Mudlaw 			vlan_count++;
57360f94570dSGrishma Kotecha 		else if (lkups[i].type == ICE_ETYPE_OL &&
57370f94570dSGrishma Kotecha 			 lkups[i].h_u.ethertype.ethtype_id ==
57380f94570dSGrishma Kotecha 				cpu_to_be16(ICE_IPV6_ETHER_ID) &&
57390f94570dSGrishma Kotecha 			 lkups[i].m_u.ethertype.ethtype_id ==
57400f94570dSGrishma Kotecha 				cpu_to_be16(0xFFFF))
5741e33163a4SAlexander Lobakin 			match |= ICE_PKT_OUTER_IPV6;
574234a89775SMartyna Szapar-Mudlaw 		else if (lkups[i].type == ICE_ETYPE_IL &&
574334a89775SMartyna Szapar-Mudlaw 			 lkups[i].h_u.ethertype.ethtype_id ==
574434a89775SMartyna Szapar-Mudlaw 				cpu_to_be16(ICE_IPV6_ETHER_ID) &&
574534a89775SMartyna Szapar-Mudlaw 			 lkups[i].m_u.ethertype.ethtype_id ==
574634a89775SMartyna Szapar-Mudlaw 				cpu_to_be16(0xFFFF))
5747e33163a4SAlexander Lobakin 			match |= ICE_PKT_INNER_IPV6;
57489a225f81SMarcin Szycik 		else if (lkups[i].type == ICE_IPV6_IL)
5749e33163a4SAlexander Lobakin 			match |= ICE_PKT_INNER_IPV6;
57509a225f81SMarcin Szycik 		else if (lkups[i].type == ICE_GTP_NO_PAY)
5751e33163a4SAlexander Lobakin 			match |= ICE_PKT_GTP_NOPAY;
5752cd8efeeeSMarcin Szycik 		else if (lkups[i].type == ICE_PPPOE) {
5753cd8efeeeSMarcin Szycik 			match |= ICE_PKT_PPPOE;
5754cd8efeeeSMarcin Szycik 			if (lkups[i].h_u.pppoe_hdr.ppp_prot_id ==
5755cd8efeeeSMarcin Szycik 			    htons(PPP_IPV6))
5756cd8efeeeSMarcin Szycik 				match |= ICE_PKT_OUTER_IPV6;
5757cd8efeeeSMarcin Szycik 		}
57589a225f81SMarcin Szycik 	}
57599a225f81SMarcin Szycik 
5760e33163a4SAlexander Lobakin 	while (ret->match && (match & ret->match) != ret->match)
5761e33163a4SAlexander Lobakin 		ret++;
57629a225f81SMarcin Szycik 
576326395726SMartyna Szapar-Mudlaw 	if (vlan_count != 0)
576426395726SMartyna Szapar-Mudlaw 		ret = ice_dummy_packet_add_vlan(ret, vlan_count);
576526395726SMartyna Szapar-Mudlaw 
5766e33163a4SAlexander Lobakin 	return ret;
57670f94570dSGrishma Kotecha }
57680f94570dSGrishma Kotecha 
57690f94570dSGrishma Kotecha /**
57700f94570dSGrishma Kotecha  * ice_fill_adv_dummy_packet - fill a dummy packet with given match criteria
57710f94570dSGrishma Kotecha  *
57720f94570dSGrishma Kotecha  * @lkups: lookup elements or match criteria for the advanced recipe, one
57730f94570dSGrishma Kotecha  *	   structure per protocol header
57740f94570dSGrishma Kotecha  * @lkups_cnt: number of protocols
57750f94570dSGrishma Kotecha  * @s_rule: stores rule information from the match criteria
57761b699f81SAlexander Lobakin  * @profile: dummy packet profile (the template, its size and header offsets)
57770f94570dSGrishma Kotecha  */
57785e24d598STony Nguyen static int
57790f94570dSGrishma Kotecha ice_fill_adv_dummy_packet(struct ice_adv_lkup_elem *lkups, u16 lkups_cnt,
57806e1ff618SAlexander Lobakin 			  struct ice_sw_rule_lkup_rx_tx *s_rule,
57811b699f81SAlexander Lobakin 			  const struct ice_dummy_pkt_profile *profile)
57820f94570dSGrishma Kotecha {
57830f94570dSGrishma Kotecha 	u8 *pkt;
57840f94570dSGrishma Kotecha 	u16 i;
57850f94570dSGrishma Kotecha 
57860f94570dSGrishma Kotecha 	/* Start with a packet with a pre-defined/dummy content. Then, fill
57870f94570dSGrishma Kotecha 	 * in the header values to be looked up or matched.
57880f94570dSGrishma Kotecha 	 */
57896e1ff618SAlexander Lobakin 	pkt = s_rule->hdr_data;
57900f94570dSGrishma Kotecha 
57911b699f81SAlexander Lobakin 	memcpy(pkt, profile->pkt, profile->pkt_len);
57920f94570dSGrishma Kotecha 
57930f94570dSGrishma Kotecha 	for (i = 0; i < lkups_cnt; i++) {
57941b699f81SAlexander Lobakin 		const struct ice_dummy_pkt_offsets *offsets = profile->offsets;
57950f94570dSGrishma Kotecha 		enum ice_protocol_type type;
57960f94570dSGrishma Kotecha 		u16 offset = 0, len = 0, j;
57970f94570dSGrishma Kotecha 		bool found = false;
57980f94570dSGrishma Kotecha 
57990f94570dSGrishma Kotecha 		/* find the start of this layer; it should be found since this
58000f94570dSGrishma Kotecha 		 * was already checked when search for the dummy packet
58010f94570dSGrishma Kotecha 		 */
58020f94570dSGrishma Kotecha 		type = lkups[i].type;
58030f94570dSGrishma Kotecha 		for (j = 0; offsets[j].type != ICE_PROTOCOL_LAST; j++) {
58040f94570dSGrishma Kotecha 			if (type == offsets[j].type) {
58050f94570dSGrishma Kotecha 				offset = offsets[j].offset;
58060f94570dSGrishma Kotecha 				found = true;
58070f94570dSGrishma Kotecha 				break;
58080f94570dSGrishma Kotecha 			}
58090f94570dSGrishma Kotecha 		}
58100f94570dSGrishma Kotecha 		/* this should never happen in a correct calling sequence */
58110f94570dSGrishma Kotecha 		if (!found)
5812d54699e2STony Nguyen 			return -EINVAL;
58130f94570dSGrishma Kotecha 
58140f94570dSGrishma Kotecha 		switch (lkups[i].type) {
58150f94570dSGrishma Kotecha 		case ICE_MAC_OFOS:
58160f94570dSGrishma Kotecha 		case ICE_MAC_IL:
58170f94570dSGrishma Kotecha 			len = sizeof(struct ice_ether_hdr);
58180f94570dSGrishma Kotecha 			break;
58190f94570dSGrishma Kotecha 		case ICE_ETYPE_OL:
582034a89775SMartyna Szapar-Mudlaw 		case ICE_ETYPE_IL:
58210f94570dSGrishma Kotecha 			len = sizeof(struct ice_ethtype_hdr);
58220f94570dSGrishma Kotecha 			break;
58230f94570dSGrishma Kotecha 		case ICE_VLAN_OFOS:
582406bca7c2SMartyna Szapar-Mudlaw 		case ICE_VLAN_EX:
582506bca7c2SMartyna Szapar-Mudlaw 		case ICE_VLAN_IN:
58260f94570dSGrishma Kotecha 			len = sizeof(struct ice_vlan_hdr);
58270f94570dSGrishma Kotecha 			break;
58280f94570dSGrishma Kotecha 		case ICE_IPV4_OFOS:
58290f94570dSGrishma Kotecha 		case ICE_IPV4_IL:
58300f94570dSGrishma Kotecha 			len = sizeof(struct ice_ipv4_hdr);
58310f94570dSGrishma Kotecha 			break;
58320f94570dSGrishma Kotecha 		case ICE_IPV6_OFOS:
58330f94570dSGrishma Kotecha 		case ICE_IPV6_IL:
58340f94570dSGrishma Kotecha 			len = sizeof(struct ice_ipv6_hdr);
58350f94570dSGrishma Kotecha 			break;
58360f94570dSGrishma Kotecha 		case ICE_TCP_IL:
58370f94570dSGrishma Kotecha 		case ICE_UDP_OF:
58380f94570dSGrishma Kotecha 		case ICE_UDP_ILOS:
58390f94570dSGrishma Kotecha 			len = sizeof(struct ice_l4_hdr);
58400f94570dSGrishma Kotecha 			break;
58410f94570dSGrishma Kotecha 		case ICE_SCTP_IL:
58420f94570dSGrishma Kotecha 			len = sizeof(struct ice_sctp_hdr);
58430f94570dSGrishma Kotecha 			break;
5844f0a35040SMichal Swiatkowski 		case ICE_NVGRE:
5845f0a35040SMichal Swiatkowski 			len = sizeof(struct ice_nvgre_hdr);
5846f0a35040SMichal Swiatkowski 			break;
58478b032a55SMichal Swiatkowski 		case ICE_VXLAN:
58488b032a55SMichal Swiatkowski 		case ICE_GENEVE:
58498b032a55SMichal Swiatkowski 			len = sizeof(struct ice_udp_tnl_hdr);
58508b032a55SMichal Swiatkowski 			break;
58519a225f81SMarcin Szycik 		case ICE_GTP_NO_PAY:
58529a225f81SMarcin Szycik 		case ICE_GTP:
58539a225f81SMarcin Szycik 			len = sizeof(struct ice_udp_gtp_hdr);
58549a225f81SMarcin Szycik 			break;
5855cd8efeeeSMarcin Szycik 		case ICE_PPPOE:
5856cd8efeeeSMarcin Szycik 			len = sizeof(struct ice_pppoe_hdr);
5857cd8efeeeSMarcin Szycik 			break;
58580f94570dSGrishma Kotecha 		default:
5859d54699e2STony Nguyen 			return -EINVAL;
58600f94570dSGrishma Kotecha 		}
58610f94570dSGrishma Kotecha 
58620f94570dSGrishma Kotecha 		/* the length should be a word multiple */
58630f94570dSGrishma Kotecha 		if (len % ICE_BYTES_PER_WORD)
5864d54699e2STony Nguyen 			return -EIO;
58650f94570dSGrishma Kotecha 
58660f94570dSGrishma Kotecha 		/* We have the offset to the header start, the length, the
58670f94570dSGrishma Kotecha 		 * caller's header values and mask. Use this information to
58680f94570dSGrishma Kotecha 		 * copy the data into the dummy packet appropriately based on
58690f94570dSGrishma Kotecha 		 * the mask. Note that we need to only write the bits as
58700f94570dSGrishma Kotecha 		 * indicated by the mask to make sure we don't improperly write
58710f94570dSGrishma Kotecha 		 * over any significant packet data.
58720f94570dSGrishma Kotecha 		 */
587327ffa273SAlexander Lobakin 		for (j = 0; j < len / sizeof(u16); j++) {
587427ffa273SAlexander Lobakin 			u16 *ptr = (u16 *)(pkt + offset);
587527ffa273SAlexander Lobakin 			u16 mask = lkups[i].m_raw[j];
587627ffa273SAlexander Lobakin 
587727ffa273SAlexander Lobakin 			if (!mask)
587827ffa273SAlexander Lobakin 				continue;
587927ffa273SAlexander Lobakin 
588027ffa273SAlexander Lobakin 			ptr[j] = (ptr[j] & ~mask) | (lkups[i].h_raw[j] & mask);
588127ffa273SAlexander Lobakin 		}
58820f94570dSGrishma Kotecha 	}
58830f94570dSGrishma Kotecha 
58846e1ff618SAlexander Lobakin 	s_rule->hdr_len = cpu_to_le16(profile->pkt_len);
58850f94570dSGrishma Kotecha 
58860f94570dSGrishma Kotecha 	return 0;
58870f94570dSGrishma Kotecha }
58880f94570dSGrishma Kotecha 
58890f94570dSGrishma Kotecha /**
58908b032a55SMichal Swiatkowski  * ice_fill_adv_packet_tun - fill dummy packet with udp tunnel port
58918b032a55SMichal Swiatkowski  * @hw: pointer to the hardware structure
58928b032a55SMichal Swiatkowski  * @tun_type: tunnel type
58938b032a55SMichal Swiatkowski  * @pkt: dummy packet to fill in
58948b032a55SMichal Swiatkowski  * @offsets: offset info for the dummy packet
58958b032a55SMichal Swiatkowski  */
5896d54699e2STony Nguyen static int
58978b032a55SMichal Swiatkowski ice_fill_adv_packet_tun(struct ice_hw *hw, enum ice_sw_tunnel_type tun_type,
58988b032a55SMichal Swiatkowski 			u8 *pkt, const struct ice_dummy_pkt_offsets *offsets)
58998b032a55SMichal Swiatkowski {
59008b032a55SMichal Swiatkowski 	u16 open_port, i;
59018b032a55SMichal Swiatkowski 
59028b032a55SMichal Swiatkowski 	switch (tun_type) {
59038b032a55SMichal Swiatkowski 	case ICE_SW_TUN_VXLAN:
5904de6acd1cSMichal Swiatkowski 		if (!ice_get_open_tunnel_port(hw, &open_port, TNL_VXLAN))
5905d54699e2STony Nguyen 			return -EIO;
59068b032a55SMichal Swiatkowski 		break;
5907de6acd1cSMichal Swiatkowski 	case ICE_SW_TUN_GENEVE:
5908de6acd1cSMichal Swiatkowski 		if (!ice_get_open_tunnel_port(hw, &open_port, TNL_GENEVE))
5909d54699e2STony Nguyen 			return -EIO;
5910de6acd1cSMichal Swiatkowski 		break;
59118b032a55SMichal Swiatkowski 	default:
59128b032a55SMichal Swiatkowski 		/* Nothing needs to be done for this tunnel type */
59138b032a55SMichal Swiatkowski 		return 0;
59148b032a55SMichal Swiatkowski 	}
59158b032a55SMichal Swiatkowski 
59168b032a55SMichal Swiatkowski 	/* Find the outer UDP protocol header and insert the port number */
59178b032a55SMichal Swiatkowski 	for (i = 0; offsets[i].type != ICE_PROTOCOL_LAST; i++) {
59188b032a55SMichal Swiatkowski 		if (offsets[i].type == ICE_UDP_OF) {
59198b032a55SMichal Swiatkowski 			struct ice_l4_hdr *hdr;
59208b032a55SMichal Swiatkowski 			u16 offset;
59218b032a55SMichal Swiatkowski 
59228b032a55SMichal Swiatkowski 			offset = offsets[i].offset;
59238b032a55SMichal Swiatkowski 			hdr = (struct ice_l4_hdr *)&pkt[offset];
59248b032a55SMichal Swiatkowski 			hdr->dst_port = cpu_to_be16(open_port);
59258b032a55SMichal Swiatkowski 
59268b032a55SMichal Swiatkowski 			return 0;
59278b032a55SMichal Swiatkowski 		}
59288b032a55SMichal Swiatkowski 	}
59298b032a55SMichal Swiatkowski 
5930d54699e2STony Nguyen 	return -EIO;
59318b032a55SMichal Swiatkowski }
59328b032a55SMichal Swiatkowski 
59338b032a55SMichal Swiatkowski /**
5934ea71b967SMartyna Szapar-Mudlaw  * ice_fill_adv_packet_vlan - fill dummy packet with VLAN tag type
5935ea71b967SMartyna Szapar-Mudlaw  * @vlan_type: VLAN tag type
5936ea71b967SMartyna Szapar-Mudlaw  * @pkt: dummy packet to fill in
5937ea71b967SMartyna Szapar-Mudlaw  * @offsets: offset info for the dummy packet
5938ea71b967SMartyna Szapar-Mudlaw  */
5939ea71b967SMartyna Szapar-Mudlaw static int
5940ea71b967SMartyna Szapar-Mudlaw ice_fill_adv_packet_vlan(u16 vlan_type, u8 *pkt,
5941ea71b967SMartyna Szapar-Mudlaw 			 const struct ice_dummy_pkt_offsets *offsets)
5942ea71b967SMartyna Szapar-Mudlaw {
5943ea71b967SMartyna Szapar-Mudlaw 	u16 i;
5944ea71b967SMartyna Szapar-Mudlaw 
5945ea71b967SMartyna Szapar-Mudlaw 	/* Find VLAN header and insert VLAN TPID */
5946ea71b967SMartyna Szapar-Mudlaw 	for (i = 0; offsets[i].type != ICE_PROTOCOL_LAST; i++) {
5947ea71b967SMartyna Szapar-Mudlaw 		if (offsets[i].type == ICE_VLAN_OFOS ||
5948ea71b967SMartyna Szapar-Mudlaw 		    offsets[i].type == ICE_VLAN_EX) {
5949ea71b967SMartyna Szapar-Mudlaw 			struct ice_vlan_hdr *hdr;
5950ea71b967SMartyna Szapar-Mudlaw 			u16 offset;
5951ea71b967SMartyna Szapar-Mudlaw 
5952ea71b967SMartyna Szapar-Mudlaw 			offset = offsets[i].offset;
5953ea71b967SMartyna Szapar-Mudlaw 			hdr = (struct ice_vlan_hdr *)&pkt[offset];
5954ea71b967SMartyna Szapar-Mudlaw 			hdr->type = cpu_to_be16(vlan_type);
5955ea71b967SMartyna Szapar-Mudlaw 
5956ea71b967SMartyna Szapar-Mudlaw 			return 0;
5957ea71b967SMartyna Szapar-Mudlaw 		}
5958ea71b967SMartyna Szapar-Mudlaw 	}
5959ea71b967SMartyna Szapar-Mudlaw 
5960ea71b967SMartyna Szapar-Mudlaw 	return -EIO;
5961ea71b967SMartyna Szapar-Mudlaw }
5962ea71b967SMartyna Szapar-Mudlaw 
5963ea71b967SMartyna Szapar-Mudlaw /**
59640f94570dSGrishma Kotecha  * ice_find_adv_rule_entry - Search a rule entry
59650f94570dSGrishma Kotecha  * @hw: pointer to the hardware structure
59660f94570dSGrishma Kotecha  * @lkups: lookup elements or match criteria for the advanced recipe, one
59670f94570dSGrishma Kotecha  *	   structure per protocol header
59680f94570dSGrishma Kotecha  * @lkups_cnt: number of protocols
59690f94570dSGrishma Kotecha  * @recp_id: recipe ID for which we are finding the rule
59700f94570dSGrishma Kotecha  * @rinfo: other information regarding the rule e.g. priority and action info
59710f94570dSGrishma Kotecha  *
59720f94570dSGrishma Kotecha  * Helper function to search for a given advance rule entry
59730f94570dSGrishma Kotecha  * Returns pointer to entry storing the rule if found
59740f94570dSGrishma Kotecha  */
59750f94570dSGrishma Kotecha static struct ice_adv_fltr_mgmt_list_entry *
59760f94570dSGrishma Kotecha ice_find_adv_rule_entry(struct ice_hw *hw, struct ice_adv_lkup_elem *lkups,
59770f94570dSGrishma Kotecha 			u16 lkups_cnt, u16 recp_id,
59780f94570dSGrishma Kotecha 			struct ice_adv_rule_info *rinfo)
59790f94570dSGrishma Kotecha {
59800f94570dSGrishma Kotecha 	struct ice_adv_fltr_mgmt_list_entry *list_itr;
59810f94570dSGrishma Kotecha 	struct ice_switch_info *sw = hw->switch_info;
59820f94570dSGrishma Kotecha 	int i;
59830f94570dSGrishma Kotecha 
59840f94570dSGrishma Kotecha 	list_for_each_entry(list_itr, &sw->recp_list[recp_id].filt_rules,
59850f94570dSGrishma Kotecha 			    list_entry) {
59860f94570dSGrishma Kotecha 		bool lkups_matched = true;
59870f94570dSGrishma Kotecha 
59880f94570dSGrishma Kotecha 		if (lkups_cnt != list_itr->lkups_cnt)
59890f94570dSGrishma Kotecha 			continue;
59900f94570dSGrishma Kotecha 		for (i = 0; i < list_itr->lkups_cnt; i++)
59910f94570dSGrishma Kotecha 			if (memcmp(&list_itr->lkups[i], &lkups[i],
59920f94570dSGrishma Kotecha 				   sizeof(*lkups))) {
59930f94570dSGrishma Kotecha 				lkups_matched = false;
59940f94570dSGrishma Kotecha 				break;
59950f94570dSGrishma Kotecha 			}
59960f94570dSGrishma Kotecha 		if (rinfo->sw_act.flag == list_itr->rule_info.sw_act.flag &&
59978b032a55SMichal Swiatkowski 		    rinfo->tun_type == list_itr->rule_info.tun_type &&
5998ea71b967SMartyna Szapar-Mudlaw 		    rinfo->vlan_type == list_itr->rule_info.vlan_type &&
59990f94570dSGrishma Kotecha 		    lkups_matched)
60000f94570dSGrishma Kotecha 			return list_itr;
60010f94570dSGrishma Kotecha 	}
60020f94570dSGrishma Kotecha 	return NULL;
60030f94570dSGrishma Kotecha }
60040f94570dSGrishma Kotecha 
60050f94570dSGrishma Kotecha /**
60060f94570dSGrishma Kotecha  * ice_adv_add_update_vsi_list
60070f94570dSGrishma Kotecha  * @hw: pointer to the hardware structure
60080f94570dSGrishma Kotecha  * @m_entry: pointer to current adv filter management list entry
60090f94570dSGrishma Kotecha  * @cur_fltr: filter information from the book keeping entry
60100f94570dSGrishma Kotecha  * @new_fltr: filter information with the new VSI to be added
60110f94570dSGrishma Kotecha  *
60120f94570dSGrishma Kotecha  * Call AQ command to add or update previously created VSI list with new VSI.
60130f94570dSGrishma Kotecha  *
60140f94570dSGrishma Kotecha  * Helper function to do book keeping associated with adding filter information
60150f94570dSGrishma Kotecha  * The algorithm to do the booking keeping is described below :
60160f94570dSGrishma Kotecha  * When a VSI needs to subscribe to a given advanced filter
60170f94570dSGrishma Kotecha  *	if only one VSI has been added till now
60180f94570dSGrishma Kotecha  *		Allocate a new VSI list and add two VSIs
60190f94570dSGrishma Kotecha  *		to this list using switch rule command
60200f94570dSGrishma Kotecha  *		Update the previously created switch rule with the
60210f94570dSGrishma Kotecha  *		newly created VSI list ID
60220f94570dSGrishma Kotecha  *	if a VSI list was previously created
60230f94570dSGrishma Kotecha  *		Add the new VSI to the previously created VSI list set
60240f94570dSGrishma Kotecha  *		using the update switch rule command
60250f94570dSGrishma Kotecha  */
60265e24d598STony Nguyen static int
60270f94570dSGrishma Kotecha ice_adv_add_update_vsi_list(struct ice_hw *hw,
60280f94570dSGrishma Kotecha 			    struct ice_adv_fltr_mgmt_list_entry *m_entry,
60290f94570dSGrishma Kotecha 			    struct ice_adv_rule_info *cur_fltr,
60300f94570dSGrishma Kotecha 			    struct ice_adv_rule_info *new_fltr)
60310f94570dSGrishma Kotecha {
60320f94570dSGrishma Kotecha 	u16 vsi_list_id = 0;
60335518ac2aSTony Nguyen 	int status;
60340f94570dSGrishma Kotecha 
60350f94570dSGrishma Kotecha 	if (cur_fltr->sw_act.fltr_act == ICE_FWD_TO_Q ||
60360f94570dSGrishma Kotecha 	    cur_fltr->sw_act.fltr_act == ICE_FWD_TO_QGRP ||
60370f94570dSGrishma Kotecha 	    cur_fltr->sw_act.fltr_act == ICE_DROP_PACKET)
6038d54699e2STony Nguyen 		return -EOPNOTSUPP;
60390f94570dSGrishma Kotecha 
60400f94570dSGrishma Kotecha 	if ((new_fltr->sw_act.fltr_act == ICE_FWD_TO_Q ||
60410f94570dSGrishma Kotecha 	     new_fltr->sw_act.fltr_act == ICE_FWD_TO_QGRP) &&
60420f94570dSGrishma Kotecha 	    (cur_fltr->sw_act.fltr_act == ICE_FWD_TO_VSI ||
60430f94570dSGrishma Kotecha 	     cur_fltr->sw_act.fltr_act == ICE_FWD_TO_VSI_LIST))
6044d54699e2STony Nguyen 		return -EOPNOTSUPP;
60450f94570dSGrishma Kotecha 
60460f94570dSGrishma Kotecha 	if (m_entry->vsi_count < 2 && !m_entry->vsi_list_info) {
60470f94570dSGrishma Kotecha 		 /* Only one entry existed in the mapping and it was not already
60480f94570dSGrishma Kotecha 		  * a part of a VSI list. So, create a VSI list with the old and
60490f94570dSGrishma Kotecha 		  * new VSIs.
60500f94570dSGrishma Kotecha 		  */
60510f94570dSGrishma Kotecha 		struct ice_fltr_info tmp_fltr;
60520f94570dSGrishma Kotecha 		u16 vsi_handle_arr[2];
60530f94570dSGrishma Kotecha 
60540f94570dSGrishma Kotecha 		/* A rule already exists with the new VSI being added */
60550f94570dSGrishma Kotecha 		if (cur_fltr->sw_act.fwd_id.hw_vsi_id ==
60560f94570dSGrishma Kotecha 		    new_fltr->sw_act.fwd_id.hw_vsi_id)
6057d54699e2STony Nguyen 			return -EEXIST;
60580f94570dSGrishma Kotecha 
60590f94570dSGrishma Kotecha 		vsi_handle_arr[0] = cur_fltr->sw_act.vsi_handle;
60600f94570dSGrishma Kotecha 		vsi_handle_arr[1] = new_fltr->sw_act.vsi_handle;
60610f94570dSGrishma Kotecha 		status = ice_create_vsi_list_rule(hw, &vsi_handle_arr[0], 2,
60620f94570dSGrishma Kotecha 						  &vsi_list_id,
60630f94570dSGrishma Kotecha 						  ICE_SW_LKUP_LAST);
60640f94570dSGrishma Kotecha 		if (status)
60650f94570dSGrishma Kotecha 			return status;
60660f94570dSGrishma Kotecha 
60670f94570dSGrishma Kotecha 		memset(&tmp_fltr, 0, sizeof(tmp_fltr));
60680f94570dSGrishma Kotecha 		tmp_fltr.flag = m_entry->rule_info.sw_act.flag;
60690f94570dSGrishma Kotecha 		tmp_fltr.fltr_rule_id = cur_fltr->fltr_rule_id;
60700f94570dSGrishma Kotecha 		tmp_fltr.fltr_act = ICE_FWD_TO_VSI_LIST;
60710f94570dSGrishma Kotecha 		tmp_fltr.fwd_id.vsi_list_id = vsi_list_id;
60720f94570dSGrishma Kotecha 		tmp_fltr.lkup_type = ICE_SW_LKUP_LAST;
60730f94570dSGrishma Kotecha 
60740f94570dSGrishma Kotecha 		/* Update the previous switch rule of "forward to VSI" to
60750f94570dSGrishma Kotecha 		 * "fwd to VSI list"
60760f94570dSGrishma Kotecha 		 */
60770f94570dSGrishma Kotecha 		status = ice_update_pkt_fwd_rule(hw, &tmp_fltr);
60780f94570dSGrishma Kotecha 		if (status)
60790f94570dSGrishma Kotecha 			return status;
60800f94570dSGrishma Kotecha 
60810f94570dSGrishma Kotecha 		cur_fltr->sw_act.fwd_id.vsi_list_id = vsi_list_id;
60820f94570dSGrishma Kotecha 		cur_fltr->sw_act.fltr_act = ICE_FWD_TO_VSI_LIST;
60830f94570dSGrishma Kotecha 		m_entry->vsi_list_info =
60840f94570dSGrishma Kotecha 			ice_create_vsi_list_map(hw, &vsi_handle_arr[0], 2,
60850f94570dSGrishma Kotecha 						vsi_list_id);
60860f94570dSGrishma Kotecha 	} else {
60870f94570dSGrishma Kotecha 		u16 vsi_handle = new_fltr->sw_act.vsi_handle;
60880f94570dSGrishma Kotecha 
60890f94570dSGrishma Kotecha 		if (!m_entry->vsi_list_info)
6090d54699e2STony Nguyen 			return -EIO;
60910f94570dSGrishma Kotecha 
60920f94570dSGrishma Kotecha 		/* A rule already exists with the new VSI being added */
60930f94570dSGrishma Kotecha 		if (test_bit(vsi_handle, m_entry->vsi_list_info->vsi_map))
60940f94570dSGrishma Kotecha 			return 0;
60950f94570dSGrishma Kotecha 
60960f94570dSGrishma Kotecha 		/* Update the previously created VSI list set with
60970f94570dSGrishma Kotecha 		 * the new VSI ID passed in
60980f94570dSGrishma Kotecha 		 */
60990f94570dSGrishma Kotecha 		vsi_list_id = cur_fltr->sw_act.fwd_id.vsi_list_id;
61000f94570dSGrishma Kotecha 
61010f94570dSGrishma Kotecha 		status = ice_update_vsi_list_rule(hw, &vsi_handle, 1,
61020f94570dSGrishma Kotecha 						  vsi_list_id, false,
61030f94570dSGrishma Kotecha 						  ice_aqc_opc_update_sw_rules,
61040f94570dSGrishma Kotecha 						  ICE_SW_LKUP_LAST);
61050f94570dSGrishma Kotecha 		/* update VSI list mapping info with new VSI ID */
61060f94570dSGrishma Kotecha 		if (!status)
61070f94570dSGrishma Kotecha 			set_bit(vsi_handle, m_entry->vsi_list_info->vsi_map);
61080f94570dSGrishma Kotecha 	}
61090f94570dSGrishma Kotecha 	if (!status)
61100f94570dSGrishma Kotecha 		m_entry->vsi_count++;
61110f94570dSGrishma Kotecha 	return status;
61120f94570dSGrishma Kotecha }
61130f94570dSGrishma Kotecha 
61140f94570dSGrishma Kotecha /**
61150f94570dSGrishma Kotecha  * ice_add_adv_rule - helper function to create an advanced switch rule
61160f94570dSGrishma Kotecha  * @hw: pointer to the hardware structure
61170f94570dSGrishma Kotecha  * @lkups: information on the words that needs to be looked up. All words
61180f94570dSGrishma Kotecha  * together makes one recipe
61190f94570dSGrishma Kotecha  * @lkups_cnt: num of entries in the lkups array
61200f94570dSGrishma Kotecha  * @rinfo: other information related to the rule that needs to be programmed
61210f94570dSGrishma Kotecha  * @added_entry: this will return recipe_id, rule_id and vsi_handle. should be
61220f94570dSGrishma Kotecha  *               ignored is case of error.
61230f94570dSGrishma Kotecha  *
61240f94570dSGrishma Kotecha  * This function can program only 1 rule at a time. The lkups is used to
61250f94570dSGrishma Kotecha  * describe the all the words that forms the "lookup" portion of the recipe.
61260f94570dSGrishma Kotecha  * These words can span multiple protocols. Callers to this function need to
61270f94570dSGrishma Kotecha  * pass in a list of protocol headers with lookup information along and mask
61280f94570dSGrishma Kotecha  * that determines which words are valid from the given protocol header.
61290f94570dSGrishma Kotecha  * rinfo describes other information related to this rule such as forwarding
61300f94570dSGrishma Kotecha  * IDs, priority of this rule, etc.
61310f94570dSGrishma Kotecha  */
61325e24d598STony Nguyen int
61330f94570dSGrishma Kotecha ice_add_adv_rule(struct ice_hw *hw, struct ice_adv_lkup_elem *lkups,
61340f94570dSGrishma Kotecha 		 u16 lkups_cnt, struct ice_adv_rule_info *rinfo,
61350f94570dSGrishma Kotecha 		 struct ice_rule_query_data *added_entry)
61360f94570dSGrishma Kotecha {
61370f94570dSGrishma Kotecha 	struct ice_adv_fltr_mgmt_list_entry *m_entry, *adv_fltr = NULL;
61386e1ff618SAlexander Lobakin 	struct ice_sw_rule_lkup_rx_tx *s_rule = NULL;
6139e33163a4SAlexander Lobakin 	const struct ice_dummy_pkt_profile *profile;
61401b699f81SAlexander Lobakin 	u16 rid = 0, i, rule_buf_sz, vsi_handle;
61410f94570dSGrishma Kotecha 	struct list_head *rule_head;
61420f94570dSGrishma Kotecha 	struct ice_switch_info *sw;
61430f94570dSGrishma Kotecha 	u16 word_cnt;
61440f94570dSGrishma Kotecha 	u32 act = 0;
61455518ac2aSTony Nguyen 	int status;
61460f94570dSGrishma Kotecha 	u8 q_rgn;
61470f94570dSGrishma Kotecha 
61480f94570dSGrishma Kotecha 	/* Initialize profile to result index bitmap */
61490f94570dSGrishma Kotecha 	if (!hw->switch_info->prof_res_bm_init) {
61500f94570dSGrishma Kotecha 		hw->switch_info->prof_res_bm_init = 1;
61510f94570dSGrishma Kotecha 		ice_init_prof_result_bm(hw);
61520f94570dSGrishma Kotecha 	}
61530f94570dSGrishma Kotecha 
61540f94570dSGrishma Kotecha 	if (!lkups_cnt)
6155d54699e2STony Nguyen 		return -EINVAL;
61560f94570dSGrishma Kotecha 
61570f94570dSGrishma Kotecha 	/* get # of words we need to match */
61580f94570dSGrishma Kotecha 	word_cnt = 0;
61590f94570dSGrishma Kotecha 	for (i = 0; i < lkups_cnt; i++) {
6160135a161aSAlexander Lobakin 		u16 j;
61610f94570dSGrishma Kotecha 
6162135a161aSAlexander Lobakin 		for (j = 0; j < ARRAY_SIZE(lkups->m_raw); j++)
6163135a161aSAlexander Lobakin 			if (lkups[i].m_raw[j])
61640f94570dSGrishma Kotecha 				word_cnt++;
61650f94570dSGrishma Kotecha 	}
61660f94570dSGrishma Kotecha 
6167bd1ffe8eSWojciech Drewek 	if (!word_cnt)
6168d54699e2STony Nguyen 		return -EINVAL;
61690f94570dSGrishma Kotecha 
6170bd1ffe8eSWojciech Drewek 	if (word_cnt > ICE_MAX_CHAIN_WORDS)
6171bd1ffe8eSWojciech Drewek 		return -ENOSPC;
6172bd1ffe8eSWojciech Drewek 
61731b699f81SAlexander Lobakin 	/* locate a dummy packet */
61741b699f81SAlexander Lobakin 	profile = ice_find_dummy_packet(lkups, lkups_cnt, rinfo->tun_type);
617526395726SMartyna Szapar-Mudlaw 	if (IS_ERR(profile))
617626395726SMartyna Szapar-Mudlaw 		return PTR_ERR(profile);
61770f94570dSGrishma Kotecha 
61780f94570dSGrishma Kotecha 	if (!(rinfo->sw_act.fltr_act == ICE_FWD_TO_VSI ||
61790f94570dSGrishma Kotecha 	      rinfo->sw_act.fltr_act == ICE_FWD_TO_Q ||
61800f94570dSGrishma Kotecha 	      rinfo->sw_act.fltr_act == ICE_FWD_TO_QGRP ||
618126395726SMartyna Szapar-Mudlaw 	      rinfo->sw_act.fltr_act == ICE_DROP_PACKET)) {
618226395726SMartyna Szapar-Mudlaw 		status = -EIO;
618326395726SMartyna Szapar-Mudlaw 		goto free_pkt_profile;
618426395726SMartyna Szapar-Mudlaw 	}
61850f94570dSGrishma Kotecha 
61860f94570dSGrishma Kotecha 	vsi_handle = rinfo->sw_act.vsi_handle;
618726395726SMartyna Szapar-Mudlaw 	if (!ice_is_vsi_valid(hw, vsi_handle)) {
618826395726SMartyna Szapar-Mudlaw 		status =  -EINVAL;
618926395726SMartyna Szapar-Mudlaw 		goto free_pkt_profile;
619026395726SMartyna Szapar-Mudlaw 	}
61910f94570dSGrishma Kotecha 
61920f94570dSGrishma Kotecha 	if (rinfo->sw_act.fltr_act == ICE_FWD_TO_VSI)
61930f94570dSGrishma Kotecha 		rinfo->sw_act.fwd_id.hw_vsi_id =
61940f94570dSGrishma Kotecha 			ice_get_hw_vsi_num(hw, vsi_handle);
61950f94570dSGrishma Kotecha 	if (rinfo->sw_act.flag & ICE_FLTR_TX)
61960f94570dSGrishma Kotecha 		rinfo->sw_act.src = ice_get_hw_vsi_num(hw, vsi_handle);
61970f94570dSGrishma Kotecha 
61980f94570dSGrishma Kotecha 	status = ice_add_adv_recipe(hw, lkups, lkups_cnt, rinfo, &rid);
61990f94570dSGrishma Kotecha 	if (status)
620026395726SMartyna Szapar-Mudlaw 		goto free_pkt_profile;
62010f94570dSGrishma Kotecha 	m_entry = ice_find_adv_rule_entry(hw, lkups, lkups_cnt, rid, rinfo);
62020f94570dSGrishma Kotecha 	if (m_entry) {
62030f94570dSGrishma Kotecha 		/* we have to add VSI to VSI_LIST and increment vsi_count.
62040f94570dSGrishma Kotecha 		 * Also Update VSI list so that we can change forwarding rule
62050f94570dSGrishma Kotecha 		 * if the rule already exists, we will check if it exists with
62060f94570dSGrishma Kotecha 		 * same vsi_id, if not then add it to the VSI list if it already
62070f94570dSGrishma Kotecha 		 * exists if not then create a VSI list and add the existing VSI
62080f94570dSGrishma Kotecha 		 * ID and the new VSI ID to the list
62090f94570dSGrishma Kotecha 		 * We will add that VSI to the list
62100f94570dSGrishma Kotecha 		 */
62110f94570dSGrishma Kotecha 		status = ice_adv_add_update_vsi_list(hw, m_entry,
62120f94570dSGrishma Kotecha 						     &m_entry->rule_info,
62130f94570dSGrishma Kotecha 						     rinfo);
62140f94570dSGrishma Kotecha 		if (added_entry) {
62150f94570dSGrishma Kotecha 			added_entry->rid = rid;
62160f94570dSGrishma Kotecha 			added_entry->rule_id = m_entry->rule_info.fltr_rule_id;
62170f94570dSGrishma Kotecha 			added_entry->vsi_handle = rinfo->sw_act.vsi_handle;
62180f94570dSGrishma Kotecha 		}
621926395726SMartyna Szapar-Mudlaw 		goto free_pkt_profile;
62200f94570dSGrishma Kotecha 	}
62216e1ff618SAlexander Lobakin 	rule_buf_sz = ICE_SW_RULE_RX_TX_HDR_SIZE(s_rule, profile->pkt_len);
62220f94570dSGrishma Kotecha 	s_rule = kzalloc(rule_buf_sz, GFP_KERNEL);
622326395726SMartyna Szapar-Mudlaw 	if (!s_rule) {
622426395726SMartyna Szapar-Mudlaw 		status = -ENOMEM;
622526395726SMartyna Szapar-Mudlaw 		goto free_pkt_profile;
622626395726SMartyna Szapar-Mudlaw 	}
622773b483b7SWojciech Drewek 	if (!rinfo->flags_info.act_valid) {
622873b483b7SWojciech Drewek 		act |= ICE_SINGLE_ACT_LAN_ENABLE;
622973b483b7SWojciech Drewek 		act |= ICE_SINGLE_ACT_LB_ENABLE;
623073b483b7SWojciech Drewek 	} else {
623173b483b7SWojciech Drewek 		act |= rinfo->flags_info.act & (ICE_SINGLE_ACT_LAN_ENABLE |
623273b483b7SWojciech Drewek 						ICE_SINGLE_ACT_LB_ENABLE);
623373b483b7SWojciech Drewek 	}
623473b483b7SWojciech Drewek 
62350f94570dSGrishma Kotecha 	switch (rinfo->sw_act.fltr_act) {
62360f94570dSGrishma Kotecha 	case ICE_FWD_TO_VSI:
62370f94570dSGrishma Kotecha 		act |= (rinfo->sw_act.fwd_id.hw_vsi_id <<
62380f94570dSGrishma Kotecha 			ICE_SINGLE_ACT_VSI_ID_S) & ICE_SINGLE_ACT_VSI_ID_M;
62390f94570dSGrishma Kotecha 		act |= ICE_SINGLE_ACT_VSI_FORWARDING | ICE_SINGLE_ACT_VALID_BIT;
62400f94570dSGrishma Kotecha 		break;
62410f94570dSGrishma Kotecha 	case ICE_FWD_TO_Q:
62420f94570dSGrishma Kotecha 		act |= ICE_SINGLE_ACT_TO_Q;
62430f94570dSGrishma Kotecha 		act |= (rinfo->sw_act.fwd_id.q_id << ICE_SINGLE_ACT_Q_INDEX_S) &
62440f94570dSGrishma Kotecha 		       ICE_SINGLE_ACT_Q_INDEX_M;
62450f94570dSGrishma Kotecha 		break;
62460f94570dSGrishma Kotecha 	case ICE_FWD_TO_QGRP:
62470f94570dSGrishma Kotecha 		q_rgn = rinfo->sw_act.qgrp_size > 0 ?
62480f94570dSGrishma Kotecha 			(u8)ilog2(rinfo->sw_act.qgrp_size) : 0;
62490f94570dSGrishma Kotecha 		act |= ICE_SINGLE_ACT_TO_Q;
62500f94570dSGrishma Kotecha 		act |= (rinfo->sw_act.fwd_id.q_id << ICE_SINGLE_ACT_Q_INDEX_S) &
62510f94570dSGrishma Kotecha 		       ICE_SINGLE_ACT_Q_INDEX_M;
62520f94570dSGrishma Kotecha 		act |= (q_rgn << ICE_SINGLE_ACT_Q_REGION_S) &
62530f94570dSGrishma Kotecha 		       ICE_SINGLE_ACT_Q_REGION_M;
62540f94570dSGrishma Kotecha 		break;
62550f94570dSGrishma Kotecha 	case ICE_DROP_PACKET:
62560f94570dSGrishma Kotecha 		act |= ICE_SINGLE_ACT_VSI_FORWARDING | ICE_SINGLE_ACT_DROP |
62570f94570dSGrishma Kotecha 		       ICE_SINGLE_ACT_VALID_BIT;
62580f94570dSGrishma Kotecha 		break;
62590f94570dSGrishma Kotecha 	default:
6260d54699e2STony Nguyen 		status = -EIO;
62610f94570dSGrishma Kotecha 		goto err_ice_add_adv_rule;
62620f94570dSGrishma Kotecha 	}
62630f94570dSGrishma Kotecha 
62640f94570dSGrishma Kotecha 	/* set the rule LOOKUP type based on caller specified 'Rx'
62650f94570dSGrishma Kotecha 	 * instead of hardcoding it to be either LOOKUP_TX/RX
62660f94570dSGrishma Kotecha 	 *
62670f94570dSGrishma Kotecha 	 * for 'Rx' set the source to be the port number
62680f94570dSGrishma Kotecha 	 * for 'Tx' set the source to be the source HW VSI number (determined
62690f94570dSGrishma Kotecha 	 * by caller)
62700f94570dSGrishma Kotecha 	 */
62710f94570dSGrishma Kotecha 	if (rinfo->rx) {
62726e1ff618SAlexander Lobakin 		s_rule->hdr.type = cpu_to_le16(ICE_AQC_SW_RULES_T_LKUP_RX);
62736e1ff618SAlexander Lobakin 		s_rule->src = cpu_to_le16(hw->port_info->lport);
62740f94570dSGrishma Kotecha 	} else {
62756e1ff618SAlexander Lobakin 		s_rule->hdr.type = cpu_to_le16(ICE_AQC_SW_RULES_T_LKUP_TX);
62766e1ff618SAlexander Lobakin 		s_rule->src = cpu_to_le16(rinfo->sw_act.src);
62770f94570dSGrishma Kotecha 	}
62780f94570dSGrishma Kotecha 
62796e1ff618SAlexander Lobakin 	s_rule->recipe_id = cpu_to_le16(rid);
62806e1ff618SAlexander Lobakin 	s_rule->act = cpu_to_le32(act);
62810f94570dSGrishma Kotecha 
6282e33163a4SAlexander Lobakin 	status = ice_fill_adv_dummy_packet(lkups, lkups_cnt, s_rule, profile);
62830f94570dSGrishma Kotecha 	if (status)
62840f94570dSGrishma Kotecha 		goto err_ice_add_adv_rule;
62850f94570dSGrishma Kotecha 
6286b70bc066SWojciech Drewek 	if (rinfo->tun_type != ICE_NON_TUN &&
6287b70bc066SWojciech Drewek 	    rinfo->tun_type != ICE_SW_TUN_AND_NON_TUN) {
62888b032a55SMichal Swiatkowski 		status = ice_fill_adv_packet_tun(hw, rinfo->tun_type,
62896e1ff618SAlexander Lobakin 						 s_rule->hdr_data,
6290e33163a4SAlexander Lobakin 						 profile->offsets);
62918b032a55SMichal Swiatkowski 		if (status)
62928b032a55SMichal Swiatkowski 			goto err_ice_add_adv_rule;
62938b032a55SMichal Swiatkowski 	}
62948b032a55SMichal Swiatkowski 
6295ea71b967SMartyna Szapar-Mudlaw 	if (rinfo->vlan_type != 0 && ice_is_dvm_ena(hw)) {
6296ea71b967SMartyna Szapar-Mudlaw 		status = ice_fill_adv_packet_vlan(rinfo->vlan_type,
6297ea71b967SMartyna Szapar-Mudlaw 						  s_rule->hdr_data,
6298ea71b967SMartyna Szapar-Mudlaw 						  profile->offsets);
6299ea71b967SMartyna Szapar-Mudlaw 		if (status)
6300ea71b967SMartyna Szapar-Mudlaw 			goto err_ice_add_adv_rule;
6301ea71b967SMartyna Szapar-Mudlaw 	}
6302ea71b967SMartyna Szapar-Mudlaw 
63030f94570dSGrishma Kotecha 	status = ice_aq_sw_rules(hw, (struct ice_aqc_sw_rules *)s_rule,
63040f94570dSGrishma Kotecha 				 rule_buf_sz, 1, ice_aqc_opc_add_sw_rules,
63050f94570dSGrishma Kotecha 				 NULL);
63060f94570dSGrishma Kotecha 	if (status)
63070f94570dSGrishma Kotecha 		goto err_ice_add_adv_rule;
63080f94570dSGrishma Kotecha 	adv_fltr = devm_kzalloc(ice_hw_to_dev(hw),
63090f94570dSGrishma Kotecha 				sizeof(struct ice_adv_fltr_mgmt_list_entry),
63100f94570dSGrishma Kotecha 				GFP_KERNEL);
63110f94570dSGrishma Kotecha 	if (!adv_fltr) {
6312d54699e2STony Nguyen 		status = -ENOMEM;
63130f94570dSGrishma Kotecha 		goto err_ice_add_adv_rule;
63140f94570dSGrishma Kotecha 	}
63150f94570dSGrishma Kotecha 
63160f94570dSGrishma Kotecha 	adv_fltr->lkups = devm_kmemdup(ice_hw_to_dev(hw), lkups,
63170f94570dSGrishma Kotecha 				       lkups_cnt * sizeof(*lkups), GFP_KERNEL);
63180f94570dSGrishma Kotecha 	if (!adv_fltr->lkups) {
6319d54699e2STony Nguyen 		status = -ENOMEM;
63200f94570dSGrishma Kotecha 		goto err_ice_add_adv_rule;
63210f94570dSGrishma Kotecha 	}
63220f94570dSGrishma Kotecha 
63230f94570dSGrishma Kotecha 	adv_fltr->lkups_cnt = lkups_cnt;
63240f94570dSGrishma Kotecha 	adv_fltr->rule_info = *rinfo;
63256e1ff618SAlexander Lobakin 	adv_fltr->rule_info.fltr_rule_id = le16_to_cpu(s_rule->index);
63260f94570dSGrishma Kotecha 	sw = hw->switch_info;
63270f94570dSGrishma Kotecha 	sw->recp_list[rid].adv_rule = true;
63280f94570dSGrishma Kotecha 	rule_head = &sw->recp_list[rid].filt_rules;
63290f94570dSGrishma Kotecha 
63300f94570dSGrishma Kotecha 	if (rinfo->sw_act.fltr_act == ICE_FWD_TO_VSI)
63310f94570dSGrishma Kotecha 		adv_fltr->vsi_count = 1;
63320f94570dSGrishma Kotecha 
63330f94570dSGrishma Kotecha 	/* Add rule entry to book keeping list */
63340f94570dSGrishma Kotecha 	list_add(&adv_fltr->list_entry, rule_head);
63350f94570dSGrishma Kotecha 	if (added_entry) {
63360f94570dSGrishma Kotecha 		added_entry->rid = rid;
63370f94570dSGrishma Kotecha 		added_entry->rule_id = adv_fltr->rule_info.fltr_rule_id;
63380f94570dSGrishma Kotecha 		added_entry->vsi_handle = rinfo->sw_act.vsi_handle;
63390f94570dSGrishma Kotecha 	}
63400f94570dSGrishma Kotecha err_ice_add_adv_rule:
63410f94570dSGrishma Kotecha 	if (status && adv_fltr) {
63420f94570dSGrishma Kotecha 		devm_kfree(ice_hw_to_dev(hw), adv_fltr->lkups);
63430f94570dSGrishma Kotecha 		devm_kfree(ice_hw_to_dev(hw), adv_fltr);
63440f94570dSGrishma Kotecha 	}
63450f94570dSGrishma Kotecha 
63460f94570dSGrishma Kotecha 	kfree(s_rule);
63470f94570dSGrishma Kotecha 
634826395726SMartyna Szapar-Mudlaw free_pkt_profile:
634926395726SMartyna Szapar-Mudlaw 	if (profile->match & ICE_PKT_KMALLOC) {
635026395726SMartyna Szapar-Mudlaw 		kfree(profile->offsets);
635126395726SMartyna Szapar-Mudlaw 		kfree(profile->pkt);
635226395726SMartyna Szapar-Mudlaw 		kfree(profile);
635326395726SMartyna Szapar-Mudlaw 	}
635426395726SMartyna Szapar-Mudlaw 
63550f94570dSGrishma Kotecha 	return status;
63560f94570dSGrishma Kotecha }
63570f94570dSGrishma Kotecha 
63580f94570dSGrishma Kotecha /**
6359334cb062SAnirudh Venkataramanan  * ice_replay_vsi_fltr - Replay filters for requested VSI
63600f9d5027SAnirudh Venkataramanan  * @hw: pointer to the hardware structure
6361334cb062SAnirudh Venkataramanan  * @vsi_handle: driver VSI handle
6362f9867df6SAnirudh Venkataramanan  * @recp_id: Recipe ID for which rules need to be replayed
6363334cb062SAnirudh Venkataramanan  * @list_head: list for which filters need to be replayed
6364334cb062SAnirudh Venkataramanan  *
6365334cb062SAnirudh Venkataramanan  * Replays the filter of recipe recp_id for a VSI represented via vsi_handle.
6366334cb062SAnirudh Venkataramanan  * It is required to pass valid VSI handle.
63670f9d5027SAnirudh Venkataramanan  */
63685e24d598STony Nguyen static int
6369334cb062SAnirudh Venkataramanan ice_replay_vsi_fltr(struct ice_hw *hw, u16 vsi_handle, u8 recp_id,
6370334cb062SAnirudh Venkataramanan 		    struct list_head *list_head)
63710f9d5027SAnirudh Venkataramanan {
63720f9d5027SAnirudh Venkataramanan 	struct ice_fltr_mgmt_list_entry *itr;
63735e24d598STony Nguyen 	int status = 0;
6374334cb062SAnirudh Venkataramanan 	u16 hw_vsi_id;
63750f9d5027SAnirudh Venkataramanan 
63760f9d5027SAnirudh Venkataramanan 	if (list_empty(list_head))
63770f9d5027SAnirudh Venkataramanan 		return status;
6378334cb062SAnirudh Venkataramanan 	hw_vsi_id = ice_get_hw_vsi_num(hw, vsi_handle);
63790f9d5027SAnirudh Venkataramanan 
6380334cb062SAnirudh Venkataramanan 	list_for_each_entry(itr, list_head, list_entry) {
63810f9d5027SAnirudh Venkataramanan 		struct ice_fltr_list_entry f_entry;
63820f9d5027SAnirudh Venkataramanan 
63830f9d5027SAnirudh Venkataramanan 		f_entry.fltr_info = itr->fltr_info;
6384334cb062SAnirudh Venkataramanan 		if (itr->vsi_count < 2 && recp_id != ICE_SW_LKUP_VLAN &&
6385334cb062SAnirudh Venkataramanan 		    itr->fltr_info.vsi_handle == vsi_handle) {
6386f9867df6SAnirudh Venkataramanan 			/* update the src in case it is VSI num */
6387334cb062SAnirudh Venkataramanan 			if (f_entry.fltr_info.src_id == ICE_SRC_ID_VSI)
6388334cb062SAnirudh Venkataramanan 				f_entry.fltr_info.src = hw_vsi_id;
63890f9d5027SAnirudh Venkataramanan 			status = ice_add_rule_internal(hw, recp_id, &f_entry);
63900f9d5027SAnirudh Venkataramanan 			if (status)
63910f9d5027SAnirudh Venkataramanan 				goto end;
63920f9d5027SAnirudh Venkataramanan 			continue;
63930f9d5027SAnirudh Venkataramanan 		}
6394072f0c3dSDave Ertman 		if (!itr->vsi_list_info ||
6395072f0c3dSDave Ertman 		    !test_bit(vsi_handle, itr->vsi_list_info->vsi_map))
6396334cb062SAnirudh Venkataramanan 			continue;
6397334cb062SAnirudh Venkataramanan 		/* Clearing it so that the logic can add it back */
6398334cb062SAnirudh Venkataramanan 		clear_bit(vsi_handle, itr->vsi_list_info->vsi_map);
6399334cb062SAnirudh Venkataramanan 		f_entry.fltr_info.vsi_handle = vsi_handle;
64000f9d5027SAnirudh Venkataramanan 		f_entry.fltr_info.fltr_act = ICE_FWD_TO_VSI;
6401f9867df6SAnirudh Venkataramanan 		/* update the src in case it is VSI num */
6402334cb062SAnirudh Venkataramanan 		if (f_entry.fltr_info.src_id == ICE_SRC_ID_VSI)
6403334cb062SAnirudh Venkataramanan 			f_entry.fltr_info.src = hw_vsi_id;
64040f9d5027SAnirudh Venkataramanan 		if (recp_id == ICE_SW_LKUP_VLAN)
64050f9d5027SAnirudh Venkataramanan 			status = ice_add_vlan_internal(hw, &f_entry);
64060f9d5027SAnirudh Venkataramanan 		else
6407334cb062SAnirudh Venkataramanan 			status = ice_add_rule_internal(hw, recp_id, &f_entry);
64080f9d5027SAnirudh Venkataramanan 		if (status)
64090f9d5027SAnirudh Venkataramanan 			goto end;
64100f9d5027SAnirudh Venkataramanan 	}
64110f9d5027SAnirudh Venkataramanan end:
64120f9d5027SAnirudh Venkataramanan 	return status;
64130f9d5027SAnirudh Venkataramanan }
64140f9d5027SAnirudh Venkataramanan 
64150f9d5027SAnirudh Venkataramanan /**
64168bb98f33SShivanshu Shukla  * ice_adv_rem_update_vsi_list
64178bb98f33SShivanshu Shukla  * @hw: pointer to the hardware structure
64188bb98f33SShivanshu Shukla  * @vsi_handle: VSI handle of the VSI to remove
64198bb98f33SShivanshu Shukla  * @fm_list: filter management entry for which the VSI list management needs to
64208bb98f33SShivanshu Shukla  *	     be done
64218bb98f33SShivanshu Shukla  */
64225e24d598STony Nguyen static int
64238bb98f33SShivanshu Shukla ice_adv_rem_update_vsi_list(struct ice_hw *hw, u16 vsi_handle,
64248bb98f33SShivanshu Shukla 			    struct ice_adv_fltr_mgmt_list_entry *fm_list)
64258bb98f33SShivanshu Shukla {
64268bb98f33SShivanshu Shukla 	struct ice_vsi_list_map_info *vsi_list_info;
64278bb98f33SShivanshu Shukla 	enum ice_sw_lkup_type lkup_type;
64288bb98f33SShivanshu Shukla 	u16 vsi_list_id;
64295518ac2aSTony Nguyen 	int status;
64308bb98f33SShivanshu Shukla 
64318bb98f33SShivanshu Shukla 	if (fm_list->rule_info.sw_act.fltr_act != ICE_FWD_TO_VSI_LIST ||
64328bb98f33SShivanshu Shukla 	    fm_list->vsi_count == 0)
6433d54699e2STony Nguyen 		return -EINVAL;
64348bb98f33SShivanshu Shukla 
64358bb98f33SShivanshu Shukla 	/* A rule with the VSI being removed does not exist */
64368bb98f33SShivanshu Shukla 	if (!test_bit(vsi_handle, fm_list->vsi_list_info->vsi_map))
6437d54699e2STony Nguyen 		return -ENOENT;
64388bb98f33SShivanshu Shukla 
64398bb98f33SShivanshu Shukla 	lkup_type = ICE_SW_LKUP_LAST;
64408bb98f33SShivanshu Shukla 	vsi_list_id = fm_list->rule_info.sw_act.fwd_id.vsi_list_id;
64418bb98f33SShivanshu Shukla 	status = ice_update_vsi_list_rule(hw, &vsi_handle, 1, vsi_list_id, true,
64428bb98f33SShivanshu Shukla 					  ice_aqc_opc_update_sw_rules,
64438bb98f33SShivanshu Shukla 					  lkup_type);
64448bb98f33SShivanshu Shukla 	if (status)
64458bb98f33SShivanshu Shukla 		return status;
64468bb98f33SShivanshu Shukla 
64478bb98f33SShivanshu Shukla 	fm_list->vsi_count--;
64488bb98f33SShivanshu Shukla 	clear_bit(vsi_handle, fm_list->vsi_list_info->vsi_map);
64498bb98f33SShivanshu Shukla 	vsi_list_info = fm_list->vsi_list_info;
64508bb98f33SShivanshu Shukla 	if (fm_list->vsi_count == 1) {
64518bb98f33SShivanshu Shukla 		struct ice_fltr_info tmp_fltr;
64528bb98f33SShivanshu Shukla 		u16 rem_vsi_handle;
64538bb98f33SShivanshu Shukla 
64548bb98f33SShivanshu Shukla 		rem_vsi_handle = find_first_bit(vsi_list_info->vsi_map,
64558bb98f33SShivanshu Shukla 						ICE_MAX_VSI);
64568bb98f33SShivanshu Shukla 		if (!ice_is_vsi_valid(hw, rem_vsi_handle))
6457d54699e2STony Nguyen 			return -EIO;
64588bb98f33SShivanshu Shukla 
64598bb98f33SShivanshu Shukla 		/* Make sure VSI list is empty before removing it below */
64608bb98f33SShivanshu Shukla 		status = ice_update_vsi_list_rule(hw, &rem_vsi_handle, 1,
64618bb98f33SShivanshu Shukla 						  vsi_list_id, true,
64628bb98f33SShivanshu Shukla 						  ice_aqc_opc_update_sw_rules,
64638bb98f33SShivanshu Shukla 						  lkup_type);
64648bb98f33SShivanshu Shukla 		if (status)
64658bb98f33SShivanshu Shukla 			return status;
64668bb98f33SShivanshu Shukla 
64678bb98f33SShivanshu Shukla 		memset(&tmp_fltr, 0, sizeof(tmp_fltr));
64688bb98f33SShivanshu Shukla 		tmp_fltr.flag = fm_list->rule_info.sw_act.flag;
64698bb98f33SShivanshu Shukla 		tmp_fltr.fltr_rule_id = fm_list->rule_info.fltr_rule_id;
64708bb98f33SShivanshu Shukla 		fm_list->rule_info.sw_act.fltr_act = ICE_FWD_TO_VSI;
64718bb98f33SShivanshu Shukla 		tmp_fltr.fltr_act = ICE_FWD_TO_VSI;
64728bb98f33SShivanshu Shukla 		tmp_fltr.fwd_id.hw_vsi_id =
64738bb98f33SShivanshu Shukla 			ice_get_hw_vsi_num(hw, rem_vsi_handle);
64748bb98f33SShivanshu Shukla 		fm_list->rule_info.sw_act.fwd_id.hw_vsi_id =
64758bb98f33SShivanshu Shukla 			ice_get_hw_vsi_num(hw, rem_vsi_handle);
64768bb98f33SShivanshu Shukla 		fm_list->rule_info.sw_act.vsi_handle = rem_vsi_handle;
64778bb98f33SShivanshu Shukla 
64788bb98f33SShivanshu Shukla 		/* Update the previous switch rule of "MAC forward to VSI" to
64798bb98f33SShivanshu Shukla 		 * "MAC fwd to VSI list"
64808bb98f33SShivanshu Shukla 		 */
64818bb98f33SShivanshu Shukla 		status = ice_update_pkt_fwd_rule(hw, &tmp_fltr);
64828bb98f33SShivanshu Shukla 		if (status) {
64838bb98f33SShivanshu Shukla 			ice_debug(hw, ICE_DBG_SW, "Failed to update pkt fwd rule to FWD_TO_VSI on HW VSI %d, error %d\n",
64848bb98f33SShivanshu Shukla 				  tmp_fltr.fwd_id.hw_vsi_id, status);
64858bb98f33SShivanshu Shukla 			return status;
64868bb98f33SShivanshu Shukla 		}
64878bb98f33SShivanshu Shukla 		fm_list->vsi_list_info->ref_cnt--;
64888bb98f33SShivanshu Shukla 
64898bb98f33SShivanshu Shukla 		/* Remove the VSI list since it is no longer used */
64908bb98f33SShivanshu Shukla 		status = ice_remove_vsi_list_rule(hw, vsi_list_id, lkup_type);
64918bb98f33SShivanshu Shukla 		if (status) {
64928bb98f33SShivanshu Shukla 			ice_debug(hw, ICE_DBG_SW, "Failed to remove VSI list %d, error %d\n",
64938bb98f33SShivanshu Shukla 				  vsi_list_id, status);
64948bb98f33SShivanshu Shukla 			return status;
64958bb98f33SShivanshu Shukla 		}
64968bb98f33SShivanshu Shukla 
64978bb98f33SShivanshu Shukla 		list_del(&vsi_list_info->list_entry);
64988bb98f33SShivanshu Shukla 		devm_kfree(ice_hw_to_dev(hw), vsi_list_info);
64998bb98f33SShivanshu Shukla 		fm_list->vsi_list_info = NULL;
65008bb98f33SShivanshu Shukla 	}
65018bb98f33SShivanshu Shukla 
65028bb98f33SShivanshu Shukla 	return status;
65038bb98f33SShivanshu Shukla }
65048bb98f33SShivanshu Shukla 
65058bb98f33SShivanshu Shukla /**
65068bb98f33SShivanshu Shukla  * ice_rem_adv_rule - removes existing advanced switch rule
65078bb98f33SShivanshu Shukla  * @hw: pointer to the hardware structure
65088bb98f33SShivanshu Shukla  * @lkups: information on the words that needs to be looked up. All words
65098bb98f33SShivanshu Shukla  *         together makes one recipe
65108bb98f33SShivanshu Shukla  * @lkups_cnt: num of entries in the lkups array
65118bb98f33SShivanshu Shukla  * @rinfo: Its the pointer to the rule information for the rule
65128bb98f33SShivanshu Shukla  *
65138bb98f33SShivanshu Shukla  * This function can be used to remove 1 rule at a time. The lkups is
65148bb98f33SShivanshu Shukla  * used to describe all the words that forms the "lookup" portion of the
65158bb98f33SShivanshu Shukla  * rule. These words can span multiple protocols. Callers to this function
65168bb98f33SShivanshu Shukla  * need to pass in a list of protocol headers with lookup information along
65178bb98f33SShivanshu Shukla  * and mask that determines which words are valid from the given protocol
65188bb98f33SShivanshu Shukla  * header. rinfo describes other information related to this rule such as
65198bb98f33SShivanshu Shukla  * forwarding IDs, priority of this rule, etc.
65208bb98f33SShivanshu Shukla  */
65215e24d598STony Nguyen static int
65228bb98f33SShivanshu Shukla ice_rem_adv_rule(struct ice_hw *hw, struct ice_adv_lkup_elem *lkups,
65238bb98f33SShivanshu Shukla 		 u16 lkups_cnt, struct ice_adv_rule_info *rinfo)
65248bb98f33SShivanshu Shukla {
65258bb98f33SShivanshu Shukla 	struct ice_adv_fltr_mgmt_list_entry *list_elem;
65268bb98f33SShivanshu Shukla 	struct ice_prot_lkup_ext lkup_exts;
65278bb98f33SShivanshu Shukla 	bool remove_rule = false;
65288bb98f33SShivanshu Shukla 	struct mutex *rule_lock; /* Lock to protect filter rule list */
65298bb98f33SShivanshu Shukla 	u16 i, rid, vsi_handle;
65305518ac2aSTony Nguyen 	int status = 0;
65318bb98f33SShivanshu Shukla 
65328bb98f33SShivanshu Shukla 	memset(&lkup_exts, 0, sizeof(lkup_exts));
65338bb98f33SShivanshu Shukla 	for (i = 0; i < lkups_cnt; i++) {
65348bb98f33SShivanshu Shukla 		u16 count;
65358bb98f33SShivanshu Shukla 
65368bb98f33SShivanshu Shukla 		if (lkups[i].type >= ICE_PROTOCOL_LAST)
6537d54699e2STony Nguyen 			return -EIO;
65388bb98f33SShivanshu Shukla 
65398bb98f33SShivanshu Shukla 		count = ice_fill_valid_words(&lkups[i], &lkup_exts);
65408bb98f33SShivanshu Shukla 		if (!count)
6541d54699e2STony Nguyen 			return -EIO;
65428bb98f33SShivanshu Shukla 	}
65438bb98f33SShivanshu Shukla 
65448b032a55SMichal Swiatkowski 	/* Create any special protocol/offset pairs, such as looking at tunnel
65458b032a55SMichal Swiatkowski 	 * bits by extracting metadata
65468b032a55SMichal Swiatkowski 	 */
6547ea71b967SMartyna Szapar-Mudlaw 	status = ice_add_special_words(rinfo, &lkup_exts, ice_is_dvm_ena(hw));
65488b032a55SMichal Swiatkowski 	if (status)
65498b032a55SMichal Swiatkowski 		return status;
65508b032a55SMichal Swiatkowski 
6551de6acd1cSMichal Swiatkowski 	rid = ice_find_recp(hw, &lkup_exts, rinfo->tun_type);
65528bb98f33SShivanshu Shukla 	/* If did not find a recipe that match the existing criteria */
65538bb98f33SShivanshu Shukla 	if (rid == ICE_MAX_NUM_RECIPES)
6554d54699e2STony Nguyen 		return -EINVAL;
65558bb98f33SShivanshu Shukla 
65568bb98f33SShivanshu Shukla 	rule_lock = &hw->switch_info->recp_list[rid].filt_rule_lock;
65578bb98f33SShivanshu Shukla 	list_elem = ice_find_adv_rule_entry(hw, lkups, lkups_cnt, rid, rinfo);
65588bb98f33SShivanshu Shukla 	/* the rule is already removed */
65598bb98f33SShivanshu Shukla 	if (!list_elem)
65608bb98f33SShivanshu Shukla 		return 0;
65618bb98f33SShivanshu Shukla 	mutex_lock(rule_lock);
65628bb98f33SShivanshu Shukla 	if (list_elem->rule_info.sw_act.fltr_act != ICE_FWD_TO_VSI_LIST) {
65638bb98f33SShivanshu Shukla 		remove_rule = true;
65648bb98f33SShivanshu Shukla 	} else if (list_elem->vsi_count > 1) {
65658bb98f33SShivanshu Shukla 		remove_rule = false;
65668bb98f33SShivanshu Shukla 		vsi_handle = rinfo->sw_act.vsi_handle;
65678bb98f33SShivanshu Shukla 		status = ice_adv_rem_update_vsi_list(hw, vsi_handle, list_elem);
65688bb98f33SShivanshu Shukla 	} else {
65698bb98f33SShivanshu Shukla 		vsi_handle = rinfo->sw_act.vsi_handle;
65708bb98f33SShivanshu Shukla 		status = ice_adv_rem_update_vsi_list(hw, vsi_handle, list_elem);
65718bb98f33SShivanshu Shukla 		if (status) {
65728bb98f33SShivanshu Shukla 			mutex_unlock(rule_lock);
65738bb98f33SShivanshu Shukla 			return status;
65748bb98f33SShivanshu Shukla 		}
65758bb98f33SShivanshu Shukla 		if (list_elem->vsi_count == 0)
65768bb98f33SShivanshu Shukla 			remove_rule = true;
65778bb98f33SShivanshu Shukla 	}
65788bb98f33SShivanshu Shukla 	mutex_unlock(rule_lock);
65798bb98f33SShivanshu Shukla 	if (remove_rule) {
65806e1ff618SAlexander Lobakin 		struct ice_sw_rule_lkup_rx_tx *s_rule;
65818bb98f33SShivanshu Shukla 		u16 rule_buf_sz;
65828bb98f33SShivanshu Shukla 
65836e1ff618SAlexander Lobakin 		rule_buf_sz = ICE_SW_RULE_RX_TX_NO_HDR_SIZE(s_rule);
65848bb98f33SShivanshu Shukla 		s_rule = kzalloc(rule_buf_sz, GFP_KERNEL);
65858bb98f33SShivanshu Shukla 		if (!s_rule)
6586d54699e2STony Nguyen 			return -ENOMEM;
65876e1ff618SAlexander Lobakin 		s_rule->act = 0;
65886e1ff618SAlexander Lobakin 		s_rule->index = cpu_to_le16(list_elem->rule_info.fltr_rule_id);
65896e1ff618SAlexander Lobakin 		s_rule->hdr_len = 0;
65908bb98f33SShivanshu Shukla 		status = ice_aq_sw_rules(hw, (struct ice_aqc_sw_rules *)s_rule,
65918bb98f33SShivanshu Shukla 					 rule_buf_sz, 1,
65928bb98f33SShivanshu Shukla 					 ice_aqc_opc_remove_sw_rules, NULL);
6593d54699e2STony Nguyen 		if (!status || status == -ENOENT) {
65948bb98f33SShivanshu Shukla 			struct ice_switch_info *sw = hw->switch_info;
65958bb98f33SShivanshu Shukla 
65968bb98f33SShivanshu Shukla 			mutex_lock(rule_lock);
65978bb98f33SShivanshu Shukla 			list_del(&list_elem->list_entry);
65988bb98f33SShivanshu Shukla 			devm_kfree(ice_hw_to_dev(hw), list_elem->lkups);
65998bb98f33SShivanshu Shukla 			devm_kfree(ice_hw_to_dev(hw), list_elem);
66008bb98f33SShivanshu Shukla 			mutex_unlock(rule_lock);
66018bb98f33SShivanshu Shukla 			if (list_empty(&sw->recp_list[rid].filt_rules))
66028bb98f33SShivanshu Shukla 				sw->recp_list[rid].adv_rule = false;
66038bb98f33SShivanshu Shukla 		}
66048bb98f33SShivanshu Shukla 		kfree(s_rule);
66058bb98f33SShivanshu Shukla 	}
66068bb98f33SShivanshu Shukla 	return status;
66078bb98f33SShivanshu Shukla }
66088bb98f33SShivanshu Shukla 
66098bb98f33SShivanshu Shukla /**
66108bb98f33SShivanshu Shukla  * ice_rem_adv_rule_by_id - removes existing advanced switch rule by ID
66118bb98f33SShivanshu Shukla  * @hw: pointer to the hardware structure
66128bb98f33SShivanshu Shukla  * @remove_entry: data struct which holds rule_id, VSI handle and recipe ID
66138bb98f33SShivanshu Shukla  *
66148bb98f33SShivanshu Shukla  * This function is used to remove 1 rule at a time. The removal is based on
66158bb98f33SShivanshu Shukla  * the remove_entry parameter. This function will remove rule for a given
66168bb98f33SShivanshu Shukla  * vsi_handle with a given rule_id which is passed as parameter in remove_entry
66178bb98f33SShivanshu Shukla  */
66185e24d598STony Nguyen int
66198bb98f33SShivanshu Shukla ice_rem_adv_rule_by_id(struct ice_hw *hw,
66208bb98f33SShivanshu Shukla 		       struct ice_rule_query_data *remove_entry)
66218bb98f33SShivanshu Shukla {
66228bb98f33SShivanshu Shukla 	struct ice_adv_fltr_mgmt_list_entry *list_itr;
66238bb98f33SShivanshu Shukla 	struct list_head *list_head;
66248bb98f33SShivanshu Shukla 	struct ice_adv_rule_info rinfo;
66258bb98f33SShivanshu Shukla 	struct ice_switch_info *sw;
66268bb98f33SShivanshu Shukla 
66278bb98f33SShivanshu Shukla 	sw = hw->switch_info;
66288bb98f33SShivanshu Shukla 	if (!sw->recp_list[remove_entry->rid].recp_created)
6629d54699e2STony Nguyen 		return -EINVAL;
66308bb98f33SShivanshu Shukla 	list_head = &sw->recp_list[remove_entry->rid].filt_rules;
66318bb98f33SShivanshu Shukla 	list_for_each_entry(list_itr, list_head, list_entry) {
66328bb98f33SShivanshu Shukla 		if (list_itr->rule_info.fltr_rule_id ==
66338bb98f33SShivanshu Shukla 		    remove_entry->rule_id) {
66348bb98f33SShivanshu Shukla 			rinfo = list_itr->rule_info;
66358bb98f33SShivanshu Shukla 			rinfo.sw_act.vsi_handle = remove_entry->vsi_handle;
66368bb98f33SShivanshu Shukla 			return ice_rem_adv_rule(hw, list_itr->lkups,
66378bb98f33SShivanshu Shukla 						list_itr->lkups_cnt, &rinfo);
66388bb98f33SShivanshu Shukla 		}
66398bb98f33SShivanshu Shukla 	}
66408bb98f33SShivanshu Shukla 	/* either list is empty or unable to find rule */
6641d54699e2STony Nguyen 	return -ENOENT;
66428bb98f33SShivanshu Shukla }
66438bb98f33SShivanshu Shukla 
66448bb98f33SShivanshu Shukla /**
6645c1e5da5dSWojciech Drewek  * ice_rem_adv_rule_for_vsi - removes existing advanced switch rules for a
6646c1e5da5dSWojciech Drewek  *                            given VSI handle
6647c1e5da5dSWojciech Drewek  * @hw: pointer to the hardware structure
6648c1e5da5dSWojciech Drewek  * @vsi_handle: VSI handle for which we are supposed to remove all the rules.
6649c1e5da5dSWojciech Drewek  *
6650c1e5da5dSWojciech Drewek  * This function is used to remove all the rules for a given VSI and as soon
6651c1e5da5dSWojciech Drewek  * as removing a rule fails, it will return immediately with the error code,
6652c1e5da5dSWojciech Drewek  * else it will return success.
6653c1e5da5dSWojciech Drewek  */
6654c1e5da5dSWojciech Drewek int ice_rem_adv_rule_for_vsi(struct ice_hw *hw, u16 vsi_handle)
6655c1e5da5dSWojciech Drewek {
6656c1e5da5dSWojciech Drewek 	struct ice_adv_fltr_mgmt_list_entry *list_itr, *tmp_entry;
6657c1e5da5dSWojciech Drewek 	struct ice_vsi_list_map_info *map_info;
6658c1e5da5dSWojciech Drewek 	struct ice_adv_rule_info rinfo;
6659c1e5da5dSWojciech Drewek 	struct list_head *list_head;
6660c1e5da5dSWojciech Drewek 	struct ice_switch_info *sw;
6661c1e5da5dSWojciech Drewek 	int status;
6662c1e5da5dSWojciech Drewek 	u8 rid;
6663c1e5da5dSWojciech Drewek 
6664c1e5da5dSWojciech Drewek 	sw = hw->switch_info;
6665c1e5da5dSWojciech Drewek 	for (rid = 0; rid < ICE_MAX_NUM_RECIPES; rid++) {
6666c1e5da5dSWojciech Drewek 		if (!sw->recp_list[rid].recp_created)
6667c1e5da5dSWojciech Drewek 			continue;
6668c1e5da5dSWojciech Drewek 		if (!sw->recp_list[rid].adv_rule)
6669c1e5da5dSWojciech Drewek 			continue;
6670c1e5da5dSWojciech Drewek 
6671c1e5da5dSWojciech Drewek 		list_head = &sw->recp_list[rid].filt_rules;
6672c1e5da5dSWojciech Drewek 		list_for_each_entry_safe(list_itr, tmp_entry, list_head,
6673c1e5da5dSWojciech Drewek 					 list_entry) {
6674c1e5da5dSWojciech Drewek 			rinfo = list_itr->rule_info;
6675c1e5da5dSWojciech Drewek 
6676c1e5da5dSWojciech Drewek 			if (rinfo.sw_act.fltr_act == ICE_FWD_TO_VSI_LIST) {
6677c1e5da5dSWojciech Drewek 				map_info = list_itr->vsi_list_info;
6678c1e5da5dSWojciech Drewek 				if (!map_info)
6679c1e5da5dSWojciech Drewek 					continue;
6680c1e5da5dSWojciech Drewek 
6681c1e5da5dSWojciech Drewek 				if (!test_bit(vsi_handle, map_info->vsi_map))
6682c1e5da5dSWojciech Drewek 					continue;
6683c1e5da5dSWojciech Drewek 			} else if (rinfo.sw_act.vsi_handle != vsi_handle) {
6684c1e5da5dSWojciech Drewek 				continue;
6685c1e5da5dSWojciech Drewek 			}
6686c1e5da5dSWojciech Drewek 
6687c1e5da5dSWojciech Drewek 			rinfo.sw_act.vsi_handle = vsi_handle;
6688c1e5da5dSWojciech Drewek 			status = ice_rem_adv_rule(hw, list_itr->lkups,
6689c1e5da5dSWojciech Drewek 						  list_itr->lkups_cnt, &rinfo);
6690c1e5da5dSWojciech Drewek 			if (status)
6691c1e5da5dSWojciech Drewek 				return status;
6692c1e5da5dSWojciech Drewek 		}
6693c1e5da5dSWojciech Drewek 	}
6694c1e5da5dSWojciech Drewek 	return 0;
6695c1e5da5dSWojciech Drewek }
6696c1e5da5dSWojciech Drewek 
6697c1e5da5dSWojciech Drewek /**
6698c36a2b97SVictor Raj  * ice_replay_vsi_adv_rule - Replay advanced rule for requested VSI
6699c36a2b97SVictor Raj  * @hw: pointer to the hardware structure
6700c36a2b97SVictor Raj  * @vsi_handle: driver VSI handle
6701c36a2b97SVictor Raj  * @list_head: list for which filters need to be replayed
6702c36a2b97SVictor Raj  *
6703c36a2b97SVictor Raj  * Replay the advanced rule for the given VSI.
6704c36a2b97SVictor Raj  */
6705c36a2b97SVictor Raj static int
6706c36a2b97SVictor Raj ice_replay_vsi_adv_rule(struct ice_hw *hw, u16 vsi_handle,
6707c36a2b97SVictor Raj 			struct list_head *list_head)
6708c36a2b97SVictor Raj {
6709c36a2b97SVictor Raj 	struct ice_rule_query_data added_entry = { 0 };
6710c36a2b97SVictor Raj 	struct ice_adv_fltr_mgmt_list_entry *adv_fltr;
6711c36a2b97SVictor Raj 	int status = 0;
6712c36a2b97SVictor Raj 
6713c36a2b97SVictor Raj 	if (list_empty(list_head))
6714c36a2b97SVictor Raj 		return status;
6715c36a2b97SVictor Raj 	list_for_each_entry(adv_fltr, list_head, list_entry) {
6716c36a2b97SVictor Raj 		struct ice_adv_rule_info *rinfo = &adv_fltr->rule_info;
6717c36a2b97SVictor Raj 		u16 lk_cnt = adv_fltr->lkups_cnt;
6718c36a2b97SVictor Raj 
6719c36a2b97SVictor Raj 		if (vsi_handle != rinfo->sw_act.vsi_handle)
6720c36a2b97SVictor Raj 			continue;
6721c36a2b97SVictor Raj 		status = ice_add_adv_rule(hw, adv_fltr->lkups, lk_cnt, rinfo,
6722c36a2b97SVictor Raj 					  &added_entry);
6723c36a2b97SVictor Raj 		if (status)
6724c36a2b97SVictor Raj 			break;
6725c36a2b97SVictor Raj 	}
6726c36a2b97SVictor Raj 	return status;
6727c36a2b97SVictor Raj }
6728c36a2b97SVictor Raj 
6729c36a2b97SVictor Raj /**
6730334cb062SAnirudh Venkataramanan  * ice_replay_vsi_all_fltr - replay all filters stored in bookkeeping lists
67310f9d5027SAnirudh Venkataramanan  * @hw: pointer to the hardware structure
6732334cb062SAnirudh Venkataramanan  * @vsi_handle: driver VSI handle
67330f9d5027SAnirudh Venkataramanan  *
6734334cb062SAnirudh Venkataramanan  * Replays filters for requested VSI via vsi_handle.
67350f9d5027SAnirudh Venkataramanan  */
67365e24d598STony Nguyen int ice_replay_vsi_all_fltr(struct ice_hw *hw, u16 vsi_handle)
67370f9d5027SAnirudh Venkataramanan {
67380f9d5027SAnirudh Venkataramanan 	struct ice_switch_info *sw = hw->switch_info;
6739c36a2b97SVictor Raj 	int status;
67400f9d5027SAnirudh Venkataramanan 	u8 i;
67410f9d5027SAnirudh Venkataramanan 
6742c36a2b97SVictor Raj 	for (i = 0; i < ICE_MAX_NUM_RECIPES; i++) {
6743334cb062SAnirudh Venkataramanan 		struct list_head *head;
67440f9d5027SAnirudh Venkataramanan 
6745334cb062SAnirudh Venkataramanan 		head = &sw->recp_list[i].filt_replay_rules;
6746c36a2b97SVictor Raj 		if (!sw->recp_list[i].adv_rule)
6747334cb062SAnirudh Venkataramanan 			status = ice_replay_vsi_fltr(hw, vsi_handle, i, head);
6748c36a2b97SVictor Raj 		else
6749c36a2b97SVictor Raj 			status = ice_replay_vsi_adv_rule(hw, vsi_handle, head);
67500f9d5027SAnirudh Venkataramanan 		if (status)
67510f9d5027SAnirudh Venkataramanan 			return status;
67520f9d5027SAnirudh Venkataramanan 	}
67530f9d5027SAnirudh Venkataramanan 	return status;
67540f9d5027SAnirudh Venkataramanan }
6755334cb062SAnirudh Venkataramanan 
6756334cb062SAnirudh Venkataramanan /**
6757334cb062SAnirudh Venkataramanan  * ice_rm_all_sw_replay_rule_info - deletes filter replay rules
6758f9867df6SAnirudh Venkataramanan  * @hw: pointer to the HW struct
6759334cb062SAnirudh Venkataramanan  *
6760334cb062SAnirudh Venkataramanan  * Deletes the filter replay rules.
6761334cb062SAnirudh Venkataramanan  */
6762334cb062SAnirudh Venkataramanan void ice_rm_all_sw_replay_rule_info(struct ice_hw *hw)
6763334cb062SAnirudh Venkataramanan {
6764334cb062SAnirudh Venkataramanan 	struct ice_switch_info *sw = hw->switch_info;
6765334cb062SAnirudh Venkataramanan 	u8 i;
6766334cb062SAnirudh Venkataramanan 
6767334cb062SAnirudh Venkataramanan 	if (!sw)
6768334cb062SAnirudh Venkataramanan 		return;
6769334cb062SAnirudh Venkataramanan 
67708b8ef05bSVictor Raj 	for (i = 0; i < ICE_MAX_NUM_RECIPES; i++) {
6771334cb062SAnirudh Venkataramanan 		if (!list_empty(&sw->recp_list[i].filt_replay_rules)) {
6772334cb062SAnirudh Venkataramanan 			struct list_head *l_head;
6773334cb062SAnirudh Venkataramanan 
6774334cb062SAnirudh Venkataramanan 			l_head = &sw->recp_list[i].filt_replay_rules;
67758b8ef05bSVictor Raj 			if (!sw->recp_list[i].adv_rule)
6776334cb062SAnirudh Venkataramanan 				ice_rem_sw_rule_info(hw, l_head);
67778b8ef05bSVictor Raj 			else
67788b8ef05bSVictor Raj 				ice_rem_adv_rule_info(hw, l_head);
6779334cb062SAnirudh Venkataramanan 		}
6780334cb062SAnirudh Venkataramanan 	}
6781334cb062SAnirudh Venkataramanan }
6782