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