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