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