xref: /dpdk/drivers/net/ice/base/ice_flow.c (revision d6cefc11)
1 /* SPDX-License-Identifier: BSD-3-Clause
2  * Copyright(c) 2001-2019
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_IP_DSCP		1
14 #define ICE_FLOW_FLD_SZ_IP_TTL		1
15 #define ICE_FLOW_FLD_SZ_IP_PROT		1
16 #define ICE_FLOW_FLD_SZ_PORT		2
17 #define ICE_FLOW_FLD_SZ_TCP_FLAGS	1
18 #define ICE_FLOW_FLD_SZ_ICMP_TYPE	1
19 #define ICE_FLOW_FLD_SZ_ICMP_CODE	1
20 #define ICE_FLOW_FLD_SZ_ARP_OPER	2
21 #define ICE_FLOW_FLD_SZ_GRE_KEYID	4
22 
23 /* Protocol header fields are extracted at the word boundaries as word-sized
24  * values. Specify the displacement value of some non-word-aligned fields needed
25  * to compute the offset of words containing the fields in the corresponding
26  * protocol headers. Displacement values are expressed in number of bits.
27  */
28 #define ICE_FLOW_FLD_IPV6_TTL_DSCP_DISP	(-4)
29 #define ICE_FLOW_FLD_IPV6_TTL_PROT_DISP	((-2) * 8)
30 #define ICE_FLOW_FLD_IPV6_TTL_TTL_DISP	((-1) * 8)
31 
32 /* Describe properties of a protocol header field */
33 struct ice_flow_field_info {
34 	enum ice_flow_seg_hdr hdr;
35 	s16 off;	/* Offset from start of a protocol header, in bits */
36 	u16 size;	/* Size of fields in bits */
37 };
38 
39 /* Table containing properties of supported protocol header fields */
40 static const
41 struct ice_flow_field_info ice_flds_info[ICE_FLOW_FIELD_IDX_MAX] = {
42 	/* Ether */
43 	/* ICE_FLOW_FIELD_IDX_ETH_DA */
44 	{ ICE_FLOW_SEG_HDR_ETH, 0, ETH_ALEN * 8 },
45 	/* ICE_FLOW_FIELD_IDX_ETH_SA */
46 	{ ICE_FLOW_SEG_HDR_ETH, ETH_ALEN * 8, ETH_ALEN * 8 },
47 	/* ICE_FLOW_FIELD_IDX_S_VLAN */
48 	{ ICE_FLOW_SEG_HDR_VLAN, 12 * 8, ICE_FLOW_FLD_SZ_VLAN * 8 },
49 	/* ICE_FLOW_FIELD_IDX_C_VLAN */
50 	{ ICE_FLOW_SEG_HDR_VLAN, 14 * 8, ICE_FLOW_FLD_SZ_VLAN * 8 },
51 	/* ICE_FLOW_FIELD_IDX_ETH_TYPE */
52 	{ ICE_FLOW_SEG_HDR_ETH, 12 * 8, ICE_FLOW_FLD_SZ_ETH_TYPE * 8 },
53 	/* IPv4 */
54 	/* ICE_FLOW_FIELD_IDX_IP_DSCP */
55 	{ ICE_FLOW_SEG_HDR_IPV4, 1 * 8, 1 * 8 },
56 	/* ICE_FLOW_FIELD_IDX_IP_TTL */
57 	{ ICE_FLOW_SEG_HDR_NONE, 8 * 8, 1 * 8 },
58 	/* ICE_FLOW_FIELD_IDX_IP_PROT */
59 	{ ICE_FLOW_SEG_HDR_NONE, 9 * 8, ICE_FLOW_FLD_SZ_IP_PROT * 8 },
60 	/* ICE_FLOW_FIELD_IDX_IPV4_SA */
61 	{ ICE_FLOW_SEG_HDR_IPV4, 12 * 8, ICE_FLOW_FLD_SZ_IPV4_ADDR * 8 },
62 	/* ICE_FLOW_FIELD_IDX_IPV4_DA */
63 	{ ICE_FLOW_SEG_HDR_IPV4, 16 * 8, ICE_FLOW_FLD_SZ_IPV4_ADDR * 8 },
64 	/* IPv6 */
65 	/* ICE_FLOW_FIELD_IDX_IPV6_SA */
66 	{ ICE_FLOW_SEG_HDR_IPV6, 8 * 8, ICE_FLOW_FLD_SZ_IPV6_ADDR * 8 },
67 	/* ICE_FLOW_FIELD_IDX_IPV6_DA */
68 	{ ICE_FLOW_SEG_HDR_IPV6, 24 * 8, ICE_FLOW_FLD_SZ_IPV6_ADDR * 8 },
69 	/* Transport */
70 	/* ICE_FLOW_FIELD_IDX_TCP_SRC_PORT */
71 	{ ICE_FLOW_SEG_HDR_TCP, 0 * 8, ICE_FLOW_FLD_SZ_PORT * 8 },
72 	/* ICE_FLOW_FIELD_IDX_TCP_DST_PORT */
73 	{ ICE_FLOW_SEG_HDR_TCP, 2 * 8, ICE_FLOW_FLD_SZ_PORT * 8 },
74 	/* ICE_FLOW_FIELD_IDX_UDP_SRC_PORT */
75 	{ ICE_FLOW_SEG_HDR_UDP, 0 * 8, ICE_FLOW_FLD_SZ_PORT * 8 },
76 	/* ICE_FLOW_FIELD_IDX_UDP_DST_PORT */
77 	{ ICE_FLOW_SEG_HDR_UDP, 2 * 8, ICE_FLOW_FLD_SZ_PORT * 8 },
78 	/* ICE_FLOW_FIELD_IDX_SCTP_SRC_PORT */
79 	{ ICE_FLOW_SEG_HDR_SCTP, 0 * 8, ICE_FLOW_FLD_SZ_PORT * 8 },
80 	/* ICE_FLOW_FIELD_IDX_SCTP_DST_PORT */
81 	{ ICE_FLOW_SEG_HDR_SCTP, 2 * 8, ICE_FLOW_FLD_SZ_PORT * 8 },
82 	/* ICE_FLOW_FIELD_IDX_TCP_FLAGS */
83 	{ ICE_FLOW_SEG_HDR_TCP, 13 * 8, ICE_FLOW_FLD_SZ_TCP_FLAGS * 8 },
84 	/* ARP */
85 	/* ICE_FLOW_FIELD_IDX_ARP_SIP */
86 	{ ICE_FLOW_SEG_HDR_ARP, 14 * 8, ICE_FLOW_FLD_SZ_IPV4_ADDR * 8 },
87 	/* ICE_FLOW_FIELD_IDX_ARP_DIP */
88 	{ ICE_FLOW_SEG_HDR_ARP, 24 * 8, ICE_FLOW_FLD_SZ_IPV4_ADDR * 8 },
89 	/* ICE_FLOW_FIELD_IDX_ARP_SHA */
90 	{ ICE_FLOW_SEG_HDR_ARP, 8 * 8, ETH_ALEN * 8 },
91 	/* ICE_FLOW_FIELD_IDX_ARP_DHA */
92 	{ ICE_FLOW_SEG_HDR_ARP, 18 * 8, ETH_ALEN * 8 },
93 	/* ICE_FLOW_FIELD_IDX_ARP_OP */
94 	{ ICE_FLOW_SEG_HDR_ARP, 6 * 8, ICE_FLOW_FLD_SZ_ARP_OPER * 8 },
95 	/* ICMP */
96 	/* ICE_FLOW_FIELD_IDX_ICMP_TYPE */
97 	{ ICE_FLOW_SEG_HDR_ICMP, 0 * 8, ICE_FLOW_FLD_SZ_ICMP_TYPE * 8 },
98 	/* ICE_FLOW_FIELD_IDX_ICMP_CODE */
99 	{ ICE_FLOW_SEG_HDR_ICMP, 1 * 8, ICE_FLOW_FLD_SZ_ICMP_CODE * 8 },
100 	/* GRE */
101 	/* ICE_FLOW_FIELD_IDX_GRE_KEYID */
102 	{ ICE_FLOW_SEG_HDR_GRE, 12 * 8, ICE_FLOW_FLD_SZ_GRE_KEYID * 8 },
103 };
104 
105 /* Bitmaps indicating relevant packet types for a particular protocol header
106  *
107  * Packet types for packets with an Outer/First/Single MAC header
108  */
109 static const u32 ice_ptypes_mac_ofos[] = {
110 	0xFDC00CC6, 0xBFBF7F7E, 0xF7EFDFDF, 0xFEFDFDFB,
111 	0x03BF7F7E, 0x00000000, 0x00000000, 0x00000000,
112 	0x000B0F0F, 0x00000000, 0x00000000, 0x00000000,
113 	0x00000000, 0x00000000, 0x00000000, 0x00000000,
114 	0x00000000, 0x00000000, 0x00000000, 0x00000000,
115 	0x00000000, 0x00000000, 0x00000000, 0x00000000,
116 	0x00000000, 0x00000000, 0x00000000, 0x00000000,
117 	0x00000000, 0x00000000, 0x00000000, 0x00000000,
118 };
119 
120 /* Packet types for packets with an Innermost/Last MAC VLAN header */
121 static const u32 ice_ptypes_macvlan_il[] = {
122 	0x00000000, 0xBC000000, 0x000001DF, 0xF0000000,
123 	0x0000077E, 0x00000000, 0x00000000, 0x00000000,
124 	0x00000000, 0x00000000, 0x00000000, 0x00000000,
125 	0x00000000, 0x00000000, 0x00000000, 0x00000000,
126 	0x00000000, 0x00000000, 0x00000000, 0x00000000,
127 	0x00000000, 0x00000000, 0x00000000, 0x00000000,
128 	0x00000000, 0x00000000, 0x00000000, 0x00000000,
129 	0x00000000, 0x00000000, 0x00000000, 0x00000000,
130 };
131 
132 /* Packet types for packets with an Outer/First/Single IPv4 header */
133 static const u32 ice_ptypes_ipv4_ofos[] = {
134 	0xFDC00000, 0xBFBF7F7E, 0x00EFDFDF, 0x00000000,
135 	0x00000000, 0x00000000, 0x00000000, 0x00000000,
136 	0x0003000F, 0x00000000, 0x00000000, 0x00000000,
137 	0x00000000, 0x00000000, 0x00000000, 0x00000000,
138 	0x00000000, 0x00000000, 0x00000000, 0x00000000,
139 	0x00000000, 0x00000000, 0x00000000, 0x00000000,
140 	0x00000000, 0x00000000, 0x00000000, 0x00000000,
141 	0x00000000, 0x00000000, 0x00000000, 0x00000000,
142 };
143 
144 /* Packet types for packets with an Innermost/Last IPv4 header */
145 static const u32 ice_ptypes_ipv4_il[] = {
146 	0xE0000000, 0xB807700E, 0x8001DC03, 0xE01DC03B,
147 	0x0007700E, 0x00000000, 0x00000000, 0x00000000,
148 	0x00000000, 0x00000000, 0x00000000, 0x00000000,
149 	0x00000000, 0x00000000, 0x00000000, 0x00000000,
150 	0x00000000, 0x00000000, 0x00000000, 0x00000000,
151 	0x00000000, 0x00000000, 0x00000000, 0x00000000,
152 	0x00000000, 0x00000000, 0x00000000, 0x00000000,
153 	0x00000000, 0x00000000, 0x00000000, 0x00000000,
154 };
155 
156 /* Packet types for packets with an Outer/First/Single IPv6 header */
157 static const u32 ice_ptypes_ipv6_ofos[] = {
158 	0x00000000, 0x00000000, 0xF7000000, 0xFEFDFDFB,
159 	0x03BF7F7E, 0x00000000, 0x00000000, 0x00000000,
160 	0x00080F00, 0x00000000, 0x00000000, 0x00000000,
161 	0x00000000, 0x00000000, 0x00000000, 0x00000000,
162 	0x00000000, 0x00000000, 0x00000000, 0x00000000,
163 	0x00000000, 0x00000000, 0x00000000, 0x00000000,
164 	0x00000000, 0x00000000, 0x00000000, 0x00000000,
165 	0x00000000, 0x00000000, 0x00000000, 0x00000000,
166 };
167 
168 /* Packet types for packets with an Innermost/Last IPv6 header */
169 static const u32 ice_ptypes_ipv6_il[] = {
170 	0x00000000, 0x03B80770, 0x00EE01DC, 0x0EE00000,
171 	0x03B80770, 0x00000000, 0x00000000, 0x00000000,
172 	0x00000000, 0x00000000, 0x00000000, 0x00000000,
173 	0x00000000, 0x00000000, 0x00000000, 0x00000000,
174 	0x00000000, 0x00000000, 0x00000000, 0x00000000,
175 	0x00000000, 0x00000000, 0x00000000, 0x00000000,
176 	0x00000000, 0x00000000, 0x00000000, 0x00000000,
177 	0x00000000, 0x00000000, 0x00000000, 0x00000000,
178 };
179 
180 /* Packet types for packets with an Outermost/First ARP header */
181 static const u32 ice_ptypes_arp_of[] = {
182 	0x00000800, 0x00000000, 0x00000000, 0x00000000,
183 	0x00000000, 0x00000000, 0x00000000, 0x00000000,
184 	0x00000000, 0x00000000, 0x00000000, 0x00000000,
185 	0x00000000, 0x00000000, 0x00000000, 0x00000000,
186 	0x00000000, 0x00000000, 0x00000000, 0x00000000,
187 	0x00000000, 0x00000000, 0x00000000, 0x00000000,
188 	0x00000000, 0x00000000, 0x00000000, 0x00000000,
189 	0x00000000, 0x00000000, 0x00000000, 0x00000000,
190 };
191 
192 /* Packet types for packets with an Outermost/First UDP header */
193 static const u32 ice_ptypes_udp_of[] = {
194 	0x81000000, 0x00000000, 0x04000000, 0x00000000,
195 	0x00000000, 0x00000000, 0x00000000, 0x00000000,
196 	0x00000000, 0x00000000, 0x00000000, 0x00000000,
197 	0x00000000, 0x00000000, 0x00000000, 0x00000000,
198 	0x00000000, 0x00000000, 0x00000000, 0x00000000,
199 	0x00000000, 0x00000000, 0x00000000, 0x00000000,
200 	0x00000000, 0x00000000, 0x00000000, 0x00000000,
201 	0x00000000, 0x00000000, 0x00000000, 0x00000000,
202 };
203 
204 /* Packet types for packets with an Innermost/Last UDP header */
205 static const u32 ice_ptypes_udp_il[] = {
206 	0x80000000, 0x20204040, 0x00081010, 0x80810102,
207 	0x00204040, 0x00000000, 0x00000000, 0x00000000,
208 	0x00000000, 0x00000000, 0x00000000, 0x00000000,
209 	0x00000000, 0x00000000, 0x00000000, 0x00000000,
210 	0x00000000, 0x00000000, 0x00000000, 0x00000000,
211 	0x00000000, 0x00000000, 0x00000000, 0x00000000,
212 	0x00000000, 0x00000000, 0x00000000, 0x00000000,
213 	0x00000000, 0x00000000, 0x00000000, 0x00000000,
214 };
215 
216 /* Packet types for packets with an Innermost/Last TCP header */
217 static const u32 ice_ptypes_tcp_il[] = {
218 	0x04000000, 0x80810102, 0x10204040, 0x42040408,
219 	0x00810002, 0x00000000, 0x00000000, 0x00000000,
220 	0x00000000, 0x00000000, 0x00000000, 0x00000000,
221 	0x00000000, 0x00000000, 0x00000000, 0x00000000,
222 	0x00000000, 0x00000000, 0x00000000, 0x00000000,
223 	0x00000000, 0x00000000, 0x00000000, 0x00000000,
224 	0x00000000, 0x00000000, 0x00000000, 0x00000000,
225 	0x00000000, 0x00000000, 0x00000000, 0x00000000,
226 };
227 
228 /* Packet types for packets with an Innermost/Last SCTP header */
229 static const u32 ice_ptypes_sctp_il[] = {
230 	0x08000000, 0x01020204, 0x20408081, 0x04080810,
231 	0x01020204, 0x00000000, 0x00000000, 0x00000000,
232 	0x00000000, 0x00000000, 0x00000000, 0x00000000,
233 	0x00000000, 0x00000000, 0x00000000, 0x00000000,
234 	0x00000000, 0x00000000, 0x00000000, 0x00000000,
235 	0x00000000, 0x00000000, 0x00000000, 0x00000000,
236 	0x00000000, 0x00000000, 0x00000000, 0x00000000,
237 	0x00000000, 0x00000000, 0x00000000, 0x00000000,
238 };
239 
240 /* Packet types for packets with an Outermost/First ICMP header */
241 static const u32 ice_ptypes_icmp_of[] = {
242 	0x10000000, 0x00000000, 0x00000000, 0x00000000,
243 	0x00000000, 0x00000000, 0x00000000, 0x00000000,
244 	0x00000000, 0x00000000, 0x00000000, 0x00000000,
245 	0x00000000, 0x00000000, 0x00000000, 0x00000000,
246 	0x00000000, 0x00000000, 0x00000000, 0x00000000,
247 	0x00000000, 0x00000000, 0x00000000, 0x00000000,
248 	0x00000000, 0x00000000, 0x00000000, 0x00000000,
249 	0x00000000, 0x00000000, 0x00000000, 0x00000000,
250 };
251 
252 /* Packet types for packets with an Innermost/Last ICMP header */
253 static const u32 ice_ptypes_icmp_il[] = {
254 	0x00000000, 0x02040408, 0x40810102, 0x08101020,
255 	0x02040408, 0x00000000, 0x00000000, 0x00000000,
256 	0x00000000, 0x00000000, 0x00000000, 0x00000000,
257 	0x00000000, 0x00000000, 0x00000000, 0x00000000,
258 	0x00000000, 0x00000000, 0x00000000, 0x00000000,
259 	0x00000000, 0x00000000, 0x00000000, 0x00000000,
260 	0x00000000, 0x00000000, 0x00000000, 0x00000000,
261 	0x00000000, 0x00000000, 0x00000000, 0x00000000,
262 };
263 
264 /* Packet types for packets with an Outermost/First GRE header */
265 static const u32 ice_ptypes_gre_of[] = {
266 	0x00000000, 0xBFBF7800, 0x00EFDFDF, 0xFEFDE000,
267 	0x03BF7F7E, 0x00000000, 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 	0x00000000, 0x00000000, 0x00000000, 0x00000000,
274 };
275 
276 /* Packet types for packets with an Innermost/Last MAC header */
277 static const u32 ice_ptypes_mac_il[] = {
278 	0x00000000, 0x00000000, 0x00EFDE00, 0x00000000,
279 	0x03BF7800, 0x00000000, 0x00000000, 0x00000000,
280 	0x00000000, 0x00000000, 0x00000000, 0x00000000,
281 	0x00000000, 0x00000000, 0x00000000, 0x00000000,
282 	0x00000000, 0x00000000, 0x00000000, 0x00000000,
283 	0x00000000, 0x00000000, 0x00000000, 0x00000000,
284 	0x00000000, 0x00000000, 0x00000000, 0x00000000,
285 	0x00000000, 0x00000000, 0x00000000, 0x00000000,
286 };
287 
288 /* Manage parameters and info. used during the creation of a flow profile */
289 struct ice_flow_prof_params {
290 	enum ice_block blk;
291 	struct ice_flow_prof *prof;
292 
293 	u16 entry_length; /* # of bytes formatted entry will require */
294 	u8 es_cnt;
295 	/* For ACL, the es[0] will have the data of ICE_RX_MDID_PKT_FLAGS_15_0
296 	 * This will give us the direction flags.
297 	 */
298 	struct ice_fv_word es[ICE_MAX_FV_WORDS];
299 
300 	ice_declare_bitmap(ptypes, ICE_FLOW_PTYPE_MAX);
301 };
302 
303 /**
304  * ice_is_pow2 - check if integer value is a power of 2
305  * @val: unsigned integer to be validated
306  */
307 static bool ice_is_pow2(u64 val)
308 {
309 	return (val && !(val & (val - 1)));
310 }
311 
312 #define ICE_FLOW_SEG_HDRS_L2_MASK	\
313 	(ICE_FLOW_SEG_HDR_ETH | ICE_FLOW_SEG_HDR_VLAN)
314 #define ICE_FLOW_SEG_HDRS_L3_MASK	\
315 	(ICE_FLOW_SEG_HDR_IPV4 | ICE_FLOW_SEG_HDR_IPV6 | ICE_FLOW_SEG_HDR_ARP)
316 #define ICE_FLOW_SEG_HDRS_L4_MASK	\
317 	(ICE_FLOW_SEG_HDR_ICMP | ICE_FLOW_SEG_HDR_TCP | ICE_FLOW_SEG_HDR_UDP | \
318 	 ICE_FLOW_SEG_HDR_SCTP)
319 
320 /**
321  * ice_flow_val_hdrs - validates packet segments for valid protocol headers
322  * @segs: array of one or more packet segments that describe the flow
323  * @segs_cnt: number of packet segments provided
324  */
325 static enum ice_status
326 ice_flow_val_hdrs(struct ice_flow_seg_info *segs, u8 segs_cnt)
327 {
328 	const u32 masks = (ICE_FLOW_SEG_HDRS_L2_MASK |
329 			   ICE_FLOW_SEG_HDRS_L3_MASK |
330 			   ICE_FLOW_SEG_HDRS_L4_MASK);
331 	u8 i;
332 
333 	for (i = 0; i < segs_cnt; i++) {
334 		/* No header specified */
335 		if (!(segs[i].hdrs & masks) || (segs[i].hdrs & ~masks))
336 			return ICE_ERR_PARAM;
337 
338 		/* Multiple L3 headers */
339 		if (segs[i].hdrs & ICE_FLOW_SEG_HDRS_L3_MASK &&
340 		    !ice_is_pow2(segs[i].hdrs & ICE_FLOW_SEG_HDRS_L3_MASK))
341 			return ICE_ERR_PARAM;
342 
343 		/* Multiple L4 headers */
344 		if (segs[i].hdrs & ICE_FLOW_SEG_HDRS_L4_MASK &&
345 		    !ice_is_pow2(segs[i].hdrs & ICE_FLOW_SEG_HDRS_L4_MASK))
346 			return ICE_ERR_PARAM;
347 	}
348 
349 	return ICE_SUCCESS;
350 }
351 
352 /* Sizes of fixed known protocol headers without header options */
353 #define ICE_FLOW_PROT_HDR_SZ_MAC	14
354 #define ICE_FLOW_PROT_HDR_SZ_MAC_VLAN	(ICE_FLOW_PROT_HDR_SZ_MAC + 2)
355 #define ICE_FLOW_PROT_HDR_SZ_IPV4	20
356 #define ICE_FLOW_PROT_HDR_SZ_IPV6	40
357 #define ICE_FLOW_PROT_HDR_SZ_ARP	28
358 #define ICE_FLOW_PROT_HDR_SZ_ICMP	8
359 #define ICE_FLOW_PROT_HDR_SZ_TCP	20
360 #define ICE_FLOW_PROT_HDR_SZ_UDP	8
361 #define ICE_FLOW_PROT_HDR_SZ_SCTP	12
362 
363 /**
364  * ice_flow_calc_seg_sz - calculates size of a packet segment based on headers
365  * @params: information about the flow to be processed
366  * @seg: index of packet segment whose header size is to be determined
367  */
368 static u16 ice_flow_calc_seg_sz(struct ice_flow_prof_params *params, u8 seg)
369 {
370 	u16 sz;
371 
372 	/* L2 headers */
373 	sz = (params->prof->segs[seg].hdrs & ICE_FLOW_SEG_HDR_VLAN) ?
374 		ICE_FLOW_PROT_HDR_SZ_MAC_VLAN : ICE_FLOW_PROT_HDR_SZ_MAC;
375 
376 	/* L3 headers */
377 	if (params->prof->segs[seg].hdrs & ICE_FLOW_SEG_HDR_IPV4)
378 		sz += ICE_FLOW_PROT_HDR_SZ_IPV4;
379 	else if (params->prof->segs[seg].hdrs & ICE_FLOW_SEG_HDR_IPV6)
380 		sz += ICE_FLOW_PROT_HDR_SZ_IPV6;
381 	else if (params->prof->segs[seg].hdrs & ICE_FLOW_SEG_HDR_ARP)
382 		sz += ICE_FLOW_PROT_HDR_SZ_ARP;
383 	else if (params->prof->segs[seg].hdrs & ICE_FLOW_SEG_HDRS_L4_MASK)
384 		/* A L3 header is required if L4 is specified */
385 		return 0;
386 
387 	/* L4 headers */
388 	if (params->prof->segs[seg].hdrs & ICE_FLOW_SEG_HDR_ICMP)
389 		sz += ICE_FLOW_PROT_HDR_SZ_ICMP;
390 	else if (params->prof->segs[seg].hdrs & ICE_FLOW_SEG_HDR_TCP)
391 		sz += ICE_FLOW_PROT_HDR_SZ_TCP;
392 	else if (params->prof->segs[seg].hdrs & ICE_FLOW_SEG_HDR_UDP)
393 		sz += ICE_FLOW_PROT_HDR_SZ_UDP;
394 	else if (params->prof->segs[seg].hdrs & ICE_FLOW_SEG_HDR_SCTP)
395 		sz += ICE_FLOW_PROT_HDR_SZ_SCTP;
396 
397 	return sz;
398 }
399 
400 /**
401  * ice_flow_proc_seg_hdrs - process protocol headers present in pkt segments
402  * @params: information about the flow to be processed
403  *
404  * This function identifies the packet types associated with the protocol
405  * headers being present in packet segments of the specified flow profile.
406  */
407 static enum ice_status
408 ice_flow_proc_seg_hdrs(struct ice_flow_prof_params *params)
409 {
410 	struct ice_flow_prof *prof;
411 	u8 i;
412 
413 	ice_memset(params->ptypes, 0xff, sizeof(params->ptypes),
414 		   ICE_NONDMA_MEM);
415 
416 	prof = params->prof;
417 
418 	for (i = 0; i < params->prof->segs_cnt; i++) {
419 		const ice_bitmap_t *src;
420 		u32 hdrs;
421 
422 		if (i > 0 && (i + 1) < prof->segs_cnt)
423 			continue;
424 
425 		hdrs = prof->segs[i].hdrs;
426 
427 		if (hdrs & ICE_FLOW_SEG_HDR_ETH) {
428 			src = !i ? (const ice_bitmap_t *)ice_ptypes_mac_ofos :
429 				(const ice_bitmap_t *)ice_ptypes_mac_il;
430 			ice_and_bitmap(params->ptypes, params->ptypes, src,
431 				       ICE_FLOW_PTYPE_MAX);
432 			hdrs &= ~ICE_FLOW_SEG_HDR_ETH;
433 		}
434 
435 		if (i && hdrs & ICE_FLOW_SEG_HDR_VLAN) {
436 			src = (const ice_bitmap_t *)ice_ptypes_macvlan_il;
437 			ice_and_bitmap(params->ptypes, params->ptypes, src,
438 				       ICE_FLOW_PTYPE_MAX);
439 			hdrs &= ~ICE_FLOW_SEG_HDR_VLAN;
440 		}
441 
442 		if (!i && hdrs & ICE_FLOW_SEG_HDR_ARP) {
443 			ice_and_bitmap(params->ptypes, params->ptypes,
444 				       (const ice_bitmap_t *)ice_ptypes_arp_of,
445 				       ICE_FLOW_PTYPE_MAX);
446 			hdrs &= ~ICE_FLOW_SEG_HDR_ARP;
447 		}
448 
449 		if (hdrs & ICE_FLOW_SEG_HDR_IPV4) {
450 			src = !i ? (const ice_bitmap_t *)ice_ptypes_ipv4_ofos :
451 				(const ice_bitmap_t *)ice_ptypes_ipv4_il;
452 			ice_and_bitmap(params->ptypes, params->ptypes, src,
453 				       ICE_FLOW_PTYPE_MAX);
454 			hdrs &= ~ICE_FLOW_SEG_HDR_IPV4;
455 		} else if (hdrs & ICE_FLOW_SEG_HDR_IPV6) {
456 			src = !i ? (const ice_bitmap_t *)ice_ptypes_ipv6_ofos :
457 				(const ice_bitmap_t *)ice_ptypes_ipv6_il;
458 			ice_and_bitmap(params->ptypes, params->ptypes, src,
459 				       ICE_FLOW_PTYPE_MAX);
460 			hdrs &= ~ICE_FLOW_SEG_HDR_IPV6;
461 		}
462 
463 		if (hdrs & ICE_FLOW_SEG_HDR_ICMP) {
464 			src = !i ? (const ice_bitmap_t *)ice_ptypes_icmp_of :
465 				(const ice_bitmap_t *)ice_ptypes_icmp_il;
466 			ice_and_bitmap(params->ptypes, params->ptypes, src,
467 				       ICE_FLOW_PTYPE_MAX);
468 			hdrs &= ~ICE_FLOW_SEG_HDR_ICMP;
469 		} else if (hdrs & ICE_FLOW_SEG_HDR_UDP) {
470 			src = !i ? (const ice_bitmap_t *)ice_ptypes_udp_of :
471 				(const ice_bitmap_t *)ice_ptypes_udp_il;
472 			ice_and_bitmap(params->ptypes, params->ptypes, src,
473 				       ICE_FLOW_PTYPE_MAX);
474 			hdrs &= ~ICE_FLOW_SEG_HDR_UDP;
475 		} else if (hdrs & ICE_FLOW_SEG_HDR_TCP) {
476 			ice_and_bitmap(params->ptypes, params->ptypes,
477 				       (const ice_bitmap_t *)ice_ptypes_tcp_il,
478 				       ICE_FLOW_PTYPE_MAX);
479 			hdrs &= ~ICE_FLOW_SEG_HDR_TCP;
480 		} else if (hdrs & ICE_FLOW_SEG_HDR_SCTP) {
481 			src = (const ice_bitmap_t *)ice_ptypes_sctp_il;
482 			ice_and_bitmap(params->ptypes, params->ptypes, src,
483 				       ICE_FLOW_PTYPE_MAX);
484 			hdrs &= ~ICE_FLOW_SEG_HDR_SCTP;
485 		} else if (hdrs & ICE_FLOW_SEG_HDR_GRE) {
486 			if (!i) {
487 				src = (const ice_bitmap_t *)ice_ptypes_gre_of;
488 				ice_and_bitmap(params->ptypes, params->ptypes,
489 					       src, ICE_FLOW_PTYPE_MAX);
490 			}
491 			hdrs &= ~ICE_FLOW_SEG_HDR_GRE;
492 		}
493 	}
494 
495 	return ICE_SUCCESS;
496 }
497 
498 /**
499  * ice_flow_xtract_fld - Create an extraction sequence entry for the given field
500  * @hw: pointer to the HW struct
501  * @params: information about the flow to be processed
502  * @seg: packet segment index of the field to be extracted
503  * @fld: ID of field to be extracted
504  *
505  * This function determines the protocol ID, offset, and size of the given
506  * field. It then allocates one or more extraction sequence entries for the
507  * given field, and fill the entries with protocol ID and offset information.
508  */
509 static enum ice_status
510 ice_flow_xtract_fld(struct ice_hw *hw, struct ice_flow_prof_params *params,
511 		    u8 seg, enum ice_flow_field fld)
512 {
513 	enum ice_flow_field sib = ICE_FLOW_FIELD_IDX_MAX;
514 	enum ice_prot_id prot_id = ICE_PROT_ID_INVAL;
515 	u8 fv_words = hw->blk[params->blk].es.fvw;
516 	struct ice_flow_fld_info *flds;
517 	u16 cnt, ese_bits, i;
518 	s16 adj = 0;
519 	u16 off;
520 
521 	flds = params->prof->segs[seg].fields;
522 
523 	switch (fld) {
524 	case ICE_FLOW_FIELD_IDX_ETH_DA:
525 	case ICE_FLOW_FIELD_IDX_ETH_SA:
526 	case ICE_FLOW_FIELD_IDX_S_VLAN:
527 	case ICE_FLOW_FIELD_IDX_C_VLAN:
528 		prot_id = seg == 0 ? ICE_PROT_MAC_OF_OR_S : ICE_PROT_MAC_IL;
529 		break;
530 	case ICE_FLOW_FIELD_IDX_ETH_TYPE:
531 		prot_id = seg == 0 ? ICE_PROT_ETYPE_OL : ICE_PROT_ETYPE_IL;
532 		break;
533 	case ICE_FLOW_FIELD_IDX_IP_DSCP:
534 		if (params->prof->segs[seg].hdrs & ICE_FLOW_SEG_HDR_IPV6)
535 			adj = ICE_FLOW_FLD_IPV6_TTL_DSCP_DISP;
536 		/* Fall through */
537 	case ICE_FLOW_FIELD_IDX_IP_TTL:
538 	case ICE_FLOW_FIELD_IDX_IP_PROT:
539 		/* Some fields are located at different offsets in IPv4 and
540 		 * IPv6
541 		 */
542 		if (params->prof->segs[seg].hdrs & ICE_FLOW_SEG_HDR_IPV4) {
543 			prot_id = seg == 0 ? ICE_PROT_IPV4_OF_OR_S :
544 				ICE_PROT_IPV4_IL;
545 			/* TTL and PROT share the same extraction seq. entry.
546 			 * Each is considered a sibling to the other in term
547 			 * sharing the same extraction sequence entry.
548 			 */
549 			if (fld == ICE_FLOW_FIELD_IDX_IP_TTL)
550 				sib = ICE_FLOW_FIELD_IDX_IP_PROT;
551 			else if (fld == ICE_FLOW_FIELD_IDX_IP_PROT)
552 				sib = ICE_FLOW_FIELD_IDX_IP_TTL;
553 		} else if (params->prof->segs[seg].hdrs &
554 			   ICE_FLOW_SEG_HDR_IPV6) {
555 			prot_id = seg == 0 ? ICE_PROT_IPV6_OF_OR_S :
556 				ICE_PROT_IPV6_IL;
557 			if (fld == ICE_FLOW_FIELD_IDX_IP_TTL)
558 				adj = ICE_FLOW_FLD_IPV6_TTL_TTL_DISP;
559 			else if (fld == ICE_FLOW_FIELD_IDX_IP_PROT)
560 				adj = ICE_FLOW_FLD_IPV6_TTL_PROT_DISP;
561 		}
562 		break;
563 	case ICE_FLOW_FIELD_IDX_IPV4_SA:
564 	case ICE_FLOW_FIELD_IDX_IPV4_DA:
565 		prot_id = seg == 0 ? ICE_PROT_IPV4_OF_OR_S : ICE_PROT_IPV4_IL;
566 		break;
567 	case ICE_FLOW_FIELD_IDX_IPV6_SA:
568 	case ICE_FLOW_FIELD_IDX_IPV6_DA:
569 		prot_id = seg == 0 ? ICE_PROT_IPV6_OF_OR_S : ICE_PROT_IPV6_IL;
570 		break;
571 	case ICE_FLOW_FIELD_IDX_TCP_SRC_PORT:
572 	case ICE_FLOW_FIELD_IDX_TCP_DST_PORT:
573 	case ICE_FLOW_FIELD_IDX_TCP_FLAGS:
574 		prot_id = ICE_PROT_TCP_IL;
575 		break;
576 	case ICE_FLOW_FIELD_IDX_UDP_SRC_PORT:
577 	case ICE_FLOW_FIELD_IDX_UDP_DST_PORT:
578 		prot_id = seg == 0 ? ICE_PROT_UDP_IL_OR_S : ICE_PROT_UDP_OF;
579 		break;
580 	case ICE_FLOW_FIELD_IDX_SCTP_SRC_PORT:
581 	case ICE_FLOW_FIELD_IDX_SCTP_DST_PORT:
582 		prot_id = ICE_PROT_SCTP_IL;
583 		break;
584 	case ICE_FLOW_FIELD_IDX_ARP_SIP:
585 	case ICE_FLOW_FIELD_IDX_ARP_DIP:
586 	case ICE_FLOW_FIELD_IDX_ARP_SHA:
587 	case ICE_FLOW_FIELD_IDX_ARP_DHA:
588 	case ICE_FLOW_FIELD_IDX_ARP_OP:
589 		prot_id = ICE_PROT_ARP_OF;
590 		break;
591 	case ICE_FLOW_FIELD_IDX_ICMP_TYPE:
592 	case ICE_FLOW_FIELD_IDX_ICMP_CODE:
593 		/* ICMP type and code share the same extraction seq. entry */
594 		prot_id = (params->prof->segs[seg].hdrs &
595 			   ICE_FLOW_SEG_HDR_IPV4) ?
596 			ICE_PROT_ICMP_IL : ICE_PROT_ICMPV6_IL;
597 		sib = fld == ICE_FLOW_FIELD_IDX_ICMP_TYPE ?
598 			ICE_FLOW_FIELD_IDX_ICMP_CODE :
599 			ICE_FLOW_FIELD_IDX_ICMP_TYPE;
600 		break;
601 	case ICE_FLOW_FIELD_IDX_GRE_KEYID:
602 		prot_id = ICE_PROT_GRE_OF;
603 		break;
604 	default:
605 		return ICE_ERR_NOT_IMPL;
606 	}
607 
608 	/* Each extraction sequence entry is a word in size, and extracts a
609 	 * word-aligned offset from a protocol header.
610 	 */
611 	ese_bits = ICE_FLOW_FV_EXTRACT_SZ * 8;
612 
613 	flds[fld].xtrct.prot_id = prot_id;
614 	flds[fld].xtrct.off = (ice_flds_info[fld].off / ese_bits) *
615 		ICE_FLOW_FV_EXTRACT_SZ;
616 	flds[fld].xtrct.disp = (u8)((ice_flds_info[fld].off + adj) % ese_bits);
617 	flds[fld].xtrct.idx = params->es_cnt;
618 
619 	/* Adjust the next field-entry index after accommodating the number of
620 	 * entries this field consumes
621 	 */
622 	cnt = DIVIDE_AND_ROUND_UP(flds[fld].xtrct.disp +
623 				  ice_flds_info[fld].size, ese_bits);
624 
625 	/* Fill in the extraction sequence entries needed for this field */
626 	off = flds[fld].xtrct.off;
627 	for (i = 0; i < cnt; i++) {
628 		/* Only consume an extraction sequence entry if there is no
629 		 * sibling field associated with this field or the sibling entry
630 		 * already extracts the word shared with this field.
631 		 */
632 		if (sib == ICE_FLOW_FIELD_IDX_MAX ||
633 		    flds[sib].xtrct.prot_id == ICE_PROT_ID_INVAL ||
634 		    flds[sib].xtrct.off != off) {
635 			u8 idx;
636 
637 			/* Make sure the number of extraction sequence required
638 			 * does not exceed the block's capability
639 			 */
640 			if (params->es_cnt >= fv_words)
641 				return ICE_ERR_MAX_LIMIT;
642 
643 			/* some blocks require a reversed field vector layout */
644 			if (hw->blk[params->blk].es.reverse)
645 				idx = fv_words - params->es_cnt - 1;
646 			else
647 				idx = params->es_cnt;
648 
649 			params->es[idx].prot_id = prot_id;
650 			params->es[idx].off = off;
651 			params->es_cnt++;
652 		}
653 
654 		off += ICE_FLOW_FV_EXTRACT_SZ;
655 	}
656 
657 	return ICE_SUCCESS;
658 }
659 
660 /**
661  * ice_flow_xtract_raws - Create extract sequence entries for raw bytes
662  * @hw: pointer to the HW struct
663  * @params: information about the flow to be processed
664  * @seg: index of packet segment whose raw fields are to be be extracted
665  */
666 static enum ice_status
667 ice_flow_xtract_raws(struct ice_hw *hw, struct ice_flow_prof_params *params,
668 		     u8 seg)
669 {
670 	u16 hdrs_sz;
671 	u8 i;
672 
673 	if (!params->prof->segs[seg].raws_cnt)
674 		return ICE_SUCCESS;
675 
676 	if (params->prof->segs[seg].raws_cnt >
677 	    ARRAY_SIZE(params->prof->segs[seg].raws))
678 		return ICE_ERR_MAX_LIMIT;
679 
680 	/* Offsets within the segment headers are not supported */
681 	hdrs_sz = ice_flow_calc_seg_sz(params, seg);
682 	if (!hdrs_sz)
683 		return ICE_ERR_PARAM;
684 
685 	for (i = 0; i < params->prof->segs[seg].raws_cnt; i++) {
686 		struct ice_flow_seg_fld_raw *raw;
687 		u16 off, cnt, j;
688 
689 		raw = &params->prof->segs[seg].raws[i];
690 
691 		/* Only support matching raw fields in the payload */
692 		if (raw->off < hdrs_sz)
693 			return ICE_ERR_PARAM;
694 
695 		/* Convert the segment-relative offset into payload-relative
696 		 * offset.
697 		 */
698 		off = raw->off - hdrs_sz;
699 
700 		/* Storing extraction information */
701 		raw->info.xtrct.prot_id = ICE_PROT_PAY;
702 		raw->info.xtrct.off = (off / ICE_FLOW_FV_EXTRACT_SZ) *
703 			ICE_FLOW_FV_EXTRACT_SZ;
704 		raw->info.xtrct.disp = (off % ICE_FLOW_FV_EXTRACT_SZ) * 8;
705 		raw->info.xtrct.idx = params->es_cnt;
706 
707 		/* Determine the number of field vector entries this raw field
708 		 * consumes.
709 		 */
710 		cnt = DIVIDE_AND_ROUND_UP(raw->info.xtrct.disp +
711 					  (raw->info.src.last * 8),
712 					  ICE_FLOW_FV_EXTRACT_SZ * 8);
713 		off = raw->info.xtrct.off;
714 		for (j = 0; j < cnt; j++) {
715 			/* Make sure the number of extraction sequence required
716 			 * does not exceed the block's capability
717 			 */
718 			if (params->es_cnt >= hw->blk[params->blk].es.count ||
719 			    params->es_cnt >= ICE_MAX_FV_WORDS)
720 				return ICE_ERR_MAX_LIMIT;
721 
722 			params->es[params->es_cnt].prot_id = ICE_PROT_PAY;
723 			params->es[params->es_cnt].off = off;
724 			params->es_cnt++;
725 			off += ICE_FLOW_FV_EXTRACT_SZ;
726 		}
727 	}
728 
729 	return ICE_SUCCESS;
730 }
731 
732 /**
733  * ice_flow_create_xtrct_seq - Create an extraction sequence for given segments
734  * @hw: pointer to the HW struct
735  * @params: information about the flow to be processed
736  *
737  * This function iterates through all matched fields in the given segments, and
738  * creates an extraction sequence for the fields.
739  */
740 static enum ice_status
741 ice_flow_create_xtrct_seq(struct ice_hw *hw,
742 			  struct ice_flow_prof_params *params)
743 {
744 	enum ice_status status = ICE_SUCCESS;
745 	u8 i;
746 
747 	for (i = 0; i < params->prof->segs_cnt; i++) {
748 		u64 match = params->prof->segs[i].match;
749 		u16 j;
750 
751 		for (j = 0; j < ICE_FLOW_FIELD_IDX_MAX && match; j++) {
752 			const u64 bit = BIT_ULL(j);
753 
754 			if (match & bit) {
755 				status = ice_flow_xtract_fld
756 					(hw, params, i, (enum ice_flow_field)j);
757 				if (status)
758 					return status;
759 				match &= ~bit;
760 			}
761 		}
762 
763 		/* Process raw matching bytes */
764 		status = ice_flow_xtract_raws(hw, params, i);
765 		if (status)
766 			return status;
767 	}
768 
769 	return status;
770 }
771 
772 /**
773  * ice_flow_proc_segs - process all packet segments associated with a profile
774  * @hw: pointer to the HW struct
775  * @params: information about the flow to be processed
776  */
777 static enum ice_status
778 ice_flow_proc_segs(struct ice_hw *hw, struct ice_flow_prof_params *params)
779 {
780 	enum ice_status status;
781 
782 	status = ice_flow_proc_seg_hdrs(params);
783 	if (status)
784 		return status;
785 
786 	status = ice_flow_create_xtrct_seq(hw, params);
787 	if (status)
788 		return status;
789 
790 	switch (params->blk) {
791 	case ICE_BLK_RSS:
792 		/* Only header information is provided for RSS configuration.
793 		 * No further processing is needed.
794 		 */
795 		status = ICE_SUCCESS;
796 		break;
797 	case ICE_BLK_FD:
798 		status = ICE_SUCCESS;
799 		break;
800 	case ICE_BLK_SW:
801 	default:
802 		return ICE_ERR_NOT_IMPL;
803 	}
804 
805 	return status;
806 }
807 
808 #define ICE_FLOW_FIND_PROF_CHK_FLDS	0x00000001
809 #define ICE_FLOW_FIND_PROF_CHK_VSI	0x00000002
810 
811 /**
812  * ice_flow_find_prof_conds - Find a profile matching headers and conditions
813  * @hw: pointer to the HW struct
814  * @blk: classification stage
815  * @dir: flow direction
816  * @segs: array of one or more packet segments that describe the flow
817  * @segs_cnt: number of packet segments provided
818  * @vsi_handle: software VSI handle to check VSI (ICE_FLOW_FIND_PROF_CHK_VSI)
819  * @conds: additional conditions to be checked (ICE_FLOW_FIND_PROF_CHK_*)
820  */
821 static struct ice_flow_prof *
822 ice_flow_find_prof_conds(struct ice_hw *hw, enum ice_block blk,
823 			 enum ice_flow_dir dir, struct ice_flow_seg_info *segs,
824 			 u8 segs_cnt, u16 vsi_handle, u32 conds)
825 {
826 	struct ice_flow_prof *p;
827 
828 	LIST_FOR_EACH_ENTRY(p, &hw->fl_profs[blk], ice_flow_prof, l_entry) {
829 		if (p->dir == dir && segs_cnt && segs_cnt == p->segs_cnt) {
830 			u8 i;
831 
832 			/* Check for profile-VSI association if specified */
833 			if ((conds & ICE_FLOW_FIND_PROF_CHK_VSI) &&
834 			    ice_is_vsi_valid(hw, vsi_handle) &&
835 			    !ice_is_bit_set(p->vsis, vsi_handle))
836 				continue;
837 
838 			/* Protocol headers must be checked. Matched fields are
839 			 * checked if specified.
840 			 */
841 			for (i = 0; i < segs_cnt; i++)
842 				if (segs[i].hdrs != p->segs[i].hdrs ||
843 				    ((conds & ICE_FLOW_FIND_PROF_CHK_FLDS) &&
844 				     segs[i].match != p->segs[i].match))
845 					break;
846 
847 			/* A match is found if all segments are matched */
848 			if (i == segs_cnt)
849 				return p;
850 		}
851 	}
852 
853 	return NULL;
854 }
855 
856 /**
857  * ice_flow_find_prof - Look up a profile matching headers and matched fields
858  * @hw: pointer to the HW struct
859  * @blk: classification stage
860  * @dir: flow direction
861  * @segs: array of one or more packet segments that describe the flow
862  * @segs_cnt: number of packet segments provided
863  */
864 u64
865 ice_flow_find_prof(struct ice_hw *hw, enum ice_block blk, enum ice_flow_dir dir,
866 		   struct ice_flow_seg_info *segs, u8 segs_cnt)
867 {
868 	struct ice_flow_prof *p;
869 
870 	ice_acquire_lock(&hw->fl_profs_locks[blk]);
871 	p = ice_flow_find_prof_conds(hw, blk, dir, segs, segs_cnt,
872 				     ICE_MAX_VSI, ICE_FLOW_FIND_PROF_CHK_FLDS);
873 	ice_release_lock(&hw->fl_profs_locks[blk]);
874 
875 	return p ? p->id : ICE_FLOW_PROF_ID_INVAL;
876 }
877 
878 /**
879  * ice_flow_find_prof_id - Look up a profile with given profile ID
880  * @hw: pointer to the HW struct
881  * @blk: classification stage
882  * @prof_id: unique ID to identify this flow profile
883  */
884 static struct ice_flow_prof *
885 ice_flow_find_prof_id(struct ice_hw *hw, enum ice_block blk, u64 prof_id)
886 {
887 	struct ice_flow_prof *p;
888 
889 	LIST_FOR_EACH_ENTRY(p, &hw->fl_profs[blk], ice_flow_prof, l_entry) {
890 		if (p->id == prof_id)
891 			return p;
892 	}
893 
894 	return NULL;
895 }
896 
897 /**
898  * ice_flow_rem_entry_sync - Remove a flow entry
899  * @hw: pointer to the HW struct
900  * @entry: flow entry to be removed
901  */
902 static enum ice_status
903 ice_flow_rem_entry_sync(struct ice_hw *hw, struct ice_flow_entry *entry)
904 {
905 	if (!entry)
906 		return ICE_ERR_BAD_PTR;
907 
908 	LIST_DEL(&entry->l_entry);
909 
910 	if (entry->entry)
911 		ice_free(hw, entry->entry);
912 
913 	if (entry->acts) {
914 		ice_free(hw, entry->acts);
915 		entry->acts = NULL;
916 		entry->acts_cnt = 0;
917 	}
918 
919 	ice_free(hw, entry);
920 
921 	return ICE_SUCCESS;
922 }
923 
924 /**
925  * ice_flow_add_prof_sync - Add a flow profile for packet segments and fields
926  * @hw: pointer to the HW struct
927  * @blk: classification stage
928  * @dir: flow direction
929  * @prof_id: unique ID to identify this flow profile
930  * @segs: array of one or more packet segments that describe the flow
931  * @segs_cnt: number of packet segments provided
932  * @acts: array of default actions
933  * @acts_cnt: number of default actions
934  * @prof: stores the returned flow profile added
935  *
936  * Assumption: the caller has acquired the lock to the profile list
937  */
938 static enum ice_status
939 ice_flow_add_prof_sync(struct ice_hw *hw, enum ice_block blk,
940 		       enum ice_flow_dir dir, u64 prof_id,
941 		       struct ice_flow_seg_info *segs, u8 segs_cnt,
942 		       struct ice_flow_action *acts, u8 acts_cnt,
943 		       struct ice_flow_prof **prof)
944 {
945 	struct ice_flow_prof_params params;
946 	enum ice_status status = ICE_SUCCESS;
947 	u8 i;
948 
949 	if (!prof || (acts_cnt && !acts))
950 		return ICE_ERR_BAD_PTR;
951 
952 	ice_memset(&params, 0, sizeof(params), ICE_NONDMA_MEM);
953 	params.prof = (struct ice_flow_prof *)
954 		ice_malloc(hw, sizeof(*params.prof));
955 	if (!params.prof)
956 		return ICE_ERR_NO_MEMORY;
957 
958 	/* initialize extraction sequence to all invalid (0xff) */
959 	for (i = 0; i < ICE_MAX_FV_WORDS; i++) {
960 		params.es[i].prot_id = ICE_PROT_INVALID;
961 		params.es[i].off = ICE_FV_OFFSET_INVAL;
962 	}
963 
964 	params.blk = blk;
965 	params.prof->id = prof_id;
966 	params.prof->dir = dir;
967 	params.prof->segs_cnt = segs_cnt;
968 
969 	/* Make a copy of the segments that need to be persistent in the flow
970 	 * profile instance
971 	 */
972 	for (i = 0; i < segs_cnt; i++)
973 		ice_memcpy(&params.prof->segs[i], &segs[i], sizeof(*segs),
974 			   ICE_NONDMA_TO_NONDMA);
975 
976 	/* Make a copy of the actions that need to be persistent in the flow
977 	 * profile instance.
978 	 */
979 	if (acts_cnt) {
980 		params.prof->acts = (struct ice_flow_action *)
981 			ice_memdup(hw, acts, acts_cnt * sizeof(*acts),
982 				   ICE_NONDMA_TO_NONDMA);
983 
984 		if (!params.prof->acts) {
985 			status = ICE_ERR_NO_MEMORY;
986 			goto out;
987 		}
988 	}
989 
990 	status = ice_flow_proc_segs(hw, &params);
991 	if (status) {
992 		ice_debug(hw, ICE_DBG_FLOW,
993 			  "Error processing a flow's packet segments\n");
994 		goto out;
995 	}
996 
997 	/* Add a HW profile for this flow profile */
998 	status = ice_add_prof(hw, blk, prof_id, (u8 *)params.ptypes, params.es);
999 	if (status) {
1000 		ice_debug(hw, ICE_DBG_FLOW, "Error adding a HW flow profile\n");
1001 		goto out;
1002 	}
1003 
1004 	INIT_LIST_HEAD(&params.prof->entries);
1005 	ice_init_lock(&params.prof->entries_lock);
1006 	*prof = params.prof;
1007 
1008 out:
1009 	if (status) {
1010 		if (params.prof->acts)
1011 			ice_free(hw, params.prof->acts);
1012 		ice_free(hw, params.prof);
1013 	}
1014 
1015 	return status;
1016 }
1017 
1018 /**
1019  * ice_flow_rem_prof_sync - remove a flow profile
1020  * @hw: pointer to the hardware structure
1021  * @blk: classification stage
1022  * @prof: pointer to flow profile to remove
1023  *
1024  * Assumption: the caller has acquired the lock to the profile list
1025  */
1026 static enum ice_status
1027 ice_flow_rem_prof_sync(struct ice_hw *hw, enum ice_block blk,
1028 		       struct ice_flow_prof *prof)
1029 {
1030 	enum ice_status status = ICE_SUCCESS;
1031 
1032 	/* Remove all remaining flow entries before removing the flow profile */
1033 	if (!LIST_EMPTY(&prof->entries)) {
1034 		struct ice_flow_entry *e, *t;
1035 
1036 		ice_acquire_lock(&prof->entries_lock);
1037 
1038 		LIST_FOR_EACH_ENTRY_SAFE(e, t, &prof->entries, ice_flow_entry,
1039 					 l_entry) {
1040 			status = ice_flow_rem_entry_sync(hw, e);
1041 			if (status)
1042 				break;
1043 		}
1044 
1045 		ice_release_lock(&prof->entries_lock);
1046 	}
1047 
1048 	/* Remove all hardware profiles associated with this flow profile */
1049 	status = ice_rem_prof(hw, blk, prof->id);
1050 	if (!status) {
1051 		LIST_DEL(&prof->l_entry);
1052 		ice_destroy_lock(&prof->entries_lock);
1053 		if (prof->acts)
1054 			ice_free(hw, prof->acts);
1055 		ice_free(hw, prof);
1056 	}
1057 
1058 	return status;
1059 }
1060 
1061 /**
1062  * ice_flow_assoc_prof - associate a VSI with a flow profile
1063  * @hw: pointer to the hardware structure
1064  * @blk: classification stage
1065  * @prof: pointer to flow profile
1066  * @vsi_handle: software VSI handle
1067  *
1068  * Assumption: the caller has acquired the lock to the profile list
1069  * and the software VSI handle has been validated
1070  */
1071 static enum ice_status
1072 ice_flow_assoc_prof(struct ice_hw *hw, enum ice_block blk,
1073 		    struct ice_flow_prof *prof, u16 vsi_handle)
1074 {
1075 	enum ice_status status = ICE_SUCCESS;
1076 
1077 	if (!ice_is_bit_set(prof->vsis, vsi_handle)) {
1078 		status = ice_add_prof_id_flow(hw, blk,
1079 					      ice_get_hw_vsi_num(hw,
1080 								 vsi_handle),
1081 					      prof->id);
1082 		if (!status)
1083 			ice_set_bit(vsi_handle, prof->vsis);
1084 		else
1085 			ice_debug(hw, ICE_DBG_FLOW,
1086 				  "HW profile add failed, %d\n",
1087 				  status);
1088 	}
1089 
1090 	return status;
1091 }
1092 
1093 /**
1094  * ice_flow_disassoc_prof - disassociate a VSI from a flow profile
1095  * @hw: pointer to the hardware structure
1096  * @blk: classification stage
1097  * @prof: pointer to flow profile
1098  * @vsi_handle: software VSI handle
1099  *
1100  * Assumption: the caller has acquired the lock to the profile list
1101  * and the software VSI handle has been validated
1102  */
1103 static enum ice_status
1104 ice_flow_disassoc_prof(struct ice_hw *hw, enum ice_block blk,
1105 		       struct ice_flow_prof *prof, u16 vsi_handle)
1106 {
1107 	enum ice_status status = ICE_SUCCESS;
1108 
1109 	if (ice_is_bit_set(prof->vsis, vsi_handle)) {
1110 		status = ice_rem_prof_id_flow(hw, blk,
1111 					      ice_get_hw_vsi_num(hw,
1112 								 vsi_handle),
1113 					      prof->id);
1114 		if (!status)
1115 			ice_clear_bit(vsi_handle, prof->vsis);
1116 		else
1117 			ice_debug(hw, ICE_DBG_FLOW,
1118 				  "HW profile remove failed, %d\n",
1119 				  status);
1120 	}
1121 
1122 	return status;
1123 }
1124 
1125 /**
1126  * ice_flow_add_prof - Add a flow profile for packet segments and matched fields
1127  * @hw: pointer to the HW struct
1128  * @blk: classification stage
1129  * @dir: flow direction
1130  * @prof_id: unique ID to identify this flow profile
1131  * @segs: array of one or more packet segments that describe the flow
1132  * @segs_cnt: number of packet segments provided
1133  * @acts: array of default actions
1134  * @acts_cnt: number of default actions
1135  * @prof: stores the returned flow profile added
1136  */
1137 enum ice_status
1138 ice_flow_add_prof(struct ice_hw *hw, enum ice_block blk, enum ice_flow_dir dir,
1139 		  u64 prof_id, struct ice_flow_seg_info *segs, u8 segs_cnt,
1140 		  struct ice_flow_action *acts, u8 acts_cnt,
1141 		  struct ice_flow_prof **prof)
1142 {
1143 	enum ice_status status;
1144 
1145 	if (segs_cnt > ICE_FLOW_SEG_MAX)
1146 		return ICE_ERR_MAX_LIMIT;
1147 
1148 	if (!segs_cnt)
1149 		return ICE_ERR_PARAM;
1150 
1151 	if (!segs)
1152 		return ICE_ERR_BAD_PTR;
1153 
1154 	status = ice_flow_val_hdrs(segs, segs_cnt);
1155 	if (status)
1156 		return status;
1157 
1158 	ice_acquire_lock(&hw->fl_profs_locks[blk]);
1159 
1160 	status = ice_flow_add_prof_sync(hw, blk, dir, prof_id, segs, segs_cnt,
1161 					acts, acts_cnt, prof);
1162 	if (!status)
1163 		LIST_ADD(&(*prof)->l_entry, &hw->fl_profs[blk]);
1164 
1165 	ice_release_lock(&hw->fl_profs_locks[blk]);
1166 
1167 	return status;
1168 }
1169 
1170 /**
1171  * ice_flow_rem_prof - Remove a flow profile and all entries associated with it
1172  * @hw: pointer to the HW struct
1173  * @blk: the block for which the flow profile is to be removed
1174  * @prof_id: unique ID of the flow profile to be removed
1175  */
1176 enum ice_status
1177 ice_flow_rem_prof(struct ice_hw *hw, enum ice_block blk, u64 prof_id)
1178 {
1179 	struct ice_flow_prof *prof;
1180 	enum ice_status status;
1181 
1182 	ice_acquire_lock(&hw->fl_profs_locks[blk]);
1183 
1184 	prof = ice_flow_find_prof_id(hw, blk, prof_id);
1185 	if (!prof) {
1186 		status = ICE_ERR_DOES_NOT_EXIST;
1187 		goto out;
1188 	}
1189 
1190 	/* prof becomes invalid after the call */
1191 	status = ice_flow_rem_prof_sync(hw, blk, prof);
1192 
1193 out:
1194 	ice_release_lock(&hw->fl_profs_locks[blk]);
1195 
1196 	return status;
1197 }
1198 
1199 /**
1200  * ice_flow_get_hw_prof - return the HW profile for a specific profile ID handle
1201  * @hw: pointer to the HW struct
1202  * @blk: classification stage
1203  * @prof_id: the profile ID handle
1204  * @hw_prof_id: pointer to variable to receive the HW profile ID
1205  */
1206 enum ice_status
1207 ice_flow_get_hw_prof(struct ice_hw *hw, enum ice_block blk, u64 prof_id,
1208 		     u8 *hw_prof_id)
1209 {
1210 	struct ice_prof_map *map;
1211 
1212 	map = ice_search_prof_id(hw, blk, prof_id);
1213 	if (map) {
1214 		*hw_prof_id = map->prof_id;
1215 		return ICE_SUCCESS;
1216 	}
1217 
1218 	return ICE_ERR_DOES_NOT_EXIST;
1219 }
1220 
1221 /**
1222  * ice_flow_find_entry - look for a flow entry using its unique ID
1223  * @hw: pointer to the HW struct
1224  * @blk: classification stage
1225  * @entry_id: unique ID to identify this flow entry
1226  *
1227  * This function looks for the flow entry with the specified unique ID in all
1228  * flow profiles of the specified classification stage. If the entry is found,
1229  * and it returns the handle to the flow entry. Otherwise, it returns
1230  * ICE_FLOW_ENTRY_ID_INVAL.
1231  */
1232 u64 ice_flow_find_entry(struct ice_hw *hw, enum ice_block blk, u64 entry_id)
1233 {
1234 	struct ice_flow_entry *found = NULL;
1235 	struct ice_flow_prof *p;
1236 
1237 	ice_acquire_lock(&hw->fl_profs_locks[blk]);
1238 
1239 	LIST_FOR_EACH_ENTRY(p, &hw->fl_profs[blk], ice_flow_prof, l_entry) {
1240 		struct ice_flow_entry *e;
1241 
1242 		ice_acquire_lock(&p->entries_lock);
1243 		LIST_FOR_EACH_ENTRY(e, &p->entries, ice_flow_entry, l_entry)
1244 			if (e->id == entry_id) {
1245 				found = e;
1246 				break;
1247 			}
1248 		ice_release_lock(&p->entries_lock);
1249 
1250 		if (found)
1251 			break;
1252 	}
1253 
1254 	ice_release_lock(&hw->fl_profs_locks[blk]);
1255 
1256 	return found ? ICE_FLOW_ENTRY_HNDL(found) : ICE_FLOW_ENTRY_HANDLE_INVAL;
1257 }
1258 
1259 /**
1260  * ice_flow_add_entry - Add a flow entry
1261  * @hw: pointer to the HW struct
1262  * @blk: classification stage
1263  * @prof_id: ID of the profile to add a new flow entry to
1264  * @entry_id: unique ID to identify this flow entry
1265  * @vsi_handle: software VSI handle for the flow entry
1266  * @prio: priority of the flow entry
1267  * @data: pointer to a data buffer containing flow entry's match values/masks
1268  * @acts: arrays of actions to be performed on a match
1269  * @acts_cnt: number of actions
1270  * @entry_h: pointer to buffer that receives the new flow entry's handle
1271  */
1272 enum ice_status
1273 ice_flow_add_entry(struct ice_hw *hw, enum ice_block blk, u64 prof_id,
1274 		   u64 entry_id, u16 vsi_handle, enum ice_flow_priority prio,
1275 		   void *data, struct ice_flow_action *acts, u8 acts_cnt,
1276 		   u64 *entry_h)
1277 {
1278 	struct ice_flow_prof *prof = NULL;
1279 	struct ice_flow_entry *e = NULL;
1280 	enum ice_status status = ICE_SUCCESS;
1281 
1282 	if (acts_cnt && !acts)
1283 		return ICE_ERR_PARAM;
1284 
1285 	/* No flow entry data is expected for RSS */
1286 	if (!entry_h || (!data && blk != ICE_BLK_RSS))
1287 		return ICE_ERR_BAD_PTR;
1288 
1289 	if (!ice_is_vsi_valid(hw, vsi_handle))
1290 		return ICE_ERR_PARAM;
1291 
1292 	ice_acquire_lock(&hw->fl_profs_locks[blk]);
1293 
1294 	prof = ice_flow_find_prof_id(hw, blk, prof_id);
1295 	if (!prof) {
1296 		status = ICE_ERR_DOES_NOT_EXIST;
1297 	} else {
1298 		/* Allocate memory for the entry being added and associate
1299 		 * the VSI to the found flow profile
1300 		 */
1301 		e = (struct ice_flow_entry *)ice_malloc(hw, sizeof(*e));
1302 		if (!e)
1303 			status = ICE_ERR_NO_MEMORY;
1304 		else
1305 			status = ice_flow_assoc_prof(hw, blk, prof, vsi_handle);
1306 	}
1307 
1308 	ice_release_lock(&hw->fl_profs_locks[blk]);
1309 	if (status)
1310 		goto out;
1311 
1312 	e->id = entry_id;
1313 	e->vsi_handle = vsi_handle;
1314 	e->prof = prof;
1315 	e->priority = prio;
1316 
1317 	switch (blk) {
1318 	case ICE_BLK_RSS:
1319 		/* RSS will add only one entry per VSI per profile */
1320 		break;
1321 	case ICE_BLK_FD:
1322 		break;
1323 	case ICE_BLK_SW:
1324 	case ICE_BLK_PE:
1325 	default:
1326 		status = ICE_ERR_NOT_IMPL;
1327 		goto out;
1328 	}
1329 
1330 	ice_acquire_lock(&prof->entries_lock);
1331 	LIST_ADD(&e->l_entry, &prof->entries);
1332 	ice_release_lock(&prof->entries_lock);
1333 
1334 	*entry_h = ICE_FLOW_ENTRY_HNDL(e);
1335 
1336 out:
1337 	if (status && e) {
1338 		if (e->entry)
1339 			ice_free(hw, e->entry);
1340 		ice_free(hw, e);
1341 	}
1342 
1343 	return status;
1344 }
1345 
1346 /**
1347  * ice_flow_rem_entry - Remove a flow entry
1348  * @hw: pointer to the HW struct
1349  * @entry_h: handle to the flow entry to be removed
1350  */
1351 enum ice_status ice_flow_rem_entry(struct ice_hw *hw, u64 entry_h)
1352 {
1353 	struct ice_flow_entry *entry;
1354 	struct ice_flow_prof *prof;
1355 	enum ice_status status;
1356 
1357 	if (entry_h == ICE_FLOW_ENTRY_HANDLE_INVAL)
1358 		return ICE_ERR_PARAM;
1359 
1360 	entry = ICE_FLOW_ENTRY_PTR((unsigned long)entry_h);
1361 
1362 	/* Retain the pointer to the flow profile as the entry will be freed */
1363 	prof = entry->prof;
1364 
1365 	ice_acquire_lock(&prof->entries_lock);
1366 	status = ice_flow_rem_entry_sync(hw, entry);
1367 	ice_release_lock(&prof->entries_lock);
1368 
1369 	return status;
1370 }
1371 
1372 /**
1373  * ice_flow_set_fld_ext - specifies locations of field from entry's input buffer
1374  * @seg: packet segment the field being set belongs to
1375  * @fld: field to be set
1376  * @type: type of the field
1377  * @val_loc: if not ICE_FLOW_FLD_OFF_INVAL, location of the value to match from
1378  *           entry's input buffer
1379  * @mask_loc: if not ICE_FLOW_FLD_OFF_INVAL, location of mask value from entry's
1380  *            input buffer
1381  * @last_loc: if not ICE_FLOW_FLD_OFF_INVAL, location of last/upper value from
1382  *            entry's input buffer
1383  *
1384  * This helper function stores information of a field being matched, including
1385  * the type of the field and the locations of the value to match, the mask, and
1386  * and the upper-bound value in the start of the input buffer for a flow entry.
1387  * This function should only be used for fixed-size data structures.
1388  *
1389  * This function also opportunistically determines the protocol headers to be
1390  * present based on the fields being set. Some fields cannot be used alone to
1391  * determine the protocol headers present. Sometimes, fields for particular
1392  * protocol headers are not matched. In those cases, the protocol headers
1393  * must be explicitly set.
1394  */
1395 static void
1396 ice_flow_set_fld_ext(struct ice_flow_seg_info *seg, enum ice_flow_field fld,
1397 		     enum ice_flow_fld_match_type type, u16 val_loc,
1398 		     u16 mask_loc, u16 last_loc)
1399 {
1400 	u64 bit = BIT_ULL(fld);
1401 
1402 	seg->match |= bit;
1403 	if (type == ICE_FLOW_FLD_TYPE_RANGE)
1404 		seg->range |= bit;
1405 
1406 	seg->fields[fld].type = type;
1407 	seg->fields[fld].src.val = val_loc;
1408 	seg->fields[fld].src.mask = mask_loc;
1409 	seg->fields[fld].src.last = last_loc;
1410 
1411 	ICE_FLOW_SET_HDRS(seg, ice_flds_info[fld].hdr);
1412 }
1413 
1414 /**
1415  * ice_flow_set_fld - specifies locations of field from entry's input buffer
1416  * @seg: packet segment the field being set belongs to
1417  * @fld: field to be set
1418  * @val_loc: if not ICE_FLOW_FLD_OFF_INVAL, location of the value to match from
1419  *           entry's input buffer
1420  * @mask_loc: if not ICE_FLOW_FLD_OFF_INVAL, location of mask value from entry's
1421  *            input buffer
1422  * @last_loc: if not ICE_FLOW_FLD_OFF_INVAL, location of last/upper value from
1423  *            entry's input buffer
1424  * @range: indicate if field being matched is to be in a range
1425  *
1426  * This function specifies the locations, in the form of byte offsets from the
1427  * start of the input buffer for a flow entry, from where the value to match,
1428  * the mask value, and upper value can be extracted. These locations are then
1429  * stored in the flow profile. When adding a flow entry associated with the
1430  * flow profile, these locations will be used to quickly extract the values and
1431  * create the content of a match entry. This function should only be used for
1432  * fixed-size data structures.
1433  */
1434 void
1435 ice_flow_set_fld(struct ice_flow_seg_info *seg, enum ice_flow_field fld,
1436 		 u16 val_loc, u16 mask_loc, u16 last_loc, bool range)
1437 {
1438 	enum ice_flow_fld_match_type t = range ?
1439 		ICE_FLOW_FLD_TYPE_RANGE : ICE_FLOW_FLD_TYPE_REG;
1440 
1441 	ice_flow_set_fld_ext(seg, fld, t, val_loc, mask_loc, last_loc);
1442 }
1443 
1444 /**
1445  * ice_flow_set_fld_prefix - sets locations of prefix field from entry's buf
1446  * @seg: packet segment the field being set belongs to
1447  * @fld: field to be set
1448  * @val_loc: if not ICE_FLOW_FLD_OFF_INVAL, location of the value to match from
1449  *           entry's input buffer
1450  * @pref_loc: location of prefix value from entry's input buffer
1451  * @pref_sz: size of the location holding the prefix value
1452  *
1453  * This function specifies the locations, in the form of byte offsets from the
1454  * start of the input buffer for a flow entry, from where the value to match
1455  * and the IPv4 prefix value can be extracted. These locations are then stored
1456  * in the flow profile. When adding flow entries to the associated flow profile,
1457  * these locations can be used to quickly extract the values to create the
1458  * content of a match entry. This function should only be used for fixed-size
1459  * data structures.
1460  */
1461 void
1462 ice_flow_set_fld_prefix(struct ice_flow_seg_info *seg, enum ice_flow_field fld,
1463 			u16 val_loc, u16 pref_loc, u8 pref_sz)
1464 {
1465 	/* For this type of field, the "mask" location is for the prefix value's
1466 	 * location and the "last" location is for the size of the location of
1467 	 * the prefix value.
1468 	 */
1469 	ice_flow_set_fld_ext(seg, fld, ICE_FLOW_FLD_TYPE_PREFIX, val_loc,
1470 			     pref_loc, (u16)pref_sz);
1471 }
1472 
1473 /**
1474  * ice_flow_add_fld_raw - sets locations of a raw field from entry's input buf
1475  * @seg: packet segment the field being set belongs to
1476  * @off: offset of the raw field from the beginning of the segment in bytes
1477  * @len: length of the raw pattern to be matched
1478  * @val_loc: location of the value to match from entry's input buffer
1479  * @mask_loc: location of mask value from entry's input buffer
1480  *
1481  * This function specifies the offset of the raw field to be match from the
1482  * beginning of the specified packet segment, and the locations, in the form of
1483  * byte offsets from the start of the input buffer for a flow entry, from where
1484  * the value to match and the mask value to be extracted. These locations are
1485  * then stored in the flow profile. When adding flow entries to the associated
1486  * flow profile, these locations can be used to quickly extract the values to
1487  * create the content of a match entry. This function should only be used for
1488  * fixed-size data structures.
1489  */
1490 void
1491 ice_flow_add_fld_raw(struct ice_flow_seg_info *seg, u16 off, u8 len,
1492 		     u16 val_loc, u16 mask_loc)
1493 {
1494 	if (seg->raws_cnt < ICE_FLOW_SEG_RAW_FLD_MAX) {
1495 		seg->raws[seg->raws_cnt].off = off;
1496 		seg->raws[seg->raws_cnt].info.type = ICE_FLOW_FLD_TYPE_SIZE;
1497 		seg->raws[seg->raws_cnt].info.src.val = val_loc;
1498 		seg->raws[seg->raws_cnt].info.src.mask = mask_loc;
1499 		/* The "last" field is used to store the length of the field */
1500 		seg->raws[seg->raws_cnt].info.src.last = len;
1501 	}
1502 
1503 	/* Overflows of "raws" will be handled as an error condition later in
1504 	 * the flow when this information is processed.
1505 	 */
1506 	seg->raws_cnt++;
1507 }
1508 
1509 #define ICE_FLOW_RSS_SEG_HDR_L3_MASKS \
1510 	(ICE_FLOW_SEG_HDR_IPV4 | ICE_FLOW_SEG_HDR_IPV6)
1511 
1512 #define ICE_FLOW_RSS_SEG_HDR_L4_MASKS \
1513 	(ICE_FLOW_SEG_HDR_TCP | ICE_FLOW_SEG_HDR_UDP | \
1514 	 ICE_FLOW_SEG_HDR_SCTP)
1515 
1516 #define ICE_FLOW_RSS_SEG_HDR_VAL_MASKS \
1517 	(ICE_FLOW_RSS_SEG_HDR_L3_MASKS | \
1518 	 ICE_FLOW_RSS_SEG_HDR_L4_MASKS)
1519 
1520 /**
1521  * ice_flow_set_rss_seg_info - setup packet segments for RSS
1522  * @segs: pointer to the flow field segment(s)
1523  * @hash_fields: fields to be hashed on for the segment(s)
1524  * @flow_hdr: protocol header fields within a packet segment
1525  *
1526  * Helper function to extract fields from hash bitmap and use flow
1527  * header value to set flow field segment for further use in flow
1528  * profile entry or removal.
1529  */
1530 static enum ice_status
1531 ice_flow_set_rss_seg_info(struct ice_flow_seg_info *segs, u64 hash_fields,
1532 			  u32 flow_hdr)
1533 {
1534 	u64 val = hash_fields;
1535 	u8 i;
1536 
1537 	for (i = 0; val && i < ICE_FLOW_FIELD_IDX_MAX; i++) {
1538 		u64 bit = BIT_ULL(i);
1539 
1540 		if (val & bit) {
1541 			ice_flow_set_fld(segs, (enum ice_flow_field)i,
1542 					 ICE_FLOW_FLD_OFF_INVAL,
1543 					 ICE_FLOW_FLD_OFF_INVAL,
1544 					 ICE_FLOW_FLD_OFF_INVAL, false);
1545 			val &= ~bit;
1546 		}
1547 	}
1548 	ICE_FLOW_SET_HDRS(segs, flow_hdr);
1549 
1550 	if (segs->hdrs & ~ICE_FLOW_RSS_SEG_HDR_VAL_MASKS)
1551 		return ICE_ERR_PARAM;
1552 
1553 	val = (u64)(segs->hdrs & ICE_FLOW_RSS_SEG_HDR_L3_MASKS);
1554 	if (!ice_is_pow2(val))
1555 		return ICE_ERR_CFG;
1556 
1557 	val = (u64)(segs->hdrs & ICE_FLOW_RSS_SEG_HDR_L4_MASKS);
1558 	if (val && !ice_is_pow2(val))
1559 		return ICE_ERR_CFG;
1560 
1561 	return ICE_SUCCESS;
1562 }
1563 
1564 /**
1565  * ice_rem_all_rss_vsi_ctx - remove all RSS configurations from VSI context
1566  * @hw: pointer to the hardware structure
1567  * @vsi_handle: software VSI handle
1568  *
1569  */
1570 void ice_rem_all_rss_vsi_ctx(struct ice_hw *hw, u16 vsi_handle)
1571 {
1572 	struct ice_rss_cfg *r, *tmp;
1573 
1574 	if (!ice_is_vsi_valid(hw, vsi_handle) ||
1575 	    LIST_EMPTY(&hw->vsi_ctx[vsi_handle]->rss_list_head))
1576 		return;
1577 
1578 	ice_acquire_lock(&hw->vsi_ctx[vsi_handle]->rss_locks);
1579 	LIST_FOR_EACH_ENTRY_SAFE(r, tmp,
1580 				 &hw->vsi_ctx[vsi_handle]->rss_list_head,
1581 				 ice_rss_cfg, l_entry) {
1582 		LIST_DEL(&r->l_entry);
1583 		ice_free(hw, r);
1584 	}
1585 	ice_release_lock(&hw->vsi_ctx[vsi_handle]->rss_locks);
1586 }
1587 
1588 /**
1589  * ice_rem_vsi_rss_cfg - remove RSS configurations associated with VSI
1590  * @hw: pointer to the hardware structure
1591  * @vsi_handle: software VSI handle
1592  *
1593  * This function will iterate through all flow profiles and disassociate
1594  * the VSI from that profile. If the flow profile has no VSIs it will
1595  * be removed.
1596  */
1597 enum ice_status ice_rem_vsi_rss_cfg(struct ice_hw *hw, u16 vsi_handle)
1598 {
1599 	const enum ice_block blk = ICE_BLK_RSS;
1600 	struct ice_flow_prof *p, *t;
1601 	enum ice_status status = ICE_SUCCESS;
1602 
1603 	if (!ice_is_vsi_valid(hw, vsi_handle))
1604 		return ICE_ERR_PARAM;
1605 
1606 	ice_acquire_lock(&hw->fl_profs_locks[blk]);
1607 	LIST_FOR_EACH_ENTRY_SAFE(p, t, &hw->fl_profs[blk], ice_flow_prof,
1608 				 l_entry) {
1609 		if (ice_is_bit_set(p->vsis, vsi_handle)) {
1610 			status = ice_flow_disassoc_prof(hw, blk, p, vsi_handle);
1611 			if (status)
1612 				break;
1613 
1614 			if (!ice_is_any_bit_set(p->vsis, ICE_MAX_VSI)) {
1615 				status = ice_flow_rem_prof_sync(hw, blk, p);
1616 				if (status)
1617 					break;
1618 			}
1619 		}
1620 	}
1621 	ice_release_lock(&hw->fl_profs_locks[blk]);
1622 
1623 	return status;
1624 }
1625 
1626 /**
1627  * ice_rem_rss_cfg_vsi_ctx - remove RSS configuration from VSI context
1628  * @hw: pointer to the hardware structure
1629  * @vsi_handle: software VSI handle
1630  * @prof: pointer to flow profile
1631  *
1632  * Assumption: lock has already been acquired for RSS list
1633  */
1634 static void
1635 ice_rem_rss_cfg_vsi_ctx(struct ice_hw *hw, u16 vsi_handle,
1636 			struct ice_flow_prof *prof)
1637 {
1638 	struct ice_rss_cfg *r, *tmp;
1639 
1640 	/* Search for RSS hash fields associated to the VSI that match the
1641 	 * hash configurations associated to the flow profile. If found
1642 	 * remove from the RSS entry list of the VSI context and delete entry.
1643 	 */
1644 	LIST_FOR_EACH_ENTRY_SAFE(r, tmp,
1645 				 &hw->vsi_ctx[vsi_handle]->rss_list_head,
1646 				 ice_rss_cfg, l_entry) {
1647 		if (r->hashed_flds == prof->segs[prof->segs_cnt - 1].match &&
1648 		    r->packet_hdr == prof->segs[prof->segs_cnt - 1].hdrs) {
1649 			LIST_DEL(&r->l_entry);
1650 			ice_free(hw, r);
1651 			return;
1652 		}
1653 	}
1654 }
1655 
1656 /**
1657  * ice_add_rss_vsi_ctx - add RSS configuration to VSI context
1658  * @hw: pointer to the hardware structure
1659  * @vsi_handle: software VSI handle
1660  * @prof: pointer to flow profile
1661  *
1662  * Assumption: lock has already been acquired for RSS list
1663  */
1664 static enum ice_status
1665 ice_add_rss_vsi_ctx(struct ice_hw *hw, u16 vsi_handle,
1666 		    struct ice_flow_prof *prof)
1667 {
1668 	struct ice_rss_cfg *r, *rss_cfg;
1669 
1670 	LIST_FOR_EACH_ENTRY(r, &hw->vsi_ctx[vsi_handle]->rss_list_head,
1671 			    ice_rss_cfg, l_entry)
1672 		if (r->hashed_flds == prof->segs[prof->segs_cnt - 1].match &&
1673 		    r->packet_hdr == prof->segs[prof->segs_cnt - 1].hdrs)
1674 			return ICE_SUCCESS;
1675 
1676 	rss_cfg = (struct ice_rss_cfg *)ice_malloc(hw, sizeof(*rss_cfg));
1677 	if (!rss_cfg)
1678 		return ICE_ERR_NO_MEMORY;
1679 
1680 	rss_cfg->hashed_flds = prof->segs[prof->segs_cnt - 1].match;
1681 	rss_cfg->packet_hdr = prof->segs[prof->segs_cnt - 1].hdrs;
1682 	LIST_ADD_TAIL(&rss_cfg->l_entry,
1683 		      &hw->vsi_ctx[vsi_handle]->rss_list_head);
1684 
1685 	return ICE_SUCCESS;
1686 }
1687 
1688 #define ICE_FLOW_PROF_HASH_S	0
1689 #define ICE_FLOW_PROF_HASH_M	(0xFFFFFFFFULL << ICE_FLOW_PROF_HASH_S)
1690 #define ICE_FLOW_PROF_HDR_S	32
1691 #define ICE_FLOW_PROF_HDR_M	(0xFFFFFFFFULL << ICE_FLOW_PROF_HDR_S)
1692 
1693 #define ICE_FLOW_GEN_PROFID(hash, hdr) \
1694 	(u64)(((u64)(hash) & ICE_FLOW_PROF_HASH_M) | \
1695 	      (((u64)(hdr) << ICE_FLOW_PROF_HDR_S) & ICE_FLOW_PROF_HDR_M))
1696 
1697 /**
1698  * ice_add_rss_cfg_sync - add an RSS configuration
1699  * @hw: pointer to the hardware structure
1700  * @vsi_handle: software VSI handle
1701  * @hashed_flds: hash bit fields (ICE_FLOW_HASH_*) to configure
1702  * @addl_hdrs: protocol header fields
1703  *
1704  * Assumption: lock has already been acquired for RSS list
1705  */
1706 static enum ice_status
1707 ice_add_rss_cfg_sync(struct ice_hw *hw, u16 vsi_handle, u64 hashed_flds,
1708 		     u32 addl_hdrs)
1709 {
1710 	const enum ice_block blk = ICE_BLK_RSS;
1711 	struct ice_flow_prof *prof = NULL;
1712 	struct ice_flow_seg_info *segs;
1713 	enum ice_status status = ICE_SUCCESS;
1714 
1715 	segs = (struct ice_flow_seg_info *)ice_malloc(hw, sizeof(*segs));
1716 	if (!segs)
1717 		return ICE_ERR_NO_MEMORY;
1718 
1719 	/* Construct the packet segment info from the hashed fields */
1720 	status = ice_flow_set_rss_seg_info(segs, hashed_flds, addl_hdrs);
1721 	if (status)
1722 		goto exit;
1723 
1724 	/* Search for a flow profile that has matching headers, hash fields
1725 	 * and has the input VSI associated to it. If found, no further
1726 	 * operations required and exit.
1727 	 */
1728 	prof = ice_flow_find_prof_conds(hw, blk, ICE_FLOW_RX, segs, 1,
1729 					vsi_handle,
1730 					ICE_FLOW_FIND_PROF_CHK_FLDS |
1731 					ICE_FLOW_FIND_PROF_CHK_VSI);
1732 	if (prof)
1733 		goto exit;
1734 
1735 	/* Check if a flow profile exists with the same protocol headers and
1736 	 * associated with the input VSI. If so disasscociate the VSI from
1737 	 * this profile. The VSI will be added to a new profile created with
1738 	 * the protocol header and new hash field configuration.
1739 	 */
1740 	prof = ice_flow_find_prof_conds(hw, blk, ICE_FLOW_RX, segs, 1,
1741 					vsi_handle, ICE_FLOW_FIND_PROF_CHK_VSI);
1742 	if (prof) {
1743 		status = ice_flow_disassoc_prof(hw, blk, prof, vsi_handle);
1744 		if (!status)
1745 			ice_rem_rss_cfg_vsi_ctx(hw, vsi_handle, prof);
1746 		else
1747 			goto exit;
1748 
1749 		/* Remove profile if it has no VSIs associated */
1750 		if (!ice_is_any_bit_set(prof->vsis, ICE_MAX_VSI)) {
1751 			status = ice_flow_rem_prof_sync(hw, blk, prof);
1752 			if (status)
1753 				goto exit;
1754 		}
1755 	}
1756 
1757 	/* Search for a profile that has same match fields only. If this
1758 	 * exists then associate the VSI to this profile.
1759 	 */
1760 	prof = ice_flow_find_prof_conds(hw, blk, ICE_FLOW_RX, segs, 1,
1761 					vsi_handle,
1762 					ICE_FLOW_FIND_PROF_CHK_FLDS);
1763 	if (prof) {
1764 		status = ice_flow_assoc_prof(hw, blk, prof, vsi_handle);
1765 		if (!status)
1766 			status = ice_add_rss_vsi_ctx(hw, vsi_handle, prof);
1767 		goto exit;
1768 	}
1769 
1770 	/* Create a new flow profile with generated profile and packet
1771 	 * segment information.
1772 	 */
1773 	status = ice_flow_add_prof(hw, blk, ICE_FLOW_RX,
1774 				   ICE_FLOW_GEN_PROFID(hashed_flds, segs->hdrs),
1775 				   segs, 1, NULL, 0, &prof);
1776 	if (status)
1777 		goto exit;
1778 
1779 	status = ice_flow_assoc_prof(hw, blk, prof, vsi_handle);
1780 	/* If association to a new flow profile failed then this profile can
1781 	 * be removed.
1782 	 */
1783 	if (status) {
1784 		ice_flow_rem_prof_sync(hw, blk, prof);
1785 		goto exit;
1786 	}
1787 
1788 	status = ice_add_rss_vsi_ctx(hw, vsi_handle, prof);
1789 
1790 exit:
1791 	ice_free(hw, segs);
1792 	return status;
1793 }
1794 
1795 /**
1796  * ice_add_rss_cfg - add an RSS configuration with specified hashed fields
1797  * @hw: pointer to the hardware structure
1798  * @vsi_handle: software VSI handle
1799  * @hashed_flds: hash bit fields (ICE_FLOW_HASH_*) to configure
1800  * @addl_hdrs: protocol header fields
1801  *
1802  * This function will generate a flow profile based on fields associated with
1803  * the input fields to hash on, the flow type and use the VSI number to add
1804  * a flow entry to the profile.
1805  */
1806 enum ice_status
1807 ice_add_rss_cfg(struct ice_hw *hw, u16 vsi_handle, u64 hashed_flds,
1808 		u32 addl_hdrs)
1809 {
1810 	enum ice_status status;
1811 
1812 	if (hashed_flds == ICE_HASH_INVALID ||
1813 	    !ice_is_vsi_valid(hw, vsi_handle))
1814 		return ICE_ERR_PARAM;
1815 
1816 	ice_acquire_lock(&hw->vsi_ctx[vsi_handle]->rss_locks);
1817 	status = ice_add_rss_cfg_sync(hw, vsi_handle, hashed_flds, addl_hdrs);
1818 	ice_release_lock(&hw->vsi_ctx[vsi_handle]->rss_locks);
1819 
1820 	return status;
1821 }
1822 
1823 /**
1824  * ice_rem_rss_cfg_sync - remove an existing RSS configuration
1825  * @hw: pointer to the hardware structure
1826  * @vsi_handle: software VSI handle
1827  * @hashed_flds: Packet hash types (ICE_FLOW_HASH_*) to remove
1828  * @addl_hdrs: Protocol header fields within a packet segment
1829  *
1830  * Assumption: lock has already been acquired for RSS list
1831  */
1832 static enum ice_status
1833 ice_rem_rss_cfg_sync(struct ice_hw *hw, u16 vsi_handle, u64 hashed_flds,
1834 		     u32 addl_hdrs)
1835 {
1836 	const enum ice_block blk = ICE_BLK_RSS;
1837 	struct ice_flow_seg_info *segs;
1838 	struct ice_flow_prof *prof;
1839 	enum ice_status status;
1840 
1841 	segs = (struct ice_flow_seg_info *)ice_malloc(hw, sizeof(*segs));
1842 	if (!segs)
1843 		return ICE_ERR_NO_MEMORY;
1844 
1845 	/* Construct the packet segment info from the hashed fields */
1846 	status = ice_flow_set_rss_seg_info(segs, hashed_flds, addl_hdrs);
1847 	if (status)
1848 		goto out;
1849 
1850 	prof = ice_flow_find_prof_conds(hw, blk, ICE_FLOW_RX, segs, 1,
1851 					vsi_handle,
1852 					ICE_FLOW_FIND_PROF_CHK_FLDS);
1853 	if (!prof) {
1854 		status = ICE_ERR_DOES_NOT_EXIST;
1855 		goto out;
1856 	}
1857 
1858 	status = ice_flow_disassoc_prof(hw, blk, prof, vsi_handle);
1859 	if (status)
1860 		goto out;
1861 
1862 	/* Remove RSS configuration from VSI context before deleting
1863 	 * the flow profile.
1864 	 */
1865 	ice_rem_rss_cfg_vsi_ctx(hw, vsi_handle, prof);
1866 
1867 	if (!ice_is_any_bit_set(prof->vsis, ICE_MAX_VSI))
1868 		status = ice_flow_rem_prof_sync(hw, blk, prof);
1869 
1870 out:
1871 	ice_free(hw, segs);
1872 	return status;
1873 }
1874 
1875 /**
1876  * ice_rem_rss_cfg - remove an existing RSS config with matching hashed fields
1877  * @hw: pointer to the hardware structure
1878  * @vsi_handle: software VSI handle
1879  * @hashed_flds: Packet hash types (ICE_FLOW_HASH_*) to remove
1880  * @addl_hdrs: Protocol header fields within a packet segment
1881  *
1882  * This function will lookup the flow profile based on the input
1883  * hash field bitmap, iterate through the profile entry list of
1884  * that profile and find entry associated with input VSI to be
1885  * removed. Calls are made to underlying flow apis which will in
1886  * turn build or update buffers for RSS XLT1 section.
1887  */
1888 enum ice_status
1889 ice_rem_rss_cfg(struct ice_hw *hw, u16 vsi_handle, u64 hashed_flds,
1890 		u32 addl_hdrs)
1891 {
1892 	enum ice_status status;
1893 
1894 	if (hashed_flds == ICE_HASH_INVALID ||
1895 	    !ice_is_vsi_valid(hw, vsi_handle))
1896 		return ICE_ERR_PARAM;
1897 
1898 	ice_acquire_lock(&hw->vsi_ctx[vsi_handle]->rss_locks);
1899 	status = ice_rem_rss_cfg_sync(hw, vsi_handle, hashed_flds, addl_hdrs);
1900 	ice_release_lock(&hw->vsi_ctx[vsi_handle]->rss_locks);
1901 
1902 	return status;
1903 }
1904 
1905 /**
1906  * ice_replay_rss_cfg - remove RSS configurations associated with VSI
1907  * @hw: pointer to the hardware structure
1908  * @vsi_handle: software VSI handle
1909  */
1910 enum ice_status ice_replay_rss_cfg(struct ice_hw *hw, u16 vsi_handle)
1911 {
1912 	enum ice_status status = ICE_SUCCESS;
1913 	struct ice_rss_cfg *r;
1914 
1915 	if (!ice_is_vsi_valid(hw, vsi_handle))
1916 		return ICE_ERR_PARAM;
1917 
1918 	ice_acquire_lock(&hw->vsi_ctx[vsi_handle]->rss_locks);
1919 	LIST_FOR_EACH_ENTRY(r, &hw->vsi_ctx[vsi_handle]->rss_list_head,
1920 			    ice_rss_cfg, l_entry) {
1921 		status = ice_add_rss_cfg_sync(hw, vsi_handle, r->hashed_flds,
1922 					      r->packet_hdr);
1923 		if (status)
1924 			break;
1925 	}
1926 	ice_release_lock(&hw->vsi_ctx[vsi_handle]->rss_locks);
1927 
1928 	return status;
1929 }
1930 
1931 /**
1932  * ice_get_rss_cfg - returns hashed fields for the given header types
1933  * @hw: pointer to the hardware structure
1934  * @vsi_handle: software VSI handle
1935  * @hdrs: protocol header type
1936  *
1937  * This function will return the match fields of the first instance of flow
1938  * profile having the given header types and containing input VSI
1939  */
1940 u64 ice_get_rss_cfg(struct ice_hw *hw, u16 vsi_handle, u32 hdrs)
1941 {
1942 	struct ice_rss_cfg *r, *rss_cfg = NULL;
1943 
1944 	/* verify if the protocol header is non zero and VSI is valid */
1945 	if (hdrs == ICE_FLOW_SEG_HDR_NONE || !ice_is_vsi_valid(hw, vsi_handle))
1946 		return ICE_HASH_INVALID;
1947 
1948 	ice_acquire_lock(&hw->vsi_ctx[vsi_handle]->rss_locks);
1949 	LIST_FOR_EACH_ENTRY(r, &hw->vsi_ctx[vsi_handle]->rss_list_head,
1950 			    ice_rss_cfg, l_entry)
1951 		if (r->packet_hdr == hdrs) {
1952 			rss_cfg = r;
1953 			break;
1954 		}
1955 	ice_release_lock(&hw->vsi_ctx[vsi_handle]->rss_locks);
1956 
1957 	return rss_cfg ? rss_cfg->hashed_flds : ICE_HASH_INVALID;
1958 }
1959