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 
1850*52da2fb2SPrzemek Kitszel 	status = ice_aq_alloc_free_res(hw, sw_buf, buf_len, opc);
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);
2104*52da2fb2SPrzemek Kitszel 	status = ice_aq_alloc_free_res(hw, sw_buf, buf_len,
2105*52da2fb2SPrzemek Kitszel 				       ice_aqc_opc_alloc_res);
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 /**
2463ec5a6c5fSDave Ertman  * ice_fill_eth_hdr - helper to copy dummy_eth_hdr into supplied buffer
2464ec5a6c5fSDave Ertman  * @eth_hdr: pointer to buffer to populate
2465ec5a6c5fSDave Ertman  */
2466ec5a6c5fSDave Ertman void ice_fill_eth_hdr(u8 *eth_hdr)
2467ec5a6c5fSDave Ertman {
2468ec5a6c5fSDave Ertman 	memcpy(eth_hdr, dummy_eth_header, DUMMY_ETH_HDR_LEN);
2469ec5a6c5fSDave Ertman }
2470ec5a6c5fSDave Ertman 
2471ec5a6c5fSDave 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_vlan_fltr_exist - does this VLAN filter exist for given VSI
34139fea7498SKiran Patil  * @hw: pointer to the hardware structure
34149fea7498SKiran Patil  * @vlan_id: VLAN ID
34159fea7498SKiran Patil  * @vsi_handle: check MAC filter for this VSI
34169fea7498SKiran Patil  */
34179fea7498SKiran Patil bool ice_vlan_fltr_exist(struct ice_hw *hw, u16 vlan_id, 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 (vlan_id > ICE_MAX_VLAN_ID)
34269fea7498SKiran Patil 		return false;
34279fea7498SKiran Patil 
34289fea7498SKiran Patil 	if (!ice_is_vsi_valid(hw, vsi_handle))
34299fea7498SKiran Patil 		return false;
34309fea7498SKiran Patil 
34319fea7498SKiran Patil 	hw_vsi_id = ice_get_hw_vsi_num(hw, vsi_handle);
34329fea7498SKiran Patil 	sw = hw->switch_info;
34339fea7498SKiran Patil 	rule_head = &sw->recp_list[ICE_SW_LKUP_VLAN].filt_rules;
34349fea7498SKiran Patil 	if (!rule_head)
34359fea7498SKiran Patil 		return false;
34369fea7498SKiran Patil 
34379fea7498SKiran Patil 	rule_lock = &sw->recp_list[ICE_SW_LKUP_VLAN].filt_rule_lock;
34389fea7498SKiran Patil 	mutex_lock(rule_lock);
34399fea7498SKiran Patil 	list_for_each_entry(entry, rule_head, list_entry) {
34409fea7498SKiran Patil 		struct ice_fltr_info *f_info = &entry->fltr_info;
34419fea7498SKiran Patil 		u16 entry_vlan_id = f_info->l_data.vlan.vlan_id;
34429fea7498SKiran Patil 		struct ice_vsi_list_map_info *map_info;
34439fea7498SKiran Patil 
34449fea7498SKiran Patil 		if (entry_vlan_id > ICE_MAX_VLAN_ID)
34459fea7498SKiran Patil 			continue;
34469fea7498SKiran Patil 
34479fea7498SKiran Patil 		if (f_info->flag != ICE_FLTR_TX ||
34489fea7498SKiran Patil 		    f_info->src_id != ICE_SRC_ID_VSI ||
34499fea7498SKiran Patil 		    f_info->lkup_type != ICE_SW_LKUP_VLAN)
34509fea7498SKiran Patil 			continue;
34519fea7498SKiran Patil 
34529fea7498SKiran Patil 		/* Only allowed filter action are FWD_TO_VSI/_VSI_LIST */
34539fea7498SKiran Patil 		if (f_info->fltr_act != ICE_FWD_TO_VSI &&
34549fea7498SKiran Patil 		    f_info->fltr_act != ICE_FWD_TO_VSI_LIST)
34559fea7498SKiran Patil 			continue;
34569fea7498SKiran Patil 
34579fea7498SKiran Patil 		if (f_info->fltr_act == ICE_FWD_TO_VSI) {
34589fea7498SKiran Patil 			if (hw_vsi_id != f_info->fwd_id.hw_vsi_id)
34599fea7498SKiran Patil 				continue;
34609fea7498SKiran Patil 		} else if (f_info->fltr_act == ICE_FWD_TO_VSI_LIST) {
34619fea7498SKiran Patil 			/* If filter_action is FWD_TO_VSI_LIST, make sure
34629fea7498SKiran Patil 			 * that VSI being checked is part of VSI list
34639fea7498SKiran Patil 			 */
34649fea7498SKiran Patil 			if (entry->vsi_count == 1 &&
34659fea7498SKiran Patil 			    entry->vsi_list_info) {
34669fea7498SKiran Patil 				map_info = entry->vsi_list_info;
34679fea7498SKiran Patil 				if (!test_bit(vsi_handle, map_info->vsi_map))
34689fea7498SKiran Patil 					continue;
34699fea7498SKiran Patil 			}
34709fea7498SKiran Patil 		}
34719fea7498SKiran Patil 
34729fea7498SKiran Patil 		if (vlan_id == entry_vlan_id) {
34739fea7498SKiran Patil 			mutex_unlock(rule_lock);
34749fea7498SKiran Patil 			return true;
34759fea7498SKiran Patil 		}
34769fea7498SKiran Patil 	}
34779fea7498SKiran Patil 	mutex_unlock(rule_lock);
34789fea7498SKiran Patil 
34799fea7498SKiran Patil 	return false;
34809fea7498SKiran Patil }
34819fea7498SKiran Patil 
34829fea7498SKiran Patil /**
34839daf8208SAnirudh Venkataramanan  * ice_add_mac - Add a MAC address based filter rule
34849daf8208SAnirudh Venkataramanan  * @hw: pointer to the hardware structure
34859daf8208SAnirudh Venkataramanan  * @m_list: list of MAC addresses and forwarding information
34869daf8208SAnirudh Venkataramanan  */
34875e24d598STony Nguyen int ice_add_mac(struct ice_hw *hw, struct list_head *m_list)
34889daf8208SAnirudh Venkataramanan {
34899daf8208SAnirudh Venkataramanan 	struct ice_fltr_list_entry *m_list_itr;
34905518ac2aSTony Nguyen 	int status = 0;
34919daf8208SAnirudh Venkataramanan 
34929daf8208SAnirudh Venkataramanan 	if (!m_list || !hw)
3493d54699e2STony Nguyen 		return -EINVAL;
34949daf8208SAnirudh Venkataramanan 
34959daf8208SAnirudh Venkataramanan 	list_for_each_entry(m_list_itr, m_list, list_entry) {
34969daf8208SAnirudh Venkataramanan 		u8 *add = &m_list_itr->fltr_info.l_data.mac.mac_addr[0];
34975726ca0eSAnirudh Venkataramanan 		u16 vsi_handle;
34985726ca0eSAnirudh Venkataramanan 		u16 hw_vsi_id;
34999daf8208SAnirudh Venkataramanan 
350080d144c9SAnirudh Venkataramanan 		m_list_itr->fltr_info.flag = ICE_FLTR_TX;
35015726ca0eSAnirudh Venkataramanan 		vsi_handle = m_list_itr->fltr_info.vsi_handle;
35025726ca0eSAnirudh Venkataramanan 		if (!ice_is_vsi_valid(hw, vsi_handle))
3503d54699e2STony Nguyen 			return -EINVAL;
35045726ca0eSAnirudh Venkataramanan 		hw_vsi_id = ice_get_hw_vsi_num(hw, vsi_handle);
35055726ca0eSAnirudh Venkataramanan 		m_list_itr->fltr_info.fwd_id.hw_vsi_id = hw_vsi_id;
3506f9867df6SAnirudh Venkataramanan 		/* update the src in case it is VSI num */
35075726ca0eSAnirudh Venkataramanan 		if (m_list_itr->fltr_info.src_id != ICE_SRC_ID_VSI)
3508d54699e2STony Nguyen 			return -EINVAL;
35095726ca0eSAnirudh Venkataramanan 		m_list_itr->fltr_info.src = hw_vsi_id;
351080d144c9SAnirudh Venkataramanan 		if (m_list_itr->fltr_info.lkup_type != ICE_SW_LKUP_MAC ||
351180d144c9SAnirudh Venkataramanan 		    is_zero_ether_addr(add))
3512d54699e2STony Nguyen 			return -EINVAL;
3513e1e9db57SSylwester Dziedziuch 
3514e1e9db57SSylwester Dziedziuch 		m_list_itr->status = ice_add_rule_internal(hw, ICE_SW_LKUP_MAC,
351580d144c9SAnirudh Venkataramanan 							   m_list_itr);
351680d144c9SAnirudh Venkataramanan 		if (m_list_itr->status)
351780d144c9SAnirudh Venkataramanan 			return m_list_itr->status;
35189daf8208SAnirudh Venkataramanan 	}
35199daf8208SAnirudh Venkataramanan 
35209daf8208SAnirudh Venkataramanan 	return status;
35219daf8208SAnirudh Venkataramanan }
35229daf8208SAnirudh Venkataramanan 
35239daf8208SAnirudh Venkataramanan /**
3524d76a60baSAnirudh Venkataramanan  * ice_add_vlan_internal - Add one VLAN based filter rule
3525d76a60baSAnirudh Venkataramanan  * @hw: pointer to the hardware structure
3526d76a60baSAnirudh Venkataramanan  * @f_entry: filter entry containing one VLAN information
3527d76a60baSAnirudh Venkataramanan  */
35285e24d598STony Nguyen static int
3529d76a60baSAnirudh Venkataramanan ice_add_vlan_internal(struct ice_hw *hw, struct ice_fltr_list_entry *f_entry)
3530d76a60baSAnirudh Venkataramanan {
353180d144c9SAnirudh Venkataramanan 	struct ice_switch_info *sw = hw->switch_info;
3532d76a60baSAnirudh Venkataramanan 	struct ice_fltr_mgmt_list_entry *v_list_itr;
35335726ca0eSAnirudh Venkataramanan 	struct ice_fltr_info *new_fltr, *cur_fltr;
35345726ca0eSAnirudh Venkataramanan 	enum ice_sw_lkup_type lkup_type;
35355726ca0eSAnirudh Venkataramanan 	u16 vsi_list_id = 0, vsi_handle;
353680d144c9SAnirudh Venkataramanan 	struct mutex *rule_lock; /* Lock to protect filter rule list */
35375e24d598STony Nguyen 	int status = 0;
3538d76a60baSAnirudh Venkataramanan 
35395726ca0eSAnirudh Venkataramanan 	if (!ice_is_vsi_valid(hw, f_entry->fltr_info.vsi_handle))
3540d54699e2STony Nguyen 		return -EINVAL;
35415726ca0eSAnirudh Venkataramanan 
35425726ca0eSAnirudh Venkataramanan 	f_entry->fltr_info.fwd_id.hw_vsi_id =
35435726ca0eSAnirudh Venkataramanan 		ice_get_hw_vsi_num(hw, f_entry->fltr_info.vsi_handle);
3544d76a60baSAnirudh Venkataramanan 	new_fltr = &f_entry->fltr_info;
35455726ca0eSAnirudh Venkataramanan 
3546f9867df6SAnirudh Venkataramanan 	/* VLAN ID should only be 12 bits */
3547d76a60baSAnirudh Venkataramanan 	if (new_fltr->l_data.vlan.vlan_id > ICE_MAX_VLAN_ID)
3548d54699e2STony Nguyen 		return -EINVAL;
3549d76a60baSAnirudh Venkataramanan 
35505726ca0eSAnirudh Venkataramanan 	if (new_fltr->src_id != ICE_SRC_ID_VSI)
3551d54699e2STony Nguyen 		return -EINVAL;
35525726ca0eSAnirudh Venkataramanan 
35535726ca0eSAnirudh Venkataramanan 	new_fltr->src = new_fltr->fwd_id.hw_vsi_id;
35545726ca0eSAnirudh Venkataramanan 	lkup_type = new_fltr->lkup_type;
35555726ca0eSAnirudh Venkataramanan 	vsi_handle = new_fltr->vsi_handle;
355680d144c9SAnirudh Venkataramanan 	rule_lock = &sw->recp_list[ICE_SW_LKUP_VLAN].filt_rule_lock;
355780d144c9SAnirudh Venkataramanan 	mutex_lock(rule_lock);
355880d144c9SAnirudh Venkataramanan 	v_list_itr = ice_find_rule_entry(hw, ICE_SW_LKUP_VLAN, new_fltr);
3559d76a60baSAnirudh Venkataramanan 	if (!v_list_itr) {
35605726ca0eSAnirudh Venkataramanan 		struct ice_vsi_list_map_info *map_info = NULL;
3561d76a60baSAnirudh Venkataramanan 
3562d76a60baSAnirudh Venkataramanan 		if (new_fltr->fltr_act == ICE_FWD_TO_VSI) {
35635726ca0eSAnirudh Venkataramanan 			/* All VLAN pruning rules use a VSI list. Check if
35645726ca0eSAnirudh Venkataramanan 			 * there is already a VSI list containing VSI that we
35655726ca0eSAnirudh Venkataramanan 			 * want to add. If found, use the same vsi_list_id for
35665726ca0eSAnirudh Venkataramanan 			 * this new VLAN rule or else create a new list.
3567d76a60baSAnirudh Venkataramanan 			 */
35685726ca0eSAnirudh Venkataramanan 			map_info = ice_find_vsi_list_entry(hw, ICE_SW_LKUP_VLAN,
35695726ca0eSAnirudh Venkataramanan 							   vsi_handle,
35705726ca0eSAnirudh Venkataramanan 							   &vsi_list_id);
35715726ca0eSAnirudh Venkataramanan 			if (!map_info) {
35725726ca0eSAnirudh Venkataramanan 				status = ice_create_vsi_list_rule(hw,
35735726ca0eSAnirudh Venkataramanan 								  &vsi_handle,
35745726ca0eSAnirudh Venkataramanan 								  1,
3575d76a60baSAnirudh Venkataramanan 								  &vsi_list_id,
3576d76a60baSAnirudh Venkataramanan 								  lkup_type);
3577d76a60baSAnirudh Venkataramanan 				if (status)
357880d144c9SAnirudh Venkataramanan 					goto exit;
35795726ca0eSAnirudh Venkataramanan 			}
35805726ca0eSAnirudh Venkataramanan 			/* Convert the action to forwarding to a VSI list. */
3581d76a60baSAnirudh Venkataramanan 			new_fltr->fltr_act = ICE_FWD_TO_VSI_LIST;
3582d76a60baSAnirudh Venkataramanan 			new_fltr->fwd_id.vsi_list_id = vsi_list_id;
3583d76a60baSAnirudh Venkataramanan 		}
3584d76a60baSAnirudh Venkataramanan 
3585d76a60baSAnirudh Venkataramanan 		status = ice_create_pkt_fwd_rule(hw, f_entry);
35865726ca0eSAnirudh Venkataramanan 		if (!status) {
358780d144c9SAnirudh Venkataramanan 			v_list_itr = ice_find_rule_entry(hw, ICE_SW_LKUP_VLAN,
358880d144c9SAnirudh Venkataramanan 							 new_fltr);
358980d144c9SAnirudh Venkataramanan 			if (!v_list_itr) {
3590d54699e2STony Nguyen 				status = -ENOENT;
359180d144c9SAnirudh Venkataramanan 				goto exit;
359280d144c9SAnirudh Venkataramanan 			}
35935726ca0eSAnirudh Venkataramanan 			/* reuse VSI list for new rule and increment ref_cnt */
35945726ca0eSAnirudh Venkataramanan 			if (map_info) {
35955726ca0eSAnirudh Venkataramanan 				v_list_itr->vsi_list_info = map_info;
35965726ca0eSAnirudh Venkataramanan 				map_info->ref_cnt++;
35975726ca0eSAnirudh Venkataramanan 			} else {
3598d76a60baSAnirudh Venkataramanan 				v_list_itr->vsi_list_info =
35995726ca0eSAnirudh Venkataramanan 					ice_create_vsi_list_map(hw, &vsi_handle,
36005726ca0eSAnirudh Venkataramanan 								1, vsi_list_id);
3601d76a60baSAnirudh Venkataramanan 			}
36025726ca0eSAnirudh Venkataramanan 		}
36035726ca0eSAnirudh Venkataramanan 	} else if (v_list_itr->vsi_list_info->ref_cnt == 1) {
3604f9867df6SAnirudh Venkataramanan 		/* Update existing VSI list to add new VSI ID only if it used
36055726ca0eSAnirudh Venkataramanan 		 * by one VLAN rule.
36065726ca0eSAnirudh Venkataramanan 		 */
36075726ca0eSAnirudh Venkataramanan 		cur_fltr = &v_list_itr->fltr_info;
36085726ca0eSAnirudh Venkataramanan 		status = ice_add_update_vsi_list(hw, v_list_itr, cur_fltr,
36095726ca0eSAnirudh Venkataramanan 						 new_fltr);
36105726ca0eSAnirudh Venkataramanan 	} else {
36115726ca0eSAnirudh Venkataramanan 		/* If VLAN rule exists and VSI list being used by this rule is
36125726ca0eSAnirudh Venkataramanan 		 * referenced by more than 1 VLAN rule. Then create a new VSI
36135726ca0eSAnirudh Venkataramanan 		 * list appending previous VSI with new VSI and update existing
3614f9867df6SAnirudh Venkataramanan 		 * VLAN rule to point to new VSI list ID
36155726ca0eSAnirudh Venkataramanan 		 */
36165726ca0eSAnirudh Venkataramanan 		struct ice_fltr_info tmp_fltr;
36175726ca0eSAnirudh Venkataramanan 		u16 vsi_handle_arr[2];
36185726ca0eSAnirudh Venkataramanan 		u16 cur_handle;
3619d76a60baSAnirudh Venkataramanan 
36205726ca0eSAnirudh Venkataramanan 		/* Current implementation only supports reusing VSI list with
36215726ca0eSAnirudh Venkataramanan 		 * one VSI count. We should never hit below condition
36225726ca0eSAnirudh Venkataramanan 		 */
36235726ca0eSAnirudh Venkataramanan 		if (v_list_itr->vsi_count > 1 &&
36245726ca0eSAnirudh Venkataramanan 		    v_list_itr->vsi_list_info->ref_cnt > 1) {
36259228d8b2SJacob 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");
3626d54699e2STony Nguyen 			status = -EIO;
362780d144c9SAnirudh Venkataramanan 			goto exit;
3628d76a60baSAnirudh Venkataramanan 		}
3629d76a60baSAnirudh Venkataramanan 
36305726ca0eSAnirudh Venkataramanan 		cur_handle =
36315726ca0eSAnirudh Venkataramanan 			find_first_bit(v_list_itr->vsi_list_info->vsi_map,
36325726ca0eSAnirudh Venkataramanan 				       ICE_MAX_VSI);
36335726ca0eSAnirudh Venkataramanan 
36345726ca0eSAnirudh Venkataramanan 		/* A rule already exists with the new VSI being added */
36355726ca0eSAnirudh Venkataramanan 		if (cur_handle == vsi_handle) {
3636d54699e2STony Nguyen 			status = -EEXIST;
36375726ca0eSAnirudh Venkataramanan 			goto exit;
36385726ca0eSAnirudh Venkataramanan 		}
36395726ca0eSAnirudh Venkataramanan 
36405726ca0eSAnirudh Venkataramanan 		vsi_handle_arr[0] = cur_handle;
36415726ca0eSAnirudh Venkataramanan 		vsi_handle_arr[1] = vsi_handle;
36425726ca0eSAnirudh Venkataramanan 		status = ice_create_vsi_list_rule(hw, &vsi_handle_arr[0], 2,
36435726ca0eSAnirudh Venkataramanan 						  &vsi_list_id, lkup_type);
36445726ca0eSAnirudh Venkataramanan 		if (status)
36455726ca0eSAnirudh Venkataramanan 			goto exit;
36465726ca0eSAnirudh Venkataramanan 
36475726ca0eSAnirudh Venkataramanan 		tmp_fltr = v_list_itr->fltr_info;
36485726ca0eSAnirudh Venkataramanan 		tmp_fltr.fltr_rule_id = v_list_itr->fltr_info.fltr_rule_id;
36495726ca0eSAnirudh Venkataramanan 		tmp_fltr.fwd_id.vsi_list_id = vsi_list_id;
36505726ca0eSAnirudh Venkataramanan 		tmp_fltr.fltr_act = ICE_FWD_TO_VSI_LIST;
36515726ca0eSAnirudh Venkataramanan 		/* Update the previous switch rule to a new VSI list which
3652df17b7e0SAnirudh Venkataramanan 		 * includes current VSI that is requested
36535726ca0eSAnirudh Venkataramanan 		 */
36545726ca0eSAnirudh Venkataramanan 		status = ice_update_pkt_fwd_rule(hw, &tmp_fltr);
36555726ca0eSAnirudh Venkataramanan 		if (status)
36565726ca0eSAnirudh Venkataramanan 			goto exit;
36575726ca0eSAnirudh Venkataramanan 
36585726ca0eSAnirudh Venkataramanan 		/* before overriding VSI list map info. decrement ref_cnt of
36595726ca0eSAnirudh Venkataramanan 		 * previous VSI list
36605726ca0eSAnirudh Venkataramanan 		 */
36615726ca0eSAnirudh Venkataramanan 		v_list_itr->vsi_list_info->ref_cnt--;
36625726ca0eSAnirudh Venkataramanan 
36635726ca0eSAnirudh Venkataramanan 		/* now update to newly created list */
36645726ca0eSAnirudh Venkataramanan 		v_list_itr->fltr_info.fwd_id.vsi_list_id = vsi_list_id;
36655726ca0eSAnirudh Venkataramanan 		v_list_itr->vsi_list_info =
36665726ca0eSAnirudh Venkataramanan 			ice_create_vsi_list_map(hw, &vsi_handle_arr[0], 2,
36675726ca0eSAnirudh Venkataramanan 						vsi_list_id);
36685726ca0eSAnirudh Venkataramanan 		v_list_itr->vsi_count++;
36695726ca0eSAnirudh Venkataramanan 	}
367080d144c9SAnirudh Venkataramanan 
367180d144c9SAnirudh Venkataramanan exit:
367280d144c9SAnirudh Venkataramanan 	mutex_unlock(rule_lock);
367380d144c9SAnirudh Venkataramanan 	return status;
3674d76a60baSAnirudh Venkataramanan }
3675d76a60baSAnirudh Venkataramanan 
3676d76a60baSAnirudh Venkataramanan /**
3677d76a60baSAnirudh Venkataramanan  * ice_add_vlan - Add VLAN based filter rule
3678d76a60baSAnirudh Venkataramanan  * @hw: pointer to the hardware structure
3679d76a60baSAnirudh Venkataramanan  * @v_list: list of VLAN entries and forwarding information
3680d76a60baSAnirudh Venkataramanan  */
36815e24d598STony Nguyen int ice_add_vlan(struct ice_hw *hw, struct list_head *v_list)
3682d76a60baSAnirudh Venkataramanan {
3683d76a60baSAnirudh Venkataramanan 	struct ice_fltr_list_entry *v_list_itr;
3684d76a60baSAnirudh Venkataramanan 
3685d76a60baSAnirudh Venkataramanan 	if (!v_list || !hw)
3686d54699e2STony Nguyen 		return -EINVAL;
3687d76a60baSAnirudh Venkataramanan 
3688d76a60baSAnirudh Venkataramanan 	list_for_each_entry(v_list_itr, v_list, list_entry) {
3689d76a60baSAnirudh Venkataramanan 		if (v_list_itr->fltr_info.lkup_type != ICE_SW_LKUP_VLAN)
3690d54699e2STony Nguyen 			return -EINVAL;
369180d144c9SAnirudh Venkataramanan 		v_list_itr->fltr_info.flag = ICE_FLTR_TX;
369280d144c9SAnirudh Venkataramanan 		v_list_itr->status = ice_add_vlan_internal(hw, v_list_itr);
369380d144c9SAnirudh Venkataramanan 		if (v_list_itr->status)
369480d144c9SAnirudh Venkataramanan 			return v_list_itr->status;
3695d76a60baSAnirudh Venkataramanan 	}
3696d76a60baSAnirudh Venkataramanan 	return 0;
3697d76a60baSAnirudh Venkataramanan }
3698d76a60baSAnirudh Venkataramanan 
3699d76a60baSAnirudh Venkataramanan /**
3700d95276ceSAkeem G Abodunrin  * ice_add_eth_mac - Add ethertype and MAC based filter rule
3701d95276ceSAkeem G Abodunrin  * @hw: pointer to the hardware structure
3702d95276ceSAkeem G Abodunrin  * @em_list: list of ether type MAC filter, MAC is optional
37032e0e6228SDave Ertman  *
37042e0e6228SDave Ertman  * This function requires the caller to populate the entries in
37052e0e6228SDave Ertman  * the filter list with the necessary fields (including flags to
37062e0e6228SDave Ertman  * indicate Tx or Rx rules).
3707d95276ceSAkeem G Abodunrin  */
37085518ac2aSTony Nguyen int ice_add_eth_mac(struct ice_hw *hw, struct list_head *em_list)
3709d95276ceSAkeem G Abodunrin {
3710d95276ceSAkeem G Abodunrin 	struct ice_fltr_list_entry *em_list_itr;
3711d95276ceSAkeem G Abodunrin 
3712d95276ceSAkeem G Abodunrin 	if (!em_list || !hw)
3713d54699e2STony Nguyen 		return -EINVAL;
3714d95276ceSAkeem G Abodunrin 
3715d95276ceSAkeem G Abodunrin 	list_for_each_entry(em_list_itr, em_list, list_entry) {
3716d95276ceSAkeem G Abodunrin 		enum ice_sw_lkup_type l_type =
3717d95276ceSAkeem G Abodunrin 			em_list_itr->fltr_info.lkup_type;
3718d95276ceSAkeem G Abodunrin 
3719d95276ceSAkeem G Abodunrin 		if (l_type != ICE_SW_LKUP_ETHERTYPE_MAC &&
3720d95276ceSAkeem G Abodunrin 		    l_type != ICE_SW_LKUP_ETHERTYPE)
3721d54699e2STony Nguyen 			return -EINVAL;
3722d95276ceSAkeem G Abodunrin 
3723d95276ceSAkeem G Abodunrin 		em_list_itr->status = ice_add_rule_internal(hw, l_type,
3724d95276ceSAkeem G Abodunrin 							    em_list_itr);
3725d95276ceSAkeem G Abodunrin 		if (em_list_itr->status)
3726d95276ceSAkeem G Abodunrin 			return em_list_itr->status;
3727d95276ceSAkeem G Abodunrin 	}
3728d95276ceSAkeem G Abodunrin 	return 0;
3729d95276ceSAkeem G Abodunrin }
3730d95276ceSAkeem G Abodunrin 
3731d95276ceSAkeem G Abodunrin /**
3732d95276ceSAkeem G Abodunrin  * ice_remove_eth_mac - Remove an ethertype (or MAC) based filter rule
3733d95276ceSAkeem G Abodunrin  * @hw: pointer to the hardware structure
3734d95276ceSAkeem G Abodunrin  * @em_list: list of ethertype or ethertype MAC entries
3735d95276ceSAkeem G Abodunrin  */
37365518ac2aSTony Nguyen int ice_remove_eth_mac(struct ice_hw *hw, struct list_head *em_list)
3737d95276ceSAkeem G Abodunrin {
3738d95276ceSAkeem G Abodunrin 	struct ice_fltr_list_entry *em_list_itr, *tmp;
3739d95276ceSAkeem G Abodunrin 
3740d95276ceSAkeem G Abodunrin 	if (!em_list || !hw)
3741d54699e2STony Nguyen 		return -EINVAL;
3742d95276ceSAkeem G Abodunrin 
3743d95276ceSAkeem G Abodunrin 	list_for_each_entry_safe(em_list_itr, tmp, em_list, list_entry) {
3744d95276ceSAkeem G Abodunrin 		enum ice_sw_lkup_type l_type =
3745d95276ceSAkeem G Abodunrin 			em_list_itr->fltr_info.lkup_type;
3746d95276ceSAkeem G Abodunrin 
3747d95276ceSAkeem G Abodunrin 		if (l_type != ICE_SW_LKUP_ETHERTYPE_MAC &&
3748d95276ceSAkeem G Abodunrin 		    l_type != ICE_SW_LKUP_ETHERTYPE)
3749d54699e2STony Nguyen 			return -EINVAL;
3750d95276ceSAkeem G Abodunrin 
3751d95276ceSAkeem G Abodunrin 		em_list_itr->status = ice_remove_rule_internal(hw, l_type,
3752d95276ceSAkeem G Abodunrin 							       em_list_itr);
3753d95276ceSAkeem G Abodunrin 		if (em_list_itr->status)
3754d95276ceSAkeem G Abodunrin 			return em_list_itr->status;
3755d95276ceSAkeem G Abodunrin 	}
3756d95276ceSAkeem G Abodunrin 	return 0;
3757d95276ceSAkeem G Abodunrin }
3758d95276ceSAkeem G Abodunrin 
3759d95276ceSAkeem G Abodunrin /**
37600f9d5027SAnirudh Venkataramanan  * ice_rem_sw_rule_info
37610f9d5027SAnirudh Venkataramanan  * @hw: pointer to the hardware structure
37620f9d5027SAnirudh Venkataramanan  * @rule_head: pointer to the switch list structure that we want to delete
37630f9d5027SAnirudh Venkataramanan  */
37640f9d5027SAnirudh Venkataramanan static void
37650f9d5027SAnirudh Venkataramanan ice_rem_sw_rule_info(struct ice_hw *hw, struct list_head *rule_head)
37660f9d5027SAnirudh Venkataramanan {
37670f9d5027SAnirudh Venkataramanan 	if (!list_empty(rule_head)) {
37680f9d5027SAnirudh Venkataramanan 		struct ice_fltr_mgmt_list_entry *entry;
37690f9d5027SAnirudh Venkataramanan 		struct ice_fltr_mgmt_list_entry *tmp;
37700f9d5027SAnirudh Venkataramanan 
37710f9d5027SAnirudh Venkataramanan 		list_for_each_entry_safe(entry, tmp, rule_head, list_entry) {
37720f9d5027SAnirudh Venkataramanan 			list_del(&entry->list_entry);
37730f9d5027SAnirudh Venkataramanan 			devm_kfree(ice_hw_to_dev(hw), entry);
37740f9d5027SAnirudh Venkataramanan 		}
37750f9d5027SAnirudh Venkataramanan 	}
37760f9d5027SAnirudh Venkataramanan }
37770f9d5027SAnirudh Venkataramanan 
37780f9d5027SAnirudh Venkataramanan /**
37798b8ef05bSVictor Raj  * ice_rem_adv_rule_info
37808b8ef05bSVictor Raj  * @hw: pointer to the hardware structure
37818b8ef05bSVictor Raj  * @rule_head: pointer to the switch list structure that we want to delete
37828b8ef05bSVictor Raj  */
37838b8ef05bSVictor Raj static void
37848b8ef05bSVictor Raj ice_rem_adv_rule_info(struct ice_hw *hw, struct list_head *rule_head)
37858b8ef05bSVictor Raj {
37868b8ef05bSVictor Raj 	struct ice_adv_fltr_mgmt_list_entry *tmp_entry;
37878b8ef05bSVictor Raj 	struct ice_adv_fltr_mgmt_list_entry *lst_itr;
37888b8ef05bSVictor Raj 
37898b8ef05bSVictor Raj 	if (list_empty(rule_head))
37908b8ef05bSVictor Raj 		return;
37918b8ef05bSVictor Raj 
37928b8ef05bSVictor Raj 	list_for_each_entry_safe(lst_itr, tmp_entry, rule_head, list_entry) {
37938b8ef05bSVictor Raj 		list_del(&lst_itr->list_entry);
37948b8ef05bSVictor Raj 		devm_kfree(ice_hw_to_dev(hw), lst_itr->lkups);
37958b8ef05bSVictor Raj 		devm_kfree(ice_hw_to_dev(hw), lst_itr);
37968b8ef05bSVictor Raj 	}
37978b8ef05bSVictor Raj }
37988b8ef05bSVictor Raj 
37998b8ef05bSVictor Raj /**
380080d144c9SAnirudh Venkataramanan  * ice_cfg_dflt_vsi - change state of VSI to set/clear default
3801d7393425SMichal Wilczynski  * @pi: pointer to the port_info structure
38025726ca0eSAnirudh Venkataramanan  * @vsi_handle: VSI handle to set as default
3803e94d4478SAnirudh Venkataramanan  * @set: true to add the above mentioned switch rule, false to remove it
3804e94d4478SAnirudh Venkataramanan  * @direction: ICE_FLTR_RX or ICE_FLTR_TX
380580d144c9SAnirudh Venkataramanan  *
380680d144c9SAnirudh Venkataramanan  * add filter rule to set/unset given VSI as default VSI for the switch
380780d144c9SAnirudh Venkataramanan  * (represented by swid)
3808e94d4478SAnirudh Venkataramanan  */
3809d7393425SMichal Wilczynski int
3810d7393425SMichal Wilczynski ice_cfg_dflt_vsi(struct ice_port_info *pi, u16 vsi_handle, bool set,
3811d7393425SMichal Wilczynski 		 u8 direction)
3812e94d4478SAnirudh Venkataramanan {
3813d7393425SMichal Wilczynski 	struct ice_fltr_list_entry f_list_entry;
3814e94d4478SAnirudh Venkataramanan 	struct ice_fltr_info f_info;
3815d7393425SMichal Wilczynski 	struct ice_hw *hw = pi->hw;
38165726ca0eSAnirudh Venkataramanan 	u16 hw_vsi_id;
38175518ac2aSTony Nguyen 	int status;
38185726ca0eSAnirudh Venkataramanan 
38195726ca0eSAnirudh Venkataramanan 	if (!ice_is_vsi_valid(hw, vsi_handle))
3820d54699e2STony Nguyen 		return -EINVAL;
3821d7393425SMichal Wilczynski 
38225726ca0eSAnirudh Venkataramanan 	hw_vsi_id = ice_get_hw_vsi_num(hw, vsi_handle);
3823e94d4478SAnirudh Venkataramanan 
3824e94d4478SAnirudh Venkataramanan 	memset(&f_info, 0, sizeof(f_info));
3825e94d4478SAnirudh Venkataramanan 
3826e94d4478SAnirudh Venkataramanan 	f_info.lkup_type = ICE_SW_LKUP_DFLT;
3827e94d4478SAnirudh Venkataramanan 	f_info.flag = direction;
3828e94d4478SAnirudh Venkataramanan 	f_info.fltr_act = ICE_FWD_TO_VSI;
38295726ca0eSAnirudh Venkataramanan 	f_info.fwd_id.hw_vsi_id = hw_vsi_id;
3830d7393425SMichal Wilczynski 	f_info.vsi_handle = vsi_handle;
3831e94d4478SAnirudh Venkataramanan 
3832e94d4478SAnirudh Venkataramanan 	if (f_info.flag & ICE_FLTR_RX) {
3833e94d4478SAnirudh Venkataramanan 		f_info.src = hw->port_info->lport;
38345726ca0eSAnirudh Venkataramanan 		f_info.src_id = ICE_SRC_ID_LPORT;
3835e94d4478SAnirudh Venkataramanan 	} else if (f_info.flag & ICE_FLTR_TX) {
38365726ca0eSAnirudh Venkataramanan 		f_info.src_id = ICE_SRC_ID_VSI;
38375726ca0eSAnirudh Venkataramanan 		f_info.src = hw_vsi_id;
3838e94d4478SAnirudh Venkataramanan 	}
3839d7393425SMichal Wilczynski 	f_list_entry.fltr_info = f_info;
3840e94d4478SAnirudh Venkataramanan 
3841e94d4478SAnirudh Venkataramanan 	if (set)
3842d7393425SMichal Wilczynski 		status = ice_add_rule_internal(hw, ICE_SW_LKUP_DFLT,
3843d7393425SMichal Wilczynski 					       &f_list_entry);
3844e94d4478SAnirudh Venkataramanan 	else
3845d7393425SMichal Wilczynski 		status = ice_remove_rule_internal(hw, ICE_SW_LKUP_DFLT,
3846d7393425SMichal Wilczynski 						  &f_list_entry);
3847e94d4478SAnirudh Venkataramanan 
3848e94d4478SAnirudh Venkataramanan 	return status;
3849e94d4478SAnirudh Venkataramanan }
3850e94d4478SAnirudh Venkataramanan 
3851e94d4478SAnirudh Venkataramanan /**
3852d7393425SMichal Wilczynski  * ice_vsi_uses_fltr - Determine if given VSI uses specified filter
3853d7393425SMichal Wilczynski  * @fm_entry: filter entry to inspect
3854d7393425SMichal Wilczynski  * @vsi_handle: VSI handle to compare with filter info
3855d7393425SMichal Wilczynski  */
3856d7393425SMichal Wilczynski static bool
3857d7393425SMichal Wilczynski ice_vsi_uses_fltr(struct ice_fltr_mgmt_list_entry *fm_entry, u16 vsi_handle)
3858d7393425SMichal Wilczynski {
3859d7393425SMichal Wilczynski 	return ((fm_entry->fltr_info.fltr_act == ICE_FWD_TO_VSI &&
3860d7393425SMichal Wilczynski 		 fm_entry->fltr_info.vsi_handle == vsi_handle) ||
3861d7393425SMichal Wilczynski 		(fm_entry->fltr_info.fltr_act == ICE_FWD_TO_VSI_LIST &&
3862d7393425SMichal Wilczynski 		 fm_entry->vsi_list_info &&
3863d7393425SMichal Wilczynski 		 (test_bit(vsi_handle, fm_entry->vsi_list_info->vsi_map))));
3864d7393425SMichal Wilczynski }
3865d7393425SMichal Wilczynski 
3866d7393425SMichal Wilczynski /**
3867d7393425SMichal Wilczynski  * ice_check_if_dflt_vsi - check if VSI is default VSI
3868d7393425SMichal Wilczynski  * @pi: pointer to the port_info structure
3869d7393425SMichal Wilczynski  * @vsi_handle: vsi handle to check for in filter list
3870d7393425SMichal Wilczynski  * @rule_exists: indicates if there are any VSI's in the rule list
3871d7393425SMichal Wilczynski  *
3872d7393425SMichal Wilczynski  * checks if the VSI is in a default VSI list, and also indicates
3873d7393425SMichal Wilczynski  * if the default VSI list is empty
3874d7393425SMichal Wilczynski  */
3875d7393425SMichal Wilczynski bool
3876d7393425SMichal Wilczynski ice_check_if_dflt_vsi(struct ice_port_info *pi, u16 vsi_handle,
3877d7393425SMichal Wilczynski 		      bool *rule_exists)
3878d7393425SMichal Wilczynski {
3879d7393425SMichal Wilczynski 	struct ice_fltr_mgmt_list_entry *fm_entry;
3880d7393425SMichal Wilczynski 	struct ice_sw_recipe *recp_list;
3881d7393425SMichal Wilczynski 	struct list_head *rule_head;
3882d7393425SMichal Wilczynski 	struct mutex *rule_lock; /* Lock to protect filter rule list */
3883d7393425SMichal Wilczynski 	bool ret = false;
3884d7393425SMichal Wilczynski 
3885d7393425SMichal Wilczynski 	recp_list = &pi->hw->switch_info->recp_list[ICE_SW_LKUP_DFLT];
3886d7393425SMichal Wilczynski 	rule_lock = &recp_list->filt_rule_lock;
3887d7393425SMichal Wilczynski 	rule_head = &recp_list->filt_rules;
3888d7393425SMichal Wilczynski 
3889d7393425SMichal Wilczynski 	mutex_lock(rule_lock);
3890d7393425SMichal Wilczynski 
3891d7393425SMichal Wilczynski 	if (rule_exists && !list_empty(rule_head))
3892d7393425SMichal Wilczynski 		*rule_exists = true;
3893d7393425SMichal Wilczynski 
3894d7393425SMichal Wilczynski 	list_for_each_entry(fm_entry, rule_head, list_entry) {
3895d7393425SMichal Wilczynski 		if (ice_vsi_uses_fltr(fm_entry, vsi_handle)) {
3896d7393425SMichal Wilczynski 			ret = true;
3897d7393425SMichal Wilczynski 			break;
3898d7393425SMichal Wilczynski 		}
3899d7393425SMichal Wilczynski 	}
3900d7393425SMichal Wilczynski 
3901d7393425SMichal Wilczynski 	mutex_unlock(rule_lock);
3902d7393425SMichal Wilczynski 
3903d7393425SMichal Wilczynski 	return ret;
3904d7393425SMichal Wilczynski }
3905d7393425SMichal Wilczynski 
3906d7393425SMichal Wilczynski /**
390780d144c9SAnirudh Venkataramanan  * ice_remove_mac - remove a MAC address based filter rule
3908d76a60baSAnirudh Venkataramanan  * @hw: pointer to the hardware structure
390980d144c9SAnirudh Venkataramanan  * @m_list: list of MAC addresses and forwarding information
391080d144c9SAnirudh Venkataramanan  *
391180d144c9SAnirudh Venkataramanan  * This function removes either a MAC filter rule or a specific VSI from a
391280d144c9SAnirudh Venkataramanan  * VSI list for a multicast MAC address.
391380d144c9SAnirudh Venkataramanan  *
39145518ac2aSTony Nguyen  * Returns -ENOENT if a given entry was not added by ice_add_mac. Caller should
39155518ac2aSTony Nguyen  * be aware that this call will only work if all the entries passed into m_list
39165518ac2aSTony Nguyen  * were added previously. It will not attempt to do a partial remove of entries
39175518ac2aSTony Nguyen  * that were found.
3918d76a60baSAnirudh Venkataramanan  */
39195e24d598STony Nguyen int ice_remove_mac(struct ice_hw *hw, struct list_head *m_list)
3920d76a60baSAnirudh Venkataramanan {
3921072f0c3dSDave Ertman 	struct ice_fltr_list_entry *list_itr, *tmp;
3922d76a60baSAnirudh Venkataramanan 
392380d144c9SAnirudh Venkataramanan 	if (!m_list)
3924d54699e2STony Nguyen 		return -EINVAL;
3925d76a60baSAnirudh Venkataramanan 
3926072f0c3dSDave Ertman 	list_for_each_entry_safe(list_itr, tmp, m_list, list_entry) {
392780d144c9SAnirudh Venkataramanan 		enum ice_sw_lkup_type l_type = list_itr->fltr_info.lkup_type;
39288b2c8582SAkeem G Abodunrin 		u16 vsi_handle;
392980d144c9SAnirudh Venkataramanan 
393080d144c9SAnirudh Venkataramanan 		if (l_type != ICE_SW_LKUP_MAC)
3931d54699e2STony Nguyen 			return -EINVAL;
39328b2c8582SAkeem G Abodunrin 
39338b2c8582SAkeem G Abodunrin 		vsi_handle = list_itr->fltr_info.vsi_handle;
39348b2c8582SAkeem G Abodunrin 		if (!ice_is_vsi_valid(hw, vsi_handle))
3935d54699e2STony Nguyen 			return -EINVAL;
39368b2c8582SAkeem G Abodunrin 
39378b2c8582SAkeem G Abodunrin 		list_itr->fltr_info.fwd_id.hw_vsi_id =
39388b2c8582SAkeem G Abodunrin 					ice_get_hw_vsi_num(hw, vsi_handle);
3939e1e9db57SSylwester Dziedziuch 
394080d144c9SAnirudh Venkataramanan 		list_itr->status = ice_remove_rule_internal(hw,
394180d144c9SAnirudh Venkataramanan 							    ICE_SW_LKUP_MAC,
394280d144c9SAnirudh Venkataramanan 							    list_itr);
394380d144c9SAnirudh Venkataramanan 		if (list_itr->status)
394480d144c9SAnirudh Venkataramanan 			return list_itr->status;
394580d144c9SAnirudh Venkataramanan 	}
394680d144c9SAnirudh Venkataramanan 	return 0;
3947d76a60baSAnirudh Venkataramanan }
3948d76a60baSAnirudh Venkataramanan 
3949d76a60baSAnirudh Venkataramanan /**
3950d76a60baSAnirudh Venkataramanan  * ice_remove_vlan - Remove VLAN based filter rule
3951d76a60baSAnirudh Venkataramanan  * @hw: pointer to the hardware structure
3952d76a60baSAnirudh Venkataramanan  * @v_list: list of VLAN entries and forwarding information
3953d76a60baSAnirudh Venkataramanan  */
39545518ac2aSTony Nguyen int ice_remove_vlan(struct ice_hw *hw, struct list_head *v_list)
3955d76a60baSAnirudh Venkataramanan {
3956072f0c3dSDave Ertman 	struct ice_fltr_list_entry *v_list_itr, *tmp;
3957d76a60baSAnirudh Venkataramanan 
3958d76a60baSAnirudh Venkataramanan 	if (!v_list || !hw)
3959d54699e2STony Nguyen 		return -EINVAL;
3960d76a60baSAnirudh Venkataramanan 
3961072f0c3dSDave Ertman 	list_for_each_entry_safe(v_list_itr, tmp, v_list, list_entry) {
396280d144c9SAnirudh Venkataramanan 		enum ice_sw_lkup_type l_type = v_list_itr->fltr_info.lkup_type;
396380d144c9SAnirudh Venkataramanan 
396480d144c9SAnirudh Venkataramanan 		if (l_type != ICE_SW_LKUP_VLAN)
3965d54699e2STony Nguyen 			return -EINVAL;
396680d144c9SAnirudh Venkataramanan 		v_list_itr->status = ice_remove_rule_internal(hw,
396780d144c9SAnirudh Venkataramanan 							      ICE_SW_LKUP_VLAN,
396880d144c9SAnirudh Venkataramanan 							      v_list_itr);
396980d144c9SAnirudh Venkataramanan 		if (v_list_itr->status)
397080d144c9SAnirudh Venkataramanan 			return v_list_itr->status;
3971d76a60baSAnirudh Venkataramanan 	}
397280d144c9SAnirudh Venkataramanan 	return 0;
3973d76a60baSAnirudh Venkataramanan }
397480d144c9SAnirudh Venkataramanan 
397580d144c9SAnirudh Venkataramanan /**
397680d144c9SAnirudh Venkataramanan  * ice_add_entry_to_vsi_fltr_list - Add copy of fltr_list_entry to remove list
397780d144c9SAnirudh Venkataramanan  * @hw: pointer to the hardware structure
39785726ca0eSAnirudh Venkataramanan  * @vsi_handle: VSI handle to remove filters from
397980d144c9SAnirudh Venkataramanan  * @vsi_list_head: pointer to the list to add entry to
398080d144c9SAnirudh Venkataramanan  * @fi: pointer to fltr_info of filter entry to copy & add
398180d144c9SAnirudh Venkataramanan  *
398280d144c9SAnirudh Venkataramanan  * Helper function, used when creating a list of filters to remove from
398380d144c9SAnirudh Venkataramanan  * a specific VSI. The entry added to vsi_list_head is a COPY of the
398480d144c9SAnirudh Venkataramanan  * original filter entry, with the exception of fltr_info.fltr_act and
398580d144c9SAnirudh Venkataramanan  * fltr_info.fwd_id fields. These are set such that later logic can
398680d144c9SAnirudh Venkataramanan  * extract which VSI to remove the fltr from, and pass on that information.
398780d144c9SAnirudh Venkataramanan  */
39885e24d598STony Nguyen static int
39895726ca0eSAnirudh Venkataramanan ice_add_entry_to_vsi_fltr_list(struct ice_hw *hw, u16 vsi_handle,
399080d144c9SAnirudh Venkataramanan 			       struct list_head *vsi_list_head,
399180d144c9SAnirudh Venkataramanan 			       struct ice_fltr_info *fi)
399280d144c9SAnirudh Venkataramanan {
399380d144c9SAnirudh Venkataramanan 	struct ice_fltr_list_entry *tmp;
399480d144c9SAnirudh Venkataramanan 
399580d144c9SAnirudh Venkataramanan 	/* this memory is freed up in the caller function
399680d144c9SAnirudh Venkataramanan 	 * once filters for this VSI are removed
399780d144c9SAnirudh Venkataramanan 	 */
399880d144c9SAnirudh Venkataramanan 	tmp = devm_kzalloc(ice_hw_to_dev(hw), sizeof(*tmp), GFP_KERNEL);
399980d144c9SAnirudh Venkataramanan 	if (!tmp)
4000d54699e2STony Nguyen 		return -ENOMEM;
400180d144c9SAnirudh Venkataramanan 
400280d144c9SAnirudh Venkataramanan 	tmp->fltr_info = *fi;
400380d144c9SAnirudh Venkataramanan 
400480d144c9SAnirudh Venkataramanan 	/* Overwrite these fields to indicate which VSI to remove filter from,
400580d144c9SAnirudh Venkataramanan 	 * so find and remove logic can extract the information from the
400680d144c9SAnirudh Venkataramanan 	 * list entries. Note that original entries will still have proper
400780d144c9SAnirudh Venkataramanan 	 * values.
400880d144c9SAnirudh Venkataramanan 	 */
400980d144c9SAnirudh Venkataramanan 	tmp->fltr_info.fltr_act = ICE_FWD_TO_VSI;
40105726ca0eSAnirudh Venkataramanan 	tmp->fltr_info.vsi_handle = vsi_handle;
40115726ca0eSAnirudh Venkataramanan 	tmp->fltr_info.fwd_id.hw_vsi_id = ice_get_hw_vsi_num(hw, vsi_handle);
401280d144c9SAnirudh Venkataramanan 
401380d144c9SAnirudh Venkataramanan 	list_add(&tmp->list_entry, vsi_list_head);
401480d144c9SAnirudh Venkataramanan 
401580d144c9SAnirudh Venkataramanan 	return 0;
4016d76a60baSAnirudh Venkataramanan }
4017d76a60baSAnirudh Venkataramanan 
4018d76a60baSAnirudh Venkataramanan /**
40199daf8208SAnirudh Venkataramanan  * ice_add_to_vsi_fltr_list - Add VSI filters to the list
40209daf8208SAnirudh Venkataramanan  * @hw: pointer to the hardware structure
40215726ca0eSAnirudh Venkataramanan  * @vsi_handle: VSI handle to remove filters from
40229daf8208SAnirudh Venkataramanan  * @lkup_list_head: pointer to the list that has certain lookup type filters
40235726ca0eSAnirudh Venkataramanan  * @vsi_list_head: pointer to the list pertaining to VSI with vsi_handle
402480d144c9SAnirudh Venkataramanan  *
402580d144c9SAnirudh Venkataramanan  * Locates all filters in lkup_list_head that are used by the given VSI,
402680d144c9SAnirudh Venkataramanan  * and adds COPIES of those entries to vsi_list_head (intended to be used
402780d144c9SAnirudh Venkataramanan  * to remove the listed filters).
402880d144c9SAnirudh Venkataramanan  * Note that this means all entries in vsi_list_head must be explicitly
402980d144c9SAnirudh Venkataramanan  * deallocated by the caller when done with list.
40309daf8208SAnirudh Venkataramanan  */
40315e24d598STony Nguyen static int
40325726ca0eSAnirudh Venkataramanan ice_add_to_vsi_fltr_list(struct ice_hw *hw, u16 vsi_handle,
40339daf8208SAnirudh Venkataramanan 			 struct list_head *lkup_list_head,
40349daf8208SAnirudh Venkataramanan 			 struct list_head *vsi_list_head)
40359daf8208SAnirudh Venkataramanan {
40369daf8208SAnirudh Venkataramanan 	struct ice_fltr_mgmt_list_entry *fm_entry;
40375e24d598STony Nguyen 	int status = 0;
40389daf8208SAnirudh Venkataramanan 
4039f9867df6SAnirudh Venkataramanan 	/* check to make sure VSI ID is valid and within boundary */
40405726ca0eSAnirudh Venkataramanan 	if (!ice_is_vsi_valid(hw, vsi_handle))
4041d54699e2STony Nguyen 		return -EINVAL;
40429daf8208SAnirudh Venkataramanan 
40439daf8208SAnirudh Venkataramanan 	list_for_each_entry(fm_entry, lkup_list_head, list_entry) {
40447a91d3f0SJacek Bułatek 		if (!ice_vsi_uses_fltr(fm_entry, vsi_handle))
404580d144c9SAnirudh Venkataramanan 			continue;
40469daf8208SAnirudh Venkataramanan 
40475726ca0eSAnirudh Venkataramanan 		status = ice_add_entry_to_vsi_fltr_list(hw, vsi_handle,
40487a91d3f0SJacek Bułatek 							vsi_list_head,
40497a91d3f0SJacek Bułatek 							&fm_entry->fltr_info);
405080d144c9SAnirudh Venkataramanan 		if (status)
405180d144c9SAnirudh Venkataramanan 			return status;
40529daf8208SAnirudh Venkataramanan 	}
405380d144c9SAnirudh Venkataramanan 	return status;
40549daf8208SAnirudh Venkataramanan }
40559daf8208SAnirudh Venkataramanan 
40569daf8208SAnirudh Venkataramanan /**
40575eda8afdSAkeem G Abodunrin  * ice_determine_promisc_mask
40585eda8afdSAkeem G Abodunrin  * @fi: filter info to parse
40595eda8afdSAkeem G Abodunrin  *
40605eda8afdSAkeem G Abodunrin  * Helper function to determine which ICE_PROMISC_ mask corresponds
40615eda8afdSAkeem G Abodunrin  * to given filter into.
40625eda8afdSAkeem G Abodunrin  */
40635eda8afdSAkeem G Abodunrin static u8 ice_determine_promisc_mask(struct ice_fltr_info *fi)
40645eda8afdSAkeem G Abodunrin {
40655eda8afdSAkeem G Abodunrin 	u16 vid = fi->l_data.mac_vlan.vlan_id;
40665eda8afdSAkeem G Abodunrin 	u8 *macaddr = fi->l_data.mac.mac_addr;
40675eda8afdSAkeem G Abodunrin 	bool is_tx_fltr = false;
40685eda8afdSAkeem G Abodunrin 	u8 promisc_mask = 0;
40695eda8afdSAkeem G Abodunrin 
40705eda8afdSAkeem G Abodunrin 	if (fi->flag == ICE_FLTR_TX)
40715eda8afdSAkeem G Abodunrin 		is_tx_fltr = true;
40725eda8afdSAkeem G Abodunrin 
40735eda8afdSAkeem G Abodunrin 	if (is_broadcast_ether_addr(macaddr))
40745eda8afdSAkeem G Abodunrin 		promisc_mask |= is_tx_fltr ?
40755eda8afdSAkeem G Abodunrin 			ICE_PROMISC_BCAST_TX : ICE_PROMISC_BCAST_RX;
40765eda8afdSAkeem G Abodunrin 	else if (is_multicast_ether_addr(macaddr))
40775eda8afdSAkeem G Abodunrin 		promisc_mask |= is_tx_fltr ?
40785eda8afdSAkeem G Abodunrin 			ICE_PROMISC_MCAST_TX : ICE_PROMISC_MCAST_RX;
40795eda8afdSAkeem G Abodunrin 	else if (is_unicast_ether_addr(macaddr))
40805eda8afdSAkeem G Abodunrin 		promisc_mask |= is_tx_fltr ?
40815eda8afdSAkeem G Abodunrin 			ICE_PROMISC_UCAST_TX : ICE_PROMISC_UCAST_RX;
40825eda8afdSAkeem G Abodunrin 	if (vid)
40835eda8afdSAkeem G Abodunrin 		promisc_mask |= is_tx_fltr ?
40845eda8afdSAkeem G Abodunrin 			ICE_PROMISC_VLAN_TX : ICE_PROMISC_VLAN_RX;
40855eda8afdSAkeem G Abodunrin 
40865eda8afdSAkeem G Abodunrin 	return promisc_mask;
40875eda8afdSAkeem G Abodunrin }
40885eda8afdSAkeem G Abodunrin 
40895eda8afdSAkeem G Abodunrin /**
40905eda8afdSAkeem G Abodunrin  * ice_remove_promisc - Remove promisc based filter rules
40915eda8afdSAkeem G Abodunrin  * @hw: pointer to the hardware structure
4092f9867df6SAnirudh Venkataramanan  * @recp_id: recipe ID for which the rule needs to removed
40935eda8afdSAkeem G Abodunrin  * @v_list: list of promisc entries
40945eda8afdSAkeem G Abodunrin  */
40955e24d598STony Nguyen static int
40965518ac2aSTony Nguyen ice_remove_promisc(struct ice_hw *hw, u8 recp_id, struct list_head *v_list)
40975eda8afdSAkeem G Abodunrin {
40985eda8afdSAkeem G Abodunrin 	struct ice_fltr_list_entry *v_list_itr, *tmp;
40995eda8afdSAkeem G Abodunrin 
41005eda8afdSAkeem G Abodunrin 	list_for_each_entry_safe(v_list_itr, tmp, v_list, list_entry) {
41015eda8afdSAkeem G Abodunrin 		v_list_itr->status =
41025eda8afdSAkeem G Abodunrin 			ice_remove_rule_internal(hw, recp_id, v_list_itr);
41035eda8afdSAkeem G Abodunrin 		if (v_list_itr->status)
41045eda8afdSAkeem G Abodunrin 			return v_list_itr->status;
41055eda8afdSAkeem G Abodunrin 	}
41065eda8afdSAkeem G Abodunrin 	return 0;
41075eda8afdSAkeem G Abodunrin }
41085eda8afdSAkeem G Abodunrin 
41095eda8afdSAkeem G Abodunrin /**
41105eda8afdSAkeem G Abodunrin  * ice_clear_vsi_promisc - clear specified promiscuous mode(s) for given VSI
41115eda8afdSAkeem G Abodunrin  * @hw: pointer to the hardware structure
41125eda8afdSAkeem G Abodunrin  * @vsi_handle: VSI handle to clear mode
41135eda8afdSAkeem G Abodunrin  * @promisc_mask: mask of promiscuous config bits to clear
41145eda8afdSAkeem G Abodunrin  * @vid: VLAN ID to clear VLAN promiscuous
41155eda8afdSAkeem G Abodunrin  */
41165e24d598STony Nguyen int
41175eda8afdSAkeem G Abodunrin ice_clear_vsi_promisc(struct ice_hw *hw, u16 vsi_handle, u8 promisc_mask,
41185eda8afdSAkeem G Abodunrin 		      u16 vid)
41195eda8afdSAkeem G Abodunrin {
41205eda8afdSAkeem G Abodunrin 	struct ice_switch_info *sw = hw->switch_info;
41215eda8afdSAkeem G Abodunrin 	struct ice_fltr_list_entry *fm_entry, *tmp;
41225eda8afdSAkeem G Abodunrin 	struct list_head remove_list_head;
41235eda8afdSAkeem G Abodunrin 	struct ice_fltr_mgmt_list_entry *itr;
41245eda8afdSAkeem G Abodunrin 	struct list_head *rule_head;
41255eda8afdSAkeem G Abodunrin 	struct mutex *rule_lock;	/* Lock to protect filter rule list */
41265e24d598STony Nguyen 	int status = 0;
41275eda8afdSAkeem G Abodunrin 	u8 recipe_id;
41285eda8afdSAkeem G Abodunrin 
41295eda8afdSAkeem G Abodunrin 	if (!ice_is_vsi_valid(hw, vsi_handle))
4130d54699e2STony Nguyen 		return -EINVAL;
41315eda8afdSAkeem G Abodunrin 
41321bc7a4abSBrett Creeley 	if (promisc_mask & (ICE_PROMISC_VLAN_RX | ICE_PROMISC_VLAN_TX))
41335eda8afdSAkeem G Abodunrin 		recipe_id = ICE_SW_LKUP_PROMISC_VLAN;
41345eda8afdSAkeem G Abodunrin 	else
41355eda8afdSAkeem G Abodunrin 		recipe_id = ICE_SW_LKUP_PROMISC;
41365eda8afdSAkeem G Abodunrin 
41375eda8afdSAkeem G Abodunrin 	rule_head = &sw->recp_list[recipe_id].filt_rules;
41385eda8afdSAkeem G Abodunrin 	rule_lock = &sw->recp_list[recipe_id].filt_rule_lock;
41395eda8afdSAkeem G Abodunrin 
41405eda8afdSAkeem G Abodunrin 	INIT_LIST_HEAD(&remove_list_head);
41415eda8afdSAkeem G Abodunrin 
41425eda8afdSAkeem G Abodunrin 	mutex_lock(rule_lock);
41435eda8afdSAkeem G Abodunrin 	list_for_each_entry(itr, rule_head, list_entry) {
41441bc7a4abSBrett Creeley 		struct ice_fltr_info *fltr_info;
41455eda8afdSAkeem G Abodunrin 		u8 fltr_promisc_mask = 0;
41465eda8afdSAkeem G Abodunrin 
41475eda8afdSAkeem G Abodunrin 		if (!ice_vsi_uses_fltr(itr, vsi_handle))
41485eda8afdSAkeem G Abodunrin 			continue;
41491bc7a4abSBrett Creeley 		fltr_info = &itr->fltr_info;
41505eda8afdSAkeem G Abodunrin 
41511bc7a4abSBrett Creeley 		if (recipe_id == ICE_SW_LKUP_PROMISC_VLAN &&
41521bc7a4abSBrett Creeley 		    vid != fltr_info->l_data.mac_vlan.vlan_id)
41531bc7a4abSBrett Creeley 			continue;
41541bc7a4abSBrett Creeley 
41551bc7a4abSBrett Creeley 		fltr_promisc_mask |= ice_determine_promisc_mask(fltr_info);
41565eda8afdSAkeem G Abodunrin 
41575eda8afdSAkeem G Abodunrin 		/* Skip if filter is not completely specified by given mask */
41585eda8afdSAkeem G Abodunrin 		if (fltr_promisc_mask & ~promisc_mask)
41595eda8afdSAkeem G Abodunrin 			continue;
41605eda8afdSAkeem G Abodunrin 
41615eda8afdSAkeem G Abodunrin 		status = ice_add_entry_to_vsi_fltr_list(hw, vsi_handle,
41625eda8afdSAkeem G Abodunrin 							&remove_list_head,
41631bc7a4abSBrett Creeley 							fltr_info);
41645eda8afdSAkeem G Abodunrin 		if (status) {
41655eda8afdSAkeem G Abodunrin 			mutex_unlock(rule_lock);
41665eda8afdSAkeem G Abodunrin 			goto free_fltr_list;
41675eda8afdSAkeem G Abodunrin 		}
41685eda8afdSAkeem G Abodunrin 	}
41695eda8afdSAkeem G Abodunrin 	mutex_unlock(rule_lock);
41705eda8afdSAkeem G Abodunrin 
41715eda8afdSAkeem G Abodunrin 	status = ice_remove_promisc(hw, recipe_id, &remove_list_head);
41725eda8afdSAkeem G Abodunrin 
41735eda8afdSAkeem G Abodunrin free_fltr_list:
41745eda8afdSAkeem G Abodunrin 	list_for_each_entry_safe(fm_entry, tmp, &remove_list_head, list_entry) {
41755eda8afdSAkeem G Abodunrin 		list_del(&fm_entry->list_entry);
41765eda8afdSAkeem G Abodunrin 		devm_kfree(ice_hw_to_dev(hw), fm_entry);
41775eda8afdSAkeem G Abodunrin 	}
41785eda8afdSAkeem G Abodunrin 
41795eda8afdSAkeem G Abodunrin 	return status;
41805eda8afdSAkeem G Abodunrin }
41815eda8afdSAkeem G Abodunrin 
41825eda8afdSAkeem G Abodunrin /**
41835eda8afdSAkeem G Abodunrin  * ice_set_vsi_promisc - set given VSI to given promiscuous mode(s)
41845eda8afdSAkeem G Abodunrin  * @hw: pointer to the hardware structure
41855eda8afdSAkeem G Abodunrin  * @vsi_handle: VSI handle to configure
41865eda8afdSAkeem G Abodunrin  * @promisc_mask: mask of promiscuous config bits
41875eda8afdSAkeem G Abodunrin  * @vid: VLAN ID to set VLAN promiscuous
41885eda8afdSAkeem G Abodunrin  */
41895e24d598STony Nguyen int
41905eda8afdSAkeem G Abodunrin ice_set_vsi_promisc(struct ice_hw *hw, u16 vsi_handle, u8 promisc_mask, u16 vid)
41915eda8afdSAkeem G Abodunrin {
41925eda8afdSAkeem G Abodunrin 	enum { UCAST_FLTR = 1, MCAST_FLTR, BCAST_FLTR };
41935eda8afdSAkeem G Abodunrin 	struct ice_fltr_list_entry f_list_entry;
41945eda8afdSAkeem G Abodunrin 	struct ice_fltr_info new_fltr;
41955eda8afdSAkeem G Abodunrin 	bool is_tx_fltr;
41965518ac2aSTony Nguyen 	int status = 0;
41975eda8afdSAkeem G Abodunrin 	u16 hw_vsi_id;
41985eda8afdSAkeem G Abodunrin 	int pkt_type;
41995eda8afdSAkeem G Abodunrin 	u8 recipe_id;
42005eda8afdSAkeem G Abodunrin 
42015eda8afdSAkeem G Abodunrin 	if (!ice_is_vsi_valid(hw, vsi_handle))
4202d54699e2STony Nguyen 		return -EINVAL;
42035eda8afdSAkeem G Abodunrin 	hw_vsi_id = ice_get_hw_vsi_num(hw, vsi_handle);
42045eda8afdSAkeem G Abodunrin 
42055eda8afdSAkeem G Abodunrin 	memset(&new_fltr, 0, sizeof(new_fltr));
42065eda8afdSAkeem G Abodunrin 
42075eda8afdSAkeem G Abodunrin 	if (promisc_mask & (ICE_PROMISC_VLAN_RX | ICE_PROMISC_VLAN_TX)) {
42085eda8afdSAkeem G Abodunrin 		new_fltr.lkup_type = ICE_SW_LKUP_PROMISC_VLAN;
42095eda8afdSAkeem G Abodunrin 		new_fltr.l_data.mac_vlan.vlan_id = vid;
42105eda8afdSAkeem G Abodunrin 		recipe_id = ICE_SW_LKUP_PROMISC_VLAN;
42115eda8afdSAkeem G Abodunrin 	} else {
42125eda8afdSAkeem G Abodunrin 		new_fltr.lkup_type = ICE_SW_LKUP_PROMISC;
42135eda8afdSAkeem G Abodunrin 		recipe_id = ICE_SW_LKUP_PROMISC;
42145eda8afdSAkeem G Abodunrin 	}
42155eda8afdSAkeem G Abodunrin 
42165eda8afdSAkeem G Abodunrin 	/* Separate filters must be set for each direction/packet type
42175eda8afdSAkeem G Abodunrin 	 * combination, so we will loop over the mask value, store the
42185eda8afdSAkeem G Abodunrin 	 * individual type, and clear it out in the input mask as it
42195eda8afdSAkeem G Abodunrin 	 * is found.
42205eda8afdSAkeem G Abodunrin 	 */
42215eda8afdSAkeem G Abodunrin 	while (promisc_mask) {
42225eda8afdSAkeem G Abodunrin 		u8 *mac_addr;
42235eda8afdSAkeem G Abodunrin 
42245eda8afdSAkeem G Abodunrin 		pkt_type = 0;
42255eda8afdSAkeem G Abodunrin 		is_tx_fltr = false;
42265eda8afdSAkeem G Abodunrin 
42275eda8afdSAkeem G Abodunrin 		if (promisc_mask & ICE_PROMISC_UCAST_RX) {
42285eda8afdSAkeem G Abodunrin 			promisc_mask &= ~ICE_PROMISC_UCAST_RX;
42295eda8afdSAkeem G Abodunrin 			pkt_type = UCAST_FLTR;
42305eda8afdSAkeem G Abodunrin 		} else if (promisc_mask & ICE_PROMISC_UCAST_TX) {
42315eda8afdSAkeem G Abodunrin 			promisc_mask &= ~ICE_PROMISC_UCAST_TX;
42325eda8afdSAkeem G Abodunrin 			pkt_type = UCAST_FLTR;
42335eda8afdSAkeem G Abodunrin 			is_tx_fltr = true;
42345eda8afdSAkeem G Abodunrin 		} else if (promisc_mask & ICE_PROMISC_MCAST_RX) {
42355eda8afdSAkeem G Abodunrin 			promisc_mask &= ~ICE_PROMISC_MCAST_RX;
42365eda8afdSAkeem G Abodunrin 			pkt_type = MCAST_FLTR;
42375eda8afdSAkeem G Abodunrin 		} else if (promisc_mask & ICE_PROMISC_MCAST_TX) {
42385eda8afdSAkeem G Abodunrin 			promisc_mask &= ~ICE_PROMISC_MCAST_TX;
42395eda8afdSAkeem G Abodunrin 			pkt_type = MCAST_FLTR;
42405eda8afdSAkeem G Abodunrin 			is_tx_fltr = true;
42415eda8afdSAkeem G Abodunrin 		} else if (promisc_mask & ICE_PROMISC_BCAST_RX) {
42425eda8afdSAkeem G Abodunrin 			promisc_mask &= ~ICE_PROMISC_BCAST_RX;
42435eda8afdSAkeem G Abodunrin 			pkt_type = BCAST_FLTR;
42445eda8afdSAkeem G Abodunrin 		} else if (promisc_mask & ICE_PROMISC_BCAST_TX) {
42455eda8afdSAkeem G Abodunrin 			promisc_mask &= ~ICE_PROMISC_BCAST_TX;
42465eda8afdSAkeem G Abodunrin 			pkt_type = BCAST_FLTR;
42475eda8afdSAkeem G Abodunrin 			is_tx_fltr = true;
42485eda8afdSAkeem G Abodunrin 		}
42495eda8afdSAkeem G Abodunrin 
42505eda8afdSAkeem G Abodunrin 		/* Check for VLAN promiscuous flag */
42515eda8afdSAkeem G Abodunrin 		if (promisc_mask & ICE_PROMISC_VLAN_RX) {
42525eda8afdSAkeem G Abodunrin 			promisc_mask &= ~ICE_PROMISC_VLAN_RX;
42535eda8afdSAkeem G Abodunrin 		} else if (promisc_mask & ICE_PROMISC_VLAN_TX) {
42545eda8afdSAkeem G Abodunrin 			promisc_mask &= ~ICE_PROMISC_VLAN_TX;
42555eda8afdSAkeem G Abodunrin 			is_tx_fltr = true;
42565eda8afdSAkeem G Abodunrin 		}
42575eda8afdSAkeem G Abodunrin 
42585eda8afdSAkeem G Abodunrin 		/* Set filter DA based on packet type */
42595eda8afdSAkeem G Abodunrin 		mac_addr = new_fltr.l_data.mac.mac_addr;
42605eda8afdSAkeem G Abodunrin 		if (pkt_type == BCAST_FLTR) {
42615eda8afdSAkeem G Abodunrin 			eth_broadcast_addr(mac_addr);
42625eda8afdSAkeem G Abodunrin 		} else if (pkt_type == MCAST_FLTR ||
42635eda8afdSAkeem G Abodunrin 			   pkt_type == UCAST_FLTR) {
42645eda8afdSAkeem G Abodunrin 			/* Use the dummy ether header DA */
42655eda8afdSAkeem G Abodunrin 			ether_addr_copy(mac_addr, dummy_eth_header);
42665eda8afdSAkeem G Abodunrin 			if (pkt_type == MCAST_FLTR)
42675eda8afdSAkeem G Abodunrin 				mac_addr[0] |= 0x1;	/* Set multicast bit */
42685eda8afdSAkeem G Abodunrin 		}
42695eda8afdSAkeem G Abodunrin 
42705eda8afdSAkeem G Abodunrin 		/* Need to reset this to zero for all iterations */
42715eda8afdSAkeem G Abodunrin 		new_fltr.flag = 0;
42725eda8afdSAkeem G Abodunrin 		if (is_tx_fltr) {
42735eda8afdSAkeem G Abodunrin 			new_fltr.flag |= ICE_FLTR_TX;
42745eda8afdSAkeem G Abodunrin 			new_fltr.src = hw_vsi_id;
42755eda8afdSAkeem G Abodunrin 		} else {
42765eda8afdSAkeem G Abodunrin 			new_fltr.flag |= ICE_FLTR_RX;
42775eda8afdSAkeem G Abodunrin 			new_fltr.src = hw->port_info->lport;
42785eda8afdSAkeem G Abodunrin 		}
42795eda8afdSAkeem G Abodunrin 
42805eda8afdSAkeem G Abodunrin 		new_fltr.fltr_act = ICE_FWD_TO_VSI;
42815eda8afdSAkeem G Abodunrin 		new_fltr.vsi_handle = vsi_handle;
42825eda8afdSAkeem G Abodunrin 		new_fltr.fwd_id.hw_vsi_id = hw_vsi_id;
42835eda8afdSAkeem G Abodunrin 		f_list_entry.fltr_info = new_fltr;
42845eda8afdSAkeem G Abodunrin 
42855eda8afdSAkeem G Abodunrin 		status = ice_add_rule_internal(hw, recipe_id, &f_list_entry);
42865eda8afdSAkeem G Abodunrin 		if (status)
42875eda8afdSAkeem G Abodunrin 			goto set_promisc_exit;
42885eda8afdSAkeem G Abodunrin 	}
42895eda8afdSAkeem G Abodunrin 
42905eda8afdSAkeem G Abodunrin set_promisc_exit:
42915eda8afdSAkeem G Abodunrin 	return status;
42925eda8afdSAkeem G Abodunrin }
42935eda8afdSAkeem G Abodunrin 
42945eda8afdSAkeem G Abodunrin /**
42955eda8afdSAkeem G Abodunrin  * ice_set_vlan_vsi_promisc
42965eda8afdSAkeem G Abodunrin  * @hw: pointer to the hardware structure
42975eda8afdSAkeem G Abodunrin  * @vsi_handle: VSI handle to configure
42985eda8afdSAkeem G Abodunrin  * @promisc_mask: mask of promiscuous config bits
42995eda8afdSAkeem G Abodunrin  * @rm_vlan_promisc: Clear VLANs VSI promisc mode
43005eda8afdSAkeem G Abodunrin  *
43015eda8afdSAkeem G Abodunrin  * Configure VSI with all associated VLANs to given promiscuous mode(s)
43025eda8afdSAkeem G Abodunrin  */
43035e24d598STony Nguyen int
43045eda8afdSAkeem G Abodunrin ice_set_vlan_vsi_promisc(struct ice_hw *hw, u16 vsi_handle, u8 promisc_mask,
43055eda8afdSAkeem G Abodunrin 			 bool rm_vlan_promisc)
43065eda8afdSAkeem G Abodunrin {
43075eda8afdSAkeem G Abodunrin 	struct ice_switch_info *sw = hw->switch_info;
43085eda8afdSAkeem G Abodunrin 	struct ice_fltr_list_entry *list_itr, *tmp;
43095eda8afdSAkeem G Abodunrin 	struct list_head vsi_list_head;
43105eda8afdSAkeem G Abodunrin 	struct list_head *vlan_head;
43115eda8afdSAkeem G Abodunrin 	struct mutex *vlan_lock; /* Lock to protect filter rule list */
43125eda8afdSAkeem G Abodunrin 	u16 vlan_id;
43135518ac2aSTony Nguyen 	int status;
43145eda8afdSAkeem G Abodunrin 
43155eda8afdSAkeem G Abodunrin 	INIT_LIST_HEAD(&vsi_list_head);
43165eda8afdSAkeem G Abodunrin 	vlan_lock = &sw->recp_list[ICE_SW_LKUP_VLAN].filt_rule_lock;
43175eda8afdSAkeem G Abodunrin 	vlan_head = &sw->recp_list[ICE_SW_LKUP_VLAN].filt_rules;
43185eda8afdSAkeem G Abodunrin 	mutex_lock(vlan_lock);
43195eda8afdSAkeem G Abodunrin 	status = ice_add_to_vsi_fltr_list(hw, vsi_handle, vlan_head,
43205eda8afdSAkeem G Abodunrin 					  &vsi_list_head);
43215eda8afdSAkeem G Abodunrin 	mutex_unlock(vlan_lock);
43225eda8afdSAkeem G Abodunrin 	if (status)
43235eda8afdSAkeem G Abodunrin 		goto free_fltr_list;
43245eda8afdSAkeem G Abodunrin 
43255eda8afdSAkeem G Abodunrin 	list_for_each_entry(list_itr, &vsi_list_head, list_entry) {
4326ffa9ed86SGrzegorz Siwik 		/* Avoid enabling or disabling VLAN zero twice when in double
4327ffa9ed86SGrzegorz Siwik 		 * VLAN mode
4328ffa9ed86SGrzegorz Siwik 		 */
4329ffa9ed86SGrzegorz Siwik 		if (ice_is_dvm_ena(hw) &&
4330ffa9ed86SGrzegorz Siwik 		    list_itr->fltr_info.l_data.vlan.tpid == 0)
4331ffa9ed86SGrzegorz Siwik 			continue;
4332ffa9ed86SGrzegorz Siwik 
43335eda8afdSAkeem G Abodunrin 		vlan_id = list_itr->fltr_info.l_data.vlan.vlan_id;
43345eda8afdSAkeem G Abodunrin 		if (rm_vlan_promisc)
43355eda8afdSAkeem G Abodunrin 			status = ice_clear_vsi_promisc(hw, vsi_handle,
43365eda8afdSAkeem G Abodunrin 						       promisc_mask, vlan_id);
43375eda8afdSAkeem G Abodunrin 		else
43385eda8afdSAkeem G Abodunrin 			status = ice_set_vsi_promisc(hw, vsi_handle,
43395eda8afdSAkeem G Abodunrin 						     promisc_mask, vlan_id);
434011e551a2SGrzegorz Siwik 		if (status && status != -EEXIST)
43415eda8afdSAkeem G Abodunrin 			break;
43425eda8afdSAkeem G Abodunrin 	}
43435eda8afdSAkeem G Abodunrin 
43445eda8afdSAkeem G Abodunrin free_fltr_list:
43455eda8afdSAkeem G Abodunrin 	list_for_each_entry_safe(list_itr, tmp, &vsi_list_head, list_entry) {
43465eda8afdSAkeem G Abodunrin 		list_del(&list_itr->list_entry);
43475eda8afdSAkeem G Abodunrin 		devm_kfree(ice_hw_to_dev(hw), list_itr);
43485eda8afdSAkeem G Abodunrin 	}
43495eda8afdSAkeem G Abodunrin 	return status;
43505eda8afdSAkeem G Abodunrin }
43515eda8afdSAkeem G Abodunrin 
43525eda8afdSAkeem G Abodunrin /**
43539daf8208SAnirudh Venkataramanan  * ice_remove_vsi_lkup_fltr - Remove lookup type filters for a VSI
43549daf8208SAnirudh Venkataramanan  * @hw: pointer to the hardware structure
43555726ca0eSAnirudh Venkataramanan  * @vsi_handle: VSI handle to remove filters from
43569daf8208SAnirudh Venkataramanan  * @lkup: switch rule filter lookup type
43579daf8208SAnirudh Venkataramanan  */
43589daf8208SAnirudh Venkataramanan static void
43595726ca0eSAnirudh Venkataramanan ice_remove_vsi_lkup_fltr(struct ice_hw *hw, u16 vsi_handle,
43609daf8208SAnirudh Venkataramanan 			 enum ice_sw_lkup_type lkup)
43619daf8208SAnirudh Venkataramanan {
43629daf8208SAnirudh Venkataramanan 	struct ice_switch_info *sw = hw->switch_info;
43639daf8208SAnirudh Venkataramanan 	struct ice_fltr_list_entry *fm_entry;
43649daf8208SAnirudh Venkataramanan 	struct list_head remove_list_head;
436580d144c9SAnirudh Venkataramanan 	struct list_head *rule_head;
43669daf8208SAnirudh Venkataramanan 	struct ice_fltr_list_entry *tmp;
436780d144c9SAnirudh Venkataramanan 	struct mutex *rule_lock;	/* Lock to protect filter rule list */
43685e24d598STony Nguyen 	int status;
43699daf8208SAnirudh Venkataramanan 
43709daf8208SAnirudh Venkataramanan 	INIT_LIST_HEAD(&remove_list_head);
437180d144c9SAnirudh Venkataramanan 	rule_lock = &sw->recp_list[lkup].filt_rule_lock;
437280d144c9SAnirudh Venkataramanan 	rule_head = &sw->recp_list[lkup].filt_rules;
437380d144c9SAnirudh Venkataramanan 	mutex_lock(rule_lock);
43745726ca0eSAnirudh Venkataramanan 	status = ice_add_to_vsi_fltr_list(hw, vsi_handle, rule_head,
437580d144c9SAnirudh Venkataramanan 					  &remove_list_head);
437680d144c9SAnirudh Venkataramanan 	mutex_unlock(rule_lock);
437780d144c9SAnirudh Venkataramanan 	if (status)
4378b7eeb527SRobert Malz 		goto free_fltr_list;
437980d144c9SAnirudh Venkataramanan 
43809daf8208SAnirudh Venkataramanan 	switch (lkup) {
43819daf8208SAnirudh Venkataramanan 	case ICE_SW_LKUP_MAC:
43829daf8208SAnirudh Venkataramanan 		ice_remove_mac(hw, &remove_list_head);
43839daf8208SAnirudh Venkataramanan 		break;
43849daf8208SAnirudh Venkataramanan 	case ICE_SW_LKUP_VLAN:
4385d76a60baSAnirudh Venkataramanan 		ice_remove_vlan(hw, &remove_list_head);
4386d76a60baSAnirudh Venkataramanan 		break;
43875eda8afdSAkeem G Abodunrin 	case ICE_SW_LKUP_PROMISC:
43885eda8afdSAkeem G Abodunrin 	case ICE_SW_LKUP_PROMISC_VLAN:
43895eda8afdSAkeem G Abodunrin 		ice_remove_promisc(hw, lkup, &remove_list_head);
43905eda8afdSAkeem G Abodunrin 		break;
43919daf8208SAnirudh Venkataramanan 	case ICE_SW_LKUP_MAC_VLAN:
43929daf8208SAnirudh Venkataramanan 	case ICE_SW_LKUP_ETHERTYPE:
43939daf8208SAnirudh Venkataramanan 	case ICE_SW_LKUP_ETHERTYPE_MAC:
43949daf8208SAnirudh Venkataramanan 	case ICE_SW_LKUP_DFLT:
439580d144c9SAnirudh Venkataramanan 	case ICE_SW_LKUP_LAST:
439680d144c9SAnirudh Venkataramanan 	default:
439780d144c9SAnirudh Venkataramanan 		ice_debug(hw, ICE_DBG_SW, "Unsupported lookup type %d\n", lkup);
43989daf8208SAnirudh Venkataramanan 		break;
43999daf8208SAnirudh Venkataramanan 	}
44009daf8208SAnirudh Venkataramanan 
4401b7eeb527SRobert Malz free_fltr_list:
44029daf8208SAnirudh Venkataramanan 	list_for_each_entry_safe(fm_entry, tmp, &remove_list_head, list_entry) {
44039daf8208SAnirudh Venkataramanan 		list_del(&fm_entry->list_entry);
44049daf8208SAnirudh Venkataramanan 		devm_kfree(ice_hw_to_dev(hw), fm_entry);
44059daf8208SAnirudh Venkataramanan 	}
44069daf8208SAnirudh Venkataramanan }
44079daf8208SAnirudh Venkataramanan 
44089daf8208SAnirudh Venkataramanan /**
44099daf8208SAnirudh Venkataramanan  * ice_remove_vsi_fltr - Remove all filters for a VSI
44109daf8208SAnirudh Venkataramanan  * @hw: pointer to the hardware structure
44115726ca0eSAnirudh Venkataramanan  * @vsi_handle: VSI handle to remove filters from
44129daf8208SAnirudh Venkataramanan  */
44135726ca0eSAnirudh Venkataramanan void ice_remove_vsi_fltr(struct ice_hw *hw, u16 vsi_handle)
44149daf8208SAnirudh Venkataramanan {
44155726ca0eSAnirudh Venkataramanan 	ice_remove_vsi_lkup_fltr(hw, vsi_handle, ICE_SW_LKUP_MAC);
44165726ca0eSAnirudh Venkataramanan 	ice_remove_vsi_lkup_fltr(hw, vsi_handle, ICE_SW_LKUP_MAC_VLAN);
44175726ca0eSAnirudh Venkataramanan 	ice_remove_vsi_lkup_fltr(hw, vsi_handle, ICE_SW_LKUP_PROMISC);
44185726ca0eSAnirudh Venkataramanan 	ice_remove_vsi_lkup_fltr(hw, vsi_handle, ICE_SW_LKUP_VLAN);
44195726ca0eSAnirudh Venkataramanan 	ice_remove_vsi_lkup_fltr(hw, vsi_handle, ICE_SW_LKUP_DFLT);
44205726ca0eSAnirudh Venkataramanan 	ice_remove_vsi_lkup_fltr(hw, vsi_handle, ICE_SW_LKUP_ETHERTYPE);
44215726ca0eSAnirudh Venkataramanan 	ice_remove_vsi_lkup_fltr(hw, vsi_handle, ICE_SW_LKUP_ETHERTYPE_MAC);
44225726ca0eSAnirudh Venkataramanan 	ice_remove_vsi_lkup_fltr(hw, vsi_handle, ICE_SW_LKUP_PROMISC_VLAN);
44239daf8208SAnirudh Venkataramanan }
44240f9d5027SAnirudh Venkataramanan 
44250f9d5027SAnirudh Venkataramanan /**
4426148beb61SHenry Tieman  * ice_alloc_res_cntr - allocating resource counter
4427148beb61SHenry Tieman  * @hw: pointer to the hardware structure
4428148beb61SHenry Tieman  * @type: type of resource
4429148beb61SHenry Tieman  * @alloc_shared: if set it is shared else dedicated
4430148beb61SHenry Tieman  * @num_items: number of entries requested for FD resource type
4431148beb61SHenry Tieman  * @counter_id: counter index returned by AQ call
4432148beb61SHenry Tieman  */
44335e24d598STony Nguyen int
4434148beb61SHenry Tieman ice_alloc_res_cntr(struct ice_hw *hw, u8 type, u8 alloc_shared, u16 num_items,
4435148beb61SHenry Tieman 		   u16 *counter_id)
4436148beb61SHenry Tieman {
4437148beb61SHenry Tieman 	struct ice_aqc_alloc_free_res_elem *buf;
4438148beb61SHenry Tieman 	u16 buf_len;
44395518ac2aSTony Nguyen 	int status;
4440148beb61SHenry Tieman 
4441148beb61SHenry Tieman 	/* Allocate resource */
444266486d89SBruce Allan 	buf_len = struct_size(buf, elem, 1);
4443148beb61SHenry Tieman 	buf = kzalloc(buf_len, GFP_KERNEL);
4444148beb61SHenry Tieman 	if (!buf)
4445d54699e2STony Nguyen 		return -ENOMEM;
4446148beb61SHenry Tieman 
4447148beb61SHenry Tieman 	buf->num_elems = cpu_to_le16(num_items);
4448148beb61SHenry Tieman 	buf->res_type = cpu_to_le16(((type << ICE_AQC_RES_TYPE_S) &
4449148beb61SHenry Tieman 				      ICE_AQC_RES_TYPE_M) | alloc_shared);
4450148beb61SHenry Tieman 
4451*52da2fb2SPrzemek Kitszel 	status = ice_aq_alloc_free_res(hw, buf, buf_len, ice_aqc_opc_alloc_res);
4452148beb61SHenry Tieman 	if (status)
4453148beb61SHenry Tieman 		goto exit;
4454148beb61SHenry Tieman 
4455148beb61SHenry Tieman 	*counter_id = le16_to_cpu(buf->elem[0].e.sw_resp);
4456148beb61SHenry Tieman 
4457148beb61SHenry Tieman exit:
4458148beb61SHenry Tieman 	kfree(buf);
4459148beb61SHenry Tieman 	return status;
4460148beb61SHenry Tieman }
4461148beb61SHenry Tieman 
4462148beb61SHenry Tieman /**
4463148beb61SHenry Tieman  * ice_free_res_cntr - free resource counter
4464148beb61SHenry Tieman  * @hw: pointer to the hardware structure
4465148beb61SHenry Tieman  * @type: type of resource
4466148beb61SHenry Tieman  * @alloc_shared: if set it is shared else dedicated
4467148beb61SHenry Tieman  * @num_items: number of entries to be freed for FD resource type
4468148beb61SHenry Tieman  * @counter_id: counter ID resource which needs to be freed
4469148beb61SHenry Tieman  */
44705e24d598STony Nguyen int
4471148beb61SHenry Tieman ice_free_res_cntr(struct ice_hw *hw, u8 type, u8 alloc_shared, u16 num_items,
4472148beb61SHenry Tieman 		  u16 counter_id)
4473148beb61SHenry Tieman {
4474148beb61SHenry Tieman 	struct ice_aqc_alloc_free_res_elem *buf;
4475148beb61SHenry Tieman 	u16 buf_len;
44765518ac2aSTony Nguyen 	int status;
4477148beb61SHenry Tieman 
4478148beb61SHenry Tieman 	/* Free resource */
447966486d89SBruce Allan 	buf_len = struct_size(buf, elem, 1);
4480148beb61SHenry Tieman 	buf = kzalloc(buf_len, GFP_KERNEL);
4481148beb61SHenry Tieman 	if (!buf)
4482d54699e2STony Nguyen 		return -ENOMEM;
4483148beb61SHenry Tieman 
4484148beb61SHenry Tieman 	buf->num_elems = cpu_to_le16(num_items);
4485148beb61SHenry Tieman 	buf->res_type = cpu_to_le16(((type << ICE_AQC_RES_TYPE_S) &
4486148beb61SHenry Tieman 				      ICE_AQC_RES_TYPE_M) | alloc_shared);
4487148beb61SHenry Tieman 	buf->elem[0].e.sw_resp = cpu_to_le16(counter_id);
4488148beb61SHenry Tieman 
4489*52da2fb2SPrzemek Kitszel 	status = ice_aq_alloc_free_res(hw, buf, buf_len, ice_aqc_opc_free_res);
4490148beb61SHenry Tieman 	if (status)
44919228d8b2SJacob Keller 		ice_debug(hw, ICE_DBG_SW, "counter resource could not be freed\n");
4492148beb61SHenry Tieman 
4493148beb61SHenry Tieman 	kfree(buf);
4494148beb61SHenry Tieman 	return status;
4495148beb61SHenry Tieman }
4496148beb61SHenry Tieman 
449717c6d835SMichal Swiatkowski #define ICE_PROTOCOL_ENTRY(id, ...) {		\
449817c6d835SMichal Swiatkowski 	.prot_type	= id,			\
449917c6d835SMichal Swiatkowski 	.offs		= {__VA_ARGS__},	\
450017c6d835SMichal Swiatkowski }
450117c6d835SMichal Swiatkowski 
450223ccae5cSDave Ertman /**
450323ccae5cSDave Ertman  * ice_share_res - set a resource as shared or dedicated
450423ccae5cSDave Ertman  * @hw: hw struct of original owner of resource
450523ccae5cSDave Ertman  * @type: resource type
450623ccae5cSDave Ertman  * @shared: is the resource being set to shared
450723ccae5cSDave Ertman  * @res_id: resource id (descriptor)
450823ccae5cSDave Ertman  */
450923ccae5cSDave Ertman int ice_share_res(struct ice_hw *hw, u16 type, u8 shared, u16 res_id)
451023ccae5cSDave Ertman {
451123ccae5cSDave Ertman 	struct ice_aqc_alloc_free_res_elem *buf;
451223ccae5cSDave Ertman 	u16 buf_len;
451323ccae5cSDave Ertman 	int status;
451423ccae5cSDave Ertman 
451523ccae5cSDave Ertman 	buf_len = struct_size(buf, elem, 1);
451623ccae5cSDave Ertman 	buf = kzalloc(buf_len, GFP_KERNEL);
451723ccae5cSDave Ertman 	if (!buf)
451823ccae5cSDave Ertman 		return -ENOMEM;
451923ccae5cSDave Ertman 
452023ccae5cSDave Ertman 	buf->num_elems = cpu_to_le16(1);
452123ccae5cSDave Ertman 	if (shared)
452223ccae5cSDave Ertman 		buf->res_type = cpu_to_le16(((type << ICE_AQC_RES_TYPE_S) &
452323ccae5cSDave Ertman 					     ICE_AQC_RES_TYPE_M) |
452423ccae5cSDave Ertman 					    ICE_AQC_RES_TYPE_FLAG_SHARED);
452523ccae5cSDave Ertman 	else
452623ccae5cSDave Ertman 		buf->res_type = cpu_to_le16(((type << ICE_AQC_RES_TYPE_S) &
452723ccae5cSDave Ertman 					     ICE_AQC_RES_TYPE_M) &
452823ccae5cSDave Ertman 					    ~ICE_AQC_RES_TYPE_FLAG_SHARED);
452923ccae5cSDave Ertman 
453023ccae5cSDave Ertman 	buf->elem[0].e.sw_resp = cpu_to_le16(res_id);
4531*52da2fb2SPrzemek Kitszel 	status = ice_aq_alloc_free_res(hw, buf, buf_len,
4532*52da2fb2SPrzemek Kitszel 				       ice_aqc_opc_share_res);
453323ccae5cSDave Ertman 	if (status)
453423ccae5cSDave Ertman 		ice_debug(hw, ICE_DBG_SW, "Could not set resource type %u id %u to %s\n",
453523ccae5cSDave Ertman 			  type, res_id, shared ? "SHARED" : "DEDICATED");
453623ccae5cSDave Ertman 
453723ccae5cSDave Ertman 	kfree(buf);
453823ccae5cSDave Ertman 	return status;
453923ccae5cSDave Ertman }
454023ccae5cSDave Ertman 
4541fd2a6b71SDan Nowlin /* This is mapping table entry that maps every word within a given protocol
4542fd2a6b71SDan Nowlin  * structure to the real byte offset as per the specification of that
4543fd2a6b71SDan Nowlin  * protocol header.
4544fd2a6b71SDan Nowlin  * for example dst address is 3 words in ethertype header and corresponding
4545fd2a6b71SDan Nowlin  * bytes are 0, 2, 3 in the actual packet header and src address is at 4, 6, 8
4546fd2a6b71SDan Nowlin  * IMPORTANT: Every structure part of "ice_prot_hdr" union should have a
4547fd2a6b71SDan Nowlin  * matching entry describing its field. This needs to be updated if new
4548fd2a6b71SDan Nowlin  * structure is added to that union.
4549fd2a6b71SDan Nowlin  */
4550fd2a6b71SDan Nowlin static const struct ice_prot_ext_tbl_entry ice_prot_ext[ICE_PROTOCOL_LAST] = {
455117c6d835SMichal Swiatkowski 	ICE_PROTOCOL_ENTRY(ICE_MAC_OFOS, 0, 2, 4, 6, 8, 10, 12),
455217c6d835SMichal Swiatkowski 	ICE_PROTOCOL_ENTRY(ICE_MAC_IL, 0, 2, 4, 6, 8, 10, 12),
455317c6d835SMichal Swiatkowski 	ICE_PROTOCOL_ENTRY(ICE_ETYPE_OL, 0),
455417c6d835SMichal Swiatkowski 	ICE_PROTOCOL_ENTRY(ICE_ETYPE_IL, 0),
455517c6d835SMichal Swiatkowski 	ICE_PROTOCOL_ENTRY(ICE_VLAN_OFOS, 2, 0),
455617c6d835SMichal Swiatkowski 	ICE_PROTOCOL_ENTRY(ICE_IPV4_OFOS, 0, 2, 4, 6, 8, 10, 12, 14, 16, 18),
455717c6d835SMichal Swiatkowski 	ICE_PROTOCOL_ENTRY(ICE_IPV4_IL,	0, 2, 4, 6, 8, 10, 12, 14, 16, 18),
455817c6d835SMichal Swiatkowski 	ICE_PROTOCOL_ENTRY(ICE_IPV6_OFOS, 0, 2, 4, 6, 8, 10, 12, 14, 16, 18,
455917c6d835SMichal Swiatkowski 			   20, 22, 24, 26, 28, 30, 32, 34, 36, 38),
456017c6d835SMichal Swiatkowski 	ICE_PROTOCOL_ENTRY(ICE_IPV6_IL, 0, 2, 4, 6, 8, 10, 12, 14, 16, 18, 20,
456117c6d835SMichal Swiatkowski 			   22, 24, 26, 28, 30, 32, 34, 36, 38),
456217c6d835SMichal Swiatkowski 	ICE_PROTOCOL_ENTRY(ICE_TCP_IL, 0, 2),
456317c6d835SMichal Swiatkowski 	ICE_PROTOCOL_ENTRY(ICE_UDP_OF, 0, 2),
456417c6d835SMichal Swiatkowski 	ICE_PROTOCOL_ENTRY(ICE_UDP_ILOS, 0, 2),
456517c6d835SMichal Swiatkowski 	ICE_PROTOCOL_ENTRY(ICE_VXLAN, 8, 10, 12, 14),
456617c6d835SMichal Swiatkowski 	ICE_PROTOCOL_ENTRY(ICE_GENEVE, 8, 10, 12, 14),
456717c6d835SMichal Swiatkowski 	ICE_PROTOCOL_ENTRY(ICE_NVGRE, 0, 2, 4, 6),
456817c6d835SMichal Swiatkowski 	ICE_PROTOCOL_ENTRY(ICE_GTP, 8, 10, 12, 14, 16, 18, 20, 22),
456917c6d835SMichal Swiatkowski 	ICE_PROTOCOL_ENTRY(ICE_GTP_NO_PAY, 8, 10, 12, 14),
457017c6d835SMichal Swiatkowski 	ICE_PROTOCOL_ENTRY(ICE_PPPOE, 0, 2, 4, 6),
457117c6d835SMichal Swiatkowski 	ICE_PROTOCOL_ENTRY(ICE_L2TPV3, 0, 2, 4, 6, 8, 10),
457217c6d835SMichal Swiatkowski 	ICE_PROTOCOL_ENTRY(ICE_VLAN_EX, 2, 0),
457317c6d835SMichal Swiatkowski 	ICE_PROTOCOL_ENTRY(ICE_VLAN_IN, 2, 0),
457403592a14SMichal Swiatkowski 	ICE_PROTOCOL_ENTRY(ICE_HW_METADATA,
457503592a14SMichal Swiatkowski 			   ICE_SOURCE_PORT_MDID_OFFSET,
457603592a14SMichal Swiatkowski 			   ICE_PTYPE_MDID_OFFSET,
457703592a14SMichal Swiatkowski 			   ICE_PACKET_LENGTH_MDID_OFFSET,
457803592a14SMichal Swiatkowski 			   ICE_SOURCE_VSI_MDID_OFFSET,
457903592a14SMichal Swiatkowski 			   ICE_PKT_VLAN_MDID_OFFSET,
458003592a14SMichal Swiatkowski 			   ICE_PKT_TUNNEL_MDID_OFFSET,
458103592a14SMichal Swiatkowski 			   ICE_PKT_TCP_MDID_OFFSET,
458203592a14SMichal Swiatkowski 			   ICE_PKT_ERROR_MDID_OFFSET),
4583fd2a6b71SDan Nowlin };
4584fd2a6b71SDan Nowlin 
4585fd2a6b71SDan Nowlin static struct ice_protocol_entry ice_prot_id_tbl[ICE_PROTOCOL_LAST] = {
4586fd2a6b71SDan Nowlin 	{ ICE_MAC_OFOS,		ICE_MAC_OFOS_HW },
4587fd2a6b71SDan Nowlin 	{ ICE_MAC_IL,		ICE_MAC_IL_HW },
4588fd2a6b71SDan Nowlin 	{ ICE_ETYPE_OL,		ICE_ETYPE_OL_HW },
458934a89775SMartyna Szapar-Mudlaw 	{ ICE_ETYPE_IL,		ICE_ETYPE_IL_HW },
4590fd2a6b71SDan Nowlin 	{ ICE_VLAN_OFOS,	ICE_VLAN_OL_HW },
4591fd2a6b71SDan Nowlin 	{ ICE_IPV4_OFOS,	ICE_IPV4_OFOS_HW },
4592fd2a6b71SDan Nowlin 	{ ICE_IPV4_IL,		ICE_IPV4_IL_HW },
4593fd2a6b71SDan Nowlin 	{ ICE_IPV6_OFOS,	ICE_IPV6_OFOS_HW },
4594fd2a6b71SDan Nowlin 	{ ICE_IPV6_IL,		ICE_IPV6_IL_HW },
4595fd2a6b71SDan Nowlin 	{ ICE_TCP_IL,		ICE_TCP_IL_HW },
4596fd2a6b71SDan Nowlin 	{ ICE_UDP_OF,		ICE_UDP_OF_HW },
4597fd2a6b71SDan Nowlin 	{ ICE_UDP_ILOS,		ICE_UDP_ILOS_HW },
45988b032a55SMichal Swiatkowski 	{ ICE_VXLAN,		ICE_UDP_OF_HW },
45998b032a55SMichal Swiatkowski 	{ ICE_GENEVE,		ICE_UDP_OF_HW },
4600f0a35040SMichal Swiatkowski 	{ ICE_NVGRE,		ICE_GRE_OF_HW },
46019a225f81SMarcin Szycik 	{ ICE_GTP,		ICE_UDP_OF_HW },
46029a225f81SMarcin Szycik 	{ ICE_GTP_NO_PAY,	ICE_UDP_ILOS_HW },
4603cd8efeeeSMarcin Szycik 	{ ICE_PPPOE,		ICE_PPPOE_HW },
4604cd634549SMarcin Szycik 	{ ICE_L2TPV3,		ICE_L2TPV3_HW },
460506bca7c2SMartyna Szapar-Mudlaw 	{ ICE_VLAN_EX,          ICE_VLAN_OF_HW },
460606bca7c2SMartyna Szapar-Mudlaw 	{ ICE_VLAN_IN,          ICE_VLAN_OL_HW },
460703592a14SMichal Swiatkowski 	{ ICE_HW_METADATA,      ICE_META_DATA_ID_HW },
4608fd2a6b71SDan Nowlin };
4609fd2a6b71SDan Nowlin 
4610fd2a6b71SDan Nowlin /**
4611fd2a6b71SDan Nowlin  * ice_find_recp - find a recipe
4612fd2a6b71SDan Nowlin  * @hw: pointer to the hardware structure
4613fd2a6b71SDan Nowlin  * @lkup_exts: extension sequence to match
4614bccd9bceSMarcin Szycik  * @rinfo: information regarding the rule e.g. priority and action info
4615fd2a6b71SDan Nowlin  *
4616fd2a6b71SDan Nowlin  * Returns index of matching recipe, or ICE_MAX_NUM_RECIPES if not found.
4617fd2a6b71SDan Nowlin  */
4618de6acd1cSMichal Swiatkowski static u16
4619de6acd1cSMichal Swiatkowski ice_find_recp(struct ice_hw *hw, struct ice_prot_lkup_ext *lkup_exts,
4620bccd9bceSMarcin Szycik 	      const struct ice_adv_rule_info *rinfo)
4621fd2a6b71SDan Nowlin {
4622fd2a6b71SDan Nowlin 	bool refresh_required = true;
4623fd2a6b71SDan Nowlin 	struct ice_sw_recipe *recp;
4624fd2a6b71SDan Nowlin 	u8 i;
4625fd2a6b71SDan Nowlin 
4626fd2a6b71SDan Nowlin 	/* Walk through existing recipes to find a match */
4627fd2a6b71SDan Nowlin 	recp = hw->switch_info->recp_list;
4628fd2a6b71SDan Nowlin 	for (i = 0; i < ICE_MAX_NUM_RECIPES; i++) {
4629fd2a6b71SDan Nowlin 		/* If recipe was not created for this ID, in SW bookkeeping,
4630fd2a6b71SDan Nowlin 		 * check if FW has an entry for this recipe. If the FW has an
4631fd2a6b71SDan Nowlin 		 * entry update it in our SW bookkeeping and continue with the
4632fd2a6b71SDan Nowlin 		 * matching.
4633fd2a6b71SDan Nowlin 		 */
4634fd2a6b71SDan Nowlin 		if (!recp[i].recp_created)
4635fd2a6b71SDan Nowlin 			if (ice_get_recp_frm_fw(hw,
4636fd2a6b71SDan Nowlin 						hw->switch_info->recp_list, i,
4637fd2a6b71SDan Nowlin 						&refresh_required))
4638fd2a6b71SDan Nowlin 				continue;
4639fd2a6b71SDan Nowlin 
4640fd2a6b71SDan Nowlin 		/* Skip inverse action recipes */
4641fd2a6b71SDan Nowlin 		if (recp[i].root_buf && recp[i].root_buf->content.act_ctrl &
4642fd2a6b71SDan Nowlin 		    ICE_AQ_RECIPE_ACT_INV_ACT)
4643fd2a6b71SDan Nowlin 			continue;
4644fd2a6b71SDan Nowlin 
4645fd2a6b71SDan Nowlin 		/* if number of words we are looking for match */
4646fd2a6b71SDan Nowlin 		if (lkup_exts->n_val_words == recp[i].lkup_exts.n_val_words) {
4647fd2a6b71SDan Nowlin 			struct ice_fv_word *ar = recp[i].lkup_exts.fv_words;
4648fd2a6b71SDan Nowlin 			struct ice_fv_word *be = lkup_exts->fv_words;
4649fd2a6b71SDan Nowlin 			u16 *cr = recp[i].lkup_exts.field_mask;
4650fd2a6b71SDan Nowlin 			u16 *de = lkup_exts->field_mask;
4651fd2a6b71SDan Nowlin 			bool found = true;
4652fd2a6b71SDan Nowlin 			u8 pe, qr;
4653fd2a6b71SDan Nowlin 
4654fd2a6b71SDan Nowlin 			/* ar, cr, and qr are related to the recipe words, while
4655fd2a6b71SDan Nowlin 			 * be, de, and pe are related to the lookup words
4656fd2a6b71SDan Nowlin 			 */
4657fd2a6b71SDan Nowlin 			for (pe = 0; pe < lkup_exts->n_val_words; pe++) {
4658fd2a6b71SDan Nowlin 				for (qr = 0; qr < recp[i].lkup_exts.n_val_words;
4659fd2a6b71SDan Nowlin 				     qr++) {
4660fd2a6b71SDan Nowlin 					if (ar[qr].off == be[pe].off &&
4661fd2a6b71SDan Nowlin 					    ar[qr].prot_id == be[pe].prot_id &&
4662fd2a6b71SDan Nowlin 					    cr[qr] == de[pe])
4663fd2a6b71SDan Nowlin 						/* Found the "pe"th word in the
4664fd2a6b71SDan Nowlin 						 * given recipe
4665fd2a6b71SDan Nowlin 						 */
4666fd2a6b71SDan Nowlin 						break;
4667fd2a6b71SDan Nowlin 				}
4668fd2a6b71SDan Nowlin 				/* After walking through all the words in the
4669fd2a6b71SDan Nowlin 				 * "i"th recipe if "p"th word was not found then
4670fd2a6b71SDan Nowlin 				 * this recipe is not what we are looking for.
4671fd2a6b71SDan Nowlin 				 * So break out from this loop and try the next
4672fd2a6b71SDan Nowlin 				 * recipe
4673fd2a6b71SDan Nowlin 				 */
4674fd2a6b71SDan Nowlin 				if (qr >= recp[i].lkup_exts.n_val_words) {
4675fd2a6b71SDan Nowlin 					found = false;
4676fd2a6b71SDan Nowlin 					break;
4677fd2a6b71SDan Nowlin 				}
4678fd2a6b71SDan Nowlin 			}
4679fd2a6b71SDan Nowlin 			/* If for "i"th recipe the found was never set to false
4680fd2a6b71SDan Nowlin 			 * then it means we found our match
4681bccd9bceSMarcin Szycik 			 * Also tun type and *_pass_l2 of recipe needs to be
4682bccd9bceSMarcin Szycik 			 * checked
4683fd2a6b71SDan Nowlin 			 */
4684bccd9bceSMarcin Szycik 			if (found && recp[i].tun_type == rinfo->tun_type &&
4685bccd9bceSMarcin Szycik 			    recp[i].need_pass_l2 == rinfo->need_pass_l2 &&
4686bccd9bceSMarcin Szycik 			    recp[i].allow_pass_l2 == rinfo->allow_pass_l2)
4687fd2a6b71SDan Nowlin 				return i; /* Return the recipe ID */
4688fd2a6b71SDan Nowlin 		}
4689fd2a6b71SDan Nowlin 	}
4690fd2a6b71SDan Nowlin 	return ICE_MAX_NUM_RECIPES;
4691fd2a6b71SDan Nowlin }
4692fd2a6b71SDan Nowlin 
4693fd2a6b71SDan Nowlin /**
4694a1ffafb0SBrett Creeley  * ice_change_proto_id_to_dvm - change proto id in prot_id_tbl
4695a1ffafb0SBrett Creeley  *
4696a1ffafb0SBrett Creeley  * As protocol id for outer vlan is different in dvm and svm, if dvm is
4697a1ffafb0SBrett Creeley  * supported protocol array record for outer vlan has to be modified to
4698a1ffafb0SBrett Creeley  * reflect the value proper for DVM.
4699a1ffafb0SBrett Creeley  */
4700a1ffafb0SBrett Creeley void ice_change_proto_id_to_dvm(void)
4701a1ffafb0SBrett Creeley {
4702a1ffafb0SBrett Creeley 	u8 i;
4703a1ffafb0SBrett Creeley 
4704a1ffafb0SBrett Creeley 	for (i = 0; i < ARRAY_SIZE(ice_prot_id_tbl); i++)
4705a1ffafb0SBrett Creeley 		if (ice_prot_id_tbl[i].type == ICE_VLAN_OFOS &&
4706a1ffafb0SBrett Creeley 		    ice_prot_id_tbl[i].protocol_id != ICE_VLAN_OF_HW)
4707a1ffafb0SBrett Creeley 			ice_prot_id_tbl[i].protocol_id = ICE_VLAN_OF_HW;
4708a1ffafb0SBrett Creeley }
4709a1ffafb0SBrett Creeley 
4710a1ffafb0SBrett Creeley /**
4711fd2a6b71SDan Nowlin  * ice_prot_type_to_id - get protocol ID from protocol type
4712fd2a6b71SDan Nowlin  * @type: protocol type
4713fd2a6b71SDan Nowlin  * @id: pointer to variable that will receive the ID
4714fd2a6b71SDan Nowlin  *
4715fd2a6b71SDan Nowlin  * Returns true if found, false otherwise
4716fd2a6b71SDan Nowlin  */
4717fd2a6b71SDan Nowlin static bool ice_prot_type_to_id(enum ice_protocol_type type, u8 *id)
4718fd2a6b71SDan Nowlin {
4719fd2a6b71SDan Nowlin 	u8 i;
4720fd2a6b71SDan Nowlin 
4721fd2a6b71SDan Nowlin 	for (i = 0; i < ARRAY_SIZE(ice_prot_id_tbl); i++)
4722fd2a6b71SDan Nowlin 		if (ice_prot_id_tbl[i].type == type) {
4723fd2a6b71SDan Nowlin 			*id = ice_prot_id_tbl[i].protocol_id;
4724fd2a6b71SDan Nowlin 			return true;
4725fd2a6b71SDan Nowlin 		}
4726fd2a6b71SDan Nowlin 	return false;
4727fd2a6b71SDan Nowlin }
4728fd2a6b71SDan Nowlin 
4729fd2a6b71SDan Nowlin /**
4730fd2a6b71SDan Nowlin  * ice_fill_valid_words - count valid words
4731fd2a6b71SDan Nowlin  * @rule: advanced rule with lookup information
4732fd2a6b71SDan Nowlin  * @lkup_exts: byte offset extractions of the words that are valid
4733fd2a6b71SDan Nowlin  *
4734fd2a6b71SDan Nowlin  * calculate valid words in a lookup rule using mask value
4735fd2a6b71SDan Nowlin  */
4736fd2a6b71SDan Nowlin static u8
4737fd2a6b71SDan Nowlin ice_fill_valid_words(struct ice_adv_lkup_elem *rule,
4738fd2a6b71SDan Nowlin 		     struct ice_prot_lkup_ext *lkup_exts)
4739fd2a6b71SDan Nowlin {
4740fd2a6b71SDan Nowlin 	u8 j, word, prot_id, ret_val;
4741fd2a6b71SDan Nowlin 
4742fd2a6b71SDan Nowlin 	if (!ice_prot_type_to_id(rule->type, &prot_id))
4743fd2a6b71SDan Nowlin 		return 0;
4744fd2a6b71SDan Nowlin 
4745fd2a6b71SDan Nowlin 	word = lkup_exts->n_val_words;
4746fd2a6b71SDan Nowlin 
4747fd2a6b71SDan Nowlin 	for (j = 0; j < sizeof(rule->m_u) / sizeof(u16); j++)
4748fd2a6b71SDan Nowlin 		if (((u16 *)&rule->m_u)[j] &&
4749fd2a6b71SDan Nowlin 		    rule->type < ARRAY_SIZE(ice_prot_ext)) {
4750fd2a6b71SDan Nowlin 			/* No more space to accommodate */
4751fd2a6b71SDan Nowlin 			if (word >= ICE_MAX_CHAIN_WORDS)
4752fd2a6b71SDan Nowlin 				return 0;
4753fd2a6b71SDan Nowlin 			lkup_exts->fv_words[word].off =
4754fd2a6b71SDan Nowlin 				ice_prot_ext[rule->type].offs[j];
4755fd2a6b71SDan Nowlin 			lkup_exts->fv_words[word].prot_id =
4756fd2a6b71SDan Nowlin 				ice_prot_id_tbl[rule->type].protocol_id;
4757fd2a6b71SDan Nowlin 			lkup_exts->field_mask[word] =
4758fd2a6b71SDan Nowlin 				be16_to_cpu(((__force __be16 *)&rule->m_u)[j]);
4759fd2a6b71SDan Nowlin 			word++;
4760fd2a6b71SDan Nowlin 		}
4761fd2a6b71SDan Nowlin 
4762fd2a6b71SDan Nowlin 	ret_val = word - lkup_exts->n_val_words;
4763fd2a6b71SDan Nowlin 	lkup_exts->n_val_words = word;
4764fd2a6b71SDan Nowlin 
4765fd2a6b71SDan Nowlin 	return ret_val;
4766fd2a6b71SDan Nowlin }
4767fd2a6b71SDan Nowlin 
4768fd2a6b71SDan Nowlin /**
4769fd2a6b71SDan Nowlin  * ice_create_first_fit_recp_def - Create a recipe grouping
4770fd2a6b71SDan Nowlin  * @hw: pointer to the hardware structure
4771fd2a6b71SDan Nowlin  * @lkup_exts: an array of protocol header extractions
4772fd2a6b71SDan Nowlin  * @rg_list: pointer to a list that stores new recipe groups
4773fd2a6b71SDan Nowlin  * @recp_cnt: pointer to a variable that stores returned number of recipe groups
4774fd2a6b71SDan Nowlin  *
4775fd2a6b71SDan Nowlin  * Using first fit algorithm, take all the words that are still not done
4776fd2a6b71SDan Nowlin  * and start grouping them in 4-word groups. Each group makes up one
4777fd2a6b71SDan Nowlin  * recipe.
4778fd2a6b71SDan Nowlin  */
47795e24d598STony Nguyen static int
4780fd2a6b71SDan Nowlin ice_create_first_fit_recp_def(struct ice_hw *hw,
4781fd2a6b71SDan Nowlin 			      struct ice_prot_lkup_ext *lkup_exts,
4782fd2a6b71SDan Nowlin 			      struct list_head *rg_list,
4783fd2a6b71SDan Nowlin 			      u8 *recp_cnt)
4784fd2a6b71SDan Nowlin {
4785fd2a6b71SDan Nowlin 	struct ice_pref_recipe_group *grp = NULL;
4786fd2a6b71SDan Nowlin 	u8 j;
4787fd2a6b71SDan Nowlin 
4788fd2a6b71SDan Nowlin 	*recp_cnt = 0;
4789fd2a6b71SDan Nowlin 
4790fd2a6b71SDan Nowlin 	/* Walk through every word in the rule to check if it is not done. If so
4791fd2a6b71SDan Nowlin 	 * then this word needs to be part of a new recipe.
4792fd2a6b71SDan Nowlin 	 */
4793fd2a6b71SDan Nowlin 	for (j = 0; j < lkup_exts->n_val_words; j++)
4794fd2a6b71SDan Nowlin 		if (!test_bit(j, lkup_exts->done)) {
4795fd2a6b71SDan Nowlin 			if (!grp ||
4796fd2a6b71SDan Nowlin 			    grp->n_val_pairs == ICE_NUM_WORDS_RECIPE) {
4797fd2a6b71SDan Nowlin 				struct ice_recp_grp_entry *entry;
4798fd2a6b71SDan Nowlin 
4799fd2a6b71SDan Nowlin 				entry = devm_kzalloc(ice_hw_to_dev(hw),
4800fd2a6b71SDan Nowlin 						     sizeof(*entry),
4801fd2a6b71SDan Nowlin 						     GFP_KERNEL);
4802fd2a6b71SDan Nowlin 				if (!entry)
4803d54699e2STony Nguyen 					return -ENOMEM;
4804fd2a6b71SDan Nowlin 				list_add(&entry->l_entry, rg_list);
4805fd2a6b71SDan Nowlin 				grp = &entry->r_group;
4806fd2a6b71SDan Nowlin 				(*recp_cnt)++;
4807fd2a6b71SDan Nowlin 			}
4808fd2a6b71SDan Nowlin 
4809fd2a6b71SDan Nowlin 			grp->pairs[grp->n_val_pairs].prot_id =
4810fd2a6b71SDan Nowlin 				lkup_exts->fv_words[j].prot_id;
4811fd2a6b71SDan Nowlin 			grp->pairs[grp->n_val_pairs].off =
4812fd2a6b71SDan Nowlin 				lkup_exts->fv_words[j].off;
4813fd2a6b71SDan Nowlin 			grp->mask[grp->n_val_pairs] = lkup_exts->field_mask[j];
4814fd2a6b71SDan Nowlin 			grp->n_val_pairs++;
4815fd2a6b71SDan Nowlin 		}
4816fd2a6b71SDan Nowlin 
4817fd2a6b71SDan Nowlin 	return 0;
4818fd2a6b71SDan Nowlin }
4819fd2a6b71SDan Nowlin 
4820fd2a6b71SDan Nowlin /**
4821fd2a6b71SDan Nowlin  * ice_fill_fv_word_index - fill in the field vector indices for a recipe group
4822fd2a6b71SDan Nowlin  * @hw: pointer to the hardware structure
4823fd2a6b71SDan Nowlin  * @fv_list: field vector with the extraction sequence information
4824fd2a6b71SDan Nowlin  * @rg_list: recipe groupings with protocol-offset pairs
4825fd2a6b71SDan Nowlin  *
4826fd2a6b71SDan Nowlin  * Helper function to fill in the field vector indices for protocol-offset
4827fd2a6b71SDan Nowlin  * pairs. These indexes are then ultimately programmed into a recipe.
4828fd2a6b71SDan Nowlin  */
48295e24d598STony Nguyen static int
4830fd2a6b71SDan Nowlin ice_fill_fv_word_index(struct ice_hw *hw, struct list_head *fv_list,
4831fd2a6b71SDan Nowlin 		       struct list_head *rg_list)
4832fd2a6b71SDan Nowlin {
4833fd2a6b71SDan Nowlin 	struct ice_sw_fv_list_entry *fv;
4834fd2a6b71SDan Nowlin 	struct ice_recp_grp_entry *rg;
4835fd2a6b71SDan Nowlin 	struct ice_fv_word *fv_ext;
4836fd2a6b71SDan Nowlin 
4837fd2a6b71SDan Nowlin 	if (list_empty(fv_list))
4838fd2a6b71SDan Nowlin 		return 0;
4839fd2a6b71SDan Nowlin 
4840fd2a6b71SDan Nowlin 	fv = list_first_entry(fv_list, struct ice_sw_fv_list_entry,
4841fd2a6b71SDan Nowlin 			      list_entry);
4842fd2a6b71SDan Nowlin 	fv_ext = fv->fv_ptr->ew;
4843fd2a6b71SDan Nowlin 
4844fd2a6b71SDan Nowlin 	list_for_each_entry(rg, rg_list, l_entry) {
4845fd2a6b71SDan Nowlin 		u8 i;
4846fd2a6b71SDan Nowlin 
4847fd2a6b71SDan Nowlin 		for (i = 0; i < rg->r_group.n_val_pairs; i++) {
4848fd2a6b71SDan Nowlin 			struct ice_fv_word *pr;
4849fd2a6b71SDan Nowlin 			bool found = false;
4850fd2a6b71SDan Nowlin 			u16 mask;
4851fd2a6b71SDan Nowlin 			u8 j;
4852fd2a6b71SDan Nowlin 
4853fd2a6b71SDan Nowlin 			pr = &rg->r_group.pairs[i];
4854fd2a6b71SDan Nowlin 			mask = rg->r_group.mask[i];
4855fd2a6b71SDan Nowlin 
4856fd2a6b71SDan Nowlin 			for (j = 0; j < hw->blk[ICE_BLK_SW].es.fvw; j++)
4857fd2a6b71SDan Nowlin 				if (fv_ext[j].prot_id == pr->prot_id &&
4858fd2a6b71SDan Nowlin 				    fv_ext[j].off == pr->off) {
4859fd2a6b71SDan Nowlin 					found = true;
4860fd2a6b71SDan Nowlin 
4861fd2a6b71SDan Nowlin 					/* Store index of field vector */
4862fd2a6b71SDan Nowlin 					rg->fv_idx[i] = j;
4863fd2a6b71SDan Nowlin 					rg->fv_mask[i] = mask;
4864fd2a6b71SDan Nowlin 					break;
4865fd2a6b71SDan Nowlin 				}
4866fd2a6b71SDan Nowlin 
4867fd2a6b71SDan Nowlin 			/* Protocol/offset could not be found, caller gave an
4868fd2a6b71SDan Nowlin 			 * invalid pair
4869fd2a6b71SDan Nowlin 			 */
4870fd2a6b71SDan Nowlin 			if (!found)
4871d54699e2STony Nguyen 				return -EINVAL;
4872fd2a6b71SDan Nowlin 		}
4873fd2a6b71SDan Nowlin 	}
4874fd2a6b71SDan Nowlin 
4875fd2a6b71SDan Nowlin 	return 0;
4876fd2a6b71SDan Nowlin }
4877fd2a6b71SDan Nowlin 
4878fd2a6b71SDan Nowlin /**
4879fd2a6b71SDan Nowlin  * ice_find_free_recp_res_idx - find free result indexes for recipe
4880fd2a6b71SDan Nowlin  * @hw: pointer to hardware structure
4881fd2a6b71SDan Nowlin  * @profiles: bitmap of profiles that will be associated with the new recipe
4882fd2a6b71SDan Nowlin  * @free_idx: pointer to variable to receive the free index bitmap
4883fd2a6b71SDan Nowlin  *
4884fd2a6b71SDan Nowlin  * The algorithm used here is:
4885fd2a6b71SDan Nowlin  *	1. When creating a new recipe, create a set P which contains all
4886fd2a6b71SDan Nowlin  *	   Profiles that will be associated with our new recipe
4887fd2a6b71SDan Nowlin  *
4888fd2a6b71SDan Nowlin  *	2. For each Profile p in set P:
4889fd2a6b71SDan Nowlin  *	    a. Add all recipes associated with Profile p into set R
4890fd2a6b71SDan Nowlin  *	    b. Optional : PossibleIndexes &= profile[p].possibleIndexes
4891fd2a6b71SDan Nowlin  *		[initially PossibleIndexes should be 0xFFFFFFFFFFFFFFFF]
4892fd2a6b71SDan Nowlin  *		i. Or just assume they all have the same possible indexes:
4893fd2a6b71SDan Nowlin  *			44, 45, 46, 47
4894fd2a6b71SDan Nowlin  *			i.e., PossibleIndexes = 0x0000F00000000000
4895fd2a6b71SDan Nowlin  *
4896fd2a6b71SDan Nowlin  *	3. For each Recipe r in set R:
4897fd2a6b71SDan Nowlin  *	    a. UsedIndexes |= (bitwise or ) recipe[r].res_indexes
4898fd2a6b71SDan Nowlin  *	    b. FreeIndexes = UsedIndexes ^ PossibleIndexes
4899fd2a6b71SDan Nowlin  *
4900fd2a6b71SDan Nowlin  *	FreeIndexes will contain the bits indicating the indexes free for use,
4901fd2a6b71SDan Nowlin  *      then the code needs to update the recipe[r].used_result_idx_bits to
4902fd2a6b71SDan Nowlin  *      indicate which indexes were selected for use by this recipe.
4903fd2a6b71SDan Nowlin  */
4904fd2a6b71SDan Nowlin static u16
4905fd2a6b71SDan Nowlin ice_find_free_recp_res_idx(struct ice_hw *hw, const unsigned long *profiles,
4906fd2a6b71SDan Nowlin 			   unsigned long *free_idx)
4907fd2a6b71SDan Nowlin {
4908fd2a6b71SDan Nowlin 	DECLARE_BITMAP(possible_idx, ICE_MAX_FV_WORDS);
4909fd2a6b71SDan Nowlin 	DECLARE_BITMAP(recipes, ICE_MAX_NUM_RECIPES);
4910fd2a6b71SDan Nowlin 	DECLARE_BITMAP(used_idx, ICE_MAX_FV_WORDS);
4911fd2a6b71SDan Nowlin 	u16 bit;
4912fd2a6b71SDan Nowlin 
4913fd2a6b71SDan Nowlin 	bitmap_zero(recipes, ICE_MAX_NUM_RECIPES);
4914fd2a6b71SDan Nowlin 	bitmap_zero(used_idx, ICE_MAX_FV_WORDS);
4915fd2a6b71SDan Nowlin 
49162f7ee2a7SAlexander Lobakin 	bitmap_fill(possible_idx, ICE_MAX_FV_WORDS);
4917fd2a6b71SDan Nowlin 
4918fd2a6b71SDan Nowlin 	/* For each profile we are going to associate the recipe with, add the
4919fd2a6b71SDan Nowlin 	 * recipes that are associated with that profile. This will give us
4920fd2a6b71SDan Nowlin 	 * the set of recipes that our recipe may collide with. Also, determine
4921fd2a6b71SDan Nowlin 	 * what possible result indexes are usable given this set of profiles.
4922fd2a6b71SDan Nowlin 	 */
4923fd2a6b71SDan Nowlin 	for_each_set_bit(bit, profiles, ICE_MAX_NUM_PROFILES) {
4924fd2a6b71SDan Nowlin 		bitmap_or(recipes, recipes, profile_to_recipe[bit],
4925fd2a6b71SDan Nowlin 			  ICE_MAX_NUM_RECIPES);
4926fd2a6b71SDan Nowlin 		bitmap_and(possible_idx, possible_idx,
4927fd2a6b71SDan Nowlin 			   hw->switch_info->prof_res_bm[bit],
4928fd2a6b71SDan Nowlin 			   ICE_MAX_FV_WORDS);
4929fd2a6b71SDan Nowlin 	}
4930fd2a6b71SDan Nowlin 
4931fd2a6b71SDan Nowlin 	/* For each recipe that our new recipe may collide with, determine
4932fd2a6b71SDan Nowlin 	 * which indexes have been used.
4933fd2a6b71SDan Nowlin 	 */
4934fd2a6b71SDan Nowlin 	for_each_set_bit(bit, recipes, ICE_MAX_NUM_RECIPES)
4935fd2a6b71SDan Nowlin 		bitmap_or(used_idx, used_idx,
4936fd2a6b71SDan Nowlin 			  hw->switch_info->recp_list[bit].res_idxs,
4937fd2a6b71SDan Nowlin 			  ICE_MAX_FV_WORDS);
4938fd2a6b71SDan Nowlin 
4939fd2a6b71SDan Nowlin 	bitmap_xor(free_idx, used_idx, possible_idx, ICE_MAX_FV_WORDS);
4940fd2a6b71SDan Nowlin 
4941fd2a6b71SDan Nowlin 	/* return number of free indexes */
4942fd2a6b71SDan Nowlin 	return (u16)bitmap_weight(free_idx, ICE_MAX_FV_WORDS);
4943fd2a6b71SDan Nowlin }
4944fd2a6b71SDan Nowlin 
4945fd2a6b71SDan Nowlin /**
4946fd2a6b71SDan Nowlin  * ice_add_sw_recipe - function to call AQ calls to create switch recipe
4947fd2a6b71SDan Nowlin  * @hw: pointer to hardware structure
4948fd2a6b71SDan Nowlin  * @rm: recipe management list entry
4949fd2a6b71SDan Nowlin  * @profiles: bitmap of profiles that will be associated.
4950fd2a6b71SDan Nowlin  */
49515e24d598STony Nguyen static int
4952fd2a6b71SDan Nowlin ice_add_sw_recipe(struct ice_hw *hw, struct ice_sw_recipe *rm,
49538b032a55SMichal Swiatkowski 		  unsigned long *profiles)
4954fd2a6b71SDan Nowlin {
4955fd2a6b71SDan Nowlin 	DECLARE_BITMAP(result_idx_bm, ICE_MAX_FV_WORDS);
4956bccd9bceSMarcin Szycik 	struct ice_aqc_recipe_content *content;
4957fd2a6b71SDan Nowlin 	struct ice_aqc_recipe_data_elem *tmp;
4958fd2a6b71SDan Nowlin 	struct ice_aqc_recipe_data_elem *buf;
4959fd2a6b71SDan Nowlin 	struct ice_recp_grp_entry *entry;
4960fd2a6b71SDan Nowlin 	u16 free_res_idx;
4961fd2a6b71SDan Nowlin 	u16 recipe_count;
4962fd2a6b71SDan Nowlin 	u8 chain_idx;
4963fd2a6b71SDan Nowlin 	u8 recps = 0;
49645518ac2aSTony Nguyen 	int status;
4965fd2a6b71SDan Nowlin 
4966fd2a6b71SDan Nowlin 	/* When more than one recipe are required, another recipe is needed to
4967fd2a6b71SDan Nowlin 	 * chain them together. Matching a tunnel metadata ID takes up one of
4968fd2a6b71SDan Nowlin 	 * the match fields in the chaining recipe reducing the number of
4969fd2a6b71SDan Nowlin 	 * chained recipes by one.
4970fd2a6b71SDan Nowlin 	 */
4971fd2a6b71SDan Nowlin 	 /* check number of free result indices */
4972fd2a6b71SDan Nowlin 	bitmap_zero(result_idx_bm, ICE_MAX_FV_WORDS);
4973fd2a6b71SDan Nowlin 	free_res_idx = ice_find_free_recp_res_idx(hw, profiles, result_idx_bm);
4974fd2a6b71SDan Nowlin 
4975fd2a6b71SDan Nowlin 	ice_debug(hw, ICE_DBG_SW, "Result idx slots: %d, need %d\n",
4976fd2a6b71SDan Nowlin 		  free_res_idx, rm->n_grp_count);
4977fd2a6b71SDan Nowlin 
4978fd2a6b71SDan Nowlin 	if (rm->n_grp_count > 1) {
4979fd2a6b71SDan Nowlin 		if (rm->n_grp_count > free_res_idx)
4980d54699e2STony Nguyen 			return -ENOSPC;
4981fd2a6b71SDan Nowlin 
4982fd2a6b71SDan Nowlin 		rm->n_grp_count++;
4983fd2a6b71SDan Nowlin 	}
4984fd2a6b71SDan Nowlin 
4985fd2a6b71SDan Nowlin 	if (rm->n_grp_count > ICE_MAX_CHAIN_RECIPE)
4986d54699e2STony Nguyen 		return -ENOSPC;
4987fd2a6b71SDan Nowlin 
4988fd2a6b71SDan Nowlin 	tmp = kcalloc(ICE_MAX_NUM_RECIPES, sizeof(*tmp), GFP_KERNEL);
4989fd2a6b71SDan Nowlin 	if (!tmp)
4990d54699e2STony Nguyen 		return -ENOMEM;
4991fd2a6b71SDan Nowlin 
4992fd2a6b71SDan Nowlin 	buf = devm_kcalloc(ice_hw_to_dev(hw), rm->n_grp_count, sizeof(*buf),
4993fd2a6b71SDan Nowlin 			   GFP_KERNEL);
4994fd2a6b71SDan Nowlin 	if (!buf) {
4995d54699e2STony Nguyen 		status = -ENOMEM;
4996fd2a6b71SDan Nowlin 		goto err_mem;
4997fd2a6b71SDan Nowlin 	}
4998fd2a6b71SDan Nowlin 
4999fd2a6b71SDan Nowlin 	bitmap_zero(rm->r_bitmap, ICE_MAX_NUM_RECIPES);
5000fd2a6b71SDan Nowlin 	recipe_count = ICE_MAX_NUM_RECIPES;
5001fd2a6b71SDan Nowlin 	status = ice_aq_get_recipe(hw, tmp, &recipe_count, ICE_SW_LKUP_MAC,
5002fd2a6b71SDan Nowlin 				   NULL);
5003fd2a6b71SDan Nowlin 	if (status || recipe_count == 0)
5004fd2a6b71SDan Nowlin 		goto err_unroll;
5005fd2a6b71SDan Nowlin 
5006fd2a6b71SDan Nowlin 	/* Allocate the recipe resources, and configure them according to the
5007fd2a6b71SDan Nowlin 	 * match fields from protocol headers and extracted field vectors.
5008fd2a6b71SDan Nowlin 	 */
5009fd2a6b71SDan Nowlin 	chain_idx = find_first_bit(result_idx_bm, ICE_MAX_FV_WORDS);
5010fd2a6b71SDan Nowlin 	list_for_each_entry(entry, &rm->rg_list, l_entry) {
5011fd2a6b71SDan Nowlin 		u8 i;
5012fd2a6b71SDan Nowlin 
5013fd2a6b71SDan Nowlin 		status = ice_alloc_recipe(hw, &entry->rid);
5014fd2a6b71SDan Nowlin 		if (status)
5015fd2a6b71SDan Nowlin 			goto err_unroll;
5016fd2a6b71SDan Nowlin 
5017bccd9bceSMarcin Szycik 		content = &buf[recps].content;
5018bccd9bceSMarcin Szycik 
5019fd2a6b71SDan Nowlin 		/* Clear the result index of the located recipe, as this will be
5020fd2a6b71SDan Nowlin 		 * updated, if needed, later in the recipe creation process.
5021fd2a6b71SDan Nowlin 		 */
5022fd2a6b71SDan Nowlin 		tmp[0].content.result_indx = 0;
5023fd2a6b71SDan Nowlin 
5024fd2a6b71SDan Nowlin 		buf[recps] = tmp[0];
5025fd2a6b71SDan Nowlin 		buf[recps].recipe_indx = (u8)entry->rid;
5026fd2a6b71SDan Nowlin 		/* if the recipe is a non-root recipe RID should be programmed
5027fd2a6b71SDan Nowlin 		 * as 0 for the rules to be applied correctly.
5028fd2a6b71SDan Nowlin 		 */
5029bccd9bceSMarcin Szycik 		content->rid = 0;
5030bccd9bceSMarcin Szycik 		memset(&content->lkup_indx, 0,
5031bccd9bceSMarcin Szycik 		       sizeof(content->lkup_indx));
5032fd2a6b71SDan Nowlin 
5033fd2a6b71SDan Nowlin 		/* All recipes use look-up index 0 to match switch ID. */
5034bccd9bceSMarcin Szycik 		content->lkup_indx[0] = ICE_AQ_SW_ID_LKUP_IDX;
5035bccd9bceSMarcin Szycik 		content->mask[0] = cpu_to_le16(ICE_AQ_SW_ID_LKUP_MASK);
5036fd2a6b71SDan Nowlin 		/* Setup lkup_indx 1..4 to INVALID/ignore and set the mask
5037fd2a6b71SDan Nowlin 		 * to be 0
5038fd2a6b71SDan Nowlin 		 */
5039fd2a6b71SDan Nowlin 		for (i = 1; i <= ICE_NUM_WORDS_RECIPE; i++) {
5040bccd9bceSMarcin Szycik 			content->lkup_indx[i] = 0x80;
5041bccd9bceSMarcin Szycik 			content->mask[i] = 0;
5042fd2a6b71SDan Nowlin 		}
5043fd2a6b71SDan Nowlin 
5044fd2a6b71SDan Nowlin 		for (i = 0; i < entry->r_group.n_val_pairs; i++) {
5045bccd9bceSMarcin Szycik 			content->lkup_indx[i + 1] = entry->fv_idx[i];
5046bccd9bceSMarcin Szycik 			content->mask[i + 1] = cpu_to_le16(entry->fv_mask[i]);
5047fd2a6b71SDan Nowlin 		}
5048fd2a6b71SDan Nowlin 
5049fd2a6b71SDan Nowlin 		if (rm->n_grp_count > 1) {
5050fd2a6b71SDan Nowlin 			/* Checks to see if there really is a valid result index
5051fd2a6b71SDan Nowlin 			 * that can be used.
5052fd2a6b71SDan Nowlin 			 */
5053fd2a6b71SDan Nowlin 			if (chain_idx >= ICE_MAX_FV_WORDS) {
5054fd2a6b71SDan Nowlin 				ice_debug(hw, ICE_DBG_SW, "No chain index available\n");
5055d54699e2STony Nguyen 				status = -ENOSPC;
5056fd2a6b71SDan Nowlin 				goto err_unroll;
5057fd2a6b71SDan Nowlin 			}
5058fd2a6b71SDan Nowlin 
5059fd2a6b71SDan Nowlin 			entry->chain_idx = chain_idx;
5060bccd9bceSMarcin Szycik 			content->result_indx =
5061fd2a6b71SDan Nowlin 				ICE_AQ_RECIPE_RESULT_EN |
5062fd2a6b71SDan Nowlin 				((chain_idx << ICE_AQ_RECIPE_RESULT_DATA_S) &
5063fd2a6b71SDan Nowlin 				 ICE_AQ_RECIPE_RESULT_DATA_M);
5064fd2a6b71SDan Nowlin 			clear_bit(chain_idx, result_idx_bm);
5065fd2a6b71SDan Nowlin 			chain_idx = find_first_bit(result_idx_bm,
5066fd2a6b71SDan Nowlin 						   ICE_MAX_FV_WORDS);
5067fd2a6b71SDan Nowlin 		}
5068fd2a6b71SDan Nowlin 
5069fd2a6b71SDan Nowlin 		/* fill recipe dependencies */
5070fd2a6b71SDan Nowlin 		bitmap_zero((unsigned long *)buf[recps].recipe_bitmap,
5071fd2a6b71SDan Nowlin 			    ICE_MAX_NUM_RECIPES);
5072fd2a6b71SDan Nowlin 		set_bit(buf[recps].recipe_indx,
5073fd2a6b71SDan Nowlin 			(unsigned long *)buf[recps].recipe_bitmap);
5074bccd9bceSMarcin Szycik 		content->act_ctrl_fwd_priority = rm->priority;
5075bccd9bceSMarcin Szycik 
5076bccd9bceSMarcin Szycik 		if (rm->need_pass_l2)
5077bccd9bceSMarcin Szycik 			content->act_ctrl |= ICE_AQ_RECIPE_ACT_NEED_PASS_L2;
5078bccd9bceSMarcin Szycik 
5079bccd9bceSMarcin Szycik 		if (rm->allow_pass_l2)
5080bccd9bceSMarcin Szycik 			content->act_ctrl |= ICE_AQ_RECIPE_ACT_ALLOW_PASS_L2;
5081fd2a6b71SDan Nowlin 		recps++;
5082fd2a6b71SDan Nowlin 	}
5083fd2a6b71SDan Nowlin 
5084fd2a6b71SDan Nowlin 	if (rm->n_grp_count == 1) {
5085fd2a6b71SDan Nowlin 		rm->root_rid = buf[0].recipe_indx;
5086fd2a6b71SDan Nowlin 		set_bit(buf[0].recipe_indx, rm->r_bitmap);
5087fd2a6b71SDan Nowlin 		buf[0].content.rid = rm->root_rid | ICE_AQ_RECIPE_ID_IS_ROOT;
5088fd2a6b71SDan Nowlin 		if (sizeof(buf[0].recipe_bitmap) >= sizeof(rm->r_bitmap)) {
5089fd2a6b71SDan Nowlin 			memcpy(buf[0].recipe_bitmap, rm->r_bitmap,
5090fd2a6b71SDan Nowlin 			       sizeof(buf[0].recipe_bitmap));
5091fd2a6b71SDan Nowlin 		} else {
5092d54699e2STony Nguyen 			status = -EINVAL;
5093fd2a6b71SDan Nowlin 			goto err_unroll;
5094fd2a6b71SDan Nowlin 		}
5095fd2a6b71SDan Nowlin 		/* Applicable only for ROOT_RECIPE, set the fwd_priority for
5096fd2a6b71SDan Nowlin 		 * the recipe which is getting created if specified
5097fd2a6b71SDan Nowlin 		 * by user. Usually any advanced switch filter, which results
5098fd2a6b71SDan Nowlin 		 * into new extraction sequence, ended up creating a new recipe
5099fd2a6b71SDan Nowlin 		 * of type ROOT and usually recipes are associated with profiles
5100fd2a6b71SDan Nowlin 		 * Switch rule referreing newly created recipe, needs to have
5101fd2a6b71SDan Nowlin 		 * either/or 'fwd' or 'join' priority, otherwise switch rule
5102fd2a6b71SDan Nowlin 		 * evaluation will not happen correctly. In other words, if
5103fd2a6b71SDan Nowlin 		 * switch rule to be evaluated on priority basis, then recipe
5104fd2a6b71SDan Nowlin 		 * needs to have priority, otherwise it will be evaluated last.
5105fd2a6b71SDan Nowlin 		 */
5106fd2a6b71SDan Nowlin 		buf[0].content.act_ctrl_fwd_priority = rm->priority;
5107fd2a6b71SDan Nowlin 	} else {
5108fd2a6b71SDan Nowlin 		struct ice_recp_grp_entry *last_chain_entry;
5109fd2a6b71SDan Nowlin 		u16 rid, i;
5110fd2a6b71SDan Nowlin 
5111fd2a6b71SDan Nowlin 		/* Allocate the last recipe that will chain the outcomes of the
5112fd2a6b71SDan Nowlin 		 * other recipes together
5113fd2a6b71SDan Nowlin 		 */
5114fd2a6b71SDan Nowlin 		status = ice_alloc_recipe(hw, &rid);
5115fd2a6b71SDan Nowlin 		if (status)
5116fd2a6b71SDan Nowlin 			goto err_unroll;
5117fd2a6b71SDan Nowlin 
5118bccd9bceSMarcin Szycik 		content = &buf[recps].content;
5119bccd9bceSMarcin Szycik 
5120fd2a6b71SDan Nowlin 		buf[recps].recipe_indx = (u8)rid;
5121bccd9bceSMarcin Szycik 		content->rid = (u8)rid;
5122bccd9bceSMarcin Szycik 		content->rid |= ICE_AQ_RECIPE_ID_IS_ROOT;
5123fd2a6b71SDan Nowlin 		/* the new entry created should also be part of rg_list to
5124fd2a6b71SDan Nowlin 		 * make sure we have complete recipe
5125fd2a6b71SDan Nowlin 		 */
5126fd2a6b71SDan Nowlin 		last_chain_entry = devm_kzalloc(ice_hw_to_dev(hw),
5127fd2a6b71SDan Nowlin 						sizeof(*last_chain_entry),
5128fd2a6b71SDan Nowlin 						GFP_KERNEL);
5129fd2a6b71SDan Nowlin 		if (!last_chain_entry) {
5130d54699e2STony Nguyen 			status = -ENOMEM;
5131fd2a6b71SDan Nowlin 			goto err_unroll;
5132fd2a6b71SDan Nowlin 		}
5133fd2a6b71SDan Nowlin 		last_chain_entry->rid = rid;
5134bccd9bceSMarcin Szycik 		memset(&content->lkup_indx, 0, sizeof(content->lkup_indx));
5135fd2a6b71SDan Nowlin 		/* All recipes use look-up index 0 to match switch ID. */
5136bccd9bceSMarcin Szycik 		content->lkup_indx[0] = ICE_AQ_SW_ID_LKUP_IDX;
5137bccd9bceSMarcin Szycik 		content->mask[0] = cpu_to_le16(ICE_AQ_SW_ID_LKUP_MASK);
5138fd2a6b71SDan Nowlin 		for (i = 1; i <= ICE_NUM_WORDS_RECIPE; i++) {
5139bccd9bceSMarcin Szycik 			content->lkup_indx[i] = ICE_AQ_RECIPE_LKUP_IGNORE;
5140bccd9bceSMarcin Szycik 			content->mask[i] = 0;
5141fd2a6b71SDan Nowlin 		}
5142fd2a6b71SDan Nowlin 
5143fd2a6b71SDan Nowlin 		i = 1;
5144fd2a6b71SDan Nowlin 		/* update r_bitmap with the recp that is used for chaining */
5145fd2a6b71SDan Nowlin 		set_bit(rid, rm->r_bitmap);
5146fd2a6b71SDan Nowlin 		/* this is the recipe that chains all the other recipes so it
5147fd2a6b71SDan Nowlin 		 * should not have a chaining ID to indicate the same
5148fd2a6b71SDan Nowlin 		 */
5149fd2a6b71SDan Nowlin 		last_chain_entry->chain_idx = ICE_INVAL_CHAIN_IND;
5150fd2a6b71SDan Nowlin 		list_for_each_entry(entry, &rm->rg_list, l_entry) {
5151fd2a6b71SDan Nowlin 			last_chain_entry->fv_idx[i] = entry->chain_idx;
5152bccd9bceSMarcin Szycik 			content->lkup_indx[i] = entry->chain_idx;
5153bccd9bceSMarcin Szycik 			content->mask[i++] = cpu_to_le16(0xFFFF);
5154fd2a6b71SDan Nowlin 			set_bit(entry->rid, rm->r_bitmap);
5155fd2a6b71SDan Nowlin 		}
5156fd2a6b71SDan Nowlin 		list_add(&last_chain_entry->l_entry, &rm->rg_list);
5157fd2a6b71SDan Nowlin 		if (sizeof(buf[recps].recipe_bitmap) >=
5158fd2a6b71SDan Nowlin 		    sizeof(rm->r_bitmap)) {
5159fd2a6b71SDan Nowlin 			memcpy(buf[recps].recipe_bitmap, rm->r_bitmap,
5160fd2a6b71SDan Nowlin 			       sizeof(buf[recps].recipe_bitmap));
5161fd2a6b71SDan Nowlin 		} else {
5162d54699e2STony Nguyen 			status = -EINVAL;
5163fd2a6b71SDan Nowlin 			goto err_unroll;
5164fd2a6b71SDan Nowlin 		}
5165bccd9bceSMarcin Szycik 		content->act_ctrl_fwd_priority = rm->priority;
5166fd2a6b71SDan Nowlin 
5167fd2a6b71SDan Nowlin 		recps++;
5168fd2a6b71SDan Nowlin 		rm->root_rid = (u8)rid;
5169fd2a6b71SDan Nowlin 	}
5170fd2a6b71SDan Nowlin 	status = ice_acquire_change_lock(hw, ICE_RES_WRITE);
5171fd2a6b71SDan Nowlin 	if (status)
5172fd2a6b71SDan Nowlin 		goto err_unroll;
5173fd2a6b71SDan Nowlin 
5174fd2a6b71SDan Nowlin 	status = ice_aq_add_recipe(hw, buf, rm->n_grp_count, NULL);
5175fd2a6b71SDan Nowlin 	ice_release_change_lock(hw);
5176fd2a6b71SDan Nowlin 	if (status)
5177fd2a6b71SDan Nowlin 		goto err_unroll;
5178fd2a6b71SDan Nowlin 
5179fd2a6b71SDan Nowlin 	/* Every recipe that just got created add it to the recipe
5180fd2a6b71SDan Nowlin 	 * book keeping list
5181fd2a6b71SDan Nowlin 	 */
5182fd2a6b71SDan Nowlin 	list_for_each_entry(entry, &rm->rg_list, l_entry) {
5183fd2a6b71SDan Nowlin 		struct ice_switch_info *sw = hw->switch_info;
5184fd2a6b71SDan Nowlin 		bool is_root, idx_found = false;
5185fd2a6b71SDan Nowlin 		struct ice_sw_recipe *recp;
5186fd2a6b71SDan Nowlin 		u16 idx, buf_idx = 0;
5187fd2a6b71SDan Nowlin 
5188fd2a6b71SDan Nowlin 		/* find buffer index for copying some data */
5189fd2a6b71SDan Nowlin 		for (idx = 0; idx < rm->n_grp_count; idx++)
5190fd2a6b71SDan Nowlin 			if (buf[idx].recipe_indx == entry->rid) {
5191fd2a6b71SDan Nowlin 				buf_idx = idx;
5192fd2a6b71SDan Nowlin 				idx_found = true;
5193fd2a6b71SDan Nowlin 			}
5194fd2a6b71SDan Nowlin 
5195fd2a6b71SDan Nowlin 		if (!idx_found) {
5196d54699e2STony Nguyen 			status = -EIO;
5197fd2a6b71SDan Nowlin 			goto err_unroll;
5198fd2a6b71SDan Nowlin 		}
5199fd2a6b71SDan Nowlin 
5200fd2a6b71SDan Nowlin 		recp = &sw->recp_list[entry->rid];
5201fd2a6b71SDan Nowlin 		is_root = (rm->root_rid == entry->rid);
5202fd2a6b71SDan Nowlin 		recp->is_root = is_root;
5203fd2a6b71SDan Nowlin 
5204fd2a6b71SDan Nowlin 		recp->root_rid = entry->rid;
5205fd2a6b71SDan Nowlin 		recp->big_recp = (is_root && rm->n_grp_count > 1);
5206fd2a6b71SDan Nowlin 
5207fd2a6b71SDan Nowlin 		memcpy(&recp->ext_words, entry->r_group.pairs,
5208fd2a6b71SDan Nowlin 		       entry->r_group.n_val_pairs * sizeof(struct ice_fv_word));
5209fd2a6b71SDan Nowlin 
5210fd2a6b71SDan Nowlin 		memcpy(recp->r_bitmap, buf[buf_idx].recipe_bitmap,
5211fd2a6b71SDan Nowlin 		       sizeof(recp->r_bitmap));
5212fd2a6b71SDan Nowlin 
5213fd2a6b71SDan Nowlin 		/* Copy non-result fv index values and masks to recipe. This
5214fd2a6b71SDan Nowlin 		 * call will also update the result recipe bitmask.
5215fd2a6b71SDan Nowlin 		 */
5216fd2a6b71SDan Nowlin 		ice_collect_result_idx(&buf[buf_idx], recp);
5217fd2a6b71SDan Nowlin 
5218fd2a6b71SDan Nowlin 		/* for non-root recipes, also copy to the root, this allows
5219fd2a6b71SDan Nowlin 		 * easier matching of a complete chained recipe
5220fd2a6b71SDan Nowlin 		 */
5221fd2a6b71SDan Nowlin 		if (!is_root)
5222fd2a6b71SDan Nowlin 			ice_collect_result_idx(&buf[buf_idx],
5223fd2a6b71SDan Nowlin 					       &sw->recp_list[rm->root_rid]);
5224fd2a6b71SDan Nowlin 
5225fd2a6b71SDan Nowlin 		recp->n_ext_words = entry->r_group.n_val_pairs;
5226fd2a6b71SDan Nowlin 		recp->chain_idx = entry->chain_idx;
5227fd2a6b71SDan Nowlin 		recp->priority = buf[buf_idx].content.act_ctrl_fwd_priority;
5228fd2a6b71SDan Nowlin 		recp->n_grp_count = rm->n_grp_count;
52298b032a55SMichal Swiatkowski 		recp->tun_type = rm->tun_type;
5230bccd9bceSMarcin Szycik 		recp->need_pass_l2 = rm->need_pass_l2;
5231bccd9bceSMarcin Szycik 		recp->allow_pass_l2 = rm->allow_pass_l2;
5232fd2a6b71SDan Nowlin 		recp->recp_created = true;
5233fd2a6b71SDan Nowlin 	}
5234fd2a6b71SDan Nowlin 	rm->root_buf = buf;
5235fd2a6b71SDan Nowlin 	kfree(tmp);
5236fd2a6b71SDan Nowlin 	return status;
5237fd2a6b71SDan Nowlin 
5238fd2a6b71SDan Nowlin err_unroll:
5239fd2a6b71SDan Nowlin err_mem:
5240fd2a6b71SDan Nowlin 	kfree(tmp);
5241fd2a6b71SDan Nowlin 	devm_kfree(ice_hw_to_dev(hw), buf);
5242fd2a6b71SDan Nowlin 	return status;
5243fd2a6b71SDan Nowlin }
5244fd2a6b71SDan Nowlin 
5245fd2a6b71SDan Nowlin /**
5246fd2a6b71SDan Nowlin  * ice_create_recipe_group - creates recipe group
5247fd2a6b71SDan Nowlin  * @hw: pointer to hardware structure
5248fd2a6b71SDan Nowlin  * @rm: recipe management list entry
5249fd2a6b71SDan Nowlin  * @lkup_exts: lookup elements
5250fd2a6b71SDan Nowlin  */
52515e24d598STony Nguyen static int
5252fd2a6b71SDan Nowlin ice_create_recipe_group(struct ice_hw *hw, struct ice_sw_recipe *rm,
5253fd2a6b71SDan Nowlin 			struct ice_prot_lkup_ext *lkup_exts)
5254fd2a6b71SDan Nowlin {
5255fd2a6b71SDan Nowlin 	u8 recp_count = 0;
52565518ac2aSTony Nguyen 	int status;
5257fd2a6b71SDan Nowlin 
5258fd2a6b71SDan Nowlin 	rm->n_grp_count = 0;
5259fd2a6b71SDan Nowlin 
5260fd2a6b71SDan Nowlin 	/* Create recipes for words that are marked not done by packing them
5261fd2a6b71SDan Nowlin 	 * as best fit.
5262fd2a6b71SDan Nowlin 	 */
5263fd2a6b71SDan Nowlin 	status = ice_create_first_fit_recp_def(hw, lkup_exts,
5264fd2a6b71SDan Nowlin 					       &rm->rg_list, &recp_count);
5265fd2a6b71SDan Nowlin 	if (!status) {
5266fd2a6b71SDan Nowlin 		rm->n_grp_count += recp_count;
5267fd2a6b71SDan Nowlin 		rm->n_ext_words = lkup_exts->n_val_words;
5268fd2a6b71SDan Nowlin 		memcpy(&rm->ext_words, lkup_exts->fv_words,
5269fd2a6b71SDan Nowlin 		       sizeof(rm->ext_words));
5270fd2a6b71SDan Nowlin 		memcpy(rm->word_masks, lkup_exts->field_mask,
5271fd2a6b71SDan Nowlin 		       sizeof(rm->word_masks));
5272fd2a6b71SDan Nowlin 	}
5273fd2a6b71SDan Nowlin 
5274fd2a6b71SDan Nowlin 	return status;
5275fd2a6b71SDan Nowlin }
5276fd2a6b71SDan Nowlin 
5277fd2a6b71SDan Nowlin /* ice_get_compat_fv_bitmap - Get compatible field vector bitmap for rule
5278fd2a6b71SDan Nowlin  * @hw: pointer to hardware structure
5279fd2a6b71SDan Nowlin  * @rinfo: other information regarding the rule e.g. priority and action info
5280fd2a6b71SDan Nowlin  * @bm: pointer to memory for returning the bitmap of field vectors
5281fd2a6b71SDan Nowlin  */
5282fd2a6b71SDan Nowlin static void
5283fd2a6b71SDan Nowlin ice_get_compat_fv_bitmap(struct ice_hw *hw, struct ice_adv_rule_info *rinfo,
5284fd2a6b71SDan Nowlin 			 unsigned long *bm)
5285fd2a6b71SDan Nowlin {
52868b032a55SMichal Swiatkowski 	enum ice_prof_type prof_type;
52878b032a55SMichal Swiatkowski 
5288fd2a6b71SDan Nowlin 	bitmap_zero(bm, ICE_MAX_NUM_PROFILES);
5289fd2a6b71SDan Nowlin 
52908b032a55SMichal Swiatkowski 	switch (rinfo->tun_type) {
52918b032a55SMichal Swiatkowski 	case ICE_NON_TUN:
52928b032a55SMichal Swiatkowski 		prof_type = ICE_PROF_NON_TUN;
52938b032a55SMichal Swiatkowski 		break;
52948b032a55SMichal Swiatkowski 	case ICE_ALL_TUNNELS:
52958b032a55SMichal Swiatkowski 		prof_type = ICE_PROF_TUN_ALL;
52968b032a55SMichal Swiatkowski 		break;
52978b032a55SMichal Swiatkowski 	case ICE_SW_TUN_GENEVE:
52988b032a55SMichal Swiatkowski 	case ICE_SW_TUN_VXLAN:
52998b032a55SMichal Swiatkowski 		prof_type = ICE_PROF_TUN_UDP;
53008b032a55SMichal Swiatkowski 		break;
5301f0a35040SMichal Swiatkowski 	case ICE_SW_TUN_NVGRE:
5302f0a35040SMichal Swiatkowski 		prof_type = ICE_PROF_TUN_GRE;
5303f0a35040SMichal Swiatkowski 		break;
53049a225f81SMarcin Szycik 	case ICE_SW_TUN_GTPU:
53059a225f81SMarcin Szycik 		prof_type = ICE_PROF_TUN_GTPU;
53069a225f81SMarcin Szycik 		break;
53079a225f81SMarcin Szycik 	case ICE_SW_TUN_GTPC:
53089a225f81SMarcin Szycik 		prof_type = ICE_PROF_TUN_GTPC;
53099a225f81SMarcin Szycik 		break;
5310b70bc066SWojciech Drewek 	case ICE_SW_TUN_AND_NON_TUN:
53118b032a55SMichal Swiatkowski 	default:
53128b032a55SMichal Swiatkowski 		prof_type = ICE_PROF_ALL;
53138b032a55SMichal Swiatkowski 		break;
53148b032a55SMichal Swiatkowski 	}
53158b032a55SMichal Swiatkowski 
53168b032a55SMichal Swiatkowski 	ice_get_sw_fv_bitmap(hw, prof_type, bm);
5317fd2a6b71SDan Nowlin }
5318fd2a6b71SDan Nowlin 
5319fd2a6b71SDan Nowlin /**
5320fd2a6b71SDan Nowlin  * ice_add_adv_recipe - Add an advanced recipe that is not part of the default
5321fd2a6b71SDan Nowlin  * @hw: pointer to hardware structure
5322fd2a6b71SDan Nowlin  * @lkups: lookup elements or match criteria for the advanced recipe, one
5323fd2a6b71SDan Nowlin  *  structure per protocol header
5324fd2a6b71SDan Nowlin  * @lkups_cnt: number of protocols
5325fd2a6b71SDan Nowlin  * @rinfo: other information regarding the rule e.g. priority and action info
5326fd2a6b71SDan Nowlin  * @rid: return the recipe ID of the recipe created
5327fd2a6b71SDan Nowlin  */
53285e24d598STony Nguyen static int
5329fd2a6b71SDan Nowlin ice_add_adv_recipe(struct ice_hw *hw, struct ice_adv_lkup_elem *lkups,
5330fd2a6b71SDan Nowlin 		   u16 lkups_cnt, struct ice_adv_rule_info *rinfo, u16 *rid)
5331fd2a6b71SDan Nowlin {
5332fd2a6b71SDan Nowlin 	DECLARE_BITMAP(fv_bitmap, ICE_MAX_NUM_PROFILES);
5333fd2a6b71SDan Nowlin 	DECLARE_BITMAP(profiles, ICE_MAX_NUM_PROFILES);
5334fd2a6b71SDan Nowlin 	struct ice_prot_lkup_ext *lkup_exts;
5335fd2a6b71SDan Nowlin 	struct ice_recp_grp_entry *r_entry;
5336fd2a6b71SDan Nowlin 	struct ice_sw_fv_list_entry *fvit;
5337fd2a6b71SDan Nowlin 	struct ice_recp_grp_entry *r_tmp;
5338fd2a6b71SDan Nowlin 	struct ice_sw_fv_list_entry *tmp;
5339fd2a6b71SDan Nowlin 	struct ice_sw_recipe *rm;
53405518ac2aSTony Nguyen 	int status = 0;
5341fd2a6b71SDan Nowlin 	u8 i;
5342fd2a6b71SDan Nowlin 
5343fd2a6b71SDan Nowlin 	if (!lkups_cnt)
5344d54699e2STony Nguyen 		return -EINVAL;
5345fd2a6b71SDan Nowlin 
5346fd2a6b71SDan Nowlin 	lkup_exts = kzalloc(sizeof(*lkup_exts), GFP_KERNEL);
5347fd2a6b71SDan Nowlin 	if (!lkup_exts)
5348d54699e2STony Nguyen 		return -ENOMEM;
5349fd2a6b71SDan Nowlin 
5350fd2a6b71SDan Nowlin 	/* Determine the number of words to be matched and if it exceeds a
5351fd2a6b71SDan Nowlin 	 * recipe's restrictions
5352fd2a6b71SDan Nowlin 	 */
5353fd2a6b71SDan Nowlin 	for (i = 0; i < lkups_cnt; i++) {
5354fd2a6b71SDan Nowlin 		u16 count;
5355fd2a6b71SDan Nowlin 
5356fd2a6b71SDan Nowlin 		if (lkups[i].type >= ICE_PROTOCOL_LAST) {
5357d54699e2STony Nguyen 			status = -EIO;
5358fd2a6b71SDan Nowlin 			goto err_free_lkup_exts;
5359fd2a6b71SDan Nowlin 		}
5360fd2a6b71SDan Nowlin 
5361fd2a6b71SDan Nowlin 		count = ice_fill_valid_words(&lkups[i], lkup_exts);
5362fd2a6b71SDan Nowlin 		if (!count) {
5363d54699e2STony Nguyen 			status = -EIO;
5364fd2a6b71SDan Nowlin 			goto err_free_lkup_exts;
5365fd2a6b71SDan Nowlin 		}
5366fd2a6b71SDan Nowlin 	}
5367fd2a6b71SDan Nowlin 
5368fd2a6b71SDan Nowlin 	rm = kzalloc(sizeof(*rm), GFP_KERNEL);
5369fd2a6b71SDan Nowlin 	if (!rm) {
5370d54699e2STony Nguyen 		status = -ENOMEM;
5371fd2a6b71SDan Nowlin 		goto err_free_lkup_exts;
5372fd2a6b71SDan Nowlin 	}
5373fd2a6b71SDan Nowlin 
5374fd2a6b71SDan Nowlin 	/* Get field vectors that contain fields extracted from all the protocol
5375fd2a6b71SDan Nowlin 	 * headers being programmed.
5376fd2a6b71SDan Nowlin 	 */
5377fd2a6b71SDan Nowlin 	INIT_LIST_HEAD(&rm->fv_list);
5378fd2a6b71SDan Nowlin 	INIT_LIST_HEAD(&rm->rg_list);
5379fd2a6b71SDan Nowlin 
5380fd2a6b71SDan Nowlin 	/* Get bitmap of field vectors (profiles) that are compatible with the
5381fd2a6b71SDan Nowlin 	 * rule request; only these will be searched in the subsequent call to
5382e5dd661bSMichal Swiatkowski 	 * ice_get_sw_fv_list.
5383fd2a6b71SDan Nowlin 	 */
5384fd2a6b71SDan Nowlin 	ice_get_compat_fv_bitmap(hw, rinfo, fv_bitmap);
5385fd2a6b71SDan Nowlin 
5386e5dd661bSMichal Swiatkowski 	status = ice_get_sw_fv_list(hw, lkup_exts, fv_bitmap, &rm->fv_list);
5387fd2a6b71SDan Nowlin 	if (status)
5388fd2a6b71SDan Nowlin 		goto err_unroll;
5389fd2a6b71SDan Nowlin 
5390fd2a6b71SDan Nowlin 	/* Group match words into recipes using preferred recipe grouping
5391fd2a6b71SDan Nowlin 	 * criteria.
5392fd2a6b71SDan Nowlin 	 */
5393fd2a6b71SDan Nowlin 	status = ice_create_recipe_group(hw, rm, lkup_exts);
5394fd2a6b71SDan Nowlin 	if (status)
5395fd2a6b71SDan Nowlin 		goto err_unroll;
5396fd2a6b71SDan Nowlin 
5397fd2a6b71SDan Nowlin 	/* set the recipe priority if specified */
5398fd2a6b71SDan Nowlin 	rm->priority = (u8)rinfo->priority;
5399fd2a6b71SDan Nowlin 
5400bccd9bceSMarcin Szycik 	rm->need_pass_l2 = rinfo->need_pass_l2;
5401bccd9bceSMarcin Szycik 	rm->allow_pass_l2 = rinfo->allow_pass_l2;
5402bccd9bceSMarcin Szycik 
5403fd2a6b71SDan Nowlin 	/* Find offsets from the field vector. Pick the first one for all the
5404fd2a6b71SDan Nowlin 	 * recipes.
5405fd2a6b71SDan Nowlin 	 */
5406fd2a6b71SDan Nowlin 	status = ice_fill_fv_word_index(hw, &rm->fv_list, &rm->rg_list);
5407fd2a6b71SDan Nowlin 	if (status)
5408fd2a6b71SDan Nowlin 		goto err_unroll;
5409fd2a6b71SDan Nowlin 
5410fd2a6b71SDan Nowlin 	/* get bitmap of all profiles the recipe will be associated with */
5411fd2a6b71SDan Nowlin 	bitmap_zero(profiles, ICE_MAX_NUM_PROFILES);
5412fd2a6b71SDan Nowlin 	list_for_each_entry(fvit, &rm->fv_list, list_entry) {
5413fd2a6b71SDan Nowlin 		ice_debug(hw, ICE_DBG_SW, "profile: %d\n", fvit->profile_id);
5414fd2a6b71SDan Nowlin 		set_bit((u16)fvit->profile_id, profiles);
5415fd2a6b71SDan Nowlin 	}
5416fd2a6b71SDan Nowlin 
5417fd2a6b71SDan Nowlin 	/* Look for a recipe which matches our requested fv / mask list */
5418bccd9bceSMarcin Szycik 	*rid = ice_find_recp(hw, lkup_exts, rinfo);
5419fd2a6b71SDan Nowlin 	if (*rid < ICE_MAX_NUM_RECIPES)
5420fd2a6b71SDan Nowlin 		/* Success if found a recipe that match the existing criteria */
5421fd2a6b71SDan Nowlin 		goto err_unroll;
5422fd2a6b71SDan Nowlin 
5423de6acd1cSMichal Swiatkowski 	rm->tun_type = rinfo->tun_type;
5424fd2a6b71SDan Nowlin 	/* Recipe we need does not exist, add a recipe */
54258b032a55SMichal Swiatkowski 	status = ice_add_sw_recipe(hw, rm, profiles);
5426fd2a6b71SDan Nowlin 	if (status)
5427fd2a6b71SDan Nowlin 		goto err_unroll;
5428fd2a6b71SDan Nowlin 
5429fd2a6b71SDan Nowlin 	/* Associate all the recipes created with all the profiles in the
5430fd2a6b71SDan Nowlin 	 * common field vector.
5431fd2a6b71SDan Nowlin 	 */
5432fd2a6b71SDan Nowlin 	list_for_each_entry(fvit, &rm->fv_list, list_entry) {
5433fd2a6b71SDan Nowlin 		DECLARE_BITMAP(r_bitmap, ICE_MAX_NUM_RECIPES);
5434fd2a6b71SDan Nowlin 		u16 j;
5435fd2a6b71SDan Nowlin 
5436fd2a6b71SDan Nowlin 		status = ice_aq_get_recipe_to_profile(hw, fvit->profile_id,
5437fd2a6b71SDan Nowlin 						      (u8 *)r_bitmap, NULL);
5438fd2a6b71SDan Nowlin 		if (status)
5439fd2a6b71SDan Nowlin 			goto err_unroll;
5440fd2a6b71SDan Nowlin 
5441fd2a6b71SDan Nowlin 		bitmap_or(r_bitmap, r_bitmap, rm->r_bitmap,
5442fd2a6b71SDan Nowlin 			  ICE_MAX_NUM_RECIPES);
5443fd2a6b71SDan Nowlin 		status = ice_acquire_change_lock(hw, ICE_RES_WRITE);
5444fd2a6b71SDan Nowlin 		if (status)
5445fd2a6b71SDan Nowlin 			goto err_unroll;
5446fd2a6b71SDan Nowlin 
5447fd2a6b71SDan Nowlin 		status = ice_aq_map_recipe_to_profile(hw, fvit->profile_id,
5448fd2a6b71SDan Nowlin 						      (u8 *)r_bitmap,
5449fd2a6b71SDan Nowlin 						      NULL);
5450fd2a6b71SDan Nowlin 		ice_release_change_lock(hw);
5451fd2a6b71SDan Nowlin 
5452fd2a6b71SDan Nowlin 		if (status)
5453fd2a6b71SDan Nowlin 			goto err_unroll;
5454fd2a6b71SDan Nowlin 
5455fd2a6b71SDan Nowlin 		/* Update profile to recipe bitmap array */
5456fd2a6b71SDan Nowlin 		bitmap_copy(profile_to_recipe[fvit->profile_id], r_bitmap,
5457fd2a6b71SDan Nowlin 			    ICE_MAX_NUM_RECIPES);
5458fd2a6b71SDan Nowlin 
5459fd2a6b71SDan Nowlin 		/* Update recipe to profile bitmap array */
5460fd2a6b71SDan Nowlin 		for_each_set_bit(j, rm->r_bitmap, ICE_MAX_NUM_RECIPES)
5461fd2a6b71SDan Nowlin 			set_bit((u16)fvit->profile_id, recipe_to_profile[j]);
5462fd2a6b71SDan Nowlin 	}
5463fd2a6b71SDan Nowlin 
5464fd2a6b71SDan Nowlin 	*rid = rm->root_rid;
5465fd2a6b71SDan Nowlin 	memcpy(&hw->switch_info->recp_list[*rid].lkup_exts, lkup_exts,
5466fd2a6b71SDan Nowlin 	       sizeof(*lkup_exts));
5467fd2a6b71SDan Nowlin err_unroll:
5468fd2a6b71SDan Nowlin 	list_for_each_entry_safe(r_entry, r_tmp, &rm->rg_list, l_entry) {
5469fd2a6b71SDan Nowlin 		list_del(&r_entry->l_entry);
5470fd2a6b71SDan Nowlin 		devm_kfree(ice_hw_to_dev(hw), r_entry);
5471fd2a6b71SDan Nowlin 	}
5472fd2a6b71SDan Nowlin 
5473fd2a6b71SDan Nowlin 	list_for_each_entry_safe(fvit, tmp, &rm->fv_list, list_entry) {
5474fd2a6b71SDan Nowlin 		list_del(&fvit->list_entry);
5475fd2a6b71SDan Nowlin 		devm_kfree(ice_hw_to_dev(hw), fvit);
5476fd2a6b71SDan Nowlin 	}
5477fd2a6b71SDan Nowlin 
5478fd2a6b71SDan Nowlin 	devm_kfree(ice_hw_to_dev(hw), rm->root_buf);
5479fd2a6b71SDan Nowlin 	kfree(rm);
5480fd2a6b71SDan Nowlin 
5481fd2a6b71SDan Nowlin err_free_lkup_exts:
5482fd2a6b71SDan Nowlin 	kfree(lkup_exts);
5483fd2a6b71SDan Nowlin 
5484fd2a6b71SDan Nowlin 	return status;
5485fd2a6b71SDan Nowlin }
5486fd2a6b71SDan Nowlin 
5487148beb61SHenry Tieman /**
548826395726SMartyna Szapar-Mudlaw  * ice_dummy_packet_add_vlan - insert VLAN header to dummy pkt
548926395726SMartyna Szapar-Mudlaw  *
549026395726SMartyna Szapar-Mudlaw  * @dummy_pkt: dummy packet profile pattern to which VLAN tag(s) will be added
549126395726SMartyna Szapar-Mudlaw  * @num_vlan: number of VLAN tags
549226395726SMartyna Szapar-Mudlaw  */
549326395726SMartyna Szapar-Mudlaw static struct ice_dummy_pkt_profile *
549426395726SMartyna Szapar-Mudlaw ice_dummy_packet_add_vlan(const struct ice_dummy_pkt_profile *dummy_pkt,
549526395726SMartyna Szapar-Mudlaw 			  u32 num_vlan)
549626395726SMartyna Szapar-Mudlaw {
549726395726SMartyna Szapar-Mudlaw 	struct ice_dummy_pkt_profile *profile;
549826395726SMartyna Szapar-Mudlaw 	struct ice_dummy_pkt_offsets *offsets;
549926395726SMartyna Szapar-Mudlaw 	u32 buf_len, off, etype_off, i;
550026395726SMartyna Szapar-Mudlaw 	u8 *pkt;
550126395726SMartyna Szapar-Mudlaw 
550226395726SMartyna Szapar-Mudlaw 	if (num_vlan < 1 || num_vlan > 2)
550326395726SMartyna Szapar-Mudlaw 		return ERR_PTR(-EINVAL);
550426395726SMartyna Szapar-Mudlaw 
550526395726SMartyna Szapar-Mudlaw 	off = num_vlan * VLAN_HLEN;
550626395726SMartyna Szapar-Mudlaw 
550726395726SMartyna Szapar-Mudlaw 	buf_len = array_size(num_vlan, sizeof(ice_dummy_vlan_packet_offsets)) +
550826395726SMartyna Szapar-Mudlaw 		  dummy_pkt->offsets_len;
550926395726SMartyna Szapar-Mudlaw 	offsets = kzalloc(buf_len, GFP_KERNEL);
551026395726SMartyna Szapar-Mudlaw 	if (!offsets)
551126395726SMartyna Szapar-Mudlaw 		return ERR_PTR(-ENOMEM);
551226395726SMartyna Szapar-Mudlaw 
551326395726SMartyna Szapar-Mudlaw 	offsets[0] = dummy_pkt->offsets[0];
551426395726SMartyna Szapar-Mudlaw 	if (num_vlan == 2) {
551526395726SMartyna Szapar-Mudlaw 		offsets[1] = ice_dummy_qinq_packet_offsets[0];
551626395726SMartyna Szapar-Mudlaw 		offsets[2] = ice_dummy_qinq_packet_offsets[1];
551726395726SMartyna Szapar-Mudlaw 	} else if (num_vlan == 1) {
551826395726SMartyna Szapar-Mudlaw 		offsets[1] = ice_dummy_vlan_packet_offsets[0];
551926395726SMartyna Szapar-Mudlaw 	}
552026395726SMartyna Szapar-Mudlaw 
552126395726SMartyna Szapar-Mudlaw 	for (i = 1; dummy_pkt->offsets[i].type != ICE_PROTOCOL_LAST; i++) {
552226395726SMartyna Szapar-Mudlaw 		offsets[i + num_vlan].type = dummy_pkt->offsets[i].type;
552326395726SMartyna Szapar-Mudlaw 		offsets[i + num_vlan].offset =
552426395726SMartyna Szapar-Mudlaw 			dummy_pkt->offsets[i].offset + off;
552526395726SMartyna Szapar-Mudlaw 	}
552626395726SMartyna Szapar-Mudlaw 	offsets[i + num_vlan] = dummy_pkt->offsets[i];
552726395726SMartyna Szapar-Mudlaw 
552826395726SMartyna Szapar-Mudlaw 	etype_off = dummy_pkt->offsets[1].offset;
552926395726SMartyna Szapar-Mudlaw 
553026395726SMartyna Szapar-Mudlaw 	buf_len = array_size(num_vlan, sizeof(ice_dummy_vlan_packet)) +
553126395726SMartyna Szapar-Mudlaw 		  dummy_pkt->pkt_len;
553226395726SMartyna Szapar-Mudlaw 	pkt = kzalloc(buf_len, GFP_KERNEL);
553326395726SMartyna Szapar-Mudlaw 	if (!pkt) {
553426395726SMartyna Szapar-Mudlaw 		kfree(offsets);
553526395726SMartyna Szapar-Mudlaw 		return ERR_PTR(-ENOMEM);
553626395726SMartyna Szapar-Mudlaw 	}
553726395726SMartyna Szapar-Mudlaw 
553826395726SMartyna Szapar-Mudlaw 	memcpy(pkt, dummy_pkt->pkt, etype_off);
553926395726SMartyna Szapar-Mudlaw 	memcpy(pkt + etype_off,
554026395726SMartyna Szapar-Mudlaw 	       num_vlan == 2 ? ice_dummy_qinq_packet : ice_dummy_vlan_packet,
554126395726SMartyna Szapar-Mudlaw 	       off);
554226395726SMartyna Szapar-Mudlaw 	memcpy(pkt + etype_off + off, dummy_pkt->pkt + etype_off,
554326395726SMartyna Szapar-Mudlaw 	       dummy_pkt->pkt_len - etype_off);
554426395726SMartyna Szapar-Mudlaw 
554526395726SMartyna Szapar-Mudlaw 	profile = kzalloc(sizeof(*profile), GFP_KERNEL);
554626395726SMartyna Szapar-Mudlaw 	if (!profile) {
554726395726SMartyna Szapar-Mudlaw 		kfree(offsets);
554826395726SMartyna Szapar-Mudlaw 		kfree(pkt);
554926395726SMartyna Szapar-Mudlaw 		return ERR_PTR(-ENOMEM);
555026395726SMartyna Szapar-Mudlaw 	}
555126395726SMartyna Szapar-Mudlaw 
555226395726SMartyna Szapar-Mudlaw 	profile->offsets = offsets;
555326395726SMartyna Szapar-Mudlaw 	profile->pkt = pkt;
555426395726SMartyna Szapar-Mudlaw 	profile->pkt_len = buf_len;
555526395726SMartyna Szapar-Mudlaw 	profile->match |= ICE_PKT_KMALLOC;
555626395726SMartyna Szapar-Mudlaw 
555726395726SMartyna Szapar-Mudlaw 	return profile;
555826395726SMartyna Szapar-Mudlaw }
555926395726SMartyna Szapar-Mudlaw 
556026395726SMartyna Szapar-Mudlaw /**
55610f94570dSGrishma Kotecha  * ice_find_dummy_packet - find dummy packet
55620f94570dSGrishma Kotecha  *
55630f94570dSGrishma Kotecha  * @lkups: lookup elements or match criteria for the advanced recipe, one
55640f94570dSGrishma Kotecha  *	   structure per protocol header
55650f94570dSGrishma Kotecha  * @lkups_cnt: number of protocols
55668b032a55SMichal Swiatkowski  * @tun_type: tunnel type
55671b699f81SAlexander Lobakin  *
55681b699f81SAlexander Lobakin  * Returns the &ice_dummy_pkt_profile corresponding to these lookup params.
55690f94570dSGrishma Kotecha  */
5570e33163a4SAlexander Lobakin static const struct ice_dummy_pkt_profile *
55710f94570dSGrishma Kotecha ice_find_dummy_packet(struct ice_adv_lkup_elem *lkups, u16 lkups_cnt,
55721b699f81SAlexander Lobakin 		      enum ice_sw_tunnel_type tun_type)
55730f94570dSGrishma Kotecha {
5574e33163a4SAlexander Lobakin 	const struct ice_dummy_pkt_profile *ret = ice_dummy_pkt_profiles;
557526395726SMartyna Szapar-Mudlaw 	u32 match = 0, vlan_count = 0;
55760f94570dSGrishma Kotecha 	u16 i;
55770f94570dSGrishma Kotecha 
5578e33163a4SAlexander Lobakin 	switch (tun_type) {
5579e33163a4SAlexander Lobakin 	case ICE_SW_TUN_GTPC:
5580e33163a4SAlexander Lobakin 		match |= ICE_PKT_TUN_GTPC;
5581e33163a4SAlexander Lobakin 		break;
5582e33163a4SAlexander Lobakin 	case ICE_SW_TUN_GTPU:
5583e33163a4SAlexander Lobakin 		match |= ICE_PKT_TUN_GTPU;
5584e33163a4SAlexander Lobakin 		break;
5585e33163a4SAlexander Lobakin 	case ICE_SW_TUN_NVGRE:
5586e33163a4SAlexander Lobakin 		match |= ICE_PKT_TUN_NVGRE;
5587e33163a4SAlexander Lobakin 		break;
5588e33163a4SAlexander Lobakin 	case ICE_SW_TUN_GENEVE:
5589e33163a4SAlexander Lobakin 	case ICE_SW_TUN_VXLAN:
5590e33163a4SAlexander Lobakin 		match |= ICE_PKT_TUN_UDP;
5591e33163a4SAlexander Lobakin 		break;
5592e33163a4SAlexander Lobakin 	default:
5593e33163a4SAlexander Lobakin 		break;
5594e33163a4SAlexander Lobakin 	}
5595e33163a4SAlexander Lobakin 
55960f94570dSGrishma Kotecha 	for (i = 0; i < lkups_cnt; i++) {
55970f94570dSGrishma Kotecha 		if (lkups[i].type == ICE_UDP_ILOS)
5598e33163a4SAlexander Lobakin 			match |= ICE_PKT_INNER_UDP;
55990f94570dSGrishma Kotecha 		else if (lkups[i].type == ICE_TCP_IL)
5600e33163a4SAlexander Lobakin 			match |= ICE_PKT_INNER_TCP;
56010f94570dSGrishma Kotecha 		else if (lkups[i].type == ICE_IPV6_OFOS)
5602e33163a4SAlexander Lobakin 			match |= ICE_PKT_OUTER_IPV6;
560306bca7c2SMartyna Szapar-Mudlaw 		else if (lkups[i].type == ICE_VLAN_OFOS ||
560406bca7c2SMartyna Szapar-Mudlaw 			 lkups[i].type == ICE_VLAN_EX)
560526395726SMartyna Szapar-Mudlaw 			vlan_count++;
560606bca7c2SMartyna Szapar-Mudlaw 		else if (lkups[i].type == ICE_VLAN_IN)
560726395726SMartyna Szapar-Mudlaw 			vlan_count++;
56080f94570dSGrishma Kotecha 		else if (lkups[i].type == ICE_ETYPE_OL &&
56090f94570dSGrishma Kotecha 			 lkups[i].h_u.ethertype.ethtype_id ==
56100f94570dSGrishma Kotecha 				cpu_to_be16(ICE_IPV6_ETHER_ID) &&
56110f94570dSGrishma Kotecha 			 lkups[i].m_u.ethertype.ethtype_id ==
56120f94570dSGrishma Kotecha 				cpu_to_be16(0xFFFF))
5613e33163a4SAlexander Lobakin 			match |= ICE_PKT_OUTER_IPV6;
561434a89775SMartyna Szapar-Mudlaw 		else if (lkups[i].type == ICE_ETYPE_IL &&
561534a89775SMartyna Szapar-Mudlaw 			 lkups[i].h_u.ethertype.ethtype_id ==
561634a89775SMartyna Szapar-Mudlaw 				cpu_to_be16(ICE_IPV6_ETHER_ID) &&
561734a89775SMartyna Szapar-Mudlaw 			 lkups[i].m_u.ethertype.ethtype_id ==
561834a89775SMartyna Szapar-Mudlaw 				cpu_to_be16(0xFFFF))
5619e33163a4SAlexander Lobakin 			match |= ICE_PKT_INNER_IPV6;
56209a225f81SMarcin Szycik 		else if (lkups[i].type == ICE_IPV6_IL)
5621e33163a4SAlexander Lobakin 			match |= ICE_PKT_INNER_IPV6;
56229a225f81SMarcin Szycik 		else if (lkups[i].type == ICE_GTP_NO_PAY)
5623e33163a4SAlexander Lobakin 			match |= ICE_PKT_GTP_NOPAY;
5624cd8efeeeSMarcin Szycik 		else if (lkups[i].type == ICE_PPPOE) {
5625cd8efeeeSMarcin Szycik 			match |= ICE_PKT_PPPOE;
5626cd8efeeeSMarcin Szycik 			if (lkups[i].h_u.pppoe_hdr.ppp_prot_id ==
5627cd8efeeeSMarcin Szycik 			    htons(PPP_IPV6))
5628cd8efeeeSMarcin Szycik 				match |= ICE_PKT_OUTER_IPV6;
5629cd634549SMarcin Szycik 		} else if (lkups[i].type == ICE_L2TPV3)
5630cd634549SMarcin Szycik 			match |= ICE_PKT_L2TPV3;
56319a225f81SMarcin Szycik 	}
56329a225f81SMarcin Szycik 
5633e33163a4SAlexander Lobakin 	while (ret->match && (match & ret->match) != ret->match)
5634e33163a4SAlexander Lobakin 		ret++;
56359a225f81SMarcin Szycik 
563626395726SMartyna Szapar-Mudlaw 	if (vlan_count != 0)
563726395726SMartyna Szapar-Mudlaw 		ret = ice_dummy_packet_add_vlan(ret, vlan_count);
563826395726SMartyna Szapar-Mudlaw 
5639e33163a4SAlexander Lobakin 	return ret;
56400f94570dSGrishma Kotecha }
56410f94570dSGrishma Kotecha 
56420f94570dSGrishma Kotecha /**
56430f94570dSGrishma Kotecha  * ice_fill_adv_dummy_packet - fill a dummy packet with given match criteria
56440f94570dSGrishma Kotecha  *
56450f94570dSGrishma Kotecha  * @lkups: lookup elements or match criteria for the advanced recipe, one
56460f94570dSGrishma Kotecha  *	   structure per protocol header
56470f94570dSGrishma Kotecha  * @lkups_cnt: number of protocols
56480f94570dSGrishma Kotecha  * @s_rule: stores rule information from the match criteria
56491b699f81SAlexander Lobakin  * @profile: dummy packet profile (the template, its size and header offsets)
56500f94570dSGrishma Kotecha  */
56515e24d598STony Nguyen static int
56520f94570dSGrishma Kotecha ice_fill_adv_dummy_packet(struct ice_adv_lkup_elem *lkups, u16 lkups_cnt,
56536e1ff618SAlexander Lobakin 			  struct ice_sw_rule_lkup_rx_tx *s_rule,
56541b699f81SAlexander Lobakin 			  const struct ice_dummy_pkt_profile *profile)
56550f94570dSGrishma Kotecha {
56560f94570dSGrishma Kotecha 	u8 *pkt;
56570f94570dSGrishma Kotecha 	u16 i;
56580f94570dSGrishma Kotecha 
56590f94570dSGrishma Kotecha 	/* Start with a packet with a pre-defined/dummy content. Then, fill
56600f94570dSGrishma Kotecha 	 * in the header values to be looked up or matched.
56610f94570dSGrishma Kotecha 	 */
56626e1ff618SAlexander Lobakin 	pkt = s_rule->hdr_data;
56630f94570dSGrishma Kotecha 
56641b699f81SAlexander Lobakin 	memcpy(pkt, profile->pkt, profile->pkt_len);
56650f94570dSGrishma Kotecha 
56660f94570dSGrishma Kotecha 	for (i = 0; i < lkups_cnt; i++) {
56671b699f81SAlexander Lobakin 		const struct ice_dummy_pkt_offsets *offsets = profile->offsets;
56680f94570dSGrishma Kotecha 		enum ice_protocol_type type;
56690f94570dSGrishma Kotecha 		u16 offset = 0, len = 0, j;
56700f94570dSGrishma Kotecha 		bool found = false;
56710f94570dSGrishma Kotecha 
56720f94570dSGrishma Kotecha 		/* find the start of this layer; it should be found since this
56730f94570dSGrishma Kotecha 		 * was already checked when search for the dummy packet
56740f94570dSGrishma Kotecha 		 */
56750f94570dSGrishma Kotecha 		type = lkups[i].type;
567603592a14SMichal Swiatkowski 		/* metadata isn't present in the packet */
567703592a14SMichal Swiatkowski 		if (type == ICE_HW_METADATA)
567803592a14SMichal Swiatkowski 			continue;
567903592a14SMichal Swiatkowski 
56800f94570dSGrishma Kotecha 		for (j = 0; offsets[j].type != ICE_PROTOCOL_LAST; j++) {
56810f94570dSGrishma Kotecha 			if (type == offsets[j].type) {
56820f94570dSGrishma Kotecha 				offset = offsets[j].offset;
56830f94570dSGrishma Kotecha 				found = true;
56840f94570dSGrishma Kotecha 				break;
56850f94570dSGrishma Kotecha 			}
56860f94570dSGrishma Kotecha 		}
56870f94570dSGrishma Kotecha 		/* this should never happen in a correct calling sequence */
56880f94570dSGrishma Kotecha 		if (!found)
5689d54699e2STony Nguyen 			return -EINVAL;
56900f94570dSGrishma Kotecha 
56910f94570dSGrishma Kotecha 		switch (lkups[i].type) {
56920f94570dSGrishma Kotecha 		case ICE_MAC_OFOS:
56930f94570dSGrishma Kotecha 		case ICE_MAC_IL:
56940f94570dSGrishma Kotecha 			len = sizeof(struct ice_ether_hdr);
56950f94570dSGrishma Kotecha 			break;
56960f94570dSGrishma Kotecha 		case ICE_ETYPE_OL:
569734a89775SMartyna Szapar-Mudlaw 		case ICE_ETYPE_IL:
56980f94570dSGrishma Kotecha 			len = sizeof(struct ice_ethtype_hdr);
56990f94570dSGrishma Kotecha 			break;
57000f94570dSGrishma Kotecha 		case ICE_VLAN_OFOS:
570106bca7c2SMartyna Szapar-Mudlaw 		case ICE_VLAN_EX:
570206bca7c2SMartyna Szapar-Mudlaw 		case ICE_VLAN_IN:
57030f94570dSGrishma Kotecha 			len = sizeof(struct ice_vlan_hdr);
57040f94570dSGrishma Kotecha 			break;
57050f94570dSGrishma Kotecha 		case ICE_IPV4_OFOS:
57060f94570dSGrishma Kotecha 		case ICE_IPV4_IL:
57070f94570dSGrishma Kotecha 			len = sizeof(struct ice_ipv4_hdr);
57080f94570dSGrishma Kotecha 			break;
57090f94570dSGrishma Kotecha 		case ICE_IPV6_OFOS:
57100f94570dSGrishma Kotecha 		case ICE_IPV6_IL:
57110f94570dSGrishma Kotecha 			len = sizeof(struct ice_ipv6_hdr);
57120f94570dSGrishma Kotecha 			break;
57130f94570dSGrishma Kotecha 		case ICE_TCP_IL:
57140f94570dSGrishma Kotecha 		case ICE_UDP_OF:
57150f94570dSGrishma Kotecha 		case ICE_UDP_ILOS:
57160f94570dSGrishma Kotecha 			len = sizeof(struct ice_l4_hdr);
57170f94570dSGrishma Kotecha 			break;
57180f94570dSGrishma Kotecha 		case ICE_SCTP_IL:
57190f94570dSGrishma Kotecha 			len = sizeof(struct ice_sctp_hdr);
57200f94570dSGrishma Kotecha 			break;
5721f0a35040SMichal Swiatkowski 		case ICE_NVGRE:
5722f0a35040SMichal Swiatkowski 			len = sizeof(struct ice_nvgre_hdr);
5723f0a35040SMichal Swiatkowski 			break;
57248b032a55SMichal Swiatkowski 		case ICE_VXLAN:
57258b032a55SMichal Swiatkowski 		case ICE_GENEVE:
57268b032a55SMichal Swiatkowski 			len = sizeof(struct ice_udp_tnl_hdr);
57278b032a55SMichal Swiatkowski 			break;
57289a225f81SMarcin Szycik 		case ICE_GTP_NO_PAY:
57299a225f81SMarcin Szycik 		case ICE_GTP:
57309a225f81SMarcin Szycik 			len = sizeof(struct ice_udp_gtp_hdr);
57319a225f81SMarcin Szycik 			break;
5732cd8efeeeSMarcin Szycik 		case ICE_PPPOE:
5733cd8efeeeSMarcin Szycik 			len = sizeof(struct ice_pppoe_hdr);
5734cd8efeeeSMarcin Szycik 			break;
5735cd634549SMarcin Szycik 		case ICE_L2TPV3:
5736cd634549SMarcin Szycik 			len = sizeof(struct ice_l2tpv3_sess_hdr);
5737cd634549SMarcin Szycik 			break;
57380f94570dSGrishma Kotecha 		default:
5739d54699e2STony Nguyen 			return -EINVAL;
57400f94570dSGrishma Kotecha 		}
57410f94570dSGrishma Kotecha 
57420f94570dSGrishma Kotecha 		/* the length should be a word multiple */
57430f94570dSGrishma Kotecha 		if (len % ICE_BYTES_PER_WORD)
5744d54699e2STony Nguyen 			return -EIO;
57450f94570dSGrishma Kotecha 
57460f94570dSGrishma Kotecha 		/* We have the offset to the header start, the length, the
57470f94570dSGrishma Kotecha 		 * caller's header values and mask. Use this information to
57480f94570dSGrishma Kotecha 		 * copy the data into the dummy packet appropriately based on
57490f94570dSGrishma Kotecha 		 * the mask. Note that we need to only write the bits as
57500f94570dSGrishma Kotecha 		 * indicated by the mask to make sure we don't improperly write
57510f94570dSGrishma Kotecha 		 * over any significant packet data.
57520f94570dSGrishma Kotecha 		 */
575327ffa273SAlexander Lobakin 		for (j = 0; j < len / sizeof(u16); j++) {
575427ffa273SAlexander Lobakin 			u16 *ptr = (u16 *)(pkt + offset);
575527ffa273SAlexander Lobakin 			u16 mask = lkups[i].m_raw[j];
575627ffa273SAlexander Lobakin 
575727ffa273SAlexander Lobakin 			if (!mask)
575827ffa273SAlexander Lobakin 				continue;
575927ffa273SAlexander Lobakin 
576027ffa273SAlexander Lobakin 			ptr[j] = (ptr[j] & ~mask) | (lkups[i].h_raw[j] & mask);
576127ffa273SAlexander Lobakin 		}
57620f94570dSGrishma Kotecha 	}
57630f94570dSGrishma Kotecha 
57646e1ff618SAlexander Lobakin 	s_rule->hdr_len = cpu_to_le16(profile->pkt_len);
57650f94570dSGrishma Kotecha 
57660f94570dSGrishma Kotecha 	return 0;
57670f94570dSGrishma Kotecha }
57680f94570dSGrishma Kotecha 
57690f94570dSGrishma Kotecha /**
57708b032a55SMichal Swiatkowski  * ice_fill_adv_packet_tun - fill dummy packet with udp tunnel port
57718b032a55SMichal Swiatkowski  * @hw: pointer to the hardware structure
57728b032a55SMichal Swiatkowski  * @tun_type: tunnel type
57738b032a55SMichal Swiatkowski  * @pkt: dummy packet to fill in
57748b032a55SMichal Swiatkowski  * @offsets: offset info for the dummy packet
57758b032a55SMichal Swiatkowski  */
5776d54699e2STony Nguyen static int
57778b032a55SMichal Swiatkowski ice_fill_adv_packet_tun(struct ice_hw *hw, enum ice_sw_tunnel_type tun_type,
57788b032a55SMichal Swiatkowski 			u8 *pkt, const struct ice_dummy_pkt_offsets *offsets)
57798b032a55SMichal Swiatkowski {
57808b032a55SMichal Swiatkowski 	u16 open_port, i;
57818b032a55SMichal Swiatkowski 
57828b032a55SMichal Swiatkowski 	switch (tun_type) {
57838b032a55SMichal Swiatkowski 	case ICE_SW_TUN_VXLAN:
5784de6acd1cSMichal Swiatkowski 		if (!ice_get_open_tunnel_port(hw, &open_port, TNL_VXLAN))
5785d54699e2STony Nguyen 			return -EIO;
57868b032a55SMichal Swiatkowski 		break;
5787de6acd1cSMichal Swiatkowski 	case ICE_SW_TUN_GENEVE:
5788de6acd1cSMichal Swiatkowski 		if (!ice_get_open_tunnel_port(hw, &open_port, TNL_GENEVE))
5789d54699e2STony Nguyen 			return -EIO;
5790de6acd1cSMichal Swiatkowski 		break;
57918b032a55SMichal Swiatkowski 	default:
57928b032a55SMichal Swiatkowski 		/* Nothing needs to be done for this tunnel type */
57938b032a55SMichal Swiatkowski 		return 0;
57948b032a55SMichal Swiatkowski 	}
57958b032a55SMichal Swiatkowski 
57968b032a55SMichal Swiatkowski 	/* Find the outer UDP protocol header and insert the port number */
57978b032a55SMichal Swiatkowski 	for (i = 0; offsets[i].type != ICE_PROTOCOL_LAST; i++) {
57988b032a55SMichal Swiatkowski 		if (offsets[i].type == ICE_UDP_OF) {
57998b032a55SMichal Swiatkowski 			struct ice_l4_hdr *hdr;
58008b032a55SMichal Swiatkowski 			u16 offset;
58018b032a55SMichal Swiatkowski 
58028b032a55SMichal Swiatkowski 			offset = offsets[i].offset;
58038b032a55SMichal Swiatkowski 			hdr = (struct ice_l4_hdr *)&pkt[offset];
58048b032a55SMichal Swiatkowski 			hdr->dst_port = cpu_to_be16(open_port);
58058b032a55SMichal Swiatkowski 
58068b032a55SMichal Swiatkowski 			return 0;
58078b032a55SMichal Swiatkowski 		}
58088b032a55SMichal Swiatkowski 	}
58098b032a55SMichal Swiatkowski 
5810d54699e2STony Nguyen 	return -EIO;
58118b032a55SMichal Swiatkowski }
58128b032a55SMichal Swiatkowski 
58138b032a55SMichal Swiatkowski /**
5814ea71b967SMartyna Szapar-Mudlaw  * ice_fill_adv_packet_vlan - fill dummy packet with VLAN tag type
581503592a14SMichal Swiatkowski  * @hw: pointer to hw structure
5816ea71b967SMartyna Szapar-Mudlaw  * @vlan_type: VLAN tag type
5817ea71b967SMartyna Szapar-Mudlaw  * @pkt: dummy packet to fill in
5818ea71b967SMartyna Szapar-Mudlaw  * @offsets: offset info for the dummy packet
5819ea71b967SMartyna Szapar-Mudlaw  */
5820ea71b967SMartyna Szapar-Mudlaw static int
582103592a14SMichal Swiatkowski ice_fill_adv_packet_vlan(struct ice_hw *hw, u16 vlan_type, u8 *pkt,
5822ea71b967SMartyna Szapar-Mudlaw 			 const struct ice_dummy_pkt_offsets *offsets)
5823ea71b967SMartyna Szapar-Mudlaw {
5824ea71b967SMartyna Szapar-Mudlaw 	u16 i;
5825ea71b967SMartyna Szapar-Mudlaw 
582603592a14SMichal Swiatkowski 	/* Check if there is something to do */
582703592a14SMichal Swiatkowski 	if (!vlan_type || !ice_is_dvm_ena(hw))
582803592a14SMichal Swiatkowski 		return 0;
582903592a14SMichal Swiatkowski 
5830ea71b967SMartyna Szapar-Mudlaw 	/* Find VLAN header and insert VLAN TPID */
5831ea71b967SMartyna Szapar-Mudlaw 	for (i = 0; offsets[i].type != ICE_PROTOCOL_LAST; i++) {
5832ea71b967SMartyna Szapar-Mudlaw 		if (offsets[i].type == ICE_VLAN_OFOS ||
5833ea71b967SMartyna Szapar-Mudlaw 		    offsets[i].type == ICE_VLAN_EX) {
5834ea71b967SMartyna Szapar-Mudlaw 			struct ice_vlan_hdr *hdr;
5835ea71b967SMartyna Szapar-Mudlaw 			u16 offset;
5836ea71b967SMartyna Szapar-Mudlaw 
5837ea71b967SMartyna Szapar-Mudlaw 			offset = offsets[i].offset;
5838ea71b967SMartyna Szapar-Mudlaw 			hdr = (struct ice_vlan_hdr *)&pkt[offset];
5839ea71b967SMartyna Szapar-Mudlaw 			hdr->type = cpu_to_be16(vlan_type);
5840ea71b967SMartyna Szapar-Mudlaw 
5841ea71b967SMartyna Szapar-Mudlaw 			return 0;
5842ea71b967SMartyna Szapar-Mudlaw 		}
5843ea71b967SMartyna Szapar-Mudlaw 	}
5844ea71b967SMartyna Szapar-Mudlaw 
5845ea71b967SMartyna Szapar-Mudlaw 	return -EIO;
5846ea71b967SMartyna Szapar-Mudlaw }
5847ea71b967SMartyna Szapar-Mudlaw 
584803592a14SMichal Swiatkowski static bool ice_rules_equal(const struct ice_adv_rule_info *first,
584903592a14SMichal Swiatkowski 			    const struct ice_adv_rule_info *second)
585003592a14SMichal Swiatkowski {
585103592a14SMichal Swiatkowski 	return first->sw_act.flag == second->sw_act.flag &&
585203592a14SMichal Swiatkowski 	       first->tun_type == second->tun_type &&
585303592a14SMichal Swiatkowski 	       first->vlan_type == second->vlan_type &&
5854bccd9bceSMarcin Szycik 	       first->src_vsi == second->src_vsi &&
5855bccd9bceSMarcin Szycik 	       first->need_pass_l2 == second->need_pass_l2 &&
5856bccd9bceSMarcin Szycik 	       first->allow_pass_l2 == second->allow_pass_l2;
585703592a14SMichal Swiatkowski }
585803592a14SMichal Swiatkowski 
5859ea71b967SMartyna Szapar-Mudlaw /**
58600f94570dSGrishma Kotecha  * ice_find_adv_rule_entry - Search a rule entry
58610f94570dSGrishma Kotecha  * @hw: pointer to the hardware structure
58620f94570dSGrishma Kotecha  * @lkups: lookup elements or match criteria for the advanced recipe, one
58630f94570dSGrishma Kotecha  *	   structure per protocol header
58640f94570dSGrishma Kotecha  * @lkups_cnt: number of protocols
58650f94570dSGrishma Kotecha  * @recp_id: recipe ID for which we are finding the rule
58660f94570dSGrishma Kotecha  * @rinfo: other information regarding the rule e.g. priority and action info
58670f94570dSGrishma Kotecha  *
58680f94570dSGrishma Kotecha  * Helper function to search for a given advance rule entry
58690f94570dSGrishma Kotecha  * Returns pointer to entry storing the rule if found
58700f94570dSGrishma Kotecha  */
58710f94570dSGrishma Kotecha static struct ice_adv_fltr_mgmt_list_entry *
58720f94570dSGrishma Kotecha ice_find_adv_rule_entry(struct ice_hw *hw, struct ice_adv_lkup_elem *lkups,
58730f94570dSGrishma Kotecha 			u16 lkups_cnt, u16 recp_id,
58740f94570dSGrishma Kotecha 			struct ice_adv_rule_info *rinfo)
58750f94570dSGrishma Kotecha {
58760f94570dSGrishma Kotecha 	struct ice_adv_fltr_mgmt_list_entry *list_itr;
58770f94570dSGrishma Kotecha 	struct ice_switch_info *sw = hw->switch_info;
58780f94570dSGrishma Kotecha 	int i;
58790f94570dSGrishma Kotecha 
58800f94570dSGrishma Kotecha 	list_for_each_entry(list_itr, &sw->recp_list[recp_id].filt_rules,
58810f94570dSGrishma Kotecha 			    list_entry) {
58820f94570dSGrishma Kotecha 		bool lkups_matched = true;
58830f94570dSGrishma Kotecha 
58840f94570dSGrishma Kotecha 		if (lkups_cnt != list_itr->lkups_cnt)
58850f94570dSGrishma Kotecha 			continue;
58860f94570dSGrishma Kotecha 		for (i = 0; i < list_itr->lkups_cnt; i++)
58870f94570dSGrishma Kotecha 			if (memcmp(&list_itr->lkups[i], &lkups[i],
58880f94570dSGrishma Kotecha 				   sizeof(*lkups))) {
58890f94570dSGrishma Kotecha 				lkups_matched = false;
58900f94570dSGrishma Kotecha 				break;
58910f94570dSGrishma Kotecha 			}
589203592a14SMichal Swiatkowski 		if (ice_rules_equal(rinfo, &list_itr->rule_info) &&
58930f94570dSGrishma Kotecha 		    lkups_matched)
58940f94570dSGrishma Kotecha 			return list_itr;
58950f94570dSGrishma Kotecha 	}
58960f94570dSGrishma Kotecha 	return NULL;
58970f94570dSGrishma Kotecha }
58980f94570dSGrishma Kotecha 
58990f94570dSGrishma Kotecha /**
59000f94570dSGrishma Kotecha  * ice_adv_add_update_vsi_list
59010f94570dSGrishma Kotecha  * @hw: pointer to the hardware structure
59020f94570dSGrishma Kotecha  * @m_entry: pointer to current adv filter management list entry
59030f94570dSGrishma Kotecha  * @cur_fltr: filter information from the book keeping entry
59040f94570dSGrishma Kotecha  * @new_fltr: filter information with the new VSI to be added
59050f94570dSGrishma Kotecha  *
59060f94570dSGrishma Kotecha  * Call AQ command to add or update previously created VSI list with new VSI.
59070f94570dSGrishma Kotecha  *
59080f94570dSGrishma Kotecha  * Helper function to do book keeping associated with adding filter information
59090f94570dSGrishma Kotecha  * The algorithm to do the booking keeping is described below :
59100f94570dSGrishma Kotecha  * When a VSI needs to subscribe to a given advanced filter
59110f94570dSGrishma Kotecha  *	if only one VSI has been added till now
59120f94570dSGrishma Kotecha  *		Allocate a new VSI list and add two VSIs
59130f94570dSGrishma Kotecha  *		to this list using switch rule command
59140f94570dSGrishma Kotecha  *		Update the previously created switch rule with the
59150f94570dSGrishma Kotecha  *		newly created VSI list ID
59160f94570dSGrishma Kotecha  *	if a VSI list was previously created
59170f94570dSGrishma Kotecha  *		Add the new VSI to the previously created VSI list set
59180f94570dSGrishma Kotecha  *		using the update switch rule command
59190f94570dSGrishma Kotecha  */
59205e24d598STony Nguyen static int
59210f94570dSGrishma Kotecha ice_adv_add_update_vsi_list(struct ice_hw *hw,
59220f94570dSGrishma Kotecha 			    struct ice_adv_fltr_mgmt_list_entry *m_entry,
59230f94570dSGrishma Kotecha 			    struct ice_adv_rule_info *cur_fltr,
59240f94570dSGrishma Kotecha 			    struct ice_adv_rule_info *new_fltr)
59250f94570dSGrishma Kotecha {
59260f94570dSGrishma Kotecha 	u16 vsi_list_id = 0;
59275518ac2aSTony Nguyen 	int status;
59280f94570dSGrishma Kotecha 
59290f94570dSGrishma Kotecha 	if (cur_fltr->sw_act.fltr_act == ICE_FWD_TO_Q ||
59300f94570dSGrishma Kotecha 	    cur_fltr->sw_act.fltr_act == ICE_FWD_TO_QGRP ||
59310f94570dSGrishma Kotecha 	    cur_fltr->sw_act.fltr_act == ICE_DROP_PACKET)
5932d54699e2STony Nguyen 		return -EOPNOTSUPP;
59330f94570dSGrishma Kotecha 
59340f94570dSGrishma Kotecha 	if ((new_fltr->sw_act.fltr_act == ICE_FWD_TO_Q ||
59350f94570dSGrishma Kotecha 	     new_fltr->sw_act.fltr_act == ICE_FWD_TO_QGRP) &&
59360f94570dSGrishma Kotecha 	    (cur_fltr->sw_act.fltr_act == ICE_FWD_TO_VSI ||
59370f94570dSGrishma Kotecha 	     cur_fltr->sw_act.fltr_act == ICE_FWD_TO_VSI_LIST))
5938d54699e2STony Nguyen 		return -EOPNOTSUPP;
59390f94570dSGrishma Kotecha 
59400f94570dSGrishma Kotecha 	if (m_entry->vsi_count < 2 && !m_entry->vsi_list_info) {
59410f94570dSGrishma Kotecha 		 /* Only one entry existed in the mapping and it was not already
59420f94570dSGrishma Kotecha 		  * a part of a VSI list. So, create a VSI list with the old and
59430f94570dSGrishma Kotecha 		  * new VSIs.
59440f94570dSGrishma Kotecha 		  */
59450f94570dSGrishma Kotecha 		struct ice_fltr_info tmp_fltr;
59460f94570dSGrishma Kotecha 		u16 vsi_handle_arr[2];
59470f94570dSGrishma Kotecha 
59480f94570dSGrishma Kotecha 		/* A rule already exists with the new VSI being added */
59490f94570dSGrishma Kotecha 		if (cur_fltr->sw_act.fwd_id.hw_vsi_id ==
59500f94570dSGrishma Kotecha 		    new_fltr->sw_act.fwd_id.hw_vsi_id)
5951d54699e2STony Nguyen 			return -EEXIST;
59520f94570dSGrishma Kotecha 
59530f94570dSGrishma Kotecha 		vsi_handle_arr[0] = cur_fltr->sw_act.vsi_handle;
59540f94570dSGrishma Kotecha 		vsi_handle_arr[1] = new_fltr->sw_act.vsi_handle;
59550f94570dSGrishma Kotecha 		status = ice_create_vsi_list_rule(hw, &vsi_handle_arr[0], 2,
59560f94570dSGrishma Kotecha 						  &vsi_list_id,
59570f94570dSGrishma Kotecha 						  ICE_SW_LKUP_LAST);
59580f94570dSGrishma Kotecha 		if (status)
59590f94570dSGrishma Kotecha 			return status;
59600f94570dSGrishma Kotecha 
59610f94570dSGrishma Kotecha 		memset(&tmp_fltr, 0, sizeof(tmp_fltr));
59620f94570dSGrishma Kotecha 		tmp_fltr.flag = m_entry->rule_info.sw_act.flag;
59630f94570dSGrishma Kotecha 		tmp_fltr.fltr_rule_id = cur_fltr->fltr_rule_id;
59640f94570dSGrishma Kotecha 		tmp_fltr.fltr_act = ICE_FWD_TO_VSI_LIST;
59650f94570dSGrishma Kotecha 		tmp_fltr.fwd_id.vsi_list_id = vsi_list_id;
59660f94570dSGrishma Kotecha 		tmp_fltr.lkup_type = ICE_SW_LKUP_LAST;
59670f94570dSGrishma Kotecha 
59680f94570dSGrishma Kotecha 		/* Update the previous switch rule of "forward to VSI" to
59690f94570dSGrishma Kotecha 		 * "fwd to VSI list"
59700f94570dSGrishma Kotecha 		 */
59710f94570dSGrishma Kotecha 		status = ice_update_pkt_fwd_rule(hw, &tmp_fltr);
59720f94570dSGrishma Kotecha 		if (status)
59730f94570dSGrishma Kotecha 			return status;
59740f94570dSGrishma Kotecha 
59750f94570dSGrishma Kotecha 		cur_fltr->sw_act.fwd_id.vsi_list_id = vsi_list_id;
59760f94570dSGrishma Kotecha 		cur_fltr->sw_act.fltr_act = ICE_FWD_TO_VSI_LIST;
59770f94570dSGrishma Kotecha 		m_entry->vsi_list_info =
59780f94570dSGrishma Kotecha 			ice_create_vsi_list_map(hw, &vsi_handle_arr[0], 2,
59790f94570dSGrishma Kotecha 						vsi_list_id);
59800f94570dSGrishma Kotecha 	} else {
59810f94570dSGrishma Kotecha 		u16 vsi_handle = new_fltr->sw_act.vsi_handle;
59820f94570dSGrishma Kotecha 
59830f94570dSGrishma Kotecha 		if (!m_entry->vsi_list_info)
5984d54699e2STony Nguyen 			return -EIO;
59850f94570dSGrishma Kotecha 
59860f94570dSGrishma Kotecha 		/* A rule already exists with the new VSI being added */
59870f94570dSGrishma Kotecha 		if (test_bit(vsi_handle, m_entry->vsi_list_info->vsi_map))
59880f94570dSGrishma Kotecha 			return 0;
59890f94570dSGrishma Kotecha 
59900f94570dSGrishma Kotecha 		/* Update the previously created VSI list set with
59910f94570dSGrishma Kotecha 		 * the new VSI ID passed in
59920f94570dSGrishma Kotecha 		 */
59930f94570dSGrishma Kotecha 		vsi_list_id = cur_fltr->sw_act.fwd_id.vsi_list_id;
59940f94570dSGrishma Kotecha 
59950f94570dSGrishma Kotecha 		status = ice_update_vsi_list_rule(hw, &vsi_handle, 1,
59960f94570dSGrishma Kotecha 						  vsi_list_id, false,
59970f94570dSGrishma Kotecha 						  ice_aqc_opc_update_sw_rules,
59980f94570dSGrishma Kotecha 						  ICE_SW_LKUP_LAST);
59990f94570dSGrishma Kotecha 		/* update VSI list mapping info with new VSI ID */
60000f94570dSGrishma Kotecha 		if (!status)
60010f94570dSGrishma Kotecha 			set_bit(vsi_handle, m_entry->vsi_list_info->vsi_map);
60020f94570dSGrishma Kotecha 	}
60030f94570dSGrishma Kotecha 	if (!status)
60040f94570dSGrishma Kotecha 		m_entry->vsi_count++;
60050f94570dSGrishma Kotecha 	return status;
60060f94570dSGrishma Kotecha }
60070f94570dSGrishma Kotecha 
600803592a14SMichal Swiatkowski void ice_rule_add_tunnel_metadata(struct ice_adv_lkup_elem *lkup)
600903592a14SMichal Swiatkowski {
601003592a14SMichal Swiatkowski 	lkup->type = ICE_HW_METADATA;
601141ad9f8eSMarcin Szycik 	lkup->m_u.metadata.flags[ICE_PKT_FLAGS_MDID21] |=
601203592a14SMichal Swiatkowski 		cpu_to_be16(ICE_PKT_TUNNEL_MASK);
601303592a14SMichal Swiatkowski }
601403592a14SMichal Swiatkowski 
60150960a27bSMarcin Szycik void ice_rule_add_direction_metadata(struct ice_adv_lkup_elem *lkup)
60160960a27bSMarcin Szycik {
60170960a27bSMarcin Szycik 	lkup->type = ICE_HW_METADATA;
601841ad9f8eSMarcin Szycik 	lkup->m_u.metadata.flags[ICE_PKT_FLAGS_MDID20] |=
60190960a27bSMarcin Szycik 		cpu_to_be16(ICE_PKT_FROM_NETWORK);
60200960a27bSMarcin Szycik }
60210960a27bSMarcin Szycik 
602203592a14SMichal Swiatkowski void ice_rule_add_vlan_metadata(struct ice_adv_lkup_elem *lkup)
602303592a14SMichal Swiatkowski {
602403592a14SMichal Swiatkowski 	lkup->type = ICE_HW_METADATA;
602541ad9f8eSMarcin Szycik 	lkup->m_u.metadata.flags[ICE_PKT_FLAGS_MDID20] |=
602603592a14SMichal Swiatkowski 		cpu_to_be16(ICE_PKT_VLAN_MASK);
602703592a14SMichal Swiatkowski }
602803592a14SMichal Swiatkowski 
60290ef4479dSMichal Swiatkowski void ice_rule_add_src_vsi_metadata(struct ice_adv_lkup_elem *lkup)
60300ef4479dSMichal Swiatkowski {
60310ef4479dSMichal Swiatkowski 	lkup->type = ICE_HW_METADATA;
60320ef4479dSMichal Swiatkowski 	lkup->m_u.metadata.source_vsi = cpu_to_be16(ICE_MDID_SOURCE_VSI_MASK);
60330ef4479dSMichal Swiatkowski }
60340ef4479dSMichal Swiatkowski 
60350f94570dSGrishma Kotecha /**
60360f94570dSGrishma Kotecha  * ice_add_adv_rule - helper function to create an advanced switch rule
60370f94570dSGrishma Kotecha  * @hw: pointer to the hardware structure
60380f94570dSGrishma Kotecha  * @lkups: information on the words that needs to be looked up. All words
60390f94570dSGrishma Kotecha  * together makes one recipe
60400f94570dSGrishma Kotecha  * @lkups_cnt: num of entries in the lkups array
60410f94570dSGrishma Kotecha  * @rinfo: other information related to the rule that needs to be programmed
60420f94570dSGrishma Kotecha  * @added_entry: this will return recipe_id, rule_id and vsi_handle. should be
60430f94570dSGrishma Kotecha  *               ignored is case of error.
60440f94570dSGrishma Kotecha  *
60450f94570dSGrishma Kotecha  * This function can program only 1 rule at a time. The lkups is used to
60460f94570dSGrishma Kotecha  * describe the all the words that forms the "lookup" portion of the recipe.
60470f94570dSGrishma Kotecha  * These words can span multiple protocols. Callers to this function need to
60480f94570dSGrishma Kotecha  * pass in a list of protocol headers with lookup information along and mask
60490f94570dSGrishma Kotecha  * that determines which words are valid from the given protocol header.
60500f94570dSGrishma Kotecha  * rinfo describes other information related to this rule such as forwarding
60510f94570dSGrishma Kotecha  * IDs, priority of this rule, etc.
60520f94570dSGrishma Kotecha  */
60535e24d598STony Nguyen int
60540f94570dSGrishma Kotecha ice_add_adv_rule(struct ice_hw *hw, struct ice_adv_lkup_elem *lkups,
60550f94570dSGrishma Kotecha 		 u16 lkups_cnt, struct ice_adv_rule_info *rinfo,
60560f94570dSGrishma Kotecha 		 struct ice_rule_query_data *added_entry)
60570f94570dSGrishma Kotecha {
60580f94570dSGrishma Kotecha 	struct ice_adv_fltr_mgmt_list_entry *m_entry, *adv_fltr = NULL;
60596e1ff618SAlexander Lobakin 	struct ice_sw_rule_lkup_rx_tx *s_rule = NULL;
6060e33163a4SAlexander Lobakin 	const struct ice_dummy_pkt_profile *profile;
60611b699f81SAlexander Lobakin 	u16 rid = 0, i, rule_buf_sz, vsi_handle;
60620f94570dSGrishma Kotecha 	struct list_head *rule_head;
60630f94570dSGrishma Kotecha 	struct ice_switch_info *sw;
60640f94570dSGrishma Kotecha 	u16 word_cnt;
60650f94570dSGrishma Kotecha 	u32 act = 0;
60665518ac2aSTony Nguyen 	int status;
60670f94570dSGrishma Kotecha 	u8 q_rgn;
60680f94570dSGrishma Kotecha 
60690f94570dSGrishma Kotecha 	/* Initialize profile to result index bitmap */
60700f94570dSGrishma Kotecha 	if (!hw->switch_info->prof_res_bm_init) {
60710f94570dSGrishma Kotecha 		hw->switch_info->prof_res_bm_init = 1;
60720f94570dSGrishma Kotecha 		ice_init_prof_result_bm(hw);
60730f94570dSGrishma Kotecha 	}
60740f94570dSGrishma Kotecha 
60750f94570dSGrishma Kotecha 	if (!lkups_cnt)
6076d54699e2STony Nguyen 		return -EINVAL;
60770f94570dSGrishma Kotecha 
60780f94570dSGrishma Kotecha 	/* get # of words we need to match */
60790f94570dSGrishma Kotecha 	word_cnt = 0;
60800f94570dSGrishma Kotecha 	for (i = 0; i < lkups_cnt; i++) {
6081135a161aSAlexander Lobakin 		u16 j;
60820f94570dSGrishma Kotecha 
6083135a161aSAlexander Lobakin 		for (j = 0; j < ARRAY_SIZE(lkups->m_raw); j++)
6084135a161aSAlexander Lobakin 			if (lkups[i].m_raw[j])
60850f94570dSGrishma Kotecha 				word_cnt++;
60860f94570dSGrishma Kotecha 	}
60870f94570dSGrishma Kotecha 
6088bd1ffe8eSWojciech Drewek 	if (!word_cnt)
6089d54699e2STony Nguyen 		return -EINVAL;
60900f94570dSGrishma Kotecha 
6091bd1ffe8eSWojciech Drewek 	if (word_cnt > ICE_MAX_CHAIN_WORDS)
6092bd1ffe8eSWojciech Drewek 		return -ENOSPC;
6093bd1ffe8eSWojciech Drewek 
60941b699f81SAlexander Lobakin 	/* locate a dummy packet */
60951b699f81SAlexander Lobakin 	profile = ice_find_dummy_packet(lkups, lkups_cnt, rinfo->tun_type);
609626395726SMartyna Szapar-Mudlaw 	if (IS_ERR(profile))
609726395726SMartyna Szapar-Mudlaw 		return PTR_ERR(profile);
60980f94570dSGrishma Kotecha 
60990f94570dSGrishma Kotecha 	if (!(rinfo->sw_act.fltr_act == ICE_FWD_TO_VSI ||
61000f94570dSGrishma Kotecha 	      rinfo->sw_act.fltr_act == ICE_FWD_TO_Q ||
61010f94570dSGrishma Kotecha 	      rinfo->sw_act.fltr_act == ICE_FWD_TO_QGRP ||
6102bccd9bceSMarcin Szycik 	      rinfo->sw_act.fltr_act == ICE_DROP_PACKET ||
6103bccd9bceSMarcin Szycik 	      rinfo->sw_act.fltr_act == ICE_NOP)) {
610426395726SMartyna Szapar-Mudlaw 		status = -EIO;
610526395726SMartyna Szapar-Mudlaw 		goto free_pkt_profile;
610626395726SMartyna Szapar-Mudlaw 	}
61070f94570dSGrishma Kotecha 
61080f94570dSGrishma Kotecha 	vsi_handle = rinfo->sw_act.vsi_handle;
610926395726SMartyna Szapar-Mudlaw 	if (!ice_is_vsi_valid(hw, vsi_handle)) {
611026395726SMartyna Szapar-Mudlaw 		status =  -EINVAL;
611126395726SMartyna Szapar-Mudlaw 		goto free_pkt_profile;
611226395726SMartyna Szapar-Mudlaw 	}
61130f94570dSGrishma Kotecha 
6114bccd9bceSMarcin Szycik 	if (rinfo->sw_act.fltr_act == ICE_FWD_TO_VSI ||
6115bccd9bceSMarcin Szycik 	    rinfo->sw_act.fltr_act == ICE_NOP)
61160f94570dSGrishma Kotecha 		rinfo->sw_act.fwd_id.hw_vsi_id =
61170f94570dSGrishma Kotecha 			ice_get_hw_vsi_num(hw, vsi_handle);
611803592a14SMichal Swiatkowski 
611903592a14SMichal Swiatkowski 	if (rinfo->src_vsi)
612003592a14SMichal Swiatkowski 		rinfo->sw_act.src = ice_get_hw_vsi_num(hw, rinfo->src_vsi);
612103592a14SMichal Swiatkowski 	else
61220f94570dSGrishma Kotecha 		rinfo->sw_act.src = ice_get_hw_vsi_num(hw, vsi_handle);
61230f94570dSGrishma Kotecha 
61240f94570dSGrishma Kotecha 	status = ice_add_adv_recipe(hw, lkups, lkups_cnt, rinfo, &rid);
61250f94570dSGrishma Kotecha 	if (status)
612626395726SMartyna Szapar-Mudlaw 		goto free_pkt_profile;
61270f94570dSGrishma Kotecha 	m_entry = ice_find_adv_rule_entry(hw, lkups, lkups_cnt, rid, rinfo);
61280f94570dSGrishma Kotecha 	if (m_entry) {
61290f94570dSGrishma Kotecha 		/* we have to add VSI to VSI_LIST and increment vsi_count.
61300f94570dSGrishma Kotecha 		 * Also Update VSI list so that we can change forwarding rule
61310f94570dSGrishma Kotecha 		 * if the rule already exists, we will check if it exists with
61320f94570dSGrishma Kotecha 		 * same vsi_id, if not then add it to the VSI list if it already
61330f94570dSGrishma Kotecha 		 * exists if not then create a VSI list and add the existing VSI
61340f94570dSGrishma Kotecha 		 * ID and the new VSI ID to the list
61350f94570dSGrishma Kotecha 		 * We will add that VSI to the list
61360f94570dSGrishma Kotecha 		 */
61370f94570dSGrishma Kotecha 		status = ice_adv_add_update_vsi_list(hw, m_entry,
61380f94570dSGrishma Kotecha 						     &m_entry->rule_info,
61390f94570dSGrishma Kotecha 						     rinfo);
61400f94570dSGrishma Kotecha 		if (added_entry) {
61410f94570dSGrishma Kotecha 			added_entry->rid = rid;
61420f94570dSGrishma Kotecha 			added_entry->rule_id = m_entry->rule_info.fltr_rule_id;
61430f94570dSGrishma Kotecha 			added_entry->vsi_handle = rinfo->sw_act.vsi_handle;
61440f94570dSGrishma Kotecha 		}
614526395726SMartyna Szapar-Mudlaw 		goto free_pkt_profile;
61460f94570dSGrishma Kotecha 	}
61476e1ff618SAlexander Lobakin 	rule_buf_sz = ICE_SW_RULE_RX_TX_HDR_SIZE(s_rule, profile->pkt_len);
61480f94570dSGrishma Kotecha 	s_rule = kzalloc(rule_buf_sz, GFP_KERNEL);
614926395726SMartyna Szapar-Mudlaw 	if (!s_rule) {
615026395726SMartyna Szapar-Mudlaw 		status = -ENOMEM;
615126395726SMartyna Szapar-Mudlaw 		goto free_pkt_profile;
615226395726SMartyna Szapar-Mudlaw 	}
615373b483b7SWojciech Drewek 	if (!rinfo->flags_info.act_valid) {
615473b483b7SWojciech Drewek 		act |= ICE_SINGLE_ACT_LAN_ENABLE;
615573b483b7SWojciech Drewek 		act |= ICE_SINGLE_ACT_LB_ENABLE;
615673b483b7SWojciech Drewek 	} else {
615773b483b7SWojciech Drewek 		act |= rinfo->flags_info.act & (ICE_SINGLE_ACT_LAN_ENABLE |
615873b483b7SWojciech Drewek 						ICE_SINGLE_ACT_LB_ENABLE);
615973b483b7SWojciech Drewek 	}
616073b483b7SWojciech Drewek 
61610f94570dSGrishma Kotecha 	switch (rinfo->sw_act.fltr_act) {
61620f94570dSGrishma Kotecha 	case ICE_FWD_TO_VSI:
61630f94570dSGrishma Kotecha 		act |= (rinfo->sw_act.fwd_id.hw_vsi_id <<
61640f94570dSGrishma Kotecha 			ICE_SINGLE_ACT_VSI_ID_S) & ICE_SINGLE_ACT_VSI_ID_M;
61650f94570dSGrishma Kotecha 		act |= ICE_SINGLE_ACT_VSI_FORWARDING | ICE_SINGLE_ACT_VALID_BIT;
61660f94570dSGrishma Kotecha 		break;
61670f94570dSGrishma Kotecha 	case ICE_FWD_TO_Q:
61680f94570dSGrishma Kotecha 		act |= ICE_SINGLE_ACT_TO_Q;
61690f94570dSGrishma Kotecha 		act |= (rinfo->sw_act.fwd_id.q_id << ICE_SINGLE_ACT_Q_INDEX_S) &
61700f94570dSGrishma Kotecha 		       ICE_SINGLE_ACT_Q_INDEX_M;
61710f94570dSGrishma Kotecha 		break;
61720f94570dSGrishma Kotecha 	case ICE_FWD_TO_QGRP:
61730f94570dSGrishma Kotecha 		q_rgn = rinfo->sw_act.qgrp_size > 0 ?
61740f94570dSGrishma Kotecha 			(u8)ilog2(rinfo->sw_act.qgrp_size) : 0;
61750f94570dSGrishma Kotecha 		act |= ICE_SINGLE_ACT_TO_Q;
61760f94570dSGrishma Kotecha 		act |= (rinfo->sw_act.fwd_id.q_id << ICE_SINGLE_ACT_Q_INDEX_S) &
61770f94570dSGrishma Kotecha 		       ICE_SINGLE_ACT_Q_INDEX_M;
61780f94570dSGrishma Kotecha 		act |= (q_rgn << ICE_SINGLE_ACT_Q_REGION_S) &
61790f94570dSGrishma Kotecha 		       ICE_SINGLE_ACT_Q_REGION_M;
61800f94570dSGrishma Kotecha 		break;
61810f94570dSGrishma Kotecha 	case ICE_DROP_PACKET:
61820f94570dSGrishma Kotecha 		act |= ICE_SINGLE_ACT_VSI_FORWARDING | ICE_SINGLE_ACT_DROP |
61830f94570dSGrishma Kotecha 		       ICE_SINGLE_ACT_VALID_BIT;
61840f94570dSGrishma Kotecha 		break;
6185bccd9bceSMarcin Szycik 	case ICE_NOP:
6186bccd9bceSMarcin Szycik 		act |= FIELD_PREP(ICE_SINGLE_ACT_VSI_ID_M,
6187bccd9bceSMarcin Szycik 				  rinfo->sw_act.fwd_id.hw_vsi_id);
6188bccd9bceSMarcin Szycik 		act &= ~ICE_SINGLE_ACT_VALID_BIT;
6189bccd9bceSMarcin Szycik 		break;
61900f94570dSGrishma Kotecha 	default:
6191d54699e2STony Nguyen 		status = -EIO;
61920f94570dSGrishma Kotecha 		goto err_ice_add_adv_rule;
61930f94570dSGrishma Kotecha 	}
61940f94570dSGrishma Kotecha 
619540fd7492SMichal Swiatkowski 	/* If there is no matching criteria for direction there
619640fd7492SMichal Swiatkowski 	 * is only one difference between Rx and Tx:
619740fd7492SMichal Swiatkowski 	 * - get switch id base on VSI number from source field (Tx)
619840fd7492SMichal Swiatkowski 	 * - get switch id base on port number (Rx)
61990f94570dSGrishma Kotecha 	 *
620040fd7492SMichal Swiatkowski 	 * If matching on direction metadata is chose rule direction is
620140fd7492SMichal Swiatkowski 	 * extracted from type value set here.
62020f94570dSGrishma Kotecha 	 */
620340fd7492SMichal Swiatkowski 	if (rinfo->sw_act.flag & ICE_FLTR_TX) {
62046e1ff618SAlexander Lobakin 		s_rule->hdr.type = cpu_to_le16(ICE_AQC_SW_RULES_T_LKUP_TX);
62056e1ff618SAlexander Lobakin 		s_rule->src = cpu_to_le16(rinfo->sw_act.src);
620640fd7492SMichal Swiatkowski 	} else {
620740fd7492SMichal Swiatkowski 		s_rule->hdr.type = cpu_to_le16(ICE_AQC_SW_RULES_T_LKUP_RX);
620840fd7492SMichal Swiatkowski 		s_rule->src = cpu_to_le16(hw->port_info->lport);
62090f94570dSGrishma Kotecha 	}
62100f94570dSGrishma Kotecha 
62116e1ff618SAlexander Lobakin 	s_rule->recipe_id = cpu_to_le16(rid);
62126e1ff618SAlexander Lobakin 	s_rule->act = cpu_to_le32(act);
62130f94570dSGrishma Kotecha 
6214e33163a4SAlexander Lobakin 	status = ice_fill_adv_dummy_packet(lkups, lkups_cnt, s_rule, profile);
62150f94570dSGrishma Kotecha 	if (status)
62160f94570dSGrishma Kotecha 		goto err_ice_add_adv_rule;
62170f94570dSGrishma Kotecha 
621803592a14SMichal Swiatkowski 	status = ice_fill_adv_packet_tun(hw, rinfo->tun_type, s_rule->hdr_data,
6219e33163a4SAlexander Lobakin 					 profile->offsets);
62208b032a55SMichal Swiatkowski 	if (status)
62218b032a55SMichal Swiatkowski 		goto err_ice_add_adv_rule;
62228b032a55SMichal Swiatkowski 
622303592a14SMichal Swiatkowski 	status = ice_fill_adv_packet_vlan(hw, rinfo->vlan_type,
6224ea71b967SMartyna Szapar-Mudlaw 					  s_rule->hdr_data,
6225ea71b967SMartyna Szapar-Mudlaw 					  profile->offsets);
6226ea71b967SMartyna Szapar-Mudlaw 	if (status)
6227ea71b967SMartyna Szapar-Mudlaw 		goto err_ice_add_adv_rule;
6228ea71b967SMartyna Szapar-Mudlaw 
62290f94570dSGrishma Kotecha 	status = ice_aq_sw_rules(hw, (struct ice_aqc_sw_rules *)s_rule,
62300f94570dSGrishma Kotecha 				 rule_buf_sz, 1, ice_aqc_opc_add_sw_rules,
62310f94570dSGrishma Kotecha 				 NULL);
62320f94570dSGrishma Kotecha 	if (status)
62330f94570dSGrishma Kotecha 		goto err_ice_add_adv_rule;
62340f94570dSGrishma Kotecha 	adv_fltr = devm_kzalloc(ice_hw_to_dev(hw),
62350f94570dSGrishma Kotecha 				sizeof(struct ice_adv_fltr_mgmt_list_entry),
62360f94570dSGrishma Kotecha 				GFP_KERNEL);
62370f94570dSGrishma Kotecha 	if (!adv_fltr) {
6238d54699e2STony Nguyen 		status = -ENOMEM;
62390f94570dSGrishma Kotecha 		goto err_ice_add_adv_rule;
62400f94570dSGrishma Kotecha 	}
62410f94570dSGrishma Kotecha 
62420f94570dSGrishma Kotecha 	adv_fltr->lkups = devm_kmemdup(ice_hw_to_dev(hw), lkups,
62430f94570dSGrishma Kotecha 				       lkups_cnt * sizeof(*lkups), GFP_KERNEL);
62440f94570dSGrishma Kotecha 	if (!adv_fltr->lkups) {
6245d54699e2STony Nguyen 		status = -ENOMEM;
62460f94570dSGrishma Kotecha 		goto err_ice_add_adv_rule;
62470f94570dSGrishma Kotecha 	}
62480f94570dSGrishma Kotecha 
62490f94570dSGrishma Kotecha 	adv_fltr->lkups_cnt = lkups_cnt;
62500f94570dSGrishma Kotecha 	adv_fltr->rule_info = *rinfo;
62516e1ff618SAlexander Lobakin 	adv_fltr->rule_info.fltr_rule_id = le16_to_cpu(s_rule->index);
62520f94570dSGrishma Kotecha 	sw = hw->switch_info;
62530f94570dSGrishma Kotecha 	sw->recp_list[rid].adv_rule = true;
62540f94570dSGrishma Kotecha 	rule_head = &sw->recp_list[rid].filt_rules;
62550f94570dSGrishma Kotecha 
62560f94570dSGrishma Kotecha 	if (rinfo->sw_act.fltr_act == ICE_FWD_TO_VSI)
62570f94570dSGrishma Kotecha 		adv_fltr->vsi_count = 1;
62580f94570dSGrishma Kotecha 
62590f94570dSGrishma Kotecha 	/* Add rule entry to book keeping list */
62600f94570dSGrishma Kotecha 	list_add(&adv_fltr->list_entry, rule_head);
62610f94570dSGrishma Kotecha 	if (added_entry) {
62620f94570dSGrishma Kotecha 		added_entry->rid = rid;
62630f94570dSGrishma Kotecha 		added_entry->rule_id = adv_fltr->rule_info.fltr_rule_id;
62640f94570dSGrishma Kotecha 		added_entry->vsi_handle = rinfo->sw_act.vsi_handle;
62650f94570dSGrishma Kotecha 	}
62660f94570dSGrishma Kotecha err_ice_add_adv_rule:
62670f94570dSGrishma Kotecha 	if (status && adv_fltr) {
62680f94570dSGrishma Kotecha 		devm_kfree(ice_hw_to_dev(hw), adv_fltr->lkups);
62690f94570dSGrishma Kotecha 		devm_kfree(ice_hw_to_dev(hw), adv_fltr);
62700f94570dSGrishma Kotecha 	}
62710f94570dSGrishma Kotecha 
62720f94570dSGrishma Kotecha 	kfree(s_rule);
62730f94570dSGrishma Kotecha 
627426395726SMartyna Szapar-Mudlaw free_pkt_profile:
627526395726SMartyna Szapar-Mudlaw 	if (profile->match & ICE_PKT_KMALLOC) {
627626395726SMartyna Szapar-Mudlaw 		kfree(profile->offsets);
627726395726SMartyna Szapar-Mudlaw 		kfree(profile->pkt);
627826395726SMartyna Szapar-Mudlaw 		kfree(profile);
627926395726SMartyna Szapar-Mudlaw 	}
628026395726SMartyna Szapar-Mudlaw 
62810f94570dSGrishma Kotecha 	return status;
62820f94570dSGrishma Kotecha }
62830f94570dSGrishma Kotecha 
62840f94570dSGrishma Kotecha /**
6285334cb062SAnirudh Venkataramanan  * ice_replay_vsi_fltr - Replay filters for requested VSI
62860f9d5027SAnirudh Venkataramanan  * @hw: pointer to the hardware structure
6287334cb062SAnirudh Venkataramanan  * @vsi_handle: driver VSI handle
6288f9867df6SAnirudh Venkataramanan  * @recp_id: Recipe ID for which rules need to be replayed
6289334cb062SAnirudh Venkataramanan  * @list_head: list for which filters need to be replayed
6290334cb062SAnirudh Venkataramanan  *
6291334cb062SAnirudh Venkataramanan  * Replays the filter of recipe recp_id for a VSI represented via vsi_handle.
6292334cb062SAnirudh Venkataramanan  * It is required to pass valid VSI handle.
62930f9d5027SAnirudh Venkataramanan  */
62945e24d598STony Nguyen static int
6295334cb062SAnirudh Venkataramanan ice_replay_vsi_fltr(struct ice_hw *hw, u16 vsi_handle, u8 recp_id,
6296334cb062SAnirudh Venkataramanan 		    struct list_head *list_head)
62970f9d5027SAnirudh Venkataramanan {
62980f9d5027SAnirudh Venkataramanan 	struct ice_fltr_mgmt_list_entry *itr;
62995e24d598STony Nguyen 	int status = 0;
6300334cb062SAnirudh Venkataramanan 	u16 hw_vsi_id;
63010f9d5027SAnirudh Venkataramanan 
63020f9d5027SAnirudh Venkataramanan 	if (list_empty(list_head))
63030f9d5027SAnirudh Venkataramanan 		return status;
6304334cb062SAnirudh Venkataramanan 	hw_vsi_id = ice_get_hw_vsi_num(hw, vsi_handle);
63050f9d5027SAnirudh Venkataramanan 
6306334cb062SAnirudh Venkataramanan 	list_for_each_entry(itr, list_head, list_entry) {
63070f9d5027SAnirudh Venkataramanan 		struct ice_fltr_list_entry f_entry;
63080f9d5027SAnirudh Venkataramanan 
63090f9d5027SAnirudh Venkataramanan 		f_entry.fltr_info = itr->fltr_info;
6310334cb062SAnirudh Venkataramanan 		if (itr->vsi_count < 2 && recp_id != ICE_SW_LKUP_VLAN &&
6311334cb062SAnirudh Venkataramanan 		    itr->fltr_info.vsi_handle == vsi_handle) {
6312f9867df6SAnirudh Venkataramanan 			/* update the src in case it is VSI num */
6313334cb062SAnirudh Venkataramanan 			if (f_entry.fltr_info.src_id == ICE_SRC_ID_VSI)
6314334cb062SAnirudh Venkataramanan 				f_entry.fltr_info.src = hw_vsi_id;
63150f9d5027SAnirudh Venkataramanan 			status = ice_add_rule_internal(hw, recp_id, &f_entry);
63160f9d5027SAnirudh Venkataramanan 			if (status)
63170f9d5027SAnirudh Venkataramanan 				goto end;
63180f9d5027SAnirudh Venkataramanan 			continue;
63190f9d5027SAnirudh Venkataramanan 		}
6320072f0c3dSDave Ertman 		if (!itr->vsi_list_info ||
6321072f0c3dSDave Ertman 		    !test_bit(vsi_handle, itr->vsi_list_info->vsi_map))
6322334cb062SAnirudh Venkataramanan 			continue;
6323334cb062SAnirudh Venkataramanan 		/* Clearing it so that the logic can add it back */
6324334cb062SAnirudh Venkataramanan 		clear_bit(vsi_handle, itr->vsi_list_info->vsi_map);
6325334cb062SAnirudh Venkataramanan 		f_entry.fltr_info.vsi_handle = vsi_handle;
63260f9d5027SAnirudh Venkataramanan 		f_entry.fltr_info.fltr_act = ICE_FWD_TO_VSI;
6327f9867df6SAnirudh Venkataramanan 		/* update the src in case it is VSI num */
6328334cb062SAnirudh Venkataramanan 		if (f_entry.fltr_info.src_id == ICE_SRC_ID_VSI)
6329334cb062SAnirudh Venkataramanan 			f_entry.fltr_info.src = hw_vsi_id;
63300f9d5027SAnirudh Venkataramanan 		if (recp_id == ICE_SW_LKUP_VLAN)
63310f9d5027SAnirudh Venkataramanan 			status = ice_add_vlan_internal(hw, &f_entry);
63320f9d5027SAnirudh Venkataramanan 		else
6333334cb062SAnirudh Venkataramanan 			status = ice_add_rule_internal(hw, recp_id, &f_entry);
63340f9d5027SAnirudh Venkataramanan 		if (status)
63350f9d5027SAnirudh Venkataramanan 			goto end;
63360f9d5027SAnirudh Venkataramanan 	}
63370f9d5027SAnirudh Venkataramanan end:
63380f9d5027SAnirudh Venkataramanan 	return status;
63390f9d5027SAnirudh Venkataramanan }
63400f9d5027SAnirudh Venkataramanan 
63410f9d5027SAnirudh Venkataramanan /**
63428bb98f33SShivanshu Shukla  * ice_adv_rem_update_vsi_list
63438bb98f33SShivanshu Shukla  * @hw: pointer to the hardware structure
63448bb98f33SShivanshu Shukla  * @vsi_handle: VSI handle of the VSI to remove
63458bb98f33SShivanshu Shukla  * @fm_list: filter management entry for which the VSI list management needs to
63468bb98f33SShivanshu Shukla  *	     be done
63478bb98f33SShivanshu Shukla  */
63485e24d598STony Nguyen static int
63498bb98f33SShivanshu Shukla ice_adv_rem_update_vsi_list(struct ice_hw *hw, u16 vsi_handle,
63508bb98f33SShivanshu Shukla 			    struct ice_adv_fltr_mgmt_list_entry *fm_list)
63518bb98f33SShivanshu Shukla {
63528bb98f33SShivanshu Shukla 	struct ice_vsi_list_map_info *vsi_list_info;
63538bb98f33SShivanshu Shukla 	enum ice_sw_lkup_type lkup_type;
63548bb98f33SShivanshu Shukla 	u16 vsi_list_id;
63555518ac2aSTony Nguyen 	int status;
63568bb98f33SShivanshu Shukla 
63578bb98f33SShivanshu Shukla 	if (fm_list->rule_info.sw_act.fltr_act != ICE_FWD_TO_VSI_LIST ||
63588bb98f33SShivanshu Shukla 	    fm_list->vsi_count == 0)
6359d54699e2STony Nguyen 		return -EINVAL;
63608bb98f33SShivanshu Shukla 
63618bb98f33SShivanshu Shukla 	/* A rule with the VSI being removed does not exist */
63628bb98f33SShivanshu Shukla 	if (!test_bit(vsi_handle, fm_list->vsi_list_info->vsi_map))
6363d54699e2STony Nguyen 		return -ENOENT;
63648bb98f33SShivanshu Shukla 
63658bb98f33SShivanshu Shukla 	lkup_type = ICE_SW_LKUP_LAST;
63668bb98f33SShivanshu Shukla 	vsi_list_id = fm_list->rule_info.sw_act.fwd_id.vsi_list_id;
63678bb98f33SShivanshu Shukla 	status = ice_update_vsi_list_rule(hw, &vsi_handle, 1, vsi_list_id, true,
63688bb98f33SShivanshu Shukla 					  ice_aqc_opc_update_sw_rules,
63698bb98f33SShivanshu Shukla 					  lkup_type);
63708bb98f33SShivanshu Shukla 	if (status)
63718bb98f33SShivanshu Shukla 		return status;
63728bb98f33SShivanshu Shukla 
63738bb98f33SShivanshu Shukla 	fm_list->vsi_count--;
63748bb98f33SShivanshu Shukla 	clear_bit(vsi_handle, fm_list->vsi_list_info->vsi_map);
63758bb98f33SShivanshu Shukla 	vsi_list_info = fm_list->vsi_list_info;
63768bb98f33SShivanshu Shukla 	if (fm_list->vsi_count == 1) {
63778bb98f33SShivanshu Shukla 		struct ice_fltr_info tmp_fltr;
63788bb98f33SShivanshu Shukla 		u16 rem_vsi_handle;
63798bb98f33SShivanshu Shukla 
63808bb98f33SShivanshu Shukla 		rem_vsi_handle = find_first_bit(vsi_list_info->vsi_map,
63818bb98f33SShivanshu Shukla 						ICE_MAX_VSI);
63828bb98f33SShivanshu Shukla 		if (!ice_is_vsi_valid(hw, rem_vsi_handle))
6383d54699e2STony Nguyen 			return -EIO;
63848bb98f33SShivanshu Shukla 
63858bb98f33SShivanshu Shukla 		/* Make sure VSI list is empty before removing it below */
63868bb98f33SShivanshu Shukla 		status = ice_update_vsi_list_rule(hw, &rem_vsi_handle, 1,
63878bb98f33SShivanshu Shukla 						  vsi_list_id, true,
63888bb98f33SShivanshu Shukla 						  ice_aqc_opc_update_sw_rules,
63898bb98f33SShivanshu Shukla 						  lkup_type);
63908bb98f33SShivanshu Shukla 		if (status)
63918bb98f33SShivanshu Shukla 			return status;
63928bb98f33SShivanshu Shukla 
63938bb98f33SShivanshu Shukla 		memset(&tmp_fltr, 0, sizeof(tmp_fltr));
63948bb98f33SShivanshu Shukla 		tmp_fltr.flag = fm_list->rule_info.sw_act.flag;
63958bb98f33SShivanshu Shukla 		tmp_fltr.fltr_rule_id = fm_list->rule_info.fltr_rule_id;
63968bb98f33SShivanshu Shukla 		fm_list->rule_info.sw_act.fltr_act = ICE_FWD_TO_VSI;
63978bb98f33SShivanshu Shukla 		tmp_fltr.fltr_act = ICE_FWD_TO_VSI;
63988bb98f33SShivanshu Shukla 		tmp_fltr.fwd_id.hw_vsi_id =
63998bb98f33SShivanshu Shukla 			ice_get_hw_vsi_num(hw, rem_vsi_handle);
64008bb98f33SShivanshu Shukla 		fm_list->rule_info.sw_act.fwd_id.hw_vsi_id =
64018bb98f33SShivanshu Shukla 			ice_get_hw_vsi_num(hw, rem_vsi_handle);
64028bb98f33SShivanshu Shukla 		fm_list->rule_info.sw_act.vsi_handle = rem_vsi_handle;
64038bb98f33SShivanshu Shukla 
64048bb98f33SShivanshu Shukla 		/* Update the previous switch rule of "MAC forward to VSI" to
64058bb98f33SShivanshu Shukla 		 * "MAC fwd to VSI list"
64068bb98f33SShivanshu Shukla 		 */
64078bb98f33SShivanshu Shukla 		status = ice_update_pkt_fwd_rule(hw, &tmp_fltr);
64088bb98f33SShivanshu Shukla 		if (status) {
64098bb98f33SShivanshu Shukla 			ice_debug(hw, ICE_DBG_SW, "Failed to update pkt fwd rule to FWD_TO_VSI on HW VSI %d, error %d\n",
64108bb98f33SShivanshu Shukla 				  tmp_fltr.fwd_id.hw_vsi_id, status);
64118bb98f33SShivanshu Shukla 			return status;
64128bb98f33SShivanshu Shukla 		}
64138bb98f33SShivanshu Shukla 		fm_list->vsi_list_info->ref_cnt--;
64148bb98f33SShivanshu Shukla 
64158bb98f33SShivanshu Shukla 		/* Remove the VSI list since it is no longer used */
64168bb98f33SShivanshu Shukla 		status = ice_remove_vsi_list_rule(hw, vsi_list_id, lkup_type);
64178bb98f33SShivanshu Shukla 		if (status) {
64188bb98f33SShivanshu Shukla 			ice_debug(hw, ICE_DBG_SW, "Failed to remove VSI list %d, error %d\n",
64198bb98f33SShivanshu Shukla 				  vsi_list_id, status);
64208bb98f33SShivanshu Shukla 			return status;
64218bb98f33SShivanshu Shukla 		}
64228bb98f33SShivanshu Shukla 
64238bb98f33SShivanshu Shukla 		list_del(&vsi_list_info->list_entry);
64248bb98f33SShivanshu Shukla 		devm_kfree(ice_hw_to_dev(hw), vsi_list_info);
64258bb98f33SShivanshu Shukla 		fm_list->vsi_list_info = NULL;
64268bb98f33SShivanshu Shukla 	}
64278bb98f33SShivanshu Shukla 
64288bb98f33SShivanshu Shukla 	return status;
64298bb98f33SShivanshu Shukla }
64308bb98f33SShivanshu Shukla 
64318bb98f33SShivanshu Shukla /**
64328bb98f33SShivanshu Shukla  * ice_rem_adv_rule - removes existing advanced switch rule
64338bb98f33SShivanshu Shukla  * @hw: pointer to the hardware structure
64348bb98f33SShivanshu Shukla  * @lkups: information on the words that needs to be looked up. All words
64358bb98f33SShivanshu Shukla  *         together makes one recipe
64368bb98f33SShivanshu Shukla  * @lkups_cnt: num of entries in the lkups array
64378bb98f33SShivanshu Shukla  * @rinfo: Its the pointer to the rule information for the rule
64388bb98f33SShivanshu Shukla  *
64398bb98f33SShivanshu Shukla  * This function can be used to remove 1 rule at a time. The lkups is
64408bb98f33SShivanshu Shukla  * used to describe all the words that forms the "lookup" portion of the
64418bb98f33SShivanshu Shukla  * rule. These words can span multiple protocols. Callers to this function
64428bb98f33SShivanshu Shukla  * need to pass in a list of protocol headers with lookup information along
64438bb98f33SShivanshu Shukla  * and mask that determines which words are valid from the given protocol
64448bb98f33SShivanshu Shukla  * header. rinfo describes other information related to this rule such as
64458bb98f33SShivanshu Shukla  * forwarding IDs, priority of this rule, etc.
64468bb98f33SShivanshu Shukla  */
64475e24d598STony Nguyen static int
64488bb98f33SShivanshu Shukla ice_rem_adv_rule(struct ice_hw *hw, struct ice_adv_lkup_elem *lkups,
64498bb98f33SShivanshu Shukla 		 u16 lkups_cnt, struct ice_adv_rule_info *rinfo)
64508bb98f33SShivanshu Shukla {
64518bb98f33SShivanshu Shukla 	struct ice_adv_fltr_mgmt_list_entry *list_elem;
64528bb98f33SShivanshu Shukla 	struct ice_prot_lkup_ext lkup_exts;
64538bb98f33SShivanshu Shukla 	bool remove_rule = false;
64548bb98f33SShivanshu Shukla 	struct mutex *rule_lock; /* Lock to protect filter rule list */
64558bb98f33SShivanshu Shukla 	u16 i, rid, vsi_handle;
64565518ac2aSTony Nguyen 	int status = 0;
64578bb98f33SShivanshu Shukla 
64588bb98f33SShivanshu Shukla 	memset(&lkup_exts, 0, sizeof(lkup_exts));
64598bb98f33SShivanshu Shukla 	for (i = 0; i < lkups_cnt; i++) {
64608bb98f33SShivanshu Shukla 		u16 count;
64618bb98f33SShivanshu Shukla 
64628bb98f33SShivanshu Shukla 		if (lkups[i].type >= ICE_PROTOCOL_LAST)
6463d54699e2STony Nguyen 			return -EIO;
64648bb98f33SShivanshu Shukla 
64658bb98f33SShivanshu Shukla 		count = ice_fill_valid_words(&lkups[i], &lkup_exts);
64668bb98f33SShivanshu Shukla 		if (!count)
6467d54699e2STony Nguyen 			return -EIO;
64688bb98f33SShivanshu Shukla 	}
64698bb98f33SShivanshu Shukla 
6470bccd9bceSMarcin Szycik 	rid = ice_find_recp(hw, &lkup_exts, rinfo);
64718bb98f33SShivanshu Shukla 	/* If did not find a recipe that match the existing criteria */
64728bb98f33SShivanshu Shukla 	if (rid == ICE_MAX_NUM_RECIPES)
6473d54699e2STony Nguyen 		return -EINVAL;
64748bb98f33SShivanshu Shukla 
64758bb98f33SShivanshu Shukla 	rule_lock = &hw->switch_info->recp_list[rid].filt_rule_lock;
64768bb98f33SShivanshu Shukla 	list_elem = ice_find_adv_rule_entry(hw, lkups, lkups_cnt, rid, rinfo);
64778bb98f33SShivanshu Shukla 	/* the rule is already removed */
64788bb98f33SShivanshu Shukla 	if (!list_elem)
64798bb98f33SShivanshu Shukla 		return 0;
64808bb98f33SShivanshu Shukla 	mutex_lock(rule_lock);
64818bb98f33SShivanshu Shukla 	if (list_elem->rule_info.sw_act.fltr_act != ICE_FWD_TO_VSI_LIST) {
64828bb98f33SShivanshu Shukla 		remove_rule = true;
64838bb98f33SShivanshu Shukla 	} else if (list_elem->vsi_count > 1) {
64848bb98f33SShivanshu Shukla 		remove_rule = false;
64858bb98f33SShivanshu Shukla 		vsi_handle = rinfo->sw_act.vsi_handle;
64868bb98f33SShivanshu Shukla 		status = ice_adv_rem_update_vsi_list(hw, vsi_handle, list_elem);
64878bb98f33SShivanshu Shukla 	} else {
64888bb98f33SShivanshu Shukla 		vsi_handle = rinfo->sw_act.vsi_handle;
64898bb98f33SShivanshu Shukla 		status = ice_adv_rem_update_vsi_list(hw, vsi_handle, list_elem);
64908bb98f33SShivanshu Shukla 		if (status) {
64918bb98f33SShivanshu Shukla 			mutex_unlock(rule_lock);
64928bb98f33SShivanshu Shukla 			return status;
64938bb98f33SShivanshu Shukla 		}
64948bb98f33SShivanshu Shukla 		if (list_elem->vsi_count == 0)
64958bb98f33SShivanshu Shukla 			remove_rule = true;
64968bb98f33SShivanshu Shukla 	}
64978bb98f33SShivanshu Shukla 	mutex_unlock(rule_lock);
64988bb98f33SShivanshu Shukla 	if (remove_rule) {
64996e1ff618SAlexander Lobakin 		struct ice_sw_rule_lkup_rx_tx *s_rule;
65008bb98f33SShivanshu Shukla 		u16 rule_buf_sz;
65018bb98f33SShivanshu Shukla 
65026e1ff618SAlexander Lobakin 		rule_buf_sz = ICE_SW_RULE_RX_TX_NO_HDR_SIZE(s_rule);
65038bb98f33SShivanshu Shukla 		s_rule = kzalloc(rule_buf_sz, GFP_KERNEL);
65048bb98f33SShivanshu Shukla 		if (!s_rule)
6505d54699e2STony Nguyen 			return -ENOMEM;
65066e1ff618SAlexander Lobakin 		s_rule->act = 0;
65076e1ff618SAlexander Lobakin 		s_rule->index = cpu_to_le16(list_elem->rule_info.fltr_rule_id);
65086e1ff618SAlexander Lobakin 		s_rule->hdr_len = 0;
65098bb98f33SShivanshu Shukla 		status = ice_aq_sw_rules(hw, (struct ice_aqc_sw_rules *)s_rule,
65108bb98f33SShivanshu Shukla 					 rule_buf_sz, 1,
65118bb98f33SShivanshu Shukla 					 ice_aqc_opc_remove_sw_rules, NULL);
6512d54699e2STony Nguyen 		if (!status || status == -ENOENT) {
65138bb98f33SShivanshu Shukla 			struct ice_switch_info *sw = hw->switch_info;
65148bb98f33SShivanshu Shukla 
65158bb98f33SShivanshu Shukla 			mutex_lock(rule_lock);
65168bb98f33SShivanshu Shukla 			list_del(&list_elem->list_entry);
65178bb98f33SShivanshu Shukla 			devm_kfree(ice_hw_to_dev(hw), list_elem->lkups);
65188bb98f33SShivanshu Shukla 			devm_kfree(ice_hw_to_dev(hw), list_elem);
65198bb98f33SShivanshu Shukla 			mutex_unlock(rule_lock);
65208bb98f33SShivanshu Shukla 			if (list_empty(&sw->recp_list[rid].filt_rules))
65218bb98f33SShivanshu Shukla 				sw->recp_list[rid].adv_rule = false;
65228bb98f33SShivanshu Shukla 		}
65238bb98f33SShivanshu Shukla 		kfree(s_rule);
65248bb98f33SShivanshu Shukla 	}
65258bb98f33SShivanshu Shukla 	return status;
65268bb98f33SShivanshu Shukla }
65278bb98f33SShivanshu Shukla 
65288bb98f33SShivanshu Shukla /**
65298bb98f33SShivanshu Shukla  * ice_rem_adv_rule_by_id - removes existing advanced switch rule by ID
65308bb98f33SShivanshu Shukla  * @hw: pointer to the hardware structure
65318bb98f33SShivanshu Shukla  * @remove_entry: data struct which holds rule_id, VSI handle and recipe ID
65328bb98f33SShivanshu Shukla  *
65338bb98f33SShivanshu Shukla  * This function is used to remove 1 rule at a time. The removal is based on
65348bb98f33SShivanshu Shukla  * the remove_entry parameter. This function will remove rule for a given
65358bb98f33SShivanshu Shukla  * vsi_handle with a given rule_id which is passed as parameter in remove_entry
65368bb98f33SShivanshu Shukla  */
65375e24d598STony Nguyen int
65388bb98f33SShivanshu Shukla ice_rem_adv_rule_by_id(struct ice_hw *hw,
65398bb98f33SShivanshu Shukla 		       struct ice_rule_query_data *remove_entry)
65408bb98f33SShivanshu Shukla {
65418bb98f33SShivanshu Shukla 	struct ice_adv_fltr_mgmt_list_entry *list_itr;
65428bb98f33SShivanshu Shukla 	struct list_head *list_head;
65438bb98f33SShivanshu Shukla 	struct ice_adv_rule_info rinfo;
65448bb98f33SShivanshu Shukla 	struct ice_switch_info *sw;
65458bb98f33SShivanshu Shukla 
65468bb98f33SShivanshu Shukla 	sw = hw->switch_info;
65478bb98f33SShivanshu Shukla 	if (!sw->recp_list[remove_entry->rid].recp_created)
6548d54699e2STony Nguyen 		return -EINVAL;
65498bb98f33SShivanshu Shukla 	list_head = &sw->recp_list[remove_entry->rid].filt_rules;
65508bb98f33SShivanshu Shukla 	list_for_each_entry(list_itr, list_head, list_entry) {
65518bb98f33SShivanshu Shukla 		if (list_itr->rule_info.fltr_rule_id ==
65528bb98f33SShivanshu Shukla 		    remove_entry->rule_id) {
65538bb98f33SShivanshu Shukla 			rinfo = list_itr->rule_info;
65548bb98f33SShivanshu Shukla 			rinfo.sw_act.vsi_handle = remove_entry->vsi_handle;
65558bb98f33SShivanshu Shukla 			return ice_rem_adv_rule(hw, list_itr->lkups,
65568bb98f33SShivanshu Shukla 						list_itr->lkups_cnt, &rinfo);
65578bb98f33SShivanshu Shukla 		}
65588bb98f33SShivanshu Shukla 	}
65598bb98f33SShivanshu Shukla 	/* either list is empty or unable to find rule */
6560d54699e2STony Nguyen 	return -ENOENT;
65618bb98f33SShivanshu Shukla }
65628bb98f33SShivanshu Shukla 
65638bb98f33SShivanshu Shukla /**
6564c36a2b97SVictor Raj  * ice_replay_vsi_adv_rule - Replay advanced rule for requested VSI
6565c36a2b97SVictor Raj  * @hw: pointer to the hardware structure
6566c36a2b97SVictor Raj  * @vsi_handle: driver VSI handle
6567c36a2b97SVictor Raj  * @list_head: list for which filters need to be replayed
6568c36a2b97SVictor Raj  *
6569c36a2b97SVictor Raj  * Replay the advanced rule for the given VSI.
6570c36a2b97SVictor Raj  */
6571c36a2b97SVictor Raj static int
6572c36a2b97SVictor Raj ice_replay_vsi_adv_rule(struct ice_hw *hw, u16 vsi_handle,
6573c36a2b97SVictor Raj 			struct list_head *list_head)
6574c36a2b97SVictor Raj {
6575c36a2b97SVictor Raj 	struct ice_rule_query_data added_entry = { 0 };
6576c36a2b97SVictor Raj 	struct ice_adv_fltr_mgmt_list_entry *adv_fltr;
6577c36a2b97SVictor Raj 	int status = 0;
6578c36a2b97SVictor Raj 
6579c36a2b97SVictor Raj 	if (list_empty(list_head))
6580c36a2b97SVictor Raj 		return status;
6581c36a2b97SVictor Raj 	list_for_each_entry(adv_fltr, list_head, list_entry) {
6582c36a2b97SVictor Raj 		struct ice_adv_rule_info *rinfo = &adv_fltr->rule_info;
6583c36a2b97SVictor Raj 		u16 lk_cnt = adv_fltr->lkups_cnt;
6584c36a2b97SVictor Raj 
6585c36a2b97SVictor Raj 		if (vsi_handle != rinfo->sw_act.vsi_handle)
6586c36a2b97SVictor Raj 			continue;
6587c36a2b97SVictor Raj 		status = ice_add_adv_rule(hw, adv_fltr->lkups, lk_cnt, rinfo,
6588c36a2b97SVictor Raj 					  &added_entry);
6589c36a2b97SVictor Raj 		if (status)
6590c36a2b97SVictor Raj 			break;
6591c36a2b97SVictor Raj 	}
6592c36a2b97SVictor Raj 	return status;
6593c36a2b97SVictor Raj }
6594c36a2b97SVictor Raj 
6595c36a2b97SVictor Raj /**
6596334cb062SAnirudh Venkataramanan  * ice_replay_vsi_all_fltr - replay all filters stored in bookkeeping lists
65970f9d5027SAnirudh Venkataramanan  * @hw: pointer to the hardware structure
6598334cb062SAnirudh Venkataramanan  * @vsi_handle: driver VSI handle
65990f9d5027SAnirudh Venkataramanan  *
6600334cb062SAnirudh Venkataramanan  * Replays filters for requested VSI via vsi_handle.
66010f9d5027SAnirudh Venkataramanan  */
66025e24d598STony Nguyen int ice_replay_vsi_all_fltr(struct ice_hw *hw, u16 vsi_handle)
66030f9d5027SAnirudh Venkataramanan {
66040f9d5027SAnirudh Venkataramanan 	struct ice_switch_info *sw = hw->switch_info;
6605c36a2b97SVictor Raj 	int status;
66060f9d5027SAnirudh Venkataramanan 	u8 i;
66070f9d5027SAnirudh Venkataramanan 
6608c36a2b97SVictor Raj 	for (i = 0; i < ICE_MAX_NUM_RECIPES; i++) {
6609334cb062SAnirudh Venkataramanan 		struct list_head *head;
66100f9d5027SAnirudh Venkataramanan 
6611334cb062SAnirudh Venkataramanan 		head = &sw->recp_list[i].filt_replay_rules;
6612c36a2b97SVictor Raj 		if (!sw->recp_list[i].adv_rule)
6613334cb062SAnirudh Venkataramanan 			status = ice_replay_vsi_fltr(hw, vsi_handle, i, head);
6614c36a2b97SVictor Raj 		else
6615c36a2b97SVictor Raj 			status = ice_replay_vsi_adv_rule(hw, vsi_handle, head);
66160f9d5027SAnirudh Venkataramanan 		if (status)
66170f9d5027SAnirudh Venkataramanan 			return status;
66180f9d5027SAnirudh Venkataramanan 	}
66190f9d5027SAnirudh Venkataramanan 	return status;
66200f9d5027SAnirudh Venkataramanan }
6621334cb062SAnirudh Venkataramanan 
6622334cb062SAnirudh Venkataramanan /**
6623334cb062SAnirudh Venkataramanan  * ice_rm_all_sw_replay_rule_info - deletes filter replay rules
6624f9867df6SAnirudh Venkataramanan  * @hw: pointer to the HW struct
6625334cb062SAnirudh Venkataramanan  *
6626334cb062SAnirudh Venkataramanan  * Deletes the filter replay rules.
6627334cb062SAnirudh Venkataramanan  */
6628334cb062SAnirudh Venkataramanan void ice_rm_all_sw_replay_rule_info(struct ice_hw *hw)
6629334cb062SAnirudh Venkataramanan {
6630334cb062SAnirudh Venkataramanan 	struct ice_switch_info *sw = hw->switch_info;
6631334cb062SAnirudh Venkataramanan 	u8 i;
6632334cb062SAnirudh Venkataramanan 
6633334cb062SAnirudh Venkataramanan 	if (!sw)
6634334cb062SAnirudh Venkataramanan 		return;
6635334cb062SAnirudh Venkataramanan 
66368b8ef05bSVictor Raj 	for (i = 0; i < ICE_MAX_NUM_RECIPES; i++) {
6637334cb062SAnirudh Venkataramanan 		if (!list_empty(&sw->recp_list[i].filt_replay_rules)) {
6638334cb062SAnirudh Venkataramanan 			struct list_head *l_head;
6639334cb062SAnirudh Venkataramanan 
6640334cb062SAnirudh Venkataramanan 			l_head = &sw->recp_list[i].filt_replay_rules;
66418b8ef05bSVictor Raj 			if (!sw->recp_list[i].adv_rule)
6642334cb062SAnirudh Venkataramanan 				ice_rem_sw_rule_info(hw, l_head);
66438b8ef05bSVictor Raj 			else
66448b8ef05bSVictor Raj 				ice_rem_adv_rule_info(hw, l_head);
6645334cb062SAnirudh Venkataramanan 		}
6646334cb062SAnirudh Venkataramanan 	}
6647334cb062SAnirudh Venkataramanan }
6648