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