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