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