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