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