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  */
ice_init_def_sw_recp(struct ice_hw * hw)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
ice_aq_get_sw_cfg(struct ice_hw * hw,struct ice_aqc_get_sw_cfg_resp_elem * buf,u16 buf_size,u16 * req_desc,u16 * num_elems,struct ice_sq_cd * cd)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
ice_aq_add_vsi(struct ice_hw * hw,struct ice_vsi_ctx * vsi_ctx,struct ice_sq_cd * cd)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
ice_aq_free_vsi(struct ice_hw * hw,struct ice_vsi_ctx * vsi_ctx,bool keep_vsi_alloc,struct ice_sq_cd * cd)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
ice_aq_update_vsi(struct ice_hw * hw,struct ice_vsi_ctx * vsi_ctx,struct ice_sq_cd * cd)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  */
ice_is_vsi_valid(struct ice_hw * hw,u16 vsi_handle)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  */
ice_get_hw_vsi_num(struct ice_hw * hw,u16 vsi_handle)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  */
ice_get_vsi_ctx(struct ice_hw * hw,u16 vsi_handle)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
ice_save_vsi_ctx(struct ice_hw * hw,u16 vsi_handle,struct ice_vsi_ctx * vsi)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  */
ice_clear_vsi_q_ctx(struct ice_hw * hw,u16 vsi_handle)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  */
ice_clear_vsi_ctx(struct ice_hw * hw,u16 vsi_handle)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  */
ice_clear_all_vsi_ctx(struct ice_hw * hw)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
ice_add_vsi(struct ice_hw * hw,u16 vsi_handle,struct ice_vsi_ctx * vsi_ctx,struct ice_sq_cd * cd)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
ice_free_vsi(struct ice_hw * hw,u16 vsi_handle,struct ice_vsi_ctx * vsi_ctx,bool keep_vsi_alloc,struct ice_sq_cd * cd)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
ice_update_vsi(struct ice_hw * hw,u16 vsi_handle,struct ice_vsi_ctx * vsi_ctx,struct ice_sq_cd * cd)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
ice_cfg_rdma_fltr(struct ice_hw * hw,u16 vsi_handle,bool enable)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
ice_aq_alloc_free_vsi_list(struct ice_hw * hw,u16 * vsi_list_id,enum ice_sw_lkup_type lkup_type,enum ice_adminq_opc opc)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 ||
1832*714782d5SMarcin Szycik 	    lkup_type == ICE_SW_LKUP_DFLT ||
1833*714782d5SMarcin Szycik 	    lkup_type == ICE_SW_LKUP_LAST) {
18349daf8208SAnirudh Venkataramanan 		sw_buf->res_type = cpu_to_le16(ICE_AQC_RES_TYPE_VSI_LIST_REP);
18359daf8208SAnirudh Venkataramanan 	} else if (lkup_type == ICE_SW_LKUP_VLAN) {
183623ccae5cSDave Ertman 		if (opc == ice_aqc_opc_alloc_res)
183723ccae5cSDave Ertman 			sw_buf->res_type =
183823ccae5cSDave Ertman 				cpu_to_le16(ICE_AQC_RES_TYPE_VSI_LIST_PRUNE |
183923ccae5cSDave Ertman 					    ICE_AQC_RES_TYPE_FLAG_SHARED);
184023ccae5cSDave Ertman 		else
18419daf8208SAnirudh Venkataramanan 			sw_buf->res_type =
18429daf8208SAnirudh Venkataramanan 				cpu_to_le16(ICE_AQC_RES_TYPE_VSI_LIST_PRUNE);
18439daf8208SAnirudh Venkataramanan 	} else {
1844d54699e2STony Nguyen 		status = -EINVAL;
18459daf8208SAnirudh Venkataramanan 		goto ice_aq_alloc_free_vsi_list_exit;
18469daf8208SAnirudh Venkataramanan 	}
18479daf8208SAnirudh Venkataramanan 
18489daf8208SAnirudh Venkataramanan 	if (opc == ice_aqc_opc_free_res)
18499daf8208SAnirudh Venkataramanan 		sw_buf->elem[0].e.sw_resp = cpu_to_le16(*vsi_list_id);
18509daf8208SAnirudh Venkataramanan 
185152da2fb2SPrzemek Kitszel 	status = ice_aq_alloc_free_res(hw, sw_buf, buf_len, opc);
18529daf8208SAnirudh Venkataramanan 	if (status)
18539daf8208SAnirudh Venkataramanan 		goto ice_aq_alloc_free_vsi_list_exit;
18549daf8208SAnirudh Venkataramanan 
18559daf8208SAnirudh Venkataramanan 	if (opc == ice_aqc_opc_alloc_res) {
18569daf8208SAnirudh Venkataramanan 		vsi_ele = &sw_buf->elem[0];
18579daf8208SAnirudh Venkataramanan 		*vsi_list_id = le16_to_cpu(vsi_ele->e.sw_resp);
18589daf8208SAnirudh Venkataramanan 	}
18599daf8208SAnirudh Venkataramanan 
18609daf8208SAnirudh Venkataramanan ice_aq_alloc_free_vsi_list_exit:
18619daf8208SAnirudh Venkataramanan 	devm_kfree(ice_hw_to_dev(hw), sw_buf);
18629daf8208SAnirudh Venkataramanan 	return status;
18639daf8208SAnirudh Venkataramanan }
18649daf8208SAnirudh Venkataramanan 
18659daf8208SAnirudh Venkataramanan /**
18669daf8208SAnirudh Venkataramanan  * ice_aq_sw_rules - add/update/remove switch rules
1867f9867df6SAnirudh Venkataramanan  * @hw: pointer to the HW struct
18689daf8208SAnirudh Venkataramanan  * @rule_list: pointer to switch rule population list
18699daf8208SAnirudh Venkataramanan  * @rule_list_sz: total size of the rule list in bytes
18709daf8208SAnirudh Venkataramanan  * @num_rules: number of switch rules in the rule_list
18719daf8208SAnirudh Venkataramanan  * @opc: switch rules population command type - pass in the command opcode
18729daf8208SAnirudh Venkataramanan  * @cd: pointer to command details structure or NULL
18739daf8208SAnirudh Venkataramanan  *
18749daf8208SAnirudh Venkataramanan  * Add(0x02a0)/Update(0x02a1)/Remove(0x02a2) switch rules commands to firmware
18759daf8208SAnirudh Venkataramanan  */
18765e24d598STony Nguyen int
ice_aq_sw_rules(struct ice_hw * hw,void * rule_list,u16 rule_list_sz,u8 num_rules,enum ice_adminq_opc opc,struct ice_sq_cd * cd)18779daf8208SAnirudh Venkataramanan ice_aq_sw_rules(struct ice_hw *hw, void *rule_list, u16 rule_list_sz,
18789daf8208SAnirudh Venkataramanan 		u8 num_rules, enum ice_adminq_opc opc, struct ice_sq_cd *cd)
18799daf8208SAnirudh Venkataramanan {
18809daf8208SAnirudh Venkataramanan 	struct ice_aq_desc desc;
18815e24d598STony Nguyen 	int status;
18829daf8208SAnirudh Venkataramanan 
18839daf8208SAnirudh Venkataramanan 	if (opc != ice_aqc_opc_add_sw_rules &&
18849daf8208SAnirudh Venkataramanan 	    opc != ice_aqc_opc_update_sw_rules &&
18859daf8208SAnirudh Venkataramanan 	    opc != ice_aqc_opc_remove_sw_rules)
1886d54699e2STony Nguyen 		return -EINVAL;
18879daf8208SAnirudh Venkataramanan 
18889daf8208SAnirudh Venkataramanan 	ice_fill_dflt_direct_cmd_desc(&desc, opc);
18899daf8208SAnirudh Venkataramanan 
18909daf8208SAnirudh Venkataramanan 	desc.flags |= cpu_to_le16(ICE_AQ_FLAG_RD);
18919daf8208SAnirudh Venkataramanan 	desc.params.sw_rules.num_rules_fltr_entry_index =
18929daf8208SAnirudh Venkataramanan 		cpu_to_le16(num_rules);
1893ca1fdb88SKiran Patil 	status = ice_aq_send_cmd(hw, &desc, rule_list, rule_list_sz, cd);
1894ca1fdb88SKiran Patil 	if (opc != ice_aqc_opc_add_sw_rules &&
1895ca1fdb88SKiran Patil 	    hw->adminq.sq_last_status == ICE_AQ_RC_ENOENT)
1896d54699e2STony Nguyen 		status = -ENOENT;
1897ca1fdb88SKiran Patil 
1898ca1fdb88SKiran Patil 	return status;
18999daf8208SAnirudh Venkataramanan }
19009daf8208SAnirudh Venkataramanan 
19017715ec32SGrishma Kotecha /**
19027715ec32SGrishma Kotecha  * ice_aq_add_recipe - add switch recipe
19037715ec32SGrishma Kotecha  * @hw: pointer to the HW struct
19047715ec32SGrishma Kotecha  * @s_recipe_list: pointer to switch rule population list
19057715ec32SGrishma Kotecha  * @num_recipes: number of switch recipes in the list
19067715ec32SGrishma Kotecha  * @cd: pointer to command details structure or NULL
19077715ec32SGrishma Kotecha  *
19087715ec32SGrishma Kotecha  * Add(0x0290)
19097715ec32SGrishma Kotecha  */
191023ccae5cSDave Ertman int
ice_aq_add_recipe(struct ice_hw * hw,struct ice_aqc_recipe_data_elem * s_recipe_list,u16 num_recipes,struct ice_sq_cd * cd)19117715ec32SGrishma Kotecha ice_aq_add_recipe(struct ice_hw *hw,
19127715ec32SGrishma Kotecha 		  struct ice_aqc_recipe_data_elem *s_recipe_list,
19137715ec32SGrishma Kotecha 		  u16 num_recipes, struct ice_sq_cd *cd)
19147715ec32SGrishma Kotecha {
19157715ec32SGrishma Kotecha 	struct ice_aqc_add_get_recipe *cmd;
19167715ec32SGrishma Kotecha 	struct ice_aq_desc desc;
19177715ec32SGrishma Kotecha 	u16 buf_size;
19187715ec32SGrishma Kotecha 
19197715ec32SGrishma Kotecha 	cmd = &desc.params.add_get_recipe;
19207715ec32SGrishma Kotecha 	ice_fill_dflt_direct_cmd_desc(&desc, ice_aqc_opc_add_recipe);
19217715ec32SGrishma Kotecha 
19227715ec32SGrishma Kotecha 	cmd->num_sub_recipes = cpu_to_le16(num_recipes);
19237715ec32SGrishma Kotecha 	desc.flags |= cpu_to_le16(ICE_AQ_FLAG_RD);
19247715ec32SGrishma Kotecha 
19257715ec32SGrishma Kotecha 	buf_size = num_recipes * sizeof(*s_recipe_list);
19267715ec32SGrishma Kotecha 
19277715ec32SGrishma Kotecha 	return ice_aq_send_cmd(hw, &desc, s_recipe_list, buf_size, cd);
19287715ec32SGrishma Kotecha }
19297715ec32SGrishma Kotecha 
19307715ec32SGrishma Kotecha /**
19317715ec32SGrishma Kotecha  * ice_aq_get_recipe - get switch recipe
19327715ec32SGrishma Kotecha  * @hw: pointer to the HW struct
19337715ec32SGrishma Kotecha  * @s_recipe_list: pointer to switch rule population list
19347715ec32SGrishma Kotecha  * @num_recipes: pointer to the number of recipes (input and output)
19357715ec32SGrishma Kotecha  * @recipe_root: root recipe number of recipe(s) to retrieve
19367715ec32SGrishma Kotecha  * @cd: pointer to command details structure or NULL
19377715ec32SGrishma Kotecha  *
19387715ec32SGrishma Kotecha  * Get(0x0292)
19397715ec32SGrishma Kotecha  *
19407715ec32SGrishma Kotecha  * On input, *num_recipes should equal the number of entries in s_recipe_list.
19417715ec32SGrishma Kotecha  * On output, *num_recipes will equal the number of entries returned in
19427715ec32SGrishma Kotecha  * s_recipe_list.
19437715ec32SGrishma Kotecha  *
19447715ec32SGrishma Kotecha  * The caller must supply enough space in s_recipe_list to hold all possible
19457715ec32SGrishma Kotecha  * recipes and *num_recipes must equal ICE_MAX_NUM_RECIPES.
19467715ec32SGrishma Kotecha  */
194723ccae5cSDave Ertman int
ice_aq_get_recipe(struct ice_hw * hw,struct ice_aqc_recipe_data_elem * s_recipe_list,u16 * num_recipes,u16 recipe_root,struct ice_sq_cd * cd)19487715ec32SGrishma Kotecha ice_aq_get_recipe(struct ice_hw *hw,
19497715ec32SGrishma Kotecha 		  struct ice_aqc_recipe_data_elem *s_recipe_list,
19507715ec32SGrishma Kotecha 		  u16 *num_recipes, u16 recipe_root, struct ice_sq_cd *cd)
19517715ec32SGrishma Kotecha {
19527715ec32SGrishma Kotecha 	struct ice_aqc_add_get_recipe *cmd;
19537715ec32SGrishma Kotecha 	struct ice_aq_desc desc;
19547715ec32SGrishma Kotecha 	u16 buf_size;
19555518ac2aSTony Nguyen 	int status;
19567715ec32SGrishma Kotecha 
19577715ec32SGrishma Kotecha 	if (*num_recipes != ICE_MAX_NUM_RECIPES)
1958d54699e2STony Nguyen 		return -EINVAL;
19597715ec32SGrishma Kotecha 
19607715ec32SGrishma Kotecha 	cmd = &desc.params.add_get_recipe;
19617715ec32SGrishma Kotecha 	ice_fill_dflt_direct_cmd_desc(&desc, ice_aqc_opc_get_recipe);
19627715ec32SGrishma Kotecha 
19637715ec32SGrishma Kotecha 	cmd->return_index = cpu_to_le16(recipe_root);
19647715ec32SGrishma Kotecha 	cmd->num_sub_recipes = 0;
19657715ec32SGrishma Kotecha 
19667715ec32SGrishma Kotecha 	buf_size = *num_recipes * sizeof(*s_recipe_list);
19677715ec32SGrishma Kotecha 
19687715ec32SGrishma Kotecha 	status = ice_aq_send_cmd(hw, &desc, s_recipe_list, buf_size, cd);
19697715ec32SGrishma Kotecha 	*num_recipes = le16_to_cpu(cmd->num_sub_recipes);
19707715ec32SGrishma Kotecha 
19717715ec32SGrishma Kotecha 	return status;
19727715ec32SGrishma Kotecha }
19737715ec32SGrishma Kotecha 
19747715ec32SGrishma Kotecha /**
1975a1ffafb0SBrett Creeley  * ice_update_recipe_lkup_idx - update a default recipe based on the lkup_idx
1976a1ffafb0SBrett Creeley  * @hw: pointer to the HW struct
1977a1ffafb0SBrett Creeley  * @params: parameters used to update the default recipe
1978a1ffafb0SBrett Creeley  *
1979a1ffafb0SBrett Creeley  * This function only supports updating default recipes and it only supports
1980a1ffafb0SBrett Creeley  * updating a single recipe based on the lkup_idx at a time.
1981a1ffafb0SBrett Creeley  *
1982a1ffafb0SBrett Creeley  * This is done as a read-modify-write operation. First, get the current recipe
1983a1ffafb0SBrett Creeley  * contents based on the recipe's ID. Then modify the field vector index and
1984a1ffafb0SBrett Creeley  * mask if it's valid at the lkup_idx. Finally, use the add recipe AQ to update
1985a1ffafb0SBrett Creeley  * the pre-existing recipe with the modifications.
1986a1ffafb0SBrett Creeley  */
1987a1ffafb0SBrett Creeley int
ice_update_recipe_lkup_idx(struct ice_hw * hw,struct ice_update_recipe_lkup_idx_params * params)1988a1ffafb0SBrett Creeley ice_update_recipe_lkup_idx(struct ice_hw *hw,
1989a1ffafb0SBrett Creeley 			   struct ice_update_recipe_lkup_idx_params *params)
1990a1ffafb0SBrett Creeley {
1991a1ffafb0SBrett Creeley 	struct ice_aqc_recipe_data_elem *rcp_list;
1992a1ffafb0SBrett Creeley 	u16 num_recps = ICE_MAX_NUM_RECIPES;
1993a1ffafb0SBrett Creeley 	int status;
1994a1ffafb0SBrett Creeley 
1995a1ffafb0SBrett Creeley 	rcp_list = kcalloc(num_recps, sizeof(*rcp_list), GFP_KERNEL);
1996a1ffafb0SBrett Creeley 	if (!rcp_list)
1997a1ffafb0SBrett Creeley 		return -ENOMEM;
1998a1ffafb0SBrett Creeley 
1999a1ffafb0SBrett Creeley 	/* read current recipe list from firmware */
2000a1ffafb0SBrett Creeley 	rcp_list->recipe_indx = params->rid;
2001a1ffafb0SBrett Creeley 	status = ice_aq_get_recipe(hw, rcp_list, &num_recps, params->rid, NULL);
2002a1ffafb0SBrett Creeley 	if (status) {
2003a1ffafb0SBrett Creeley 		ice_debug(hw, ICE_DBG_SW, "Failed to get recipe %d, status %d\n",
2004a1ffafb0SBrett Creeley 			  params->rid, status);
2005a1ffafb0SBrett Creeley 		goto error_out;
2006a1ffafb0SBrett Creeley 	}
2007a1ffafb0SBrett Creeley 
2008a1ffafb0SBrett Creeley 	/* only modify existing recipe's lkup_idx and mask if valid, while
2009a1ffafb0SBrett Creeley 	 * leaving all other fields the same, then update the recipe firmware
2010a1ffafb0SBrett Creeley 	 */
2011a1ffafb0SBrett Creeley 	rcp_list->content.lkup_indx[params->lkup_idx] = params->fv_idx;
2012a1ffafb0SBrett Creeley 	if (params->mask_valid)
2013a1ffafb0SBrett Creeley 		rcp_list->content.mask[params->lkup_idx] =
2014a1ffafb0SBrett Creeley 			cpu_to_le16(params->mask);
2015a1ffafb0SBrett Creeley 
2016a1ffafb0SBrett Creeley 	if (params->ignore_valid)
2017a1ffafb0SBrett Creeley 		rcp_list->content.lkup_indx[params->lkup_idx] |=
2018a1ffafb0SBrett Creeley 			ICE_AQ_RECIPE_LKUP_IGNORE;
2019a1ffafb0SBrett Creeley 
2020a1ffafb0SBrett Creeley 	status = ice_aq_add_recipe(hw, &rcp_list[0], 1, NULL);
2021a1ffafb0SBrett Creeley 	if (status)
2022a1ffafb0SBrett 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",
2023a1ffafb0SBrett Creeley 			  params->rid, params->lkup_idx, params->fv_idx,
2024a1ffafb0SBrett Creeley 			  params->mask, params->mask_valid ? "true" : "false",
2025a1ffafb0SBrett Creeley 			  status);
2026a1ffafb0SBrett Creeley 
2027a1ffafb0SBrett Creeley error_out:
2028a1ffafb0SBrett Creeley 	kfree(rcp_list);
2029a1ffafb0SBrett Creeley 	return status;
2030a1ffafb0SBrett Creeley }
2031a1ffafb0SBrett Creeley 
2032a1ffafb0SBrett Creeley /**
20337715ec32SGrishma Kotecha  * ice_aq_map_recipe_to_profile - Map recipe to packet profile
20347715ec32SGrishma Kotecha  * @hw: pointer to the HW struct
20357715ec32SGrishma Kotecha  * @profile_id: package profile ID to associate the recipe with
2036493b2993SSteven Zou  * @r_assoc: Recipe bitmap filled in and need to be returned as response
20377715ec32SGrishma Kotecha  * @cd: pointer to command details structure or NULL
20387715ec32SGrishma Kotecha  * Recipe to profile association (0x0291)
20397715ec32SGrishma Kotecha  */
204023ccae5cSDave Ertman int
ice_aq_map_recipe_to_profile(struct ice_hw * hw,u32 profile_id,u64 r_assoc,struct ice_sq_cd * cd)2041493b2993SSteven Zou ice_aq_map_recipe_to_profile(struct ice_hw *hw, u32 profile_id, u64 r_assoc,
20427715ec32SGrishma Kotecha 			     struct ice_sq_cd *cd)
20437715ec32SGrishma Kotecha {
20447715ec32SGrishma Kotecha 	struct ice_aqc_recipe_to_profile *cmd;
20457715ec32SGrishma Kotecha 	struct ice_aq_desc desc;
20467715ec32SGrishma Kotecha 
20477715ec32SGrishma Kotecha 	cmd = &desc.params.recipe_to_profile;
20487715ec32SGrishma Kotecha 	ice_fill_dflt_direct_cmd_desc(&desc, ice_aqc_opc_recipe_to_profile);
20497715ec32SGrishma Kotecha 	cmd->profile_id = cpu_to_le16(profile_id);
20507715ec32SGrishma Kotecha 	/* Set the recipe ID bit in the bitmask to let the device know which
20517715ec32SGrishma Kotecha 	 * profile we are associating the recipe to
20527715ec32SGrishma Kotecha 	 */
2053493b2993SSteven Zou 	cmd->recipe_assoc = cpu_to_le64(r_assoc);
20547715ec32SGrishma Kotecha 
20557715ec32SGrishma Kotecha 	return ice_aq_send_cmd(hw, &desc, NULL, 0, cd);
20567715ec32SGrishma Kotecha }
20577715ec32SGrishma Kotecha 
20587715ec32SGrishma Kotecha /**
20597715ec32SGrishma Kotecha  * ice_aq_get_recipe_to_profile - Map recipe to packet profile
20607715ec32SGrishma Kotecha  * @hw: pointer to the HW struct
20617715ec32SGrishma Kotecha  * @profile_id: package profile ID to associate the recipe with
2062493b2993SSteven Zou  * @r_assoc: Recipe bitmap filled in and need to be returned as response
20637715ec32SGrishma Kotecha  * @cd: pointer to command details structure or NULL
20647715ec32SGrishma Kotecha  * Associate profile ID with given recipe (0x0293)
20657715ec32SGrishma Kotecha  */
206623ccae5cSDave Ertman int
ice_aq_get_recipe_to_profile(struct ice_hw * hw,u32 profile_id,u64 * r_assoc,struct ice_sq_cd * cd)2067493b2993SSteven Zou ice_aq_get_recipe_to_profile(struct ice_hw *hw, u32 profile_id, u64 *r_assoc,
20687715ec32SGrishma Kotecha 			     struct ice_sq_cd *cd)
20697715ec32SGrishma Kotecha {
20707715ec32SGrishma Kotecha 	struct ice_aqc_recipe_to_profile *cmd;
20717715ec32SGrishma Kotecha 	struct ice_aq_desc desc;
20725e24d598STony Nguyen 	int status;
20737715ec32SGrishma Kotecha 
20747715ec32SGrishma Kotecha 	cmd = &desc.params.recipe_to_profile;
20757715ec32SGrishma Kotecha 	ice_fill_dflt_direct_cmd_desc(&desc, ice_aqc_opc_get_recipe_to_profile);
20767715ec32SGrishma Kotecha 	cmd->profile_id = cpu_to_le16(profile_id);
20777715ec32SGrishma Kotecha 
20787715ec32SGrishma Kotecha 	status = ice_aq_send_cmd(hw, &desc, NULL, 0, cd);
20797715ec32SGrishma Kotecha 	if (!status)
2080493b2993SSteven Zou 		*r_assoc = le64_to_cpu(cmd->recipe_assoc);
20817715ec32SGrishma Kotecha 
20827715ec32SGrishma Kotecha 	return status;
20837715ec32SGrishma Kotecha }
20847715ec32SGrishma Kotecha 
20857715ec32SGrishma Kotecha /**
20867715ec32SGrishma Kotecha  * ice_alloc_recipe - add recipe resource
20877715ec32SGrishma Kotecha  * @hw: pointer to the hardware structure
20887715ec32SGrishma Kotecha  * @rid: recipe ID returned as response to AQ call
20897715ec32SGrishma Kotecha  */
ice_alloc_recipe(struct ice_hw * hw,u16 * rid)209023ccae5cSDave Ertman int ice_alloc_recipe(struct ice_hw *hw, u16 *rid)
20917715ec32SGrishma Kotecha {
20927715ec32SGrishma Kotecha 	struct ice_aqc_alloc_free_res_elem *sw_buf;
20937715ec32SGrishma Kotecha 	u16 buf_len;
20945518ac2aSTony Nguyen 	int status;
20957715ec32SGrishma Kotecha 
20967715ec32SGrishma Kotecha 	buf_len = struct_size(sw_buf, elem, 1);
20977715ec32SGrishma Kotecha 	sw_buf = kzalloc(buf_len, GFP_KERNEL);
20987715ec32SGrishma Kotecha 	if (!sw_buf)
2099d54699e2STony Nguyen 		return -ENOMEM;
21007715ec32SGrishma Kotecha 
21017715ec32SGrishma Kotecha 	sw_buf->num_elems = cpu_to_le16(1);
21027715ec32SGrishma Kotecha 	sw_buf->res_type = cpu_to_le16((ICE_AQC_RES_TYPE_RECIPE <<
21037715ec32SGrishma Kotecha 					ICE_AQC_RES_TYPE_S) |
21047715ec32SGrishma Kotecha 					ICE_AQC_RES_TYPE_FLAG_SHARED);
210552da2fb2SPrzemek Kitszel 	status = ice_aq_alloc_free_res(hw, sw_buf, buf_len,
210652da2fb2SPrzemek Kitszel 				       ice_aqc_opc_alloc_res);
21077715ec32SGrishma Kotecha 	if (!status)
21087715ec32SGrishma Kotecha 		*rid = le16_to_cpu(sw_buf->elem[0].e.sw_resp);
21097715ec32SGrishma Kotecha 	kfree(sw_buf);
21107715ec32SGrishma Kotecha 
21117715ec32SGrishma Kotecha 	return status;
21127715ec32SGrishma Kotecha }
21137715ec32SGrishma Kotecha 
2114fd2a6b71SDan Nowlin /**
2115fd2a6b71SDan Nowlin  * ice_get_recp_to_prof_map - updates recipe to profile mapping
2116fd2a6b71SDan Nowlin  * @hw: pointer to hardware structure
2117fd2a6b71SDan Nowlin  *
2118fd2a6b71SDan Nowlin  * This function is used to populate recipe_to_profile matrix where index to
2119fd2a6b71SDan Nowlin  * this array is the recipe ID and the element is the mapping of which profiles
2120fd2a6b71SDan Nowlin  * is this recipe mapped to.
2121fd2a6b71SDan Nowlin  */
ice_get_recp_to_prof_map(struct ice_hw * hw)2122fd2a6b71SDan Nowlin static void ice_get_recp_to_prof_map(struct ice_hw *hw)
2123fd2a6b71SDan Nowlin {
2124fd2a6b71SDan Nowlin 	DECLARE_BITMAP(r_bitmap, ICE_MAX_NUM_RECIPES);
2125493b2993SSteven Zou 	u64 recp_assoc;
2126fd2a6b71SDan Nowlin 	u16 i;
2127fd2a6b71SDan Nowlin 
2128fd2a6b71SDan Nowlin 	for (i = 0; i < hw->switch_info->max_used_prof_index + 1; i++) {
2129fd2a6b71SDan Nowlin 		u16 j;
2130fd2a6b71SDan Nowlin 
2131fd2a6b71SDan Nowlin 		bitmap_zero(profile_to_recipe[i], ICE_MAX_NUM_RECIPES);
2132fd2a6b71SDan Nowlin 		bitmap_zero(r_bitmap, ICE_MAX_NUM_RECIPES);
2133493b2993SSteven Zou 		if (ice_aq_get_recipe_to_profile(hw, i, &recp_assoc, NULL))
2134fd2a6b71SDan Nowlin 			continue;
2135493b2993SSteven Zou 		bitmap_from_arr64(r_bitmap, &recp_assoc, ICE_MAX_NUM_RECIPES);
2136fd2a6b71SDan Nowlin 		bitmap_copy(profile_to_recipe[i], r_bitmap,
2137fd2a6b71SDan Nowlin 			    ICE_MAX_NUM_RECIPES);
2138fd2a6b71SDan Nowlin 		for_each_set_bit(j, r_bitmap, ICE_MAX_NUM_RECIPES)
2139fd2a6b71SDan Nowlin 			set_bit(i, recipe_to_profile[j]);
2140fd2a6b71SDan Nowlin 	}
2141fd2a6b71SDan Nowlin }
2142fd2a6b71SDan Nowlin 
2143fd2a6b71SDan Nowlin /**
2144fd2a6b71SDan Nowlin  * ice_collect_result_idx - copy result index values
2145fd2a6b71SDan Nowlin  * @buf: buffer that contains the result index
2146fd2a6b71SDan Nowlin  * @recp: the recipe struct to copy data into
2147fd2a6b71SDan Nowlin  */
2148fd2a6b71SDan Nowlin static void
ice_collect_result_idx(struct ice_aqc_recipe_data_elem * buf,struct ice_sw_recipe * recp)2149fd2a6b71SDan Nowlin ice_collect_result_idx(struct ice_aqc_recipe_data_elem *buf,
2150fd2a6b71SDan Nowlin 		       struct ice_sw_recipe *recp)
2151fd2a6b71SDan Nowlin {
2152fd2a6b71SDan Nowlin 	if (buf->content.result_indx & ICE_AQ_RECIPE_RESULT_EN)
2153fd2a6b71SDan Nowlin 		set_bit(buf->content.result_indx & ~ICE_AQ_RECIPE_RESULT_EN,
2154fd2a6b71SDan Nowlin 			recp->res_idxs);
2155fd2a6b71SDan Nowlin }
2156fd2a6b71SDan Nowlin 
2157fd2a6b71SDan Nowlin /**
2158fd2a6b71SDan Nowlin  * ice_get_recp_frm_fw - update SW bookkeeping from FW recipe entries
2159fd2a6b71SDan Nowlin  * @hw: pointer to hardware structure
2160fd2a6b71SDan Nowlin  * @recps: struct that we need to populate
2161fd2a6b71SDan Nowlin  * @rid: recipe ID that we are populating
2162fd2a6b71SDan Nowlin  * @refresh_required: true if we should get recipe to profile mapping from FW
2163fd2a6b71SDan Nowlin  *
2164fd2a6b71SDan Nowlin  * This function is used to populate all the necessary entries into our
2165fd2a6b71SDan Nowlin  * bookkeeping so that we have a current list of all the recipes that are
2166fd2a6b71SDan Nowlin  * programmed in the firmware.
2167fd2a6b71SDan Nowlin  */
21685e24d598STony Nguyen static int
ice_get_recp_frm_fw(struct ice_hw * hw,struct ice_sw_recipe * recps,u8 rid,bool * refresh_required)2169fd2a6b71SDan Nowlin ice_get_recp_frm_fw(struct ice_hw *hw, struct ice_sw_recipe *recps, u8 rid,
2170fd2a6b71SDan Nowlin 		    bool *refresh_required)
2171fd2a6b71SDan Nowlin {
2172fd2a6b71SDan Nowlin 	DECLARE_BITMAP(result_bm, ICE_MAX_FV_WORDS);
2173fd2a6b71SDan Nowlin 	struct ice_aqc_recipe_data_elem *tmp;
2174fd2a6b71SDan Nowlin 	u16 num_recps = ICE_MAX_NUM_RECIPES;
2175fd2a6b71SDan Nowlin 	struct ice_prot_lkup_ext *lkup_exts;
2176fd2a6b71SDan Nowlin 	u8 fv_word_idx = 0;
2177fd2a6b71SDan Nowlin 	u16 sub_recps;
21785518ac2aSTony Nguyen 	int status;
2179fd2a6b71SDan Nowlin 
2180fd2a6b71SDan Nowlin 	bitmap_zero(result_bm, ICE_MAX_FV_WORDS);
2181fd2a6b71SDan Nowlin 
2182fd2a6b71SDan Nowlin 	/* we need a buffer big enough to accommodate all the recipes */
2183fd2a6b71SDan Nowlin 	tmp = kcalloc(ICE_MAX_NUM_RECIPES, sizeof(*tmp), GFP_KERNEL);
2184fd2a6b71SDan Nowlin 	if (!tmp)
2185d54699e2STony Nguyen 		return -ENOMEM;
2186fd2a6b71SDan Nowlin 
2187fd2a6b71SDan Nowlin 	tmp[0].recipe_indx = rid;
2188fd2a6b71SDan Nowlin 	status = ice_aq_get_recipe(hw, tmp, &num_recps, rid, NULL);
2189fd2a6b71SDan Nowlin 	/* non-zero status meaning recipe doesn't exist */
2190fd2a6b71SDan Nowlin 	if (status)
2191fd2a6b71SDan Nowlin 		goto err_unroll;
2192fd2a6b71SDan Nowlin 
2193fd2a6b71SDan Nowlin 	/* Get recipe to profile map so that we can get the fv from lkups that
2194fd2a6b71SDan Nowlin 	 * we read for a recipe from FW. Since we want to minimize the number of
2195fd2a6b71SDan Nowlin 	 * times we make this FW call, just make one call and cache the copy
2196fd2a6b71SDan Nowlin 	 * until a new recipe is added. This operation is only required the
2197fd2a6b71SDan Nowlin 	 * first time to get the changes from FW. Then to search existing
2198fd2a6b71SDan Nowlin 	 * entries we don't need to update the cache again until another recipe
2199fd2a6b71SDan Nowlin 	 * gets added.
2200fd2a6b71SDan Nowlin 	 */
2201fd2a6b71SDan Nowlin 	if (*refresh_required) {
2202fd2a6b71SDan Nowlin 		ice_get_recp_to_prof_map(hw);
2203fd2a6b71SDan Nowlin 		*refresh_required = false;
2204fd2a6b71SDan Nowlin 	}
2205fd2a6b71SDan Nowlin 
2206fd2a6b71SDan Nowlin 	/* Start populating all the entries for recps[rid] based on lkups from
2207fd2a6b71SDan Nowlin 	 * firmware. Note that we are only creating the root recipe in our
2208fd2a6b71SDan Nowlin 	 * database.
2209fd2a6b71SDan Nowlin 	 */
2210fd2a6b71SDan Nowlin 	lkup_exts = &recps[rid].lkup_exts;
2211fd2a6b71SDan Nowlin 
2212fd2a6b71SDan Nowlin 	for (sub_recps = 0; sub_recps < num_recps; sub_recps++) {
2213fd2a6b71SDan Nowlin 		struct ice_aqc_recipe_data_elem root_bufs = tmp[sub_recps];
2214fd2a6b71SDan Nowlin 		struct ice_recp_grp_entry *rg_entry;
2215fd2a6b71SDan Nowlin 		u8 i, prof, idx, prot = 0;
2216fd2a6b71SDan Nowlin 		bool is_root;
2217fd2a6b71SDan Nowlin 		u16 off = 0;
2218fd2a6b71SDan Nowlin 
2219fd2a6b71SDan Nowlin 		rg_entry = devm_kzalloc(ice_hw_to_dev(hw), sizeof(*rg_entry),
2220fd2a6b71SDan Nowlin 					GFP_KERNEL);
2221fd2a6b71SDan Nowlin 		if (!rg_entry) {
2222d54699e2STony Nguyen 			status = -ENOMEM;
2223fd2a6b71SDan Nowlin 			goto err_unroll;
2224fd2a6b71SDan Nowlin 		}
2225fd2a6b71SDan Nowlin 
2226fd2a6b71SDan Nowlin 		idx = root_bufs.recipe_indx;
2227fd2a6b71SDan Nowlin 		is_root = root_bufs.content.rid & ICE_AQ_RECIPE_ID_IS_ROOT;
2228fd2a6b71SDan Nowlin 
2229fd2a6b71SDan Nowlin 		/* Mark all result indices in this chain */
2230fd2a6b71SDan Nowlin 		if (root_bufs.content.result_indx & ICE_AQ_RECIPE_RESULT_EN)
2231fd2a6b71SDan Nowlin 			set_bit(root_bufs.content.result_indx & ~ICE_AQ_RECIPE_RESULT_EN,
2232fd2a6b71SDan Nowlin 				result_bm);
2233fd2a6b71SDan Nowlin 
2234fd2a6b71SDan Nowlin 		/* get the first profile that is associated with rid */
2235fd2a6b71SDan Nowlin 		prof = find_first_bit(recipe_to_profile[idx],
2236fd2a6b71SDan Nowlin 				      ICE_MAX_NUM_PROFILES);
2237fd2a6b71SDan Nowlin 		for (i = 0; i < ICE_NUM_WORDS_RECIPE; i++) {
2238fd2a6b71SDan Nowlin 			u8 lkup_indx = root_bufs.content.lkup_indx[i + 1];
2239fd2a6b71SDan Nowlin 
2240fd2a6b71SDan Nowlin 			rg_entry->fv_idx[i] = lkup_indx;
2241fd2a6b71SDan Nowlin 			rg_entry->fv_mask[i] =
2242fd2a6b71SDan Nowlin 				le16_to_cpu(root_bufs.content.mask[i + 1]);
2243fd2a6b71SDan Nowlin 
2244fd2a6b71SDan Nowlin 			/* If the recipe is a chained recipe then all its
2245fd2a6b71SDan Nowlin 			 * child recipe's result will have a result index.
2246fd2a6b71SDan Nowlin 			 * To fill fv_words we should not use those result
2247fd2a6b71SDan Nowlin 			 * index, we only need the protocol ids and offsets.
2248fd2a6b71SDan Nowlin 			 * We will skip all the fv_idx which stores result
2249fd2a6b71SDan Nowlin 			 * index in them. We also need to skip any fv_idx which
2250fd2a6b71SDan Nowlin 			 * has ICE_AQ_RECIPE_LKUP_IGNORE or 0 since it isn't a
2251fd2a6b71SDan Nowlin 			 * valid offset value.
2252fd2a6b71SDan Nowlin 			 */
2253fd2a6b71SDan Nowlin 			if (test_bit(rg_entry->fv_idx[i], hw->switch_info->prof_res_bm[prof]) ||
2254fd2a6b71SDan Nowlin 			    rg_entry->fv_idx[i] & ICE_AQ_RECIPE_LKUP_IGNORE ||
2255fd2a6b71SDan Nowlin 			    rg_entry->fv_idx[i] == 0)
2256fd2a6b71SDan Nowlin 				continue;
2257fd2a6b71SDan Nowlin 
2258fd2a6b71SDan Nowlin 			ice_find_prot_off(hw, ICE_BLK_SW, prof,
2259fd2a6b71SDan Nowlin 					  rg_entry->fv_idx[i], &prot, &off);
2260fd2a6b71SDan Nowlin 			lkup_exts->fv_words[fv_word_idx].prot_id = prot;
2261fd2a6b71SDan Nowlin 			lkup_exts->fv_words[fv_word_idx].off = off;
2262fd2a6b71SDan Nowlin 			lkup_exts->field_mask[fv_word_idx] =
2263fd2a6b71SDan Nowlin 				rg_entry->fv_mask[i];
2264fd2a6b71SDan Nowlin 			fv_word_idx++;
2265fd2a6b71SDan Nowlin 		}
2266fd2a6b71SDan Nowlin 		/* populate rg_list with the data from the child entry of this
2267fd2a6b71SDan Nowlin 		 * recipe
2268fd2a6b71SDan Nowlin 		 */
2269fd2a6b71SDan Nowlin 		list_add(&rg_entry->l_entry, &recps[rid].rg_list);
2270fd2a6b71SDan Nowlin 
2271fd2a6b71SDan Nowlin 		/* Propagate some data to the recipe database */
2272fd2a6b71SDan Nowlin 		recps[idx].is_root = !!is_root;
2273fd2a6b71SDan Nowlin 		recps[idx].priority = root_bufs.content.act_ctrl_fwd_priority;
2274bccd9bceSMarcin Szycik 		recps[idx].need_pass_l2 = root_bufs.content.act_ctrl &
2275bccd9bceSMarcin Szycik 					  ICE_AQ_RECIPE_ACT_NEED_PASS_L2;
2276bccd9bceSMarcin Szycik 		recps[idx].allow_pass_l2 = root_bufs.content.act_ctrl &
2277bccd9bceSMarcin Szycik 					   ICE_AQ_RECIPE_ACT_ALLOW_PASS_L2;
2278fd2a6b71SDan Nowlin 		bitmap_zero(recps[idx].res_idxs, ICE_MAX_FV_WORDS);
2279fd2a6b71SDan Nowlin 		if (root_bufs.content.result_indx & ICE_AQ_RECIPE_RESULT_EN) {
2280fd2a6b71SDan Nowlin 			recps[idx].chain_idx = root_bufs.content.result_indx &
2281fd2a6b71SDan Nowlin 				~ICE_AQ_RECIPE_RESULT_EN;
2282fd2a6b71SDan Nowlin 			set_bit(recps[idx].chain_idx, recps[idx].res_idxs);
2283fd2a6b71SDan Nowlin 		} else {
2284fd2a6b71SDan Nowlin 			recps[idx].chain_idx = ICE_INVAL_CHAIN_IND;
2285fd2a6b71SDan Nowlin 		}
2286fd2a6b71SDan Nowlin 
2287fd2a6b71SDan Nowlin 		if (!is_root)
2288fd2a6b71SDan Nowlin 			continue;
2289fd2a6b71SDan Nowlin 
2290fd2a6b71SDan Nowlin 		/* Only do the following for root recipes entries */
2291fd2a6b71SDan Nowlin 		memcpy(recps[idx].r_bitmap, root_bufs.recipe_bitmap,
2292fd2a6b71SDan Nowlin 		       sizeof(recps[idx].r_bitmap));
2293fd2a6b71SDan Nowlin 		recps[idx].root_rid = root_bufs.content.rid &
2294fd2a6b71SDan Nowlin 			~ICE_AQ_RECIPE_ID_IS_ROOT;
2295fd2a6b71SDan Nowlin 		recps[idx].priority = root_bufs.content.act_ctrl_fwd_priority;
2296fd2a6b71SDan Nowlin 	}
2297fd2a6b71SDan Nowlin 
2298fd2a6b71SDan Nowlin 	/* Complete initialization of the root recipe entry */
2299fd2a6b71SDan Nowlin 	lkup_exts->n_val_words = fv_word_idx;
2300fd2a6b71SDan Nowlin 	recps[rid].big_recp = (num_recps > 1);
2301fd2a6b71SDan Nowlin 	recps[rid].n_grp_count = (u8)num_recps;
2302fd2a6b71SDan Nowlin 	recps[rid].root_buf = devm_kmemdup(ice_hw_to_dev(hw), tmp,
2303fd2a6b71SDan Nowlin 					   recps[rid].n_grp_count * sizeof(*recps[rid].root_buf),
2304fd2a6b71SDan Nowlin 					   GFP_KERNEL);
2305c8e51a01SWang Hai 	if (!recps[rid].root_buf) {
2306d54699e2STony Nguyen 		status = -ENOMEM;
2307fd2a6b71SDan Nowlin 		goto err_unroll;
2308c8e51a01SWang Hai 	}
2309fd2a6b71SDan Nowlin 
2310fd2a6b71SDan Nowlin 	/* Copy result indexes */
2311fd2a6b71SDan Nowlin 	bitmap_copy(recps[rid].res_idxs, result_bm, ICE_MAX_FV_WORDS);
2312fd2a6b71SDan Nowlin 	recps[rid].recp_created = true;
2313fd2a6b71SDan Nowlin 
2314fd2a6b71SDan Nowlin err_unroll:
2315fd2a6b71SDan Nowlin 	kfree(tmp);
2316fd2a6b71SDan Nowlin 	return status;
2317fd2a6b71SDan Nowlin }
2318fd2a6b71SDan Nowlin 
23199c20346bSAnirudh Venkataramanan /* ice_init_port_info - Initialize port_info with switch configuration data
23209c20346bSAnirudh Venkataramanan  * @pi: pointer to port_info
23219c20346bSAnirudh Venkataramanan  * @vsi_port_num: VSI number or port number
23229c20346bSAnirudh Venkataramanan  * @type: Type of switch element (port or VSI)
23239c20346bSAnirudh Venkataramanan  * @swid: switch ID of the switch the element is attached to
23249c20346bSAnirudh Venkataramanan  * @pf_vf_num: PF or VF number
23259c20346bSAnirudh Venkataramanan  * @is_vf: true if the element is a VF, false otherwise
23269c20346bSAnirudh Venkataramanan  */
23279c20346bSAnirudh Venkataramanan static void
ice_init_port_info(struct ice_port_info * pi,u16 vsi_port_num,u8 type,u16 swid,u16 pf_vf_num,bool is_vf)23289c20346bSAnirudh Venkataramanan ice_init_port_info(struct ice_port_info *pi, u16 vsi_port_num, u8 type,
23299c20346bSAnirudh Venkataramanan 		   u16 swid, u16 pf_vf_num, bool is_vf)
23309c20346bSAnirudh Venkataramanan {
23319c20346bSAnirudh Venkataramanan 	switch (type) {
23329c20346bSAnirudh Venkataramanan 	case ICE_AQC_GET_SW_CONF_RESP_PHYS_PORT:
23339c20346bSAnirudh Venkataramanan 		pi->lport = (u8)(vsi_port_num & ICE_LPORT_MASK);
23349c20346bSAnirudh Venkataramanan 		pi->sw_id = swid;
23359c20346bSAnirudh Venkataramanan 		pi->pf_vf_num = pf_vf_num;
23369c20346bSAnirudh Venkataramanan 		pi->is_vf = is_vf;
23379c20346bSAnirudh Venkataramanan 		break;
23389c20346bSAnirudh Venkataramanan 	default:
23399228d8b2SJacob Keller 		ice_debug(pi->hw, ICE_DBG_SW, "incorrect VSI/port type received\n");
23409c20346bSAnirudh Venkataramanan 		break;
23419c20346bSAnirudh Venkataramanan 	}
23429c20346bSAnirudh Venkataramanan }
23439c20346bSAnirudh Venkataramanan 
23449c20346bSAnirudh Venkataramanan /* ice_get_initial_sw_cfg - Get initial port and default VSI data
23459c20346bSAnirudh Venkataramanan  * @hw: pointer to the hardware structure
23469c20346bSAnirudh Venkataramanan  */
ice_get_initial_sw_cfg(struct ice_hw * hw)23475e24d598STony Nguyen int ice_get_initial_sw_cfg(struct ice_hw *hw)
23489c20346bSAnirudh Venkataramanan {
2349b3c38904SBruce Allan 	struct ice_aqc_get_sw_cfg_resp_elem *rbuf;
23509c20346bSAnirudh Venkataramanan 	u16 req_desc = 0;
23519c20346bSAnirudh Venkataramanan 	u16 num_elems;
23525518ac2aSTony Nguyen 	int status;
23539c20346bSAnirudh Venkataramanan 	u16 i;
23549c20346bSAnirudh Venkataramanan 
23551b9e740dSChristophe JAILLET 	rbuf = kzalloc(ICE_SW_CFG_MAX_BUF_LEN, GFP_KERNEL);
23569c20346bSAnirudh Venkataramanan 	if (!rbuf)
2357d54699e2STony Nguyen 		return -ENOMEM;
23589c20346bSAnirudh Venkataramanan 
23599c20346bSAnirudh Venkataramanan 	/* Multiple calls to ice_aq_get_sw_cfg may be required
23609c20346bSAnirudh Venkataramanan 	 * to get all the switch configuration information. The need
23619c20346bSAnirudh Venkataramanan 	 * for additional calls is indicated by ice_aq_get_sw_cfg
23629c20346bSAnirudh Venkataramanan 	 * writing a non-zero value in req_desc
23639c20346bSAnirudh Venkataramanan 	 */
23649c20346bSAnirudh Venkataramanan 	do {
2365b3c38904SBruce Allan 		struct ice_aqc_get_sw_cfg_resp_elem *ele;
2366b3c38904SBruce Allan 
23679c20346bSAnirudh Venkataramanan 		status = ice_aq_get_sw_cfg(hw, rbuf, ICE_SW_CFG_MAX_BUF_LEN,
23689c20346bSAnirudh Venkataramanan 					   &req_desc, &num_elems, NULL);
23699c20346bSAnirudh Venkataramanan 
23709c20346bSAnirudh Venkataramanan 		if (status)
23719c20346bSAnirudh Venkataramanan 			break;
23729c20346bSAnirudh Venkataramanan 
2373b3c38904SBruce Allan 		for (i = 0, ele = rbuf; i < num_elems; i++, ele++) {
23749c20346bSAnirudh Venkataramanan 			u16 pf_vf_num, swid, vsi_port_num;
23759c20346bSAnirudh Venkataramanan 			bool is_vf = false;
23766dae8aa0SBruce Allan 			u8 res_type;
23779c20346bSAnirudh Venkataramanan 
23789c20346bSAnirudh Venkataramanan 			vsi_port_num = le16_to_cpu(ele->vsi_port_num) &
23799c20346bSAnirudh Venkataramanan 				ICE_AQC_GET_SW_CONF_RESP_VSI_PORT_NUM_M;
23809c20346bSAnirudh Venkataramanan 
23819c20346bSAnirudh Venkataramanan 			pf_vf_num = le16_to_cpu(ele->pf_vf_num) &
23829c20346bSAnirudh Venkataramanan 				ICE_AQC_GET_SW_CONF_RESP_FUNC_NUM_M;
23839c20346bSAnirudh Venkataramanan 
23849c20346bSAnirudh Venkataramanan 			swid = le16_to_cpu(ele->swid);
23859c20346bSAnirudh Venkataramanan 
23869c20346bSAnirudh Venkataramanan 			if (le16_to_cpu(ele->pf_vf_num) &
23879c20346bSAnirudh Venkataramanan 			    ICE_AQC_GET_SW_CONF_RESP_IS_VF)
23889c20346bSAnirudh Venkataramanan 				is_vf = true;
23899c20346bSAnirudh Venkataramanan 
239088865fc4SKarol Kolacinski 			res_type = (u8)(le16_to_cpu(ele->vsi_port_num) >>
239188865fc4SKarol Kolacinski 					ICE_AQC_GET_SW_CONF_RESP_TYPE_S);
23929c20346bSAnirudh Venkataramanan 
23936dae8aa0SBruce Allan 			if (res_type == ICE_AQC_GET_SW_CONF_RESP_VSI) {
23949c20346bSAnirudh Venkataramanan 				/* FW VSI is not needed. Just continue. */
23959c20346bSAnirudh Venkataramanan 				continue;
23969c20346bSAnirudh Venkataramanan 			}
23979c20346bSAnirudh Venkataramanan 
23989c20346bSAnirudh Venkataramanan 			ice_init_port_info(hw->port_info, vsi_port_num,
23996dae8aa0SBruce Allan 					   res_type, swid, pf_vf_num, is_vf);
24009c20346bSAnirudh Venkataramanan 		}
24019c20346bSAnirudh Venkataramanan 	} while (req_desc && !status);
24029c20346bSAnirudh Venkataramanan 
24031b9e740dSChristophe JAILLET 	kfree(rbuf);
24049c20346bSAnirudh Venkataramanan 	return status;
24059c20346bSAnirudh Venkataramanan }
24069daf8208SAnirudh Venkataramanan 
24079daf8208SAnirudh Venkataramanan /**
24089daf8208SAnirudh Venkataramanan  * ice_fill_sw_info - Helper function to populate lb_en and lan_en
24099daf8208SAnirudh Venkataramanan  * @hw: pointer to the hardware structure
24106a7e6993SYashaswini Raghuram Prathivadi Bhayankaram  * @fi: filter info structure to fill/update
24119daf8208SAnirudh Venkataramanan  *
24129daf8208SAnirudh Venkataramanan  * This helper function populates the lb_en and lan_en elements of the provided
24139daf8208SAnirudh Venkataramanan  * ice_fltr_info struct using the switch's type and characteristics of the
24149daf8208SAnirudh Venkataramanan  * switch rule being configured.
24159daf8208SAnirudh Venkataramanan  */
ice_fill_sw_info(struct ice_hw * hw,struct ice_fltr_info * fi)24166a7e6993SYashaswini Raghuram Prathivadi Bhayankaram static void ice_fill_sw_info(struct ice_hw *hw, struct ice_fltr_info *fi)
24179daf8208SAnirudh Venkataramanan {
24186a7e6993SYashaswini Raghuram Prathivadi Bhayankaram 	fi->lb_en = false;
24196a7e6993SYashaswini Raghuram Prathivadi Bhayankaram 	fi->lan_en = false;
24206a7e6993SYashaswini Raghuram Prathivadi Bhayankaram 	if ((fi->flag & ICE_FLTR_TX) &&
24216a7e6993SYashaswini Raghuram Prathivadi Bhayankaram 	    (fi->fltr_act == ICE_FWD_TO_VSI ||
24226a7e6993SYashaswini Raghuram Prathivadi Bhayankaram 	     fi->fltr_act == ICE_FWD_TO_VSI_LIST ||
24236a7e6993SYashaswini Raghuram Prathivadi Bhayankaram 	     fi->fltr_act == ICE_FWD_TO_Q ||
24246a7e6993SYashaswini Raghuram Prathivadi Bhayankaram 	     fi->fltr_act == ICE_FWD_TO_QGRP)) {
2425b58dafbcSChristopher N Bednarz 		/* Setting LB for prune actions will result in replicated
2426b58dafbcSChristopher N Bednarz 		 * packets to the internal switch that will be dropped.
2427b58dafbcSChristopher N Bednarz 		 */
2428b58dafbcSChristopher N Bednarz 		if (fi->lkup_type != ICE_SW_LKUP_VLAN)
24296a7e6993SYashaswini Raghuram Prathivadi Bhayankaram 			fi->lb_en = true;
2430b58dafbcSChristopher N Bednarz 
2431277b3a45SYashaswini Raghuram Prathivadi Bhayankaram 		/* Set lan_en to TRUE if
24326a7e6993SYashaswini Raghuram Prathivadi Bhayankaram 		 * 1. The switch is a VEB AND
24336a7e6993SYashaswini Raghuram Prathivadi Bhayankaram 		 * 2
243426069b44SYashaswini Raghuram Prathivadi Bhayankaram 		 * 2.1 The lookup is a directional lookup like ethertype,
2435f9867df6SAnirudh Venkataramanan 		 * promiscuous, ethertype-MAC, promiscuous-VLAN
243626069b44SYashaswini Raghuram Prathivadi Bhayankaram 		 * and default-port OR
243726069b44SYashaswini Raghuram Prathivadi Bhayankaram 		 * 2.2 The lookup is VLAN, OR
2438277b3a45SYashaswini Raghuram Prathivadi Bhayankaram 		 * 2.3 The lookup is MAC with mcast or bcast addr for MAC, OR
2439277b3a45SYashaswini Raghuram Prathivadi Bhayankaram 		 * 2.4 The lookup is MAC_VLAN with mcast or bcast addr for MAC.
24406a7e6993SYashaswini Raghuram Prathivadi Bhayankaram 		 *
2441277b3a45SYashaswini Raghuram Prathivadi Bhayankaram 		 * OR
2442277b3a45SYashaswini Raghuram Prathivadi Bhayankaram 		 *
2443277b3a45SYashaswini Raghuram Prathivadi Bhayankaram 		 * The switch is a VEPA.
2444277b3a45SYashaswini Raghuram Prathivadi Bhayankaram 		 *
2445277b3a45SYashaswini Raghuram Prathivadi Bhayankaram 		 * In all other cases, the LAN enable has to be set to false.
24466a7e6993SYashaswini Raghuram Prathivadi Bhayankaram 		 */
2447277b3a45SYashaswini Raghuram Prathivadi Bhayankaram 		if (hw->evb_veb) {
244826069b44SYashaswini Raghuram Prathivadi Bhayankaram 			if (fi->lkup_type == ICE_SW_LKUP_ETHERTYPE ||
244926069b44SYashaswini Raghuram Prathivadi Bhayankaram 			    fi->lkup_type == ICE_SW_LKUP_PROMISC ||
245026069b44SYashaswini Raghuram Prathivadi Bhayankaram 			    fi->lkup_type == ICE_SW_LKUP_ETHERTYPE_MAC ||
245126069b44SYashaswini Raghuram Prathivadi Bhayankaram 			    fi->lkup_type == ICE_SW_LKUP_PROMISC_VLAN ||
2452277b3a45SYashaswini Raghuram Prathivadi Bhayankaram 			    fi->lkup_type == ICE_SW_LKUP_DFLT ||
245326069b44SYashaswini Raghuram Prathivadi Bhayankaram 			    fi->lkup_type == ICE_SW_LKUP_VLAN ||
2454277b3a45SYashaswini Raghuram Prathivadi Bhayankaram 			    (fi->lkup_type == ICE_SW_LKUP_MAC &&
2455277b3a45SYashaswini Raghuram Prathivadi Bhayankaram 			     !is_unicast_ether_addr(fi->l_data.mac.mac_addr)) ||
24566a7e6993SYashaswini Raghuram Prathivadi Bhayankaram 			    (fi->lkup_type == ICE_SW_LKUP_MAC_VLAN &&
2457277b3a45SYashaswini Raghuram Prathivadi Bhayankaram 			     !is_unicast_ether_addr(fi->l_data.mac.mac_addr)))
24586a7e6993SYashaswini Raghuram Prathivadi Bhayankaram 				fi->lan_en = true;
2459277b3a45SYashaswini Raghuram Prathivadi Bhayankaram 		} else {
2460277b3a45SYashaswini Raghuram Prathivadi Bhayankaram 			fi->lan_en = true;
2461277b3a45SYashaswini Raghuram Prathivadi Bhayankaram 		}
24629daf8208SAnirudh Venkataramanan 	}
24639daf8208SAnirudh Venkataramanan }
24649daf8208SAnirudh Venkataramanan 
24659daf8208SAnirudh Venkataramanan /**
2466ec5a6c5fSDave Ertman  * ice_fill_eth_hdr - helper to copy dummy_eth_hdr into supplied buffer
2467ec5a6c5fSDave Ertman  * @eth_hdr: pointer to buffer to populate
2468ec5a6c5fSDave Ertman  */
ice_fill_eth_hdr(u8 * eth_hdr)2469ec5a6c5fSDave Ertman void ice_fill_eth_hdr(u8 *eth_hdr)
2470ec5a6c5fSDave Ertman {
2471ec5a6c5fSDave Ertman 	memcpy(eth_hdr, dummy_eth_header, DUMMY_ETH_HDR_LEN);
2472ec5a6c5fSDave Ertman }
2473ec5a6c5fSDave Ertman 
2474ec5a6c5fSDave Ertman /**
24759daf8208SAnirudh Venkataramanan  * ice_fill_sw_rule - Helper function to fill switch rule structure
24769daf8208SAnirudh Venkataramanan  * @hw: pointer to the hardware structure
24779daf8208SAnirudh Venkataramanan  * @f_info: entry containing packet forwarding information
24789daf8208SAnirudh Venkataramanan  * @s_rule: switch rule structure to be filled in based on mac_entry
24799daf8208SAnirudh Venkataramanan  * @opc: switch rules population command type - pass in the command opcode
24809daf8208SAnirudh Venkataramanan  */
24819daf8208SAnirudh Venkataramanan static void
ice_fill_sw_rule(struct ice_hw * hw,struct ice_fltr_info * f_info,struct ice_sw_rule_lkup_rx_tx * s_rule,enum ice_adminq_opc opc)24829daf8208SAnirudh Venkataramanan ice_fill_sw_rule(struct ice_hw *hw, struct ice_fltr_info *f_info,
24836e1ff618SAlexander Lobakin 		 struct ice_sw_rule_lkup_rx_tx *s_rule,
24846e1ff618SAlexander Lobakin 		 enum ice_adminq_opc opc)
24859daf8208SAnirudh Venkataramanan {
24869daf8208SAnirudh Venkataramanan 	u16 vlan_id = ICE_MAX_VLAN_ID + 1;
24872bfefa2dSBrett Creeley 	u16 vlan_tpid = ETH_P_8021Q;
24889daf8208SAnirudh Venkataramanan 	void *daddr = NULL;
248974118f7aSZhenning Xiao 	u16 eth_hdr_sz;
249074118f7aSZhenning Xiao 	u8 *eth_hdr;
24919daf8208SAnirudh Venkataramanan 	u32 act = 0;
24929daf8208SAnirudh Venkataramanan 	__be16 *off;
2493be8ff000SAnirudh Venkataramanan 	u8 q_rgn;
24949daf8208SAnirudh Venkataramanan 
24959daf8208SAnirudh Venkataramanan 	if (opc == ice_aqc_opc_remove_sw_rules) {
24966e1ff618SAlexander Lobakin 		s_rule->act = 0;
24976e1ff618SAlexander Lobakin 		s_rule->index = cpu_to_le16(f_info->fltr_rule_id);
24986e1ff618SAlexander Lobakin 		s_rule->hdr_len = 0;
24999daf8208SAnirudh Venkataramanan 		return;
25009daf8208SAnirudh Venkataramanan 	}
25019daf8208SAnirudh Venkataramanan 
250274118f7aSZhenning Xiao 	eth_hdr_sz = sizeof(dummy_eth_header);
25036e1ff618SAlexander Lobakin 	eth_hdr = s_rule->hdr_data;
250474118f7aSZhenning Xiao 
25059daf8208SAnirudh Venkataramanan 	/* initialize the ether header with a dummy header */
250674118f7aSZhenning Xiao 	memcpy(eth_hdr, dummy_eth_header, eth_hdr_sz);
25079daf8208SAnirudh Venkataramanan 	ice_fill_sw_info(hw, f_info);
25089daf8208SAnirudh Venkataramanan 
25099daf8208SAnirudh Venkataramanan 	switch (f_info->fltr_act) {
25109daf8208SAnirudh Venkataramanan 	case ICE_FWD_TO_VSI:
25115726ca0eSAnirudh Venkataramanan 		act |= (f_info->fwd_id.hw_vsi_id << ICE_SINGLE_ACT_VSI_ID_S) &
25129daf8208SAnirudh Venkataramanan 			ICE_SINGLE_ACT_VSI_ID_M;
25139daf8208SAnirudh Venkataramanan 		if (f_info->lkup_type != ICE_SW_LKUP_VLAN)
25149daf8208SAnirudh Venkataramanan 			act |= ICE_SINGLE_ACT_VSI_FORWARDING |
25159daf8208SAnirudh Venkataramanan 				ICE_SINGLE_ACT_VALID_BIT;
25169daf8208SAnirudh Venkataramanan 		break;
25179daf8208SAnirudh Venkataramanan 	case ICE_FWD_TO_VSI_LIST:
25189daf8208SAnirudh Venkataramanan 		act |= ICE_SINGLE_ACT_VSI_LIST;
25199daf8208SAnirudh Venkataramanan 		act |= (f_info->fwd_id.vsi_list_id <<
25209daf8208SAnirudh Venkataramanan 			ICE_SINGLE_ACT_VSI_LIST_ID_S) &
25219daf8208SAnirudh Venkataramanan 			ICE_SINGLE_ACT_VSI_LIST_ID_M;
25229daf8208SAnirudh Venkataramanan 		if (f_info->lkup_type != ICE_SW_LKUP_VLAN)
25239daf8208SAnirudh Venkataramanan 			act |= ICE_SINGLE_ACT_VSI_FORWARDING |
25249daf8208SAnirudh Venkataramanan 				ICE_SINGLE_ACT_VALID_BIT;
25259daf8208SAnirudh Venkataramanan 		break;
25269daf8208SAnirudh Venkataramanan 	case ICE_FWD_TO_Q:
25279daf8208SAnirudh Venkataramanan 		act |= ICE_SINGLE_ACT_TO_Q;
25289daf8208SAnirudh Venkataramanan 		act |= (f_info->fwd_id.q_id << ICE_SINGLE_ACT_Q_INDEX_S) &
25299daf8208SAnirudh Venkataramanan 			ICE_SINGLE_ACT_Q_INDEX_M;
25309daf8208SAnirudh Venkataramanan 		break;
25319daf8208SAnirudh Venkataramanan 	case ICE_DROP_PACKET:
2532be8ff000SAnirudh Venkataramanan 		act |= ICE_SINGLE_ACT_VSI_FORWARDING | ICE_SINGLE_ACT_DROP |
2533be8ff000SAnirudh Venkataramanan 			ICE_SINGLE_ACT_VALID_BIT;
2534be8ff000SAnirudh Venkataramanan 		break;
2535be8ff000SAnirudh Venkataramanan 	case ICE_FWD_TO_QGRP:
2536be8ff000SAnirudh Venkataramanan 		q_rgn = f_info->qgrp_size > 0 ?
2537be8ff000SAnirudh Venkataramanan 			(u8)ilog2(f_info->qgrp_size) : 0;
2538be8ff000SAnirudh Venkataramanan 		act |= ICE_SINGLE_ACT_TO_Q;
2539be8ff000SAnirudh Venkataramanan 		act |= (f_info->fwd_id.q_id << ICE_SINGLE_ACT_Q_INDEX_S) &
2540be8ff000SAnirudh Venkataramanan 			ICE_SINGLE_ACT_Q_INDEX_M;
2541be8ff000SAnirudh Venkataramanan 		act |= (q_rgn << ICE_SINGLE_ACT_Q_REGION_S) &
2542be8ff000SAnirudh Venkataramanan 			ICE_SINGLE_ACT_Q_REGION_M;
25439daf8208SAnirudh Venkataramanan 		break;
25449daf8208SAnirudh Venkataramanan 	default:
25459daf8208SAnirudh Venkataramanan 		return;
25469daf8208SAnirudh Venkataramanan 	}
25479daf8208SAnirudh Venkataramanan 
25489daf8208SAnirudh Venkataramanan 	if (f_info->lb_en)
25499daf8208SAnirudh Venkataramanan 		act |= ICE_SINGLE_ACT_LB_ENABLE;
25509daf8208SAnirudh Venkataramanan 	if (f_info->lan_en)
25519daf8208SAnirudh Venkataramanan 		act |= ICE_SINGLE_ACT_LAN_ENABLE;
25529daf8208SAnirudh Venkataramanan 
25539daf8208SAnirudh Venkataramanan 	switch (f_info->lkup_type) {
25549daf8208SAnirudh Venkataramanan 	case ICE_SW_LKUP_MAC:
25559daf8208SAnirudh Venkataramanan 		daddr = f_info->l_data.mac.mac_addr;
25569daf8208SAnirudh Venkataramanan 		break;
25579daf8208SAnirudh Venkataramanan 	case ICE_SW_LKUP_VLAN:
25589daf8208SAnirudh Venkataramanan 		vlan_id = f_info->l_data.vlan.vlan_id;
25592bfefa2dSBrett Creeley 		if (f_info->l_data.vlan.tpid_valid)
25602bfefa2dSBrett Creeley 			vlan_tpid = f_info->l_data.vlan.tpid;
25619daf8208SAnirudh Venkataramanan 		if (f_info->fltr_act == ICE_FWD_TO_VSI ||
25629daf8208SAnirudh Venkataramanan 		    f_info->fltr_act == ICE_FWD_TO_VSI_LIST) {
25639daf8208SAnirudh Venkataramanan 			act |= ICE_SINGLE_ACT_PRUNE;
25649daf8208SAnirudh Venkataramanan 			act |= ICE_SINGLE_ACT_EGRESS | ICE_SINGLE_ACT_INGRESS;
25659daf8208SAnirudh Venkataramanan 		}
25669daf8208SAnirudh Venkataramanan 		break;
25679daf8208SAnirudh Venkataramanan 	case ICE_SW_LKUP_ETHERTYPE_MAC:
25689daf8208SAnirudh Venkataramanan 		daddr = f_info->l_data.ethertype_mac.mac_addr;
25694e83fc93SBruce Allan 		fallthrough;
25709daf8208SAnirudh Venkataramanan 	case ICE_SW_LKUP_ETHERTYPE:
2571feee3cb3SBruce Allan 		off = (__force __be16 *)(eth_hdr + ICE_ETH_ETHTYPE_OFFSET);
25729daf8208SAnirudh Venkataramanan 		*off = cpu_to_be16(f_info->l_data.ethertype_mac.ethertype);
25739daf8208SAnirudh Venkataramanan 		break;
25749daf8208SAnirudh Venkataramanan 	case ICE_SW_LKUP_MAC_VLAN:
25759daf8208SAnirudh Venkataramanan 		daddr = f_info->l_data.mac_vlan.mac_addr;
25769daf8208SAnirudh Venkataramanan 		vlan_id = f_info->l_data.mac_vlan.vlan_id;
25779daf8208SAnirudh Venkataramanan 		break;
25789daf8208SAnirudh Venkataramanan 	case ICE_SW_LKUP_PROMISC_VLAN:
25799daf8208SAnirudh Venkataramanan 		vlan_id = f_info->l_data.mac_vlan.vlan_id;
25804e83fc93SBruce Allan 		fallthrough;
25819daf8208SAnirudh Venkataramanan 	case ICE_SW_LKUP_PROMISC:
25829daf8208SAnirudh Venkataramanan 		daddr = f_info->l_data.mac_vlan.mac_addr;
25839daf8208SAnirudh Venkataramanan 		break;
25849daf8208SAnirudh Venkataramanan 	default:
25859daf8208SAnirudh Venkataramanan 		break;
25869daf8208SAnirudh Venkataramanan 	}
25879daf8208SAnirudh Venkataramanan 
25886e1ff618SAlexander Lobakin 	s_rule->hdr.type = (f_info->flag & ICE_FLTR_RX) ?
25899daf8208SAnirudh Venkataramanan 		cpu_to_le16(ICE_AQC_SW_RULES_T_LKUP_RX) :
25909daf8208SAnirudh Venkataramanan 		cpu_to_le16(ICE_AQC_SW_RULES_T_LKUP_TX);
25919daf8208SAnirudh Venkataramanan 
25929daf8208SAnirudh Venkataramanan 	/* Recipe set depending on lookup type */
25936e1ff618SAlexander Lobakin 	s_rule->recipe_id = cpu_to_le16(f_info->lkup_type);
25946e1ff618SAlexander Lobakin 	s_rule->src = cpu_to_le16(f_info->src);
25956e1ff618SAlexander Lobakin 	s_rule->act = cpu_to_le32(act);
25969daf8208SAnirudh Venkataramanan 
25979daf8208SAnirudh Venkataramanan 	if (daddr)
259874118f7aSZhenning Xiao 		ether_addr_copy(eth_hdr + ICE_ETH_DA_OFFSET, daddr);
25999daf8208SAnirudh Venkataramanan 
26009daf8208SAnirudh Venkataramanan 	if (!(vlan_id > ICE_MAX_VLAN_ID)) {
2601feee3cb3SBruce Allan 		off = (__force __be16 *)(eth_hdr + ICE_ETH_VLAN_TCI_OFFSET);
26029daf8208SAnirudh Venkataramanan 		*off = cpu_to_be16(vlan_id);
26032bfefa2dSBrett Creeley 		off = (__force __be16 *)(eth_hdr + ICE_ETH_ETHTYPE_OFFSET);
26042bfefa2dSBrett Creeley 		*off = cpu_to_be16(vlan_tpid);
26059daf8208SAnirudh Venkataramanan 	}
26069daf8208SAnirudh Venkataramanan 
26079daf8208SAnirudh Venkataramanan 	/* Create the switch rule with the final dummy Ethernet header */
26089daf8208SAnirudh Venkataramanan 	if (opc != ice_aqc_opc_update_sw_rules)
26096e1ff618SAlexander Lobakin 		s_rule->hdr_len = cpu_to_le16(eth_hdr_sz);
26109daf8208SAnirudh Venkataramanan }
26119daf8208SAnirudh Venkataramanan 
26129daf8208SAnirudh Venkataramanan /**
26139daf8208SAnirudh Venkataramanan  * ice_add_marker_act
26149daf8208SAnirudh Venkataramanan  * @hw: pointer to the hardware structure
26159daf8208SAnirudh Venkataramanan  * @m_ent: the management entry for which sw marker needs to be added
26169daf8208SAnirudh Venkataramanan  * @sw_marker: sw marker to tag the Rx descriptor with
2617f9867df6SAnirudh Venkataramanan  * @l_id: large action resource ID
26189daf8208SAnirudh Venkataramanan  *
26199daf8208SAnirudh Venkataramanan  * Create a large action to hold software marker and update the switch rule
26209daf8208SAnirudh Venkataramanan  * entry pointed by m_ent with newly created large action
26219daf8208SAnirudh Venkataramanan  */
26225e24d598STony Nguyen static int
ice_add_marker_act(struct ice_hw * hw,struct ice_fltr_mgmt_list_entry * m_ent,u16 sw_marker,u16 l_id)26239daf8208SAnirudh Venkataramanan ice_add_marker_act(struct ice_hw *hw, struct ice_fltr_mgmt_list_entry *m_ent,
26249daf8208SAnirudh Venkataramanan 		   u16 sw_marker, u16 l_id)
26259daf8208SAnirudh Venkataramanan {
26266e1ff618SAlexander Lobakin 	struct ice_sw_rule_lkup_rx_tx *rx_tx;
26276e1ff618SAlexander Lobakin 	struct ice_sw_rule_lg_act *lg_act;
26289daf8208SAnirudh Venkataramanan 	/* For software marker we need 3 large actions
26299daf8208SAnirudh Venkataramanan 	 * 1. FWD action: FWD TO VSI or VSI LIST
2630f9867df6SAnirudh Venkataramanan 	 * 2. GENERIC VALUE action to hold the profile ID
2631f9867df6SAnirudh Venkataramanan 	 * 3. GENERIC VALUE action to hold the software marker ID
26329daf8208SAnirudh Venkataramanan 	 */
26339daf8208SAnirudh Venkataramanan 	const u16 num_lg_acts = 3;
26349daf8208SAnirudh Venkataramanan 	u16 lg_act_size;
26359daf8208SAnirudh Venkataramanan 	u16 rules_size;
26365518ac2aSTony Nguyen 	int status;
26379daf8208SAnirudh Venkataramanan 	u32 act;
26385726ca0eSAnirudh Venkataramanan 	u16 id;
26399daf8208SAnirudh Venkataramanan 
26409daf8208SAnirudh Venkataramanan 	if (m_ent->fltr_info.lkup_type != ICE_SW_LKUP_MAC)
2641d54699e2STony Nguyen 		return -EINVAL;
26429daf8208SAnirudh Venkataramanan 
26439daf8208SAnirudh Venkataramanan 	/* Create two back-to-back switch rules and submit them to the HW using
26449daf8208SAnirudh Venkataramanan 	 * one memory buffer:
26459daf8208SAnirudh Venkataramanan 	 *    1. Large Action
2646d337f2afSAnirudh Venkataramanan 	 *    2. Look up Tx Rx
26479daf8208SAnirudh Venkataramanan 	 */
26486e1ff618SAlexander Lobakin 	lg_act_size = (u16)ICE_SW_RULE_LG_ACT_SIZE(lg_act, num_lg_acts);
26496e1ff618SAlexander Lobakin 	rules_size = lg_act_size + ICE_SW_RULE_RX_TX_ETH_HDR_SIZE(rx_tx);
26509daf8208SAnirudh Venkataramanan 	lg_act = devm_kzalloc(ice_hw_to_dev(hw), rules_size, GFP_KERNEL);
26519daf8208SAnirudh Venkataramanan 	if (!lg_act)
2652d54699e2STony Nguyen 		return -ENOMEM;
26539daf8208SAnirudh Venkataramanan 
26546e1ff618SAlexander Lobakin 	rx_tx = (typeof(rx_tx))((u8 *)lg_act + lg_act_size);
26559daf8208SAnirudh Venkataramanan 
26569daf8208SAnirudh Venkataramanan 	/* Fill in the first switch rule i.e. large action */
26576e1ff618SAlexander Lobakin 	lg_act->hdr.type = cpu_to_le16(ICE_AQC_SW_RULES_T_LG_ACT);
26586e1ff618SAlexander Lobakin 	lg_act->index = cpu_to_le16(l_id);
26596e1ff618SAlexander Lobakin 	lg_act->size = cpu_to_le16(num_lg_acts);
26609daf8208SAnirudh Venkataramanan 
26619daf8208SAnirudh Venkataramanan 	/* First action VSI forwarding or VSI list forwarding depending on how
26629daf8208SAnirudh Venkataramanan 	 * many VSIs
26639daf8208SAnirudh Venkataramanan 	 */
26645726ca0eSAnirudh Venkataramanan 	id = (m_ent->vsi_count > 1) ? m_ent->fltr_info.fwd_id.vsi_list_id :
26655726ca0eSAnirudh Venkataramanan 		m_ent->fltr_info.fwd_id.hw_vsi_id;
26669daf8208SAnirudh Venkataramanan 
26679daf8208SAnirudh Venkataramanan 	act = ICE_LG_ACT_VSI_FORWARDING | ICE_LG_ACT_VALID_BIT;
266866486d89SBruce Allan 	act |= (id << ICE_LG_ACT_VSI_LIST_ID_S) & ICE_LG_ACT_VSI_LIST_ID_M;
26699daf8208SAnirudh Venkataramanan 	if (m_ent->vsi_count > 1)
26709daf8208SAnirudh Venkataramanan 		act |= ICE_LG_ACT_VSI_LIST;
26716e1ff618SAlexander Lobakin 	lg_act->act[0] = cpu_to_le32(act);
26729daf8208SAnirudh Venkataramanan 
26739daf8208SAnirudh Venkataramanan 	/* Second action descriptor type */
26749daf8208SAnirudh Venkataramanan 	act = ICE_LG_ACT_GENERIC;
26759daf8208SAnirudh Venkataramanan 
26769daf8208SAnirudh Venkataramanan 	act |= (1 << ICE_LG_ACT_GENERIC_VALUE_S) & ICE_LG_ACT_GENERIC_VALUE_M;
26776e1ff618SAlexander Lobakin 	lg_act->act[1] = cpu_to_le32(act);
26789daf8208SAnirudh Venkataramanan 
26794381147dSAnirudh Venkataramanan 	act = (ICE_LG_ACT_GENERIC_OFF_RX_DESC_PROF_IDX <<
26804381147dSAnirudh Venkataramanan 	       ICE_LG_ACT_GENERIC_OFFSET_S) & ICE_LG_ACT_GENERIC_OFFSET_M;
26819daf8208SAnirudh Venkataramanan 
26829daf8208SAnirudh Venkataramanan 	/* Third action Marker value */
26839daf8208SAnirudh Venkataramanan 	act |= ICE_LG_ACT_GENERIC;
26849daf8208SAnirudh Venkataramanan 	act |= (sw_marker << ICE_LG_ACT_GENERIC_VALUE_S) &
26859daf8208SAnirudh Venkataramanan 		ICE_LG_ACT_GENERIC_VALUE_M;
26869daf8208SAnirudh Venkataramanan 
26876e1ff618SAlexander Lobakin 	lg_act->act[2] = cpu_to_le32(act);
26889daf8208SAnirudh Venkataramanan 
2689d337f2afSAnirudh Venkataramanan 	/* call the fill switch rule to fill the lookup Tx Rx structure */
26909daf8208SAnirudh Venkataramanan 	ice_fill_sw_rule(hw, &m_ent->fltr_info, rx_tx,
26919daf8208SAnirudh Venkataramanan 			 ice_aqc_opc_update_sw_rules);
26929daf8208SAnirudh Venkataramanan 
2693f9867df6SAnirudh Venkataramanan 	/* Update the action to point to the large action ID */
26946e1ff618SAlexander Lobakin 	rx_tx->act = cpu_to_le32(ICE_SINGLE_ACT_PTR |
26959daf8208SAnirudh Venkataramanan 				 ((l_id << ICE_SINGLE_ACT_PTR_VAL_S) &
26969daf8208SAnirudh Venkataramanan 				  ICE_SINGLE_ACT_PTR_VAL_M));
26979daf8208SAnirudh Venkataramanan 
2698f9867df6SAnirudh Venkataramanan 	/* Use the filter rule ID of the previously created rule with single
26999daf8208SAnirudh Venkataramanan 	 * act. Once the update happens, hardware will treat this as large
27009daf8208SAnirudh Venkataramanan 	 * action
27019daf8208SAnirudh Venkataramanan 	 */
27026e1ff618SAlexander Lobakin 	rx_tx->index = cpu_to_le16(m_ent->fltr_info.fltr_rule_id);
27039daf8208SAnirudh Venkataramanan 
27049daf8208SAnirudh Venkataramanan 	status = ice_aq_sw_rules(hw, lg_act, rules_size, 2,
27059daf8208SAnirudh Venkataramanan 				 ice_aqc_opc_update_sw_rules, NULL);
27069daf8208SAnirudh Venkataramanan 	if (!status) {
27079daf8208SAnirudh Venkataramanan 		m_ent->lg_act_idx = l_id;
27089daf8208SAnirudh Venkataramanan 		m_ent->sw_marker_id = sw_marker;
27099daf8208SAnirudh Venkataramanan 	}
27109daf8208SAnirudh Venkataramanan 
27119daf8208SAnirudh Venkataramanan 	devm_kfree(ice_hw_to_dev(hw), lg_act);
27129daf8208SAnirudh Venkataramanan 	return status;
27139daf8208SAnirudh Venkataramanan }
27149daf8208SAnirudh Venkataramanan 
27159daf8208SAnirudh Venkataramanan /**
27169daf8208SAnirudh Venkataramanan  * ice_create_vsi_list_map
27179daf8208SAnirudh Venkataramanan  * @hw: pointer to the hardware structure
27185726ca0eSAnirudh Venkataramanan  * @vsi_handle_arr: array of VSI handles to set in the VSI mapping
27195726ca0eSAnirudh Venkataramanan  * @num_vsi: number of VSI handles in the array
2720f9867df6SAnirudh Venkataramanan  * @vsi_list_id: VSI list ID generated as part of allocate resource
27219daf8208SAnirudh Venkataramanan  *
2722f9867df6SAnirudh Venkataramanan  * Helper function to create a new entry of VSI list ID to VSI mapping
2723f9867df6SAnirudh Venkataramanan  * using the given VSI list ID
27249daf8208SAnirudh Venkataramanan  */
27259daf8208SAnirudh Venkataramanan static struct ice_vsi_list_map_info *
ice_create_vsi_list_map(struct ice_hw * hw,u16 * vsi_handle_arr,u16 num_vsi,u16 vsi_list_id)27265726ca0eSAnirudh Venkataramanan ice_create_vsi_list_map(struct ice_hw *hw, u16 *vsi_handle_arr, u16 num_vsi,
27279daf8208SAnirudh Venkataramanan 			u16 vsi_list_id)
27289daf8208SAnirudh Venkataramanan {
27299daf8208SAnirudh Venkataramanan 	struct ice_switch_info *sw = hw->switch_info;
27309daf8208SAnirudh Venkataramanan 	struct ice_vsi_list_map_info *v_map;
27319daf8208SAnirudh Venkataramanan 	int i;
27329daf8208SAnirudh Venkataramanan 
273336ac7911SBruce Allan 	v_map = devm_kzalloc(ice_hw_to_dev(hw), sizeof(*v_map), GFP_KERNEL);
27349daf8208SAnirudh Venkataramanan 	if (!v_map)
27359daf8208SAnirudh Venkataramanan 		return NULL;
27369daf8208SAnirudh Venkataramanan 
27379daf8208SAnirudh Venkataramanan 	v_map->vsi_list_id = vsi_list_id;
27385726ca0eSAnirudh Venkataramanan 	v_map->ref_cnt = 1;
27399daf8208SAnirudh Venkataramanan 	for (i = 0; i < num_vsi; i++)
27405726ca0eSAnirudh Venkataramanan 		set_bit(vsi_handle_arr[i], v_map->vsi_map);
27419daf8208SAnirudh Venkataramanan 
27429daf8208SAnirudh Venkataramanan 	list_add(&v_map->list_entry, &sw->vsi_list_map_head);
27439daf8208SAnirudh Venkataramanan 	return v_map;
27449daf8208SAnirudh Venkataramanan }
27459daf8208SAnirudh Venkataramanan 
27469daf8208SAnirudh Venkataramanan /**
27479daf8208SAnirudh Venkataramanan  * ice_update_vsi_list_rule
27489daf8208SAnirudh Venkataramanan  * @hw: pointer to the hardware structure
27495726ca0eSAnirudh Venkataramanan  * @vsi_handle_arr: array of VSI handles to form a VSI list
27505726ca0eSAnirudh Venkataramanan  * @num_vsi: number of VSI handles in the array
2751f9867df6SAnirudh Venkataramanan  * @vsi_list_id: VSI list ID generated as part of allocate resource
27529daf8208SAnirudh Venkataramanan  * @remove: Boolean value to indicate if this is a remove action
27539daf8208SAnirudh Venkataramanan  * @opc: switch rules population command type - pass in the command opcode
27549daf8208SAnirudh Venkataramanan  * @lkup_type: lookup type of the filter
27559daf8208SAnirudh Venkataramanan  *
27569daf8208SAnirudh Venkataramanan  * Call AQ command to add a new switch rule or update existing switch rule
2757f9867df6SAnirudh Venkataramanan  * using the given VSI list ID
27589daf8208SAnirudh Venkataramanan  */
27595e24d598STony Nguyen static int
ice_update_vsi_list_rule(struct ice_hw * hw,u16 * vsi_handle_arr,u16 num_vsi,u16 vsi_list_id,bool remove,enum ice_adminq_opc opc,enum ice_sw_lkup_type lkup_type)27605726ca0eSAnirudh Venkataramanan ice_update_vsi_list_rule(struct ice_hw *hw, u16 *vsi_handle_arr, u16 num_vsi,
27619daf8208SAnirudh Venkataramanan 			 u16 vsi_list_id, bool remove, enum ice_adminq_opc opc,
27629daf8208SAnirudh Venkataramanan 			 enum ice_sw_lkup_type lkup_type)
27639daf8208SAnirudh Venkataramanan {
27646e1ff618SAlexander Lobakin 	struct ice_sw_rule_vsi_list *s_rule;
27659daf8208SAnirudh Venkataramanan 	u16 s_rule_size;
27666dae8aa0SBruce Allan 	u16 rule_type;
27675518ac2aSTony Nguyen 	int status;
27689daf8208SAnirudh Venkataramanan 	int i;
27699daf8208SAnirudh Venkataramanan 
27709daf8208SAnirudh Venkataramanan 	if (!num_vsi)
2771d54699e2STony Nguyen 		return -EINVAL;
27729daf8208SAnirudh Venkataramanan 
27739daf8208SAnirudh Venkataramanan 	if (lkup_type == ICE_SW_LKUP_MAC ||
27749daf8208SAnirudh Venkataramanan 	    lkup_type == ICE_SW_LKUP_MAC_VLAN ||
27759daf8208SAnirudh Venkataramanan 	    lkup_type == ICE_SW_LKUP_ETHERTYPE ||
27769daf8208SAnirudh Venkataramanan 	    lkup_type == ICE_SW_LKUP_ETHERTYPE_MAC ||
27779daf8208SAnirudh Venkataramanan 	    lkup_type == ICE_SW_LKUP_PROMISC ||
2778d7393425SMichal Wilczynski 	    lkup_type == ICE_SW_LKUP_PROMISC_VLAN ||
2779*714782d5SMarcin Szycik 	    lkup_type == ICE_SW_LKUP_DFLT ||
2780*714782d5SMarcin Szycik 	    lkup_type == ICE_SW_LKUP_LAST)
27816dae8aa0SBruce Allan 		rule_type = remove ? ICE_AQC_SW_RULES_T_VSI_LIST_CLEAR :
27829daf8208SAnirudh Venkataramanan 			ICE_AQC_SW_RULES_T_VSI_LIST_SET;
27839daf8208SAnirudh Venkataramanan 	else if (lkup_type == ICE_SW_LKUP_VLAN)
27846dae8aa0SBruce Allan 		rule_type = remove ? ICE_AQC_SW_RULES_T_PRUNE_LIST_CLEAR :
27859daf8208SAnirudh Venkataramanan 			ICE_AQC_SW_RULES_T_PRUNE_LIST_SET;
27869daf8208SAnirudh Venkataramanan 	else
2787d54699e2STony Nguyen 		return -EINVAL;
27889daf8208SAnirudh Venkataramanan 
27896e1ff618SAlexander Lobakin 	s_rule_size = (u16)ICE_SW_RULE_VSI_LIST_SIZE(s_rule, num_vsi);
27909daf8208SAnirudh Venkataramanan 	s_rule = devm_kzalloc(ice_hw_to_dev(hw), s_rule_size, GFP_KERNEL);
27919daf8208SAnirudh Venkataramanan 	if (!s_rule)
2792d54699e2STony Nguyen 		return -ENOMEM;
27935726ca0eSAnirudh Venkataramanan 	for (i = 0; i < num_vsi; i++) {
27945726ca0eSAnirudh Venkataramanan 		if (!ice_is_vsi_valid(hw, vsi_handle_arr[i])) {
2795d54699e2STony Nguyen 			status = -EINVAL;
27965726ca0eSAnirudh Venkataramanan 			goto exit;
27975726ca0eSAnirudh Venkataramanan 		}
27985726ca0eSAnirudh Venkataramanan 		/* AQ call requires hw_vsi_id(s) */
27996e1ff618SAlexander Lobakin 		s_rule->vsi[i] =
28005726ca0eSAnirudh Venkataramanan 			cpu_to_le16(ice_get_hw_vsi_num(hw, vsi_handle_arr[i]));
28015726ca0eSAnirudh Venkataramanan 	}
28029daf8208SAnirudh Venkataramanan 
28036e1ff618SAlexander Lobakin 	s_rule->hdr.type = cpu_to_le16(rule_type);
28046e1ff618SAlexander Lobakin 	s_rule->number_vsi = cpu_to_le16(num_vsi);
28056e1ff618SAlexander Lobakin 	s_rule->index = cpu_to_le16(vsi_list_id);
28069daf8208SAnirudh Venkataramanan 
28079daf8208SAnirudh Venkataramanan 	status = ice_aq_sw_rules(hw, s_rule, s_rule_size, 1, opc, NULL);
28089daf8208SAnirudh Venkataramanan 
28095726ca0eSAnirudh Venkataramanan exit:
28109daf8208SAnirudh Venkataramanan 	devm_kfree(ice_hw_to_dev(hw), s_rule);
28119daf8208SAnirudh Venkataramanan 	return status;
28129daf8208SAnirudh Venkataramanan }
28139daf8208SAnirudh Venkataramanan 
28149daf8208SAnirudh Venkataramanan /**
28159daf8208SAnirudh Venkataramanan  * ice_create_vsi_list_rule - Creates and populates a VSI list rule
2816f9867df6SAnirudh Venkataramanan  * @hw: pointer to the HW struct
28175726ca0eSAnirudh Venkataramanan  * @vsi_handle_arr: array of VSI handles to form a VSI list
28185726ca0eSAnirudh Venkataramanan  * @num_vsi: number of VSI handles in the array
28199daf8208SAnirudh Venkataramanan  * @vsi_list_id: stores the ID of the VSI list to be created
28209daf8208SAnirudh Venkataramanan  * @lkup_type: switch rule filter's lookup type
28219daf8208SAnirudh Venkataramanan  */
28225e24d598STony Nguyen static int
ice_create_vsi_list_rule(struct ice_hw * hw,u16 * vsi_handle_arr,u16 num_vsi,u16 * vsi_list_id,enum ice_sw_lkup_type lkup_type)28235726ca0eSAnirudh Venkataramanan ice_create_vsi_list_rule(struct ice_hw *hw, u16 *vsi_handle_arr, u16 num_vsi,
28249daf8208SAnirudh Venkataramanan 			 u16 *vsi_list_id, enum ice_sw_lkup_type lkup_type)
28259daf8208SAnirudh Venkataramanan {
28265e24d598STony Nguyen 	int status;
28279daf8208SAnirudh Venkataramanan 
28289daf8208SAnirudh Venkataramanan 	status = ice_aq_alloc_free_vsi_list(hw, vsi_list_id, lkup_type,
28299daf8208SAnirudh Venkataramanan 					    ice_aqc_opc_alloc_res);
28309daf8208SAnirudh Venkataramanan 	if (status)
28319daf8208SAnirudh Venkataramanan 		return status;
28329daf8208SAnirudh Venkataramanan 
28339daf8208SAnirudh Venkataramanan 	/* Update the newly created VSI list to include the specified VSIs */
28345726ca0eSAnirudh Venkataramanan 	return ice_update_vsi_list_rule(hw, vsi_handle_arr, num_vsi,
28355726ca0eSAnirudh Venkataramanan 					*vsi_list_id, false,
28365726ca0eSAnirudh Venkataramanan 					ice_aqc_opc_add_sw_rules, lkup_type);
28379daf8208SAnirudh Venkataramanan }
28389daf8208SAnirudh Venkataramanan 
28399daf8208SAnirudh Venkataramanan /**
28409daf8208SAnirudh Venkataramanan  * ice_create_pkt_fwd_rule
28419daf8208SAnirudh Venkataramanan  * @hw: pointer to the hardware structure
28429daf8208SAnirudh Venkataramanan  * @f_entry: entry containing packet forwarding information
28439daf8208SAnirudh Venkataramanan  *
28449daf8208SAnirudh Venkataramanan  * Create switch rule with given filter information and add an entry
28459daf8208SAnirudh Venkataramanan  * to the corresponding filter management list to track this switch rule
28469daf8208SAnirudh Venkataramanan  * and VSI mapping
28479daf8208SAnirudh Venkataramanan  */
28485e24d598STony Nguyen static int
ice_create_pkt_fwd_rule(struct ice_hw * hw,struct ice_fltr_list_entry * f_entry)28499daf8208SAnirudh Venkataramanan ice_create_pkt_fwd_rule(struct ice_hw *hw,
28509daf8208SAnirudh Venkataramanan 			struct ice_fltr_list_entry *f_entry)
28519daf8208SAnirudh Venkataramanan {
28529daf8208SAnirudh Venkataramanan 	struct ice_fltr_mgmt_list_entry *fm_entry;
28536e1ff618SAlexander Lobakin 	struct ice_sw_rule_lkup_rx_tx *s_rule;
28549daf8208SAnirudh Venkataramanan 	enum ice_sw_lkup_type l_type;
285580d144c9SAnirudh Venkataramanan 	struct ice_sw_recipe *recp;
28565e24d598STony Nguyen 	int status;
28579daf8208SAnirudh Venkataramanan 
28589daf8208SAnirudh Venkataramanan 	s_rule = devm_kzalloc(ice_hw_to_dev(hw),
28596e1ff618SAlexander Lobakin 			      ICE_SW_RULE_RX_TX_ETH_HDR_SIZE(s_rule),
28606e1ff618SAlexander Lobakin 			      GFP_KERNEL);
28619daf8208SAnirudh Venkataramanan 	if (!s_rule)
2862d54699e2STony Nguyen 		return -ENOMEM;
28639daf8208SAnirudh Venkataramanan 	fm_entry = devm_kzalloc(ice_hw_to_dev(hw), sizeof(*fm_entry),
28649daf8208SAnirudh Venkataramanan 				GFP_KERNEL);
28659daf8208SAnirudh Venkataramanan 	if (!fm_entry) {
2866d54699e2STony Nguyen 		status = -ENOMEM;
28679daf8208SAnirudh Venkataramanan 		goto ice_create_pkt_fwd_rule_exit;
28689daf8208SAnirudh Venkataramanan 	}
28699daf8208SAnirudh Venkataramanan 
28709daf8208SAnirudh Venkataramanan 	fm_entry->fltr_info = f_entry->fltr_info;
28719daf8208SAnirudh Venkataramanan 
28729daf8208SAnirudh Venkataramanan 	/* Initialize all the fields for the management entry */
28739daf8208SAnirudh Venkataramanan 	fm_entry->vsi_count = 1;
28749daf8208SAnirudh Venkataramanan 	fm_entry->lg_act_idx = ICE_INVAL_LG_ACT_INDEX;
28759daf8208SAnirudh Venkataramanan 	fm_entry->sw_marker_id = ICE_INVAL_SW_MARKER_ID;
28769daf8208SAnirudh Venkataramanan 	fm_entry->counter_index = ICE_INVAL_COUNTER_ID;
28779daf8208SAnirudh Venkataramanan 
28789daf8208SAnirudh Venkataramanan 	ice_fill_sw_rule(hw, &fm_entry->fltr_info, s_rule,
28799daf8208SAnirudh Venkataramanan 			 ice_aqc_opc_add_sw_rules);
28809daf8208SAnirudh Venkataramanan 
28816e1ff618SAlexander Lobakin 	status = ice_aq_sw_rules(hw, s_rule,
28826e1ff618SAlexander Lobakin 				 ICE_SW_RULE_RX_TX_ETH_HDR_SIZE(s_rule), 1,
28839daf8208SAnirudh Venkataramanan 				 ice_aqc_opc_add_sw_rules, NULL);
28849daf8208SAnirudh Venkataramanan 	if (status) {
28859daf8208SAnirudh Venkataramanan 		devm_kfree(ice_hw_to_dev(hw), fm_entry);
28869daf8208SAnirudh Venkataramanan 		goto ice_create_pkt_fwd_rule_exit;
28879daf8208SAnirudh Venkataramanan 	}
28889daf8208SAnirudh Venkataramanan 
28896e1ff618SAlexander Lobakin 	f_entry->fltr_info.fltr_rule_id = le16_to_cpu(s_rule->index);
28906e1ff618SAlexander Lobakin 	fm_entry->fltr_info.fltr_rule_id = le16_to_cpu(s_rule->index);
28919daf8208SAnirudh Venkataramanan 
28929daf8208SAnirudh Venkataramanan 	/* The book keeping entries will get removed when base driver
28939daf8208SAnirudh Venkataramanan 	 * calls remove filter AQ command
28949daf8208SAnirudh Venkataramanan 	 */
28959daf8208SAnirudh Venkataramanan 	l_type = fm_entry->fltr_info.lkup_type;
289680d144c9SAnirudh Venkataramanan 	recp = &hw->switch_info->recp_list[l_type];
289780d144c9SAnirudh Venkataramanan 	list_add(&fm_entry->list_entry, &recp->filt_rules);
289880d144c9SAnirudh Venkataramanan 
28999daf8208SAnirudh Venkataramanan ice_create_pkt_fwd_rule_exit:
29009daf8208SAnirudh Venkataramanan 	devm_kfree(ice_hw_to_dev(hw), s_rule);
29019daf8208SAnirudh Venkataramanan 	return status;
29029daf8208SAnirudh Venkataramanan }
29039daf8208SAnirudh Venkataramanan 
29049daf8208SAnirudh Venkataramanan /**
29059daf8208SAnirudh Venkataramanan  * ice_update_pkt_fwd_rule
29069daf8208SAnirudh Venkataramanan  * @hw: pointer to the hardware structure
290780d144c9SAnirudh Venkataramanan  * @f_info: filter information for switch rule
29089daf8208SAnirudh Venkataramanan  *
29099daf8208SAnirudh Venkataramanan  * Call AQ command to update a previously created switch rule with a
2910f9867df6SAnirudh Venkataramanan  * VSI list ID
29119daf8208SAnirudh Venkataramanan  */
29125e24d598STony Nguyen static int
ice_update_pkt_fwd_rule(struct ice_hw * hw,struct ice_fltr_info * f_info)291380d144c9SAnirudh Venkataramanan ice_update_pkt_fwd_rule(struct ice_hw *hw, struct ice_fltr_info *f_info)
29149daf8208SAnirudh Venkataramanan {
29156e1ff618SAlexander Lobakin 	struct ice_sw_rule_lkup_rx_tx *s_rule;
29165e24d598STony Nguyen 	int status;
29179daf8208SAnirudh Venkataramanan 
29189daf8208SAnirudh Venkataramanan 	s_rule = devm_kzalloc(ice_hw_to_dev(hw),
29196e1ff618SAlexander Lobakin 			      ICE_SW_RULE_RX_TX_ETH_HDR_SIZE(s_rule),
29206e1ff618SAlexander Lobakin 			      GFP_KERNEL);
29219daf8208SAnirudh Venkataramanan 	if (!s_rule)
2922d54699e2STony Nguyen 		return -ENOMEM;
29239daf8208SAnirudh Venkataramanan 
292480d144c9SAnirudh Venkataramanan 	ice_fill_sw_rule(hw, f_info, s_rule, ice_aqc_opc_update_sw_rules);
29259daf8208SAnirudh Venkataramanan 
29266e1ff618SAlexander Lobakin 	s_rule->index = cpu_to_le16(f_info->fltr_rule_id);
29279daf8208SAnirudh Venkataramanan 
29289daf8208SAnirudh Venkataramanan 	/* Update switch rule with new rule set to forward VSI list */
29296e1ff618SAlexander Lobakin 	status = ice_aq_sw_rules(hw, s_rule,
29306e1ff618SAlexander Lobakin 				 ICE_SW_RULE_RX_TX_ETH_HDR_SIZE(s_rule), 1,
29319daf8208SAnirudh Venkataramanan 				 ice_aqc_opc_update_sw_rules, NULL);
29329daf8208SAnirudh Venkataramanan 
29339daf8208SAnirudh Venkataramanan 	devm_kfree(ice_hw_to_dev(hw), s_rule);
29349daf8208SAnirudh Venkataramanan 	return status;
29359daf8208SAnirudh Venkataramanan }
29369daf8208SAnirudh Venkataramanan 
29379daf8208SAnirudh Venkataramanan /**
2938b1edc14aSMd Fahad Iqbal Polash  * ice_update_sw_rule_bridge_mode
2939f9867df6SAnirudh Venkataramanan  * @hw: pointer to the HW struct
2940b1edc14aSMd Fahad Iqbal Polash  *
2941b1edc14aSMd Fahad Iqbal Polash  * Updates unicast switch filter rules based on VEB/VEPA mode
2942b1edc14aSMd Fahad Iqbal Polash  */
ice_update_sw_rule_bridge_mode(struct ice_hw * hw)29435e24d598STony Nguyen int ice_update_sw_rule_bridge_mode(struct ice_hw *hw)
2944b1edc14aSMd Fahad Iqbal Polash {
2945b1edc14aSMd Fahad Iqbal Polash 	struct ice_switch_info *sw = hw->switch_info;
2946b1edc14aSMd Fahad Iqbal Polash 	struct ice_fltr_mgmt_list_entry *fm_entry;
2947b1edc14aSMd Fahad Iqbal Polash 	struct list_head *rule_head;
2948b1edc14aSMd Fahad Iqbal Polash 	struct mutex *rule_lock; /* Lock to protect filter rule list */
29495518ac2aSTony Nguyen 	int status = 0;
2950b1edc14aSMd Fahad Iqbal Polash 
2951b1edc14aSMd Fahad Iqbal Polash 	rule_lock = &sw->recp_list[ICE_SW_LKUP_MAC].filt_rule_lock;
2952b1edc14aSMd Fahad Iqbal Polash 	rule_head = &sw->recp_list[ICE_SW_LKUP_MAC].filt_rules;
2953b1edc14aSMd Fahad Iqbal Polash 
2954b1edc14aSMd Fahad Iqbal Polash 	mutex_lock(rule_lock);
2955b1edc14aSMd Fahad Iqbal Polash 	list_for_each_entry(fm_entry, rule_head, list_entry) {
2956b1edc14aSMd Fahad Iqbal Polash 		struct ice_fltr_info *fi = &fm_entry->fltr_info;
2957b1edc14aSMd Fahad Iqbal Polash 		u8 *addr = fi->l_data.mac.mac_addr;
2958b1edc14aSMd Fahad Iqbal Polash 
2959b1edc14aSMd Fahad Iqbal Polash 		/* Update unicast Tx rules to reflect the selected
2960b1edc14aSMd Fahad Iqbal Polash 		 * VEB/VEPA mode
2961b1edc14aSMd Fahad Iqbal Polash 		 */
2962b1edc14aSMd Fahad Iqbal Polash 		if ((fi->flag & ICE_FLTR_TX) && is_unicast_ether_addr(addr) &&
2963b1edc14aSMd Fahad Iqbal Polash 		    (fi->fltr_act == ICE_FWD_TO_VSI ||
2964b1edc14aSMd Fahad Iqbal Polash 		     fi->fltr_act == ICE_FWD_TO_VSI_LIST ||
2965b1edc14aSMd Fahad Iqbal Polash 		     fi->fltr_act == ICE_FWD_TO_Q ||
2966b1edc14aSMd Fahad Iqbal Polash 		     fi->fltr_act == ICE_FWD_TO_QGRP)) {
2967b1edc14aSMd Fahad Iqbal Polash 			status = ice_update_pkt_fwd_rule(hw, fi);
2968b1edc14aSMd Fahad Iqbal Polash 			if (status)
2969b1edc14aSMd Fahad Iqbal Polash 				break;
2970b1edc14aSMd Fahad Iqbal Polash 		}
2971b1edc14aSMd Fahad Iqbal Polash 	}
2972b1edc14aSMd Fahad Iqbal Polash 
2973b1edc14aSMd Fahad Iqbal Polash 	mutex_unlock(rule_lock);
2974b1edc14aSMd Fahad Iqbal Polash 
2975b1edc14aSMd Fahad Iqbal Polash 	return status;
2976b1edc14aSMd Fahad Iqbal Polash }
2977b1edc14aSMd Fahad Iqbal Polash 
2978b1edc14aSMd Fahad Iqbal Polash /**
297980d144c9SAnirudh Venkataramanan  * ice_add_update_vsi_list
29809daf8208SAnirudh Venkataramanan  * @hw: pointer to the hardware structure
29819daf8208SAnirudh Venkataramanan  * @m_entry: pointer to current filter management list entry
29829daf8208SAnirudh Venkataramanan  * @cur_fltr: filter information from the book keeping entry
29839daf8208SAnirudh Venkataramanan  * @new_fltr: filter information with the new VSI to be added
29849daf8208SAnirudh Venkataramanan  *
29859daf8208SAnirudh Venkataramanan  * Call AQ command to add or update previously created VSI list with new VSI.
29869daf8208SAnirudh Venkataramanan  *
29879daf8208SAnirudh Venkataramanan  * Helper function to do book keeping associated with adding filter information
2988d337f2afSAnirudh Venkataramanan  * The algorithm to do the book keeping is described below :
29899daf8208SAnirudh Venkataramanan  * When a VSI needs to subscribe to a given filter (MAC/VLAN/Ethtype etc.)
29909daf8208SAnirudh Venkataramanan  *	if only one VSI has been added till now
29919daf8208SAnirudh Venkataramanan  *		Allocate a new VSI list and add two VSIs
29929daf8208SAnirudh Venkataramanan  *		to this list using switch rule command
29939daf8208SAnirudh Venkataramanan  *		Update the previously created switch rule with the
2994f9867df6SAnirudh Venkataramanan  *		newly created VSI list ID
29959daf8208SAnirudh Venkataramanan  *	if a VSI list was previously created
29969daf8208SAnirudh Venkataramanan  *		Add the new VSI to the previously created VSI list set
29979daf8208SAnirudh Venkataramanan  *		using the update switch rule command
29989daf8208SAnirudh Venkataramanan  */
29995e24d598STony Nguyen static int
ice_add_update_vsi_list(struct ice_hw * hw,struct ice_fltr_mgmt_list_entry * m_entry,struct ice_fltr_info * cur_fltr,struct ice_fltr_info * new_fltr)300080d144c9SAnirudh Venkataramanan ice_add_update_vsi_list(struct ice_hw *hw,
30019daf8208SAnirudh Venkataramanan 			struct ice_fltr_mgmt_list_entry *m_entry,
30029daf8208SAnirudh Venkataramanan 			struct ice_fltr_info *cur_fltr,
30039daf8208SAnirudh Venkataramanan 			struct ice_fltr_info *new_fltr)
30049daf8208SAnirudh Venkataramanan {
30059daf8208SAnirudh Venkataramanan 	u16 vsi_list_id = 0;
30065518ac2aSTony Nguyen 	int status = 0;
30079daf8208SAnirudh Venkataramanan 
30089daf8208SAnirudh Venkataramanan 	if ((cur_fltr->fltr_act == ICE_FWD_TO_Q ||
30099daf8208SAnirudh Venkataramanan 	     cur_fltr->fltr_act == ICE_FWD_TO_QGRP))
3010d54699e2STony Nguyen 		return -EOPNOTSUPP;
30119daf8208SAnirudh Venkataramanan 
30129daf8208SAnirudh Venkataramanan 	if ((new_fltr->fltr_act == ICE_FWD_TO_Q ||
30139daf8208SAnirudh Venkataramanan 	     new_fltr->fltr_act == ICE_FWD_TO_QGRP) &&
30149daf8208SAnirudh Venkataramanan 	    (cur_fltr->fltr_act == ICE_FWD_TO_VSI ||
30159daf8208SAnirudh Venkataramanan 	     cur_fltr->fltr_act == ICE_FWD_TO_VSI_LIST))
3016d54699e2STony Nguyen 		return -EOPNOTSUPP;
30179daf8208SAnirudh Venkataramanan 
30189daf8208SAnirudh Venkataramanan 	if (m_entry->vsi_count < 2 && !m_entry->vsi_list_info) {
30199daf8208SAnirudh Venkataramanan 		/* Only one entry existed in the mapping and it was not already
30209daf8208SAnirudh Venkataramanan 		 * a part of a VSI list. So, create a VSI list with the old and
30219daf8208SAnirudh Venkataramanan 		 * new VSIs.
30229daf8208SAnirudh Venkataramanan 		 */
302380d144c9SAnirudh Venkataramanan 		struct ice_fltr_info tmp_fltr;
30245726ca0eSAnirudh Venkataramanan 		u16 vsi_handle_arr[2];
30259daf8208SAnirudh Venkataramanan 
30269daf8208SAnirudh Venkataramanan 		/* A rule already exists with the new VSI being added */
30275726ca0eSAnirudh Venkataramanan 		if (cur_fltr->fwd_id.hw_vsi_id == new_fltr->fwd_id.hw_vsi_id)
3028d54699e2STony Nguyen 			return -EEXIST;
30299daf8208SAnirudh Venkataramanan 
30305726ca0eSAnirudh Venkataramanan 		vsi_handle_arr[0] = cur_fltr->vsi_handle;
30315726ca0eSAnirudh Venkataramanan 		vsi_handle_arr[1] = new_fltr->vsi_handle;
30325726ca0eSAnirudh Venkataramanan 		status = ice_create_vsi_list_rule(hw, &vsi_handle_arr[0], 2,
30339daf8208SAnirudh Venkataramanan 						  &vsi_list_id,
30349daf8208SAnirudh Venkataramanan 						  new_fltr->lkup_type);
30359daf8208SAnirudh Venkataramanan 		if (status)
30369daf8208SAnirudh Venkataramanan 			return status;
30379daf8208SAnirudh Venkataramanan 
303880d144c9SAnirudh Venkataramanan 		tmp_fltr = *new_fltr;
303980d144c9SAnirudh Venkataramanan 		tmp_fltr.fltr_rule_id = cur_fltr->fltr_rule_id;
304080d144c9SAnirudh Venkataramanan 		tmp_fltr.fltr_act = ICE_FWD_TO_VSI_LIST;
304180d144c9SAnirudh Venkataramanan 		tmp_fltr.fwd_id.vsi_list_id = vsi_list_id;
30429daf8208SAnirudh Venkataramanan 		/* Update the previous switch rule of "MAC forward to VSI" to
30439daf8208SAnirudh Venkataramanan 		 * "MAC fwd to VSI list"
30449daf8208SAnirudh Venkataramanan 		 */
304580d144c9SAnirudh Venkataramanan 		status = ice_update_pkt_fwd_rule(hw, &tmp_fltr);
30469daf8208SAnirudh Venkataramanan 		if (status)
30479daf8208SAnirudh Venkataramanan 			return status;
30489daf8208SAnirudh Venkataramanan 
30499daf8208SAnirudh Venkataramanan 		cur_fltr->fwd_id.vsi_list_id = vsi_list_id;
30509daf8208SAnirudh Venkataramanan 		cur_fltr->fltr_act = ICE_FWD_TO_VSI_LIST;
30519daf8208SAnirudh Venkataramanan 		m_entry->vsi_list_info =
30525726ca0eSAnirudh Venkataramanan 			ice_create_vsi_list_map(hw, &vsi_handle_arr[0], 2,
30539daf8208SAnirudh Venkataramanan 						vsi_list_id);
30549daf8208SAnirudh Venkataramanan 
30557a91d3f0SJacek Bułatek 		if (!m_entry->vsi_list_info)
3056d54699e2STony Nguyen 			return -ENOMEM;
30577a91d3f0SJacek Bułatek 
30589daf8208SAnirudh Venkataramanan 		/* If this entry was large action then the large action needs
30599daf8208SAnirudh Venkataramanan 		 * to be updated to point to FWD to VSI list
30609daf8208SAnirudh Venkataramanan 		 */
30619daf8208SAnirudh Venkataramanan 		if (m_entry->sw_marker_id != ICE_INVAL_SW_MARKER_ID)
30629daf8208SAnirudh Venkataramanan 			status =
30639daf8208SAnirudh Venkataramanan 			    ice_add_marker_act(hw, m_entry,
30649daf8208SAnirudh Venkataramanan 					       m_entry->sw_marker_id,
30659daf8208SAnirudh Venkataramanan 					       m_entry->lg_act_idx);
30669daf8208SAnirudh Venkataramanan 	} else {
30675726ca0eSAnirudh Venkataramanan 		u16 vsi_handle = new_fltr->vsi_handle;
30689daf8208SAnirudh Venkataramanan 		enum ice_adminq_opc opcode;
30699daf8208SAnirudh Venkataramanan 
3070f25dad19SBruce Allan 		if (!m_entry->vsi_list_info)
3071d54699e2STony Nguyen 			return -EIO;
3072f25dad19SBruce Allan 
30739daf8208SAnirudh Venkataramanan 		/* A rule already exists with the new VSI being added */
30745726ca0eSAnirudh Venkataramanan 		if (test_bit(vsi_handle, m_entry->vsi_list_info->vsi_map))
30759daf8208SAnirudh Venkataramanan 			return 0;
30769daf8208SAnirudh Venkataramanan 
30779daf8208SAnirudh Venkataramanan 		/* Update the previously created VSI list set with
3078f9867df6SAnirudh Venkataramanan 		 * the new VSI ID passed in
30799daf8208SAnirudh Venkataramanan 		 */
30809daf8208SAnirudh Venkataramanan 		vsi_list_id = cur_fltr->fwd_id.vsi_list_id;
30819daf8208SAnirudh Venkataramanan 		opcode = ice_aqc_opc_update_sw_rules;
30829daf8208SAnirudh Venkataramanan 
30835726ca0eSAnirudh Venkataramanan 		status = ice_update_vsi_list_rule(hw, &vsi_handle, 1,
30845726ca0eSAnirudh Venkataramanan 						  vsi_list_id, false, opcode,
30859daf8208SAnirudh Venkataramanan 						  new_fltr->lkup_type);
3086f9867df6SAnirudh Venkataramanan 		/* update VSI list mapping info with new VSI ID */
30879daf8208SAnirudh Venkataramanan 		if (!status)
30885726ca0eSAnirudh Venkataramanan 			set_bit(vsi_handle, m_entry->vsi_list_info->vsi_map);
30899daf8208SAnirudh Venkataramanan 	}
30909daf8208SAnirudh Venkataramanan 	if (!status)
30919daf8208SAnirudh Venkataramanan 		m_entry->vsi_count++;
30929daf8208SAnirudh Venkataramanan 	return status;
30939daf8208SAnirudh Venkataramanan }
30949daf8208SAnirudh Venkataramanan 
30959daf8208SAnirudh Venkataramanan /**
309680d144c9SAnirudh Venkataramanan  * ice_find_rule_entry - Search a rule entry
30979daf8208SAnirudh Venkataramanan  * @hw: pointer to the hardware structure
309880d144c9SAnirudh Venkataramanan  * @recp_id: lookup type for which the specified rule needs to be searched
309980d144c9SAnirudh Venkataramanan  * @f_info: rule information
31009daf8208SAnirudh Venkataramanan  *
310180d144c9SAnirudh Venkataramanan  * Helper function to search for a given rule entry
310280d144c9SAnirudh Venkataramanan  * Returns pointer to entry storing the rule if found
31039daf8208SAnirudh Venkataramanan  */
31049daf8208SAnirudh Venkataramanan static struct ice_fltr_mgmt_list_entry *
ice_find_rule_entry(struct ice_hw * hw,u8 recp_id,struct ice_fltr_info * f_info)310580d144c9SAnirudh Venkataramanan ice_find_rule_entry(struct ice_hw *hw, u8 recp_id, struct ice_fltr_info *f_info)
31069daf8208SAnirudh Venkataramanan {
310780d144c9SAnirudh Venkataramanan 	struct ice_fltr_mgmt_list_entry *list_itr, *ret = NULL;
31089daf8208SAnirudh Venkataramanan 	struct ice_switch_info *sw = hw->switch_info;
310980d144c9SAnirudh Venkataramanan 	struct list_head *list_head;
31109daf8208SAnirudh Venkataramanan 
311180d144c9SAnirudh Venkataramanan 	list_head = &sw->recp_list[recp_id].filt_rules;
311280d144c9SAnirudh Venkataramanan 	list_for_each_entry(list_itr, list_head, list_entry) {
311380d144c9SAnirudh Venkataramanan 		if (!memcmp(&f_info->l_data, &list_itr->fltr_info.l_data,
311480d144c9SAnirudh Venkataramanan 			    sizeof(f_info->l_data)) &&
311580d144c9SAnirudh Venkataramanan 		    f_info->flag == list_itr->fltr_info.flag) {
311680d144c9SAnirudh Venkataramanan 			ret = list_itr;
31179daf8208SAnirudh Venkataramanan 			break;
31189daf8208SAnirudh Venkataramanan 		}
31199daf8208SAnirudh Venkataramanan 	}
312080d144c9SAnirudh Venkataramanan 	return ret;
31219daf8208SAnirudh Venkataramanan }
31229daf8208SAnirudh Venkataramanan 
31239daf8208SAnirudh Venkataramanan /**
31245726ca0eSAnirudh Venkataramanan  * ice_find_vsi_list_entry - Search VSI list map with VSI count 1
31255726ca0eSAnirudh Venkataramanan  * @hw: pointer to the hardware structure
31265726ca0eSAnirudh Venkataramanan  * @recp_id: lookup type for which VSI lists needs to be searched
31275726ca0eSAnirudh Venkataramanan  * @vsi_handle: VSI handle to be found in VSI list
3128f9867df6SAnirudh Venkataramanan  * @vsi_list_id: VSI list ID found containing vsi_handle
31295726ca0eSAnirudh Venkataramanan  *
31305726ca0eSAnirudh Venkataramanan  * Helper function to search a VSI list with single entry containing given VSI
31315726ca0eSAnirudh Venkataramanan  * handle element. This can be extended further to search VSI list with more
31325726ca0eSAnirudh Venkataramanan  * than 1 vsi_count. Returns pointer to VSI list entry if found.
31335726ca0eSAnirudh Venkataramanan  */
313423ccae5cSDave Ertman struct ice_vsi_list_map_info *
ice_find_vsi_list_entry(struct ice_hw * hw,u8 recp_id,u16 vsi_handle,u16 * vsi_list_id)31355726ca0eSAnirudh Venkataramanan ice_find_vsi_list_entry(struct ice_hw *hw, u8 recp_id, u16 vsi_handle,
31365726ca0eSAnirudh Venkataramanan 			u16 *vsi_list_id)
31375726ca0eSAnirudh Venkataramanan {
31385726ca0eSAnirudh Venkataramanan 	struct ice_vsi_list_map_info *map_info = NULL;
31395726ca0eSAnirudh Venkataramanan 	struct ice_switch_info *sw = hw->switch_info;
31405726ca0eSAnirudh Venkataramanan 	struct ice_fltr_mgmt_list_entry *list_itr;
31415726ca0eSAnirudh Venkataramanan 	struct list_head *list_head;
31425726ca0eSAnirudh Venkataramanan 
31435726ca0eSAnirudh Venkataramanan 	list_head = &sw->recp_list[recp_id].filt_rules;
31445726ca0eSAnirudh Venkataramanan 	list_for_each_entry(list_itr, list_head, list_entry) {
314523ccae5cSDave Ertman 		if (list_itr->vsi_list_info) {
31465726ca0eSAnirudh Venkataramanan 			map_info = list_itr->vsi_list_info;
31475726ca0eSAnirudh Venkataramanan 			if (test_bit(vsi_handle, map_info->vsi_map)) {
31485726ca0eSAnirudh Venkataramanan 				*vsi_list_id = map_info->vsi_list_id;
31495726ca0eSAnirudh Venkataramanan 				return map_info;
31505726ca0eSAnirudh Venkataramanan 			}
31515726ca0eSAnirudh Venkataramanan 		}
31525726ca0eSAnirudh Venkataramanan 	}
31535726ca0eSAnirudh Venkataramanan 	return NULL;
31545726ca0eSAnirudh Venkataramanan }
31555726ca0eSAnirudh Venkataramanan 
31565726ca0eSAnirudh Venkataramanan /**
315780d144c9SAnirudh Venkataramanan  * ice_add_rule_internal - add rule for a given lookup type
31589daf8208SAnirudh Venkataramanan  * @hw: pointer to the hardware structure
3159f9867df6SAnirudh Venkataramanan  * @recp_id: lookup type (recipe ID) for which rule has to be added
31609daf8208SAnirudh Venkataramanan  * @f_entry: structure containing MAC forwarding information
31619daf8208SAnirudh Venkataramanan  *
316280d144c9SAnirudh Venkataramanan  * Adds or updates the rule lists for a given recipe
31639daf8208SAnirudh Venkataramanan  */
31645e24d598STony Nguyen static int
ice_add_rule_internal(struct ice_hw * hw,u8 recp_id,struct ice_fltr_list_entry * f_entry)316580d144c9SAnirudh Venkataramanan ice_add_rule_internal(struct ice_hw *hw, u8 recp_id,
316680d144c9SAnirudh Venkataramanan 		      struct ice_fltr_list_entry *f_entry)
31679daf8208SAnirudh Venkataramanan {
316880d144c9SAnirudh Venkataramanan 	struct ice_switch_info *sw = hw->switch_info;
31699daf8208SAnirudh Venkataramanan 	struct ice_fltr_info *new_fltr, *cur_fltr;
31709daf8208SAnirudh Venkataramanan 	struct ice_fltr_mgmt_list_entry *m_entry;
317180d144c9SAnirudh Venkataramanan 	struct mutex *rule_lock; /* Lock to protect filter rule list */
31725e24d598STony Nguyen 	int status = 0;
31739daf8208SAnirudh Venkataramanan 
31745726ca0eSAnirudh Venkataramanan 	if (!ice_is_vsi_valid(hw, f_entry->fltr_info.vsi_handle))
3175d54699e2STony Nguyen 		return -EINVAL;
31765726ca0eSAnirudh Venkataramanan 	f_entry->fltr_info.fwd_id.hw_vsi_id =
31775726ca0eSAnirudh Venkataramanan 		ice_get_hw_vsi_num(hw, f_entry->fltr_info.vsi_handle);
31785726ca0eSAnirudh Venkataramanan 
317980d144c9SAnirudh Venkataramanan 	rule_lock = &sw->recp_list[recp_id].filt_rule_lock;
318080d144c9SAnirudh Venkataramanan 
318180d144c9SAnirudh Venkataramanan 	mutex_lock(rule_lock);
31829daf8208SAnirudh Venkataramanan 	new_fltr = &f_entry->fltr_info;
318380d144c9SAnirudh Venkataramanan 	if (new_fltr->flag & ICE_FLTR_RX)
318480d144c9SAnirudh Venkataramanan 		new_fltr->src = hw->port_info->lport;
318580d144c9SAnirudh Venkataramanan 	else if (new_fltr->flag & ICE_FLTR_TX)
31865726ca0eSAnirudh Venkataramanan 		new_fltr->src = f_entry->fltr_info.fwd_id.hw_vsi_id;
31879daf8208SAnirudh Venkataramanan 
318880d144c9SAnirudh Venkataramanan 	m_entry = ice_find_rule_entry(hw, recp_id, new_fltr);
318980d144c9SAnirudh Venkataramanan 	if (!m_entry) {
319080d144c9SAnirudh Venkataramanan 		mutex_unlock(rule_lock);
31919daf8208SAnirudh Venkataramanan 		return ice_create_pkt_fwd_rule(hw, f_entry);
319280d144c9SAnirudh Venkataramanan 	}
31939daf8208SAnirudh Venkataramanan 
31949daf8208SAnirudh Venkataramanan 	cur_fltr = &m_entry->fltr_info;
319580d144c9SAnirudh Venkataramanan 	status = ice_add_update_vsi_list(hw, m_entry, cur_fltr, new_fltr);
319680d144c9SAnirudh Venkataramanan 	mutex_unlock(rule_lock);
31979daf8208SAnirudh Venkataramanan 
319880d144c9SAnirudh Venkataramanan 	return status;
319980d144c9SAnirudh Venkataramanan }
320080d144c9SAnirudh Venkataramanan 
320180d144c9SAnirudh Venkataramanan /**
320280d144c9SAnirudh Venkataramanan  * ice_remove_vsi_list_rule
320380d144c9SAnirudh Venkataramanan  * @hw: pointer to the hardware structure
3204f9867df6SAnirudh Venkataramanan  * @vsi_list_id: VSI list ID generated as part of allocate resource
320580d144c9SAnirudh Venkataramanan  * @lkup_type: switch rule filter lookup type
320680d144c9SAnirudh Venkataramanan  *
320780d144c9SAnirudh Venkataramanan  * The VSI list should be emptied before this function is called to remove the
320880d144c9SAnirudh Venkataramanan  * VSI list.
320980d144c9SAnirudh Venkataramanan  */
32105e24d598STony Nguyen static int
ice_remove_vsi_list_rule(struct ice_hw * hw,u16 vsi_list_id,enum ice_sw_lkup_type lkup_type)321180d144c9SAnirudh Venkataramanan ice_remove_vsi_list_rule(struct ice_hw *hw, u16 vsi_list_id,
321280d144c9SAnirudh Venkataramanan 			 enum ice_sw_lkup_type lkup_type)
321380d144c9SAnirudh Venkataramanan {
32146e1ff618SAlexander Lobakin 	struct ice_sw_rule_vsi_list *s_rule;
321580d144c9SAnirudh Venkataramanan 	u16 s_rule_size;
32165518ac2aSTony Nguyen 	int status;
321780d144c9SAnirudh Venkataramanan 
32186e1ff618SAlexander Lobakin 	s_rule_size = (u16)ICE_SW_RULE_VSI_LIST_SIZE(s_rule, 0);
321980d144c9SAnirudh Venkataramanan 	s_rule = devm_kzalloc(ice_hw_to_dev(hw), s_rule_size, GFP_KERNEL);
322080d144c9SAnirudh Venkataramanan 	if (!s_rule)
3221d54699e2STony Nguyen 		return -ENOMEM;
322280d144c9SAnirudh Venkataramanan 
32236e1ff618SAlexander Lobakin 	s_rule->hdr.type = cpu_to_le16(ICE_AQC_SW_RULES_T_VSI_LIST_CLEAR);
32246e1ff618SAlexander Lobakin 	s_rule->index = cpu_to_le16(vsi_list_id);
322580d144c9SAnirudh Venkataramanan 
322680d144c9SAnirudh Venkataramanan 	/* Free the vsi_list resource that we allocated. It is assumed that the
322780d144c9SAnirudh Venkataramanan 	 * list is empty at this point.
322880d144c9SAnirudh Venkataramanan 	 */
322980d144c9SAnirudh Venkataramanan 	status = ice_aq_alloc_free_vsi_list(hw, &vsi_list_id, lkup_type,
323080d144c9SAnirudh Venkataramanan 					    ice_aqc_opc_free_res);
323180d144c9SAnirudh Venkataramanan 
323280d144c9SAnirudh Venkataramanan 	devm_kfree(ice_hw_to_dev(hw), s_rule);
323380d144c9SAnirudh Venkataramanan 	return status;
323480d144c9SAnirudh Venkataramanan }
323580d144c9SAnirudh Venkataramanan 
323680d144c9SAnirudh Venkataramanan /**
323780d144c9SAnirudh Venkataramanan  * ice_rem_update_vsi_list
323880d144c9SAnirudh Venkataramanan  * @hw: pointer to the hardware structure
32395726ca0eSAnirudh Venkataramanan  * @vsi_handle: VSI handle of the VSI to remove
324080d144c9SAnirudh Venkataramanan  * @fm_list: filter management entry for which the VSI list management needs to
324180d144c9SAnirudh Venkataramanan  *           be done
324280d144c9SAnirudh Venkataramanan  */
32435e24d598STony Nguyen static int
ice_rem_update_vsi_list(struct ice_hw * hw,u16 vsi_handle,struct ice_fltr_mgmt_list_entry * fm_list)32445726ca0eSAnirudh Venkataramanan ice_rem_update_vsi_list(struct ice_hw *hw, u16 vsi_handle,
324580d144c9SAnirudh Venkataramanan 			struct ice_fltr_mgmt_list_entry *fm_list)
324680d144c9SAnirudh Venkataramanan {
324780d144c9SAnirudh Venkataramanan 	enum ice_sw_lkup_type lkup_type;
324880d144c9SAnirudh Venkataramanan 	u16 vsi_list_id;
32495518ac2aSTony Nguyen 	int status = 0;
325080d144c9SAnirudh Venkataramanan 
325180d144c9SAnirudh Venkataramanan 	if (fm_list->fltr_info.fltr_act != ICE_FWD_TO_VSI_LIST ||
325280d144c9SAnirudh Venkataramanan 	    fm_list->vsi_count == 0)
3253d54699e2STony Nguyen 		return -EINVAL;
325480d144c9SAnirudh Venkataramanan 
325580d144c9SAnirudh Venkataramanan 	/* A rule with the VSI being removed does not exist */
32565726ca0eSAnirudh Venkataramanan 	if (!test_bit(vsi_handle, fm_list->vsi_list_info->vsi_map))
3257d54699e2STony Nguyen 		return -ENOENT;
325880d144c9SAnirudh Venkataramanan 
325980d144c9SAnirudh Venkataramanan 	lkup_type = fm_list->fltr_info.lkup_type;
326080d144c9SAnirudh Venkataramanan 	vsi_list_id = fm_list->fltr_info.fwd_id.vsi_list_id;
32615726ca0eSAnirudh Venkataramanan 	status = ice_update_vsi_list_rule(hw, &vsi_handle, 1, vsi_list_id, true,
326280d144c9SAnirudh Venkataramanan 					  ice_aqc_opc_update_sw_rules,
326380d144c9SAnirudh Venkataramanan 					  lkup_type);
326480d144c9SAnirudh Venkataramanan 	if (status)
326580d144c9SAnirudh Venkataramanan 		return status;
326680d144c9SAnirudh Venkataramanan 
326780d144c9SAnirudh Venkataramanan 	fm_list->vsi_count--;
32685726ca0eSAnirudh Venkataramanan 	clear_bit(vsi_handle, fm_list->vsi_list_info->vsi_map);
326980d144c9SAnirudh Venkataramanan 
3270c60cdb13SBrett Creeley 	if (fm_list->vsi_count == 1 && lkup_type != ICE_SW_LKUP_VLAN) {
3271c60cdb13SBrett Creeley 		struct ice_fltr_info tmp_fltr_info = fm_list->fltr_info;
327280d144c9SAnirudh Venkataramanan 		struct ice_vsi_list_map_info *vsi_list_info =
327380d144c9SAnirudh Venkataramanan 			fm_list->vsi_list_info;
32745726ca0eSAnirudh Venkataramanan 		u16 rem_vsi_handle;
327580d144c9SAnirudh Venkataramanan 
32765726ca0eSAnirudh Venkataramanan 		rem_vsi_handle = find_first_bit(vsi_list_info->vsi_map,
327780d144c9SAnirudh Venkataramanan 						ICE_MAX_VSI);
32785726ca0eSAnirudh Venkataramanan 		if (!ice_is_vsi_valid(hw, rem_vsi_handle))
3279d54699e2STony Nguyen 			return -EIO;
3280c60cdb13SBrett Creeley 
3281c60cdb13SBrett Creeley 		/* Make sure VSI list is empty before removing it below */
32825726ca0eSAnirudh Venkataramanan 		status = ice_update_vsi_list_rule(hw, &rem_vsi_handle, 1,
328380d144c9SAnirudh Venkataramanan 						  vsi_list_id, true,
328480d144c9SAnirudh Venkataramanan 						  ice_aqc_opc_update_sw_rules,
328580d144c9SAnirudh Venkataramanan 						  lkup_type);
328680d144c9SAnirudh Venkataramanan 		if (status)
328780d144c9SAnirudh Venkataramanan 			return status;
328880d144c9SAnirudh Venkataramanan 
3289c60cdb13SBrett Creeley 		tmp_fltr_info.fltr_act = ICE_FWD_TO_VSI;
3290c60cdb13SBrett Creeley 		tmp_fltr_info.fwd_id.hw_vsi_id =
3291c60cdb13SBrett Creeley 			ice_get_hw_vsi_num(hw, rem_vsi_handle);
3292c60cdb13SBrett Creeley 		tmp_fltr_info.vsi_handle = rem_vsi_handle;
3293c60cdb13SBrett Creeley 		status = ice_update_pkt_fwd_rule(hw, &tmp_fltr_info);
3294c60cdb13SBrett Creeley 		if (status) {
32959228d8b2SJacob Keller 			ice_debug(hw, ICE_DBG_SW, "Failed to update pkt fwd rule to FWD_TO_VSI on HW VSI %d, error %d\n",
3296c60cdb13SBrett Creeley 				  tmp_fltr_info.fwd_id.hw_vsi_id, status);
3297c60cdb13SBrett Creeley 			return status;
3298c60cdb13SBrett Creeley 		}
3299c60cdb13SBrett Creeley 
3300c60cdb13SBrett Creeley 		fm_list->fltr_info = tmp_fltr_info;
3301c60cdb13SBrett Creeley 	}
3302c60cdb13SBrett Creeley 
3303c60cdb13SBrett Creeley 	if ((fm_list->vsi_count == 1 && lkup_type != ICE_SW_LKUP_VLAN) ||
3304c60cdb13SBrett Creeley 	    (fm_list->vsi_count == 0 && lkup_type == ICE_SW_LKUP_VLAN)) {
3305c60cdb13SBrett Creeley 		struct ice_vsi_list_map_info *vsi_list_info =
3306c60cdb13SBrett Creeley 			fm_list->vsi_list_info;
3307c60cdb13SBrett Creeley 
330880d144c9SAnirudh Venkataramanan 		/* Remove the VSI list since it is no longer used */
330980d144c9SAnirudh Venkataramanan 		status = ice_remove_vsi_list_rule(hw, vsi_list_id, lkup_type);
3310c60cdb13SBrett Creeley 		if (status) {
33119228d8b2SJacob Keller 			ice_debug(hw, ICE_DBG_SW, "Failed to remove VSI list %d, error %d\n",
3312c60cdb13SBrett Creeley 				  vsi_list_id, status);
331380d144c9SAnirudh Venkataramanan 			return status;
3314c60cdb13SBrett Creeley 		}
331580d144c9SAnirudh Venkataramanan 
331680d144c9SAnirudh Venkataramanan 		list_del(&vsi_list_info->list_entry);
331780d144c9SAnirudh Venkataramanan 		devm_kfree(ice_hw_to_dev(hw), vsi_list_info);
331880d144c9SAnirudh Venkataramanan 		fm_list->vsi_list_info = NULL;
331980d144c9SAnirudh Venkataramanan 	}
332080d144c9SAnirudh Venkataramanan 
332180d144c9SAnirudh Venkataramanan 	return status;
332280d144c9SAnirudh Venkataramanan }
332380d144c9SAnirudh Venkataramanan 
332480d144c9SAnirudh Venkataramanan /**
332580d144c9SAnirudh Venkataramanan  * ice_remove_rule_internal - Remove a filter rule of a given type
332680d144c9SAnirudh Venkataramanan  * @hw: pointer to the hardware structure
3327f9867df6SAnirudh Venkataramanan  * @recp_id: recipe ID for which the rule needs to removed
332880d144c9SAnirudh Venkataramanan  * @f_entry: rule entry containing filter information
332980d144c9SAnirudh Venkataramanan  */
33305e24d598STony Nguyen static int
ice_remove_rule_internal(struct ice_hw * hw,u8 recp_id,struct ice_fltr_list_entry * f_entry)333180d144c9SAnirudh Venkataramanan ice_remove_rule_internal(struct ice_hw *hw, u8 recp_id,
333280d144c9SAnirudh Venkataramanan 			 struct ice_fltr_list_entry *f_entry)
333380d144c9SAnirudh Venkataramanan {
333480d144c9SAnirudh Venkataramanan 	struct ice_switch_info *sw = hw->switch_info;
333580d144c9SAnirudh Venkataramanan 	struct ice_fltr_mgmt_list_entry *list_elem;
333680d144c9SAnirudh Venkataramanan 	struct mutex *rule_lock; /* Lock to protect filter rule list */
333780d144c9SAnirudh Venkataramanan 	bool remove_rule = false;
33385726ca0eSAnirudh Venkataramanan 	u16 vsi_handle;
33395518ac2aSTony Nguyen 	int status = 0;
33405726ca0eSAnirudh Venkataramanan 
33415726ca0eSAnirudh Venkataramanan 	if (!ice_is_vsi_valid(hw, f_entry->fltr_info.vsi_handle))
3342d54699e2STony Nguyen 		return -EINVAL;
33435726ca0eSAnirudh Venkataramanan 	f_entry->fltr_info.fwd_id.hw_vsi_id =
33445726ca0eSAnirudh Venkataramanan 		ice_get_hw_vsi_num(hw, f_entry->fltr_info.vsi_handle);
334580d144c9SAnirudh Venkataramanan 
334680d144c9SAnirudh Venkataramanan 	rule_lock = &sw->recp_list[recp_id].filt_rule_lock;
334780d144c9SAnirudh Venkataramanan 	mutex_lock(rule_lock);
334880d144c9SAnirudh Venkataramanan 	list_elem = ice_find_rule_entry(hw, recp_id, &f_entry->fltr_info);
334980d144c9SAnirudh Venkataramanan 	if (!list_elem) {
3350d54699e2STony Nguyen 		status = -ENOENT;
335180d144c9SAnirudh Venkataramanan 		goto exit;
335280d144c9SAnirudh Venkataramanan 	}
335380d144c9SAnirudh Venkataramanan 
335480d144c9SAnirudh Venkataramanan 	if (list_elem->fltr_info.fltr_act != ICE_FWD_TO_VSI_LIST) {
335580d144c9SAnirudh Venkataramanan 		remove_rule = true;
33565726ca0eSAnirudh Venkataramanan 	} else if (!list_elem->vsi_list_info) {
3357d54699e2STony Nguyen 		status = -ENOENT;
33585726ca0eSAnirudh Venkataramanan 		goto exit;
3359f9264dd6SJacob Keller 	} else if (list_elem->vsi_list_info->ref_cnt > 1) {
3360f9264dd6SJacob Keller 		/* a ref_cnt > 1 indicates that the vsi_list is being
3361f9264dd6SJacob Keller 		 * shared by multiple rules. Decrement the ref_cnt and
3362f9264dd6SJacob Keller 		 * remove this rule, but do not modify the list, as it
3363f9264dd6SJacob Keller 		 * is in-use by other rules.
3364f9264dd6SJacob Keller 		 */
33655726ca0eSAnirudh Venkataramanan 		list_elem->vsi_list_info->ref_cnt--;
3366f9264dd6SJacob Keller 		remove_rule = true;
3367f9264dd6SJacob Keller 	} else {
3368f9264dd6SJacob Keller 		/* a ref_cnt of 1 indicates the vsi_list is only used
3369f9264dd6SJacob Keller 		 * by one rule. However, the original removal request is only
3370f9264dd6SJacob Keller 		 * for a single VSI. Update the vsi_list first, and only
3371f9264dd6SJacob Keller 		 * remove the rule if there are no further VSIs in this list.
3372f9264dd6SJacob Keller 		 */
33735726ca0eSAnirudh Venkataramanan 		vsi_handle = f_entry->fltr_info.vsi_handle;
33745726ca0eSAnirudh Venkataramanan 		status = ice_rem_update_vsi_list(hw, vsi_handle, list_elem);
337580d144c9SAnirudh Venkataramanan 		if (status)
337680d144c9SAnirudh Venkataramanan 			goto exit;
3377f9867df6SAnirudh Venkataramanan 		/* if VSI count goes to zero after updating the VSI list */
337880d144c9SAnirudh Venkataramanan 		if (list_elem->vsi_count == 0)
337980d144c9SAnirudh Venkataramanan 			remove_rule = true;
338080d144c9SAnirudh Venkataramanan 	}
338180d144c9SAnirudh Venkataramanan 
338280d144c9SAnirudh Venkataramanan 	if (remove_rule) {
338380d144c9SAnirudh Venkataramanan 		/* Remove the lookup rule */
33846e1ff618SAlexander Lobakin 		struct ice_sw_rule_lkup_rx_tx *s_rule;
338580d144c9SAnirudh Venkataramanan 
338680d144c9SAnirudh Venkataramanan 		s_rule = devm_kzalloc(ice_hw_to_dev(hw),
33876e1ff618SAlexander Lobakin 				      ICE_SW_RULE_RX_TX_NO_HDR_SIZE(s_rule),
338880d144c9SAnirudh Venkataramanan 				      GFP_KERNEL);
338980d144c9SAnirudh Venkataramanan 		if (!s_rule) {
3390d54699e2STony Nguyen 			status = -ENOMEM;
339180d144c9SAnirudh Venkataramanan 			goto exit;
339280d144c9SAnirudh Venkataramanan 		}
339380d144c9SAnirudh Venkataramanan 
339480d144c9SAnirudh Venkataramanan 		ice_fill_sw_rule(hw, &list_elem->fltr_info, s_rule,
339580d144c9SAnirudh Venkataramanan 				 ice_aqc_opc_remove_sw_rules);
339680d144c9SAnirudh Venkataramanan 
339780d144c9SAnirudh Venkataramanan 		status = ice_aq_sw_rules(hw, s_rule,
33986e1ff618SAlexander Lobakin 					 ICE_SW_RULE_RX_TX_NO_HDR_SIZE(s_rule),
33996e1ff618SAlexander Lobakin 					 1, ice_aqc_opc_remove_sw_rules, NULL);
340080d144c9SAnirudh Venkataramanan 
340180d144c9SAnirudh Venkataramanan 		/* Remove a book keeping from the list */
340280d144c9SAnirudh Venkataramanan 		devm_kfree(ice_hw_to_dev(hw), s_rule);
340380d144c9SAnirudh Venkataramanan 
34048132e17dSJeb Cramer 		if (status)
34058132e17dSJeb Cramer 			goto exit;
34068132e17dSJeb Cramer 
340780d144c9SAnirudh Venkataramanan 		list_del(&list_elem->list_entry);
340880d144c9SAnirudh Venkataramanan 		devm_kfree(ice_hw_to_dev(hw), list_elem);
340980d144c9SAnirudh Venkataramanan 	}
341080d144c9SAnirudh Venkataramanan exit:
341180d144c9SAnirudh Venkataramanan 	mutex_unlock(rule_lock);
341280d144c9SAnirudh Venkataramanan 	return status;
34139daf8208SAnirudh Venkataramanan }
34149daf8208SAnirudh Venkataramanan 
34159daf8208SAnirudh Venkataramanan /**
34169fea7498SKiran Patil  * ice_vlan_fltr_exist - does this VLAN filter exist for given VSI
34179fea7498SKiran Patil  * @hw: pointer to the hardware structure
34189fea7498SKiran Patil  * @vlan_id: VLAN ID
34199fea7498SKiran Patil  * @vsi_handle: check MAC filter for this VSI
34209fea7498SKiran Patil  */
ice_vlan_fltr_exist(struct ice_hw * hw,u16 vlan_id,u16 vsi_handle)34219fea7498SKiran Patil bool ice_vlan_fltr_exist(struct ice_hw *hw, u16 vlan_id, u16 vsi_handle)
34229fea7498SKiran Patil {
34239fea7498SKiran Patil 	struct ice_fltr_mgmt_list_entry *entry;
34249fea7498SKiran Patil 	struct list_head *rule_head;
34259fea7498SKiran Patil 	struct ice_switch_info *sw;
34269fea7498SKiran Patil 	struct mutex *rule_lock; /* Lock to protect filter rule list */
34279fea7498SKiran Patil 	u16 hw_vsi_id;
34289fea7498SKiran Patil 
34299fea7498SKiran Patil 	if (vlan_id > ICE_MAX_VLAN_ID)
34309fea7498SKiran Patil 		return false;
34319fea7498SKiran Patil 
34329fea7498SKiran Patil 	if (!ice_is_vsi_valid(hw, vsi_handle))
34339fea7498SKiran Patil 		return false;
34349fea7498SKiran Patil 
34359fea7498SKiran Patil 	hw_vsi_id = ice_get_hw_vsi_num(hw, vsi_handle);
34369fea7498SKiran Patil 	sw = hw->switch_info;
34379fea7498SKiran Patil 	rule_head = &sw->recp_list[ICE_SW_LKUP_VLAN].filt_rules;
34389fea7498SKiran Patil 	if (!rule_head)
34399fea7498SKiran Patil 		return false;
34409fea7498SKiran Patil 
34419fea7498SKiran Patil 	rule_lock = &sw->recp_list[ICE_SW_LKUP_VLAN].filt_rule_lock;
34429fea7498SKiran Patil 	mutex_lock(rule_lock);
34439fea7498SKiran Patil 	list_for_each_entry(entry, rule_head, list_entry) {
34449fea7498SKiran Patil 		struct ice_fltr_info *f_info = &entry->fltr_info;
34459fea7498SKiran Patil 		u16 entry_vlan_id = f_info->l_data.vlan.vlan_id;
34469fea7498SKiran Patil 		struct ice_vsi_list_map_info *map_info;
34479fea7498SKiran Patil 
34489fea7498SKiran Patil 		if (entry_vlan_id > ICE_MAX_VLAN_ID)
34499fea7498SKiran Patil 			continue;
34509fea7498SKiran Patil 
34519fea7498SKiran Patil 		if (f_info->flag != ICE_FLTR_TX ||
34529fea7498SKiran Patil 		    f_info->src_id != ICE_SRC_ID_VSI ||
34539fea7498SKiran Patil 		    f_info->lkup_type != ICE_SW_LKUP_VLAN)
34549fea7498SKiran Patil 			continue;
34559fea7498SKiran Patil 
34569fea7498SKiran Patil 		/* Only allowed filter action are FWD_TO_VSI/_VSI_LIST */
34579fea7498SKiran Patil 		if (f_info->fltr_act != ICE_FWD_TO_VSI &&
34589fea7498SKiran Patil 		    f_info->fltr_act != ICE_FWD_TO_VSI_LIST)
34599fea7498SKiran Patil 			continue;
34609fea7498SKiran Patil 
34619fea7498SKiran Patil 		if (f_info->fltr_act == ICE_FWD_TO_VSI) {
34629fea7498SKiran Patil 			if (hw_vsi_id != f_info->fwd_id.hw_vsi_id)
34639fea7498SKiran Patil 				continue;
34649fea7498SKiran Patil 		} else if (f_info->fltr_act == ICE_FWD_TO_VSI_LIST) {
34659fea7498SKiran Patil 			/* If filter_action is FWD_TO_VSI_LIST, make sure
34669fea7498SKiran Patil 			 * that VSI being checked is part of VSI list
34679fea7498SKiran Patil 			 */
34689fea7498SKiran Patil 			if (entry->vsi_count == 1 &&
34699fea7498SKiran Patil 			    entry->vsi_list_info) {
34709fea7498SKiran Patil 				map_info = entry->vsi_list_info;
34719fea7498SKiran Patil 				if (!test_bit(vsi_handle, map_info->vsi_map))
34729fea7498SKiran Patil 					continue;
34739fea7498SKiran Patil 			}
34749fea7498SKiran Patil 		}
34759fea7498SKiran Patil 
34769fea7498SKiran Patil 		if (vlan_id == entry_vlan_id) {
34779fea7498SKiran Patil 			mutex_unlock(rule_lock);
34789fea7498SKiran Patil 			return true;
34799fea7498SKiran Patil 		}
34809fea7498SKiran Patil 	}
34819fea7498SKiran Patil 	mutex_unlock(rule_lock);
34829fea7498SKiran Patil 
34839fea7498SKiran Patil 	return false;
34849fea7498SKiran Patil }
34859fea7498SKiran Patil 
34869fea7498SKiran Patil /**
34879daf8208SAnirudh Venkataramanan  * ice_add_mac - Add a MAC address based filter rule
34889daf8208SAnirudh Venkataramanan  * @hw: pointer to the hardware structure
34899daf8208SAnirudh Venkataramanan  * @m_list: list of MAC addresses and forwarding information
34909daf8208SAnirudh Venkataramanan  */
ice_add_mac(struct ice_hw * hw,struct list_head * m_list)34915e24d598STony Nguyen int ice_add_mac(struct ice_hw *hw, struct list_head *m_list)
34929daf8208SAnirudh Venkataramanan {
34939daf8208SAnirudh Venkataramanan 	struct ice_fltr_list_entry *m_list_itr;
34945518ac2aSTony Nguyen 	int status = 0;
34959daf8208SAnirudh Venkataramanan 
34969daf8208SAnirudh Venkataramanan 	if (!m_list || !hw)
3497d54699e2STony Nguyen 		return -EINVAL;
34989daf8208SAnirudh Venkataramanan 
34999daf8208SAnirudh Venkataramanan 	list_for_each_entry(m_list_itr, m_list, list_entry) {
35009daf8208SAnirudh Venkataramanan 		u8 *add = &m_list_itr->fltr_info.l_data.mac.mac_addr[0];
35015726ca0eSAnirudh Venkataramanan 		u16 vsi_handle;
35025726ca0eSAnirudh Venkataramanan 		u16 hw_vsi_id;
35039daf8208SAnirudh Venkataramanan 
350480d144c9SAnirudh Venkataramanan 		m_list_itr->fltr_info.flag = ICE_FLTR_TX;
35055726ca0eSAnirudh Venkataramanan 		vsi_handle = m_list_itr->fltr_info.vsi_handle;
35065726ca0eSAnirudh Venkataramanan 		if (!ice_is_vsi_valid(hw, vsi_handle))
3507d54699e2STony Nguyen 			return -EINVAL;
35085726ca0eSAnirudh Venkataramanan 		hw_vsi_id = ice_get_hw_vsi_num(hw, vsi_handle);
35095726ca0eSAnirudh Venkataramanan 		m_list_itr->fltr_info.fwd_id.hw_vsi_id = hw_vsi_id;
3510f9867df6SAnirudh Venkataramanan 		/* update the src in case it is VSI num */
35115726ca0eSAnirudh Venkataramanan 		if (m_list_itr->fltr_info.src_id != ICE_SRC_ID_VSI)
3512d54699e2STony Nguyen 			return -EINVAL;
35135726ca0eSAnirudh Venkataramanan 		m_list_itr->fltr_info.src = hw_vsi_id;
351480d144c9SAnirudh Venkataramanan 		if (m_list_itr->fltr_info.lkup_type != ICE_SW_LKUP_MAC ||
351580d144c9SAnirudh Venkataramanan 		    is_zero_ether_addr(add))
3516d54699e2STony Nguyen 			return -EINVAL;
3517e1e9db57SSylwester Dziedziuch 
3518e1e9db57SSylwester Dziedziuch 		m_list_itr->status = ice_add_rule_internal(hw, ICE_SW_LKUP_MAC,
351980d144c9SAnirudh Venkataramanan 							   m_list_itr);
352080d144c9SAnirudh Venkataramanan 		if (m_list_itr->status)
352180d144c9SAnirudh Venkataramanan 			return m_list_itr->status;
35229daf8208SAnirudh Venkataramanan 	}
35239daf8208SAnirudh Venkataramanan 
35249daf8208SAnirudh Venkataramanan 	return status;
35259daf8208SAnirudh Venkataramanan }
35269daf8208SAnirudh Venkataramanan 
35279daf8208SAnirudh Venkataramanan /**
3528d76a60baSAnirudh Venkataramanan  * ice_add_vlan_internal - Add one VLAN based filter rule
3529d76a60baSAnirudh Venkataramanan  * @hw: pointer to the hardware structure
3530d76a60baSAnirudh Venkataramanan  * @f_entry: filter entry containing one VLAN information
3531d76a60baSAnirudh Venkataramanan  */
35325e24d598STony Nguyen static int
ice_add_vlan_internal(struct ice_hw * hw,struct ice_fltr_list_entry * f_entry)3533d76a60baSAnirudh Venkataramanan ice_add_vlan_internal(struct ice_hw *hw, struct ice_fltr_list_entry *f_entry)
3534d76a60baSAnirudh Venkataramanan {
353580d144c9SAnirudh Venkataramanan 	struct ice_switch_info *sw = hw->switch_info;
3536d76a60baSAnirudh Venkataramanan 	struct ice_fltr_mgmt_list_entry *v_list_itr;
35375726ca0eSAnirudh Venkataramanan 	struct ice_fltr_info *new_fltr, *cur_fltr;
35385726ca0eSAnirudh Venkataramanan 	enum ice_sw_lkup_type lkup_type;
35395726ca0eSAnirudh Venkataramanan 	u16 vsi_list_id = 0, vsi_handle;
354080d144c9SAnirudh Venkataramanan 	struct mutex *rule_lock; /* Lock to protect filter rule list */
35415e24d598STony Nguyen 	int status = 0;
3542d76a60baSAnirudh Venkataramanan 
35435726ca0eSAnirudh Venkataramanan 	if (!ice_is_vsi_valid(hw, f_entry->fltr_info.vsi_handle))
3544d54699e2STony Nguyen 		return -EINVAL;
35455726ca0eSAnirudh Venkataramanan 
35465726ca0eSAnirudh Venkataramanan 	f_entry->fltr_info.fwd_id.hw_vsi_id =
35475726ca0eSAnirudh Venkataramanan 		ice_get_hw_vsi_num(hw, f_entry->fltr_info.vsi_handle);
3548d76a60baSAnirudh Venkataramanan 	new_fltr = &f_entry->fltr_info;
35495726ca0eSAnirudh Venkataramanan 
3550f9867df6SAnirudh Venkataramanan 	/* VLAN ID should only be 12 bits */
3551d76a60baSAnirudh Venkataramanan 	if (new_fltr->l_data.vlan.vlan_id > ICE_MAX_VLAN_ID)
3552d54699e2STony Nguyen 		return -EINVAL;
3553d76a60baSAnirudh Venkataramanan 
35545726ca0eSAnirudh Venkataramanan 	if (new_fltr->src_id != ICE_SRC_ID_VSI)
3555d54699e2STony Nguyen 		return -EINVAL;
35565726ca0eSAnirudh Venkataramanan 
35575726ca0eSAnirudh Venkataramanan 	new_fltr->src = new_fltr->fwd_id.hw_vsi_id;
35585726ca0eSAnirudh Venkataramanan 	lkup_type = new_fltr->lkup_type;
35595726ca0eSAnirudh Venkataramanan 	vsi_handle = new_fltr->vsi_handle;
356080d144c9SAnirudh Venkataramanan 	rule_lock = &sw->recp_list[ICE_SW_LKUP_VLAN].filt_rule_lock;
356180d144c9SAnirudh Venkataramanan 	mutex_lock(rule_lock);
356280d144c9SAnirudh Venkataramanan 	v_list_itr = ice_find_rule_entry(hw, ICE_SW_LKUP_VLAN, new_fltr);
3563d76a60baSAnirudh Venkataramanan 	if (!v_list_itr) {
35645726ca0eSAnirudh Venkataramanan 		struct ice_vsi_list_map_info *map_info = NULL;
3565d76a60baSAnirudh Venkataramanan 
3566d76a60baSAnirudh Venkataramanan 		if (new_fltr->fltr_act == ICE_FWD_TO_VSI) {
35675726ca0eSAnirudh Venkataramanan 			/* All VLAN pruning rules use a VSI list. Check if
35685726ca0eSAnirudh Venkataramanan 			 * there is already a VSI list containing VSI that we
35695726ca0eSAnirudh Venkataramanan 			 * want to add. If found, use the same vsi_list_id for
35705726ca0eSAnirudh Venkataramanan 			 * this new VLAN rule or else create a new list.
3571d76a60baSAnirudh Venkataramanan 			 */
35725726ca0eSAnirudh Venkataramanan 			map_info = ice_find_vsi_list_entry(hw, ICE_SW_LKUP_VLAN,
35735726ca0eSAnirudh Venkataramanan 							   vsi_handle,
35745726ca0eSAnirudh Venkataramanan 							   &vsi_list_id);
35755726ca0eSAnirudh Venkataramanan 			if (!map_info) {
35765726ca0eSAnirudh Venkataramanan 				status = ice_create_vsi_list_rule(hw,
35775726ca0eSAnirudh Venkataramanan 								  &vsi_handle,
35785726ca0eSAnirudh Venkataramanan 								  1,
3579d76a60baSAnirudh Venkataramanan 								  &vsi_list_id,
3580d76a60baSAnirudh Venkataramanan 								  lkup_type);
3581d76a60baSAnirudh Venkataramanan 				if (status)
358280d144c9SAnirudh Venkataramanan 					goto exit;
35835726ca0eSAnirudh Venkataramanan 			}
35845726ca0eSAnirudh Venkataramanan 			/* Convert the action to forwarding to a VSI list. */
3585d76a60baSAnirudh Venkataramanan 			new_fltr->fltr_act = ICE_FWD_TO_VSI_LIST;
3586d76a60baSAnirudh Venkataramanan 			new_fltr->fwd_id.vsi_list_id = vsi_list_id;
3587d76a60baSAnirudh Venkataramanan 		}
3588d76a60baSAnirudh Venkataramanan 
3589d76a60baSAnirudh Venkataramanan 		status = ice_create_pkt_fwd_rule(hw, f_entry);
35905726ca0eSAnirudh Venkataramanan 		if (!status) {
359180d144c9SAnirudh Venkataramanan 			v_list_itr = ice_find_rule_entry(hw, ICE_SW_LKUP_VLAN,
359280d144c9SAnirudh Venkataramanan 							 new_fltr);
359380d144c9SAnirudh Venkataramanan 			if (!v_list_itr) {
3594d54699e2STony Nguyen 				status = -ENOENT;
359580d144c9SAnirudh Venkataramanan 				goto exit;
359680d144c9SAnirudh Venkataramanan 			}
35975726ca0eSAnirudh Venkataramanan 			/* reuse VSI list for new rule and increment ref_cnt */
35985726ca0eSAnirudh Venkataramanan 			if (map_info) {
35995726ca0eSAnirudh Venkataramanan 				v_list_itr->vsi_list_info = map_info;
36005726ca0eSAnirudh Venkataramanan 				map_info->ref_cnt++;
36015726ca0eSAnirudh Venkataramanan 			} else {
3602d76a60baSAnirudh Venkataramanan 				v_list_itr->vsi_list_info =
36035726ca0eSAnirudh Venkataramanan 					ice_create_vsi_list_map(hw, &vsi_handle,
36045726ca0eSAnirudh Venkataramanan 								1, vsi_list_id);
3605d76a60baSAnirudh Venkataramanan 			}
36065726ca0eSAnirudh Venkataramanan 		}
36075726ca0eSAnirudh Venkataramanan 	} else if (v_list_itr->vsi_list_info->ref_cnt == 1) {
3608f9867df6SAnirudh Venkataramanan 		/* Update existing VSI list to add new VSI ID only if it used
36095726ca0eSAnirudh Venkataramanan 		 * by one VLAN rule.
36105726ca0eSAnirudh Venkataramanan 		 */
36115726ca0eSAnirudh Venkataramanan 		cur_fltr = &v_list_itr->fltr_info;
36125726ca0eSAnirudh Venkataramanan 		status = ice_add_update_vsi_list(hw, v_list_itr, cur_fltr,
36135726ca0eSAnirudh Venkataramanan 						 new_fltr);
36145726ca0eSAnirudh Venkataramanan 	} else {
36155726ca0eSAnirudh Venkataramanan 		/* If VLAN rule exists and VSI list being used by this rule is
36165726ca0eSAnirudh Venkataramanan 		 * referenced by more than 1 VLAN rule. Then create a new VSI
36175726ca0eSAnirudh Venkataramanan 		 * list appending previous VSI with new VSI and update existing
3618f9867df6SAnirudh Venkataramanan 		 * VLAN rule to point to new VSI list ID
36195726ca0eSAnirudh Venkataramanan 		 */
36205726ca0eSAnirudh Venkataramanan 		struct ice_fltr_info tmp_fltr;
36215726ca0eSAnirudh Venkataramanan 		u16 vsi_handle_arr[2];
36225726ca0eSAnirudh Venkataramanan 		u16 cur_handle;
3623d76a60baSAnirudh Venkataramanan 
36245726ca0eSAnirudh Venkataramanan 		/* Current implementation only supports reusing VSI list with
36255726ca0eSAnirudh Venkataramanan 		 * one VSI count. We should never hit below condition
36265726ca0eSAnirudh Venkataramanan 		 */
36275726ca0eSAnirudh Venkataramanan 		if (v_list_itr->vsi_count > 1 &&
36285726ca0eSAnirudh Venkataramanan 		    v_list_itr->vsi_list_info->ref_cnt > 1) {
36299228d8b2SJacob 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");
3630d54699e2STony Nguyen 			status = -EIO;
363180d144c9SAnirudh Venkataramanan 			goto exit;
3632d76a60baSAnirudh Venkataramanan 		}
3633d76a60baSAnirudh Venkataramanan 
36345726ca0eSAnirudh Venkataramanan 		cur_handle =
36355726ca0eSAnirudh Venkataramanan 			find_first_bit(v_list_itr->vsi_list_info->vsi_map,
36365726ca0eSAnirudh Venkataramanan 				       ICE_MAX_VSI);
36375726ca0eSAnirudh Venkataramanan 
36385726ca0eSAnirudh Venkataramanan 		/* A rule already exists with the new VSI being added */
36395726ca0eSAnirudh Venkataramanan 		if (cur_handle == vsi_handle) {
3640d54699e2STony Nguyen 			status = -EEXIST;
36415726ca0eSAnirudh Venkataramanan 			goto exit;
36425726ca0eSAnirudh Venkataramanan 		}
36435726ca0eSAnirudh Venkataramanan 
36445726ca0eSAnirudh Venkataramanan 		vsi_handle_arr[0] = cur_handle;
36455726ca0eSAnirudh Venkataramanan 		vsi_handle_arr[1] = vsi_handle;
36465726ca0eSAnirudh Venkataramanan 		status = ice_create_vsi_list_rule(hw, &vsi_handle_arr[0], 2,
36475726ca0eSAnirudh Venkataramanan 						  &vsi_list_id, lkup_type);
36485726ca0eSAnirudh Venkataramanan 		if (status)
36495726ca0eSAnirudh Venkataramanan 			goto exit;
36505726ca0eSAnirudh Venkataramanan 
36515726ca0eSAnirudh Venkataramanan 		tmp_fltr = v_list_itr->fltr_info;
36525726ca0eSAnirudh Venkataramanan 		tmp_fltr.fltr_rule_id = v_list_itr->fltr_info.fltr_rule_id;
36535726ca0eSAnirudh Venkataramanan 		tmp_fltr.fwd_id.vsi_list_id = vsi_list_id;
36545726ca0eSAnirudh Venkataramanan 		tmp_fltr.fltr_act = ICE_FWD_TO_VSI_LIST;
36555726ca0eSAnirudh Venkataramanan 		/* Update the previous switch rule to a new VSI list which
3656df17b7e0SAnirudh Venkataramanan 		 * includes current VSI that is requested
36575726ca0eSAnirudh Venkataramanan 		 */
36585726ca0eSAnirudh Venkataramanan 		status = ice_update_pkt_fwd_rule(hw, &tmp_fltr);
36595726ca0eSAnirudh Venkataramanan 		if (status)
36605726ca0eSAnirudh Venkataramanan 			goto exit;
36615726ca0eSAnirudh Venkataramanan 
36625726ca0eSAnirudh Venkataramanan 		/* before overriding VSI list map info. decrement ref_cnt of
36635726ca0eSAnirudh Venkataramanan 		 * previous VSI list
36645726ca0eSAnirudh Venkataramanan 		 */
36655726ca0eSAnirudh Venkataramanan 		v_list_itr->vsi_list_info->ref_cnt--;
36665726ca0eSAnirudh Venkataramanan 
36675726ca0eSAnirudh Venkataramanan 		/* now update to newly created list */
36685726ca0eSAnirudh Venkataramanan 		v_list_itr->fltr_info.fwd_id.vsi_list_id = vsi_list_id;
36695726ca0eSAnirudh Venkataramanan 		v_list_itr->vsi_list_info =
36705726ca0eSAnirudh Venkataramanan 			ice_create_vsi_list_map(hw, &vsi_handle_arr[0], 2,
36715726ca0eSAnirudh Venkataramanan 						vsi_list_id);
36725726ca0eSAnirudh Venkataramanan 		v_list_itr->vsi_count++;
36735726ca0eSAnirudh Venkataramanan 	}
367480d144c9SAnirudh Venkataramanan 
367580d144c9SAnirudh Venkataramanan exit:
367680d144c9SAnirudh Venkataramanan 	mutex_unlock(rule_lock);
367780d144c9SAnirudh Venkataramanan 	return status;
3678d76a60baSAnirudh Venkataramanan }
3679d76a60baSAnirudh Venkataramanan 
3680d76a60baSAnirudh Venkataramanan /**
3681d76a60baSAnirudh Venkataramanan  * ice_add_vlan - Add VLAN based filter rule
3682d76a60baSAnirudh Venkataramanan  * @hw: pointer to the hardware structure
3683d76a60baSAnirudh Venkataramanan  * @v_list: list of VLAN entries and forwarding information
3684d76a60baSAnirudh Venkataramanan  */
ice_add_vlan(struct ice_hw * hw,struct list_head * v_list)36855e24d598STony Nguyen int ice_add_vlan(struct ice_hw *hw, struct list_head *v_list)
3686d76a60baSAnirudh Venkataramanan {
3687d76a60baSAnirudh Venkataramanan 	struct ice_fltr_list_entry *v_list_itr;
3688d76a60baSAnirudh Venkataramanan 
3689d76a60baSAnirudh Venkataramanan 	if (!v_list || !hw)
3690d54699e2STony Nguyen 		return -EINVAL;
3691d76a60baSAnirudh Venkataramanan 
3692d76a60baSAnirudh Venkataramanan 	list_for_each_entry(v_list_itr, v_list, list_entry) {
3693d76a60baSAnirudh Venkataramanan 		if (v_list_itr->fltr_info.lkup_type != ICE_SW_LKUP_VLAN)
3694d54699e2STony Nguyen 			return -EINVAL;
369580d144c9SAnirudh Venkataramanan 		v_list_itr->fltr_info.flag = ICE_FLTR_TX;
369680d144c9SAnirudh Venkataramanan 		v_list_itr->status = ice_add_vlan_internal(hw, v_list_itr);
369780d144c9SAnirudh Venkataramanan 		if (v_list_itr->status)
369880d144c9SAnirudh Venkataramanan 			return v_list_itr->status;
3699d76a60baSAnirudh Venkataramanan 	}
3700d76a60baSAnirudh Venkataramanan 	return 0;
3701d76a60baSAnirudh Venkataramanan }
3702d76a60baSAnirudh Venkataramanan 
3703d76a60baSAnirudh Venkataramanan /**
3704d95276ceSAkeem G Abodunrin  * ice_add_eth_mac - Add ethertype and MAC based filter rule
3705d95276ceSAkeem G Abodunrin  * @hw: pointer to the hardware structure
3706d95276ceSAkeem G Abodunrin  * @em_list: list of ether type MAC filter, MAC is optional
37072e0e6228SDave Ertman  *
37082e0e6228SDave Ertman  * This function requires the caller to populate the entries in
37092e0e6228SDave Ertman  * the filter list with the necessary fields (including flags to
37102e0e6228SDave Ertman  * indicate Tx or Rx rules).
3711d95276ceSAkeem G Abodunrin  */
ice_add_eth_mac(struct ice_hw * hw,struct list_head * em_list)37125518ac2aSTony Nguyen int ice_add_eth_mac(struct ice_hw *hw, struct list_head *em_list)
3713d95276ceSAkeem G Abodunrin {
3714d95276ceSAkeem G Abodunrin 	struct ice_fltr_list_entry *em_list_itr;
3715d95276ceSAkeem G Abodunrin 
3716d95276ceSAkeem G Abodunrin 	if (!em_list || !hw)
3717d54699e2STony Nguyen 		return -EINVAL;
3718d95276ceSAkeem G Abodunrin 
3719d95276ceSAkeem G Abodunrin 	list_for_each_entry(em_list_itr, em_list, list_entry) {
3720d95276ceSAkeem G Abodunrin 		enum ice_sw_lkup_type l_type =
3721d95276ceSAkeem G Abodunrin 			em_list_itr->fltr_info.lkup_type;
3722d95276ceSAkeem G Abodunrin 
3723d95276ceSAkeem G Abodunrin 		if (l_type != ICE_SW_LKUP_ETHERTYPE_MAC &&
3724d95276ceSAkeem G Abodunrin 		    l_type != ICE_SW_LKUP_ETHERTYPE)
3725d54699e2STony Nguyen 			return -EINVAL;
3726d95276ceSAkeem G Abodunrin 
3727d95276ceSAkeem G Abodunrin 		em_list_itr->status = ice_add_rule_internal(hw, l_type,
3728d95276ceSAkeem G Abodunrin 							    em_list_itr);
3729d95276ceSAkeem G Abodunrin 		if (em_list_itr->status)
3730d95276ceSAkeem G Abodunrin 			return em_list_itr->status;
3731d95276ceSAkeem G Abodunrin 	}
3732d95276ceSAkeem G Abodunrin 	return 0;
3733d95276ceSAkeem G Abodunrin }
3734d95276ceSAkeem G Abodunrin 
3735d95276ceSAkeem G Abodunrin /**
3736d95276ceSAkeem G Abodunrin  * ice_remove_eth_mac - Remove an ethertype (or MAC) based filter rule
3737d95276ceSAkeem G Abodunrin  * @hw: pointer to the hardware structure
3738d95276ceSAkeem G Abodunrin  * @em_list: list of ethertype or ethertype MAC entries
3739d95276ceSAkeem G Abodunrin  */
ice_remove_eth_mac(struct ice_hw * hw,struct list_head * em_list)37405518ac2aSTony Nguyen int ice_remove_eth_mac(struct ice_hw *hw, struct list_head *em_list)
3741d95276ceSAkeem G Abodunrin {
3742d95276ceSAkeem G Abodunrin 	struct ice_fltr_list_entry *em_list_itr, *tmp;
3743d95276ceSAkeem G Abodunrin 
3744d95276ceSAkeem G Abodunrin 	if (!em_list || !hw)
3745d54699e2STony Nguyen 		return -EINVAL;
3746d95276ceSAkeem G Abodunrin 
3747d95276ceSAkeem G Abodunrin 	list_for_each_entry_safe(em_list_itr, tmp, em_list, list_entry) {
3748d95276ceSAkeem G Abodunrin 		enum ice_sw_lkup_type l_type =
3749d95276ceSAkeem G Abodunrin 			em_list_itr->fltr_info.lkup_type;
3750d95276ceSAkeem G Abodunrin 
3751d95276ceSAkeem G Abodunrin 		if (l_type != ICE_SW_LKUP_ETHERTYPE_MAC &&
3752d95276ceSAkeem G Abodunrin 		    l_type != ICE_SW_LKUP_ETHERTYPE)
3753d54699e2STony Nguyen 			return -EINVAL;
3754d95276ceSAkeem G Abodunrin 
3755d95276ceSAkeem G Abodunrin 		em_list_itr->status = ice_remove_rule_internal(hw, l_type,
3756d95276ceSAkeem G Abodunrin 							       em_list_itr);
3757d95276ceSAkeem G Abodunrin 		if (em_list_itr->status)
3758d95276ceSAkeem G Abodunrin 			return em_list_itr->status;
3759d95276ceSAkeem G Abodunrin 	}
3760d95276ceSAkeem G Abodunrin 	return 0;
3761d95276ceSAkeem G Abodunrin }
3762d95276ceSAkeem G Abodunrin 
3763d95276ceSAkeem G Abodunrin /**
37640f9d5027SAnirudh Venkataramanan  * ice_rem_sw_rule_info
37650f9d5027SAnirudh Venkataramanan  * @hw: pointer to the hardware structure
37660f9d5027SAnirudh Venkataramanan  * @rule_head: pointer to the switch list structure that we want to delete
37670f9d5027SAnirudh Venkataramanan  */
37680f9d5027SAnirudh Venkataramanan static void
ice_rem_sw_rule_info(struct ice_hw * hw,struct list_head * rule_head)37690f9d5027SAnirudh Venkataramanan ice_rem_sw_rule_info(struct ice_hw *hw, struct list_head *rule_head)
37700f9d5027SAnirudh Venkataramanan {
37710f9d5027SAnirudh Venkataramanan 	if (!list_empty(rule_head)) {
37720f9d5027SAnirudh Venkataramanan 		struct ice_fltr_mgmt_list_entry *entry;
37730f9d5027SAnirudh Venkataramanan 		struct ice_fltr_mgmt_list_entry *tmp;
37740f9d5027SAnirudh Venkataramanan 
37750f9d5027SAnirudh Venkataramanan 		list_for_each_entry_safe(entry, tmp, rule_head, list_entry) {
37760f9d5027SAnirudh Venkataramanan 			list_del(&entry->list_entry);
37770f9d5027SAnirudh Venkataramanan 			devm_kfree(ice_hw_to_dev(hw), entry);
37780f9d5027SAnirudh Venkataramanan 		}
37790f9d5027SAnirudh Venkataramanan 	}
37800f9d5027SAnirudh Venkataramanan }
37810f9d5027SAnirudh Venkataramanan 
37820f9d5027SAnirudh Venkataramanan /**
37838b8ef05bSVictor Raj  * ice_rem_adv_rule_info
37848b8ef05bSVictor Raj  * @hw: pointer to the hardware structure
37858b8ef05bSVictor Raj  * @rule_head: pointer to the switch list structure that we want to delete
37868b8ef05bSVictor Raj  */
37878b8ef05bSVictor Raj static void
ice_rem_adv_rule_info(struct ice_hw * hw,struct list_head * rule_head)37888b8ef05bSVictor Raj ice_rem_adv_rule_info(struct ice_hw *hw, struct list_head *rule_head)
37898b8ef05bSVictor Raj {
37908b8ef05bSVictor Raj 	struct ice_adv_fltr_mgmt_list_entry *tmp_entry;
37918b8ef05bSVictor Raj 	struct ice_adv_fltr_mgmt_list_entry *lst_itr;
37928b8ef05bSVictor Raj 
37938b8ef05bSVictor Raj 	if (list_empty(rule_head))
37948b8ef05bSVictor Raj 		return;
37958b8ef05bSVictor Raj 
37968b8ef05bSVictor Raj 	list_for_each_entry_safe(lst_itr, tmp_entry, rule_head, list_entry) {
37978b8ef05bSVictor Raj 		list_del(&lst_itr->list_entry);
37988b8ef05bSVictor Raj 		devm_kfree(ice_hw_to_dev(hw), lst_itr->lkups);
37998b8ef05bSVictor Raj 		devm_kfree(ice_hw_to_dev(hw), lst_itr);
38008b8ef05bSVictor Raj 	}
38018b8ef05bSVictor Raj }
38028b8ef05bSVictor Raj 
38038b8ef05bSVictor Raj /**
380480d144c9SAnirudh Venkataramanan  * ice_cfg_dflt_vsi - change state of VSI to set/clear default
3805d7393425SMichal Wilczynski  * @pi: pointer to the port_info structure
38065726ca0eSAnirudh Venkataramanan  * @vsi_handle: VSI handle to set as default
3807e94d4478SAnirudh Venkataramanan  * @set: true to add the above mentioned switch rule, false to remove it
3808e94d4478SAnirudh Venkataramanan  * @direction: ICE_FLTR_RX or ICE_FLTR_TX
380980d144c9SAnirudh Venkataramanan  *
381080d144c9SAnirudh Venkataramanan  * add filter rule to set/unset given VSI as default VSI for the switch
381180d144c9SAnirudh Venkataramanan  * (represented by swid)
3812e94d4478SAnirudh Venkataramanan  */
3813d7393425SMichal Wilczynski int
ice_cfg_dflt_vsi(struct ice_port_info * pi,u16 vsi_handle,bool set,u8 direction)3814d7393425SMichal Wilczynski ice_cfg_dflt_vsi(struct ice_port_info *pi, u16 vsi_handle, bool set,
3815d7393425SMichal Wilczynski 		 u8 direction)
3816e94d4478SAnirudh Venkataramanan {
3817d7393425SMichal Wilczynski 	struct ice_fltr_list_entry f_list_entry;
3818e94d4478SAnirudh Venkataramanan 	struct ice_fltr_info f_info;
3819d7393425SMichal Wilczynski 	struct ice_hw *hw = pi->hw;
38205726ca0eSAnirudh Venkataramanan 	u16 hw_vsi_id;
38215518ac2aSTony Nguyen 	int status;
38225726ca0eSAnirudh Venkataramanan 
38235726ca0eSAnirudh Venkataramanan 	if (!ice_is_vsi_valid(hw, vsi_handle))
3824d54699e2STony Nguyen 		return -EINVAL;
3825d7393425SMichal Wilczynski 
38265726ca0eSAnirudh Venkataramanan 	hw_vsi_id = ice_get_hw_vsi_num(hw, vsi_handle);
3827e94d4478SAnirudh Venkataramanan 
3828e94d4478SAnirudh Venkataramanan 	memset(&f_info, 0, sizeof(f_info));
3829e94d4478SAnirudh Venkataramanan 
3830e94d4478SAnirudh Venkataramanan 	f_info.lkup_type = ICE_SW_LKUP_DFLT;
3831e94d4478SAnirudh Venkataramanan 	f_info.flag = direction;
3832e94d4478SAnirudh Venkataramanan 	f_info.fltr_act = ICE_FWD_TO_VSI;
38335726ca0eSAnirudh Venkataramanan 	f_info.fwd_id.hw_vsi_id = hw_vsi_id;
3834d7393425SMichal Wilczynski 	f_info.vsi_handle = vsi_handle;
3835e94d4478SAnirudh Venkataramanan 
3836e94d4478SAnirudh Venkataramanan 	if (f_info.flag & ICE_FLTR_RX) {
3837e94d4478SAnirudh Venkataramanan 		f_info.src = hw->port_info->lport;
38385726ca0eSAnirudh Venkataramanan 		f_info.src_id = ICE_SRC_ID_LPORT;
3839e94d4478SAnirudh Venkataramanan 	} else if (f_info.flag & ICE_FLTR_TX) {
38405726ca0eSAnirudh Venkataramanan 		f_info.src_id = ICE_SRC_ID_VSI;
38415726ca0eSAnirudh Venkataramanan 		f_info.src = hw_vsi_id;
3842e94d4478SAnirudh Venkataramanan 	}
3843d7393425SMichal Wilczynski 	f_list_entry.fltr_info = f_info;
3844e94d4478SAnirudh Venkataramanan 
3845e94d4478SAnirudh Venkataramanan 	if (set)
3846d7393425SMichal Wilczynski 		status = ice_add_rule_internal(hw, ICE_SW_LKUP_DFLT,
3847d7393425SMichal Wilczynski 					       &f_list_entry);
3848e94d4478SAnirudh Venkataramanan 	else
3849d7393425SMichal Wilczynski 		status = ice_remove_rule_internal(hw, ICE_SW_LKUP_DFLT,
3850d7393425SMichal Wilczynski 						  &f_list_entry);
3851e94d4478SAnirudh Venkataramanan 
3852e94d4478SAnirudh Venkataramanan 	return status;
3853e94d4478SAnirudh Venkataramanan }
3854e94d4478SAnirudh Venkataramanan 
3855e94d4478SAnirudh Venkataramanan /**
3856d7393425SMichal Wilczynski  * ice_vsi_uses_fltr - Determine if given VSI uses specified filter
3857d7393425SMichal Wilczynski  * @fm_entry: filter entry to inspect
3858d7393425SMichal Wilczynski  * @vsi_handle: VSI handle to compare with filter info
3859d7393425SMichal Wilczynski  */
3860d7393425SMichal Wilczynski static bool
ice_vsi_uses_fltr(struct ice_fltr_mgmt_list_entry * fm_entry,u16 vsi_handle)3861d7393425SMichal Wilczynski ice_vsi_uses_fltr(struct ice_fltr_mgmt_list_entry *fm_entry, u16 vsi_handle)
3862d7393425SMichal Wilczynski {
3863d7393425SMichal Wilczynski 	return ((fm_entry->fltr_info.fltr_act == ICE_FWD_TO_VSI &&
3864d7393425SMichal Wilczynski 		 fm_entry->fltr_info.vsi_handle == vsi_handle) ||
3865d7393425SMichal Wilczynski 		(fm_entry->fltr_info.fltr_act == ICE_FWD_TO_VSI_LIST &&
3866d7393425SMichal Wilczynski 		 fm_entry->vsi_list_info &&
3867d7393425SMichal Wilczynski 		 (test_bit(vsi_handle, fm_entry->vsi_list_info->vsi_map))));
3868d7393425SMichal Wilczynski }
3869d7393425SMichal Wilczynski 
3870d7393425SMichal Wilczynski /**
3871d7393425SMichal Wilczynski  * ice_check_if_dflt_vsi - check if VSI is default VSI
3872d7393425SMichal Wilczynski  * @pi: pointer to the port_info structure
3873d7393425SMichal Wilczynski  * @vsi_handle: vsi handle to check for in filter list
3874d7393425SMichal Wilczynski  * @rule_exists: indicates if there are any VSI's in the rule list
3875d7393425SMichal Wilczynski  *
3876d7393425SMichal Wilczynski  * checks if the VSI is in a default VSI list, and also indicates
3877d7393425SMichal Wilczynski  * if the default VSI list is empty
3878d7393425SMichal Wilczynski  */
3879d7393425SMichal Wilczynski bool
ice_check_if_dflt_vsi(struct ice_port_info * pi,u16 vsi_handle,bool * rule_exists)3880d7393425SMichal Wilczynski ice_check_if_dflt_vsi(struct ice_port_info *pi, u16 vsi_handle,
3881d7393425SMichal Wilczynski 		      bool *rule_exists)
3882d7393425SMichal Wilczynski {
3883d7393425SMichal Wilczynski 	struct ice_fltr_mgmt_list_entry *fm_entry;
3884d7393425SMichal Wilczynski 	struct ice_sw_recipe *recp_list;
3885d7393425SMichal Wilczynski 	struct list_head *rule_head;
3886d7393425SMichal Wilczynski 	struct mutex *rule_lock; /* Lock to protect filter rule list */
3887d7393425SMichal Wilczynski 	bool ret = false;
3888d7393425SMichal Wilczynski 
3889d7393425SMichal Wilczynski 	recp_list = &pi->hw->switch_info->recp_list[ICE_SW_LKUP_DFLT];
3890d7393425SMichal Wilczynski 	rule_lock = &recp_list->filt_rule_lock;
3891d7393425SMichal Wilczynski 	rule_head = &recp_list->filt_rules;
3892d7393425SMichal Wilczynski 
3893d7393425SMichal Wilczynski 	mutex_lock(rule_lock);
3894d7393425SMichal Wilczynski 
3895d7393425SMichal Wilczynski 	if (rule_exists && !list_empty(rule_head))
3896d7393425SMichal Wilczynski 		*rule_exists = true;
3897d7393425SMichal Wilczynski 
3898d7393425SMichal Wilczynski 	list_for_each_entry(fm_entry, rule_head, list_entry) {
3899d7393425SMichal Wilczynski 		if (ice_vsi_uses_fltr(fm_entry, vsi_handle)) {
3900d7393425SMichal Wilczynski 			ret = true;
3901d7393425SMichal Wilczynski 			break;
3902d7393425SMichal Wilczynski 		}
3903d7393425SMichal Wilczynski 	}
3904d7393425SMichal Wilczynski 
3905d7393425SMichal Wilczynski 	mutex_unlock(rule_lock);
3906d7393425SMichal Wilczynski 
3907d7393425SMichal Wilczynski 	return ret;
3908d7393425SMichal Wilczynski }
3909d7393425SMichal Wilczynski 
3910d7393425SMichal Wilczynski /**
391180d144c9SAnirudh Venkataramanan  * ice_remove_mac - remove a MAC address based filter rule
3912d76a60baSAnirudh Venkataramanan  * @hw: pointer to the hardware structure
391380d144c9SAnirudh Venkataramanan  * @m_list: list of MAC addresses and forwarding information
391480d144c9SAnirudh Venkataramanan  *
391580d144c9SAnirudh Venkataramanan  * This function removes either a MAC filter rule or a specific VSI from a
391680d144c9SAnirudh Venkataramanan  * VSI list for a multicast MAC address.
391780d144c9SAnirudh Venkataramanan  *
39185518ac2aSTony Nguyen  * Returns -ENOENT if a given entry was not added by ice_add_mac. Caller should
39195518ac2aSTony Nguyen  * be aware that this call will only work if all the entries passed into m_list
39205518ac2aSTony Nguyen  * were added previously. It will not attempt to do a partial remove of entries
39215518ac2aSTony Nguyen  * that were found.
3922d76a60baSAnirudh Venkataramanan  */
ice_remove_mac(struct ice_hw * hw,struct list_head * m_list)39235e24d598STony Nguyen int ice_remove_mac(struct ice_hw *hw, struct list_head *m_list)
3924d76a60baSAnirudh Venkataramanan {
3925072f0c3dSDave Ertman 	struct ice_fltr_list_entry *list_itr, *tmp;
3926d76a60baSAnirudh Venkataramanan 
392780d144c9SAnirudh Venkataramanan 	if (!m_list)
3928d54699e2STony Nguyen 		return -EINVAL;
3929d76a60baSAnirudh Venkataramanan 
3930072f0c3dSDave Ertman 	list_for_each_entry_safe(list_itr, tmp, m_list, list_entry) {
393180d144c9SAnirudh Venkataramanan 		enum ice_sw_lkup_type l_type = list_itr->fltr_info.lkup_type;
39328b2c8582SAkeem G Abodunrin 		u16 vsi_handle;
393380d144c9SAnirudh Venkataramanan 
393480d144c9SAnirudh Venkataramanan 		if (l_type != ICE_SW_LKUP_MAC)
3935d54699e2STony Nguyen 			return -EINVAL;
39368b2c8582SAkeem G Abodunrin 
39378b2c8582SAkeem G Abodunrin 		vsi_handle = list_itr->fltr_info.vsi_handle;
39388b2c8582SAkeem G Abodunrin 		if (!ice_is_vsi_valid(hw, vsi_handle))
3939d54699e2STony Nguyen 			return -EINVAL;
39408b2c8582SAkeem G Abodunrin 
39418b2c8582SAkeem G Abodunrin 		list_itr->fltr_info.fwd_id.hw_vsi_id =
39428b2c8582SAkeem G Abodunrin 					ice_get_hw_vsi_num(hw, vsi_handle);
3943e1e9db57SSylwester Dziedziuch 
394480d144c9SAnirudh Venkataramanan 		list_itr->status = ice_remove_rule_internal(hw,
394580d144c9SAnirudh Venkataramanan 							    ICE_SW_LKUP_MAC,
394680d144c9SAnirudh Venkataramanan 							    list_itr);
394780d144c9SAnirudh Venkataramanan 		if (list_itr->status)
394880d144c9SAnirudh Venkataramanan 			return list_itr->status;
394980d144c9SAnirudh Venkataramanan 	}
395080d144c9SAnirudh Venkataramanan 	return 0;
3951d76a60baSAnirudh Venkataramanan }
3952d76a60baSAnirudh Venkataramanan 
3953d76a60baSAnirudh Venkataramanan /**
3954d76a60baSAnirudh Venkataramanan  * ice_remove_vlan - Remove VLAN based filter rule
3955d76a60baSAnirudh Venkataramanan  * @hw: pointer to the hardware structure
3956d76a60baSAnirudh Venkataramanan  * @v_list: list of VLAN entries and forwarding information
3957d76a60baSAnirudh Venkataramanan  */
ice_remove_vlan(struct ice_hw * hw,struct list_head * v_list)39585518ac2aSTony Nguyen int ice_remove_vlan(struct ice_hw *hw, struct list_head *v_list)
3959d76a60baSAnirudh Venkataramanan {
3960072f0c3dSDave Ertman 	struct ice_fltr_list_entry *v_list_itr, *tmp;
3961d76a60baSAnirudh Venkataramanan 
3962d76a60baSAnirudh Venkataramanan 	if (!v_list || !hw)
3963d54699e2STony Nguyen 		return -EINVAL;
3964d76a60baSAnirudh Venkataramanan 
3965072f0c3dSDave Ertman 	list_for_each_entry_safe(v_list_itr, tmp, v_list, list_entry) {
396680d144c9SAnirudh Venkataramanan 		enum ice_sw_lkup_type l_type = v_list_itr->fltr_info.lkup_type;
396780d144c9SAnirudh Venkataramanan 
396880d144c9SAnirudh Venkataramanan 		if (l_type != ICE_SW_LKUP_VLAN)
3969d54699e2STony Nguyen 			return -EINVAL;
397080d144c9SAnirudh Venkataramanan 		v_list_itr->status = ice_remove_rule_internal(hw,
397180d144c9SAnirudh Venkataramanan 							      ICE_SW_LKUP_VLAN,
397280d144c9SAnirudh Venkataramanan 							      v_list_itr);
397380d144c9SAnirudh Venkataramanan 		if (v_list_itr->status)
397480d144c9SAnirudh Venkataramanan 			return v_list_itr->status;
3975d76a60baSAnirudh Venkataramanan 	}
397680d144c9SAnirudh Venkataramanan 	return 0;
3977d76a60baSAnirudh Venkataramanan }
397880d144c9SAnirudh Venkataramanan 
397980d144c9SAnirudh Venkataramanan /**
398080d144c9SAnirudh Venkataramanan  * ice_add_entry_to_vsi_fltr_list - Add copy of fltr_list_entry to remove list
398180d144c9SAnirudh Venkataramanan  * @hw: pointer to the hardware structure
39825726ca0eSAnirudh Venkataramanan  * @vsi_handle: VSI handle to remove filters from
398380d144c9SAnirudh Venkataramanan  * @vsi_list_head: pointer to the list to add entry to
398480d144c9SAnirudh Venkataramanan  * @fi: pointer to fltr_info of filter entry to copy & add
398580d144c9SAnirudh Venkataramanan  *
398680d144c9SAnirudh Venkataramanan  * Helper function, used when creating a list of filters to remove from
398780d144c9SAnirudh Venkataramanan  * a specific VSI. The entry added to vsi_list_head is a COPY of the
398880d144c9SAnirudh Venkataramanan  * original filter entry, with the exception of fltr_info.fltr_act and
398980d144c9SAnirudh Venkataramanan  * fltr_info.fwd_id fields. These are set such that later logic can
399080d144c9SAnirudh Venkataramanan  * extract which VSI to remove the fltr from, and pass on that information.
399180d144c9SAnirudh Venkataramanan  */
39925e24d598STony Nguyen static int
ice_add_entry_to_vsi_fltr_list(struct ice_hw * hw,u16 vsi_handle,struct list_head * vsi_list_head,struct ice_fltr_info * fi)39935726ca0eSAnirudh Venkataramanan ice_add_entry_to_vsi_fltr_list(struct ice_hw *hw, u16 vsi_handle,
399480d144c9SAnirudh Venkataramanan 			       struct list_head *vsi_list_head,
399580d144c9SAnirudh Venkataramanan 			       struct ice_fltr_info *fi)
399680d144c9SAnirudh Venkataramanan {
399780d144c9SAnirudh Venkataramanan 	struct ice_fltr_list_entry *tmp;
399880d144c9SAnirudh Venkataramanan 
399980d144c9SAnirudh Venkataramanan 	/* this memory is freed up in the caller function
400080d144c9SAnirudh Venkataramanan 	 * once filters for this VSI are removed
400180d144c9SAnirudh Venkataramanan 	 */
400280d144c9SAnirudh Venkataramanan 	tmp = devm_kzalloc(ice_hw_to_dev(hw), sizeof(*tmp), GFP_KERNEL);
400380d144c9SAnirudh Venkataramanan 	if (!tmp)
4004d54699e2STony Nguyen 		return -ENOMEM;
400580d144c9SAnirudh Venkataramanan 
400680d144c9SAnirudh Venkataramanan 	tmp->fltr_info = *fi;
400780d144c9SAnirudh Venkataramanan 
400880d144c9SAnirudh Venkataramanan 	/* Overwrite these fields to indicate which VSI to remove filter from,
400980d144c9SAnirudh Venkataramanan 	 * so find and remove logic can extract the information from the
401080d144c9SAnirudh Venkataramanan 	 * list entries. Note that original entries will still have proper
401180d144c9SAnirudh Venkataramanan 	 * values.
401280d144c9SAnirudh Venkataramanan 	 */
401380d144c9SAnirudh Venkataramanan 	tmp->fltr_info.fltr_act = ICE_FWD_TO_VSI;
40145726ca0eSAnirudh Venkataramanan 	tmp->fltr_info.vsi_handle = vsi_handle;
40155726ca0eSAnirudh Venkataramanan 	tmp->fltr_info.fwd_id.hw_vsi_id = ice_get_hw_vsi_num(hw, vsi_handle);
401680d144c9SAnirudh Venkataramanan 
401780d144c9SAnirudh Venkataramanan 	list_add(&tmp->list_entry, vsi_list_head);
401880d144c9SAnirudh Venkataramanan 
401980d144c9SAnirudh Venkataramanan 	return 0;
4020d76a60baSAnirudh Venkataramanan }
4021d76a60baSAnirudh Venkataramanan 
4022d76a60baSAnirudh Venkataramanan /**
40239daf8208SAnirudh Venkataramanan  * ice_add_to_vsi_fltr_list - Add VSI filters to the list
40249daf8208SAnirudh Venkataramanan  * @hw: pointer to the hardware structure
40255726ca0eSAnirudh Venkataramanan  * @vsi_handle: VSI handle to remove filters from
40269daf8208SAnirudh Venkataramanan  * @lkup_list_head: pointer to the list that has certain lookup type filters
40275726ca0eSAnirudh Venkataramanan  * @vsi_list_head: pointer to the list pertaining to VSI with vsi_handle
402880d144c9SAnirudh Venkataramanan  *
402980d144c9SAnirudh Venkataramanan  * Locates all filters in lkup_list_head that are used by the given VSI,
403080d144c9SAnirudh Venkataramanan  * and adds COPIES of those entries to vsi_list_head (intended to be used
403180d144c9SAnirudh Venkataramanan  * to remove the listed filters).
403280d144c9SAnirudh Venkataramanan  * Note that this means all entries in vsi_list_head must be explicitly
403380d144c9SAnirudh Venkataramanan  * deallocated by the caller when done with list.
40349daf8208SAnirudh Venkataramanan  */
40355e24d598STony Nguyen static int
ice_add_to_vsi_fltr_list(struct ice_hw * hw,u16 vsi_handle,struct list_head * lkup_list_head,struct list_head * vsi_list_head)40365726ca0eSAnirudh Venkataramanan ice_add_to_vsi_fltr_list(struct ice_hw *hw, u16 vsi_handle,
40379daf8208SAnirudh Venkataramanan 			 struct list_head *lkup_list_head,
40389daf8208SAnirudh Venkataramanan 			 struct list_head *vsi_list_head)
40399daf8208SAnirudh Venkataramanan {
40409daf8208SAnirudh Venkataramanan 	struct ice_fltr_mgmt_list_entry *fm_entry;
40415e24d598STony Nguyen 	int status = 0;
40429daf8208SAnirudh Venkataramanan 
4043f9867df6SAnirudh Venkataramanan 	/* check to make sure VSI ID is valid and within boundary */
40445726ca0eSAnirudh Venkataramanan 	if (!ice_is_vsi_valid(hw, vsi_handle))
4045d54699e2STony Nguyen 		return -EINVAL;
40469daf8208SAnirudh Venkataramanan 
40479daf8208SAnirudh Venkataramanan 	list_for_each_entry(fm_entry, lkup_list_head, list_entry) {
40487a91d3f0SJacek Bułatek 		if (!ice_vsi_uses_fltr(fm_entry, vsi_handle))
404980d144c9SAnirudh Venkataramanan 			continue;
40509daf8208SAnirudh Venkataramanan 
40515726ca0eSAnirudh Venkataramanan 		status = ice_add_entry_to_vsi_fltr_list(hw, vsi_handle,
40527a91d3f0SJacek Bułatek 							vsi_list_head,
40537a91d3f0SJacek Bułatek 							&fm_entry->fltr_info);
405480d144c9SAnirudh Venkataramanan 		if (status)
405580d144c9SAnirudh Venkataramanan 			return status;
40569daf8208SAnirudh Venkataramanan 	}
405780d144c9SAnirudh Venkataramanan 	return status;
40589daf8208SAnirudh Venkataramanan }
40599daf8208SAnirudh Venkataramanan 
40609daf8208SAnirudh Venkataramanan /**
40615eda8afdSAkeem G Abodunrin  * ice_determine_promisc_mask
40625eda8afdSAkeem G Abodunrin  * @fi: filter info to parse
40635eda8afdSAkeem G Abodunrin  *
40645eda8afdSAkeem G Abodunrin  * Helper function to determine which ICE_PROMISC_ mask corresponds
40655eda8afdSAkeem G Abodunrin  * to given filter into.
40665eda8afdSAkeem G Abodunrin  */
ice_determine_promisc_mask(struct ice_fltr_info * fi)40675eda8afdSAkeem G Abodunrin static u8 ice_determine_promisc_mask(struct ice_fltr_info *fi)
40685eda8afdSAkeem G Abodunrin {
40695eda8afdSAkeem G Abodunrin 	u16 vid = fi->l_data.mac_vlan.vlan_id;
40705eda8afdSAkeem G Abodunrin 	u8 *macaddr = fi->l_data.mac.mac_addr;
40715eda8afdSAkeem G Abodunrin 	bool is_tx_fltr = false;
40725eda8afdSAkeem G Abodunrin 	u8 promisc_mask = 0;
40735eda8afdSAkeem G Abodunrin 
40745eda8afdSAkeem G Abodunrin 	if (fi->flag == ICE_FLTR_TX)
40755eda8afdSAkeem G Abodunrin 		is_tx_fltr = true;
40765eda8afdSAkeem G Abodunrin 
40775eda8afdSAkeem G Abodunrin 	if (is_broadcast_ether_addr(macaddr))
40785eda8afdSAkeem G Abodunrin 		promisc_mask |= is_tx_fltr ?
40795eda8afdSAkeem G Abodunrin 			ICE_PROMISC_BCAST_TX : ICE_PROMISC_BCAST_RX;
40805eda8afdSAkeem G Abodunrin 	else if (is_multicast_ether_addr(macaddr))
40815eda8afdSAkeem G Abodunrin 		promisc_mask |= is_tx_fltr ?
40825eda8afdSAkeem G Abodunrin 			ICE_PROMISC_MCAST_TX : ICE_PROMISC_MCAST_RX;
40835eda8afdSAkeem G Abodunrin 	else if (is_unicast_ether_addr(macaddr))
40845eda8afdSAkeem G Abodunrin 		promisc_mask |= is_tx_fltr ?
40855eda8afdSAkeem G Abodunrin 			ICE_PROMISC_UCAST_TX : ICE_PROMISC_UCAST_RX;
40865eda8afdSAkeem G Abodunrin 	if (vid)
40875eda8afdSAkeem G Abodunrin 		promisc_mask |= is_tx_fltr ?
40885eda8afdSAkeem G Abodunrin 			ICE_PROMISC_VLAN_TX : ICE_PROMISC_VLAN_RX;
40895eda8afdSAkeem G Abodunrin 
40905eda8afdSAkeem G Abodunrin 	return promisc_mask;
40915eda8afdSAkeem G Abodunrin }
40925eda8afdSAkeem G Abodunrin 
40935eda8afdSAkeem G Abodunrin /**
40945eda8afdSAkeem G Abodunrin  * ice_remove_promisc - Remove promisc based filter rules
40955eda8afdSAkeem G Abodunrin  * @hw: pointer to the hardware structure
4096f9867df6SAnirudh Venkataramanan  * @recp_id: recipe ID for which the rule needs to removed
40975eda8afdSAkeem G Abodunrin  * @v_list: list of promisc entries
40985eda8afdSAkeem G Abodunrin  */
40995e24d598STony Nguyen static int
ice_remove_promisc(struct ice_hw * hw,u8 recp_id,struct list_head * v_list)41005518ac2aSTony Nguyen ice_remove_promisc(struct ice_hw *hw, u8 recp_id, struct list_head *v_list)
41015eda8afdSAkeem G Abodunrin {
41025eda8afdSAkeem G Abodunrin 	struct ice_fltr_list_entry *v_list_itr, *tmp;
41035eda8afdSAkeem G Abodunrin 
41045eda8afdSAkeem G Abodunrin 	list_for_each_entry_safe(v_list_itr, tmp, v_list, list_entry) {
41055eda8afdSAkeem G Abodunrin 		v_list_itr->status =
41065eda8afdSAkeem G Abodunrin 			ice_remove_rule_internal(hw, recp_id, v_list_itr);
41075eda8afdSAkeem G Abodunrin 		if (v_list_itr->status)
41085eda8afdSAkeem G Abodunrin 			return v_list_itr->status;
41095eda8afdSAkeem G Abodunrin 	}
41105eda8afdSAkeem G Abodunrin 	return 0;
41115eda8afdSAkeem G Abodunrin }
41125eda8afdSAkeem G Abodunrin 
41135eda8afdSAkeem G Abodunrin /**
41145eda8afdSAkeem G Abodunrin  * ice_clear_vsi_promisc - clear specified promiscuous mode(s) for given VSI
41155eda8afdSAkeem G Abodunrin  * @hw: pointer to the hardware structure
41165eda8afdSAkeem G Abodunrin  * @vsi_handle: VSI handle to clear mode
41175eda8afdSAkeem G Abodunrin  * @promisc_mask: mask of promiscuous config bits to clear
41185eda8afdSAkeem G Abodunrin  * @vid: VLAN ID to clear VLAN promiscuous
41195eda8afdSAkeem G Abodunrin  */
41205e24d598STony Nguyen int
ice_clear_vsi_promisc(struct ice_hw * hw,u16 vsi_handle,u8 promisc_mask,u16 vid)41215eda8afdSAkeem G Abodunrin ice_clear_vsi_promisc(struct ice_hw *hw, u16 vsi_handle, u8 promisc_mask,
41225eda8afdSAkeem G Abodunrin 		      u16 vid)
41235eda8afdSAkeem G Abodunrin {
41245eda8afdSAkeem G Abodunrin 	struct ice_switch_info *sw = hw->switch_info;
41255eda8afdSAkeem G Abodunrin 	struct ice_fltr_list_entry *fm_entry, *tmp;
41265eda8afdSAkeem G Abodunrin 	struct list_head remove_list_head;
41275eda8afdSAkeem G Abodunrin 	struct ice_fltr_mgmt_list_entry *itr;
41285eda8afdSAkeem G Abodunrin 	struct list_head *rule_head;
41295eda8afdSAkeem G Abodunrin 	struct mutex *rule_lock;	/* Lock to protect filter rule list */
41305e24d598STony Nguyen 	int status = 0;
41315eda8afdSAkeem G Abodunrin 	u8 recipe_id;
41325eda8afdSAkeem G Abodunrin 
41335eda8afdSAkeem G Abodunrin 	if (!ice_is_vsi_valid(hw, vsi_handle))
4134d54699e2STony Nguyen 		return -EINVAL;
41355eda8afdSAkeem G Abodunrin 
41361bc7a4abSBrett Creeley 	if (promisc_mask & (ICE_PROMISC_VLAN_RX | ICE_PROMISC_VLAN_TX))
41375eda8afdSAkeem G Abodunrin 		recipe_id = ICE_SW_LKUP_PROMISC_VLAN;
41385eda8afdSAkeem G Abodunrin 	else
41395eda8afdSAkeem G Abodunrin 		recipe_id = ICE_SW_LKUP_PROMISC;
41405eda8afdSAkeem G Abodunrin 
41415eda8afdSAkeem G Abodunrin 	rule_head = &sw->recp_list[recipe_id].filt_rules;
41425eda8afdSAkeem G Abodunrin 	rule_lock = &sw->recp_list[recipe_id].filt_rule_lock;
41435eda8afdSAkeem G Abodunrin 
41445eda8afdSAkeem G Abodunrin 	INIT_LIST_HEAD(&remove_list_head);
41455eda8afdSAkeem G Abodunrin 
41465eda8afdSAkeem G Abodunrin 	mutex_lock(rule_lock);
41475eda8afdSAkeem G Abodunrin 	list_for_each_entry(itr, rule_head, list_entry) {
41481bc7a4abSBrett Creeley 		struct ice_fltr_info *fltr_info;
41495eda8afdSAkeem G Abodunrin 		u8 fltr_promisc_mask = 0;
41505eda8afdSAkeem G Abodunrin 
41515eda8afdSAkeem G Abodunrin 		if (!ice_vsi_uses_fltr(itr, vsi_handle))
41525eda8afdSAkeem G Abodunrin 			continue;
41531bc7a4abSBrett Creeley 		fltr_info = &itr->fltr_info;
41545eda8afdSAkeem G Abodunrin 
41551bc7a4abSBrett Creeley 		if (recipe_id == ICE_SW_LKUP_PROMISC_VLAN &&
41561bc7a4abSBrett Creeley 		    vid != fltr_info->l_data.mac_vlan.vlan_id)
41571bc7a4abSBrett Creeley 			continue;
41581bc7a4abSBrett Creeley 
41591bc7a4abSBrett Creeley 		fltr_promisc_mask |= ice_determine_promisc_mask(fltr_info);
41605eda8afdSAkeem G Abodunrin 
41615eda8afdSAkeem G Abodunrin 		/* Skip if filter is not completely specified by given mask */
41625eda8afdSAkeem G Abodunrin 		if (fltr_promisc_mask & ~promisc_mask)
41635eda8afdSAkeem G Abodunrin 			continue;
41645eda8afdSAkeem G Abodunrin 
41655eda8afdSAkeem G Abodunrin 		status = ice_add_entry_to_vsi_fltr_list(hw, vsi_handle,
41665eda8afdSAkeem G Abodunrin 							&remove_list_head,
41671bc7a4abSBrett Creeley 							fltr_info);
41685eda8afdSAkeem G Abodunrin 		if (status) {
41695eda8afdSAkeem G Abodunrin 			mutex_unlock(rule_lock);
41705eda8afdSAkeem G Abodunrin 			goto free_fltr_list;
41715eda8afdSAkeem G Abodunrin 		}
41725eda8afdSAkeem G Abodunrin 	}
41735eda8afdSAkeem G Abodunrin 	mutex_unlock(rule_lock);
41745eda8afdSAkeem G Abodunrin 
41755eda8afdSAkeem G Abodunrin 	status = ice_remove_promisc(hw, recipe_id, &remove_list_head);
41765eda8afdSAkeem G Abodunrin 
41775eda8afdSAkeem G Abodunrin free_fltr_list:
41785eda8afdSAkeem G Abodunrin 	list_for_each_entry_safe(fm_entry, tmp, &remove_list_head, list_entry) {
41795eda8afdSAkeem G Abodunrin 		list_del(&fm_entry->list_entry);
41805eda8afdSAkeem G Abodunrin 		devm_kfree(ice_hw_to_dev(hw), fm_entry);
41815eda8afdSAkeem G Abodunrin 	}
41825eda8afdSAkeem G Abodunrin 
41835eda8afdSAkeem G Abodunrin 	return status;
41845eda8afdSAkeem G Abodunrin }
41855eda8afdSAkeem G Abodunrin 
41865eda8afdSAkeem G Abodunrin /**
41875eda8afdSAkeem G Abodunrin  * ice_set_vsi_promisc - set given VSI to given promiscuous mode(s)
41885eda8afdSAkeem G Abodunrin  * @hw: pointer to the hardware structure
41895eda8afdSAkeem G Abodunrin  * @vsi_handle: VSI handle to configure
41905eda8afdSAkeem G Abodunrin  * @promisc_mask: mask of promiscuous config bits
41915eda8afdSAkeem G Abodunrin  * @vid: VLAN ID to set VLAN promiscuous
41925eda8afdSAkeem G Abodunrin  */
41935e24d598STony Nguyen int
ice_set_vsi_promisc(struct ice_hw * hw,u16 vsi_handle,u8 promisc_mask,u16 vid)41945eda8afdSAkeem G Abodunrin ice_set_vsi_promisc(struct ice_hw *hw, u16 vsi_handle, u8 promisc_mask, u16 vid)
41955eda8afdSAkeem G Abodunrin {
41965eda8afdSAkeem G Abodunrin 	enum { UCAST_FLTR = 1, MCAST_FLTR, BCAST_FLTR };
41975eda8afdSAkeem G Abodunrin 	struct ice_fltr_list_entry f_list_entry;
41985eda8afdSAkeem G Abodunrin 	struct ice_fltr_info new_fltr;
41995eda8afdSAkeem G Abodunrin 	bool is_tx_fltr;
42005518ac2aSTony Nguyen 	int status = 0;
42015eda8afdSAkeem G Abodunrin 	u16 hw_vsi_id;
42025eda8afdSAkeem G Abodunrin 	int pkt_type;
42035eda8afdSAkeem G Abodunrin 	u8 recipe_id;
42045eda8afdSAkeem G Abodunrin 
42055eda8afdSAkeem G Abodunrin 	if (!ice_is_vsi_valid(hw, vsi_handle))
4206d54699e2STony Nguyen 		return -EINVAL;
42075eda8afdSAkeem G Abodunrin 	hw_vsi_id = ice_get_hw_vsi_num(hw, vsi_handle);
42085eda8afdSAkeem G Abodunrin 
42095eda8afdSAkeem G Abodunrin 	memset(&new_fltr, 0, sizeof(new_fltr));
42105eda8afdSAkeem G Abodunrin 
42115eda8afdSAkeem G Abodunrin 	if (promisc_mask & (ICE_PROMISC_VLAN_RX | ICE_PROMISC_VLAN_TX)) {
42125eda8afdSAkeem G Abodunrin 		new_fltr.lkup_type = ICE_SW_LKUP_PROMISC_VLAN;
42135eda8afdSAkeem G Abodunrin 		new_fltr.l_data.mac_vlan.vlan_id = vid;
42145eda8afdSAkeem G Abodunrin 		recipe_id = ICE_SW_LKUP_PROMISC_VLAN;
42155eda8afdSAkeem G Abodunrin 	} else {
42165eda8afdSAkeem G Abodunrin 		new_fltr.lkup_type = ICE_SW_LKUP_PROMISC;
42175eda8afdSAkeem G Abodunrin 		recipe_id = ICE_SW_LKUP_PROMISC;
42185eda8afdSAkeem G Abodunrin 	}
42195eda8afdSAkeem G Abodunrin 
42205eda8afdSAkeem G Abodunrin 	/* Separate filters must be set for each direction/packet type
42215eda8afdSAkeem G Abodunrin 	 * combination, so we will loop over the mask value, store the
42225eda8afdSAkeem G Abodunrin 	 * individual type, and clear it out in the input mask as it
42235eda8afdSAkeem G Abodunrin 	 * is found.
42245eda8afdSAkeem G Abodunrin 	 */
42255eda8afdSAkeem G Abodunrin 	while (promisc_mask) {
42265eda8afdSAkeem G Abodunrin 		u8 *mac_addr;
42275eda8afdSAkeem G Abodunrin 
42285eda8afdSAkeem G Abodunrin 		pkt_type = 0;
42295eda8afdSAkeem G Abodunrin 		is_tx_fltr = false;
42305eda8afdSAkeem G Abodunrin 
42315eda8afdSAkeem G Abodunrin 		if (promisc_mask & ICE_PROMISC_UCAST_RX) {
42325eda8afdSAkeem G Abodunrin 			promisc_mask &= ~ICE_PROMISC_UCAST_RX;
42335eda8afdSAkeem G Abodunrin 			pkt_type = UCAST_FLTR;
42345eda8afdSAkeem G Abodunrin 		} else if (promisc_mask & ICE_PROMISC_UCAST_TX) {
42355eda8afdSAkeem G Abodunrin 			promisc_mask &= ~ICE_PROMISC_UCAST_TX;
42365eda8afdSAkeem G Abodunrin 			pkt_type = UCAST_FLTR;
42375eda8afdSAkeem G Abodunrin 			is_tx_fltr = true;
42385eda8afdSAkeem G Abodunrin 		} else if (promisc_mask & ICE_PROMISC_MCAST_RX) {
42395eda8afdSAkeem G Abodunrin 			promisc_mask &= ~ICE_PROMISC_MCAST_RX;
42405eda8afdSAkeem G Abodunrin 			pkt_type = MCAST_FLTR;
42415eda8afdSAkeem G Abodunrin 		} else if (promisc_mask & ICE_PROMISC_MCAST_TX) {
42425eda8afdSAkeem G Abodunrin 			promisc_mask &= ~ICE_PROMISC_MCAST_TX;
42435eda8afdSAkeem G Abodunrin 			pkt_type = MCAST_FLTR;
42445eda8afdSAkeem G Abodunrin 			is_tx_fltr = true;
42455eda8afdSAkeem G Abodunrin 		} else if (promisc_mask & ICE_PROMISC_BCAST_RX) {
42465eda8afdSAkeem G Abodunrin 			promisc_mask &= ~ICE_PROMISC_BCAST_RX;
42475eda8afdSAkeem G Abodunrin 			pkt_type = BCAST_FLTR;
42485eda8afdSAkeem G Abodunrin 		} else if (promisc_mask & ICE_PROMISC_BCAST_TX) {
42495eda8afdSAkeem G Abodunrin 			promisc_mask &= ~ICE_PROMISC_BCAST_TX;
42505eda8afdSAkeem G Abodunrin 			pkt_type = BCAST_FLTR;
42515eda8afdSAkeem G Abodunrin 			is_tx_fltr = true;
42525eda8afdSAkeem G Abodunrin 		}
42535eda8afdSAkeem G Abodunrin 
42545eda8afdSAkeem G Abodunrin 		/* Check for VLAN promiscuous flag */
42555eda8afdSAkeem G Abodunrin 		if (promisc_mask & ICE_PROMISC_VLAN_RX) {
42565eda8afdSAkeem G Abodunrin 			promisc_mask &= ~ICE_PROMISC_VLAN_RX;
42575eda8afdSAkeem G Abodunrin 		} else if (promisc_mask & ICE_PROMISC_VLAN_TX) {
42585eda8afdSAkeem G Abodunrin 			promisc_mask &= ~ICE_PROMISC_VLAN_TX;
42595eda8afdSAkeem G Abodunrin 			is_tx_fltr = true;
42605eda8afdSAkeem G Abodunrin 		}
42615eda8afdSAkeem G Abodunrin 
42625eda8afdSAkeem G Abodunrin 		/* Set filter DA based on packet type */
42635eda8afdSAkeem G Abodunrin 		mac_addr = new_fltr.l_data.mac.mac_addr;
42645eda8afdSAkeem G Abodunrin 		if (pkt_type == BCAST_FLTR) {
42655eda8afdSAkeem G Abodunrin 			eth_broadcast_addr(mac_addr);
42665eda8afdSAkeem G Abodunrin 		} else if (pkt_type == MCAST_FLTR ||
42675eda8afdSAkeem G Abodunrin 			   pkt_type == UCAST_FLTR) {
42685eda8afdSAkeem G Abodunrin 			/* Use the dummy ether header DA */
42695eda8afdSAkeem G Abodunrin 			ether_addr_copy(mac_addr, dummy_eth_header);
42705eda8afdSAkeem G Abodunrin 			if (pkt_type == MCAST_FLTR)
42715eda8afdSAkeem G Abodunrin 				mac_addr[0] |= 0x1;	/* Set multicast bit */
42725eda8afdSAkeem G Abodunrin 		}
42735eda8afdSAkeem G Abodunrin 
42745eda8afdSAkeem G Abodunrin 		/* Need to reset this to zero for all iterations */
42755eda8afdSAkeem G Abodunrin 		new_fltr.flag = 0;
42765eda8afdSAkeem G Abodunrin 		if (is_tx_fltr) {
42775eda8afdSAkeem G Abodunrin 			new_fltr.flag |= ICE_FLTR_TX;
42785eda8afdSAkeem G Abodunrin 			new_fltr.src = hw_vsi_id;
42795eda8afdSAkeem G Abodunrin 		} else {
42805eda8afdSAkeem G Abodunrin 			new_fltr.flag |= ICE_FLTR_RX;
42815eda8afdSAkeem G Abodunrin 			new_fltr.src = hw->port_info->lport;
42825eda8afdSAkeem G Abodunrin 		}
42835eda8afdSAkeem G Abodunrin 
42845eda8afdSAkeem G Abodunrin 		new_fltr.fltr_act = ICE_FWD_TO_VSI;
42855eda8afdSAkeem G Abodunrin 		new_fltr.vsi_handle = vsi_handle;
42865eda8afdSAkeem G Abodunrin 		new_fltr.fwd_id.hw_vsi_id = hw_vsi_id;
42875eda8afdSAkeem G Abodunrin 		f_list_entry.fltr_info = new_fltr;
42885eda8afdSAkeem G Abodunrin 
42895eda8afdSAkeem G Abodunrin 		status = ice_add_rule_internal(hw, recipe_id, &f_list_entry);
42905eda8afdSAkeem G Abodunrin 		if (status)
42915eda8afdSAkeem G Abodunrin 			goto set_promisc_exit;
42925eda8afdSAkeem G Abodunrin 	}
42935eda8afdSAkeem G Abodunrin 
42945eda8afdSAkeem G Abodunrin set_promisc_exit:
42955eda8afdSAkeem G Abodunrin 	return status;
42965eda8afdSAkeem G Abodunrin }
42975eda8afdSAkeem G Abodunrin 
42985eda8afdSAkeem G Abodunrin /**
42995eda8afdSAkeem G Abodunrin  * ice_set_vlan_vsi_promisc
43005eda8afdSAkeem G Abodunrin  * @hw: pointer to the hardware structure
43015eda8afdSAkeem G Abodunrin  * @vsi_handle: VSI handle to configure
43025eda8afdSAkeem G Abodunrin  * @promisc_mask: mask of promiscuous config bits
43035eda8afdSAkeem G Abodunrin  * @rm_vlan_promisc: Clear VLANs VSI promisc mode
43045eda8afdSAkeem G Abodunrin  *
43055eda8afdSAkeem G Abodunrin  * Configure VSI with all associated VLANs to given promiscuous mode(s)
43065eda8afdSAkeem G Abodunrin  */
43075e24d598STony Nguyen int
ice_set_vlan_vsi_promisc(struct ice_hw * hw,u16 vsi_handle,u8 promisc_mask,bool rm_vlan_promisc)43085eda8afdSAkeem G Abodunrin ice_set_vlan_vsi_promisc(struct ice_hw *hw, u16 vsi_handle, u8 promisc_mask,
43095eda8afdSAkeem G Abodunrin 			 bool rm_vlan_promisc)
43105eda8afdSAkeem G Abodunrin {
43115eda8afdSAkeem G Abodunrin 	struct ice_switch_info *sw = hw->switch_info;
43125eda8afdSAkeem G Abodunrin 	struct ice_fltr_list_entry *list_itr, *tmp;
43135eda8afdSAkeem G Abodunrin 	struct list_head vsi_list_head;
43145eda8afdSAkeem G Abodunrin 	struct list_head *vlan_head;
43155eda8afdSAkeem G Abodunrin 	struct mutex *vlan_lock; /* Lock to protect filter rule list */
43165eda8afdSAkeem G Abodunrin 	u16 vlan_id;
43175518ac2aSTony Nguyen 	int status;
43185eda8afdSAkeem G Abodunrin 
43195eda8afdSAkeem G Abodunrin 	INIT_LIST_HEAD(&vsi_list_head);
43205eda8afdSAkeem G Abodunrin 	vlan_lock = &sw->recp_list[ICE_SW_LKUP_VLAN].filt_rule_lock;
43215eda8afdSAkeem G Abodunrin 	vlan_head = &sw->recp_list[ICE_SW_LKUP_VLAN].filt_rules;
43225eda8afdSAkeem G Abodunrin 	mutex_lock(vlan_lock);
43235eda8afdSAkeem G Abodunrin 	status = ice_add_to_vsi_fltr_list(hw, vsi_handle, vlan_head,
43245eda8afdSAkeem G Abodunrin 					  &vsi_list_head);
43255eda8afdSAkeem G Abodunrin 	mutex_unlock(vlan_lock);
43265eda8afdSAkeem G Abodunrin 	if (status)
43275eda8afdSAkeem G Abodunrin 		goto free_fltr_list;
43285eda8afdSAkeem G Abodunrin 
43295eda8afdSAkeem G Abodunrin 	list_for_each_entry(list_itr, &vsi_list_head, list_entry) {
4330ffa9ed86SGrzegorz Siwik 		/* Avoid enabling or disabling VLAN zero twice when in double
4331ffa9ed86SGrzegorz Siwik 		 * VLAN mode
4332ffa9ed86SGrzegorz Siwik 		 */
4333ffa9ed86SGrzegorz Siwik 		if (ice_is_dvm_ena(hw) &&
4334ffa9ed86SGrzegorz Siwik 		    list_itr->fltr_info.l_data.vlan.tpid == 0)
4335ffa9ed86SGrzegorz Siwik 			continue;
4336ffa9ed86SGrzegorz Siwik 
43375eda8afdSAkeem G Abodunrin 		vlan_id = list_itr->fltr_info.l_data.vlan.vlan_id;
43385eda8afdSAkeem G Abodunrin 		if (rm_vlan_promisc)
43395eda8afdSAkeem G Abodunrin 			status = ice_clear_vsi_promisc(hw, vsi_handle,
43405eda8afdSAkeem G Abodunrin 						       promisc_mask, vlan_id);
43415eda8afdSAkeem G Abodunrin 		else
43425eda8afdSAkeem G Abodunrin 			status = ice_set_vsi_promisc(hw, vsi_handle,
43435eda8afdSAkeem G Abodunrin 						     promisc_mask, vlan_id);
434411e551a2SGrzegorz Siwik 		if (status && status != -EEXIST)
43455eda8afdSAkeem G Abodunrin 			break;
43465eda8afdSAkeem G Abodunrin 	}
43475eda8afdSAkeem G Abodunrin 
43485eda8afdSAkeem G Abodunrin free_fltr_list:
43495eda8afdSAkeem G Abodunrin 	list_for_each_entry_safe(list_itr, tmp, &vsi_list_head, list_entry) {
43505eda8afdSAkeem G Abodunrin 		list_del(&list_itr->list_entry);
43515eda8afdSAkeem G Abodunrin 		devm_kfree(ice_hw_to_dev(hw), list_itr);
43525eda8afdSAkeem G Abodunrin 	}
43535eda8afdSAkeem G Abodunrin 	return status;
43545eda8afdSAkeem G Abodunrin }
43555eda8afdSAkeem G Abodunrin 
43565eda8afdSAkeem G Abodunrin /**
43579daf8208SAnirudh Venkataramanan  * ice_remove_vsi_lkup_fltr - Remove lookup type filters for a VSI
43589daf8208SAnirudh Venkataramanan  * @hw: pointer to the hardware structure
43595726ca0eSAnirudh Venkataramanan  * @vsi_handle: VSI handle to remove filters from
43609daf8208SAnirudh Venkataramanan  * @lkup: switch rule filter lookup type
43619daf8208SAnirudh Venkataramanan  */
43629daf8208SAnirudh Venkataramanan static void
ice_remove_vsi_lkup_fltr(struct ice_hw * hw,u16 vsi_handle,enum ice_sw_lkup_type lkup)43635726ca0eSAnirudh Venkataramanan ice_remove_vsi_lkup_fltr(struct ice_hw *hw, u16 vsi_handle,
43649daf8208SAnirudh Venkataramanan 			 enum ice_sw_lkup_type lkup)
43659daf8208SAnirudh Venkataramanan {
43669daf8208SAnirudh Venkataramanan 	struct ice_switch_info *sw = hw->switch_info;
43679daf8208SAnirudh Venkataramanan 	struct ice_fltr_list_entry *fm_entry;
43689daf8208SAnirudh Venkataramanan 	struct list_head remove_list_head;
436980d144c9SAnirudh Venkataramanan 	struct list_head *rule_head;
43709daf8208SAnirudh Venkataramanan 	struct ice_fltr_list_entry *tmp;
437180d144c9SAnirudh Venkataramanan 	struct mutex *rule_lock;	/* Lock to protect filter rule list */
43725e24d598STony Nguyen 	int status;
43739daf8208SAnirudh Venkataramanan 
43749daf8208SAnirudh Venkataramanan 	INIT_LIST_HEAD(&remove_list_head);
437580d144c9SAnirudh Venkataramanan 	rule_lock = &sw->recp_list[lkup].filt_rule_lock;
437680d144c9SAnirudh Venkataramanan 	rule_head = &sw->recp_list[lkup].filt_rules;
437780d144c9SAnirudh Venkataramanan 	mutex_lock(rule_lock);
43785726ca0eSAnirudh Venkataramanan 	status = ice_add_to_vsi_fltr_list(hw, vsi_handle, rule_head,
437980d144c9SAnirudh Venkataramanan 					  &remove_list_head);
438080d144c9SAnirudh Venkataramanan 	mutex_unlock(rule_lock);
438180d144c9SAnirudh Venkataramanan 	if (status)
4382b7eeb527SRobert Malz 		goto free_fltr_list;
438380d144c9SAnirudh Venkataramanan 
43849daf8208SAnirudh Venkataramanan 	switch (lkup) {
43859daf8208SAnirudh Venkataramanan 	case ICE_SW_LKUP_MAC:
43869daf8208SAnirudh Venkataramanan 		ice_remove_mac(hw, &remove_list_head);
43879daf8208SAnirudh Venkataramanan 		break;
43889daf8208SAnirudh Venkataramanan 	case ICE_SW_LKUP_VLAN:
4389d76a60baSAnirudh Venkataramanan 		ice_remove_vlan(hw, &remove_list_head);
4390d76a60baSAnirudh Venkataramanan 		break;
43915eda8afdSAkeem G Abodunrin 	case ICE_SW_LKUP_PROMISC:
43925eda8afdSAkeem G Abodunrin 	case ICE_SW_LKUP_PROMISC_VLAN:
43935eda8afdSAkeem G Abodunrin 		ice_remove_promisc(hw, lkup, &remove_list_head);
43945eda8afdSAkeem G Abodunrin 		break;
43959daf8208SAnirudh Venkataramanan 	case ICE_SW_LKUP_MAC_VLAN:
43969daf8208SAnirudh Venkataramanan 	case ICE_SW_LKUP_ETHERTYPE:
43979daf8208SAnirudh Venkataramanan 	case ICE_SW_LKUP_ETHERTYPE_MAC:
43989daf8208SAnirudh Venkataramanan 	case ICE_SW_LKUP_DFLT:
439980d144c9SAnirudh Venkataramanan 	case ICE_SW_LKUP_LAST:
440080d144c9SAnirudh Venkataramanan 	default:
440180d144c9SAnirudh Venkataramanan 		ice_debug(hw, ICE_DBG_SW, "Unsupported lookup type %d\n", lkup);
44029daf8208SAnirudh Venkataramanan 		break;
44039daf8208SAnirudh Venkataramanan 	}
44049daf8208SAnirudh Venkataramanan 
4405b7eeb527SRobert Malz free_fltr_list:
44069daf8208SAnirudh Venkataramanan 	list_for_each_entry_safe(fm_entry, tmp, &remove_list_head, list_entry) {
44079daf8208SAnirudh Venkataramanan 		list_del(&fm_entry->list_entry);
44089daf8208SAnirudh Venkataramanan 		devm_kfree(ice_hw_to_dev(hw), fm_entry);
44099daf8208SAnirudh Venkataramanan 	}
44109daf8208SAnirudh Venkataramanan }
44119daf8208SAnirudh Venkataramanan 
44129daf8208SAnirudh Venkataramanan /**
44139daf8208SAnirudh Venkataramanan  * ice_remove_vsi_fltr - Remove all filters for a VSI
44149daf8208SAnirudh Venkataramanan  * @hw: pointer to the hardware structure
44155726ca0eSAnirudh Venkataramanan  * @vsi_handle: VSI handle to remove filters from
44169daf8208SAnirudh Venkataramanan  */
ice_remove_vsi_fltr(struct ice_hw * hw,u16 vsi_handle)44175726ca0eSAnirudh Venkataramanan void ice_remove_vsi_fltr(struct ice_hw *hw, u16 vsi_handle)
44189daf8208SAnirudh Venkataramanan {
44195726ca0eSAnirudh Venkataramanan 	ice_remove_vsi_lkup_fltr(hw, vsi_handle, ICE_SW_LKUP_MAC);
44205726ca0eSAnirudh Venkataramanan 	ice_remove_vsi_lkup_fltr(hw, vsi_handle, ICE_SW_LKUP_MAC_VLAN);
44215726ca0eSAnirudh Venkataramanan 	ice_remove_vsi_lkup_fltr(hw, vsi_handle, ICE_SW_LKUP_PROMISC);
44225726ca0eSAnirudh Venkataramanan 	ice_remove_vsi_lkup_fltr(hw, vsi_handle, ICE_SW_LKUP_VLAN);
44235726ca0eSAnirudh Venkataramanan 	ice_remove_vsi_lkup_fltr(hw, vsi_handle, ICE_SW_LKUP_DFLT);
44245726ca0eSAnirudh Venkataramanan 	ice_remove_vsi_lkup_fltr(hw, vsi_handle, ICE_SW_LKUP_ETHERTYPE);
44255726ca0eSAnirudh Venkataramanan 	ice_remove_vsi_lkup_fltr(hw, vsi_handle, ICE_SW_LKUP_ETHERTYPE_MAC);
44265726ca0eSAnirudh Venkataramanan 	ice_remove_vsi_lkup_fltr(hw, vsi_handle, ICE_SW_LKUP_PROMISC_VLAN);
44279daf8208SAnirudh Venkataramanan }
44280f9d5027SAnirudh Venkataramanan 
44290f9d5027SAnirudh Venkataramanan /**
4430148beb61SHenry Tieman  * ice_alloc_res_cntr - allocating resource counter
4431148beb61SHenry Tieman  * @hw: pointer to the hardware structure
4432148beb61SHenry Tieman  * @type: type of resource
4433148beb61SHenry Tieman  * @alloc_shared: if set it is shared else dedicated
4434148beb61SHenry Tieman  * @num_items: number of entries requested for FD resource type
4435148beb61SHenry Tieman  * @counter_id: counter index returned by AQ call
4436148beb61SHenry Tieman  */
44375e24d598STony Nguyen int
ice_alloc_res_cntr(struct ice_hw * hw,u8 type,u8 alloc_shared,u16 num_items,u16 * counter_id)4438148beb61SHenry Tieman ice_alloc_res_cntr(struct ice_hw *hw, u8 type, u8 alloc_shared, u16 num_items,
4439148beb61SHenry Tieman 		   u16 *counter_id)
4440148beb61SHenry Tieman {
4441148beb61SHenry Tieman 	struct ice_aqc_alloc_free_res_elem *buf;
4442148beb61SHenry Tieman 	u16 buf_len;
44435518ac2aSTony Nguyen 	int status;
4444148beb61SHenry Tieman 
4445148beb61SHenry Tieman 	/* Allocate resource */
444666486d89SBruce Allan 	buf_len = struct_size(buf, elem, 1);
4447148beb61SHenry Tieman 	buf = kzalloc(buf_len, GFP_KERNEL);
4448148beb61SHenry Tieman 	if (!buf)
4449d54699e2STony Nguyen 		return -ENOMEM;
4450148beb61SHenry Tieman 
4451148beb61SHenry Tieman 	buf->num_elems = cpu_to_le16(num_items);
4452148beb61SHenry Tieman 	buf->res_type = cpu_to_le16(((type << ICE_AQC_RES_TYPE_S) &
4453148beb61SHenry Tieman 				      ICE_AQC_RES_TYPE_M) | alloc_shared);
4454148beb61SHenry Tieman 
445552da2fb2SPrzemek Kitszel 	status = ice_aq_alloc_free_res(hw, buf, buf_len, ice_aqc_opc_alloc_res);
4456148beb61SHenry Tieman 	if (status)
4457148beb61SHenry Tieman 		goto exit;
4458148beb61SHenry Tieman 
4459148beb61SHenry Tieman 	*counter_id = le16_to_cpu(buf->elem[0].e.sw_resp);
4460148beb61SHenry Tieman 
4461148beb61SHenry Tieman exit:
4462148beb61SHenry Tieman 	kfree(buf);
4463148beb61SHenry Tieman 	return status;
4464148beb61SHenry Tieman }
4465148beb61SHenry Tieman 
4466148beb61SHenry Tieman /**
4467148beb61SHenry Tieman  * ice_free_res_cntr - free resource counter
4468148beb61SHenry Tieman  * @hw: pointer to the hardware structure
4469148beb61SHenry Tieman  * @type: type of resource
4470148beb61SHenry Tieman  * @alloc_shared: if set it is shared else dedicated
4471148beb61SHenry Tieman  * @num_items: number of entries to be freed for FD resource type
4472148beb61SHenry Tieman  * @counter_id: counter ID resource which needs to be freed
4473148beb61SHenry Tieman  */
44745e24d598STony Nguyen int
ice_free_res_cntr(struct ice_hw * hw,u8 type,u8 alloc_shared,u16 num_items,u16 counter_id)4475148beb61SHenry Tieman ice_free_res_cntr(struct ice_hw *hw, u8 type, u8 alloc_shared, u16 num_items,
4476148beb61SHenry Tieman 		  u16 counter_id)
4477148beb61SHenry Tieman {
4478148beb61SHenry Tieman 	struct ice_aqc_alloc_free_res_elem *buf;
4479148beb61SHenry Tieman 	u16 buf_len;
44805518ac2aSTony Nguyen 	int status;
4481148beb61SHenry Tieman 
4482148beb61SHenry Tieman 	/* Free resource */
448366486d89SBruce Allan 	buf_len = struct_size(buf, elem, 1);
4484148beb61SHenry Tieman 	buf = kzalloc(buf_len, GFP_KERNEL);
4485148beb61SHenry Tieman 	if (!buf)
4486d54699e2STony Nguyen 		return -ENOMEM;
4487148beb61SHenry Tieman 
4488148beb61SHenry Tieman 	buf->num_elems = cpu_to_le16(num_items);
4489148beb61SHenry Tieman 	buf->res_type = cpu_to_le16(((type << ICE_AQC_RES_TYPE_S) &
4490148beb61SHenry Tieman 				      ICE_AQC_RES_TYPE_M) | alloc_shared);
4491148beb61SHenry Tieman 	buf->elem[0].e.sw_resp = cpu_to_le16(counter_id);
4492148beb61SHenry Tieman 
449352da2fb2SPrzemek Kitszel 	status = ice_aq_alloc_free_res(hw, buf, buf_len, ice_aqc_opc_free_res);
4494148beb61SHenry Tieman 	if (status)
44959228d8b2SJacob Keller 		ice_debug(hw, ICE_DBG_SW, "counter resource could not be freed\n");
4496148beb61SHenry Tieman 
4497148beb61SHenry Tieman 	kfree(buf);
4498148beb61SHenry Tieman 	return status;
4499148beb61SHenry Tieman }
4500148beb61SHenry Tieman 
450117c6d835SMichal Swiatkowski #define ICE_PROTOCOL_ENTRY(id, ...) {		\
450217c6d835SMichal Swiatkowski 	.prot_type	= id,			\
450317c6d835SMichal Swiatkowski 	.offs		= {__VA_ARGS__},	\
450417c6d835SMichal Swiatkowski }
450517c6d835SMichal Swiatkowski 
450623ccae5cSDave Ertman /**
450723ccae5cSDave Ertman  * ice_share_res - set a resource as shared or dedicated
450823ccae5cSDave Ertman  * @hw: hw struct of original owner of resource
450923ccae5cSDave Ertman  * @type: resource type
451023ccae5cSDave Ertman  * @shared: is the resource being set to shared
451123ccae5cSDave Ertman  * @res_id: resource id (descriptor)
451223ccae5cSDave Ertman  */
ice_share_res(struct ice_hw * hw,u16 type,u8 shared,u16 res_id)451323ccae5cSDave Ertman int ice_share_res(struct ice_hw *hw, u16 type, u8 shared, u16 res_id)
451423ccae5cSDave Ertman {
451523ccae5cSDave Ertman 	struct ice_aqc_alloc_free_res_elem *buf;
451623ccae5cSDave Ertman 	u16 buf_len;
451723ccae5cSDave Ertman 	int status;
451823ccae5cSDave Ertman 
451923ccae5cSDave Ertman 	buf_len = struct_size(buf, elem, 1);
452023ccae5cSDave Ertman 	buf = kzalloc(buf_len, GFP_KERNEL);
452123ccae5cSDave Ertman 	if (!buf)
452223ccae5cSDave Ertman 		return -ENOMEM;
452323ccae5cSDave Ertman 
452423ccae5cSDave Ertman 	buf->num_elems = cpu_to_le16(1);
452523ccae5cSDave Ertman 	if (shared)
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 	else
453023ccae5cSDave Ertman 		buf->res_type = cpu_to_le16(((type << ICE_AQC_RES_TYPE_S) &
453123ccae5cSDave Ertman 					     ICE_AQC_RES_TYPE_M) &
453223ccae5cSDave Ertman 					    ~ICE_AQC_RES_TYPE_FLAG_SHARED);
453323ccae5cSDave Ertman 
453423ccae5cSDave Ertman 	buf->elem[0].e.sw_resp = cpu_to_le16(res_id);
453552da2fb2SPrzemek Kitszel 	status = ice_aq_alloc_free_res(hw, buf, buf_len,
453652da2fb2SPrzemek Kitszel 				       ice_aqc_opc_share_res);
453723ccae5cSDave Ertman 	if (status)
453823ccae5cSDave Ertman 		ice_debug(hw, ICE_DBG_SW, "Could not set resource type %u id %u to %s\n",
453923ccae5cSDave Ertman 			  type, res_id, shared ? "SHARED" : "DEDICATED");
454023ccae5cSDave Ertman 
454123ccae5cSDave Ertman 	kfree(buf);
454223ccae5cSDave Ertman 	return status;
454323ccae5cSDave Ertman }
454423ccae5cSDave Ertman 
4545fd2a6b71SDan Nowlin /* This is mapping table entry that maps every word within a given protocol
4546fd2a6b71SDan Nowlin  * structure to the real byte offset as per the specification of that
4547fd2a6b71SDan Nowlin  * protocol header.
4548fd2a6b71SDan Nowlin  * for example dst address is 3 words in ethertype header and corresponding
4549fd2a6b71SDan Nowlin  * bytes are 0, 2, 3 in the actual packet header and src address is at 4, 6, 8
4550fd2a6b71SDan Nowlin  * IMPORTANT: Every structure part of "ice_prot_hdr" union should have a
4551fd2a6b71SDan Nowlin  * matching entry describing its field. This needs to be updated if new
4552fd2a6b71SDan Nowlin  * structure is added to that union.
4553fd2a6b71SDan Nowlin  */
4554fd2a6b71SDan Nowlin static const struct ice_prot_ext_tbl_entry ice_prot_ext[ICE_PROTOCOL_LAST] = {
455517c6d835SMichal Swiatkowski 	ICE_PROTOCOL_ENTRY(ICE_MAC_OFOS, 0, 2, 4, 6, 8, 10, 12),
455617c6d835SMichal Swiatkowski 	ICE_PROTOCOL_ENTRY(ICE_MAC_IL, 0, 2, 4, 6, 8, 10, 12),
455717c6d835SMichal Swiatkowski 	ICE_PROTOCOL_ENTRY(ICE_ETYPE_OL, 0),
455817c6d835SMichal Swiatkowski 	ICE_PROTOCOL_ENTRY(ICE_ETYPE_IL, 0),
455917c6d835SMichal Swiatkowski 	ICE_PROTOCOL_ENTRY(ICE_VLAN_OFOS, 2, 0),
456017c6d835SMichal Swiatkowski 	ICE_PROTOCOL_ENTRY(ICE_IPV4_OFOS, 0, 2, 4, 6, 8, 10, 12, 14, 16, 18),
456117c6d835SMichal Swiatkowski 	ICE_PROTOCOL_ENTRY(ICE_IPV4_IL,	0, 2, 4, 6, 8, 10, 12, 14, 16, 18),
456217c6d835SMichal Swiatkowski 	ICE_PROTOCOL_ENTRY(ICE_IPV6_OFOS, 0, 2, 4, 6, 8, 10, 12, 14, 16, 18,
456317c6d835SMichal Swiatkowski 			   20, 22, 24, 26, 28, 30, 32, 34, 36, 38),
456417c6d835SMichal Swiatkowski 	ICE_PROTOCOL_ENTRY(ICE_IPV6_IL, 0, 2, 4, 6, 8, 10, 12, 14, 16, 18, 20,
456517c6d835SMichal Swiatkowski 			   22, 24, 26, 28, 30, 32, 34, 36, 38),
456617c6d835SMichal Swiatkowski 	ICE_PROTOCOL_ENTRY(ICE_TCP_IL, 0, 2),
456717c6d835SMichal Swiatkowski 	ICE_PROTOCOL_ENTRY(ICE_UDP_OF, 0, 2),
456817c6d835SMichal Swiatkowski 	ICE_PROTOCOL_ENTRY(ICE_UDP_ILOS, 0, 2),
456917c6d835SMichal Swiatkowski 	ICE_PROTOCOL_ENTRY(ICE_VXLAN, 8, 10, 12, 14),
457017c6d835SMichal Swiatkowski 	ICE_PROTOCOL_ENTRY(ICE_GENEVE, 8, 10, 12, 14),
457117c6d835SMichal Swiatkowski 	ICE_PROTOCOL_ENTRY(ICE_NVGRE, 0, 2, 4, 6),
457217c6d835SMichal Swiatkowski 	ICE_PROTOCOL_ENTRY(ICE_GTP, 8, 10, 12, 14, 16, 18, 20, 22),
457317c6d835SMichal Swiatkowski 	ICE_PROTOCOL_ENTRY(ICE_GTP_NO_PAY, 8, 10, 12, 14),
457417c6d835SMichal Swiatkowski 	ICE_PROTOCOL_ENTRY(ICE_PPPOE, 0, 2, 4, 6),
457517c6d835SMichal Swiatkowski 	ICE_PROTOCOL_ENTRY(ICE_L2TPV3, 0, 2, 4, 6, 8, 10),
457617c6d835SMichal Swiatkowski 	ICE_PROTOCOL_ENTRY(ICE_VLAN_EX, 2, 0),
457717c6d835SMichal Swiatkowski 	ICE_PROTOCOL_ENTRY(ICE_VLAN_IN, 2, 0),
457803592a14SMichal Swiatkowski 	ICE_PROTOCOL_ENTRY(ICE_HW_METADATA,
457903592a14SMichal Swiatkowski 			   ICE_SOURCE_PORT_MDID_OFFSET,
458003592a14SMichal Swiatkowski 			   ICE_PTYPE_MDID_OFFSET,
458103592a14SMichal Swiatkowski 			   ICE_PACKET_LENGTH_MDID_OFFSET,
458203592a14SMichal Swiatkowski 			   ICE_SOURCE_VSI_MDID_OFFSET,
458303592a14SMichal Swiatkowski 			   ICE_PKT_VLAN_MDID_OFFSET,
458403592a14SMichal Swiatkowski 			   ICE_PKT_TUNNEL_MDID_OFFSET,
458503592a14SMichal Swiatkowski 			   ICE_PKT_TCP_MDID_OFFSET,
458603592a14SMichal Swiatkowski 			   ICE_PKT_ERROR_MDID_OFFSET),
4587fd2a6b71SDan Nowlin };
4588fd2a6b71SDan Nowlin 
4589fd2a6b71SDan Nowlin static struct ice_protocol_entry ice_prot_id_tbl[ICE_PROTOCOL_LAST] = {
4590fd2a6b71SDan Nowlin 	{ ICE_MAC_OFOS,		ICE_MAC_OFOS_HW },
4591fd2a6b71SDan Nowlin 	{ ICE_MAC_IL,		ICE_MAC_IL_HW },
4592fd2a6b71SDan Nowlin 	{ ICE_ETYPE_OL,		ICE_ETYPE_OL_HW },
459334a89775SMartyna Szapar-Mudlaw 	{ ICE_ETYPE_IL,		ICE_ETYPE_IL_HW },
4594fd2a6b71SDan Nowlin 	{ ICE_VLAN_OFOS,	ICE_VLAN_OL_HW },
4595fd2a6b71SDan Nowlin 	{ ICE_IPV4_OFOS,	ICE_IPV4_OFOS_HW },
4596fd2a6b71SDan Nowlin 	{ ICE_IPV4_IL,		ICE_IPV4_IL_HW },
4597fd2a6b71SDan Nowlin 	{ ICE_IPV6_OFOS,	ICE_IPV6_OFOS_HW },
4598fd2a6b71SDan Nowlin 	{ ICE_IPV6_IL,		ICE_IPV6_IL_HW },
4599fd2a6b71SDan Nowlin 	{ ICE_TCP_IL,		ICE_TCP_IL_HW },
4600fd2a6b71SDan Nowlin 	{ ICE_UDP_OF,		ICE_UDP_OF_HW },
4601fd2a6b71SDan Nowlin 	{ ICE_UDP_ILOS,		ICE_UDP_ILOS_HW },
46028b032a55SMichal Swiatkowski 	{ ICE_VXLAN,		ICE_UDP_OF_HW },
46038b032a55SMichal Swiatkowski 	{ ICE_GENEVE,		ICE_UDP_OF_HW },
4604f0a35040SMichal Swiatkowski 	{ ICE_NVGRE,		ICE_GRE_OF_HW },
46059a225f81SMarcin Szycik 	{ ICE_GTP,		ICE_UDP_OF_HW },
46069a225f81SMarcin Szycik 	{ ICE_GTP_NO_PAY,	ICE_UDP_ILOS_HW },
4607cd8efeeeSMarcin Szycik 	{ ICE_PPPOE,		ICE_PPPOE_HW },
4608cd634549SMarcin Szycik 	{ ICE_L2TPV3,		ICE_L2TPV3_HW },
460906bca7c2SMartyna Szapar-Mudlaw 	{ ICE_VLAN_EX,          ICE_VLAN_OF_HW },
461006bca7c2SMartyna Szapar-Mudlaw 	{ ICE_VLAN_IN,          ICE_VLAN_OL_HW },
461103592a14SMichal Swiatkowski 	{ ICE_HW_METADATA,      ICE_META_DATA_ID_HW },
4612fd2a6b71SDan Nowlin };
4613fd2a6b71SDan Nowlin 
4614fd2a6b71SDan Nowlin /**
4615fd2a6b71SDan Nowlin  * ice_find_recp - find a recipe
4616fd2a6b71SDan Nowlin  * @hw: pointer to the hardware structure
4617fd2a6b71SDan Nowlin  * @lkup_exts: extension sequence to match
4618bccd9bceSMarcin Szycik  * @rinfo: information regarding the rule e.g. priority and action info
4619fd2a6b71SDan Nowlin  *
4620fd2a6b71SDan Nowlin  * Returns index of matching recipe, or ICE_MAX_NUM_RECIPES if not found.
4621fd2a6b71SDan Nowlin  */
4622de6acd1cSMichal Swiatkowski static u16
ice_find_recp(struct ice_hw * hw,struct ice_prot_lkup_ext * lkup_exts,const struct ice_adv_rule_info * rinfo)4623de6acd1cSMichal Swiatkowski ice_find_recp(struct ice_hw *hw, struct ice_prot_lkup_ext *lkup_exts,
4624bccd9bceSMarcin Szycik 	      const struct ice_adv_rule_info *rinfo)
4625fd2a6b71SDan Nowlin {
4626fd2a6b71SDan Nowlin 	bool refresh_required = true;
4627fd2a6b71SDan Nowlin 	struct ice_sw_recipe *recp;
4628fd2a6b71SDan Nowlin 	u8 i;
4629fd2a6b71SDan Nowlin 
4630fd2a6b71SDan Nowlin 	/* Walk through existing recipes to find a match */
4631fd2a6b71SDan Nowlin 	recp = hw->switch_info->recp_list;
4632fd2a6b71SDan Nowlin 	for (i = 0; i < ICE_MAX_NUM_RECIPES; i++) {
4633fd2a6b71SDan Nowlin 		/* If recipe was not created for this ID, in SW bookkeeping,
4634fd2a6b71SDan Nowlin 		 * check if FW has an entry for this recipe. If the FW has an
4635fd2a6b71SDan Nowlin 		 * entry update it in our SW bookkeeping and continue with the
4636fd2a6b71SDan Nowlin 		 * matching.
4637fd2a6b71SDan Nowlin 		 */
4638fd2a6b71SDan Nowlin 		if (!recp[i].recp_created)
4639fd2a6b71SDan Nowlin 			if (ice_get_recp_frm_fw(hw,
4640fd2a6b71SDan Nowlin 						hw->switch_info->recp_list, i,
4641fd2a6b71SDan Nowlin 						&refresh_required))
4642fd2a6b71SDan Nowlin 				continue;
4643fd2a6b71SDan Nowlin 
4644fd2a6b71SDan Nowlin 		/* Skip inverse action recipes */
4645fd2a6b71SDan Nowlin 		if (recp[i].root_buf && recp[i].root_buf->content.act_ctrl &
4646fd2a6b71SDan Nowlin 		    ICE_AQ_RECIPE_ACT_INV_ACT)
4647fd2a6b71SDan Nowlin 			continue;
4648fd2a6b71SDan Nowlin 
4649fd2a6b71SDan Nowlin 		/* if number of words we are looking for match */
4650fd2a6b71SDan Nowlin 		if (lkup_exts->n_val_words == recp[i].lkup_exts.n_val_words) {
4651fd2a6b71SDan Nowlin 			struct ice_fv_word *ar = recp[i].lkup_exts.fv_words;
4652fd2a6b71SDan Nowlin 			struct ice_fv_word *be = lkup_exts->fv_words;
4653fd2a6b71SDan Nowlin 			u16 *cr = recp[i].lkup_exts.field_mask;
4654fd2a6b71SDan Nowlin 			u16 *de = lkup_exts->field_mask;
4655fd2a6b71SDan Nowlin 			bool found = true;
4656fd2a6b71SDan Nowlin 			u8 pe, qr;
4657fd2a6b71SDan Nowlin 
4658fd2a6b71SDan Nowlin 			/* ar, cr, and qr are related to the recipe words, while
4659fd2a6b71SDan Nowlin 			 * be, de, and pe are related to the lookup words
4660fd2a6b71SDan Nowlin 			 */
4661fd2a6b71SDan Nowlin 			for (pe = 0; pe < lkup_exts->n_val_words; pe++) {
4662fd2a6b71SDan Nowlin 				for (qr = 0; qr < recp[i].lkup_exts.n_val_words;
4663fd2a6b71SDan Nowlin 				     qr++) {
4664fd2a6b71SDan Nowlin 					if (ar[qr].off == be[pe].off &&
4665fd2a6b71SDan Nowlin 					    ar[qr].prot_id == be[pe].prot_id &&
4666fd2a6b71SDan Nowlin 					    cr[qr] == de[pe])
4667fd2a6b71SDan Nowlin 						/* Found the "pe"th word in the
4668fd2a6b71SDan Nowlin 						 * given recipe
4669fd2a6b71SDan Nowlin 						 */
4670fd2a6b71SDan Nowlin 						break;
4671fd2a6b71SDan Nowlin 				}
4672fd2a6b71SDan Nowlin 				/* After walking through all the words in the
4673fd2a6b71SDan Nowlin 				 * "i"th recipe if "p"th word was not found then
4674fd2a6b71SDan Nowlin 				 * this recipe is not what we are looking for.
4675fd2a6b71SDan Nowlin 				 * So break out from this loop and try the next
4676fd2a6b71SDan Nowlin 				 * recipe
4677fd2a6b71SDan Nowlin 				 */
4678fd2a6b71SDan Nowlin 				if (qr >= recp[i].lkup_exts.n_val_words) {
4679fd2a6b71SDan Nowlin 					found = false;
4680fd2a6b71SDan Nowlin 					break;
4681fd2a6b71SDan Nowlin 				}
4682fd2a6b71SDan Nowlin 			}
4683fd2a6b71SDan Nowlin 			/* If for "i"th recipe the found was never set to false
4684fd2a6b71SDan Nowlin 			 * then it means we found our match
4685bccd9bceSMarcin Szycik 			 * Also tun type and *_pass_l2 of recipe needs to be
4686bccd9bceSMarcin Szycik 			 * checked
4687fd2a6b71SDan Nowlin 			 */
4688bccd9bceSMarcin Szycik 			if (found && recp[i].tun_type == rinfo->tun_type &&
4689bccd9bceSMarcin Szycik 			    recp[i].need_pass_l2 == rinfo->need_pass_l2 &&
4690bccd9bceSMarcin Szycik 			    recp[i].allow_pass_l2 == rinfo->allow_pass_l2)
4691fd2a6b71SDan Nowlin 				return i; /* Return the recipe ID */
4692fd2a6b71SDan Nowlin 		}
4693fd2a6b71SDan Nowlin 	}
4694fd2a6b71SDan Nowlin 	return ICE_MAX_NUM_RECIPES;
4695fd2a6b71SDan Nowlin }
4696fd2a6b71SDan Nowlin 
4697fd2a6b71SDan Nowlin /**
4698a1ffafb0SBrett Creeley  * ice_change_proto_id_to_dvm - change proto id in prot_id_tbl
4699a1ffafb0SBrett Creeley  *
4700a1ffafb0SBrett Creeley  * As protocol id for outer vlan is different in dvm and svm, if dvm is
4701a1ffafb0SBrett Creeley  * supported protocol array record for outer vlan has to be modified to
4702a1ffafb0SBrett Creeley  * reflect the value proper for DVM.
4703a1ffafb0SBrett Creeley  */
ice_change_proto_id_to_dvm(void)4704a1ffafb0SBrett Creeley void ice_change_proto_id_to_dvm(void)
4705a1ffafb0SBrett Creeley {
4706a1ffafb0SBrett Creeley 	u8 i;
4707a1ffafb0SBrett Creeley 
4708a1ffafb0SBrett Creeley 	for (i = 0; i < ARRAY_SIZE(ice_prot_id_tbl); i++)
4709a1ffafb0SBrett Creeley 		if (ice_prot_id_tbl[i].type == ICE_VLAN_OFOS &&
4710a1ffafb0SBrett Creeley 		    ice_prot_id_tbl[i].protocol_id != ICE_VLAN_OF_HW)
4711a1ffafb0SBrett Creeley 			ice_prot_id_tbl[i].protocol_id = ICE_VLAN_OF_HW;
4712a1ffafb0SBrett Creeley }
4713a1ffafb0SBrett Creeley 
4714a1ffafb0SBrett Creeley /**
4715fd2a6b71SDan Nowlin  * ice_prot_type_to_id - get protocol ID from protocol type
4716fd2a6b71SDan Nowlin  * @type: protocol type
4717fd2a6b71SDan Nowlin  * @id: pointer to variable that will receive the ID
4718fd2a6b71SDan Nowlin  *
4719fd2a6b71SDan Nowlin  * Returns true if found, false otherwise
4720fd2a6b71SDan Nowlin  */
ice_prot_type_to_id(enum ice_protocol_type type,u8 * id)4721fd2a6b71SDan Nowlin static bool ice_prot_type_to_id(enum ice_protocol_type type, u8 *id)
4722fd2a6b71SDan Nowlin {
4723fd2a6b71SDan Nowlin 	u8 i;
4724fd2a6b71SDan Nowlin 
4725fd2a6b71SDan Nowlin 	for (i = 0; i < ARRAY_SIZE(ice_prot_id_tbl); i++)
4726fd2a6b71SDan Nowlin 		if (ice_prot_id_tbl[i].type == type) {
4727fd2a6b71SDan Nowlin 			*id = ice_prot_id_tbl[i].protocol_id;
4728fd2a6b71SDan Nowlin 			return true;
4729fd2a6b71SDan Nowlin 		}
4730fd2a6b71SDan Nowlin 	return false;
4731fd2a6b71SDan Nowlin }
4732fd2a6b71SDan Nowlin 
4733fd2a6b71SDan Nowlin /**
4734fd2a6b71SDan Nowlin  * ice_fill_valid_words - count valid words
4735fd2a6b71SDan Nowlin  * @rule: advanced rule with lookup information
4736fd2a6b71SDan Nowlin  * @lkup_exts: byte offset extractions of the words that are valid
4737fd2a6b71SDan Nowlin  *
4738fd2a6b71SDan Nowlin  * calculate valid words in a lookup rule using mask value
4739fd2a6b71SDan Nowlin  */
4740fd2a6b71SDan Nowlin static u8
ice_fill_valid_words(struct ice_adv_lkup_elem * rule,struct ice_prot_lkup_ext * lkup_exts)4741fd2a6b71SDan Nowlin ice_fill_valid_words(struct ice_adv_lkup_elem *rule,
4742fd2a6b71SDan Nowlin 		     struct ice_prot_lkup_ext *lkup_exts)
4743fd2a6b71SDan Nowlin {
4744fd2a6b71SDan Nowlin 	u8 j, word, prot_id, ret_val;
4745fd2a6b71SDan Nowlin 
4746fd2a6b71SDan Nowlin 	if (!ice_prot_type_to_id(rule->type, &prot_id))
4747fd2a6b71SDan Nowlin 		return 0;
4748fd2a6b71SDan Nowlin 
4749fd2a6b71SDan Nowlin 	word = lkup_exts->n_val_words;
4750fd2a6b71SDan Nowlin 
4751fd2a6b71SDan Nowlin 	for (j = 0; j < sizeof(rule->m_u) / sizeof(u16); j++)
4752fd2a6b71SDan Nowlin 		if (((u16 *)&rule->m_u)[j] &&
4753fd2a6b71SDan Nowlin 		    rule->type < ARRAY_SIZE(ice_prot_ext)) {
4754fd2a6b71SDan Nowlin 			/* No more space to accommodate */
4755fd2a6b71SDan Nowlin 			if (word >= ICE_MAX_CHAIN_WORDS)
4756fd2a6b71SDan Nowlin 				return 0;
4757fd2a6b71SDan Nowlin 			lkup_exts->fv_words[word].off =
4758fd2a6b71SDan Nowlin 				ice_prot_ext[rule->type].offs[j];
4759fd2a6b71SDan Nowlin 			lkup_exts->fv_words[word].prot_id =
4760fd2a6b71SDan Nowlin 				ice_prot_id_tbl[rule->type].protocol_id;
4761fd2a6b71SDan Nowlin 			lkup_exts->field_mask[word] =
4762fd2a6b71SDan Nowlin 				be16_to_cpu(((__force __be16 *)&rule->m_u)[j]);
4763fd2a6b71SDan Nowlin 			word++;
4764fd2a6b71SDan Nowlin 		}
4765fd2a6b71SDan Nowlin 
4766fd2a6b71SDan Nowlin 	ret_val = word - lkup_exts->n_val_words;
4767fd2a6b71SDan Nowlin 	lkup_exts->n_val_words = word;
4768fd2a6b71SDan Nowlin 
4769fd2a6b71SDan Nowlin 	return ret_val;
4770fd2a6b71SDan Nowlin }
4771fd2a6b71SDan Nowlin 
4772fd2a6b71SDan Nowlin /**
4773fd2a6b71SDan Nowlin  * ice_create_first_fit_recp_def - Create a recipe grouping
4774fd2a6b71SDan Nowlin  * @hw: pointer to the hardware structure
4775fd2a6b71SDan Nowlin  * @lkup_exts: an array of protocol header extractions
4776fd2a6b71SDan Nowlin  * @rg_list: pointer to a list that stores new recipe groups
4777fd2a6b71SDan Nowlin  * @recp_cnt: pointer to a variable that stores returned number of recipe groups
4778fd2a6b71SDan Nowlin  *
4779fd2a6b71SDan Nowlin  * Using first fit algorithm, take all the words that are still not done
4780fd2a6b71SDan Nowlin  * and start grouping them in 4-word groups. Each group makes up one
4781fd2a6b71SDan Nowlin  * recipe.
4782fd2a6b71SDan Nowlin  */
47835e24d598STony Nguyen static int
ice_create_first_fit_recp_def(struct ice_hw * hw,struct ice_prot_lkup_ext * lkup_exts,struct list_head * rg_list,u8 * recp_cnt)4784fd2a6b71SDan Nowlin ice_create_first_fit_recp_def(struct ice_hw *hw,
4785fd2a6b71SDan Nowlin 			      struct ice_prot_lkup_ext *lkup_exts,
4786fd2a6b71SDan Nowlin 			      struct list_head *rg_list,
4787fd2a6b71SDan Nowlin 			      u8 *recp_cnt)
4788fd2a6b71SDan Nowlin {
4789fd2a6b71SDan Nowlin 	struct ice_pref_recipe_group *grp = NULL;
4790fd2a6b71SDan Nowlin 	u8 j;
4791fd2a6b71SDan Nowlin 
4792fd2a6b71SDan Nowlin 	*recp_cnt = 0;
4793fd2a6b71SDan Nowlin 
4794fd2a6b71SDan Nowlin 	/* Walk through every word in the rule to check if it is not done. If so
4795fd2a6b71SDan Nowlin 	 * then this word needs to be part of a new recipe.
4796fd2a6b71SDan Nowlin 	 */
4797fd2a6b71SDan Nowlin 	for (j = 0; j < lkup_exts->n_val_words; j++)
4798fd2a6b71SDan Nowlin 		if (!test_bit(j, lkup_exts->done)) {
4799fd2a6b71SDan Nowlin 			if (!grp ||
4800fd2a6b71SDan Nowlin 			    grp->n_val_pairs == ICE_NUM_WORDS_RECIPE) {
4801fd2a6b71SDan Nowlin 				struct ice_recp_grp_entry *entry;
4802fd2a6b71SDan Nowlin 
4803fd2a6b71SDan Nowlin 				entry = devm_kzalloc(ice_hw_to_dev(hw),
4804fd2a6b71SDan Nowlin 						     sizeof(*entry),
4805fd2a6b71SDan Nowlin 						     GFP_KERNEL);
4806fd2a6b71SDan Nowlin 				if (!entry)
4807d54699e2STony Nguyen 					return -ENOMEM;
4808fd2a6b71SDan Nowlin 				list_add(&entry->l_entry, rg_list);
4809fd2a6b71SDan Nowlin 				grp = &entry->r_group;
4810fd2a6b71SDan Nowlin 				(*recp_cnt)++;
4811fd2a6b71SDan Nowlin 			}
4812fd2a6b71SDan Nowlin 
4813fd2a6b71SDan Nowlin 			grp->pairs[grp->n_val_pairs].prot_id =
4814fd2a6b71SDan Nowlin 				lkup_exts->fv_words[j].prot_id;
4815fd2a6b71SDan Nowlin 			grp->pairs[grp->n_val_pairs].off =
4816fd2a6b71SDan Nowlin 				lkup_exts->fv_words[j].off;
4817fd2a6b71SDan Nowlin 			grp->mask[grp->n_val_pairs] = lkup_exts->field_mask[j];
4818fd2a6b71SDan Nowlin 			grp->n_val_pairs++;
4819fd2a6b71SDan Nowlin 		}
4820fd2a6b71SDan Nowlin 
4821fd2a6b71SDan Nowlin 	return 0;
4822fd2a6b71SDan Nowlin }
4823fd2a6b71SDan Nowlin 
4824fd2a6b71SDan Nowlin /**
4825fd2a6b71SDan Nowlin  * ice_fill_fv_word_index - fill in the field vector indices for a recipe group
4826fd2a6b71SDan Nowlin  * @hw: pointer to the hardware structure
4827fd2a6b71SDan Nowlin  * @fv_list: field vector with the extraction sequence information
4828fd2a6b71SDan Nowlin  * @rg_list: recipe groupings with protocol-offset pairs
4829fd2a6b71SDan Nowlin  *
4830fd2a6b71SDan Nowlin  * Helper function to fill in the field vector indices for protocol-offset
4831fd2a6b71SDan Nowlin  * pairs. These indexes are then ultimately programmed into a recipe.
4832fd2a6b71SDan Nowlin  */
48335e24d598STony Nguyen static int
ice_fill_fv_word_index(struct ice_hw * hw,struct list_head * fv_list,struct list_head * rg_list)4834fd2a6b71SDan Nowlin ice_fill_fv_word_index(struct ice_hw *hw, struct list_head *fv_list,
4835fd2a6b71SDan Nowlin 		       struct list_head *rg_list)
4836fd2a6b71SDan Nowlin {
4837fd2a6b71SDan Nowlin 	struct ice_sw_fv_list_entry *fv;
4838fd2a6b71SDan Nowlin 	struct ice_recp_grp_entry *rg;
4839fd2a6b71SDan Nowlin 	struct ice_fv_word *fv_ext;
4840fd2a6b71SDan Nowlin 
4841fd2a6b71SDan Nowlin 	if (list_empty(fv_list))
4842fd2a6b71SDan Nowlin 		return 0;
4843fd2a6b71SDan Nowlin 
4844fd2a6b71SDan Nowlin 	fv = list_first_entry(fv_list, struct ice_sw_fv_list_entry,
4845fd2a6b71SDan Nowlin 			      list_entry);
4846fd2a6b71SDan Nowlin 	fv_ext = fv->fv_ptr->ew;
4847fd2a6b71SDan Nowlin 
4848fd2a6b71SDan Nowlin 	list_for_each_entry(rg, rg_list, l_entry) {
4849fd2a6b71SDan Nowlin 		u8 i;
4850fd2a6b71SDan Nowlin 
4851fd2a6b71SDan Nowlin 		for (i = 0; i < rg->r_group.n_val_pairs; i++) {
4852fd2a6b71SDan Nowlin 			struct ice_fv_word *pr;
4853fd2a6b71SDan Nowlin 			bool found = false;
4854fd2a6b71SDan Nowlin 			u16 mask;
4855fd2a6b71SDan Nowlin 			u8 j;
4856fd2a6b71SDan Nowlin 
4857fd2a6b71SDan Nowlin 			pr = &rg->r_group.pairs[i];
4858fd2a6b71SDan Nowlin 			mask = rg->r_group.mask[i];
4859fd2a6b71SDan Nowlin 
4860fd2a6b71SDan Nowlin 			for (j = 0; j < hw->blk[ICE_BLK_SW].es.fvw; j++)
4861fd2a6b71SDan Nowlin 				if (fv_ext[j].prot_id == pr->prot_id &&
4862fd2a6b71SDan Nowlin 				    fv_ext[j].off == pr->off) {
4863fd2a6b71SDan Nowlin 					found = true;
4864fd2a6b71SDan Nowlin 
4865fd2a6b71SDan Nowlin 					/* Store index of field vector */
4866fd2a6b71SDan Nowlin 					rg->fv_idx[i] = j;
4867fd2a6b71SDan Nowlin 					rg->fv_mask[i] = mask;
4868fd2a6b71SDan Nowlin 					break;
4869fd2a6b71SDan Nowlin 				}
4870fd2a6b71SDan Nowlin 
4871fd2a6b71SDan Nowlin 			/* Protocol/offset could not be found, caller gave an
4872fd2a6b71SDan Nowlin 			 * invalid pair
4873fd2a6b71SDan Nowlin 			 */
4874fd2a6b71SDan Nowlin 			if (!found)
4875d54699e2STony Nguyen 				return -EINVAL;
4876fd2a6b71SDan Nowlin 		}
4877fd2a6b71SDan Nowlin 	}
4878fd2a6b71SDan Nowlin 
4879fd2a6b71SDan Nowlin 	return 0;
4880fd2a6b71SDan Nowlin }
4881fd2a6b71SDan Nowlin 
4882fd2a6b71SDan Nowlin /**
4883fd2a6b71SDan Nowlin  * ice_find_free_recp_res_idx - find free result indexes for recipe
4884fd2a6b71SDan Nowlin  * @hw: pointer to hardware structure
4885fd2a6b71SDan Nowlin  * @profiles: bitmap of profiles that will be associated with the new recipe
4886fd2a6b71SDan Nowlin  * @free_idx: pointer to variable to receive the free index bitmap
4887fd2a6b71SDan Nowlin  *
4888fd2a6b71SDan Nowlin  * The algorithm used here is:
4889fd2a6b71SDan Nowlin  *	1. When creating a new recipe, create a set P which contains all
4890fd2a6b71SDan Nowlin  *	   Profiles that will be associated with our new recipe
4891fd2a6b71SDan Nowlin  *
4892fd2a6b71SDan Nowlin  *	2. For each Profile p in set P:
4893fd2a6b71SDan Nowlin  *	    a. Add all recipes associated with Profile p into set R
4894fd2a6b71SDan Nowlin  *	    b. Optional : PossibleIndexes &= profile[p].possibleIndexes
4895fd2a6b71SDan Nowlin  *		[initially PossibleIndexes should be 0xFFFFFFFFFFFFFFFF]
4896fd2a6b71SDan Nowlin  *		i. Or just assume they all have the same possible indexes:
4897fd2a6b71SDan Nowlin  *			44, 45, 46, 47
4898fd2a6b71SDan Nowlin  *			i.e., PossibleIndexes = 0x0000F00000000000
4899fd2a6b71SDan Nowlin  *
4900fd2a6b71SDan Nowlin  *	3. For each Recipe r in set R:
4901fd2a6b71SDan Nowlin  *	    a. UsedIndexes |= (bitwise or ) recipe[r].res_indexes
4902fd2a6b71SDan Nowlin  *	    b. FreeIndexes = UsedIndexes ^ PossibleIndexes
4903fd2a6b71SDan Nowlin  *
4904fd2a6b71SDan Nowlin  *	FreeIndexes will contain the bits indicating the indexes free for use,
4905fd2a6b71SDan Nowlin  *      then the code needs to update the recipe[r].used_result_idx_bits to
4906fd2a6b71SDan Nowlin  *      indicate which indexes were selected for use by this recipe.
4907fd2a6b71SDan Nowlin  */
4908fd2a6b71SDan Nowlin static u16
ice_find_free_recp_res_idx(struct ice_hw * hw,const unsigned long * profiles,unsigned long * free_idx)4909fd2a6b71SDan Nowlin ice_find_free_recp_res_idx(struct ice_hw *hw, const unsigned long *profiles,
4910fd2a6b71SDan Nowlin 			   unsigned long *free_idx)
4911fd2a6b71SDan Nowlin {
4912fd2a6b71SDan Nowlin 	DECLARE_BITMAP(possible_idx, ICE_MAX_FV_WORDS);
4913fd2a6b71SDan Nowlin 	DECLARE_BITMAP(recipes, ICE_MAX_NUM_RECIPES);
4914fd2a6b71SDan Nowlin 	DECLARE_BITMAP(used_idx, ICE_MAX_FV_WORDS);
4915fd2a6b71SDan Nowlin 	u16 bit;
4916fd2a6b71SDan Nowlin 
4917fd2a6b71SDan Nowlin 	bitmap_zero(recipes, ICE_MAX_NUM_RECIPES);
4918fd2a6b71SDan Nowlin 	bitmap_zero(used_idx, ICE_MAX_FV_WORDS);
4919fd2a6b71SDan Nowlin 
49202f7ee2a7SAlexander Lobakin 	bitmap_fill(possible_idx, ICE_MAX_FV_WORDS);
4921fd2a6b71SDan Nowlin 
4922fd2a6b71SDan Nowlin 	/* For each profile we are going to associate the recipe with, add the
4923fd2a6b71SDan Nowlin 	 * recipes that are associated with that profile. This will give us
4924fd2a6b71SDan Nowlin 	 * the set of recipes that our recipe may collide with. Also, determine
4925fd2a6b71SDan Nowlin 	 * what possible result indexes are usable given this set of profiles.
4926fd2a6b71SDan Nowlin 	 */
4927fd2a6b71SDan Nowlin 	for_each_set_bit(bit, profiles, ICE_MAX_NUM_PROFILES) {
4928fd2a6b71SDan Nowlin 		bitmap_or(recipes, recipes, profile_to_recipe[bit],
4929fd2a6b71SDan Nowlin 			  ICE_MAX_NUM_RECIPES);
4930fd2a6b71SDan Nowlin 		bitmap_and(possible_idx, possible_idx,
4931fd2a6b71SDan Nowlin 			   hw->switch_info->prof_res_bm[bit],
4932fd2a6b71SDan Nowlin 			   ICE_MAX_FV_WORDS);
4933fd2a6b71SDan Nowlin 	}
4934fd2a6b71SDan Nowlin 
4935fd2a6b71SDan Nowlin 	/* For each recipe that our new recipe may collide with, determine
4936fd2a6b71SDan Nowlin 	 * which indexes have been used.
4937fd2a6b71SDan Nowlin 	 */
4938fd2a6b71SDan Nowlin 	for_each_set_bit(bit, recipes, ICE_MAX_NUM_RECIPES)
4939fd2a6b71SDan Nowlin 		bitmap_or(used_idx, used_idx,
4940fd2a6b71SDan Nowlin 			  hw->switch_info->recp_list[bit].res_idxs,
4941fd2a6b71SDan Nowlin 			  ICE_MAX_FV_WORDS);
4942fd2a6b71SDan Nowlin 
4943fd2a6b71SDan Nowlin 	bitmap_xor(free_idx, used_idx, possible_idx, ICE_MAX_FV_WORDS);
4944fd2a6b71SDan Nowlin 
4945fd2a6b71SDan Nowlin 	/* return number of free indexes */
4946fd2a6b71SDan Nowlin 	return (u16)bitmap_weight(free_idx, ICE_MAX_FV_WORDS);
4947fd2a6b71SDan Nowlin }
4948fd2a6b71SDan Nowlin 
4949fd2a6b71SDan Nowlin /**
4950fd2a6b71SDan Nowlin  * ice_add_sw_recipe - function to call AQ calls to create switch recipe
4951fd2a6b71SDan Nowlin  * @hw: pointer to hardware structure
4952fd2a6b71SDan Nowlin  * @rm: recipe management list entry
4953fd2a6b71SDan Nowlin  * @profiles: bitmap of profiles that will be associated.
4954fd2a6b71SDan Nowlin  */
49555e24d598STony Nguyen static int
ice_add_sw_recipe(struct ice_hw * hw,struct ice_sw_recipe * rm,unsigned long * profiles)4956fd2a6b71SDan Nowlin ice_add_sw_recipe(struct ice_hw *hw, struct ice_sw_recipe *rm,
49578b032a55SMichal Swiatkowski 		  unsigned long *profiles)
4958fd2a6b71SDan Nowlin {
4959fd2a6b71SDan Nowlin 	DECLARE_BITMAP(result_idx_bm, ICE_MAX_FV_WORDS);
4960bccd9bceSMarcin Szycik 	struct ice_aqc_recipe_content *content;
4961fd2a6b71SDan Nowlin 	struct ice_aqc_recipe_data_elem *tmp;
4962fd2a6b71SDan Nowlin 	struct ice_aqc_recipe_data_elem *buf;
4963fd2a6b71SDan Nowlin 	struct ice_recp_grp_entry *entry;
4964fd2a6b71SDan Nowlin 	u16 free_res_idx;
4965fd2a6b71SDan Nowlin 	u16 recipe_count;
4966fd2a6b71SDan Nowlin 	u8 chain_idx;
4967fd2a6b71SDan Nowlin 	u8 recps = 0;
49685518ac2aSTony Nguyen 	int status;
4969fd2a6b71SDan Nowlin 
4970fd2a6b71SDan Nowlin 	/* When more than one recipe are required, another recipe is needed to
4971fd2a6b71SDan Nowlin 	 * chain them together. Matching a tunnel metadata ID takes up one of
4972fd2a6b71SDan Nowlin 	 * the match fields in the chaining recipe reducing the number of
4973fd2a6b71SDan Nowlin 	 * chained recipes by one.
4974fd2a6b71SDan Nowlin 	 */
4975fd2a6b71SDan Nowlin 	 /* check number of free result indices */
4976fd2a6b71SDan Nowlin 	bitmap_zero(result_idx_bm, ICE_MAX_FV_WORDS);
4977fd2a6b71SDan Nowlin 	free_res_idx = ice_find_free_recp_res_idx(hw, profiles, result_idx_bm);
4978fd2a6b71SDan Nowlin 
4979fd2a6b71SDan Nowlin 	ice_debug(hw, ICE_DBG_SW, "Result idx slots: %d, need %d\n",
4980fd2a6b71SDan Nowlin 		  free_res_idx, rm->n_grp_count);
4981fd2a6b71SDan Nowlin 
4982fd2a6b71SDan Nowlin 	if (rm->n_grp_count > 1) {
4983fd2a6b71SDan Nowlin 		if (rm->n_grp_count > free_res_idx)
4984d54699e2STony Nguyen 			return -ENOSPC;
4985fd2a6b71SDan Nowlin 
4986fd2a6b71SDan Nowlin 		rm->n_grp_count++;
4987fd2a6b71SDan Nowlin 	}
4988fd2a6b71SDan Nowlin 
4989fd2a6b71SDan Nowlin 	if (rm->n_grp_count > ICE_MAX_CHAIN_RECIPE)
4990d54699e2STony Nguyen 		return -ENOSPC;
4991fd2a6b71SDan Nowlin 
4992fd2a6b71SDan Nowlin 	tmp = kcalloc(ICE_MAX_NUM_RECIPES, sizeof(*tmp), GFP_KERNEL);
4993fd2a6b71SDan Nowlin 	if (!tmp)
4994d54699e2STony Nguyen 		return -ENOMEM;
4995fd2a6b71SDan Nowlin 
4996fd2a6b71SDan Nowlin 	buf = devm_kcalloc(ice_hw_to_dev(hw), rm->n_grp_count, sizeof(*buf),
4997fd2a6b71SDan Nowlin 			   GFP_KERNEL);
4998fd2a6b71SDan Nowlin 	if (!buf) {
4999d54699e2STony Nguyen 		status = -ENOMEM;
5000fd2a6b71SDan Nowlin 		goto err_mem;
5001fd2a6b71SDan Nowlin 	}
5002fd2a6b71SDan Nowlin 
5003fd2a6b71SDan Nowlin 	bitmap_zero(rm->r_bitmap, ICE_MAX_NUM_RECIPES);
5004fd2a6b71SDan Nowlin 	recipe_count = ICE_MAX_NUM_RECIPES;
5005fd2a6b71SDan Nowlin 	status = ice_aq_get_recipe(hw, tmp, &recipe_count, ICE_SW_LKUP_MAC,
5006fd2a6b71SDan Nowlin 				   NULL);
5007fd2a6b71SDan Nowlin 	if (status || recipe_count == 0)
5008fd2a6b71SDan Nowlin 		goto err_unroll;
5009fd2a6b71SDan Nowlin 
5010fd2a6b71SDan Nowlin 	/* Allocate the recipe resources, and configure them according to the
5011fd2a6b71SDan Nowlin 	 * match fields from protocol headers and extracted field vectors.
5012fd2a6b71SDan Nowlin 	 */
5013fd2a6b71SDan Nowlin 	chain_idx = find_first_bit(result_idx_bm, ICE_MAX_FV_WORDS);
5014fd2a6b71SDan Nowlin 	list_for_each_entry(entry, &rm->rg_list, l_entry) {
5015fd2a6b71SDan Nowlin 		u8 i;
5016fd2a6b71SDan Nowlin 
5017fd2a6b71SDan Nowlin 		status = ice_alloc_recipe(hw, &entry->rid);
5018fd2a6b71SDan Nowlin 		if (status)
5019fd2a6b71SDan Nowlin 			goto err_unroll;
5020fd2a6b71SDan Nowlin 
5021bccd9bceSMarcin Szycik 		content = &buf[recps].content;
5022bccd9bceSMarcin Szycik 
5023fd2a6b71SDan Nowlin 		/* Clear the result index of the located recipe, as this will be
5024fd2a6b71SDan Nowlin 		 * updated, if needed, later in the recipe creation process.
5025fd2a6b71SDan Nowlin 		 */
5026fd2a6b71SDan Nowlin 		tmp[0].content.result_indx = 0;
5027fd2a6b71SDan Nowlin 
5028fd2a6b71SDan Nowlin 		buf[recps] = tmp[0];
5029fd2a6b71SDan Nowlin 		buf[recps].recipe_indx = (u8)entry->rid;
5030fd2a6b71SDan Nowlin 		/* if the recipe is a non-root recipe RID should be programmed
5031fd2a6b71SDan Nowlin 		 * as 0 for the rules to be applied correctly.
5032fd2a6b71SDan Nowlin 		 */
5033bccd9bceSMarcin Szycik 		content->rid = 0;
5034bccd9bceSMarcin Szycik 		memset(&content->lkup_indx, 0,
5035bccd9bceSMarcin Szycik 		       sizeof(content->lkup_indx));
5036fd2a6b71SDan Nowlin 
5037fd2a6b71SDan Nowlin 		/* All recipes use look-up index 0 to match switch ID. */
5038bccd9bceSMarcin Szycik 		content->lkup_indx[0] = ICE_AQ_SW_ID_LKUP_IDX;
5039bccd9bceSMarcin Szycik 		content->mask[0] = cpu_to_le16(ICE_AQ_SW_ID_LKUP_MASK);
5040fd2a6b71SDan Nowlin 		/* Setup lkup_indx 1..4 to INVALID/ignore and set the mask
5041fd2a6b71SDan Nowlin 		 * to be 0
5042fd2a6b71SDan Nowlin 		 */
5043fd2a6b71SDan Nowlin 		for (i = 1; i <= ICE_NUM_WORDS_RECIPE; i++) {
5044bccd9bceSMarcin Szycik 			content->lkup_indx[i] = 0x80;
5045bccd9bceSMarcin Szycik 			content->mask[i] = 0;
5046fd2a6b71SDan Nowlin 		}
5047fd2a6b71SDan Nowlin 
5048fd2a6b71SDan Nowlin 		for (i = 0; i < entry->r_group.n_val_pairs; i++) {
5049bccd9bceSMarcin Szycik 			content->lkup_indx[i + 1] = entry->fv_idx[i];
5050bccd9bceSMarcin Szycik 			content->mask[i + 1] = cpu_to_le16(entry->fv_mask[i]);
5051fd2a6b71SDan Nowlin 		}
5052fd2a6b71SDan Nowlin 
5053fd2a6b71SDan Nowlin 		if (rm->n_grp_count > 1) {
5054fd2a6b71SDan Nowlin 			/* Checks to see if there really is a valid result index
5055fd2a6b71SDan Nowlin 			 * that can be used.
5056fd2a6b71SDan Nowlin 			 */
5057fd2a6b71SDan Nowlin 			if (chain_idx >= ICE_MAX_FV_WORDS) {
5058fd2a6b71SDan Nowlin 				ice_debug(hw, ICE_DBG_SW, "No chain index available\n");
5059d54699e2STony Nguyen 				status = -ENOSPC;
5060fd2a6b71SDan Nowlin 				goto err_unroll;
5061fd2a6b71SDan Nowlin 			}
5062fd2a6b71SDan Nowlin 
5063fd2a6b71SDan Nowlin 			entry->chain_idx = chain_idx;
5064bccd9bceSMarcin Szycik 			content->result_indx =
5065fd2a6b71SDan Nowlin 				ICE_AQ_RECIPE_RESULT_EN |
5066fd2a6b71SDan Nowlin 				((chain_idx << ICE_AQ_RECIPE_RESULT_DATA_S) &
5067fd2a6b71SDan Nowlin 				 ICE_AQ_RECIPE_RESULT_DATA_M);
5068fd2a6b71SDan Nowlin 			clear_bit(chain_idx, result_idx_bm);
5069fd2a6b71SDan Nowlin 			chain_idx = find_first_bit(result_idx_bm,
5070fd2a6b71SDan Nowlin 						   ICE_MAX_FV_WORDS);
5071fd2a6b71SDan Nowlin 		}
5072fd2a6b71SDan Nowlin 
5073fd2a6b71SDan Nowlin 		/* fill recipe dependencies */
5074fd2a6b71SDan Nowlin 		bitmap_zero((unsigned long *)buf[recps].recipe_bitmap,
5075fd2a6b71SDan Nowlin 			    ICE_MAX_NUM_RECIPES);
5076fd2a6b71SDan Nowlin 		set_bit(buf[recps].recipe_indx,
5077fd2a6b71SDan Nowlin 			(unsigned long *)buf[recps].recipe_bitmap);
5078bccd9bceSMarcin Szycik 		content->act_ctrl_fwd_priority = rm->priority;
5079bccd9bceSMarcin Szycik 
5080bccd9bceSMarcin Szycik 		if (rm->need_pass_l2)
5081bccd9bceSMarcin Szycik 			content->act_ctrl |= ICE_AQ_RECIPE_ACT_NEED_PASS_L2;
5082bccd9bceSMarcin Szycik 
5083bccd9bceSMarcin Szycik 		if (rm->allow_pass_l2)
5084bccd9bceSMarcin Szycik 			content->act_ctrl |= ICE_AQ_RECIPE_ACT_ALLOW_PASS_L2;
5085fd2a6b71SDan Nowlin 		recps++;
5086fd2a6b71SDan Nowlin 	}
5087fd2a6b71SDan Nowlin 
5088fd2a6b71SDan Nowlin 	if (rm->n_grp_count == 1) {
5089fd2a6b71SDan Nowlin 		rm->root_rid = buf[0].recipe_indx;
5090fd2a6b71SDan Nowlin 		set_bit(buf[0].recipe_indx, rm->r_bitmap);
5091fd2a6b71SDan Nowlin 		buf[0].content.rid = rm->root_rid | ICE_AQ_RECIPE_ID_IS_ROOT;
5092fd2a6b71SDan Nowlin 		if (sizeof(buf[0].recipe_bitmap) >= sizeof(rm->r_bitmap)) {
5093fd2a6b71SDan Nowlin 			memcpy(buf[0].recipe_bitmap, rm->r_bitmap,
5094fd2a6b71SDan Nowlin 			       sizeof(buf[0].recipe_bitmap));
5095fd2a6b71SDan Nowlin 		} else {
5096d54699e2STony Nguyen 			status = -EINVAL;
5097fd2a6b71SDan Nowlin 			goto err_unroll;
5098fd2a6b71SDan Nowlin 		}
5099fd2a6b71SDan Nowlin 		/* Applicable only for ROOT_RECIPE, set the fwd_priority for
5100fd2a6b71SDan Nowlin 		 * the recipe which is getting created if specified
5101fd2a6b71SDan Nowlin 		 * by user. Usually any advanced switch filter, which results
5102fd2a6b71SDan Nowlin 		 * into new extraction sequence, ended up creating a new recipe
5103fd2a6b71SDan Nowlin 		 * of type ROOT and usually recipes are associated with profiles
5104fd2a6b71SDan Nowlin 		 * Switch rule referreing newly created recipe, needs to have
5105fd2a6b71SDan Nowlin 		 * either/or 'fwd' or 'join' priority, otherwise switch rule
5106fd2a6b71SDan Nowlin 		 * evaluation will not happen correctly. In other words, if
5107fd2a6b71SDan Nowlin 		 * switch rule to be evaluated on priority basis, then recipe
5108fd2a6b71SDan Nowlin 		 * needs to have priority, otherwise it will be evaluated last.
5109fd2a6b71SDan Nowlin 		 */
5110fd2a6b71SDan Nowlin 		buf[0].content.act_ctrl_fwd_priority = rm->priority;
5111fd2a6b71SDan Nowlin 	} else {
5112fd2a6b71SDan Nowlin 		struct ice_recp_grp_entry *last_chain_entry;
5113fd2a6b71SDan Nowlin 		u16 rid, i;
5114fd2a6b71SDan Nowlin 
5115fd2a6b71SDan Nowlin 		/* Allocate the last recipe that will chain the outcomes of the
5116fd2a6b71SDan Nowlin 		 * other recipes together
5117fd2a6b71SDan Nowlin 		 */
5118fd2a6b71SDan Nowlin 		status = ice_alloc_recipe(hw, &rid);
5119fd2a6b71SDan Nowlin 		if (status)
5120fd2a6b71SDan Nowlin 			goto err_unroll;
5121fd2a6b71SDan Nowlin 
5122bccd9bceSMarcin Szycik 		content = &buf[recps].content;
5123bccd9bceSMarcin Szycik 
5124fd2a6b71SDan Nowlin 		buf[recps].recipe_indx = (u8)rid;
5125bccd9bceSMarcin Szycik 		content->rid = (u8)rid;
5126bccd9bceSMarcin Szycik 		content->rid |= ICE_AQ_RECIPE_ID_IS_ROOT;
5127fd2a6b71SDan Nowlin 		/* the new entry created should also be part of rg_list to
5128fd2a6b71SDan Nowlin 		 * make sure we have complete recipe
5129fd2a6b71SDan Nowlin 		 */
5130fd2a6b71SDan Nowlin 		last_chain_entry = devm_kzalloc(ice_hw_to_dev(hw),
5131fd2a6b71SDan Nowlin 						sizeof(*last_chain_entry),
5132fd2a6b71SDan Nowlin 						GFP_KERNEL);
5133fd2a6b71SDan Nowlin 		if (!last_chain_entry) {
5134d54699e2STony Nguyen 			status = -ENOMEM;
5135fd2a6b71SDan Nowlin 			goto err_unroll;
5136fd2a6b71SDan Nowlin 		}
5137fd2a6b71SDan Nowlin 		last_chain_entry->rid = rid;
5138bccd9bceSMarcin Szycik 		memset(&content->lkup_indx, 0, sizeof(content->lkup_indx));
5139fd2a6b71SDan Nowlin 		/* All recipes use look-up index 0 to match switch ID. */
5140bccd9bceSMarcin Szycik 		content->lkup_indx[0] = ICE_AQ_SW_ID_LKUP_IDX;
5141bccd9bceSMarcin Szycik 		content->mask[0] = cpu_to_le16(ICE_AQ_SW_ID_LKUP_MASK);
5142fd2a6b71SDan Nowlin 		for (i = 1; i <= ICE_NUM_WORDS_RECIPE; i++) {
5143bccd9bceSMarcin Szycik 			content->lkup_indx[i] = ICE_AQ_RECIPE_LKUP_IGNORE;
5144bccd9bceSMarcin Szycik 			content->mask[i] = 0;
5145fd2a6b71SDan Nowlin 		}
5146fd2a6b71SDan Nowlin 
5147fd2a6b71SDan Nowlin 		i = 1;
5148fd2a6b71SDan Nowlin 		/* update r_bitmap with the recp that is used for chaining */
5149fd2a6b71SDan Nowlin 		set_bit(rid, rm->r_bitmap);
5150fd2a6b71SDan Nowlin 		/* this is the recipe that chains all the other recipes so it
5151fd2a6b71SDan Nowlin 		 * should not have a chaining ID to indicate the same
5152fd2a6b71SDan Nowlin 		 */
5153fd2a6b71SDan Nowlin 		last_chain_entry->chain_idx = ICE_INVAL_CHAIN_IND;
5154fd2a6b71SDan Nowlin 		list_for_each_entry(entry, &rm->rg_list, l_entry) {
5155fd2a6b71SDan Nowlin 			last_chain_entry->fv_idx[i] = entry->chain_idx;
5156bccd9bceSMarcin Szycik 			content->lkup_indx[i] = entry->chain_idx;
5157bccd9bceSMarcin Szycik 			content->mask[i++] = cpu_to_le16(0xFFFF);
5158fd2a6b71SDan Nowlin 			set_bit(entry->rid, rm->r_bitmap);
5159fd2a6b71SDan Nowlin 		}
5160fd2a6b71SDan Nowlin 		list_add(&last_chain_entry->l_entry, &rm->rg_list);
5161fd2a6b71SDan Nowlin 		if (sizeof(buf[recps].recipe_bitmap) >=
5162fd2a6b71SDan Nowlin 		    sizeof(rm->r_bitmap)) {
5163fd2a6b71SDan Nowlin 			memcpy(buf[recps].recipe_bitmap, rm->r_bitmap,
5164fd2a6b71SDan Nowlin 			       sizeof(buf[recps].recipe_bitmap));
5165fd2a6b71SDan Nowlin 		} else {
5166d54699e2STony Nguyen 			status = -EINVAL;
5167fd2a6b71SDan Nowlin 			goto err_unroll;
5168fd2a6b71SDan Nowlin 		}
5169bccd9bceSMarcin Szycik 		content->act_ctrl_fwd_priority = rm->priority;
5170fd2a6b71SDan Nowlin 
5171fd2a6b71SDan Nowlin 		recps++;
5172fd2a6b71SDan Nowlin 		rm->root_rid = (u8)rid;
5173fd2a6b71SDan Nowlin 	}
5174fd2a6b71SDan Nowlin 	status = ice_acquire_change_lock(hw, ICE_RES_WRITE);
5175fd2a6b71SDan Nowlin 	if (status)
5176fd2a6b71SDan Nowlin 		goto err_unroll;
5177fd2a6b71SDan Nowlin 
5178fd2a6b71SDan Nowlin 	status = ice_aq_add_recipe(hw, buf, rm->n_grp_count, NULL);
5179fd2a6b71SDan Nowlin 	ice_release_change_lock(hw);
5180fd2a6b71SDan Nowlin 	if (status)
5181fd2a6b71SDan Nowlin 		goto err_unroll;
5182fd2a6b71SDan Nowlin 
5183fd2a6b71SDan Nowlin 	/* Every recipe that just got created add it to the recipe
5184fd2a6b71SDan Nowlin 	 * book keeping list
5185fd2a6b71SDan Nowlin 	 */
5186fd2a6b71SDan Nowlin 	list_for_each_entry(entry, &rm->rg_list, l_entry) {
5187fd2a6b71SDan Nowlin 		struct ice_switch_info *sw = hw->switch_info;
5188fd2a6b71SDan Nowlin 		bool is_root, idx_found = false;
5189fd2a6b71SDan Nowlin 		struct ice_sw_recipe *recp;
5190fd2a6b71SDan Nowlin 		u16 idx, buf_idx = 0;
5191fd2a6b71SDan Nowlin 
5192fd2a6b71SDan Nowlin 		/* find buffer index for copying some data */
5193fd2a6b71SDan Nowlin 		for (idx = 0; idx < rm->n_grp_count; idx++)
5194fd2a6b71SDan Nowlin 			if (buf[idx].recipe_indx == entry->rid) {
5195fd2a6b71SDan Nowlin 				buf_idx = idx;
5196fd2a6b71SDan Nowlin 				idx_found = true;
5197fd2a6b71SDan Nowlin 			}
5198fd2a6b71SDan Nowlin 
5199fd2a6b71SDan Nowlin 		if (!idx_found) {
5200d54699e2STony Nguyen 			status = -EIO;
5201fd2a6b71SDan Nowlin 			goto err_unroll;
5202fd2a6b71SDan Nowlin 		}
5203fd2a6b71SDan Nowlin 
5204fd2a6b71SDan Nowlin 		recp = &sw->recp_list[entry->rid];
5205fd2a6b71SDan Nowlin 		is_root = (rm->root_rid == entry->rid);
5206fd2a6b71SDan Nowlin 		recp->is_root = is_root;
5207fd2a6b71SDan Nowlin 
5208fd2a6b71SDan Nowlin 		recp->root_rid = entry->rid;
5209fd2a6b71SDan Nowlin 		recp->big_recp = (is_root && rm->n_grp_count > 1);
5210fd2a6b71SDan Nowlin 
5211fd2a6b71SDan Nowlin 		memcpy(&recp->ext_words, entry->r_group.pairs,
5212fd2a6b71SDan Nowlin 		       entry->r_group.n_val_pairs * sizeof(struct ice_fv_word));
5213fd2a6b71SDan Nowlin 
5214fd2a6b71SDan Nowlin 		memcpy(recp->r_bitmap, buf[buf_idx].recipe_bitmap,
5215fd2a6b71SDan Nowlin 		       sizeof(recp->r_bitmap));
5216fd2a6b71SDan Nowlin 
5217fd2a6b71SDan Nowlin 		/* Copy non-result fv index values and masks to recipe. This
5218fd2a6b71SDan Nowlin 		 * call will also update the result recipe bitmask.
5219fd2a6b71SDan Nowlin 		 */
5220fd2a6b71SDan Nowlin 		ice_collect_result_idx(&buf[buf_idx], recp);
5221fd2a6b71SDan Nowlin 
5222fd2a6b71SDan Nowlin 		/* for non-root recipes, also copy to the root, this allows
5223fd2a6b71SDan Nowlin 		 * easier matching of a complete chained recipe
5224fd2a6b71SDan Nowlin 		 */
5225fd2a6b71SDan Nowlin 		if (!is_root)
5226fd2a6b71SDan Nowlin 			ice_collect_result_idx(&buf[buf_idx],
5227fd2a6b71SDan Nowlin 					       &sw->recp_list[rm->root_rid]);
5228fd2a6b71SDan Nowlin 
5229fd2a6b71SDan Nowlin 		recp->n_ext_words = entry->r_group.n_val_pairs;
5230fd2a6b71SDan Nowlin 		recp->chain_idx = entry->chain_idx;
5231fd2a6b71SDan Nowlin 		recp->priority = buf[buf_idx].content.act_ctrl_fwd_priority;
5232fd2a6b71SDan Nowlin 		recp->n_grp_count = rm->n_grp_count;
52338b032a55SMichal Swiatkowski 		recp->tun_type = rm->tun_type;
5234bccd9bceSMarcin Szycik 		recp->need_pass_l2 = rm->need_pass_l2;
5235bccd9bceSMarcin Szycik 		recp->allow_pass_l2 = rm->allow_pass_l2;
5236fd2a6b71SDan Nowlin 		recp->recp_created = true;
5237fd2a6b71SDan Nowlin 	}
5238fd2a6b71SDan Nowlin 	rm->root_buf = buf;
5239fd2a6b71SDan Nowlin 	kfree(tmp);
5240fd2a6b71SDan Nowlin 	return status;
5241fd2a6b71SDan Nowlin 
5242fd2a6b71SDan Nowlin err_unroll:
5243fd2a6b71SDan Nowlin err_mem:
5244fd2a6b71SDan Nowlin 	kfree(tmp);
5245fd2a6b71SDan Nowlin 	devm_kfree(ice_hw_to_dev(hw), buf);
5246fd2a6b71SDan Nowlin 	return status;
5247fd2a6b71SDan Nowlin }
5248fd2a6b71SDan Nowlin 
5249fd2a6b71SDan Nowlin /**
5250fd2a6b71SDan Nowlin  * ice_create_recipe_group - creates recipe group
5251fd2a6b71SDan Nowlin  * @hw: pointer to hardware structure
5252fd2a6b71SDan Nowlin  * @rm: recipe management list entry
5253fd2a6b71SDan Nowlin  * @lkup_exts: lookup elements
5254fd2a6b71SDan Nowlin  */
52555e24d598STony Nguyen static int
ice_create_recipe_group(struct ice_hw * hw,struct ice_sw_recipe * rm,struct ice_prot_lkup_ext * lkup_exts)5256fd2a6b71SDan Nowlin ice_create_recipe_group(struct ice_hw *hw, struct ice_sw_recipe *rm,
5257fd2a6b71SDan Nowlin 			struct ice_prot_lkup_ext *lkup_exts)
5258fd2a6b71SDan Nowlin {
5259fd2a6b71SDan Nowlin 	u8 recp_count = 0;
52605518ac2aSTony Nguyen 	int status;
5261fd2a6b71SDan Nowlin 
5262fd2a6b71SDan Nowlin 	rm->n_grp_count = 0;
5263fd2a6b71SDan Nowlin 
5264fd2a6b71SDan Nowlin 	/* Create recipes for words that are marked not done by packing them
5265fd2a6b71SDan Nowlin 	 * as best fit.
5266fd2a6b71SDan Nowlin 	 */
5267fd2a6b71SDan Nowlin 	status = ice_create_first_fit_recp_def(hw, lkup_exts,
5268fd2a6b71SDan Nowlin 					       &rm->rg_list, &recp_count);
5269fd2a6b71SDan Nowlin 	if (!status) {
5270fd2a6b71SDan Nowlin 		rm->n_grp_count += recp_count;
5271fd2a6b71SDan Nowlin 		rm->n_ext_words = lkup_exts->n_val_words;
5272fd2a6b71SDan Nowlin 		memcpy(&rm->ext_words, lkup_exts->fv_words,
5273fd2a6b71SDan Nowlin 		       sizeof(rm->ext_words));
5274fd2a6b71SDan Nowlin 		memcpy(rm->word_masks, lkup_exts->field_mask,
5275fd2a6b71SDan Nowlin 		       sizeof(rm->word_masks));
5276fd2a6b71SDan Nowlin 	}
5277fd2a6b71SDan Nowlin 
5278fd2a6b71SDan Nowlin 	return status;
5279fd2a6b71SDan Nowlin }
5280fd2a6b71SDan Nowlin 
5281fd2a6b71SDan Nowlin /* ice_get_compat_fv_bitmap - Get compatible field vector bitmap for rule
5282fd2a6b71SDan Nowlin  * @hw: pointer to hardware structure
5283fd2a6b71SDan Nowlin  * @rinfo: other information regarding the rule e.g. priority and action info
5284fd2a6b71SDan Nowlin  * @bm: pointer to memory for returning the bitmap of field vectors
5285fd2a6b71SDan Nowlin  */
5286fd2a6b71SDan Nowlin static void
ice_get_compat_fv_bitmap(struct ice_hw * hw,struct ice_adv_rule_info * rinfo,unsigned long * bm)5287fd2a6b71SDan Nowlin ice_get_compat_fv_bitmap(struct ice_hw *hw, struct ice_adv_rule_info *rinfo,
5288fd2a6b71SDan Nowlin 			 unsigned long *bm)
5289fd2a6b71SDan Nowlin {
52908b032a55SMichal Swiatkowski 	enum ice_prof_type prof_type;
52918b032a55SMichal Swiatkowski 
5292fd2a6b71SDan Nowlin 	bitmap_zero(bm, ICE_MAX_NUM_PROFILES);
5293fd2a6b71SDan Nowlin 
52948b032a55SMichal Swiatkowski 	switch (rinfo->tun_type) {
52958b032a55SMichal Swiatkowski 	case ICE_NON_TUN:
52968b032a55SMichal Swiatkowski 		prof_type = ICE_PROF_NON_TUN;
52978b032a55SMichal Swiatkowski 		break;
52988b032a55SMichal Swiatkowski 	case ICE_ALL_TUNNELS:
52998b032a55SMichal Swiatkowski 		prof_type = ICE_PROF_TUN_ALL;
53008b032a55SMichal Swiatkowski 		break;
53018b032a55SMichal Swiatkowski 	case ICE_SW_TUN_GENEVE:
53028b032a55SMichal Swiatkowski 	case ICE_SW_TUN_VXLAN:
53038b032a55SMichal Swiatkowski 		prof_type = ICE_PROF_TUN_UDP;
53048b032a55SMichal Swiatkowski 		break;
5305f0a35040SMichal Swiatkowski 	case ICE_SW_TUN_NVGRE:
5306f0a35040SMichal Swiatkowski 		prof_type = ICE_PROF_TUN_GRE;
5307f0a35040SMichal Swiatkowski 		break;
53089a225f81SMarcin Szycik 	case ICE_SW_TUN_GTPU:
53099a225f81SMarcin Szycik 		prof_type = ICE_PROF_TUN_GTPU;
53109a225f81SMarcin Szycik 		break;
53119a225f81SMarcin Szycik 	case ICE_SW_TUN_GTPC:
53129a225f81SMarcin Szycik 		prof_type = ICE_PROF_TUN_GTPC;
53139a225f81SMarcin Szycik 		break;
5314b70bc066SWojciech Drewek 	case ICE_SW_TUN_AND_NON_TUN:
53158b032a55SMichal Swiatkowski 	default:
53168b032a55SMichal Swiatkowski 		prof_type = ICE_PROF_ALL;
53178b032a55SMichal Swiatkowski 		break;
53188b032a55SMichal Swiatkowski 	}
53198b032a55SMichal Swiatkowski 
53208b032a55SMichal Swiatkowski 	ice_get_sw_fv_bitmap(hw, prof_type, bm);
5321fd2a6b71SDan Nowlin }
5322fd2a6b71SDan Nowlin 
5323fd2a6b71SDan Nowlin /**
5324fd2a6b71SDan Nowlin  * ice_add_adv_recipe - Add an advanced recipe that is not part of the default
5325fd2a6b71SDan Nowlin  * @hw: pointer to hardware structure
5326fd2a6b71SDan Nowlin  * @lkups: lookup elements or match criteria for the advanced recipe, one
5327fd2a6b71SDan Nowlin  *  structure per protocol header
5328fd2a6b71SDan Nowlin  * @lkups_cnt: number of protocols
5329fd2a6b71SDan Nowlin  * @rinfo: other information regarding the rule e.g. priority and action info
5330fd2a6b71SDan Nowlin  * @rid: return the recipe ID of the recipe created
5331fd2a6b71SDan Nowlin  */
53325e24d598STony Nguyen static int
ice_add_adv_recipe(struct ice_hw * hw,struct ice_adv_lkup_elem * lkups,u16 lkups_cnt,struct ice_adv_rule_info * rinfo,u16 * rid)5333fd2a6b71SDan Nowlin ice_add_adv_recipe(struct ice_hw *hw, struct ice_adv_lkup_elem *lkups,
5334fd2a6b71SDan Nowlin 		   u16 lkups_cnt, struct ice_adv_rule_info *rinfo, u16 *rid)
5335fd2a6b71SDan Nowlin {
5336fd2a6b71SDan Nowlin 	DECLARE_BITMAP(fv_bitmap, ICE_MAX_NUM_PROFILES);
5337fd2a6b71SDan Nowlin 	DECLARE_BITMAP(profiles, ICE_MAX_NUM_PROFILES);
5338fd2a6b71SDan Nowlin 	struct ice_prot_lkup_ext *lkup_exts;
5339fd2a6b71SDan Nowlin 	struct ice_recp_grp_entry *r_entry;
5340fd2a6b71SDan Nowlin 	struct ice_sw_fv_list_entry *fvit;
5341fd2a6b71SDan Nowlin 	struct ice_recp_grp_entry *r_tmp;
5342fd2a6b71SDan Nowlin 	struct ice_sw_fv_list_entry *tmp;
5343fd2a6b71SDan Nowlin 	struct ice_sw_recipe *rm;
53445518ac2aSTony Nguyen 	int status = 0;
5345fd2a6b71SDan Nowlin 	u8 i;
5346fd2a6b71SDan Nowlin 
5347fd2a6b71SDan Nowlin 	if (!lkups_cnt)
5348d54699e2STony Nguyen 		return -EINVAL;
5349fd2a6b71SDan Nowlin 
5350fd2a6b71SDan Nowlin 	lkup_exts = kzalloc(sizeof(*lkup_exts), GFP_KERNEL);
5351fd2a6b71SDan Nowlin 	if (!lkup_exts)
5352d54699e2STony Nguyen 		return -ENOMEM;
5353fd2a6b71SDan Nowlin 
5354fd2a6b71SDan Nowlin 	/* Determine the number of words to be matched and if it exceeds a
5355fd2a6b71SDan Nowlin 	 * recipe's restrictions
5356fd2a6b71SDan Nowlin 	 */
5357fd2a6b71SDan Nowlin 	for (i = 0; i < lkups_cnt; i++) {
5358fd2a6b71SDan Nowlin 		u16 count;
5359fd2a6b71SDan Nowlin 
5360fd2a6b71SDan Nowlin 		if (lkups[i].type >= ICE_PROTOCOL_LAST) {
5361d54699e2STony Nguyen 			status = -EIO;
5362fd2a6b71SDan Nowlin 			goto err_free_lkup_exts;
5363fd2a6b71SDan Nowlin 		}
5364fd2a6b71SDan Nowlin 
5365fd2a6b71SDan Nowlin 		count = ice_fill_valid_words(&lkups[i], lkup_exts);
5366fd2a6b71SDan Nowlin 		if (!count) {
5367d54699e2STony Nguyen 			status = -EIO;
5368fd2a6b71SDan Nowlin 			goto err_free_lkup_exts;
5369fd2a6b71SDan Nowlin 		}
5370fd2a6b71SDan Nowlin 	}
5371fd2a6b71SDan Nowlin 
5372fd2a6b71SDan Nowlin 	rm = kzalloc(sizeof(*rm), GFP_KERNEL);
5373fd2a6b71SDan Nowlin 	if (!rm) {
5374d54699e2STony Nguyen 		status = -ENOMEM;
5375fd2a6b71SDan Nowlin 		goto err_free_lkup_exts;
5376fd2a6b71SDan Nowlin 	}
5377fd2a6b71SDan Nowlin 
5378fd2a6b71SDan Nowlin 	/* Get field vectors that contain fields extracted from all the protocol
5379fd2a6b71SDan Nowlin 	 * headers being programmed.
5380fd2a6b71SDan Nowlin 	 */
5381fd2a6b71SDan Nowlin 	INIT_LIST_HEAD(&rm->fv_list);
5382fd2a6b71SDan Nowlin 	INIT_LIST_HEAD(&rm->rg_list);
5383fd2a6b71SDan Nowlin 
5384fd2a6b71SDan Nowlin 	/* Get bitmap of field vectors (profiles) that are compatible with the
5385fd2a6b71SDan Nowlin 	 * rule request; only these will be searched in the subsequent call to
5386e5dd661bSMichal Swiatkowski 	 * ice_get_sw_fv_list.
5387fd2a6b71SDan Nowlin 	 */
5388fd2a6b71SDan Nowlin 	ice_get_compat_fv_bitmap(hw, rinfo, fv_bitmap);
5389fd2a6b71SDan Nowlin 
5390e5dd661bSMichal Swiatkowski 	status = ice_get_sw_fv_list(hw, lkup_exts, fv_bitmap, &rm->fv_list);
5391fd2a6b71SDan Nowlin 	if (status)
5392fd2a6b71SDan Nowlin 		goto err_unroll;
5393fd2a6b71SDan Nowlin 
5394fd2a6b71SDan Nowlin 	/* Group match words into recipes using preferred recipe grouping
5395fd2a6b71SDan Nowlin 	 * criteria.
5396fd2a6b71SDan Nowlin 	 */
5397fd2a6b71SDan Nowlin 	status = ice_create_recipe_group(hw, rm, lkup_exts);
5398fd2a6b71SDan Nowlin 	if (status)
5399fd2a6b71SDan Nowlin 		goto err_unroll;
5400fd2a6b71SDan Nowlin 
5401fd2a6b71SDan Nowlin 	/* set the recipe priority if specified */
5402fd2a6b71SDan Nowlin 	rm->priority = (u8)rinfo->priority;
5403fd2a6b71SDan Nowlin 
5404bccd9bceSMarcin Szycik 	rm->need_pass_l2 = rinfo->need_pass_l2;
5405bccd9bceSMarcin Szycik 	rm->allow_pass_l2 = rinfo->allow_pass_l2;
5406bccd9bceSMarcin Szycik 
5407fd2a6b71SDan Nowlin 	/* Find offsets from the field vector. Pick the first one for all the
5408fd2a6b71SDan Nowlin 	 * recipes.
5409fd2a6b71SDan Nowlin 	 */
5410fd2a6b71SDan Nowlin 	status = ice_fill_fv_word_index(hw, &rm->fv_list, &rm->rg_list);
5411fd2a6b71SDan Nowlin 	if (status)
5412fd2a6b71SDan Nowlin 		goto err_unroll;
5413fd2a6b71SDan Nowlin 
5414fd2a6b71SDan Nowlin 	/* get bitmap of all profiles the recipe will be associated with */
5415fd2a6b71SDan Nowlin 	bitmap_zero(profiles, ICE_MAX_NUM_PROFILES);
5416fd2a6b71SDan Nowlin 	list_for_each_entry(fvit, &rm->fv_list, list_entry) {
5417fd2a6b71SDan Nowlin 		ice_debug(hw, ICE_DBG_SW, "profile: %d\n", fvit->profile_id);
5418fd2a6b71SDan Nowlin 		set_bit((u16)fvit->profile_id, profiles);
5419fd2a6b71SDan Nowlin 	}
5420fd2a6b71SDan Nowlin 
5421fd2a6b71SDan Nowlin 	/* Look for a recipe which matches our requested fv / mask list */
5422bccd9bceSMarcin Szycik 	*rid = ice_find_recp(hw, lkup_exts, rinfo);
5423fd2a6b71SDan Nowlin 	if (*rid < ICE_MAX_NUM_RECIPES)
5424fd2a6b71SDan Nowlin 		/* Success if found a recipe that match the existing criteria */
5425fd2a6b71SDan Nowlin 		goto err_unroll;
5426fd2a6b71SDan Nowlin 
5427de6acd1cSMichal Swiatkowski 	rm->tun_type = rinfo->tun_type;
5428fd2a6b71SDan Nowlin 	/* Recipe we need does not exist, add a recipe */
54298b032a55SMichal Swiatkowski 	status = ice_add_sw_recipe(hw, rm, profiles);
5430fd2a6b71SDan Nowlin 	if (status)
5431fd2a6b71SDan Nowlin 		goto err_unroll;
5432fd2a6b71SDan Nowlin 
5433fd2a6b71SDan Nowlin 	/* Associate all the recipes created with all the profiles in the
5434fd2a6b71SDan Nowlin 	 * common field vector.
5435fd2a6b71SDan Nowlin 	 */
5436fd2a6b71SDan Nowlin 	list_for_each_entry(fvit, &rm->fv_list, list_entry) {
5437fd2a6b71SDan Nowlin 		DECLARE_BITMAP(r_bitmap, ICE_MAX_NUM_RECIPES);
5438493b2993SSteven Zou 		u64 recp_assoc;
5439fd2a6b71SDan Nowlin 		u16 j;
5440fd2a6b71SDan Nowlin 
5441fd2a6b71SDan Nowlin 		status = ice_aq_get_recipe_to_profile(hw, fvit->profile_id,
5442493b2993SSteven Zou 						      &recp_assoc, NULL);
5443fd2a6b71SDan Nowlin 		if (status)
5444fd2a6b71SDan Nowlin 			goto err_unroll;
5445fd2a6b71SDan Nowlin 
5446493b2993SSteven Zou 		bitmap_from_arr64(r_bitmap, &recp_assoc, ICE_MAX_NUM_RECIPES);
5447fd2a6b71SDan Nowlin 		bitmap_or(r_bitmap, r_bitmap, rm->r_bitmap,
5448fd2a6b71SDan Nowlin 			  ICE_MAX_NUM_RECIPES);
5449fd2a6b71SDan Nowlin 		status = ice_acquire_change_lock(hw, ICE_RES_WRITE);
5450fd2a6b71SDan Nowlin 		if (status)
5451fd2a6b71SDan Nowlin 			goto err_unroll;
5452fd2a6b71SDan Nowlin 
5453493b2993SSteven Zou 		bitmap_to_arr64(&recp_assoc, r_bitmap, ICE_MAX_NUM_RECIPES);
5454fd2a6b71SDan Nowlin 		status = ice_aq_map_recipe_to_profile(hw, fvit->profile_id,
5455493b2993SSteven Zou 						      recp_assoc, NULL);
5456fd2a6b71SDan Nowlin 		ice_release_change_lock(hw);
5457fd2a6b71SDan Nowlin 
5458fd2a6b71SDan Nowlin 		if (status)
5459fd2a6b71SDan Nowlin 			goto err_unroll;
5460fd2a6b71SDan Nowlin 
5461fd2a6b71SDan Nowlin 		/* Update profile to recipe bitmap array */
5462fd2a6b71SDan Nowlin 		bitmap_copy(profile_to_recipe[fvit->profile_id], r_bitmap,
5463fd2a6b71SDan Nowlin 			    ICE_MAX_NUM_RECIPES);
5464fd2a6b71SDan Nowlin 
5465fd2a6b71SDan Nowlin 		/* Update recipe to profile bitmap array */
5466fd2a6b71SDan Nowlin 		for_each_set_bit(j, rm->r_bitmap, ICE_MAX_NUM_RECIPES)
5467fd2a6b71SDan Nowlin 			set_bit((u16)fvit->profile_id, recipe_to_profile[j]);
5468fd2a6b71SDan Nowlin 	}
5469fd2a6b71SDan Nowlin 
5470fd2a6b71SDan Nowlin 	*rid = rm->root_rid;
5471fd2a6b71SDan Nowlin 	memcpy(&hw->switch_info->recp_list[*rid].lkup_exts, lkup_exts,
5472fd2a6b71SDan Nowlin 	       sizeof(*lkup_exts));
5473fd2a6b71SDan Nowlin err_unroll:
5474fd2a6b71SDan Nowlin 	list_for_each_entry_safe(r_entry, r_tmp, &rm->rg_list, l_entry) {
5475fd2a6b71SDan Nowlin 		list_del(&r_entry->l_entry);
5476fd2a6b71SDan Nowlin 		devm_kfree(ice_hw_to_dev(hw), r_entry);
5477fd2a6b71SDan Nowlin 	}
5478fd2a6b71SDan Nowlin 
5479fd2a6b71SDan Nowlin 	list_for_each_entry_safe(fvit, tmp, &rm->fv_list, list_entry) {
5480fd2a6b71SDan Nowlin 		list_del(&fvit->list_entry);
5481fd2a6b71SDan Nowlin 		devm_kfree(ice_hw_to_dev(hw), fvit);
5482fd2a6b71SDan Nowlin 	}
5483fd2a6b71SDan Nowlin 
5484fd2a6b71SDan Nowlin 	devm_kfree(ice_hw_to_dev(hw), rm->root_buf);
5485fd2a6b71SDan Nowlin 	kfree(rm);
5486fd2a6b71SDan Nowlin 
5487fd2a6b71SDan Nowlin err_free_lkup_exts:
5488fd2a6b71SDan Nowlin 	kfree(lkup_exts);
5489fd2a6b71SDan Nowlin 
5490fd2a6b71SDan Nowlin 	return status;
5491fd2a6b71SDan Nowlin }
5492fd2a6b71SDan Nowlin 
5493148beb61SHenry Tieman /**
549426395726SMartyna Szapar-Mudlaw  * ice_dummy_packet_add_vlan - insert VLAN header to dummy pkt
549526395726SMartyna Szapar-Mudlaw  *
549626395726SMartyna Szapar-Mudlaw  * @dummy_pkt: dummy packet profile pattern to which VLAN tag(s) will be added
549726395726SMartyna Szapar-Mudlaw  * @num_vlan: number of VLAN tags
549826395726SMartyna Szapar-Mudlaw  */
549926395726SMartyna Szapar-Mudlaw static struct ice_dummy_pkt_profile *
ice_dummy_packet_add_vlan(const struct ice_dummy_pkt_profile * dummy_pkt,u32 num_vlan)550026395726SMartyna Szapar-Mudlaw ice_dummy_packet_add_vlan(const struct ice_dummy_pkt_profile *dummy_pkt,
550126395726SMartyna Szapar-Mudlaw 			  u32 num_vlan)
550226395726SMartyna Szapar-Mudlaw {
550326395726SMartyna Szapar-Mudlaw 	struct ice_dummy_pkt_profile *profile;
550426395726SMartyna Szapar-Mudlaw 	struct ice_dummy_pkt_offsets *offsets;
550526395726SMartyna Szapar-Mudlaw 	u32 buf_len, off, etype_off, i;
550626395726SMartyna Szapar-Mudlaw 	u8 *pkt;
550726395726SMartyna Szapar-Mudlaw 
550826395726SMartyna Szapar-Mudlaw 	if (num_vlan < 1 || num_vlan > 2)
550926395726SMartyna Szapar-Mudlaw 		return ERR_PTR(-EINVAL);
551026395726SMartyna Szapar-Mudlaw 
551126395726SMartyna Szapar-Mudlaw 	off = num_vlan * VLAN_HLEN;
551226395726SMartyna Szapar-Mudlaw 
551326395726SMartyna Szapar-Mudlaw 	buf_len = array_size(num_vlan, sizeof(ice_dummy_vlan_packet_offsets)) +
551426395726SMartyna Szapar-Mudlaw 		  dummy_pkt->offsets_len;
551526395726SMartyna Szapar-Mudlaw 	offsets = kzalloc(buf_len, GFP_KERNEL);
551626395726SMartyna Szapar-Mudlaw 	if (!offsets)
551726395726SMartyna Szapar-Mudlaw 		return ERR_PTR(-ENOMEM);
551826395726SMartyna Szapar-Mudlaw 
551926395726SMartyna Szapar-Mudlaw 	offsets[0] = dummy_pkt->offsets[0];
552026395726SMartyna Szapar-Mudlaw 	if (num_vlan == 2) {
552126395726SMartyna Szapar-Mudlaw 		offsets[1] = ice_dummy_qinq_packet_offsets[0];
552226395726SMartyna Szapar-Mudlaw 		offsets[2] = ice_dummy_qinq_packet_offsets[1];
552326395726SMartyna Szapar-Mudlaw 	} else if (num_vlan == 1) {
552426395726SMartyna Szapar-Mudlaw 		offsets[1] = ice_dummy_vlan_packet_offsets[0];
552526395726SMartyna Szapar-Mudlaw 	}
552626395726SMartyna Szapar-Mudlaw 
552726395726SMartyna Szapar-Mudlaw 	for (i = 1; dummy_pkt->offsets[i].type != ICE_PROTOCOL_LAST; i++) {
552826395726SMartyna Szapar-Mudlaw 		offsets[i + num_vlan].type = dummy_pkt->offsets[i].type;
552926395726SMartyna Szapar-Mudlaw 		offsets[i + num_vlan].offset =
553026395726SMartyna Szapar-Mudlaw 			dummy_pkt->offsets[i].offset + off;
553126395726SMartyna Szapar-Mudlaw 	}
553226395726SMartyna Szapar-Mudlaw 	offsets[i + num_vlan] = dummy_pkt->offsets[i];
553326395726SMartyna Szapar-Mudlaw 
553426395726SMartyna Szapar-Mudlaw 	etype_off = dummy_pkt->offsets[1].offset;
553526395726SMartyna Szapar-Mudlaw 
553626395726SMartyna Szapar-Mudlaw 	buf_len = array_size(num_vlan, sizeof(ice_dummy_vlan_packet)) +
553726395726SMartyna Szapar-Mudlaw 		  dummy_pkt->pkt_len;
553826395726SMartyna Szapar-Mudlaw 	pkt = kzalloc(buf_len, GFP_KERNEL);
553926395726SMartyna Szapar-Mudlaw 	if (!pkt) {
554026395726SMartyna Szapar-Mudlaw 		kfree(offsets);
554126395726SMartyna Szapar-Mudlaw 		return ERR_PTR(-ENOMEM);
554226395726SMartyna Szapar-Mudlaw 	}
554326395726SMartyna Szapar-Mudlaw 
554426395726SMartyna Szapar-Mudlaw 	memcpy(pkt, dummy_pkt->pkt, etype_off);
554526395726SMartyna Szapar-Mudlaw 	memcpy(pkt + etype_off,
554626395726SMartyna Szapar-Mudlaw 	       num_vlan == 2 ? ice_dummy_qinq_packet : ice_dummy_vlan_packet,
554726395726SMartyna Szapar-Mudlaw 	       off);
554826395726SMartyna Szapar-Mudlaw 	memcpy(pkt + etype_off + off, dummy_pkt->pkt + etype_off,
554926395726SMartyna Szapar-Mudlaw 	       dummy_pkt->pkt_len - etype_off);
555026395726SMartyna Szapar-Mudlaw 
555126395726SMartyna Szapar-Mudlaw 	profile = kzalloc(sizeof(*profile), GFP_KERNEL);
555226395726SMartyna Szapar-Mudlaw 	if (!profile) {
555326395726SMartyna Szapar-Mudlaw 		kfree(offsets);
555426395726SMartyna Szapar-Mudlaw 		kfree(pkt);
555526395726SMartyna Szapar-Mudlaw 		return ERR_PTR(-ENOMEM);
555626395726SMartyna Szapar-Mudlaw 	}
555726395726SMartyna Szapar-Mudlaw 
555826395726SMartyna Szapar-Mudlaw 	profile->offsets = offsets;
555926395726SMartyna Szapar-Mudlaw 	profile->pkt = pkt;
556026395726SMartyna Szapar-Mudlaw 	profile->pkt_len = buf_len;
556126395726SMartyna Szapar-Mudlaw 	profile->match |= ICE_PKT_KMALLOC;
556226395726SMartyna Szapar-Mudlaw 
556326395726SMartyna Szapar-Mudlaw 	return profile;
556426395726SMartyna Szapar-Mudlaw }
556526395726SMartyna Szapar-Mudlaw 
556626395726SMartyna Szapar-Mudlaw /**
55670f94570dSGrishma Kotecha  * ice_find_dummy_packet - find dummy packet
55680f94570dSGrishma Kotecha  *
55690f94570dSGrishma Kotecha  * @lkups: lookup elements or match criteria for the advanced recipe, one
55700f94570dSGrishma Kotecha  *	   structure per protocol header
55710f94570dSGrishma Kotecha  * @lkups_cnt: number of protocols
55728b032a55SMichal Swiatkowski  * @tun_type: tunnel type
55731b699f81SAlexander Lobakin  *
55741b699f81SAlexander Lobakin  * Returns the &ice_dummy_pkt_profile corresponding to these lookup params.
55750f94570dSGrishma Kotecha  */
5576e33163a4SAlexander Lobakin static const struct ice_dummy_pkt_profile *
ice_find_dummy_packet(struct ice_adv_lkup_elem * lkups,u16 lkups_cnt,enum ice_sw_tunnel_type tun_type)55770f94570dSGrishma Kotecha ice_find_dummy_packet(struct ice_adv_lkup_elem *lkups, u16 lkups_cnt,
55781b699f81SAlexander Lobakin 		      enum ice_sw_tunnel_type tun_type)
55790f94570dSGrishma Kotecha {
5580e33163a4SAlexander Lobakin 	const struct ice_dummy_pkt_profile *ret = ice_dummy_pkt_profiles;
558126395726SMartyna Szapar-Mudlaw 	u32 match = 0, vlan_count = 0;
55820f94570dSGrishma Kotecha 	u16 i;
55830f94570dSGrishma Kotecha 
5584e33163a4SAlexander Lobakin 	switch (tun_type) {
5585e33163a4SAlexander Lobakin 	case ICE_SW_TUN_GTPC:
5586e33163a4SAlexander Lobakin 		match |= ICE_PKT_TUN_GTPC;
5587e33163a4SAlexander Lobakin 		break;
5588e33163a4SAlexander Lobakin 	case ICE_SW_TUN_GTPU:
5589e33163a4SAlexander Lobakin 		match |= ICE_PKT_TUN_GTPU;
5590e33163a4SAlexander Lobakin 		break;
5591e33163a4SAlexander Lobakin 	case ICE_SW_TUN_NVGRE:
5592e33163a4SAlexander Lobakin 		match |= ICE_PKT_TUN_NVGRE;
5593e33163a4SAlexander Lobakin 		break;
5594e33163a4SAlexander Lobakin 	case ICE_SW_TUN_GENEVE:
5595e33163a4SAlexander Lobakin 	case ICE_SW_TUN_VXLAN:
5596e33163a4SAlexander Lobakin 		match |= ICE_PKT_TUN_UDP;
5597e33163a4SAlexander Lobakin 		break;
5598e33163a4SAlexander Lobakin 	default:
5599e33163a4SAlexander Lobakin 		break;
5600e33163a4SAlexander Lobakin 	}
5601e33163a4SAlexander Lobakin 
56020f94570dSGrishma Kotecha 	for (i = 0; i < lkups_cnt; i++) {
56030f94570dSGrishma Kotecha 		if (lkups[i].type == ICE_UDP_ILOS)
5604e33163a4SAlexander Lobakin 			match |= ICE_PKT_INNER_UDP;
56050f94570dSGrishma Kotecha 		else if (lkups[i].type == ICE_TCP_IL)
5606e33163a4SAlexander Lobakin 			match |= ICE_PKT_INNER_TCP;
56070f94570dSGrishma Kotecha 		else if (lkups[i].type == ICE_IPV6_OFOS)
5608e33163a4SAlexander Lobakin 			match |= ICE_PKT_OUTER_IPV6;
560906bca7c2SMartyna Szapar-Mudlaw 		else if (lkups[i].type == ICE_VLAN_OFOS ||
561006bca7c2SMartyna Szapar-Mudlaw 			 lkups[i].type == ICE_VLAN_EX)
561126395726SMartyna Szapar-Mudlaw 			vlan_count++;
561206bca7c2SMartyna Szapar-Mudlaw 		else if (lkups[i].type == ICE_VLAN_IN)
561326395726SMartyna Szapar-Mudlaw 			vlan_count++;
56140f94570dSGrishma Kotecha 		else if (lkups[i].type == ICE_ETYPE_OL &&
56150f94570dSGrishma Kotecha 			 lkups[i].h_u.ethertype.ethtype_id ==
56160f94570dSGrishma Kotecha 				cpu_to_be16(ICE_IPV6_ETHER_ID) &&
56170f94570dSGrishma Kotecha 			 lkups[i].m_u.ethertype.ethtype_id ==
56180f94570dSGrishma Kotecha 				cpu_to_be16(0xFFFF))
5619e33163a4SAlexander Lobakin 			match |= ICE_PKT_OUTER_IPV6;
562034a89775SMartyna Szapar-Mudlaw 		else if (lkups[i].type == ICE_ETYPE_IL &&
562134a89775SMartyna Szapar-Mudlaw 			 lkups[i].h_u.ethertype.ethtype_id ==
562234a89775SMartyna Szapar-Mudlaw 				cpu_to_be16(ICE_IPV6_ETHER_ID) &&
562334a89775SMartyna Szapar-Mudlaw 			 lkups[i].m_u.ethertype.ethtype_id ==
562434a89775SMartyna Szapar-Mudlaw 				cpu_to_be16(0xFFFF))
5625e33163a4SAlexander Lobakin 			match |= ICE_PKT_INNER_IPV6;
56269a225f81SMarcin Szycik 		else if (lkups[i].type == ICE_IPV6_IL)
5627e33163a4SAlexander Lobakin 			match |= ICE_PKT_INNER_IPV6;
56289a225f81SMarcin Szycik 		else if (lkups[i].type == ICE_GTP_NO_PAY)
5629e33163a4SAlexander Lobakin 			match |= ICE_PKT_GTP_NOPAY;
5630cd8efeeeSMarcin Szycik 		else if (lkups[i].type == ICE_PPPOE) {
5631cd8efeeeSMarcin Szycik 			match |= ICE_PKT_PPPOE;
5632cd8efeeeSMarcin Szycik 			if (lkups[i].h_u.pppoe_hdr.ppp_prot_id ==
5633cd8efeeeSMarcin Szycik 			    htons(PPP_IPV6))
5634cd8efeeeSMarcin Szycik 				match |= ICE_PKT_OUTER_IPV6;
5635cd634549SMarcin Szycik 		} else if (lkups[i].type == ICE_L2TPV3)
5636cd634549SMarcin Szycik 			match |= ICE_PKT_L2TPV3;
56379a225f81SMarcin Szycik 	}
56389a225f81SMarcin Szycik 
5639e33163a4SAlexander Lobakin 	while (ret->match && (match & ret->match) != ret->match)
5640e33163a4SAlexander Lobakin 		ret++;
56419a225f81SMarcin Szycik 
564226395726SMartyna Szapar-Mudlaw 	if (vlan_count != 0)
564326395726SMartyna Szapar-Mudlaw 		ret = ice_dummy_packet_add_vlan(ret, vlan_count);
564426395726SMartyna Szapar-Mudlaw 
5645e33163a4SAlexander Lobakin 	return ret;
56460f94570dSGrishma Kotecha }
56470f94570dSGrishma Kotecha 
56480f94570dSGrishma Kotecha /**
56490f94570dSGrishma Kotecha  * ice_fill_adv_dummy_packet - fill a dummy packet with given match criteria
56500f94570dSGrishma Kotecha  *
56510f94570dSGrishma Kotecha  * @lkups: lookup elements or match criteria for the advanced recipe, one
56520f94570dSGrishma Kotecha  *	   structure per protocol header
56530f94570dSGrishma Kotecha  * @lkups_cnt: number of protocols
56540f94570dSGrishma Kotecha  * @s_rule: stores rule information from the match criteria
56551b699f81SAlexander Lobakin  * @profile: dummy packet profile (the template, its size and header offsets)
56560f94570dSGrishma Kotecha  */
56575e24d598STony Nguyen static int
ice_fill_adv_dummy_packet(struct ice_adv_lkup_elem * lkups,u16 lkups_cnt,struct ice_sw_rule_lkup_rx_tx * s_rule,const struct ice_dummy_pkt_profile * profile)56580f94570dSGrishma Kotecha ice_fill_adv_dummy_packet(struct ice_adv_lkup_elem *lkups, u16 lkups_cnt,
56596e1ff618SAlexander Lobakin 			  struct ice_sw_rule_lkup_rx_tx *s_rule,
56601b699f81SAlexander Lobakin 			  const struct ice_dummy_pkt_profile *profile)
56610f94570dSGrishma Kotecha {
56620f94570dSGrishma Kotecha 	u8 *pkt;
56630f94570dSGrishma Kotecha 	u16 i;
56640f94570dSGrishma Kotecha 
56650f94570dSGrishma Kotecha 	/* Start with a packet with a pre-defined/dummy content. Then, fill
56660f94570dSGrishma Kotecha 	 * in the header values to be looked up or matched.
56670f94570dSGrishma Kotecha 	 */
56686e1ff618SAlexander Lobakin 	pkt = s_rule->hdr_data;
56690f94570dSGrishma Kotecha 
56701b699f81SAlexander Lobakin 	memcpy(pkt, profile->pkt, profile->pkt_len);
56710f94570dSGrishma Kotecha 
56720f94570dSGrishma Kotecha 	for (i = 0; i < lkups_cnt; i++) {
56731b699f81SAlexander Lobakin 		const struct ice_dummy_pkt_offsets *offsets = profile->offsets;
56740f94570dSGrishma Kotecha 		enum ice_protocol_type type;
56750f94570dSGrishma Kotecha 		u16 offset = 0, len = 0, j;
56760f94570dSGrishma Kotecha 		bool found = false;
56770f94570dSGrishma Kotecha 
56780f94570dSGrishma Kotecha 		/* find the start of this layer; it should be found since this
56790f94570dSGrishma Kotecha 		 * was already checked when search for the dummy packet
56800f94570dSGrishma Kotecha 		 */
56810f94570dSGrishma Kotecha 		type = lkups[i].type;
568203592a14SMichal Swiatkowski 		/* metadata isn't present in the packet */
568303592a14SMichal Swiatkowski 		if (type == ICE_HW_METADATA)
568403592a14SMichal Swiatkowski 			continue;
568503592a14SMichal Swiatkowski 
56860f94570dSGrishma Kotecha 		for (j = 0; offsets[j].type != ICE_PROTOCOL_LAST; j++) {
56870f94570dSGrishma Kotecha 			if (type == offsets[j].type) {
56880f94570dSGrishma Kotecha 				offset = offsets[j].offset;
56890f94570dSGrishma Kotecha 				found = true;
56900f94570dSGrishma Kotecha 				break;
56910f94570dSGrishma Kotecha 			}
56920f94570dSGrishma Kotecha 		}
56930f94570dSGrishma Kotecha 		/* this should never happen in a correct calling sequence */
56940f94570dSGrishma Kotecha 		if (!found)
5695d54699e2STony Nguyen 			return -EINVAL;
56960f94570dSGrishma Kotecha 
56970f94570dSGrishma Kotecha 		switch (lkups[i].type) {
56980f94570dSGrishma Kotecha 		case ICE_MAC_OFOS:
56990f94570dSGrishma Kotecha 		case ICE_MAC_IL:
57000f94570dSGrishma Kotecha 			len = sizeof(struct ice_ether_hdr);
57010f94570dSGrishma Kotecha 			break;
57020f94570dSGrishma Kotecha 		case ICE_ETYPE_OL:
570334a89775SMartyna Szapar-Mudlaw 		case ICE_ETYPE_IL:
57040f94570dSGrishma Kotecha 			len = sizeof(struct ice_ethtype_hdr);
57050f94570dSGrishma Kotecha 			break;
57060f94570dSGrishma Kotecha 		case ICE_VLAN_OFOS:
570706bca7c2SMartyna Szapar-Mudlaw 		case ICE_VLAN_EX:
570806bca7c2SMartyna Szapar-Mudlaw 		case ICE_VLAN_IN:
57090f94570dSGrishma Kotecha 			len = sizeof(struct ice_vlan_hdr);
57100f94570dSGrishma Kotecha 			break;
57110f94570dSGrishma Kotecha 		case ICE_IPV4_OFOS:
57120f94570dSGrishma Kotecha 		case ICE_IPV4_IL:
57130f94570dSGrishma Kotecha 			len = sizeof(struct ice_ipv4_hdr);
57140f94570dSGrishma Kotecha 			break;
57150f94570dSGrishma Kotecha 		case ICE_IPV6_OFOS:
57160f94570dSGrishma Kotecha 		case ICE_IPV6_IL:
57170f94570dSGrishma Kotecha 			len = sizeof(struct ice_ipv6_hdr);
57180f94570dSGrishma Kotecha 			break;
57190f94570dSGrishma Kotecha 		case ICE_TCP_IL:
57200f94570dSGrishma Kotecha 		case ICE_UDP_OF:
57210f94570dSGrishma Kotecha 		case ICE_UDP_ILOS:
57220f94570dSGrishma Kotecha 			len = sizeof(struct ice_l4_hdr);
57230f94570dSGrishma Kotecha 			break;
57240f94570dSGrishma Kotecha 		case ICE_SCTP_IL:
57250f94570dSGrishma Kotecha 			len = sizeof(struct ice_sctp_hdr);
57260f94570dSGrishma Kotecha 			break;
5727f0a35040SMichal Swiatkowski 		case ICE_NVGRE:
5728f0a35040SMichal Swiatkowski 			len = sizeof(struct ice_nvgre_hdr);
5729f0a35040SMichal Swiatkowski 			break;
57308b032a55SMichal Swiatkowski 		case ICE_VXLAN:
57318b032a55SMichal Swiatkowski 		case ICE_GENEVE:
57328b032a55SMichal Swiatkowski 			len = sizeof(struct ice_udp_tnl_hdr);
57338b032a55SMichal Swiatkowski 			break;
57349a225f81SMarcin Szycik 		case ICE_GTP_NO_PAY:
57359a225f81SMarcin Szycik 		case ICE_GTP:
57369a225f81SMarcin Szycik 			len = sizeof(struct ice_udp_gtp_hdr);
57379a225f81SMarcin Szycik 			break;
5738cd8efeeeSMarcin Szycik 		case ICE_PPPOE:
5739cd8efeeeSMarcin Szycik 			len = sizeof(struct ice_pppoe_hdr);
5740cd8efeeeSMarcin Szycik 			break;
5741cd634549SMarcin Szycik 		case ICE_L2TPV3:
5742cd634549SMarcin Szycik 			len = sizeof(struct ice_l2tpv3_sess_hdr);
5743cd634549SMarcin Szycik 			break;
57440f94570dSGrishma Kotecha 		default:
5745d54699e2STony Nguyen 			return -EINVAL;
57460f94570dSGrishma Kotecha 		}
57470f94570dSGrishma Kotecha 
57480f94570dSGrishma Kotecha 		/* the length should be a word multiple */
57490f94570dSGrishma Kotecha 		if (len % ICE_BYTES_PER_WORD)
5750d54699e2STony Nguyen 			return -EIO;
57510f94570dSGrishma Kotecha 
57520f94570dSGrishma Kotecha 		/* We have the offset to the header start, the length, the
57530f94570dSGrishma Kotecha 		 * caller's header values and mask. Use this information to
57540f94570dSGrishma Kotecha 		 * copy the data into the dummy packet appropriately based on
57550f94570dSGrishma Kotecha 		 * the mask. Note that we need to only write the bits as
57560f94570dSGrishma Kotecha 		 * indicated by the mask to make sure we don't improperly write
57570f94570dSGrishma Kotecha 		 * over any significant packet data.
57580f94570dSGrishma Kotecha 		 */
575927ffa273SAlexander Lobakin 		for (j = 0; j < len / sizeof(u16); j++) {
576027ffa273SAlexander Lobakin 			u16 *ptr = (u16 *)(pkt + offset);
576127ffa273SAlexander Lobakin 			u16 mask = lkups[i].m_raw[j];
576227ffa273SAlexander Lobakin 
576327ffa273SAlexander Lobakin 			if (!mask)
576427ffa273SAlexander Lobakin 				continue;
576527ffa273SAlexander Lobakin 
576627ffa273SAlexander Lobakin 			ptr[j] = (ptr[j] & ~mask) | (lkups[i].h_raw[j] & mask);
576727ffa273SAlexander Lobakin 		}
57680f94570dSGrishma Kotecha 	}
57690f94570dSGrishma Kotecha 
57706e1ff618SAlexander Lobakin 	s_rule->hdr_len = cpu_to_le16(profile->pkt_len);
57710f94570dSGrishma Kotecha 
57720f94570dSGrishma Kotecha 	return 0;
57730f94570dSGrishma Kotecha }
57740f94570dSGrishma Kotecha 
57750f94570dSGrishma Kotecha /**
57768b032a55SMichal Swiatkowski  * ice_fill_adv_packet_tun - fill dummy packet with udp tunnel port
57778b032a55SMichal Swiatkowski  * @hw: pointer to the hardware structure
57788b032a55SMichal Swiatkowski  * @tun_type: tunnel type
57798b032a55SMichal Swiatkowski  * @pkt: dummy packet to fill in
57808b032a55SMichal Swiatkowski  * @offsets: offset info for the dummy packet
57818b032a55SMichal Swiatkowski  */
5782d54699e2STony Nguyen static int
ice_fill_adv_packet_tun(struct ice_hw * hw,enum ice_sw_tunnel_type tun_type,u8 * pkt,const struct ice_dummy_pkt_offsets * offsets)57838b032a55SMichal Swiatkowski ice_fill_adv_packet_tun(struct ice_hw *hw, enum ice_sw_tunnel_type tun_type,
57848b032a55SMichal Swiatkowski 			u8 *pkt, const struct ice_dummy_pkt_offsets *offsets)
57858b032a55SMichal Swiatkowski {
57868b032a55SMichal Swiatkowski 	u16 open_port, i;
57878b032a55SMichal Swiatkowski 
57888b032a55SMichal Swiatkowski 	switch (tun_type) {
57898b032a55SMichal Swiatkowski 	case ICE_SW_TUN_VXLAN:
5790de6acd1cSMichal Swiatkowski 		if (!ice_get_open_tunnel_port(hw, &open_port, TNL_VXLAN))
5791d54699e2STony Nguyen 			return -EIO;
57928b032a55SMichal Swiatkowski 		break;
5793de6acd1cSMichal Swiatkowski 	case ICE_SW_TUN_GENEVE:
5794de6acd1cSMichal Swiatkowski 		if (!ice_get_open_tunnel_port(hw, &open_port, TNL_GENEVE))
5795d54699e2STony Nguyen 			return -EIO;
5796de6acd1cSMichal Swiatkowski 		break;
57978b032a55SMichal Swiatkowski 	default:
57988b032a55SMichal Swiatkowski 		/* Nothing needs to be done for this tunnel type */
57998b032a55SMichal Swiatkowski 		return 0;
58008b032a55SMichal Swiatkowski 	}
58018b032a55SMichal Swiatkowski 
58028b032a55SMichal Swiatkowski 	/* Find the outer UDP protocol header and insert the port number */
58038b032a55SMichal Swiatkowski 	for (i = 0; offsets[i].type != ICE_PROTOCOL_LAST; i++) {
58048b032a55SMichal Swiatkowski 		if (offsets[i].type == ICE_UDP_OF) {
58058b032a55SMichal Swiatkowski 			struct ice_l4_hdr *hdr;
58068b032a55SMichal Swiatkowski 			u16 offset;
58078b032a55SMichal Swiatkowski 
58088b032a55SMichal Swiatkowski 			offset = offsets[i].offset;
58098b032a55SMichal Swiatkowski 			hdr = (struct ice_l4_hdr *)&pkt[offset];
58108b032a55SMichal Swiatkowski 			hdr->dst_port = cpu_to_be16(open_port);
58118b032a55SMichal Swiatkowski 
58128b032a55SMichal Swiatkowski 			return 0;
58138b032a55SMichal Swiatkowski 		}
58148b032a55SMichal Swiatkowski 	}
58158b032a55SMichal Swiatkowski 
5816d54699e2STony Nguyen 	return -EIO;
58178b032a55SMichal Swiatkowski }
58188b032a55SMichal Swiatkowski 
58198b032a55SMichal Swiatkowski /**
5820ea71b967SMartyna Szapar-Mudlaw  * ice_fill_adv_packet_vlan - fill dummy packet with VLAN tag type
582103592a14SMichal Swiatkowski  * @hw: pointer to hw structure
5822ea71b967SMartyna Szapar-Mudlaw  * @vlan_type: VLAN tag type
5823ea71b967SMartyna Szapar-Mudlaw  * @pkt: dummy packet to fill in
5824ea71b967SMartyna Szapar-Mudlaw  * @offsets: offset info for the dummy packet
5825ea71b967SMartyna Szapar-Mudlaw  */
5826ea71b967SMartyna Szapar-Mudlaw static int
ice_fill_adv_packet_vlan(struct ice_hw * hw,u16 vlan_type,u8 * pkt,const struct ice_dummy_pkt_offsets * offsets)582703592a14SMichal Swiatkowski ice_fill_adv_packet_vlan(struct ice_hw *hw, u16 vlan_type, u8 *pkt,
5828ea71b967SMartyna Szapar-Mudlaw 			 const struct ice_dummy_pkt_offsets *offsets)
5829ea71b967SMartyna Szapar-Mudlaw {
5830ea71b967SMartyna Szapar-Mudlaw 	u16 i;
5831ea71b967SMartyna Szapar-Mudlaw 
583203592a14SMichal Swiatkowski 	/* Check if there is something to do */
583303592a14SMichal Swiatkowski 	if (!vlan_type || !ice_is_dvm_ena(hw))
583403592a14SMichal Swiatkowski 		return 0;
583503592a14SMichal Swiatkowski 
5836ea71b967SMartyna Szapar-Mudlaw 	/* Find VLAN header and insert VLAN TPID */
5837ea71b967SMartyna Szapar-Mudlaw 	for (i = 0; offsets[i].type != ICE_PROTOCOL_LAST; i++) {
5838ea71b967SMartyna Szapar-Mudlaw 		if (offsets[i].type == ICE_VLAN_OFOS ||
5839ea71b967SMartyna Szapar-Mudlaw 		    offsets[i].type == ICE_VLAN_EX) {
5840ea71b967SMartyna Szapar-Mudlaw 			struct ice_vlan_hdr *hdr;
5841ea71b967SMartyna Szapar-Mudlaw 			u16 offset;
5842ea71b967SMartyna Szapar-Mudlaw 
5843ea71b967SMartyna Szapar-Mudlaw 			offset = offsets[i].offset;
5844ea71b967SMartyna Szapar-Mudlaw 			hdr = (struct ice_vlan_hdr *)&pkt[offset];
5845ea71b967SMartyna Szapar-Mudlaw 			hdr->type = cpu_to_be16(vlan_type);
5846ea71b967SMartyna Szapar-Mudlaw 
5847ea71b967SMartyna Szapar-Mudlaw 			return 0;
5848ea71b967SMartyna Szapar-Mudlaw 		}
5849ea71b967SMartyna Szapar-Mudlaw 	}
5850ea71b967SMartyna Szapar-Mudlaw 
5851ea71b967SMartyna Szapar-Mudlaw 	return -EIO;
5852ea71b967SMartyna Szapar-Mudlaw }
5853ea71b967SMartyna Szapar-Mudlaw 
ice_rules_equal(const struct ice_adv_rule_info * first,const struct ice_adv_rule_info * second)585403592a14SMichal Swiatkowski static bool ice_rules_equal(const struct ice_adv_rule_info *first,
585503592a14SMichal Swiatkowski 			    const struct ice_adv_rule_info *second)
585603592a14SMichal Swiatkowski {
585703592a14SMichal Swiatkowski 	return first->sw_act.flag == second->sw_act.flag &&
585803592a14SMichal Swiatkowski 	       first->tun_type == second->tun_type &&
585903592a14SMichal Swiatkowski 	       first->vlan_type == second->vlan_type &&
5860bccd9bceSMarcin Szycik 	       first->src_vsi == second->src_vsi &&
5861bccd9bceSMarcin Szycik 	       first->need_pass_l2 == second->need_pass_l2 &&
5862bccd9bceSMarcin Szycik 	       first->allow_pass_l2 == second->allow_pass_l2;
586303592a14SMichal Swiatkowski }
586403592a14SMichal Swiatkowski 
5865ea71b967SMartyna Szapar-Mudlaw /**
58660f94570dSGrishma Kotecha  * ice_find_adv_rule_entry - Search a rule entry
58670f94570dSGrishma Kotecha  * @hw: pointer to the hardware structure
58680f94570dSGrishma Kotecha  * @lkups: lookup elements or match criteria for the advanced recipe, one
58690f94570dSGrishma Kotecha  *	   structure per protocol header
58700f94570dSGrishma Kotecha  * @lkups_cnt: number of protocols
58710f94570dSGrishma Kotecha  * @recp_id: recipe ID for which we are finding the rule
58720f94570dSGrishma Kotecha  * @rinfo: other information regarding the rule e.g. priority and action info
58730f94570dSGrishma Kotecha  *
58740f94570dSGrishma Kotecha  * Helper function to search for a given advance rule entry
58750f94570dSGrishma Kotecha  * Returns pointer to entry storing the rule if found
58760f94570dSGrishma Kotecha  */
58770f94570dSGrishma Kotecha static struct ice_adv_fltr_mgmt_list_entry *
ice_find_adv_rule_entry(struct ice_hw * hw,struct ice_adv_lkup_elem * lkups,u16 lkups_cnt,u16 recp_id,struct ice_adv_rule_info * rinfo)58780f94570dSGrishma Kotecha ice_find_adv_rule_entry(struct ice_hw *hw, struct ice_adv_lkup_elem *lkups,
58790f94570dSGrishma Kotecha 			u16 lkups_cnt, u16 recp_id,
58800f94570dSGrishma Kotecha 			struct ice_adv_rule_info *rinfo)
58810f94570dSGrishma Kotecha {
58820f94570dSGrishma Kotecha 	struct ice_adv_fltr_mgmt_list_entry *list_itr;
58830f94570dSGrishma Kotecha 	struct ice_switch_info *sw = hw->switch_info;
58840f94570dSGrishma Kotecha 	int i;
58850f94570dSGrishma Kotecha 
58860f94570dSGrishma Kotecha 	list_for_each_entry(list_itr, &sw->recp_list[recp_id].filt_rules,
58870f94570dSGrishma Kotecha 			    list_entry) {
58880f94570dSGrishma Kotecha 		bool lkups_matched = true;
58890f94570dSGrishma Kotecha 
58900f94570dSGrishma Kotecha 		if (lkups_cnt != list_itr->lkups_cnt)
58910f94570dSGrishma Kotecha 			continue;
58920f94570dSGrishma Kotecha 		for (i = 0; i < list_itr->lkups_cnt; i++)
58930f94570dSGrishma Kotecha 			if (memcmp(&list_itr->lkups[i], &lkups[i],
58940f94570dSGrishma Kotecha 				   sizeof(*lkups))) {
58950f94570dSGrishma Kotecha 				lkups_matched = false;
58960f94570dSGrishma Kotecha 				break;
58970f94570dSGrishma Kotecha 			}
589803592a14SMichal Swiatkowski 		if (ice_rules_equal(rinfo, &list_itr->rule_info) &&
58990f94570dSGrishma Kotecha 		    lkups_matched)
59000f94570dSGrishma Kotecha 			return list_itr;
59010f94570dSGrishma Kotecha 	}
59020f94570dSGrishma Kotecha 	return NULL;
59030f94570dSGrishma Kotecha }
59040f94570dSGrishma Kotecha 
59050f94570dSGrishma Kotecha /**
59060f94570dSGrishma Kotecha  * ice_adv_add_update_vsi_list
59070f94570dSGrishma Kotecha  * @hw: pointer to the hardware structure
59080f94570dSGrishma Kotecha  * @m_entry: pointer to current adv filter management list entry
59090f94570dSGrishma Kotecha  * @cur_fltr: filter information from the book keeping entry
59100f94570dSGrishma Kotecha  * @new_fltr: filter information with the new VSI to be added
59110f94570dSGrishma Kotecha  *
59120f94570dSGrishma Kotecha  * Call AQ command to add or update previously created VSI list with new VSI.
59130f94570dSGrishma Kotecha  *
59140f94570dSGrishma Kotecha  * Helper function to do book keeping associated with adding filter information
59150f94570dSGrishma Kotecha  * The algorithm to do the booking keeping is described below :
59160f94570dSGrishma Kotecha  * When a VSI needs to subscribe to a given advanced filter
59170f94570dSGrishma Kotecha  *	if only one VSI has been added till now
59180f94570dSGrishma Kotecha  *		Allocate a new VSI list and add two VSIs
59190f94570dSGrishma Kotecha  *		to this list using switch rule command
59200f94570dSGrishma Kotecha  *		Update the previously created switch rule with the
59210f94570dSGrishma Kotecha  *		newly created VSI list ID
59220f94570dSGrishma Kotecha  *	if a VSI list was previously created
59230f94570dSGrishma Kotecha  *		Add the new VSI to the previously created VSI list set
59240f94570dSGrishma Kotecha  *		using the update switch rule command
59250f94570dSGrishma Kotecha  */
59265e24d598STony Nguyen static int
ice_adv_add_update_vsi_list(struct ice_hw * hw,struct ice_adv_fltr_mgmt_list_entry * m_entry,struct ice_adv_rule_info * cur_fltr,struct ice_adv_rule_info * new_fltr)59270f94570dSGrishma Kotecha ice_adv_add_update_vsi_list(struct ice_hw *hw,
59280f94570dSGrishma Kotecha 			    struct ice_adv_fltr_mgmt_list_entry *m_entry,
59290f94570dSGrishma Kotecha 			    struct ice_adv_rule_info *cur_fltr,
59300f94570dSGrishma Kotecha 			    struct ice_adv_rule_info *new_fltr)
59310f94570dSGrishma Kotecha {
59320f94570dSGrishma Kotecha 	u16 vsi_list_id = 0;
59335518ac2aSTony Nguyen 	int status;
59340f94570dSGrishma Kotecha 
59350f94570dSGrishma Kotecha 	if (cur_fltr->sw_act.fltr_act == ICE_FWD_TO_Q ||
59360f94570dSGrishma Kotecha 	    cur_fltr->sw_act.fltr_act == ICE_FWD_TO_QGRP ||
59370f94570dSGrishma Kotecha 	    cur_fltr->sw_act.fltr_act == ICE_DROP_PACKET)
5938d54699e2STony Nguyen 		return -EOPNOTSUPP;
59390f94570dSGrishma Kotecha 
59400f94570dSGrishma Kotecha 	if ((new_fltr->sw_act.fltr_act == ICE_FWD_TO_Q ||
59410f94570dSGrishma Kotecha 	     new_fltr->sw_act.fltr_act == ICE_FWD_TO_QGRP) &&
59420f94570dSGrishma Kotecha 	    (cur_fltr->sw_act.fltr_act == ICE_FWD_TO_VSI ||
59430f94570dSGrishma Kotecha 	     cur_fltr->sw_act.fltr_act == ICE_FWD_TO_VSI_LIST))
5944d54699e2STony Nguyen 		return -EOPNOTSUPP;
59450f94570dSGrishma Kotecha 
59460f94570dSGrishma Kotecha 	if (m_entry->vsi_count < 2 && !m_entry->vsi_list_info) {
59470f94570dSGrishma Kotecha 		 /* Only one entry existed in the mapping and it was not already
59480f94570dSGrishma Kotecha 		  * a part of a VSI list. So, create a VSI list with the old and
59490f94570dSGrishma Kotecha 		  * new VSIs.
59500f94570dSGrishma Kotecha 		  */
59510f94570dSGrishma Kotecha 		struct ice_fltr_info tmp_fltr;
59520f94570dSGrishma Kotecha 		u16 vsi_handle_arr[2];
59530f94570dSGrishma Kotecha 
59540f94570dSGrishma Kotecha 		/* A rule already exists with the new VSI being added */
59550f94570dSGrishma Kotecha 		if (cur_fltr->sw_act.fwd_id.hw_vsi_id ==
59560f94570dSGrishma Kotecha 		    new_fltr->sw_act.fwd_id.hw_vsi_id)
5957d54699e2STony Nguyen 			return -EEXIST;
59580f94570dSGrishma Kotecha 
59590f94570dSGrishma Kotecha 		vsi_handle_arr[0] = cur_fltr->sw_act.vsi_handle;
59600f94570dSGrishma Kotecha 		vsi_handle_arr[1] = new_fltr->sw_act.vsi_handle;
59610f94570dSGrishma Kotecha 		status = ice_create_vsi_list_rule(hw, &vsi_handle_arr[0], 2,
59620f94570dSGrishma Kotecha 						  &vsi_list_id,
59630f94570dSGrishma Kotecha 						  ICE_SW_LKUP_LAST);
59640f94570dSGrishma Kotecha 		if (status)
59650f94570dSGrishma Kotecha 			return status;
59660f94570dSGrishma Kotecha 
59670f94570dSGrishma Kotecha 		memset(&tmp_fltr, 0, sizeof(tmp_fltr));
59680f94570dSGrishma Kotecha 		tmp_fltr.flag = m_entry->rule_info.sw_act.flag;
59690f94570dSGrishma Kotecha 		tmp_fltr.fltr_rule_id = cur_fltr->fltr_rule_id;
59700f94570dSGrishma Kotecha 		tmp_fltr.fltr_act = ICE_FWD_TO_VSI_LIST;
59710f94570dSGrishma Kotecha 		tmp_fltr.fwd_id.vsi_list_id = vsi_list_id;
59720f94570dSGrishma Kotecha 		tmp_fltr.lkup_type = ICE_SW_LKUP_LAST;
59730f94570dSGrishma Kotecha 
59740f94570dSGrishma Kotecha 		/* Update the previous switch rule of "forward to VSI" to
59750f94570dSGrishma Kotecha 		 * "fwd to VSI list"
59760f94570dSGrishma Kotecha 		 */
59770f94570dSGrishma Kotecha 		status = ice_update_pkt_fwd_rule(hw, &tmp_fltr);
59780f94570dSGrishma Kotecha 		if (status)
59790f94570dSGrishma Kotecha 			return status;
59800f94570dSGrishma Kotecha 
59810f94570dSGrishma Kotecha 		cur_fltr->sw_act.fwd_id.vsi_list_id = vsi_list_id;
59820f94570dSGrishma Kotecha 		cur_fltr->sw_act.fltr_act = ICE_FWD_TO_VSI_LIST;
59830f94570dSGrishma Kotecha 		m_entry->vsi_list_info =
59840f94570dSGrishma Kotecha 			ice_create_vsi_list_map(hw, &vsi_handle_arr[0], 2,
59850f94570dSGrishma Kotecha 						vsi_list_id);
59860f94570dSGrishma Kotecha 	} else {
59870f94570dSGrishma Kotecha 		u16 vsi_handle = new_fltr->sw_act.vsi_handle;
59880f94570dSGrishma Kotecha 
59890f94570dSGrishma Kotecha 		if (!m_entry->vsi_list_info)
5990d54699e2STony Nguyen 			return -EIO;
59910f94570dSGrishma Kotecha 
59920f94570dSGrishma Kotecha 		/* A rule already exists with the new VSI being added */
59930f94570dSGrishma Kotecha 		if (test_bit(vsi_handle, m_entry->vsi_list_info->vsi_map))
59940f94570dSGrishma Kotecha 			return 0;
59950f94570dSGrishma Kotecha 
59960f94570dSGrishma Kotecha 		/* Update the previously created VSI list set with
59970f94570dSGrishma Kotecha 		 * the new VSI ID passed in
59980f94570dSGrishma Kotecha 		 */
59990f94570dSGrishma Kotecha 		vsi_list_id = cur_fltr->sw_act.fwd_id.vsi_list_id;
60000f94570dSGrishma Kotecha 
60010f94570dSGrishma Kotecha 		status = ice_update_vsi_list_rule(hw, &vsi_handle, 1,
60020f94570dSGrishma Kotecha 						  vsi_list_id, false,
60030f94570dSGrishma Kotecha 						  ice_aqc_opc_update_sw_rules,
60040f94570dSGrishma Kotecha 						  ICE_SW_LKUP_LAST);
60050f94570dSGrishma Kotecha 		/* update VSI list mapping info with new VSI ID */
60060f94570dSGrishma Kotecha 		if (!status)
60070f94570dSGrishma Kotecha 			set_bit(vsi_handle, m_entry->vsi_list_info->vsi_map);
60080f94570dSGrishma Kotecha 	}
60090f94570dSGrishma Kotecha 	if (!status)
60100f94570dSGrishma Kotecha 		m_entry->vsi_count++;
60110f94570dSGrishma Kotecha 	return status;
60120f94570dSGrishma Kotecha }
60130f94570dSGrishma Kotecha 
ice_rule_add_tunnel_metadata(struct ice_adv_lkup_elem * lkup)601403592a14SMichal Swiatkowski void ice_rule_add_tunnel_metadata(struct ice_adv_lkup_elem *lkup)
601503592a14SMichal Swiatkowski {
601603592a14SMichal Swiatkowski 	lkup->type = ICE_HW_METADATA;
601741ad9f8eSMarcin Szycik 	lkup->m_u.metadata.flags[ICE_PKT_FLAGS_MDID21] |=
601803592a14SMichal Swiatkowski 		cpu_to_be16(ICE_PKT_TUNNEL_MASK);
601903592a14SMichal Swiatkowski }
602003592a14SMichal Swiatkowski 
ice_rule_add_direction_metadata(struct ice_adv_lkup_elem * lkup)60210960a27bSMarcin Szycik void ice_rule_add_direction_metadata(struct ice_adv_lkup_elem *lkup)
60220960a27bSMarcin Szycik {
60230960a27bSMarcin Szycik 	lkup->type = ICE_HW_METADATA;
602441ad9f8eSMarcin Szycik 	lkup->m_u.metadata.flags[ICE_PKT_FLAGS_MDID20] |=
60250960a27bSMarcin Szycik 		cpu_to_be16(ICE_PKT_FROM_NETWORK);
60260960a27bSMarcin Szycik }
60270960a27bSMarcin Szycik 
ice_rule_add_vlan_metadata(struct ice_adv_lkup_elem * lkup)602803592a14SMichal Swiatkowski void ice_rule_add_vlan_metadata(struct ice_adv_lkup_elem *lkup)
602903592a14SMichal Swiatkowski {
603003592a14SMichal Swiatkowski 	lkup->type = ICE_HW_METADATA;
603141ad9f8eSMarcin Szycik 	lkup->m_u.metadata.flags[ICE_PKT_FLAGS_MDID20] |=
603203592a14SMichal Swiatkowski 		cpu_to_be16(ICE_PKT_VLAN_MASK);
603303592a14SMichal Swiatkowski }
603403592a14SMichal Swiatkowski 
ice_rule_add_src_vsi_metadata(struct ice_adv_lkup_elem * lkup)60350ef4479dSMichal Swiatkowski void ice_rule_add_src_vsi_metadata(struct ice_adv_lkup_elem *lkup)
60360ef4479dSMichal Swiatkowski {
60370ef4479dSMichal Swiatkowski 	lkup->type = ICE_HW_METADATA;
60380ef4479dSMichal Swiatkowski 	lkup->m_u.metadata.source_vsi = cpu_to_be16(ICE_MDID_SOURCE_VSI_MASK);
60390ef4479dSMichal Swiatkowski }
60400ef4479dSMichal Swiatkowski 
60410f94570dSGrishma Kotecha /**
60420f94570dSGrishma Kotecha  * ice_add_adv_rule - helper function to create an advanced switch rule
60430f94570dSGrishma Kotecha  * @hw: pointer to the hardware structure
60440f94570dSGrishma Kotecha  * @lkups: information on the words that needs to be looked up. All words
60450f94570dSGrishma Kotecha  * together makes one recipe
60460f94570dSGrishma Kotecha  * @lkups_cnt: num of entries in the lkups array
60470f94570dSGrishma Kotecha  * @rinfo: other information related to the rule that needs to be programmed
60480f94570dSGrishma Kotecha  * @added_entry: this will return recipe_id, rule_id and vsi_handle. should be
60490f94570dSGrishma Kotecha  *               ignored is case of error.
60500f94570dSGrishma Kotecha  *
60510f94570dSGrishma Kotecha  * This function can program only 1 rule at a time. The lkups is used to
60520f94570dSGrishma Kotecha  * describe the all the words that forms the "lookup" portion of the recipe.
60530f94570dSGrishma Kotecha  * These words can span multiple protocols. Callers to this function need to
60540f94570dSGrishma Kotecha  * pass in a list of protocol headers with lookup information along and mask
60550f94570dSGrishma Kotecha  * that determines which words are valid from the given protocol header.
60560f94570dSGrishma Kotecha  * rinfo describes other information related to this rule such as forwarding
60570f94570dSGrishma Kotecha  * IDs, priority of this rule, etc.
60580f94570dSGrishma Kotecha  */
60595e24d598STony Nguyen int
ice_add_adv_rule(struct ice_hw * hw,struct ice_adv_lkup_elem * lkups,u16 lkups_cnt,struct ice_adv_rule_info * rinfo,struct ice_rule_query_data * added_entry)60600f94570dSGrishma Kotecha ice_add_adv_rule(struct ice_hw *hw, struct ice_adv_lkup_elem *lkups,
60610f94570dSGrishma Kotecha 		 u16 lkups_cnt, struct ice_adv_rule_info *rinfo,
60620f94570dSGrishma Kotecha 		 struct ice_rule_query_data *added_entry)
60630f94570dSGrishma Kotecha {
60640f94570dSGrishma Kotecha 	struct ice_adv_fltr_mgmt_list_entry *m_entry, *adv_fltr = NULL;
60656e1ff618SAlexander Lobakin 	struct ice_sw_rule_lkup_rx_tx *s_rule = NULL;
6066e33163a4SAlexander Lobakin 	const struct ice_dummy_pkt_profile *profile;
60671b699f81SAlexander Lobakin 	u16 rid = 0, i, rule_buf_sz, vsi_handle;
60680f94570dSGrishma Kotecha 	struct list_head *rule_head;
60690f94570dSGrishma Kotecha 	struct ice_switch_info *sw;
60700f94570dSGrishma Kotecha 	u16 word_cnt;
60710f94570dSGrishma Kotecha 	u32 act = 0;
60725518ac2aSTony Nguyen 	int status;
60730f94570dSGrishma Kotecha 	u8 q_rgn;
60740f94570dSGrishma Kotecha 
60750f94570dSGrishma Kotecha 	/* Initialize profile to result index bitmap */
60760f94570dSGrishma Kotecha 	if (!hw->switch_info->prof_res_bm_init) {
60770f94570dSGrishma Kotecha 		hw->switch_info->prof_res_bm_init = 1;
60780f94570dSGrishma Kotecha 		ice_init_prof_result_bm(hw);
60790f94570dSGrishma Kotecha 	}
60800f94570dSGrishma Kotecha 
60810f94570dSGrishma Kotecha 	if (!lkups_cnt)
6082d54699e2STony Nguyen 		return -EINVAL;
60830f94570dSGrishma Kotecha 
60840f94570dSGrishma Kotecha 	/* get # of words we need to match */
60850f94570dSGrishma Kotecha 	word_cnt = 0;
60860f94570dSGrishma Kotecha 	for (i = 0; i < lkups_cnt; i++) {
6087135a161aSAlexander Lobakin 		u16 j;
60880f94570dSGrishma Kotecha 
6089135a161aSAlexander Lobakin 		for (j = 0; j < ARRAY_SIZE(lkups->m_raw); j++)
6090135a161aSAlexander Lobakin 			if (lkups[i].m_raw[j])
60910f94570dSGrishma Kotecha 				word_cnt++;
60920f94570dSGrishma Kotecha 	}
60930f94570dSGrishma Kotecha 
6094bd1ffe8eSWojciech Drewek 	if (!word_cnt)
6095d54699e2STony Nguyen 		return -EINVAL;
60960f94570dSGrishma Kotecha 
6097bd1ffe8eSWojciech Drewek 	if (word_cnt > ICE_MAX_CHAIN_WORDS)
6098bd1ffe8eSWojciech Drewek 		return -ENOSPC;
6099bd1ffe8eSWojciech Drewek 
61001b699f81SAlexander Lobakin 	/* locate a dummy packet */
61011b699f81SAlexander Lobakin 	profile = ice_find_dummy_packet(lkups, lkups_cnt, rinfo->tun_type);
610226395726SMartyna Szapar-Mudlaw 	if (IS_ERR(profile))
610326395726SMartyna Szapar-Mudlaw 		return PTR_ERR(profile);
61040f94570dSGrishma Kotecha 
61050f94570dSGrishma Kotecha 	if (!(rinfo->sw_act.fltr_act == ICE_FWD_TO_VSI ||
61060f94570dSGrishma Kotecha 	      rinfo->sw_act.fltr_act == ICE_FWD_TO_Q ||
61070f94570dSGrishma Kotecha 	      rinfo->sw_act.fltr_act == ICE_FWD_TO_QGRP ||
6108bccd9bceSMarcin Szycik 	      rinfo->sw_act.fltr_act == ICE_DROP_PACKET ||
6109bccd9bceSMarcin Szycik 	      rinfo->sw_act.fltr_act == ICE_NOP)) {
611026395726SMartyna Szapar-Mudlaw 		status = -EIO;
611126395726SMartyna Szapar-Mudlaw 		goto free_pkt_profile;
611226395726SMartyna Szapar-Mudlaw 	}
61130f94570dSGrishma Kotecha 
61140f94570dSGrishma Kotecha 	vsi_handle = rinfo->sw_act.vsi_handle;
611526395726SMartyna Szapar-Mudlaw 	if (!ice_is_vsi_valid(hw, vsi_handle)) {
611626395726SMartyna Szapar-Mudlaw 		status =  -EINVAL;
611726395726SMartyna Szapar-Mudlaw 		goto free_pkt_profile;
611826395726SMartyna Szapar-Mudlaw 	}
61190f94570dSGrishma Kotecha 
6120bccd9bceSMarcin Szycik 	if (rinfo->sw_act.fltr_act == ICE_FWD_TO_VSI ||
6121bccd9bceSMarcin Szycik 	    rinfo->sw_act.fltr_act == ICE_NOP)
61220f94570dSGrishma Kotecha 		rinfo->sw_act.fwd_id.hw_vsi_id =
61230f94570dSGrishma Kotecha 			ice_get_hw_vsi_num(hw, vsi_handle);
612403592a14SMichal Swiatkowski 
612503592a14SMichal Swiatkowski 	if (rinfo->src_vsi)
612603592a14SMichal Swiatkowski 		rinfo->sw_act.src = ice_get_hw_vsi_num(hw, rinfo->src_vsi);
612703592a14SMichal Swiatkowski 	else
61280f94570dSGrishma Kotecha 		rinfo->sw_act.src = ice_get_hw_vsi_num(hw, vsi_handle);
61290f94570dSGrishma Kotecha 
61300f94570dSGrishma Kotecha 	status = ice_add_adv_recipe(hw, lkups, lkups_cnt, rinfo, &rid);
61310f94570dSGrishma Kotecha 	if (status)
613226395726SMartyna Szapar-Mudlaw 		goto free_pkt_profile;
61330f94570dSGrishma Kotecha 	m_entry = ice_find_adv_rule_entry(hw, lkups, lkups_cnt, rid, rinfo);
61340f94570dSGrishma Kotecha 	if (m_entry) {
61350f94570dSGrishma Kotecha 		/* we have to add VSI to VSI_LIST and increment vsi_count.
61360f94570dSGrishma Kotecha 		 * Also Update VSI list so that we can change forwarding rule
61370f94570dSGrishma Kotecha 		 * if the rule already exists, we will check if it exists with
61380f94570dSGrishma Kotecha 		 * same vsi_id, if not then add it to the VSI list if it already
61390f94570dSGrishma Kotecha 		 * exists if not then create a VSI list and add the existing VSI
61400f94570dSGrishma Kotecha 		 * ID and the new VSI ID to the list
61410f94570dSGrishma Kotecha 		 * We will add that VSI to the list
61420f94570dSGrishma Kotecha 		 */
61430f94570dSGrishma Kotecha 		status = ice_adv_add_update_vsi_list(hw, m_entry,
61440f94570dSGrishma Kotecha 						     &m_entry->rule_info,
61450f94570dSGrishma Kotecha 						     rinfo);
61460f94570dSGrishma Kotecha 		if (added_entry) {
61470f94570dSGrishma Kotecha 			added_entry->rid = rid;
61480f94570dSGrishma Kotecha 			added_entry->rule_id = m_entry->rule_info.fltr_rule_id;
61490f94570dSGrishma Kotecha 			added_entry->vsi_handle = rinfo->sw_act.vsi_handle;
61500f94570dSGrishma Kotecha 		}
615126395726SMartyna Szapar-Mudlaw 		goto free_pkt_profile;
61520f94570dSGrishma Kotecha 	}
61536e1ff618SAlexander Lobakin 	rule_buf_sz = ICE_SW_RULE_RX_TX_HDR_SIZE(s_rule, profile->pkt_len);
61540f94570dSGrishma Kotecha 	s_rule = kzalloc(rule_buf_sz, GFP_KERNEL);
615526395726SMartyna Szapar-Mudlaw 	if (!s_rule) {
615626395726SMartyna Szapar-Mudlaw 		status = -ENOMEM;
615726395726SMartyna Szapar-Mudlaw 		goto free_pkt_profile;
615826395726SMartyna Szapar-Mudlaw 	}
615973b483b7SWojciech Drewek 	if (!rinfo->flags_info.act_valid) {
616073b483b7SWojciech Drewek 		act |= ICE_SINGLE_ACT_LAN_ENABLE;
616173b483b7SWojciech Drewek 		act |= ICE_SINGLE_ACT_LB_ENABLE;
616273b483b7SWojciech Drewek 	} else {
616373b483b7SWojciech Drewek 		act |= rinfo->flags_info.act & (ICE_SINGLE_ACT_LAN_ENABLE |
616473b483b7SWojciech Drewek 						ICE_SINGLE_ACT_LB_ENABLE);
616573b483b7SWojciech Drewek 	}
616673b483b7SWojciech Drewek 
61670f94570dSGrishma Kotecha 	switch (rinfo->sw_act.fltr_act) {
61680f94570dSGrishma Kotecha 	case ICE_FWD_TO_VSI:
61690f94570dSGrishma Kotecha 		act |= (rinfo->sw_act.fwd_id.hw_vsi_id <<
61700f94570dSGrishma Kotecha 			ICE_SINGLE_ACT_VSI_ID_S) & ICE_SINGLE_ACT_VSI_ID_M;
61710f94570dSGrishma Kotecha 		act |= ICE_SINGLE_ACT_VSI_FORWARDING | ICE_SINGLE_ACT_VALID_BIT;
61720f94570dSGrishma Kotecha 		break;
61730f94570dSGrishma Kotecha 	case ICE_FWD_TO_Q:
61740f94570dSGrishma Kotecha 		act |= ICE_SINGLE_ACT_TO_Q;
61750f94570dSGrishma Kotecha 		act |= (rinfo->sw_act.fwd_id.q_id << ICE_SINGLE_ACT_Q_INDEX_S) &
61760f94570dSGrishma Kotecha 		       ICE_SINGLE_ACT_Q_INDEX_M;
61770f94570dSGrishma Kotecha 		break;
61780f94570dSGrishma Kotecha 	case ICE_FWD_TO_QGRP:
61790f94570dSGrishma Kotecha 		q_rgn = rinfo->sw_act.qgrp_size > 0 ?
61800f94570dSGrishma Kotecha 			(u8)ilog2(rinfo->sw_act.qgrp_size) : 0;
61810f94570dSGrishma Kotecha 		act |= ICE_SINGLE_ACT_TO_Q;
61820f94570dSGrishma Kotecha 		act |= (rinfo->sw_act.fwd_id.q_id << ICE_SINGLE_ACT_Q_INDEX_S) &
61830f94570dSGrishma Kotecha 		       ICE_SINGLE_ACT_Q_INDEX_M;
61840f94570dSGrishma Kotecha 		act |= (q_rgn << ICE_SINGLE_ACT_Q_REGION_S) &
61850f94570dSGrishma Kotecha 		       ICE_SINGLE_ACT_Q_REGION_M;
61860f94570dSGrishma Kotecha 		break;
61870f94570dSGrishma Kotecha 	case ICE_DROP_PACKET:
61880f94570dSGrishma Kotecha 		act |= ICE_SINGLE_ACT_VSI_FORWARDING | ICE_SINGLE_ACT_DROP |
61890f94570dSGrishma Kotecha 		       ICE_SINGLE_ACT_VALID_BIT;
61900f94570dSGrishma Kotecha 		break;
6191bccd9bceSMarcin Szycik 	case ICE_NOP:
6192bccd9bceSMarcin Szycik 		act |= FIELD_PREP(ICE_SINGLE_ACT_VSI_ID_M,
6193bccd9bceSMarcin Szycik 				  rinfo->sw_act.fwd_id.hw_vsi_id);
6194bccd9bceSMarcin Szycik 		act &= ~ICE_SINGLE_ACT_VALID_BIT;
6195bccd9bceSMarcin Szycik 		break;
61960f94570dSGrishma Kotecha 	default:
6197d54699e2STony Nguyen 		status = -EIO;
61980f94570dSGrishma Kotecha 		goto err_ice_add_adv_rule;
61990f94570dSGrishma Kotecha 	}
62000f94570dSGrishma Kotecha 
620140fd7492SMichal Swiatkowski 	/* If there is no matching criteria for direction there
620240fd7492SMichal Swiatkowski 	 * is only one difference between Rx and Tx:
620340fd7492SMichal Swiatkowski 	 * - get switch id base on VSI number from source field (Tx)
620440fd7492SMichal Swiatkowski 	 * - get switch id base on port number (Rx)
62050f94570dSGrishma Kotecha 	 *
620640fd7492SMichal Swiatkowski 	 * If matching on direction metadata is chose rule direction is
620740fd7492SMichal Swiatkowski 	 * extracted from type value set here.
62080f94570dSGrishma Kotecha 	 */
620940fd7492SMichal Swiatkowski 	if (rinfo->sw_act.flag & ICE_FLTR_TX) {
62106e1ff618SAlexander Lobakin 		s_rule->hdr.type = cpu_to_le16(ICE_AQC_SW_RULES_T_LKUP_TX);
62116e1ff618SAlexander Lobakin 		s_rule->src = cpu_to_le16(rinfo->sw_act.src);
621240fd7492SMichal Swiatkowski 	} else {
621340fd7492SMichal Swiatkowski 		s_rule->hdr.type = cpu_to_le16(ICE_AQC_SW_RULES_T_LKUP_RX);
621440fd7492SMichal Swiatkowski 		s_rule->src = cpu_to_le16(hw->port_info->lport);
62150f94570dSGrishma Kotecha 	}
62160f94570dSGrishma Kotecha 
62176e1ff618SAlexander Lobakin 	s_rule->recipe_id = cpu_to_le16(rid);
62186e1ff618SAlexander Lobakin 	s_rule->act = cpu_to_le32(act);
62190f94570dSGrishma Kotecha 
6220e33163a4SAlexander Lobakin 	status = ice_fill_adv_dummy_packet(lkups, lkups_cnt, s_rule, profile);
62210f94570dSGrishma Kotecha 	if (status)
62220f94570dSGrishma Kotecha 		goto err_ice_add_adv_rule;
62230f94570dSGrishma Kotecha 
622403592a14SMichal Swiatkowski 	status = ice_fill_adv_packet_tun(hw, rinfo->tun_type, s_rule->hdr_data,
6225e33163a4SAlexander Lobakin 					 profile->offsets);
62268b032a55SMichal Swiatkowski 	if (status)
62278b032a55SMichal Swiatkowski 		goto err_ice_add_adv_rule;
62288b032a55SMichal Swiatkowski 
622903592a14SMichal Swiatkowski 	status = ice_fill_adv_packet_vlan(hw, rinfo->vlan_type,
6230ea71b967SMartyna Szapar-Mudlaw 					  s_rule->hdr_data,
6231ea71b967SMartyna Szapar-Mudlaw 					  profile->offsets);
6232ea71b967SMartyna Szapar-Mudlaw 	if (status)
6233ea71b967SMartyna Szapar-Mudlaw 		goto err_ice_add_adv_rule;
6234ea71b967SMartyna Szapar-Mudlaw 
62350f94570dSGrishma Kotecha 	status = ice_aq_sw_rules(hw, (struct ice_aqc_sw_rules *)s_rule,
62360f94570dSGrishma Kotecha 				 rule_buf_sz, 1, ice_aqc_opc_add_sw_rules,
62370f94570dSGrishma Kotecha 				 NULL);
62380f94570dSGrishma Kotecha 	if (status)
62390f94570dSGrishma Kotecha 		goto err_ice_add_adv_rule;
62400f94570dSGrishma Kotecha 	adv_fltr = devm_kzalloc(ice_hw_to_dev(hw),
62410f94570dSGrishma Kotecha 				sizeof(struct ice_adv_fltr_mgmt_list_entry),
62420f94570dSGrishma Kotecha 				GFP_KERNEL);
62430f94570dSGrishma Kotecha 	if (!adv_fltr) {
6244d54699e2STony Nguyen 		status = -ENOMEM;
62450f94570dSGrishma Kotecha 		goto err_ice_add_adv_rule;
62460f94570dSGrishma Kotecha 	}
62470f94570dSGrishma Kotecha 
62480f94570dSGrishma Kotecha 	adv_fltr->lkups = devm_kmemdup(ice_hw_to_dev(hw), lkups,
62490f94570dSGrishma Kotecha 				       lkups_cnt * sizeof(*lkups), GFP_KERNEL);
62500f94570dSGrishma Kotecha 	if (!adv_fltr->lkups) {
6251d54699e2STony Nguyen 		status = -ENOMEM;
62520f94570dSGrishma Kotecha 		goto err_ice_add_adv_rule;
62530f94570dSGrishma Kotecha 	}
62540f94570dSGrishma Kotecha 
62550f94570dSGrishma Kotecha 	adv_fltr->lkups_cnt = lkups_cnt;
62560f94570dSGrishma Kotecha 	adv_fltr->rule_info = *rinfo;
62576e1ff618SAlexander Lobakin 	adv_fltr->rule_info.fltr_rule_id = le16_to_cpu(s_rule->index);
62580f94570dSGrishma Kotecha 	sw = hw->switch_info;
62590f94570dSGrishma Kotecha 	sw->recp_list[rid].adv_rule = true;
62600f94570dSGrishma Kotecha 	rule_head = &sw->recp_list[rid].filt_rules;
62610f94570dSGrishma Kotecha 
62620f94570dSGrishma Kotecha 	if (rinfo->sw_act.fltr_act == ICE_FWD_TO_VSI)
62630f94570dSGrishma Kotecha 		adv_fltr->vsi_count = 1;
62640f94570dSGrishma Kotecha 
62650f94570dSGrishma Kotecha 	/* Add rule entry to book keeping list */
62660f94570dSGrishma Kotecha 	list_add(&adv_fltr->list_entry, rule_head);
62670f94570dSGrishma Kotecha 	if (added_entry) {
62680f94570dSGrishma Kotecha 		added_entry->rid = rid;
62690f94570dSGrishma Kotecha 		added_entry->rule_id = adv_fltr->rule_info.fltr_rule_id;
62700f94570dSGrishma Kotecha 		added_entry->vsi_handle = rinfo->sw_act.vsi_handle;
62710f94570dSGrishma Kotecha 	}
62720f94570dSGrishma Kotecha err_ice_add_adv_rule:
62730f94570dSGrishma Kotecha 	if (status && adv_fltr) {
62740f94570dSGrishma Kotecha 		devm_kfree(ice_hw_to_dev(hw), adv_fltr->lkups);
62750f94570dSGrishma Kotecha 		devm_kfree(ice_hw_to_dev(hw), adv_fltr);
62760f94570dSGrishma Kotecha 	}
62770f94570dSGrishma Kotecha 
62780f94570dSGrishma Kotecha 	kfree(s_rule);
62790f94570dSGrishma Kotecha 
628026395726SMartyna Szapar-Mudlaw free_pkt_profile:
628126395726SMartyna Szapar-Mudlaw 	if (profile->match & ICE_PKT_KMALLOC) {
628226395726SMartyna Szapar-Mudlaw 		kfree(profile->offsets);
628326395726SMartyna Szapar-Mudlaw 		kfree(profile->pkt);
628426395726SMartyna Szapar-Mudlaw 		kfree(profile);
628526395726SMartyna Szapar-Mudlaw 	}
628626395726SMartyna Szapar-Mudlaw 
62870f94570dSGrishma Kotecha 	return status;
62880f94570dSGrishma Kotecha }
62890f94570dSGrishma Kotecha 
62900f94570dSGrishma Kotecha /**
6291334cb062SAnirudh Venkataramanan  * ice_replay_vsi_fltr - Replay filters for requested VSI
62920f9d5027SAnirudh Venkataramanan  * @hw: pointer to the hardware structure
6293334cb062SAnirudh Venkataramanan  * @vsi_handle: driver VSI handle
6294f9867df6SAnirudh Venkataramanan  * @recp_id: Recipe ID for which rules need to be replayed
6295334cb062SAnirudh Venkataramanan  * @list_head: list for which filters need to be replayed
6296334cb062SAnirudh Venkataramanan  *
6297334cb062SAnirudh Venkataramanan  * Replays the filter of recipe recp_id for a VSI represented via vsi_handle.
6298334cb062SAnirudh Venkataramanan  * It is required to pass valid VSI handle.
62990f9d5027SAnirudh Venkataramanan  */
63005e24d598STony Nguyen static int
ice_replay_vsi_fltr(struct ice_hw * hw,u16 vsi_handle,u8 recp_id,struct list_head * list_head)6301334cb062SAnirudh Venkataramanan ice_replay_vsi_fltr(struct ice_hw *hw, u16 vsi_handle, u8 recp_id,
6302334cb062SAnirudh Venkataramanan 		    struct list_head *list_head)
63030f9d5027SAnirudh Venkataramanan {
63040f9d5027SAnirudh Venkataramanan 	struct ice_fltr_mgmt_list_entry *itr;
63055e24d598STony Nguyen 	int status = 0;
6306334cb062SAnirudh Venkataramanan 	u16 hw_vsi_id;
63070f9d5027SAnirudh Venkataramanan 
63080f9d5027SAnirudh Venkataramanan 	if (list_empty(list_head))
63090f9d5027SAnirudh Venkataramanan 		return status;
6310334cb062SAnirudh Venkataramanan 	hw_vsi_id = ice_get_hw_vsi_num(hw, vsi_handle);
63110f9d5027SAnirudh Venkataramanan 
6312334cb062SAnirudh Venkataramanan 	list_for_each_entry(itr, list_head, list_entry) {
63130f9d5027SAnirudh Venkataramanan 		struct ice_fltr_list_entry f_entry;
63140f9d5027SAnirudh Venkataramanan 
63150f9d5027SAnirudh Venkataramanan 		f_entry.fltr_info = itr->fltr_info;
6316334cb062SAnirudh Venkataramanan 		if (itr->vsi_count < 2 && recp_id != ICE_SW_LKUP_VLAN &&
6317334cb062SAnirudh Venkataramanan 		    itr->fltr_info.vsi_handle == vsi_handle) {
6318f9867df6SAnirudh Venkataramanan 			/* update the src in case it is VSI num */
6319334cb062SAnirudh Venkataramanan 			if (f_entry.fltr_info.src_id == ICE_SRC_ID_VSI)
6320334cb062SAnirudh Venkataramanan 				f_entry.fltr_info.src = hw_vsi_id;
63210f9d5027SAnirudh Venkataramanan 			status = ice_add_rule_internal(hw, recp_id, &f_entry);
63220f9d5027SAnirudh Venkataramanan 			if (status)
63230f9d5027SAnirudh Venkataramanan 				goto end;
63240f9d5027SAnirudh Venkataramanan 			continue;
63250f9d5027SAnirudh Venkataramanan 		}
6326072f0c3dSDave Ertman 		if (!itr->vsi_list_info ||
6327072f0c3dSDave Ertman 		    !test_bit(vsi_handle, itr->vsi_list_info->vsi_map))
6328334cb062SAnirudh Venkataramanan 			continue;
6329334cb062SAnirudh Venkataramanan 		/* Clearing it so that the logic can add it back */
6330334cb062SAnirudh Venkataramanan 		clear_bit(vsi_handle, itr->vsi_list_info->vsi_map);
6331334cb062SAnirudh Venkataramanan 		f_entry.fltr_info.vsi_handle = vsi_handle;
63320f9d5027SAnirudh Venkataramanan 		f_entry.fltr_info.fltr_act = ICE_FWD_TO_VSI;
6333f9867df6SAnirudh Venkataramanan 		/* update the src in case it is VSI num */
6334334cb062SAnirudh Venkataramanan 		if (f_entry.fltr_info.src_id == ICE_SRC_ID_VSI)
6335334cb062SAnirudh Venkataramanan 			f_entry.fltr_info.src = hw_vsi_id;
63360f9d5027SAnirudh Venkataramanan 		if (recp_id == ICE_SW_LKUP_VLAN)
63370f9d5027SAnirudh Venkataramanan 			status = ice_add_vlan_internal(hw, &f_entry);
63380f9d5027SAnirudh Venkataramanan 		else
6339334cb062SAnirudh Venkataramanan 			status = ice_add_rule_internal(hw, recp_id, &f_entry);
63400f9d5027SAnirudh Venkataramanan 		if (status)
63410f9d5027SAnirudh Venkataramanan 			goto end;
63420f9d5027SAnirudh Venkataramanan 	}
63430f9d5027SAnirudh Venkataramanan end:
63440f9d5027SAnirudh Venkataramanan 	return status;
63450f9d5027SAnirudh Venkataramanan }
63460f9d5027SAnirudh Venkataramanan 
63470f9d5027SAnirudh Venkataramanan /**
63488bb98f33SShivanshu Shukla  * ice_adv_rem_update_vsi_list
63498bb98f33SShivanshu Shukla  * @hw: pointer to the hardware structure
63508bb98f33SShivanshu Shukla  * @vsi_handle: VSI handle of the VSI to remove
63518bb98f33SShivanshu Shukla  * @fm_list: filter management entry for which the VSI list management needs to
63528bb98f33SShivanshu Shukla  *	     be done
63538bb98f33SShivanshu Shukla  */
63545e24d598STony Nguyen static int
ice_adv_rem_update_vsi_list(struct ice_hw * hw,u16 vsi_handle,struct ice_adv_fltr_mgmt_list_entry * fm_list)63558bb98f33SShivanshu Shukla ice_adv_rem_update_vsi_list(struct ice_hw *hw, u16 vsi_handle,
63568bb98f33SShivanshu Shukla 			    struct ice_adv_fltr_mgmt_list_entry *fm_list)
63578bb98f33SShivanshu Shukla {
63588bb98f33SShivanshu Shukla 	struct ice_vsi_list_map_info *vsi_list_info;
63598bb98f33SShivanshu Shukla 	enum ice_sw_lkup_type lkup_type;
63608bb98f33SShivanshu Shukla 	u16 vsi_list_id;
63615518ac2aSTony Nguyen 	int status;
63628bb98f33SShivanshu Shukla 
63638bb98f33SShivanshu Shukla 	if (fm_list->rule_info.sw_act.fltr_act != ICE_FWD_TO_VSI_LIST ||
63648bb98f33SShivanshu Shukla 	    fm_list->vsi_count == 0)
6365d54699e2STony Nguyen 		return -EINVAL;
63668bb98f33SShivanshu Shukla 
63678bb98f33SShivanshu Shukla 	/* A rule with the VSI being removed does not exist */
63688bb98f33SShivanshu Shukla 	if (!test_bit(vsi_handle, fm_list->vsi_list_info->vsi_map))
6369d54699e2STony Nguyen 		return -ENOENT;
63708bb98f33SShivanshu Shukla 
63718bb98f33SShivanshu Shukla 	lkup_type = ICE_SW_LKUP_LAST;
63728bb98f33SShivanshu Shukla 	vsi_list_id = fm_list->rule_info.sw_act.fwd_id.vsi_list_id;
63738bb98f33SShivanshu Shukla 	status = ice_update_vsi_list_rule(hw, &vsi_handle, 1, vsi_list_id, true,
63748bb98f33SShivanshu Shukla 					  ice_aqc_opc_update_sw_rules,
63758bb98f33SShivanshu Shukla 					  lkup_type);
63768bb98f33SShivanshu Shukla 	if (status)
63778bb98f33SShivanshu Shukla 		return status;
63788bb98f33SShivanshu Shukla 
63798bb98f33SShivanshu Shukla 	fm_list->vsi_count--;
63808bb98f33SShivanshu Shukla 	clear_bit(vsi_handle, fm_list->vsi_list_info->vsi_map);
63818bb98f33SShivanshu Shukla 	vsi_list_info = fm_list->vsi_list_info;
63828bb98f33SShivanshu Shukla 	if (fm_list->vsi_count == 1) {
63838bb98f33SShivanshu Shukla 		struct ice_fltr_info tmp_fltr;
63848bb98f33SShivanshu Shukla 		u16 rem_vsi_handle;
63858bb98f33SShivanshu Shukla 
63868bb98f33SShivanshu Shukla 		rem_vsi_handle = find_first_bit(vsi_list_info->vsi_map,
63878bb98f33SShivanshu Shukla 						ICE_MAX_VSI);
63888bb98f33SShivanshu Shukla 		if (!ice_is_vsi_valid(hw, rem_vsi_handle))
6389d54699e2STony Nguyen 			return -EIO;
63908bb98f33SShivanshu Shukla 
63918bb98f33SShivanshu Shukla 		/* Make sure VSI list is empty before removing it below */
63928bb98f33SShivanshu Shukla 		status = ice_update_vsi_list_rule(hw, &rem_vsi_handle, 1,
63938bb98f33SShivanshu Shukla 						  vsi_list_id, true,
63948bb98f33SShivanshu Shukla 						  ice_aqc_opc_update_sw_rules,
63958bb98f33SShivanshu Shukla 						  lkup_type);
63968bb98f33SShivanshu Shukla 		if (status)
63978bb98f33SShivanshu Shukla 			return status;
63988bb98f33SShivanshu Shukla 
63998bb98f33SShivanshu Shukla 		memset(&tmp_fltr, 0, sizeof(tmp_fltr));
64008bb98f33SShivanshu Shukla 		tmp_fltr.flag = fm_list->rule_info.sw_act.flag;
64018bb98f33SShivanshu Shukla 		tmp_fltr.fltr_rule_id = fm_list->rule_info.fltr_rule_id;
64028bb98f33SShivanshu Shukla 		fm_list->rule_info.sw_act.fltr_act = ICE_FWD_TO_VSI;
64038bb98f33SShivanshu Shukla 		tmp_fltr.fltr_act = ICE_FWD_TO_VSI;
64048bb98f33SShivanshu Shukla 		tmp_fltr.fwd_id.hw_vsi_id =
64058bb98f33SShivanshu Shukla 			ice_get_hw_vsi_num(hw, rem_vsi_handle);
64068bb98f33SShivanshu Shukla 		fm_list->rule_info.sw_act.fwd_id.hw_vsi_id =
64078bb98f33SShivanshu Shukla 			ice_get_hw_vsi_num(hw, rem_vsi_handle);
64088bb98f33SShivanshu Shukla 		fm_list->rule_info.sw_act.vsi_handle = rem_vsi_handle;
64098bb98f33SShivanshu Shukla 
64108bb98f33SShivanshu Shukla 		/* Update the previous switch rule of "MAC forward to VSI" to
64118bb98f33SShivanshu Shukla 		 * "MAC fwd to VSI list"
64128bb98f33SShivanshu Shukla 		 */
64138bb98f33SShivanshu Shukla 		status = ice_update_pkt_fwd_rule(hw, &tmp_fltr);
64148bb98f33SShivanshu Shukla 		if (status) {
64158bb98f33SShivanshu Shukla 			ice_debug(hw, ICE_DBG_SW, "Failed to update pkt fwd rule to FWD_TO_VSI on HW VSI %d, error %d\n",
64168bb98f33SShivanshu Shukla 				  tmp_fltr.fwd_id.hw_vsi_id, status);
64178bb98f33SShivanshu Shukla 			return status;
64188bb98f33SShivanshu Shukla 		}
64198bb98f33SShivanshu Shukla 		fm_list->vsi_list_info->ref_cnt--;
64208bb98f33SShivanshu Shukla 
64218bb98f33SShivanshu Shukla 		/* Remove the VSI list since it is no longer used */
64228bb98f33SShivanshu Shukla 		status = ice_remove_vsi_list_rule(hw, vsi_list_id, lkup_type);
64238bb98f33SShivanshu Shukla 		if (status) {
64248bb98f33SShivanshu Shukla 			ice_debug(hw, ICE_DBG_SW, "Failed to remove VSI list %d, error %d\n",
64258bb98f33SShivanshu Shukla 				  vsi_list_id, status);
64268bb98f33SShivanshu Shukla 			return status;
64278bb98f33SShivanshu Shukla 		}
64288bb98f33SShivanshu Shukla 
64298bb98f33SShivanshu Shukla 		list_del(&vsi_list_info->list_entry);
64308bb98f33SShivanshu Shukla 		devm_kfree(ice_hw_to_dev(hw), vsi_list_info);
64318bb98f33SShivanshu Shukla 		fm_list->vsi_list_info = NULL;
64328bb98f33SShivanshu Shukla 	}
64338bb98f33SShivanshu Shukla 
64348bb98f33SShivanshu Shukla 	return status;
64358bb98f33SShivanshu Shukla }
64368bb98f33SShivanshu Shukla 
64378bb98f33SShivanshu Shukla /**
64388bb98f33SShivanshu Shukla  * ice_rem_adv_rule - removes existing advanced switch rule
64398bb98f33SShivanshu Shukla  * @hw: pointer to the hardware structure
64408bb98f33SShivanshu Shukla  * @lkups: information on the words that needs to be looked up. All words
64418bb98f33SShivanshu Shukla  *         together makes one recipe
64428bb98f33SShivanshu Shukla  * @lkups_cnt: num of entries in the lkups array
64438bb98f33SShivanshu Shukla  * @rinfo: Its the pointer to the rule information for the rule
64448bb98f33SShivanshu Shukla  *
64458bb98f33SShivanshu Shukla  * This function can be used to remove 1 rule at a time. The lkups is
64468bb98f33SShivanshu Shukla  * used to describe all the words that forms the "lookup" portion of the
64478bb98f33SShivanshu Shukla  * rule. These words can span multiple protocols. Callers to this function
64488bb98f33SShivanshu Shukla  * need to pass in a list of protocol headers with lookup information along
64498bb98f33SShivanshu Shukla  * and mask that determines which words are valid from the given protocol
64508bb98f33SShivanshu Shukla  * header. rinfo describes other information related to this rule such as
64518bb98f33SShivanshu Shukla  * forwarding IDs, priority of this rule, etc.
64528bb98f33SShivanshu Shukla  */
64535e24d598STony Nguyen static int
ice_rem_adv_rule(struct ice_hw * hw,struct ice_adv_lkup_elem * lkups,u16 lkups_cnt,struct ice_adv_rule_info * rinfo)64548bb98f33SShivanshu Shukla ice_rem_adv_rule(struct ice_hw *hw, struct ice_adv_lkup_elem *lkups,
64558bb98f33SShivanshu Shukla 		 u16 lkups_cnt, struct ice_adv_rule_info *rinfo)
64568bb98f33SShivanshu Shukla {
64578bb98f33SShivanshu Shukla 	struct ice_adv_fltr_mgmt_list_entry *list_elem;
64588bb98f33SShivanshu Shukla 	struct ice_prot_lkup_ext lkup_exts;
64598bb98f33SShivanshu Shukla 	bool remove_rule = false;
64608bb98f33SShivanshu Shukla 	struct mutex *rule_lock; /* Lock to protect filter rule list */
64618bb98f33SShivanshu Shukla 	u16 i, rid, vsi_handle;
64625518ac2aSTony Nguyen 	int status = 0;
64638bb98f33SShivanshu Shukla 
64648bb98f33SShivanshu Shukla 	memset(&lkup_exts, 0, sizeof(lkup_exts));
64658bb98f33SShivanshu Shukla 	for (i = 0; i < lkups_cnt; i++) {
64668bb98f33SShivanshu Shukla 		u16 count;
64678bb98f33SShivanshu Shukla 
64688bb98f33SShivanshu Shukla 		if (lkups[i].type >= ICE_PROTOCOL_LAST)
6469d54699e2STony Nguyen 			return -EIO;
64708bb98f33SShivanshu Shukla 
64718bb98f33SShivanshu Shukla 		count = ice_fill_valid_words(&lkups[i], &lkup_exts);
64728bb98f33SShivanshu Shukla 		if (!count)
6473d54699e2STony Nguyen 			return -EIO;
64748bb98f33SShivanshu Shukla 	}
64758bb98f33SShivanshu Shukla 
6476bccd9bceSMarcin Szycik 	rid = ice_find_recp(hw, &lkup_exts, rinfo);
64778bb98f33SShivanshu Shukla 	/* If did not find a recipe that match the existing criteria */
64788bb98f33SShivanshu Shukla 	if (rid == ICE_MAX_NUM_RECIPES)
6479d54699e2STony Nguyen 		return -EINVAL;
64808bb98f33SShivanshu Shukla 
64818bb98f33SShivanshu Shukla 	rule_lock = &hw->switch_info->recp_list[rid].filt_rule_lock;
64828bb98f33SShivanshu Shukla 	list_elem = ice_find_adv_rule_entry(hw, lkups, lkups_cnt, rid, rinfo);
64838bb98f33SShivanshu Shukla 	/* the rule is already removed */
64848bb98f33SShivanshu Shukla 	if (!list_elem)
64858bb98f33SShivanshu Shukla 		return 0;
64868bb98f33SShivanshu Shukla 	mutex_lock(rule_lock);
64878bb98f33SShivanshu Shukla 	if (list_elem->rule_info.sw_act.fltr_act != ICE_FWD_TO_VSI_LIST) {
64888bb98f33SShivanshu Shukla 		remove_rule = true;
64898bb98f33SShivanshu Shukla 	} else if (list_elem->vsi_count > 1) {
64908bb98f33SShivanshu Shukla 		remove_rule = false;
64918bb98f33SShivanshu Shukla 		vsi_handle = rinfo->sw_act.vsi_handle;
64928bb98f33SShivanshu Shukla 		status = ice_adv_rem_update_vsi_list(hw, vsi_handle, list_elem);
64938bb98f33SShivanshu Shukla 	} else {
64948bb98f33SShivanshu Shukla 		vsi_handle = rinfo->sw_act.vsi_handle;
64958bb98f33SShivanshu Shukla 		status = ice_adv_rem_update_vsi_list(hw, vsi_handle, list_elem);
64968bb98f33SShivanshu Shukla 		if (status) {
64978bb98f33SShivanshu Shukla 			mutex_unlock(rule_lock);
64988bb98f33SShivanshu Shukla 			return status;
64998bb98f33SShivanshu Shukla 		}
65008bb98f33SShivanshu Shukla 		if (list_elem->vsi_count == 0)
65018bb98f33SShivanshu Shukla 			remove_rule = true;
65028bb98f33SShivanshu Shukla 	}
65038bb98f33SShivanshu Shukla 	mutex_unlock(rule_lock);
65048bb98f33SShivanshu Shukla 	if (remove_rule) {
65056e1ff618SAlexander Lobakin 		struct ice_sw_rule_lkup_rx_tx *s_rule;
65068bb98f33SShivanshu Shukla 		u16 rule_buf_sz;
65078bb98f33SShivanshu Shukla 
65086e1ff618SAlexander Lobakin 		rule_buf_sz = ICE_SW_RULE_RX_TX_NO_HDR_SIZE(s_rule);
65098bb98f33SShivanshu Shukla 		s_rule = kzalloc(rule_buf_sz, GFP_KERNEL);
65108bb98f33SShivanshu Shukla 		if (!s_rule)
6511d54699e2STony Nguyen 			return -ENOMEM;
65126e1ff618SAlexander Lobakin 		s_rule->act = 0;
65136e1ff618SAlexander Lobakin 		s_rule->index = cpu_to_le16(list_elem->rule_info.fltr_rule_id);
65146e1ff618SAlexander Lobakin 		s_rule->hdr_len = 0;
65158bb98f33SShivanshu Shukla 		status = ice_aq_sw_rules(hw, (struct ice_aqc_sw_rules *)s_rule,
65168bb98f33SShivanshu Shukla 					 rule_buf_sz, 1,
65178bb98f33SShivanshu Shukla 					 ice_aqc_opc_remove_sw_rules, NULL);
6518d54699e2STony Nguyen 		if (!status || status == -ENOENT) {
65198bb98f33SShivanshu Shukla 			struct ice_switch_info *sw = hw->switch_info;
65208bb98f33SShivanshu Shukla 
65218bb98f33SShivanshu Shukla 			mutex_lock(rule_lock);
65228bb98f33SShivanshu Shukla 			list_del(&list_elem->list_entry);
65238bb98f33SShivanshu Shukla 			devm_kfree(ice_hw_to_dev(hw), list_elem->lkups);
65248bb98f33SShivanshu Shukla 			devm_kfree(ice_hw_to_dev(hw), list_elem);
65258bb98f33SShivanshu Shukla 			mutex_unlock(rule_lock);
65268bb98f33SShivanshu Shukla 			if (list_empty(&sw->recp_list[rid].filt_rules))
65278bb98f33SShivanshu Shukla 				sw->recp_list[rid].adv_rule = false;
65288bb98f33SShivanshu Shukla 		}
65298bb98f33SShivanshu Shukla 		kfree(s_rule);
65308bb98f33SShivanshu Shukla 	}
65318bb98f33SShivanshu Shukla 	return status;
65328bb98f33SShivanshu Shukla }
65338bb98f33SShivanshu Shukla 
65348bb98f33SShivanshu Shukla /**
65358bb98f33SShivanshu Shukla  * ice_rem_adv_rule_by_id - removes existing advanced switch rule by ID
65368bb98f33SShivanshu Shukla  * @hw: pointer to the hardware structure
65378bb98f33SShivanshu Shukla  * @remove_entry: data struct which holds rule_id, VSI handle and recipe ID
65388bb98f33SShivanshu Shukla  *
65398bb98f33SShivanshu Shukla  * This function is used to remove 1 rule at a time. The removal is based on
65408bb98f33SShivanshu Shukla  * the remove_entry parameter. This function will remove rule for a given
65418bb98f33SShivanshu Shukla  * vsi_handle with a given rule_id which is passed as parameter in remove_entry
65428bb98f33SShivanshu Shukla  */
65435e24d598STony Nguyen int
ice_rem_adv_rule_by_id(struct ice_hw * hw,struct ice_rule_query_data * remove_entry)65448bb98f33SShivanshu Shukla ice_rem_adv_rule_by_id(struct ice_hw *hw,
65458bb98f33SShivanshu Shukla 		       struct ice_rule_query_data *remove_entry)
65468bb98f33SShivanshu Shukla {
65478bb98f33SShivanshu Shukla 	struct ice_adv_fltr_mgmt_list_entry *list_itr;
65488bb98f33SShivanshu Shukla 	struct list_head *list_head;
65498bb98f33SShivanshu Shukla 	struct ice_adv_rule_info rinfo;
65508bb98f33SShivanshu Shukla 	struct ice_switch_info *sw;
65518bb98f33SShivanshu Shukla 
65528bb98f33SShivanshu Shukla 	sw = hw->switch_info;
65538bb98f33SShivanshu Shukla 	if (!sw->recp_list[remove_entry->rid].recp_created)
6554d54699e2STony Nguyen 		return -EINVAL;
65558bb98f33SShivanshu Shukla 	list_head = &sw->recp_list[remove_entry->rid].filt_rules;
65568bb98f33SShivanshu Shukla 	list_for_each_entry(list_itr, list_head, list_entry) {
65578bb98f33SShivanshu Shukla 		if (list_itr->rule_info.fltr_rule_id ==
65588bb98f33SShivanshu Shukla 		    remove_entry->rule_id) {
65598bb98f33SShivanshu Shukla 			rinfo = list_itr->rule_info;
65608bb98f33SShivanshu Shukla 			rinfo.sw_act.vsi_handle = remove_entry->vsi_handle;
65618bb98f33SShivanshu Shukla 			return ice_rem_adv_rule(hw, list_itr->lkups,
65628bb98f33SShivanshu Shukla 						list_itr->lkups_cnt, &rinfo);
65638bb98f33SShivanshu Shukla 		}
65648bb98f33SShivanshu Shukla 	}
65658bb98f33SShivanshu Shukla 	/* either list is empty or unable to find rule */
6566d54699e2STony Nguyen 	return -ENOENT;
65678bb98f33SShivanshu Shukla }
65688bb98f33SShivanshu Shukla 
65698bb98f33SShivanshu Shukla /**
6570c36a2b97SVictor Raj  * ice_replay_vsi_adv_rule - Replay advanced rule for requested VSI
6571c36a2b97SVictor Raj  * @hw: pointer to the hardware structure
6572c36a2b97SVictor Raj  * @vsi_handle: driver VSI handle
6573c36a2b97SVictor Raj  * @list_head: list for which filters need to be replayed
6574c36a2b97SVictor Raj  *
6575c36a2b97SVictor Raj  * Replay the advanced rule for the given VSI.
6576c36a2b97SVictor Raj  */
6577c36a2b97SVictor Raj static int
ice_replay_vsi_adv_rule(struct ice_hw * hw,u16 vsi_handle,struct list_head * list_head)6578c36a2b97SVictor Raj ice_replay_vsi_adv_rule(struct ice_hw *hw, u16 vsi_handle,
6579c36a2b97SVictor Raj 			struct list_head *list_head)
6580c36a2b97SVictor Raj {
6581c36a2b97SVictor Raj 	struct ice_rule_query_data added_entry = { 0 };
6582c36a2b97SVictor Raj 	struct ice_adv_fltr_mgmt_list_entry *adv_fltr;
6583c36a2b97SVictor Raj 	int status = 0;
6584c36a2b97SVictor Raj 
6585c36a2b97SVictor Raj 	if (list_empty(list_head))
6586c36a2b97SVictor Raj 		return status;
6587c36a2b97SVictor Raj 	list_for_each_entry(adv_fltr, list_head, list_entry) {
6588c36a2b97SVictor Raj 		struct ice_adv_rule_info *rinfo = &adv_fltr->rule_info;
6589c36a2b97SVictor Raj 		u16 lk_cnt = adv_fltr->lkups_cnt;
6590c36a2b97SVictor Raj 
6591c36a2b97SVictor Raj 		if (vsi_handle != rinfo->sw_act.vsi_handle)
6592c36a2b97SVictor Raj 			continue;
6593c36a2b97SVictor Raj 		status = ice_add_adv_rule(hw, adv_fltr->lkups, lk_cnt, rinfo,
6594c36a2b97SVictor Raj 					  &added_entry);
6595c36a2b97SVictor Raj 		if (status)
6596c36a2b97SVictor Raj 			break;
6597c36a2b97SVictor Raj 	}
6598c36a2b97SVictor Raj 	return status;
6599c36a2b97SVictor Raj }
6600c36a2b97SVictor Raj 
6601c36a2b97SVictor Raj /**
6602334cb062SAnirudh Venkataramanan  * ice_replay_vsi_all_fltr - replay all filters stored in bookkeeping lists
66030f9d5027SAnirudh Venkataramanan  * @hw: pointer to the hardware structure
6604334cb062SAnirudh Venkataramanan  * @vsi_handle: driver VSI handle
66050f9d5027SAnirudh Venkataramanan  *
6606334cb062SAnirudh Venkataramanan  * Replays filters for requested VSI via vsi_handle.
66070f9d5027SAnirudh Venkataramanan  */
ice_replay_vsi_all_fltr(struct ice_hw * hw,u16 vsi_handle)66085e24d598STony Nguyen int ice_replay_vsi_all_fltr(struct ice_hw *hw, u16 vsi_handle)
66090f9d5027SAnirudh Venkataramanan {
66100f9d5027SAnirudh Venkataramanan 	struct ice_switch_info *sw = hw->switch_info;
6611c36a2b97SVictor Raj 	int status;
66120f9d5027SAnirudh Venkataramanan 	u8 i;
66130f9d5027SAnirudh Venkataramanan 
6614c36a2b97SVictor Raj 	for (i = 0; i < ICE_MAX_NUM_RECIPES; i++) {
6615334cb062SAnirudh Venkataramanan 		struct list_head *head;
66160f9d5027SAnirudh Venkataramanan 
6617334cb062SAnirudh Venkataramanan 		head = &sw->recp_list[i].filt_replay_rules;
6618c36a2b97SVictor Raj 		if (!sw->recp_list[i].adv_rule)
6619334cb062SAnirudh Venkataramanan 			status = ice_replay_vsi_fltr(hw, vsi_handle, i, head);
6620c36a2b97SVictor Raj 		else
6621c36a2b97SVictor Raj 			status = ice_replay_vsi_adv_rule(hw, vsi_handle, head);
66220f9d5027SAnirudh Venkataramanan 		if (status)
66230f9d5027SAnirudh Venkataramanan 			return status;
66240f9d5027SAnirudh Venkataramanan 	}
66250f9d5027SAnirudh Venkataramanan 	return status;
66260f9d5027SAnirudh Venkataramanan }
6627334cb062SAnirudh Venkataramanan 
6628334cb062SAnirudh Venkataramanan /**
6629334cb062SAnirudh Venkataramanan  * ice_rm_all_sw_replay_rule_info - deletes filter replay rules
6630f9867df6SAnirudh Venkataramanan  * @hw: pointer to the HW struct
6631334cb062SAnirudh Venkataramanan  *
6632334cb062SAnirudh Venkataramanan  * Deletes the filter replay rules.
6633334cb062SAnirudh Venkataramanan  */
ice_rm_all_sw_replay_rule_info(struct ice_hw * hw)6634334cb062SAnirudh Venkataramanan void ice_rm_all_sw_replay_rule_info(struct ice_hw *hw)
6635334cb062SAnirudh Venkataramanan {
6636334cb062SAnirudh Venkataramanan 	struct ice_switch_info *sw = hw->switch_info;
6637334cb062SAnirudh Venkataramanan 	u8 i;
6638334cb062SAnirudh Venkataramanan 
6639334cb062SAnirudh Venkataramanan 	if (!sw)
6640334cb062SAnirudh Venkataramanan 		return;
6641334cb062SAnirudh Venkataramanan 
66428b8ef05bSVictor Raj 	for (i = 0; i < ICE_MAX_NUM_RECIPES; i++) {
6643334cb062SAnirudh Venkataramanan 		if (!list_empty(&sw->recp_list[i].filt_replay_rules)) {
6644334cb062SAnirudh Venkataramanan 			struct list_head *l_head;
6645334cb062SAnirudh Venkataramanan 
6646334cb062SAnirudh Venkataramanan 			l_head = &sw->recp_list[i].filt_replay_rules;
66478b8ef05bSVictor Raj 			if (!sw->recp_list[i].adv_rule)
6648334cb062SAnirudh Venkataramanan 				ice_rem_sw_rule_info(hw, l_head);
66498b8ef05bSVictor Raj 			else
66508b8ef05bSVictor Raj 				ice_rem_adv_rule_info(hw, l_head);
6651334cb062SAnirudh Venkataramanan 		}
6652334cb062SAnirudh Venkataramanan 	}
6653334cb062SAnirudh Venkataramanan }
6654