xref: /freebsd/sys/dev/ice/ice_flow.c (revision 2008043f386721d58158e37e0d7e50df8095942d)
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 		ice_declare_bitmap(match, ICE_FLOW_FIELD_IDX_MAX);
731 		enum ice_flow_field j;
732 
733 		ice_cp_bitmap(match, params->prof->segs[i].match,
734 			      ICE_FLOW_FIELD_IDX_MAX);
735 		ice_for_each_set_bit(j, match, 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, 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 				     (ice_cmp_bitmap(segs[i].match,
815 						     p->segs[i].match,
816 						     ICE_FLOW_FIELD_IDX_MAX) ==
817 				       false)))
818 					break;
819 
820 			/* A match is found if all segments are matched */
821 			if (i == segs_cnt) {
822 				prof = p;
823 				break;
824 			}
825 		}
826 	ice_release_lock(&hw->fl_profs_locks[blk]);
827 
828 	return prof;
829 }
830 
831 /**
832  * ice_flow_find_prof - Look up a profile matching headers and matched fields
833  * @hw: pointer to the HW struct
834  * @blk: classification stage
835  * @dir: flow direction
836  * @segs: array of one or more packet segments that describe the flow
837  * @segs_cnt: number of packet segments provided
838  */
839 u64
840 ice_flow_find_prof(struct ice_hw *hw, enum ice_block blk, enum ice_flow_dir dir,
841 		   struct ice_flow_seg_info *segs, u8 segs_cnt)
842 {
843 	struct ice_flow_prof *p;
844 
845 	p = ice_flow_find_prof_conds(hw, blk, dir, segs, segs_cnt,
846 				     ICE_MAX_VSI, ICE_FLOW_FIND_PROF_CHK_FLDS);
847 
848 	return p ? p->id : ICE_FLOW_PROF_ID_INVAL;
849 }
850 
851 /**
852  * ice_flow_find_prof_id - Look up a profile with given profile ID
853  * @hw: pointer to the HW struct
854  * @blk: classification stage
855  * @prof_id: unique ID to identify this flow profile
856  */
857 static struct ice_flow_prof *
858 ice_flow_find_prof_id(struct ice_hw *hw, enum ice_block blk, u64 prof_id)
859 {
860 	struct ice_flow_prof *p;
861 
862 	LIST_FOR_EACH_ENTRY(p, &hw->fl_profs[blk], ice_flow_prof, l_entry)
863 		if (p->id == prof_id)
864 			return p;
865 
866 	return NULL;
867 }
868 
869 /**
870  * ice_flow_get_hw_prof - return the HW profile for a specific profile ID handle
871  * @hw: pointer to the HW struct
872  * @blk: classification stage
873  * @prof_id: the profile ID handle
874  * @hw_prof_id: pointer to variable to receive the HW profile ID
875  */
876 enum ice_status
877 ice_flow_get_hw_prof(struct ice_hw *hw, enum ice_block blk, u64 prof_id,
878 		     u8 *hw_prof_id)
879 {
880 	enum ice_status status = ICE_ERR_DOES_NOT_EXIST;
881 	struct ice_prof_map *map;
882 
883 	ice_acquire_lock(&hw->blk[blk].es.prof_map_lock);
884 	map = ice_search_prof_id(hw, blk, prof_id);
885 	if (map) {
886 		*hw_prof_id = map->prof_id;
887 		status = ICE_SUCCESS;
888 	}
889 	ice_release_lock(&hw->blk[blk].es.prof_map_lock);
890 	return status;
891 }
892 
893 /**
894  * ice_flow_add_prof_sync - Add a flow profile for packet segments and fields
895  * @hw: pointer to the HW struct
896  * @blk: classification stage
897  * @dir: flow direction
898  * @prof_id: unique ID to identify this flow profile
899  * @segs: array of one or more packet segments that describe the flow
900  * @segs_cnt: number of packet segments provided
901  * @acts: array of default actions
902  * @acts_cnt: number of default actions
903  * @prof: stores the returned flow profile added
904  *
905  * Assumption: the caller has acquired the lock to the profile list
906  */
907 static enum ice_status
908 ice_flow_add_prof_sync(struct ice_hw *hw, enum ice_block blk,
909 		       enum ice_flow_dir dir, u64 prof_id,
910 		       struct ice_flow_seg_info *segs, u8 segs_cnt,
911 		       struct ice_flow_action *acts, u8 acts_cnt,
912 		       struct ice_flow_prof **prof)
913 {
914 	struct ice_flow_prof_params *params;
915 	enum ice_status status;
916 	u8 i;
917 
918 	if (!prof || (acts_cnt && !acts))
919 		return ICE_ERR_BAD_PTR;
920 
921 	params = (struct ice_flow_prof_params *)ice_malloc(hw, sizeof(*params));
922 	if (!params)
923 		return ICE_ERR_NO_MEMORY;
924 
925 	params->prof = (struct ice_flow_prof *)
926 		ice_malloc(hw, sizeof(*params->prof));
927 	if (!params->prof) {
928 		status = ICE_ERR_NO_MEMORY;
929 		goto free_params;
930 	}
931 
932 	/* initialize extraction sequence to all invalid (0xff) */
933 	for (i = 0; i < ICE_MAX_FV_WORDS; i++) {
934 		params->es[i].prot_id = ICE_PROT_INVALID;
935 		params->es[i].off = ICE_FV_OFFSET_INVAL;
936 	}
937 
938 	params->blk = blk;
939 	params->prof->id = prof_id;
940 	params->prof->dir = dir;
941 	params->prof->segs_cnt = segs_cnt;
942 
943 	/* Make a copy of the segments that need to be persistent in the flow
944 	 * profile instance
945 	 */
946 	for (i = 0; i < segs_cnt; i++)
947 		ice_memcpy(&params->prof->segs[i], &segs[i], sizeof(*segs),
948 			   ICE_NONDMA_TO_NONDMA);
949 
950 	status = ice_flow_proc_segs(hw, params);
951 	if (status) {
952 		ice_debug(hw, ICE_DBG_FLOW, "Error processing a flow's packet segments\n");
953 		goto out;
954 	}
955 
956 	/* Add a HW profile for this flow profile */
957 	status = ice_add_prof(hw, blk, prof_id, params->ptypes, params->es);
958 	if (status) {
959 		ice_debug(hw, ICE_DBG_FLOW, "Error adding a HW flow profile\n");
960 		goto out;
961 	}
962 
963 	*prof = params->prof;
964 
965 out:
966 	if (status) {
967 		ice_free(hw, params->prof);
968 	}
969 free_params:
970 	ice_free(hw, params);
971 
972 	return status;
973 }
974 
975 /**
976  * ice_flow_rem_prof_sync - remove a flow profile
977  * @hw: pointer to the hardware structure
978  * @blk: classification stage
979  * @prof: pointer to flow profile to remove
980  *
981  * Assumption: the caller has acquired the lock to the profile list
982  */
983 static enum ice_status
984 ice_flow_rem_prof_sync(struct ice_hw *hw, enum ice_block blk,
985 		       struct ice_flow_prof *prof)
986 {
987 	enum ice_status status;
988 
989 	/* Remove all hardware profiles associated with this flow profile */
990 	status = ice_rem_prof(hw, blk, prof->id);
991 	if (!status) {
992 		LIST_DEL(&prof->l_entry);
993 		ice_free(hw, prof);
994 	}
995 
996 	return status;
997 }
998 
999 /**
1000  * ice_flow_assoc_vsig_vsi - associate a VSI with VSIG
1001  * @hw: pointer to the hardware structure
1002  * @blk: classification stage
1003  * @vsi_handle: software VSI handle
1004  * @vsig: target VSI group
1005  *
1006  * Assumption: the caller has already verified that the VSI to
1007  * be added has the same characteristics as the VSIG and will
1008  * thereby have access to all resources added to that VSIG.
1009  */
1010 enum ice_status
1011 ice_flow_assoc_vsig_vsi(struct ice_hw *hw, enum ice_block blk, u16 vsi_handle,
1012 			u16 vsig)
1013 {
1014 	enum ice_status status;
1015 
1016 	if (!ice_is_vsi_valid(hw, vsi_handle) || blk >= ICE_BLK_COUNT)
1017 		return ICE_ERR_PARAM;
1018 
1019 	ice_acquire_lock(&hw->fl_profs_locks[blk]);
1020 	status = ice_add_vsi_flow(hw, blk, ice_get_hw_vsi_num(hw, vsi_handle),
1021 				  vsig);
1022 	ice_release_lock(&hw->fl_profs_locks[blk]);
1023 
1024 	return status;
1025 }
1026 
1027 /**
1028  * ice_flow_assoc_prof - associate a VSI with a flow profile
1029  * @hw: pointer to the hardware structure
1030  * @blk: classification stage
1031  * @prof: pointer to flow profile
1032  * @vsi_handle: software VSI handle
1033  *
1034  * Assumption: the caller has acquired the lock to the profile list
1035  * and the software VSI handle has been validated
1036  */
1037 static enum ice_status
1038 ice_flow_assoc_prof(struct ice_hw *hw, enum ice_block blk,
1039 		    struct ice_flow_prof *prof, u16 vsi_handle)
1040 {
1041 	enum ice_status status = ICE_SUCCESS;
1042 
1043 	if (!ice_is_bit_set(prof->vsis, vsi_handle)) {
1044 		status = ice_add_prof_id_flow(hw, blk,
1045 					      ice_get_hw_vsi_num(hw,
1046 								 vsi_handle),
1047 					      prof->id);
1048 		if (!status)
1049 			ice_set_bit(vsi_handle, prof->vsis);
1050 		else
1051 			ice_debug(hw, ICE_DBG_FLOW, "HW profile add failed, %d\n",
1052 				  status);
1053 	}
1054 
1055 	return status;
1056 }
1057 
1058 /**
1059  * ice_flow_disassoc_prof - disassociate a VSI from a flow profile
1060  * @hw: pointer to the hardware structure
1061  * @blk: classification stage
1062  * @prof: pointer to flow profile
1063  * @vsi_handle: software VSI handle
1064  *
1065  * Assumption: the caller has acquired the lock to the profile list
1066  * and the software VSI handle has been validated
1067  */
1068 static enum ice_status
1069 ice_flow_disassoc_prof(struct ice_hw *hw, enum ice_block blk,
1070 		       struct ice_flow_prof *prof, u16 vsi_handle)
1071 {
1072 	enum ice_status status = ICE_SUCCESS;
1073 
1074 	if (ice_is_bit_set(prof->vsis, vsi_handle)) {
1075 		status = ice_rem_prof_id_flow(hw, blk,
1076 					      ice_get_hw_vsi_num(hw,
1077 								 vsi_handle),
1078 					      prof->id);
1079 		if (!status)
1080 			ice_clear_bit(vsi_handle, prof->vsis);
1081 		else
1082 			ice_debug(hw, ICE_DBG_FLOW, "HW profile remove failed, %d\n",
1083 				  status);
1084 	}
1085 
1086 	return status;
1087 }
1088 
1089 /**
1090  * ice_flow_add_prof - Add a flow profile for packet segments and matched fields
1091  * @hw: pointer to the HW struct
1092  * @blk: classification stage
1093  * @dir: flow direction
1094  * @prof_id: unique ID to identify this flow profile
1095  * @segs: array of one or more packet segments that describe the flow
1096  * @segs_cnt: number of packet segments provided
1097  * @acts: array of default actions
1098  * @acts_cnt: number of default actions
1099  * @prof: stores the returned flow profile added
1100  */
1101 static enum ice_status
1102 ice_flow_add_prof(struct ice_hw *hw, enum ice_block blk, enum ice_flow_dir dir,
1103 		  u64 prof_id, struct ice_flow_seg_info *segs, u8 segs_cnt,
1104 		  struct ice_flow_action *acts, u8 acts_cnt,
1105 		  struct ice_flow_prof **prof)
1106 {
1107 	enum ice_status status;
1108 
1109 	if (segs_cnt > ICE_FLOW_SEG_MAX)
1110 		return ICE_ERR_MAX_LIMIT;
1111 
1112 	if (!segs_cnt)
1113 		return ICE_ERR_PARAM;
1114 
1115 	if (!segs)
1116 		return ICE_ERR_BAD_PTR;
1117 
1118 	status = ice_flow_val_hdrs(segs, segs_cnt);
1119 	if (status)
1120 		return status;
1121 
1122 	ice_acquire_lock(&hw->fl_profs_locks[blk]);
1123 
1124 	status = ice_flow_add_prof_sync(hw, blk, dir, prof_id, segs, segs_cnt,
1125 					acts, acts_cnt, prof);
1126 	if (!status)
1127 		LIST_ADD(&(*prof)->l_entry, &hw->fl_profs[blk]);
1128 
1129 	ice_release_lock(&hw->fl_profs_locks[blk]);
1130 
1131 	return status;
1132 }
1133 
1134 /**
1135  * ice_flow_rem_prof - Remove a flow profile and all entries associated with it
1136  * @hw: pointer to the HW struct
1137  * @blk: the block for which the flow profile is to be removed
1138  * @prof_id: unique ID of the flow profile to be removed
1139  */
1140 static enum ice_status
1141 ice_flow_rem_prof(struct ice_hw *hw, enum ice_block blk, u64 prof_id)
1142 {
1143 	struct ice_flow_prof *prof;
1144 	enum ice_status status;
1145 
1146 	ice_acquire_lock(&hw->fl_profs_locks[blk]);
1147 
1148 	prof = ice_flow_find_prof_id(hw, blk, prof_id);
1149 	if (!prof) {
1150 		status = ICE_ERR_DOES_NOT_EXIST;
1151 		goto out;
1152 	}
1153 
1154 	/* prof becomes invalid after the call */
1155 	status = ice_flow_rem_prof_sync(hw, blk, prof);
1156 
1157 out:
1158 	ice_release_lock(&hw->fl_profs_locks[blk]);
1159 
1160 	return status;
1161 }
1162 
1163 /**
1164  * ice_flow_set_fld_ext - specifies locations of field from entry's input buffer
1165  * @seg: packet segment the field being set belongs to
1166  * @fld: field to be set
1167  * @field_type: type of the field
1168  * @val_loc: if not ICE_FLOW_FLD_OFF_INVAL, location of the value to match from
1169  *           entry's input buffer
1170  * @mask_loc: if not ICE_FLOW_FLD_OFF_INVAL, location of mask value from entry's
1171  *            input buffer
1172  * @last_loc: if not ICE_FLOW_FLD_OFF_INVAL, location of last/upper value from
1173  *            entry's input buffer
1174  *
1175  * This helper function stores information of a field being matched, including
1176  * the type of the field and the locations of the value to match, the mask, and
1177  * the upper-bound value in the start of the input buffer for a flow entry.
1178  * This function should only be used for fixed-size data structures.
1179  *
1180  * This function also opportunistically determines the protocol headers to be
1181  * present based on the fields being set. Some fields cannot be used alone to
1182  * determine the protocol headers present. Sometimes, fields for particular
1183  * protocol headers are not matched. In those cases, the protocol headers
1184  * must be explicitly set.
1185  */
1186 static void
1187 ice_flow_set_fld_ext(struct ice_flow_seg_info *seg, enum ice_flow_field fld,
1188 		     enum ice_flow_fld_match_type field_type, u16 val_loc,
1189 		     u16 mask_loc, u16 last_loc)
1190 {
1191 	ice_set_bit(fld, seg->match);
1192 	if (field_type == ICE_FLOW_FLD_TYPE_RANGE)
1193 		ice_set_bit(fld, seg->range);
1194 
1195 	seg->fields[fld].type = field_type;
1196 	seg->fields[fld].src.val = val_loc;
1197 	seg->fields[fld].src.mask = mask_loc;
1198 	seg->fields[fld].src.last = last_loc;
1199 
1200 	ICE_FLOW_SET_HDRS(seg, ice_flds_info[fld].hdr);
1201 }
1202 
1203 /**
1204  * ice_flow_set_fld - specifies locations of field from entry's input buffer
1205  * @seg: packet segment the field being set belongs to
1206  * @fld: field to be set
1207  * @val_loc: if not ICE_FLOW_FLD_OFF_INVAL, location of the value to match from
1208  *           entry's input buffer
1209  * @mask_loc: if not ICE_FLOW_FLD_OFF_INVAL, location of mask value from entry's
1210  *            input buffer
1211  * @last_loc: if not ICE_FLOW_FLD_OFF_INVAL, location of last/upper value from
1212  *            entry's input buffer
1213  * @range: indicate if field being matched is to be in a range
1214  *
1215  * This function specifies the locations, in the form of byte offsets from the
1216  * start of the input buffer for a flow entry, from where the value to match,
1217  * the mask value, and upper value can be extracted. These locations are then
1218  * stored in the flow profile. When adding a flow entry associated with the
1219  * flow profile, these locations will be used to quickly extract the values and
1220  * create the content of a match entry. This function should only be used for
1221  * fixed-size data structures.
1222  */
1223 static void
1224 ice_flow_set_fld(struct ice_flow_seg_info *seg, enum ice_flow_field fld,
1225 		 u16 val_loc, u16 mask_loc, u16 last_loc, bool range)
1226 {
1227 	enum ice_flow_fld_match_type t = range ?
1228 		ICE_FLOW_FLD_TYPE_RANGE : ICE_FLOW_FLD_TYPE_REG;
1229 
1230 	ice_flow_set_fld_ext(seg, fld, t, val_loc, mask_loc, last_loc);
1231 }
1232 
1233 /**
1234  * ice_flow_set_fld_prefix - sets locations of prefix field from entry's buf
1235  * @seg: packet segment the field being set belongs to
1236  * @fld: field to be set
1237  * @val_loc: if not ICE_FLOW_FLD_OFF_INVAL, location of the value to match from
1238  *           entry's input buffer
1239  * @pref_loc: location of prefix value from entry's input buffer
1240  * @pref_sz: size of the location holding the prefix value
1241  *
1242  * This function specifies the locations, in the form of byte offsets from the
1243  * start of the input buffer for a flow entry, from where the value to match
1244  * and the IPv4 prefix value can be extracted. These locations are then stored
1245  * in the flow profile. When adding flow entries to the associated flow profile,
1246  * these locations can be used to quickly extract the values to create the
1247  * content of a match entry. This function should only be used for fixed-size
1248  * data structures.
1249  */
1250 void
1251 ice_flow_set_fld_prefix(struct ice_flow_seg_info *seg, enum ice_flow_field fld,
1252 			u16 val_loc, u16 pref_loc, u8 pref_sz)
1253 {
1254 	/* For this type of field, the "mask" location is for the prefix value's
1255 	 * location and the "last" location is for the size of the location of
1256 	 * the prefix value.
1257 	 */
1258 	ice_flow_set_fld_ext(seg, fld, ICE_FLOW_FLD_TYPE_PREFIX, val_loc,
1259 			     pref_loc, (u16)pref_sz);
1260 }
1261 
1262 #define ICE_FLOW_RSS_SEG_HDR_L3_MASKS \
1263 	(ICE_FLOW_SEG_HDR_IPV4 | ICE_FLOW_SEG_HDR_IPV6)
1264 
1265 #define ICE_FLOW_RSS_SEG_HDR_L4_MASKS \
1266 	(ICE_FLOW_SEG_HDR_TCP | ICE_FLOW_SEG_HDR_UDP | ICE_FLOW_SEG_HDR_SCTP)
1267 
1268 #define ICE_FLOW_RSS_SEG_HDR_VAL_MASKS \
1269 	(ICE_FLOW_RSS_SEG_HDR_L3_MASKS | \
1270 	 ICE_FLOW_RSS_SEG_HDR_L4_MASKS)
1271 
1272 /**
1273  * ice_flow_set_rss_seg_info - setup packet segments for RSS
1274  * @segs: pointer to the flow field segment(s)
1275  * @seg_cnt: segment count
1276  * @cfg: configure parameters
1277  *
1278  * Helper function to extract fields from hash bitmap and use flow
1279  * header value to set flow field segment for further use in flow
1280  * profile entry or removal.
1281  */
1282 static enum ice_status
1283 ice_flow_set_rss_seg_info(struct ice_flow_seg_info *segs, u8 seg_cnt,
1284 			  const struct ice_rss_hash_cfg *cfg)
1285 {
1286 	struct ice_flow_seg_info *seg;
1287 	u64 val;
1288 	u16 i;
1289 
1290 	/* set inner most segment */
1291 	seg = &segs[seg_cnt - 1];
1292 
1293 	ice_for_each_set_bit(i, (const ice_bitmap_t *)&cfg->hash_flds,
1294 			     (u16)ICE_FLOW_FIELD_IDX_MAX)
1295 		ice_flow_set_fld(seg, (enum ice_flow_field)i,
1296 				 ICE_FLOW_FLD_OFF_INVAL, ICE_FLOW_FLD_OFF_INVAL,
1297 				 ICE_FLOW_FLD_OFF_INVAL, false);
1298 
1299 	ICE_FLOW_SET_HDRS(seg, cfg->addl_hdrs);
1300 
1301 	/* set outer most header */
1302 	if (cfg->hdr_type == ICE_RSS_INNER_HEADERS_W_OUTER_IPV4)
1303 		segs[ICE_RSS_OUTER_HEADERS].hdrs |= ICE_FLOW_SEG_HDR_IPV4 |
1304 						   ICE_FLOW_SEG_HDR_IPV_FRAG |
1305 						   ICE_FLOW_SEG_HDR_IPV_OTHER;
1306 	else if (cfg->hdr_type == ICE_RSS_INNER_HEADERS_W_OUTER_IPV6)
1307 		segs[ICE_RSS_OUTER_HEADERS].hdrs |= ICE_FLOW_SEG_HDR_IPV6 |
1308 						   ICE_FLOW_SEG_HDR_IPV_FRAG |
1309 						   ICE_FLOW_SEG_HDR_IPV_OTHER;
1310 	else if (cfg->hdr_type == ICE_RSS_INNER_HEADERS_W_OUTER_IPV4_GRE)
1311 		segs[ICE_RSS_OUTER_HEADERS].hdrs |= ICE_FLOW_SEG_HDR_IPV4 |
1312 						   ICE_FLOW_SEG_HDR_GRE |
1313 						   ICE_FLOW_SEG_HDR_IPV_OTHER;
1314 	else if (cfg->hdr_type == ICE_RSS_INNER_HEADERS_W_OUTER_IPV6_GRE)
1315 		segs[ICE_RSS_OUTER_HEADERS].hdrs |= ICE_FLOW_SEG_HDR_IPV6 |
1316 						   ICE_FLOW_SEG_HDR_GRE |
1317 						   ICE_FLOW_SEG_HDR_IPV_OTHER;
1318 
1319 	if (seg->hdrs & ~ICE_FLOW_RSS_SEG_HDR_VAL_MASKS)
1320 		return ICE_ERR_PARAM;
1321 
1322 	val = (u64)(seg->hdrs & ICE_FLOW_RSS_SEG_HDR_L3_MASKS);
1323 	if (val && !ice_is_pow2(val))
1324 		return ICE_ERR_CFG;
1325 
1326 	val = (u64)(seg->hdrs & ICE_FLOW_RSS_SEG_HDR_L4_MASKS);
1327 	if (val && !ice_is_pow2(val))
1328 		return ICE_ERR_CFG;
1329 
1330 	return ICE_SUCCESS;
1331 }
1332 
1333 /**
1334  * ice_rem_vsi_rss_list - remove VSI from RSS list
1335  * @hw: pointer to the hardware structure
1336  * @vsi_handle: software VSI handle
1337  *
1338  * Remove the VSI from all RSS configurations in the list.
1339  */
1340 void ice_rem_vsi_rss_list(struct ice_hw *hw, u16 vsi_handle)
1341 {
1342 	struct ice_rss_cfg *r, *tmp;
1343 
1344 	if (LIST_EMPTY(&hw->rss_list_head))
1345 		return;
1346 
1347 	ice_acquire_lock(&hw->rss_locks);
1348 	LIST_FOR_EACH_ENTRY_SAFE(r, tmp, &hw->rss_list_head,
1349 				 ice_rss_cfg, l_entry)
1350 		if (ice_test_and_clear_bit(vsi_handle, r->vsis))
1351 			if (!ice_is_any_bit_set(r->vsis, ICE_MAX_VSI)) {
1352 				LIST_DEL(&r->l_entry);
1353 				ice_free(hw, r);
1354 			}
1355 	ice_release_lock(&hw->rss_locks);
1356 }
1357 
1358 /**
1359  * ice_rem_vsi_rss_cfg - remove RSS configurations associated with VSI
1360  * @hw: pointer to the hardware structure
1361  * @vsi_handle: software VSI handle
1362  *
1363  * This function will iterate through all flow profiles and disassociate
1364  * the VSI from that profile. If the flow profile has no VSIs it will
1365  * be removed.
1366  */
1367 enum ice_status ice_rem_vsi_rss_cfg(struct ice_hw *hw, u16 vsi_handle)
1368 {
1369 	const enum ice_block blk = ICE_BLK_RSS;
1370 	struct ice_flow_prof *p, *t;
1371 	enum ice_status status = ICE_SUCCESS;
1372 	u16 vsig;
1373 
1374 	if (!ice_is_vsi_valid(hw, vsi_handle))
1375 		return ICE_ERR_PARAM;
1376 
1377 	if (LIST_EMPTY(&hw->fl_profs[blk]))
1378 		return ICE_SUCCESS;
1379 
1380 	ice_acquire_lock(&hw->rss_locks);
1381 	LIST_FOR_EACH_ENTRY_SAFE(p, t, &hw->fl_profs[blk], ice_flow_prof,
1382 				 l_entry) {
1383 		int ret;
1384 
1385 		/* check if vsig is already removed */
1386 		ret = ice_vsig_find_vsi(hw, blk,
1387 					ice_get_hw_vsi_num(hw, vsi_handle),
1388 					&vsig);
1389 		if (!ret && !vsig)
1390 			break;
1391 
1392 		if (ice_is_bit_set(p->vsis, vsi_handle)) {
1393 			status = ice_flow_disassoc_prof(hw, blk, p, vsi_handle);
1394 			if (status)
1395 				break;
1396 
1397 			if (!ice_is_any_bit_set(p->vsis, ICE_MAX_VSI)) {
1398 				status = ice_flow_rem_prof(hw, blk, p->id);
1399 				if (status)
1400 					break;
1401 			}
1402 		}
1403 	}
1404 	ice_release_lock(&hw->rss_locks);
1405 
1406 	return status;
1407 }
1408 
1409 /**
1410  * ice_get_rss_hdr_type - get a RSS profile's header type
1411  * @prof: RSS flow profile
1412  */
1413 static enum ice_rss_cfg_hdr_type
1414 ice_get_rss_hdr_type(struct ice_flow_prof *prof)
1415 {
1416 	enum ice_rss_cfg_hdr_type hdr_type = ICE_RSS_ANY_HEADERS;
1417 
1418 	if (prof->segs_cnt == ICE_FLOW_SEG_SINGLE) {
1419 		hdr_type = ICE_RSS_OUTER_HEADERS;
1420 	} else if (prof->segs_cnt == ICE_FLOW_SEG_MAX) {
1421 		if (prof->segs[ICE_RSS_OUTER_HEADERS].hdrs == ICE_FLOW_SEG_HDR_NONE)
1422 			hdr_type = ICE_RSS_INNER_HEADERS;
1423 		if (prof->segs[ICE_RSS_OUTER_HEADERS].hdrs & ICE_FLOW_SEG_HDR_IPV4)
1424 			hdr_type = ICE_RSS_INNER_HEADERS_W_OUTER_IPV4;
1425 		if (prof->segs[ICE_RSS_OUTER_HEADERS].hdrs & ICE_FLOW_SEG_HDR_IPV6)
1426 			hdr_type = ICE_RSS_INNER_HEADERS_W_OUTER_IPV6;
1427 	}
1428 
1429 	return hdr_type;
1430 }
1431 
1432 /**
1433  * ice_rem_rss_list - remove RSS configuration from list
1434  * @hw: pointer to the hardware structure
1435  * @vsi_handle: software VSI handle
1436  * @prof: pointer to flow profile
1437  *
1438  * Assumption: lock has already been acquired for RSS list
1439  */
1440 static void
1441 ice_rem_rss_list(struct ice_hw *hw, u16 vsi_handle, struct ice_flow_prof *prof)
1442 {
1443 	enum ice_rss_cfg_hdr_type hdr_type;
1444 	struct ice_rss_cfg *r, *tmp;
1445 	u64 seg_match = 0;
1446 	u16 i;
1447 
1448 	/* convert match bitmap to u64 for hash field comparison */
1449 	ice_for_each_set_bit(i, prof->segs[prof->segs_cnt - 1].match,
1450 			     ICE_FLOW_FIELD_IDX_MAX) {
1451 		seg_match |= 1ULL << i;
1452 	}
1453 
1454 	/* Search for RSS hash fields associated to the VSI that match the
1455 	 * hash configurations associated to the flow profile. If found
1456 	 * remove from the RSS entry list of the VSI context and delete entry.
1457 	 */
1458 	hdr_type = ice_get_rss_hdr_type(prof);
1459 	LIST_FOR_EACH_ENTRY_SAFE(r, tmp, &hw->rss_list_head,
1460 				 ice_rss_cfg, l_entry)
1461 		if (r->hash.hash_flds == seg_match &&
1462 		    r->hash.addl_hdrs == prof->segs[prof->segs_cnt - 1].hdrs &&
1463 		    r->hash.hdr_type == hdr_type) {
1464 			ice_clear_bit(vsi_handle, r->vsis);
1465 			if (!ice_is_any_bit_set(r->vsis, ICE_MAX_VSI)) {
1466 				LIST_DEL(&r->l_entry);
1467 				ice_free(hw, r);
1468 			}
1469 			return;
1470 		}
1471 }
1472 
1473 /**
1474  * ice_add_rss_list - add RSS configuration to list
1475  * @hw: pointer to the hardware structure
1476  * @vsi_handle: software VSI handle
1477  * @prof: pointer to flow profile
1478  *
1479  * Assumption: lock has already been acquired for RSS list
1480  */
1481 static enum ice_status
1482 ice_add_rss_list(struct ice_hw *hw, u16 vsi_handle, struct ice_flow_prof *prof)
1483 {
1484 	enum ice_rss_cfg_hdr_type hdr_type;
1485 	struct ice_rss_cfg *r, *rss_cfg;
1486 	u64 seg_match = 0;
1487 	u16 i;
1488 
1489 	ice_for_each_set_bit(i, prof->segs[prof->segs_cnt - 1].match,
1490 			     ICE_FLOW_FIELD_IDX_MAX) {
1491 		seg_match |= 1ULL << i;
1492 	}
1493 
1494 	hdr_type = ice_get_rss_hdr_type(prof);
1495 	LIST_FOR_EACH_ENTRY(r, &hw->rss_list_head,
1496 			    ice_rss_cfg, l_entry)
1497 		if (r->hash.hash_flds == seg_match &&
1498 		    r->hash.addl_hdrs == prof->segs[prof->segs_cnt - 1].hdrs &&
1499 		    r->hash.hdr_type == hdr_type) {
1500 			ice_set_bit(vsi_handle, r->vsis);
1501 			return ICE_SUCCESS;
1502 		}
1503 
1504 	rss_cfg = (struct ice_rss_cfg *)ice_malloc(hw, sizeof(*rss_cfg));
1505 	if (!rss_cfg)
1506 		return ICE_ERR_NO_MEMORY;
1507 
1508 	rss_cfg->hash.hash_flds = seg_match;
1509 	rss_cfg->hash.addl_hdrs = prof->segs[prof->segs_cnt - 1].hdrs;
1510 	rss_cfg->hash.hdr_type = hdr_type;
1511 	rss_cfg->hash.symm = prof->cfg.symm;
1512 	ice_set_bit(vsi_handle, rss_cfg->vsis);
1513 
1514 	LIST_ADD_TAIL(&rss_cfg->l_entry, &hw->rss_list_head);
1515 
1516 	return ICE_SUCCESS;
1517 }
1518 
1519 #define ICE_FLOW_PROF_HASH_S	0
1520 #define ICE_FLOW_PROF_HASH_M	(0xFFFFFFFFULL << ICE_FLOW_PROF_HASH_S)
1521 #define ICE_FLOW_PROF_HDR_S	32
1522 #define ICE_FLOW_PROF_HDR_M	(0x3FFFFFFFULL << ICE_FLOW_PROF_HDR_S)
1523 #define ICE_FLOW_PROF_ENCAP_S	62
1524 #define ICE_FLOW_PROF_ENCAP_M	(0x3ULL << ICE_FLOW_PROF_ENCAP_S)
1525 
1526 /* Flow profile ID format:
1527  * [0:31] - Packet match fields
1528  * [32:61] - Protocol header
1529  * [62:63] - Encapsulation flag:
1530  *	     0 if non-tunneled
1531  *	     1 if tunneled
1532  *	     2 for tunneled with outer ipv4
1533  *	     3 for tunneled with outer ipv6
1534  */
1535 #define ICE_FLOW_GEN_PROFID(hash, hdr, encap) \
1536 	((u64)(((u64)(hash) & ICE_FLOW_PROF_HASH_M) | \
1537 	       (((u64)(hdr) << ICE_FLOW_PROF_HDR_S) & ICE_FLOW_PROF_HDR_M) | \
1538 	       (((u64)(encap) << ICE_FLOW_PROF_ENCAP_S) & ICE_FLOW_PROF_ENCAP_M)))
1539 
1540 /**
1541  * ice_add_rss_cfg_sync - add an RSS configuration
1542  * @hw: pointer to the hardware structure
1543  * @vsi_handle: software VSI handle
1544  * @cfg: configure parameters
1545  *
1546  * Assumption: lock has already been acquired for RSS list
1547  */
1548 static enum ice_status
1549 ice_add_rss_cfg_sync(struct ice_hw *hw, u16 vsi_handle,
1550 		     const struct ice_rss_hash_cfg *cfg)
1551 {
1552 	const enum ice_block blk = ICE_BLK_RSS;
1553 	struct ice_flow_prof *prof = NULL;
1554 	struct ice_flow_seg_info *segs;
1555 	enum ice_status status;
1556 	u8 segs_cnt;
1557 
1558 	if (cfg->symm)
1559 		return ICE_ERR_PARAM;
1560 
1561 	segs_cnt = (cfg->hdr_type == ICE_RSS_OUTER_HEADERS) ?
1562 			ICE_FLOW_SEG_SINGLE : ICE_FLOW_SEG_MAX;
1563 
1564 	segs = (struct ice_flow_seg_info *)ice_calloc(hw, segs_cnt,
1565 						      sizeof(*segs));
1566 	if (!segs)
1567 		return ICE_ERR_NO_MEMORY;
1568 
1569 	/* Construct the packet segment info from the hashed fields */
1570 	status = ice_flow_set_rss_seg_info(segs, segs_cnt, cfg);
1571 	if (status)
1572 		goto exit;
1573 
1574 	/* Search for a flow profile that has matching headers, hash fields
1575 	 * and has the input VSI associated to it. If found, no further
1576 	 * operations required and exit.
1577 	 */
1578 	prof = ice_flow_find_prof_conds(hw, blk, ICE_FLOW_RX, segs, segs_cnt,
1579 					vsi_handle,
1580 					ICE_FLOW_FIND_PROF_CHK_FLDS |
1581 					ICE_FLOW_FIND_PROF_CHK_VSI);
1582 	if (prof)
1583 		goto exit;
1584 
1585 	/* Check if a flow profile exists with the same protocol headers and
1586 	 * associated with the input VSI. If so disassociate the VSI from
1587 	 * this profile. The VSI will be added to a new profile created with
1588 	 * the protocol header and new hash field configuration.
1589 	 */
1590 	prof = ice_flow_find_prof_conds(hw, blk, ICE_FLOW_RX, segs, segs_cnt,
1591 					vsi_handle, ICE_FLOW_FIND_PROF_CHK_VSI);
1592 	if (prof) {
1593 		status = ice_flow_disassoc_prof(hw, blk, prof, vsi_handle);
1594 		if (!status)
1595 			ice_rem_rss_list(hw, vsi_handle, prof);
1596 		else
1597 			goto exit;
1598 
1599 		/* Remove profile if it has no VSIs associated */
1600 		if (!ice_is_any_bit_set(prof->vsis, ICE_MAX_VSI)) {
1601 			status = ice_flow_rem_prof(hw, blk, prof->id);
1602 			if (status)
1603 				goto exit;
1604 		}
1605 	}
1606 
1607 	/* Search for a profile that has same match fields only. If this
1608 	 * exists then associate the VSI to this profile.
1609 	 */
1610 	prof = ice_flow_find_prof_conds(hw, blk, ICE_FLOW_RX, segs, segs_cnt,
1611 					vsi_handle,
1612 					ICE_FLOW_FIND_PROF_CHK_FLDS);
1613 	if (prof) {
1614 		status = ice_flow_assoc_prof(hw, blk, prof, vsi_handle);
1615 		if (!status)
1616 			status = ice_add_rss_list(hw, vsi_handle, prof);
1617 		goto exit;
1618 	}
1619 
1620 	/* Create a new flow profile with generated profile and packet
1621 	 * segment information.
1622 	 */
1623 	status = ice_flow_add_prof(hw, blk, ICE_FLOW_RX,
1624 				   ICE_FLOW_GEN_PROFID(cfg->hash_flds,
1625 						       segs[segs_cnt - 1].hdrs,
1626 						       cfg->hdr_type),
1627 				   segs, segs_cnt, NULL, 0, &prof);
1628 	if (status)
1629 		goto exit;
1630 
1631 	status = ice_flow_assoc_prof(hw, blk, prof, vsi_handle);
1632 	/* If association to a new flow profile failed then this profile can
1633 	 * be removed.
1634 	 */
1635 	if (status) {
1636 		ice_flow_rem_prof(hw, blk, prof->id);
1637 		goto exit;
1638 	}
1639 
1640 	status = ice_add_rss_list(hw, vsi_handle, prof);
1641 
1642 	prof->cfg.symm = cfg->symm;
1643 
1644 exit:
1645 	ice_free(hw, segs);
1646 	return status;
1647 }
1648 
1649 /**
1650  * ice_add_rss_cfg - add an RSS configuration with specified hashed fields
1651  * @hw: pointer to the hardware structure
1652  * @vsi_handle: software VSI handle
1653  * @cfg: configure parameters
1654  *
1655  * This function will generate a flow profile based on fields associated with
1656  * the input fields to hash on, the flow type and use the VSI number to add
1657  * a flow entry to the profile.
1658  */
1659 enum ice_status
1660 ice_add_rss_cfg(struct ice_hw *hw, u16 vsi_handle,
1661 		const struct ice_rss_hash_cfg *cfg)
1662 {
1663 	struct ice_rss_hash_cfg local_cfg;
1664 	enum ice_status status;
1665 
1666 	if (!ice_is_vsi_valid(hw, vsi_handle) ||
1667 	    !cfg || cfg->hdr_type > ICE_RSS_ANY_HEADERS ||
1668 	    cfg->hash_flds == ICE_HASH_INVALID)
1669 		return ICE_ERR_PARAM;
1670 
1671 	local_cfg = *cfg;
1672 	if (cfg->hdr_type < ICE_RSS_ANY_HEADERS) {
1673 		ice_acquire_lock(&hw->rss_locks);
1674 		status = ice_add_rss_cfg_sync(hw, vsi_handle, &local_cfg);
1675 		ice_release_lock(&hw->rss_locks);
1676 	} else {
1677 		ice_acquire_lock(&hw->rss_locks);
1678 		local_cfg.hdr_type = ICE_RSS_OUTER_HEADERS;
1679 		status = ice_add_rss_cfg_sync(hw, vsi_handle, &local_cfg);
1680 		if (!status) {
1681 			local_cfg.hdr_type = ICE_RSS_INNER_HEADERS;
1682 			status = ice_add_rss_cfg_sync(hw, vsi_handle,
1683 						      &local_cfg);
1684 		}
1685 		ice_release_lock(&hw->rss_locks);
1686 	}
1687 
1688 	return status;
1689 }
1690 
1691 /**
1692  * ice_rem_rss_cfg_sync - remove an existing RSS configuration
1693  * @hw: pointer to the hardware structure
1694  * @vsi_handle: software VSI handle
1695  * @cfg: configure parameters
1696  *
1697  * Assumption: lock has already been acquired for RSS list
1698  */
1699 static enum ice_status
1700 ice_rem_rss_cfg_sync(struct ice_hw *hw, u16 vsi_handle,
1701 		     const struct ice_rss_hash_cfg *cfg)
1702 {
1703 	const enum ice_block blk = ICE_BLK_RSS;
1704 	struct ice_flow_seg_info *segs;
1705 	struct ice_flow_prof *prof;
1706 	enum ice_status status;
1707 	u8 segs_cnt;
1708 
1709 	segs_cnt = (cfg->hdr_type == ICE_RSS_OUTER_HEADERS) ?
1710 			ICE_FLOW_SEG_SINGLE : ICE_FLOW_SEG_MAX;
1711 	segs = (struct ice_flow_seg_info *)ice_calloc(hw, segs_cnt,
1712 						      sizeof(*segs));
1713 	if (!segs)
1714 		return ICE_ERR_NO_MEMORY;
1715 
1716 	/* Construct the packet segment info from the hashed fields */
1717 	status = ice_flow_set_rss_seg_info(segs, segs_cnt, cfg);
1718 	if (status)
1719 		goto out;
1720 
1721 	prof = ice_flow_find_prof_conds(hw, blk, ICE_FLOW_RX, segs, segs_cnt,
1722 					vsi_handle,
1723 					ICE_FLOW_FIND_PROF_CHK_FLDS);
1724 	if (!prof) {
1725 		status = ICE_ERR_DOES_NOT_EXIST;
1726 		goto out;
1727 	}
1728 
1729 	status = ice_flow_disassoc_prof(hw, blk, prof, vsi_handle);
1730 	if (status)
1731 		goto out;
1732 
1733 	/* Remove RSS configuration from VSI context before deleting
1734 	 * the flow profile.
1735 	 */
1736 	ice_rem_rss_list(hw, vsi_handle, prof);
1737 
1738 	if (!ice_is_any_bit_set(prof->vsis, ICE_MAX_VSI))
1739 		status = ice_flow_rem_prof(hw, blk, prof->id);
1740 
1741 out:
1742 	ice_free(hw, segs);
1743 	return status;
1744 }
1745 
1746 /**
1747  * ice_rem_rss_cfg - remove an existing RSS config with matching hashed fields
1748  * @hw: pointer to the hardware structure
1749  * @vsi_handle: software VSI handle
1750  * @cfg: configure parameters
1751  *
1752  * This function will lookup the flow profile based on the input
1753  * hash field bitmap, iterate through the profile entry list of
1754  * that profile and find entry associated with input VSI to be
1755  * removed. Calls are made to underlying flow apis which will in
1756  * turn build or update buffers for RSS XLT1 section.
1757  */
1758 enum ice_status
1759 ice_rem_rss_cfg(struct ice_hw *hw, u16 vsi_handle,
1760 		const struct ice_rss_hash_cfg *cfg)
1761 {
1762 	struct ice_rss_hash_cfg local_cfg;
1763 	enum ice_status status;
1764 
1765 	if (!ice_is_vsi_valid(hw, vsi_handle) ||
1766 	    !cfg || cfg->hdr_type > ICE_RSS_ANY_HEADERS ||
1767 	    cfg->hash_flds == ICE_HASH_INVALID)
1768 		return ICE_ERR_PARAM;
1769 
1770 	ice_acquire_lock(&hw->rss_locks);
1771 	local_cfg = *cfg;
1772 	if (cfg->hdr_type < ICE_RSS_ANY_HEADERS) {
1773 		status = ice_rem_rss_cfg_sync(hw, vsi_handle, &local_cfg);
1774 	} else {
1775 		local_cfg.hdr_type = ICE_RSS_OUTER_HEADERS;
1776 		status = ice_rem_rss_cfg_sync(hw, vsi_handle, &local_cfg);
1777 
1778 		if (!status) {
1779 			local_cfg.hdr_type = ICE_RSS_INNER_HEADERS;
1780 			status = ice_rem_rss_cfg_sync(hw, vsi_handle,
1781 						      &local_cfg);
1782 		}
1783 	}
1784 	ice_release_lock(&hw->rss_locks);
1785 
1786 	return status;
1787 }
1788 
1789 /* Mapping of AVF hash bit fields to an L3-L4 hash combination.
1790  * As the ice_flow_avf_hdr_field represent individual bit shifts in a hash,
1791  * convert its values to their appropriate flow L3, L4 values.
1792  */
1793 #define ICE_FLOW_AVF_RSS_IPV4_MASKS \
1794 	(BIT_ULL(ICE_AVF_FLOW_FIELD_IPV4_OTHER) | \
1795 	 BIT_ULL(ICE_AVF_FLOW_FIELD_FRAG_IPV4))
1796 #define ICE_FLOW_AVF_RSS_TCP_IPV4_MASKS \
1797 	(BIT_ULL(ICE_AVF_FLOW_FIELD_IPV4_TCP_SYN_NO_ACK) | \
1798 	 BIT_ULL(ICE_AVF_FLOW_FIELD_IPV4_TCP))
1799 #define ICE_FLOW_AVF_RSS_UDP_IPV4_MASKS \
1800 	(BIT_ULL(ICE_AVF_FLOW_FIELD_UNICAST_IPV4_UDP) | \
1801 	 BIT_ULL(ICE_AVF_FLOW_FIELD_MULTICAST_IPV4_UDP) | \
1802 	 BIT_ULL(ICE_AVF_FLOW_FIELD_IPV4_UDP))
1803 #define ICE_FLOW_AVF_RSS_ALL_IPV4_MASKS \
1804 	(ICE_FLOW_AVF_RSS_TCP_IPV4_MASKS | ICE_FLOW_AVF_RSS_UDP_IPV4_MASKS | \
1805 	 ICE_FLOW_AVF_RSS_IPV4_MASKS | BIT_ULL(ICE_AVF_FLOW_FIELD_IPV4_SCTP))
1806 
1807 #define ICE_FLOW_AVF_RSS_IPV6_MASKS \
1808 	(BIT_ULL(ICE_AVF_FLOW_FIELD_IPV6_OTHER) | \
1809 	 BIT_ULL(ICE_AVF_FLOW_FIELD_FRAG_IPV6))
1810 #define ICE_FLOW_AVF_RSS_UDP_IPV6_MASKS \
1811 	(BIT_ULL(ICE_AVF_FLOW_FIELD_UNICAST_IPV6_UDP) | \
1812 	 BIT_ULL(ICE_AVF_FLOW_FIELD_MULTICAST_IPV6_UDP) | \
1813 	 BIT_ULL(ICE_AVF_FLOW_FIELD_IPV6_UDP))
1814 #define ICE_FLOW_AVF_RSS_TCP_IPV6_MASKS \
1815 	(BIT_ULL(ICE_AVF_FLOW_FIELD_IPV6_TCP_SYN_NO_ACK) | \
1816 	 BIT_ULL(ICE_AVF_FLOW_FIELD_IPV6_TCP))
1817 #define ICE_FLOW_AVF_RSS_ALL_IPV6_MASKS \
1818 	(ICE_FLOW_AVF_RSS_TCP_IPV6_MASKS | ICE_FLOW_AVF_RSS_UDP_IPV6_MASKS | \
1819 	 ICE_FLOW_AVF_RSS_IPV6_MASKS | BIT_ULL(ICE_AVF_FLOW_FIELD_IPV6_SCTP))
1820 
1821 /**
1822  * ice_add_avf_rss_cfg - add an RSS configuration for AVF driver
1823  * @hw: pointer to the hardware structure
1824  * @vsi_handle: software VSI handle
1825  * @avf_hash: hash bit fields (ICE_AVF_FLOW_FIELD_*) to configure
1826  *
1827  * This function will take the hash bitmap provided by the AVF driver via a
1828  * message, convert it to ICE-compatible values, and configure RSS flow
1829  * profiles.
1830  */
1831 enum ice_status
1832 ice_add_avf_rss_cfg(struct ice_hw *hw, u16 vsi_handle, u64 avf_hash)
1833 {
1834 	enum ice_status status = ICE_SUCCESS;
1835 	struct ice_rss_hash_cfg hcfg;
1836 	u64 hash_flds;
1837 
1838 	if (avf_hash == ICE_AVF_FLOW_FIELD_INVALID ||
1839 	    !ice_is_vsi_valid(hw, vsi_handle))
1840 		return ICE_ERR_PARAM;
1841 
1842 	/* Make sure no unsupported bits are specified */
1843 	if (avf_hash & ~(ICE_FLOW_AVF_RSS_ALL_IPV4_MASKS |
1844 			 ICE_FLOW_AVF_RSS_ALL_IPV6_MASKS))
1845 		return ICE_ERR_CFG;
1846 
1847 	hash_flds = avf_hash;
1848 
1849 	/* Always create an L3 RSS configuration for any L4 RSS configuration */
1850 	if (hash_flds & ICE_FLOW_AVF_RSS_ALL_IPV4_MASKS)
1851 		hash_flds |= ICE_FLOW_AVF_RSS_IPV4_MASKS;
1852 
1853 	if (hash_flds & ICE_FLOW_AVF_RSS_ALL_IPV6_MASKS)
1854 		hash_flds |= ICE_FLOW_AVF_RSS_IPV6_MASKS;
1855 
1856 	/* Create the corresponding RSS configuration for each valid hash bit */
1857 	while (hash_flds) {
1858 		u64 rss_hash = ICE_HASH_INVALID;
1859 
1860 		if (hash_flds & ICE_FLOW_AVF_RSS_ALL_IPV4_MASKS) {
1861 			if (hash_flds & ICE_FLOW_AVF_RSS_IPV4_MASKS) {
1862 				rss_hash = ICE_FLOW_HASH_IPV4;
1863 				hash_flds &= ~ICE_FLOW_AVF_RSS_IPV4_MASKS;
1864 			} else if (hash_flds &
1865 				   ICE_FLOW_AVF_RSS_TCP_IPV4_MASKS) {
1866 				rss_hash = ICE_FLOW_HASH_IPV4 |
1867 					ICE_FLOW_HASH_TCP_PORT;
1868 				hash_flds &= ~ICE_FLOW_AVF_RSS_TCP_IPV4_MASKS;
1869 			} else if (hash_flds &
1870 				   ICE_FLOW_AVF_RSS_UDP_IPV4_MASKS) {
1871 				rss_hash = ICE_FLOW_HASH_IPV4 |
1872 					ICE_FLOW_HASH_UDP_PORT;
1873 				hash_flds &= ~ICE_FLOW_AVF_RSS_UDP_IPV4_MASKS;
1874 			} else if (hash_flds &
1875 				   BIT_ULL(ICE_AVF_FLOW_FIELD_IPV4_SCTP)) {
1876 				rss_hash = ICE_FLOW_HASH_IPV4 |
1877 					ICE_FLOW_HASH_SCTP_PORT;
1878 				hash_flds &=
1879 					~BIT_ULL(ICE_AVF_FLOW_FIELD_IPV4_SCTP);
1880 			}
1881 		} else if (hash_flds & ICE_FLOW_AVF_RSS_ALL_IPV6_MASKS) {
1882 			if (hash_flds & ICE_FLOW_AVF_RSS_IPV6_MASKS) {
1883 				rss_hash = ICE_FLOW_HASH_IPV6;
1884 				hash_flds &= ~ICE_FLOW_AVF_RSS_IPV6_MASKS;
1885 			} else if (hash_flds &
1886 				   ICE_FLOW_AVF_RSS_TCP_IPV6_MASKS) {
1887 				rss_hash = ICE_FLOW_HASH_IPV6 |
1888 					ICE_FLOW_HASH_TCP_PORT;
1889 				hash_flds &= ~ICE_FLOW_AVF_RSS_TCP_IPV6_MASKS;
1890 			} else if (hash_flds &
1891 				   ICE_FLOW_AVF_RSS_UDP_IPV6_MASKS) {
1892 				rss_hash = ICE_FLOW_HASH_IPV6 |
1893 					ICE_FLOW_HASH_UDP_PORT;
1894 				hash_flds &= ~ICE_FLOW_AVF_RSS_UDP_IPV6_MASKS;
1895 			} else if (hash_flds &
1896 				   BIT_ULL(ICE_AVF_FLOW_FIELD_IPV6_SCTP)) {
1897 				rss_hash = ICE_FLOW_HASH_IPV6 |
1898 					ICE_FLOW_HASH_SCTP_PORT;
1899 				hash_flds &=
1900 					~BIT_ULL(ICE_AVF_FLOW_FIELD_IPV6_SCTP);
1901 			}
1902 		}
1903 
1904 		if (rss_hash == ICE_HASH_INVALID)
1905 			return ICE_ERR_OUT_OF_RANGE;
1906 
1907 		hcfg.addl_hdrs = ICE_FLOW_SEG_HDR_NONE;
1908 		hcfg.hash_flds = rss_hash;
1909 		hcfg.symm = false;
1910 		hcfg.hdr_type = ICE_RSS_ANY_HEADERS;
1911 		status = ice_add_rss_cfg(hw, vsi_handle, &hcfg);
1912 		if (status)
1913 			break;
1914 	}
1915 
1916 	return status;
1917 }
1918 
1919 /**
1920  * ice_replay_rss_cfg - replay RSS configurations associated with VSI
1921  * @hw: pointer to the hardware structure
1922  * @vsi_handle: software VSI handle
1923  */
1924 enum ice_status ice_replay_rss_cfg(struct ice_hw *hw, u16 vsi_handle)
1925 {
1926 	enum ice_status status = ICE_SUCCESS;
1927 	struct ice_rss_cfg *r;
1928 
1929 	if (!ice_is_vsi_valid(hw, vsi_handle))
1930 		return ICE_ERR_PARAM;
1931 
1932 	ice_acquire_lock(&hw->rss_locks);
1933 	LIST_FOR_EACH_ENTRY(r, &hw->rss_list_head,
1934 			    ice_rss_cfg, l_entry) {
1935 		if (ice_is_bit_set(r->vsis, vsi_handle)) {
1936 			status = ice_add_rss_cfg_sync(hw, vsi_handle, &r->hash);
1937 			if (status)
1938 				break;
1939 		}
1940 	}
1941 	ice_release_lock(&hw->rss_locks);
1942 
1943 	return status;
1944 }
1945 
1946 /**
1947  * ice_get_rss_cfg - returns hashed fields for the given header types
1948  * @hw: pointer to the hardware structure
1949  * @vsi_handle: software VSI handle
1950  * @hdrs: protocol header type
1951  *
1952  * This function will return the match fields of the first instance of flow
1953  * profile having the given header types and containing input VSI
1954  */
1955 u64 ice_get_rss_cfg(struct ice_hw *hw, u16 vsi_handle, u32 hdrs)
1956 {
1957 	u64 rss_hash = ICE_HASH_INVALID;
1958 	struct ice_rss_cfg *r;
1959 
1960 	/* verify if the protocol header is non zero and VSI is valid */
1961 	if (hdrs == ICE_FLOW_SEG_HDR_NONE || !ice_is_vsi_valid(hw, vsi_handle))
1962 		return ICE_HASH_INVALID;
1963 
1964 	ice_acquire_lock(&hw->rss_locks);
1965 	LIST_FOR_EACH_ENTRY(r, &hw->rss_list_head,
1966 			    ice_rss_cfg, l_entry)
1967 		if (ice_is_bit_set(r->vsis, vsi_handle) &&
1968 		    r->hash.addl_hdrs == hdrs) {
1969 			rss_hash = r->hash.hash_flds;
1970 			break;
1971 		}
1972 	ice_release_lock(&hw->rss_locks);
1973 
1974 	return rss_hash;
1975 }
1976