xref: /freebsd/sys/dev/ice/ice_flow.c (revision 0d4ad64077bcddcff5a170ee97273db95b9cab55)
1 /* SPDX-License-Identifier: BSD-3-Clause */
2 /*  Copyright (c) 2024, 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 | ICE_FLOW_SEG_HDR_ARP)
408 #define ICE_FLOW_SEG_HDRS_L4_MASK	\
409 	(ICE_FLOW_SEG_HDR_ICMP | ICE_FLOW_SEG_HDR_TCP | ICE_FLOW_SEG_HDR_UDP | \
410 	 ICE_FLOW_SEG_HDR_SCTP)
411 /* mask for L4 protocols that are NOT part of IPv4/6 OTHER PTYPE groups */
412 #define ICE_FLOW_SEG_HDRS_L4_MASK_NO_OTHER	\
413 	(ICE_FLOW_SEG_HDR_TCP | ICE_FLOW_SEG_HDR_UDP | ICE_FLOW_SEG_HDR_SCTP)
414 
415 /**
416  * ice_flow_val_hdrs - validates packet segments for valid protocol headers
417  * @segs: array of one or more packet segments that describe the flow
418  * @segs_cnt: number of packet segments provided
419  */
420 static enum ice_status
421 ice_flow_val_hdrs(struct ice_flow_seg_info *segs, u8 segs_cnt)
422 {
423 	u8 i;
424 
425 	for (i = 0; i < segs_cnt; i++) {
426 		/* Multiple L3 headers */
427 		if (segs[i].hdrs & ICE_FLOW_SEG_HDRS_L3_MASK &&
428 		    !ice_is_pow2(segs[i].hdrs & ICE_FLOW_SEG_HDRS_L3_MASK))
429 			return ICE_ERR_PARAM;
430 
431 		/* Multiple L4 headers */
432 		if (segs[i].hdrs & ICE_FLOW_SEG_HDRS_L4_MASK &&
433 		    !ice_is_pow2(segs[i].hdrs & ICE_FLOW_SEG_HDRS_L4_MASK))
434 			return ICE_ERR_PARAM;
435 	}
436 
437 	return ICE_SUCCESS;
438 }
439 
440 /**
441  * ice_flow_proc_seg_hdrs - process protocol headers present in pkt segments
442  * @params: information about the flow to be processed
443  *
444  * This function identifies the packet types associated with the protocol
445  * headers being present in packet segments of the specified flow profile.
446  */
447 static enum ice_status
448 ice_flow_proc_seg_hdrs(struct ice_flow_prof_params *params)
449 {
450 	struct ice_flow_prof *prof;
451 	u8 i;
452 
453 	ice_memset(params->ptypes, 0xff, sizeof(params->ptypes),
454 		   ICE_NONDMA_MEM);
455 
456 	prof = params->prof;
457 
458 	for (i = 0; i < params->prof->segs_cnt; i++) {
459 		const ice_bitmap_t *src;
460 		u32 hdrs;
461 
462 		hdrs = prof->segs[i].hdrs;
463 
464 		if (hdrs & ICE_FLOW_SEG_HDR_ETH) {
465 			src = !i ? (const ice_bitmap_t *)ice_ptypes_mac_ofos :
466 				(const ice_bitmap_t *)ice_ptypes_mac_il;
467 			ice_and_bitmap(params->ptypes, params->ptypes, src,
468 				       ICE_FLOW_PTYPE_MAX);
469 		}
470 
471 		if (i && hdrs & ICE_FLOW_SEG_HDR_VLAN) {
472 			src = (const ice_bitmap_t *)ice_ptypes_macvlan_il;
473 			ice_and_bitmap(params->ptypes, params->ptypes, src,
474 				       ICE_FLOW_PTYPE_MAX);
475 		}
476 
477 		if (!i && hdrs & ICE_FLOW_SEG_HDR_ARP) {
478 			ice_and_bitmap(params->ptypes, params->ptypes,
479 				       (const ice_bitmap_t *)ice_ptypes_arp_of,
480 				       ICE_FLOW_PTYPE_MAX);
481 		}
482 
483 		if ((hdrs & ICE_FLOW_SEG_HDR_IPV4) &&
484 		    (hdrs & ICE_FLOW_SEG_HDR_IPV_OTHER)) {
485 			src = i ? (const ice_bitmap_t *)ice_ptypes_ipv4_il :
486 				(const ice_bitmap_t *)ice_ptypes_ipv4_ofos_all;
487 			ice_and_bitmap(params->ptypes, params->ptypes, src,
488 				       ICE_FLOW_PTYPE_MAX);
489 		} else if ((hdrs & ICE_FLOW_SEG_HDR_IPV6) &&
490 			   (hdrs & ICE_FLOW_SEG_HDR_IPV_OTHER)) {
491 			src = i ? (const ice_bitmap_t *)ice_ptypes_ipv6_il :
492 				(const ice_bitmap_t *)ice_ptypes_ipv6_ofos_all;
493 			ice_and_bitmap(params->ptypes, params->ptypes, src,
494 				       ICE_FLOW_PTYPE_MAX);
495 		} else if ((hdrs & ICE_FLOW_SEG_HDR_IPV4) &&
496 			   !(hdrs & ICE_FLOW_SEG_HDRS_L4_MASK_NO_OTHER)) {
497 			src = !i ? (const ice_bitmap_t *)ice_ptypes_ipv4_ofos_no_l4 :
498 				(const ice_bitmap_t *)ice_ptypes_ipv4_il_no_l4;
499 			ice_and_bitmap(params->ptypes, params->ptypes, src,
500 				       ICE_FLOW_PTYPE_MAX);
501 		} else if (hdrs & ICE_FLOW_SEG_HDR_IPV4) {
502 			src = !i ? (const ice_bitmap_t *)ice_ptypes_ipv4_ofos :
503 				(const ice_bitmap_t *)ice_ptypes_ipv4_il;
504 			ice_and_bitmap(params->ptypes, params->ptypes, src,
505 				       ICE_FLOW_PTYPE_MAX);
506 		} else if ((hdrs & ICE_FLOW_SEG_HDR_IPV6) &&
507 			   !(hdrs & ICE_FLOW_SEG_HDRS_L4_MASK_NO_OTHER)) {
508 			src = !i ? (const ice_bitmap_t *)ice_ptypes_ipv6_ofos_no_l4 :
509 				(const ice_bitmap_t *)ice_ptypes_ipv6_il_no_l4;
510 			ice_and_bitmap(params->ptypes, params->ptypes, src,
511 				       ICE_FLOW_PTYPE_MAX);
512 		} else if (hdrs & ICE_FLOW_SEG_HDR_IPV6) {
513 			src = !i ? (const ice_bitmap_t *)ice_ptypes_ipv6_ofos :
514 				(const ice_bitmap_t *)ice_ptypes_ipv6_il;
515 			ice_and_bitmap(params->ptypes, params->ptypes, src,
516 				       ICE_FLOW_PTYPE_MAX);
517 		}
518 
519 		if (hdrs & ICE_FLOW_SEG_HDR_UDP) {
520 			src = (const ice_bitmap_t *)ice_ptypes_udp_il;
521 			ice_and_bitmap(params->ptypes, params->ptypes, src,
522 				       ICE_FLOW_PTYPE_MAX);
523 		} else if (hdrs & ICE_FLOW_SEG_HDR_TCP) {
524 			ice_and_bitmap(params->ptypes, params->ptypes,
525 				       (const ice_bitmap_t *)ice_ptypes_tcp_il,
526 				       ICE_FLOW_PTYPE_MAX);
527 		} else if (hdrs & ICE_FLOW_SEG_HDR_SCTP) {
528 			src = (const ice_bitmap_t *)ice_ptypes_sctp_il;
529 			ice_and_bitmap(params->ptypes, params->ptypes, src,
530 				       ICE_FLOW_PTYPE_MAX);
531 		}
532 
533 		if (hdrs & ICE_FLOW_SEG_HDR_ICMP) {
534 			src = !i ? (const ice_bitmap_t *)ice_ptypes_icmp_of :
535 				(const ice_bitmap_t *)ice_ptypes_icmp_il;
536 			ice_and_bitmap(params->ptypes, params->ptypes, src,
537 				       ICE_FLOW_PTYPE_MAX);
538 		} else if (hdrs & ICE_FLOW_SEG_HDR_GRE) {
539 			if (!i) {
540 				src = (const ice_bitmap_t *)ice_ptypes_gre_of;
541 				ice_and_bitmap(params->ptypes, params->ptypes,
542 					       src, ICE_FLOW_PTYPE_MAX);
543 			}
544 		}
545 	}
546 
547 	return ICE_SUCCESS;
548 }
549 
550 /**
551  * ice_flow_xtract_fld - Create an extraction sequence entry for the given field
552  * @hw: pointer to the HW struct
553  * @params: information about the flow to be processed
554  * @seg: packet segment index of the field to be extracted
555  * @fld: ID of field to be extracted
556  *
557  * This function determines the protocol ID, offset, and size of the given
558  * field. It then allocates one or more extraction sequence entries for the
559  * given field, and fill the entries with protocol ID and offset information.
560  */
561 static enum ice_status
562 ice_flow_xtract_fld(struct ice_hw *hw, struct ice_flow_prof_params *params,
563 		    u8 seg, enum ice_flow_field fld)
564 {
565 	enum ice_flow_field sib = ICE_FLOW_FIELD_IDX_MAX;
566 	u8 fv_words = (u8)hw->blk[params->blk].es.fvw;
567 	enum ice_prot_id prot_id = ICE_PROT_ID_INVAL;
568 	struct ice_flow_fld_info *flds;
569 	u16 cnt, ese_bits, i;
570 	u16 off;
571 
572 	flds = params->prof->segs[seg].fields;
573 
574 	switch (fld) {
575 	case ICE_FLOW_FIELD_IDX_ETH_DA:
576 	case ICE_FLOW_FIELD_IDX_ETH_SA:
577 	case ICE_FLOW_FIELD_IDX_S_VLAN:
578 	case ICE_FLOW_FIELD_IDX_C_VLAN:
579 		prot_id = seg == 0 ? ICE_PROT_MAC_OF_OR_S : ICE_PROT_MAC_IL;
580 		break;
581 	case ICE_FLOW_FIELD_IDX_ETH_TYPE:
582 		prot_id = seg == 0 ? ICE_PROT_ETYPE_OL : ICE_PROT_ETYPE_IL;
583 		break;
584 	case ICE_FLOW_FIELD_IDX_IPV4_DSCP:
585 		prot_id = seg == 0 ? ICE_PROT_IPV4_OF_OR_S : ICE_PROT_IPV4_IL;
586 		break;
587 	case ICE_FLOW_FIELD_IDX_IPV6_DSCP:
588 		prot_id = seg == 0 ? ICE_PROT_IPV6_OF_OR_S : ICE_PROT_IPV6_IL;
589 		break;
590 	case ICE_FLOW_FIELD_IDX_IPV4_TTL:
591 	case ICE_FLOW_FIELD_IDX_IPV4_PROT:
592 		prot_id = seg == 0 ? ICE_PROT_IPV4_OF_OR_S : ICE_PROT_IPV4_IL;
593 		/* TTL and PROT share the same extraction seq. entry.
594 		 * Each is considered a sibling to the other in terms of sharing
595 		 * the same extraction sequence entry.
596 		 */
597 		if (fld == ICE_FLOW_FIELD_IDX_IPV4_TTL)
598 			sib = ICE_FLOW_FIELD_IDX_IPV4_PROT;
599 		else
600 			sib = ICE_FLOW_FIELD_IDX_IPV4_TTL;
601 		break;
602 	case ICE_FLOW_FIELD_IDX_IPV6_TTL:
603 	case ICE_FLOW_FIELD_IDX_IPV6_PROT:
604 		prot_id = seg == 0 ? ICE_PROT_IPV6_OF_OR_S : ICE_PROT_IPV6_IL;
605 		/* TTL and PROT share the same extraction seq. entry.
606 		 * Each is considered a sibling to the other in terms of sharing
607 		 * the same extraction sequence entry.
608 		 */
609 		if (fld == ICE_FLOW_FIELD_IDX_IPV6_TTL)
610 			sib = ICE_FLOW_FIELD_IDX_IPV6_PROT;
611 		else
612 			sib = ICE_FLOW_FIELD_IDX_IPV6_TTL;
613 		break;
614 	case ICE_FLOW_FIELD_IDX_IPV4_SA:
615 	case ICE_FLOW_FIELD_IDX_IPV4_DA:
616 		prot_id = seg == 0 ? ICE_PROT_IPV4_OF_OR_S : ICE_PROT_IPV4_IL;
617 		break;
618 	case ICE_FLOW_FIELD_IDX_IPV6_SA:
619 	case ICE_FLOW_FIELD_IDX_IPV6_DA:
620 		prot_id = seg == 0 ? ICE_PROT_IPV6_OF_OR_S : ICE_PROT_IPV6_IL;
621 		break;
622 	case ICE_FLOW_FIELD_IDX_TCP_SRC_PORT:
623 	case ICE_FLOW_FIELD_IDX_TCP_DST_PORT:
624 	case ICE_FLOW_FIELD_IDX_TCP_FLAGS:
625 		prot_id = ICE_PROT_TCP_IL;
626 		break;
627 	case ICE_FLOW_FIELD_IDX_UDP_SRC_PORT:
628 	case ICE_FLOW_FIELD_IDX_UDP_DST_PORT:
629 		prot_id = ICE_PROT_UDP_IL_OR_S;
630 		break;
631 	case ICE_FLOW_FIELD_IDX_SCTP_SRC_PORT:
632 	case ICE_FLOW_FIELD_IDX_SCTP_DST_PORT:
633 		prot_id = ICE_PROT_SCTP_IL;
634 		break;
635 	case ICE_FLOW_FIELD_IDX_ARP_SIP:
636 	case ICE_FLOW_FIELD_IDX_ARP_DIP:
637 	case ICE_FLOW_FIELD_IDX_ARP_SHA:
638 	case ICE_FLOW_FIELD_IDX_ARP_DHA:
639 	case ICE_FLOW_FIELD_IDX_ARP_OP:
640 		prot_id = ICE_PROT_ARP_OF;
641 		break;
642 	case ICE_FLOW_FIELD_IDX_ICMP_TYPE:
643 	case ICE_FLOW_FIELD_IDX_ICMP_CODE:
644 		/* ICMP type and code share the same extraction seq. entry */
645 		prot_id = (params->prof->segs[seg].hdrs & ICE_FLOW_SEG_HDR_IPV4) ?
646 			ICE_PROT_ICMP_IL : ICE_PROT_ICMPV6_IL;
647 		sib = fld == ICE_FLOW_FIELD_IDX_ICMP_TYPE ?
648 			ICE_FLOW_FIELD_IDX_ICMP_CODE :
649 			ICE_FLOW_FIELD_IDX_ICMP_TYPE;
650 		break;
651 	case ICE_FLOW_FIELD_IDX_GRE_KEYID:
652 		prot_id = ICE_PROT_GRE_OF;
653 		break;
654 	default:
655 		return ICE_ERR_NOT_IMPL;
656 	}
657 
658 	/* Each extraction sequence entry is a word in size, and extracts a
659 	 * word-aligned offset from a protocol header.
660 	 */
661 	ese_bits = ICE_FLOW_FV_EXTRACT_SZ * BITS_PER_BYTE;
662 
663 	flds[fld].xtrct.prot_id = (u8)prot_id;
664 	flds[fld].xtrct.off = (ice_flds_info[fld].off / ese_bits) *
665 		ICE_FLOW_FV_EXTRACT_SZ;
666 	flds[fld].xtrct.disp = (u8)(ice_flds_info[fld].off % ese_bits);
667 	flds[fld].xtrct.idx = params->es_cnt;
668 
669 	/* Adjust the next field-entry index after accommodating the number of
670 	 * entries this field consumes
671 	 */
672 	cnt = DIVIDE_AND_ROUND_UP(flds[fld].xtrct.disp +
673 				  ice_flds_info[fld].size, ese_bits);
674 
675 	/* Fill in the extraction sequence entries needed for this field */
676 	off = flds[fld].xtrct.off;
677 	for (i = 0; i < cnt; i++) {
678 		/* Only consume an extraction sequence entry if there is no
679 		 * sibling field associated with this field or the sibling entry
680 		 * already extracts the word shared with this field.
681 		 */
682 		if (sib == ICE_FLOW_FIELD_IDX_MAX ||
683 		    flds[sib].xtrct.prot_id == ICE_PROT_ID_INVAL ||
684 		    flds[sib].xtrct.off != off) {
685 			u8 idx;
686 
687 			/* Make sure the number of extraction sequence required
688 			 * does not exceed the block's capability
689 			 */
690 			if (params->es_cnt >= fv_words)
691 				return ICE_ERR_MAX_LIMIT;
692 
693 			/* some blocks require a reversed field vector layout */
694 			if (hw->blk[params->blk].es.reverse)
695 				idx = fv_words - params->es_cnt - 1;
696 			else
697 				idx = params->es_cnt;
698 
699 			params->es[idx].prot_id = (u8)prot_id;
700 			params->es[idx].off = off;
701 			params->es_cnt++;
702 		}
703 
704 		off += ICE_FLOW_FV_EXTRACT_SZ;
705 	}
706 
707 	return ICE_SUCCESS;
708 }
709 
710 /**
711  * ice_flow_create_xtrct_seq - Create an extraction sequence for given segments
712  * @hw: pointer to the HW struct
713  * @params: information about the flow to be processed
714  *
715  * This function iterates through all matched fields in the given segments, and
716  * creates an extraction sequence for the fields.
717  */
718 static enum ice_status
719 ice_flow_create_xtrct_seq(struct ice_hw *hw,
720 			  struct ice_flow_prof_params *params)
721 {
722 	enum ice_status status = ICE_SUCCESS;
723 	u8 i;
724 
725 	for (i = 0; i < params->prof->segs_cnt; i++) {
726 		ice_declare_bitmap(match, ICE_FLOW_FIELD_IDX_MAX);
727 		enum ice_flow_field j;
728 
729 		ice_cp_bitmap(match, params->prof->segs[i].match,
730 			      ICE_FLOW_FIELD_IDX_MAX);
731 		ice_for_each_set_bit(j, match, ICE_FLOW_FIELD_IDX_MAX) {
732 			status = ice_flow_xtract_fld(hw, params, i, j);
733 			if (status)
734 				return status;
735 			ice_clear_bit(j, match);
736 		}
737 	}
738 
739 	return status;
740 }
741 
742 /**
743  * ice_flow_proc_segs - process all packet segments associated with a profile
744  * @hw: pointer to the HW struct
745  * @params: information about the flow to be processed
746  */
747 static enum ice_status
748 ice_flow_proc_segs(struct ice_hw *hw, struct ice_flow_prof_params *params)
749 {
750 	enum ice_status status;
751 
752 	status = ice_flow_proc_seg_hdrs(params);
753 	if (status)
754 		return status;
755 
756 	status = ice_flow_create_xtrct_seq(hw, params);
757 	if (status)
758 		return status;
759 
760 	switch (params->blk) {
761 	case ICE_BLK_RSS:
762 		status = ICE_SUCCESS;
763 		break;
764 	default:
765 		return ICE_ERR_NOT_IMPL;
766 	}
767 
768 	return status;
769 }
770 
771 #define ICE_FLOW_FIND_PROF_CHK_FLDS	0x00000001
772 #define ICE_FLOW_FIND_PROF_CHK_VSI	0x00000002
773 #define ICE_FLOW_FIND_PROF_NOT_CHK_DIR	0x00000004
774 
775 /**
776  * ice_flow_find_prof_conds - Find a profile matching headers and conditions
777  * @hw: pointer to the HW struct
778  * @blk: classification stage
779  * @dir: flow direction
780  * @segs: array of one or more packet segments that describe the flow
781  * @segs_cnt: number of packet segments provided
782  * @vsi_handle: software VSI handle to check VSI (ICE_FLOW_FIND_PROF_CHK_VSI)
783  * @conds: additional conditions to be checked (ICE_FLOW_FIND_PROF_CHK_*)
784  */
785 static struct ice_flow_prof *
786 ice_flow_find_prof_conds(struct ice_hw *hw, enum ice_block blk,
787 			 enum ice_flow_dir dir, struct ice_flow_seg_info *segs,
788 			 u8 segs_cnt, u16 vsi_handle, u32 conds)
789 {
790 	struct ice_flow_prof *p, *prof = NULL;
791 
792 	ice_acquire_lock(&hw->fl_profs_locks[blk]);
793 	LIST_FOR_EACH_ENTRY(p, &hw->fl_profs[blk], ice_flow_prof, l_entry)
794 		if ((p->dir == dir || conds & ICE_FLOW_FIND_PROF_NOT_CHK_DIR) &&
795 		    segs_cnt && segs_cnt == p->segs_cnt) {
796 			u8 i;
797 
798 			/* Check for profile-VSI association if specified */
799 			if ((conds & ICE_FLOW_FIND_PROF_CHK_VSI) &&
800 			    ice_is_vsi_valid(hw, vsi_handle) &&
801 			    !ice_is_bit_set(p->vsis, vsi_handle))
802 				continue;
803 
804 			/* Protocol headers must be checked. Matched fields are
805 			 * checked if specified.
806 			 */
807 			for (i = 0; i < segs_cnt; i++)
808 				if (segs[i].hdrs != p->segs[i].hdrs ||
809 				    ((conds & ICE_FLOW_FIND_PROF_CHK_FLDS) &&
810 				     (ice_cmp_bitmap(segs[i].match,
811 						     p->segs[i].match,
812 						     ICE_FLOW_FIELD_IDX_MAX) ==
813 				       false)))
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 	ice_set_bit(fld, seg->match);
1188 	if (field_type == ICE_FLOW_FLD_TYPE_RANGE)
1189 		ice_set_bit(fld, seg->range);
1190 
1191 	seg->fields[fld].type = field_type;
1192 	seg->fields[fld].src.val = val_loc;
1193 	seg->fields[fld].src.mask = mask_loc;
1194 	seg->fields[fld].src.last = last_loc;
1195 
1196 	ICE_FLOW_SET_HDRS(seg, ice_flds_info[fld].hdr);
1197 }
1198 
1199 /**
1200  * ice_flow_set_fld - specifies locations of field from entry's input buffer
1201  * @seg: packet segment the field being set belongs to
1202  * @fld: field to be set
1203  * @val_loc: if not ICE_FLOW_FLD_OFF_INVAL, location of the value to match from
1204  *           entry's input buffer
1205  * @mask_loc: if not ICE_FLOW_FLD_OFF_INVAL, location of mask value from entry's
1206  *            input buffer
1207  * @last_loc: if not ICE_FLOW_FLD_OFF_INVAL, location of last/upper value from
1208  *            entry's input buffer
1209  * @range: indicate if field being matched is to be in a range
1210  *
1211  * This function specifies the locations, in the form of byte offsets from the
1212  * start of the input buffer for a flow entry, from where the value to match,
1213  * the mask value, and upper value can be extracted. These locations are then
1214  * stored in the flow profile. When adding a flow entry associated with the
1215  * flow profile, these locations will be used to quickly extract the values and
1216  * create the content of a match entry. This function should only be used for
1217  * fixed-size data structures.
1218  */
1219 static void
1220 ice_flow_set_fld(struct ice_flow_seg_info *seg, enum ice_flow_field fld,
1221 		 u16 val_loc, u16 mask_loc, u16 last_loc, bool range)
1222 {
1223 	enum ice_flow_fld_match_type t = range ?
1224 		ICE_FLOW_FLD_TYPE_RANGE : ICE_FLOW_FLD_TYPE_REG;
1225 
1226 	ice_flow_set_fld_ext(seg, fld, t, val_loc, mask_loc, last_loc);
1227 }
1228 
1229 /**
1230  * ice_flow_set_fld_prefix - sets locations of prefix field from entry's buf
1231  * @seg: packet segment the field being set belongs to
1232  * @fld: field to be set
1233  * @val_loc: if not ICE_FLOW_FLD_OFF_INVAL, location of the value to match from
1234  *           entry's input buffer
1235  * @pref_loc: location of prefix value from entry's input buffer
1236  * @pref_sz: size of the location holding the prefix value
1237  *
1238  * This function specifies the locations, in the form of byte offsets from the
1239  * start of the input buffer for a flow entry, from where the value to match
1240  * and the IPv4 prefix value can be extracted. These locations are then stored
1241  * in the flow profile. When adding flow entries to the associated flow profile,
1242  * these locations can be used to quickly extract the values to create the
1243  * content of a match entry. This function should only be used for fixed-size
1244  * data structures.
1245  */
1246 void
1247 ice_flow_set_fld_prefix(struct ice_flow_seg_info *seg, enum ice_flow_field fld,
1248 			u16 val_loc, u16 pref_loc, u8 pref_sz)
1249 {
1250 	/* For this type of field, the "mask" location is for the prefix value's
1251 	 * location and the "last" location is for the size of the location of
1252 	 * the prefix value.
1253 	 */
1254 	ice_flow_set_fld_ext(seg, fld, ICE_FLOW_FLD_TYPE_PREFIX, val_loc,
1255 			     pref_loc, (u16)pref_sz);
1256 }
1257 
1258 #define ICE_FLOW_RSS_SEG_HDR_L3_MASKS \
1259 	(ICE_FLOW_SEG_HDR_IPV4 | ICE_FLOW_SEG_HDR_IPV6)
1260 
1261 #define ICE_FLOW_RSS_SEG_HDR_L4_MASKS \
1262 	(ICE_FLOW_SEG_HDR_TCP | ICE_FLOW_SEG_HDR_UDP | ICE_FLOW_SEG_HDR_SCTP)
1263 
1264 #define ICE_FLOW_RSS_SEG_HDR_VAL_MASKS \
1265 	(ICE_FLOW_RSS_SEG_HDR_L3_MASKS | \
1266 	 ICE_FLOW_RSS_SEG_HDR_L4_MASKS)
1267 
1268 /**
1269  * ice_flow_set_rss_seg_info - setup packet segments for RSS
1270  * @segs: pointer to the flow field segment(s)
1271  * @seg_cnt: segment count
1272  * @cfg: configure parameters
1273  *
1274  * Helper function to extract fields from hash bitmap and use flow
1275  * header value to set flow field segment for further use in flow
1276  * profile entry or removal.
1277  */
1278 static enum ice_status
1279 ice_flow_set_rss_seg_info(struct ice_flow_seg_info *segs, u8 seg_cnt,
1280 			  const struct ice_rss_hash_cfg *cfg)
1281 {
1282 	struct ice_flow_seg_info *seg;
1283 	u64 val;
1284 	u16 i;
1285 
1286 	/* set inner most segment */
1287 	seg = &segs[seg_cnt - 1];
1288 
1289 	ice_for_each_set_bit(i, (const ice_bitmap_t *)&cfg->hash_flds,
1290 			     (u16)ICE_FLOW_FIELD_IDX_MAX)
1291 		ice_flow_set_fld(seg, (enum ice_flow_field)i,
1292 				 ICE_FLOW_FLD_OFF_INVAL, ICE_FLOW_FLD_OFF_INVAL,
1293 				 ICE_FLOW_FLD_OFF_INVAL, false);
1294 
1295 	ICE_FLOW_SET_HDRS(seg, cfg->addl_hdrs);
1296 
1297 	/* set outer most header */
1298 	if (cfg->hdr_type == ICE_RSS_INNER_HEADERS_W_OUTER_IPV4)
1299 		segs[ICE_RSS_OUTER_HEADERS].hdrs |= ICE_FLOW_SEG_HDR_IPV4 |
1300 						    ICE_FLOW_SEG_HDR_IPV_FRAG |
1301 						    ICE_FLOW_SEG_HDR_IPV_OTHER;
1302 	else if (cfg->hdr_type == ICE_RSS_INNER_HEADERS_W_OUTER_IPV6)
1303 		segs[ICE_RSS_OUTER_HEADERS].hdrs |= ICE_FLOW_SEG_HDR_IPV6 |
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_IPV4_GRE)
1307 		segs[ICE_RSS_OUTER_HEADERS].hdrs |= ICE_FLOW_SEG_HDR_IPV4 |
1308 						    ICE_FLOW_SEG_HDR_GRE |
1309 						    ICE_FLOW_SEG_HDR_IPV_OTHER;
1310 	else if (cfg->hdr_type == ICE_RSS_INNER_HEADERS_W_OUTER_IPV6_GRE)
1311 		segs[ICE_RSS_OUTER_HEADERS].hdrs |= ICE_FLOW_SEG_HDR_IPV6 |
1312 						    ICE_FLOW_SEG_HDR_GRE |
1313 						    ICE_FLOW_SEG_HDR_IPV_OTHER;
1314 
1315 	if (seg->hdrs & ~ICE_FLOW_RSS_SEG_HDR_VAL_MASKS)
1316 		return ICE_ERR_PARAM;
1317 
1318 	val = (u64)(seg->hdrs & ICE_FLOW_RSS_SEG_HDR_L3_MASKS);
1319 	if (val && !ice_is_pow2(val))
1320 		return ICE_ERR_CFG;
1321 
1322 	val = (u64)(seg->hdrs & ICE_FLOW_RSS_SEG_HDR_L4_MASKS);
1323 	if (val && !ice_is_pow2(val))
1324 		return ICE_ERR_CFG;
1325 
1326 	return ICE_SUCCESS;
1327 }
1328 
1329 /**
1330  * ice_rem_vsi_rss_list - remove VSI from RSS list
1331  * @hw: pointer to the hardware structure
1332  * @vsi_handle: software VSI handle
1333  *
1334  * Remove the VSI from all RSS configurations in the list.
1335  */
1336 void ice_rem_vsi_rss_list(struct ice_hw *hw, u16 vsi_handle)
1337 {
1338 	struct ice_rss_cfg *r, *tmp;
1339 
1340 	if (LIST_EMPTY(&hw->rss_list_head))
1341 		return;
1342 
1343 	ice_acquire_lock(&hw->rss_locks);
1344 	LIST_FOR_EACH_ENTRY_SAFE(r, tmp, &hw->rss_list_head,
1345 				 ice_rss_cfg, l_entry)
1346 		if (ice_test_and_clear_bit(vsi_handle, r->vsis))
1347 			if (!ice_is_any_bit_set(r->vsis, ICE_MAX_VSI)) {
1348 				LIST_DEL(&r->l_entry);
1349 				ice_free(hw, r);
1350 			}
1351 	ice_release_lock(&hw->rss_locks);
1352 }
1353 
1354 /**
1355  * ice_rem_vsi_rss_cfg - remove RSS configurations associated with VSI
1356  * @hw: pointer to the hardware structure
1357  * @vsi_handle: software VSI handle
1358  *
1359  * This function will iterate through all flow profiles and disassociate
1360  * the VSI from that profile. If the flow profile has no VSIs it will
1361  * be removed.
1362  */
1363 enum ice_status ice_rem_vsi_rss_cfg(struct ice_hw *hw, u16 vsi_handle)
1364 {
1365 	const enum ice_block blk = ICE_BLK_RSS;
1366 	struct ice_flow_prof *p, *t;
1367 	enum ice_status status = ICE_SUCCESS;
1368 	u16 vsig;
1369 
1370 	if (!ice_is_vsi_valid(hw, vsi_handle))
1371 		return ICE_ERR_PARAM;
1372 
1373 	if (LIST_EMPTY(&hw->fl_profs[blk]))
1374 		return ICE_SUCCESS;
1375 
1376 	ice_acquire_lock(&hw->rss_locks);
1377 	LIST_FOR_EACH_ENTRY_SAFE(p, t, &hw->fl_profs[blk], ice_flow_prof,
1378 				 l_entry) {
1379 		int ret;
1380 
1381 		/* check if vsig is already removed */
1382 		ret = ice_vsig_find_vsi(hw, blk,
1383 					ice_get_hw_vsi_num(hw, vsi_handle),
1384 					&vsig);
1385 		if (!ret && !vsig)
1386 			break;
1387 
1388 		if (ice_is_bit_set(p->vsis, vsi_handle)) {
1389 			status = ice_flow_disassoc_prof(hw, blk, p, vsi_handle);
1390 			if (status)
1391 				break;
1392 
1393 			if (!ice_is_any_bit_set(p->vsis, ICE_MAX_VSI)) {
1394 				status = ice_flow_rem_prof(hw, blk, p->id);
1395 				if (status)
1396 					break;
1397 			}
1398 		}
1399 	}
1400 	ice_release_lock(&hw->rss_locks);
1401 
1402 	return status;
1403 }
1404 
1405 /**
1406  * ice_get_rss_hdr_type - get a RSS profile's header type
1407  * @prof: RSS flow profile
1408  */
1409 static enum ice_rss_cfg_hdr_type
1410 ice_get_rss_hdr_type(struct ice_flow_prof *prof)
1411 {
1412 	enum ice_rss_cfg_hdr_type hdr_type = ICE_RSS_ANY_HEADERS;
1413 
1414 	if (prof->segs_cnt == ICE_FLOW_SEG_SINGLE) {
1415 		hdr_type = ICE_RSS_OUTER_HEADERS;
1416 	} else if (prof->segs_cnt == ICE_FLOW_SEG_MAX) {
1417 		const struct ice_flow_seg_info *s;
1418 
1419 		s = &prof->segs[ICE_RSS_OUTER_HEADERS];
1420 		if (s->hdrs == ICE_FLOW_SEG_HDR_NONE)
1421 			hdr_type = ICE_RSS_INNER_HEADERS;
1422 		if (s->hdrs & ICE_FLOW_SEG_HDR_IPV4)
1423 			hdr_type = ICE_RSS_INNER_HEADERS_W_OUTER_IPV4;
1424 		if (s->hdrs & ICE_FLOW_SEG_HDR_IPV6)
1425 			hdr_type = ICE_RSS_INNER_HEADERS_W_OUTER_IPV6;
1426 	}
1427 
1428 	return hdr_type;
1429 }
1430 
1431 /**
1432  * ice_rem_rss_list - remove RSS configuration from list
1433  * @hw: pointer to the hardware structure
1434  * @vsi_handle: software VSI handle
1435  * @prof: pointer to flow profile
1436  *
1437  * Assumption: lock has already been acquired for RSS list
1438  */
1439 static void
1440 ice_rem_rss_list(struct ice_hw *hw, u16 vsi_handle, struct ice_flow_prof *prof)
1441 {
1442 	enum ice_rss_cfg_hdr_type hdr_type;
1443 	struct ice_rss_cfg *r, *tmp;
1444 	u64 seg_match = 0;
1445 	u16 i;
1446 
1447 	/* convert match bitmap to u64 for hash field comparison */
1448 	ice_for_each_set_bit(i, prof->segs[prof->segs_cnt - 1].match,
1449 			     ICE_FLOW_FIELD_IDX_MAX) {
1450 		seg_match |= 1ULL << i;
1451 	}
1452 
1453 	/* Search for RSS hash fields associated to the VSI that match the
1454 	 * hash configurations associated to the flow profile. If found
1455 	 * remove from the RSS entry list of the VSI context and delete entry.
1456 	 */
1457 	hdr_type = ice_get_rss_hdr_type(prof);
1458 	LIST_FOR_EACH_ENTRY_SAFE(r, tmp, &hw->rss_list_head,
1459 				 ice_rss_cfg, l_entry)
1460 		if (r->hash.hash_flds == seg_match &&
1461 		    r->hash.addl_hdrs == prof->segs[prof->segs_cnt - 1].hdrs &&
1462 		    r->hash.hdr_type == hdr_type) {
1463 			ice_clear_bit(vsi_handle, r->vsis);
1464 			if (!ice_is_any_bit_set(r->vsis, ICE_MAX_VSI)) {
1465 				LIST_DEL(&r->l_entry);
1466 				ice_free(hw, r);
1467 			}
1468 			return;
1469 		}
1470 }
1471 
1472 /**
1473  * ice_add_rss_list - add RSS configuration to list
1474  * @hw: pointer to the hardware structure
1475  * @vsi_handle: software VSI handle
1476  * @prof: pointer to flow profile
1477  *
1478  * Assumption: lock has already been acquired for RSS list
1479  */
1480 static enum ice_status
1481 ice_add_rss_list(struct ice_hw *hw, u16 vsi_handle, struct ice_flow_prof *prof)
1482 {
1483 	enum ice_rss_cfg_hdr_type hdr_type;
1484 	struct ice_rss_cfg *r, *rss_cfg;
1485 	u64 seg_match = 0;
1486 	u16 i;
1487 
1488 	ice_for_each_set_bit(i, prof->segs[prof->segs_cnt - 1].match,
1489 			     ICE_FLOW_FIELD_IDX_MAX) {
1490 		seg_match |= 1ULL << i;
1491 	}
1492 
1493 	hdr_type = ice_get_rss_hdr_type(prof);
1494 	LIST_FOR_EACH_ENTRY(r, &hw->rss_list_head,
1495 			    ice_rss_cfg, l_entry)
1496 		if (r->hash.hash_flds == seg_match &&
1497 		    r->hash.addl_hdrs == prof->segs[prof->segs_cnt - 1].hdrs &&
1498 		    r->hash.hdr_type == hdr_type) {
1499 			ice_set_bit(vsi_handle, r->vsis);
1500 			return ICE_SUCCESS;
1501 		}
1502 
1503 	rss_cfg = (struct ice_rss_cfg *)ice_malloc(hw, sizeof(*rss_cfg));
1504 	if (!rss_cfg)
1505 		return ICE_ERR_NO_MEMORY;
1506 
1507 	rss_cfg->hash.hash_flds = seg_match;
1508 	rss_cfg->hash.addl_hdrs = prof->segs[prof->segs_cnt - 1].hdrs;
1509 	rss_cfg->hash.hdr_type = hdr_type;
1510 	rss_cfg->hash.symm = prof->cfg.symm;
1511 	ice_set_bit(vsi_handle, rss_cfg->vsis);
1512 
1513 	LIST_ADD_TAIL(&rss_cfg->l_entry, &hw->rss_list_head);
1514 
1515 	return ICE_SUCCESS;
1516 }
1517 
1518 #define ICE_FLOW_PROF_HASH_S	0
1519 #define ICE_FLOW_PROF_HASH_M	(0xFFFFFFFFULL << ICE_FLOW_PROF_HASH_S)
1520 #define ICE_FLOW_PROF_HDR_S	32
1521 #define ICE_FLOW_PROF_HDR_M	(0x3FFFFFFFULL << ICE_FLOW_PROF_HDR_S)
1522 #define ICE_FLOW_PROF_ENCAP_S	62
1523 #define ICE_FLOW_PROF_ENCAP_M	(0x3ULL << ICE_FLOW_PROF_ENCAP_S)
1524 
1525 /* Flow profile ID format:
1526  * [0:31] - Packet match fields
1527  * [32:61] - Protocol header
1528  * [62:63] - Encapsulation flag:
1529  *	     0 if non-tunneled
1530  *	     1 if tunneled
1531  *	     2 for tunneled with outer IPv4
1532  *	     3 for tunneled with outer IPv6
1533  */
1534 #define ICE_FLOW_GEN_PROFID(hash, hdr, encap)                                \
1535 	((u64)(((u64)(hash) & ICE_FLOW_PROF_HASH_M) |                        \
1536 	       (((u64)(hdr) << ICE_FLOW_PROF_HDR_S) & ICE_FLOW_PROF_HDR_M) | \
1537 	       (((u64)(encap) << ICE_FLOW_PROF_ENCAP_S) &                    \
1538 		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 :
1563 			   ICE_FLOW_SEG_MAX;
1564 
1565 	segs = (struct ice_flow_seg_info *)ice_calloc(hw, segs_cnt,
1566 						      sizeof(*segs));
1567 	if (!segs)
1568 		return ICE_ERR_NO_MEMORY;
1569 
1570 	/* Construct the packet segment info from the hashed fields */
1571 	status = ice_flow_set_rss_seg_info(segs, segs_cnt, cfg);
1572 	if (status)
1573 		goto exit;
1574 
1575 	/* Search for a flow profile that has matching headers, hash fields
1576 	 * and has the input VSI associated to it. If found, no further
1577 	 * operations required and exit.
1578 	 */
1579 	prof = ice_flow_find_prof_conds(hw, blk, ICE_FLOW_RX, segs, segs_cnt,
1580 					vsi_handle,
1581 					ICE_FLOW_FIND_PROF_CHK_FLDS |
1582 					ICE_FLOW_FIND_PROF_CHK_VSI);
1583 	if (prof)
1584 		goto exit;
1585 
1586 	/* Check if a flow profile exists with the same protocol headers and
1587 	 * associated with the input VSI. If so disassociate the VSI from
1588 	 * this profile. The VSI will be added to a new profile created with
1589 	 * the protocol header and new hash field configuration.
1590 	 */
1591 	prof = ice_flow_find_prof_conds(hw, blk, ICE_FLOW_RX, segs, segs_cnt,
1592 					vsi_handle, ICE_FLOW_FIND_PROF_CHK_VSI);
1593 	if (prof) {
1594 		status = ice_flow_disassoc_prof(hw, blk, prof, vsi_handle);
1595 		if (!status)
1596 			ice_rem_rss_list(hw, vsi_handle, prof);
1597 		else
1598 			goto exit;
1599 
1600 		/* Remove profile if it has no VSIs associated */
1601 		if (!ice_is_any_bit_set(prof->vsis, ICE_MAX_VSI)) {
1602 			status = ice_flow_rem_prof(hw, blk, prof->id);
1603 			if (status)
1604 				goto exit;
1605 		}
1606 	}
1607 
1608 	/* Search for a profile that has same match fields only. If this
1609 	 * exists then associate the VSI to this profile.
1610 	 */
1611 	prof = ice_flow_find_prof_conds(hw, blk, ICE_FLOW_RX, segs, segs_cnt,
1612 					vsi_handle,
1613 					ICE_FLOW_FIND_PROF_CHK_FLDS);
1614 	if (prof) {
1615 		status = ice_flow_assoc_prof(hw, blk, prof, vsi_handle);
1616 		if (!status)
1617 			status = ice_add_rss_list(hw, vsi_handle, prof);
1618 		goto exit;
1619 	}
1620 
1621 	/* Create a new flow profile with generated profile and packet
1622 	 * segment information.
1623 	 */
1624 	status = ice_flow_add_prof(hw, blk, ICE_FLOW_RX,
1625 				   ICE_FLOW_GEN_PROFID(cfg->hash_flds,
1626 						       segs[segs_cnt - 1].hdrs,
1627 						       cfg->hdr_type),
1628 				   segs, segs_cnt, NULL, 0, &prof);
1629 	if (status)
1630 		goto exit;
1631 
1632 	status = ice_flow_assoc_prof(hw, blk, prof, vsi_handle);
1633 	/* If association to a new flow profile failed then this profile can
1634 	 * be removed.
1635 	 */
1636 	if (status) {
1637 		ice_flow_rem_prof(hw, blk, prof->id);
1638 		goto exit;
1639 	}
1640 
1641 	status = ice_add_rss_list(hw, vsi_handle, prof);
1642 
1643 	prof->cfg.symm = cfg->symm;
1644 
1645 exit:
1646 	ice_free(hw, segs);
1647 	return status;
1648 }
1649 
1650 /**
1651  * ice_add_rss_cfg - add an RSS configuration with specified hashed fields
1652  * @hw: pointer to the hardware structure
1653  * @vsi_handle: software VSI handle
1654  * @cfg: configure parameters
1655  *
1656  * This function will generate a flow profile based on fields associated with
1657  * the input fields to hash on, the flow type and use the VSI number to add
1658  * a flow entry to the profile.
1659  */
1660 enum ice_status
1661 ice_add_rss_cfg(struct ice_hw *hw, u16 vsi_handle,
1662 		const struct ice_rss_hash_cfg *cfg)
1663 {
1664 	struct ice_rss_hash_cfg local_cfg;
1665 	enum ice_status status;
1666 
1667 	if (!ice_is_vsi_valid(hw, vsi_handle) || !cfg ||
1668 	    cfg->hdr_type > ICE_RSS_ANY_HEADERS ||
1669 	    cfg->hash_flds == ICE_HASH_INVALID)
1670 		return ICE_ERR_PARAM;
1671 
1672 	ice_acquire_lock(&hw->rss_locks);
1673 	local_cfg = *cfg;
1674 	if (cfg->hdr_type < ICE_RSS_ANY_HEADERS) {
1675 		status = ice_add_rss_cfg_sync(hw, vsi_handle, &local_cfg);
1676 	} else {
1677 		local_cfg.hdr_type = ICE_RSS_OUTER_HEADERS;
1678 		status = ice_add_rss_cfg_sync(hw, vsi_handle, &local_cfg);
1679 		if (!status) {
1680 			local_cfg.hdr_type = ICE_RSS_INNER_HEADERS;
1681 			status = ice_add_rss_cfg_sync(hw, vsi_handle,
1682 						      &local_cfg);
1683 		}
1684 	}
1685 	ice_release_lock(&hw->rss_locks);
1686 
1687 	return status;
1688 }
1689 
1690 /**
1691  * ice_rem_rss_cfg_sync - remove an existing RSS configuration
1692  * @hw: pointer to the hardware structure
1693  * @vsi_handle: software VSI handle
1694  * @cfg: configure parameters
1695  *
1696  * Assumption: lock has already been acquired for RSS list
1697  */
1698 static enum ice_status
1699 ice_rem_rss_cfg_sync(struct ice_hw *hw, u16 vsi_handle,
1700 		     const struct ice_rss_hash_cfg *cfg)
1701 {
1702 	const enum ice_block blk = ICE_BLK_RSS;
1703 	struct ice_flow_seg_info *segs;
1704 	struct ice_flow_prof *prof;
1705 	enum ice_status status;
1706 	u8 segs_cnt;
1707 
1708 	segs_cnt = (cfg->hdr_type == ICE_RSS_OUTER_HEADERS) ?
1709 			   ICE_FLOW_SEG_SINGLE :
1710 			   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) || !cfg ||
1766 	    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 		if (!status) {
1778 			local_cfg.hdr_type = ICE_RSS_INNER_HEADERS;
1779 			status = ice_rem_rss_cfg_sync(hw, vsi_handle,
1780 						      &local_cfg);
1781 		}
1782 	}
1783 	ice_release_lock(&hw->rss_locks);
1784 
1785 	return status;
1786 }
1787 
1788 /* Mapping of AVF hash bit fields to an L3-L4 hash combination.
1789  * As the ice_flow_avf_hdr_field represent individual bit shifts in a hash,
1790  * convert its values to their appropriate flow L3, L4 values.
1791  */
1792 #define ICE_FLOW_AVF_RSS_IPV4_MASKS \
1793 	(BIT_ULL(ICE_AVF_FLOW_FIELD_IPV4_OTHER) | \
1794 	 BIT_ULL(ICE_AVF_FLOW_FIELD_FRAG_IPV4))
1795 #define ICE_FLOW_AVF_RSS_TCP_IPV4_MASKS \
1796 	(BIT_ULL(ICE_AVF_FLOW_FIELD_IPV4_TCP_SYN_NO_ACK) | \
1797 	 BIT_ULL(ICE_AVF_FLOW_FIELD_IPV4_TCP))
1798 #define ICE_FLOW_AVF_RSS_UDP_IPV4_MASKS \
1799 	(BIT_ULL(ICE_AVF_FLOW_FIELD_UNICAST_IPV4_UDP) | \
1800 	 BIT_ULL(ICE_AVF_FLOW_FIELD_MULTICAST_IPV4_UDP) | \
1801 	 BIT_ULL(ICE_AVF_FLOW_FIELD_IPV4_UDP))
1802 #define ICE_FLOW_AVF_RSS_ALL_IPV4_MASKS \
1803 	(ICE_FLOW_AVF_RSS_TCP_IPV4_MASKS | ICE_FLOW_AVF_RSS_UDP_IPV4_MASKS | \
1804 	 ICE_FLOW_AVF_RSS_IPV4_MASKS | BIT_ULL(ICE_AVF_FLOW_FIELD_IPV4_SCTP))
1805 
1806 #define ICE_FLOW_AVF_RSS_IPV6_MASKS \
1807 	(BIT_ULL(ICE_AVF_FLOW_FIELD_IPV6_OTHER) | \
1808 	 BIT_ULL(ICE_AVF_FLOW_FIELD_FRAG_IPV6))
1809 #define ICE_FLOW_AVF_RSS_UDP_IPV6_MASKS \
1810 	(BIT_ULL(ICE_AVF_FLOW_FIELD_UNICAST_IPV6_UDP) | \
1811 	 BIT_ULL(ICE_AVF_FLOW_FIELD_MULTICAST_IPV6_UDP) | \
1812 	 BIT_ULL(ICE_AVF_FLOW_FIELD_IPV6_UDP))
1813 #define ICE_FLOW_AVF_RSS_TCP_IPV6_MASKS \
1814 	(BIT_ULL(ICE_AVF_FLOW_FIELD_IPV6_TCP_SYN_NO_ACK) | \
1815 	 BIT_ULL(ICE_AVF_FLOW_FIELD_IPV6_TCP))
1816 #define ICE_FLOW_AVF_RSS_ALL_IPV6_MASKS \
1817 	(ICE_FLOW_AVF_RSS_TCP_IPV6_MASKS | ICE_FLOW_AVF_RSS_UDP_IPV6_MASKS | \
1818 	 ICE_FLOW_AVF_RSS_IPV6_MASKS | BIT_ULL(ICE_AVF_FLOW_FIELD_IPV6_SCTP))
1819 
1820 /**
1821  * ice_add_avf_rss_cfg - add an RSS configuration for AVF driver
1822  * @hw: pointer to the hardware structure
1823  * @vsi_handle: software VSI handle
1824  * @avf_hash: hash bit fields (ICE_AVF_FLOW_FIELD_*) to configure
1825  *
1826  * This function will take the hash bitmap provided by the AVF driver via a
1827  * message, convert it to ICE-compatible values, and configure RSS flow
1828  * profiles.
1829  */
1830 enum ice_status
1831 ice_add_avf_rss_cfg(struct ice_hw *hw, u16 vsi_handle, u64 avf_hash)
1832 {
1833 	enum ice_status status = ICE_SUCCESS;
1834 	struct ice_rss_hash_cfg hcfg;
1835 	u64 hash_flds;
1836 
1837 	if (avf_hash == ICE_AVF_FLOW_FIELD_INVALID ||
1838 	    !ice_is_vsi_valid(hw, vsi_handle))
1839 		return ICE_ERR_PARAM;
1840 
1841 	/* Make sure no unsupported bits are specified */
1842 	if (avf_hash & ~(ICE_FLOW_AVF_RSS_ALL_IPV4_MASKS |
1843 			 ICE_FLOW_AVF_RSS_ALL_IPV6_MASKS))
1844 		return ICE_ERR_CFG;
1845 
1846 	hash_flds = avf_hash;
1847 
1848 	/* Always create an L3 RSS configuration for any L4 RSS configuration */
1849 	if (hash_flds & ICE_FLOW_AVF_RSS_ALL_IPV4_MASKS)
1850 		hash_flds |= ICE_FLOW_AVF_RSS_IPV4_MASKS;
1851 
1852 	if (hash_flds & ICE_FLOW_AVF_RSS_ALL_IPV6_MASKS)
1853 		hash_flds |= ICE_FLOW_AVF_RSS_IPV6_MASKS;
1854 
1855 	/* Create the corresponding RSS configuration for each valid hash bit */
1856 	while (hash_flds) {
1857 		u64 rss_hash = ICE_HASH_INVALID;
1858 
1859 		if (hash_flds & ICE_FLOW_AVF_RSS_ALL_IPV4_MASKS) {
1860 			if (hash_flds & ICE_FLOW_AVF_RSS_IPV4_MASKS) {
1861 				rss_hash = ICE_FLOW_HASH_IPV4;
1862 				hash_flds &= ~ICE_FLOW_AVF_RSS_IPV4_MASKS;
1863 			} else if (hash_flds &
1864 				   ICE_FLOW_AVF_RSS_TCP_IPV4_MASKS) {
1865 				rss_hash = ICE_FLOW_HASH_IPV4 |
1866 					ICE_FLOW_HASH_TCP_PORT;
1867 				hash_flds &= ~ICE_FLOW_AVF_RSS_TCP_IPV4_MASKS;
1868 			} else if (hash_flds &
1869 				   ICE_FLOW_AVF_RSS_UDP_IPV4_MASKS) {
1870 				rss_hash = ICE_FLOW_HASH_IPV4 |
1871 					ICE_FLOW_HASH_UDP_PORT;
1872 				hash_flds &= ~ICE_FLOW_AVF_RSS_UDP_IPV4_MASKS;
1873 			} else if (hash_flds &
1874 				   BIT_ULL(ICE_AVF_FLOW_FIELD_IPV4_SCTP)) {
1875 				rss_hash = ICE_FLOW_HASH_IPV4 |
1876 					ICE_FLOW_HASH_SCTP_PORT;
1877 				hash_flds &=
1878 					~BIT_ULL(ICE_AVF_FLOW_FIELD_IPV4_SCTP);
1879 			}
1880 		} else if (hash_flds & ICE_FLOW_AVF_RSS_ALL_IPV6_MASKS) {
1881 			if (hash_flds & ICE_FLOW_AVF_RSS_IPV6_MASKS) {
1882 				rss_hash = ICE_FLOW_HASH_IPV6;
1883 				hash_flds &= ~ICE_FLOW_AVF_RSS_IPV6_MASKS;
1884 			} else if (hash_flds &
1885 				   ICE_FLOW_AVF_RSS_TCP_IPV6_MASKS) {
1886 				rss_hash = ICE_FLOW_HASH_IPV6 |
1887 					ICE_FLOW_HASH_TCP_PORT;
1888 				hash_flds &= ~ICE_FLOW_AVF_RSS_TCP_IPV6_MASKS;
1889 			} else if (hash_flds &
1890 				   ICE_FLOW_AVF_RSS_UDP_IPV6_MASKS) {
1891 				rss_hash = ICE_FLOW_HASH_IPV6 |
1892 					ICE_FLOW_HASH_UDP_PORT;
1893 				hash_flds &= ~ICE_FLOW_AVF_RSS_UDP_IPV6_MASKS;
1894 			} else if (hash_flds &
1895 				   BIT_ULL(ICE_AVF_FLOW_FIELD_IPV6_SCTP)) {
1896 				rss_hash = ICE_FLOW_HASH_IPV6 |
1897 					ICE_FLOW_HASH_SCTP_PORT;
1898 				hash_flds &=
1899 					~BIT_ULL(ICE_AVF_FLOW_FIELD_IPV6_SCTP);
1900 			}
1901 		}
1902 
1903 		if (rss_hash == ICE_HASH_INVALID)
1904 			return ICE_ERR_OUT_OF_RANGE;
1905 
1906 		hcfg.addl_hdrs = ICE_FLOW_SEG_HDR_NONE;
1907 		hcfg.hash_flds = rss_hash;
1908 		hcfg.symm = false;
1909 		hcfg.hdr_type = ICE_RSS_ANY_HEADERS;
1910 		status = ice_add_rss_cfg(hw, vsi_handle, &hcfg);
1911 		if (status)
1912 			break;
1913 	}
1914 
1915 	return status;
1916 }
1917 
1918 /**
1919  * ice_replay_rss_cfg - replay RSS configurations associated with VSI
1920  * @hw: pointer to the hardware structure
1921  * @vsi_handle: software VSI handle
1922  */
1923 enum ice_status ice_replay_rss_cfg(struct ice_hw *hw, u16 vsi_handle)
1924 {
1925 	enum ice_status status = ICE_SUCCESS;
1926 	struct ice_rss_cfg *r;
1927 
1928 	if (!ice_is_vsi_valid(hw, vsi_handle))
1929 		return ICE_ERR_PARAM;
1930 
1931 	ice_acquire_lock(&hw->rss_locks);
1932 	LIST_FOR_EACH_ENTRY(r, &hw->rss_list_head,
1933 			    ice_rss_cfg, l_entry) {
1934 		if (ice_is_bit_set(r->vsis, vsi_handle)) {
1935 			status = ice_add_rss_cfg_sync(hw, vsi_handle, &r->hash);
1936 			if (status)
1937 				break;
1938 		}
1939 	}
1940 	ice_release_lock(&hw->rss_locks);
1941 
1942 	return status;
1943 }
1944 
1945 /**
1946  * ice_get_rss_cfg - returns hashed fields for the given header types
1947  * @hw: pointer to the hardware structure
1948  * @vsi_handle: software VSI handle
1949  * @hdrs: protocol header type
1950  *
1951  * This function will return the match fields of the first instance of flow
1952  * profile having the given header types and containing input VSI
1953  */
1954 u64 ice_get_rss_cfg(struct ice_hw *hw, u16 vsi_handle, u32 hdrs)
1955 {
1956 	u64 rss_hash = ICE_HASH_INVALID;
1957 	struct ice_rss_cfg *r;
1958 
1959 	/* verify if the protocol header is non zero and VSI is valid */
1960 	if (hdrs == ICE_FLOW_SEG_HDR_NONE || !ice_is_vsi_valid(hw, vsi_handle))
1961 		return ICE_HASH_INVALID;
1962 
1963 	ice_acquire_lock(&hw->rss_locks);
1964 	LIST_FOR_EACH_ENTRY(r, &hw->rss_list_head,
1965 			    ice_rss_cfg, l_entry)
1966 		if (ice_is_bit_set(r->vsis, vsi_handle) &&
1967 		    r->hash.addl_hdrs == hdrs) {
1968 			rss_hash = r->hash.hash_flds;
1969 			break;
1970 		}
1971 	ice_release_lock(&hw->rss_locks);
1972 
1973 	return rss_hash;
1974 }
1975