1 // SPDX-License-Identifier: GPL-2.0
2 /* Copyright (c) 2019, Intel Corporation. */
4 #include "ice_common.h"
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 */
14 #define ICE_FLOW_FLD_INFO(_hdr, _offset_bytes, _size_bytes) { \
16 .off = (_offset_bytes) * BITS_PER_BYTE, \
17 .size = (_size_bytes) * BITS_PER_BYTE, \
20 /* Table containing properties of supported protocol header fields */
22 struct ice_flow_field_info ice_flds_info
[ICE_FLOW_FIELD_IDX_MAX
] = {
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
)),
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
)),
48 /* Bitmaps indicating relevant packet types for a particular protocol header
50 * Packet types for packets with an Outer/First/Single IPv4 header
52 static const u32 ice_ptypes_ipv4_ofos
[] = {
53 0x1DC00000, 0x04000800, 0x00000000, 0x00000000,
54 0x00000000, 0x00000000, 0x00000000, 0x00000000,
55 0x00000000, 0x00000000, 0x00000000, 0x00000000,
56 0x00000000, 0x00000000, 0x00000000, 0x00000000,
57 0x00000000, 0x00000000, 0x00000000, 0x00000000,
58 0x00000000, 0x00000000, 0x00000000, 0x00000000,
59 0x00000000, 0x00000000, 0x00000000, 0x00000000,
60 0x00000000, 0x00000000, 0x00000000, 0x00000000,
63 /* Packet types for packets with an Innermost/Last IPv4 header */
64 static const u32 ice_ptypes_ipv4_il
[] = {
65 0xE0000000, 0xB807700E, 0x80000003, 0xE01DC03B,
66 0x0000000E, 0x00000000, 0x00000000, 0x00000000,
67 0x00000000, 0x00000000, 0x00000000, 0x00000000,
68 0x00000000, 0x00000000, 0x00000000, 0x00000000,
69 0x00000000, 0x00000000, 0x00000000, 0x00000000,
70 0x00000000, 0x00000000, 0x00000000, 0x00000000,
71 0x00000000, 0x00000000, 0x00000000, 0x00000000,
72 0x00000000, 0x00000000, 0x00000000, 0x00000000,
75 /* Packet types for packets with an Outer/First/Single IPv6 header */
76 static const u32 ice_ptypes_ipv6_ofos
[] = {
77 0x00000000, 0x00000000, 0x77000000, 0x10002000,
78 0x00000000, 0x00000000, 0x00000000, 0x00000000,
79 0x00000000, 0x00000000, 0x00000000, 0x00000000,
80 0x00000000, 0x00000000, 0x00000000, 0x00000000,
81 0x00000000, 0x00000000, 0x00000000, 0x00000000,
82 0x00000000, 0x00000000, 0x00000000, 0x00000000,
83 0x00000000, 0x00000000, 0x00000000, 0x00000000,
84 0x00000000, 0x00000000, 0x00000000, 0x00000000,
87 /* Packet types for packets with an Innermost/Last IPv6 header */
88 static const u32 ice_ptypes_ipv6_il
[] = {
89 0x00000000, 0x03B80770, 0x000001DC, 0x0EE00000,
90 0x00000770, 0x00000000, 0x00000000, 0x00000000,
91 0x00000000, 0x00000000, 0x00000000, 0x00000000,
92 0x00000000, 0x00000000, 0x00000000, 0x00000000,
93 0x00000000, 0x00000000, 0x00000000, 0x00000000,
94 0x00000000, 0x00000000, 0x00000000, 0x00000000,
95 0x00000000, 0x00000000, 0x00000000, 0x00000000,
96 0x00000000, 0x00000000, 0x00000000, 0x00000000,
99 /* UDP Packet types for non-tunneled packets or tunneled
100 * packets with inner UDP.
102 static const u32 ice_ptypes_udp_il
[] = {
103 0x81000000, 0x20204040, 0x04000010, 0x80810102,
104 0x00000040, 0x00000000, 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,
113 /* Packet types for packets with an Innermost/Last TCP header */
114 static const u32 ice_ptypes_tcp_il
[] = {
115 0x04000000, 0x80810102, 0x10000040, 0x02040408,
116 0x00000102, 0x00000000, 0x00000000, 0x00000000,
117 0x00000000, 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,
125 /* Packet types for packets with an Innermost/Last SCTP header */
126 static const u32 ice_ptypes_sctp_il
[] = {
127 0x08000000, 0x01020204, 0x20000081, 0x04080810,
128 0x00000204, 0x00000000, 0x00000000, 0x00000000,
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,
137 /* Manage parameters and info. used during the creation of a flow profile */
138 struct ice_flow_prof_params
{
140 u16 entry_length
; /* # of bytes formatted entry will require */
142 struct ice_flow_prof
*prof
;
144 /* For ACL, the es[0] will have the data of ICE_RX_MDID_PKT_FLAGS_15_0
145 * This will give us the direction flags.
147 struct ice_fv_word es
[ICE_MAX_FV_WORDS
];
148 DECLARE_BITMAP(ptypes
, ICE_FLOW_PTYPE_MAX
);
151 #define ICE_FLOW_SEG_HDRS_L3_MASK \
152 (ICE_FLOW_SEG_HDR_IPV4 | ICE_FLOW_SEG_HDR_IPV6)
153 #define ICE_FLOW_SEG_HDRS_L4_MASK \
154 (ICE_FLOW_SEG_HDR_TCP | ICE_FLOW_SEG_HDR_UDP | ICE_FLOW_SEG_HDR_SCTP)
157 * ice_flow_val_hdrs - validates packet segments for valid protocol headers
158 * @segs: array of one or more packet segments that describe the flow
159 * @segs_cnt: number of packet segments provided
161 static enum ice_status
162 ice_flow_val_hdrs(struct ice_flow_seg_info
*segs
, u8 segs_cnt
)
166 for (i
= 0; i
< segs_cnt
; i
++) {
167 /* Multiple L3 headers */
168 if (segs
[i
].hdrs
& ICE_FLOW_SEG_HDRS_L3_MASK
&&
169 !is_power_of_2(segs
[i
].hdrs
& ICE_FLOW_SEG_HDRS_L3_MASK
))
170 return ICE_ERR_PARAM
;
172 /* Multiple L4 headers */
173 if (segs
[i
].hdrs
& ICE_FLOW_SEG_HDRS_L4_MASK
&&
174 !is_power_of_2(segs
[i
].hdrs
& ICE_FLOW_SEG_HDRS_L4_MASK
))
175 return ICE_ERR_PARAM
;
182 * ice_flow_proc_seg_hdrs - process protocol headers present in pkt segments
183 * @params: information about the flow to be processed
185 * This function identifies the packet types associated with the protocol
186 * headers being present in packet segments of the specified flow profile.
188 static enum ice_status
189 ice_flow_proc_seg_hdrs(struct ice_flow_prof_params
*params
)
191 struct ice_flow_prof
*prof
;
194 memset(params
->ptypes
, 0xff, sizeof(params
->ptypes
));
198 for (i
= 0; i
< params
->prof
->segs_cnt
; i
++) {
199 const unsigned long *src
;
202 hdrs
= prof
->segs
[i
].hdrs
;
204 if (hdrs
& ICE_FLOW_SEG_HDR_IPV4
) {
205 src
= !i
? (const unsigned long *)ice_ptypes_ipv4_ofos
:
206 (const unsigned long *)ice_ptypes_ipv4_il
;
207 bitmap_and(params
->ptypes
, params
->ptypes
, src
,
209 } else if (hdrs
& ICE_FLOW_SEG_HDR_IPV6
) {
210 src
= !i
? (const unsigned long *)ice_ptypes_ipv6_ofos
:
211 (const unsigned long *)ice_ptypes_ipv6_il
;
212 bitmap_and(params
->ptypes
, params
->ptypes
, src
,
216 if (hdrs
& ICE_FLOW_SEG_HDR_UDP
) {
217 src
= (const unsigned long *)ice_ptypes_udp_il
;
218 bitmap_and(params
->ptypes
, params
->ptypes
, src
,
220 } else if (hdrs
& ICE_FLOW_SEG_HDR_TCP
) {
221 bitmap_and(params
->ptypes
, params
->ptypes
,
222 (const unsigned long *)ice_ptypes_tcp_il
,
224 } else if (hdrs
& ICE_FLOW_SEG_HDR_SCTP
) {
225 src
= (const unsigned long *)ice_ptypes_sctp_il
;
226 bitmap_and(params
->ptypes
, params
->ptypes
, src
,
235 * ice_flow_xtract_fld - Create an extraction sequence entry for the given field
236 * @hw: pointer to the HW struct
237 * @params: information about the flow to be processed
238 * @seg: packet segment index of the field to be extracted
239 * @fld: ID of field to be extracted
241 * This function determines the protocol ID, offset, and size of the given
242 * field. It then allocates one or more extraction sequence entries for the
243 * given field, and fill the entries with protocol ID and offset information.
245 static enum ice_status
246 ice_flow_xtract_fld(struct ice_hw
*hw
, struct ice_flow_prof_params
*params
,
247 u8 seg
, enum ice_flow_field fld
)
249 enum ice_prot_id prot_id
= ICE_PROT_ID_INVAL
;
250 u8 fv_words
= hw
->blk
[params
->blk
].es
.fvw
;
251 struct ice_flow_fld_info
*flds
;
252 u16 cnt
, ese_bits
, i
;
255 flds
= params
->prof
->segs
[seg
].fields
;
258 case ICE_FLOW_FIELD_IDX_IPV4_SA
:
259 case ICE_FLOW_FIELD_IDX_IPV4_DA
:
260 prot_id
= seg
== 0 ? ICE_PROT_IPV4_OF_OR_S
: ICE_PROT_IPV4_IL
;
262 case ICE_FLOW_FIELD_IDX_IPV6_SA
:
263 case ICE_FLOW_FIELD_IDX_IPV6_DA
:
264 prot_id
= seg
== 0 ? ICE_PROT_IPV6_OF_OR_S
: ICE_PROT_IPV6_IL
;
266 case ICE_FLOW_FIELD_IDX_TCP_SRC_PORT
:
267 case ICE_FLOW_FIELD_IDX_TCP_DST_PORT
:
268 prot_id
= ICE_PROT_TCP_IL
;
270 case ICE_FLOW_FIELD_IDX_UDP_SRC_PORT
:
271 case ICE_FLOW_FIELD_IDX_UDP_DST_PORT
:
272 prot_id
= ICE_PROT_UDP_IL_OR_S
;
274 case ICE_FLOW_FIELD_IDX_SCTP_SRC_PORT
:
275 case ICE_FLOW_FIELD_IDX_SCTP_DST_PORT
:
276 prot_id
= ICE_PROT_SCTP_IL
;
279 return ICE_ERR_NOT_IMPL
;
282 /* Each extraction sequence entry is a word in size, and extracts a
283 * word-aligned offset from a protocol header.
285 ese_bits
= ICE_FLOW_FV_EXTRACT_SZ
* BITS_PER_BYTE
;
287 flds
[fld
].xtrct
.prot_id
= prot_id
;
288 flds
[fld
].xtrct
.off
= (ice_flds_info
[fld
].off
/ ese_bits
) *
289 ICE_FLOW_FV_EXTRACT_SZ
;
290 flds
[fld
].xtrct
.disp
= (u8
)(ice_flds_info
[fld
].off
% ese_bits
);
291 flds
[fld
].xtrct
.idx
= params
->es_cnt
;
293 /* Adjust the next field-entry index after accommodating the number of
294 * entries this field consumes
296 cnt
= DIV_ROUND_UP(flds
[fld
].xtrct
.disp
+ ice_flds_info
[fld
].size
,
299 /* Fill in the extraction sequence entries needed for this field */
300 off
= flds
[fld
].xtrct
.off
;
301 for (i
= 0; i
< cnt
; i
++) {
304 /* Make sure the number of extraction sequence required
305 * does not exceed the block's capability
307 if (params
->es_cnt
>= fv_words
)
308 return ICE_ERR_MAX_LIMIT
;
310 /* some blocks require a reversed field vector layout */
311 if (hw
->blk
[params
->blk
].es
.reverse
)
312 idx
= fv_words
- params
->es_cnt
- 1;
314 idx
= params
->es_cnt
;
316 params
->es
[idx
].prot_id
= prot_id
;
317 params
->es
[idx
].off
= off
;
320 off
+= ICE_FLOW_FV_EXTRACT_SZ
;
327 * ice_flow_create_xtrct_seq - Create an extraction sequence for given segments
328 * @hw: pointer to the HW struct
329 * @params: information about the flow to be processed
331 * This function iterates through all matched fields in the given segments, and
332 * creates an extraction sequence for the fields.
334 static enum ice_status
335 ice_flow_create_xtrct_seq(struct ice_hw
*hw
,
336 struct ice_flow_prof_params
*params
)
338 struct ice_flow_prof
*prof
= params
->prof
;
339 enum ice_status status
= 0;
342 for (i
= 0; i
< prof
->segs_cnt
; i
++) {
345 for_each_set_bit(j
, (unsigned long *)&prof
->segs
[i
].match
,
346 ICE_FLOW_FIELD_IDX_MAX
) {
347 status
= ice_flow_xtract_fld(hw
, params
, i
,
348 (enum ice_flow_field
)j
);
358 * ice_flow_proc_segs - process all packet segments associated with a profile
359 * @hw: pointer to the HW struct
360 * @params: information about the flow to be processed
362 static enum ice_status
363 ice_flow_proc_segs(struct ice_hw
*hw
, struct ice_flow_prof_params
*params
)
365 enum ice_status status
;
367 status
= ice_flow_proc_seg_hdrs(params
);
371 status
= ice_flow_create_xtrct_seq(hw
, params
);
375 switch (params
->blk
) {
377 /* Only header information is provided for RSS configuration.
378 * No further processing is needed.
383 return ICE_ERR_NOT_IMPL
;
389 #define ICE_FLOW_FIND_PROF_CHK_FLDS 0x00000001
390 #define ICE_FLOW_FIND_PROF_CHK_VSI 0x00000002
391 #define ICE_FLOW_FIND_PROF_NOT_CHK_DIR 0x00000004
394 * ice_flow_find_prof_conds - Find a profile matching headers and conditions
395 * @hw: pointer to the HW struct
396 * @blk: classification stage
397 * @dir: flow direction
398 * @segs: array of one or more packet segments that describe the flow
399 * @segs_cnt: number of packet segments provided
400 * @vsi_handle: software VSI handle to check VSI (ICE_FLOW_FIND_PROF_CHK_VSI)
401 * @conds: additional conditions to be checked (ICE_FLOW_FIND_PROF_CHK_*)
403 static struct ice_flow_prof
*
404 ice_flow_find_prof_conds(struct ice_hw
*hw
, enum ice_block blk
,
405 enum ice_flow_dir dir
, struct ice_flow_seg_info
*segs
,
406 u8 segs_cnt
, u16 vsi_handle
, u32 conds
)
408 struct ice_flow_prof
*p
, *prof
= NULL
;
410 mutex_lock(&hw
->fl_profs_locks
[blk
]);
411 list_for_each_entry(p
, &hw
->fl_profs
[blk
], l_entry
)
412 if ((p
->dir
== dir
|| conds
& ICE_FLOW_FIND_PROF_NOT_CHK_DIR
) &&
413 segs_cnt
&& segs_cnt
== p
->segs_cnt
) {
416 /* Check for profile-VSI association if specified */
417 if ((conds
& ICE_FLOW_FIND_PROF_CHK_VSI
) &&
418 ice_is_vsi_valid(hw
, vsi_handle
) &&
419 !test_bit(vsi_handle
, p
->vsis
))
422 /* Protocol headers must be checked. Matched fields are
423 * checked if specified.
425 for (i
= 0; i
< segs_cnt
; i
++)
426 if (segs
[i
].hdrs
!= p
->segs
[i
].hdrs
||
427 ((conds
& ICE_FLOW_FIND_PROF_CHK_FLDS
) &&
428 segs
[i
].match
!= p
->segs
[i
].match
))
431 /* A match is found if all segments are matched */
437 mutex_unlock(&hw
->fl_profs_locks
[blk
]);
443 * ice_flow_find_prof_id - Look up a profile with given profile ID
444 * @hw: pointer to the HW struct
445 * @blk: classification stage
446 * @prof_id: unique ID to identify this flow profile
448 static struct ice_flow_prof
*
449 ice_flow_find_prof_id(struct ice_hw
*hw
, enum ice_block blk
, u64 prof_id
)
451 struct ice_flow_prof
*p
;
453 list_for_each_entry(p
, &hw
->fl_profs
[blk
], l_entry
)
454 if (p
->id
== prof_id
)
461 * ice_flow_add_prof_sync - Add a flow profile for packet segments and fields
462 * @hw: pointer to the HW struct
463 * @blk: classification stage
464 * @dir: flow direction
465 * @prof_id: unique ID to identify this flow profile
466 * @segs: array of one or more packet segments that describe the flow
467 * @segs_cnt: number of packet segments provided
468 * @prof: stores the returned flow profile added
470 * Assumption: the caller has acquired the lock to the profile list
472 static enum ice_status
473 ice_flow_add_prof_sync(struct ice_hw
*hw
, enum ice_block blk
,
474 enum ice_flow_dir dir
, u64 prof_id
,
475 struct ice_flow_seg_info
*segs
, u8 segs_cnt
,
476 struct ice_flow_prof
**prof
)
478 struct ice_flow_prof_params params
;
479 enum ice_status status
;
483 return ICE_ERR_BAD_PTR
;
485 memset(¶ms
, 0, sizeof(params
));
486 params
.prof
= devm_kzalloc(ice_hw_to_dev(hw
), sizeof(*params
.prof
),
489 return ICE_ERR_NO_MEMORY
;
491 /* initialize extraction sequence to all invalid (0xff) */
492 for (i
= 0; i
< ICE_MAX_FV_WORDS
; i
++) {
493 params
.es
[i
].prot_id
= ICE_PROT_INVALID
;
494 params
.es
[i
].off
= ICE_FV_OFFSET_INVAL
;
498 params
.prof
->id
= prof_id
;
499 params
.prof
->dir
= dir
;
500 params
.prof
->segs_cnt
= segs_cnt
;
502 /* Make a copy of the segments that need to be persistent in the flow
505 for (i
= 0; i
< segs_cnt
; i
++)
506 memcpy(¶ms
.prof
->segs
[i
], &segs
[i
], sizeof(*segs
));
508 status
= ice_flow_proc_segs(hw
, ¶ms
);
510 ice_debug(hw
, ICE_DBG_FLOW
,
511 "Error processing a flow's packet segments\n");
515 /* Add a HW profile for this flow profile */
516 status
= ice_add_prof(hw
, blk
, prof_id
, (u8
*)params
.ptypes
, params
.es
);
518 ice_debug(hw
, ICE_DBG_FLOW
, "Error adding a HW flow profile\n");
522 INIT_LIST_HEAD(¶ms
.prof
->entries
);
523 mutex_init(¶ms
.prof
->entries_lock
);
528 devm_kfree(ice_hw_to_dev(hw
), params
.prof
);
534 * ice_flow_rem_prof_sync - remove a flow profile
535 * @hw: pointer to the hardware structure
536 * @blk: classification stage
537 * @prof: pointer to flow profile to remove
539 * Assumption: the caller has acquired the lock to the profile list
541 static enum ice_status
542 ice_flow_rem_prof_sync(struct ice_hw
*hw
, enum ice_block blk
,
543 struct ice_flow_prof
*prof
)
545 enum ice_status status
;
547 /* Remove all hardware profiles associated with this flow profile */
548 status
= ice_rem_prof(hw
, blk
, prof
->id
);
550 list_del(&prof
->l_entry
);
551 mutex_destroy(&prof
->entries_lock
);
552 devm_kfree(ice_hw_to_dev(hw
), prof
);
559 * ice_flow_assoc_prof - associate a VSI with a flow profile
560 * @hw: pointer to the hardware structure
561 * @blk: classification stage
562 * @prof: pointer to flow profile
563 * @vsi_handle: software VSI handle
565 * Assumption: the caller has acquired the lock to the profile list
566 * and the software VSI handle has been validated
568 static enum ice_status
569 ice_flow_assoc_prof(struct ice_hw
*hw
, enum ice_block blk
,
570 struct ice_flow_prof
*prof
, u16 vsi_handle
)
572 enum ice_status status
= 0;
574 if (!test_bit(vsi_handle
, prof
->vsis
)) {
575 status
= ice_add_prof_id_flow(hw
, blk
,
576 ice_get_hw_vsi_num(hw
,
580 set_bit(vsi_handle
, prof
->vsis
);
582 ice_debug(hw
, ICE_DBG_FLOW
,
583 "HW profile add failed, %d\n",
591 * ice_flow_disassoc_prof - disassociate a VSI from a flow profile
592 * @hw: pointer to the hardware structure
593 * @blk: classification stage
594 * @prof: pointer to flow profile
595 * @vsi_handle: software VSI handle
597 * Assumption: the caller has acquired the lock to the profile list
598 * and the software VSI handle has been validated
600 static enum ice_status
601 ice_flow_disassoc_prof(struct ice_hw
*hw
, enum ice_block blk
,
602 struct ice_flow_prof
*prof
, u16 vsi_handle
)
604 enum ice_status status
= 0;
606 if (test_bit(vsi_handle
, prof
->vsis
)) {
607 status
= ice_rem_prof_id_flow(hw
, blk
,
608 ice_get_hw_vsi_num(hw
,
612 clear_bit(vsi_handle
, prof
->vsis
);
614 ice_debug(hw
, ICE_DBG_FLOW
,
615 "HW profile remove failed, %d\n",
623 * ice_flow_add_prof - Add a flow profile for packet segments and matched fields
624 * @hw: pointer to the HW struct
625 * @blk: classification stage
626 * @dir: flow direction
627 * @prof_id: unique ID to identify this flow profile
628 * @segs: array of one or more packet segments that describe the flow
629 * @segs_cnt: number of packet segments provided
630 * @prof: stores the returned flow profile added
632 static enum ice_status
633 ice_flow_add_prof(struct ice_hw
*hw
, enum ice_block blk
, enum ice_flow_dir dir
,
634 u64 prof_id
, struct ice_flow_seg_info
*segs
, u8 segs_cnt
,
635 struct ice_flow_prof
**prof
)
637 enum ice_status status
;
639 if (segs_cnt
> ICE_FLOW_SEG_MAX
)
640 return ICE_ERR_MAX_LIMIT
;
643 return ICE_ERR_PARAM
;
646 return ICE_ERR_BAD_PTR
;
648 status
= ice_flow_val_hdrs(segs
, segs_cnt
);
652 mutex_lock(&hw
->fl_profs_locks
[blk
]);
654 status
= ice_flow_add_prof_sync(hw
, blk
, dir
, prof_id
, segs
, segs_cnt
,
657 list_add(&(*prof
)->l_entry
, &hw
->fl_profs
[blk
]);
659 mutex_unlock(&hw
->fl_profs_locks
[blk
]);
665 * ice_flow_rem_prof - Remove a flow profile and all entries associated with it
666 * @hw: pointer to the HW struct
667 * @blk: the block for which the flow profile is to be removed
668 * @prof_id: unique ID of the flow profile to be removed
670 static enum ice_status
671 ice_flow_rem_prof(struct ice_hw
*hw
, enum ice_block blk
, u64 prof_id
)
673 struct ice_flow_prof
*prof
;
674 enum ice_status status
;
676 mutex_lock(&hw
->fl_profs_locks
[blk
]);
678 prof
= ice_flow_find_prof_id(hw
, blk
, prof_id
);
680 status
= ICE_ERR_DOES_NOT_EXIST
;
684 /* prof becomes invalid after the call */
685 status
= ice_flow_rem_prof_sync(hw
, blk
, prof
);
688 mutex_unlock(&hw
->fl_profs_locks
[blk
]);
694 * ice_flow_set_fld_ext - specifies locations of field from entry's input buffer
695 * @seg: packet segment the field being set belongs to
696 * @fld: field to be set
697 * @field_type: type of the field
698 * @val_loc: if not ICE_FLOW_FLD_OFF_INVAL, location of the value to match from
699 * entry's input buffer
700 * @mask_loc: if not ICE_FLOW_FLD_OFF_INVAL, location of mask value from entry's
702 * @last_loc: if not ICE_FLOW_FLD_OFF_INVAL, location of last/upper value from
703 * entry's input buffer
705 * This helper function stores information of a field being matched, including
706 * the type of the field and the locations of the value to match, the mask, and
707 * and the upper-bound value in the start of the input buffer for a flow entry.
708 * This function should only be used for fixed-size data structures.
710 * This function also opportunistically determines the protocol headers to be
711 * present based on the fields being set. Some fields cannot be used alone to
712 * determine the protocol headers present. Sometimes, fields for particular
713 * protocol headers are not matched. In those cases, the protocol headers
714 * must be explicitly set.
717 ice_flow_set_fld_ext(struct ice_flow_seg_info
*seg
, enum ice_flow_field fld
,
718 enum ice_flow_fld_match_type field_type
, u16 val_loc
,
719 u16 mask_loc
, u16 last_loc
)
721 u64 bit
= BIT_ULL(fld
);
724 if (field_type
== ICE_FLOW_FLD_TYPE_RANGE
)
727 seg
->fields
[fld
].type
= field_type
;
728 seg
->fields
[fld
].src
.val
= val_loc
;
729 seg
->fields
[fld
].src
.mask
= mask_loc
;
730 seg
->fields
[fld
].src
.last
= last_loc
;
732 ICE_FLOW_SET_HDRS(seg
, ice_flds_info
[fld
].hdr
);
736 * ice_flow_set_fld - specifies locations of field from entry's input buffer
737 * @seg: packet segment the field being set belongs to
738 * @fld: field to be set
739 * @val_loc: if not ICE_FLOW_FLD_OFF_INVAL, location of the value to match from
740 * entry's input buffer
741 * @mask_loc: if not ICE_FLOW_FLD_OFF_INVAL, location of mask value from entry's
743 * @last_loc: if not ICE_FLOW_FLD_OFF_INVAL, location of last/upper value from
744 * entry's input buffer
745 * @range: indicate if field being matched is to be in a range
747 * This function specifies the locations, in the form of byte offsets from the
748 * start of the input buffer for a flow entry, from where the value to match,
749 * the mask value, and upper value can be extracted. These locations are then
750 * stored in the flow profile. When adding a flow entry associated with the
751 * flow profile, these locations will be used to quickly extract the values and
752 * create the content of a match entry. This function should only be used for
753 * fixed-size data structures.
756 ice_flow_set_fld(struct ice_flow_seg_info
*seg
, enum ice_flow_field fld
,
757 u16 val_loc
, u16 mask_loc
, u16 last_loc
, bool range
)
759 enum ice_flow_fld_match_type t
= range
?
760 ICE_FLOW_FLD_TYPE_RANGE
: ICE_FLOW_FLD_TYPE_REG
;
762 ice_flow_set_fld_ext(seg
, fld
, t
, val_loc
, mask_loc
, last_loc
);
765 #define ICE_FLOW_RSS_SEG_HDR_L3_MASKS \
766 (ICE_FLOW_SEG_HDR_IPV4 | ICE_FLOW_SEG_HDR_IPV6)
768 #define ICE_FLOW_RSS_SEG_HDR_L4_MASKS \
769 (ICE_FLOW_SEG_HDR_TCP | ICE_FLOW_SEG_HDR_UDP | ICE_FLOW_SEG_HDR_SCTP)
771 #define ICE_FLOW_RSS_SEG_HDR_VAL_MASKS \
772 (ICE_FLOW_RSS_SEG_HDR_L3_MASKS | \
773 ICE_FLOW_RSS_SEG_HDR_L4_MASKS)
776 * ice_flow_set_rss_seg_info - setup packet segments for RSS
777 * @segs: pointer to the flow field segment(s)
778 * @hash_fields: fields to be hashed on for the segment(s)
779 * @flow_hdr: protocol header fields within a packet segment
781 * Helper function to extract fields from hash bitmap and use flow
782 * header value to set flow field segment for further use in flow
783 * profile entry or removal.
785 static enum ice_status
786 ice_flow_set_rss_seg_info(struct ice_flow_seg_info
*segs
, u64 hash_fields
,
792 for_each_set_bit(i
, (unsigned long *)&hash_fields
,
793 ICE_FLOW_FIELD_IDX_MAX
)
794 ice_flow_set_fld(segs
, (enum ice_flow_field
)i
,
795 ICE_FLOW_FLD_OFF_INVAL
, ICE_FLOW_FLD_OFF_INVAL
,
796 ICE_FLOW_FLD_OFF_INVAL
, false);
798 ICE_FLOW_SET_HDRS(segs
, flow_hdr
);
800 if (segs
->hdrs
& ~ICE_FLOW_RSS_SEG_HDR_VAL_MASKS
)
801 return ICE_ERR_PARAM
;
803 val
= (u64
)(segs
->hdrs
& ICE_FLOW_RSS_SEG_HDR_L3_MASKS
);
804 if (val
&& !is_power_of_2(val
))
807 val
= (u64
)(segs
->hdrs
& ICE_FLOW_RSS_SEG_HDR_L4_MASKS
);
808 if (val
&& !is_power_of_2(val
))
815 * ice_rem_vsi_rss_list - remove VSI from RSS list
816 * @hw: pointer to the hardware structure
817 * @vsi_handle: software VSI handle
819 * Remove the VSI from all RSS configurations in the list.
821 void ice_rem_vsi_rss_list(struct ice_hw
*hw
, u16 vsi_handle
)
823 struct ice_rss_cfg
*r
, *tmp
;
825 if (list_empty(&hw
->rss_list_head
))
828 mutex_lock(&hw
->rss_locks
);
829 list_for_each_entry_safe(r
, tmp
, &hw
->rss_list_head
, l_entry
)
830 if (test_and_clear_bit(vsi_handle
, r
->vsis
))
831 if (bitmap_empty(r
->vsis
, ICE_MAX_VSI
)) {
832 list_del(&r
->l_entry
);
833 devm_kfree(ice_hw_to_dev(hw
), r
);
835 mutex_unlock(&hw
->rss_locks
);
839 * ice_rem_vsi_rss_cfg - remove RSS configurations associated with VSI
840 * @hw: pointer to the hardware structure
841 * @vsi_handle: software VSI handle
843 * This function will iterate through all flow profiles and disassociate
844 * the VSI from that profile. If the flow profile has no VSIs it will
847 enum ice_status
ice_rem_vsi_rss_cfg(struct ice_hw
*hw
, u16 vsi_handle
)
849 const enum ice_block blk
= ICE_BLK_RSS
;
850 struct ice_flow_prof
*p
, *t
;
851 enum ice_status status
= 0;
853 if (!ice_is_vsi_valid(hw
, vsi_handle
))
854 return ICE_ERR_PARAM
;
856 if (list_empty(&hw
->fl_profs
[blk
]))
859 mutex_lock(&hw
->fl_profs_locks
[blk
]);
860 list_for_each_entry_safe(p
, t
, &hw
->fl_profs
[blk
], l_entry
)
861 if (test_bit(vsi_handle
, p
->vsis
)) {
862 status
= ice_flow_disassoc_prof(hw
, blk
, p
, vsi_handle
);
866 if (bitmap_empty(p
->vsis
, ICE_MAX_VSI
)) {
867 status
= ice_flow_rem_prof_sync(hw
, blk
, p
);
872 mutex_unlock(&hw
->fl_profs_locks
[blk
]);
878 * ice_rem_rss_list - remove RSS configuration from list
879 * @hw: pointer to the hardware structure
880 * @vsi_handle: software VSI handle
881 * @prof: pointer to flow profile
883 * Assumption: lock has already been acquired for RSS list
886 ice_rem_rss_list(struct ice_hw
*hw
, u16 vsi_handle
, struct ice_flow_prof
*prof
)
888 struct ice_rss_cfg
*r
, *tmp
;
890 /* Search for RSS hash fields associated to the VSI that match the
891 * hash configurations associated to the flow profile. If found
892 * remove from the RSS entry list of the VSI context and delete entry.
894 list_for_each_entry_safe(r
, tmp
, &hw
->rss_list_head
, l_entry
)
895 if (r
->hashed_flds
== prof
->segs
[prof
->segs_cnt
- 1].match
&&
896 r
->packet_hdr
== prof
->segs
[prof
->segs_cnt
- 1].hdrs
) {
897 clear_bit(vsi_handle
, r
->vsis
);
898 if (bitmap_empty(r
->vsis
, ICE_MAX_VSI
)) {
899 list_del(&r
->l_entry
);
900 devm_kfree(ice_hw_to_dev(hw
), r
);
907 * ice_add_rss_list - add RSS configuration to list
908 * @hw: pointer to the hardware structure
909 * @vsi_handle: software VSI handle
910 * @prof: pointer to flow profile
912 * Assumption: lock has already been acquired for RSS list
914 static enum ice_status
915 ice_add_rss_list(struct ice_hw
*hw
, u16 vsi_handle
, struct ice_flow_prof
*prof
)
917 struct ice_rss_cfg
*r
, *rss_cfg
;
919 list_for_each_entry(r
, &hw
->rss_list_head
, l_entry
)
920 if (r
->hashed_flds
== prof
->segs
[prof
->segs_cnt
- 1].match
&&
921 r
->packet_hdr
== prof
->segs
[prof
->segs_cnt
- 1].hdrs
) {
922 set_bit(vsi_handle
, r
->vsis
);
926 rss_cfg
= devm_kzalloc(ice_hw_to_dev(hw
), sizeof(*rss_cfg
),
929 return ICE_ERR_NO_MEMORY
;
931 rss_cfg
->hashed_flds
= prof
->segs
[prof
->segs_cnt
- 1].match
;
932 rss_cfg
->packet_hdr
= prof
->segs
[prof
->segs_cnt
- 1].hdrs
;
933 set_bit(vsi_handle
, rss_cfg
->vsis
);
935 list_add_tail(&rss_cfg
->l_entry
, &hw
->rss_list_head
);
940 #define ICE_FLOW_PROF_HASH_S 0
941 #define ICE_FLOW_PROF_HASH_M (0xFFFFFFFFULL << ICE_FLOW_PROF_HASH_S)
942 #define ICE_FLOW_PROF_HDR_S 32
943 #define ICE_FLOW_PROF_HDR_M (0x3FFFFFFFULL << ICE_FLOW_PROF_HDR_S)
944 #define ICE_FLOW_PROF_ENCAP_S 63
945 #define ICE_FLOW_PROF_ENCAP_M (BIT_ULL(ICE_FLOW_PROF_ENCAP_S))
947 #define ICE_RSS_OUTER_HEADERS 1
949 /* Flow profile ID format:
950 * [0:31] - Packet match fields
951 * [32:62] - Protocol header
952 * [63] - Encapsulation flag, 0 if non-tunneled, 1 if tunneled
954 #define ICE_FLOW_GEN_PROFID(hash, hdr, segs_cnt) \
955 (u64)(((u64)(hash) & ICE_FLOW_PROF_HASH_M) | \
956 (((u64)(hdr) << ICE_FLOW_PROF_HDR_S) & ICE_FLOW_PROF_HDR_M) | \
957 ((u8)((segs_cnt) - 1) ? ICE_FLOW_PROF_ENCAP_M : 0))
960 * ice_add_rss_cfg_sync - add an RSS configuration
961 * @hw: pointer to the hardware structure
962 * @vsi_handle: software VSI handle
963 * @hashed_flds: hash bit fields (ICE_FLOW_HASH_*) to configure
964 * @addl_hdrs: protocol header fields
965 * @segs_cnt: packet segment count
967 * Assumption: lock has already been acquired for RSS list
969 static enum ice_status
970 ice_add_rss_cfg_sync(struct ice_hw
*hw
, u16 vsi_handle
, u64 hashed_flds
,
971 u32 addl_hdrs
, u8 segs_cnt
)
973 const enum ice_block blk
= ICE_BLK_RSS
;
974 struct ice_flow_prof
*prof
= NULL
;
975 struct ice_flow_seg_info
*segs
;
976 enum ice_status status
;
978 if (!segs_cnt
|| segs_cnt
> ICE_FLOW_SEG_MAX
)
979 return ICE_ERR_PARAM
;
981 segs
= kcalloc(segs_cnt
, sizeof(*segs
), GFP_KERNEL
);
983 return ICE_ERR_NO_MEMORY
;
985 /* Construct the packet segment info from the hashed fields */
986 status
= ice_flow_set_rss_seg_info(&segs
[segs_cnt
- 1], hashed_flds
,
991 /* Search for a flow profile that has matching headers, hash fields
992 * and has the input VSI associated to it. If found, no further
993 * operations required and exit.
995 prof
= ice_flow_find_prof_conds(hw
, blk
, ICE_FLOW_RX
, segs
, segs_cnt
,
997 ICE_FLOW_FIND_PROF_CHK_FLDS
|
998 ICE_FLOW_FIND_PROF_CHK_VSI
);
1002 /* Check if a flow profile exists with the same protocol headers and
1003 * associated with the input VSI. If so disassociate the VSI from
1004 * this profile. The VSI will be added to a new profile created with
1005 * the protocol header and new hash field configuration.
1007 prof
= ice_flow_find_prof_conds(hw
, blk
, ICE_FLOW_RX
, segs
, segs_cnt
,
1008 vsi_handle
, ICE_FLOW_FIND_PROF_CHK_VSI
);
1010 status
= ice_flow_disassoc_prof(hw
, blk
, prof
, vsi_handle
);
1012 ice_rem_rss_list(hw
, vsi_handle
, prof
);
1016 /* Remove profile if it has no VSIs associated */
1017 if (bitmap_empty(prof
->vsis
, ICE_MAX_VSI
)) {
1018 status
= ice_flow_rem_prof(hw
, blk
, prof
->id
);
1024 /* Search for a profile that has same match fields only. If this
1025 * exists then associate the VSI to this profile.
1027 prof
= ice_flow_find_prof_conds(hw
, blk
, ICE_FLOW_RX
, segs
, segs_cnt
,
1029 ICE_FLOW_FIND_PROF_CHK_FLDS
);
1031 status
= ice_flow_assoc_prof(hw
, blk
, prof
, vsi_handle
);
1033 status
= ice_add_rss_list(hw
, vsi_handle
, prof
);
1037 /* Create a new flow profile with generated profile and packet
1038 * segment information.
1040 status
= ice_flow_add_prof(hw
, blk
, ICE_FLOW_RX
,
1041 ICE_FLOW_GEN_PROFID(hashed_flds
,
1042 segs
[segs_cnt
- 1].hdrs
,
1044 segs
, segs_cnt
, &prof
);
1048 status
= ice_flow_assoc_prof(hw
, blk
, prof
, vsi_handle
);
1049 /* If association to a new flow profile failed then this profile can
1053 ice_flow_rem_prof(hw
, blk
, prof
->id
);
1057 status
= ice_add_rss_list(hw
, vsi_handle
, prof
);
1065 * ice_add_rss_cfg - add an RSS configuration with specified hashed fields
1066 * @hw: pointer to the hardware structure
1067 * @vsi_handle: software VSI handle
1068 * @hashed_flds: hash bit fields (ICE_FLOW_HASH_*) to configure
1069 * @addl_hdrs: protocol header fields
1071 * This function will generate a flow profile based on fields associated with
1072 * the input fields to hash on, the flow type and use the VSI number to add
1073 * a flow entry to the profile.
1076 ice_add_rss_cfg(struct ice_hw
*hw
, u16 vsi_handle
, u64 hashed_flds
,
1079 enum ice_status status
;
1081 if (hashed_flds
== ICE_HASH_INVALID
||
1082 !ice_is_vsi_valid(hw
, vsi_handle
))
1083 return ICE_ERR_PARAM
;
1085 mutex_lock(&hw
->rss_locks
);
1086 status
= ice_add_rss_cfg_sync(hw
, vsi_handle
, hashed_flds
, addl_hdrs
,
1087 ICE_RSS_OUTER_HEADERS
);
1088 mutex_unlock(&hw
->rss_locks
);
1093 /* Mapping of AVF hash bit fields to an L3-L4 hash combination.
1094 * As the ice_flow_avf_hdr_field represent individual bit shifts in a hash,
1095 * convert its values to their appropriate flow L3, L4 values.
1097 #define ICE_FLOW_AVF_RSS_IPV4_MASKS \
1098 (BIT_ULL(ICE_AVF_FLOW_FIELD_IPV4_OTHER) | \
1099 BIT_ULL(ICE_AVF_FLOW_FIELD_FRAG_IPV4))
1100 #define ICE_FLOW_AVF_RSS_TCP_IPV4_MASKS \
1101 (BIT_ULL(ICE_AVF_FLOW_FIELD_IPV4_TCP_SYN_NO_ACK) | \
1102 BIT_ULL(ICE_AVF_FLOW_FIELD_IPV4_TCP))
1103 #define ICE_FLOW_AVF_RSS_UDP_IPV4_MASKS \
1104 (BIT_ULL(ICE_AVF_FLOW_FIELD_UNICAST_IPV4_UDP) | \
1105 BIT_ULL(ICE_AVF_FLOW_FIELD_MULTICAST_IPV4_UDP) | \
1106 BIT_ULL(ICE_AVF_FLOW_FIELD_IPV4_UDP))
1107 #define ICE_FLOW_AVF_RSS_ALL_IPV4_MASKS \
1108 (ICE_FLOW_AVF_RSS_TCP_IPV4_MASKS | ICE_FLOW_AVF_RSS_UDP_IPV4_MASKS | \
1109 ICE_FLOW_AVF_RSS_IPV4_MASKS | BIT_ULL(ICE_AVF_FLOW_FIELD_IPV4_SCTP))
1111 #define ICE_FLOW_AVF_RSS_IPV6_MASKS \
1112 (BIT_ULL(ICE_AVF_FLOW_FIELD_IPV6_OTHER) | \
1113 BIT_ULL(ICE_AVF_FLOW_FIELD_FRAG_IPV6))
1114 #define ICE_FLOW_AVF_RSS_UDP_IPV6_MASKS \
1115 (BIT_ULL(ICE_AVF_FLOW_FIELD_UNICAST_IPV6_UDP) | \
1116 BIT_ULL(ICE_AVF_FLOW_FIELD_MULTICAST_IPV6_UDP) | \
1117 BIT_ULL(ICE_AVF_FLOW_FIELD_IPV6_UDP))
1118 #define ICE_FLOW_AVF_RSS_TCP_IPV6_MASKS \
1119 (BIT_ULL(ICE_AVF_FLOW_FIELD_IPV6_TCP_SYN_NO_ACK) | \
1120 BIT_ULL(ICE_AVF_FLOW_FIELD_IPV6_TCP))
1121 #define ICE_FLOW_AVF_RSS_ALL_IPV6_MASKS \
1122 (ICE_FLOW_AVF_RSS_TCP_IPV6_MASKS | ICE_FLOW_AVF_RSS_UDP_IPV6_MASKS | \
1123 ICE_FLOW_AVF_RSS_IPV6_MASKS | BIT_ULL(ICE_AVF_FLOW_FIELD_IPV6_SCTP))
1126 * ice_add_avf_rss_cfg - add an RSS configuration for AVF driver
1127 * @hw: pointer to the hardware structure
1128 * @vsi_handle: software VSI handle
1129 * @avf_hash: hash bit fields (ICE_AVF_FLOW_FIELD_*) to configure
1131 * This function will take the hash bitmap provided by the AVF driver via a
1132 * message, convert it to ICE-compatible values, and configure RSS flow
1136 ice_add_avf_rss_cfg(struct ice_hw
*hw
, u16 vsi_handle
, u64 avf_hash
)
1138 enum ice_status status
= 0;
1141 if (avf_hash
== ICE_AVF_FLOW_FIELD_INVALID
||
1142 !ice_is_vsi_valid(hw
, vsi_handle
))
1143 return ICE_ERR_PARAM
;
1145 /* Make sure no unsupported bits are specified */
1146 if (avf_hash
& ~(ICE_FLOW_AVF_RSS_ALL_IPV4_MASKS
|
1147 ICE_FLOW_AVF_RSS_ALL_IPV6_MASKS
))
1150 hash_flds
= avf_hash
;
1152 /* Always create an L3 RSS configuration for any L4 RSS configuration */
1153 if (hash_flds
& ICE_FLOW_AVF_RSS_ALL_IPV4_MASKS
)
1154 hash_flds
|= ICE_FLOW_AVF_RSS_IPV4_MASKS
;
1156 if (hash_flds
& ICE_FLOW_AVF_RSS_ALL_IPV6_MASKS
)
1157 hash_flds
|= ICE_FLOW_AVF_RSS_IPV6_MASKS
;
1159 /* Create the corresponding RSS configuration for each valid hash bit */
1161 u64 rss_hash
= ICE_HASH_INVALID
;
1163 if (hash_flds
& ICE_FLOW_AVF_RSS_ALL_IPV4_MASKS
) {
1164 if (hash_flds
& ICE_FLOW_AVF_RSS_IPV4_MASKS
) {
1165 rss_hash
= ICE_FLOW_HASH_IPV4
;
1166 hash_flds
&= ~ICE_FLOW_AVF_RSS_IPV4_MASKS
;
1167 } else if (hash_flds
&
1168 ICE_FLOW_AVF_RSS_TCP_IPV4_MASKS
) {
1169 rss_hash
= ICE_FLOW_HASH_IPV4
|
1170 ICE_FLOW_HASH_TCP_PORT
;
1171 hash_flds
&= ~ICE_FLOW_AVF_RSS_TCP_IPV4_MASKS
;
1172 } else if (hash_flds
&
1173 ICE_FLOW_AVF_RSS_UDP_IPV4_MASKS
) {
1174 rss_hash
= ICE_FLOW_HASH_IPV4
|
1175 ICE_FLOW_HASH_UDP_PORT
;
1176 hash_flds
&= ~ICE_FLOW_AVF_RSS_UDP_IPV4_MASKS
;
1177 } else if (hash_flds
&
1178 BIT_ULL(ICE_AVF_FLOW_FIELD_IPV4_SCTP
)) {
1179 rss_hash
= ICE_FLOW_HASH_IPV4
|
1180 ICE_FLOW_HASH_SCTP_PORT
;
1182 ~BIT_ULL(ICE_AVF_FLOW_FIELD_IPV4_SCTP
);
1184 } else if (hash_flds
& ICE_FLOW_AVF_RSS_ALL_IPV6_MASKS
) {
1185 if (hash_flds
& ICE_FLOW_AVF_RSS_IPV6_MASKS
) {
1186 rss_hash
= ICE_FLOW_HASH_IPV6
;
1187 hash_flds
&= ~ICE_FLOW_AVF_RSS_IPV6_MASKS
;
1188 } else if (hash_flds
&
1189 ICE_FLOW_AVF_RSS_TCP_IPV6_MASKS
) {
1190 rss_hash
= ICE_FLOW_HASH_IPV6
|
1191 ICE_FLOW_HASH_TCP_PORT
;
1192 hash_flds
&= ~ICE_FLOW_AVF_RSS_TCP_IPV6_MASKS
;
1193 } else if (hash_flds
&
1194 ICE_FLOW_AVF_RSS_UDP_IPV6_MASKS
) {
1195 rss_hash
= ICE_FLOW_HASH_IPV6
|
1196 ICE_FLOW_HASH_UDP_PORT
;
1197 hash_flds
&= ~ICE_FLOW_AVF_RSS_UDP_IPV6_MASKS
;
1198 } else if (hash_flds
&
1199 BIT_ULL(ICE_AVF_FLOW_FIELD_IPV6_SCTP
)) {
1200 rss_hash
= ICE_FLOW_HASH_IPV6
|
1201 ICE_FLOW_HASH_SCTP_PORT
;
1203 ~BIT_ULL(ICE_AVF_FLOW_FIELD_IPV6_SCTP
);
1207 if (rss_hash
== ICE_HASH_INVALID
)
1208 return ICE_ERR_OUT_OF_RANGE
;
1210 status
= ice_add_rss_cfg(hw
, vsi_handle
, rss_hash
,
1211 ICE_FLOW_SEG_HDR_NONE
);
1220 * ice_replay_rss_cfg - replay RSS configurations associated with VSI
1221 * @hw: pointer to the hardware structure
1222 * @vsi_handle: software VSI handle
1224 enum ice_status
ice_replay_rss_cfg(struct ice_hw
*hw
, u16 vsi_handle
)
1226 enum ice_status status
= 0;
1227 struct ice_rss_cfg
*r
;
1229 if (!ice_is_vsi_valid(hw
, vsi_handle
))
1230 return ICE_ERR_PARAM
;
1232 mutex_lock(&hw
->rss_locks
);
1233 list_for_each_entry(r
, &hw
->rss_list_head
, l_entry
) {
1234 if (test_bit(vsi_handle
, r
->vsis
)) {
1235 status
= ice_add_rss_cfg_sync(hw
, vsi_handle
,
1238 ICE_RSS_OUTER_HEADERS
);
1243 mutex_unlock(&hw
->rss_locks
);
1249 * ice_get_rss_cfg - returns hashed fields for the given header types
1250 * @hw: pointer to the hardware structure
1251 * @vsi_handle: software VSI handle
1252 * @hdrs: protocol header type
1254 * This function will return the match fields of the first instance of flow
1255 * profile having the given header types and containing input VSI
1257 u64
ice_get_rss_cfg(struct ice_hw
*hw
, u16 vsi_handle
, u32 hdrs
)
1259 struct ice_rss_cfg
*r
, *rss_cfg
= NULL
;
1261 /* verify if the protocol header is non zero and VSI is valid */
1262 if (hdrs
== ICE_FLOW_SEG_HDR_NONE
|| !ice_is_vsi_valid(hw
, vsi_handle
))
1263 return ICE_HASH_INVALID
;
1265 mutex_lock(&hw
->rss_locks
);
1266 list_for_each_entry(r
, &hw
->rss_list_head
, l_entry
)
1267 if (test_bit(vsi_handle
, r
->vsis
) &&
1268 r
->packet_hdr
== hdrs
) {
1272 mutex_unlock(&hw
->rss_locks
);
1274 return rss_cfg
? rss_cfg
->hashed_flds
: ICE_HASH_INVALID
;