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