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