428002c2832bcd41f04b41564b36c38967f20578
[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
916         ice_free(hw, entry);
917
918         return ICE_SUCCESS;
919 }
920
921 /**
922  * ice_flow_add_prof_sync - Add a flow profile for packet segments and fields
923  * @hw: pointer to the HW struct
924  * @blk: classification stage
925  * @dir: flow direction
926  * @prof_id: unique ID to identify this flow profile
927  * @segs: array of one or more packet segments that describe the flow
928  * @segs_cnt: number of packet segments provided
929  * @acts: array of default actions
930  * @acts_cnt: number of default actions
931  * @prof: stores the returned flow profile added
932  *
933  * Assumption: the caller has acquired the lock to the profile list
934  */
935 static enum ice_status
936 ice_flow_add_prof_sync(struct ice_hw *hw, enum ice_block blk,
937                        enum ice_flow_dir dir, u64 prof_id,
938                        struct ice_flow_seg_info *segs, u8 segs_cnt,
939                        struct ice_flow_action *acts, u8 acts_cnt,
940                        struct ice_flow_prof **prof)
941 {
942         struct ice_flow_prof_params params;
943         enum ice_status status = ICE_SUCCESS;
944         u8 i;
945
946         if (!prof || (acts_cnt && !acts))
947                 return ICE_ERR_BAD_PTR;
948
949         ice_memset(&params, 0, sizeof(params), ICE_NONDMA_MEM);
950         params.prof = (struct ice_flow_prof *)
951                 ice_malloc(hw, sizeof(*params.prof));
952         if (!params.prof)
953                 return ICE_ERR_NO_MEMORY;
954
955         /* initialize extraction sequence to all invalid (0xff) */
956         ice_memset(params.es, 0xff, sizeof(params.es), ICE_NONDMA_MEM);
957
958         params.blk = blk;
959         params.prof->id = prof_id;
960         params.prof->dir = dir;
961         params.prof->segs_cnt = segs_cnt;
962
963         /* Make a copy of the segments that need to be persistent in the flow
964          * profile instance
965          */
966         for (i = 0; i < segs_cnt; i++)
967                 ice_memcpy(&params.prof->segs[i], &segs[i], sizeof(*segs),
968                            ICE_NONDMA_TO_NONDMA);
969
970         /* Make a copy of the actions that need to be persistent in the flow
971          * profile instance.
972          */
973         if (acts_cnt) {
974                 params.prof->acts = (struct ice_flow_action *)
975                         ice_memdup(hw, acts, acts_cnt * sizeof(*acts),
976                                    ICE_NONDMA_TO_NONDMA);
977
978                 if (!params.prof->acts) {
979                         status = ICE_ERR_NO_MEMORY;
980                         goto out;
981                 }
982         }
983
984         status = ice_flow_proc_segs(hw, &params);
985         if (status) {
986                 ice_debug(hw, ICE_DBG_FLOW,
987                           "Error processing a flow's packet segments\n");
988                 goto out;
989         }
990
991         /* Add a HW profile for this flow profile */
992         status = ice_add_prof(hw, blk, prof_id, (u8 *)params.ptypes, params.es);
993         if (status) {
994                 ice_debug(hw, ICE_DBG_FLOW, "Error adding a HW flow profile\n");
995                 goto out;
996         }
997
998         INIT_LIST_HEAD(&params.prof->entries);
999         ice_init_lock(&params.prof->entries_lock);
1000         *prof = params.prof;
1001
1002 out:
1003         if (status) {
1004                 if (params.prof->acts)
1005                         ice_free(hw, params.prof->acts);
1006                 ice_free(hw, params.prof);
1007         }
1008
1009         return status;
1010 }
1011
1012 /**
1013  * ice_flow_rem_prof_sync - remove a flow profile
1014  * @hw: pointer to the hardware structure
1015  * @blk: classification stage
1016  * @prof: pointer to flow profile to remove
1017  *
1018  * Assumption: the caller has acquired the lock to the profile list
1019  */
1020 static enum ice_status
1021 ice_flow_rem_prof_sync(struct ice_hw *hw, enum ice_block blk,
1022                        struct ice_flow_prof *prof)
1023 {
1024         enum ice_status status = ICE_SUCCESS;
1025
1026         /* Remove all remaining flow entries before removing the flow profile */
1027         if (!LIST_EMPTY(&prof->entries)) {
1028                 struct ice_flow_entry *e, *t;
1029
1030                 ice_acquire_lock(&prof->entries_lock);
1031
1032                 LIST_FOR_EACH_ENTRY_SAFE(e, t, &prof->entries, ice_flow_entry,
1033                                          l_entry) {
1034                         status = ice_flow_rem_entry_sync(hw, e);
1035                         if (status)
1036                                 break;
1037                 }
1038
1039                 ice_release_lock(&prof->entries_lock);
1040         }
1041
1042         /* Remove all hardware profiles associated with this flow profile */
1043         status = ice_rem_prof(hw, blk, prof->id);
1044         if (!status) {
1045                 LIST_DEL(&prof->l_entry);
1046                 ice_destroy_lock(&prof->entries_lock);
1047                 if (prof->acts)
1048                         ice_free(hw, prof->acts);
1049                 ice_free(hw, prof);
1050         }
1051
1052         return status;
1053 }
1054
1055 /**
1056  * ice_flow_assoc_prof - associate a VSI with a flow profile
1057  * @hw: pointer to the hardware structure
1058  * @blk: classification stage
1059  * @prof: pointer to flow profile
1060  * @vsi_handle: software VSI handle
1061  *
1062  * Assumption: the caller has acquired the lock to the profile list
1063  * and the software VSI handle has been validated
1064  */
1065 static enum ice_status
1066 ice_flow_assoc_prof(struct ice_hw *hw, enum ice_block blk,
1067                     struct ice_flow_prof *prof, u16 vsi_handle)
1068 {
1069         enum ice_status status = ICE_SUCCESS;
1070
1071         if (!ice_is_bit_set(prof->vsis, vsi_handle)) {
1072                 status = ice_add_prof_id_flow(hw, blk,
1073                                               ice_get_hw_vsi_num(hw,
1074                                                                  vsi_handle),
1075                                               prof->id);
1076                 if (!status)
1077                         ice_set_bit(vsi_handle, prof->vsis);
1078                 else
1079                         ice_debug(hw, ICE_DBG_FLOW,
1080                                   "HW profile add failed, %d\n",
1081                                   status);
1082         }
1083
1084         return status;
1085 }
1086
1087 /**
1088  * ice_flow_disassoc_prof - disassociate a VSI from a flow profile
1089  * @hw: pointer to the hardware structure
1090  * @blk: classification stage
1091  * @prof: pointer to flow profile
1092  * @vsi_handle: software VSI handle
1093  *
1094  * Assumption: the caller has acquired the lock to the profile list
1095  * and the software VSI handle has been validated
1096  */
1097 static enum ice_status
1098 ice_flow_disassoc_prof(struct ice_hw *hw, enum ice_block blk,
1099                        struct ice_flow_prof *prof, u16 vsi_handle)
1100 {
1101         enum ice_status status = ICE_SUCCESS;
1102
1103         if (ice_is_bit_set(prof->vsis, vsi_handle)) {
1104                 status = ice_rem_prof_id_flow(hw, blk,
1105                                               ice_get_hw_vsi_num(hw,
1106                                                                  vsi_handle),
1107                                               prof->id);
1108                 if (!status)
1109                         ice_clear_bit(vsi_handle, prof->vsis);
1110                 else
1111                         ice_debug(hw, ICE_DBG_FLOW,
1112                                   "HW profile remove failed, %d\n",
1113                                   status);
1114         }
1115
1116         return status;
1117 }
1118
1119 /**
1120  * ice_flow_add_prof - Add a flow profile for packet segments and matched fields
1121  * @hw: pointer to the HW struct
1122  * @blk: classification stage
1123  * @dir: flow direction
1124  * @prof_id: unique ID to identify this flow profile
1125  * @segs: array of one or more packet segments that describe the flow
1126  * @segs_cnt: number of packet segments provided
1127  * @acts: array of default actions
1128  * @acts_cnt: number of default actions
1129  * @prof: stores the returned flow profile added
1130  */
1131 enum ice_status
1132 ice_flow_add_prof(struct ice_hw *hw, enum ice_block blk, enum ice_flow_dir dir,
1133                   u64 prof_id, struct ice_flow_seg_info *segs, u8 segs_cnt,
1134                   struct ice_flow_action *acts, u8 acts_cnt,
1135                   struct ice_flow_prof **prof)
1136 {
1137         enum ice_status status;
1138
1139         if (segs_cnt > ICE_FLOW_SEG_MAX)
1140                 return ICE_ERR_MAX_LIMIT;
1141
1142         if (!segs_cnt)
1143                 return ICE_ERR_PARAM;
1144
1145         if (!segs)
1146                 return ICE_ERR_BAD_PTR;
1147
1148         status = ice_flow_val_hdrs(segs, segs_cnt);
1149         if (status)
1150                 return status;
1151
1152         ice_acquire_lock(&hw->fl_profs_locks[blk]);
1153
1154         status = ice_flow_add_prof_sync(hw, blk, dir, prof_id, segs, segs_cnt,
1155                                         acts, acts_cnt, prof);
1156         if (!status)
1157                 LIST_ADD(&(*prof)->l_entry, &hw->fl_profs[blk]);
1158
1159         ice_release_lock(&hw->fl_profs_locks[blk]);
1160
1161         return status;
1162 }
1163
1164 /**
1165  * ice_flow_rem_prof - Remove a flow profile and all entries associated with it
1166  * @hw: pointer to the HW struct
1167  * @blk: the block for which the flow profile is to be removed
1168  * @prof_id: unique ID of the flow profile to be removed
1169  */
1170 enum ice_status
1171 ice_flow_rem_prof(struct ice_hw *hw, enum ice_block blk, u64 prof_id)
1172 {
1173         struct ice_flow_prof *prof;
1174         enum ice_status status;
1175
1176         ice_acquire_lock(&hw->fl_profs_locks[blk]);
1177
1178         prof = ice_flow_find_prof_id(hw, blk, prof_id);
1179         if (!prof) {
1180                 status = ICE_ERR_DOES_NOT_EXIST;
1181                 goto out;
1182         }
1183
1184         /* prof becomes invalid after the call */
1185         status = ice_flow_rem_prof_sync(hw, blk, prof);
1186
1187 out:
1188         ice_release_lock(&hw->fl_profs_locks[blk]);
1189
1190         return status;
1191 }
1192
1193 /**
1194  * ice_flow_get_hw_prof - return the HW profile for a specific profile ID handle
1195  * @hw: pointer to the HW struct
1196  * @blk: classification stage
1197  * @prof_id: the profile ID handle
1198  * @hw_prof_id: pointer to variable to receive the HW profile ID
1199  */
1200 enum ice_status
1201 ice_flow_get_hw_prof(struct ice_hw *hw, enum ice_block blk, u64 prof_id,
1202                      u8 *hw_prof_id)
1203 {
1204         struct ice_prof_map *map;
1205
1206         map = ice_search_prof_id(hw, blk, prof_id);
1207         if (map) {
1208                 *hw_prof_id = map->prof_id;
1209                 return ICE_SUCCESS;
1210         }
1211
1212         return ICE_ERR_DOES_NOT_EXIST;
1213 }
1214
1215 /**
1216  * ice_flow_find_entry - look for a flow entry using its unique ID
1217  * @hw: pointer to the HW struct
1218  * @blk: classification stage
1219  * @entry_id: unique ID to identify this flow entry
1220  *
1221  * This function looks for the flow entry with the specified unique ID in all
1222  * flow profiles of the specified classification stage. If the entry is found,
1223  * and it returns the handle to the flow entry. Otherwise, it returns
1224  * ICE_FLOW_ENTRY_ID_INVAL.
1225  */
1226 u64 ice_flow_find_entry(struct ice_hw *hw, enum ice_block blk, u64 entry_id)
1227 {
1228         struct ice_flow_entry *found = NULL;
1229         struct ice_flow_prof *p;
1230
1231         ice_acquire_lock(&hw->fl_profs_locks[blk]);
1232
1233         LIST_FOR_EACH_ENTRY(p, &hw->fl_profs[blk], ice_flow_prof, l_entry) {
1234                 struct ice_flow_entry *e;
1235
1236                 ice_acquire_lock(&p->entries_lock);
1237                 LIST_FOR_EACH_ENTRY(e, &p->entries, ice_flow_entry, l_entry)
1238                         if (e->id == entry_id) {
1239                                 found = e;
1240                                 break;
1241                         }
1242                 ice_release_lock(&p->entries_lock);
1243
1244                 if (found)
1245                         break;
1246         }
1247
1248         ice_release_lock(&hw->fl_profs_locks[blk]);
1249
1250         return found ? ICE_FLOW_ENTRY_HNDL(found) : ICE_FLOW_ENTRY_HANDLE_INVAL;
1251 }
1252
1253 /**
1254  * ice_flow_add_entry - Add a flow entry
1255  * @hw: pointer to the HW struct
1256  * @blk: classification stage
1257  * @prof_id: ID of the profile to add a new flow entry to
1258  * @entry_id: unique ID to identify this flow entry
1259  * @vsi_handle: software VSI handle for the flow entry
1260  * @prio: priority of the flow entry
1261  * @data: pointer to a data buffer containing flow entry's match values/masks
1262  * @acts: arrays of actions to be performed on a match
1263  * @acts_cnt: number of actions
1264  * @entry_h: pointer to buffer that receives the new flow entry's handle
1265  */
1266 enum ice_status
1267 ice_flow_add_entry(struct ice_hw *hw, enum ice_block blk, u64 prof_id,
1268                    u64 entry_id, u16 vsi_handle, enum ice_flow_priority prio,
1269                    void *data, struct ice_flow_action *acts, u8 acts_cnt,
1270                    u64 *entry_h)
1271 {
1272         struct ice_flow_prof *prof = NULL;
1273         struct ice_flow_entry *e = NULL;
1274         enum ice_status status = ICE_SUCCESS;
1275
1276         if (acts_cnt && !acts)
1277                 return ICE_ERR_PARAM;
1278
1279         /* No flow entry data is expected for RSS */
1280         if (!entry_h || (!data && blk != ICE_BLK_RSS))
1281                 return ICE_ERR_BAD_PTR;
1282
1283         if (!ice_is_vsi_valid(hw, vsi_handle))
1284                 return ICE_ERR_PARAM;
1285
1286         ice_acquire_lock(&hw->fl_profs_locks[blk]);
1287
1288         prof = ice_flow_find_prof_id(hw, blk, prof_id);
1289         if (!prof) {
1290                 status = ICE_ERR_DOES_NOT_EXIST;
1291         } else {
1292                 /* Allocate memory for the entry being added and associate
1293                  * the VSI to the found flow profile
1294                  */
1295                 e = (struct ice_flow_entry *)ice_malloc(hw, sizeof(*e));
1296                 if (!e)
1297                         status = ICE_ERR_NO_MEMORY;
1298                 else
1299                         status = ice_flow_assoc_prof(hw, blk, prof, vsi_handle);
1300         }
1301
1302         ice_release_lock(&hw->fl_profs_locks[blk]);
1303         if (status)
1304                 goto out;
1305
1306         e->id = entry_id;
1307         e->vsi_handle = vsi_handle;
1308         e->prof = prof;
1309
1310         switch (blk) {
1311         case ICE_BLK_RSS:
1312                 /* RSS will add only one entry per VSI per profile */
1313                 break;
1314         case ICE_BLK_FD:
1315                 break;
1316         case ICE_BLK_SW:
1317         case ICE_BLK_PE:
1318         default:
1319                 status = ICE_ERR_NOT_IMPL;
1320                 goto out;
1321         }
1322
1323         ice_acquire_lock(&prof->entries_lock);
1324         LIST_ADD(&e->l_entry, &prof->entries);
1325         ice_release_lock(&prof->entries_lock);
1326
1327         *entry_h = ICE_FLOW_ENTRY_HNDL(e);
1328
1329 out:
1330         if (status && e) {
1331                 if (e->entry)
1332                         ice_free(hw, e->entry);
1333                 ice_free(hw, e);
1334         }
1335
1336         return status;
1337 }
1338
1339 /**
1340  * ice_flow_rem_entry - Remove a flow entry
1341  * @hw: pointer to the HW struct
1342  * @entry_h: handle to the flow entry to be removed
1343  */
1344 enum ice_status ice_flow_rem_entry(struct ice_hw *hw, u64 entry_h)
1345 {
1346         struct ice_flow_entry *entry;
1347         struct ice_flow_prof *prof;
1348         enum ice_status status;
1349
1350         if (entry_h == ICE_FLOW_ENTRY_HANDLE_INVAL)
1351                 return ICE_ERR_PARAM;
1352
1353         entry = ICE_FLOW_ENTRY_PTR((unsigned long)entry_h);
1354
1355         /* Retain the pointer to the flow profile as the entry will be freed */
1356         prof = entry->prof;
1357
1358         ice_acquire_lock(&prof->entries_lock);
1359         status = ice_flow_rem_entry_sync(hw, entry);
1360         ice_release_lock(&prof->entries_lock);
1361
1362         return status;
1363 }
1364
1365 /**
1366  * ice_flow_set_fld_ext - specifies locations of field from entry's input buffer
1367  * @seg: packet segment the field being set belongs to
1368  * @fld: field to be set
1369  * @type: type of the field
1370  * @val_loc: if not ICE_FLOW_FLD_OFF_INVAL, location of the value to match from
1371  *           entry's input buffer
1372  * @mask_loc: if not ICE_FLOW_FLD_OFF_INVAL, location of mask value from entry's
1373  *            input buffer
1374  * @last_loc: if not ICE_FLOW_FLD_OFF_INVAL, location of last/upper value from
1375  *            entry's input buffer
1376  *
1377  * This helper function stores information of a field being matched, including
1378  * the type of the field and the locations of the value to match, the mask, and
1379  * and the upper-bound value in the start of the input buffer for a flow entry.
1380  * This function should only be used for fixed-size data structures.
1381  *
1382  * This function also opportunistically determines the protocol headers to be
1383  * present based on the fields being set. Some fields cannot be used alone to
1384  * determine the protocol headers present. Sometimes, fields for particular
1385  * protocol headers are not matched. In those cases, the protocol headers
1386  * must be explicitly set.
1387  */
1388 static void
1389 ice_flow_set_fld_ext(struct ice_flow_seg_info *seg, enum ice_flow_field fld,
1390                      enum ice_flow_fld_match_type type, u16 val_loc,
1391                      u16 mask_loc, u16 last_loc)
1392 {
1393         u64 bit = BIT_ULL(fld);
1394
1395         seg->match |= bit;
1396         if (type == ICE_FLOW_FLD_TYPE_RANGE)
1397                 seg->range |= bit;
1398
1399         seg->fields[fld].type = type;
1400         seg->fields[fld].src.val = val_loc;
1401         seg->fields[fld].src.mask = mask_loc;
1402         seg->fields[fld].src.last = last_loc;
1403
1404         ICE_FLOW_SET_HDRS(seg, ice_flds_info[fld].hdr);
1405 }
1406
1407 /**
1408  * ice_flow_set_fld - specifies locations of field from entry's input buffer
1409  * @seg: packet segment the field being set belongs to
1410  * @fld: field to be set
1411  * @val_loc: if not ICE_FLOW_FLD_OFF_INVAL, location of the value to match from
1412  *           entry's input buffer
1413  * @mask_loc: if not ICE_FLOW_FLD_OFF_INVAL, location of mask value from entry's
1414  *            input buffer
1415  * @last_loc: if not ICE_FLOW_FLD_OFF_INVAL, location of last/upper value from
1416  *            entry's input buffer
1417  * @range: indicate if field being matched is to be in a range
1418  *
1419  * This function specifies the locations, in the form of byte offsets from the
1420  * start of the input buffer for a flow entry, from where the value to match,
1421  * the mask value, and upper value can be extracted. These locations are then
1422  * stored in the flow profile. When adding a flow entry associated with the
1423  * flow profile, these locations will be used to quickly extract the values and
1424  * create the content of a match entry. This function should only be used for
1425  * fixed-size data structures.
1426  */
1427 void
1428 ice_flow_set_fld(struct ice_flow_seg_info *seg, enum ice_flow_field fld,
1429                  u16 val_loc, u16 mask_loc, u16 last_loc, bool range)
1430 {
1431         enum ice_flow_fld_match_type t = range ?
1432                 ICE_FLOW_FLD_TYPE_RANGE : ICE_FLOW_FLD_TYPE_REG;
1433
1434         ice_flow_set_fld_ext(seg, fld, t, val_loc, mask_loc, last_loc);
1435 }
1436
1437 /**
1438  * ice_flow_set_fld_prefix - sets locations of prefix field from entry's buf
1439  * @seg: packet segment the field being set belongs to
1440  * @fld: field to be set
1441  * @val_loc: if not ICE_FLOW_FLD_OFF_INVAL, location of the value to match from
1442  *           entry's input buffer
1443  * @pref_loc: location of prefix value from entry's input buffer
1444  * @pref_sz: size of the location holding the prefix value
1445  *
1446  * This function specifies the locations, in the form of byte offsets from the
1447  * start of the input buffer for a flow entry, from where the value to match
1448  * and the IPv4 prefix value can be extracted. These locations are then stored
1449  * in the flow profile. When adding flow entries to the associated flow profile,
1450  * these locations can be used to quickly extract the values to create the
1451  * content of a match entry. This function should only be used for fixed-size
1452  * data structures.
1453  */
1454 void
1455 ice_flow_set_fld_prefix(struct ice_flow_seg_info *seg, enum ice_flow_field fld,
1456                         u16 val_loc, u16 pref_loc, u8 pref_sz)
1457 {
1458         /* For this type of field, the "mask" location is for the prefix value's
1459          * location and the "last" location is for the size of the location of
1460          * the prefix value.
1461          */
1462         ice_flow_set_fld_ext(seg, fld, ICE_FLOW_FLD_TYPE_PREFIX, val_loc,
1463                              pref_loc, (u16)pref_sz);
1464 }
1465
1466 /**
1467  * ice_flow_add_fld_raw - sets locations of a raw field from entry's input buf
1468  * @seg: packet segment the field being set belongs to
1469  * @off: offset of the raw field from the beginning of the segment in bytes
1470  * @len: length of the raw pattern to be matched
1471  * @val_loc: location of the value to match from entry's input buffer
1472  * @mask_loc: location of mask value from entry's input buffer
1473  *
1474  * This function specifies the offset of the raw field to be match from the
1475  * beginning of the specified packet segment, and the locations, in the form of
1476  * byte offsets from the start of the input buffer for a flow entry, from where
1477  * the value to match and the mask value to be extracted. These locations are
1478  * then stored in the flow profile. When adding flow entries to the associated
1479  * flow profile, these locations can be used to quickly extract the values to
1480  * create the content of a match entry. This function should only be used for
1481  * fixed-size data structures.
1482  */
1483 void
1484 ice_flow_add_fld_raw(struct ice_flow_seg_info *seg, u16 off, u8 len,
1485                      u16 val_loc, u16 mask_loc)
1486 {
1487         if (seg->raws_cnt < ICE_FLOW_SEG_RAW_FLD_MAX) {
1488                 seg->raws[seg->raws_cnt].off = off;
1489                 seg->raws[seg->raws_cnt].info.type = ICE_FLOW_FLD_TYPE_SIZE;
1490                 seg->raws[seg->raws_cnt].info.src.val = val_loc;
1491                 seg->raws[seg->raws_cnt].info.src.mask = mask_loc;
1492                 /* The "last" field is used to store the length of the field */
1493                 seg->raws[seg->raws_cnt].info.src.last = len;
1494         }
1495
1496         /* Overflows of "raws" will be handled as an error condition later in
1497          * the flow when this information is processed.
1498          */
1499         seg->raws_cnt++;
1500 }
1501
1502 #define ICE_FLOW_RSS_SEG_HDR_L3_MASKS \
1503         (ICE_FLOW_SEG_HDR_IPV4 | ICE_FLOW_SEG_HDR_IPV6)
1504
1505 #define ICE_FLOW_RSS_SEG_HDR_L4_MASKS \
1506         (ICE_FLOW_SEG_HDR_TCP | ICE_FLOW_SEG_HDR_UDP | \
1507          ICE_FLOW_SEG_HDR_SCTP)
1508
1509 #define ICE_FLOW_RSS_SEG_HDR_VAL_MASKS \
1510         (ICE_FLOW_RSS_SEG_HDR_L3_MASKS | \
1511          ICE_FLOW_RSS_SEG_HDR_L4_MASKS)
1512
1513 /**
1514  * ice_flow_set_rss_seg_info - setup packet segments for RSS
1515  * @segs: pointer to the flow field segment(s)
1516  * @hash_fields: fields to be hashed on for the segment(s)
1517  * @flow_hdr: protocol header fields within a packet segment
1518  *
1519  * Helper function to extract fields from hash bitmap and use flow
1520  * header value to set flow field segment for further use in flow
1521  * profile entry or removal.
1522  */
1523 static enum ice_status
1524 ice_flow_set_rss_seg_info(struct ice_flow_seg_info *segs, u64 hash_fields,
1525                           u32 flow_hdr)
1526 {
1527         u64 val = hash_fields;
1528         u8 i;
1529
1530         for (i = 0; val && i < ICE_FLOW_FIELD_IDX_MAX; i++) {
1531                 u64 bit = BIT_ULL(i);
1532
1533                 if (val & bit) {
1534                         ice_flow_set_fld(segs, (enum ice_flow_field)i,
1535                                          ICE_FLOW_FLD_OFF_INVAL,
1536                                          ICE_FLOW_FLD_OFF_INVAL,
1537                                          ICE_FLOW_FLD_OFF_INVAL, false);
1538                         val &= ~bit;
1539                 }
1540         }
1541         ICE_FLOW_SET_HDRS(segs, flow_hdr);
1542
1543         if (segs->hdrs & ~ICE_FLOW_RSS_SEG_HDR_VAL_MASKS)
1544                 return ICE_ERR_PARAM;
1545
1546         val = (u64)(segs->hdrs & ICE_FLOW_RSS_SEG_HDR_L3_MASKS);
1547         if (!ice_is_pow2(val))
1548                 return ICE_ERR_CFG;
1549
1550         val = (u64)(segs->hdrs & ICE_FLOW_RSS_SEG_HDR_L4_MASKS);
1551         if (val && !ice_is_pow2(val))
1552                 return ICE_ERR_CFG;
1553
1554         return ICE_SUCCESS;
1555 }
1556
1557 /**
1558  * ice_rem_all_rss_vsi_ctx - remove all RSS configurations from VSI context
1559  * @hw: pointer to the hardware structure
1560  * @vsi_handle: software VSI handle
1561  *
1562  */
1563 void ice_rem_all_rss_vsi_ctx(struct ice_hw *hw, u16 vsi_handle)
1564 {
1565         struct ice_rss_cfg *r, *tmp;
1566
1567         if (!ice_is_vsi_valid(hw, vsi_handle) ||
1568             LIST_EMPTY(&hw->vsi_ctx[vsi_handle]->rss_list_head))
1569                 return;
1570
1571         ice_acquire_lock(&hw->vsi_ctx[vsi_handle]->rss_locks);
1572         LIST_FOR_EACH_ENTRY_SAFE(r, tmp,
1573                                  &hw->vsi_ctx[vsi_handle]->rss_list_head,
1574                                  ice_rss_cfg, l_entry) {
1575                 LIST_DEL(&r->l_entry);
1576                 ice_free(hw, r);
1577         }
1578         ice_release_lock(&hw->vsi_ctx[vsi_handle]->rss_locks);
1579 }
1580
1581 /**
1582  * ice_rem_vsi_rss_cfg - remove RSS configurations associated with VSI
1583  * @hw: pointer to the hardware structure
1584  * @vsi_handle: software VSI handle
1585  *
1586  * This function will iterate through all flow profiles and disassociate
1587  * the VSI from that profile. If the flow profile has no VSIs it will
1588  * be removed.
1589  */
1590 enum ice_status ice_rem_vsi_rss_cfg(struct ice_hw *hw, u16 vsi_handle)
1591 {
1592         const enum ice_block blk = ICE_BLK_RSS;
1593         struct ice_flow_prof *p, *t;
1594         enum ice_status status = ICE_SUCCESS;
1595
1596         if (!ice_is_vsi_valid(hw, vsi_handle))
1597                 return ICE_ERR_PARAM;
1598
1599         ice_acquire_lock(&hw->fl_profs_locks[blk]);
1600         LIST_FOR_EACH_ENTRY_SAFE(p, t, &hw->fl_profs[blk], ice_flow_prof,
1601                                  l_entry) {
1602                 if (ice_is_bit_set(p->vsis, vsi_handle)) {
1603                         status = ice_flow_disassoc_prof(hw, blk, p, vsi_handle);
1604                         if (status)
1605                                 break;
1606
1607                         if (!ice_is_any_bit_set(p->vsis, ICE_MAX_VSI)) {
1608                                 status = ice_flow_rem_prof_sync(hw, blk, p);
1609                                 if (status)
1610                                         break;
1611                         }
1612                 }
1613         }
1614         ice_release_lock(&hw->fl_profs_locks[blk]);
1615
1616         return status;
1617 }
1618
1619 /**
1620  * ice_rem_rss_cfg_vsi_ctx - remove RSS configuration from VSI context
1621  * @hw: pointer to the hardware structure
1622  * @vsi_handle: software VSI handle
1623  * @prof: pointer to flow profile
1624  *
1625  * Assumption: lock has already been acquired for RSS list
1626  */
1627 static void
1628 ice_rem_rss_cfg_vsi_ctx(struct ice_hw *hw, u16 vsi_handle,
1629                         struct ice_flow_prof *prof)
1630 {
1631         struct ice_rss_cfg *r, *tmp;
1632
1633         /* Search for RSS hash fields associated to the VSI that match the
1634          * hash configurations associated to the flow profile. If found
1635          * remove from the RSS entry list of the VSI context and delete entry.
1636          */
1637         LIST_FOR_EACH_ENTRY_SAFE(r, tmp,
1638                                  &hw->vsi_ctx[vsi_handle]->rss_list_head,
1639                                  ice_rss_cfg, l_entry) {
1640                 if (r->hashed_flds == prof->segs[prof->segs_cnt - 1].match &&
1641                     r->packet_hdr == prof->segs[prof->segs_cnt - 1].hdrs) {
1642                         LIST_DEL(&r->l_entry);
1643                         ice_free(hw, r);
1644                         return;
1645                 }
1646         }
1647 }
1648
1649 /**
1650  * ice_add_rss_vsi_ctx - add RSS configuration to VSI context
1651  * @hw: pointer to the hardware structure
1652  * @vsi_handle: software VSI handle
1653  * @prof: pointer to flow profile
1654  *
1655  * Assumption: lock has already been acquired for RSS list
1656  */
1657 static enum ice_status
1658 ice_add_rss_vsi_ctx(struct ice_hw *hw, u16 vsi_handle,
1659                     struct ice_flow_prof *prof)
1660 {
1661         struct ice_rss_cfg *r, *rss_cfg;
1662
1663         LIST_FOR_EACH_ENTRY(r, &hw->vsi_ctx[vsi_handle]->rss_list_head,
1664                             ice_rss_cfg, l_entry)
1665                 if (r->hashed_flds == prof->segs[prof->segs_cnt - 1].match &&
1666                     r->packet_hdr == prof->segs[prof->segs_cnt - 1].hdrs)
1667                         return ICE_SUCCESS;
1668
1669         rss_cfg = (struct ice_rss_cfg *)ice_malloc(hw, sizeof(*rss_cfg));
1670         if (!rss_cfg)
1671                 return ICE_ERR_NO_MEMORY;
1672
1673         rss_cfg->hashed_flds = prof->segs[prof->segs_cnt - 1].match;
1674         rss_cfg->packet_hdr = prof->segs[prof->segs_cnt - 1].hdrs;
1675         LIST_ADD_TAIL(&rss_cfg->l_entry,
1676                       &hw->vsi_ctx[vsi_handle]->rss_list_head);
1677
1678         return ICE_SUCCESS;
1679 }
1680
1681 #define ICE_FLOW_PROF_HASH_S    0
1682 #define ICE_FLOW_PROF_HASH_M    (0xFFFFFFFFULL << ICE_FLOW_PROF_HASH_S)
1683 #define ICE_FLOW_PROF_HDR_S     32
1684 #define ICE_FLOW_PROF_HDR_M     (0xFFFFFFFFULL << ICE_FLOW_PROF_HDR_S)
1685
1686 #define ICE_FLOW_GEN_PROFID(hash, hdr) \
1687         (u64)(((u64)(hash) & ICE_FLOW_PROF_HASH_M) | \
1688               (((u64)(hdr) << ICE_FLOW_PROF_HDR_S) & ICE_FLOW_PROF_HDR_M))
1689
1690 /**
1691  * ice_add_rss_cfg_sync - add an RSS configuration
1692  * @hw: pointer to the hardware structure
1693  * @vsi_handle: software VSI handle
1694  * @hashed_flds: hash bit fields (ICE_FLOW_HASH_*) to configure
1695  * @addl_hdrs: protocol header fields
1696  *
1697  * Assumption: lock has already been acquired for RSS list
1698  */
1699 static enum ice_status
1700 ice_add_rss_cfg_sync(struct ice_hw *hw, u16 vsi_handle, u64 hashed_flds,
1701                      u32 addl_hdrs)
1702 {
1703         const enum ice_block blk = ICE_BLK_RSS;
1704         struct ice_flow_prof *prof = NULL;
1705         struct ice_flow_seg_info *segs;
1706         enum ice_status status = ICE_SUCCESS;
1707
1708         segs = (struct ice_flow_seg_info *)ice_malloc(hw, sizeof(*segs));
1709         if (!segs)
1710                 return ICE_ERR_NO_MEMORY;
1711
1712         /* Construct the packet segment info from the hashed fields */
1713         status = ice_flow_set_rss_seg_info(segs, hashed_flds, addl_hdrs);
1714         if (status)
1715                 goto exit;
1716
1717         /* Search for a flow profile that has matching headers, hash fields
1718          * and has the input VSI associated to it. If found, no further
1719          * operations required and exit.
1720          */
1721         prof = ice_flow_find_prof_conds(hw, blk, ICE_FLOW_RX, segs, 1,
1722                                         vsi_handle,
1723                                         ICE_FLOW_FIND_PROF_CHK_FLDS |
1724                                         ICE_FLOW_FIND_PROF_CHK_VSI);
1725         if (prof)
1726                 goto exit;
1727
1728         /* Check if a flow profile exists with the same protocol headers and
1729          * associated with the input VSI. If so disasscociate the VSI from
1730          * this profile. The VSI will be added to a new profile created with
1731          * the protocol header and new hash field configuration.
1732          */
1733         prof = ice_flow_find_prof_conds(hw, blk, ICE_FLOW_RX, segs, 1,
1734                                         vsi_handle, ICE_FLOW_FIND_PROF_CHK_VSI);
1735         if (prof) {
1736                 status = ice_flow_disassoc_prof(hw, blk, prof, vsi_handle);
1737                 if (!status)
1738                         ice_rem_rss_cfg_vsi_ctx(hw, vsi_handle, prof);
1739                 else
1740                         goto exit;
1741
1742                 /* Remove profile if it has no VSIs associated */
1743                 if (!ice_is_any_bit_set(prof->vsis, ICE_MAX_VSI)) {
1744                         status = ice_flow_rem_prof_sync(hw, blk, prof);
1745                         if (status)
1746                                 goto exit;
1747                 }
1748         }
1749
1750         /* Search for a profile that has same match fields only. If this
1751          * exists then associate the VSI to this profile.
1752          */
1753         prof = ice_flow_find_prof_conds(hw, blk, ICE_FLOW_RX, segs, 1,
1754                                         vsi_handle,
1755                                         ICE_FLOW_FIND_PROF_CHK_FLDS);
1756         if (prof) {
1757                 status = ice_flow_assoc_prof(hw, blk, prof, vsi_handle);
1758                 if (!status)
1759                         status = ice_add_rss_vsi_ctx(hw, vsi_handle, prof);
1760                 goto exit;
1761         }
1762
1763         /* Create a new flow profile with generated profile and packet
1764          * segment information.
1765          */
1766         status = ice_flow_add_prof(hw, blk, ICE_FLOW_RX,
1767                                    ICE_FLOW_GEN_PROFID(hashed_flds, segs->hdrs),
1768                                    segs, 1, NULL, 0, &prof);
1769         if (status)
1770                 goto exit;
1771
1772         status = ice_flow_assoc_prof(hw, blk, prof, vsi_handle);
1773         /* If association to a new flow profile failed then this profile can
1774          * be removed.
1775          */
1776         if (status) {
1777                 ice_flow_rem_prof_sync(hw, blk, prof);
1778                 goto exit;
1779         }
1780
1781         status = ice_add_rss_vsi_ctx(hw, vsi_handle, prof);
1782
1783 exit:
1784         ice_free(hw, segs);
1785         return status;
1786 }
1787
1788 /**
1789  * ice_add_rss_cfg - add an RSS configuration with specified hashed fields
1790  * @hw: pointer to the hardware structure
1791  * @vsi_handle: software VSI handle
1792  * @hashed_flds: hash bit fields (ICE_FLOW_HASH_*) to configure
1793  * @addl_hdrs: protocol header fields
1794  *
1795  * This function will generate a flow profile based on fields associated with
1796  * the input fields to hash on, the flow type and use the VSI number to add
1797  * a flow entry to the profile.
1798  */
1799 enum ice_status
1800 ice_add_rss_cfg(struct ice_hw *hw, u16 vsi_handle, u64 hashed_flds,
1801                 u32 addl_hdrs)
1802 {
1803         enum ice_status status;
1804
1805         if (hashed_flds == ICE_HASH_INVALID ||
1806             !ice_is_vsi_valid(hw, vsi_handle))
1807                 return ICE_ERR_PARAM;
1808
1809         ice_acquire_lock(&hw->vsi_ctx[vsi_handle]->rss_locks);
1810         status = ice_add_rss_cfg_sync(hw, vsi_handle, hashed_flds, addl_hdrs);
1811         ice_release_lock(&hw->vsi_ctx[vsi_handle]->rss_locks);
1812
1813         return status;
1814 }
1815
1816 /**
1817  * ice_rem_rss_cfg_sync - remove an existing RSS configuration
1818  * @hw: pointer to the hardware structure
1819  * @vsi_handle: software VSI handle
1820  * @hashed_flds: Packet hash types (ICE_FLOW_HASH_*) to remove
1821  * @addl_hdrs: Protocol header fields within a packet segment
1822  *
1823  * Assumption: lock has already been acquired for RSS list
1824  */
1825 static enum ice_status
1826 ice_rem_rss_cfg_sync(struct ice_hw *hw, u16 vsi_handle, u64 hashed_flds,
1827                      u32 addl_hdrs)
1828 {
1829         const enum ice_block blk = ICE_BLK_RSS;
1830         struct ice_flow_seg_info *segs;
1831         struct ice_flow_prof *prof;
1832         enum ice_status status;
1833
1834         segs = (struct ice_flow_seg_info *)ice_malloc(hw, sizeof(*segs));
1835         if (!segs)
1836                 return ICE_ERR_NO_MEMORY;
1837
1838         /* Construct the packet segment info from the hashed fields */
1839         status = ice_flow_set_rss_seg_info(segs, hashed_flds, addl_hdrs);
1840         if (status)
1841                 goto out;
1842
1843         prof = ice_flow_find_prof_conds(hw, blk, ICE_FLOW_RX, segs, 1,
1844                                         vsi_handle,
1845                                         ICE_FLOW_FIND_PROF_CHK_FLDS);
1846         if (!prof) {
1847                 status = ICE_ERR_DOES_NOT_EXIST;
1848                 goto out;
1849         }
1850
1851         status = ice_flow_disassoc_prof(hw, blk, prof, vsi_handle);
1852         if (status)
1853                 goto out;
1854
1855         if (!ice_is_any_bit_set(prof->vsis, ICE_MAX_VSI))
1856                 status = ice_flow_rem_prof_sync(hw, blk, prof);
1857
1858         ice_rem_rss_cfg_vsi_ctx(hw, vsi_handle, prof);
1859
1860 out:
1861         ice_free(hw, segs);
1862         return status;
1863 }
1864
1865 /**
1866  * ice_rem_rss_cfg - remove an existing RSS config with matching hashed fields
1867  * @hw: pointer to the hardware structure
1868  * @vsi_handle: software VSI handle
1869  * @hashed_flds: Packet hash types (ICE_FLOW_HASH_*) to remove
1870  * @addl_hdrs: Protocol header fields within a packet segment
1871  *
1872  * This function will lookup the flow profile based on the input
1873  * hash field bitmap, iterate through the profile entry list of
1874  * that profile and find entry associated with input VSI to be
1875  * removed. Calls are made to underlying flow apis which will in
1876  * turn build or update buffers for RSS XLT1 section.
1877  */
1878 enum ice_status
1879 ice_rem_rss_cfg(struct ice_hw *hw, u16 vsi_handle, u64 hashed_flds,
1880                 u32 addl_hdrs)
1881 {
1882         enum ice_status status;
1883
1884         if (hashed_flds == ICE_HASH_INVALID ||
1885             !ice_is_vsi_valid(hw, vsi_handle))
1886                 return ICE_ERR_PARAM;
1887
1888         ice_acquire_lock(&hw->vsi_ctx[vsi_handle]->rss_locks);
1889         status = ice_rem_rss_cfg_sync(hw, vsi_handle, hashed_flds, addl_hdrs);
1890         ice_release_lock(&hw->vsi_ctx[vsi_handle]->rss_locks);
1891
1892         return status;
1893 }
1894
1895 /**
1896  * ice_replay_rss_cfg - remove RSS configurations associated with VSI
1897  * @hw: pointer to the hardware structure
1898  * @vsi_handle: software VSI handle
1899  */
1900 enum ice_status ice_replay_rss_cfg(struct ice_hw *hw, u16 vsi_handle)
1901 {
1902         enum ice_status status = ICE_SUCCESS;
1903         struct ice_rss_cfg *r;
1904
1905         if (!ice_is_vsi_valid(hw, vsi_handle))
1906                 return ICE_ERR_PARAM;
1907
1908         ice_acquire_lock(&hw->vsi_ctx[vsi_handle]->rss_locks);
1909         LIST_FOR_EACH_ENTRY(r, &hw->vsi_ctx[vsi_handle]->rss_list_head,
1910                             ice_rss_cfg, l_entry) {
1911                 status = ice_add_rss_cfg_sync(hw, vsi_handle, r->hashed_flds,
1912                                               r->packet_hdr);
1913                 if (status)
1914                         break;
1915         }
1916         ice_release_lock(&hw->vsi_ctx[vsi_handle]->rss_locks);
1917
1918         return status;
1919 }
1920
1921 /**
1922  * ice_get_rss_cfg - returns hashed fields for the given header types
1923  * @hw: pointer to the hardware structure
1924  * @vsi_handle: software VSI handle
1925  * @hdrs: protocol header type
1926  *
1927  * This function will return the match fields of the first instance of flow
1928  * profile having the given header types and containing input VSI
1929  */
1930 u64 ice_get_rss_cfg(struct ice_hw *hw, u16 vsi_handle, u32 hdrs)
1931 {
1932         struct ice_rss_cfg *r, *rss_cfg = NULL;
1933
1934         /* verify if the protocol header is non zero and VSI is valid */
1935         if (hdrs == ICE_FLOW_SEG_HDR_NONE || !ice_is_vsi_valid(hw, vsi_handle))
1936                 return ICE_HASH_INVALID;
1937
1938         ice_acquire_lock(&hw->vsi_ctx[vsi_handle]->rss_locks);
1939         LIST_FOR_EACH_ENTRY(r, &hw->vsi_ctx[vsi_handle]->rss_list_head,
1940                             ice_rss_cfg, l_entry)
1941                 if (r->packet_hdr == hdrs) {
1942                         rss_cfg = r;
1943                         break;
1944                 }
1945         ice_release_lock(&hw->vsi_ctx[vsi_handle]->rss_locks);
1946
1947         return rss_cfg ? rss_cfg->hashed_flds : ICE_HASH_INVALID;
1948 }