xref: /freebsd/sys/dev/ice/ice_flow.c (revision f2635e844dd138ac9dfba676f27d41750049af26)
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 int ice_flow_val_hdrs(struct ice_flow_seg_info *segs, u8 segs_cnt)
421 {
422 	u8 i;
423 
424 	for (i = 0; i < segs_cnt; i++) {
425 		/* Multiple L3 headers */
426 		if (segs[i].hdrs & ICE_FLOW_SEG_HDRS_L3_MASK &&
427 		    !ice_is_pow2(segs[i].hdrs & ICE_FLOW_SEG_HDRS_L3_MASK))
428 			return ICE_ERR_PARAM;
429 
430 		/* Multiple L4 headers */
431 		if (segs[i].hdrs & ICE_FLOW_SEG_HDRS_L4_MASK &&
432 		    !ice_is_pow2(segs[i].hdrs & ICE_FLOW_SEG_HDRS_L4_MASK))
433 			return ICE_ERR_PARAM;
434 	}
435 
436 	return 0;
437 }
438 
439 /**
440  * ice_flow_proc_seg_hdrs - process protocol headers present in pkt segments
441  * @params: information about the flow to be processed
442  *
443  * This function identifies the packet types associated with the protocol
444  * headers being present in packet segments of the specified flow profile.
445  */
446 static int
447 ice_flow_proc_seg_hdrs(struct ice_flow_prof_params *params)
448 {
449 	struct ice_flow_prof *prof;
450 	u8 i;
451 
452 	ice_memset(params->ptypes, 0xff, sizeof(params->ptypes),
453 		   ICE_NONDMA_MEM);
454 
455 	prof = params->prof;
456 
457 	for (i = 0; i < params->prof->segs_cnt; i++) {
458 		const ice_bitmap_t *src;
459 		u32 hdrs;
460 
461 		hdrs = prof->segs[i].hdrs;
462 
463 		if (hdrs & ICE_FLOW_SEG_HDR_ETH) {
464 			src = !i ? (const ice_bitmap_t *)ice_ptypes_mac_ofos :
465 				(const ice_bitmap_t *)ice_ptypes_mac_il;
466 			ice_and_bitmap(params->ptypes, params->ptypes, src,
467 				       ICE_FLOW_PTYPE_MAX);
468 		}
469 
470 		if (i && hdrs & ICE_FLOW_SEG_HDR_VLAN) {
471 			src = (const ice_bitmap_t *)ice_ptypes_macvlan_il;
472 			ice_and_bitmap(params->ptypes, params->ptypes, src,
473 				       ICE_FLOW_PTYPE_MAX);
474 		}
475 
476 		if (!i && hdrs & ICE_FLOW_SEG_HDR_ARP) {
477 			ice_and_bitmap(params->ptypes, params->ptypes,
478 				       (const ice_bitmap_t *)ice_ptypes_arp_of,
479 				       ICE_FLOW_PTYPE_MAX);
480 		}
481 
482 		if ((hdrs & ICE_FLOW_SEG_HDR_IPV4) &&
483 		    (hdrs & ICE_FLOW_SEG_HDR_IPV_OTHER)) {
484 			src = i ? (const ice_bitmap_t *)ice_ptypes_ipv4_il :
485 				(const ice_bitmap_t *)ice_ptypes_ipv4_ofos_all;
486 			ice_and_bitmap(params->ptypes, params->ptypes, src,
487 				       ICE_FLOW_PTYPE_MAX);
488 		} else if ((hdrs & ICE_FLOW_SEG_HDR_IPV6) &&
489 			   (hdrs & ICE_FLOW_SEG_HDR_IPV_OTHER)) {
490 			src = i ? (const ice_bitmap_t *)ice_ptypes_ipv6_il :
491 				(const ice_bitmap_t *)ice_ptypes_ipv6_ofos_all;
492 			ice_and_bitmap(params->ptypes, params->ptypes, src,
493 				       ICE_FLOW_PTYPE_MAX);
494 		} else if ((hdrs & ICE_FLOW_SEG_HDR_IPV4) &&
495 			   !(hdrs & ICE_FLOW_SEG_HDRS_L4_MASK_NO_OTHER)) {
496 			src = !i ? (const ice_bitmap_t *)ice_ptypes_ipv4_ofos_no_l4 :
497 				(const ice_bitmap_t *)ice_ptypes_ipv4_il_no_l4;
498 			ice_and_bitmap(params->ptypes, params->ptypes, src,
499 				       ICE_FLOW_PTYPE_MAX);
500 		} else if (hdrs & ICE_FLOW_SEG_HDR_IPV4) {
501 			src = !i ? (const ice_bitmap_t *)ice_ptypes_ipv4_ofos :
502 				(const ice_bitmap_t *)ice_ptypes_ipv4_il;
503 			ice_and_bitmap(params->ptypes, params->ptypes, src,
504 				       ICE_FLOW_PTYPE_MAX);
505 		} else if ((hdrs & ICE_FLOW_SEG_HDR_IPV6) &&
506 			   !(hdrs & ICE_FLOW_SEG_HDRS_L4_MASK_NO_OTHER)) {
507 			src = !i ? (const ice_bitmap_t *)ice_ptypes_ipv6_ofos_no_l4 :
508 				(const ice_bitmap_t *)ice_ptypes_ipv6_il_no_l4;
509 			ice_and_bitmap(params->ptypes, params->ptypes, src,
510 				       ICE_FLOW_PTYPE_MAX);
511 		} else if (hdrs & ICE_FLOW_SEG_HDR_IPV6) {
512 			src = !i ? (const ice_bitmap_t *)ice_ptypes_ipv6_ofos :
513 				(const ice_bitmap_t *)ice_ptypes_ipv6_il;
514 			ice_and_bitmap(params->ptypes, params->ptypes, src,
515 				       ICE_FLOW_PTYPE_MAX);
516 		}
517 
518 		if (hdrs & ICE_FLOW_SEG_HDR_UDP) {
519 			src = (const ice_bitmap_t *)ice_ptypes_udp_il;
520 			ice_and_bitmap(params->ptypes, params->ptypes, src,
521 				       ICE_FLOW_PTYPE_MAX);
522 		} else if (hdrs & ICE_FLOW_SEG_HDR_TCP) {
523 			ice_and_bitmap(params->ptypes, params->ptypes,
524 				       (const ice_bitmap_t *)ice_ptypes_tcp_il,
525 				       ICE_FLOW_PTYPE_MAX);
526 		} else if (hdrs & ICE_FLOW_SEG_HDR_SCTP) {
527 			src = (const ice_bitmap_t *)ice_ptypes_sctp_il;
528 			ice_and_bitmap(params->ptypes, params->ptypes, src,
529 				       ICE_FLOW_PTYPE_MAX);
530 		}
531 
532 		if (hdrs & ICE_FLOW_SEG_HDR_ICMP) {
533 			src = !i ? (const ice_bitmap_t *)ice_ptypes_icmp_of :
534 				(const ice_bitmap_t *)ice_ptypes_icmp_il;
535 			ice_and_bitmap(params->ptypes, params->ptypes, src,
536 				       ICE_FLOW_PTYPE_MAX);
537 		} else if (hdrs & ICE_FLOW_SEG_HDR_GRE) {
538 			if (!i) {
539 				src = (const ice_bitmap_t *)ice_ptypes_gre_of;
540 				ice_and_bitmap(params->ptypes, params->ptypes,
541 					       src, ICE_FLOW_PTYPE_MAX);
542 			}
543 		}
544 	}
545 
546 	return 0;
547 }
548 
549 /*
550  * ice_flow_xtract_fld - Create an extraction sequence entry for the given field
551  * @hw: pointer to the HW struct
552  * @params: information about the flow to be processed
553  * @seg: packet segment index of the field to be extracted
554  * @fld: ID of field to be extracted
555  *
556  * This function determines the protocol ID, offset, and size of the given
557  * field. It then allocates one or more extraction sequence entries for the
558  * given field, and fill the entries with protocol ID and offset information.
559  */
560 static int
561 ice_flow_xtract_fld(struct ice_hw *hw, struct ice_flow_prof_params *params,
562 		    u8 seg, enum ice_flow_field fld)
563 {
564 	enum ice_flow_field sib = ICE_FLOW_FIELD_IDX_MAX;
565 	u8 fv_words = (u8)hw->blk[params->blk].es.fvw;
566 	enum ice_prot_id prot_id = ICE_PROT_ID_INVAL;
567 	struct ice_flow_fld_info *flds;
568 	u16 cnt, ese_bits, i;
569 	u16 off;
570 
571 	flds = params->prof->segs[seg].fields;
572 
573 	switch (fld) {
574 	case ICE_FLOW_FIELD_IDX_ETH_DA:
575 	case ICE_FLOW_FIELD_IDX_ETH_SA:
576 	case ICE_FLOW_FIELD_IDX_S_VLAN:
577 	case ICE_FLOW_FIELD_IDX_C_VLAN:
578 		prot_id = seg == 0 ? ICE_PROT_MAC_OF_OR_S : ICE_PROT_MAC_IL;
579 		break;
580 	case ICE_FLOW_FIELD_IDX_ETH_TYPE:
581 		prot_id = seg == 0 ? ICE_PROT_ETYPE_OL : ICE_PROT_ETYPE_IL;
582 		break;
583 	case ICE_FLOW_FIELD_IDX_IPV4_DSCP:
584 		prot_id = seg == 0 ? ICE_PROT_IPV4_OF_OR_S : ICE_PROT_IPV4_IL;
585 		break;
586 	case ICE_FLOW_FIELD_IDX_IPV6_DSCP:
587 		prot_id = seg == 0 ? ICE_PROT_IPV6_OF_OR_S : ICE_PROT_IPV6_IL;
588 		break;
589 	case ICE_FLOW_FIELD_IDX_IPV4_TTL:
590 	case ICE_FLOW_FIELD_IDX_IPV4_PROT:
591 		prot_id = seg == 0 ? ICE_PROT_IPV4_OF_OR_S : ICE_PROT_IPV4_IL;
592 		/* TTL and PROT share the same extraction seq. entry.
593 		 * Each is considered a sibling to the other in terms of sharing
594 		 * the same extraction sequence entry.
595 		 */
596 		if (fld == ICE_FLOW_FIELD_IDX_IPV4_TTL)
597 			sib = ICE_FLOW_FIELD_IDX_IPV4_PROT;
598 		else
599 			sib = ICE_FLOW_FIELD_IDX_IPV4_TTL;
600 		break;
601 	case ICE_FLOW_FIELD_IDX_IPV6_TTL:
602 	case ICE_FLOW_FIELD_IDX_IPV6_PROT:
603 		prot_id = seg == 0 ? ICE_PROT_IPV6_OF_OR_S : ICE_PROT_IPV6_IL;
604 		/* TTL and PROT share the same extraction seq. entry.
605 		 * Each is considered a sibling to the other in terms of sharing
606 		 * the same extraction sequence entry.
607 		 */
608 		if (fld == ICE_FLOW_FIELD_IDX_IPV6_TTL)
609 			sib = ICE_FLOW_FIELD_IDX_IPV6_PROT;
610 		else
611 			sib = ICE_FLOW_FIELD_IDX_IPV6_TTL;
612 		break;
613 	case ICE_FLOW_FIELD_IDX_IPV4_SA:
614 	case ICE_FLOW_FIELD_IDX_IPV4_DA:
615 		prot_id = seg == 0 ? ICE_PROT_IPV4_OF_OR_S : ICE_PROT_IPV4_IL;
616 		break;
617 	case ICE_FLOW_FIELD_IDX_IPV6_SA:
618 	case ICE_FLOW_FIELD_IDX_IPV6_DA:
619 		prot_id = seg == 0 ? ICE_PROT_IPV6_OF_OR_S : ICE_PROT_IPV6_IL;
620 		break;
621 	case ICE_FLOW_FIELD_IDX_TCP_SRC_PORT:
622 	case ICE_FLOW_FIELD_IDX_TCP_DST_PORT:
623 	case ICE_FLOW_FIELD_IDX_TCP_FLAGS:
624 		prot_id = ICE_PROT_TCP_IL;
625 		break;
626 	case ICE_FLOW_FIELD_IDX_UDP_SRC_PORT:
627 	case ICE_FLOW_FIELD_IDX_UDP_DST_PORT:
628 		prot_id = ICE_PROT_UDP_IL_OR_S;
629 		break;
630 	case ICE_FLOW_FIELD_IDX_SCTP_SRC_PORT:
631 	case ICE_FLOW_FIELD_IDX_SCTP_DST_PORT:
632 		prot_id = ICE_PROT_SCTP_IL;
633 		break;
634 	case ICE_FLOW_FIELD_IDX_ARP_SIP:
635 	case ICE_FLOW_FIELD_IDX_ARP_DIP:
636 	case ICE_FLOW_FIELD_IDX_ARP_SHA:
637 	case ICE_FLOW_FIELD_IDX_ARP_DHA:
638 	case ICE_FLOW_FIELD_IDX_ARP_OP:
639 		prot_id = ICE_PROT_ARP_OF;
640 		break;
641 	case ICE_FLOW_FIELD_IDX_ICMP_TYPE:
642 	case ICE_FLOW_FIELD_IDX_ICMP_CODE:
643 		/* ICMP type and code share the same extraction seq. entry */
644 		prot_id = (params->prof->segs[seg].hdrs & ICE_FLOW_SEG_HDR_IPV4) ?
645 			ICE_PROT_ICMP_IL : ICE_PROT_ICMPV6_IL;
646 		sib = fld == ICE_FLOW_FIELD_IDX_ICMP_TYPE ?
647 			ICE_FLOW_FIELD_IDX_ICMP_CODE :
648 			ICE_FLOW_FIELD_IDX_ICMP_TYPE;
649 		break;
650 	case ICE_FLOW_FIELD_IDX_GRE_KEYID:
651 		prot_id = ICE_PROT_GRE_OF;
652 		break;
653 	default:
654 		return ICE_ERR_NOT_IMPL;
655 	}
656 
657 	/* Each extraction sequence entry is a word in size, and extracts a
658 	 * word-aligned offset from a protocol header.
659 	 */
660 	ese_bits = ICE_FLOW_FV_EXTRACT_SZ * BITS_PER_BYTE;
661 
662 	flds[fld].xtrct.prot_id = (u8)prot_id;
663 	flds[fld].xtrct.off = (ice_flds_info[fld].off / ese_bits) *
664 		ICE_FLOW_FV_EXTRACT_SZ;
665 	flds[fld].xtrct.disp = (u8)(ice_flds_info[fld].off % ese_bits);
666 	flds[fld].xtrct.idx = params->es_cnt;
667 
668 	/* Adjust the next field-entry index after accommodating the number of
669 	 * entries this field consumes
670 	 */
671 	cnt = DIVIDE_AND_ROUND_UP(flds[fld].xtrct.disp +
672 				  ice_flds_info[fld].size, ese_bits);
673 
674 	/* Fill in the extraction sequence entries needed for this field */
675 	off = flds[fld].xtrct.off;
676 	for (i = 0; i < cnt; i++) {
677 		/* Only consume an extraction sequence entry if there is no
678 		 * sibling field associated with this field or the sibling entry
679 		 * already extracts the word shared with this field.
680 		 */
681 		if (sib == ICE_FLOW_FIELD_IDX_MAX ||
682 		    flds[sib].xtrct.prot_id == ICE_PROT_ID_INVAL ||
683 		    flds[sib].xtrct.off != off) {
684 			u8 idx;
685 
686 			/* Make sure the number of extraction sequence required
687 			 * does not exceed the block's capability
688 			 */
689 			if (params->es_cnt >= fv_words)
690 				return ICE_ERR_MAX_LIMIT;
691 
692 			/* some blocks require a reversed field vector layout */
693 			if (hw->blk[params->blk].es.reverse)
694 				idx = fv_words - params->es_cnt - 1;
695 			else
696 				idx = params->es_cnt;
697 
698 			params->es[idx].prot_id = (u8)prot_id;
699 			params->es[idx].off = off;
700 			params->es_cnt++;
701 		}
702 
703 		off += ICE_FLOW_FV_EXTRACT_SZ;
704 	}
705 
706 	return 0;
707 }
708 
709 /**
710  * ice_flow_create_xtrct_seq - Create an extraction sequence for given segments
711  * @hw: pointer to the HW struct
712  * @params: information about the flow to be processed
713  *
714  * This function iterates through all matched fields in the given segments, and
715  * creates an extraction sequence for the fields.
716  */
717 static int
718 ice_flow_create_xtrct_seq(struct ice_hw *hw,
719 			  struct ice_flow_prof_params *params)
720 {
721 	int status = 0;
722 	u8 i;
723 
724 	for (i = 0; i < params->prof->segs_cnt; i++) {
725 		ice_declare_bitmap(match, ICE_FLOW_FIELD_IDX_MAX);
726 		enum ice_flow_field j;
727 
728 		ice_cp_bitmap(match, params->prof->segs[i].match,
729 			      ICE_FLOW_FIELD_IDX_MAX);
730 		ice_for_each_set_bit(j, match, ICE_FLOW_FIELD_IDX_MAX) {
731 			status = ice_flow_xtract_fld(hw, params, i, j);
732 			if (status)
733 				return status;
734 			ice_clear_bit(j, match);
735 		}
736 	}
737 
738 	return status;
739 }
740 
741 /**
742  * ice_flow_proc_segs - process all packet segments associated with a profile
743  * @hw: pointer to the HW struct
744  * @params: information about the flow to be processed
745  */
746 static int
747 ice_flow_proc_segs(struct ice_hw *hw, struct ice_flow_prof_params *params)
748 {
749 	int status;
750 
751 	status = ice_flow_proc_seg_hdrs(params);
752 	if (status)
753 		return status;
754 
755 	status = ice_flow_create_xtrct_seq(hw, params);
756 	if (status)
757 		return status;
758 
759 	switch (params->blk) {
760 	case ICE_BLK_RSS:
761 		status = 0;
762 		break;
763 	default:
764 		return ICE_ERR_NOT_IMPL;
765 	}
766 
767 	return status;
768 }
769 
770 #define ICE_FLOW_FIND_PROF_CHK_FLDS	0x00000001
771 #define ICE_FLOW_FIND_PROF_CHK_VSI	0x00000002
772 #define ICE_FLOW_FIND_PROF_NOT_CHK_DIR	0x00000004
773 
774 /**
775  * ice_flow_find_prof_conds - Find a profile matching headers and conditions
776  * @hw: pointer to the HW struct
777  * @blk: classification stage
778  * @dir: flow direction
779  * @segs: array of one or more packet segments that describe the flow
780  * @segs_cnt: number of packet segments provided
781  * @vsi_handle: software VSI handle to check VSI (ICE_FLOW_FIND_PROF_CHK_VSI)
782  * @conds: additional conditions to be checked (ICE_FLOW_FIND_PROF_CHK_*)
783  */
784 static struct ice_flow_prof *
785 ice_flow_find_prof_conds(struct ice_hw *hw, enum ice_block blk,
786 			 enum ice_flow_dir dir, struct ice_flow_seg_info *segs,
787 			 u8 segs_cnt, u16 vsi_handle, u32 conds)
788 {
789 	struct ice_flow_prof *p, *prof = NULL;
790 
791 	ice_acquire_lock(&hw->fl_profs_locks[blk]);
792 	LIST_FOR_EACH_ENTRY(p, &hw->fl_profs[blk], ice_flow_prof, l_entry)
793 		if ((p->dir == dir || conds & ICE_FLOW_FIND_PROF_NOT_CHK_DIR) &&
794 		    segs_cnt && segs_cnt == p->segs_cnt) {
795 			u8 i;
796 
797 			/* Check for profile-VSI association if specified */
798 			if ((conds & ICE_FLOW_FIND_PROF_CHK_VSI) &&
799 			    ice_is_vsi_valid(hw, vsi_handle) &&
800 			    !ice_is_bit_set(p->vsis, vsi_handle))
801 				continue;
802 
803 			/* Protocol headers must be checked. Matched fields are
804 			 * checked if specified.
805 			 */
806 			for (i = 0; i < segs_cnt; i++)
807 				if (segs[i].hdrs != p->segs[i].hdrs ||
808 				    ((conds & ICE_FLOW_FIND_PROF_CHK_FLDS) &&
809 				     (ice_cmp_bitmap(segs[i].match,
810 						     p->segs[i].match,
811 						     ICE_FLOW_FIELD_IDX_MAX) ==
812 				       false)))
813 					break;
814 
815 			/* A match is found if all segments are matched */
816 			if (i == segs_cnt) {
817 				prof = p;
818 				break;
819 			}
820 		}
821 	ice_release_lock(&hw->fl_profs_locks[blk]);
822 
823 	return prof;
824 }
825 
826 /**
827  * ice_flow_find_prof - Look up a profile matching headers and matched fields
828  * @hw: pointer to the HW struct
829  * @blk: classification stage
830  * @dir: flow direction
831  * @segs: array of one or more packet segments that describe the flow
832  * @segs_cnt: number of packet segments provided
833  */
834 u64
835 ice_flow_find_prof(struct ice_hw *hw, enum ice_block blk, enum ice_flow_dir dir,
836 		   struct ice_flow_seg_info *segs, u8 segs_cnt)
837 {
838 	struct ice_flow_prof *p;
839 
840 	p = ice_flow_find_prof_conds(hw, blk, dir, segs, segs_cnt,
841 				     ICE_MAX_VSI, ICE_FLOW_FIND_PROF_CHK_FLDS);
842 
843 	return p ? p->id : ICE_FLOW_PROF_ID_INVAL;
844 }
845 
846 /**
847  * ice_flow_find_prof_id - Look up a profile with given profile ID
848  * @hw: pointer to the HW struct
849  * @blk: classification stage
850  * @prof_id: unique ID to identify this flow profile
851  */
852 static struct ice_flow_prof *
853 ice_flow_find_prof_id(struct ice_hw *hw, enum ice_block blk, u64 prof_id)
854 {
855 	struct ice_flow_prof *p;
856 
857 	LIST_FOR_EACH_ENTRY(p, &hw->fl_profs[blk], ice_flow_prof, l_entry)
858 		if (p->id == prof_id)
859 			return p;
860 
861 	return NULL;
862 }
863 
864 /**
865  * ice_flow_get_hw_prof - return the HW profile for a specific profile ID handle
866  * @hw: pointer to the HW struct
867  * @blk: classification stage
868  * @prof_id: the profile ID handle
869  * @hw_prof_id: pointer to variable to receive the HW profile ID
870  */
871 int
872 ice_flow_get_hw_prof(struct ice_hw *hw, enum ice_block blk, u64 prof_id,
873 		     u8 *hw_prof_id)
874 {
875 	struct ice_prof_map *map;
876 	int status = ICE_ERR_DOES_NOT_EXIST;
877 
878 	ice_acquire_lock(&hw->blk[blk].es.prof_map_lock);
879 	map = ice_search_prof_id(hw, blk, prof_id);
880 	if (map) {
881 		*hw_prof_id = map->prof_id;
882 		status = 0;
883 	}
884 	ice_release_lock(&hw->blk[blk].es.prof_map_lock);
885 	return status;
886 }
887 
888 /**
889  * ice_flow_add_prof_sync - Add a flow profile for packet segments and fields
890  * @hw: pointer to the HW struct
891  * @blk: classification stage
892  * @dir: flow direction
893  * @prof_id: unique ID to identify this flow profile
894  * @segs: array of one or more packet segments that describe the flow
895  * @segs_cnt: number of packet segments provided
896  * @acts: array of default actions
897  * @acts_cnt: number of default actions
898  * @prof: stores the returned flow profile added
899  *
900  * Assumption: the caller has acquired the lock to the profile list
901  */
902 static int
903 ice_flow_add_prof_sync(struct ice_hw *hw, enum ice_block blk,
904 		       enum ice_flow_dir dir, u64 prof_id,
905 		       struct ice_flow_seg_info *segs, u8 segs_cnt,
906 		       struct ice_flow_action *acts, u8 acts_cnt,
907 		       struct ice_flow_prof **prof)
908 {
909 	struct ice_flow_prof_params *params;
910 	int status;
911 	u8 i;
912 
913 	if (!prof || (acts_cnt && !acts))
914 		return ICE_ERR_BAD_PTR;
915 
916 	params = (struct ice_flow_prof_params *)ice_malloc(hw, sizeof(*params));
917 	if (!params)
918 		return ICE_ERR_NO_MEMORY;
919 
920 	params->prof = (struct ice_flow_prof *)
921 		ice_malloc(hw, sizeof(*params->prof));
922 	if (!params->prof) {
923 		status = ICE_ERR_NO_MEMORY;
924 		goto free_params;
925 	}
926 
927 	/* initialize extraction sequence to all invalid (0xff) */
928 	for (i = 0; i < ICE_MAX_FV_WORDS; i++) {
929 		params->es[i].prot_id = ICE_PROT_INVALID;
930 		params->es[i].off = ICE_FV_OFFSET_INVAL;
931 	}
932 
933 	params->blk = blk;
934 	params->prof->id = prof_id;
935 	params->prof->dir = dir;
936 	params->prof->segs_cnt = segs_cnt;
937 
938 	/* Make a copy of the segments that need to be persistent in the flow
939 	 * profile instance
940 	 */
941 	for (i = 0; i < segs_cnt; i++)
942 		ice_memcpy(&params->prof->segs[i], &segs[i], sizeof(*segs),
943 			   ICE_NONDMA_TO_NONDMA);
944 
945 	status = ice_flow_proc_segs(hw, params);
946 	if (status) {
947 		ice_debug(hw, ICE_DBG_FLOW, "Error processing a flow's packet segments\n");
948 		goto out;
949 	}
950 
951 	/* Add a HW profile for this flow profile */
952 	status = ice_add_prof(hw, blk, prof_id, params->ptypes, params->es);
953 	if (status) {
954 		ice_debug(hw, ICE_DBG_FLOW, "Error adding a HW flow profile\n");
955 		goto out;
956 	}
957 
958 	*prof = params->prof;
959 
960 out:
961 	if (status) {
962 		ice_free(hw, params->prof);
963 	}
964 free_params:
965 	ice_free(hw, params);
966 
967 	return status;
968 }
969 
970 /**
971  * ice_flow_rem_prof_sync - remove a flow profile
972  * @hw: pointer to the hardware structure
973  * @blk: classification stage
974  * @prof: pointer to flow profile to remove
975  *
976  * Assumption: the caller has acquired the lock to the profile list
977  */
978 static int
979 ice_flow_rem_prof_sync(struct ice_hw *hw, enum ice_block blk,
980 		       struct ice_flow_prof *prof)
981 {
982 	int status;
983 
984 	/* Remove all hardware profiles associated with this flow profile */
985 	status = ice_rem_prof(hw, blk, prof->id);
986 	if (!status) {
987 		LIST_DEL(&prof->l_entry);
988 		ice_free(hw, prof);
989 	}
990 
991 	return status;
992 }
993 
994 /**
995  * ice_flow_assoc_vsig_vsi - associate a VSI with VSIG
996  * @hw: pointer to the hardware structure
997  * @blk: classification stage
998  * @vsi_handle: software VSI handle
999  * @vsig: target VSI group
1000  *
1001  * Assumption: the caller has already verified that the VSI to
1002  * be added has the same characteristics as the VSIG and will
1003  * thereby have access to all resources added to that VSIG.
1004  */
1005 int
1006 ice_flow_assoc_vsig_vsi(struct ice_hw *hw, enum ice_block blk, u16 vsi_handle,
1007 			u16 vsig)
1008 {
1009 	int status;
1010 
1011 	if (!ice_is_vsi_valid(hw, vsi_handle) || blk >= ICE_BLK_COUNT)
1012 		return ICE_ERR_PARAM;
1013 
1014 	ice_acquire_lock(&hw->fl_profs_locks[blk]);
1015 	status = ice_add_vsi_flow(hw, blk, ice_get_hw_vsi_num(hw, vsi_handle),
1016 				  vsig);
1017 	ice_release_lock(&hw->fl_profs_locks[blk]);
1018 
1019 	return status;
1020 }
1021 
1022 /**
1023  * ice_flow_assoc_prof - associate a VSI with a flow profile
1024  * @hw: pointer to the hardware structure
1025  * @blk: classification stage
1026  * @prof: pointer to flow profile
1027  * @vsi_handle: software VSI handle
1028  *
1029  * Assumption: the caller has acquired the lock to the profile list
1030  * and the software VSI handle has been validated
1031  */
1032 static int
1033 ice_flow_assoc_prof(struct ice_hw *hw, enum ice_block blk,
1034 		    struct ice_flow_prof *prof, u16 vsi_handle)
1035 {
1036 	int status = 0;
1037 
1038 	if (!ice_is_bit_set(prof->vsis, vsi_handle)) {
1039 		status = ice_add_prof_id_flow(hw, blk,
1040 					      ice_get_hw_vsi_num(hw,
1041 								 vsi_handle),
1042 					      prof->id);
1043 		if (!status)
1044 			ice_set_bit(vsi_handle, prof->vsis);
1045 		else
1046 			ice_debug(hw, ICE_DBG_FLOW, "HW profile add failed, %d\n",
1047 				  status);
1048 	}
1049 
1050 	return status;
1051 }
1052 
1053 /**
1054  * ice_flow_disassoc_prof - disassociate a VSI from a flow profile
1055  * @hw: pointer to the hardware structure
1056  * @blk: classification stage
1057  * @prof: pointer to flow profile
1058  * @vsi_handle: software VSI handle
1059  *
1060  * Assumption: the caller has acquired the lock to the profile list
1061  * and the software VSI handle has been validated
1062  */
1063 static int
1064 ice_flow_disassoc_prof(struct ice_hw *hw, enum ice_block blk,
1065 		       struct ice_flow_prof *prof, u16 vsi_handle)
1066 {
1067 	int status = 0;
1068 
1069 	if (ice_is_bit_set(prof->vsis, vsi_handle)) {
1070 		status = ice_rem_prof_id_flow(hw, blk,
1071 					      ice_get_hw_vsi_num(hw,
1072 								 vsi_handle),
1073 					      prof->id);
1074 		if (!status)
1075 			ice_clear_bit(vsi_handle, prof->vsis);
1076 		else
1077 			ice_debug(hw, ICE_DBG_FLOW, "HW profile remove failed, %d\n",
1078 				  status);
1079 	}
1080 
1081 	return status;
1082 }
1083 
1084 /**
1085  * ice_flow_add_prof - Add a flow profile for packet segments and matched fields
1086  * @hw: pointer to the HW struct
1087  * @blk: classification stage
1088  * @dir: flow direction
1089  * @prof_id: unique ID to identify this flow profile
1090  * @segs: array of one or more packet segments that describe the flow
1091  * @segs_cnt: number of packet segments provided
1092  * @acts: array of default actions
1093  * @acts_cnt: number of default actions
1094  * @prof: stores the returned flow profile added
1095  */
1096 static int
1097 ice_flow_add_prof(struct ice_hw *hw, enum ice_block blk, enum ice_flow_dir dir,
1098 		  u64 prof_id, struct ice_flow_seg_info *segs, u8 segs_cnt,
1099 		  struct ice_flow_action *acts, u8 acts_cnt,
1100 		  struct ice_flow_prof **prof)
1101 {
1102 	int status;
1103 
1104 	if (segs_cnt > ICE_FLOW_SEG_MAX)
1105 		return ICE_ERR_MAX_LIMIT;
1106 
1107 	if (!segs_cnt)
1108 		return ICE_ERR_PARAM;
1109 
1110 	if (!segs)
1111 		return ICE_ERR_BAD_PTR;
1112 
1113 	status = ice_flow_val_hdrs(segs, segs_cnt);
1114 	if (status)
1115 		return status;
1116 
1117 	ice_acquire_lock(&hw->fl_profs_locks[blk]);
1118 
1119 	status = ice_flow_add_prof_sync(hw, blk, dir, prof_id, segs, segs_cnt,
1120 					acts, acts_cnt, prof);
1121 	if (!status)
1122 		LIST_ADD(&(*prof)->l_entry, &hw->fl_profs[blk]);
1123 
1124 	ice_release_lock(&hw->fl_profs_locks[blk]);
1125 
1126 	return status;
1127 }
1128 
1129 /**
1130  * ice_flow_rem_prof - Remove a flow profile and all entries associated with it
1131  * @hw: pointer to the HW struct
1132  * @blk: the block for which the flow profile is to be removed
1133  * @prof_id: unique ID of the flow profile to be removed
1134  */
1135 static int
1136 ice_flow_rem_prof(struct ice_hw *hw, enum ice_block blk, u64 prof_id)
1137 {
1138 	struct ice_flow_prof *prof;
1139 	int status;
1140 
1141 	ice_acquire_lock(&hw->fl_profs_locks[blk]);
1142 
1143 	prof = ice_flow_find_prof_id(hw, blk, prof_id);
1144 	if (!prof) {
1145 		status = ICE_ERR_DOES_NOT_EXIST;
1146 		goto out;
1147 	}
1148 
1149 	/* prof becomes invalid after the call */
1150 	status = ice_flow_rem_prof_sync(hw, blk, prof);
1151 
1152 out:
1153 	ice_release_lock(&hw->fl_profs_locks[blk]);
1154 
1155 	return status;
1156 }
1157 
1158 /**
1159  * ice_flow_set_fld_ext - specifies locations of field from entry's input buffer
1160  * @seg: packet segment the field being set belongs to
1161  * @fld: field to be set
1162  * @field_type: type of the field
1163  * @val_loc: if not ICE_FLOW_FLD_OFF_INVAL, location of the value to match from
1164  *           entry's input buffer
1165  * @mask_loc: if not ICE_FLOW_FLD_OFF_INVAL, location of mask value from entry's
1166  *            input buffer
1167  * @last_loc: if not ICE_FLOW_FLD_OFF_INVAL, location of last/upper value from
1168  *            entry's input buffer
1169  *
1170  * This helper function stores information of a field being matched, including
1171  * the type of the field and the locations of the value to match, the mask, and
1172  * the upper-bound value in the start of the input buffer for a flow entry.
1173  * This function should only be used for fixed-size data structures.
1174  *
1175  * This function also opportunistically determines the protocol headers to be
1176  * present based on the fields being set. Some fields cannot be used alone to
1177  * determine the protocol headers present. Sometimes, fields for particular
1178  * protocol headers are not matched. In those cases, the protocol headers
1179  * must be explicitly set.
1180  */
1181 static void
1182 ice_flow_set_fld_ext(struct ice_flow_seg_info *seg, enum ice_flow_field fld,
1183 		     enum ice_flow_fld_match_type field_type, u16 val_loc,
1184 		     u16 mask_loc, u16 last_loc)
1185 {
1186 	ice_set_bit(fld, seg->match);
1187 	if (field_type == ICE_FLOW_FLD_TYPE_RANGE)
1188 		ice_set_bit(fld, seg->range);
1189 
1190 	seg->fields[fld].type = field_type;
1191 	seg->fields[fld].src.val = val_loc;
1192 	seg->fields[fld].src.mask = mask_loc;
1193 	seg->fields[fld].src.last = last_loc;
1194 
1195 	ICE_FLOW_SET_HDRS(seg, ice_flds_info[fld].hdr);
1196 }
1197 
1198 /**
1199  * ice_flow_set_fld - specifies locations of field from entry's input buffer
1200  * @seg: packet segment the field being set belongs to
1201  * @fld: field to be set
1202  * @val_loc: if not ICE_FLOW_FLD_OFF_INVAL, location of the value to match from
1203  *           entry's input buffer
1204  * @mask_loc: if not ICE_FLOW_FLD_OFF_INVAL, location of mask value from entry's
1205  *            input buffer
1206  * @last_loc: if not ICE_FLOW_FLD_OFF_INVAL, location of last/upper value from
1207  *            entry's input buffer
1208  * @range: indicate if field being matched is to be in a range
1209  *
1210  * This function specifies the locations, in the form of byte offsets from the
1211  * start of the input buffer for a flow entry, from where the value to match,
1212  * the mask value, and upper value can be extracted. These locations are then
1213  * stored in the flow profile. When adding a flow entry associated with the
1214  * flow profile, these locations will be used to quickly extract the values and
1215  * create the content of a match entry. This function should only be used for
1216  * fixed-size data structures.
1217  */
1218 static void
1219 ice_flow_set_fld(struct ice_flow_seg_info *seg, enum ice_flow_field fld,
1220 		 u16 val_loc, u16 mask_loc, u16 last_loc, bool range)
1221 {
1222 	enum ice_flow_fld_match_type t = range ?
1223 		ICE_FLOW_FLD_TYPE_RANGE : ICE_FLOW_FLD_TYPE_REG;
1224 
1225 	ice_flow_set_fld_ext(seg, fld, t, val_loc, mask_loc, last_loc);
1226 }
1227 
1228 /**
1229  * ice_flow_set_fld_prefix - sets locations of prefix field from entry's buf
1230  * @seg: packet segment the field being set belongs to
1231  * @fld: field to be set
1232  * @val_loc: if not ICE_FLOW_FLD_OFF_INVAL, location of the value to match from
1233  *           entry's input buffer
1234  * @pref_loc: location of prefix value from entry's input buffer
1235  * @pref_sz: size of the location holding the prefix value
1236  *
1237  * This function specifies the locations, in the form of byte offsets from the
1238  * start of the input buffer for a flow entry, from where the value to match
1239  * and the IPv4 prefix value can be extracted. These locations are then stored
1240  * in the flow profile. When adding flow entries to the associated flow profile,
1241  * these locations can be used to quickly extract the values to create the
1242  * content of a match entry. This function should only be used for fixed-size
1243  * data structures.
1244  */
1245 void
1246 ice_flow_set_fld_prefix(struct ice_flow_seg_info *seg, enum ice_flow_field fld,
1247 			u16 val_loc, u16 pref_loc, u8 pref_sz)
1248 {
1249 	/* For this type of field, the "mask" location is for the prefix value's
1250 	 * location and the "last" location is for the size of the location of
1251 	 * the prefix value.
1252 	 */
1253 	ice_flow_set_fld_ext(seg, fld, ICE_FLOW_FLD_TYPE_PREFIX, val_loc,
1254 			     pref_loc, (u16)pref_sz);
1255 }
1256 
1257 #define ICE_FLOW_RSS_SEG_HDR_L3_MASKS \
1258 	(ICE_FLOW_SEG_HDR_IPV4 | ICE_FLOW_SEG_HDR_IPV6)
1259 
1260 #define ICE_FLOW_RSS_SEG_HDR_L4_MASKS \
1261 	(ICE_FLOW_SEG_HDR_TCP | ICE_FLOW_SEG_HDR_UDP | ICE_FLOW_SEG_HDR_SCTP)
1262 
1263 #define ICE_FLOW_RSS_SEG_HDR_VAL_MASKS \
1264 	(ICE_FLOW_RSS_SEG_HDR_L3_MASKS | \
1265 	 ICE_FLOW_RSS_SEG_HDR_L4_MASKS)
1266 
1267 /**
1268  * ice_flow_set_rss_seg_info - setup packet segments for RSS
1269  * @segs: pointer to the flow field segment(s)
1270  * @seg_cnt: segment count
1271  * @cfg: configure parameters
1272  *
1273  * Helper function to extract fields from hash bitmap and use flow
1274  * header value to set flow field segment for further use in flow
1275  * profile entry or removal.
1276  */
1277 static int
1278 ice_flow_set_rss_seg_info(struct ice_flow_seg_info *segs, u8 seg_cnt,
1279 			  const struct ice_rss_hash_cfg *cfg)
1280 {
1281 	struct ice_flow_seg_info *seg;
1282 	u64 val;
1283 	u16 i;
1284 
1285 	/* set inner most segment */
1286 	seg = &segs[seg_cnt - 1];
1287 
1288 	ice_for_each_set_bit(i, (const ice_bitmap_t *)&cfg->hash_flds,
1289 			     (u16)ICE_FLOW_FIELD_IDX_MAX)
1290 		ice_flow_set_fld(seg, (enum ice_flow_field)i,
1291 				 ICE_FLOW_FLD_OFF_INVAL, ICE_FLOW_FLD_OFF_INVAL,
1292 				 ICE_FLOW_FLD_OFF_INVAL, false);
1293 
1294 	ICE_FLOW_SET_HDRS(seg, cfg->addl_hdrs);
1295 
1296 	/* set outer most header */
1297 	if (cfg->hdr_type == ICE_RSS_INNER_HEADERS_W_OUTER_IPV4)
1298 		segs[ICE_RSS_OUTER_HEADERS].hdrs |= ICE_FLOW_SEG_HDR_IPV4 |
1299 						    ICE_FLOW_SEG_HDR_IPV_FRAG |
1300 						    ICE_FLOW_SEG_HDR_IPV_OTHER;
1301 	else if (cfg->hdr_type == ICE_RSS_INNER_HEADERS_W_OUTER_IPV6)
1302 		segs[ICE_RSS_OUTER_HEADERS].hdrs |= ICE_FLOW_SEG_HDR_IPV6 |
1303 						    ICE_FLOW_SEG_HDR_IPV_FRAG |
1304 						    ICE_FLOW_SEG_HDR_IPV_OTHER;
1305 	else if (cfg->hdr_type == ICE_RSS_INNER_HEADERS_W_OUTER_IPV4_GRE)
1306 		segs[ICE_RSS_OUTER_HEADERS].hdrs |= ICE_FLOW_SEG_HDR_IPV4 |
1307 						    ICE_FLOW_SEG_HDR_GRE |
1308 						    ICE_FLOW_SEG_HDR_IPV_OTHER;
1309 	else if (cfg->hdr_type == ICE_RSS_INNER_HEADERS_W_OUTER_IPV6_GRE)
1310 		segs[ICE_RSS_OUTER_HEADERS].hdrs |= ICE_FLOW_SEG_HDR_IPV6 |
1311 						    ICE_FLOW_SEG_HDR_GRE |
1312 						    ICE_FLOW_SEG_HDR_IPV_OTHER;
1313 
1314 	if (seg->hdrs & ~ICE_FLOW_RSS_SEG_HDR_VAL_MASKS)
1315 		return ICE_ERR_PARAM;
1316 
1317 	val = (u64)(seg->hdrs & ICE_FLOW_RSS_SEG_HDR_L3_MASKS);
1318 	if (val && !ice_is_pow2(val))
1319 		return ICE_ERR_CFG;
1320 
1321 	val = (u64)(seg->hdrs & ICE_FLOW_RSS_SEG_HDR_L4_MASKS);
1322 	if (val && !ice_is_pow2(val))
1323 		return ICE_ERR_CFG;
1324 
1325 	return 0;
1326 }
1327 
1328 /**
1329  * ice_rem_vsi_rss_list - remove VSI from RSS list
1330  * @hw: pointer to the hardware structure
1331  * @vsi_handle: software VSI handle
1332  *
1333  * Remove the VSI from all RSS configurations in the list.
1334  */
1335 void ice_rem_vsi_rss_list(struct ice_hw *hw, u16 vsi_handle)
1336 {
1337 	struct ice_rss_cfg *r, *tmp;
1338 
1339 	if (LIST_EMPTY(&hw->rss_list_head))
1340 		return;
1341 
1342 	ice_acquire_lock(&hw->rss_locks);
1343 	LIST_FOR_EACH_ENTRY_SAFE(r, tmp, &hw->rss_list_head,
1344 				 ice_rss_cfg, l_entry)
1345 		if (ice_test_and_clear_bit(vsi_handle, r->vsis))
1346 			if (!ice_is_any_bit_set(r->vsis, ICE_MAX_VSI)) {
1347 				LIST_DEL(&r->l_entry);
1348 				ice_free(hw, r);
1349 			}
1350 	ice_release_lock(&hw->rss_locks);
1351 }
1352 
1353 /**
1354  * ice_rem_vsi_rss_cfg - remove RSS configurations associated with VSI
1355  * @hw: pointer to the hardware structure
1356  * @vsi_handle: software VSI handle
1357  *
1358  * This function will iterate through all flow profiles and disassociate
1359  * the VSI from that profile. If the flow profile has no VSIs it will
1360  * be removed.
1361  */
1362 int ice_rem_vsi_rss_cfg(struct ice_hw *hw, u16 vsi_handle)
1363 {
1364 	const enum ice_block blk = ICE_BLK_RSS;
1365 	struct ice_flow_prof *p, *t;
1366 	int status = 0;
1367 	u16 vsig;
1368 
1369 	if (!ice_is_vsi_valid(hw, vsi_handle))
1370 		return ICE_ERR_PARAM;
1371 
1372 	if (LIST_EMPTY(&hw->fl_profs[blk]))
1373 		return 0;
1374 
1375 	ice_acquire_lock(&hw->rss_locks);
1376 	LIST_FOR_EACH_ENTRY_SAFE(p, t, &hw->fl_profs[blk], ice_flow_prof,
1377 				 l_entry) {
1378 		int ret;
1379 
1380 		/* check if vsig is already removed */
1381 		ret = ice_vsig_find_vsi(hw, blk,
1382 					ice_get_hw_vsi_num(hw, vsi_handle),
1383 					&vsig);
1384 		if (!ret && !vsig)
1385 			break;
1386 
1387 		if (ice_is_bit_set(p->vsis, vsi_handle)) {
1388 			status = ice_flow_disassoc_prof(hw, blk, p, vsi_handle);
1389 			if (status)
1390 				break;
1391 
1392 			if (!ice_is_any_bit_set(p->vsis, ICE_MAX_VSI)) {
1393 				status = ice_flow_rem_prof(hw, blk, p->id);
1394 				if (status)
1395 					break;
1396 			}
1397 		}
1398 	}
1399 	ice_release_lock(&hw->rss_locks);
1400 
1401 	return status;
1402 }
1403 
1404 /**
1405  * ice_get_rss_hdr_type - get a RSS profile's header type
1406  * @prof: RSS flow profile
1407  */
1408 static enum ice_rss_cfg_hdr_type
1409 ice_get_rss_hdr_type(struct ice_flow_prof *prof)
1410 {
1411 	enum ice_rss_cfg_hdr_type hdr_type = ICE_RSS_ANY_HEADERS;
1412 
1413 	if (prof->segs_cnt == ICE_FLOW_SEG_SINGLE) {
1414 		hdr_type = ICE_RSS_OUTER_HEADERS;
1415 	} else if (prof->segs_cnt == ICE_FLOW_SEG_MAX) {
1416 		const struct ice_flow_seg_info *s;
1417 
1418 		s = &prof->segs[ICE_RSS_OUTER_HEADERS];
1419 		if (s->hdrs == ICE_FLOW_SEG_HDR_NONE)
1420 			hdr_type = ICE_RSS_INNER_HEADERS;
1421 		if (s->hdrs & ICE_FLOW_SEG_HDR_IPV4)
1422 			hdr_type = ICE_RSS_INNER_HEADERS_W_OUTER_IPV4;
1423 		if (s->hdrs & ICE_FLOW_SEG_HDR_IPV6)
1424 			hdr_type = ICE_RSS_INNER_HEADERS_W_OUTER_IPV6;
1425 	}
1426 
1427 	return hdr_type;
1428 }
1429 
1430 /**
1431  * ice_rem_rss_list - remove RSS configuration from list
1432  * @hw: pointer to the hardware structure
1433  * @vsi_handle: software VSI handle
1434  * @prof: pointer to flow profile
1435  *
1436  * Assumption: lock has already been acquired for RSS list
1437  */
1438 static void
1439 ice_rem_rss_list(struct ice_hw *hw, u16 vsi_handle, struct ice_flow_prof *prof)
1440 {
1441 	enum ice_rss_cfg_hdr_type hdr_type;
1442 	struct ice_rss_cfg *r, *tmp;
1443 	u64 seg_match = 0;
1444 	u16 i;
1445 
1446 	/* convert match bitmap to u64 for hash field comparison */
1447 	ice_for_each_set_bit(i, prof->segs[prof->segs_cnt - 1].match,
1448 			     ICE_FLOW_FIELD_IDX_MAX) {
1449 		seg_match |= 1ULL << i;
1450 	}
1451 
1452 	/* Search for RSS hash fields associated to the VSI that match the
1453 	 * hash configurations associated to the flow profile. If found
1454 	 * remove from the RSS entry list of the VSI context and delete entry.
1455 	 */
1456 	hdr_type = ice_get_rss_hdr_type(prof);
1457 	LIST_FOR_EACH_ENTRY_SAFE(r, tmp, &hw->rss_list_head,
1458 				 ice_rss_cfg, l_entry)
1459 		if (r->hash.hash_flds == seg_match &&
1460 		    r->hash.addl_hdrs == prof->segs[prof->segs_cnt - 1].hdrs &&
1461 		    r->hash.hdr_type == hdr_type) {
1462 			ice_clear_bit(vsi_handle, r->vsis);
1463 			if (!ice_is_any_bit_set(r->vsis, ICE_MAX_VSI)) {
1464 				LIST_DEL(&r->l_entry);
1465 				ice_free(hw, r);
1466 			}
1467 			return;
1468 		}
1469 }
1470 
1471 /**
1472  * ice_add_rss_list - add RSS configuration to list
1473  * @hw: pointer to the hardware structure
1474  * @vsi_handle: software VSI handle
1475  * @prof: pointer to flow profile
1476  *
1477  * Assumption: lock has already been acquired for RSS list
1478  */
1479 static int
1480 ice_add_rss_list(struct ice_hw *hw, u16 vsi_handle, struct ice_flow_prof *prof)
1481 {
1482 	enum ice_rss_cfg_hdr_type hdr_type;
1483 	struct ice_rss_cfg *r, *rss_cfg;
1484 	u64 seg_match = 0;
1485 	u16 i;
1486 
1487 	ice_for_each_set_bit(i, prof->segs[prof->segs_cnt - 1].match,
1488 			     ICE_FLOW_FIELD_IDX_MAX) {
1489 		seg_match |= 1ULL << i;
1490 	}
1491 
1492 	hdr_type = ice_get_rss_hdr_type(prof);
1493 	LIST_FOR_EACH_ENTRY(r, &hw->rss_list_head,
1494 			    ice_rss_cfg, l_entry)
1495 		if (r->hash.hash_flds == seg_match &&
1496 		    r->hash.addl_hdrs == prof->segs[prof->segs_cnt - 1].hdrs &&
1497 		    r->hash.hdr_type == hdr_type) {
1498 			ice_set_bit(vsi_handle, r->vsis);
1499 			return 0;
1500 		}
1501 
1502 	rss_cfg = (struct ice_rss_cfg *)ice_malloc(hw, sizeof(*rss_cfg));
1503 	if (!rss_cfg)
1504 		return ICE_ERR_NO_MEMORY;
1505 
1506 	rss_cfg->hash.hash_flds = seg_match;
1507 	rss_cfg->hash.addl_hdrs = prof->segs[prof->segs_cnt - 1].hdrs;
1508 	rss_cfg->hash.hdr_type = hdr_type;
1509 	rss_cfg->hash.symm = prof->cfg.symm;
1510 	ice_set_bit(vsi_handle, rss_cfg->vsis);
1511 
1512 	LIST_ADD_TAIL(&rss_cfg->l_entry, &hw->rss_list_head);
1513 
1514 	return 0;
1515 }
1516 
1517 #define ICE_FLOW_PROF_HASH_S	0
1518 #define ICE_FLOW_PROF_HASH_M	(0xFFFFFFFFULL << ICE_FLOW_PROF_HASH_S)
1519 #define ICE_FLOW_PROF_HDR_S	32
1520 #define ICE_FLOW_PROF_HDR_M	(0x3FFFFFFFULL << ICE_FLOW_PROF_HDR_S)
1521 #define ICE_FLOW_PROF_ENCAP_S	62
1522 #define ICE_FLOW_PROF_ENCAP_M	(0x3ULL << ICE_FLOW_PROF_ENCAP_S)
1523 
1524 /* Flow profile ID format:
1525  * [0:31] - Packet match fields
1526  * [32:61] - Protocol header
1527  * [62:63] - Encapsulation flag:
1528  *	     0 if non-tunneled
1529  *	     1 if tunneled
1530  *	     2 for tunneled with outer IPv4
1531  *	     3 for tunneled with outer IPv6
1532  */
1533 #define ICE_FLOW_GEN_PROFID(hash, hdr, encap)                                \
1534 	((u64)(((u64)(hash) & ICE_FLOW_PROF_HASH_M) |                        \
1535 	       (((u64)(hdr) << ICE_FLOW_PROF_HDR_S) & ICE_FLOW_PROF_HDR_M) | \
1536 	       (((u64)(encap) << ICE_FLOW_PROF_ENCAP_S) &                    \
1537 		ICE_FLOW_PROF_ENCAP_M)))
1538 
1539 /**
1540  * ice_add_rss_cfg_sync - add an RSS configuration
1541  * @hw: pointer to the hardware structure
1542  * @vsi_handle: software VSI handle
1543  * @cfg: configure parameters
1544  *
1545  * Assumption: lock has already been acquired for RSS list
1546  */
1547 static int
1548 ice_add_rss_cfg_sync(struct ice_hw *hw, u16 vsi_handle,
1549 		     const struct ice_rss_hash_cfg *cfg)
1550 {
1551 	const enum ice_block blk = ICE_BLK_RSS;
1552 	struct ice_flow_prof *prof = NULL;
1553 	struct ice_flow_seg_info *segs;
1554 	u8 segs_cnt;
1555 	int status;
1556 
1557 	if (cfg->symm)
1558 		return ICE_ERR_PARAM;
1559 
1560 	segs_cnt = (cfg->hdr_type == ICE_RSS_OUTER_HEADERS) ?
1561 			   ICE_FLOW_SEG_SINGLE :
1562 			   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 int
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 	int status;
1665 
1666 	if (!ice_is_vsi_valid(hw, vsi_handle) || !cfg ||
1667 	    cfg->hdr_type > ICE_RSS_ANY_HEADERS ||
1668 	    cfg->hash_flds == ICE_HASH_INVALID)
1669 		return ICE_ERR_PARAM;
1670 
1671 	ice_acquire_lock(&hw->rss_locks);
1672 	local_cfg = *cfg;
1673 	if (cfg->hdr_type < ICE_RSS_ANY_HEADERS) {
1674 		status = ice_add_rss_cfg_sync(hw, vsi_handle, &local_cfg);
1675 	} else {
1676 		local_cfg.hdr_type = ICE_RSS_OUTER_HEADERS;
1677 		status = ice_add_rss_cfg_sync(hw, vsi_handle, &local_cfg);
1678 		if (!status) {
1679 			local_cfg.hdr_type = ICE_RSS_INNER_HEADERS;
1680 			status = ice_add_rss_cfg_sync(hw, vsi_handle,
1681 						      &local_cfg);
1682 		}
1683 	}
1684 	ice_release_lock(&hw->rss_locks);
1685 
1686 	return status;
1687 }
1688 
1689 /**
1690  * ice_rem_rss_cfg_sync - remove an existing RSS configuration
1691  * @hw: pointer to the hardware structure
1692  * @vsi_handle: software VSI handle
1693  * @cfg: configure parameters
1694  *
1695  * Assumption: lock has already been acquired for RSS list
1696  */
1697 static int
1698 ice_rem_rss_cfg_sync(struct ice_hw *hw, u16 vsi_handle,
1699 		     const struct ice_rss_hash_cfg *cfg)
1700 {
1701 	const enum ice_block blk = ICE_BLK_RSS;
1702 	struct ice_flow_seg_info *segs;
1703 	struct ice_flow_prof *prof;
1704 	u8 segs_cnt;
1705 	int status;
1706 
1707 	segs_cnt = (cfg->hdr_type == ICE_RSS_OUTER_HEADERS) ?
1708 			   ICE_FLOW_SEG_SINGLE :
1709 			   ICE_FLOW_SEG_MAX;
1710 	segs = (struct ice_flow_seg_info *)ice_calloc(hw, segs_cnt,
1711 						      sizeof(*segs));
1712 	if (!segs)
1713 		return ICE_ERR_NO_MEMORY;
1714 
1715 	/* Construct the packet segment info from the hashed fields */
1716 	status = ice_flow_set_rss_seg_info(segs, segs_cnt, cfg);
1717 	if (status)
1718 		goto out;
1719 
1720 	prof = ice_flow_find_prof_conds(hw, blk, ICE_FLOW_RX, segs, segs_cnt,
1721 					vsi_handle,
1722 					ICE_FLOW_FIND_PROF_CHK_FLDS);
1723 	if (!prof) {
1724 		status = ICE_ERR_DOES_NOT_EXIST;
1725 		goto out;
1726 	}
1727 
1728 	status = ice_flow_disassoc_prof(hw, blk, prof, vsi_handle);
1729 	if (status)
1730 		goto out;
1731 
1732 	/* Remove RSS configuration from VSI context before deleting
1733 	 * the flow profile.
1734 	 */
1735 	ice_rem_rss_list(hw, vsi_handle, prof);
1736 
1737 	if (!ice_is_any_bit_set(prof->vsis, ICE_MAX_VSI))
1738 		status = ice_flow_rem_prof(hw, blk, prof->id);
1739 
1740 out:
1741 	ice_free(hw, segs);
1742 	return status;
1743 }
1744 
1745 /**
1746  * ice_rem_rss_cfg - remove an existing RSS config with matching hashed fields
1747  * @hw: pointer to the hardware structure
1748  * @vsi_handle: software VSI handle
1749  * @cfg: configure parameters
1750  *
1751  * This function will lookup the flow profile based on the input
1752  * hash field bitmap, iterate through the profile entry list of
1753  * that profile and find entry associated with input VSI to be
1754  * removed. Calls are made to underlying flow apis which will in
1755  * turn build or update buffers for RSS XLT1 section.
1756  */
1757 int
1758 ice_rem_rss_cfg(struct ice_hw *hw, u16 vsi_handle,
1759 		const struct ice_rss_hash_cfg *cfg)
1760 {
1761 	struct ice_rss_hash_cfg local_cfg;
1762 	int status;
1763 
1764 	if (!ice_is_vsi_valid(hw, vsi_handle) || !cfg ||
1765 	    cfg->hdr_type > ICE_RSS_ANY_HEADERS ||
1766 	    cfg->hash_flds == ICE_HASH_INVALID)
1767 		return ICE_ERR_PARAM;
1768 
1769 	ice_acquire_lock(&hw->rss_locks);
1770 	local_cfg = *cfg;
1771 	if (cfg->hdr_type < ICE_RSS_ANY_HEADERS) {
1772 		status = ice_rem_rss_cfg_sync(hw, vsi_handle, &local_cfg);
1773 	} else {
1774 		local_cfg.hdr_type = ICE_RSS_OUTER_HEADERS;
1775 		status = ice_rem_rss_cfg_sync(hw, vsi_handle, &local_cfg);
1776 		if (!status) {
1777 			local_cfg.hdr_type = ICE_RSS_INNER_HEADERS;
1778 			status = ice_rem_rss_cfg_sync(hw, vsi_handle,
1779 						      &local_cfg);
1780 		}
1781 	}
1782 	ice_release_lock(&hw->rss_locks);
1783 
1784 	return status;
1785 }
1786 
1787 /* Mapping of AVF hash bit fields to an L3-L4 hash combination.
1788  * As the ice_flow_avf_hdr_field represent individual bit shifts in a hash,
1789  * convert its values to their appropriate flow L3, L4 values.
1790  */
1791 #define ICE_FLOW_AVF_RSS_IPV4_MASKS \
1792 	(BIT_ULL(ICE_AVF_FLOW_FIELD_IPV4_OTHER) | \
1793 	 BIT_ULL(ICE_AVF_FLOW_FIELD_FRAG_IPV4))
1794 #define ICE_FLOW_AVF_RSS_TCP_IPV4_MASKS \
1795 	(BIT_ULL(ICE_AVF_FLOW_FIELD_IPV4_TCP_SYN_NO_ACK) | \
1796 	 BIT_ULL(ICE_AVF_FLOW_FIELD_IPV4_TCP))
1797 #define ICE_FLOW_AVF_RSS_UDP_IPV4_MASKS \
1798 	(BIT_ULL(ICE_AVF_FLOW_FIELD_UNICAST_IPV4_UDP) | \
1799 	 BIT_ULL(ICE_AVF_FLOW_FIELD_MULTICAST_IPV4_UDP) | \
1800 	 BIT_ULL(ICE_AVF_FLOW_FIELD_IPV4_UDP))
1801 #define ICE_FLOW_AVF_RSS_ALL_IPV4_MASKS \
1802 	(ICE_FLOW_AVF_RSS_TCP_IPV4_MASKS | ICE_FLOW_AVF_RSS_UDP_IPV4_MASKS | \
1803 	 ICE_FLOW_AVF_RSS_IPV4_MASKS | BIT_ULL(ICE_AVF_FLOW_FIELD_IPV4_SCTP))
1804 
1805 #define ICE_FLOW_AVF_RSS_IPV6_MASKS \
1806 	(BIT_ULL(ICE_AVF_FLOW_FIELD_IPV6_OTHER) | \
1807 	 BIT_ULL(ICE_AVF_FLOW_FIELD_FRAG_IPV6))
1808 #define ICE_FLOW_AVF_RSS_UDP_IPV6_MASKS \
1809 	(BIT_ULL(ICE_AVF_FLOW_FIELD_UNICAST_IPV6_UDP) | \
1810 	 BIT_ULL(ICE_AVF_FLOW_FIELD_MULTICAST_IPV6_UDP) | \
1811 	 BIT_ULL(ICE_AVF_FLOW_FIELD_IPV6_UDP))
1812 #define ICE_FLOW_AVF_RSS_TCP_IPV6_MASKS \
1813 	(BIT_ULL(ICE_AVF_FLOW_FIELD_IPV6_TCP_SYN_NO_ACK) | \
1814 	 BIT_ULL(ICE_AVF_FLOW_FIELD_IPV6_TCP))
1815 #define ICE_FLOW_AVF_RSS_ALL_IPV6_MASKS \
1816 	(ICE_FLOW_AVF_RSS_TCP_IPV6_MASKS | ICE_FLOW_AVF_RSS_UDP_IPV6_MASKS | \
1817 	 ICE_FLOW_AVF_RSS_IPV6_MASKS | BIT_ULL(ICE_AVF_FLOW_FIELD_IPV6_SCTP))
1818 
1819 /**
1820  * ice_add_avf_rss_cfg - add an RSS configuration for AVF driver
1821  * @hw: pointer to the hardware structure
1822  * @vsi_handle: software VSI handle
1823  * @avf_hash: hash bit fields (ICE_AVF_FLOW_FIELD_*) to configure
1824  *
1825  * This function will take the hash bitmap provided by the AVF driver via a
1826  * message, convert it to ICE-compatible values, and configure RSS flow
1827  * profiles.
1828  */
1829 int ice_add_avf_rss_cfg(struct ice_hw *hw, u16 vsi_handle, u64 avf_hash)
1830 {
1831 	struct ice_rss_hash_cfg hcfg;
1832 	int status = 0;
1833 	u64 hash_flds;
1834 
1835 	if (avf_hash == ICE_AVF_FLOW_FIELD_INVALID ||
1836 	    !ice_is_vsi_valid(hw, vsi_handle))
1837 		return ICE_ERR_PARAM;
1838 
1839 	/* Make sure no unsupported bits are specified */
1840 	if (avf_hash & ~(ICE_FLOW_AVF_RSS_ALL_IPV4_MASKS |
1841 			 ICE_FLOW_AVF_RSS_ALL_IPV6_MASKS))
1842 		return ICE_ERR_CFG;
1843 
1844 	hash_flds = avf_hash;
1845 
1846 	/* Always create an L3 RSS configuration for any L4 RSS configuration */
1847 	if (hash_flds & ICE_FLOW_AVF_RSS_ALL_IPV4_MASKS)
1848 		hash_flds |= ICE_FLOW_AVF_RSS_IPV4_MASKS;
1849 
1850 	if (hash_flds & ICE_FLOW_AVF_RSS_ALL_IPV6_MASKS)
1851 		hash_flds |= ICE_FLOW_AVF_RSS_IPV6_MASKS;
1852 
1853 	/* Create the corresponding RSS configuration for each valid hash bit */
1854 	while (hash_flds) {
1855 		u64 rss_hash = ICE_HASH_INVALID;
1856 
1857 		if (hash_flds & ICE_FLOW_AVF_RSS_ALL_IPV4_MASKS) {
1858 			if (hash_flds & ICE_FLOW_AVF_RSS_IPV4_MASKS) {
1859 				rss_hash = ICE_FLOW_HASH_IPV4;
1860 				hash_flds &= ~ICE_FLOW_AVF_RSS_IPV4_MASKS;
1861 			} else if (hash_flds &
1862 				   ICE_FLOW_AVF_RSS_TCP_IPV4_MASKS) {
1863 				rss_hash = ICE_FLOW_HASH_IPV4 |
1864 					ICE_FLOW_HASH_TCP_PORT;
1865 				hash_flds &= ~ICE_FLOW_AVF_RSS_TCP_IPV4_MASKS;
1866 			} else if (hash_flds &
1867 				   ICE_FLOW_AVF_RSS_UDP_IPV4_MASKS) {
1868 				rss_hash = ICE_FLOW_HASH_IPV4 |
1869 					ICE_FLOW_HASH_UDP_PORT;
1870 				hash_flds &= ~ICE_FLOW_AVF_RSS_UDP_IPV4_MASKS;
1871 			} else if (hash_flds &
1872 				   BIT_ULL(ICE_AVF_FLOW_FIELD_IPV4_SCTP)) {
1873 				rss_hash = ICE_FLOW_HASH_IPV4 |
1874 					ICE_FLOW_HASH_SCTP_PORT;
1875 				hash_flds &=
1876 					~BIT_ULL(ICE_AVF_FLOW_FIELD_IPV4_SCTP);
1877 			}
1878 		} else if (hash_flds & ICE_FLOW_AVF_RSS_ALL_IPV6_MASKS) {
1879 			if (hash_flds & ICE_FLOW_AVF_RSS_IPV6_MASKS) {
1880 				rss_hash = ICE_FLOW_HASH_IPV6;
1881 				hash_flds &= ~ICE_FLOW_AVF_RSS_IPV6_MASKS;
1882 			} else if (hash_flds &
1883 				   ICE_FLOW_AVF_RSS_TCP_IPV6_MASKS) {
1884 				rss_hash = ICE_FLOW_HASH_IPV6 |
1885 					ICE_FLOW_HASH_TCP_PORT;
1886 				hash_flds &= ~ICE_FLOW_AVF_RSS_TCP_IPV6_MASKS;
1887 			} else if (hash_flds &
1888 				   ICE_FLOW_AVF_RSS_UDP_IPV6_MASKS) {
1889 				rss_hash = ICE_FLOW_HASH_IPV6 |
1890 					ICE_FLOW_HASH_UDP_PORT;
1891 				hash_flds &= ~ICE_FLOW_AVF_RSS_UDP_IPV6_MASKS;
1892 			} else if (hash_flds &
1893 				   BIT_ULL(ICE_AVF_FLOW_FIELD_IPV6_SCTP)) {
1894 				rss_hash = ICE_FLOW_HASH_IPV6 |
1895 					ICE_FLOW_HASH_SCTP_PORT;
1896 				hash_flds &=
1897 					~BIT_ULL(ICE_AVF_FLOW_FIELD_IPV6_SCTP);
1898 			}
1899 		}
1900 
1901 		if (rss_hash == ICE_HASH_INVALID)
1902 			return ICE_ERR_OUT_OF_RANGE;
1903 
1904 		hcfg.addl_hdrs = ICE_FLOW_SEG_HDR_NONE;
1905 		hcfg.hash_flds = rss_hash;
1906 		hcfg.symm = false;
1907 		hcfg.hdr_type = ICE_RSS_ANY_HEADERS;
1908 		status = ice_add_rss_cfg(hw, vsi_handle, &hcfg);
1909 		if (status)
1910 			break;
1911 	}
1912 
1913 	return status;
1914 }
1915 
1916 /**
1917  * ice_replay_rss_cfg - replay RSS configurations associated with VSI
1918  * @hw: pointer to the hardware structure
1919  * @vsi_handle: software VSI handle
1920  */
1921 int ice_replay_rss_cfg(struct ice_hw *hw, u16 vsi_handle)
1922 {
1923 	struct ice_rss_cfg *r;
1924 	int status = 0;
1925 
1926 	if (!ice_is_vsi_valid(hw, vsi_handle))
1927 		return ICE_ERR_PARAM;
1928 
1929 	ice_acquire_lock(&hw->rss_locks);
1930 	LIST_FOR_EACH_ENTRY(r, &hw->rss_list_head,
1931 			    ice_rss_cfg, l_entry) {
1932 		if (ice_is_bit_set(r->vsis, vsi_handle)) {
1933 			status = ice_add_rss_cfg_sync(hw, vsi_handle, &r->hash);
1934 			if (status)
1935 				break;
1936 		}
1937 	}
1938 	ice_release_lock(&hw->rss_locks);
1939 
1940 	return status;
1941 }
1942 
1943 /**
1944  * ice_get_rss_cfg - returns hashed fields for the given header types
1945  * @hw: pointer to the hardware structure
1946  * @vsi_handle: software VSI handle
1947  * @hdrs: protocol header type
1948  *
1949  * This function will return the match fields of the first instance of flow
1950  * profile having the given header types and containing input VSI
1951  */
1952 u64 ice_get_rss_cfg(struct ice_hw *hw, u16 vsi_handle, u32 hdrs)
1953 {
1954 	u64 rss_hash = ICE_HASH_INVALID;
1955 	struct ice_rss_cfg *r;
1956 
1957 	/* verify if the protocol header is non zero and VSI is valid */
1958 	if (hdrs == ICE_FLOW_SEG_HDR_NONE || !ice_is_vsi_valid(hw, vsi_handle))
1959 		return ICE_HASH_INVALID;
1960 
1961 	ice_acquire_lock(&hw->rss_locks);
1962 	LIST_FOR_EACH_ENTRY(r, &hw->rss_list_head,
1963 			    ice_rss_cfg, l_entry)
1964 		if (ice_is_bit_set(r->vsis, vsi_handle) &&
1965 		    r->hash.addl_hdrs == hdrs) {
1966 			rss_hash = r->hash.hash_flds;
1967 			break;
1968 		}
1969 	ice_release_lock(&hw->rss_locks);
1970 
1971 	return rss_hash;
1972 }
1973