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