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