1 // SPDX-License-Identifier: GPL-2.0
2 /* Copyright (c) 2019, Intel Corporation. */
3 
4 #include "ice_common.h"
5 #include "ice_flow.h"
6 
7 /* Describe properties of a protocol header field */
8 struct ice_flow_field_info {
9 	enum ice_flow_seg_hdr hdr;
10 	s16 off;	/* Offset from start of a protocol header, in bits */
11 	u16 size;	/* Size of fields in bits */
12 };
13 
14 #define ICE_FLOW_FLD_INFO(_hdr, _offset_bytes, _size_bytes) { \
15 	.hdr = _hdr, \
16 	.off = (_offset_bytes) * BITS_PER_BYTE, \
17 	.size = (_size_bytes) * BITS_PER_BYTE, \
18 }
19 
20 /* Table containing properties of supported protocol header fields */
21 static const
22 struct ice_flow_field_info ice_flds_info[ICE_FLOW_FIELD_IDX_MAX] = {
23 	/* IPv4 / IPv6 */
24 	/* ICE_FLOW_FIELD_IDX_IPV4_SA */
25 	ICE_FLOW_FLD_INFO(ICE_FLOW_SEG_HDR_IPV4, 12, sizeof(struct in_addr)),
26 	/* ICE_FLOW_FIELD_IDX_IPV4_DA */
27 	ICE_FLOW_FLD_INFO(ICE_FLOW_SEG_HDR_IPV4, 16, sizeof(struct in_addr)),
28 	/* ICE_FLOW_FIELD_IDX_IPV6_SA */
29 	ICE_FLOW_FLD_INFO(ICE_FLOW_SEG_HDR_IPV6, 8, sizeof(struct in6_addr)),
30 	/* ICE_FLOW_FIELD_IDX_IPV6_DA */
31 	ICE_FLOW_FLD_INFO(ICE_FLOW_SEG_HDR_IPV6, 24, sizeof(struct in6_addr)),
32 	/* Transport */
33 	/* ICE_FLOW_FIELD_IDX_TCP_SRC_PORT */
34 	ICE_FLOW_FLD_INFO(ICE_FLOW_SEG_HDR_TCP, 0, sizeof(__be16)),
35 	/* ICE_FLOW_FIELD_IDX_TCP_DST_PORT */
36 	ICE_FLOW_FLD_INFO(ICE_FLOW_SEG_HDR_TCP, 2, sizeof(__be16)),
37 	/* ICE_FLOW_FIELD_IDX_UDP_SRC_PORT */
38 	ICE_FLOW_FLD_INFO(ICE_FLOW_SEG_HDR_UDP, 0, sizeof(__be16)),
39 	/* ICE_FLOW_FIELD_IDX_UDP_DST_PORT */
40 	ICE_FLOW_FLD_INFO(ICE_FLOW_SEG_HDR_UDP, 2, sizeof(__be16)),
41 	/* ICE_FLOW_FIELD_IDX_SCTP_SRC_PORT */
42 	ICE_FLOW_FLD_INFO(ICE_FLOW_SEG_HDR_SCTP, 0, sizeof(__be16)),
43 	/* ICE_FLOW_FIELD_IDX_SCTP_DST_PORT */
44 	ICE_FLOW_FLD_INFO(ICE_FLOW_SEG_HDR_SCTP, 2, sizeof(__be16)),
45 	/* GRE */
46 	/* ICE_FLOW_FIELD_IDX_GRE_KEYID */
47 	ICE_FLOW_FLD_INFO(ICE_FLOW_SEG_HDR_GRE, 12,
48 			  sizeof_field(struct gre_full_hdr, key)),
49 };
50 
51 /* Bitmaps indicating relevant packet types for a particular protocol header
52  *
53  * Packet types for packets with an Outer/First/Single IPv4 header
54  */
55 static const u32 ice_ptypes_ipv4_ofos[] = {
56 	0x1DC00000, 0x04000800, 0x00000000, 0x00000000,
57 	0x00000000, 0x00000000, 0x00000000, 0x00000000,
58 	0x00000000, 0x00000000, 0x00000000, 0x00000000,
59 	0x00000000, 0x00000000, 0x00000000, 0x00000000,
60 	0x00000000, 0x00000000, 0x00000000, 0x00000000,
61 	0x00000000, 0x00000000, 0x00000000, 0x00000000,
62 	0x00000000, 0x00000000, 0x00000000, 0x00000000,
63 	0x00000000, 0x00000000, 0x00000000, 0x00000000,
64 };
65 
66 /* Packet types for packets with an Innermost/Last IPv4 header */
67 static const u32 ice_ptypes_ipv4_il[] = {
68 	0xE0000000, 0xB807700E, 0x80000003, 0xE01DC03B,
69 	0x0000000E, 0x00000000, 0x00000000, 0x00000000,
70 	0x00000000, 0x00000000, 0x00000000, 0x00000000,
71 	0x00000000, 0x00000000, 0x00000000, 0x00000000,
72 	0x00000000, 0x00000000, 0x00000000, 0x00000000,
73 	0x00000000, 0x00000000, 0x00000000, 0x00000000,
74 	0x00000000, 0x00000000, 0x00000000, 0x00000000,
75 	0x00000000, 0x00000000, 0x00000000, 0x00000000,
76 };
77 
78 /* Packet types for packets with an Outer/First/Single IPv6 header */
79 static const u32 ice_ptypes_ipv6_ofos[] = {
80 	0x00000000, 0x00000000, 0x77000000, 0x10002000,
81 	0x00000000, 0x00000000, 0x00000000, 0x00000000,
82 	0x00000000, 0x00000000, 0x00000000, 0x00000000,
83 	0x00000000, 0x00000000, 0x00000000, 0x00000000,
84 	0x00000000, 0x00000000, 0x00000000, 0x00000000,
85 	0x00000000, 0x00000000, 0x00000000, 0x00000000,
86 	0x00000000, 0x00000000, 0x00000000, 0x00000000,
87 	0x00000000, 0x00000000, 0x00000000, 0x00000000,
88 };
89 
90 /* Packet types for packets with an Innermost/Last IPv6 header */
91 static const u32 ice_ptypes_ipv6_il[] = {
92 	0x00000000, 0x03B80770, 0x000001DC, 0x0EE00000,
93 	0x00000770, 0x00000000, 0x00000000, 0x00000000,
94 	0x00000000, 0x00000000, 0x00000000, 0x00000000,
95 	0x00000000, 0x00000000, 0x00000000, 0x00000000,
96 	0x00000000, 0x00000000, 0x00000000, 0x00000000,
97 	0x00000000, 0x00000000, 0x00000000, 0x00000000,
98 	0x00000000, 0x00000000, 0x00000000, 0x00000000,
99 	0x00000000, 0x00000000, 0x00000000, 0x00000000,
100 };
101 
102 /* Packet types for packets with an Outer/First/Single IPv4 header - no L4 */
103 static const u32 ice_ipv4_ofos_no_l4[] = {
104 	0x10C00000, 0x04000800, 0x00000000, 0x00000000,
105 	0x00000000, 0x00000000, 0x00000000, 0x00000000,
106 	0x00000000, 0x00000000, 0x00000000, 0x00000000,
107 	0x00000000, 0x00000000, 0x00000000, 0x00000000,
108 	0x00000000, 0x00000000, 0x00000000, 0x00000000,
109 	0x00000000, 0x00000000, 0x00000000, 0x00000000,
110 	0x00000000, 0x00000000, 0x00000000, 0x00000000,
111 	0x00000000, 0x00000000, 0x00000000, 0x00000000,
112 };
113 
114 /* Packet types for packets with an Innermost/Last IPv4 header - no L4 */
115 static const u32 ice_ipv4_il_no_l4[] = {
116 	0x60000000, 0x18043008, 0x80000002, 0x6010c021,
117 	0x00000008, 0x00000000, 0x00000000, 0x00000000,
118 	0x00000000, 0x00000000, 0x00000000, 0x00000000,
119 	0x00000000, 0x00000000, 0x00000000, 0x00000000,
120 	0x00000000, 0x00000000, 0x00000000, 0x00000000,
121 	0x00000000, 0x00000000, 0x00000000, 0x00000000,
122 	0x00000000, 0x00000000, 0x00000000, 0x00000000,
123 	0x00000000, 0x00000000, 0x00000000, 0x00000000,
124 };
125 
126 /* Packet types for packets with an Outer/First/Single IPv6 header - no L4 */
127 static const u32 ice_ipv6_ofos_no_l4[] = {
128 	0x00000000, 0x00000000, 0x43000000, 0x10002000,
129 	0x00000000, 0x00000000, 0x00000000, 0x00000000,
130 	0x00000000, 0x00000000, 0x00000000, 0x00000000,
131 	0x00000000, 0x00000000, 0x00000000, 0x00000000,
132 	0x00000000, 0x00000000, 0x00000000, 0x00000000,
133 	0x00000000, 0x00000000, 0x00000000, 0x00000000,
134 	0x00000000, 0x00000000, 0x00000000, 0x00000000,
135 	0x00000000, 0x00000000, 0x00000000, 0x00000000,
136 };
137 
138 /* Packet types for packets with an Innermost/Last IPv6 header - no L4 */
139 static const u32 ice_ipv6_il_no_l4[] = {
140 	0x00000000, 0x02180430, 0x0000010c, 0x086010c0,
141 	0x00000430, 0x00000000, 0x00000000, 0x00000000,
142 	0x00000000, 0x00000000, 0x00000000, 0x00000000,
143 	0x00000000, 0x00000000, 0x00000000, 0x00000000,
144 	0x00000000, 0x00000000, 0x00000000, 0x00000000,
145 	0x00000000, 0x00000000, 0x00000000, 0x00000000,
146 	0x00000000, 0x00000000, 0x00000000, 0x00000000,
147 	0x00000000, 0x00000000, 0x00000000, 0x00000000,
148 };
149 
150 /* UDP Packet types for non-tunneled packets or tunneled
151  * packets with inner UDP.
152  */
153 static const u32 ice_ptypes_udp_il[] = {
154 	0x81000000, 0x20204040, 0x04000010, 0x80810102,
155 	0x00000040, 0x00000000, 0x00000000, 0x00000000,
156 	0x00000000, 0x00000000, 0x00000000, 0x00000000,
157 	0x00000000, 0x00000000, 0x00000000, 0x00000000,
158 	0x00000000, 0x00000000, 0x00000000, 0x00000000,
159 	0x00000000, 0x00000000, 0x00000000, 0x00000000,
160 	0x00000000, 0x00000000, 0x00000000, 0x00000000,
161 	0x00000000, 0x00000000, 0x00000000, 0x00000000,
162 };
163 
164 /* Packet types for packets with an Innermost/Last TCP header */
165 static const u32 ice_ptypes_tcp_il[] = {
166 	0x04000000, 0x80810102, 0x10000040, 0x02040408,
167 	0x00000102, 0x00000000, 0x00000000, 0x00000000,
168 	0x00000000, 0x00000000, 0x00000000, 0x00000000,
169 	0x00000000, 0x00000000, 0x00000000, 0x00000000,
170 	0x00000000, 0x00000000, 0x00000000, 0x00000000,
171 	0x00000000, 0x00000000, 0x00000000, 0x00000000,
172 	0x00000000, 0x00000000, 0x00000000, 0x00000000,
173 	0x00000000, 0x00000000, 0x00000000, 0x00000000,
174 };
175 
176 /* Packet types for packets with an Innermost/Last SCTP header */
177 static const u32 ice_ptypes_sctp_il[] = {
178 	0x08000000, 0x01020204, 0x20000081, 0x04080810,
179 	0x00000204, 0x00000000, 0x00000000, 0x00000000,
180 	0x00000000, 0x00000000, 0x00000000, 0x00000000,
181 	0x00000000, 0x00000000, 0x00000000, 0x00000000,
182 	0x00000000, 0x00000000, 0x00000000, 0x00000000,
183 	0x00000000, 0x00000000, 0x00000000, 0x00000000,
184 	0x00000000, 0x00000000, 0x00000000, 0x00000000,
185 	0x00000000, 0x00000000, 0x00000000, 0x00000000,
186 };
187 
188 /* Packet types for packets with an Outermost/First GRE header */
189 static const u32 ice_ptypes_gre_of[] = {
190 	0x00000000, 0xBFBF7800, 0x000001DF, 0xFEFDE000,
191 	0x0000017E, 0x00000000, 0x00000000, 0x00000000,
192 	0x00000000, 0x00000000, 0x00000000, 0x00000000,
193 	0x00000000, 0x00000000, 0x00000000, 0x00000000,
194 	0x00000000, 0x00000000, 0x00000000, 0x00000000,
195 	0x00000000, 0x00000000, 0x00000000, 0x00000000,
196 	0x00000000, 0x00000000, 0x00000000, 0x00000000,
197 	0x00000000, 0x00000000, 0x00000000, 0x00000000,
198 };
199 
200 /* Manage parameters and info. used during the creation of a flow profile */
201 struct ice_flow_prof_params {
202 	enum ice_block blk;
203 	u16 entry_length; /* # of bytes formatted entry will require */
204 	u8 es_cnt;
205 	struct ice_flow_prof *prof;
206 
207 	/* For ACL, the es[0] will have the data of ICE_RX_MDID_PKT_FLAGS_15_0
208 	 * This will give us the direction flags.
209 	 */
210 	struct ice_fv_word es[ICE_MAX_FV_WORDS];
211 	DECLARE_BITMAP(ptypes, ICE_FLOW_PTYPE_MAX);
212 };
213 
214 #define ICE_FLOW_SEG_HDRS_L3_MASK	\
215 	(ICE_FLOW_SEG_HDR_IPV4 | ICE_FLOW_SEG_HDR_IPV6)
216 #define ICE_FLOW_SEG_HDRS_L4_MASK	\
217 	(ICE_FLOW_SEG_HDR_TCP | ICE_FLOW_SEG_HDR_UDP | ICE_FLOW_SEG_HDR_SCTP)
218 
219 /**
220  * ice_flow_val_hdrs - validates packet segments for valid protocol headers
221  * @segs: array of one or more packet segments that describe the flow
222  * @segs_cnt: number of packet segments provided
223  */
224 static enum ice_status
225 ice_flow_val_hdrs(struct ice_flow_seg_info *segs, u8 segs_cnt)
226 {
227 	u8 i;
228 
229 	for (i = 0; i < segs_cnt; i++) {
230 		/* Multiple L3 headers */
231 		if (segs[i].hdrs & ICE_FLOW_SEG_HDRS_L3_MASK &&
232 		    !is_power_of_2(segs[i].hdrs & ICE_FLOW_SEG_HDRS_L3_MASK))
233 			return ICE_ERR_PARAM;
234 
235 		/* Multiple L4 headers */
236 		if (segs[i].hdrs & ICE_FLOW_SEG_HDRS_L4_MASK &&
237 		    !is_power_of_2(segs[i].hdrs & ICE_FLOW_SEG_HDRS_L4_MASK))
238 			return ICE_ERR_PARAM;
239 	}
240 
241 	return 0;
242 }
243 
244 /* Sizes of fixed known protocol headers without header options */
245 #define ICE_FLOW_PROT_HDR_SZ_MAC	14
246 #define ICE_FLOW_PROT_HDR_SZ_IPV4	20
247 #define ICE_FLOW_PROT_HDR_SZ_IPV6	40
248 #define ICE_FLOW_PROT_HDR_SZ_TCP	20
249 #define ICE_FLOW_PROT_HDR_SZ_UDP	8
250 #define ICE_FLOW_PROT_HDR_SZ_SCTP	12
251 
252 /**
253  * ice_flow_calc_seg_sz - calculates size of a packet segment based on headers
254  * @params: information about the flow to be processed
255  * @seg: index of packet segment whose header size is to be determined
256  */
257 static u16 ice_flow_calc_seg_sz(struct ice_flow_prof_params *params, u8 seg)
258 {
259 	u16 sz = ICE_FLOW_PROT_HDR_SZ_MAC;
260 
261 	/* L3 headers */
262 	if (params->prof->segs[seg].hdrs & ICE_FLOW_SEG_HDR_IPV4)
263 		sz += ICE_FLOW_PROT_HDR_SZ_IPV4;
264 	else if (params->prof->segs[seg].hdrs & ICE_FLOW_SEG_HDR_IPV6)
265 		sz += ICE_FLOW_PROT_HDR_SZ_IPV6;
266 
267 	/* L4 headers */
268 	if (params->prof->segs[seg].hdrs & ICE_FLOW_SEG_HDR_TCP)
269 		sz += ICE_FLOW_PROT_HDR_SZ_TCP;
270 	else if (params->prof->segs[seg].hdrs & ICE_FLOW_SEG_HDR_UDP)
271 		sz += ICE_FLOW_PROT_HDR_SZ_UDP;
272 	else if (params->prof->segs[seg].hdrs & ICE_FLOW_SEG_HDR_SCTP)
273 		sz += ICE_FLOW_PROT_HDR_SZ_SCTP;
274 
275 	return sz;
276 }
277 
278 /**
279  * ice_flow_proc_seg_hdrs - process protocol headers present in pkt segments
280  * @params: information about the flow to be processed
281  *
282  * This function identifies the packet types associated with the protocol
283  * headers being present in packet segments of the specified flow profile.
284  */
285 static enum ice_status
286 ice_flow_proc_seg_hdrs(struct ice_flow_prof_params *params)
287 {
288 	struct ice_flow_prof *prof;
289 	u8 i;
290 
291 	memset(params->ptypes, 0xff, sizeof(params->ptypes));
292 
293 	prof = params->prof;
294 
295 	for (i = 0; i < params->prof->segs_cnt; i++) {
296 		const unsigned long *src;
297 		u32 hdrs;
298 
299 		hdrs = prof->segs[i].hdrs;
300 
301 		if ((hdrs & ICE_FLOW_SEG_HDR_IPV4) &&
302 		    !(hdrs & ICE_FLOW_SEG_HDRS_L4_MASK)) {
303 			src = !i ? (const unsigned long *)ice_ipv4_ofos_no_l4 :
304 				(const unsigned long *)ice_ipv4_il_no_l4;
305 			bitmap_and(params->ptypes, params->ptypes, src,
306 				   ICE_FLOW_PTYPE_MAX);
307 		} else if (hdrs & ICE_FLOW_SEG_HDR_IPV4) {
308 			src = !i ? (const unsigned long *)ice_ptypes_ipv4_ofos :
309 				(const unsigned long *)ice_ptypes_ipv4_il;
310 			bitmap_and(params->ptypes, params->ptypes, src,
311 				   ICE_FLOW_PTYPE_MAX);
312 		} else if ((hdrs & ICE_FLOW_SEG_HDR_IPV6) &&
313 			   !(hdrs & ICE_FLOW_SEG_HDRS_L4_MASK)) {
314 			src = !i ? (const unsigned long *)ice_ipv6_ofos_no_l4 :
315 				(const unsigned long *)ice_ipv6_il_no_l4;
316 			bitmap_and(params->ptypes, params->ptypes, src,
317 				   ICE_FLOW_PTYPE_MAX);
318 		} else if (hdrs & ICE_FLOW_SEG_HDR_IPV6) {
319 			src = !i ? (const unsigned long *)ice_ptypes_ipv6_ofos :
320 				(const unsigned long *)ice_ptypes_ipv6_il;
321 			bitmap_and(params->ptypes, params->ptypes, src,
322 				   ICE_FLOW_PTYPE_MAX);
323 		}
324 
325 		if (hdrs & ICE_FLOW_SEG_HDR_UDP) {
326 			src = (const unsigned long *)ice_ptypes_udp_il;
327 			bitmap_and(params->ptypes, params->ptypes, src,
328 				   ICE_FLOW_PTYPE_MAX);
329 		} else if (hdrs & ICE_FLOW_SEG_HDR_TCP) {
330 			bitmap_and(params->ptypes, params->ptypes,
331 				   (const unsigned long *)ice_ptypes_tcp_il,
332 				   ICE_FLOW_PTYPE_MAX);
333 		} else if (hdrs & ICE_FLOW_SEG_HDR_SCTP) {
334 			src = (const unsigned long *)ice_ptypes_sctp_il;
335 			bitmap_and(params->ptypes, params->ptypes, src,
336 				   ICE_FLOW_PTYPE_MAX);
337 		} else if (hdrs & ICE_FLOW_SEG_HDR_GRE) {
338 			if (!i) {
339 				src = (const unsigned long *)ice_ptypes_gre_of;
340 				bitmap_and(params->ptypes, params->ptypes,
341 					   src, ICE_FLOW_PTYPE_MAX);
342 			}
343 		}
344 	}
345 
346 	return 0;
347 }
348 
349 /**
350  * ice_flow_xtract_fld - Create an extraction sequence entry for the given field
351  * @hw: pointer to the HW struct
352  * @params: information about the flow to be processed
353  * @seg: packet segment index of the field to be extracted
354  * @fld: ID of field to be extracted
355  *
356  * This function determines the protocol ID, offset, and size of the given
357  * field. It then allocates one or more extraction sequence entries for the
358  * given field, and fill the entries with protocol ID and offset information.
359  */
360 static enum ice_status
361 ice_flow_xtract_fld(struct ice_hw *hw, struct ice_flow_prof_params *params,
362 		    u8 seg, enum ice_flow_field fld)
363 {
364 	enum ice_prot_id prot_id = ICE_PROT_ID_INVAL;
365 	u8 fv_words = hw->blk[params->blk].es.fvw;
366 	struct ice_flow_fld_info *flds;
367 	u16 cnt, ese_bits, i;
368 	u16 off;
369 
370 	flds = params->prof->segs[seg].fields;
371 
372 	switch (fld) {
373 	case ICE_FLOW_FIELD_IDX_IPV4_SA:
374 	case ICE_FLOW_FIELD_IDX_IPV4_DA:
375 		prot_id = seg == 0 ? ICE_PROT_IPV4_OF_OR_S : ICE_PROT_IPV4_IL;
376 		break;
377 	case ICE_FLOW_FIELD_IDX_IPV6_SA:
378 	case ICE_FLOW_FIELD_IDX_IPV6_DA:
379 		prot_id = seg == 0 ? ICE_PROT_IPV6_OF_OR_S : ICE_PROT_IPV6_IL;
380 		break;
381 	case ICE_FLOW_FIELD_IDX_TCP_SRC_PORT:
382 	case ICE_FLOW_FIELD_IDX_TCP_DST_PORT:
383 		prot_id = ICE_PROT_TCP_IL;
384 		break;
385 	case ICE_FLOW_FIELD_IDX_UDP_SRC_PORT:
386 	case ICE_FLOW_FIELD_IDX_UDP_DST_PORT:
387 		prot_id = ICE_PROT_UDP_IL_OR_S;
388 		break;
389 	case ICE_FLOW_FIELD_IDX_SCTP_SRC_PORT:
390 	case ICE_FLOW_FIELD_IDX_SCTP_DST_PORT:
391 		prot_id = ICE_PROT_SCTP_IL;
392 		break;
393 	case ICE_FLOW_FIELD_IDX_GRE_KEYID:
394 		prot_id = ICE_PROT_GRE_OF;
395 		break;
396 	default:
397 		return ICE_ERR_NOT_IMPL;
398 	}
399 
400 	/* Each extraction sequence entry is a word in size, and extracts a
401 	 * word-aligned offset from a protocol header.
402 	 */
403 	ese_bits = ICE_FLOW_FV_EXTRACT_SZ * BITS_PER_BYTE;
404 
405 	flds[fld].xtrct.prot_id = prot_id;
406 	flds[fld].xtrct.off = (ice_flds_info[fld].off / ese_bits) *
407 		ICE_FLOW_FV_EXTRACT_SZ;
408 	flds[fld].xtrct.disp = (u8)(ice_flds_info[fld].off % ese_bits);
409 	flds[fld].xtrct.idx = params->es_cnt;
410 
411 	/* Adjust the next field-entry index after accommodating the number of
412 	 * entries this field consumes
413 	 */
414 	cnt = DIV_ROUND_UP(flds[fld].xtrct.disp + ice_flds_info[fld].size,
415 			   ese_bits);
416 
417 	/* Fill in the extraction sequence entries needed for this field */
418 	off = flds[fld].xtrct.off;
419 	for (i = 0; i < cnt; i++) {
420 		u8 idx;
421 
422 		/* Make sure the number of extraction sequence required
423 		 * does not exceed the block's capability
424 		 */
425 		if (params->es_cnt >= fv_words)
426 			return ICE_ERR_MAX_LIMIT;
427 
428 		/* some blocks require a reversed field vector layout */
429 		if (hw->blk[params->blk].es.reverse)
430 			idx = fv_words - params->es_cnt - 1;
431 		else
432 			idx = params->es_cnt;
433 
434 		params->es[idx].prot_id = prot_id;
435 		params->es[idx].off = off;
436 		params->es_cnt++;
437 
438 		off += ICE_FLOW_FV_EXTRACT_SZ;
439 	}
440 
441 	return 0;
442 }
443 
444 /**
445  * ice_flow_xtract_raws - Create extract sequence entries for raw bytes
446  * @hw: pointer to the HW struct
447  * @params: information about the flow to be processed
448  * @seg: index of packet segment whose raw fields are to be extracted
449  */
450 static enum ice_status
451 ice_flow_xtract_raws(struct ice_hw *hw, struct ice_flow_prof_params *params,
452 		     u8 seg)
453 {
454 	u16 fv_words;
455 	u16 hdrs_sz;
456 	u8 i;
457 
458 	if (!params->prof->segs[seg].raws_cnt)
459 		return 0;
460 
461 	if (params->prof->segs[seg].raws_cnt >
462 	    ARRAY_SIZE(params->prof->segs[seg].raws))
463 		return ICE_ERR_MAX_LIMIT;
464 
465 	/* Offsets within the segment headers are not supported */
466 	hdrs_sz = ice_flow_calc_seg_sz(params, seg);
467 	if (!hdrs_sz)
468 		return ICE_ERR_PARAM;
469 
470 	fv_words = hw->blk[params->blk].es.fvw;
471 
472 	for (i = 0; i < params->prof->segs[seg].raws_cnt; i++) {
473 		struct ice_flow_seg_fld_raw *raw;
474 		u16 off, cnt, j;
475 
476 		raw = &params->prof->segs[seg].raws[i];
477 
478 		/* Storing extraction information */
479 		raw->info.xtrct.prot_id = ICE_PROT_MAC_OF_OR_S;
480 		raw->info.xtrct.off = (raw->off / ICE_FLOW_FV_EXTRACT_SZ) *
481 			ICE_FLOW_FV_EXTRACT_SZ;
482 		raw->info.xtrct.disp = (raw->off % ICE_FLOW_FV_EXTRACT_SZ) *
483 			BITS_PER_BYTE;
484 		raw->info.xtrct.idx = params->es_cnt;
485 
486 		/* Determine the number of field vector entries this raw field
487 		 * consumes.
488 		 */
489 		cnt = DIV_ROUND_UP(raw->info.xtrct.disp +
490 				   (raw->info.src.last * BITS_PER_BYTE),
491 				   (ICE_FLOW_FV_EXTRACT_SZ * BITS_PER_BYTE));
492 		off = raw->info.xtrct.off;
493 		for (j = 0; j < cnt; j++) {
494 			u16 idx;
495 
496 			/* Make sure the number of extraction sequence required
497 			 * does not exceed the block's capability
498 			 */
499 			if (params->es_cnt >= hw->blk[params->blk].es.count ||
500 			    params->es_cnt >= ICE_MAX_FV_WORDS)
501 				return ICE_ERR_MAX_LIMIT;
502 
503 			/* some blocks require a reversed field vector layout */
504 			if (hw->blk[params->blk].es.reverse)
505 				idx = fv_words - params->es_cnt - 1;
506 			else
507 				idx = params->es_cnt;
508 
509 			params->es[idx].prot_id = raw->info.xtrct.prot_id;
510 			params->es[idx].off = off;
511 			params->es_cnt++;
512 			off += ICE_FLOW_FV_EXTRACT_SZ;
513 		}
514 	}
515 
516 	return 0;
517 }
518 
519 /**
520  * ice_flow_create_xtrct_seq - Create an extraction sequence for given segments
521  * @hw: pointer to the HW struct
522  * @params: information about the flow to be processed
523  *
524  * This function iterates through all matched fields in the given segments, and
525  * creates an extraction sequence for the fields.
526  */
527 static enum ice_status
528 ice_flow_create_xtrct_seq(struct ice_hw *hw,
529 			  struct ice_flow_prof_params *params)
530 {
531 	struct ice_flow_prof *prof = params->prof;
532 	enum ice_status status = 0;
533 	u8 i;
534 
535 	for (i = 0; i < prof->segs_cnt; i++) {
536 		u8 j;
537 
538 		for_each_set_bit(j, (unsigned long *)&prof->segs[i].match,
539 				 ICE_FLOW_FIELD_IDX_MAX) {
540 			status = ice_flow_xtract_fld(hw, params, i,
541 						     (enum ice_flow_field)j);
542 			if (status)
543 				return status;
544 		}
545 
546 		/* Process raw matching bytes */
547 		status = ice_flow_xtract_raws(hw, params, i);
548 		if (status)
549 			return status;
550 	}
551 
552 	return status;
553 }
554 
555 /**
556  * ice_flow_proc_segs - process all packet segments associated with a profile
557  * @hw: pointer to the HW struct
558  * @params: information about the flow to be processed
559  */
560 static enum ice_status
561 ice_flow_proc_segs(struct ice_hw *hw, struct ice_flow_prof_params *params)
562 {
563 	enum ice_status status;
564 
565 	status = ice_flow_proc_seg_hdrs(params);
566 	if (status)
567 		return status;
568 
569 	status = ice_flow_create_xtrct_seq(hw, params);
570 	if (status)
571 		return status;
572 
573 	switch (params->blk) {
574 	case ICE_BLK_FD:
575 	case ICE_BLK_RSS:
576 		status = 0;
577 		break;
578 	default:
579 		return ICE_ERR_NOT_IMPL;
580 	}
581 
582 	return status;
583 }
584 
585 #define ICE_FLOW_FIND_PROF_CHK_FLDS	0x00000001
586 #define ICE_FLOW_FIND_PROF_CHK_VSI	0x00000002
587 #define ICE_FLOW_FIND_PROF_NOT_CHK_DIR	0x00000004
588 
589 /**
590  * ice_flow_find_prof_conds - Find a profile matching headers and conditions
591  * @hw: pointer to the HW struct
592  * @blk: classification stage
593  * @dir: flow direction
594  * @segs: array of one or more packet segments that describe the flow
595  * @segs_cnt: number of packet segments provided
596  * @vsi_handle: software VSI handle to check VSI (ICE_FLOW_FIND_PROF_CHK_VSI)
597  * @conds: additional conditions to be checked (ICE_FLOW_FIND_PROF_CHK_*)
598  */
599 static struct ice_flow_prof *
600 ice_flow_find_prof_conds(struct ice_hw *hw, enum ice_block blk,
601 			 enum ice_flow_dir dir, struct ice_flow_seg_info *segs,
602 			 u8 segs_cnt, u16 vsi_handle, u32 conds)
603 {
604 	struct ice_flow_prof *p, *prof = NULL;
605 
606 	mutex_lock(&hw->fl_profs_locks[blk]);
607 	list_for_each_entry(p, &hw->fl_profs[blk], l_entry)
608 		if ((p->dir == dir || conds & ICE_FLOW_FIND_PROF_NOT_CHK_DIR) &&
609 		    segs_cnt && segs_cnt == p->segs_cnt) {
610 			u8 i;
611 
612 			/* Check for profile-VSI association if specified */
613 			if ((conds & ICE_FLOW_FIND_PROF_CHK_VSI) &&
614 			    ice_is_vsi_valid(hw, vsi_handle) &&
615 			    !test_bit(vsi_handle, p->vsis))
616 				continue;
617 
618 			/* Protocol headers must be checked. Matched fields are
619 			 * checked if specified.
620 			 */
621 			for (i = 0; i < segs_cnt; i++)
622 				if (segs[i].hdrs != p->segs[i].hdrs ||
623 				    ((conds & ICE_FLOW_FIND_PROF_CHK_FLDS) &&
624 				     segs[i].match != p->segs[i].match))
625 					break;
626 
627 			/* A match is found if all segments are matched */
628 			if (i == segs_cnt) {
629 				prof = p;
630 				break;
631 			}
632 		}
633 	mutex_unlock(&hw->fl_profs_locks[blk]);
634 
635 	return prof;
636 }
637 
638 /**
639  * ice_flow_find_prof_id - Look up a profile with given profile ID
640  * @hw: pointer to the HW struct
641  * @blk: classification stage
642  * @prof_id: unique ID to identify this flow profile
643  */
644 static struct ice_flow_prof *
645 ice_flow_find_prof_id(struct ice_hw *hw, enum ice_block blk, u64 prof_id)
646 {
647 	struct ice_flow_prof *p;
648 
649 	list_for_each_entry(p, &hw->fl_profs[blk], l_entry)
650 		if (p->id == prof_id)
651 			return p;
652 
653 	return NULL;
654 }
655 
656 /**
657  * ice_dealloc_flow_entry - Deallocate flow entry memory
658  * @hw: pointer to the HW struct
659  * @entry: flow entry to be removed
660  */
661 static void
662 ice_dealloc_flow_entry(struct ice_hw *hw, struct ice_flow_entry *entry)
663 {
664 	if (!entry)
665 		return;
666 
667 	if (entry->entry)
668 		devm_kfree(ice_hw_to_dev(hw), entry->entry);
669 
670 	devm_kfree(ice_hw_to_dev(hw), entry);
671 }
672 
673 /**
674  * ice_flow_rem_entry_sync - Remove a flow entry
675  * @hw: pointer to the HW struct
676  * @blk: classification stage
677  * @entry: flow entry to be removed
678  */
679 static enum ice_status
680 ice_flow_rem_entry_sync(struct ice_hw *hw, enum ice_block __always_unused blk,
681 			struct ice_flow_entry *entry)
682 {
683 	if (!entry)
684 		return ICE_ERR_BAD_PTR;
685 
686 	list_del(&entry->l_entry);
687 
688 	ice_dealloc_flow_entry(hw, entry);
689 
690 	return 0;
691 }
692 
693 /**
694  * ice_flow_add_prof_sync - Add a flow profile for packet segments and fields
695  * @hw: pointer to the HW struct
696  * @blk: classification stage
697  * @dir: flow direction
698  * @prof_id: unique ID to identify this flow profile
699  * @segs: array of one or more packet segments that describe the flow
700  * @segs_cnt: number of packet segments provided
701  * @prof: stores the returned flow profile added
702  *
703  * Assumption: the caller has acquired the lock to the profile list
704  */
705 static enum ice_status
706 ice_flow_add_prof_sync(struct ice_hw *hw, enum ice_block blk,
707 		       enum ice_flow_dir dir, u64 prof_id,
708 		       struct ice_flow_seg_info *segs, u8 segs_cnt,
709 		       struct ice_flow_prof **prof)
710 {
711 	struct ice_flow_prof_params *params;
712 	enum ice_status status;
713 	u8 i;
714 
715 	if (!prof)
716 		return ICE_ERR_BAD_PTR;
717 
718 	params = kzalloc(sizeof(*params), GFP_KERNEL);
719 	if (!params)
720 		return ICE_ERR_NO_MEMORY;
721 
722 	params->prof = devm_kzalloc(ice_hw_to_dev(hw), sizeof(*params->prof),
723 				    GFP_KERNEL);
724 	if (!params->prof) {
725 		status = ICE_ERR_NO_MEMORY;
726 		goto free_params;
727 	}
728 
729 	/* initialize extraction sequence to all invalid (0xff) */
730 	for (i = 0; i < ICE_MAX_FV_WORDS; i++) {
731 		params->es[i].prot_id = ICE_PROT_INVALID;
732 		params->es[i].off = ICE_FV_OFFSET_INVAL;
733 	}
734 
735 	params->blk = blk;
736 	params->prof->id = prof_id;
737 	params->prof->dir = dir;
738 	params->prof->segs_cnt = segs_cnt;
739 
740 	/* Make a copy of the segments that need to be persistent in the flow
741 	 * profile instance
742 	 */
743 	for (i = 0; i < segs_cnt; i++)
744 		memcpy(&params->prof->segs[i], &segs[i], sizeof(*segs));
745 
746 	status = ice_flow_proc_segs(hw, params);
747 	if (status) {
748 		ice_debug(hw, ICE_DBG_FLOW, "Error processing a flow's packet segments\n");
749 		goto out;
750 	}
751 
752 	/* Add a HW profile for this flow profile */
753 	status = ice_add_prof(hw, blk, prof_id, (u8 *)params->ptypes,
754 			      params->es);
755 	if (status) {
756 		ice_debug(hw, ICE_DBG_FLOW, "Error adding a HW flow profile\n");
757 		goto out;
758 	}
759 
760 	INIT_LIST_HEAD(&params->prof->entries);
761 	mutex_init(&params->prof->entries_lock);
762 	*prof = params->prof;
763 
764 out:
765 	if (status)
766 		devm_kfree(ice_hw_to_dev(hw), params->prof);
767 free_params:
768 	kfree(params);
769 
770 	return status;
771 }
772 
773 /**
774  * ice_flow_rem_prof_sync - remove a flow profile
775  * @hw: pointer to the hardware structure
776  * @blk: classification stage
777  * @prof: pointer to flow profile to remove
778  *
779  * Assumption: the caller has acquired the lock to the profile list
780  */
781 static enum ice_status
782 ice_flow_rem_prof_sync(struct ice_hw *hw, enum ice_block blk,
783 		       struct ice_flow_prof *prof)
784 {
785 	enum ice_status status;
786 
787 	/* Remove all remaining flow entries before removing the flow profile */
788 	if (!list_empty(&prof->entries)) {
789 		struct ice_flow_entry *e, *t;
790 
791 		mutex_lock(&prof->entries_lock);
792 
793 		list_for_each_entry_safe(e, t, &prof->entries, l_entry) {
794 			status = ice_flow_rem_entry_sync(hw, blk, e);
795 			if (status)
796 				break;
797 		}
798 
799 		mutex_unlock(&prof->entries_lock);
800 	}
801 
802 	/* Remove all hardware profiles associated with this flow profile */
803 	status = ice_rem_prof(hw, blk, prof->id);
804 	if (!status) {
805 		list_del(&prof->l_entry);
806 		mutex_destroy(&prof->entries_lock);
807 		devm_kfree(ice_hw_to_dev(hw), prof);
808 	}
809 
810 	return status;
811 }
812 
813 /**
814  * ice_flow_assoc_prof - associate a VSI with a flow profile
815  * @hw: pointer to the hardware structure
816  * @blk: classification stage
817  * @prof: pointer to flow profile
818  * @vsi_handle: software VSI handle
819  *
820  * Assumption: the caller has acquired the lock to the profile list
821  * and the software VSI handle has been validated
822  */
823 static enum ice_status
824 ice_flow_assoc_prof(struct ice_hw *hw, enum ice_block blk,
825 		    struct ice_flow_prof *prof, u16 vsi_handle)
826 {
827 	enum ice_status status = 0;
828 
829 	if (!test_bit(vsi_handle, prof->vsis)) {
830 		status = ice_add_prof_id_flow(hw, blk,
831 					      ice_get_hw_vsi_num(hw,
832 								 vsi_handle),
833 					      prof->id);
834 		if (!status)
835 			set_bit(vsi_handle, prof->vsis);
836 		else
837 			ice_debug(hw, ICE_DBG_FLOW, "HW profile add failed, %d\n",
838 				  status);
839 	}
840 
841 	return status;
842 }
843 
844 /**
845  * ice_flow_disassoc_prof - disassociate a VSI from a flow profile
846  * @hw: pointer to the hardware structure
847  * @blk: classification stage
848  * @prof: pointer to flow profile
849  * @vsi_handle: software VSI handle
850  *
851  * Assumption: the caller has acquired the lock to the profile list
852  * and the software VSI handle has been validated
853  */
854 static enum ice_status
855 ice_flow_disassoc_prof(struct ice_hw *hw, enum ice_block blk,
856 		       struct ice_flow_prof *prof, u16 vsi_handle)
857 {
858 	enum ice_status status = 0;
859 
860 	if (test_bit(vsi_handle, prof->vsis)) {
861 		status = ice_rem_prof_id_flow(hw, blk,
862 					      ice_get_hw_vsi_num(hw,
863 								 vsi_handle),
864 					      prof->id);
865 		if (!status)
866 			clear_bit(vsi_handle, prof->vsis);
867 		else
868 			ice_debug(hw, ICE_DBG_FLOW, "HW profile remove failed, %d\n",
869 				  status);
870 	}
871 
872 	return status;
873 }
874 
875 /**
876  * ice_flow_add_prof - Add a flow profile for packet segments and matched fields
877  * @hw: pointer to the HW struct
878  * @blk: classification stage
879  * @dir: flow direction
880  * @prof_id: unique ID to identify this flow profile
881  * @segs: array of one or more packet segments that describe the flow
882  * @segs_cnt: number of packet segments provided
883  * @prof: stores the returned flow profile added
884  */
885 enum ice_status
886 ice_flow_add_prof(struct ice_hw *hw, enum ice_block blk, enum ice_flow_dir dir,
887 		  u64 prof_id, struct ice_flow_seg_info *segs, u8 segs_cnt,
888 		  struct ice_flow_prof **prof)
889 {
890 	enum ice_status status;
891 
892 	if (segs_cnt > ICE_FLOW_SEG_MAX)
893 		return ICE_ERR_MAX_LIMIT;
894 
895 	if (!segs_cnt)
896 		return ICE_ERR_PARAM;
897 
898 	if (!segs)
899 		return ICE_ERR_BAD_PTR;
900 
901 	status = ice_flow_val_hdrs(segs, segs_cnt);
902 	if (status)
903 		return status;
904 
905 	mutex_lock(&hw->fl_profs_locks[blk]);
906 
907 	status = ice_flow_add_prof_sync(hw, blk, dir, prof_id, segs, segs_cnt,
908 					prof);
909 	if (!status)
910 		list_add(&(*prof)->l_entry, &hw->fl_profs[blk]);
911 
912 	mutex_unlock(&hw->fl_profs_locks[blk]);
913 
914 	return status;
915 }
916 
917 /**
918  * ice_flow_rem_prof - Remove a flow profile and all entries associated with it
919  * @hw: pointer to the HW struct
920  * @blk: the block for which the flow profile is to be removed
921  * @prof_id: unique ID of the flow profile to be removed
922  */
923 enum ice_status
924 ice_flow_rem_prof(struct ice_hw *hw, enum ice_block blk, u64 prof_id)
925 {
926 	struct ice_flow_prof *prof;
927 	enum ice_status status;
928 
929 	mutex_lock(&hw->fl_profs_locks[blk]);
930 
931 	prof = ice_flow_find_prof_id(hw, blk, prof_id);
932 	if (!prof) {
933 		status = ICE_ERR_DOES_NOT_EXIST;
934 		goto out;
935 	}
936 
937 	/* prof becomes invalid after the call */
938 	status = ice_flow_rem_prof_sync(hw, blk, prof);
939 
940 out:
941 	mutex_unlock(&hw->fl_profs_locks[blk]);
942 
943 	return status;
944 }
945 
946 /**
947  * ice_flow_add_entry - Add a flow entry
948  * @hw: pointer to the HW struct
949  * @blk: classification stage
950  * @prof_id: ID of the profile to add a new flow entry to
951  * @entry_id: unique ID to identify this flow entry
952  * @vsi_handle: software VSI handle for the flow entry
953  * @prio: priority of the flow entry
954  * @data: pointer to a data buffer containing flow entry's match values/masks
955  * @entry_h: pointer to buffer that receives the new flow entry's handle
956  */
957 enum ice_status
958 ice_flow_add_entry(struct ice_hw *hw, enum ice_block blk, u64 prof_id,
959 		   u64 entry_id, u16 vsi_handle, enum ice_flow_priority prio,
960 		   void *data, u64 *entry_h)
961 {
962 	struct ice_flow_entry *e = NULL;
963 	struct ice_flow_prof *prof;
964 	enum ice_status status;
965 
966 	/* No flow entry data is expected for RSS */
967 	if (!entry_h || (!data && blk != ICE_BLK_RSS))
968 		return ICE_ERR_BAD_PTR;
969 
970 	if (!ice_is_vsi_valid(hw, vsi_handle))
971 		return ICE_ERR_PARAM;
972 
973 	mutex_lock(&hw->fl_profs_locks[blk]);
974 
975 	prof = ice_flow_find_prof_id(hw, blk, prof_id);
976 	if (!prof) {
977 		status = ICE_ERR_DOES_NOT_EXIST;
978 	} else {
979 		/* Allocate memory for the entry being added and associate
980 		 * the VSI to the found flow profile
981 		 */
982 		e = devm_kzalloc(ice_hw_to_dev(hw), sizeof(*e), GFP_KERNEL);
983 		if (!e)
984 			status = ICE_ERR_NO_MEMORY;
985 		else
986 			status = ice_flow_assoc_prof(hw, blk, prof, vsi_handle);
987 	}
988 
989 	mutex_unlock(&hw->fl_profs_locks[blk]);
990 	if (status)
991 		goto out;
992 
993 	e->id = entry_id;
994 	e->vsi_handle = vsi_handle;
995 	e->prof = prof;
996 	e->priority = prio;
997 
998 	switch (blk) {
999 	case ICE_BLK_FD:
1000 	case ICE_BLK_RSS:
1001 		break;
1002 	default:
1003 		status = ICE_ERR_NOT_IMPL;
1004 		goto out;
1005 	}
1006 
1007 	mutex_lock(&prof->entries_lock);
1008 	list_add(&e->l_entry, &prof->entries);
1009 	mutex_unlock(&prof->entries_lock);
1010 
1011 	*entry_h = ICE_FLOW_ENTRY_HNDL(e);
1012 
1013 out:
1014 	if (status && e) {
1015 		if (e->entry)
1016 			devm_kfree(ice_hw_to_dev(hw), e->entry);
1017 		devm_kfree(ice_hw_to_dev(hw), e);
1018 	}
1019 
1020 	return status;
1021 }
1022 
1023 /**
1024  * ice_flow_rem_entry - Remove a flow entry
1025  * @hw: pointer to the HW struct
1026  * @blk: classification stage
1027  * @entry_h: handle to the flow entry to be removed
1028  */
1029 enum ice_status ice_flow_rem_entry(struct ice_hw *hw, enum ice_block blk,
1030 				   u64 entry_h)
1031 {
1032 	struct ice_flow_entry *entry;
1033 	struct ice_flow_prof *prof;
1034 	enum ice_status status = 0;
1035 
1036 	if (entry_h == ICE_FLOW_ENTRY_HANDLE_INVAL)
1037 		return ICE_ERR_PARAM;
1038 
1039 	entry = ICE_FLOW_ENTRY_PTR(entry_h);
1040 
1041 	/* Retain the pointer to the flow profile as the entry will be freed */
1042 	prof = entry->prof;
1043 
1044 	if (prof) {
1045 		mutex_lock(&prof->entries_lock);
1046 		status = ice_flow_rem_entry_sync(hw, blk, entry);
1047 		mutex_unlock(&prof->entries_lock);
1048 	}
1049 
1050 	return status;
1051 }
1052 
1053 /**
1054  * ice_flow_set_fld_ext - specifies locations of field from entry's input buffer
1055  * @seg: packet segment the field being set belongs to
1056  * @fld: field to be set
1057  * @field_type: type of the field
1058  * @val_loc: if not ICE_FLOW_FLD_OFF_INVAL, location of the value to match from
1059  *           entry's input buffer
1060  * @mask_loc: if not ICE_FLOW_FLD_OFF_INVAL, location of mask value from entry's
1061  *            input buffer
1062  * @last_loc: if not ICE_FLOW_FLD_OFF_INVAL, location of last/upper value from
1063  *            entry's input buffer
1064  *
1065  * This helper function stores information of a field being matched, including
1066  * the type of the field and the locations of the value to match, the mask, and
1067  * the upper-bound value in the start of the input buffer for a flow entry.
1068  * This function should only be used for fixed-size data structures.
1069  *
1070  * This function also opportunistically determines the protocol headers to be
1071  * present based on the fields being set. Some fields cannot be used alone to
1072  * determine the protocol headers present. Sometimes, fields for particular
1073  * protocol headers are not matched. In those cases, the protocol headers
1074  * must be explicitly set.
1075  */
1076 static void
1077 ice_flow_set_fld_ext(struct ice_flow_seg_info *seg, enum ice_flow_field fld,
1078 		     enum ice_flow_fld_match_type field_type, u16 val_loc,
1079 		     u16 mask_loc, u16 last_loc)
1080 {
1081 	u64 bit = BIT_ULL(fld);
1082 
1083 	seg->match |= bit;
1084 	if (field_type == ICE_FLOW_FLD_TYPE_RANGE)
1085 		seg->range |= bit;
1086 
1087 	seg->fields[fld].type = field_type;
1088 	seg->fields[fld].src.val = val_loc;
1089 	seg->fields[fld].src.mask = mask_loc;
1090 	seg->fields[fld].src.last = last_loc;
1091 
1092 	ICE_FLOW_SET_HDRS(seg, ice_flds_info[fld].hdr);
1093 }
1094 
1095 /**
1096  * ice_flow_set_fld - specifies locations of field from entry's input buffer
1097  * @seg: packet segment the field being set belongs to
1098  * @fld: field to be set
1099  * @val_loc: if not ICE_FLOW_FLD_OFF_INVAL, location of the value to match from
1100  *           entry's input buffer
1101  * @mask_loc: if not ICE_FLOW_FLD_OFF_INVAL, location of mask value from entry's
1102  *            input buffer
1103  * @last_loc: if not ICE_FLOW_FLD_OFF_INVAL, location of last/upper value from
1104  *            entry's input buffer
1105  * @range: indicate if field being matched is to be in a range
1106  *
1107  * This function specifies the locations, in the form of byte offsets from the
1108  * start of the input buffer for a flow entry, from where the value to match,
1109  * the mask value, and upper value can be extracted. These locations are then
1110  * stored in the flow profile. When adding a flow entry associated with the
1111  * flow profile, these locations will be used to quickly extract the values and
1112  * create the content of a match entry. This function should only be used for
1113  * fixed-size data structures.
1114  */
1115 void
1116 ice_flow_set_fld(struct ice_flow_seg_info *seg, enum ice_flow_field fld,
1117 		 u16 val_loc, u16 mask_loc, u16 last_loc, bool range)
1118 {
1119 	enum ice_flow_fld_match_type t = range ?
1120 		ICE_FLOW_FLD_TYPE_RANGE : ICE_FLOW_FLD_TYPE_REG;
1121 
1122 	ice_flow_set_fld_ext(seg, fld, t, val_loc, mask_loc, last_loc);
1123 }
1124 
1125 /**
1126  * ice_flow_add_fld_raw - sets locations of a raw field from entry's input buf
1127  * @seg: packet segment the field being set belongs to
1128  * @off: offset of the raw field from the beginning of the segment in bytes
1129  * @len: length of the raw pattern to be matched
1130  * @val_loc: location of the value to match from entry's input buffer
1131  * @mask_loc: location of mask value from entry's input buffer
1132  *
1133  * This function specifies the offset of the raw field to be match from the
1134  * beginning of the specified packet segment, and the locations, in the form of
1135  * byte offsets from the start of the input buffer for a flow entry, from where
1136  * the value to match and the mask value to be extracted. These locations are
1137  * then stored in the flow profile. When adding flow entries to the associated
1138  * flow profile, these locations can be used to quickly extract the values to
1139  * create the content of a match entry. This function should only be used for
1140  * fixed-size data structures.
1141  */
1142 void
1143 ice_flow_add_fld_raw(struct ice_flow_seg_info *seg, u16 off, u8 len,
1144 		     u16 val_loc, u16 mask_loc)
1145 {
1146 	if (seg->raws_cnt < ICE_FLOW_SEG_RAW_FLD_MAX) {
1147 		seg->raws[seg->raws_cnt].off = off;
1148 		seg->raws[seg->raws_cnt].info.type = ICE_FLOW_FLD_TYPE_SIZE;
1149 		seg->raws[seg->raws_cnt].info.src.val = val_loc;
1150 		seg->raws[seg->raws_cnt].info.src.mask = mask_loc;
1151 		/* The "last" field is used to store the length of the field */
1152 		seg->raws[seg->raws_cnt].info.src.last = len;
1153 	}
1154 
1155 	/* Overflows of "raws" will be handled as an error condition later in
1156 	 * the flow when this information is processed.
1157 	 */
1158 	seg->raws_cnt++;
1159 }
1160 
1161 #define ICE_FLOW_RSS_SEG_HDR_L3_MASKS \
1162 	(ICE_FLOW_SEG_HDR_IPV4 | ICE_FLOW_SEG_HDR_IPV6)
1163 
1164 #define ICE_FLOW_RSS_SEG_HDR_L4_MASKS \
1165 	(ICE_FLOW_SEG_HDR_TCP | ICE_FLOW_SEG_HDR_UDP | ICE_FLOW_SEG_HDR_SCTP)
1166 
1167 #define ICE_FLOW_RSS_SEG_HDR_VAL_MASKS \
1168 	(ICE_FLOW_RSS_SEG_HDR_L3_MASKS | \
1169 	 ICE_FLOW_RSS_SEG_HDR_L4_MASKS)
1170 
1171 /**
1172  * ice_flow_set_rss_seg_info - setup packet segments for RSS
1173  * @segs: pointer to the flow field segment(s)
1174  * @hash_fields: fields to be hashed on for the segment(s)
1175  * @flow_hdr: protocol header fields within a packet segment
1176  *
1177  * Helper function to extract fields from hash bitmap and use flow
1178  * header value to set flow field segment for further use in flow
1179  * profile entry or removal.
1180  */
1181 static enum ice_status
1182 ice_flow_set_rss_seg_info(struct ice_flow_seg_info *segs, u64 hash_fields,
1183 			  u32 flow_hdr)
1184 {
1185 	u64 val;
1186 	u8 i;
1187 
1188 	for_each_set_bit(i, (unsigned long *)&hash_fields,
1189 			 ICE_FLOW_FIELD_IDX_MAX)
1190 		ice_flow_set_fld(segs, (enum ice_flow_field)i,
1191 				 ICE_FLOW_FLD_OFF_INVAL, ICE_FLOW_FLD_OFF_INVAL,
1192 				 ICE_FLOW_FLD_OFF_INVAL, false);
1193 
1194 	ICE_FLOW_SET_HDRS(segs, flow_hdr);
1195 
1196 	if (segs->hdrs & ~ICE_FLOW_RSS_SEG_HDR_VAL_MASKS)
1197 		return ICE_ERR_PARAM;
1198 
1199 	val = (u64)(segs->hdrs & ICE_FLOW_RSS_SEG_HDR_L3_MASKS);
1200 	if (val && !is_power_of_2(val))
1201 		return ICE_ERR_CFG;
1202 
1203 	val = (u64)(segs->hdrs & ICE_FLOW_RSS_SEG_HDR_L4_MASKS);
1204 	if (val && !is_power_of_2(val))
1205 		return ICE_ERR_CFG;
1206 
1207 	return 0;
1208 }
1209 
1210 /**
1211  * ice_rem_vsi_rss_list - remove VSI from RSS list
1212  * @hw: pointer to the hardware structure
1213  * @vsi_handle: software VSI handle
1214  *
1215  * Remove the VSI from all RSS configurations in the list.
1216  */
1217 void ice_rem_vsi_rss_list(struct ice_hw *hw, u16 vsi_handle)
1218 {
1219 	struct ice_rss_cfg *r, *tmp;
1220 
1221 	if (list_empty(&hw->rss_list_head))
1222 		return;
1223 
1224 	mutex_lock(&hw->rss_locks);
1225 	list_for_each_entry_safe(r, tmp, &hw->rss_list_head, l_entry)
1226 		if (test_and_clear_bit(vsi_handle, r->vsis))
1227 			if (bitmap_empty(r->vsis, ICE_MAX_VSI)) {
1228 				list_del(&r->l_entry);
1229 				devm_kfree(ice_hw_to_dev(hw), r);
1230 			}
1231 	mutex_unlock(&hw->rss_locks);
1232 }
1233 
1234 /**
1235  * ice_rem_vsi_rss_cfg - remove RSS configurations associated with VSI
1236  * @hw: pointer to the hardware structure
1237  * @vsi_handle: software VSI handle
1238  *
1239  * This function will iterate through all flow profiles and disassociate
1240  * the VSI from that profile. If the flow profile has no VSIs it will
1241  * be removed.
1242  */
1243 enum ice_status ice_rem_vsi_rss_cfg(struct ice_hw *hw, u16 vsi_handle)
1244 {
1245 	const enum ice_block blk = ICE_BLK_RSS;
1246 	struct ice_flow_prof *p, *t;
1247 	enum ice_status status = 0;
1248 
1249 	if (!ice_is_vsi_valid(hw, vsi_handle))
1250 		return ICE_ERR_PARAM;
1251 
1252 	if (list_empty(&hw->fl_profs[blk]))
1253 		return 0;
1254 
1255 	mutex_lock(&hw->rss_locks);
1256 	list_for_each_entry_safe(p, t, &hw->fl_profs[blk], l_entry)
1257 		if (test_bit(vsi_handle, p->vsis)) {
1258 			status = ice_flow_disassoc_prof(hw, blk, p, vsi_handle);
1259 			if (status)
1260 				break;
1261 
1262 			if (bitmap_empty(p->vsis, ICE_MAX_VSI)) {
1263 				status = ice_flow_rem_prof(hw, blk, p->id);
1264 				if (status)
1265 					break;
1266 			}
1267 		}
1268 	mutex_unlock(&hw->rss_locks);
1269 
1270 	return status;
1271 }
1272 
1273 /**
1274  * ice_rem_rss_list - remove RSS configuration from list
1275  * @hw: pointer to the hardware structure
1276  * @vsi_handle: software VSI handle
1277  * @prof: pointer to flow profile
1278  *
1279  * Assumption: lock has already been acquired for RSS list
1280  */
1281 static void
1282 ice_rem_rss_list(struct ice_hw *hw, u16 vsi_handle, struct ice_flow_prof *prof)
1283 {
1284 	struct ice_rss_cfg *r, *tmp;
1285 
1286 	/* Search for RSS hash fields associated to the VSI that match the
1287 	 * hash configurations associated to the flow profile. If found
1288 	 * remove from the RSS entry list of the VSI context and delete entry.
1289 	 */
1290 	list_for_each_entry_safe(r, tmp, &hw->rss_list_head, l_entry)
1291 		if (r->hashed_flds == prof->segs[prof->segs_cnt - 1].match &&
1292 		    r->packet_hdr == prof->segs[prof->segs_cnt - 1].hdrs) {
1293 			clear_bit(vsi_handle, r->vsis);
1294 			if (bitmap_empty(r->vsis, ICE_MAX_VSI)) {
1295 				list_del(&r->l_entry);
1296 				devm_kfree(ice_hw_to_dev(hw), r);
1297 			}
1298 			return;
1299 		}
1300 }
1301 
1302 /**
1303  * ice_add_rss_list - add RSS configuration to list
1304  * @hw: pointer to the hardware structure
1305  * @vsi_handle: software VSI handle
1306  * @prof: pointer to flow profile
1307  *
1308  * Assumption: lock has already been acquired for RSS list
1309  */
1310 static enum ice_status
1311 ice_add_rss_list(struct ice_hw *hw, u16 vsi_handle, struct ice_flow_prof *prof)
1312 {
1313 	struct ice_rss_cfg *r, *rss_cfg;
1314 
1315 	list_for_each_entry(r, &hw->rss_list_head, l_entry)
1316 		if (r->hashed_flds == prof->segs[prof->segs_cnt - 1].match &&
1317 		    r->packet_hdr == prof->segs[prof->segs_cnt - 1].hdrs) {
1318 			set_bit(vsi_handle, r->vsis);
1319 			return 0;
1320 		}
1321 
1322 	rss_cfg = devm_kzalloc(ice_hw_to_dev(hw), sizeof(*rss_cfg),
1323 			       GFP_KERNEL);
1324 	if (!rss_cfg)
1325 		return ICE_ERR_NO_MEMORY;
1326 
1327 	rss_cfg->hashed_flds = prof->segs[prof->segs_cnt - 1].match;
1328 	rss_cfg->packet_hdr = prof->segs[prof->segs_cnt - 1].hdrs;
1329 	set_bit(vsi_handle, rss_cfg->vsis);
1330 
1331 	list_add_tail(&rss_cfg->l_entry, &hw->rss_list_head);
1332 
1333 	return 0;
1334 }
1335 
1336 #define ICE_FLOW_PROF_HASH_S	0
1337 #define ICE_FLOW_PROF_HASH_M	(0xFFFFFFFFULL << ICE_FLOW_PROF_HASH_S)
1338 #define ICE_FLOW_PROF_HDR_S	32
1339 #define ICE_FLOW_PROF_HDR_M	(0x3FFFFFFFULL << ICE_FLOW_PROF_HDR_S)
1340 #define ICE_FLOW_PROF_ENCAP_S	63
1341 #define ICE_FLOW_PROF_ENCAP_M	(BIT_ULL(ICE_FLOW_PROF_ENCAP_S))
1342 
1343 #define ICE_RSS_OUTER_HEADERS	1
1344 #define ICE_RSS_INNER_HEADERS	2
1345 
1346 /* Flow profile ID format:
1347  * [0:31] - Packet match fields
1348  * [32:62] - Protocol header
1349  * [63] - Encapsulation flag, 0 if non-tunneled, 1 if tunneled
1350  */
1351 #define ICE_FLOW_GEN_PROFID(hash, hdr, segs_cnt) \
1352 	(u64)(((u64)(hash) & ICE_FLOW_PROF_HASH_M) | \
1353 	      (((u64)(hdr) << ICE_FLOW_PROF_HDR_S) & ICE_FLOW_PROF_HDR_M) | \
1354 	      ((u8)((segs_cnt) - 1) ? ICE_FLOW_PROF_ENCAP_M : 0))
1355 
1356 /**
1357  * ice_add_rss_cfg_sync - add an RSS configuration
1358  * @hw: pointer to the hardware structure
1359  * @vsi_handle: software VSI handle
1360  * @hashed_flds: hash bit fields (ICE_FLOW_HASH_*) to configure
1361  * @addl_hdrs: protocol header fields
1362  * @segs_cnt: packet segment count
1363  *
1364  * Assumption: lock has already been acquired for RSS list
1365  */
1366 static enum ice_status
1367 ice_add_rss_cfg_sync(struct ice_hw *hw, u16 vsi_handle, u64 hashed_flds,
1368 		     u32 addl_hdrs, u8 segs_cnt)
1369 {
1370 	const enum ice_block blk = ICE_BLK_RSS;
1371 	struct ice_flow_prof *prof = NULL;
1372 	struct ice_flow_seg_info *segs;
1373 	enum ice_status status;
1374 
1375 	if (!segs_cnt || segs_cnt > ICE_FLOW_SEG_MAX)
1376 		return ICE_ERR_PARAM;
1377 
1378 	segs = kcalloc(segs_cnt, sizeof(*segs), GFP_KERNEL);
1379 	if (!segs)
1380 		return ICE_ERR_NO_MEMORY;
1381 
1382 	/* Construct the packet segment info from the hashed fields */
1383 	status = ice_flow_set_rss_seg_info(&segs[segs_cnt - 1], hashed_flds,
1384 					   addl_hdrs);
1385 	if (status)
1386 		goto exit;
1387 
1388 	/* Search for a flow profile that has matching headers, hash fields
1389 	 * and has the input VSI associated to it. If found, no further
1390 	 * operations required and exit.
1391 	 */
1392 	prof = ice_flow_find_prof_conds(hw, blk, ICE_FLOW_RX, segs, segs_cnt,
1393 					vsi_handle,
1394 					ICE_FLOW_FIND_PROF_CHK_FLDS |
1395 					ICE_FLOW_FIND_PROF_CHK_VSI);
1396 	if (prof)
1397 		goto exit;
1398 
1399 	/* Check if a flow profile exists with the same protocol headers and
1400 	 * associated with the input VSI. If so disassociate the VSI from
1401 	 * this profile. The VSI will be added to a new profile created with
1402 	 * the protocol header and new hash field configuration.
1403 	 */
1404 	prof = ice_flow_find_prof_conds(hw, blk, ICE_FLOW_RX, segs, segs_cnt,
1405 					vsi_handle, ICE_FLOW_FIND_PROF_CHK_VSI);
1406 	if (prof) {
1407 		status = ice_flow_disassoc_prof(hw, blk, prof, vsi_handle);
1408 		if (!status)
1409 			ice_rem_rss_list(hw, vsi_handle, prof);
1410 		else
1411 			goto exit;
1412 
1413 		/* Remove profile if it has no VSIs associated */
1414 		if (bitmap_empty(prof->vsis, ICE_MAX_VSI)) {
1415 			status = ice_flow_rem_prof(hw, blk, prof->id);
1416 			if (status)
1417 				goto exit;
1418 		}
1419 	}
1420 
1421 	/* Search for a profile that has same match fields only. If this
1422 	 * exists then associate the VSI to this profile.
1423 	 */
1424 	prof = ice_flow_find_prof_conds(hw, blk, ICE_FLOW_RX, segs, segs_cnt,
1425 					vsi_handle,
1426 					ICE_FLOW_FIND_PROF_CHK_FLDS);
1427 	if (prof) {
1428 		status = ice_flow_assoc_prof(hw, blk, prof, vsi_handle);
1429 		if (!status)
1430 			status = ice_add_rss_list(hw, vsi_handle, prof);
1431 		goto exit;
1432 	}
1433 
1434 	/* Create a new flow profile with generated profile and packet
1435 	 * segment information.
1436 	 */
1437 	status = ice_flow_add_prof(hw, blk, ICE_FLOW_RX,
1438 				   ICE_FLOW_GEN_PROFID(hashed_flds,
1439 						       segs[segs_cnt - 1].hdrs,
1440 						       segs_cnt),
1441 				   segs, segs_cnt, &prof);
1442 	if (status)
1443 		goto exit;
1444 
1445 	status = ice_flow_assoc_prof(hw, blk, prof, vsi_handle);
1446 	/* If association to a new flow profile failed then this profile can
1447 	 * be removed.
1448 	 */
1449 	if (status) {
1450 		ice_flow_rem_prof(hw, blk, prof->id);
1451 		goto exit;
1452 	}
1453 
1454 	status = ice_add_rss_list(hw, vsi_handle, prof);
1455 
1456 exit:
1457 	kfree(segs);
1458 	return status;
1459 }
1460 
1461 /**
1462  * ice_add_rss_cfg - add an RSS configuration with specified hashed fields
1463  * @hw: pointer to the hardware structure
1464  * @vsi_handle: software VSI handle
1465  * @hashed_flds: hash bit fields (ICE_FLOW_HASH_*) to configure
1466  * @addl_hdrs: protocol header fields
1467  *
1468  * This function will generate a flow profile based on fields associated with
1469  * the input fields to hash on, the flow type and use the VSI number to add
1470  * a flow entry to the profile.
1471  */
1472 enum ice_status
1473 ice_add_rss_cfg(struct ice_hw *hw, u16 vsi_handle, u64 hashed_flds,
1474 		u32 addl_hdrs)
1475 {
1476 	enum ice_status status;
1477 
1478 	if (hashed_flds == ICE_HASH_INVALID ||
1479 	    !ice_is_vsi_valid(hw, vsi_handle))
1480 		return ICE_ERR_PARAM;
1481 
1482 	mutex_lock(&hw->rss_locks);
1483 	status = ice_add_rss_cfg_sync(hw, vsi_handle, hashed_flds, addl_hdrs,
1484 				      ICE_RSS_OUTER_HEADERS);
1485 	if (!status)
1486 		status = ice_add_rss_cfg_sync(hw, vsi_handle, hashed_flds,
1487 					      addl_hdrs, ICE_RSS_INNER_HEADERS);
1488 	mutex_unlock(&hw->rss_locks);
1489 
1490 	return status;
1491 }
1492 
1493 /* Mapping of AVF hash bit fields to an L3-L4 hash combination.
1494  * As the ice_flow_avf_hdr_field represent individual bit shifts in a hash,
1495  * convert its values to their appropriate flow L3, L4 values.
1496  */
1497 #define ICE_FLOW_AVF_RSS_IPV4_MASKS \
1498 	(BIT_ULL(ICE_AVF_FLOW_FIELD_IPV4_OTHER) | \
1499 	 BIT_ULL(ICE_AVF_FLOW_FIELD_FRAG_IPV4))
1500 #define ICE_FLOW_AVF_RSS_TCP_IPV4_MASKS \
1501 	(BIT_ULL(ICE_AVF_FLOW_FIELD_IPV4_TCP_SYN_NO_ACK) | \
1502 	 BIT_ULL(ICE_AVF_FLOW_FIELD_IPV4_TCP))
1503 #define ICE_FLOW_AVF_RSS_UDP_IPV4_MASKS \
1504 	(BIT_ULL(ICE_AVF_FLOW_FIELD_UNICAST_IPV4_UDP) | \
1505 	 BIT_ULL(ICE_AVF_FLOW_FIELD_MULTICAST_IPV4_UDP) | \
1506 	 BIT_ULL(ICE_AVF_FLOW_FIELD_IPV4_UDP))
1507 #define ICE_FLOW_AVF_RSS_ALL_IPV4_MASKS \
1508 	(ICE_FLOW_AVF_RSS_TCP_IPV4_MASKS | ICE_FLOW_AVF_RSS_UDP_IPV4_MASKS | \
1509 	 ICE_FLOW_AVF_RSS_IPV4_MASKS | BIT_ULL(ICE_AVF_FLOW_FIELD_IPV4_SCTP))
1510 
1511 #define ICE_FLOW_AVF_RSS_IPV6_MASKS \
1512 	(BIT_ULL(ICE_AVF_FLOW_FIELD_IPV6_OTHER) | \
1513 	 BIT_ULL(ICE_AVF_FLOW_FIELD_FRAG_IPV6))
1514 #define ICE_FLOW_AVF_RSS_UDP_IPV6_MASKS \
1515 	(BIT_ULL(ICE_AVF_FLOW_FIELD_UNICAST_IPV6_UDP) | \
1516 	 BIT_ULL(ICE_AVF_FLOW_FIELD_MULTICAST_IPV6_UDP) | \
1517 	 BIT_ULL(ICE_AVF_FLOW_FIELD_IPV6_UDP))
1518 #define ICE_FLOW_AVF_RSS_TCP_IPV6_MASKS \
1519 	(BIT_ULL(ICE_AVF_FLOW_FIELD_IPV6_TCP_SYN_NO_ACK) | \
1520 	 BIT_ULL(ICE_AVF_FLOW_FIELD_IPV6_TCP))
1521 #define ICE_FLOW_AVF_RSS_ALL_IPV6_MASKS \
1522 	(ICE_FLOW_AVF_RSS_TCP_IPV6_MASKS | ICE_FLOW_AVF_RSS_UDP_IPV6_MASKS | \
1523 	 ICE_FLOW_AVF_RSS_IPV6_MASKS | BIT_ULL(ICE_AVF_FLOW_FIELD_IPV6_SCTP))
1524 
1525 /**
1526  * ice_add_avf_rss_cfg - add an RSS configuration for AVF driver
1527  * @hw: pointer to the hardware structure
1528  * @vsi_handle: software VSI handle
1529  * @avf_hash: hash bit fields (ICE_AVF_FLOW_FIELD_*) to configure
1530  *
1531  * This function will take the hash bitmap provided by the AVF driver via a
1532  * message, convert it to ICE-compatible values, and configure RSS flow
1533  * profiles.
1534  */
1535 enum ice_status
1536 ice_add_avf_rss_cfg(struct ice_hw *hw, u16 vsi_handle, u64 avf_hash)
1537 {
1538 	enum ice_status status = 0;
1539 	u64 hash_flds;
1540 
1541 	if (avf_hash == ICE_AVF_FLOW_FIELD_INVALID ||
1542 	    !ice_is_vsi_valid(hw, vsi_handle))
1543 		return ICE_ERR_PARAM;
1544 
1545 	/* Make sure no unsupported bits are specified */
1546 	if (avf_hash & ~(ICE_FLOW_AVF_RSS_ALL_IPV4_MASKS |
1547 			 ICE_FLOW_AVF_RSS_ALL_IPV6_MASKS))
1548 		return ICE_ERR_CFG;
1549 
1550 	hash_flds = avf_hash;
1551 
1552 	/* Always create an L3 RSS configuration for any L4 RSS configuration */
1553 	if (hash_flds & ICE_FLOW_AVF_RSS_ALL_IPV4_MASKS)
1554 		hash_flds |= ICE_FLOW_AVF_RSS_IPV4_MASKS;
1555 
1556 	if (hash_flds & ICE_FLOW_AVF_RSS_ALL_IPV6_MASKS)
1557 		hash_flds |= ICE_FLOW_AVF_RSS_IPV6_MASKS;
1558 
1559 	/* Create the corresponding RSS configuration for each valid hash bit */
1560 	while (hash_flds) {
1561 		u64 rss_hash = ICE_HASH_INVALID;
1562 
1563 		if (hash_flds & ICE_FLOW_AVF_RSS_ALL_IPV4_MASKS) {
1564 			if (hash_flds & ICE_FLOW_AVF_RSS_IPV4_MASKS) {
1565 				rss_hash = ICE_FLOW_HASH_IPV4;
1566 				hash_flds &= ~ICE_FLOW_AVF_RSS_IPV4_MASKS;
1567 			} else if (hash_flds &
1568 				   ICE_FLOW_AVF_RSS_TCP_IPV4_MASKS) {
1569 				rss_hash = ICE_FLOW_HASH_IPV4 |
1570 					ICE_FLOW_HASH_TCP_PORT;
1571 				hash_flds &= ~ICE_FLOW_AVF_RSS_TCP_IPV4_MASKS;
1572 			} else if (hash_flds &
1573 				   ICE_FLOW_AVF_RSS_UDP_IPV4_MASKS) {
1574 				rss_hash = ICE_FLOW_HASH_IPV4 |
1575 					ICE_FLOW_HASH_UDP_PORT;
1576 				hash_flds &= ~ICE_FLOW_AVF_RSS_UDP_IPV4_MASKS;
1577 			} else if (hash_flds &
1578 				   BIT_ULL(ICE_AVF_FLOW_FIELD_IPV4_SCTP)) {
1579 				rss_hash = ICE_FLOW_HASH_IPV4 |
1580 					ICE_FLOW_HASH_SCTP_PORT;
1581 				hash_flds &=
1582 					~BIT_ULL(ICE_AVF_FLOW_FIELD_IPV4_SCTP);
1583 			}
1584 		} else if (hash_flds & ICE_FLOW_AVF_RSS_ALL_IPV6_MASKS) {
1585 			if (hash_flds & ICE_FLOW_AVF_RSS_IPV6_MASKS) {
1586 				rss_hash = ICE_FLOW_HASH_IPV6;
1587 				hash_flds &= ~ICE_FLOW_AVF_RSS_IPV6_MASKS;
1588 			} else if (hash_flds &
1589 				   ICE_FLOW_AVF_RSS_TCP_IPV6_MASKS) {
1590 				rss_hash = ICE_FLOW_HASH_IPV6 |
1591 					ICE_FLOW_HASH_TCP_PORT;
1592 				hash_flds &= ~ICE_FLOW_AVF_RSS_TCP_IPV6_MASKS;
1593 			} else if (hash_flds &
1594 				   ICE_FLOW_AVF_RSS_UDP_IPV6_MASKS) {
1595 				rss_hash = ICE_FLOW_HASH_IPV6 |
1596 					ICE_FLOW_HASH_UDP_PORT;
1597 				hash_flds &= ~ICE_FLOW_AVF_RSS_UDP_IPV6_MASKS;
1598 			} else if (hash_flds &
1599 				   BIT_ULL(ICE_AVF_FLOW_FIELD_IPV6_SCTP)) {
1600 				rss_hash = ICE_FLOW_HASH_IPV6 |
1601 					ICE_FLOW_HASH_SCTP_PORT;
1602 				hash_flds &=
1603 					~BIT_ULL(ICE_AVF_FLOW_FIELD_IPV6_SCTP);
1604 			}
1605 		}
1606 
1607 		if (rss_hash == ICE_HASH_INVALID)
1608 			return ICE_ERR_OUT_OF_RANGE;
1609 
1610 		status = ice_add_rss_cfg(hw, vsi_handle, rss_hash,
1611 					 ICE_FLOW_SEG_HDR_NONE);
1612 		if (status)
1613 			break;
1614 	}
1615 
1616 	return status;
1617 }
1618 
1619 /**
1620  * ice_replay_rss_cfg - replay RSS configurations associated with VSI
1621  * @hw: pointer to the hardware structure
1622  * @vsi_handle: software VSI handle
1623  */
1624 enum ice_status ice_replay_rss_cfg(struct ice_hw *hw, u16 vsi_handle)
1625 {
1626 	enum ice_status status = 0;
1627 	struct ice_rss_cfg *r;
1628 
1629 	if (!ice_is_vsi_valid(hw, vsi_handle))
1630 		return ICE_ERR_PARAM;
1631 
1632 	mutex_lock(&hw->rss_locks);
1633 	list_for_each_entry(r, &hw->rss_list_head, l_entry) {
1634 		if (test_bit(vsi_handle, r->vsis)) {
1635 			status = ice_add_rss_cfg_sync(hw, vsi_handle,
1636 						      r->hashed_flds,
1637 						      r->packet_hdr,
1638 						      ICE_RSS_OUTER_HEADERS);
1639 			if (status)
1640 				break;
1641 			status = ice_add_rss_cfg_sync(hw, vsi_handle,
1642 						      r->hashed_flds,
1643 						      r->packet_hdr,
1644 						      ICE_RSS_INNER_HEADERS);
1645 			if (status)
1646 				break;
1647 		}
1648 	}
1649 	mutex_unlock(&hw->rss_locks);
1650 
1651 	return status;
1652 }
1653 
1654 /**
1655  * ice_get_rss_cfg - returns hashed fields for the given header types
1656  * @hw: pointer to the hardware structure
1657  * @vsi_handle: software VSI handle
1658  * @hdrs: protocol header type
1659  *
1660  * This function will return the match fields of the first instance of flow
1661  * profile having the given header types and containing input VSI
1662  */
1663 u64 ice_get_rss_cfg(struct ice_hw *hw, u16 vsi_handle, u32 hdrs)
1664 {
1665 	u64 rss_hash = ICE_HASH_INVALID;
1666 	struct ice_rss_cfg *r;
1667 
1668 	/* verify if the protocol header is non zero and VSI is valid */
1669 	if (hdrs == ICE_FLOW_SEG_HDR_NONE || !ice_is_vsi_valid(hw, vsi_handle))
1670 		return ICE_HASH_INVALID;
1671 
1672 	mutex_lock(&hw->rss_locks);
1673 	list_for_each_entry(r, &hw->rss_list_head, l_entry)
1674 		if (test_bit(vsi_handle, r->vsis) &&
1675 		    r->packet_hdr == hdrs) {
1676 			rss_hash = r->hashed_flds;
1677 			break;
1678 		}
1679 	mutex_unlock(&hw->rss_locks);
1680 
1681 	return rss_hash;
1682 }
1683