]> CyberLeo.Net >> Repos - FreeBSD/FreeBSD.git/blob - sys/dev/ice/ice_flow.c
contrib/bc: merge version 5.1.0 from vendor branch
[FreeBSD/FreeBSD.git] / sys / dev / ice / ice_flow.c
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 }