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