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