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