xref: /freebsd/sys/dev/ice/ice_flow.c (revision 6ba2210ee039f2f12878c217bcf058e9c8b26b29)
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 IPv4 header, does NOT
163  * include IPV4 other PTYPEs
164  */
165 static const u32 ice_ptypes_ipv4_ofos[] = {
166 	0x1DC00000, 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 IPv4 header, includes
177  * IPV4 other PTYPEs
178  */
179 static const u32 ice_ptypes_ipv4_ofos_all[] = {
180 	0x1DC00000, 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 IPv6 header, does NOT
203  * include IVP6 other PTYPEs
204  */
205 static const u32 ice_ptypes_ipv6_ofos[] = {
206 	0x00000000, 0x00000000, 0x77000000, 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 IPv6 header, includes
217  * IPV6 other PTYPEs
218  */
219 static const u32 ice_ptypes_ipv6_ofos_all[] = {
220 	0x00000000, 0x00000000, 0x77000000, 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 IPv4 header - no L4 */
243 static const u32 ice_ptypes_ipv4_ofos_no_l4[] = {
244 	0x10C00000, 0x04000800, 0x00000000, 0x00000000,
245 	0x00000000, 0x00000000, 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 };
253 
254 /* Packet types for packets with an Innermost/Last IPv4 header - no L4 */
255 static const u32 ice_ptypes_ipv4_il_no_l4[] = {
256 	0x60000000, 0x18043008, 0x80000002, 0x6010c021,
257 	0x00000008, 0x00000000, 0x00000000, 0x00000000,
258 	0x00000000, 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 };
265 
266 /* Packet types for packets with an Outer/First/Single IPv6 header - no L4 */
267 static const u32 ice_ptypes_ipv6_ofos_no_l4[] = {
268 	0x00000000, 0x00000000, 0x43000000, 0x10002000,
269 	0x00000000, 0x00000000, 0x00000000, 0x00000000,
270 	0x00000000, 0x00000000, 0x00000000, 0x00000000,
271 	0x00000000, 0x00000000, 0x00000000, 0x00000000,
272 	0x00000000, 0x00000000, 0x00000000, 0x00000000,
273 	0x00000000, 0x00000000, 0x00000000, 0x00000000,
274 	0x00000000, 0x00000000, 0x00000000, 0x00000000,
275 	0x00000000, 0x00000000, 0x00000000, 0x00000000,
276 };
277 
278 /* Packet types for packets with an Innermost/Last IPv6 header - no L4 */
279 static const u32 ice_ptypes_ipv6_il_no_l4[] = {
280 	0x00000000, 0x02180430, 0x0000010c, 0x086010c0,
281 	0x00000430, 0x00000000, 0x00000000, 0x00000000,
282 	0x00000000, 0x00000000, 0x00000000, 0x00000000,
283 	0x00000000, 0x00000000, 0x00000000, 0x00000000,
284 	0x00000000, 0x00000000, 0x00000000, 0x00000000,
285 	0x00000000, 0x00000000, 0x00000000, 0x00000000,
286 	0x00000000, 0x00000000, 0x00000000, 0x00000000,
287 	0x00000000, 0x00000000, 0x00000000, 0x00000000,
288 };
289 
290 /* Packet types for packets with an Outermost/First ARP header */
291 static const u32 ice_ptypes_arp_of[] = {
292 	0x00000800, 0x00000000, 0x00000000, 0x00000000,
293 	0x00000000, 0x00000000, 0x00000000, 0x00000000,
294 	0x00000000, 0x00000000, 0x00000000, 0x00000000,
295 	0x00000000, 0x00000000, 0x00000000, 0x00000000,
296 	0x00000000, 0x00000000, 0x00000000, 0x00000000,
297 	0x00000000, 0x00000000, 0x00000000, 0x00000000,
298 	0x00000000, 0x00000000, 0x00000000, 0x00000000,
299 	0x00000000, 0x00000000, 0x00000000, 0x00000000,
300 };
301 
302 /* UDP Packet types for non-tunneled packets or tunneled
303  * packets with inner UDP.
304  */
305 static const u32 ice_ptypes_udp_il[] = {
306 	0x81000000, 0x20204040, 0x04000010, 0x80810102,
307 	0x00000040, 0x00000000, 0x00000000, 0x00000000,
308 	0x00000000, 0x00000000, 0x00000000, 0x00000000,
309 	0x00000000, 0x00000000, 0x00000000, 0x00000000,
310 	0x00000000, 0x00000000, 0x00000000, 0x00000000,
311 	0x00000000, 0x00000000, 0x00000000, 0x00000000,
312 	0x00000000, 0x00000000, 0x00000000, 0x00000000,
313 	0x00000000, 0x00000000, 0x00000000, 0x00000000,
314 };
315 
316 /* Packet types for packets with an Innermost/Last TCP header */
317 static const u32 ice_ptypes_tcp_il[] = {
318 	0x04000000, 0x80810102, 0x10000040, 0x02040408,
319 	0x00000102, 0x00000000, 0x00000000, 0x00000000,
320 	0x00000000, 0x00000000, 0x00000000, 0x00000000,
321 	0x00000000, 0x00000000, 0x00000000, 0x00000000,
322 	0x00000000, 0x00000000, 0x00000000, 0x00000000,
323 	0x00000000, 0x00000000, 0x00000000, 0x00000000,
324 	0x00000000, 0x00000000, 0x00000000, 0x00000000,
325 	0x00000000, 0x00000000, 0x00000000, 0x00000000,
326 };
327 
328 /* Packet types for packets with an Innermost/Last SCTP header */
329 static const u32 ice_ptypes_sctp_il[] = {
330 	0x08000000, 0x01020204, 0x20000081, 0x04080810,
331 	0x00000204, 0x00000000, 0x00000000, 0x00000000,
332 	0x00000000, 0x00000000, 0x00000000, 0x00000000,
333 	0x00000000, 0x00000000, 0x00000000, 0x00000000,
334 	0x00000000, 0x00000000, 0x00000000, 0x00000000,
335 	0x00000000, 0x00000000, 0x00000000, 0x00000000,
336 	0x00000000, 0x00000000, 0x00000000, 0x00000000,
337 	0x00000000, 0x00000000, 0x00000000, 0x00000000,
338 };
339 
340 /* Packet types for packets with an Outermost/First ICMP header */
341 static const u32 ice_ptypes_icmp_of[] = {
342 	0x10000000, 0x00000000, 0x00000000, 0x00000000,
343 	0x00000000, 0x00000000, 0x00000000, 0x00000000,
344 	0x00000000, 0x00000000, 0x00000000, 0x00000000,
345 	0x00000000, 0x00000000, 0x00000000, 0x00000000,
346 	0x00000000, 0x00000000, 0x00000000, 0x00000000,
347 	0x00000000, 0x00000000, 0x00000000, 0x00000000,
348 	0x00000000, 0x00000000, 0x00000000, 0x00000000,
349 	0x00000000, 0x00000000, 0x00000000, 0x00000000,
350 };
351 
352 /* Packet types for packets with an Innermost/Last ICMP header */
353 static const u32 ice_ptypes_icmp_il[] = {
354 	0x00000000, 0x02040408, 0x40000102, 0x08101020,
355 	0x00000408, 0x00000000, 0x00000000, 0x00000000,
356 	0x00000000, 0x00000000, 0x00000000, 0x00000000,
357 	0x00000000, 0x00000000, 0x00000000, 0x00000000,
358 	0x00000000, 0x00000000, 0x00000000, 0x00000000,
359 	0x00000000, 0x00000000, 0x00000000, 0x00000000,
360 	0x00000000, 0x00000000, 0x00000000, 0x00000000,
361 	0x00000000, 0x00000000, 0x00000000, 0x00000000,
362 };
363 
364 /* Packet types for packets with an Outermost/First GRE header */
365 static const u32 ice_ptypes_gre_of[] = {
366 	0x00000000, 0xBFBF7800, 0x000001DF, 0xFEFDE000,
367 	0x0000017E, 0x00000000, 0x00000000, 0x00000000,
368 	0x00000000, 0x00000000, 0x00000000, 0x00000000,
369 	0x00000000, 0x00000000, 0x00000000, 0x00000000,
370 	0x00000000, 0x00000000, 0x00000000, 0x00000000,
371 	0x00000000, 0x00000000, 0x00000000, 0x00000000,
372 	0x00000000, 0x00000000, 0x00000000, 0x00000000,
373 	0x00000000, 0x00000000, 0x00000000, 0x00000000,
374 };
375 
376 /* Packet types for packets with an Innermost/Last MAC header */
377 static const u32 ice_ptypes_mac_il[] = {
378 	0x00000000, 0x00000000, 0x00000000, 0x00000000,
379 	0x00000000, 0x00000000, 0x00000000, 0x00000000,
380 	0x00000000, 0x00000000, 0x00000000, 0x00000000,
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 };
387 
388 /* Manage parameters and info. used during the creation of a flow profile */
389 struct ice_flow_prof_params {
390 	enum ice_block blk;
391 	u16 entry_length; /* # of bytes formatted entry will require */
392 	u8 es_cnt;
393 	struct ice_flow_prof *prof;
394 
395 	/* For ACL, the es[0] will have the data of ICE_RX_MDID_PKT_FLAGS_15_0
396 	 * This will give us the direction flags.
397 	 */
398 	struct ice_fv_word es[ICE_MAX_FV_WORDS];
399 	ice_declare_bitmap(ptypes, ICE_FLOW_PTYPE_MAX);
400 };
401 
402 #define ICE_FLOW_SEG_HDRS_L3_MASK	\
403 	(ICE_FLOW_SEG_HDR_IPV4 | ICE_FLOW_SEG_HDR_IPV6 | \
404 	 ICE_FLOW_SEG_HDR_ARP)
405 #define ICE_FLOW_SEG_HDRS_L4_MASK	\
406 	(ICE_FLOW_SEG_HDR_ICMP | ICE_FLOW_SEG_HDR_TCP | ICE_FLOW_SEG_HDR_UDP | \
407 	 ICE_FLOW_SEG_HDR_SCTP)
408 /* mask for L4 protocols that are NOT part of IPV4/6 OTHER PTYPE groups */
409 #define ICE_FLOW_SEG_HDRS_L4_MASK_NO_OTHER	\
410 	(ICE_FLOW_SEG_HDR_TCP | ICE_FLOW_SEG_HDR_UDP | ICE_FLOW_SEG_HDR_SCTP)
411 
412 /**
413  * ice_flow_val_hdrs - validates packet segments for valid protocol headers
414  * @segs: array of one or more packet segments that describe the flow
415  * @segs_cnt: number of packet segments provided
416  */
417 static enum ice_status
418 ice_flow_val_hdrs(struct ice_flow_seg_info *segs, u8 segs_cnt)
419 {
420 	u8 i;
421 
422 	for (i = 0; i < segs_cnt; i++) {
423 		/* Multiple L3 headers */
424 		if (segs[i].hdrs & ICE_FLOW_SEG_HDRS_L3_MASK &&
425 		    !ice_is_pow2(segs[i].hdrs & ICE_FLOW_SEG_HDRS_L3_MASK))
426 			return ICE_ERR_PARAM;
427 
428 		/* Multiple L4 headers */
429 		if (segs[i].hdrs & ICE_FLOW_SEG_HDRS_L4_MASK &&
430 		    !ice_is_pow2(segs[i].hdrs & ICE_FLOW_SEG_HDRS_L4_MASK))
431 			return ICE_ERR_PARAM;
432 	}
433 
434 	return ICE_SUCCESS;
435 }
436 
437 /**
438  * ice_flow_proc_seg_hdrs - process protocol headers present in pkt segments
439  * @params: information about the flow to be processed
440  *
441  * This function identifies the packet types associated with the protocol
442  * headers being present in packet segments of the specified flow profile.
443  */
444 static enum ice_status
445 ice_flow_proc_seg_hdrs(struct ice_flow_prof_params *params)
446 {
447 	struct ice_flow_prof *prof;
448 	u8 i;
449 
450 	ice_memset(params->ptypes, 0xff, sizeof(params->ptypes),
451 		   ICE_NONDMA_MEM);
452 
453 	prof = params->prof;
454 
455 	for (i = 0; i < params->prof->segs_cnt; i++) {
456 		const ice_bitmap_t *src;
457 		u32 hdrs;
458 
459 		hdrs = prof->segs[i].hdrs;
460 
461 		if (hdrs & ICE_FLOW_SEG_HDR_ETH) {
462 			src = !i ? (const ice_bitmap_t *)ice_ptypes_mac_ofos :
463 				(const ice_bitmap_t *)ice_ptypes_mac_il;
464 			ice_and_bitmap(params->ptypes, params->ptypes, src,
465 				       ICE_FLOW_PTYPE_MAX);
466 		}
467 
468 		if (i && hdrs & ICE_FLOW_SEG_HDR_VLAN) {
469 			src = (const ice_bitmap_t *)ice_ptypes_macvlan_il;
470 			ice_and_bitmap(params->ptypes, params->ptypes, src,
471 				       ICE_FLOW_PTYPE_MAX);
472 		}
473 
474 		if (!i && hdrs & ICE_FLOW_SEG_HDR_ARP) {
475 			ice_and_bitmap(params->ptypes, params->ptypes,
476 				       (const ice_bitmap_t *)ice_ptypes_arp_of,
477 				       ICE_FLOW_PTYPE_MAX);
478 		}
479 
480 		if ((hdrs & ICE_FLOW_SEG_HDR_IPV4) &&
481 		    (hdrs & ICE_FLOW_SEG_HDR_IPV_OTHER)) {
482 			src = i ?
483 				(const ice_bitmap_t *)ice_ptypes_ipv4_il :
484 				(const ice_bitmap_t *)ice_ptypes_ipv4_ofos_all;
485 			ice_and_bitmap(params->ptypes, params->ptypes, src,
486 				       ICE_FLOW_PTYPE_MAX);
487 		} else if ((hdrs & ICE_FLOW_SEG_HDR_IPV6) &&
488 			   (hdrs & ICE_FLOW_SEG_HDR_IPV_OTHER)) {
489 			src = i ?
490 				(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 ICE_SUCCESS;
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 enum ice_status
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 	enum ice_prot_id prot_id = ICE_PROT_ID_INVAL;
566 	u8 fv_words = hw->blk[params->blk].es.fvw;
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 
593 		/* TTL and PROT share the same extraction seq. entry.
594 		 * Each is considered a sibling to the other in terms of sharing
595 		 * the same extraction sequence entry.
596 		 */
597 		if (fld == ICE_FLOW_FIELD_IDX_IPV4_TTL)
598 			sib = ICE_FLOW_FIELD_IDX_IPV4_PROT;
599 		else
600 			sib = ICE_FLOW_FIELD_IDX_IPV4_TTL;
601 		break;
602 	case ICE_FLOW_FIELD_IDX_IPV6_TTL:
603 	case ICE_FLOW_FIELD_IDX_IPV6_PROT:
604 		prot_id = seg == 0 ? ICE_PROT_IPV6_OF_OR_S : ICE_PROT_IPV6_IL;
605 
606 		/* TTL and PROT share the same extraction seq. entry.
607 		 * Each is considered a sibling to the other in terms of sharing
608 		 * the same extraction sequence entry.
609 		 */
610 		if (fld == ICE_FLOW_FIELD_IDX_IPV6_TTL)
611 			sib = ICE_FLOW_FIELD_IDX_IPV6_PROT;
612 		else
613 			sib = ICE_FLOW_FIELD_IDX_IPV6_TTL;
614 		break;
615 	case ICE_FLOW_FIELD_IDX_IPV4_SA:
616 	case ICE_FLOW_FIELD_IDX_IPV4_DA:
617 		prot_id = seg == 0 ? ICE_PROT_IPV4_OF_OR_S : ICE_PROT_IPV4_IL;
618 		break;
619 	case ICE_FLOW_FIELD_IDX_IPV6_SA:
620 	case ICE_FLOW_FIELD_IDX_IPV6_DA:
621 		prot_id = seg == 0 ? ICE_PROT_IPV6_OF_OR_S : ICE_PROT_IPV6_IL;
622 		break;
623 	case ICE_FLOW_FIELD_IDX_TCP_SRC_PORT:
624 	case ICE_FLOW_FIELD_IDX_TCP_DST_PORT:
625 	case ICE_FLOW_FIELD_IDX_TCP_FLAGS:
626 		prot_id = ICE_PROT_TCP_IL;
627 		break;
628 	case ICE_FLOW_FIELD_IDX_UDP_SRC_PORT:
629 	case ICE_FLOW_FIELD_IDX_UDP_DST_PORT:
630 		prot_id = ICE_PROT_UDP_IL_OR_S;
631 		break;
632 	case ICE_FLOW_FIELD_IDX_SCTP_SRC_PORT:
633 	case ICE_FLOW_FIELD_IDX_SCTP_DST_PORT:
634 		prot_id = ICE_PROT_SCTP_IL;
635 		break;
636 	case ICE_FLOW_FIELD_IDX_ARP_SIP:
637 	case ICE_FLOW_FIELD_IDX_ARP_DIP:
638 	case ICE_FLOW_FIELD_IDX_ARP_SHA:
639 	case ICE_FLOW_FIELD_IDX_ARP_DHA:
640 	case ICE_FLOW_FIELD_IDX_ARP_OP:
641 		prot_id = ICE_PROT_ARP_OF;
642 		break;
643 	case ICE_FLOW_FIELD_IDX_ICMP_TYPE:
644 	case ICE_FLOW_FIELD_IDX_ICMP_CODE:
645 		/* ICMP type and code share the same extraction seq. entry */
646 		prot_id = (params->prof->segs[seg].hdrs &
647 			   ICE_FLOW_SEG_HDR_IPV4) ?
648 			ICE_PROT_ICMP_IL : ICE_PROT_ICMPV6_IL;
649 		sib = fld == ICE_FLOW_FIELD_IDX_ICMP_TYPE ?
650 			ICE_FLOW_FIELD_IDX_ICMP_CODE :
651 			ICE_FLOW_FIELD_IDX_ICMP_TYPE;
652 		break;
653 	case ICE_FLOW_FIELD_IDX_GRE_KEYID:
654 		prot_id = ICE_PROT_GRE_OF;
655 		break;
656 	default:
657 		return ICE_ERR_NOT_IMPL;
658 	}
659 
660 	/* Each extraction sequence entry is a word in size, and extracts a
661 	 * word-aligned offset from a protocol header.
662 	 */
663 	ese_bits = ICE_FLOW_FV_EXTRACT_SZ * BITS_PER_BYTE;
664 
665 	flds[fld].xtrct.prot_id = prot_id;
666 	flds[fld].xtrct.off = (ice_flds_info[fld].off / ese_bits) *
667 		ICE_FLOW_FV_EXTRACT_SZ;
668 	flds[fld].xtrct.disp = (u8)(ice_flds_info[fld].off % ese_bits);
669 	flds[fld].xtrct.idx = params->es_cnt;
670 
671 	/* Adjust the next field-entry index after accommodating the number of
672 	 * entries this field consumes
673 	 */
674 	cnt = DIVIDE_AND_ROUND_UP(flds[fld].xtrct.disp +
675 				  ice_flds_info[fld].size, ese_bits);
676 
677 	/* Fill in the extraction sequence entries needed for this field */
678 	off = flds[fld].xtrct.off;
679 	for (i = 0; i < cnt; i++) {
680 		/* Only consume an extraction sequence entry if there is no
681 		 * sibling field associated with this field or the sibling entry
682 		 * already extracts the word shared with this field.
683 		 */
684 		if (sib == ICE_FLOW_FIELD_IDX_MAX ||
685 		    flds[sib].xtrct.prot_id == ICE_PROT_ID_INVAL ||
686 		    flds[sib].xtrct.off != off) {
687 			u8 idx;
688 
689 			/* Make sure the number of extraction sequence required
690 			 * does not exceed the block's capability
691 			 */
692 			if (params->es_cnt >= fv_words)
693 				return ICE_ERR_MAX_LIMIT;
694 
695 			/* some blocks require a reversed field vector layout */
696 			if (hw->blk[params->blk].es.reverse)
697 				idx = fv_words - params->es_cnt - 1;
698 			else
699 				idx = params->es_cnt;
700 
701 			params->es[idx].prot_id = prot_id;
702 			params->es[idx].off = off;
703 			params->es_cnt++;
704 		}
705 
706 		off += ICE_FLOW_FV_EXTRACT_SZ;
707 	}
708 
709 	return ICE_SUCCESS;
710 }
711 
712 /**
713  * ice_flow_create_xtrct_seq - Create an extraction sequence for given segments
714  * @hw: pointer to the HW struct
715  * @params: information about the flow to be processed
716  *
717  * This function iterates through all matched fields in the given segments, and
718  * creates an extraction sequence for the fields.
719  */
720 static enum ice_status
721 ice_flow_create_xtrct_seq(struct ice_hw *hw,
722 			  struct ice_flow_prof_params *params)
723 {
724 	enum ice_status status = ICE_SUCCESS;
725 	u8 i;
726 
727 	for (i = 0; i < params->prof->segs_cnt; i++) {
728 		u64 match = params->prof->segs[i].match;
729 		enum ice_flow_field j;
730 
731 		ice_for_each_set_bit(j, (ice_bitmap_t *)&match,
732 				     ICE_FLOW_FIELD_IDX_MAX) {
733 			status = ice_flow_xtract_fld(hw, params, i, j);
734 			if (status)
735 				return status;
736 			ice_clear_bit(j, (ice_bitmap_t *)&match);
737 		}
738 	}
739 
740 	return status;
741 }
742 
743 /**
744  * ice_flow_proc_segs - process all packet segments associated with a profile
745  * @hw: pointer to the HW struct
746  * @params: information about the flow to be processed
747  */
748 static enum ice_status
749 ice_flow_proc_segs(struct ice_hw *hw, struct ice_flow_prof_params *params)
750 {
751 	enum ice_status status;
752 
753 	status = ice_flow_proc_seg_hdrs(params);
754 	if (status)
755 		return status;
756 
757 	status = ice_flow_create_xtrct_seq(hw, params);
758 	if (status)
759 		return status;
760 
761 	switch (params->blk) {
762 	case ICE_BLK_RSS:
763 		status = ICE_SUCCESS;
764 		break;
765 	default:
766 		return ICE_ERR_NOT_IMPL;
767 	}
768 
769 	return status;
770 }
771 
772 #define ICE_FLOW_FIND_PROF_CHK_FLDS	0x00000001
773 #define ICE_FLOW_FIND_PROF_CHK_VSI	0x00000002
774 #define ICE_FLOW_FIND_PROF_NOT_CHK_DIR	0x00000004
775 
776 /**
777  * ice_flow_find_prof_conds - Find a profile matching headers and conditions
778  * @hw: pointer to the HW struct
779  * @blk: classification stage
780  * @dir: flow direction
781  * @segs: array of one or more packet segments that describe the flow
782  * @segs_cnt: number of packet segments provided
783  * @vsi_handle: software VSI handle to check VSI (ICE_FLOW_FIND_PROF_CHK_VSI)
784  * @conds: additional conditions to be checked (ICE_FLOW_FIND_PROF_CHK_*)
785  */
786 static struct ice_flow_prof *
787 ice_flow_find_prof_conds(struct ice_hw *hw, enum ice_block blk,
788 			 enum ice_flow_dir dir, struct ice_flow_seg_info *segs,
789 			 u8 segs_cnt, u16 vsi_handle, u32 conds)
790 {
791 	struct ice_flow_prof *p, *prof = NULL;
792 
793 	ice_acquire_lock(&hw->fl_profs_locks[blk]);
794 	LIST_FOR_EACH_ENTRY(p, &hw->fl_profs[blk], ice_flow_prof, l_entry)
795 		if ((p->dir == dir || conds & ICE_FLOW_FIND_PROF_NOT_CHK_DIR) &&
796 		    segs_cnt && segs_cnt == p->segs_cnt) {
797 			u8 i;
798 
799 			/* Check for profile-VSI association if specified */
800 			if ((conds & ICE_FLOW_FIND_PROF_CHK_VSI) &&
801 			    ice_is_vsi_valid(hw, vsi_handle) &&
802 			    !ice_is_bit_set(p->vsis, vsi_handle))
803 				continue;
804 
805 			/* Protocol headers must be checked. Matched fields are
806 			 * checked if specified.
807 			 */
808 			for (i = 0; i < segs_cnt; i++)
809 				if (segs[i].hdrs != p->segs[i].hdrs ||
810 				    ((conds & ICE_FLOW_FIND_PROF_CHK_FLDS) &&
811 				     segs[i].match != p->segs[i].match))
812 					break;
813 
814 			/* A match is found if all segments are matched */
815 			if (i == segs_cnt) {
816 				prof = p;
817 				break;
818 			}
819 		}
820 	ice_release_lock(&hw->fl_profs_locks[blk]);
821 
822 	return prof;
823 }
824 
825 /**
826  * ice_flow_find_prof - Look up a profile matching headers and matched fields
827  * @hw: pointer to the HW struct
828  * @blk: classification stage
829  * @dir: flow direction
830  * @segs: array of one or more packet segments that describe the flow
831  * @segs_cnt: number of packet segments provided
832  */
833 u64
834 ice_flow_find_prof(struct ice_hw *hw, enum ice_block blk, enum ice_flow_dir dir,
835 		   struct ice_flow_seg_info *segs, u8 segs_cnt)
836 {
837 	struct ice_flow_prof *p;
838 
839 	p = ice_flow_find_prof_conds(hw, blk, dir, segs, segs_cnt,
840 				     ICE_MAX_VSI, ICE_FLOW_FIND_PROF_CHK_FLDS);
841 
842 	return p ? p->id : ICE_FLOW_PROF_ID_INVAL;
843 }
844 
845 /**
846  * ice_flow_find_prof_id - Look up a profile with given profile ID
847  * @hw: pointer to the HW struct
848  * @blk: classification stage
849  * @prof_id: unique ID to identify this flow profile
850  */
851 static struct ice_flow_prof *
852 ice_flow_find_prof_id(struct ice_hw *hw, enum ice_block blk, u64 prof_id)
853 {
854 	struct ice_flow_prof *p;
855 
856 	LIST_FOR_EACH_ENTRY(p, &hw->fl_profs[blk], ice_flow_prof, l_entry)
857 		if (p->id == prof_id)
858 			return p;
859 
860 	return NULL;
861 }
862 
863 /**
864  * ice_flow_get_hw_prof - return the HW profile for a specific profile ID handle
865  * @hw: pointer to the HW struct
866  * @blk: classification stage
867  * @prof_id: the profile ID handle
868  * @hw_prof_id: pointer to variable to receive the HW profile ID
869  */
870 enum ice_status
871 ice_flow_get_hw_prof(struct ice_hw *hw, enum ice_block blk, u64 prof_id,
872 		     u8 *hw_prof_id)
873 {
874 	enum ice_status status = ICE_ERR_DOES_NOT_EXIST;
875 	struct ice_prof_map *map;
876 
877 	ice_acquire_lock(&hw->blk[blk].es.prof_map_lock);
878 	map = ice_search_prof_id(hw, blk, prof_id);
879 	if (map) {
880 		*hw_prof_id = map->prof_id;
881 		status = ICE_SUCCESS;
882 	}
883 	ice_release_lock(&hw->blk[blk].es.prof_map_lock);
884 	return status;
885 }
886 
887 /**
888  * ice_flow_add_prof_sync - Add a flow profile for packet segments and fields
889  * @hw: pointer to the HW struct
890  * @blk: classification stage
891  * @dir: flow direction
892  * @prof_id: unique ID to identify this flow profile
893  * @segs: array of one or more packet segments that describe the flow
894  * @segs_cnt: number of packet segments provided
895  * @acts: array of default actions
896  * @acts_cnt: number of default actions
897  * @prof: stores the returned flow profile added
898  *
899  * Assumption: the caller has acquired the lock to the profile list
900  */
901 static enum ice_status
902 ice_flow_add_prof_sync(struct ice_hw *hw, enum ice_block blk,
903 		       enum ice_flow_dir dir, u64 prof_id,
904 		       struct ice_flow_seg_info *segs, u8 segs_cnt,
905 		       struct ice_flow_action *acts, u8 acts_cnt,
906 		       struct ice_flow_prof **prof)
907 {
908 	struct ice_flow_prof_params *params;
909 	enum ice_status status;
910 	u8 i;
911 
912 	if (!prof || (acts_cnt && !acts))
913 		return ICE_ERR_BAD_PTR;
914 
915 	params = (struct ice_flow_prof_params *)ice_malloc(hw, sizeof(*params));
916 	if (!params)
917 		return ICE_ERR_NO_MEMORY;
918 
919 	params->prof = (struct ice_flow_prof *)
920 		ice_malloc(hw, sizeof(*params->prof));
921 	if (!params->prof) {
922 		status = ICE_ERR_NO_MEMORY;
923 		goto free_params;
924 	}
925 
926 	/* initialize extraction sequence to all invalid (0xff) */
927 	for (i = 0; i < ICE_MAX_FV_WORDS; i++) {
928 		params->es[i].prot_id = ICE_PROT_INVALID;
929 		params->es[i].off = ICE_FV_OFFSET_INVAL;
930 	}
931 
932 	params->blk = blk;
933 	params->prof->id = prof_id;
934 	params->prof->dir = dir;
935 	params->prof->segs_cnt = segs_cnt;
936 
937 	/* Make a copy of the segments that need to be persistent in the flow
938 	 * profile instance
939 	 */
940 	for (i = 0; i < segs_cnt; i++)
941 		ice_memcpy(&params->prof->segs[i], &segs[i], sizeof(*segs),
942 			   ICE_NONDMA_TO_NONDMA);
943 
944 	status = ice_flow_proc_segs(hw, params);
945 	if (status) {
946 		ice_debug(hw, ICE_DBG_FLOW, "Error processing a flow's packet segments\n");
947 		goto out;
948 	}
949 
950 	/* Add a HW profile for this flow profile */
951 	status = ice_add_prof(hw, blk, prof_id, (u8 *)params->ptypes,
952 			      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 enum ice_status
979 ice_flow_rem_prof_sync(struct ice_hw *hw, enum ice_block blk,
980 		       struct ice_flow_prof *prof)
981 {
982 	enum ice_status 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 enum ice_status
1006 ice_flow_assoc_vsig_vsi(struct ice_hw *hw, enum ice_block blk, u16 vsi_handle,
1007 			u16 vsig)
1008 {
1009 	enum ice_status 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 enum ice_status
1033 ice_flow_assoc_prof(struct ice_hw *hw, enum ice_block blk,
1034 		    struct ice_flow_prof *prof, u16 vsi_handle)
1035 {
1036 	enum ice_status status = ICE_SUCCESS;
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 enum ice_status
1064 ice_flow_disassoc_prof(struct ice_hw *hw, enum ice_block blk,
1065 		       struct ice_flow_prof *prof, u16 vsi_handle)
1066 {
1067 	enum ice_status status = ICE_SUCCESS;
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 enum ice_status
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 	enum ice_status 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 enum ice_status
1136 ice_flow_rem_prof(struct ice_hw *hw, enum ice_block blk, u64 prof_id)
1137 {
1138 	struct ice_flow_prof *prof;
1139 	enum ice_status 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 	u64 bit = BIT_ULL(fld);
1187 
1188 	seg->match |= bit;
1189 	if (field_type == ICE_FLOW_FLD_TYPE_RANGE)
1190 		seg->range |= bit;
1191 
1192 	seg->fields[fld].type = field_type;
1193 	seg->fields[fld].src.val = val_loc;
1194 	seg->fields[fld].src.mask = mask_loc;
1195 	seg->fields[fld].src.last = last_loc;
1196 
1197 	ICE_FLOW_SET_HDRS(seg, ice_flds_info[fld].hdr);
1198 }
1199 
1200 /**
1201  * ice_flow_set_fld - specifies locations of field from entry's input buffer
1202  * @seg: packet segment the field being set belongs to
1203  * @fld: field to be set
1204  * @val_loc: if not ICE_FLOW_FLD_OFF_INVAL, location of the value to match from
1205  *           entry's input buffer
1206  * @mask_loc: if not ICE_FLOW_FLD_OFF_INVAL, location of mask value from entry's
1207  *            input buffer
1208  * @last_loc: if not ICE_FLOW_FLD_OFF_INVAL, location of last/upper value from
1209  *            entry's input buffer
1210  * @range: indicate if field being matched is to be in a range
1211  *
1212  * This function specifies the locations, in the form of byte offsets from the
1213  * start of the input buffer for a flow entry, from where the value to match,
1214  * the mask value, and upper value can be extracted. These locations are then
1215  * stored in the flow profile. When adding a flow entry associated with the
1216  * flow profile, these locations will be used to quickly extract the values and
1217  * create the content of a match entry. This function should only be used for
1218  * fixed-size data structures.
1219  */
1220 static void
1221 ice_flow_set_fld(struct ice_flow_seg_info *seg, enum ice_flow_field fld,
1222 		 u16 val_loc, u16 mask_loc, u16 last_loc, bool range)
1223 {
1224 	enum ice_flow_fld_match_type t = range ?
1225 		ICE_FLOW_FLD_TYPE_RANGE : ICE_FLOW_FLD_TYPE_REG;
1226 
1227 	ice_flow_set_fld_ext(seg, fld, t, val_loc, mask_loc, last_loc);
1228 }
1229 
1230 /**
1231  * ice_flow_set_fld_prefix - sets locations of prefix field from entry's buf
1232  * @seg: packet segment the field being set belongs to
1233  * @fld: field to be set
1234  * @val_loc: if not ICE_FLOW_FLD_OFF_INVAL, location of the value to match from
1235  *           entry's input buffer
1236  * @pref_loc: location of prefix value from entry's input buffer
1237  * @pref_sz: size of the location holding the prefix value
1238  *
1239  * This function specifies the locations, in the form of byte offsets from the
1240  * start of the input buffer for a flow entry, from where the value to match
1241  * and the IPv4 prefix value can be extracted. These locations are then stored
1242  * in the flow profile. When adding flow entries to the associated flow profile,
1243  * these locations can be used to quickly extract the values to create the
1244  * content of a match entry. This function should only be used for fixed-size
1245  * data structures.
1246  */
1247 void
1248 ice_flow_set_fld_prefix(struct ice_flow_seg_info *seg, enum ice_flow_field fld,
1249 			u16 val_loc, u16 pref_loc, u8 pref_sz)
1250 {
1251 	/* For this type of field, the "mask" location is for the prefix value's
1252 	 * location and the "last" location is for the size of the location of
1253 	 * the prefix value.
1254 	 */
1255 	ice_flow_set_fld_ext(seg, fld, ICE_FLOW_FLD_TYPE_PREFIX, val_loc,
1256 			     pref_loc, (u16)pref_sz);
1257 }
1258 
1259 #define ICE_FLOW_RSS_SEG_HDR_L3_MASKS \
1260 	(ICE_FLOW_SEG_HDR_IPV4 | ICE_FLOW_SEG_HDR_IPV6)
1261 
1262 #define ICE_FLOW_RSS_SEG_HDR_L4_MASKS \
1263 	(ICE_FLOW_SEG_HDR_TCP | ICE_FLOW_SEG_HDR_UDP | ICE_FLOW_SEG_HDR_SCTP)
1264 
1265 #define ICE_FLOW_RSS_SEG_HDR_VAL_MASKS \
1266 	(ICE_FLOW_RSS_SEG_HDR_L3_MASKS | \
1267 	 ICE_FLOW_RSS_SEG_HDR_L4_MASKS)
1268 
1269 /**
1270  * ice_flow_set_rss_seg_info - setup packet segments for RSS
1271  * @segs: pointer to the flow field segment(s)
1272  * @seg_cnt: segment count
1273  * @cfg: configure parameters
1274  *
1275  * Helper function to extract fields from hash bitmap and use flow
1276  * header value to set flow field segment for further use in flow
1277  * profile entry or removal.
1278  */
1279 static enum ice_status
1280 ice_flow_set_rss_seg_info(struct ice_flow_seg_info *segs, u8 seg_cnt,
1281 			  const struct ice_rss_hash_cfg *cfg)
1282 {
1283 	struct ice_flow_seg_info *seg;
1284 	u64 val;
1285 	u8 i;
1286 
1287 	/* set inner most segment */
1288 	seg = &segs[seg_cnt - 1];
1289 
1290 	ice_for_each_set_bit(i, (const ice_bitmap_t *)&cfg->hash_flds,
1291 			     ICE_FLOW_FIELD_IDX_MAX)
1292 		ice_flow_set_fld(seg, (enum ice_flow_field)i,
1293 				 ICE_FLOW_FLD_OFF_INVAL, ICE_FLOW_FLD_OFF_INVAL,
1294 				 ICE_FLOW_FLD_OFF_INVAL, false);
1295 
1296 	ICE_FLOW_SET_HDRS(seg, cfg->addl_hdrs);
1297 
1298 	/* set outer most header */
1299 	if (cfg->hdr_type == ICE_RSS_INNER_HEADERS_W_OUTER_IPV4)
1300 		segs[ICE_RSS_OUTER_HEADERS].hdrs |= ICE_FLOW_SEG_HDR_IPV4 |
1301 						   ICE_FLOW_SEG_HDR_IPV_OTHER;
1302 	else if (cfg->hdr_type == ICE_RSS_INNER_HEADERS_W_OUTER_IPV6)
1303 		segs[ICE_RSS_OUTER_HEADERS].hdrs |= ICE_FLOW_SEG_HDR_IPV6 |
1304 						   ICE_FLOW_SEG_HDR_IPV_OTHER;
1305 
1306 	if (seg->hdrs & ~ICE_FLOW_RSS_SEG_HDR_VAL_MASKS)
1307 		return ICE_ERR_PARAM;
1308 
1309 	val = (u64)(seg->hdrs & ICE_FLOW_RSS_SEG_HDR_L3_MASKS);
1310 	if (val && !ice_is_pow2(val))
1311 		return ICE_ERR_CFG;
1312 
1313 	val = (u64)(seg->hdrs & ICE_FLOW_RSS_SEG_HDR_L4_MASKS);
1314 	if (val && !ice_is_pow2(val))
1315 		return ICE_ERR_CFG;
1316 
1317 	return ICE_SUCCESS;
1318 }
1319 
1320 /**
1321  * ice_rem_vsi_rss_list - remove VSI from RSS list
1322  * @hw: pointer to the hardware structure
1323  * @vsi_handle: software VSI handle
1324  *
1325  * Remove the VSI from all RSS configurations in the list.
1326  */
1327 void ice_rem_vsi_rss_list(struct ice_hw *hw, u16 vsi_handle)
1328 {
1329 	struct ice_rss_cfg *r, *tmp;
1330 
1331 	if (LIST_EMPTY(&hw->rss_list_head))
1332 		return;
1333 
1334 	ice_acquire_lock(&hw->rss_locks);
1335 	LIST_FOR_EACH_ENTRY_SAFE(r, tmp, &hw->rss_list_head,
1336 				 ice_rss_cfg, l_entry)
1337 		if (ice_test_and_clear_bit(vsi_handle, r->vsis))
1338 			if (!ice_is_any_bit_set(r->vsis, ICE_MAX_VSI)) {
1339 				LIST_DEL(&r->l_entry);
1340 				ice_free(hw, r);
1341 			}
1342 	ice_release_lock(&hw->rss_locks);
1343 }
1344 
1345 /**
1346  * ice_rem_vsi_rss_cfg - remove RSS configurations associated with VSI
1347  * @hw: pointer to the hardware structure
1348  * @vsi_handle: software VSI handle
1349  *
1350  * This function will iterate through all flow profiles and disassociate
1351  * the VSI from that profile. If the flow profile has no VSIs it will
1352  * be removed.
1353  */
1354 enum ice_status ice_rem_vsi_rss_cfg(struct ice_hw *hw, u16 vsi_handle)
1355 {
1356 	const enum ice_block blk = ICE_BLK_RSS;
1357 	struct ice_flow_prof *p, *t;
1358 	enum ice_status status = ICE_SUCCESS;
1359 
1360 	if (!ice_is_vsi_valid(hw, vsi_handle))
1361 		return ICE_ERR_PARAM;
1362 
1363 	if (LIST_EMPTY(&hw->fl_profs[blk]))
1364 		return ICE_SUCCESS;
1365 
1366 	ice_acquire_lock(&hw->rss_locks);
1367 	LIST_FOR_EACH_ENTRY_SAFE(p, t, &hw->fl_profs[blk], ice_flow_prof,
1368 				 l_entry)
1369 		if (ice_is_bit_set(p->vsis, vsi_handle)) {
1370 			status = ice_flow_disassoc_prof(hw, blk, p, vsi_handle);
1371 			if (status)
1372 				break;
1373 
1374 			if (!ice_is_any_bit_set(p->vsis, ICE_MAX_VSI)) {
1375 				status = ice_flow_rem_prof(hw, blk, p->id);
1376 				if (status)
1377 					break;
1378 			}
1379 		}
1380 	ice_release_lock(&hw->rss_locks);
1381 
1382 	return status;
1383 }
1384 
1385 /**
1386  * ice_get_rss_hdr_type - get a RSS profile's header type
1387  * @prof: RSS flow profile
1388  */
1389 static enum ice_rss_cfg_hdr_type
1390 ice_get_rss_hdr_type(struct ice_flow_prof *prof)
1391 {
1392 	enum ice_rss_cfg_hdr_type hdr_type = ICE_RSS_ANY_HEADERS;
1393 
1394 	if (prof->segs_cnt == ICE_FLOW_SEG_SINGLE) {
1395 		hdr_type = ICE_RSS_OUTER_HEADERS;
1396 	} else if (prof->segs_cnt == ICE_FLOW_SEG_MAX) {
1397 		if (prof->segs[ICE_RSS_OUTER_HEADERS].hdrs == ICE_FLOW_SEG_HDR_NONE)
1398 			hdr_type = ICE_RSS_INNER_HEADERS;
1399 		if (prof->segs[ICE_RSS_OUTER_HEADERS].hdrs & ICE_FLOW_SEG_HDR_IPV4)
1400 			hdr_type = ICE_RSS_INNER_HEADERS_W_OUTER_IPV4;
1401 		if (prof->segs[ICE_RSS_OUTER_HEADERS].hdrs & ICE_FLOW_SEG_HDR_IPV6)
1402 			hdr_type = ICE_RSS_INNER_HEADERS_W_OUTER_IPV6;
1403 	}
1404 
1405 	return hdr_type;
1406 }
1407 
1408 /**
1409  * ice_rem_rss_list - remove RSS configuration from list
1410  * @hw: pointer to the hardware structure
1411  * @vsi_handle: software VSI handle
1412  * @prof: pointer to flow profile
1413  *
1414  * Assumption: lock has already been acquired for RSS list
1415  */
1416 static void
1417 ice_rem_rss_list(struct ice_hw *hw, u16 vsi_handle, struct ice_flow_prof *prof)
1418 {
1419 	enum ice_rss_cfg_hdr_type hdr_type;
1420 	struct ice_rss_cfg *r, *tmp;
1421 
1422 	/* Search for RSS hash fields associated to the VSI that match the
1423 	 * hash configurations associated to the flow profile. If found
1424 	 * remove from the RSS entry list of the VSI context and delete entry.
1425 	 */
1426 	hdr_type = ice_get_rss_hdr_type(prof);
1427 	LIST_FOR_EACH_ENTRY_SAFE(r, tmp, &hw->rss_list_head,
1428 				 ice_rss_cfg, l_entry)
1429 		if (r->hash.hash_flds == prof->segs[prof->segs_cnt - 1].match &&
1430 		    r->hash.addl_hdrs == prof->segs[prof->segs_cnt - 1].hdrs &&
1431 		    r->hash.hdr_type == hdr_type) {
1432 			ice_clear_bit(vsi_handle, r->vsis);
1433 			if (!ice_is_any_bit_set(r->vsis, ICE_MAX_VSI)) {
1434 				LIST_DEL(&r->l_entry);
1435 				ice_free(hw, r);
1436 			}
1437 			return;
1438 		}
1439 }
1440 
1441 /**
1442  * ice_add_rss_list - add RSS configuration to list
1443  * @hw: pointer to the hardware structure
1444  * @vsi_handle: software VSI handle
1445  * @prof: pointer to flow profile
1446  *
1447  * Assumption: lock has already been acquired for RSS list
1448  */
1449 static enum ice_status
1450 ice_add_rss_list(struct ice_hw *hw, u16 vsi_handle, struct ice_flow_prof *prof)
1451 {
1452 	enum ice_rss_cfg_hdr_type hdr_type;
1453 	struct ice_rss_cfg *r, *rss_cfg;
1454 
1455 	hdr_type = ice_get_rss_hdr_type(prof);
1456 	LIST_FOR_EACH_ENTRY(r, &hw->rss_list_head,
1457 			    ice_rss_cfg, l_entry)
1458 		if (r->hash.hash_flds == prof->segs[prof->segs_cnt - 1].match &&
1459 		    r->hash.addl_hdrs == prof->segs[prof->segs_cnt - 1].hdrs &&
1460 		    r->hash.hdr_type == hdr_type) {
1461 			ice_set_bit(vsi_handle, r->vsis);
1462 			return ICE_SUCCESS;
1463 		}
1464 
1465 	rss_cfg = (struct ice_rss_cfg *)ice_malloc(hw, sizeof(*rss_cfg));
1466 	if (!rss_cfg)
1467 		return ICE_ERR_NO_MEMORY;
1468 
1469 	rss_cfg->hash.hash_flds = prof->segs[prof->segs_cnt - 1].match;
1470 	rss_cfg->hash.addl_hdrs = prof->segs[prof->segs_cnt - 1].hdrs;
1471 	rss_cfg->hash.hdr_type = hdr_type;
1472 	rss_cfg->hash.symm = prof->cfg.symm;
1473 	ice_set_bit(vsi_handle, rss_cfg->vsis);
1474 
1475 	LIST_ADD_TAIL(&rss_cfg->l_entry, &hw->rss_list_head);
1476 
1477 	return ICE_SUCCESS;
1478 }
1479 
1480 #define ICE_FLOW_PROF_HASH_S	0
1481 #define ICE_FLOW_PROF_HASH_M	(0xFFFFFFFFULL << ICE_FLOW_PROF_HASH_S)
1482 #define ICE_FLOW_PROF_HDR_S	32
1483 #define ICE_FLOW_PROF_HDR_M	(0x3FFFFFFFULL << ICE_FLOW_PROF_HDR_S)
1484 #define ICE_FLOW_PROF_ENCAP_S	62
1485 #define ICE_FLOW_PROF_ENCAP_M	(0x3ULL << ICE_FLOW_PROF_ENCAP_S)
1486 
1487 /* Flow profile ID format:
1488  * [0:31] - Packet match fields
1489  * [32:61] - Protocol header
1490  * [62:63] - Encapsulation flag:
1491  *	     0 if non-tunneled
1492  *	     1 if tunneled
1493  *	     2 for tunneled with outer ipv4
1494  *	     3 for tunneled with outer ipv6
1495  */
1496 #define ICE_FLOW_GEN_PROFID(hash, hdr, encap) \
1497 	(u64)(((u64)(hash) & ICE_FLOW_PROF_HASH_M) | \
1498 	      (((u64)(hdr) << ICE_FLOW_PROF_HDR_S) & ICE_FLOW_PROF_HDR_M) | \
1499 	      (((u64)(encap) << ICE_FLOW_PROF_ENCAP_S) & ICE_FLOW_PROF_ENCAP_M))
1500 
1501 /**
1502  * ice_add_rss_cfg_sync - add an RSS configuration
1503  * @hw: pointer to the hardware structure
1504  * @vsi_handle: software VSI handle
1505  * @cfg: configure parameters
1506  *
1507  * Assumption: lock has already been acquired for RSS list
1508  */
1509 static enum ice_status
1510 ice_add_rss_cfg_sync(struct ice_hw *hw, u16 vsi_handle,
1511 		     const struct ice_rss_hash_cfg *cfg)
1512 {
1513 	const enum ice_block blk = ICE_BLK_RSS;
1514 	struct ice_flow_prof *prof = NULL;
1515 	struct ice_flow_seg_info *segs;
1516 	enum ice_status status;
1517 	u8 segs_cnt;
1518 
1519 	if (cfg->symm)
1520 		return ICE_ERR_PARAM;
1521 
1522 	segs_cnt = (cfg->hdr_type == ICE_RSS_OUTER_HEADERS) ?
1523 			ICE_FLOW_SEG_SINGLE : ICE_FLOW_SEG_MAX;
1524 
1525 	segs = (struct ice_flow_seg_info *)ice_calloc(hw, segs_cnt,
1526 						      sizeof(*segs));
1527 	if (!segs)
1528 		return ICE_ERR_NO_MEMORY;
1529 
1530 	/* Construct the packet segment info from the hashed fields */
1531 	status = ice_flow_set_rss_seg_info(segs, segs_cnt, cfg);
1532 	if (status)
1533 		goto exit;
1534 
1535 	/* Search for a flow profile that has matching headers, hash fields
1536 	 * and has the input VSI associated to it. If found, no further
1537 	 * operations required and exit.
1538 	 */
1539 	prof = ice_flow_find_prof_conds(hw, blk, ICE_FLOW_RX, segs, segs_cnt,
1540 					vsi_handle,
1541 					ICE_FLOW_FIND_PROF_CHK_FLDS |
1542 					ICE_FLOW_FIND_PROF_CHK_VSI);
1543 	if (prof)
1544 		goto exit;
1545 
1546 	/* Check if a flow profile exists with the same protocol headers and
1547 	 * associated with the input VSI. If so disassociate the VSI from
1548 	 * this profile. The VSI will be added to a new profile created with
1549 	 * the protocol header and new hash field configuration.
1550 	 */
1551 	prof = ice_flow_find_prof_conds(hw, blk, ICE_FLOW_RX, segs, segs_cnt,
1552 					vsi_handle, ICE_FLOW_FIND_PROF_CHK_VSI);
1553 	if (prof) {
1554 		status = ice_flow_disassoc_prof(hw, blk, prof, vsi_handle);
1555 		if (!status)
1556 			ice_rem_rss_list(hw, vsi_handle, prof);
1557 		else
1558 			goto exit;
1559 
1560 		/* Remove profile if it has no VSIs associated */
1561 		if (!ice_is_any_bit_set(prof->vsis, ICE_MAX_VSI)) {
1562 			status = ice_flow_rem_prof(hw, blk, prof->id);
1563 			if (status)
1564 				goto exit;
1565 		}
1566 	}
1567 
1568 	/* Search for a profile that has same match fields only. If this
1569 	 * exists then associate the VSI to this profile.
1570 	 */
1571 	prof = ice_flow_find_prof_conds(hw, blk, ICE_FLOW_RX, segs, segs_cnt,
1572 					vsi_handle,
1573 					ICE_FLOW_FIND_PROF_CHK_FLDS);
1574 	if (prof) {
1575 		status = ice_flow_assoc_prof(hw, blk, prof, vsi_handle);
1576 		if (!status)
1577 			status = ice_add_rss_list(hw, vsi_handle, prof);
1578 		goto exit;
1579 	}
1580 
1581 	/* Create a new flow profile with generated profile and packet
1582 	 * segment information.
1583 	 */
1584 	status = ice_flow_add_prof(hw, blk, ICE_FLOW_RX,
1585 				   ICE_FLOW_GEN_PROFID(cfg->hash_flds,
1586 						       segs[segs_cnt - 1].hdrs,
1587 						       cfg->hdr_type),
1588 				   segs, segs_cnt, NULL, 0, &prof);
1589 	if (status)
1590 		goto exit;
1591 
1592 	status = ice_flow_assoc_prof(hw, blk, prof, vsi_handle);
1593 	/* If association to a new flow profile failed then this profile can
1594 	 * be removed.
1595 	 */
1596 	if (status) {
1597 		ice_flow_rem_prof(hw, blk, prof->id);
1598 		goto exit;
1599 	}
1600 
1601 	status = ice_add_rss_list(hw, vsi_handle, prof);
1602 
1603 	prof->cfg.symm = cfg->symm;
1604 
1605 exit:
1606 	ice_free(hw, segs);
1607 	return status;
1608 }
1609 
1610 /**
1611  * ice_add_rss_cfg - add an RSS configuration with specified hashed fields
1612  * @hw: pointer to the hardware structure
1613  * @vsi_handle: software VSI handle
1614  * @cfg: configure parameters
1615  *
1616  * This function will generate a flow profile based on fields associated with
1617  * the input fields to hash on, the flow type and use the VSI number to add
1618  * a flow entry to the profile.
1619  */
1620 enum ice_status
1621 ice_add_rss_cfg(struct ice_hw *hw, u16 vsi_handle,
1622 		const struct ice_rss_hash_cfg *cfg)
1623 {
1624 	struct ice_rss_hash_cfg local_cfg;
1625 	enum ice_status status;
1626 
1627 	if (!ice_is_vsi_valid(hw, vsi_handle) ||
1628 	    !cfg || cfg->hdr_type > ICE_RSS_ANY_HEADERS ||
1629 	    cfg->hash_flds == ICE_HASH_INVALID)
1630 		return ICE_ERR_PARAM;
1631 
1632 	local_cfg = *cfg;
1633 	if (cfg->hdr_type < ICE_RSS_ANY_HEADERS) {
1634 		ice_acquire_lock(&hw->rss_locks);
1635 		status = ice_add_rss_cfg_sync(hw, vsi_handle, &local_cfg);
1636 		ice_release_lock(&hw->rss_locks);
1637 	} else {
1638 		ice_acquire_lock(&hw->rss_locks);
1639 		local_cfg.hdr_type = ICE_RSS_OUTER_HEADERS;
1640 		status = ice_add_rss_cfg_sync(hw, vsi_handle, &local_cfg);
1641 		if (!status) {
1642 			local_cfg.hdr_type = ICE_RSS_INNER_HEADERS;
1643 			status = ice_add_rss_cfg_sync(hw, vsi_handle,
1644 						      &local_cfg);
1645 		}
1646 		ice_release_lock(&hw->rss_locks);
1647 	}
1648 
1649 	return status;
1650 }
1651 
1652 /**
1653  * ice_rem_rss_cfg_sync - remove an existing RSS configuration
1654  * @hw: pointer to the hardware structure
1655  * @vsi_handle: software VSI handle
1656  * @cfg: configure parameters
1657  *
1658  * Assumption: lock has already been acquired for RSS list
1659  */
1660 static enum ice_status
1661 ice_rem_rss_cfg_sync(struct ice_hw *hw, u16 vsi_handle,
1662 		     const struct ice_rss_hash_cfg *cfg)
1663 {
1664 	const enum ice_block blk = ICE_BLK_RSS;
1665 	struct ice_flow_seg_info *segs;
1666 	struct ice_flow_prof *prof;
1667 	enum ice_status status;
1668 	u8 segs_cnt;
1669 
1670 	segs_cnt = (cfg->hdr_type == ICE_RSS_OUTER_HEADERS) ?
1671 			ICE_FLOW_SEG_SINGLE : ICE_FLOW_SEG_MAX;
1672 	segs = (struct ice_flow_seg_info *)ice_calloc(hw, segs_cnt,
1673 						      sizeof(*segs));
1674 	if (!segs)
1675 		return ICE_ERR_NO_MEMORY;
1676 
1677 	/* Construct the packet segment info from the hashed fields */
1678 	status = ice_flow_set_rss_seg_info(segs, segs_cnt, cfg);
1679 	if (status)
1680 		goto out;
1681 
1682 	prof = ice_flow_find_prof_conds(hw, blk, ICE_FLOW_RX, segs, segs_cnt,
1683 					vsi_handle,
1684 					ICE_FLOW_FIND_PROF_CHK_FLDS);
1685 	if (!prof) {
1686 		status = ICE_ERR_DOES_NOT_EXIST;
1687 		goto out;
1688 	}
1689 
1690 	status = ice_flow_disassoc_prof(hw, blk, prof, vsi_handle);
1691 	if (status)
1692 		goto out;
1693 
1694 	/* Remove RSS configuration from VSI context before deleting
1695 	 * the flow profile.
1696 	 */
1697 	ice_rem_rss_list(hw, vsi_handle, prof);
1698 
1699 	if (!ice_is_any_bit_set(prof->vsis, ICE_MAX_VSI))
1700 		status = ice_flow_rem_prof(hw, blk, prof->id);
1701 
1702 out:
1703 	ice_free(hw, segs);
1704 	return status;
1705 }
1706 
1707 /**
1708  * ice_rem_rss_cfg - remove an existing RSS config with matching hashed fields
1709  * @hw: pointer to the hardware structure
1710  * @vsi_handle: software VSI handle
1711  * @cfg: configure parameters
1712  *
1713  * This function will lookup the flow profile based on the input
1714  * hash field bitmap, iterate through the profile entry list of
1715  * that profile and find entry associated with input VSI to be
1716  * removed. Calls are made to underlying flow apis which will in
1717  * turn build or update buffers for RSS XLT1 section.
1718  */
1719 enum ice_status
1720 ice_rem_rss_cfg(struct ice_hw *hw, u16 vsi_handle,
1721 		const struct ice_rss_hash_cfg *cfg)
1722 {
1723 	struct ice_rss_hash_cfg local_cfg;
1724 	enum ice_status status;
1725 
1726 	if (!ice_is_vsi_valid(hw, vsi_handle) ||
1727 	    !cfg || cfg->hdr_type > ICE_RSS_ANY_HEADERS ||
1728 	    cfg->hash_flds == ICE_HASH_INVALID)
1729 		return ICE_ERR_PARAM;
1730 
1731 	ice_acquire_lock(&hw->rss_locks);
1732 	local_cfg = *cfg;
1733 	if (cfg->hdr_type < ICE_RSS_ANY_HEADERS) {
1734 		status = ice_rem_rss_cfg_sync(hw, vsi_handle, &local_cfg);
1735 	} else {
1736 		local_cfg.hdr_type = ICE_RSS_OUTER_HEADERS;
1737 		status = ice_rem_rss_cfg_sync(hw, vsi_handle, &local_cfg);
1738 
1739 		if (!status) {
1740 			local_cfg.hdr_type = ICE_RSS_INNER_HEADERS;
1741 			status = ice_rem_rss_cfg_sync(hw, vsi_handle,
1742 						      &local_cfg);
1743 		}
1744 	}
1745 	ice_release_lock(&hw->rss_locks);
1746 
1747 	return status;
1748 }
1749 
1750 /* Mapping of AVF hash bit fields to an L3-L4 hash combination.
1751  * As the ice_flow_avf_hdr_field represent individual bit shifts in a hash,
1752  * convert its values to their appropriate flow L3, L4 values.
1753  */
1754 #define ICE_FLOW_AVF_RSS_IPV4_MASKS \
1755 	(BIT_ULL(ICE_AVF_FLOW_FIELD_IPV4_OTHER) | \
1756 	 BIT_ULL(ICE_AVF_FLOW_FIELD_FRAG_IPV4))
1757 #define ICE_FLOW_AVF_RSS_TCP_IPV4_MASKS \
1758 	(BIT_ULL(ICE_AVF_FLOW_FIELD_IPV4_TCP_SYN_NO_ACK) | \
1759 	 BIT_ULL(ICE_AVF_FLOW_FIELD_IPV4_TCP))
1760 #define ICE_FLOW_AVF_RSS_UDP_IPV4_MASKS \
1761 	(BIT_ULL(ICE_AVF_FLOW_FIELD_UNICAST_IPV4_UDP) | \
1762 	 BIT_ULL(ICE_AVF_FLOW_FIELD_MULTICAST_IPV4_UDP) | \
1763 	 BIT_ULL(ICE_AVF_FLOW_FIELD_IPV4_UDP))
1764 #define ICE_FLOW_AVF_RSS_ALL_IPV4_MASKS \
1765 	(ICE_FLOW_AVF_RSS_TCP_IPV4_MASKS | ICE_FLOW_AVF_RSS_UDP_IPV4_MASKS | \
1766 	 ICE_FLOW_AVF_RSS_IPV4_MASKS | BIT_ULL(ICE_AVF_FLOW_FIELD_IPV4_SCTP))
1767 
1768 #define ICE_FLOW_AVF_RSS_IPV6_MASKS \
1769 	(BIT_ULL(ICE_AVF_FLOW_FIELD_IPV6_OTHER) | \
1770 	 BIT_ULL(ICE_AVF_FLOW_FIELD_FRAG_IPV6))
1771 #define ICE_FLOW_AVF_RSS_UDP_IPV6_MASKS \
1772 	(BIT_ULL(ICE_AVF_FLOW_FIELD_UNICAST_IPV6_UDP) | \
1773 	 BIT_ULL(ICE_AVF_FLOW_FIELD_MULTICAST_IPV6_UDP) | \
1774 	 BIT_ULL(ICE_AVF_FLOW_FIELD_IPV6_UDP))
1775 #define ICE_FLOW_AVF_RSS_TCP_IPV6_MASKS \
1776 	(BIT_ULL(ICE_AVF_FLOW_FIELD_IPV6_TCP_SYN_NO_ACK) | \
1777 	 BIT_ULL(ICE_AVF_FLOW_FIELD_IPV6_TCP))
1778 #define ICE_FLOW_AVF_RSS_ALL_IPV6_MASKS \
1779 	(ICE_FLOW_AVF_RSS_TCP_IPV6_MASKS | ICE_FLOW_AVF_RSS_UDP_IPV6_MASKS | \
1780 	 ICE_FLOW_AVF_RSS_IPV6_MASKS | BIT_ULL(ICE_AVF_FLOW_FIELD_IPV6_SCTP))
1781 
1782 /**
1783  * ice_add_avf_rss_cfg - add an RSS configuration for AVF driver
1784  * @hw: pointer to the hardware structure
1785  * @vsi_handle: software VSI handle
1786  * @avf_hash: hash bit fields (ICE_AVF_FLOW_FIELD_*) to configure
1787  *
1788  * This function will take the hash bitmap provided by the AVF driver via a
1789  * message, convert it to ICE-compatible values, and configure RSS flow
1790  * profiles.
1791  */
1792 enum ice_status
1793 ice_add_avf_rss_cfg(struct ice_hw *hw, u16 vsi_handle, u64 avf_hash)
1794 {
1795 	enum ice_status status = ICE_SUCCESS;
1796 	struct ice_rss_hash_cfg hcfg;
1797 	u64 hash_flds;
1798 
1799 	if (avf_hash == ICE_AVF_FLOW_FIELD_INVALID ||
1800 	    !ice_is_vsi_valid(hw, vsi_handle))
1801 		return ICE_ERR_PARAM;
1802 
1803 	/* Make sure no unsupported bits are specified */
1804 	if (avf_hash & ~(ICE_FLOW_AVF_RSS_ALL_IPV4_MASKS |
1805 			 ICE_FLOW_AVF_RSS_ALL_IPV6_MASKS))
1806 		return ICE_ERR_CFG;
1807 
1808 	hash_flds = avf_hash;
1809 
1810 	/* Always create an L3 RSS configuration for any L4 RSS configuration */
1811 	if (hash_flds & ICE_FLOW_AVF_RSS_ALL_IPV4_MASKS)
1812 		hash_flds |= ICE_FLOW_AVF_RSS_IPV4_MASKS;
1813 
1814 	if (hash_flds & ICE_FLOW_AVF_RSS_ALL_IPV6_MASKS)
1815 		hash_flds |= ICE_FLOW_AVF_RSS_IPV6_MASKS;
1816 
1817 	/* Create the corresponding RSS configuration for each valid hash bit */
1818 	while (hash_flds) {
1819 		u64 rss_hash = ICE_HASH_INVALID;
1820 
1821 		if (hash_flds & ICE_FLOW_AVF_RSS_ALL_IPV4_MASKS) {
1822 			if (hash_flds & ICE_FLOW_AVF_RSS_IPV4_MASKS) {
1823 				rss_hash = ICE_FLOW_HASH_IPV4;
1824 				hash_flds &= ~ICE_FLOW_AVF_RSS_IPV4_MASKS;
1825 			} else if (hash_flds &
1826 				   ICE_FLOW_AVF_RSS_TCP_IPV4_MASKS) {
1827 				rss_hash = ICE_FLOW_HASH_IPV4 |
1828 					ICE_FLOW_HASH_TCP_PORT;
1829 				hash_flds &= ~ICE_FLOW_AVF_RSS_TCP_IPV4_MASKS;
1830 			} else if (hash_flds &
1831 				   ICE_FLOW_AVF_RSS_UDP_IPV4_MASKS) {
1832 				rss_hash = ICE_FLOW_HASH_IPV4 |
1833 					ICE_FLOW_HASH_UDP_PORT;
1834 				hash_flds &= ~ICE_FLOW_AVF_RSS_UDP_IPV4_MASKS;
1835 			} else if (hash_flds &
1836 				   BIT_ULL(ICE_AVF_FLOW_FIELD_IPV4_SCTP)) {
1837 				rss_hash = ICE_FLOW_HASH_IPV4 |
1838 					ICE_FLOW_HASH_SCTP_PORT;
1839 				hash_flds &=
1840 					~BIT_ULL(ICE_AVF_FLOW_FIELD_IPV4_SCTP);
1841 			}
1842 		} else if (hash_flds & ICE_FLOW_AVF_RSS_ALL_IPV6_MASKS) {
1843 			if (hash_flds & ICE_FLOW_AVF_RSS_IPV6_MASKS) {
1844 				rss_hash = ICE_FLOW_HASH_IPV6;
1845 				hash_flds &= ~ICE_FLOW_AVF_RSS_IPV6_MASKS;
1846 			} else if (hash_flds &
1847 				   ICE_FLOW_AVF_RSS_TCP_IPV6_MASKS) {
1848 				rss_hash = ICE_FLOW_HASH_IPV6 |
1849 					ICE_FLOW_HASH_TCP_PORT;
1850 				hash_flds &= ~ICE_FLOW_AVF_RSS_TCP_IPV6_MASKS;
1851 			} else if (hash_flds &
1852 				   ICE_FLOW_AVF_RSS_UDP_IPV6_MASKS) {
1853 				rss_hash = ICE_FLOW_HASH_IPV6 |
1854 					ICE_FLOW_HASH_UDP_PORT;
1855 				hash_flds &= ~ICE_FLOW_AVF_RSS_UDP_IPV6_MASKS;
1856 			} else if (hash_flds &
1857 				   BIT_ULL(ICE_AVF_FLOW_FIELD_IPV6_SCTP)) {
1858 				rss_hash = ICE_FLOW_HASH_IPV6 |
1859 					ICE_FLOW_HASH_SCTP_PORT;
1860 				hash_flds &=
1861 					~BIT_ULL(ICE_AVF_FLOW_FIELD_IPV6_SCTP);
1862 			}
1863 		}
1864 
1865 		if (rss_hash == ICE_HASH_INVALID)
1866 			return ICE_ERR_OUT_OF_RANGE;
1867 
1868 		hcfg.addl_hdrs = ICE_FLOW_SEG_HDR_NONE;
1869 		hcfg.hash_flds = rss_hash;
1870 		hcfg.symm = false;
1871 		hcfg.hdr_type = ICE_RSS_ANY_HEADERS;
1872 		status = ice_add_rss_cfg(hw, vsi_handle, &hcfg);
1873 		if (status)
1874 			break;
1875 	}
1876 
1877 	return status;
1878 }
1879 
1880 /**
1881  * ice_replay_rss_cfg - replay RSS configurations associated with VSI
1882  * @hw: pointer to the hardware structure
1883  * @vsi_handle: software VSI handle
1884  */
1885 enum ice_status ice_replay_rss_cfg(struct ice_hw *hw, u16 vsi_handle)
1886 {
1887 	enum ice_status status = ICE_SUCCESS;
1888 	struct ice_rss_cfg *r;
1889 
1890 	if (!ice_is_vsi_valid(hw, vsi_handle))
1891 		return ICE_ERR_PARAM;
1892 
1893 	ice_acquire_lock(&hw->rss_locks);
1894 	LIST_FOR_EACH_ENTRY(r, &hw->rss_list_head,
1895 			    ice_rss_cfg, l_entry) {
1896 		if (ice_is_bit_set(r->vsis, vsi_handle)) {
1897 			status = ice_add_rss_cfg_sync(hw, vsi_handle, &r->hash);
1898 			if (status)
1899 				break;
1900 		}
1901 	}
1902 	ice_release_lock(&hw->rss_locks);
1903 
1904 	return status;
1905 }
1906 
1907 /**
1908  * ice_get_rss_cfg - returns hashed fields for the given header types
1909  * @hw: pointer to the hardware structure
1910  * @vsi_handle: software VSI handle
1911  * @hdrs: protocol header type
1912  *
1913  * This function will return the match fields of the first instance of flow
1914  * profile having the given header types and containing input VSI
1915  */
1916 u64 ice_get_rss_cfg(struct ice_hw *hw, u16 vsi_handle, u32 hdrs)
1917 {
1918 	u64 rss_hash = ICE_HASH_INVALID;
1919 	struct ice_rss_cfg *r;
1920 
1921 	/* verify if the protocol header is non zero and VSI is valid */
1922 	if (hdrs == ICE_FLOW_SEG_HDR_NONE || !ice_is_vsi_valid(hw, vsi_handle))
1923 		return ICE_HASH_INVALID;
1924 
1925 	ice_acquire_lock(&hw->rss_locks);
1926 	LIST_FOR_EACH_ENTRY(r, &hw->rss_list_head,
1927 			    ice_rss_cfg, l_entry)
1928 		if (ice_is_bit_set(r->vsis, vsi_handle) &&
1929 		    r->hash.addl_hdrs == hdrs) {
1930 			rss_hash = r->hash.hash_flds;
1931 			break;
1932 		}
1933 	ice_release_lock(&hw->rss_locks);
1934 
1935 	return rss_hash;
1936 }
1937