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