xref: /dpdk/drivers/net/ice/base/ice_flow.c (revision e253c33d)
1 /* SPDX-License-Identifier: BSD-3-Clause
2  * Copyright(c) 2001-2020 Intel Corporation
3  */
4 
5 #include "ice_common.h"
6 #include "ice_flow.h"
7 
8 /* Size of known protocol header fields */
9 #define ICE_FLOW_FLD_SZ_ETH_TYPE	2
10 #define ICE_FLOW_FLD_SZ_VLAN		2
11 #define ICE_FLOW_FLD_SZ_IPV4_ADDR	4
12 #define ICE_FLOW_FLD_SZ_IPV6_ADDR	16
13 #define ICE_FLOW_FLD_SZ_IPV6_PRE32_ADDR	4
14 #define ICE_FLOW_FLD_SZ_IPV6_PRE48_ADDR	6
15 #define ICE_FLOW_FLD_SZ_IPV6_PRE64_ADDR	8
16 #define ICE_FLOW_FLD_SZ_IP_DSCP		1
17 #define ICE_FLOW_FLD_SZ_IP_TTL		1
18 #define ICE_FLOW_FLD_SZ_IP_PROT		1
19 #define ICE_FLOW_FLD_SZ_PORT		2
20 #define ICE_FLOW_FLD_SZ_TCP_FLAGS	1
21 #define ICE_FLOW_FLD_SZ_ICMP_TYPE	1
22 #define ICE_FLOW_FLD_SZ_ICMP_CODE	1
23 #define ICE_FLOW_FLD_SZ_ARP_OPER	2
24 #define ICE_FLOW_FLD_SZ_GRE_KEYID	4
25 #define ICE_FLOW_FLD_SZ_GTP_TEID	4
26 #define ICE_FLOW_FLD_SZ_GTP_QFI		2
27 #define ICE_FLOW_FLD_SZ_PPPOE_SESS_ID   2
28 #define ICE_FLOW_FLD_SZ_PFCP_SEID 8
29 #define ICE_FLOW_FLD_SZ_L2TPV3_SESS_ID	4
30 #define ICE_FLOW_FLD_SZ_ESP_SPI	4
31 #define ICE_FLOW_FLD_SZ_AH_SPI	4
32 #define ICE_FLOW_FLD_SZ_NAT_T_ESP_SPI	4
33 #define ICE_FLOW_FLD_SZ_VXLAN_VNI	4
34 #define ICE_FLOW_FLD_SZ_ECPRI_TP0_PC_ID	2
35 
36 /* Describe properties of a protocol header field */
37 struct ice_flow_field_info {
38 	enum ice_flow_seg_hdr hdr;
39 	s16 off;	/* Offset from start of a protocol header, in bits */
40 	u16 size;	/* Size of fields in bits */
41 	u16 mask;	/* 16-bit mask for field */
42 };
43 
44 #define ICE_FLOW_FLD_INFO(_hdr, _offset_bytes, _size_bytes) { \
45 	.hdr = _hdr, \
46 	.off = (_offset_bytes) * BITS_PER_BYTE, \
47 	.size = (_size_bytes) * BITS_PER_BYTE, \
48 	.mask = 0, \
49 }
50 
51 #define ICE_FLOW_FLD_INFO_MSK(_hdr, _offset_bytes, _size_bytes, _mask) { \
52 	.hdr = _hdr, \
53 	.off = (_offset_bytes) * BITS_PER_BYTE, \
54 	.size = (_size_bytes) * BITS_PER_BYTE, \
55 	.mask = _mask, \
56 }
57 
58 /* Table containing properties of supported protocol header fields */
59 static const
60 struct ice_flow_field_info ice_flds_info[ICE_FLOW_FIELD_IDX_MAX] = {
61 	/* Ether */
62 	/* ICE_FLOW_FIELD_IDX_ETH_DA */
63 	ICE_FLOW_FLD_INFO(ICE_FLOW_SEG_HDR_ETH, 0, ETH_ALEN),
64 	/* ICE_FLOW_FIELD_IDX_ETH_SA */
65 	ICE_FLOW_FLD_INFO(ICE_FLOW_SEG_HDR_ETH, ETH_ALEN, ETH_ALEN),
66 	/* ICE_FLOW_FIELD_IDX_S_VLAN */
67 	ICE_FLOW_FLD_INFO(ICE_FLOW_SEG_HDR_VLAN, 12, ICE_FLOW_FLD_SZ_VLAN),
68 	/* ICE_FLOW_FIELD_IDX_C_VLAN */
69 	ICE_FLOW_FLD_INFO(ICE_FLOW_SEG_HDR_VLAN, 14, ICE_FLOW_FLD_SZ_VLAN),
70 	/* ICE_FLOW_FIELD_IDX_ETH_TYPE */
71 	ICE_FLOW_FLD_INFO(ICE_FLOW_SEG_HDR_ETH, 0, ICE_FLOW_FLD_SZ_ETH_TYPE),
72 	/* IPv4 / IPv6 */
73 	/* ICE_FLOW_FIELD_IDX_IPV4_DSCP */
74 	ICE_FLOW_FLD_INFO_MSK(ICE_FLOW_SEG_HDR_IPV4, 0, ICE_FLOW_FLD_SZ_IP_DSCP,
75 			      0x00fc),
76 	/* ICE_FLOW_FIELD_IDX_IPV6_DSCP */
77 	ICE_FLOW_FLD_INFO_MSK(ICE_FLOW_SEG_HDR_IPV6, 0, ICE_FLOW_FLD_SZ_IP_DSCP,
78 			      0x0ff0),
79 	/* ICE_FLOW_FIELD_IDX_IPV4_TTL */
80 	ICE_FLOW_FLD_INFO_MSK(ICE_FLOW_SEG_HDR_NONE, 8,
81 			      ICE_FLOW_FLD_SZ_IP_TTL, 0xff00),
82 	/* ICE_FLOW_FIELD_IDX_IPV4_PROT */
83 	ICE_FLOW_FLD_INFO_MSK(ICE_FLOW_SEG_HDR_NONE, 8,
84 			      ICE_FLOW_FLD_SZ_IP_PROT, 0x00ff),
85 	/* ICE_FLOW_FIELD_IDX_IPV6_TTL */
86 	ICE_FLOW_FLD_INFO_MSK(ICE_FLOW_SEG_HDR_NONE, 6,
87 			      ICE_FLOW_FLD_SZ_IP_TTL, 0x00ff),
88 	/* ICE_FLOW_FIELD_IDX_IPV6_PROT */
89 	ICE_FLOW_FLD_INFO_MSK(ICE_FLOW_SEG_HDR_NONE, 6,
90 			      ICE_FLOW_FLD_SZ_IP_PROT, 0xff00),
91 	/* ICE_FLOW_FIELD_IDX_IPV4_SA */
92 	ICE_FLOW_FLD_INFO(ICE_FLOW_SEG_HDR_IPV4, 12, ICE_FLOW_FLD_SZ_IPV4_ADDR),
93 	/* ICE_FLOW_FIELD_IDX_IPV4_DA */
94 	ICE_FLOW_FLD_INFO(ICE_FLOW_SEG_HDR_IPV4, 16, ICE_FLOW_FLD_SZ_IPV4_ADDR),
95 	/* ICE_FLOW_FIELD_IDX_IPV6_SA */
96 	ICE_FLOW_FLD_INFO(ICE_FLOW_SEG_HDR_IPV6, 8, ICE_FLOW_FLD_SZ_IPV6_ADDR),
97 	/* ICE_FLOW_FIELD_IDX_IPV6_DA */
98 	ICE_FLOW_FLD_INFO(ICE_FLOW_SEG_HDR_IPV6, 24, ICE_FLOW_FLD_SZ_IPV6_ADDR),
99 	/* ICE_FLOW_FIELD_IDX_IPV6_PRE32_SA */
100 	ICE_FLOW_FLD_INFO(ICE_FLOW_SEG_HDR_IPV6, 8,
101 			  ICE_FLOW_FLD_SZ_IPV6_PRE32_ADDR),
102 	/* ICE_FLOW_FIELD_IDX_IPV6_PRE32_DA */
103 	ICE_FLOW_FLD_INFO(ICE_FLOW_SEG_HDR_IPV6, 24,
104 			  ICE_FLOW_FLD_SZ_IPV6_PRE32_ADDR),
105 	/* ICE_FLOW_FIELD_IDX_IPV6_PRE48_SA */
106 	ICE_FLOW_FLD_INFO(ICE_FLOW_SEG_HDR_IPV6, 8,
107 			  ICE_FLOW_FLD_SZ_IPV6_PRE48_ADDR),
108 	/* ICE_FLOW_FIELD_IDX_IPV6_PRE48_DA */
109 	ICE_FLOW_FLD_INFO(ICE_FLOW_SEG_HDR_IPV6, 24,
110 			  ICE_FLOW_FLD_SZ_IPV6_PRE48_ADDR),
111 	/* ICE_FLOW_FIELD_IDX_IPV6_PRE64_SA */
112 	ICE_FLOW_FLD_INFO(ICE_FLOW_SEG_HDR_IPV6, 8,
113 			  ICE_FLOW_FLD_SZ_IPV6_PRE64_ADDR),
114 	/* ICE_FLOW_FIELD_IDX_IPV6_PRE64_DA */
115 	ICE_FLOW_FLD_INFO(ICE_FLOW_SEG_HDR_IPV6, 24,
116 			  ICE_FLOW_FLD_SZ_IPV6_PRE64_ADDR),
117 	/* Transport */
118 	/* ICE_FLOW_FIELD_IDX_TCP_SRC_PORT */
119 	ICE_FLOW_FLD_INFO(ICE_FLOW_SEG_HDR_TCP, 0, ICE_FLOW_FLD_SZ_PORT),
120 	/* ICE_FLOW_FIELD_IDX_TCP_DST_PORT */
121 	ICE_FLOW_FLD_INFO(ICE_FLOW_SEG_HDR_TCP, 2, ICE_FLOW_FLD_SZ_PORT),
122 	/* ICE_FLOW_FIELD_IDX_UDP_SRC_PORT */
123 	ICE_FLOW_FLD_INFO(ICE_FLOW_SEG_HDR_UDP, 0, ICE_FLOW_FLD_SZ_PORT),
124 	/* ICE_FLOW_FIELD_IDX_UDP_DST_PORT */
125 	ICE_FLOW_FLD_INFO(ICE_FLOW_SEG_HDR_UDP, 2, ICE_FLOW_FLD_SZ_PORT),
126 	/* ICE_FLOW_FIELD_IDX_SCTP_SRC_PORT */
127 	ICE_FLOW_FLD_INFO(ICE_FLOW_SEG_HDR_SCTP, 0, ICE_FLOW_FLD_SZ_PORT),
128 	/* ICE_FLOW_FIELD_IDX_SCTP_DST_PORT */
129 	ICE_FLOW_FLD_INFO(ICE_FLOW_SEG_HDR_SCTP, 2, ICE_FLOW_FLD_SZ_PORT),
130 	/* ICE_FLOW_FIELD_IDX_TCP_FLAGS */
131 	ICE_FLOW_FLD_INFO(ICE_FLOW_SEG_HDR_TCP, 13, ICE_FLOW_FLD_SZ_TCP_FLAGS),
132 	/* ARP */
133 	/* ICE_FLOW_FIELD_IDX_ARP_SIP */
134 	ICE_FLOW_FLD_INFO(ICE_FLOW_SEG_HDR_ARP, 14, ICE_FLOW_FLD_SZ_IPV4_ADDR),
135 	/* ICE_FLOW_FIELD_IDX_ARP_DIP */
136 	ICE_FLOW_FLD_INFO(ICE_FLOW_SEG_HDR_ARP, 24, ICE_FLOW_FLD_SZ_IPV4_ADDR),
137 	/* ICE_FLOW_FIELD_IDX_ARP_SHA */
138 	ICE_FLOW_FLD_INFO(ICE_FLOW_SEG_HDR_ARP, 8, ETH_ALEN),
139 	/* ICE_FLOW_FIELD_IDX_ARP_DHA */
140 	ICE_FLOW_FLD_INFO(ICE_FLOW_SEG_HDR_ARP, 18, ETH_ALEN),
141 	/* ICE_FLOW_FIELD_IDX_ARP_OP */
142 	ICE_FLOW_FLD_INFO(ICE_FLOW_SEG_HDR_ARP, 6, ICE_FLOW_FLD_SZ_ARP_OPER),
143 	/* ICMP */
144 	/* ICE_FLOW_FIELD_IDX_ICMP_TYPE */
145 	ICE_FLOW_FLD_INFO(ICE_FLOW_SEG_HDR_ICMP, 0, ICE_FLOW_FLD_SZ_ICMP_TYPE),
146 	/* ICE_FLOW_FIELD_IDX_ICMP_CODE */
147 	ICE_FLOW_FLD_INFO(ICE_FLOW_SEG_HDR_ICMP, 1, ICE_FLOW_FLD_SZ_ICMP_CODE),
148 	/* GRE */
149 	/* ICE_FLOW_FIELD_IDX_GRE_KEYID */
150 	ICE_FLOW_FLD_INFO(ICE_FLOW_SEG_HDR_GRE, 12, ICE_FLOW_FLD_SZ_GRE_KEYID),
151 	/* GTP */
152 	/* ICE_FLOW_FIELD_IDX_GTPC_TEID */
153 	ICE_FLOW_FLD_INFO(ICE_FLOW_SEG_HDR_GTPC_TEID, 12,
154 			  ICE_FLOW_FLD_SZ_GTP_TEID),
155 	/* ICE_FLOW_FIELD_IDX_GTPU_IP_TEID */
156 	ICE_FLOW_FLD_INFO(ICE_FLOW_SEG_HDR_GTPU_IP, 12,
157 			  ICE_FLOW_FLD_SZ_GTP_TEID),
158 	/* ICE_FLOW_FIELD_IDX_GTPU_EH_TEID */
159 	ICE_FLOW_FLD_INFO(ICE_FLOW_SEG_HDR_GTPU_EH, 12,
160 			  ICE_FLOW_FLD_SZ_GTP_TEID),
161 	/* ICE_FLOW_FIELD_IDX_GTPU_EH_QFI */
162 	ICE_FLOW_FLD_INFO_MSK(ICE_FLOW_SEG_HDR_GTPU_EH, 22,
163 			      ICE_FLOW_FLD_SZ_GTP_QFI, 0x3f00),
164 	/* ICE_FLOW_FIELD_IDX_GTPU_UP_TEID */
165 	ICE_FLOW_FLD_INFO(ICE_FLOW_SEG_HDR_GTPU_UP, 12,
166 			  ICE_FLOW_FLD_SZ_GTP_TEID),
167 	/* ICE_FLOW_FIELD_IDX_GTPU_DWN_TEID */
168 	ICE_FLOW_FLD_INFO(ICE_FLOW_SEG_HDR_GTPU_DWN, 12,
169 			  ICE_FLOW_FLD_SZ_GTP_TEID),
170 	/* PPPOE */
171 	/* ICE_FLOW_FIELD_IDX_PPPOE_SESS_ID */
172 	ICE_FLOW_FLD_INFO(ICE_FLOW_SEG_HDR_PPPOE, 2,
173 			  ICE_FLOW_FLD_SZ_PPPOE_SESS_ID),
174 	/* PFCP */
175 	/* ICE_FLOW_FIELD_IDX_PFCP_SEID */
176 	ICE_FLOW_FLD_INFO(ICE_FLOW_SEG_HDR_PFCP_SESSION, 12,
177 			  ICE_FLOW_FLD_SZ_PFCP_SEID),
178 	/* L2TPV3 */
179 	/* ICE_FLOW_FIELD_IDX_L2TPV3_SESS_ID */
180 	ICE_FLOW_FLD_INFO(ICE_FLOW_SEG_HDR_L2TPV3, 0,
181 			  ICE_FLOW_FLD_SZ_L2TPV3_SESS_ID),
182 	/* ESP */
183 	/* ICE_FLOW_FIELD_IDX_ESP_SPI */
184 	ICE_FLOW_FLD_INFO(ICE_FLOW_SEG_HDR_ESP, 0,
185 			  ICE_FLOW_FLD_SZ_ESP_SPI),
186 	/* AH */
187 	/* ICE_FLOW_FIELD_IDX_AH_SPI */
188 	ICE_FLOW_FLD_INFO(ICE_FLOW_SEG_HDR_AH, 4,
189 			  ICE_FLOW_FLD_SZ_AH_SPI),
190 	/* NAT_T_ESP */
191 	/* ICE_FLOW_FIELD_IDX_NAT_T_ESP_SPI */
192 	ICE_FLOW_FLD_INFO(ICE_FLOW_SEG_HDR_NAT_T_ESP, 8,
193 			  ICE_FLOW_FLD_SZ_NAT_T_ESP_SPI),
194 	/* ICE_FLOW_FIELD_IDX_VXLAN_VNI */
195 	ICE_FLOW_FLD_INFO(ICE_FLOW_SEG_HDR_VXLAN, 12,
196 			  ICE_FLOW_FLD_SZ_VXLAN_VNI),
197 	/* ECPRI_TP0 */
198 	/* ICE_FLOW_FIELD_IDX_ECPRI_TP0_PC_ID */
199 	ICE_FLOW_FLD_INFO(ICE_FLOW_SEG_HDR_ECPRI_TP0, 4,
200 			  ICE_FLOW_FLD_SZ_ECPRI_TP0_PC_ID),
201 	/* UDP_ECPRI_TP0 */
202 	/* ICE_FLOW_FIELD_IDX_UDP_ECPRI_TP0_PC_ID */
203 	ICE_FLOW_FLD_INFO(ICE_FLOW_SEG_HDR_UDP_ECPRI_TP0, 12,
204 			  ICE_FLOW_FLD_SZ_ECPRI_TP0_PC_ID),
205 };
206 
207 /* Bitmaps indicating relevant packet types for a particular protocol header
208  *
209  * Packet types for packets with an Outer/First/Single MAC header
210  */
211 static const u32 ice_ptypes_mac_ofos[] = {
212 	0xFDC00846, 0xBFBF7F7E, 0xF70001DF, 0xFEFDFDFB,
213 	0x0000077E, 0x000003FF, 0x00000000, 0x00000000,
214 	0x00400000, 0x03FFF000, 0xFFFFFFE0, 0x00100707,
215 	0x00000000, 0x00000000, 0x00000000, 0x00000000,
216 	0x00000000, 0x00000000, 0x00000000, 0x00000000,
217 	0x00000000, 0x00000000, 0x00000000, 0x00000000,
218 	0x00000000, 0x00000000, 0x00000000, 0x00000000,
219 	0x00000000, 0x00000000, 0x00000000, 0x00000000,
220 };
221 
222 /* Packet types for packets with an Innermost/Last MAC VLAN header */
223 static const u32 ice_ptypes_macvlan_il[] = {
224 	0x00000000, 0xBC000000, 0x000001DF, 0xF0000000,
225 	0x0000077E, 0x00000000, 0x00000000, 0x00000000,
226 	0x00000000, 0x00000000, 0x00000000, 0x00000000,
227 	0x00000000, 0x00000000, 0x00000000, 0x00000000,
228 	0x00000000, 0x00000000, 0x00000000, 0x00000000,
229 	0x00000000, 0x00000000, 0x00000000, 0x00000000,
230 	0x00000000, 0x00000000, 0x00000000, 0x00000000,
231 	0x00000000, 0x00000000, 0x00000000, 0x00000000,
232 };
233 
234 /* Packet types for packets with an Outer/First/Single IPv4 header, does NOT
235  * include IPV4 other PTYPEs
236  */
237 static const u32 ice_ptypes_ipv4_ofos[] = {
238 	0x1DC00000, 0x24000800, 0x00000000, 0x00000000,
239 	0x00000000, 0x00000155, 0x00000000, 0x00000000,
240 	0x00000000, 0x000FC000, 0x000002A0, 0x00100000,
241 	0x00000000, 0x00000000, 0x00000000, 0x00000000,
242 	0x00000000, 0x00000000, 0x00000000, 0x00000000,
243 	0x00000000, 0x00000000, 0x00000000, 0x00000000,
244 	0x00000000, 0x00000000, 0x00000000, 0x00000000,
245 	0x00000000, 0x00000000, 0x00000000, 0x00000000,
246 };
247 
248 /* Packet types for packets with an Outer/First/Single IPv4 header, includes
249  * IPV4 other PTYPEs
250  */
251 static const u32 ice_ptypes_ipv4_ofos_all[] = {
252 	0x1DC00000, 0x24000800, 0x00000000, 0x00000000,
253 	0x00000000, 0x00000155, 0x00000000, 0x00000000,
254 	0x00000000, 0x000FC000, 0x83E0FAA0, 0x00000101,
255 	0x00000000, 0x00000000, 0x00000000, 0x00000000,
256 	0x00000000, 0x00000000, 0x00000000, 0x00000000,
257 	0x00000000, 0x00000000, 0x00000000, 0x00000000,
258 	0x00000000, 0x00000000, 0x00000000, 0x00000000,
259 	0x00000000, 0x00000000, 0x00000000, 0x00000000,
260 };
261 
262 /* Packet types for packets with an Innermost/Last IPv4 header */
263 static const u32 ice_ptypes_ipv4_il[] = {
264 	0xE0000000, 0xB807700E, 0x80000003, 0xE01DC03B,
265 	0x0000000E, 0x00000000, 0x00000000, 0x00000000,
266 	0x00000000, 0x00000000, 0x001FF800, 0x00100000,
267 	0x00000000, 0x00000000, 0x00000000, 0x00000000,
268 	0x00000000, 0x00000000, 0x00000000, 0x00000000,
269 	0x00000000, 0x00000000, 0x00000000, 0x00000000,
270 	0x00000000, 0x00000000, 0x00000000, 0x00000000,
271 	0x00000000, 0x00000000, 0x00000000, 0x00000000,
272 };
273 
274 /* Packet types for packets with an Outer/First/Single IPv6 header, does NOT
275  * include IVP6 other PTYPEs
276  */
277 static const u32 ice_ptypes_ipv6_ofos[] = {
278 	0x00000000, 0x00000000, 0x77000000, 0x10002000,
279 	0x00000000, 0x000002AA, 0x00000000, 0x00000000,
280 	0x00000000, 0x03F00000, 0x00000540, 0x00000000,
281 	0x00000000, 0x00000000, 0x00000000, 0x00000000,
282 	0x00000000, 0x00000000, 0x00000000, 0x00000000,
283 	0x00000000, 0x00000000, 0x00000000, 0x00000000,
284 	0x00000000, 0x00000000, 0x00000000, 0x00000000,
285 	0x00000000, 0x00000000, 0x00000000, 0x00000000,
286 };
287 
288 /* Packet types for packets with an Outer/First/Single IPv6 header, includes
289  * IPV6 other PTYPEs
290  */
291 static const u32 ice_ptypes_ipv6_ofos_all[] = {
292 	0x00000000, 0x00000000, 0x77000000, 0x10002000,
293 	0x00000000, 0x000002AA, 0x00000000, 0x00000000,
294 	0x00000000, 0x03F00000, 0x7C1F0540, 0x00000206,
295 	0x00000000, 0x00000000, 0x00000000, 0x00000000,
296 	0x00000000, 0x00000000, 0x00000000, 0x00000000,
297 	0x00000000, 0x00000000, 0x00000000, 0x00000000,
298 	0x00000000, 0x00000000, 0x00000000, 0x00000000,
299 	0x00000000, 0x00000000, 0x00000000, 0x00000000,
300 };
301 
302 /* Packet types for packets with an Innermost/Last IPv6 header */
303 static const u32 ice_ptypes_ipv6_il[] = {
304 	0x00000000, 0x03B80770, 0x000001DC, 0x0EE00000,
305 	0x00000770, 0x00000000, 0x00000000, 0x00000000,
306 	0x00000000, 0x00000000, 0x7FE00000, 0x00000000,
307 	0x00000000, 0x00000000, 0x00000000, 0x00000000,
308 	0x00000000, 0x00000000, 0x00000000, 0x00000000,
309 	0x00000000, 0x00000000, 0x00000000, 0x00000000,
310 	0x00000000, 0x00000000, 0x00000000, 0x00000000,
311 	0x00000000, 0x00000000, 0x00000000, 0x00000000,
312 };
313 
314 /* Packet types for packets with an Outer/First/Single IPv4 header - no L4 */
315 static const u32 ice_ptypes_ipv4_ofos_no_l4[] = {
316 	0x10C00000, 0x04000800, 0x00000000, 0x00000000,
317 	0x00000000, 0x00000000, 0x00000000, 0x00000000,
318 	0x00000000, 0x000cc000, 0x000002A0, 0x00000000,
319 	0x00000000, 0x00000000, 0x00000000, 0x00000000,
320 	0x00000000, 0x00000000, 0x00000000, 0x00000000,
321 	0x00000000, 0x00000000, 0x00000000, 0x00000000,
322 	0x00000000, 0x00000000, 0x00000000, 0x00000000,
323 	0x00000000, 0x00000000, 0x00000000, 0x00000000,
324 };
325 
326 /* Packet types for packets with an Innermost/Last IPv4 header - no L4 */
327 static const u32 ice_ptypes_ipv4_il_no_l4[] = {
328 	0x60000000, 0x18043008, 0x80000002, 0x6010c021,
329 	0x00000008, 0x00000000, 0x00000000, 0x00000000,
330 	0x00000000, 0x00000000, 0x00139800, 0x00000000,
331 	0x00000000, 0x00000000, 0x00000000, 0x00000000,
332 	0x00000000, 0x00000000, 0x00000000, 0x00000000,
333 	0x00000000, 0x00000000, 0x00000000, 0x00000000,
334 	0x00000000, 0x00000000, 0x00000000, 0x00000000,
335 	0x00000000, 0x00000000, 0x00000000, 0x00000000,
336 };
337 
338 /* Packet types for packets with an Outer/First/Single IPv6 header - no L4 */
339 static const u32 ice_ptypes_ipv6_ofos_no_l4[] = {
340 	0x00000000, 0x00000000, 0x43000000, 0x10002000,
341 	0x00000000, 0x00000000, 0x00000000, 0x00000000,
342 	0x00000000, 0x02300000, 0x00000540, 0x00000000,
343 	0x00000000, 0x00000000, 0x00000000, 0x00000000,
344 	0x00000000, 0x00000000, 0x00000000, 0x00000000,
345 	0x00000000, 0x00000000, 0x00000000, 0x00000000,
346 	0x00000000, 0x00000000, 0x00000000, 0x00000000,
347 	0x00000000, 0x00000000, 0x00000000, 0x00000000,
348 };
349 
350 /* Packet types for packets with an Innermost/Last IPv6 header - no L4 */
351 static const u32 ice_ptypes_ipv6_il_no_l4[] = {
352 	0x00000000, 0x02180430, 0x0000010c, 0x086010c0,
353 	0x00000430, 0x00000000, 0x00000000, 0x00000000,
354 	0x00000000, 0x00000000, 0x4e600000, 0x00000000,
355 	0x00000000, 0x00000000, 0x00000000, 0x00000000,
356 	0x00000000, 0x00000000, 0x00000000, 0x00000000,
357 	0x00000000, 0x00000000, 0x00000000, 0x00000000,
358 	0x00000000, 0x00000000, 0x00000000, 0x00000000,
359 	0x00000000, 0x00000000, 0x00000000, 0x00000000,
360 };
361 
362 /* Packet types for packets with an Outermost/First ARP header */
363 static const u32 ice_ptypes_arp_of[] = {
364 	0x00000800, 0x00000000, 0x00000000, 0x00000000,
365 	0x00000000, 0x00000000, 0x00000000, 0x00000000,
366 	0x00000000, 0x00000000, 0x00000000, 0x00000000,
367 	0x00000000, 0x00000000, 0x00000000, 0x00000000,
368 	0x00000000, 0x00000000, 0x00000000, 0x00000000,
369 	0x00000000, 0x00000000, 0x00000000, 0x00000000,
370 	0x00000000, 0x00000000, 0x00000000, 0x00000000,
371 	0x00000000, 0x00000000, 0x00000000, 0x00000000,
372 };
373 
374 /* UDP Packet types for non-tunneled packets or tunneled
375  * packets with inner UDP.
376  */
377 static const u32 ice_ptypes_udp_il[] = {
378 	0x81000000, 0x20204040, 0x04000010, 0x80810102,
379 	0x00000040, 0x00000000, 0x00000000, 0x00000000,
380 	0x00000000, 0x00410000, 0x908427E0, 0x00100007,
381 	0x00000000, 0x00000000, 0x00000000, 0x00000000,
382 	0x00000000, 0x00000000, 0x00000000, 0x00000000,
383 	0x00000000, 0x00000000, 0x00000000, 0x00000000,
384 	0x00000000, 0x00000000, 0x00000000, 0x00000000,
385 	0x00000000, 0x00000000, 0x00000000, 0x00000000,
386 };
387 
388 /* Packet types for packets with an Innermost/Last TCP header */
389 static const u32 ice_ptypes_tcp_il[] = {
390 	0x04000000, 0x80810102, 0x10000040, 0x02040408,
391 	0x00000102, 0x00000000, 0x00000000, 0x00000000,
392 	0x00000000, 0x00820000, 0x21084000, 0x00000000,
393 	0x00000000, 0x00000000, 0x00000000, 0x00000000,
394 	0x00000000, 0x00000000, 0x00000000, 0x00000000,
395 	0x00000000, 0x00000000, 0x00000000, 0x00000000,
396 	0x00000000, 0x00000000, 0x00000000, 0x00000000,
397 	0x00000000, 0x00000000, 0x00000000, 0x00000000,
398 };
399 
400 /* Packet types for packets with an Innermost/Last SCTP header */
401 static const u32 ice_ptypes_sctp_il[] = {
402 	0x08000000, 0x01020204, 0x20000081, 0x04080810,
403 	0x00000204, 0x00000000, 0x00000000, 0x00000000,
404 	0x00000000, 0x01040000, 0x00000000, 0x00000000,
405 	0x00000000, 0x00000000, 0x00000000, 0x00000000,
406 	0x00000000, 0x00000000, 0x00000000, 0x00000000,
407 	0x00000000, 0x00000000, 0x00000000, 0x00000000,
408 	0x00000000, 0x00000000, 0x00000000, 0x00000000,
409 	0x00000000, 0x00000000, 0x00000000, 0x00000000,
410 };
411 
412 /* Packet types for packets with an Outermost/First ICMP header */
413 static const u32 ice_ptypes_icmp_of[] = {
414 	0x10000000, 0x00000000, 0x00000000, 0x00000000,
415 	0x00000000, 0x00000000, 0x00000000, 0x00000000,
416 	0x00000000, 0x00000000, 0x00000000, 0x00000000,
417 	0x00000000, 0x00000000, 0x00000000, 0x00000000,
418 	0x00000000, 0x00000000, 0x00000000, 0x00000000,
419 	0x00000000, 0x00000000, 0x00000000, 0x00000000,
420 	0x00000000, 0x00000000, 0x00000000, 0x00000000,
421 	0x00000000, 0x00000000, 0x00000000, 0x00000000,
422 };
423 
424 /* Packet types for packets with an Innermost/Last ICMP header */
425 static const u32 ice_ptypes_icmp_il[] = {
426 	0x00000000, 0x02040408, 0x40000102, 0x08101020,
427 	0x00000408, 0x00000000, 0x00000000, 0x00000000,
428 	0x00000000, 0x00000000, 0x42108000, 0x00000000,
429 	0x00000000, 0x00000000, 0x00000000, 0x00000000,
430 	0x00000000, 0x00000000, 0x00000000, 0x00000000,
431 	0x00000000, 0x00000000, 0x00000000, 0x00000000,
432 	0x00000000, 0x00000000, 0x00000000, 0x00000000,
433 	0x00000000, 0x00000000, 0x00000000, 0x00000000,
434 };
435 
436 /* Packet types for packets with an Outermost/First GRE header */
437 static const u32 ice_ptypes_gre_of[] = {
438 	0x00000000, 0xBFBF7800, 0x000001DF, 0xFEFDE000,
439 	0x0000017E, 0x00000000, 0x00000000, 0x00000000,
440 	0x00000000, 0x00000000, 0x00000000, 0x00000000,
441 	0x00000000, 0x00000000, 0x00000000, 0x00000000,
442 	0x00000000, 0x00000000, 0x00000000, 0x00000000,
443 	0x00000000, 0x00000000, 0x00000000, 0x00000000,
444 	0x00000000, 0x00000000, 0x00000000, 0x00000000,
445 	0x00000000, 0x00000000, 0x00000000, 0x00000000,
446 };
447 
448 /* Packet types for packets with an Innermost/Last MAC header */
449 static const u32 ice_ptypes_mac_il[] = {
450 	0x00000000, 0x20000000, 0x00000000, 0x00000000,
451 	0x00000000, 0x00000000, 0x00000000, 0x00000000,
452 	0x00000000, 0x00000000, 0x00000000, 0x00000000,
453 	0x00000000, 0x00000000, 0x00000000, 0x00000000,
454 	0x00000000, 0x00000000, 0x00000000, 0x00000000,
455 	0x00000000, 0x00000000, 0x00000000, 0x00000000,
456 	0x00000000, 0x00000000, 0x00000000, 0x00000000,
457 	0x00000000, 0x00000000, 0x00000000, 0x00000000,
458 };
459 
460 /* Packet types for GTPC */
461 static const u32 ice_ptypes_gtpc[] = {
462 	0x00000000, 0x00000000, 0x00000000, 0x00000000,
463 	0x00000000, 0x00000000, 0x00000000, 0x00000000,
464 	0x00000000, 0x00000000, 0x000001E0, 0x00000000,
465 	0x00000000, 0x00000000, 0x00000000, 0x00000000,
466 	0x00000000, 0x00000000, 0x00000000, 0x00000000,
467 	0x00000000, 0x00000000, 0x00000000, 0x00000000,
468 	0x00000000, 0x00000000, 0x00000000, 0x00000000,
469 	0x00000000, 0x00000000, 0x00000000, 0x00000000,
470 };
471 
472 /* Packet types for VXLAN with VNI */
473 static const u32 ice_ptypes_vxlan_vni[] = {
474 	0x00000000, 0xBFBFF800, 0x00EFDFDF, 0xFEFDE000,
475 	0x03BF7F7E, 0x00000000, 0x00000000, 0x00000000,
476 	0x00000000, 0x00000000, 0x00000000, 0x00000000,
477 	0x00000000, 0x00000000, 0x00000000, 0x00000000,
478 	0x00000000, 0x00000000, 0x00000000, 0x00000000,
479 	0x00000000, 0x00000000, 0x00000000, 0x00000000,
480 	0x00000000, 0x00000000, 0x00000000, 0x00000000,
481 	0x00000000, 0x00000000, 0x00000000, 0x00000000,
482 };
483 
484 /* Packet types for GTPC with TEID */
485 static const u32 ice_ptypes_gtpc_tid[] = {
486 	0x00000000, 0x00000000, 0x00000000, 0x00000000,
487 	0x00000000, 0x00000000, 0x00000000, 0x00000000,
488 	0x00000000, 0x00000000, 0x00000060, 0x00000000,
489 	0x00000000, 0x00000000, 0x00000000, 0x00000000,
490 	0x00000000, 0x00000000, 0x00000000, 0x00000000,
491 	0x00000000, 0x00000000, 0x00000000, 0x00000000,
492 	0x00000000, 0x00000000, 0x00000000, 0x00000000,
493 	0x00000000, 0x00000000, 0x00000000, 0x00000000,
494 };
495 
496 /* Packet types for GTPU */
497 static const struct ice_ptype_attributes ice_attr_gtpu_session[] = {
498 	{ ICE_MAC_IPV4_GTPU_IPV4_FRAG,	  ICE_PTYPE_ATTR_GTP_SESSION },
499 	{ ICE_MAC_IPV4_GTPU_IPV4_PAY,	  ICE_PTYPE_ATTR_GTP_SESSION },
500 	{ ICE_MAC_IPV4_GTPU_IPV4_UDP_PAY, ICE_PTYPE_ATTR_GTP_SESSION },
501 	{ ICE_MAC_IPV4_GTPU_IPV4_TCP,	  ICE_PTYPE_ATTR_GTP_SESSION },
502 	{ ICE_MAC_IPV4_GTPU_IPV4_ICMP,	  ICE_PTYPE_ATTR_GTP_SESSION },
503 	{ ICE_MAC_IPV6_GTPU_IPV4_FRAG,	  ICE_PTYPE_ATTR_GTP_SESSION },
504 	{ ICE_MAC_IPV6_GTPU_IPV4_PAY,	  ICE_PTYPE_ATTR_GTP_SESSION },
505 	{ ICE_MAC_IPV6_GTPU_IPV4_UDP_PAY, ICE_PTYPE_ATTR_GTP_SESSION },
506 	{ ICE_MAC_IPV6_GTPU_IPV4_TCP,	  ICE_PTYPE_ATTR_GTP_SESSION },
507 	{ ICE_MAC_IPV6_GTPU_IPV4_ICMP,	  ICE_PTYPE_ATTR_GTP_SESSION },
508 	{ ICE_MAC_IPV4_GTPU_IPV6_FRAG,	  ICE_PTYPE_ATTR_GTP_SESSION },
509 	{ ICE_MAC_IPV4_GTPU_IPV6_PAY,	  ICE_PTYPE_ATTR_GTP_SESSION },
510 	{ ICE_MAC_IPV4_GTPU_IPV6_UDP_PAY, ICE_PTYPE_ATTR_GTP_SESSION },
511 	{ ICE_MAC_IPV4_GTPU_IPV6_TCP,	  ICE_PTYPE_ATTR_GTP_SESSION },
512 	{ ICE_MAC_IPV4_GTPU_IPV6_ICMPV6,  ICE_PTYPE_ATTR_GTP_SESSION },
513 	{ ICE_MAC_IPV6_GTPU_IPV6_FRAG,	  ICE_PTYPE_ATTR_GTP_SESSION },
514 	{ ICE_MAC_IPV6_GTPU_IPV6_PAY,	  ICE_PTYPE_ATTR_GTP_SESSION },
515 	{ ICE_MAC_IPV6_GTPU_IPV6_UDP_PAY, ICE_PTYPE_ATTR_GTP_SESSION },
516 	{ ICE_MAC_IPV6_GTPU_IPV6_TCP,	  ICE_PTYPE_ATTR_GTP_SESSION },
517 	{ ICE_MAC_IPV6_GTPU_IPV6_ICMPV6,  ICE_PTYPE_ATTR_GTP_SESSION },
518 };
519 
520 static const struct ice_ptype_attributes ice_attr_gtpu_eh[] = {
521 	{ ICE_MAC_IPV4_GTPU_IPV4_FRAG,	  ICE_PTYPE_ATTR_GTP_PDU_EH },
522 	{ ICE_MAC_IPV4_GTPU_IPV4_PAY,	  ICE_PTYPE_ATTR_GTP_PDU_EH },
523 	{ ICE_MAC_IPV4_GTPU_IPV4_UDP_PAY, ICE_PTYPE_ATTR_GTP_PDU_EH },
524 	{ ICE_MAC_IPV4_GTPU_IPV4_TCP,	  ICE_PTYPE_ATTR_GTP_PDU_EH },
525 	{ ICE_MAC_IPV4_GTPU_IPV4_ICMP,	  ICE_PTYPE_ATTR_GTP_PDU_EH },
526 	{ ICE_MAC_IPV6_GTPU_IPV4_FRAG,	  ICE_PTYPE_ATTR_GTP_PDU_EH },
527 	{ ICE_MAC_IPV6_GTPU_IPV4_PAY,	  ICE_PTYPE_ATTR_GTP_PDU_EH },
528 	{ ICE_MAC_IPV6_GTPU_IPV4_UDP_PAY, ICE_PTYPE_ATTR_GTP_PDU_EH },
529 	{ ICE_MAC_IPV6_GTPU_IPV4_TCP,	  ICE_PTYPE_ATTR_GTP_PDU_EH },
530 	{ ICE_MAC_IPV6_GTPU_IPV4_ICMP,	  ICE_PTYPE_ATTR_GTP_PDU_EH },
531 	{ ICE_MAC_IPV4_GTPU_IPV6_FRAG,	  ICE_PTYPE_ATTR_GTP_PDU_EH },
532 	{ ICE_MAC_IPV4_GTPU_IPV6_PAY,	  ICE_PTYPE_ATTR_GTP_PDU_EH },
533 	{ ICE_MAC_IPV4_GTPU_IPV6_UDP_PAY, ICE_PTYPE_ATTR_GTP_PDU_EH },
534 	{ ICE_MAC_IPV4_GTPU_IPV6_TCP,	  ICE_PTYPE_ATTR_GTP_PDU_EH },
535 	{ ICE_MAC_IPV4_GTPU_IPV6_ICMPV6,  ICE_PTYPE_ATTR_GTP_PDU_EH },
536 	{ ICE_MAC_IPV6_GTPU_IPV6_FRAG,	  ICE_PTYPE_ATTR_GTP_PDU_EH },
537 	{ ICE_MAC_IPV6_GTPU_IPV6_PAY,	  ICE_PTYPE_ATTR_GTP_PDU_EH },
538 	{ ICE_MAC_IPV6_GTPU_IPV6_UDP_PAY, ICE_PTYPE_ATTR_GTP_PDU_EH },
539 	{ ICE_MAC_IPV6_GTPU_IPV6_TCP,	  ICE_PTYPE_ATTR_GTP_PDU_EH },
540 	{ ICE_MAC_IPV6_GTPU_IPV6_ICMPV6,  ICE_PTYPE_ATTR_GTP_PDU_EH },
541 };
542 
543 static const struct ice_ptype_attributes ice_attr_gtpu_down[] = {
544 	{ ICE_MAC_IPV4_GTPU_IPV4_FRAG,	  ICE_PTYPE_ATTR_GTP_DOWNLINK },
545 	{ ICE_MAC_IPV4_GTPU_IPV4_PAY,	  ICE_PTYPE_ATTR_GTP_DOWNLINK },
546 	{ ICE_MAC_IPV4_GTPU_IPV4_UDP_PAY, ICE_PTYPE_ATTR_GTP_DOWNLINK },
547 	{ ICE_MAC_IPV4_GTPU_IPV4_TCP,	  ICE_PTYPE_ATTR_GTP_DOWNLINK },
548 	{ ICE_MAC_IPV4_GTPU_IPV4_ICMP,	  ICE_PTYPE_ATTR_GTP_DOWNLINK },
549 	{ ICE_MAC_IPV6_GTPU_IPV4_FRAG,	  ICE_PTYPE_ATTR_GTP_DOWNLINK },
550 	{ ICE_MAC_IPV6_GTPU_IPV4_PAY,	  ICE_PTYPE_ATTR_GTP_DOWNLINK },
551 	{ ICE_MAC_IPV6_GTPU_IPV4_UDP_PAY, ICE_PTYPE_ATTR_GTP_DOWNLINK },
552 	{ ICE_MAC_IPV6_GTPU_IPV4_TCP,	  ICE_PTYPE_ATTR_GTP_DOWNLINK },
553 	{ ICE_MAC_IPV6_GTPU_IPV4_ICMP,	  ICE_PTYPE_ATTR_GTP_DOWNLINK },
554 	{ ICE_MAC_IPV4_GTPU_IPV6_FRAG,	  ICE_PTYPE_ATTR_GTP_DOWNLINK },
555 	{ ICE_MAC_IPV4_GTPU_IPV6_PAY,	  ICE_PTYPE_ATTR_GTP_DOWNLINK },
556 	{ ICE_MAC_IPV4_GTPU_IPV6_UDP_PAY, ICE_PTYPE_ATTR_GTP_DOWNLINK },
557 	{ ICE_MAC_IPV4_GTPU_IPV6_TCP,	  ICE_PTYPE_ATTR_GTP_DOWNLINK },
558 	{ ICE_MAC_IPV4_GTPU_IPV6_ICMPV6,  ICE_PTYPE_ATTR_GTP_DOWNLINK },
559 	{ ICE_MAC_IPV6_GTPU_IPV6_FRAG,	  ICE_PTYPE_ATTR_GTP_DOWNLINK },
560 	{ ICE_MAC_IPV6_GTPU_IPV6_PAY,	  ICE_PTYPE_ATTR_GTP_DOWNLINK },
561 	{ ICE_MAC_IPV6_GTPU_IPV6_UDP_PAY, ICE_PTYPE_ATTR_GTP_DOWNLINK },
562 	{ ICE_MAC_IPV6_GTPU_IPV6_TCP,	  ICE_PTYPE_ATTR_GTP_DOWNLINK },
563 	{ ICE_MAC_IPV6_GTPU_IPV6_ICMPV6,  ICE_PTYPE_ATTR_GTP_DOWNLINK },
564 };
565 
566 static const struct ice_ptype_attributes ice_attr_gtpu_up[] = {
567 	{ ICE_MAC_IPV4_GTPU_IPV4_FRAG,	  ICE_PTYPE_ATTR_GTP_UPLINK },
568 	{ ICE_MAC_IPV4_GTPU_IPV4_PAY,	  ICE_PTYPE_ATTR_GTP_UPLINK },
569 	{ ICE_MAC_IPV4_GTPU_IPV4_UDP_PAY, ICE_PTYPE_ATTR_GTP_UPLINK },
570 	{ ICE_MAC_IPV4_GTPU_IPV4_TCP,	  ICE_PTYPE_ATTR_GTP_UPLINK },
571 	{ ICE_MAC_IPV4_GTPU_IPV4_ICMP,	  ICE_PTYPE_ATTR_GTP_UPLINK },
572 	{ ICE_MAC_IPV6_GTPU_IPV4_FRAG,	  ICE_PTYPE_ATTR_GTP_UPLINK },
573 	{ ICE_MAC_IPV6_GTPU_IPV4_PAY,	  ICE_PTYPE_ATTR_GTP_UPLINK },
574 	{ ICE_MAC_IPV6_GTPU_IPV4_UDP_PAY, ICE_PTYPE_ATTR_GTP_UPLINK },
575 	{ ICE_MAC_IPV6_GTPU_IPV4_TCP,	  ICE_PTYPE_ATTR_GTP_UPLINK },
576 	{ ICE_MAC_IPV6_GTPU_IPV4_ICMP,	  ICE_PTYPE_ATTR_GTP_UPLINK },
577 	{ ICE_MAC_IPV4_GTPU_IPV6_FRAG,	  ICE_PTYPE_ATTR_GTP_UPLINK },
578 	{ ICE_MAC_IPV4_GTPU_IPV6_PAY,	  ICE_PTYPE_ATTR_GTP_UPLINK },
579 	{ ICE_MAC_IPV4_GTPU_IPV6_UDP_PAY, ICE_PTYPE_ATTR_GTP_UPLINK },
580 	{ ICE_MAC_IPV4_GTPU_IPV6_TCP,	  ICE_PTYPE_ATTR_GTP_UPLINK },
581 	{ ICE_MAC_IPV4_GTPU_IPV6_ICMPV6,  ICE_PTYPE_ATTR_GTP_UPLINK },
582 	{ ICE_MAC_IPV6_GTPU_IPV6_FRAG,	  ICE_PTYPE_ATTR_GTP_UPLINK },
583 	{ ICE_MAC_IPV6_GTPU_IPV6_PAY,	  ICE_PTYPE_ATTR_GTP_UPLINK },
584 	{ ICE_MAC_IPV6_GTPU_IPV6_UDP_PAY, ICE_PTYPE_ATTR_GTP_UPLINK },
585 	{ ICE_MAC_IPV6_GTPU_IPV6_TCP,	  ICE_PTYPE_ATTR_GTP_UPLINK },
586 	{ ICE_MAC_IPV6_GTPU_IPV6_ICMPV6,  ICE_PTYPE_ATTR_GTP_UPLINK },
587 };
588 
589 static const u32 ice_ptypes_gtpu[] = {
590 	0x00000000, 0x00000000, 0x00000000, 0x00000000,
591 	0x00000000, 0x00000000, 0x00000000, 0x00000000,
592 	0x00000000, 0x00000000, 0x7FFFFE00, 0x00000000,
593 	0x00000000, 0x00000000, 0x00000000, 0x00000000,
594 	0x00000000, 0x00000000, 0x00000000, 0x00000000,
595 	0x00000000, 0x00000000, 0x00000000, 0x00000000,
596 	0x00000000, 0x00000000, 0x00000000, 0x00000000,
597 	0x00000000, 0x00000000, 0x00000000, 0x00000000,
598 };
599 
600 /* Packet types for pppoe */
601 static const u32 ice_ptypes_pppoe[] = {
602 	0x00000000, 0x00000000, 0x00000000, 0x00000000,
603 	0x00000000, 0x00000000, 0x00000000, 0x00000000,
604 	0x00000000, 0x03ffe000, 0x00000000, 0x00000000,
605 	0x00000000, 0x00000000, 0x00000000, 0x00000000,
606 	0x00000000, 0x00000000, 0x00000000, 0x00000000,
607 	0x00000000, 0x00000000, 0x00000000, 0x00000000,
608 	0x00000000, 0x00000000, 0x00000000, 0x00000000,
609 	0x00000000, 0x00000000, 0x00000000, 0x00000000,
610 };
611 
612 /* Packet types for packets with PFCP NODE header */
613 static const u32 ice_ptypes_pfcp_node[] = {
614 	0x00000000, 0x00000000, 0x00000000, 0x00000000,
615 	0x00000000, 0x00000000, 0x00000000, 0x00000000,
616 	0x00000000, 0x00000000, 0x80000000, 0x00000002,
617 	0x00000000, 0x00000000, 0x00000000, 0x00000000,
618 	0x00000000, 0x00000000, 0x00000000, 0x00000000,
619 	0x00000000, 0x00000000, 0x00000000, 0x00000000,
620 	0x00000000, 0x00000000, 0x00000000, 0x00000000,
621 	0x00000000, 0x00000000, 0x00000000, 0x00000000,
622 };
623 
624 /* Packet types for packets with PFCP SESSION header */
625 static const u32 ice_ptypes_pfcp_session[] = {
626 	0x00000000, 0x00000000, 0x00000000, 0x00000000,
627 	0x00000000, 0x00000000, 0x00000000, 0x00000000,
628 	0x00000000, 0x00000000, 0x00000000, 0x00000005,
629 	0x00000000, 0x00000000, 0x00000000, 0x00000000,
630 	0x00000000, 0x00000000, 0x00000000, 0x00000000,
631 	0x00000000, 0x00000000, 0x00000000, 0x00000000,
632 	0x00000000, 0x00000000, 0x00000000, 0x00000000,
633 	0x00000000, 0x00000000, 0x00000000, 0x00000000,
634 };
635 
636 /* Packet types for l2tpv3 */
637 static const u32 ice_ptypes_l2tpv3[] = {
638 	0x00000000, 0x00000000, 0x00000000, 0x00000000,
639 	0x00000000, 0x00000000, 0x00000000, 0x00000000,
640 	0x00000000, 0x00000000, 0x00000000, 0x00000300,
641 	0x00000000, 0x00000000, 0x00000000, 0x00000000,
642 	0x00000000, 0x00000000, 0x00000000, 0x00000000,
643 	0x00000000, 0x00000000, 0x00000000, 0x00000000,
644 	0x00000000, 0x00000000, 0x00000000, 0x00000000,
645 	0x00000000, 0x00000000, 0x00000000, 0x00000000,
646 };
647 
648 /* Packet types for esp */
649 static const u32 ice_ptypes_esp[] = {
650 	0x00000000, 0x00000000, 0x00000000, 0x00000000,
651 	0x00000000, 0x00000003, 0x00000000, 0x00000000,
652 	0x00000000, 0x00000000, 0x00000000, 0x00000000,
653 	0x00000000, 0x00000000, 0x00000000, 0x00000000,
654 	0x00000000, 0x00000000, 0x00000000, 0x00000000,
655 	0x00000000, 0x00000000, 0x00000000, 0x00000000,
656 	0x00000000, 0x00000000, 0x00000000, 0x00000000,
657 	0x00000000, 0x00000000, 0x00000000, 0x00000000,
658 };
659 
660 /* Packet types for ah */
661 static const u32 ice_ptypes_ah[] = {
662 	0x00000000, 0x00000000, 0x00000000, 0x00000000,
663 	0x00000000, 0x0000000C, 0x00000000, 0x00000000,
664 	0x00000000, 0x00000000, 0x00000000, 0x00000000,
665 	0x00000000, 0x00000000, 0x00000000, 0x00000000,
666 	0x00000000, 0x00000000, 0x00000000, 0x00000000,
667 	0x00000000, 0x00000000, 0x00000000, 0x00000000,
668 	0x00000000, 0x00000000, 0x00000000, 0x00000000,
669 	0x00000000, 0x00000000, 0x00000000, 0x00000000,
670 };
671 
672 /* Packet types for packets with NAT_T ESP header */
673 static const u32 ice_ptypes_nat_t_esp[] = {
674 	0x00000000, 0x00000000, 0x00000000, 0x00000000,
675 	0x00000000, 0x00000030, 0x00000000, 0x00000000,
676 	0x00000000, 0x00000000, 0x00000000, 0x00000000,
677 	0x00000000, 0x00000000, 0x00000000, 0x00000000,
678 	0x00000000, 0x00000000, 0x00000000, 0x00000000,
679 	0x00000000, 0x00000000, 0x00000000, 0x00000000,
680 	0x00000000, 0x00000000, 0x00000000, 0x00000000,
681 	0x00000000, 0x00000000, 0x00000000, 0x00000000,
682 };
683 
684 static const u32 ice_ptypes_mac_non_ip_ofos[] = {
685 	0x00000846, 0x00000000, 0x00000000, 0x00000000,
686 	0x00000000, 0x00000000, 0x00000000, 0x00000000,
687 	0x00400000, 0x03FFF000, 0x00000000, 0x00000000,
688 	0x00000000, 0x00000000, 0x00000000, 0x00000000,
689 	0x00000000, 0x00000000, 0x00000000, 0x00000000,
690 	0x00000000, 0x00000000, 0x00000000, 0x00000000,
691 	0x00000000, 0x00000000, 0x00000000, 0x00000000,
692 	0x00000000, 0x00000000, 0x00000000, 0x00000000,
693 };
694 
695 static const u32 ice_ptypes_gtpu_no_ip[] = {
696 	0x00000000, 0x00000000, 0x00000000, 0x00000000,
697 	0x00000000, 0x00000000, 0x00000000, 0x00000000,
698 	0x00000000, 0x00000000, 0x00000600, 0x00000000,
699 	0x00000000, 0x00000000, 0x00000000, 0x00000000,
700 	0x00000000, 0x00000000, 0x00000000, 0x00000000,
701 	0x00000000, 0x00000000, 0x00000000, 0x00000000,
702 	0x00000000, 0x00000000, 0x00000000, 0x00000000,
703 	0x00000000, 0x00000000, 0x00000000, 0x00000000,
704 };
705 
706 static const u32 ice_ptypes_ecpri_tp0[] = {
707 	0x00000000, 0x00000000, 0x00000000, 0x00000000,
708 	0x00000000, 0x00000000, 0x00000000, 0x00000000,
709 	0x00000000, 0x00000000, 0x00000000, 0x00000400,
710 	0x00000000, 0x00000000, 0x00000000, 0x00000000,
711 	0x00000000, 0x00000000, 0x00000000, 0x00000000,
712 	0x00000000, 0x00000000, 0x00000000, 0x00000000,
713 	0x00000000, 0x00000000, 0x00000000, 0x00000000,
714 	0x00000000, 0x00000000, 0x00000000, 0x00000000,
715 };
716 
717 static const u32 ice_ptypes_udp_ecpri_tp0[] = {
718 	0x00000000, 0x00000000, 0x00000000, 0x00000000,
719 	0x00000000, 0x00000000, 0x00000000, 0x00000000,
720 	0x00000000, 0x00000000, 0x00000000, 0x00100000,
721 	0x00000000, 0x00000000, 0x00000000, 0x00000000,
722 	0x00000000, 0x00000000, 0x00000000, 0x00000000,
723 	0x00000000, 0x00000000, 0x00000000, 0x00000000,
724 	0x00000000, 0x00000000, 0x00000000, 0x00000000,
725 	0x00000000, 0x00000000, 0x00000000, 0x00000000,
726 };
727 
728 /* Manage parameters and info. used during the creation of a flow profile */
729 struct ice_flow_prof_params {
730 	enum ice_block blk;
731 	u16 entry_length; /* # of bytes formatted entry will require */
732 	u8 es_cnt;
733 	struct ice_flow_prof *prof;
734 
735 	/* For ACL, the es[0] will have the data of ICE_RX_MDID_PKT_FLAGS_15_0
736 	 * This will give us the direction flags.
737 	 */
738 	struct ice_fv_word es[ICE_MAX_FV_WORDS];
739 	/* attributes can be used to add attributes to a particular PTYPE */
740 	const struct ice_ptype_attributes *attr;
741 	u16 attr_cnt;
742 
743 	u16 mask[ICE_MAX_FV_WORDS];
744 	ice_declare_bitmap(ptypes, ICE_FLOW_PTYPE_MAX);
745 };
746 
747 #define ICE_FLOW_RSS_HDRS_INNER_MASK \
748 	(ICE_FLOW_SEG_HDR_PPPOE | ICE_FLOW_SEG_HDR_GTPC | \
749 	ICE_FLOW_SEG_HDR_GTPC_TEID | ICE_FLOW_SEG_HDR_GTPU | \
750 	ICE_FLOW_SEG_HDR_PFCP_SESSION | ICE_FLOW_SEG_HDR_L2TPV3 | \
751 	ICE_FLOW_SEG_HDR_ESP | ICE_FLOW_SEG_HDR_AH | \
752 	ICE_FLOW_SEG_HDR_NAT_T_ESP | ICE_FLOW_SEG_HDR_GTPU_NON_IP | \
753 	ICE_FLOW_SEG_HDR_ECPRI_TP0 | ICE_FLOW_SEG_HDR_UDP_ECPRI_TP0)
754 
755 #define ICE_FLOW_SEG_HDRS_L2_MASK	\
756 	(ICE_FLOW_SEG_HDR_ETH | ICE_FLOW_SEG_HDR_VLAN)
757 #define ICE_FLOW_SEG_HDRS_L3_MASK	\
758 	(ICE_FLOW_SEG_HDR_IPV4 | ICE_FLOW_SEG_HDR_IPV6 | \
759 	 ICE_FLOW_SEG_HDR_ARP)
760 #define ICE_FLOW_SEG_HDRS_L4_MASK	\
761 	(ICE_FLOW_SEG_HDR_ICMP | ICE_FLOW_SEG_HDR_TCP | ICE_FLOW_SEG_HDR_UDP | \
762 	 ICE_FLOW_SEG_HDR_SCTP)
763 /* mask for L4 protocols that are NOT part of IPV4/6 OTHER PTYPE groups */
764 #define ICE_FLOW_SEG_HDRS_L4_MASK_NO_OTHER	\
765 	(ICE_FLOW_SEG_HDR_TCP | ICE_FLOW_SEG_HDR_UDP | ICE_FLOW_SEG_HDR_SCTP)
766 
767 /**
768  * ice_flow_val_hdrs - validates packet segments for valid protocol headers
769  * @segs: array of one or more packet segments that describe the flow
770  * @segs_cnt: number of packet segments provided
771  */
772 static enum ice_status
773 ice_flow_val_hdrs(struct ice_flow_seg_info *segs, u8 segs_cnt)
774 {
775 	u8 i;
776 
777 	for (i = 0; i < segs_cnt; i++) {
778 		/* Multiple L3 headers */
779 		if (segs[i].hdrs & ICE_FLOW_SEG_HDRS_L3_MASK &&
780 		    !ice_is_pow2(segs[i].hdrs & ICE_FLOW_SEG_HDRS_L3_MASK))
781 			return ICE_ERR_PARAM;
782 
783 		/* Multiple L4 headers */
784 		if (segs[i].hdrs & ICE_FLOW_SEG_HDRS_L4_MASK &&
785 		    !ice_is_pow2(segs[i].hdrs & ICE_FLOW_SEG_HDRS_L4_MASK))
786 			return ICE_ERR_PARAM;
787 	}
788 
789 	return ICE_SUCCESS;
790 }
791 
792 /* Sizes of fixed known protocol headers without header options */
793 #define ICE_FLOW_PROT_HDR_SZ_MAC	14
794 #define ICE_FLOW_PROT_HDR_SZ_MAC_VLAN	(ICE_FLOW_PROT_HDR_SZ_MAC + 2)
795 #define ICE_FLOW_PROT_HDR_SZ_IPV4	20
796 #define ICE_FLOW_PROT_HDR_SZ_IPV6	40
797 #define ICE_FLOW_PROT_HDR_SZ_ARP	28
798 #define ICE_FLOW_PROT_HDR_SZ_ICMP	8
799 #define ICE_FLOW_PROT_HDR_SZ_TCP	20
800 #define ICE_FLOW_PROT_HDR_SZ_UDP	8
801 #define ICE_FLOW_PROT_HDR_SZ_SCTP	12
802 
803 /**
804  * ice_flow_calc_seg_sz - calculates size of a packet segment based on headers
805  * @params: information about the flow to be processed
806  * @seg: index of packet segment whose header size is to be determined
807  */
808 static u16 ice_flow_calc_seg_sz(struct ice_flow_prof_params *params, u8 seg)
809 {
810 	u16 sz;
811 
812 	/* L2 headers */
813 	sz = (params->prof->segs[seg].hdrs & ICE_FLOW_SEG_HDR_VLAN) ?
814 		ICE_FLOW_PROT_HDR_SZ_MAC_VLAN : ICE_FLOW_PROT_HDR_SZ_MAC;
815 
816 	/* L3 headers */
817 	if (params->prof->segs[seg].hdrs & ICE_FLOW_SEG_HDR_IPV4)
818 		sz += ICE_FLOW_PROT_HDR_SZ_IPV4;
819 	else if (params->prof->segs[seg].hdrs & ICE_FLOW_SEG_HDR_IPV6)
820 		sz += ICE_FLOW_PROT_HDR_SZ_IPV6;
821 	else if (params->prof->segs[seg].hdrs & ICE_FLOW_SEG_HDR_ARP)
822 		sz += ICE_FLOW_PROT_HDR_SZ_ARP;
823 	else if (params->prof->segs[seg].hdrs & ICE_FLOW_SEG_HDRS_L4_MASK)
824 		/* A L3 header is required if L4 is specified */
825 		return 0;
826 
827 	/* L4 headers */
828 	if (params->prof->segs[seg].hdrs & ICE_FLOW_SEG_HDR_ICMP)
829 		sz += ICE_FLOW_PROT_HDR_SZ_ICMP;
830 	else if (params->prof->segs[seg].hdrs & ICE_FLOW_SEG_HDR_TCP)
831 		sz += ICE_FLOW_PROT_HDR_SZ_TCP;
832 	else if (params->prof->segs[seg].hdrs & ICE_FLOW_SEG_HDR_UDP)
833 		sz += ICE_FLOW_PROT_HDR_SZ_UDP;
834 	else if (params->prof->segs[seg].hdrs & ICE_FLOW_SEG_HDR_SCTP)
835 		sz += ICE_FLOW_PROT_HDR_SZ_SCTP;
836 
837 	return sz;
838 }
839 
840 /**
841  * ice_flow_proc_seg_hdrs - process protocol headers present in pkt segments
842  * @params: information about the flow to be processed
843  *
844  * This function identifies the packet types associated with the protocol
845  * headers being present in packet segments of the specified flow profile.
846  */
847 static enum ice_status
848 ice_flow_proc_seg_hdrs(struct ice_flow_prof_params *params)
849 {
850 	struct ice_flow_prof *prof;
851 	u8 i;
852 
853 	ice_memset(params->ptypes, 0xff, sizeof(params->ptypes),
854 		   ICE_NONDMA_MEM);
855 
856 	prof = params->prof;
857 
858 	for (i = 0; i < params->prof->segs_cnt; i++) {
859 		const ice_bitmap_t *src;
860 		u32 hdrs;
861 
862 		hdrs = prof->segs[i].hdrs;
863 
864 		if (hdrs & ICE_FLOW_SEG_HDR_ETH) {
865 			src = !i ? (const ice_bitmap_t *)ice_ptypes_mac_ofos :
866 				(const ice_bitmap_t *)ice_ptypes_mac_il;
867 			ice_and_bitmap(params->ptypes, params->ptypes, src,
868 				       ICE_FLOW_PTYPE_MAX);
869 		}
870 
871 		if (i && hdrs & ICE_FLOW_SEG_HDR_VLAN) {
872 			src = (const ice_bitmap_t *)ice_ptypes_macvlan_il;
873 			ice_and_bitmap(params->ptypes, params->ptypes, src,
874 				       ICE_FLOW_PTYPE_MAX);
875 		}
876 
877 		if (!i && hdrs & ICE_FLOW_SEG_HDR_ARP) {
878 			ice_and_bitmap(params->ptypes, params->ptypes,
879 				       (const ice_bitmap_t *)ice_ptypes_arp_of,
880 				       ICE_FLOW_PTYPE_MAX);
881 		}
882 
883 		if (hdrs & ICE_FLOW_SEG_HDR_ECPRI_TP0) {
884 			src = (const ice_bitmap_t *)ice_ptypes_ecpri_tp0;
885 			ice_and_bitmap(params->ptypes, params->ptypes, src,
886 				       ICE_FLOW_PTYPE_MAX);
887 		}
888 		if ((hdrs & ICE_FLOW_SEG_HDR_IPV4) &&
889 		    (hdrs & ICE_FLOW_SEG_HDR_IPV_OTHER)) {
890 			src = i ?
891 				(const ice_bitmap_t *)ice_ptypes_ipv4_il :
892 				(const ice_bitmap_t *)ice_ptypes_ipv4_ofos_all;
893 			ice_and_bitmap(params->ptypes, params->ptypes, src,
894 				       ICE_FLOW_PTYPE_MAX);
895 		} else if ((hdrs & ICE_FLOW_SEG_HDR_IPV6) &&
896 			   (hdrs & ICE_FLOW_SEG_HDR_IPV_OTHER)) {
897 			src = i ?
898 				(const ice_bitmap_t *)ice_ptypes_ipv6_il :
899 				(const ice_bitmap_t *)ice_ptypes_ipv6_ofos_all;
900 			ice_and_bitmap(params->ptypes, params->ptypes, src,
901 				       ICE_FLOW_PTYPE_MAX);
902 		} else if ((hdrs & ICE_FLOW_SEG_HDR_IPV4) &&
903 			   !(hdrs & ICE_FLOW_SEG_HDRS_L4_MASK_NO_OTHER)) {
904 			src = !i ? (const ice_bitmap_t *)ice_ptypes_ipv4_ofos_no_l4 :
905 				(const ice_bitmap_t *)ice_ptypes_ipv4_il_no_l4;
906 			ice_and_bitmap(params->ptypes, params->ptypes, src,
907 				       ICE_FLOW_PTYPE_MAX);
908 		} else if (hdrs & ICE_FLOW_SEG_HDR_IPV4) {
909 			src = !i ? (const ice_bitmap_t *)ice_ptypes_ipv4_ofos :
910 				(const ice_bitmap_t *)ice_ptypes_ipv4_il;
911 			ice_and_bitmap(params->ptypes, params->ptypes, src,
912 				       ICE_FLOW_PTYPE_MAX);
913 		} else if ((hdrs & ICE_FLOW_SEG_HDR_IPV6) &&
914 			   !(hdrs & ICE_FLOW_SEG_HDRS_L4_MASK_NO_OTHER)) {
915 			src = !i ? (const ice_bitmap_t *)ice_ptypes_ipv6_ofos_no_l4 :
916 				(const ice_bitmap_t *)ice_ptypes_ipv6_il_no_l4;
917 			ice_and_bitmap(params->ptypes, params->ptypes, src,
918 				       ICE_FLOW_PTYPE_MAX);
919 		} else if (hdrs & ICE_FLOW_SEG_HDR_IPV6) {
920 			src = !i ? (const ice_bitmap_t *)ice_ptypes_ipv6_ofos :
921 				(const ice_bitmap_t *)ice_ptypes_ipv6_il;
922 			ice_and_bitmap(params->ptypes, params->ptypes, src,
923 				       ICE_FLOW_PTYPE_MAX);
924 		}
925 
926 		if (hdrs & ICE_FLOW_SEG_HDR_ETH_NON_IP) {
927 			src = (const ice_bitmap_t *)ice_ptypes_mac_non_ip_ofos;
928 			ice_and_bitmap(params->ptypes, params->ptypes,
929 				       src, ICE_FLOW_PTYPE_MAX);
930 		} else if (hdrs & ICE_FLOW_SEG_HDR_PPPOE) {
931 			src = (const ice_bitmap_t *)ice_ptypes_pppoe;
932 			ice_and_bitmap(params->ptypes, params->ptypes, src,
933 				       ICE_FLOW_PTYPE_MAX);
934 		} else {
935 			src = (const ice_bitmap_t *)ice_ptypes_pppoe;
936 			ice_andnot_bitmap(params->ptypes, params->ptypes, src,
937 					  ICE_FLOW_PTYPE_MAX);
938 		}
939 
940 		if (hdrs & ICE_FLOW_SEG_HDR_UDP) {
941 			src = (const ice_bitmap_t *)ice_ptypes_udp_il;
942 			ice_and_bitmap(params->ptypes, params->ptypes, src,
943 				       ICE_FLOW_PTYPE_MAX);
944 		} else if (hdrs & ICE_FLOW_SEG_HDR_TCP) {
945 			ice_and_bitmap(params->ptypes, params->ptypes,
946 				       (const ice_bitmap_t *)ice_ptypes_tcp_il,
947 				       ICE_FLOW_PTYPE_MAX);
948 		} else if (hdrs & ICE_FLOW_SEG_HDR_SCTP) {
949 			src = (const ice_bitmap_t *)ice_ptypes_sctp_il;
950 			ice_and_bitmap(params->ptypes, params->ptypes, src,
951 				       ICE_FLOW_PTYPE_MAX);
952 		}
953 
954 		if (hdrs & ICE_FLOW_SEG_HDR_ICMP) {
955 			src = !i ? (const ice_bitmap_t *)ice_ptypes_icmp_of :
956 				(const ice_bitmap_t *)ice_ptypes_icmp_il;
957 			ice_and_bitmap(params->ptypes, params->ptypes, src,
958 				       ICE_FLOW_PTYPE_MAX);
959 		} else if (hdrs & ICE_FLOW_SEG_HDR_GRE) {
960 			if (!i) {
961 				src = (const ice_bitmap_t *)ice_ptypes_gre_of;
962 				ice_and_bitmap(params->ptypes, params->ptypes,
963 					       src, ICE_FLOW_PTYPE_MAX);
964 			}
965 		} else if (hdrs & ICE_FLOW_SEG_HDR_GTPC) {
966 			src = (const ice_bitmap_t *)ice_ptypes_gtpc;
967 			ice_and_bitmap(params->ptypes, params->ptypes,
968 				       src, ICE_FLOW_PTYPE_MAX);
969 		} else if (hdrs & ICE_FLOW_SEG_HDR_GTPC_TEID) {
970 			src = (const ice_bitmap_t *)ice_ptypes_gtpc_tid;
971 			ice_and_bitmap(params->ptypes, params->ptypes,
972 				       src, ICE_FLOW_PTYPE_MAX);
973 		} else if (hdrs & ICE_FLOW_SEG_HDR_GTPU_NON_IP) {
974 			src = (const ice_bitmap_t *)ice_ptypes_gtpu_no_ip;
975 			ice_and_bitmap(params->ptypes, params->ptypes,
976 				       src, ICE_FLOW_PTYPE_MAX);
977 		} else if (hdrs & ICE_FLOW_SEG_HDR_GTPU_DWN) {
978 			src = (const ice_bitmap_t *)ice_ptypes_gtpu;
979 			ice_and_bitmap(params->ptypes, params->ptypes,
980 				       src, ICE_FLOW_PTYPE_MAX);
981 
982 			/* Attributes for GTP packet with downlink */
983 			params->attr = ice_attr_gtpu_down;
984 			params->attr_cnt = ARRAY_SIZE(ice_attr_gtpu_down);
985 		} else if (hdrs & ICE_FLOW_SEG_HDR_GTPU_UP) {
986 			src = (const ice_bitmap_t *)ice_ptypes_gtpu;
987 			ice_and_bitmap(params->ptypes, params->ptypes,
988 				       src, ICE_FLOW_PTYPE_MAX);
989 
990 			/* Attributes for GTP packet with uplink */
991 			params->attr = ice_attr_gtpu_up;
992 			params->attr_cnt = ARRAY_SIZE(ice_attr_gtpu_up);
993 		} else if (hdrs & ICE_FLOW_SEG_HDR_GTPU_EH) {
994 			src = (const ice_bitmap_t *)ice_ptypes_gtpu;
995 			ice_and_bitmap(params->ptypes, params->ptypes,
996 				       src, ICE_FLOW_PTYPE_MAX);
997 
998 			/* Attributes for GTP packet with Extension Header */
999 			params->attr = ice_attr_gtpu_eh;
1000 			params->attr_cnt = ARRAY_SIZE(ice_attr_gtpu_eh);
1001 		} else if (hdrs & ICE_FLOW_SEG_HDR_GTPU_IP) {
1002 			src = (const ice_bitmap_t *)ice_ptypes_gtpu;
1003 			ice_and_bitmap(params->ptypes, params->ptypes,
1004 				       src, ICE_FLOW_PTYPE_MAX);
1005 
1006 			/* Attributes for GTP packet without Extension Header */
1007 			params->attr = ice_attr_gtpu_session;
1008 			params->attr_cnt = ARRAY_SIZE(ice_attr_gtpu_session);
1009 		} else if (hdrs & ICE_FLOW_SEG_HDR_L2TPV3) {
1010 			src = (const ice_bitmap_t *)ice_ptypes_l2tpv3;
1011 			ice_and_bitmap(params->ptypes, params->ptypes,
1012 				       src, ICE_FLOW_PTYPE_MAX);
1013 		} else if (hdrs & ICE_FLOW_SEG_HDR_ESP) {
1014 			src = (const ice_bitmap_t *)ice_ptypes_esp;
1015 			ice_and_bitmap(params->ptypes, params->ptypes,
1016 				       src, ICE_FLOW_PTYPE_MAX);
1017 		} else if (hdrs & ICE_FLOW_SEG_HDR_AH) {
1018 			src = (const ice_bitmap_t *)ice_ptypes_ah;
1019 			ice_and_bitmap(params->ptypes, params->ptypes,
1020 				       src, ICE_FLOW_PTYPE_MAX);
1021 		} else if (hdrs & ICE_FLOW_SEG_HDR_NAT_T_ESP) {
1022 			src = (const ice_bitmap_t *)ice_ptypes_nat_t_esp;
1023 			ice_and_bitmap(params->ptypes, params->ptypes,
1024 				       src, ICE_FLOW_PTYPE_MAX);
1025 		} else if (hdrs & ICE_FLOW_SEG_HDR_VXLAN) {
1026 			src = (const ice_bitmap_t *)ice_ptypes_vxlan_vni;
1027 			ice_and_bitmap(params->ptypes, params->ptypes,
1028 				       src, ICE_FLOW_PTYPE_MAX);
1029 		} else if (hdrs & ICE_FLOW_SEG_HDR_UDP_ECPRI_TP0) {
1030 			src = (const ice_bitmap_t *)ice_ptypes_udp_ecpri_tp0;
1031 			ice_and_bitmap(params->ptypes, params->ptypes,
1032 				       src, ICE_FLOW_PTYPE_MAX);
1033 		}
1034 
1035 		if (hdrs & ICE_FLOW_SEG_HDR_PFCP) {
1036 			if (hdrs & ICE_FLOW_SEG_HDR_PFCP_NODE)
1037 				src =
1038 				(const ice_bitmap_t *)ice_ptypes_pfcp_node;
1039 			else
1040 				src =
1041 				(const ice_bitmap_t *)ice_ptypes_pfcp_session;
1042 
1043 			ice_and_bitmap(params->ptypes, params->ptypes,
1044 				       src, ICE_FLOW_PTYPE_MAX);
1045 		} else {
1046 			src = (const ice_bitmap_t *)ice_ptypes_pfcp_node;
1047 			ice_andnot_bitmap(params->ptypes, params->ptypes,
1048 					  src, ICE_FLOW_PTYPE_MAX);
1049 
1050 			src = (const ice_bitmap_t *)ice_ptypes_pfcp_session;
1051 			ice_andnot_bitmap(params->ptypes, params->ptypes,
1052 					  src, ICE_FLOW_PTYPE_MAX);
1053 		}
1054 	}
1055 
1056 	return ICE_SUCCESS;
1057 }
1058 
1059 /**
1060  * ice_flow_xtract_pkt_flags - Create an extr sequence entry for packet flags
1061  * @hw: pointer to the HW struct
1062  * @params: information about the flow to be processed
1063  * @flags: The value of pkt_flags[x:x] in Rx/Tx MDID metadata.
1064  *
1065  * This function will allocate an extraction sequence entries for a DWORD size
1066  * chunk of the packet flags.
1067  */
1068 static enum ice_status
1069 ice_flow_xtract_pkt_flags(struct ice_hw *hw,
1070 			  struct ice_flow_prof_params *params,
1071 			  enum ice_flex_mdid_pkt_flags flags)
1072 {
1073 	u8 fv_words = hw->blk[params->blk].es.fvw;
1074 	u8 idx;
1075 
1076 	/* Make sure the number of extraction sequence entries required does not
1077 	 * exceed the block's capacity.
1078 	 */
1079 	if (params->es_cnt >= fv_words)
1080 		return ICE_ERR_MAX_LIMIT;
1081 
1082 	/* some blocks require a reversed field vector layout */
1083 	if (hw->blk[params->blk].es.reverse)
1084 		idx = fv_words - params->es_cnt - 1;
1085 	else
1086 		idx = params->es_cnt;
1087 
1088 	params->es[idx].prot_id = ICE_PROT_META_ID;
1089 	params->es[idx].off = flags;
1090 	params->es_cnt++;
1091 
1092 	return ICE_SUCCESS;
1093 }
1094 
1095 /**
1096  * ice_flow_xtract_fld - Create an extraction sequence entry for the given field
1097  * @hw: pointer to the HW struct
1098  * @params: information about the flow to be processed
1099  * @seg: packet segment index of the field to be extracted
1100  * @fld: ID of field to be extracted
1101  * @match: bitfield of all fields
1102  *
1103  * This function determines the protocol ID, offset, and size of the given
1104  * field. It then allocates one or more extraction sequence entries for the
1105  * given field, and fill the entries with protocol ID and offset information.
1106  */
1107 static enum ice_status
1108 ice_flow_xtract_fld(struct ice_hw *hw, struct ice_flow_prof_params *params,
1109 		    u8 seg, enum ice_flow_field fld, u64 match)
1110 {
1111 	enum ice_flow_field sib = ICE_FLOW_FIELD_IDX_MAX;
1112 	enum ice_prot_id prot_id = ICE_PROT_ID_INVAL;
1113 	u8 fv_words = hw->blk[params->blk].es.fvw;
1114 	struct ice_flow_fld_info *flds;
1115 	u16 cnt, ese_bits, i;
1116 	u16 sib_mask = 0;
1117 	u16 mask;
1118 	u16 off;
1119 
1120 	flds = params->prof->segs[seg].fields;
1121 
1122 	switch (fld) {
1123 	case ICE_FLOW_FIELD_IDX_ETH_DA:
1124 	case ICE_FLOW_FIELD_IDX_ETH_SA:
1125 	case ICE_FLOW_FIELD_IDX_S_VLAN:
1126 	case ICE_FLOW_FIELD_IDX_C_VLAN:
1127 		prot_id = seg == 0 ? ICE_PROT_MAC_OF_OR_S : ICE_PROT_MAC_IL;
1128 		break;
1129 	case ICE_FLOW_FIELD_IDX_ETH_TYPE:
1130 		prot_id = seg == 0 ? ICE_PROT_ETYPE_OL : ICE_PROT_ETYPE_IL;
1131 		break;
1132 	case ICE_FLOW_FIELD_IDX_IPV4_DSCP:
1133 		prot_id = seg == 0 ? ICE_PROT_IPV4_OF_OR_S : ICE_PROT_IPV4_IL;
1134 		break;
1135 	case ICE_FLOW_FIELD_IDX_IPV6_DSCP:
1136 		prot_id = seg == 0 ? ICE_PROT_IPV6_OF_OR_S : ICE_PROT_IPV6_IL;
1137 		break;
1138 	case ICE_FLOW_FIELD_IDX_IPV4_TTL:
1139 	case ICE_FLOW_FIELD_IDX_IPV4_PROT:
1140 		prot_id = seg == 0 ? ICE_PROT_IPV4_OF_OR_S : ICE_PROT_IPV4_IL;
1141 
1142 		/* TTL and PROT share the same extraction seq. entry.
1143 		 * Each is considered a sibling to the other in terms of sharing
1144 		 * the same extraction sequence entry.
1145 		 */
1146 		if (fld == ICE_FLOW_FIELD_IDX_IPV4_TTL)
1147 			sib = ICE_FLOW_FIELD_IDX_IPV4_PROT;
1148 		else
1149 			sib = ICE_FLOW_FIELD_IDX_IPV4_TTL;
1150 
1151 		/* If the sibling field is also included, that field's
1152 		 * mask needs to be included.
1153 		 */
1154 		if (match & BIT(sib))
1155 			sib_mask = ice_flds_info[sib].mask;
1156 		break;
1157 	case ICE_FLOW_FIELD_IDX_IPV6_TTL:
1158 	case ICE_FLOW_FIELD_IDX_IPV6_PROT:
1159 		prot_id = seg == 0 ? ICE_PROT_IPV6_OF_OR_S : ICE_PROT_IPV6_IL;
1160 
1161 		/* TTL and PROT share the same extraction seq. entry.
1162 		 * Each is considered a sibling to the other in terms of sharing
1163 		 * the same extraction sequence entry.
1164 		 */
1165 		if (fld == ICE_FLOW_FIELD_IDX_IPV6_TTL)
1166 			sib = ICE_FLOW_FIELD_IDX_IPV6_PROT;
1167 		else
1168 			sib = ICE_FLOW_FIELD_IDX_IPV6_TTL;
1169 
1170 		/* If the sibling field is also included, that field's
1171 		 * mask needs to be included.
1172 		 */
1173 		if (match & BIT(sib))
1174 			sib_mask = ice_flds_info[sib].mask;
1175 		break;
1176 	case ICE_FLOW_FIELD_IDX_IPV4_SA:
1177 	case ICE_FLOW_FIELD_IDX_IPV4_DA:
1178 		prot_id = seg == 0 ? ICE_PROT_IPV4_OF_OR_S : ICE_PROT_IPV4_IL;
1179 		break;
1180 	case ICE_FLOW_FIELD_IDX_IPV6_SA:
1181 	case ICE_FLOW_FIELD_IDX_IPV6_DA:
1182 	case ICE_FLOW_FIELD_IDX_IPV6_PRE32_SA:
1183 	case ICE_FLOW_FIELD_IDX_IPV6_PRE32_DA:
1184 	case ICE_FLOW_FIELD_IDX_IPV6_PRE48_SA:
1185 	case ICE_FLOW_FIELD_IDX_IPV6_PRE48_DA:
1186 	case ICE_FLOW_FIELD_IDX_IPV6_PRE64_SA:
1187 	case ICE_FLOW_FIELD_IDX_IPV6_PRE64_DA:
1188 		prot_id = seg == 0 ? ICE_PROT_IPV6_OF_OR_S : ICE_PROT_IPV6_IL;
1189 		break;
1190 	case ICE_FLOW_FIELD_IDX_TCP_SRC_PORT:
1191 	case ICE_FLOW_FIELD_IDX_TCP_DST_PORT:
1192 	case ICE_FLOW_FIELD_IDX_TCP_FLAGS:
1193 		prot_id = ICE_PROT_TCP_IL;
1194 		break;
1195 	case ICE_FLOW_FIELD_IDX_UDP_SRC_PORT:
1196 	case ICE_FLOW_FIELD_IDX_UDP_DST_PORT:
1197 		prot_id = ICE_PROT_UDP_IL_OR_S;
1198 		break;
1199 	case ICE_FLOW_FIELD_IDX_SCTP_SRC_PORT:
1200 	case ICE_FLOW_FIELD_IDX_SCTP_DST_PORT:
1201 		prot_id = ICE_PROT_SCTP_IL;
1202 		break;
1203 	case ICE_FLOW_FIELD_IDX_VXLAN_VNI:
1204 	case ICE_FLOW_FIELD_IDX_GTPC_TEID:
1205 	case ICE_FLOW_FIELD_IDX_GTPU_IP_TEID:
1206 	case ICE_FLOW_FIELD_IDX_GTPU_UP_TEID:
1207 	case ICE_FLOW_FIELD_IDX_GTPU_DWN_TEID:
1208 	case ICE_FLOW_FIELD_IDX_GTPU_EH_TEID:
1209 	case ICE_FLOW_FIELD_IDX_GTPU_EH_QFI:
1210 		/* GTP is accessed through UDP OF protocol */
1211 		prot_id = ICE_PROT_UDP_OF;
1212 		break;
1213 	case ICE_FLOW_FIELD_IDX_PPPOE_SESS_ID:
1214 		prot_id = ICE_PROT_PPPOE;
1215 		break;
1216 	case ICE_FLOW_FIELD_IDX_PFCP_SEID:
1217 		prot_id = ICE_PROT_UDP_IL_OR_S;
1218 		break;
1219 	case ICE_FLOW_FIELD_IDX_L2TPV3_SESS_ID:
1220 		prot_id = ICE_PROT_L2TPV3;
1221 		break;
1222 	case ICE_FLOW_FIELD_IDX_ESP_SPI:
1223 		prot_id = ICE_PROT_ESP_F;
1224 		break;
1225 	case ICE_FLOW_FIELD_IDX_AH_SPI:
1226 		prot_id = ICE_PROT_ESP_2;
1227 		break;
1228 	case ICE_FLOW_FIELD_IDX_NAT_T_ESP_SPI:
1229 		prot_id = ICE_PROT_UDP_IL_OR_S;
1230 		break;
1231 	case ICE_FLOW_FIELD_IDX_ECPRI_TP0_PC_ID:
1232 		prot_id = ICE_PROT_ECPRI;
1233 		break;
1234 	case ICE_FLOW_FIELD_IDX_UDP_ECPRI_TP0_PC_ID:
1235 		prot_id = ICE_PROT_UDP_IL_OR_S;
1236 		break;
1237 	case ICE_FLOW_FIELD_IDX_ARP_SIP:
1238 	case ICE_FLOW_FIELD_IDX_ARP_DIP:
1239 	case ICE_FLOW_FIELD_IDX_ARP_SHA:
1240 	case ICE_FLOW_FIELD_IDX_ARP_DHA:
1241 	case ICE_FLOW_FIELD_IDX_ARP_OP:
1242 		prot_id = ICE_PROT_ARP_OF;
1243 		break;
1244 	case ICE_FLOW_FIELD_IDX_ICMP_TYPE:
1245 	case ICE_FLOW_FIELD_IDX_ICMP_CODE:
1246 		/* ICMP type and code share the same extraction seq. entry */
1247 		prot_id = (params->prof->segs[seg].hdrs &
1248 			   ICE_FLOW_SEG_HDR_IPV4) ?
1249 			ICE_PROT_ICMP_IL : ICE_PROT_ICMPV6_IL;
1250 		sib = fld == ICE_FLOW_FIELD_IDX_ICMP_TYPE ?
1251 			ICE_FLOW_FIELD_IDX_ICMP_CODE :
1252 			ICE_FLOW_FIELD_IDX_ICMP_TYPE;
1253 		break;
1254 	case ICE_FLOW_FIELD_IDX_GRE_KEYID:
1255 		prot_id = ICE_PROT_GRE_OF;
1256 		break;
1257 	default:
1258 		return ICE_ERR_NOT_IMPL;
1259 	}
1260 
1261 	/* Each extraction sequence entry is a word in size, and extracts a
1262 	 * word-aligned offset from a protocol header.
1263 	 */
1264 	ese_bits = ICE_FLOW_FV_EXTRACT_SZ * BITS_PER_BYTE;
1265 
1266 	flds[fld].xtrct.prot_id = prot_id;
1267 	flds[fld].xtrct.off = (ice_flds_info[fld].off / ese_bits) *
1268 		ICE_FLOW_FV_EXTRACT_SZ;
1269 	flds[fld].xtrct.disp = (u8)(ice_flds_info[fld].off % ese_bits);
1270 	flds[fld].xtrct.idx = params->es_cnt;
1271 	flds[fld].xtrct.mask = ice_flds_info[fld].mask;
1272 
1273 	/* Adjust the next field-entry index after accommodating the number of
1274 	 * entries this field consumes
1275 	 */
1276 	cnt = DIVIDE_AND_ROUND_UP(flds[fld].xtrct.disp +
1277 				  ice_flds_info[fld].size, ese_bits);
1278 
1279 	/* Fill in the extraction sequence entries needed for this field */
1280 	off = flds[fld].xtrct.off;
1281 	mask = flds[fld].xtrct.mask;
1282 	for (i = 0; i < cnt; i++) {
1283 		/* Only consume an extraction sequence entry if there is no
1284 		 * sibling field associated with this field or the sibling entry
1285 		 * already extracts the word shared with this field.
1286 		 */
1287 		if (sib == ICE_FLOW_FIELD_IDX_MAX ||
1288 		    flds[sib].xtrct.prot_id == ICE_PROT_ID_INVAL ||
1289 		    flds[sib].xtrct.off != off) {
1290 			u8 idx;
1291 
1292 			/* Make sure the number of extraction sequence required
1293 			 * does not exceed the block's capability
1294 			 */
1295 			if (params->es_cnt >= fv_words)
1296 				return ICE_ERR_MAX_LIMIT;
1297 
1298 			/* some blocks require a reversed field vector layout */
1299 			if (hw->blk[params->blk].es.reverse)
1300 				idx = fv_words - params->es_cnt - 1;
1301 			else
1302 				idx = params->es_cnt;
1303 
1304 			params->es[idx].prot_id = prot_id;
1305 			params->es[idx].off = off;
1306 			params->mask[idx] = mask | sib_mask;
1307 			params->es_cnt++;
1308 		}
1309 
1310 		off += ICE_FLOW_FV_EXTRACT_SZ;
1311 	}
1312 
1313 	return ICE_SUCCESS;
1314 }
1315 
1316 /**
1317  * ice_flow_xtract_raws - Create extract sequence entries for raw bytes
1318  * @hw: pointer to the HW struct
1319  * @params: information about the flow to be processed
1320  * @seg: index of packet segment whose raw fields are to be extracted
1321  */
1322 static enum ice_status
1323 ice_flow_xtract_raws(struct ice_hw *hw, struct ice_flow_prof_params *params,
1324 		     u8 seg)
1325 {
1326 	u16 fv_words;
1327 	u16 hdrs_sz;
1328 	u8 i;
1329 
1330 	if (!params->prof->segs[seg].raws_cnt)
1331 		return ICE_SUCCESS;
1332 
1333 	if (params->prof->segs[seg].raws_cnt >
1334 	    ARRAY_SIZE(params->prof->segs[seg].raws))
1335 		return ICE_ERR_MAX_LIMIT;
1336 
1337 	/* Offsets within the segment headers are not supported */
1338 	hdrs_sz = ice_flow_calc_seg_sz(params, seg);
1339 	if (!hdrs_sz)
1340 		return ICE_ERR_PARAM;
1341 
1342 	fv_words = hw->blk[params->blk].es.fvw;
1343 
1344 	for (i = 0; i < params->prof->segs[seg].raws_cnt; i++) {
1345 		struct ice_flow_seg_fld_raw *raw;
1346 		u16 off, cnt, j;
1347 
1348 		raw = &params->prof->segs[seg].raws[i];
1349 
1350 		/* Storing extraction information */
1351 		raw->info.xtrct.prot_id = ICE_PROT_MAC_OF_OR_S;
1352 		raw->info.xtrct.off = (raw->off / ICE_FLOW_FV_EXTRACT_SZ) *
1353 			ICE_FLOW_FV_EXTRACT_SZ;
1354 		raw->info.xtrct.disp = (raw->off % ICE_FLOW_FV_EXTRACT_SZ) *
1355 			BITS_PER_BYTE;
1356 		raw->info.xtrct.idx = params->es_cnt;
1357 
1358 		/* Determine the number of field vector entries this raw field
1359 		 * consumes.
1360 		 */
1361 		cnt = DIVIDE_AND_ROUND_UP(raw->info.xtrct.disp +
1362 					  (raw->info.src.last * BITS_PER_BYTE),
1363 					  (ICE_FLOW_FV_EXTRACT_SZ *
1364 					   BITS_PER_BYTE));
1365 		off = raw->info.xtrct.off;
1366 		for (j = 0; j < cnt; j++) {
1367 			u16 idx;
1368 
1369 			/* Make sure the number of extraction sequence required
1370 			 * does not exceed the block's capability
1371 			 */
1372 			if (params->es_cnt >= hw->blk[params->blk].es.count ||
1373 			    params->es_cnt >= ICE_MAX_FV_WORDS)
1374 				return ICE_ERR_MAX_LIMIT;
1375 
1376 			/* some blocks require a reversed field vector layout */
1377 			if (hw->blk[params->blk].es.reverse)
1378 				idx = fv_words - params->es_cnt - 1;
1379 			else
1380 				idx = params->es_cnt;
1381 
1382 			params->es[idx].prot_id = raw->info.xtrct.prot_id;
1383 			params->es[idx].off = off;
1384 			params->es_cnt++;
1385 			off += ICE_FLOW_FV_EXTRACT_SZ;
1386 		}
1387 	}
1388 
1389 	return ICE_SUCCESS;
1390 }
1391 
1392 /**
1393  * ice_flow_create_xtrct_seq - Create an extraction sequence for given segments
1394  * @hw: pointer to the HW struct
1395  * @params: information about the flow to be processed
1396  *
1397  * This function iterates through all matched fields in the given segments, and
1398  * creates an extraction sequence for the fields.
1399  */
1400 static enum ice_status
1401 ice_flow_create_xtrct_seq(struct ice_hw *hw,
1402 			  struct ice_flow_prof_params *params)
1403 {
1404 	enum ice_status status = ICE_SUCCESS;
1405 	u8 i;
1406 
1407 	/* For ACL, we also need to extract the direction bit (Rx,Tx) data from
1408 	 * packet flags
1409 	 */
1410 	if (params->blk == ICE_BLK_ACL) {
1411 		status = ice_flow_xtract_pkt_flags(hw, params,
1412 						   ICE_RX_MDID_PKT_FLAGS_15_0);
1413 		if (status)
1414 			return status;
1415 	}
1416 
1417 	for (i = 0; i < params->prof->segs_cnt; i++) {
1418 		u64 match = params->prof->segs[i].match;
1419 		enum ice_flow_field j;
1420 
1421 		ice_for_each_set_bit(j, (ice_bitmap_t *)&match,
1422 				     ICE_FLOW_FIELD_IDX_MAX) {
1423 			status = ice_flow_xtract_fld(hw, params, i, j, match);
1424 			if (status)
1425 				return status;
1426 			ice_clear_bit(j, (ice_bitmap_t *)&match);
1427 		}
1428 
1429 		/* Process raw matching bytes */
1430 		status = ice_flow_xtract_raws(hw, params, i);
1431 		if (status)
1432 			return status;
1433 	}
1434 
1435 	return status;
1436 }
1437 
1438 /**
1439  * ice_flow_sel_acl_scen - returns the specific scenario
1440  * @hw: pointer to the hardware structure
1441  * @params: information about the flow to be processed
1442  *
1443  * This function will return the specific scenario based on the
1444  * params passed to it
1445  */
1446 static enum ice_status
1447 ice_flow_sel_acl_scen(struct ice_hw *hw, struct ice_flow_prof_params *params)
1448 {
1449 	/* Find the best-fit scenario for the provided match width */
1450 	struct ice_acl_scen *cand_scen = NULL, *scen;
1451 
1452 	if (!hw->acl_tbl)
1453 		return ICE_ERR_DOES_NOT_EXIST;
1454 
1455 	/* Loop through each scenario and match against the scenario width
1456 	 * to select the specific scenario
1457 	 */
1458 	LIST_FOR_EACH_ENTRY(scen, &hw->acl_tbl->scens, ice_acl_scen, list_entry)
1459 		if (scen->eff_width >= params->entry_length &&
1460 		    (!cand_scen || cand_scen->eff_width > scen->eff_width))
1461 			cand_scen = scen;
1462 	if (!cand_scen)
1463 		return ICE_ERR_DOES_NOT_EXIST;
1464 
1465 	params->prof->cfg.scen = cand_scen;
1466 
1467 	return ICE_SUCCESS;
1468 }
1469 
1470 /**
1471  * ice_flow_acl_def_entry_frmt - Determine the layout of flow entries
1472  * @params: information about the flow to be processed
1473  */
1474 static enum ice_status
1475 ice_flow_acl_def_entry_frmt(struct ice_flow_prof_params *params)
1476 {
1477 	u16 index, i, range_idx = 0;
1478 
1479 	index = ICE_AQC_ACL_PROF_BYTE_SEL_START_IDX;
1480 
1481 	for (i = 0; i < params->prof->segs_cnt; i++) {
1482 		struct ice_flow_seg_info *seg = &params->prof->segs[i];
1483 		u8 j;
1484 
1485 		ice_for_each_set_bit(j, (ice_bitmap_t *)&seg->match,
1486 				     ICE_FLOW_FIELD_IDX_MAX) {
1487 			struct ice_flow_fld_info *fld = &seg->fields[j];
1488 
1489 			fld->entry.mask = ICE_FLOW_FLD_OFF_INVAL;
1490 
1491 			if (fld->type == ICE_FLOW_FLD_TYPE_RANGE) {
1492 				fld->entry.last = ICE_FLOW_FLD_OFF_INVAL;
1493 
1494 				/* Range checking only supported for single
1495 				 * words
1496 				 */
1497 				if (DIVIDE_AND_ROUND_UP(ice_flds_info[j].size +
1498 							fld->xtrct.disp,
1499 							BITS_PER_BYTE * 2) > 1)
1500 					return ICE_ERR_PARAM;
1501 
1502 				/* Ranges must define low and high values */
1503 				if (fld->src.val == ICE_FLOW_FLD_OFF_INVAL ||
1504 				    fld->src.last == ICE_FLOW_FLD_OFF_INVAL)
1505 					return ICE_ERR_PARAM;
1506 
1507 				fld->entry.val = range_idx++;
1508 			} else {
1509 				/* Store adjusted byte-length of field for later
1510 				 * use, taking into account potential
1511 				 * non-byte-aligned displacement
1512 				 */
1513 				fld->entry.last = DIVIDE_AND_ROUND_UP
1514 					(ice_flds_info[j].size +
1515 					 (fld->xtrct.disp % BITS_PER_BYTE),
1516 					 BITS_PER_BYTE);
1517 				fld->entry.val = index;
1518 				index += fld->entry.last;
1519 			}
1520 		}
1521 
1522 		for (j = 0; j < seg->raws_cnt; j++) {
1523 			struct ice_flow_seg_fld_raw *raw = &seg->raws[j];
1524 
1525 			raw->info.entry.mask = ICE_FLOW_FLD_OFF_INVAL;
1526 			raw->info.entry.val = index;
1527 			raw->info.entry.last = raw->info.src.last;
1528 			index += raw->info.entry.last;
1529 		}
1530 	}
1531 
1532 	/* Currently only support using the byte selection base, which only
1533 	 * allows for an effective entry size of 30 bytes. Reject anything
1534 	 * larger.
1535 	 */
1536 	if (index > ICE_AQC_ACL_PROF_BYTE_SEL_ELEMS)
1537 		return ICE_ERR_PARAM;
1538 
1539 	/* Only 8 range checkers per profile, reject anything trying to use
1540 	 * more
1541 	 */
1542 	if (range_idx > ICE_AQC_ACL_PROF_RANGES_NUM_CFG)
1543 		return ICE_ERR_PARAM;
1544 
1545 	/* Store # bytes required for entry for later use */
1546 	params->entry_length = index - ICE_AQC_ACL_PROF_BYTE_SEL_START_IDX;
1547 
1548 	return ICE_SUCCESS;
1549 }
1550 
1551 /**
1552  * ice_flow_proc_segs - process all packet segments associated with a profile
1553  * @hw: pointer to the HW struct
1554  * @params: information about the flow to be processed
1555  */
1556 static enum ice_status
1557 ice_flow_proc_segs(struct ice_hw *hw, struct ice_flow_prof_params *params)
1558 {
1559 	enum ice_status status;
1560 
1561 	status = ice_flow_proc_seg_hdrs(params);
1562 	if (status)
1563 		return status;
1564 
1565 	status = ice_flow_create_xtrct_seq(hw, params);
1566 	if (status)
1567 		return status;
1568 
1569 	switch (params->blk) {
1570 	case ICE_BLK_FD:
1571 	case ICE_BLK_RSS:
1572 		status = ICE_SUCCESS;
1573 		break;
1574 	case ICE_BLK_ACL:
1575 		status = ice_flow_acl_def_entry_frmt(params);
1576 		if (status)
1577 			return status;
1578 		status = ice_flow_sel_acl_scen(hw, params);
1579 		if (status)
1580 			return status;
1581 		break;
1582 	default:
1583 		return ICE_ERR_NOT_IMPL;
1584 	}
1585 
1586 	return status;
1587 }
1588 
1589 #define ICE_FLOW_FIND_PROF_CHK_FLDS	0x00000001
1590 #define ICE_FLOW_FIND_PROF_CHK_VSI	0x00000002
1591 #define ICE_FLOW_FIND_PROF_NOT_CHK_DIR	0x00000004
1592 
1593 /**
1594  * ice_flow_find_prof_conds - Find a profile matching headers and conditions
1595  * @hw: pointer to the HW struct
1596  * @blk: classification stage
1597  * @dir: flow direction
1598  * @segs: array of one or more packet segments that describe the flow
1599  * @segs_cnt: number of packet segments provided
1600  * @vsi_handle: software VSI handle to check VSI (ICE_FLOW_FIND_PROF_CHK_VSI)
1601  * @conds: additional conditions to be checked (ICE_FLOW_FIND_PROF_CHK_*)
1602  */
1603 static struct ice_flow_prof *
1604 ice_flow_find_prof_conds(struct ice_hw *hw, enum ice_block blk,
1605 			 enum ice_flow_dir dir, struct ice_flow_seg_info *segs,
1606 			 u8 segs_cnt, u16 vsi_handle, u32 conds)
1607 {
1608 	struct ice_flow_prof *p, *prof = NULL;
1609 
1610 	ice_acquire_lock(&hw->fl_profs_locks[blk]);
1611 	LIST_FOR_EACH_ENTRY(p, &hw->fl_profs[blk], ice_flow_prof, l_entry)
1612 		if ((p->dir == dir || conds & ICE_FLOW_FIND_PROF_NOT_CHK_DIR) &&
1613 		    segs_cnt && segs_cnt == p->segs_cnt) {
1614 			u8 i;
1615 
1616 			/* Check for profile-VSI association if specified */
1617 			if ((conds & ICE_FLOW_FIND_PROF_CHK_VSI) &&
1618 			    ice_is_vsi_valid(hw, vsi_handle) &&
1619 			    !ice_is_bit_set(p->vsis, vsi_handle))
1620 				continue;
1621 
1622 			/* Protocol headers must be checked. Matched fields are
1623 			 * checked if specified.
1624 			 */
1625 			for (i = 0; i < segs_cnt; i++)
1626 				if (segs[i].hdrs != p->segs[i].hdrs ||
1627 				    ((conds & ICE_FLOW_FIND_PROF_CHK_FLDS) &&
1628 				     segs[i].match != p->segs[i].match))
1629 					break;
1630 
1631 			/* A match is found if all segments are matched */
1632 			if (i == segs_cnt) {
1633 				prof = p;
1634 				break;
1635 			}
1636 		}
1637 	ice_release_lock(&hw->fl_profs_locks[blk]);
1638 
1639 	return prof;
1640 }
1641 
1642 /**
1643  * ice_flow_find_prof - Look up a profile matching headers and matched fields
1644  * @hw: pointer to the HW struct
1645  * @blk: classification stage
1646  * @dir: flow direction
1647  * @segs: array of one or more packet segments that describe the flow
1648  * @segs_cnt: number of packet segments provided
1649  */
1650 u64
1651 ice_flow_find_prof(struct ice_hw *hw, enum ice_block blk, enum ice_flow_dir dir,
1652 		   struct ice_flow_seg_info *segs, u8 segs_cnt)
1653 {
1654 	struct ice_flow_prof *p;
1655 
1656 	p = ice_flow_find_prof_conds(hw, blk, dir, segs, segs_cnt,
1657 				     ICE_MAX_VSI, ICE_FLOW_FIND_PROF_CHK_FLDS);
1658 
1659 	return p ? p->id : ICE_FLOW_PROF_ID_INVAL;
1660 }
1661 
1662 /**
1663  * ice_flow_find_prof_id - Look up a profile with given profile ID
1664  * @hw: pointer to the HW struct
1665  * @blk: classification stage
1666  * @prof_id: unique ID to identify this flow profile
1667  */
1668 static struct ice_flow_prof *
1669 ice_flow_find_prof_id(struct ice_hw *hw, enum ice_block blk, u64 prof_id)
1670 {
1671 	struct ice_flow_prof *p;
1672 
1673 	LIST_FOR_EACH_ENTRY(p, &hw->fl_profs[blk], ice_flow_prof, l_entry)
1674 		if (p->id == prof_id)
1675 			return p;
1676 
1677 	return NULL;
1678 }
1679 
1680 /**
1681  * ice_dealloc_flow_entry - Deallocate flow entry memory
1682  * @hw: pointer to the HW struct
1683  * @entry: flow entry to be removed
1684  */
1685 static void
1686 ice_dealloc_flow_entry(struct ice_hw *hw, struct ice_flow_entry *entry)
1687 {
1688 	if (!entry)
1689 		return;
1690 
1691 	if (entry->entry)
1692 		ice_free(hw, entry->entry);
1693 
1694 	if (entry->range_buf) {
1695 		ice_free(hw, entry->range_buf);
1696 		entry->range_buf = NULL;
1697 	}
1698 
1699 	if (entry->acts) {
1700 		ice_free(hw, entry->acts);
1701 		entry->acts = NULL;
1702 		entry->acts_cnt = 0;
1703 	}
1704 
1705 	ice_free(hw, entry);
1706 }
1707 
1708 /**
1709  * ice_flow_get_hw_prof - return the HW profile for a specific profile ID handle
1710  * @hw: pointer to the HW struct
1711  * @blk: classification stage
1712  * @prof_id: the profile ID handle
1713  * @hw_prof_id: pointer to variable to receive the HW profile ID
1714  */
1715 enum ice_status
1716 ice_flow_get_hw_prof(struct ice_hw *hw, enum ice_block blk, u64 prof_id,
1717 		     u8 *hw_prof_id)
1718 {
1719 	enum ice_status status = ICE_ERR_DOES_NOT_EXIST;
1720 	struct ice_prof_map *map;
1721 
1722 	ice_acquire_lock(&hw->blk[blk].es.prof_map_lock);
1723 	map = ice_search_prof_id(hw, blk, prof_id);
1724 	if (map) {
1725 		*hw_prof_id = map->prof_id;
1726 		status = ICE_SUCCESS;
1727 	}
1728 	ice_release_lock(&hw->blk[blk].es.prof_map_lock);
1729 	return status;
1730 }
1731 
1732 #define ICE_ACL_INVALID_SCEN	0x3f
1733 
1734 /**
1735  * ice_flow_acl_is_prof_in_use - Verify if the profile is associated to any PF
1736  * @hw: pointer to the hardware structure
1737  * @prof: pointer to flow profile
1738  * @buf: destination buffer function writes partial extraction sequence to
1739  *
1740  * returns ICE_SUCCESS if no PF is associated to the given profile
1741  * returns ICE_ERR_IN_USE if at least one PF is associated to the given profile
1742  * returns other error code for real error
1743  */
1744 static enum ice_status
1745 ice_flow_acl_is_prof_in_use(struct ice_hw *hw, struct ice_flow_prof *prof,
1746 			    struct ice_aqc_acl_prof_generic_frmt *buf)
1747 {
1748 	enum ice_status status;
1749 	u8 prof_id = 0;
1750 
1751 	status = ice_flow_get_hw_prof(hw, ICE_BLK_ACL, prof->id, &prof_id);
1752 	if (status)
1753 		return status;
1754 
1755 	status = ice_query_acl_prof(hw, prof_id, buf, NULL);
1756 	if (status)
1757 		return status;
1758 
1759 	/* If all PF's associated scenarios are all 0 or all
1760 	 * ICE_ACL_INVALID_SCEN (63) for the given profile then the latter has
1761 	 * not been configured yet.
1762 	 */
1763 	if (buf->pf_scenario_num[0] == 0 && buf->pf_scenario_num[1] == 0 &&
1764 	    buf->pf_scenario_num[2] == 0 && buf->pf_scenario_num[3] == 0 &&
1765 	    buf->pf_scenario_num[4] == 0 && buf->pf_scenario_num[5] == 0 &&
1766 	    buf->pf_scenario_num[6] == 0 && buf->pf_scenario_num[7] == 0)
1767 		return ICE_SUCCESS;
1768 
1769 	if (buf->pf_scenario_num[0] == ICE_ACL_INVALID_SCEN &&
1770 	    buf->pf_scenario_num[1] == ICE_ACL_INVALID_SCEN &&
1771 	    buf->pf_scenario_num[2] == ICE_ACL_INVALID_SCEN &&
1772 	    buf->pf_scenario_num[3] == ICE_ACL_INVALID_SCEN &&
1773 	    buf->pf_scenario_num[4] == ICE_ACL_INVALID_SCEN &&
1774 	    buf->pf_scenario_num[5] == ICE_ACL_INVALID_SCEN &&
1775 	    buf->pf_scenario_num[6] == ICE_ACL_INVALID_SCEN &&
1776 	    buf->pf_scenario_num[7] == ICE_ACL_INVALID_SCEN)
1777 		return ICE_SUCCESS;
1778 
1779 	return ICE_ERR_IN_USE;
1780 }
1781 
1782 /**
1783  * ice_flow_acl_free_act_cntr - Free the ACL rule's actions
1784  * @hw: pointer to the hardware structure
1785  * @acts: array of actions to be performed on a match
1786  * @acts_cnt: number of actions
1787  */
1788 static enum ice_status
1789 ice_flow_acl_free_act_cntr(struct ice_hw *hw, struct ice_flow_action *acts,
1790 			   u8 acts_cnt)
1791 {
1792 	int i;
1793 
1794 	for (i = 0; i < acts_cnt; i++) {
1795 		if (acts[i].type == ICE_FLOW_ACT_CNTR_PKT ||
1796 		    acts[i].type == ICE_FLOW_ACT_CNTR_BYTES ||
1797 		    acts[i].type == ICE_FLOW_ACT_CNTR_PKT_BYTES) {
1798 			struct ice_acl_cntrs cntrs;
1799 			enum ice_status status;
1800 
1801 			cntrs.bank = 0; /* Only bank0 for the moment */
1802 			cntrs.first_cntr =
1803 					LE16_TO_CPU(acts[i].data.acl_act.value);
1804 			cntrs.last_cntr =
1805 					LE16_TO_CPU(acts[i].data.acl_act.value);
1806 
1807 			if (acts[i].type == ICE_FLOW_ACT_CNTR_PKT_BYTES)
1808 				cntrs.type = ICE_AQC_ACL_CNT_TYPE_DUAL;
1809 			else
1810 				cntrs.type = ICE_AQC_ACL_CNT_TYPE_SINGLE;
1811 
1812 			status = ice_aq_dealloc_acl_cntrs(hw, &cntrs, NULL);
1813 			if (status)
1814 				return status;
1815 		}
1816 	}
1817 	return ICE_SUCCESS;
1818 }
1819 
1820 /**
1821  * ice_flow_acl_disassoc_scen - Disassociate the scenario from the profile
1822  * @hw: pointer to the hardware structure
1823  * @prof: pointer to flow profile
1824  *
1825  * Disassociate the scenario from the profile for the PF of the VSI.
1826  */
1827 static enum ice_status
1828 ice_flow_acl_disassoc_scen(struct ice_hw *hw, struct ice_flow_prof *prof)
1829 {
1830 	struct ice_aqc_acl_prof_generic_frmt buf;
1831 	enum ice_status status = ICE_SUCCESS;
1832 	u8 prof_id = 0;
1833 
1834 	ice_memset(&buf, 0, sizeof(buf), ICE_NONDMA_MEM);
1835 
1836 	status = ice_flow_get_hw_prof(hw, ICE_BLK_ACL, prof->id, &prof_id);
1837 	if (status)
1838 		return status;
1839 
1840 	status = ice_query_acl_prof(hw, prof_id, &buf, NULL);
1841 	if (status)
1842 		return status;
1843 
1844 	/* Clear scenario for this PF */
1845 	buf.pf_scenario_num[hw->pf_id] = ICE_ACL_INVALID_SCEN;
1846 	status = ice_prgm_acl_prof_xtrct(hw, prof_id, &buf, NULL);
1847 
1848 	return status;
1849 }
1850 
1851 /**
1852  * ice_flow_rem_entry_sync - Remove a flow entry
1853  * @hw: pointer to the HW struct
1854  * @blk: classification stage
1855  * @entry: flow entry to be removed
1856  */
1857 static enum ice_status
1858 ice_flow_rem_entry_sync(struct ice_hw *hw, enum ice_block blk,
1859 			struct ice_flow_entry *entry)
1860 {
1861 	if (!entry)
1862 		return ICE_ERR_BAD_PTR;
1863 
1864 	if (blk == ICE_BLK_ACL) {
1865 		enum ice_status status;
1866 
1867 		if (!entry->prof)
1868 			return ICE_ERR_BAD_PTR;
1869 
1870 		status = ice_acl_rem_entry(hw, entry->prof->cfg.scen,
1871 					   entry->scen_entry_idx);
1872 		if (status)
1873 			return status;
1874 
1875 		/* Checks if we need to release an ACL counter. */
1876 		if (entry->acts_cnt && entry->acts)
1877 			ice_flow_acl_free_act_cntr(hw, entry->acts,
1878 						   entry->acts_cnt);
1879 	}
1880 
1881 	LIST_DEL(&entry->l_entry);
1882 
1883 	ice_dealloc_flow_entry(hw, entry);
1884 
1885 	return ICE_SUCCESS;
1886 }
1887 
1888 /**
1889  * ice_flow_add_prof_sync - Add a flow profile for packet segments and fields
1890  * @hw: pointer to the HW struct
1891  * @blk: classification stage
1892  * @dir: flow direction
1893  * @prof_id: unique ID to identify this flow profile
1894  * @segs: array of one or more packet segments that describe the flow
1895  * @segs_cnt: number of packet segments provided
1896  * @acts: array of default actions
1897  * @acts_cnt: number of default actions
1898  * @prof: stores the returned flow profile added
1899  *
1900  * Assumption: the caller has acquired the lock to the profile list
1901  */
1902 static enum ice_status
1903 ice_flow_add_prof_sync(struct ice_hw *hw, enum ice_block blk,
1904 		       enum ice_flow_dir dir, u64 prof_id,
1905 		       struct ice_flow_seg_info *segs, u8 segs_cnt,
1906 		       struct ice_flow_action *acts, u8 acts_cnt,
1907 		       struct ice_flow_prof **prof)
1908 {
1909 	struct ice_flow_prof_params *params;
1910 	enum ice_status status;
1911 	u8 i;
1912 
1913 	if (!prof || (acts_cnt && !acts))
1914 		return ICE_ERR_BAD_PTR;
1915 
1916 	params = (struct ice_flow_prof_params *)ice_malloc(hw, sizeof(*params));
1917 	if (!params)
1918 		return ICE_ERR_NO_MEMORY;
1919 
1920 	params->prof = (struct ice_flow_prof *)
1921 		ice_malloc(hw, sizeof(*params->prof));
1922 	if (!params->prof) {
1923 		status = ICE_ERR_NO_MEMORY;
1924 		goto free_params;
1925 	}
1926 
1927 	/* initialize extraction sequence to all invalid (0xff) */
1928 	for (i = 0; i < ICE_MAX_FV_WORDS; i++) {
1929 		params->es[i].prot_id = ICE_PROT_INVALID;
1930 		params->es[i].off = ICE_FV_OFFSET_INVAL;
1931 	}
1932 
1933 	params->blk = blk;
1934 	params->prof->id = prof_id;
1935 	params->prof->dir = dir;
1936 	params->prof->segs_cnt = segs_cnt;
1937 
1938 	/* Make a copy of the segments that need to be persistent in the flow
1939 	 * profile instance
1940 	 */
1941 	for (i = 0; i < segs_cnt; i++)
1942 		ice_memcpy(&params->prof->segs[i], &segs[i], sizeof(*segs),
1943 			   ICE_NONDMA_TO_NONDMA);
1944 
1945 	/* Make a copy of the actions that need to be persistent in the flow
1946 	 * profile instance.
1947 	 */
1948 	if (acts_cnt) {
1949 		params->prof->acts = (struct ice_flow_action *)
1950 			ice_memdup(hw, acts, acts_cnt * sizeof(*acts),
1951 				   ICE_NONDMA_TO_NONDMA);
1952 
1953 		if (!params->prof->acts) {
1954 			status = ICE_ERR_NO_MEMORY;
1955 			goto out;
1956 		}
1957 	}
1958 
1959 	status = ice_flow_proc_segs(hw, params);
1960 	if (status) {
1961 		ice_debug(hw, ICE_DBG_FLOW, "Error processing a flow's packet segments\n");
1962 		goto out;
1963 	}
1964 
1965 	/* Add a HW profile for this flow profile */
1966 	status = ice_add_prof(hw, blk, prof_id, (u8 *)params->ptypes,
1967 			      params->attr, params->attr_cnt, params->es,
1968 			      params->mask);
1969 	if (status) {
1970 		ice_debug(hw, ICE_DBG_FLOW, "Error adding a HW flow profile\n");
1971 		goto out;
1972 	}
1973 
1974 	INIT_LIST_HEAD(&params->prof->entries);
1975 	ice_init_lock(&params->prof->entries_lock);
1976 	*prof = params->prof;
1977 
1978 out:
1979 	if (status) {
1980 		if (params->prof->acts)
1981 			ice_free(hw, params->prof->acts);
1982 		ice_free(hw, params->prof);
1983 	}
1984 free_params:
1985 	ice_free(hw, params);
1986 
1987 	return status;
1988 }
1989 
1990 /**
1991  * ice_flow_rem_prof_sync - remove a flow profile
1992  * @hw: pointer to the hardware structure
1993  * @blk: classification stage
1994  * @prof: pointer to flow profile to remove
1995  *
1996  * Assumption: the caller has acquired the lock to the profile list
1997  */
1998 static enum ice_status
1999 ice_flow_rem_prof_sync(struct ice_hw *hw, enum ice_block blk,
2000 		       struct ice_flow_prof *prof)
2001 {
2002 	enum ice_status status;
2003 
2004 	/* Remove all remaining flow entries before removing the flow profile */
2005 	if (!LIST_EMPTY(&prof->entries)) {
2006 		struct ice_flow_entry *e, *t;
2007 
2008 		ice_acquire_lock(&prof->entries_lock);
2009 
2010 		LIST_FOR_EACH_ENTRY_SAFE(e, t, &prof->entries, ice_flow_entry,
2011 					 l_entry) {
2012 			status = ice_flow_rem_entry_sync(hw, blk, e);
2013 			if (status)
2014 				break;
2015 		}
2016 
2017 		ice_release_lock(&prof->entries_lock);
2018 	}
2019 
2020 	if (blk == ICE_BLK_ACL) {
2021 		struct ice_aqc_acl_profile_ranges query_rng_buf;
2022 		struct ice_aqc_acl_prof_generic_frmt buf;
2023 		u8 prof_id = 0;
2024 
2025 		/* Disassociate the scenario from the profile for the PF */
2026 		status = ice_flow_acl_disassoc_scen(hw, prof);
2027 		if (status)
2028 			return status;
2029 
2030 		/* Clear the range-checker if the profile ID is no longer
2031 		 * used by any PF
2032 		 */
2033 		status = ice_flow_acl_is_prof_in_use(hw, prof, &buf);
2034 		if (status && status != ICE_ERR_IN_USE) {
2035 			return status;
2036 		} else if (!status) {
2037 			/* Clear the range-checker value for profile ID */
2038 			ice_memset(&query_rng_buf, 0,
2039 				   sizeof(struct ice_aqc_acl_profile_ranges),
2040 				   ICE_NONDMA_MEM);
2041 
2042 			status = ice_flow_get_hw_prof(hw, blk, prof->id,
2043 						      &prof_id);
2044 			if (status)
2045 				return status;
2046 
2047 			status = ice_prog_acl_prof_ranges(hw, prof_id,
2048 							  &query_rng_buf, NULL);
2049 			if (status)
2050 				return status;
2051 		}
2052 	}
2053 
2054 	/* Remove all hardware profiles associated with this flow profile */
2055 	status = ice_rem_prof(hw, blk, prof->id);
2056 	if (!status) {
2057 		LIST_DEL(&prof->l_entry);
2058 		ice_destroy_lock(&prof->entries_lock);
2059 		if (prof->acts)
2060 			ice_free(hw, prof->acts);
2061 		ice_free(hw, prof);
2062 	}
2063 
2064 	return status;
2065 }
2066 
2067 /**
2068  * ice_flow_acl_set_xtrct_seq_fld - Populate xtrct seq for single field
2069  * @buf: Destination buffer function writes partial xtrct sequence to
2070  * @info: Info about field
2071  */
2072 static void
2073 ice_flow_acl_set_xtrct_seq_fld(struct ice_aqc_acl_prof_generic_frmt *buf,
2074 			       struct ice_flow_fld_info *info)
2075 {
2076 	u16 dst, i;
2077 	u8 src;
2078 
2079 	src = info->xtrct.idx * ICE_FLOW_FV_EXTRACT_SZ +
2080 		info->xtrct.disp / BITS_PER_BYTE;
2081 	dst = info->entry.val;
2082 	for (i = 0; i < info->entry.last; i++)
2083 		/* HW stores field vector words in LE, convert words back to BE
2084 		 * so constructed entries will end up in network order
2085 		 */
2086 		buf->byte_selection[dst++] = src++ ^ 1;
2087 }
2088 
2089 /**
2090  * ice_flow_acl_set_xtrct_seq - Program ACL extraction sequence
2091  * @hw: pointer to the hardware structure
2092  * @prof: pointer to flow profile
2093  */
2094 static enum ice_status
2095 ice_flow_acl_set_xtrct_seq(struct ice_hw *hw, struct ice_flow_prof *prof)
2096 {
2097 	struct ice_aqc_acl_prof_generic_frmt buf;
2098 	struct ice_flow_fld_info *info;
2099 	enum ice_status status;
2100 	u8 prof_id = 0;
2101 	u16 i;
2102 
2103 	ice_memset(&buf, 0, sizeof(buf), ICE_NONDMA_MEM);
2104 
2105 	status = ice_flow_get_hw_prof(hw, ICE_BLK_ACL, prof->id, &prof_id);
2106 	if (status)
2107 		return status;
2108 
2109 	status = ice_flow_acl_is_prof_in_use(hw, prof, &buf);
2110 	if (status && status != ICE_ERR_IN_USE)
2111 		return status;
2112 
2113 	if (!status) {
2114 		/* Program the profile dependent configuration. This is done
2115 		 * only once regardless of the number of PFs using that profile
2116 		 */
2117 		ice_memset(&buf, 0, sizeof(buf), ICE_NONDMA_MEM);
2118 
2119 		for (i = 0; i < prof->segs_cnt; i++) {
2120 			struct ice_flow_seg_info *seg = &prof->segs[i];
2121 			u16 j;
2122 
2123 			ice_for_each_set_bit(j, (ice_bitmap_t *)&seg->match,
2124 					     ICE_FLOW_FIELD_IDX_MAX) {
2125 				info = &seg->fields[j];
2126 
2127 				if (info->type == ICE_FLOW_FLD_TYPE_RANGE)
2128 					buf.word_selection[info->entry.val] =
2129 						info->xtrct.idx;
2130 				else
2131 					ice_flow_acl_set_xtrct_seq_fld(&buf,
2132 								       info);
2133 			}
2134 
2135 			for (j = 0; j < seg->raws_cnt; j++) {
2136 				info = &seg->raws[j].info;
2137 				ice_flow_acl_set_xtrct_seq_fld(&buf, info);
2138 			}
2139 		}
2140 
2141 		ice_memset(&buf.pf_scenario_num[0], ICE_ACL_INVALID_SCEN,
2142 			   ICE_AQC_ACL_PROF_PF_SCEN_NUM_ELEMS,
2143 			   ICE_NONDMA_MEM);
2144 	}
2145 
2146 	/* Update the current PF */
2147 	buf.pf_scenario_num[hw->pf_id] = (u8)prof->cfg.scen->id;
2148 	status = ice_prgm_acl_prof_xtrct(hw, prof_id, &buf, NULL);
2149 
2150 	return status;
2151 }
2152 
2153 /**
2154  * ice_flow_assoc_vsig_vsi - associate a VSI with VSIG
2155  * @hw: pointer to the hardware structure
2156  * @blk: classification stage
2157  * @vsi_handle: software VSI handle
2158  * @vsig: target VSI group
2159  *
2160  * Assumption: the caller has already verified that the VSI to
2161  * be added has the same characteristics as the VSIG and will
2162  * thereby have access to all resources added to that VSIG.
2163  */
2164 enum ice_status
2165 ice_flow_assoc_vsig_vsi(struct ice_hw *hw, enum ice_block blk, u16 vsi_handle,
2166 			u16 vsig)
2167 {
2168 	enum ice_status status;
2169 
2170 	if (!ice_is_vsi_valid(hw, vsi_handle) || blk >= ICE_BLK_COUNT)
2171 		return ICE_ERR_PARAM;
2172 
2173 	ice_acquire_lock(&hw->fl_profs_locks[blk]);
2174 	status = ice_add_vsi_flow(hw, blk, ice_get_hw_vsi_num(hw, vsi_handle),
2175 				  vsig);
2176 	ice_release_lock(&hw->fl_profs_locks[blk]);
2177 
2178 	return status;
2179 }
2180 
2181 /**
2182  * ice_flow_assoc_prof - associate a VSI with a flow profile
2183  * @hw: pointer to the hardware structure
2184  * @blk: classification stage
2185  * @prof: pointer to flow profile
2186  * @vsi_handle: software VSI handle
2187  *
2188  * Assumption: the caller has acquired the lock to the profile list
2189  * and the software VSI handle has been validated
2190  */
2191 enum ice_status
2192 ice_flow_assoc_prof(struct ice_hw *hw, enum ice_block blk,
2193 		    struct ice_flow_prof *prof, u16 vsi_handle)
2194 {
2195 	enum ice_status status = ICE_SUCCESS;
2196 
2197 	if (!ice_is_bit_set(prof->vsis, vsi_handle)) {
2198 		if (blk == ICE_BLK_ACL) {
2199 			status = ice_flow_acl_set_xtrct_seq(hw, prof);
2200 			if (status)
2201 				return status;
2202 		}
2203 		status = ice_add_prof_id_flow(hw, blk,
2204 					      ice_get_hw_vsi_num(hw,
2205 								 vsi_handle),
2206 					      prof->id);
2207 		if (!status)
2208 			ice_set_bit(vsi_handle, prof->vsis);
2209 		else
2210 			ice_debug(hw, ICE_DBG_FLOW, "HW profile add failed, %d\n",
2211 				  status);
2212 	}
2213 
2214 	return status;
2215 }
2216 
2217 /**
2218  * ice_flow_disassoc_prof - disassociate a VSI from a flow profile
2219  * @hw: pointer to the hardware structure
2220  * @blk: classification stage
2221  * @prof: pointer to flow profile
2222  * @vsi_handle: software VSI handle
2223  *
2224  * Assumption: the caller has acquired the lock to the profile list
2225  * and the software VSI handle has been validated
2226  */
2227 static enum ice_status
2228 ice_flow_disassoc_prof(struct ice_hw *hw, enum ice_block blk,
2229 		       struct ice_flow_prof *prof, u16 vsi_handle)
2230 {
2231 	enum ice_status status = ICE_SUCCESS;
2232 
2233 	if (ice_is_bit_set(prof->vsis, vsi_handle)) {
2234 		status = ice_rem_prof_id_flow(hw, blk,
2235 					      ice_get_hw_vsi_num(hw,
2236 								 vsi_handle),
2237 					      prof->id);
2238 		if (!status)
2239 			ice_clear_bit(vsi_handle, prof->vsis);
2240 		else
2241 			ice_debug(hw, ICE_DBG_FLOW, "HW profile remove failed, %d\n",
2242 				  status);
2243 	}
2244 
2245 	return status;
2246 }
2247 
2248 /**
2249  * ice_flow_add_prof - Add a flow profile for packet segments and matched fields
2250  * @hw: pointer to the HW struct
2251  * @blk: classification stage
2252  * @dir: flow direction
2253  * @prof_id: unique ID to identify this flow profile
2254  * @segs: array of one or more packet segments that describe the flow
2255  * @segs_cnt: number of packet segments provided
2256  * @acts: array of default actions
2257  * @acts_cnt: number of default actions
2258  * @prof: stores the returned flow profile added
2259  */
2260 enum ice_status
2261 ice_flow_add_prof(struct ice_hw *hw, enum ice_block blk, enum ice_flow_dir dir,
2262 		  u64 prof_id, struct ice_flow_seg_info *segs, u8 segs_cnt,
2263 		  struct ice_flow_action *acts, u8 acts_cnt,
2264 		  struct ice_flow_prof **prof)
2265 {
2266 	enum ice_status status;
2267 
2268 	if (segs_cnt > ICE_FLOW_SEG_MAX)
2269 		return ICE_ERR_MAX_LIMIT;
2270 
2271 	if (!segs_cnt)
2272 		return ICE_ERR_PARAM;
2273 
2274 	if (!segs)
2275 		return ICE_ERR_BAD_PTR;
2276 
2277 	status = ice_flow_val_hdrs(segs, segs_cnt);
2278 	if (status)
2279 		return status;
2280 
2281 	ice_acquire_lock(&hw->fl_profs_locks[blk]);
2282 
2283 	status = ice_flow_add_prof_sync(hw, blk, dir, prof_id, segs, segs_cnt,
2284 					acts, acts_cnt, prof);
2285 	if (!status)
2286 		LIST_ADD(&(*prof)->l_entry, &hw->fl_profs[blk]);
2287 
2288 	ice_release_lock(&hw->fl_profs_locks[blk]);
2289 
2290 	return status;
2291 }
2292 
2293 /**
2294  * ice_flow_rem_prof - Remove a flow profile and all entries associated with it
2295  * @hw: pointer to the HW struct
2296  * @blk: the block for which the flow profile is to be removed
2297  * @prof_id: unique ID of the flow profile to be removed
2298  */
2299 enum ice_status
2300 ice_flow_rem_prof(struct ice_hw *hw, enum ice_block blk, u64 prof_id)
2301 {
2302 	struct ice_flow_prof *prof;
2303 	enum ice_status status;
2304 
2305 	ice_acquire_lock(&hw->fl_profs_locks[blk]);
2306 
2307 	prof = ice_flow_find_prof_id(hw, blk, prof_id);
2308 	if (!prof) {
2309 		status = ICE_ERR_DOES_NOT_EXIST;
2310 		goto out;
2311 	}
2312 
2313 	/* prof becomes invalid after the call */
2314 	status = ice_flow_rem_prof_sync(hw, blk, prof);
2315 
2316 out:
2317 	ice_release_lock(&hw->fl_profs_locks[blk]);
2318 
2319 	return status;
2320 }
2321 
2322 /**
2323  * ice_flow_find_entry - look for a flow entry using its unique ID
2324  * @hw: pointer to the HW struct
2325  * @blk: classification stage
2326  * @entry_id: unique ID to identify this flow entry
2327  *
2328  * This function looks for the flow entry with the specified unique ID in all
2329  * flow profiles of the specified classification stage. If the entry is found,
2330  * and it returns the handle to the flow entry. Otherwise, it returns
2331  * ICE_FLOW_ENTRY_ID_INVAL.
2332  */
2333 u64 ice_flow_find_entry(struct ice_hw *hw, enum ice_block blk, u64 entry_id)
2334 {
2335 	struct ice_flow_entry *found = NULL;
2336 	struct ice_flow_prof *p;
2337 
2338 	ice_acquire_lock(&hw->fl_profs_locks[blk]);
2339 
2340 	LIST_FOR_EACH_ENTRY(p, &hw->fl_profs[blk], ice_flow_prof, l_entry) {
2341 		struct ice_flow_entry *e;
2342 
2343 		ice_acquire_lock(&p->entries_lock);
2344 		LIST_FOR_EACH_ENTRY(e, &p->entries, ice_flow_entry, l_entry)
2345 			if (e->id == entry_id) {
2346 				found = e;
2347 				break;
2348 			}
2349 		ice_release_lock(&p->entries_lock);
2350 
2351 		if (found)
2352 			break;
2353 	}
2354 
2355 	ice_release_lock(&hw->fl_profs_locks[blk]);
2356 
2357 	return found ? ICE_FLOW_ENTRY_HNDL(found) : ICE_FLOW_ENTRY_HANDLE_INVAL;
2358 }
2359 
2360 /**
2361  * ice_flow_acl_check_actions - Checks the ACL rule's actions
2362  * @hw: pointer to the hardware structure
2363  * @acts: array of actions to be performed on a match
2364  * @acts_cnt: number of actions
2365  * @cnt_alloc: indicates if an ACL counter has been allocated.
2366  */
2367 static enum ice_status
2368 ice_flow_acl_check_actions(struct ice_hw *hw, struct ice_flow_action *acts,
2369 			   u8 acts_cnt, bool *cnt_alloc)
2370 {
2371 	ice_declare_bitmap(dup_check, ICE_AQC_TBL_MAX_ACTION_PAIRS * 2);
2372 	int i;
2373 
2374 	ice_zero_bitmap(dup_check, ICE_AQC_TBL_MAX_ACTION_PAIRS * 2);
2375 	*cnt_alloc = false;
2376 
2377 	if (acts_cnt > ICE_FLOW_ACL_MAX_NUM_ACT)
2378 		return ICE_ERR_OUT_OF_RANGE;
2379 
2380 	for (i = 0; i < acts_cnt; i++) {
2381 		if (acts[i].type != ICE_FLOW_ACT_NOP &&
2382 		    acts[i].type != ICE_FLOW_ACT_DROP &&
2383 		    acts[i].type != ICE_FLOW_ACT_CNTR_PKT &&
2384 		    acts[i].type != ICE_FLOW_ACT_FWD_QUEUE)
2385 			return ICE_ERR_CFG;
2386 
2387 		/* If the caller want to add two actions of the same type, then
2388 		 * it is considered invalid configuration.
2389 		 */
2390 		if (ice_test_and_set_bit(acts[i].type, dup_check))
2391 			return ICE_ERR_PARAM;
2392 	}
2393 
2394 	/* Checks if ACL counters are needed. */
2395 	for (i = 0; i < acts_cnt; i++) {
2396 		if (acts[i].type == ICE_FLOW_ACT_CNTR_PKT ||
2397 		    acts[i].type == ICE_FLOW_ACT_CNTR_BYTES ||
2398 		    acts[i].type == ICE_FLOW_ACT_CNTR_PKT_BYTES) {
2399 			struct ice_acl_cntrs cntrs;
2400 			enum ice_status status;
2401 
2402 			cntrs.amount = 1;
2403 			cntrs.bank = 0; /* Only bank0 for the moment */
2404 
2405 			if (acts[i].type == ICE_FLOW_ACT_CNTR_PKT_BYTES)
2406 				cntrs.type = ICE_AQC_ACL_CNT_TYPE_DUAL;
2407 			else
2408 				cntrs.type = ICE_AQC_ACL_CNT_TYPE_SINGLE;
2409 
2410 			status = ice_aq_alloc_acl_cntrs(hw, &cntrs, NULL);
2411 			if (status)
2412 				return status;
2413 			/* Counter index within the bank */
2414 			acts[i].data.acl_act.value =
2415 						CPU_TO_LE16(cntrs.first_cntr);
2416 			*cnt_alloc = true;
2417 		}
2418 	}
2419 
2420 	return ICE_SUCCESS;
2421 }
2422 
2423 /**
2424  * ice_flow_acl_frmt_entry_range - Format an ACL range checker for a given field
2425  * @fld: number of the given field
2426  * @info: info about field
2427  * @range_buf: range checker configuration buffer
2428  * @data: pointer to a data buffer containing flow entry's match values/masks
2429  * @range: Input/output param indicating which range checkers are being used
2430  */
2431 static void
2432 ice_flow_acl_frmt_entry_range(u16 fld, struct ice_flow_fld_info *info,
2433 			      struct ice_aqc_acl_profile_ranges *range_buf,
2434 			      u8 *data, u8 *range)
2435 {
2436 	u16 new_mask;
2437 
2438 	/* If not specified, default mask is all bits in field */
2439 	new_mask = (info->src.mask == ICE_FLOW_FLD_OFF_INVAL ?
2440 		    BIT(ice_flds_info[fld].size) - 1 :
2441 		    (*(u16 *)(data + info->src.mask))) << info->xtrct.disp;
2442 
2443 	/* If the mask is 0, then we don't need to worry about this input
2444 	 * range checker value.
2445 	 */
2446 	if (new_mask) {
2447 		u16 new_high =
2448 			(*(u16 *)(data + info->src.last)) << info->xtrct.disp;
2449 		u16 new_low =
2450 			(*(u16 *)(data + info->src.val)) << info->xtrct.disp;
2451 		u8 range_idx = info->entry.val;
2452 
2453 		range_buf->checker_cfg[range_idx].low_boundary =
2454 			CPU_TO_BE16(new_low);
2455 		range_buf->checker_cfg[range_idx].high_boundary =
2456 			CPU_TO_BE16(new_high);
2457 		range_buf->checker_cfg[range_idx].mask = CPU_TO_BE16(new_mask);
2458 
2459 		/* Indicate which range checker is being used */
2460 		*range |= BIT(range_idx);
2461 	}
2462 }
2463 
2464 /**
2465  * ice_flow_acl_frmt_entry_fld - Partially format ACL entry for a given field
2466  * @fld: number of the given field
2467  * @info: info about the field
2468  * @buf: buffer containing the entry
2469  * @dontcare: buffer containing don't care mask for entry
2470  * @data: pointer to a data buffer containing flow entry's match values/masks
2471  */
2472 static void
2473 ice_flow_acl_frmt_entry_fld(u16 fld, struct ice_flow_fld_info *info, u8 *buf,
2474 			    u8 *dontcare, u8 *data)
2475 {
2476 	u16 dst, src, mask, k, end_disp, tmp_s = 0, tmp_m = 0;
2477 	bool use_mask = false;
2478 	u8 disp;
2479 
2480 	src = info->src.val;
2481 	mask = info->src.mask;
2482 	dst = info->entry.val - ICE_AQC_ACL_PROF_BYTE_SEL_START_IDX;
2483 	disp = info->xtrct.disp % BITS_PER_BYTE;
2484 
2485 	if (mask != ICE_FLOW_FLD_OFF_INVAL)
2486 		use_mask = true;
2487 
2488 	for (k = 0; k < info->entry.last; k++, dst++) {
2489 		/* Add overflow bits from previous byte */
2490 		buf[dst] = (tmp_s & 0xff00) >> 8;
2491 
2492 		/* If mask is not valid, tmp_m is always zero, so just setting
2493 		 * dontcare to 0 (no masked bits). If mask is valid, pulls in
2494 		 * overflow bits of mask from prev byte
2495 		 */
2496 		dontcare[dst] = (tmp_m & 0xff00) >> 8;
2497 
2498 		/* If there is displacement, last byte will only contain
2499 		 * displaced data, but there is no more data to read from user
2500 		 * buffer, so skip so as not to potentially read beyond end of
2501 		 * user buffer
2502 		 */
2503 		if (!disp || k < info->entry.last - 1) {
2504 			/* Store shifted data to use in next byte */
2505 			tmp_s = data[src++] << disp;
2506 
2507 			/* Add current (shifted) byte */
2508 			buf[dst] |= tmp_s & 0xff;
2509 
2510 			/* Handle mask if valid */
2511 			if (use_mask) {
2512 				tmp_m = (~data[mask++] & 0xff) << disp;
2513 				dontcare[dst] |= tmp_m & 0xff;
2514 			}
2515 		}
2516 	}
2517 
2518 	/* Fill in don't care bits at beginning of field */
2519 	if (disp) {
2520 		dst = info->entry.val - ICE_AQC_ACL_PROF_BYTE_SEL_START_IDX;
2521 		for (k = 0; k < disp; k++)
2522 			dontcare[dst] |= BIT(k);
2523 	}
2524 
2525 	end_disp = (disp + ice_flds_info[fld].size) % BITS_PER_BYTE;
2526 
2527 	/* Fill in don't care bits at end of field */
2528 	if (end_disp) {
2529 		dst = info->entry.val - ICE_AQC_ACL_PROF_BYTE_SEL_START_IDX +
2530 		      info->entry.last - 1;
2531 		for (k = end_disp; k < BITS_PER_BYTE; k++)
2532 			dontcare[dst] |= BIT(k);
2533 	}
2534 }
2535 
2536 /**
2537  * ice_flow_acl_frmt_entry - Format ACL entry
2538  * @hw: pointer to the hardware structure
2539  * @prof: pointer to flow profile
2540  * @e: pointer to the flow entry
2541  * @data: pointer to a data buffer containing flow entry's match values/masks
2542  * @acts: array of actions to be performed on a match
2543  * @acts_cnt: number of actions
2544  *
2545  * Formats the key (and key_inverse) to be matched from the data passed in,
2546  * along with data from the flow profile. This key/key_inverse pair makes up
2547  * the 'entry' for an ACL flow entry.
2548  */
2549 static enum ice_status
2550 ice_flow_acl_frmt_entry(struct ice_hw *hw, struct ice_flow_prof *prof,
2551 			struct ice_flow_entry *e, u8 *data,
2552 			struct ice_flow_action *acts, u8 acts_cnt)
2553 {
2554 	u8 *buf = NULL, *dontcare = NULL, *key = NULL, range = 0, dir_flag_msk;
2555 	struct ice_aqc_acl_profile_ranges *range_buf = NULL;
2556 	enum ice_status status;
2557 	bool cnt_alloc;
2558 	u8 prof_id = 0;
2559 	u16 i, buf_sz;
2560 
2561 	status = ice_flow_get_hw_prof(hw, ICE_BLK_ACL, prof->id, &prof_id);
2562 	if (status)
2563 		return status;
2564 
2565 	/* Format the result action */
2566 
2567 	status = ice_flow_acl_check_actions(hw, acts, acts_cnt, &cnt_alloc);
2568 	if (status)
2569 		return status;
2570 
2571 	status = ICE_ERR_NO_MEMORY;
2572 
2573 	e->acts = (struct ice_flow_action *)
2574 		ice_memdup(hw, acts, acts_cnt * sizeof(*acts),
2575 			   ICE_NONDMA_TO_NONDMA);
2576 	if (!e->acts)
2577 		goto out;
2578 
2579 	e->acts_cnt = acts_cnt;
2580 
2581 	/* Format the matching data */
2582 	buf_sz = prof->cfg.scen->width;
2583 	buf = (u8 *)ice_malloc(hw, buf_sz);
2584 	if (!buf)
2585 		goto out;
2586 
2587 	dontcare = (u8 *)ice_malloc(hw, buf_sz);
2588 	if (!dontcare)
2589 		goto out;
2590 
2591 	/* 'key' buffer will store both key and key_inverse, so must be twice
2592 	 * size of buf
2593 	 */
2594 	key = (u8 *)ice_malloc(hw, buf_sz * 2);
2595 	if (!key)
2596 		goto out;
2597 
2598 	range_buf = (struct ice_aqc_acl_profile_ranges *)
2599 		ice_malloc(hw, sizeof(struct ice_aqc_acl_profile_ranges));
2600 	if (!range_buf)
2601 		goto out;
2602 
2603 	/* Set don't care mask to all 1's to start, will zero out used bytes */
2604 	ice_memset(dontcare, 0xff, buf_sz, ICE_NONDMA_MEM);
2605 
2606 	for (i = 0; i < prof->segs_cnt; i++) {
2607 		struct ice_flow_seg_info *seg = &prof->segs[i];
2608 		u8 j;
2609 
2610 		ice_for_each_set_bit(j, (ice_bitmap_t *)&seg->match,
2611 				     ICE_FLOW_FIELD_IDX_MAX) {
2612 			struct ice_flow_fld_info *info = &seg->fields[j];
2613 
2614 			if (info->type == ICE_FLOW_FLD_TYPE_RANGE)
2615 				ice_flow_acl_frmt_entry_range(j, info,
2616 							      range_buf, data,
2617 							      &range);
2618 			else
2619 				ice_flow_acl_frmt_entry_fld(j, info, buf,
2620 							    dontcare, data);
2621 		}
2622 
2623 		for (j = 0; j < seg->raws_cnt; j++) {
2624 			struct ice_flow_fld_info *info = &seg->raws[j].info;
2625 			u16 dst, src, mask, k;
2626 			bool use_mask = false;
2627 
2628 			src = info->src.val;
2629 			dst = info->entry.val -
2630 					ICE_AQC_ACL_PROF_BYTE_SEL_START_IDX;
2631 			mask = info->src.mask;
2632 
2633 			if (mask != ICE_FLOW_FLD_OFF_INVAL)
2634 				use_mask = true;
2635 
2636 			for (k = 0; k < info->entry.last; k++, dst++) {
2637 				buf[dst] = data[src++];
2638 				if (use_mask)
2639 					dontcare[dst] = ~data[mask++];
2640 				else
2641 					dontcare[dst] = 0;
2642 			}
2643 		}
2644 	}
2645 
2646 	buf[prof->cfg.scen->pid_idx] = (u8)prof_id;
2647 	dontcare[prof->cfg.scen->pid_idx] = 0;
2648 
2649 	/* Format the buffer for direction flags */
2650 	dir_flag_msk = BIT(ICE_FLG_PKT_DIR);
2651 
2652 	if (prof->dir == ICE_FLOW_RX)
2653 		buf[prof->cfg.scen->pkt_dir_idx] = dir_flag_msk;
2654 
2655 	if (range) {
2656 		buf[prof->cfg.scen->rng_chk_idx] = range;
2657 		/* Mark any unused range checkers as don't care */
2658 		dontcare[prof->cfg.scen->rng_chk_idx] = ~range;
2659 		e->range_buf = range_buf;
2660 	} else {
2661 		ice_free(hw, range_buf);
2662 	}
2663 
2664 	status = ice_set_key(key, buf_sz * 2, buf, NULL, dontcare, NULL, 0,
2665 			     buf_sz);
2666 	if (status)
2667 		goto out;
2668 
2669 	e->entry = key;
2670 	e->entry_sz = buf_sz * 2;
2671 
2672 out:
2673 	if (buf)
2674 		ice_free(hw, buf);
2675 
2676 	if (dontcare)
2677 		ice_free(hw, dontcare);
2678 
2679 	if (status && key)
2680 		ice_free(hw, key);
2681 
2682 	if (status && range_buf) {
2683 		ice_free(hw, range_buf);
2684 		e->range_buf = NULL;
2685 	}
2686 
2687 	if (status && e->acts) {
2688 		ice_free(hw, e->acts);
2689 		e->acts = NULL;
2690 		e->acts_cnt = 0;
2691 	}
2692 
2693 	if (status && cnt_alloc)
2694 		ice_flow_acl_free_act_cntr(hw, acts, acts_cnt);
2695 
2696 	return status;
2697 }
2698 
2699 /**
2700  * ice_flow_acl_find_scen_entry_cond - Find an ACL scenario entry that matches
2701  *				       the compared data.
2702  * @prof: pointer to flow profile
2703  * @e: pointer to the comparing flow entry
2704  * @do_chg_action: decide if we want to change the ACL action
2705  * @do_add_entry: decide if we want to add the new ACL entry
2706  * @do_rem_entry: decide if we want to remove the current ACL entry
2707  *
2708  * Find an ACL scenario entry that matches the compared data. In the same time,
2709  * this function also figure out:
2710  * a/ If we want to change the ACL action
2711  * b/ If we want to add the new ACL entry
2712  * c/ If we want to remove the current ACL entry
2713  */
2714 static struct ice_flow_entry *
2715 ice_flow_acl_find_scen_entry_cond(struct ice_flow_prof *prof,
2716 				  struct ice_flow_entry *e, bool *do_chg_action,
2717 				  bool *do_add_entry, bool *do_rem_entry)
2718 {
2719 	struct ice_flow_entry *p, *return_entry = NULL;
2720 	u8 i, j;
2721 
2722 	/* Check if:
2723 	 * a/ There exists an entry with same matching data, but different
2724 	 *    priority, then we remove this existing ACL entry. Then, we
2725 	 *    will add the new entry to the ACL scenario.
2726 	 * b/ There exists an entry with same matching data, priority, and
2727 	 *    result action, then we do nothing
2728 	 * c/ There exists an entry with same matching data, priority, but
2729 	 *    different, action, then do only change the action's entry.
2730 	 * d/ Else, we add this new entry to the ACL scenario.
2731 	 */
2732 	*do_chg_action = false;
2733 	*do_add_entry = true;
2734 	*do_rem_entry = false;
2735 	LIST_FOR_EACH_ENTRY(p, &prof->entries, ice_flow_entry, l_entry) {
2736 		if (memcmp(p->entry, e->entry, p->entry_sz))
2737 			continue;
2738 
2739 		/* From this point, we have the same matching_data. */
2740 		*do_add_entry = false;
2741 		return_entry = p;
2742 
2743 		if (p->priority != e->priority) {
2744 			/* matching data && !priority */
2745 			*do_add_entry = true;
2746 			*do_rem_entry = true;
2747 			break;
2748 		}
2749 
2750 		/* From this point, we will have matching_data && priority */
2751 		if (p->acts_cnt != e->acts_cnt)
2752 			*do_chg_action = true;
2753 		for (i = 0; i < p->acts_cnt; i++) {
2754 			bool found_not_match = false;
2755 
2756 			for (j = 0; j < e->acts_cnt; j++)
2757 				if (memcmp(&p->acts[i], &e->acts[j],
2758 					   sizeof(struct ice_flow_action))) {
2759 					found_not_match = true;
2760 					break;
2761 				}
2762 
2763 			if (found_not_match) {
2764 				*do_chg_action = true;
2765 				break;
2766 			}
2767 		}
2768 
2769 		/* (do_chg_action = true) means :
2770 		 *    matching_data && priority && !result_action
2771 		 * (do_chg_action = false) means :
2772 		 *    matching_data && priority && result_action
2773 		 */
2774 		break;
2775 	}
2776 
2777 	return return_entry;
2778 }
2779 
2780 /**
2781  * ice_flow_acl_convert_to_acl_prio - Convert to ACL priority
2782  * @p: flow priority
2783  */
2784 static enum ice_acl_entry_prio
2785 ice_flow_acl_convert_to_acl_prio(enum ice_flow_priority p)
2786 {
2787 	enum ice_acl_entry_prio acl_prio;
2788 
2789 	switch (p) {
2790 	case ICE_FLOW_PRIO_LOW:
2791 		acl_prio = ICE_ACL_PRIO_LOW;
2792 		break;
2793 	case ICE_FLOW_PRIO_NORMAL:
2794 		acl_prio = ICE_ACL_PRIO_NORMAL;
2795 		break;
2796 	case ICE_FLOW_PRIO_HIGH:
2797 		acl_prio = ICE_ACL_PRIO_HIGH;
2798 		break;
2799 	default:
2800 		acl_prio = ICE_ACL_PRIO_NORMAL;
2801 		break;
2802 	}
2803 
2804 	return acl_prio;
2805 }
2806 
2807 /**
2808  * ice_flow_acl_union_rng_chk - Perform union operation between two
2809  *                              range-range checker buffers
2810  * @dst_buf: pointer to destination range checker buffer
2811  * @src_buf: pointer to source range checker buffer
2812  *
2813  * For this function, we do the union between dst_buf and src_buf
2814  * range checker buffer, and we will save the result back to dst_buf
2815  */
2816 static enum ice_status
2817 ice_flow_acl_union_rng_chk(struct ice_aqc_acl_profile_ranges *dst_buf,
2818 			   struct ice_aqc_acl_profile_ranges *src_buf)
2819 {
2820 	u8 i, j;
2821 
2822 	if (!dst_buf || !src_buf)
2823 		return ICE_ERR_BAD_PTR;
2824 
2825 	for (i = 0; i < ICE_AQC_ACL_PROF_RANGES_NUM_CFG; i++) {
2826 		struct ice_acl_rng_data *cfg_data = NULL, *in_data;
2827 		bool will_populate = false;
2828 
2829 		in_data = &src_buf->checker_cfg[i];
2830 
2831 		if (!in_data->mask)
2832 			break;
2833 
2834 		for (j = 0; j < ICE_AQC_ACL_PROF_RANGES_NUM_CFG; j++) {
2835 			cfg_data = &dst_buf->checker_cfg[j];
2836 
2837 			if (!cfg_data->mask ||
2838 			    !memcmp(cfg_data, in_data,
2839 				    sizeof(struct ice_acl_rng_data))) {
2840 				will_populate = true;
2841 				break;
2842 			}
2843 		}
2844 
2845 		if (will_populate) {
2846 			ice_memcpy(cfg_data, in_data,
2847 				   sizeof(struct ice_acl_rng_data),
2848 				   ICE_NONDMA_TO_NONDMA);
2849 		} else {
2850 			/* No available slot left to program range checker */
2851 			return ICE_ERR_MAX_LIMIT;
2852 		}
2853 	}
2854 
2855 	return ICE_SUCCESS;
2856 }
2857 
2858 /**
2859  * ice_flow_acl_add_scen_entry_sync - Add entry to ACL scenario sync
2860  * @hw: pointer to the hardware structure
2861  * @prof: pointer to flow profile
2862  * @entry: double pointer to the flow entry
2863  *
2864  * For this function, we will look at the current added entries in the
2865  * corresponding ACL scenario. Then, we will perform matching logic to
2866  * see if we want to add/modify/do nothing with this new entry.
2867  */
2868 static enum ice_status
2869 ice_flow_acl_add_scen_entry_sync(struct ice_hw *hw, struct ice_flow_prof *prof,
2870 				 struct ice_flow_entry **entry)
2871 {
2872 	bool do_add_entry, do_rem_entry, do_chg_action, do_chg_rng_chk;
2873 	struct ice_aqc_acl_profile_ranges query_rng_buf, cfg_rng_buf;
2874 	struct ice_acl_act_entry *acts = NULL;
2875 	struct ice_flow_entry *exist;
2876 	enum ice_status status = ICE_SUCCESS;
2877 	struct ice_flow_entry *e;
2878 	u8 i;
2879 
2880 	if (!entry || !(*entry) || !prof)
2881 		return ICE_ERR_BAD_PTR;
2882 
2883 	e = *entry;
2884 
2885 	do_chg_rng_chk = false;
2886 	if (e->range_buf) {
2887 		u8 prof_id = 0;
2888 
2889 		status = ice_flow_get_hw_prof(hw, ICE_BLK_ACL, prof->id,
2890 					      &prof_id);
2891 		if (status)
2892 			return status;
2893 
2894 		/* Query the current range-checker value in FW */
2895 		status = ice_query_acl_prof_ranges(hw, prof_id, &query_rng_buf,
2896 						   NULL);
2897 		if (status)
2898 			return status;
2899 		ice_memcpy(&cfg_rng_buf, &query_rng_buf,
2900 			   sizeof(struct ice_aqc_acl_profile_ranges),
2901 			   ICE_NONDMA_TO_NONDMA);
2902 
2903 		/* Generate the new range-checker value */
2904 		status = ice_flow_acl_union_rng_chk(&cfg_rng_buf, e->range_buf);
2905 		if (status)
2906 			return status;
2907 
2908 		/* Reconfigure the range check if the buffer is changed. */
2909 		do_chg_rng_chk = false;
2910 		if (memcmp(&query_rng_buf, &cfg_rng_buf,
2911 			   sizeof(struct ice_aqc_acl_profile_ranges))) {
2912 			status = ice_prog_acl_prof_ranges(hw, prof_id,
2913 							  &cfg_rng_buf, NULL);
2914 			if (status)
2915 				return status;
2916 
2917 			do_chg_rng_chk = true;
2918 		}
2919 	}
2920 
2921 	/* Figure out if we want to (change the ACL action) and/or
2922 	 * (Add the new ACL entry) and/or (Remove the current ACL entry)
2923 	 */
2924 	exist = ice_flow_acl_find_scen_entry_cond(prof, e, &do_chg_action,
2925 						  &do_add_entry, &do_rem_entry);
2926 	if (do_rem_entry) {
2927 		status = ice_flow_rem_entry_sync(hw, ICE_BLK_ACL, exist);
2928 		if (status)
2929 			return status;
2930 	}
2931 
2932 	/* Prepare the result action buffer */
2933 	acts = (struct ice_acl_act_entry *)
2934 		ice_calloc(hw, e->entry_sz, sizeof(struct ice_acl_act_entry));
2935 	if (!acts)
2936 		return ICE_ERR_NO_MEMORY;
2937 
2938 	for (i = 0; i < e->acts_cnt; i++)
2939 		ice_memcpy(&acts[i], &e->acts[i].data.acl_act,
2940 			   sizeof(struct ice_acl_act_entry),
2941 			   ICE_NONDMA_TO_NONDMA);
2942 
2943 	if (do_add_entry) {
2944 		enum ice_acl_entry_prio prio;
2945 		u8 *keys, *inverts;
2946 		u16 entry_idx;
2947 
2948 		keys = (u8 *)e->entry;
2949 		inverts = keys + (e->entry_sz / 2);
2950 		prio = ice_flow_acl_convert_to_acl_prio(e->priority);
2951 
2952 		status = ice_acl_add_entry(hw, prof->cfg.scen, prio, keys,
2953 					   inverts, acts, e->acts_cnt,
2954 					   &entry_idx);
2955 		if (status)
2956 			goto out;
2957 
2958 		e->scen_entry_idx = entry_idx;
2959 		LIST_ADD(&e->l_entry, &prof->entries);
2960 	} else {
2961 		if (do_chg_action) {
2962 			/* For the action memory info, update the SW's copy of
2963 			 * exist entry with e's action memory info
2964 			 */
2965 			ice_free(hw, exist->acts);
2966 			exist->acts_cnt = e->acts_cnt;
2967 			exist->acts = (struct ice_flow_action *)
2968 				ice_calloc(hw, exist->acts_cnt,
2969 					   sizeof(struct ice_flow_action));
2970 			if (!exist->acts) {
2971 				status = ICE_ERR_NO_MEMORY;
2972 				goto out;
2973 			}
2974 
2975 			ice_memcpy(exist->acts, e->acts,
2976 				   sizeof(struct ice_flow_action) * e->acts_cnt,
2977 				   ICE_NONDMA_TO_NONDMA);
2978 
2979 			status = ice_acl_prog_act(hw, prof->cfg.scen, acts,
2980 						  e->acts_cnt,
2981 						  exist->scen_entry_idx);
2982 			if (status)
2983 				goto out;
2984 		}
2985 
2986 		if (do_chg_rng_chk) {
2987 			/* In this case, we want to update the range checker
2988 			 * information of the exist entry
2989 			 */
2990 			status = ice_flow_acl_union_rng_chk(exist->range_buf,
2991 							    e->range_buf);
2992 			if (status)
2993 				goto out;
2994 		}
2995 
2996 		/* As we don't add the new entry to our SW DB, deallocate its
2997 		 * memories, and return the exist entry to the caller
2998 		 */
2999 		ice_dealloc_flow_entry(hw, e);
3000 		*(entry) = exist;
3001 	}
3002 out:
3003 	ice_free(hw, acts);
3004 
3005 	return status;
3006 }
3007 
3008 /**
3009  * ice_flow_acl_add_scen_entry - Add entry to ACL scenario
3010  * @hw: pointer to the hardware structure
3011  * @prof: pointer to flow profile
3012  * @e: double pointer to the flow entry
3013  */
3014 static enum ice_status
3015 ice_flow_acl_add_scen_entry(struct ice_hw *hw, struct ice_flow_prof *prof,
3016 			    struct ice_flow_entry **e)
3017 {
3018 	enum ice_status status;
3019 
3020 	ice_acquire_lock(&prof->entries_lock);
3021 	status = ice_flow_acl_add_scen_entry_sync(hw, prof, e);
3022 	ice_release_lock(&prof->entries_lock);
3023 
3024 	return status;
3025 }
3026 
3027 /**
3028  * ice_flow_add_entry - Add a flow entry
3029  * @hw: pointer to the HW struct
3030  * @blk: classification stage
3031  * @prof_id: ID of the profile to add a new flow entry to
3032  * @entry_id: unique ID to identify this flow entry
3033  * @vsi_handle: software VSI handle for the flow entry
3034  * @prio: priority of the flow entry
3035  * @data: pointer to a data buffer containing flow entry's match values/masks
3036  * @acts: arrays of actions to be performed on a match
3037  * @acts_cnt: number of actions
3038  * @entry_h: pointer to buffer that receives the new flow entry's handle
3039  */
3040 enum ice_status
3041 ice_flow_add_entry(struct ice_hw *hw, enum ice_block blk, u64 prof_id,
3042 		   u64 entry_id, u16 vsi_handle, enum ice_flow_priority prio,
3043 		   void *data, struct ice_flow_action *acts, u8 acts_cnt,
3044 		   u64 *entry_h)
3045 {
3046 	struct ice_flow_entry *e = NULL;
3047 	struct ice_flow_prof *prof;
3048 	enum ice_status status = ICE_SUCCESS;
3049 
3050 	/* ACL entries must indicate an action */
3051 	if (blk == ICE_BLK_ACL && (!acts || !acts_cnt))
3052 		return ICE_ERR_PARAM;
3053 
3054 	/* No flow entry data is expected for RSS */
3055 	if (!entry_h || (!data && blk != ICE_BLK_RSS))
3056 		return ICE_ERR_BAD_PTR;
3057 
3058 	if (!ice_is_vsi_valid(hw, vsi_handle))
3059 		return ICE_ERR_PARAM;
3060 
3061 	ice_acquire_lock(&hw->fl_profs_locks[blk]);
3062 
3063 	prof = ice_flow_find_prof_id(hw, blk, prof_id);
3064 	if (!prof) {
3065 		status = ICE_ERR_DOES_NOT_EXIST;
3066 	} else {
3067 		/* Allocate memory for the entry being added and associate
3068 		 * the VSI to the found flow profile
3069 		 */
3070 		e = (struct ice_flow_entry *)ice_malloc(hw, sizeof(*e));
3071 		if (!e)
3072 			status = ICE_ERR_NO_MEMORY;
3073 		else
3074 			status = ice_flow_assoc_prof(hw, blk, prof, vsi_handle);
3075 	}
3076 
3077 	ice_release_lock(&hw->fl_profs_locks[blk]);
3078 	if (status)
3079 		goto out;
3080 
3081 	e->id = entry_id;
3082 	e->vsi_handle = vsi_handle;
3083 	e->prof = prof;
3084 	e->priority = prio;
3085 
3086 	switch (blk) {
3087 	case ICE_BLK_FD:
3088 	case ICE_BLK_RSS:
3089 		break;
3090 	case ICE_BLK_ACL:
3091 		/* ACL will handle the entry management */
3092 		status = ice_flow_acl_frmt_entry(hw, prof, e, (u8 *)data, acts,
3093 						 acts_cnt);
3094 		if (status)
3095 			goto out;
3096 
3097 		status = ice_flow_acl_add_scen_entry(hw, prof, &e);
3098 		if (status)
3099 			goto out;
3100 
3101 		break;
3102 	default:
3103 		status = ICE_ERR_NOT_IMPL;
3104 		goto out;
3105 	}
3106 
3107 	if (blk != ICE_BLK_ACL) {
3108 		/* ACL will handle the entry management */
3109 		ice_acquire_lock(&prof->entries_lock);
3110 		LIST_ADD(&e->l_entry, &prof->entries);
3111 		ice_release_lock(&prof->entries_lock);
3112 	}
3113 
3114 	*entry_h = ICE_FLOW_ENTRY_HNDL(e);
3115 
3116 out:
3117 	if (status && e) {
3118 		if (e->entry)
3119 			ice_free(hw, e->entry);
3120 		ice_free(hw, e);
3121 	}
3122 
3123 	return status;
3124 }
3125 
3126 /**
3127  * ice_flow_rem_entry - Remove a flow entry
3128  * @hw: pointer to the HW struct
3129  * @blk: classification stage
3130  * @entry_h: handle to the flow entry to be removed
3131  */
3132 enum ice_status ice_flow_rem_entry(struct ice_hw *hw, enum ice_block blk,
3133 				   u64 entry_h)
3134 {
3135 	struct ice_flow_entry *entry;
3136 	struct ice_flow_prof *prof;
3137 	enum ice_status status = ICE_SUCCESS;
3138 
3139 	if (entry_h == ICE_FLOW_ENTRY_HANDLE_INVAL)
3140 		return ICE_ERR_PARAM;
3141 
3142 	entry = ICE_FLOW_ENTRY_PTR((unsigned long)entry_h);
3143 
3144 	/* Retain the pointer to the flow profile as the entry will be freed */
3145 	prof = entry->prof;
3146 
3147 	if (prof) {
3148 		ice_acquire_lock(&prof->entries_lock);
3149 		status = ice_flow_rem_entry_sync(hw, blk, entry);
3150 		ice_release_lock(&prof->entries_lock);
3151 	}
3152 
3153 	return status;
3154 }
3155 
3156 /**
3157  * ice_flow_set_fld_ext - specifies locations of field from entry's input buffer
3158  * @seg: packet segment the field being set belongs to
3159  * @fld: field to be set
3160  * @field_type: type of the field
3161  * @val_loc: if not ICE_FLOW_FLD_OFF_INVAL, location of the value to match from
3162  *           entry's input buffer
3163  * @mask_loc: if not ICE_FLOW_FLD_OFF_INVAL, location of mask value from entry's
3164  *            input buffer
3165  * @last_loc: if not ICE_FLOW_FLD_OFF_INVAL, location of last/upper value from
3166  *            entry's input buffer
3167  *
3168  * This helper function stores information of a field being matched, including
3169  * the type of the field and the locations of the value to match, the mask, and
3170  * the upper-bound value in the start of the input buffer for a flow entry.
3171  * This function should only be used for fixed-size data structures.
3172  *
3173  * This function also opportunistically determines the protocol headers to be
3174  * present based on the fields being set. Some fields cannot be used alone to
3175  * determine the protocol headers present. Sometimes, fields for particular
3176  * protocol headers are not matched. In those cases, the protocol headers
3177  * must be explicitly set.
3178  */
3179 static void
3180 ice_flow_set_fld_ext(struct ice_flow_seg_info *seg, enum ice_flow_field fld,
3181 		     enum ice_flow_fld_match_type field_type, u16 val_loc,
3182 		     u16 mask_loc, u16 last_loc)
3183 {
3184 	u64 bit = BIT_ULL(fld);
3185 
3186 	seg->match |= bit;
3187 	if (field_type == ICE_FLOW_FLD_TYPE_RANGE)
3188 		seg->range |= bit;
3189 
3190 	seg->fields[fld].type = field_type;
3191 	seg->fields[fld].src.val = val_loc;
3192 	seg->fields[fld].src.mask = mask_loc;
3193 	seg->fields[fld].src.last = last_loc;
3194 
3195 	ICE_FLOW_SET_HDRS(seg, ice_flds_info[fld].hdr);
3196 }
3197 
3198 /**
3199  * ice_flow_set_fld - specifies locations of field from entry's input buffer
3200  * @seg: packet segment the field being set belongs to
3201  * @fld: field to be set
3202  * @val_loc: if not ICE_FLOW_FLD_OFF_INVAL, location of the value to match from
3203  *           entry's input buffer
3204  * @mask_loc: if not ICE_FLOW_FLD_OFF_INVAL, location of mask value from entry's
3205  *            input buffer
3206  * @last_loc: if not ICE_FLOW_FLD_OFF_INVAL, location of last/upper value from
3207  *            entry's input buffer
3208  * @range: indicate if field being matched is to be in a range
3209  *
3210  * This function specifies the locations, in the form of byte offsets from the
3211  * start of the input buffer for a flow entry, from where the value to match,
3212  * the mask value, and upper value can be extracted. These locations are then
3213  * stored in the flow profile. When adding a flow entry associated with the
3214  * flow profile, these locations will be used to quickly extract the values and
3215  * create the content of a match entry. This function should only be used for
3216  * fixed-size data structures.
3217  */
3218 void
3219 ice_flow_set_fld(struct ice_flow_seg_info *seg, enum ice_flow_field fld,
3220 		 u16 val_loc, u16 mask_loc, u16 last_loc, bool range)
3221 {
3222 	enum ice_flow_fld_match_type t = range ?
3223 		ICE_FLOW_FLD_TYPE_RANGE : ICE_FLOW_FLD_TYPE_REG;
3224 
3225 	ice_flow_set_fld_ext(seg, fld, t, val_loc, mask_loc, last_loc);
3226 }
3227 
3228 /**
3229  * ice_flow_set_fld_prefix - sets locations of prefix field from entry's buf
3230  * @seg: packet segment the field being set belongs to
3231  * @fld: field to be set
3232  * @val_loc: if not ICE_FLOW_FLD_OFF_INVAL, location of the value to match from
3233  *           entry's input buffer
3234  * @pref_loc: location of prefix value from entry's input buffer
3235  * @pref_sz: size of the location holding the prefix value
3236  *
3237  * This function specifies the locations, in the form of byte offsets from the
3238  * start of the input buffer for a flow entry, from where the value to match
3239  * and the IPv4 prefix value can be extracted. These locations are then stored
3240  * in the flow profile. When adding flow entries to the associated flow profile,
3241  * these locations can be used to quickly extract the values to create the
3242  * content of a match entry. This function should only be used for fixed-size
3243  * data structures.
3244  */
3245 void
3246 ice_flow_set_fld_prefix(struct ice_flow_seg_info *seg, enum ice_flow_field fld,
3247 			u16 val_loc, u16 pref_loc, u8 pref_sz)
3248 {
3249 	/* For this type of field, the "mask" location is for the prefix value's
3250 	 * location and the "last" location is for the size of the location of
3251 	 * the prefix value.
3252 	 */
3253 	ice_flow_set_fld_ext(seg, fld, ICE_FLOW_FLD_TYPE_PREFIX, val_loc,
3254 			     pref_loc, (u16)pref_sz);
3255 }
3256 
3257 /**
3258  * ice_flow_add_fld_raw - sets locations of a raw field from entry's input buf
3259  * @seg: packet segment the field being set belongs to
3260  * @off: offset of the raw field from the beginning of the segment in bytes
3261  * @len: length of the raw pattern to be matched
3262  * @val_loc: location of the value to match from entry's input buffer
3263  * @mask_loc: location of mask value from entry's input buffer
3264  *
3265  * This function specifies the offset of the raw field to be match from the
3266  * beginning of the specified packet segment, and the locations, in the form of
3267  * byte offsets from the start of the input buffer for a flow entry, from where
3268  * the value to match and the mask value to be extracted. These locations are
3269  * then stored in the flow profile. When adding flow entries to the associated
3270  * flow profile, these locations can be used to quickly extract the values to
3271  * create the content of a match entry. This function should only be used for
3272  * fixed-size data structures.
3273  */
3274 void
3275 ice_flow_add_fld_raw(struct ice_flow_seg_info *seg, u16 off, u8 len,
3276 		     u16 val_loc, u16 mask_loc)
3277 {
3278 	if (seg->raws_cnt < ICE_FLOW_SEG_RAW_FLD_MAX) {
3279 		seg->raws[seg->raws_cnt].off = off;
3280 		seg->raws[seg->raws_cnt].info.type = ICE_FLOW_FLD_TYPE_SIZE;
3281 		seg->raws[seg->raws_cnt].info.src.val = val_loc;
3282 		seg->raws[seg->raws_cnt].info.src.mask = mask_loc;
3283 		/* The "last" field is used to store the length of the field */
3284 		seg->raws[seg->raws_cnt].info.src.last = len;
3285 	}
3286 
3287 	/* Overflows of "raws" will be handled as an error condition later in
3288 	 * the flow when this information is processed.
3289 	 */
3290 	seg->raws_cnt++;
3291 }
3292 
3293 #define ICE_FLOW_RSS_SEG_HDR_L2_MASKS \
3294 (ICE_FLOW_SEG_HDR_ETH | ICE_FLOW_SEG_HDR_VLAN)
3295 
3296 #define ICE_FLOW_RSS_SEG_HDR_L3_MASKS \
3297 	(ICE_FLOW_SEG_HDR_IPV4 | ICE_FLOW_SEG_HDR_IPV6)
3298 
3299 #define ICE_FLOW_RSS_SEG_HDR_L4_MASKS \
3300 	(ICE_FLOW_SEG_HDR_TCP | ICE_FLOW_SEG_HDR_UDP | ICE_FLOW_SEG_HDR_SCTP)
3301 
3302 #define ICE_FLOW_RSS_SEG_HDR_VAL_MASKS \
3303 	(ICE_FLOW_RSS_SEG_HDR_L2_MASKS | \
3304 	 ICE_FLOW_RSS_SEG_HDR_L3_MASKS | \
3305 	 ICE_FLOW_RSS_SEG_HDR_L4_MASKS)
3306 
3307 /**
3308  * ice_flow_set_rss_seg_info - setup packet segments for RSS
3309  * @segs: pointer to the flow field segment(s)
3310  * @seg_cnt: segment count
3311  * @cfg: configure parameters
3312  *
3313  * Helper function to extract fields from hash bitmap and use flow
3314  * header value to set flow field segment for further use in flow
3315  * profile entry or removal.
3316  */
3317 static enum ice_status
3318 ice_flow_set_rss_seg_info(struct ice_flow_seg_info *segs, u8 seg_cnt,
3319 			  const struct ice_rss_hash_cfg *cfg)
3320 {
3321 	struct ice_flow_seg_info *seg;
3322 	u64 val;
3323 	u8 i;
3324 
3325 	/* set inner most segment */
3326 	seg = &segs[seg_cnt - 1];
3327 
3328 	ice_for_each_set_bit(i, (const ice_bitmap_t *)&cfg->hash_flds,
3329 			     ICE_FLOW_FIELD_IDX_MAX)
3330 		ice_flow_set_fld(seg, (enum ice_flow_field)i,
3331 				 ICE_FLOW_FLD_OFF_INVAL, ICE_FLOW_FLD_OFF_INVAL,
3332 				 ICE_FLOW_FLD_OFF_INVAL, false);
3333 
3334 	ICE_FLOW_SET_HDRS(seg, cfg->addl_hdrs);
3335 
3336 	/* set outer most header */
3337 	if (cfg->hdr_type == ICE_RSS_INNER_HEADERS_W_OUTER_IPV4)
3338 		segs[ICE_RSS_OUTER_HEADERS].hdrs |= ICE_FLOW_SEG_HDR_IPV4 |
3339 						   ICE_FLOW_SEG_HDR_IPV_OTHER;
3340 	else if (cfg->hdr_type == ICE_RSS_INNER_HEADERS_W_OUTER_IPV6)
3341 		segs[ICE_RSS_OUTER_HEADERS].hdrs |= ICE_FLOW_SEG_HDR_IPV6 |
3342 						   ICE_FLOW_SEG_HDR_IPV_OTHER;
3343 
3344 	if (seg->hdrs & ~ICE_FLOW_RSS_SEG_HDR_VAL_MASKS &
3345 	    ~ICE_FLOW_RSS_HDRS_INNER_MASK & ~ICE_FLOW_SEG_HDR_IPV_OTHER)
3346 		return ICE_ERR_PARAM;
3347 
3348 	val = (u64)(seg->hdrs & ICE_FLOW_RSS_SEG_HDR_L3_MASKS);
3349 	if (val && !ice_is_pow2(val))
3350 		return ICE_ERR_CFG;
3351 
3352 	val = (u64)(seg->hdrs & ICE_FLOW_RSS_SEG_HDR_L4_MASKS);
3353 	if (val && !ice_is_pow2(val))
3354 		return ICE_ERR_CFG;
3355 
3356 	return ICE_SUCCESS;
3357 }
3358 
3359 /**
3360  * ice_rem_vsi_rss_list - remove VSI from RSS list
3361  * @hw: pointer to the hardware structure
3362  * @vsi_handle: software VSI handle
3363  *
3364  * Remove the VSI from all RSS configurations in the list.
3365  */
3366 void ice_rem_vsi_rss_list(struct ice_hw *hw, u16 vsi_handle)
3367 {
3368 	struct ice_rss_cfg *r, *tmp;
3369 
3370 	if (LIST_EMPTY(&hw->rss_list_head))
3371 		return;
3372 
3373 	ice_acquire_lock(&hw->rss_locks);
3374 	LIST_FOR_EACH_ENTRY_SAFE(r, tmp, &hw->rss_list_head,
3375 				 ice_rss_cfg, l_entry)
3376 		if (ice_test_and_clear_bit(vsi_handle, r->vsis))
3377 			if (!ice_is_any_bit_set(r->vsis, ICE_MAX_VSI)) {
3378 				LIST_DEL(&r->l_entry);
3379 				ice_free(hw, r);
3380 			}
3381 	ice_release_lock(&hw->rss_locks);
3382 }
3383 
3384 /**
3385  * ice_rem_vsi_rss_cfg - remove RSS configurations associated with VSI
3386  * @hw: pointer to the hardware structure
3387  * @vsi_handle: software VSI handle
3388  *
3389  * This function will iterate through all flow profiles and disassociate
3390  * the VSI from that profile. If the flow profile has no VSIs it will
3391  * be removed.
3392  */
3393 enum ice_status ice_rem_vsi_rss_cfg(struct ice_hw *hw, u16 vsi_handle)
3394 {
3395 	const enum ice_block blk = ICE_BLK_RSS;
3396 	struct ice_flow_prof *p, *t;
3397 	enum ice_status status = ICE_SUCCESS;
3398 
3399 	if (!ice_is_vsi_valid(hw, vsi_handle))
3400 		return ICE_ERR_PARAM;
3401 
3402 	if (LIST_EMPTY(&hw->fl_profs[blk]))
3403 		return ICE_SUCCESS;
3404 
3405 	ice_acquire_lock(&hw->rss_locks);
3406 	LIST_FOR_EACH_ENTRY_SAFE(p, t, &hw->fl_profs[blk], ice_flow_prof,
3407 				 l_entry)
3408 		if (ice_is_bit_set(p->vsis, vsi_handle)) {
3409 			status = ice_flow_disassoc_prof(hw, blk, p, vsi_handle);
3410 			if (status)
3411 				break;
3412 
3413 			if (!ice_is_any_bit_set(p->vsis, ICE_MAX_VSI)) {
3414 				status = ice_flow_rem_prof(hw, blk, p->id);
3415 				if (status)
3416 					break;
3417 			}
3418 		}
3419 	ice_release_lock(&hw->rss_locks);
3420 
3421 	return status;
3422 }
3423 
3424 /**
3425  * ice_get_rss_hdr_type - get a RSS profile's header type
3426  * @prof: RSS flow profile
3427  */
3428 static enum ice_rss_cfg_hdr_type
3429 ice_get_rss_hdr_type(struct ice_flow_prof *prof)
3430 {
3431 	enum ice_rss_cfg_hdr_type hdr_type = ICE_RSS_ANY_HEADERS;
3432 
3433 	if (prof->segs_cnt == ICE_FLOW_SEG_SINGLE) {
3434 		hdr_type = ICE_RSS_OUTER_HEADERS;
3435 	} else if (prof->segs_cnt == ICE_FLOW_SEG_MAX) {
3436 		if (prof->segs[ICE_RSS_OUTER_HEADERS].hdrs == ICE_FLOW_SEG_HDR_NONE)
3437 			hdr_type = ICE_RSS_INNER_HEADERS;
3438 		if (prof->segs[ICE_RSS_OUTER_HEADERS].hdrs & ICE_FLOW_SEG_HDR_IPV4)
3439 			hdr_type = ICE_RSS_INNER_HEADERS_W_OUTER_IPV4;
3440 		if (prof->segs[ICE_RSS_OUTER_HEADERS].hdrs & ICE_FLOW_SEG_HDR_IPV6)
3441 			hdr_type = ICE_RSS_INNER_HEADERS_W_OUTER_IPV6;
3442 	}
3443 
3444 	return hdr_type;
3445 }
3446 
3447 /**
3448  * ice_rem_rss_list - remove RSS configuration from list
3449  * @hw: pointer to the hardware structure
3450  * @vsi_handle: software VSI handle
3451  * @prof: pointer to flow profile
3452  *
3453  * Assumption: lock has already been acquired for RSS list
3454  */
3455 static void
3456 ice_rem_rss_list(struct ice_hw *hw, u16 vsi_handle, struct ice_flow_prof *prof)
3457 {
3458 	enum ice_rss_cfg_hdr_type hdr_type;
3459 	struct ice_rss_cfg *r, *tmp;
3460 
3461 	/* Search for RSS hash fields associated to the VSI that match the
3462 	 * hash configurations associated to the flow profile. If found
3463 	 * remove from the RSS entry list of the VSI context and delete entry.
3464 	 */
3465 	hdr_type = ice_get_rss_hdr_type(prof);
3466 	LIST_FOR_EACH_ENTRY_SAFE(r, tmp, &hw->rss_list_head,
3467 				 ice_rss_cfg, l_entry)
3468 		if (r->hash.hash_flds == prof->segs[prof->segs_cnt - 1].match &&
3469 		    r->hash.addl_hdrs == prof->segs[prof->segs_cnt - 1].hdrs &&
3470 		    r->hash.hdr_type == hdr_type) {
3471 			ice_clear_bit(vsi_handle, r->vsis);
3472 			if (!ice_is_any_bit_set(r->vsis, ICE_MAX_VSI)) {
3473 				LIST_DEL(&r->l_entry);
3474 				ice_free(hw, r);
3475 			}
3476 			return;
3477 		}
3478 }
3479 
3480 /**
3481  * ice_add_rss_list - add RSS configuration to list
3482  * @hw: pointer to the hardware structure
3483  * @vsi_handle: software VSI handle
3484  * @prof: pointer to flow profile
3485  *
3486  * Assumption: lock has already been acquired for RSS list
3487  */
3488 static enum ice_status
3489 ice_add_rss_list(struct ice_hw *hw, u16 vsi_handle, struct ice_flow_prof *prof)
3490 {
3491 	enum ice_rss_cfg_hdr_type hdr_type;
3492 	struct ice_rss_cfg *r, *rss_cfg;
3493 
3494 	hdr_type = ice_get_rss_hdr_type(prof);
3495 	LIST_FOR_EACH_ENTRY(r, &hw->rss_list_head,
3496 			    ice_rss_cfg, l_entry)
3497 		if (r->hash.hash_flds == prof->segs[prof->segs_cnt - 1].match &&
3498 		    r->hash.addl_hdrs == prof->segs[prof->segs_cnt - 1].hdrs &&
3499 		    r->hash.hdr_type == hdr_type) {
3500 			ice_set_bit(vsi_handle, r->vsis);
3501 			return ICE_SUCCESS;
3502 		}
3503 
3504 	rss_cfg = (struct ice_rss_cfg *)ice_malloc(hw, sizeof(*rss_cfg));
3505 	if (!rss_cfg)
3506 		return ICE_ERR_NO_MEMORY;
3507 
3508 	rss_cfg->hash.hash_flds = prof->segs[prof->segs_cnt - 1].match;
3509 	rss_cfg->hash.addl_hdrs = prof->segs[prof->segs_cnt - 1].hdrs;
3510 	rss_cfg->hash.hdr_type = hdr_type;
3511 	rss_cfg->hash.symm = prof->cfg.symm;
3512 	ice_set_bit(vsi_handle, rss_cfg->vsis);
3513 
3514 	LIST_ADD_TAIL(&rss_cfg->l_entry, &hw->rss_list_head);
3515 
3516 	return ICE_SUCCESS;
3517 }
3518 
3519 #define ICE_FLOW_PROF_HASH_S	0
3520 #define ICE_FLOW_PROF_HASH_M	(0xFFFFFFFFULL << ICE_FLOW_PROF_HASH_S)
3521 #define ICE_FLOW_PROF_HDR_S	32
3522 #define ICE_FLOW_PROF_HDR_M	(0x3FFFFFFFULL << ICE_FLOW_PROF_HDR_S)
3523 #define ICE_FLOW_PROF_ENCAP_S	62
3524 #define ICE_FLOW_PROF_ENCAP_M	(0x3ULL << ICE_FLOW_PROF_ENCAP_S)
3525 
3526 /* Flow profile ID format:
3527  * [0:31] - Packet match fields
3528  * [32:61] - Protocol header
3529  * [62:63] - Encapsulation flag:
3530  *	     0 if non-tunneled
3531  *	     1 if tunneled
3532  *	     2 for tunneled with outer ipv4
3533  *	     3 for tunneled with outer ipv6
3534  */
3535 #define ICE_FLOW_GEN_PROFID(hash, hdr, encap) \
3536 	(u64)(((u64)(hash) & ICE_FLOW_PROF_HASH_M) | \
3537 	      (((u64)(hdr) << ICE_FLOW_PROF_HDR_S) & ICE_FLOW_PROF_HDR_M) | \
3538 	      (((u64)(encap) << ICE_FLOW_PROF_ENCAP_S) & ICE_FLOW_PROF_ENCAP_M))
3539 
3540 static void
3541 ice_rss_config_xor_word(struct ice_hw *hw, u8 prof_id, u8 src, u8 dst)
3542 {
3543 	u32 s = ((src % 4) << 3); /* byte shift */
3544 	u32 v = dst | 0x80; /* value to program */
3545 	u8 i = src / 4; /* register index */
3546 	u32 reg;
3547 
3548 	reg = rd32(hw, GLQF_HSYMM(prof_id, i));
3549 	reg = (reg & ~(0xff << s)) | (v << s);
3550 	wr32(hw, GLQF_HSYMM(prof_id, i), reg);
3551 }
3552 
3553 static void
3554 ice_rss_config_xor(struct ice_hw *hw, u8 prof_id, u8 src, u8 dst, u8 len)
3555 {
3556 	int fv_last_word =
3557 		ICE_FLOW_SW_FIELD_VECTOR_MAX / ICE_FLOW_FV_EXTRACT_SZ - 1;
3558 	int i;
3559 
3560 	for (i = 0; i < len; i++) {
3561 		ice_rss_config_xor_word(hw, prof_id,
3562 					/* Yes, field vector in GLQF_HSYMM and
3563 					 * GLQF_HINSET is inversed!
3564 					 */
3565 					fv_last_word - (src + i),
3566 					fv_last_word - (dst + i));
3567 		ice_rss_config_xor_word(hw, prof_id,
3568 					fv_last_word - (dst + i),
3569 					fv_last_word - (src + i));
3570 	}
3571 }
3572 
3573 static void
3574 ice_rss_update_symm(struct ice_hw *hw,
3575 		    struct ice_flow_prof *prof)
3576 {
3577 	struct ice_prof_map *map;
3578 	u8 prof_id, m;
3579 
3580 	ice_acquire_lock(&hw->blk[ICE_BLK_RSS].es.prof_map_lock);
3581 	map = ice_search_prof_id(hw, ICE_BLK_RSS, prof->id);
3582 	if (map)
3583 		prof_id = map->prof_id;
3584 	ice_release_lock(&hw->blk[ICE_BLK_RSS].es.prof_map_lock);
3585 	if (!map)
3586 		return;
3587 	/* clear to default */
3588 	for (m = 0; m < 6; m++)
3589 		wr32(hw, GLQF_HSYMM(prof_id, m), 0);
3590 	if (prof->cfg.symm) {
3591 		struct ice_flow_seg_info *seg =
3592 			&prof->segs[prof->segs_cnt - 1];
3593 
3594 		struct ice_flow_seg_xtrct *ipv4_src =
3595 			&seg->fields[ICE_FLOW_FIELD_IDX_IPV4_SA].xtrct;
3596 		struct ice_flow_seg_xtrct *ipv4_dst =
3597 			&seg->fields[ICE_FLOW_FIELD_IDX_IPV4_DA].xtrct;
3598 		struct ice_flow_seg_xtrct *ipv6_src =
3599 			&seg->fields[ICE_FLOW_FIELD_IDX_IPV6_SA].xtrct;
3600 		struct ice_flow_seg_xtrct *ipv6_dst =
3601 			&seg->fields[ICE_FLOW_FIELD_IDX_IPV6_DA].xtrct;
3602 
3603 		struct ice_flow_seg_xtrct *tcp_src =
3604 			&seg->fields[ICE_FLOW_FIELD_IDX_TCP_SRC_PORT].xtrct;
3605 		struct ice_flow_seg_xtrct *tcp_dst =
3606 			&seg->fields[ICE_FLOW_FIELD_IDX_TCP_DST_PORT].xtrct;
3607 
3608 		struct ice_flow_seg_xtrct *udp_src =
3609 			&seg->fields[ICE_FLOW_FIELD_IDX_UDP_SRC_PORT].xtrct;
3610 		struct ice_flow_seg_xtrct *udp_dst =
3611 			&seg->fields[ICE_FLOW_FIELD_IDX_UDP_DST_PORT].xtrct;
3612 
3613 		struct ice_flow_seg_xtrct *sctp_src =
3614 			&seg->fields[ICE_FLOW_FIELD_IDX_SCTP_SRC_PORT].xtrct;
3615 		struct ice_flow_seg_xtrct *sctp_dst =
3616 			&seg->fields[ICE_FLOW_FIELD_IDX_SCTP_DST_PORT].xtrct;
3617 
3618 		/* xor IPv4 */
3619 		if (ipv4_src->prot_id != 0 && ipv4_dst->prot_id != 0)
3620 			ice_rss_config_xor(hw, prof_id,
3621 					   ipv4_src->idx, ipv4_dst->idx, 2);
3622 
3623 		/* xor IPv6 */
3624 		if (ipv6_src->prot_id != 0 && ipv6_dst->prot_id != 0)
3625 			ice_rss_config_xor(hw, prof_id,
3626 					   ipv6_src->idx, ipv6_dst->idx, 8);
3627 
3628 		/* xor TCP */
3629 		if (tcp_src->prot_id != 0 && tcp_dst->prot_id != 0)
3630 			ice_rss_config_xor(hw, prof_id,
3631 					   tcp_src->idx, tcp_dst->idx, 1);
3632 
3633 		/* xor UDP */
3634 		if (udp_src->prot_id != 0 && udp_dst->prot_id != 0)
3635 			ice_rss_config_xor(hw, prof_id,
3636 					   udp_src->idx, udp_dst->idx, 1);
3637 
3638 		/* xor SCTP */
3639 		if (sctp_src->prot_id != 0 && sctp_dst->prot_id != 0)
3640 			ice_rss_config_xor(hw, prof_id,
3641 					   sctp_src->idx, sctp_dst->idx, 1);
3642 	}
3643 }
3644 
3645 /**
3646  * ice_add_rss_cfg_sync - add an RSS configuration
3647  * @hw: pointer to the hardware structure
3648  * @vsi_handle: software VSI handle
3649  * @cfg: configure parameters
3650  *
3651  * Assumption: lock has already been acquired for RSS list
3652  */
3653 static enum ice_status
3654 ice_add_rss_cfg_sync(struct ice_hw *hw, u16 vsi_handle,
3655 		     const struct ice_rss_hash_cfg *cfg)
3656 {
3657 	const enum ice_block blk = ICE_BLK_RSS;
3658 	struct ice_flow_prof *prof = NULL;
3659 	struct ice_flow_seg_info *segs;
3660 	enum ice_status status;
3661 	u8 segs_cnt;
3662 
3663 	segs_cnt = (cfg->hdr_type == ICE_RSS_OUTER_HEADERS) ?
3664 			ICE_FLOW_SEG_SINGLE : ICE_FLOW_SEG_MAX;
3665 
3666 	segs = (struct ice_flow_seg_info *)ice_calloc(hw, segs_cnt,
3667 						      sizeof(*segs));
3668 	if (!segs)
3669 		return ICE_ERR_NO_MEMORY;
3670 
3671 	/* Construct the packet segment info from the hashed fields */
3672 	status = ice_flow_set_rss_seg_info(segs, segs_cnt, cfg);
3673 	if (status)
3674 		goto exit;
3675 
3676 	/* Don't do RSS for GTPU Outer */
3677 	if (segs_cnt == ICE_FLOW_SEG_SINGLE &&
3678 	    segs[segs_cnt - 1].hdrs & ICE_FLOW_SEG_HDR_GTPU) {
3679 		status = ICE_SUCCESS;
3680 		goto exit;
3681 	}
3682 
3683 	/* Search for a flow profile that has matching headers, hash fields
3684 	 * and has the input VSI associated to it. If found, no further
3685 	 * operations required and exit.
3686 	 */
3687 	prof = ice_flow_find_prof_conds(hw, blk, ICE_FLOW_RX, segs, segs_cnt,
3688 					vsi_handle,
3689 					ICE_FLOW_FIND_PROF_CHK_FLDS |
3690 					ICE_FLOW_FIND_PROF_CHK_VSI);
3691 	if (prof) {
3692 		if (prof->cfg.symm == cfg->symm)
3693 			goto exit;
3694 		prof->cfg.symm = cfg->symm;
3695 		goto update_symm;
3696 	}
3697 
3698 	/* Check if a flow profile exists with the same protocol headers and
3699 	 * associated with the input VSI. If so disassociate the VSI from
3700 	 * this profile. The VSI will be added to a new profile created with
3701 	 * the protocol header and new hash field configuration.
3702 	 */
3703 	prof = ice_flow_find_prof_conds(hw, blk, ICE_FLOW_RX, segs, segs_cnt,
3704 					vsi_handle, ICE_FLOW_FIND_PROF_CHK_VSI);
3705 	if (prof) {
3706 		status = ice_flow_disassoc_prof(hw, blk, prof, vsi_handle);
3707 		if (!status)
3708 			ice_rem_rss_list(hw, vsi_handle, prof);
3709 		else
3710 			goto exit;
3711 
3712 		/* Remove profile if it has no VSIs associated */
3713 		if (!ice_is_any_bit_set(prof->vsis, ICE_MAX_VSI)) {
3714 			status = ice_flow_rem_prof(hw, blk, prof->id);
3715 			if (status)
3716 				goto exit;
3717 		}
3718 	}
3719 
3720 	/* Search for a profile that has same match fields only. If this
3721 	 * exists then associate the VSI to this profile.
3722 	 */
3723 	prof = ice_flow_find_prof_conds(hw, blk, ICE_FLOW_RX, segs, segs_cnt,
3724 					vsi_handle,
3725 					ICE_FLOW_FIND_PROF_CHK_FLDS);
3726 	if (prof) {
3727 		if (prof->cfg.symm == cfg->symm) {
3728 			status = ice_flow_assoc_prof(hw, blk, prof,
3729 						     vsi_handle);
3730 			if (!status)
3731 				status = ice_add_rss_list(hw, vsi_handle,
3732 							  prof);
3733 		} else {
3734 			/* if a profile exist but with different symmetric
3735 			 * requirement, just return error.
3736 			 */
3737 			status = ICE_ERR_NOT_SUPPORTED;
3738 		}
3739 		goto exit;
3740 	}
3741 
3742 	/* Create a new flow profile with generated profile and packet
3743 	 * segment information.
3744 	 */
3745 	status = ice_flow_add_prof(hw, blk, ICE_FLOW_RX,
3746 				   ICE_FLOW_GEN_PROFID(cfg->hash_flds,
3747 						       segs[segs_cnt - 1].hdrs,
3748 						       cfg->hdr_type),
3749 				   segs, segs_cnt, NULL, 0, &prof);
3750 	if (status)
3751 		goto exit;
3752 
3753 	status = ice_flow_assoc_prof(hw, blk, prof, vsi_handle);
3754 	/* If association to a new flow profile failed then this profile can
3755 	 * be removed.
3756 	 */
3757 	if (status) {
3758 		ice_flow_rem_prof(hw, blk, prof->id);
3759 		goto exit;
3760 	}
3761 
3762 	status = ice_add_rss_list(hw, vsi_handle, prof);
3763 
3764 	prof->cfg.symm = cfg->symm;
3765 update_symm:
3766 	ice_rss_update_symm(hw, prof);
3767 
3768 exit:
3769 	ice_free(hw, segs);
3770 	return status;
3771 }
3772 
3773 /**
3774  * ice_add_rss_cfg - add an RSS configuration with specified hashed fields
3775  * @hw: pointer to the hardware structure
3776  * @vsi_handle: software VSI handle
3777  * @cfg: configure parameters
3778  *
3779  * This function will generate a flow profile based on fields associated with
3780  * the input fields to hash on, the flow type and use the VSI number to add
3781  * a flow entry to the profile.
3782  */
3783 enum ice_status
3784 ice_add_rss_cfg(struct ice_hw *hw, u16 vsi_handle,
3785 		const struct ice_rss_hash_cfg *cfg)
3786 {
3787 	struct ice_rss_hash_cfg local_cfg;
3788 	enum ice_status status;
3789 
3790 	if (!ice_is_vsi_valid(hw, vsi_handle) ||
3791 	    !cfg || cfg->hdr_type > ICE_RSS_ANY_HEADERS ||
3792 	    cfg->hash_flds == ICE_HASH_INVALID)
3793 		return ICE_ERR_PARAM;
3794 
3795 	local_cfg = *cfg;
3796 	if (cfg->hdr_type < ICE_RSS_ANY_HEADERS) {
3797 		ice_acquire_lock(&hw->rss_locks);
3798 		status = ice_add_rss_cfg_sync(hw, vsi_handle, &local_cfg);
3799 		ice_release_lock(&hw->rss_locks);
3800 	} else {
3801 		ice_acquire_lock(&hw->rss_locks);
3802 		local_cfg.hdr_type = ICE_RSS_OUTER_HEADERS;
3803 		status = ice_add_rss_cfg_sync(hw, vsi_handle, &local_cfg);
3804 		if (!status) {
3805 			local_cfg.hdr_type = ICE_RSS_INNER_HEADERS;
3806 			status = ice_add_rss_cfg_sync(hw, vsi_handle,
3807 						      &local_cfg);
3808 		}
3809 		ice_release_lock(&hw->rss_locks);
3810 	}
3811 
3812 	return status;
3813 }
3814 
3815 /**
3816  * ice_rem_rss_cfg_sync - remove an existing RSS configuration
3817  * @hw: pointer to the hardware structure
3818  * @vsi_handle: software VSI handle
3819  * @cfg: configure parameters
3820  *
3821  * Assumption: lock has already been acquired for RSS list
3822  */
3823 static enum ice_status
3824 ice_rem_rss_cfg_sync(struct ice_hw *hw, u16 vsi_handle,
3825 		     const struct ice_rss_hash_cfg *cfg)
3826 {
3827 	const enum ice_block blk = ICE_BLK_RSS;
3828 	struct ice_flow_seg_info *segs;
3829 	struct ice_flow_prof *prof;
3830 	enum ice_status status;
3831 	u8 segs_cnt;
3832 
3833 	segs_cnt = (cfg->hdr_type == ICE_RSS_OUTER_HEADERS) ?
3834 			ICE_FLOW_SEG_SINGLE : ICE_FLOW_SEG_MAX;
3835 	segs = (struct ice_flow_seg_info *)ice_calloc(hw, segs_cnt,
3836 						      sizeof(*segs));
3837 	if (!segs)
3838 		return ICE_ERR_NO_MEMORY;
3839 
3840 	/* Construct the packet segment info from the hashed fields */
3841 	status = ice_flow_set_rss_seg_info(segs, segs_cnt, cfg);
3842 	if (status)
3843 		goto out;
3844 
3845 	/* Don't do RSS for GTPU Outer */
3846 	if (segs_cnt == ICE_FLOW_SEG_SINGLE &&
3847 	    segs[segs_cnt - 1].hdrs & ICE_FLOW_SEG_HDR_GTPU) {
3848 		status = ICE_SUCCESS;
3849 		goto out;
3850 	}
3851 
3852 	prof = ice_flow_find_prof_conds(hw, blk, ICE_FLOW_RX, segs, segs_cnt,
3853 					vsi_handle,
3854 					ICE_FLOW_FIND_PROF_CHK_FLDS);
3855 	if (!prof) {
3856 		status = ICE_ERR_DOES_NOT_EXIST;
3857 		goto out;
3858 	}
3859 
3860 	status = ice_flow_disassoc_prof(hw, blk, prof, vsi_handle);
3861 	if (status)
3862 		goto out;
3863 
3864 	/* Remove RSS configuration from VSI context before deleting
3865 	 * the flow profile.
3866 	 */
3867 	ice_rem_rss_list(hw, vsi_handle, prof);
3868 
3869 	if (!ice_is_any_bit_set(prof->vsis, ICE_MAX_VSI))
3870 		status = ice_flow_rem_prof(hw, blk, prof->id);
3871 
3872 out:
3873 	ice_free(hw, segs);
3874 	return status;
3875 }
3876 
3877 /**
3878  * ice_rem_rss_cfg - remove an existing RSS config with matching hashed fields
3879  * @hw: pointer to the hardware structure
3880  * @vsi_handle: software VSI handle
3881  * @cfg: configure parameters
3882  *
3883  * This function will lookup the flow profile based on the input
3884  * hash field bitmap, iterate through the profile entry list of
3885  * that profile and find entry associated with input VSI to be
3886  * removed. Calls are made to underlying flow apis which will in
3887  * turn build or update buffers for RSS XLT1 section.
3888  */
3889 enum ice_status
3890 ice_rem_rss_cfg(struct ice_hw *hw, u16 vsi_handle,
3891 		const struct ice_rss_hash_cfg *cfg)
3892 {
3893 	struct ice_rss_hash_cfg local_cfg;
3894 	enum ice_status status;
3895 
3896 	if (!ice_is_vsi_valid(hw, vsi_handle) ||
3897 	    !cfg || cfg->hdr_type > ICE_RSS_ANY_HEADERS ||
3898 	    cfg->hash_flds == ICE_HASH_INVALID)
3899 		return ICE_ERR_PARAM;
3900 
3901 	ice_acquire_lock(&hw->rss_locks);
3902 	local_cfg = *cfg;
3903 	if (cfg->hdr_type < ICE_RSS_ANY_HEADERS) {
3904 		status = ice_rem_rss_cfg_sync(hw, vsi_handle, &local_cfg);
3905 	} else {
3906 		local_cfg.hdr_type = ICE_RSS_OUTER_HEADERS;
3907 		status = ice_rem_rss_cfg_sync(hw, vsi_handle, &local_cfg);
3908 
3909 		if (!status) {
3910 			local_cfg.hdr_type = ICE_RSS_INNER_HEADERS;
3911 			status = ice_rem_rss_cfg_sync(hw, vsi_handle,
3912 						      &local_cfg);
3913 		}
3914 	}
3915 	ice_release_lock(&hw->rss_locks);
3916 
3917 	return status;
3918 }
3919 
3920 /**
3921  * ice_replay_rss_cfg - replay RSS configurations associated with VSI
3922  * @hw: pointer to the hardware structure
3923  * @vsi_handle: software VSI handle
3924  */
3925 enum ice_status ice_replay_rss_cfg(struct ice_hw *hw, u16 vsi_handle)
3926 {
3927 	enum ice_status status = ICE_SUCCESS;
3928 	struct ice_rss_cfg *r;
3929 
3930 	if (!ice_is_vsi_valid(hw, vsi_handle))
3931 		return ICE_ERR_PARAM;
3932 
3933 	ice_acquire_lock(&hw->rss_locks);
3934 	LIST_FOR_EACH_ENTRY(r, &hw->rss_list_head,
3935 			    ice_rss_cfg, l_entry) {
3936 		if (ice_is_bit_set(r->vsis, vsi_handle)) {
3937 			status = ice_add_rss_cfg_sync(hw, vsi_handle, &r->hash);
3938 			if (status)
3939 				break;
3940 		}
3941 	}
3942 	ice_release_lock(&hw->rss_locks);
3943 
3944 	return status;
3945 }
3946 
3947 /**
3948  * ice_get_rss_cfg - returns hashed fields for the given header types
3949  * @hw: pointer to the hardware structure
3950  * @vsi_handle: software VSI handle
3951  * @hdrs: protocol header type
3952  *
3953  * This function will return the match fields of the first instance of flow
3954  * profile having the given header types and containing input VSI
3955  */
3956 u64 ice_get_rss_cfg(struct ice_hw *hw, u16 vsi_handle, u32 hdrs)
3957 {
3958 	u64 rss_hash = ICE_HASH_INVALID;
3959 	struct ice_rss_cfg *r;
3960 
3961 	/* verify if the protocol header is non zero and VSI is valid */
3962 	if (hdrs == ICE_FLOW_SEG_HDR_NONE || !ice_is_vsi_valid(hw, vsi_handle))
3963 		return ICE_HASH_INVALID;
3964 
3965 	ice_acquire_lock(&hw->rss_locks);
3966 	LIST_FOR_EACH_ENTRY(r, &hw->rss_list_head,
3967 			    ice_rss_cfg, l_entry)
3968 		if (ice_is_bit_set(r->vsis, vsi_handle) &&
3969 		    r->hash.addl_hdrs == hdrs) {
3970 			rss_hash = r->hash.hash_flds;
3971 			break;
3972 		}
3973 	ice_release_lock(&hw->rss_locks);
3974 
3975 	return rss_hash;
3976 }
3977