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 
46 };
47 
48 /* Bitmaps indicating relevant packet types for a particular protocol header
49  *
50  * Packet types for packets with an Outer/First/Single IPv4 header
51  */
52 static const u32 ice_ptypes_ipv4_ofos[] = {
53 	0x1DC00000, 0x04000800, 0x00000000, 0x00000000,
54 	0x00000000, 0x00000000, 0x00000000, 0x00000000,
55 	0x00000000, 0x00000000, 0x00000000, 0x00000000,
56 	0x00000000, 0x00000000, 0x00000000, 0x00000000,
57 	0x00000000, 0x00000000, 0x00000000, 0x00000000,
58 	0x00000000, 0x00000000, 0x00000000, 0x00000000,
59 	0x00000000, 0x00000000, 0x00000000, 0x00000000,
60 	0x00000000, 0x00000000, 0x00000000, 0x00000000,
61 };
62 
63 /* Packet types for packets with an Innermost/Last IPv4 header */
64 static const u32 ice_ptypes_ipv4_il[] = {
65 	0xE0000000, 0xB807700E, 0x80000003, 0xE01DC03B,
66 	0x0000000E, 0x00000000, 0x00000000, 0x00000000,
67 	0x00000000, 0x00000000, 0x00000000, 0x00000000,
68 	0x00000000, 0x00000000, 0x00000000, 0x00000000,
69 	0x00000000, 0x00000000, 0x00000000, 0x00000000,
70 	0x00000000, 0x00000000, 0x00000000, 0x00000000,
71 	0x00000000, 0x00000000, 0x00000000, 0x00000000,
72 	0x00000000, 0x00000000, 0x00000000, 0x00000000,
73 };
74 
75 /* Packet types for packets with an Outer/First/Single IPv6 header */
76 static const u32 ice_ptypes_ipv6_ofos[] = {
77 	0x00000000, 0x00000000, 0x77000000, 0x10002000,
78 	0x00000000, 0x00000000, 0x00000000, 0x00000000,
79 	0x00000000, 0x00000000, 0x00000000, 0x00000000,
80 	0x00000000, 0x00000000, 0x00000000, 0x00000000,
81 	0x00000000, 0x00000000, 0x00000000, 0x00000000,
82 	0x00000000, 0x00000000, 0x00000000, 0x00000000,
83 	0x00000000, 0x00000000, 0x00000000, 0x00000000,
84 	0x00000000, 0x00000000, 0x00000000, 0x00000000,
85 };
86 
87 /* Packet types for packets with an Innermost/Last IPv6 header */
88 static const u32 ice_ptypes_ipv6_il[] = {
89 	0x00000000, 0x03B80770, 0x000001DC, 0x0EE00000,
90 	0x00000770, 0x00000000, 0x00000000, 0x00000000,
91 	0x00000000, 0x00000000, 0x00000000, 0x00000000,
92 	0x00000000, 0x00000000, 0x00000000, 0x00000000,
93 	0x00000000, 0x00000000, 0x00000000, 0x00000000,
94 	0x00000000, 0x00000000, 0x00000000, 0x00000000,
95 	0x00000000, 0x00000000, 0x00000000, 0x00000000,
96 	0x00000000, 0x00000000, 0x00000000, 0x00000000,
97 };
98 
99 /* UDP Packet types for non-tunneled packets or tunneled
100  * packets with inner UDP.
101  */
102 static const u32 ice_ptypes_udp_il[] = {
103 	0x81000000, 0x20204040, 0x04000010, 0x80810102,
104 	0x00000040, 0x00000000, 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 };
112 
113 /* Packet types for packets with an Innermost/Last TCP header */
114 static const u32 ice_ptypes_tcp_il[] = {
115 	0x04000000, 0x80810102, 0x10000040, 0x02040408,
116 	0x00000102, 0x00000000, 0x00000000, 0x00000000,
117 	0x00000000, 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 };
124 
125 /* Packet types for packets with an Innermost/Last SCTP header */
126 static const u32 ice_ptypes_sctp_il[] = {
127 	0x08000000, 0x01020204, 0x20000081, 0x04080810,
128 	0x00000204, 0x00000000, 0x00000000, 0x00000000,
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 };
136 
137 /* Manage parameters and info. used during the creation of a flow profile */
138 struct ice_flow_prof_params {
139 	enum ice_block blk;
140 	u16 entry_length; /* # of bytes formatted entry will require */
141 	u8 es_cnt;
142 	struct ice_flow_prof *prof;
143 
144 	/* For ACL, the es[0] will have the data of ICE_RX_MDID_PKT_FLAGS_15_0
145 	 * This will give us the direction flags.
146 	 */
147 	struct ice_fv_word es[ICE_MAX_FV_WORDS];
148 	DECLARE_BITMAP(ptypes, ICE_FLOW_PTYPE_MAX);
149 };
150 
151 #define ICE_FLOW_SEG_HDRS_L3_MASK	\
152 	(ICE_FLOW_SEG_HDR_IPV4 | ICE_FLOW_SEG_HDR_IPV6)
153 #define ICE_FLOW_SEG_HDRS_L4_MASK	\
154 	(ICE_FLOW_SEG_HDR_TCP | ICE_FLOW_SEG_HDR_UDP | ICE_FLOW_SEG_HDR_SCTP)
155 
156 /**
157  * ice_flow_val_hdrs - validates packet segments for valid protocol headers
158  * @segs: array of one or more packet segments that describe the flow
159  * @segs_cnt: number of packet segments provided
160  */
161 static enum ice_status
162 ice_flow_val_hdrs(struct ice_flow_seg_info *segs, u8 segs_cnt)
163 {
164 	u8 i;
165 
166 	for (i = 0; i < segs_cnt; i++) {
167 		/* Multiple L3 headers */
168 		if (segs[i].hdrs & ICE_FLOW_SEG_HDRS_L3_MASK &&
169 		    !is_power_of_2(segs[i].hdrs & ICE_FLOW_SEG_HDRS_L3_MASK))
170 			return ICE_ERR_PARAM;
171 
172 		/* Multiple L4 headers */
173 		if (segs[i].hdrs & ICE_FLOW_SEG_HDRS_L4_MASK &&
174 		    !is_power_of_2(segs[i].hdrs & ICE_FLOW_SEG_HDRS_L4_MASK))
175 			return ICE_ERR_PARAM;
176 	}
177 
178 	return 0;
179 }
180 
181 /**
182  * ice_flow_proc_seg_hdrs - process protocol headers present in pkt segments
183  * @params: information about the flow to be processed
184  *
185  * This function identifies the packet types associated with the protocol
186  * headers being present in packet segments of the specified flow profile.
187  */
188 static enum ice_status
189 ice_flow_proc_seg_hdrs(struct ice_flow_prof_params *params)
190 {
191 	struct ice_flow_prof *prof;
192 	u8 i;
193 
194 	memset(params->ptypes, 0xff, sizeof(params->ptypes));
195 
196 	prof = params->prof;
197 
198 	for (i = 0; i < params->prof->segs_cnt; i++) {
199 		const unsigned long *src;
200 		u32 hdrs;
201 
202 		hdrs = prof->segs[i].hdrs;
203 
204 		if (hdrs & ICE_FLOW_SEG_HDR_IPV4) {
205 			src = !i ? (const unsigned long *)ice_ptypes_ipv4_ofos :
206 				(const unsigned long *)ice_ptypes_ipv4_il;
207 			bitmap_and(params->ptypes, params->ptypes, src,
208 				   ICE_FLOW_PTYPE_MAX);
209 		} else if (hdrs & ICE_FLOW_SEG_HDR_IPV6) {
210 			src = !i ? (const unsigned long *)ice_ptypes_ipv6_ofos :
211 				(const unsigned long *)ice_ptypes_ipv6_il;
212 			bitmap_and(params->ptypes, params->ptypes, src,
213 				   ICE_FLOW_PTYPE_MAX);
214 		}
215 
216 		if (hdrs & ICE_FLOW_SEG_HDR_UDP) {
217 			src = (const unsigned long *)ice_ptypes_udp_il;
218 			bitmap_and(params->ptypes, params->ptypes, src,
219 				   ICE_FLOW_PTYPE_MAX);
220 		} else if (hdrs & ICE_FLOW_SEG_HDR_TCP) {
221 			bitmap_and(params->ptypes, params->ptypes,
222 				   (const unsigned long *)ice_ptypes_tcp_il,
223 				   ICE_FLOW_PTYPE_MAX);
224 		} else if (hdrs & ICE_FLOW_SEG_HDR_SCTP) {
225 			src = (const unsigned long *)ice_ptypes_sctp_il;
226 			bitmap_and(params->ptypes, params->ptypes, src,
227 				   ICE_FLOW_PTYPE_MAX);
228 		}
229 	}
230 
231 	return 0;
232 }
233 
234 /**
235  * ice_flow_xtract_fld - Create an extraction sequence entry for the given field
236  * @hw: pointer to the HW struct
237  * @params: information about the flow to be processed
238  * @seg: packet segment index of the field to be extracted
239  * @fld: ID of field to be extracted
240  *
241  * This function determines the protocol ID, offset, and size of the given
242  * field. It then allocates one or more extraction sequence entries for the
243  * given field, and fill the entries with protocol ID and offset information.
244  */
245 static enum ice_status
246 ice_flow_xtract_fld(struct ice_hw *hw, struct ice_flow_prof_params *params,
247 		    u8 seg, enum ice_flow_field fld)
248 {
249 	enum ice_prot_id prot_id = ICE_PROT_ID_INVAL;
250 	u8 fv_words = hw->blk[params->blk].es.fvw;
251 	struct ice_flow_fld_info *flds;
252 	u16 cnt, ese_bits, i;
253 	u16 off;
254 
255 	flds = params->prof->segs[seg].fields;
256 
257 	switch (fld) {
258 	case ICE_FLOW_FIELD_IDX_IPV4_SA:
259 	case ICE_FLOW_FIELD_IDX_IPV4_DA:
260 		prot_id = seg == 0 ? ICE_PROT_IPV4_OF_OR_S : ICE_PROT_IPV4_IL;
261 		break;
262 	case ICE_FLOW_FIELD_IDX_IPV6_SA:
263 	case ICE_FLOW_FIELD_IDX_IPV6_DA:
264 		prot_id = seg == 0 ? ICE_PROT_IPV6_OF_OR_S : ICE_PROT_IPV6_IL;
265 		break;
266 	case ICE_FLOW_FIELD_IDX_TCP_SRC_PORT:
267 	case ICE_FLOW_FIELD_IDX_TCP_DST_PORT:
268 		prot_id = ICE_PROT_TCP_IL;
269 		break;
270 	case ICE_FLOW_FIELD_IDX_UDP_SRC_PORT:
271 	case ICE_FLOW_FIELD_IDX_UDP_DST_PORT:
272 		prot_id = ICE_PROT_UDP_IL_OR_S;
273 		break;
274 	case ICE_FLOW_FIELD_IDX_SCTP_SRC_PORT:
275 	case ICE_FLOW_FIELD_IDX_SCTP_DST_PORT:
276 		prot_id = ICE_PROT_SCTP_IL;
277 		break;
278 	default:
279 		return ICE_ERR_NOT_IMPL;
280 	}
281 
282 	/* Each extraction sequence entry is a word in size, and extracts a
283 	 * word-aligned offset from a protocol header.
284 	 */
285 	ese_bits = ICE_FLOW_FV_EXTRACT_SZ * BITS_PER_BYTE;
286 
287 	flds[fld].xtrct.prot_id = prot_id;
288 	flds[fld].xtrct.off = (ice_flds_info[fld].off / ese_bits) *
289 		ICE_FLOW_FV_EXTRACT_SZ;
290 	flds[fld].xtrct.disp = (u8)(ice_flds_info[fld].off % ese_bits);
291 	flds[fld].xtrct.idx = params->es_cnt;
292 
293 	/* Adjust the next field-entry index after accommodating the number of
294 	 * entries this field consumes
295 	 */
296 	cnt = DIV_ROUND_UP(flds[fld].xtrct.disp + ice_flds_info[fld].size,
297 			   ese_bits);
298 
299 	/* Fill in the extraction sequence entries needed for this field */
300 	off = flds[fld].xtrct.off;
301 	for (i = 0; i < cnt; i++) {
302 		u8 idx;
303 
304 		/* Make sure the number of extraction sequence required
305 		 * does not exceed the block's capability
306 		 */
307 		if (params->es_cnt >= fv_words)
308 			return ICE_ERR_MAX_LIMIT;
309 
310 		/* some blocks require a reversed field vector layout */
311 		if (hw->blk[params->blk].es.reverse)
312 			idx = fv_words - params->es_cnt - 1;
313 		else
314 			idx = params->es_cnt;
315 
316 		params->es[idx].prot_id = prot_id;
317 		params->es[idx].off = off;
318 		params->es_cnt++;
319 
320 		off += ICE_FLOW_FV_EXTRACT_SZ;
321 	}
322 
323 	return 0;
324 }
325 
326 /**
327  * ice_flow_create_xtrct_seq - Create an extraction sequence for given segments
328  * @hw: pointer to the HW struct
329  * @params: information about the flow to be processed
330  *
331  * This function iterates through all matched fields in the given segments, and
332  * creates an extraction sequence for the fields.
333  */
334 static enum ice_status
335 ice_flow_create_xtrct_seq(struct ice_hw *hw,
336 			  struct ice_flow_prof_params *params)
337 {
338 	struct ice_flow_prof *prof = params->prof;
339 	enum ice_status status = 0;
340 	u8 i;
341 
342 	for (i = 0; i < prof->segs_cnt; i++) {
343 		u8 j;
344 
345 		for_each_set_bit(j, (unsigned long *)&prof->segs[i].match,
346 				 ICE_FLOW_FIELD_IDX_MAX) {
347 			status = ice_flow_xtract_fld(hw, params, i,
348 						     (enum ice_flow_field)j);
349 			if (status)
350 				return status;
351 		}
352 	}
353 
354 	return status;
355 }
356 
357 /**
358  * ice_flow_proc_segs - process all packet segments associated with a profile
359  * @hw: pointer to the HW struct
360  * @params: information about the flow to be processed
361  */
362 static enum ice_status
363 ice_flow_proc_segs(struct ice_hw *hw, struct ice_flow_prof_params *params)
364 {
365 	enum ice_status status;
366 
367 	status = ice_flow_proc_seg_hdrs(params);
368 	if (status)
369 		return status;
370 
371 	status = ice_flow_create_xtrct_seq(hw, params);
372 	if (status)
373 		return status;
374 
375 	switch (params->blk) {
376 	case ICE_BLK_RSS:
377 		/* Only header information is provided for RSS configuration.
378 		 * No further processing is needed.
379 		 */
380 		status = 0;
381 		break;
382 	default:
383 		return ICE_ERR_NOT_IMPL;
384 	}
385 
386 	return status;
387 }
388 
389 #define ICE_FLOW_FIND_PROF_CHK_FLDS	0x00000001
390 #define ICE_FLOW_FIND_PROF_CHK_VSI	0x00000002
391 #define ICE_FLOW_FIND_PROF_NOT_CHK_DIR	0x00000004
392 
393 /**
394  * ice_flow_find_prof_conds - Find a profile matching headers and conditions
395  * @hw: pointer to the HW struct
396  * @blk: classification stage
397  * @dir: flow direction
398  * @segs: array of one or more packet segments that describe the flow
399  * @segs_cnt: number of packet segments provided
400  * @vsi_handle: software VSI handle to check VSI (ICE_FLOW_FIND_PROF_CHK_VSI)
401  * @conds: additional conditions to be checked (ICE_FLOW_FIND_PROF_CHK_*)
402  */
403 static struct ice_flow_prof *
404 ice_flow_find_prof_conds(struct ice_hw *hw, enum ice_block blk,
405 			 enum ice_flow_dir dir, struct ice_flow_seg_info *segs,
406 			 u8 segs_cnt, u16 vsi_handle, u32 conds)
407 {
408 	struct ice_flow_prof *p, *prof = NULL;
409 
410 	mutex_lock(&hw->fl_profs_locks[blk]);
411 	list_for_each_entry(p, &hw->fl_profs[blk], l_entry)
412 		if ((p->dir == dir || conds & ICE_FLOW_FIND_PROF_NOT_CHK_DIR) &&
413 		    segs_cnt && segs_cnt == p->segs_cnt) {
414 			u8 i;
415 
416 			/* Check for profile-VSI association if specified */
417 			if ((conds & ICE_FLOW_FIND_PROF_CHK_VSI) &&
418 			    ice_is_vsi_valid(hw, vsi_handle) &&
419 			    !test_bit(vsi_handle, p->vsis))
420 				continue;
421 
422 			/* Protocol headers must be checked. Matched fields are
423 			 * checked if specified.
424 			 */
425 			for (i = 0; i < segs_cnt; i++)
426 				if (segs[i].hdrs != p->segs[i].hdrs ||
427 				    ((conds & ICE_FLOW_FIND_PROF_CHK_FLDS) &&
428 				     segs[i].match != p->segs[i].match))
429 					break;
430 
431 			/* A match is found if all segments are matched */
432 			if (i == segs_cnt) {
433 				prof = p;
434 				break;
435 			}
436 		}
437 	mutex_unlock(&hw->fl_profs_locks[blk]);
438 
439 	return prof;
440 }
441 
442 /**
443  * ice_flow_find_prof_id - Look up a profile with given profile ID
444  * @hw: pointer to the HW struct
445  * @blk: classification stage
446  * @prof_id: unique ID to identify this flow profile
447  */
448 static struct ice_flow_prof *
449 ice_flow_find_prof_id(struct ice_hw *hw, enum ice_block blk, u64 prof_id)
450 {
451 	struct ice_flow_prof *p;
452 
453 	list_for_each_entry(p, &hw->fl_profs[blk], l_entry)
454 		if (p->id == prof_id)
455 			return p;
456 
457 	return NULL;
458 }
459 
460 /**
461  * ice_flow_add_prof_sync - Add a flow profile for packet segments and fields
462  * @hw: pointer to the HW struct
463  * @blk: classification stage
464  * @dir: flow direction
465  * @prof_id: unique ID to identify this flow profile
466  * @segs: array of one or more packet segments that describe the flow
467  * @segs_cnt: number of packet segments provided
468  * @prof: stores the returned flow profile added
469  *
470  * Assumption: the caller has acquired the lock to the profile list
471  */
472 static enum ice_status
473 ice_flow_add_prof_sync(struct ice_hw *hw, enum ice_block blk,
474 		       enum ice_flow_dir dir, u64 prof_id,
475 		       struct ice_flow_seg_info *segs, u8 segs_cnt,
476 		       struct ice_flow_prof **prof)
477 {
478 	struct ice_flow_prof_params params;
479 	enum ice_status status;
480 	u8 i;
481 
482 	if (!prof)
483 		return ICE_ERR_BAD_PTR;
484 
485 	memset(&params, 0, sizeof(params));
486 	params.prof = devm_kzalloc(ice_hw_to_dev(hw), sizeof(*params.prof),
487 				   GFP_KERNEL);
488 	if (!params.prof)
489 		return ICE_ERR_NO_MEMORY;
490 
491 	/* initialize extraction sequence to all invalid (0xff) */
492 	for (i = 0; i < ICE_MAX_FV_WORDS; i++) {
493 		params.es[i].prot_id = ICE_PROT_INVALID;
494 		params.es[i].off = ICE_FV_OFFSET_INVAL;
495 	}
496 
497 	params.blk = blk;
498 	params.prof->id = prof_id;
499 	params.prof->dir = dir;
500 	params.prof->segs_cnt = segs_cnt;
501 
502 	/* Make a copy of the segments that need to be persistent in the flow
503 	 * profile instance
504 	 */
505 	for (i = 0; i < segs_cnt; i++)
506 		memcpy(&params.prof->segs[i], &segs[i], sizeof(*segs));
507 
508 	status = ice_flow_proc_segs(hw, &params);
509 	if (status) {
510 		ice_debug(hw, ICE_DBG_FLOW,
511 			  "Error processing a flow's packet segments\n");
512 		goto out;
513 	}
514 
515 	/* Add a HW profile for this flow profile */
516 	status = ice_add_prof(hw, blk, prof_id, (u8 *)params.ptypes, params.es);
517 	if (status) {
518 		ice_debug(hw, ICE_DBG_FLOW, "Error adding a HW flow profile\n");
519 		goto out;
520 	}
521 
522 	INIT_LIST_HEAD(&params.prof->entries);
523 	mutex_init(&params.prof->entries_lock);
524 	*prof = params.prof;
525 
526 out:
527 	if (status)
528 		devm_kfree(ice_hw_to_dev(hw), params.prof);
529 
530 	return status;
531 }
532 
533 /**
534  * ice_flow_rem_prof_sync - remove a flow profile
535  * @hw: pointer to the hardware structure
536  * @blk: classification stage
537  * @prof: pointer to flow profile to remove
538  *
539  * Assumption: the caller has acquired the lock to the profile list
540  */
541 static enum ice_status
542 ice_flow_rem_prof_sync(struct ice_hw *hw, enum ice_block blk,
543 		       struct ice_flow_prof *prof)
544 {
545 	enum ice_status status;
546 
547 	/* Remove all hardware profiles associated with this flow profile */
548 	status = ice_rem_prof(hw, blk, prof->id);
549 	if (!status) {
550 		list_del(&prof->l_entry);
551 		mutex_destroy(&prof->entries_lock);
552 		devm_kfree(ice_hw_to_dev(hw), prof);
553 	}
554 
555 	return status;
556 }
557 
558 /**
559  * ice_flow_assoc_prof - associate a VSI with a flow profile
560  * @hw: pointer to the hardware structure
561  * @blk: classification stage
562  * @prof: pointer to flow profile
563  * @vsi_handle: software VSI handle
564  *
565  * Assumption: the caller has acquired the lock to the profile list
566  * and the software VSI handle has been validated
567  */
568 static enum ice_status
569 ice_flow_assoc_prof(struct ice_hw *hw, enum ice_block blk,
570 		    struct ice_flow_prof *prof, u16 vsi_handle)
571 {
572 	enum ice_status status = 0;
573 
574 	if (!test_bit(vsi_handle, prof->vsis)) {
575 		status = ice_add_prof_id_flow(hw, blk,
576 					      ice_get_hw_vsi_num(hw,
577 								 vsi_handle),
578 					      prof->id);
579 		if (!status)
580 			set_bit(vsi_handle, prof->vsis);
581 		else
582 			ice_debug(hw, ICE_DBG_FLOW,
583 				  "HW profile add failed, %d\n",
584 				  status);
585 	}
586 
587 	return status;
588 }
589 
590 /**
591  * ice_flow_disassoc_prof - disassociate a VSI from a flow profile
592  * @hw: pointer to the hardware structure
593  * @blk: classification stage
594  * @prof: pointer to flow profile
595  * @vsi_handle: software VSI handle
596  *
597  * Assumption: the caller has acquired the lock to the profile list
598  * and the software VSI handle has been validated
599  */
600 static enum ice_status
601 ice_flow_disassoc_prof(struct ice_hw *hw, enum ice_block blk,
602 		       struct ice_flow_prof *prof, u16 vsi_handle)
603 {
604 	enum ice_status status = 0;
605 
606 	if (test_bit(vsi_handle, prof->vsis)) {
607 		status = ice_rem_prof_id_flow(hw, blk,
608 					      ice_get_hw_vsi_num(hw,
609 								 vsi_handle),
610 					      prof->id);
611 		if (!status)
612 			clear_bit(vsi_handle, prof->vsis);
613 		else
614 			ice_debug(hw, ICE_DBG_FLOW,
615 				  "HW profile remove failed, %d\n",
616 				  status);
617 	}
618 
619 	return status;
620 }
621 
622 /**
623  * ice_flow_add_prof - Add a flow profile for packet segments and matched fields
624  * @hw: pointer to the HW struct
625  * @blk: classification stage
626  * @dir: flow direction
627  * @prof_id: unique ID to identify this flow profile
628  * @segs: array of one or more packet segments that describe the flow
629  * @segs_cnt: number of packet segments provided
630  * @prof: stores the returned flow profile added
631  */
632 static enum ice_status
633 ice_flow_add_prof(struct ice_hw *hw, enum ice_block blk, enum ice_flow_dir dir,
634 		  u64 prof_id, struct ice_flow_seg_info *segs, u8 segs_cnt,
635 		  struct ice_flow_prof **prof)
636 {
637 	enum ice_status status;
638 
639 	if (segs_cnt > ICE_FLOW_SEG_MAX)
640 		return ICE_ERR_MAX_LIMIT;
641 
642 	if (!segs_cnt)
643 		return ICE_ERR_PARAM;
644 
645 	if (!segs)
646 		return ICE_ERR_BAD_PTR;
647 
648 	status = ice_flow_val_hdrs(segs, segs_cnt);
649 	if (status)
650 		return status;
651 
652 	mutex_lock(&hw->fl_profs_locks[blk]);
653 
654 	status = ice_flow_add_prof_sync(hw, blk, dir, prof_id, segs, segs_cnt,
655 					prof);
656 	if (!status)
657 		list_add(&(*prof)->l_entry, &hw->fl_profs[blk]);
658 
659 	mutex_unlock(&hw->fl_profs_locks[blk]);
660 
661 	return status;
662 }
663 
664 /**
665  * ice_flow_rem_prof - Remove a flow profile and all entries associated with it
666  * @hw: pointer to the HW struct
667  * @blk: the block for which the flow profile is to be removed
668  * @prof_id: unique ID of the flow profile to be removed
669  */
670 static enum ice_status
671 ice_flow_rem_prof(struct ice_hw *hw, enum ice_block blk, u64 prof_id)
672 {
673 	struct ice_flow_prof *prof;
674 	enum ice_status status;
675 
676 	mutex_lock(&hw->fl_profs_locks[blk]);
677 
678 	prof = ice_flow_find_prof_id(hw, blk, prof_id);
679 	if (!prof) {
680 		status = ICE_ERR_DOES_NOT_EXIST;
681 		goto out;
682 	}
683 
684 	/* prof becomes invalid after the call */
685 	status = ice_flow_rem_prof_sync(hw, blk, prof);
686 
687 out:
688 	mutex_unlock(&hw->fl_profs_locks[blk]);
689 
690 	return status;
691 }
692 
693 /**
694  * ice_flow_set_fld_ext - specifies locations of field from entry's input buffer
695  * @seg: packet segment the field being set belongs to
696  * @fld: field to be set
697  * @type: type of the field
698  * @val_loc: if not ICE_FLOW_FLD_OFF_INVAL, location of the value to match from
699  *           entry's input buffer
700  * @mask_loc: if not ICE_FLOW_FLD_OFF_INVAL, location of mask value from entry's
701  *            input buffer
702  * @last_loc: if not ICE_FLOW_FLD_OFF_INVAL, location of last/upper value from
703  *            entry's input buffer
704  *
705  * This helper function stores information of a field being matched, including
706  * the type of the field and the locations of the value to match, the mask, and
707  * and the upper-bound value in the start of the input buffer for a flow entry.
708  * This function should only be used for fixed-size data structures.
709  *
710  * This function also opportunistically determines the protocol headers to be
711  * present based on the fields being set. Some fields cannot be used alone to
712  * determine the protocol headers present. Sometimes, fields for particular
713  * protocol headers are not matched. In those cases, the protocol headers
714  * must be explicitly set.
715  */
716 static void
717 ice_flow_set_fld_ext(struct ice_flow_seg_info *seg, enum ice_flow_field fld,
718 		     enum ice_flow_fld_match_type type, u16 val_loc,
719 		     u16 mask_loc, u16 last_loc)
720 {
721 	u64 bit = BIT_ULL(fld);
722 
723 	seg->match |= bit;
724 	if (type == ICE_FLOW_FLD_TYPE_RANGE)
725 		seg->range |= bit;
726 
727 	seg->fields[fld].type = type;
728 	seg->fields[fld].src.val = val_loc;
729 	seg->fields[fld].src.mask = mask_loc;
730 	seg->fields[fld].src.last = last_loc;
731 
732 	ICE_FLOW_SET_HDRS(seg, ice_flds_info[fld].hdr);
733 }
734 
735 /**
736  * ice_flow_set_fld - specifies locations of field from entry's input buffer
737  * @seg: packet segment the field being set belongs to
738  * @fld: field to be set
739  * @val_loc: if not ICE_FLOW_FLD_OFF_INVAL, location of the value to match from
740  *           entry's input buffer
741  * @mask_loc: if not ICE_FLOW_FLD_OFF_INVAL, location of mask value from entry's
742  *            input buffer
743  * @last_loc: if not ICE_FLOW_FLD_OFF_INVAL, location of last/upper value from
744  *            entry's input buffer
745  * @range: indicate if field being matched is to be in a range
746  *
747  * This function specifies the locations, in the form of byte offsets from the
748  * start of the input buffer for a flow entry, from where the value to match,
749  * the mask value, and upper value can be extracted. These locations are then
750  * stored in the flow profile. When adding a flow entry associated with the
751  * flow profile, these locations will be used to quickly extract the values and
752  * create the content of a match entry. This function should only be used for
753  * fixed-size data structures.
754  */
755 static void
756 ice_flow_set_fld(struct ice_flow_seg_info *seg, enum ice_flow_field fld,
757 		 u16 val_loc, u16 mask_loc, u16 last_loc, bool range)
758 {
759 	enum ice_flow_fld_match_type t = range ?
760 		ICE_FLOW_FLD_TYPE_RANGE : ICE_FLOW_FLD_TYPE_REG;
761 
762 	ice_flow_set_fld_ext(seg, fld, t, val_loc, mask_loc, last_loc);
763 }
764 
765 #define ICE_FLOW_RSS_SEG_HDR_L3_MASKS \
766 	(ICE_FLOW_SEG_HDR_IPV4 | ICE_FLOW_SEG_HDR_IPV6)
767 
768 #define ICE_FLOW_RSS_SEG_HDR_L4_MASKS \
769 	(ICE_FLOW_SEG_HDR_TCP | ICE_FLOW_SEG_HDR_UDP | ICE_FLOW_SEG_HDR_SCTP)
770 
771 #define ICE_FLOW_RSS_SEG_HDR_VAL_MASKS \
772 	(ICE_FLOW_RSS_SEG_HDR_L3_MASKS | \
773 	 ICE_FLOW_RSS_SEG_HDR_L4_MASKS)
774 
775 /**
776  * ice_flow_set_rss_seg_info - setup packet segments for RSS
777  * @segs: pointer to the flow field segment(s)
778  * @hash_fields: fields to be hashed on for the segment(s)
779  * @flow_hdr: protocol header fields within a packet segment
780  *
781  * Helper function to extract fields from hash bitmap and use flow
782  * header value to set flow field segment for further use in flow
783  * profile entry or removal.
784  */
785 static enum ice_status
786 ice_flow_set_rss_seg_info(struct ice_flow_seg_info *segs, u64 hash_fields,
787 			  u32 flow_hdr)
788 {
789 	u64 val;
790 	u8 i;
791 
792 	for_each_set_bit(i, (unsigned long *)&hash_fields,
793 			 ICE_FLOW_FIELD_IDX_MAX)
794 		ice_flow_set_fld(segs, (enum ice_flow_field)i,
795 				 ICE_FLOW_FLD_OFF_INVAL, ICE_FLOW_FLD_OFF_INVAL,
796 				 ICE_FLOW_FLD_OFF_INVAL, false);
797 
798 	ICE_FLOW_SET_HDRS(segs, flow_hdr);
799 
800 	if (segs->hdrs & ~ICE_FLOW_RSS_SEG_HDR_VAL_MASKS)
801 		return ICE_ERR_PARAM;
802 
803 	val = (u64)(segs->hdrs & ICE_FLOW_RSS_SEG_HDR_L3_MASKS);
804 	if (val && !is_power_of_2(val))
805 		return ICE_ERR_CFG;
806 
807 	val = (u64)(segs->hdrs & ICE_FLOW_RSS_SEG_HDR_L4_MASKS);
808 	if (val && !is_power_of_2(val))
809 		return ICE_ERR_CFG;
810 
811 	return 0;
812 }
813 
814 /**
815  * ice_rem_vsi_rss_list - remove VSI from RSS list
816  * @hw: pointer to the hardware structure
817  * @vsi_handle: software VSI handle
818  *
819  * Remove the VSI from all RSS configurations in the list.
820  */
821 void ice_rem_vsi_rss_list(struct ice_hw *hw, u16 vsi_handle)
822 {
823 	struct ice_rss_cfg *r, *tmp;
824 
825 	if (list_empty(&hw->rss_list_head))
826 		return;
827 
828 	mutex_lock(&hw->rss_locks);
829 	list_for_each_entry_safe(r, tmp, &hw->rss_list_head, l_entry)
830 		if (test_and_clear_bit(vsi_handle, r->vsis))
831 			if (bitmap_empty(r->vsis, ICE_MAX_VSI)) {
832 				list_del(&r->l_entry);
833 				devm_kfree(ice_hw_to_dev(hw), r);
834 			}
835 	mutex_unlock(&hw->rss_locks);
836 }
837 
838 /**
839  * ice_rem_vsi_rss_cfg - remove RSS configurations associated with VSI
840  * @hw: pointer to the hardware structure
841  * @vsi_handle: software VSI handle
842  *
843  * This function will iterate through all flow profiles and disassociate
844  * the VSI from that profile. If the flow profile has no VSIs it will
845  * be removed.
846  */
847 enum ice_status ice_rem_vsi_rss_cfg(struct ice_hw *hw, u16 vsi_handle)
848 {
849 	const enum ice_block blk = ICE_BLK_RSS;
850 	struct ice_flow_prof *p, *t;
851 	enum ice_status status = 0;
852 
853 	if (!ice_is_vsi_valid(hw, vsi_handle))
854 		return ICE_ERR_PARAM;
855 
856 	if (list_empty(&hw->fl_profs[blk]))
857 		return 0;
858 
859 	mutex_lock(&hw->fl_profs_locks[blk]);
860 	list_for_each_entry_safe(p, t, &hw->fl_profs[blk], l_entry)
861 		if (test_bit(vsi_handle, p->vsis)) {
862 			status = ice_flow_disassoc_prof(hw, blk, p, vsi_handle);
863 			if (status)
864 				break;
865 
866 			if (bitmap_empty(p->vsis, ICE_MAX_VSI)) {
867 				status = ice_flow_rem_prof_sync(hw, blk, p);
868 				if (status)
869 					break;
870 			}
871 		}
872 	mutex_unlock(&hw->fl_profs_locks[blk]);
873 
874 	return status;
875 }
876 
877 /**
878  * ice_rem_rss_list - remove RSS configuration from list
879  * @hw: pointer to the hardware structure
880  * @vsi_handle: software VSI handle
881  * @prof: pointer to flow profile
882  *
883  * Assumption: lock has already been acquired for RSS list
884  */
885 static void
886 ice_rem_rss_list(struct ice_hw *hw, u16 vsi_handle, struct ice_flow_prof *prof)
887 {
888 	struct ice_rss_cfg *r, *tmp;
889 
890 	/* Search for RSS hash fields associated to the VSI that match the
891 	 * hash configurations associated to the flow profile. If found
892 	 * remove from the RSS entry list of the VSI context and delete entry.
893 	 */
894 	list_for_each_entry_safe(r, tmp, &hw->rss_list_head, l_entry)
895 		if (r->hashed_flds == prof->segs[prof->segs_cnt - 1].match &&
896 		    r->packet_hdr == prof->segs[prof->segs_cnt - 1].hdrs) {
897 			clear_bit(vsi_handle, r->vsis);
898 			if (bitmap_empty(r->vsis, ICE_MAX_VSI)) {
899 				list_del(&r->l_entry);
900 				devm_kfree(ice_hw_to_dev(hw), r);
901 			}
902 			return;
903 		}
904 }
905 
906 /**
907  * ice_add_rss_list - add RSS configuration to list
908  * @hw: pointer to the hardware structure
909  * @vsi_handle: software VSI handle
910  * @prof: pointer to flow profile
911  *
912  * Assumption: lock has already been acquired for RSS list
913  */
914 static enum ice_status
915 ice_add_rss_list(struct ice_hw *hw, u16 vsi_handle, struct ice_flow_prof *prof)
916 {
917 	struct ice_rss_cfg *r, *rss_cfg;
918 
919 	list_for_each_entry(r, &hw->rss_list_head, l_entry)
920 		if (r->hashed_flds == prof->segs[prof->segs_cnt - 1].match &&
921 		    r->packet_hdr == prof->segs[prof->segs_cnt - 1].hdrs) {
922 			set_bit(vsi_handle, r->vsis);
923 			return 0;
924 		}
925 
926 	rss_cfg = devm_kzalloc(ice_hw_to_dev(hw), sizeof(*rss_cfg),
927 			       GFP_KERNEL);
928 	if (!rss_cfg)
929 		return ICE_ERR_NO_MEMORY;
930 
931 	rss_cfg->hashed_flds = prof->segs[prof->segs_cnt - 1].match;
932 	rss_cfg->packet_hdr = prof->segs[prof->segs_cnt - 1].hdrs;
933 	set_bit(vsi_handle, rss_cfg->vsis);
934 
935 	list_add_tail(&rss_cfg->l_entry, &hw->rss_list_head);
936 
937 	return 0;
938 }
939 
940 #define ICE_FLOW_PROF_HASH_S	0
941 #define ICE_FLOW_PROF_HASH_M	(0xFFFFFFFFULL << ICE_FLOW_PROF_HASH_S)
942 #define ICE_FLOW_PROF_HDR_S	32
943 #define ICE_FLOW_PROF_HDR_M	(0x3FFFFFFFULL << ICE_FLOW_PROF_HDR_S)
944 #define ICE_FLOW_PROF_ENCAP_S	63
945 #define ICE_FLOW_PROF_ENCAP_M	(BIT_ULL(ICE_FLOW_PROF_ENCAP_S))
946 
947 #define ICE_RSS_OUTER_HEADERS	1
948 
949 /* Flow profile ID format:
950  * [0:31] - Packet match fields
951  * [32:62] - Protocol header
952  * [63] - Encapsulation flag, 0 if non-tunneled, 1 if tunneled
953  */
954 #define ICE_FLOW_GEN_PROFID(hash, hdr, segs_cnt) \
955 	(u64)(((u64)(hash) & ICE_FLOW_PROF_HASH_M) | \
956 	      (((u64)(hdr) << ICE_FLOW_PROF_HDR_S) & ICE_FLOW_PROF_HDR_M) | \
957 	      ((u8)((segs_cnt) - 1) ? ICE_FLOW_PROF_ENCAP_M : 0))
958 
959 /**
960  * ice_add_rss_cfg_sync - add an RSS configuration
961  * @hw: pointer to the hardware structure
962  * @vsi_handle: software VSI handle
963  * @hashed_flds: hash bit fields (ICE_FLOW_HASH_*) to configure
964  * @addl_hdrs: protocol header fields
965  * @segs_cnt: packet segment count
966  *
967  * Assumption: lock has already been acquired for RSS list
968  */
969 static enum ice_status
970 ice_add_rss_cfg_sync(struct ice_hw *hw, u16 vsi_handle, u64 hashed_flds,
971 		     u32 addl_hdrs, u8 segs_cnt)
972 {
973 	const enum ice_block blk = ICE_BLK_RSS;
974 	struct ice_flow_prof *prof = NULL;
975 	struct ice_flow_seg_info *segs;
976 	enum ice_status status;
977 
978 	if (!segs_cnt || segs_cnt > ICE_FLOW_SEG_MAX)
979 		return ICE_ERR_PARAM;
980 
981 	segs = kcalloc(segs_cnt, sizeof(*segs), GFP_KERNEL);
982 	if (!segs)
983 		return ICE_ERR_NO_MEMORY;
984 
985 	/* Construct the packet segment info from the hashed fields */
986 	status = ice_flow_set_rss_seg_info(&segs[segs_cnt - 1], hashed_flds,
987 					   addl_hdrs);
988 	if (status)
989 		goto exit;
990 
991 	/* Search for a flow profile that has matching headers, hash fields
992 	 * and has the input VSI associated to it. If found, no further
993 	 * operations required and exit.
994 	 */
995 	prof = ice_flow_find_prof_conds(hw, blk, ICE_FLOW_RX, segs, segs_cnt,
996 					vsi_handle,
997 					ICE_FLOW_FIND_PROF_CHK_FLDS |
998 					ICE_FLOW_FIND_PROF_CHK_VSI);
999 	if (prof)
1000 		goto exit;
1001 
1002 	/* Check if a flow profile exists with the same protocol headers and
1003 	 * associated with the input VSI. If so disassociate the VSI from
1004 	 * this profile. The VSI will be added to a new profile created with
1005 	 * the protocol header and new hash field configuration.
1006 	 */
1007 	prof = ice_flow_find_prof_conds(hw, blk, ICE_FLOW_RX, segs, segs_cnt,
1008 					vsi_handle, ICE_FLOW_FIND_PROF_CHK_VSI);
1009 	if (prof) {
1010 		status = ice_flow_disassoc_prof(hw, blk, prof, vsi_handle);
1011 		if (!status)
1012 			ice_rem_rss_list(hw, vsi_handle, prof);
1013 		else
1014 			goto exit;
1015 
1016 		/* Remove profile if it has no VSIs associated */
1017 		if (bitmap_empty(prof->vsis, ICE_MAX_VSI)) {
1018 			status = ice_flow_rem_prof(hw, blk, prof->id);
1019 			if (status)
1020 				goto exit;
1021 		}
1022 	}
1023 
1024 	/* Search for a profile that has same match fields only. If this
1025 	 * exists then associate the VSI to this profile.
1026 	 */
1027 	prof = ice_flow_find_prof_conds(hw, blk, ICE_FLOW_RX, segs, segs_cnt,
1028 					vsi_handle,
1029 					ICE_FLOW_FIND_PROF_CHK_FLDS);
1030 	if (prof) {
1031 		status = ice_flow_assoc_prof(hw, blk, prof, vsi_handle);
1032 		if (!status)
1033 			status = ice_add_rss_list(hw, vsi_handle, prof);
1034 		goto exit;
1035 	}
1036 
1037 	/* Create a new flow profile with generated profile and packet
1038 	 * segment information.
1039 	 */
1040 	status = ice_flow_add_prof(hw, blk, ICE_FLOW_RX,
1041 				   ICE_FLOW_GEN_PROFID(hashed_flds,
1042 						       segs[segs_cnt - 1].hdrs,
1043 						       segs_cnt),
1044 				   segs, segs_cnt, &prof);
1045 	if (status)
1046 		goto exit;
1047 
1048 	status = ice_flow_assoc_prof(hw, blk, prof, vsi_handle);
1049 	/* If association to a new flow profile failed then this profile can
1050 	 * be removed.
1051 	 */
1052 	if (status) {
1053 		ice_flow_rem_prof(hw, blk, prof->id);
1054 		goto exit;
1055 	}
1056 
1057 	status = ice_add_rss_list(hw, vsi_handle, prof);
1058 
1059 exit:
1060 	kfree(segs);
1061 	return status;
1062 }
1063 
1064 /**
1065  * ice_add_rss_cfg - add an RSS configuration with specified hashed fields
1066  * @hw: pointer to the hardware structure
1067  * @vsi_handle: software VSI handle
1068  * @hashed_flds: hash bit fields (ICE_FLOW_HASH_*) to configure
1069  * @addl_hdrs: protocol header fields
1070  *
1071  * This function will generate a flow profile based on fields associated with
1072  * the input fields to hash on, the flow type and use the VSI number to add
1073  * a flow entry to the profile.
1074  */
1075 enum ice_status
1076 ice_add_rss_cfg(struct ice_hw *hw, u16 vsi_handle, u64 hashed_flds,
1077 		u32 addl_hdrs)
1078 {
1079 	enum ice_status status;
1080 
1081 	if (hashed_flds == ICE_HASH_INVALID ||
1082 	    !ice_is_vsi_valid(hw, vsi_handle))
1083 		return ICE_ERR_PARAM;
1084 
1085 	mutex_lock(&hw->rss_locks);
1086 	status = ice_add_rss_cfg_sync(hw, vsi_handle, hashed_flds, addl_hdrs,
1087 				      ICE_RSS_OUTER_HEADERS);
1088 	mutex_unlock(&hw->rss_locks);
1089 
1090 	return status;
1091 }
1092 
1093 /* Mapping of AVF hash bit fields to an L3-L4 hash combination.
1094  * As the ice_flow_avf_hdr_field represent individual bit shifts in a hash,
1095  * convert its values to their appropriate flow L3, L4 values.
1096  */
1097 #define ICE_FLOW_AVF_RSS_IPV4_MASKS \
1098 	(BIT_ULL(ICE_AVF_FLOW_FIELD_IPV4_OTHER) | \
1099 	 BIT_ULL(ICE_AVF_FLOW_FIELD_FRAG_IPV4))
1100 #define ICE_FLOW_AVF_RSS_TCP_IPV4_MASKS \
1101 	(BIT_ULL(ICE_AVF_FLOW_FIELD_IPV4_TCP_SYN_NO_ACK) | \
1102 	 BIT_ULL(ICE_AVF_FLOW_FIELD_IPV4_TCP))
1103 #define ICE_FLOW_AVF_RSS_UDP_IPV4_MASKS \
1104 	(BIT_ULL(ICE_AVF_FLOW_FIELD_UNICAST_IPV4_UDP) | \
1105 	 BIT_ULL(ICE_AVF_FLOW_FIELD_MULTICAST_IPV4_UDP) | \
1106 	 BIT_ULL(ICE_AVF_FLOW_FIELD_IPV4_UDP))
1107 #define ICE_FLOW_AVF_RSS_ALL_IPV4_MASKS \
1108 	(ICE_FLOW_AVF_RSS_TCP_IPV4_MASKS | ICE_FLOW_AVF_RSS_UDP_IPV4_MASKS | \
1109 	 ICE_FLOW_AVF_RSS_IPV4_MASKS | BIT_ULL(ICE_AVF_FLOW_FIELD_IPV4_SCTP))
1110 
1111 #define ICE_FLOW_AVF_RSS_IPV6_MASKS \
1112 	(BIT_ULL(ICE_AVF_FLOW_FIELD_IPV6_OTHER) | \
1113 	 BIT_ULL(ICE_AVF_FLOW_FIELD_FRAG_IPV6))
1114 #define ICE_FLOW_AVF_RSS_UDP_IPV6_MASKS \
1115 	(BIT_ULL(ICE_AVF_FLOW_FIELD_UNICAST_IPV6_UDP) | \
1116 	 BIT_ULL(ICE_AVF_FLOW_FIELD_MULTICAST_IPV6_UDP) | \
1117 	 BIT_ULL(ICE_AVF_FLOW_FIELD_IPV6_UDP))
1118 #define ICE_FLOW_AVF_RSS_TCP_IPV6_MASKS \
1119 	(BIT_ULL(ICE_AVF_FLOW_FIELD_IPV6_TCP_SYN_NO_ACK) | \
1120 	 BIT_ULL(ICE_AVF_FLOW_FIELD_IPV6_TCP))
1121 #define ICE_FLOW_AVF_RSS_ALL_IPV6_MASKS \
1122 	(ICE_FLOW_AVF_RSS_TCP_IPV6_MASKS | ICE_FLOW_AVF_RSS_UDP_IPV6_MASKS | \
1123 	 ICE_FLOW_AVF_RSS_IPV6_MASKS | BIT_ULL(ICE_AVF_FLOW_FIELD_IPV6_SCTP))
1124 
1125 /**
1126  * ice_add_avf_rss_cfg - add an RSS configuration for AVF driver
1127  * @hw: pointer to the hardware structure
1128  * @vsi_handle: software VSI handle
1129  * @avf_hash: hash bit fields (ICE_AVF_FLOW_FIELD_*) to configure
1130  *
1131  * This function will take the hash bitmap provided by the AVF driver via a
1132  * message, convert it to ICE-compatible values, and configure RSS flow
1133  * profiles.
1134  */
1135 enum ice_status
1136 ice_add_avf_rss_cfg(struct ice_hw *hw, u16 vsi_handle, u64 avf_hash)
1137 {
1138 	enum ice_status status = 0;
1139 	u64 hash_flds;
1140 
1141 	if (avf_hash == ICE_AVF_FLOW_FIELD_INVALID ||
1142 	    !ice_is_vsi_valid(hw, vsi_handle))
1143 		return ICE_ERR_PARAM;
1144 
1145 	/* Make sure no unsupported bits are specified */
1146 	if (avf_hash & ~(ICE_FLOW_AVF_RSS_ALL_IPV4_MASKS |
1147 			 ICE_FLOW_AVF_RSS_ALL_IPV6_MASKS))
1148 		return ICE_ERR_CFG;
1149 
1150 	hash_flds = avf_hash;
1151 
1152 	/* Always create an L3 RSS configuration for any L4 RSS configuration */
1153 	if (hash_flds & ICE_FLOW_AVF_RSS_ALL_IPV4_MASKS)
1154 		hash_flds |= ICE_FLOW_AVF_RSS_IPV4_MASKS;
1155 
1156 	if (hash_flds & ICE_FLOW_AVF_RSS_ALL_IPV6_MASKS)
1157 		hash_flds |= ICE_FLOW_AVF_RSS_IPV6_MASKS;
1158 
1159 	/* Create the corresponding RSS configuration for each valid hash bit */
1160 	while (hash_flds) {
1161 		u64 rss_hash = ICE_HASH_INVALID;
1162 
1163 		if (hash_flds & ICE_FLOW_AVF_RSS_ALL_IPV4_MASKS) {
1164 			if (hash_flds & ICE_FLOW_AVF_RSS_IPV4_MASKS) {
1165 				rss_hash = ICE_FLOW_HASH_IPV4;
1166 				hash_flds &= ~ICE_FLOW_AVF_RSS_IPV4_MASKS;
1167 			} else if (hash_flds &
1168 				   ICE_FLOW_AVF_RSS_TCP_IPV4_MASKS) {
1169 				rss_hash = ICE_FLOW_HASH_IPV4 |
1170 					ICE_FLOW_HASH_TCP_PORT;
1171 				hash_flds &= ~ICE_FLOW_AVF_RSS_TCP_IPV4_MASKS;
1172 			} else if (hash_flds &
1173 				   ICE_FLOW_AVF_RSS_UDP_IPV4_MASKS) {
1174 				rss_hash = ICE_FLOW_HASH_IPV4 |
1175 					ICE_FLOW_HASH_UDP_PORT;
1176 				hash_flds &= ~ICE_FLOW_AVF_RSS_UDP_IPV4_MASKS;
1177 			} else if (hash_flds &
1178 				   BIT_ULL(ICE_AVF_FLOW_FIELD_IPV4_SCTP)) {
1179 				rss_hash = ICE_FLOW_HASH_IPV4 |
1180 					ICE_FLOW_HASH_SCTP_PORT;
1181 				hash_flds &=
1182 					~BIT_ULL(ICE_AVF_FLOW_FIELD_IPV4_SCTP);
1183 			}
1184 		} else if (hash_flds & ICE_FLOW_AVF_RSS_ALL_IPV6_MASKS) {
1185 			if (hash_flds & ICE_FLOW_AVF_RSS_IPV6_MASKS) {
1186 				rss_hash = ICE_FLOW_HASH_IPV6;
1187 				hash_flds &= ~ICE_FLOW_AVF_RSS_IPV6_MASKS;
1188 			} else if (hash_flds &
1189 				   ICE_FLOW_AVF_RSS_TCP_IPV6_MASKS) {
1190 				rss_hash = ICE_FLOW_HASH_IPV6 |
1191 					ICE_FLOW_HASH_TCP_PORT;
1192 				hash_flds &= ~ICE_FLOW_AVF_RSS_TCP_IPV6_MASKS;
1193 			} else if (hash_flds &
1194 				   ICE_FLOW_AVF_RSS_UDP_IPV6_MASKS) {
1195 				rss_hash = ICE_FLOW_HASH_IPV6 |
1196 					ICE_FLOW_HASH_UDP_PORT;
1197 				hash_flds &= ~ICE_FLOW_AVF_RSS_UDP_IPV6_MASKS;
1198 			} else if (hash_flds &
1199 				   BIT_ULL(ICE_AVF_FLOW_FIELD_IPV6_SCTP)) {
1200 				rss_hash = ICE_FLOW_HASH_IPV6 |
1201 					ICE_FLOW_HASH_SCTP_PORT;
1202 				hash_flds &=
1203 					~BIT_ULL(ICE_AVF_FLOW_FIELD_IPV6_SCTP);
1204 			}
1205 		}
1206 
1207 		if (rss_hash == ICE_HASH_INVALID)
1208 			return ICE_ERR_OUT_OF_RANGE;
1209 
1210 		status = ice_add_rss_cfg(hw, vsi_handle, rss_hash,
1211 					 ICE_FLOW_SEG_HDR_NONE);
1212 		if (status)
1213 			break;
1214 	}
1215 
1216 	return status;
1217 }
1218 
1219 /**
1220  * ice_replay_rss_cfg - replay RSS configurations associated with VSI
1221  * @hw: pointer to the hardware structure
1222  * @vsi_handle: software VSI handle
1223  */
1224 enum ice_status ice_replay_rss_cfg(struct ice_hw *hw, u16 vsi_handle)
1225 {
1226 	enum ice_status status = 0;
1227 	struct ice_rss_cfg *r;
1228 
1229 	if (!ice_is_vsi_valid(hw, vsi_handle))
1230 		return ICE_ERR_PARAM;
1231 
1232 	mutex_lock(&hw->rss_locks);
1233 	list_for_each_entry(r, &hw->rss_list_head, l_entry) {
1234 		if (test_bit(vsi_handle, r->vsis)) {
1235 			status = ice_add_rss_cfg_sync(hw, vsi_handle,
1236 						      r->hashed_flds,
1237 						      r->packet_hdr,
1238 						      ICE_RSS_OUTER_HEADERS);
1239 			if (status)
1240 				break;
1241 		}
1242 	}
1243 	mutex_unlock(&hw->rss_locks);
1244 
1245 	return status;
1246 }
1247 
1248 /**
1249  * ice_get_rss_cfg - returns hashed fields for the given header types
1250  * @hw: pointer to the hardware structure
1251  * @vsi_handle: software VSI handle
1252  * @hdrs: protocol header type
1253  *
1254  * This function will return the match fields of the first instance of flow
1255  * profile having the given header types and containing input VSI
1256  */
1257 u64 ice_get_rss_cfg(struct ice_hw *hw, u16 vsi_handle, u32 hdrs)
1258 {
1259 	struct ice_rss_cfg *r, *rss_cfg = NULL;
1260 
1261 	/* verify if the protocol header is non zero and VSI is valid */
1262 	if (hdrs == ICE_FLOW_SEG_HDR_NONE || !ice_is_vsi_valid(hw, vsi_handle))
1263 		return ICE_HASH_INVALID;
1264 
1265 	mutex_lock(&hw->rss_locks);
1266 	list_for_each_entry(r, &hw->rss_list_head, l_entry)
1267 		if (test_bit(vsi_handle, r->vsis) &&
1268 		    r->packet_hdr == hdrs) {
1269 			rss_cfg = r;
1270 			break;
1271 		}
1272 	mutex_unlock(&hw->rss_locks);
1273 
1274 	return rss_cfg ? rss_cfg->hashed_flds : ICE_HASH_INVALID;
1275 }
1276