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