Loading...
1// SPDX-License-Identifier: GPL-2.0
2/* Copyright (c) 2019, Intel Corporation. */
3
4#include "ice_common.h"
5#include "ice_flow.h"
6#include <net/gre.h>
7
8/* Describe properties of a protocol header field */
9struct ice_flow_field_info {
10 enum ice_flow_seg_hdr hdr;
11 s16 off; /* Offset from start of a protocol header, in bits */
12 u16 size; /* Size of fields in bits */
13 u16 mask; /* 16-bit mask for field */
14};
15
16#define ICE_FLOW_FLD_INFO(_hdr, _offset_bytes, _size_bytes) { \
17 .hdr = _hdr, \
18 .off = (_offset_bytes) * BITS_PER_BYTE, \
19 .size = (_size_bytes) * BITS_PER_BYTE, \
20 .mask = 0, \
21}
22
23#define ICE_FLOW_FLD_INFO_MSK(_hdr, _offset_bytes, _size_bytes, _mask) { \
24 .hdr = _hdr, \
25 .off = (_offset_bytes) * BITS_PER_BYTE, \
26 .size = (_size_bytes) * BITS_PER_BYTE, \
27 .mask = _mask, \
28}
29
30/* Table containing properties of supported protocol header fields */
31static const
32struct ice_flow_field_info ice_flds_info[ICE_FLOW_FIELD_IDX_MAX] = {
33 /* Ether */
34 /* ICE_FLOW_FIELD_IDX_ETH_DA */
35 ICE_FLOW_FLD_INFO(ICE_FLOW_SEG_HDR_ETH, 0, ETH_ALEN),
36 /* ICE_FLOW_FIELD_IDX_ETH_SA */
37 ICE_FLOW_FLD_INFO(ICE_FLOW_SEG_HDR_ETH, ETH_ALEN, ETH_ALEN),
38 /* ICE_FLOW_FIELD_IDX_S_VLAN */
39 ICE_FLOW_FLD_INFO(ICE_FLOW_SEG_HDR_VLAN, 12, sizeof(__be16)),
40 /* ICE_FLOW_FIELD_IDX_C_VLAN */
41 ICE_FLOW_FLD_INFO(ICE_FLOW_SEG_HDR_VLAN, 14, sizeof(__be16)),
42 /* ICE_FLOW_FIELD_IDX_ETH_TYPE */
43 ICE_FLOW_FLD_INFO(ICE_FLOW_SEG_HDR_ETH, 0, sizeof(__be16)),
44 /* IPv4 / IPv6 */
45 /* ICE_FLOW_FIELD_IDX_IPV4_DSCP */
46 ICE_FLOW_FLD_INFO_MSK(ICE_FLOW_SEG_HDR_IPV4, 0, 1, 0x00fc),
47 /* ICE_FLOW_FIELD_IDX_IPV6_DSCP */
48 ICE_FLOW_FLD_INFO_MSK(ICE_FLOW_SEG_HDR_IPV6, 0, 1, 0x0ff0),
49 /* ICE_FLOW_FIELD_IDX_IPV4_TTL */
50 ICE_FLOW_FLD_INFO_MSK(ICE_FLOW_SEG_HDR_NONE, 8, 1, 0xff00),
51 /* ICE_FLOW_FIELD_IDX_IPV4_PROT */
52 ICE_FLOW_FLD_INFO_MSK(ICE_FLOW_SEG_HDR_NONE, 8, 1, 0x00ff),
53 /* ICE_FLOW_FIELD_IDX_IPV6_TTL */
54 ICE_FLOW_FLD_INFO_MSK(ICE_FLOW_SEG_HDR_NONE, 6, 1, 0x00ff),
55 /* ICE_FLOW_FIELD_IDX_IPV6_PROT */
56 ICE_FLOW_FLD_INFO_MSK(ICE_FLOW_SEG_HDR_NONE, 6, 1, 0xff00),
57 /* ICE_FLOW_FIELD_IDX_IPV4_SA */
58 ICE_FLOW_FLD_INFO(ICE_FLOW_SEG_HDR_IPV4, 12, sizeof(struct in_addr)),
59 /* ICE_FLOW_FIELD_IDX_IPV4_DA */
60 ICE_FLOW_FLD_INFO(ICE_FLOW_SEG_HDR_IPV4, 16, sizeof(struct in_addr)),
61 /* ICE_FLOW_FIELD_IDX_IPV6_SA */
62 ICE_FLOW_FLD_INFO(ICE_FLOW_SEG_HDR_IPV6, 8, sizeof(struct in6_addr)),
63 /* ICE_FLOW_FIELD_IDX_IPV6_DA */
64 ICE_FLOW_FLD_INFO(ICE_FLOW_SEG_HDR_IPV6, 24, sizeof(struct in6_addr)),
65 /* Transport */
66 /* ICE_FLOW_FIELD_IDX_TCP_SRC_PORT */
67 ICE_FLOW_FLD_INFO(ICE_FLOW_SEG_HDR_TCP, 0, sizeof(__be16)),
68 /* ICE_FLOW_FIELD_IDX_TCP_DST_PORT */
69 ICE_FLOW_FLD_INFO(ICE_FLOW_SEG_HDR_TCP, 2, sizeof(__be16)),
70 /* ICE_FLOW_FIELD_IDX_UDP_SRC_PORT */
71 ICE_FLOW_FLD_INFO(ICE_FLOW_SEG_HDR_UDP, 0, sizeof(__be16)),
72 /* ICE_FLOW_FIELD_IDX_UDP_DST_PORT */
73 ICE_FLOW_FLD_INFO(ICE_FLOW_SEG_HDR_UDP, 2, sizeof(__be16)),
74 /* ICE_FLOW_FIELD_IDX_SCTP_SRC_PORT */
75 ICE_FLOW_FLD_INFO(ICE_FLOW_SEG_HDR_SCTP, 0, sizeof(__be16)),
76 /* ICE_FLOW_FIELD_IDX_SCTP_DST_PORT */
77 ICE_FLOW_FLD_INFO(ICE_FLOW_SEG_HDR_SCTP, 2, sizeof(__be16)),
78 /* ICE_FLOW_FIELD_IDX_TCP_FLAGS */
79 ICE_FLOW_FLD_INFO(ICE_FLOW_SEG_HDR_TCP, 13, 1),
80 /* ARP */
81 /* ICE_FLOW_FIELD_IDX_ARP_SIP */
82 ICE_FLOW_FLD_INFO(ICE_FLOW_SEG_HDR_ARP, 14, sizeof(struct in_addr)),
83 /* ICE_FLOW_FIELD_IDX_ARP_DIP */
84 ICE_FLOW_FLD_INFO(ICE_FLOW_SEG_HDR_ARP, 24, sizeof(struct in_addr)),
85 /* ICE_FLOW_FIELD_IDX_ARP_SHA */
86 ICE_FLOW_FLD_INFO(ICE_FLOW_SEG_HDR_ARP, 8, ETH_ALEN),
87 /* ICE_FLOW_FIELD_IDX_ARP_DHA */
88 ICE_FLOW_FLD_INFO(ICE_FLOW_SEG_HDR_ARP, 18, ETH_ALEN),
89 /* ICE_FLOW_FIELD_IDX_ARP_OP */
90 ICE_FLOW_FLD_INFO(ICE_FLOW_SEG_HDR_ARP, 6, sizeof(__be16)),
91 /* ICMP */
92 /* ICE_FLOW_FIELD_IDX_ICMP_TYPE */
93 ICE_FLOW_FLD_INFO(ICE_FLOW_SEG_HDR_ICMP, 0, 1),
94 /* ICE_FLOW_FIELD_IDX_ICMP_CODE */
95 ICE_FLOW_FLD_INFO(ICE_FLOW_SEG_HDR_ICMP, 1, 1),
96 /* GRE */
97 /* ICE_FLOW_FIELD_IDX_GRE_KEYID */
98 ICE_FLOW_FLD_INFO(ICE_FLOW_SEG_HDR_GRE, 12,
99 sizeof_field(struct gre_full_hdr, key)),
100 /* GTP */
101 /* ICE_FLOW_FIELD_IDX_GTPC_TEID */
102 ICE_FLOW_FLD_INFO(ICE_FLOW_SEG_HDR_GTPC_TEID, 12, sizeof(__be32)),
103 /* ICE_FLOW_FIELD_IDX_GTPU_IP_TEID */
104 ICE_FLOW_FLD_INFO(ICE_FLOW_SEG_HDR_GTPU_IP, 12, sizeof(__be32)),
105 /* ICE_FLOW_FIELD_IDX_GTPU_EH_TEID */
106 ICE_FLOW_FLD_INFO(ICE_FLOW_SEG_HDR_GTPU_EH, 12, sizeof(__be32)),
107 /* ICE_FLOW_FIELD_IDX_GTPU_EH_QFI */
108 ICE_FLOW_FLD_INFO_MSK(ICE_FLOW_SEG_HDR_GTPU_EH, 22, sizeof(__be16),
109 0x3f00),
110 /* ICE_FLOW_FIELD_IDX_GTPU_UP_TEID */
111 ICE_FLOW_FLD_INFO(ICE_FLOW_SEG_HDR_GTPU_UP, 12, sizeof(__be32)),
112 /* ICE_FLOW_FIELD_IDX_GTPU_DWN_TEID */
113 ICE_FLOW_FLD_INFO(ICE_FLOW_SEG_HDR_GTPU_DWN, 12, sizeof(__be32)),
114 /* PPPoE */
115 /* ICE_FLOW_FIELD_IDX_PPPOE_SESS_ID */
116 ICE_FLOW_FLD_INFO(ICE_FLOW_SEG_HDR_PPPOE, 2, sizeof(__be16)),
117 /* PFCP */
118 /* ICE_FLOW_FIELD_IDX_PFCP_SEID */
119 ICE_FLOW_FLD_INFO(ICE_FLOW_SEG_HDR_PFCP_SESSION, 12, sizeof(__be64)),
120 /* L2TPv3 */
121 /* ICE_FLOW_FIELD_IDX_L2TPV3_SESS_ID */
122 ICE_FLOW_FLD_INFO(ICE_FLOW_SEG_HDR_L2TPV3, 0, sizeof(__be32)),
123 /* ESP */
124 /* ICE_FLOW_FIELD_IDX_ESP_SPI */
125 ICE_FLOW_FLD_INFO(ICE_FLOW_SEG_HDR_ESP, 0, sizeof(__be32)),
126 /* AH */
127 /* ICE_FLOW_FIELD_IDX_AH_SPI */
128 ICE_FLOW_FLD_INFO(ICE_FLOW_SEG_HDR_AH, 4, sizeof(__be32)),
129 /* NAT_T_ESP */
130 /* ICE_FLOW_FIELD_IDX_NAT_T_ESP_SPI */
131 ICE_FLOW_FLD_INFO(ICE_FLOW_SEG_HDR_NAT_T_ESP, 8, sizeof(__be32)),
132};
133
134/* Bitmaps indicating relevant packet types for a particular protocol header
135 *
136 * Packet types for packets with an Outer/First/Single MAC header
137 */
138static const u32 ice_ptypes_mac_ofos[] = {
139 0xFDC00846, 0xBFBF7F7E, 0xF70001DF, 0xFEFDFDFB,
140 0x0000077E, 0x00000000, 0x00000000, 0x00000000,
141 0x00400000, 0x03FFF000, 0x7FFFFFE0, 0x00000000,
142 0x00000000, 0x00000000, 0x00000000, 0x00000000,
143 0x00000000, 0x00000000, 0x00000000, 0x00000000,
144 0x00000000, 0x00000000, 0x00000000, 0x00000000,
145 0x00000000, 0x00000000, 0x00000000, 0x00000000,
146 0x00000000, 0x00000000, 0x00000000, 0x00000000,
147};
148
149/* Packet types for packets with an Innermost/Last MAC VLAN header */
150static const u32 ice_ptypes_macvlan_il[] = {
151 0x00000000, 0xBC000000, 0x000001DF, 0xF0000000,
152 0x0000077E, 0x00000000, 0x00000000, 0x00000000,
153 0x00000000, 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};
160
161/* Packet types for packets with an Outer/First/Single IPv4 header, does NOT
162 * include IPv4 other PTYPEs
163 */
164static const u32 ice_ptypes_ipv4_ofos[] = {
165 0x1DC00000, 0x04000800, 0x00000000, 0x00000000,
166 0x00000000, 0x00000155, 0x00000000, 0x00000000,
167 0x00000000, 0x000FC000, 0x00000000, 0x00000000,
168 0x00000000, 0x00000000, 0x00000000, 0x00000000,
169 0x00000000, 0x00000000, 0x00000000, 0x00000000,
170 0x00000000, 0x00000000, 0x00000000, 0x00000000,
171 0x00000000, 0x00000000, 0x00000000, 0x00000000,
172 0x00000000, 0x00000000, 0x00000000, 0x00000000,
173};
174
175/* Packet types for packets with an Outer/First/Single IPv4 header, includes
176 * IPv4 other PTYPEs
177 */
178static const u32 ice_ptypes_ipv4_ofos_all[] = {
179 0x1DC00000, 0x04000800, 0x00000000, 0x00000000,
180 0x00000000, 0x00000155, 0x00000000, 0x00000000,
181 0x00000000, 0x000FC000, 0x83E0F800, 0x00000101,
182 0x00000000, 0x00000000, 0x00000000, 0x00000000,
183 0x00000000, 0x00000000, 0x00000000, 0x00000000,
184 0x00000000, 0x00000000, 0x00000000, 0x00000000,
185 0x00000000, 0x00000000, 0x00000000, 0x00000000,
186 0x00000000, 0x00000000, 0x00000000, 0x00000000,
187};
188
189/* Packet types for packets with an Innermost/Last IPv4 header */
190static const u32 ice_ptypes_ipv4_il[] = {
191 0xE0000000, 0xB807700E, 0x80000003, 0xE01DC03B,
192 0x0000000E, 0x00000000, 0x00000000, 0x00000000,
193 0x00000000, 0x00000000, 0x001FF800, 0x00000000,
194 0x00000000, 0x00000000, 0x00000000, 0x00000000,
195 0x00000000, 0x00000000, 0x00000000, 0x00000000,
196 0x00000000, 0x00000000, 0x00000000, 0x00000000,
197 0x00000000, 0x00000000, 0x00000000, 0x00000000,
198 0x00000000, 0x00000000, 0x00000000, 0x00000000,
199};
200
201/* Packet types for packets with an Outer/First/Single IPv6 header, does NOT
202 * include IPv6 other PTYPEs
203 */
204static const u32 ice_ptypes_ipv6_ofos[] = {
205 0x00000000, 0x00000000, 0x77000000, 0x10002000,
206 0x00000000, 0x000002AA, 0x00000000, 0x00000000,
207 0x00000000, 0x03F00000, 0x00000000, 0x00000000,
208 0x00000000, 0x00000000, 0x00000000, 0x00000000,
209 0x00000000, 0x00000000, 0x00000000, 0x00000000,
210 0x00000000, 0x00000000, 0x00000000, 0x00000000,
211 0x00000000, 0x00000000, 0x00000000, 0x00000000,
212 0x00000000, 0x00000000, 0x00000000, 0x00000000,
213};
214
215/* Packet types for packets with an Outer/First/Single IPv6 header, includes
216 * IPv6 other PTYPEs
217 */
218static const u32 ice_ptypes_ipv6_ofos_all[] = {
219 0x00000000, 0x00000000, 0x77000000, 0x10002000,
220 0x00000000, 0x000002AA, 0x00000000, 0x00000000,
221 0x00080F00, 0x03F00000, 0x7C1F0000, 0x00000206,
222 0x00000000, 0x00000000, 0x00000000, 0x00000000,
223 0x00000000, 0x00000000, 0x00000000, 0x00000000,
224 0x00000000, 0x00000000, 0x00000000, 0x00000000,
225 0x00000000, 0x00000000, 0x00000000, 0x00000000,
226 0x00000000, 0x00000000, 0x00000000, 0x00000000,
227};
228
229/* Packet types for packets with an Innermost/Last IPv6 header */
230static const u32 ice_ptypes_ipv6_il[] = {
231 0x00000000, 0x03B80770, 0x000001DC, 0x0EE00000,
232 0x00000770, 0x00000000, 0x00000000, 0x00000000,
233 0x00000000, 0x00000000, 0x7FE00000, 0x00000000,
234 0x00000000, 0x00000000, 0x00000000, 0x00000000,
235 0x00000000, 0x00000000, 0x00000000, 0x00000000,
236 0x00000000, 0x00000000, 0x00000000, 0x00000000,
237 0x00000000, 0x00000000, 0x00000000, 0x00000000,
238 0x00000000, 0x00000000, 0x00000000, 0x00000000,
239};
240
241/* Packet types for packets with an Outer/First/Single IPv4 header - no L4 */
242static const u32 ice_ptypes_ipv4_ofos_no_l4[] = {
243 0x10C00000, 0x04000800, 0x00000000, 0x00000000,
244 0x00000000, 0x00000000, 0x00000000, 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 0x00000000, 0x00000000, 0x00000000, 0x00000000,
251};
252
253/* Packet types for packets with an Outermost/First ARP header */
254static const u32 ice_ptypes_arp_of[] = {
255 0x00000800, 0x00000000, 0x00000000, 0x00000000,
256 0x00000000, 0x00000000, 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 0x00000000, 0x00000000, 0x00000000, 0x00000000,
263};
264
265/* Packet types for packets with an Innermost/Last IPv4 header - no L4 */
266static const u32 ice_ptypes_ipv4_il_no_l4[] = {
267 0x60000000, 0x18043008, 0x80000002, 0x6010c021,
268 0x00000008, 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 0x00000000, 0x00000000, 0x00000000, 0x00000000,
275};
276
277/* Packet types for packets with an Outer/First/Single IPv6 header - no L4 */
278static const u32 ice_ptypes_ipv6_ofos_no_l4[] = {
279 0x00000000, 0x00000000, 0x43000000, 0x10002000,
280 0x00000000, 0x00000000, 0x00000000, 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 0x00000000, 0x00000000, 0x00000000, 0x00000000,
287};
288
289/* Packet types for packets with an Innermost/Last IPv6 header - no L4 */
290static const u32 ice_ptypes_ipv6_il_no_l4[] = {
291 0x00000000, 0x02180430, 0x0000010c, 0x086010c0,
292 0x00000430, 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 0x00000000, 0x00000000, 0x00000000, 0x00000000,
299};
300
301/* UDP Packet types for non-tunneled packets or tunneled
302 * packets with inner UDP.
303 */
304static const u32 ice_ptypes_udp_il[] = {
305 0x81000000, 0x20204040, 0x04000010, 0x80810102,
306 0x00000040, 0x00000000, 0x00000000, 0x00000000,
307 0x00000000, 0x00410000, 0x90842000, 0x00000007,
308 0x00000000, 0x00000000, 0x00000000, 0x00000000,
309 0x00000000, 0x00000000, 0x00000000, 0x00000000,
310 0x00000000, 0x00000000, 0x00000000, 0x00000000,
311 0x00000000, 0x00000000, 0x00000000, 0x00000000,
312 0x00000000, 0x00000000, 0x00000000, 0x00000000,
313};
314
315/* Packet types for packets with an Innermost/Last TCP header */
316static const u32 ice_ptypes_tcp_il[] = {
317 0x04000000, 0x80810102, 0x10000040, 0x02040408,
318 0x00000102, 0x00000000, 0x00000000, 0x00000000,
319 0x00000000, 0x00820000, 0x21084000, 0x00000000,
320 0x00000000, 0x00000000, 0x00000000, 0x00000000,
321 0x00000000, 0x00000000, 0x00000000, 0x00000000,
322 0x00000000, 0x00000000, 0x00000000, 0x00000000,
323 0x00000000, 0x00000000, 0x00000000, 0x00000000,
324 0x00000000, 0x00000000, 0x00000000, 0x00000000,
325};
326
327/* Packet types for packets with an Innermost/Last SCTP header */
328static const u32 ice_ptypes_sctp_il[] = {
329 0x08000000, 0x01020204, 0x20000081, 0x04080810,
330 0x00000204, 0x00000000, 0x00000000, 0x00000000,
331 0x00000000, 0x01040000, 0x00000000, 0x00000000,
332 0x00000000, 0x00000000, 0x00000000, 0x00000000,
333 0x00000000, 0x00000000, 0x00000000, 0x00000000,
334 0x00000000, 0x00000000, 0x00000000, 0x00000000,
335 0x00000000, 0x00000000, 0x00000000, 0x00000000,
336 0x00000000, 0x00000000, 0x00000000, 0x00000000,
337};
338
339/* Packet types for packets with an Outermost/First ICMP header */
340static const u32 ice_ptypes_icmp_of[] = {
341 0x10000000, 0x00000000, 0x00000000, 0x00000000,
342 0x00000000, 0x00000000, 0x00000000, 0x00000000,
343 0x00000000, 0x00000000, 0x00000000, 0x00000000,
344 0x00000000, 0x00000000, 0x00000000, 0x00000000,
345 0x00000000, 0x00000000, 0x00000000, 0x00000000,
346 0x00000000, 0x00000000, 0x00000000, 0x00000000,
347 0x00000000, 0x00000000, 0x00000000, 0x00000000,
348 0x00000000, 0x00000000, 0x00000000, 0x00000000,
349};
350
351/* Packet types for packets with an Innermost/Last ICMP header */
352static const u32 ice_ptypes_icmp_il[] = {
353 0x00000000, 0x02040408, 0x40000102, 0x08101020,
354 0x00000408, 0x00000000, 0x00000000, 0x00000000,
355 0x00000000, 0x00000000, 0x42108000, 0x00000000,
356 0x00000000, 0x00000000, 0x00000000, 0x00000000,
357 0x00000000, 0x00000000, 0x00000000, 0x00000000,
358 0x00000000, 0x00000000, 0x00000000, 0x00000000,
359 0x00000000, 0x00000000, 0x00000000, 0x00000000,
360 0x00000000, 0x00000000, 0x00000000, 0x00000000,
361};
362
363/* Packet types for packets with an Outermost/First GRE header */
364static const u32 ice_ptypes_gre_of[] = {
365 0x00000000, 0xBFBF7800, 0x000001DF, 0xFEFDE000,
366 0x0000017E, 0x00000000, 0x00000000, 0x00000000,
367 0x00000000, 0x00000000, 0x00000000, 0x00000000,
368 0x00000000, 0x00000000, 0x00000000, 0x00000000,
369 0x00000000, 0x00000000, 0x00000000, 0x00000000,
370 0x00000000, 0x00000000, 0x00000000, 0x00000000,
371 0x00000000, 0x00000000, 0x00000000, 0x00000000,
372 0x00000000, 0x00000000, 0x00000000, 0x00000000,
373};
374
375/* Packet types for packets with an Innermost/Last MAC header */
376static const u32 ice_ptypes_mac_il[] = {
377 0x00000000, 0x00000000, 0x00000000, 0x00000000,
378 0x00000000, 0x00000000, 0x00000000, 0x00000000,
379 0x00000000, 0x00000000, 0x00000000, 0x00000000,
380 0x00000000, 0x00000000, 0x00000000, 0x00000000,
381 0x00000000, 0x00000000, 0x00000000, 0x00000000,
382 0x00000000, 0x00000000, 0x00000000, 0x00000000,
383 0x00000000, 0x00000000, 0x00000000, 0x00000000,
384 0x00000000, 0x00000000, 0x00000000, 0x00000000,
385};
386
387/* Packet types for GTPC */
388static const u32 ice_ptypes_gtpc[] = {
389 0x00000000, 0x00000000, 0x00000000, 0x00000000,
390 0x00000000, 0x00000000, 0x00000000, 0x00000000,
391 0x00000000, 0x00000000, 0x00000180, 0x00000000,
392 0x00000000, 0x00000000, 0x00000000, 0x00000000,
393 0x00000000, 0x00000000, 0x00000000, 0x00000000,
394 0x00000000, 0x00000000, 0x00000000, 0x00000000,
395 0x00000000, 0x00000000, 0x00000000, 0x00000000,
396 0x00000000, 0x00000000, 0x00000000, 0x00000000,
397};
398
399/* Packet types for GTPC with TEID */
400static const u32 ice_ptypes_gtpc_tid[] = {
401 0x00000000, 0x00000000, 0x00000000, 0x00000000,
402 0x00000000, 0x00000000, 0x00000000, 0x00000000,
403 0x00000000, 0x00000000, 0x00000060, 0x00000000,
404 0x00000000, 0x00000000, 0x00000000, 0x00000000,
405 0x00000000, 0x00000000, 0x00000000, 0x00000000,
406 0x00000000, 0x00000000, 0x00000000, 0x00000000,
407 0x00000000, 0x00000000, 0x00000000, 0x00000000,
408 0x00000000, 0x00000000, 0x00000000, 0x00000000,
409};
410
411/* Packet types for GTPU */
412static const struct ice_ptype_attributes ice_attr_gtpu_eh[] = {
413 { ICE_MAC_IPV4_GTPU_IPV4_FRAG, ICE_PTYPE_ATTR_GTP_PDU_EH },
414 { ICE_MAC_IPV4_GTPU_IPV4_PAY, ICE_PTYPE_ATTR_GTP_PDU_EH },
415 { ICE_MAC_IPV4_GTPU_IPV4_UDP_PAY, ICE_PTYPE_ATTR_GTP_PDU_EH },
416 { ICE_MAC_IPV4_GTPU_IPV4_TCP, ICE_PTYPE_ATTR_GTP_PDU_EH },
417 { ICE_MAC_IPV4_GTPU_IPV4_ICMP, ICE_PTYPE_ATTR_GTP_PDU_EH },
418 { ICE_MAC_IPV6_GTPU_IPV4_FRAG, ICE_PTYPE_ATTR_GTP_PDU_EH },
419 { ICE_MAC_IPV6_GTPU_IPV4_PAY, ICE_PTYPE_ATTR_GTP_PDU_EH },
420 { ICE_MAC_IPV6_GTPU_IPV4_UDP_PAY, ICE_PTYPE_ATTR_GTP_PDU_EH },
421 { ICE_MAC_IPV6_GTPU_IPV4_TCP, ICE_PTYPE_ATTR_GTP_PDU_EH },
422 { ICE_MAC_IPV6_GTPU_IPV4_ICMP, ICE_PTYPE_ATTR_GTP_PDU_EH },
423 { ICE_MAC_IPV4_GTPU_IPV6_FRAG, ICE_PTYPE_ATTR_GTP_PDU_EH },
424 { ICE_MAC_IPV4_GTPU_IPV6_PAY, ICE_PTYPE_ATTR_GTP_PDU_EH },
425 { ICE_MAC_IPV4_GTPU_IPV6_UDP_PAY, ICE_PTYPE_ATTR_GTP_PDU_EH },
426 { ICE_MAC_IPV4_GTPU_IPV6_TCP, ICE_PTYPE_ATTR_GTP_PDU_EH },
427 { ICE_MAC_IPV4_GTPU_IPV6_ICMPV6, ICE_PTYPE_ATTR_GTP_PDU_EH },
428 { ICE_MAC_IPV6_GTPU_IPV6_FRAG, ICE_PTYPE_ATTR_GTP_PDU_EH },
429 { ICE_MAC_IPV6_GTPU_IPV6_PAY, ICE_PTYPE_ATTR_GTP_PDU_EH },
430 { ICE_MAC_IPV6_GTPU_IPV6_UDP_PAY, ICE_PTYPE_ATTR_GTP_PDU_EH },
431 { ICE_MAC_IPV6_GTPU_IPV6_TCP, ICE_PTYPE_ATTR_GTP_PDU_EH },
432 { ICE_MAC_IPV6_GTPU_IPV6_ICMPV6, ICE_PTYPE_ATTR_GTP_PDU_EH },
433};
434
435static const struct ice_ptype_attributes ice_attr_gtpu_down[] = {
436 { ICE_MAC_IPV4_GTPU_IPV4_FRAG, ICE_PTYPE_ATTR_GTP_DOWNLINK },
437 { ICE_MAC_IPV4_GTPU_IPV4_PAY, ICE_PTYPE_ATTR_GTP_DOWNLINK },
438 { ICE_MAC_IPV4_GTPU_IPV4_UDP_PAY, ICE_PTYPE_ATTR_GTP_DOWNLINK },
439 { ICE_MAC_IPV4_GTPU_IPV4_TCP, ICE_PTYPE_ATTR_GTP_DOWNLINK },
440 { ICE_MAC_IPV4_GTPU_IPV4_ICMP, ICE_PTYPE_ATTR_GTP_DOWNLINK },
441 { ICE_MAC_IPV6_GTPU_IPV4_FRAG, ICE_PTYPE_ATTR_GTP_DOWNLINK },
442 { ICE_MAC_IPV6_GTPU_IPV4_PAY, ICE_PTYPE_ATTR_GTP_DOWNLINK },
443 { ICE_MAC_IPV6_GTPU_IPV4_UDP_PAY, ICE_PTYPE_ATTR_GTP_DOWNLINK },
444 { ICE_MAC_IPV6_GTPU_IPV4_TCP, ICE_PTYPE_ATTR_GTP_DOWNLINK },
445 { ICE_MAC_IPV6_GTPU_IPV4_ICMP, ICE_PTYPE_ATTR_GTP_DOWNLINK },
446 { ICE_MAC_IPV4_GTPU_IPV6_FRAG, ICE_PTYPE_ATTR_GTP_DOWNLINK },
447 { ICE_MAC_IPV4_GTPU_IPV6_PAY, ICE_PTYPE_ATTR_GTP_DOWNLINK },
448 { ICE_MAC_IPV4_GTPU_IPV6_UDP_PAY, ICE_PTYPE_ATTR_GTP_DOWNLINK },
449 { ICE_MAC_IPV4_GTPU_IPV6_TCP, ICE_PTYPE_ATTR_GTP_DOWNLINK },
450 { ICE_MAC_IPV4_GTPU_IPV6_ICMPV6, ICE_PTYPE_ATTR_GTP_DOWNLINK },
451 { ICE_MAC_IPV6_GTPU_IPV6_FRAG, ICE_PTYPE_ATTR_GTP_DOWNLINK },
452 { ICE_MAC_IPV6_GTPU_IPV6_PAY, ICE_PTYPE_ATTR_GTP_DOWNLINK },
453 { ICE_MAC_IPV6_GTPU_IPV6_UDP_PAY, ICE_PTYPE_ATTR_GTP_DOWNLINK },
454 { ICE_MAC_IPV6_GTPU_IPV6_TCP, ICE_PTYPE_ATTR_GTP_DOWNLINK },
455 { ICE_MAC_IPV6_GTPU_IPV6_ICMPV6, ICE_PTYPE_ATTR_GTP_DOWNLINK },
456};
457
458static const struct ice_ptype_attributes ice_attr_gtpu_up[] = {
459 { ICE_MAC_IPV4_GTPU_IPV4_FRAG, ICE_PTYPE_ATTR_GTP_UPLINK },
460 { ICE_MAC_IPV4_GTPU_IPV4_PAY, ICE_PTYPE_ATTR_GTP_UPLINK },
461 { ICE_MAC_IPV4_GTPU_IPV4_UDP_PAY, ICE_PTYPE_ATTR_GTP_UPLINK },
462 { ICE_MAC_IPV4_GTPU_IPV4_TCP, ICE_PTYPE_ATTR_GTP_UPLINK },
463 { ICE_MAC_IPV4_GTPU_IPV4_ICMP, ICE_PTYPE_ATTR_GTP_UPLINK },
464 { ICE_MAC_IPV6_GTPU_IPV4_FRAG, ICE_PTYPE_ATTR_GTP_UPLINK },
465 { ICE_MAC_IPV6_GTPU_IPV4_PAY, ICE_PTYPE_ATTR_GTP_UPLINK },
466 { ICE_MAC_IPV6_GTPU_IPV4_UDP_PAY, ICE_PTYPE_ATTR_GTP_UPLINK },
467 { ICE_MAC_IPV6_GTPU_IPV4_TCP, ICE_PTYPE_ATTR_GTP_UPLINK },
468 { ICE_MAC_IPV6_GTPU_IPV4_ICMP, ICE_PTYPE_ATTR_GTP_UPLINK },
469 { ICE_MAC_IPV4_GTPU_IPV6_FRAG, ICE_PTYPE_ATTR_GTP_UPLINK },
470 { ICE_MAC_IPV4_GTPU_IPV6_PAY, ICE_PTYPE_ATTR_GTP_UPLINK },
471 { ICE_MAC_IPV4_GTPU_IPV6_UDP_PAY, ICE_PTYPE_ATTR_GTP_UPLINK },
472 { ICE_MAC_IPV4_GTPU_IPV6_TCP, ICE_PTYPE_ATTR_GTP_UPLINK },
473 { ICE_MAC_IPV4_GTPU_IPV6_ICMPV6, ICE_PTYPE_ATTR_GTP_UPLINK },
474 { ICE_MAC_IPV6_GTPU_IPV6_FRAG, ICE_PTYPE_ATTR_GTP_UPLINK },
475 { ICE_MAC_IPV6_GTPU_IPV6_PAY, ICE_PTYPE_ATTR_GTP_UPLINK },
476 { ICE_MAC_IPV6_GTPU_IPV6_UDP_PAY, ICE_PTYPE_ATTR_GTP_UPLINK },
477 { ICE_MAC_IPV6_GTPU_IPV6_TCP, ICE_PTYPE_ATTR_GTP_UPLINK },
478 { ICE_MAC_IPV6_GTPU_IPV6_ICMPV6, ICE_PTYPE_ATTR_GTP_UPLINK },
479};
480
481static const u32 ice_ptypes_gtpu[] = {
482 0x00000000, 0x00000000, 0x00000000, 0x00000000,
483 0x00000000, 0x00000000, 0x00000000, 0x00000000,
484 0x00000000, 0x00000000, 0x7FFFFE00, 0x00000000,
485 0x00000000, 0x00000000, 0x00000000, 0x00000000,
486 0x00000000, 0x00000000, 0x00000000, 0x00000000,
487 0x00000000, 0x00000000, 0x00000000, 0x00000000,
488 0x00000000, 0x00000000, 0x00000000, 0x00000000,
489 0x00000000, 0x00000000, 0x00000000, 0x00000000,
490};
491
492/* Packet types for PPPoE */
493static const u32 ice_ptypes_pppoe[] = {
494 0x00000000, 0x00000000, 0x00000000, 0x00000000,
495 0x00000000, 0x00000000, 0x00000000, 0x00000000,
496 0x00000000, 0x03ffe000, 0x00000000, 0x00000000,
497 0x00000000, 0x00000000, 0x00000000, 0x00000000,
498 0x00000000, 0x00000000, 0x00000000, 0x00000000,
499 0x00000000, 0x00000000, 0x00000000, 0x00000000,
500 0x00000000, 0x00000000, 0x00000000, 0x00000000,
501 0x00000000, 0x00000000, 0x00000000, 0x00000000,
502};
503
504/* Packet types for packets with PFCP NODE header */
505static const u32 ice_ptypes_pfcp_node[] = {
506 0x00000000, 0x00000000, 0x00000000, 0x00000000,
507 0x00000000, 0x00000000, 0x00000000, 0x00000000,
508 0x00000000, 0x00000000, 0x80000000, 0x00000002,
509 0x00000000, 0x00000000, 0x00000000, 0x00000000,
510 0x00000000, 0x00000000, 0x00000000, 0x00000000,
511 0x00000000, 0x00000000, 0x00000000, 0x00000000,
512 0x00000000, 0x00000000, 0x00000000, 0x00000000,
513 0x00000000, 0x00000000, 0x00000000, 0x00000000,
514};
515
516/* Packet types for packets with PFCP SESSION header */
517static const u32 ice_ptypes_pfcp_session[] = {
518 0x00000000, 0x00000000, 0x00000000, 0x00000000,
519 0x00000000, 0x00000000, 0x00000000, 0x00000000,
520 0x00000000, 0x00000000, 0x00000000, 0x00000005,
521 0x00000000, 0x00000000, 0x00000000, 0x00000000,
522 0x00000000, 0x00000000, 0x00000000, 0x00000000,
523 0x00000000, 0x00000000, 0x00000000, 0x00000000,
524 0x00000000, 0x00000000, 0x00000000, 0x00000000,
525 0x00000000, 0x00000000, 0x00000000, 0x00000000,
526};
527
528/* Packet types for L2TPv3 */
529static const u32 ice_ptypes_l2tpv3[] = {
530 0x00000000, 0x00000000, 0x00000000, 0x00000000,
531 0x00000000, 0x00000000, 0x00000000, 0x00000000,
532 0x00000000, 0x00000000, 0x00000000, 0x00000300,
533 0x00000000, 0x00000000, 0x00000000, 0x00000000,
534 0x00000000, 0x00000000, 0x00000000, 0x00000000,
535 0x00000000, 0x00000000, 0x00000000, 0x00000000,
536 0x00000000, 0x00000000, 0x00000000, 0x00000000,
537 0x00000000, 0x00000000, 0x00000000, 0x00000000,
538};
539
540/* Packet types for ESP */
541static const u32 ice_ptypes_esp[] = {
542 0x00000000, 0x00000000, 0x00000000, 0x00000000,
543 0x00000000, 0x00000003, 0x00000000, 0x00000000,
544 0x00000000, 0x00000000, 0x00000000, 0x00000000,
545 0x00000000, 0x00000000, 0x00000000, 0x00000000,
546 0x00000000, 0x00000000, 0x00000000, 0x00000000,
547 0x00000000, 0x00000000, 0x00000000, 0x00000000,
548 0x00000000, 0x00000000, 0x00000000, 0x00000000,
549 0x00000000, 0x00000000, 0x00000000, 0x00000000,
550};
551
552/* Packet types for AH */
553static const u32 ice_ptypes_ah[] = {
554 0x00000000, 0x00000000, 0x00000000, 0x00000000,
555 0x00000000, 0x0000000C, 0x00000000, 0x00000000,
556 0x00000000, 0x00000000, 0x00000000, 0x00000000,
557 0x00000000, 0x00000000, 0x00000000, 0x00000000,
558 0x00000000, 0x00000000, 0x00000000, 0x00000000,
559 0x00000000, 0x00000000, 0x00000000, 0x00000000,
560 0x00000000, 0x00000000, 0x00000000, 0x00000000,
561 0x00000000, 0x00000000, 0x00000000, 0x00000000,
562};
563
564/* Packet types for packets with NAT_T ESP header */
565static const u32 ice_ptypes_nat_t_esp[] = {
566 0x00000000, 0x00000000, 0x00000000, 0x00000000,
567 0x00000000, 0x00000030, 0x00000000, 0x00000000,
568 0x00000000, 0x00000000, 0x00000000, 0x00000000,
569 0x00000000, 0x00000000, 0x00000000, 0x00000000,
570 0x00000000, 0x00000000, 0x00000000, 0x00000000,
571 0x00000000, 0x00000000, 0x00000000, 0x00000000,
572 0x00000000, 0x00000000, 0x00000000, 0x00000000,
573 0x00000000, 0x00000000, 0x00000000, 0x00000000,
574};
575
576static const u32 ice_ptypes_mac_non_ip_ofos[] = {
577 0x00000846, 0x00000000, 0x00000000, 0x00000000,
578 0x00000000, 0x00000000, 0x00000000, 0x00000000,
579 0x00400000, 0x03FFF000, 0x00000000, 0x00000000,
580 0x00000000, 0x00000000, 0x00000000, 0x00000000,
581 0x00000000, 0x00000000, 0x00000000, 0x00000000,
582 0x00000000, 0x00000000, 0x00000000, 0x00000000,
583 0x00000000, 0x00000000, 0x00000000, 0x00000000,
584 0x00000000, 0x00000000, 0x00000000, 0x00000000,
585};
586
587/* Manage parameters and info. used during the creation of a flow profile */
588struct ice_flow_prof_params {
589 enum ice_block blk;
590 u16 entry_length; /* # of bytes formatted entry will require */
591 u8 es_cnt;
592 struct ice_flow_prof *prof;
593
594 /* For ACL, the es[0] will have the data of ICE_RX_MDID_PKT_FLAGS_15_0
595 * This will give us the direction flags.
596 */
597 struct ice_fv_word es[ICE_MAX_FV_WORDS];
598 /* attributes can be used to add attributes to a particular PTYPE */
599 const struct ice_ptype_attributes *attr;
600 u16 attr_cnt;
601
602 u16 mask[ICE_MAX_FV_WORDS];
603 DECLARE_BITMAP(ptypes, ICE_FLOW_PTYPE_MAX);
604};
605
606#define ICE_FLOW_RSS_HDRS_INNER_MASK \
607 (ICE_FLOW_SEG_HDR_PPPOE | ICE_FLOW_SEG_HDR_GTPC | \
608 ICE_FLOW_SEG_HDR_GTPC_TEID | ICE_FLOW_SEG_HDR_GTPU | \
609 ICE_FLOW_SEG_HDR_PFCP_SESSION | ICE_FLOW_SEG_HDR_L2TPV3 | \
610 ICE_FLOW_SEG_HDR_ESP | ICE_FLOW_SEG_HDR_AH | \
611 ICE_FLOW_SEG_HDR_NAT_T_ESP)
612
613#define ICE_FLOW_SEG_HDRS_L3_MASK \
614 (ICE_FLOW_SEG_HDR_IPV4 | ICE_FLOW_SEG_HDR_IPV6 | ICE_FLOW_SEG_HDR_ARP)
615#define ICE_FLOW_SEG_HDRS_L4_MASK \
616 (ICE_FLOW_SEG_HDR_ICMP | ICE_FLOW_SEG_HDR_TCP | ICE_FLOW_SEG_HDR_UDP | \
617 ICE_FLOW_SEG_HDR_SCTP)
618/* mask for L4 protocols that are NOT part of IPv4/6 OTHER PTYPE groups */
619#define ICE_FLOW_SEG_HDRS_L4_MASK_NO_OTHER \
620 (ICE_FLOW_SEG_HDR_TCP | ICE_FLOW_SEG_HDR_UDP | ICE_FLOW_SEG_HDR_SCTP)
621
622/**
623 * ice_flow_val_hdrs - validates packet segments for valid protocol headers
624 * @segs: array of one or more packet segments that describe the flow
625 * @segs_cnt: number of packet segments provided
626 */
627static int ice_flow_val_hdrs(struct ice_flow_seg_info *segs, u8 segs_cnt)
628{
629 u8 i;
630
631 for (i = 0; i < segs_cnt; i++) {
632 /* Multiple L3 headers */
633 if (segs[i].hdrs & ICE_FLOW_SEG_HDRS_L3_MASK &&
634 !is_power_of_2(segs[i].hdrs & ICE_FLOW_SEG_HDRS_L3_MASK))
635 return -EINVAL;
636
637 /* Multiple L4 headers */
638 if (segs[i].hdrs & ICE_FLOW_SEG_HDRS_L4_MASK &&
639 !is_power_of_2(segs[i].hdrs & ICE_FLOW_SEG_HDRS_L4_MASK))
640 return -EINVAL;
641 }
642
643 return 0;
644}
645
646/* Sizes of fixed known protocol headers without header options */
647#define ICE_FLOW_PROT_HDR_SZ_MAC 14
648#define ICE_FLOW_PROT_HDR_SZ_MAC_VLAN (ICE_FLOW_PROT_HDR_SZ_MAC + 2)
649#define ICE_FLOW_PROT_HDR_SZ_IPV4 20
650#define ICE_FLOW_PROT_HDR_SZ_IPV6 40
651#define ICE_FLOW_PROT_HDR_SZ_ARP 28
652#define ICE_FLOW_PROT_HDR_SZ_ICMP 8
653#define ICE_FLOW_PROT_HDR_SZ_TCP 20
654#define ICE_FLOW_PROT_HDR_SZ_UDP 8
655#define ICE_FLOW_PROT_HDR_SZ_SCTP 12
656
657/**
658 * ice_flow_calc_seg_sz - calculates size of a packet segment based on headers
659 * @params: information about the flow to be processed
660 * @seg: index of packet segment whose header size is to be determined
661 */
662static u16 ice_flow_calc_seg_sz(struct ice_flow_prof_params *params, u8 seg)
663{
664 u16 sz;
665
666 /* L2 headers */
667 sz = (params->prof->segs[seg].hdrs & ICE_FLOW_SEG_HDR_VLAN) ?
668 ICE_FLOW_PROT_HDR_SZ_MAC_VLAN : ICE_FLOW_PROT_HDR_SZ_MAC;
669
670 /* L3 headers */
671 if (params->prof->segs[seg].hdrs & ICE_FLOW_SEG_HDR_IPV4)
672 sz += ICE_FLOW_PROT_HDR_SZ_IPV4;
673 else if (params->prof->segs[seg].hdrs & ICE_FLOW_SEG_HDR_IPV6)
674 sz += ICE_FLOW_PROT_HDR_SZ_IPV6;
675 else if (params->prof->segs[seg].hdrs & ICE_FLOW_SEG_HDR_ARP)
676 sz += ICE_FLOW_PROT_HDR_SZ_ARP;
677 else if (params->prof->segs[seg].hdrs & ICE_FLOW_SEG_HDRS_L4_MASK)
678 /* An L3 header is required if L4 is specified */
679 return 0;
680
681 /* L4 headers */
682 if (params->prof->segs[seg].hdrs & ICE_FLOW_SEG_HDR_ICMP)
683 sz += ICE_FLOW_PROT_HDR_SZ_ICMP;
684 else if (params->prof->segs[seg].hdrs & ICE_FLOW_SEG_HDR_TCP)
685 sz += ICE_FLOW_PROT_HDR_SZ_TCP;
686 else if (params->prof->segs[seg].hdrs & ICE_FLOW_SEG_HDR_UDP)
687 sz += ICE_FLOW_PROT_HDR_SZ_UDP;
688 else if (params->prof->segs[seg].hdrs & ICE_FLOW_SEG_HDR_SCTP)
689 sz += ICE_FLOW_PROT_HDR_SZ_SCTP;
690
691 return sz;
692}
693
694/**
695 * ice_flow_proc_seg_hdrs - process protocol headers present in pkt segments
696 * @params: information about the flow to be processed
697 *
698 * This function identifies the packet types associated with the protocol
699 * headers being present in packet segments of the specified flow profile.
700 */
701static int ice_flow_proc_seg_hdrs(struct ice_flow_prof_params *params)
702{
703 struct ice_flow_prof *prof;
704 u8 i;
705
706 memset(params->ptypes, 0xff, sizeof(params->ptypes));
707
708 prof = params->prof;
709
710 for (i = 0; i < params->prof->segs_cnt; i++) {
711 const unsigned long *src;
712 u32 hdrs;
713
714 hdrs = prof->segs[i].hdrs;
715
716 if (hdrs & ICE_FLOW_SEG_HDR_ETH) {
717 src = !i ? (const unsigned long *)ice_ptypes_mac_ofos :
718 (const unsigned long *)ice_ptypes_mac_il;
719 bitmap_and(params->ptypes, params->ptypes, src,
720 ICE_FLOW_PTYPE_MAX);
721 }
722
723 if (i && hdrs & ICE_FLOW_SEG_HDR_VLAN) {
724 src = (const unsigned long *)ice_ptypes_macvlan_il;
725 bitmap_and(params->ptypes, params->ptypes, src,
726 ICE_FLOW_PTYPE_MAX);
727 }
728
729 if (!i && hdrs & ICE_FLOW_SEG_HDR_ARP) {
730 bitmap_and(params->ptypes, params->ptypes,
731 (const unsigned long *)ice_ptypes_arp_of,
732 ICE_FLOW_PTYPE_MAX);
733 }
734
735 if ((hdrs & ICE_FLOW_SEG_HDR_IPV4) &&
736 (hdrs & ICE_FLOW_SEG_HDR_IPV_OTHER)) {
737 src = i ? (const unsigned long *)ice_ptypes_ipv4_il :
738 (const unsigned long *)ice_ptypes_ipv4_ofos_all;
739 bitmap_and(params->ptypes, params->ptypes, src,
740 ICE_FLOW_PTYPE_MAX);
741 } else if ((hdrs & ICE_FLOW_SEG_HDR_IPV6) &&
742 (hdrs & ICE_FLOW_SEG_HDR_IPV_OTHER)) {
743 src = i ? (const unsigned long *)ice_ptypes_ipv6_il :
744 (const unsigned long *)ice_ptypes_ipv6_ofos_all;
745 bitmap_and(params->ptypes, params->ptypes, src,
746 ICE_FLOW_PTYPE_MAX);
747 } else if ((hdrs & ICE_FLOW_SEG_HDR_IPV4) &&
748 !(hdrs & ICE_FLOW_SEG_HDRS_L4_MASK_NO_OTHER)) {
749 src = !i ? (const unsigned long *)ice_ptypes_ipv4_ofos_no_l4 :
750 (const unsigned long *)ice_ptypes_ipv4_il_no_l4;
751 bitmap_and(params->ptypes, params->ptypes, src,
752 ICE_FLOW_PTYPE_MAX);
753 } else if (hdrs & ICE_FLOW_SEG_HDR_IPV4) {
754 src = !i ? (const unsigned long *)ice_ptypes_ipv4_ofos :
755 (const unsigned long *)ice_ptypes_ipv4_il;
756 bitmap_and(params->ptypes, params->ptypes, src,
757 ICE_FLOW_PTYPE_MAX);
758 } else if ((hdrs & ICE_FLOW_SEG_HDR_IPV6) &&
759 !(hdrs & ICE_FLOW_SEG_HDRS_L4_MASK_NO_OTHER)) {
760 src = !i ? (const unsigned long *)ice_ptypes_ipv6_ofos_no_l4 :
761 (const unsigned long *)ice_ptypes_ipv6_il_no_l4;
762 bitmap_and(params->ptypes, params->ptypes, src,
763 ICE_FLOW_PTYPE_MAX);
764 } else if (hdrs & ICE_FLOW_SEG_HDR_IPV6) {
765 src = !i ? (const unsigned long *)ice_ptypes_ipv6_ofos :
766 (const unsigned long *)ice_ptypes_ipv6_il;
767 bitmap_and(params->ptypes, params->ptypes, src,
768 ICE_FLOW_PTYPE_MAX);
769 }
770
771 if (hdrs & ICE_FLOW_SEG_HDR_ETH_NON_IP) {
772 src = (const unsigned long *)ice_ptypes_mac_non_ip_ofos;
773 bitmap_and(params->ptypes, params->ptypes, src,
774 ICE_FLOW_PTYPE_MAX);
775 } else if (hdrs & ICE_FLOW_SEG_HDR_PPPOE) {
776 src = (const unsigned long *)ice_ptypes_pppoe;
777 bitmap_and(params->ptypes, params->ptypes, src,
778 ICE_FLOW_PTYPE_MAX);
779 } else {
780 src = (const unsigned long *)ice_ptypes_pppoe;
781 bitmap_andnot(params->ptypes, params->ptypes, src,
782 ICE_FLOW_PTYPE_MAX);
783 }
784
785 if (hdrs & ICE_FLOW_SEG_HDR_UDP) {
786 src = (const unsigned long *)ice_ptypes_udp_il;
787 bitmap_and(params->ptypes, params->ptypes, src,
788 ICE_FLOW_PTYPE_MAX);
789 } else if (hdrs & ICE_FLOW_SEG_HDR_TCP) {
790 bitmap_and(params->ptypes, params->ptypes,
791 (const unsigned long *)ice_ptypes_tcp_il,
792 ICE_FLOW_PTYPE_MAX);
793 } else if (hdrs & ICE_FLOW_SEG_HDR_SCTP) {
794 src = (const unsigned long *)ice_ptypes_sctp_il;
795 bitmap_and(params->ptypes, params->ptypes, src,
796 ICE_FLOW_PTYPE_MAX);
797 }
798
799 if (hdrs & ICE_FLOW_SEG_HDR_ICMP) {
800 src = !i ? (const unsigned long *)ice_ptypes_icmp_of :
801 (const unsigned long *)ice_ptypes_icmp_il;
802 bitmap_and(params->ptypes, params->ptypes, src,
803 ICE_FLOW_PTYPE_MAX);
804 } else if (hdrs & ICE_FLOW_SEG_HDR_GRE) {
805 if (!i) {
806 src = (const unsigned long *)ice_ptypes_gre_of;
807 bitmap_and(params->ptypes, params->ptypes,
808 src, ICE_FLOW_PTYPE_MAX);
809 }
810 } else if (hdrs & ICE_FLOW_SEG_HDR_GTPC) {
811 src = (const unsigned long *)ice_ptypes_gtpc;
812 bitmap_and(params->ptypes, params->ptypes, src,
813 ICE_FLOW_PTYPE_MAX);
814 } else if (hdrs & ICE_FLOW_SEG_HDR_GTPC_TEID) {
815 src = (const unsigned long *)ice_ptypes_gtpc_tid;
816 bitmap_and(params->ptypes, params->ptypes, src,
817 ICE_FLOW_PTYPE_MAX);
818 } else if (hdrs & ICE_FLOW_SEG_HDR_GTPU_DWN) {
819 src = (const unsigned long *)ice_ptypes_gtpu;
820 bitmap_and(params->ptypes, params->ptypes, src,
821 ICE_FLOW_PTYPE_MAX);
822
823 /* Attributes for GTP packet with downlink */
824 params->attr = ice_attr_gtpu_down;
825 params->attr_cnt = ARRAY_SIZE(ice_attr_gtpu_down);
826 } else if (hdrs & ICE_FLOW_SEG_HDR_GTPU_UP) {
827 src = (const unsigned long *)ice_ptypes_gtpu;
828 bitmap_and(params->ptypes, params->ptypes, src,
829 ICE_FLOW_PTYPE_MAX);
830
831 /* Attributes for GTP packet with uplink */
832 params->attr = ice_attr_gtpu_up;
833 params->attr_cnt = ARRAY_SIZE(ice_attr_gtpu_up);
834 } else if (hdrs & ICE_FLOW_SEG_HDR_GTPU_EH) {
835 src = (const unsigned long *)ice_ptypes_gtpu;
836 bitmap_and(params->ptypes, params->ptypes, src,
837 ICE_FLOW_PTYPE_MAX);
838
839 /* Attributes for GTP packet with Extension Header */
840 params->attr = ice_attr_gtpu_eh;
841 params->attr_cnt = ARRAY_SIZE(ice_attr_gtpu_eh);
842 } else if (hdrs & ICE_FLOW_SEG_HDR_GTPU_IP) {
843 src = (const unsigned long *)ice_ptypes_gtpu;
844 bitmap_and(params->ptypes, params->ptypes, src,
845 ICE_FLOW_PTYPE_MAX);
846 } else if (hdrs & ICE_FLOW_SEG_HDR_L2TPV3) {
847 src = (const unsigned long *)ice_ptypes_l2tpv3;
848 bitmap_and(params->ptypes, params->ptypes, src,
849 ICE_FLOW_PTYPE_MAX);
850 } else if (hdrs & ICE_FLOW_SEG_HDR_ESP) {
851 src = (const unsigned long *)ice_ptypes_esp;
852 bitmap_and(params->ptypes, params->ptypes, src,
853 ICE_FLOW_PTYPE_MAX);
854 } else if (hdrs & ICE_FLOW_SEG_HDR_AH) {
855 src = (const unsigned long *)ice_ptypes_ah;
856 bitmap_and(params->ptypes, params->ptypes, src,
857 ICE_FLOW_PTYPE_MAX);
858 } else if (hdrs & ICE_FLOW_SEG_HDR_NAT_T_ESP) {
859 src = (const unsigned long *)ice_ptypes_nat_t_esp;
860 bitmap_and(params->ptypes, params->ptypes, src,
861 ICE_FLOW_PTYPE_MAX);
862 }
863
864 if (hdrs & ICE_FLOW_SEG_HDR_PFCP) {
865 if (hdrs & ICE_FLOW_SEG_HDR_PFCP_NODE)
866 src = (const unsigned long *)ice_ptypes_pfcp_node;
867 else
868 src = (const unsigned long *)ice_ptypes_pfcp_session;
869
870 bitmap_and(params->ptypes, params->ptypes, src,
871 ICE_FLOW_PTYPE_MAX);
872 } else {
873 src = (const unsigned long *)ice_ptypes_pfcp_node;
874 bitmap_andnot(params->ptypes, params->ptypes, src,
875 ICE_FLOW_PTYPE_MAX);
876
877 src = (const unsigned long *)ice_ptypes_pfcp_session;
878 bitmap_andnot(params->ptypes, params->ptypes, src,
879 ICE_FLOW_PTYPE_MAX);
880 }
881 }
882
883 return 0;
884}
885
886/**
887 * ice_flow_xtract_fld - Create an extraction sequence entry for the given field
888 * @hw: pointer to the HW struct
889 * @params: information about the flow to be processed
890 * @seg: packet segment index of the field to be extracted
891 * @fld: ID of field to be extracted
892 * @match: bit field of all fields
893 *
894 * This function determines the protocol ID, offset, and size of the given
895 * field. It then allocates one or more extraction sequence entries for the
896 * given field, and fill the entries with protocol ID and offset information.
897 */
898static int
899ice_flow_xtract_fld(struct ice_hw *hw, struct ice_flow_prof_params *params,
900 u8 seg, enum ice_flow_field fld, u64 match)
901{
902 enum ice_flow_field sib = ICE_FLOW_FIELD_IDX_MAX;
903 enum ice_prot_id prot_id = ICE_PROT_ID_INVAL;
904 u8 fv_words = hw->blk[params->blk].es.fvw;
905 struct ice_flow_fld_info *flds;
906 u16 cnt, ese_bits, i;
907 u16 sib_mask = 0;
908 u16 mask;
909 u16 off;
910
911 flds = params->prof->segs[seg].fields;
912
913 switch (fld) {
914 case ICE_FLOW_FIELD_IDX_ETH_DA:
915 case ICE_FLOW_FIELD_IDX_ETH_SA:
916 case ICE_FLOW_FIELD_IDX_S_VLAN:
917 case ICE_FLOW_FIELD_IDX_C_VLAN:
918 prot_id = seg == 0 ? ICE_PROT_MAC_OF_OR_S : ICE_PROT_MAC_IL;
919 break;
920 case ICE_FLOW_FIELD_IDX_ETH_TYPE:
921 prot_id = seg == 0 ? ICE_PROT_ETYPE_OL : ICE_PROT_ETYPE_IL;
922 break;
923 case ICE_FLOW_FIELD_IDX_IPV4_DSCP:
924 prot_id = seg == 0 ? ICE_PROT_IPV4_OF_OR_S : ICE_PROT_IPV4_IL;
925 break;
926 case ICE_FLOW_FIELD_IDX_IPV6_DSCP:
927 prot_id = seg == 0 ? ICE_PROT_IPV6_OF_OR_S : ICE_PROT_IPV6_IL;
928 break;
929 case ICE_FLOW_FIELD_IDX_IPV4_TTL:
930 case ICE_FLOW_FIELD_IDX_IPV4_PROT:
931 prot_id = seg == 0 ? ICE_PROT_IPV4_OF_OR_S : ICE_PROT_IPV4_IL;
932
933 /* TTL and PROT share the same extraction seq. entry.
934 * Each is considered a sibling to the other in terms of sharing
935 * the same extraction sequence entry.
936 */
937 if (fld == ICE_FLOW_FIELD_IDX_IPV4_TTL)
938 sib = ICE_FLOW_FIELD_IDX_IPV4_PROT;
939 else if (fld == ICE_FLOW_FIELD_IDX_IPV4_PROT)
940 sib = ICE_FLOW_FIELD_IDX_IPV4_TTL;
941
942 /* If the sibling field is also included, that field's
943 * mask needs to be included.
944 */
945 if (match & BIT(sib))
946 sib_mask = ice_flds_info[sib].mask;
947 break;
948 case ICE_FLOW_FIELD_IDX_IPV6_TTL:
949 case ICE_FLOW_FIELD_IDX_IPV6_PROT:
950 prot_id = seg == 0 ? ICE_PROT_IPV6_OF_OR_S : ICE_PROT_IPV6_IL;
951
952 /* TTL and PROT share the same extraction seq. entry.
953 * Each is considered a sibling to the other in terms of sharing
954 * the same extraction sequence entry.
955 */
956 if (fld == ICE_FLOW_FIELD_IDX_IPV6_TTL)
957 sib = ICE_FLOW_FIELD_IDX_IPV6_PROT;
958 else if (fld == ICE_FLOW_FIELD_IDX_IPV6_PROT)
959 sib = ICE_FLOW_FIELD_IDX_IPV6_TTL;
960
961 /* If the sibling field is also included, that field's
962 * mask needs to be included.
963 */
964 if (match & BIT(sib))
965 sib_mask = ice_flds_info[sib].mask;
966 break;
967 case ICE_FLOW_FIELD_IDX_IPV4_SA:
968 case ICE_FLOW_FIELD_IDX_IPV4_DA:
969 prot_id = seg == 0 ? ICE_PROT_IPV4_OF_OR_S : ICE_PROT_IPV4_IL;
970 break;
971 case ICE_FLOW_FIELD_IDX_IPV6_SA:
972 case ICE_FLOW_FIELD_IDX_IPV6_DA:
973 prot_id = seg == 0 ? ICE_PROT_IPV6_OF_OR_S : ICE_PROT_IPV6_IL;
974 break;
975 case ICE_FLOW_FIELD_IDX_TCP_SRC_PORT:
976 case ICE_FLOW_FIELD_IDX_TCP_DST_PORT:
977 case ICE_FLOW_FIELD_IDX_TCP_FLAGS:
978 prot_id = ICE_PROT_TCP_IL;
979 break;
980 case ICE_FLOW_FIELD_IDX_UDP_SRC_PORT:
981 case ICE_FLOW_FIELD_IDX_UDP_DST_PORT:
982 prot_id = ICE_PROT_UDP_IL_OR_S;
983 break;
984 case ICE_FLOW_FIELD_IDX_SCTP_SRC_PORT:
985 case ICE_FLOW_FIELD_IDX_SCTP_DST_PORT:
986 prot_id = ICE_PROT_SCTP_IL;
987 break;
988 case ICE_FLOW_FIELD_IDX_GTPC_TEID:
989 case ICE_FLOW_FIELD_IDX_GTPU_IP_TEID:
990 case ICE_FLOW_FIELD_IDX_GTPU_UP_TEID:
991 case ICE_FLOW_FIELD_IDX_GTPU_DWN_TEID:
992 case ICE_FLOW_FIELD_IDX_GTPU_EH_TEID:
993 case ICE_FLOW_FIELD_IDX_GTPU_EH_QFI:
994 /* GTP is accessed through UDP OF protocol */
995 prot_id = ICE_PROT_UDP_OF;
996 break;
997 case ICE_FLOW_FIELD_IDX_PPPOE_SESS_ID:
998 prot_id = ICE_PROT_PPPOE;
999 break;
1000 case ICE_FLOW_FIELD_IDX_PFCP_SEID:
1001 prot_id = ICE_PROT_UDP_IL_OR_S;
1002 break;
1003 case ICE_FLOW_FIELD_IDX_L2TPV3_SESS_ID:
1004 prot_id = ICE_PROT_L2TPV3;
1005 break;
1006 case ICE_FLOW_FIELD_IDX_ESP_SPI:
1007 prot_id = ICE_PROT_ESP_F;
1008 break;
1009 case ICE_FLOW_FIELD_IDX_AH_SPI:
1010 prot_id = ICE_PROT_ESP_2;
1011 break;
1012 case ICE_FLOW_FIELD_IDX_NAT_T_ESP_SPI:
1013 prot_id = ICE_PROT_UDP_IL_OR_S;
1014 break;
1015 case ICE_FLOW_FIELD_IDX_ARP_SIP:
1016 case ICE_FLOW_FIELD_IDX_ARP_DIP:
1017 case ICE_FLOW_FIELD_IDX_ARP_SHA:
1018 case ICE_FLOW_FIELD_IDX_ARP_DHA:
1019 case ICE_FLOW_FIELD_IDX_ARP_OP:
1020 prot_id = ICE_PROT_ARP_OF;
1021 break;
1022 case ICE_FLOW_FIELD_IDX_ICMP_TYPE:
1023 case ICE_FLOW_FIELD_IDX_ICMP_CODE:
1024 /* ICMP type and code share the same extraction seq. entry */
1025 prot_id = (params->prof->segs[seg].hdrs & ICE_FLOW_SEG_HDR_IPV4) ?
1026 ICE_PROT_ICMP_IL : ICE_PROT_ICMPV6_IL;
1027 sib = fld == ICE_FLOW_FIELD_IDX_ICMP_TYPE ?
1028 ICE_FLOW_FIELD_IDX_ICMP_CODE :
1029 ICE_FLOW_FIELD_IDX_ICMP_TYPE;
1030 break;
1031 case ICE_FLOW_FIELD_IDX_GRE_KEYID:
1032 prot_id = ICE_PROT_GRE_OF;
1033 break;
1034 default:
1035 return -EOPNOTSUPP;
1036 }
1037
1038 /* Each extraction sequence entry is a word in size, and extracts a
1039 * word-aligned offset from a protocol header.
1040 */
1041 ese_bits = ICE_FLOW_FV_EXTRACT_SZ * BITS_PER_BYTE;
1042
1043 flds[fld].xtrct.prot_id = prot_id;
1044 flds[fld].xtrct.off = (ice_flds_info[fld].off / ese_bits) *
1045 ICE_FLOW_FV_EXTRACT_SZ;
1046 flds[fld].xtrct.disp = (u8)(ice_flds_info[fld].off % ese_bits);
1047 flds[fld].xtrct.idx = params->es_cnt;
1048 flds[fld].xtrct.mask = ice_flds_info[fld].mask;
1049
1050 /* Adjust the next field-entry index after accommodating the number of
1051 * entries this field consumes
1052 */
1053 cnt = DIV_ROUND_UP(flds[fld].xtrct.disp + ice_flds_info[fld].size,
1054 ese_bits);
1055
1056 /* Fill in the extraction sequence entries needed for this field */
1057 off = flds[fld].xtrct.off;
1058 mask = flds[fld].xtrct.mask;
1059 for (i = 0; i < cnt; i++) {
1060 /* Only consume an extraction sequence entry if there is no
1061 * sibling field associated with this field or the sibling entry
1062 * already extracts the word shared with this field.
1063 */
1064 if (sib == ICE_FLOW_FIELD_IDX_MAX ||
1065 flds[sib].xtrct.prot_id == ICE_PROT_ID_INVAL ||
1066 flds[sib].xtrct.off != off) {
1067 u8 idx;
1068
1069 /* Make sure the number of extraction sequence required
1070 * does not exceed the block's capability
1071 */
1072 if (params->es_cnt >= fv_words)
1073 return -ENOSPC;
1074
1075 /* some blocks require a reversed field vector layout */
1076 if (hw->blk[params->blk].es.reverse)
1077 idx = fv_words - params->es_cnt - 1;
1078 else
1079 idx = params->es_cnt;
1080
1081 params->es[idx].prot_id = prot_id;
1082 params->es[idx].off = off;
1083 params->mask[idx] = mask | sib_mask;
1084 params->es_cnt++;
1085 }
1086
1087 off += ICE_FLOW_FV_EXTRACT_SZ;
1088 }
1089
1090 return 0;
1091}
1092
1093/**
1094 * ice_flow_xtract_raws - Create extract sequence entries for raw bytes
1095 * @hw: pointer to the HW struct
1096 * @params: information about the flow to be processed
1097 * @seg: index of packet segment whose raw fields are to be extracted
1098 */
1099static int
1100ice_flow_xtract_raws(struct ice_hw *hw, struct ice_flow_prof_params *params,
1101 u8 seg)
1102{
1103 u16 fv_words;
1104 u16 hdrs_sz;
1105 u8 i;
1106
1107 if (!params->prof->segs[seg].raws_cnt)
1108 return 0;
1109
1110 if (params->prof->segs[seg].raws_cnt >
1111 ARRAY_SIZE(params->prof->segs[seg].raws))
1112 return -ENOSPC;
1113
1114 /* Offsets within the segment headers are not supported */
1115 hdrs_sz = ice_flow_calc_seg_sz(params, seg);
1116 if (!hdrs_sz)
1117 return -EINVAL;
1118
1119 fv_words = hw->blk[params->blk].es.fvw;
1120
1121 for (i = 0; i < params->prof->segs[seg].raws_cnt; i++) {
1122 struct ice_flow_seg_fld_raw *raw;
1123 u16 off, cnt, j;
1124
1125 raw = ¶ms->prof->segs[seg].raws[i];
1126
1127 /* Storing extraction information */
1128 raw->info.xtrct.prot_id = ICE_PROT_MAC_OF_OR_S;
1129 raw->info.xtrct.off = (raw->off / ICE_FLOW_FV_EXTRACT_SZ) *
1130 ICE_FLOW_FV_EXTRACT_SZ;
1131 raw->info.xtrct.disp = (raw->off % ICE_FLOW_FV_EXTRACT_SZ) *
1132 BITS_PER_BYTE;
1133 raw->info.xtrct.idx = params->es_cnt;
1134
1135 /* Determine the number of field vector entries this raw field
1136 * consumes.
1137 */
1138 cnt = DIV_ROUND_UP(raw->info.xtrct.disp +
1139 (raw->info.src.last * BITS_PER_BYTE),
1140 (ICE_FLOW_FV_EXTRACT_SZ * BITS_PER_BYTE));
1141 off = raw->info.xtrct.off;
1142 for (j = 0; j < cnt; j++) {
1143 u16 idx;
1144
1145 /* Make sure the number of extraction sequence required
1146 * does not exceed the block's capability
1147 */
1148 if (params->es_cnt >= hw->blk[params->blk].es.count ||
1149 params->es_cnt >= ICE_MAX_FV_WORDS)
1150 return -ENOSPC;
1151
1152 /* some blocks require a reversed field vector layout */
1153 if (hw->blk[params->blk].es.reverse)
1154 idx = fv_words - params->es_cnt - 1;
1155 else
1156 idx = params->es_cnt;
1157
1158 params->es[idx].prot_id = raw->info.xtrct.prot_id;
1159 params->es[idx].off = off;
1160 params->es_cnt++;
1161 off += ICE_FLOW_FV_EXTRACT_SZ;
1162 }
1163 }
1164
1165 return 0;
1166}
1167
1168/**
1169 * ice_flow_create_xtrct_seq - Create an extraction sequence for given segments
1170 * @hw: pointer to the HW struct
1171 * @params: information about the flow to be processed
1172 *
1173 * This function iterates through all matched fields in the given segments, and
1174 * creates an extraction sequence for the fields.
1175 */
1176static int
1177ice_flow_create_xtrct_seq(struct ice_hw *hw,
1178 struct ice_flow_prof_params *params)
1179{
1180 struct ice_flow_prof *prof = params->prof;
1181 int status = 0;
1182 u8 i;
1183
1184 for (i = 0; i < prof->segs_cnt; i++) {
1185 u64 match = params->prof->segs[i].match;
1186 enum ice_flow_field j;
1187
1188 for_each_set_bit(j, (unsigned long *)&match,
1189 ICE_FLOW_FIELD_IDX_MAX) {
1190 status = ice_flow_xtract_fld(hw, params, i, j, match);
1191 if (status)
1192 return status;
1193 clear_bit(j, (unsigned long *)&match);
1194 }
1195
1196 /* Process raw matching bytes */
1197 status = ice_flow_xtract_raws(hw, params, i);
1198 if (status)
1199 return status;
1200 }
1201
1202 return status;
1203}
1204
1205/**
1206 * ice_flow_proc_segs - process all packet segments associated with a profile
1207 * @hw: pointer to the HW struct
1208 * @params: information about the flow to be processed
1209 */
1210static int
1211ice_flow_proc_segs(struct ice_hw *hw, struct ice_flow_prof_params *params)
1212{
1213 int status;
1214
1215 status = ice_flow_proc_seg_hdrs(params);
1216 if (status)
1217 return status;
1218
1219 status = ice_flow_create_xtrct_seq(hw, params);
1220 if (status)
1221 return status;
1222
1223 switch (params->blk) {
1224 case ICE_BLK_FD:
1225 case ICE_BLK_RSS:
1226 status = 0;
1227 break;
1228 default:
1229 return -EOPNOTSUPP;
1230 }
1231
1232 return status;
1233}
1234
1235#define ICE_FLOW_FIND_PROF_CHK_FLDS 0x00000001
1236#define ICE_FLOW_FIND_PROF_CHK_VSI 0x00000002
1237#define ICE_FLOW_FIND_PROF_NOT_CHK_DIR 0x00000004
1238#define ICE_FLOW_FIND_PROF_CHK_SYMM 0x00000008
1239
1240/**
1241 * ice_flow_find_prof_conds - Find a profile matching headers and conditions
1242 * @hw: pointer to the HW struct
1243 * @blk: classification stage
1244 * @dir: flow direction
1245 * @segs: array of one or more packet segments that describe the flow
1246 * @segs_cnt: number of packet segments provided
1247 * @symm: symmetric setting for RSS profiles
1248 * @vsi_handle: software VSI handle to check VSI (ICE_FLOW_FIND_PROF_CHK_VSI)
1249 * @conds: additional conditions to be checked (ICE_FLOW_FIND_PROF_CHK_*)
1250 */
1251static struct ice_flow_prof *
1252ice_flow_find_prof_conds(struct ice_hw *hw, enum ice_block blk,
1253 enum ice_flow_dir dir, struct ice_flow_seg_info *segs,
1254 u8 segs_cnt, bool symm, u16 vsi_handle, u32 conds)
1255{
1256 struct ice_flow_prof *p, *prof = NULL;
1257
1258 mutex_lock(&hw->fl_profs_locks[blk]);
1259 list_for_each_entry(p, &hw->fl_profs[blk], l_entry)
1260 if ((p->dir == dir || conds & ICE_FLOW_FIND_PROF_NOT_CHK_DIR) &&
1261 segs_cnt && segs_cnt == p->segs_cnt) {
1262 u8 i;
1263
1264 /* Check for profile-VSI association if specified */
1265 if ((conds & ICE_FLOW_FIND_PROF_CHK_VSI) &&
1266 ice_is_vsi_valid(hw, vsi_handle) &&
1267 !test_bit(vsi_handle, p->vsis))
1268 continue;
1269
1270 /* Check for symmetric settings */
1271 if ((conds & ICE_FLOW_FIND_PROF_CHK_SYMM) &&
1272 p->symm != symm)
1273 continue;
1274
1275 /* Protocol headers must be checked. Matched fields are
1276 * checked if specified.
1277 */
1278 for (i = 0; i < segs_cnt; i++)
1279 if (segs[i].hdrs != p->segs[i].hdrs ||
1280 ((conds & ICE_FLOW_FIND_PROF_CHK_FLDS) &&
1281 segs[i].match != p->segs[i].match))
1282 break;
1283
1284 /* A match is found if all segments are matched */
1285 if (i == segs_cnt) {
1286 prof = p;
1287 break;
1288 }
1289 }
1290 mutex_unlock(&hw->fl_profs_locks[blk]);
1291
1292 return prof;
1293}
1294
1295/**
1296 * ice_flow_find_prof_id - Look up a profile with given profile ID
1297 * @hw: pointer to the HW struct
1298 * @blk: classification stage
1299 * @prof_id: unique ID to identify this flow profile
1300 */
1301static struct ice_flow_prof *
1302ice_flow_find_prof_id(struct ice_hw *hw, enum ice_block blk, u64 prof_id)
1303{
1304 struct ice_flow_prof *p;
1305
1306 list_for_each_entry(p, &hw->fl_profs[blk], l_entry)
1307 if (p->id == prof_id)
1308 return p;
1309
1310 return NULL;
1311}
1312
1313/**
1314 * ice_flow_rem_entry_sync - Remove a flow entry
1315 * @hw: pointer to the HW struct
1316 * @blk: classification stage
1317 * @entry: flow entry to be removed
1318 */
1319static int
1320ice_flow_rem_entry_sync(struct ice_hw *hw, enum ice_block __always_unused blk,
1321 struct ice_flow_entry *entry)
1322{
1323 if (!entry)
1324 return -EINVAL;
1325
1326 list_del(&entry->l_entry);
1327
1328 devm_kfree(ice_hw_to_dev(hw), entry);
1329
1330 return 0;
1331}
1332
1333/**
1334 * ice_flow_add_prof_sync - Add a flow profile for packet segments and fields
1335 * @hw: pointer to the HW struct
1336 * @blk: classification stage
1337 * @dir: flow direction
1338 * @segs: array of one or more packet segments that describe the flow
1339 * @segs_cnt: number of packet segments provided
1340 * @symm: symmetric setting for RSS profiles
1341 * @prof: stores the returned flow profile added
1342 *
1343 * Assumption: the caller has acquired the lock to the profile list
1344 */
1345static int
1346ice_flow_add_prof_sync(struct ice_hw *hw, enum ice_block blk,
1347 enum ice_flow_dir dir,
1348 struct ice_flow_seg_info *segs, u8 segs_cnt,
1349 bool symm, struct ice_flow_prof **prof)
1350{
1351 struct ice_flow_prof_params *params;
1352 struct ice_prof_id *ids;
1353 int status;
1354 u64 prof_id;
1355 u8 i;
1356
1357 if (!prof)
1358 return -EINVAL;
1359
1360 ids = &hw->blk[blk].prof_id;
1361 prof_id = find_first_zero_bit(ids->id, ids->count);
1362 if (prof_id >= ids->count)
1363 return -ENOSPC;
1364
1365 params = kzalloc(sizeof(*params), GFP_KERNEL);
1366 if (!params)
1367 return -ENOMEM;
1368
1369 params->prof = devm_kzalloc(ice_hw_to_dev(hw), sizeof(*params->prof),
1370 GFP_KERNEL);
1371 if (!params->prof) {
1372 status = -ENOMEM;
1373 goto free_params;
1374 }
1375
1376 /* initialize extraction sequence to all invalid (0xff) */
1377 for (i = 0; i < ICE_MAX_FV_WORDS; i++) {
1378 params->es[i].prot_id = ICE_PROT_INVALID;
1379 params->es[i].off = ICE_FV_OFFSET_INVAL;
1380 }
1381
1382 params->blk = blk;
1383 params->prof->id = prof_id;
1384 params->prof->dir = dir;
1385 params->prof->segs_cnt = segs_cnt;
1386 params->prof->symm = symm;
1387
1388 /* Make a copy of the segments that need to be persistent in the flow
1389 * profile instance
1390 */
1391 for (i = 0; i < segs_cnt; i++)
1392 memcpy(¶ms->prof->segs[i], &segs[i], sizeof(*segs));
1393
1394 status = ice_flow_proc_segs(hw, params);
1395 if (status) {
1396 ice_debug(hw, ICE_DBG_FLOW, "Error processing a flow's packet segments\n");
1397 goto out;
1398 }
1399
1400 /* Add a HW profile for this flow profile */
1401 status = ice_add_prof(hw, blk, prof_id, (u8 *)params->ptypes,
1402 params->attr, params->attr_cnt, params->es,
1403 params->mask, symm);
1404 if (status) {
1405 ice_debug(hw, ICE_DBG_FLOW, "Error adding a HW flow profile\n");
1406 goto out;
1407 }
1408
1409 INIT_LIST_HEAD(¶ms->prof->entries);
1410 mutex_init(¶ms->prof->entries_lock);
1411 set_bit(prof_id, ids->id);
1412 *prof = params->prof;
1413
1414out:
1415 if (status)
1416 devm_kfree(ice_hw_to_dev(hw), params->prof);
1417free_params:
1418 kfree(params);
1419
1420 return status;
1421}
1422
1423/**
1424 * ice_flow_rem_prof_sync - remove a flow profile
1425 * @hw: pointer to the hardware structure
1426 * @blk: classification stage
1427 * @prof: pointer to flow profile to remove
1428 *
1429 * Assumption: the caller has acquired the lock to the profile list
1430 */
1431static int
1432ice_flow_rem_prof_sync(struct ice_hw *hw, enum ice_block blk,
1433 struct ice_flow_prof *prof)
1434{
1435 int status;
1436
1437 /* Remove all remaining flow entries before removing the flow profile */
1438 if (!list_empty(&prof->entries)) {
1439 struct ice_flow_entry *e, *t;
1440
1441 mutex_lock(&prof->entries_lock);
1442
1443 list_for_each_entry_safe(e, t, &prof->entries, l_entry) {
1444 status = ice_flow_rem_entry_sync(hw, blk, e);
1445 if (status)
1446 break;
1447 }
1448
1449 mutex_unlock(&prof->entries_lock);
1450 }
1451
1452 /* Remove all hardware profiles associated with this flow profile */
1453 status = ice_rem_prof(hw, blk, prof->id);
1454 if (!status) {
1455 clear_bit(prof->id, hw->blk[blk].prof_id.id);
1456 list_del(&prof->l_entry);
1457 mutex_destroy(&prof->entries_lock);
1458 devm_kfree(ice_hw_to_dev(hw), prof);
1459 }
1460
1461 return status;
1462}
1463
1464/**
1465 * ice_flow_assoc_prof - associate a VSI with a flow profile
1466 * @hw: pointer to the hardware structure
1467 * @blk: classification stage
1468 * @prof: pointer to flow profile
1469 * @vsi_handle: software VSI handle
1470 *
1471 * Assumption: the caller has acquired the lock to the profile list
1472 * and the software VSI handle has been validated
1473 */
1474static int
1475ice_flow_assoc_prof(struct ice_hw *hw, enum ice_block blk,
1476 struct ice_flow_prof *prof, u16 vsi_handle)
1477{
1478 int status = 0;
1479
1480 if (!test_bit(vsi_handle, prof->vsis)) {
1481 status = ice_add_prof_id_flow(hw, blk,
1482 ice_get_hw_vsi_num(hw,
1483 vsi_handle),
1484 prof->id);
1485 if (!status)
1486 set_bit(vsi_handle, prof->vsis);
1487 else
1488 ice_debug(hw, ICE_DBG_FLOW, "HW profile add failed, %d\n",
1489 status);
1490 }
1491
1492 return status;
1493}
1494
1495/**
1496 * ice_flow_disassoc_prof - disassociate a VSI from a flow profile
1497 * @hw: pointer to the hardware structure
1498 * @blk: classification stage
1499 * @prof: pointer to flow profile
1500 * @vsi_handle: software VSI handle
1501 *
1502 * Assumption: the caller has acquired the lock to the profile list
1503 * and the software VSI handle has been validated
1504 */
1505static int
1506ice_flow_disassoc_prof(struct ice_hw *hw, enum ice_block blk,
1507 struct ice_flow_prof *prof, u16 vsi_handle)
1508{
1509 int status = 0;
1510
1511 if (test_bit(vsi_handle, prof->vsis)) {
1512 status = ice_rem_prof_id_flow(hw, blk,
1513 ice_get_hw_vsi_num(hw,
1514 vsi_handle),
1515 prof->id);
1516 if (!status)
1517 clear_bit(vsi_handle, prof->vsis);
1518 else
1519 ice_debug(hw, ICE_DBG_FLOW, "HW profile remove failed, %d\n",
1520 status);
1521 }
1522
1523 return status;
1524}
1525
1526/**
1527 * ice_flow_add_prof - Add a flow profile for packet segments and matched fields
1528 * @hw: pointer to the HW struct
1529 * @blk: classification stage
1530 * @dir: flow direction
1531 * @segs: array of one or more packet segments that describe the flow
1532 * @segs_cnt: number of packet segments provided
1533 * @symm: symmetric setting for RSS profiles
1534 * @prof: stores the returned flow profile added
1535 */
1536int
1537ice_flow_add_prof(struct ice_hw *hw, enum ice_block blk, enum ice_flow_dir dir,
1538 struct ice_flow_seg_info *segs, u8 segs_cnt,
1539 bool symm, struct ice_flow_prof **prof)
1540{
1541 int status;
1542
1543 if (segs_cnt > ICE_FLOW_SEG_MAX)
1544 return -ENOSPC;
1545
1546 if (!segs_cnt)
1547 return -EINVAL;
1548
1549 if (!segs)
1550 return -EINVAL;
1551
1552 status = ice_flow_val_hdrs(segs, segs_cnt);
1553 if (status)
1554 return status;
1555
1556 mutex_lock(&hw->fl_profs_locks[blk]);
1557
1558 status = ice_flow_add_prof_sync(hw, blk, dir, segs, segs_cnt,
1559 symm, prof);
1560 if (!status)
1561 list_add(&(*prof)->l_entry, &hw->fl_profs[blk]);
1562
1563 mutex_unlock(&hw->fl_profs_locks[blk]);
1564
1565 return status;
1566}
1567
1568/**
1569 * ice_flow_rem_prof - Remove a flow profile and all entries associated with it
1570 * @hw: pointer to the HW struct
1571 * @blk: the block for which the flow profile is to be removed
1572 * @prof_id: unique ID of the flow profile to be removed
1573 */
1574int ice_flow_rem_prof(struct ice_hw *hw, enum ice_block blk, u64 prof_id)
1575{
1576 struct ice_flow_prof *prof;
1577 int status;
1578
1579 mutex_lock(&hw->fl_profs_locks[blk]);
1580
1581 prof = ice_flow_find_prof_id(hw, blk, prof_id);
1582 if (!prof) {
1583 status = -ENOENT;
1584 goto out;
1585 }
1586
1587 /* prof becomes invalid after the call */
1588 status = ice_flow_rem_prof_sync(hw, blk, prof);
1589
1590out:
1591 mutex_unlock(&hw->fl_profs_locks[blk]);
1592
1593 return status;
1594}
1595
1596/**
1597 * ice_flow_add_entry - Add a flow entry
1598 * @hw: pointer to the HW struct
1599 * @blk: classification stage
1600 * @prof_id: ID of the profile to add a new flow entry to
1601 * @entry_id: unique ID to identify this flow entry
1602 * @vsi_handle: software VSI handle for the flow entry
1603 * @prio: priority of the flow entry
1604 * @data: pointer to a data buffer containing flow entry's match values/masks
1605 * @entry_h: pointer to buffer that receives the new flow entry's handle
1606 */
1607int
1608ice_flow_add_entry(struct ice_hw *hw, enum ice_block blk, u64 prof_id,
1609 u64 entry_id, u16 vsi_handle, enum ice_flow_priority prio,
1610 void *data, u64 *entry_h)
1611{
1612 struct ice_flow_entry *e = NULL;
1613 struct ice_flow_prof *prof;
1614 int status;
1615
1616 /* No flow entry data is expected for RSS */
1617 if (!entry_h || (!data && blk != ICE_BLK_RSS))
1618 return -EINVAL;
1619
1620 if (!ice_is_vsi_valid(hw, vsi_handle))
1621 return -EINVAL;
1622
1623 mutex_lock(&hw->fl_profs_locks[blk]);
1624
1625 prof = ice_flow_find_prof_id(hw, blk, prof_id);
1626 if (!prof) {
1627 status = -ENOENT;
1628 } else {
1629 /* Allocate memory for the entry being added and associate
1630 * the VSI to the found flow profile
1631 */
1632 e = devm_kzalloc(ice_hw_to_dev(hw), sizeof(*e), GFP_KERNEL);
1633 if (!e)
1634 status = -ENOMEM;
1635 else
1636 status = ice_flow_assoc_prof(hw, blk, prof, vsi_handle);
1637 }
1638
1639 mutex_unlock(&hw->fl_profs_locks[blk]);
1640 if (status)
1641 goto out;
1642
1643 e->id = entry_id;
1644 e->vsi_handle = vsi_handle;
1645 e->prof = prof;
1646 e->priority = prio;
1647
1648 switch (blk) {
1649 case ICE_BLK_FD:
1650 case ICE_BLK_RSS:
1651 break;
1652 default:
1653 status = -EOPNOTSUPP;
1654 goto out;
1655 }
1656
1657 mutex_lock(&prof->entries_lock);
1658 list_add(&e->l_entry, &prof->entries);
1659 mutex_unlock(&prof->entries_lock);
1660
1661 *entry_h = ICE_FLOW_ENTRY_HNDL(e);
1662
1663out:
1664 if (status)
1665 devm_kfree(ice_hw_to_dev(hw), e);
1666
1667 return status;
1668}
1669
1670/**
1671 * ice_flow_rem_entry - Remove a flow entry
1672 * @hw: pointer to the HW struct
1673 * @blk: classification stage
1674 * @entry_h: handle to the flow entry to be removed
1675 */
1676int ice_flow_rem_entry(struct ice_hw *hw, enum ice_block blk, u64 entry_h)
1677{
1678 struct ice_flow_entry *entry;
1679 struct ice_flow_prof *prof;
1680 int status = 0;
1681
1682 if (entry_h == ICE_FLOW_ENTRY_HANDLE_INVAL)
1683 return -EINVAL;
1684
1685 entry = ICE_FLOW_ENTRY_PTR(entry_h);
1686
1687 /* Retain the pointer to the flow profile as the entry will be freed */
1688 prof = entry->prof;
1689
1690 if (prof) {
1691 mutex_lock(&prof->entries_lock);
1692 status = ice_flow_rem_entry_sync(hw, blk, entry);
1693 mutex_unlock(&prof->entries_lock);
1694 }
1695
1696 return status;
1697}
1698
1699/**
1700 * ice_flow_set_fld_ext - specifies locations of field from entry's input buffer
1701 * @seg: packet segment the field being set belongs to
1702 * @fld: field to be set
1703 * @field_type: type of the field
1704 * @val_loc: if not ICE_FLOW_FLD_OFF_INVAL, location of the value to match from
1705 * entry's input buffer
1706 * @mask_loc: if not ICE_FLOW_FLD_OFF_INVAL, location of mask value from entry's
1707 * input buffer
1708 * @last_loc: if not ICE_FLOW_FLD_OFF_INVAL, location of last/upper value from
1709 * entry's input buffer
1710 *
1711 * This helper function stores information of a field being matched, including
1712 * the type of the field and the locations of the value to match, the mask, and
1713 * the upper-bound value in the start of the input buffer for a flow entry.
1714 * This function should only be used for fixed-size data structures.
1715 *
1716 * This function also opportunistically determines the protocol headers to be
1717 * present based on the fields being set. Some fields cannot be used alone to
1718 * determine the protocol headers present. Sometimes, fields for particular
1719 * protocol headers are not matched. In those cases, the protocol headers
1720 * must be explicitly set.
1721 */
1722static void
1723ice_flow_set_fld_ext(struct ice_flow_seg_info *seg, enum ice_flow_field fld,
1724 enum ice_flow_fld_match_type field_type, u16 val_loc,
1725 u16 mask_loc, u16 last_loc)
1726{
1727 u64 bit = BIT_ULL(fld);
1728
1729 seg->match |= bit;
1730 if (field_type == ICE_FLOW_FLD_TYPE_RANGE)
1731 seg->range |= bit;
1732
1733 seg->fields[fld].type = field_type;
1734 seg->fields[fld].src.val = val_loc;
1735 seg->fields[fld].src.mask = mask_loc;
1736 seg->fields[fld].src.last = last_loc;
1737
1738 ICE_FLOW_SET_HDRS(seg, ice_flds_info[fld].hdr);
1739}
1740
1741/**
1742 * ice_flow_set_fld - specifies locations of field from entry's input buffer
1743 * @seg: packet segment the field being set belongs to
1744 * @fld: field to be set
1745 * @val_loc: if not ICE_FLOW_FLD_OFF_INVAL, location of the value to match from
1746 * entry's input buffer
1747 * @mask_loc: if not ICE_FLOW_FLD_OFF_INVAL, location of mask value from entry's
1748 * input buffer
1749 * @last_loc: if not ICE_FLOW_FLD_OFF_INVAL, location of last/upper value from
1750 * entry's input buffer
1751 * @range: indicate if field being matched is to be in a range
1752 *
1753 * This function specifies the locations, in the form of byte offsets from the
1754 * start of the input buffer for a flow entry, from where the value to match,
1755 * the mask value, and upper value can be extracted. These locations are then
1756 * stored in the flow profile. When adding a flow entry associated with the
1757 * flow profile, these locations will be used to quickly extract the values and
1758 * create the content of a match entry. This function should only be used for
1759 * fixed-size data structures.
1760 */
1761void
1762ice_flow_set_fld(struct ice_flow_seg_info *seg, enum ice_flow_field fld,
1763 u16 val_loc, u16 mask_loc, u16 last_loc, bool range)
1764{
1765 enum ice_flow_fld_match_type t = range ?
1766 ICE_FLOW_FLD_TYPE_RANGE : ICE_FLOW_FLD_TYPE_REG;
1767
1768 ice_flow_set_fld_ext(seg, fld, t, val_loc, mask_loc, last_loc);
1769}
1770
1771/**
1772 * ice_flow_add_fld_raw - sets locations of a raw field from entry's input buf
1773 * @seg: packet segment the field being set belongs to
1774 * @off: offset of the raw field from the beginning of the segment in bytes
1775 * @len: length of the raw pattern to be matched
1776 * @val_loc: location of the value to match from entry's input buffer
1777 * @mask_loc: location of mask value from entry's input buffer
1778 *
1779 * This function specifies the offset of the raw field to be match from the
1780 * beginning of the specified packet segment, and the locations, in the form of
1781 * byte offsets from the start of the input buffer for a flow entry, from where
1782 * the value to match and the mask value to be extracted. These locations are
1783 * then stored in the flow profile. When adding flow entries to the associated
1784 * flow profile, these locations can be used to quickly extract the values to
1785 * create the content of a match entry. This function should only be used for
1786 * fixed-size data structures.
1787 */
1788void
1789ice_flow_add_fld_raw(struct ice_flow_seg_info *seg, u16 off, u8 len,
1790 u16 val_loc, u16 mask_loc)
1791{
1792 if (seg->raws_cnt < ICE_FLOW_SEG_RAW_FLD_MAX) {
1793 seg->raws[seg->raws_cnt].off = off;
1794 seg->raws[seg->raws_cnt].info.type = ICE_FLOW_FLD_TYPE_SIZE;
1795 seg->raws[seg->raws_cnt].info.src.val = val_loc;
1796 seg->raws[seg->raws_cnt].info.src.mask = mask_loc;
1797 /* The "last" field is used to store the length of the field */
1798 seg->raws[seg->raws_cnt].info.src.last = len;
1799 }
1800
1801 /* Overflows of "raws" will be handled as an error condition later in
1802 * the flow when this information is processed.
1803 */
1804 seg->raws_cnt++;
1805}
1806
1807/**
1808 * ice_flow_rem_vsi_prof - remove VSI from flow profile
1809 * @hw: pointer to the hardware structure
1810 * @vsi_handle: software VSI handle
1811 * @prof_id: unique ID to identify this flow profile
1812 *
1813 * This function removes the flow entries associated to the input
1814 * VSI handle and disassociate the VSI from the flow profile.
1815 */
1816int ice_flow_rem_vsi_prof(struct ice_hw *hw, u16 vsi_handle, u64 prof_id)
1817{
1818 struct ice_flow_prof *prof;
1819 int status = 0;
1820
1821 if (!ice_is_vsi_valid(hw, vsi_handle))
1822 return -EINVAL;
1823
1824 /* find flow profile pointer with input package block and profile ID */
1825 prof = ice_flow_find_prof_id(hw, ICE_BLK_FD, prof_id);
1826 if (!prof) {
1827 ice_debug(hw, ICE_DBG_PKG, "Cannot find flow profile id=%llu\n",
1828 prof_id);
1829 return -ENOENT;
1830 }
1831
1832 /* Remove all remaining flow entries before removing the flow profile */
1833 if (!list_empty(&prof->entries)) {
1834 struct ice_flow_entry *e, *t;
1835
1836 mutex_lock(&prof->entries_lock);
1837 list_for_each_entry_safe(e, t, &prof->entries, l_entry) {
1838 if (e->vsi_handle != vsi_handle)
1839 continue;
1840
1841 status = ice_flow_rem_entry_sync(hw, ICE_BLK_FD, e);
1842 if (status)
1843 break;
1844 }
1845 mutex_unlock(&prof->entries_lock);
1846 }
1847 if (status)
1848 return status;
1849
1850 /* disassociate the flow profile from sw VSI handle */
1851 status = ice_flow_disassoc_prof(hw, ICE_BLK_FD, prof, vsi_handle);
1852 if (status)
1853 ice_debug(hw, ICE_DBG_PKG, "ice_flow_disassoc_prof() failed with status=%d\n",
1854 status);
1855 return status;
1856}
1857
1858#define ICE_FLOW_RSS_SEG_HDR_L2_MASKS \
1859 (ICE_FLOW_SEG_HDR_ETH | ICE_FLOW_SEG_HDR_VLAN)
1860
1861#define ICE_FLOW_RSS_SEG_HDR_L3_MASKS \
1862 (ICE_FLOW_SEG_HDR_IPV4 | ICE_FLOW_SEG_HDR_IPV6)
1863
1864#define ICE_FLOW_RSS_SEG_HDR_L4_MASKS \
1865 (ICE_FLOW_SEG_HDR_TCP | ICE_FLOW_SEG_HDR_UDP | ICE_FLOW_SEG_HDR_SCTP)
1866
1867#define ICE_FLOW_RSS_SEG_HDR_VAL_MASKS \
1868 (ICE_FLOW_RSS_SEG_HDR_L2_MASKS | \
1869 ICE_FLOW_RSS_SEG_HDR_L3_MASKS | \
1870 ICE_FLOW_RSS_SEG_HDR_L4_MASKS)
1871
1872/**
1873 * ice_flow_set_rss_seg_info - setup packet segments for RSS
1874 * @segs: pointer to the flow field segment(s)
1875 * @seg_cnt: segment count
1876 * @cfg: configure parameters
1877 *
1878 * Helper function to extract fields from hash bitmap and use flow
1879 * header value to set flow field segment for further use in flow
1880 * profile entry or removal.
1881 */
1882static int
1883ice_flow_set_rss_seg_info(struct ice_flow_seg_info *segs, u8 seg_cnt,
1884 const struct ice_rss_hash_cfg *cfg)
1885{
1886 struct ice_flow_seg_info *seg;
1887 u64 val;
1888 u16 i;
1889
1890 /* set inner most segment */
1891 seg = &segs[seg_cnt - 1];
1892
1893 for_each_set_bit(i, (const unsigned long *)&cfg->hash_flds,
1894 (u16)ICE_FLOW_FIELD_IDX_MAX)
1895 ice_flow_set_fld(seg, (enum ice_flow_field)i,
1896 ICE_FLOW_FLD_OFF_INVAL, ICE_FLOW_FLD_OFF_INVAL,
1897 ICE_FLOW_FLD_OFF_INVAL, false);
1898
1899 ICE_FLOW_SET_HDRS(seg, cfg->addl_hdrs);
1900
1901 /* set outer most header */
1902 if (cfg->hdr_type == ICE_RSS_INNER_HEADERS_W_OUTER_IPV4)
1903 segs[ICE_RSS_OUTER_HEADERS].hdrs |= ICE_FLOW_SEG_HDR_IPV4 |
1904 ICE_FLOW_SEG_HDR_IPV_OTHER;
1905 else if (cfg->hdr_type == ICE_RSS_INNER_HEADERS_W_OUTER_IPV6)
1906 segs[ICE_RSS_OUTER_HEADERS].hdrs |= ICE_FLOW_SEG_HDR_IPV6 |
1907 ICE_FLOW_SEG_HDR_IPV_OTHER;
1908
1909 if (seg->hdrs & ~ICE_FLOW_RSS_SEG_HDR_VAL_MASKS &
1910 ~ICE_FLOW_RSS_HDRS_INNER_MASK & ~ICE_FLOW_SEG_HDR_IPV_OTHER)
1911 return -EINVAL;
1912
1913 val = (u64)(seg->hdrs & ICE_FLOW_RSS_SEG_HDR_L3_MASKS);
1914 if (val && !is_power_of_2(val))
1915 return -EIO;
1916
1917 val = (u64)(seg->hdrs & ICE_FLOW_RSS_SEG_HDR_L4_MASKS);
1918 if (val && !is_power_of_2(val))
1919 return -EIO;
1920
1921 return 0;
1922}
1923
1924/**
1925 * ice_rem_vsi_rss_list - remove VSI from RSS list
1926 * @hw: pointer to the hardware structure
1927 * @vsi_handle: software VSI handle
1928 *
1929 * Remove the VSI from all RSS configurations in the list.
1930 */
1931void ice_rem_vsi_rss_list(struct ice_hw *hw, u16 vsi_handle)
1932{
1933 struct ice_rss_cfg *r, *tmp;
1934
1935 if (list_empty(&hw->rss_list_head))
1936 return;
1937
1938 mutex_lock(&hw->rss_locks);
1939 list_for_each_entry_safe(r, tmp, &hw->rss_list_head, l_entry)
1940 if (test_and_clear_bit(vsi_handle, r->vsis))
1941 if (bitmap_empty(r->vsis, ICE_MAX_VSI)) {
1942 list_del(&r->l_entry);
1943 devm_kfree(ice_hw_to_dev(hw), r);
1944 }
1945 mutex_unlock(&hw->rss_locks);
1946}
1947
1948/**
1949 * ice_rem_vsi_rss_cfg - remove RSS configurations associated with VSI
1950 * @hw: pointer to the hardware structure
1951 * @vsi_handle: software VSI handle
1952 *
1953 * This function will iterate through all flow profiles and disassociate
1954 * the VSI from that profile. If the flow profile has no VSIs it will
1955 * be removed.
1956 */
1957int ice_rem_vsi_rss_cfg(struct ice_hw *hw, u16 vsi_handle)
1958{
1959 const enum ice_block blk = ICE_BLK_RSS;
1960 struct ice_flow_prof *p, *t;
1961 int status = 0;
1962
1963 if (!ice_is_vsi_valid(hw, vsi_handle))
1964 return -EINVAL;
1965
1966 if (list_empty(&hw->fl_profs[blk]))
1967 return 0;
1968
1969 mutex_lock(&hw->rss_locks);
1970 list_for_each_entry_safe(p, t, &hw->fl_profs[blk], l_entry)
1971 if (test_bit(vsi_handle, p->vsis)) {
1972 status = ice_flow_disassoc_prof(hw, blk, p, vsi_handle);
1973 if (status)
1974 break;
1975
1976 if (bitmap_empty(p->vsis, ICE_MAX_VSI)) {
1977 status = ice_flow_rem_prof(hw, blk, p->id);
1978 if (status)
1979 break;
1980 }
1981 }
1982 mutex_unlock(&hw->rss_locks);
1983
1984 return status;
1985}
1986
1987/**
1988 * ice_get_rss_hdr_type - get a RSS profile's header type
1989 * @prof: RSS flow profile
1990 */
1991static enum ice_rss_cfg_hdr_type
1992ice_get_rss_hdr_type(struct ice_flow_prof *prof)
1993{
1994 if (prof->segs_cnt == ICE_FLOW_SEG_SINGLE) {
1995 return ICE_RSS_OUTER_HEADERS;
1996 } else if (prof->segs_cnt == ICE_FLOW_SEG_MAX) {
1997 const struct ice_flow_seg_info *s;
1998
1999 s = &prof->segs[ICE_RSS_OUTER_HEADERS];
2000 if (s->hdrs == ICE_FLOW_SEG_HDR_NONE)
2001 return ICE_RSS_INNER_HEADERS;
2002 if (s->hdrs & ICE_FLOW_SEG_HDR_IPV4)
2003 return ICE_RSS_INNER_HEADERS_W_OUTER_IPV4;
2004 if (s->hdrs & ICE_FLOW_SEG_HDR_IPV6)
2005 return ICE_RSS_INNER_HEADERS_W_OUTER_IPV6;
2006 }
2007
2008 return ICE_RSS_ANY_HEADERS;
2009}
2010
2011static bool
2012ice_rss_match_prof(struct ice_rss_cfg *r, struct ice_flow_prof *prof,
2013 enum ice_rss_cfg_hdr_type hdr_type)
2014{
2015 return (r->hash.hdr_type == hdr_type &&
2016 r->hash.hash_flds == prof->segs[prof->segs_cnt - 1].match &&
2017 r->hash.addl_hdrs == prof->segs[prof->segs_cnt - 1].hdrs);
2018}
2019
2020/**
2021 * ice_rem_rss_list - remove RSS configuration from list
2022 * @hw: pointer to the hardware structure
2023 * @vsi_handle: software VSI handle
2024 * @prof: pointer to flow profile
2025 *
2026 * Assumption: lock has already been acquired for RSS list
2027 */
2028static void
2029ice_rem_rss_list(struct ice_hw *hw, u16 vsi_handle, struct ice_flow_prof *prof)
2030{
2031 enum ice_rss_cfg_hdr_type hdr_type;
2032 struct ice_rss_cfg *r, *tmp;
2033
2034 /* Search for RSS hash fields associated to the VSI that match the
2035 * hash configurations associated to the flow profile. If found
2036 * remove from the RSS entry list of the VSI context and delete entry.
2037 */
2038 hdr_type = ice_get_rss_hdr_type(prof);
2039 list_for_each_entry_safe(r, tmp, &hw->rss_list_head, l_entry)
2040 if (ice_rss_match_prof(r, prof, hdr_type)) {
2041 clear_bit(vsi_handle, r->vsis);
2042 if (bitmap_empty(r->vsis, ICE_MAX_VSI)) {
2043 list_del(&r->l_entry);
2044 devm_kfree(ice_hw_to_dev(hw), r);
2045 }
2046 return;
2047 }
2048}
2049
2050/**
2051 * ice_add_rss_list - add RSS configuration to list
2052 * @hw: pointer to the hardware structure
2053 * @vsi_handle: software VSI handle
2054 * @prof: pointer to flow profile
2055 *
2056 * Assumption: lock has already been acquired for RSS list
2057 */
2058static int
2059ice_add_rss_list(struct ice_hw *hw, u16 vsi_handle, struct ice_flow_prof *prof)
2060{
2061 enum ice_rss_cfg_hdr_type hdr_type;
2062 struct ice_rss_cfg *r, *rss_cfg;
2063
2064 hdr_type = ice_get_rss_hdr_type(prof);
2065 list_for_each_entry(r, &hw->rss_list_head, l_entry)
2066 if (ice_rss_match_prof(r, prof, hdr_type)) {
2067 set_bit(vsi_handle, r->vsis);
2068 return 0;
2069 }
2070
2071 rss_cfg = devm_kzalloc(ice_hw_to_dev(hw), sizeof(*rss_cfg),
2072 GFP_KERNEL);
2073 if (!rss_cfg)
2074 return -ENOMEM;
2075
2076 rss_cfg->hash.hash_flds = prof->segs[prof->segs_cnt - 1].match;
2077 rss_cfg->hash.addl_hdrs = prof->segs[prof->segs_cnt - 1].hdrs;
2078 rss_cfg->hash.hdr_type = hdr_type;
2079 rss_cfg->hash.symm = prof->symm;
2080 set_bit(vsi_handle, rss_cfg->vsis);
2081
2082 list_add_tail(&rss_cfg->l_entry, &hw->rss_list_head);
2083
2084 return 0;
2085}
2086
2087/**
2088 * ice_rss_config_xor_word - set the HSYMM registers for one input set word
2089 * @hw: pointer to the hardware structure
2090 * @prof_id: RSS hardware profile id
2091 * @src: the FV index used by the protocol's source field
2092 * @dst: the FV index used by the protocol's destination field
2093 *
2094 * Write to the HSYMM register with the index of @src FV the value of the @dst
2095 * FV index. This will tell the hardware to XOR HSYMM[src] with INSET[dst]
2096 * while calculating the RSS input set.
2097 */
2098static void
2099ice_rss_config_xor_word(struct ice_hw *hw, u8 prof_id, u8 src, u8 dst)
2100{
2101 u32 val, reg, bits_shift;
2102 u8 reg_idx;
2103
2104 reg_idx = src / GLQF_HSYMM_REG_SIZE;
2105 bits_shift = ((src % GLQF_HSYMM_REG_SIZE) << 3);
2106 val = dst | GLQF_HSYMM_ENABLE_BIT;
2107
2108 reg = rd32(hw, GLQF_HSYMM(prof_id, reg_idx));
2109 reg = (reg & ~(0xff << bits_shift)) | (val << bits_shift);
2110 wr32(hw, GLQF_HSYMM(prof_id, reg_idx), reg);
2111}
2112
2113/**
2114 * ice_rss_config_xor - set the symmetric registers for a profile's protocol
2115 * @hw: pointer to the hardware structure
2116 * @prof_id: RSS hardware profile id
2117 * @src: the FV index used by the protocol's source field
2118 * @dst: the FV index used by the protocol's destination field
2119 * @len: length of the source/destination fields in words
2120 */
2121static void
2122ice_rss_config_xor(struct ice_hw *hw, u8 prof_id, u8 src, u8 dst, u8 len)
2123{
2124 int fv_last_word =
2125 ICE_FLOW_SW_FIELD_VECTOR_MAX / ICE_FLOW_FV_EXTRACT_SZ - 1;
2126 int i;
2127
2128 for (i = 0; i < len; i++) {
2129 ice_rss_config_xor_word(hw, prof_id,
2130 /* Yes, field vector in GLQF_HSYMM and
2131 * GLQF_HINSET is inversed!
2132 */
2133 fv_last_word - (src + i),
2134 fv_last_word - (dst + i));
2135 ice_rss_config_xor_word(hw, prof_id,
2136 fv_last_word - (dst + i),
2137 fv_last_word - (src + i));
2138 }
2139}
2140
2141/**
2142 * ice_rss_set_symm - set the symmetric settings for an RSS profile
2143 * @hw: pointer to the hardware structure
2144 * @prof: pointer to flow profile
2145 *
2146 * The symmetric hash will result from XORing the protocol's fields with
2147 * indexes in GLQF_HSYMM and GLQF_HINSET. This function configures the profile's
2148 * GLQF_HSYMM registers.
2149 */
2150static void ice_rss_set_symm(struct ice_hw *hw, struct ice_flow_prof *prof)
2151{
2152 struct ice_prof_map *map;
2153 u8 prof_id, m;
2154
2155 mutex_lock(&hw->blk[ICE_BLK_RSS].es.prof_map_lock);
2156 map = ice_search_prof_id(hw, ICE_BLK_RSS, prof->id);
2157 if (map)
2158 prof_id = map->prof_id;
2159 mutex_unlock(&hw->blk[ICE_BLK_RSS].es.prof_map_lock);
2160
2161 if (!map)
2162 return;
2163
2164 /* clear to default */
2165 for (m = 0; m < GLQF_HSYMM_REG_PER_PROF; m++)
2166 wr32(hw, GLQF_HSYMM(prof_id, m), 0);
2167
2168 if (prof->symm) {
2169 struct ice_flow_seg_xtrct *ipv4_src, *ipv4_dst;
2170 struct ice_flow_seg_xtrct *ipv6_src, *ipv6_dst;
2171 struct ice_flow_seg_xtrct *sctp_src, *sctp_dst;
2172 struct ice_flow_seg_xtrct *tcp_src, *tcp_dst;
2173 struct ice_flow_seg_xtrct *udp_src, *udp_dst;
2174 struct ice_flow_seg_info *seg;
2175
2176 seg = &prof->segs[prof->segs_cnt - 1];
2177
2178 ipv4_src = &seg->fields[ICE_FLOW_FIELD_IDX_IPV4_SA].xtrct;
2179 ipv4_dst = &seg->fields[ICE_FLOW_FIELD_IDX_IPV4_DA].xtrct;
2180
2181 ipv6_src = &seg->fields[ICE_FLOW_FIELD_IDX_IPV6_SA].xtrct;
2182 ipv6_dst = &seg->fields[ICE_FLOW_FIELD_IDX_IPV6_DA].xtrct;
2183
2184 tcp_src = &seg->fields[ICE_FLOW_FIELD_IDX_TCP_SRC_PORT].xtrct;
2185 tcp_dst = &seg->fields[ICE_FLOW_FIELD_IDX_TCP_DST_PORT].xtrct;
2186
2187 udp_src = &seg->fields[ICE_FLOW_FIELD_IDX_UDP_SRC_PORT].xtrct;
2188 udp_dst = &seg->fields[ICE_FLOW_FIELD_IDX_UDP_DST_PORT].xtrct;
2189
2190 sctp_src = &seg->fields[ICE_FLOW_FIELD_IDX_SCTP_SRC_PORT].xtrct;
2191 sctp_dst = &seg->fields[ICE_FLOW_FIELD_IDX_SCTP_DST_PORT].xtrct;
2192
2193 /* xor IPv4 */
2194 if (ipv4_src->prot_id != 0 && ipv4_dst->prot_id != 0)
2195 ice_rss_config_xor(hw, prof_id,
2196 ipv4_src->idx, ipv4_dst->idx, 2);
2197
2198 /* xor IPv6 */
2199 if (ipv6_src->prot_id != 0 && ipv6_dst->prot_id != 0)
2200 ice_rss_config_xor(hw, prof_id,
2201 ipv6_src->idx, ipv6_dst->idx, 8);
2202
2203 /* xor TCP */
2204 if (tcp_src->prot_id != 0 && tcp_dst->prot_id != 0)
2205 ice_rss_config_xor(hw, prof_id,
2206 tcp_src->idx, tcp_dst->idx, 1);
2207
2208 /* xor UDP */
2209 if (udp_src->prot_id != 0 && udp_dst->prot_id != 0)
2210 ice_rss_config_xor(hw, prof_id,
2211 udp_src->idx, udp_dst->idx, 1);
2212
2213 /* xor SCTP */
2214 if (sctp_src->prot_id != 0 && sctp_dst->prot_id != 0)
2215 ice_rss_config_xor(hw, prof_id,
2216 sctp_src->idx, sctp_dst->idx, 1);
2217 }
2218}
2219
2220/**
2221 * ice_add_rss_cfg_sync - add an RSS configuration
2222 * @hw: pointer to the hardware structure
2223 * @vsi_handle: software VSI handle
2224 * @cfg: configure parameters
2225 *
2226 * Assumption: lock has already been acquired for RSS list
2227 */
2228static int
2229ice_add_rss_cfg_sync(struct ice_hw *hw, u16 vsi_handle,
2230 const struct ice_rss_hash_cfg *cfg)
2231{
2232 const enum ice_block blk = ICE_BLK_RSS;
2233 struct ice_flow_prof *prof = NULL;
2234 struct ice_flow_seg_info *segs;
2235 u8 segs_cnt;
2236 int status;
2237
2238 segs_cnt = (cfg->hdr_type == ICE_RSS_OUTER_HEADERS) ?
2239 ICE_FLOW_SEG_SINGLE : ICE_FLOW_SEG_MAX;
2240
2241 segs = kcalloc(segs_cnt, sizeof(*segs), GFP_KERNEL);
2242 if (!segs)
2243 return -ENOMEM;
2244
2245 /* Construct the packet segment info from the hashed fields */
2246 status = ice_flow_set_rss_seg_info(segs, segs_cnt, cfg);
2247 if (status)
2248 goto exit;
2249
2250 /* Search for a flow profile that has matching headers, hash fields,
2251 * symm and has the input VSI associated to it. If found, no further
2252 * operations required and exit.
2253 */
2254 prof = ice_flow_find_prof_conds(hw, blk, ICE_FLOW_RX, segs, segs_cnt,
2255 cfg->symm, vsi_handle,
2256 ICE_FLOW_FIND_PROF_CHK_FLDS |
2257 ICE_FLOW_FIND_PROF_CHK_SYMM |
2258 ICE_FLOW_FIND_PROF_CHK_VSI);
2259 if (prof)
2260 goto exit;
2261
2262 /* Check if a flow profile exists with the same protocol headers and
2263 * associated with the input VSI. If so disassociate the VSI from
2264 * this profile. The VSI will be added to a new profile created with
2265 * the protocol header and new hash field configuration.
2266 */
2267 prof = ice_flow_find_prof_conds(hw, blk, ICE_FLOW_RX, segs, segs_cnt,
2268 cfg->symm, vsi_handle,
2269 ICE_FLOW_FIND_PROF_CHK_VSI);
2270 if (prof) {
2271 status = ice_flow_disassoc_prof(hw, blk, prof, vsi_handle);
2272 if (!status)
2273 ice_rem_rss_list(hw, vsi_handle, prof);
2274 else
2275 goto exit;
2276
2277 /* Remove profile if it has no VSIs associated */
2278 if (bitmap_empty(prof->vsis, ICE_MAX_VSI)) {
2279 status = ice_flow_rem_prof(hw, blk, prof->id);
2280 if (status)
2281 goto exit;
2282 }
2283 }
2284
2285 /* Search for a profile that has the same match fields and symmetric
2286 * setting. If this exists then associate the VSI to this profile.
2287 */
2288 prof = ice_flow_find_prof_conds(hw, blk, ICE_FLOW_RX, segs, segs_cnt,
2289 cfg->symm, vsi_handle,
2290 ICE_FLOW_FIND_PROF_CHK_SYMM |
2291 ICE_FLOW_FIND_PROF_CHK_FLDS);
2292 if (prof) {
2293 status = ice_flow_assoc_prof(hw, blk, prof, vsi_handle);
2294 if (!status)
2295 status = ice_add_rss_list(hw, vsi_handle, prof);
2296 goto exit;
2297 }
2298
2299 /* Create a new flow profile with packet segment information. */
2300 status = ice_flow_add_prof(hw, blk, ICE_FLOW_RX,
2301 segs, segs_cnt, cfg->symm, &prof);
2302 if (status)
2303 goto exit;
2304
2305 prof->symm = cfg->symm;
2306 ice_rss_set_symm(hw, prof);
2307 status = ice_flow_assoc_prof(hw, blk, prof, vsi_handle);
2308 /* If association to a new flow profile failed then this profile can
2309 * be removed.
2310 */
2311 if (status) {
2312 ice_flow_rem_prof(hw, blk, prof->id);
2313 goto exit;
2314 }
2315
2316 status = ice_add_rss_list(hw, vsi_handle, prof);
2317
2318exit:
2319 kfree(segs);
2320 return status;
2321}
2322
2323/**
2324 * ice_add_rss_cfg - add an RSS configuration with specified hashed fields
2325 * @hw: pointer to the hardware structure
2326 * @vsi: VSI to add the RSS configuration to
2327 * @cfg: configure parameters
2328 *
2329 * This function will generate a flow profile based on fields associated with
2330 * the input fields to hash on, the flow type and use the VSI number to add
2331 * a flow entry to the profile.
2332 */
2333int
2334ice_add_rss_cfg(struct ice_hw *hw, struct ice_vsi *vsi,
2335 const struct ice_rss_hash_cfg *cfg)
2336{
2337 struct ice_rss_hash_cfg local_cfg;
2338 u16 vsi_handle;
2339 int status;
2340
2341 if (!vsi)
2342 return -EINVAL;
2343
2344 vsi_handle = vsi->idx;
2345 if (!ice_is_vsi_valid(hw, vsi_handle) ||
2346 !cfg || cfg->hdr_type > ICE_RSS_ANY_HEADERS ||
2347 cfg->hash_flds == ICE_HASH_INVALID)
2348 return -EINVAL;
2349
2350 mutex_lock(&hw->rss_locks);
2351 local_cfg = *cfg;
2352 if (cfg->hdr_type < ICE_RSS_ANY_HEADERS) {
2353 status = ice_add_rss_cfg_sync(hw, vsi_handle, &local_cfg);
2354 } else {
2355 local_cfg.hdr_type = ICE_RSS_OUTER_HEADERS;
2356 status = ice_add_rss_cfg_sync(hw, vsi_handle, &local_cfg);
2357 if (!status) {
2358 local_cfg.hdr_type = ICE_RSS_INNER_HEADERS;
2359 status = ice_add_rss_cfg_sync(hw, vsi_handle,
2360 &local_cfg);
2361 }
2362 }
2363 mutex_unlock(&hw->rss_locks);
2364
2365 return status;
2366}
2367
2368/**
2369 * ice_rem_rss_cfg_sync - remove an existing RSS configuration
2370 * @hw: pointer to the hardware structure
2371 * @vsi_handle: software VSI handle
2372 * @cfg: configure parameters
2373 *
2374 * Assumption: lock has already been acquired for RSS list
2375 */
2376static int
2377ice_rem_rss_cfg_sync(struct ice_hw *hw, u16 vsi_handle,
2378 const struct ice_rss_hash_cfg *cfg)
2379{
2380 const enum ice_block blk = ICE_BLK_RSS;
2381 struct ice_flow_seg_info *segs;
2382 struct ice_flow_prof *prof;
2383 u8 segs_cnt;
2384 int status;
2385
2386 segs_cnt = (cfg->hdr_type == ICE_RSS_OUTER_HEADERS) ?
2387 ICE_FLOW_SEG_SINGLE : ICE_FLOW_SEG_MAX;
2388 segs = kcalloc(segs_cnt, sizeof(*segs), GFP_KERNEL);
2389 if (!segs)
2390 return -ENOMEM;
2391
2392 /* Construct the packet segment info from the hashed fields */
2393 status = ice_flow_set_rss_seg_info(segs, segs_cnt, cfg);
2394 if (status)
2395 goto out;
2396
2397 prof = ice_flow_find_prof_conds(hw, blk, ICE_FLOW_RX, segs, segs_cnt,
2398 cfg->symm, vsi_handle,
2399 ICE_FLOW_FIND_PROF_CHK_FLDS);
2400 if (!prof) {
2401 status = -ENOENT;
2402 goto out;
2403 }
2404
2405 status = ice_flow_disassoc_prof(hw, blk, prof, vsi_handle);
2406 if (status)
2407 goto out;
2408
2409 /* Remove RSS configuration from VSI context before deleting
2410 * the flow profile.
2411 */
2412 ice_rem_rss_list(hw, vsi_handle, prof);
2413
2414 if (bitmap_empty(prof->vsis, ICE_MAX_VSI))
2415 status = ice_flow_rem_prof(hw, blk, prof->id);
2416
2417out:
2418 kfree(segs);
2419 return status;
2420}
2421
2422/**
2423 * ice_rem_rss_cfg - remove an existing RSS config with matching hashed fields
2424 * @hw: pointer to the hardware structure
2425 * @vsi_handle: software VSI handle
2426 * @cfg: configure parameters
2427 *
2428 * This function will lookup the flow profile based on the input
2429 * hash field bitmap, iterate through the profile entry list of
2430 * that profile and find entry associated with input VSI to be
2431 * removed. Calls are made to underlying flow apis which will in
2432 * turn build or update buffers for RSS XLT1 section.
2433 */
2434int
2435ice_rem_rss_cfg(struct ice_hw *hw, u16 vsi_handle,
2436 const struct ice_rss_hash_cfg *cfg)
2437{
2438 struct ice_rss_hash_cfg local_cfg;
2439 int status;
2440
2441 if (!ice_is_vsi_valid(hw, vsi_handle) ||
2442 !cfg || cfg->hdr_type > ICE_RSS_ANY_HEADERS ||
2443 cfg->hash_flds == ICE_HASH_INVALID)
2444 return -EINVAL;
2445
2446 mutex_lock(&hw->rss_locks);
2447 local_cfg = *cfg;
2448 if (cfg->hdr_type < ICE_RSS_ANY_HEADERS) {
2449 status = ice_rem_rss_cfg_sync(hw, vsi_handle, &local_cfg);
2450 } else {
2451 local_cfg.hdr_type = ICE_RSS_OUTER_HEADERS;
2452 status = ice_rem_rss_cfg_sync(hw, vsi_handle, &local_cfg);
2453 if (!status) {
2454 local_cfg.hdr_type = ICE_RSS_INNER_HEADERS;
2455 status = ice_rem_rss_cfg_sync(hw, vsi_handle,
2456 &local_cfg);
2457 }
2458 }
2459 mutex_unlock(&hw->rss_locks);
2460
2461 return status;
2462}
2463
2464/* Mapping of AVF hash bit fields to an L3-L4 hash combination.
2465 * As the ice_flow_avf_hdr_field represent individual bit shifts in a hash,
2466 * convert its values to their appropriate flow L3, L4 values.
2467 */
2468#define ICE_FLOW_AVF_RSS_IPV4_MASKS \
2469 (BIT_ULL(ICE_AVF_FLOW_FIELD_IPV4_OTHER) | \
2470 BIT_ULL(ICE_AVF_FLOW_FIELD_FRAG_IPV4))
2471#define ICE_FLOW_AVF_RSS_TCP_IPV4_MASKS \
2472 (BIT_ULL(ICE_AVF_FLOW_FIELD_IPV4_TCP_SYN_NO_ACK) | \
2473 BIT_ULL(ICE_AVF_FLOW_FIELD_IPV4_TCP))
2474#define ICE_FLOW_AVF_RSS_UDP_IPV4_MASKS \
2475 (BIT_ULL(ICE_AVF_FLOW_FIELD_UNICAST_IPV4_UDP) | \
2476 BIT_ULL(ICE_AVF_FLOW_FIELD_MULTICAST_IPV4_UDP) | \
2477 BIT_ULL(ICE_AVF_FLOW_FIELD_IPV4_UDP))
2478#define ICE_FLOW_AVF_RSS_ALL_IPV4_MASKS \
2479 (ICE_FLOW_AVF_RSS_TCP_IPV4_MASKS | ICE_FLOW_AVF_RSS_UDP_IPV4_MASKS | \
2480 ICE_FLOW_AVF_RSS_IPV4_MASKS | BIT_ULL(ICE_AVF_FLOW_FIELD_IPV4_SCTP))
2481
2482#define ICE_FLOW_AVF_RSS_IPV6_MASKS \
2483 (BIT_ULL(ICE_AVF_FLOW_FIELD_IPV6_OTHER) | \
2484 BIT_ULL(ICE_AVF_FLOW_FIELD_FRAG_IPV6))
2485#define ICE_FLOW_AVF_RSS_UDP_IPV6_MASKS \
2486 (BIT_ULL(ICE_AVF_FLOW_FIELD_UNICAST_IPV6_UDP) | \
2487 BIT_ULL(ICE_AVF_FLOW_FIELD_MULTICAST_IPV6_UDP) | \
2488 BIT_ULL(ICE_AVF_FLOW_FIELD_IPV6_UDP))
2489#define ICE_FLOW_AVF_RSS_TCP_IPV6_MASKS \
2490 (BIT_ULL(ICE_AVF_FLOW_FIELD_IPV6_TCP_SYN_NO_ACK) | \
2491 BIT_ULL(ICE_AVF_FLOW_FIELD_IPV6_TCP))
2492#define ICE_FLOW_AVF_RSS_ALL_IPV6_MASKS \
2493 (ICE_FLOW_AVF_RSS_TCP_IPV6_MASKS | ICE_FLOW_AVF_RSS_UDP_IPV6_MASKS | \
2494 ICE_FLOW_AVF_RSS_IPV6_MASKS | BIT_ULL(ICE_AVF_FLOW_FIELD_IPV6_SCTP))
2495
2496/**
2497 * ice_add_avf_rss_cfg - add an RSS configuration for AVF driver
2498 * @hw: pointer to the hardware structure
2499 * @vsi: VF's VSI
2500 * @avf_hash: hash bit fields (ICE_AVF_FLOW_FIELD_*) to configure
2501 *
2502 * This function will take the hash bitmap provided by the AVF driver via a
2503 * message, convert it to ICE-compatible values, and configure RSS flow
2504 * profiles.
2505 */
2506int ice_add_avf_rss_cfg(struct ice_hw *hw, struct ice_vsi *vsi, u64 avf_hash)
2507{
2508 struct ice_rss_hash_cfg hcfg;
2509 u16 vsi_handle;
2510 int status = 0;
2511 u64 hash_flds;
2512
2513 if (!vsi)
2514 return -EINVAL;
2515
2516 vsi_handle = vsi->idx;
2517 if (avf_hash == ICE_AVF_FLOW_FIELD_INVALID ||
2518 !ice_is_vsi_valid(hw, vsi_handle))
2519 return -EINVAL;
2520
2521 /* Make sure no unsupported bits are specified */
2522 if (avf_hash & ~(ICE_FLOW_AVF_RSS_ALL_IPV4_MASKS |
2523 ICE_FLOW_AVF_RSS_ALL_IPV6_MASKS))
2524 return -EIO;
2525
2526 hash_flds = avf_hash;
2527
2528 /* Always create an L3 RSS configuration for any L4 RSS configuration */
2529 if (hash_flds & ICE_FLOW_AVF_RSS_ALL_IPV4_MASKS)
2530 hash_flds |= ICE_FLOW_AVF_RSS_IPV4_MASKS;
2531
2532 if (hash_flds & ICE_FLOW_AVF_RSS_ALL_IPV6_MASKS)
2533 hash_flds |= ICE_FLOW_AVF_RSS_IPV6_MASKS;
2534
2535 /* Create the corresponding RSS configuration for each valid hash bit */
2536 while (hash_flds) {
2537 u64 rss_hash = ICE_HASH_INVALID;
2538
2539 if (hash_flds & ICE_FLOW_AVF_RSS_ALL_IPV4_MASKS) {
2540 if (hash_flds & ICE_FLOW_AVF_RSS_IPV4_MASKS) {
2541 rss_hash = ICE_FLOW_HASH_IPV4;
2542 hash_flds &= ~ICE_FLOW_AVF_RSS_IPV4_MASKS;
2543 } else if (hash_flds &
2544 ICE_FLOW_AVF_RSS_TCP_IPV4_MASKS) {
2545 rss_hash = ICE_FLOW_HASH_IPV4 |
2546 ICE_FLOW_HASH_TCP_PORT;
2547 hash_flds &= ~ICE_FLOW_AVF_RSS_TCP_IPV4_MASKS;
2548 } else if (hash_flds &
2549 ICE_FLOW_AVF_RSS_UDP_IPV4_MASKS) {
2550 rss_hash = ICE_FLOW_HASH_IPV4 |
2551 ICE_FLOW_HASH_UDP_PORT;
2552 hash_flds &= ~ICE_FLOW_AVF_RSS_UDP_IPV4_MASKS;
2553 } else if (hash_flds &
2554 BIT_ULL(ICE_AVF_FLOW_FIELD_IPV4_SCTP)) {
2555 rss_hash = ICE_FLOW_HASH_IPV4 |
2556 ICE_FLOW_HASH_SCTP_PORT;
2557 hash_flds &=
2558 ~BIT_ULL(ICE_AVF_FLOW_FIELD_IPV4_SCTP);
2559 }
2560 } else if (hash_flds & ICE_FLOW_AVF_RSS_ALL_IPV6_MASKS) {
2561 if (hash_flds & ICE_FLOW_AVF_RSS_IPV6_MASKS) {
2562 rss_hash = ICE_FLOW_HASH_IPV6;
2563 hash_flds &= ~ICE_FLOW_AVF_RSS_IPV6_MASKS;
2564 } else if (hash_flds &
2565 ICE_FLOW_AVF_RSS_TCP_IPV6_MASKS) {
2566 rss_hash = ICE_FLOW_HASH_IPV6 |
2567 ICE_FLOW_HASH_TCP_PORT;
2568 hash_flds &= ~ICE_FLOW_AVF_RSS_TCP_IPV6_MASKS;
2569 } else if (hash_flds &
2570 ICE_FLOW_AVF_RSS_UDP_IPV6_MASKS) {
2571 rss_hash = ICE_FLOW_HASH_IPV6 |
2572 ICE_FLOW_HASH_UDP_PORT;
2573 hash_flds &= ~ICE_FLOW_AVF_RSS_UDP_IPV6_MASKS;
2574 } else if (hash_flds &
2575 BIT_ULL(ICE_AVF_FLOW_FIELD_IPV6_SCTP)) {
2576 rss_hash = ICE_FLOW_HASH_IPV6 |
2577 ICE_FLOW_HASH_SCTP_PORT;
2578 hash_flds &=
2579 ~BIT_ULL(ICE_AVF_FLOW_FIELD_IPV6_SCTP);
2580 }
2581 }
2582
2583 if (rss_hash == ICE_HASH_INVALID)
2584 return -EIO;
2585
2586 hcfg.addl_hdrs = ICE_FLOW_SEG_HDR_NONE;
2587 hcfg.hash_flds = rss_hash;
2588 hcfg.hdr_type = ICE_RSS_ANY_HEADERS;
2589 hcfg.symm = false;
2590 status = ice_add_rss_cfg(hw, vsi, &hcfg);
2591 if (status)
2592 break;
2593 }
2594
2595 return status;
2596}
2597
2598static bool rss_cfg_symm_valid(u64 hfld)
2599{
2600 return !((!!(hfld & ICE_FLOW_HASH_FLD_IPV4_SA) ^
2601 !!(hfld & ICE_FLOW_HASH_FLD_IPV4_DA)) ||
2602 (!!(hfld & ICE_FLOW_HASH_FLD_IPV6_SA) ^
2603 !!(hfld & ICE_FLOW_HASH_FLD_IPV6_DA)) ||
2604 (!!(hfld & ICE_FLOW_HASH_FLD_TCP_SRC_PORT) ^
2605 !!(hfld & ICE_FLOW_HASH_FLD_TCP_DST_PORT)) ||
2606 (!!(hfld & ICE_FLOW_HASH_FLD_UDP_SRC_PORT) ^
2607 !!(hfld & ICE_FLOW_HASH_FLD_UDP_DST_PORT)) ||
2608 (!!(hfld & ICE_FLOW_HASH_FLD_SCTP_SRC_PORT) ^
2609 !!(hfld & ICE_FLOW_HASH_FLD_SCTP_DST_PORT)));
2610}
2611
2612/**
2613 * ice_set_rss_cfg_symm - set symmtery for all VSI's RSS configurations
2614 * @hw: pointer to the hardware structure
2615 * @vsi: VSI to set/unset Symmetric RSS
2616 * @symm: TRUE to set Symmetric RSS hashing
2617 */
2618int ice_set_rss_cfg_symm(struct ice_hw *hw, struct ice_vsi *vsi, bool symm)
2619{
2620 struct ice_rss_hash_cfg local;
2621 struct ice_rss_cfg *r, *tmp;
2622 u16 vsi_handle = vsi->idx;
2623 int status = 0;
2624
2625 if (!ice_is_vsi_valid(hw, vsi_handle))
2626 return -EINVAL;
2627
2628 mutex_lock(&hw->rss_locks);
2629 list_for_each_entry_safe(r, tmp, &hw->rss_list_head, l_entry) {
2630 if (test_bit(vsi_handle, r->vsis) && r->hash.symm != symm) {
2631 local = r->hash;
2632 local.symm = symm;
2633 if (symm && !rss_cfg_symm_valid(r->hash.hash_flds))
2634 continue;
2635
2636 status = ice_add_rss_cfg_sync(hw, vsi_handle, &local);
2637 if (status)
2638 break;
2639 }
2640 }
2641 mutex_unlock(&hw->rss_locks);
2642
2643 return status;
2644}
2645
2646/**
2647 * ice_replay_rss_cfg - replay RSS configurations associated with VSI
2648 * @hw: pointer to the hardware structure
2649 * @vsi_handle: software VSI handle
2650 */
2651int ice_replay_rss_cfg(struct ice_hw *hw, u16 vsi_handle)
2652{
2653 struct ice_rss_cfg *r;
2654 int status = 0;
2655
2656 if (!ice_is_vsi_valid(hw, vsi_handle))
2657 return -EINVAL;
2658
2659 mutex_lock(&hw->rss_locks);
2660 list_for_each_entry(r, &hw->rss_list_head, l_entry) {
2661 if (test_bit(vsi_handle, r->vsis)) {
2662 status = ice_add_rss_cfg_sync(hw, vsi_handle, &r->hash);
2663 if (status)
2664 break;
2665 }
2666 }
2667 mutex_unlock(&hw->rss_locks);
2668
2669 return status;
2670}
2671
2672/**
2673 * ice_get_rss_cfg - returns hashed fields for the given header types
2674 * @hw: pointer to the hardware structure
2675 * @vsi_handle: software VSI handle
2676 * @hdrs: protocol header type
2677 * @symm: whether the RSS is symmetric (bool, output)
2678 *
2679 * This function will return the match fields of the first instance of flow
2680 * profile having the given header types and containing input VSI
2681 */
2682u64 ice_get_rss_cfg(struct ice_hw *hw, u16 vsi_handle, u32 hdrs, bool *symm)
2683{
2684 u64 rss_hash = ICE_HASH_INVALID;
2685 struct ice_rss_cfg *r;
2686
2687 /* verify if the protocol header is non zero and VSI is valid */
2688 if (hdrs == ICE_FLOW_SEG_HDR_NONE || !ice_is_vsi_valid(hw, vsi_handle))
2689 return ICE_HASH_INVALID;
2690
2691 mutex_lock(&hw->rss_locks);
2692 list_for_each_entry(r, &hw->rss_list_head, l_entry)
2693 if (test_bit(vsi_handle, r->vsis) &&
2694 r->hash.addl_hdrs == hdrs) {
2695 rss_hash = r->hash.hash_flds;
2696 *symm = r->hash.symm;
2697 break;
2698 }
2699 mutex_unlock(&hw->rss_locks);
2700
2701 return rss_hash;
2702}
1// SPDX-License-Identifier: GPL-2.0
2/* Copyright (c) 2019, Intel Corporation. */
3
4#include "ice_common.h"
5#include "ice_flow.h"
6
7/* Describe properties of a protocol header field */
8struct ice_flow_field_info {
9 enum ice_flow_seg_hdr hdr;
10 s16 off; /* Offset from start of a protocol header, in bits */
11 u16 size; /* Size of fields in bits */
12};
13
14#define ICE_FLOW_FLD_INFO(_hdr, _offset_bytes, _size_bytes) { \
15 .hdr = _hdr, \
16 .off = (_offset_bytes) * BITS_PER_BYTE, \
17 .size = (_size_bytes) * BITS_PER_BYTE, \
18}
19
20/* Table containing properties of supported protocol header fields */
21static const
22struct ice_flow_field_info ice_flds_info[ICE_FLOW_FIELD_IDX_MAX] = {
23 /* IPv4 / IPv6 */
24 /* ICE_FLOW_FIELD_IDX_IPV4_SA */
25 ICE_FLOW_FLD_INFO(ICE_FLOW_SEG_HDR_IPV4, 12, sizeof(struct in_addr)),
26 /* ICE_FLOW_FIELD_IDX_IPV4_DA */
27 ICE_FLOW_FLD_INFO(ICE_FLOW_SEG_HDR_IPV4, 16, sizeof(struct in_addr)),
28 /* ICE_FLOW_FIELD_IDX_IPV6_SA */
29 ICE_FLOW_FLD_INFO(ICE_FLOW_SEG_HDR_IPV6, 8, sizeof(struct in6_addr)),
30 /* ICE_FLOW_FIELD_IDX_IPV6_DA */
31 ICE_FLOW_FLD_INFO(ICE_FLOW_SEG_HDR_IPV6, 24, sizeof(struct in6_addr)),
32 /* Transport */
33 /* ICE_FLOW_FIELD_IDX_TCP_SRC_PORT */
34 ICE_FLOW_FLD_INFO(ICE_FLOW_SEG_HDR_TCP, 0, sizeof(__be16)),
35 /* ICE_FLOW_FIELD_IDX_TCP_DST_PORT */
36 ICE_FLOW_FLD_INFO(ICE_FLOW_SEG_HDR_TCP, 2, sizeof(__be16)),
37 /* ICE_FLOW_FIELD_IDX_UDP_SRC_PORT */
38 ICE_FLOW_FLD_INFO(ICE_FLOW_SEG_HDR_UDP, 0, sizeof(__be16)),
39 /* ICE_FLOW_FIELD_IDX_UDP_DST_PORT */
40 ICE_FLOW_FLD_INFO(ICE_FLOW_SEG_HDR_UDP, 2, sizeof(__be16)),
41 /* ICE_FLOW_FIELD_IDX_SCTP_SRC_PORT */
42 ICE_FLOW_FLD_INFO(ICE_FLOW_SEG_HDR_SCTP, 0, sizeof(__be16)),
43 /* ICE_FLOW_FIELD_IDX_SCTP_DST_PORT */
44 ICE_FLOW_FLD_INFO(ICE_FLOW_SEG_HDR_SCTP, 2, sizeof(__be16)),
45 /* GRE */
46 /* ICE_FLOW_FIELD_IDX_GRE_KEYID */
47 ICE_FLOW_FLD_INFO(ICE_FLOW_SEG_HDR_GRE, 12,
48 sizeof_field(struct gre_full_hdr, key)),
49};
50
51/* Bitmaps indicating relevant packet types for a particular protocol header
52 *
53 * Packet types for packets with an Outer/First/Single IPv4 header
54 */
55static const u32 ice_ptypes_ipv4_ofos[] = {
56 0x1DC00000, 0x04000800, 0x00000000, 0x00000000,
57 0x00000000, 0x00000000, 0x00000000, 0x00000000,
58 0x00000000, 0x00000000, 0x00000000, 0x00000000,
59 0x00000000, 0x00000000, 0x00000000, 0x00000000,
60 0x00000000, 0x00000000, 0x00000000, 0x00000000,
61 0x00000000, 0x00000000, 0x00000000, 0x00000000,
62 0x00000000, 0x00000000, 0x00000000, 0x00000000,
63 0x00000000, 0x00000000, 0x00000000, 0x00000000,
64};
65
66/* Packet types for packets with an Innermost/Last IPv4 header */
67static const u32 ice_ptypes_ipv4_il[] = {
68 0xE0000000, 0xB807700E, 0x80000003, 0xE01DC03B,
69 0x0000000E, 0x00000000, 0x00000000, 0x00000000,
70 0x00000000, 0x00000000, 0x00000000, 0x00000000,
71 0x00000000, 0x00000000, 0x00000000, 0x00000000,
72 0x00000000, 0x00000000, 0x00000000, 0x00000000,
73 0x00000000, 0x00000000, 0x00000000, 0x00000000,
74 0x00000000, 0x00000000, 0x00000000, 0x00000000,
75 0x00000000, 0x00000000, 0x00000000, 0x00000000,
76};
77
78/* Packet types for packets with an Outer/First/Single IPv6 header */
79static const u32 ice_ptypes_ipv6_ofos[] = {
80 0x00000000, 0x00000000, 0x77000000, 0x10002000,
81 0x00000000, 0x00000000, 0x00000000, 0x00000000,
82 0x00000000, 0x00000000, 0x00000000, 0x00000000,
83 0x00000000, 0x00000000, 0x00000000, 0x00000000,
84 0x00000000, 0x00000000, 0x00000000, 0x00000000,
85 0x00000000, 0x00000000, 0x00000000, 0x00000000,
86 0x00000000, 0x00000000, 0x00000000, 0x00000000,
87 0x00000000, 0x00000000, 0x00000000, 0x00000000,
88};
89
90/* Packet types for packets with an Innermost/Last IPv6 header */
91static const u32 ice_ptypes_ipv6_il[] = {
92 0x00000000, 0x03B80770, 0x000001DC, 0x0EE00000,
93 0x00000770, 0x00000000, 0x00000000, 0x00000000,
94 0x00000000, 0x00000000, 0x00000000, 0x00000000,
95 0x00000000, 0x00000000, 0x00000000, 0x00000000,
96 0x00000000, 0x00000000, 0x00000000, 0x00000000,
97 0x00000000, 0x00000000, 0x00000000, 0x00000000,
98 0x00000000, 0x00000000, 0x00000000, 0x00000000,
99 0x00000000, 0x00000000, 0x00000000, 0x00000000,
100};
101
102/* UDP Packet types for non-tunneled packets or tunneled
103 * packets with inner UDP.
104 */
105static const u32 ice_ptypes_udp_il[] = {
106 0x81000000, 0x20204040, 0x04000010, 0x80810102,
107 0x00000040, 0x00000000, 0x00000000, 0x00000000,
108 0x00000000, 0x00000000, 0x00000000, 0x00000000,
109 0x00000000, 0x00000000, 0x00000000, 0x00000000,
110 0x00000000, 0x00000000, 0x00000000, 0x00000000,
111 0x00000000, 0x00000000, 0x00000000, 0x00000000,
112 0x00000000, 0x00000000, 0x00000000, 0x00000000,
113 0x00000000, 0x00000000, 0x00000000, 0x00000000,
114};
115
116/* Packet types for packets with an Innermost/Last TCP header */
117static const u32 ice_ptypes_tcp_il[] = {
118 0x04000000, 0x80810102, 0x10000040, 0x02040408,
119 0x00000102, 0x00000000, 0x00000000, 0x00000000,
120 0x00000000, 0x00000000, 0x00000000, 0x00000000,
121 0x00000000, 0x00000000, 0x00000000, 0x00000000,
122 0x00000000, 0x00000000, 0x00000000, 0x00000000,
123 0x00000000, 0x00000000, 0x00000000, 0x00000000,
124 0x00000000, 0x00000000, 0x00000000, 0x00000000,
125 0x00000000, 0x00000000, 0x00000000, 0x00000000,
126};
127
128/* Packet types for packets with an Innermost/Last SCTP header */
129static const u32 ice_ptypes_sctp_il[] = {
130 0x08000000, 0x01020204, 0x20000081, 0x04080810,
131 0x00000204, 0x00000000, 0x00000000, 0x00000000,
132 0x00000000, 0x00000000, 0x00000000, 0x00000000,
133 0x00000000, 0x00000000, 0x00000000, 0x00000000,
134 0x00000000, 0x00000000, 0x00000000, 0x00000000,
135 0x00000000, 0x00000000, 0x00000000, 0x00000000,
136 0x00000000, 0x00000000, 0x00000000, 0x00000000,
137 0x00000000, 0x00000000, 0x00000000, 0x00000000,
138};
139
140/* Packet types for packets with an Outermost/First GRE header */
141static const u32 ice_ptypes_gre_of[] = {
142 0x00000000, 0xBFBF7800, 0x000001DF, 0xFEFDE000,
143 0x0000017E, 0x00000000, 0x00000000, 0x00000000,
144 0x00000000, 0x00000000, 0x00000000, 0x00000000,
145 0x00000000, 0x00000000, 0x00000000, 0x00000000,
146 0x00000000, 0x00000000, 0x00000000, 0x00000000,
147 0x00000000, 0x00000000, 0x00000000, 0x00000000,
148 0x00000000, 0x00000000, 0x00000000, 0x00000000,
149 0x00000000, 0x00000000, 0x00000000, 0x00000000,
150};
151
152/* Manage parameters and info. used during the creation of a flow profile */
153struct ice_flow_prof_params {
154 enum ice_block blk;
155 u16 entry_length; /* # of bytes formatted entry will require */
156 u8 es_cnt;
157 struct ice_flow_prof *prof;
158
159 /* For ACL, the es[0] will have the data of ICE_RX_MDID_PKT_FLAGS_15_0
160 * This will give us the direction flags.
161 */
162 struct ice_fv_word es[ICE_MAX_FV_WORDS];
163 DECLARE_BITMAP(ptypes, ICE_FLOW_PTYPE_MAX);
164};
165
166#define ICE_FLOW_SEG_HDRS_L3_MASK \
167 (ICE_FLOW_SEG_HDR_IPV4 | ICE_FLOW_SEG_HDR_IPV6)
168#define ICE_FLOW_SEG_HDRS_L4_MASK \
169 (ICE_FLOW_SEG_HDR_TCP | ICE_FLOW_SEG_HDR_UDP | ICE_FLOW_SEG_HDR_SCTP)
170
171/**
172 * ice_flow_val_hdrs - validates packet segments for valid protocol headers
173 * @segs: array of one or more packet segments that describe the flow
174 * @segs_cnt: number of packet segments provided
175 */
176static enum ice_status
177ice_flow_val_hdrs(struct ice_flow_seg_info *segs, u8 segs_cnt)
178{
179 u8 i;
180
181 for (i = 0; i < segs_cnt; i++) {
182 /* Multiple L3 headers */
183 if (segs[i].hdrs & ICE_FLOW_SEG_HDRS_L3_MASK &&
184 !is_power_of_2(segs[i].hdrs & ICE_FLOW_SEG_HDRS_L3_MASK))
185 return ICE_ERR_PARAM;
186
187 /* Multiple L4 headers */
188 if (segs[i].hdrs & ICE_FLOW_SEG_HDRS_L4_MASK &&
189 !is_power_of_2(segs[i].hdrs & ICE_FLOW_SEG_HDRS_L4_MASK))
190 return ICE_ERR_PARAM;
191 }
192
193 return 0;
194}
195
196/* Sizes of fixed known protocol headers without header options */
197#define ICE_FLOW_PROT_HDR_SZ_MAC 14
198#define ICE_FLOW_PROT_HDR_SZ_IPV4 20
199#define ICE_FLOW_PROT_HDR_SZ_IPV6 40
200#define ICE_FLOW_PROT_HDR_SZ_TCP 20
201#define ICE_FLOW_PROT_HDR_SZ_UDP 8
202#define ICE_FLOW_PROT_HDR_SZ_SCTP 12
203
204/**
205 * ice_flow_calc_seg_sz - calculates size of a packet segment based on headers
206 * @params: information about the flow to be processed
207 * @seg: index of packet segment whose header size is to be determined
208 */
209static u16 ice_flow_calc_seg_sz(struct ice_flow_prof_params *params, u8 seg)
210{
211 u16 sz = ICE_FLOW_PROT_HDR_SZ_MAC;
212
213 /* L3 headers */
214 if (params->prof->segs[seg].hdrs & ICE_FLOW_SEG_HDR_IPV4)
215 sz += ICE_FLOW_PROT_HDR_SZ_IPV4;
216 else if (params->prof->segs[seg].hdrs & ICE_FLOW_SEG_HDR_IPV6)
217 sz += ICE_FLOW_PROT_HDR_SZ_IPV6;
218
219 /* L4 headers */
220 if (params->prof->segs[seg].hdrs & ICE_FLOW_SEG_HDR_TCP)
221 sz += ICE_FLOW_PROT_HDR_SZ_TCP;
222 else if (params->prof->segs[seg].hdrs & ICE_FLOW_SEG_HDR_UDP)
223 sz += ICE_FLOW_PROT_HDR_SZ_UDP;
224 else if (params->prof->segs[seg].hdrs & ICE_FLOW_SEG_HDR_SCTP)
225 sz += ICE_FLOW_PROT_HDR_SZ_SCTP;
226
227 return sz;
228}
229
230/**
231 * ice_flow_proc_seg_hdrs - process protocol headers present in pkt segments
232 * @params: information about the flow to be processed
233 *
234 * This function identifies the packet types associated with the protocol
235 * headers being present in packet segments of the specified flow profile.
236 */
237static enum ice_status
238ice_flow_proc_seg_hdrs(struct ice_flow_prof_params *params)
239{
240 struct ice_flow_prof *prof;
241 u8 i;
242
243 memset(params->ptypes, 0xff, sizeof(params->ptypes));
244
245 prof = params->prof;
246
247 for (i = 0; i < params->prof->segs_cnt; i++) {
248 const unsigned long *src;
249 u32 hdrs;
250
251 hdrs = prof->segs[i].hdrs;
252
253 if (hdrs & ICE_FLOW_SEG_HDR_IPV4) {
254 src = !i ? (const unsigned long *)ice_ptypes_ipv4_ofos :
255 (const unsigned long *)ice_ptypes_ipv4_il;
256 bitmap_and(params->ptypes, params->ptypes, src,
257 ICE_FLOW_PTYPE_MAX);
258 } else if (hdrs & ICE_FLOW_SEG_HDR_IPV6) {
259 src = !i ? (const unsigned long *)ice_ptypes_ipv6_ofos :
260 (const unsigned long *)ice_ptypes_ipv6_il;
261 bitmap_and(params->ptypes, params->ptypes, src,
262 ICE_FLOW_PTYPE_MAX);
263 }
264
265 if (hdrs & ICE_FLOW_SEG_HDR_UDP) {
266 src = (const unsigned long *)ice_ptypes_udp_il;
267 bitmap_and(params->ptypes, params->ptypes, src,
268 ICE_FLOW_PTYPE_MAX);
269 } else if (hdrs & ICE_FLOW_SEG_HDR_TCP) {
270 bitmap_and(params->ptypes, params->ptypes,
271 (const unsigned long *)ice_ptypes_tcp_il,
272 ICE_FLOW_PTYPE_MAX);
273 } else if (hdrs & ICE_FLOW_SEG_HDR_SCTP) {
274 src = (const unsigned long *)ice_ptypes_sctp_il;
275 bitmap_and(params->ptypes, params->ptypes, src,
276 ICE_FLOW_PTYPE_MAX);
277 } else if (hdrs & ICE_FLOW_SEG_HDR_GRE) {
278 if (!i) {
279 src = (const unsigned long *)ice_ptypes_gre_of;
280 bitmap_and(params->ptypes, params->ptypes,
281 src, ICE_FLOW_PTYPE_MAX);
282 }
283 }
284 }
285
286 return 0;
287}
288
289/**
290 * ice_flow_xtract_fld - Create an extraction sequence entry for the given field
291 * @hw: pointer to the HW struct
292 * @params: information about the flow to be processed
293 * @seg: packet segment index of the field to be extracted
294 * @fld: ID of field to be extracted
295 *
296 * This function determines the protocol ID, offset, and size of the given
297 * field. It then allocates one or more extraction sequence entries for the
298 * given field, and fill the entries with protocol ID and offset information.
299 */
300static enum ice_status
301ice_flow_xtract_fld(struct ice_hw *hw, struct ice_flow_prof_params *params,
302 u8 seg, enum ice_flow_field fld)
303{
304 enum ice_prot_id prot_id = ICE_PROT_ID_INVAL;
305 u8 fv_words = hw->blk[params->blk].es.fvw;
306 struct ice_flow_fld_info *flds;
307 u16 cnt, ese_bits, i;
308 u16 off;
309
310 flds = params->prof->segs[seg].fields;
311
312 switch (fld) {
313 case ICE_FLOW_FIELD_IDX_IPV4_SA:
314 case ICE_FLOW_FIELD_IDX_IPV4_DA:
315 prot_id = seg == 0 ? ICE_PROT_IPV4_OF_OR_S : ICE_PROT_IPV4_IL;
316 break;
317 case ICE_FLOW_FIELD_IDX_IPV6_SA:
318 case ICE_FLOW_FIELD_IDX_IPV6_DA:
319 prot_id = seg == 0 ? ICE_PROT_IPV6_OF_OR_S : ICE_PROT_IPV6_IL;
320 break;
321 case ICE_FLOW_FIELD_IDX_TCP_SRC_PORT:
322 case ICE_FLOW_FIELD_IDX_TCP_DST_PORT:
323 prot_id = ICE_PROT_TCP_IL;
324 break;
325 case ICE_FLOW_FIELD_IDX_UDP_SRC_PORT:
326 case ICE_FLOW_FIELD_IDX_UDP_DST_PORT:
327 prot_id = ICE_PROT_UDP_IL_OR_S;
328 break;
329 case ICE_FLOW_FIELD_IDX_SCTP_SRC_PORT:
330 case ICE_FLOW_FIELD_IDX_SCTP_DST_PORT:
331 prot_id = ICE_PROT_SCTP_IL;
332 break;
333 case ICE_FLOW_FIELD_IDX_GRE_KEYID:
334 prot_id = ICE_PROT_GRE_OF;
335 break;
336 default:
337 return ICE_ERR_NOT_IMPL;
338 }
339
340 /* Each extraction sequence entry is a word in size, and extracts a
341 * word-aligned offset from a protocol header.
342 */
343 ese_bits = ICE_FLOW_FV_EXTRACT_SZ * BITS_PER_BYTE;
344
345 flds[fld].xtrct.prot_id = prot_id;
346 flds[fld].xtrct.off = (ice_flds_info[fld].off / ese_bits) *
347 ICE_FLOW_FV_EXTRACT_SZ;
348 flds[fld].xtrct.disp = (u8)(ice_flds_info[fld].off % ese_bits);
349 flds[fld].xtrct.idx = params->es_cnt;
350
351 /* Adjust the next field-entry index after accommodating the number of
352 * entries this field consumes
353 */
354 cnt = DIV_ROUND_UP(flds[fld].xtrct.disp + ice_flds_info[fld].size,
355 ese_bits);
356
357 /* Fill in the extraction sequence entries needed for this field */
358 off = flds[fld].xtrct.off;
359 for (i = 0; i < cnt; i++) {
360 u8 idx;
361
362 /* Make sure the number of extraction sequence required
363 * does not exceed the block's capability
364 */
365 if (params->es_cnt >= fv_words)
366 return ICE_ERR_MAX_LIMIT;
367
368 /* some blocks require a reversed field vector layout */
369 if (hw->blk[params->blk].es.reverse)
370 idx = fv_words - params->es_cnt - 1;
371 else
372 idx = params->es_cnt;
373
374 params->es[idx].prot_id = prot_id;
375 params->es[idx].off = off;
376 params->es_cnt++;
377
378 off += ICE_FLOW_FV_EXTRACT_SZ;
379 }
380
381 return 0;
382}
383
384/**
385 * ice_flow_xtract_raws - Create extract sequence entries for raw bytes
386 * @hw: pointer to the HW struct
387 * @params: information about the flow to be processed
388 * @seg: index of packet segment whose raw fields are to be be extracted
389 */
390static enum ice_status
391ice_flow_xtract_raws(struct ice_hw *hw, struct ice_flow_prof_params *params,
392 u8 seg)
393{
394 u16 fv_words;
395 u16 hdrs_sz;
396 u8 i;
397
398 if (!params->prof->segs[seg].raws_cnt)
399 return 0;
400
401 if (params->prof->segs[seg].raws_cnt >
402 ARRAY_SIZE(params->prof->segs[seg].raws))
403 return ICE_ERR_MAX_LIMIT;
404
405 /* Offsets within the segment headers are not supported */
406 hdrs_sz = ice_flow_calc_seg_sz(params, seg);
407 if (!hdrs_sz)
408 return ICE_ERR_PARAM;
409
410 fv_words = hw->blk[params->blk].es.fvw;
411
412 for (i = 0; i < params->prof->segs[seg].raws_cnt; i++) {
413 struct ice_flow_seg_fld_raw *raw;
414 u16 off, cnt, j;
415
416 raw = ¶ms->prof->segs[seg].raws[i];
417
418 /* Storing extraction information */
419 raw->info.xtrct.prot_id = ICE_PROT_MAC_OF_OR_S;
420 raw->info.xtrct.off = (raw->off / ICE_FLOW_FV_EXTRACT_SZ) *
421 ICE_FLOW_FV_EXTRACT_SZ;
422 raw->info.xtrct.disp = (raw->off % ICE_FLOW_FV_EXTRACT_SZ) *
423 BITS_PER_BYTE;
424 raw->info.xtrct.idx = params->es_cnt;
425
426 /* Determine the number of field vector entries this raw field
427 * consumes.
428 */
429 cnt = DIV_ROUND_UP(raw->info.xtrct.disp +
430 (raw->info.src.last * BITS_PER_BYTE),
431 (ICE_FLOW_FV_EXTRACT_SZ * BITS_PER_BYTE));
432 off = raw->info.xtrct.off;
433 for (j = 0; j < cnt; j++) {
434 u16 idx;
435
436 /* Make sure the number of extraction sequence required
437 * does not exceed the block's capability
438 */
439 if (params->es_cnt >= hw->blk[params->blk].es.count ||
440 params->es_cnt >= ICE_MAX_FV_WORDS)
441 return ICE_ERR_MAX_LIMIT;
442
443 /* some blocks require a reversed field vector layout */
444 if (hw->blk[params->blk].es.reverse)
445 idx = fv_words - params->es_cnt - 1;
446 else
447 idx = params->es_cnt;
448
449 params->es[idx].prot_id = raw->info.xtrct.prot_id;
450 params->es[idx].off = off;
451 params->es_cnt++;
452 off += ICE_FLOW_FV_EXTRACT_SZ;
453 }
454 }
455
456 return 0;
457}
458
459/**
460 * ice_flow_create_xtrct_seq - Create an extraction sequence for given segments
461 * @hw: pointer to the HW struct
462 * @params: information about the flow to be processed
463 *
464 * This function iterates through all matched fields in the given segments, and
465 * creates an extraction sequence for the fields.
466 */
467static enum ice_status
468ice_flow_create_xtrct_seq(struct ice_hw *hw,
469 struct ice_flow_prof_params *params)
470{
471 struct ice_flow_prof *prof = params->prof;
472 enum ice_status status = 0;
473 u8 i;
474
475 for (i = 0; i < prof->segs_cnt; i++) {
476 u8 j;
477
478 for_each_set_bit(j, (unsigned long *)&prof->segs[i].match,
479 ICE_FLOW_FIELD_IDX_MAX) {
480 status = ice_flow_xtract_fld(hw, params, i,
481 (enum ice_flow_field)j);
482 if (status)
483 return status;
484 }
485
486 /* Process raw matching bytes */
487 status = ice_flow_xtract_raws(hw, params, i);
488 if (status)
489 return status;
490 }
491
492 return status;
493}
494
495/**
496 * ice_flow_proc_segs - process all packet segments associated with a profile
497 * @hw: pointer to the HW struct
498 * @params: information about the flow to be processed
499 */
500static enum ice_status
501ice_flow_proc_segs(struct ice_hw *hw, struct ice_flow_prof_params *params)
502{
503 enum ice_status status;
504
505 status = ice_flow_proc_seg_hdrs(params);
506 if (status)
507 return status;
508
509 status = ice_flow_create_xtrct_seq(hw, params);
510 if (status)
511 return status;
512
513 switch (params->blk) {
514 case ICE_BLK_FD:
515 case ICE_BLK_RSS:
516 status = 0;
517 break;
518 default:
519 return ICE_ERR_NOT_IMPL;
520 }
521
522 return status;
523}
524
525#define ICE_FLOW_FIND_PROF_CHK_FLDS 0x00000001
526#define ICE_FLOW_FIND_PROF_CHK_VSI 0x00000002
527#define ICE_FLOW_FIND_PROF_NOT_CHK_DIR 0x00000004
528
529/**
530 * ice_flow_find_prof_conds - Find a profile matching headers and conditions
531 * @hw: pointer to the HW struct
532 * @blk: classification stage
533 * @dir: flow direction
534 * @segs: array of one or more packet segments that describe the flow
535 * @segs_cnt: number of packet segments provided
536 * @vsi_handle: software VSI handle to check VSI (ICE_FLOW_FIND_PROF_CHK_VSI)
537 * @conds: additional conditions to be checked (ICE_FLOW_FIND_PROF_CHK_*)
538 */
539static struct ice_flow_prof *
540ice_flow_find_prof_conds(struct ice_hw *hw, enum ice_block blk,
541 enum ice_flow_dir dir, struct ice_flow_seg_info *segs,
542 u8 segs_cnt, u16 vsi_handle, u32 conds)
543{
544 struct ice_flow_prof *p, *prof = NULL;
545
546 mutex_lock(&hw->fl_profs_locks[blk]);
547 list_for_each_entry(p, &hw->fl_profs[blk], l_entry)
548 if ((p->dir == dir || conds & ICE_FLOW_FIND_PROF_NOT_CHK_DIR) &&
549 segs_cnt && segs_cnt == p->segs_cnt) {
550 u8 i;
551
552 /* Check for profile-VSI association if specified */
553 if ((conds & ICE_FLOW_FIND_PROF_CHK_VSI) &&
554 ice_is_vsi_valid(hw, vsi_handle) &&
555 !test_bit(vsi_handle, p->vsis))
556 continue;
557
558 /* Protocol headers must be checked. Matched fields are
559 * checked if specified.
560 */
561 for (i = 0; i < segs_cnt; i++)
562 if (segs[i].hdrs != p->segs[i].hdrs ||
563 ((conds & ICE_FLOW_FIND_PROF_CHK_FLDS) &&
564 segs[i].match != p->segs[i].match))
565 break;
566
567 /* A match is found if all segments are matched */
568 if (i == segs_cnt) {
569 prof = p;
570 break;
571 }
572 }
573 mutex_unlock(&hw->fl_profs_locks[blk]);
574
575 return prof;
576}
577
578/**
579 * ice_flow_find_prof_id - Look up a profile with given profile ID
580 * @hw: pointer to the HW struct
581 * @blk: classification stage
582 * @prof_id: unique ID to identify this flow profile
583 */
584static struct ice_flow_prof *
585ice_flow_find_prof_id(struct ice_hw *hw, enum ice_block blk, u64 prof_id)
586{
587 struct ice_flow_prof *p;
588
589 list_for_each_entry(p, &hw->fl_profs[blk], l_entry)
590 if (p->id == prof_id)
591 return p;
592
593 return NULL;
594}
595
596/**
597 * ice_dealloc_flow_entry - Deallocate flow entry memory
598 * @hw: pointer to the HW struct
599 * @entry: flow entry to be removed
600 */
601static void
602ice_dealloc_flow_entry(struct ice_hw *hw, struct ice_flow_entry *entry)
603{
604 if (!entry)
605 return;
606
607 if (entry->entry)
608 devm_kfree(ice_hw_to_dev(hw), entry->entry);
609
610 devm_kfree(ice_hw_to_dev(hw), entry);
611}
612
613/**
614 * ice_flow_rem_entry_sync - Remove a flow entry
615 * @hw: pointer to the HW struct
616 * @blk: classification stage
617 * @entry: flow entry to be removed
618 */
619static enum ice_status
620ice_flow_rem_entry_sync(struct ice_hw *hw, enum ice_block __always_unused blk,
621 struct ice_flow_entry *entry)
622{
623 if (!entry)
624 return ICE_ERR_BAD_PTR;
625
626 list_del(&entry->l_entry);
627
628 ice_dealloc_flow_entry(hw, entry);
629
630 return 0;
631}
632
633/**
634 * ice_flow_add_prof_sync - Add a flow profile for packet segments and fields
635 * @hw: pointer to the HW struct
636 * @blk: classification stage
637 * @dir: flow direction
638 * @prof_id: unique ID to identify this flow profile
639 * @segs: array of one or more packet segments that describe the flow
640 * @segs_cnt: number of packet segments provided
641 * @prof: stores the returned flow profile added
642 *
643 * Assumption: the caller has acquired the lock to the profile list
644 */
645static enum ice_status
646ice_flow_add_prof_sync(struct ice_hw *hw, enum ice_block blk,
647 enum ice_flow_dir dir, u64 prof_id,
648 struct ice_flow_seg_info *segs, u8 segs_cnt,
649 struct ice_flow_prof **prof)
650{
651 struct ice_flow_prof_params params;
652 enum ice_status status;
653 u8 i;
654
655 if (!prof)
656 return ICE_ERR_BAD_PTR;
657
658 memset(¶ms, 0, sizeof(params));
659 params.prof = devm_kzalloc(ice_hw_to_dev(hw), sizeof(*params.prof),
660 GFP_KERNEL);
661 if (!params.prof)
662 return ICE_ERR_NO_MEMORY;
663
664 /* initialize extraction sequence to all invalid (0xff) */
665 for (i = 0; i < ICE_MAX_FV_WORDS; i++) {
666 params.es[i].prot_id = ICE_PROT_INVALID;
667 params.es[i].off = ICE_FV_OFFSET_INVAL;
668 }
669
670 params.blk = blk;
671 params.prof->id = prof_id;
672 params.prof->dir = dir;
673 params.prof->segs_cnt = segs_cnt;
674
675 /* Make a copy of the segments that need to be persistent in the flow
676 * profile instance
677 */
678 for (i = 0; i < segs_cnt; i++)
679 memcpy(¶ms.prof->segs[i], &segs[i], sizeof(*segs));
680
681 status = ice_flow_proc_segs(hw, ¶ms);
682 if (status) {
683 ice_debug(hw, ICE_DBG_FLOW,
684 "Error processing a flow's packet segments\n");
685 goto out;
686 }
687
688 /* Add a HW profile for this flow profile */
689 status = ice_add_prof(hw, blk, prof_id, (u8 *)params.ptypes, params.es);
690 if (status) {
691 ice_debug(hw, ICE_DBG_FLOW, "Error adding a HW flow profile\n");
692 goto out;
693 }
694
695 INIT_LIST_HEAD(¶ms.prof->entries);
696 mutex_init(¶ms.prof->entries_lock);
697 *prof = params.prof;
698
699out:
700 if (status)
701 devm_kfree(ice_hw_to_dev(hw), params.prof);
702
703 return status;
704}
705
706/**
707 * ice_flow_rem_prof_sync - remove a flow profile
708 * @hw: pointer to the hardware structure
709 * @blk: classification stage
710 * @prof: pointer to flow profile to remove
711 *
712 * Assumption: the caller has acquired the lock to the profile list
713 */
714static enum ice_status
715ice_flow_rem_prof_sync(struct ice_hw *hw, enum ice_block blk,
716 struct ice_flow_prof *prof)
717{
718 enum ice_status status;
719
720 /* Remove all remaining flow entries before removing the flow profile */
721 if (!list_empty(&prof->entries)) {
722 struct ice_flow_entry *e, *t;
723
724 mutex_lock(&prof->entries_lock);
725
726 list_for_each_entry_safe(e, t, &prof->entries, l_entry) {
727 status = ice_flow_rem_entry_sync(hw, blk, e);
728 if (status)
729 break;
730 }
731
732 mutex_unlock(&prof->entries_lock);
733 }
734
735 /* Remove all hardware profiles associated with this flow profile */
736 status = ice_rem_prof(hw, blk, prof->id);
737 if (!status) {
738 list_del(&prof->l_entry);
739 mutex_destroy(&prof->entries_lock);
740 devm_kfree(ice_hw_to_dev(hw), prof);
741 }
742
743 return status;
744}
745
746/**
747 * ice_flow_assoc_prof - associate a VSI with a flow profile
748 * @hw: pointer to the hardware structure
749 * @blk: classification stage
750 * @prof: pointer to flow profile
751 * @vsi_handle: software VSI handle
752 *
753 * Assumption: the caller has acquired the lock to the profile list
754 * and the software VSI handle has been validated
755 */
756static enum ice_status
757ice_flow_assoc_prof(struct ice_hw *hw, enum ice_block blk,
758 struct ice_flow_prof *prof, u16 vsi_handle)
759{
760 enum ice_status status = 0;
761
762 if (!test_bit(vsi_handle, prof->vsis)) {
763 status = ice_add_prof_id_flow(hw, blk,
764 ice_get_hw_vsi_num(hw,
765 vsi_handle),
766 prof->id);
767 if (!status)
768 set_bit(vsi_handle, prof->vsis);
769 else
770 ice_debug(hw, ICE_DBG_FLOW,
771 "HW profile add failed, %d\n",
772 status);
773 }
774
775 return status;
776}
777
778/**
779 * ice_flow_disassoc_prof - disassociate a VSI from a flow profile
780 * @hw: pointer to the hardware structure
781 * @blk: classification stage
782 * @prof: pointer to flow profile
783 * @vsi_handle: software VSI handle
784 *
785 * Assumption: the caller has acquired the lock to the profile list
786 * and the software VSI handle has been validated
787 */
788static enum ice_status
789ice_flow_disassoc_prof(struct ice_hw *hw, enum ice_block blk,
790 struct ice_flow_prof *prof, u16 vsi_handle)
791{
792 enum ice_status status = 0;
793
794 if (test_bit(vsi_handle, prof->vsis)) {
795 status = ice_rem_prof_id_flow(hw, blk,
796 ice_get_hw_vsi_num(hw,
797 vsi_handle),
798 prof->id);
799 if (!status)
800 clear_bit(vsi_handle, prof->vsis);
801 else
802 ice_debug(hw, ICE_DBG_FLOW,
803 "HW profile remove failed, %d\n",
804 status);
805 }
806
807 return status;
808}
809
810/**
811 * ice_flow_add_prof - Add a flow profile for packet segments and matched fields
812 * @hw: pointer to the HW struct
813 * @blk: classification stage
814 * @dir: flow direction
815 * @prof_id: unique ID to identify this flow profile
816 * @segs: array of one or more packet segments that describe the flow
817 * @segs_cnt: number of packet segments provided
818 * @prof: stores the returned flow profile added
819 */
820enum ice_status
821ice_flow_add_prof(struct ice_hw *hw, enum ice_block blk, enum ice_flow_dir dir,
822 u64 prof_id, struct ice_flow_seg_info *segs, u8 segs_cnt,
823 struct ice_flow_prof **prof)
824{
825 enum ice_status status;
826
827 if (segs_cnt > ICE_FLOW_SEG_MAX)
828 return ICE_ERR_MAX_LIMIT;
829
830 if (!segs_cnt)
831 return ICE_ERR_PARAM;
832
833 if (!segs)
834 return ICE_ERR_BAD_PTR;
835
836 status = ice_flow_val_hdrs(segs, segs_cnt);
837 if (status)
838 return status;
839
840 mutex_lock(&hw->fl_profs_locks[blk]);
841
842 status = ice_flow_add_prof_sync(hw, blk, dir, prof_id, segs, segs_cnt,
843 prof);
844 if (!status)
845 list_add(&(*prof)->l_entry, &hw->fl_profs[blk]);
846
847 mutex_unlock(&hw->fl_profs_locks[blk]);
848
849 return status;
850}
851
852/**
853 * ice_flow_rem_prof - Remove a flow profile and all entries associated with it
854 * @hw: pointer to the HW struct
855 * @blk: the block for which the flow profile is to be removed
856 * @prof_id: unique ID of the flow profile to be removed
857 */
858enum ice_status
859ice_flow_rem_prof(struct ice_hw *hw, enum ice_block blk, u64 prof_id)
860{
861 struct ice_flow_prof *prof;
862 enum ice_status status;
863
864 mutex_lock(&hw->fl_profs_locks[blk]);
865
866 prof = ice_flow_find_prof_id(hw, blk, prof_id);
867 if (!prof) {
868 status = ICE_ERR_DOES_NOT_EXIST;
869 goto out;
870 }
871
872 /* prof becomes invalid after the call */
873 status = ice_flow_rem_prof_sync(hw, blk, prof);
874
875out:
876 mutex_unlock(&hw->fl_profs_locks[blk]);
877
878 return status;
879}
880
881/**
882 * ice_flow_add_entry - Add a flow entry
883 * @hw: pointer to the HW struct
884 * @blk: classification stage
885 * @prof_id: ID of the profile to add a new flow entry to
886 * @entry_id: unique ID to identify this flow entry
887 * @vsi_handle: software VSI handle for the flow entry
888 * @prio: priority of the flow entry
889 * @data: pointer to a data buffer containing flow entry's match values/masks
890 * @entry_h: pointer to buffer that receives the new flow entry's handle
891 */
892enum ice_status
893ice_flow_add_entry(struct ice_hw *hw, enum ice_block blk, u64 prof_id,
894 u64 entry_id, u16 vsi_handle, enum ice_flow_priority prio,
895 void *data, u64 *entry_h)
896{
897 struct ice_flow_entry *e = NULL;
898 struct ice_flow_prof *prof;
899 enum ice_status status;
900
901 /* No flow entry data is expected for RSS */
902 if (!entry_h || (!data && blk != ICE_BLK_RSS))
903 return ICE_ERR_BAD_PTR;
904
905 if (!ice_is_vsi_valid(hw, vsi_handle))
906 return ICE_ERR_PARAM;
907
908 mutex_lock(&hw->fl_profs_locks[blk]);
909
910 prof = ice_flow_find_prof_id(hw, blk, prof_id);
911 if (!prof) {
912 status = ICE_ERR_DOES_NOT_EXIST;
913 } else {
914 /* Allocate memory for the entry being added and associate
915 * the VSI to the found flow profile
916 */
917 e = devm_kzalloc(ice_hw_to_dev(hw), sizeof(*e), GFP_KERNEL);
918 if (!e)
919 status = ICE_ERR_NO_MEMORY;
920 else
921 status = ice_flow_assoc_prof(hw, blk, prof, vsi_handle);
922 }
923
924 mutex_unlock(&hw->fl_profs_locks[blk]);
925 if (status)
926 goto out;
927
928 e->id = entry_id;
929 e->vsi_handle = vsi_handle;
930 e->prof = prof;
931 e->priority = prio;
932
933 switch (blk) {
934 case ICE_BLK_FD:
935 case ICE_BLK_RSS:
936 break;
937 default:
938 status = ICE_ERR_NOT_IMPL;
939 goto out;
940 }
941
942 mutex_lock(&prof->entries_lock);
943 list_add(&e->l_entry, &prof->entries);
944 mutex_unlock(&prof->entries_lock);
945
946 *entry_h = ICE_FLOW_ENTRY_HNDL(e);
947
948out:
949 if (status && e) {
950 if (e->entry)
951 devm_kfree(ice_hw_to_dev(hw), e->entry);
952 devm_kfree(ice_hw_to_dev(hw), e);
953 }
954
955 return status;
956}
957
958/**
959 * ice_flow_rem_entry - Remove a flow entry
960 * @hw: pointer to the HW struct
961 * @blk: classification stage
962 * @entry_h: handle to the flow entry to be removed
963 */
964enum ice_status ice_flow_rem_entry(struct ice_hw *hw, enum ice_block blk,
965 u64 entry_h)
966{
967 struct ice_flow_entry *entry;
968 struct ice_flow_prof *prof;
969 enum ice_status status = 0;
970
971 if (entry_h == ICE_FLOW_ENTRY_HANDLE_INVAL)
972 return ICE_ERR_PARAM;
973
974 entry = ICE_FLOW_ENTRY_PTR(entry_h);
975
976 /* Retain the pointer to the flow profile as the entry will be freed */
977 prof = entry->prof;
978
979 if (prof) {
980 mutex_lock(&prof->entries_lock);
981 status = ice_flow_rem_entry_sync(hw, blk, entry);
982 mutex_unlock(&prof->entries_lock);
983 }
984
985 return status;
986}
987
988/**
989 * ice_flow_set_fld_ext - specifies locations of field from entry's input buffer
990 * @seg: packet segment the field being set belongs to
991 * @fld: field to be set
992 * @field_type: type of the field
993 * @val_loc: if not ICE_FLOW_FLD_OFF_INVAL, location of the value to match from
994 * entry's input buffer
995 * @mask_loc: if not ICE_FLOW_FLD_OFF_INVAL, location of mask value from entry's
996 * input buffer
997 * @last_loc: if not ICE_FLOW_FLD_OFF_INVAL, location of last/upper value from
998 * entry's input buffer
999 *
1000 * This helper function stores information of a field being matched, including
1001 * the type of the field and the locations of the value to match, the mask, and
1002 * and the upper-bound value in the start of the input buffer for a flow entry.
1003 * This function should only be used for fixed-size data structures.
1004 *
1005 * This function also opportunistically determines the protocol headers to be
1006 * present based on the fields being set. Some fields cannot be used alone to
1007 * determine the protocol headers present. Sometimes, fields for particular
1008 * protocol headers are not matched. In those cases, the protocol headers
1009 * must be explicitly set.
1010 */
1011static void
1012ice_flow_set_fld_ext(struct ice_flow_seg_info *seg, enum ice_flow_field fld,
1013 enum ice_flow_fld_match_type field_type, u16 val_loc,
1014 u16 mask_loc, u16 last_loc)
1015{
1016 u64 bit = BIT_ULL(fld);
1017
1018 seg->match |= bit;
1019 if (field_type == ICE_FLOW_FLD_TYPE_RANGE)
1020 seg->range |= bit;
1021
1022 seg->fields[fld].type = field_type;
1023 seg->fields[fld].src.val = val_loc;
1024 seg->fields[fld].src.mask = mask_loc;
1025 seg->fields[fld].src.last = last_loc;
1026
1027 ICE_FLOW_SET_HDRS(seg, ice_flds_info[fld].hdr);
1028}
1029
1030/**
1031 * ice_flow_set_fld - specifies locations of field from entry's input buffer
1032 * @seg: packet segment the field being set belongs to
1033 * @fld: field to be set
1034 * @val_loc: if not ICE_FLOW_FLD_OFF_INVAL, location of the value to match from
1035 * entry's input buffer
1036 * @mask_loc: if not ICE_FLOW_FLD_OFF_INVAL, location of mask value from entry's
1037 * input buffer
1038 * @last_loc: if not ICE_FLOW_FLD_OFF_INVAL, location of last/upper value from
1039 * entry's input buffer
1040 * @range: indicate if field being matched is to be in a range
1041 *
1042 * This function specifies the locations, in the form of byte offsets from the
1043 * start of the input buffer for a flow entry, from where the value to match,
1044 * the mask value, and upper value can be extracted. These locations are then
1045 * stored in the flow profile. When adding a flow entry associated with the
1046 * flow profile, these locations will be used to quickly extract the values and
1047 * create the content of a match entry. This function should only be used for
1048 * fixed-size data structures.
1049 */
1050void
1051ice_flow_set_fld(struct ice_flow_seg_info *seg, enum ice_flow_field fld,
1052 u16 val_loc, u16 mask_loc, u16 last_loc, bool range)
1053{
1054 enum ice_flow_fld_match_type t = range ?
1055 ICE_FLOW_FLD_TYPE_RANGE : ICE_FLOW_FLD_TYPE_REG;
1056
1057 ice_flow_set_fld_ext(seg, fld, t, val_loc, mask_loc, last_loc);
1058}
1059
1060/**
1061 * ice_flow_add_fld_raw - sets locations of a raw field from entry's input buf
1062 * @seg: packet segment the field being set belongs to
1063 * @off: offset of the raw field from the beginning of the segment in bytes
1064 * @len: length of the raw pattern to be matched
1065 * @val_loc: location of the value to match from entry's input buffer
1066 * @mask_loc: location of mask value from entry's input buffer
1067 *
1068 * This function specifies the offset of the raw field to be match from the
1069 * beginning of the specified packet segment, and the locations, in the form of
1070 * byte offsets from the start of the input buffer for a flow entry, from where
1071 * the value to match and the mask value to be extracted. These locations are
1072 * then stored in the flow profile. When adding flow entries to the associated
1073 * flow profile, these locations can be used to quickly extract the values to
1074 * create the content of a match entry. This function should only be used for
1075 * fixed-size data structures.
1076 */
1077void
1078ice_flow_add_fld_raw(struct ice_flow_seg_info *seg, u16 off, u8 len,
1079 u16 val_loc, u16 mask_loc)
1080{
1081 if (seg->raws_cnt < ICE_FLOW_SEG_RAW_FLD_MAX) {
1082 seg->raws[seg->raws_cnt].off = off;
1083 seg->raws[seg->raws_cnt].info.type = ICE_FLOW_FLD_TYPE_SIZE;
1084 seg->raws[seg->raws_cnt].info.src.val = val_loc;
1085 seg->raws[seg->raws_cnt].info.src.mask = mask_loc;
1086 /* The "last" field is used to store the length of the field */
1087 seg->raws[seg->raws_cnt].info.src.last = len;
1088 }
1089
1090 /* Overflows of "raws" will be handled as an error condition later in
1091 * the flow when this information is processed.
1092 */
1093 seg->raws_cnt++;
1094}
1095
1096#define ICE_FLOW_RSS_SEG_HDR_L3_MASKS \
1097 (ICE_FLOW_SEG_HDR_IPV4 | ICE_FLOW_SEG_HDR_IPV6)
1098
1099#define ICE_FLOW_RSS_SEG_HDR_L4_MASKS \
1100 (ICE_FLOW_SEG_HDR_TCP | ICE_FLOW_SEG_HDR_UDP | ICE_FLOW_SEG_HDR_SCTP)
1101
1102#define ICE_FLOW_RSS_SEG_HDR_VAL_MASKS \
1103 (ICE_FLOW_RSS_SEG_HDR_L3_MASKS | \
1104 ICE_FLOW_RSS_SEG_HDR_L4_MASKS)
1105
1106/**
1107 * ice_flow_set_rss_seg_info - setup packet segments for RSS
1108 * @segs: pointer to the flow field segment(s)
1109 * @hash_fields: fields to be hashed on for the segment(s)
1110 * @flow_hdr: protocol header fields within a packet segment
1111 *
1112 * Helper function to extract fields from hash bitmap and use flow
1113 * header value to set flow field segment for further use in flow
1114 * profile entry or removal.
1115 */
1116static enum ice_status
1117ice_flow_set_rss_seg_info(struct ice_flow_seg_info *segs, u64 hash_fields,
1118 u32 flow_hdr)
1119{
1120 u64 val;
1121 u8 i;
1122
1123 for_each_set_bit(i, (unsigned long *)&hash_fields,
1124 ICE_FLOW_FIELD_IDX_MAX)
1125 ice_flow_set_fld(segs, (enum ice_flow_field)i,
1126 ICE_FLOW_FLD_OFF_INVAL, ICE_FLOW_FLD_OFF_INVAL,
1127 ICE_FLOW_FLD_OFF_INVAL, false);
1128
1129 ICE_FLOW_SET_HDRS(segs, flow_hdr);
1130
1131 if (segs->hdrs & ~ICE_FLOW_RSS_SEG_HDR_VAL_MASKS)
1132 return ICE_ERR_PARAM;
1133
1134 val = (u64)(segs->hdrs & ICE_FLOW_RSS_SEG_HDR_L3_MASKS);
1135 if (val && !is_power_of_2(val))
1136 return ICE_ERR_CFG;
1137
1138 val = (u64)(segs->hdrs & ICE_FLOW_RSS_SEG_HDR_L4_MASKS);
1139 if (val && !is_power_of_2(val))
1140 return ICE_ERR_CFG;
1141
1142 return 0;
1143}
1144
1145/**
1146 * ice_rem_vsi_rss_list - remove VSI from RSS list
1147 * @hw: pointer to the hardware structure
1148 * @vsi_handle: software VSI handle
1149 *
1150 * Remove the VSI from all RSS configurations in the list.
1151 */
1152void ice_rem_vsi_rss_list(struct ice_hw *hw, u16 vsi_handle)
1153{
1154 struct ice_rss_cfg *r, *tmp;
1155
1156 if (list_empty(&hw->rss_list_head))
1157 return;
1158
1159 mutex_lock(&hw->rss_locks);
1160 list_for_each_entry_safe(r, tmp, &hw->rss_list_head, l_entry)
1161 if (test_and_clear_bit(vsi_handle, r->vsis))
1162 if (bitmap_empty(r->vsis, ICE_MAX_VSI)) {
1163 list_del(&r->l_entry);
1164 devm_kfree(ice_hw_to_dev(hw), r);
1165 }
1166 mutex_unlock(&hw->rss_locks);
1167}
1168
1169/**
1170 * ice_rem_vsi_rss_cfg - remove RSS configurations associated with VSI
1171 * @hw: pointer to the hardware structure
1172 * @vsi_handle: software VSI handle
1173 *
1174 * This function will iterate through all flow profiles and disassociate
1175 * the VSI from that profile. If the flow profile has no VSIs it will
1176 * be removed.
1177 */
1178enum ice_status ice_rem_vsi_rss_cfg(struct ice_hw *hw, u16 vsi_handle)
1179{
1180 const enum ice_block blk = ICE_BLK_RSS;
1181 struct ice_flow_prof *p, *t;
1182 enum ice_status status = 0;
1183
1184 if (!ice_is_vsi_valid(hw, vsi_handle))
1185 return ICE_ERR_PARAM;
1186
1187 if (list_empty(&hw->fl_profs[blk]))
1188 return 0;
1189
1190 mutex_lock(&hw->rss_locks);
1191 list_for_each_entry_safe(p, t, &hw->fl_profs[blk], l_entry)
1192 if (test_bit(vsi_handle, p->vsis)) {
1193 status = ice_flow_disassoc_prof(hw, blk, p, vsi_handle);
1194 if (status)
1195 break;
1196
1197 if (bitmap_empty(p->vsis, ICE_MAX_VSI)) {
1198 status = ice_flow_rem_prof(hw, blk, p->id);
1199 if (status)
1200 break;
1201 }
1202 }
1203 mutex_unlock(&hw->rss_locks);
1204
1205 return status;
1206}
1207
1208/**
1209 * ice_rem_rss_list - remove RSS configuration from list
1210 * @hw: pointer to the hardware structure
1211 * @vsi_handle: software VSI handle
1212 * @prof: pointer to flow profile
1213 *
1214 * Assumption: lock has already been acquired for RSS list
1215 */
1216static void
1217ice_rem_rss_list(struct ice_hw *hw, u16 vsi_handle, struct ice_flow_prof *prof)
1218{
1219 struct ice_rss_cfg *r, *tmp;
1220
1221 /* Search for RSS hash fields associated to the VSI that match the
1222 * hash configurations associated to the flow profile. If found
1223 * remove from the RSS entry list of the VSI context and delete entry.
1224 */
1225 list_for_each_entry_safe(r, tmp, &hw->rss_list_head, l_entry)
1226 if (r->hashed_flds == prof->segs[prof->segs_cnt - 1].match &&
1227 r->packet_hdr == prof->segs[prof->segs_cnt - 1].hdrs) {
1228 clear_bit(vsi_handle, r->vsis);
1229 if (bitmap_empty(r->vsis, ICE_MAX_VSI)) {
1230 list_del(&r->l_entry);
1231 devm_kfree(ice_hw_to_dev(hw), r);
1232 }
1233 return;
1234 }
1235}
1236
1237/**
1238 * ice_add_rss_list - add RSS configuration to list
1239 * @hw: pointer to the hardware structure
1240 * @vsi_handle: software VSI handle
1241 * @prof: pointer to flow profile
1242 *
1243 * Assumption: lock has already been acquired for RSS list
1244 */
1245static enum ice_status
1246ice_add_rss_list(struct ice_hw *hw, u16 vsi_handle, struct ice_flow_prof *prof)
1247{
1248 struct ice_rss_cfg *r, *rss_cfg;
1249
1250 list_for_each_entry(r, &hw->rss_list_head, l_entry)
1251 if (r->hashed_flds == prof->segs[prof->segs_cnt - 1].match &&
1252 r->packet_hdr == prof->segs[prof->segs_cnt - 1].hdrs) {
1253 set_bit(vsi_handle, r->vsis);
1254 return 0;
1255 }
1256
1257 rss_cfg = devm_kzalloc(ice_hw_to_dev(hw), sizeof(*rss_cfg),
1258 GFP_KERNEL);
1259 if (!rss_cfg)
1260 return ICE_ERR_NO_MEMORY;
1261
1262 rss_cfg->hashed_flds = prof->segs[prof->segs_cnt - 1].match;
1263 rss_cfg->packet_hdr = prof->segs[prof->segs_cnt - 1].hdrs;
1264 set_bit(vsi_handle, rss_cfg->vsis);
1265
1266 list_add_tail(&rss_cfg->l_entry, &hw->rss_list_head);
1267
1268 return 0;
1269}
1270
1271#define ICE_FLOW_PROF_HASH_S 0
1272#define ICE_FLOW_PROF_HASH_M (0xFFFFFFFFULL << ICE_FLOW_PROF_HASH_S)
1273#define ICE_FLOW_PROF_HDR_S 32
1274#define ICE_FLOW_PROF_HDR_M (0x3FFFFFFFULL << ICE_FLOW_PROF_HDR_S)
1275#define ICE_FLOW_PROF_ENCAP_S 63
1276#define ICE_FLOW_PROF_ENCAP_M (BIT_ULL(ICE_FLOW_PROF_ENCAP_S))
1277
1278#define ICE_RSS_OUTER_HEADERS 1
1279#define ICE_RSS_INNER_HEADERS 2
1280
1281/* Flow profile ID format:
1282 * [0:31] - Packet match fields
1283 * [32:62] - Protocol header
1284 * [63] - Encapsulation flag, 0 if non-tunneled, 1 if tunneled
1285 */
1286#define ICE_FLOW_GEN_PROFID(hash, hdr, segs_cnt) \
1287 (u64)(((u64)(hash) & ICE_FLOW_PROF_HASH_M) | \
1288 (((u64)(hdr) << ICE_FLOW_PROF_HDR_S) & ICE_FLOW_PROF_HDR_M) | \
1289 ((u8)((segs_cnt) - 1) ? ICE_FLOW_PROF_ENCAP_M : 0))
1290
1291/**
1292 * ice_add_rss_cfg_sync - add an RSS configuration
1293 * @hw: pointer to the hardware structure
1294 * @vsi_handle: software VSI handle
1295 * @hashed_flds: hash bit fields (ICE_FLOW_HASH_*) to configure
1296 * @addl_hdrs: protocol header fields
1297 * @segs_cnt: packet segment count
1298 *
1299 * Assumption: lock has already been acquired for RSS list
1300 */
1301static enum ice_status
1302ice_add_rss_cfg_sync(struct ice_hw *hw, u16 vsi_handle, u64 hashed_flds,
1303 u32 addl_hdrs, u8 segs_cnt)
1304{
1305 const enum ice_block blk = ICE_BLK_RSS;
1306 struct ice_flow_prof *prof = NULL;
1307 struct ice_flow_seg_info *segs;
1308 enum ice_status status;
1309
1310 if (!segs_cnt || segs_cnt > ICE_FLOW_SEG_MAX)
1311 return ICE_ERR_PARAM;
1312
1313 segs = kcalloc(segs_cnt, sizeof(*segs), GFP_KERNEL);
1314 if (!segs)
1315 return ICE_ERR_NO_MEMORY;
1316
1317 /* Construct the packet segment info from the hashed fields */
1318 status = ice_flow_set_rss_seg_info(&segs[segs_cnt - 1], hashed_flds,
1319 addl_hdrs);
1320 if (status)
1321 goto exit;
1322
1323 /* Search for a flow profile that has matching headers, hash fields
1324 * and has the input VSI associated to it. If found, no further
1325 * operations required and exit.
1326 */
1327 prof = ice_flow_find_prof_conds(hw, blk, ICE_FLOW_RX, segs, segs_cnt,
1328 vsi_handle,
1329 ICE_FLOW_FIND_PROF_CHK_FLDS |
1330 ICE_FLOW_FIND_PROF_CHK_VSI);
1331 if (prof)
1332 goto exit;
1333
1334 /* Check if a flow profile exists with the same protocol headers and
1335 * associated with the input VSI. If so disassociate the VSI from
1336 * this profile. The VSI will be added to a new profile created with
1337 * the protocol header and new hash field configuration.
1338 */
1339 prof = ice_flow_find_prof_conds(hw, blk, ICE_FLOW_RX, segs, segs_cnt,
1340 vsi_handle, ICE_FLOW_FIND_PROF_CHK_VSI);
1341 if (prof) {
1342 status = ice_flow_disassoc_prof(hw, blk, prof, vsi_handle);
1343 if (!status)
1344 ice_rem_rss_list(hw, vsi_handle, prof);
1345 else
1346 goto exit;
1347
1348 /* Remove profile if it has no VSIs associated */
1349 if (bitmap_empty(prof->vsis, ICE_MAX_VSI)) {
1350 status = ice_flow_rem_prof(hw, blk, prof->id);
1351 if (status)
1352 goto exit;
1353 }
1354 }
1355
1356 /* Search for a profile that has same match fields only. If this
1357 * exists then associate the VSI to this profile.
1358 */
1359 prof = ice_flow_find_prof_conds(hw, blk, ICE_FLOW_RX, segs, segs_cnt,
1360 vsi_handle,
1361 ICE_FLOW_FIND_PROF_CHK_FLDS);
1362 if (prof) {
1363 status = ice_flow_assoc_prof(hw, blk, prof, vsi_handle);
1364 if (!status)
1365 status = ice_add_rss_list(hw, vsi_handle, prof);
1366 goto exit;
1367 }
1368
1369 /* Create a new flow profile with generated profile and packet
1370 * segment information.
1371 */
1372 status = ice_flow_add_prof(hw, blk, ICE_FLOW_RX,
1373 ICE_FLOW_GEN_PROFID(hashed_flds,
1374 segs[segs_cnt - 1].hdrs,
1375 segs_cnt),
1376 segs, segs_cnt, &prof);
1377 if (status)
1378 goto exit;
1379
1380 status = ice_flow_assoc_prof(hw, blk, prof, vsi_handle);
1381 /* If association to a new flow profile failed then this profile can
1382 * be removed.
1383 */
1384 if (status) {
1385 ice_flow_rem_prof(hw, blk, prof->id);
1386 goto exit;
1387 }
1388
1389 status = ice_add_rss_list(hw, vsi_handle, prof);
1390
1391exit:
1392 kfree(segs);
1393 return status;
1394}
1395
1396/**
1397 * ice_add_rss_cfg - add an RSS configuration with specified hashed fields
1398 * @hw: pointer to the hardware structure
1399 * @vsi_handle: software VSI handle
1400 * @hashed_flds: hash bit fields (ICE_FLOW_HASH_*) to configure
1401 * @addl_hdrs: protocol header fields
1402 *
1403 * This function will generate a flow profile based on fields associated with
1404 * the input fields to hash on, the flow type and use the VSI number to add
1405 * a flow entry to the profile.
1406 */
1407enum ice_status
1408ice_add_rss_cfg(struct ice_hw *hw, u16 vsi_handle, u64 hashed_flds,
1409 u32 addl_hdrs)
1410{
1411 enum ice_status status;
1412
1413 if (hashed_flds == ICE_HASH_INVALID ||
1414 !ice_is_vsi_valid(hw, vsi_handle))
1415 return ICE_ERR_PARAM;
1416
1417 mutex_lock(&hw->rss_locks);
1418 status = ice_add_rss_cfg_sync(hw, vsi_handle, hashed_flds, addl_hdrs,
1419 ICE_RSS_OUTER_HEADERS);
1420 if (!status)
1421 status = ice_add_rss_cfg_sync(hw, vsi_handle, hashed_flds,
1422 addl_hdrs, ICE_RSS_INNER_HEADERS);
1423 mutex_unlock(&hw->rss_locks);
1424
1425 return status;
1426}
1427
1428/* Mapping of AVF hash bit fields to an L3-L4 hash combination.
1429 * As the ice_flow_avf_hdr_field represent individual bit shifts in a hash,
1430 * convert its values to their appropriate flow L3, L4 values.
1431 */
1432#define ICE_FLOW_AVF_RSS_IPV4_MASKS \
1433 (BIT_ULL(ICE_AVF_FLOW_FIELD_IPV4_OTHER) | \
1434 BIT_ULL(ICE_AVF_FLOW_FIELD_FRAG_IPV4))
1435#define ICE_FLOW_AVF_RSS_TCP_IPV4_MASKS \
1436 (BIT_ULL(ICE_AVF_FLOW_FIELD_IPV4_TCP_SYN_NO_ACK) | \
1437 BIT_ULL(ICE_AVF_FLOW_FIELD_IPV4_TCP))
1438#define ICE_FLOW_AVF_RSS_UDP_IPV4_MASKS \
1439 (BIT_ULL(ICE_AVF_FLOW_FIELD_UNICAST_IPV4_UDP) | \
1440 BIT_ULL(ICE_AVF_FLOW_FIELD_MULTICAST_IPV4_UDP) | \
1441 BIT_ULL(ICE_AVF_FLOW_FIELD_IPV4_UDP))
1442#define ICE_FLOW_AVF_RSS_ALL_IPV4_MASKS \
1443 (ICE_FLOW_AVF_RSS_TCP_IPV4_MASKS | ICE_FLOW_AVF_RSS_UDP_IPV4_MASKS | \
1444 ICE_FLOW_AVF_RSS_IPV4_MASKS | BIT_ULL(ICE_AVF_FLOW_FIELD_IPV4_SCTP))
1445
1446#define ICE_FLOW_AVF_RSS_IPV6_MASKS \
1447 (BIT_ULL(ICE_AVF_FLOW_FIELD_IPV6_OTHER) | \
1448 BIT_ULL(ICE_AVF_FLOW_FIELD_FRAG_IPV6))
1449#define ICE_FLOW_AVF_RSS_UDP_IPV6_MASKS \
1450 (BIT_ULL(ICE_AVF_FLOW_FIELD_UNICAST_IPV6_UDP) | \
1451 BIT_ULL(ICE_AVF_FLOW_FIELD_MULTICAST_IPV6_UDP) | \
1452 BIT_ULL(ICE_AVF_FLOW_FIELD_IPV6_UDP))
1453#define ICE_FLOW_AVF_RSS_TCP_IPV6_MASKS \
1454 (BIT_ULL(ICE_AVF_FLOW_FIELD_IPV6_TCP_SYN_NO_ACK) | \
1455 BIT_ULL(ICE_AVF_FLOW_FIELD_IPV6_TCP))
1456#define ICE_FLOW_AVF_RSS_ALL_IPV6_MASKS \
1457 (ICE_FLOW_AVF_RSS_TCP_IPV6_MASKS | ICE_FLOW_AVF_RSS_UDP_IPV6_MASKS | \
1458 ICE_FLOW_AVF_RSS_IPV6_MASKS | BIT_ULL(ICE_AVF_FLOW_FIELD_IPV6_SCTP))
1459
1460/**
1461 * ice_add_avf_rss_cfg - add an RSS configuration for AVF driver
1462 * @hw: pointer to the hardware structure
1463 * @vsi_handle: software VSI handle
1464 * @avf_hash: hash bit fields (ICE_AVF_FLOW_FIELD_*) to configure
1465 *
1466 * This function will take the hash bitmap provided by the AVF driver via a
1467 * message, convert it to ICE-compatible values, and configure RSS flow
1468 * profiles.
1469 */
1470enum ice_status
1471ice_add_avf_rss_cfg(struct ice_hw *hw, u16 vsi_handle, u64 avf_hash)
1472{
1473 enum ice_status status = 0;
1474 u64 hash_flds;
1475
1476 if (avf_hash == ICE_AVF_FLOW_FIELD_INVALID ||
1477 !ice_is_vsi_valid(hw, vsi_handle))
1478 return ICE_ERR_PARAM;
1479
1480 /* Make sure no unsupported bits are specified */
1481 if (avf_hash & ~(ICE_FLOW_AVF_RSS_ALL_IPV4_MASKS |
1482 ICE_FLOW_AVF_RSS_ALL_IPV6_MASKS))
1483 return ICE_ERR_CFG;
1484
1485 hash_flds = avf_hash;
1486
1487 /* Always create an L3 RSS configuration for any L4 RSS configuration */
1488 if (hash_flds & ICE_FLOW_AVF_RSS_ALL_IPV4_MASKS)
1489 hash_flds |= ICE_FLOW_AVF_RSS_IPV4_MASKS;
1490
1491 if (hash_flds & ICE_FLOW_AVF_RSS_ALL_IPV6_MASKS)
1492 hash_flds |= ICE_FLOW_AVF_RSS_IPV6_MASKS;
1493
1494 /* Create the corresponding RSS configuration for each valid hash bit */
1495 while (hash_flds) {
1496 u64 rss_hash = ICE_HASH_INVALID;
1497
1498 if (hash_flds & ICE_FLOW_AVF_RSS_ALL_IPV4_MASKS) {
1499 if (hash_flds & ICE_FLOW_AVF_RSS_IPV4_MASKS) {
1500 rss_hash = ICE_FLOW_HASH_IPV4;
1501 hash_flds &= ~ICE_FLOW_AVF_RSS_IPV4_MASKS;
1502 } else if (hash_flds &
1503 ICE_FLOW_AVF_RSS_TCP_IPV4_MASKS) {
1504 rss_hash = ICE_FLOW_HASH_IPV4 |
1505 ICE_FLOW_HASH_TCP_PORT;
1506 hash_flds &= ~ICE_FLOW_AVF_RSS_TCP_IPV4_MASKS;
1507 } else if (hash_flds &
1508 ICE_FLOW_AVF_RSS_UDP_IPV4_MASKS) {
1509 rss_hash = ICE_FLOW_HASH_IPV4 |
1510 ICE_FLOW_HASH_UDP_PORT;
1511 hash_flds &= ~ICE_FLOW_AVF_RSS_UDP_IPV4_MASKS;
1512 } else if (hash_flds &
1513 BIT_ULL(ICE_AVF_FLOW_FIELD_IPV4_SCTP)) {
1514 rss_hash = ICE_FLOW_HASH_IPV4 |
1515 ICE_FLOW_HASH_SCTP_PORT;
1516 hash_flds &=
1517 ~BIT_ULL(ICE_AVF_FLOW_FIELD_IPV4_SCTP);
1518 }
1519 } else if (hash_flds & ICE_FLOW_AVF_RSS_ALL_IPV6_MASKS) {
1520 if (hash_flds & ICE_FLOW_AVF_RSS_IPV6_MASKS) {
1521 rss_hash = ICE_FLOW_HASH_IPV6;
1522 hash_flds &= ~ICE_FLOW_AVF_RSS_IPV6_MASKS;
1523 } else if (hash_flds &
1524 ICE_FLOW_AVF_RSS_TCP_IPV6_MASKS) {
1525 rss_hash = ICE_FLOW_HASH_IPV6 |
1526 ICE_FLOW_HASH_TCP_PORT;
1527 hash_flds &= ~ICE_FLOW_AVF_RSS_TCP_IPV6_MASKS;
1528 } else if (hash_flds &
1529 ICE_FLOW_AVF_RSS_UDP_IPV6_MASKS) {
1530 rss_hash = ICE_FLOW_HASH_IPV6 |
1531 ICE_FLOW_HASH_UDP_PORT;
1532 hash_flds &= ~ICE_FLOW_AVF_RSS_UDP_IPV6_MASKS;
1533 } else if (hash_flds &
1534 BIT_ULL(ICE_AVF_FLOW_FIELD_IPV6_SCTP)) {
1535 rss_hash = ICE_FLOW_HASH_IPV6 |
1536 ICE_FLOW_HASH_SCTP_PORT;
1537 hash_flds &=
1538 ~BIT_ULL(ICE_AVF_FLOW_FIELD_IPV6_SCTP);
1539 }
1540 }
1541
1542 if (rss_hash == ICE_HASH_INVALID)
1543 return ICE_ERR_OUT_OF_RANGE;
1544
1545 status = ice_add_rss_cfg(hw, vsi_handle, rss_hash,
1546 ICE_FLOW_SEG_HDR_NONE);
1547 if (status)
1548 break;
1549 }
1550
1551 return status;
1552}
1553
1554/**
1555 * ice_replay_rss_cfg - replay RSS configurations associated with VSI
1556 * @hw: pointer to the hardware structure
1557 * @vsi_handle: software VSI handle
1558 */
1559enum ice_status ice_replay_rss_cfg(struct ice_hw *hw, u16 vsi_handle)
1560{
1561 enum ice_status status = 0;
1562 struct ice_rss_cfg *r;
1563
1564 if (!ice_is_vsi_valid(hw, vsi_handle))
1565 return ICE_ERR_PARAM;
1566
1567 mutex_lock(&hw->rss_locks);
1568 list_for_each_entry(r, &hw->rss_list_head, l_entry) {
1569 if (test_bit(vsi_handle, r->vsis)) {
1570 status = ice_add_rss_cfg_sync(hw, vsi_handle,
1571 r->hashed_flds,
1572 r->packet_hdr,
1573 ICE_RSS_OUTER_HEADERS);
1574 if (status)
1575 break;
1576 status = ice_add_rss_cfg_sync(hw, vsi_handle,
1577 r->hashed_flds,
1578 r->packet_hdr,
1579 ICE_RSS_INNER_HEADERS);
1580 if (status)
1581 break;
1582 }
1583 }
1584 mutex_unlock(&hw->rss_locks);
1585
1586 return status;
1587}
1588
1589/**
1590 * ice_get_rss_cfg - returns hashed fields for the given header types
1591 * @hw: pointer to the hardware structure
1592 * @vsi_handle: software VSI handle
1593 * @hdrs: protocol header type
1594 *
1595 * This function will return the match fields of the first instance of flow
1596 * profile having the given header types and containing input VSI
1597 */
1598u64 ice_get_rss_cfg(struct ice_hw *hw, u16 vsi_handle, u32 hdrs)
1599{
1600 u64 rss_hash = ICE_HASH_INVALID;
1601 struct ice_rss_cfg *r;
1602
1603 /* verify if the protocol header is non zero and VSI is valid */
1604 if (hdrs == ICE_FLOW_SEG_HDR_NONE || !ice_is_vsi_valid(hw, vsi_handle))
1605 return ICE_HASH_INVALID;
1606
1607 mutex_lock(&hw->rss_locks);
1608 list_for_each_entry(r, &hw->rss_list_head, l_entry)
1609 if (test_bit(vsi_handle, r->vsis) &&
1610 r->packet_hdr == hdrs) {
1611 rss_hash = r->hashed_flds;
1612 break;
1613 }
1614 mutex_unlock(&hw->rss_locks);
1615
1616 return rss_hash;
1617}