net/ice/base: fix minor issues
[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_fld - Create an extraction sequence entry for the given field
500  * @hw: pointer to the HW struct
501  * @params: information about the flow to be processed
502  * @seg: packet segment index of the field to be extracted
503  * @fld: ID of field to be extracted
504  *
505  * This function determines the protocol ID, offset, and size of the given
506  * field. It then allocates one or more extraction sequence entries for the
507  * given field, and fill the entries with protocol ID and offset information.
508  */
509 static enum ice_status
510 ice_flow_xtract_fld(struct ice_hw *hw, struct ice_flow_prof_params *params,
511                     u8 seg, enum ice_flow_field fld)
512 {
513         enum ice_flow_field sib = ICE_FLOW_FIELD_IDX_MAX;
514         enum ice_prot_id prot_id = ICE_PROT_ID_INVAL;
515         u8 fv_words = hw->blk[params->blk].es.fvw;
516         struct ice_flow_fld_info *flds;
517         u16 cnt, ese_bits, i;
518         s16 adj = 0;
519         u8 off;
520
521         flds = params->prof->segs[seg].fields;
522
523         switch (fld) {
524         case ICE_FLOW_FIELD_IDX_ETH_DA:
525         case ICE_FLOW_FIELD_IDX_ETH_SA:
526         case ICE_FLOW_FIELD_IDX_S_VLAN:
527         case ICE_FLOW_FIELD_IDX_C_VLAN:
528                 prot_id = seg == 0 ? ICE_PROT_MAC_OF_OR_S : ICE_PROT_MAC_IL;
529                 break;
530         case ICE_FLOW_FIELD_IDX_ETH_TYPE:
531                 prot_id = seg == 0 ? ICE_PROT_ETYPE_OL : ICE_PROT_ETYPE_IL;
532                 break;
533         case ICE_FLOW_FIELD_IDX_IP_DSCP:
534                 if (params->prof->segs[seg].hdrs & ICE_FLOW_SEG_HDR_IPV6)
535                         adj = ICE_FLOW_FLD_IPV6_TTL_DSCP_DISP;
536                 /* Fall through */
537         case ICE_FLOW_FIELD_IDX_IP_TTL:
538         case ICE_FLOW_FIELD_IDX_IP_PROT:
539                 /* Some fields are located at different offsets in IPv4 and
540                  * IPv6
541                  */
542                 if (params->prof->segs[seg].hdrs & ICE_FLOW_SEG_HDR_IPV4) {
543                         prot_id = seg == 0 ? ICE_PROT_IPV4_OF_OR_S :
544                                 ICE_PROT_IPV4_IL;
545                         /* TTL and PROT share the same extraction seq. entry.
546                          * Each is considered a sibling to the other in term
547                          * sharing the same extraction sequence entry.
548                          */
549                         if (fld == ICE_FLOW_FIELD_IDX_IP_TTL)
550                                 sib = ICE_FLOW_FIELD_IDX_IP_PROT;
551                         else if (fld == ICE_FLOW_FIELD_IDX_IP_PROT)
552                                 sib = ICE_FLOW_FIELD_IDX_IP_TTL;
553                 } else if (params->prof->segs[seg].hdrs &
554                            ICE_FLOW_SEG_HDR_IPV6) {
555                         prot_id = seg == 0 ? ICE_PROT_IPV6_OF_OR_S :
556                                 ICE_PROT_IPV6_IL;
557                         if (fld == ICE_FLOW_FIELD_IDX_IP_TTL)
558                                 adj = ICE_FLOW_FLD_IPV6_TTL_TTL_DISP;
559                         else if (fld == ICE_FLOW_FIELD_IDX_IP_PROT)
560                                 adj = ICE_FLOW_FLD_IPV6_TTL_PROT_DISP;
561                 }
562                 break;
563         case ICE_FLOW_FIELD_IDX_IPV4_SA:
564         case ICE_FLOW_FIELD_IDX_IPV4_DA:
565                 prot_id = seg == 0 ? ICE_PROT_IPV4_OF_OR_S : ICE_PROT_IPV4_IL;
566                 break;
567         case ICE_FLOW_FIELD_IDX_IPV6_SA:
568         case ICE_FLOW_FIELD_IDX_IPV6_DA:
569                 prot_id = seg == 0 ? ICE_PROT_IPV6_OF_OR_S : ICE_PROT_IPV6_IL;
570                 break;
571         case ICE_FLOW_FIELD_IDX_TCP_SRC_PORT:
572         case ICE_FLOW_FIELD_IDX_TCP_DST_PORT:
573         case ICE_FLOW_FIELD_IDX_TCP_FLAGS:
574                 prot_id = ICE_PROT_TCP_IL;
575                 break;
576         case ICE_FLOW_FIELD_IDX_UDP_SRC_PORT:
577         case ICE_FLOW_FIELD_IDX_UDP_DST_PORT:
578                 prot_id = seg == 0 ? ICE_PROT_UDP_IL_OR_S : ICE_PROT_UDP_OF;
579                 break;
580         case ICE_FLOW_FIELD_IDX_SCTP_SRC_PORT:
581         case ICE_FLOW_FIELD_IDX_SCTP_DST_PORT:
582                 prot_id = ICE_PROT_SCTP_IL;
583                 break;
584         case ICE_FLOW_FIELD_IDX_ARP_SIP:
585         case ICE_FLOW_FIELD_IDX_ARP_DIP:
586         case ICE_FLOW_FIELD_IDX_ARP_SHA:
587         case ICE_FLOW_FIELD_IDX_ARP_DHA:
588         case ICE_FLOW_FIELD_IDX_ARP_OP:
589                 prot_id = ICE_PROT_ARP_OF;
590                 break;
591         case ICE_FLOW_FIELD_IDX_ICMP_TYPE:
592         case ICE_FLOW_FIELD_IDX_ICMP_CODE:
593                 /* ICMP type and code share the same extraction seq. entry */
594                 prot_id = (params->prof->segs[seg].hdrs &
595                            ICE_FLOW_SEG_HDR_IPV4) ?
596                         ICE_PROT_ICMP_IL : ICE_PROT_ICMPV6_IL;
597                 sib = fld == ICE_FLOW_FIELD_IDX_ICMP_TYPE ?
598                         ICE_FLOW_FIELD_IDX_ICMP_CODE :
599                         ICE_FLOW_FIELD_IDX_ICMP_TYPE;
600                 break;
601         case ICE_FLOW_FIELD_IDX_GRE_KEYID:
602                 prot_id = ICE_PROT_GRE_OF;
603                 break;
604         default:
605                 return ICE_ERR_NOT_IMPL;
606         }
607
608         /* Each extraction sequence entry is a word in size, and extracts a
609          * word-aligned offset from a protocol header.
610          */
611         ese_bits = ICE_FLOW_FV_EXTRACT_SZ * 8;
612
613         flds[fld].xtrct.prot_id = prot_id;
614         flds[fld].xtrct.off = (ice_flds_info[fld].off / ese_bits) *
615                 ICE_FLOW_FV_EXTRACT_SZ;
616         flds[fld].xtrct.disp = (u8)((ice_flds_info[fld].off + adj) % ese_bits);
617         flds[fld].xtrct.idx = params->es_cnt;
618
619         /* Adjust the next field-entry index after accommodating the number of
620          * entries this field consumes
621          */
622         cnt = DIVIDE_AND_ROUND_UP(flds[fld].xtrct.disp +
623                                   ice_flds_info[fld].size, ese_bits);
624
625         /* Fill in the extraction sequence entries needed for this field */
626         off = flds[fld].xtrct.off;
627         for (i = 0; i < cnt; i++) {
628                 /* Only consume an extraction sequence entry if there is no
629                  * sibling field associated with this field or the sibling entry
630                  * already extracts the word shared with this field.
631                  */
632                 if (sib == ICE_FLOW_FIELD_IDX_MAX ||
633                     flds[sib].xtrct.prot_id == ICE_PROT_ID_INVAL ||
634                     flds[sib].xtrct.off != off) {
635                         u8 idx;
636
637                         /* Make sure the number of extraction sequence required
638                          * does not exceed the block's capability
639                          */
640                         if (params->es_cnt >= fv_words)
641                                 return ICE_ERR_MAX_LIMIT;
642
643                         /* some blocks require a reversed field vector layout */
644                         if (hw->blk[params->blk].es.reverse)
645                                 idx = fv_words - params->es_cnt - 1;
646                         else
647                                 idx = params->es_cnt;
648
649                         params->es[idx].prot_id = prot_id;
650                         params->es[idx].off = off;
651                         params->es_cnt++;
652                 }
653
654                 off += ICE_FLOW_FV_EXTRACT_SZ;
655         }
656
657         return ICE_SUCCESS;
658 }
659
660 /**
661  * ice_flow_xtract_raws - Create extract sequence entries for raw bytes
662  * @hw: pointer to the HW struct
663  * @params: information about the flow to be processed
664  * @seg: index of packet segment whose raw fields are to be be extracted
665  */
666 static enum ice_status
667 ice_flow_xtract_raws(struct ice_hw *hw, struct ice_flow_prof_params *params,
668                      u8 seg)
669 {
670         u16 hdrs_sz;
671         u8 i;
672
673         if (!params->prof->segs[seg].raws_cnt)
674                 return ICE_SUCCESS;
675
676         if (params->prof->segs[seg].raws_cnt >
677             ARRAY_SIZE(params->prof->segs[seg].raws))
678                 return ICE_ERR_MAX_LIMIT;
679
680         /* Offsets within the segment headers are not supported */
681         hdrs_sz = ice_flow_calc_seg_sz(params, seg);
682         if (!hdrs_sz)
683                 return ICE_ERR_PARAM;
684
685         for (i = 0; i < params->prof->segs[seg].raws_cnt; i++) {
686                 struct ice_flow_seg_fld_raw *raw;
687                 u16 off, cnt, j;
688
689                 raw = &params->prof->segs[seg].raws[i];
690
691                 /* Only support matching raw fields in the payload */
692                 if (raw->off < hdrs_sz)
693                         return ICE_ERR_PARAM;
694
695                 /* Convert the segment-relative offset into payload-relative
696                  * offset.
697                  */
698                 off = raw->off - hdrs_sz;
699
700                 /* Storing extraction information */
701                 raw->info.xtrct.prot_id = ICE_PROT_PAY;
702                 raw->info.xtrct.off = (off / ICE_FLOW_FV_EXTRACT_SZ) *
703                         ICE_FLOW_FV_EXTRACT_SZ;
704                 raw->info.xtrct.disp = (off % ICE_FLOW_FV_EXTRACT_SZ) * 8;
705                 raw->info.xtrct.idx = params->es_cnt;
706
707                 /* Determine the number of field vector entries this raw field
708                  * consumes.
709                  */
710                 cnt = DIVIDE_AND_ROUND_UP(raw->info.xtrct.disp +
711                                           (raw->info.src.last * 8),
712                                           ICE_FLOW_FV_EXTRACT_SZ * 8);
713                 off = raw->info.xtrct.off;
714                 for (j = 0; j < cnt; j++) {
715                         /* Make sure the number of extraction sequence required
716                          * does not exceed the block's capability
717                          */
718                         if (params->es_cnt >= hw->blk[params->blk].es.count ||
719                             params->es_cnt >= ICE_MAX_FV_WORDS)
720                                 return ICE_ERR_MAX_LIMIT;
721
722                         params->es[params->es_cnt].prot_id = ICE_PROT_PAY;
723                         params->es[params->es_cnt].off = off;
724                         params->es_cnt++;
725                         off += ICE_FLOW_FV_EXTRACT_SZ;
726                 }
727         }
728
729         return ICE_SUCCESS;
730 }
731
732 /**
733  * ice_flow_create_xtrct_seq - Create an extraction sequence for given segments
734  * @hw: pointer to the HW struct
735  * @params: information about the flow to be processed
736  *
737  * This function iterates through all matched fields in the given segments, and
738  * creates an extraction sequence for the fields.
739  */
740 static enum ice_status
741 ice_flow_create_xtrct_seq(struct ice_hw *hw,
742                           struct ice_flow_prof_params *params)
743 {
744         enum ice_status status = ICE_SUCCESS;
745         u8 i;
746
747         for (i = 0; i < params->prof->segs_cnt; i++) {
748                 u64 match = params->prof->segs[i].match;
749                 u16 j;
750
751                 for (j = 0; j < ICE_FLOW_FIELD_IDX_MAX && match; j++) {
752                         const u64 bit = BIT_ULL(j);
753
754                         if (match & bit) {
755                                 status = ice_flow_xtract_fld
756                                         (hw, params, i, (enum ice_flow_field)j);
757                                 if (status)
758                                         return status;
759                                 match &= ~bit;
760                         }
761                 }
762
763                 /* Process raw matching bytes */
764                 status = ice_flow_xtract_raws(hw, params, i);
765                 if (status)
766                         return status;
767         }
768
769         return status;
770 }
771
772 /**
773  * ice_flow_proc_segs - process all packet segments associated with a profile
774  * @hw: pointer to the HW struct
775  * @params: information about the flow to be processed
776  */
777 static enum ice_status
778 ice_flow_proc_segs(struct ice_hw *hw, struct ice_flow_prof_params *params)
779 {
780         enum ice_status status;
781
782         status = ice_flow_proc_seg_hdrs(params);
783         if (status)
784                 return status;
785
786         status = ice_flow_create_xtrct_seq(hw, params);
787         if (status)
788                 return status;
789
790         switch (params->blk) {
791         case ICE_BLK_RSS:
792                 /* Only header information is provided for RSS configuration.
793                  * No further processing is needed.
794                  */
795                 status = ICE_SUCCESS;
796                 break;
797         case ICE_BLK_FD:
798                 status = ICE_SUCCESS;
799                 break;
800         case ICE_BLK_SW:
801         default:
802                 return ICE_ERR_NOT_IMPL;
803         }
804
805         return status;
806 }
807
808 #define ICE_FLOW_FIND_PROF_CHK_FLDS     0x00000001
809 #define ICE_FLOW_FIND_PROF_CHK_VSI      0x00000002
810
811 /**
812  * ice_flow_find_prof_conds - Find a profile matching headers and conditions
813  * @hw: pointer to the HW struct
814  * @blk: classification stage
815  * @dir: flow direction
816  * @segs: array of one or more packet segments that describe the flow
817  * @segs_cnt: number of packet segments provided
818  * @vsi_handle: software VSI handle to check VSI (ICE_FLOW_FIND_PROF_CHK_VSI)
819  * @conds: additional conditions to be checked (ICE_FLOW_FIND_PROF_CHK_*)
820  */
821 static struct ice_flow_prof *
822 ice_flow_find_prof_conds(struct ice_hw *hw, enum ice_block blk,
823                          enum ice_flow_dir dir, struct ice_flow_seg_info *segs,
824                          u8 segs_cnt, u16 vsi_handle, u32 conds)
825 {
826         struct ice_flow_prof *p;
827
828         LIST_FOR_EACH_ENTRY(p, &hw->fl_profs[blk], ice_flow_prof, l_entry) {
829                 if (p->dir == dir && segs_cnt && segs_cnt == p->segs_cnt) {
830                         u8 i;
831
832                         /* Check for profile-VSI association if specified */
833                         if ((conds & ICE_FLOW_FIND_PROF_CHK_VSI) &&
834                             ice_is_vsi_valid(hw, vsi_handle) &&
835                             !ice_is_bit_set(p->vsis, vsi_handle))
836                                 continue;
837
838                         /* Protocol headers must be checked. Matched fields are
839                          * checked if specified.
840                          */
841                         for (i = 0; i < segs_cnt; i++)
842                                 if (segs[i].hdrs != p->segs[i].hdrs ||
843                                     ((conds & ICE_FLOW_FIND_PROF_CHK_FLDS) &&
844                                      segs[i].match != p->segs[i].match))
845                                         break;
846
847                         /* A match is found if all segments are matched */
848                         if (i == segs_cnt)
849                                 return p;
850                 }
851         }
852
853         return NULL;
854 }
855
856 /**
857  * ice_flow_find_prof - Look up a profile matching headers and matched fields
858  * @hw: pointer to the HW struct
859  * @blk: classification stage
860  * @dir: flow direction
861  * @segs: array of one or more packet segments that describe the flow
862  * @segs_cnt: number of packet segments provided
863  */
864 u64
865 ice_flow_find_prof(struct ice_hw *hw, enum ice_block blk, enum ice_flow_dir dir,
866                    struct ice_flow_seg_info *segs, u8 segs_cnt)
867 {
868         struct ice_flow_prof *p;
869
870         ice_acquire_lock(&hw->fl_profs_locks[blk]);
871         p = ice_flow_find_prof_conds(hw, blk, dir, segs, segs_cnt,
872                                      ICE_MAX_VSI, ICE_FLOW_FIND_PROF_CHK_FLDS);
873         ice_release_lock(&hw->fl_profs_locks[blk]);
874
875         return p ? p->id : ICE_FLOW_PROF_ID_INVAL;
876 }
877
878 /**
879  * ice_flow_find_prof_id - Look up a profile with given profile ID
880  * @hw: pointer to the HW struct
881  * @blk: classification stage
882  * @prof_id: unique ID to identify this flow profile
883  */
884 static struct ice_flow_prof *
885 ice_flow_find_prof_id(struct ice_hw *hw, enum ice_block blk, u64 prof_id)
886 {
887         struct ice_flow_prof *p;
888
889         LIST_FOR_EACH_ENTRY(p, &hw->fl_profs[blk], ice_flow_prof, l_entry) {
890                 if (p->id == prof_id)
891                         return p;
892         }
893
894         return NULL;
895 }
896
897 /**
898  * ice_flow_rem_entry_sync - Remove a flow entry
899  * @hw: pointer to the HW struct
900  * @entry: flow entry to be removed
901  */
902 static enum ice_status
903 ice_flow_rem_entry_sync(struct ice_hw *hw, struct ice_flow_entry *entry)
904 {
905         if (!entry)
906                 return ICE_ERR_BAD_PTR;
907
908         LIST_DEL(&entry->l_entry);
909
910         if (entry->entry)
911                 ice_free(hw, entry->entry);
912
913         if (entry->acts) {
914                 ice_free(hw, entry->acts);
915                 entry->acts = NULL;
916                 entry->acts_cnt = 0;
917         }
918
919         ice_free(hw, entry);
920
921         return ICE_SUCCESS;
922 }
923
924 /**
925  * ice_flow_add_prof_sync - Add a flow profile for packet segments and fields
926  * @hw: pointer to the HW struct
927  * @blk: classification stage
928  * @dir: flow direction
929  * @prof_id: unique ID to identify this flow profile
930  * @segs: array of one or more packet segments that describe the flow
931  * @segs_cnt: number of packet segments provided
932  * @acts: array of default actions
933  * @acts_cnt: number of default actions
934  * @prof: stores the returned flow profile added
935  *
936  * Assumption: the caller has acquired the lock to the profile list
937  */
938 static enum ice_status
939 ice_flow_add_prof_sync(struct ice_hw *hw, enum ice_block blk,
940                        enum ice_flow_dir dir, u64 prof_id,
941                        struct ice_flow_seg_info *segs, u8 segs_cnt,
942                        struct ice_flow_action *acts, u8 acts_cnt,
943                        struct ice_flow_prof **prof)
944 {
945         struct ice_flow_prof_params params;
946         enum ice_status status = ICE_SUCCESS;
947         u8 i;
948
949         if (!prof || (acts_cnt && !acts))
950                 return ICE_ERR_BAD_PTR;
951
952         ice_memset(&params, 0, sizeof(params), ICE_NONDMA_MEM);
953         params.prof = (struct ice_flow_prof *)
954                 ice_malloc(hw, sizeof(*params.prof));
955         if (!params.prof)
956                 return ICE_ERR_NO_MEMORY;
957
958         /* initialize extraction sequence to all invalid (0xff) */
959         ice_memset(params.es, 0xff, sizeof(params.es), ICE_NONDMA_MEM);
960
961         params.blk = blk;
962         params.prof->id = prof_id;
963         params.prof->dir = dir;
964         params.prof->segs_cnt = segs_cnt;
965
966         /* Make a copy of the segments that need to be persistent in the flow
967          * profile instance
968          */
969         for (i = 0; i < segs_cnt; i++)
970                 ice_memcpy(&params.prof->segs[i], &segs[i], sizeof(*segs),
971                            ICE_NONDMA_TO_NONDMA);
972
973         /* Make a copy of the actions that need to be persistent in the flow
974          * profile instance.
975          */
976         if (acts_cnt) {
977                 params.prof->acts = (struct ice_flow_action *)
978                         ice_memdup(hw, acts, acts_cnt * sizeof(*acts),
979                                    ICE_NONDMA_TO_NONDMA);
980
981                 if (!params.prof->acts) {
982                         status = ICE_ERR_NO_MEMORY;
983                         goto out;
984                 }
985         }
986
987         status = ice_flow_proc_segs(hw, &params);
988         if (status) {
989                 ice_debug(hw, ICE_DBG_FLOW,
990                           "Error processing a flow's packet segments\n");
991                 goto out;
992         }
993
994         /* Add a HW profile for this flow profile */
995         status = ice_add_prof(hw, blk, prof_id, (u8 *)params.ptypes, params.es);
996         if (status) {
997                 ice_debug(hw, ICE_DBG_FLOW, "Error adding a HW flow profile\n");
998                 goto out;
999         }
1000
1001         INIT_LIST_HEAD(&params.prof->entries);
1002         ice_init_lock(&params.prof->entries_lock);
1003         *prof = params.prof;
1004
1005 out:
1006         if (status) {
1007                 if (params.prof->acts)
1008                         ice_free(hw, params.prof->acts);
1009                 ice_free(hw, params.prof);
1010         }
1011
1012         return status;
1013 }
1014
1015 /**
1016  * ice_flow_rem_prof_sync - remove a flow profile
1017  * @hw: pointer to the hardware structure
1018  * @blk: classification stage
1019  * @prof: pointer to flow profile to remove
1020  *
1021  * Assumption: the caller has acquired the lock to the profile list
1022  */
1023 static enum ice_status
1024 ice_flow_rem_prof_sync(struct ice_hw *hw, enum ice_block blk,
1025                        struct ice_flow_prof *prof)
1026 {
1027         enum ice_status status = ICE_SUCCESS;
1028
1029         /* Remove all remaining flow entries before removing the flow profile */
1030         if (!LIST_EMPTY(&prof->entries)) {
1031                 struct ice_flow_entry *e, *t;
1032
1033                 ice_acquire_lock(&prof->entries_lock);
1034
1035                 LIST_FOR_EACH_ENTRY_SAFE(e, t, &prof->entries, ice_flow_entry,
1036                                          l_entry) {
1037                         status = ice_flow_rem_entry_sync(hw, e);
1038                         if (status)
1039                                 break;
1040                 }
1041
1042                 ice_release_lock(&prof->entries_lock);
1043         }
1044
1045         /* Remove all hardware profiles associated with this flow profile */
1046         status = ice_rem_prof(hw, blk, prof->id);
1047         if (!status) {
1048                 LIST_DEL(&prof->l_entry);
1049                 ice_destroy_lock(&prof->entries_lock);
1050                 if (prof->acts)
1051                         ice_free(hw, prof->acts);
1052                 ice_free(hw, prof);
1053         }
1054
1055         return status;
1056 }
1057
1058 /**
1059  * ice_flow_assoc_prof - associate a VSI with a flow profile
1060  * @hw: pointer to the hardware structure
1061  * @blk: classification stage
1062  * @prof: pointer to flow profile
1063  * @vsi_handle: software VSI handle
1064  *
1065  * Assumption: the caller has acquired the lock to the profile list
1066  * and the software VSI handle has been validated
1067  */
1068 static enum ice_status
1069 ice_flow_assoc_prof(struct ice_hw *hw, enum ice_block blk,
1070                     struct ice_flow_prof *prof, u16 vsi_handle)
1071 {
1072         enum ice_status status = ICE_SUCCESS;
1073
1074         if (!ice_is_bit_set(prof->vsis, vsi_handle)) {
1075                 status = ice_add_prof_id_flow(hw, blk,
1076                                               ice_get_hw_vsi_num(hw,
1077                                                                  vsi_handle),
1078                                               prof->id);
1079                 if (!status)
1080                         ice_set_bit(vsi_handle, prof->vsis);
1081                 else
1082                         ice_debug(hw, ICE_DBG_FLOW,
1083                                   "HW profile add failed, %d\n",
1084                                   status);
1085         }
1086
1087         return status;
1088 }
1089
1090 /**
1091  * ice_flow_disassoc_prof - disassociate a VSI from a flow profile
1092  * @hw: pointer to the hardware structure
1093  * @blk: classification stage
1094  * @prof: pointer to flow profile
1095  * @vsi_handle: software VSI handle
1096  *
1097  * Assumption: the caller has acquired the lock to the profile list
1098  * and the software VSI handle has been validated
1099  */
1100 static enum ice_status
1101 ice_flow_disassoc_prof(struct ice_hw *hw, enum ice_block blk,
1102                        struct ice_flow_prof *prof, u16 vsi_handle)
1103 {
1104         enum ice_status status = ICE_SUCCESS;
1105
1106         if (ice_is_bit_set(prof->vsis, vsi_handle)) {
1107                 status = ice_rem_prof_id_flow(hw, blk,
1108                                               ice_get_hw_vsi_num(hw,
1109                                                                  vsi_handle),
1110                                               prof->id);
1111                 if (!status)
1112                         ice_clear_bit(vsi_handle, prof->vsis);
1113                 else
1114                         ice_debug(hw, ICE_DBG_FLOW,
1115                                   "HW profile remove failed, %d\n",
1116                                   status);
1117         }
1118
1119         return status;
1120 }
1121
1122 /**
1123  * ice_flow_add_prof - Add a flow profile for packet segments and matched fields
1124  * @hw: pointer to the HW struct
1125  * @blk: classification stage
1126  * @dir: flow direction
1127  * @prof_id: unique ID to identify this flow profile
1128  * @segs: array of one or more packet segments that describe the flow
1129  * @segs_cnt: number of packet segments provided
1130  * @acts: array of default actions
1131  * @acts_cnt: number of default actions
1132  * @prof: stores the returned flow profile added
1133  */
1134 enum ice_status
1135 ice_flow_add_prof(struct ice_hw *hw, enum ice_block blk, enum ice_flow_dir dir,
1136                   u64 prof_id, struct ice_flow_seg_info *segs, u8 segs_cnt,
1137                   struct ice_flow_action *acts, u8 acts_cnt,
1138                   struct ice_flow_prof **prof)
1139 {
1140         enum ice_status status;
1141
1142         if (segs_cnt > ICE_FLOW_SEG_MAX)
1143                 return ICE_ERR_MAX_LIMIT;
1144
1145         if (!segs_cnt)
1146                 return ICE_ERR_PARAM;
1147
1148         if (!segs)
1149                 return ICE_ERR_BAD_PTR;
1150
1151         status = ice_flow_val_hdrs(segs, segs_cnt);
1152         if (status)
1153                 return status;
1154
1155         ice_acquire_lock(&hw->fl_profs_locks[blk]);
1156
1157         status = ice_flow_add_prof_sync(hw, blk, dir, prof_id, segs, segs_cnt,
1158                                         acts, acts_cnt, prof);
1159         if (!status)
1160                 LIST_ADD(&(*prof)->l_entry, &hw->fl_profs[blk]);
1161
1162         ice_release_lock(&hw->fl_profs_locks[blk]);
1163
1164         return status;
1165 }
1166
1167 /**
1168  * ice_flow_rem_prof - Remove a flow profile and all entries associated with it
1169  * @hw: pointer to the HW struct
1170  * @blk: the block for which the flow profile is to be removed
1171  * @prof_id: unique ID of the flow profile to be removed
1172  */
1173 enum ice_status
1174 ice_flow_rem_prof(struct ice_hw *hw, enum ice_block blk, u64 prof_id)
1175 {
1176         struct ice_flow_prof *prof;
1177         enum ice_status status;
1178
1179         ice_acquire_lock(&hw->fl_profs_locks[blk]);
1180
1181         prof = ice_flow_find_prof_id(hw, blk, prof_id);
1182         if (!prof) {
1183                 status = ICE_ERR_DOES_NOT_EXIST;
1184                 goto out;
1185         }
1186
1187         /* prof becomes invalid after the call */
1188         status = ice_flow_rem_prof_sync(hw, blk, prof);
1189
1190 out:
1191         ice_release_lock(&hw->fl_profs_locks[blk]);
1192
1193         return status;
1194 }
1195
1196 /**
1197  * ice_flow_get_hw_prof - return the HW profile for a specific profile ID handle
1198  * @hw: pointer to the HW struct
1199  * @blk: classification stage
1200  * @prof_id: the profile ID handle
1201  * @hw_prof_id: pointer to variable to receive the HW profile ID
1202  */
1203 enum ice_status
1204 ice_flow_get_hw_prof(struct ice_hw *hw, enum ice_block blk, u64 prof_id,
1205                      u8 *hw_prof_id)
1206 {
1207         struct ice_prof_map *map;
1208
1209         map = ice_search_prof_id(hw, blk, prof_id);
1210         if (map) {
1211                 *hw_prof_id = map->prof_id;
1212                 return ICE_SUCCESS;
1213         }
1214
1215         return ICE_ERR_DOES_NOT_EXIST;
1216 }
1217
1218 /**
1219  * ice_flow_find_entry - look for a flow entry using its unique ID
1220  * @hw: pointer to the HW struct
1221  * @blk: classification stage
1222  * @entry_id: unique ID to identify this flow entry
1223  *
1224  * This function looks for the flow entry with the specified unique ID in all
1225  * flow profiles of the specified classification stage. If the entry is found,
1226  * and it returns the handle to the flow entry. Otherwise, it returns
1227  * ICE_FLOW_ENTRY_ID_INVAL.
1228  */
1229 u64 ice_flow_find_entry(struct ice_hw *hw, enum ice_block blk, u64 entry_id)
1230 {
1231         struct ice_flow_entry *found = NULL;
1232         struct ice_flow_prof *p;
1233
1234         ice_acquire_lock(&hw->fl_profs_locks[blk]);
1235
1236         LIST_FOR_EACH_ENTRY(p, &hw->fl_profs[blk], ice_flow_prof, l_entry) {
1237                 struct ice_flow_entry *e;
1238
1239                 ice_acquire_lock(&p->entries_lock);
1240                 LIST_FOR_EACH_ENTRY(e, &p->entries, ice_flow_entry, l_entry)
1241                         if (e->id == entry_id) {
1242                                 found = e;
1243                                 break;
1244                         }
1245                 ice_release_lock(&p->entries_lock);
1246
1247                 if (found)
1248                         break;
1249         }
1250
1251         ice_release_lock(&hw->fl_profs_locks[blk]);
1252
1253         return found ? ICE_FLOW_ENTRY_HNDL(found) : ICE_FLOW_ENTRY_HANDLE_INVAL;
1254 }
1255
1256 /**
1257  * ice_flow_add_entry - Add a flow entry
1258  * @hw: pointer to the HW struct
1259  * @blk: classification stage
1260  * @prof_id: ID of the profile to add a new flow entry to
1261  * @entry_id: unique ID to identify this flow entry
1262  * @vsi_handle: software VSI handle for the flow entry
1263  * @prio: priority of the flow entry
1264  * @data: pointer to a data buffer containing flow entry's match values/masks
1265  * @acts: arrays of actions to be performed on a match
1266  * @acts_cnt: number of actions
1267  * @entry_h: pointer to buffer that receives the new flow entry's handle
1268  */
1269 enum ice_status
1270 ice_flow_add_entry(struct ice_hw *hw, enum ice_block blk, u64 prof_id,
1271                    u64 entry_id, u16 vsi_handle, enum ice_flow_priority prio,
1272                    void *data, struct ice_flow_action *acts, u8 acts_cnt,
1273                    u64 *entry_h)
1274 {
1275         struct ice_flow_prof *prof = NULL;
1276         struct ice_flow_entry *e = NULL;
1277         enum ice_status status = ICE_SUCCESS;
1278
1279         if (acts_cnt && !acts)
1280                 return ICE_ERR_PARAM;
1281
1282         /* No flow entry data is expected for RSS */
1283         if (!entry_h || (!data && blk != ICE_BLK_RSS))
1284                 return ICE_ERR_BAD_PTR;
1285
1286         if (!ice_is_vsi_valid(hw, vsi_handle))
1287                 return ICE_ERR_PARAM;
1288
1289         ice_acquire_lock(&hw->fl_profs_locks[blk]);
1290
1291         prof = ice_flow_find_prof_id(hw, blk, prof_id);
1292         if (!prof) {
1293                 status = ICE_ERR_DOES_NOT_EXIST;
1294         } else {
1295                 /* Allocate memory for the entry being added and associate
1296                  * the VSI to the found flow profile
1297                  */
1298                 e = (struct ice_flow_entry *)ice_malloc(hw, sizeof(*e));
1299                 if (!e)
1300                         status = ICE_ERR_NO_MEMORY;
1301                 else
1302                         status = ice_flow_assoc_prof(hw, blk, prof, vsi_handle);
1303         }
1304
1305         ice_release_lock(&hw->fl_profs_locks[blk]);
1306         if (status)
1307                 goto out;
1308
1309         e->id = entry_id;
1310         e->vsi_handle = vsi_handle;
1311         e->prof = prof;
1312         e->priority = prio;
1313
1314         switch (blk) {
1315         case ICE_BLK_RSS:
1316                 /* RSS will add only one entry per VSI per profile */
1317                 break;
1318         case ICE_BLK_FD:
1319                 break;
1320         case ICE_BLK_SW:
1321         case ICE_BLK_PE:
1322         default:
1323                 status = ICE_ERR_NOT_IMPL;
1324                 goto out;
1325         }
1326
1327         ice_acquire_lock(&prof->entries_lock);
1328         LIST_ADD(&e->l_entry, &prof->entries);
1329         ice_release_lock(&prof->entries_lock);
1330
1331         *entry_h = ICE_FLOW_ENTRY_HNDL(e);
1332
1333 out:
1334         if (status && e) {
1335                 if (e->entry)
1336                         ice_free(hw, e->entry);
1337                 ice_free(hw, e);
1338         }
1339
1340         return status;
1341 }
1342
1343 /**
1344  * ice_flow_rem_entry - Remove a flow entry
1345  * @hw: pointer to the HW struct
1346  * @entry_h: handle to the flow entry to be removed
1347  */
1348 enum ice_status ice_flow_rem_entry(struct ice_hw *hw, u64 entry_h)
1349 {
1350         struct ice_flow_entry *entry;
1351         struct ice_flow_prof *prof;
1352         enum ice_status status;
1353
1354         if (entry_h == ICE_FLOW_ENTRY_HANDLE_INVAL)
1355                 return ICE_ERR_PARAM;
1356
1357         entry = ICE_FLOW_ENTRY_PTR((unsigned long)entry_h);
1358
1359         /* Retain the pointer to the flow profile as the entry will be freed */
1360         prof = entry->prof;
1361
1362         ice_acquire_lock(&prof->entries_lock);
1363         status = ice_flow_rem_entry_sync(hw, entry);
1364         ice_release_lock(&prof->entries_lock);
1365
1366         return status;
1367 }
1368
1369 /**
1370  * ice_flow_set_fld_ext - specifies locations of field from entry's input buffer
1371  * @seg: packet segment the field being set belongs to
1372  * @fld: field to be set
1373  * @type: type of the field
1374  * @val_loc: if not ICE_FLOW_FLD_OFF_INVAL, location of the value to match from
1375  *           entry's input buffer
1376  * @mask_loc: if not ICE_FLOW_FLD_OFF_INVAL, location of mask value from entry's
1377  *            input buffer
1378  * @last_loc: if not ICE_FLOW_FLD_OFF_INVAL, location of last/upper value from
1379  *            entry's input buffer
1380  *
1381  * This helper function stores information of a field being matched, including
1382  * the type of the field and the locations of the value to match, the mask, and
1383  * and the upper-bound value in the start of the input buffer for a flow entry.
1384  * This function should only be used for fixed-size data structures.
1385  *
1386  * This function also opportunistically determines the protocol headers to be
1387  * present based on the fields being set. Some fields cannot be used alone to
1388  * determine the protocol headers present. Sometimes, fields for particular
1389  * protocol headers are not matched. In those cases, the protocol headers
1390  * must be explicitly set.
1391  */
1392 static void
1393 ice_flow_set_fld_ext(struct ice_flow_seg_info *seg, enum ice_flow_field fld,
1394                      enum ice_flow_fld_match_type type, u16 val_loc,
1395                      u16 mask_loc, u16 last_loc)
1396 {
1397         u64 bit = BIT_ULL(fld);
1398
1399         seg->match |= bit;
1400         if (type == ICE_FLOW_FLD_TYPE_RANGE)
1401                 seg->range |= bit;
1402
1403         seg->fields[fld].type = type;
1404         seg->fields[fld].src.val = val_loc;
1405         seg->fields[fld].src.mask = mask_loc;
1406         seg->fields[fld].src.last = last_loc;
1407
1408         ICE_FLOW_SET_HDRS(seg, ice_flds_info[fld].hdr);
1409 }
1410
1411 /**
1412  * ice_flow_set_fld - specifies locations of field from entry's input buffer
1413  * @seg: packet segment the field being set belongs to
1414  * @fld: field to be set
1415  * @val_loc: if not ICE_FLOW_FLD_OFF_INVAL, location of the value to match from
1416  *           entry's input buffer
1417  * @mask_loc: if not ICE_FLOW_FLD_OFF_INVAL, location of mask value from entry's
1418  *            input buffer
1419  * @last_loc: if not ICE_FLOW_FLD_OFF_INVAL, location of last/upper value from
1420  *            entry's input buffer
1421  * @range: indicate if field being matched is to be in a range
1422  *
1423  * This function specifies the locations, in the form of byte offsets from the
1424  * start of the input buffer for a flow entry, from where the value to match,
1425  * the mask value, and upper value can be extracted. These locations are then
1426  * stored in the flow profile. When adding a flow entry associated with the
1427  * flow profile, these locations will be used to quickly extract the values and
1428  * create the content of a match entry. This function should only be used for
1429  * fixed-size data structures.
1430  */
1431 void
1432 ice_flow_set_fld(struct ice_flow_seg_info *seg, enum ice_flow_field fld,
1433                  u16 val_loc, u16 mask_loc, u16 last_loc, bool range)
1434 {
1435         enum ice_flow_fld_match_type t = range ?
1436                 ICE_FLOW_FLD_TYPE_RANGE : ICE_FLOW_FLD_TYPE_REG;
1437
1438         ice_flow_set_fld_ext(seg, fld, t, val_loc, mask_loc, last_loc);
1439 }
1440
1441 /**
1442  * ice_flow_set_fld_prefix - sets locations of prefix field from entry's buf
1443  * @seg: packet segment the field being set belongs to
1444  * @fld: field to be set
1445  * @val_loc: if not ICE_FLOW_FLD_OFF_INVAL, location of the value to match from
1446  *           entry's input buffer
1447  * @pref_loc: location of prefix value from entry's input buffer
1448  * @pref_sz: size of the location holding the prefix value
1449  *
1450  * This function specifies the locations, in the form of byte offsets from the
1451  * start of the input buffer for a flow entry, from where the value to match
1452  * and the IPv4 prefix value can be extracted. These locations are then stored
1453  * in the flow profile. When adding flow entries to the associated flow profile,
1454  * these locations can be used to quickly extract the values to create the
1455  * content of a match entry. This function should only be used for fixed-size
1456  * data structures.
1457  */
1458 void
1459 ice_flow_set_fld_prefix(struct ice_flow_seg_info *seg, enum ice_flow_field fld,
1460                         u16 val_loc, u16 pref_loc, u8 pref_sz)
1461 {
1462         /* For this type of field, the "mask" location is for the prefix value's
1463          * location and the "last" location is for the size of the location of
1464          * the prefix value.
1465          */
1466         ice_flow_set_fld_ext(seg, fld, ICE_FLOW_FLD_TYPE_PREFIX, val_loc,
1467                              pref_loc, (u16)pref_sz);
1468 }
1469
1470 /**
1471  * ice_flow_add_fld_raw - sets locations of a raw field from entry's input buf
1472  * @seg: packet segment the field being set belongs to
1473  * @off: offset of the raw field from the beginning of the segment in bytes
1474  * @len: length of the raw pattern to be matched
1475  * @val_loc: location of the value to match from entry's input buffer
1476  * @mask_loc: location of mask value from entry's input buffer
1477  *
1478  * This function specifies the offset of the raw field to be match from the
1479  * beginning of the specified packet segment, and the locations, in the form of
1480  * byte offsets from the start of the input buffer for a flow entry, from where
1481  * the value to match and the mask value to be extracted. These locations are
1482  * then stored in the flow profile. When adding flow entries to the associated
1483  * flow profile, these locations can be used to quickly extract the values to
1484  * create the content of a match entry. This function should only be used for
1485  * fixed-size data structures.
1486  */
1487 void
1488 ice_flow_add_fld_raw(struct ice_flow_seg_info *seg, u16 off, u8 len,
1489                      u16 val_loc, u16 mask_loc)
1490 {
1491         if (seg->raws_cnt < ICE_FLOW_SEG_RAW_FLD_MAX) {
1492                 seg->raws[seg->raws_cnt].off = off;
1493                 seg->raws[seg->raws_cnt].info.type = ICE_FLOW_FLD_TYPE_SIZE;
1494                 seg->raws[seg->raws_cnt].info.src.val = val_loc;
1495                 seg->raws[seg->raws_cnt].info.src.mask = mask_loc;
1496                 /* The "last" field is used to store the length of the field */
1497                 seg->raws[seg->raws_cnt].info.src.last = len;
1498         }
1499
1500         /* Overflows of "raws" will be handled as an error condition later in
1501          * the flow when this information is processed.
1502          */
1503         seg->raws_cnt++;
1504 }
1505
1506 #define ICE_FLOW_RSS_SEG_HDR_L3_MASKS \
1507         (ICE_FLOW_SEG_HDR_IPV4 | ICE_FLOW_SEG_HDR_IPV6)
1508
1509 #define ICE_FLOW_RSS_SEG_HDR_L4_MASKS \
1510         (ICE_FLOW_SEG_HDR_TCP | ICE_FLOW_SEG_HDR_UDP | \
1511          ICE_FLOW_SEG_HDR_SCTP)
1512
1513 #define ICE_FLOW_RSS_SEG_HDR_VAL_MASKS \
1514         (ICE_FLOW_RSS_SEG_HDR_L3_MASKS | \
1515          ICE_FLOW_RSS_SEG_HDR_L4_MASKS)
1516
1517 /**
1518  * ice_flow_set_rss_seg_info - setup packet segments for RSS
1519  * @segs: pointer to the flow field segment(s)
1520  * @hash_fields: fields to be hashed on for the segment(s)
1521  * @flow_hdr: protocol header fields within a packet segment
1522  *
1523  * Helper function to extract fields from hash bitmap and use flow
1524  * header value to set flow field segment for further use in flow
1525  * profile entry or removal.
1526  */
1527 static enum ice_status
1528 ice_flow_set_rss_seg_info(struct ice_flow_seg_info *segs, u64 hash_fields,
1529                           u32 flow_hdr)
1530 {
1531         u64 val = hash_fields;
1532         u8 i;
1533
1534         for (i = 0; val && i < ICE_FLOW_FIELD_IDX_MAX; i++) {
1535                 u64 bit = BIT_ULL(i);
1536
1537                 if (val & bit) {
1538                         ice_flow_set_fld(segs, (enum ice_flow_field)i,
1539                                          ICE_FLOW_FLD_OFF_INVAL,
1540                                          ICE_FLOW_FLD_OFF_INVAL,
1541                                          ICE_FLOW_FLD_OFF_INVAL, false);
1542                         val &= ~bit;
1543                 }
1544         }
1545         ICE_FLOW_SET_HDRS(segs, flow_hdr);
1546
1547         if (segs->hdrs & ~ICE_FLOW_RSS_SEG_HDR_VAL_MASKS)
1548                 return ICE_ERR_PARAM;
1549
1550         val = (u64)(segs->hdrs & ICE_FLOW_RSS_SEG_HDR_L3_MASKS);
1551         if (!ice_is_pow2(val))
1552                 return ICE_ERR_CFG;
1553
1554         val = (u64)(segs->hdrs & ICE_FLOW_RSS_SEG_HDR_L4_MASKS);
1555         if (val && !ice_is_pow2(val))
1556                 return ICE_ERR_CFG;
1557
1558         return ICE_SUCCESS;
1559 }
1560
1561 /**
1562  * ice_rem_all_rss_vsi_ctx - remove all RSS configurations from VSI context
1563  * @hw: pointer to the hardware structure
1564  * @vsi_handle: software VSI handle
1565  *
1566  */
1567 void ice_rem_all_rss_vsi_ctx(struct ice_hw *hw, u16 vsi_handle)
1568 {
1569         struct ice_rss_cfg *r, *tmp;
1570
1571         if (!ice_is_vsi_valid(hw, vsi_handle) ||
1572             LIST_EMPTY(&hw->vsi_ctx[vsi_handle]->rss_list_head))
1573                 return;
1574
1575         ice_acquire_lock(&hw->vsi_ctx[vsi_handle]->rss_locks);
1576         LIST_FOR_EACH_ENTRY_SAFE(r, tmp,
1577                                  &hw->vsi_ctx[vsi_handle]->rss_list_head,
1578                                  ice_rss_cfg, l_entry) {
1579                 LIST_DEL(&r->l_entry);
1580                 ice_free(hw, r);
1581         }
1582         ice_release_lock(&hw->vsi_ctx[vsi_handle]->rss_locks);
1583 }
1584
1585 /**
1586  * ice_rem_vsi_rss_cfg - remove RSS configurations associated with VSI
1587  * @hw: pointer to the hardware structure
1588  * @vsi_handle: software VSI handle
1589  *
1590  * This function will iterate through all flow profiles and disassociate
1591  * the VSI from that profile. If the flow profile has no VSIs it will
1592  * be removed.
1593  */
1594 enum ice_status ice_rem_vsi_rss_cfg(struct ice_hw *hw, u16 vsi_handle)
1595 {
1596         const enum ice_block blk = ICE_BLK_RSS;
1597         struct ice_flow_prof *p, *t;
1598         enum ice_status status = ICE_SUCCESS;
1599
1600         if (!ice_is_vsi_valid(hw, vsi_handle))
1601                 return ICE_ERR_PARAM;
1602
1603         ice_acquire_lock(&hw->fl_profs_locks[blk]);
1604         LIST_FOR_EACH_ENTRY_SAFE(p, t, &hw->fl_profs[blk], ice_flow_prof,
1605                                  l_entry) {
1606                 if (ice_is_bit_set(p->vsis, vsi_handle)) {
1607                         status = ice_flow_disassoc_prof(hw, blk, p, vsi_handle);
1608                         if (status)
1609                                 break;
1610
1611                         if (!ice_is_any_bit_set(p->vsis, ICE_MAX_VSI)) {
1612                                 status = ice_flow_rem_prof_sync(hw, blk, p);
1613                                 if (status)
1614                                         break;
1615                         }
1616                 }
1617         }
1618         ice_release_lock(&hw->fl_profs_locks[blk]);
1619
1620         return status;
1621 }
1622
1623 /**
1624  * ice_rem_rss_cfg_vsi_ctx - remove RSS configuration from VSI context
1625  * @hw: pointer to the hardware structure
1626  * @vsi_handle: software VSI handle
1627  * @prof: pointer to flow profile
1628  *
1629  * Assumption: lock has already been acquired for RSS list
1630  */
1631 static void
1632 ice_rem_rss_cfg_vsi_ctx(struct ice_hw *hw, u16 vsi_handle,
1633                         struct ice_flow_prof *prof)
1634 {
1635         struct ice_rss_cfg *r, *tmp;
1636
1637         /* Search for RSS hash fields associated to the VSI that match the
1638          * hash configurations associated to the flow profile. If found
1639          * remove from the RSS entry list of the VSI context and delete entry.
1640          */
1641         LIST_FOR_EACH_ENTRY_SAFE(r, tmp,
1642                                  &hw->vsi_ctx[vsi_handle]->rss_list_head,
1643                                  ice_rss_cfg, l_entry) {
1644                 if (r->hashed_flds == prof->segs[prof->segs_cnt - 1].match &&
1645                     r->packet_hdr == prof->segs[prof->segs_cnt - 1].hdrs) {
1646                         LIST_DEL(&r->l_entry);
1647                         ice_free(hw, r);
1648                         return;
1649                 }
1650         }
1651 }
1652
1653 /**
1654  * ice_add_rss_vsi_ctx - add RSS configuration to VSI context
1655  * @hw: pointer to the hardware structure
1656  * @vsi_handle: software VSI handle
1657  * @prof: pointer to flow profile
1658  *
1659  * Assumption: lock has already been acquired for RSS list
1660  */
1661 static enum ice_status
1662 ice_add_rss_vsi_ctx(struct ice_hw *hw, u16 vsi_handle,
1663                     struct ice_flow_prof *prof)
1664 {
1665         struct ice_rss_cfg *r, *rss_cfg;
1666
1667         LIST_FOR_EACH_ENTRY(r, &hw->vsi_ctx[vsi_handle]->rss_list_head,
1668                             ice_rss_cfg, l_entry)
1669                 if (r->hashed_flds == prof->segs[prof->segs_cnt - 1].match &&
1670                     r->packet_hdr == prof->segs[prof->segs_cnt - 1].hdrs)
1671                         return ICE_SUCCESS;
1672
1673         rss_cfg = (struct ice_rss_cfg *)ice_malloc(hw, sizeof(*rss_cfg));
1674         if (!rss_cfg)
1675                 return ICE_ERR_NO_MEMORY;
1676
1677         rss_cfg->hashed_flds = prof->segs[prof->segs_cnt - 1].match;
1678         rss_cfg->packet_hdr = prof->segs[prof->segs_cnt - 1].hdrs;
1679         LIST_ADD_TAIL(&rss_cfg->l_entry,
1680                       &hw->vsi_ctx[vsi_handle]->rss_list_head);
1681
1682         return ICE_SUCCESS;
1683 }
1684
1685 #define ICE_FLOW_PROF_HASH_S    0
1686 #define ICE_FLOW_PROF_HASH_M    (0xFFFFFFFFULL << ICE_FLOW_PROF_HASH_S)
1687 #define ICE_FLOW_PROF_HDR_S     32
1688 #define ICE_FLOW_PROF_HDR_M     (0xFFFFFFFFULL << ICE_FLOW_PROF_HDR_S)
1689
1690 #define ICE_FLOW_GEN_PROFID(hash, hdr) \
1691         (u64)(((u64)(hash) & ICE_FLOW_PROF_HASH_M) | \
1692               (((u64)(hdr) << ICE_FLOW_PROF_HDR_S) & ICE_FLOW_PROF_HDR_M))
1693
1694 /**
1695  * ice_add_rss_cfg_sync - add an RSS configuration
1696  * @hw: pointer to the hardware structure
1697  * @vsi_handle: software VSI handle
1698  * @hashed_flds: hash bit fields (ICE_FLOW_HASH_*) to configure
1699  * @addl_hdrs: protocol header fields
1700  *
1701  * Assumption: lock has already been acquired for RSS list
1702  */
1703 static enum ice_status
1704 ice_add_rss_cfg_sync(struct ice_hw *hw, u16 vsi_handle, u64 hashed_flds,
1705                      u32 addl_hdrs)
1706 {
1707         const enum ice_block blk = ICE_BLK_RSS;
1708         struct ice_flow_prof *prof = NULL;
1709         struct ice_flow_seg_info *segs;
1710         enum ice_status status = ICE_SUCCESS;
1711
1712         segs = (struct ice_flow_seg_info *)ice_malloc(hw, sizeof(*segs));
1713         if (!segs)
1714                 return ICE_ERR_NO_MEMORY;
1715
1716         /* Construct the packet segment info from the hashed fields */
1717         status = ice_flow_set_rss_seg_info(segs, hashed_flds, addl_hdrs);
1718         if (status)
1719                 goto exit;
1720
1721         /* Search for a flow profile that has matching headers, hash fields
1722          * and has the input VSI associated to it. If found, no further
1723          * operations required and exit.
1724          */
1725         prof = ice_flow_find_prof_conds(hw, blk, ICE_FLOW_RX, segs, 1,
1726                                         vsi_handle,
1727                                         ICE_FLOW_FIND_PROF_CHK_FLDS |
1728                                         ICE_FLOW_FIND_PROF_CHK_VSI);
1729         if (prof)
1730                 goto exit;
1731
1732         /* Check if a flow profile exists with the same protocol headers and
1733          * associated with the input VSI. If so disasscociate the VSI from
1734          * this profile. The VSI will be added to a new profile created with
1735          * the protocol header and new hash field configuration.
1736          */
1737         prof = ice_flow_find_prof_conds(hw, blk, ICE_FLOW_RX, segs, 1,
1738                                         vsi_handle, ICE_FLOW_FIND_PROF_CHK_VSI);
1739         if (prof) {
1740                 status = ice_flow_disassoc_prof(hw, blk, prof, vsi_handle);
1741                 if (!status)
1742                         ice_rem_rss_cfg_vsi_ctx(hw, vsi_handle, prof);
1743                 else
1744                         goto exit;
1745
1746                 /* Remove profile if it has no VSIs associated */
1747                 if (!ice_is_any_bit_set(prof->vsis, ICE_MAX_VSI)) {
1748                         status = ice_flow_rem_prof_sync(hw, blk, prof);
1749                         if (status)
1750                                 goto exit;
1751                 }
1752         }
1753
1754         /* Search for a profile that has same match fields only. If this
1755          * exists then associate the VSI to this profile.
1756          */
1757         prof = ice_flow_find_prof_conds(hw, blk, ICE_FLOW_RX, segs, 1,
1758                                         vsi_handle,
1759                                         ICE_FLOW_FIND_PROF_CHK_FLDS);
1760         if (prof) {
1761                 status = ice_flow_assoc_prof(hw, blk, prof, vsi_handle);
1762                 if (!status)
1763                         status = ice_add_rss_vsi_ctx(hw, vsi_handle, prof);
1764                 goto exit;
1765         }
1766
1767         /* Create a new flow profile with generated profile and packet
1768          * segment information.
1769          */
1770         status = ice_flow_add_prof(hw, blk, ICE_FLOW_RX,
1771                                    ICE_FLOW_GEN_PROFID(hashed_flds, segs->hdrs),
1772                                    segs, 1, NULL, 0, &prof);
1773         if (status)
1774                 goto exit;
1775
1776         status = ice_flow_assoc_prof(hw, blk, prof, vsi_handle);
1777         /* If association to a new flow profile failed then this profile can
1778          * be removed.
1779          */
1780         if (status) {
1781                 ice_flow_rem_prof_sync(hw, blk, prof);
1782                 goto exit;
1783         }
1784
1785         status = ice_add_rss_vsi_ctx(hw, vsi_handle, prof);
1786
1787 exit:
1788         ice_free(hw, segs);
1789         return status;
1790 }
1791
1792 /**
1793  * ice_add_rss_cfg - add an RSS configuration with specified hashed fields
1794  * @hw: pointer to the hardware structure
1795  * @vsi_handle: software VSI handle
1796  * @hashed_flds: hash bit fields (ICE_FLOW_HASH_*) to configure
1797  * @addl_hdrs: protocol header fields
1798  *
1799  * This function will generate a flow profile based on fields associated with
1800  * the input fields to hash on, the flow type and use the VSI number to add
1801  * a flow entry to the profile.
1802  */
1803 enum ice_status
1804 ice_add_rss_cfg(struct ice_hw *hw, u16 vsi_handle, u64 hashed_flds,
1805                 u32 addl_hdrs)
1806 {
1807         enum ice_status status;
1808
1809         if (hashed_flds == ICE_HASH_INVALID ||
1810             !ice_is_vsi_valid(hw, vsi_handle))
1811                 return ICE_ERR_PARAM;
1812
1813         ice_acquire_lock(&hw->vsi_ctx[vsi_handle]->rss_locks);
1814         status = ice_add_rss_cfg_sync(hw, vsi_handle, hashed_flds, addl_hdrs);
1815         ice_release_lock(&hw->vsi_ctx[vsi_handle]->rss_locks);
1816
1817         return status;
1818 }
1819
1820 /**
1821  * ice_rem_rss_cfg_sync - remove an existing RSS configuration
1822  * @hw: pointer to the hardware structure
1823  * @vsi_handle: software VSI handle
1824  * @hashed_flds: Packet hash types (ICE_FLOW_HASH_*) to remove
1825  * @addl_hdrs: Protocol header fields within a packet segment
1826  *
1827  * Assumption: lock has already been acquired for RSS list
1828  */
1829 static enum ice_status
1830 ice_rem_rss_cfg_sync(struct ice_hw *hw, u16 vsi_handle, u64 hashed_flds,
1831                      u32 addl_hdrs)
1832 {
1833         const enum ice_block blk = ICE_BLK_RSS;
1834         struct ice_flow_seg_info *segs;
1835         struct ice_flow_prof *prof;
1836         enum ice_status status;
1837
1838         segs = (struct ice_flow_seg_info *)ice_malloc(hw, sizeof(*segs));
1839         if (!segs)
1840                 return ICE_ERR_NO_MEMORY;
1841
1842         /* Construct the packet segment info from the hashed fields */
1843         status = ice_flow_set_rss_seg_info(segs, hashed_flds, addl_hdrs);
1844         if (status)
1845                 goto out;
1846
1847         prof = ice_flow_find_prof_conds(hw, blk, ICE_FLOW_RX, segs, 1,
1848                                         vsi_handle,
1849                                         ICE_FLOW_FIND_PROF_CHK_FLDS);
1850         if (!prof) {
1851                 status = ICE_ERR_DOES_NOT_EXIST;
1852                 goto out;
1853         }
1854
1855         status = ice_flow_disassoc_prof(hw, blk, prof, vsi_handle);
1856         if (status)
1857                 goto out;
1858
1859         /* Remove RSS configuration from VSI context before deleting
1860          * the flow profile.
1861          */
1862         ice_rem_rss_cfg_vsi_ctx(hw, vsi_handle, prof);
1863
1864         if (!ice_is_any_bit_set(prof->vsis, ICE_MAX_VSI))
1865                 status = ice_flow_rem_prof_sync(hw, blk, prof);
1866
1867 out:
1868         ice_free(hw, segs);
1869         return status;
1870 }
1871
1872 /**
1873  * ice_rem_rss_cfg - remove an existing RSS config with matching hashed fields
1874  * @hw: pointer to the hardware structure
1875  * @vsi_handle: software VSI handle
1876  * @hashed_flds: Packet hash types (ICE_FLOW_HASH_*) to remove
1877  * @addl_hdrs: Protocol header fields within a packet segment
1878  *
1879  * This function will lookup the flow profile based on the input
1880  * hash field bitmap, iterate through the profile entry list of
1881  * that profile and find entry associated with input VSI to be
1882  * removed. Calls are made to underlying flow apis which will in
1883  * turn build or update buffers for RSS XLT1 section.
1884  */
1885 enum ice_status
1886 ice_rem_rss_cfg(struct ice_hw *hw, u16 vsi_handle, u64 hashed_flds,
1887                 u32 addl_hdrs)
1888 {
1889         enum ice_status status;
1890
1891         if (hashed_flds == ICE_HASH_INVALID ||
1892             !ice_is_vsi_valid(hw, vsi_handle))
1893                 return ICE_ERR_PARAM;
1894
1895         ice_acquire_lock(&hw->vsi_ctx[vsi_handle]->rss_locks);
1896         status = ice_rem_rss_cfg_sync(hw, vsi_handle, hashed_flds, addl_hdrs);
1897         ice_release_lock(&hw->vsi_ctx[vsi_handle]->rss_locks);
1898
1899         return status;
1900 }
1901
1902 /**
1903  * ice_replay_rss_cfg - remove RSS configurations associated with VSI
1904  * @hw: pointer to the hardware structure
1905  * @vsi_handle: software VSI handle
1906  */
1907 enum ice_status ice_replay_rss_cfg(struct ice_hw *hw, u16 vsi_handle)
1908 {
1909         enum ice_status status = ICE_SUCCESS;
1910         struct ice_rss_cfg *r;
1911
1912         if (!ice_is_vsi_valid(hw, vsi_handle))
1913                 return ICE_ERR_PARAM;
1914
1915         ice_acquire_lock(&hw->vsi_ctx[vsi_handle]->rss_locks);
1916         LIST_FOR_EACH_ENTRY(r, &hw->vsi_ctx[vsi_handle]->rss_list_head,
1917                             ice_rss_cfg, l_entry) {
1918                 status = ice_add_rss_cfg_sync(hw, vsi_handle, r->hashed_flds,
1919                                               r->packet_hdr);
1920                 if (status)
1921                         break;
1922         }
1923         ice_release_lock(&hw->vsi_ctx[vsi_handle]->rss_locks);
1924
1925         return status;
1926 }
1927
1928 /**
1929  * ice_get_rss_cfg - returns hashed fields for the given header types
1930  * @hw: pointer to the hardware structure
1931  * @vsi_handle: software VSI handle
1932  * @hdrs: protocol header type
1933  *
1934  * This function will return the match fields of the first instance of flow
1935  * profile having the given header types and containing input VSI
1936  */
1937 u64 ice_get_rss_cfg(struct ice_hw *hw, u16 vsi_handle, u32 hdrs)
1938 {
1939         struct ice_rss_cfg *r, *rss_cfg = NULL;
1940
1941         /* verify if the protocol header is non zero and VSI is valid */
1942         if (hdrs == ICE_FLOW_SEG_HDR_NONE || !ice_is_vsi_valid(hw, vsi_handle))
1943                 return ICE_HASH_INVALID;
1944
1945         ice_acquire_lock(&hw->vsi_ctx[vsi_handle]->rss_locks);
1946         LIST_FOR_EACH_ENTRY(r, &hw->vsi_ctx[vsi_handle]->rss_list_head,
1947                             ice_rss_cfg, l_entry)
1948                 if (r->packet_hdr == hdrs) {
1949                         rss_cfg = r;
1950                         break;
1951                 }
1952         ice_release_lock(&hw->vsi_ctx[vsi_handle]->rss_locks);
1953
1954         return rss_cfg ? rss_cfg->hashed_flds : ICE_HASH_INVALID;
1955 }