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