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 static const u8 dummy_eth_header[DUMMY_ETH_HDR_LEN] = { 0x2, 0, 0, 0, 0, 0,
299daf8208SAnirudh Venkataramanan 							0x2, 0, 0, 0, 0, 0,
309daf8208SAnirudh Venkataramanan 							0x81, 0, 0, 0};
319daf8208SAnirudh Venkataramanan 
32e33163a4SAlexander Lobakin enum {
3326395726SMartyna Szapar-Mudlaw 	ICE_PKT_OUTER_IPV6	= BIT(0),
3426395726SMartyna Szapar-Mudlaw 	ICE_PKT_TUN_GTPC	= BIT(1),
3526395726SMartyna Szapar-Mudlaw 	ICE_PKT_TUN_GTPU	= BIT(2),
3626395726SMartyna Szapar-Mudlaw 	ICE_PKT_TUN_NVGRE	= BIT(3),
3726395726SMartyna Szapar-Mudlaw 	ICE_PKT_TUN_UDP		= BIT(4),
3826395726SMartyna Szapar-Mudlaw 	ICE_PKT_INNER_IPV6	= BIT(5),
3926395726SMartyna Szapar-Mudlaw 	ICE_PKT_INNER_TCP	= BIT(6),
4026395726SMartyna Szapar-Mudlaw 	ICE_PKT_INNER_UDP	= BIT(7),
4126395726SMartyna Szapar-Mudlaw 	ICE_PKT_GTP_NOPAY	= BIT(8),
4226395726SMartyna Szapar-Mudlaw 	ICE_PKT_KMALLOC		= BIT(9),
43cd8efeeeSMarcin Szycik 	ICE_PKT_PPPOE		= BIT(10),
44cd634549SMarcin Szycik 	ICE_PKT_L2TPV3		= BIT(11),
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 
1261cd634549SMarcin Szycik ICE_DECLARE_PKT_OFFSETS(ipv4_l2tpv3) = {
1262cd634549SMarcin Szycik 	{ ICE_MAC_OFOS,		0 },
1263cd634549SMarcin Szycik 	{ ICE_ETYPE_OL,		12 },
1264cd634549SMarcin Szycik 	{ ICE_IPV4_OFOS,	14 },
1265cd634549SMarcin Szycik 	{ ICE_L2TPV3,		34 },
1266cd634549SMarcin Szycik 	{ ICE_PROTOCOL_LAST,	0 },
1267cd634549SMarcin Szycik };
1268cd634549SMarcin Szycik 
1269cd634549SMarcin Szycik ICE_DECLARE_PKT_TEMPLATE(ipv4_l2tpv3) = {
1270cd634549SMarcin Szycik 	0x00, 0x00, 0x00, 0x00, /* ICE_MAC_OFOS 0 */
1271cd634549SMarcin Szycik 	0x00, 0x00, 0x00, 0x00,
1272cd634549SMarcin Szycik 	0x00, 0x00, 0x00, 0x00,
1273cd634549SMarcin Szycik 
1274cd634549SMarcin Szycik 	0x08, 0x00,		/* ICE_ETYPE_OL 12 */
1275cd634549SMarcin Szycik 
1276cd634549SMarcin Szycik 	0x45, 0x00, 0x00, 0x20, /* ICE_IPV4_IL 14 */
1277cd634549SMarcin Szycik 	0x00, 0x00, 0x40, 0x00,
1278cd634549SMarcin Szycik 	0x40, 0x73, 0x00, 0x00,
1279cd634549SMarcin Szycik 	0x00, 0x00, 0x00, 0x00,
1280cd634549SMarcin Szycik 	0x00, 0x00, 0x00, 0x00,
1281cd634549SMarcin Szycik 
1282cd634549SMarcin Szycik 	0x00, 0x00, 0x00, 0x00, /* ICE_L2TPV3 34 */
1283cd634549SMarcin Szycik 	0x00, 0x00, 0x00, 0x00,
1284cd634549SMarcin Szycik 	0x00, 0x00, 0x00, 0x00,
1285cd634549SMarcin Szycik 	0x00, 0x00,		/* 2 bytes for 4 bytes alignment */
1286cd634549SMarcin Szycik };
1287cd634549SMarcin Szycik 
1288cd634549SMarcin Szycik ICE_DECLARE_PKT_OFFSETS(ipv6_l2tpv3) = {
1289cd634549SMarcin Szycik 	{ ICE_MAC_OFOS,		0 },
1290cd634549SMarcin Szycik 	{ ICE_ETYPE_OL,		12 },
1291cd634549SMarcin Szycik 	{ ICE_IPV6_OFOS,	14 },
1292cd634549SMarcin Szycik 	{ ICE_L2TPV3,		54 },
1293cd634549SMarcin Szycik 	{ ICE_PROTOCOL_LAST,	0 },
1294cd634549SMarcin Szycik };
1295cd634549SMarcin Szycik 
1296cd634549SMarcin Szycik ICE_DECLARE_PKT_TEMPLATE(ipv6_l2tpv3) = {
1297cd634549SMarcin Szycik 	0x00, 0x00, 0x00, 0x00, /* ICE_MAC_OFOS 0 */
1298cd634549SMarcin Szycik 	0x00, 0x00, 0x00, 0x00,
1299cd634549SMarcin Szycik 	0x00, 0x00, 0x00, 0x00,
1300cd634549SMarcin Szycik 
1301cd634549SMarcin Szycik 	0x86, 0xDD,		/* ICE_ETYPE_OL 12 */
1302cd634549SMarcin Szycik 
1303cd634549SMarcin Szycik 	0x60, 0x00, 0x00, 0x00, /* ICE_IPV6_IL 14 */
1304cd634549SMarcin Szycik 	0x00, 0x0c, 0x73, 0x40,
1305cd634549SMarcin Szycik 	0x00, 0x00, 0x00, 0x00,
1306cd634549SMarcin Szycik 	0x00, 0x00, 0x00, 0x00,
1307cd634549SMarcin Szycik 	0x00, 0x00, 0x00, 0x00,
1308cd634549SMarcin Szycik 	0x00, 0x00, 0x00, 0x00,
1309cd634549SMarcin Szycik 	0x00, 0x00, 0x00, 0x00,
1310cd634549SMarcin Szycik 	0x00, 0x00, 0x00, 0x00,
1311cd634549SMarcin Szycik 	0x00, 0x00, 0x00, 0x00,
1312cd634549SMarcin Szycik 	0x00, 0x00, 0x00, 0x00,
1313cd634549SMarcin Szycik 
1314cd634549SMarcin Szycik 	0x00, 0x00, 0x00, 0x00, /* ICE_L2TPV3 54 */
1315cd634549SMarcin Szycik 	0x00, 0x00, 0x00, 0x00,
1316cd634549SMarcin Szycik 	0x00, 0x00, 0x00, 0x00,
1317cd634549SMarcin Szycik 	0x00, 0x00,		/* 2 bytes for 4 bytes alignment */
1318cd634549SMarcin Szycik };
1319cd634549SMarcin Szycik 
1320e33163a4SAlexander Lobakin static const struct ice_dummy_pkt_profile ice_dummy_pkt_profiles[] = {
1321e33163a4SAlexander Lobakin 	ICE_PKT_PROFILE(ipv6_gtp, ICE_PKT_TUN_GTPU | ICE_PKT_OUTER_IPV6 |
1322e33163a4SAlexander Lobakin 				  ICE_PKT_GTP_NOPAY),
1323e33163a4SAlexander Lobakin 	ICE_PKT_PROFILE(ipv6_gtpu_ipv6_udp, ICE_PKT_TUN_GTPU |
1324e33163a4SAlexander Lobakin 					    ICE_PKT_OUTER_IPV6 |
1325e33163a4SAlexander Lobakin 					    ICE_PKT_INNER_IPV6 |
1326e33163a4SAlexander Lobakin 					    ICE_PKT_INNER_UDP),
1327e33163a4SAlexander Lobakin 	ICE_PKT_PROFILE(ipv6_gtpu_ipv6_tcp, ICE_PKT_TUN_GTPU |
1328e33163a4SAlexander Lobakin 					    ICE_PKT_OUTER_IPV6 |
1329e33163a4SAlexander Lobakin 					    ICE_PKT_INNER_IPV6),
1330e33163a4SAlexander Lobakin 	ICE_PKT_PROFILE(ipv6_gtpu_ipv4_udp, ICE_PKT_TUN_GTPU |
1331e33163a4SAlexander Lobakin 					    ICE_PKT_OUTER_IPV6 |
1332e33163a4SAlexander Lobakin 					    ICE_PKT_INNER_UDP),
1333e33163a4SAlexander Lobakin 	ICE_PKT_PROFILE(ipv6_gtpu_ipv4_tcp, ICE_PKT_TUN_GTPU |
1334e33163a4SAlexander Lobakin 					    ICE_PKT_OUTER_IPV6),
1335e33163a4SAlexander Lobakin 	ICE_PKT_PROFILE(ipv4_gtpu_ipv4, ICE_PKT_TUN_GTPU | ICE_PKT_GTP_NOPAY),
1336e33163a4SAlexander Lobakin 	ICE_PKT_PROFILE(ipv4_gtpu_ipv6_udp, ICE_PKT_TUN_GTPU |
1337e33163a4SAlexander Lobakin 					    ICE_PKT_INNER_IPV6 |
1338e33163a4SAlexander Lobakin 					    ICE_PKT_INNER_UDP),
1339e33163a4SAlexander Lobakin 	ICE_PKT_PROFILE(ipv4_gtpu_ipv6_tcp, ICE_PKT_TUN_GTPU |
1340e33163a4SAlexander Lobakin 					    ICE_PKT_INNER_IPV6),
1341e33163a4SAlexander Lobakin 	ICE_PKT_PROFILE(ipv4_gtpu_ipv4_udp, ICE_PKT_TUN_GTPU |
1342e33163a4SAlexander Lobakin 					    ICE_PKT_INNER_UDP),
1343e33163a4SAlexander Lobakin 	ICE_PKT_PROFILE(ipv4_gtpu_ipv4_tcp, ICE_PKT_TUN_GTPU),
1344e33163a4SAlexander Lobakin 	ICE_PKT_PROFILE(ipv6_gtp, ICE_PKT_TUN_GTPC | ICE_PKT_OUTER_IPV6),
1345e33163a4SAlexander Lobakin 	ICE_PKT_PROFILE(ipv4_gtpu_ipv4, ICE_PKT_TUN_GTPC),
1346cd8efeeeSMarcin Szycik 	ICE_PKT_PROFILE(pppoe_ipv6_udp, ICE_PKT_PPPOE | ICE_PKT_OUTER_IPV6 |
1347cd8efeeeSMarcin Szycik 					ICE_PKT_INNER_UDP),
1348cd8efeeeSMarcin Szycik 	ICE_PKT_PROFILE(pppoe_ipv6_tcp, ICE_PKT_PPPOE | ICE_PKT_OUTER_IPV6),
1349cd8efeeeSMarcin Szycik 	ICE_PKT_PROFILE(pppoe_ipv4_udp, ICE_PKT_PPPOE | ICE_PKT_INNER_UDP),
1350cd8efeeeSMarcin Szycik 	ICE_PKT_PROFILE(pppoe_ipv4_tcp, ICE_PKT_PPPOE),
1351e33163a4SAlexander Lobakin 	ICE_PKT_PROFILE(gre_ipv6_tcp, ICE_PKT_TUN_NVGRE | ICE_PKT_INNER_IPV6 |
1352e33163a4SAlexander Lobakin 				      ICE_PKT_INNER_TCP),
1353e33163a4SAlexander Lobakin 	ICE_PKT_PROFILE(gre_tcp, ICE_PKT_TUN_NVGRE | ICE_PKT_INNER_TCP),
1354e33163a4SAlexander Lobakin 	ICE_PKT_PROFILE(gre_ipv6_udp, ICE_PKT_TUN_NVGRE | ICE_PKT_INNER_IPV6),
1355e33163a4SAlexander Lobakin 	ICE_PKT_PROFILE(gre_udp, ICE_PKT_TUN_NVGRE),
1356e33163a4SAlexander Lobakin 	ICE_PKT_PROFILE(udp_tun_ipv6_tcp, ICE_PKT_TUN_UDP |
1357e33163a4SAlexander Lobakin 					  ICE_PKT_INNER_IPV6 |
1358e33163a4SAlexander Lobakin 					  ICE_PKT_INNER_TCP),
1359cd634549SMarcin Szycik 	ICE_PKT_PROFILE(ipv6_l2tpv3, ICE_PKT_L2TPV3 | ICE_PKT_OUTER_IPV6),
1360cd634549SMarcin Szycik 	ICE_PKT_PROFILE(ipv4_l2tpv3, ICE_PKT_L2TPV3),
1361e33163a4SAlexander Lobakin 	ICE_PKT_PROFILE(udp_tun_tcp, ICE_PKT_TUN_UDP | ICE_PKT_INNER_TCP),
1362e33163a4SAlexander Lobakin 	ICE_PKT_PROFILE(udp_tun_ipv6_udp, ICE_PKT_TUN_UDP |
1363e33163a4SAlexander Lobakin 					  ICE_PKT_INNER_IPV6),
1364e33163a4SAlexander Lobakin 	ICE_PKT_PROFILE(udp_tun_udp, ICE_PKT_TUN_UDP),
1365e33163a4SAlexander Lobakin 	ICE_PKT_PROFILE(udp_ipv6, ICE_PKT_OUTER_IPV6 | ICE_PKT_INNER_UDP),
1366e33163a4SAlexander Lobakin 	ICE_PKT_PROFILE(udp, ICE_PKT_INNER_UDP),
1367e33163a4SAlexander Lobakin 	ICE_PKT_PROFILE(tcp_ipv6, ICE_PKT_OUTER_IPV6),
1368e33163a4SAlexander Lobakin 	ICE_PKT_PROFILE(tcp, 0),
1369e33163a4SAlexander Lobakin };
1370e33163a4SAlexander Lobakin 
1371fd2a6b71SDan Nowlin /* this is a recipe to profile association bitmap */
1372fd2a6b71SDan Nowlin static DECLARE_BITMAP(recipe_to_profile[ICE_MAX_NUM_RECIPES],
1373fd2a6b71SDan Nowlin 			  ICE_MAX_NUM_PROFILES);
1374fd2a6b71SDan Nowlin 
1375fd2a6b71SDan Nowlin /* this is a profile to recipe association bitmap */
1376fd2a6b71SDan Nowlin static DECLARE_BITMAP(profile_to_recipe[ICE_MAX_NUM_PROFILES],
1377fd2a6b71SDan Nowlin 			  ICE_MAX_NUM_RECIPES);
1378fd2a6b71SDan Nowlin 
13799daf8208SAnirudh Venkataramanan /**
138080d144c9SAnirudh Venkataramanan  * ice_init_def_sw_recp - initialize the recipe book keeping tables
1381f9867df6SAnirudh Venkataramanan  * @hw: pointer to the HW struct
138280d144c9SAnirudh Venkataramanan  *
138380d144c9SAnirudh Venkataramanan  * Allocate memory for the entire recipe table and initialize the structures/
138480d144c9SAnirudh Venkataramanan  * entries corresponding to basic recipes.
138580d144c9SAnirudh Venkataramanan  */
13865e24d598STony Nguyen int ice_init_def_sw_recp(struct ice_hw *hw)
138780d144c9SAnirudh Venkataramanan {
138880d144c9SAnirudh Venkataramanan 	struct ice_sw_recipe *recps;
138980d144c9SAnirudh Venkataramanan 	u8 i;
139080d144c9SAnirudh Venkataramanan 
139180d144c9SAnirudh Venkataramanan 	recps = devm_kcalloc(ice_hw_to_dev(hw), ICE_MAX_NUM_RECIPES,
1392c6dfd690SBruce Allan 			     sizeof(*recps), GFP_KERNEL);
139380d144c9SAnirudh Venkataramanan 	if (!recps)
1394d54699e2STony Nguyen 		return -ENOMEM;
139580d144c9SAnirudh Venkataramanan 
1396450052a4SDan Nowlin 	for (i = 0; i < ICE_MAX_NUM_RECIPES; i++) {
139780d144c9SAnirudh Venkataramanan 		recps[i].root_rid = i;
139880d144c9SAnirudh Venkataramanan 		INIT_LIST_HEAD(&recps[i].filt_rules);
1399334cb062SAnirudh Venkataramanan 		INIT_LIST_HEAD(&recps[i].filt_replay_rules);
1400450052a4SDan Nowlin 		INIT_LIST_HEAD(&recps[i].rg_list);
140180d144c9SAnirudh Venkataramanan 		mutex_init(&recps[i].filt_rule_lock);
140280d144c9SAnirudh Venkataramanan 	}
140380d144c9SAnirudh Venkataramanan 
140480d144c9SAnirudh Venkataramanan 	hw->switch_info->recp_list = recps;
140580d144c9SAnirudh Venkataramanan 
140680d144c9SAnirudh Venkataramanan 	return 0;
140780d144c9SAnirudh Venkataramanan }
140880d144c9SAnirudh Venkataramanan 
140980d144c9SAnirudh Venkataramanan /**
14109c20346bSAnirudh Venkataramanan  * ice_aq_get_sw_cfg - get switch configuration
14119c20346bSAnirudh Venkataramanan  * @hw: pointer to the hardware structure
14129c20346bSAnirudh Venkataramanan  * @buf: pointer to the result buffer
14139c20346bSAnirudh Venkataramanan  * @buf_size: length of the buffer available for response
14149c20346bSAnirudh Venkataramanan  * @req_desc: pointer to requested descriptor
14159c20346bSAnirudh Venkataramanan  * @num_elems: pointer to number of elements
14169c20346bSAnirudh Venkataramanan  * @cd: pointer to command details structure or NULL
14179c20346bSAnirudh Venkataramanan  *
1418b3c38904SBruce Allan  * Get switch configuration (0x0200) to be placed in buf.
14199c20346bSAnirudh Venkataramanan  * This admin command returns information such as initial VSI/port number
14209c20346bSAnirudh Venkataramanan  * and switch ID it belongs to.
14219c20346bSAnirudh Venkataramanan  *
14229c20346bSAnirudh Venkataramanan  * NOTE: *req_desc is both an input/output parameter.
14239c20346bSAnirudh Venkataramanan  * The caller of this function first calls this function with *request_desc set
14249c20346bSAnirudh Venkataramanan  * to 0. If the response from f/w has *req_desc set to 0, all the switch
14259c20346bSAnirudh Venkataramanan  * configuration information has been returned; if non-zero (meaning not all
14269c20346bSAnirudh Venkataramanan  * the information was returned), the caller should call this function again
14279c20346bSAnirudh Venkataramanan  * with *req_desc set to the previous value returned by f/w to get the
14289c20346bSAnirudh Venkataramanan  * next block of switch configuration information.
14299c20346bSAnirudh Venkataramanan  *
14309c20346bSAnirudh Venkataramanan  * *num_elems is output only parameter. This reflects the number of elements
14319c20346bSAnirudh Venkataramanan  * in response buffer. The caller of this function to use *num_elems while
14329c20346bSAnirudh Venkataramanan  * parsing the response buffer.
14339c20346bSAnirudh Venkataramanan  */
14345e24d598STony Nguyen static int
1435b3c38904SBruce Allan ice_aq_get_sw_cfg(struct ice_hw *hw, struct ice_aqc_get_sw_cfg_resp_elem *buf,
14369c20346bSAnirudh Venkataramanan 		  u16 buf_size, u16 *req_desc, u16 *num_elems,
14379c20346bSAnirudh Venkataramanan 		  struct ice_sq_cd *cd)
14389c20346bSAnirudh Venkataramanan {
14399c20346bSAnirudh Venkataramanan 	struct ice_aqc_get_sw_cfg *cmd;
14409c20346bSAnirudh Venkataramanan 	struct ice_aq_desc desc;
14415e24d598STony Nguyen 	int status;
14429c20346bSAnirudh Venkataramanan 
14439c20346bSAnirudh Venkataramanan 	ice_fill_dflt_direct_cmd_desc(&desc, ice_aqc_opc_get_sw_cfg);
14449c20346bSAnirudh Venkataramanan 	cmd = &desc.params.get_sw_conf;
14459c20346bSAnirudh Venkataramanan 	cmd->element = cpu_to_le16(*req_desc);
14469c20346bSAnirudh Venkataramanan 
14479c20346bSAnirudh Venkataramanan 	status = ice_aq_send_cmd(hw, &desc, buf, buf_size, cd);
14489c20346bSAnirudh Venkataramanan 	if (!status) {
14499c20346bSAnirudh Venkataramanan 		*req_desc = le16_to_cpu(cmd->element);
14509c20346bSAnirudh Venkataramanan 		*num_elems = le16_to_cpu(cmd->num_elems);
14519c20346bSAnirudh Venkataramanan 	}
14529c20346bSAnirudh Venkataramanan 
14539c20346bSAnirudh Venkataramanan 	return status;
14549c20346bSAnirudh Venkataramanan }
14559c20346bSAnirudh Venkataramanan 
14563a858ba3SAnirudh Venkataramanan /**
14573a858ba3SAnirudh Venkataramanan  * ice_aq_add_vsi
1458f9867df6SAnirudh Venkataramanan  * @hw: pointer to the HW struct
14593a858ba3SAnirudh Venkataramanan  * @vsi_ctx: pointer to a VSI context struct
14603a858ba3SAnirudh Venkataramanan  * @cd: pointer to command details structure or NULL
14613a858ba3SAnirudh Venkataramanan  *
14623a858ba3SAnirudh Venkataramanan  * Add a VSI context to the hardware (0x0210)
14633a858ba3SAnirudh Venkataramanan  */
14645e24d598STony Nguyen static int
14653a858ba3SAnirudh Venkataramanan ice_aq_add_vsi(struct ice_hw *hw, struct ice_vsi_ctx *vsi_ctx,
14663a858ba3SAnirudh Venkataramanan 	       struct ice_sq_cd *cd)
14673a858ba3SAnirudh Venkataramanan {
14683a858ba3SAnirudh Venkataramanan 	struct ice_aqc_add_update_free_vsi_resp *res;
14693a858ba3SAnirudh Venkataramanan 	struct ice_aqc_add_get_update_free_vsi *cmd;
14703a858ba3SAnirudh Venkataramanan 	struct ice_aq_desc desc;
14715e24d598STony Nguyen 	int status;
14723a858ba3SAnirudh Venkataramanan 
14733a858ba3SAnirudh Venkataramanan 	cmd = &desc.params.vsi_cmd;
14740f9d5027SAnirudh Venkataramanan 	res = &desc.params.add_update_free_vsi_res;
14753a858ba3SAnirudh Venkataramanan 
14763a858ba3SAnirudh Venkataramanan 	ice_fill_dflt_direct_cmd_desc(&desc, ice_aqc_opc_add_vsi);
14773a858ba3SAnirudh Venkataramanan 
14783a858ba3SAnirudh Venkataramanan 	if (!vsi_ctx->alloc_from_pool)
14793a858ba3SAnirudh Venkataramanan 		cmd->vsi_num = cpu_to_le16(vsi_ctx->vsi_num |
14803a858ba3SAnirudh Venkataramanan 					   ICE_AQ_VSI_IS_VALID);
14811071a835SAnirudh Venkataramanan 	cmd->vf_id = vsi_ctx->vf_num;
14823a858ba3SAnirudh Venkataramanan 
14833a858ba3SAnirudh Venkataramanan 	cmd->vsi_flags = cpu_to_le16(vsi_ctx->flags);
14843a858ba3SAnirudh Venkataramanan 
14853a858ba3SAnirudh Venkataramanan 	desc.flags |= cpu_to_le16(ICE_AQ_FLAG_RD);
14863a858ba3SAnirudh Venkataramanan 
14873a858ba3SAnirudh Venkataramanan 	status = ice_aq_send_cmd(hw, &desc, &vsi_ctx->info,
14883a858ba3SAnirudh Venkataramanan 				 sizeof(vsi_ctx->info), cd);
14893a858ba3SAnirudh Venkataramanan 
14903a858ba3SAnirudh Venkataramanan 	if (!status) {
14913a858ba3SAnirudh Venkataramanan 		vsi_ctx->vsi_num = le16_to_cpu(res->vsi_num) & ICE_AQ_VSI_NUM_M;
14923a858ba3SAnirudh Venkataramanan 		vsi_ctx->vsis_allocd = le16_to_cpu(res->vsi_used);
14933a858ba3SAnirudh Venkataramanan 		vsi_ctx->vsis_unallocated = le16_to_cpu(res->vsi_free);
14943a858ba3SAnirudh Venkataramanan 	}
14953a858ba3SAnirudh Venkataramanan 
14963a858ba3SAnirudh Venkataramanan 	return status;
14973a858ba3SAnirudh Venkataramanan }
14983a858ba3SAnirudh Venkataramanan 
14993a858ba3SAnirudh Venkataramanan /**
15000f9d5027SAnirudh Venkataramanan  * ice_aq_free_vsi
1501f9867df6SAnirudh Venkataramanan  * @hw: pointer to the HW struct
15020f9d5027SAnirudh Venkataramanan  * @vsi_ctx: pointer to a VSI context struct
15030f9d5027SAnirudh Venkataramanan  * @keep_vsi_alloc: keep VSI allocation as part of this PF's resources
15040f9d5027SAnirudh Venkataramanan  * @cd: pointer to command details structure or NULL
15050f9d5027SAnirudh Venkataramanan  *
15060f9d5027SAnirudh Venkataramanan  * Free VSI context info from hardware (0x0213)
15070f9d5027SAnirudh Venkataramanan  */
15085e24d598STony Nguyen static int
15090f9d5027SAnirudh Venkataramanan ice_aq_free_vsi(struct ice_hw *hw, struct ice_vsi_ctx *vsi_ctx,
15100f9d5027SAnirudh Venkataramanan 		bool keep_vsi_alloc, struct ice_sq_cd *cd)
15110f9d5027SAnirudh Venkataramanan {
15120f9d5027SAnirudh Venkataramanan 	struct ice_aqc_add_update_free_vsi_resp *resp;
15130f9d5027SAnirudh Venkataramanan 	struct ice_aqc_add_get_update_free_vsi *cmd;
15140f9d5027SAnirudh Venkataramanan 	struct ice_aq_desc desc;
15155e24d598STony Nguyen 	int status;
15160f9d5027SAnirudh Venkataramanan 
15170f9d5027SAnirudh Venkataramanan 	cmd = &desc.params.vsi_cmd;
15180f9d5027SAnirudh Venkataramanan 	resp = &desc.params.add_update_free_vsi_res;
15190f9d5027SAnirudh Venkataramanan 
15200f9d5027SAnirudh Venkataramanan 	ice_fill_dflt_direct_cmd_desc(&desc, ice_aqc_opc_free_vsi);
15210f9d5027SAnirudh Venkataramanan 
15220f9d5027SAnirudh Venkataramanan 	cmd->vsi_num = cpu_to_le16(vsi_ctx->vsi_num | ICE_AQ_VSI_IS_VALID);
15230f9d5027SAnirudh Venkataramanan 	if (keep_vsi_alloc)
15240f9d5027SAnirudh Venkataramanan 		cmd->cmd_flags = cpu_to_le16(ICE_AQ_VSI_KEEP_ALLOC);
15250f9d5027SAnirudh Venkataramanan 
15260f9d5027SAnirudh Venkataramanan 	status = ice_aq_send_cmd(hw, &desc, NULL, 0, cd);
15270f9d5027SAnirudh Venkataramanan 	if (!status) {
15280f9d5027SAnirudh Venkataramanan 		vsi_ctx->vsis_allocd = le16_to_cpu(resp->vsi_used);
15290f9d5027SAnirudh Venkataramanan 		vsi_ctx->vsis_unallocated = le16_to_cpu(resp->vsi_free);
15300f9d5027SAnirudh Venkataramanan 	}
15310f9d5027SAnirudh Venkataramanan 
15320f9d5027SAnirudh Venkataramanan 	return status;
15330f9d5027SAnirudh Venkataramanan }
15340f9d5027SAnirudh Venkataramanan 
15350f9d5027SAnirudh Venkataramanan /**
15363a858ba3SAnirudh Venkataramanan  * ice_aq_update_vsi
1537f9867df6SAnirudh Venkataramanan  * @hw: pointer to the HW struct
15383a858ba3SAnirudh Venkataramanan  * @vsi_ctx: pointer to a VSI context struct
15393a858ba3SAnirudh Venkataramanan  * @cd: pointer to command details structure or NULL
15403a858ba3SAnirudh Venkataramanan  *
15413a858ba3SAnirudh Venkataramanan  * Update VSI context in the hardware (0x0211)
15423a858ba3SAnirudh Venkataramanan  */
15435e24d598STony Nguyen static int
15443a858ba3SAnirudh Venkataramanan ice_aq_update_vsi(struct ice_hw *hw, struct ice_vsi_ctx *vsi_ctx,
15453a858ba3SAnirudh Venkataramanan 		  struct ice_sq_cd *cd)
15463a858ba3SAnirudh Venkataramanan {
15473a858ba3SAnirudh Venkataramanan 	struct ice_aqc_add_update_free_vsi_resp *resp;
15483a858ba3SAnirudh Venkataramanan 	struct ice_aqc_add_get_update_free_vsi *cmd;
15493a858ba3SAnirudh Venkataramanan 	struct ice_aq_desc desc;
15505e24d598STony Nguyen 	int status;
15513a858ba3SAnirudh Venkataramanan 
15523a858ba3SAnirudh Venkataramanan 	cmd = &desc.params.vsi_cmd;
15530f9d5027SAnirudh Venkataramanan 	resp = &desc.params.add_update_free_vsi_res;
15543a858ba3SAnirudh Venkataramanan 
15553a858ba3SAnirudh Venkataramanan 	ice_fill_dflt_direct_cmd_desc(&desc, ice_aqc_opc_update_vsi);
15563a858ba3SAnirudh Venkataramanan 
15573a858ba3SAnirudh Venkataramanan 	cmd->vsi_num = cpu_to_le16(vsi_ctx->vsi_num | ICE_AQ_VSI_IS_VALID);
15583a858ba3SAnirudh Venkataramanan 
15593a858ba3SAnirudh Venkataramanan 	desc.flags |= cpu_to_le16(ICE_AQ_FLAG_RD);
15603a858ba3SAnirudh Venkataramanan 
15613a858ba3SAnirudh Venkataramanan 	status = ice_aq_send_cmd(hw, &desc, &vsi_ctx->info,
15623a858ba3SAnirudh Venkataramanan 				 sizeof(vsi_ctx->info), cd);
15633a858ba3SAnirudh Venkataramanan 
15643a858ba3SAnirudh Venkataramanan 	if (!status) {
15653a858ba3SAnirudh Venkataramanan 		vsi_ctx->vsis_allocd = le16_to_cpu(resp->vsi_used);
15663a858ba3SAnirudh Venkataramanan 		vsi_ctx->vsis_unallocated = le16_to_cpu(resp->vsi_free);
15673a858ba3SAnirudh Venkataramanan 	}
15683a858ba3SAnirudh Venkataramanan 
15693a858ba3SAnirudh Venkataramanan 	return status;
15703a858ba3SAnirudh Venkataramanan }
15713a858ba3SAnirudh Venkataramanan 
15723a858ba3SAnirudh Venkataramanan /**
15730f9d5027SAnirudh Venkataramanan  * ice_is_vsi_valid - check whether the VSI is valid or not
1574f9867df6SAnirudh Venkataramanan  * @hw: pointer to the HW struct
15750f9d5027SAnirudh Venkataramanan  * @vsi_handle: VSI handle
15760f9d5027SAnirudh Venkataramanan  *
15770f9d5027SAnirudh Venkataramanan  * check whether the VSI is valid or not
15780f9d5027SAnirudh Venkataramanan  */
15794fb33f31SAnirudh Venkataramanan bool ice_is_vsi_valid(struct ice_hw *hw, u16 vsi_handle)
15800f9d5027SAnirudh Venkataramanan {
15810f9d5027SAnirudh Venkataramanan 	return vsi_handle < ICE_MAX_VSI && hw->vsi_ctx[vsi_handle];
15820f9d5027SAnirudh Venkataramanan }
15830f9d5027SAnirudh Venkataramanan 
15840f9d5027SAnirudh Venkataramanan /**
1585f9867df6SAnirudh Venkataramanan  * ice_get_hw_vsi_num - return the HW VSI number
1586f9867df6SAnirudh Venkataramanan  * @hw: pointer to the HW struct
15870f9d5027SAnirudh Venkataramanan  * @vsi_handle: VSI handle
15880f9d5027SAnirudh Venkataramanan  *
1589f9867df6SAnirudh Venkataramanan  * return the HW VSI number
15900f9d5027SAnirudh Venkataramanan  * Caution: call this function only if VSI is valid (ice_is_vsi_valid)
15910f9d5027SAnirudh Venkataramanan  */
15924fb33f31SAnirudh Venkataramanan u16 ice_get_hw_vsi_num(struct ice_hw *hw, u16 vsi_handle)
15930f9d5027SAnirudh Venkataramanan {
15940f9d5027SAnirudh Venkataramanan 	return hw->vsi_ctx[vsi_handle]->vsi_num;
15950f9d5027SAnirudh Venkataramanan }
15960f9d5027SAnirudh Venkataramanan 
15970f9d5027SAnirudh Venkataramanan /**
15980f9d5027SAnirudh Venkataramanan  * ice_get_vsi_ctx - return the VSI context entry for a given VSI handle
1599f9867df6SAnirudh Venkataramanan  * @hw: pointer to the HW struct
16000f9d5027SAnirudh Venkataramanan  * @vsi_handle: VSI handle
16010f9d5027SAnirudh Venkataramanan  *
16020f9d5027SAnirudh Venkataramanan  * return the VSI context entry for a given VSI handle
16030f9d5027SAnirudh Venkataramanan  */
16044fb33f31SAnirudh Venkataramanan struct ice_vsi_ctx *ice_get_vsi_ctx(struct ice_hw *hw, u16 vsi_handle)
16050f9d5027SAnirudh Venkataramanan {
16060f9d5027SAnirudh Venkataramanan 	return (vsi_handle >= ICE_MAX_VSI) ? NULL : hw->vsi_ctx[vsi_handle];
16070f9d5027SAnirudh Venkataramanan }
16080f9d5027SAnirudh Venkataramanan 
16090f9d5027SAnirudh Venkataramanan /**
16100f9d5027SAnirudh Venkataramanan  * ice_save_vsi_ctx - save the VSI context for a given VSI handle
1611f9867df6SAnirudh Venkataramanan  * @hw: pointer to the HW struct
16120f9d5027SAnirudh Venkataramanan  * @vsi_handle: VSI handle
16130f9d5027SAnirudh Venkataramanan  * @vsi: VSI context pointer
16140f9d5027SAnirudh Venkataramanan  *
16150f9d5027SAnirudh Venkataramanan  * save the VSI context entry for a given VSI handle
16160f9d5027SAnirudh Venkataramanan  */
1617c8b7abddSBruce Allan static void
1618c8b7abddSBruce Allan ice_save_vsi_ctx(struct ice_hw *hw, u16 vsi_handle, struct ice_vsi_ctx *vsi)
16190f9d5027SAnirudh Venkataramanan {
16200f9d5027SAnirudh Venkataramanan 	hw->vsi_ctx[vsi_handle] = vsi;
16210f9d5027SAnirudh Venkataramanan }
16220f9d5027SAnirudh Venkataramanan 
16230f9d5027SAnirudh Venkataramanan /**
1624bb87ee0eSAnirudh Venkataramanan  * ice_clear_vsi_q_ctx - clear VSI queue contexts for all TCs
1625bb87ee0eSAnirudh Venkataramanan  * @hw: pointer to the HW struct
1626bb87ee0eSAnirudh Venkataramanan  * @vsi_handle: VSI handle
1627bb87ee0eSAnirudh Venkataramanan  */
1628bb87ee0eSAnirudh Venkataramanan static void ice_clear_vsi_q_ctx(struct ice_hw *hw, u16 vsi_handle)
1629bb87ee0eSAnirudh Venkataramanan {
1630ad667d62SPrzemek Kitszel 	struct ice_vsi_ctx *vsi = ice_get_vsi_ctx(hw, vsi_handle);
1631bb87ee0eSAnirudh Venkataramanan 	u8 i;
1632bb87ee0eSAnirudh Venkataramanan 
1633bb87ee0eSAnirudh Venkataramanan 	if (!vsi)
1634bb87ee0eSAnirudh Venkataramanan 		return;
1635bb87ee0eSAnirudh Venkataramanan 	ice_for_each_traffic_class(i) {
1636bb87ee0eSAnirudh Venkataramanan 		devm_kfree(ice_hw_to_dev(hw), vsi->lan_q_ctx[i]);
1637bb87ee0eSAnirudh Venkataramanan 		vsi->lan_q_ctx[i] = NULL;
1638348048e7SDave Ertman 		devm_kfree(ice_hw_to_dev(hw), vsi->rdma_q_ctx[i]);
1639348048e7SDave Ertman 		vsi->rdma_q_ctx[i] = NULL;
1640348048e7SDave Ertman 	}
1641bb87ee0eSAnirudh Venkataramanan }
1642bb87ee0eSAnirudh Venkataramanan 
1643bb87ee0eSAnirudh Venkataramanan /**
16440f9d5027SAnirudh Venkataramanan  * ice_clear_vsi_ctx - clear the VSI context entry
1645f9867df6SAnirudh Venkataramanan  * @hw: pointer to the HW struct
16460f9d5027SAnirudh Venkataramanan  * @vsi_handle: VSI handle
16470f9d5027SAnirudh Venkataramanan  *
16480f9d5027SAnirudh Venkataramanan  * clear the VSI context entry
16490f9d5027SAnirudh Venkataramanan  */
16500f9d5027SAnirudh Venkataramanan static void ice_clear_vsi_ctx(struct ice_hw *hw, u16 vsi_handle)
16510f9d5027SAnirudh Venkataramanan {
16520f9d5027SAnirudh Venkataramanan 	struct ice_vsi_ctx *vsi;
16530f9d5027SAnirudh Venkataramanan 
16540f9d5027SAnirudh Venkataramanan 	vsi = ice_get_vsi_ctx(hw, vsi_handle);
16550f9d5027SAnirudh Venkataramanan 	if (vsi) {
1656bb87ee0eSAnirudh Venkataramanan 		ice_clear_vsi_q_ctx(hw, vsi_handle);
16570f9d5027SAnirudh Venkataramanan 		devm_kfree(ice_hw_to_dev(hw), vsi);
16580f9d5027SAnirudh Venkataramanan 		hw->vsi_ctx[vsi_handle] = NULL;
16590f9d5027SAnirudh Venkataramanan 	}
16600f9d5027SAnirudh Venkataramanan }
16610f9d5027SAnirudh Venkataramanan 
16620f9d5027SAnirudh Venkataramanan /**
166333e055fcSVictor Raj  * ice_clear_all_vsi_ctx - clear all the VSI context entries
1664f9867df6SAnirudh Venkataramanan  * @hw: pointer to the HW struct
166533e055fcSVictor Raj  */
166633e055fcSVictor Raj void ice_clear_all_vsi_ctx(struct ice_hw *hw)
166733e055fcSVictor Raj {
166833e055fcSVictor Raj 	u16 i;
166933e055fcSVictor Raj 
167033e055fcSVictor Raj 	for (i = 0; i < ICE_MAX_VSI; i++)
167133e055fcSVictor Raj 		ice_clear_vsi_ctx(hw, i);
167233e055fcSVictor Raj }
167333e055fcSVictor Raj 
167433e055fcSVictor Raj /**
16750f9d5027SAnirudh Venkataramanan  * ice_add_vsi - add VSI context to the hardware and VSI handle list
1676f9867df6SAnirudh Venkataramanan  * @hw: pointer to the HW struct
16770f9d5027SAnirudh Venkataramanan  * @vsi_handle: unique VSI handle provided by drivers
16780f9d5027SAnirudh Venkataramanan  * @vsi_ctx: pointer to a VSI context struct
16790f9d5027SAnirudh Venkataramanan  * @cd: pointer to command details structure or NULL
16800f9d5027SAnirudh Venkataramanan  *
16810f9d5027SAnirudh Venkataramanan  * Add a VSI context to the hardware also add it into the VSI handle list.
16820f9d5027SAnirudh Venkataramanan  * If this function gets called after reset for existing VSIs then update
16830f9d5027SAnirudh Venkataramanan  * with the new HW VSI number in the corresponding VSI handle list entry.
16840f9d5027SAnirudh Venkataramanan  */
16855e24d598STony Nguyen int
16860f9d5027SAnirudh Venkataramanan ice_add_vsi(struct ice_hw *hw, u16 vsi_handle, struct ice_vsi_ctx *vsi_ctx,
16870f9d5027SAnirudh Venkataramanan 	    struct ice_sq_cd *cd)
16880f9d5027SAnirudh Venkataramanan {
16890f9d5027SAnirudh Venkataramanan 	struct ice_vsi_ctx *tmp_vsi_ctx;
16905e24d598STony Nguyen 	int status;
16910f9d5027SAnirudh Venkataramanan 
16920f9d5027SAnirudh Venkataramanan 	if (vsi_handle >= ICE_MAX_VSI)
1693d54699e2STony Nguyen 		return -EINVAL;
16940f9d5027SAnirudh Venkataramanan 	status = ice_aq_add_vsi(hw, vsi_ctx, cd);
16950f9d5027SAnirudh Venkataramanan 	if (status)
16960f9d5027SAnirudh Venkataramanan 		return status;
16970f9d5027SAnirudh Venkataramanan 	tmp_vsi_ctx = ice_get_vsi_ctx(hw, vsi_handle);
16980f9d5027SAnirudh Venkataramanan 	if (!tmp_vsi_ctx) {
1699f9867df6SAnirudh Venkataramanan 		/* Create a new VSI context */
17000f9d5027SAnirudh Venkataramanan 		tmp_vsi_ctx = devm_kzalloc(ice_hw_to_dev(hw),
17010f9d5027SAnirudh Venkataramanan 					   sizeof(*tmp_vsi_ctx), GFP_KERNEL);
17020f9d5027SAnirudh Venkataramanan 		if (!tmp_vsi_ctx) {
17030f9d5027SAnirudh Venkataramanan 			ice_aq_free_vsi(hw, vsi_ctx, false, cd);
1704d54699e2STony Nguyen 			return -ENOMEM;
17050f9d5027SAnirudh Venkataramanan 		}
17060f9d5027SAnirudh Venkataramanan 		*tmp_vsi_ctx = *vsi_ctx;
17070f9d5027SAnirudh Venkataramanan 		ice_save_vsi_ctx(hw, vsi_handle, tmp_vsi_ctx);
17080f9d5027SAnirudh Venkataramanan 	} else {
17090f9d5027SAnirudh Venkataramanan 		/* update with new HW VSI num */
17100f9d5027SAnirudh Venkataramanan 		tmp_vsi_ctx->vsi_num = vsi_ctx->vsi_num;
17110f9d5027SAnirudh Venkataramanan 	}
17120f9d5027SAnirudh Venkataramanan 
17131b5c19c7SBruce Allan 	return 0;
17140f9d5027SAnirudh Venkataramanan }
17150f9d5027SAnirudh Venkataramanan 
17160f9d5027SAnirudh Venkataramanan /**
17170f9d5027SAnirudh Venkataramanan  * ice_free_vsi- free VSI context from hardware and VSI handle list
1718f9867df6SAnirudh Venkataramanan  * @hw: pointer to the HW struct
17190f9d5027SAnirudh Venkataramanan  * @vsi_handle: unique VSI handle
17203a858ba3SAnirudh Venkataramanan  * @vsi_ctx: pointer to a VSI context struct
17213a858ba3SAnirudh Venkataramanan  * @keep_vsi_alloc: keep VSI allocation as part of this PF's resources
17223a858ba3SAnirudh Venkataramanan  * @cd: pointer to command details structure or NULL
17233a858ba3SAnirudh Venkataramanan  *
17240f9d5027SAnirudh Venkataramanan  * Free VSI context info from hardware as well as from VSI handle list
17253a858ba3SAnirudh Venkataramanan  */
17265e24d598STony Nguyen int
17270f9d5027SAnirudh Venkataramanan ice_free_vsi(struct ice_hw *hw, u16 vsi_handle, struct ice_vsi_ctx *vsi_ctx,
17283a858ba3SAnirudh Venkataramanan 	     bool keep_vsi_alloc, struct ice_sq_cd *cd)
17293a858ba3SAnirudh Venkataramanan {
17305e24d598STony Nguyen 	int status;
17313a858ba3SAnirudh Venkataramanan 
17320f9d5027SAnirudh Venkataramanan 	if (!ice_is_vsi_valid(hw, vsi_handle))
1733d54699e2STony Nguyen 		return -EINVAL;
17340f9d5027SAnirudh Venkataramanan 	vsi_ctx->vsi_num = ice_get_hw_vsi_num(hw, vsi_handle);
17350f9d5027SAnirudh Venkataramanan 	status = ice_aq_free_vsi(hw, vsi_ctx, keep_vsi_alloc, cd);
17360f9d5027SAnirudh Venkataramanan 	if (!status)
17370f9d5027SAnirudh Venkataramanan 		ice_clear_vsi_ctx(hw, vsi_handle);
17383a858ba3SAnirudh Venkataramanan 	return status;
17393a858ba3SAnirudh Venkataramanan }
17403a858ba3SAnirudh Venkataramanan 
17419daf8208SAnirudh Venkataramanan /**
17425726ca0eSAnirudh Venkataramanan  * ice_update_vsi
1743f9867df6SAnirudh Venkataramanan  * @hw: pointer to the HW struct
17445726ca0eSAnirudh Venkataramanan  * @vsi_handle: unique VSI handle
17455726ca0eSAnirudh Venkataramanan  * @vsi_ctx: pointer to a VSI context struct
17465726ca0eSAnirudh Venkataramanan  * @cd: pointer to command details structure or NULL
17475726ca0eSAnirudh Venkataramanan  *
17485726ca0eSAnirudh Venkataramanan  * Update VSI context in the hardware
17495726ca0eSAnirudh Venkataramanan  */
17505e24d598STony Nguyen int
17515726ca0eSAnirudh Venkataramanan ice_update_vsi(struct ice_hw *hw, u16 vsi_handle, struct ice_vsi_ctx *vsi_ctx,
17525726ca0eSAnirudh Venkataramanan 	       struct ice_sq_cd *cd)
17535726ca0eSAnirudh Venkataramanan {
17545726ca0eSAnirudh Venkataramanan 	if (!ice_is_vsi_valid(hw, vsi_handle))
1755d54699e2STony Nguyen 		return -EINVAL;
17565726ca0eSAnirudh Venkataramanan 	vsi_ctx->vsi_num = ice_get_hw_vsi_num(hw, vsi_handle);
17575726ca0eSAnirudh Venkataramanan 	return ice_aq_update_vsi(hw, vsi_ctx, cd);
17585726ca0eSAnirudh Venkataramanan }
17595726ca0eSAnirudh Venkataramanan 
17605726ca0eSAnirudh Venkataramanan /**
1761348048e7SDave Ertman  * ice_cfg_rdma_fltr - enable/disable RDMA filtering on VSI
1762348048e7SDave Ertman  * @hw: pointer to HW struct
1763348048e7SDave Ertman  * @vsi_handle: VSI SW index
1764348048e7SDave Ertman  * @enable: boolean for enable/disable
1765348048e7SDave Ertman  */
1766348048e7SDave Ertman int
1767348048e7SDave Ertman ice_cfg_rdma_fltr(struct ice_hw *hw, u16 vsi_handle, bool enable)
1768348048e7SDave Ertman {
1769d94dbdc4SBrett Creeley 	struct ice_vsi_ctx *ctx, *cached_ctx;
1770d94dbdc4SBrett Creeley 	int status;
1771348048e7SDave Ertman 
1772d94dbdc4SBrett Creeley 	cached_ctx = ice_get_vsi_ctx(hw, vsi_handle);
1773d94dbdc4SBrett Creeley 	if (!cached_ctx)
1774d94dbdc4SBrett Creeley 		return -ENOENT;
1775d94dbdc4SBrett Creeley 
1776d94dbdc4SBrett Creeley 	ctx = kzalloc(sizeof(*ctx), GFP_KERNEL);
1777348048e7SDave Ertman 	if (!ctx)
1778d94dbdc4SBrett Creeley 		return -ENOMEM;
1779d94dbdc4SBrett Creeley 
1780d94dbdc4SBrett Creeley 	ctx->info.q_opt_rss = cached_ctx->info.q_opt_rss;
1781d94dbdc4SBrett Creeley 	ctx->info.q_opt_tc = cached_ctx->info.q_opt_tc;
1782d94dbdc4SBrett Creeley 	ctx->info.q_opt_flags = cached_ctx->info.q_opt_flags;
1783d94dbdc4SBrett Creeley 
1784d94dbdc4SBrett Creeley 	ctx->info.valid_sections = cpu_to_le16(ICE_AQ_VSI_PROP_Q_OPT_VALID);
1785348048e7SDave Ertman 
1786348048e7SDave Ertman 	if (enable)
1787348048e7SDave Ertman 		ctx->info.q_opt_flags |= ICE_AQ_VSI_Q_OPT_PE_FLTR_EN;
1788348048e7SDave Ertman 	else
1789348048e7SDave Ertman 		ctx->info.q_opt_flags &= ~ICE_AQ_VSI_Q_OPT_PE_FLTR_EN;
1790348048e7SDave Ertman 
1791d94dbdc4SBrett Creeley 	status = ice_update_vsi(hw, vsi_handle, ctx, NULL);
1792d94dbdc4SBrett Creeley 	if (!status) {
1793d94dbdc4SBrett Creeley 		cached_ctx->info.q_opt_flags = ctx->info.q_opt_flags;
1794d94dbdc4SBrett Creeley 		cached_ctx->info.valid_sections |= ctx->info.valid_sections;
1795d94dbdc4SBrett Creeley 	}
1796d94dbdc4SBrett Creeley 
1797d94dbdc4SBrett Creeley 	kfree(ctx);
1798d94dbdc4SBrett Creeley 	return status;
1799348048e7SDave Ertman }
1800348048e7SDave Ertman 
1801348048e7SDave Ertman /**
18029daf8208SAnirudh Venkataramanan  * ice_aq_alloc_free_vsi_list
1803f9867df6SAnirudh Venkataramanan  * @hw: pointer to the HW struct
1804f9867df6SAnirudh Venkataramanan  * @vsi_list_id: VSI list ID returned or used for lookup
18059daf8208SAnirudh Venkataramanan  * @lkup_type: switch rule filter lookup type
18069daf8208SAnirudh Venkataramanan  * @opc: switch rules population command type - pass in the command opcode
18079daf8208SAnirudh Venkataramanan  *
18089daf8208SAnirudh Venkataramanan  * allocates or free a VSI list resource
18099daf8208SAnirudh Venkataramanan  */
18105e24d598STony Nguyen static int
18119daf8208SAnirudh Venkataramanan ice_aq_alloc_free_vsi_list(struct ice_hw *hw, u16 *vsi_list_id,
18129daf8208SAnirudh Venkataramanan 			   enum ice_sw_lkup_type lkup_type,
18139daf8208SAnirudh Venkataramanan 			   enum ice_adminq_opc opc)
18149daf8208SAnirudh Venkataramanan {
18159daf8208SAnirudh Venkataramanan 	struct ice_aqc_alloc_free_res_elem *sw_buf;
18169daf8208SAnirudh Venkataramanan 	struct ice_aqc_res_elem *vsi_ele;
18179daf8208SAnirudh Venkataramanan 	u16 buf_len;
18185518ac2aSTony Nguyen 	int status;
18199daf8208SAnirudh Venkataramanan 
182066486d89SBruce Allan 	buf_len = struct_size(sw_buf, elem, 1);
18219daf8208SAnirudh Venkataramanan 	sw_buf = devm_kzalloc(ice_hw_to_dev(hw), buf_len, GFP_KERNEL);
18229daf8208SAnirudh Venkataramanan 	if (!sw_buf)
1823d54699e2STony Nguyen 		return -ENOMEM;
18249daf8208SAnirudh Venkataramanan 	sw_buf->num_elems = cpu_to_le16(1);
18259daf8208SAnirudh Venkataramanan 
18269daf8208SAnirudh Venkataramanan 	if (lkup_type == ICE_SW_LKUP_MAC ||
18279daf8208SAnirudh Venkataramanan 	    lkup_type == ICE_SW_LKUP_MAC_VLAN ||
18289daf8208SAnirudh Venkataramanan 	    lkup_type == ICE_SW_LKUP_ETHERTYPE ||
18299daf8208SAnirudh Venkataramanan 	    lkup_type == ICE_SW_LKUP_ETHERTYPE_MAC ||
18309daf8208SAnirudh Venkataramanan 	    lkup_type == ICE_SW_LKUP_PROMISC ||
1831d7393425SMichal Wilczynski 	    lkup_type == ICE_SW_LKUP_PROMISC_VLAN ||
1832d7393425SMichal Wilczynski 	    lkup_type == ICE_SW_LKUP_DFLT) {
18339daf8208SAnirudh Venkataramanan 		sw_buf->res_type = cpu_to_le16(ICE_AQC_RES_TYPE_VSI_LIST_REP);
18349daf8208SAnirudh Venkataramanan 	} else if (lkup_type == ICE_SW_LKUP_VLAN) {
183523ccae5cSDave Ertman 		if (opc == ice_aqc_opc_alloc_res)
183623ccae5cSDave Ertman 			sw_buf->res_type =
183723ccae5cSDave Ertman 				cpu_to_le16(ICE_AQC_RES_TYPE_VSI_LIST_PRUNE |
183823ccae5cSDave Ertman 					    ICE_AQC_RES_TYPE_FLAG_SHARED);
183923ccae5cSDave Ertman 		else
18409daf8208SAnirudh Venkataramanan 			sw_buf->res_type =
18419daf8208SAnirudh Venkataramanan 				cpu_to_le16(ICE_AQC_RES_TYPE_VSI_LIST_PRUNE);
18429daf8208SAnirudh Venkataramanan 	} else {
1843d54699e2STony Nguyen 		status = -EINVAL;
18449daf8208SAnirudh Venkataramanan 		goto ice_aq_alloc_free_vsi_list_exit;
18459daf8208SAnirudh Venkataramanan 	}
18469daf8208SAnirudh Venkataramanan 
18479daf8208SAnirudh Venkataramanan 	if (opc == ice_aqc_opc_free_res)
18489daf8208SAnirudh Venkataramanan 		sw_buf->elem[0].e.sw_resp = cpu_to_le16(*vsi_list_id);
18499daf8208SAnirudh Venkataramanan 
18509daf8208SAnirudh Venkataramanan 	status = ice_aq_alloc_free_res(hw, 1, sw_buf, buf_len, opc, NULL);
18519daf8208SAnirudh Venkataramanan 	if (status)
18529daf8208SAnirudh Venkataramanan 		goto ice_aq_alloc_free_vsi_list_exit;
18539daf8208SAnirudh Venkataramanan 
18549daf8208SAnirudh Venkataramanan 	if (opc == ice_aqc_opc_alloc_res) {
18559daf8208SAnirudh Venkataramanan 		vsi_ele = &sw_buf->elem[0];
18569daf8208SAnirudh Venkataramanan 		*vsi_list_id = le16_to_cpu(vsi_ele->e.sw_resp);
18579daf8208SAnirudh Venkataramanan 	}
18589daf8208SAnirudh Venkataramanan 
18599daf8208SAnirudh Venkataramanan ice_aq_alloc_free_vsi_list_exit:
18609daf8208SAnirudh Venkataramanan 	devm_kfree(ice_hw_to_dev(hw), sw_buf);
18619daf8208SAnirudh Venkataramanan 	return status;
18629daf8208SAnirudh Venkataramanan }
18639daf8208SAnirudh Venkataramanan 
18649daf8208SAnirudh Venkataramanan /**
18659daf8208SAnirudh Venkataramanan  * ice_aq_sw_rules - add/update/remove switch rules
1866f9867df6SAnirudh Venkataramanan  * @hw: pointer to the HW struct
18679daf8208SAnirudh Venkataramanan  * @rule_list: pointer to switch rule population list
18689daf8208SAnirudh Venkataramanan  * @rule_list_sz: total size of the rule list in bytes
18699daf8208SAnirudh Venkataramanan  * @num_rules: number of switch rules in the rule_list
18709daf8208SAnirudh Venkataramanan  * @opc: switch rules population command type - pass in the command opcode
18719daf8208SAnirudh Venkataramanan  * @cd: pointer to command details structure or NULL
18729daf8208SAnirudh Venkataramanan  *
18739daf8208SAnirudh Venkataramanan  * Add(0x02a0)/Update(0x02a1)/Remove(0x02a2) switch rules commands to firmware
18749daf8208SAnirudh Venkataramanan  */
18755e24d598STony Nguyen int
18769daf8208SAnirudh Venkataramanan ice_aq_sw_rules(struct ice_hw *hw, void *rule_list, u16 rule_list_sz,
18779daf8208SAnirudh Venkataramanan 		u8 num_rules, enum ice_adminq_opc opc, struct ice_sq_cd *cd)
18789daf8208SAnirudh Venkataramanan {
18799daf8208SAnirudh Venkataramanan 	struct ice_aq_desc desc;
18805e24d598STony Nguyen 	int status;
18819daf8208SAnirudh Venkataramanan 
18829daf8208SAnirudh Venkataramanan 	if (opc != ice_aqc_opc_add_sw_rules &&
18839daf8208SAnirudh Venkataramanan 	    opc != ice_aqc_opc_update_sw_rules &&
18849daf8208SAnirudh Venkataramanan 	    opc != ice_aqc_opc_remove_sw_rules)
1885d54699e2STony Nguyen 		return -EINVAL;
18869daf8208SAnirudh Venkataramanan 
18879daf8208SAnirudh Venkataramanan 	ice_fill_dflt_direct_cmd_desc(&desc, opc);
18889daf8208SAnirudh Venkataramanan 
18899daf8208SAnirudh Venkataramanan 	desc.flags |= cpu_to_le16(ICE_AQ_FLAG_RD);
18909daf8208SAnirudh Venkataramanan 	desc.params.sw_rules.num_rules_fltr_entry_index =
18919daf8208SAnirudh Venkataramanan 		cpu_to_le16(num_rules);
1892ca1fdb88SKiran Patil 	status = ice_aq_send_cmd(hw, &desc, rule_list, rule_list_sz, cd);
1893ca1fdb88SKiran Patil 	if (opc != ice_aqc_opc_add_sw_rules &&
1894ca1fdb88SKiran Patil 	    hw->adminq.sq_last_status == ICE_AQ_RC_ENOENT)
1895d54699e2STony Nguyen 		status = -ENOENT;
1896ca1fdb88SKiran Patil 
1897ca1fdb88SKiran Patil 	return status;
18989daf8208SAnirudh Venkataramanan }
18999daf8208SAnirudh Venkataramanan 
19007715ec32SGrishma Kotecha /**
19017715ec32SGrishma Kotecha  * ice_aq_add_recipe - add switch recipe
19027715ec32SGrishma Kotecha  * @hw: pointer to the HW struct
19037715ec32SGrishma Kotecha  * @s_recipe_list: pointer to switch rule population list
19047715ec32SGrishma Kotecha  * @num_recipes: number of switch recipes in the list
19057715ec32SGrishma Kotecha  * @cd: pointer to command details structure or NULL
19067715ec32SGrishma Kotecha  *
19077715ec32SGrishma Kotecha  * Add(0x0290)
19087715ec32SGrishma Kotecha  */
190923ccae5cSDave Ertman int
19107715ec32SGrishma Kotecha ice_aq_add_recipe(struct ice_hw *hw,
19117715ec32SGrishma Kotecha 		  struct ice_aqc_recipe_data_elem *s_recipe_list,
19127715ec32SGrishma Kotecha 		  u16 num_recipes, struct ice_sq_cd *cd)
19137715ec32SGrishma Kotecha {
19147715ec32SGrishma Kotecha 	struct ice_aqc_add_get_recipe *cmd;
19157715ec32SGrishma Kotecha 	struct ice_aq_desc desc;
19167715ec32SGrishma Kotecha 	u16 buf_size;
19177715ec32SGrishma Kotecha 
19187715ec32SGrishma Kotecha 	cmd = &desc.params.add_get_recipe;
19197715ec32SGrishma Kotecha 	ice_fill_dflt_direct_cmd_desc(&desc, ice_aqc_opc_add_recipe);
19207715ec32SGrishma Kotecha 
19217715ec32SGrishma Kotecha 	cmd->num_sub_recipes = cpu_to_le16(num_recipes);
19227715ec32SGrishma Kotecha 	desc.flags |= cpu_to_le16(ICE_AQ_FLAG_RD);
19237715ec32SGrishma Kotecha 
19247715ec32SGrishma Kotecha 	buf_size = num_recipes * sizeof(*s_recipe_list);
19257715ec32SGrishma Kotecha 
19267715ec32SGrishma Kotecha 	return ice_aq_send_cmd(hw, &desc, s_recipe_list, buf_size, cd);
19277715ec32SGrishma Kotecha }
19287715ec32SGrishma Kotecha 
19297715ec32SGrishma Kotecha /**
19307715ec32SGrishma Kotecha  * ice_aq_get_recipe - get switch recipe
19317715ec32SGrishma Kotecha  * @hw: pointer to the HW struct
19327715ec32SGrishma Kotecha  * @s_recipe_list: pointer to switch rule population list
19337715ec32SGrishma Kotecha  * @num_recipes: pointer to the number of recipes (input and output)
19347715ec32SGrishma Kotecha  * @recipe_root: root recipe number of recipe(s) to retrieve
19357715ec32SGrishma Kotecha  * @cd: pointer to command details structure or NULL
19367715ec32SGrishma Kotecha  *
19377715ec32SGrishma Kotecha  * Get(0x0292)
19387715ec32SGrishma Kotecha  *
19397715ec32SGrishma Kotecha  * On input, *num_recipes should equal the number of entries in s_recipe_list.
19407715ec32SGrishma Kotecha  * On output, *num_recipes will equal the number of entries returned in
19417715ec32SGrishma Kotecha  * s_recipe_list.
19427715ec32SGrishma Kotecha  *
19437715ec32SGrishma Kotecha  * The caller must supply enough space in s_recipe_list to hold all possible
19447715ec32SGrishma Kotecha  * recipes and *num_recipes must equal ICE_MAX_NUM_RECIPES.
19457715ec32SGrishma Kotecha  */
194623ccae5cSDave Ertman int
19477715ec32SGrishma Kotecha ice_aq_get_recipe(struct ice_hw *hw,
19487715ec32SGrishma Kotecha 		  struct ice_aqc_recipe_data_elem *s_recipe_list,
19497715ec32SGrishma Kotecha 		  u16 *num_recipes, u16 recipe_root, struct ice_sq_cd *cd)
19507715ec32SGrishma Kotecha {
19517715ec32SGrishma Kotecha 	struct ice_aqc_add_get_recipe *cmd;
19527715ec32SGrishma Kotecha 	struct ice_aq_desc desc;
19537715ec32SGrishma Kotecha 	u16 buf_size;
19545518ac2aSTony Nguyen 	int status;
19557715ec32SGrishma Kotecha 
19567715ec32SGrishma Kotecha 	if (*num_recipes != ICE_MAX_NUM_RECIPES)
1957d54699e2STony Nguyen 		return -EINVAL;
19587715ec32SGrishma Kotecha 
19597715ec32SGrishma Kotecha 	cmd = &desc.params.add_get_recipe;
19607715ec32SGrishma Kotecha 	ice_fill_dflt_direct_cmd_desc(&desc, ice_aqc_opc_get_recipe);
19617715ec32SGrishma Kotecha 
19627715ec32SGrishma Kotecha 	cmd->return_index = cpu_to_le16(recipe_root);
19637715ec32SGrishma Kotecha 	cmd->num_sub_recipes = 0;
19647715ec32SGrishma Kotecha 
19657715ec32SGrishma Kotecha 	buf_size = *num_recipes * sizeof(*s_recipe_list);
19667715ec32SGrishma Kotecha 
19677715ec32SGrishma Kotecha 	status = ice_aq_send_cmd(hw, &desc, s_recipe_list, buf_size, cd);
19687715ec32SGrishma Kotecha 	*num_recipes = le16_to_cpu(cmd->num_sub_recipes);
19697715ec32SGrishma Kotecha 
19707715ec32SGrishma Kotecha 	return status;
19717715ec32SGrishma Kotecha }
19727715ec32SGrishma Kotecha 
19737715ec32SGrishma Kotecha /**
1974a1ffafb0SBrett Creeley  * ice_update_recipe_lkup_idx - update a default recipe based on the lkup_idx
1975a1ffafb0SBrett Creeley  * @hw: pointer to the HW struct
1976a1ffafb0SBrett Creeley  * @params: parameters used to update the default recipe
1977a1ffafb0SBrett Creeley  *
1978a1ffafb0SBrett Creeley  * This function only supports updating default recipes and it only supports
1979a1ffafb0SBrett Creeley  * updating a single recipe based on the lkup_idx at a time.
1980a1ffafb0SBrett Creeley  *
1981a1ffafb0SBrett Creeley  * This is done as a read-modify-write operation. First, get the current recipe
1982a1ffafb0SBrett Creeley  * contents based on the recipe's ID. Then modify the field vector index and
1983a1ffafb0SBrett Creeley  * mask if it's valid at the lkup_idx. Finally, use the add recipe AQ to update
1984a1ffafb0SBrett Creeley  * the pre-existing recipe with the modifications.
1985a1ffafb0SBrett Creeley  */
1986a1ffafb0SBrett Creeley int
1987a1ffafb0SBrett Creeley ice_update_recipe_lkup_idx(struct ice_hw *hw,
1988a1ffafb0SBrett Creeley 			   struct ice_update_recipe_lkup_idx_params *params)
1989a1ffafb0SBrett Creeley {
1990a1ffafb0SBrett Creeley 	struct ice_aqc_recipe_data_elem *rcp_list;
1991a1ffafb0SBrett Creeley 	u16 num_recps = ICE_MAX_NUM_RECIPES;
1992a1ffafb0SBrett Creeley 	int status;
1993a1ffafb0SBrett Creeley 
1994a1ffafb0SBrett Creeley 	rcp_list = kcalloc(num_recps, sizeof(*rcp_list), GFP_KERNEL);
1995a1ffafb0SBrett Creeley 	if (!rcp_list)
1996a1ffafb0SBrett Creeley 		return -ENOMEM;
1997a1ffafb0SBrett Creeley 
1998a1ffafb0SBrett Creeley 	/* read current recipe list from firmware */
1999a1ffafb0SBrett Creeley 	rcp_list->recipe_indx = params->rid;
2000a1ffafb0SBrett Creeley 	status = ice_aq_get_recipe(hw, rcp_list, &num_recps, params->rid, NULL);
2001a1ffafb0SBrett Creeley 	if (status) {
2002a1ffafb0SBrett Creeley 		ice_debug(hw, ICE_DBG_SW, "Failed to get recipe %d, status %d\n",
2003a1ffafb0SBrett Creeley 			  params->rid, status);
2004a1ffafb0SBrett Creeley 		goto error_out;
2005a1ffafb0SBrett Creeley 	}
2006a1ffafb0SBrett Creeley 
2007a1ffafb0SBrett Creeley 	/* only modify existing recipe's lkup_idx and mask if valid, while
2008a1ffafb0SBrett Creeley 	 * leaving all other fields the same, then update the recipe firmware
2009a1ffafb0SBrett Creeley 	 */
2010a1ffafb0SBrett Creeley 	rcp_list->content.lkup_indx[params->lkup_idx] = params->fv_idx;
2011a1ffafb0SBrett Creeley 	if (params->mask_valid)
2012a1ffafb0SBrett Creeley 		rcp_list->content.mask[params->lkup_idx] =
2013a1ffafb0SBrett Creeley 			cpu_to_le16(params->mask);
2014a1ffafb0SBrett Creeley 
2015a1ffafb0SBrett Creeley 	if (params->ignore_valid)
2016a1ffafb0SBrett Creeley 		rcp_list->content.lkup_indx[params->lkup_idx] |=
2017a1ffafb0SBrett Creeley 			ICE_AQ_RECIPE_LKUP_IGNORE;
2018a1ffafb0SBrett Creeley 
2019a1ffafb0SBrett Creeley 	status = ice_aq_add_recipe(hw, &rcp_list[0], 1, NULL);
2020a1ffafb0SBrett Creeley 	if (status)
2021a1ffafb0SBrett 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",
2022a1ffafb0SBrett Creeley 			  params->rid, params->lkup_idx, params->fv_idx,
2023a1ffafb0SBrett Creeley 			  params->mask, params->mask_valid ? "true" : "false",
2024a1ffafb0SBrett Creeley 			  status);
2025a1ffafb0SBrett Creeley 
2026a1ffafb0SBrett Creeley error_out:
2027a1ffafb0SBrett Creeley 	kfree(rcp_list);
2028a1ffafb0SBrett Creeley 	return status;
2029a1ffafb0SBrett Creeley }
2030a1ffafb0SBrett Creeley 
2031a1ffafb0SBrett Creeley /**
20327715ec32SGrishma Kotecha  * ice_aq_map_recipe_to_profile - Map recipe to packet profile
20337715ec32SGrishma Kotecha  * @hw: pointer to the HW struct
20347715ec32SGrishma Kotecha  * @profile_id: package profile ID to associate the recipe with
20357715ec32SGrishma Kotecha  * @r_bitmap: Recipe bitmap filled in and need to be returned as response
20367715ec32SGrishma Kotecha  * @cd: pointer to command details structure or NULL
20377715ec32SGrishma Kotecha  * Recipe to profile association (0x0291)
20387715ec32SGrishma Kotecha  */
203923ccae5cSDave Ertman int
20407715ec32SGrishma Kotecha ice_aq_map_recipe_to_profile(struct ice_hw *hw, u32 profile_id, u8 *r_bitmap,
20417715ec32SGrishma Kotecha 			     struct ice_sq_cd *cd)
20427715ec32SGrishma Kotecha {
20437715ec32SGrishma Kotecha 	struct ice_aqc_recipe_to_profile *cmd;
20447715ec32SGrishma Kotecha 	struct ice_aq_desc desc;
20457715ec32SGrishma Kotecha 
20467715ec32SGrishma Kotecha 	cmd = &desc.params.recipe_to_profile;
20477715ec32SGrishma Kotecha 	ice_fill_dflt_direct_cmd_desc(&desc, ice_aqc_opc_recipe_to_profile);
20487715ec32SGrishma Kotecha 	cmd->profile_id = cpu_to_le16(profile_id);
20497715ec32SGrishma Kotecha 	/* Set the recipe ID bit in the bitmask to let the device know which
20507715ec32SGrishma Kotecha 	 * profile we are associating the recipe to
20517715ec32SGrishma Kotecha 	 */
20527715ec32SGrishma Kotecha 	memcpy(cmd->recipe_assoc, r_bitmap, sizeof(cmd->recipe_assoc));
20537715ec32SGrishma Kotecha 
20547715ec32SGrishma Kotecha 	return ice_aq_send_cmd(hw, &desc, NULL, 0, cd);
20557715ec32SGrishma Kotecha }
20567715ec32SGrishma Kotecha 
20577715ec32SGrishma Kotecha /**
20587715ec32SGrishma Kotecha  * ice_aq_get_recipe_to_profile - Map recipe to packet profile
20597715ec32SGrishma Kotecha  * @hw: pointer to the HW struct
20607715ec32SGrishma Kotecha  * @profile_id: package profile ID to associate the recipe with
20617715ec32SGrishma Kotecha  * @r_bitmap: Recipe bitmap filled in and need to be returned as response
20627715ec32SGrishma Kotecha  * @cd: pointer to command details structure or NULL
20637715ec32SGrishma Kotecha  * Associate profile ID with given recipe (0x0293)
20647715ec32SGrishma Kotecha  */
206523ccae5cSDave Ertman int
20667715ec32SGrishma Kotecha ice_aq_get_recipe_to_profile(struct ice_hw *hw, u32 profile_id, u8 *r_bitmap,
20677715ec32SGrishma Kotecha 			     struct ice_sq_cd *cd)
20687715ec32SGrishma Kotecha {
20697715ec32SGrishma Kotecha 	struct ice_aqc_recipe_to_profile *cmd;
20707715ec32SGrishma Kotecha 	struct ice_aq_desc desc;
20715e24d598STony Nguyen 	int status;
20727715ec32SGrishma Kotecha 
20737715ec32SGrishma Kotecha 	cmd = &desc.params.recipe_to_profile;
20747715ec32SGrishma Kotecha 	ice_fill_dflt_direct_cmd_desc(&desc, ice_aqc_opc_get_recipe_to_profile);
20757715ec32SGrishma Kotecha 	cmd->profile_id = cpu_to_le16(profile_id);
20767715ec32SGrishma Kotecha 
20777715ec32SGrishma Kotecha 	status = ice_aq_send_cmd(hw, &desc, NULL, 0, cd);
20787715ec32SGrishma Kotecha 	if (!status)
20797715ec32SGrishma Kotecha 		memcpy(r_bitmap, cmd->recipe_assoc, sizeof(cmd->recipe_assoc));
20807715ec32SGrishma Kotecha 
20817715ec32SGrishma Kotecha 	return status;
20827715ec32SGrishma Kotecha }
20837715ec32SGrishma Kotecha 
20847715ec32SGrishma Kotecha /**
20857715ec32SGrishma Kotecha  * ice_alloc_recipe - add recipe resource
20867715ec32SGrishma Kotecha  * @hw: pointer to the hardware structure
20877715ec32SGrishma Kotecha  * @rid: recipe ID returned as response to AQ call
20887715ec32SGrishma Kotecha  */
208923ccae5cSDave Ertman int ice_alloc_recipe(struct ice_hw *hw, u16 *rid)
20907715ec32SGrishma Kotecha {
20917715ec32SGrishma Kotecha 	struct ice_aqc_alloc_free_res_elem *sw_buf;
20927715ec32SGrishma Kotecha 	u16 buf_len;
20935518ac2aSTony Nguyen 	int status;
20947715ec32SGrishma Kotecha 
20957715ec32SGrishma Kotecha 	buf_len = struct_size(sw_buf, elem, 1);
20967715ec32SGrishma Kotecha 	sw_buf = kzalloc(buf_len, GFP_KERNEL);
20977715ec32SGrishma Kotecha 	if (!sw_buf)
2098d54699e2STony Nguyen 		return -ENOMEM;
20997715ec32SGrishma Kotecha 
21007715ec32SGrishma Kotecha 	sw_buf->num_elems = cpu_to_le16(1);
21017715ec32SGrishma Kotecha 	sw_buf->res_type = cpu_to_le16((ICE_AQC_RES_TYPE_RECIPE <<
21027715ec32SGrishma Kotecha 					ICE_AQC_RES_TYPE_S) |
21037715ec32SGrishma Kotecha 					ICE_AQC_RES_TYPE_FLAG_SHARED);
21047715ec32SGrishma Kotecha 	status = ice_aq_alloc_free_res(hw, 1, sw_buf, buf_len,
21057715ec32SGrishma Kotecha 				       ice_aqc_opc_alloc_res, NULL);
21067715ec32SGrishma Kotecha 	if (!status)
21077715ec32SGrishma Kotecha 		*rid = le16_to_cpu(sw_buf->elem[0].e.sw_resp);
21087715ec32SGrishma Kotecha 	kfree(sw_buf);
21097715ec32SGrishma Kotecha 
21107715ec32SGrishma Kotecha 	return status;
21117715ec32SGrishma Kotecha }
21127715ec32SGrishma Kotecha 
2113fd2a6b71SDan Nowlin /**
2114fd2a6b71SDan Nowlin  * ice_get_recp_to_prof_map - updates recipe to profile mapping
2115fd2a6b71SDan Nowlin  * @hw: pointer to hardware structure
2116fd2a6b71SDan Nowlin  *
2117fd2a6b71SDan Nowlin  * This function is used to populate recipe_to_profile matrix where index to
2118fd2a6b71SDan Nowlin  * this array is the recipe ID and the element is the mapping of which profiles
2119fd2a6b71SDan Nowlin  * is this recipe mapped to.
2120fd2a6b71SDan Nowlin  */
2121fd2a6b71SDan Nowlin static void ice_get_recp_to_prof_map(struct ice_hw *hw)
2122fd2a6b71SDan Nowlin {
2123fd2a6b71SDan Nowlin 	DECLARE_BITMAP(r_bitmap, ICE_MAX_NUM_RECIPES);
2124fd2a6b71SDan Nowlin 	u16 i;
2125fd2a6b71SDan Nowlin 
2126fd2a6b71SDan Nowlin 	for (i = 0; i < hw->switch_info->max_used_prof_index + 1; i++) {
2127fd2a6b71SDan Nowlin 		u16 j;
2128fd2a6b71SDan Nowlin 
2129fd2a6b71SDan Nowlin 		bitmap_zero(profile_to_recipe[i], ICE_MAX_NUM_RECIPES);
2130fd2a6b71SDan Nowlin 		bitmap_zero(r_bitmap, ICE_MAX_NUM_RECIPES);
2131fd2a6b71SDan Nowlin 		if (ice_aq_get_recipe_to_profile(hw, i, (u8 *)r_bitmap, NULL))
2132fd2a6b71SDan Nowlin 			continue;
2133fd2a6b71SDan Nowlin 		bitmap_copy(profile_to_recipe[i], r_bitmap,
2134fd2a6b71SDan Nowlin 			    ICE_MAX_NUM_RECIPES);
2135fd2a6b71SDan Nowlin 		for_each_set_bit(j, r_bitmap, ICE_MAX_NUM_RECIPES)
2136fd2a6b71SDan Nowlin 			set_bit(i, recipe_to_profile[j]);
2137fd2a6b71SDan Nowlin 	}
2138fd2a6b71SDan Nowlin }
2139fd2a6b71SDan Nowlin 
2140fd2a6b71SDan Nowlin /**
2141fd2a6b71SDan Nowlin  * ice_collect_result_idx - copy result index values
2142fd2a6b71SDan Nowlin  * @buf: buffer that contains the result index
2143fd2a6b71SDan Nowlin  * @recp: the recipe struct to copy data into
2144fd2a6b71SDan Nowlin  */
2145fd2a6b71SDan Nowlin static void
2146fd2a6b71SDan Nowlin ice_collect_result_idx(struct ice_aqc_recipe_data_elem *buf,
2147fd2a6b71SDan Nowlin 		       struct ice_sw_recipe *recp)
2148fd2a6b71SDan Nowlin {
2149fd2a6b71SDan Nowlin 	if (buf->content.result_indx & ICE_AQ_RECIPE_RESULT_EN)
2150fd2a6b71SDan Nowlin 		set_bit(buf->content.result_indx & ~ICE_AQ_RECIPE_RESULT_EN,
2151fd2a6b71SDan Nowlin 			recp->res_idxs);
2152fd2a6b71SDan Nowlin }
2153fd2a6b71SDan Nowlin 
2154fd2a6b71SDan Nowlin /**
2155fd2a6b71SDan Nowlin  * ice_get_recp_frm_fw - update SW bookkeeping from FW recipe entries
2156fd2a6b71SDan Nowlin  * @hw: pointer to hardware structure
2157fd2a6b71SDan Nowlin  * @recps: struct that we need to populate
2158fd2a6b71SDan Nowlin  * @rid: recipe ID that we are populating
2159fd2a6b71SDan Nowlin  * @refresh_required: true if we should get recipe to profile mapping from FW
2160fd2a6b71SDan Nowlin  *
2161fd2a6b71SDan Nowlin  * This function is used to populate all the necessary entries into our
2162fd2a6b71SDan Nowlin  * bookkeeping so that we have a current list of all the recipes that are
2163fd2a6b71SDan Nowlin  * programmed in the firmware.
2164fd2a6b71SDan Nowlin  */
21655e24d598STony Nguyen static int
2166fd2a6b71SDan Nowlin ice_get_recp_frm_fw(struct ice_hw *hw, struct ice_sw_recipe *recps, u8 rid,
2167fd2a6b71SDan Nowlin 		    bool *refresh_required)
2168fd2a6b71SDan Nowlin {
2169fd2a6b71SDan Nowlin 	DECLARE_BITMAP(result_bm, ICE_MAX_FV_WORDS);
2170fd2a6b71SDan Nowlin 	struct ice_aqc_recipe_data_elem *tmp;
2171fd2a6b71SDan Nowlin 	u16 num_recps = ICE_MAX_NUM_RECIPES;
2172fd2a6b71SDan Nowlin 	struct ice_prot_lkup_ext *lkup_exts;
2173fd2a6b71SDan Nowlin 	u8 fv_word_idx = 0;
2174fd2a6b71SDan Nowlin 	u16 sub_recps;
21755518ac2aSTony Nguyen 	int status;
2176fd2a6b71SDan Nowlin 
2177fd2a6b71SDan Nowlin 	bitmap_zero(result_bm, ICE_MAX_FV_WORDS);
2178fd2a6b71SDan Nowlin 
2179fd2a6b71SDan Nowlin 	/* we need a buffer big enough to accommodate all the recipes */
2180fd2a6b71SDan Nowlin 	tmp = kcalloc(ICE_MAX_NUM_RECIPES, sizeof(*tmp), GFP_KERNEL);
2181fd2a6b71SDan Nowlin 	if (!tmp)
2182d54699e2STony Nguyen 		return -ENOMEM;
2183fd2a6b71SDan Nowlin 
2184fd2a6b71SDan Nowlin 	tmp[0].recipe_indx = rid;
2185fd2a6b71SDan Nowlin 	status = ice_aq_get_recipe(hw, tmp, &num_recps, rid, NULL);
2186fd2a6b71SDan Nowlin 	/* non-zero status meaning recipe doesn't exist */
2187fd2a6b71SDan Nowlin 	if (status)
2188fd2a6b71SDan Nowlin 		goto err_unroll;
2189fd2a6b71SDan Nowlin 
2190fd2a6b71SDan Nowlin 	/* Get recipe to profile map so that we can get the fv from lkups that
2191fd2a6b71SDan Nowlin 	 * we read for a recipe from FW. Since we want to minimize the number of
2192fd2a6b71SDan Nowlin 	 * times we make this FW call, just make one call and cache the copy
2193fd2a6b71SDan Nowlin 	 * until a new recipe is added. This operation is only required the
2194fd2a6b71SDan Nowlin 	 * first time to get the changes from FW. Then to search existing
2195fd2a6b71SDan Nowlin 	 * entries we don't need to update the cache again until another recipe
2196fd2a6b71SDan Nowlin 	 * gets added.
2197fd2a6b71SDan Nowlin 	 */
2198fd2a6b71SDan Nowlin 	if (*refresh_required) {
2199fd2a6b71SDan Nowlin 		ice_get_recp_to_prof_map(hw);
2200fd2a6b71SDan Nowlin 		*refresh_required = false;
2201fd2a6b71SDan Nowlin 	}
2202fd2a6b71SDan Nowlin 
2203fd2a6b71SDan Nowlin 	/* Start populating all the entries for recps[rid] based on lkups from
2204fd2a6b71SDan Nowlin 	 * firmware. Note that we are only creating the root recipe in our
2205fd2a6b71SDan Nowlin 	 * database.
2206fd2a6b71SDan Nowlin 	 */
2207fd2a6b71SDan Nowlin 	lkup_exts = &recps[rid].lkup_exts;
2208fd2a6b71SDan Nowlin 
2209fd2a6b71SDan Nowlin 	for (sub_recps = 0; sub_recps < num_recps; sub_recps++) {
2210fd2a6b71SDan Nowlin 		struct ice_aqc_recipe_data_elem root_bufs = tmp[sub_recps];
2211fd2a6b71SDan Nowlin 		struct ice_recp_grp_entry *rg_entry;
2212fd2a6b71SDan Nowlin 		u8 i, prof, idx, prot = 0;
2213fd2a6b71SDan Nowlin 		bool is_root;
2214fd2a6b71SDan Nowlin 		u16 off = 0;
2215fd2a6b71SDan Nowlin 
2216fd2a6b71SDan Nowlin 		rg_entry = devm_kzalloc(ice_hw_to_dev(hw), sizeof(*rg_entry),
2217fd2a6b71SDan Nowlin 					GFP_KERNEL);
2218fd2a6b71SDan Nowlin 		if (!rg_entry) {
2219d54699e2STony Nguyen 			status = -ENOMEM;
2220fd2a6b71SDan Nowlin 			goto err_unroll;
2221fd2a6b71SDan Nowlin 		}
2222fd2a6b71SDan Nowlin 
2223fd2a6b71SDan Nowlin 		idx = root_bufs.recipe_indx;
2224fd2a6b71SDan Nowlin 		is_root = root_bufs.content.rid & ICE_AQ_RECIPE_ID_IS_ROOT;
2225fd2a6b71SDan Nowlin 
2226fd2a6b71SDan Nowlin 		/* Mark all result indices in this chain */
2227fd2a6b71SDan Nowlin 		if (root_bufs.content.result_indx & ICE_AQ_RECIPE_RESULT_EN)
2228fd2a6b71SDan Nowlin 			set_bit(root_bufs.content.result_indx & ~ICE_AQ_RECIPE_RESULT_EN,
2229fd2a6b71SDan Nowlin 				result_bm);
2230fd2a6b71SDan Nowlin 
2231fd2a6b71SDan Nowlin 		/* get the first profile that is associated with rid */
2232fd2a6b71SDan Nowlin 		prof = find_first_bit(recipe_to_profile[idx],
2233fd2a6b71SDan Nowlin 				      ICE_MAX_NUM_PROFILES);
2234fd2a6b71SDan Nowlin 		for (i = 0; i < ICE_NUM_WORDS_RECIPE; i++) {
2235fd2a6b71SDan Nowlin 			u8 lkup_indx = root_bufs.content.lkup_indx[i + 1];
2236fd2a6b71SDan Nowlin 
2237fd2a6b71SDan Nowlin 			rg_entry->fv_idx[i] = lkup_indx;
2238fd2a6b71SDan Nowlin 			rg_entry->fv_mask[i] =
2239fd2a6b71SDan Nowlin 				le16_to_cpu(root_bufs.content.mask[i + 1]);
2240fd2a6b71SDan Nowlin 
2241fd2a6b71SDan Nowlin 			/* If the recipe is a chained recipe then all its
2242fd2a6b71SDan Nowlin 			 * child recipe's result will have a result index.
2243fd2a6b71SDan Nowlin 			 * To fill fv_words we should not use those result
2244fd2a6b71SDan Nowlin 			 * index, we only need the protocol ids and offsets.
2245fd2a6b71SDan Nowlin 			 * We will skip all the fv_idx which stores result
2246fd2a6b71SDan Nowlin 			 * index in them. We also need to skip any fv_idx which
2247fd2a6b71SDan Nowlin 			 * has ICE_AQ_RECIPE_LKUP_IGNORE or 0 since it isn't a
2248fd2a6b71SDan Nowlin 			 * valid offset value.
2249fd2a6b71SDan Nowlin 			 */
2250fd2a6b71SDan Nowlin 			if (test_bit(rg_entry->fv_idx[i], hw->switch_info->prof_res_bm[prof]) ||
2251fd2a6b71SDan Nowlin 			    rg_entry->fv_idx[i] & ICE_AQ_RECIPE_LKUP_IGNORE ||
2252fd2a6b71SDan Nowlin 			    rg_entry->fv_idx[i] == 0)
2253fd2a6b71SDan Nowlin 				continue;
2254fd2a6b71SDan Nowlin 
2255fd2a6b71SDan Nowlin 			ice_find_prot_off(hw, ICE_BLK_SW, prof,
2256fd2a6b71SDan Nowlin 					  rg_entry->fv_idx[i], &prot, &off);
2257fd2a6b71SDan Nowlin 			lkup_exts->fv_words[fv_word_idx].prot_id = prot;
2258fd2a6b71SDan Nowlin 			lkup_exts->fv_words[fv_word_idx].off = off;
2259fd2a6b71SDan Nowlin 			lkup_exts->field_mask[fv_word_idx] =
2260fd2a6b71SDan Nowlin 				rg_entry->fv_mask[i];
2261fd2a6b71SDan Nowlin 			fv_word_idx++;
2262fd2a6b71SDan Nowlin 		}
2263fd2a6b71SDan Nowlin 		/* populate rg_list with the data from the child entry of this
2264fd2a6b71SDan Nowlin 		 * recipe
2265fd2a6b71SDan Nowlin 		 */
2266fd2a6b71SDan Nowlin 		list_add(&rg_entry->l_entry, &recps[rid].rg_list);
2267fd2a6b71SDan Nowlin 
2268fd2a6b71SDan Nowlin 		/* Propagate some data to the recipe database */
2269fd2a6b71SDan Nowlin 		recps[idx].is_root = !!is_root;
2270fd2a6b71SDan Nowlin 		recps[idx].priority = root_bufs.content.act_ctrl_fwd_priority;
2271bccd9bceSMarcin Szycik 		recps[idx].need_pass_l2 = root_bufs.content.act_ctrl &
2272bccd9bceSMarcin Szycik 					  ICE_AQ_RECIPE_ACT_NEED_PASS_L2;
2273bccd9bceSMarcin Szycik 		recps[idx].allow_pass_l2 = root_bufs.content.act_ctrl &
2274bccd9bceSMarcin Szycik 					   ICE_AQ_RECIPE_ACT_ALLOW_PASS_L2;
2275fd2a6b71SDan Nowlin 		bitmap_zero(recps[idx].res_idxs, ICE_MAX_FV_WORDS);
2276fd2a6b71SDan Nowlin 		if (root_bufs.content.result_indx & ICE_AQ_RECIPE_RESULT_EN) {
2277fd2a6b71SDan Nowlin 			recps[idx].chain_idx = root_bufs.content.result_indx &
2278fd2a6b71SDan Nowlin 				~ICE_AQ_RECIPE_RESULT_EN;
2279fd2a6b71SDan Nowlin 			set_bit(recps[idx].chain_idx, recps[idx].res_idxs);
2280fd2a6b71SDan Nowlin 		} else {
2281fd2a6b71SDan Nowlin 			recps[idx].chain_idx = ICE_INVAL_CHAIN_IND;
2282fd2a6b71SDan Nowlin 		}
2283fd2a6b71SDan Nowlin 
2284fd2a6b71SDan Nowlin 		if (!is_root)
2285fd2a6b71SDan Nowlin 			continue;
2286fd2a6b71SDan Nowlin 
2287fd2a6b71SDan Nowlin 		/* Only do the following for root recipes entries */
2288fd2a6b71SDan Nowlin 		memcpy(recps[idx].r_bitmap, root_bufs.recipe_bitmap,
2289fd2a6b71SDan Nowlin 		       sizeof(recps[idx].r_bitmap));
2290fd2a6b71SDan Nowlin 		recps[idx].root_rid = root_bufs.content.rid &
2291fd2a6b71SDan Nowlin 			~ICE_AQ_RECIPE_ID_IS_ROOT;
2292fd2a6b71SDan Nowlin 		recps[idx].priority = root_bufs.content.act_ctrl_fwd_priority;
2293fd2a6b71SDan Nowlin 	}
2294fd2a6b71SDan Nowlin 
2295fd2a6b71SDan Nowlin 	/* Complete initialization of the root recipe entry */
2296fd2a6b71SDan Nowlin 	lkup_exts->n_val_words = fv_word_idx;
2297fd2a6b71SDan Nowlin 	recps[rid].big_recp = (num_recps > 1);
2298fd2a6b71SDan Nowlin 	recps[rid].n_grp_count = (u8)num_recps;
2299fd2a6b71SDan Nowlin 	recps[rid].root_buf = devm_kmemdup(ice_hw_to_dev(hw), tmp,
2300fd2a6b71SDan Nowlin 					   recps[rid].n_grp_count * sizeof(*recps[rid].root_buf),
2301fd2a6b71SDan Nowlin 					   GFP_KERNEL);
2302c8e51a01SWang Hai 	if (!recps[rid].root_buf) {
2303d54699e2STony Nguyen 		status = -ENOMEM;
2304fd2a6b71SDan Nowlin 		goto err_unroll;
2305c8e51a01SWang Hai 	}
2306fd2a6b71SDan Nowlin 
2307fd2a6b71SDan Nowlin 	/* Copy result indexes */
2308fd2a6b71SDan Nowlin 	bitmap_copy(recps[rid].res_idxs, result_bm, ICE_MAX_FV_WORDS);
2309fd2a6b71SDan Nowlin 	recps[rid].recp_created = true;
2310fd2a6b71SDan Nowlin 
2311fd2a6b71SDan Nowlin err_unroll:
2312fd2a6b71SDan Nowlin 	kfree(tmp);
2313fd2a6b71SDan Nowlin 	return status;
2314fd2a6b71SDan Nowlin }
2315fd2a6b71SDan Nowlin 
23169c20346bSAnirudh Venkataramanan /* ice_init_port_info - Initialize port_info with switch configuration data
23179c20346bSAnirudh Venkataramanan  * @pi: pointer to port_info
23189c20346bSAnirudh Venkataramanan  * @vsi_port_num: VSI number or port number
23199c20346bSAnirudh Venkataramanan  * @type: Type of switch element (port or VSI)
23209c20346bSAnirudh Venkataramanan  * @swid: switch ID of the switch the element is attached to
23219c20346bSAnirudh Venkataramanan  * @pf_vf_num: PF or VF number
23229c20346bSAnirudh Venkataramanan  * @is_vf: true if the element is a VF, false otherwise
23239c20346bSAnirudh Venkataramanan  */
23249c20346bSAnirudh Venkataramanan static void
23259c20346bSAnirudh Venkataramanan ice_init_port_info(struct ice_port_info *pi, u16 vsi_port_num, u8 type,
23269c20346bSAnirudh Venkataramanan 		   u16 swid, u16 pf_vf_num, bool is_vf)
23279c20346bSAnirudh Venkataramanan {
23289c20346bSAnirudh Venkataramanan 	switch (type) {
23299c20346bSAnirudh Venkataramanan 	case ICE_AQC_GET_SW_CONF_RESP_PHYS_PORT:
23309c20346bSAnirudh Venkataramanan 		pi->lport = (u8)(vsi_port_num & ICE_LPORT_MASK);
23319c20346bSAnirudh Venkataramanan 		pi->sw_id = swid;
23329c20346bSAnirudh Venkataramanan 		pi->pf_vf_num = pf_vf_num;
23339c20346bSAnirudh Venkataramanan 		pi->is_vf = is_vf;
23349c20346bSAnirudh Venkataramanan 		break;
23359c20346bSAnirudh Venkataramanan 	default:
23369228d8b2SJacob Keller 		ice_debug(pi->hw, ICE_DBG_SW, "incorrect VSI/port type received\n");
23379c20346bSAnirudh Venkataramanan 		break;
23389c20346bSAnirudh Venkataramanan 	}
23399c20346bSAnirudh Venkataramanan }
23409c20346bSAnirudh Venkataramanan 
23419c20346bSAnirudh Venkataramanan /* ice_get_initial_sw_cfg - Get initial port and default VSI data
23429c20346bSAnirudh Venkataramanan  * @hw: pointer to the hardware structure
23439c20346bSAnirudh Venkataramanan  */
23445e24d598STony Nguyen int ice_get_initial_sw_cfg(struct ice_hw *hw)
23459c20346bSAnirudh Venkataramanan {
2346b3c38904SBruce Allan 	struct ice_aqc_get_sw_cfg_resp_elem *rbuf;
23479c20346bSAnirudh Venkataramanan 	u16 req_desc = 0;
23489c20346bSAnirudh Venkataramanan 	u16 num_elems;
23495518ac2aSTony Nguyen 	int status;
23509c20346bSAnirudh Venkataramanan 	u16 i;
23519c20346bSAnirudh Venkataramanan 
23521b9e740dSChristophe JAILLET 	rbuf = kzalloc(ICE_SW_CFG_MAX_BUF_LEN, GFP_KERNEL);
23539c20346bSAnirudh Venkataramanan 	if (!rbuf)
2354d54699e2STony Nguyen 		return -ENOMEM;
23559c20346bSAnirudh Venkataramanan 
23569c20346bSAnirudh Venkataramanan 	/* Multiple calls to ice_aq_get_sw_cfg may be required
23579c20346bSAnirudh Venkataramanan 	 * to get all the switch configuration information. The need
23589c20346bSAnirudh Venkataramanan 	 * for additional calls is indicated by ice_aq_get_sw_cfg
23599c20346bSAnirudh Venkataramanan 	 * writing a non-zero value in req_desc
23609c20346bSAnirudh Venkataramanan 	 */
23619c20346bSAnirudh Venkataramanan 	do {
2362b3c38904SBruce Allan 		struct ice_aqc_get_sw_cfg_resp_elem *ele;
2363b3c38904SBruce Allan 
23649c20346bSAnirudh Venkataramanan 		status = ice_aq_get_sw_cfg(hw, rbuf, ICE_SW_CFG_MAX_BUF_LEN,
23659c20346bSAnirudh Venkataramanan 					   &req_desc, &num_elems, NULL);
23669c20346bSAnirudh Venkataramanan 
23679c20346bSAnirudh Venkataramanan 		if (status)
23689c20346bSAnirudh Venkataramanan 			break;
23699c20346bSAnirudh Venkataramanan 
2370b3c38904SBruce Allan 		for (i = 0, ele = rbuf; i < num_elems; i++, ele++) {
23719c20346bSAnirudh Venkataramanan 			u16 pf_vf_num, swid, vsi_port_num;
23729c20346bSAnirudh Venkataramanan 			bool is_vf = false;
23736dae8aa0SBruce Allan 			u8 res_type;
23749c20346bSAnirudh Venkataramanan 
23759c20346bSAnirudh Venkataramanan 			vsi_port_num = le16_to_cpu(ele->vsi_port_num) &
23769c20346bSAnirudh Venkataramanan 				ICE_AQC_GET_SW_CONF_RESP_VSI_PORT_NUM_M;
23779c20346bSAnirudh Venkataramanan 
23789c20346bSAnirudh Venkataramanan 			pf_vf_num = le16_to_cpu(ele->pf_vf_num) &
23799c20346bSAnirudh Venkataramanan 				ICE_AQC_GET_SW_CONF_RESP_FUNC_NUM_M;
23809c20346bSAnirudh Venkataramanan 
23819c20346bSAnirudh Venkataramanan 			swid = le16_to_cpu(ele->swid);
23829c20346bSAnirudh Venkataramanan 
23839c20346bSAnirudh Venkataramanan 			if (le16_to_cpu(ele->pf_vf_num) &
23849c20346bSAnirudh Venkataramanan 			    ICE_AQC_GET_SW_CONF_RESP_IS_VF)
23859c20346bSAnirudh Venkataramanan 				is_vf = true;
23869c20346bSAnirudh Venkataramanan 
238788865fc4SKarol Kolacinski 			res_type = (u8)(le16_to_cpu(ele->vsi_port_num) >>
238888865fc4SKarol Kolacinski 					ICE_AQC_GET_SW_CONF_RESP_TYPE_S);
23899c20346bSAnirudh Venkataramanan 
23906dae8aa0SBruce Allan 			if (res_type == ICE_AQC_GET_SW_CONF_RESP_VSI) {
23919c20346bSAnirudh Venkataramanan 				/* FW VSI is not needed. Just continue. */
23929c20346bSAnirudh Venkataramanan 				continue;
23939c20346bSAnirudh Venkataramanan 			}
23949c20346bSAnirudh Venkataramanan 
23959c20346bSAnirudh Venkataramanan 			ice_init_port_info(hw->port_info, vsi_port_num,
23966dae8aa0SBruce Allan 					   res_type, swid, pf_vf_num, is_vf);
23979c20346bSAnirudh Venkataramanan 		}
23989c20346bSAnirudh Venkataramanan 	} while (req_desc && !status);
23999c20346bSAnirudh Venkataramanan 
24001b9e740dSChristophe JAILLET 	kfree(rbuf);
24019c20346bSAnirudh Venkataramanan 	return status;
24029c20346bSAnirudh Venkataramanan }
24039daf8208SAnirudh Venkataramanan 
24049daf8208SAnirudh Venkataramanan /**
24059daf8208SAnirudh Venkataramanan  * ice_fill_sw_info - Helper function to populate lb_en and lan_en
24069daf8208SAnirudh Venkataramanan  * @hw: pointer to the hardware structure
24076a7e6993SYashaswini Raghuram Prathivadi Bhayankaram  * @fi: filter info structure to fill/update
24089daf8208SAnirudh Venkataramanan  *
24099daf8208SAnirudh Venkataramanan  * This helper function populates the lb_en and lan_en elements of the provided
24109daf8208SAnirudh Venkataramanan  * ice_fltr_info struct using the switch's type and characteristics of the
24119daf8208SAnirudh Venkataramanan  * switch rule being configured.
24129daf8208SAnirudh Venkataramanan  */
24136a7e6993SYashaswini Raghuram Prathivadi Bhayankaram static void ice_fill_sw_info(struct ice_hw *hw, struct ice_fltr_info *fi)
24149daf8208SAnirudh Venkataramanan {
24156a7e6993SYashaswini Raghuram Prathivadi Bhayankaram 	fi->lb_en = false;
24166a7e6993SYashaswini Raghuram Prathivadi Bhayankaram 	fi->lan_en = false;
24176a7e6993SYashaswini Raghuram Prathivadi Bhayankaram 	if ((fi->flag & ICE_FLTR_TX) &&
24186a7e6993SYashaswini Raghuram Prathivadi Bhayankaram 	    (fi->fltr_act == ICE_FWD_TO_VSI ||
24196a7e6993SYashaswini Raghuram Prathivadi Bhayankaram 	     fi->fltr_act == ICE_FWD_TO_VSI_LIST ||
24206a7e6993SYashaswini Raghuram Prathivadi Bhayankaram 	     fi->fltr_act == ICE_FWD_TO_Q ||
24216a7e6993SYashaswini Raghuram Prathivadi Bhayankaram 	     fi->fltr_act == ICE_FWD_TO_QGRP)) {
2422b58dafbcSChristopher N Bednarz 		/* Setting LB for prune actions will result in replicated
2423b58dafbcSChristopher N Bednarz 		 * packets to the internal switch that will be dropped.
2424b58dafbcSChristopher N Bednarz 		 */
2425b58dafbcSChristopher N Bednarz 		if (fi->lkup_type != ICE_SW_LKUP_VLAN)
24266a7e6993SYashaswini Raghuram Prathivadi Bhayankaram 			fi->lb_en = true;
2427b58dafbcSChristopher N Bednarz 
2428277b3a45SYashaswini Raghuram Prathivadi Bhayankaram 		/* Set lan_en to TRUE if
24296a7e6993SYashaswini Raghuram Prathivadi Bhayankaram 		 * 1. The switch is a VEB AND
24306a7e6993SYashaswini Raghuram Prathivadi Bhayankaram 		 * 2
243126069b44SYashaswini Raghuram Prathivadi Bhayankaram 		 * 2.1 The lookup is a directional lookup like ethertype,
2432f9867df6SAnirudh Venkataramanan 		 * promiscuous, ethertype-MAC, promiscuous-VLAN
243326069b44SYashaswini Raghuram Prathivadi Bhayankaram 		 * and default-port OR
243426069b44SYashaswini Raghuram Prathivadi Bhayankaram 		 * 2.2 The lookup is VLAN, OR
2435277b3a45SYashaswini Raghuram Prathivadi Bhayankaram 		 * 2.3 The lookup is MAC with mcast or bcast addr for MAC, OR
2436277b3a45SYashaswini Raghuram Prathivadi Bhayankaram 		 * 2.4 The lookup is MAC_VLAN with mcast or bcast addr for MAC.
24376a7e6993SYashaswini Raghuram Prathivadi Bhayankaram 		 *
2438277b3a45SYashaswini Raghuram Prathivadi Bhayankaram 		 * OR
2439277b3a45SYashaswini Raghuram Prathivadi Bhayankaram 		 *
2440277b3a45SYashaswini Raghuram Prathivadi Bhayankaram 		 * The switch is a VEPA.
2441277b3a45SYashaswini Raghuram Prathivadi Bhayankaram 		 *
2442277b3a45SYashaswini Raghuram Prathivadi Bhayankaram 		 * In all other cases, the LAN enable has to be set to false.
24436a7e6993SYashaswini Raghuram Prathivadi Bhayankaram 		 */
2444277b3a45SYashaswini Raghuram Prathivadi Bhayankaram 		if (hw->evb_veb) {
244526069b44SYashaswini Raghuram Prathivadi Bhayankaram 			if (fi->lkup_type == ICE_SW_LKUP_ETHERTYPE ||
244626069b44SYashaswini Raghuram Prathivadi Bhayankaram 			    fi->lkup_type == ICE_SW_LKUP_PROMISC ||
244726069b44SYashaswini Raghuram Prathivadi Bhayankaram 			    fi->lkup_type == ICE_SW_LKUP_ETHERTYPE_MAC ||
244826069b44SYashaswini Raghuram Prathivadi Bhayankaram 			    fi->lkup_type == ICE_SW_LKUP_PROMISC_VLAN ||
2449277b3a45SYashaswini Raghuram Prathivadi Bhayankaram 			    fi->lkup_type == ICE_SW_LKUP_DFLT ||
245026069b44SYashaswini Raghuram Prathivadi Bhayankaram 			    fi->lkup_type == ICE_SW_LKUP_VLAN ||
2451277b3a45SYashaswini Raghuram Prathivadi Bhayankaram 			    (fi->lkup_type == ICE_SW_LKUP_MAC &&
2452277b3a45SYashaswini Raghuram Prathivadi Bhayankaram 			     !is_unicast_ether_addr(fi->l_data.mac.mac_addr)) ||
24536a7e6993SYashaswini Raghuram Prathivadi Bhayankaram 			    (fi->lkup_type == ICE_SW_LKUP_MAC_VLAN &&
2454277b3a45SYashaswini Raghuram Prathivadi Bhayankaram 			     !is_unicast_ether_addr(fi->l_data.mac.mac_addr)))
24556a7e6993SYashaswini Raghuram Prathivadi Bhayankaram 				fi->lan_en = true;
2456277b3a45SYashaswini Raghuram Prathivadi Bhayankaram 		} else {
2457277b3a45SYashaswini Raghuram Prathivadi Bhayankaram 			fi->lan_en = true;
2458277b3a45SYashaswini Raghuram Prathivadi Bhayankaram 		}
24599daf8208SAnirudh Venkataramanan 	}
24609daf8208SAnirudh Venkataramanan }
24619daf8208SAnirudh Venkataramanan 
24629daf8208SAnirudh Venkataramanan /**
2463*ec5a6c5fSDave Ertman  * ice_fill_eth_hdr - helper to copy dummy_eth_hdr into supplied buffer
2464*ec5a6c5fSDave Ertman  * @eth_hdr: pointer to buffer to populate
2465*ec5a6c5fSDave Ertman  */
2466*ec5a6c5fSDave Ertman void ice_fill_eth_hdr(u8 *eth_hdr)
2467*ec5a6c5fSDave Ertman {
2468*ec5a6c5fSDave Ertman 	memcpy(eth_hdr, dummy_eth_header, DUMMY_ETH_HDR_LEN);
2469*ec5a6c5fSDave Ertman }
2470*ec5a6c5fSDave Ertman 
2471*ec5a6c5fSDave Ertman /**
24729daf8208SAnirudh Venkataramanan  * ice_fill_sw_rule - Helper function to fill switch rule structure
24739daf8208SAnirudh Venkataramanan  * @hw: pointer to the hardware structure
24749daf8208SAnirudh Venkataramanan  * @f_info: entry containing packet forwarding information
24759daf8208SAnirudh Venkataramanan  * @s_rule: switch rule structure to be filled in based on mac_entry
24769daf8208SAnirudh Venkataramanan  * @opc: switch rules population command type - pass in the command opcode
24779daf8208SAnirudh Venkataramanan  */
24789daf8208SAnirudh Venkataramanan static void
24799daf8208SAnirudh Venkataramanan ice_fill_sw_rule(struct ice_hw *hw, struct ice_fltr_info *f_info,
24806e1ff618SAlexander Lobakin 		 struct ice_sw_rule_lkup_rx_tx *s_rule,
24816e1ff618SAlexander Lobakin 		 enum ice_adminq_opc opc)
24829daf8208SAnirudh Venkataramanan {
24839daf8208SAnirudh Venkataramanan 	u16 vlan_id = ICE_MAX_VLAN_ID + 1;
24842bfefa2dSBrett Creeley 	u16 vlan_tpid = ETH_P_8021Q;
24859daf8208SAnirudh Venkataramanan 	void *daddr = NULL;
248674118f7aSZhenning Xiao 	u16 eth_hdr_sz;
248774118f7aSZhenning Xiao 	u8 *eth_hdr;
24889daf8208SAnirudh Venkataramanan 	u32 act = 0;
24899daf8208SAnirudh Venkataramanan 	__be16 *off;
2490be8ff000SAnirudh Venkataramanan 	u8 q_rgn;
24919daf8208SAnirudh Venkataramanan 
24929daf8208SAnirudh Venkataramanan 	if (opc == ice_aqc_opc_remove_sw_rules) {
24936e1ff618SAlexander Lobakin 		s_rule->act = 0;
24946e1ff618SAlexander Lobakin 		s_rule->index = cpu_to_le16(f_info->fltr_rule_id);
24956e1ff618SAlexander Lobakin 		s_rule->hdr_len = 0;
24969daf8208SAnirudh Venkataramanan 		return;
24979daf8208SAnirudh Venkataramanan 	}
24989daf8208SAnirudh Venkataramanan 
249974118f7aSZhenning Xiao 	eth_hdr_sz = sizeof(dummy_eth_header);
25006e1ff618SAlexander Lobakin 	eth_hdr = s_rule->hdr_data;
250174118f7aSZhenning Xiao 
25029daf8208SAnirudh Venkataramanan 	/* initialize the ether header with a dummy header */
250374118f7aSZhenning Xiao 	memcpy(eth_hdr, dummy_eth_header, eth_hdr_sz);
25049daf8208SAnirudh Venkataramanan 	ice_fill_sw_info(hw, f_info);
25059daf8208SAnirudh Venkataramanan 
25069daf8208SAnirudh Venkataramanan 	switch (f_info->fltr_act) {
25079daf8208SAnirudh Venkataramanan 	case ICE_FWD_TO_VSI:
25085726ca0eSAnirudh Venkataramanan 		act |= (f_info->fwd_id.hw_vsi_id << ICE_SINGLE_ACT_VSI_ID_S) &
25099daf8208SAnirudh Venkataramanan 			ICE_SINGLE_ACT_VSI_ID_M;
25109daf8208SAnirudh Venkataramanan 		if (f_info->lkup_type != ICE_SW_LKUP_VLAN)
25119daf8208SAnirudh Venkataramanan 			act |= ICE_SINGLE_ACT_VSI_FORWARDING |
25129daf8208SAnirudh Venkataramanan 				ICE_SINGLE_ACT_VALID_BIT;
25139daf8208SAnirudh Venkataramanan 		break;
25149daf8208SAnirudh Venkataramanan 	case ICE_FWD_TO_VSI_LIST:
25159daf8208SAnirudh Venkataramanan 		act |= ICE_SINGLE_ACT_VSI_LIST;
25169daf8208SAnirudh Venkataramanan 		act |= (f_info->fwd_id.vsi_list_id <<
25179daf8208SAnirudh Venkataramanan 			ICE_SINGLE_ACT_VSI_LIST_ID_S) &
25189daf8208SAnirudh Venkataramanan 			ICE_SINGLE_ACT_VSI_LIST_ID_M;
25199daf8208SAnirudh Venkataramanan 		if (f_info->lkup_type != ICE_SW_LKUP_VLAN)
25209daf8208SAnirudh Venkataramanan 			act |= ICE_SINGLE_ACT_VSI_FORWARDING |
25219daf8208SAnirudh Venkataramanan 				ICE_SINGLE_ACT_VALID_BIT;
25229daf8208SAnirudh Venkataramanan 		break;
25239daf8208SAnirudh Venkataramanan 	case ICE_FWD_TO_Q:
25249daf8208SAnirudh Venkataramanan 		act |= ICE_SINGLE_ACT_TO_Q;
25259daf8208SAnirudh Venkataramanan 		act |= (f_info->fwd_id.q_id << ICE_SINGLE_ACT_Q_INDEX_S) &
25269daf8208SAnirudh Venkataramanan 			ICE_SINGLE_ACT_Q_INDEX_M;
25279daf8208SAnirudh Venkataramanan 		break;
25289daf8208SAnirudh Venkataramanan 	case ICE_DROP_PACKET:
2529be8ff000SAnirudh Venkataramanan 		act |= ICE_SINGLE_ACT_VSI_FORWARDING | ICE_SINGLE_ACT_DROP |
2530be8ff000SAnirudh Venkataramanan 			ICE_SINGLE_ACT_VALID_BIT;
2531be8ff000SAnirudh Venkataramanan 		break;
2532be8ff000SAnirudh Venkataramanan 	case ICE_FWD_TO_QGRP:
2533be8ff000SAnirudh Venkataramanan 		q_rgn = f_info->qgrp_size > 0 ?
2534be8ff000SAnirudh Venkataramanan 			(u8)ilog2(f_info->qgrp_size) : 0;
2535be8ff000SAnirudh Venkataramanan 		act |= ICE_SINGLE_ACT_TO_Q;
2536be8ff000SAnirudh Venkataramanan 		act |= (f_info->fwd_id.q_id << ICE_SINGLE_ACT_Q_INDEX_S) &
2537be8ff000SAnirudh Venkataramanan 			ICE_SINGLE_ACT_Q_INDEX_M;
2538be8ff000SAnirudh Venkataramanan 		act |= (q_rgn << ICE_SINGLE_ACT_Q_REGION_S) &
2539be8ff000SAnirudh Venkataramanan 			ICE_SINGLE_ACT_Q_REGION_M;
25409daf8208SAnirudh Venkataramanan 		break;
25419daf8208SAnirudh Venkataramanan 	default:
25429daf8208SAnirudh Venkataramanan 		return;
25439daf8208SAnirudh Venkataramanan 	}
25449daf8208SAnirudh Venkataramanan 
25459daf8208SAnirudh Venkataramanan 	if (f_info->lb_en)
25469daf8208SAnirudh Venkataramanan 		act |= ICE_SINGLE_ACT_LB_ENABLE;
25479daf8208SAnirudh Venkataramanan 	if (f_info->lan_en)
25489daf8208SAnirudh Venkataramanan 		act |= ICE_SINGLE_ACT_LAN_ENABLE;
25499daf8208SAnirudh Venkataramanan 
25509daf8208SAnirudh Venkataramanan 	switch (f_info->lkup_type) {
25519daf8208SAnirudh Venkataramanan 	case ICE_SW_LKUP_MAC:
25529daf8208SAnirudh Venkataramanan 		daddr = f_info->l_data.mac.mac_addr;
25539daf8208SAnirudh Venkataramanan 		break;
25549daf8208SAnirudh Venkataramanan 	case ICE_SW_LKUP_VLAN:
25559daf8208SAnirudh Venkataramanan 		vlan_id = f_info->l_data.vlan.vlan_id;
25562bfefa2dSBrett Creeley 		if (f_info->l_data.vlan.tpid_valid)
25572bfefa2dSBrett Creeley 			vlan_tpid = f_info->l_data.vlan.tpid;
25589daf8208SAnirudh Venkataramanan 		if (f_info->fltr_act == ICE_FWD_TO_VSI ||
25599daf8208SAnirudh Venkataramanan 		    f_info->fltr_act == ICE_FWD_TO_VSI_LIST) {
25609daf8208SAnirudh Venkataramanan 			act |= ICE_SINGLE_ACT_PRUNE;
25619daf8208SAnirudh Venkataramanan 			act |= ICE_SINGLE_ACT_EGRESS | ICE_SINGLE_ACT_INGRESS;
25629daf8208SAnirudh Venkataramanan 		}
25639daf8208SAnirudh Venkataramanan 		break;
25649daf8208SAnirudh Venkataramanan 	case ICE_SW_LKUP_ETHERTYPE_MAC:
25659daf8208SAnirudh Venkataramanan 		daddr = f_info->l_data.ethertype_mac.mac_addr;
25664e83fc93SBruce Allan 		fallthrough;
25679daf8208SAnirudh Venkataramanan 	case ICE_SW_LKUP_ETHERTYPE:
2568feee3cb3SBruce Allan 		off = (__force __be16 *)(eth_hdr + ICE_ETH_ETHTYPE_OFFSET);
25699daf8208SAnirudh Venkataramanan 		*off = cpu_to_be16(f_info->l_data.ethertype_mac.ethertype);
25709daf8208SAnirudh Venkataramanan 		break;
25719daf8208SAnirudh Venkataramanan 	case ICE_SW_LKUP_MAC_VLAN:
25729daf8208SAnirudh Venkataramanan 		daddr = f_info->l_data.mac_vlan.mac_addr;
25739daf8208SAnirudh Venkataramanan 		vlan_id = f_info->l_data.mac_vlan.vlan_id;
25749daf8208SAnirudh Venkataramanan 		break;
25759daf8208SAnirudh Venkataramanan 	case ICE_SW_LKUP_PROMISC_VLAN:
25769daf8208SAnirudh Venkataramanan 		vlan_id = f_info->l_data.mac_vlan.vlan_id;
25774e83fc93SBruce Allan 		fallthrough;
25789daf8208SAnirudh Venkataramanan 	case ICE_SW_LKUP_PROMISC:
25799daf8208SAnirudh Venkataramanan 		daddr = f_info->l_data.mac_vlan.mac_addr;
25809daf8208SAnirudh Venkataramanan 		break;
25819daf8208SAnirudh Venkataramanan 	default:
25829daf8208SAnirudh Venkataramanan 		break;
25839daf8208SAnirudh Venkataramanan 	}
25849daf8208SAnirudh Venkataramanan 
25856e1ff618SAlexander Lobakin 	s_rule->hdr.type = (f_info->flag & ICE_FLTR_RX) ?
25869daf8208SAnirudh Venkataramanan 		cpu_to_le16(ICE_AQC_SW_RULES_T_LKUP_RX) :
25879daf8208SAnirudh Venkataramanan 		cpu_to_le16(ICE_AQC_SW_RULES_T_LKUP_TX);
25889daf8208SAnirudh Venkataramanan 
25899daf8208SAnirudh Venkataramanan 	/* Recipe set depending on lookup type */
25906e1ff618SAlexander Lobakin 	s_rule->recipe_id = cpu_to_le16(f_info->lkup_type);
25916e1ff618SAlexander Lobakin 	s_rule->src = cpu_to_le16(f_info->src);
25926e1ff618SAlexander Lobakin 	s_rule->act = cpu_to_le32(act);
25939daf8208SAnirudh Venkataramanan 
25949daf8208SAnirudh Venkataramanan 	if (daddr)
259574118f7aSZhenning Xiao 		ether_addr_copy(eth_hdr + ICE_ETH_DA_OFFSET, daddr);
25969daf8208SAnirudh Venkataramanan 
25979daf8208SAnirudh Venkataramanan 	if (!(vlan_id > ICE_MAX_VLAN_ID)) {
2598feee3cb3SBruce Allan 		off = (__force __be16 *)(eth_hdr + ICE_ETH_VLAN_TCI_OFFSET);
25999daf8208SAnirudh Venkataramanan 		*off = cpu_to_be16(vlan_id);
26002bfefa2dSBrett Creeley 		off = (__force __be16 *)(eth_hdr + ICE_ETH_ETHTYPE_OFFSET);
26012bfefa2dSBrett Creeley 		*off = cpu_to_be16(vlan_tpid);
26029daf8208SAnirudh Venkataramanan 	}
26039daf8208SAnirudh Venkataramanan 
26049daf8208SAnirudh Venkataramanan 	/* Create the switch rule with the final dummy Ethernet header */
26059daf8208SAnirudh Venkataramanan 	if (opc != ice_aqc_opc_update_sw_rules)
26066e1ff618SAlexander Lobakin 		s_rule->hdr_len = cpu_to_le16(eth_hdr_sz);
26079daf8208SAnirudh Venkataramanan }
26089daf8208SAnirudh Venkataramanan 
26099daf8208SAnirudh Venkataramanan /**
26109daf8208SAnirudh Venkataramanan  * ice_add_marker_act
26119daf8208SAnirudh Venkataramanan  * @hw: pointer to the hardware structure
26129daf8208SAnirudh Venkataramanan  * @m_ent: the management entry for which sw marker needs to be added
26139daf8208SAnirudh Venkataramanan  * @sw_marker: sw marker to tag the Rx descriptor with
2614f9867df6SAnirudh Venkataramanan  * @l_id: large action resource ID
26159daf8208SAnirudh Venkataramanan  *
26169daf8208SAnirudh Venkataramanan  * Create a large action to hold software marker and update the switch rule
26179daf8208SAnirudh Venkataramanan  * entry pointed by m_ent with newly created large action
26189daf8208SAnirudh Venkataramanan  */
26195e24d598STony Nguyen static int
26209daf8208SAnirudh Venkataramanan ice_add_marker_act(struct ice_hw *hw, struct ice_fltr_mgmt_list_entry *m_ent,
26219daf8208SAnirudh Venkataramanan 		   u16 sw_marker, u16 l_id)
26229daf8208SAnirudh Venkataramanan {
26236e1ff618SAlexander Lobakin 	struct ice_sw_rule_lkup_rx_tx *rx_tx;
26246e1ff618SAlexander Lobakin 	struct ice_sw_rule_lg_act *lg_act;
26259daf8208SAnirudh Venkataramanan 	/* For software marker we need 3 large actions
26269daf8208SAnirudh Venkataramanan 	 * 1. FWD action: FWD TO VSI or VSI LIST
2627f9867df6SAnirudh Venkataramanan 	 * 2. GENERIC VALUE action to hold the profile ID
2628f9867df6SAnirudh Venkataramanan 	 * 3. GENERIC VALUE action to hold the software marker ID
26299daf8208SAnirudh Venkataramanan 	 */
26309daf8208SAnirudh Venkataramanan 	const u16 num_lg_acts = 3;
26319daf8208SAnirudh Venkataramanan 	u16 lg_act_size;
26329daf8208SAnirudh Venkataramanan 	u16 rules_size;
26335518ac2aSTony Nguyen 	int status;
26349daf8208SAnirudh Venkataramanan 	u32 act;
26355726ca0eSAnirudh Venkataramanan 	u16 id;
26369daf8208SAnirudh Venkataramanan 
26379daf8208SAnirudh Venkataramanan 	if (m_ent->fltr_info.lkup_type != ICE_SW_LKUP_MAC)
2638d54699e2STony Nguyen 		return -EINVAL;
26399daf8208SAnirudh Venkataramanan 
26409daf8208SAnirudh Venkataramanan 	/* Create two back-to-back switch rules and submit them to the HW using
26419daf8208SAnirudh Venkataramanan 	 * one memory buffer:
26429daf8208SAnirudh Venkataramanan 	 *    1. Large Action
2643d337f2afSAnirudh Venkataramanan 	 *    2. Look up Tx Rx
26449daf8208SAnirudh Venkataramanan 	 */
26456e1ff618SAlexander Lobakin 	lg_act_size = (u16)ICE_SW_RULE_LG_ACT_SIZE(lg_act, num_lg_acts);
26466e1ff618SAlexander Lobakin 	rules_size = lg_act_size + ICE_SW_RULE_RX_TX_ETH_HDR_SIZE(rx_tx);
26479daf8208SAnirudh Venkataramanan 	lg_act = devm_kzalloc(ice_hw_to_dev(hw), rules_size, GFP_KERNEL);
26489daf8208SAnirudh Venkataramanan 	if (!lg_act)
2649d54699e2STony Nguyen 		return -ENOMEM;
26509daf8208SAnirudh Venkataramanan 
26516e1ff618SAlexander Lobakin 	rx_tx = (typeof(rx_tx))((u8 *)lg_act + lg_act_size);
26529daf8208SAnirudh Venkataramanan 
26539daf8208SAnirudh Venkataramanan 	/* Fill in the first switch rule i.e. large action */
26546e1ff618SAlexander Lobakin 	lg_act->hdr.type = cpu_to_le16(ICE_AQC_SW_RULES_T_LG_ACT);
26556e1ff618SAlexander Lobakin 	lg_act->index = cpu_to_le16(l_id);
26566e1ff618SAlexander Lobakin 	lg_act->size = cpu_to_le16(num_lg_acts);
26579daf8208SAnirudh Venkataramanan 
26589daf8208SAnirudh Venkataramanan 	/* First action VSI forwarding or VSI list forwarding depending on how
26599daf8208SAnirudh Venkataramanan 	 * many VSIs
26609daf8208SAnirudh Venkataramanan 	 */
26615726ca0eSAnirudh Venkataramanan 	id = (m_ent->vsi_count > 1) ? m_ent->fltr_info.fwd_id.vsi_list_id :
26625726ca0eSAnirudh Venkataramanan 		m_ent->fltr_info.fwd_id.hw_vsi_id;
26639daf8208SAnirudh Venkataramanan 
26649daf8208SAnirudh Venkataramanan 	act = ICE_LG_ACT_VSI_FORWARDING | ICE_LG_ACT_VALID_BIT;
266566486d89SBruce Allan 	act |= (id << ICE_LG_ACT_VSI_LIST_ID_S) & ICE_LG_ACT_VSI_LIST_ID_M;
26669daf8208SAnirudh Venkataramanan 	if (m_ent->vsi_count > 1)
26679daf8208SAnirudh Venkataramanan 		act |= ICE_LG_ACT_VSI_LIST;
26686e1ff618SAlexander Lobakin 	lg_act->act[0] = cpu_to_le32(act);
26699daf8208SAnirudh Venkataramanan 
26709daf8208SAnirudh Venkataramanan 	/* Second action descriptor type */
26719daf8208SAnirudh Venkataramanan 	act = ICE_LG_ACT_GENERIC;
26729daf8208SAnirudh Venkataramanan 
26739daf8208SAnirudh Venkataramanan 	act |= (1 << ICE_LG_ACT_GENERIC_VALUE_S) & ICE_LG_ACT_GENERIC_VALUE_M;
26746e1ff618SAlexander Lobakin 	lg_act->act[1] = cpu_to_le32(act);
26759daf8208SAnirudh Venkataramanan 
26764381147dSAnirudh Venkataramanan 	act = (ICE_LG_ACT_GENERIC_OFF_RX_DESC_PROF_IDX <<
26774381147dSAnirudh Venkataramanan 	       ICE_LG_ACT_GENERIC_OFFSET_S) & ICE_LG_ACT_GENERIC_OFFSET_M;
26789daf8208SAnirudh Venkataramanan 
26799daf8208SAnirudh Venkataramanan 	/* Third action Marker value */
26809daf8208SAnirudh Venkataramanan 	act |= ICE_LG_ACT_GENERIC;
26819daf8208SAnirudh Venkataramanan 	act |= (sw_marker << ICE_LG_ACT_GENERIC_VALUE_S) &
26829daf8208SAnirudh Venkataramanan 		ICE_LG_ACT_GENERIC_VALUE_M;
26839daf8208SAnirudh Venkataramanan 
26846e1ff618SAlexander Lobakin 	lg_act->act[2] = cpu_to_le32(act);
26859daf8208SAnirudh Venkataramanan 
2686d337f2afSAnirudh Venkataramanan 	/* call the fill switch rule to fill the lookup Tx Rx structure */
26879daf8208SAnirudh Venkataramanan 	ice_fill_sw_rule(hw, &m_ent->fltr_info, rx_tx,
26889daf8208SAnirudh Venkataramanan 			 ice_aqc_opc_update_sw_rules);
26899daf8208SAnirudh Venkataramanan 
2690f9867df6SAnirudh Venkataramanan 	/* Update the action to point to the large action ID */
26916e1ff618SAlexander Lobakin 	rx_tx->act = cpu_to_le32(ICE_SINGLE_ACT_PTR |
26929daf8208SAnirudh Venkataramanan 				 ((l_id << ICE_SINGLE_ACT_PTR_VAL_S) &
26939daf8208SAnirudh Venkataramanan 				  ICE_SINGLE_ACT_PTR_VAL_M));
26949daf8208SAnirudh Venkataramanan 
2695f9867df6SAnirudh Venkataramanan 	/* Use the filter rule ID of the previously created rule with single
26969daf8208SAnirudh Venkataramanan 	 * act. Once the update happens, hardware will treat this as large
26979daf8208SAnirudh Venkataramanan 	 * action
26989daf8208SAnirudh Venkataramanan 	 */
26996e1ff618SAlexander Lobakin 	rx_tx->index = cpu_to_le16(m_ent->fltr_info.fltr_rule_id);
27009daf8208SAnirudh Venkataramanan 
27019daf8208SAnirudh Venkataramanan 	status = ice_aq_sw_rules(hw, lg_act, rules_size, 2,
27029daf8208SAnirudh Venkataramanan 				 ice_aqc_opc_update_sw_rules, NULL);
27039daf8208SAnirudh Venkataramanan 	if (!status) {
27049daf8208SAnirudh Venkataramanan 		m_ent->lg_act_idx = l_id;
27059daf8208SAnirudh Venkataramanan 		m_ent->sw_marker_id = sw_marker;
27069daf8208SAnirudh Venkataramanan 	}
27079daf8208SAnirudh Venkataramanan 
27089daf8208SAnirudh Venkataramanan 	devm_kfree(ice_hw_to_dev(hw), lg_act);
27099daf8208SAnirudh Venkataramanan 	return status;
27109daf8208SAnirudh Venkataramanan }
27119daf8208SAnirudh Venkataramanan 
27129daf8208SAnirudh Venkataramanan /**
27139daf8208SAnirudh Venkataramanan  * ice_create_vsi_list_map
27149daf8208SAnirudh Venkataramanan  * @hw: pointer to the hardware structure
27155726ca0eSAnirudh Venkataramanan  * @vsi_handle_arr: array of VSI handles to set in the VSI mapping
27165726ca0eSAnirudh Venkataramanan  * @num_vsi: number of VSI handles in the array
2717f9867df6SAnirudh Venkataramanan  * @vsi_list_id: VSI list ID generated as part of allocate resource
27189daf8208SAnirudh Venkataramanan  *
2719f9867df6SAnirudh Venkataramanan  * Helper function to create a new entry of VSI list ID to VSI mapping
2720f9867df6SAnirudh Venkataramanan  * using the given VSI list ID
27219daf8208SAnirudh Venkataramanan  */
27229daf8208SAnirudh Venkataramanan static struct ice_vsi_list_map_info *
27235726ca0eSAnirudh Venkataramanan ice_create_vsi_list_map(struct ice_hw *hw, u16 *vsi_handle_arr, u16 num_vsi,
27249daf8208SAnirudh Venkataramanan 			u16 vsi_list_id)
27259daf8208SAnirudh Venkataramanan {
27269daf8208SAnirudh Venkataramanan 	struct ice_switch_info *sw = hw->switch_info;
27279daf8208SAnirudh Venkataramanan 	struct ice_vsi_list_map_info *v_map;
27289daf8208SAnirudh Venkataramanan 	int i;
27299daf8208SAnirudh Venkataramanan 
273036ac7911SBruce Allan 	v_map = devm_kzalloc(ice_hw_to_dev(hw), sizeof(*v_map), GFP_KERNEL);
27319daf8208SAnirudh Venkataramanan 	if (!v_map)
27329daf8208SAnirudh Venkataramanan 		return NULL;
27339daf8208SAnirudh Venkataramanan 
27349daf8208SAnirudh Venkataramanan 	v_map->vsi_list_id = vsi_list_id;
27355726ca0eSAnirudh Venkataramanan 	v_map->ref_cnt = 1;
27369daf8208SAnirudh Venkataramanan 	for (i = 0; i < num_vsi; i++)
27375726ca0eSAnirudh Venkataramanan 		set_bit(vsi_handle_arr[i], v_map->vsi_map);
27389daf8208SAnirudh Venkataramanan 
27399daf8208SAnirudh Venkataramanan 	list_add(&v_map->list_entry, &sw->vsi_list_map_head);
27409daf8208SAnirudh Venkataramanan 	return v_map;
27419daf8208SAnirudh Venkataramanan }
27429daf8208SAnirudh Venkataramanan 
27439daf8208SAnirudh Venkataramanan /**
27449daf8208SAnirudh Venkataramanan  * ice_update_vsi_list_rule
27459daf8208SAnirudh Venkataramanan  * @hw: pointer to the hardware structure
27465726ca0eSAnirudh Venkataramanan  * @vsi_handle_arr: array of VSI handles to form a VSI list
27475726ca0eSAnirudh Venkataramanan  * @num_vsi: number of VSI handles in the array
2748f9867df6SAnirudh Venkataramanan  * @vsi_list_id: VSI list ID generated as part of allocate resource
27499daf8208SAnirudh Venkataramanan  * @remove: Boolean value to indicate if this is a remove action
27509daf8208SAnirudh Venkataramanan  * @opc: switch rules population command type - pass in the command opcode
27519daf8208SAnirudh Venkataramanan  * @lkup_type: lookup type of the filter
27529daf8208SAnirudh Venkataramanan  *
27539daf8208SAnirudh Venkataramanan  * Call AQ command to add a new switch rule or update existing switch rule
2754f9867df6SAnirudh Venkataramanan  * using the given VSI list ID
27559daf8208SAnirudh Venkataramanan  */
27565e24d598STony Nguyen static int
27575726ca0eSAnirudh Venkataramanan ice_update_vsi_list_rule(struct ice_hw *hw, u16 *vsi_handle_arr, u16 num_vsi,
27589daf8208SAnirudh Venkataramanan 			 u16 vsi_list_id, bool remove, enum ice_adminq_opc opc,
27599daf8208SAnirudh Venkataramanan 			 enum ice_sw_lkup_type lkup_type)
27609daf8208SAnirudh Venkataramanan {
27616e1ff618SAlexander Lobakin 	struct ice_sw_rule_vsi_list *s_rule;
27629daf8208SAnirudh Venkataramanan 	u16 s_rule_size;
27636dae8aa0SBruce Allan 	u16 rule_type;
27645518ac2aSTony Nguyen 	int status;
27659daf8208SAnirudh Venkataramanan 	int i;
27669daf8208SAnirudh Venkataramanan 
27679daf8208SAnirudh Venkataramanan 	if (!num_vsi)
2768d54699e2STony Nguyen 		return -EINVAL;
27699daf8208SAnirudh Venkataramanan 
27709daf8208SAnirudh Venkataramanan 	if (lkup_type == ICE_SW_LKUP_MAC ||
27719daf8208SAnirudh Venkataramanan 	    lkup_type == ICE_SW_LKUP_MAC_VLAN ||
27729daf8208SAnirudh Venkataramanan 	    lkup_type == ICE_SW_LKUP_ETHERTYPE ||
27739daf8208SAnirudh Venkataramanan 	    lkup_type == ICE_SW_LKUP_ETHERTYPE_MAC ||
27749daf8208SAnirudh Venkataramanan 	    lkup_type == ICE_SW_LKUP_PROMISC ||
2775d7393425SMichal Wilczynski 	    lkup_type == ICE_SW_LKUP_PROMISC_VLAN ||
2776d7393425SMichal Wilczynski 	    lkup_type == ICE_SW_LKUP_DFLT)
27776dae8aa0SBruce Allan 		rule_type = remove ? ICE_AQC_SW_RULES_T_VSI_LIST_CLEAR :
27789daf8208SAnirudh Venkataramanan 			ICE_AQC_SW_RULES_T_VSI_LIST_SET;
27799daf8208SAnirudh Venkataramanan 	else if (lkup_type == ICE_SW_LKUP_VLAN)
27806dae8aa0SBruce Allan 		rule_type = remove ? ICE_AQC_SW_RULES_T_PRUNE_LIST_CLEAR :
27819daf8208SAnirudh Venkataramanan 			ICE_AQC_SW_RULES_T_PRUNE_LIST_SET;
27829daf8208SAnirudh Venkataramanan 	else
2783d54699e2STony Nguyen 		return -EINVAL;
27849daf8208SAnirudh Venkataramanan 
27856e1ff618SAlexander Lobakin 	s_rule_size = (u16)ICE_SW_RULE_VSI_LIST_SIZE(s_rule, num_vsi);
27869daf8208SAnirudh Venkataramanan 	s_rule = devm_kzalloc(ice_hw_to_dev(hw), s_rule_size, GFP_KERNEL);
27879daf8208SAnirudh Venkataramanan 	if (!s_rule)
2788d54699e2STony Nguyen 		return -ENOMEM;
27895726ca0eSAnirudh Venkataramanan 	for (i = 0; i < num_vsi; i++) {
27905726ca0eSAnirudh Venkataramanan 		if (!ice_is_vsi_valid(hw, vsi_handle_arr[i])) {
2791d54699e2STony Nguyen 			status = -EINVAL;
27925726ca0eSAnirudh Venkataramanan 			goto exit;
27935726ca0eSAnirudh Venkataramanan 		}
27945726ca0eSAnirudh Venkataramanan 		/* AQ call requires hw_vsi_id(s) */
27956e1ff618SAlexander Lobakin 		s_rule->vsi[i] =
27965726ca0eSAnirudh Venkataramanan 			cpu_to_le16(ice_get_hw_vsi_num(hw, vsi_handle_arr[i]));
27975726ca0eSAnirudh Venkataramanan 	}
27989daf8208SAnirudh Venkataramanan 
27996e1ff618SAlexander Lobakin 	s_rule->hdr.type = cpu_to_le16(rule_type);
28006e1ff618SAlexander Lobakin 	s_rule->number_vsi = cpu_to_le16(num_vsi);
28016e1ff618SAlexander Lobakin 	s_rule->index = cpu_to_le16(vsi_list_id);
28029daf8208SAnirudh Venkataramanan 
28039daf8208SAnirudh Venkataramanan 	status = ice_aq_sw_rules(hw, s_rule, s_rule_size, 1, opc, NULL);
28049daf8208SAnirudh Venkataramanan 
28055726ca0eSAnirudh Venkataramanan exit:
28069daf8208SAnirudh Venkataramanan 	devm_kfree(ice_hw_to_dev(hw), s_rule);
28079daf8208SAnirudh Venkataramanan 	return status;
28089daf8208SAnirudh Venkataramanan }
28099daf8208SAnirudh Venkataramanan 
28109daf8208SAnirudh Venkataramanan /**
28119daf8208SAnirudh Venkataramanan  * ice_create_vsi_list_rule - Creates and populates a VSI list rule
2812f9867df6SAnirudh Venkataramanan  * @hw: pointer to the HW struct
28135726ca0eSAnirudh Venkataramanan  * @vsi_handle_arr: array of VSI handles to form a VSI list
28145726ca0eSAnirudh Venkataramanan  * @num_vsi: number of VSI handles in the array
28159daf8208SAnirudh Venkataramanan  * @vsi_list_id: stores the ID of the VSI list to be created
28169daf8208SAnirudh Venkataramanan  * @lkup_type: switch rule filter's lookup type
28179daf8208SAnirudh Venkataramanan  */
28185e24d598STony Nguyen static int
28195726ca0eSAnirudh Venkataramanan ice_create_vsi_list_rule(struct ice_hw *hw, u16 *vsi_handle_arr, u16 num_vsi,
28209daf8208SAnirudh Venkataramanan 			 u16 *vsi_list_id, enum ice_sw_lkup_type lkup_type)
28219daf8208SAnirudh Venkataramanan {
28225e24d598STony Nguyen 	int status;
28239daf8208SAnirudh Venkataramanan 
28249daf8208SAnirudh Venkataramanan 	status = ice_aq_alloc_free_vsi_list(hw, vsi_list_id, lkup_type,
28259daf8208SAnirudh Venkataramanan 					    ice_aqc_opc_alloc_res);
28269daf8208SAnirudh Venkataramanan 	if (status)
28279daf8208SAnirudh Venkataramanan 		return status;
28289daf8208SAnirudh Venkataramanan 
28299daf8208SAnirudh Venkataramanan 	/* Update the newly created VSI list to include the specified VSIs */
28305726ca0eSAnirudh Venkataramanan 	return ice_update_vsi_list_rule(hw, vsi_handle_arr, num_vsi,
28315726ca0eSAnirudh Venkataramanan 					*vsi_list_id, false,
28325726ca0eSAnirudh Venkataramanan 					ice_aqc_opc_add_sw_rules, lkup_type);
28339daf8208SAnirudh Venkataramanan }
28349daf8208SAnirudh Venkataramanan 
28359daf8208SAnirudh Venkataramanan /**
28369daf8208SAnirudh Venkataramanan  * ice_create_pkt_fwd_rule
28379daf8208SAnirudh Venkataramanan  * @hw: pointer to the hardware structure
28389daf8208SAnirudh Venkataramanan  * @f_entry: entry containing packet forwarding information
28399daf8208SAnirudh Venkataramanan  *
28409daf8208SAnirudh Venkataramanan  * Create switch rule with given filter information and add an entry
28419daf8208SAnirudh Venkataramanan  * to the corresponding filter management list to track this switch rule
28429daf8208SAnirudh Venkataramanan  * and VSI mapping
28439daf8208SAnirudh Venkataramanan  */
28445e24d598STony Nguyen static int
28459daf8208SAnirudh Venkataramanan ice_create_pkt_fwd_rule(struct ice_hw *hw,
28469daf8208SAnirudh Venkataramanan 			struct ice_fltr_list_entry *f_entry)
28479daf8208SAnirudh Venkataramanan {
28489daf8208SAnirudh Venkataramanan 	struct ice_fltr_mgmt_list_entry *fm_entry;
28496e1ff618SAlexander Lobakin 	struct ice_sw_rule_lkup_rx_tx *s_rule;
28509daf8208SAnirudh Venkataramanan 	enum ice_sw_lkup_type l_type;
285180d144c9SAnirudh Venkataramanan 	struct ice_sw_recipe *recp;
28525e24d598STony Nguyen 	int status;
28539daf8208SAnirudh Venkataramanan 
28549daf8208SAnirudh Venkataramanan 	s_rule = devm_kzalloc(ice_hw_to_dev(hw),
28556e1ff618SAlexander Lobakin 			      ICE_SW_RULE_RX_TX_ETH_HDR_SIZE(s_rule),
28566e1ff618SAlexander Lobakin 			      GFP_KERNEL);
28579daf8208SAnirudh Venkataramanan 	if (!s_rule)
2858d54699e2STony Nguyen 		return -ENOMEM;
28599daf8208SAnirudh Venkataramanan 	fm_entry = devm_kzalloc(ice_hw_to_dev(hw), sizeof(*fm_entry),
28609daf8208SAnirudh Venkataramanan 				GFP_KERNEL);
28619daf8208SAnirudh Venkataramanan 	if (!fm_entry) {
2862d54699e2STony Nguyen 		status = -ENOMEM;
28639daf8208SAnirudh Venkataramanan 		goto ice_create_pkt_fwd_rule_exit;
28649daf8208SAnirudh Venkataramanan 	}
28659daf8208SAnirudh Venkataramanan 
28669daf8208SAnirudh Venkataramanan 	fm_entry->fltr_info = f_entry->fltr_info;
28679daf8208SAnirudh Venkataramanan 
28689daf8208SAnirudh Venkataramanan 	/* Initialize all the fields for the management entry */
28699daf8208SAnirudh Venkataramanan 	fm_entry->vsi_count = 1;
28709daf8208SAnirudh Venkataramanan 	fm_entry->lg_act_idx = ICE_INVAL_LG_ACT_INDEX;
28719daf8208SAnirudh Venkataramanan 	fm_entry->sw_marker_id = ICE_INVAL_SW_MARKER_ID;
28729daf8208SAnirudh Venkataramanan 	fm_entry->counter_index = ICE_INVAL_COUNTER_ID;
28739daf8208SAnirudh Venkataramanan 
28749daf8208SAnirudh Venkataramanan 	ice_fill_sw_rule(hw, &fm_entry->fltr_info, s_rule,
28759daf8208SAnirudh Venkataramanan 			 ice_aqc_opc_add_sw_rules);
28769daf8208SAnirudh Venkataramanan 
28776e1ff618SAlexander Lobakin 	status = ice_aq_sw_rules(hw, s_rule,
28786e1ff618SAlexander Lobakin 				 ICE_SW_RULE_RX_TX_ETH_HDR_SIZE(s_rule), 1,
28799daf8208SAnirudh Venkataramanan 				 ice_aqc_opc_add_sw_rules, NULL);
28809daf8208SAnirudh Venkataramanan 	if (status) {
28819daf8208SAnirudh Venkataramanan 		devm_kfree(ice_hw_to_dev(hw), fm_entry);
28829daf8208SAnirudh Venkataramanan 		goto ice_create_pkt_fwd_rule_exit;
28839daf8208SAnirudh Venkataramanan 	}
28849daf8208SAnirudh Venkataramanan 
28856e1ff618SAlexander Lobakin 	f_entry->fltr_info.fltr_rule_id = le16_to_cpu(s_rule->index);
28866e1ff618SAlexander Lobakin 	fm_entry->fltr_info.fltr_rule_id = le16_to_cpu(s_rule->index);
28879daf8208SAnirudh Venkataramanan 
28889daf8208SAnirudh Venkataramanan 	/* The book keeping entries will get removed when base driver
28899daf8208SAnirudh Venkataramanan 	 * calls remove filter AQ command
28909daf8208SAnirudh Venkataramanan 	 */
28919daf8208SAnirudh Venkataramanan 	l_type = fm_entry->fltr_info.lkup_type;
289280d144c9SAnirudh Venkataramanan 	recp = &hw->switch_info->recp_list[l_type];
289380d144c9SAnirudh Venkataramanan 	list_add(&fm_entry->list_entry, &recp->filt_rules);
289480d144c9SAnirudh Venkataramanan 
28959daf8208SAnirudh Venkataramanan ice_create_pkt_fwd_rule_exit:
28969daf8208SAnirudh Venkataramanan 	devm_kfree(ice_hw_to_dev(hw), s_rule);
28979daf8208SAnirudh Venkataramanan 	return status;
28989daf8208SAnirudh Venkataramanan }
28999daf8208SAnirudh Venkataramanan 
29009daf8208SAnirudh Venkataramanan /**
29019daf8208SAnirudh Venkataramanan  * ice_update_pkt_fwd_rule
29029daf8208SAnirudh Venkataramanan  * @hw: pointer to the hardware structure
290380d144c9SAnirudh Venkataramanan  * @f_info: filter information for switch rule
29049daf8208SAnirudh Venkataramanan  *
29059daf8208SAnirudh Venkataramanan  * Call AQ command to update a previously created switch rule with a
2906f9867df6SAnirudh Venkataramanan  * VSI list ID
29079daf8208SAnirudh Venkataramanan  */
29085e24d598STony Nguyen static int
290980d144c9SAnirudh Venkataramanan ice_update_pkt_fwd_rule(struct ice_hw *hw, struct ice_fltr_info *f_info)
29109daf8208SAnirudh Venkataramanan {
29116e1ff618SAlexander Lobakin 	struct ice_sw_rule_lkup_rx_tx *s_rule;
29125e24d598STony Nguyen 	int status;
29139daf8208SAnirudh Venkataramanan 
29149daf8208SAnirudh Venkataramanan 	s_rule = devm_kzalloc(ice_hw_to_dev(hw),
29156e1ff618SAlexander Lobakin 			      ICE_SW_RULE_RX_TX_ETH_HDR_SIZE(s_rule),
29166e1ff618SAlexander Lobakin 			      GFP_KERNEL);
29179daf8208SAnirudh Venkataramanan 	if (!s_rule)
2918d54699e2STony Nguyen 		return -ENOMEM;
29199daf8208SAnirudh Venkataramanan 
292080d144c9SAnirudh Venkataramanan 	ice_fill_sw_rule(hw, f_info, s_rule, ice_aqc_opc_update_sw_rules);
29219daf8208SAnirudh Venkataramanan 
29226e1ff618SAlexander Lobakin 	s_rule->index = cpu_to_le16(f_info->fltr_rule_id);
29239daf8208SAnirudh Venkataramanan 
29249daf8208SAnirudh Venkataramanan 	/* Update switch rule with new rule set to forward VSI list */
29256e1ff618SAlexander Lobakin 	status = ice_aq_sw_rules(hw, s_rule,
29266e1ff618SAlexander Lobakin 				 ICE_SW_RULE_RX_TX_ETH_HDR_SIZE(s_rule), 1,
29279daf8208SAnirudh Venkataramanan 				 ice_aqc_opc_update_sw_rules, NULL);
29289daf8208SAnirudh Venkataramanan 
29299daf8208SAnirudh Venkataramanan 	devm_kfree(ice_hw_to_dev(hw), s_rule);
29309daf8208SAnirudh Venkataramanan 	return status;
29319daf8208SAnirudh Venkataramanan }
29329daf8208SAnirudh Venkataramanan 
29339daf8208SAnirudh Venkataramanan /**
2934b1edc14aSMd Fahad Iqbal Polash  * ice_update_sw_rule_bridge_mode
2935f9867df6SAnirudh Venkataramanan  * @hw: pointer to the HW struct
2936b1edc14aSMd Fahad Iqbal Polash  *
2937b1edc14aSMd Fahad Iqbal Polash  * Updates unicast switch filter rules based on VEB/VEPA mode
2938b1edc14aSMd Fahad Iqbal Polash  */
29395e24d598STony Nguyen int ice_update_sw_rule_bridge_mode(struct ice_hw *hw)
2940b1edc14aSMd Fahad Iqbal Polash {
2941b1edc14aSMd Fahad Iqbal Polash 	struct ice_switch_info *sw = hw->switch_info;
2942b1edc14aSMd Fahad Iqbal Polash 	struct ice_fltr_mgmt_list_entry *fm_entry;
2943b1edc14aSMd Fahad Iqbal Polash 	struct list_head *rule_head;
2944b1edc14aSMd Fahad Iqbal Polash 	struct mutex *rule_lock; /* Lock to protect filter rule list */
29455518ac2aSTony Nguyen 	int status = 0;
2946b1edc14aSMd Fahad Iqbal Polash 
2947b1edc14aSMd Fahad Iqbal Polash 	rule_lock = &sw->recp_list[ICE_SW_LKUP_MAC].filt_rule_lock;
2948b1edc14aSMd Fahad Iqbal Polash 	rule_head = &sw->recp_list[ICE_SW_LKUP_MAC].filt_rules;
2949b1edc14aSMd Fahad Iqbal Polash 
2950b1edc14aSMd Fahad Iqbal Polash 	mutex_lock(rule_lock);
2951b1edc14aSMd Fahad Iqbal Polash 	list_for_each_entry(fm_entry, rule_head, list_entry) {
2952b1edc14aSMd Fahad Iqbal Polash 		struct ice_fltr_info *fi = &fm_entry->fltr_info;
2953b1edc14aSMd Fahad Iqbal Polash 		u8 *addr = fi->l_data.mac.mac_addr;
2954b1edc14aSMd Fahad Iqbal Polash 
2955b1edc14aSMd Fahad Iqbal Polash 		/* Update unicast Tx rules to reflect the selected
2956b1edc14aSMd Fahad Iqbal Polash 		 * VEB/VEPA mode
2957b1edc14aSMd Fahad Iqbal Polash 		 */
2958b1edc14aSMd Fahad Iqbal Polash 		if ((fi->flag & ICE_FLTR_TX) && is_unicast_ether_addr(addr) &&
2959b1edc14aSMd Fahad Iqbal Polash 		    (fi->fltr_act == ICE_FWD_TO_VSI ||
2960b1edc14aSMd Fahad Iqbal Polash 		     fi->fltr_act == ICE_FWD_TO_VSI_LIST ||
2961b1edc14aSMd Fahad Iqbal Polash 		     fi->fltr_act == ICE_FWD_TO_Q ||
2962b1edc14aSMd Fahad Iqbal Polash 		     fi->fltr_act == ICE_FWD_TO_QGRP)) {
2963b1edc14aSMd Fahad Iqbal Polash 			status = ice_update_pkt_fwd_rule(hw, fi);
2964b1edc14aSMd Fahad Iqbal Polash 			if (status)
2965b1edc14aSMd Fahad Iqbal Polash 				break;
2966b1edc14aSMd Fahad Iqbal Polash 		}
2967b1edc14aSMd Fahad Iqbal Polash 	}
2968b1edc14aSMd Fahad Iqbal Polash 
2969b1edc14aSMd Fahad Iqbal Polash 	mutex_unlock(rule_lock);
2970b1edc14aSMd Fahad Iqbal Polash 
2971b1edc14aSMd Fahad Iqbal Polash 	return status;
2972b1edc14aSMd Fahad Iqbal Polash }
2973b1edc14aSMd Fahad Iqbal Polash 
2974b1edc14aSMd Fahad Iqbal Polash /**
297580d144c9SAnirudh Venkataramanan  * ice_add_update_vsi_list
29769daf8208SAnirudh Venkataramanan  * @hw: pointer to the hardware structure
29779daf8208SAnirudh Venkataramanan  * @m_entry: pointer to current filter management list entry
29789daf8208SAnirudh Venkataramanan  * @cur_fltr: filter information from the book keeping entry
29799daf8208SAnirudh Venkataramanan  * @new_fltr: filter information with the new VSI to be added
29809daf8208SAnirudh Venkataramanan  *
29819daf8208SAnirudh Venkataramanan  * Call AQ command to add or update previously created VSI list with new VSI.
29829daf8208SAnirudh Venkataramanan  *
29839daf8208SAnirudh Venkataramanan  * Helper function to do book keeping associated with adding filter information
2984d337f2afSAnirudh Venkataramanan  * The algorithm to do the book keeping is described below :
29859daf8208SAnirudh Venkataramanan  * When a VSI needs to subscribe to a given filter (MAC/VLAN/Ethtype etc.)
29869daf8208SAnirudh Venkataramanan  *	if only one VSI has been added till now
29879daf8208SAnirudh Venkataramanan  *		Allocate a new VSI list and add two VSIs
29889daf8208SAnirudh Venkataramanan  *		to this list using switch rule command
29899daf8208SAnirudh Venkataramanan  *		Update the previously created switch rule with the
2990f9867df6SAnirudh Venkataramanan  *		newly created VSI list ID
29919daf8208SAnirudh Venkataramanan  *	if a VSI list was previously created
29929daf8208SAnirudh Venkataramanan  *		Add the new VSI to the previously created VSI list set
29939daf8208SAnirudh Venkataramanan  *		using the update switch rule command
29949daf8208SAnirudh Venkataramanan  */
29955e24d598STony Nguyen static int
299680d144c9SAnirudh Venkataramanan ice_add_update_vsi_list(struct ice_hw *hw,
29979daf8208SAnirudh Venkataramanan 			struct ice_fltr_mgmt_list_entry *m_entry,
29989daf8208SAnirudh Venkataramanan 			struct ice_fltr_info *cur_fltr,
29999daf8208SAnirudh Venkataramanan 			struct ice_fltr_info *new_fltr)
30009daf8208SAnirudh Venkataramanan {
30019daf8208SAnirudh Venkataramanan 	u16 vsi_list_id = 0;
30025518ac2aSTony Nguyen 	int status = 0;
30039daf8208SAnirudh Venkataramanan 
30049daf8208SAnirudh Venkataramanan 	if ((cur_fltr->fltr_act == ICE_FWD_TO_Q ||
30059daf8208SAnirudh Venkataramanan 	     cur_fltr->fltr_act == ICE_FWD_TO_QGRP))
3006d54699e2STony Nguyen 		return -EOPNOTSUPP;
30079daf8208SAnirudh Venkataramanan 
30089daf8208SAnirudh Venkataramanan 	if ((new_fltr->fltr_act == ICE_FWD_TO_Q ||
30099daf8208SAnirudh Venkataramanan 	     new_fltr->fltr_act == ICE_FWD_TO_QGRP) &&
30109daf8208SAnirudh Venkataramanan 	    (cur_fltr->fltr_act == ICE_FWD_TO_VSI ||
30119daf8208SAnirudh Venkataramanan 	     cur_fltr->fltr_act == ICE_FWD_TO_VSI_LIST))
3012d54699e2STony Nguyen 		return -EOPNOTSUPP;
30139daf8208SAnirudh Venkataramanan 
30149daf8208SAnirudh Venkataramanan 	if (m_entry->vsi_count < 2 && !m_entry->vsi_list_info) {
30159daf8208SAnirudh Venkataramanan 		/* Only one entry existed in the mapping and it was not already
30169daf8208SAnirudh Venkataramanan 		 * a part of a VSI list. So, create a VSI list with the old and
30179daf8208SAnirudh Venkataramanan 		 * new VSIs.
30189daf8208SAnirudh Venkataramanan 		 */
301980d144c9SAnirudh Venkataramanan 		struct ice_fltr_info tmp_fltr;
30205726ca0eSAnirudh Venkataramanan 		u16 vsi_handle_arr[2];
30219daf8208SAnirudh Venkataramanan 
30229daf8208SAnirudh Venkataramanan 		/* A rule already exists with the new VSI being added */
30235726ca0eSAnirudh Venkataramanan 		if (cur_fltr->fwd_id.hw_vsi_id == new_fltr->fwd_id.hw_vsi_id)
3024d54699e2STony Nguyen 			return -EEXIST;
30259daf8208SAnirudh Venkataramanan 
30265726ca0eSAnirudh Venkataramanan 		vsi_handle_arr[0] = cur_fltr->vsi_handle;
30275726ca0eSAnirudh Venkataramanan 		vsi_handle_arr[1] = new_fltr->vsi_handle;
30285726ca0eSAnirudh Venkataramanan 		status = ice_create_vsi_list_rule(hw, &vsi_handle_arr[0], 2,
30299daf8208SAnirudh Venkataramanan 						  &vsi_list_id,
30309daf8208SAnirudh Venkataramanan 						  new_fltr->lkup_type);
30319daf8208SAnirudh Venkataramanan 		if (status)
30329daf8208SAnirudh Venkataramanan 			return status;
30339daf8208SAnirudh Venkataramanan 
303480d144c9SAnirudh Venkataramanan 		tmp_fltr = *new_fltr;
303580d144c9SAnirudh Venkataramanan 		tmp_fltr.fltr_rule_id = cur_fltr->fltr_rule_id;
303680d144c9SAnirudh Venkataramanan 		tmp_fltr.fltr_act = ICE_FWD_TO_VSI_LIST;
303780d144c9SAnirudh Venkataramanan 		tmp_fltr.fwd_id.vsi_list_id = vsi_list_id;
30389daf8208SAnirudh Venkataramanan 		/* Update the previous switch rule of "MAC forward to VSI" to
30399daf8208SAnirudh Venkataramanan 		 * "MAC fwd to VSI list"
30409daf8208SAnirudh Venkataramanan 		 */
304180d144c9SAnirudh Venkataramanan 		status = ice_update_pkt_fwd_rule(hw, &tmp_fltr);
30429daf8208SAnirudh Venkataramanan 		if (status)
30439daf8208SAnirudh Venkataramanan 			return status;
30449daf8208SAnirudh Venkataramanan 
30459daf8208SAnirudh Venkataramanan 		cur_fltr->fwd_id.vsi_list_id = vsi_list_id;
30469daf8208SAnirudh Venkataramanan 		cur_fltr->fltr_act = ICE_FWD_TO_VSI_LIST;
30479daf8208SAnirudh Venkataramanan 		m_entry->vsi_list_info =
30485726ca0eSAnirudh Venkataramanan 			ice_create_vsi_list_map(hw, &vsi_handle_arr[0], 2,
30499daf8208SAnirudh Venkataramanan 						vsi_list_id);
30509daf8208SAnirudh Venkataramanan 
30517a91d3f0SJacek Bułatek 		if (!m_entry->vsi_list_info)
3052d54699e2STony Nguyen 			return -ENOMEM;
30537a91d3f0SJacek Bułatek 
30549daf8208SAnirudh Venkataramanan 		/* If this entry was large action then the large action needs
30559daf8208SAnirudh Venkataramanan 		 * to be updated to point to FWD to VSI list
30569daf8208SAnirudh Venkataramanan 		 */
30579daf8208SAnirudh Venkataramanan 		if (m_entry->sw_marker_id != ICE_INVAL_SW_MARKER_ID)
30589daf8208SAnirudh Venkataramanan 			status =
30599daf8208SAnirudh Venkataramanan 			    ice_add_marker_act(hw, m_entry,
30609daf8208SAnirudh Venkataramanan 					       m_entry->sw_marker_id,
30619daf8208SAnirudh Venkataramanan 					       m_entry->lg_act_idx);
30629daf8208SAnirudh Venkataramanan 	} else {
30635726ca0eSAnirudh Venkataramanan 		u16 vsi_handle = new_fltr->vsi_handle;
30649daf8208SAnirudh Venkataramanan 		enum ice_adminq_opc opcode;
30659daf8208SAnirudh Venkataramanan 
3066f25dad19SBruce Allan 		if (!m_entry->vsi_list_info)
3067d54699e2STony Nguyen 			return -EIO;
3068f25dad19SBruce Allan 
30699daf8208SAnirudh Venkataramanan 		/* A rule already exists with the new VSI being added */
30705726ca0eSAnirudh Venkataramanan 		if (test_bit(vsi_handle, m_entry->vsi_list_info->vsi_map))
30719daf8208SAnirudh Venkataramanan 			return 0;
30729daf8208SAnirudh Venkataramanan 
30739daf8208SAnirudh Venkataramanan 		/* Update the previously created VSI list set with
3074f9867df6SAnirudh Venkataramanan 		 * the new VSI ID passed in
30759daf8208SAnirudh Venkataramanan 		 */
30769daf8208SAnirudh Venkataramanan 		vsi_list_id = cur_fltr->fwd_id.vsi_list_id;
30779daf8208SAnirudh Venkataramanan 		opcode = ice_aqc_opc_update_sw_rules;
30789daf8208SAnirudh Venkataramanan 
30795726ca0eSAnirudh Venkataramanan 		status = ice_update_vsi_list_rule(hw, &vsi_handle, 1,
30805726ca0eSAnirudh Venkataramanan 						  vsi_list_id, false, opcode,
30819daf8208SAnirudh Venkataramanan 						  new_fltr->lkup_type);
3082f9867df6SAnirudh Venkataramanan 		/* update VSI list mapping info with new VSI ID */
30839daf8208SAnirudh Venkataramanan 		if (!status)
30845726ca0eSAnirudh Venkataramanan 			set_bit(vsi_handle, m_entry->vsi_list_info->vsi_map);
30859daf8208SAnirudh Venkataramanan 	}
30869daf8208SAnirudh Venkataramanan 	if (!status)
30879daf8208SAnirudh Venkataramanan 		m_entry->vsi_count++;
30889daf8208SAnirudh Venkataramanan 	return status;
30899daf8208SAnirudh Venkataramanan }
30909daf8208SAnirudh Venkataramanan 
30919daf8208SAnirudh Venkataramanan /**
309280d144c9SAnirudh Venkataramanan  * ice_find_rule_entry - Search a rule entry
30939daf8208SAnirudh Venkataramanan  * @hw: pointer to the hardware structure
309480d144c9SAnirudh Venkataramanan  * @recp_id: lookup type for which the specified rule needs to be searched
309580d144c9SAnirudh Venkataramanan  * @f_info: rule information
30969daf8208SAnirudh Venkataramanan  *
309780d144c9SAnirudh Venkataramanan  * Helper function to search for a given rule entry
309880d144c9SAnirudh Venkataramanan  * Returns pointer to entry storing the rule if found
30999daf8208SAnirudh Venkataramanan  */
31009daf8208SAnirudh Venkataramanan static struct ice_fltr_mgmt_list_entry *
310180d144c9SAnirudh Venkataramanan ice_find_rule_entry(struct ice_hw *hw, u8 recp_id, struct ice_fltr_info *f_info)
31029daf8208SAnirudh Venkataramanan {
310380d144c9SAnirudh Venkataramanan 	struct ice_fltr_mgmt_list_entry *list_itr, *ret = NULL;
31049daf8208SAnirudh Venkataramanan 	struct ice_switch_info *sw = hw->switch_info;
310580d144c9SAnirudh Venkataramanan 	struct list_head *list_head;
31069daf8208SAnirudh Venkataramanan 
310780d144c9SAnirudh Venkataramanan 	list_head = &sw->recp_list[recp_id].filt_rules;
310880d144c9SAnirudh Venkataramanan 	list_for_each_entry(list_itr, list_head, list_entry) {
310980d144c9SAnirudh Venkataramanan 		if (!memcmp(&f_info->l_data, &list_itr->fltr_info.l_data,
311080d144c9SAnirudh Venkataramanan 			    sizeof(f_info->l_data)) &&
311180d144c9SAnirudh Venkataramanan 		    f_info->flag == list_itr->fltr_info.flag) {
311280d144c9SAnirudh Venkataramanan 			ret = list_itr;
31139daf8208SAnirudh Venkataramanan 			break;
31149daf8208SAnirudh Venkataramanan 		}
31159daf8208SAnirudh Venkataramanan 	}
311680d144c9SAnirudh Venkataramanan 	return ret;
31179daf8208SAnirudh Venkataramanan }
31189daf8208SAnirudh Venkataramanan 
31199daf8208SAnirudh Venkataramanan /**
31205726ca0eSAnirudh Venkataramanan  * ice_find_vsi_list_entry - Search VSI list map with VSI count 1
31215726ca0eSAnirudh Venkataramanan  * @hw: pointer to the hardware structure
31225726ca0eSAnirudh Venkataramanan  * @recp_id: lookup type for which VSI lists needs to be searched
31235726ca0eSAnirudh Venkataramanan  * @vsi_handle: VSI handle to be found in VSI list
3124f9867df6SAnirudh Venkataramanan  * @vsi_list_id: VSI list ID found containing vsi_handle
31255726ca0eSAnirudh Venkataramanan  *
31265726ca0eSAnirudh Venkataramanan  * Helper function to search a VSI list with single entry containing given VSI
31275726ca0eSAnirudh Venkataramanan  * handle element. This can be extended further to search VSI list with more
31285726ca0eSAnirudh Venkataramanan  * than 1 vsi_count. Returns pointer to VSI list entry if found.
31295726ca0eSAnirudh Venkataramanan  */
313023ccae5cSDave Ertman struct ice_vsi_list_map_info *
31315726ca0eSAnirudh Venkataramanan ice_find_vsi_list_entry(struct ice_hw *hw, u8 recp_id, u16 vsi_handle,
31325726ca0eSAnirudh Venkataramanan 			u16 *vsi_list_id)
31335726ca0eSAnirudh Venkataramanan {
31345726ca0eSAnirudh Venkataramanan 	struct ice_vsi_list_map_info *map_info = NULL;
31355726ca0eSAnirudh Venkataramanan 	struct ice_switch_info *sw = hw->switch_info;
31365726ca0eSAnirudh Venkataramanan 	struct ice_fltr_mgmt_list_entry *list_itr;
31375726ca0eSAnirudh Venkataramanan 	struct list_head *list_head;
31385726ca0eSAnirudh Venkataramanan 
31395726ca0eSAnirudh Venkataramanan 	list_head = &sw->recp_list[recp_id].filt_rules;
31405726ca0eSAnirudh Venkataramanan 	list_for_each_entry(list_itr, list_head, list_entry) {
314123ccae5cSDave Ertman 		if (list_itr->vsi_list_info) {
31425726ca0eSAnirudh Venkataramanan 			map_info = list_itr->vsi_list_info;
31435726ca0eSAnirudh Venkataramanan 			if (test_bit(vsi_handle, map_info->vsi_map)) {
31445726ca0eSAnirudh Venkataramanan 				*vsi_list_id = map_info->vsi_list_id;
31455726ca0eSAnirudh Venkataramanan 				return map_info;
31465726ca0eSAnirudh Venkataramanan 			}
31475726ca0eSAnirudh Venkataramanan 		}
31485726ca0eSAnirudh Venkataramanan 	}
31495726ca0eSAnirudh Venkataramanan 	return NULL;
31505726ca0eSAnirudh Venkataramanan }
31515726ca0eSAnirudh Venkataramanan 
31525726ca0eSAnirudh Venkataramanan /**
315380d144c9SAnirudh Venkataramanan  * ice_add_rule_internal - add rule for a given lookup type
31549daf8208SAnirudh Venkataramanan  * @hw: pointer to the hardware structure
3155f9867df6SAnirudh Venkataramanan  * @recp_id: lookup type (recipe ID) for which rule has to be added
31569daf8208SAnirudh Venkataramanan  * @f_entry: structure containing MAC forwarding information
31579daf8208SAnirudh Venkataramanan  *
315880d144c9SAnirudh Venkataramanan  * Adds or updates the rule lists for a given recipe
31599daf8208SAnirudh Venkataramanan  */
31605e24d598STony Nguyen static int
316180d144c9SAnirudh Venkataramanan ice_add_rule_internal(struct ice_hw *hw, u8 recp_id,
316280d144c9SAnirudh Venkataramanan 		      struct ice_fltr_list_entry *f_entry)
31639daf8208SAnirudh Venkataramanan {
316480d144c9SAnirudh Venkataramanan 	struct ice_switch_info *sw = hw->switch_info;
31659daf8208SAnirudh Venkataramanan 	struct ice_fltr_info *new_fltr, *cur_fltr;
31669daf8208SAnirudh Venkataramanan 	struct ice_fltr_mgmt_list_entry *m_entry;
316780d144c9SAnirudh Venkataramanan 	struct mutex *rule_lock; /* Lock to protect filter rule list */
31685e24d598STony Nguyen 	int status = 0;
31699daf8208SAnirudh Venkataramanan 
31705726ca0eSAnirudh Venkataramanan 	if (!ice_is_vsi_valid(hw, f_entry->fltr_info.vsi_handle))
3171d54699e2STony Nguyen 		return -EINVAL;
31725726ca0eSAnirudh Venkataramanan 	f_entry->fltr_info.fwd_id.hw_vsi_id =
31735726ca0eSAnirudh Venkataramanan 		ice_get_hw_vsi_num(hw, f_entry->fltr_info.vsi_handle);
31745726ca0eSAnirudh Venkataramanan 
317580d144c9SAnirudh Venkataramanan 	rule_lock = &sw->recp_list[recp_id].filt_rule_lock;
317680d144c9SAnirudh Venkataramanan 
317780d144c9SAnirudh Venkataramanan 	mutex_lock(rule_lock);
31789daf8208SAnirudh Venkataramanan 	new_fltr = &f_entry->fltr_info;
317980d144c9SAnirudh Venkataramanan 	if (new_fltr->flag & ICE_FLTR_RX)
318080d144c9SAnirudh Venkataramanan 		new_fltr->src = hw->port_info->lport;
318180d144c9SAnirudh Venkataramanan 	else if (new_fltr->flag & ICE_FLTR_TX)
31825726ca0eSAnirudh Venkataramanan 		new_fltr->src = f_entry->fltr_info.fwd_id.hw_vsi_id;
31839daf8208SAnirudh Venkataramanan 
318480d144c9SAnirudh Venkataramanan 	m_entry = ice_find_rule_entry(hw, recp_id, new_fltr);
318580d144c9SAnirudh Venkataramanan 	if (!m_entry) {
318680d144c9SAnirudh Venkataramanan 		mutex_unlock(rule_lock);
31879daf8208SAnirudh Venkataramanan 		return ice_create_pkt_fwd_rule(hw, f_entry);
318880d144c9SAnirudh Venkataramanan 	}
31899daf8208SAnirudh Venkataramanan 
31909daf8208SAnirudh Venkataramanan 	cur_fltr = &m_entry->fltr_info;
319180d144c9SAnirudh Venkataramanan 	status = ice_add_update_vsi_list(hw, m_entry, cur_fltr, new_fltr);
319280d144c9SAnirudh Venkataramanan 	mutex_unlock(rule_lock);
31939daf8208SAnirudh Venkataramanan 
319480d144c9SAnirudh Venkataramanan 	return status;
319580d144c9SAnirudh Venkataramanan }
319680d144c9SAnirudh Venkataramanan 
319780d144c9SAnirudh Venkataramanan /**
319880d144c9SAnirudh Venkataramanan  * ice_remove_vsi_list_rule
319980d144c9SAnirudh Venkataramanan  * @hw: pointer to the hardware structure
3200f9867df6SAnirudh Venkataramanan  * @vsi_list_id: VSI list ID generated as part of allocate resource
320180d144c9SAnirudh Venkataramanan  * @lkup_type: switch rule filter lookup type
320280d144c9SAnirudh Venkataramanan  *
320380d144c9SAnirudh Venkataramanan  * The VSI list should be emptied before this function is called to remove the
320480d144c9SAnirudh Venkataramanan  * VSI list.
320580d144c9SAnirudh Venkataramanan  */
32065e24d598STony Nguyen static int
320780d144c9SAnirudh Venkataramanan ice_remove_vsi_list_rule(struct ice_hw *hw, u16 vsi_list_id,
320880d144c9SAnirudh Venkataramanan 			 enum ice_sw_lkup_type lkup_type)
320980d144c9SAnirudh Venkataramanan {
32106e1ff618SAlexander Lobakin 	struct ice_sw_rule_vsi_list *s_rule;
321180d144c9SAnirudh Venkataramanan 	u16 s_rule_size;
32125518ac2aSTony Nguyen 	int status;
321380d144c9SAnirudh Venkataramanan 
32146e1ff618SAlexander Lobakin 	s_rule_size = (u16)ICE_SW_RULE_VSI_LIST_SIZE(s_rule, 0);
321580d144c9SAnirudh Venkataramanan 	s_rule = devm_kzalloc(ice_hw_to_dev(hw), s_rule_size, GFP_KERNEL);
321680d144c9SAnirudh Venkataramanan 	if (!s_rule)
3217d54699e2STony Nguyen 		return -ENOMEM;
321880d144c9SAnirudh Venkataramanan 
32196e1ff618SAlexander Lobakin 	s_rule->hdr.type = cpu_to_le16(ICE_AQC_SW_RULES_T_VSI_LIST_CLEAR);
32206e1ff618SAlexander Lobakin 	s_rule->index = cpu_to_le16(vsi_list_id);
322180d144c9SAnirudh Venkataramanan 
322280d144c9SAnirudh Venkataramanan 	/* Free the vsi_list resource that we allocated. It is assumed that the
322380d144c9SAnirudh Venkataramanan 	 * list is empty at this point.
322480d144c9SAnirudh Venkataramanan 	 */
322580d144c9SAnirudh Venkataramanan 	status = ice_aq_alloc_free_vsi_list(hw, &vsi_list_id, lkup_type,
322680d144c9SAnirudh Venkataramanan 					    ice_aqc_opc_free_res);
322780d144c9SAnirudh Venkataramanan 
322880d144c9SAnirudh Venkataramanan 	devm_kfree(ice_hw_to_dev(hw), s_rule);
322980d144c9SAnirudh Venkataramanan 	return status;
323080d144c9SAnirudh Venkataramanan }
323180d144c9SAnirudh Venkataramanan 
323280d144c9SAnirudh Venkataramanan /**
323380d144c9SAnirudh Venkataramanan  * ice_rem_update_vsi_list
323480d144c9SAnirudh Venkataramanan  * @hw: pointer to the hardware structure
32355726ca0eSAnirudh Venkataramanan  * @vsi_handle: VSI handle of the VSI to remove
323680d144c9SAnirudh Venkataramanan  * @fm_list: filter management entry for which the VSI list management needs to
323780d144c9SAnirudh Venkataramanan  *           be done
323880d144c9SAnirudh Venkataramanan  */
32395e24d598STony Nguyen static int
32405726ca0eSAnirudh Venkataramanan ice_rem_update_vsi_list(struct ice_hw *hw, u16 vsi_handle,
324180d144c9SAnirudh Venkataramanan 			struct ice_fltr_mgmt_list_entry *fm_list)
324280d144c9SAnirudh Venkataramanan {
324380d144c9SAnirudh Venkataramanan 	enum ice_sw_lkup_type lkup_type;
324480d144c9SAnirudh Venkataramanan 	u16 vsi_list_id;
32455518ac2aSTony Nguyen 	int status = 0;
324680d144c9SAnirudh Venkataramanan 
324780d144c9SAnirudh Venkataramanan 	if (fm_list->fltr_info.fltr_act != ICE_FWD_TO_VSI_LIST ||
324880d144c9SAnirudh Venkataramanan 	    fm_list->vsi_count == 0)
3249d54699e2STony Nguyen 		return -EINVAL;
325080d144c9SAnirudh Venkataramanan 
325180d144c9SAnirudh Venkataramanan 	/* A rule with the VSI being removed does not exist */
32525726ca0eSAnirudh Venkataramanan 	if (!test_bit(vsi_handle, fm_list->vsi_list_info->vsi_map))
3253d54699e2STony Nguyen 		return -ENOENT;
325480d144c9SAnirudh Venkataramanan 
325580d144c9SAnirudh Venkataramanan 	lkup_type = fm_list->fltr_info.lkup_type;
325680d144c9SAnirudh Venkataramanan 	vsi_list_id = fm_list->fltr_info.fwd_id.vsi_list_id;
32575726ca0eSAnirudh Venkataramanan 	status = ice_update_vsi_list_rule(hw, &vsi_handle, 1, vsi_list_id, true,
325880d144c9SAnirudh Venkataramanan 					  ice_aqc_opc_update_sw_rules,
325980d144c9SAnirudh Venkataramanan 					  lkup_type);
326080d144c9SAnirudh Venkataramanan 	if (status)
326180d144c9SAnirudh Venkataramanan 		return status;
326280d144c9SAnirudh Venkataramanan 
326380d144c9SAnirudh Venkataramanan 	fm_list->vsi_count--;
32645726ca0eSAnirudh Venkataramanan 	clear_bit(vsi_handle, fm_list->vsi_list_info->vsi_map);
326580d144c9SAnirudh Venkataramanan 
3266c60cdb13SBrett Creeley 	if (fm_list->vsi_count == 1 && lkup_type != ICE_SW_LKUP_VLAN) {
3267c60cdb13SBrett Creeley 		struct ice_fltr_info tmp_fltr_info = fm_list->fltr_info;
326880d144c9SAnirudh Venkataramanan 		struct ice_vsi_list_map_info *vsi_list_info =
326980d144c9SAnirudh Venkataramanan 			fm_list->vsi_list_info;
32705726ca0eSAnirudh Venkataramanan 		u16 rem_vsi_handle;
327180d144c9SAnirudh Venkataramanan 
32725726ca0eSAnirudh Venkataramanan 		rem_vsi_handle = find_first_bit(vsi_list_info->vsi_map,
327380d144c9SAnirudh Venkataramanan 						ICE_MAX_VSI);
32745726ca0eSAnirudh Venkataramanan 		if (!ice_is_vsi_valid(hw, rem_vsi_handle))
3275d54699e2STony Nguyen 			return -EIO;
3276c60cdb13SBrett Creeley 
3277c60cdb13SBrett Creeley 		/* Make sure VSI list is empty before removing it below */
32785726ca0eSAnirudh Venkataramanan 		status = ice_update_vsi_list_rule(hw, &rem_vsi_handle, 1,
327980d144c9SAnirudh Venkataramanan 						  vsi_list_id, true,
328080d144c9SAnirudh Venkataramanan 						  ice_aqc_opc_update_sw_rules,
328180d144c9SAnirudh Venkataramanan 						  lkup_type);
328280d144c9SAnirudh Venkataramanan 		if (status)
328380d144c9SAnirudh Venkataramanan 			return status;
328480d144c9SAnirudh Venkataramanan 
3285c60cdb13SBrett Creeley 		tmp_fltr_info.fltr_act = ICE_FWD_TO_VSI;
3286c60cdb13SBrett Creeley 		tmp_fltr_info.fwd_id.hw_vsi_id =
3287c60cdb13SBrett Creeley 			ice_get_hw_vsi_num(hw, rem_vsi_handle);
3288c60cdb13SBrett Creeley 		tmp_fltr_info.vsi_handle = rem_vsi_handle;
3289c60cdb13SBrett Creeley 		status = ice_update_pkt_fwd_rule(hw, &tmp_fltr_info);
3290c60cdb13SBrett Creeley 		if (status) {
32919228d8b2SJacob Keller 			ice_debug(hw, ICE_DBG_SW, "Failed to update pkt fwd rule to FWD_TO_VSI on HW VSI %d, error %d\n",
3292c60cdb13SBrett Creeley 				  tmp_fltr_info.fwd_id.hw_vsi_id, status);
3293c60cdb13SBrett Creeley 			return status;
3294c60cdb13SBrett Creeley 		}
3295c60cdb13SBrett Creeley 
3296c60cdb13SBrett Creeley 		fm_list->fltr_info = tmp_fltr_info;
3297c60cdb13SBrett Creeley 	}
3298c60cdb13SBrett Creeley 
3299c60cdb13SBrett Creeley 	if ((fm_list->vsi_count == 1 && lkup_type != ICE_SW_LKUP_VLAN) ||
3300c60cdb13SBrett Creeley 	    (fm_list->vsi_count == 0 && lkup_type == ICE_SW_LKUP_VLAN)) {
3301c60cdb13SBrett Creeley 		struct ice_vsi_list_map_info *vsi_list_info =
3302c60cdb13SBrett Creeley 			fm_list->vsi_list_info;
3303c60cdb13SBrett Creeley 
330480d144c9SAnirudh Venkataramanan 		/* Remove the VSI list since it is no longer used */
330580d144c9SAnirudh Venkataramanan 		status = ice_remove_vsi_list_rule(hw, vsi_list_id, lkup_type);
3306c60cdb13SBrett Creeley 		if (status) {
33079228d8b2SJacob Keller 			ice_debug(hw, ICE_DBG_SW, "Failed to remove VSI list %d, error %d\n",
3308c60cdb13SBrett Creeley 				  vsi_list_id, status);
330980d144c9SAnirudh Venkataramanan 			return status;
3310c60cdb13SBrett Creeley 		}
331180d144c9SAnirudh Venkataramanan 
331280d144c9SAnirudh Venkataramanan 		list_del(&vsi_list_info->list_entry);
331380d144c9SAnirudh Venkataramanan 		devm_kfree(ice_hw_to_dev(hw), vsi_list_info);
331480d144c9SAnirudh Venkataramanan 		fm_list->vsi_list_info = NULL;
331580d144c9SAnirudh Venkataramanan 	}
331680d144c9SAnirudh Venkataramanan 
331780d144c9SAnirudh Venkataramanan 	return status;
331880d144c9SAnirudh Venkataramanan }
331980d144c9SAnirudh Venkataramanan 
332080d144c9SAnirudh Venkataramanan /**
332180d144c9SAnirudh Venkataramanan  * ice_remove_rule_internal - Remove a filter rule of a given type
332280d144c9SAnirudh Venkataramanan  * @hw: pointer to the hardware structure
3323f9867df6SAnirudh Venkataramanan  * @recp_id: recipe ID for which the rule needs to removed
332480d144c9SAnirudh Venkataramanan  * @f_entry: rule entry containing filter information
332580d144c9SAnirudh Venkataramanan  */
33265e24d598STony Nguyen static int
332780d144c9SAnirudh Venkataramanan ice_remove_rule_internal(struct ice_hw *hw, u8 recp_id,
332880d144c9SAnirudh Venkataramanan 			 struct ice_fltr_list_entry *f_entry)
332980d144c9SAnirudh Venkataramanan {
333080d144c9SAnirudh Venkataramanan 	struct ice_switch_info *sw = hw->switch_info;
333180d144c9SAnirudh Venkataramanan 	struct ice_fltr_mgmt_list_entry *list_elem;
333280d144c9SAnirudh Venkataramanan 	struct mutex *rule_lock; /* Lock to protect filter rule list */
333380d144c9SAnirudh Venkataramanan 	bool remove_rule = false;
33345726ca0eSAnirudh Venkataramanan 	u16 vsi_handle;
33355518ac2aSTony Nguyen 	int status = 0;
33365726ca0eSAnirudh Venkataramanan 
33375726ca0eSAnirudh Venkataramanan 	if (!ice_is_vsi_valid(hw, f_entry->fltr_info.vsi_handle))
3338d54699e2STony Nguyen 		return -EINVAL;
33395726ca0eSAnirudh Venkataramanan 	f_entry->fltr_info.fwd_id.hw_vsi_id =
33405726ca0eSAnirudh Venkataramanan 		ice_get_hw_vsi_num(hw, f_entry->fltr_info.vsi_handle);
334180d144c9SAnirudh Venkataramanan 
334280d144c9SAnirudh Venkataramanan 	rule_lock = &sw->recp_list[recp_id].filt_rule_lock;
334380d144c9SAnirudh Venkataramanan 	mutex_lock(rule_lock);
334480d144c9SAnirudh Venkataramanan 	list_elem = ice_find_rule_entry(hw, recp_id, &f_entry->fltr_info);
334580d144c9SAnirudh Venkataramanan 	if (!list_elem) {
3346d54699e2STony Nguyen 		status = -ENOENT;
334780d144c9SAnirudh Venkataramanan 		goto exit;
334880d144c9SAnirudh Venkataramanan 	}
334980d144c9SAnirudh Venkataramanan 
335080d144c9SAnirudh Venkataramanan 	if (list_elem->fltr_info.fltr_act != ICE_FWD_TO_VSI_LIST) {
335180d144c9SAnirudh Venkataramanan 		remove_rule = true;
33525726ca0eSAnirudh Venkataramanan 	} else if (!list_elem->vsi_list_info) {
3353d54699e2STony Nguyen 		status = -ENOENT;
33545726ca0eSAnirudh Venkataramanan 		goto exit;
3355f9264dd6SJacob Keller 	} else if (list_elem->vsi_list_info->ref_cnt > 1) {
3356f9264dd6SJacob Keller 		/* a ref_cnt > 1 indicates that the vsi_list is being
3357f9264dd6SJacob Keller 		 * shared by multiple rules. Decrement the ref_cnt and
3358f9264dd6SJacob Keller 		 * remove this rule, but do not modify the list, as it
3359f9264dd6SJacob Keller 		 * is in-use by other rules.
3360f9264dd6SJacob Keller 		 */
33615726ca0eSAnirudh Venkataramanan 		list_elem->vsi_list_info->ref_cnt--;
3362f9264dd6SJacob Keller 		remove_rule = true;
3363f9264dd6SJacob Keller 	} else {
3364f9264dd6SJacob Keller 		/* a ref_cnt of 1 indicates the vsi_list is only used
3365f9264dd6SJacob Keller 		 * by one rule. However, the original removal request is only
3366f9264dd6SJacob Keller 		 * for a single VSI. Update the vsi_list first, and only
3367f9264dd6SJacob Keller 		 * remove the rule if there are no further VSIs in this list.
3368f9264dd6SJacob Keller 		 */
33695726ca0eSAnirudh Venkataramanan 		vsi_handle = f_entry->fltr_info.vsi_handle;
33705726ca0eSAnirudh Venkataramanan 		status = ice_rem_update_vsi_list(hw, vsi_handle, list_elem);
337180d144c9SAnirudh Venkataramanan 		if (status)
337280d144c9SAnirudh Venkataramanan 			goto exit;
3373f9867df6SAnirudh Venkataramanan 		/* if VSI count goes to zero after updating the VSI list */
337480d144c9SAnirudh Venkataramanan 		if (list_elem->vsi_count == 0)
337580d144c9SAnirudh Venkataramanan 			remove_rule = true;
337680d144c9SAnirudh Venkataramanan 	}
337780d144c9SAnirudh Venkataramanan 
337880d144c9SAnirudh Venkataramanan 	if (remove_rule) {
337980d144c9SAnirudh Venkataramanan 		/* Remove the lookup rule */
33806e1ff618SAlexander Lobakin 		struct ice_sw_rule_lkup_rx_tx *s_rule;
338180d144c9SAnirudh Venkataramanan 
338280d144c9SAnirudh Venkataramanan 		s_rule = devm_kzalloc(ice_hw_to_dev(hw),
33836e1ff618SAlexander Lobakin 				      ICE_SW_RULE_RX_TX_NO_HDR_SIZE(s_rule),
338480d144c9SAnirudh Venkataramanan 				      GFP_KERNEL);
338580d144c9SAnirudh Venkataramanan 		if (!s_rule) {
3386d54699e2STony Nguyen 			status = -ENOMEM;
338780d144c9SAnirudh Venkataramanan 			goto exit;
338880d144c9SAnirudh Venkataramanan 		}
338980d144c9SAnirudh Venkataramanan 
339080d144c9SAnirudh Venkataramanan 		ice_fill_sw_rule(hw, &list_elem->fltr_info, s_rule,
339180d144c9SAnirudh Venkataramanan 				 ice_aqc_opc_remove_sw_rules);
339280d144c9SAnirudh Venkataramanan 
339380d144c9SAnirudh Venkataramanan 		status = ice_aq_sw_rules(hw, s_rule,
33946e1ff618SAlexander Lobakin 					 ICE_SW_RULE_RX_TX_NO_HDR_SIZE(s_rule),
33956e1ff618SAlexander Lobakin 					 1, ice_aqc_opc_remove_sw_rules, NULL);
339680d144c9SAnirudh Venkataramanan 
339780d144c9SAnirudh Venkataramanan 		/* Remove a book keeping from the list */
339880d144c9SAnirudh Venkataramanan 		devm_kfree(ice_hw_to_dev(hw), s_rule);
339980d144c9SAnirudh Venkataramanan 
34008132e17dSJeb Cramer 		if (status)
34018132e17dSJeb Cramer 			goto exit;
34028132e17dSJeb Cramer 
340380d144c9SAnirudh Venkataramanan 		list_del(&list_elem->list_entry);
340480d144c9SAnirudh Venkataramanan 		devm_kfree(ice_hw_to_dev(hw), list_elem);
340580d144c9SAnirudh Venkataramanan 	}
340680d144c9SAnirudh Venkataramanan exit:
340780d144c9SAnirudh Venkataramanan 	mutex_unlock(rule_lock);
340880d144c9SAnirudh Venkataramanan 	return status;
34099daf8208SAnirudh Venkataramanan }
34109daf8208SAnirudh Venkataramanan 
34119daf8208SAnirudh Venkataramanan /**
34129fea7498SKiran Patil  * ice_mac_fltr_exist - does this MAC filter exist for given VSI
34139fea7498SKiran Patil  * @hw: pointer to the hardware structure
34149fea7498SKiran Patil  * @mac: MAC address to be checked (for MAC filter)
34159fea7498SKiran Patil  * @vsi_handle: check MAC filter for this VSI
34169fea7498SKiran Patil  */
34179fea7498SKiran Patil bool ice_mac_fltr_exist(struct ice_hw *hw, u8 *mac, u16 vsi_handle)
34189fea7498SKiran Patil {
34199fea7498SKiran Patil 	struct ice_fltr_mgmt_list_entry *entry;
34209fea7498SKiran Patil 	struct list_head *rule_head;
34219fea7498SKiran Patil 	struct ice_switch_info *sw;
34229fea7498SKiran Patil 	struct mutex *rule_lock; /* Lock to protect filter rule list */
34239fea7498SKiran Patil 	u16 hw_vsi_id;
34249fea7498SKiran Patil 
34259fea7498SKiran Patil 	if (!ice_is_vsi_valid(hw, vsi_handle))
34269fea7498SKiran Patil 		return false;
34279fea7498SKiran Patil 
34289fea7498SKiran Patil 	hw_vsi_id = ice_get_hw_vsi_num(hw, vsi_handle);
34299fea7498SKiran Patil 	sw = hw->switch_info;
34309fea7498SKiran Patil 	rule_head = &sw->recp_list[ICE_SW_LKUP_MAC].filt_rules;
34319fea7498SKiran Patil 	if (!rule_head)
34329fea7498SKiran Patil 		return false;
34339fea7498SKiran Patil 
34349fea7498SKiran Patil 	rule_lock = &sw->recp_list[ICE_SW_LKUP_MAC].filt_rule_lock;
34359fea7498SKiran Patil 	mutex_lock(rule_lock);
34369fea7498SKiran Patil 	list_for_each_entry(entry, rule_head, list_entry) {
34379fea7498SKiran Patil 		struct ice_fltr_info *f_info = &entry->fltr_info;
34389fea7498SKiran Patil 		u8 *mac_addr = &f_info->l_data.mac.mac_addr[0];
34399fea7498SKiran Patil 
34409fea7498SKiran Patil 		if (is_zero_ether_addr(mac_addr))
34419fea7498SKiran Patil 			continue;
34429fea7498SKiran Patil 
34439fea7498SKiran Patil 		if (f_info->flag != ICE_FLTR_TX ||
34449fea7498SKiran Patil 		    f_info->src_id != ICE_SRC_ID_VSI ||
34459fea7498SKiran Patil 		    f_info->lkup_type != ICE_SW_LKUP_MAC ||
34469fea7498SKiran Patil 		    f_info->fltr_act != ICE_FWD_TO_VSI ||
34479fea7498SKiran Patil 		    hw_vsi_id != f_info->fwd_id.hw_vsi_id)
34489fea7498SKiran Patil 			continue;
34499fea7498SKiran Patil 
34509fea7498SKiran Patil 		if (ether_addr_equal(mac, mac_addr)) {
34519fea7498SKiran Patil 			mutex_unlock(rule_lock);
34529fea7498SKiran Patil 			return true;
34539fea7498SKiran Patil 		}
34549fea7498SKiran Patil 	}
34559fea7498SKiran Patil 	mutex_unlock(rule_lock);
34569fea7498SKiran Patil 	return false;
34579fea7498SKiran Patil }
34589fea7498SKiran Patil 
34599fea7498SKiran Patil /**
34609fea7498SKiran Patil  * ice_vlan_fltr_exist - does this VLAN filter exist for given VSI
34619fea7498SKiran Patil  * @hw: pointer to the hardware structure
34629fea7498SKiran Patil  * @vlan_id: VLAN ID
34639fea7498SKiran Patil  * @vsi_handle: check MAC filter for this VSI
34649fea7498SKiran Patil  */
34659fea7498SKiran Patil bool ice_vlan_fltr_exist(struct ice_hw *hw, u16 vlan_id, u16 vsi_handle)
34669fea7498SKiran Patil {
34679fea7498SKiran Patil 	struct ice_fltr_mgmt_list_entry *entry;
34689fea7498SKiran Patil 	struct list_head *rule_head;
34699fea7498SKiran Patil 	struct ice_switch_info *sw;
34709fea7498SKiran Patil 	struct mutex *rule_lock; /* Lock to protect filter rule list */
34719fea7498SKiran Patil 	u16 hw_vsi_id;
34729fea7498SKiran Patil 
34739fea7498SKiran Patil 	if (vlan_id > ICE_MAX_VLAN_ID)
34749fea7498SKiran Patil 		return false;
34759fea7498SKiran Patil 
34769fea7498SKiran Patil 	if (!ice_is_vsi_valid(hw, vsi_handle))
34779fea7498SKiran Patil 		return false;
34789fea7498SKiran Patil 
34799fea7498SKiran Patil 	hw_vsi_id = ice_get_hw_vsi_num(hw, vsi_handle);
34809fea7498SKiran Patil 	sw = hw->switch_info;
34819fea7498SKiran Patil 	rule_head = &sw->recp_list[ICE_SW_LKUP_VLAN].filt_rules;
34829fea7498SKiran Patil 	if (!rule_head)
34839fea7498SKiran Patil 		return false;
34849fea7498SKiran Patil 
34859fea7498SKiran Patil 	rule_lock = &sw->recp_list[ICE_SW_LKUP_VLAN].filt_rule_lock;
34869fea7498SKiran Patil 	mutex_lock(rule_lock);
34879fea7498SKiran Patil 	list_for_each_entry(entry, rule_head, list_entry) {
34889fea7498SKiran Patil 		struct ice_fltr_info *f_info = &entry->fltr_info;
34899fea7498SKiran Patil 		u16 entry_vlan_id = f_info->l_data.vlan.vlan_id;
34909fea7498SKiran Patil 		struct ice_vsi_list_map_info *map_info;
34919fea7498SKiran Patil 
34929fea7498SKiran Patil 		if (entry_vlan_id > ICE_MAX_VLAN_ID)
34939fea7498SKiran Patil 			continue;
34949fea7498SKiran Patil 
34959fea7498SKiran Patil 		if (f_info->flag != ICE_FLTR_TX ||
34969fea7498SKiran Patil 		    f_info->src_id != ICE_SRC_ID_VSI ||
34979fea7498SKiran Patil 		    f_info->lkup_type != ICE_SW_LKUP_VLAN)
34989fea7498SKiran Patil 			continue;
34999fea7498SKiran Patil 
35009fea7498SKiran Patil 		/* Only allowed filter action are FWD_TO_VSI/_VSI_LIST */
35019fea7498SKiran Patil 		if (f_info->fltr_act != ICE_FWD_TO_VSI &&
35029fea7498SKiran Patil 		    f_info->fltr_act != ICE_FWD_TO_VSI_LIST)
35039fea7498SKiran Patil 			continue;
35049fea7498SKiran Patil 
35059fea7498SKiran Patil 		if (f_info->fltr_act == ICE_FWD_TO_VSI) {
35069fea7498SKiran Patil 			if (hw_vsi_id != f_info->fwd_id.hw_vsi_id)
35079fea7498SKiran Patil 				continue;
35089fea7498SKiran Patil 		} else if (f_info->fltr_act == ICE_FWD_TO_VSI_LIST) {
35099fea7498SKiran Patil 			/* If filter_action is FWD_TO_VSI_LIST, make sure
35109fea7498SKiran Patil 			 * that VSI being checked is part of VSI list
35119fea7498SKiran Patil 			 */
35129fea7498SKiran Patil 			if (entry->vsi_count == 1 &&
35139fea7498SKiran Patil 			    entry->vsi_list_info) {
35149fea7498SKiran Patil 				map_info = entry->vsi_list_info;
35159fea7498SKiran Patil 				if (!test_bit(vsi_handle, map_info->vsi_map))
35169fea7498SKiran Patil 					continue;
35179fea7498SKiran Patil 			}
35189fea7498SKiran Patil 		}
35199fea7498SKiran Patil 
35209fea7498SKiran Patil 		if (vlan_id == entry_vlan_id) {
35219fea7498SKiran Patil 			mutex_unlock(rule_lock);
35229fea7498SKiran Patil 			return true;
35239fea7498SKiran Patil 		}
35249fea7498SKiran Patil 	}
35259fea7498SKiran Patil 	mutex_unlock(rule_lock);
35269fea7498SKiran Patil 
35279fea7498SKiran Patil 	return false;
35289fea7498SKiran Patil }
35299fea7498SKiran Patil 
35309fea7498SKiran Patil /**
35319daf8208SAnirudh Venkataramanan  * ice_add_mac - Add a MAC address based filter rule
35329daf8208SAnirudh Venkataramanan  * @hw: pointer to the hardware structure
35339daf8208SAnirudh Venkataramanan  * @m_list: list of MAC addresses and forwarding information
35349daf8208SAnirudh Venkataramanan  */
35355e24d598STony Nguyen int ice_add_mac(struct ice_hw *hw, struct list_head *m_list)
35369daf8208SAnirudh Venkataramanan {
35379daf8208SAnirudh Venkataramanan 	struct ice_fltr_list_entry *m_list_itr;
35385518ac2aSTony Nguyen 	int status = 0;
35399daf8208SAnirudh Venkataramanan 
35409daf8208SAnirudh Venkataramanan 	if (!m_list || !hw)
3541d54699e2STony Nguyen 		return -EINVAL;
35429daf8208SAnirudh Venkataramanan 
35439daf8208SAnirudh Venkataramanan 	list_for_each_entry(m_list_itr, m_list, list_entry) {
35449daf8208SAnirudh Venkataramanan 		u8 *add = &m_list_itr->fltr_info.l_data.mac.mac_addr[0];
35455726ca0eSAnirudh Venkataramanan 		u16 vsi_handle;
35465726ca0eSAnirudh Venkataramanan 		u16 hw_vsi_id;
35479daf8208SAnirudh Venkataramanan 
354880d144c9SAnirudh Venkataramanan 		m_list_itr->fltr_info.flag = ICE_FLTR_TX;
35495726ca0eSAnirudh Venkataramanan 		vsi_handle = m_list_itr->fltr_info.vsi_handle;
35505726ca0eSAnirudh Venkataramanan 		if (!ice_is_vsi_valid(hw, vsi_handle))
3551d54699e2STony Nguyen 			return -EINVAL;
35525726ca0eSAnirudh Venkataramanan 		hw_vsi_id = ice_get_hw_vsi_num(hw, vsi_handle);
35535726ca0eSAnirudh Venkataramanan 		m_list_itr->fltr_info.fwd_id.hw_vsi_id = hw_vsi_id;
3554f9867df6SAnirudh Venkataramanan 		/* update the src in case it is VSI num */
35555726ca0eSAnirudh Venkataramanan 		if (m_list_itr->fltr_info.src_id != ICE_SRC_ID_VSI)
3556d54699e2STony Nguyen 			return -EINVAL;
35575726ca0eSAnirudh Venkataramanan 		m_list_itr->fltr_info.src = hw_vsi_id;
355880d144c9SAnirudh Venkataramanan 		if (m_list_itr->fltr_info.lkup_type != ICE_SW_LKUP_MAC ||
355980d144c9SAnirudh Venkataramanan 		    is_zero_ether_addr(add))
3560d54699e2STony Nguyen 			return -EINVAL;
3561e1e9db57SSylwester Dziedziuch 
3562e1e9db57SSylwester Dziedziuch 		m_list_itr->status = ice_add_rule_internal(hw, ICE_SW_LKUP_MAC,
356380d144c9SAnirudh Venkataramanan 							   m_list_itr);
356480d144c9SAnirudh Venkataramanan 		if (m_list_itr->status)
356580d144c9SAnirudh Venkataramanan 			return m_list_itr->status;
35669daf8208SAnirudh Venkataramanan 	}
35679daf8208SAnirudh Venkataramanan 
35689daf8208SAnirudh Venkataramanan 	return status;
35699daf8208SAnirudh Venkataramanan }
35709daf8208SAnirudh Venkataramanan 
35719daf8208SAnirudh Venkataramanan /**
3572d76a60baSAnirudh Venkataramanan  * ice_add_vlan_internal - Add one VLAN based filter rule
3573d76a60baSAnirudh Venkataramanan  * @hw: pointer to the hardware structure
3574d76a60baSAnirudh Venkataramanan  * @f_entry: filter entry containing one VLAN information
3575d76a60baSAnirudh Venkataramanan  */
35765e24d598STony Nguyen static int
3577d76a60baSAnirudh Venkataramanan ice_add_vlan_internal(struct ice_hw *hw, struct ice_fltr_list_entry *f_entry)
3578d76a60baSAnirudh Venkataramanan {
357980d144c9SAnirudh Venkataramanan 	struct ice_switch_info *sw = hw->switch_info;
3580d76a60baSAnirudh Venkataramanan 	struct ice_fltr_mgmt_list_entry *v_list_itr;
35815726ca0eSAnirudh Venkataramanan 	struct ice_fltr_info *new_fltr, *cur_fltr;
35825726ca0eSAnirudh Venkataramanan 	enum ice_sw_lkup_type lkup_type;
35835726ca0eSAnirudh Venkataramanan 	u16 vsi_list_id = 0, vsi_handle;
358480d144c9SAnirudh Venkataramanan 	struct mutex *rule_lock; /* Lock to protect filter rule list */
35855e24d598STony Nguyen 	int status = 0;
3586d76a60baSAnirudh Venkataramanan 
35875726ca0eSAnirudh Venkataramanan 	if (!ice_is_vsi_valid(hw, f_entry->fltr_info.vsi_handle))
3588d54699e2STony Nguyen 		return -EINVAL;
35895726ca0eSAnirudh Venkataramanan 
35905726ca0eSAnirudh Venkataramanan 	f_entry->fltr_info.fwd_id.hw_vsi_id =
35915726ca0eSAnirudh Venkataramanan 		ice_get_hw_vsi_num(hw, f_entry->fltr_info.vsi_handle);
3592d76a60baSAnirudh Venkataramanan 	new_fltr = &f_entry->fltr_info;
35935726ca0eSAnirudh Venkataramanan 
3594f9867df6SAnirudh Venkataramanan 	/* VLAN ID should only be 12 bits */
3595d76a60baSAnirudh Venkataramanan 	if (new_fltr->l_data.vlan.vlan_id > ICE_MAX_VLAN_ID)
3596d54699e2STony Nguyen 		return -EINVAL;
3597d76a60baSAnirudh Venkataramanan 
35985726ca0eSAnirudh Venkataramanan 	if (new_fltr->src_id != ICE_SRC_ID_VSI)
3599d54699e2STony Nguyen 		return -EINVAL;
36005726ca0eSAnirudh Venkataramanan 
36015726ca0eSAnirudh Venkataramanan 	new_fltr->src = new_fltr->fwd_id.hw_vsi_id;
36025726ca0eSAnirudh Venkataramanan 	lkup_type = new_fltr->lkup_type;
36035726ca0eSAnirudh Venkataramanan 	vsi_handle = new_fltr->vsi_handle;
360480d144c9SAnirudh Venkataramanan 	rule_lock = &sw->recp_list[ICE_SW_LKUP_VLAN].filt_rule_lock;
360580d144c9SAnirudh Venkataramanan 	mutex_lock(rule_lock);
360680d144c9SAnirudh Venkataramanan 	v_list_itr = ice_find_rule_entry(hw, ICE_SW_LKUP_VLAN, new_fltr);
3607d76a60baSAnirudh Venkataramanan 	if (!v_list_itr) {
36085726ca0eSAnirudh Venkataramanan 		struct ice_vsi_list_map_info *map_info = NULL;
3609d76a60baSAnirudh Venkataramanan 
3610d76a60baSAnirudh Venkataramanan 		if (new_fltr->fltr_act == ICE_FWD_TO_VSI) {
36115726ca0eSAnirudh Venkataramanan 			/* All VLAN pruning rules use a VSI list. Check if
36125726ca0eSAnirudh Venkataramanan 			 * there is already a VSI list containing VSI that we
36135726ca0eSAnirudh Venkataramanan 			 * want to add. If found, use the same vsi_list_id for
36145726ca0eSAnirudh Venkataramanan 			 * this new VLAN rule or else create a new list.
3615d76a60baSAnirudh Venkataramanan 			 */
36165726ca0eSAnirudh Venkataramanan 			map_info = ice_find_vsi_list_entry(hw, ICE_SW_LKUP_VLAN,
36175726ca0eSAnirudh Venkataramanan 							   vsi_handle,
36185726ca0eSAnirudh Venkataramanan 							   &vsi_list_id);
36195726ca0eSAnirudh Venkataramanan 			if (!map_info) {
36205726ca0eSAnirudh Venkataramanan 				status = ice_create_vsi_list_rule(hw,
36215726ca0eSAnirudh Venkataramanan 								  &vsi_handle,
36225726ca0eSAnirudh Venkataramanan 								  1,
3623d76a60baSAnirudh Venkataramanan 								  &vsi_list_id,
3624d76a60baSAnirudh Venkataramanan 								  lkup_type);
3625d76a60baSAnirudh Venkataramanan 				if (status)
362680d144c9SAnirudh Venkataramanan 					goto exit;
36275726ca0eSAnirudh Venkataramanan 			}
36285726ca0eSAnirudh Venkataramanan 			/* Convert the action to forwarding to a VSI list. */
3629d76a60baSAnirudh Venkataramanan 			new_fltr->fltr_act = ICE_FWD_TO_VSI_LIST;
3630d76a60baSAnirudh Venkataramanan 			new_fltr->fwd_id.vsi_list_id = vsi_list_id;
3631d76a60baSAnirudh Venkataramanan 		}
3632d76a60baSAnirudh Venkataramanan 
3633d76a60baSAnirudh Venkataramanan 		status = ice_create_pkt_fwd_rule(hw, f_entry);
36345726ca0eSAnirudh Venkataramanan 		if (!status) {
363580d144c9SAnirudh Venkataramanan 			v_list_itr = ice_find_rule_entry(hw, ICE_SW_LKUP_VLAN,
363680d144c9SAnirudh Venkataramanan 							 new_fltr);
363780d144c9SAnirudh Venkataramanan 			if (!v_list_itr) {
3638d54699e2STony Nguyen 				status = -ENOENT;
363980d144c9SAnirudh Venkataramanan 				goto exit;
364080d144c9SAnirudh Venkataramanan 			}
36415726ca0eSAnirudh Venkataramanan 			/* reuse VSI list for new rule and increment ref_cnt */
36425726ca0eSAnirudh Venkataramanan 			if (map_info) {
36435726ca0eSAnirudh Venkataramanan 				v_list_itr->vsi_list_info = map_info;
36445726ca0eSAnirudh Venkataramanan 				map_info->ref_cnt++;
36455726ca0eSAnirudh Venkataramanan 			} else {
3646d76a60baSAnirudh Venkataramanan 				v_list_itr->vsi_list_info =
36475726ca0eSAnirudh Venkataramanan 					ice_create_vsi_list_map(hw, &vsi_handle,
36485726ca0eSAnirudh Venkataramanan 								1, vsi_list_id);
3649d76a60baSAnirudh Venkataramanan 			}
36505726ca0eSAnirudh Venkataramanan 		}
36515726ca0eSAnirudh Venkataramanan 	} else if (v_list_itr->vsi_list_info->ref_cnt == 1) {
3652f9867df6SAnirudh Venkataramanan 		/* Update existing VSI list to add new VSI ID only if it used
36535726ca0eSAnirudh Venkataramanan 		 * by one VLAN rule.
36545726ca0eSAnirudh Venkataramanan 		 */
36555726ca0eSAnirudh Venkataramanan 		cur_fltr = &v_list_itr->fltr_info;
36565726ca0eSAnirudh Venkataramanan 		status = ice_add_update_vsi_list(hw, v_list_itr, cur_fltr,
36575726ca0eSAnirudh Venkataramanan 						 new_fltr);
36585726ca0eSAnirudh Venkataramanan 	} else {
36595726ca0eSAnirudh Venkataramanan 		/* If VLAN rule exists and VSI list being used by this rule is
36605726ca0eSAnirudh Venkataramanan 		 * referenced by more than 1 VLAN rule. Then create a new VSI
36615726ca0eSAnirudh Venkataramanan 		 * list appending previous VSI with new VSI and update existing
3662f9867df6SAnirudh Venkataramanan 		 * VLAN rule to point to new VSI list ID
36635726ca0eSAnirudh Venkataramanan 		 */
36645726ca0eSAnirudh Venkataramanan 		struct ice_fltr_info tmp_fltr;
36655726ca0eSAnirudh Venkataramanan 		u16 vsi_handle_arr[2];
36665726ca0eSAnirudh Venkataramanan 		u16 cur_handle;
3667d76a60baSAnirudh Venkataramanan 
36685726ca0eSAnirudh Venkataramanan 		/* Current implementation only supports reusing VSI list with
36695726ca0eSAnirudh Venkataramanan 		 * one VSI count. We should never hit below condition
36705726ca0eSAnirudh Venkataramanan 		 */
36715726ca0eSAnirudh Venkataramanan 		if (v_list_itr->vsi_count > 1 &&
36725726ca0eSAnirudh Venkataramanan 		    v_list_itr->vsi_list_info->ref_cnt > 1) {
36739228d8b2SJacob 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");
3674d54699e2STony Nguyen 			status = -EIO;
367580d144c9SAnirudh Venkataramanan 			goto exit;
3676d76a60baSAnirudh Venkataramanan 		}
3677d76a60baSAnirudh Venkataramanan 
36785726ca0eSAnirudh Venkataramanan 		cur_handle =
36795726ca0eSAnirudh Venkataramanan 			find_first_bit(v_list_itr->vsi_list_info->vsi_map,
36805726ca0eSAnirudh Venkataramanan 				       ICE_MAX_VSI);
36815726ca0eSAnirudh Venkataramanan 
36825726ca0eSAnirudh Venkataramanan 		/* A rule already exists with the new VSI being added */
36835726ca0eSAnirudh Venkataramanan 		if (cur_handle == vsi_handle) {
3684d54699e2STony Nguyen 			status = -EEXIST;
36855726ca0eSAnirudh Venkataramanan 			goto exit;
36865726ca0eSAnirudh Venkataramanan 		}
36875726ca0eSAnirudh Venkataramanan 
36885726ca0eSAnirudh Venkataramanan 		vsi_handle_arr[0] = cur_handle;
36895726ca0eSAnirudh Venkataramanan 		vsi_handle_arr[1] = vsi_handle;
36905726ca0eSAnirudh Venkataramanan 		status = ice_create_vsi_list_rule(hw, &vsi_handle_arr[0], 2,
36915726ca0eSAnirudh Venkataramanan 						  &vsi_list_id, lkup_type);
36925726ca0eSAnirudh Venkataramanan 		if (status)
36935726ca0eSAnirudh Venkataramanan 			goto exit;
36945726ca0eSAnirudh Venkataramanan 
36955726ca0eSAnirudh Venkataramanan 		tmp_fltr = v_list_itr->fltr_info;
36965726ca0eSAnirudh Venkataramanan 		tmp_fltr.fltr_rule_id = v_list_itr->fltr_info.fltr_rule_id;
36975726ca0eSAnirudh Venkataramanan 		tmp_fltr.fwd_id.vsi_list_id = vsi_list_id;
36985726ca0eSAnirudh Venkataramanan 		tmp_fltr.fltr_act = ICE_FWD_TO_VSI_LIST;
36995726ca0eSAnirudh Venkataramanan 		/* Update the previous switch rule to a new VSI list which
3700df17b7e0SAnirudh Venkataramanan 		 * includes current VSI that is requested
37015726ca0eSAnirudh Venkataramanan 		 */
37025726ca0eSAnirudh Venkataramanan 		status = ice_update_pkt_fwd_rule(hw, &tmp_fltr);
37035726ca0eSAnirudh Venkataramanan 		if (status)
37045726ca0eSAnirudh Venkataramanan 			goto exit;
37055726ca0eSAnirudh Venkataramanan 
37065726ca0eSAnirudh Venkataramanan 		/* before overriding VSI list map info. decrement ref_cnt of
37075726ca0eSAnirudh Venkataramanan 		 * previous VSI list
37085726ca0eSAnirudh Venkataramanan 		 */
37095726ca0eSAnirudh Venkataramanan 		v_list_itr->vsi_list_info->ref_cnt--;
37105726ca0eSAnirudh Venkataramanan 
37115726ca0eSAnirudh Venkataramanan 		/* now update to newly created list */
37125726ca0eSAnirudh Venkataramanan 		v_list_itr->fltr_info.fwd_id.vsi_list_id = vsi_list_id;
37135726ca0eSAnirudh Venkataramanan 		v_list_itr->vsi_list_info =
37145726ca0eSAnirudh Venkataramanan 			ice_create_vsi_list_map(hw, &vsi_handle_arr[0], 2,
37155726ca0eSAnirudh Venkataramanan 						vsi_list_id);
37165726ca0eSAnirudh Venkataramanan 		v_list_itr->vsi_count++;
37175726ca0eSAnirudh Venkataramanan 	}
371880d144c9SAnirudh Venkataramanan 
371980d144c9SAnirudh Venkataramanan exit:
372080d144c9SAnirudh Venkataramanan 	mutex_unlock(rule_lock);
372180d144c9SAnirudh Venkataramanan 	return status;
3722d76a60baSAnirudh Venkataramanan }
3723d76a60baSAnirudh Venkataramanan 
3724d76a60baSAnirudh Venkataramanan /**
3725d76a60baSAnirudh Venkataramanan  * ice_add_vlan - Add VLAN based filter rule
3726d76a60baSAnirudh Venkataramanan  * @hw: pointer to the hardware structure
3727d76a60baSAnirudh Venkataramanan  * @v_list: list of VLAN entries and forwarding information
3728d76a60baSAnirudh Venkataramanan  */
37295e24d598STony Nguyen int ice_add_vlan(struct ice_hw *hw, struct list_head *v_list)
3730d76a60baSAnirudh Venkataramanan {
3731d76a60baSAnirudh Venkataramanan 	struct ice_fltr_list_entry *v_list_itr;
3732d76a60baSAnirudh Venkataramanan 
3733d76a60baSAnirudh Venkataramanan 	if (!v_list || !hw)
3734d54699e2STony Nguyen 		return -EINVAL;
3735d76a60baSAnirudh Venkataramanan 
3736d76a60baSAnirudh Venkataramanan 	list_for_each_entry(v_list_itr, v_list, list_entry) {
3737d76a60baSAnirudh Venkataramanan 		if (v_list_itr->fltr_info.lkup_type != ICE_SW_LKUP_VLAN)
3738d54699e2STony Nguyen 			return -EINVAL;
373980d144c9SAnirudh Venkataramanan 		v_list_itr->fltr_info.flag = ICE_FLTR_TX;
374080d144c9SAnirudh Venkataramanan 		v_list_itr->status = ice_add_vlan_internal(hw, v_list_itr);
374180d144c9SAnirudh Venkataramanan 		if (v_list_itr->status)
374280d144c9SAnirudh Venkataramanan 			return v_list_itr->status;
3743d76a60baSAnirudh Venkataramanan 	}
3744d76a60baSAnirudh Venkataramanan 	return 0;
3745d76a60baSAnirudh Venkataramanan }
3746d76a60baSAnirudh Venkataramanan 
3747d76a60baSAnirudh Venkataramanan /**
3748d95276ceSAkeem G Abodunrin  * ice_add_eth_mac - Add ethertype and MAC based filter rule
3749d95276ceSAkeem G Abodunrin  * @hw: pointer to the hardware structure
3750d95276ceSAkeem G Abodunrin  * @em_list: list of ether type MAC filter, MAC is optional
37512e0e6228SDave Ertman  *
37522e0e6228SDave Ertman  * This function requires the caller to populate the entries in
37532e0e6228SDave Ertman  * the filter list with the necessary fields (including flags to
37542e0e6228SDave Ertman  * indicate Tx or Rx rules).
3755d95276ceSAkeem G Abodunrin  */
37565518ac2aSTony Nguyen int ice_add_eth_mac(struct ice_hw *hw, struct list_head *em_list)
3757d95276ceSAkeem G Abodunrin {
3758d95276ceSAkeem G Abodunrin 	struct ice_fltr_list_entry *em_list_itr;
3759d95276ceSAkeem G Abodunrin 
3760d95276ceSAkeem G Abodunrin 	if (!em_list || !hw)
3761d54699e2STony Nguyen 		return -EINVAL;
3762d95276ceSAkeem G Abodunrin 
3763d95276ceSAkeem G Abodunrin 	list_for_each_entry(em_list_itr, em_list, list_entry) {
3764d95276ceSAkeem G Abodunrin 		enum ice_sw_lkup_type l_type =
3765d95276ceSAkeem G Abodunrin 			em_list_itr->fltr_info.lkup_type;
3766d95276ceSAkeem G Abodunrin 
3767d95276ceSAkeem G Abodunrin 		if (l_type != ICE_SW_LKUP_ETHERTYPE_MAC &&
3768d95276ceSAkeem G Abodunrin 		    l_type != ICE_SW_LKUP_ETHERTYPE)
3769d54699e2STony Nguyen 			return -EINVAL;
3770d95276ceSAkeem G Abodunrin 
3771d95276ceSAkeem G Abodunrin 		em_list_itr->status = ice_add_rule_internal(hw, l_type,
3772d95276ceSAkeem G Abodunrin 							    em_list_itr);
3773d95276ceSAkeem G Abodunrin 		if (em_list_itr->status)
3774d95276ceSAkeem G Abodunrin 			return em_list_itr->status;
3775d95276ceSAkeem G Abodunrin 	}
3776d95276ceSAkeem G Abodunrin 	return 0;
3777d95276ceSAkeem G Abodunrin }
3778d95276ceSAkeem G Abodunrin 
3779d95276ceSAkeem G Abodunrin /**
3780d95276ceSAkeem G Abodunrin  * ice_remove_eth_mac - Remove an ethertype (or MAC) based filter rule
3781d95276ceSAkeem G Abodunrin  * @hw: pointer to the hardware structure
3782d95276ceSAkeem G Abodunrin  * @em_list: list of ethertype or ethertype MAC entries
3783d95276ceSAkeem G Abodunrin  */
37845518ac2aSTony Nguyen int ice_remove_eth_mac(struct ice_hw *hw, struct list_head *em_list)
3785d95276ceSAkeem G Abodunrin {
3786d95276ceSAkeem G Abodunrin 	struct ice_fltr_list_entry *em_list_itr, *tmp;
3787d95276ceSAkeem G Abodunrin 
3788d95276ceSAkeem G Abodunrin 	if (!em_list || !hw)
3789d54699e2STony Nguyen 		return -EINVAL;
3790d95276ceSAkeem G Abodunrin 
3791d95276ceSAkeem G Abodunrin 	list_for_each_entry_safe(em_list_itr, tmp, em_list, list_entry) {
3792d95276ceSAkeem G Abodunrin 		enum ice_sw_lkup_type l_type =
3793d95276ceSAkeem G Abodunrin 			em_list_itr->fltr_info.lkup_type;
3794d95276ceSAkeem G Abodunrin 
3795d95276ceSAkeem G Abodunrin 		if (l_type != ICE_SW_LKUP_ETHERTYPE_MAC &&
3796d95276ceSAkeem G Abodunrin 		    l_type != ICE_SW_LKUP_ETHERTYPE)
3797d54699e2STony Nguyen 			return -EINVAL;
3798d95276ceSAkeem G Abodunrin 
3799d95276ceSAkeem G Abodunrin 		em_list_itr->status = ice_remove_rule_internal(hw, l_type,
3800d95276ceSAkeem G Abodunrin 							       em_list_itr);
3801d95276ceSAkeem G Abodunrin 		if (em_list_itr->status)
3802d95276ceSAkeem G Abodunrin 			return em_list_itr->status;
3803d95276ceSAkeem G Abodunrin 	}
3804d95276ceSAkeem G Abodunrin 	return 0;
3805d95276ceSAkeem G Abodunrin }
3806d95276ceSAkeem G Abodunrin 
3807d95276ceSAkeem G Abodunrin /**
38080f9d5027SAnirudh Venkataramanan  * ice_rem_sw_rule_info
38090f9d5027SAnirudh Venkataramanan  * @hw: pointer to the hardware structure
38100f9d5027SAnirudh Venkataramanan  * @rule_head: pointer to the switch list structure that we want to delete
38110f9d5027SAnirudh Venkataramanan  */
38120f9d5027SAnirudh Venkataramanan static void
38130f9d5027SAnirudh Venkataramanan ice_rem_sw_rule_info(struct ice_hw *hw, struct list_head *rule_head)
38140f9d5027SAnirudh Venkataramanan {
38150f9d5027SAnirudh Venkataramanan 	if (!list_empty(rule_head)) {
38160f9d5027SAnirudh Venkataramanan 		struct ice_fltr_mgmt_list_entry *entry;
38170f9d5027SAnirudh Venkataramanan 		struct ice_fltr_mgmt_list_entry *tmp;
38180f9d5027SAnirudh Venkataramanan 
38190f9d5027SAnirudh Venkataramanan 		list_for_each_entry_safe(entry, tmp, rule_head, list_entry) {
38200f9d5027SAnirudh Venkataramanan 			list_del(&entry->list_entry);
38210f9d5027SAnirudh Venkataramanan 			devm_kfree(ice_hw_to_dev(hw), entry);
38220f9d5027SAnirudh Venkataramanan 		}
38230f9d5027SAnirudh Venkataramanan 	}
38240f9d5027SAnirudh Venkataramanan }
38250f9d5027SAnirudh Venkataramanan 
38260f9d5027SAnirudh Venkataramanan /**
38278b8ef05bSVictor Raj  * ice_rem_adv_rule_info
38288b8ef05bSVictor Raj  * @hw: pointer to the hardware structure
38298b8ef05bSVictor Raj  * @rule_head: pointer to the switch list structure that we want to delete
38308b8ef05bSVictor Raj  */
38318b8ef05bSVictor Raj static void
38328b8ef05bSVictor Raj ice_rem_adv_rule_info(struct ice_hw *hw, struct list_head *rule_head)
38338b8ef05bSVictor Raj {
38348b8ef05bSVictor Raj 	struct ice_adv_fltr_mgmt_list_entry *tmp_entry;
38358b8ef05bSVictor Raj 	struct ice_adv_fltr_mgmt_list_entry *lst_itr;
38368b8ef05bSVictor Raj 
38378b8ef05bSVictor Raj 	if (list_empty(rule_head))
38388b8ef05bSVictor Raj 		return;
38398b8ef05bSVictor Raj 
38408b8ef05bSVictor Raj 	list_for_each_entry_safe(lst_itr, tmp_entry, rule_head, list_entry) {
38418b8ef05bSVictor Raj 		list_del(&lst_itr->list_entry);
38428b8ef05bSVictor Raj 		devm_kfree(ice_hw_to_dev(hw), lst_itr->lkups);
38438b8ef05bSVictor Raj 		devm_kfree(ice_hw_to_dev(hw), lst_itr);
38448b8ef05bSVictor Raj 	}
38458b8ef05bSVictor Raj }
38468b8ef05bSVictor Raj 
38478b8ef05bSVictor Raj /**
384880d144c9SAnirudh Venkataramanan  * ice_cfg_dflt_vsi - change state of VSI to set/clear default
3849d7393425SMichal Wilczynski  * @pi: pointer to the port_info structure
38505726ca0eSAnirudh Venkataramanan  * @vsi_handle: VSI handle to set as default
3851e94d4478SAnirudh Venkataramanan  * @set: true to add the above mentioned switch rule, false to remove it
3852e94d4478SAnirudh Venkataramanan  * @direction: ICE_FLTR_RX or ICE_FLTR_TX
385380d144c9SAnirudh Venkataramanan  *
385480d144c9SAnirudh Venkataramanan  * add filter rule to set/unset given VSI as default VSI for the switch
385580d144c9SAnirudh Venkataramanan  * (represented by swid)
3856e94d4478SAnirudh Venkataramanan  */
3857d7393425SMichal Wilczynski int
3858d7393425SMichal Wilczynski ice_cfg_dflt_vsi(struct ice_port_info *pi, u16 vsi_handle, bool set,
3859d7393425SMichal Wilczynski 		 u8 direction)
3860e94d4478SAnirudh Venkataramanan {
3861d7393425SMichal Wilczynski 	struct ice_fltr_list_entry f_list_entry;
3862e94d4478SAnirudh Venkataramanan 	struct ice_fltr_info f_info;
3863d7393425SMichal Wilczynski 	struct ice_hw *hw = pi->hw;
38645726ca0eSAnirudh Venkataramanan 	u16 hw_vsi_id;
38655518ac2aSTony Nguyen 	int status;
38665726ca0eSAnirudh Venkataramanan 
38675726ca0eSAnirudh Venkataramanan 	if (!ice_is_vsi_valid(hw, vsi_handle))
3868d54699e2STony Nguyen 		return -EINVAL;
3869d7393425SMichal Wilczynski 
38705726ca0eSAnirudh Venkataramanan 	hw_vsi_id = ice_get_hw_vsi_num(hw, vsi_handle);
3871e94d4478SAnirudh Venkataramanan 
3872e94d4478SAnirudh Venkataramanan 	memset(&f_info, 0, sizeof(f_info));
3873e94d4478SAnirudh Venkataramanan 
3874e94d4478SAnirudh Venkataramanan 	f_info.lkup_type = ICE_SW_LKUP_DFLT;
3875e94d4478SAnirudh Venkataramanan 	f_info.flag = direction;
3876e94d4478SAnirudh Venkataramanan 	f_info.fltr_act = ICE_FWD_TO_VSI;
38775726ca0eSAnirudh Venkataramanan 	f_info.fwd_id.hw_vsi_id = hw_vsi_id;
3878d7393425SMichal Wilczynski 	f_info.vsi_handle = vsi_handle;
3879e94d4478SAnirudh Venkataramanan 
3880e94d4478SAnirudh Venkataramanan 	if (f_info.flag & ICE_FLTR_RX) {
3881e94d4478SAnirudh Venkataramanan 		f_info.src = hw->port_info->lport;
38825726ca0eSAnirudh Venkataramanan 		f_info.src_id = ICE_SRC_ID_LPORT;
3883e94d4478SAnirudh Venkataramanan 	} else if (f_info.flag & ICE_FLTR_TX) {
38845726ca0eSAnirudh Venkataramanan 		f_info.src_id = ICE_SRC_ID_VSI;
38855726ca0eSAnirudh Venkataramanan 		f_info.src = hw_vsi_id;
3886e94d4478SAnirudh Venkataramanan 	}
3887d7393425SMichal Wilczynski 	f_list_entry.fltr_info = f_info;
3888e94d4478SAnirudh Venkataramanan 
3889e94d4478SAnirudh Venkataramanan 	if (set)
3890d7393425SMichal Wilczynski 		status = ice_add_rule_internal(hw, ICE_SW_LKUP_DFLT,
3891d7393425SMichal Wilczynski 					       &f_list_entry);
3892e94d4478SAnirudh Venkataramanan 	else
3893d7393425SMichal Wilczynski 		status = ice_remove_rule_internal(hw, ICE_SW_LKUP_DFLT,
3894d7393425SMichal Wilczynski 						  &f_list_entry);
3895e94d4478SAnirudh Venkataramanan 
3896e94d4478SAnirudh Venkataramanan 	return status;
3897e94d4478SAnirudh Venkataramanan }
3898e94d4478SAnirudh Venkataramanan 
3899e94d4478SAnirudh Venkataramanan /**
3900d7393425SMichal Wilczynski  * ice_vsi_uses_fltr - Determine if given VSI uses specified filter
3901d7393425SMichal Wilczynski  * @fm_entry: filter entry to inspect
3902d7393425SMichal Wilczynski  * @vsi_handle: VSI handle to compare with filter info
3903d7393425SMichal Wilczynski  */
3904d7393425SMichal Wilczynski static bool
3905d7393425SMichal Wilczynski ice_vsi_uses_fltr(struct ice_fltr_mgmt_list_entry *fm_entry, u16 vsi_handle)
3906d7393425SMichal Wilczynski {
3907d7393425SMichal Wilczynski 	return ((fm_entry->fltr_info.fltr_act == ICE_FWD_TO_VSI &&
3908d7393425SMichal Wilczynski 		 fm_entry->fltr_info.vsi_handle == vsi_handle) ||
3909d7393425SMichal Wilczynski 		(fm_entry->fltr_info.fltr_act == ICE_FWD_TO_VSI_LIST &&
3910d7393425SMichal Wilczynski 		 fm_entry->vsi_list_info &&
3911d7393425SMichal Wilczynski 		 (test_bit(vsi_handle, fm_entry->vsi_list_info->vsi_map))));
3912d7393425SMichal Wilczynski }
3913d7393425SMichal Wilczynski 
3914d7393425SMichal Wilczynski /**
3915d7393425SMichal Wilczynski  * ice_check_if_dflt_vsi - check if VSI is default VSI
3916d7393425SMichal Wilczynski  * @pi: pointer to the port_info structure
3917d7393425SMichal Wilczynski  * @vsi_handle: vsi handle to check for in filter list
3918d7393425SMichal Wilczynski  * @rule_exists: indicates if there are any VSI's in the rule list
3919d7393425SMichal Wilczynski  *
3920d7393425SMichal Wilczynski  * checks if the VSI is in a default VSI list, and also indicates
3921d7393425SMichal Wilczynski  * if the default VSI list is empty
3922d7393425SMichal Wilczynski  */
3923d7393425SMichal Wilczynski bool
3924d7393425SMichal Wilczynski ice_check_if_dflt_vsi(struct ice_port_info *pi, u16 vsi_handle,
3925d7393425SMichal Wilczynski 		      bool *rule_exists)
3926d7393425SMichal Wilczynski {
3927d7393425SMichal Wilczynski 	struct ice_fltr_mgmt_list_entry *fm_entry;
3928d7393425SMichal Wilczynski 	struct ice_sw_recipe *recp_list;
3929d7393425SMichal Wilczynski 	struct list_head *rule_head;
3930d7393425SMichal Wilczynski 	struct mutex *rule_lock; /* Lock to protect filter rule list */
3931d7393425SMichal Wilczynski 	bool ret = false;
3932d7393425SMichal Wilczynski 
3933d7393425SMichal Wilczynski 	recp_list = &pi->hw->switch_info->recp_list[ICE_SW_LKUP_DFLT];
3934d7393425SMichal Wilczynski 	rule_lock = &recp_list->filt_rule_lock;
3935d7393425SMichal Wilczynski 	rule_head = &recp_list->filt_rules;
3936d7393425SMichal Wilczynski 
3937d7393425SMichal Wilczynski 	mutex_lock(rule_lock);
3938d7393425SMichal Wilczynski 
3939d7393425SMichal Wilczynski 	if (rule_exists && !list_empty(rule_head))
3940d7393425SMichal Wilczynski 		*rule_exists = true;
3941d7393425SMichal Wilczynski 
3942d7393425SMichal Wilczynski 	list_for_each_entry(fm_entry, rule_head, list_entry) {
3943d7393425SMichal Wilczynski 		if (ice_vsi_uses_fltr(fm_entry, vsi_handle)) {
3944d7393425SMichal Wilczynski 			ret = true;
3945d7393425SMichal Wilczynski 			break;
3946d7393425SMichal Wilczynski 		}
3947d7393425SMichal Wilczynski 	}
3948d7393425SMichal Wilczynski 
3949d7393425SMichal Wilczynski 	mutex_unlock(rule_lock);
3950d7393425SMichal Wilczynski 
3951d7393425SMichal Wilczynski 	return ret;
3952d7393425SMichal Wilczynski }
3953d7393425SMichal Wilczynski 
3954d7393425SMichal Wilczynski /**
395580d144c9SAnirudh Venkataramanan  * ice_remove_mac - remove a MAC address based filter rule
3956d76a60baSAnirudh Venkataramanan  * @hw: pointer to the hardware structure
395780d144c9SAnirudh Venkataramanan  * @m_list: list of MAC addresses and forwarding information
395880d144c9SAnirudh Venkataramanan  *
395980d144c9SAnirudh Venkataramanan  * This function removes either a MAC filter rule or a specific VSI from a
396080d144c9SAnirudh Venkataramanan  * VSI list for a multicast MAC address.
396180d144c9SAnirudh Venkataramanan  *
39625518ac2aSTony Nguyen  * Returns -ENOENT if a given entry was not added by ice_add_mac. Caller should
39635518ac2aSTony Nguyen  * be aware that this call will only work if all the entries passed into m_list
39645518ac2aSTony Nguyen  * were added previously. It will not attempt to do a partial remove of entries
39655518ac2aSTony Nguyen  * that were found.
3966d76a60baSAnirudh Venkataramanan  */
39675e24d598STony Nguyen int ice_remove_mac(struct ice_hw *hw, struct list_head *m_list)
3968d76a60baSAnirudh Venkataramanan {
3969072f0c3dSDave Ertman 	struct ice_fltr_list_entry *list_itr, *tmp;
3970d76a60baSAnirudh Venkataramanan 
397180d144c9SAnirudh Venkataramanan 	if (!m_list)
3972d54699e2STony Nguyen 		return -EINVAL;
3973d76a60baSAnirudh Venkataramanan 
3974072f0c3dSDave Ertman 	list_for_each_entry_safe(list_itr, tmp, m_list, list_entry) {
397580d144c9SAnirudh Venkataramanan 		enum ice_sw_lkup_type l_type = list_itr->fltr_info.lkup_type;
39768b2c8582SAkeem G Abodunrin 		u16 vsi_handle;
397780d144c9SAnirudh Venkataramanan 
397880d144c9SAnirudh Venkataramanan 		if (l_type != ICE_SW_LKUP_MAC)
3979d54699e2STony Nguyen 			return -EINVAL;
39808b2c8582SAkeem G Abodunrin 
39818b2c8582SAkeem G Abodunrin 		vsi_handle = list_itr->fltr_info.vsi_handle;
39828b2c8582SAkeem G Abodunrin 		if (!ice_is_vsi_valid(hw, vsi_handle))
3983d54699e2STony Nguyen 			return -EINVAL;
39848b2c8582SAkeem G Abodunrin 
39858b2c8582SAkeem G Abodunrin 		list_itr->fltr_info.fwd_id.hw_vsi_id =
39868b2c8582SAkeem G Abodunrin 					ice_get_hw_vsi_num(hw, vsi_handle);
3987e1e9db57SSylwester Dziedziuch 
398880d144c9SAnirudh Venkataramanan 		list_itr->status = ice_remove_rule_internal(hw,
398980d144c9SAnirudh Venkataramanan 							    ICE_SW_LKUP_MAC,
399080d144c9SAnirudh Venkataramanan 							    list_itr);
399180d144c9SAnirudh Venkataramanan 		if (list_itr->status)
399280d144c9SAnirudh Venkataramanan 			return list_itr->status;
399380d144c9SAnirudh Venkataramanan 	}
399480d144c9SAnirudh Venkataramanan 	return 0;
3995d76a60baSAnirudh Venkataramanan }
3996d76a60baSAnirudh Venkataramanan 
3997d76a60baSAnirudh Venkataramanan /**
3998d76a60baSAnirudh Venkataramanan  * ice_remove_vlan - Remove VLAN based filter rule
3999d76a60baSAnirudh Venkataramanan  * @hw: pointer to the hardware structure
4000d76a60baSAnirudh Venkataramanan  * @v_list: list of VLAN entries and forwarding information
4001d76a60baSAnirudh Venkataramanan  */
40025518ac2aSTony Nguyen int ice_remove_vlan(struct ice_hw *hw, struct list_head *v_list)
4003d76a60baSAnirudh Venkataramanan {
4004072f0c3dSDave Ertman 	struct ice_fltr_list_entry *v_list_itr, *tmp;
4005d76a60baSAnirudh Venkataramanan 
4006d76a60baSAnirudh Venkataramanan 	if (!v_list || !hw)
4007d54699e2STony Nguyen 		return -EINVAL;
4008d76a60baSAnirudh Venkataramanan 
4009072f0c3dSDave Ertman 	list_for_each_entry_safe(v_list_itr, tmp, v_list, list_entry) {
401080d144c9SAnirudh Venkataramanan 		enum ice_sw_lkup_type l_type = v_list_itr->fltr_info.lkup_type;
401180d144c9SAnirudh Venkataramanan 
401280d144c9SAnirudh Venkataramanan 		if (l_type != ICE_SW_LKUP_VLAN)
4013d54699e2STony Nguyen 			return -EINVAL;
401480d144c9SAnirudh Venkataramanan 		v_list_itr->status = ice_remove_rule_internal(hw,
401580d144c9SAnirudh Venkataramanan 							      ICE_SW_LKUP_VLAN,
401680d144c9SAnirudh Venkataramanan 							      v_list_itr);
401780d144c9SAnirudh Venkataramanan 		if (v_list_itr->status)
401880d144c9SAnirudh Venkataramanan 			return v_list_itr->status;
4019d76a60baSAnirudh Venkataramanan 	}
402080d144c9SAnirudh Venkataramanan 	return 0;
4021d76a60baSAnirudh Venkataramanan }
402280d144c9SAnirudh Venkataramanan 
402380d144c9SAnirudh Venkataramanan /**
402480d144c9SAnirudh Venkataramanan  * ice_add_entry_to_vsi_fltr_list - Add copy of fltr_list_entry to remove list
402580d144c9SAnirudh Venkataramanan  * @hw: pointer to the hardware structure
40265726ca0eSAnirudh Venkataramanan  * @vsi_handle: VSI handle to remove filters from
402780d144c9SAnirudh Venkataramanan  * @vsi_list_head: pointer to the list to add entry to
402880d144c9SAnirudh Venkataramanan  * @fi: pointer to fltr_info of filter entry to copy & add
402980d144c9SAnirudh Venkataramanan  *
403080d144c9SAnirudh Venkataramanan  * Helper function, used when creating a list of filters to remove from
403180d144c9SAnirudh Venkataramanan  * a specific VSI. The entry added to vsi_list_head is a COPY of the
403280d144c9SAnirudh Venkataramanan  * original filter entry, with the exception of fltr_info.fltr_act and
403380d144c9SAnirudh Venkataramanan  * fltr_info.fwd_id fields. These are set such that later logic can
403480d144c9SAnirudh Venkataramanan  * extract which VSI to remove the fltr from, and pass on that information.
403580d144c9SAnirudh Venkataramanan  */
40365e24d598STony Nguyen static int
40375726ca0eSAnirudh Venkataramanan ice_add_entry_to_vsi_fltr_list(struct ice_hw *hw, u16 vsi_handle,
403880d144c9SAnirudh Venkataramanan 			       struct list_head *vsi_list_head,
403980d144c9SAnirudh Venkataramanan 			       struct ice_fltr_info *fi)
404080d144c9SAnirudh Venkataramanan {
404180d144c9SAnirudh Venkataramanan 	struct ice_fltr_list_entry *tmp;
404280d144c9SAnirudh Venkataramanan 
404380d144c9SAnirudh Venkataramanan 	/* this memory is freed up in the caller function
404480d144c9SAnirudh Venkataramanan 	 * once filters for this VSI are removed
404580d144c9SAnirudh Venkataramanan 	 */
404680d144c9SAnirudh Venkataramanan 	tmp = devm_kzalloc(ice_hw_to_dev(hw), sizeof(*tmp), GFP_KERNEL);
404780d144c9SAnirudh Venkataramanan 	if (!tmp)
4048d54699e2STony Nguyen 		return -ENOMEM;
404980d144c9SAnirudh Venkataramanan 
405080d144c9SAnirudh Venkataramanan 	tmp->fltr_info = *fi;
405180d144c9SAnirudh Venkataramanan 
405280d144c9SAnirudh Venkataramanan 	/* Overwrite these fields to indicate which VSI to remove filter from,
405380d144c9SAnirudh Venkataramanan 	 * so find and remove logic can extract the information from the
405480d144c9SAnirudh Venkataramanan 	 * list entries. Note that original entries will still have proper
405580d144c9SAnirudh Venkataramanan 	 * values.
405680d144c9SAnirudh Venkataramanan 	 */
405780d144c9SAnirudh Venkataramanan 	tmp->fltr_info.fltr_act = ICE_FWD_TO_VSI;
40585726ca0eSAnirudh Venkataramanan 	tmp->fltr_info.vsi_handle = vsi_handle;
40595726ca0eSAnirudh Venkataramanan 	tmp->fltr_info.fwd_id.hw_vsi_id = ice_get_hw_vsi_num(hw, vsi_handle);
406080d144c9SAnirudh Venkataramanan 
406180d144c9SAnirudh Venkataramanan 	list_add(&tmp->list_entry, vsi_list_head);
406280d144c9SAnirudh Venkataramanan 
406380d144c9SAnirudh Venkataramanan 	return 0;
4064d76a60baSAnirudh Venkataramanan }
4065d76a60baSAnirudh Venkataramanan 
4066d76a60baSAnirudh Venkataramanan /**
40679daf8208SAnirudh Venkataramanan  * ice_add_to_vsi_fltr_list - Add VSI filters to the list
40689daf8208SAnirudh Venkataramanan  * @hw: pointer to the hardware structure
40695726ca0eSAnirudh Venkataramanan  * @vsi_handle: VSI handle to remove filters from
40709daf8208SAnirudh Venkataramanan  * @lkup_list_head: pointer to the list that has certain lookup type filters
40715726ca0eSAnirudh Venkataramanan  * @vsi_list_head: pointer to the list pertaining to VSI with vsi_handle
407280d144c9SAnirudh Venkataramanan  *
407380d144c9SAnirudh Venkataramanan  * Locates all filters in lkup_list_head that are used by the given VSI,
407480d144c9SAnirudh Venkataramanan  * and adds COPIES of those entries to vsi_list_head (intended to be used
407580d144c9SAnirudh Venkataramanan  * to remove the listed filters).
407680d144c9SAnirudh Venkataramanan  * Note that this means all entries in vsi_list_head must be explicitly
407780d144c9SAnirudh Venkataramanan  * deallocated by the caller when done with list.
40789daf8208SAnirudh Venkataramanan  */
40795e24d598STony Nguyen static int
40805726ca0eSAnirudh Venkataramanan ice_add_to_vsi_fltr_list(struct ice_hw *hw, u16 vsi_handle,
40819daf8208SAnirudh Venkataramanan 			 struct list_head *lkup_list_head,
40829daf8208SAnirudh Venkataramanan 			 struct list_head *vsi_list_head)
40839daf8208SAnirudh Venkataramanan {
40849daf8208SAnirudh Venkataramanan 	struct ice_fltr_mgmt_list_entry *fm_entry;
40855e24d598STony Nguyen 	int status = 0;
40869daf8208SAnirudh Venkataramanan 
4087f9867df6SAnirudh Venkataramanan 	/* check to make sure VSI ID is valid and within boundary */
40885726ca0eSAnirudh Venkataramanan 	if (!ice_is_vsi_valid(hw, vsi_handle))
4089d54699e2STony Nguyen 		return -EINVAL;
40909daf8208SAnirudh Venkataramanan 
40919daf8208SAnirudh Venkataramanan 	list_for_each_entry(fm_entry, lkup_list_head, list_entry) {
40927a91d3f0SJacek Bułatek 		if (!ice_vsi_uses_fltr(fm_entry, vsi_handle))
409380d144c9SAnirudh Venkataramanan 			continue;
40949daf8208SAnirudh Venkataramanan 
40955726ca0eSAnirudh Venkataramanan 		status = ice_add_entry_to_vsi_fltr_list(hw, vsi_handle,
40967a91d3f0SJacek Bułatek 							vsi_list_head,
40977a91d3f0SJacek Bułatek 							&fm_entry->fltr_info);
409880d144c9SAnirudh Venkataramanan 		if (status)
409980d144c9SAnirudh Venkataramanan 			return status;
41009daf8208SAnirudh Venkataramanan 	}
410180d144c9SAnirudh Venkataramanan 	return status;
41029daf8208SAnirudh Venkataramanan }
41039daf8208SAnirudh Venkataramanan 
41049daf8208SAnirudh Venkataramanan /**
41055eda8afdSAkeem G Abodunrin  * ice_determine_promisc_mask
41065eda8afdSAkeem G Abodunrin  * @fi: filter info to parse
41075eda8afdSAkeem G Abodunrin  *
41085eda8afdSAkeem G Abodunrin  * Helper function to determine which ICE_PROMISC_ mask corresponds
41095eda8afdSAkeem G Abodunrin  * to given filter into.
41105eda8afdSAkeem G Abodunrin  */
41115eda8afdSAkeem G Abodunrin static u8 ice_determine_promisc_mask(struct ice_fltr_info *fi)
41125eda8afdSAkeem G Abodunrin {
41135eda8afdSAkeem G Abodunrin 	u16 vid = fi->l_data.mac_vlan.vlan_id;
41145eda8afdSAkeem G Abodunrin 	u8 *macaddr = fi->l_data.mac.mac_addr;
41155eda8afdSAkeem G Abodunrin 	bool is_tx_fltr = false;
41165eda8afdSAkeem G Abodunrin 	u8 promisc_mask = 0;
41175eda8afdSAkeem G Abodunrin 
41185eda8afdSAkeem G Abodunrin 	if (fi->flag == ICE_FLTR_TX)
41195eda8afdSAkeem G Abodunrin 		is_tx_fltr = true;
41205eda8afdSAkeem G Abodunrin 
41215eda8afdSAkeem G Abodunrin 	if (is_broadcast_ether_addr(macaddr))
41225eda8afdSAkeem G Abodunrin 		promisc_mask |= is_tx_fltr ?
41235eda8afdSAkeem G Abodunrin 			ICE_PROMISC_BCAST_TX : ICE_PROMISC_BCAST_RX;
41245eda8afdSAkeem G Abodunrin 	else if (is_multicast_ether_addr(macaddr))
41255eda8afdSAkeem G Abodunrin 		promisc_mask |= is_tx_fltr ?
41265eda8afdSAkeem G Abodunrin 			ICE_PROMISC_MCAST_TX : ICE_PROMISC_MCAST_RX;
41275eda8afdSAkeem G Abodunrin 	else if (is_unicast_ether_addr(macaddr))
41285eda8afdSAkeem G Abodunrin 		promisc_mask |= is_tx_fltr ?
41295eda8afdSAkeem G Abodunrin 			ICE_PROMISC_UCAST_TX : ICE_PROMISC_UCAST_RX;
41305eda8afdSAkeem G Abodunrin 	if (vid)
41315eda8afdSAkeem G Abodunrin 		promisc_mask |= is_tx_fltr ?
41325eda8afdSAkeem G Abodunrin 			ICE_PROMISC_VLAN_TX : ICE_PROMISC_VLAN_RX;
41335eda8afdSAkeem G Abodunrin 
41345eda8afdSAkeem G Abodunrin 	return promisc_mask;
41355eda8afdSAkeem G Abodunrin }
41365eda8afdSAkeem G Abodunrin 
41375eda8afdSAkeem G Abodunrin /**
41385eda8afdSAkeem G Abodunrin  * ice_remove_promisc - Remove promisc based filter rules
41395eda8afdSAkeem G Abodunrin  * @hw: pointer to the hardware structure
4140f9867df6SAnirudh Venkataramanan  * @recp_id: recipe ID for which the rule needs to removed
41415eda8afdSAkeem G Abodunrin  * @v_list: list of promisc entries
41425eda8afdSAkeem G Abodunrin  */
41435e24d598STony Nguyen static int
41445518ac2aSTony Nguyen ice_remove_promisc(struct ice_hw *hw, u8 recp_id, struct list_head *v_list)
41455eda8afdSAkeem G Abodunrin {
41465eda8afdSAkeem G Abodunrin 	struct ice_fltr_list_entry *v_list_itr, *tmp;
41475eda8afdSAkeem G Abodunrin 
41485eda8afdSAkeem G Abodunrin 	list_for_each_entry_safe(v_list_itr, tmp, v_list, list_entry) {
41495eda8afdSAkeem G Abodunrin 		v_list_itr->status =
41505eda8afdSAkeem G Abodunrin 			ice_remove_rule_internal(hw, recp_id, v_list_itr);
41515eda8afdSAkeem G Abodunrin 		if (v_list_itr->status)
41525eda8afdSAkeem G Abodunrin 			return v_list_itr->status;
41535eda8afdSAkeem G Abodunrin 	}
41545eda8afdSAkeem G Abodunrin 	return 0;
41555eda8afdSAkeem G Abodunrin }
41565eda8afdSAkeem G Abodunrin 
41575eda8afdSAkeem G Abodunrin /**
41585eda8afdSAkeem G Abodunrin  * ice_clear_vsi_promisc - clear specified promiscuous mode(s) for given VSI
41595eda8afdSAkeem G Abodunrin  * @hw: pointer to the hardware structure
41605eda8afdSAkeem G Abodunrin  * @vsi_handle: VSI handle to clear mode
41615eda8afdSAkeem G Abodunrin  * @promisc_mask: mask of promiscuous config bits to clear
41625eda8afdSAkeem G Abodunrin  * @vid: VLAN ID to clear VLAN promiscuous
41635eda8afdSAkeem G Abodunrin  */
41645e24d598STony Nguyen int
41655eda8afdSAkeem G Abodunrin ice_clear_vsi_promisc(struct ice_hw *hw, u16 vsi_handle, u8 promisc_mask,
41665eda8afdSAkeem G Abodunrin 		      u16 vid)
41675eda8afdSAkeem G Abodunrin {
41685eda8afdSAkeem G Abodunrin 	struct ice_switch_info *sw = hw->switch_info;
41695eda8afdSAkeem G Abodunrin 	struct ice_fltr_list_entry *fm_entry, *tmp;
41705eda8afdSAkeem G Abodunrin 	struct list_head remove_list_head;
41715eda8afdSAkeem G Abodunrin 	struct ice_fltr_mgmt_list_entry *itr;
41725eda8afdSAkeem G Abodunrin 	struct list_head *rule_head;
41735eda8afdSAkeem G Abodunrin 	struct mutex *rule_lock;	/* Lock to protect filter rule list */
41745e24d598STony Nguyen 	int status = 0;
41755eda8afdSAkeem G Abodunrin 	u8 recipe_id;
41765eda8afdSAkeem G Abodunrin 
41775eda8afdSAkeem G Abodunrin 	if (!ice_is_vsi_valid(hw, vsi_handle))
4178d54699e2STony Nguyen 		return -EINVAL;
41795eda8afdSAkeem G Abodunrin 
41801bc7a4abSBrett Creeley 	if (promisc_mask & (ICE_PROMISC_VLAN_RX | ICE_PROMISC_VLAN_TX))
41815eda8afdSAkeem G Abodunrin 		recipe_id = ICE_SW_LKUP_PROMISC_VLAN;
41825eda8afdSAkeem G Abodunrin 	else
41835eda8afdSAkeem G Abodunrin 		recipe_id = ICE_SW_LKUP_PROMISC;
41845eda8afdSAkeem G Abodunrin 
41855eda8afdSAkeem G Abodunrin 	rule_head = &sw->recp_list[recipe_id].filt_rules;
41865eda8afdSAkeem G Abodunrin 	rule_lock = &sw->recp_list[recipe_id].filt_rule_lock;
41875eda8afdSAkeem G Abodunrin 
41885eda8afdSAkeem G Abodunrin 	INIT_LIST_HEAD(&remove_list_head);
41895eda8afdSAkeem G Abodunrin 
41905eda8afdSAkeem G Abodunrin 	mutex_lock(rule_lock);
41915eda8afdSAkeem G Abodunrin 	list_for_each_entry(itr, rule_head, list_entry) {
41921bc7a4abSBrett Creeley 		struct ice_fltr_info *fltr_info;
41935eda8afdSAkeem G Abodunrin 		u8 fltr_promisc_mask = 0;
41945eda8afdSAkeem G Abodunrin 
41955eda8afdSAkeem G Abodunrin 		if (!ice_vsi_uses_fltr(itr, vsi_handle))
41965eda8afdSAkeem G Abodunrin 			continue;
41971bc7a4abSBrett Creeley 		fltr_info = &itr->fltr_info;
41985eda8afdSAkeem G Abodunrin 
41991bc7a4abSBrett Creeley 		if (recipe_id == ICE_SW_LKUP_PROMISC_VLAN &&
42001bc7a4abSBrett Creeley 		    vid != fltr_info->l_data.mac_vlan.vlan_id)
42011bc7a4abSBrett Creeley 			continue;
42021bc7a4abSBrett Creeley 
42031bc7a4abSBrett Creeley 		fltr_promisc_mask |= ice_determine_promisc_mask(fltr_info);
42045eda8afdSAkeem G Abodunrin 
42055eda8afdSAkeem G Abodunrin 		/* Skip if filter is not completely specified by given mask */
42065eda8afdSAkeem G Abodunrin 		if (fltr_promisc_mask & ~promisc_mask)
42075eda8afdSAkeem G Abodunrin 			continue;
42085eda8afdSAkeem G Abodunrin 
42095eda8afdSAkeem G Abodunrin 		status = ice_add_entry_to_vsi_fltr_list(hw, vsi_handle,
42105eda8afdSAkeem G Abodunrin 							&remove_list_head,
42111bc7a4abSBrett Creeley 							fltr_info);
42125eda8afdSAkeem G Abodunrin 		if (status) {
42135eda8afdSAkeem G Abodunrin 			mutex_unlock(rule_lock);
42145eda8afdSAkeem G Abodunrin 			goto free_fltr_list;
42155eda8afdSAkeem G Abodunrin 		}
42165eda8afdSAkeem G Abodunrin 	}
42175eda8afdSAkeem G Abodunrin 	mutex_unlock(rule_lock);
42185eda8afdSAkeem G Abodunrin 
42195eda8afdSAkeem G Abodunrin 	status = ice_remove_promisc(hw, recipe_id, &remove_list_head);
42205eda8afdSAkeem G Abodunrin 
42215eda8afdSAkeem G Abodunrin free_fltr_list:
42225eda8afdSAkeem G Abodunrin 	list_for_each_entry_safe(fm_entry, tmp, &remove_list_head, list_entry) {
42235eda8afdSAkeem G Abodunrin 		list_del(&fm_entry->list_entry);
42245eda8afdSAkeem G Abodunrin 		devm_kfree(ice_hw_to_dev(hw), fm_entry);
42255eda8afdSAkeem G Abodunrin 	}
42265eda8afdSAkeem G Abodunrin 
42275eda8afdSAkeem G Abodunrin 	return status;
42285eda8afdSAkeem G Abodunrin }
42295eda8afdSAkeem G Abodunrin 
42305eda8afdSAkeem G Abodunrin /**
42315eda8afdSAkeem G Abodunrin  * ice_set_vsi_promisc - set given VSI to given promiscuous mode(s)
42325eda8afdSAkeem G Abodunrin  * @hw: pointer to the hardware structure
42335eda8afdSAkeem G Abodunrin  * @vsi_handle: VSI handle to configure
42345eda8afdSAkeem G Abodunrin  * @promisc_mask: mask of promiscuous config bits
42355eda8afdSAkeem G Abodunrin  * @vid: VLAN ID to set VLAN promiscuous
42365eda8afdSAkeem G Abodunrin  */
42375e24d598STony Nguyen int
42385eda8afdSAkeem G Abodunrin ice_set_vsi_promisc(struct ice_hw *hw, u16 vsi_handle, u8 promisc_mask, u16 vid)
42395eda8afdSAkeem G Abodunrin {
42405eda8afdSAkeem G Abodunrin 	enum { UCAST_FLTR = 1, MCAST_FLTR, BCAST_FLTR };
42415eda8afdSAkeem G Abodunrin 	struct ice_fltr_list_entry f_list_entry;
42425eda8afdSAkeem G Abodunrin 	struct ice_fltr_info new_fltr;
42435eda8afdSAkeem G Abodunrin 	bool is_tx_fltr;
42445518ac2aSTony Nguyen 	int status = 0;
42455eda8afdSAkeem G Abodunrin 	u16 hw_vsi_id;
42465eda8afdSAkeem G Abodunrin 	int pkt_type;
42475eda8afdSAkeem G Abodunrin 	u8 recipe_id;
42485eda8afdSAkeem G Abodunrin 
42495eda8afdSAkeem G Abodunrin 	if (!ice_is_vsi_valid(hw, vsi_handle))
4250d54699e2STony Nguyen 		return -EINVAL;
42515eda8afdSAkeem G Abodunrin 	hw_vsi_id = ice_get_hw_vsi_num(hw, vsi_handle);
42525eda8afdSAkeem G Abodunrin 
42535eda8afdSAkeem G Abodunrin 	memset(&new_fltr, 0, sizeof(new_fltr));
42545eda8afdSAkeem G Abodunrin 
42555eda8afdSAkeem G Abodunrin 	if (promisc_mask & (ICE_PROMISC_VLAN_RX | ICE_PROMISC_VLAN_TX)) {
42565eda8afdSAkeem G Abodunrin 		new_fltr.lkup_type = ICE_SW_LKUP_PROMISC_VLAN;
42575eda8afdSAkeem G Abodunrin 		new_fltr.l_data.mac_vlan.vlan_id = vid;
42585eda8afdSAkeem G Abodunrin 		recipe_id = ICE_SW_LKUP_PROMISC_VLAN;
42595eda8afdSAkeem G Abodunrin 	} else {
42605eda8afdSAkeem G Abodunrin 		new_fltr.lkup_type = ICE_SW_LKUP_PROMISC;
42615eda8afdSAkeem G Abodunrin 		recipe_id = ICE_SW_LKUP_PROMISC;
42625eda8afdSAkeem G Abodunrin 	}
42635eda8afdSAkeem G Abodunrin 
42645eda8afdSAkeem G Abodunrin 	/* Separate filters must be set for each direction/packet type
42655eda8afdSAkeem G Abodunrin 	 * combination, so we will loop over the mask value, store the
42665eda8afdSAkeem G Abodunrin 	 * individual type, and clear it out in the input mask as it
42675eda8afdSAkeem G Abodunrin 	 * is found.
42685eda8afdSAkeem G Abodunrin 	 */
42695eda8afdSAkeem G Abodunrin 	while (promisc_mask) {
42705eda8afdSAkeem G Abodunrin 		u8 *mac_addr;
42715eda8afdSAkeem G Abodunrin 
42725eda8afdSAkeem G Abodunrin 		pkt_type = 0;
42735eda8afdSAkeem G Abodunrin 		is_tx_fltr = false;
42745eda8afdSAkeem G Abodunrin 
42755eda8afdSAkeem G Abodunrin 		if (promisc_mask & ICE_PROMISC_UCAST_RX) {
42765eda8afdSAkeem G Abodunrin 			promisc_mask &= ~ICE_PROMISC_UCAST_RX;
42775eda8afdSAkeem G Abodunrin 			pkt_type = UCAST_FLTR;
42785eda8afdSAkeem G Abodunrin 		} else if (promisc_mask & ICE_PROMISC_UCAST_TX) {
42795eda8afdSAkeem G Abodunrin 			promisc_mask &= ~ICE_PROMISC_UCAST_TX;
42805eda8afdSAkeem G Abodunrin 			pkt_type = UCAST_FLTR;
42815eda8afdSAkeem G Abodunrin 			is_tx_fltr = true;
42825eda8afdSAkeem G Abodunrin 		} else if (promisc_mask & ICE_PROMISC_MCAST_RX) {
42835eda8afdSAkeem G Abodunrin 			promisc_mask &= ~ICE_PROMISC_MCAST_RX;
42845eda8afdSAkeem G Abodunrin 			pkt_type = MCAST_FLTR;
42855eda8afdSAkeem G Abodunrin 		} else if (promisc_mask & ICE_PROMISC_MCAST_TX) {
42865eda8afdSAkeem G Abodunrin 			promisc_mask &= ~ICE_PROMISC_MCAST_TX;
42875eda8afdSAkeem G Abodunrin 			pkt_type = MCAST_FLTR;
42885eda8afdSAkeem G Abodunrin 			is_tx_fltr = true;
42895eda8afdSAkeem G Abodunrin 		} else if (promisc_mask & ICE_PROMISC_BCAST_RX) {
42905eda8afdSAkeem G Abodunrin 			promisc_mask &= ~ICE_PROMISC_BCAST_RX;
42915eda8afdSAkeem G Abodunrin 			pkt_type = BCAST_FLTR;
42925eda8afdSAkeem G Abodunrin 		} else if (promisc_mask & ICE_PROMISC_BCAST_TX) {
42935eda8afdSAkeem G Abodunrin 			promisc_mask &= ~ICE_PROMISC_BCAST_TX;
42945eda8afdSAkeem G Abodunrin 			pkt_type = BCAST_FLTR;
42955eda8afdSAkeem G Abodunrin 			is_tx_fltr = true;
42965eda8afdSAkeem G Abodunrin 		}
42975eda8afdSAkeem G Abodunrin 
42985eda8afdSAkeem G Abodunrin 		/* Check for VLAN promiscuous flag */
42995eda8afdSAkeem G Abodunrin 		if (promisc_mask & ICE_PROMISC_VLAN_RX) {
43005eda8afdSAkeem G Abodunrin 			promisc_mask &= ~ICE_PROMISC_VLAN_RX;
43015eda8afdSAkeem G Abodunrin 		} else if (promisc_mask & ICE_PROMISC_VLAN_TX) {
43025eda8afdSAkeem G Abodunrin 			promisc_mask &= ~ICE_PROMISC_VLAN_TX;
43035eda8afdSAkeem G Abodunrin 			is_tx_fltr = true;
43045eda8afdSAkeem G Abodunrin 		}
43055eda8afdSAkeem G Abodunrin 
43065eda8afdSAkeem G Abodunrin 		/* Set filter DA based on packet type */
43075eda8afdSAkeem G Abodunrin 		mac_addr = new_fltr.l_data.mac.mac_addr;
43085eda8afdSAkeem G Abodunrin 		if (pkt_type == BCAST_FLTR) {
43095eda8afdSAkeem G Abodunrin 			eth_broadcast_addr(mac_addr);
43105eda8afdSAkeem G Abodunrin 		} else if (pkt_type == MCAST_FLTR ||
43115eda8afdSAkeem G Abodunrin 			   pkt_type == UCAST_FLTR) {
43125eda8afdSAkeem G Abodunrin 			/* Use the dummy ether header DA */
43135eda8afdSAkeem G Abodunrin 			ether_addr_copy(mac_addr, dummy_eth_header);
43145eda8afdSAkeem G Abodunrin 			if (pkt_type == MCAST_FLTR)
43155eda8afdSAkeem G Abodunrin 				mac_addr[0] |= 0x1;	/* Set multicast bit */
43165eda8afdSAkeem G Abodunrin 		}
43175eda8afdSAkeem G Abodunrin 
43185eda8afdSAkeem G Abodunrin 		/* Need to reset this to zero for all iterations */
43195eda8afdSAkeem G Abodunrin 		new_fltr.flag = 0;
43205eda8afdSAkeem G Abodunrin 		if (is_tx_fltr) {
43215eda8afdSAkeem G Abodunrin 			new_fltr.flag |= ICE_FLTR_TX;
43225eda8afdSAkeem G Abodunrin 			new_fltr.src = hw_vsi_id;
43235eda8afdSAkeem G Abodunrin 		} else {
43245eda8afdSAkeem G Abodunrin 			new_fltr.flag |= ICE_FLTR_RX;
43255eda8afdSAkeem G Abodunrin 			new_fltr.src = hw->port_info->lport;
43265eda8afdSAkeem G Abodunrin 		}
43275eda8afdSAkeem G Abodunrin 
43285eda8afdSAkeem G Abodunrin 		new_fltr.fltr_act = ICE_FWD_TO_VSI;
43295eda8afdSAkeem G Abodunrin 		new_fltr.vsi_handle = vsi_handle;
43305eda8afdSAkeem G Abodunrin 		new_fltr.fwd_id.hw_vsi_id = hw_vsi_id;
43315eda8afdSAkeem G Abodunrin 		f_list_entry.fltr_info = new_fltr;
43325eda8afdSAkeem G Abodunrin 
43335eda8afdSAkeem G Abodunrin 		status = ice_add_rule_internal(hw, recipe_id, &f_list_entry);
43345eda8afdSAkeem G Abodunrin 		if (status)
43355eda8afdSAkeem G Abodunrin 			goto set_promisc_exit;
43365eda8afdSAkeem G Abodunrin 	}
43375eda8afdSAkeem G Abodunrin 
43385eda8afdSAkeem G Abodunrin set_promisc_exit:
43395eda8afdSAkeem G Abodunrin 	return status;
43405eda8afdSAkeem G Abodunrin }
43415eda8afdSAkeem G Abodunrin 
43425eda8afdSAkeem G Abodunrin /**
43435eda8afdSAkeem G Abodunrin  * ice_set_vlan_vsi_promisc
43445eda8afdSAkeem G Abodunrin  * @hw: pointer to the hardware structure
43455eda8afdSAkeem G Abodunrin  * @vsi_handle: VSI handle to configure
43465eda8afdSAkeem G Abodunrin  * @promisc_mask: mask of promiscuous config bits
43475eda8afdSAkeem G Abodunrin  * @rm_vlan_promisc: Clear VLANs VSI promisc mode
43485eda8afdSAkeem G Abodunrin  *
43495eda8afdSAkeem G Abodunrin  * Configure VSI with all associated VLANs to given promiscuous mode(s)
43505eda8afdSAkeem G Abodunrin  */
43515e24d598STony Nguyen int
43525eda8afdSAkeem G Abodunrin ice_set_vlan_vsi_promisc(struct ice_hw *hw, u16 vsi_handle, u8 promisc_mask,
43535eda8afdSAkeem G Abodunrin 			 bool rm_vlan_promisc)
43545eda8afdSAkeem G Abodunrin {
43555eda8afdSAkeem G Abodunrin 	struct ice_switch_info *sw = hw->switch_info;
43565eda8afdSAkeem G Abodunrin 	struct ice_fltr_list_entry *list_itr, *tmp;
43575eda8afdSAkeem G Abodunrin 	struct list_head vsi_list_head;
43585eda8afdSAkeem G Abodunrin 	struct list_head *vlan_head;
43595eda8afdSAkeem G Abodunrin 	struct mutex *vlan_lock; /* Lock to protect filter rule list */
43605eda8afdSAkeem G Abodunrin 	u16 vlan_id;
43615518ac2aSTony Nguyen 	int status;
43625eda8afdSAkeem G Abodunrin 
43635eda8afdSAkeem G Abodunrin 	INIT_LIST_HEAD(&vsi_list_head);
43645eda8afdSAkeem G Abodunrin 	vlan_lock = &sw->recp_list[ICE_SW_LKUP_VLAN].filt_rule_lock;
43655eda8afdSAkeem G Abodunrin 	vlan_head = &sw->recp_list[ICE_SW_LKUP_VLAN].filt_rules;
43665eda8afdSAkeem G Abodunrin 	mutex_lock(vlan_lock);
43675eda8afdSAkeem G Abodunrin 	status = ice_add_to_vsi_fltr_list(hw, vsi_handle, vlan_head,
43685eda8afdSAkeem G Abodunrin 					  &vsi_list_head);
43695eda8afdSAkeem G Abodunrin 	mutex_unlock(vlan_lock);
43705eda8afdSAkeem G Abodunrin 	if (status)
43715eda8afdSAkeem G Abodunrin 		goto free_fltr_list;
43725eda8afdSAkeem G Abodunrin 
43735eda8afdSAkeem G Abodunrin 	list_for_each_entry(list_itr, &vsi_list_head, list_entry) {
4374ffa9ed86SGrzegorz Siwik 		/* Avoid enabling or disabling VLAN zero twice when in double
4375ffa9ed86SGrzegorz Siwik 		 * VLAN mode
4376ffa9ed86SGrzegorz Siwik 		 */
4377ffa9ed86SGrzegorz Siwik 		if (ice_is_dvm_ena(hw) &&
4378ffa9ed86SGrzegorz Siwik 		    list_itr->fltr_info.l_data.vlan.tpid == 0)
4379ffa9ed86SGrzegorz Siwik 			continue;
4380ffa9ed86SGrzegorz Siwik 
43815eda8afdSAkeem G Abodunrin 		vlan_id = list_itr->fltr_info.l_data.vlan.vlan_id;
43825eda8afdSAkeem G Abodunrin 		if (rm_vlan_promisc)
43835eda8afdSAkeem G Abodunrin 			status = ice_clear_vsi_promisc(hw, vsi_handle,
43845eda8afdSAkeem G Abodunrin 						       promisc_mask, vlan_id);
43855eda8afdSAkeem G Abodunrin 		else
43865eda8afdSAkeem G Abodunrin 			status = ice_set_vsi_promisc(hw, vsi_handle,
43875eda8afdSAkeem G Abodunrin 						     promisc_mask, vlan_id);
438811e551a2SGrzegorz Siwik 		if (status && status != -EEXIST)
43895eda8afdSAkeem G Abodunrin 			break;
43905eda8afdSAkeem G Abodunrin 	}
43915eda8afdSAkeem G Abodunrin 
43925eda8afdSAkeem G Abodunrin free_fltr_list:
43935eda8afdSAkeem G Abodunrin 	list_for_each_entry_safe(list_itr, tmp, &vsi_list_head, list_entry) {
43945eda8afdSAkeem G Abodunrin 		list_del(&list_itr->list_entry);
43955eda8afdSAkeem G Abodunrin 		devm_kfree(ice_hw_to_dev(hw), list_itr);
43965eda8afdSAkeem G Abodunrin 	}
43975eda8afdSAkeem G Abodunrin 	return status;
43985eda8afdSAkeem G Abodunrin }
43995eda8afdSAkeem G Abodunrin 
44005eda8afdSAkeem G Abodunrin /**
44019daf8208SAnirudh Venkataramanan  * ice_remove_vsi_lkup_fltr - Remove lookup type filters for a VSI
44029daf8208SAnirudh Venkataramanan  * @hw: pointer to the hardware structure
44035726ca0eSAnirudh Venkataramanan  * @vsi_handle: VSI handle to remove filters from
44049daf8208SAnirudh Venkataramanan  * @lkup: switch rule filter lookup type
44059daf8208SAnirudh Venkataramanan  */
44069daf8208SAnirudh Venkataramanan static void
44075726ca0eSAnirudh Venkataramanan ice_remove_vsi_lkup_fltr(struct ice_hw *hw, u16 vsi_handle,
44089daf8208SAnirudh Venkataramanan 			 enum ice_sw_lkup_type lkup)
44099daf8208SAnirudh Venkataramanan {
44109daf8208SAnirudh Venkataramanan 	struct ice_switch_info *sw = hw->switch_info;
44119daf8208SAnirudh Venkataramanan 	struct ice_fltr_list_entry *fm_entry;
44129daf8208SAnirudh Venkataramanan 	struct list_head remove_list_head;
441380d144c9SAnirudh Venkataramanan 	struct list_head *rule_head;
44149daf8208SAnirudh Venkataramanan 	struct ice_fltr_list_entry *tmp;
441580d144c9SAnirudh Venkataramanan 	struct mutex *rule_lock;	/* Lock to protect filter rule list */
44165e24d598STony Nguyen 	int status;
44179daf8208SAnirudh Venkataramanan 
44189daf8208SAnirudh Venkataramanan 	INIT_LIST_HEAD(&remove_list_head);
441980d144c9SAnirudh Venkataramanan 	rule_lock = &sw->recp_list[lkup].filt_rule_lock;
442080d144c9SAnirudh Venkataramanan 	rule_head = &sw->recp_list[lkup].filt_rules;
442180d144c9SAnirudh Venkataramanan 	mutex_lock(rule_lock);
44225726ca0eSAnirudh Venkataramanan 	status = ice_add_to_vsi_fltr_list(hw, vsi_handle, rule_head,
442380d144c9SAnirudh Venkataramanan 					  &remove_list_head);
442480d144c9SAnirudh Venkataramanan 	mutex_unlock(rule_lock);
442580d144c9SAnirudh Venkataramanan 	if (status)
4426b7eeb527SRobert Malz 		goto free_fltr_list;
442780d144c9SAnirudh Venkataramanan 
44289daf8208SAnirudh Venkataramanan 	switch (lkup) {
44299daf8208SAnirudh Venkataramanan 	case ICE_SW_LKUP_MAC:
44309daf8208SAnirudh Venkataramanan 		ice_remove_mac(hw, &remove_list_head);
44319daf8208SAnirudh Venkataramanan 		break;
44329daf8208SAnirudh Venkataramanan 	case ICE_SW_LKUP_VLAN:
4433d76a60baSAnirudh Venkataramanan 		ice_remove_vlan(hw, &remove_list_head);
4434d76a60baSAnirudh Venkataramanan 		break;
44355eda8afdSAkeem G Abodunrin 	case ICE_SW_LKUP_PROMISC:
44365eda8afdSAkeem G Abodunrin 	case ICE_SW_LKUP_PROMISC_VLAN:
44375eda8afdSAkeem G Abodunrin 		ice_remove_promisc(hw, lkup, &remove_list_head);
44385eda8afdSAkeem G Abodunrin 		break;
44399daf8208SAnirudh Venkataramanan 	case ICE_SW_LKUP_MAC_VLAN:
44409daf8208SAnirudh Venkataramanan 	case ICE_SW_LKUP_ETHERTYPE:
44419daf8208SAnirudh Venkataramanan 	case ICE_SW_LKUP_ETHERTYPE_MAC:
44429daf8208SAnirudh Venkataramanan 	case ICE_SW_LKUP_DFLT:
444380d144c9SAnirudh Venkataramanan 	case ICE_SW_LKUP_LAST:
444480d144c9SAnirudh Venkataramanan 	default:
444580d144c9SAnirudh Venkataramanan 		ice_debug(hw, ICE_DBG_SW, "Unsupported lookup type %d\n", lkup);
44469daf8208SAnirudh Venkataramanan 		break;
44479daf8208SAnirudh Venkataramanan 	}
44489daf8208SAnirudh Venkataramanan 
4449b7eeb527SRobert Malz free_fltr_list:
44509daf8208SAnirudh Venkataramanan 	list_for_each_entry_safe(fm_entry, tmp, &remove_list_head, list_entry) {
44519daf8208SAnirudh Venkataramanan 		list_del(&fm_entry->list_entry);
44529daf8208SAnirudh Venkataramanan 		devm_kfree(ice_hw_to_dev(hw), fm_entry);
44539daf8208SAnirudh Venkataramanan 	}
44549daf8208SAnirudh Venkataramanan }
44559daf8208SAnirudh Venkataramanan 
44569daf8208SAnirudh Venkataramanan /**
44579daf8208SAnirudh Venkataramanan  * ice_remove_vsi_fltr - Remove all filters for a VSI
44589daf8208SAnirudh Venkataramanan  * @hw: pointer to the hardware structure
44595726ca0eSAnirudh Venkataramanan  * @vsi_handle: VSI handle to remove filters from
44609daf8208SAnirudh Venkataramanan  */
44615726ca0eSAnirudh Venkataramanan void ice_remove_vsi_fltr(struct ice_hw *hw, u16 vsi_handle)
44629daf8208SAnirudh Venkataramanan {
44635726ca0eSAnirudh Venkataramanan 	ice_remove_vsi_lkup_fltr(hw, vsi_handle, ICE_SW_LKUP_MAC);
44645726ca0eSAnirudh Venkataramanan 	ice_remove_vsi_lkup_fltr(hw, vsi_handle, ICE_SW_LKUP_MAC_VLAN);
44655726ca0eSAnirudh Venkataramanan 	ice_remove_vsi_lkup_fltr(hw, vsi_handle, ICE_SW_LKUP_PROMISC);
44665726ca0eSAnirudh Venkataramanan 	ice_remove_vsi_lkup_fltr(hw, vsi_handle, ICE_SW_LKUP_VLAN);
44675726ca0eSAnirudh Venkataramanan 	ice_remove_vsi_lkup_fltr(hw, vsi_handle, ICE_SW_LKUP_DFLT);
44685726ca0eSAnirudh Venkataramanan 	ice_remove_vsi_lkup_fltr(hw, vsi_handle, ICE_SW_LKUP_ETHERTYPE);
44695726ca0eSAnirudh Venkataramanan 	ice_remove_vsi_lkup_fltr(hw, vsi_handle, ICE_SW_LKUP_ETHERTYPE_MAC);
44705726ca0eSAnirudh Venkataramanan 	ice_remove_vsi_lkup_fltr(hw, vsi_handle, ICE_SW_LKUP_PROMISC_VLAN);
44719daf8208SAnirudh Venkataramanan }
44720f9d5027SAnirudh Venkataramanan 
44730f9d5027SAnirudh Venkataramanan /**
4474148beb61SHenry Tieman  * ice_alloc_res_cntr - allocating resource counter
4475148beb61SHenry Tieman  * @hw: pointer to the hardware structure
4476148beb61SHenry Tieman  * @type: type of resource
4477148beb61SHenry Tieman  * @alloc_shared: if set it is shared else dedicated
4478148beb61SHenry Tieman  * @num_items: number of entries requested for FD resource type
4479148beb61SHenry Tieman  * @counter_id: counter index returned by AQ call
4480148beb61SHenry Tieman  */
44815e24d598STony Nguyen int
4482148beb61SHenry Tieman ice_alloc_res_cntr(struct ice_hw *hw, u8 type, u8 alloc_shared, u16 num_items,
4483148beb61SHenry Tieman 		   u16 *counter_id)
4484148beb61SHenry Tieman {
4485148beb61SHenry Tieman 	struct ice_aqc_alloc_free_res_elem *buf;
4486148beb61SHenry Tieman 	u16 buf_len;
44875518ac2aSTony Nguyen 	int status;
4488148beb61SHenry Tieman 
4489148beb61SHenry Tieman 	/* Allocate resource */
449066486d89SBruce Allan 	buf_len = struct_size(buf, elem, 1);
4491148beb61SHenry Tieman 	buf = kzalloc(buf_len, GFP_KERNEL);
4492148beb61SHenry Tieman 	if (!buf)
4493d54699e2STony Nguyen 		return -ENOMEM;
4494148beb61SHenry Tieman 
4495148beb61SHenry Tieman 	buf->num_elems = cpu_to_le16(num_items);
4496148beb61SHenry Tieman 	buf->res_type = cpu_to_le16(((type << ICE_AQC_RES_TYPE_S) &
4497148beb61SHenry Tieman 				      ICE_AQC_RES_TYPE_M) | alloc_shared);
4498148beb61SHenry Tieman 
4499148beb61SHenry Tieman 	status = ice_aq_alloc_free_res(hw, 1, buf, buf_len,
4500148beb61SHenry Tieman 				       ice_aqc_opc_alloc_res, NULL);
4501148beb61SHenry Tieman 	if (status)
4502148beb61SHenry Tieman 		goto exit;
4503148beb61SHenry Tieman 
4504148beb61SHenry Tieman 	*counter_id = le16_to_cpu(buf->elem[0].e.sw_resp);
4505148beb61SHenry Tieman 
4506148beb61SHenry Tieman exit:
4507148beb61SHenry Tieman 	kfree(buf);
4508148beb61SHenry Tieman 	return status;
4509148beb61SHenry Tieman }
4510148beb61SHenry Tieman 
4511148beb61SHenry Tieman /**
4512148beb61SHenry Tieman  * ice_free_res_cntr - free resource counter
4513148beb61SHenry Tieman  * @hw: pointer to the hardware structure
4514148beb61SHenry Tieman  * @type: type of resource
4515148beb61SHenry Tieman  * @alloc_shared: if set it is shared else dedicated
4516148beb61SHenry Tieman  * @num_items: number of entries to be freed for FD resource type
4517148beb61SHenry Tieman  * @counter_id: counter ID resource which needs to be freed
4518148beb61SHenry Tieman  */
45195e24d598STony Nguyen int
4520148beb61SHenry Tieman ice_free_res_cntr(struct ice_hw *hw, u8 type, u8 alloc_shared, u16 num_items,
4521148beb61SHenry Tieman 		  u16 counter_id)
4522148beb61SHenry Tieman {
4523148beb61SHenry Tieman 	struct ice_aqc_alloc_free_res_elem *buf;
4524148beb61SHenry Tieman 	u16 buf_len;
45255518ac2aSTony Nguyen 	int status;
4526148beb61SHenry Tieman 
4527148beb61SHenry Tieman 	/* Free resource */
452866486d89SBruce Allan 	buf_len = struct_size(buf, elem, 1);
4529148beb61SHenry Tieman 	buf = kzalloc(buf_len, GFP_KERNEL);
4530148beb61SHenry Tieman 	if (!buf)
4531d54699e2STony Nguyen 		return -ENOMEM;
4532148beb61SHenry Tieman 
4533148beb61SHenry Tieman 	buf->num_elems = cpu_to_le16(num_items);
4534148beb61SHenry Tieman 	buf->res_type = cpu_to_le16(((type << ICE_AQC_RES_TYPE_S) &
4535148beb61SHenry Tieman 				      ICE_AQC_RES_TYPE_M) | alloc_shared);
4536148beb61SHenry Tieman 	buf->elem[0].e.sw_resp = cpu_to_le16(counter_id);
4537148beb61SHenry Tieman 
4538148beb61SHenry Tieman 	status = ice_aq_alloc_free_res(hw, 1, buf, buf_len,
4539148beb61SHenry Tieman 				       ice_aqc_opc_free_res, NULL);
4540148beb61SHenry Tieman 	if (status)
45419228d8b2SJacob Keller 		ice_debug(hw, ICE_DBG_SW, "counter resource could not be freed\n");
4542148beb61SHenry Tieman 
4543148beb61SHenry Tieman 	kfree(buf);
4544148beb61SHenry Tieman 	return status;
4545148beb61SHenry Tieman }
4546148beb61SHenry Tieman 
454717c6d835SMichal Swiatkowski #define ICE_PROTOCOL_ENTRY(id, ...) {		\
454817c6d835SMichal Swiatkowski 	.prot_type	= id,			\
454917c6d835SMichal Swiatkowski 	.offs		= {__VA_ARGS__},	\
455017c6d835SMichal Swiatkowski }
455117c6d835SMichal Swiatkowski 
455223ccae5cSDave Ertman /**
455323ccae5cSDave Ertman  * ice_share_res - set a resource as shared or dedicated
455423ccae5cSDave Ertman  * @hw: hw struct of original owner of resource
455523ccae5cSDave Ertman  * @type: resource type
455623ccae5cSDave Ertman  * @shared: is the resource being set to shared
455723ccae5cSDave Ertman  * @res_id: resource id (descriptor)
455823ccae5cSDave Ertman  */
455923ccae5cSDave Ertman int ice_share_res(struct ice_hw *hw, u16 type, u8 shared, u16 res_id)
456023ccae5cSDave Ertman {
456123ccae5cSDave Ertman 	struct ice_aqc_alloc_free_res_elem *buf;
456223ccae5cSDave Ertman 	u16 buf_len;
456323ccae5cSDave Ertman 	int status;
456423ccae5cSDave Ertman 
456523ccae5cSDave Ertman 	buf_len = struct_size(buf, elem, 1);
456623ccae5cSDave Ertman 	buf = kzalloc(buf_len, GFP_KERNEL);
456723ccae5cSDave Ertman 	if (!buf)
456823ccae5cSDave Ertman 		return -ENOMEM;
456923ccae5cSDave Ertman 
457023ccae5cSDave Ertman 	buf->num_elems = cpu_to_le16(1);
457123ccae5cSDave Ertman 	if (shared)
457223ccae5cSDave Ertman 		buf->res_type = cpu_to_le16(((type << ICE_AQC_RES_TYPE_S) &
457323ccae5cSDave Ertman 					     ICE_AQC_RES_TYPE_M) |
457423ccae5cSDave Ertman 					    ICE_AQC_RES_TYPE_FLAG_SHARED);
457523ccae5cSDave Ertman 	else
457623ccae5cSDave Ertman 		buf->res_type = cpu_to_le16(((type << ICE_AQC_RES_TYPE_S) &
457723ccae5cSDave Ertman 					     ICE_AQC_RES_TYPE_M) &
457823ccae5cSDave Ertman 					    ~ICE_AQC_RES_TYPE_FLAG_SHARED);
457923ccae5cSDave Ertman 
458023ccae5cSDave Ertman 	buf->elem[0].e.sw_resp = cpu_to_le16(res_id);
458123ccae5cSDave Ertman 	status = ice_aq_alloc_free_res(hw, 1, buf, buf_len,
458223ccae5cSDave Ertman 				       ice_aqc_opc_share_res, NULL);
458323ccae5cSDave Ertman 	if (status)
458423ccae5cSDave Ertman 		ice_debug(hw, ICE_DBG_SW, "Could not set resource type %u id %u to %s\n",
458523ccae5cSDave Ertman 			  type, res_id, shared ? "SHARED" : "DEDICATED");
458623ccae5cSDave Ertman 
458723ccae5cSDave Ertman 	kfree(buf);
458823ccae5cSDave Ertman 	return status;
458923ccae5cSDave Ertman }
459023ccae5cSDave Ertman 
4591fd2a6b71SDan Nowlin /* This is mapping table entry that maps every word within a given protocol
4592fd2a6b71SDan Nowlin  * structure to the real byte offset as per the specification of that
4593fd2a6b71SDan Nowlin  * protocol header.
4594fd2a6b71SDan Nowlin  * for example dst address is 3 words in ethertype header and corresponding
4595fd2a6b71SDan Nowlin  * bytes are 0, 2, 3 in the actual packet header and src address is at 4, 6, 8
4596fd2a6b71SDan Nowlin  * IMPORTANT: Every structure part of "ice_prot_hdr" union should have a
4597fd2a6b71SDan Nowlin  * matching entry describing its field. This needs to be updated if new
4598fd2a6b71SDan Nowlin  * structure is added to that union.
4599fd2a6b71SDan Nowlin  */
4600fd2a6b71SDan Nowlin static const struct ice_prot_ext_tbl_entry ice_prot_ext[ICE_PROTOCOL_LAST] = {
460117c6d835SMichal Swiatkowski 	ICE_PROTOCOL_ENTRY(ICE_MAC_OFOS, 0, 2, 4, 6, 8, 10, 12),
460217c6d835SMichal Swiatkowski 	ICE_PROTOCOL_ENTRY(ICE_MAC_IL, 0, 2, 4, 6, 8, 10, 12),
460317c6d835SMichal Swiatkowski 	ICE_PROTOCOL_ENTRY(ICE_ETYPE_OL, 0),
460417c6d835SMichal Swiatkowski 	ICE_PROTOCOL_ENTRY(ICE_ETYPE_IL, 0),
460517c6d835SMichal Swiatkowski 	ICE_PROTOCOL_ENTRY(ICE_VLAN_OFOS, 2, 0),
460617c6d835SMichal Swiatkowski 	ICE_PROTOCOL_ENTRY(ICE_IPV4_OFOS, 0, 2, 4, 6, 8, 10, 12, 14, 16, 18),
460717c6d835SMichal Swiatkowski 	ICE_PROTOCOL_ENTRY(ICE_IPV4_IL,	0, 2, 4, 6, 8, 10, 12, 14, 16, 18),
460817c6d835SMichal Swiatkowski 	ICE_PROTOCOL_ENTRY(ICE_IPV6_OFOS, 0, 2, 4, 6, 8, 10, 12, 14, 16, 18,
460917c6d835SMichal Swiatkowski 			   20, 22, 24, 26, 28, 30, 32, 34, 36, 38),
461017c6d835SMichal Swiatkowski 	ICE_PROTOCOL_ENTRY(ICE_IPV6_IL, 0, 2, 4, 6, 8, 10, 12, 14, 16, 18, 20,
461117c6d835SMichal Swiatkowski 			   22, 24, 26, 28, 30, 32, 34, 36, 38),
461217c6d835SMichal Swiatkowski 	ICE_PROTOCOL_ENTRY(ICE_TCP_IL, 0, 2),
461317c6d835SMichal Swiatkowski 	ICE_PROTOCOL_ENTRY(ICE_UDP_OF, 0, 2),
461417c6d835SMichal Swiatkowski 	ICE_PROTOCOL_ENTRY(ICE_UDP_ILOS, 0, 2),
461517c6d835SMichal Swiatkowski 	ICE_PROTOCOL_ENTRY(ICE_VXLAN, 8, 10, 12, 14),
461617c6d835SMichal Swiatkowski 	ICE_PROTOCOL_ENTRY(ICE_GENEVE, 8, 10, 12, 14),
461717c6d835SMichal Swiatkowski 	ICE_PROTOCOL_ENTRY(ICE_NVGRE, 0, 2, 4, 6),
461817c6d835SMichal Swiatkowski 	ICE_PROTOCOL_ENTRY(ICE_GTP, 8, 10, 12, 14, 16, 18, 20, 22),
461917c6d835SMichal Swiatkowski 	ICE_PROTOCOL_ENTRY(ICE_GTP_NO_PAY, 8, 10, 12, 14),
462017c6d835SMichal Swiatkowski 	ICE_PROTOCOL_ENTRY(ICE_PPPOE, 0, 2, 4, 6),
462117c6d835SMichal Swiatkowski 	ICE_PROTOCOL_ENTRY(ICE_L2TPV3, 0, 2, 4, 6, 8, 10),
462217c6d835SMichal Swiatkowski 	ICE_PROTOCOL_ENTRY(ICE_VLAN_EX, 2, 0),
462317c6d835SMichal Swiatkowski 	ICE_PROTOCOL_ENTRY(ICE_VLAN_IN, 2, 0),
462403592a14SMichal Swiatkowski 	ICE_PROTOCOL_ENTRY(ICE_HW_METADATA,
462503592a14SMichal Swiatkowski 			   ICE_SOURCE_PORT_MDID_OFFSET,
462603592a14SMichal Swiatkowski 			   ICE_PTYPE_MDID_OFFSET,
462703592a14SMichal Swiatkowski 			   ICE_PACKET_LENGTH_MDID_OFFSET,
462803592a14SMichal Swiatkowski 			   ICE_SOURCE_VSI_MDID_OFFSET,
462903592a14SMichal Swiatkowski 			   ICE_PKT_VLAN_MDID_OFFSET,
463003592a14SMichal Swiatkowski 			   ICE_PKT_TUNNEL_MDID_OFFSET,
463103592a14SMichal Swiatkowski 			   ICE_PKT_TCP_MDID_OFFSET,
463203592a14SMichal Swiatkowski 			   ICE_PKT_ERROR_MDID_OFFSET),
4633fd2a6b71SDan Nowlin };
4634fd2a6b71SDan Nowlin 
4635fd2a6b71SDan Nowlin static struct ice_protocol_entry ice_prot_id_tbl[ICE_PROTOCOL_LAST] = {
4636fd2a6b71SDan Nowlin 	{ ICE_MAC_OFOS,		ICE_MAC_OFOS_HW },
4637fd2a6b71SDan Nowlin 	{ ICE_MAC_IL,		ICE_MAC_IL_HW },
4638fd2a6b71SDan Nowlin 	{ ICE_ETYPE_OL,		ICE_ETYPE_OL_HW },
463934a89775SMartyna Szapar-Mudlaw 	{ ICE_ETYPE_IL,		ICE_ETYPE_IL_HW },
4640fd2a6b71SDan Nowlin 	{ ICE_VLAN_OFOS,	ICE_VLAN_OL_HW },
4641fd2a6b71SDan Nowlin 	{ ICE_IPV4_OFOS,	ICE_IPV4_OFOS_HW },
4642fd2a6b71SDan Nowlin 	{ ICE_IPV4_IL,		ICE_IPV4_IL_HW },
4643fd2a6b71SDan Nowlin 	{ ICE_IPV6_OFOS,	ICE_IPV6_OFOS_HW },
4644fd2a6b71SDan Nowlin 	{ ICE_IPV6_IL,		ICE_IPV6_IL_HW },
4645fd2a6b71SDan Nowlin 	{ ICE_TCP_IL,		ICE_TCP_IL_HW },
4646fd2a6b71SDan Nowlin 	{ ICE_UDP_OF,		ICE_UDP_OF_HW },
4647fd2a6b71SDan Nowlin 	{ ICE_UDP_ILOS,		ICE_UDP_ILOS_HW },
46488b032a55SMichal Swiatkowski 	{ ICE_VXLAN,		ICE_UDP_OF_HW },
46498b032a55SMichal Swiatkowski 	{ ICE_GENEVE,		ICE_UDP_OF_HW },
4650f0a35040SMichal Swiatkowski 	{ ICE_NVGRE,		ICE_GRE_OF_HW },
46519a225f81SMarcin Szycik 	{ ICE_GTP,		ICE_UDP_OF_HW },
46529a225f81SMarcin Szycik 	{ ICE_GTP_NO_PAY,	ICE_UDP_ILOS_HW },
4653cd8efeeeSMarcin Szycik 	{ ICE_PPPOE,		ICE_PPPOE_HW },
4654cd634549SMarcin Szycik 	{ ICE_L2TPV3,		ICE_L2TPV3_HW },
465506bca7c2SMartyna Szapar-Mudlaw 	{ ICE_VLAN_EX,          ICE_VLAN_OF_HW },
465606bca7c2SMartyna Szapar-Mudlaw 	{ ICE_VLAN_IN,          ICE_VLAN_OL_HW },
465703592a14SMichal Swiatkowski 	{ ICE_HW_METADATA,      ICE_META_DATA_ID_HW },
4658fd2a6b71SDan Nowlin };
4659fd2a6b71SDan Nowlin 
4660fd2a6b71SDan Nowlin /**
4661fd2a6b71SDan Nowlin  * ice_find_recp - find a recipe
4662fd2a6b71SDan Nowlin  * @hw: pointer to the hardware structure
4663fd2a6b71SDan Nowlin  * @lkup_exts: extension sequence to match
4664bccd9bceSMarcin Szycik  * @rinfo: information regarding the rule e.g. priority and action info
4665fd2a6b71SDan Nowlin  *
4666fd2a6b71SDan Nowlin  * Returns index of matching recipe, or ICE_MAX_NUM_RECIPES if not found.
4667fd2a6b71SDan Nowlin  */
4668de6acd1cSMichal Swiatkowski static u16
4669de6acd1cSMichal Swiatkowski ice_find_recp(struct ice_hw *hw, struct ice_prot_lkup_ext *lkup_exts,
4670bccd9bceSMarcin Szycik 	      const struct ice_adv_rule_info *rinfo)
4671fd2a6b71SDan Nowlin {
4672fd2a6b71SDan Nowlin 	bool refresh_required = true;
4673fd2a6b71SDan Nowlin 	struct ice_sw_recipe *recp;
4674fd2a6b71SDan Nowlin 	u8 i;
4675fd2a6b71SDan Nowlin 
4676fd2a6b71SDan Nowlin 	/* Walk through existing recipes to find a match */
4677fd2a6b71SDan Nowlin 	recp = hw->switch_info->recp_list;
4678fd2a6b71SDan Nowlin 	for (i = 0; i < ICE_MAX_NUM_RECIPES; i++) {
4679fd2a6b71SDan Nowlin 		/* If recipe was not created for this ID, in SW bookkeeping,
4680fd2a6b71SDan Nowlin 		 * check if FW has an entry for this recipe. If the FW has an
4681fd2a6b71SDan Nowlin 		 * entry update it in our SW bookkeeping and continue with the
4682fd2a6b71SDan Nowlin 		 * matching.
4683fd2a6b71SDan Nowlin 		 */
4684fd2a6b71SDan Nowlin 		if (!recp[i].recp_created)
4685fd2a6b71SDan Nowlin 			if (ice_get_recp_frm_fw(hw,
4686fd2a6b71SDan Nowlin 						hw->switch_info->recp_list, i,
4687fd2a6b71SDan Nowlin 						&refresh_required))
4688fd2a6b71SDan Nowlin 				continue;
4689fd2a6b71SDan Nowlin 
4690fd2a6b71SDan Nowlin 		/* Skip inverse action recipes */
4691fd2a6b71SDan Nowlin 		if (recp[i].root_buf && recp[i].root_buf->content.act_ctrl &
4692fd2a6b71SDan Nowlin 		    ICE_AQ_RECIPE_ACT_INV_ACT)
4693fd2a6b71SDan Nowlin 			continue;
4694fd2a6b71SDan Nowlin 
4695fd2a6b71SDan Nowlin 		/* if number of words we are looking for match */
4696fd2a6b71SDan Nowlin 		if (lkup_exts->n_val_words == recp[i].lkup_exts.n_val_words) {
4697fd2a6b71SDan Nowlin 			struct ice_fv_word *ar = recp[i].lkup_exts.fv_words;
4698fd2a6b71SDan Nowlin 			struct ice_fv_word *be = lkup_exts->fv_words;
4699fd2a6b71SDan Nowlin 			u16 *cr = recp[i].lkup_exts.field_mask;
4700fd2a6b71SDan Nowlin 			u16 *de = lkup_exts->field_mask;
4701fd2a6b71SDan Nowlin 			bool found = true;
4702fd2a6b71SDan Nowlin 			u8 pe, qr;
4703fd2a6b71SDan Nowlin 
4704fd2a6b71SDan Nowlin 			/* ar, cr, and qr are related to the recipe words, while
4705fd2a6b71SDan Nowlin 			 * be, de, and pe are related to the lookup words
4706fd2a6b71SDan Nowlin 			 */
4707fd2a6b71SDan Nowlin 			for (pe = 0; pe < lkup_exts->n_val_words; pe++) {
4708fd2a6b71SDan Nowlin 				for (qr = 0; qr < recp[i].lkup_exts.n_val_words;
4709fd2a6b71SDan Nowlin 				     qr++) {
4710fd2a6b71SDan Nowlin 					if (ar[qr].off == be[pe].off &&
4711fd2a6b71SDan Nowlin 					    ar[qr].prot_id == be[pe].prot_id &&
4712fd2a6b71SDan Nowlin 					    cr[qr] == de[pe])
4713fd2a6b71SDan Nowlin 						/* Found the "pe"th word in the
4714fd2a6b71SDan Nowlin 						 * given recipe
4715fd2a6b71SDan Nowlin 						 */
4716fd2a6b71SDan Nowlin 						break;
4717fd2a6b71SDan Nowlin 				}
4718fd2a6b71SDan Nowlin 				/* After walking through all the words in the
4719fd2a6b71SDan Nowlin 				 * "i"th recipe if "p"th word was not found then
4720fd2a6b71SDan Nowlin 				 * this recipe is not what we are looking for.
4721fd2a6b71SDan Nowlin 				 * So break out from this loop and try the next
4722fd2a6b71SDan Nowlin 				 * recipe
4723fd2a6b71SDan Nowlin 				 */
4724fd2a6b71SDan Nowlin 				if (qr >= recp[i].lkup_exts.n_val_words) {
4725fd2a6b71SDan Nowlin 					found = false;
4726fd2a6b71SDan Nowlin 					break;
4727fd2a6b71SDan Nowlin 				}
4728fd2a6b71SDan Nowlin 			}
4729fd2a6b71SDan Nowlin 			/* If for "i"th recipe the found was never set to false
4730fd2a6b71SDan Nowlin 			 * then it means we found our match
4731bccd9bceSMarcin Szycik 			 * Also tun type and *_pass_l2 of recipe needs to be
4732bccd9bceSMarcin Szycik 			 * checked
4733fd2a6b71SDan Nowlin 			 */
4734bccd9bceSMarcin Szycik 			if (found && recp[i].tun_type == rinfo->tun_type &&
4735bccd9bceSMarcin Szycik 			    recp[i].need_pass_l2 == rinfo->need_pass_l2 &&
4736bccd9bceSMarcin Szycik 			    recp[i].allow_pass_l2 == rinfo->allow_pass_l2)
4737fd2a6b71SDan Nowlin 				return i; /* Return the recipe ID */
4738fd2a6b71SDan Nowlin 		}
4739fd2a6b71SDan Nowlin 	}
4740fd2a6b71SDan Nowlin 	return ICE_MAX_NUM_RECIPES;
4741fd2a6b71SDan Nowlin }
4742fd2a6b71SDan Nowlin 
4743fd2a6b71SDan Nowlin /**
4744a1ffafb0SBrett Creeley  * ice_change_proto_id_to_dvm - change proto id in prot_id_tbl
4745a1ffafb0SBrett Creeley  *
4746a1ffafb0SBrett Creeley  * As protocol id for outer vlan is different in dvm and svm, if dvm is
4747a1ffafb0SBrett Creeley  * supported protocol array record for outer vlan has to be modified to
4748a1ffafb0SBrett Creeley  * reflect the value proper for DVM.
4749a1ffafb0SBrett Creeley  */
4750a1ffafb0SBrett Creeley void ice_change_proto_id_to_dvm(void)
4751a1ffafb0SBrett Creeley {
4752a1ffafb0SBrett Creeley 	u8 i;
4753a1ffafb0SBrett Creeley 
4754a1ffafb0SBrett Creeley 	for (i = 0; i < ARRAY_SIZE(ice_prot_id_tbl); i++)
4755a1ffafb0SBrett Creeley 		if (ice_prot_id_tbl[i].type == ICE_VLAN_OFOS &&
4756a1ffafb0SBrett Creeley 		    ice_prot_id_tbl[i].protocol_id != ICE_VLAN_OF_HW)
4757a1ffafb0SBrett Creeley 			ice_prot_id_tbl[i].protocol_id = ICE_VLAN_OF_HW;
4758a1ffafb0SBrett Creeley }
4759a1ffafb0SBrett Creeley 
4760a1ffafb0SBrett Creeley /**
4761fd2a6b71SDan Nowlin  * ice_prot_type_to_id - get protocol ID from protocol type
4762fd2a6b71SDan Nowlin  * @type: protocol type
4763fd2a6b71SDan Nowlin  * @id: pointer to variable that will receive the ID
4764fd2a6b71SDan Nowlin  *
4765fd2a6b71SDan Nowlin  * Returns true if found, false otherwise
4766fd2a6b71SDan Nowlin  */
4767fd2a6b71SDan Nowlin static bool ice_prot_type_to_id(enum ice_protocol_type type, u8 *id)
4768fd2a6b71SDan Nowlin {
4769fd2a6b71SDan Nowlin 	u8 i;
4770fd2a6b71SDan Nowlin 
4771fd2a6b71SDan Nowlin 	for (i = 0; i < ARRAY_SIZE(ice_prot_id_tbl); i++)
4772fd2a6b71SDan Nowlin 		if (ice_prot_id_tbl[i].type == type) {
4773fd2a6b71SDan Nowlin 			*id = ice_prot_id_tbl[i].protocol_id;
4774fd2a6b71SDan Nowlin 			return true;
4775fd2a6b71SDan Nowlin 		}
4776fd2a6b71SDan Nowlin 	return false;
4777fd2a6b71SDan Nowlin }
4778fd2a6b71SDan Nowlin 
4779fd2a6b71SDan Nowlin /**
4780fd2a6b71SDan Nowlin  * ice_fill_valid_words - count valid words
4781fd2a6b71SDan Nowlin  * @rule: advanced rule with lookup information
4782fd2a6b71SDan Nowlin  * @lkup_exts: byte offset extractions of the words that are valid
4783fd2a6b71SDan Nowlin  *
4784fd2a6b71SDan Nowlin  * calculate valid words in a lookup rule using mask value
4785fd2a6b71SDan Nowlin  */
4786fd2a6b71SDan Nowlin static u8
4787fd2a6b71SDan Nowlin ice_fill_valid_words(struct ice_adv_lkup_elem *rule,
4788fd2a6b71SDan Nowlin 		     struct ice_prot_lkup_ext *lkup_exts)
4789fd2a6b71SDan Nowlin {
4790fd2a6b71SDan Nowlin 	u8 j, word, prot_id, ret_val;
4791fd2a6b71SDan Nowlin 
4792fd2a6b71SDan Nowlin 	if (!ice_prot_type_to_id(rule->type, &prot_id))
4793fd2a6b71SDan Nowlin 		return 0;
4794fd2a6b71SDan Nowlin 
4795fd2a6b71SDan Nowlin 	word = lkup_exts->n_val_words;
4796fd2a6b71SDan Nowlin 
4797fd2a6b71SDan Nowlin 	for (j = 0; j < sizeof(rule->m_u) / sizeof(u16); j++)
4798fd2a6b71SDan Nowlin 		if (((u16 *)&rule->m_u)[j] &&
4799fd2a6b71SDan Nowlin 		    rule->type < ARRAY_SIZE(ice_prot_ext)) {
4800fd2a6b71SDan Nowlin 			/* No more space to accommodate */
4801fd2a6b71SDan Nowlin 			if (word >= ICE_MAX_CHAIN_WORDS)
4802fd2a6b71SDan Nowlin 				return 0;
4803fd2a6b71SDan Nowlin 			lkup_exts->fv_words[word].off =
4804fd2a6b71SDan Nowlin 				ice_prot_ext[rule->type].offs[j];
4805fd2a6b71SDan Nowlin 			lkup_exts->fv_words[word].prot_id =
4806fd2a6b71SDan Nowlin 				ice_prot_id_tbl[rule->type].protocol_id;
4807fd2a6b71SDan Nowlin 			lkup_exts->field_mask[word] =
4808fd2a6b71SDan Nowlin 				be16_to_cpu(((__force __be16 *)&rule->m_u)[j]);
4809fd2a6b71SDan Nowlin 			word++;
4810fd2a6b71SDan Nowlin 		}
4811fd2a6b71SDan Nowlin 
4812fd2a6b71SDan Nowlin 	ret_val = word - lkup_exts->n_val_words;
4813fd2a6b71SDan Nowlin 	lkup_exts->n_val_words = word;
4814fd2a6b71SDan Nowlin 
4815fd2a6b71SDan Nowlin 	return ret_val;
4816fd2a6b71SDan Nowlin }
4817fd2a6b71SDan Nowlin 
4818fd2a6b71SDan Nowlin /**
4819fd2a6b71SDan Nowlin  * ice_create_first_fit_recp_def - Create a recipe grouping
4820fd2a6b71SDan Nowlin  * @hw: pointer to the hardware structure
4821fd2a6b71SDan Nowlin  * @lkup_exts: an array of protocol header extractions
4822fd2a6b71SDan Nowlin  * @rg_list: pointer to a list that stores new recipe groups
4823fd2a6b71SDan Nowlin  * @recp_cnt: pointer to a variable that stores returned number of recipe groups
4824fd2a6b71SDan Nowlin  *
4825fd2a6b71SDan Nowlin  * Using first fit algorithm, take all the words that are still not done
4826fd2a6b71SDan Nowlin  * and start grouping them in 4-word groups. Each group makes up one
4827fd2a6b71SDan Nowlin  * recipe.
4828fd2a6b71SDan Nowlin  */
48295e24d598STony Nguyen static int
4830fd2a6b71SDan Nowlin ice_create_first_fit_recp_def(struct ice_hw *hw,
4831fd2a6b71SDan Nowlin 			      struct ice_prot_lkup_ext *lkup_exts,
4832fd2a6b71SDan Nowlin 			      struct list_head *rg_list,
4833fd2a6b71SDan Nowlin 			      u8 *recp_cnt)
4834fd2a6b71SDan Nowlin {
4835fd2a6b71SDan Nowlin 	struct ice_pref_recipe_group *grp = NULL;
4836fd2a6b71SDan Nowlin 	u8 j;
4837fd2a6b71SDan Nowlin 
4838fd2a6b71SDan Nowlin 	*recp_cnt = 0;
4839fd2a6b71SDan Nowlin 
4840fd2a6b71SDan Nowlin 	/* Walk through every word in the rule to check if it is not done. If so
4841fd2a6b71SDan Nowlin 	 * then this word needs to be part of a new recipe.
4842fd2a6b71SDan Nowlin 	 */
4843fd2a6b71SDan Nowlin 	for (j = 0; j < lkup_exts->n_val_words; j++)
4844fd2a6b71SDan Nowlin 		if (!test_bit(j, lkup_exts->done)) {
4845fd2a6b71SDan Nowlin 			if (!grp ||
4846fd2a6b71SDan Nowlin 			    grp->n_val_pairs == ICE_NUM_WORDS_RECIPE) {
4847fd2a6b71SDan Nowlin 				struct ice_recp_grp_entry *entry;
4848fd2a6b71SDan Nowlin 
4849fd2a6b71SDan Nowlin 				entry = devm_kzalloc(ice_hw_to_dev(hw),
4850fd2a6b71SDan Nowlin 						     sizeof(*entry),
4851fd2a6b71SDan Nowlin 						     GFP_KERNEL);
4852fd2a6b71SDan Nowlin 				if (!entry)
4853d54699e2STony Nguyen 					return -ENOMEM;
4854fd2a6b71SDan Nowlin 				list_add(&entry->l_entry, rg_list);
4855fd2a6b71SDan Nowlin 				grp = &entry->r_group;
4856fd2a6b71SDan Nowlin 				(*recp_cnt)++;
4857fd2a6b71SDan Nowlin 			}
4858fd2a6b71SDan Nowlin 
4859fd2a6b71SDan Nowlin 			grp->pairs[grp->n_val_pairs].prot_id =
4860fd2a6b71SDan Nowlin 				lkup_exts->fv_words[j].prot_id;
4861fd2a6b71SDan Nowlin 			grp->pairs[grp->n_val_pairs].off =
4862fd2a6b71SDan Nowlin 				lkup_exts->fv_words[j].off;
4863fd2a6b71SDan Nowlin 			grp->mask[grp->n_val_pairs] = lkup_exts->field_mask[j];
4864fd2a6b71SDan Nowlin 			grp->n_val_pairs++;
4865fd2a6b71SDan Nowlin 		}
4866fd2a6b71SDan Nowlin 
4867fd2a6b71SDan Nowlin 	return 0;
4868fd2a6b71SDan Nowlin }
4869fd2a6b71SDan Nowlin 
4870fd2a6b71SDan Nowlin /**
4871fd2a6b71SDan Nowlin  * ice_fill_fv_word_index - fill in the field vector indices for a recipe group
4872fd2a6b71SDan Nowlin  * @hw: pointer to the hardware structure
4873fd2a6b71SDan Nowlin  * @fv_list: field vector with the extraction sequence information
4874fd2a6b71SDan Nowlin  * @rg_list: recipe groupings with protocol-offset pairs
4875fd2a6b71SDan Nowlin  *
4876fd2a6b71SDan Nowlin  * Helper function to fill in the field vector indices for protocol-offset
4877fd2a6b71SDan Nowlin  * pairs. These indexes are then ultimately programmed into a recipe.
4878fd2a6b71SDan Nowlin  */
48795e24d598STony Nguyen static int
4880fd2a6b71SDan Nowlin ice_fill_fv_word_index(struct ice_hw *hw, struct list_head *fv_list,
4881fd2a6b71SDan Nowlin 		       struct list_head *rg_list)
4882fd2a6b71SDan Nowlin {
4883fd2a6b71SDan Nowlin 	struct ice_sw_fv_list_entry *fv;
4884fd2a6b71SDan Nowlin 	struct ice_recp_grp_entry *rg;
4885fd2a6b71SDan Nowlin 	struct ice_fv_word *fv_ext;
4886fd2a6b71SDan Nowlin 
4887fd2a6b71SDan Nowlin 	if (list_empty(fv_list))
4888fd2a6b71SDan Nowlin 		return 0;
4889fd2a6b71SDan Nowlin 
4890fd2a6b71SDan Nowlin 	fv = list_first_entry(fv_list, struct ice_sw_fv_list_entry,
4891fd2a6b71SDan Nowlin 			      list_entry);
4892fd2a6b71SDan Nowlin 	fv_ext = fv->fv_ptr->ew;
4893fd2a6b71SDan Nowlin 
4894fd2a6b71SDan Nowlin 	list_for_each_entry(rg, rg_list, l_entry) {
4895fd2a6b71SDan Nowlin 		u8 i;
4896fd2a6b71SDan Nowlin 
4897fd2a6b71SDan Nowlin 		for (i = 0; i < rg->r_group.n_val_pairs; i++) {
4898fd2a6b71SDan Nowlin 			struct ice_fv_word *pr;
4899fd2a6b71SDan Nowlin 			bool found = false;
4900fd2a6b71SDan Nowlin 			u16 mask;
4901fd2a6b71SDan Nowlin 			u8 j;
4902fd2a6b71SDan Nowlin 
4903fd2a6b71SDan Nowlin 			pr = &rg->r_group.pairs[i];
4904fd2a6b71SDan Nowlin 			mask = rg->r_group.mask[i];
4905fd2a6b71SDan Nowlin 
4906fd2a6b71SDan Nowlin 			for (j = 0; j < hw->blk[ICE_BLK_SW].es.fvw; j++)
4907fd2a6b71SDan Nowlin 				if (fv_ext[j].prot_id == pr->prot_id &&
4908fd2a6b71SDan Nowlin 				    fv_ext[j].off == pr->off) {
4909fd2a6b71SDan Nowlin 					found = true;
4910fd2a6b71SDan Nowlin 
4911fd2a6b71SDan Nowlin 					/* Store index of field vector */
4912fd2a6b71SDan Nowlin 					rg->fv_idx[i] = j;
4913fd2a6b71SDan Nowlin 					rg->fv_mask[i] = mask;
4914fd2a6b71SDan Nowlin 					break;
4915fd2a6b71SDan Nowlin 				}
4916fd2a6b71SDan Nowlin 
4917fd2a6b71SDan Nowlin 			/* Protocol/offset could not be found, caller gave an
4918fd2a6b71SDan Nowlin 			 * invalid pair
4919fd2a6b71SDan Nowlin 			 */
4920fd2a6b71SDan Nowlin 			if (!found)
4921d54699e2STony Nguyen 				return -EINVAL;
4922fd2a6b71SDan Nowlin 		}
4923fd2a6b71SDan Nowlin 	}
4924fd2a6b71SDan Nowlin 
4925fd2a6b71SDan Nowlin 	return 0;
4926fd2a6b71SDan Nowlin }
4927fd2a6b71SDan Nowlin 
4928fd2a6b71SDan Nowlin /**
4929fd2a6b71SDan Nowlin  * ice_find_free_recp_res_idx - find free result indexes for recipe
4930fd2a6b71SDan Nowlin  * @hw: pointer to hardware structure
4931fd2a6b71SDan Nowlin  * @profiles: bitmap of profiles that will be associated with the new recipe
4932fd2a6b71SDan Nowlin  * @free_idx: pointer to variable to receive the free index bitmap
4933fd2a6b71SDan Nowlin  *
4934fd2a6b71SDan Nowlin  * The algorithm used here is:
4935fd2a6b71SDan Nowlin  *	1. When creating a new recipe, create a set P which contains all
4936fd2a6b71SDan Nowlin  *	   Profiles that will be associated with our new recipe
4937fd2a6b71SDan Nowlin  *
4938fd2a6b71SDan Nowlin  *	2. For each Profile p in set P:
4939fd2a6b71SDan Nowlin  *	    a. Add all recipes associated with Profile p into set R
4940fd2a6b71SDan Nowlin  *	    b. Optional : PossibleIndexes &= profile[p].possibleIndexes
4941fd2a6b71SDan Nowlin  *		[initially PossibleIndexes should be 0xFFFFFFFFFFFFFFFF]
4942fd2a6b71SDan Nowlin  *		i. Or just assume they all have the same possible indexes:
4943fd2a6b71SDan Nowlin  *			44, 45, 46, 47
4944fd2a6b71SDan Nowlin  *			i.e., PossibleIndexes = 0x0000F00000000000
4945fd2a6b71SDan Nowlin  *
4946fd2a6b71SDan Nowlin  *	3. For each Recipe r in set R:
4947fd2a6b71SDan Nowlin  *	    a. UsedIndexes |= (bitwise or ) recipe[r].res_indexes
4948fd2a6b71SDan Nowlin  *	    b. FreeIndexes = UsedIndexes ^ PossibleIndexes
4949fd2a6b71SDan Nowlin  *
4950fd2a6b71SDan Nowlin  *	FreeIndexes will contain the bits indicating the indexes free for use,
4951fd2a6b71SDan Nowlin  *      then the code needs to update the recipe[r].used_result_idx_bits to
4952fd2a6b71SDan Nowlin  *      indicate which indexes were selected for use by this recipe.
4953fd2a6b71SDan Nowlin  */
4954fd2a6b71SDan Nowlin static u16
4955fd2a6b71SDan Nowlin ice_find_free_recp_res_idx(struct ice_hw *hw, const unsigned long *profiles,
4956fd2a6b71SDan Nowlin 			   unsigned long *free_idx)
4957fd2a6b71SDan Nowlin {
4958fd2a6b71SDan Nowlin 	DECLARE_BITMAP(possible_idx, ICE_MAX_FV_WORDS);
4959fd2a6b71SDan Nowlin 	DECLARE_BITMAP(recipes, ICE_MAX_NUM_RECIPES);
4960fd2a6b71SDan Nowlin 	DECLARE_BITMAP(used_idx, ICE_MAX_FV_WORDS);
4961fd2a6b71SDan Nowlin 	u16 bit;
4962fd2a6b71SDan Nowlin 
4963fd2a6b71SDan Nowlin 	bitmap_zero(recipes, ICE_MAX_NUM_RECIPES);
4964fd2a6b71SDan Nowlin 	bitmap_zero(used_idx, ICE_MAX_FV_WORDS);
4965fd2a6b71SDan Nowlin 
49662f7ee2a7SAlexander Lobakin 	bitmap_fill(possible_idx, ICE_MAX_FV_WORDS);
4967fd2a6b71SDan Nowlin 
4968fd2a6b71SDan Nowlin 	/* For each profile we are going to associate the recipe with, add the
4969fd2a6b71SDan Nowlin 	 * recipes that are associated with that profile. This will give us
4970fd2a6b71SDan Nowlin 	 * the set of recipes that our recipe may collide with. Also, determine
4971fd2a6b71SDan Nowlin 	 * what possible result indexes are usable given this set of profiles.
4972fd2a6b71SDan Nowlin 	 */
4973fd2a6b71SDan Nowlin 	for_each_set_bit(bit, profiles, ICE_MAX_NUM_PROFILES) {
4974fd2a6b71SDan Nowlin 		bitmap_or(recipes, recipes, profile_to_recipe[bit],
4975fd2a6b71SDan Nowlin 			  ICE_MAX_NUM_RECIPES);
4976fd2a6b71SDan Nowlin 		bitmap_and(possible_idx, possible_idx,
4977fd2a6b71SDan Nowlin 			   hw->switch_info->prof_res_bm[bit],
4978fd2a6b71SDan Nowlin 			   ICE_MAX_FV_WORDS);
4979fd2a6b71SDan Nowlin 	}
4980fd2a6b71SDan Nowlin 
4981fd2a6b71SDan Nowlin 	/* For each recipe that our new recipe may collide with, determine
4982fd2a6b71SDan Nowlin 	 * which indexes have been used.
4983fd2a6b71SDan Nowlin 	 */
4984fd2a6b71SDan Nowlin 	for_each_set_bit(bit, recipes, ICE_MAX_NUM_RECIPES)
4985fd2a6b71SDan Nowlin 		bitmap_or(used_idx, used_idx,
4986fd2a6b71SDan Nowlin 			  hw->switch_info->recp_list[bit].res_idxs,
4987fd2a6b71SDan Nowlin 			  ICE_MAX_FV_WORDS);
4988fd2a6b71SDan Nowlin 
4989fd2a6b71SDan Nowlin 	bitmap_xor(free_idx, used_idx, possible_idx, ICE_MAX_FV_WORDS);
4990fd2a6b71SDan Nowlin 
4991fd2a6b71SDan Nowlin 	/* return number of free indexes */
4992fd2a6b71SDan Nowlin 	return (u16)bitmap_weight(free_idx, ICE_MAX_FV_WORDS);
4993fd2a6b71SDan Nowlin }
4994fd2a6b71SDan Nowlin 
4995fd2a6b71SDan Nowlin /**
4996fd2a6b71SDan Nowlin  * ice_add_sw_recipe - function to call AQ calls to create switch recipe
4997fd2a6b71SDan Nowlin  * @hw: pointer to hardware structure
4998fd2a6b71SDan Nowlin  * @rm: recipe management list entry
4999fd2a6b71SDan Nowlin  * @profiles: bitmap of profiles that will be associated.
5000fd2a6b71SDan Nowlin  */
50015e24d598STony Nguyen static int
5002fd2a6b71SDan Nowlin ice_add_sw_recipe(struct ice_hw *hw, struct ice_sw_recipe *rm,
50038b032a55SMichal Swiatkowski 		  unsigned long *profiles)
5004fd2a6b71SDan Nowlin {
5005fd2a6b71SDan Nowlin 	DECLARE_BITMAP(result_idx_bm, ICE_MAX_FV_WORDS);
5006bccd9bceSMarcin Szycik 	struct ice_aqc_recipe_content *content;
5007fd2a6b71SDan Nowlin 	struct ice_aqc_recipe_data_elem *tmp;
5008fd2a6b71SDan Nowlin 	struct ice_aqc_recipe_data_elem *buf;
5009fd2a6b71SDan Nowlin 	struct ice_recp_grp_entry *entry;
5010fd2a6b71SDan Nowlin 	u16 free_res_idx;
5011fd2a6b71SDan Nowlin 	u16 recipe_count;
5012fd2a6b71SDan Nowlin 	u8 chain_idx;
5013fd2a6b71SDan Nowlin 	u8 recps = 0;
50145518ac2aSTony Nguyen 	int status;
5015fd2a6b71SDan Nowlin 
5016fd2a6b71SDan Nowlin 	/* When more than one recipe are required, another recipe is needed to
5017fd2a6b71SDan Nowlin 	 * chain them together. Matching a tunnel metadata ID takes up one of
5018fd2a6b71SDan Nowlin 	 * the match fields in the chaining recipe reducing the number of
5019fd2a6b71SDan Nowlin 	 * chained recipes by one.
5020fd2a6b71SDan Nowlin 	 */
5021fd2a6b71SDan Nowlin 	 /* check number of free result indices */
5022fd2a6b71SDan Nowlin 	bitmap_zero(result_idx_bm, ICE_MAX_FV_WORDS);
5023fd2a6b71SDan Nowlin 	free_res_idx = ice_find_free_recp_res_idx(hw, profiles, result_idx_bm);
5024fd2a6b71SDan Nowlin 
5025fd2a6b71SDan Nowlin 	ice_debug(hw, ICE_DBG_SW, "Result idx slots: %d, need %d\n",
5026fd2a6b71SDan Nowlin 		  free_res_idx, rm->n_grp_count);
5027fd2a6b71SDan Nowlin 
5028fd2a6b71SDan Nowlin 	if (rm->n_grp_count > 1) {
5029fd2a6b71SDan Nowlin 		if (rm->n_grp_count > free_res_idx)
5030d54699e2STony Nguyen 			return -ENOSPC;
5031fd2a6b71SDan Nowlin 
5032fd2a6b71SDan Nowlin 		rm->n_grp_count++;
5033fd2a6b71SDan Nowlin 	}
5034fd2a6b71SDan Nowlin 
5035fd2a6b71SDan Nowlin 	if (rm->n_grp_count > ICE_MAX_CHAIN_RECIPE)
5036d54699e2STony Nguyen 		return -ENOSPC;
5037fd2a6b71SDan Nowlin 
5038fd2a6b71SDan Nowlin 	tmp = kcalloc(ICE_MAX_NUM_RECIPES, sizeof(*tmp), GFP_KERNEL);
5039fd2a6b71SDan Nowlin 	if (!tmp)
5040d54699e2STony Nguyen 		return -ENOMEM;
5041fd2a6b71SDan Nowlin 
5042fd2a6b71SDan Nowlin 	buf = devm_kcalloc(ice_hw_to_dev(hw), rm->n_grp_count, sizeof(*buf),
5043fd2a6b71SDan Nowlin 			   GFP_KERNEL);
5044fd2a6b71SDan Nowlin 	if (!buf) {
5045d54699e2STony Nguyen 		status = -ENOMEM;
5046fd2a6b71SDan Nowlin 		goto err_mem;
5047fd2a6b71SDan Nowlin 	}
5048fd2a6b71SDan Nowlin 
5049fd2a6b71SDan Nowlin 	bitmap_zero(rm->r_bitmap, ICE_MAX_NUM_RECIPES);
5050fd2a6b71SDan Nowlin 	recipe_count = ICE_MAX_NUM_RECIPES;
5051fd2a6b71SDan Nowlin 	status = ice_aq_get_recipe(hw, tmp, &recipe_count, ICE_SW_LKUP_MAC,
5052fd2a6b71SDan Nowlin 				   NULL);
5053fd2a6b71SDan Nowlin 	if (status || recipe_count == 0)
5054fd2a6b71SDan Nowlin 		goto err_unroll;
5055fd2a6b71SDan Nowlin 
5056fd2a6b71SDan Nowlin 	/* Allocate the recipe resources, and configure them according to the
5057fd2a6b71SDan Nowlin 	 * match fields from protocol headers and extracted field vectors.
5058fd2a6b71SDan Nowlin 	 */
5059fd2a6b71SDan Nowlin 	chain_idx = find_first_bit(result_idx_bm, ICE_MAX_FV_WORDS);
5060fd2a6b71SDan Nowlin 	list_for_each_entry(entry, &rm->rg_list, l_entry) {
5061fd2a6b71SDan Nowlin 		u8 i;
5062fd2a6b71SDan Nowlin 
5063fd2a6b71SDan Nowlin 		status = ice_alloc_recipe(hw, &entry->rid);
5064fd2a6b71SDan Nowlin 		if (status)
5065fd2a6b71SDan Nowlin 			goto err_unroll;
5066fd2a6b71SDan Nowlin 
5067bccd9bceSMarcin Szycik 		content = &buf[recps].content;
5068bccd9bceSMarcin Szycik 
5069fd2a6b71SDan Nowlin 		/* Clear the result index of the located recipe, as this will be
5070fd2a6b71SDan Nowlin 		 * updated, if needed, later in the recipe creation process.
5071fd2a6b71SDan Nowlin 		 */
5072fd2a6b71SDan Nowlin 		tmp[0].content.result_indx = 0;
5073fd2a6b71SDan Nowlin 
5074fd2a6b71SDan Nowlin 		buf[recps] = tmp[0];
5075fd2a6b71SDan Nowlin 		buf[recps].recipe_indx = (u8)entry->rid;
5076fd2a6b71SDan Nowlin 		/* if the recipe is a non-root recipe RID should be programmed
5077fd2a6b71SDan Nowlin 		 * as 0 for the rules to be applied correctly.
5078fd2a6b71SDan Nowlin 		 */
5079bccd9bceSMarcin Szycik 		content->rid = 0;
5080bccd9bceSMarcin Szycik 		memset(&content->lkup_indx, 0,
5081bccd9bceSMarcin Szycik 		       sizeof(content->lkup_indx));
5082fd2a6b71SDan Nowlin 
5083fd2a6b71SDan Nowlin 		/* All recipes use look-up index 0 to match switch ID. */
5084bccd9bceSMarcin Szycik 		content->lkup_indx[0] = ICE_AQ_SW_ID_LKUP_IDX;
5085bccd9bceSMarcin Szycik 		content->mask[0] = cpu_to_le16(ICE_AQ_SW_ID_LKUP_MASK);
5086fd2a6b71SDan Nowlin 		/* Setup lkup_indx 1..4 to INVALID/ignore and set the mask
5087fd2a6b71SDan Nowlin 		 * to be 0
5088fd2a6b71SDan Nowlin 		 */
5089fd2a6b71SDan Nowlin 		for (i = 1; i <= ICE_NUM_WORDS_RECIPE; i++) {
5090bccd9bceSMarcin Szycik 			content->lkup_indx[i] = 0x80;
5091bccd9bceSMarcin Szycik 			content->mask[i] = 0;
5092fd2a6b71SDan Nowlin 		}
5093fd2a6b71SDan Nowlin 
5094fd2a6b71SDan Nowlin 		for (i = 0; i < entry->r_group.n_val_pairs; i++) {
5095bccd9bceSMarcin Szycik 			content->lkup_indx[i + 1] = entry->fv_idx[i];
5096bccd9bceSMarcin Szycik 			content->mask[i + 1] = cpu_to_le16(entry->fv_mask[i]);
5097fd2a6b71SDan Nowlin 		}
5098fd2a6b71SDan Nowlin 
5099fd2a6b71SDan Nowlin 		if (rm->n_grp_count > 1) {
5100fd2a6b71SDan Nowlin 			/* Checks to see if there really is a valid result index
5101fd2a6b71SDan Nowlin 			 * that can be used.
5102fd2a6b71SDan Nowlin 			 */
5103fd2a6b71SDan Nowlin 			if (chain_idx >= ICE_MAX_FV_WORDS) {
5104fd2a6b71SDan Nowlin 				ice_debug(hw, ICE_DBG_SW, "No chain index available\n");
5105d54699e2STony Nguyen 				status = -ENOSPC;
5106fd2a6b71SDan Nowlin 				goto err_unroll;
5107fd2a6b71SDan Nowlin 			}
5108fd2a6b71SDan Nowlin 
5109fd2a6b71SDan Nowlin 			entry->chain_idx = chain_idx;
5110bccd9bceSMarcin Szycik 			content->result_indx =
5111fd2a6b71SDan Nowlin 				ICE_AQ_RECIPE_RESULT_EN |
5112fd2a6b71SDan Nowlin 				((chain_idx << ICE_AQ_RECIPE_RESULT_DATA_S) &
5113fd2a6b71SDan Nowlin 				 ICE_AQ_RECIPE_RESULT_DATA_M);
5114fd2a6b71SDan Nowlin 			clear_bit(chain_idx, result_idx_bm);
5115fd2a6b71SDan Nowlin 			chain_idx = find_first_bit(result_idx_bm,
5116fd2a6b71SDan Nowlin 						   ICE_MAX_FV_WORDS);
5117fd2a6b71SDan Nowlin 		}
5118fd2a6b71SDan Nowlin 
5119fd2a6b71SDan Nowlin 		/* fill recipe dependencies */
5120fd2a6b71SDan Nowlin 		bitmap_zero((unsigned long *)buf[recps].recipe_bitmap,
5121fd2a6b71SDan Nowlin 			    ICE_MAX_NUM_RECIPES);
5122fd2a6b71SDan Nowlin 		set_bit(buf[recps].recipe_indx,
5123fd2a6b71SDan Nowlin 			(unsigned long *)buf[recps].recipe_bitmap);
5124bccd9bceSMarcin Szycik 		content->act_ctrl_fwd_priority = rm->priority;
5125bccd9bceSMarcin Szycik 
5126bccd9bceSMarcin Szycik 		if (rm->need_pass_l2)
5127bccd9bceSMarcin Szycik 			content->act_ctrl |= ICE_AQ_RECIPE_ACT_NEED_PASS_L2;
5128bccd9bceSMarcin Szycik 
5129bccd9bceSMarcin Szycik 		if (rm->allow_pass_l2)
5130bccd9bceSMarcin Szycik 			content->act_ctrl |= ICE_AQ_RECIPE_ACT_ALLOW_PASS_L2;
5131fd2a6b71SDan Nowlin 		recps++;
5132fd2a6b71SDan Nowlin 	}
5133fd2a6b71SDan Nowlin 
5134fd2a6b71SDan Nowlin 	if (rm->n_grp_count == 1) {
5135fd2a6b71SDan Nowlin 		rm->root_rid = buf[0].recipe_indx;
5136fd2a6b71SDan Nowlin 		set_bit(buf[0].recipe_indx, rm->r_bitmap);
5137fd2a6b71SDan Nowlin 		buf[0].content.rid = rm->root_rid | ICE_AQ_RECIPE_ID_IS_ROOT;
5138fd2a6b71SDan Nowlin 		if (sizeof(buf[0].recipe_bitmap) >= sizeof(rm->r_bitmap)) {
5139fd2a6b71SDan Nowlin 			memcpy(buf[0].recipe_bitmap, rm->r_bitmap,
5140fd2a6b71SDan Nowlin 			       sizeof(buf[0].recipe_bitmap));
5141fd2a6b71SDan Nowlin 		} else {
5142d54699e2STony Nguyen 			status = -EINVAL;
5143fd2a6b71SDan Nowlin 			goto err_unroll;
5144fd2a6b71SDan Nowlin 		}
5145fd2a6b71SDan Nowlin 		/* Applicable only for ROOT_RECIPE, set the fwd_priority for
5146fd2a6b71SDan Nowlin 		 * the recipe which is getting created if specified
5147fd2a6b71SDan Nowlin 		 * by user. Usually any advanced switch filter, which results
5148fd2a6b71SDan Nowlin 		 * into new extraction sequence, ended up creating a new recipe
5149fd2a6b71SDan Nowlin 		 * of type ROOT and usually recipes are associated with profiles
5150fd2a6b71SDan Nowlin 		 * Switch rule referreing newly created recipe, needs to have
5151fd2a6b71SDan Nowlin 		 * either/or 'fwd' or 'join' priority, otherwise switch rule
5152fd2a6b71SDan Nowlin 		 * evaluation will not happen correctly. In other words, if
5153fd2a6b71SDan Nowlin 		 * switch rule to be evaluated on priority basis, then recipe
5154fd2a6b71SDan Nowlin 		 * needs to have priority, otherwise it will be evaluated last.
5155fd2a6b71SDan Nowlin 		 */
5156fd2a6b71SDan Nowlin 		buf[0].content.act_ctrl_fwd_priority = rm->priority;
5157fd2a6b71SDan Nowlin 	} else {
5158fd2a6b71SDan Nowlin 		struct ice_recp_grp_entry *last_chain_entry;
5159fd2a6b71SDan Nowlin 		u16 rid, i;
5160fd2a6b71SDan Nowlin 
5161fd2a6b71SDan Nowlin 		/* Allocate the last recipe that will chain the outcomes of the
5162fd2a6b71SDan Nowlin 		 * other recipes together
5163fd2a6b71SDan Nowlin 		 */
5164fd2a6b71SDan Nowlin 		status = ice_alloc_recipe(hw, &rid);
5165fd2a6b71SDan Nowlin 		if (status)
5166fd2a6b71SDan Nowlin 			goto err_unroll;
5167fd2a6b71SDan Nowlin 
5168bccd9bceSMarcin Szycik 		content = &buf[recps].content;
5169bccd9bceSMarcin Szycik 
5170fd2a6b71SDan Nowlin 		buf[recps].recipe_indx = (u8)rid;
5171bccd9bceSMarcin Szycik 		content->rid = (u8)rid;
5172bccd9bceSMarcin Szycik 		content->rid |= ICE_AQ_RECIPE_ID_IS_ROOT;
5173fd2a6b71SDan Nowlin 		/* the new entry created should also be part of rg_list to
5174fd2a6b71SDan Nowlin 		 * make sure we have complete recipe
5175fd2a6b71SDan Nowlin 		 */
5176fd2a6b71SDan Nowlin 		last_chain_entry = devm_kzalloc(ice_hw_to_dev(hw),
5177fd2a6b71SDan Nowlin 						sizeof(*last_chain_entry),
5178fd2a6b71SDan Nowlin 						GFP_KERNEL);
5179fd2a6b71SDan Nowlin 		if (!last_chain_entry) {
5180d54699e2STony Nguyen 			status = -ENOMEM;
5181fd2a6b71SDan Nowlin 			goto err_unroll;
5182fd2a6b71SDan Nowlin 		}
5183fd2a6b71SDan Nowlin 		last_chain_entry->rid = rid;
5184bccd9bceSMarcin Szycik 		memset(&content->lkup_indx, 0, sizeof(content->lkup_indx));
5185fd2a6b71SDan Nowlin 		/* All recipes use look-up index 0 to match switch ID. */
5186bccd9bceSMarcin Szycik 		content->lkup_indx[0] = ICE_AQ_SW_ID_LKUP_IDX;
5187bccd9bceSMarcin Szycik 		content->mask[0] = cpu_to_le16(ICE_AQ_SW_ID_LKUP_MASK);
5188fd2a6b71SDan Nowlin 		for (i = 1; i <= ICE_NUM_WORDS_RECIPE; i++) {
5189bccd9bceSMarcin Szycik 			content->lkup_indx[i] = ICE_AQ_RECIPE_LKUP_IGNORE;
5190bccd9bceSMarcin Szycik 			content->mask[i] = 0;
5191fd2a6b71SDan Nowlin 		}
5192fd2a6b71SDan Nowlin 
5193fd2a6b71SDan Nowlin 		i = 1;
5194fd2a6b71SDan Nowlin 		/* update r_bitmap with the recp that is used for chaining */
5195fd2a6b71SDan Nowlin 		set_bit(rid, rm->r_bitmap);
5196fd2a6b71SDan Nowlin 		/* this is the recipe that chains all the other recipes so it
5197fd2a6b71SDan Nowlin 		 * should not have a chaining ID to indicate the same
5198fd2a6b71SDan Nowlin 		 */
5199fd2a6b71SDan Nowlin 		last_chain_entry->chain_idx = ICE_INVAL_CHAIN_IND;
5200fd2a6b71SDan Nowlin 		list_for_each_entry(entry, &rm->rg_list, l_entry) {
5201fd2a6b71SDan Nowlin 			last_chain_entry->fv_idx[i] = entry->chain_idx;
5202bccd9bceSMarcin Szycik 			content->lkup_indx[i] = entry->chain_idx;
5203bccd9bceSMarcin Szycik 			content->mask[i++] = cpu_to_le16(0xFFFF);
5204fd2a6b71SDan Nowlin 			set_bit(entry->rid, rm->r_bitmap);
5205fd2a6b71SDan Nowlin 		}
5206fd2a6b71SDan Nowlin 		list_add(&last_chain_entry->l_entry, &rm->rg_list);
5207fd2a6b71SDan Nowlin 		if (sizeof(buf[recps].recipe_bitmap) >=
5208fd2a6b71SDan Nowlin 		    sizeof(rm->r_bitmap)) {
5209fd2a6b71SDan Nowlin 			memcpy(buf[recps].recipe_bitmap, rm->r_bitmap,
5210fd2a6b71SDan Nowlin 			       sizeof(buf[recps].recipe_bitmap));
5211fd2a6b71SDan Nowlin 		} else {
5212d54699e2STony Nguyen 			status = -EINVAL;
5213fd2a6b71SDan Nowlin 			goto err_unroll;
5214fd2a6b71SDan Nowlin 		}
5215bccd9bceSMarcin Szycik 		content->act_ctrl_fwd_priority = rm->priority;
5216fd2a6b71SDan Nowlin 
5217fd2a6b71SDan Nowlin 		recps++;
5218fd2a6b71SDan Nowlin 		rm->root_rid = (u8)rid;
5219fd2a6b71SDan Nowlin 	}
5220fd2a6b71SDan Nowlin 	status = ice_acquire_change_lock(hw, ICE_RES_WRITE);
5221fd2a6b71SDan Nowlin 	if (status)
5222fd2a6b71SDan Nowlin 		goto err_unroll;
5223fd2a6b71SDan Nowlin 
5224fd2a6b71SDan Nowlin 	status = ice_aq_add_recipe(hw, buf, rm->n_grp_count, NULL);
5225fd2a6b71SDan Nowlin 	ice_release_change_lock(hw);
5226fd2a6b71SDan Nowlin 	if (status)
5227fd2a6b71SDan Nowlin 		goto err_unroll;
5228fd2a6b71SDan Nowlin 
5229fd2a6b71SDan Nowlin 	/* Every recipe that just got created add it to the recipe
5230fd2a6b71SDan Nowlin 	 * book keeping list
5231fd2a6b71SDan Nowlin 	 */
5232fd2a6b71SDan Nowlin 	list_for_each_entry(entry, &rm->rg_list, l_entry) {
5233fd2a6b71SDan Nowlin 		struct ice_switch_info *sw = hw->switch_info;
5234fd2a6b71SDan Nowlin 		bool is_root, idx_found = false;
5235fd2a6b71SDan Nowlin 		struct ice_sw_recipe *recp;
5236fd2a6b71SDan Nowlin 		u16 idx, buf_idx = 0;
5237fd2a6b71SDan Nowlin 
5238fd2a6b71SDan Nowlin 		/* find buffer index for copying some data */
5239fd2a6b71SDan Nowlin 		for (idx = 0; idx < rm->n_grp_count; idx++)
5240fd2a6b71SDan Nowlin 			if (buf[idx].recipe_indx == entry->rid) {
5241fd2a6b71SDan Nowlin 				buf_idx = idx;
5242fd2a6b71SDan Nowlin 				idx_found = true;
5243fd2a6b71SDan Nowlin 			}
5244fd2a6b71SDan Nowlin 
5245fd2a6b71SDan Nowlin 		if (!idx_found) {
5246d54699e2STony Nguyen 			status = -EIO;
5247fd2a6b71SDan Nowlin 			goto err_unroll;
5248fd2a6b71SDan Nowlin 		}
5249fd2a6b71SDan Nowlin 
5250fd2a6b71SDan Nowlin 		recp = &sw->recp_list[entry->rid];
5251fd2a6b71SDan Nowlin 		is_root = (rm->root_rid == entry->rid);
5252fd2a6b71SDan Nowlin 		recp->is_root = is_root;
5253fd2a6b71SDan Nowlin 
5254fd2a6b71SDan Nowlin 		recp->root_rid = entry->rid;
5255fd2a6b71SDan Nowlin 		recp->big_recp = (is_root && rm->n_grp_count > 1);
5256fd2a6b71SDan Nowlin 
5257fd2a6b71SDan Nowlin 		memcpy(&recp->ext_words, entry->r_group.pairs,
5258fd2a6b71SDan Nowlin 		       entry->r_group.n_val_pairs * sizeof(struct ice_fv_word));
5259fd2a6b71SDan Nowlin 
5260fd2a6b71SDan Nowlin 		memcpy(recp->r_bitmap, buf[buf_idx].recipe_bitmap,
5261fd2a6b71SDan Nowlin 		       sizeof(recp->r_bitmap));
5262fd2a6b71SDan Nowlin 
5263fd2a6b71SDan Nowlin 		/* Copy non-result fv index values and masks to recipe. This
5264fd2a6b71SDan Nowlin 		 * call will also update the result recipe bitmask.
5265fd2a6b71SDan Nowlin 		 */
5266fd2a6b71SDan Nowlin 		ice_collect_result_idx(&buf[buf_idx], recp);
5267fd2a6b71SDan Nowlin 
5268fd2a6b71SDan Nowlin 		/* for non-root recipes, also copy to the root, this allows
5269fd2a6b71SDan Nowlin 		 * easier matching of a complete chained recipe
5270fd2a6b71SDan Nowlin 		 */
5271fd2a6b71SDan Nowlin 		if (!is_root)
5272fd2a6b71SDan Nowlin 			ice_collect_result_idx(&buf[buf_idx],
5273fd2a6b71SDan Nowlin 					       &sw->recp_list[rm->root_rid]);
5274fd2a6b71SDan Nowlin 
5275fd2a6b71SDan Nowlin 		recp->n_ext_words = entry->r_group.n_val_pairs;
5276fd2a6b71SDan Nowlin 		recp->chain_idx = entry->chain_idx;
5277fd2a6b71SDan Nowlin 		recp->priority = buf[buf_idx].content.act_ctrl_fwd_priority;
5278fd2a6b71SDan Nowlin 		recp->n_grp_count = rm->n_grp_count;
52798b032a55SMichal Swiatkowski 		recp->tun_type = rm->tun_type;
5280bccd9bceSMarcin Szycik 		recp->need_pass_l2 = rm->need_pass_l2;
5281bccd9bceSMarcin Szycik 		recp->allow_pass_l2 = rm->allow_pass_l2;
5282fd2a6b71SDan Nowlin 		recp->recp_created = true;
5283fd2a6b71SDan Nowlin 	}
5284fd2a6b71SDan Nowlin 	rm->root_buf = buf;
5285fd2a6b71SDan Nowlin 	kfree(tmp);
5286fd2a6b71SDan Nowlin 	return status;
5287fd2a6b71SDan Nowlin 
5288fd2a6b71SDan Nowlin err_unroll:
5289fd2a6b71SDan Nowlin err_mem:
5290fd2a6b71SDan Nowlin 	kfree(tmp);
5291fd2a6b71SDan Nowlin 	devm_kfree(ice_hw_to_dev(hw), buf);
5292fd2a6b71SDan Nowlin 	return status;
5293fd2a6b71SDan Nowlin }
5294fd2a6b71SDan Nowlin 
5295fd2a6b71SDan Nowlin /**
5296fd2a6b71SDan Nowlin  * ice_create_recipe_group - creates recipe group
5297fd2a6b71SDan Nowlin  * @hw: pointer to hardware structure
5298fd2a6b71SDan Nowlin  * @rm: recipe management list entry
5299fd2a6b71SDan Nowlin  * @lkup_exts: lookup elements
5300fd2a6b71SDan Nowlin  */
53015e24d598STony Nguyen static int
5302fd2a6b71SDan Nowlin ice_create_recipe_group(struct ice_hw *hw, struct ice_sw_recipe *rm,
5303fd2a6b71SDan Nowlin 			struct ice_prot_lkup_ext *lkup_exts)
5304fd2a6b71SDan Nowlin {
5305fd2a6b71SDan Nowlin 	u8 recp_count = 0;
53065518ac2aSTony Nguyen 	int status;
5307fd2a6b71SDan Nowlin 
5308fd2a6b71SDan Nowlin 	rm->n_grp_count = 0;
5309fd2a6b71SDan Nowlin 
5310fd2a6b71SDan Nowlin 	/* Create recipes for words that are marked not done by packing them
5311fd2a6b71SDan Nowlin 	 * as best fit.
5312fd2a6b71SDan Nowlin 	 */
5313fd2a6b71SDan Nowlin 	status = ice_create_first_fit_recp_def(hw, lkup_exts,
5314fd2a6b71SDan Nowlin 					       &rm->rg_list, &recp_count);
5315fd2a6b71SDan Nowlin 	if (!status) {
5316fd2a6b71SDan Nowlin 		rm->n_grp_count += recp_count;
5317fd2a6b71SDan Nowlin 		rm->n_ext_words = lkup_exts->n_val_words;
5318fd2a6b71SDan Nowlin 		memcpy(&rm->ext_words, lkup_exts->fv_words,
5319fd2a6b71SDan Nowlin 		       sizeof(rm->ext_words));
5320fd2a6b71SDan Nowlin 		memcpy(rm->word_masks, lkup_exts->field_mask,
5321fd2a6b71SDan Nowlin 		       sizeof(rm->word_masks));
5322fd2a6b71SDan Nowlin 	}
5323fd2a6b71SDan Nowlin 
5324fd2a6b71SDan Nowlin 	return status;
5325fd2a6b71SDan Nowlin }
5326fd2a6b71SDan Nowlin 
5327fd2a6b71SDan Nowlin /* ice_get_compat_fv_bitmap - Get compatible field vector bitmap for rule
5328fd2a6b71SDan Nowlin  * @hw: pointer to hardware structure
5329fd2a6b71SDan Nowlin  * @rinfo: other information regarding the rule e.g. priority and action info
5330fd2a6b71SDan Nowlin  * @bm: pointer to memory for returning the bitmap of field vectors
5331fd2a6b71SDan Nowlin  */
5332fd2a6b71SDan Nowlin static void
5333fd2a6b71SDan Nowlin ice_get_compat_fv_bitmap(struct ice_hw *hw, struct ice_adv_rule_info *rinfo,
5334fd2a6b71SDan Nowlin 			 unsigned long *bm)
5335fd2a6b71SDan Nowlin {
53368b032a55SMichal Swiatkowski 	enum ice_prof_type prof_type;
53378b032a55SMichal Swiatkowski 
5338fd2a6b71SDan Nowlin 	bitmap_zero(bm, ICE_MAX_NUM_PROFILES);
5339fd2a6b71SDan Nowlin 
53408b032a55SMichal Swiatkowski 	switch (rinfo->tun_type) {
53418b032a55SMichal Swiatkowski 	case ICE_NON_TUN:
53428b032a55SMichal Swiatkowski 		prof_type = ICE_PROF_NON_TUN;
53438b032a55SMichal Swiatkowski 		break;
53448b032a55SMichal Swiatkowski 	case ICE_ALL_TUNNELS:
53458b032a55SMichal Swiatkowski 		prof_type = ICE_PROF_TUN_ALL;
53468b032a55SMichal Swiatkowski 		break;
53478b032a55SMichal Swiatkowski 	case ICE_SW_TUN_GENEVE:
53488b032a55SMichal Swiatkowski 	case ICE_SW_TUN_VXLAN:
53498b032a55SMichal Swiatkowski 		prof_type = ICE_PROF_TUN_UDP;
53508b032a55SMichal Swiatkowski 		break;
5351f0a35040SMichal Swiatkowski 	case ICE_SW_TUN_NVGRE:
5352f0a35040SMichal Swiatkowski 		prof_type = ICE_PROF_TUN_GRE;
5353f0a35040SMichal Swiatkowski 		break;
53549a225f81SMarcin Szycik 	case ICE_SW_TUN_GTPU:
53559a225f81SMarcin Szycik 		prof_type = ICE_PROF_TUN_GTPU;
53569a225f81SMarcin Szycik 		break;
53579a225f81SMarcin Szycik 	case ICE_SW_TUN_GTPC:
53589a225f81SMarcin Szycik 		prof_type = ICE_PROF_TUN_GTPC;
53599a225f81SMarcin Szycik 		break;
5360b70bc066SWojciech Drewek 	case ICE_SW_TUN_AND_NON_TUN:
53618b032a55SMichal Swiatkowski 	default:
53628b032a55SMichal Swiatkowski 		prof_type = ICE_PROF_ALL;
53638b032a55SMichal Swiatkowski 		break;
53648b032a55SMichal Swiatkowski 	}
53658b032a55SMichal Swiatkowski 
53668b032a55SMichal Swiatkowski 	ice_get_sw_fv_bitmap(hw, prof_type, bm);
5367fd2a6b71SDan Nowlin }
5368fd2a6b71SDan Nowlin 
5369fd2a6b71SDan Nowlin /**
5370fd2a6b71SDan Nowlin  * ice_add_adv_recipe - Add an advanced recipe that is not part of the default
5371fd2a6b71SDan Nowlin  * @hw: pointer to hardware structure
5372fd2a6b71SDan Nowlin  * @lkups: lookup elements or match criteria for the advanced recipe, one
5373fd2a6b71SDan Nowlin  *  structure per protocol header
5374fd2a6b71SDan Nowlin  * @lkups_cnt: number of protocols
5375fd2a6b71SDan Nowlin  * @rinfo: other information regarding the rule e.g. priority and action info
5376fd2a6b71SDan Nowlin  * @rid: return the recipe ID of the recipe created
5377fd2a6b71SDan Nowlin  */
53785e24d598STony Nguyen static int
5379fd2a6b71SDan Nowlin ice_add_adv_recipe(struct ice_hw *hw, struct ice_adv_lkup_elem *lkups,
5380fd2a6b71SDan Nowlin 		   u16 lkups_cnt, struct ice_adv_rule_info *rinfo, u16 *rid)
5381fd2a6b71SDan Nowlin {
5382fd2a6b71SDan Nowlin 	DECLARE_BITMAP(fv_bitmap, ICE_MAX_NUM_PROFILES);
5383fd2a6b71SDan Nowlin 	DECLARE_BITMAP(profiles, ICE_MAX_NUM_PROFILES);
5384fd2a6b71SDan Nowlin 	struct ice_prot_lkup_ext *lkup_exts;
5385fd2a6b71SDan Nowlin 	struct ice_recp_grp_entry *r_entry;
5386fd2a6b71SDan Nowlin 	struct ice_sw_fv_list_entry *fvit;
5387fd2a6b71SDan Nowlin 	struct ice_recp_grp_entry *r_tmp;
5388fd2a6b71SDan Nowlin 	struct ice_sw_fv_list_entry *tmp;
5389fd2a6b71SDan Nowlin 	struct ice_sw_recipe *rm;
53905518ac2aSTony Nguyen 	int status = 0;
5391fd2a6b71SDan Nowlin 	u8 i;
5392fd2a6b71SDan Nowlin 
5393fd2a6b71SDan Nowlin 	if (!lkups_cnt)
5394d54699e2STony Nguyen 		return -EINVAL;
5395fd2a6b71SDan Nowlin 
5396fd2a6b71SDan Nowlin 	lkup_exts = kzalloc(sizeof(*lkup_exts), GFP_KERNEL);
5397fd2a6b71SDan Nowlin 	if (!lkup_exts)
5398d54699e2STony Nguyen 		return -ENOMEM;
5399fd2a6b71SDan Nowlin 
5400fd2a6b71SDan Nowlin 	/* Determine the number of words to be matched and if it exceeds a
5401fd2a6b71SDan Nowlin 	 * recipe's restrictions
5402fd2a6b71SDan Nowlin 	 */
5403fd2a6b71SDan Nowlin 	for (i = 0; i < lkups_cnt; i++) {
5404fd2a6b71SDan Nowlin 		u16 count;
5405fd2a6b71SDan Nowlin 
5406fd2a6b71SDan Nowlin 		if (lkups[i].type >= ICE_PROTOCOL_LAST) {
5407d54699e2STony Nguyen 			status = -EIO;
5408fd2a6b71SDan Nowlin 			goto err_free_lkup_exts;
5409fd2a6b71SDan Nowlin 		}
5410fd2a6b71SDan Nowlin 
5411fd2a6b71SDan Nowlin 		count = ice_fill_valid_words(&lkups[i], lkup_exts);
5412fd2a6b71SDan Nowlin 		if (!count) {
5413d54699e2STony Nguyen 			status = -EIO;
5414fd2a6b71SDan Nowlin 			goto err_free_lkup_exts;
5415fd2a6b71SDan Nowlin 		}
5416fd2a6b71SDan Nowlin 	}
5417fd2a6b71SDan Nowlin 
5418fd2a6b71SDan Nowlin 	rm = kzalloc(sizeof(*rm), GFP_KERNEL);
5419fd2a6b71SDan Nowlin 	if (!rm) {
5420d54699e2STony Nguyen 		status = -ENOMEM;
5421fd2a6b71SDan Nowlin 		goto err_free_lkup_exts;
5422fd2a6b71SDan Nowlin 	}
5423fd2a6b71SDan Nowlin 
5424fd2a6b71SDan Nowlin 	/* Get field vectors that contain fields extracted from all the protocol
5425fd2a6b71SDan Nowlin 	 * headers being programmed.
5426fd2a6b71SDan Nowlin 	 */
5427fd2a6b71SDan Nowlin 	INIT_LIST_HEAD(&rm->fv_list);
5428fd2a6b71SDan Nowlin 	INIT_LIST_HEAD(&rm->rg_list);
5429fd2a6b71SDan Nowlin 
5430fd2a6b71SDan Nowlin 	/* Get bitmap of field vectors (profiles) that are compatible with the
5431fd2a6b71SDan Nowlin 	 * rule request; only these will be searched in the subsequent call to
5432e5dd661bSMichal Swiatkowski 	 * ice_get_sw_fv_list.
5433fd2a6b71SDan Nowlin 	 */
5434fd2a6b71SDan Nowlin 	ice_get_compat_fv_bitmap(hw, rinfo, fv_bitmap);
5435fd2a6b71SDan Nowlin 
5436e5dd661bSMichal Swiatkowski 	status = ice_get_sw_fv_list(hw, lkup_exts, fv_bitmap, &rm->fv_list);
5437fd2a6b71SDan Nowlin 	if (status)
5438fd2a6b71SDan Nowlin 		goto err_unroll;
5439fd2a6b71SDan Nowlin 
5440fd2a6b71SDan Nowlin 	/* Group match words into recipes using preferred recipe grouping
5441fd2a6b71SDan Nowlin 	 * criteria.
5442fd2a6b71SDan Nowlin 	 */
5443fd2a6b71SDan Nowlin 	status = ice_create_recipe_group(hw, rm, lkup_exts);
5444fd2a6b71SDan Nowlin 	if (status)
5445fd2a6b71SDan Nowlin 		goto err_unroll;
5446fd2a6b71SDan Nowlin 
5447fd2a6b71SDan Nowlin 	/* set the recipe priority if specified */
5448fd2a6b71SDan Nowlin 	rm->priority = (u8)rinfo->priority;
5449fd2a6b71SDan Nowlin 
5450bccd9bceSMarcin Szycik 	rm->need_pass_l2 = rinfo->need_pass_l2;
5451bccd9bceSMarcin Szycik 	rm->allow_pass_l2 = rinfo->allow_pass_l2;
5452bccd9bceSMarcin Szycik 
5453fd2a6b71SDan Nowlin 	/* Find offsets from the field vector. Pick the first one for all the
5454fd2a6b71SDan Nowlin 	 * recipes.
5455fd2a6b71SDan Nowlin 	 */
5456fd2a6b71SDan Nowlin 	status = ice_fill_fv_word_index(hw, &rm->fv_list, &rm->rg_list);
5457fd2a6b71SDan Nowlin 	if (status)
5458fd2a6b71SDan Nowlin 		goto err_unroll;
5459fd2a6b71SDan Nowlin 
5460fd2a6b71SDan Nowlin 	/* get bitmap of all profiles the recipe will be associated with */
5461fd2a6b71SDan Nowlin 	bitmap_zero(profiles, ICE_MAX_NUM_PROFILES);
5462fd2a6b71SDan Nowlin 	list_for_each_entry(fvit, &rm->fv_list, list_entry) {
5463fd2a6b71SDan Nowlin 		ice_debug(hw, ICE_DBG_SW, "profile: %d\n", fvit->profile_id);
5464fd2a6b71SDan Nowlin 		set_bit((u16)fvit->profile_id, profiles);
5465fd2a6b71SDan Nowlin 	}
5466fd2a6b71SDan Nowlin 
5467fd2a6b71SDan Nowlin 	/* Look for a recipe which matches our requested fv / mask list */
5468bccd9bceSMarcin Szycik 	*rid = ice_find_recp(hw, lkup_exts, rinfo);
5469fd2a6b71SDan Nowlin 	if (*rid < ICE_MAX_NUM_RECIPES)
5470fd2a6b71SDan Nowlin 		/* Success if found a recipe that match the existing criteria */
5471fd2a6b71SDan Nowlin 		goto err_unroll;
5472fd2a6b71SDan Nowlin 
5473de6acd1cSMichal Swiatkowski 	rm->tun_type = rinfo->tun_type;
5474fd2a6b71SDan Nowlin 	/* Recipe we need does not exist, add a recipe */
54758b032a55SMichal Swiatkowski 	status = ice_add_sw_recipe(hw, rm, profiles);
5476fd2a6b71SDan Nowlin 	if (status)
5477fd2a6b71SDan Nowlin 		goto err_unroll;
5478fd2a6b71SDan Nowlin 
5479fd2a6b71SDan Nowlin 	/* Associate all the recipes created with all the profiles in the
5480fd2a6b71SDan Nowlin 	 * common field vector.
5481fd2a6b71SDan Nowlin 	 */
5482fd2a6b71SDan Nowlin 	list_for_each_entry(fvit, &rm->fv_list, list_entry) {
5483fd2a6b71SDan Nowlin 		DECLARE_BITMAP(r_bitmap, ICE_MAX_NUM_RECIPES);
5484fd2a6b71SDan Nowlin 		u16 j;
5485fd2a6b71SDan Nowlin 
5486fd2a6b71SDan Nowlin 		status = ice_aq_get_recipe_to_profile(hw, fvit->profile_id,
5487fd2a6b71SDan Nowlin 						      (u8 *)r_bitmap, NULL);
5488fd2a6b71SDan Nowlin 		if (status)
5489fd2a6b71SDan Nowlin 			goto err_unroll;
5490fd2a6b71SDan Nowlin 
5491fd2a6b71SDan Nowlin 		bitmap_or(r_bitmap, r_bitmap, rm->r_bitmap,
5492fd2a6b71SDan Nowlin 			  ICE_MAX_NUM_RECIPES);
5493fd2a6b71SDan Nowlin 		status = ice_acquire_change_lock(hw, ICE_RES_WRITE);
5494fd2a6b71SDan Nowlin 		if (status)
5495fd2a6b71SDan Nowlin 			goto err_unroll;
5496fd2a6b71SDan Nowlin 
5497fd2a6b71SDan Nowlin 		status = ice_aq_map_recipe_to_profile(hw, fvit->profile_id,
5498fd2a6b71SDan Nowlin 						      (u8 *)r_bitmap,
5499fd2a6b71SDan Nowlin 						      NULL);
5500fd2a6b71SDan Nowlin 		ice_release_change_lock(hw);
5501fd2a6b71SDan Nowlin 
5502fd2a6b71SDan Nowlin 		if (status)
5503fd2a6b71SDan Nowlin 			goto err_unroll;
5504fd2a6b71SDan Nowlin 
5505fd2a6b71SDan Nowlin 		/* Update profile to recipe bitmap array */
5506fd2a6b71SDan Nowlin 		bitmap_copy(profile_to_recipe[fvit->profile_id], r_bitmap,
5507fd2a6b71SDan Nowlin 			    ICE_MAX_NUM_RECIPES);
5508fd2a6b71SDan Nowlin 
5509fd2a6b71SDan Nowlin 		/* Update recipe to profile bitmap array */
5510fd2a6b71SDan Nowlin 		for_each_set_bit(j, rm->r_bitmap, ICE_MAX_NUM_RECIPES)
5511fd2a6b71SDan Nowlin 			set_bit((u16)fvit->profile_id, recipe_to_profile[j]);
5512fd2a6b71SDan Nowlin 	}
5513fd2a6b71SDan Nowlin 
5514fd2a6b71SDan Nowlin 	*rid = rm->root_rid;
5515fd2a6b71SDan Nowlin 	memcpy(&hw->switch_info->recp_list[*rid].lkup_exts, lkup_exts,
5516fd2a6b71SDan Nowlin 	       sizeof(*lkup_exts));
5517fd2a6b71SDan Nowlin err_unroll:
5518fd2a6b71SDan Nowlin 	list_for_each_entry_safe(r_entry, r_tmp, &rm->rg_list, l_entry) {
5519fd2a6b71SDan Nowlin 		list_del(&r_entry->l_entry);
5520fd2a6b71SDan Nowlin 		devm_kfree(ice_hw_to_dev(hw), r_entry);
5521fd2a6b71SDan Nowlin 	}
5522fd2a6b71SDan Nowlin 
5523fd2a6b71SDan Nowlin 	list_for_each_entry_safe(fvit, tmp, &rm->fv_list, list_entry) {
5524fd2a6b71SDan Nowlin 		list_del(&fvit->list_entry);
5525fd2a6b71SDan Nowlin 		devm_kfree(ice_hw_to_dev(hw), fvit);
5526fd2a6b71SDan Nowlin 	}
5527fd2a6b71SDan Nowlin 
5528fd2a6b71SDan Nowlin 	devm_kfree(ice_hw_to_dev(hw), rm->root_buf);
5529fd2a6b71SDan Nowlin 	kfree(rm);
5530fd2a6b71SDan Nowlin 
5531fd2a6b71SDan Nowlin err_free_lkup_exts:
5532fd2a6b71SDan Nowlin 	kfree(lkup_exts);
5533fd2a6b71SDan Nowlin 
5534fd2a6b71SDan Nowlin 	return status;
5535fd2a6b71SDan Nowlin }
5536fd2a6b71SDan Nowlin 
5537148beb61SHenry Tieman /**
553826395726SMartyna Szapar-Mudlaw  * ice_dummy_packet_add_vlan - insert VLAN header to dummy pkt
553926395726SMartyna Szapar-Mudlaw  *
554026395726SMartyna Szapar-Mudlaw  * @dummy_pkt: dummy packet profile pattern to which VLAN tag(s) will be added
554126395726SMartyna Szapar-Mudlaw  * @num_vlan: number of VLAN tags
554226395726SMartyna Szapar-Mudlaw  */
554326395726SMartyna Szapar-Mudlaw static struct ice_dummy_pkt_profile *
554426395726SMartyna Szapar-Mudlaw ice_dummy_packet_add_vlan(const struct ice_dummy_pkt_profile *dummy_pkt,
554526395726SMartyna Szapar-Mudlaw 			  u32 num_vlan)
554626395726SMartyna Szapar-Mudlaw {
554726395726SMartyna Szapar-Mudlaw 	struct ice_dummy_pkt_profile *profile;
554826395726SMartyna Szapar-Mudlaw 	struct ice_dummy_pkt_offsets *offsets;
554926395726SMartyna Szapar-Mudlaw 	u32 buf_len, off, etype_off, i;
555026395726SMartyna Szapar-Mudlaw 	u8 *pkt;
555126395726SMartyna Szapar-Mudlaw 
555226395726SMartyna Szapar-Mudlaw 	if (num_vlan < 1 || num_vlan > 2)
555326395726SMartyna Szapar-Mudlaw 		return ERR_PTR(-EINVAL);
555426395726SMartyna Szapar-Mudlaw 
555526395726SMartyna Szapar-Mudlaw 	off = num_vlan * VLAN_HLEN;
555626395726SMartyna Szapar-Mudlaw 
555726395726SMartyna Szapar-Mudlaw 	buf_len = array_size(num_vlan, sizeof(ice_dummy_vlan_packet_offsets)) +
555826395726SMartyna Szapar-Mudlaw 		  dummy_pkt->offsets_len;
555926395726SMartyna Szapar-Mudlaw 	offsets = kzalloc(buf_len, GFP_KERNEL);
556026395726SMartyna Szapar-Mudlaw 	if (!offsets)
556126395726SMartyna Szapar-Mudlaw 		return ERR_PTR(-ENOMEM);
556226395726SMartyna Szapar-Mudlaw 
556326395726SMartyna Szapar-Mudlaw 	offsets[0] = dummy_pkt->offsets[0];
556426395726SMartyna Szapar-Mudlaw 	if (num_vlan == 2) {
556526395726SMartyna Szapar-Mudlaw 		offsets[1] = ice_dummy_qinq_packet_offsets[0];
556626395726SMartyna Szapar-Mudlaw 		offsets[2] = ice_dummy_qinq_packet_offsets[1];
556726395726SMartyna Szapar-Mudlaw 	} else if (num_vlan == 1) {
556826395726SMartyna Szapar-Mudlaw 		offsets[1] = ice_dummy_vlan_packet_offsets[0];
556926395726SMartyna Szapar-Mudlaw 	}
557026395726SMartyna Szapar-Mudlaw 
557126395726SMartyna Szapar-Mudlaw 	for (i = 1; dummy_pkt->offsets[i].type != ICE_PROTOCOL_LAST; i++) {
557226395726SMartyna Szapar-Mudlaw 		offsets[i + num_vlan].type = dummy_pkt->offsets[i].type;
557326395726SMartyna Szapar-Mudlaw 		offsets[i + num_vlan].offset =
557426395726SMartyna Szapar-Mudlaw 			dummy_pkt->offsets[i].offset + off;
557526395726SMartyna Szapar-Mudlaw 	}
557626395726SMartyna Szapar-Mudlaw 	offsets[i + num_vlan] = dummy_pkt->offsets[i];
557726395726SMartyna Szapar-Mudlaw 
557826395726SMartyna Szapar-Mudlaw 	etype_off = dummy_pkt->offsets[1].offset;
557926395726SMartyna Szapar-Mudlaw 
558026395726SMartyna Szapar-Mudlaw 	buf_len = array_size(num_vlan, sizeof(ice_dummy_vlan_packet)) +
558126395726SMartyna Szapar-Mudlaw 		  dummy_pkt->pkt_len;
558226395726SMartyna Szapar-Mudlaw 	pkt = kzalloc(buf_len, GFP_KERNEL);
558326395726SMartyna Szapar-Mudlaw 	if (!pkt) {
558426395726SMartyna Szapar-Mudlaw 		kfree(offsets);
558526395726SMartyna Szapar-Mudlaw 		return ERR_PTR(-ENOMEM);
558626395726SMartyna Szapar-Mudlaw 	}
558726395726SMartyna Szapar-Mudlaw 
558826395726SMartyna Szapar-Mudlaw 	memcpy(pkt, dummy_pkt->pkt, etype_off);
558926395726SMartyna Szapar-Mudlaw 	memcpy(pkt + etype_off,
559026395726SMartyna Szapar-Mudlaw 	       num_vlan == 2 ? ice_dummy_qinq_packet : ice_dummy_vlan_packet,
559126395726SMartyna Szapar-Mudlaw 	       off);
559226395726SMartyna Szapar-Mudlaw 	memcpy(pkt + etype_off + off, dummy_pkt->pkt + etype_off,
559326395726SMartyna Szapar-Mudlaw 	       dummy_pkt->pkt_len - etype_off);
559426395726SMartyna Szapar-Mudlaw 
559526395726SMartyna Szapar-Mudlaw 	profile = kzalloc(sizeof(*profile), GFP_KERNEL);
559626395726SMartyna Szapar-Mudlaw 	if (!profile) {
559726395726SMartyna Szapar-Mudlaw 		kfree(offsets);
559826395726SMartyna Szapar-Mudlaw 		kfree(pkt);
559926395726SMartyna Szapar-Mudlaw 		return ERR_PTR(-ENOMEM);
560026395726SMartyna Szapar-Mudlaw 	}
560126395726SMartyna Szapar-Mudlaw 
560226395726SMartyna Szapar-Mudlaw 	profile->offsets = offsets;
560326395726SMartyna Szapar-Mudlaw 	profile->pkt = pkt;
560426395726SMartyna Szapar-Mudlaw 	profile->pkt_len = buf_len;
560526395726SMartyna Szapar-Mudlaw 	profile->match |= ICE_PKT_KMALLOC;
560626395726SMartyna Szapar-Mudlaw 
560726395726SMartyna Szapar-Mudlaw 	return profile;
560826395726SMartyna Szapar-Mudlaw }
560926395726SMartyna Szapar-Mudlaw 
561026395726SMartyna Szapar-Mudlaw /**
56110f94570dSGrishma Kotecha  * ice_find_dummy_packet - find dummy packet
56120f94570dSGrishma Kotecha  *
56130f94570dSGrishma Kotecha  * @lkups: lookup elements or match criteria for the advanced recipe, one
56140f94570dSGrishma Kotecha  *	   structure per protocol header
56150f94570dSGrishma Kotecha  * @lkups_cnt: number of protocols
56168b032a55SMichal Swiatkowski  * @tun_type: tunnel type
56171b699f81SAlexander Lobakin  *
56181b699f81SAlexander Lobakin  * Returns the &ice_dummy_pkt_profile corresponding to these lookup params.
56190f94570dSGrishma Kotecha  */
5620e33163a4SAlexander Lobakin static const struct ice_dummy_pkt_profile *
56210f94570dSGrishma Kotecha ice_find_dummy_packet(struct ice_adv_lkup_elem *lkups, u16 lkups_cnt,
56221b699f81SAlexander Lobakin 		      enum ice_sw_tunnel_type tun_type)
56230f94570dSGrishma Kotecha {
5624e33163a4SAlexander Lobakin 	const struct ice_dummy_pkt_profile *ret = ice_dummy_pkt_profiles;
562526395726SMartyna Szapar-Mudlaw 	u32 match = 0, vlan_count = 0;
56260f94570dSGrishma Kotecha 	u16 i;
56270f94570dSGrishma Kotecha 
5628e33163a4SAlexander Lobakin 	switch (tun_type) {
5629e33163a4SAlexander Lobakin 	case ICE_SW_TUN_GTPC:
5630e33163a4SAlexander Lobakin 		match |= ICE_PKT_TUN_GTPC;
5631e33163a4SAlexander Lobakin 		break;
5632e33163a4SAlexander Lobakin 	case ICE_SW_TUN_GTPU:
5633e33163a4SAlexander Lobakin 		match |= ICE_PKT_TUN_GTPU;
5634e33163a4SAlexander Lobakin 		break;
5635e33163a4SAlexander Lobakin 	case ICE_SW_TUN_NVGRE:
5636e33163a4SAlexander Lobakin 		match |= ICE_PKT_TUN_NVGRE;
5637e33163a4SAlexander Lobakin 		break;
5638e33163a4SAlexander Lobakin 	case ICE_SW_TUN_GENEVE:
5639e33163a4SAlexander Lobakin 	case ICE_SW_TUN_VXLAN:
5640e33163a4SAlexander Lobakin 		match |= ICE_PKT_TUN_UDP;
5641e33163a4SAlexander Lobakin 		break;
5642e33163a4SAlexander Lobakin 	default:
5643e33163a4SAlexander Lobakin 		break;
5644e33163a4SAlexander Lobakin 	}
5645e33163a4SAlexander Lobakin 
56460f94570dSGrishma Kotecha 	for (i = 0; i < lkups_cnt; i++) {
56470f94570dSGrishma Kotecha 		if (lkups[i].type == ICE_UDP_ILOS)
5648e33163a4SAlexander Lobakin 			match |= ICE_PKT_INNER_UDP;
56490f94570dSGrishma Kotecha 		else if (lkups[i].type == ICE_TCP_IL)
5650e33163a4SAlexander Lobakin 			match |= ICE_PKT_INNER_TCP;
56510f94570dSGrishma Kotecha 		else if (lkups[i].type == ICE_IPV6_OFOS)
5652e33163a4SAlexander Lobakin 			match |= ICE_PKT_OUTER_IPV6;
565306bca7c2SMartyna Szapar-Mudlaw 		else if (lkups[i].type == ICE_VLAN_OFOS ||
565406bca7c2SMartyna Szapar-Mudlaw 			 lkups[i].type == ICE_VLAN_EX)
565526395726SMartyna Szapar-Mudlaw 			vlan_count++;
565606bca7c2SMartyna Szapar-Mudlaw 		else if (lkups[i].type == ICE_VLAN_IN)
565726395726SMartyna Szapar-Mudlaw 			vlan_count++;
56580f94570dSGrishma Kotecha 		else if (lkups[i].type == ICE_ETYPE_OL &&
56590f94570dSGrishma Kotecha 			 lkups[i].h_u.ethertype.ethtype_id ==
56600f94570dSGrishma Kotecha 				cpu_to_be16(ICE_IPV6_ETHER_ID) &&
56610f94570dSGrishma Kotecha 			 lkups[i].m_u.ethertype.ethtype_id ==
56620f94570dSGrishma Kotecha 				cpu_to_be16(0xFFFF))
5663e33163a4SAlexander Lobakin 			match |= ICE_PKT_OUTER_IPV6;
566434a89775SMartyna Szapar-Mudlaw 		else if (lkups[i].type == ICE_ETYPE_IL &&
566534a89775SMartyna Szapar-Mudlaw 			 lkups[i].h_u.ethertype.ethtype_id ==
566634a89775SMartyna Szapar-Mudlaw 				cpu_to_be16(ICE_IPV6_ETHER_ID) &&
566734a89775SMartyna Szapar-Mudlaw 			 lkups[i].m_u.ethertype.ethtype_id ==
566834a89775SMartyna Szapar-Mudlaw 				cpu_to_be16(0xFFFF))
5669e33163a4SAlexander Lobakin 			match |= ICE_PKT_INNER_IPV6;
56709a225f81SMarcin Szycik 		else if (lkups[i].type == ICE_IPV6_IL)
5671e33163a4SAlexander Lobakin 			match |= ICE_PKT_INNER_IPV6;
56729a225f81SMarcin Szycik 		else if (lkups[i].type == ICE_GTP_NO_PAY)
5673e33163a4SAlexander Lobakin 			match |= ICE_PKT_GTP_NOPAY;
5674cd8efeeeSMarcin Szycik 		else if (lkups[i].type == ICE_PPPOE) {
5675cd8efeeeSMarcin Szycik 			match |= ICE_PKT_PPPOE;
5676cd8efeeeSMarcin Szycik 			if (lkups[i].h_u.pppoe_hdr.ppp_prot_id ==
5677cd8efeeeSMarcin Szycik 			    htons(PPP_IPV6))
5678cd8efeeeSMarcin Szycik 				match |= ICE_PKT_OUTER_IPV6;
5679cd634549SMarcin Szycik 		} else if (lkups[i].type == ICE_L2TPV3)
5680cd634549SMarcin Szycik 			match |= ICE_PKT_L2TPV3;
56819a225f81SMarcin Szycik 	}
56829a225f81SMarcin Szycik 
5683e33163a4SAlexander Lobakin 	while (ret->match && (match & ret->match) != ret->match)
5684e33163a4SAlexander Lobakin 		ret++;
56859a225f81SMarcin Szycik 
568626395726SMartyna Szapar-Mudlaw 	if (vlan_count != 0)
568726395726SMartyna Szapar-Mudlaw 		ret = ice_dummy_packet_add_vlan(ret, vlan_count);
568826395726SMartyna Szapar-Mudlaw 
5689e33163a4SAlexander Lobakin 	return ret;
56900f94570dSGrishma Kotecha }
56910f94570dSGrishma Kotecha 
56920f94570dSGrishma Kotecha /**
56930f94570dSGrishma Kotecha  * ice_fill_adv_dummy_packet - fill a dummy packet with given match criteria
56940f94570dSGrishma Kotecha  *
56950f94570dSGrishma Kotecha  * @lkups: lookup elements or match criteria for the advanced recipe, one
56960f94570dSGrishma Kotecha  *	   structure per protocol header
56970f94570dSGrishma Kotecha  * @lkups_cnt: number of protocols
56980f94570dSGrishma Kotecha  * @s_rule: stores rule information from the match criteria
56991b699f81SAlexander Lobakin  * @profile: dummy packet profile (the template, its size and header offsets)
57000f94570dSGrishma Kotecha  */
57015e24d598STony Nguyen static int
57020f94570dSGrishma Kotecha ice_fill_adv_dummy_packet(struct ice_adv_lkup_elem *lkups, u16 lkups_cnt,
57036e1ff618SAlexander Lobakin 			  struct ice_sw_rule_lkup_rx_tx *s_rule,
57041b699f81SAlexander Lobakin 			  const struct ice_dummy_pkt_profile *profile)
57050f94570dSGrishma Kotecha {
57060f94570dSGrishma Kotecha 	u8 *pkt;
57070f94570dSGrishma Kotecha 	u16 i;
57080f94570dSGrishma Kotecha 
57090f94570dSGrishma Kotecha 	/* Start with a packet with a pre-defined/dummy content. Then, fill
57100f94570dSGrishma Kotecha 	 * in the header values to be looked up or matched.
57110f94570dSGrishma Kotecha 	 */
57126e1ff618SAlexander Lobakin 	pkt = s_rule->hdr_data;
57130f94570dSGrishma Kotecha 
57141b699f81SAlexander Lobakin 	memcpy(pkt, profile->pkt, profile->pkt_len);
57150f94570dSGrishma Kotecha 
57160f94570dSGrishma Kotecha 	for (i = 0; i < lkups_cnt; i++) {
57171b699f81SAlexander Lobakin 		const struct ice_dummy_pkt_offsets *offsets = profile->offsets;
57180f94570dSGrishma Kotecha 		enum ice_protocol_type type;
57190f94570dSGrishma Kotecha 		u16 offset = 0, len = 0, j;
57200f94570dSGrishma Kotecha 		bool found = false;
57210f94570dSGrishma Kotecha 
57220f94570dSGrishma Kotecha 		/* find the start of this layer; it should be found since this
57230f94570dSGrishma Kotecha 		 * was already checked when search for the dummy packet
57240f94570dSGrishma Kotecha 		 */
57250f94570dSGrishma Kotecha 		type = lkups[i].type;
572603592a14SMichal Swiatkowski 		/* metadata isn't present in the packet */
572703592a14SMichal Swiatkowski 		if (type == ICE_HW_METADATA)
572803592a14SMichal Swiatkowski 			continue;
572903592a14SMichal Swiatkowski 
57300f94570dSGrishma Kotecha 		for (j = 0; offsets[j].type != ICE_PROTOCOL_LAST; j++) {
57310f94570dSGrishma Kotecha 			if (type == offsets[j].type) {
57320f94570dSGrishma Kotecha 				offset = offsets[j].offset;
57330f94570dSGrishma Kotecha 				found = true;
57340f94570dSGrishma Kotecha 				break;
57350f94570dSGrishma Kotecha 			}
57360f94570dSGrishma Kotecha 		}
57370f94570dSGrishma Kotecha 		/* this should never happen in a correct calling sequence */
57380f94570dSGrishma Kotecha 		if (!found)
5739d54699e2STony Nguyen 			return -EINVAL;
57400f94570dSGrishma Kotecha 
57410f94570dSGrishma Kotecha 		switch (lkups[i].type) {
57420f94570dSGrishma Kotecha 		case ICE_MAC_OFOS:
57430f94570dSGrishma Kotecha 		case ICE_MAC_IL:
57440f94570dSGrishma Kotecha 			len = sizeof(struct ice_ether_hdr);
57450f94570dSGrishma Kotecha 			break;
57460f94570dSGrishma Kotecha 		case ICE_ETYPE_OL:
574734a89775SMartyna Szapar-Mudlaw 		case ICE_ETYPE_IL:
57480f94570dSGrishma Kotecha 			len = sizeof(struct ice_ethtype_hdr);
57490f94570dSGrishma Kotecha 			break;
57500f94570dSGrishma Kotecha 		case ICE_VLAN_OFOS:
575106bca7c2SMartyna Szapar-Mudlaw 		case ICE_VLAN_EX:
575206bca7c2SMartyna Szapar-Mudlaw 		case ICE_VLAN_IN:
57530f94570dSGrishma Kotecha 			len = sizeof(struct ice_vlan_hdr);
57540f94570dSGrishma Kotecha 			break;
57550f94570dSGrishma Kotecha 		case ICE_IPV4_OFOS:
57560f94570dSGrishma Kotecha 		case ICE_IPV4_IL:
57570f94570dSGrishma Kotecha 			len = sizeof(struct ice_ipv4_hdr);
57580f94570dSGrishma Kotecha 			break;
57590f94570dSGrishma Kotecha 		case ICE_IPV6_OFOS:
57600f94570dSGrishma Kotecha 		case ICE_IPV6_IL:
57610f94570dSGrishma Kotecha 			len = sizeof(struct ice_ipv6_hdr);
57620f94570dSGrishma Kotecha 			break;
57630f94570dSGrishma Kotecha 		case ICE_TCP_IL:
57640f94570dSGrishma Kotecha 		case ICE_UDP_OF:
57650f94570dSGrishma Kotecha 		case ICE_UDP_ILOS:
57660f94570dSGrishma Kotecha 			len = sizeof(struct ice_l4_hdr);
57670f94570dSGrishma Kotecha 			break;
57680f94570dSGrishma Kotecha 		case ICE_SCTP_IL:
57690f94570dSGrishma Kotecha 			len = sizeof(struct ice_sctp_hdr);
57700f94570dSGrishma Kotecha 			break;
5771f0a35040SMichal Swiatkowski 		case ICE_NVGRE:
5772f0a35040SMichal Swiatkowski 			len = sizeof(struct ice_nvgre_hdr);
5773f0a35040SMichal Swiatkowski 			break;
57748b032a55SMichal Swiatkowski 		case ICE_VXLAN:
57758b032a55SMichal Swiatkowski 		case ICE_GENEVE:
57768b032a55SMichal Swiatkowski 			len = sizeof(struct ice_udp_tnl_hdr);
57778b032a55SMichal Swiatkowski 			break;
57789a225f81SMarcin Szycik 		case ICE_GTP_NO_PAY:
57799a225f81SMarcin Szycik 		case ICE_GTP:
57809a225f81SMarcin Szycik 			len = sizeof(struct ice_udp_gtp_hdr);
57819a225f81SMarcin Szycik 			break;
5782cd8efeeeSMarcin Szycik 		case ICE_PPPOE:
5783cd8efeeeSMarcin Szycik 			len = sizeof(struct ice_pppoe_hdr);
5784cd8efeeeSMarcin Szycik 			break;
5785cd634549SMarcin Szycik 		case ICE_L2TPV3:
5786cd634549SMarcin Szycik 			len = sizeof(struct ice_l2tpv3_sess_hdr);
5787cd634549SMarcin Szycik 			break;
57880f94570dSGrishma Kotecha 		default:
5789d54699e2STony Nguyen 			return -EINVAL;
57900f94570dSGrishma Kotecha 		}
57910f94570dSGrishma Kotecha 
57920f94570dSGrishma Kotecha 		/* the length should be a word multiple */
57930f94570dSGrishma Kotecha 		if (len % ICE_BYTES_PER_WORD)
5794d54699e2STony Nguyen 			return -EIO;
57950f94570dSGrishma Kotecha 
57960f94570dSGrishma Kotecha 		/* We have the offset to the header start, the length, the
57970f94570dSGrishma Kotecha 		 * caller's header values and mask. Use this information to
57980f94570dSGrishma Kotecha 		 * copy the data into the dummy packet appropriately based on
57990f94570dSGrishma Kotecha 		 * the mask. Note that we need to only write the bits as
58000f94570dSGrishma Kotecha 		 * indicated by the mask to make sure we don't improperly write
58010f94570dSGrishma Kotecha 		 * over any significant packet data.
58020f94570dSGrishma Kotecha 		 */
580327ffa273SAlexander Lobakin 		for (j = 0; j < len / sizeof(u16); j++) {
580427ffa273SAlexander Lobakin 			u16 *ptr = (u16 *)(pkt + offset);
580527ffa273SAlexander Lobakin 			u16 mask = lkups[i].m_raw[j];
580627ffa273SAlexander Lobakin 
580727ffa273SAlexander Lobakin 			if (!mask)
580827ffa273SAlexander Lobakin 				continue;
580927ffa273SAlexander Lobakin 
581027ffa273SAlexander Lobakin 			ptr[j] = (ptr[j] & ~mask) | (lkups[i].h_raw[j] & mask);
581127ffa273SAlexander Lobakin 		}
58120f94570dSGrishma Kotecha 	}
58130f94570dSGrishma Kotecha 
58146e1ff618SAlexander Lobakin 	s_rule->hdr_len = cpu_to_le16(profile->pkt_len);
58150f94570dSGrishma Kotecha 
58160f94570dSGrishma Kotecha 	return 0;
58170f94570dSGrishma Kotecha }
58180f94570dSGrishma Kotecha 
58190f94570dSGrishma Kotecha /**
58208b032a55SMichal Swiatkowski  * ice_fill_adv_packet_tun - fill dummy packet with udp tunnel port
58218b032a55SMichal Swiatkowski  * @hw: pointer to the hardware structure
58228b032a55SMichal Swiatkowski  * @tun_type: tunnel type
58238b032a55SMichal Swiatkowski  * @pkt: dummy packet to fill in
58248b032a55SMichal Swiatkowski  * @offsets: offset info for the dummy packet
58258b032a55SMichal Swiatkowski  */
5826d54699e2STony Nguyen static int
58278b032a55SMichal Swiatkowski ice_fill_adv_packet_tun(struct ice_hw *hw, enum ice_sw_tunnel_type tun_type,
58288b032a55SMichal Swiatkowski 			u8 *pkt, const struct ice_dummy_pkt_offsets *offsets)
58298b032a55SMichal Swiatkowski {
58308b032a55SMichal Swiatkowski 	u16 open_port, i;
58318b032a55SMichal Swiatkowski 
58328b032a55SMichal Swiatkowski 	switch (tun_type) {
58338b032a55SMichal Swiatkowski 	case ICE_SW_TUN_VXLAN:
5834de6acd1cSMichal Swiatkowski 		if (!ice_get_open_tunnel_port(hw, &open_port, TNL_VXLAN))
5835d54699e2STony Nguyen 			return -EIO;
58368b032a55SMichal Swiatkowski 		break;
5837de6acd1cSMichal Swiatkowski 	case ICE_SW_TUN_GENEVE:
5838de6acd1cSMichal Swiatkowski 		if (!ice_get_open_tunnel_port(hw, &open_port, TNL_GENEVE))
5839d54699e2STony Nguyen 			return -EIO;
5840de6acd1cSMichal Swiatkowski 		break;
58418b032a55SMichal Swiatkowski 	default:
58428b032a55SMichal Swiatkowski 		/* Nothing needs to be done for this tunnel type */
58438b032a55SMichal Swiatkowski 		return 0;
58448b032a55SMichal Swiatkowski 	}
58458b032a55SMichal Swiatkowski 
58468b032a55SMichal Swiatkowski 	/* Find the outer UDP protocol header and insert the port number */
58478b032a55SMichal Swiatkowski 	for (i = 0; offsets[i].type != ICE_PROTOCOL_LAST; i++) {
58488b032a55SMichal Swiatkowski 		if (offsets[i].type == ICE_UDP_OF) {
58498b032a55SMichal Swiatkowski 			struct ice_l4_hdr *hdr;
58508b032a55SMichal Swiatkowski 			u16 offset;
58518b032a55SMichal Swiatkowski 
58528b032a55SMichal Swiatkowski 			offset = offsets[i].offset;
58538b032a55SMichal Swiatkowski 			hdr = (struct ice_l4_hdr *)&pkt[offset];
58548b032a55SMichal Swiatkowski 			hdr->dst_port = cpu_to_be16(open_port);
58558b032a55SMichal Swiatkowski 
58568b032a55SMichal Swiatkowski 			return 0;
58578b032a55SMichal Swiatkowski 		}
58588b032a55SMichal Swiatkowski 	}
58598b032a55SMichal Swiatkowski 
5860d54699e2STony Nguyen 	return -EIO;
58618b032a55SMichal Swiatkowski }
58628b032a55SMichal Swiatkowski 
58638b032a55SMichal Swiatkowski /**
5864ea71b967SMartyna Szapar-Mudlaw  * ice_fill_adv_packet_vlan - fill dummy packet with VLAN tag type
586503592a14SMichal Swiatkowski  * @hw: pointer to hw structure
5866ea71b967SMartyna Szapar-Mudlaw  * @vlan_type: VLAN tag type
5867ea71b967SMartyna Szapar-Mudlaw  * @pkt: dummy packet to fill in
5868ea71b967SMartyna Szapar-Mudlaw  * @offsets: offset info for the dummy packet
5869ea71b967SMartyna Szapar-Mudlaw  */
5870ea71b967SMartyna Szapar-Mudlaw static int
587103592a14SMichal Swiatkowski ice_fill_adv_packet_vlan(struct ice_hw *hw, u16 vlan_type, u8 *pkt,
5872ea71b967SMartyna Szapar-Mudlaw 			 const struct ice_dummy_pkt_offsets *offsets)
5873ea71b967SMartyna Szapar-Mudlaw {
5874ea71b967SMartyna Szapar-Mudlaw 	u16 i;
5875ea71b967SMartyna Szapar-Mudlaw 
587603592a14SMichal Swiatkowski 	/* Check if there is something to do */
587703592a14SMichal Swiatkowski 	if (!vlan_type || !ice_is_dvm_ena(hw))
587803592a14SMichal Swiatkowski 		return 0;
587903592a14SMichal Swiatkowski 
5880ea71b967SMartyna Szapar-Mudlaw 	/* Find VLAN header and insert VLAN TPID */
5881ea71b967SMartyna Szapar-Mudlaw 	for (i = 0; offsets[i].type != ICE_PROTOCOL_LAST; i++) {
5882ea71b967SMartyna Szapar-Mudlaw 		if (offsets[i].type == ICE_VLAN_OFOS ||
5883ea71b967SMartyna Szapar-Mudlaw 		    offsets[i].type == ICE_VLAN_EX) {
5884ea71b967SMartyna Szapar-Mudlaw 			struct ice_vlan_hdr *hdr;
5885ea71b967SMartyna Szapar-Mudlaw 			u16 offset;
5886ea71b967SMartyna Szapar-Mudlaw 
5887ea71b967SMartyna Szapar-Mudlaw 			offset = offsets[i].offset;
5888ea71b967SMartyna Szapar-Mudlaw 			hdr = (struct ice_vlan_hdr *)&pkt[offset];
5889ea71b967SMartyna Szapar-Mudlaw 			hdr->type = cpu_to_be16(vlan_type);
5890ea71b967SMartyna Szapar-Mudlaw 
5891ea71b967SMartyna Szapar-Mudlaw 			return 0;
5892ea71b967SMartyna Szapar-Mudlaw 		}
5893ea71b967SMartyna Szapar-Mudlaw 	}
5894ea71b967SMartyna Szapar-Mudlaw 
5895ea71b967SMartyna Szapar-Mudlaw 	return -EIO;
5896ea71b967SMartyna Szapar-Mudlaw }
5897ea71b967SMartyna Szapar-Mudlaw 
589803592a14SMichal Swiatkowski static bool ice_rules_equal(const struct ice_adv_rule_info *first,
589903592a14SMichal Swiatkowski 			    const struct ice_adv_rule_info *second)
590003592a14SMichal Swiatkowski {
590103592a14SMichal Swiatkowski 	return first->sw_act.flag == second->sw_act.flag &&
590203592a14SMichal Swiatkowski 	       first->tun_type == second->tun_type &&
590303592a14SMichal Swiatkowski 	       first->vlan_type == second->vlan_type &&
5904bccd9bceSMarcin Szycik 	       first->src_vsi == second->src_vsi &&
5905bccd9bceSMarcin Szycik 	       first->need_pass_l2 == second->need_pass_l2 &&
5906bccd9bceSMarcin Szycik 	       first->allow_pass_l2 == second->allow_pass_l2;
590703592a14SMichal Swiatkowski }
590803592a14SMichal Swiatkowski 
5909ea71b967SMartyna Szapar-Mudlaw /**
59100f94570dSGrishma Kotecha  * ice_find_adv_rule_entry - Search a rule entry
59110f94570dSGrishma Kotecha  * @hw: pointer to the hardware structure
59120f94570dSGrishma Kotecha  * @lkups: lookup elements or match criteria for the advanced recipe, one
59130f94570dSGrishma Kotecha  *	   structure per protocol header
59140f94570dSGrishma Kotecha  * @lkups_cnt: number of protocols
59150f94570dSGrishma Kotecha  * @recp_id: recipe ID for which we are finding the rule
59160f94570dSGrishma Kotecha  * @rinfo: other information regarding the rule e.g. priority and action info
59170f94570dSGrishma Kotecha  *
59180f94570dSGrishma Kotecha  * Helper function to search for a given advance rule entry
59190f94570dSGrishma Kotecha  * Returns pointer to entry storing the rule if found
59200f94570dSGrishma Kotecha  */
59210f94570dSGrishma Kotecha static struct ice_adv_fltr_mgmt_list_entry *
59220f94570dSGrishma Kotecha ice_find_adv_rule_entry(struct ice_hw *hw, struct ice_adv_lkup_elem *lkups,
59230f94570dSGrishma Kotecha 			u16 lkups_cnt, u16 recp_id,
59240f94570dSGrishma Kotecha 			struct ice_adv_rule_info *rinfo)
59250f94570dSGrishma Kotecha {
59260f94570dSGrishma Kotecha 	struct ice_adv_fltr_mgmt_list_entry *list_itr;
59270f94570dSGrishma Kotecha 	struct ice_switch_info *sw = hw->switch_info;
59280f94570dSGrishma Kotecha 	int i;
59290f94570dSGrishma Kotecha 
59300f94570dSGrishma Kotecha 	list_for_each_entry(list_itr, &sw->recp_list[recp_id].filt_rules,
59310f94570dSGrishma Kotecha 			    list_entry) {
59320f94570dSGrishma Kotecha 		bool lkups_matched = true;
59330f94570dSGrishma Kotecha 
59340f94570dSGrishma Kotecha 		if (lkups_cnt != list_itr->lkups_cnt)
59350f94570dSGrishma Kotecha 			continue;
59360f94570dSGrishma Kotecha 		for (i = 0; i < list_itr->lkups_cnt; i++)
59370f94570dSGrishma Kotecha 			if (memcmp(&list_itr->lkups[i], &lkups[i],
59380f94570dSGrishma Kotecha 				   sizeof(*lkups))) {
59390f94570dSGrishma Kotecha 				lkups_matched = false;
59400f94570dSGrishma Kotecha 				break;
59410f94570dSGrishma Kotecha 			}
594203592a14SMichal Swiatkowski 		if (ice_rules_equal(rinfo, &list_itr->rule_info) &&
59430f94570dSGrishma Kotecha 		    lkups_matched)
59440f94570dSGrishma Kotecha 			return list_itr;
59450f94570dSGrishma Kotecha 	}
59460f94570dSGrishma Kotecha 	return NULL;
59470f94570dSGrishma Kotecha }
59480f94570dSGrishma Kotecha 
59490f94570dSGrishma Kotecha /**
59500f94570dSGrishma Kotecha  * ice_adv_add_update_vsi_list
59510f94570dSGrishma Kotecha  * @hw: pointer to the hardware structure
59520f94570dSGrishma Kotecha  * @m_entry: pointer to current adv filter management list entry
59530f94570dSGrishma Kotecha  * @cur_fltr: filter information from the book keeping entry
59540f94570dSGrishma Kotecha  * @new_fltr: filter information with the new VSI to be added
59550f94570dSGrishma Kotecha  *
59560f94570dSGrishma Kotecha  * Call AQ command to add or update previously created VSI list with new VSI.
59570f94570dSGrishma Kotecha  *
59580f94570dSGrishma Kotecha  * Helper function to do book keeping associated with adding filter information
59590f94570dSGrishma Kotecha  * The algorithm to do the booking keeping is described below :
59600f94570dSGrishma Kotecha  * When a VSI needs to subscribe to a given advanced filter
59610f94570dSGrishma Kotecha  *	if only one VSI has been added till now
59620f94570dSGrishma Kotecha  *		Allocate a new VSI list and add two VSIs
59630f94570dSGrishma Kotecha  *		to this list using switch rule command
59640f94570dSGrishma Kotecha  *		Update the previously created switch rule with the
59650f94570dSGrishma Kotecha  *		newly created VSI list ID
59660f94570dSGrishma Kotecha  *	if a VSI list was previously created
59670f94570dSGrishma Kotecha  *		Add the new VSI to the previously created VSI list set
59680f94570dSGrishma Kotecha  *		using the update switch rule command
59690f94570dSGrishma Kotecha  */
59705e24d598STony Nguyen static int
59710f94570dSGrishma Kotecha ice_adv_add_update_vsi_list(struct ice_hw *hw,
59720f94570dSGrishma Kotecha 			    struct ice_adv_fltr_mgmt_list_entry *m_entry,
59730f94570dSGrishma Kotecha 			    struct ice_adv_rule_info *cur_fltr,
59740f94570dSGrishma Kotecha 			    struct ice_adv_rule_info *new_fltr)
59750f94570dSGrishma Kotecha {
59760f94570dSGrishma Kotecha 	u16 vsi_list_id = 0;
59775518ac2aSTony Nguyen 	int status;
59780f94570dSGrishma Kotecha 
59790f94570dSGrishma Kotecha 	if (cur_fltr->sw_act.fltr_act == ICE_FWD_TO_Q ||
59800f94570dSGrishma Kotecha 	    cur_fltr->sw_act.fltr_act == ICE_FWD_TO_QGRP ||
59810f94570dSGrishma Kotecha 	    cur_fltr->sw_act.fltr_act == ICE_DROP_PACKET)
5982d54699e2STony Nguyen 		return -EOPNOTSUPP;
59830f94570dSGrishma Kotecha 
59840f94570dSGrishma Kotecha 	if ((new_fltr->sw_act.fltr_act == ICE_FWD_TO_Q ||
59850f94570dSGrishma Kotecha 	     new_fltr->sw_act.fltr_act == ICE_FWD_TO_QGRP) &&
59860f94570dSGrishma Kotecha 	    (cur_fltr->sw_act.fltr_act == ICE_FWD_TO_VSI ||
59870f94570dSGrishma Kotecha 	     cur_fltr->sw_act.fltr_act == ICE_FWD_TO_VSI_LIST))
5988d54699e2STony Nguyen 		return -EOPNOTSUPP;
59890f94570dSGrishma Kotecha 
59900f94570dSGrishma Kotecha 	if (m_entry->vsi_count < 2 && !m_entry->vsi_list_info) {
59910f94570dSGrishma Kotecha 		 /* Only one entry existed in the mapping and it was not already
59920f94570dSGrishma Kotecha 		  * a part of a VSI list. So, create a VSI list with the old and
59930f94570dSGrishma Kotecha 		  * new VSIs.
59940f94570dSGrishma Kotecha 		  */
59950f94570dSGrishma Kotecha 		struct ice_fltr_info tmp_fltr;
59960f94570dSGrishma Kotecha 		u16 vsi_handle_arr[2];
59970f94570dSGrishma Kotecha 
59980f94570dSGrishma Kotecha 		/* A rule already exists with the new VSI being added */
59990f94570dSGrishma Kotecha 		if (cur_fltr->sw_act.fwd_id.hw_vsi_id ==
60000f94570dSGrishma Kotecha 		    new_fltr->sw_act.fwd_id.hw_vsi_id)
6001d54699e2STony Nguyen 			return -EEXIST;
60020f94570dSGrishma Kotecha 
60030f94570dSGrishma Kotecha 		vsi_handle_arr[0] = cur_fltr->sw_act.vsi_handle;
60040f94570dSGrishma Kotecha 		vsi_handle_arr[1] = new_fltr->sw_act.vsi_handle;
60050f94570dSGrishma Kotecha 		status = ice_create_vsi_list_rule(hw, &vsi_handle_arr[0], 2,
60060f94570dSGrishma Kotecha 						  &vsi_list_id,
60070f94570dSGrishma Kotecha 						  ICE_SW_LKUP_LAST);
60080f94570dSGrishma Kotecha 		if (status)
60090f94570dSGrishma Kotecha 			return status;
60100f94570dSGrishma Kotecha 
60110f94570dSGrishma Kotecha 		memset(&tmp_fltr, 0, sizeof(tmp_fltr));
60120f94570dSGrishma Kotecha 		tmp_fltr.flag = m_entry->rule_info.sw_act.flag;
60130f94570dSGrishma Kotecha 		tmp_fltr.fltr_rule_id = cur_fltr->fltr_rule_id;
60140f94570dSGrishma Kotecha 		tmp_fltr.fltr_act = ICE_FWD_TO_VSI_LIST;
60150f94570dSGrishma Kotecha 		tmp_fltr.fwd_id.vsi_list_id = vsi_list_id;
60160f94570dSGrishma Kotecha 		tmp_fltr.lkup_type = ICE_SW_LKUP_LAST;
60170f94570dSGrishma Kotecha 
60180f94570dSGrishma Kotecha 		/* Update the previous switch rule of "forward to VSI" to
60190f94570dSGrishma Kotecha 		 * "fwd to VSI list"
60200f94570dSGrishma Kotecha 		 */
60210f94570dSGrishma Kotecha 		status = ice_update_pkt_fwd_rule(hw, &tmp_fltr);
60220f94570dSGrishma Kotecha 		if (status)
60230f94570dSGrishma Kotecha 			return status;
60240f94570dSGrishma Kotecha 
60250f94570dSGrishma Kotecha 		cur_fltr->sw_act.fwd_id.vsi_list_id = vsi_list_id;
60260f94570dSGrishma Kotecha 		cur_fltr->sw_act.fltr_act = ICE_FWD_TO_VSI_LIST;
60270f94570dSGrishma Kotecha 		m_entry->vsi_list_info =
60280f94570dSGrishma Kotecha 			ice_create_vsi_list_map(hw, &vsi_handle_arr[0], 2,
60290f94570dSGrishma Kotecha 						vsi_list_id);
60300f94570dSGrishma Kotecha 	} else {
60310f94570dSGrishma Kotecha 		u16 vsi_handle = new_fltr->sw_act.vsi_handle;
60320f94570dSGrishma Kotecha 
60330f94570dSGrishma Kotecha 		if (!m_entry->vsi_list_info)
6034d54699e2STony Nguyen 			return -EIO;
60350f94570dSGrishma Kotecha 
60360f94570dSGrishma Kotecha 		/* A rule already exists with the new VSI being added */
60370f94570dSGrishma Kotecha 		if (test_bit(vsi_handle, m_entry->vsi_list_info->vsi_map))
60380f94570dSGrishma Kotecha 			return 0;
60390f94570dSGrishma Kotecha 
60400f94570dSGrishma Kotecha 		/* Update the previously created VSI list set with
60410f94570dSGrishma Kotecha 		 * the new VSI ID passed in
60420f94570dSGrishma Kotecha 		 */
60430f94570dSGrishma Kotecha 		vsi_list_id = cur_fltr->sw_act.fwd_id.vsi_list_id;
60440f94570dSGrishma Kotecha 
60450f94570dSGrishma Kotecha 		status = ice_update_vsi_list_rule(hw, &vsi_handle, 1,
60460f94570dSGrishma Kotecha 						  vsi_list_id, false,
60470f94570dSGrishma Kotecha 						  ice_aqc_opc_update_sw_rules,
60480f94570dSGrishma Kotecha 						  ICE_SW_LKUP_LAST);
60490f94570dSGrishma Kotecha 		/* update VSI list mapping info with new VSI ID */
60500f94570dSGrishma Kotecha 		if (!status)
60510f94570dSGrishma Kotecha 			set_bit(vsi_handle, m_entry->vsi_list_info->vsi_map);
60520f94570dSGrishma Kotecha 	}
60530f94570dSGrishma Kotecha 	if (!status)
60540f94570dSGrishma Kotecha 		m_entry->vsi_count++;
60550f94570dSGrishma Kotecha 	return status;
60560f94570dSGrishma Kotecha }
60570f94570dSGrishma Kotecha 
605803592a14SMichal Swiatkowski void ice_rule_add_tunnel_metadata(struct ice_adv_lkup_elem *lkup)
605903592a14SMichal Swiatkowski {
606003592a14SMichal Swiatkowski 	lkup->type = ICE_HW_METADATA;
606103592a14SMichal Swiatkowski 	lkup->m_u.metadata.flags[ICE_PKT_FLAGS_TUNNEL] =
606203592a14SMichal Swiatkowski 		cpu_to_be16(ICE_PKT_TUNNEL_MASK);
606303592a14SMichal Swiatkowski }
606403592a14SMichal Swiatkowski 
606503592a14SMichal Swiatkowski void ice_rule_add_vlan_metadata(struct ice_adv_lkup_elem *lkup)
606603592a14SMichal Swiatkowski {
606703592a14SMichal Swiatkowski 	lkup->type = ICE_HW_METADATA;
606803592a14SMichal Swiatkowski 	lkup->m_u.metadata.flags[ICE_PKT_FLAGS_VLAN] =
606903592a14SMichal Swiatkowski 		cpu_to_be16(ICE_PKT_VLAN_MASK);
607003592a14SMichal Swiatkowski }
607103592a14SMichal Swiatkowski 
60720ef4479dSMichal Swiatkowski void ice_rule_add_src_vsi_metadata(struct ice_adv_lkup_elem *lkup)
60730ef4479dSMichal Swiatkowski {
60740ef4479dSMichal Swiatkowski 	lkup->type = ICE_HW_METADATA;
60750ef4479dSMichal Swiatkowski 	lkup->m_u.metadata.source_vsi = cpu_to_be16(ICE_MDID_SOURCE_VSI_MASK);
60760ef4479dSMichal Swiatkowski }
60770ef4479dSMichal Swiatkowski 
60780f94570dSGrishma Kotecha /**
60790f94570dSGrishma Kotecha  * ice_add_adv_rule - helper function to create an advanced switch rule
60800f94570dSGrishma Kotecha  * @hw: pointer to the hardware structure
60810f94570dSGrishma Kotecha  * @lkups: information on the words that needs to be looked up. All words
60820f94570dSGrishma Kotecha  * together makes one recipe
60830f94570dSGrishma Kotecha  * @lkups_cnt: num of entries in the lkups array
60840f94570dSGrishma Kotecha  * @rinfo: other information related to the rule that needs to be programmed
60850f94570dSGrishma Kotecha  * @added_entry: this will return recipe_id, rule_id and vsi_handle. should be
60860f94570dSGrishma Kotecha  *               ignored is case of error.
60870f94570dSGrishma Kotecha  *
60880f94570dSGrishma Kotecha  * This function can program only 1 rule at a time. The lkups is used to
60890f94570dSGrishma Kotecha  * describe the all the words that forms the "lookup" portion of the recipe.
60900f94570dSGrishma Kotecha  * These words can span multiple protocols. Callers to this function need to
60910f94570dSGrishma Kotecha  * pass in a list of protocol headers with lookup information along and mask
60920f94570dSGrishma Kotecha  * that determines which words are valid from the given protocol header.
60930f94570dSGrishma Kotecha  * rinfo describes other information related to this rule such as forwarding
60940f94570dSGrishma Kotecha  * IDs, priority of this rule, etc.
60950f94570dSGrishma Kotecha  */
60965e24d598STony Nguyen int
60970f94570dSGrishma Kotecha ice_add_adv_rule(struct ice_hw *hw, struct ice_adv_lkup_elem *lkups,
60980f94570dSGrishma Kotecha 		 u16 lkups_cnt, struct ice_adv_rule_info *rinfo,
60990f94570dSGrishma Kotecha 		 struct ice_rule_query_data *added_entry)
61000f94570dSGrishma Kotecha {
61010f94570dSGrishma Kotecha 	struct ice_adv_fltr_mgmt_list_entry *m_entry, *adv_fltr = NULL;
61026e1ff618SAlexander Lobakin 	struct ice_sw_rule_lkup_rx_tx *s_rule = NULL;
6103e33163a4SAlexander Lobakin 	const struct ice_dummy_pkt_profile *profile;
61041b699f81SAlexander Lobakin 	u16 rid = 0, i, rule_buf_sz, vsi_handle;
61050f94570dSGrishma Kotecha 	struct list_head *rule_head;
61060f94570dSGrishma Kotecha 	struct ice_switch_info *sw;
61070f94570dSGrishma Kotecha 	u16 word_cnt;
61080f94570dSGrishma Kotecha 	u32 act = 0;
61095518ac2aSTony Nguyen 	int status;
61100f94570dSGrishma Kotecha 	u8 q_rgn;
61110f94570dSGrishma Kotecha 
61120f94570dSGrishma Kotecha 	/* Initialize profile to result index bitmap */
61130f94570dSGrishma Kotecha 	if (!hw->switch_info->prof_res_bm_init) {
61140f94570dSGrishma Kotecha 		hw->switch_info->prof_res_bm_init = 1;
61150f94570dSGrishma Kotecha 		ice_init_prof_result_bm(hw);
61160f94570dSGrishma Kotecha 	}
61170f94570dSGrishma Kotecha 
61180f94570dSGrishma Kotecha 	if (!lkups_cnt)
6119d54699e2STony Nguyen 		return -EINVAL;
61200f94570dSGrishma Kotecha 
61210f94570dSGrishma Kotecha 	/* get # of words we need to match */
61220f94570dSGrishma Kotecha 	word_cnt = 0;
61230f94570dSGrishma Kotecha 	for (i = 0; i < lkups_cnt; i++) {
6124135a161aSAlexander Lobakin 		u16 j;
61250f94570dSGrishma Kotecha 
6126135a161aSAlexander Lobakin 		for (j = 0; j < ARRAY_SIZE(lkups->m_raw); j++)
6127135a161aSAlexander Lobakin 			if (lkups[i].m_raw[j])
61280f94570dSGrishma Kotecha 				word_cnt++;
61290f94570dSGrishma Kotecha 	}
61300f94570dSGrishma Kotecha 
6131bd1ffe8eSWojciech Drewek 	if (!word_cnt)
6132d54699e2STony Nguyen 		return -EINVAL;
61330f94570dSGrishma Kotecha 
6134bd1ffe8eSWojciech Drewek 	if (word_cnt > ICE_MAX_CHAIN_WORDS)
6135bd1ffe8eSWojciech Drewek 		return -ENOSPC;
6136bd1ffe8eSWojciech Drewek 
61371b699f81SAlexander Lobakin 	/* locate a dummy packet */
61381b699f81SAlexander Lobakin 	profile = ice_find_dummy_packet(lkups, lkups_cnt, rinfo->tun_type);
613926395726SMartyna Szapar-Mudlaw 	if (IS_ERR(profile))
614026395726SMartyna Szapar-Mudlaw 		return PTR_ERR(profile);
61410f94570dSGrishma Kotecha 
61420f94570dSGrishma Kotecha 	if (!(rinfo->sw_act.fltr_act == ICE_FWD_TO_VSI ||
61430f94570dSGrishma Kotecha 	      rinfo->sw_act.fltr_act == ICE_FWD_TO_Q ||
61440f94570dSGrishma Kotecha 	      rinfo->sw_act.fltr_act == ICE_FWD_TO_QGRP ||
6145bccd9bceSMarcin Szycik 	      rinfo->sw_act.fltr_act == ICE_DROP_PACKET ||
6146bccd9bceSMarcin Szycik 	      rinfo->sw_act.fltr_act == ICE_NOP)) {
614726395726SMartyna Szapar-Mudlaw 		status = -EIO;
614826395726SMartyna Szapar-Mudlaw 		goto free_pkt_profile;
614926395726SMartyna Szapar-Mudlaw 	}
61500f94570dSGrishma Kotecha 
61510f94570dSGrishma Kotecha 	vsi_handle = rinfo->sw_act.vsi_handle;
615226395726SMartyna Szapar-Mudlaw 	if (!ice_is_vsi_valid(hw, vsi_handle)) {
615326395726SMartyna Szapar-Mudlaw 		status =  -EINVAL;
615426395726SMartyna Szapar-Mudlaw 		goto free_pkt_profile;
615526395726SMartyna Szapar-Mudlaw 	}
61560f94570dSGrishma Kotecha 
6157bccd9bceSMarcin Szycik 	if (rinfo->sw_act.fltr_act == ICE_FWD_TO_VSI ||
6158bccd9bceSMarcin Szycik 	    rinfo->sw_act.fltr_act == ICE_NOP)
61590f94570dSGrishma Kotecha 		rinfo->sw_act.fwd_id.hw_vsi_id =
61600f94570dSGrishma Kotecha 			ice_get_hw_vsi_num(hw, vsi_handle);
616103592a14SMichal Swiatkowski 
616203592a14SMichal Swiatkowski 	if (rinfo->src_vsi)
616303592a14SMichal Swiatkowski 		rinfo->sw_act.src = ice_get_hw_vsi_num(hw, rinfo->src_vsi);
616403592a14SMichal Swiatkowski 	else
61650f94570dSGrishma Kotecha 		rinfo->sw_act.src = ice_get_hw_vsi_num(hw, vsi_handle);
61660f94570dSGrishma Kotecha 
61670f94570dSGrishma Kotecha 	status = ice_add_adv_recipe(hw, lkups, lkups_cnt, rinfo, &rid);
61680f94570dSGrishma Kotecha 	if (status)
616926395726SMartyna Szapar-Mudlaw 		goto free_pkt_profile;
61700f94570dSGrishma Kotecha 	m_entry = ice_find_adv_rule_entry(hw, lkups, lkups_cnt, rid, rinfo);
61710f94570dSGrishma Kotecha 	if (m_entry) {
61720f94570dSGrishma Kotecha 		/* we have to add VSI to VSI_LIST and increment vsi_count.
61730f94570dSGrishma Kotecha 		 * Also Update VSI list so that we can change forwarding rule
61740f94570dSGrishma Kotecha 		 * if the rule already exists, we will check if it exists with
61750f94570dSGrishma Kotecha 		 * same vsi_id, if not then add it to the VSI list if it already
61760f94570dSGrishma Kotecha 		 * exists if not then create a VSI list and add the existing VSI
61770f94570dSGrishma Kotecha 		 * ID and the new VSI ID to the list
61780f94570dSGrishma Kotecha 		 * We will add that VSI to the list
61790f94570dSGrishma Kotecha 		 */
61800f94570dSGrishma Kotecha 		status = ice_adv_add_update_vsi_list(hw, m_entry,
61810f94570dSGrishma Kotecha 						     &m_entry->rule_info,
61820f94570dSGrishma Kotecha 						     rinfo);
61830f94570dSGrishma Kotecha 		if (added_entry) {
61840f94570dSGrishma Kotecha 			added_entry->rid = rid;
61850f94570dSGrishma Kotecha 			added_entry->rule_id = m_entry->rule_info.fltr_rule_id;
61860f94570dSGrishma Kotecha 			added_entry->vsi_handle = rinfo->sw_act.vsi_handle;
61870f94570dSGrishma Kotecha 		}
618826395726SMartyna Szapar-Mudlaw 		goto free_pkt_profile;
61890f94570dSGrishma Kotecha 	}
61906e1ff618SAlexander Lobakin 	rule_buf_sz = ICE_SW_RULE_RX_TX_HDR_SIZE(s_rule, profile->pkt_len);
61910f94570dSGrishma Kotecha 	s_rule = kzalloc(rule_buf_sz, GFP_KERNEL);
619226395726SMartyna Szapar-Mudlaw 	if (!s_rule) {
619326395726SMartyna Szapar-Mudlaw 		status = -ENOMEM;
619426395726SMartyna Szapar-Mudlaw 		goto free_pkt_profile;
619526395726SMartyna Szapar-Mudlaw 	}
619673b483b7SWojciech Drewek 	if (!rinfo->flags_info.act_valid) {
619773b483b7SWojciech Drewek 		act |= ICE_SINGLE_ACT_LAN_ENABLE;
619873b483b7SWojciech Drewek 		act |= ICE_SINGLE_ACT_LB_ENABLE;
619973b483b7SWojciech Drewek 	} else {
620073b483b7SWojciech Drewek 		act |= rinfo->flags_info.act & (ICE_SINGLE_ACT_LAN_ENABLE |
620173b483b7SWojciech Drewek 						ICE_SINGLE_ACT_LB_ENABLE);
620273b483b7SWojciech Drewek 	}
620373b483b7SWojciech Drewek 
62040f94570dSGrishma Kotecha 	switch (rinfo->sw_act.fltr_act) {
62050f94570dSGrishma Kotecha 	case ICE_FWD_TO_VSI:
62060f94570dSGrishma Kotecha 		act |= (rinfo->sw_act.fwd_id.hw_vsi_id <<
62070f94570dSGrishma Kotecha 			ICE_SINGLE_ACT_VSI_ID_S) & ICE_SINGLE_ACT_VSI_ID_M;
62080f94570dSGrishma Kotecha 		act |= ICE_SINGLE_ACT_VSI_FORWARDING | ICE_SINGLE_ACT_VALID_BIT;
62090f94570dSGrishma Kotecha 		break;
62100f94570dSGrishma Kotecha 	case ICE_FWD_TO_Q:
62110f94570dSGrishma Kotecha 		act |= ICE_SINGLE_ACT_TO_Q;
62120f94570dSGrishma Kotecha 		act |= (rinfo->sw_act.fwd_id.q_id << ICE_SINGLE_ACT_Q_INDEX_S) &
62130f94570dSGrishma Kotecha 		       ICE_SINGLE_ACT_Q_INDEX_M;
62140f94570dSGrishma Kotecha 		break;
62150f94570dSGrishma Kotecha 	case ICE_FWD_TO_QGRP:
62160f94570dSGrishma Kotecha 		q_rgn = rinfo->sw_act.qgrp_size > 0 ?
62170f94570dSGrishma Kotecha 			(u8)ilog2(rinfo->sw_act.qgrp_size) : 0;
62180f94570dSGrishma Kotecha 		act |= ICE_SINGLE_ACT_TO_Q;
62190f94570dSGrishma Kotecha 		act |= (rinfo->sw_act.fwd_id.q_id << ICE_SINGLE_ACT_Q_INDEX_S) &
62200f94570dSGrishma Kotecha 		       ICE_SINGLE_ACT_Q_INDEX_M;
62210f94570dSGrishma Kotecha 		act |= (q_rgn << ICE_SINGLE_ACT_Q_REGION_S) &
62220f94570dSGrishma Kotecha 		       ICE_SINGLE_ACT_Q_REGION_M;
62230f94570dSGrishma Kotecha 		break;
62240f94570dSGrishma Kotecha 	case ICE_DROP_PACKET:
62250f94570dSGrishma Kotecha 		act |= ICE_SINGLE_ACT_VSI_FORWARDING | ICE_SINGLE_ACT_DROP |
62260f94570dSGrishma Kotecha 		       ICE_SINGLE_ACT_VALID_BIT;
62270f94570dSGrishma Kotecha 		break;
6228bccd9bceSMarcin Szycik 	case ICE_NOP:
6229bccd9bceSMarcin Szycik 		act |= FIELD_PREP(ICE_SINGLE_ACT_VSI_ID_M,
6230bccd9bceSMarcin Szycik 				  rinfo->sw_act.fwd_id.hw_vsi_id);
6231bccd9bceSMarcin Szycik 		act &= ~ICE_SINGLE_ACT_VALID_BIT;
6232bccd9bceSMarcin Szycik 		break;
62330f94570dSGrishma Kotecha 	default:
6234d54699e2STony Nguyen 		status = -EIO;
62350f94570dSGrishma Kotecha 		goto err_ice_add_adv_rule;
62360f94570dSGrishma Kotecha 	}
62370f94570dSGrishma Kotecha 
623840fd7492SMichal Swiatkowski 	/* If there is no matching criteria for direction there
623940fd7492SMichal Swiatkowski 	 * is only one difference between Rx and Tx:
624040fd7492SMichal Swiatkowski 	 * - get switch id base on VSI number from source field (Tx)
624140fd7492SMichal Swiatkowski 	 * - get switch id base on port number (Rx)
62420f94570dSGrishma Kotecha 	 *
624340fd7492SMichal Swiatkowski 	 * If matching on direction metadata is chose rule direction is
624440fd7492SMichal Swiatkowski 	 * extracted from type value set here.
62450f94570dSGrishma Kotecha 	 */
624640fd7492SMichal Swiatkowski 	if (rinfo->sw_act.flag & ICE_FLTR_TX) {
62476e1ff618SAlexander Lobakin 		s_rule->hdr.type = cpu_to_le16(ICE_AQC_SW_RULES_T_LKUP_TX);
62486e1ff618SAlexander Lobakin 		s_rule->src = cpu_to_le16(rinfo->sw_act.src);
624940fd7492SMichal Swiatkowski 	} else {
625040fd7492SMichal Swiatkowski 		s_rule->hdr.type = cpu_to_le16(ICE_AQC_SW_RULES_T_LKUP_RX);
625140fd7492SMichal Swiatkowski 		s_rule->src = cpu_to_le16(hw->port_info->lport);
62520f94570dSGrishma Kotecha 	}
62530f94570dSGrishma Kotecha 
62546e1ff618SAlexander Lobakin 	s_rule->recipe_id = cpu_to_le16(rid);
62556e1ff618SAlexander Lobakin 	s_rule->act = cpu_to_le32(act);
62560f94570dSGrishma Kotecha 
6257e33163a4SAlexander Lobakin 	status = ice_fill_adv_dummy_packet(lkups, lkups_cnt, s_rule, profile);
62580f94570dSGrishma Kotecha 	if (status)
62590f94570dSGrishma Kotecha 		goto err_ice_add_adv_rule;
62600f94570dSGrishma Kotecha 
626103592a14SMichal Swiatkowski 	status = ice_fill_adv_packet_tun(hw, rinfo->tun_type, s_rule->hdr_data,
6262e33163a4SAlexander Lobakin 					 profile->offsets);
62638b032a55SMichal Swiatkowski 	if (status)
62648b032a55SMichal Swiatkowski 		goto err_ice_add_adv_rule;
62658b032a55SMichal Swiatkowski 
626603592a14SMichal Swiatkowski 	status = ice_fill_adv_packet_vlan(hw, rinfo->vlan_type,
6267ea71b967SMartyna Szapar-Mudlaw 					  s_rule->hdr_data,
6268ea71b967SMartyna Szapar-Mudlaw 					  profile->offsets);
6269ea71b967SMartyna Szapar-Mudlaw 	if (status)
6270ea71b967SMartyna Szapar-Mudlaw 		goto err_ice_add_adv_rule;
6271ea71b967SMartyna Szapar-Mudlaw 
62720f94570dSGrishma Kotecha 	status = ice_aq_sw_rules(hw, (struct ice_aqc_sw_rules *)s_rule,
62730f94570dSGrishma Kotecha 				 rule_buf_sz, 1, ice_aqc_opc_add_sw_rules,
62740f94570dSGrishma Kotecha 				 NULL);
62750f94570dSGrishma Kotecha 	if (status)
62760f94570dSGrishma Kotecha 		goto err_ice_add_adv_rule;
62770f94570dSGrishma Kotecha 	adv_fltr = devm_kzalloc(ice_hw_to_dev(hw),
62780f94570dSGrishma Kotecha 				sizeof(struct ice_adv_fltr_mgmt_list_entry),
62790f94570dSGrishma Kotecha 				GFP_KERNEL);
62800f94570dSGrishma Kotecha 	if (!adv_fltr) {
6281d54699e2STony Nguyen 		status = -ENOMEM;
62820f94570dSGrishma Kotecha 		goto err_ice_add_adv_rule;
62830f94570dSGrishma Kotecha 	}
62840f94570dSGrishma Kotecha 
62850f94570dSGrishma Kotecha 	adv_fltr->lkups = devm_kmemdup(ice_hw_to_dev(hw), lkups,
62860f94570dSGrishma Kotecha 				       lkups_cnt * sizeof(*lkups), GFP_KERNEL);
62870f94570dSGrishma Kotecha 	if (!adv_fltr->lkups) {
6288d54699e2STony Nguyen 		status = -ENOMEM;
62890f94570dSGrishma Kotecha 		goto err_ice_add_adv_rule;
62900f94570dSGrishma Kotecha 	}
62910f94570dSGrishma Kotecha 
62920f94570dSGrishma Kotecha 	adv_fltr->lkups_cnt = lkups_cnt;
62930f94570dSGrishma Kotecha 	adv_fltr->rule_info = *rinfo;
62946e1ff618SAlexander Lobakin 	adv_fltr->rule_info.fltr_rule_id = le16_to_cpu(s_rule->index);
62950f94570dSGrishma Kotecha 	sw = hw->switch_info;
62960f94570dSGrishma Kotecha 	sw->recp_list[rid].adv_rule = true;
62970f94570dSGrishma Kotecha 	rule_head = &sw->recp_list[rid].filt_rules;
62980f94570dSGrishma Kotecha 
62990f94570dSGrishma Kotecha 	if (rinfo->sw_act.fltr_act == ICE_FWD_TO_VSI)
63000f94570dSGrishma Kotecha 		adv_fltr->vsi_count = 1;
63010f94570dSGrishma Kotecha 
63020f94570dSGrishma Kotecha 	/* Add rule entry to book keeping list */
63030f94570dSGrishma Kotecha 	list_add(&adv_fltr->list_entry, rule_head);
63040f94570dSGrishma Kotecha 	if (added_entry) {
63050f94570dSGrishma Kotecha 		added_entry->rid = rid;
63060f94570dSGrishma Kotecha 		added_entry->rule_id = adv_fltr->rule_info.fltr_rule_id;
63070f94570dSGrishma Kotecha 		added_entry->vsi_handle = rinfo->sw_act.vsi_handle;
63080f94570dSGrishma Kotecha 	}
63090f94570dSGrishma Kotecha err_ice_add_adv_rule:
63100f94570dSGrishma Kotecha 	if (status && adv_fltr) {
63110f94570dSGrishma Kotecha 		devm_kfree(ice_hw_to_dev(hw), adv_fltr->lkups);
63120f94570dSGrishma Kotecha 		devm_kfree(ice_hw_to_dev(hw), adv_fltr);
63130f94570dSGrishma Kotecha 	}
63140f94570dSGrishma Kotecha 
63150f94570dSGrishma Kotecha 	kfree(s_rule);
63160f94570dSGrishma Kotecha 
631726395726SMartyna Szapar-Mudlaw free_pkt_profile:
631826395726SMartyna Szapar-Mudlaw 	if (profile->match & ICE_PKT_KMALLOC) {
631926395726SMartyna Szapar-Mudlaw 		kfree(profile->offsets);
632026395726SMartyna Szapar-Mudlaw 		kfree(profile->pkt);
632126395726SMartyna Szapar-Mudlaw 		kfree(profile);
632226395726SMartyna Szapar-Mudlaw 	}
632326395726SMartyna Szapar-Mudlaw 
63240f94570dSGrishma Kotecha 	return status;
63250f94570dSGrishma Kotecha }
63260f94570dSGrishma Kotecha 
63270f94570dSGrishma Kotecha /**
6328334cb062SAnirudh Venkataramanan  * ice_replay_vsi_fltr - Replay filters for requested VSI
63290f9d5027SAnirudh Venkataramanan  * @hw: pointer to the hardware structure
6330334cb062SAnirudh Venkataramanan  * @vsi_handle: driver VSI handle
6331f9867df6SAnirudh Venkataramanan  * @recp_id: Recipe ID for which rules need to be replayed
6332334cb062SAnirudh Venkataramanan  * @list_head: list for which filters need to be replayed
6333334cb062SAnirudh Venkataramanan  *
6334334cb062SAnirudh Venkataramanan  * Replays the filter of recipe recp_id for a VSI represented via vsi_handle.
6335334cb062SAnirudh Venkataramanan  * It is required to pass valid VSI handle.
63360f9d5027SAnirudh Venkataramanan  */
63375e24d598STony Nguyen static int
6338334cb062SAnirudh Venkataramanan ice_replay_vsi_fltr(struct ice_hw *hw, u16 vsi_handle, u8 recp_id,
6339334cb062SAnirudh Venkataramanan 		    struct list_head *list_head)
63400f9d5027SAnirudh Venkataramanan {
63410f9d5027SAnirudh Venkataramanan 	struct ice_fltr_mgmt_list_entry *itr;
63425e24d598STony Nguyen 	int status = 0;
6343334cb062SAnirudh Venkataramanan 	u16 hw_vsi_id;
63440f9d5027SAnirudh Venkataramanan 
63450f9d5027SAnirudh Venkataramanan 	if (list_empty(list_head))
63460f9d5027SAnirudh Venkataramanan 		return status;
6347334cb062SAnirudh Venkataramanan 	hw_vsi_id = ice_get_hw_vsi_num(hw, vsi_handle);
63480f9d5027SAnirudh Venkataramanan 
6349334cb062SAnirudh Venkataramanan 	list_for_each_entry(itr, list_head, list_entry) {
63500f9d5027SAnirudh Venkataramanan 		struct ice_fltr_list_entry f_entry;
63510f9d5027SAnirudh Venkataramanan 
63520f9d5027SAnirudh Venkataramanan 		f_entry.fltr_info = itr->fltr_info;
6353334cb062SAnirudh Venkataramanan 		if (itr->vsi_count < 2 && recp_id != ICE_SW_LKUP_VLAN &&
6354334cb062SAnirudh Venkataramanan 		    itr->fltr_info.vsi_handle == vsi_handle) {
6355f9867df6SAnirudh Venkataramanan 			/* update the src in case it is VSI num */
6356334cb062SAnirudh Venkataramanan 			if (f_entry.fltr_info.src_id == ICE_SRC_ID_VSI)
6357334cb062SAnirudh Venkataramanan 				f_entry.fltr_info.src = hw_vsi_id;
63580f9d5027SAnirudh Venkataramanan 			status = ice_add_rule_internal(hw, recp_id, &f_entry);
63590f9d5027SAnirudh Venkataramanan 			if (status)
63600f9d5027SAnirudh Venkataramanan 				goto end;
63610f9d5027SAnirudh Venkataramanan 			continue;
63620f9d5027SAnirudh Venkataramanan 		}
6363072f0c3dSDave Ertman 		if (!itr->vsi_list_info ||
6364072f0c3dSDave Ertman 		    !test_bit(vsi_handle, itr->vsi_list_info->vsi_map))
6365334cb062SAnirudh Venkataramanan 			continue;
6366334cb062SAnirudh Venkataramanan 		/* Clearing it so that the logic can add it back */
6367334cb062SAnirudh Venkataramanan 		clear_bit(vsi_handle, itr->vsi_list_info->vsi_map);
6368334cb062SAnirudh Venkataramanan 		f_entry.fltr_info.vsi_handle = vsi_handle;
63690f9d5027SAnirudh Venkataramanan 		f_entry.fltr_info.fltr_act = ICE_FWD_TO_VSI;
6370f9867df6SAnirudh Venkataramanan 		/* update the src in case it is VSI num */
6371334cb062SAnirudh Venkataramanan 		if (f_entry.fltr_info.src_id == ICE_SRC_ID_VSI)
6372334cb062SAnirudh Venkataramanan 			f_entry.fltr_info.src = hw_vsi_id;
63730f9d5027SAnirudh Venkataramanan 		if (recp_id == ICE_SW_LKUP_VLAN)
63740f9d5027SAnirudh Venkataramanan 			status = ice_add_vlan_internal(hw, &f_entry);
63750f9d5027SAnirudh Venkataramanan 		else
6376334cb062SAnirudh Venkataramanan 			status = ice_add_rule_internal(hw, recp_id, &f_entry);
63770f9d5027SAnirudh Venkataramanan 		if (status)
63780f9d5027SAnirudh Venkataramanan 			goto end;
63790f9d5027SAnirudh Venkataramanan 	}
63800f9d5027SAnirudh Venkataramanan end:
63810f9d5027SAnirudh Venkataramanan 	return status;
63820f9d5027SAnirudh Venkataramanan }
63830f9d5027SAnirudh Venkataramanan 
63840f9d5027SAnirudh Venkataramanan /**
63858bb98f33SShivanshu Shukla  * ice_adv_rem_update_vsi_list
63868bb98f33SShivanshu Shukla  * @hw: pointer to the hardware structure
63878bb98f33SShivanshu Shukla  * @vsi_handle: VSI handle of the VSI to remove
63888bb98f33SShivanshu Shukla  * @fm_list: filter management entry for which the VSI list management needs to
63898bb98f33SShivanshu Shukla  *	     be done
63908bb98f33SShivanshu Shukla  */
63915e24d598STony Nguyen static int
63928bb98f33SShivanshu Shukla ice_adv_rem_update_vsi_list(struct ice_hw *hw, u16 vsi_handle,
63938bb98f33SShivanshu Shukla 			    struct ice_adv_fltr_mgmt_list_entry *fm_list)
63948bb98f33SShivanshu Shukla {
63958bb98f33SShivanshu Shukla 	struct ice_vsi_list_map_info *vsi_list_info;
63968bb98f33SShivanshu Shukla 	enum ice_sw_lkup_type lkup_type;
63978bb98f33SShivanshu Shukla 	u16 vsi_list_id;
63985518ac2aSTony Nguyen 	int status;
63998bb98f33SShivanshu Shukla 
64008bb98f33SShivanshu Shukla 	if (fm_list->rule_info.sw_act.fltr_act != ICE_FWD_TO_VSI_LIST ||
64018bb98f33SShivanshu Shukla 	    fm_list->vsi_count == 0)
6402d54699e2STony Nguyen 		return -EINVAL;
64038bb98f33SShivanshu Shukla 
64048bb98f33SShivanshu Shukla 	/* A rule with the VSI being removed does not exist */
64058bb98f33SShivanshu Shukla 	if (!test_bit(vsi_handle, fm_list->vsi_list_info->vsi_map))
6406d54699e2STony Nguyen 		return -ENOENT;
64078bb98f33SShivanshu Shukla 
64088bb98f33SShivanshu Shukla 	lkup_type = ICE_SW_LKUP_LAST;
64098bb98f33SShivanshu Shukla 	vsi_list_id = fm_list->rule_info.sw_act.fwd_id.vsi_list_id;
64108bb98f33SShivanshu Shukla 	status = ice_update_vsi_list_rule(hw, &vsi_handle, 1, vsi_list_id, true,
64118bb98f33SShivanshu Shukla 					  ice_aqc_opc_update_sw_rules,
64128bb98f33SShivanshu Shukla 					  lkup_type);
64138bb98f33SShivanshu Shukla 	if (status)
64148bb98f33SShivanshu Shukla 		return status;
64158bb98f33SShivanshu Shukla 
64168bb98f33SShivanshu Shukla 	fm_list->vsi_count--;
64178bb98f33SShivanshu Shukla 	clear_bit(vsi_handle, fm_list->vsi_list_info->vsi_map);
64188bb98f33SShivanshu Shukla 	vsi_list_info = fm_list->vsi_list_info;
64198bb98f33SShivanshu Shukla 	if (fm_list->vsi_count == 1) {
64208bb98f33SShivanshu Shukla 		struct ice_fltr_info tmp_fltr;
64218bb98f33SShivanshu Shukla 		u16 rem_vsi_handle;
64228bb98f33SShivanshu Shukla 
64238bb98f33SShivanshu Shukla 		rem_vsi_handle = find_first_bit(vsi_list_info->vsi_map,
64248bb98f33SShivanshu Shukla 						ICE_MAX_VSI);
64258bb98f33SShivanshu Shukla 		if (!ice_is_vsi_valid(hw, rem_vsi_handle))
6426d54699e2STony Nguyen 			return -EIO;
64278bb98f33SShivanshu Shukla 
64288bb98f33SShivanshu Shukla 		/* Make sure VSI list is empty before removing it below */
64298bb98f33SShivanshu Shukla 		status = ice_update_vsi_list_rule(hw, &rem_vsi_handle, 1,
64308bb98f33SShivanshu Shukla 						  vsi_list_id, true,
64318bb98f33SShivanshu Shukla 						  ice_aqc_opc_update_sw_rules,
64328bb98f33SShivanshu Shukla 						  lkup_type);
64338bb98f33SShivanshu Shukla 		if (status)
64348bb98f33SShivanshu Shukla 			return status;
64358bb98f33SShivanshu Shukla 
64368bb98f33SShivanshu Shukla 		memset(&tmp_fltr, 0, sizeof(tmp_fltr));
64378bb98f33SShivanshu Shukla 		tmp_fltr.flag = fm_list->rule_info.sw_act.flag;
64388bb98f33SShivanshu Shukla 		tmp_fltr.fltr_rule_id = fm_list->rule_info.fltr_rule_id;
64398bb98f33SShivanshu Shukla 		fm_list->rule_info.sw_act.fltr_act = ICE_FWD_TO_VSI;
64408bb98f33SShivanshu Shukla 		tmp_fltr.fltr_act = ICE_FWD_TO_VSI;
64418bb98f33SShivanshu Shukla 		tmp_fltr.fwd_id.hw_vsi_id =
64428bb98f33SShivanshu Shukla 			ice_get_hw_vsi_num(hw, rem_vsi_handle);
64438bb98f33SShivanshu Shukla 		fm_list->rule_info.sw_act.fwd_id.hw_vsi_id =
64448bb98f33SShivanshu Shukla 			ice_get_hw_vsi_num(hw, rem_vsi_handle);
64458bb98f33SShivanshu Shukla 		fm_list->rule_info.sw_act.vsi_handle = rem_vsi_handle;
64468bb98f33SShivanshu Shukla 
64478bb98f33SShivanshu Shukla 		/* Update the previous switch rule of "MAC forward to VSI" to
64488bb98f33SShivanshu Shukla 		 * "MAC fwd to VSI list"
64498bb98f33SShivanshu Shukla 		 */
64508bb98f33SShivanshu Shukla 		status = ice_update_pkt_fwd_rule(hw, &tmp_fltr);
64518bb98f33SShivanshu Shukla 		if (status) {
64528bb98f33SShivanshu Shukla 			ice_debug(hw, ICE_DBG_SW, "Failed to update pkt fwd rule to FWD_TO_VSI on HW VSI %d, error %d\n",
64538bb98f33SShivanshu Shukla 				  tmp_fltr.fwd_id.hw_vsi_id, status);
64548bb98f33SShivanshu Shukla 			return status;
64558bb98f33SShivanshu Shukla 		}
64568bb98f33SShivanshu Shukla 		fm_list->vsi_list_info->ref_cnt--;
64578bb98f33SShivanshu Shukla 
64588bb98f33SShivanshu Shukla 		/* Remove the VSI list since it is no longer used */
64598bb98f33SShivanshu Shukla 		status = ice_remove_vsi_list_rule(hw, vsi_list_id, lkup_type);
64608bb98f33SShivanshu Shukla 		if (status) {
64618bb98f33SShivanshu Shukla 			ice_debug(hw, ICE_DBG_SW, "Failed to remove VSI list %d, error %d\n",
64628bb98f33SShivanshu Shukla 				  vsi_list_id, status);
64638bb98f33SShivanshu Shukla 			return status;
64648bb98f33SShivanshu Shukla 		}
64658bb98f33SShivanshu Shukla 
64668bb98f33SShivanshu Shukla 		list_del(&vsi_list_info->list_entry);
64678bb98f33SShivanshu Shukla 		devm_kfree(ice_hw_to_dev(hw), vsi_list_info);
64688bb98f33SShivanshu Shukla 		fm_list->vsi_list_info = NULL;
64698bb98f33SShivanshu Shukla 	}
64708bb98f33SShivanshu Shukla 
64718bb98f33SShivanshu Shukla 	return status;
64728bb98f33SShivanshu Shukla }
64738bb98f33SShivanshu Shukla 
64748bb98f33SShivanshu Shukla /**
64758bb98f33SShivanshu Shukla  * ice_rem_adv_rule - removes existing advanced switch rule
64768bb98f33SShivanshu Shukla  * @hw: pointer to the hardware structure
64778bb98f33SShivanshu Shukla  * @lkups: information on the words that needs to be looked up. All words
64788bb98f33SShivanshu Shukla  *         together makes one recipe
64798bb98f33SShivanshu Shukla  * @lkups_cnt: num of entries in the lkups array
64808bb98f33SShivanshu Shukla  * @rinfo: Its the pointer to the rule information for the rule
64818bb98f33SShivanshu Shukla  *
64828bb98f33SShivanshu Shukla  * This function can be used to remove 1 rule at a time. The lkups is
64838bb98f33SShivanshu Shukla  * used to describe all the words that forms the "lookup" portion of the
64848bb98f33SShivanshu Shukla  * rule. These words can span multiple protocols. Callers to this function
64858bb98f33SShivanshu Shukla  * need to pass in a list of protocol headers with lookup information along
64868bb98f33SShivanshu Shukla  * and mask that determines which words are valid from the given protocol
64878bb98f33SShivanshu Shukla  * header. rinfo describes other information related to this rule such as
64888bb98f33SShivanshu Shukla  * forwarding IDs, priority of this rule, etc.
64898bb98f33SShivanshu Shukla  */
64905e24d598STony Nguyen static int
64918bb98f33SShivanshu Shukla ice_rem_adv_rule(struct ice_hw *hw, struct ice_adv_lkup_elem *lkups,
64928bb98f33SShivanshu Shukla 		 u16 lkups_cnt, struct ice_adv_rule_info *rinfo)
64938bb98f33SShivanshu Shukla {
64948bb98f33SShivanshu Shukla 	struct ice_adv_fltr_mgmt_list_entry *list_elem;
64958bb98f33SShivanshu Shukla 	struct ice_prot_lkup_ext lkup_exts;
64968bb98f33SShivanshu Shukla 	bool remove_rule = false;
64978bb98f33SShivanshu Shukla 	struct mutex *rule_lock; /* Lock to protect filter rule list */
64988bb98f33SShivanshu Shukla 	u16 i, rid, vsi_handle;
64995518ac2aSTony Nguyen 	int status = 0;
65008bb98f33SShivanshu Shukla 
65018bb98f33SShivanshu Shukla 	memset(&lkup_exts, 0, sizeof(lkup_exts));
65028bb98f33SShivanshu Shukla 	for (i = 0; i < lkups_cnt; i++) {
65038bb98f33SShivanshu Shukla 		u16 count;
65048bb98f33SShivanshu Shukla 
65058bb98f33SShivanshu Shukla 		if (lkups[i].type >= ICE_PROTOCOL_LAST)
6506d54699e2STony Nguyen 			return -EIO;
65078bb98f33SShivanshu Shukla 
65088bb98f33SShivanshu Shukla 		count = ice_fill_valid_words(&lkups[i], &lkup_exts);
65098bb98f33SShivanshu Shukla 		if (!count)
6510d54699e2STony Nguyen 			return -EIO;
65118bb98f33SShivanshu Shukla 	}
65128bb98f33SShivanshu Shukla 
6513bccd9bceSMarcin Szycik 	rid = ice_find_recp(hw, &lkup_exts, rinfo);
65148bb98f33SShivanshu Shukla 	/* If did not find a recipe that match the existing criteria */
65158bb98f33SShivanshu Shukla 	if (rid == ICE_MAX_NUM_RECIPES)
6516d54699e2STony Nguyen 		return -EINVAL;
65178bb98f33SShivanshu Shukla 
65188bb98f33SShivanshu Shukla 	rule_lock = &hw->switch_info->recp_list[rid].filt_rule_lock;
65198bb98f33SShivanshu Shukla 	list_elem = ice_find_adv_rule_entry(hw, lkups, lkups_cnt, rid, rinfo);
65208bb98f33SShivanshu Shukla 	/* the rule is already removed */
65218bb98f33SShivanshu Shukla 	if (!list_elem)
65228bb98f33SShivanshu Shukla 		return 0;
65238bb98f33SShivanshu Shukla 	mutex_lock(rule_lock);
65248bb98f33SShivanshu Shukla 	if (list_elem->rule_info.sw_act.fltr_act != ICE_FWD_TO_VSI_LIST) {
65258bb98f33SShivanshu Shukla 		remove_rule = true;
65268bb98f33SShivanshu Shukla 	} else if (list_elem->vsi_count > 1) {
65278bb98f33SShivanshu Shukla 		remove_rule = false;
65288bb98f33SShivanshu Shukla 		vsi_handle = rinfo->sw_act.vsi_handle;
65298bb98f33SShivanshu Shukla 		status = ice_adv_rem_update_vsi_list(hw, vsi_handle, list_elem);
65308bb98f33SShivanshu Shukla 	} else {
65318bb98f33SShivanshu Shukla 		vsi_handle = rinfo->sw_act.vsi_handle;
65328bb98f33SShivanshu Shukla 		status = ice_adv_rem_update_vsi_list(hw, vsi_handle, list_elem);
65338bb98f33SShivanshu Shukla 		if (status) {
65348bb98f33SShivanshu Shukla 			mutex_unlock(rule_lock);
65358bb98f33SShivanshu Shukla 			return status;
65368bb98f33SShivanshu Shukla 		}
65378bb98f33SShivanshu Shukla 		if (list_elem->vsi_count == 0)
65388bb98f33SShivanshu Shukla 			remove_rule = true;
65398bb98f33SShivanshu Shukla 	}
65408bb98f33SShivanshu Shukla 	mutex_unlock(rule_lock);
65418bb98f33SShivanshu Shukla 	if (remove_rule) {
65426e1ff618SAlexander Lobakin 		struct ice_sw_rule_lkup_rx_tx *s_rule;
65438bb98f33SShivanshu Shukla 		u16 rule_buf_sz;
65448bb98f33SShivanshu Shukla 
65456e1ff618SAlexander Lobakin 		rule_buf_sz = ICE_SW_RULE_RX_TX_NO_HDR_SIZE(s_rule);
65468bb98f33SShivanshu Shukla 		s_rule = kzalloc(rule_buf_sz, GFP_KERNEL);
65478bb98f33SShivanshu Shukla 		if (!s_rule)
6548d54699e2STony Nguyen 			return -ENOMEM;
65496e1ff618SAlexander Lobakin 		s_rule->act = 0;
65506e1ff618SAlexander Lobakin 		s_rule->index = cpu_to_le16(list_elem->rule_info.fltr_rule_id);
65516e1ff618SAlexander Lobakin 		s_rule->hdr_len = 0;
65528bb98f33SShivanshu Shukla 		status = ice_aq_sw_rules(hw, (struct ice_aqc_sw_rules *)s_rule,
65538bb98f33SShivanshu Shukla 					 rule_buf_sz, 1,
65548bb98f33SShivanshu Shukla 					 ice_aqc_opc_remove_sw_rules, NULL);
6555d54699e2STony Nguyen 		if (!status || status == -ENOENT) {
65568bb98f33SShivanshu Shukla 			struct ice_switch_info *sw = hw->switch_info;
65578bb98f33SShivanshu Shukla 
65588bb98f33SShivanshu Shukla 			mutex_lock(rule_lock);
65598bb98f33SShivanshu Shukla 			list_del(&list_elem->list_entry);
65608bb98f33SShivanshu Shukla 			devm_kfree(ice_hw_to_dev(hw), list_elem->lkups);
65618bb98f33SShivanshu Shukla 			devm_kfree(ice_hw_to_dev(hw), list_elem);
65628bb98f33SShivanshu Shukla 			mutex_unlock(rule_lock);
65638bb98f33SShivanshu Shukla 			if (list_empty(&sw->recp_list[rid].filt_rules))
65648bb98f33SShivanshu Shukla 				sw->recp_list[rid].adv_rule = false;
65658bb98f33SShivanshu Shukla 		}
65668bb98f33SShivanshu Shukla 		kfree(s_rule);
65678bb98f33SShivanshu Shukla 	}
65688bb98f33SShivanshu Shukla 	return status;
65698bb98f33SShivanshu Shukla }
65708bb98f33SShivanshu Shukla 
65718bb98f33SShivanshu Shukla /**
65728bb98f33SShivanshu Shukla  * ice_rem_adv_rule_by_id - removes existing advanced switch rule by ID
65738bb98f33SShivanshu Shukla  * @hw: pointer to the hardware structure
65748bb98f33SShivanshu Shukla  * @remove_entry: data struct which holds rule_id, VSI handle and recipe ID
65758bb98f33SShivanshu Shukla  *
65768bb98f33SShivanshu Shukla  * This function is used to remove 1 rule at a time. The removal is based on
65778bb98f33SShivanshu Shukla  * the remove_entry parameter. This function will remove rule for a given
65788bb98f33SShivanshu Shukla  * vsi_handle with a given rule_id which is passed as parameter in remove_entry
65798bb98f33SShivanshu Shukla  */
65805e24d598STony Nguyen int
65818bb98f33SShivanshu Shukla ice_rem_adv_rule_by_id(struct ice_hw *hw,
65828bb98f33SShivanshu Shukla 		       struct ice_rule_query_data *remove_entry)
65838bb98f33SShivanshu Shukla {
65848bb98f33SShivanshu Shukla 	struct ice_adv_fltr_mgmt_list_entry *list_itr;
65858bb98f33SShivanshu Shukla 	struct list_head *list_head;
65868bb98f33SShivanshu Shukla 	struct ice_adv_rule_info rinfo;
65878bb98f33SShivanshu Shukla 	struct ice_switch_info *sw;
65888bb98f33SShivanshu Shukla 
65898bb98f33SShivanshu Shukla 	sw = hw->switch_info;
65908bb98f33SShivanshu Shukla 	if (!sw->recp_list[remove_entry->rid].recp_created)
6591d54699e2STony Nguyen 		return -EINVAL;
65928bb98f33SShivanshu Shukla 	list_head = &sw->recp_list[remove_entry->rid].filt_rules;
65938bb98f33SShivanshu Shukla 	list_for_each_entry(list_itr, list_head, list_entry) {
65948bb98f33SShivanshu Shukla 		if (list_itr->rule_info.fltr_rule_id ==
65958bb98f33SShivanshu Shukla 		    remove_entry->rule_id) {
65968bb98f33SShivanshu Shukla 			rinfo = list_itr->rule_info;
65978bb98f33SShivanshu Shukla 			rinfo.sw_act.vsi_handle = remove_entry->vsi_handle;
65988bb98f33SShivanshu Shukla 			return ice_rem_adv_rule(hw, list_itr->lkups,
65998bb98f33SShivanshu Shukla 						list_itr->lkups_cnt, &rinfo);
66008bb98f33SShivanshu Shukla 		}
66018bb98f33SShivanshu Shukla 	}
66028bb98f33SShivanshu Shukla 	/* either list is empty or unable to find rule */
6603d54699e2STony Nguyen 	return -ENOENT;
66048bb98f33SShivanshu Shukla }
66058bb98f33SShivanshu Shukla 
66068bb98f33SShivanshu Shukla /**
6607c36a2b97SVictor Raj  * ice_replay_vsi_adv_rule - Replay advanced rule for requested VSI
6608c36a2b97SVictor Raj  * @hw: pointer to the hardware structure
6609c36a2b97SVictor Raj  * @vsi_handle: driver VSI handle
6610c36a2b97SVictor Raj  * @list_head: list for which filters need to be replayed
6611c36a2b97SVictor Raj  *
6612c36a2b97SVictor Raj  * Replay the advanced rule for the given VSI.
6613c36a2b97SVictor Raj  */
6614c36a2b97SVictor Raj static int
6615c36a2b97SVictor Raj ice_replay_vsi_adv_rule(struct ice_hw *hw, u16 vsi_handle,
6616c36a2b97SVictor Raj 			struct list_head *list_head)
6617c36a2b97SVictor Raj {
6618c36a2b97SVictor Raj 	struct ice_rule_query_data added_entry = { 0 };
6619c36a2b97SVictor Raj 	struct ice_adv_fltr_mgmt_list_entry *adv_fltr;
6620c36a2b97SVictor Raj 	int status = 0;
6621c36a2b97SVictor Raj 
6622c36a2b97SVictor Raj 	if (list_empty(list_head))
6623c36a2b97SVictor Raj 		return status;
6624c36a2b97SVictor Raj 	list_for_each_entry(adv_fltr, list_head, list_entry) {
6625c36a2b97SVictor Raj 		struct ice_adv_rule_info *rinfo = &adv_fltr->rule_info;
6626c36a2b97SVictor Raj 		u16 lk_cnt = adv_fltr->lkups_cnt;
6627c36a2b97SVictor Raj 
6628c36a2b97SVictor Raj 		if (vsi_handle != rinfo->sw_act.vsi_handle)
6629c36a2b97SVictor Raj 			continue;
6630c36a2b97SVictor Raj 		status = ice_add_adv_rule(hw, adv_fltr->lkups, lk_cnt, rinfo,
6631c36a2b97SVictor Raj 					  &added_entry);
6632c36a2b97SVictor Raj 		if (status)
6633c36a2b97SVictor Raj 			break;
6634c36a2b97SVictor Raj 	}
6635c36a2b97SVictor Raj 	return status;
6636c36a2b97SVictor Raj }
6637c36a2b97SVictor Raj 
6638c36a2b97SVictor Raj /**
6639334cb062SAnirudh Venkataramanan  * ice_replay_vsi_all_fltr - replay all filters stored in bookkeeping lists
66400f9d5027SAnirudh Venkataramanan  * @hw: pointer to the hardware structure
6641334cb062SAnirudh Venkataramanan  * @vsi_handle: driver VSI handle
66420f9d5027SAnirudh Venkataramanan  *
6643334cb062SAnirudh Venkataramanan  * Replays filters for requested VSI via vsi_handle.
66440f9d5027SAnirudh Venkataramanan  */
66455e24d598STony Nguyen int ice_replay_vsi_all_fltr(struct ice_hw *hw, u16 vsi_handle)
66460f9d5027SAnirudh Venkataramanan {
66470f9d5027SAnirudh Venkataramanan 	struct ice_switch_info *sw = hw->switch_info;
6648c36a2b97SVictor Raj 	int status;
66490f9d5027SAnirudh Venkataramanan 	u8 i;
66500f9d5027SAnirudh Venkataramanan 
6651c36a2b97SVictor Raj 	for (i = 0; i < ICE_MAX_NUM_RECIPES; i++) {
6652334cb062SAnirudh Venkataramanan 		struct list_head *head;
66530f9d5027SAnirudh Venkataramanan 
6654334cb062SAnirudh Venkataramanan 		head = &sw->recp_list[i].filt_replay_rules;
6655c36a2b97SVictor Raj 		if (!sw->recp_list[i].adv_rule)
6656334cb062SAnirudh Venkataramanan 			status = ice_replay_vsi_fltr(hw, vsi_handle, i, head);
6657c36a2b97SVictor Raj 		else
6658c36a2b97SVictor Raj 			status = ice_replay_vsi_adv_rule(hw, vsi_handle, head);
66590f9d5027SAnirudh Venkataramanan 		if (status)
66600f9d5027SAnirudh Venkataramanan 			return status;
66610f9d5027SAnirudh Venkataramanan 	}
66620f9d5027SAnirudh Venkataramanan 	return status;
66630f9d5027SAnirudh Venkataramanan }
6664334cb062SAnirudh Venkataramanan 
6665334cb062SAnirudh Venkataramanan /**
6666334cb062SAnirudh Venkataramanan  * ice_rm_all_sw_replay_rule_info - deletes filter replay rules
6667f9867df6SAnirudh Venkataramanan  * @hw: pointer to the HW struct
6668334cb062SAnirudh Venkataramanan  *
6669334cb062SAnirudh Venkataramanan  * Deletes the filter replay rules.
6670334cb062SAnirudh Venkataramanan  */
6671334cb062SAnirudh Venkataramanan void ice_rm_all_sw_replay_rule_info(struct ice_hw *hw)
6672334cb062SAnirudh Venkataramanan {
6673334cb062SAnirudh Venkataramanan 	struct ice_switch_info *sw = hw->switch_info;
6674334cb062SAnirudh Venkataramanan 	u8 i;
6675334cb062SAnirudh Venkataramanan 
6676334cb062SAnirudh Venkataramanan 	if (!sw)
6677334cb062SAnirudh Venkataramanan 		return;
6678334cb062SAnirudh Venkataramanan 
66798b8ef05bSVictor Raj 	for (i = 0; i < ICE_MAX_NUM_RECIPES; i++) {
6680334cb062SAnirudh Venkataramanan 		if (!list_empty(&sw->recp_list[i].filt_replay_rules)) {
6681334cb062SAnirudh Venkataramanan 			struct list_head *l_head;
6682334cb062SAnirudh Venkataramanan 
6683334cb062SAnirudh Venkataramanan 			l_head = &sw->recp_list[i].filt_replay_rules;
66848b8ef05bSVictor Raj 			if (!sw->recp_list[i].adv_rule)
6685334cb062SAnirudh Venkataramanan 				ice_rem_sw_rule_info(hw, l_head);
66868b8ef05bSVictor Raj 			else
66878b8ef05bSVictor Raj 				ice_rem_adv_rule_info(hw, l_head);
6688334cb062SAnirudh Venkataramanan 		}
6689334cb062SAnirudh Venkataramanan 	}
6690334cb062SAnirudh Venkataramanan }
6691