ad318567777a2238d05bb672ea6be7cddcc1e2f6
[dpdk.git] / drivers / net / ice / base / ice_flow.c
1 /* SPDX-License-Identifier: BSD-3-Clause
2  * Copyright(c) 2001-2020 Intel Corporation
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_IPV6_PRE32_ADDR 4
14 #define ICE_FLOW_FLD_SZ_IPV6_PRE48_ADDR 6
15 #define ICE_FLOW_FLD_SZ_IPV6_PRE64_ADDR 8
16 #define ICE_FLOW_FLD_SZ_IP_DSCP         1
17 #define ICE_FLOW_FLD_SZ_IP_TTL          1
18 #define ICE_FLOW_FLD_SZ_IP_PROT         1
19 #define ICE_FLOW_FLD_SZ_PORT            2
20 #define ICE_FLOW_FLD_SZ_TCP_FLAGS       1
21 #define ICE_FLOW_FLD_SZ_ICMP_TYPE       1
22 #define ICE_FLOW_FLD_SZ_ICMP_CODE       1
23 #define ICE_FLOW_FLD_SZ_ARP_OPER        2
24 #define ICE_FLOW_FLD_SZ_GRE_KEYID       4
25 #define ICE_FLOW_FLD_SZ_GTP_TEID        4
26 #define ICE_FLOW_FLD_SZ_GTP_QFI         2
27 #define ICE_FLOW_FLD_SZ_PPPOE_SESS_ID   2
28 #define ICE_FLOW_FLD_SZ_PFCP_SEID 8
29 #define ICE_FLOW_FLD_SZ_L2TPV3_SESS_ID  4
30 #define ICE_FLOW_FLD_SZ_ESP_SPI 4
31 #define ICE_FLOW_FLD_SZ_AH_SPI  4
32 #define ICE_FLOW_FLD_SZ_NAT_T_ESP_SPI   4
33 #define ICE_FLOW_FLD_SZ_VXLAN_VNI       4
34 #define ICE_FLOW_FLD_SZ_ECPRI_TP0_PC_ID 2
35
36 /* Describe properties of a protocol header field */
37 struct ice_flow_field_info {
38         enum ice_flow_seg_hdr hdr;
39         s16 off;        /* Offset from start of a protocol header, in bits */
40         u16 size;       /* Size of fields in bits */
41         u16 mask;       /* 16-bit mask for field */
42 };
43
44 #define ICE_FLOW_FLD_INFO(_hdr, _offset_bytes, _size_bytes) { \
45         .hdr = _hdr, \
46         .off = (_offset_bytes) * BITS_PER_BYTE, \
47         .size = (_size_bytes) * BITS_PER_BYTE, \
48         .mask = 0, \
49 }
50
51 #define ICE_FLOW_FLD_INFO_MSK(_hdr, _offset_bytes, _size_bytes, _mask) { \
52         .hdr = _hdr, \
53         .off = (_offset_bytes) * BITS_PER_BYTE, \
54         .size = (_size_bytes) * BITS_PER_BYTE, \
55         .mask = _mask, \
56 }
57
58 /* Table containing properties of supported protocol header fields */
59 static const
60 struct ice_flow_field_info ice_flds_info[ICE_FLOW_FIELD_IDX_MAX] = {
61         /* Ether */
62         /* ICE_FLOW_FIELD_IDX_ETH_DA */
63         ICE_FLOW_FLD_INFO(ICE_FLOW_SEG_HDR_ETH, 0, ETH_ALEN),
64         /* ICE_FLOW_FIELD_IDX_ETH_SA */
65         ICE_FLOW_FLD_INFO(ICE_FLOW_SEG_HDR_ETH, ETH_ALEN, ETH_ALEN),
66         /* ICE_FLOW_FIELD_IDX_S_VLAN */
67         ICE_FLOW_FLD_INFO(ICE_FLOW_SEG_HDR_VLAN, 12, ICE_FLOW_FLD_SZ_VLAN),
68         /* ICE_FLOW_FIELD_IDX_C_VLAN */
69         ICE_FLOW_FLD_INFO(ICE_FLOW_SEG_HDR_VLAN, 14, ICE_FLOW_FLD_SZ_VLAN),
70         /* ICE_FLOW_FIELD_IDX_ETH_TYPE */
71         ICE_FLOW_FLD_INFO(ICE_FLOW_SEG_HDR_ETH, 0, ICE_FLOW_FLD_SZ_ETH_TYPE),
72         /* IPv4 / IPv6 */
73         /* ICE_FLOW_FIELD_IDX_IPV4_DSCP */
74         ICE_FLOW_FLD_INFO_MSK(ICE_FLOW_SEG_HDR_IPV4, 0, ICE_FLOW_FLD_SZ_IP_DSCP,
75                               0x00fc),
76         /* ICE_FLOW_FIELD_IDX_IPV6_DSCP */
77         ICE_FLOW_FLD_INFO_MSK(ICE_FLOW_SEG_HDR_IPV6, 0, ICE_FLOW_FLD_SZ_IP_DSCP,
78                               0x0ff0),
79         /* ICE_FLOW_FIELD_IDX_IPV4_TTL */
80         ICE_FLOW_FLD_INFO_MSK(ICE_FLOW_SEG_HDR_NONE, 8,
81                               ICE_FLOW_FLD_SZ_IP_TTL, 0xff00),
82         /* ICE_FLOW_FIELD_IDX_IPV4_PROT */
83         ICE_FLOW_FLD_INFO_MSK(ICE_FLOW_SEG_HDR_NONE, 8,
84                               ICE_FLOW_FLD_SZ_IP_PROT, 0x00ff),
85         /* ICE_FLOW_FIELD_IDX_IPV6_TTL */
86         ICE_FLOW_FLD_INFO_MSK(ICE_FLOW_SEG_HDR_NONE, 6,
87                               ICE_FLOW_FLD_SZ_IP_TTL, 0x00ff),
88         /* ICE_FLOW_FIELD_IDX_IPV6_PROT */
89         ICE_FLOW_FLD_INFO_MSK(ICE_FLOW_SEG_HDR_NONE, 6,
90                               ICE_FLOW_FLD_SZ_IP_PROT, 0xff00),
91         /* ICE_FLOW_FIELD_IDX_IPV4_SA */
92         ICE_FLOW_FLD_INFO(ICE_FLOW_SEG_HDR_IPV4, 12, ICE_FLOW_FLD_SZ_IPV4_ADDR),
93         /* ICE_FLOW_FIELD_IDX_IPV4_DA */
94         ICE_FLOW_FLD_INFO(ICE_FLOW_SEG_HDR_IPV4, 16, ICE_FLOW_FLD_SZ_IPV4_ADDR),
95         /* ICE_FLOW_FIELD_IDX_IPV6_SA */
96         ICE_FLOW_FLD_INFO(ICE_FLOW_SEG_HDR_IPV6, 8, ICE_FLOW_FLD_SZ_IPV6_ADDR),
97         /* ICE_FLOW_FIELD_IDX_IPV6_DA */
98         ICE_FLOW_FLD_INFO(ICE_FLOW_SEG_HDR_IPV6, 24, ICE_FLOW_FLD_SZ_IPV6_ADDR),
99         /* ICE_FLOW_FIELD_IDX_IPV6_PRE32_SA */
100         ICE_FLOW_FLD_INFO(ICE_FLOW_SEG_HDR_IPV6, 8,
101                           ICE_FLOW_FLD_SZ_IPV6_PRE32_ADDR),
102         /* ICE_FLOW_FIELD_IDX_IPV6_PRE32_DA */
103         ICE_FLOW_FLD_INFO(ICE_FLOW_SEG_HDR_IPV6, 24,
104                           ICE_FLOW_FLD_SZ_IPV6_PRE32_ADDR),
105         /* ICE_FLOW_FIELD_IDX_IPV6_PRE48_SA */
106         ICE_FLOW_FLD_INFO(ICE_FLOW_SEG_HDR_IPV6, 8,
107                           ICE_FLOW_FLD_SZ_IPV6_PRE48_ADDR),
108         /* ICE_FLOW_FIELD_IDX_IPV6_PRE48_DA */
109         ICE_FLOW_FLD_INFO(ICE_FLOW_SEG_HDR_IPV6, 24,
110                           ICE_FLOW_FLD_SZ_IPV6_PRE48_ADDR),
111         /* ICE_FLOW_FIELD_IDX_IPV6_PRE64_SA */
112         ICE_FLOW_FLD_INFO(ICE_FLOW_SEG_HDR_IPV6, 8,
113                           ICE_FLOW_FLD_SZ_IPV6_PRE64_ADDR),
114         /* ICE_FLOW_FIELD_IDX_IPV6_PRE64_DA */
115         ICE_FLOW_FLD_INFO(ICE_FLOW_SEG_HDR_IPV6, 24,
116                           ICE_FLOW_FLD_SZ_IPV6_PRE64_ADDR),
117         /* Transport */
118         /* ICE_FLOW_FIELD_IDX_TCP_SRC_PORT */
119         ICE_FLOW_FLD_INFO(ICE_FLOW_SEG_HDR_TCP, 0, ICE_FLOW_FLD_SZ_PORT),
120         /* ICE_FLOW_FIELD_IDX_TCP_DST_PORT */
121         ICE_FLOW_FLD_INFO(ICE_FLOW_SEG_HDR_TCP, 2, ICE_FLOW_FLD_SZ_PORT),
122         /* ICE_FLOW_FIELD_IDX_UDP_SRC_PORT */
123         ICE_FLOW_FLD_INFO(ICE_FLOW_SEG_HDR_UDP, 0, ICE_FLOW_FLD_SZ_PORT),
124         /* ICE_FLOW_FIELD_IDX_UDP_DST_PORT */
125         ICE_FLOW_FLD_INFO(ICE_FLOW_SEG_HDR_UDP, 2, ICE_FLOW_FLD_SZ_PORT),
126         /* ICE_FLOW_FIELD_IDX_SCTP_SRC_PORT */
127         ICE_FLOW_FLD_INFO(ICE_FLOW_SEG_HDR_SCTP, 0, ICE_FLOW_FLD_SZ_PORT),
128         /* ICE_FLOW_FIELD_IDX_SCTP_DST_PORT */
129         ICE_FLOW_FLD_INFO(ICE_FLOW_SEG_HDR_SCTP, 2, ICE_FLOW_FLD_SZ_PORT),
130         /* ICE_FLOW_FIELD_IDX_TCP_FLAGS */
131         ICE_FLOW_FLD_INFO(ICE_FLOW_SEG_HDR_TCP, 13, ICE_FLOW_FLD_SZ_TCP_FLAGS),
132         /* ARP */
133         /* ICE_FLOW_FIELD_IDX_ARP_SIP */
134         ICE_FLOW_FLD_INFO(ICE_FLOW_SEG_HDR_ARP, 14, ICE_FLOW_FLD_SZ_IPV4_ADDR),
135         /* ICE_FLOW_FIELD_IDX_ARP_DIP */
136         ICE_FLOW_FLD_INFO(ICE_FLOW_SEG_HDR_ARP, 24, ICE_FLOW_FLD_SZ_IPV4_ADDR),
137         /* ICE_FLOW_FIELD_IDX_ARP_SHA */
138         ICE_FLOW_FLD_INFO(ICE_FLOW_SEG_HDR_ARP, 8, ETH_ALEN),
139         /* ICE_FLOW_FIELD_IDX_ARP_DHA */
140         ICE_FLOW_FLD_INFO(ICE_FLOW_SEG_HDR_ARP, 18, ETH_ALEN),
141         /* ICE_FLOW_FIELD_IDX_ARP_OP */
142         ICE_FLOW_FLD_INFO(ICE_FLOW_SEG_HDR_ARP, 6, ICE_FLOW_FLD_SZ_ARP_OPER),
143         /* ICMP */
144         /* ICE_FLOW_FIELD_IDX_ICMP_TYPE */
145         ICE_FLOW_FLD_INFO(ICE_FLOW_SEG_HDR_ICMP, 0, ICE_FLOW_FLD_SZ_ICMP_TYPE),
146         /* ICE_FLOW_FIELD_IDX_ICMP_CODE */
147         ICE_FLOW_FLD_INFO(ICE_FLOW_SEG_HDR_ICMP, 1, ICE_FLOW_FLD_SZ_ICMP_CODE),
148         /* GRE */
149         /* ICE_FLOW_FIELD_IDX_GRE_KEYID */
150         ICE_FLOW_FLD_INFO(ICE_FLOW_SEG_HDR_GRE, 12, ICE_FLOW_FLD_SZ_GRE_KEYID),
151         /* GTP */
152         /* ICE_FLOW_FIELD_IDX_GTPC_TEID */
153         ICE_FLOW_FLD_INFO(ICE_FLOW_SEG_HDR_GTPC_TEID, 12,
154                           ICE_FLOW_FLD_SZ_GTP_TEID),
155         /* ICE_FLOW_FIELD_IDX_GTPU_IP_TEID */
156         ICE_FLOW_FLD_INFO(ICE_FLOW_SEG_HDR_GTPU_IP, 12,
157                           ICE_FLOW_FLD_SZ_GTP_TEID),
158         /* ICE_FLOW_FIELD_IDX_GTPU_EH_TEID */
159         ICE_FLOW_FLD_INFO(ICE_FLOW_SEG_HDR_GTPU_EH, 12,
160                           ICE_FLOW_FLD_SZ_GTP_TEID),
161         /* ICE_FLOW_FIELD_IDX_GTPU_EH_QFI */
162         ICE_FLOW_FLD_INFO_MSK(ICE_FLOW_SEG_HDR_GTPU_EH, 22,
163                               ICE_FLOW_FLD_SZ_GTP_QFI, 0x3f00),
164         /* ICE_FLOW_FIELD_IDX_GTPU_UP_TEID */
165         ICE_FLOW_FLD_INFO(ICE_FLOW_SEG_HDR_GTPU_UP, 12,
166                           ICE_FLOW_FLD_SZ_GTP_TEID),
167         /* ICE_FLOW_FIELD_IDX_GTPU_DWN_TEID */
168         ICE_FLOW_FLD_INFO(ICE_FLOW_SEG_HDR_GTPU_DWN, 12,
169                           ICE_FLOW_FLD_SZ_GTP_TEID),
170         /* PPPOE */
171         /* ICE_FLOW_FIELD_IDX_PPPOE_SESS_ID */
172         ICE_FLOW_FLD_INFO(ICE_FLOW_SEG_HDR_PPPOE, 2,
173                           ICE_FLOW_FLD_SZ_PPPOE_SESS_ID),
174         /* PFCP */
175         /* ICE_FLOW_FIELD_IDX_PFCP_SEID */
176         ICE_FLOW_FLD_INFO(ICE_FLOW_SEG_HDR_PFCP_SESSION, 12,
177                           ICE_FLOW_FLD_SZ_PFCP_SEID),
178         /* L2TPV3 */
179         /* ICE_FLOW_FIELD_IDX_L2TPV3_SESS_ID */
180         ICE_FLOW_FLD_INFO(ICE_FLOW_SEG_HDR_L2TPV3, 0,
181                           ICE_FLOW_FLD_SZ_L2TPV3_SESS_ID),
182         /* ESP */
183         /* ICE_FLOW_FIELD_IDX_ESP_SPI */
184         ICE_FLOW_FLD_INFO(ICE_FLOW_SEG_HDR_ESP, 0,
185                           ICE_FLOW_FLD_SZ_ESP_SPI),
186         /* AH */
187         /* ICE_FLOW_FIELD_IDX_AH_SPI */
188         ICE_FLOW_FLD_INFO(ICE_FLOW_SEG_HDR_AH, 4,
189                           ICE_FLOW_FLD_SZ_AH_SPI),
190         /* NAT_T_ESP */
191         /* ICE_FLOW_FIELD_IDX_NAT_T_ESP_SPI */
192         ICE_FLOW_FLD_INFO(ICE_FLOW_SEG_HDR_NAT_T_ESP, 8,
193                           ICE_FLOW_FLD_SZ_NAT_T_ESP_SPI),
194         /* ICE_FLOW_FIELD_IDX_VXLAN_VNI */
195         ICE_FLOW_FLD_INFO(ICE_FLOW_SEG_HDR_VXLAN, 12,
196                           ICE_FLOW_FLD_SZ_VXLAN_VNI),
197         /* ECPRI_TP0 */
198         /* ICE_FLOW_FIELD_IDX_ECPRI_TP0_PC_ID */
199         ICE_FLOW_FLD_INFO(ICE_FLOW_SEG_HDR_ECPRI_TP0, 4,
200                           ICE_FLOW_FLD_SZ_ECPRI_TP0_PC_ID),
201         /* UDP_ECPRI_TP0 */
202         /* ICE_FLOW_FIELD_IDX_UDP_ECPRI_TP0_PC_ID */
203         ICE_FLOW_FLD_INFO(ICE_FLOW_SEG_HDR_UDP_ECPRI_TP0, 12,
204                           ICE_FLOW_FLD_SZ_ECPRI_TP0_PC_ID),
205 };
206
207 /* Bitmaps indicating relevant packet types for a particular protocol header
208  *
209  * Packet types for packets with an Outer/First/Single MAC header
210  */
211 static const u32 ice_ptypes_mac_ofos[] = {
212         0xFDC00846, 0xBFBF7F7E, 0xF70001DF, 0xFEFDFDFB,
213         0x0000077E, 0x000003FF, 0x00000000, 0x00000000,
214         0x00400000, 0x03FFF000, 0xFFFFFFE0, 0x00100707,
215         0x00000000, 0x00000000, 0x00000000, 0x00000000,
216         0x00000000, 0x00000000, 0x00000000, 0x00000000,
217         0x00000000, 0x00000000, 0x00000000, 0x00000000,
218         0x00000000, 0x00000000, 0x00000000, 0x00000000,
219         0x00000000, 0x00000000, 0x00000000, 0x00000000,
220 };
221
222 /* Packet types for packets with an Innermost/Last MAC VLAN header */
223 static const u32 ice_ptypes_macvlan_il[] = {
224         0x00000000, 0xBC000000, 0x000001DF, 0xF0000000,
225         0x0000077E, 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 };
233
234 /* Packet types for packets with an Outer/First/Single IPv4 header, does NOT
235  * include IPV4 other PTYPEs
236  */
237 static const u32 ice_ptypes_ipv4_ofos[] = {
238         0x1DC00000, 0x24000800, 0x00000000, 0x00000000,
239         0x00000000, 0x00000155, 0x00000000, 0x00000000,
240         0x00000000, 0x000FC000, 0x000002A0, 0x00100000,
241         0x00000000, 0x00000000, 0x00000000, 0x00000000,
242         0x00000000, 0x00000000, 0x00000000, 0x00000000,
243         0x00000000, 0x00000000, 0x00000000, 0x00000000,
244         0x00000000, 0x00000000, 0x00000000, 0x00000000,
245         0x00000000, 0x00000000, 0x00000000, 0x00000000,
246 };
247
248 /* Packet types for packets with an Outer/First/Single IPv4 header, includes
249  * IPV4 other PTYPEs
250  */
251 static const u32 ice_ptypes_ipv4_ofos_all[] = {
252         0x1DC00000, 0x24000800, 0x00000000, 0x00000000,
253         0x00000000, 0x00000155, 0x00000000, 0x00000000,
254         0x00000000, 0x000FC000, 0x83E0FAA0, 0x00000101,
255         0x00000000, 0x00000000, 0x00000000, 0x00000000,
256         0x00000000, 0x00000000, 0x00000000, 0x00000000,
257         0x00000000, 0x00000000, 0x00000000, 0x00000000,
258         0x00000000, 0x00000000, 0x00000000, 0x00000000,
259         0x00000000, 0x00000000, 0x00000000, 0x00000000,
260 };
261
262 /* Packet types for packets with an Innermost/Last IPv4 header */
263 static const u32 ice_ptypes_ipv4_il[] = {
264         0xE0000000, 0xB807700E, 0x80000003, 0xE01DC03B,
265         0x0000000E, 0x00000000, 0x00000000, 0x00000000,
266         0x00000000, 0x00000000, 0x001FF800, 0x00100000,
267         0x00000000, 0x00000000, 0x00000000, 0x00000000,
268         0x00000000, 0x00000000, 0x00000000, 0x00000000,
269         0x00000000, 0x00000000, 0x00000000, 0x00000000,
270         0x00000000, 0x00000000, 0x00000000, 0x00000000,
271         0x00000000, 0x00000000, 0x00000000, 0x00000000,
272 };
273
274 /* Packet types for packets with an Outer/First/Single IPv6 header, does NOT
275  * include IVP6 other PTYPEs
276  */
277 static const u32 ice_ptypes_ipv6_ofos[] = {
278         0x00000000, 0x00000000, 0x77000000, 0x10002000,
279         0x00000000, 0x000002AA, 0x00000000, 0x00000000,
280         0x00000000, 0x03F00000, 0x00000540, 0x00000000,
281         0x00000000, 0x00000000, 0x00000000, 0x00000000,
282         0x00000000, 0x00000000, 0x00000000, 0x00000000,
283         0x00000000, 0x00000000, 0x00000000, 0x00000000,
284         0x00000000, 0x00000000, 0x00000000, 0x00000000,
285         0x00000000, 0x00000000, 0x00000000, 0x00000000,
286 };
287
288 /* Packet types for packets with an Outer/First/Single IPv6 header, includes
289  * IPV6 other PTYPEs
290  */
291 static const u32 ice_ptypes_ipv6_ofos_all[] = {
292         0x00000000, 0x00000000, 0x77000000, 0x10002000,
293         0x00000000, 0x000002AA, 0x00000000, 0x00000000,
294         0x00000000, 0x03F00000, 0x7C1F0540, 0x00000206,
295         0x00000000, 0x00000000, 0x00000000, 0x00000000,
296         0x00000000, 0x00000000, 0x00000000, 0x00000000,
297         0x00000000, 0x00000000, 0x00000000, 0x00000000,
298         0x00000000, 0x00000000, 0x00000000, 0x00000000,
299         0x00000000, 0x00000000, 0x00000000, 0x00000000,
300 };
301
302 /* Packet types for packets with an Innermost/Last IPv6 header */
303 static const u32 ice_ptypes_ipv6_il[] = {
304         0x00000000, 0x03B80770, 0x000001DC, 0x0EE00000,
305         0x00000770, 0x00000000, 0x00000000, 0x00000000,
306         0x00000000, 0x00000000, 0x7FE00000, 0x00000000,
307         0x00000000, 0x00000000, 0x00000000, 0x00000000,
308         0x00000000, 0x00000000, 0x00000000, 0x00000000,
309         0x00000000, 0x00000000, 0x00000000, 0x00000000,
310         0x00000000, 0x00000000, 0x00000000, 0x00000000,
311         0x00000000, 0x00000000, 0x00000000, 0x00000000,
312 };
313
314 /* Packet types for packets with an Outer/First/Single IPv4 header - no L4 */
315 static const u32 ice_ptypes_ipv4_ofos_no_l4[] = {
316         0x10C00000, 0x04000800, 0x00000000, 0x00000000,
317         0x00000000, 0x00000000, 0x00000000, 0x00000000,
318         0x00000000, 0x000cc000, 0x000002A0, 0x00000000,
319         0x00000000, 0x00000000, 0x00000000, 0x00000000,
320         0x00000000, 0x00000000, 0x00000000, 0x00000000,
321         0x00000000, 0x00000000, 0x00000000, 0x00000000,
322         0x00000000, 0x00000000, 0x00000000, 0x00000000,
323         0x00000000, 0x00000000, 0x00000000, 0x00000000,
324 };
325
326 /* Packet types for packets with an Innermost/Last IPv4 header - no L4 */
327 static const u32 ice_ptypes_ipv4_il_no_l4[] = {
328         0x60000000, 0x18043008, 0x80000002, 0x6010c021,
329         0x00000008, 0x00000000, 0x00000000, 0x00000000,
330         0x00000000, 0x00000000, 0x00139800, 0x00000000,
331         0x00000000, 0x00000000, 0x00000000, 0x00000000,
332         0x00000000, 0x00000000, 0x00000000, 0x00000000,
333         0x00000000, 0x00000000, 0x00000000, 0x00000000,
334         0x00000000, 0x00000000, 0x00000000, 0x00000000,
335         0x00000000, 0x00000000, 0x00000000, 0x00000000,
336 };
337
338 /* Packet types for packets with an Outer/First/Single IPv6 header - no L4 */
339 static const u32 ice_ptypes_ipv6_ofos_no_l4[] = {
340         0x00000000, 0x00000000, 0x43000000, 0x10002000,
341         0x00000000, 0x00000000, 0x00000000, 0x00000000,
342         0x00000000, 0x02300000, 0x00000540, 0x00000000,
343         0x00000000, 0x00000000, 0x00000000, 0x00000000,
344         0x00000000, 0x00000000, 0x00000000, 0x00000000,
345         0x00000000, 0x00000000, 0x00000000, 0x00000000,
346         0x00000000, 0x00000000, 0x00000000, 0x00000000,
347         0x00000000, 0x00000000, 0x00000000, 0x00000000,
348 };
349
350 /* Packet types for packets with an Innermost/Last IPv6 header - no L4 */
351 static const u32 ice_ptypes_ipv6_il_no_l4[] = {
352         0x00000000, 0x02180430, 0x0000010c, 0x086010c0,
353         0x00000430, 0x00000000, 0x00000000, 0x00000000,
354         0x00000000, 0x00000000, 0x4e600000, 0x00000000,
355         0x00000000, 0x00000000, 0x00000000, 0x00000000,
356         0x00000000, 0x00000000, 0x00000000, 0x00000000,
357         0x00000000, 0x00000000, 0x00000000, 0x00000000,
358         0x00000000, 0x00000000, 0x00000000, 0x00000000,
359         0x00000000, 0x00000000, 0x00000000, 0x00000000,
360 };
361
362 /* Packet types for packets with an Outermost/First ARP header */
363 static const u32 ice_ptypes_arp_of[] = {
364         0x00000800, 0x00000000, 0x00000000, 0x00000000,
365         0x00000000, 0x00000000, 0x00000000, 0x00000000,
366         0x00000000, 0x00000000, 0x00000000, 0x00000000,
367         0x00000000, 0x00000000, 0x00000000, 0x00000000,
368         0x00000000, 0x00000000, 0x00000000, 0x00000000,
369         0x00000000, 0x00000000, 0x00000000, 0x00000000,
370         0x00000000, 0x00000000, 0x00000000, 0x00000000,
371         0x00000000, 0x00000000, 0x00000000, 0x00000000,
372 };
373
374 /* UDP Packet types for non-tunneled packets or tunneled
375  * packets with inner UDP.
376  */
377 static const u32 ice_ptypes_udp_il[] = {
378         0x81000000, 0x20204040, 0x04000010, 0x80810102,
379         0x00000040, 0x00000000, 0x00000000, 0x00000000,
380         0x00000000, 0x00410000, 0x908427E0, 0x00100007,
381         0x00000000, 0x00000000, 0x00000000, 0x00000000,
382         0x00000000, 0x00000000, 0x00000000, 0x00000000,
383         0x00000000, 0x00000000, 0x00000000, 0x00000000,
384         0x00000000, 0x00000000, 0x00000000, 0x00000000,
385         0x00000000, 0x00000000, 0x00000000, 0x00000000,
386 };
387
388 /* Packet types for packets with an Innermost/Last TCP header */
389 static const u32 ice_ptypes_tcp_il[] = {
390         0x04000000, 0x80810102, 0x10000040, 0x02040408,
391         0x00000102, 0x00000000, 0x00000000, 0x00000000,
392         0x00000000, 0x00820000, 0x21084000, 0x00000000,
393         0x00000000, 0x00000000, 0x00000000, 0x00000000,
394         0x00000000, 0x00000000, 0x00000000, 0x00000000,
395         0x00000000, 0x00000000, 0x00000000, 0x00000000,
396         0x00000000, 0x00000000, 0x00000000, 0x00000000,
397         0x00000000, 0x00000000, 0x00000000, 0x00000000,
398 };
399
400 /* Packet types for packets with an Innermost/Last SCTP header */
401 static const u32 ice_ptypes_sctp_il[] = {
402         0x08000000, 0x01020204, 0x20000081, 0x04080810,
403         0x00000204, 0x00000000, 0x00000000, 0x00000000,
404         0x00000000, 0x01040000, 0x00000000, 0x00000000,
405         0x00000000, 0x00000000, 0x00000000, 0x00000000,
406         0x00000000, 0x00000000, 0x00000000, 0x00000000,
407         0x00000000, 0x00000000, 0x00000000, 0x00000000,
408         0x00000000, 0x00000000, 0x00000000, 0x00000000,
409         0x00000000, 0x00000000, 0x00000000, 0x00000000,
410 };
411
412 /* Packet types for packets with an Outermost/First ICMP header */
413 static const u32 ice_ptypes_icmp_of[] = {
414         0x10000000, 0x00000000, 0x00000000, 0x00000000,
415         0x00000000, 0x00000000, 0x00000000, 0x00000000,
416         0x00000000, 0x00000000, 0x00000000, 0x00000000,
417         0x00000000, 0x00000000, 0x00000000, 0x00000000,
418         0x00000000, 0x00000000, 0x00000000, 0x00000000,
419         0x00000000, 0x00000000, 0x00000000, 0x00000000,
420         0x00000000, 0x00000000, 0x00000000, 0x00000000,
421         0x00000000, 0x00000000, 0x00000000, 0x00000000,
422 };
423
424 /* Packet types for packets with an Innermost/Last ICMP header */
425 static const u32 ice_ptypes_icmp_il[] = {
426         0x00000000, 0x02040408, 0x40000102, 0x08101020,
427         0x00000408, 0x00000000, 0x00000000, 0x00000000,
428         0x00000000, 0x00000000, 0x42108000, 0x00000000,
429         0x00000000, 0x00000000, 0x00000000, 0x00000000,
430         0x00000000, 0x00000000, 0x00000000, 0x00000000,
431         0x00000000, 0x00000000, 0x00000000, 0x00000000,
432         0x00000000, 0x00000000, 0x00000000, 0x00000000,
433         0x00000000, 0x00000000, 0x00000000, 0x00000000,
434 };
435
436 /* Packet types for packets with an Outermost/First GRE header */
437 static const u32 ice_ptypes_gre_of[] = {
438         0x00000000, 0xBFBF7800, 0x000001DF, 0xFEFDE000,
439         0x0000017E, 0x00000000, 0x00000000, 0x00000000,
440         0x00000000, 0x00000000, 0x00000000, 0x00000000,
441         0x00000000, 0x00000000, 0x00000000, 0x00000000,
442         0x00000000, 0x00000000, 0x00000000, 0x00000000,
443         0x00000000, 0x00000000, 0x00000000, 0x00000000,
444         0x00000000, 0x00000000, 0x00000000, 0x00000000,
445         0x00000000, 0x00000000, 0x00000000, 0x00000000,
446 };
447
448 /* Packet types for packets with an Innermost/Last MAC header */
449 static const u32 ice_ptypes_mac_il[] = {
450         0x00000000, 0x20000000, 0x00000000, 0x00000000,
451         0x00000000, 0x00000000, 0x00000000, 0x00000000,
452         0x00000000, 0x00000000, 0x00000000, 0x00000000,
453         0x00000000, 0x00000000, 0x00000000, 0x00000000,
454         0x00000000, 0x00000000, 0x00000000, 0x00000000,
455         0x00000000, 0x00000000, 0x00000000, 0x00000000,
456         0x00000000, 0x00000000, 0x00000000, 0x00000000,
457         0x00000000, 0x00000000, 0x00000000, 0x00000000,
458 };
459
460 /* Packet types for GTPC */
461 static const u32 ice_ptypes_gtpc[] = {
462         0x00000000, 0x00000000, 0x00000000, 0x00000000,
463         0x00000000, 0x00000000, 0x00000000, 0x00000000,
464         0x00000000, 0x00000000, 0x000001E0, 0x00000000,
465         0x00000000, 0x00000000, 0x00000000, 0x00000000,
466         0x00000000, 0x00000000, 0x00000000, 0x00000000,
467         0x00000000, 0x00000000, 0x00000000, 0x00000000,
468         0x00000000, 0x00000000, 0x00000000, 0x00000000,
469         0x00000000, 0x00000000, 0x00000000, 0x00000000,
470 };
471
472 /* Packet types for VXLAN with VNI */
473 static const u32 ice_ptypes_vxlan_vni[] = {
474         0x00000000, 0xBFBFF800, 0x00EFDFDF, 0xFEFDE000,
475         0x03BF7F7E, 0x00000000, 0x00000000, 0x00000000,
476         0x00000000, 0x00000000, 0x00000000, 0x00000000,
477         0x00000000, 0x00000000, 0x00000000, 0x00000000,
478         0x00000000, 0x00000000, 0x00000000, 0x00000000,
479         0x00000000, 0x00000000, 0x00000000, 0x00000000,
480         0x00000000, 0x00000000, 0x00000000, 0x00000000,
481         0x00000000, 0x00000000, 0x00000000, 0x00000000,
482 };
483
484 /* Packet types for GTPC with TEID */
485 static const u32 ice_ptypes_gtpc_tid[] = {
486         0x00000000, 0x00000000, 0x00000000, 0x00000000,
487         0x00000000, 0x00000000, 0x00000000, 0x00000000,
488         0x00000000, 0x00000000, 0x00000060, 0x00000000,
489         0x00000000, 0x00000000, 0x00000000, 0x00000000,
490         0x00000000, 0x00000000, 0x00000000, 0x00000000,
491         0x00000000, 0x00000000, 0x00000000, 0x00000000,
492         0x00000000, 0x00000000, 0x00000000, 0x00000000,
493         0x00000000, 0x00000000, 0x00000000, 0x00000000,
494 };
495
496 /* Packet types for GTPU */
497 static const struct ice_ptype_attributes ice_attr_gtpu_session[] = {
498         { ICE_MAC_IPV4_GTPU_IPV4_FRAG,    ICE_PTYPE_ATTR_GTP_SESSION },
499         { ICE_MAC_IPV4_GTPU_IPV4_PAY,     ICE_PTYPE_ATTR_GTP_SESSION },
500         { ICE_MAC_IPV4_GTPU_IPV4_UDP_PAY, ICE_PTYPE_ATTR_GTP_SESSION },
501         { ICE_MAC_IPV4_GTPU_IPV4_TCP,     ICE_PTYPE_ATTR_GTP_SESSION },
502         { ICE_MAC_IPV4_GTPU_IPV4_ICMP,    ICE_PTYPE_ATTR_GTP_SESSION },
503         { ICE_MAC_IPV6_GTPU_IPV4_FRAG,    ICE_PTYPE_ATTR_GTP_SESSION },
504         { ICE_MAC_IPV6_GTPU_IPV4_PAY,     ICE_PTYPE_ATTR_GTP_SESSION },
505         { ICE_MAC_IPV6_GTPU_IPV4_UDP_PAY, ICE_PTYPE_ATTR_GTP_SESSION },
506         { ICE_MAC_IPV6_GTPU_IPV4_TCP,     ICE_PTYPE_ATTR_GTP_SESSION },
507         { ICE_MAC_IPV6_GTPU_IPV4_ICMP,    ICE_PTYPE_ATTR_GTP_SESSION },
508         { ICE_MAC_IPV4_GTPU_IPV6_FRAG,    ICE_PTYPE_ATTR_GTP_SESSION },
509         { ICE_MAC_IPV4_GTPU_IPV6_PAY,     ICE_PTYPE_ATTR_GTP_SESSION },
510         { ICE_MAC_IPV4_GTPU_IPV6_UDP_PAY, ICE_PTYPE_ATTR_GTP_SESSION },
511         { ICE_MAC_IPV4_GTPU_IPV6_TCP,     ICE_PTYPE_ATTR_GTP_SESSION },
512         { ICE_MAC_IPV4_GTPU_IPV6_ICMPV6,  ICE_PTYPE_ATTR_GTP_SESSION },
513         { ICE_MAC_IPV6_GTPU_IPV6_FRAG,    ICE_PTYPE_ATTR_GTP_SESSION },
514         { ICE_MAC_IPV6_GTPU_IPV6_PAY,     ICE_PTYPE_ATTR_GTP_SESSION },
515         { ICE_MAC_IPV6_GTPU_IPV6_UDP_PAY, ICE_PTYPE_ATTR_GTP_SESSION },
516         { ICE_MAC_IPV6_GTPU_IPV6_TCP,     ICE_PTYPE_ATTR_GTP_SESSION },
517         { ICE_MAC_IPV6_GTPU_IPV6_ICMPV6,  ICE_PTYPE_ATTR_GTP_SESSION },
518 };
519
520 static const struct ice_ptype_attributes ice_attr_gtpu_eh[] = {
521         { ICE_MAC_IPV4_GTPU_IPV4_FRAG,    ICE_PTYPE_ATTR_GTP_PDU_EH },
522         { ICE_MAC_IPV4_GTPU_IPV4_PAY,     ICE_PTYPE_ATTR_GTP_PDU_EH },
523         { ICE_MAC_IPV4_GTPU_IPV4_UDP_PAY, ICE_PTYPE_ATTR_GTP_PDU_EH },
524         { ICE_MAC_IPV4_GTPU_IPV4_TCP,     ICE_PTYPE_ATTR_GTP_PDU_EH },
525         { ICE_MAC_IPV4_GTPU_IPV4_ICMP,    ICE_PTYPE_ATTR_GTP_PDU_EH },
526         { ICE_MAC_IPV6_GTPU_IPV4_FRAG,    ICE_PTYPE_ATTR_GTP_PDU_EH },
527         { ICE_MAC_IPV6_GTPU_IPV4_PAY,     ICE_PTYPE_ATTR_GTP_PDU_EH },
528         { ICE_MAC_IPV6_GTPU_IPV4_UDP_PAY, ICE_PTYPE_ATTR_GTP_PDU_EH },
529         { ICE_MAC_IPV6_GTPU_IPV4_TCP,     ICE_PTYPE_ATTR_GTP_PDU_EH },
530         { ICE_MAC_IPV6_GTPU_IPV4_ICMP,    ICE_PTYPE_ATTR_GTP_PDU_EH },
531         { ICE_MAC_IPV4_GTPU_IPV6_FRAG,    ICE_PTYPE_ATTR_GTP_PDU_EH },
532         { ICE_MAC_IPV4_GTPU_IPV6_PAY,     ICE_PTYPE_ATTR_GTP_PDU_EH },
533         { ICE_MAC_IPV4_GTPU_IPV6_UDP_PAY, ICE_PTYPE_ATTR_GTP_PDU_EH },
534         { ICE_MAC_IPV4_GTPU_IPV6_TCP,     ICE_PTYPE_ATTR_GTP_PDU_EH },
535         { ICE_MAC_IPV4_GTPU_IPV6_ICMPV6,  ICE_PTYPE_ATTR_GTP_PDU_EH },
536         { ICE_MAC_IPV6_GTPU_IPV6_FRAG,    ICE_PTYPE_ATTR_GTP_PDU_EH },
537         { ICE_MAC_IPV6_GTPU_IPV6_PAY,     ICE_PTYPE_ATTR_GTP_PDU_EH },
538         { ICE_MAC_IPV6_GTPU_IPV6_UDP_PAY, ICE_PTYPE_ATTR_GTP_PDU_EH },
539         { ICE_MAC_IPV6_GTPU_IPV6_TCP,     ICE_PTYPE_ATTR_GTP_PDU_EH },
540         { ICE_MAC_IPV6_GTPU_IPV6_ICMPV6,  ICE_PTYPE_ATTR_GTP_PDU_EH },
541 };
542
543 static const struct ice_ptype_attributes ice_attr_gtpu_down[] = {
544         { ICE_MAC_IPV4_GTPU_IPV4_FRAG,    ICE_PTYPE_ATTR_GTP_DOWNLINK },
545         { ICE_MAC_IPV4_GTPU_IPV4_PAY,     ICE_PTYPE_ATTR_GTP_DOWNLINK },
546         { ICE_MAC_IPV4_GTPU_IPV4_UDP_PAY, ICE_PTYPE_ATTR_GTP_DOWNLINK },
547         { ICE_MAC_IPV4_GTPU_IPV4_TCP,     ICE_PTYPE_ATTR_GTP_DOWNLINK },
548         { ICE_MAC_IPV4_GTPU_IPV4_ICMP,    ICE_PTYPE_ATTR_GTP_DOWNLINK },
549         { ICE_MAC_IPV6_GTPU_IPV4_FRAG,    ICE_PTYPE_ATTR_GTP_DOWNLINK },
550         { ICE_MAC_IPV6_GTPU_IPV4_PAY,     ICE_PTYPE_ATTR_GTP_DOWNLINK },
551         { ICE_MAC_IPV6_GTPU_IPV4_UDP_PAY, ICE_PTYPE_ATTR_GTP_DOWNLINK },
552         { ICE_MAC_IPV6_GTPU_IPV4_TCP,     ICE_PTYPE_ATTR_GTP_DOWNLINK },
553         { ICE_MAC_IPV6_GTPU_IPV4_ICMP,    ICE_PTYPE_ATTR_GTP_DOWNLINK },
554         { ICE_MAC_IPV4_GTPU_IPV6_FRAG,    ICE_PTYPE_ATTR_GTP_DOWNLINK },
555         { ICE_MAC_IPV4_GTPU_IPV6_PAY,     ICE_PTYPE_ATTR_GTP_DOWNLINK },
556         { ICE_MAC_IPV4_GTPU_IPV6_UDP_PAY, ICE_PTYPE_ATTR_GTP_DOWNLINK },
557         { ICE_MAC_IPV4_GTPU_IPV6_TCP,     ICE_PTYPE_ATTR_GTP_DOWNLINK },
558         { ICE_MAC_IPV4_GTPU_IPV6_ICMPV6,  ICE_PTYPE_ATTR_GTP_DOWNLINK },
559         { ICE_MAC_IPV6_GTPU_IPV6_FRAG,    ICE_PTYPE_ATTR_GTP_DOWNLINK },
560         { ICE_MAC_IPV6_GTPU_IPV6_PAY,     ICE_PTYPE_ATTR_GTP_DOWNLINK },
561         { ICE_MAC_IPV6_GTPU_IPV6_UDP_PAY, ICE_PTYPE_ATTR_GTP_DOWNLINK },
562         { ICE_MAC_IPV6_GTPU_IPV6_TCP,     ICE_PTYPE_ATTR_GTP_DOWNLINK },
563         { ICE_MAC_IPV6_GTPU_IPV6_ICMPV6,  ICE_PTYPE_ATTR_GTP_DOWNLINK },
564 };
565
566 static const struct ice_ptype_attributes ice_attr_gtpu_up[] = {
567         { ICE_MAC_IPV4_GTPU_IPV4_FRAG,    ICE_PTYPE_ATTR_GTP_UPLINK },
568         { ICE_MAC_IPV4_GTPU_IPV4_PAY,     ICE_PTYPE_ATTR_GTP_UPLINK },
569         { ICE_MAC_IPV4_GTPU_IPV4_UDP_PAY, ICE_PTYPE_ATTR_GTP_UPLINK },
570         { ICE_MAC_IPV4_GTPU_IPV4_TCP,     ICE_PTYPE_ATTR_GTP_UPLINK },
571         { ICE_MAC_IPV4_GTPU_IPV4_ICMP,    ICE_PTYPE_ATTR_GTP_UPLINK },
572         { ICE_MAC_IPV6_GTPU_IPV4_FRAG,    ICE_PTYPE_ATTR_GTP_UPLINK },
573         { ICE_MAC_IPV6_GTPU_IPV4_PAY,     ICE_PTYPE_ATTR_GTP_UPLINK },
574         { ICE_MAC_IPV6_GTPU_IPV4_UDP_PAY, ICE_PTYPE_ATTR_GTP_UPLINK },
575         { ICE_MAC_IPV6_GTPU_IPV4_TCP,     ICE_PTYPE_ATTR_GTP_UPLINK },
576         { ICE_MAC_IPV6_GTPU_IPV4_ICMP,    ICE_PTYPE_ATTR_GTP_UPLINK },
577         { ICE_MAC_IPV4_GTPU_IPV6_FRAG,    ICE_PTYPE_ATTR_GTP_UPLINK },
578         { ICE_MAC_IPV4_GTPU_IPV6_PAY,     ICE_PTYPE_ATTR_GTP_UPLINK },
579         { ICE_MAC_IPV4_GTPU_IPV6_UDP_PAY, ICE_PTYPE_ATTR_GTP_UPLINK },
580         { ICE_MAC_IPV4_GTPU_IPV6_TCP,     ICE_PTYPE_ATTR_GTP_UPLINK },
581         { ICE_MAC_IPV4_GTPU_IPV6_ICMPV6,  ICE_PTYPE_ATTR_GTP_UPLINK },
582         { ICE_MAC_IPV6_GTPU_IPV6_FRAG,    ICE_PTYPE_ATTR_GTP_UPLINK },
583         { ICE_MAC_IPV6_GTPU_IPV6_PAY,     ICE_PTYPE_ATTR_GTP_UPLINK },
584         { ICE_MAC_IPV6_GTPU_IPV6_UDP_PAY, ICE_PTYPE_ATTR_GTP_UPLINK },
585         { ICE_MAC_IPV6_GTPU_IPV6_TCP,     ICE_PTYPE_ATTR_GTP_UPLINK },
586         { ICE_MAC_IPV6_GTPU_IPV6_ICMPV6,  ICE_PTYPE_ATTR_GTP_UPLINK },
587 };
588
589 static const u32 ice_ptypes_gtpu[] = {
590         0x00000000, 0x00000000, 0x00000000, 0x00000000,
591         0x00000000, 0x00000000, 0x00000000, 0x00000000,
592         0x00000000, 0x00000000, 0x7FFFFE00, 0x00000000,
593         0x00000000, 0x00000000, 0x00000000, 0x00000000,
594         0x00000000, 0x00000000, 0x00000000, 0x00000000,
595         0x00000000, 0x00000000, 0x00000000, 0x00000000,
596         0x00000000, 0x00000000, 0x00000000, 0x00000000,
597         0x00000000, 0x00000000, 0x00000000, 0x00000000,
598 };
599
600 /* Packet types for pppoe */
601 static const u32 ice_ptypes_pppoe[] = {
602         0x00000000, 0x00000000, 0x00000000, 0x00000000,
603         0x00000000, 0x00000000, 0x00000000, 0x00000000,
604         0x00000000, 0x03ffe000, 0x00000000, 0x00000000,
605         0x00000000, 0x00000000, 0x00000000, 0x00000000,
606         0x00000000, 0x00000000, 0x00000000, 0x00000000,
607         0x00000000, 0x00000000, 0x00000000, 0x00000000,
608         0x00000000, 0x00000000, 0x00000000, 0x00000000,
609         0x00000000, 0x00000000, 0x00000000, 0x00000000,
610 };
611
612 /* Packet types for packets with PFCP NODE header */
613 static const u32 ice_ptypes_pfcp_node[] = {
614         0x00000000, 0x00000000, 0x00000000, 0x00000000,
615         0x00000000, 0x00000000, 0x00000000, 0x00000000,
616         0x00000000, 0x00000000, 0x80000000, 0x00000002,
617         0x00000000, 0x00000000, 0x00000000, 0x00000000,
618         0x00000000, 0x00000000, 0x00000000, 0x00000000,
619         0x00000000, 0x00000000, 0x00000000, 0x00000000,
620         0x00000000, 0x00000000, 0x00000000, 0x00000000,
621         0x00000000, 0x00000000, 0x00000000, 0x00000000,
622 };
623
624 /* Packet types for packets with PFCP SESSION header */
625 static const u32 ice_ptypes_pfcp_session[] = {
626         0x00000000, 0x00000000, 0x00000000, 0x00000000,
627         0x00000000, 0x00000000, 0x00000000, 0x00000000,
628         0x00000000, 0x00000000, 0x00000000, 0x00000005,
629         0x00000000, 0x00000000, 0x00000000, 0x00000000,
630         0x00000000, 0x00000000, 0x00000000, 0x00000000,
631         0x00000000, 0x00000000, 0x00000000, 0x00000000,
632         0x00000000, 0x00000000, 0x00000000, 0x00000000,
633         0x00000000, 0x00000000, 0x00000000, 0x00000000,
634 };
635
636 /* Packet types for l2tpv3 */
637 static const u32 ice_ptypes_l2tpv3[] = {
638         0x00000000, 0x00000000, 0x00000000, 0x00000000,
639         0x00000000, 0x00000000, 0x00000000, 0x00000000,
640         0x00000000, 0x00000000, 0x00000000, 0x00000300,
641         0x00000000, 0x00000000, 0x00000000, 0x00000000,
642         0x00000000, 0x00000000, 0x00000000, 0x00000000,
643         0x00000000, 0x00000000, 0x00000000, 0x00000000,
644         0x00000000, 0x00000000, 0x00000000, 0x00000000,
645         0x00000000, 0x00000000, 0x00000000, 0x00000000,
646 };
647
648 /* Packet types for esp */
649 static const u32 ice_ptypes_esp[] = {
650         0x00000000, 0x00000000, 0x00000000, 0x00000000,
651         0x00000000, 0x00000003, 0x00000000, 0x00000000,
652         0x00000000, 0x00000000, 0x00000000, 0x00000000,
653         0x00000000, 0x00000000, 0x00000000, 0x00000000,
654         0x00000000, 0x00000000, 0x00000000, 0x00000000,
655         0x00000000, 0x00000000, 0x00000000, 0x00000000,
656         0x00000000, 0x00000000, 0x00000000, 0x00000000,
657         0x00000000, 0x00000000, 0x00000000, 0x00000000,
658 };
659
660 /* Packet types for ah */
661 static const u32 ice_ptypes_ah[] = {
662         0x00000000, 0x00000000, 0x00000000, 0x00000000,
663         0x00000000, 0x0000000C, 0x00000000, 0x00000000,
664         0x00000000, 0x00000000, 0x00000000, 0x00000000,
665         0x00000000, 0x00000000, 0x00000000, 0x00000000,
666         0x00000000, 0x00000000, 0x00000000, 0x00000000,
667         0x00000000, 0x00000000, 0x00000000, 0x00000000,
668         0x00000000, 0x00000000, 0x00000000, 0x00000000,
669         0x00000000, 0x00000000, 0x00000000, 0x00000000,
670 };
671
672 /* Packet types for packets with NAT_T ESP header */
673 static const u32 ice_ptypes_nat_t_esp[] = {
674         0x00000000, 0x00000000, 0x00000000, 0x00000000,
675         0x00000000, 0x00000030, 0x00000000, 0x00000000,
676         0x00000000, 0x00000000, 0x00000000, 0x00000000,
677         0x00000000, 0x00000000, 0x00000000, 0x00000000,
678         0x00000000, 0x00000000, 0x00000000, 0x00000000,
679         0x00000000, 0x00000000, 0x00000000, 0x00000000,
680         0x00000000, 0x00000000, 0x00000000, 0x00000000,
681         0x00000000, 0x00000000, 0x00000000, 0x00000000,
682 };
683
684 static const u32 ice_ptypes_mac_non_ip_ofos[] = {
685         0x00000846, 0x00000000, 0x00000000, 0x00000000,
686         0x00000000, 0x00000000, 0x00000000, 0x00000000,
687         0x00400000, 0x03FFF000, 0x00000000, 0x00000000,
688         0x00000000, 0x00000000, 0x00000000, 0x00000000,
689         0x00000000, 0x00000000, 0x00000000, 0x00000000,
690         0x00000000, 0x00000000, 0x00000000, 0x00000000,
691         0x00000000, 0x00000000, 0x00000000, 0x00000000,
692         0x00000000, 0x00000000, 0x00000000, 0x00000000,
693 };
694
695 static const u32 ice_ptypes_gtpu_no_ip[] = {
696         0x00000000, 0x00000000, 0x00000000, 0x00000000,
697         0x00000000, 0x00000000, 0x00000000, 0x00000000,
698         0x00000000, 0x00000000, 0x00000600, 0x00000000,
699         0x00000000, 0x00000000, 0x00000000, 0x00000000,
700         0x00000000, 0x00000000, 0x00000000, 0x00000000,
701         0x00000000, 0x00000000, 0x00000000, 0x00000000,
702         0x00000000, 0x00000000, 0x00000000, 0x00000000,
703         0x00000000, 0x00000000, 0x00000000, 0x00000000,
704 };
705
706 static const u32 ice_ptypes_ecpri_tp0[] = {
707         0x00000000, 0x00000000, 0x00000000, 0x00000000,
708         0x00000000, 0x00000000, 0x00000000, 0x00000000,
709         0x00000000, 0x00000000, 0x00000000, 0x00000400,
710         0x00000000, 0x00000000, 0x00000000, 0x00000000,
711         0x00000000, 0x00000000, 0x00000000, 0x00000000,
712         0x00000000, 0x00000000, 0x00000000, 0x00000000,
713         0x00000000, 0x00000000, 0x00000000, 0x00000000,
714         0x00000000, 0x00000000, 0x00000000, 0x00000000,
715 };
716
717 static const u32 ice_ptypes_udp_ecpri_tp0[] = {
718         0x00000000, 0x00000000, 0x00000000, 0x00000000,
719         0x00000000, 0x00000000, 0x00000000, 0x00000000,
720         0x00000000, 0x00000000, 0x00000000, 0x00100000,
721         0x00000000, 0x00000000, 0x00000000, 0x00000000,
722         0x00000000, 0x00000000, 0x00000000, 0x00000000,
723         0x00000000, 0x00000000, 0x00000000, 0x00000000,
724         0x00000000, 0x00000000, 0x00000000, 0x00000000,
725         0x00000000, 0x00000000, 0x00000000, 0x00000000,
726 };
727
728 /* Manage parameters and info. used during the creation of a flow profile */
729 struct ice_flow_prof_params {
730         enum ice_block blk;
731         u16 entry_length; /* # of bytes formatted entry will require */
732         u8 es_cnt;
733         struct ice_flow_prof *prof;
734
735         /* For ACL, the es[0] will have the data of ICE_RX_MDID_PKT_FLAGS_15_0
736          * This will give us the direction flags.
737          */
738         struct ice_fv_word es[ICE_MAX_FV_WORDS];
739         /* attributes can be used to add attributes to a particular PTYPE */
740         const struct ice_ptype_attributes *attr;
741         u16 attr_cnt;
742
743         u16 mask[ICE_MAX_FV_WORDS];
744         ice_declare_bitmap(ptypes, ICE_FLOW_PTYPE_MAX);
745 };
746
747 #define ICE_FLOW_RSS_HDRS_INNER_MASK \
748         (ICE_FLOW_SEG_HDR_PPPOE | ICE_FLOW_SEG_HDR_GTPC | \
749         ICE_FLOW_SEG_HDR_GTPC_TEID | ICE_FLOW_SEG_HDR_GTPU | \
750         ICE_FLOW_SEG_HDR_PFCP_SESSION | ICE_FLOW_SEG_HDR_L2TPV3 | \
751         ICE_FLOW_SEG_HDR_ESP | ICE_FLOW_SEG_HDR_AH | \
752         ICE_FLOW_SEG_HDR_NAT_T_ESP | ICE_FLOW_SEG_HDR_GTPU_NON_IP | \
753         ICE_FLOW_SEG_HDR_ECPRI_TP0 | ICE_FLOW_SEG_HDR_UDP_ECPRI_TP0)
754
755 #define ICE_FLOW_SEG_HDRS_L2_MASK       \
756         (ICE_FLOW_SEG_HDR_ETH | ICE_FLOW_SEG_HDR_VLAN)
757 #define ICE_FLOW_SEG_HDRS_L3_MASK       \
758         (ICE_FLOW_SEG_HDR_IPV4 | ICE_FLOW_SEG_HDR_IPV6 | \
759          ICE_FLOW_SEG_HDR_ARP)
760 #define ICE_FLOW_SEG_HDRS_L4_MASK       \
761         (ICE_FLOW_SEG_HDR_ICMP | ICE_FLOW_SEG_HDR_TCP | ICE_FLOW_SEG_HDR_UDP | \
762          ICE_FLOW_SEG_HDR_SCTP)
763 /* mask for L4 protocols that are NOT part of IPV4/6 OTHER PTYPE groups */
764 #define ICE_FLOW_SEG_HDRS_L4_MASK_NO_OTHER      \
765         (ICE_FLOW_SEG_HDR_TCP | ICE_FLOW_SEG_HDR_UDP | ICE_FLOW_SEG_HDR_SCTP)
766
767 /**
768  * ice_flow_val_hdrs - validates packet segments for valid protocol headers
769  * @segs: array of one or more packet segments that describe the flow
770  * @segs_cnt: number of packet segments provided
771  */
772 static enum ice_status
773 ice_flow_val_hdrs(struct ice_flow_seg_info *segs, u8 segs_cnt)
774 {
775         u8 i;
776
777         for (i = 0; i < segs_cnt; i++) {
778                 /* Multiple L3 headers */
779                 if (segs[i].hdrs & ICE_FLOW_SEG_HDRS_L3_MASK &&
780                     !ice_is_pow2(segs[i].hdrs & ICE_FLOW_SEG_HDRS_L3_MASK))
781                         return ICE_ERR_PARAM;
782
783                 /* Multiple L4 headers */
784                 if (segs[i].hdrs & ICE_FLOW_SEG_HDRS_L4_MASK &&
785                     !ice_is_pow2(segs[i].hdrs & ICE_FLOW_SEG_HDRS_L4_MASK))
786                         return ICE_ERR_PARAM;
787         }
788
789         return ICE_SUCCESS;
790 }
791
792 /* Sizes of fixed known protocol headers without header options */
793 #define ICE_FLOW_PROT_HDR_SZ_MAC        14
794 #define ICE_FLOW_PROT_HDR_SZ_MAC_VLAN   (ICE_FLOW_PROT_HDR_SZ_MAC + 2)
795 #define ICE_FLOW_PROT_HDR_SZ_IPV4       20
796 #define ICE_FLOW_PROT_HDR_SZ_IPV6       40
797 #define ICE_FLOW_PROT_HDR_SZ_ARP        28
798 #define ICE_FLOW_PROT_HDR_SZ_ICMP       8
799 #define ICE_FLOW_PROT_HDR_SZ_TCP        20
800 #define ICE_FLOW_PROT_HDR_SZ_UDP        8
801 #define ICE_FLOW_PROT_HDR_SZ_SCTP       12
802
803 /**
804  * ice_flow_calc_seg_sz - calculates size of a packet segment based on headers
805  * @params: information about the flow to be processed
806  * @seg: index of packet segment whose header size is to be determined
807  */
808 static u16 ice_flow_calc_seg_sz(struct ice_flow_prof_params *params, u8 seg)
809 {
810         u16 sz;
811
812         /* L2 headers */
813         sz = (params->prof->segs[seg].hdrs & ICE_FLOW_SEG_HDR_VLAN) ?
814                 ICE_FLOW_PROT_HDR_SZ_MAC_VLAN : ICE_FLOW_PROT_HDR_SZ_MAC;
815
816         /* L3 headers */
817         if (params->prof->segs[seg].hdrs & ICE_FLOW_SEG_HDR_IPV4)
818                 sz += ICE_FLOW_PROT_HDR_SZ_IPV4;
819         else if (params->prof->segs[seg].hdrs & ICE_FLOW_SEG_HDR_IPV6)
820                 sz += ICE_FLOW_PROT_HDR_SZ_IPV6;
821         else if (params->prof->segs[seg].hdrs & ICE_FLOW_SEG_HDR_ARP)
822                 sz += ICE_FLOW_PROT_HDR_SZ_ARP;
823         else if (params->prof->segs[seg].hdrs & ICE_FLOW_SEG_HDRS_L4_MASK)
824                 /* A L3 header is required if L4 is specified */
825                 return 0;
826
827         /* L4 headers */
828         if (params->prof->segs[seg].hdrs & ICE_FLOW_SEG_HDR_ICMP)
829                 sz += ICE_FLOW_PROT_HDR_SZ_ICMP;
830         else if (params->prof->segs[seg].hdrs & ICE_FLOW_SEG_HDR_TCP)
831                 sz += ICE_FLOW_PROT_HDR_SZ_TCP;
832         else if (params->prof->segs[seg].hdrs & ICE_FLOW_SEG_HDR_UDP)
833                 sz += ICE_FLOW_PROT_HDR_SZ_UDP;
834         else if (params->prof->segs[seg].hdrs & ICE_FLOW_SEG_HDR_SCTP)
835                 sz += ICE_FLOW_PROT_HDR_SZ_SCTP;
836
837         return sz;
838 }
839
840 /**
841  * ice_flow_proc_seg_hdrs - process protocol headers present in pkt segments
842  * @params: information about the flow to be processed
843  *
844  * This function identifies the packet types associated with the protocol
845  * headers being present in packet segments of the specified flow profile.
846  */
847 static enum ice_status
848 ice_flow_proc_seg_hdrs(struct ice_flow_prof_params *params)
849 {
850         struct ice_flow_prof *prof;
851         u8 i;
852
853         ice_memset(params->ptypes, 0xff, sizeof(params->ptypes),
854                    ICE_NONDMA_MEM);
855
856         prof = params->prof;
857
858         for (i = 0; i < params->prof->segs_cnt; i++) {
859                 const ice_bitmap_t *src;
860                 u32 hdrs;
861
862                 hdrs = prof->segs[i].hdrs;
863
864                 if (hdrs & ICE_FLOW_SEG_HDR_ETH) {
865                         src = !i ? (const ice_bitmap_t *)ice_ptypes_mac_ofos :
866                                 (const ice_bitmap_t *)ice_ptypes_mac_il;
867                         ice_and_bitmap(params->ptypes, params->ptypes, src,
868                                        ICE_FLOW_PTYPE_MAX);
869                 }
870
871                 if (i && hdrs & ICE_FLOW_SEG_HDR_VLAN) {
872                         src = (const ice_bitmap_t *)ice_ptypes_macvlan_il;
873                         ice_and_bitmap(params->ptypes, params->ptypes, src,
874                                        ICE_FLOW_PTYPE_MAX);
875                 }
876
877                 if (!i && hdrs & ICE_FLOW_SEG_HDR_ARP) {
878                         ice_and_bitmap(params->ptypes, params->ptypes,
879                                        (const ice_bitmap_t *)ice_ptypes_arp_of,
880                                        ICE_FLOW_PTYPE_MAX);
881                 }
882
883                 if (hdrs & ICE_FLOW_SEG_HDR_ECPRI_TP0) {
884                         src = (const ice_bitmap_t *)ice_ptypes_ecpri_tp0;
885                         ice_and_bitmap(params->ptypes, params->ptypes, src,
886                                        ICE_FLOW_PTYPE_MAX);
887                 }
888                 if ((hdrs & ICE_FLOW_SEG_HDR_IPV4) &&
889                     (hdrs & ICE_FLOW_SEG_HDR_IPV_OTHER)) {
890                         src = i ?
891                                 (const ice_bitmap_t *)ice_ptypes_ipv4_il :
892                                 (const ice_bitmap_t *)ice_ptypes_ipv4_ofos_all;
893                         ice_and_bitmap(params->ptypes, params->ptypes, src,
894                                        ICE_FLOW_PTYPE_MAX);
895                 } else if ((hdrs & ICE_FLOW_SEG_HDR_IPV6) &&
896                            (hdrs & ICE_FLOW_SEG_HDR_IPV_OTHER)) {
897                         src = i ?
898                                 (const ice_bitmap_t *)ice_ptypes_ipv6_il :
899                                 (const ice_bitmap_t *)ice_ptypes_ipv6_ofos_all;
900                         ice_and_bitmap(params->ptypes, params->ptypes, src,
901                                        ICE_FLOW_PTYPE_MAX);
902                 } else if ((hdrs & ICE_FLOW_SEG_HDR_IPV4) &&
903                            !(hdrs & ICE_FLOW_SEG_HDRS_L4_MASK_NO_OTHER)) {
904                         src = !i ? (const ice_bitmap_t *)ice_ptypes_ipv4_ofos_no_l4 :
905                                 (const ice_bitmap_t *)ice_ptypes_ipv4_il_no_l4;
906                         ice_and_bitmap(params->ptypes, params->ptypes, src,
907                                        ICE_FLOW_PTYPE_MAX);
908                 } else if (hdrs & ICE_FLOW_SEG_HDR_IPV4) {
909                         src = !i ? (const ice_bitmap_t *)ice_ptypes_ipv4_ofos :
910                                 (const ice_bitmap_t *)ice_ptypes_ipv4_il;
911                         ice_and_bitmap(params->ptypes, params->ptypes, src,
912                                        ICE_FLOW_PTYPE_MAX);
913                 } else if ((hdrs & ICE_FLOW_SEG_HDR_IPV6) &&
914                            !(hdrs & ICE_FLOW_SEG_HDRS_L4_MASK_NO_OTHER)) {
915                         src = !i ? (const ice_bitmap_t *)ice_ptypes_ipv6_ofos_no_l4 :
916                                 (const ice_bitmap_t *)ice_ptypes_ipv6_il_no_l4;
917                         ice_and_bitmap(params->ptypes, params->ptypes, src,
918                                        ICE_FLOW_PTYPE_MAX);
919                 } else if (hdrs & ICE_FLOW_SEG_HDR_IPV6) {
920                         src = !i ? (const ice_bitmap_t *)ice_ptypes_ipv6_ofos :
921                                 (const ice_bitmap_t *)ice_ptypes_ipv6_il;
922                         ice_and_bitmap(params->ptypes, params->ptypes, src,
923                                        ICE_FLOW_PTYPE_MAX);
924                 }
925
926                 if (hdrs & ICE_FLOW_SEG_HDR_ETH_NON_IP) {
927                         src = (const ice_bitmap_t *)ice_ptypes_mac_non_ip_ofos;
928                         ice_and_bitmap(params->ptypes, params->ptypes,
929                                        src, ICE_FLOW_PTYPE_MAX);
930                 } else if (hdrs & ICE_FLOW_SEG_HDR_PPPOE) {
931                         src = (const ice_bitmap_t *)ice_ptypes_pppoe;
932                         ice_and_bitmap(params->ptypes, params->ptypes, src,
933                                        ICE_FLOW_PTYPE_MAX);
934                 } else {
935                         src = (const ice_bitmap_t *)ice_ptypes_pppoe;
936                         ice_andnot_bitmap(params->ptypes, params->ptypes, src,
937                                           ICE_FLOW_PTYPE_MAX);
938                 }
939
940                 if (hdrs & ICE_FLOW_SEG_HDR_UDP) {
941                         src = (const ice_bitmap_t *)ice_ptypes_udp_il;
942                         ice_and_bitmap(params->ptypes, params->ptypes, src,
943                                        ICE_FLOW_PTYPE_MAX);
944                 } else if (hdrs & ICE_FLOW_SEG_HDR_TCP) {
945                         ice_and_bitmap(params->ptypes, params->ptypes,
946                                        (const ice_bitmap_t *)ice_ptypes_tcp_il,
947                                        ICE_FLOW_PTYPE_MAX);
948                 } else if (hdrs & ICE_FLOW_SEG_HDR_SCTP) {
949                         src = (const ice_bitmap_t *)ice_ptypes_sctp_il;
950                         ice_and_bitmap(params->ptypes, params->ptypes, src,
951                                        ICE_FLOW_PTYPE_MAX);
952                 }
953
954                 if (hdrs & ICE_FLOW_SEG_HDR_ICMP) {
955                         src = !i ? (const ice_bitmap_t *)ice_ptypes_icmp_of :
956                                 (const ice_bitmap_t *)ice_ptypes_icmp_il;
957                         ice_and_bitmap(params->ptypes, params->ptypes, src,
958                                        ICE_FLOW_PTYPE_MAX);
959                 } else if (hdrs & ICE_FLOW_SEG_HDR_GRE) {
960                         if (!i) {
961                                 src = (const ice_bitmap_t *)ice_ptypes_gre_of;
962                                 ice_and_bitmap(params->ptypes, params->ptypes,
963                                                src, ICE_FLOW_PTYPE_MAX);
964                         }
965                 } else if (hdrs & ICE_FLOW_SEG_HDR_GTPC) {
966                         src = (const ice_bitmap_t *)ice_ptypes_gtpc;
967                         ice_and_bitmap(params->ptypes, params->ptypes,
968                                        src, ICE_FLOW_PTYPE_MAX);
969                 } else if (hdrs & ICE_FLOW_SEG_HDR_GTPC_TEID) {
970                         src = (const ice_bitmap_t *)ice_ptypes_gtpc_tid;
971                         ice_and_bitmap(params->ptypes, params->ptypes,
972                                        src, ICE_FLOW_PTYPE_MAX);
973                 } else if (hdrs & ICE_FLOW_SEG_HDR_GTPU_NON_IP) {
974                         src = (const ice_bitmap_t *)ice_ptypes_gtpu_no_ip;
975                         ice_and_bitmap(params->ptypes, params->ptypes,
976                                        src, ICE_FLOW_PTYPE_MAX);
977                 } else if (hdrs & ICE_FLOW_SEG_HDR_GTPU_DWN) {
978                         src = (const ice_bitmap_t *)ice_ptypes_gtpu;
979                         ice_and_bitmap(params->ptypes, params->ptypes,
980                                        src, ICE_FLOW_PTYPE_MAX);
981
982                         /* Attributes for GTP packet with downlink */
983                         params->attr = ice_attr_gtpu_down;
984                         params->attr_cnt = ARRAY_SIZE(ice_attr_gtpu_down);
985                 } else if (hdrs & ICE_FLOW_SEG_HDR_GTPU_UP) {
986                         src = (const ice_bitmap_t *)ice_ptypes_gtpu;
987                         ice_and_bitmap(params->ptypes, params->ptypes,
988                                        src, ICE_FLOW_PTYPE_MAX);
989
990                         /* Attributes for GTP packet with uplink */
991                         params->attr = ice_attr_gtpu_up;
992                         params->attr_cnt = ARRAY_SIZE(ice_attr_gtpu_up);
993                 } else if (hdrs & ICE_FLOW_SEG_HDR_GTPU_EH) {
994                         src = (const ice_bitmap_t *)ice_ptypes_gtpu;
995                         ice_and_bitmap(params->ptypes, params->ptypes,
996                                        src, ICE_FLOW_PTYPE_MAX);
997
998                         /* Attributes for GTP packet with Extension Header */
999                         params->attr = ice_attr_gtpu_eh;
1000                         params->attr_cnt = ARRAY_SIZE(ice_attr_gtpu_eh);
1001                 } else if (hdrs & ICE_FLOW_SEG_HDR_GTPU_IP) {
1002                         src = (const ice_bitmap_t *)ice_ptypes_gtpu;
1003                         ice_and_bitmap(params->ptypes, params->ptypes,
1004                                        src, ICE_FLOW_PTYPE_MAX);
1005
1006                         /* Attributes for GTP packet without Extension Header */
1007                         params->attr = ice_attr_gtpu_session;
1008                         params->attr_cnt = ARRAY_SIZE(ice_attr_gtpu_session);
1009                 } else if (hdrs & ICE_FLOW_SEG_HDR_L2TPV3) {
1010                         src = (const ice_bitmap_t *)ice_ptypes_l2tpv3;
1011                         ice_and_bitmap(params->ptypes, params->ptypes,
1012                                        src, ICE_FLOW_PTYPE_MAX);
1013                 } else if (hdrs & ICE_FLOW_SEG_HDR_ESP) {
1014                         src = (const ice_bitmap_t *)ice_ptypes_esp;
1015                         ice_and_bitmap(params->ptypes, params->ptypes,
1016                                        src, ICE_FLOW_PTYPE_MAX);
1017                 } else if (hdrs & ICE_FLOW_SEG_HDR_AH) {
1018                         src = (const ice_bitmap_t *)ice_ptypes_ah;
1019                         ice_and_bitmap(params->ptypes, params->ptypes,
1020                                        src, ICE_FLOW_PTYPE_MAX);
1021                 } else if (hdrs & ICE_FLOW_SEG_HDR_NAT_T_ESP) {
1022                         src = (const ice_bitmap_t *)ice_ptypes_nat_t_esp;
1023                         ice_and_bitmap(params->ptypes, params->ptypes,
1024                                        src, ICE_FLOW_PTYPE_MAX);
1025                 } else if (hdrs & ICE_FLOW_SEG_HDR_VXLAN) {
1026                         src = (const ice_bitmap_t *)ice_ptypes_vxlan_vni;
1027                         ice_and_bitmap(params->ptypes, params->ptypes,
1028                                        src, ICE_FLOW_PTYPE_MAX);
1029                 } else if (hdrs & ICE_FLOW_SEG_HDR_UDP_ECPRI_TP0) {
1030                         src = (const ice_bitmap_t *)ice_ptypes_udp_ecpri_tp0;
1031                         ice_and_bitmap(params->ptypes, params->ptypes,
1032                                        src, ICE_FLOW_PTYPE_MAX);
1033                 }
1034
1035                 if (hdrs & ICE_FLOW_SEG_HDR_PFCP) {
1036                         if (hdrs & ICE_FLOW_SEG_HDR_PFCP_NODE)
1037                                 src =
1038                                 (const ice_bitmap_t *)ice_ptypes_pfcp_node;
1039                         else
1040                                 src =
1041                                 (const ice_bitmap_t *)ice_ptypes_pfcp_session;
1042
1043                         ice_and_bitmap(params->ptypes, params->ptypes,
1044                                        src, ICE_FLOW_PTYPE_MAX);
1045                 } else {
1046                         src = (const ice_bitmap_t *)ice_ptypes_pfcp_node;
1047                         ice_andnot_bitmap(params->ptypes, params->ptypes,
1048                                           src, ICE_FLOW_PTYPE_MAX);
1049
1050                         src = (const ice_bitmap_t *)ice_ptypes_pfcp_session;
1051                         ice_andnot_bitmap(params->ptypes, params->ptypes,
1052                                           src, ICE_FLOW_PTYPE_MAX);
1053                 }
1054         }
1055
1056         return ICE_SUCCESS;
1057 }
1058
1059 /**
1060  * ice_flow_xtract_pkt_flags - Create an extr sequence entry for packet flags
1061  * @hw: pointer to the HW struct
1062  * @params: information about the flow to be processed
1063  * @flags: The value of pkt_flags[x:x] in Rx/Tx MDID metadata.
1064  *
1065  * This function will allocate an extraction sequence entries for a DWORD size
1066  * chunk of the packet flags.
1067  */
1068 static enum ice_status
1069 ice_flow_xtract_pkt_flags(struct ice_hw *hw,
1070                           struct ice_flow_prof_params *params,
1071                           enum ice_flex_mdid_pkt_flags flags)
1072 {
1073         u8 fv_words = hw->blk[params->blk].es.fvw;
1074         u8 idx;
1075
1076         /* Make sure the number of extraction sequence entries required does not
1077          * exceed the block's capacity.
1078          */
1079         if (params->es_cnt >= fv_words)
1080                 return ICE_ERR_MAX_LIMIT;
1081
1082         /* some blocks require a reversed field vector layout */
1083         if (hw->blk[params->blk].es.reverse)
1084                 idx = fv_words - params->es_cnt - 1;
1085         else
1086                 idx = params->es_cnt;
1087
1088         params->es[idx].prot_id = ICE_PROT_META_ID;
1089         params->es[idx].off = flags;
1090         params->es_cnt++;
1091
1092         return ICE_SUCCESS;
1093 }
1094
1095 /**
1096  * ice_flow_xtract_fld - Create an extraction sequence entry for the given field
1097  * @hw: pointer to the HW struct
1098  * @params: information about the flow to be processed
1099  * @seg: packet segment index of the field to be extracted
1100  * @fld: ID of field to be extracted
1101  * @match: bitfield of all fields
1102  *
1103  * This function determines the protocol ID, offset, and size of the given
1104  * field. It then allocates one or more extraction sequence entries for the
1105  * given field, and fill the entries with protocol ID and offset information.
1106  */
1107 static enum ice_status
1108 ice_flow_xtract_fld(struct ice_hw *hw, struct ice_flow_prof_params *params,
1109                     u8 seg, enum ice_flow_field fld, u64 match)
1110 {
1111         enum ice_flow_field sib = ICE_FLOW_FIELD_IDX_MAX;
1112         enum ice_prot_id prot_id = ICE_PROT_ID_INVAL;
1113         u8 fv_words = hw->blk[params->blk].es.fvw;
1114         struct ice_flow_fld_info *flds;
1115         u16 cnt, ese_bits, i;
1116         u16 sib_mask = 0;
1117         u16 mask;
1118         u16 off;
1119
1120         flds = params->prof->segs[seg].fields;
1121
1122         switch (fld) {
1123         case ICE_FLOW_FIELD_IDX_ETH_DA:
1124         case ICE_FLOW_FIELD_IDX_ETH_SA:
1125         case ICE_FLOW_FIELD_IDX_S_VLAN:
1126         case ICE_FLOW_FIELD_IDX_C_VLAN:
1127                 prot_id = seg == 0 ? ICE_PROT_MAC_OF_OR_S : ICE_PROT_MAC_IL;
1128                 break;
1129         case ICE_FLOW_FIELD_IDX_ETH_TYPE:
1130                 prot_id = seg == 0 ? ICE_PROT_ETYPE_OL : ICE_PROT_ETYPE_IL;
1131                 break;
1132         case ICE_FLOW_FIELD_IDX_IPV4_DSCP:
1133                 prot_id = seg == 0 ? ICE_PROT_IPV4_OF_OR_S : ICE_PROT_IPV4_IL;
1134                 break;
1135         case ICE_FLOW_FIELD_IDX_IPV6_DSCP:
1136                 prot_id = seg == 0 ? ICE_PROT_IPV6_OF_OR_S : ICE_PROT_IPV6_IL;
1137                 break;
1138         case ICE_FLOW_FIELD_IDX_IPV4_TTL:
1139         case ICE_FLOW_FIELD_IDX_IPV4_PROT:
1140                 prot_id = seg == 0 ? ICE_PROT_IPV4_OF_OR_S : ICE_PROT_IPV4_IL;
1141
1142                 /* TTL and PROT share the same extraction seq. entry.
1143                  * Each is considered a sibling to the other in terms of sharing
1144                  * the same extraction sequence entry.
1145                  */
1146                 if (fld == ICE_FLOW_FIELD_IDX_IPV4_TTL)
1147                         sib = ICE_FLOW_FIELD_IDX_IPV4_PROT;
1148                 else
1149                         sib = ICE_FLOW_FIELD_IDX_IPV4_TTL;
1150
1151                 /* If the sibling field is also included, that field's
1152                  * mask needs to be included.
1153                  */
1154                 if (match & BIT(sib))
1155                         sib_mask = ice_flds_info[sib].mask;
1156                 break;
1157         case ICE_FLOW_FIELD_IDX_IPV6_TTL:
1158         case ICE_FLOW_FIELD_IDX_IPV6_PROT:
1159                 prot_id = seg == 0 ? ICE_PROT_IPV6_OF_OR_S : ICE_PROT_IPV6_IL;
1160
1161                 /* TTL and PROT share the same extraction seq. entry.
1162                  * Each is considered a sibling to the other in terms of sharing
1163                  * the same extraction sequence entry.
1164                  */
1165                 if (fld == ICE_FLOW_FIELD_IDX_IPV6_TTL)
1166                         sib = ICE_FLOW_FIELD_IDX_IPV6_PROT;
1167                 else
1168                         sib = ICE_FLOW_FIELD_IDX_IPV6_TTL;
1169
1170                 /* If the sibling field is also included, that field's
1171                  * mask needs to be included.
1172                  */
1173                 if (match & BIT(sib))
1174                         sib_mask = ice_flds_info[sib].mask;
1175                 break;
1176         case ICE_FLOW_FIELD_IDX_IPV4_SA:
1177         case ICE_FLOW_FIELD_IDX_IPV4_DA:
1178                 prot_id = seg == 0 ? ICE_PROT_IPV4_OF_OR_S : ICE_PROT_IPV4_IL;
1179                 break;
1180         case ICE_FLOW_FIELD_IDX_IPV6_SA:
1181         case ICE_FLOW_FIELD_IDX_IPV6_DA:
1182         case ICE_FLOW_FIELD_IDX_IPV6_PRE32_SA:
1183         case ICE_FLOW_FIELD_IDX_IPV6_PRE32_DA:
1184         case ICE_FLOW_FIELD_IDX_IPV6_PRE48_SA:
1185         case ICE_FLOW_FIELD_IDX_IPV6_PRE48_DA:
1186         case ICE_FLOW_FIELD_IDX_IPV6_PRE64_SA:
1187         case ICE_FLOW_FIELD_IDX_IPV6_PRE64_DA:
1188                 prot_id = seg == 0 ? ICE_PROT_IPV6_OF_OR_S : ICE_PROT_IPV6_IL;
1189                 break;
1190         case ICE_FLOW_FIELD_IDX_TCP_SRC_PORT:
1191         case ICE_FLOW_FIELD_IDX_TCP_DST_PORT:
1192         case ICE_FLOW_FIELD_IDX_TCP_FLAGS:
1193                 prot_id = ICE_PROT_TCP_IL;
1194                 break;
1195         case ICE_FLOW_FIELD_IDX_UDP_SRC_PORT:
1196         case ICE_FLOW_FIELD_IDX_UDP_DST_PORT:
1197                 prot_id = ICE_PROT_UDP_IL_OR_S;
1198                 break;
1199         case ICE_FLOW_FIELD_IDX_SCTP_SRC_PORT:
1200         case ICE_FLOW_FIELD_IDX_SCTP_DST_PORT:
1201                 prot_id = ICE_PROT_SCTP_IL;
1202                 break;
1203         case ICE_FLOW_FIELD_IDX_VXLAN_VNI:
1204         case ICE_FLOW_FIELD_IDX_GTPC_TEID:
1205         case ICE_FLOW_FIELD_IDX_GTPU_IP_TEID:
1206         case ICE_FLOW_FIELD_IDX_GTPU_UP_TEID:
1207         case ICE_FLOW_FIELD_IDX_GTPU_DWN_TEID:
1208         case ICE_FLOW_FIELD_IDX_GTPU_EH_TEID:
1209         case ICE_FLOW_FIELD_IDX_GTPU_EH_QFI:
1210                 /* GTP is accessed through UDP OF protocol */
1211                 prot_id = ICE_PROT_UDP_OF;
1212                 break;
1213         case ICE_FLOW_FIELD_IDX_PPPOE_SESS_ID:
1214                 prot_id = ICE_PROT_PPPOE;
1215                 break;
1216         case ICE_FLOW_FIELD_IDX_PFCP_SEID:
1217                 prot_id = ICE_PROT_UDP_IL_OR_S;
1218                 break;
1219         case ICE_FLOW_FIELD_IDX_L2TPV3_SESS_ID:
1220                 prot_id = ICE_PROT_L2TPV3;
1221                 break;
1222         case ICE_FLOW_FIELD_IDX_ESP_SPI:
1223                 prot_id = ICE_PROT_ESP_F;
1224                 break;
1225         case ICE_FLOW_FIELD_IDX_AH_SPI:
1226                 prot_id = ICE_PROT_ESP_2;
1227                 break;
1228         case ICE_FLOW_FIELD_IDX_NAT_T_ESP_SPI:
1229                 prot_id = ICE_PROT_UDP_IL_OR_S;
1230                 break;
1231         case ICE_FLOW_FIELD_IDX_ECPRI_TP0_PC_ID:
1232                 prot_id = ICE_PROT_ECPRI;
1233                 break;
1234         case ICE_FLOW_FIELD_IDX_UDP_ECPRI_TP0_PC_ID:
1235                 prot_id = ICE_PROT_UDP_IL_OR_S;
1236                 break;
1237         case ICE_FLOW_FIELD_IDX_ARP_SIP:
1238         case ICE_FLOW_FIELD_IDX_ARP_DIP:
1239         case ICE_FLOW_FIELD_IDX_ARP_SHA:
1240         case ICE_FLOW_FIELD_IDX_ARP_DHA:
1241         case ICE_FLOW_FIELD_IDX_ARP_OP:
1242                 prot_id = ICE_PROT_ARP_OF;
1243                 break;
1244         case ICE_FLOW_FIELD_IDX_ICMP_TYPE:
1245         case ICE_FLOW_FIELD_IDX_ICMP_CODE:
1246                 /* ICMP type and code share the same extraction seq. entry */
1247                 prot_id = (params->prof->segs[seg].hdrs &
1248                            ICE_FLOW_SEG_HDR_IPV4) ?
1249                         ICE_PROT_ICMP_IL : ICE_PROT_ICMPV6_IL;
1250                 sib = fld == ICE_FLOW_FIELD_IDX_ICMP_TYPE ?
1251                         ICE_FLOW_FIELD_IDX_ICMP_CODE :
1252                         ICE_FLOW_FIELD_IDX_ICMP_TYPE;
1253                 break;
1254         case ICE_FLOW_FIELD_IDX_GRE_KEYID:
1255                 prot_id = ICE_PROT_GRE_OF;
1256                 break;
1257         default:
1258                 return ICE_ERR_NOT_IMPL;
1259         }
1260
1261         /* Each extraction sequence entry is a word in size, and extracts a
1262          * word-aligned offset from a protocol header.
1263          */
1264         ese_bits = ICE_FLOW_FV_EXTRACT_SZ * BITS_PER_BYTE;
1265
1266         flds[fld].xtrct.prot_id = prot_id;
1267         flds[fld].xtrct.off = (ice_flds_info[fld].off / ese_bits) *
1268                 ICE_FLOW_FV_EXTRACT_SZ;
1269         flds[fld].xtrct.disp = (u8)(ice_flds_info[fld].off % ese_bits);
1270         flds[fld].xtrct.idx = params->es_cnt;
1271         flds[fld].xtrct.mask = ice_flds_info[fld].mask;
1272
1273         /* Adjust the next field-entry index after accommodating the number of
1274          * entries this field consumes
1275          */
1276         cnt = DIVIDE_AND_ROUND_UP(flds[fld].xtrct.disp +
1277                                   ice_flds_info[fld].size, ese_bits);
1278
1279         /* Fill in the extraction sequence entries needed for this field */
1280         off = flds[fld].xtrct.off;
1281         mask = flds[fld].xtrct.mask;
1282         for (i = 0; i < cnt; i++) {
1283                 /* Only consume an extraction sequence entry if there is no
1284                  * sibling field associated with this field or the sibling entry
1285                  * already extracts the word shared with this field.
1286                  */
1287                 if (sib == ICE_FLOW_FIELD_IDX_MAX ||
1288                     flds[sib].xtrct.prot_id == ICE_PROT_ID_INVAL ||
1289                     flds[sib].xtrct.off != off) {
1290                         u8 idx;
1291
1292                         /* Make sure the number of extraction sequence required
1293                          * does not exceed the block's capability
1294                          */
1295                         if (params->es_cnt >= fv_words)
1296                                 return ICE_ERR_MAX_LIMIT;
1297
1298                         /* some blocks require a reversed field vector layout */
1299                         if (hw->blk[params->blk].es.reverse)
1300                                 idx = fv_words - params->es_cnt - 1;
1301                         else
1302                                 idx = params->es_cnt;
1303
1304                         params->es[idx].prot_id = prot_id;
1305                         params->es[idx].off = off;
1306                         params->mask[idx] = mask | sib_mask;
1307                         params->es_cnt++;
1308                 }
1309
1310                 off += ICE_FLOW_FV_EXTRACT_SZ;
1311         }
1312
1313         return ICE_SUCCESS;
1314 }
1315
1316 /**
1317  * ice_flow_xtract_raws - Create extract sequence entries for raw bytes
1318  * @hw: pointer to the HW struct
1319  * @params: information about the flow to be processed
1320  * @seg: index of packet segment whose raw fields are to be extracted
1321  */
1322 static enum ice_status
1323 ice_flow_xtract_raws(struct ice_hw *hw, struct ice_flow_prof_params *params,
1324                      u8 seg)
1325 {
1326         u16 fv_words;
1327         u16 hdrs_sz;
1328         u8 i;
1329
1330         if (!params->prof->segs[seg].raws_cnt)
1331                 return ICE_SUCCESS;
1332
1333         if (params->prof->segs[seg].raws_cnt >
1334             ARRAY_SIZE(params->prof->segs[seg].raws))
1335                 return ICE_ERR_MAX_LIMIT;
1336
1337         /* Offsets within the segment headers are not supported */
1338         hdrs_sz = ice_flow_calc_seg_sz(params, seg);
1339         if (!hdrs_sz)
1340                 return ICE_ERR_PARAM;
1341
1342         fv_words = hw->blk[params->blk].es.fvw;
1343
1344         for (i = 0; i < params->prof->segs[seg].raws_cnt; i++) {
1345                 struct ice_flow_seg_fld_raw *raw;
1346                 u16 off, cnt, j;
1347
1348                 raw = &params->prof->segs[seg].raws[i];
1349
1350                 /* Storing extraction information */
1351                 raw->info.xtrct.prot_id = ICE_PROT_MAC_OF_OR_S;
1352                 raw->info.xtrct.off = (raw->off / ICE_FLOW_FV_EXTRACT_SZ) *
1353                         ICE_FLOW_FV_EXTRACT_SZ;
1354                 raw->info.xtrct.disp = (raw->off % ICE_FLOW_FV_EXTRACT_SZ) *
1355                         BITS_PER_BYTE;
1356                 raw->info.xtrct.idx = params->es_cnt;
1357
1358                 /* Determine the number of field vector entries this raw field
1359                  * consumes.
1360                  */
1361                 cnt = DIVIDE_AND_ROUND_UP(raw->info.xtrct.disp +
1362                                           (raw->info.src.last * BITS_PER_BYTE),
1363                                           (ICE_FLOW_FV_EXTRACT_SZ *
1364                                            BITS_PER_BYTE));
1365                 off = raw->info.xtrct.off;
1366                 for (j = 0; j < cnt; j++) {
1367                         u16 idx;
1368
1369                         /* Make sure the number of extraction sequence required
1370                          * does not exceed the block's capability
1371                          */
1372                         if (params->es_cnt >= hw->blk[params->blk].es.count ||
1373                             params->es_cnt >= ICE_MAX_FV_WORDS)
1374                                 return ICE_ERR_MAX_LIMIT;
1375
1376                         /* some blocks require a reversed field vector layout */
1377                         if (hw->blk[params->blk].es.reverse)
1378                                 idx = fv_words - params->es_cnt - 1;
1379                         else
1380                                 idx = params->es_cnt;
1381
1382                         params->es[idx].prot_id = raw->info.xtrct.prot_id;
1383                         params->es[idx].off = off;
1384                         params->es_cnt++;
1385                         off += ICE_FLOW_FV_EXTRACT_SZ;
1386                 }
1387         }
1388
1389         return ICE_SUCCESS;
1390 }
1391
1392 /**
1393  * ice_flow_create_xtrct_seq - Create an extraction sequence for given segments
1394  * @hw: pointer to the HW struct
1395  * @params: information about the flow to be processed
1396  *
1397  * This function iterates through all matched fields in the given segments, and
1398  * creates an extraction sequence for the fields.
1399  */
1400 static enum ice_status
1401 ice_flow_create_xtrct_seq(struct ice_hw *hw,
1402                           struct ice_flow_prof_params *params)
1403 {
1404         enum ice_status status = ICE_SUCCESS;
1405         u8 i;
1406
1407         /* For ACL, we also need to extract the direction bit (Rx,Tx) data from
1408          * packet flags
1409          */
1410         if (params->blk == ICE_BLK_ACL) {
1411                 status = ice_flow_xtract_pkt_flags(hw, params,
1412                                                    ICE_RX_MDID_PKT_FLAGS_15_0);
1413                 if (status)
1414                         return status;
1415         }
1416
1417         for (i = 0; i < params->prof->segs_cnt; i++) {
1418                 u64 match = params->prof->segs[i].match;
1419                 enum ice_flow_field j;
1420
1421                 ice_for_each_set_bit(j, (ice_bitmap_t *)&match,
1422                                      ICE_FLOW_FIELD_IDX_MAX) {
1423                         status = ice_flow_xtract_fld(hw, params, i, j, match);
1424                         if (status)
1425                                 return status;
1426                         ice_clear_bit(j, (ice_bitmap_t *)&match);
1427                 }
1428
1429                 /* Process raw matching bytes */
1430                 status = ice_flow_xtract_raws(hw, params, i);
1431                 if (status)
1432                         return status;
1433         }
1434
1435         return status;
1436 }
1437
1438 /**
1439  * ice_flow_sel_acl_scen - returns the specific scenario
1440  * @hw: pointer to the hardware structure
1441  * @params: information about the flow to be processed
1442  *
1443  * This function will return the specific scenario based on the
1444  * params passed to it
1445  */
1446 static enum ice_status
1447 ice_flow_sel_acl_scen(struct ice_hw *hw, struct ice_flow_prof_params *params)
1448 {
1449         /* Find the best-fit scenario for the provided match width */
1450         struct ice_acl_scen *cand_scen = NULL, *scen;
1451
1452         if (!hw->acl_tbl)
1453                 return ICE_ERR_DOES_NOT_EXIST;
1454
1455         /* Loop through each scenario and match against the scenario width
1456          * to select the specific scenario
1457          */
1458         LIST_FOR_EACH_ENTRY(scen, &hw->acl_tbl->scens, ice_acl_scen, list_entry)
1459                 if (scen->eff_width >= params->entry_length &&
1460                     (!cand_scen || cand_scen->eff_width > scen->eff_width))
1461                         cand_scen = scen;
1462         if (!cand_scen)
1463                 return ICE_ERR_DOES_NOT_EXIST;
1464
1465         params->prof->cfg.scen = cand_scen;
1466
1467         return ICE_SUCCESS;
1468 }
1469
1470 /**
1471  * ice_flow_acl_def_entry_frmt - Determine the layout of flow entries
1472  * @params: information about the flow to be processed
1473  */
1474 static enum ice_status
1475 ice_flow_acl_def_entry_frmt(struct ice_flow_prof_params *params)
1476 {
1477         u16 index, i, range_idx = 0;
1478
1479         index = ICE_AQC_ACL_PROF_BYTE_SEL_START_IDX;
1480
1481         for (i = 0; i < params->prof->segs_cnt; i++) {
1482                 struct ice_flow_seg_info *seg = &params->prof->segs[i];
1483                 u8 j;
1484
1485                 ice_for_each_set_bit(j, (ice_bitmap_t *)&seg->match,
1486                                      ICE_FLOW_FIELD_IDX_MAX) {
1487                         struct ice_flow_fld_info *fld = &seg->fields[j];
1488
1489                         fld->entry.mask = ICE_FLOW_FLD_OFF_INVAL;
1490
1491                         if (fld->type == ICE_FLOW_FLD_TYPE_RANGE) {
1492                                 fld->entry.last = ICE_FLOW_FLD_OFF_INVAL;
1493
1494                                 /* Range checking only supported for single
1495                                  * words
1496                                  */
1497                                 if (DIVIDE_AND_ROUND_UP(ice_flds_info[j].size +
1498                                                         fld->xtrct.disp,
1499                                                         BITS_PER_BYTE * 2) > 1)
1500                                         return ICE_ERR_PARAM;
1501
1502                                 /* Ranges must define low and high values */
1503                                 if (fld->src.val == ICE_FLOW_FLD_OFF_INVAL ||
1504                                     fld->src.last == ICE_FLOW_FLD_OFF_INVAL)
1505                                         return ICE_ERR_PARAM;
1506
1507                                 fld->entry.val = range_idx++;
1508                         } else {
1509                                 /* Store adjusted byte-length of field for later
1510                                  * use, taking into account potential
1511                                  * non-byte-aligned displacement
1512                                  */
1513                                 fld->entry.last = DIVIDE_AND_ROUND_UP
1514                                         (ice_flds_info[j].size +
1515                                          (fld->xtrct.disp % BITS_PER_BYTE),
1516                                          BITS_PER_BYTE);
1517                                 fld->entry.val = index;
1518                                 index += fld->entry.last;
1519                         }
1520                 }
1521
1522                 for (j = 0; j < seg->raws_cnt; j++) {
1523                         struct ice_flow_seg_fld_raw *raw = &seg->raws[j];
1524
1525                         raw->info.entry.mask = ICE_FLOW_FLD_OFF_INVAL;
1526                         raw->info.entry.val = index;
1527                         raw->info.entry.last = raw->info.src.last;
1528                         index += raw->info.entry.last;
1529                 }
1530         }
1531
1532         /* Currently only support using the byte selection base, which only
1533          * allows for an effective entry size of 30 bytes. Reject anything
1534          * larger.
1535          */
1536         if (index > ICE_AQC_ACL_PROF_BYTE_SEL_ELEMS)
1537                 return ICE_ERR_PARAM;
1538
1539         /* Only 8 range checkers per profile, reject anything trying to use
1540          * more
1541          */
1542         if (range_idx > ICE_AQC_ACL_PROF_RANGES_NUM_CFG)
1543                 return ICE_ERR_PARAM;
1544
1545         /* Store # bytes required for entry for later use */
1546         params->entry_length = index - ICE_AQC_ACL_PROF_BYTE_SEL_START_IDX;
1547
1548         return ICE_SUCCESS;
1549 }
1550
1551 /**
1552  * ice_flow_proc_segs - process all packet segments associated with a profile
1553  * @hw: pointer to the HW struct
1554  * @params: information about the flow to be processed
1555  */
1556 static enum ice_status
1557 ice_flow_proc_segs(struct ice_hw *hw, struct ice_flow_prof_params *params)
1558 {
1559         enum ice_status status;
1560
1561         status = ice_flow_proc_seg_hdrs(params);
1562         if (status)
1563                 return status;
1564
1565         status = ice_flow_create_xtrct_seq(hw, params);
1566         if (status)
1567                 return status;
1568
1569         switch (params->blk) {
1570         case ICE_BLK_FD:
1571         case ICE_BLK_RSS:
1572                 status = ICE_SUCCESS;
1573                 break;
1574         case ICE_BLK_ACL:
1575                 status = ice_flow_acl_def_entry_frmt(params);
1576                 if (status)
1577                         return status;
1578                 status = ice_flow_sel_acl_scen(hw, params);
1579                 if (status)
1580                         return status;
1581                 break;
1582         default:
1583                 return ICE_ERR_NOT_IMPL;
1584         }
1585
1586         return status;
1587 }
1588
1589 #define ICE_FLOW_FIND_PROF_CHK_FLDS     0x00000001
1590 #define ICE_FLOW_FIND_PROF_CHK_VSI      0x00000002
1591 #define ICE_FLOW_FIND_PROF_NOT_CHK_DIR  0x00000004
1592
1593 /**
1594  * ice_flow_find_prof_conds - Find a profile matching headers and conditions
1595  * @hw: pointer to the HW struct
1596  * @blk: classification stage
1597  * @dir: flow direction
1598  * @segs: array of one or more packet segments that describe the flow
1599  * @segs_cnt: number of packet segments provided
1600  * @vsi_handle: software VSI handle to check VSI (ICE_FLOW_FIND_PROF_CHK_VSI)
1601  * @conds: additional conditions to be checked (ICE_FLOW_FIND_PROF_CHK_*)
1602  */
1603 static struct ice_flow_prof *
1604 ice_flow_find_prof_conds(struct ice_hw *hw, enum ice_block blk,
1605                          enum ice_flow_dir dir, struct ice_flow_seg_info *segs,
1606                          u8 segs_cnt, u16 vsi_handle, u32 conds)
1607 {
1608         struct ice_flow_prof *p, *prof = NULL;
1609
1610         ice_acquire_lock(&hw->fl_profs_locks[blk]);
1611         LIST_FOR_EACH_ENTRY(p, &hw->fl_profs[blk], ice_flow_prof, l_entry)
1612                 if ((p->dir == dir || conds & ICE_FLOW_FIND_PROF_NOT_CHK_DIR) &&
1613                     segs_cnt && segs_cnt == p->segs_cnt) {
1614                         u8 i;
1615
1616                         /* Check for profile-VSI association if specified */
1617                         if ((conds & ICE_FLOW_FIND_PROF_CHK_VSI) &&
1618                             ice_is_vsi_valid(hw, vsi_handle) &&
1619                             !ice_is_bit_set(p->vsis, vsi_handle))
1620                                 continue;
1621
1622                         /* Protocol headers must be checked. Matched fields are
1623                          * checked if specified.
1624                          */
1625                         for (i = 0; i < segs_cnt; i++)
1626                                 if (segs[i].hdrs != p->segs[i].hdrs ||
1627                                     ((conds & ICE_FLOW_FIND_PROF_CHK_FLDS) &&
1628                                      segs[i].match != p->segs[i].match))
1629                                         break;
1630
1631                         /* A match is found if all segments are matched */
1632                         if (i == segs_cnt) {
1633                                 prof = p;
1634                                 break;
1635                         }
1636                 }
1637         ice_release_lock(&hw->fl_profs_locks[blk]);
1638
1639         return prof;
1640 }
1641
1642 /**
1643  * ice_flow_find_prof - Look up a profile matching headers and matched fields
1644  * @hw: pointer to the HW struct
1645  * @blk: classification stage
1646  * @dir: flow direction
1647  * @segs: array of one or more packet segments that describe the flow
1648  * @segs_cnt: number of packet segments provided
1649  */
1650 u64
1651 ice_flow_find_prof(struct ice_hw *hw, enum ice_block blk, enum ice_flow_dir dir,
1652                    struct ice_flow_seg_info *segs, u8 segs_cnt)
1653 {
1654         struct ice_flow_prof *p;
1655
1656         p = ice_flow_find_prof_conds(hw, blk, dir, segs, segs_cnt,
1657                                      ICE_MAX_VSI, ICE_FLOW_FIND_PROF_CHK_FLDS);
1658
1659         return p ? p->id : ICE_FLOW_PROF_ID_INVAL;
1660 }
1661
1662 /**
1663  * ice_flow_find_prof_id - Look up a profile with given profile ID
1664  * @hw: pointer to the HW struct
1665  * @blk: classification stage
1666  * @prof_id: unique ID to identify this flow profile
1667  */
1668 static struct ice_flow_prof *
1669 ice_flow_find_prof_id(struct ice_hw *hw, enum ice_block blk, u64 prof_id)
1670 {
1671         struct ice_flow_prof *p;
1672
1673         LIST_FOR_EACH_ENTRY(p, &hw->fl_profs[blk], ice_flow_prof, l_entry)
1674                 if (p->id == prof_id)
1675                         return p;
1676
1677         return NULL;
1678 }
1679
1680 /**
1681  * ice_dealloc_flow_entry - Deallocate flow entry memory
1682  * @hw: pointer to the HW struct
1683  * @entry: flow entry to be removed
1684  */
1685 static void
1686 ice_dealloc_flow_entry(struct ice_hw *hw, struct ice_flow_entry *entry)
1687 {
1688         if (!entry)
1689                 return;
1690
1691         if (entry->entry)
1692                 ice_free(hw, entry->entry);
1693
1694         if (entry->range_buf) {
1695                 ice_free(hw, entry->range_buf);
1696                 entry->range_buf = NULL;
1697         }
1698
1699         if (entry->acts) {
1700                 ice_free(hw, entry->acts);
1701                 entry->acts = NULL;
1702                 entry->acts_cnt = 0;
1703         }
1704
1705         ice_free(hw, entry);
1706 }
1707
1708 /**
1709  * ice_flow_get_hw_prof - return the HW profile for a specific profile ID handle
1710  * @hw: pointer to the HW struct
1711  * @blk: classification stage
1712  * @prof_id: the profile ID handle
1713  * @hw_prof_id: pointer to variable to receive the HW profile ID
1714  */
1715 enum ice_status
1716 ice_flow_get_hw_prof(struct ice_hw *hw, enum ice_block blk, u64 prof_id,
1717                      u8 *hw_prof_id)
1718 {
1719         enum ice_status status = ICE_ERR_DOES_NOT_EXIST;
1720         struct ice_prof_map *map;
1721
1722         ice_acquire_lock(&hw->blk[blk].es.prof_map_lock);
1723         map = ice_search_prof_id(hw, blk, prof_id);
1724         if (map) {
1725                 *hw_prof_id = map->prof_id;
1726                 status = ICE_SUCCESS;
1727         }
1728         ice_release_lock(&hw->blk[blk].es.prof_map_lock);
1729         return status;
1730 }
1731
1732 #define ICE_ACL_INVALID_SCEN    0x3f
1733
1734 /**
1735  * ice_flow_acl_is_prof_in_use - Verify if the profile is associated to any PF
1736  * @hw: pointer to the hardware structure
1737  * @prof: pointer to flow profile
1738  * @buf: destination buffer function writes partial extraction sequence to
1739  *
1740  * returns ICE_SUCCESS if no PF is associated to the given profile
1741  * returns ICE_ERR_IN_USE if at least one PF is associated to the given profile
1742  * returns other error code for real error
1743  */
1744 static enum ice_status
1745 ice_flow_acl_is_prof_in_use(struct ice_hw *hw, struct ice_flow_prof *prof,
1746                             struct ice_aqc_acl_prof_generic_frmt *buf)
1747 {
1748         enum ice_status status;
1749         u8 prof_id = 0;
1750
1751         status = ice_flow_get_hw_prof(hw, ICE_BLK_ACL, prof->id, &prof_id);
1752         if (status)
1753                 return status;
1754
1755         status = ice_query_acl_prof(hw, prof_id, buf, NULL);
1756         if (status)
1757                 return status;
1758
1759         /* If all PF's associated scenarios are all 0 or all
1760          * ICE_ACL_INVALID_SCEN (63) for the given profile then the latter has
1761          * not been configured yet.
1762          */
1763         if (buf->pf_scenario_num[0] == 0 && buf->pf_scenario_num[1] == 0 &&
1764             buf->pf_scenario_num[2] == 0 && buf->pf_scenario_num[3] == 0 &&
1765             buf->pf_scenario_num[4] == 0 && buf->pf_scenario_num[5] == 0 &&
1766             buf->pf_scenario_num[6] == 0 && buf->pf_scenario_num[7] == 0)
1767                 return ICE_SUCCESS;
1768
1769         if (buf->pf_scenario_num[0] == ICE_ACL_INVALID_SCEN &&
1770             buf->pf_scenario_num[1] == ICE_ACL_INVALID_SCEN &&
1771             buf->pf_scenario_num[2] == ICE_ACL_INVALID_SCEN &&
1772             buf->pf_scenario_num[3] == ICE_ACL_INVALID_SCEN &&
1773             buf->pf_scenario_num[4] == ICE_ACL_INVALID_SCEN &&
1774             buf->pf_scenario_num[5] == ICE_ACL_INVALID_SCEN &&
1775             buf->pf_scenario_num[6] == ICE_ACL_INVALID_SCEN &&
1776             buf->pf_scenario_num[7] == ICE_ACL_INVALID_SCEN)
1777                 return ICE_SUCCESS;
1778
1779         return ICE_ERR_IN_USE;
1780 }
1781
1782 /**
1783  * ice_flow_acl_free_act_cntr - Free the ACL rule's actions
1784  * @hw: pointer to the hardware structure
1785  * @acts: array of actions to be performed on a match
1786  * @acts_cnt: number of actions
1787  */
1788 static enum ice_status
1789 ice_flow_acl_free_act_cntr(struct ice_hw *hw, struct ice_flow_action *acts,
1790                            u8 acts_cnt)
1791 {
1792         int i;
1793
1794         for (i = 0; i < acts_cnt; i++) {
1795                 if (acts[i].type == ICE_FLOW_ACT_CNTR_PKT ||
1796                     acts[i].type == ICE_FLOW_ACT_CNTR_BYTES ||
1797                     acts[i].type == ICE_FLOW_ACT_CNTR_PKT_BYTES) {
1798                         struct ice_acl_cntrs cntrs;
1799                         enum ice_status status;
1800
1801                         cntrs.bank = 0; /* Only bank0 for the moment */
1802                         cntrs.first_cntr =
1803                                         LE16_TO_CPU(acts[i].data.acl_act.value);
1804                         cntrs.last_cntr =
1805                                         LE16_TO_CPU(acts[i].data.acl_act.value);
1806
1807                         if (acts[i].type == ICE_FLOW_ACT_CNTR_PKT_BYTES)
1808                                 cntrs.type = ICE_AQC_ACL_CNT_TYPE_DUAL;
1809                         else
1810                                 cntrs.type = ICE_AQC_ACL_CNT_TYPE_SINGLE;
1811
1812                         status = ice_aq_dealloc_acl_cntrs(hw, &cntrs, NULL);
1813                         if (status)
1814                                 return status;
1815                 }
1816         }
1817         return ICE_SUCCESS;
1818 }
1819
1820 /**
1821  * ice_flow_acl_disassoc_scen - Disassociate the scenario from the profile
1822  * @hw: pointer to the hardware structure
1823  * @prof: pointer to flow profile
1824  *
1825  * Disassociate the scenario from the profile for the PF of the VSI.
1826  */
1827 static enum ice_status
1828 ice_flow_acl_disassoc_scen(struct ice_hw *hw, struct ice_flow_prof *prof)
1829 {
1830         struct ice_aqc_acl_prof_generic_frmt buf;
1831         enum ice_status status = ICE_SUCCESS;
1832         u8 prof_id = 0;
1833
1834         ice_memset(&buf, 0, sizeof(buf), ICE_NONDMA_MEM);
1835
1836         status = ice_flow_get_hw_prof(hw, ICE_BLK_ACL, prof->id, &prof_id);
1837         if (status)
1838                 return status;
1839
1840         status = ice_query_acl_prof(hw, prof_id, &buf, NULL);
1841         if (status)
1842                 return status;
1843
1844         /* Clear scenario for this PF */
1845         buf.pf_scenario_num[hw->pf_id] = ICE_ACL_INVALID_SCEN;
1846         status = ice_prgm_acl_prof_xtrct(hw, prof_id, &buf, NULL);
1847
1848         return status;
1849 }
1850
1851 /**
1852  * ice_flow_rem_entry_sync - Remove a flow entry
1853  * @hw: pointer to the HW struct
1854  * @blk: classification stage
1855  * @entry: flow entry to be removed
1856  */
1857 static enum ice_status
1858 ice_flow_rem_entry_sync(struct ice_hw *hw, enum ice_block blk,
1859                         struct ice_flow_entry *entry)
1860 {
1861         if (!entry)
1862                 return ICE_ERR_BAD_PTR;
1863
1864         if (blk == ICE_BLK_ACL) {
1865                 enum ice_status status;
1866
1867                 if (!entry->prof)
1868                         return ICE_ERR_BAD_PTR;
1869
1870                 status = ice_acl_rem_entry(hw, entry->prof->cfg.scen,
1871                                            entry->scen_entry_idx);
1872                 if (status)
1873                         return status;
1874
1875                 /* Checks if we need to release an ACL counter. */
1876                 if (entry->acts_cnt && entry->acts)
1877                         ice_flow_acl_free_act_cntr(hw, entry->acts,
1878                                                    entry->acts_cnt);
1879         }
1880
1881         LIST_DEL(&entry->l_entry);
1882
1883         ice_dealloc_flow_entry(hw, entry);
1884
1885         return ICE_SUCCESS;
1886 }
1887
1888 /**
1889  * ice_flow_add_prof_sync - Add a flow profile for packet segments and fields
1890  * @hw: pointer to the HW struct
1891  * @blk: classification stage
1892  * @dir: flow direction
1893  * @prof_id: unique ID to identify this flow profile
1894  * @segs: array of one or more packet segments that describe the flow
1895  * @segs_cnt: number of packet segments provided
1896  * @acts: array of default actions
1897  * @acts_cnt: number of default actions
1898  * @prof: stores the returned flow profile added
1899  *
1900  * Assumption: the caller has acquired the lock to the profile list
1901  */
1902 static enum ice_status
1903 ice_flow_add_prof_sync(struct ice_hw *hw, enum ice_block blk,
1904                        enum ice_flow_dir dir, u64 prof_id,
1905                        struct ice_flow_seg_info *segs, u8 segs_cnt,
1906                        struct ice_flow_action *acts, u8 acts_cnt,
1907                        struct ice_flow_prof **prof)
1908 {
1909         struct ice_flow_prof_params *params;
1910         enum ice_status status;
1911         u8 i;
1912
1913         if (!prof || (acts_cnt && !acts))
1914                 return ICE_ERR_BAD_PTR;
1915
1916         params = (struct ice_flow_prof_params *)ice_malloc(hw, sizeof(*params));
1917         if (!params)
1918                 return ICE_ERR_NO_MEMORY;
1919
1920         params->prof = (struct ice_flow_prof *)
1921                 ice_malloc(hw, sizeof(*params->prof));
1922         if (!params->prof) {
1923                 status = ICE_ERR_NO_MEMORY;
1924                 goto free_params;
1925         }
1926
1927         /* initialize extraction sequence to all invalid (0xff) */
1928         for (i = 0; i < ICE_MAX_FV_WORDS; i++) {
1929                 params->es[i].prot_id = ICE_PROT_INVALID;
1930                 params->es[i].off = ICE_FV_OFFSET_INVAL;
1931         }
1932
1933         params->blk = blk;
1934         params->prof->id = prof_id;
1935         params->prof->dir = dir;
1936         params->prof->segs_cnt = segs_cnt;
1937
1938         /* Make a copy of the segments that need to be persistent in the flow
1939          * profile instance
1940          */
1941         for (i = 0; i < segs_cnt; i++)
1942                 ice_memcpy(&params->prof->segs[i], &segs[i], sizeof(*segs),
1943                            ICE_NONDMA_TO_NONDMA);
1944
1945         /* Make a copy of the actions that need to be persistent in the flow
1946          * profile instance.
1947          */
1948         if (acts_cnt) {
1949                 params->prof->acts = (struct ice_flow_action *)
1950                         ice_memdup(hw, acts, acts_cnt * sizeof(*acts),
1951                                    ICE_NONDMA_TO_NONDMA);
1952
1953                 if (!params->prof->acts) {
1954                         status = ICE_ERR_NO_MEMORY;
1955                         goto out;
1956                 }
1957         }
1958
1959         status = ice_flow_proc_segs(hw, params);
1960         if (status) {
1961                 ice_debug(hw, ICE_DBG_FLOW, "Error processing a flow's packet segments\n");
1962                 goto out;
1963         }
1964
1965         /* Add a HW profile for this flow profile */
1966         status = ice_add_prof(hw, blk, prof_id, (u8 *)params->ptypes,
1967                               params->attr, params->attr_cnt, params->es,
1968                               params->mask);
1969         if (status) {
1970                 ice_debug(hw, ICE_DBG_FLOW, "Error adding a HW flow profile\n");
1971                 goto out;
1972         }
1973
1974         INIT_LIST_HEAD(&params->prof->entries);
1975         ice_init_lock(&params->prof->entries_lock);
1976         *prof = params->prof;
1977
1978 out:
1979         if (status) {
1980                 if (params->prof->acts)
1981                         ice_free(hw, params->prof->acts);
1982                 ice_free(hw, params->prof);
1983         }
1984 free_params:
1985         ice_free(hw, params);
1986
1987         return status;
1988 }
1989
1990 /**
1991  * ice_flow_rem_prof_sync - remove a flow profile
1992  * @hw: pointer to the hardware structure
1993  * @blk: classification stage
1994  * @prof: pointer to flow profile to remove
1995  *
1996  * Assumption: the caller has acquired the lock to the profile list
1997  */
1998 static enum ice_status
1999 ice_flow_rem_prof_sync(struct ice_hw *hw, enum ice_block blk,
2000                        struct ice_flow_prof *prof)
2001 {
2002         enum ice_status status;
2003
2004         /* Remove all remaining flow entries before removing the flow profile */
2005         if (!LIST_EMPTY(&prof->entries)) {
2006                 struct ice_flow_entry *e, *t;
2007
2008                 ice_acquire_lock(&prof->entries_lock);
2009
2010                 LIST_FOR_EACH_ENTRY_SAFE(e, t, &prof->entries, ice_flow_entry,
2011                                          l_entry) {
2012                         status = ice_flow_rem_entry_sync(hw, blk, e);
2013                         if (status)
2014                                 break;
2015                 }
2016
2017                 ice_release_lock(&prof->entries_lock);
2018         }
2019
2020         if (blk == ICE_BLK_ACL) {
2021                 struct ice_aqc_acl_profile_ranges query_rng_buf;
2022                 struct ice_aqc_acl_prof_generic_frmt buf;
2023                 u8 prof_id = 0;
2024
2025                 /* Disassociate the scenario from the profile for the PF */
2026                 status = ice_flow_acl_disassoc_scen(hw, prof);
2027                 if (status)
2028                         return status;
2029
2030                 /* Clear the range-checker if the profile ID is no longer
2031                  * used by any PF
2032                  */
2033                 status = ice_flow_acl_is_prof_in_use(hw, prof, &buf);
2034                 if (status && status != ICE_ERR_IN_USE) {
2035                         return status;
2036                 } else if (!status) {
2037                         /* Clear the range-checker value for profile ID */
2038                         ice_memset(&query_rng_buf, 0,
2039                                    sizeof(struct ice_aqc_acl_profile_ranges),
2040                                    ICE_NONDMA_MEM);
2041
2042                         status = ice_flow_get_hw_prof(hw, blk, prof->id,
2043                                                       &prof_id);
2044                         if (status)
2045                                 return status;
2046
2047                         status = ice_prog_acl_prof_ranges(hw, prof_id,
2048                                                           &query_rng_buf, NULL);
2049                         if (status)
2050                                 return status;
2051                 }
2052         }
2053
2054         /* Remove all hardware profiles associated with this flow profile */
2055         status = ice_rem_prof(hw, blk, prof->id);
2056         if (!status) {
2057                 LIST_DEL(&prof->l_entry);
2058                 ice_destroy_lock(&prof->entries_lock);
2059                 if (prof->acts)
2060                         ice_free(hw, prof->acts);
2061                 ice_free(hw, prof);
2062         }
2063
2064         return status;
2065 }
2066
2067 /**
2068  * ice_flow_acl_set_xtrct_seq_fld - Populate xtrct seq for single field
2069  * @buf: Destination buffer function writes partial xtrct sequence to
2070  * @info: Info about field
2071  */
2072 static void
2073 ice_flow_acl_set_xtrct_seq_fld(struct ice_aqc_acl_prof_generic_frmt *buf,
2074                                struct ice_flow_fld_info *info)
2075 {
2076         u16 dst, i;
2077         u8 src;
2078
2079         src = info->xtrct.idx * ICE_FLOW_FV_EXTRACT_SZ +
2080                 info->xtrct.disp / BITS_PER_BYTE;
2081         dst = info->entry.val;
2082         for (i = 0; i < info->entry.last; i++)
2083                 /* HW stores field vector words in LE, convert words back to BE
2084                  * so constructed entries will end up in network order
2085                  */
2086                 buf->byte_selection[dst++] = src++ ^ 1;
2087 }
2088
2089 /**
2090  * ice_flow_acl_set_xtrct_seq - Program ACL extraction sequence
2091  * @hw: pointer to the hardware structure
2092  * @prof: pointer to flow profile
2093  */
2094 static enum ice_status
2095 ice_flow_acl_set_xtrct_seq(struct ice_hw *hw, struct ice_flow_prof *prof)
2096 {
2097         struct ice_aqc_acl_prof_generic_frmt buf;
2098         struct ice_flow_fld_info *info;
2099         enum ice_status status;
2100         u8 prof_id = 0;
2101         u16 i;
2102
2103         ice_memset(&buf, 0, sizeof(buf), ICE_NONDMA_MEM);
2104
2105         status = ice_flow_get_hw_prof(hw, ICE_BLK_ACL, prof->id, &prof_id);
2106         if (status)
2107                 return status;
2108
2109         status = ice_flow_acl_is_prof_in_use(hw, prof, &buf);
2110         if (status && status != ICE_ERR_IN_USE)
2111                 return status;
2112
2113         if (!status) {
2114                 /* Program the profile dependent configuration. This is done
2115                  * only once regardless of the number of PFs using that profile
2116                  */
2117                 ice_memset(&buf, 0, sizeof(buf), ICE_NONDMA_MEM);
2118
2119                 for (i = 0; i < prof->segs_cnt; i++) {
2120                         struct ice_flow_seg_info *seg = &prof->segs[i];
2121                         u16 j;
2122
2123                         ice_for_each_set_bit(j, (ice_bitmap_t *)&seg->match,
2124                                              ICE_FLOW_FIELD_IDX_MAX) {
2125                                 info = &seg->fields[j];
2126
2127                                 if (info->type == ICE_FLOW_FLD_TYPE_RANGE)
2128                                         buf.word_selection[info->entry.val] =
2129                                                 info->xtrct.idx;
2130                                 else
2131                                         ice_flow_acl_set_xtrct_seq_fld(&buf,
2132                                                                        info);
2133                         }
2134
2135                         for (j = 0; j < seg->raws_cnt; j++) {
2136                                 info = &seg->raws[j].info;
2137                                 ice_flow_acl_set_xtrct_seq_fld(&buf, info);
2138                         }
2139                 }
2140
2141                 ice_memset(&buf.pf_scenario_num[0], ICE_ACL_INVALID_SCEN,
2142                            ICE_AQC_ACL_PROF_PF_SCEN_NUM_ELEMS,
2143                            ICE_NONDMA_MEM);
2144         }
2145
2146         /* Update the current PF */
2147         buf.pf_scenario_num[hw->pf_id] = (u8)prof->cfg.scen->id;
2148         status = ice_prgm_acl_prof_xtrct(hw, prof_id, &buf, NULL);
2149
2150         return status;
2151 }
2152
2153 /**
2154  * ice_flow_assoc_vsig_vsi - associate a VSI with VSIG
2155  * @hw: pointer to the hardware structure
2156  * @blk: classification stage
2157  * @vsi_handle: software VSI handle
2158  * @vsig: target VSI group
2159  *
2160  * Assumption: the caller has already verified that the VSI to
2161  * be added has the same characteristics as the VSIG and will
2162  * thereby have access to all resources added to that VSIG.
2163  */
2164 enum ice_status
2165 ice_flow_assoc_vsig_vsi(struct ice_hw *hw, enum ice_block blk, u16 vsi_handle,
2166                         u16 vsig)
2167 {
2168         enum ice_status status;
2169
2170         if (!ice_is_vsi_valid(hw, vsi_handle) || blk >= ICE_BLK_COUNT)
2171                 return ICE_ERR_PARAM;
2172
2173         ice_acquire_lock(&hw->fl_profs_locks[blk]);
2174         status = ice_add_vsi_flow(hw, blk, ice_get_hw_vsi_num(hw, vsi_handle),
2175                                   vsig);
2176         ice_release_lock(&hw->fl_profs_locks[blk]);
2177
2178         return status;
2179 }
2180
2181 /**
2182  * ice_flow_assoc_prof - associate a VSI with a flow profile
2183  * @hw: pointer to the hardware structure
2184  * @blk: classification stage
2185  * @prof: pointer to flow profile
2186  * @vsi_handle: software VSI handle
2187  *
2188  * Assumption: the caller has acquired the lock to the profile list
2189  * and the software VSI handle has been validated
2190  */
2191 enum ice_status
2192 ice_flow_assoc_prof(struct ice_hw *hw, enum ice_block blk,
2193                     struct ice_flow_prof *prof, u16 vsi_handle)
2194 {
2195         enum ice_status status = ICE_SUCCESS;
2196
2197         if (!ice_is_bit_set(prof->vsis, vsi_handle)) {
2198                 if (blk == ICE_BLK_ACL) {
2199                         status = ice_flow_acl_set_xtrct_seq(hw, prof);
2200                         if (status)
2201                                 return status;
2202                 }
2203                 status = ice_add_prof_id_flow(hw, blk,
2204                                               ice_get_hw_vsi_num(hw,
2205                                                                  vsi_handle),
2206                                               prof->id);
2207                 if (!status)
2208                         ice_set_bit(vsi_handle, prof->vsis);
2209                 else
2210                         ice_debug(hw, ICE_DBG_FLOW, "HW profile add failed, %d\n",
2211                                   status);
2212         }
2213
2214         return status;
2215 }
2216
2217 /**
2218  * ice_flow_disassoc_prof - disassociate a VSI from a flow profile
2219  * @hw: pointer to the hardware structure
2220  * @blk: classification stage
2221  * @prof: pointer to flow profile
2222  * @vsi_handle: software VSI handle
2223  *
2224  * Assumption: the caller has acquired the lock to the profile list
2225  * and the software VSI handle has been validated
2226  */
2227 static enum ice_status
2228 ice_flow_disassoc_prof(struct ice_hw *hw, enum ice_block blk,
2229                        struct ice_flow_prof *prof, u16 vsi_handle)
2230 {
2231         enum ice_status status = ICE_SUCCESS;
2232
2233         if (ice_is_bit_set(prof->vsis, vsi_handle)) {
2234                 status = ice_rem_prof_id_flow(hw, blk,
2235                                               ice_get_hw_vsi_num(hw,
2236                                                                  vsi_handle),
2237                                               prof->id);
2238                 if (!status)
2239                         ice_clear_bit(vsi_handle, prof->vsis);
2240                 else
2241                         ice_debug(hw, ICE_DBG_FLOW, "HW profile remove failed, %d\n",
2242                                   status);
2243         }
2244
2245         return status;
2246 }
2247
2248 /**
2249  * ice_flow_add_prof - Add a flow profile for packet segments and matched fields
2250  * @hw: pointer to the HW struct
2251  * @blk: classification stage
2252  * @dir: flow direction
2253  * @prof_id: unique ID to identify this flow profile
2254  * @segs: array of one or more packet segments that describe the flow
2255  * @segs_cnt: number of packet segments provided
2256  * @acts: array of default actions
2257  * @acts_cnt: number of default actions
2258  * @prof: stores the returned flow profile added
2259  */
2260 enum ice_status
2261 ice_flow_add_prof(struct ice_hw *hw, enum ice_block blk, enum ice_flow_dir dir,
2262                   u64 prof_id, struct ice_flow_seg_info *segs, u8 segs_cnt,
2263                   struct ice_flow_action *acts, u8 acts_cnt,
2264                   struct ice_flow_prof **prof)
2265 {
2266         enum ice_status status;
2267
2268         if (segs_cnt > ICE_FLOW_SEG_MAX)
2269                 return ICE_ERR_MAX_LIMIT;
2270
2271         if (!segs_cnt)
2272                 return ICE_ERR_PARAM;
2273
2274         if (!segs)
2275                 return ICE_ERR_BAD_PTR;
2276
2277         status = ice_flow_val_hdrs(segs, segs_cnt);
2278         if (status)
2279                 return status;
2280
2281         ice_acquire_lock(&hw->fl_profs_locks[blk]);
2282
2283         status = ice_flow_add_prof_sync(hw, blk, dir, prof_id, segs, segs_cnt,
2284                                         acts, acts_cnt, prof);
2285         if (!status)
2286                 LIST_ADD(&(*prof)->l_entry, &hw->fl_profs[blk]);
2287
2288         ice_release_lock(&hw->fl_profs_locks[blk]);
2289
2290         return status;
2291 }
2292
2293 /**
2294  * ice_flow_rem_prof - Remove a flow profile and all entries associated with it
2295  * @hw: pointer to the HW struct
2296  * @blk: the block for which the flow profile is to be removed
2297  * @prof_id: unique ID of the flow profile to be removed
2298  */
2299 enum ice_status
2300 ice_flow_rem_prof(struct ice_hw *hw, enum ice_block blk, u64 prof_id)
2301 {
2302         struct ice_flow_prof *prof;
2303         enum ice_status status;
2304
2305         ice_acquire_lock(&hw->fl_profs_locks[blk]);
2306
2307         prof = ice_flow_find_prof_id(hw, blk, prof_id);
2308         if (!prof) {
2309                 status = ICE_ERR_DOES_NOT_EXIST;
2310                 goto out;
2311         }
2312
2313         /* prof becomes invalid after the call */
2314         status = ice_flow_rem_prof_sync(hw, blk, prof);
2315
2316 out:
2317         ice_release_lock(&hw->fl_profs_locks[blk]);
2318
2319         return status;
2320 }
2321
2322 /**
2323  * ice_flow_find_entry - look for a flow entry using its unique ID
2324  * @hw: pointer to the HW struct
2325  * @blk: classification stage
2326  * @entry_id: unique ID to identify this flow entry
2327  *
2328  * This function looks for the flow entry with the specified unique ID in all
2329  * flow profiles of the specified classification stage. If the entry is found,
2330  * and it returns the handle to the flow entry. Otherwise, it returns
2331  * ICE_FLOW_ENTRY_ID_INVAL.
2332  */
2333 u64 ice_flow_find_entry(struct ice_hw *hw, enum ice_block blk, u64 entry_id)
2334 {
2335         struct ice_flow_entry *found = NULL;
2336         struct ice_flow_prof *p;
2337
2338         ice_acquire_lock(&hw->fl_profs_locks[blk]);
2339
2340         LIST_FOR_EACH_ENTRY(p, &hw->fl_profs[blk], ice_flow_prof, l_entry) {
2341                 struct ice_flow_entry *e;
2342
2343                 ice_acquire_lock(&p->entries_lock);
2344                 LIST_FOR_EACH_ENTRY(e, &p->entries, ice_flow_entry, l_entry)
2345                         if (e->id == entry_id) {
2346                                 found = e;
2347                                 break;
2348                         }
2349                 ice_release_lock(&p->entries_lock);
2350
2351                 if (found)
2352                         break;
2353         }
2354
2355         ice_release_lock(&hw->fl_profs_locks[blk]);
2356
2357         return found ? ICE_FLOW_ENTRY_HNDL(found) : ICE_FLOW_ENTRY_HANDLE_INVAL;
2358 }
2359
2360 /**
2361  * ice_flow_acl_check_actions - Checks the ACL rule's actions
2362  * @hw: pointer to the hardware structure
2363  * @acts: array of actions to be performed on a match
2364  * @acts_cnt: number of actions
2365  * @cnt_alloc: indicates if an ACL counter has been allocated.
2366  */
2367 static enum ice_status
2368 ice_flow_acl_check_actions(struct ice_hw *hw, struct ice_flow_action *acts,
2369                            u8 acts_cnt, bool *cnt_alloc)
2370 {
2371         ice_declare_bitmap(dup_check, ICE_AQC_TBL_MAX_ACTION_PAIRS * 2);
2372         int i;
2373
2374         ice_zero_bitmap(dup_check, ICE_AQC_TBL_MAX_ACTION_PAIRS * 2);
2375         *cnt_alloc = false;
2376
2377         if (acts_cnt > ICE_FLOW_ACL_MAX_NUM_ACT)
2378                 return ICE_ERR_OUT_OF_RANGE;
2379
2380         for (i = 0; i < acts_cnt; i++) {
2381                 if (acts[i].type != ICE_FLOW_ACT_NOP &&
2382                     acts[i].type != ICE_FLOW_ACT_DROP &&
2383                     acts[i].type != ICE_FLOW_ACT_CNTR_PKT &&
2384                     acts[i].type != ICE_FLOW_ACT_FWD_QUEUE)
2385                         return ICE_ERR_CFG;
2386
2387                 /* If the caller want to add two actions of the same type, then
2388                  * it is considered invalid configuration.
2389                  */
2390                 if (ice_test_and_set_bit(acts[i].type, dup_check))
2391                         return ICE_ERR_PARAM;
2392         }
2393
2394         /* Checks if ACL counters are needed. */
2395         for (i = 0; i < acts_cnt; i++) {
2396                 if (acts[i].type == ICE_FLOW_ACT_CNTR_PKT ||
2397                     acts[i].type == ICE_FLOW_ACT_CNTR_BYTES ||
2398                     acts[i].type == ICE_FLOW_ACT_CNTR_PKT_BYTES) {
2399                         struct ice_acl_cntrs cntrs;
2400                         enum ice_status status;
2401
2402                         cntrs.amount = 1;
2403                         cntrs.bank = 0; /* Only bank0 for the moment */
2404
2405                         if (acts[i].type == ICE_FLOW_ACT_CNTR_PKT_BYTES)
2406                                 cntrs.type = ICE_AQC_ACL_CNT_TYPE_DUAL;
2407                         else
2408                                 cntrs.type = ICE_AQC_ACL_CNT_TYPE_SINGLE;
2409
2410                         status = ice_aq_alloc_acl_cntrs(hw, &cntrs, NULL);
2411                         if (status)
2412                                 return status;
2413                         /* Counter index within the bank */
2414                         acts[i].data.acl_act.value =
2415                                                 CPU_TO_LE16(cntrs.first_cntr);
2416                         *cnt_alloc = true;
2417                 }
2418         }
2419
2420         return ICE_SUCCESS;
2421 }
2422
2423 /**
2424  * ice_flow_acl_frmt_entry_range - Format an ACL range checker for a given field
2425  * @fld: number of the given field
2426  * @info: info about field
2427  * @range_buf: range checker configuration buffer
2428  * @data: pointer to a data buffer containing flow entry's match values/masks
2429  * @range: Input/output param indicating which range checkers are being used
2430  */
2431 static void
2432 ice_flow_acl_frmt_entry_range(u16 fld, struct ice_flow_fld_info *info,
2433                               struct ice_aqc_acl_profile_ranges *range_buf,
2434                               u8 *data, u8 *range)
2435 {
2436         u16 new_mask;
2437
2438         /* If not specified, default mask is all bits in field */
2439         new_mask = (info->src.mask == ICE_FLOW_FLD_OFF_INVAL ?
2440                     BIT(ice_flds_info[fld].size) - 1 :
2441                     (*(u16 *)(data + info->src.mask))) << info->xtrct.disp;
2442
2443         /* If the mask is 0, then we don't need to worry about this input
2444          * range checker value.
2445          */
2446         if (new_mask) {
2447                 u16 new_high =
2448                         (*(u16 *)(data + info->src.last)) << info->xtrct.disp;
2449                 u16 new_low =
2450                         (*(u16 *)(data + info->src.val)) << info->xtrct.disp;
2451                 u8 range_idx = info->entry.val;
2452
2453                 range_buf->checker_cfg[range_idx].low_boundary =
2454                         CPU_TO_BE16(new_low);
2455                 range_buf->checker_cfg[range_idx].high_boundary =
2456                         CPU_TO_BE16(new_high);
2457                 range_buf->checker_cfg[range_idx].mask = CPU_TO_BE16(new_mask);
2458
2459                 /* Indicate which range checker is being used */
2460                 *range |= BIT(range_idx);
2461         }
2462 }
2463
2464 /**
2465  * ice_flow_acl_frmt_entry_fld - Partially format ACL entry for a given field
2466  * @fld: number of the given field
2467  * @info: info about the field
2468  * @buf: buffer containing the entry
2469  * @dontcare: buffer containing don't care mask for entry
2470  * @data: pointer to a data buffer containing flow entry's match values/masks
2471  */
2472 static void
2473 ice_flow_acl_frmt_entry_fld(u16 fld, struct ice_flow_fld_info *info, u8 *buf,
2474                             u8 *dontcare, u8 *data)
2475 {
2476         u16 dst, src, mask, k, end_disp, tmp_s = 0, tmp_m = 0;
2477         bool use_mask = false;
2478         u8 disp;
2479
2480         src = info->src.val;
2481         mask = info->src.mask;
2482         dst = info->entry.val - ICE_AQC_ACL_PROF_BYTE_SEL_START_IDX;
2483         disp = info->xtrct.disp % BITS_PER_BYTE;
2484
2485         if (mask != ICE_FLOW_FLD_OFF_INVAL)
2486                 use_mask = true;
2487
2488         for (k = 0; k < info->entry.last; k++, dst++) {
2489                 /* Add overflow bits from previous byte */
2490                 buf[dst] = (tmp_s & 0xff00) >> 8;
2491
2492                 /* If mask is not valid, tmp_m is always zero, so just setting
2493                  * dontcare to 0 (no masked bits). If mask is valid, pulls in
2494                  * overflow bits of mask from prev byte
2495                  */
2496                 dontcare[dst] = (tmp_m & 0xff00) >> 8;
2497
2498                 /* If there is displacement, last byte will only contain
2499                  * displaced data, but there is no more data to read from user
2500                  * buffer, so skip so as not to potentially read beyond end of
2501                  * user buffer
2502                  */
2503                 if (!disp || k < info->entry.last - 1) {
2504                         /* Store shifted data to use in next byte */
2505                         tmp_s = data[src++] << disp;
2506
2507                         /* Add current (shifted) byte */
2508                         buf[dst] |= tmp_s & 0xff;
2509
2510                         /* Handle mask if valid */
2511                         if (use_mask) {
2512                                 tmp_m = (~data[mask++] & 0xff) << disp;
2513                                 dontcare[dst] |= tmp_m & 0xff;
2514                         }
2515                 }
2516         }
2517
2518         /* Fill in don't care bits at beginning of field */
2519         if (disp) {
2520                 dst = info->entry.val - ICE_AQC_ACL_PROF_BYTE_SEL_START_IDX;
2521                 for (k = 0; k < disp; k++)
2522                         dontcare[dst] |= BIT(k);
2523         }
2524
2525         end_disp = (disp + ice_flds_info[fld].size) % BITS_PER_BYTE;
2526
2527         /* Fill in don't care bits at end of field */
2528         if (end_disp) {
2529                 dst = info->entry.val - ICE_AQC_ACL_PROF_BYTE_SEL_START_IDX +
2530                       info->entry.last - 1;
2531                 for (k = end_disp; k < BITS_PER_BYTE; k++)
2532                         dontcare[dst] |= BIT(k);
2533         }
2534 }
2535
2536 /**
2537  * ice_flow_acl_frmt_entry - Format ACL entry
2538  * @hw: pointer to the hardware structure
2539  * @prof: pointer to flow profile
2540  * @e: pointer to the flow entry
2541  * @data: pointer to a data buffer containing flow entry's match values/masks
2542  * @acts: array of actions to be performed on a match
2543  * @acts_cnt: number of actions
2544  *
2545  * Formats the key (and key_inverse) to be matched from the data passed in,
2546  * along with data from the flow profile. This key/key_inverse pair makes up
2547  * the 'entry' for an ACL flow entry.
2548  */
2549 static enum ice_status
2550 ice_flow_acl_frmt_entry(struct ice_hw *hw, struct ice_flow_prof *prof,
2551                         struct ice_flow_entry *e, u8 *data,
2552                         struct ice_flow_action *acts, u8 acts_cnt)
2553 {
2554         u8 *buf = NULL, *dontcare = NULL, *key = NULL, range = 0, dir_flag_msk;
2555         struct ice_aqc_acl_profile_ranges *range_buf = NULL;
2556         enum ice_status status;
2557         bool cnt_alloc;
2558         u8 prof_id = 0;
2559         u16 i, buf_sz;
2560
2561         status = ice_flow_get_hw_prof(hw, ICE_BLK_ACL, prof->id, &prof_id);
2562         if (status)
2563                 return status;
2564
2565         /* Format the result action */
2566
2567         status = ice_flow_acl_check_actions(hw, acts, acts_cnt, &cnt_alloc);
2568         if (status)
2569                 return status;
2570
2571         status = ICE_ERR_NO_MEMORY;
2572
2573         e->acts = (struct ice_flow_action *)
2574                 ice_memdup(hw, acts, acts_cnt * sizeof(*acts),
2575                            ICE_NONDMA_TO_NONDMA);
2576         if (!e->acts)
2577                 goto out;
2578
2579         e->acts_cnt = acts_cnt;
2580
2581         /* Format the matching data */
2582         buf_sz = prof->cfg.scen->width;
2583         buf = (u8 *)ice_malloc(hw, buf_sz);
2584         if (!buf)
2585                 goto out;
2586
2587         dontcare = (u8 *)ice_malloc(hw, buf_sz);
2588         if (!dontcare)
2589                 goto out;
2590
2591         /* 'key' buffer will store both key and key_inverse, so must be twice
2592          * size of buf
2593          */
2594         key = (u8 *)ice_malloc(hw, buf_sz * 2);
2595         if (!key)
2596                 goto out;
2597
2598         range_buf = (struct ice_aqc_acl_profile_ranges *)
2599                 ice_malloc(hw, sizeof(struct ice_aqc_acl_profile_ranges));
2600         if (!range_buf)
2601                 goto out;
2602
2603         /* Set don't care mask to all 1's to start, will zero out used bytes */
2604         ice_memset(dontcare, 0xff, buf_sz, ICE_NONDMA_MEM);
2605
2606         for (i = 0; i < prof->segs_cnt; i++) {
2607                 struct ice_flow_seg_info *seg = &prof->segs[i];
2608                 u8 j;
2609
2610                 ice_for_each_set_bit(j, (ice_bitmap_t *)&seg->match,
2611                                      ICE_FLOW_FIELD_IDX_MAX) {
2612                         struct ice_flow_fld_info *info = &seg->fields[j];
2613
2614                         if (info->type == ICE_FLOW_FLD_TYPE_RANGE)
2615                                 ice_flow_acl_frmt_entry_range(j, info,
2616                                                               range_buf, data,
2617                                                               &range);
2618                         else
2619                                 ice_flow_acl_frmt_entry_fld(j, info, buf,
2620                                                             dontcare, data);
2621                 }
2622
2623                 for (j = 0; j < seg->raws_cnt; j++) {
2624                         struct ice_flow_fld_info *info = &seg->raws[j].info;
2625                         u16 dst, src, mask, k;
2626                         bool use_mask = false;
2627
2628                         src = info->src.val;
2629                         dst = info->entry.val -
2630                                         ICE_AQC_ACL_PROF_BYTE_SEL_START_IDX;
2631                         mask = info->src.mask;
2632
2633                         if (mask != ICE_FLOW_FLD_OFF_INVAL)
2634                                 use_mask = true;
2635
2636                         for (k = 0; k < info->entry.last; k++, dst++) {
2637                                 buf[dst] = data[src++];
2638                                 if (use_mask)
2639                                         dontcare[dst] = ~data[mask++];
2640                                 else
2641                                         dontcare[dst] = 0;
2642                         }
2643                 }
2644         }
2645
2646         buf[prof->cfg.scen->pid_idx] = (u8)prof_id;
2647         dontcare[prof->cfg.scen->pid_idx] = 0;
2648
2649         /* Format the buffer for direction flags */
2650         dir_flag_msk = BIT(ICE_FLG_PKT_DIR);
2651
2652         if (prof->dir == ICE_FLOW_RX)
2653                 buf[prof->cfg.scen->pkt_dir_idx] = dir_flag_msk;
2654
2655         if (range) {
2656                 buf[prof->cfg.scen->rng_chk_idx] = range;
2657                 /* Mark any unused range checkers as don't care */
2658                 dontcare[prof->cfg.scen->rng_chk_idx] = ~range;
2659                 e->range_buf = range_buf;
2660         } else {
2661                 ice_free(hw, range_buf);
2662         }
2663
2664         status = ice_set_key(key, buf_sz * 2, buf, NULL, dontcare, NULL, 0,
2665                              buf_sz);
2666         if (status)
2667                 goto out;
2668
2669         e->entry = key;
2670         e->entry_sz = buf_sz * 2;
2671
2672 out:
2673         if (buf)
2674                 ice_free(hw, buf);
2675
2676         if (dontcare)
2677                 ice_free(hw, dontcare);
2678
2679         if (status && key)
2680                 ice_free(hw, key);
2681
2682         if (status && range_buf) {
2683                 ice_free(hw, range_buf);
2684                 e->range_buf = NULL;
2685         }
2686
2687         if (status && e->acts) {
2688                 ice_free(hw, e->acts);
2689                 e->acts = NULL;
2690                 e->acts_cnt = 0;
2691         }
2692
2693         if (status && cnt_alloc)
2694                 ice_flow_acl_free_act_cntr(hw, acts, acts_cnt);
2695
2696         return status;
2697 }
2698
2699 /**
2700  * ice_flow_acl_find_scen_entry_cond - Find an ACL scenario entry that matches
2701  *                                     the compared data.
2702  * @prof: pointer to flow profile
2703  * @e: pointer to the comparing flow entry
2704  * @do_chg_action: decide if we want to change the ACL action
2705  * @do_add_entry: decide if we want to add the new ACL entry
2706  * @do_rem_entry: decide if we want to remove the current ACL entry
2707  *
2708  * Find an ACL scenario entry that matches the compared data. In the same time,
2709  * this function also figure out:
2710  * a/ If we want to change the ACL action
2711  * b/ If we want to add the new ACL entry
2712  * c/ If we want to remove the current ACL entry
2713  */
2714 static struct ice_flow_entry *
2715 ice_flow_acl_find_scen_entry_cond(struct ice_flow_prof *prof,
2716                                   struct ice_flow_entry *e, bool *do_chg_action,
2717                                   bool *do_add_entry, bool *do_rem_entry)
2718 {
2719         struct ice_flow_entry *p, *return_entry = NULL;
2720         u8 i, j;
2721
2722         /* Check if:
2723          * a/ There exists an entry with same matching data, but different
2724          *    priority, then we remove this existing ACL entry. Then, we
2725          *    will add the new entry to the ACL scenario.
2726          * b/ There exists an entry with same matching data, priority, and
2727          *    result action, then we do nothing
2728          * c/ There exists an entry with same matching data, priority, but
2729          *    different, action, then do only change the action's entry.
2730          * d/ Else, we add this new entry to the ACL scenario.
2731          */
2732         *do_chg_action = false;
2733         *do_add_entry = true;
2734         *do_rem_entry = false;
2735         LIST_FOR_EACH_ENTRY(p, &prof->entries, ice_flow_entry, l_entry) {
2736                 if (memcmp(p->entry, e->entry, p->entry_sz))
2737                         continue;
2738
2739                 /* From this point, we have the same matching_data. */
2740                 *do_add_entry = false;
2741                 return_entry = p;
2742
2743                 if (p->priority != e->priority) {
2744                         /* matching data && !priority */
2745                         *do_add_entry = true;
2746                         *do_rem_entry = true;
2747                         break;
2748                 }
2749
2750                 /* From this point, we will have matching_data && priority */
2751                 if (p->acts_cnt != e->acts_cnt)
2752                         *do_chg_action = true;
2753                 for (i = 0; i < p->acts_cnt; i++) {
2754                         bool found_not_match = false;
2755
2756                         for (j = 0; j < e->acts_cnt; j++)
2757                                 if (memcmp(&p->acts[i], &e->acts[j],
2758                                            sizeof(struct ice_flow_action))) {
2759                                         found_not_match = true;
2760                                         break;
2761                                 }
2762
2763                         if (found_not_match) {
2764                                 *do_chg_action = true;
2765                                 break;
2766                         }
2767                 }
2768
2769                 /* (do_chg_action = true) means :
2770                  *    matching_data && priority && !result_action
2771                  * (do_chg_action = false) means :
2772                  *    matching_data && priority && result_action
2773                  */
2774                 break;
2775         }
2776
2777         return return_entry;
2778 }
2779
2780 /**
2781  * ice_flow_acl_convert_to_acl_prio - Convert to ACL priority
2782  * @p: flow priority
2783  */
2784 static enum ice_acl_entry_prio
2785 ice_flow_acl_convert_to_acl_prio(enum ice_flow_priority p)
2786 {
2787         enum ice_acl_entry_prio acl_prio;
2788
2789         switch (p) {
2790         case ICE_FLOW_PRIO_LOW:
2791                 acl_prio = ICE_ACL_PRIO_LOW;
2792                 break;
2793         case ICE_FLOW_PRIO_NORMAL:
2794                 acl_prio = ICE_ACL_PRIO_NORMAL;
2795                 break;
2796         case ICE_FLOW_PRIO_HIGH:
2797                 acl_prio = ICE_ACL_PRIO_HIGH;
2798                 break;
2799         default:
2800                 acl_prio = ICE_ACL_PRIO_NORMAL;
2801                 break;
2802         }
2803
2804         return acl_prio;
2805 }
2806
2807 /**
2808  * ice_flow_acl_union_rng_chk - Perform union operation between two
2809  *                              range-range checker buffers
2810  * @dst_buf: pointer to destination range checker buffer
2811  * @src_buf: pointer to source range checker buffer
2812  *
2813  * For this function, we do the union between dst_buf and src_buf
2814  * range checker buffer, and we will save the result back to dst_buf
2815  */
2816 static enum ice_status
2817 ice_flow_acl_union_rng_chk(struct ice_aqc_acl_profile_ranges *dst_buf,
2818                            struct ice_aqc_acl_profile_ranges *src_buf)
2819 {
2820         u8 i, j;
2821
2822         if (!dst_buf || !src_buf)
2823                 return ICE_ERR_BAD_PTR;
2824
2825         for (i = 0; i < ICE_AQC_ACL_PROF_RANGES_NUM_CFG; i++) {
2826                 struct ice_acl_rng_data *cfg_data = NULL, *in_data;
2827                 bool will_populate = false;
2828
2829                 in_data = &src_buf->checker_cfg[i];
2830
2831                 if (!in_data->mask)
2832                         break;
2833
2834                 for (j = 0; j < ICE_AQC_ACL_PROF_RANGES_NUM_CFG; j++) {
2835                         cfg_data = &dst_buf->checker_cfg[j];
2836
2837                         if (!cfg_data->mask ||
2838                             !memcmp(cfg_data, in_data,
2839                                     sizeof(struct ice_acl_rng_data))) {
2840                                 will_populate = true;
2841                                 break;
2842                         }
2843                 }
2844
2845                 if (will_populate) {
2846                         ice_memcpy(cfg_data, in_data,
2847                                    sizeof(struct ice_acl_rng_data),
2848                                    ICE_NONDMA_TO_NONDMA);
2849                 } else {
2850                         /* No available slot left to program range checker */
2851                         return ICE_ERR_MAX_LIMIT;
2852                 }
2853         }
2854
2855         return ICE_SUCCESS;
2856 }
2857
2858 /**
2859  * ice_flow_acl_add_scen_entry_sync - Add entry to ACL scenario sync
2860  * @hw: pointer to the hardware structure
2861  * @prof: pointer to flow profile
2862  * @entry: double pointer to the flow entry
2863  *
2864  * For this function, we will look at the current added entries in the
2865  * corresponding ACL scenario. Then, we will perform matching logic to
2866  * see if we want to add/modify/do nothing with this new entry.
2867  */
2868 static enum ice_status
2869 ice_flow_acl_add_scen_entry_sync(struct ice_hw *hw, struct ice_flow_prof *prof,
2870                                  struct ice_flow_entry **entry)
2871 {
2872         bool do_add_entry, do_rem_entry, do_chg_action, do_chg_rng_chk;
2873         struct ice_aqc_acl_profile_ranges query_rng_buf, cfg_rng_buf;
2874         struct ice_acl_act_entry *acts = NULL;
2875         struct ice_flow_entry *exist;
2876         enum ice_status status = ICE_SUCCESS;
2877         struct ice_flow_entry *e;
2878         u8 i;
2879
2880         if (!entry || !(*entry) || !prof)
2881                 return ICE_ERR_BAD_PTR;
2882
2883         e = *entry;
2884
2885         do_chg_rng_chk = false;
2886         if (e->range_buf) {
2887                 u8 prof_id = 0;
2888
2889                 status = ice_flow_get_hw_prof(hw, ICE_BLK_ACL, prof->id,
2890                                               &prof_id);
2891                 if (status)
2892                         return status;
2893
2894                 /* Query the current range-checker value in FW */
2895                 status = ice_query_acl_prof_ranges(hw, prof_id, &query_rng_buf,
2896                                                    NULL);
2897                 if (status)
2898                         return status;
2899                 ice_memcpy(&cfg_rng_buf, &query_rng_buf,
2900                            sizeof(struct ice_aqc_acl_profile_ranges),
2901                            ICE_NONDMA_TO_NONDMA);
2902
2903                 /* Generate the new range-checker value */
2904                 status = ice_flow_acl_union_rng_chk(&cfg_rng_buf, e->range_buf);
2905                 if (status)
2906                         return status;
2907
2908                 /* Reconfigure the range check if the buffer is changed. */
2909                 do_chg_rng_chk = false;
2910                 if (memcmp(&query_rng_buf, &cfg_rng_buf,
2911                            sizeof(struct ice_aqc_acl_profile_ranges))) {
2912                         status = ice_prog_acl_prof_ranges(hw, prof_id,
2913                                                           &cfg_rng_buf, NULL);
2914                         if (status)
2915                                 return status;
2916
2917                         do_chg_rng_chk = true;
2918                 }
2919         }
2920
2921         /* Figure out if we want to (change the ACL action) and/or
2922          * (Add the new ACL entry) and/or (Remove the current ACL entry)
2923          */
2924         exist = ice_flow_acl_find_scen_entry_cond(prof, e, &do_chg_action,
2925                                                   &do_add_entry, &do_rem_entry);
2926         if (do_rem_entry) {
2927                 status = ice_flow_rem_entry_sync(hw, ICE_BLK_ACL, exist);
2928                 if (status)
2929                         return status;
2930         }
2931
2932         /* Prepare the result action buffer */
2933         acts = (struct ice_acl_act_entry *)
2934                 ice_calloc(hw, e->entry_sz, sizeof(struct ice_acl_act_entry));
2935         if (!acts)
2936                 return ICE_ERR_NO_MEMORY;
2937
2938         for (i = 0; i < e->acts_cnt; i++)
2939                 ice_memcpy(&acts[i], &e->acts[i].data.acl_act,
2940                            sizeof(struct ice_acl_act_entry),
2941                            ICE_NONDMA_TO_NONDMA);
2942
2943         if (do_add_entry) {
2944                 enum ice_acl_entry_prio prio;
2945                 u8 *keys, *inverts;
2946                 u16 entry_idx;
2947
2948                 keys = (u8 *)e->entry;
2949                 inverts = keys + (e->entry_sz / 2);
2950                 prio = ice_flow_acl_convert_to_acl_prio(e->priority);
2951
2952                 status = ice_acl_add_entry(hw, prof->cfg.scen, prio, keys,
2953                                            inverts, acts, e->acts_cnt,
2954                                            &entry_idx);
2955                 if (status)
2956                         goto out;
2957
2958                 e->scen_entry_idx = entry_idx;
2959                 LIST_ADD(&e->l_entry, &prof->entries);
2960         } else {
2961                 if (do_chg_action) {
2962                         /* For the action memory info, update the SW's copy of
2963                          * exist entry with e's action memory info
2964                          */
2965                         ice_free(hw, exist->acts);
2966                         exist->acts_cnt = e->acts_cnt;
2967                         exist->acts = (struct ice_flow_action *)
2968                                 ice_calloc(hw, exist->acts_cnt,
2969                                            sizeof(struct ice_flow_action));
2970                         if (!exist->acts) {
2971                                 status = ICE_ERR_NO_MEMORY;
2972                                 goto out;
2973                         }
2974
2975                         ice_memcpy(exist->acts, e->acts,
2976                                    sizeof(struct ice_flow_action) * e->acts_cnt,
2977                                    ICE_NONDMA_TO_NONDMA);
2978
2979                         status = ice_acl_prog_act(hw, prof->cfg.scen, acts,
2980                                                   e->acts_cnt,
2981                                                   exist->scen_entry_idx);
2982                         if (status)
2983                                 goto out;
2984                 }
2985
2986                 if (do_chg_rng_chk) {
2987                         /* In this case, we want to update the range checker
2988                          * information of the exist entry
2989                          */
2990                         status = ice_flow_acl_union_rng_chk(exist->range_buf,
2991                                                             e->range_buf);
2992                         if (status)
2993                                 goto out;
2994                 }
2995
2996                 /* As we don't add the new entry to our SW DB, deallocate its
2997                  * memories, and return the exist entry to the caller
2998                  */
2999                 ice_dealloc_flow_entry(hw, e);
3000                 *(entry) = exist;
3001         }
3002 out:
3003         ice_free(hw, acts);
3004
3005         return status;
3006 }
3007
3008 /**
3009  * ice_flow_acl_add_scen_entry - Add entry to ACL scenario
3010  * @hw: pointer to the hardware structure
3011  * @prof: pointer to flow profile
3012  * @e: double pointer to the flow entry
3013  */
3014 static enum ice_status
3015 ice_flow_acl_add_scen_entry(struct ice_hw *hw, struct ice_flow_prof *prof,
3016                             struct ice_flow_entry **e)
3017 {
3018         enum ice_status status;
3019
3020         ice_acquire_lock(&prof->entries_lock);
3021         status = ice_flow_acl_add_scen_entry_sync(hw, prof, e);
3022         ice_release_lock(&prof->entries_lock);
3023
3024         return status;
3025 }
3026
3027 /**
3028  * ice_flow_add_entry - Add a flow entry
3029  * @hw: pointer to the HW struct
3030  * @blk: classification stage
3031  * @prof_id: ID of the profile to add a new flow entry to
3032  * @entry_id: unique ID to identify this flow entry
3033  * @vsi_handle: software VSI handle for the flow entry
3034  * @prio: priority of the flow entry
3035  * @data: pointer to a data buffer containing flow entry's match values/masks
3036  * @acts: arrays of actions to be performed on a match
3037  * @acts_cnt: number of actions
3038  * @entry_h: pointer to buffer that receives the new flow entry's handle
3039  */
3040 enum ice_status
3041 ice_flow_add_entry(struct ice_hw *hw, enum ice_block blk, u64 prof_id,
3042                    u64 entry_id, u16 vsi_handle, enum ice_flow_priority prio,
3043                    void *data, struct ice_flow_action *acts, u8 acts_cnt,
3044                    u64 *entry_h)
3045 {
3046         struct ice_flow_entry *e = NULL;
3047         struct ice_flow_prof *prof;
3048         enum ice_status status = ICE_SUCCESS;
3049
3050         /* ACL entries must indicate an action */
3051         if (blk == ICE_BLK_ACL && (!acts || !acts_cnt))
3052                 return ICE_ERR_PARAM;
3053
3054         /* No flow entry data is expected for RSS */
3055         if (!entry_h || (!data && blk != ICE_BLK_RSS))
3056                 return ICE_ERR_BAD_PTR;
3057
3058         if (!ice_is_vsi_valid(hw, vsi_handle))
3059                 return ICE_ERR_PARAM;
3060
3061         ice_acquire_lock(&hw->fl_profs_locks[blk]);
3062
3063         prof = ice_flow_find_prof_id(hw, blk, prof_id);
3064         if (!prof) {
3065                 status = ICE_ERR_DOES_NOT_EXIST;
3066         } else {
3067                 /* Allocate memory for the entry being added and associate
3068                  * the VSI to the found flow profile
3069                  */
3070                 e = (struct ice_flow_entry *)ice_malloc(hw, sizeof(*e));
3071                 if (!e)
3072                         status = ICE_ERR_NO_MEMORY;
3073                 else
3074                         status = ice_flow_assoc_prof(hw, blk, prof, vsi_handle);
3075         }
3076
3077         ice_release_lock(&hw->fl_profs_locks[blk]);
3078         if (status)
3079                 goto out;
3080
3081         e->id = entry_id;
3082         e->vsi_handle = vsi_handle;
3083         e->prof = prof;
3084         e->priority = prio;
3085
3086         switch (blk) {
3087         case ICE_BLK_FD:
3088         case ICE_BLK_RSS:
3089                 break;
3090         case ICE_BLK_ACL:
3091                 /* ACL will handle the entry management */
3092                 status = ice_flow_acl_frmt_entry(hw, prof, e, (u8 *)data, acts,
3093                                                  acts_cnt);
3094                 if (status)
3095                         goto out;
3096
3097                 status = ice_flow_acl_add_scen_entry(hw, prof, &e);
3098                 if (status)
3099                         goto out;
3100
3101                 break;
3102         default:
3103                 status = ICE_ERR_NOT_IMPL;
3104                 goto out;
3105         }
3106
3107         if (blk != ICE_BLK_ACL) {
3108                 /* ACL will handle the entry management */
3109                 ice_acquire_lock(&prof->entries_lock);
3110                 LIST_ADD(&e->l_entry, &prof->entries);
3111                 ice_release_lock(&prof->entries_lock);
3112         }
3113
3114         *entry_h = ICE_FLOW_ENTRY_HNDL(e);
3115
3116 out:
3117         if (status && e) {
3118                 if (e->entry)
3119                         ice_free(hw, e->entry);
3120                 ice_free(hw, e);
3121         }
3122
3123         return status;
3124 }
3125
3126 /**
3127  * ice_flow_rem_entry - Remove a flow entry
3128  * @hw: pointer to the HW struct
3129  * @blk: classification stage
3130  * @entry_h: handle to the flow entry to be removed
3131  */
3132 enum ice_status ice_flow_rem_entry(struct ice_hw *hw, enum ice_block blk,
3133                                    u64 entry_h)
3134 {
3135         struct ice_flow_entry *entry;
3136         struct ice_flow_prof *prof;
3137         enum ice_status status = ICE_SUCCESS;
3138
3139         if (entry_h == ICE_FLOW_ENTRY_HANDLE_INVAL)
3140                 return ICE_ERR_PARAM;
3141
3142         entry = ICE_FLOW_ENTRY_PTR((unsigned long)entry_h);
3143
3144         /* Retain the pointer to the flow profile as the entry will be freed */
3145         prof = entry->prof;
3146
3147         if (prof) {
3148                 ice_acquire_lock(&prof->entries_lock);
3149                 status = ice_flow_rem_entry_sync(hw, blk, entry);
3150                 ice_release_lock(&prof->entries_lock);
3151         }
3152
3153         return status;
3154 }
3155
3156 /**
3157  * ice_flow_set_fld_ext - specifies locations of field from entry's input buffer
3158  * @seg: packet segment the field being set belongs to
3159  * @fld: field to be set
3160  * @field_type: type of the field
3161  * @val_loc: if not ICE_FLOW_FLD_OFF_INVAL, location of the value to match from
3162  *           entry's input buffer
3163  * @mask_loc: if not ICE_FLOW_FLD_OFF_INVAL, location of mask value from entry's
3164  *            input buffer
3165  * @last_loc: if not ICE_FLOW_FLD_OFF_INVAL, location of last/upper value from
3166  *            entry's input buffer
3167  *
3168  * This helper function stores information of a field being matched, including
3169  * the type of the field and the locations of the value to match, the mask, and
3170  * the upper-bound value in the start of the input buffer for a flow entry.
3171  * This function should only be used for fixed-size data structures.
3172  *
3173  * This function also opportunistically determines the protocol headers to be
3174  * present based on the fields being set. Some fields cannot be used alone to
3175  * determine the protocol headers present. Sometimes, fields for particular
3176  * protocol headers are not matched. In those cases, the protocol headers
3177  * must be explicitly set.
3178  */
3179 static void
3180 ice_flow_set_fld_ext(struct ice_flow_seg_info *seg, enum ice_flow_field fld,
3181                      enum ice_flow_fld_match_type field_type, u16 val_loc,
3182                      u16 mask_loc, u16 last_loc)
3183 {
3184         u64 bit = BIT_ULL(fld);
3185
3186         seg->match |= bit;
3187         if (field_type == ICE_FLOW_FLD_TYPE_RANGE)
3188                 seg->range |= bit;
3189
3190         seg->fields[fld].type = field_type;
3191         seg->fields[fld].src.val = val_loc;
3192         seg->fields[fld].src.mask = mask_loc;
3193         seg->fields[fld].src.last = last_loc;
3194
3195         ICE_FLOW_SET_HDRS(seg, ice_flds_info[fld].hdr);
3196 }
3197
3198 /**
3199  * ice_flow_set_fld - specifies locations of field from entry's input buffer
3200  * @seg: packet segment the field being set belongs to
3201  * @fld: field to be set
3202  * @val_loc: if not ICE_FLOW_FLD_OFF_INVAL, location of the value to match from
3203  *           entry's input buffer
3204  * @mask_loc: if not ICE_FLOW_FLD_OFF_INVAL, location of mask value from entry's
3205  *            input buffer
3206  * @last_loc: if not ICE_FLOW_FLD_OFF_INVAL, location of last/upper value from
3207  *            entry's input buffer
3208  * @range: indicate if field being matched is to be in a range
3209  *
3210  * This function specifies the locations, in the form of byte offsets from the
3211  * start of the input buffer for a flow entry, from where the value to match,
3212  * the mask value, and upper value can be extracted. These locations are then
3213  * stored in the flow profile. When adding a flow entry associated with the
3214  * flow profile, these locations will be used to quickly extract the values and
3215  * create the content of a match entry. This function should only be used for
3216  * fixed-size data structures.
3217  */
3218 void
3219 ice_flow_set_fld(struct ice_flow_seg_info *seg, enum ice_flow_field fld,
3220                  u16 val_loc, u16 mask_loc, u16 last_loc, bool range)
3221 {
3222         enum ice_flow_fld_match_type t = range ?
3223                 ICE_FLOW_FLD_TYPE_RANGE : ICE_FLOW_FLD_TYPE_REG;
3224
3225         ice_flow_set_fld_ext(seg, fld, t, val_loc, mask_loc, last_loc);
3226 }
3227
3228 /**
3229  * ice_flow_set_fld_prefix - sets locations of prefix field from entry's buf
3230  * @seg: packet segment the field being set belongs to
3231  * @fld: field to be set
3232  * @val_loc: if not ICE_FLOW_FLD_OFF_INVAL, location of the value to match from
3233  *           entry's input buffer
3234  * @pref_loc: location of prefix value from entry's input buffer
3235  * @pref_sz: size of the location holding the prefix value
3236  *
3237  * This function specifies the locations, in the form of byte offsets from the
3238  * start of the input buffer for a flow entry, from where the value to match
3239  * and the IPv4 prefix value can be extracted. These locations are then stored
3240  * in the flow profile. When adding flow entries to the associated flow profile,
3241  * these locations can be used to quickly extract the values to create the
3242  * content of a match entry. This function should only be used for fixed-size
3243  * data structures.
3244  */
3245 void
3246 ice_flow_set_fld_prefix(struct ice_flow_seg_info *seg, enum ice_flow_field fld,
3247                         u16 val_loc, u16 pref_loc, u8 pref_sz)
3248 {
3249         /* For this type of field, the "mask" location is for the prefix value's
3250          * location and the "last" location is for the size of the location of
3251          * the prefix value.
3252          */
3253         ice_flow_set_fld_ext(seg, fld, ICE_FLOW_FLD_TYPE_PREFIX, val_loc,
3254                              pref_loc, (u16)pref_sz);
3255 }
3256
3257 /**
3258  * ice_flow_add_fld_raw - sets locations of a raw field from entry's input buf
3259  * @seg: packet segment the field being set belongs to
3260  * @off: offset of the raw field from the beginning of the segment in bytes
3261  * @len: length of the raw pattern to be matched
3262  * @val_loc: location of the value to match from entry's input buffer
3263  * @mask_loc: location of mask value from entry's input buffer
3264  *
3265  * This function specifies the offset of the raw field to be match from the
3266  * beginning of the specified packet segment, and the locations, in the form of
3267  * byte offsets from the start of the input buffer for a flow entry, from where
3268  * the value to match and the mask value to be extracted. These locations are
3269  * then stored in the flow profile. When adding flow entries to the associated
3270  * flow profile, these locations can be used to quickly extract the values to
3271  * create the content of a match entry. This function should only be used for
3272  * fixed-size data structures.
3273  */
3274 void
3275 ice_flow_add_fld_raw(struct ice_flow_seg_info *seg, u16 off, u8 len,
3276                      u16 val_loc, u16 mask_loc)
3277 {
3278         if (seg->raws_cnt < ICE_FLOW_SEG_RAW_FLD_MAX) {
3279                 seg->raws[seg->raws_cnt].off = off;
3280                 seg->raws[seg->raws_cnt].info.type = ICE_FLOW_FLD_TYPE_SIZE;
3281                 seg->raws[seg->raws_cnt].info.src.val = val_loc;
3282                 seg->raws[seg->raws_cnt].info.src.mask = mask_loc;
3283                 /* The "last" field is used to store the length of the field */
3284                 seg->raws[seg->raws_cnt].info.src.last = len;
3285         }
3286
3287         /* Overflows of "raws" will be handled as an error condition later in
3288          * the flow when this information is processed.
3289          */
3290         seg->raws_cnt++;
3291 }
3292
3293 #define ICE_FLOW_RSS_SEG_HDR_L2_MASKS \
3294 (ICE_FLOW_SEG_HDR_ETH | ICE_FLOW_SEG_HDR_VLAN)
3295
3296 #define ICE_FLOW_RSS_SEG_HDR_L3_MASKS \
3297         (ICE_FLOW_SEG_HDR_IPV4 | ICE_FLOW_SEG_HDR_IPV6)
3298
3299 #define ICE_FLOW_RSS_SEG_HDR_L4_MASKS \
3300         (ICE_FLOW_SEG_HDR_TCP | ICE_FLOW_SEG_HDR_UDP | ICE_FLOW_SEG_HDR_SCTP)
3301
3302 #define ICE_FLOW_RSS_SEG_HDR_VAL_MASKS \
3303         (ICE_FLOW_RSS_SEG_HDR_L2_MASKS | \
3304          ICE_FLOW_RSS_SEG_HDR_L3_MASKS | \
3305          ICE_FLOW_RSS_SEG_HDR_L4_MASKS)
3306
3307 /**
3308  * ice_flow_set_rss_seg_info - setup packet segments for RSS
3309  * @segs: pointer to the flow field segment(s)
3310  * @seg_cnt: segment count
3311  * @cfg: configure parameters
3312  *
3313  * Helper function to extract fields from hash bitmap and use flow
3314  * header value to set flow field segment for further use in flow
3315  * profile entry or removal.
3316  */
3317 static enum ice_status
3318 ice_flow_set_rss_seg_info(struct ice_flow_seg_info *segs, u8 seg_cnt,
3319                           const struct ice_rss_hash_cfg *cfg)
3320 {
3321         struct ice_flow_seg_info *seg;
3322         u64 val;
3323         u8 i;
3324
3325         /* set inner most segment */
3326         seg = &segs[seg_cnt - 1];
3327
3328         ice_for_each_set_bit(i, (const ice_bitmap_t *)&cfg->hash_flds,
3329                              ICE_FLOW_FIELD_IDX_MAX)
3330                 ice_flow_set_fld(seg, (enum ice_flow_field)i,
3331                                  ICE_FLOW_FLD_OFF_INVAL, ICE_FLOW_FLD_OFF_INVAL,
3332                                  ICE_FLOW_FLD_OFF_INVAL, false);
3333
3334         ICE_FLOW_SET_HDRS(seg, cfg->addl_hdrs);
3335
3336         /* set outer most header */
3337         if (cfg->hdr_type == ICE_RSS_INNER_HEADERS_W_OUTER_IPV4)
3338                 segs[ICE_RSS_OUTER_HEADERS].hdrs |= ICE_FLOW_SEG_HDR_IPV4 |
3339                                                    ICE_FLOW_SEG_HDR_IPV_OTHER;
3340         else if (cfg->hdr_type == ICE_RSS_INNER_HEADERS_W_OUTER_IPV6)
3341                 segs[ICE_RSS_OUTER_HEADERS].hdrs |= ICE_FLOW_SEG_HDR_IPV6 |
3342                                                    ICE_FLOW_SEG_HDR_IPV_OTHER;
3343
3344         if (seg->hdrs & ~ICE_FLOW_RSS_SEG_HDR_VAL_MASKS &
3345             ~ICE_FLOW_RSS_HDRS_INNER_MASK & ~ICE_FLOW_SEG_HDR_IPV_OTHER)
3346                 return ICE_ERR_PARAM;
3347
3348         val = (u64)(seg->hdrs & ICE_FLOW_RSS_SEG_HDR_L3_MASKS);
3349         if (val && !ice_is_pow2(val))
3350                 return ICE_ERR_CFG;
3351
3352         val = (u64)(seg->hdrs & ICE_FLOW_RSS_SEG_HDR_L4_MASKS);
3353         if (val && !ice_is_pow2(val))
3354                 return ICE_ERR_CFG;
3355
3356         return ICE_SUCCESS;
3357 }
3358
3359 /**
3360  * ice_rem_vsi_rss_list - remove VSI from RSS list
3361  * @hw: pointer to the hardware structure
3362  * @vsi_handle: software VSI handle
3363  *
3364  * Remove the VSI from all RSS configurations in the list.
3365  */
3366 void ice_rem_vsi_rss_list(struct ice_hw *hw, u16 vsi_handle)
3367 {
3368         struct ice_rss_cfg *r, *tmp;
3369
3370         if (LIST_EMPTY(&hw->rss_list_head))
3371                 return;
3372
3373         ice_acquire_lock(&hw->rss_locks);
3374         LIST_FOR_EACH_ENTRY_SAFE(r, tmp, &hw->rss_list_head,
3375                                  ice_rss_cfg, l_entry)
3376                 if (ice_test_and_clear_bit(vsi_handle, r->vsis))
3377                         if (!ice_is_any_bit_set(r->vsis, ICE_MAX_VSI)) {
3378                                 LIST_DEL(&r->l_entry);
3379                                 ice_free(hw, r);
3380                         }
3381         ice_release_lock(&hw->rss_locks);
3382 }
3383
3384 /**
3385  * ice_rem_vsi_rss_cfg - remove RSS configurations associated with VSI
3386  * @hw: pointer to the hardware structure
3387  * @vsi_handle: software VSI handle
3388  *
3389  * This function will iterate through all flow profiles and disassociate
3390  * the VSI from that profile. If the flow profile has no VSIs it will
3391  * be removed.
3392  */
3393 enum ice_status ice_rem_vsi_rss_cfg(struct ice_hw *hw, u16 vsi_handle)
3394 {
3395         const enum ice_block blk = ICE_BLK_RSS;
3396         struct ice_flow_prof *p, *t;
3397         enum ice_status status = ICE_SUCCESS;
3398
3399         if (!ice_is_vsi_valid(hw, vsi_handle))
3400                 return ICE_ERR_PARAM;
3401
3402         if (LIST_EMPTY(&hw->fl_profs[blk]))
3403                 return ICE_SUCCESS;
3404
3405         ice_acquire_lock(&hw->rss_locks);
3406         LIST_FOR_EACH_ENTRY_SAFE(p, t, &hw->fl_profs[blk], ice_flow_prof,
3407                                  l_entry)
3408                 if (ice_is_bit_set(p->vsis, vsi_handle)) {
3409                         status = ice_flow_disassoc_prof(hw, blk, p, vsi_handle);
3410                         if (status)
3411                                 break;
3412
3413                         if (!ice_is_any_bit_set(p->vsis, ICE_MAX_VSI)) {
3414                                 status = ice_flow_rem_prof(hw, blk, p->id);
3415                                 if (status)
3416                                         break;
3417                         }
3418                 }
3419         ice_release_lock(&hw->rss_locks);
3420
3421         return status;
3422 }
3423
3424 /**
3425  * ice_get_rss_hdr_type - get a RSS profile's header type
3426  * @prof: RSS flow profile
3427  */
3428 static enum ice_rss_cfg_hdr_type
3429 ice_get_rss_hdr_type(struct ice_flow_prof *prof)
3430 {
3431         enum ice_rss_cfg_hdr_type hdr_type = ICE_RSS_ANY_HEADERS;
3432
3433         if (prof->segs_cnt == ICE_FLOW_SEG_SINGLE) {
3434                 hdr_type = ICE_RSS_OUTER_HEADERS;
3435         } else if (prof->segs_cnt == ICE_FLOW_SEG_MAX) {
3436                 if (prof->segs[ICE_RSS_OUTER_HEADERS].hdrs == ICE_FLOW_SEG_HDR_NONE)
3437                         hdr_type = ICE_RSS_INNER_HEADERS;
3438                 if (prof->segs[ICE_RSS_OUTER_HEADERS].hdrs & ICE_FLOW_SEG_HDR_IPV4)
3439                         hdr_type = ICE_RSS_INNER_HEADERS_W_OUTER_IPV4;
3440                 if (prof->segs[ICE_RSS_OUTER_HEADERS].hdrs & ICE_FLOW_SEG_HDR_IPV6)
3441                         hdr_type = ICE_RSS_INNER_HEADERS_W_OUTER_IPV6;
3442         }
3443
3444         return hdr_type;
3445 }
3446
3447 /**
3448  * ice_rem_rss_list - remove RSS configuration from list
3449  * @hw: pointer to the hardware structure
3450  * @vsi_handle: software VSI handle
3451  * @prof: pointer to flow profile
3452  *
3453  * Assumption: lock has already been acquired for RSS list
3454  */
3455 static void
3456 ice_rem_rss_list(struct ice_hw *hw, u16 vsi_handle, struct ice_flow_prof *prof)
3457 {
3458         enum ice_rss_cfg_hdr_type hdr_type;
3459         struct ice_rss_cfg *r, *tmp;
3460
3461         /* Search for RSS hash fields associated to the VSI that match the
3462          * hash configurations associated to the flow profile. If found
3463          * remove from the RSS entry list of the VSI context and delete entry.
3464          */
3465         hdr_type = ice_get_rss_hdr_type(prof);
3466         LIST_FOR_EACH_ENTRY_SAFE(r, tmp, &hw->rss_list_head,
3467                                  ice_rss_cfg, l_entry)
3468                 if (r->hash.hash_flds == prof->segs[prof->segs_cnt - 1].match &&
3469                     r->hash.addl_hdrs == prof->segs[prof->segs_cnt - 1].hdrs &&
3470                     r->hash.hdr_type == hdr_type) {
3471                         ice_clear_bit(vsi_handle, r->vsis);
3472                         if (!ice_is_any_bit_set(r->vsis, ICE_MAX_VSI)) {
3473                                 LIST_DEL(&r->l_entry);
3474                                 ice_free(hw, r);
3475                         }
3476                         return;
3477                 }
3478 }
3479
3480 /**
3481  * ice_add_rss_list - add RSS configuration to list
3482  * @hw: pointer to the hardware structure
3483  * @vsi_handle: software VSI handle
3484  * @prof: pointer to flow profile
3485  *
3486  * Assumption: lock has already been acquired for RSS list
3487  */
3488 static enum ice_status
3489 ice_add_rss_list(struct ice_hw *hw, u16 vsi_handle, struct ice_flow_prof *prof)
3490 {
3491         enum ice_rss_cfg_hdr_type hdr_type;
3492         struct ice_rss_cfg *r, *rss_cfg;
3493
3494         hdr_type = ice_get_rss_hdr_type(prof);
3495         LIST_FOR_EACH_ENTRY(r, &hw->rss_list_head,
3496                             ice_rss_cfg, l_entry)
3497                 if (r->hash.hash_flds == prof->segs[prof->segs_cnt - 1].match &&
3498                     r->hash.addl_hdrs == prof->segs[prof->segs_cnt - 1].hdrs &&
3499                     r->hash.hdr_type == hdr_type) {
3500                         ice_set_bit(vsi_handle, r->vsis);
3501                         return ICE_SUCCESS;
3502                 }
3503
3504         rss_cfg = (struct ice_rss_cfg *)ice_malloc(hw, sizeof(*rss_cfg));
3505         if (!rss_cfg)
3506                 return ICE_ERR_NO_MEMORY;
3507
3508         rss_cfg->hash.hash_flds = prof->segs[prof->segs_cnt - 1].match;
3509         rss_cfg->hash.addl_hdrs = prof->segs[prof->segs_cnt - 1].hdrs;
3510         rss_cfg->hash.hdr_type = hdr_type;
3511         rss_cfg->hash.symm = prof->cfg.symm;
3512         ice_set_bit(vsi_handle, rss_cfg->vsis);
3513
3514         LIST_ADD_TAIL(&rss_cfg->l_entry, &hw->rss_list_head);
3515
3516         return ICE_SUCCESS;
3517 }
3518
3519 #define ICE_FLOW_PROF_HASH_S    0
3520 #define ICE_FLOW_PROF_HASH_M    (0xFFFFFFFFULL << ICE_FLOW_PROF_HASH_S)
3521 #define ICE_FLOW_PROF_HDR_S     32
3522 #define ICE_FLOW_PROF_HDR_M     (0x3FFFFFFFULL << ICE_FLOW_PROF_HDR_S)
3523 #define ICE_FLOW_PROF_ENCAP_S   62
3524 #define ICE_FLOW_PROF_ENCAP_M   (0x3ULL << ICE_FLOW_PROF_ENCAP_S)
3525
3526 /* Flow profile ID format:
3527  * [0:31] - Packet match fields
3528  * [32:61] - Protocol header
3529  * [62:63] - Encapsulation flag:
3530  *           0 if non-tunneled
3531  *           1 if tunneled
3532  *           2 for tunneled with outer ipv4
3533  *           3 for tunneled with outer ipv6
3534  */
3535 #define ICE_FLOW_GEN_PROFID(hash, hdr, encap) \
3536         ((u64)(((u64)(hash) & ICE_FLOW_PROF_HASH_M) | \
3537                (((u64)(hdr) << ICE_FLOW_PROF_HDR_S) & ICE_FLOW_PROF_HDR_M) | \
3538                (((u64)(encap) << ICE_FLOW_PROF_ENCAP_S) & ICE_FLOW_PROF_ENCAP_M)))
3539
3540 static void
3541 ice_rss_config_xor_word(struct ice_hw *hw, u8 prof_id, u8 src, u8 dst)
3542 {
3543         u32 s = ((src % 4) << 3); /* byte shift */
3544         u32 v = dst | 0x80; /* value to program */
3545         u8 i = src / 4; /* register index */
3546         u32 reg;
3547
3548         reg = rd32(hw, GLQF_HSYMM(prof_id, i));
3549         reg = (reg & ~(0xff << s)) | (v << s);
3550         wr32(hw, GLQF_HSYMM(prof_id, i), reg);
3551 }
3552
3553 static void
3554 ice_rss_config_xor(struct ice_hw *hw, u8 prof_id, u8 src, u8 dst, u8 len)
3555 {
3556         int fv_last_word =
3557                 ICE_FLOW_SW_FIELD_VECTOR_MAX / ICE_FLOW_FV_EXTRACT_SZ - 1;
3558         int i;
3559
3560         for (i = 0; i < len; i++) {
3561                 ice_rss_config_xor_word(hw, prof_id,
3562                                         /* Yes, field vector in GLQF_HSYMM and
3563                                          * GLQF_HINSET is inversed!
3564                                          */
3565                                         fv_last_word - (src + i),
3566                                         fv_last_word - (dst + i));
3567                 ice_rss_config_xor_word(hw, prof_id,
3568                                         fv_last_word - (dst + i),
3569                                         fv_last_word - (src + i));
3570         }
3571 }
3572
3573 static void
3574 ice_rss_update_symm(struct ice_hw *hw,
3575                     struct ice_flow_prof *prof)
3576 {
3577         struct ice_prof_map *map;
3578         u8 prof_id, m;
3579
3580         ice_acquire_lock(&hw->blk[ICE_BLK_RSS].es.prof_map_lock);
3581         map = ice_search_prof_id(hw, ICE_BLK_RSS, prof->id);
3582         if (map)
3583                 prof_id = map->prof_id;
3584         ice_release_lock(&hw->blk[ICE_BLK_RSS].es.prof_map_lock);
3585         if (!map)
3586                 return;
3587         /* clear to default */
3588         for (m = 0; m < 6; m++)
3589                 wr32(hw, GLQF_HSYMM(prof_id, m), 0);
3590         if (prof->cfg.symm) {
3591                 struct ice_flow_seg_info *seg =
3592                         &prof->segs[prof->segs_cnt - 1];
3593
3594                 struct ice_flow_seg_xtrct *ipv4_src =
3595                         &seg->fields[ICE_FLOW_FIELD_IDX_IPV4_SA].xtrct;
3596                 struct ice_flow_seg_xtrct *ipv4_dst =
3597                         &seg->fields[ICE_FLOW_FIELD_IDX_IPV4_DA].xtrct;
3598                 struct ice_flow_seg_xtrct *ipv6_src =
3599                         &seg->fields[ICE_FLOW_FIELD_IDX_IPV6_SA].xtrct;
3600                 struct ice_flow_seg_xtrct *ipv6_dst =
3601                         &seg->fields[ICE_FLOW_FIELD_IDX_IPV6_DA].xtrct;
3602
3603                 struct ice_flow_seg_xtrct *tcp_src =
3604                         &seg->fields[ICE_FLOW_FIELD_IDX_TCP_SRC_PORT].xtrct;
3605                 struct ice_flow_seg_xtrct *tcp_dst =
3606                         &seg->fields[ICE_FLOW_FIELD_IDX_TCP_DST_PORT].xtrct;
3607
3608                 struct ice_flow_seg_xtrct *udp_src =
3609                         &seg->fields[ICE_FLOW_FIELD_IDX_UDP_SRC_PORT].xtrct;
3610                 struct ice_flow_seg_xtrct *udp_dst =
3611                         &seg->fields[ICE_FLOW_FIELD_IDX_UDP_DST_PORT].xtrct;
3612
3613                 struct ice_flow_seg_xtrct *sctp_src =
3614                         &seg->fields[ICE_FLOW_FIELD_IDX_SCTP_SRC_PORT].xtrct;
3615                 struct ice_flow_seg_xtrct *sctp_dst =
3616                         &seg->fields[ICE_FLOW_FIELD_IDX_SCTP_DST_PORT].xtrct;
3617
3618                 /* xor IPv4 */
3619                 if (ipv4_src->prot_id != 0 && ipv4_dst->prot_id != 0)
3620                         ice_rss_config_xor(hw, prof_id,
3621                                            ipv4_src->idx, ipv4_dst->idx, 2);
3622
3623                 /* xor IPv6 */
3624                 if (ipv6_src->prot_id != 0 && ipv6_dst->prot_id != 0)
3625                         ice_rss_config_xor(hw, prof_id,
3626                                            ipv6_src->idx, ipv6_dst->idx, 8);
3627
3628                 /* xor TCP */
3629                 if (tcp_src->prot_id != 0 && tcp_dst->prot_id != 0)
3630                         ice_rss_config_xor(hw, prof_id,
3631                                            tcp_src->idx, tcp_dst->idx, 1);
3632
3633                 /* xor UDP */
3634                 if (udp_src->prot_id != 0 && udp_dst->prot_id != 0)
3635                         ice_rss_config_xor(hw, prof_id,
3636                                            udp_src->idx, udp_dst->idx, 1);
3637
3638                 /* xor SCTP */
3639                 if (sctp_src->prot_id != 0 && sctp_dst->prot_id != 0)
3640                         ice_rss_config_xor(hw, prof_id,
3641                                            sctp_src->idx, sctp_dst->idx, 1);
3642         }
3643 }
3644
3645 /**
3646  * ice_add_rss_cfg_sync - add an RSS configuration
3647  * @hw: pointer to the hardware structure
3648  * @vsi_handle: software VSI handle
3649  * @cfg: configure parameters
3650  *
3651  * Assumption: lock has already been acquired for RSS list
3652  */
3653 static enum ice_status
3654 ice_add_rss_cfg_sync(struct ice_hw *hw, u16 vsi_handle,
3655                      const struct ice_rss_hash_cfg *cfg)
3656 {
3657         const enum ice_block blk = ICE_BLK_RSS;
3658         struct ice_flow_prof *prof = NULL;
3659         struct ice_flow_seg_info *segs;
3660         enum ice_status status;
3661         u8 segs_cnt;
3662
3663         segs_cnt = (cfg->hdr_type == ICE_RSS_OUTER_HEADERS) ?
3664                         ICE_FLOW_SEG_SINGLE : ICE_FLOW_SEG_MAX;
3665
3666         segs = (struct ice_flow_seg_info *)ice_calloc(hw, segs_cnt,
3667                                                       sizeof(*segs));
3668         if (!segs)
3669                 return ICE_ERR_NO_MEMORY;
3670
3671         /* Construct the packet segment info from the hashed fields */
3672         status = ice_flow_set_rss_seg_info(segs, segs_cnt, cfg);
3673         if (status)
3674                 goto exit;
3675
3676         /* Don't do RSS for GTPU Outer */
3677         if (segs_cnt == ICE_FLOW_SEG_SINGLE &&
3678             segs[segs_cnt - 1].hdrs & ICE_FLOW_SEG_HDR_GTPU) {
3679                 status = ICE_SUCCESS;
3680                 goto exit;
3681         }
3682
3683         /* Search for a flow profile that has matching headers, hash fields
3684          * and has the input VSI associated to it. If found, no further
3685          * operations required and exit.
3686          */
3687         prof = ice_flow_find_prof_conds(hw, blk, ICE_FLOW_RX, segs, segs_cnt,
3688                                         vsi_handle,
3689                                         ICE_FLOW_FIND_PROF_CHK_FLDS |
3690                                         ICE_FLOW_FIND_PROF_CHK_VSI);
3691         if (prof) {
3692                 if (prof->cfg.symm == cfg->symm)
3693                         goto exit;
3694                 prof->cfg.symm = cfg->symm;
3695                 goto update_symm;
3696         }
3697
3698         /* Check if a flow profile exists with the same protocol headers and
3699          * associated with the input VSI. If so disassociate the VSI from
3700          * this profile. The VSI will be added to a new profile created with
3701          * the protocol header and new hash field configuration.
3702          */
3703         prof = ice_flow_find_prof_conds(hw, blk, ICE_FLOW_RX, segs, segs_cnt,
3704                                         vsi_handle, ICE_FLOW_FIND_PROF_CHK_VSI);
3705         if (prof) {
3706                 status = ice_flow_disassoc_prof(hw, blk, prof, vsi_handle);
3707                 if (!status)
3708                         ice_rem_rss_list(hw, vsi_handle, prof);
3709                 else
3710                         goto exit;
3711
3712                 /* Remove profile if it has no VSIs associated */
3713                 if (!ice_is_any_bit_set(prof->vsis, ICE_MAX_VSI)) {
3714                         status = ice_flow_rem_prof(hw, blk, prof->id);
3715                         if (status)
3716                                 goto exit;
3717                 }
3718         }
3719
3720         /* Search for a profile that has same match fields only. If this
3721          * exists then associate the VSI to this profile.
3722          */
3723         prof = ice_flow_find_prof_conds(hw, blk, ICE_FLOW_RX, segs, segs_cnt,
3724                                         vsi_handle,
3725                                         ICE_FLOW_FIND_PROF_CHK_FLDS);
3726         if (prof) {
3727                 if (prof->cfg.symm == cfg->symm) {
3728                         status = ice_flow_assoc_prof(hw, blk, prof,
3729                                                      vsi_handle);
3730                         if (!status)
3731                                 status = ice_add_rss_list(hw, vsi_handle,
3732                                                           prof);
3733                 } else {
3734                         /* if a profile exist but with different symmetric
3735                          * requirement, just return error.
3736                          */
3737                         status = ICE_ERR_NOT_SUPPORTED;
3738                 }
3739                 goto exit;
3740         }
3741
3742         /* Create a new flow profile with generated profile and packet
3743          * segment information.
3744          */
3745         status = ice_flow_add_prof(hw, blk, ICE_FLOW_RX,
3746                                    ICE_FLOW_GEN_PROFID(cfg->hash_flds,
3747                                                        segs[segs_cnt - 1].hdrs,
3748                                                        cfg->hdr_type),
3749                                    segs, segs_cnt, NULL, 0, &prof);
3750         if (status)
3751                 goto exit;
3752
3753         status = ice_flow_assoc_prof(hw, blk, prof, vsi_handle);
3754         /* If association to a new flow profile failed then this profile can
3755          * be removed.
3756          */
3757         if (status) {
3758                 ice_flow_rem_prof(hw, blk, prof->id);
3759                 goto exit;
3760         }
3761
3762         status = ice_add_rss_list(hw, vsi_handle, prof);
3763
3764         prof->cfg.symm = cfg->symm;
3765 update_symm:
3766         ice_rss_update_symm(hw, prof);
3767
3768 exit:
3769         ice_free(hw, segs);
3770         return status;
3771 }
3772
3773 /**
3774  * ice_add_rss_cfg - add an RSS configuration with specified hashed fields
3775  * @hw: pointer to the hardware structure
3776  * @vsi_handle: software VSI handle
3777  * @cfg: configure parameters
3778  *
3779  * This function will generate a flow profile based on fields associated with
3780  * the input fields to hash on, the flow type and use the VSI number to add
3781  * a flow entry to the profile.
3782  */
3783 enum ice_status
3784 ice_add_rss_cfg(struct ice_hw *hw, u16 vsi_handle,
3785                 const struct ice_rss_hash_cfg *cfg)
3786 {
3787         struct ice_rss_hash_cfg local_cfg;
3788         enum ice_status status;
3789
3790         if (!ice_is_vsi_valid(hw, vsi_handle) ||
3791             !cfg || cfg->hdr_type > ICE_RSS_ANY_HEADERS ||
3792             cfg->hash_flds == ICE_HASH_INVALID)
3793                 return ICE_ERR_PARAM;
3794
3795         local_cfg = *cfg;
3796         if (cfg->hdr_type < ICE_RSS_ANY_HEADERS) {
3797                 ice_acquire_lock(&hw->rss_locks);
3798                 status = ice_add_rss_cfg_sync(hw, vsi_handle, &local_cfg);
3799                 ice_release_lock(&hw->rss_locks);
3800         } else {
3801                 ice_acquire_lock(&hw->rss_locks);
3802                 local_cfg.hdr_type = ICE_RSS_OUTER_HEADERS;
3803                 status = ice_add_rss_cfg_sync(hw, vsi_handle, &local_cfg);
3804                 if (!status) {
3805                         local_cfg.hdr_type = ICE_RSS_INNER_HEADERS;
3806                         status = ice_add_rss_cfg_sync(hw, vsi_handle,
3807                                                       &local_cfg);
3808                 }
3809                 ice_release_lock(&hw->rss_locks);
3810         }
3811
3812         return status;
3813 }
3814
3815 /**
3816  * ice_rem_rss_cfg_sync - remove an existing RSS configuration
3817  * @hw: pointer to the hardware structure
3818  * @vsi_handle: software VSI handle
3819  * @cfg: configure parameters
3820  *
3821  * Assumption: lock has already been acquired for RSS list
3822  */
3823 static enum ice_status
3824 ice_rem_rss_cfg_sync(struct ice_hw *hw, u16 vsi_handle,
3825                      const struct ice_rss_hash_cfg *cfg)
3826 {
3827         const enum ice_block blk = ICE_BLK_RSS;
3828         struct ice_flow_seg_info *segs;
3829         struct ice_flow_prof *prof;
3830         enum ice_status status;
3831         u8 segs_cnt;
3832
3833         segs_cnt = (cfg->hdr_type == ICE_RSS_OUTER_HEADERS) ?
3834                         ICE_FLOW_SEG_SINGLE : ICE_FLOW_SEG_MAX;
3835         segs = (struct ice_flow_seg_info *)ice_calloc(hw, segs_cnt,
3836                                                       sizeof(*segs));
3837         if (!segs)
3838                 return ICE_ERR_NO_MEMORY;
3839
3840         /* Construct the packet segment info from the hashed fields */
3841         status = ice_flow_set_rss_seg_info(segs, segs_cnt, cfg);
3842         if (status)
3843                 goto out;
3844
3845         /* Don't do RSS for GTPU Outer */
3846         if (segs_cnt == ICE_FLOW_SEG_SINGLE &&
3847             segs[segs_cnt - 1].hdrs & ICE_FLOW_SEG_HDR_GTPU) {
3848                 status = ICE_SUCCESS;
3849                 goto out;
3850         }
3851
3852         prof = ice_flow_find_prof_conds(hw, blk, ICE_FLOW_RX, segs, segs_cnt,
3853                                         vsi_handle,
3854                                         ICE_FLOW_FIND_PROF_CHK_FLDS);
3855         if (!prof) {
3856                 status = ICE_ERR_DOES_NOT_EXIST;
3857                 goto out;
3858         }
3859
3860         status = ice_flow_disassoc_prof(hw, blk, prof, vsi_handle);
3861         if (status)
3862                 goto out;
3863
3864         /* Remove RSS configuration from VSI context before deleting
3865          * the flow profile.
3866          */
3867         ice_rem_rss_list(hw, vsi_handle, prof);
3868
3869         if (!ice_is_any_bit_set(prof->vsis, ICE_MAX_VSI))
3870                 status = ice_flow_rem_prof(hw, blk, prof->id);
3871
3872 out:
3873         ice_free(hw, segs);
3874         return status;
3875 }
3876
3877 /**
3878  * ice_rem_rss_cfg - remove an existing RSS config with matching hashed fields
3879  * @hw: pointer to the hardware structure
3880  * @vsi_handle: software VSI handle
3881  * @cfg: configure parameters
3882  *
3883  * This function will lookup the flow profile based on the input
3884  * hash field bitmap, iterate through the profile entry list of
3885  * that profile and find entry associated with input VSI to be
3886  * removed. Calls are made to underlying flow apis which will in
3887  * turn build or update buffers for RSS XLT1 section.
3888  */
3889 enum ice_status
3890 ice_rem_rss_cfg(struct ice_hw *hw, u16 vsi_handle,
3891                 const struct ice_rss_hash_cfg *cfg)
3892 {
3893         struct ice_rss_hash_cfg local_cfg;
3894         enum ice_status status;
3895
3896         if (!ice_is_vsi_valid(hw, vsi_handle) ||
3897             !cfg || cfg->hdr_type > ICE_RSS_ANY_HEADERS ||
3898             cfg->hash_flds == ICE_HASH_INVALID)
3899                 return ICE_ERR_PARAM;
3900
3901         ice_acquire_lock(&hw->rss_locks);
3902         local_cfg = *cfg;
3903         if (cfg->hdr_type < ICE_RSS_ANY_HEADERS) {
3904                 status = ice_rem_rss_cfg_sync(hw, vsi_handle, &local_cfg);
3905         } else {
3906                 local_cfg.hdr_type = ICE_RSS_OUTER_HEADERS;
3907                 status = ice_rem_rss_cfg_sync(hw, vsi_handle, &local_cfg);
3908
3909                 if (!status) {
3910                         local_cfg.hdr_type = ICE_RSS_INNER_HEADERS;
3911                         status = ice_rem_rss_cfg_sync(hw, vsi_handle,
3912                                                       &local_cfg);
3913                 }
3914         }
3915         ice_release_lock(&hw->rss_locks);
3916
3917         return status;
3918 }
3919
3920 /**
3921  * ice_replay_rss_cfg - replay RSS configurations associated with VSI
3922  * @hw: pointer to the hardware structure
3923  * @vsi_handle: software VSI handle
3924  */
3925 enum ice_status ice_replay_rss_cfg(struct ice_hw *hw, u16 vsi_handle)
3926 {
3927         enum ice_status status = ICE_SUCCESS;
3928         struct ice_rss_cfg *r;
3929
3930         if (!ice_is_vsi_valid(hw, vsi_handle))
3931                 return ICE_ERR_PARAM;
3932
3933         ice_acquire_lock(&hw->rss_locks);
3934         LIST_FOR_EACH_ENTRY(r, &hw->rss_list_head,
3935                             ice_rss_cfg, l_entry) {
3936                 if (ice_is_bit_set(r->vsis, vsi_handle)) {
3937                         status = ice_add_rss_cfg_sync(hw, vsi_handle, &r->hash);
3938                         if (status)
3939                                 break;
3940                 }
3941         }
3942         ice_release_lock(&hw->rss_locks);
3943
3944         return status;
3945 }
3946
3947 /**
3948  * ice_get_rss_cfg - returns hashed fields for the given header types
3949  * @hw: pointer to the hardware structure
3950  * @vsi_handle: software VSI handle
3951  * @hdrs: protocol header type
3952  *
3953  * This function will return the match fields of the first instance of flow
3954  * profile having the given header types and containing input VSI
3955  */
3956 u64 ice_get_rss_cfg(struct ice_hw *hw, u16 vsi_handle, u32 hdrs)
3957 {
3958         u64 rss_hash = ICE_HASH_INVALID;
3959         struct ice_rss_cfg *r;
3960
3961         /* verify if the protocol header is non zero and VSI is valid */
3962         if (hdrs == ICE_FLOW_SEG_HDR_NONE || !ice_is_vsi_valid(hw, vsi_handle))
3963                 return ICE_HASH_INVALID;
3964
3965         ice_acquire_lock(&hw->rss_locks);
3966         LIST_FOR_EACH_ENTRY(r, &hw->rss_list_head,
3967                             ice_rss_cfg, l_entry)
3968                 if (ice_is_bit_set(r->vsis, vsi_handle) &&
3969                     r->hash.addl_hdrs == hdrs) {
3970                         rss_hash = r->hash.hash_flds;
3971                         break;
3972                 }
3973         ice_release_lock(&hw->rss_locks);
3974
3975         return rss_hash;
3976 }