38c7c42f74c4d12ae4c2d937bc56a515dd19dbc4
[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 fv_words;
810         u16 hdrs_sz;
811         u8 i;
812
813         if (!params->prof->segs[seg].raws_cnt)
814                 return ICE_SUCCESS;
815
816         if (params->prof->segs[seg].raws_cnt >
817             ARRAY_SIZE(params->prof->segs[seg].raws))
818                 return ICE_ERR_MAX_LIMIT;
819
820         /* Offsets within the segment headers are not supported */
821         hdrs_sz = ice_flow_calc_seg_sz(params, seg);
822         if (!hdrs_sz)
823                 return ICE_ERR_PARAM;
824
825         fv_words = hw->blk[params->blk].es.fvw;
826
827         for (i = 0; i < params->prof->segs[seg].raws_cnt; i++) {
828                 struct ice_flow_seg_fld_raw *raw;
829                 u16 off, cnt, j;
830
831                 raw = &params->prof->segs[seg].raws[i];
832
833                 /* Only support matching raw fields in the payload */
834                 if (raw->off < hdrs_sz)
835                         return ICE_ERR_PARAM;
836
837                 /* Convert the segment-relative offset into payload-relative
838                  * offset.
839                  */
840                 off = raw->off - hdrs_sz;
841
842                 /* Storing extraction information */
843                 raw->info.xtrct.prot_id = ICE_PROT_PAY;
844                 raw->info.xtrct.off = (off / ICE_FLOW_FV_EXTRACT_SZ) *
845                         ICE_FLOW_FV_EXTRACT_SZ;
846                 raw->info.xtrct.disp = (off % ICE_FLOW_FV_EXTRACT_SZ) *
847                         BITS_PER_BYTE;
848                 raw->info.xtrct.idx = params->es_cnt;
849
850                 /* Determine the number of field vector entries this raw field
851                  * consumes.
852                  */
853                 cnt = DIVIDE_AND_ROUND_UP(raw->info.xtrct.disp +
854                                           (raw->info.src.last * BITS_PER_BYTE),
855                                           (ICE_FLOW_FV_EXTRACT_SZ *
856                                            BITS_PER_BYTE));
857                 off = raw->info.xtrct.off;
858                 for (j = 0; j < cnt; j++) {
859                         u16 idx;
860
861                         /* Make sure the number of extraction sequence required
862                          * does not exceed the block's capability
863                          */
864                         if (params->es_cnt >= hw->blk[params->blk].es.count ||
865                             params->es_cnt >= ICE_MAX_FV_WORDS)
866                                 return ICE_ERR_MAX_LIMIT;
867
868                         /* some blocks require a reversed field vector layout */
869                         if (hw->blk[params->blk].es.reverse)
870                                 idx = fv_words - params->es_cnt - 1;
871                         else
872                                 idx = params->es_cnt;
873
874                         params->es[idx].prot_id = ICE_PROT_PAY;
875                         params->es[idx].off = off;
876                         params->es_cnt++;
877                         off += ICE_FLOW_FV_EXTRACT_SZ;
878                 }
879         }
880
881         return ICE_SUCCESS;
882 }
883
884 /**
885  * ice_flow_create_xtrct_seq - Create an extraction sequence for given segments
886  * @hw: pointer to the HW struct
887  * @params: information about the flow to be processed
888  *
889  * This function iterates through all matched fields in the given segments, and
890  * creates an extraction sequence for the fields.
891  */
892 static enum ice_status
893 ice_flow_create_xtrct_seq(struct ice_hw *hw,
894                           struct ice_flow_prof_params *params)
895 {
896         enum ice_status status = ICE_SUCCESS;
897         u8 i;
898
899         /* For ACL, we also need to extract the direction bit (Rx,Tx) data from
900          * packet flags
901          */
902         if (params->blk == ICE_BLK_ACL) {
903                 status = ice_flow_xtract_pkt_flags(hw, params,
904                                                    ICE_RX_MDID_PKT_FLAGS_15_0);
905                 if (status)
906                         return status;
907         }
908
909         for (i = 0; i < params->prof->segs_cnt; i++) {
910                 u64 match = params->prof->segs[i].match;
911                 u16 j;
912
913                 for (j = 0; j < ICE_FLOW_FIELD_IDX_MAX && match; j++) {
914                         const u64 bit = BIT_ULL(j);
915
916                         if (match & bit) {
917                                 status = ice_flow_xtract_fld
918                                         (hw, params, i, (enum ice_flow_field)j,
919                                          match);
920                                 if (status)
921                                         return status;
922                                 match &= ~bit;
923                         }
924                 }
925
926                 /* Process raw matching bytes */
927                 status = ice_flow_xtract_raws(hw, params, i);
928                 if (status)
929                         return status;
930         }
931
932         return status;
933 }
934
935 /**
936  * ice_flow_proc_segs - process all packet segments associated with a profile
937  * @hw: pointer to the HW struct
938  * @params: information about the flow to be processed
939  */
940 static enum ice_status
941 ice_flow_proc_segs(struct ice_hw *hw, struct ice_flow_prof_params *params)
942 {
943         enum ice_status status;
944
945         status = ice_flow_proc_seg_hdrs(params);
946         if (status)
947                 return status;
948
949         status = ice_flow_create_xtrct_seq(hw, params);
950         if (status)
951                 return status;
952
953         switch (params->blk) {
954         case ICE_BLK_RSS:
955                 /* Only header information is provided for RSS configuration.
956                  * No further processing is needed.
957                  */
958                 status = ICE_SUCCESS;
959                 break;
960         case ICE_BLK_FD:
961                 status = ICE_SUCCESS;
962                 break;
963         case ICE_BLK_SW:
964         default:
965                 return ICE_ERR_NOT_IMPL;
966         }
967
968         return status;
969 }
970
971 #define ICE_FLOW_FIND_PROF_CHK_FLDS     0x00000001
972 #define ICE_FLOW_FIND_PROF_CHK_VSI      0x00000002
973 #define ICE_FLOW_FIND_PROF_NOT_CHK_DIR  0x00000004
974
975 /**
976  * ice_flow_find_prof_conds - Find a profile matching headers and conditions
977  * @hw: pointer to the HW struct
978  * @blk: classification stage
979  * @dir: flow direction
980  * @segs: array of one or more packet segments that describe the flow
981  * @segs_cnt: number of packet segments provided
982  * @vsi_handle: software VSI handle to check VSI (ICE_FLOW_FIND_PROF_CHK_VSI)
983  * @conds: additional conditions to be checked (ICE_FLOW_FIND_PROF_CHK_*)
984  */
985 static struct ice_flow_prof *
986 ice_flow_find_prof_conds(struct ice_hw *hw, enum ice_block blk,
987                          enum ice_flow_dir dir, struct ice_flow_seg_info *segs,
988                          u8 segs_cnt, u16 vsi_handle, u32 conds)
989 {
990         struct ice_flow_prof *p, *prof = NULL;
991
992         ice_acquire_lock(&hw->fl_profs_locks[blk]);
993         LIST_FOR_EACH_ENTRY(p, &hw->fl_profs[blk], ice_flow_prof, l_entry) {
994                 if ((p->dir == dir || conds & ICE_FLOW_FIND_PROF_NOT_CHK_DIR) &&
995                     segs_cnt && segs_cnt == p->segs_cnt) {
996                         u8 i;
997
998                         /* Check for profile-VSI association if specified */
999                         if ((conds & ICE_FLOW_FIND_PROF_CHK_VSI) &&
1000                             ice_is_vsi_valid(hw, vsi_handle) &&
1001                             !ice_is_bit_set(p->vsis, vsi_handle))
1002                                 continue;
1003
1004                         /* Protocol headers must be checked. Matched fields are
1005                          * checked if specified.
1006                          */
1007                         for (i = 0; i < segs_cnt; i++)
1008                                 if (segs[i].hdrs != p->segs[i].hdrs ||
1009                                     ((conds & ICE_FLOW_FIND_PROF_CHK_FLDS) &&
1010                                      segs[i].match != p->segs[i].match))
1011                                         break;
1012
1013                         /* A match is found if all segments are matched */
1014                         if (i == segs_cnt) {
1015                                 prof = p;
1016                                 break;
1017                         }
1018                 }
1019         }
1020         ice_release_lock(&hw->fl_profs_locks[blk]);
1021
1022         return prof;
1023 }
1024
1025 /**
1026  * ice_flow_find_prof - Look up a profile matching headers and matched fields
1027  * @hw: pointer to the HW struct
1028  * @blk: classification stage
1029  * @dir: flow direction
1030  * @segs: array of one or more packet segments that describe the flow
1031  * @segs_cnt: number of packet segments provided
1032  */
1033 u64
1034 ice_flow_find_prof(struct ice_hw *hw, enum ice_block blk, enum ice_flow_dir dir,
1035                    struct ice_flow_seg_info *segs, u8 segs_cnt)
1036 {
1037         struct ice_flow_prof *p;
1038
1039         p = ice_flow_find_prof_conds(hw, blk, dir, segs, segs_cnt,
1040                                      ICE_MAX_VSI, ICE_FLOW_FIND_PROF_CHK_FLDS);
1041
1042         return p ? p->id : ICE_FLOW_PROF_ID_INVAL;
1043 }
1044
1045 /**
1046  * ice_flow_find_prof_id - Look up a profile with given profile ID
1047  * @hw: pointer to the HW struct
1048  * @blk: classification stage
1049  * @prof_id: unique ID to identify this flow profile
1050  */
1051 static struct ice_flow_prof *
1052 ice_flow_find_prof_id(struct ice_hw *hw, enum ice_block blk, u64 prof_id)
1053 {
1054         struct ice_flow_prof *p;
1055
1056         LIST_FOR_EACH_ENTRY(p, &hw->fl_profs[blk], ice_flow_prof, l_entry) {
1057                 if (p->id == prof_id)
1058                         return p;
1059         }
1060
1061         return NULL;
1062 }
1063
1064 /**
1065  * ice_dealloc_flow_entry - Deallocate flow entry memory
1066  * @hw: pointer to the HW struct
1067  * @entry: flow entry to be removed
1068  */
1069 static void
1070 ice_dealloc_flow_entry(struct ice_hw *hw, struct ice_flow_entry *entry)
1071 {
1072         if (!entry)
1073                 return;
1074
1075         if (entry->entry)
1076                 ice_free(hw, entry->entry);
1077
1078         if (entry->acts) {
1079                 ice_free(hw, entry->acts);
1080                 entry->acts = NULL;
1081                 entry->acts_cnt = 0;
1082         }
1083
1084         ice_free(hw, entry);
1085 }
1086
1087 /**
1088  * ice_flow_rem_entry_sync - Remove a flow entry
1089  * @hw: pointer to the HW struct
1090  * @entry: flow entry to be removed
1091  */
1092 static enum ice_status
1093 ice_flow_rem_entry_sync(struct ice_hw *hw, struct ice_flow_entry *entry)
1094 {
1095         if (!entry)
1096                 return ICE_ERR_BAD_PTR;
1097
1098         LIST_DEL(&entry->l_entry);
1099
1100         ice_dealloc_flow_entry(hw, entry);
1101
1102         return ICE_SUCCESS;
1103 }
1104
1105 /**
1106  * ice_flow_add_prof_sync - Add a flow profile for packet segments and fields
1107  * @hw: pointer to the HW struct
1108  * @blk: classification stage
1109  * @dir: flow direction
1110  * @prof_id: unique ID to identify this flow profile
1111  * @segs: array of one or more packet segments that describe the flow
1112  * @segs_cnt: number of packet segments provided
1113  * @acts: array of default actions
1114  * @acts_cnt: number of default actions
1115  * @prof: stores the returned flow profile added
1116  *
1117  * Assumption: the caller has acquired the lock to the profile list
1118  */
1119 static enum ice_status
1120 ice_flow_add_prof_sync(struct ice_hw *hw, enum ice_block blk,
1121                        enum ice_flow_dir dir, u64 prof_id,
1122                        struct ice_flow_seg_info *segs, u8 segs_cnt,
1123                        struct ice_flow_action *acts, u8 acts_cnt,
1124                        struct ice_flow_prof **prof)
1125 {
1126         struct ice_flow_prof_params params;
1127         enum ice_status status = ICE_SUCCESS;
1128         u8 i;
1129
1130         if (!prof || (acts_cnt && !acts))
1131                 return ICE_ERR_BAD_PTR;
1132
1133         ice_memset(&params, 0, sizeof(params), ICE_NONDMA_MEM);
1134         params.prof = (struct ice_flow_prof *)
1135                 ice_malloc(hw, sizeof(*params.prof));
1136         if (!params.prof)
1137                 return ICE_ERR_NO_MEMORY;
1138
1139         /* initialize extraction sequence to all invalid (0xff) */
1140         for (i = 0; i < ICE_MAX_FV_WORDS; i++) {
1141                 params.es[i].prot_id = ICE_PROT_INVALID;
1142                 params.es[i].off = ICE_FV_OFFSET_INVAL;
1143         }
1144
1145         params.blk = blk;
1146         params.prof->id = prof_id;
1147         params.prof->dir = dir;
1148         params.prof->segs_cnt = segs_cnt;
1149
1150         /* Make a copy of the segments that need to be persistent in the flow
1151          * profile instance
1152          */
1153         for (i = 0; i < segs_cnt; i++)
1154                 ice_memcpy(&params.prof->segs[i], &segs[i], sizeof(*segs),
1155                            ICE_NONDMA_TO_NONDMA);
1156
1157         /* Make a copy of the actions that need to be persistent in the flow
1158          * profile instance.
1159          */
1160         if (acts_cnt) {
1161                 params.prof->acts = (struct ice_flow_action *)
1162                         ice_memdup(hw, acts, acts_cnt * sizeof(*acts),
1163                                    ICE_NONDMA_TO_NONDMA);
1164
1165                 if (!params.prof->acts) {
1166                         status = ICE_ERR_NO_MEMORY;
1167                         goto out;
1168                 }
1169         }
1170
1171         status = ice_flow_proc_segs(hw, &params);
1172         if (status) {
1173                 ice_debug(hw, ICE_DBG_FLOW,
1174                           "Error processing a flow's packet segments\n");
1175                 goto out;
1176         }
1177
1178         /* Add a HW profile for this flow profile */
1179         status = ice_add_prof_with_mask(hw, blk, prof_id, (u8 *)params.ptypes,
1180                                         params.es, params.mask);
1181         if (status) {
1182                 ice_debug(hw, ICE_DBG_FLOW, "Error adding a HW flow profile\n");
1183                 goto out;
1184         }
1185
1186         INIT_LIST_HEAD(&params.prof->entries);
1187         ice_init_lock(&params.prof->entries_lock);
1188         *prof = params.prof;
1189
1190 out:
1191         if (status) {
1192                 if (params.prof->acts)
1193                         ice_free(hw, params.prof->acts);
1194                 ice_free(hw, params.prof);
1195         }
1196
1197         return status;
1198 }
1199
1200 /**
1201  * ice_flow_rem_prof_sync - remove a flow profile
1202  * @hw: pointer to the hardware structure
1203  * @blk: classification stage
1204  * @prof: pointer to flow profile to remove
1205  *
1206  * Assumption: the caller has acquired the lock to the profile list
1207  */
1208 static enum ice_status
1209 ice_flow_rem_prof_sync(struct ice_hw *hw, enum ice_block blk,
1210                        struct ice_flow_prof *prof)
1211 {
1212         enum ice_status status = ICE_SUCCESS;
1213
1214         /* Remove all remaining flow entries before removing the flow profile */
1215         if (!LIST_EMPTY(&prof->entries)) {
1216                 struct ice_flow_entry *e, *t;
1217
1218                 ice_acquire_lock(&prof->entries_lock);
1219
1220                 LIST_FOR_EACH_ENTRY_SAFE(e, t, &prof->entries, ice_flow_entry,
1221                                          l_entry) {
1222                         status = ice_flow_rem_entry_sync(hw, e);
1223                         if (status)
1224                                 break;
1225                 }
1226
1227                 ice_release_lock(&prof->entries_lock);
1228         }
1229
1230         /* Remove all hardware profiles associated with this flow profile */
1231         status = ice_rem_prof(hw, blk, prof->id);
1232         if (!status) {
1233                 LIST_DEL(&prof->l_entry);
1234                 ice_destroy_lock(&prof->entries_lock);
1235                 if (prof->acts)
1236                         ice_free(hw, prof->acts);
1237                 ice_free(hw, prof);
1238         }
1239
1240         return status;
1241 }
1242
1243 /**
1244  * ice_flow_assoc_vsig_vsi - associate a VSI with VSIG
1245  * @hw: pointer to the hardware structure
1246  * @blk: classification stage
1247  * @vsi_handle: software VSI handle
1248  * @vsig: target VSI group
1249  *
1250  * Assumption: the caller has already verified that the VSI to
1251  * be added has the same characteristics as the VSIG and will
1252  * thereby have access to all resources added to that VSIG.
1253  */
1254 enum ice_status
1255 ice_flow_assoc_vsig_vsi(struct ice_hw *hw, enum ice_block blk, u16 vsi_handle,
1256                         u16 vsig)
1257 {
1258         enum ice_status status;
1259
1260         if (!ice_is_vsi_valid(hw, vsi_handle) || blk >= ICE_BLK_COUNT)
1261                 return ICE_ERR_PARAM;
1262
1263         ice_acquire_lock(&hw->fl_profs_locks[blk]);
1264         status = ice_add_vsi_flow(hw, blk, ice_get_hw_vsi_num(hw, vsi_handle),
1265                                   vsig);
1266         ice_release_lock(&hw->fl_profs_locks[blk]);
1267
1268         return status;
1269 }
1270
1271 /**
1272  * ice_flow_assoc_prof - associate a VSI with a flow profile
1273  * @hw: pointer to the hardware structure
1274  * @blk: classification stage
1275  * @prof: pointer to flow profile
1276  * @vsi_handle: software VSI handle
1277  *
1278  * Assumption: the caller has acquired the lock to the profile list
1279  * and the software VSI handle has been validated
1280  */
1281 static enum ice_status
1282 ice_flow_assoc_prof(struct ice_hw *hw, enum ice_block blk,
1283                     struct ice_flow_prof *prof, u16 vsi_handle)
1284 {
1285         enum ice_status status = ICE_SUCCESS;
1286
1287         if (!ice_is_bit_set(prof->vsis, vsi_handle)) {
1288                 status = ice_add_prof_id_flow(hw, blk,
1289                                               ice_get_hw_vsi_num(hw,
1290                                                                  vsi_handle),
1291                                               prof->id);
1292                 if (!status)
1293                         ice_set_bit(vsi_handle, prof->vsis);
1294                 else
1295                         ice_debug(hw, ICE_DBG_FLOW,
1296                                   "HW profile add failed, %d\n",
1297                                   status);
1298         }
1299
1300         return status;
1301 }
1302
1303 /**
1304  * ice_flow_disassoc_prof - disassociate a VSI from a flow profile
1305  * @hw: pointer to the hardware structure
1306  * @blk: classification stage
1307  * @prof: pointer to flow profile
1308  * @vsi_handle: software VSI handle
1309  *
1310  * Assumption: the caller has acquired the lock to the profile list
1311  * and the software VSI handle has been validated
1312  */
1313 static enum ice_status
1314 ice_flow_disassoc_prof(struct ice_hw *hw, enum ice_block blk,
1315                        struct ice_flow_prof *prof, u16 vsi_handle)
1316 {
1317         enum ice_status status = ICE_SUCCESS;
1318
1319         if (ice_is_bit_set(prof->vsis, vsi_handle)) {
1320                 status = ice_rem_prof_id_flow(hw, blk,
1321                                               ice_get_hw_vsi_num(hw,
1322                                                                  vsi_handle),
1323                                               prof->id);
1324                 if (!status)
1325                         ice_clear_bit(vsi_handle, prof->vsis);
1326                 else
1327                         ice_debug(hw, ICE_DBG_FLOW,
1328                                   "HW profile remove failed, %d\n",
1329                                   status);
1330         }
1331
1332         return status;
1333 }
1334
1335 /**
1336  * ice_flow_add_prof - Add a flow profile for packet segments and matched fields
1337  * @hw: pointer to the HW struct
1338  * @blk: classification stage
1339  * @dir: flow direction
1340  * @prof_id: unique ID to identify this flow profile
1341  * @segs: array of one or more packet segments that describe the flow
1342  * @segs_cnt: number of packet segments provided
1343  * @acts: array of default actions
1344  * @acts_cnt: number of default actions
1345  * @prof: stores the returned flow profile added
1346  */
1347 enum ice_status
1348 ice_flow_add_prof(struct ice_hw *hw, enum ice_block blk, enum ice_flow_dir dir,
1349                   u64 prof_id, struct ice_flow_seg_info *segs, u8 segs_cnt,
1350                   struct ice_flow_action *acts, u8 acts_cnt,
1351                   struct ice_flow_prof **prof)
1352 {
1353         enum ice_status status;
1354
1355         if (segs_cnt > ICE_FLOW_SEG_MAX)
1356                 return ICE_ERR_MAX_LIMIT;
1357
1358         if (!segs_cnt)
1359                 return ICE_ERR_PARAM;
1360
1361         if (!segs)
1362                 return ICE_ERR_BAD_PTR;
1363
1364         status = ice_flow_val_hdrs(segs, segs_cnt);
1365         if (status)
1366                 return status;
1367
1368         ice_acquire_lock(&hw->fl_profs_locks[blk]);
1369
1370         status = ice_flow_add_prof_sync(hw, blk, dir, prof_id, segs, segs_cnt,
1371                                         acts, acts_cnt, prof);
1372         if (!status)
1373                 LIST_ADD(&(*prof)->l_entry, &hw->fl_profs[blk]);
1374
1375         ice_release_lock(&hw->fl_profs_locks[blk]);
1376
1377         return status;
1378 }
1379
1380 /**
1381  * ice_flow_rem_prof - Remove a flow profile and all entries associated with it
1382  * @hw: pointer to the HW struct
1383  * @blk: the block for which the flow profile is to be removed
1384  * @prof_id: unique ID of the flow profile to be removed
1385  */
1386 enum ice_status
1387 ice_flow_rem_prof(struct ice_hw *hw, enum ice_block blk, u64 prof_id)
1388 {
1389         struct ice_flow_prof *prof;
1390         enum ice_status status;
1391
1392         ice_acquire_lock(&hw->fl_profs_locks[blk]);
1393
1394         prof = ice_flow_find_prof_id(hw, blk, prof_id);
1395         if (!prof) {
1396                 status = ICE_ERR_DOES_NOT_EXIST;
1397                 goto out;
1398         }
1399
1400         /* prof becomes invalid after the call */
1401         status = ice_flow_rem_prof_sync(hw, blk, prof);
1402
1403 out:
1404         ice_release_lock(&hw->fl_profs_locks[blk]);
1405
1406         return status;
1407 }
1408
1409 /**
1410  * ice_flow_get_hw_prof - return the HW profile for a specific profile ID handle
1411  * @hw: pointer to the HW struct
1412  * @blk: classification stage
1413  * @prof_id: the profile ID handle
1414  * @hw_prof_id: pointer to variable to receive the HW profile ID
1415  */
1416 enum ice_status
1417 ice_flow_get_hw_prof(struct ice_hw *hw, enum ice_block blk, u64 prof_id,
1418                      u8 *hw_prof_id)
1419 {
1420         struct ice_prof_map *map;
1421
1422         map = ice_search_prof_id(hw, blk, prof_id);
1423         if (map) {
1424                 *hw_prof_id = map->prof_id;
1425                 return ICE_SUCCESS;
1426         }
1427
1428         return ICE_ERR_DOES_NOT_EXIST;
1429 }
1430
1431 /**
1432  * ice_flow_find_entry - look for a flow entry using its unique ID
1433  * @hw: pointer to the HW struct
1434  * @blk: classification stage
1435  * @entry_id: unique ID to identify this flow entry
1436  *
1437  * This function looks for the flow entry with the specified unique ID in all
1438  * flow profiles of the specified classification stage. If the entry is found,
1439  * and it returns the handle to the flow entry. Otherwise, it returns
1440  * ICE_FLOW_ENTRY_ID_INVAL.
1441  */
1442 u64 ice_flow_find_entry(struct ice_hw *hw, enum ice_block blk, u64 entry_id)
1443 {
1444         struct ice_flow_entry *found = NULL;
1445         struct ice_flow_prof *p;
1446
1447         ice_acquire_lock(&hw->fl_profs_locks[blk]);
1448
1449         LIST_FOR_EACH_ENTRY(p, &hw->fl_profs[blk], ice_flow_prof, l_entry) {
1450                 struct ice_flow_entry *e;
1451
1452                 ice_acquire_lock(&p->entries_lock);
1453                 LIST_FOR_EACH_ENTRY(e, &p->entries, ice_flow_entry, l_entry)
1454                         if (e->id == entry_id) {
1455                                 found = e;
1456                                 break;
1457                         }
1458                 ice_release_lock(&p->entries_lock);
1459
1460                 if (found)
1461                         break;
1462         }
1463
1464         ice_release_lock(&hw->fl_profs_locks[blk]);
1465
1466         return found ? ICE_FLOW_ENTRY_HNDL(found) : ICE_FLOW_ENTRY_HANDLE_INVAL;
1467 }
1468
1469 /**
1470  * ice_flow_add_entry - Add a flow entry
1471  * @hw: pointer to the HW struct
1472  * @blk: classification stage
1473  * @prof_id: ID of the profile to add a new flow entry to
1474  * @entry_id: unique ID to identify this flow entry
1475  * @vsi_handle: software VSI handle for the flow entry
1476  * @prio: priority of the flow entry
1477  * @data: pointer to a data buffer containing flow entry's match values/masks
1478  * @acts: arrays of actions to be performed on a match
1479  * @acts_cnt: number of actions
1480  * @entry_h: pointer to buffer that receives the new flow entry's handle
1481  */
1482 enum ice_status
1483 ice_flow_add_entry(struct ice_hw *hw, enum ice_block blk, u64 prof_id,
1484                    u64 entry_id, u16 vsi_handle, enum ice_flow_priority prio,
1485                    void *data, struct ice_flow_action *acts, u8 acts_cnt,
1486                    u64 *entry_h)
1487 {
1488         struct ice_flow_prof *prof = NULL;
1489         struct ice_flow_entry *e = NULL;
1490         enum ice_status status = ICE_SUCCESS;
1491
1492         if (acts_cnt && !acts)
1493                 return ICE_ERR_PARAM;
1494
1495         /* No flow entry data is expected for RSS */
1496         if (!entry_h || (!data && blk != ICE_BLK_RSS))
1497                 return ICE_ERR_BAD_PTR;
1498
1499         if (!ice_is_vsi_valid(hw, vsi_handle))
1500                 return ICE_ERR_PARAM;
1501
1502         ice_acquire_lock(&hw->fl_profs_locks[blk]);
1503
1504         prof = ice_flow_find_prof_id(hw, blk, prof_id);
1505         if (!prof) {
1506                 status = ICE_ERR_DOES_NOT_EXIST;
1507         } else {
1508                 /* Allocate memory for the entry being added and associate
1509                  * the VSI to the found flow profile
1510                  */
1511                 e = (struct ice_flow_entry *)ice_malloc(hw, sizeof(*e));
1512                 if (!e)
1513                         status = ICE_ERR_NO_MEMORY;
1514                 else
1515                         status = ice_flow_assoc_prof(hw, blk, prof, vsi_handle);
1516         }
1517
1518         ice_release_lock(&hw->fl_profs_locks[blk]);
1519         if (status)
1520                 goto out;
1521
1522         e->id = entry_id;
1523         e->vsi_handle = vsi_handle;
1524         e->prof = prof;
1525         e->priority = prio;
1526
1527         switch (blk) {
1528         case ICE_BLK_RSS:
1529                 /* RSS will add only one entry per VSI per profile */
1530                 break;
1531         case ICE_BLK_FD:
1532                 break;
1533         case ICE_BLK_SW:
1534         case ICE_BLK_PE:
1535         default:
1536                 status = ICE_ERR_NOT_IMPL;
1537                 goto out;
1538         }
1539
1540         if (blk != ICE_BLK_ACL) {
1541                 /* ACL will handle the entry management */
1542                 ice_acquire_lock(&prof->entries_lock);
1543                 LIST_ADD(&e->l_entry, &prof->entries);
1544                 ice_release_lock(&prof->entries_lock);
1545         }
1546
1547         *entry_h = ICE_FLOW_ENTRY_HNDL(e);
1548
1549 out:
1550         if (status && e) {
1551                 if (e->entry)
1552                         ice_free(hw, e->entry);
1553                 ice_free(hw, e);
1554         }
1555
1556         return status;
1557 }
1558
1559 /**
1560  * ice_flow_rem_entry - Remove a flow entry
1561  * @hw: pointer to the HW struct
1562  * @entry_h: handle to the flow entry to be removed
1563  */
1564 enum ice_status ice_flow_rem_entry(struct ice_hw *hw, u64 entry_h)
1565 {
1566         struct ice_flow_entry *entry;
1567         struct ice_flow_prof *prof;
1568         enum ice_status status;
1569
1570         if (entry_h == ICE_FLOW_ENTRY_HANDLE_INVAL)
1571                 return ICE_ERR_PARAM;
1572
1573         entry = ICE_FLOW_ENTRY_PTR((unsigned long)entry_h);
1574
1575         /* Retain the pointer to the flow profile as the entry will be freed */
1576         prof = entry->prof;
1577
1578         ice_acquire_lock(&prof->entries_lock);
1579         status = ice_flow_rem_entry_sync(hw, entry);
1580         ice_release_lock(&prof->entries_lock);
1581
1582         return status;
1583 }
1584
1585 /**
1586  * ice_flow_set_fld_ext - specifies locations of field from entry's input buffer
1587  * @seg: packet segment the field being set belongs to
1588  * @fld: field to be set
1589  * @type: type of the field
1590  * @val_loc: if not ICE_FLOW_FLD_OFF_INVAL, location of the value to match from
1591  *           entry's input buffer
1592  * @mask_loc: if not ICE_FLOW_FLD_OFF_INVAL, location of mask value from entry's
1593  *            input buffer
1594  * @last_loc: if not ICE_FLOW_FLD_OFF_INVAL, location of last/upper value from
1595  *            entry's input buffer
1596  *
1597  * This helper function stores information of a field being matched, including
1598  * the type of the field and the locations of the value to match, the mask, and
1599  * and the upper-bound value in the start of the input buffer for a flow entry.
1600  * This function should only be used for fixed-size data structures.
1601  *
1602  * This function also opportunistically determines the protocol headers to be
1603  * present based on the fields being set. Some fields cannot be used alone to
1604  * determine the protocol headers present. Sometimes, fields for particular
1605  * protocol headers are not matched. In those cases, the protocol headers
1606  * must be explicitly set.
1607  */
1608 static void
1609 ice_flow_set_fld_ext(struct ice_flow_seg_info *seg, enum ice_flow_field fld,
1610                      enum ice_flow_fld_match_type type, u16 val_loc,
1611                      u16 mask_loc, u16 last_loc)
1612 {
1613         u64 bit = BIT_ULL(fld);
1614
1615         seg->match |= bit;
1616         if (type == ICE_FLOW_FLD_TYPE_RANGE)
1617                 seg->range |= bit;
1618
1619         seg->fields[fld].type = type;
1620         seg->fields[fld].src.val = val_loc;
1621         seg->fields[fld].src.mask = mask_loc;
1622         seg->fields[fld].src.last = last_loc;
1623
1624         ICE_FLOW_SET_HDRS(seg, ice_flds_info[fld].hdr);
1625 }
1626
1627 /**
1628  * ice_flow_set_fld - specifies locations of field from entry's input buffer
1629  * @seg: packet segment the field being set belongs to
1630  * @fld: field to be set
1631  * @val_loc: if not ICE_FLOW_FLD_OFF_INVAL, location of the value to match from
1632  *           entry's input buffer
1633  * @mask_loc: if not ICE_FLOW_FLD_OFF_INVAL, location of mask value from entry's
1634  *            input buffer
1635  * @last_loc: if not ICE_FLOW_FLD_OFF_INVAL, location of last/upper value from
1636  *            entry's input buffer
1637  * @range: indicate if field being matched is to be in a range
1638  *
1639  * This function specifies the locations, in the form of byte offsets from the
1640  * start of the input buffer for a flow entry, from where the value to match,
1641  * the mask value, and upper value can be extracted. These locations are then
1642  * stored in the flow profile. When adding a flow entry associated with the
1643  * flow profile, these locations will be used to quickly extract the values and
1644  * create the content of a match entry. This function should only be used for
1645  * fixed-size data structures.
1646  */
1647 void
1648 ice_flow_set_fld(struct ice_flow_seg_info *seg, enum ice_flow_field fld,
1649                  u16 val_loc, u16 mask_loc, u16 last_loc, bool range)
1650 {
1651         enum ice_flow_fld_match_type t = range ?
1652                 ICE_FLOW_FLD_TYPE_RANGE : ICE_FLOW_FLD_TYPE_REG;
1653
1654         ice_flow_set_fld_ext(seg, fld, t, val_loc, mask_loc, last_loc);
1655 }
1656
1657 /**
1658  * ice_flow_set_fld_prefix - sets locations of prefix field from entry's buf
1659  * @seg: packet segment the field being set belongs to
1660  * @fld: field to be set
1661  * @val_loc: if not ICE_FLOW_FLD_OFF_INVAL, location of the value to match from
1662  *           entry's input buffer
1663  * @pref_loc: location of prefix value from entry's input buffer
1664  * @pref_sz: size of the location holding the prefix value
1665  *
1666  * This function specifies the locations, in the form of byte offsets from the
1667  * start of the input buffer for a flow entry, from where the value to match
1668  * and the IPv4 prefix value can be extracted. These locations are then stored
1669  * in the flow profile. When adding flow entries to the associated flow profile,
1670  * these locations can be used to quickly extract the values to create the
1671  * content of a match entry. This function should only be used for fixed-size
1672  * data structures.
1673  */
1674 void
1675 ice_flow_set_fld_prefix(struct ice_flow_seg_info *seg, enum ice_flow_field fld,
1676                         u16 val_loc, u16 pref_loc, u8 pref_sz)
1677 {
1678         /* For this type of field, the "mask" location is for the prefix value's
1679          * location and the "last" location is for the size of the location of
1680          * the prefix value.
1681          */
1682         ice_flow_set_fld_ext(seg, fld, ICE_FLOW_FLD_TYPE_PREFIX, val_loc,
1683                              pref_loc, (u16)pref_sz);
1684 }
1685
1686 /**
1687  * ice_flow_add_fld_raw - sets locations of a raw field from entry's input buf
1688  * @seg: packet segment the field being set belongs to
1689  * @off: offset of the raw field from the beginning of the segment in bytes
1690  * @len: length of the raw pattern to be matched
1691  * @val_loc: location of the value to match from entry's input buffer
1692  * @mask_loc: location of mask value from entry's input buffer
1693  *
1694  * This function specifies the offset of the raw field to be match from the
1695  * beginning of the specified packet segment, and the locations, in the form of
1696  * byte offsets from the start of the input buffer for a flow entry, from where
1697  * the value to match and the mask value to be extracted. These locations are
1698  * then stored in the flow profile. When adding flow entries to the associated
1699  * flow profile, these locations can be used to quickly extract the values to
1700  * create the content of a match entry. This function should only be used for
1701  * fixed-size data structures.
1702  */
1703 void
1704 ice_flow_add_fld_raw(struct ice_flow_seg_info *seg, u16 off, u8 len,
1705                      u16 val_loc, u16 mask_loc)
1706 {
1707         if (seg->raws_cnt < ICE_FLOW_SEG_RAW_FLD_MAX) {
1708                 seg->raws[seg->raws_cnt].off = off;
1709                 seg->raws[seg->raws_cnt].info.type = ICE_FLOW_FLD_TYPE_SIZE;
1710                 seg->raws[seg->raws_cnt].info.src.val = val_loc;
1711                 seg->raws[seg->raws_cnt].info.src.mask = mask_loc;
1712                 /* The "last" field is used to store the length of the field */
1713                 seg->raws[seg->raws_cnt].info.src.last = len;
1714         }
1715
1716         /* Overflows of "raws" will be handled as an error condition later in
1717          * the flow when this information is processed.
1718          */
1719         seg->raws_cnt++;
1720 }
1721
1722 #define ICE_FLOW_RSS_SEG_HDR_L2_MASKS \
1723 (ICE_FLOW_SEG_HDR_ETH | ICE_FLOW_SEG_HDR_VLAN)
1724
1725 #define ICE_FLOW_RSS_SEG_HDR_L3_MASKS \
1726         (ICE_FLOW_SEG_HDR_IPV4 | ICE_FLOW_SEG_HDR_IPV6)
1727
1728 #define ICE_FLOW_RSS_SEG_HDR_L4_MASKS \
1729         (ICE_FLOW_SEG_HDR_TCP | ICE_FLOW_SEG_HDR_UDP | \
1730          ICE_FLOW_SEG_HDR_SCTP)
1731
1732 #define ICE_FLOW_RSS_SEG_HDR_VAL_MASKS \
1733         (ICE_FLOW_RSS_SEG_HDR_L2_MASKS | \
1734          ICE_FLOW_RSS_SEG_HDR_L3_MASKS | \
1735          ICE_FLOW_RSS_SEG_HDR_L4_MASKS)
1736
1737 /**
1738  * ice_flow_set_rss_seg_info - setup packet segments for RSS
1739  * @segs: pointer to the flow field segment(s)
1740  * @hash_fields: fields to be hashed on for the segment(s)
1741  * @flow_hdr: protocol header fields within a packet segment
1742  *
1743  * Helper function to extract fields from hash bitmap and use flow
1744  * header value to set flow field segment for further use in flow
1745  * profile entry or removal.
1746  */
1747 static enum ice_status
1748 ice_flow_set_rss_seg_info(struct ice_flow_seg_info *segs, u64 hash_fields,
1749                           u32 flow_hdr)
1750 {
1751         u64 val = hash_fields;
1752         u8 i;
1753
1754         for (i = 0; val && i < ICE_FLOW_FIELD_IDX_MAX; i++) {
1755                 u64 bit = BIT_ULL(i);
1756
1757                 if (val & bit) {
1758                         ice_flow_set_fld(segs, (enum ice_flow_field)i,
1759                                          ICE_FLOW_FLD_OFF_INVAL,
1760                                          ICE_FLOW_FLD_OFF_INVAL,
1761                                          ICE_FLOW_FLD_OFF_INVAL, false);
1762                         val &= ~bit;
1763                 }
1764         }
1765         ICE_FLOW_SET_HDRS(segs, flow_hdr);
1766
1767         if (segs->hdrs & ~ICE_FLOW_RSS_SEG_HDR_VAL_MASKS &
1768             ~ICE_FLOW_RSS_HDRS_INNER_MASK)
1769                 return ICE_ERR_PARAM;
1770
1771         val = (u64)(segs->hdrs & ICE_FLOW_RSS_SEG_HDR_L3_MASKS);
1772         if (val && !ice_is_pow2(val))
1773                 return ICE_ERR_CFG;
1774
1775         val = (u64)(segs->hdrs & ICE_FLOW_RSS_SEG_HDR_L4_MASKS);
1776         if (val && !ice_is_pow2(val))
1777                 return ICE_ERR_CFG;
1778
1779         return ICE_SUCCESS;
1780 }
1781
1782 /**
1783  * ice_rem_vsi_rss_list - remove VSI from RSS list
1784  * @hw: pointer to the hardware structure
1785  * @vsi_handle: software VSI handle
1786  *
1787  * Remove the VSI from all RSS configurations in the list.
1788  */
1789 void ice_rem_vsi_rss_list(struct ice_hw *hw, u16 vsi_handle)
1790 {
1791         struct ice_rss_cfg *r, *tmp;
1792
1793         if (LIST_EMPTY(&hw->rss_list_head))
1794                 return;
1795
1796         ice_acquire_lock(&hw->rss_locks);
1797         LIST_FOR_EACH_ENTRY_SAFE(r, tmp, &hw->rss_list_head,
1798                                  ice_rss_cfg, l_entry) {
1799                 if (ice_is_bit_set(r->vsis, vsi_handle)) {
1800                         ice_clear_bit(vsi_handle, r->vsis);
1801
1802                         if (!ice_is_any_bit_set(r->vsis, ICE_MAX_VSI)) {
1803                                 LIST_DEL(&r->l_entry);
1804                                 ice_free(hw, r);
1805                         }
1806                 }
1807         }
1808         ice_release_lock(&hw->rss_locks);
1809 }
1810
1811 /**
1812  * ice_rem_vsi_rss_cfg - remove RSS configurations associated with VSI
1813  * @hw: pointer to the hardware structure
1814  * @vsi_handle: software VSI handle
1815  *
1816  * This function will iterate through all flow profiles and disassociate
1817  * the VSI from that profile. If the flow profile has no VSIs it will
1818  * be removed.
1819  */
1820 enum ice_status ice_rem_vsi_rss_cfg(struct ice_hw *hw, u16 vsi_handle)
1821 {
1822         const enum ice_block blk = ICE_BLK_RSS;
1823         struct ice_flow_prof *p, *t;
1824         enum ice_status status = ICE_SUCCESS;
1825
1826         if (!ice_is_vsi_valid(hw, vsi_handle))
1827                 return ICE_ERR_PARAM;
1828
1829         if (LIST_EMPTY(&hw->fl_profs[blk]))
1830                 return ICE_SUCCESS;
1831
1832         ice_acquire_lock(&hw->fl_profs_locks[blk]);
1833         LIST_FOR_EACH_ENTRY_SAFE(p, t, &hw->fl_profs[blk], ice_flow_prof,
1834                                  l_entry) {
1835                 if (ice_is_bit_set(p->vsis, vsi_handle)) {
1836                         status = ice_flow_disassoc_prof(hw, blk, p, vsi_handle);
1837                         if (status)
1838                                 break;
1839
1840                         if (!ice_is_any_bit_set(p->vsis, ICE_MAX_VSI)) {
1841                                 status = ice_flow_rem_prof_sync(hw, blk, p);
1842                                 if (status)
1843                                         break;
1844                         }
1845                 }
1846         }
1847         ice_release_lock(&hw->fl_profs_locks[blk]);
1848
1849         return status;
1850 }
1851
1852 /**
1853  * ice_rem_rss_list - remove RSS configuration from list
1854  * @hw: pointer to the hardware structure
1855  * @vsi_handle: software VSI handle
1856  * @prof: pointer to flow profile
1857  *
1858  * Assumption: lock has already been acquired for RSS list
1859  */
1860 static void
1861 ice_rem_rss_list(struct ice_hw *hw, u16 vsi_handle, struct ice_flow_prof *prof)
1862 {
1863         struct ice_rss_cfg *r, *tmp;
1864
1865         /* Search for RSS hash fields associated to the VSI that match the
1866          * hash configurations associated to the flow profile. If found
1867          * remove from the RSS entry list of the VSI context and delete entry.
1868          */
1869         LIST_FOR_EACH_ENTRY_SAFE(r, tmp, &hw->rss_list_head,
1870                                  ice_rss_cfg, l_entry) {
1871                 if (r->hashed_flds == prof->segs[prof->segs_cnt - 1].match &&
1872                     r->packet_hdr == prof->segs[prof->segs_cnt - 1].hdrs) {
1873                         ice_clear_bit(vsi_handle, r->vsis);
1874                         if (!ice_is_any_bit_set(r->vsis, ICE_MAX_VSI)) {
1875                                 LIST_DEL(&r->l_entry);
1876                                 ice_free(hw, r);
1877                         }
1878                         return;
1879                 }
1880         }
1881 }
1882
1883 /**
1884  * ice_add_rss_list - add RSS configuration to list
1885  * @hw: pointer to the hardware structure
1886  * @vsi_handle: software VSI handle
1887  * @prof: pointer to flow profile
1888  *
1889  * Assumption: lock has already been acquired for RSS list
1890  */
1891 static enum ice_status
1892 ice_add_rss_list(struct ice_hw *hw, u16 vsi_handle, struct ice_flow_prof *prof)
1893 {
1894         struct ice_rss_cfg *r, *rss_cfg;
1895
1896         LIST_FOR_EACH_ENTRY(r, &hw->rss_list_head,
1897                             ice_rss_cfg, l_entry)
1898                 if (r->hashed_flds == prof->segs[prof->segs_cnt - 1].match &&
1899                     r->packet_hdr == prof->segs[prof->segs_cnt - 1].hdrs) {
1900                         ice_set_bit(vsi_handle, r->vsis);
1901                         return ICE_SUCCESS;
1902                 }
1903
1904         rss_cfg = (struct ice_rss_cfg *)ice_malloc(hw, sizeof(*rss_cfg));
1905         if (!rss_cfg)
1906                 return ICE_ERR_NO_MEMORY;
1907
1908         rss_cfg->hashed_flds = prof->segs[prof->segs_cnt - 1].match;
1909         rss_cfg->packet_hdr = prof->segs[prof->segs_cnt - 1].hdrs;
1910         rss_cfg->symm = prof->cfg.symm;
1911         ice_set_bit(vsi_handle, rss_cfg->vsis);
1912
1913         LIST_ADD_TAIL(&rss_cfg->l_entry, &hw->rss_list_head);
1914
1915         return ICE_SUCCESS;
1916 }
1917
1918 #define ICE_FLOW_PROF_HASH_S    0
1919 #define ICE_FLOW_PROF_HASH_M    (0xFFFFFFFFULL << ICE_FLOW_PROF_HASH_S)
1920 #define ICE_FLOW_PROF_HDR_S     32
1921 #define ICE_FLOW_PROF_HDR_M     (0x3FFFFFFFULL << ICE_FLOW_PROF_HDR_S)
1922 #define ICE_FLOW_PROF_ENCAP_S   63
1923 #define ICE_FLOW_PROF_ENCAP_M   (BIT_ULL(ICE_FLOW_PROF_ENCAP_S))
1924
1925 #define ICE_RSS_OUTER_HEADERS   1
1926 #define ICE_RSS_INNER_HEADERS   2
1927
1928 /* Flow profile ID format:
1929  * [0:31] - Packet match fields
1930  * [32:62] - Protocol header
1931  * [63] - Encapsulation flag, 0 if non-tunneled, 1 if tunneled
1932  */
1933 #define ICE_FLOW_GEN_PROFID(hash, hdr, segs_cnt) \
1934         (u64)(((u64)(hash) & ICE_FLOW_PROF_HASH_M) | \
1935               (((u64)(hdr) << ICE_FLOW_PROF_HDR_S) & ICE_FLOW_PROF_HDR_M) | \
1936               ((u8)((segs_cnt) - 1) ? ICE_FLOW_PROF_ENCAP_M : 0))
1937
1938 static void
1939 ice_rss_config_xor_word(struct ice_hw *hw, u8 prof_id, u8 src, u8 dst)
1940 {
1941         u32 s = ((src % 4) << 3); /* byte shift */
1942         u32 v = dst | 0x80; /* value to program */
1943         u8 i = src / 4; /* register index */
1944         u32 reg;
1945
1946         reg = rd32(hw, GLQF_HSYMM(prof_id, i));
1947         reg = (reg & ~(0xff << s)) | (v << s);
1948         wr32(hw, GLQF_HSYMM(prof_id, i), reg);
1949 }
1950
1951 static void
1952 ice_rss_config_xor(struct ice_hw *hw, u8 prof_id, u8 src, u8 dst, u8 len)
1953 {
1954         int fv_last_word =
1955                 ICE_FLOW_SW_FIELD_VECTOR_MAX / ICE_FLOW_FV_EXTRACT_SZ - 1;
1956         int i;
1957
1958         for (i = 0; i < len; i++) {
1959                 ice_rss_config_xor_word(hw, prof_id,
1960                                         /* Yes, field vector in GLQF_HSYMM and
1961                                          * GLQF_HINSET is inversed!
1962                                          */
1963                                         fv_last_word - (src + i),
1964                                         fv_last_word - (dst + i));
1965                 ice_rss_config_xor_word(hw, prof_id,
1966                                         fv_last_word - (dst + i),
1967                                         fv_last_word - (src + i));
1968         }
1969 }
1970
1971 static void
1972 ice_rss_update_symm(struct ice_hw *hw,
1973                     struct ice_flow_prof *prof)
1974 {
1975         struct ice_prof_map *map;
1976         u8 prof_id, m;
1977
1978         map = ice_search_prof_id(hw, ICE_BLK_RSS, prof->id);
1979         prof_id = map->prof_id;
1980
1981         /* clear to default */
1982         for (m = 0; m < 6; m++)
1983                 wr32(hw, GLQF_HSYMM(prof_id, m), 0);
1984         if (prof->cfg.symm) {
1985                 struct ice_flow_seg_info *seg =
1986                         &prof->segs[prof->segs_cnt - 1];
1987
1988                 struct ice_flow_seg_xtrct *ipv4_src =
1989                         &seg->fields[ICE_FLOW_FIELD_IDX_IPV4_SA].xtrct;
1990                 struct ice_flow_seg_xtrct *ipv4_dst =
1991                         &seg->fields[ICE_FLOW_FIELD_IDX_IPV4_DA].xtrct;
1992                 struct ice_flow_seg_xtrct *ipv6_src =
1993                         &seg->fields[ICE_FLOW_FIELD_IDX_IPV6_SA].xtrct;
1994                 struct ice_flow_seg_xtrct *ipv6_dst =
1995                         &seg->fields[ICE_FLOW_FIELD_IDX_IPV6_DA].xtrct;
1996
1997                 struct ice_flow_seg_xtrct *tcp_src =
1998                         &seg->fields[ICE_FLOW_FIELD_IDX_TCP_SRC_PORT].xtrct;
1999                 struct ice_flow_seg_xtrct *tcp_dst =
2000                         &seg->fields[ICE_FLOW_FIELD_IDX_TCP_DST_PORT].xtrct;
2001
2002                 struct ice_flow_seg_xtrct *udp_src =
2003                         &seg->fields[ICE_FLOW_FIELD_IDX_UDP_SRC_PORT].xtrct;
2004                 struct ice_flow_seg_xtrct *udp_dst =
2005                         &seg->fields[ICE_FLOW_FIELD_IDX_UDP_DST_PORT].xtrct;
2006
2007                 struct ice_flow_seg_xtrct *sctp_src =
2008                         &seg->fields[ICE_FLOW_FIELD_IDX_SCTP_SRC_PORT].xtrct;
2009                 struct ice_flow_seg_xtrct *sctp_dst =
2010                         &seg->fields[ICE_FLOW_FIELD_IDX_SCTP_DST_PORT].xtrct;
2011
2012                 /* xor IPv4 */
2013                 if (ipv4_src->prot_id != 0 && ipv4_dst->prot_id != 0)
2014                         ice_rss_config_xor(hw, prof_id,
2015                                            ipv4_src->idx, ipv4_dst->idx, 2);
2016
2017                 /* xor IPv6 */
2018                 if (ipv6_src->prot_id != 0 && ipv6_dst->prot_id != 0)
2019                         ice_rss_config_xor(hw, prof_id,
2020                                            ipv6_src->idx, ipv6_dst->idx, 8);
2021
2022                 /* xor TCP */
2023                 if (tcp_src->prot_id != 0 && tcp_dst->prot_id != 0)
2024                         ice_rss_config_xor(hw, prof_id,
2025                                            tcp_src->idx, tcp_dst->idx, 1);
2026
2027                 /* xor UDP */
2028                 if (udp_src->prot_id != 0 && udp_dst->prot_id != 0)
2029                         ice_rss_config_xor(hw, prof_id,
2030                                            udp_src->idx, udp_dst->idx, 1);
2031
2032                 /* xor SCTP */
2033                 if (sctp_src->prot_id != 0 && sctp_dst->prot_id != 0)
2034                         ice_rss_config_xor(hw, prof_id,
2035                                            sctp_src->idx, sctp_dst->idx, 1);
2036         }
2037 }
2038
2039 /**
2040  * ice_add_rss_cfg_sync - add an RSS configuration
2041  * @hw: pointer to the hardware structure
2042  * @vsi_handle: software VSI handle
2043  * @hashed_flds: hash bit fields (ICE_FLOW_HASH_*) to configure
2044  * @addl_hdrs: protocol header fields
2045  * @segs_cnt: packet segment count
2046  * @symm: symmetric hash enable/disable
2047  *
2048  * Assumption: lock has already been acquired for RSS list
2049  */
2050 static enum ice_status
2051 ice_add_rss_cfg_sync(struct ice_hw *hw, u16 vsi_handle, u64 hashed_flds,
2052                      u32 addl_hdrs, u8 segs_cnt, bool symm)
2053 {
2054         const enum ice_block blk = ICE_BLK_RSS;
2055         struct ice_flow_prof *prof = NULL;
2056         struct ice_flow_seg_info *segs;
2057         enum ice_status status = ICE_SUCCESS;
2058
2059         if (!segs_cnt || segs_cnt > ICE_FLOW_SEG_MAX)
2060                 return ICE_ERR_PARAM;
2061
2062         segs = (struct ice_flow_seg_info *)ice_calloc(hw, segs_cnt,
2063                                                       sizeof(*segs));
2064         if (!segs)
2065                 return ICE_ERR_NO_MEMORY;
2066
2067         /* Construct the packet segment info from the hashed fields */
2068         status = ice_flow_set_rss_seg_info(&segs[segs_cnt - 1], hashed_flds,
2069                                            addl_hdrs);
2070         if (status)
2071                 goto exit;
2072
2073         /* Search for a flow profile that has matching headers, hash fields
2074          * and has the input VSI associated to it. If found, no further
2075          * operations required and exit.
2076          */
2077         prof = ice_flow_find_prof_conds(hw, blk, ICE_FLOW_RX, segs, segs_cnt,
2078                                         vsi_handle,
2079                                         ICE_FLOW_FIND_PROF_CHK_FLDS |
2080                                         ICE_FLOW_FIND_PROF_CHK_VSI);
2081         if (prof) {
2082                 if (prof->cfg.symm == symm)
2083                         goto exit;
2084                 prof->cfg.symm = symm;
2085                 goto update_symm;
2086         }
2087
2088         /* Check if a flow profile exists with the same protocol headers and
2089          * associated with the input VSI. If so disasscociate the VSI from
2090          * this profile. The VSI will be added to a new profile created with
2091          * the protocol header and new hash field configuration.
2092          */
2093         prof = ice_flow_find_prof_conds(hw, blk, ICE_FLOW_RX, segs, segs_cnt,
2094                                         vsi_handle, ICE_FLOW_FIND_PROF_CHK_VSI);
2095         if (prof) {
2096                 status = ice_flow_disassoc_prof(hw, blk, prof, vsi_handle);
2097                 if (!status)
2098                         ice_rem_rss_list(hw, vsi_handle, prof);
2099                 else
2100                         goto exit;
2101
2102                 /* Remove profile if it has no VSIs associated */
2103                 if (!ice_is_any_bit_set(prof->vsis, ICE_MAX_VSI)) {
2104                         status = ice_flow_rem_prof(hw, blk, prof->id);
2105                         if (status)
2106                                 goto exit;
2107                 }
2108         }
2109
2110         /* Search for a profile that has same match fields only. If this
2111          * exists then associate the VSI to this profile.
2112          */
2113         prof = ice_flow_find_prof_conds(hw, blk, ICE_FLOW_RX, segs, segs_cnt,
2114                                         vsi_handle,
2115                                         ICE_FLOW_FIND_PROF_CHK_FLDS);
2116         if (prof) {
2117                 if (prof->cfg.symm == symm) {
2118                         status = ice_flow_assoc_prof(hw, blk, prof,
2119                                                      vsi_handle);
2120                         if (!status)
2121                                 status = ice_add_rss_list(hw, vsi_handle,
2122                                                           prof);
2123                 } else {
2124                         /* if a profile exist but with different symmetric
2125                          * requirement, just return error.
2126                          */
2127                         status = ICE_ERR_NOT_SUPPORTED;
2128                 }
2129                 goto exit;
2130         }
2131
2132         /* Create a new flow profile with generated profile and packet
2133          * segment information.
2134          */
2135         status = ice_flow_add_prof(hw, blk, ICE_FLOW_RX,
2136                                    ICE_FLOW_GEN_PROFID(hashed_flds,
2137                                                        segs[segs_cnt - 1].hdrs,
2138                                                        segs_cnt),
2139                                    segs, segs_cnt, NULL, 0, &prof);
2140         if (status)
2141                 goto exit;
2142
2143         status = ice_flow_assoc_prof(hw, blk, prof, vsi_handle);
2144         /* If association to a new flow profile failed then this profile can
2145          * be removed.
2146          */
2147         if (status) {
2148                 ice_flow_rem_prof(hw, blk, prof->id);
2149                 goto exit;
2150         }
2151
2152         status = ice_add_rss_list(hw, vsi_handle, prof);
2153
2154         prof->cfg.symm = symm;
2155         if (!symm)
2156                 goto exit;
2157
2158 update_symm:
2159         ice_rss_update_symm(hw, prof);
2160
2161 exit:
2162         ice_free(hw, segs);
2163         return status;
2164 }
2165
2166 /**
2167  * ice_add_rss_cfg - add an RSS configuration with specified hashed fields
2168  * @hw: pointer to the hardware structure
2169  * @vsi_handle: software VSI handle
2170  * @hashed_flds: hash bit fields (ICE_FLOW_HASH_*) to configure
2171  * @addl_hdrs: protocol header fields
2172  * @symm: symmetric hash enable/disable
2173  *
2174  * This function will generate a flow profile based on fields associated with
2175  * the input fields to hash on, the flow type and use the VSI number to add
2176  * a flow entry to the profile.
2177  */
2178 enum ice_status
2179 ice_add_rss_cfg(struct ice_hw *hw, u16 vsi_handle, u64 hashed_flds,
2180                 u32 addl_hdrs, bool symm)
2181 {
2182         enum ice_status status;
2183
2184         if (hashed_flds == ICE_HASH_INVALID ||
2185             !ice_is_vsi_valid(hw, vsi_handle))
2186                 return ICE_ERR_PARAM;
2187
2188         ice_acquire_lock(&hw->rss_locks);
2189         status = ice_add_rss_cfg_sync(hw, vsi_handle, hashed_flds, addl_hdrs,
2190                                       ICE_RSS_OUTER_HEADERS, symm);
2191         if (!status)
2192                 status = ice_add_rss_cfg_sync(hw, vsi_handle, hashed_flds,
2193                                               addl_hdrs, ICE_RSS_INNER_HEADERS,
2194                                               symm);
2195         ice_release_lock(&hw->rss_locks);
2196
2197         return status;
2198 }
2199
2200 /**
2201  * ice_rem_rss_cfg_sync - remove an existing RSS configuration
2202  * @hw: pointer to the hardware structure
2203  * @vsi_handle: software VSI handle
2204  * @hashed_flds: Packet hash types (ICE_FLOW_HASH_*) to remove
2205  * @addl_hdrs: Protocol header fields within a packet segment
2206  * @segs_cnt: packet segment count
2207  *
2208  * Assumption: lock has already been acquired for RSS list
2209  */
2210 static enum ice_status
2211 ice_rem_rss_cfg_sync(struct ice_hw *hw, u16 vsi_handle, u64 hashed_flds,
2212                      u32 addl_hdrs, u8 segs_cnt)
2213 {
2214         const enum ice_block blk = ICE_BLK_RSS;
2215         struct ice_flow_seg_info *segs;
2216         struct ice_flow_prof *prof;
2217         enum ice_status status;
2218
2219         segs = (struct ice_flow_seg_info *)ice_calloc(hw, segs_cnt,
2220                                                       sizeof(*segs));
2221         if (!segs)
2222                 return ICE_ERR_NO_MEMORY;
2223
2224         /* Construct the packet segment info from the hashed fields */
2225         status = ice_flow_set_rss_seg_info(&segs[segs_cnt - 1], hashed_flds,
2226                                            addl_hdrs);
2227         if (status)
2228                 goto out;
2229
2230         prof = ice_flow_find_prof_conds(hw, blk, ICE_FLOW_RX, segs, segs_cnt,
2231                                         vsi_handle,
2232                                         ICE_FLOW_FIND_PROF_CHK_FLDS);
2233         if (!prof) {
2234                 status = ICE_ERR_DOES_NOT_EXIST;
2235                 goto out;
2236         }
2237
2238         status = ice_flow_disassoc_prof(hw, blk, prof, vsi_handle);
2239         if (status)
2240                 goto out;
2241
2242         /* Remove RSS configuration from VSI context before deleting
2243          * the flow profile.
2244          */
2245         ice_rem_rss_list(hw, vsi_handle, prof);
2246
2247         if (!ice_is_any_bit_set(prof->vsis, ICE_MAX_VSI))
2248                 status = ice_flow_rem_prof(hw, blk, prof->id);
2249
2250 out:
2251         ice_free(hw, segs);
2252         return status;
2253 }
2254
2255 /**
2256  * ice_rem_rss_cfg - remove an existing RSS config with matching hashed fields
2257  * @hw: pointer to the hardware structure
2258  * @vsi_handle: software VSI handle
2259  * @hashed_flds: Packet hash types (ICE_FLOW_HASH_*) to remove
2260  * @addl_hdrs: Protocol header fields within a packet segment
2261  *
2262  * This function will lookup the flow profile based on the input
2263  * hash field bitmap, iterate through the profile entry list of
2264  * that profile and find entry associated with input VSI to be
2265  * removed. Calls are made to underlying flow apis which will in
2266  * turn build or update buffers for RSS XLT1 section.
2267  */
2268 enum ice_status
2269 ice_rem_rss_cfg(struct ice_hw *hw, u16 vsi_handle, u64 hashed_flds,
2270                 u32 addl_hdrs)
2271 {
2272         enum ice_status status;
2273
2274         if (hashed_flds == ICE_HASH_INVALID ||
2275             !ice_is_vsi_valid(hw, vsi_handle))
2276                 return ICE_ERR_PARAM;
2277
2278         ice_acquire_lock(&hw->rss_locks);
2279         status = ice_rem_rss_cfg_sync(hw, vsi_handle, hashed_flds, addl_hdrs,
2280                                       ICE_RSS_OUTER_HEADERS);
2281         if (!status)
2282                 status = ice_rem_rss_cfg_sync(hw, vsi_handle, hashed_flds,
2283                                               addl_hdrs, ICE_RSS_INNER_HEADERS);
2284         ice_release_lock(&hw->rss_locks);
2285
2286         return status;
2287 }
2288
2289 /**
2290  * ice_replay_rss_cfg - replay RSS configurations associated with VSI
2291  * @hw: pointer to the hardware structure
2292  * @vsi_handle: software VSI handle
2293  */
2294 enum ice_status ice_replay_rss_cfg(struct ice_hw *hw, u16 vsi_handle)
2295 {
2296         enum ice_status status = ICE_SUCCESS;
2297         struct ice_rss_cfg *r;
2298
2299         if (!ice_is_vsi_valid(hw, vsi_handle))
2300                 return ICE_ERR_PARAM;
2301
2302         ice_acquire_lock(&hw->rss_locks);
2303         LIST_FOR_EACH_ENTRY(r, &hw->rss_list_head,
2304                             ice_rss_cfg, l_entry) {
2305                 if (ice_is_bit_set(r->vsis, vsi_handle)) {
2306                         status = ice_add_rss_cfg_sync(hw, vsi_handle,
2307                                                       r->hashed_flds,
2308                                                       r->packet_hdr,
2309                                                       ICE_RSS_OUTER_HEADERS,
2310                                                       r->symm);
2311                         if (status)
2312                                 break;
2313                         status = ice_add_rss_cfg_sync(hw, vsi_handle,
2314                                                       r->hashed_flds,
2315                                                       r->packet_hdr,
2316                                                       ICE_RSS_INNER_HEADERS,
2317                                                       r->symm);
2318                         if (status)
2319                                 break;
2320                 }
2321         }
2322         ice_release_lock(&hw->rss_locks);
2323
2324         return status;
2325 }
2326
2327 /**
2328  * ice_get_rss_cfg - returns hashed fields for the given header types
2329  * @hw: pointer to the hardware structure
2330  * @vsi_handle: software VSI handle
2331  * @hdrs: protocol header type
2332  *
2333  * This function will return the match fields of the first instance of flow
2334  * profile having the given header types and containing input VSI
2335  */
2336 u64 ice_get_rss_cfg(struct ice_hw *hw, u16 vsi_handle, u32 hdrs)
2337 {
2338         struct ice_rss_cfg *r, *rss_cfg = NULL;
2339
2340         /* verify if the protocol header is non zero and VSI is valid */
2341         if (hdrs == ICE_FLOW_SEG_HDR_NONE || !ice_is_vsi_valid(hw, vsi_handle))
2342                 return ICE_HASH_INVALID;
2343
2344         ice_acquire_lock(&hw->rss_locks);
2345         LIST_FOR_EACH_ENTRY(r, &hw->rss_list_head,
2346                             ice_rss_cfg, l_entry)
2347                 if (ice_is_bit_set(r->vsis, vsi_handle) &&
2348                     r->packet_hdr == hdrs) {
2349                         rss_cfg = r;
2350                         break;
2351                 }
2352         ice_release_lock(&hw->rss_locks);
2353
2354         return rss_cfg ? rss_cfg->hashed_flds : ICE_HASH_INVALID;
2355 }