1271651Skargl/* SPDX-License-Identifier: BSD-3-Clause */
2271651Skargl/*  Copyright (c) 2024, Intel Corporation
3271651Skargl *  All rights reserved.
4271651Skargl *
5271651Skargl *  Redistribution and use in source and binary forms, with or without
6271651Skargl *  modification, are permitted provided that the following conditions are met:
7271651Skargl *
8271651Skargl *   1. Redistributions of source code must retain the above copyright notice,
9271651Skargl *      this list of conditions and the following disclaimer.
10271651Skargl *
11271651Skargl *   2. Redistributions in binary form must reproduce the above copyright
12271651Skargl *      notice, this list of conditions and the following disclaimer in the
13271651Skargl *      documentation and/or other materials provided with the distribution.
14271651Skargl *
15271651Skargl *   3. Neither the name of the Intel Corporation nor the names of its
16271651Skargl *      contributors may be used to endorse or promote products derived from
17284810Stijl *      this software without specific prior written permission.
18271651Skargl *
19271651Skargl *  THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
20271651Skargl *  AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
21271651Skargl *  IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
22271651Skargl *  ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE
23271651Skargl *  LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
24271651Skargl *  CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
25271651Skargl *  SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
26271651Skargl *  INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
27271651Skargl *  CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
28271651Skargl *  ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
29271651Skargl *  POSSIBILITY OF SUCH DAMAGE.
30271651Skargl */
31271651Skargl
32271651Skargl#include "ice_common.h"
33271651Skargl#include "ice_flow.h"
34271651Skargl
35271651Skargl/* Size of known protocol header fields */
36271651Skargl#define ICE_FLOW_FLD_SZ_ETH_TYPE	2
37271651Skargl#define ICE_FLOW_FLD_SZ_VLAN		2
38271651Skargl#define ICE_FLOW_FLD_SZ_IPV4_ADDR	4
39271651Skargl#define ICE_FLOW_FLD_SZ_IPV6_ADDR	16
40271651Skargl#define ICE_FLOW_FLD_SZ_IP_DSCP		1
41271651Skargl#define ICE_FLOW_FLD_SZ_IP_TTL		1
42271651Skargl#define ICE_FLOW_FLD_SZ_IP_PROT		1
43271651Skargl#define ICE_FLOW_FLD_SZ_PORT		2
44271651Skargl#define ICE_FLOW_FLD_SZ_TCP_FLAGS	1
45271651Skargl#define ICE_FLOW_FLD_SZ_ICMP_TYPE	1
46271651Skargl#define ICE_FLOW_FLD_SZ_ICMP_CODE	1
47271651Skargl#define ICE_FLOW_FLD_SZ_ARP_OPER	2
48271651Skargl#define ICE_FLOW_FLD_SZ_GRE_KEYID	4
49271651Skargl
50271651Skargl/* Describe properties of a protocol header field */
51271651Skarglstruct ice_flow_field_info {
52271651Skargl	enum ice_flow_seg_hdr hdr;
53271651Skargl	s16 off;	/* Offset from start of a protocol header, in bits */
54271651Skargl	u16 size;	/* Size of fields in bits */
55271651Skargl};
56271651Skargl
57271651Skargl#define ICE_FLOW_FLD_INFO(_hdr, _offset_bytes, _size_bytes) { \
58271651Skargl	.hdr = _hdr, \
59271651Skargl	.off = (_offset_bytes) * BITS_PER_BYTE, \
60271651Skargl	.size = (_size_bytes) * BITS_PER_BYTE, \
61271651Skargl}
62271651Skargl
63271651Skargl/* Table containing properties of supported protocol header fields */
64271651Skarglstatic const
65271651Skarglstruct ice_flow_field_info ice_flds_info[ICE_FLOW_FIELD_IDX_MAX] = {
66271651Skargl	/* Ether */
67271651Skargl	/* ICE_FLOW_FIELD_IDX_ETH_DA */
68271651Skargl	ICE_FLOW_FLD_INFO(ICE_FLOW_SEG_HDR_ETH, 0, ETH_ALEN),
69271651Skargl	/* ICE_FLOW_FIELD_IDX_ETH_SA */
70271651Skargl	ICE_FLOW_FLD_INFO(ICE_FLOW_SEG_HDR_ETH, ETH_ALEN, ETH_ALEN),
71271651Skargl	/* ICE_FLOW_FIELD_IDX_S_VLAN */
72271651Skargl	ICE_FLOW_FLD_INFO(ICE_FLOW_SEG_HDR_VLAN, 12, ICE_FLOW_FLD_SZ_VLAN),
73271651Skargl	/* ICE_FLOW_FIELD_IDX_C_VLAN */
74271651Skargl	ICE_FLOW_FLD_INFO(ICE_FLOW_SEG_HDR_VLAN, 14, ICE_FLOW_FLD_SZ_VLAN),
75271651Skargl	/* ICE_FLOW_FIELD_IDX_ETH_TYPE */
76271651Skargl	ICE_FLOW_FLD_INFO(ICE_FLOW_SEG_HDR_ETH, 0, ICE_FLOW_FLD_SZ_ETH_TYPE),
77271651Skargl	/* IPv4 / IPv6 */
78271651Skargl	/* ICE_FLOW_FIELD_IDX_IPV4_DSCP */
79271651Skargl	ICE_FLOW_FLD_INFO(ICE_FLOW_SEG_HDR_IPV4, 1, ICE_FLOW_FLD_SZ_IP_DSCP),
80271651Skargl	/* ICE_FLOW_FIELD_IDX_IPV6_DSCP */
81271651Skargl	ICE_FLOW_FLD_INFO(ICE_FLOW_SEG_HDR_IPV6, 0, ICE_FLOW_FLD_SZ_IP_DSCP),
82271651Skargl	/* ICE_FLOW_FIELD_IDX_IPV4_TTL */
83271651Skargl	ICE_FLOW_FLD_INFO(ICE_FLOW_SEG_HDR_NONE, 8, ICE_FLOW_FLD_SZ_IP_TTL),
84271651Skargl	/* ICE_FLOW_FIELD_IDX_IPV4_PROT */
85271651Skargl	ICE_FLOW_FLD_INFO(ICE_FLOW_SEG_HDR_NONE, 9, ICE_FLOW_FLD_SZ_IP_PROT),
86271651Skargl	/* ICE_FLOW_FIELD_IDX_IPV6_TTL */
87271651Skargl	ICE_FLOW_FLD_INFO(ICE_FLOW_SEG_HDR_NONE, 7, ICE_FLOW_FLD_SZ_IP_TTL),
88271651Skargl	/* ICE_FLOW_FIELD_IDX_IPV4_PROT */
89271651Skargl	ICE_FLOW_FLD_INFO(ICE_FLOW_SEG_HDR_NONE, 6, ICE_FLOW_FLD_SZ_IP_PROT),
90271651Skargl	/* ICE_FLOW_FIELD_IDX_IPV4_SA */
91271651Skargl	ICE_FLOW_FLD_INFO(ICE_FLOW_SEG_HDR_IPV4, 12, ICE_FLOW_FLD_SZ_IPV4_ADDR),
92271651Skargl	/* ICE_FLOW_FIELD_IDX_IPV4_DA */
93271651Skargl	ICE_FLOW_FLD_INFO(ICE_FLOW_SEG_HDR_IPV4, 16, ICE_FLOW_FLD_SZ_IPV4_ADDR),
94271651Skargl	/* ICE_FLOW_FIELD_IDX_IPV6_SA */
95271651Skargl	ICE_FLOW_FLD_INFO(ICE_FLOW_SEG_HDR_IPV6, 8, ICE_FLOW_FLD_SZ_IPV6_ADDR),
96271651Skargl	/* ICE_FLOW_FIELD_IDX_IPV6_DA */
97271651Skargl	ICE_FLOW_FLD_INFO(ICE_FLOW_SEG_HDR_IPV6, 24, ICE_FLOW_FLD_SZ_IPV6_ADDR),
98271651Skargl	/* Transport */
99271651Skargl	/* ICE_FLOW_FIELD_IDX_TCP_SRC_PORT */
100271651Skargl	ICE_FLOW_FLD_INFO(ICE_FLOW_SEG_HDR_TCP, 0, ICE_FLOW_FLD_SZ_PORT),
101271651Skargl	/* ICE_FLOW_FIELD_IDX_TCP_DST_PORT */
102271651Skargl	ICE_FLOW_FLD_INFO(ICE_FLOW_SEG_HDR_TCP, 2, ICE_FLOW_FLD_SZ_PORT),
103271651Skargl	/* ICE_FLOW_FIELD_IDX_UDP_SRC_PORT */
104271651Skargl	ICE_FLOW_FLD_INFO(ICE_FLOW_SEG_HDR_UDP, 0, ICE_FLOW_FLD_SZ_PORT),
105271651Skargl	/* ICE_FLOW_FIELD_IDX_UDP_DST_PORT */
106271651Skargl	ICE_FLOW_FLD_INFO(ICE_FLOW_SEG_HDR_UDP, 2, ICE_FLOW_FLD_SZ_PORT),
107271651Skargl	/* ICE_FLOW_FIELD_IDX_SCTP_SRC_PORT */
108271651Skargl	ICE_FLOW_FLD_INFO(ICE_FLOW_SEG_HDR_SCTP, 0, ICE_FLOW_FLD_SZ_PORT),
109271651Skargl	/* ICE_FLOW_FIELD_IDX_SCTP_DST_PORT */
110271651Skargl	ICE_FLOW_FLD_INFO(ICE_FLOW_SEG_HDR_SCTP, 2, ICE_FLOW_FLD_SZ_PORT),
111271651Skargl	/* ICE_FLOW_FIELD_IDX_TCP_FLAGS */
112271651Skargl	ICE_FLOW_FLD_INFO(ICE_FLOW_SEG_HDR_TCP, 13, ICE_FLOW_FLD_SZ_TCP_FLAGS),
113271651Skargl	/* ARP */
114271651Skargl	/* ICE_FLOW_FIELD_IDX_ARP_SIP */
115271651Skargl	ICE_FLOW_FLD_INFO(ICE_FLOW_SEG_HDR_ARP, 14, ICE_FLOW_FLD_SZ_IPV4_ADDR),
116271651Skargl	/* ICE_FLOW_FIELD_IDX_ARP_DIP */
117271651Skargl	ICE_FLOW_FLD_INFO(ICE_FLOW_SEG_HDR_ARP, 24, ICE_FLOW_FLD_SZ_IPV4_ADDR),
118271651Skargl	/* ICE_FLOW_FIELD_IDX_ARP_SHA */
119271651Skargl	ICE_FLOW_FLD_INFO(ICE_FLOW_SEG_HDR_ARP, 8, ETH_ALEN),
120271651Skargl	/* ICE_FLOW_FIELD_IDX_ARP_DHA */
121271651Skargl	ICE_FLOW_FLD_INFO(ICE_FLOW_SEG_HDR_ARP, 18, ETH_ALEN),
122271651Skargl	/* ICE_FLOW_FIELD_IDX_ARP_OP */
123271651Skargl	ICE_FLOW_FLD_INFO(ICE_FLOW_SEG_HDR_ARP, 6, ICE_FLOW_FLD_SZ_ARP_OPER),
124271651Skargl	/* ICMP */
125271651Skargl	/* ICE_FLOW_FIELD_IDX_ICMP_TYPE */
126271651Skargl	ICE_FLOW_FLD_INFO(ICE_FLOW_SEG_HDR_ICMP, 0, ICE_FLOW_FLD_SZ_ICMP_TYPE),
127271651Skargl	/* ICE_FLOW_FIELD_IDX_ICMP_CODE */
128271651Skargl	ICE_FLOW_FLD_INFO(ICE_FLOW_SEG_HDR_ICMP, 1, ICE_FLOW_FLD_SZ_ICMP_CODE),
129271651Skargl	/* GRE */
130271651Skargl	/* ICE_FLOW_FIELD_IDX_GRE_KEYID */
131271651Skargl	ICE_FLOW_FLD_INFO(ICE_FLOW_SEG_HDR_GRE, 12, ICE_FLOW_FLD_SZ_GRE_KEYID),
132271651Skargl};
133271651Skargl
134271651Skargl/* Bitmaps indicating relevant packet types for a particular protocol header
135271651Skargl *
136271651Skargl * Packet types for packets with an Outer/First/Single MAC header
137271651Skargl */
138271651Skarglstatic const u32 ice_ptypes_mac_ofos[] = {
139271651Skargl	0xFDC00846, 0xBFBF7F7E, 0xF70001DF, 0xFEFDFDFB,
140271651Skargl	0x0000077E, 0x00000000, 0x00000000, 0x00000000,
141271651Skargl	0x00000000, 0x00000000, 0x00000000, 0x00000000,
142271651Skargl	0x00000000, 0x00000000, 0x00000000, 0x00000000,
143271651Skargl	0x00000000, 0x00000000, 0x00000000, 0x00000000,
144271651Skargl	0x00000000, 0x00000000, 0x00000000, 0x00000000,
145271651Skargl	0x00000000, 0x00000000, 0x00000000, 0x00000000,
146271651Skargl	0x00000000, 0x00000000, 0x00000000, 0x00000000,
147271651Skargl};
148271651Skargl
149271651Skargl/* Packet types for packets with an Innermost/Last MAC VLAN header */
150271651Skarglstatic const u32 ice_ptypes_macvlan_il[] = {
151271651Skargl	0x00000000, 0xBC000000, 0x000001DF, 0xF0000000,
152271651Skargl	0x0000077E, 0x00000000, 0x00000000, 0x00000000,
153271651Skargl	0x00000000, 0x00000000, 0x00000000, 0x00000000,
154271651Skargl	0x00000000, 0x00000000, 0x00000000, 0x00000000,
155271651Skargl	0x00000000, 0x00000000, 0x00000000, 0x00000000,
156271651Skargl	0x00000000, 0x00000000, 0x00000000, 0x00000000,
157271651Skargl	0x00000000, 0x00000000, 0x00000000, 0x00000000,
158271651Skargl	0x00000000, 0x00000000, 0x00000000, 0x00000000,
159271651Skargl};
160271651Skargl
161271651Skargl/* Packet types for packets with an Outer/First/Single non-frag IPv4 header,
162271651Skargl * does NOT include IPV4 other PTYPEs
163271651Skargl */
164271651Skarglstatic const u32 ice_ptypes_ipv4_ofos[] = {
165271651Skargl	0x1D800000, 0x04000800, 0x00000000, 0x00000000,
166271651Skargl	0x00000000, 0x00000000, 0x00000000, 0x00000000,
167271651Skargl	0x00000000, 0x00000000, 0x00000000, 0x00000000,
168271651Skargl	0x00000000, 0x00000000, 0x00000000, 0x00000000,
169271651Skargl	0x00000000, 0x00000000, 0x00000000, 0x00000000,
170271651Skargl	0x00000000, 0x00000000, 0x00000000, 0x00000000,
171271651Skargl	0x00000000, 0x00000000, 0x00000000, 0x00000000,
172271651Skargl	0x00000000, 0x00000000, 0x00000000, 0x00000000,
173271651Skargl};
174271651Skargl
175271651Skargl/* Packet types for packets with an Outer/First/Single non-frag IPv4 header,
176271651Skargl * includes IPV4 other PTYPEs
177271651Skargl */
178271651Skarglstatic const u32 ice_ptypes_ipv4_ofos_all[] = {
179271651Skargl	0x1D800000, 0x04000800, 0x00000000, 0x00000000,
180271651Skargl	0x00000000, 0x00000000, 0x00000000, 0x00000000,
181271651Skargl	0x00000000, 0x00000000, 0x00000000, 0x00000000,
182271651Skargl	0x00000000, 0x00000000, 0x00000000, 0x00000000,
183271651Skargl	0x00000000, 0x00000000, 0x00000000, 0x00000000,
184271651Skargl	0x00000000, 0x00000000, 0x00000000, 0x00000000,
185271651Skargl	0x00000000, 0x00000000, 0x00000000, 0x00000000,
186271651Skargl	0x00000000, 0x00000000, 0x00000000, 0x00000000,
187271651Skargl};
188271651Skargl
189271651Skargl/* Packet types for packets with an Innermost/Last IPv4 header */
190271651Skarglstatic const u32 ice_ptypes_ipv4_il[] = {
191271651Skargl	0xE0000000, 0xB807700E, 0x80000003, 0xE01DC03B,
192271651Skargl	0x0000000E, 0x00000000, 0x00000000, 0x00000000,
193271651Skargl	0x00000000, 0x00000000, 0x00000000, 0x00000000,
194271651Skargl	0x00000000, 0x00000000, 0x00000000, 0x00000000,
195271651Skargl	0x00000000, 0x00000000, 0x00000000, 0x00000000,
196271651Skargl	0x00000000, 0x00000000, 0x00000000, 0x00000000,
197271651Skargl	0x00000000, 0x00000000, 0x00000000, 0x00000000,
198271651Skargl	0x00000000, 0x00000000, 0x00000000, 0x00000000,
199271651Skargl};
200271651Skargl
201271651Skargl/* Packet types for packets with an Outer/First/Single non-frag IPv6 header,
202271651Skargl * does NOT include IVP6 other PTYPEs
203271651Skargl */
204271651Skarglstatic const u32 ice_ptypes_ipv6_ofos[] = {
205271651Skargl	0x00000000, 0x00000000, 0x76000000, 0x10002000,
206271651Skargl	0x00000000, 0x00000000, 0x00000000, 0x00000000,
207271651Skargl	0x00000000, 0x00000000, 0x00000000, 0x00000000,
208271651Skargl	0x00000000, 0x00000000, 0x00000000, 0x00000000,
209271651Skargl	0x00000000, 0x00000000, 0x00000000, 0x00000000,
210271651Skargl	0x00000000, 0x00000000, 0x00000000, 0x00000000,
211271651Skargl	0x00000000, 0x00000000, 0x00000000, 0x00000000,
212271651Skargl	0x00000000, 0x00000000, 0x00000000, 0x00000000,
213271651Skargl};
214271651Skargl
215271651Skargl/* Packet types for packets with an Outer/First/Single non-frag IPv6 header,
216271651Skargl * includes IPV6 other PTYPEs
217271651Skargl */
218271651Skarglstatic const u32 ice_ptypes_ipv6_ofos_all[] = {
219271651Skargl	0x00000000, 0x00000000, 0x76000000, 0x10002000,
220271651Skargl	0x00000000, 0x00000000, 0x00000000, 0x00000000,
221284810Stijl	0x00000000, 0x00000000, 0x00000000, 0x00000000,
222284810Stijl	0x00000000, 0x00000000, 0x00000000, 0x00000000,
223271651Skargl	0x00000000, 0x00000000, 0x00000000, 0x00000000,
224271651Skargl	0x00000000, 0x00000000, 0x00000000, 0x00000000,
225271651Skargl	0x00000000, 0x00000000, 0x00000000, 0x00000000,
226271651Skargl	0x00000000, 0x00000000, 0x00000000, 0x00000000,
227271651Skargl};
228271651Skargl
229271651Skargl/* Packet types for packets with an Innermost/Last IPv6 header */
230271651Skarglstatic const u32 ice_ptypes_ipv6_il[] = {
231271651Skargl	0x00000000, 0x03B80770, 0x000001DC, 0x0EE00000,
232271651Skargl	0x00000770, 0x00000000, 0x00000000, 0x00000000,
233271651Skargl	0x00000000, 0x00000000, 0x00000000, 0x00000000,
234271651Skargl	0x00000000, 0x00000000, 0x00000000, 0x00000000,
235271651Skargl	0x00000000, 0x00000000, 0x00000000, 0x00000000,
236271651Skargl	0x00000000, 0x00000000, 0x00000000, 0x00000000,
237271651Skargl	0x00000000, 0x00000000, 0x00000000, 0x00000000,
238271651Skargl	0x00000000, 0x00000000, 0x00000000, 0x00000000,
239271651Skargl};
240271651Skargl
241271651Skargl/* Packet types for packets with an Outer/First/Single
242271651Skargl * non-frag IPv4 header - no L4
243271651Skargl */
244271651Skarglstatic const u32 ice_ptypes_ipv4_ofos_no_l4[] = {
245284810Stijl	0x10800000, 0x04000800, 0x00000000, 0x00000000,
246271651Skargl	0x00000000, 0x00000000, 0x00000000, 0x00000000,
247271651Skargl	0x00000000, 0x00000000, 0x00000000, 0x00000000,
248271651Skargl	0x00000000, 0x00000000, 0x00000000, 0x00000000,
249271651Skargl	0x00000000, 0x00000000, 0x00000000, 0x00000000,
250271651Skargl	0x00000000, 0x00000000, 0x00000000, 0x00000000,
251271651Skargl	0x00000000, 0x00000000, 0x00000000, 0x00000000,
252271651Skargl	0x00000000, 0x00000000, 0x00000000, 0x00000000,
253271651Skargl};
254271651Skargl
255284810Stijl/* Packet types for packets with an Innermost/Last IPv4 header - no L4 */
256271651Skarglstatic const u32 ice_ptypes_ipv4_il_no_l4[] = {
257271651Skargl	0x60000000, 0x18043008, 0x80000002, 0x6010c021,
258271651Skargl	0x00000008, 0x00000000, 0x00000000, 0x00000000,
259284810Stijl	0x00000000, 0x00000000, 0x00000000, 0x00000000,
260271651Skargl	0x00000000, 0x00000000, 0x00000000, 0x00000000,
261284810Stijl	0x00000000, 0x00000000, 0x00000000, 0x00000000,
262284810Stijl	0x00000000, 0x00000000, 0x00000000, 0x00000000,
263271651Skargl	0x00000000, 0x00000000, 0x00000000, 0x00000000,
264271651Skargl	0x00000000, 0x00000000, 0x00000000, 0x00000000,
265271651Skargl};
266284810Stijl
267284810Stijl/* Packet types for packets with an Outer/First/Single
268284810Stijl * non-frag IPv6 header - no L4
269284810Stijl */
270284810Stijlstatic const u32 ice_ptypes_ipv6_ofos_no_l4[] = {
271284810Stijl	0x00000000, 0x00000000, 0x42000000, 0x10002000,
272271651Skargl	0x00000000, 0x00000000, 0x00000000, 0x00000000,
273284810Stijl	0x00000000, 0x00000000, 0x00000000, 0x00000000,
274284810Stijl	0x00000000, 0x00000000, 0x00000000, 0x00000000,
275271651Skargl	0x00000000, 0x00000000, 0x00000000, 0x00000000,
276284810Stijl	0x00000000, 0x00000000, 0x00000000, 0x00000000,
277284810Stijl	0x00000000, 0x00000000, 0x00000000, 0x00000000,
278271651Skargl	0x00000000, 0x00000000, 0x00000000, 0x00000000,
279271651Skargl};
280271651Skargl
281271651Skargl/* Packet types for packets with an Innermost/Last IPv6 header - no L4 */
282271651Skarglstatic const u32 ice_ptypes_ipv6_il_no_l4[] = {
283271651Skargl	0x00000000, 0x02180430, 0x0000010c, 0x086010c0,
284271651Skargl	0x00000430, 0x00000000, 0x00000000, 0x00000000,
285271651Skargl	0x00000000, 0x00000000, 0x00000000, 0x00000000,
286284810Stijl	0x00000000, 0x00000000, 0x00000000, 0x00000000,
287284810Stijl	0x00000000, 0x00000000, 0x00000000, 0x00000000,
288271651Skargl	0x00000000, 0x00000000, 0x00000000, 0x00000000,
289284810Stijl	0x00000000, 0x00000000, 0x00000000, 0x00000000,
290284810Stijl	0x00000000, 0x00000000, 0x00000000, 0x00000000,
291284810Stijl};
292284810Stijl
293284810Stijl/* Packet types for packets with an Outermost/First ARP header */
294284810Stijlstatic const u32 ice_ptypes_arp_of[] = {
295284810Stijl	0x00000800, 0x00000000, 0x00000000, 0x00000000,
296284810Stijl	0x00000000, 0x00000000, 0x00000000, 0x00000000,
297284810Stijl	0x00000000, 0x00000000, 0x00000000, 0x00000000,
298284810Stijl	0x00000000, 0x00000000, 0x00000000, 0x00000000,
299284810Stijl	0x00000000, 0x00000000, 0x00000000, 0x00000000,
300284810Stijl	0x00000000, 0x00000000, 0x00000000, 0x00000000,
301284810Stijl	0x00000000, 0x00000000, 0x00000000, 0x00000000,
302284810Stijl	0x00000000, 0x00000000, 0x00000000, 0x00000000,
303284810Stijl};
304284810Stijl
305284810Stijl/* UDP Packet types for non-tunneled packets or tunneled
306271651Skargl * packets with inner UDP.
307271651Skargl */
308284810Stijlstatic const u32 ice_ptypes_udp_il[] = {
309284810Stijl	0x81000000, 0x20204040, 0x04000010, 0x80810102,
310271651Skargl	0x00000040, 0x00000000, 0x00000000, 0x00000000,
311271651Skargl	0x00000000, 0x00000000, 0x00000000, 0x00000000,
312271651Skargl	0x00000000, 0x00000000, 0x00000000, 0x00000000,
313271651Skargl	0x00000000, 0x00000000, 0x00000000, 0x00000000,
314271651Skargl	0x00000000, 0x00000000, 0x00000000, 0x00000000,
315271651Skargl	0x00000000, 0x00000000, 0x00000000, 0x00000000,
316271651Skargl	0x00000000, 0x00000000, 0x00000000, 0x00000000,
317271651Skargl};
318284810Stijl
319271651Skargl/* Packet types for packets with an Innermost/Last TCP header */
320271651Skarglstatic const u32 ice_ptypes_tcp_il[] = {
321271651Skargl	0x04000000, 0x80810102, 0x10000040, 0x02040408,
322271651Skargl	0x00000102, 0x00000000, 0x00000000, 0x00000000,
323284810Stijl	0x00000000, 0x00000000, 0x00000000, 0x00000000,
324271651Skargl	0x00000000, 0x00000000, 0x00000000, 0x00000000,
325271651Skargl	0x00000000, 0x00000000, 0x00000000, 0x00000000,
326271651Skargl	0x00000000, 0x00000000, 0x00000000, 0x00000000,
327284810Stijl	0x00000000, 0x00000000, 0x00000000, 0x00000000,
328271651Skargl	0x00000000, 0x00000000, 0x00000000, 0x00000000,
329271651Skargl};
330284810Stijl
331284810Stijl/* Packet types for packets with an Innermost/Last SCTP header */
332271651Skarglstatic const u32 ice_ptypes_sctp_il[] = {
333271651Skargl	0x08000000, 0x01020204, 0x20000081, 0x04080810,
334271651Skargl	0x00000204, 0x00000000, 0x00000000, 0x00000000,
335271651Skargl	0x00000000, 0x00000000, 0x00000000, 0x00000000,
336271651Skargl	0x00000000, 0x00000000, 0x00000000, 0x00000000,
337271651Skargl	0x00000000, 0x00000000, 0x00000000, 0x00000000,
338271651Skargl	0x00000000, 0x00000000, 0x00000000, 0x00000000,
339271651Skargl	0x00000000, 0x00000000, 0x00000000, 0x00000000,
340271651Skargl	0x00000000, 0x00000000, 0x00000000, 0x00000000,
341271651Skargl};
342271651Skargl
343271651Skargl/* Packet types for packets with an Outermost/First ICMP header */
344271651Skarglstatic const u32 ice_ptypes_icmp_of[] = {
345271651Skargl	0x10000000, 0x00000000, 0x00000000, 0x00000000,
346284810Stijl	0x00000000, 0x00000000, 0x00000000, 0x00000000,
347284810Stijl	0x00000000, 0x00000000, 0x00000000, 0x00000000,
348271651Skargl	0x00000000, 0x00000000, 0x00000000, 0x00000000,
349271651Skargl	0x00000000, 0x00000000, 0x00000000, 0x00000000,
350271651Skargl	0x00000000, 0x00000000, 0x00000000, 0x00000000,
351271651Skargl	0x00000000, 0x00000000, 0x00000000, 0x00000000,
352271651Skargl	0x00000000, 0x00000000, 0x00000000, 0x00000000,
353284810Stijl};
354271651Skargl
355271651Skargl/* Packet types for packets with an Innermost/Last ICMP header */
356271651Skarglstatic const u32 ice_ptypes_icmp_il[] = {
357271651Skargl	0x00000000, 0x02040408, 0x40000102, 0x08101020,
358271651Skargl	0x00000408, 0x00000000, 0x00000000, 0x00000000,
359	0x00000000, 0x00000000, 0x00000000, 0x00000000,
360	0x00000000, 0x00000000, 0x00000000, 0x00000000,
361	0x00000000, 0x00000000, 0x00000000, 0x00000000,
362	0x00000000, 0x00000000, 0x00000000, 0x00000000,
363	0x00000000, 0x00000000, 0x00000000, 0x00000000,
364	0x00000000, 0x00000000, 0x00000000, 0x00000000,
365};
366
367/* Packet types for packets with an Outermost/First GRE header */
368static const u32 ice_ptypes_gre_of[] = {
369	0x00000000, 0xBFBF7800, 0x000001DF, 0xFEFDE000,
370	0x0000017E, 0x00000000, 0x00000000, 0x00000000,
371	0x00000000, 0x00000000, 0x00000000, 0x00000000,
372	0x00000000, 0x00000000, 0x00000000, 0x00000000,
373	0x00000000, 0x00000000, 0x00000000, 0x00000000,
374	0x00000000, 0x00000000, 0x00000000, 0x00000000,
375	0x00000000, 0x00000000, 0x00000000, 0x00000000,
376	0x00000000, 0x00000000, 0x00000000, 0x00000000,
377};
378
379/* Packet types for packets with an Innermost/Last MAC header */
380static const u32 ice_ptypes_mac_il[] = {
381	0x00000000, 0x00000000, 0x00000000, 0x00000000,
382	0x00000000, 0x00000000, 0x00000000, 0x00000000,
383	0x00000000, 0x00000000, 0x00000000, 0x00000000,
384	0x00000000, 0x00000000, 0x00000000, 0x00000000,
385	0x00000000, 0x00000000, 0x00000000, 0x00000000,
386	0x00000000, 0x00000000, 0x00000000, 0x00000000,
387	0x00000000, 0x00000000, 0x00000000, 0x00000000,
388	0x00000000, 0x00000000, 0x00000000, 0x00000000,
389};
390
391/* Manage parameters and info. used during the creation of a flow profile */
392struct ice_flow_prof_params {
393	enum ice_block blk;
394	u16 entry_length; /* # of bytes formatted entry will require */
395	u8 es_cnt;
396	struct ice_flow_prof *prof;
397
398	/* For ACL, the es[0] will have the data of ICE_RX_MDID_PKT_FLAGS_15_0
399	 * This will give us the direction flags.
400	 */
401	struct ice_fv_word es[ICE_MAX_FV_WORDS];
402
403	ice_declare_bitmap(ptypes, ICE_FLOW_PTYPE_MAX);
404};
405
406#define ICE_FLOW_SEG_HDRS_L3_MASK	\
407	(ICE_FLOW_SEG_HDR_IPV4 | ICE_FLOW_SEG_HDR_IPV6 | ICE_FLOW_SEG_HDR_ARP)
408#define ICE_FLOW_SEG_HDRS_L4_MASK	\
409	(ICE_FLOW_SEG_HDR_ICMP | ICE_FLOW_SEG_HDR_TCP | ICE_FLOW_SEG_HDR_UDP | \
410	 ICE_FLOW_SEG_HDR_SCTP)
411/* mask for L4 protocols that are NOT part of IPv4/6 OTHER PTYPE groups */
412#define ICE_FLOW_SEG_HDRS_L4_MASK_NO_OTHER	\
413	(ICE_FLOW_SEG_HDR_TCP | ICE_FLOW_SEG_HDR_UDP | ICE_FLOW_SEG_HDR_SCTP)
414
415/**
416 * ice_flow_val_hdrs - validates packet segments for valid protocol headers
417 * @segs: array of one or more packet segments that describe the flow
418 * @segs_cnt: number of packet segments provided
419 */
420static enum ice_status
421ice_flow_val_hdrs(struct ice_flow_seg_info *segs, u8 segs_cnt)
422{
423	u8 i;
424
425	for (i = 0; i < segs_cnt; i++) {
426		/* Multiple L3 headers */
427		if (segs[i].hdrs & ICE_FLOW_SEG_HDRS_L3_MASK &&
428		    !ice_is_pow2(segs[i].hdrs & ICE_FLOW_SEG_HDRS_L3_MASK))
429			return ICE_ERR_PARAM;
430
431		/* Multiple L4 headers */
432		if (segs[i].hdrs & ICE_FLOW_SEG_HDRS_L4_MASK &&
433		    !ice_is_pow2(segs[i].hdrs & ICE_FLOW_SEG_HDRS_L4_MASK))
434			return ICE_ERR_PARAM;
435	}
436
437	return ICE_SUCCESS;
438}
439
440/**
441 * ice_flow_proc_seg_hdrs - process protocol headers present in pkt segments
442 * @params: information about the flow to be processed
443 *
444 * This function identifies the packet types associated with the protocol
445 * headers being present in packet segments of the specified flow profile.
446 */
447static enum ice_status
448ice_flow_proc_seg_hdrs(struct ice_flow_prof_params *params)
449{
450	struct ice_flow_prof *prof;
451	u8 i;
452
453	ice_memset(params->ptypes, 0xff, sizeof(params->ptypes),
454		   ICE_NONDMA_MEM);
455
456	prof = params->prof;
457
458	for (i = 0; i < params->prof->segs_cnt; i++) {
459		const ice_bitmap_t *src;
460		u32 hdrs;
461
462		hdrs = prof->segs[i].hdrs;
463
464		if (hdrs & ICE_FLOW_SEG_HDR_ETH) {
465			src = !i ? (const ice_bitmap_t *)ice_ptypes_mac_ofos :
466				(const ice_bitmap_t *)ice_ptypes_mac_il;
467			ice_and_bitmap(params->ptypes, params->ptypes, src,
468				       ICE_FLOW_PTYPE_MAX);
469		}
470
471		if (i && hdrs & ICE_FLOW_SEG_HDR_VLAN) {
472			src = (const ice_bitmap_t *)ice_ptypes_macvlan_il;
473			ice_and_bitmap(params->ptypes, params->ptypes, src,
474				       ICE_FLOW_PTYPE_MAX);
475		}
476
477		if (!i && hdrs & ICE_FLOW_SEG_HDR_ARP) {
478			ice_and_bitmap(params->ptypes, params->ptypes,
479				       (const ice_bitmap_t *)ice_ptypes_arp_of,
480				       ICE_FLOW_PTYPE_MAX);
481		}
482
483		if ((hdrs & ICE_FLOW_SEG_HDR_IPV4) &&
484		    (hdrs & ICE_FLOW_SEG_HDR_IPV_OTHER)) {
485			src = i ? (const ice_bitmap_t *)ice_ptypes_ipv4_il :
486				(const ice_bitmap_t *)ice_ptypes_ipv4_ofos_all;
487			ice_and_bitmap(params->ptypes, params->ptypes, src,
488				       ICE_FLOW_PTYPE_MAX);
489		} else if ((hdrs & ICE_FLOW_SEG_HDR_IPV6) &&
490			   (hdrs & ICE_FLOW_SEG_HDR_IPV_OTHER)) {
491			src = i ? (const ice_bitmap_t *)ice_ptypes_ipv6_il :
492				(const ice_bitmap_t *)ice_ptypes_ipv6_ofos_all;
493			ice_and_bitmap(params->ptypes, params->ptypes, src,
494				       ICE_FLOW_PTYPE_MAX);
495		} else if ((hdrs & ICE_FLOW_SEG_HDR_IPV4) &&
496			   !(hdrs & ICE_FLOW_SEG_HDRS_L4_MASK_NO_OTHER)) {
497			src = !i ? (const ice_bitmap_t *)ice_ptypes_ipv4_ofos_no_l4 :
498				(const ice_bitmap_t *)ice_ptypes_ipv4_il_no_l4;
499			ice_and_bitmap(params->ptypes, params->ptypes, src,
500				       ICE_FLOW_PTYPE_MAX);
501		} else if (hdrs & ICE_FLOW_SEG_HDR_IPV4) {
502			src = !i ? (const ice_bitmap_t *)ice_ptypes_ipv4_ofos :
503				(const ice_bitmap_t *)ice_ptypes_ipv4_il;
504			ice_and_bitmap(params->ptypes, params->ptypes, src,
505				       ICE_FLOW_PTYPE_MAX);
506		} else if ((hdrs & ICE_FLOW_SEG_HDR_IPV6) &&
507			   !(hdrs & ICE_FLOW_SEG_HDRS_L4_MASK_NO_OTHER)) {
508			src = !i ? (const ice_bitmap_t *)ice_ptypes_ipv6_ofos_no_l4 :
509				(const ice_bitmap_t *)ice_ptypes_ipv6_il_no_l4;
510			ice_and_bitmap(params->ptypes, params->ptypes, src,
511				       ICE_FLOW_PTYPE_MAX);
512		} else if (hdrs & ICE_FLOW_SEG_HDR_IPV6) {
513			src = !i ? (const ice_bitmap_t *)ice_ptypes_ipv6_ofos :
514				(const ice_bitmap_t *)ice_ptypes_ipv6_il;
515			ice_and_bitmap(params->ptypes, params->ptypes, src,
516				       ICE_FLOW_PTYPE_MAX);
517		}
518
519		if (hdrs & ICE_FLOW_SEG_HDR_UDP) {
520			src = (const ice_bitmap_t *)ice_ptypes_udp_il;
521			ice_and_bitmap(params->ptypes, params->ptypes, src,
522				       ICE_FLOW_PTYPE_MAX);
523		} else if (hdrs & ICE_FLOW_SEG_HDR_TCP) {
524			ice_and_bitmap(params->ptypes, params->ptypes,
525				       (const ice_bitmap_t *)ice_ptypes_tcp_il,
526				       ICE_FLOW_PTYPE_MAX);
527		} else if (hdrs & ICE_FLOW_SEG_HDR_SCTP) {
528			src = (const ice_bitmap_t *)ice_ptypes_sctp_il;
529			ice_and_bitmap(params->ptypes, params->ptypes, src,
530				       ICE_FLOW_PTYPE_MAX);
531		}
532
533		if (hdrs & ICE_FLOW_SEG_HDR_ICMP) {
534			src = !i ? (const ice_bitmap_t *)ice_ptypes_icmp_of :
535				(const ice_bitmap_t *)ice_ptypes_icmp_il;
536			ice_and_bitmap(params->ptypes, params->ptypes, src,
537				       ICE_FLOW_PTYPE_MAX);
538		} else if (hdrs & ICE_FLOW_SEG_HDR_GRE) {
539			if (!i) {
540				src = (const ice_bitmap_t *)ice_ptypes_gre_of;
541				ice_and_bitmap(params->ptypes, params->ptypes,
542					       src, ICE_FLOW_PTYPE_MAX);
543			}
544		}
545	}
546
547	return ICE_SUCCESS;
548}
549
550/**
551 * ice_flow_xtract_fld - Create an extraction sequence entry for the given field
552 * @hw: pointer to the HW struct
553 * @params: information about the flow to be processed
554 * @seg: packet segment index of the field to be extracted
555 * @fld: ID of field to be extracted
556 *
557 * This function determines the protocol ID, offset, and size of the given
558 * field. It then allocates one or more extraction sequence entries for the
559 * given field, and fill the entries with protocol ID and offset information.
560 */
561static enum ice_status
562ice_flow_xtract_fld(struct ice_hw *hw, struct ice_flow_prof_params *params,
563		    u8 seg, enum ice_flow_field fld)
564{
565	enum ice_flow_field sib = ICE_FLOW_FIELD_IDX_MAX;
566	u8 fv_words = (u8)hw->blk[params->blk].es.fvw;
567	enum ice_prot_id prot_id = ICE_PROT_ID_INVAL;
568	struct ice_flow_fld_info *flds;
569	u16 cnt, ese_bits, i;
570	u16 off;
571
572	flds = params->prof->segs[seg].fields;
573
574	switch (fld) {
575	case ICE_FLOW_FIELD_IDX_ETH_DA:
576	case ICE_FLOW_FIELD_IDX_ETH_SA:
577	case ICE_FLOW_FIELD_IDX_S_VLAN:
578	case ICE_FLOW_FIELD_IDX_C_VLAN:
579		prot_id = seg == 0 ? ICE_PROT_MAC_OF_OR_S : ICE_PROT_MAC_IL;
580		break;
581	case ICE_FLOW_FIELD_IDX_ETH_TYPE:
582		prot_id = seg == 0 ? ICE_PROT_ETYPE_OL : ICE_PROT_ETYPE_IL;
583		break;
584	case ICE_FLOW_FIELD_IDX_IPV4_DSCP:
585		prot_id = seg == 0 ? ICE_PROT_IPV4_OF_OR_S : ICE_PROT_IPV4_IL;
586		break;
587	case ICE_FLOW_FIELD_IDX_IPV6_DSCP:
588		prot_id = seg == 0 ? ICE_PROT_IPV6_OF_OR_S : ICE_PROT_IPV6_IL;
589		break;
590	case ICE_FLOW_FIELD_IDX_IPV4_TTL:
591	case ICE_FLOW_FIELD_IDX_IPV4_PROT:
592		prot_id = seg == 0 ? ICE_PROT_IPV4_OF_OR_S : ICE_PROT_IPV4_IL;
593		/* TTL and PROT share the same extraction seq. entry.
594		 * Each is considered a sibling to the other in terms of sharing
595		 * the same extraction sequence entry.
596		 */
597		if (fld == ICE_FLOW_FIELD_IDX_IPV4_TTL)
598			sib = ICE_FLOW_FIELD_IDX_IPV4_PROT;
599		else
600			sib = ICE_FLOW_FIELD_IDX_IPV4_TTL;
601		break;
602	case ICE_FLOW_FIELD_IDX_IPV6_TTL:
603	case ICE_FLOW_FIELD_IDX_IPV6_PROT:
604		prot_id = seg == 0 ? ICE_PROT_IPV6_OF_OR_S : ICE_PROT_IPV6_IL;
605		/* TTL and PROT share the same extraction seq. entry.
606		 * Each is considered a sibling to the other in terms of sharing
607		 * the same extraction sequence entry.
608		 */
609		if (fld == ICE_FLOW_FIELD_IDX_IPV6_TTL)
610			sib = ICE_FLOW_FIELD_IDX_IPV6_PROT;
611		else
612			sib = ICE_FLOW_FIELD_IDX_IPV6_TTL;
613		break;
614	case ICE_FLOW_FIELD_IDX_IPV4_SA:
615	case ICE_FLOW_FIELD_IDX_IPV4_DA:
616		prot_id = seg == 0 ? ICE_PROT_IPV4_OF_OR_S : ICE_PROT_IPV4_IL;
617		break;
618	case ICE_FLOW_FIELD_IDX_IPV6_SA:
619	case ICE_FLOW_FIELD_IDX_IPV6_DA:
620		prot_id = seg == 0 ? ICE_PROT_IPV6_OF_OR_S : ICE_PROT_IPV6_IL;
621		break;
622	case ICE_FLOW_FIELD_IDX_TCP_SRC_PORT:
623	case ICE_FLOW_FIELD_IDX_TCP_DST_PORT:
624	case ICE_FLOW_FIELD_IDX_TCP_FLAGS:
625		prot_id = ICE_PROT_TCP_IL;
626		break;
627	case ICE_FLOW_FIELD_IDX_UDP_SRC_PORT:
628	case ICE_FLOW_FIELD_IDX_UDP_DST_PORT:
629		prot_id = ICE_PROT_UDP_IL_OR_S;
630		break;
631	case ICE_FLOW_FIELD_IDX_SCTP_SRC_PORT:
632	case ICE_FLOW_FIELD_IDX_SCTP_DST_PORT:
633		prot_id = ICE_PROT_SCTP_IL;
634		break;
635	case ICE_FLOW_FIELD_IDX_ARP_SIP:
636	case ICE_FLOW_FIELD_IDX_ARP_DIP:
637	case ICE_FLOW_FIELD_IDX_ARP_SHA:
638	case ICE_FLOW_FIELD_IDX_ARP_DHA:
639	case ICE_FLOW_FIELD_IDX_ARP_OP:
640		prot_id = ICE_PROT_ARP_OF;
641		break;
642	case ICE_FLOW_FIELD_IDX_ICMP_TYPE:
643	case ICE_FLOW_FIELD_IDX_ICMP_CODE:
644		/* ICMP type and code share the same extraction seq. entry */
645		prot_id = (params->prof->segs[seg].hdrs & ICE_FLOW_SEG_HDR_IPV4) ?
646			ICE_PROT_ICMP_IL : ICE_PROT_ICMPV6_IL;
647		sib = fld == ICE_FLOW_FIELD_IDX_ICMP_TYPE ?
648			ICE_FLOW_FIELD_IDX_ICMP_CODE :
649			ICE_FLOW_FIELD_IDX_ICMP_TYPE;
650		break;
651	case ICE_FLOW_FIELD_IDX_GRE_KEYID:
652		prot_id = ICE_PROT_GRE_OF;
653		break;
654	default:
655		return ICE_ERR_NOT_IMPL;
656	}
657
658	/* Each extraction sequence entry is a word in size, and extracts a
659	 * word-aligned offset from a protocol header.
660	 */
661	ese_bits = ICE_FLOW_FV_EXTRACT_SZ * BITS_PER_BYTE;
662
663	flds[fld].xtrct.prot_id = (u8)prot_id;
664	flds[fld].xtrct.off = (ice_flds_info[fld].off / ese_bits) *
665		ICE_FLOW_FV_EXTRACT_SZ;
666	flds[fld].xtrct.disp = (u8)(ice_flds_info[fld].off % ese_bits);
667	flds[fld].xtrct.idx = params->es_cnt;
668
669	/* Adjust the next field-entry index after accommodating the number of
670	 * entries this field consumes
671	 */
672	cnt = DIVIDE_AND_ROUND_UP(flds[fld].xtrct.disp +
673				  ice_flds_info[fld].size, ese_bits);
674
675	/* Fill in the extraction sequence entries needed for this field */
676	off = flds[fld].xtrct.off;
677	for (i = 0; i < cnt; i++) {
678		/* Only consume an extraction sequence entry if there is no
679		 * sibling field associated with this field or the sibling entry
680		 * already extracts the word shared with this field.
681		 */
682		if (sib == ICE_FLOW_FIELD_IDX_MAX ||
683		    flds[sib].xtrct.prot_id == ICE_PROT_ID_INVAL ||
684		    flds[sib].xtrct.off != off) {
685			u8 idx;
686
687			/* Make sure the number of extraction sequence required
688			 * does not exceed the block's capability
689			 */
690			if (params->es_cnt >= fv_words)
691				return ICE_ERR_MAX_LIMIT;
692
693			/* some blocks require a reversed field vector layout */
694			if (hw->blk[params->blk].es.reverse)
695				idx = fv_words - params->es_cnt - 1;
696			else
697				idx = params->es_cnt;
698
699			params->es[idx].prot_id = (u8)prot_id;
700			params->es[idx].off = off;
701			params->es_cnt++;
702		}
703
704		off += ICE_FLOW_FV_EXTRACT_SZ;
705	}
706
707	return ICE_SUCCESS;
708}
709
710/**
711 * ice_flow_create_xtrct_seq - Create an extraction sequence for given segments
712 * @hw: pointer to the HW struct
713 * @params: information about the flow to be processed
714 *
715 * This function iterates through all matched fields in the given segments, and
716 * creates an extraction sequence for the fields.
717 */
718static enum ice_status
719ice_flow_create_xtrct_seq(struct ice_hw *hw,
720			  struct ice_flow_prof_params *params)
721{
722	enum ice_status status = ICE_SUCCESS;
723	u8 i;
724
725	for (i = 0; i < params->prof->segs_cnt; i++) {
726		ice_declare_bitmap(match, ICE_FLOW_FIELD_IDX_MAX);
727		enum ice_flow_field j;
728
729		ice_cp_bitmap(match, params->prof->segs[i].match,
730			      ICE_FLOW_FIELD_IDX_MAX);
731		ice_for_each_set_bit(j, match, ICE_FLOW_FIELD_IDX_MAX) {
732			status = ice_flow_xtract_fld(hw, params, i, j);
733			if (status)
734				return status;
735			ice_clear_bit(j, match);
736		}
737	}
738
739	return status;
740}
741
742/**
743 * ice_flow_proc_segs - process all packet segments associated with a profile
744 * @hw: pointer to the HW struct
745 * @params: information about the flow to be processed
746 */
747static enum ice_status
748ice_flow_proc_segs(struct ice_hw *hw, struct ice_flow_prof_params *params)
749{
750	enum ice_status status;
751
752	status = ice_flow_proc_seg_hdrs(params);
753	if (status)
754		return status;
755
756	status = ice_flow_create_xtrct_seq(hw, params);
757	if (status)
758		return status;
759
760	switch (params->blk) {
761	case ICE_BLK_RSS:
762		status = ICE_SUCCESS;
763		break;
764	default:
765		return ICE_ERR_NOT_IMPL;
766	}
767
768	return status;
769}
770
771#define ICE_FLOW_FIND_PROF_CHK_FLDS	0x00000001
772#define ICE_FLOW_FIND_PROF_CHK_VSI	0x00000002
773#define ICE_FLOW_FIND_PROF_NOT_CHK_DIR	0x00000004
774
775/**
776 * ice_flow_find_prof_conds - Find a profile matching headers and conditions
777 * @hw: pointer to the HW struct
778 * @blk: classification stage
779 * @dir: flow direction
780 * @segs: array of one or more packet segments that describe the flow
781 * @segs_cnt: number of packet segments provided
782 * @vsi_handle: software VSI handle to check VSI (ICE_FLOW_FIND_PROF_CHK_VSI)
783 * @conds: additional conditions to be checked (ICE_FLOW_FIND_PROF_CHK_*)
784 */
785static struct ice_flow_prof *
786ice_flow_find_prof_conds(struct ice_hw *hw, enum ice_block blk,
787			 enum ice_flow_dir dir, struct ice_flow_seg_info *segs,
788			 u8 segs_cnt, u16 vsi_handle, u32 conds)
789{
790	struct ice_flow_prof *p, *prof = NULL;
791
792	ice_acquire_lock(&hw->fl_profs_locks[blk]);
793	LIST_FOR_EACH_ENTRY(p, &hw->fl_profs[blk], ice_flow_prof, l_entry)
794		if ((p->dir == dir || conds & ICE_FLOW_FIND_PROF_NOT_CHK_DIR) &&
795		    segs_cnt && segs_cnt == p->segs_cnt) {
796			u8 i;
797
798			/* Check for profile-VSI association if specified */
799			if ((conds & ICE_FLOW_FIND_PROF_CHK_VSI) &&
800			    ice_is_vsi_valid(hw, vsi_handle) &&
801			    !ice_is_bit_set(p->vsis, vsi_handle))
802				continue;
803
804			/* Protocol headers must be checked. Matched fields are
805			 * checked if specified.
806			 */
807			for (i = 0; i < segs_cnt; i++)
808				if (segs[i].hdrs != p->segs[i].hdrs ||
809				    ((conds & ICE_FLOW_FIND_PROF_CHK_FLDS) &&
810				     (ice_cmp_bitmap(segs[i].match,
811						     p->segs[i].match,
812						     ICE_FLOW_FIELD_IDX_MAX) ==
813				       false)))
814					break;
815
816			/* A match is found if all segments are matched */
817			if (i == segs_cnt) {
818				prof = p;
819				break;
820			}
821		}
822	ice_release_lock(&hw->fl_profs_locks[blk]);
823
824	return prof;
825}
826
827/**
828 * ice_flow_find_prof - Look up a profile matching headers and matched fields
829 * @hw: pointer to the HW struct
830 * @blk: classification stage
831 * @dir: flow direction
832 * @segs: array of one or more packet segments that describe the flow
833 * @segs_cnt: number of packet segments provided
834 */
835u64
836ice_flow_find_prof(struct ice_hw *hw, enum ice_block blk, enum ice_flow_dir dir,
837		   struct ice_flow_seg_info *segs, u8 segs_cnt)
838{
839	struct ice_flow_prof *p;
840
841	p = ice_flow_find_prof_conds(hw, blk, dir, segs, segs_cnt,
842				     ICE_MAX_VSI, ICE_FLOW_FIND_PROF_CHK_FLDS);
843
844	return p ? p->id : ICE_FLOW_PROF_ID_INVAL;
845}
846
847/**
848 * ice_flow_find_prof_id - Look up a profile with given profile ID
849 * @hw: pointer to the HW struct
850 * @blk: classification stage
851 * @prof_id: unique ID to identify this flow profile
852 */
853static struct ice_flow_prof *
854ice_flow_find_prof_id(struct ice_hw *hw, enum ice_block blk, u64 prof_id)
855{
856	struct ice_flow_prof *p;
857
858	LIST_FOR_EACH_ENTRY(p, &hw->fl_profs[blk], ice_flow_prof, l_entry)
859		if (p->id == prof_id)
860			return p;
861
862	return NULL;
863}
864
865/**
866 * ice_flow_get_hw_prof - return the HW profile for a specific profile ID handle
867 * @hw: pointer to the HW struct
868 * @blk: classification stage
869 * @prof_id: the profile ID handle
870 * @hw_prof_id: pointer to variable to receive the HW profile ID
871 */
872enum ice_status
873ice_flow_get_hw_prof(struct ice_hw *hw, enum ice_block blk, u64 prof_id,
874		     u8 *hw_prof_id)
875{
876	enum ice_status status = ICE_ERR_DOES_NOT_EXIST;
877	struct ice_prof_map *map;
878
879	ice_acquire_lock(&hw->blk[blk].es.prof_map_lock);
880	map = ice_search_prof_id(hw, blk, prof_id);
881	if (map) {
882		*hw_prof_id = map->prof_id;
883		status = ICE_SUCCESS;
884	}
885	ice_release_lock(&hw->blk[blk].es.prof_map_lock);
886	return status;
887}
888
889/**
890 * ice_flow_add_prof_sync - Add a flow profile for packet segments and fields
891 * @hw: pointer to the HW struct
892 * @blk: classification stage
893 * @dir: flow direction
894 * @prof_id: unique ID to identify this flow profile
895 * @segs: array of one or more packet segments that describe the flow
896 * @segs_cnt: number of packet segments provided
897 * @acts: array of default actions
898 * @acts_cnt: number of default actions
899 * @prof: stores the returned flow profile added
900 *
901 * Assumption: the caller has acquired the lock to the profile list
902 */
903static enum ice_status
904ice_flow_add_prof_sync(struct ice_hw *hw, enum ice_block blk,
905		       enum ice_flow_dir dir, u64 prof_id,
906		       struct ice_flow_seg_info *segs, u8 segs_cnt,
907		       struct ice_flow_action *acts, u8 acts_cnt,
908		       struct ice_flow_prof **prof)
909{
910	struct ice_flow_prof_params *params;
911	enum ice_status status;
912	u8 i;
913
914	if (!prof || (acts_cnt && !acts))
915		return ICE_ERR_BAD_PTR;
916
917	params = (struct ice_flow_prof_params *)ice_malloc(hw, sizeof(*params));
918	if (!params)
919		return ICE_ERR_NO_MEMORY;
920
921	params->prof = (struct ice_flow_prof *)
922		ice_malloc(hw, sizeof(*params->prof));
923	if (!params->prof) {
924		status = ICE_ERR_NO_MEMORY;
925		goto free_params;
926	}
927
928	/* initialize extraction sequence to all invalid (0xff) */
929	for (i = 0; i < ICE_MAX_FV_WORDS; i++) {
930		params->es[i].prot_id = ICE_PROT_INVALID;
931		params->es[i].off = ICE_FV_OFFSET_INVAL;
932	}
933
934	params->blk = blk;
935	params->prof->id = prof_id;
936	params->prof->dir = dir;
937	params->prof->segs_cnt = segs_cnt;
938
939	/* Make a copy of the segments that need to be persistent in the flow
940	 * profile instance
941	 */
942	for (i = 0; i < segs_cnt; i++)
943		ice_memcpy(&params->prof->segs[i], &segs[i], sizeof(*segs),
944			   ICE_NONDMA_TO_NONDMA);
945
946	status = ice_flow_proc_segs(hw, params);
947	if (status) {
948		ice_debug(hw, ICE_DBG_FLOW, "Error processing a flow's packet segments\n");
949		goto out;
950	}
951
952	/* Add a HW profile for this flow profile */
953	status = ice_add_prof(hw, blk, prof_id, params->ptypes, params->es);
954	if (status) {
955		ice_debug(hw, ICE_DBG_FLOW, "Error adding a HW flow profile\n");
956		goto out;
957	}
958
959	*prof = params->prof;
960
961out:
962	if (status) {
963		ice_free(hw, params->prof);
964	}
965free_params:
966	ice_free(hw, params);
967
968	return status;
969}
970
971/**
972 * ice_flow_rem_prof_sync - remove a flow profile
973 * @hw: pointer to the hardware structure
974 * @blk: classification stage
975 * @prof: pointer to flow profile to remove
976 *
977 * Assumption: the caller has acquired the lock to the profile list
978 */
979static enum ice_status
980ice_flow_rem_prof_sync(struct ice_hw *hw, enum ice_block blk,
981		       struct ice_flow_prof *prof)
982{
983	enum ice_status status;
984
985	/* Remove all hardware profiles associated with this flow profile */
986	status = ice_rem_prof(hw, blk, prof->id);
987	if (!status) {
988		LIST_DEL(&prof->l_entry);
989		ice_free(hw, prof);
990	}
991
992	return status;
993}
994
995/**
996 * ice_flow_assoc_vsig_vsi - associate a VSI with VSIG
997 * @hw: pointer to the hardware structure
998 * @blk: classification stage
999 * @vsi_handle: software VSI handle
1000 * @vsig: target VSI group
1001 *
1002 * Assumption: the caller has already verified that the VSI to
1003 * be added has the same characteristics as the VSIG and will
1004 * thereby have access to all resources added to that VSIG.
1005 */
1006enum ice_status
1007ice_flow_assoc_vsig_vsi(struct ice_hw *hw, enum ice_block blk, u16 vsi_handle,
1008			u16 vsig)
1009{
1010	enum ice_status status;
1011
1012	if (!ice_is_vsi_valid(hw, vsi_handle) || blk >= ICE_BLK_COUNT)
1013		return ICE_ERR_PARAM;
1014
1015	ice_acquire_lock(&hw->fl_profs_locks[blk]);
1016	status = ice_add_vsi_flow(hw, blk, ice_get_hw_vsi_num(hw, vsi_handle),
1017				  vsig);
1018	ice_release_lock(&hw->fl_profs_locks[blk]);
1019
1020	return status;
1021}
1022
1023/**
1024 * ice_flow_assoc_prof - associate a VSI with a flow profile
1025 * @hw: pointer to the hardware structure
1026 * @blk: classification stage
1027 * @prof: pointer to flow profile
1028 * @vsi_handle: software VSI handle
1029 *
1030 * Assumption: the caller has acquired the lock to the profile list
1031 * and the software VSI handle has been validated
1032 */
1033static enum ice_status
1034ice_flow_assoc_prof(struct ice_hw *hw, enum ice_block blk,
1035		    struct ice_flow_prof *prof, u16 vsi_handle)
1036{
1037	enum ice_status status = ICE_SUCCESS;
1038
1039	if (!ice_is_bit_set(prof->vsis, vsi_handle)) {
1040		status = ice_add_prof_id_flow(hw, blk,
1041					      ice_get_hw_vsi_num(hw,
1042								 vsi_handle),
1043					      prof->id);
1044		if (!status)
1045			ice_set_bit(vsi_handle, prof->vsis);
1046		else
1047			ice_debug(hw, ICE_DBG_FLOW, "HW profile add failed, %d\n",
1048				  status);
1049	}
1050
1051	return status;
1052}
1053
1054/**
1055 * ice_flow_disassoc_prof - disassociate a VSI from a flow profile
1056 * @hw: pointer to the hardware structure
1057 * @blk: classification stage
1058 * @prof: pointer to flow profile
1059 * @vsi_handle: software VSI handle
1060 *
1061 * Assumption: the caller has acquired the lock to the profile list
1062 * and the software VSI handle has been validated
1063 */
1064static enum ice_status
1065ice_flow_disassoc_prof(struct ice_hw *hw, enum ice_block blk,
1066		       struct ice_flow_prof *prof, u16 vsi_handle)
1067{
1068	enum ice_status status = ICE_SUCCESS;
1069
1070	if (ice_is_bit_set(prof->vsis, vsi_handle)) {
1071		status = ice_rem_prof_id_flow(hw, blk,
1072					      ice_get_hw_vsi_num(hw,
1073								 vsi_handle),
1074					      prof->id);
1075		if (!status)
1076			ice_clear_bit(vsi_handle, prof->vsis);
1077		else
1078			ice_debug(hw, ICE_DBG_FLOW, "HW profile remove failed, %d\n",
1079				  status);
1080	}
1081
1082	return status;
1083}
1084
1085/**
1086 * ice_flow_add_prof - Add a flow profile for packet segments and matched fields
1087 * @hw: pointer to the HW struct
1088 * @blk: classification stage
1089 * @dir: flow direction
1090 * @prof_id: unique ID to identify this flow profile
1091 * @segs: array of one or more packet segments that describe the flow
1092 * @segs_cnt: number of packet segments provided
1093 * @acts: array of default actions
1094 * @acts_cnt: number of default actions
1095 * @prof: stores the returned flow profile added
1096 */
1097static enum ice_status
1098ice_flow_add_prof(struct ice_hw *hw, enum ice_block blk, enum ice_flow_dir dir,
1099		  u64 prof_id, struct ice_flow_seg_info *segs, u8 segs_cnt,
1100		  struct ice_flow_action *acts, u8 acts_cnt,
1101		  struct ice_flow_prof **prof)
1102{
1103	enum ice_status status;
1104
1105	if (segs_cnt > ICE_FLOW_SEG_MAX)
1106		return ICE_ERR_MAX_LIMIT;
1107
1108	if (!segs_cnt)
1109		return ICE_ERR_PARAM;
1110
1111	if (!segs)
1112		return ICE_ERR_BAD_PTR;
1113
1114	status = ice_flow_val_hdrs(segs, segs_cnt);
1115	if (status)
1116		return status;
1117
1118	ice_acquire_lock(&hw->fl_profs_locks[blk]);
1119
1120	status = ice_flow_add_prof_sync(hw, blk, dir, prof_id, segs, segs_cnt,
1121					acts, acts_cnt, prof);
1122	if (!status)
1123		LIST_ADD(&(*prof)->l_entry, &hw->fl_profs[blk]);
1124
1125	ice_release_lock(&hw->fl_profs_locks[blk]);
1126
1127	return status;
1128}
1129
1130/**
1131 * ice_flow_rem_prof - Remove a flow profile and all entries associated with it
1132 * @hw: pointer to the HW struct
1133 * @blk: the block for which the flow profile is to be removed
1134 * @prof_id: unique ID of the flow profile to be removed
1135 */
1136static enum ice_status
1137ice_flow_rem_prof(struct ice_hw *hw, enum ice_block blk, u64 prof_id)
1138{
1139	struct ice_flow_prof *prof;
1140	enum ice_status status;
1141
1142	ice_acquire_lock(&hw->fl_profs_locks[blk]);
1143
1144	prof = ice_flow_find_prof_id(hw, blk, prof_id);
1145	if (!prof) {
1146		status = ICE_ERR_DOES_NOT_EXIST;
1147		goto out;
1148	}
1149
1150	/* prof becomes invalid after the call */
1151	status = ice_flow_rem_prof_sync(hw, blk, prof);
1152
1153out:
1154	ice_release_lock(&hw->fl_profs_locks[blk]);
1155
1156	return status;
1157}
1158
1159/**
1160 * ice_flow_set_fld_ext - specifies locations of field from entry's input buffer
1161 * @seg: packet segment the field being set belongs to
1162 * @fld: field to be set
1163 * @field_type: type of the field
1164 * @val_loc: if not ICE_FLOW_FLD_OFF_INVAL, location of the value to match from
1165 *           entry's input buffer
1166 * @mask_loc: if not ICE_FLOW_FLD_OFF_INVAL, location of mask value from entry's
1167 *            input buffer
1168 * @last_loc: if not ICE_FLOW_FLD_OFF_INVAL, location of last/upper value from
1169 *            entry's input buffer
1170 *
1171 * This helper function stores information of a field being matched, including
1172 * the type of the field and the locations of the value to match, the mask, and
1173 * the upper-bound value in the start of the input buffer for a flow entry.
1174 * This function should only be used for fixed-size data structures.
1175 *
1176 * This function also opportunistically determines the protocol headers to be
1177 * present based on the fields being set. Some fields cannot be used alone to
1178 * determine the protocol headers present. Sometimes, fields for particular
1179 * protocol headers are not matched. In those cases, the protocol headers
1180 * must be explicitly set.
1181 */
1182static void
1183ice_flow_set_fld_ext(struct ice_flow_seg_info *seg, enum ice_flow_field fld,
1184		     enum ice_flow_fld_match_type field_type, u16 val_loc,
1185		     u16 mask_loc, u16 last_loc)
1186{
1187	ice_set_bit(fld, seg->match);
1188	if (field_type == ICE_FLOW_FLD_TYPE_RANGE)
1189		ice_set_bit(fld, seg->range);
1190
1191	seg->fields[fld].type = field_type;
1192	seg->fields[fld].src.val = val_loc;
1193	seg->fields[fld].src.mask = mask_loc;
1194	seg->fields[fld].src.last = last_loc;
1195
1196	ICE_FLOW_SET_HDRS(seg, ice_flds_info[fld].hdr);
1197}
1198
1199/**
1200 * ice_flow_set_fld - specifies locations of field from entry's input buffer
1201 * @seg: packet segment the field being set belongs to
1202 * @fld: field to be set
1203 * @val_loc: if not ICE_FLOW_FLD_OFF_INVAL, location of the value to match from
1204 *           entry's input buffer
1205 * @mask_loc: if not ICE_FLOW_FLD_OFF_INVAL, location of mask value from entry's
1206 *            input buffer
1207 * @last_loc: if not ICE_FLOW_FLD_OFF_INVAL, location of last/upper value from
1208 *            entry's input buffer
1209 * @range: indicate if field being matched is to be in a range
1210 *
1211 * This function specifies the locations, in the form of byte offsets from the
1212 * start of the input buffer for a flow entry, from where the value to match,
1213 * the mask value, and upper value can be extracted. These locations are then
1214 * stored in the flow profile. When adding a flow entry associated with the
1215 * flow profile, these locations will be used to quickly extract the values and
1216 * create the content of a match entry. This function should only be used for
1217 * fixed-size data structures.
1218 */
1219static void
1220ice_flow_set_fld(struct ice_flow_seg_info *seg, enum ice_flow_field fld,
1221		 u16 val_loc, u16 mask_loc, u16 last_loc, bool range)
1222{
1223	enum ice_flow_fld_match_type t = range ?
1224		ICE_FLOW_FLD_TYPE_RANGE : ICE_FLOW_FLD_TYPE_REG;
1225
1226	ice_flow_set_fld_ext(seg, fld, t, val_loc, mask_loc, last_loc);
1227}
1228
1229/**
1230 * ice_flow_set_fld_prefix - sets locations of prefix field from entry's buf
1231 * @seg: packet segment the field being set belongs to
1232 * @fld: field to be set
1233 * @val_loc: if not ICE_FLOW_FLD_OFF_INVAL, location of the value to match from
1234 *           entry's input buffer
1235 * @pref_loc: location of prefix value from entry's input buffer
1236 * @pref_sz: size of the location holding the prefix value
1237 *
1238 * This function specifies the locations, in the form of byte offsets from the
1239 * start of the input buffer for a flow entry, from where the value to match
1240 * and the IPv4 prefix value can be extracted. These locations are then stored
1241 * in the flow profile. When adding flow entries to the associated flow profile,
1242 * these locations can be used to quickly extract the values to create the
1243 * content of a match entry. This function should only be used for fixed-size
1244 * data structures.
1245 */
1246void
1247ice_flow_set_fld_prefix(struct ice_flow_seg_info *seg, enum ice_flow_field fld,
1248			u16 val_loc, u16 pref_loc, u8 pref_sz)
1249{
1250	/* For this type of field, the "mask" location is for the prefix value's
1251	 * location and the "last" location is for the size of the location of
1252	 * the prefix value.
1253	 */
1254	ice_flow_set_fld_ext(seg, fld, ICE_FLOW_FLD_TYPE_PREFIX, val_loc,
1255			     pref_loc, (u16)pref_sz);
1256}
1257
1258#define ICE_FLOW_RSS_SEG_HDR_L3_MASKS \
1259	(ICE_FLOW_SEG_HDR_IPV4 | ICE_FLOW_SEG_HDR_IPV6)
1260
1261#define ICE_FLOW_RSS_SEG_HDR_L4_MASKS \
1262	(ICE_FLOW_SEG_HDR_TCP | ICE_FLOW_SEG_HDR_UDP | ICE_FLOW_SEG_HDR_SCTP)
1263
1264#define ICE_FLOW_RSS_SEG_HDR_VAL_MASKS \
1265	(ICE_FLOW_RSS_SEG_HDR_L3_MASKS | \
1266	 ICE_FLOW_RSS_SEG_HDR_L4_MASKS)
1267
1268/**
1269 * ice_flow_set_rss_seg_info - setup packet segments for RSS
1270 * @segs: pointer to the flow field segment(s)
1271 * @seg_cnt: segment count
1272 * @cfg: configure parameters
1273 *
1274 * Helper function to extract fields from hash bitmap and use flow
1275 * header value to set flow field segment for further use in flow
1276 * profile entry or removal.
1277 */
1278static enum ice_status
1279ice_flow_set_rss_seg_info(struct ice_flow_seg_info *segs, u8 seg_cnt,
1280			  const struct ice_rss_hash_cfg *cfg)
1281{
1282	struct ice_flow_seg_info *seg;
1283	u64 val;
1284	u16 i;
1285
1286	/* set inner most segment */
1287	seg = &segs[seg_cnt - 1];
1288
1289	ice_for_each_set_bit(i, (const ice_bitmap_t *)&cfg->hash_flds,
1290			     (u16)ICE_FLOW_FIELD_IDX_MAX)
1291		ice_flow_set_fld(seg, (enum ice_flow_field)i,
1292				 ICE_FLOW_FLD_OFF_INVAL, ICE_FLOW_FLD_OFF_INVAL,
1293				 ICE_FLOW_FLD_OFF_INVAL, false);
1294
1295	ICE_FLOW_SET_HDRS(seg, cfg->addl_hdrs);
1296
1297	/* set outer most header */
1298	if (cfg->hdr_type == ICE_RSS_INNER_HEADERS_W_OUTER_IPV4)
1299		segs[ICE_RSS_OUTER_HEADERS].hdrs |= ICE_FLOW_SEG_HDR_IPV4 |
1300						    ICE_FLOW_SEG_HDR_IPV_FRAG |
1301						    ICE_FLOW_SEG_HDR_IPV_OTHER;
1302	else if (cfg->hdr_type == ICE_RSS_INNER_HEADERS_W_OUTER_IPV6)
1303		segs[ICE_RSS_OUTER_HEADERS].hdrs |= ICE_FLOW_SEG_HDR_IPV6 |
1304						    ICE_FLOW_SEG_HDR_IPV_FRAG |
1305						    ICE_FLOW_SEG_HDR_IPV_OTHER;
1306	else if (cfg->hdr_type == ICE_RSS_INNER_HEADERS_W_OUTER_IPV4_GRE)
1307		segs[ICE_RSS_OUTER_HEADERS].hdrs |= ICE_FLOW_SEG_HDR_IPV4 |
1308						    ICE_FLOW_SEG_HDR_GRE |
1309						    ICE_FLOW_SEG_HDR_IPV_OTHER;
1310	else if (cfg->hdr_type == ICE_RSS_INNER_HEADERS_W_OUTER_IPV6_GRE)
1311		segs[ICE_RSS_OUTER_HEADERS].hdrs |= ICE_FLOW_SEG_HDR_IPV6 |
1312						    ICE_FLOW_SEG_HDR_GRE |
1313						    ICE_FLOW_SEG_HDR_IPV_OTHER;
1314
1315	if (seg->hdrs & ~ICE_FLOW_RSS_SEG_HDR_VAL_MASKS)
1316		return ICE_ERR_PARAM;
1317
1318	val = (u64)(seg->hdrs & ICE_FLOW_RSS_SEG_HDR_L3_MASKS);
1319	if (val && !ice_is_pow2(val))
1320		return ICE_ERR_CFG;
1321
1322	val = (u64)(seg->hdrs & ICE_FLOW_RSS_SEG_HDR_L4_MASKS);
1323	if (val && !ice_is_pow2(val))
1324		return ICE_ERR_CFG;
1325
1326	return ICE_SUCCESS;
1327}
1328
1329/**
1330 * ice_rem_vsi_rss_list - remove VSI from RSS list
1331 * @hw: pointer to the hardware structure
1332 * @vsi_handle: software VSI handle
1333 *
1334 * Remove the VSI from all RSS configurations in the list.
1335 */
1336void ice_rem_vsi_rss_list(struct ice_hw *hw, u16 vsi_handle)
1337{
1338	struct ice_rss_cfg *r, *tmp;
1339
1340	if (LIST_EMPTY(&hw->rss_list_head))
1341		return;
1342
1343	ice_acquire_lock(&hw->rss_locks);
1344	LIST_FOR_EACH_ENTRY_SAFE(r, tmp, &hw->rss_list_head,
1345				 ice_rss_cfg, l_entry)
1346		if (ice_test_and_clear_bit(vsi_handle, r->vsis))
1347			if (!ice_is_any_bit_set(r->vsis, ICE_MAX_VSI)) {
1348				LIST_DEL(&r->l_entry);
1349				ice_free(hw, r);
1350			}
1351	ice_release_lock(&hw->rss_locks);
1352}
1353
1354/**
1355 * ice_rem_vsi_rss_cfg - remove RSS configurations associated with VSI
1356 * @hw: pointer to the hardware structure
1357 * @vsi_handle: software VSI handle
1358 *
1359 * This function will iterate through all flow profiles and disassociate
1360 * the VSI from that profile. If the flow profile has no VSIs it will
1361 * be removed.
1362 */
1363enum ice_status ice_rem_vsi_rss_cfg(struct ice_hw *hw, u16 vsi_handle)
1364{
1365	const enum ice_block blk = ICE_BLK_RSS;
1366	struct ice_flow_prof *p, *t;
1367	enum ice_status status = ICE_SUCCESS;
1368	u16 vsig;
1369
1370	if (!ice_is_vsi_valid(hw, vsi_handle))
1371		return ICE_ERR_PARAM;
1372
1373	if (LIST_EMPTY(&hw->fl_profs[blk]))
1374		return ICE_SUCCESS;
1375
1376	ice_acquire_lock(&hw->rss_locks);
1377	LIST_FOR_EACH_ENTRY_SAFE(p, t, &hw->fl_profs[blk], ice_flow_prof,
1378				 l_entry) {
1379		int ret;
1380
1381		/* check if vsig is already removed */
1382		ret = ice_vsig_find_vsi(hw, blk,
1383					ice_get_hw_vsi_num(hw, vsi_handle),
1384					&vsig);
1385		if (!ret && !vsig)
1386			break;
1387
1388		if (ice_is_bit_set(p->vsis, vsi_handle)) {
1389			status = ice_flow_disassoc_prof(hw, blk, p, vsi_handle);
1390			if (status)
1391				break;
1392
1393			if (!ice_is_any_bit_set(p->vsis, ICE_MAX_VSI)) {
1394				status = ice_flow_rem_prof(hw, blk, p->id);
1395				if (status)
1396					break;
1397			}
1398		}
1399	}
1400	ice_release_lock(&hw->rss_locks);
1401
1402	return status;
1403}
1404
1405/**
1406 * ice_get_rss_hdr_type - get a RSS profile's header type
1407 * @prof: RSS flow profile
1408 */
1409static enum ice_rss_cfg_hdr_type
1410ice_get_rss_hdr_type(struct ice_flow_prof *prof)
1411{
1412	enum ice_rss_cfg_hdr_type hdr_type = ICE_RSS_ANY_HEADERS;
1413
1414	if (prof->segs_cnt == ICE_FLOW_SEG_SINGLE) {
1415		hdr_type = ICE_RSS_OUTER_HEADERS;
1416	} else if (prof->segs_cnt == ICE_FLOW_SEG_MAX) {
1417		const struct ice_flow_seg_info *s;
1418
1419		s = &prof->segs[ICE_RSS_OUTER_HEADERS];
1420		if (s->hdrs == ICE_FLOW_SEG_HDR_NONE)
1421			hdr_type = ICE_RSS_INNER_HEADERS;
1422		if (s->hdrs & ICE_FLOW_SEG_HDR_IPV4)
1423			hdr_type = ICE_RSS_INNER_HEADERS_W_OUTER_IPV4;
1424		if (s->hdrs & ICE_FLOW_SEG_HDR_IPV6)
1425			hdr_type = ICE_RSS_INNER_HEADERS_W_OUTER_IPV6;
1426	}
1427
1428	return hdr_type;
1429}
1430
1431/**
1432 * ice_rem_rss_list - remove RSS configuration from list
1433 * @hw: pointer to the hardware structure
1434 * @vsi_handle: software VSI handle
1435 * @prof: pointer to flow profile
1436 *
1437 * Assumption: lock has already been acquired for RSS list
1438 */
1439static void
1440ice_rem_rss_list(struct ice_hw *hw, u16 vsi_handle, struct ice_flow_prof *prof)
1441{
1442	enum ice_rss_cfg_hdr_type hdr_type;
1443	struct ice_rss_cfg *r, *tmp;
1444	u64 seg_match = 0;
1445	u16 i;
1446
1447	/* convert match bitmap to u64 for hash field comparison */
1448	ice_for_each_set_bit(i, prof->segs[prof->segs_cnt - 1].match,
1449			     ICE_FLOW_FIELD_IDX_MAX) {
1450		seg_match |= 1ULL << i;
1451	}
1452
1453	/* Search for RSS hash fields associated to the VSI that match the
1454	 * hash configurations associated to the flow profile. If found
1455	 * remove from the RSS entry list of the VSI context and delete entry.
1456	 */
1457	hdr_type = ice_get_rss_hdr_type(prof);
1458	LIST_FOR_EACH_ENTRY_SAFE(r, tmp, &hw->rss_list_head,
1459				 ice_rss_cfg, l_entry)
1460		if (r->hash.hash_flds == seg_match &&
1461		    r->hash.addl_hdrs == prof->segs[prof->segs_cnt - 1].hdrs &&
1462		    r->hash.hdr_type == hdr_type) {
1463			ice_clear_bit(vsi_handle, r->vsis);
1464			if (!ice_is_any_bit_set(r->vsis, ICE_MAX_VSI)) {
1465				LIST_DEL(&r->l_entry);
1466				ice_free(hw, r);
1467			}
1468			return;
1469		}
1470}
1471
1472/**
1473 * ice_add_rss_list - add RSS configuration to list
1474 * @hw: pointer to the hardware structure
1475 * @vsi_handle: software VSI handle
1476 * @prof: pointer to flow profile
1477 *
1478 * Assumption: lock has already been acquired for RSS list
1479 */
1480static enum ice_status
1481ice_add_rss_list(struct ice_hw *hw, u16 vsi_handle, struct ice_flow_prof *prof)
1482{
1483	enum ice_rss_cfg_hdr_type hdr_type;
1484	struct ice_rss_cfg *r, *rss_cfg;
1485	u64 seg_match = 0;
1486	u16 i;
1487
1488	ice_for_each_set_bit(i, prof->segs[prof->segs_cnt - 1].match,
1489			     ICE_FLOW_FIELD_IDX_MAX) {
1490		seg_match |= 1ULL << i;
1491	}
1492
1493	hdr_type = ice_get_rss_hdr_type(prof);
1494	LIST_FOR_EACH_ENTRY(r, &hw->rss_list_head,
1495			    ice_rss_cfg, l_entry)
1496		if (r->hash.hash_flds == seg_match &&
1497		    r->hash.addl_hdrs == prof->segs[prof->segs_cnt - 1].hdrs &&
1498		    r->hash.hdr_type == hdr_type) {
1499			ice_set_bit(vsi_handle, r->vsis);
1500			return ICE_SUCCESS;
1501		}
1502
1503	rss_cfg = (struct ice_rss_cfg *)ice_malloc(hw, sizeof(*rss_cfg));
1504	if (!rss_cfg)
1505		return ICE_ERR_NO_MEMORY;
1506
1507	rss_cfg->hash.hash_flds = seg_match;
1508	rss_cfg->hash.addl_hdrs = prof->segs[prof->segs_cnt - 1].hdrs;
1509	rss_cfg->hash.hdr_type = hdr_type;
1510	rss_cfg->hash.symm = prof->cfg.symm;
1511	ice_set_bit(vsi_handle, rss_cfg->vsis);
1512
1513	LIST_ADD_TAIL(&rss_cfg->l_entry, &hw->rss_list_head);
1514
1515	return ICE_SUCCESS;
1516}
1517
1518#define ICE_FLOW_PROF_HASH_S	0
1519#define ICE_FLOW_PROF_HASH_M	(0xFFFFFFFFULL << ICE_FLOW_PROF_HASH_S)
1520#define ICE_FLOW_PROF_HDR_S	32
1521#define ICE_FLOW_PROF_HDR_M	(0x3FFFFFFFULL << ICE_FLOW_PROF_HDR_S)
1522#define ICE_FLOW_PROF_ENCAP_S	62
1523#define ICE_FLOW_PROF_ENCAP_M	(0x3ULL << ICE_FLOW_PROF_ENCAP_S)
1524
1525/* Flow profile ID format:
1526 * [0:31] - Packet match fields
1527 * [32:61] - Protocol header
1528 * [62:63] - Encapsulation flag:
1529 *	     0 if non-tunneled
1530 *	     1 if tunneled
1531 *	     2 for tunneled with outer IPv4
1532 *	     3 for tunneled with outer IPv6
1533 */
1534#define ICE_FLOW_GEN_PROFID(hash, hdr, encap)                                \
1535	((u64)(((u64)(hash) & ICE_FLOW_PROF_HASH_M) |                        \
1536	       (((u64)(hdr) << ICE_FLOW_PROF_HDR_S) & ICE_FLOW_PROF_HDR_M) | \
1537	       (((u64)(encap) << ICE_FLOW_PROF_ENCAP_S) &                    \
1538		ICE_FLOW_PROF_ENCAP_M)))
1539
1540/**
1541 * ice_add_rss_cfg_sync - add an RSS configuration
1542 * @hw: pointer to the hardware structure
1543 * @vsi_handle: software VSI handle
1544 * @cfg: configure parameters
1545 *
1546 * Assumption: lock has already been acquired for RSS list
1547 */
1548static enum ice_status
1549ice_add_rss_cfg_sync(struct ice_hw *hw, u16 vsi_handle,
1550		     const struct ice_rss_hash_cfg *cfg)
1551{
1552	const enum ice_block blk = ICE_BLK_RSS;
1553	struct ice_flow_prof *prof = NULL;
1554	struct ice_flow_seg_info *segs;
1555	enum ice_status status;
1556	u8 segs_cnt;
1557
1558	if (cfg->symm)
1559		return ICE_ERR_PARAM;
1560
1561	segs_cnt = (cfg->hdr_type == ICE_RSS_OUTER_HEADERS) ?
1562			   ICE_FLOW_SEG_SINGLE :
1563			   ICE_FLOW_SEG_MAX;
1564
1565	segs = (struct ice_flow_seg_info *)ice_calloc(hw, segs_cnt,
1566						      sizeof(*segs));
1567	if (!segs)
1568		return ICE_ERR_NO_MEMORY;
1569
1570	/* Construct the packet segment info from the hashed fields */
1571	status = ice_flow_set_rss_seg_info(segs, segs_cnt, cfg);
1572	if (status)
1573		goto exit;
1574
1575	/* Search for a flow profile that has matching headers, hash fields
1576	 * and has the input VSI associated to it. If found, no further
1577	 * operations required and exit.
1578	 */
1579	prof = ice_flow_find_prof_conds(hw, blk, ICE_FLOW_RX, segs, segs_cnt,
1580					vsi_handle,
1581					ICE_FLOW_FIND_PROF_CHK_FLDS |
1582					ICE_FLOW_FIND_PROF_CHK_VSI);
1583	if (prof)
1584		goto exit;
1585
1586	/* Check if a flow profile exists with the same protocol headers and
1587	 * associated with the input VSI. If so disassociate the VSI from
1588	 * this profile. The VSI will be added to a new profile created with
1589	 * the protocol header and new hash field configuration.
1590	 */
1591	prof = ice_flow_find_prof_conds(hw, blk, ICE_FLOW_RX, segs, segs_cnt,
1592					vsi_handle, ICE_FLOW_FIND_PROF_CHK_VSI);
1593	if (prof) {
1594		status = ice_flow_disassoc_prof(hw, blk, prof, vsi_handle);
1595		if (!status)
1596			ice_rem_rss_list(hw, vsi_handle, prof);
1597		else
1598			goto exit;
1599
1600		/* Remove profile if it has no VSIs associated */
1601		if (!ice_is_any_bit_set(prof->vsis, ICE_MAX_VSI)) {
1602			status = ice_flow_rem_prof(hw, blk, prof->id);
1603			if (status)
1604				goto exit;
1605		}
1606	}
1607
1608	/* Search for a profile that has same match fields only. If this
1609	 * exists then associate the VSI to this profile.
1610	 */
1611	prof = ice_flow_find_prof_conds(hw, blk, ICE_FLOW_RX, segs, segs_cnt,
1612					vsi_handle,
1613					ICE_FLOW_FIND_PROF_CHK_FLDS);
1614	if (prof) {
1615		status = ice_flow_assoc_prof(hw, blk, prof, vsi_handle);
1616		if (!status)
1617			status = ice_add_rss_list(hw, vsi_handle, prof);
1618		goto exit;
1619	}
1620
1621	/* Create a new flow profile with generated profile and packet
1622	 * segment information.
1623	 */
1624	status = ice_flow_add_prof(hw, blk, ICE_FLOW_RX,
1625				   ICE_FLOW_GEN_PROFID(cfg->hash_flds,
1626						       segs[segs_cnt - 1].hdrs,
1627						       cfg->hdr_type),
1628				   segs, segs_cnt, NULL, 0, &prof);
1629	if (status)
1630		goto exit;
1631
1632	status = ice_flow_assoc_prof(hw, blk, prof, vsi_handle);
1633	/* If association to a new flow profile failed then this profile can
1634	 * be removed.
1635	 */
1636	if (status) {
1637		ice_flow_rem_prof(hw, blk, prof->id);
1638		goto exit;
1639	}
1640
1641	status = ice_add_rss_list(hw, vsi_handle, prof);
1642
1643	prof->cfg.symm = cfg->symm;
1644
1645exit:
1646	ice_free(hw, segs);
1647	return status;
1648}
1649
1650/**
1651 * ice_add_rss_cfg - add an RSS configuration with specified hashed fields
1652 * @hw: pointer to the hardware structure
1653 * @vsi_handle: software VSI handle
1654 * @cfg: configure parameters
1655 *
1656 * This function will generate a flow profile based on fields associated with
1657 * the input fields to hash on, the flow type and use the VSI number to add
1658 * a flow entry to the profile.
1659 */
1660enum ice_status
1661ice_add_rss_cfg(struct ice_hw *hw, u16 vsi_handle,
1662		const struct ice_rss_hash_cfg *cfg)
1663{
1664	struct ice_rss_hash_cfg local_cfg;
1665	enum ice_status status;
1666
1667	if (!ice_is_vsi_valid(hw, vsi_handle) || !cfg ||
1668	    cfg->hdr_type > ICE_RSS_ANY_HEADERS ||
1669	    cfg->hash_flds == ICE_HASH_INVALID)
1670		return ICE_ERR_PARAM;
1671
1672	ice_acquire_lock(&hw->rss_locks);
1673	local_cfg = *cfg;
1674	if (cfg->hdr_type < ICE_RSS_ANY_HEADERS) {
1675		status = ice_add_rss_cfg_sync(hw, vsi_handle, &local_cfg);
1676	} else {
1677		local_cfg.hdr_type = ICE_RSS_OUTER_HEADERS;
1678		status = ice_add_rss_cfg_sync(hw, vsi_handle, &local_cfg);
1679		if (!status) {
1680			local_cfg.hdr_type = ICE_RSS_INNER_HEADERS;
1681			status = ice_add_rss_cfg_sync(hw, vsi_handle,
1682						      &local_cfg);
1683		}
1684	}
1685	ice_release_lock(&hw->rss_locks);
1686
1687	return status;
1688}
1689
1690/**
1691 * ice_rem_rss_cfg_sync - remove an existing RSS configuration
1692 * @hw: pointer to the hardware structure
1693 * @vsi_handle: software VSI handle
1694 * @cfg: configure parameters
1695 *
1696 * Assumption: lock has already been acquired for RSS list
1697 */
1698static enum ice_status
1699ice_rem_rss_cfg_sync(struct ice_hw *hw, u16 vsi_handle,
1700		     const struct ice_rss_hash_cfg *cfg)
1701{
1702	const enum ice_block blk = ICE_BLK_RSS;
1703	struct ice_flow_seg_info *segs;
1704	struct ice_flow_prof *prof;
1705	enum ice_status status;
1706	u8 segs_cnt;
1707
1708	segs_cnt = (cfg->hdr_type == ICE_RSS_OUTER_HEADERS) ?
1709			   ICE_FLOW_SEG_SINGLE :
1710			   ICE_FLOW_SEG_MAX;
1711	segs = (struct ice_flow_seg_info *)ice_calloc(hw, segs_cnt,
1712						      sizeof(*segs));
1713	if (!segs)
1714		return ICE_ERR_NO_MEMORY;
1715
1716	/* Construct the packet segment info from the hashed fields */
1717	status = ice_flow_set_rss_seg_info(segs, segs_cnt, cfg);
1718	if (status)
1719		goto out;
1720
1721	prof = ice_flow_find_prof_conds(hw, blk, ICE_FLOW_RX, segs, segs_cnt,
1722					vsi_handle,
1723					ICE_FLOW_FIND_PROF_CHK_FLDS);
1724	if (!prof) {
1725		status = ICE_ERR_DOES_NOT_EXIST;
1726		goto out;
1727	}
1728
1729	status = ice_flow_disassoc_prof(hw, blk, prof, vsi_handle);
1730	if (status)
1731		goto out;
1732
1733	/* Remove RSS configuration from VSI context before deleting
1734	 * the flow profile.
1735	 */
1736	ice_rem_rss_list(hw, vsi_handle, prof);
1737
1738	if (!ice_is_any_bit_set(prof->vsis, ICE_MAX_VSI))
1739		status = ice_flow_rem_prof(hw, blk, prof->id);
1740
1741out:
1742	ice_free(hw, segs);
1743	return status;
1744}
1745
1746/**
1747 * ice_rem_rss_cfg - remove an existing RSS config with matching hashed fields
1748 * @hw: pointer to the hardware structure
1749 * @vsi_handle: software VSI handle
1750 * @cfg: configure parameters
1751 *
1752 * This function will lookup the flow profile based on the input
1753 * hash field bitmap, iterate through the profile entry list of
1754 * that profile and find entry associated with input VSI to be
1755 * removed. Calls are made to underlying flow apis which will in
1756 * turn build or update buffers for RSS XLT1 section.
1757 */
1758enum ice_status
1759ice_rem_rss_cfg(struct ice_hw *hw, u16 vsi_handle,
1760		const struct ice_rss_hash_cfg *cfg)
1761{
1762	struct ice_rss_hash_cfg local_cfg;
1763	enum ice_status status;
1764
1765	if (!ice_is_vsi_valid(hw, vsi_handle) || !cfg ||
1766	    cfg->hdr_type > ICE_RSS_ANY_HEADERS ||
1767	    cfg->hash_flds == ICE_HASH_INVALID)
1768		return ICE_ERR_PARAM;
1769
1770	ice_acquire_lock(&hw->rss_locks);
1771	local_cfg = *cfg;
1772	if (cfg->hdr_type < ICE_RSS_ANY_HEADERS) {
1773		status = ice_rem_rss_cfg_sync(hw, vsi_handle, &local_cfg);
1774	} else {
1775		local_cfg.hdr_type = ICE_RSS_OUTER_HEADERS;
1776		status = ice_rem_rss_cfg_sync(hw, vsi_handle, &local_cfg);
1777		if (!status) {
1778			local_cfg.hdr_type = ICE_RSS_INNER_HEADERS;
1779			status = ice_rem_rss_cfg_sync(hw, vsi_handle,
1780						      &local_cfg);
1781		}
1782	}
1783	ice_release_lock(&hw->rss_locks);
1784
1785	return status;
1786}
1787
1788/* Mapping of AVF hash bit fields to an L3-L4 hash combination.
1789 * As the ice_flow_avf_hdr_field represent individual bit shifts in a hash,
1790 * convert its values to their appropriate flow L3, L4 values.
1791 */
1792#define ICE_FLOW_AVF_RSS_IPV4_MASKS \
1793	(BIT_ULL(ICE_AVF_FLOW_FIELD_IPV4_OTHER) | \
1794	 BIT_ULL(ICE_AVF_FLOW_FIELD_FRAG_IPV4))
1795#define ICE_FLOW_AVF_RSS_TCP_IPV4_MASKS \
1796	(BIT_ULL(ICE_AVF_FLOW_FIELD_IPV4_TCP_SYN_NO_ACK) | \
1797	 BIT_ULL(ICE_AVF_FLOW_FIELD_IPV4_TCP))
1798#define ICE_FLOW_AVF_RSS_UDP_IPV4_MASKS \
1799	(BIT_ULL(ICE_AVF_FLOW_FIELD_UNICAST_IPV4_UDP) | \
1800	 BIT_ULL(ICE_AVF_FLOW_FIELD_MULTICAST_IPV4_UDP) | \
1801	 BIT_ULL(ICE_AVF_FLOW_FIELD_IPV4_UDP))
1802#define ICE_FLOW_AVF_RSS_ALL_IPV4_MASKS \
1803	(ICE_FLOW_AVF_RSS_TCP_IPV4_MASKS | ICE_FLOW_AVF_RSS_UDP_IPV4_MASKS | \
1804	 ICE_FLOW_AVF_RSS_IPV4_MASKS | BIT_ULL(ICE_AVF_FLOW_FIELD_IPV4_SCTP))
1805
1806#define ICE_FLOW_AVF_RSS_IPV6_MASKS \
1807	(BIT_ULL(ICE_AVF_FLOW_FIELD_IPV6_OTHER) | \
1808	 BIT_ULL(ICE_AVF_FLOW_FIELD_FRAG_IPV6))
1809#define ICE_FLOW_AVF_RSS_UDP_IPV6_MASKS \
1810	(BIT_ULL(ICE_AVF_FLOW_FIELD_UNICAST_IPV6_UDP) | \
1811	 BIT_ULL(ICE_AVF_FLOW_FIELD_MULTICAST_IPV6_UDP) | \
1812	 BIT_ULL(ICE_AVF_FLOW_FIELD_IPV6_UDP))
1813#define ICE_FLOW_AVF_RSS_TCP_IPV6_MASKS \
1814	(BIT_ULL(ICE_AVF_FLOW_FIELD_IPV6_TCP_SYN_NO_ACK) | \
1815	 BIT_ULL(ICE_AVF_FLOW_FIELD_IPV6_TCP))
1816#define ICE_FLOW_AVF_RSS_ALL_IPV6_MASKS \
1817	(ICE_FLOW_AVF_RSS_TCP_IPV6_MASKS | ICE_FLOW_AVF_RSS_UDP_IPV6_MASKS | \
1818	 ICE_FLOW_AVF_RSS_IPV6_MASKS | BIT_ULL(ICE_AVF_FLOW_FIELD_IPV6_SCTP))
1819
1820/**
1821 * ice_add_avf_rss_cfg - add an RSS configuration for AVF driver
1822 * @hw: pointer to the hardware structure
1823 * @vsi_handle: software VSI handle
1824 * @avf_hash: hash bit fields (ICE_AVF_FLOW_FIELD_*) to configure
1825 *
1826 * This function will take the hash bitmap provided by the AVF driver via a
1827 * message, convert it to ICE-compatible values, and configure RSS flow
1828 * profiles.
1829 */
1830enum ice_status
1831ice_add_avf_rss_cfg(struct ice_hw *hw, u16 vsi_handle, u64 avf_hash)
1832{
1833	enum ice_status status = ICE_SUCCESS;
1834	struct ice_rss_hash_cfg hcfg;
1835	u64 hash_flds;
1836
1837	if (avf_hash == ICE_AVF_FLOW_FIELD_INVALID ||
1838	    !ice_is_vsi_valid(hw, vsi_handle))
1839		return ICE_ERR_PARAM;
1840
1841	/* Make sure no unsupported bits are specified */
1842	if (avf_hash & ~(ICE_FLOW_AVF_RSS_ALL_IPV4_MASKS |
1843			 ICE_FLOW_AVF_RSS_ALL_IPV6_MASKS))
1844		return ICE_ERR_CFG;
1845
1846	hash_flds = avf_hash;
1847
1848	/* Always create an L3 RSS configuration for any L4 RSS configuration */
1849	if (hash_flds & ICE_FLOW_AVF_RSS_ALL_IPV4_MASKS)
1850		hash_flds |= ICE_FLOW_AVF_RSS_IPV4_MASKS;
1851
1852	if (hash_flds & ICE_FLOW_AVF_RSS_ALL_IPV6_MASKS)
1853		hash_flds |= ICE_FLOW_AVF_RSS_IPV6_MASKS;
1854
1855	/* Create the corresponding RSS configuration for each valid hash bit */
1856	while (hash_flds) {
1857		u64 rss_hash = ICE_HASH_INVALID;
1858
1859		if (hash_flds & ICE_FLOW_AVF_RSS_ALL_IPV4_MASKS) {
1860			if (hash_flds & ICE_FLOW_AVF_RSS_IPV4_MASKS) {
1861				rss_hash = ICE_FLOW_HASH_IPV4;
1862				hash_flds &= ~ICE_FLOW_AVF_RSS_IPV4_MASKS;
1863			} else if (hash_flds &
1864				   ICE_FLOW_AVF_RSS_TCP_IPV4_MASKS) {
1865				rss_hash = ICE_FLOW_HASH_IPV4 |
1866					ICE_FLOW_HASH_TCP_PORT;
1867				hash_flds &= ~ICE_FLOW_AVF_RSS_TCP_IPV4_MASKS;
1868			} else if (hash_flds &
1869				   ICE_FLOW_AVF_RSS_UDP_IPV4_MASKS) {
1870				rss_hash = ICE_FLOW_HASH_IPV4 |
1871					ICE_FLOW_HASH_UDP_PORT;
1872				hash_flds &= ~ICE_FLOW_AVF_RSS_UDP_IPV4_MASKS;
1873			} else if (hash_flds &
1874				   BIT_ULL(ICE_AVF_FLOW_FIELD_IPV4_SCTP)) {
1875				rss_hash = ICE_FLOW_HASH_IPV4 |
1876					ICE_FLOW_HASH_SCTP_PORT;
1877				hash_flds &=
1878					~BIT_ULL(ICE_AVF_FLOW_FIELD_IPV4_SCTP);
1879			}
1880		} else if (hash_flds & ICE_FLOW_AVF_RSS_ALL_IPV6_MASKS) {
1881			if (hash_flds & ICE_FLOW_AVF_RSS_IPV6_MASKS) {
1882				rss_hash = ICE_FLOW_HASH_IPV6;
1883				hash_flds &= ~ICE_FLOW_AVF_RSS_IPV6_MASKS;
1884			} else if (hash_flds &
1885				   ICE_FLOW_AVF_RSS_TCP_IPV6_MASKS) {
1886				rss_hash = ICE_FLOW_HASH_IPV6 |
1887					ICE_FLOW_HASH_TCP_PORT;
1888				hash_flds &= ~ICE_FLOW_AVF_RSS_TCP_IPV6_MASKS;
1889			} else if (hash_flds &
1890				   ICE_FLOW_AVF_RSS_UDP_IPV6_MASKS) {
1891				rss_hash = ICE_FLOW_HASH_IPV6 |
1892					ICE_FLOW_HASH_UDP_PORT;
1893				hash_flds &= ~ICE_FLOW_AVF_RSS_UDP_IPV6_MASKS;
1894			} else if (hash_flds &
1895				   BIT_ULL(ICE_AVF_FLOW_FIELD_IPV6_SCTP)) {
1896				rss_hash = ICE_FLOW_HASH_IPV6 |
1897					ICE_FLOW_HASH_SCTP_PORT;
1898				hash_flds &=
1899					~BIT_ULL(ICE_AVF_FLOW_FIELD_IPV6_SCTP);
1900			}
1901		}
1902
1903		if (rss_hash == ICE_HASH_INVALID)
1904			return ICE_ERR_OUT_OF_RANGE;
1905
1906		hcfg.addl_hdrs = ICE_FLOW_SEG_HDR_NONE;
1907		hcfg.hash_flds = rss_hash;
1908		hcfg.symm = false;
1909		hcfg.hdr_type = ICE_RSS_ANY_HEADERS;
1910		status = ice_add_rss_cfg(hw, vsi_handle, &hcfg);
1911		if (status)
1912			break;
1913	}
1914
1915	return status;
1916}
1917
1918/**
1919 * ice_replay_rss_cfg - replay RSS configurations associated with VSI
1920 * @hw: pointer to the hardware structure
1921 * @vsi_handle: software VSI handle
1922 */
1923enum ice_status ice_replay_rss_cfg(struct ice_hw *hw, u16 vsi_handle)
1924{
1925	enum ice_status status = ICE_SUCCESS;
1926	struct ice_rss_cfg *r;
1927
1928	if (!ice_is_vsi_valid(hw, vsi_handle))
1929		return ICE_ERR_PARAM;
1930
1931	ice_acquire_lock(&hw->rss_locks);
1932	LIST_FOR_EACH_ENTRY(r, &hw->rss_list_head,
1933			    ice_rss_cfg, l_entry) {
1934		if (ice_is_bit_set(r->vsis, vsi_handle)) {
1935			status = ice_add_rss_cfg_sync(hw, vsi_handle, &r->hash);
1936			if (status)
1937				break;
1938		}
1939	}
1940	ice_release_lock(&hw->rss_locks);
1941
1942	return status;
1943}
1944
1945/**
1946 * ice_get_rss_cfg - returns hashed fields for the given header types
1947 * @hw: pointer to the hardware structure
1948 * @vsi_handle: software VSI handle
1949 * @hdrs: protocol header type
1950 *
1951 * This function will return the match fields of the first instance of flow
1952 * profile having the given header types and containing input VSI
1953 */
1954u64 ice_get_rss_cfg(struct ice_hw *hw, u16 vsi_handle, u32 hdrs)
1955{
1956	u64 rss_hash = ICE_HASH_INVALID;
1957	struct ice_rss_cfg *r;
1958
1959	/* verify if the protocol header is non zero and VSI is valid */
1960	if (hdrs == ICE_FLOW_SEG_HDR_NONE || !ice_is_vsi_valid(hw, vsi_handle))
1961		return ICE_HASH_INVALID;
1962
1963	ice_acquire_lock(&hw->rss_locks);
1964	LIST_FOR_EACH_ENTRY(r, &hw->rss_list_head,
1965			    ice_rss_cfg, l_entry)
1966		if (ice_is_bit_set(r->vsis, vsi_handle) &&
1967		    r->hash.addl_hdrs == hdrs) {
1968			rss_hash = r->hash.hash_flds;
1969			break;
1970		}
1971	ice_release_lock(&hw->rss_locks);
1972
1973	return rss_hash;
1974}
1975