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 */
8 struct 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 */
21 static const
22 struct 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 */
55 static 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 */
67 static 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 */
79 static 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 */
91 static 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 /* Packet types for packets with an Outer/First/Single IPv4 header - no L4 */
103 static const u32 ice_ipv4_ofos_no_l4[] = {
104 0x10C00000, 0x04000800, 0x00000000, 0x00000000,
105 0x00000000, 0x00000000, 0x00000000, 0x00000000,
106 0x00000000, 0x00000000, 0x00000000, 0x00000000,
107 0x00000000, 0x00000000, 0x00000000, 0x00000000,
108 0x00000000, 0x00000000, 0x00000000, 0x00000000,
109 0x00000000, 0x00000000, 0x00000000, 0x00000000,
110 0x00000000, 0x00000000, 0x00000000, 0x00000000,
111 0x00000000, 0x00000000, 0x00000000, 0x00000000,
112 };
113
114 /* Packet types for packets with an Innermost/Last IPv4 header - no L4 */
115 static const u32 ice_ipv4_il_no_l4[] = {
116 0x60000000, 0x18043008, 0x80000002, 0x6010c021,
117 0x00000008, 0x00000000, 0x00000000, 0x00000000,
118 0x00000000, 0x00000000, 0x00000000, 0x00000000,
119 0x00000000, 0x00000000, 0x00000000, 0x00000000,
120 0x00000000, 0x00000000, 0x00000000, 0x00000000,
121 0x00000000, 0x00000000, 0x00000000, 0x00000000,
122 0x00000000, 0x00000000, 0x00000000, 0x00000000,
123 0x00000000, 0x00000000, 0x00000000, 0x00000000,
124 };
125
126 /* Packet types for packets with an Outer/First/Single IPv6 header - no L4 */
127 static const u32 ice_ipv6_ofos_no_l4[] = {
128 0x00000000, 0x00000000, 0x43000000, 0x10002000,
129 0x00000000, 0x00000000, 0x00000000, 0x00000000,
130 0x00000000, 0x00000000, 0x00000000, 0x00000000,
131 0x00000000, 0x00000000, 0x00000000, 0x00000000,
132 0x00000000, 0x00000000, 0x00000000, 0x00000000,
133 0x00000000, 0x00000000, 0x00000000, 0x00000000,
134 0x00000000, 0x00000000, 0x00000000, 0x00000000,
135 0x00000000, 0x00000000, 0x00000000, 0x00000000,
136 };
137
138 /* Packet types for packets with an Innermost/Last IPv6 header - no L4 */
139 static const u32 ice_ipv6_il_no_l4[] = {
140 0x00000000, 0x02180430, 0x0000010c, 0x086010c0,
141 0x00000430, 0x00000000, 0x00000000, 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 0x00000000, 0x00000000, 0x00000000, 0x00000000,
148 };
149
150 /* UDP Packet types for non-tunneled packets or tunneled
151 * packets with inner UDP.
152 */
153 static const u32 ice_ptypes_udp_il[] = {
154 0x81000000, 0x20204040, 0x04000010, 0x80810102,
155 0x00000040, 0x00000000, 0x00000000, 0x00000000,
156 0x00000000, 0x00000000, 0x00000000, 0x00000000,
157 0x00000000, 0x00000000, 0x00000000, 0x00000000,
158 0x00000000, 0x00000000, 0x00000000, 0x00000000,
159 0x00000000, 0x00000000, 0x00000000, 0x00000000,
160 0x00000000, 0x00000000, 0x00000000, 0x00000000,
161 0x00000000, 0x00000000, 0x00000000, 0x00000000,
162 };
163
164 /* Packet types for packets with an Innermost/Last TCP header */
165 static const u32 ice_ptypes_tcp_il[] = {
166 0x04000000, 0x80810102, 0x10000040, 0x02040408,
167 0x00000102, 0x00000000, 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 0x00000000, 0x00000000, 0x00000000, 0x00000000,
174 };
175
176 /* Packet types for packets with an Innermost/Last SCTP header */
177 static const u32 ice_ptypes_sctp_il[] = {
178 0x08000000, 0x01020204, 0x20000081, 0x04080810,
179 0x00000204, 0x00000000, 0x00000000, 0x00000000,
180 0x00000000, 0x00000000, 0x00000000, 0x00000000,
181 0x00000000, 0x00000000, 0x00000000, 0x00000000,
182 0x00000000, 0x00000000, 0x00000000, 0x00000000,
183 0x00000000, 0x00000000, 0x00000000, 0x00000000,
184 0x00000000, 0x00000000, 0x00000000, 0x00000000,
185 0x00000000, 0x00000000, 0x00000000, 0x00000000,
186 };
187
188 /* Packet types for packets with an Outermost/First GRE header */
189 static const u32 ice_ptypes_gre_of[] = {
190 0x00000000, 0xBFBF7800, 0x000001DF, 0xFEFDE000,
191 0x0000017E, 0x00000000, 0x00000000, 0x00000000,
192 0x00000000, 0x00000000, 0x00000000, 0x00000000,
193 0x00000000, 0x00000000, 0x00000000, 0x00000000,
194 0x00000000, 0x00000000, 0x00000000, 0x00000000,
195 0x00000000, 0x00000000, 0x00000000, 0x00000000,
196 0x00000000, 0x00000000, 0x00000000, 0x00000000,
197 0x00000000, 0x00000000, 0x00000000, 0x00000000,
198 };
199
200 /* Manage parameters and info. used during the creation of a flow profile */
201 struct ice_flow_prof_params {
202 enum ice_block blk;
203 u16 entry_length; /* # of bytes formatted entry will require */
204 u8 es_cnt;
205 struct ice_flow_prof *prof;
206
207 /* For ACL, the es[0] will have the data of ICE_RX_MDID_PKT_FLAGS_15_0
208 * This will give us the direction flags.
209 */
210 struct ice_fv_word es[ICE_MAX_FV_WORDS];
211 DECLARE_BITMAP(ptypes, ICE_FLOW_PTYPE_MAX);
212 };
213
214 #define ICE_FLOW_SEG_HDRS_L3_MASK \
215 (ICE_FLOW_SEG_HDR_IPV4 | ICE_FLOW_SEG_HDR_IPV6)
216 #define ICE_FLOW_SEG_HDRS_L4_MASK \
217 (ICE_FLOW_SEG_HDR_TCP | ICE_FLOW_SEG_HDR_UDP | ICE_FLOW_SEG_HDR_SCTP)
218
219 /**
220 * ice_flow_val_hdrs - validates packet segments for valid protocol headers
221 * @segs: array of one or more packet segments that describe the flow
222 * @segs_cnt: number of packet segments provided
223 */
224 static enum ice_status
ice_flow_val_hdrs(struct ice_flow_seg_info * segs,u8 segs_cnt)225 ice_flow_val_hdrs(struct ice_flow_seg_info *segs, u8 segs_cnt)
226 {
227 u8 i;
228
229 for (i = 0; i < segs_cnt; i++) {
230 /* Multiple L3 headers */
231 if (segs[i].hdrs & ICE_FLOW_SEG_HDRS_L3_MASK &&
232 !is_power_of_2(segs[i].hdrs & ICE_FLOW_SEG_HDRS_L3_MASK))
233 return ICE_ERR_PARAM;
234
235 /* Multiple L4 headers */
236 if (segs[i].hdrs & ICE_FLOW_SEG_HDRS_L4_MASK &&
237 !is_power_of_2(segs[i].hdrs & ICE_FLOW_SEG_HDRS_L4_MASK))
238 return ICE_ERR_PARAM;
239 }
240
241 return 0;
242 }
243
244 /* Sizes of fixed known protocol headers without header options */
245 #define ICE_FLOW_PROT_HDR_SZ_MAC 14
246 #define ICE_FLOW_PROT_HDR_SZ_IPV4 20
247 #define ICE_FLOW_PROT_HDR_SZ_IPV6 40
248 #define ICE_FLOW_PROT_HDR_SZ_TCP 20
249 #define ICE_FLOW_PROT_HDR_SZ_UDP 8
250 #define ICE_FLOW_PROT_HDR_SZ_SCTP 12
251
252 /**
253 * ice_flow_calc_seg_sz - calculates size of a packet segment based on headers
254 * @params: information about the flow to be processed
255 * @seg: index of packet segment whose header size is to be determined
256 */
ice_flow_calc_seg_sz(struct ice_flow_prof_params * params,u8 seg)257 static u16 ice_flow_calc_seg_sz(struct ice_flow_prof_params *params, u8 seg)
258 {
259 u16 sz = ICE_FLOW_PROT_HDR_SZ_MAC;
260
261 /* L3 headers */
262 if (params->prof->segs[seg].hdrs & ICE_FLOW_SEG_HDR_IPV4)
263 sz += ICE_FLOW_PROT_HDR_SZ_IPV4;
264 else if (params->prof->segs[seg].hdrs & ICE_FLOW_SEG_HDR_IPV6)
265 sz += ICE_FLOW_PROT_HDR_SZ_IPV6;
266
267 /* L4 headers */
268 if (params->prof->segs[seg].hdrs & ICE_FLOW_SEG_HDR_TCP)
269 sz += ICE_FLOW_PROT_HDR_SZ_TCP;
270 else if (params->prof->segs[seg].hdrs & ICE_FLOW_SEG_HDR_UDP)
271 sz += ICE_FLOW_PROT_HDR_SZ_UDP;
272 else if (params->prof->segs[seg].hdrs & ICE_FLOW_SEG_HDR_SCTP)
273 sz += ICE_FLOW_PROT_HDR_SZ_SCTP;
274
275 return sz;
276 }
277
278 /**
279 * ice_flow_proc_seg_hdrs - process protocol headers present in pkt segments
280 * @params: information about the flow to be processed
281 *
282 * This function identifies the packet types associated with the protocol
283 * headers being present in packet segments of the specified flow profile.
284 */
285 static enum ice_status
ice_flow_proc_seg_hdrs(struct ice_flow_prof_params * params)286 ice_flow_proc_seg_hdrs(struct ice_flow_prof_params *params)
287 {
288 struct ice_flow_prof *prof;
289 u8 i;
290
291 memset(params->ptypes, 0xff, sizeof(params->ptypes));
292
293 prof = params->prof;
294
295 for (i = 0; i < params->prof->segs_cnt; i++) {
296 const unsigned long *src;
297 u32 hdrs;
298
299 hdrs = prof->segs[i].hdrs;
300
301 if ((hdrs & ICE_FLOW_SEG_HDR_IPV4) &&
302 !(hdrs & ICE_FLOW_SEG_HDRS_L4_MASK)) {
303 src = !i ? (const unsigned long *)ice_ipv4_ofos_no_l4 :
304 (const unsigned long *)ice_ipv4_il_no_l4;
305 bitmap_and(params->ptypes, params->ptypes, src,
306 ICE_FLOW_PTYPE_MAX);
307 } else if (hdrs & ICE_FLOW_SEG_HDR_IPV4) {
308 src = !i ? (const unsigned long *)ice_ptypes_ipv4_ofos :
309 (const unsigned long *)ice_ptypes_ipv4_il;
310 bitmap_and(params->ptypes, params->ptypes, src,
311 ICE_FLOW_PTYPE_MAX);
312 } else if ((hdrs & ICE_FLOW_SEG_HDR_IPV6) &&
313 !(hdrs & ICE_FLOW_SEG_HDRS_L4_MASK)) {
314 src = !i ? (const unsigned long *)ice_ipv6_ofos_no_l4 :
315 (const unsigned long *)ice_ipv6_il_no_l4;
316 bitmap_and(params->ptypes, params->ptypes, src,
317 ICE_FLOW_PTYPE_MAX);
318 } else if (hdrs & ICE_FLOW_SEG_HDR_IPV6) {
319 src = !i ? (const unsigned long *)ice_ptypes_ipv6_ofos :
320 (const unsigned long *)ice_ptypes_ipv6_il;
321 bitmap_and(params->ptypes, params->ptypes, src,
322 ICE_FLOW_PTYPE_MAX);
323 }
324
325 if (hdrs & ICE_FLOW_SEG_HDR_UDP) {
326 src = (const unsigned long *)ice_ptypes_udp_il;
327 bitmap_and(params->ptypes, params->ptypes, src,
328 ICE_FLOW_PTYPE_MAX);
329 } else if (hdrs & ICE_FLOW_SEG_HDR_TCP) {
330 bitmap_and(params->ptypes, params->ptypes,
331 (const unsigned long *)ice_ptypes_tcp_il,
332 ICE_FLOW_PTYPE_MAX);
333 } else if (hdrs & ICE_FLOW_SEG_HDR_SCTP) {
334 src = (const unsigned long *)ice_ptypes_sctp_il;
335 bitmap_and(params->ptypes, params->ptypes, src,
336 ICE_FLOW_PTYPE_MAX);
337 } else if (hdrs & ICE_FLOW_SEG_HDR_GRE) {
338 if (!i) {
339 src = (const unsigned long *)ice_ptypes_gre_of;
340 bitmap_and(params->ptypes, params->ptypes,
341 src, ICE_FLOW_PTYPE_MAX);
342 }
343 }
344 }
345
346 return 0;
347 }
348
349 /**
350 * ice_flow_xtract_fld - Create an extraction sequence entry for the given field
351 * @hw: pointer to the HW struct
352 * @params: information about the flow to be processed
353 * @seg: packet segment index of the field to be extracted
354 * @fld: ID of field to be extracted
355 *
356 * This function determines the protocol ID, offset, and size of the given
357 * field. It then allocates one or more extraction sequence entries for the
358 * given field, and fill the entries with protocol ID and offset information.
359 */
360 static enum ice_status
ice_flow_xtract_fld(struct ice_hw * hw,struct ice_flow_prof_params * params,u8 seg,enum ice_flow_field fld)361 ice_flow_xtract_fld(struct ice_hw *hw, struct ice_flow_prof_params *params,
362 u8 seg, enum ice_flow_field fld)
363 {
364 enum ice_prot_id prot_id = ICE_PROT_ID_INVAL;
365 u8 fv_words = hw->blk[params->blk].es.fvw;
366 struct ice_flow_fld_info *flds;
367 u16 cnt, ese_bits, i;
368 u16 off;
369
370 flds = params->prof->segs[seg].fields;
371
372 switch (fld) {
373 case ICE_FLOW_FIELD_IDX_IPV4_SA:
374 case ICE_FLOW_FIELD_IDX_IPV4_DA:
375 prot_id = seg == 0 ? ICE_PROT_IPV4_OF_OR_S : ICE_PROT_IPV4_IL;
376 break;
377 case ICE_FLOW_FIELD_IDX_IPV6_SA:
378 case ICE_FLOW_FIELD_IDX_IPV6_DA:
379 prot_id = seg == 0 ? ICE_PROT_IPV6_OF_OR_S : ICE_PROT_IPV6_IL;
380 break;
381 case ICE_FLOW_FIELD_IDX_TCP_SRC_PORT:
382 case ICE_FLOW_FIELD_IDX_TCP_DST_PORT:
383 prot_id = ICE_PROT_TCP_IL;
384 break;
385 case ICE_FLOW_FIELD_IDX_UDP_SRC_PORT:
386 case ICE_FLOW_FIELD_IDX_UDP_DST_PORT:
387 prot_id = ICE_PROT_UDP_IL_OR_S;
388 break;
389 case ICE_FLOW_FIELD_IDX_SCTP_SRC_PORT:
390 case ICE_FLOW_FIELD_IDX_SCTP_DST_PORT:
391 prot_id = ICE_PROT_SCTP_IL;
392 break;
393 case ICE_FLOW_FIELD_IDX_GRE_KEYID:
394 prot_id = ICE_PROT_GRE_OF;
395 break;
396 default:
397 return ICE_ERR_NOT_IMPL;
398 }
399
400 /* Each extraction sequence entry is a word in size, and extracts a
401 * word-aligned offset from a protocol header.
402 */
403 ese_bits = ICE_FLOW_FV_EXTRACT_SZ * BITS_PER_BYTE;
404
405 flds[fld].xtrct.prot_id = prot_id;
406 flds[fld].xtrct.off = (ice_flds_info[fld].off / ese_bits) *
407 ICE_FLOW_FV_EXTRACT_SZ;
408 flds[fld].xtrct.disp = (u8)(ice_flds_info[fld].off % ese_bits);
409 flds[fld].xtrct.idx = params->es_cnt;
410
411 /* Adjust the next field-entry index after accommodating the number of
412 * entries this field consumes
413 */
414 cnt = DIV_ROUND_UP(flds[fld].xtrct.disp + ice_flds_info[fld].size,
415 ese_bits);
416
417 /* Fill in the extraction sequence entries needed for this field */
418 off = flds[fld].xtrct.off;
419 for (i = 0; i < cnt; i++) {
420 u8 idx;
421
422 /* Make sure the number of extraction sequence required
423 * does not exceed the block's capability
424 */
425 if (params->es_cnt >= fv_words)
426 return ICE_ERR_MAX_LIMIT;
427
428 /* some blocks require a reversed field vector layout */
429 if (hw->blk[params->blk].es.reverse)
430 idx = fv_words - params->es_cnt - 1;
431 else
432 idx = params->es_cnt;
433
434 params->es[idx].prot_id = prot_id;
435 params->es[idx].off = off;
436 params->es_cnt++;
437
438 off += ICE_FLOW_FV_EXTRACT_SZ;
439 }
440
441 return 0;
442 }
443
444 /**
445 * ice_flow_xtract_raws - Create extract sequence entries for raw bytes
446 * @hw: pointer to the HW struct
447 * @params: information about the flow to be processed
448 * @seg: index of packet segment whose raw fields are to be extracted
449 */
450 static enum ice_status
ice_flow_xtract_raws(struct ice_hw * hw,struct ice_flow_prof_params * params,u8 seg)451 ice_flow_xtract_raws(struct ice_hw *hw, struct ice_flow_prof_params *params,
452 u8 seg)
453 {
454 u16 fv_words;
455 u16 hdrs_sz;
456 u8 i;
457
458 if (!params->prof->segs[seg].raws_cnt)
459 return 0;
460
461 if (params->prof->segs[seg].raws_cnt >
462 ARRAY_SIZE(params->prof->segs[seg].raws))
463 return ICE_ERR_MAX_LIMIT;
464
465 /* Offsets within the segment headers are not supported */
466 hdrs_sz = ice_flow_calc_seg_sz(params, seg);
467 if (!hdrs_sz)
468 return ICE_ERR_PARAM;
469
470 fv_words = hw->blk[params->blk].es.fvw;
471
472 for (i = 0; i < params->prof->segs[seg].raws_cnt; i++) {
473 struct ice_flow_seg_fld_raw *raw;
474 u16 off, cnt, j;
475
476 raw = ¶ms->prof->segs[seg].raws[i];
477
478 /* Storing extraction information */
479 raw->info.xtrct.prot_id = ICE_PROT_MAC_OF_OR_S;
480 raw->info.xtrct.off = (raw->off / ICE_FLOW_FV_EXTRACT_SZ) *
481 ICE_FLOW_FV_EXTRACT_SZ;
482 raw->info.xtrct.disp = (raw->off % ICE_FLOW_FV_EXTRACT_SZ) *
483 BITS_PER_BYTE;
484 raw->info.xtrct.idx = params->es_cnt;
485
486 /* Determine the number of field vector entries this raw field
487 * consumes.
488 */
489 cnt = DIV_ROUND_UP(raw->info.xtrct.disp +
490 (raw->info.src.last * BITS_PER_BYTE),
491 (ICE_FLOW_FV_EXTRACT_SZ * BITS_PER_BYTE));
492 off = raw->info.xtrct.off;
493 for (j = 0; j < cnt; j++) {
494 u16 idx;
495
496 /* Make sure the number of extraction sequence required
497 * does not exceed the block's capability
498 */
499 if (params->es_cnt >= hw->blk[params->blk].es.count ||
500 params->es_cnt >= ICE_MAX_FV_WORDS)
501 return ICE_ERR_MAX_LIMIT;
502
503 /* some blocks require a reversed field vector layout */
504 if (hw->blk[params->blk].es.reverse)
505 idx = fv_words - params->es_cnt - 1;
506 else
507 idx = params->es_cnt;
508
509 params->es[idx].prot_id = raw->info.xtrct.prot_id;
510 params->es[idx].off = off;
511 params->es_cnt++;
512 off += ICE_FLOW_FV_EXTRACT_SZ;
513 }
514 }
515
516 return 0;
517 }
518
519 /**
520 * ice_flow_create_xtrct_seq - Create an extraction sequence for given segments
521 * @hw: pointer to the HW struct
522 * @params: information about the flow to be processed
523 *
524 * This function iterates through all matched fields in the given segments, and
525 * creates an extraction sequence for the fields.
526 */
527 static enum ice_status
ice_flow_create_xtrct_seq(struct ice_hw * hw,struct ice_flow_prof_params * params)528 ice_flow_create_xtrct_seq(struct ice_hw *hw,
529 struct ice_flow_prof_params *params)
530 {
531 struct ice_flow_prof *prof = params->prof;
532 enum ice_status status = 0;
533 u8 i;
534
535 for (i = 0; i < prof->segs_cnt; i++) {
536 u8 j;
537
538 for_each_set_bit(j, (unsigned long *)&prof->segs[i].match,
539 ICE_FLOW_FIELD_IDX_MAX) {
540 status = ice_flow_xtract_fld(hw, params, i,
541 (enum ice_flow_field)j);
542 if (status)
543 return status;
544 }
545
546 /* Process raw matching bytes */
547 status = ice_flow_xtract_raws(hw, params, i);
548 if (status)
549 return status;
550 }
551
552 return status;
553 }
554
555 /**
556 * ice_flow_proc_segs - process all packet segments associated with a profile
557 * @hw: pointer to the HW struct
558 * @params: information about the flow to be processed
559 */
560 static enum ice_status
ice_flow_proc_segs(struct ice_hw * hw,struct ice_flow_prof_params * params)561 ice_flow_proc_segs(struct ice_hw *hw, struct ice_flow_prof_params *params)
562 {
563 enum ice_status status;
564
565 status = ice_flow_proc_seg_hdrs(params);
566 if (status)
567 return status;
568
569 status = ice_flow_create_xtrct_seq(hw, params);
570 if (status)
571 return status;
572
573 switch (params->blk) {
574 case ICE_BLK_FD:
575 case ICE_BLK_RSS:
576 status = 0;
577 break;
578 default:
579 return ICE_ERR_NOT_IMPL;
580 }
581
582 return status;
583 }
584
585 #define ICE_FLOW_FIND_PROF_CHK_FLDS 0x00000001
586 #define ICE_FLOW_FIND_PROF_CHK_VSI 0x00000002
587 #define ICE_FLOW_FIND_PROF_NOT_CHK_DIR 0x00000004
588
589 /**
590 * ice_flow_find_prof_conds - Find a profile matching headers and conditions
591 * @hw: pointer to the HW struct
592 * @blk: classification stage
593 * @dir: flow direction
594 * @segs: array of one or more packet segments that describe the flow
595 * @segs_cnt: number of packet segments provided
596 * @vsi_handle: software VSI handle to check VSI (ICE_FLOW_FIND_PROF_CHK_VSI)
597 * @conds: additional conditions to be checked (ICE_FLOW_FIND_PROF_CHK_*)
598 */
599 static struct ice_flow_prof *
ice_flow_find_prof_conds(struct ice_hw * hw,enum ice_block blk,enum ice_flow_dir dir,struct ice_flow_seg_info * segs,u8 segs_cnt,u16 vsi_handle,u32 conds)600 ice_flow_find_prof_conds(struct ice_hw *hw, enum ice_block blk,
601 enum ice_flow_dir dir, struct ice_flow_seg_info *segs,
602 u8 segs_cnt, u16 vsi_handle, u32 conds)
603 {
604 struct ice_flow_prof *p, *prof = NULL;
605
606 mutex_lock(&hw->fl_profs_locks[blk]);
607 list_for_each_entry(p, &hw->fl_profs[blk], l_entry)
608 if ((p->dir == dir || conds & ICE_FLOW_FIND_PROF_NOT_CHK_DIR) &&
609 segs_cnt && segs_cnt == p->segs_cnt) {
610 u8 i;
611
612 /* Check for profile-VSI association if specified */
613 if ((conds & ICE_FLOW_FIND_PROF_CHK_VSI) &&
614 ice_is_vsi_valid(hw, vsi_handle) &&
615 !test_bit(vsi_handle, p->vsis))
616 continue;
617
618 /* Protocol headers must be checked. Matched fields are
619 * checked if specified.
620 */
621 for (i = 0; i < segs_cnt; i++)
622 if (segs[i].hdrs != p->segs[i].hdrs ||
623 ((conds & ICE_FLOW_FIND_PROF_CHK_FLDS) &&
624 segs[i].match != p->segs[i].match))
625 break;
626
627 /* A match is found if all segments are matched */
628 if (i == segs_cnt) {
629 prof = p;
630 break;
631 }
632 }
633 mutex_unlock(&hw->fl_profs_locks[blk]);
634
635 return prof;
636 }
637
638 /**
639 * ice_flow_find_prof_id - Look up a profile with given profile ID
640 * @hw: pointer to the HW struct
641 * @blk: classification stage
642 * @prof_id: unique ID to identify this flow profile
643 */
644 static struct ice_flow_prof *
ice_flow_find_prof_id(struct ice_hw * hw,enum ice_block blk,u64 prof_id)645 ice_flow_find_prof_id(struct ice_hw *hw, enum ice_block blk, u64 prof_id)
646 {
647 struct ice_flow_prof *p;
648
649 list_for_each_entry(p, &hw->fl_profs[blk], l_entry)
650 if (p->id == prof_id)
651 return p;
652
653 return NULL;
654 }
655
656 /**
657 * ice_dealloc_flow_entry - Deallocate flow entry memory
658 * @hw: pointer to the HW struct
659 * @entry: flow entry to be removed
660 */
661 static void
ice_dealloc_flow_entry(struct ice_hw * hw,struct ice_flow_entry * entry)662 ice_dealloc_flow_entry(struct ice_hw *hw, struct ice_flow_entry *entry)
663 {
664 if (!entry)
665 return;
666
667 if (entry->entry)
668 devm_kfree(ice_hw_to_dev(hw), entry->entry);
669
670 devm_kfree(ice_hw_to_dev(hw), entry);
671 }
672
673 /**
674 * ice_flow_rem_entry_sync - Remove a flow entry
675 * @hw: pointer to the HW struct
676 * @blk: classification stage
677 * @entry: flow entry to be removed
678 */
679 static enum ice_status
ice_flow_rem_entry_sync(struct ice_hw * hw,enum ice_block __always_unused blk,struct ice_flow_entry * entry)680 ice_flow_rem_entry_sync(struct ice_hw *hw, enum ice_block __always_unused blk,
681 struct ice_flow_entry *entry)
682 {
683 if (!entry)
684 return ICE_ERR_BAD_PTR;
685
686 list_del(&entry->l_entry);
687
688 ice_dealloc_flow_entry(hw, entry);
689
690 return 0;
691 }
692
693 /**
694 * ice_flow_add_prof_sync - Add a flow profile for packet segments and fields
695 * @hw: pointer to the HW struct
696 * @blk: classification stage
697 * @dir: flow direction
698 * @prof_id: unique ID to identify this flow profile
699 * @segs: array of one or more packet segments that describe the flow
700 * @segs_cnt: number of packet segments provided
701 * @prof: stores the returned flow profile added
702 *
703 * Assumption: the caller has acquired the lock to the profile list
704 */
705 static enum ice_status
ice_flow_add_prof_sync(struct ice_hw * hw,enum ice_block blk,enum ice_flow_dir dir,u64 prof_id,struct ice_flow_seg_info * segs,u8 segs_cnt,struct ice_flow_prof ** prof)706 ice_flow_add_prof_sync(struct ice_hw *hw, enum ice_block blk,
707 enum ice_flow_dir dir, u64 prof_id,
708 struct ice_flow_seg_info *segs, u8 segs_cnt,
709 struct ice_flow_prof **prof)
710 {
711 struct ice_flow_prof_params params;
712 enum ice_status status;
713 u8 i;
714
715 if (!prof)
716 return ICE_ERR_BAD_PTR;
717
718 memset(¶ms, 0, sizeof(params));
719 params.prof = devm_kzalloc(ice_hw_to_dev(hw), sizeof(*params.prof),
720 GFP_KERNEL);
721 if (!params.prof)
722 return ICE_ERR_NO_MEMORY;
723
724 /* initialize extraction sequence to all invalid (0xff) */
725 for (i = 0; i < ICE_MAX_FV_WORDS; i++) {
726 params.es[i].prot_id = ICE_PROT_INVALID;
727 params.es[i].off = ICE_FV_OFFSET_INVAL;
728 }
729
730 params.blk = blk;
731 params.prof->id = prof_id;
732 params.prof->dir = dir;
733 params.prof->segs_cnt = segs_cnt;
734
735 /* Make a copy of the segments that need to be persistent in the flow
736 * profile instance
737 */
738 for (i = 0; i < segs_cnt; i++)
739 memcpy(¶ms.prof->segs[i], &segs[i], sizeof(*segs));
740
741 status = ice_flow_proc_segs(hw, ¶ms);
742 if (status) {
743 ice_debug(hw, ICE_DBG_FLOW,
744 "Error processing a flow's packet segments\n");
745 goto out;
746 }
747
748 /* Add a HW profile for this flow profile */
749 status = ice_add_prof(hw, blk, prof_id, (u8 *)params.ptypes, params.es);
750 if (status) {
751 ice_debug(hw, ICE_DBG_FLOW, "Error adding a HW flow profile\n");
752 goto out;
753 }
754
755 INIT_LIST_HEAD(¶ms.prof->entries);
756 mutex_init(¶ms.prof->entries_lock);
757 *prof = params.prof;
758
759 out:
760 if (status)
761 devm_kfree(ice_hw_to_dev(hw), params.prof);
762
763 return status;
764 }
765
766 /**
767 * ice_flow_rem_prof_sync - remove a flow profile
768 * @hw: pointer to the hardware structure
769 * @blk: classification stage
770 * @prof: pointer to flow profile to remove
771 *
772 * Assumption: the caller has acquired the lock to the profile list
773 */
774 static enum ice_status
ice_flow_rem_prof_sync(struct ice_hw * hw,enum ice_block blk,struct ice_flow_prof * prof)775 ice_flow_rem_prof_sync(struct ice_hw *hw, enum ice_block blk,
776 struct ice_flow_prof *prof)
777 {
778 enum ice_status status;
779
780 /* Remove all remaining flow entries before removing the flow profile */
781 if (!list_empty(&prof->entries)) {
782 struct ice_flow_entry *e, *t;
783
784 mutex_lock(&prof->entries_lock);
785
786 list_for_each_entry_safe(e, t, &prof->entries, l_entry) {
787 status = ice_flow_rem_entry_sync(hw, blk, e);
788 if (status)
789 break;
790 }
791
792 mutex_unlock(&prof->entries_lock);
793 }
794
795 /* Remove all hardware profiles associated with this flow profile */
796 status = ice_rem_prof(hw, blk, prof->id);
797 if (!status) {
798 list_del(&prof->l_entry);
799 mutex_destroy(&prof->entries_lock);
800 devm_kfree(ice_hw_to_dev(hw), prof);
801 }
802
803 return status;
804 }
805
806 /**
807 * ice_flow_assoc_prof - associate a VSI with a flow profile
808 * @hw: pointer to the hardware structure
809 * @blk: classification stage
810 * @prof: pointer to flow profile
811 * @vsi_handle: software VSI handle
812 *
813 * Assumption: the caller has acquired the lock to the profile list
814 * and the software VSI handle has been validated
815 */
816 static enum ice_status
ice_flow_assoc_prof(struct ice_hw * hw,enum ice_block blk,struct ice_flow_prof * prof,u16 vsi_handle)817 ice_flow_assoc_prof(struct ice_hw *hw, enum ice_block blk,
818 struct ice_flow_prof *prof, u16 vsi_handle)
819 {
820 enum ice_status status = 0;
821
822 if (!test_bit(vsi_handle, prof->vsis)) {
823 status = ice_add_prof_id_flow(hw, blk,
824 ice_get_hw_vsi_num(hw,
825 vsi_handle),
826 prof->id);
827 if (!status)
828 set_bit(vsi_handle, prof->vsis);
829 else
830 ice_debug(hw, ICE_DBG_FLOW,
831 "HW profile add failed, %d\n",
832 status);
833 }
834
835 return status;
836 }
837
838 /**
839 * ice_flow_disassoc_prof - disassociate a VSI from a flow profile
840 * @hw: pointer to the hardware structure
841 * @blk: classification stage
842 * @prof: pointer to flow profile
843 * @vsi_handle: software VSI handle
844 *
845 * Assumption: the caller has acquired the lock to the profile list
846 * and the software VSI handle has been validated
847 */
848 static enum ice_status
ice_flow_disassoc_prof(struct ice_hw * hw,enum ice_block blk,struct ice_flow_prof * prof,u16 vsi_handle)849 ice_flow_disassoc_prof(struct ice_hw *hw, enum ice_block blk,
850 struct ice_flow_prof *prof, u16 vsi_handle)
851 {
852 enum ice_status status = 0;
853
854 if (test_bit(vsi_handle, prof->vsis)) {
855 status = ice_rem_prof_id_flow(hw, blk,
856 ice_get_hw_vsi_num(hw,
857 vsi_handle),
858 prof->id);
859 if (!status)
860 clear_bit(vsi_handle, prof->vsis);
861 else
862 ice_debug(hw, ICE_DBG_FLOW,
863 "HW profile remove failed, %d\n",
864 status);
865 }
866
867 return status;
868 }
869
870 /**
871 * ice_flow_add_prof - Add a flow profile for packet segments and matched fields
872 * @hw: pointer to the HW struct
873 * @blk: classification stage
874 * @dir: flow direction
875 * @prof_id: unique ID to identify this flow profile
876 * @segs: array of one or more packet segments that describe the flow
877 * @segs_cnt: number of packet segments provided
878 * @prof: stores the returned flow profile added
879 */
880 enum ice_status
ice_flow_add_prof(struct ice_hw * hw,enum ice_block blk,enum ice_flow_dir dir,u64 prof_id,struct ice_flow_seg_info * segs,u8 segs_cnt,struct ice_flow_prof ** prof)881 ice_flow_add_prof(struct ice_hw *hw, enum ice_block blk, enum ice_flow_dir dir,
882 u64 prof_id, struct ice_flow_seg_info *segs, u8 segs_cnt,
883 struct ice_flow_prof **prof)
884 {
885 enum ice_status status;
886
887 if (segs_cnt > ICE_FLOW_SEG_MAX)
888 return ICE_ERR_MAX_LIMIT;
889
890 if (!segs_cnt)
891 return ICE_ERR_PARAM;
892
893 if (!segs)
894 return ICE_ERR_BAD_PTR;
895
896 status = ice_flow_val_hdrs(segs, segs_cnt);
897 if (status)
898 return status;
899
900 mutex_lock(&hw->fl_profs_locks[blk]);
901
902 status = ice_flow_add_prof_sync(hw, blk, dir, prof_id, segs, segs_cnt,
903 prof);
904 if (!status)
905 list_add(&(*prof)->l_entry, &hw->fl_profs[blk]);
906
907 mutex_unlock(&hw->fl_profs_locks[blk]);
908
909 return status;
910 }
911
912 /**
913 * ice_flow_rem_prof - Remove a flow profile and all entries associated with it
914 * @hw: pointer to the HW struct
915 * @blk: the block for which the flow profile is to be removed
916 * @prof_id: unique ID of the flow profile to be removed
917 */
918 enum ice_status
ice_flow_rem_prof(struct ice_hw * hw,enum ice_block blk,u64 prof_id)919 ice_flow_rem_prof(struct ice_hw *hw, enum ice_block blk, u64 prof_id)
920 {
921 struct ice_flow_prof *prof;
922 enum ice_status status;
923
924 mutex_lock(&hw->fl_profs_locks[blk]);
925
926 prof = ice_flow_find_prof_id(hw, blk, prof_id);
927 if (!prof) {
928 status = ICE_ERR_DOES_NOT_EXIST;
929 goto out;
930 }
931
932 /* prof becomes invalid after the call */
933 status = ice_flow_rem_prof_sync(hw, blk, prof);
934
935 out:
936 mutex_unlock(&hw->fl_profs_locks[blk]);
937
938 return status;
939 }
940
941 /**
942 * ice_flow_add_entry - Add a flow entry
943 * @hw: pointer to the HW struct
944 * @blk: classification stage
945 * @prof_id: ID of the profile to add a new flow entry to
946 * @entry_id: unique ID to identify this flow entry
947 * @vsi_handle: software VSI handle for the flow entry
948 * @prio: priority of the flow entry
949 * @data: pointer to a data buffer containing flow entry's match values/masks
950 * @entry_h: pointer to buffer that receives the new flow entry's handle
951 */
952 enum ice_status
ice_flow_add_entry(struct ice_hw * hw,enum ice_block blk,u64 prof_id,u64 entry_id,u16 vsi_handle,enum ice_flow_priority prio,void * data,u64 * entry_h)953 ice_flow_add_entry(struct ice_hw *hw, enum ice_block blk, u64 prof_id,
954 u64 entry_id, u16 vsi_handle, enum ice_flow_priority prio,
955 void *data, u64 *entry_h)
956 {
957 struct ice_flow_entry *e = NULL;
958 struct ice_flow_prof *prof;
959 enum ice_status status;
960
961 /* No flow entry data is expected for RSS */
962 if (!entry_h || (!data && blk != ICE_BLK_RSS))
963 return ICE_ERR_BAD_PTR;
964
965 if (!ice_is_vsi_valid(hw, vsi_handle))
966 return ICE_ERR_PARAM;
967
968 mutex_lock(&hw->fl_profs_locks[blk]);
969
970 prof = ice_flow_find_prof_id(hw, blk, prof_id);
971 if (!prof) {
972 status = ICE_ERR_DOES_NOT_EXIST;
973 } else {
974 /* Allocate memory for the entry being added and associate
975 * the VSI to the found flow profile
976 */
977 e = devm_kzalloc(ice_hw_to_dev(hw), sizeof(*e), GFP_KERNEL);
978 if (!e)
979 status = ICE_ERR_NO_MEMORY;
980 else
981 status = ice_flow_assoc_prof(hw, blk, prof, vsi_handle);
982 }
983
984 mutex_unlock(&hw->fl_profs_locks[blk]);
985 if (status)
986 goto out;
987
988 e->id = entry_id;
989 e->vsi_handle = vsi_handle;
990 e->prof = prof;
991 e->priority = prio;
992
993 switch (blk) {
994 case ICE_BLK_FD:
995 case ICE_BLK_RSS:
996 break;
997 default:
998 status = ICE_ERR_NOT_IMPL;
999 goto out;
1000 }
1001
1002 mutex_lock(&prof->entries_lock);
1003 list_add(&e->l_entry, &prof->entries);
1004 mutex_unlock(&prof->entries_lock);
1005
1006 *entry_h = ICE_FLOW_ENTRY_HNDL(e);
1007
1008 out:
1009 if (status && e) {
1010 if (e->entry)
1011 devm_kfree(ice_hw_to_dev(hw), e->entry);
1012 devm_kfree(ice_hw_to_dev(hw), e);
1013 }
1014
1015 return status;
1016 }
1017
1018 /**
1019 * ice_flow_rem_entry - Remove a flow entry
1020 * @hw: pointer to the HW struct
1021 * @blk: classification stage
1022 * @entry_h: handle to the flow entry to be removed
1023 */
ice_flow_rem_entry(struct ice_hw * hw,enum ice_block blk,u64 entry_h)1024 enum ice_status ice_flow_rem_entry(struct ice_hw *hw, enum ice_block blk,
1025 u64 entry_h)
1026 {
1027 struct ice_flow_entry *entry;
1028 struct ice_flow_prof *prof;
1029 enum ice_status status = 0;
1030
1031 if (entry_h == ICE_FLOW_ENTRY_HANDLE_INVAL)
1032 return ICE_ERR_PARAM;
1033
1034 entry = ICE_FLOW_ENTRY_PTR(entry_h);
1035
1036 /* Retain the pointer to the flow profile as the entry will be freed */
1037 prof = entry->prof;
1038
1039 if (prof) {
1040 mutex_lock(&prof->entries_lock);
1041 status = ice_flow_rem_entry_sync(hw, blk, entry);
1042 mutex_unlock(&prof->entries_lock);
1043 }
1044
1045 return status;
1046 }
1047
1048 /**
1049 * ice_flow_set_fld_ext - specifies locations of field from entry's input buffer
1050 * @seg: packet segment the field being set belongs to
1051 * @fld: field to be set
1052 * @field_type: type of the field
1053 * @val_loc: if not ICE_FLOW_FLD_OFF_INVAL, location of the value to match from
1054 * entry's input buffer
1055 * @mask_loc: if not ICE_FLOW_FLD_OFF_INVAL, location of mask value from entry's
1056 * input buffer
1057 * @last_loc: if not ICE_FLOW_FLD_OFF_INVAL, location of last/upper value from
1058 * entry's input buffer
1059 *
1060 * This helper function stores information of a field being matched, including
1061 * the type of the field and the locations of the value to match, the mask, and
1062 * the upper-bound value in the start of the input buffer for a flow entry.
1063 * This function should only be used for fixed-size data structures.
1064 *
1065 * This function also opportunistically determines the protocol headers to be
1066 * present based on the fields being set. Some fields cannot be used alone to
1067 * determine the protocol headers present. Sometimes, fields for particular
1068 * protocol headers are not matched. In those cases, the protocol headers
1069 * must be explicitly set.
1070 */
1071 static void
ice_flow_set_fld_ext(struct ice_flow_seg_info * seg,enum ice_flow_field fld,enum ice_flow_fld_match_type field_type,u16 val_loc,u16 mask_loc,u16 last_loc)1072 ice_flow_set_fld_ext(struct ice_flow_seg_info *seg, enum ice_flow_field fld,
1073 enum ice_flow_fld_match_type field_type, u16 val_loc,
1074 u16 mask_loc, u16 last_loc)
1075 {
1076 u64 bit = BIT_ULL(fld);
1077
1078 seg->match |= bit;
1079 if (field_type == ICE_FLOW_FLD_TYPE_RANGE)
1080 seg->range |= bit;
1081
1082 seg->fields[fld].type = field_type;
1083 seg->fields[fld].src.val = val_loc;
1084 seg->fields[fld].src.mask = mask_loc;
1085 seg->fields[fld].src.last = last_loc;
1086
1087 ICE_FLOW_SET_HDRS(seg, ice_flds_info[fld].hdr);
1088 }
1089
1090 /**
1091 * ice_flow_set_fld - specifies locations of field from entry's input buffer
1092 * @seg: packet segment the field being set belongs to
1093 * @fld: field to be set
1094 * @val_loc: if not ICE_FLOW_FLD_OFF_INVAL, location of the value to match from
1095 * entry's input buffer
1096 * @mask_loc: if not ICE_FLOW_FLD_OFF_INVAL, location of mask value from entry's
1097 * input buffer
1098 * @last_loc: if not ICE_FLOW_FLD_OFF_INVAL, location of last/upper value from
1099 * entry's input buffer
1100 * @range: indicate if field being matched is to be in a range
1101 *
1102 * This function specifies the locations, in the form of byte offsets from the
1103 * start of the input buffer for a flow entry, from where the value to match,
1104 * the mask value, and upper value can be extracted. These locations are then
1105 * stored in the flow profile. When adding a flow entry associated with the
1106 * flow profile, these locations will be used to quickly extract the values and
1107 * create the content of a match entry. This function should only be used for
1108 * fixed-size data structures.
1109 */
1110 void
ice_flow_set_fld(struct ice_flow_seg_info * seg,enum ice_flow_field fld,u16 val_loc,u16 mask_loc,u16 last_loc,bool range)1111 ice_flow_set_fld(struct ice_flow_seg_info *seg, enum ice_flow_field fld,
1112 u16 val_loc, u16 mask_loc, u16 last_loc, bool range)
1113 {
1114 enum ice_flow_fld_match_type t = range ?
1115 ICE_FLOW_FLD_TYPE_RANGE : ICE_FLOW_FLD_TYPE_REG;
1116
1117 ice_flow_set_fld_ext(seg, fld, t, val_loc, mask_loc, last_loc);
1118 }
1119
1120 /**
1121 * ice_flow_add_fld_raw - sets locations of a raw field from entry's input buf
1122 * @seg: packet segment the field being set belongs to
1123 * @off: offset of the raw field from the beginning of the segment in bytes
1124 * @len: length of the raw pattern to be matched
1125 * @val_loc: location of the value to match from entry's input buffer
1126 * @mask_loc: location of mask value from entry's input buffer
1127 *
1128 * This function specifies the offset of the raw field to be match from the
1129 * beginning of the specified packet segment, and the locations, in the form of
1130 * byte offsets from the start of the input buffer for a flow entry, from where
1131 * the value to match and the mask value to be extracted. These locations are
1132 * then stored in the flow profile. When adding flow entries to the associated
1133 * flow profile, these locations can be used to quickly extract the values to
1134 * create the content of a match entry. This function should only be used for
1135 * fixed-size data structures.
1136 */
1137 void
ice_flow_add_fld_raw(struct ice_flow_seg_info * seg,u16 off,u8 len,u16 val_loc,u16 mask_loc)1138 ice_flow_add_fld_raw(struct ice_flow_seg_info *seg, u16 off, u8 len,
1139 u16 val_loc, u16 mask_loc)
1140 {
1141 if (seg->raws_cnt < ICE_FLOW_SEG_RAW_FLD_MAX) {
1142 seg->raws[seg->raws_cnt].off = off;
1143 seg->raws[seg->raws_cnt].info.type = ICE_FLOW_FLD_TYPE_SIZE;
1144 seg->raws[seg->raws_cnt].info.src.val = val_loc;
1145 seg->raws[seg->raws_cnt].info.src.mask = mask_loc;
1146 /* The "last" field is used to store the length of the field */
1147 seg->raws[seg->raws_cnt].info.src.last = len;
1148 }
1149
1150 /* Overflows of "raws" will be handled as an error condition later in
1151 * the flow when this information is processed.
1152 */
1153 seg->raws_cnt++;
1154 }
1155
1156 #define ICE_FLOW_RSS_SEG_HDR_L3_MASKS \
1157 (ICE_FLOW_SEG_HDR_IPV4 | ICE_FLOW_SEG_HDR_IPV6)
1158
1159 #define ICE_FLOW_RSS_SEG_HDR_L4_MASKS \
1160 (ICE_FLOW_SEG_HDR_TCP | ICE_FLOW_SEG_HDR_UDP | ICE_FLOW_SEG_HDR_SCTP)
1161
1162 #define ICE_FLOW_RSS_SEG_HDR_VAL_MASKS \
1163 (ICE_FLOW_RSS_SEG_HDR_L3_MASKS | \
1164 ICE_FLOW_RSS_SEG_HDR_L4_MASKS)
1165
1166 /**
1167 * ice_flow_set_rss_seg_info - setup packet segments for RSS
1168 * @segs: pointer to the flow field segment(s)
1169 * @hash_fields: fields to be hashed on for the segment(s)
1170 * @flow_hdr: protocol header fields within a packet segment
1171 *
1172 * Helper function to extract fields from hash bitmap and use flow
1173 * header value to set flow field segment for further use in flow
1174 * profile entry or removal.
1175 */
1176 static enum ice_status
ice_flow_set_rss_seg_info(struct ice_flow_seg_info * segs,u64 hash_fields,u32 flow_hdr)1177 ice_flow_set_rss_seg_info(struct ice_flow_seg_info *segs, u64 hash_fields,
1178 u32 flow_hdr)
1179 {
1180 u64 val;
1181 u8 i;
1182
1183 for_each_set_bit(i, (unsigned long *)&hash_fields,
1184 ICE_FLOW_FIELD_IDX_MAX)
1185 ice_flow_set_fld(segs, (enum ice_flow_field)i,
1186 ICE_FLOW_FLD_OFF_INVAL, ICE_FLOW_FLD_OFF_INVAL,
1187 ICE_FLOW_FLD_OFF_INVAL, false);
1188
1189 ICE_FLOW_SET_HDRS(segs, flow_hdr);
1190
1191 if (segs->hdrs & ~ICE_FLOW_RSS_SEG_HDR_VAL_MASKS)
1192 return ICE_ERR_PARAM;
1193
1194 val = (u64)(segs->hdrs & ICE_FLOW_RSS_SEG_HDR_L3_MASKS);
1195 if (val && !is_power_of_2(val))
1196 return ICE_ERR_CFG;
1197
1198 val = (u64)(segs->hdrs & ICE_FLOW_RSS_SEG_HDR_L4_MASKS);
1199 if (val && !is_power_of_2(val))
1200 return ICE_ERR_CFG;
1201
1202 return 0;
1203 }
1204
1205 /**
1206 * ice_rem_vsi_rss_list - remove VSI from RSS list
1207 * @hw: pointer to the hardware structure
1208 * @vsi_handle: software VSI handle
1209 *
1210 * Remove the VSI from all RSS configurations in the list.
1211 */
ice_rem_vsi_rss_list(struct ice_hw * hw,u16 vsi_handle)1212 void ice_rem_vsi_rss_list(struct ice_hw *hw, u16 vsi_handle)
1213 {
1214 struct ice_rss_cfg *r, *tmp;
1215
1216 if (list_empty(&hw->rss_list_head))
1217 return;
1218
1219 mutex_lock(&hw->rss_locks);
1220 list_for_each_entry_safe(r, tmp, &hw->rss_list_head, l_entry)
1221 if (test_and_clear_bit(vsi_handle, r->vsis))
1222 if (bitmap_empty(r->vsis, ICE_MAX_VSI)) {
1223 list_del(&r->l_entry);
1224 devm_kfree(ice_hw_to_dev(hw), r);
1225 }
1226 mutex_unlock(&hw->rss_locks);
1227 }
1228
1229 /**
1230 * ice_rem_vsi_rss_cfg - remove RSS configurations associated with VSI
1231 * @hw: pointer to the hardware structure
1232 * @vsi_handle: software VSI handle
1233 *
1234 * This function will iterate through all flow profiles and disassociate
1235 * the VSI from that profile. If the flow profile has no VSIs it will
1236 * be removed.
1237 */
ice_rem_vsi_rss_cfg(struct ice_hw * hw,u16 vsi_handle)1238 enum ice_status ice_rem_vsi_rss_cfg(struct ice_hw *hw, u16 vsi_handle)
1239 {
1240 const enum ice_block blk = ICE_BLK_RSS;
1241 struct ice_flow_prof *p, *t;
1242 enum ice_status status = 0;
1243
1244 if (!ice_is_vsi_valid(hw, vsi_handle))
1245 return ICE_ERR_PARAM;
1246
1247 if (list_empty(&hw->fl_profs[blk]))
1248 return 0;
1249
1250 mutex_lock(&hw->rss_locks);
1251 list_for_each_entry_safe(p, t, &hw->fl_profs[blk], l_entry)
1252 if (test_bit(vsi_handle, p->vsis)) {
1253 status = ice_flow_disassoc_prof(hw, blk, p, vsi_handle);
1254 if (status)
1255 break;
1256
1257 if (bitmap_empty(p->vsis, ICE_MAX_VSI)) {
1258 status = ice_flow_rem_prof(hw, blk, p->id);
1259 if (status)
1260 break;
1261 }
1262 }
1263 mutex_unlock(&hw->rss_locks);
1264
1265 return status;
1266 }
1267
1268 /**
1269 * ice_rem_rss_list - remove RSS configuration from list
1270 * @hw: pointer to the hardware structure
1271 * @vsi_handle: software VSI handle
1272 * @prof: pointer to flow profile
1273 *
1274 * Assumption: lock has already been acquired for RSS list
1275 */
1276 static void
ice_rem_rss_list(struct ice_hw * hw,u16 vsi_handle,struct ice_flow_prof * prof)1277 ice_rem_rss_list(struct ice_hw *hw, u16 vsi_handle, struct ice_flow_prof *prof)
1278 {
1279 struct ice_rss_cfg *r, *tmp;
1280
1281 /* Search for RSS hash fields associated to the VSI that match the
1282 * hash configurations associated to the flow profile. If found
1283 * remove from the RSS entry list of the VSI context and delete entry.
1284 */
1285 list_for_each_entry_safe(r, tmp, &hw->rss_list_head, l_entry)
1286 if (r->hashed_flds == prof->segs[prof->segs_cnt - 1].match &&
1287 r->packet_hdr == prof->segs[prof->segs_cnt - 1].hdrs) {
1288 clear_bit(vsi_handle, r->vsis);
1289 if (bitmap_empty(r->vsis, ICE_MAX_VSI)) {
1290 list_del(&r->l_entry);
1291 devm_kfree(ice_hw_to_dev(hw), r);
1292 }
1293 return;
1294 }
1295 }
1296
1297 /**
1298 * ice_add_rss_list - add RSS configuration to list
1299 * @hw: pointer to the hardware structure
1300 * @vsi_handle: software VSI handle
1301 * @prof: pointer to flow profile
1302 *
1303 * Assumption: lock has already been acquired for RSS list
1304 */
1305 static enum ice_status
ice_add_rss_list(struct ice_hw * hw,u16 vsi_handle,struct ice_flow_prof * prof)1306 ice_add_rss_list(struct ice_hw *hw, u16 vsi_handle, struct ice_flow_prof *prof)
1307 {
1308 struct ice_rss_cfg *r, *rss_cfg;
1309
1310 list_for_each_entry(r, &hw->rss_list_head, l_entry)
1311 if (r->hashed_flds == prof->segs[prof->segs_cnt - 1].match &&
1312 r->packet_hdr == prof->segs[prof->segs_cnt - 1].hdrs) {
1313 set_bit(vsi_handle, r->vsis);
1314 return 0;
1315 }
1316
1317 rss_cfg = devm_kzalloc(ice_hw_to_dev(hw), sizeof(*rss_cfg),
1318 GFP_KERNEL);
1319 if (!rss_cfg)
1320 return ICE_ERR_NO_MEMORY;
1321
1322 rss_cfg->hashed_flds = prof->segs[prof->segs_cnt - 1].match;
1323 rss_cfg->packet_hdr = prof->segs[prof->segs_cnt - 1].hdrs;
1324 set_bit(vsi_handle, rss_cfg->vsis);
1325
1326 list_add_tail(&rss_cfg->l_entry, &hw->rss_list_head);
1327
1328 return 0;
1329 }
1330
1331 #define ICE_FLOW_PROF_HASH_S 0
1332 #define ICE_FLOW_PROF_HASH_M (0xFFFFFFFFULL << ICE_FLOW_PROF_HASH_S)
1333 #define ICE_FLOW_PROF_HDR_S 32
1334 #define ICE_FLOW_PROF_HDR_M (0x3FFFFFFFULL << ICE_FLOW_PROF_HDR_S)
1335 #define ICE_FLOW_PROF_ENCAP_S 63
1336 #define ICE_FLOW_PROF_ENCAP_M (BIT_ULL(ICE_FLOW_PROF_ENCAP_S))
1337
1338 #define ICE_RSS_OUTER_HEADERS 1
1339 #define ICE_RSS_INNER_HEADERS 2
1340
1341 /* Flow profile ID format:
1342 * [0:31] - Packet match fields
1343 * [32:62] - Protocol header
1344 * [63] - Encapsulation flag, 0 if non-tunneled, 1 if tunneled
1345 */
1346 #define ICE_FLOW_GEN_PROFID(hash, hdr, segs_cnt) \
1347 (u64)(((u64)(hash) & ICE_FLOW_PROF_HASH_M) | \
1348 (((u64)(hdr) << ICE_FLOW_PROF_HDR_S) & ICE_FLOW_PROF_HDR_M) | \
1349 ((u8)((segs_cnt) - 1) ? ICE_FLOW_PROF_ENCAP_M : 0))
1350
1351 /**
1352 * ice_add_rss_cfg_sync - add an RSS configuration
1353 * @hw: pointer to the hardware structure
1354 * @vsi_handle: software VSI handle
1355 * @hashed_flds: hash bit fields (ICE_FLOW_HASH_*) to configure
1356 * @addl_hdrs: protocol header fields
1357 * @segs_cnt: packet segment count
1358 *
1359 * Assumption: lock has already been acquired for RSS list
1360 */
1361 static enum ice_status
ice_add_rss_cfg_sync(struct ice_hw * hw,u16 vsi_handle,u64 hashed_flds,u32 addl_hdrs,u8 segs_cnt)1362 ice_add_rss_cfg_sync(struct ice_hw *hw, u16 vsi_handle, u64 hashed_flds,
1363 u32 addl_hdrs, u8 segs_cnt)
1364 {
1365 const enum ice_block blk = ICE_BLK_RSS;
1366 struct ice_flow_prof *prof = NULL;
1367 struct ice_flow_seg_info *segs;
1368 enum ice_status status;
1369
1370 if (!segs_cnt || segs_cnt > ICE_FLOW_SEG_MAX)
1371 return ICE_ERR_PARAM;
1372
1373 segs = kcalloc(segs_cnt, sizeof(*segs), GFP_KERNEL);
1374 if (!segs)
1375 return ICE_ERR_NO_MEMORY;
1376
1377 /* Construct the packet segment info from the hashed fields */
1378 status = ice_flow_set_rss_seg_info(&segs[segs_cnt - 1], hashed_flds,
1379 addl_hdrs);
1380 if (status)
1381 goto exit;
1382
1383 /* Search for a flow profile that has matching headers, hash fields
1384 * and has the input VSI associated to it. If found, no further
1385 * operations required and exit.
1386 */
1387 prof = ice_flow_find_prof_conds(hw, blk, ICE_FLOW_RX, segs, segs_cnt,
1388 vsi_handle,
1389 ICE_FLOW_FIND_PROF_CHK_FLDS |
1390 ICE_FLOW_FIND_PROF_CHK_VSI);
1391 if (prof)
1392 goto exit;
1393
1394 /* Check if a flow profile exists with the same protocol headers and
1395 * associated with the input VSI. If so disassociate the VSI from
1396 * this profile. The VSI will be added to a new profile created with
1397 * the protocol header and new hash field configuration.
1398 */
1399 prof = ice_flow_find_prof_conds(hw, blk, ICE_FLOW_RX, segs, segs_cnt,
1400 vsi_handle, ICE_FLOW_FIND_PROF_CHK_VSI);
1401 if (prof) {
1402 status = ice_flow_disassoc_prof(hw, blk, prof, vsi_handle);
1403 if (!status)
1404 ice_rem_rss_list(hw, vsi_handle, prof);
1405 else
1406 goto exit;
1407
1408 /* Remove profile if it has no VSIs associated */
1409 if (bitmap_empty(prof->vsis, ICE_MAX_VSI)) {
1410 status = ice_flow_rem_prof(hw, blk, prof->id);
1411 if (status)
1412 goto exit;
1413 }
1414 }
1415
1416 /* Search for a profile that has same match fields only. If this
1417 * exists then associate the VSI to this profile.
1418 */
1419 prof = ice_flow_find_prof_conds(hw, blk, ICE_FLOW_RX, segs, segs_cnt,
1420 vsi_handle,
1421 ICE_FLOW_FIND_PROF_CHK_FLDS);
1422 if (prof) {
1423 status = ice_flow_assoc_prof(hw, blk, prof, vsi_handle);
1424 if (!status)
1425 status = ice_add_rss_list(hw, vsi_handle, prof);
1426 goto exit;
1427 }
1428
1429 /* Create a new flow profile with generated profile and packet
1430 * segment information.
1431 */
1432 status = ice_flow_add_prof(hw, blk, ICE_FLOW_RX,
1433 ICE_FLOW_GEN_PROFID(hashed_flds,
1434 segs[segs_cnt - 1].hdrs,
1435 segs_cnt),
1436 segs, segs_cnt, &prof);
1437 if (status)
1438 goto exit;
1439
1440 status = ice_flow_assoc_prof(hw, blk, prof, vsi_handle);
1441 /* If association to a new flow profile failed then this profile can
1442 * be removed.
1443 */
1444 if (status) {
1445 ice_flow_rem_prof(hw, blk, prof->id);
1446 goto exit;
1447 }
1448
1449 status = ice_add_rss_list(hw, vsi_handle, prof);
1450
1451 exit:
1452 kfree(segs);
1453 return status;
1454 }
1455
1456 /**
1457 * ice_add_rss_cfg - add an RSS configuration with specified hashed fields
1458 * @hw: pointer to the hardware structure
1459 * @vsi_handle: software VSI handle
1460 * @hashed_flds: hash bit fields (ICE_FLOW_HASH_*) to configure
1461 * @addl_hdrs: protocol header fields
1462 *
1463 * This function will generate a flow profile based on fields associated with
1464 * the input fields to hash on, the flow type and use the VSI number to add
1465 * a flow entry to the profile.
1466 */
1467 enum ice_status
ice_add_rss_cfg(struct ice_hw * hw,u16 vsi_handle,u64 hashed_flds,u32 addl_hdrs)1468 ice_add_rss_cfg(struct ice_hw *hw, u16 vsi_handle, u64 hashed_flds,
1469 u32 addl_hdrs)
1470 {
1471 enum ice_status status;
1472
1473 if (hashed_flds == ICE_HASH_INVALID ||
1474 !ice_is_vsi_valid(hw, vsi_handle))
1475 return ICE_ERR_PARAM;
1476
1477 mutex_lock(&hw->rss_locks);
1478 status = ice_add_rss_cfg_sync(hw, vsi_handle, hashed_flds, addl_hdrs,
1479 ICE_RSS_OUTER_HEADERS);
1480 if (!status)
1481 status = ice_add_rss_cfg_sync(hw, vsi_handle, hashed_flds,
1482 addl_hdrs, ICE_RSS_INNER_HEADERS);
1483 mutex_unlock(&hw->rss_locks);
1484
1485 return status;
1486 }
1487
1488 /* Mapping of AVF hash bit fields to an L3-L4 hash combination.
1489 * As the ice_flow_avf_hdr_field represent individual bit shifts in a hash,
1490 * convert its values to their appropriate flow L3, L4 values.
1491 */
1492 #define ICE_FLOW_AVF_RSS_IPV4_MASKS \
1493 (BIT_ULL(ICE_AVF_FLOW_FIELD_IPV4_OTHER) | \
1494 BIT_ULL(ICE_AVF_FLOW_FIELD_FRAG_IPV4))
1495 #define ICE_FLOW_AVF_RSS_TCP_IPV4_MASKS \
1496 (BIT_ULL(ICE_AVF_FLOW_FIELD_IPV4_TCP_SYN_NO_ACK) | \
1497 BIT_ULL(ICE_AVF_FLOW_FIELD_IPV4_TCP))
1498 #define ICE_FLOW_AVF_RSS_UDP_IPV4_MASKS \
1499 (BIT_ULL(ICE_AVF_FLOW_FIELD_UNICAST_IPV4_UDP) | \
1500 BIT_ULL(ICE_AVF_FLOW_FIELD_MULTICAST_IPV4_UDP) | \
1501 BIT_ULL(ICE_AVF_FLOW_FIELD_IPV4_UDP))
1502 #define ICE_FLOW_AVF_RSS_ALL_IPV4_MASKS \
1503 (ICE_FLOW_AVF_RSS_TCP_IPV4_MASKS | ICE_FLOW_AVF_RSS_UDP_IPV4_MASKS | \
1504 ICE_FLOW_AVF_RSS_IPV4_MASKS | BIT_ULL(ICE_AVF_FLOW_FIELD_IPV4_SCTP))
1505
1506 #define ICE_FLOW_AVF_RSS_IPV6_MASKS \
1507 (BIT_ULL(ICE_AVF_FLOW_FIELD_IPV6_OTHER) | \
1508 BIT_ULL(ICE_AVF_FLOW_FIELD_FRAG_IPV6))
1509 #define ICE_FLOW_AVF_RSS_UDP_IPV6_MASKS \
1510 (BIT_ULL(ICE_AVF_FLOW_FIELD_UNICAST_IPV6_UDP) | \
1511 BIT_ULL(ICE_AVF_FLOW_FIELD_MULTICAST_IPV6_UDP) | \
1512 BIT_ULL(ICE_AVF_FLOW_FIELD_IPV6_UDP))
1513 #define ICE_FLOW_AVF_RSS_TCP_IPV6_MASKS \
1514 (BIT_ULL(ICE_AVF_FLOW_FIELD_IPV6_TCP_SYN_NO_ACK) | \
1515 BIT_ULL(ICE_AVF_FLOW_FIELD_IPV6_TCP))
1516 #define ICE_FLOW_AVF_RSS_ALL_IPV6_MASKS \
1517 (ICE_FLOW_AVF_RSS_TCP_IPV6_MASKS | ICE_FLOW_AVF_RSS_UDP_IPV6_MASKS | \
1518 ICE_FLOW_AVF_RSS_IPV6_MASKS | BIT_ULL(ICE_AVF_FLOW_FIELD_IPV6_SCTP))
1519
1520 /**
1521 * ice_add_avf_rss_cfg - add an RSS configuration for AVF driver
1522 * @hw: pointer to the hardware structure
1523 * @vsi_handle: software VSI handle
1524 * @avf_hash: hash bit fields (ICE_AVF_FLOW_FIELD_*) to configure
1525 *
1526 * This function will take the hash bitmap provided by the AVF driver via a
1527 * message, convert it to ICE-compatible values, and configure RSS flow
1528 * profiles.
1529 */
1530 enum ice_status
ice_add_avf_rss_cfg(struct ice_hw * hw,u16 vsi_handle,u64 avf_hash)1531 ice_add_avf_rss_cfg(struct ice_hw *hw, u16 vsi_handle, u64 avf_hash)
1532 {
1533 enum ice_status status = 0;
1534 u64 hash_flds;
1535
1536 if (avf_hash == ICE_AVF_FLOW_FIELD_INVALID ||
1537 !ice_is_vsi_valid(hw, vsi_handle))
1538 return ICE_ERR_PARAM;
1539
1540 /* Make sure no unsupported bits are specified */
1541 if (avf_hash & ~(ICE_FLOW_AVF_RSS_ALL_IPV4_MASKS |
1542 ICE_FLOW_AVF_RSS_ALL_IPV6_MASKS))
1543 return ICE_ERR_CFG;
1544
1545 hash_flds = avf_hash;
1546
1547 /* Always create an L3 RSS configuration for any L4 RSS configuration */
1548 if (hash_flds & ICE_FLOW_AVF_RSS_ALL_IPV4_MASKS)
1549 hash_flds |= ICE_FLOW_AVF_RSS_IPV4_MASKS;
1550
1551 if (hash_flds & ICE_FLOW_AVF_RSS_ALL_IPV6_MASKS)
1552 hash_flds |= ICE_FLOW_AVF_RSS_IPV6_MASKS;
1553
1554 /* Create the corresponding RSS configuration for each valid hash bit */
1555 while (hash_flds) {
1556 u64 rss_hash = ICE_HASH_INVALID;
1557
1558 if (hash_flds & ICE_FLOW_AVF_RSS_ALL_IPV4_MASKS) {
1559 if (hash_flds & ICE_FLOW_AVF_RSS_IPV4_MASKS) {
1560 rss_hash = ICE_FLOW_HASH_IPV4;
1561 hash_flds &= ~ICE_FLOW_AVF_RSS_IPV4_MASKS;
1562 } else if (hash_flds &
1563 ICE_FLOW_AVF_RSS_TCP_IPV4_MASKS) {
1564 rss_hash = ICE_FLOW_HASH_IPV4 |
1565 ICE_FLOW_HASH_TCP_PORT;
1566 hash_flds &= ~ICE_FLOW_AVF_RSS_TCP_IPV4_MASKS;
1567 } else if (hash_flds &
1568 ICE_FLOW_AVF_RSS_UDP_IPV4_MASKS) {
1569 rss_hash = ICE_FLOW_HASH_IPV4 |
1570 ICE_FLOW_HASH_UDP_PORT;
1571 hash_flds &= ~ICE_FLOW_AVF_RSS_UDP_IPV4_MASKS;
1572 } else if (hash_flds &
1573 BIT_ULL(ICE_AVF_FLOW_FIELD_IPV4_SCTP)) {
1574 rss_hash = ICE_FLOW_HASH_IPV4 |
1575 ICE_FLOW_HASH_SCTP_PORT;
1576 hash_flds &=
1577 ~BIT_ULL(ICE_AVF_FLOW_FIELD_IPV4_SCTP);
1578 }
1579 } else if (hash_flds & ICE_FLOW_AVF_RSS_ALL_IPV6_MASKS) {
1580 if (hash_flds & ICE_FLOW_AVF_RSS_IPV6_MASKS) {
1581 rss_hash = ICE_FLOW_HASH_IPV6;
1582 hash_flds &= ~ICE_FLOW_AVF_RSS_IPV6_MASKS;
1583 } else if (hash_flds &
1584 ICE_FLOW_AVF_RSS_TCP_IPV6_MASKS) {
1585 rss_hash = ICE_FLOW_HASH_IPV6 |
1586 ICE_FLOW_HASH_TCP_PORT;
1587 hash_flds &= ~ICE_FLOW_AVF_RSS_TCP_IPV6_MASKS;
1588 } else if (hash_flds &
1589 ICE_FLOW_AVF_RSS_UDP_IPV6_MASKS) {
1590 rss_hash = ICE_FLOW_HASH_IPV6 |
1591 ICE_FLOW_HASH_UDP_PORT;
1592 hash_flds &= ~ICE_FLOW_AVF_RSS_UDP_IPV6_MASKS;
1593 } else if (hash_flds &
1594 BIT_ULL(ICE_AVF_FLOW_FIELD_IPV6_SCTP)) {
1595 rss_hash = ICE_FLOW_HASH_IPV6 |
1596 ICE_FLOW_HASH_SCTP_PORT;
1597 hash_flds &=
1598 ~BIT_ULL(ICE_AVF_FLOW_FIELD_IPV6_SCTP);
1599 }
1600 }
1601
1602 if (rss_hash == ICE_HASH_INVALID)
1603 return ICE_ERR_OUT_OF_RANGE;
1604
1605 status = ice_add_rss_cfg(hw, vsi_handle, rss_hash,
1606 ICE_FLOW_SEG_HDR_NONE);
1607 if (status)
1608 break;
1609 }
1610
1611 return status;
1612 }
1613
1614 /**
1615 * ice_replay_rss_cfg - replay RSS configurations associated with VSI
1616 * @hw: pointer to the hardware structure
1617 * @vsi_handle: software VSI handle
1618 */
ice_replay_rss_cfg(struct ice_hw * hw,u16 vsi_handle)1619 enum ice_status ice_replay_rss_cfg(struct ice_hw *hw, u16 vsi_handle)
1620 {
1621 enum ice_status status = 0;
1622 struct ice_rss_cfg *r;
1623
1624 if (!ice_is_vsi_valid(hw, vsi_handle))
1625 return ICE_ERR_PARAM;
1626
1627 mutex_lock(&hw->rss_locks);
1628 list_for_each_entry(r, &hw->rss_list_head, l_entry) {
1629 if (test_bit(vsi_handle, r->vsis)) {
1630 status = ice_add_rss_cfg_sync(hw, vsi_handle,
1631 r->hashed_flds,
1632 r->packet_hdr,
1633 ICE_RSS_OUTER_HEADERS);
1634 if (status)
1635 break;
1636 status = ice_add_rss_cfg_sync(hw, vsi_handle,
1637 r->hashed_flds,
1638 r->packet_hdr,
1639 ICE_RSS_INNER_HEADERS);
1640 if (status)
1641 break;
1642 }
1643 }
1644 mutex_unlock(&hw->rss_locks);
1645
1646 return status;
1647 }
1648
1649 /**
1650 * ice_get_rss_cfg - returns hashed fields for the given header types
1651 * @hw: pointer to the hardware structure
1652 * @vsi_handle: software VSI handle
1653 * @hdrs: protocol header type
1654 *
1655 * This function will return the match fields of the first instance of flow
1656 * profile having the given header types and containing input VSI
1657 */
ice_get_rss_cfg(struct ice_hw * hw,u16 vsi_handle,u32 hdrs)1658 u64 ice_get_rss_cfg(struct ice_hw *hw, u16 vsi_handle, u32 hdrs)
1659 {
1660 u64 rss_hash = ICE_HASH_INVALID;
1661 struct ice_rss_cfg *r;
1662
1663 /* verify if the protocol header is non zero and VSI is valid */
1664 if (hdrs == ICE_FLOW_SEG_HDR_NONE || !ice_is_vsi_valid(hw, vsi_handle))
1665 return ICE_HASH_INVALID;
1666
1667 mutex_lock(&hw->rss_locks);
1668 list_for_each_entry(r, &hw->rss_list_head, l_entry)
1669 if (test_bit(vsi_handle, r->vsis) &&
1670 r->packet_hdr == hdrs) {
1671 rss_hash = r->hashed_flds;
1672 break;
1673 }
1674 mutex_unlock(&hw->rss_locks);
1675
1676 return rss_hash;
1677 }
1678