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