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