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