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