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