162306a36Sopenharmony_ci// SPDX-License-Identifier: GPL-2.0
262306a36Sopenharmony_ci/* Copyright (c) 2019, Intel Corporation. */
362306a36Sopenharmony_ci
462306a36Sopenharmony_ci#include "ice_common.h"
562306a36Sopenharmony_ci#include "ice_flow.h"
662306a36Sopenharmony_ci#include <net/gre.h>
762306a36Sopenharmony_ci
862306a36Sopenharmony_ci/* Describe properties of a protocol header field */
962306a36Sopenharmony_cistruct ice_flow_field_info {
1062306a36Sopenharmony_ci	enum ice_flow_seg_hdr hdr;
1162306a36Sopenharmony_ci	s16 off;	/* Offset from start of a protocol header, in bits */
1262306a36Sopenharmony_ci	u16 size;	/* Size of fields in bits */
1362306a36Sopenharmony_ci	u16 mask;	/* 16-bit mask for field */
1462306a36Sopenharmony_ci};
1562306a36Sopenharmony_ci
1662306a36Sopenharmony_ci#define ICE_FLOW_FLD_INFO(_hdr, _offset_bytes, _size_bytes) { \
1762306a36Sopenharmony_ci	.hdr = _hdr, \
1862306a36Sopenharmony_ci	.off = (_offset_bytes) * BITS_PER_BYTE, \
1962306a36Sopenharmony_ci	.size = (_size_bytes) * BITS_PER_BYTE, \
2062306a36Sopenharmony_ci	.mask = 0, \
2162306a36Sopenharmony_ci}
2262306a36Sopenharmony_ci
2362306a36Sopenharmony_ci#define ICE_FLOW_FLD_INFO_MSK(_hdr, _offset_bytes, _size_bytes, _mask) { \
2462306a36Sopenharmony_ci	.hdr = _hdr, \
2562306a36Sopenharmony_ci	.off = (_offset_bytes) * BITS_PER_BYTE, \
2662306a36Sopenharmony_ci	.size = (_size_bytes) * BITS_PER_BYTE, \
2762306a36Sopenharmony_ci	.mask = _mask, \
2862306a36Sopenharmony_ci}
2962306a36Sopenharmony_ci
3062306a36Sopenharmony_ci/* Table containing properties of supported protocol header fields */
3162306a36Sopenharmony_cistatic const
3262306a36Sopenharmony_cistruct ice_flow_field_info ice_flds_info[ICE_FLOW_FIELD_IDX_MAX] = {
3362306a36Sopenharmony_ci	/* Ether */
3462306a36Sopenharmony_ci	/* ICE_FLOW_FIELD_IDX_ETH_DA */
3562306a36Sopenharmony_ci	ICE_FLOW_FLD_INFO(ICE_FLOW_SEG_HDR_ETH, 0, ETH_ALEN),
3662306a36Sopenharmony_ci	/* ICE_FLOW_FIELD_IDX_ETH_SA */
3762306a36Sopenharmony_ci	ICE_FLOW_FLD_INFO(ICE_FLOW_SEG_HDR_ETH, ETH_ALEN, ETH_ALEN),
3862306a36Sopenharmony_ci	/* ICE_FLOW_FIELD_IDX_S_VLAN */
3962306a36Sopenharmony_ci	ICE_FLOW_FLD_INFO(ICE_FLOW_SEG_HDR_VLAN, 12, sizeof(__be16)),
4062306a36Sopenharmony_ci	/* ICE_FLOW_FIELD_IDX_C_VLAN */
4162306a36Sopenharmony_ci	ICE_FLOW_FLD_INFO(ICE_FLOW_SEG_HDR_VLAN, 14, sizeof(__be16)),
4262306a36Sopenharmony_ci	/* ICE_FLOW_FIELD_IDX_ETH_TYPE */
4362306a36Sopenharmony_ci	ICE_FLOW_FLD_INFO(ICE_FLOW_SEG_HDR_ETH, 0, sizeof(__be16)),
4462306a36Sopenharmony_ci	/* IPv4 / IPv6 */
4562306a36Sopenharmony_ci	/* ICE_FLOW_FIELD_IDX_IPV4_DSCP */
4662306a36Sopenharmony_ci	ICE_FLOW_FLD_INFO_MSK(ICE_FLOW_SEG_HDR_IPV4, 0, 1, 0x00fc),
4762306a36Sopenharmony_ci	/* ICE_FLOW_FIELD_IDX_IPV6_DSCP */
4862306a36Sopenharmony_ci	ICE_FLOW_FLD_INFO_MSK(ICE_FLOW_SEG_HDR_IPV6, 0, 1, 0x0ff0),
4962306a36Sopenharmony_ci	/* ICE_FLOW_FIELD_IDX_IPV4_TTL */
5062306a36Sopenharmony_ci	ICE_FLOW_FLD_INFO_MSK(ICE_FLOW_SEG_HDR_NONE, 8, 1, 0xff00),
5162306a36Sopenharmony_ci	/* ICE_FLOW_FIELD_IDX_IPV4_PROT */
5262306a36Sopenharmony_ci	ICE_FLOW_FLD_INFO_MSK(ICE_FLOW_SEG_HDR_NONE, 8, 1, 0x00ff),
5362306a36Sopenharmony_ci	/* ICE_FLOW_FIELD_IDX_IPV6_TTL */
5462306a36Sopenharmony_ci	ICE_FLOW_FLD_INFO_MSK(ICE_FLOW_SEG_HDR_NONE, 6, 1, 0x00ff),
5562306a36Sopenharmony_ci	/* ICE_FLOW_FIELD_IDX_IPV6_PROT */
5662306a36Sopenharmony_ci	ICE_FLOW_FLD_INFO_MSK(ICE_FLOW_SEG_HDR_NONE, 6, 1, 0xff00),
5762306a36Sopenharmony_ci	/* ICE_FLOW_FIELD_IDX_IPV4_SA */
5862306a36Sopenharmony_ci	ICE_FLOW_FLD_INFO(ICE_FLOW_SEG_HDR_IPV4, 12, sizeof(struct in_addr)),
5962306a36Sopenharmony_ci	/* ICE_FLOW_FIELD_IDX_IPV4_DA */
6062306a36Sopenharmony_ci	ICE_FLOW_FLD_INFO(ICE_FLOW_SEG_HDR_IPV4, 16, sizeof(struct in_addr)),
6162306a36Sopenharmony_ci	/* ICE_FLOW_FIELD_IDX_IPV6_SA */
6262306a36Sopenharmony_ci	ICE_FLOW_FLD_INFO(ICE_FLOW_SEG_HDR_IPV6, 8, sizeof(struct in6_addr)),
6362306a36Sopenharmony_ci	/* ICE_FLOW_FIELD_IDX_IPV6_DA */
6462306a36Sopenharmony_ci	ICE_FLOW_FLD_INFO(ICE_FLOW_SEG_HDR_IPV6, 24, sizeof(struct in6_addr)),
6562306a36Sopenharmony_ci	/* Transport */
6662306a36Sopenharmony_ci	/* ICE_FLOW_FIELD_IDX_TCP_SRC_PORT */
6762306a36Sopenharmony_ci	ICE_FLOW_FLD_INFO(ICE_FLOW_SEG_HDR_TCP, 0, sizeof(__be16)),
6862306a36Sopenharmony_ci	/* ICE_FLOW_FIELD_IDX_TCP_DST_PORT */
6962306a36Sopenharmony_ci	ICE_FLOW_FLD_INFO(ICE_FLOW_SEG_HDR_TCP, 2, sizeof(__be16)),
7062306a36Sopenharmony_ci	/* ICE_FLOW_FIELD_IDX_UDP_SRC_PORT */
7162306a36Sopenharmony_ci	ICE_FLOW_FLD_INFO(ICE_FLOW_SEG_HDR_UDP, 0, sizeof(__be16)),
7262306a36Sopenharmony_ci	/* ICE_FLOW_FIELD_IDX_UDP_DST_PORT */
7362306a36Sopenharmony_ci	ICE_FLOW_FLD_INFO(ICE_FLOW_SEG_HDR_UDP, 2, sizeof(__be16)),
7462306a36Sopenharmony_ci	/* ICE_FLOW_FIELD_IDX_SCTP_SRC_PORT */
7562306a36Sopenharmony_ci	ICE_FLOW_FLD_INFO(ICE_FLOW_SEG_HDR_SCTP, 0, sizeof(__be16)),
7662306a36Sopenharmony_ci	/* ICE_FLOW_FIELD_IDX_SCTP_DST_PORT */
7762306a36Sopenharmony_ci	ICE_FLOW_FLD_INFO(ICE_FLOW_SEG_HDR_SCTP, 2, sizeof(__be16)),
7862306a36Sopenharmony_ci	/* ICE_FLOW_FIELD_IDX_TCP_FLAGS */
7962306a36Sopenharmony_ci	ICE_FLOW_FLD_INFO(ICE_FLOW_SEG_HDR_TCP, 13, 1),
8062306a36Sopenharmony_ci	/* ARP */
8162306a36Sopenharmony_ci	/* ICE_FLOW_FIELD_IDX_ARP_SIP */
8262306a36Sopenharmony_ci	ICE_FLOW_FLD_INFO(ICE_FLOW_SEG_HDR_ARP, 14, sizeof(struct in_addr)),
8362306a36Sopenharmony_ci	/* ICE_FLOW_FIELD_IDX_ARP_DIP */
8462306a36Sopenharmony_ci	ICE_FLOW_FLD_INFO(ICE_FLOW_SEG_HDR_ARP, 24, sizeof(struct in_addr)),
8562306a36Sopenharmony_ci	/* ICE_FLOW_FIELD_IDX_ARP_SHA */
8662306a36Sopenharmony_ci	ICE_FLOW_FLD_INFO(ICE_FLOW_SEG_HDR_ARP, 8, ETH_ALEN),
8762306a36Sopenharmony_ci	/* ICE_FLOW_FIELD_IDX_ARP_DHA */
8862306a36Sopenharmony_ci	ICE_FLOW_FLD_INFO(ICE_FLOW_SEG_HDR_ARP, 18, ETH_ALEN),
8962306a36Sopenharmony_ci	/* ICE_FLOW_FIELD_IDX_ARP_OP */
9062306a36Sopenharmony_ci	ICE_FLOW_FLD_INFO(ICE_FLOW_SEG_HDR_ARP, 6, sizeof(__be16)),
9162306a36Sopenharmony_ci	/* ICMP */
9262306a36Sopenharmony_ci	/* ICE_FLOW_FIELD_IDX_ICMP_TYPE */
9362306a36Sopenharmony_ci	ICE_FLOW_FLD_INFO(ICE_FLOW_SEG_HDR_ICMP, 0, 1),
9462306a36Sopenharmony_ci	/* ICE_FLOW_FIELD_IDX_ICMP_CODE */
9562306a36Sopenharmony_ci	ICE_FLOW_FLD_INFO(ICE_FLOW_SEG_HDR_ICMP, 1, 1),
9662306a36Sopenharmony_ci	/* GRE */
9762306a36Sopenharmony_ci	/* ICE_FLOW_FIELD_IDX_GRE_KEYID */
9862306a36Sopenharmony_ci	ICE_FLOW_FLD_INFO(ICE_FLOW_SEG_HDR_GRE, 12,
9962306a36Sopenharmony_ci			  sizeof_field(struct gre_full_hdr, key)),
10062306a36Sopenharmony_ci	/* GTP */
10162306a36Sopenharmony_ci	/* ICE_FLOW_FIELD_IDX_GTPC_TEID */
10262306a36Sopenharmony_ci	ICE_FLOW_FLD_INFO(ICE_FLOW_SEG_HDR_GTPC_TEID, 12, sizeof(__be32)),
10362306a36Sopenharmony_ci	/* ICE_FLOW_FIELD_IDX_GTPU_IP_TEID */
10462306a36Sopenharmony_ci	ICE_FLOW_FLD_INFO(ICE_FLOW_SEG_HDR_GTPU_IP, 12, sizeof(__be32)),
10562306a36Sopenharmony_ci	/* ICE_FLOW_FIELD_IDX_GTPU_EH_TEID */
10662306a36Sopenharmony_ci	ICE_FLOW_FLD_INFO(ICE_FLOW_SEG_HDR_GTPU_EH, 12, sizeof(__be32)),
10762306a36Sopenharmony_ci	/* ICE_FLOW_FIELD_IDX_GTPU_EH_QFI */
10862306a36Sopenharmony_ci	ICE_FLOW_FLD_INFO_MSK(ICE_FLOW_SEG_HDR_GTPU_EH, 22, sizeof(__be16),
10962306a36Sopenharmony_ci			      0x3f00),
11062306a36Sopenharmony_ci	/* ICE_FLOW_FIELD_IDX_GTPU_UP_TEID */
11162306a36Sopenharmony_ci	ICE_FLOW_FLD_INFO(ICE_FLOW_SEG_HDR_GTPU_UP, 12, sizeof(__be32)),
11262306a36Sopenharmony_ci	/* ICE_FLOW_FIELD_IDX_GTPU_DWN_TEID */
11362306a36Sopenharmony_ci	ICE_FLOW_FLD_INFO(ICE_FLOW_SEG_HDR_GTPU_DWN, 12, sizeof(__be32)),
11462306a36Sopenharmony_ci	/* PPPoE */
11562306a36Sopenharmony_ci	/* ICE_FLOW_FIELD_IDX_PPPOE_SESS_ID */
11662306a36Sopenharmony_ci	ICE_FLOW_FLD_INFO(ICE_FLOW_SEG_HDR_PPPOE, 2, sizeof(__be16)),
11762306a36Sopenharmony_ci	/* PFCP */
11862306a36Sopenharmony_ci	/* ICE_FLOW_FIELD_IDX_PFCP_SEID */
11962306a36Sopenharmony_ci	ICE_FLOW_FLD_INFO(ICE_FLOW_SEG_HDR_PFCP_SESSION, 12, sizeof(__be64)),
12062306a36Sopenharmony_ci	/* L2TPv3 */
12162306a36Sopenharmony_ci	/* ICE_FLOW_FIELD_IDX_L2TPV3_SESS_ID */
12262306a36Sopenharmony_ci	ICE_FLOW_FLD_INFO(ICE_FLOW_SEG_HDR_L2TPV3, 0, sizeof(__be32)),
12362306a36Sopenharmony_ci	/* ESP */
12462306a36Sopenharmony_ci	/* ICE_FLOW_FIELD_IDX_ESP_SPI */
12562306a36Sopenharmony_ci	ICE_FLOW_FLD_INFO(ICE_FLOW_SEG_HDR_ESP, 0, sizeof(__be32)),
12662306a36Sopenharmony_ci	/* AH */
12762306a36Sopenharmony_ci	/* ICE_FLOW_FIELD_IDX_AH_SPI */
12862306a36Sopenharmony_ci	ICE_FLOW_FLD_INFO(ICE_FLOW_SEG_HDR_AH, 4, sizeof(__be32)),
12962306a36Sopenharmony_ci	/* NAT_T_ESP */
13062306a36Sopenharmony_ci	/* ICE_FLOW_FIELD_IDX_NAT_T_ESP_SPI */
13162306a36Sopenharmony_ci	ICE_FLOW_FLD_INFO(ICE_FLOW_SEG_HDR_NAT_T_ESP, 8, sizeof(__be32)),
13262306a36Sopenharmony_ci};
13362306a36Sopenharmony_ci
13462306a36Sopenharmony_ci/* Bitmaps indicating relevant packet types for a particular protocol header
13562306a36Sopenharmony_ci *
13662306a36Sopenharmony_ci * Packet types for packets with an Outer/First/Single MAC header
13762306a36Sopenharmony_ci */
13862306a36Sopenharmony_cistatic const u32 ice_ptypes_mac_ofos[] = {
13962306a36Sopenharmony_ci	0xFDC00846, 0xBFBF7F7E, 0xF70001DF, 0xFEFDFDFB,
14062306a36Sopenharmony_ci	0x0000077E, 0x00000000, 0x00000000, 0x00000000,
14162306a36Sopenharmony_ci	0x00400000, 0x03FFF000, 0x7FFFFFE0, 0x00000000,
14262306a36Sopenharmony_ci	0x00000000, 0x00000000, 0x00000000, 0x00000000,
14362306a36Sopenharmony_ci	0x00000000, 0x00000000, 0x00000000, 0x00000000,
14462306a36Sopenharmony_ci	0x00000000, 0x00000000, 0x00000000, 0x00000000,
14562306a36Sopenharmony_ci	0x00000000, 0x00000000, 0x00000000, 0x00000000,
14662306a36Sopenharmony_ci	0x00000000, 0x00000000, 0x00000000, 0x00000000,
14762306a36Sopenharmony_ci};
14862306a36Sopenharmony_ci
14962306a36Sopenharmony_ci/* Packet types for packets with an Innermost/Last MAC VLAN header */
15062306a36Sopenharmony_cistatic const u32 ice_ptypes_macvlan_il[] = {
15162306a36Sopenharmony_ci	0x00000000, 0xBC000000, 0x000001DF, 0xF0000000,
15262306a36Sopenharmony_ci	0x0000077E, 0x00000000, 0x00000000, 0x00000000,
15362306a36Sopenharmony_ci	0x00000000, 0x00000000, 0x00000000, 0x00000000,
15462306a36Sopenharmony_ci	0x00000000, 0x00000000, 0x00000000, 0x00000000,
15562306a36Sopenharmony_ci	0x00000000, 0x00000000, 0x00000000, 0x00000000,
15662306a36Sopenharmony_ci	0x00000000, 0x00000000, 0x00000000, 0x00000000,
15762306a36Sopenharmony_ci	0x00000000, 0x00000000, 0x00000000, 0x00000000,
15862306a36Sopenharmony_ci	0x00000000, 0x00000000, 0x00000000, 0x00000000,
15962306a36Sopenharmony_ci};
16062306a36Sopenharmony_ci
16162306a36Sopenharmony_ci/* Packet types for packets with an Outer/First/Single IPv4 header, does NOT
16262306a36Sopenharmony_ci * include IPv4 other PTYPEs
16362306a36Sopenharmony_ci */
16462306a36Sopenharmony_cistatic const u32 ice_ptypes_ipv4_ofos[] = {
16562306a36Sopenharmony_ci	0x1DC00000, 0x04000800, 0x00000000, 0x00000000,
16662306a36Sopenharmony_ci	0x00000000, 0x00000155, 0x00000000, 0x00000000,
16762306a36Sopenharmony_ci	0x00000000, 0x000FC000, 0x00000000, 0x00000000,
16862306a36Sopenharmony_ci	0x00000000, 0x00000000, 0x00000000, 0x00000000,
16962306a36Sopenharmony_ci	0x00000000, 0x00000000, 0x00000000, 0x00000000,
17062306a36Sopenharmony_ci	0x00000000, 0x00000000, 0x00000000, 0x00000000,
17162306a36Sopenharmony_ci	0x00000000, 0x00000000, 0x00000000, 0x00000000,
17262306a36Sopenharmony_ci	0x00000000, 0x00000000, 0x00000000, 0x00000000,
17362306a36Sopenharmony_ci};
17462306a36Sopenharmony_ci
17562306a36Sopenharmony_ci/* Packet types for packets with an Outer/First/Single IPv4 header, includes
17662306a36Sopenharmony_ci * IPv4 other PTYPEs
17762306a36Sopenharmony_ci */
17862306a36Sopenharmony_cistatic const u32 ice_ptypes_ipv4_ofos_all[] = {
17962306a36Sopenharmony_ci	0x1DC00000, 0x04000800, 0x00000000, 0x00000000,
18062306a36Sopenharmony_ci	0x00000000, 0x00000155, 0x00000000, 0x00000000,
18162306a36Sopenharmony_ci	0x00000000, 0x000FC000, 0x83E0F800, 0x00000101,
18262306a36Sopenharmony_ci	0x00000000, 0x00000000, 0x00000000, 0x00000000,
18362306a36Sopenharmony_ci	0x00000000, 0x00000000, 0x00000000, 0x00000000,
18462306a36Sopenharmony_ci	0x00000000, 0x00000000, 0x00000000, 0x00000000,
18562306a36Sopenharmony_ci	0x00000000, 0x00000000, 0x00000000, 0x00000000,
18662306a36Sopenharmony_ci	0x00000000, 0x00000000, 0x00000000, 0x00000000,
18762306a36Sopenharmony_ci};
18862306a36Sopenharmony_ci
18962306a36Sopenharmony_ci/* Packet types for packets with an Innermost/Last IPv4 header */
19062306a36Sopenharmony_cistatic const u32 ice_ptypes_ipv4_il[] = {
19162306a36Sopenharmony_ci	0xE0000000, 0xB807700E, 0x80000003, 0xE01DC03B,
19262306a36Sopenharmony_ci	0x0000000E, 0x00000000, 0x00000000, 0x00000000,
19362306a36Sopenharmony_ci	0x00000000, 0x00000000, 0x001FF800, 0x00000000,
19462306a36Sopenharmony_ci	0x00000000, 0x00000000, 0x00000000, 0x00000000,
19562306a36Sopenharmony_ci	0x00000000, 0x00000000, 0x00000000, 0x00000000,
19662306a36Sopenharmony_ci	0x00000000, 0x00000000, 0x00000000, 0x00000000,
19762306a36Sopenharmony_ci	0x00000000, 0x00000000, 0x00000000, 0x00000000,
19862306a36Sopenharmony_ci	0x00000000, 0x00000000, 0x00000000, 0x00000000,
19962306a36Sopenharmony_ci};
20062306a36Sopenharmony_ci
20162306a36Sopenharmony_ci/* Packet types for packets with an Outer/First/Single IPv6 header, does NOT
20262306a36Sopenharmony_ci * include IPv6 other PTYPEs
20362306a36Sopenharmony_ci */
20462306a36Sopenharmony_cistatic const u32 ice_ptypes_ipv6_ofos[] = {
20562306a36Sopenharmony_ci	0x00000000, 0x00000000, 0x77000000, 0x10002000,
20662306a36Sopenharmony_ci	0x00000000, 0x000002AA, 0x00000000, 0x00000000,
20762306a36Sopenharmony_ci	0x00000000, 0x03F00000, 0x00000000, 0x00000000,
20862306a36Sopenharmony_ci	0x00000000, 0x00000000, 0x00000000, 0x00000000,
20962306a36Sopenharmony_ci	0x00000000, 0x00000000, 0x00000000, 0x00000000,
21062306a36Sopenharmony_ci	0x00000000, 0x00000000, 0x00000000, 0x00000000,
21162306a36Sopenharmony_ci	0x00000000, 0x00000000, 0x00000000, 0x00000000,
21262306a36Sopenharmony_ci	0x00000000, 0x00000000, 0x00000000, 0x00000000,
21362306a36Sopenharmony_ci};
21462306a36Sopenharmony_ci
21562306a36Sopenharmony_ci/* Packet types for packets with an Outer/First/Single IPv6 header, includes
21662306a36Sopenharmony_ci * IPv6 other PTYPEs
21762306a36Sopenharmony_ci */
21862306a36Sopenharmony_cistatic const u32 ice_ptypes_ipv6_ofos_all[] = {
21962306a36Sopenharmony_ci	0x00000000, 0x00000000, 0x77000000, 0x10002000,
22062306a36Sopenharmony_ci	0x00000000, 0x000002AA, 0x00000000, 0x00000000,
22162306a36Sopenharmony_ci	0x00080F00, 0x03F00000, 0x7C1F0000, 0x00000206,
22262306a36Sopenharmony_ci	0x00000000, 0x00000000, 0x00000000, 0x00000000,
22362306a36Sopenharmony_ci	0x00000000, 0x00000000, 0x00000000, 0x00000000,
22462306a36Sopenharmony_ci	0x00000000, 0x00000000, 0x00000000, 0x00000000,
22562306a36Sopenharmony_ci	0x00000000, 0x00000000, 0x00000000, 0x00000000,
22662306a36Sopenharmony_ci	0x00000000, 0x00000000, 0x00000000, 0x00000000,
22762306a36Sopenharmony_ci};
22862306a36Sopenharmony_ci
22962306a36Sopenharmony_ci/* Packet types for packets with an Innermost/Last IPv6 header */
23062306a36Sopenharmony_cistatic const u32 ice_ptypes_ipv6_il[] = {
23162306a36Sopenharmony_ci	0x00000000, 0x03B80770, 0x000001DC, 0x0EE00000,
23262306a36Sopenharmony_ci	0x00000770, 0x00000000, 0x00000000, 0x00000000,
23362306a36Sopenharmony_ci	0x00000000, 0x00000000, 0x7FE00000, 0x00000000,
23462306a36Sopenharmony_ci	0x00000000, 0x00000000, 0x00000000, 0x00000000,
23562306a36Sopenharmony_ci	0x00000000, 0x00000000, 0x00000000, 0x00000000,
23662306a36Sopenharmony_ci	0x00000000, 0x00000000, 0x00000000, 0x00000000,
23762306a36Sopenharmony_ci	0x00000000, 0x00000000, 0x00000000, 0x00000000,
23862306a36Sopenharmony_ci	0x00000000, 0x00000000, 0x00000000, 0x00000000,
23962306a36Sopenharmony_ci};
24062306a36Sopenharmony_ci
24162306a36Sopenharmony_ci/* Packet types for packets with an Outer/First/Single IPv4 header - no L4 */
24262306a36Sopenharmony_cistatic const u32 ice_ptypes_ipv4_ofos_no_l4[] = {
24362306a36Sopenharmony_ci	0x10C00000, 0x04000800, 0x00000000, 0x00000000,
24462306a36Sopenharmony_ci	0x00000000, 0x00000000, 0x00000000, 0x00000000,
24562306a36Sopenharmony_ci	0x00000000, 0x00000000, 0x00000000, 0x00000000,
24662306a36Sopenharmony_ci	0x00000000, 0x00000000, 0x00000000, 0x00000000,
24762306a36Sopenharmony_ci	0x00000000, 0x00000000, 0x00000000, 0x00000000,
24862306a36Sopenharmony_ci	0x00000000, 0x00000000, 0x00000000, 0x00000000,
24962306a36Sopenharmony_ci	0x00000000, 0x00000000, 0x00000000, 0x00000000,
25062306a36Sopenharmony_ci	0x00000000, 0x00000000, 0x00000000, 0x00000000,
25162306a36Sopenharmony_ci};
25262306a36Sopenharmony_ci
25362306a36Sopenharmony_ci/* Packet types for packets with an Outermost/First ARP header */
25462306a36Sopenharmony_cistatic const u32 ice_ptypes_arp_of[] = {
25562306a36Sopenharmony_ci	0x00000800, 0x00000000, 0x00000000, 0x00000000,
25662306a36Sopenharmony_ci	0x00000000, 0x00000000, 0x00000000, 0x00000000,
25762306a36Sopenharmony_ci	0x00000000, 0x00000000, 0x00000000, 0x00000000,
25862306a36Sopenharmony_ci	0x00000000, 0x00000000, 0x00000000, 0x00000000,
25962306a36Sopenharmony_ci	0x00000000, 0x00000000, 0x00000000, 0x00000000,
26062306a36Sopenharmony_ci	0x00000000, 0x00000000, 0x00000000, 0x00000000,
26162306a36Sopenharmony_ci	0x00000000, 0x00000000, 0x00000000, 0x00000000,
26262306a36Sopenharmony_ci	0x00000000, 0x00000000, 0x00000000, 0x00000000,
26362306a36Sopenharmony_ci};
26462306a36Sopenharmony_ci
26562306a36Sopenharmony_ci/* Packet types for packets with an Innermost/Last IPv4 header - no L4 */
26662306a36Sopenharmony_cistatic const u32 ice_ptypes_ipv4_il_no_l4[] = {
26762306a36Sopenharmony_ci	0x60000000, 0x18043008, 0x80000002, 0x6010c021,
26862306a36Sopenharmony_ci	0x00000008, 0x00000000, 0x00000000, 0x00000000,
26962306a36Sopenharmony_ci	0x00000000, 0x00000000, 0x00000000, 0x00000000,
27062306a36Sopenharmony_ci	0x00000000, 0x00000000, 0x00000000, 0x00000000,
27162306a36Sopenharmony_ci	0x00000000, 0x00000000, 0x00000000, 0x00000000,
27262306a36Sopenharmony_ci	0x00000000, 0x00000000, 0x00000000, 0x00000000,
27362306a36Sopenharmony_ci	0x00000000, 0x00000000, 0x00000000, 0x00000000,
27462306a36Sopenharmony_ci	0x00000000, 0x00000000, 0x00000000, 0x00000000,
27562306a36Sopenharmony_ci};
27662306a36Sopenharmony_ci
27762306a36Sopenharmony_ci/* Packet types for packets with an Outer/First/Single IPv6 header - no L4 */
27862306a36Sopenharmony_cistatic const u32 ice_ptypes_ipv6_ofos_no_l4[] = {
27962306a36Sopenharmony_ci	0x00000000, 0x00000000, 0x43000000, 0x10002000,
28062306a36Sopenharmony_ci	0x00000000, 0x00000000, 0x00000000, 0x00000000,
28162306a36Sopenharmony_ci	0x00000000, 0x00000000, 0x00000000, 0x00000000,
28262306a36Sopenharmony_ci	0x00000000, 0x00000000, 0x00000000, 0x00000000,
28362306a36Sopenharmony_ci	0x00000000, 0x00000000, 0x00000000, 0x00000000,
28462306a36Sopenharmony_ci	0x00000000, 0x00000000, 0x00000000, 0x00000000,
28562306a36Sopenharmony_ci	0x00000000, 0x00000000, 0x00000000, 0x00000000,
28662306a36Sopenharmony_ci	0x00000000, 0x00000000, 0x00000000, 0x00000000,
28762306a36Sopenharmony_ci};
28862306a36Sopenharmony_ci
28962306a36Sopenharmony_ci/* Packet types for packets with an Innermost/Last IPv6 header - no L4 */
29062306a36Sopenharmony_cistatic const u32 ice_ptypes_ipv6_il_no_l4[] = {
29162306a36Sopenharmony_ci	0x00000000, 0x02180430, 0x0000010c, 0x086010c0,
29262306a36Sopenharmony_ci	0x00000430, 0x00000000, 0x00000000, 0x00000000,
29362306a36Sopenharmony_ci	0x00000000, 0x00000000, 0x00000000, 0x00000000,
29462306a36Sopenharmony_ci	0x00000000, 0x00000000, 0x00000000, 0x00000000,
29562306a36Sopenharmony_ci	0x00000000, 0x00000000, 0x00000000, 0x00000000,
29662306a36Sopenharmony_ci	0x00000000, 0x00000000, 0x00000000, 0x00000000,
29762306a36Sopenharmony_ci	0x00000000, 0x00000000, 0x00000000, 0x00000000,
29862306a36Sopenharmony_ci	0x00000000, 0x00000000, 0x00000000, 0x00000000,
29962306a36Sopenharmony_ci};
30062306a36Sopenharmony_ci
30162306a36Sopenharmony_ci/* UDP Packet types for non-tunneled packets or tunneled
30262306a36Sopenharmony_ci * packets with inner UDP.
30362306a36Sopenharmony_ci */
30462306a36Sopenharmony_cistatic const u32 ice_ptypes_udp_il[] = {
30562306a36Sopenharmony_ci	0x81000000, 0x20204040, 0x04000010, 0x80810102,
30662306a36Sopenharmony_ci	0x00000040, 0x00000000, 0x00000000, 0x00000000,
30762306a36Sopenharmony_ci	0x00000000, 0x00410000, 0x90842000, 0x00000007,
30862306a36Sopenharmony_ci	0x00000000, 0x00000000, 0x00000000, 0x00000000,
30962306a36Sopenharmony_ci	0x00000000, 0x00000000, 0x00000000, 0x00000000,
31062306a36Sopenharmony_ci	0x00000000, 0x00000000, 0x00000000, 0x00000000,
31162306a36Sopenharmony_ci	0x00000000, 0x00000000, 0x00000000, 0x00000000,
31262306a36Sopenharmony_ci	0x00000000, 0x00000000, 0x00000000, 0x00000000,
31362306a36Sopenharmony_ci};
31462306a36Sopenharmony_ci
31562306a36Sopenharmony_ci/* Packet types for packets with an Innermost/Last TCP header */
31662306a36Sopenharmony_cistatic const u32 ice_ptypes_tcp_il[] = {
31762306a36Sopenharmony_ci	0x04000000, 0x80810102, 0x10000040, 0x02040408,
31862306a36Sopenharmony_ci	0x00000102, 0x00000000, 0x00000000, 0x00000000,
31962306a36Sopenharmony_ci	0x00000000, 0x00820000, 0x21084000, 0x00000000,
32062306a36Sopenharmony_ci	0x00000000, 0x00000000, 0x00000000, 0x00000000,
32162306a36Sopenharmony_ci	0x00000000, 0x00000000, 0x00000000, 0x00000000,
32262306a36Sopenharmony_ci	0x00000000, 0x00000000, 0x00000000, 0x00000000,
32362306a36Sopenharmony_ci	0x00000000, 0x00000000, 0x00000000, 0x00000000,
32462306a36Sopenharmony_ci	0x00000000, 0x00000000, 0x00000000, 0x00000000,
32562306a36Sopenharmony_ci};
32662306a36Sopenharmony_ci
32762306a36Sopenharmony_ci/* Packet types for packets with an Innermost/Last SCTP header */
32862306a36Sopenharmony_cistatic const u32 ice_ptypes_sctp_il[] = {
32962306a36Sopenharmony_ci	0x08000000, 0x01020204, 0x20000081, 0x04080810,
33062306a36Sopenharmony_ci	0x00000204, 0x00000000, 0x00000000, 0x00000000,
33162306a36Sopenharmony_ci	0x00000000, 0x01040000, 0x00000000, 0x00000000,
33262306a36Sopenharmony_ci	0x00000000, 0x00000000, 0x00000000, 0x00000000,
33362306a36Sopenharmony_ci	0x00000000, 0x00000000, 0x00000000, 0x00000000,
33462306a36Sopenharmony_ci	0x00000000, 0x00000000, 0x00000000, 0x00000000,
33562306a36Sopenharmony_ci	0x00000000, 0x00000000, 0x00000000, 0x00000000,
33662306a36Sopenharmony_ci	0x00000000, 0x00000000, 0x00000000, 0x00000000,
33762306a36Sopenharmony_ci};
33862306a36Sopenharmony_ci
33962306a36Sopenharmony_ci/* Packet types for packets with an Outermost/First ICMP header */
34062306a36Sopenharmony_cistatic const u32 ice_ptypes_icmp_of[] = {
34162306a36Sopenharmony_ci	0x10000000, 0x00000000, 0x00000000, 0x00000000,
34262306a36Sopenharmony_ci	0x00000000, 0x00000000, 0x00000000, 0x00000000,
34362306a36Sopenharmony_ci	0x00000000, 0x00000000, 0x00000000, 0x00000000,
34462306a36Sopenharmony_ci	0x00000000, 0x00000000, 0x00000000, 0x00000000,
34562306a36Sopenharmony_ci	0x00000000, 0x00000000, 0x00000000, 0x00000000,
34662306a36Sopenharmony_ci	0x00000000, 0x00000000, 0x00000000, 0x00000000,
34762306a36Sopenharmony_ci	0x00000000, 0x00000000, 0x00000000, 0x00000000,
34862306a36Sopenharmony_ci	0x00000000, 0x00000000, 0x00000000, 0x00000000,
34962306a36Sopenharmony_ci};
35062306a36Sopenharmony_ci
35162306a36Sopenharmony_ci/* Packet types for packets with an Innermost/Last ICMP header */
35262306a36Sopenharmony_cistatic const u32 ice_ptypes_icmp_il[] = {
35362306a36Sopenharmony_ci	0x00000000, 0x02040408, 0x40000102, 0x08101020,
35462306a36Sopenharmony_ci	0x00000408, 0x00000000, 0x00000000, 0x00000000,
35562306a36Sopenharmony_ci	0x00000000, 0x00000000, 0x42108000, 0x00000000,
35662306a36Sopenharmony_ci	0x00000000, 0x00000000, 0x00000000, 0x00000000,
35762306a36Sopenharmony_ci	0x00000000, 0x00000000, 0x00000000, 0x00000000,
35862306a36Sopenharmony_ci	0x00000000, 0x00000000, 0x00000000, 0x00000000,
35962306a36Sopenharmony_ci	0x00000000, 0x00000000, 0x00000000, 0x00000000,
36062306a36Sopenharmony_ci	0x00000000, 0x00000000, 0x00000000, 0x00000000,
36162306a36Sopenharmony_ci};
36262306a36Sopenharmony_ci
36362306a36Sopenharmony_ci/* Packet types for packets with an Outermost/First GRE header */
36462306a36Sopenharmony_cistatic const u32 ice_ptypes_gre_of[] = {
36562306a36Sopenharmony_ci	0x00000000, 0xBFBF7800, 0x000001DF, 0xFEFDE000,
36662306a36Sopenharmony_ci	0x0000017E, 0x00000000, 0x00000000, 0x00000000,
36762306a36Sopenharmony_ci	0x00000000, 0x00000000, 0x00000000, 0x00000000,
36862306a36Sopenharmony_ci	0x00000000, 0x00000000, 0x00000000, 0x00000000,
36962306a36Sopenharmony_ci	0x00000000, 0x00000000, 0x00000000, 0x00000000,
37062306a36Sopenharmony_ci	0x00000000, 0x00000000, 0x00000000, 0x00000000,
37162306a36Sopenharmony_ci	0x00000000, 0x00000000, 0x00000000, 0x00000000,
37262306a36Sopenharmony_ci	0x00000000, 0x00000000, 0x00000000, 0x00000000,
37362306a36Sopenharmony_ci};
37462306a36Sopenharmony_ci
37562306a36Sopenharmony_ci/* Packet types for packets with an Innermost/Last MAC header */
37662306a36Sopenharmony_cistatic const u32 ice_ptypes_mac_il[] = {
37762306a36Sopenharmony_ci	0x00000000, 0x00000000, 0x00000000, 0x00000000,
37862306a36Sopenharmony_ci	0x00000000, 0x00000000, 0x00000000, 0x00000000,
37962306a36Sopenharmony_ci	0x00000000, 0x00000000, 0x00000000, 0x00000000,
38062306a36Sopenharmony_ci	0x00000000, 0x00000000, 0x00000000, 0x00000000,
38162306a36Sopenharmony_ci	0x00000000, 0x00000000, 0x00000000, 0x00000000,
38262306a36Sopenharmony_ci	0x00000000, 0x00000000, 0x00000000, 0x00000000,
38362306a36Sopenharmony_ci	0x00000000, 0x00000000, 0x00000000, 0x00000000,
38462306a36Sopenharmony_ci	0x00000000, 0x00000000, 0x00000000, 0x00000000,
38562306a36Sopenharmony_ci};
38662306a36Sopenharmony_ci
38762306a36Sopenharmony_ci/* Packet types for GTPC */
38862306a36Sopenharmony_cistatic const u32 ice_ptypes_gtpc[] = {
38962306a36Sopenharmony_ci	0x00000000, 0x00000000, 0x00000000, 0x00000000,
39062306a36Sopenharmony_ci	0x00000000, 0x00000000, 0x00000000, 0x00000000,
39162306a36Sopenharmony_ci	0x00000000, 0x00000000, 0x00000180, 0x00000000,
39262306a36Sopenharmony_ci	0x00000000, 0x00000000, 0x00000000, 0x00000000,
39362306a36Sopenharmony_ci	0x00000000, 0x00000000, 0x00000000, 0x00000000,
39462306a36Sopenharmony_ci	0x00000000, 0x00000000, 0x00000000, 0x00000000,
39562306a36Sopenharmony_ci	0x00000000, 0x00000000, 0x00000000, 0x00000000,
39662306a36Sopenharmony_ci	0x00000000, 0x00000000, 0x00000000, 0x00000000,
39762306a36Sopenharmony_ci};
39862306a36Sopenharmony_ci
39962306a36Sopenharmony_ci/* Packet types for GTPC with TEID */
40062306a36Sopenharmony_cistatic const u32 ice_ptypes_gtpc_tid[] = {
40162306a36Sopenharmony_ci	0x00000000, 0x00000000, 0x00000000, 0x00000000,
40262306a36Sopenharmony_ci	0x00000000, 0x00000000, 0x00000000, 0x00000000,
40362306a36Sopenharmony_ci	0x00000000, 0x00000000, 0x00000060, 0x00000000,
40462306a36Sopenharmony_ci	0x00000000, 0x00000000, 0x00000000, 0x00000000,
40562306a36Sopenharmony_ci	0x00000000, 0x00000000, 0x00000000, 0x00000000,
40662306a36Sopenharmony_ci	0x00000000, 0x00000000, 0x00000000, 0x00000000,
40762306a36Sopenharmony_ci	0x00000000, 0x00000000, 0x00000000, 0x00000000,
40862306a36Sopenharmony_ci	0x00000000, 0x00000000, 0x00000000, 0x00000000,
40962306a36Sopenharmony_ci};
41062306a36Sopenharmony_ci
41162306a36Sopenharmony_ci/* Packet types for GTPU */
41262306a36Sopenharmony_cistatic const struct ice_ptype_attributes ice_attr_gtpu_eh[] = {
41362306a36Sopenharmony_ci	{ ICE_MAC_IPV4_GTPU_IPV4_FRAG,	  ICE_PTYPE_ATTR_GTP_PDU_EH },
41462306a36Sopenharmony_ci	{ ICE_MAC_IPV4_GTPU_IPV4_PAY,	  ICE_PTYPE_ATTR_GTP_PDU_EH },
41562306a36Sopenharmony_ci	{ ICE_MAC_IPV4_GTPU_IPV4_UDP_PAY, ICE_PTYPE_ATTR_GTP_PDU_EH },
41662306a36Sopenharmony_ci	{ ICE_MAC_IPV4_GTPU_IPV4_TCP,	  ICE_PTYPE_ATTR_GTP_PDU_EH },
41762306a36Sopenharmony_ci	{ ICE_MAC_IPV4_GTPU_IPV4_ICMP,	  ICE_PTYPE_ATTR_GTP_PDU_EH },
41862306a36Sopenharmony_ci	{ ICE_MAC_IPV6_GTPU_IPV4_FRAG,	  ICE_PTYPE_ATTR_GTP_PDU_EH },
41962306a36Sopenharmony_ci	{ ICE_MAC_IPV6_GTPU_IPV4_PAY,	  ICE_PTYPE_ATTR_GTP_PDU_EH },
42062306a36Sopenharmony_ci	{ ICE_MAC_IPV6_GTPU_IPV4_UDP_PAY, ICE_PTYPE_ATTR_GTP_PDU_EH },
42162306a36Sopenharmony_ci	{ ICE_MAC_IPV6_GTPU_IPV4_TCP,	  ICE_PTYPE_ATTR_GTP_PDU_EH },
42262306a36Sopenharmony_ci	{ ICE_MAC_IPV6_GTPU_IPV4_ICMP,	  ICE_PTYPE_ATTR_GTP_PDU_EH },
42362306a36Sopenharmony_ci	{ ICE_MAC_IPV4_GTPU_IPV6_FRAG,	  ICE_PTYPE_ATTR_GTP_PDU_EH },
42462306a36Sopenharmony_ci	{ ICE_MAC_IPV4_GTPU_IPV6_PAY,	  ICE_PTYPE_ATTR_GTP_PDU_EH },
42562306a36Sopenharmony_ci	{ ICE_MAC_IPV4_GTPU_IPV6_UDP_PAY, ICE_PTYPE_ATTR_GTP_PDU_EH },
42662306a36Sopenharmony_ci	{ ICE_MAC_IPV4_GTPU_IPV6_TCP,	  ICE_PTYPE_ATTR_GTP_PDU_EH },
42762306a36Sopenharmony_ci	{ ICE_MAC_IPV4_GTPU_IPV6_ICMPV6,  ICE_PTYPE_ATTR_GTP_PDU_EH },
42862306a36Sopenharmony_ci	{ ICE_MAC_IPV6_GTPU_IPV6_FRAG,	  ICE_PTYPE_ATTR_GTP_PDU_EH },
42962306a36Sopenharmony_ci	{ ICE_MAC_IPV6_GTPU_IPV6_PAY,	  ICE_PTYPE_ATTR_GTP_PDU_EH },
43062306a36Sopenharmony_ci	{ ICE_MAC_IPV6_GTPU_IPV6_UDP_PAY, ICE_PTYPE_ATTR_GTP_PDU_EH },
43162306a36Sopenharmony_ci	{ ICE_MAC_IPV6_GTPU_IPV6_TCP,	  ICE_PTYPE_ATTR_GTP_PDU_EH },
43262306a36Sopenharmony_ci	{ ICE_MAC_IPV6_GTPU_IPV6_ICMPV6,  ICE_PTYPE_ATTR_GTP_PDU_EH },
43362306a36Sopenharmony_ci};
43462306a36Sopenharmony_ci
43562306a36Sopenharmony_cistatic const struct ice_ptype_attributes ice_attr_gtpu_down[] = {
43662306a36Sopenharmony_ci	{ ICE_MAC_IPV4_GTPU_IPV4_FRAG,	  ICE_PTYPE_ATTR_GTP_DOWNLINK },
43762306a36Sopenharmony_ci	{ ICE_MAC_IPV4_GTPU_IPV4_PAY,	  ICE_PTYPE_ATTR_GTP_DOWNLINK },
43862306a36Sopenharmony_ci	{ ICE_MAC_IPV4_GTPU_IPV4_UDP_PAY, ICE_PTYPE_ATTR_GTP_DOWNLINK },
43962306a36Sopenharmony_ci	{ ICE_MAC_IPV4_GTPU_IPV4_TCP,	  ICE_PTYPE_ATTR_GTP_DOWNLINK },
44062306a36Sopenharmony_ci	{ ICE_MAC_IPV4_GTPU_IPV4_ICMP,	  ICE_PTYPE_ATTR_GTP_DOWNLINK },
44162306a36Sopenharmony_ci	{ ICE_MAC_IPV6_GTPU_IPV4_FRAG,	  ICE_PTYPE_ATTR_GTP_DOWNLINK },
44262306a36Sopenharmony_ci	{ ICE_MAC_IPV6_GTPU_IPV4_PAY,	  ICE_PTYPE_ATTR_GTP_DOWNLINK },
44362306a36Sopenharmony_ci	{ ICE_MAC_IPV6_GTPU_IPV4_UDP_PAY, ICE_PTYPE_ATTR_GTP_DOWNLINK },
44462306a36Sopenharmony_ci	{ ICE_MAC_IPV6_GTPU_IPV4_TCP,	  ICE_PTYPE_ATTR_GTP_DOWNLINK },
44562306a36Sopenharmony_ci	{ ICE_MAC_IPV6_GTPU_IPV4_ICMP,	  ICE_PTYPE_ATTR_GTP_DOWNLINK },
44662306a36Sopenharmony_ci	{ ICE_MAC_IPV4_GTPU_IPV6_FRAG,	  ICE_PTYPE_ATTR_GTP_DOWNLINK },
44762306a36Sopenharmony_ci	{ ICE_MAC_IPV4_GTPU_IPV6_PAY,	  ICE_PTYPE_ATTR_GTP_DOWNLINK },
44862306a36Sopenharmony_ci	{ ICE_MAC_IPV4_GTPU_IPV6_UDP_PAY, ICE_PTYPE_ATTR_GTP_DOWNLINK },
44962306a36Sopenharmony_ci	{ ICE_MAC_IPV4_GTPU_IPV6_TCP,	  ICE_PTYPE_ATTR_GTP_DOWNLINK },
45062306a36Sopenharmony_ci	{ ICE_MAC_IPV4_GTPU_IPV6_ICMPV6,  ICE_PTYPE_ATTR_GTP_DOWNLINK },
45162306a36Sopenharmony_ci	{ ICE_MAC_IPV6_GTPU_IPV6_FRAG,	  ICE_PTYPE_ATTR_GTP_DOWNLINK },
45262306a36Sopenharmony_ci	{ ICE_MAC_IPV6_GTPU_IPV6_PAY,	  ICE_PTYPE_ATTR_GTP_DOWNLINK },
45362306a36Sopenharmony_ci	{ ICE_MAC_IPV6_GTPU_IPV6_UDP_PAY, ICE_PTYPE_ATTR_GTP_DOWNLINK },
45462306a36Sopenharmony_ci	{ ICE_MAC_IPV6_GTPU_IPV6_TCP,	  ICE_PTYPE_ATTR_GTP_DOWNLINK },
45562306a36Sopenharmony_ci	{ ICE_MAC_IPV6_GTPU_IPV6_ICMPV6,  ICE_PTYPE_ATTR_GTP_DOWNLINK },
45662306a36Sopenharmony_ci};
45762306a36Sopenharmony_ci
45862306a36Sopenharmony_cistatic const struct ice_ptype_attributes ice_attr_gtpu_up[] = {
45962306a36Sopenharmony_ci	{ ICE_MAC_IPV4_GTPU_IPV4_FRAG,	  ICE_PTYPE_ATTR_GTP_UPLINK },
46062306a36Sopenharmony_ci	{ ICE_MAC_IPV4_GTPU_IPV4_PAY,	  ICE_PTYPE_ATTR_GTP_UPLINK },
46162306a36Sopenharmony_ci	{ ICE_MAC_IPV4_GTPU_IPV4_UDP_PAY, ICE_PTYPE_ATTR_GTP_UPLINK },
46262306a36Sopenharmony_ci	{ ICE_MAC_IPV4_GTPU_IPV4_TCP,	  ICE_PTYPE_ATTR_GTP_UPLINK },
46362306a36Sopenharmony_ci	{ ICE_MAC_IPV4_GTPU_IPV4_ICMP,	  ICE_PTYPE_ATTR_GTP_UPLINK },
46462306a36Sopenharmony_ci	{ ICE_MAC_IPV6_GTPU_IPV4_FRAG,	  ICE_PTYPE_ATTR_GTP_UPLINK },
46562306a36Sopenharmony_ci	{ ICE_MAC_IPV6_GTPU_IPV4_PAY,	  ICE_PTYPE_ATTR_GTP_UPLINK },
46662306a36Sopenharmony_ci	{ ICE_MAC_IPV6_GTPU_IPV4_UDP_PAY, ICE_PTYPE_ATTR_GTP_UPLINK },
46762306a36Sopenharmony_ci	{ ICE_MAC_IPV6_GTPU_IPV4_TCP,	  ICE_PTYPE_ATTR_GTP_UPLINK },
46862306a36Sopenharmony_ci	{ ICE_MAC_IPV6_GTPU_IPV4_ICMP,	  ICE_PTYPE_ATTR_GTP_UPLINK },
46962306a36Sopenharmony_ci	{ ICE_MAC_IPV4_GTPU_IPV6_FRAG,	  ICE_PTYPE_ATTR_GTP_UPLINK },
47062306a36Sopenharmony_ci	{ ICE_MAC_IPV4_GTPU_IPV6_PAY,	  ICE_PTYPE_ATTR_GTP_UPLINK },
47162306a36Sopenharmony_ci	{ ICE_MAC_IPV4_GTPU_IPV6_UDP_PAY, ICE_PTYPE_ATTR_GTP_UPLINK },
47262306a36Sopenharmony_ci	{ ICE_MAC_IPV4_GTPU_IPV6_TCP,	  ICE_PTYPE_ATTR_GTP_UPLINK },
47362306a36Sopenharmony_ci	{ ICE_MAC_IPV4_GTPU_IPV6_ICMPV6,  ICE_PTYPE_ATTR_GTP_UPLINK },
47462306a36Sopenharmony_ci	{ ICE_MAC_IPV6_GTPU_IPV6_FRAG,	  ICE_PTYPE_ATTR_GTP_UPLINK },
47562306a36Sopenharmony_ci	{ ICE_MAC_IPV6_GTPU_IPV6_PAY,	  ICE_PTYPE_ATTR_GTP_UPLINK },
47662306a36Sopenharmony_ci	{ ICE_MAC_IPV6_GTPU_IPV6_UDP_PAY, ICE_PTYPE_ATTR_GTP_UPLINK },
47762306a36Sopenharmony_ci	{ ICE_MAC_IPV6_GTPU_IPV6_TCP,	  ICE_PTYPE_ATTR_GTP_UPLINK },
47862306a36Sopenharmony_ci	{ ICE_MAC_IPV6_GTPU_IPV6_ICMPV6,  ICE_PTYPE_ATTR_GTP_UPLINK },
47962306a36Sopenharmony_ci};
48062306a36Sopenharmony_ci
48162306a36Sopenharmony_cistatic const u32 ice_ptypes_gtpu[] = {
48262306a36Sopenharmony_ci	0x00000000, 0x00000000, 0x00000000, 0x00000000,
48362306a36Sopenharmony_ci	0x00000000, 0x00000000, 0x00000000, 0x00000000,
48462306a36Sopenharmony_ci	0x00000000, 0x00000000, 0x7FFFFE00, 0x00000000,
48562306a36Sopenharmony_ci	0x00000000, 0x00000000, 0x00000000, 0x00000000,
48662306a36Sopenharmony_ci	0x00000000, 0x00000000, 0x00000000, 0x00000000,
48762306a36Sopenharmony_ci	0x00000000, 0x00000000, 0x00000000, 0x00000000,
48862306a36Sopenharmony_ci	0x00000000, 0x00000000, 0x00000000, 0x00000000,
48962306a36Sopenharmony_ci	0x00000000, 0x00000000, 0x00000000, 0x00000000,
49062306a36Sopenharmony_ci};
49162306a36Sopenharmony_ci
49262306a36Sopenharmony_ci/* Packet types for PPPoE */
49362306a36Sopenharmony_cistatic const u32 ice_ptypes_pppoe[] = {
49462306a36Sopenharmony_ci	0x00000000, 0x00000000, 0x00000000, 0x00000000,
49562306a36Sopenharmony_ci	0x00000000, 0x00000000, 0x00000000, 0x00000000,
49662306a36Sopenharmony_ci	0x00000000, 0x03ffe000, 0x00000000, 0x00000000,
49762306a36Sopenharmony_ci	0x00000000, 0x00000000, 0x00000000, 0x00000000,
49862306a36Sopenharmony_ci	0x00000000, 0x00000000, 0x00000000, 0x00000000,
49962306a36Sopenharmony_ci	0x00000000, 0x00000000, 0x00000000, 0x00000000,
50062306a36Sopenharmony_ci	0x00000000, 0x00000000, 0x00000000, 0x00000000,
50162306a36Sopenharmony_ci	0x00000000, 0x00000000, 0x00000000, 0x00000000,
50262306a36Sopenharmony_ci};
50362306a36Sopenharmony_ci
50462306a36Sopenharmony_ci/* Packet types for packets with PFCP NODE header */
50562306a36Sopenharmony_cistatic const u32 ice_ptypes_pfcp_node[] = {
50662306a36Sopenharmony_ci	0x00000000, 0x00000000, 0x00000000, 0x00000000,
50762306a36Sopenharmony_ci	0x00000000, 0x00000000, 0x00000000, 0x00000000,
50862306a36Sopenharmony_ci	0x00000000, 0x00000000, 0x80000000, 0x00000002,
50962306a36Sopenharmony_ci	0x00000000, 0x00000000, 0x00000000, 0x00000000,
51062306a36Sopenharmony_ci	0x00000000, 0x00000000, 0x00000000, 0x00000000,
51162306a36Sopenharmony_ci	0x00000000, 0x00000000, 0x00000000, 0x00000000,
51262306a36Sopenharmony_ci	0x00000000, 0x00000000, 0x00000000, 0x00000000,
51362306a36Sopenharmony_ci	0x00000000, 0x00000000, 0x00000000, 0x00000000,
51462306a36Sopenharmony_ci};
51562306a36Sopenharmony_ci
51662306a36Sopenharmony_ci/* Packet types for packets with PFCP SESSION header */
51762306a36Sopenharmony_cistatic const u32 ice_ptypes_pfcp_session[] = {
51862306a36Sopenharmony_ci	0x00000000, 0x00000000, 0x00000000, 0x00000000,
51962306a36Sopenharmony_ci	0x00000000, 0x00000000, 0x00000000, 0x00000000,
52062306a36Sopenharmony_ci	0x00000000, 0x00000000, 0x00000000, 0x00000005,
52162306a36Sopenharmony_ci	0x00000000, 0x00000000, 0x00000000, 0x00000000,
52262306a36Sopenharmony_ci	0x00000000, 0x00000000, 0x00000000, 0x00000000,
52362306a36Sopenharmony_ci	0x00000000, 0x00000000, 0x00000000, 0x00000000,
52462306a36Sopenharmony_ci	0x00000000, 0x00000000, 0x00000000, 0x00000000,
52562306a36Sopenharmony_ci	0x00000000, 0x00000000, 0x00000000, 0x00000000,
52662306a36Sopenharmony_ci};
52762306a36Sopenharmony_ci
52862306a36Sopenharmony_ci/* Packet types for L2TPv3 */
52962306a36Sopenharmony_cistatic const u32 ice_ptypes_l2tpv3[] = {
53062306a36Sopenharmony_ci	0x00000000, 0x00000000, 0x00000000, 0x00000000,
53162306a36Sopenharmony_ci	0x00000000, 0x00000000, 0x00000000, 0x00000000,
53262306a36Sopenharmony_ci	0x00000000, 0x00000000, 0x00000000, 0x00000300,
53362306a36Sopenharmony_ci	0x00000000, 0x00000000, 0x00000000, 0x00000000,
53462306a36Sopenharmony_ci	0x00000000, 0x00000000, 0x00000000, 0x00000000,
53562306a36Sopenharmony_ci	0x00000000, 0x00000000, 0x00000000, 0x00000000,
53662306a36Sopenharmony_ci	0x00000000, 0x00000000, 0x00000000, 0x00000000,
53762306a36Sopenharmony_ci	0x00000000, 0x00000000, 0x00000000, 0x00000000,
53862306a36Sopenharmony_ci};
53962306a36Sopenharmony_ci
54062306a36Sopenharmony_ci/* Packet types for ESP */
54162306a36Sopenharmony_cistatic const u32 ice_ptypes_esp[] = {
54262306a36Sopenharmony_ci	0x00000000, 0x00000000, 0x00000000, 0x00000000,
54362306a36Sopenharmony_ci	0x00000000, 0x00000003, 0x00000000, 0x00000000,
54462306a36Sopenharmony_ci	0x00000000, 0x00000000, 0x00000000, 0x00000000,
54562306a36Sopenharmony_ci	0x00000000, 0x00000000, 0x00000000, 0x00000000,
54662306a36Sopenharmony_ci	0x00000000, 0x00000000, 0x00000000, 0x00000000,
54762306a36Sopenharmony_ci	0x00000000, 0x00000000, 0x00000000, 0x00000000,
54862306a36Sopenharmony_ci	0x00000000, 0x00000000, 0x00000000, 0x00000000,
54962306a36Sopenharmony_ci	0x00000000, 0x00000000, 0x00000000, 0x00000000,
55062306a36Sopenharmony_ci};
55162306a36Sopenharmony_ci
55262306a36Sopenharmony_ci/* Packet types for AH */
55362306a36Sopenharmony_cistatic const u32 ice_ptypes_ah[] = {
55462306a36Sopenharmony_ci	0x00000000, 0x00000000, 0x00000000, 0x00000000,
55562306a36Sopenharmony_ci	0x00000000, 0x0000000C, 0x00000000, 0x00000000,
55662306a36Sopenharmony_ci	0x00000000, 0x00000000, 0x00000000, 0x00000000,
55762306a36Sopenharmony_ci	0x00000000, 0x00000000, 0x00000000, 0x00000000,
55862306a36Sopenharmony_ci	0x00000000, 0x00000000, 0x00000000, 0x00000000,
55962306a36Sopenharmony_ci	0x00000000, 0x00000000, 0x00000000, 0x00000000,
56062306a36Sopenharmony_ci	0x00000000, 0x00000000, 0x00000000, 0x00000000,
56162306a36Sopenharmony_ci	0x00000000, 0x00000000, 0x00000000, 0x00000000,
56262306a36Sopenharmony_ci};
56362306a36Sopenharmony_ci
56462306a36Sopenharmony_ci/* Packet types for packets with NAT_T ESP header */
56562306a36Sopenharmony_cistatic const u32 ice_ptypes_nat_t_esp[] = {
56662306a36Sopenharmony_ci	0x00000000, 0x00000000, 0x00000000, 0x00000000,
56762306a36Sopenharmony_ci	0x00000000, 0x00000030, 0x00000000, 0x00000000,
56862306a36Sopenharmony_ci	0x00000000, 0x00000000, 0x00000000, 0x00000000,
56962306a36Sopenharmony_ci	0x00000000, 0x00000000, 0x00000000, 0x00000000,
57062306a36Sopenharmony_ci	0x00000000, 0x00000000, 0x00000000, 0x00000000,
57162306a36Sopenharmony_ci	0x00000000, 0x00000000, 0x00000000, 0x00000000,
57262306a36Sopenharmony_ci	0x00000000, 0x00000000, 0x00000000, 0x00000000,
57362306a36Sopenharmony_ci	0x00000000, 0x00000000, 0x00000000, 0x00000000,
57462306a36Sopenharmony_ci};
57562306a36Sopenharmony_ci
57662306a36Sopenharmony_cistatic const u32 ice_ptypes_mac_non_ip_ofos[] = {
57762306a36Sopenharmony_ci	0x00000846, 0x00000000, 0x00000000, 0x00000000,
57862306a36Sopenharmony_ci	0x00000000, 0x00000000, 0x00000000, 0x00000000,
57962306a36Sopenharmony_ci	0x00400000, 0x03FFF000, 0x00000000, 0x00000000,
58062306a36Sopenharmony_ci	0x00000000, 0x00000000, 0x00000000, 0x00000000,
58162306a36Sopenharmony_ci	0x00000000, 0x00000000, 0x00000000, 0x00000000,
58262306a36Sopenharmony_ci	0x00000000, 0x00000000, 0x00000000, 0x00000000,
58362306a36Sopenharmony_ci	0x00000000, 0x00000000, 0x00000000, 0x00000000,
58462306a36Sopenharmony_ci	0x00000000, 0x00000000, 0x00000000, 0x00000000,
58562306a36Sopenharmony_ci};
58662306a36Sopenharmony_ci
58762306a36Sopenharmony_ci/* Manage parameters and info. used during the creation of a flow profile */
58862306a36Sopenharmony_cistruct ice_flow_prof_params {
58962306a36Sopenharmony_ci	enum ice_block blk;
59062306a36Sopenharmony_ci	u16 entry_length; /* # of bytes formatted entry will require */
59162306a36Sopenharmony_ci	u8 es_cnt;
59262306a36Sopenharmony_ci	struct ice_flow_prof *prof;
59362306a36Sopenharmony_ci
59462306a36Sopenharmony_ci	/* For ACL, the es[0] will have the data of ICE_RX_MDID_PKT_FLAGS_15_0
59562306a36Sopenharmony_ci	 * This will give us the direction flags.
59662306a36Sopenharmony_ci	 */
59762306a36Sopenharmony_ci	struct ice_fv_word es[ICE_MAX_FV_WORDS];
59862306a36Sopenharmony_ci	/* attributes can be used to add attributes to a particular PTYPE */
59962306a36Sopenharmony_ci	const struct ice_ptype_attributes *attr;
60062306a36Sopenharmony_ci	u16 attr_cnt;
60162306a36Sopenharmony_ci
60262306a36Sopenharmony_ci	u16 mask[ICE_MAX_FV_WORDS];
60362306a36Sopenharmony_ci	DECLARE_BITMAP(ptypes, ICE_FLOW_PTYPE_MAX);
60462306a36Sopenharmony_ci};
60562306a36Sopenharmony_ci
60662306a36Sopenharmony_ci#define ICE_FLOW_RSS_HDRS_INNER_MASK \
60762306a36Sopenharmony_ci	(ICE_FLOW_SEG_HDR_PPPOE | ICE_FLOW_SEG_HDR_GTPC | \
60862306a36Sopenharmony_ci	ICE_FLOW_SEG_HDR_GTPC_TEID | ICE_FLOW_SEG_HDR_GTPU | \
60962306a36Sopenharmony_ci	ICE_FLOW_SEG_HDR_PFCP_SESSION | ICE_FLOW_SEG_HDR_L2TPV3 | \
61062306a36Sopenharmony_ci	ICE_FLOW_SEG_HDR_ESP | ICE_FLOW_SEG_HDR_AH | \
61162306a36Sopenharmony_ci	ICE_FLOW_SEG_HDR_NAT_T_ESP)
61262306a36Sopenharmony_ci
61362306a36Sopenharmony_ci#define ICE_FLOW_SEG_HDRS_L3_MASK	\
61462306a36Sopenharmony_ci	(ICE_FLOW_SEG_HDR_IPV4 | ICE_FLOW_SEG_HDR_IPV6 | ICE_FLOW_SEG_HDR_ARP)
61562306a36Sopenharmony_ci#define ICE_FLOW_SEG_HDRS_L4_MASK	\
61662306a36Sopenharmony_ci	(ICE_FLOW_SEG_HDR_ICMP | ICE_FLOW_SEG_HDR_TCP | ICE_FLOW_SEG_HDR_UDP | \
61762306a36Sopenharmony_ci	 ICE_FLOW_SEG_HDR_SCTP)
61862306a36Sopenharmony_ci/* mask for L4 protocols that are NOT part of IPv4/6 OTHER PTYPE groups */
61962306a36Sopenharmony_ci#define ICE_FLOW_SEG_HDRS_L4_MASK_NO_OTHER	\
62062306a36Sopenharmony_ci	(ICE_FLOW_SEG_HDR_TCP | ICE_FLOW_SEG_HDR_UDP | ICE_FLOW_SEG_HDR_SCTP)
62162306a36Sopenharmony_ci
62262306a36Sopenharmony_ci/**
62362306a36Sopenharmony_ci * ice_flow_val_hdrs - validates packet segments for valid protocol headers
62462306a36Sopenharmony_ci * @segs: array of one or more packet segments that describe the flow
62562306a36Sopenharmony_ci * @segs_cnt: number of packet segments provided
62662306a36Sopenharmony_ci */
62762306a36Sopenharmony_cistatic int ice_flow_val_hdrs(struct ice_flow_seg_info *segs, u8 segs_cnt)
62862306a36Sopenharmony_ci{
62962306a36Sopenharmony_ci	u8 i;
63062306a36Sopenharmony_ci
63162306a36Sopenharmony_ci	for (i = 0; i < segs_cnt; i++) {
63262306a36Sopenharmony_ci		/* Multiple L3 headers */
63362306a36Sopenharmony_ci		if (segs[i].hdrs & ICE_FLOW_SEG_HDRS_L3_MASK &&
63462306a36Sopenharmony_ci		    !is_power_of_2(segs[i].hdrs & ICE_FLOW_SEG_HDRS_L3_MASK))
63562306a36Sopenharmony_ci			return -EINVAL;
63662306a36Sopenharmony_ci
63762306a36Sopenharmony_ci		/* Multiple L4 headers */
63862306a36Sopenharmony_ci		if (segs[i].hdrs & ICE_FLOW_SEG_HDRS_L4_MASK &&
63962306a36Sopenharmony_ci		    !is_power_of_2(segs[i].hdrs & ICE_FLOW_SEG_HDRS_L4_MASK))
64062306a36Sopenharmony_ci			return -EINVAL;
64162306a36Sopenharmony_ci	}
64262306a36Sopenharmony_ci
64362306a36Sopenharmony_ci	return 0;
64462306a36Sopenharmony_ci}
64562306a36Sopenharmony_ci
64662306a36Sopenharmony_ci/* Sizes of fixed known protocol headers without header options */
64762306a36Sopenharmony_ci#define ICE_FLOW_PROT_HDR_SZ_MAC	14
64862306a36Sopenharmony_ci#define ICE_FLOW_PROT_HDR_SZ_MAC_VLAN	(ICE_FLOW_PROT_HDR_SZ_MAC + 2)
64962306a36Sopenharmony_ci#define ICE_FLOW_PROT_HDR_SZ_IPV4	20
65062306a36Sopenharmony_ci#define ICE_FLOW_PROT_HDR_SZ_IPV6	40
65162306a36Sopenharmony_ci#define ICE_FLOW_PROT_HDR_SZ_ARP	28
65262306a36Sopenharmony_ci#define ICE_FLOW_PROT_HDR_SZ_ICMP	8
65362306a36Sopenharmony_ci#define ICE_FLOW_PROT_HDR_SZ_TCP	20
65462306a36Sopenharmony_ci#define ICE_FLOW_PROT_HDR_SZ_UDP	8
65562306a36Sopenharmony_ci#define ICE_FLOW_PROT_HDR_SZ_SCTP	12
65662306a36Sopenharmony_ci
65762306a36Sopenharmony_ci/**
65862306a36Sopenharmony_ci * ice_flow_calc_seg_sz - calculates size of a packet segment based on headers
65962306a36Sopenharmony_ci * @params: information about the flow to be processed
66062306a36Sopenharmony_ci * @seg: index of packet segment whose header size is to be determined
66162306a36Sopenharmony_ci */
66262306a36Sopenharmony_cistatic u16 ice_flow_calc_seg_sz(struct ice_flow_prof_params *params, u8 seg)
66362306a36Sopenharmony_ci{
66462306a36Sopenharmony_ci	u16 sz;
66562306a36Sopenharmony_ci
66662306a36Sopenharmony_ci	/* L2 headers */
66762306a36Sopenharmony_ci	sz = (params->prof->segs[seg].hdrs & ICE_FLOW_SEG_HDR_VLAN) ?
66862306a36Sopenharmony_ci		ICE_FLOW_PROT_HDR_SZ_MAC_VLAN : ICE_FLOW_PROT_HDR_SZ_MAC;
66962306a36Sopenharmony_ci
67062306a36Sopenharmony_ci	/* L3 headers */
67162306a36Sopenharmony_ci	if (params->prof->segs[seg].hdrs & ICE_FLOW_SEG_HDR_IPV4)
67262306a36Sopenharmony_ci		sz += ICE_FLOW_PROT_HDR_SZ_IPV4;
67362306a36Sopenharmony_ci	else if (params->prof->segs[seg].hdrs & ICE_FLOW_SEG_HDR_IPV6)
67462306a36Sopenharmony_ci		sz += ICE_FLOW_PROT_HDR_SZ_IPV6;
67562306a36Sopenharmony_ci	else if (params->prof->segs[seg].hdrs & ICE_FLOW_SEG_HDR_ARP)
67662306a36Sopenharmony_ci		sz += ICE_FLOW_PROT_HDR_SZ_ARP;
67762306a36Sopenharmony_ci	else if (params->prof->segs[seg].hdrs & ICE_FLOW_SEG_HDRS_L4_MASK)
67862306a36Sopenharmony_ci		/* An L3 header is required if L4 is specified */
67962306a36Sopenharmony_ci		return 0;
68062306a36Sopenharmony_ci
68162306a36Sopenharmony_ci	/* L4 headers */
68262306a36Sopenharmony_ci	if (params->prof->segs[seg].hdrs & ICE_FLOW_SEG_HDR_ICMP)
68362306a36Sopenharmony_ci		sz += ICE_FLOW_PROT_HDR_SZ_ICMP;
68462306a36Sopenharmony_ci	else if (params->prof->segs[seg].hdrs & ICE_FLOW_SEG_HDR_TCP)
68562306a36Sopenharmony_ci		sz += ICE_FLOW_PROT_HDR_SZ_TCP;
68662306a36Sopenharmony_ci	else if (params->prof->segs[seg].hdrs & ICE_FLOW_SEG_HDR_UDP)
68762306a36Sopenharmony_ci		sz += ICE_FLOW_PROT_HDR_SZ_UDP;
68862306a36Sopenharmony_ci	else if (params->prof->segs[seg].hdrs & ICE_FLOW_SEG_HDR_SCTP)
68962306a36Sopenharmony_ci		sz += ICE_FLOW_PROT_HDR_SZ_SCTP;
69062306a36Sopenharmony_ci
69162306a36Sopenharmony_ci	return sz;
69262306a36Sopenharmony_ci}
69362306a36Sopenharmony_ci
69462306a36Sopenharmony_ci/**
69562306a36Sopenharmony_ci * ice_flow_proc_seg_hdrs - process protocol headers present in pkt segments
69662306a36Sopenharmony_ci * @params: information about the flow to be processed
69762306a36Sopenharmony_ci *
69862306a36Sopenharmony_ci * This function identifies the packet types associated with the protocol
69962306a36Sopenharmony_ci * headers being present in packet segments of the specified flow profile.
70062306a36Sopenharmony_ci */
70162306a36Sopenharmony_cistatic int ice_flow_proc_seg_hdrs(struct ice_flow_prof_params *params)
70262306a36Sopenharmony_ci{
70362306a36Sopenharmony_ci	struct ice_flow_prof *prof;
70462306a36Sopenharmony_ci	u8 i;
70562306a36Sopenharmony_ci
70662306a36Sopenharmony_ci	memset(params->ptypes, 0xff, sizeof(params->ptypes));
70762306a36Sopenharmony_ci
70862306a36Sopenharmony_ci	prof = params->prof;
70962306a36Sopenharmony_ci
71062306a36Sopenharmony_ci	for (i = 0; i < params->prof->segs_cnt; i++) {
71162306a36Sopenharmony_ci		const unsigned long *src;
71262306a36Sopenharmony_ci		u32 hdrs;
71362306a36Sopenharmony_ci
71462306a36Sopenharmony_ci		hdrs = prof->segs[i].hdrs;
71562306a36Sopenharmony_ci
71662306a36Sopenharmony_ci		if (hdrs & ICE_FLOW_SEG_HDR_ETH) {
71762306a36Sopenharmony_ci			src = !i ? (const unsigned long *)ice_ptypes_mac_ofos :
71862306a36Sopenharmony_ci				(const unsigned long *)ice_ptypes_mac_il;
71962306a36Sopenharmony_ci			bitmap_and(params->ptypes, params->ptypes, src,
72062306a36Sopenharmony_ci				   ICE_FLOW_PTYPE_MAX);
72162306a36Sopenharmony_ci		}
72262306a36Sopenharmony_ci
72362306a36Sopenharmony_ci		if (i && hdrs & ICE_FLOW_SEG_HDR_VLAN) {
72462306a36Sopenharmony_ci			src = (const unsigned long *)ice_ptypes_macvlan_il;
72562306a36Sopenharmony_ci			bitmap_and(params->ptypes, params->ptypes, src,
72662306a36Sopenharmony_ci				   ICE_FLOW_PTYPE_MAX);
72762306a36Sopenharmony_ci		}
72862306a36Sopenharmony_ci
72962306a36Sopenharmony_ci		if (!i && hdrs & ICE_FLOW_SEG_HDR_ARP) {
73062306a36Sopenharmony_ci			bitmap_and(params->ptypes, params->ptypes,
73162306a36Sopenharmony_ci				   (const unsigned long *)ice_ptypes_arp_of,
73262306a36Sopenharmony_ci				   ICE_FLOW_PTYPE_MAX);
73362306a36Sopenharmony_ci		}
73462306a36Sopenharmony_ci
73562306a36Sopenharmony_ci		if ((hdrs & ICE_FLOW_SEG_HDR_IPV4) &&
73662306a36Sopenharmony_ci		    (hdrs & ICE_FLOW_SEG_HDR_IPV_OTHER)) {
73762306a36Sopenharmony_ci			src = i ? (const unsigned long *)ice_ptypes_ipv4_il :
73862306a36Sopenharmony_ci				(const unsigned long *)ice_ptypes_ipv4_ofos_all;
73962306a36Sopenharmony_ci			bitmap_and(params->ptypes, params->ptypes, src,
74062306a36Sopenharmony_ci				   ICE_FLOW_PTYPE_MAX);
74162306a36Sopenharmony_ci		} else if ((hdrs & ICE_FLOW_SEG_HDR_IPV6) &&
74262306a36Sopenharmony_ci			   (hdrs & ICE_FLOW_SEG_HDR_IPV_OTHER)) {
74362306a36Sopenharmony_ci			src = i ? (const unsigned long *)ice_ptypes_ipv6_il :
74462306a36Sopenharmony_ci				(const unsigned long *)ice_ptypes_ipv6_ofos_all;
74562306a36Sopenharmony_ci			bitmap_and(params->ptypes, params->ptypes, src,
74662306a36Sopenharmony_ci				   ICE_FLOW_PTYPE_MAX);
74762306a36Sopenharmony_ci		} else if ((hdrs & ICE_FLOW_SEG_HDR_IPV4) &&
74862306a36Sopenharmony_ci			   !(hdrs & ICE_FLOW_SEG_HDRS_L4_MASK_NO_OTHER)) {
74962306a36Sopenharmony_ci			src = !i ? (const unsigned long *)ice_ptypes_ipv4_ofos_no_l4 :
75062306a36Sopenharmony_ci				(const unsigned long *)ice_ptypes_ipv4_il_no_l4;
75162306a36Sopenharmony_ci			bitmap_and(params->ptypes, params->ptypes, src,
75262306a36Sopenharmony_ci				   ICE_FLOW_PTYPE_MAX);
75362306a36Sopenharmony_ci		} else if (hdrs & ICE_FLOW_SEG_HDR_IPV4) {
75462306a36Sopenharmony_ci			src = !i ? (const unsigned long *)ice_ptypes_ipv4_ofos :
75562306a36Sopenharmony_ci				(const unsigned long *)ice_ptypes_ipv4_il;
75662306a36Sopenharmony_ci			bitmap_and(params->ptypes, params->ptypes, src,
75762306a36Sopenharmony_ci				   ICE_FLOW_PTYPE_MAX);
75862306a36Sopenharmony_ci		} else if ((hdrs & ICE_FLOW_SEG_HDR_IPV6) &&
75962306a36Sopenharmony_ci			   !(hdrs & ICE_FLOW_SEG_HDRS_L4_MASK_NO_OTHER)) {
76062306a36Sopenharmony_ci			src = !i ? (const unsigned long *)ice_ptypes_ipv6_ofos_no_l4 :
76162306a36Sopenharmony_ci				(const unsigned long *)ice_ptypes_ipv6_il_no_l4;
76262306a36Sopenharmony_ci			bitmap_and(params->ptypes, params->ptypes, src,
76362306a36Sopenharmony_ci				   ICE_FLOW_PTYPE_MAX);
76462306a36Sopenharmony_ci		} else if (hdrs & ICE_FLOW_SEG_HDR_IPV6) {
76562306a36Sopenharmony_ci			src = !i ? (const unsigned long *)ice_ptypes_ipv6_ofos :
76662306a36Sopenharmony_ci				(const unsigned long *)ice_ptypes_ipv6_il;
76762306a36Sopenharmony_ci			bitmap_and(params->ptypes, params->ptypes, src,
76862306a36Sopenharmony_ci				   ICE_FLOW_PTYPE_MAX);
76962306a36Sopenharmony_ci		}
77062306a36Sopenharmony_ci
77162306a36Sopenharmony_ci		if (hdrs & ICE_FLOW_SEG_HDR_ETH_NON_IP) {
77262306a36Sopenharmony_ci			src = (const unsigned long *)ice_ptypes_mac_non_ip_ofos;
77362306a36Sopenharmony_ci			bitmap_and(params->ptypes, params->ptypes, src,
77462306a36Sopenharmony_ci				   ICE_FLOW_PTYPE_MAX);
77562306a36Sopenharmony_ci		} else if (hdrs & ICE_FLOW_SEG_HDR_PPPOE) {
77662306a36Sopenharmony_ci			src = (const unsigned long *)ice_ptypes_pppoe;
77762306a36Sopenharmony_ci			bitmap_and(params->ptypes, params->ptypes, src,
77862306a36Sopenharmony_ci				   ICE_FLOW_PTYPE_MAX);
77962306a36Sopenharmony_ci		} else {
78062306a36Sopenharmony_ci			src = (const unsigned long *)ice_ptypes_pppoe;
78162306a36Sopenharmony_ci			bitmap_andnot(params->ptypes, params->ptypes, src,
78262306a36Sopenharmony_ci				      ICE_FLOW_PTYPE_MAX);
78362306a36Sopenharmony_ci		}
78462306a36Sopenharmony_ci
78562306a36Sopenharmony_ci		if (hdrs & ICE_FLOW_SEG_HDR_UDP) {
78662306a36Sopenharmony_ci			src = (const unsigned long *)ice_ptypes_udp_il;
78762306a36Sopenharmony_ci			bitmap_and(params->ptypes, params->ptypes, src,
78862306a36Sopenharmony_ci				   ICE_FLOW_PTYPE_MAX);
78962306a36Sopenharmony_ci		} else if (hdrs & ICE_FLOW_SEG_HDR_TCP) {
79062306a36Sopenharmony_ci			bitmap_and(params->ptypes, params->ptypes,
79162306a36Sopenharmony_ci				   (const unsigned long *)ice_ptypes_tcp_il,
79262306a36Sopenharmony_ci				   ICE_FLOW_PTYPE_MAX);
79362306a36Sopenharmony_ci		} else if (hdrs & ICE_FLOW_SEG_HDR_SCTP) {
79462306a36Sopenharmony_ci			src = (const unsigned long *)ice_ptypes_sctp_il;
79562306a36Sopenharmony_ci			bitmap_and(params->ptypes, params->ptypes, src,
79662306a36Sopenharmony_ci				   ICE_FLOW_PTYPE_MAX);
79762306a36Sopenharmony_ci		}
79862306a36Sopenharmony_ci
79962306a36Sopenharmony_ci		if (hdrs & ICE_FLOW_SEG_HDR_ICMP) {
80062306a36Sopenharmony_ci			src = !i ? (const unsigned long *)ice_ptypes_icmp_of :
80162306a36Sopenharmony_ci				(const unsigned long *)ice_ptypes_icmp_il;
80262306a36Sopenharmony_ci			bitmap_and(params->ptypes, params->ptypes, src,
80362306a36Sopenharmony_ci				   ICE_FLOW_PTYPE_MAX);
80462306a36Sopenharmony_ci		} else if (hdrs & ICE_FLOW_SEG_HDR_GRE) {
80562306a36Sopenharmony_ci			if (!i) {
80662306a36Sopenharmony_ci				src = (const unsigned long *)ice_ptypes_gre_of;
80762306a36Sopenharmony_ci				bitmap_and(params->ptypes, params->ptypes,
80862306a36Sopenharmony_ci					   src, ICE_FLOW_PTYPE_MAX);
80962306a36Sopenharmony_ci			}
81062306a36Sopenharmony_ci		} else if (hdrs & ICE_FLOW_SEG_HDR_GTPC) {
81162306a36Sopenharmony_ci			src = (const unsigned long *)ice_ptypes_gtpc;
81262306a36Sopenharmony_ci			bitmap_and(params->ptypes, params->ptypes, src,
81362306a36Sopenharmony_ci				   ICE_FLOW_PTYPE_MAX);
81462306a36Sopenharmony_ci		} else if (hdrs & ICE_FLOW_SEG_HDR_GTPC_TEID) {
81562306a36Sopenharmony_ci			src = (const unsigned long *)ice_ptypes_gtpc_tid;
81662306a36Sopenharmony_ci			bitmap_and(params->ptypes, params->ptypes, src,
81762306a36Sopenharmony_ci				   ICE_FLOW_PTYPE_MAX);
81862306a36Sopenharmony_ci		} else if (hdrs & ICE_FLOW_SEG_HDR_GTPU_DWN) {
81962306a36Sopenharmony_ci			src = (const unsigned long *)ice_ptypes_gtpu;
82062306a36Sopenharmony_ci			bitmap_and(params->ptypes, params->ptypes, src,
82162306a36Sopenharmony_ci				   ICE_FLOW_PTYPE_MAX);
82262306a36Sopenharmony_ci
82362306a36Sopenharmony_ci			/* Attributes for GTP packet with downlink */
82462306a36Sopenharmony_ci			params->attr = ice_attr_gtpu_down;
82562306a36Sopenharmony_ci			params->attr_cnt = ARRAY_SIZE(ice_attr_gtpu_down);
82662306a36Sopenharmony_ci		} else if (hdrs & ICE_FLOW_SEG_HDR_GTPU_UP) {
82762306a36Sopenharmony_ci			src = (const unsigned long *)ice_ptypes_gtpu;
82862306a36Sopenharmony_ci			bitmap_and(params->ptypes, params->ptypes, src,
82962306a36Sopenharmony_ci				   ICE_FLOW_PTYPE_MAX);
83062306a36Sopenharmony_ci
83162306a36Sopenharmony_ci			/* Attributes for GTP packet with uplink */
83262306a36Sopenharmony_ci			params->attr = ice_attr_gtpu_up;
83362306a36Sopenharmony_ci			params->attr_cnt = ARRAY_SIZE(ice_attr_gtpu_up);
83462306a36Sopenharmony_ci		} else if (hdrs & ICE_FLOW_SEG_HDR_GTPU_EH) {
83562306a36Sopenharmony_ci			src = (const unsigned long *)ice_ptypes_gtpu;
83662306a36Sopenharmony_ci			bitmap_and(params->ptypes, params->ptypes, src,
83762306a36Sopenharmony_ci				   ICE_FLOW_PTYPE_MAX);
83862306a36Sopenharmony_ci
83962306a36Sopenharmony_ci			/* Attributes for GTP packet with Extension Header */
84062306a36Sopenharmony_ci			params->attr = ice_attr_gtpu_eh;
84162306a36Sopenharmony_ci			params->attr_cnt = ARRAY_SIZE(ice_attr_gtpu_eh);
84262306a36Sopenharmony_ci		} else if (hdrs & ICE_FLOW_SEG_HDR_GTPU_IP) {
84362306a36Sopenharmony_ci			src = (const unsigned long *)ice_ptypes_gtpu;
84462306a36Sopenharmony_ci			bitmap_and(params->ptypes, params->ptypes, src,
84562306a36Sopenharmony_ci				   ICE_FLOW_PTYPE_MAX);
84662306a36Sopenharmony_ci		} else if (hdrs & ICE_FLOW_SEG_HDR_L2TPV3) {
84762306a36Sopenharmony_ci			src = (const unsigned long *)ice_ptypes_l2tpv3;
84862306a36Sopenharmony_ci			bitmap_and(params->ptypes, params->ptypes, src,
84962306a36Sopenharmony_ci				   ICE_FLOW_PTYPE_MAX);
85062306a36Sopenharmony_ci		} else if (hdrs & ICE_FLOW_SEG_HDR_ESP) {
85162306a36Sopenharmony_ci			src = (const unsigned long *)ice_ptypes_esp;
85262306a36Sopenharmony_ci			bitmap_and(params->ptypes, params->ptypes, src,
85362306a36Sopenharmony_ci				   ICE_FLOW_PTYPE_MAX);
85462306a36Sopenharmony_ci		} else if (hdrs & ICE_FLOW_SEG_HDR_AH) {
85562306a36Sopenharmony_ci			src = (const unsigned long *)ice_ptypes_ah;
85662306a36Sopenharmony_ci			bitmap_and(params->ptypes, params->ptypes, src,
85762306a36Sopenharmony_ci				   ICE_FLOW_PTYPE_MAX);
85862306a36Sopenharmony_ci		} else if (hdrs & ICE_FLOW_SEG_HDR_NAT_T_ESP) {
85962306a36Sopenharmony_ci			src = (const unsigned long *)ice_ptypes_nat_t_esp;
86062306a36Sopenharmony_ci			bitmap_and(params->ptypes, params->ptypes, src,
86162306a36Sopenharmony_ci				   ICE_FLOW_PTYPE_MAX);
86262306a36Sopenharmony_ci		}
86362306a36Sopenharmony_ci
86462306a36Sopenharmony_ci		if (hdrs & ICE_FLOW_SEG_HDR_PFCP) {
86562306a36Sopenharmony_ci			if (hdrs & ICE_FLOW_SEG_HDR_PFCP_NODE)
86662306a36Sopenharmony_ci				src = (const unsigned long *)ice_ptypes_pfcp_node;
86762306a36Sopenharmony_ci			else
86862306a36Sopenharmony_ci				src = (const unsigned long *)ice_ptypes_pfcp_session;
86962306a36Sopenharmony_ci
87062306a36Sopenharmony_ci			bitmap_and(params->ptypes, params->ptypes, src,
87162306a36Sopenharmony_ci				   ICE_FLOW_PTYPE_MAX);
87262306a36Sopenharmony_ci		} else {
87362306a36Sopenharmony_ci			src = (const unsigned long *)ice_ptypes_pfcp_node;
87462306a36Sopenharmony_ci			bitmap_andnot(params->ptypes, params->ptypes, src,
87562306a36Sopenharmony_ci				      ICE_FLOW_PTYPE_MAX);
87662306a36Sopenharmony_ci
87762306a36Sopenharmony_ci			src = (const unsigned long *)ice_ptypes_pfcp_session;
87862306a36Sopenharmony_ci			bitmap_andnot(params->ptypes, params->ptypes, src,
87962306a36Sopenharmony_ci				      ICE_FLOW_PTYPE_MAX);
88062306a36Sopenharmony_ci		}
88162306a36Sopenharmony_ci	}
88262306a36Sopenharmony_ci
88362306a36Sopenharmony_ci	return 0;
88462306a36Sopenharmony_ci}
88562306a36Sopenharmony_ci
88662306a36Sopenharmony_ci/**
88762306a36Sopenharmony_ci * ice_flow_xtract_fld - Create an extraction sequence entry for the given field
88862306a36Sopenharmony_ci * @hw: pointer to the HW struct
88962306a36Sopenharmony_ci * @params: information about the flow to be processed
89062306a36Sopenharmony_ci * @seg: packet segment index of the field to be extracted
89162306a36Sopenharmony_ci * @fld: ID of field to be extracted
89262306a36Sopenharmony_ci * @match: bit field of all fields
89362306a36Sopenharmony_ci *
89462306a36Sopenharmony_ci * This function determines the protocol ID, offset, and size of the given
89562306a36Sopenharmony_ci * field. It then allocates one or more extraction sequence entries for the
89662306a36Sopenharmony_ci * given field, and fill the entries with protocol ID and offset information.
89762306a36Sopenharmony_ci */
89862306a36Sopenharmony_cistatic int
89962306a36Sopenharmony_ciice_flow_xtract_fld(struct ice_hw *hw, struct ice_flow_prof_params *params,
90062306a36Sopenharmony_ci		    u8 seg, enum ice_flow_field fld, u64 match)
90162306a36Sopenharmony_ci{
90262306a36Sopenharmony_ci	enum ice_flow_field sib = ICE_FLOW_FIELD_IDX_MAX;
90362306a36Sopenharmony_ci	enum ice_prot_id prot_id = ICE_PROT_ID_INVAL;
90462306a36Sopenharmony_ci	u8 fv_words = hw->blk[params->blk].es.fvw;
90562306a36Sopenharmony_ci	struct ice_flow_fld_info *flds;
90662306a36Sopenharmony_ci	u16 cnt, ese_bits, i;
90762306a36Sopenharmony_ci	u16 sib_mask = 0;
90862306a36Sopenharmony_ci	u16 mask;
90962306a36Sopenharmony_ci	u16 off;
91062306a36Sopenharmony_ci
91162306a36Sopenharmony_ci	flds = params->prof->segs[seg].fields;
91262306a36Sopenharmony_ci
91362306a36Sopenharmony_ci	switch (fld) {
91462306a36Sopenharmony_ci	case ICE_FLOW_FIELD_IDX_ETH_DA:
91562306a36Sopenharmony_ci	case ICE_FLOW_FIELD_IDX_ETH_SA:
91662306a36Sopenharmony_ci	case ICE_FLOW_FIELD_IDX_S_VLAN:
91762306a36Sopenharmony_ci	case ICE_FLOW_FIELD_IDX_C_VLAN:
91862306a36Sopenharmony_ci		prot_id = seg == 0 ? ICE_PROT_MAC_OF_OR_S : ICE_PROT_MAC_IL;
91962306a36Sopenharmony_ci		break;
92062306a36Sopenharmony_ci	case ICE_FLOW_FIELD_IDX_ETH_TYPE:
92162306a36Sopenharmony_ci		prot_id = seg == 0 ? ICE_PROT_ETYPE_OL : ICE_PROT_ETYPE_IL;
92262306a36Sopenharmony_ci		break;
92362306a36Sopenharmony_ci	case ICE_FLOW_FIELD_IDX_IPV4_DSCP:
92462306a36Sopenharmony_ci		prot_id = seg == 0 ? ICE_PROT_IPV4_OF_OR_S : ICE_PROT_IPV4_IL;
92562306a36Sopenharmony_ci		break;
92662306a36Sopenharmony_ci	case ICE_FLOW_FIELD_IDX_IPV6_DSCP:
92762306a36Sopenharmony_ci		prot_id = seg == 0 ? ICE_PROT_IPV6_OF_OR_S : ICE_PROT_IPV6_IL;
92862306a36Sopenharmony_ci		break;
92962306a36Sopenharmony_ci	case ICE_FLOW_FIELD_IDX_IPV4_TTL:
93062306a36Sopenharmony_ci	case ICE_FLOW_FIELD_IDX_IPV4_PROT:
93162306a36Sopenharmony_ci		prot_id = seg == 0 ? ICE_PROT_IPV4_OF_OR_S : ICE_PROT_IPV4_IL;
93262306a36Sopenharmony_ci
93362306a36Sopenharmony_ci		/* TTL and PROT share the same extraction seq. entry.
93462306a36Sopenharmony_ci		 * Each is considered a sibling to the other in terms of sharing
93562306a36Sopenharmony_ci		 * the same extraction sequence entry.
93662306a36Sopenharmony_ci		 */
93762306a36Sopenharmony_ci		if (fld == ICE_FLOW_FIELD_IDX_IPV4_TTL)
93862306a36Sopenharmony_ci			sib = ICE_FLOW_FIELD_IDX_IPV4_PROT;
93962306a36Sopenharmony_ci		else if (fld == ICE_FLOW_FIELD_IDX_IPV4_PROT)
94062306a36Sopenharmony_ci			sib = ICE_FLOW_FIELD_IDX_IPV4_TTL;
94162306a36Sopenharmony_ci
94262306a36Sopenharmony_ci		/* If the sibling field is also included, that field's
94362306a36Sopenharmony_ci		 * mask needs to be included.
94462306a36Sopenharmony_ci		 */
94562306a36Sopenharmony_ci		if (match & BIT(sib))
94662306a36Sopenharmony_ci			sib_mask = ice_flds_info[sib].mask;
94762306a36Sopenharmony_ci		break;
94862306a36Sopenharmony_ci	case ICE_FLOW_FIELD_IDX_IPV6_TTL:
94962306a36Sopenharmony_ci	case ICE_FLOW_FIELD_IDX_IPV6_PROT:
95062306a36Sopenharmony_ci		prot_id = seg == 0 ? ICE_PROT_IPV6_OF_OR_S : ICE_PROT_IPV6_IL;
95162306a36Sopenharmony_ci
95262306a36Sopenharmony_ci		/* TTL and PROT share the same extraction seq. entry.
95362306a36Sopenharmony_ci		 * Each is considered a sibling to the other in terms of sharing
95462306a36Sopenharmony_ci		 * the same extraction sequence entry.
95562306a36Sopenharmony_ci		 */
95662306a36Sopenharmony_ci		if (fld == ICE_FLOW_FIELD_IDX_IPV6_TTL)
95762306a36Sopenharmony_ci			sib = ICE_FLOW_FIELD_IDX_IPV6_PROT;
95862306a36Sopenharmony_ci		else if (fld == ICE_FLOW_FIELD_IDX_IPV6_PROT)
95962306a36Sopenharmony_ci			sib = ICE_FLOW_FIELD_IDX_IPV6_TTL;
96062306a36Sopenharmony_ci
96162306a36Sopenharmony_ci		/* If the sibling field is also included, that field's
96262306a36Sopenharmony_ci		 * mask needs to be included.
96362306a36Sopenharmony_ci		 */
96462306a36Sopenharmony_ci		if (match & BIT(sib))
96562306a36Sopenharmony_ci			sib_mask = ice_flds_info[sib].mask;
96662306a36Sopenharmony_ci		break;
96762306a36Sopenharmony_ci	case ICE_FLOW_FIELD_IDX_IPV4_SA:
96862306a36Sopenharmony_ci	case ICE_FLOW_FIELD_IDX_IPV4_DA:
96962306a36Sopenharmony_ci		prot_id = seg == 0 ? ICE_PROT_IPV4_OF_OR_S : ICE_PROT_IPV4_IL;
97062306a36Sopenharmony_ci		break;
97162306a36Sopenharmony_ci	case ICE_FLOW_FIELD_IDX_IPV6_SA:
97262306a36Sopenharmony_ci	case ICE_FLOW_FIELD_IDX_IPV6_DA:
97362306a36Sopenharmony_ci		prot_id = seg == 0 ? ICE_PROT_IPV6_OF_OR_S : ICE_PROT_IPV6_IL;
97462306a36Sopenharmony_ci		break;
97562306a36Sopenharmony_ci	case ICE_FLOW_FIELD_IDX_TCP_SRC_PORT:
97662306a36Sopenharmony_ci	case ICE_FLOW_FIELD_IDX_TCP_DST_PORT:
97762306a36Sopenharmony_ci	case ICE_FLOW_FIELD_IDX_TCP_FLAGS:
97862306a36Sopenharmony_ci		prot_id = ICE_PROT_TCP_IL;
97962306a36Sopenharmony_ci		break;
98062306a36Sopenharmony_ci	case ICE_FLOW_FIELD_IDX_UDP_SRC_PORT:
98162306a36Sopenharmony_ci	case ICE_FLOW_FIELD_IDX_UDP_DST_PORT:
98262306a36Sopenharmony_ci		prot_id = ICE_PROT_UDP_IL_OR_S;
98362306a36Sopenharmony_ci		break;
98462306a36Sopenharmony_ci	case ICE_FLOW_FIELD_IDX_SCTP_SRC_PORT:
98562306a36Sopenharmony_ci	case ICE_FLOW_FIELD_IDX_SCTP_DST_PORT:
98662306a36Sopenharmony_ci		prot_id = ICE_PROT_SCTP_IL;
98762306a36Sopenharmony_ci		break;
98862306a36Sopenharmony_ci	case ICE_FLOW_FIELD_IDX_GTPC_TEID:
98962306a36Sopenharmony_ci	case ICE_FLOW_FIELD_IDX_GTPU_IP_TEID:
99062306a36Sopenharmony_ci	case ICE_FLOW_FIELD_IDX_GTPU_UP_TEID:
99162306a36Sopenharmony_ci	case ICE_FLOW_FIELD_IDX_GTPU_DWN_TEID:
99262306a36Sopenharmony_ci	case ICE_FLOW_FIELD_IDX_GTPU_EH_TEID:
99362306a36Sopenharmony_ci	case ICE_FLOW_FIELD_IDX_GTPU_EH_QFI:
99462306a36Sopenharmony_ci		/* GTP is accessed through UDP OF protocol */
99562306a36Sopenharmony_ci		prot_id = ICE_PROT_UDP_OF;
99662306a36Sopenharmony_ci		break;
99762306a36Sopenharmony_ci	case ICE_FLOW_FIELD_IDX_PPPOE_SESS_ID:
99862306a36Sopenharmony_ci		prot_id = ICE_PROT_PPPOE;
99962306a36Sopenharmony_ci		break;
100062306a36Sopenharmony_ci	case ICE_FLOW_FIELD_IDX_PFCP_SEID:
100162306a36Sopenharmony_ci		prot_id = ICE_PROT_UDP_IL_OR_S;
100262306a36Sopenharmony_ci		break;
100362306a36Sopenharmony_ci	case ICE_FLOW_FIELD_IDX_L2TPV3_SESS_ID:
100462306a36Sopenharmony_ci		prot_id = ICE_PROT_L2TPV3;
100562306a36Sopenharmony_ci		break;
100662306a36Sopenharmony_ci	case ICE_FLOW_FIELD_IDX_ESP_SPI:
100762306a36Sopenharmony_ci		prot_id = ICE_PROT_ESP_F;
100862306a36Sopenharmony_ci		break;
100962306a36Sopenharmony_ci	case ICE_FLOW_FIELD_IDX_AH_SPI:
101062306a36Sopenharmony_ci		prot_id = ICE_PROT_ESP_2;
101162306a36Sopenharmony_ci		break;
101262306a36Sopenharmony_ci	case ICE_FLOW_FIELD_IDX_NAT_T_ESP_SPI:
101362306a36Sopenharmony_ci		prot_id = ICE_PROT_UDP_IL_OR_S;
101462306a36Sopenharmony_ci		break;
101562306a36Sopenharmony_ci	case ICE_FLOW_FIELD_IDX_ARP_SIP:
101662306a36Sopenharmony_ci	case ICE_FLOW_FIELD_IDX_ARP_DIP:
101762306a36Sopenharmony_ci	case ICE_FLOW_FIELD_IDX_ARP_SHA:
101862306a36Sopenharmony_ci	case ICE_FLOW_FIELD_IDX_ARP_DHA:
101962306a36Sopenharmony_ci	case ICE_FLOW_FIELD_IDX_ARP_OP:
102062306a36Sopenharmony_ci		prot_id = ICE_PROT_ARP_OF;
102162306a36Sopenharmony_ci		break;
102262306a36Sopenharmony_ci	case ICE_FLOW_FIELD_IDX_ICMP_TYPE:
102362306a36Sopenharmony_ci	case ICE_FLOW_FIELD_IDX_ICMP_CODE:
102462306a36Sopenharmony_ci		/* ICMP type and code share the same extraction seq. entry */
102562306a36Sopenharmony_ci		prot_id = (params->prof->segs[seg].hdrs & ICE_FLOW_SEG_HDR_IPV4) ?
102662306a36Sopenharmony_ci				ICE_PROT_ICMP_IL : ICE_PROT_ICMPV6_IL;
102762306a36Sopenharmony_ci		sib = fld == ICE_FLOW_FIELD_IDX_ICMP_TYPE ?
102862306a36Sopenharmony_ci			ICE_FLOW_FIELD_IDX_ICMP_CODE :
102962306a36Sopenharmony_ci			ICE_FLOW_FIELD_IDX_ICMP_TYPE;
103062306a36Sopenharmony_ci		break;
103162306a36Sopenharmony_ci	case ICE_FLOW_FIELD_IDX_GRE_KEYID:
103262306a36Sopenharmony_ci		prot_id = ICE_PROT_GRE_OF;
103362306a36Sopenharmony_ci		break;
103462306a36Sopenharmony_ci	default:
103562306a36Sopenharmony_ci		return -EOPNOTSUPP;
103662306a36Sopenharmony_ci	}
103762306a36Sopenharmony_ci
103862306a36Sopenharmony_ci	/* Each extraction sequence entry is a word in size, and extracts a
103962306a36Sopenharmony_ci	 * word-aligned offset from a protocol header.
104062306a36Sopenharmony_ci	 */
104162306a36Sopenharmony_ci	ese_bits = ICE_FLOW_FV_EXTRACT_SZ * BITS_PER_BYTE;
104262306a36Sopenharmony_ci
104362306a36Sopenharmony_ci	flds[fld].xtrct.prot_id = prot_id;
104462306a36Sopenharmony_ci	flds[fld].xtrct.off = (ice_flds_info[fld].off / ese_bits) *
104562306a36Sopenharmony_ci		ICE_FLOW_FV_EXTRACT_SZ;
104662306a36Sopenharmony_ci	flds[fld].xtrct.disp = (u8)(ice_flds_info[fld].off % ese_bits);
104762306a36Sopenharmony_ci	flds[fld].xtrct.idx = params->es_cnt;
104862306a36Sopenharmony_ci	flds[fld].xtrct.mask = ice_flds_info[fld].mask;
104962306a36Sopenharmony_ci
105062306a36Sopenharmony_ci	/* Adjust the next field-entry index after accommodating the number of
105162306a36Sopenharmony_ci	 * entries this field consumes
105262306a36Sopenharmony_ci	 */
105362306a36Sopenharmony_ci	cnt = DIV_ROUND_UP(flds[fld].xtrct.disp + ice_flds_info[fld].size,
105462306a36Sopenharmony_ci			   ese_bits);
105562306a36Sopenharmony_ci
105662306a36Sopenharmony_ci	/* Fill in the extraction sequence entries needed for this field */
105762306a36Sopenharmony_ci	off = flds[fld].xtrct.off;
105862306a36Sopenharmony_ci	mask = flds[fld].xtrct.mask;
105962306a36Sopenharmony_ci	for (i = 0; i < cnt; i++) {
106062306a36Sopenharmony_ci		/* Only consume an extraction sequence entry if there is no
106162306a36Sopenharmony_ci		 * sibling field associated with this field or the sibling entry
106262306a36Sopenharmony_ci		 * already extracts the word shared with this field.
106362306a36Sopenharmony_ci		 */
106462306a36Sopenharmony_ci		if (sib == ICE_FLOW_FIELD_IDX_MAX ||
106562306a36Sopenharmony_ci		    flds[sib].xtrct.prot_id == ICE_PROT_ID_INVAL ||
106662306a36Sopenharmony_ci		    flds[sib].xtrct.off != off) {
106762306a36Sopenharmony_ci			u8 idx;
106862306a36Sopenharmony_ci
106962306a36Sopenharmony_ci			/* Make sure the number of extraction sequence required
107062306a36Sopenharmony_ci			 * does not exceed the block's capability
107162306a36Sopenharmony_ci			 */
107262306a36Sopenharmony_ci			if (params->es_cnt >= fv_words)
107362306a36Sopenharmony_ci				return -ENOSPC;
107462306a36Sopenharmony_ci
107562306a36Sopenharmony_ci			/* some blocks require a reversed field vector layout */
107662306a36Sopenharmony_ci			if (hw->blk[params->blk].es.reverse)
107762306a36Sopenharmony_ci				idx = fv_words - params->es_cnt - 1;
107862306a36Sopenharmony_ci			else
107962306a36Sopenharmony_ci				idx = params->es_cnt;
108062306a36Sopenharmony_ci
108162306a36Sopenharmony_ci			params->es[idx].prot_id = prot_id;
108262306a36Sopenharmony_ci			params->es[idx].off = off;
108362306a36Sopenharmony_ci			params->mask[idx] = mask | sib_mask;
108462306a36Sopenharmony_ci			params->es_cnt++;
108562306a36Sopenharmony_ci		}
108662306a36Sopenharmony_ci
108762306a36Sopenharmony_ci		off += ICE_FLOW_FV_EXTRACT_SZ;
108862306a36Sopenharmony_ci	}
108962306a36Sopenharmony_ci
109062306a36Sopenharmony_ci	return 0;
109162306a36Sopenharmony_ci}
109262306a36Sopenharmony_ci
109362306a36Sopenharmony_ci/**
109462306a36Sopenharmony_ci * ice_flow_xtract_raws - Create extract sequence entries for raw bytes
109562306a36Sopenharmony_ci * @hw: pointer to the HW struct
109662306a36Sopenharmony_ci * @params: information about the flow to be processed
109762306a36Sopenharmony_ci * @seg: index of packet segment whose raw fields are to be extracted
109862306a36Sopenharmony_ci */
109962306a36Sopenharmony_cistatic int
110062306a36Sopenharmony_ciice_flow_xtract_raws(struct ice_hw *hw, struct ice_flow_prof_params *params,
110162306a36Sopenharmony_ci		     u8 seg)
110262306a36Sopenharmony_ci{
110362306a36Sopenharmony_ci	u16 fv_words;
110462306a36Sopenharmony_ci	u16 hdrs_sz;
110562306a36Sopenharmony_ci	u8 i;
110662306a36Sopenharmony_ci
110762306a36Sopenharmony_ci	if (!params->prof->segs[seg].raws_cnt)
110862306a36Sopenharmony_ci		return 0;
110962306a36Sopenharmony_ci
111062306a36Sopenharmony_ci	if (params->prof->segs[seg].raws_cnt >
111162306a36Sopenharmony_ci	    ARRAY_SIZE(params->prof->segs[seg].raws))
111262306a36Sopenharmony_ci		return -ENOSPC;
111362306a36Sopenharmony_ci
111462306a36Sopenharmony_ci	/* Offsets within the segment headers are not supported */
111562306a36Sopenharmony_ci	hdrs_sz = ice_flow_calc_seg_sz(params, seg);
111662306a36Sopenharmony_ci	if (!hdrs_sz)
111762306a36Sopenharmony_ci		return -EINVAL;
111862306a36Sopenharmony_ci
111962306a36Sopenharmony_ci	fv_words = hw->blk[params->blk].es.fvw;
112062306a36Sopenharmony_ci
112162306a36Sopenharmony_ci	for (i = 0; i < params->prof->segs[seg].raws_cnt; i++) {
112262306a36Sopenharmony_ci		struct ice_flow_seg_fld_raw *raw;
112362306a36Sopenharmony_ci		u16 off, cnt, j;
112462306a36Sopenharmony_ci
112562306a36Sopenharmony_ci		raw = &params->prof->segs[seg].raws[i];
112662306a36Sopenharmony_ci
112762306a36Sopenharmony_ci		/* Storing extraction information */
112862306a36Sopenharmony_ci		raw->info.xtrct.prot_id = ICE_PROT_MAC_OF_OR_S;
112962306a36Sopenharmony_ci		raw->info.xtrct.off = (raw->off / ICE_FLOW_FV_EXTRACT_SZ) *
113062306a36Sopenharmony_ci			ICE_FLOW_FV_EXTRACT_SZ;
113162306a36Sopenharmony_ci		raw->info.xtrct.disp = (raw->off % ICE_FLOW_FV_EXTRACT_SZ) *
113262306a36Sopenharmony_ci			BITS_PER_BYTE;
113362306a36Sopenharmony_ci		raw->info.xtrct.idx = params->es_cnt;
113462306a36Sopenharmony_ci
113562306a36Sopenharmony_ci		/* Determine the number of field vector entries this raw field
113662306a36Sopenharmony_ci		 * consumes.
113762306a36Sopenharmony_ci		 */
113862306a36Sopenharmony_ci		cnt = DIV_ROUND_UP(raw->info.xtrct.disp +
113962306a36Sopenharmony_ci				   (raw->info.src.last * BITS_PER_BYTE),
114062306a36Sopenharmony_ci				   (ICE_FLOW_FV_EXTRACT_SZ * BITS_PER_BYTE));
114162306a36Sopenharmony_ci		off = raw->info.xtrct.off;
114262306a36Sopenharmony_ci		for (j = 0; j < cnt; j++) {
114362306a36Sopenharmony_ci			u16 idx;
114462306a36Sopenharmony_ci
114562306a36Sopenharmony_ci			/* Make sure the number of extraction sequence required
114662306a36Sopenharmony_ci			 * does not exceed the block's capability
114762306a36Sopenharmony_ci			 */
114862306a36Sopenharmony_ci			if (params->es_cnt >= hw->blk[params->blk].es.count ||
114962306a36Sopenharmony_ci			    params->es_cnt >= ICE_MAX_FV_WORDS)
115062306a36Sopenharmony_ci				return -ENOSPC;
115162306a36Sopenharmony_ci
115262306a36Sopenharmony_ci			/* some blocks require a reversed field vector layout */
115362306a36Sopenharmony_ci			if (hw->blk[params->blk].es.reverse)
115462306a36Sopenharmony_ci				idx = fv_words - params->es_cnt - 1;
115562306a36Sopenharmony_ci			else
115662306a36Sopenharmony_ci				idx = params->es_cnt;
115762306a36Sopenharmony_ci
115862306a36Sopenharmony_ci			params->es[idx].prot_id = raw->info.xtrct.prot_id;
115962306a36Sopenharmony_ci			params->es[idx].off = off;
116062306a36Sopenharmony_ci			params->es_cnt++;
116162306a36Sopenharmony_ci			off += ICE_FLOW_FV_EXTRACT_SZ;
116262306a36Sopenharmony_ci		}
116362306a36Sopenharmony_ci	}
116462306a36Sopenharmony_ci
116562306a36Sopenharmony_ci	return 0;
116662306a36Sopenharmony_ci}
116762306a36Sopenharmony_ci
116862306a36Sopenharmony_ci/**
116962306a36Sopenharmony_ci * ice_flow_create_xtrct_seq - Create an extraction sequence for given segments
117062306a36Sopenharmony_ci * @hw: pointer to the HW struct
117162306a36Sopenharmony_ci * @params: information about the flow to be processed
117262306a36Sopenharmony_ci *
117362306a36Sopenharmony_ci * This function iterates through all matched fields in the given segments, and
117462306a36Sopenharmony_ci * creates an extraction sequence for the fields.
117562306a36Sopenharmony_ci */
117662306a36Sopenharmony_cistatic int
117762306a36Sopenharmony_ciice_flow_create_xtrct_seq(struct ice_hw *hw,
117862306a36Sopenharmony_ci			  struct ice_flow_prof_params *params)
117962306a36Sopenharmony_ci{
118062306a36Sopenharmony_ci	struct ice_flow_prof *prof = params->prof;
118162306a36Sopenharmony_ci	int status = 0;
118262306a36Sopenharmony_ci	u8 i;
118362306a36Sopenharmony_ci
118462306a36Sopenharmony_ci	for (i = 0; i < prof->segs_cnt; i++) {
118562306a36Sopenharmony_ci		u64 match = params->prof->segs[i].match;
118662306a36Sopenharmony_ci		enum ice_flow_field j;
118762306a36Sopenharmony_ci
118862306a36Sopenharmony_ci		for_each_set_bit(j, (unsigned long *)&match,
118962306a36Sopenharmony_ci				 ICE_FLOW_FIELD_IDX_MAX) {
119062306a36Sopenharmony_ci			status = ice_flow_xtract_fld(hw, params, i, j, match);
119162306a36Sopenharmony_ci			if (status)
119262306a36Sopenharmony_ci				return status;
119362306a36Sopenharmony_ci			clear_bit(j, (unsigned long *)&match);
119462306a36Sopenharmony_ci		}
119562306a36Sopenharmony_ci
119662306a36Sopenharmony_ci		/* Process raw matching bytes */
119762306a36Sopenharmony_ci		status = ice_flow_xtract_raws(hw, params, i);
119862306a36Sopenharmony_ci		if (status)
119962306a36Sopenharmony_ci			return status;
120062306a36Sopenharmony_ci	}
120162306a36Sopenharmony_ci
120262306a36Sopenharmony_ci	return status;
120362306a36Sopenharmony_ci}
120462306a36Sopenharmony_ci
120562306a36Sopenharmony_ci/**
120662306a36Sopenharmony_ci * ice_flow_proc_segs - process all packet segments associated with a profile
120762306a36Sopenharmony_ci * @hw: pointer to the HW struct
120862306a36Sopenharmony_ci * @params: information about the flow to be processed
120962306a36Sopenharmony_ci */
121062306a36Sopenharmony_cistatic int
121162306a36Sopenharmony_ciice_flow_proc_segs(struct ice_hw *hw, struct ice_flow_prof_params *params)
121262306a36Sopenharmony_ci{
121362306a36Sopenharmony_ci	int status;
121462306a36Sopenharmony_ci
121562306a36Sopenharmony_ci	status = ice_flow_proc_seg_hdrs(params);
121662306a36Sopenharmony_ci	if (status)
121762306a36Sopenharmony_ci		return status;
121862306a36Sopenharmony_ci
121962306a36Sopenharmony_ci	status = ice_flow_create_xtrct_seq(hw, params);
122062306a36Sopenharmony_ci	if (status)
122162306a36Sopenharmony_ci		return status;
122262306a36Sopenharmony_ci
122362306a36Sopenharmony_ci	switch (params->blk) {
122462306a36Sopenharmony_ci	case ICE_BLK_FD:
122562306a36Sopenharmony_ci	case ICE_BLK_RSS:
122662306a36Sopenharmony_ci		status = 0;
122762306a36Sopenharmony_ci		break;
122862306a36Sopenharmony_ci	default:
122962306a36Sopenharmony_ci		return -EOPNOTSUPP;
123062306a36Sopenharmony_ci	}
123162306a36Sopenharmony_ci
123262306a36Sopenharmony_ci	return status;
123362306a36Sopenharmony_ci}
123462306a36Sopenharmony_ci
123562306a36Sopenharmony_ci#define ICE_FLOW_FIND_PROF_CHK_FLDS	0x00000001
123662306a36Sopenharmony_ci#define ICE_FLOW_FIND_PROF_CHK_VSI	0x00000002
123762306a36Sopenharmony_ci#define ICE_FLOW_FIND_PROF_NOT_CHK_DIR	0x00000004
123862306a36Sopenharmony_ci
123962306a36Sopenharmony_ci/**
124062306a36Sopenharmony_ci * ice_flow_find_prof_conds - Find a profile matching headers and conditions
124162306a36Sopenharmony_ci * @hw: pointer to the HW struct
124262306a36Sopenharmony_ci * @blk: classification stage
124362306a36Sopenharmony_ci * @dir: flow direction
124462306a36Sopenharmony_ci * @segs: array of one or more packet segments that describe the flow
124562306a36Sopenharmony_ci * @segs_cnt: number of packet segments provided
124662306a36Sopenharmony_ci * @vsi_handle: software VSI handle to check VSI (ICE_FLOW_FIND_PROF_CHK_VSI)
124762306a36Sopenharmony_ci * @conds: additional conditions to be checked (ICE_FLOW_FIND_PROF_CHK_*)
124862306a36Sopenharmony_ci */
124962306a36Sopenharmony_cistatic struct ice_flow_prof *
125062306a36Sopenharmony_ciice_flow_find_prof_conds(struct ice_hw *hw, enum ice_block blk,
125162306a36Sopenharmony_ci			 enum ice_flow_dir dir, struct ice_flow_seg_info *segs,
125262306a36Sopenharmony_ci			 u8 segs_cnt, u16 vsi_handle, u32 conds)
125362306a36Sopenharmony_ci{
125462306a36Sopenharmony_ci	struct ice_flow_prof *p, *prof = NULL;
125562306a36Sopenharmony_ci
125662306a36Sopenharmony_ci	mutex_lock(&hw->fl_profs_locks[blk]);
125762306a36Sopenharmony_ci	list_for_each_entry(p, &hw->fl_profs[blk], l_entry)
125862306a36Sopenharmony_ci		if ((p->dir == dir || conds & ICE_FLOW_FIND_PROF_NOT_CHK_DIR) &&
125962306a36Sopenharmony_ci		    segs_cnt && segs_cnt == p->segs_cnt) {
126062306a36Sopenharmony_ci			u8 i;
126162306a36Sopenharmony_ci
126262306a36Sopenharmony_ci			/* Check for profile-VSI association if specified */
126362306a36Sopenharmony_ci			if ((conds & ICE_FLOW_FIND_PROF_CHK_VSI) &&
126462306a36Sopenharmony_ci			    ice_is_vsi_valid(hw, vsi_handle) &&
126562306a36Sopenharmony_ci			    !test_bit(vsi_handle, p->vsis))
126662306a36Sopenharmony_ci				continue;
126762306a36Sopenharmony_ci
126862306a36Sopenharmony_ci			/* Protocol headers must be checked. Matched fields are
126962306a36Sopenharmony_ci			 * checked if specified.
127062306a36Sopenharmony_ci			 */
127162306a36Sopenharmony_ci			for (i = 0; i < segs_cnt; i++)
127262306a36Sopenharmony_ci				if (segs[i].hdrs != p->segs[i].hdrs ||
127362306a36Sopenharmony_ci				    ((conds & ICE_FLOW_FIND_PROF_CHK_FLDS) &&
127462306a36Sopenharmony_ci				     segs[i].match != p->segs[i].match))
127562306a36Sopenharmony_ci					break;
127662306a36Sopenharmony_ci
127762306a36Sopenharmony_ci			/* A match is found if all segments are matched */
127862306a36Sopenharmony_ci			if (i == segs_cnt) {
127962306a36Sopenharmony_ci				prof = p;
128062306a36Sopenharmony_ci				break;
128162306a36Sopenharmony_ci			}
128262306a36Sopenharmony_ci		}
128362306a36Sopenharmony_ci	mutex_unlock(&hw->fl_profs_locks[blk]);
128462306a36Sopenharmony_ci
128562306a36Sopenharmony_ci	return prof;
128662306a36Sopenharmony_ci}
128762306a36Sopenharmony_ci
128862306a36Sopenharmony_ci/**
128962306a36Sopenharmony_ci * ice_flow_find_prof_id - Look up a profile with given profile ID
129062306a36Sopenharmony_ci * @hw: pointer to the HW struct
129162306a36Sopenharmony_ci * @blk: classification stage
129262306a36Sopenharmony_ci * @prof_id: unique ID to identify this flow profile
129362306a36Sopenharmony_ci */
129462306a36Sopenharmony_cistatic struct ice_flow_prof *
129562306a36Sopenharmony_ciice_flow_find_prof_id(struct ice_hw *hw, enum ice_block blk, u64 prof_id)
129662306a36Sopenharmony_ci{
129762306a36Sopenharmony_ci	struct ice_flow_prof *p;
129862306a36Sopenharmony_ci
129962306a36Sopenharmony_ci	list_for_each_entry(p, &hw->fl_profs[blk], l_entry)
130062306a36Sopenharmony_ci		if (p->id == prof_id)
130162306a36Sopenharmony_ci			return p;
130262306a36Sopenharmony_ci
130362306a36Sopenharmony_ci	return NULL;
130462306a36Sopenharmony_ci}
130562306a36Sopenharmony_ci
130662306a36Sopenharmony_ci/**
130762306a36Sopenharmony_ci * ice_flow_rem_entry_sync - Remove a flow entry
130862306a36Sopenharmony_ci * @hw: pointer to the HW struct
130962306a36Sopenharmony_ci * @blk: classification stage
131062306a36Sopenharmony_ci * @entry: flow entry to be removed
131162306a36Sopenharmony_ci */
131262306a36Sopenharmony_cistatic int
131362306a36Sopenharmony_ciice_flow_rem_entry_sync(struct ice_hw *hw, enum ice_block __always_unused blk,
131462306a36Sopenharmony_ci			struct ice_flow_entry *entry)
131562306a36Sopenharmony_ci{
131662306a36Sopenharmony_ci	if (!entry)
131762306a36Sopenharmony_ci		return -EINVAL;
131862306a36Sopenharmony_ci
131962306a36Sopenharmony_ci	list_del(&entry->l_entry);
132062306a36Sopenharmony_ci
132162306a36Sopenharmony_ci	devm_kfree(ice_hw_to_dev(hw), entry->entry);
132262306a36Sopenharmony_ci	devm_kfree(ice_hw_to_dev(hw), entry);
132362306a36Sopenharmony_ci
132462306a36Sopenharmony_ci	return 0;
132562306a36Sopenharmony_ci}
132662306a36Sopenharmony_ci
132762306a36Sopenharmony_ci/**
132862306a36Sopenharmony_ci * ice_flow_add_prof_sync - Add a flow profile for packet segments and fields
132962306a36Sopenharmony_ci * @hw: pointer to the HW struct
133062306a36Sopenharmony_ci * @blk: classification stage
133162306a36Sopenharmony_ci * @dir: flow direction
133262306a36Sopenharmony_ci * @prof_id: unique ID to identify this flow profile
133362306a36Sopenharmony_ci * @segs: array of one or more packet segments that describe the flow
133462306a36Sopenharmony_ci * @segs_cnt: number of packet segments provided
133562306a36Sopenharmony_ci * @prof: stores the returned flow profile added
133662306a36Sopenharmony_ci *
133762306a36Sopenharmony_ci * Assumption: the caller has acquired the lock to the profile list
133862306a36Sopenharmony_ci */
133962306a36Sopenharmony_cistatic int
134062306a36Sopenharmony_ciice_flow_add_prof_sync(struct ice_hw *hw, enum ice_block blk,
134162306a36Sopenharmony_ci		       enum ice_flow_dir dir, u64 prof_id,
134262306a36Sopenharmony_ci		       struct ice_flow_seg_info *segs, u8 segs_cnt,
134362306a36Sopenharmony_ci		       struct ice_flow_prof **prof)
134462306a36Sopenharmony_ci{
134562306a36Sopenharmony_ci	struct ice_flow_prof_params *params;
134662306a36Sopenharmony_ci	int status;
134762306a36Sopenharmony_ci	u8 i;
134862306a36Sopenharmony_ci
134962306a36Sopenharmony_ci	if (!prof)
135062306a36Sopenharmony_ci		return -EINVAL;
135162306a36Sopenharmony_ci
135262306a36Sopenharmony_ci	params = kzalloc(sizeof(*params), GFP_KERNEL);
135362306a36Sopenharmony_ci	if (!params)
135462306a36Sopenharmony_ci		return -ENOMEM;
135562306a36Sopenharmony_ci
135662306a36Sopenharmony_ci	params->prof = devm_kzalloc(ice_hw_to_dev(hw), sizeof(*params->prof),
135762306a36Sopenharmony_ci				    GFP_KERNEL);
135862306a36Sopenharmony_ci	if (!params->prof) {
135962306a36Sopenharmony_ci		status = -ENOMEM;
136062306a36Sopenharmony_ci		goto free_params;
136162306a36Sopenharmony_ci	}
136262306a36Sopenharmony_ci
136362306a36Sopenharmony_ci	/* initialize extraction sequence to all invalid (0xff) */
136462306a36Sopenharmony_ci	for (i = 0; i < ICE_MAX_FV_WORDS; i++) {
136562306a36Sopenharmony_ci		params->es[i].prot_id = ICE_PROT_INVALID;
136662306a36Sopenharmony_ci		params->es[i].off = ICE_FV_OFFSET_INVAL;
136762306a36Sopenharmony_ci	}
136862306a36Sopenharmony_ci
136962306a36Sopenharmony_ci	params->blk = blk;
137062306a36Sopenharmony_ci	params->prof->id = prof_id;
137162306a36Sopenharmony_ci	params->prof->dir = dir;
137262306a36Sopenharmony_ci	params->prof->segs_cnt = segs_cnt;
137362306a36Sopenharmony_ci
137462306a36Sopenharmony_ci	/* Make a copy of the segments that need to be persistent in the flow
137562306a36Sopenharmony_ci	 * profile instance
137662306a36Sopenharmony_ci	 */
137762306a36Sopenharmony_ci	for (i = 0; i < segs_cnt; i++)
137862306a36Sopenharmony_ci		memcpy(&params->prof->segs[i], &segs[i], sizeof(*segs));
137962306a36Sopenharmony_ci
138062306a36Sopenharmony_ci	status = ice_flow_proc_segs(hw, params);
138162306a36Sopenharmony_ci	if (status) {
138262306a36Sopenharmony_ci		ice_debug(hw, ICE_DBG_FLOW, "Error processing a flow's packet segments\n");
138362306a36Sopenharmony_ci		goto out;
138462306a36Sopenharmony_ci	}
138562306a36Sopenharmony_ci
138662306a36Sopenharmony_ci	/* Add a HW profile for this flow profile */
138762306a36Sopenharmony_ci	status = ice_add_prof(hw, blk, prof_id, (u8 *)params->ptypes,
138862306a36Sopenharmony_ci			      params->attr, params->attr_cnt, params->es,
138962306a36Sopenharmony_ci			      params->mask);
139062306a36Sopenharmony_ci	if (status) {
139162306a36Sopenharmony_ci		ice_debug(hw, ICE_DBG_FLOW, "Error adding a HW flow profile\n");
139262306a36Sopenharmony_ci		goto out;
139362306a36Sopenharmony_ci	}
139462306a36Sopenharmony_ci
139562306a36Sopenharmony_ci	INIT_LIST_HEAD(&params->prof->entries);
139662306a36Sopenharmony_ci	mutex_init(&params->prof->entries_lock);
139762306a36Sopenharmony_ci	*prof = params->prof;
139862306a36Sopenharmony_ci
139962306a36Sopenharmony_ciout:
140062306a36Sopenharmony_ci	if (status)
140162306a36Sopenharmony_ci		devm_kfree(ice_hw_to_dev(hw), params->prof);
140262306a36Sopenharmony_cifree_params:
140362306a36Sopenharmony_ci	kfree(params);
140462306a36Sopenharmony_ci
140562306a36Sopenharmony_ci	return status;
140662306a36Sopenharmony_ci}
140762306a36Sopenharmony_ci
140862306a36Sopenharmony_ci/**
140962306a36Sopenharmony_ci * ice_flow_rem_prof_sync - remove a flow profile
141062306a36Sopenharmony_ci * @hw: pointer to the hardware structure
141162306a36Sopenharmony_ci * @blk: classification stage
141262306a36Sopenharmony_ci * @prof: pointer to flow profile to remove
141362306a36Sopenharmony_ci *
141462306a36Sopenharmony_ci * Assumption: the caller has acquired the lock to the profile list
141562306a36Sopenharmony_ci */
141662306a36Sopenharmony_cistatic int
141762306a36Sopenharmony_ciice_flow_rem_prof_sync(struct ice_hw *hw, enum ice_block blk,
141862306a36Sopenharmony_ci		       struct ice_flow_prof *prof)
141962306a36Sopenharmony_ci{
142062306a36Sopenharmony_ci	int status;
142162306a36Sopenharmony_ci
142262306a36Sopenharmony_ci	/* Remove all remaining flow entries before removing the flow profile */
142362306a36Sopenharmony_ci	if (!list_empty(&prof->entries)) {
142462306a36Sopenharmony_ci		struct ice_flow_entry *e, *t;
142562306a36Sopenharmony_ci
142662306a36Sopenharmony_ci		mutex_lock(&prof->entries_lock);
142762306a36Sopenharmony_ci
142862306a36Sopenharmony_ci		list_for_each_entry_safe(e, t, &prof->entries, l_entry) {
142962306a36Sopenharmony_ci			status = ice_flow_rem_entry_sync(hw, blk, e);
143062306a36Sopenharmony_ci			if (status)
143162306a36Sopenharmony_ci				break;
143262306a36Sopenharmony_ci		}
143362306a36Sopenharmony_ci
143462306a36Sopenharmony_ci		mutex_unlock(&prof->entries_lock);
143562306a36Sopenharmony_ci	}
143662306a36Sopenharmony_ci
143762306a36Sopenharmony_ci	/* Remove all hardware profiles associated with this flow profile */
143862306a36Sopenharmony_ci	status = ice_rem_prof(hw, blk, prof->id);
143962306a36Sopenharmony_ci	if (!status) {
144062306a36Sopenharmony_ci		list_del(&prof->l_entry);
144162306a36Sopenharmony_ci		mutex_destroy(&prof->entries_lock);
144262306a36Sopenharmony_ci		devm_kfree(ice_hw_to_dev(hw), prof);
144362306a36Sopenharmony_ci	}
144462306a36Sopenharmony_ci
144562306a36Sopenharmony_ci	return status;
144662306a36Sopenharmony_ci}
144762306a36Sopenharmony_ci
144862306a36Sopenharmony_ci/**
144962306a36Sopenharmony_ci * ice_flow_assoc_prof - associate a VSI with a flow profile
145062306a36Sopenharmony_ci * @hw: pointer to the hardware structure
145162306a36Sopenharmony_ci * @blk: classification stage
145262306a36Sopenharmony_ci * @prof: pointer to flow profile
145362306a36Sopenharmony_ci * @vsi_handle: software VSI handle
145462306a36Sopenharmony_ci *
145562306a36Sopenharmony_ci * Assumption: the caller has acquired the lock to the profile list
145662306a36Sopenharmony_ci * and the software VSI handle has been validated
145762306a36Sopenharmony_ci */
145862306a36Sopenharmony_cistatic int
145962306a36Sopenharmony_ciice_flow_assoc_prof(struct ice_hw *hw, enum ice_block blk,
146062306a36Sopenharmony_ci		    struct ice_flow_prof *prof, u16 vsi_handle)
146162306a36Sopenharmony_ci{
146262306a36Sopenharmony_ci	int status = 0;
146362306a36Sopenharmony_ci
146462306a36Sopenharmony_ci	if (!test_bit(vsi_handle, prof->vsis)) {
146562306a36Sopenharmony_ci		status = ice_add_prof_id_flow(hw, blk,
146662306a36Sopenharmony_ci					      ice_get_hw_vsi_num(hw,
146762306a36Sopenharmony_ci								 vsi_handle),
146862306a36Sopenharmony_ci					      prof->id);
146962306a36Sopenharmony_ci		if (!status)
147062306a36Sopenharmony_ci			set_bit(vsi_handle, prof->vsis);
147162306a36Sopenharmony_ci		else
147262306a36Sopenharmony_ci			ice_debug(hw, ICE_DBG_FLOW, "HW profile add failed, %d\n",
147362306a36Sopenharmony_ci				  status);
147462306a36Sopenharmony_ci	}
147562306a36Sopenharmony_ci
147662306a36Sopenharmony_ci	return status;
147762306a36Sopenharmony_ci}
147862306a36Sopenharmony_ci
147962306a36Sopenharmony_ci/**
148062306a36Sopenharmony_ci * ice_flow_disassoc_prof - disassociate a VSI from a flow profile
148162306a36Sopenharmony_ci * @hw: pointer to the hardware structure
148262306a36Sopenharmony_ci * @blk: classification stage
148362306a36Sopenharmony_ci * @prof: pointer to flow profile
148462306a36Sopenharmony_ci * @vsi_handle: software VSI handle
148562306a36Sopenharmony_ci *
148662306a36Sopenharmony_ci * Assumption: the caller has acquired the lock to the profile list
148762306a36Sopenharmony_ci * and the software VSI handle has been validated
148862306a36Sopenharmony_ci */
148962306a36Sopenharmony_cistatic int
149062306a36Sopenharmony_ciice_flow_disassoc_prof(struct ice_hw *hw, enum ice_block blk,
149162306a36Sopenharmony_ci		       struct ice_flow_prof *prof, u16 vsi_handle)
149262306a36Sopenharmony_ci{
149362306a36Sopenharmony_ci	int status = 0;
149462306a36Sopenharmony_ci
149562306a36Sopenharmony_ci	if (test_bit(vsi_handle, prof->vsis)) {
149662306a36Sopenharmony_ci		status = ice_rem_prof_id_flow(hw, blk,
149762306a36Sopenharmony_ci					      ice_get_hw_vsi_num(hw,
149862306a36Sopenharmony_ci								 vsi_handle),
149962306a36Sopenharmony_ci					      prof->id);
150062306a36Sopenharmony_ci		if (!status)
150162306a36Sopenharmony_ci			clear_bit(vsi_handle, prof->vsis);
150262306a36Sopenharmony_ci		else
150362306a36Sopenharmony_ci			ice_debug(hw, ICE_DBG_FLOW, "HW profile remove failed, %d\n",
150462306a36Sopenharmony_ci				  status);
150562306a36Sopenharmony_ci	}
150662306a36Sopenharmony_ci
150762306a36Sopenharmony_ci	return status;
150862306a36Sopenharmony_ci}
150962306a36Sopenharmony_ci
151062306a36Sopenharmony_ci/**
151162306a36Sopenharmony_ci * ice_flow_add_prof - Add a flow profile for packet segments and matched fields
151262306a36Sopenharmony_ci * @hw: pointer to the HW struct
151362306a36Sopenharmony_ci * @blk: classification stage
151462306a36Sopenharmony_ci * @dir: flow direction
151562306a36Sopenharmony_ci * @prof_id: unique ID to identify this flow profile
151662306a36Sopenharmony_ci * @segs: array of one or more packet segments that describe the flow
151762306a36Sopenharmony_ci * @segs_cnt: number of packet segments provided
151862306a36Sopenharmony_ci * @prof: stores the returned flow profile added
151962306a36Sopenharmony_ci */
152062306a36Sopenharmony_ciint
152162306a36Sopenharmony_ciice_flow_add_prof(struct ice_hw *hw, enum ice_block blk, enum ice_flow_dir dir,
152262306a36Sopenharmony_ci		  u64 prof_id, struct ice_flow_seg_info *segs, u8 segs_cnt,
152362306a36Sopenharmony_ci		  struct ice_flow_prof **prof)
152462306a36Sopenharmony_ci{
152562306a36Sopenharmony_ci	int status;
152662306a36Sopenharmony_ci
152762306a36Sopenharmony_ci	if (segs_cnt > ICE_FLOW_SEG_MAX)
152862306a36Sopenharmony_ci		return -ENOSPC;
152962306a36Sopenharmony_ci
153062306a36Sopenharmony_ci	if (!segs_cnt)
153162306a36Sopenharmony_ci		return -EINVAL;
153262306a36Sopenharmony_ci
153362306a36Sopenharmony_ci	if (!segs)
153462306a36Sopenharmony_ci		return -EINVAL;
153562306a36Sopenharmony_ci
153662306a36Sopenharmony_ci	status = ice_flow_val_hdrs(segs, segs_cnt);
153762306a36Sopenharmony_ci	if (status)
153862306a36Sopenharmony_ci		return status;
153962306a36Sopenharmony_ci
154062306a36Sopenharmony_ci	mutex_lock(&hw->fl_profs_locks[blk]);
154162306a36Sopenharmony_ci
154262306a36Sopenharmony_ci	status = ice_flow_add_prof_sync(hw, blk, dir, prof_id, segs, segs_cnt,
154362306a36Sopenharmony_ci					prof);
154462306a36Sopenharmony_ci	if (!status)
154562306a36Sopenharmony_ci		list_add(&(*prof)->l_entry, &hw->fl_profs[blk]);
154662306a36Sopenharmony_ci
154762306a36Sopenharmony_ci	mutex_unlock(&hw->fl_profs_locks[blk]);
154862306a36Sopenharmony_ci
154962306a36Sopenharmony_ci	return status;
155062306a36Sopenharmony_ci}
155162306a36Sopenharmony_ci
155262306a36Sopenharmony_ci/**
155362306a36Sopenharmony_ci * ice_flow_rem_prof - Remove a flow profile and all entries associated with it
155462306a36Sopenharmony_ci * @hw: pointer to the HW struct
155562306a36Sopenharmony_ci * @blk: the block for which the flow profile is to be removed
155662306a36Sopenharmony_ci * @prof_id: unique ID of the flow profile to be removed
155762306a36Sopenharmony_ci */
155862306a36Sopenharmony_ciint ice_flow_rem_prof(struct ice_hw *hw, enum ice_block blk, u64 prof_id)
155962306a36Sopenharmony_ci{
156062306a36Sopenharmony_ci	struct ice_flow_prof *prof;
156162306a36Sopenharmony_ci	int status;
156262306a36Sopenharmony_ci
156362306a36Sopenharmony_ci	mutex_lock(&hw->fl_profs_locks[blk]);
156462306a36Sopenharmony_ci
156562306a36Sopenharmony_ci	prof = ice_flow_find_prof_id(hw, blk, prof_id);
156662306a36Sopenharmony_ci	if (!prof) {
156762306a36Sopenharmony_ci		status = -ENOENT;
156862306a36Sopenharmony_ci		goto out;
156962306a36Sopenharmony_ci	}
157062306a36Sopenharmony_ci
157162306a36Sopenharmony_ci	/* prof becomes invalid after the call */
157262306a36Sopenharmony_ci	status = ice_flow_rem_prof_sync(hw, blk, prof);
157362306a36Sopenharmony_ci
157462306a36Sopenharmony_ciout:
157562306a36Sopenharmony_ci	mutex_unlock(&hw->fl_profs_locks[blk]);
157662306a36Sopenharmony_ci
157762306a36Sopenharmony_ci	return status;
157862306a36Sopenharmony_ci}
157962306a36Sopenharmony_ci
158062306a36Sopenharmony_ci/**
158162306a36Sopenharmony_ci * ice_flow_add_entry - Add a flow entry
158262306a36Sopenharmony_ci * @hw: pointer to the HW struct
158362306a36Sopenharmony_ci * @blk: classification stage
158462306a36Sopenharmony_ci * @prof_id: ID of the profile to add a new flow entry to
158562306a36Sopenharmony_ci * @entry_id: unique ID to identify this flow entry
158662306a36Sopenharmony_ci * @vsi_handle: software VSI handle for the flow entry
158762306a36Sopenharmony_ci * @prio: priority of the flow entry
158862306a36Sopenharmony_ci * @data: pointer to a data buffer containing flow entry's match values/masks
158962306a36Sopenharmony_ci * @entry_h: pointer to buffer that receives the new flow entry's handle
159062306a36Sopenharmony_ci */
159162306a36Sopenharmony_ciint
159262306a36Sopenharmony_ciice_flow_add_entry(struct ice_hw *hw, enum ice_block blk, u64 prof_id,
159362306a36Sopenharmony_ci		   u64 entry_id, u16 vsi_handle, enum ice_flow_priority prio,
159462306a36Sopenharmony_ci		   void *data, u64 *entry_h)
159562306a36Sopenharmony_ci{
159662306a36Sopenharmony_ci	struct ice_flow_entry *e = NULL;
159762306a36Sopenharmony_ci	struct ice_flow_prof *prof;
159862306a36Sopenharmony_ci	int status;
159962306a36Sopenharmony_ci
160062306a36Sopenharmony_ci	/* No flow entry data is expected for RSS */
160162306a36Sopenharmony_ci	if (!entry_h || (!data && blk != ICE_BLK_RSS))
160262306a36Sopenharmony_ci		return -EINVAL;
160362306a36Sopenharmony_ci
160462306a36Sopenharmony_ci	if (!ice_is_vsi_valid(hw, vsi_handle))
160562306a36Sopenharmony_ci		return -EINVAL;
160662306a36Sopenharmony_ci
160762306a36Sopenharmony_ci	mutex_lock(&hw->fl_profs_locks[blk]);
160862306a36Sopenharmony_ci
160962306a36Sopenharmony_ci	prof = ice_flow_find_prof_id(hw, blk, prof_id);
161062306a36Sopenharmony_ci	if (!prof) {
161162306a36Sopenharmony_ci		status = -ENOENT;
161262306a36Sopenharmony_ci	} else {
161362306a36Sopenharmony_ci		/* Allocate memory for the entry being added and associate
161462306a36Sopenharmony_ci		 * the VSI to the found flow profile
161562306a36Sopenharmony_ci		 */
161662306a36Sopenharmony_ci		e = devm_kzalloc(ice_hw_to_dev(hw), sizeof(*e), GFP_KERNEL);
161762306a36Sopenharmony_ci		if (!e)
161862306a36Sopenharmony_ci			status = -ENOMEM;
161962306a36Sopenharmony_ci		else
162062306a36Sopenharmony_ci			status = ice_flow_assoc_prof(hw, blk, prof, vsi_handle);
162162306a36Sopenharmony_ci	}
162262306a36Sopenharmony_ci
162362306a36Sopenharmony_ci	mutex_unlock(&hw->fl_profs_locks[blk]);
162462306a36Sopenharmony_ci	if (status)
162562306a36Sopenharmony_ci		goto out;
162662306a36Sopenharmony_ci
162762306a36Sopenharmony_ci	e->id = entry_id;
162862306a36Sopenharmony_ci	e->vsi_handle = vsi_handle;
162962306a36Sopenharmony_ci	e->prof = prof;
163062306a36Sopenharmony_ci	e->priority = prio;
163162306a36Sopenharmony_ci
163262306a36Sopenharmony_ci	switch (blk) {
163362306a36Sopenharmony_ci	case ICE_BLK_FD:
163462306a36Sopenharmony_ci	case ICE_BLK_RSS:
163562306a36Sopenharmony_ci		break;
163662306a36Sopenharmony_ci	default:
163762306a36Sopenharmony_ci		status = -EOPNOTSUPP;
163862306a36Sopenharmony_ci		goto out;
163962306a36Sopenharmony_ci	}
164062306a36Sopenharmony_ci
164162306a36Sopenharmony_ci	mutex_lock(&prof->entries_lock);
164262306a36Sopenharmony_ci	list_add(&e->l_entry, &prof->entries);
164362306a36Sopenharmony_ci	mutex_unlock(&prof->entries_lock);
164462306a36Sopenharmony_ci
164562306a36Sopenharmony_ci	*entry_h = ICE_FLOW_ENTRY_HNDL(e);
164662306a36Sopenharmony_ci
164762306a36Sopenharmony_ciout:
164862306a36Sopenharmony_ci	if (status && e) {
164962306a36Sopenharmony_ci		devm_kfree(ice_hw_to_dev(hw), e->entry);
165062306a36Sopenharmony_ci		devm_kfree(ice_hw_to_dev(hw), e);
165162306a36Sopenharmony_ci	}
165262306a36Sopenharmony_ci
165362306a36Sopenharmony_ci	return status;
165462306a36Sopenharmony_ci}
165562306a36Sopenharmony_ci
165662306a36Sopenharmony_ci/**
165762306a36Sopenharmony_ci * ice_flow_rem_entry - Remove a flow entry
165862306a36Sopenharmony_ci * @hw: pointer to the HW struct
165962306a36Sopenharmony_ci * @blk: classification stage
166062306a36Sopenharmony_ci * @entry_h: handle to the flow entry to be removed
166162306a36Sopenharmony_ci */
166262306a36Sopenharmony_ciint ice_flow_rem_entry(struct ice_hw *hw, enum ice_block blk, u64 entry_h)
166362306a36Sopenharmony_ci{
166462306a36Sopenharmony_ci	struct ice_flow_entry *entry;
166562306a36Sopenharmony_ci	struct ice_flow_prof *prof;
166662306a36Sopenharmony_ci	int status = 0;
166762306a36Sopenharmony_ci
166862306a36Sopenharmony_ci	if (entry_h == ICE_FLOW_ENTRY_HANDLE_INVAL)
166962306a36Sopenharmony_ci		return -EINVAL;
167062306a36Sopenharmony_ci
167162306a36Sopenharmony_ci	entry = ICE_FLOW_ENTRY_PTR(entry_h);
167262306a36Sopenharmony_ci
167362306a36Sopenharmony_ci	/* Retain the pointer to the flow profile as the entry will be freed */
167462306a36Sopenharmony_ci	prof = entry->prof;
167562306a36Sopenharmony_ci
167662306a36Sopenharmony_ci	if (prof) {
167762306a36Sopenharmony_ci		mutex_lock(&prof->entries_lock);
167862306a36Sopenharmony_ci		status = ice_flow_rem_entry_sync(hw, blk, entry);
167962306a36Sopenharmony_ci		mutex_unlock(&prof->entries_lock);
168062306a36Sopenharmony_ci	}
168162306a36Sopenharmony_ci
168262306a36Sopenharmony_ci	return status;
168362306a36Sopenharmony_ci}
168462306a36Sopenharmony_ci
168562306a36Sopenharmony_ci/**
168662306a36Sopenharmony_ci * ice_flow_set_fld_ext - specifies locations of field from entry's input buffer
168762306a36Sopenharmony_ci * @seg: packet segment the field being set belongs to
168862306a36Sopenharmony_ci * @fld: field to be set
168962306a36Sopenharmony_ci * @field_type: type of the field
169062306a36Sopenharmony_ci * @val_loc: if not ICE_FLOW_FLD_OFF_INVAL, location of the value to match from
169162306a36Sopenharmony_ci *           entry's input buffer
169262306a36Sopenharmony_ci * @mask_loc: if not ICE_FLOW_FLD_OFF_INVAL, location of mask value from entry's
169362306a36Sopenharmony_ci *            input buffer
169462306a36Sopenharmony_ci * @last_loc: if not ICE_FLOW_FLD_OFF_INVAL, location of last/upper value from
169562306a36Sopenharmony_ci *            entry's input buffer
169662306a36Sopenharmony_ci *
169762306a36Sopenharmony_ci * This helper function stores information of a field being matched, including
169862306a36Sopenharmony_ci * the type of the field and the locations of the value to match, the mask, and
169962306a36Sopenharmony_ci * the upper-bound value in the start of the input buffer for a flow entry.
170062306a36Sopenharmony_ci * This function should only be used for fixed-size data structures.
170162306a36Sopenharmony_ci *
170262306a36Sopenharmony_ci * This function also opportunistically determines the protocol headers to be
170362306a36Sopenharmony_ci * present based on the fields being set. Some fields cannot be used alone to
170462306a36Sopenharmony_ci * determine the protocol headers present. Sometimes, fields for particular
170562306a36Sopenharmony_ci * protocol headers are not matched. In those cases, the protocol headers
170662306a36Sopenharmony_ci * must be explicitly set.
170762306a36Sopenharmony_ci */
170862306a36Sopenharmony_cistatic void
170962306a36Sopenharmony_ciice_flow_set_fld_ext(struct ice_flow_seg_info *seg, enum ice_flow_field fld,
171062306a36Sopenharmony_ci		     enum ice_flow_fld_match_type field_type, u16 val_loc,
171162306a36Sopenharmony_ci		     u16 mask_loc, u16 last_loc)
171262306a36Sopenharmony_ci{
171362306a36Sopenharmony_ci	u64 bit = BIT_ULL(fld);
171462306a36Sopenharmony_ci
171562306a36Sopenharmony_ci	seg->match |= bit;
171662306a36Sopenharmony_ci	if (field_type == ICE_FLOW_FLD_TYPE_RANGE)
171762306a36Sopenharmony_ci		seg->range |= bit;
171862306a36Sopenharmony_ci
171962306a36Sopenharmony_ci	seg->fields[fld].type = field_type;
172062306a36Sopenharmony_ci	seg->fields[fld].src.val = val_loc;
172162306a36Sopenharmony_ci	seg->fields[fld].src.mask = mask_loc;
172262306a36Sopenharmony_ci	seg->fields[fld].src.last = last_loc;
172362306a36Sopenharmony_ci
172462306a36Sopenharmony_ci	ICE_FLOW_SET_HDRS(seg, ice_flds_info[fld].hdr);
172562306a36Sopenharmony_ci}
172662306a36Sopenharmony_ci
172762306a36Sopenharmony_ci/**
172862306a36Sopenharmony_ci * ice_flow_set_fld - specifies locations of field from entry's input buffer
172962306a36Sopenharmony_ci * @seg: packet segment the field being set belongs to
173062306a36Sopenharmony_ci * @fld: field to be set
173162306a36Sopenharmony_ci * @val_loc: if not ICE_FLOW_FLD_OFF_INVAL, location of the value to match from
173262306a36Sopenharmony_ci *           entry's input buffer
173362306a36Sopenharmony_ci * @mask_loc: if not ICE_FLOW_FLD_OFF_INVAL, location of mask value from entry's
173462306a36Sopenharmony_ci *            input buffer
173562306a36Sopenharmony_ci * @last_loc: if not ICE_FLOW_FLD_OFF_INVAL, location of last/upper value from
173662306a36Sopenharmony_ci *            entry's input buffer
173762306a36Sopenharmony_ci * @range: indicate if field being matched is to be in a range
173862306a36Sopenharmony_ci *
173962306a36Sopenharmony_ci * This function specifies the locations, in the form of byte offsets from the
174062306a36Sopenharmony_ci * start of the input buffer for a flow entry, from where the value to match,
174162306a36Sopenharmony_ci * the mask value, and upper value can be extracted. These locations are then
174262306a36Sopenharmony_ci * stored in the flow profile. When adding a flow entry associated with the
174362306a36Sopenharmony_ci * flow profile, these locations will be used to quickly extract the values and
174462306a36Sopenharmony_ci * create the content of a match entry. This function should only be used for
174562306a36Sopenharmony_ci * fixed-size data structures.
174662306a36Sopenharmony_ci */
174762306a36Sopenharmony_civoid
174862306a36Sopenharmony_ciice_flow_set_fld(struct ice_flow_seg_info *seg, enum ice_flow_field fld,
174962306a36Sopenharmony_ci		 u16 val_loc, u16 mask_loc, u16 last_loc, bool range)
175062306a36Sopenharmony_ci{
175162306a36Sopenharmony_ci	enum ice_flow_fld_match_type t = range ?
175262306a36Sopenharmony_ci		ICE_FLOW_FLD_TYPE_RANGE : ICE_FLOW_FLD_TYPE_REG;
175362306a36Sopenharmony_ci
175462306a36Sopenharmony_ci	ice_flow_set_fld_ext(seg, fld, t, val_loc, mask_loc, last_loc);
175562306a36Sopenharmony_ci}
175662306a36Sopenharmony_ci
175762306a36Sopenharmony_ci/**
175862306a36Sopenharmony_ci * ice_flow_add_fld_raw - sets locations of a raw field from entry's input buf
175962306a36Sopenharmony_ci * @seg: packet segment the field being set belongs to
176062306a36Sopenharmony_ci * @off: offset of the raw field from the beginning of the segment in bytes
176162306a36Sopenharmony_ci * @len: length of the raw pattern to be matched
176262306a36Sopenharmony_ci * @val_loc: location of the value to match from entry's input buffer
176362306a36Sopenharmony_ci * @mask_loc: location of mask value from entry's input buffer
176462306a36Sopenharmony_ci *
176562306a36Sopenharmony_ci * This function specifies the offset of the raw field to be match from the
176662306a36Sopenharmony_ci * beginning of the specified packet segment, and the locations, in the form of
176762306a36Sopenharmony_ci * byte offsets from the start of the input buffer for a flow entry, from where
176862306a36Sopenharmony_ci * the value to match and the mask value to be extracted. These locations are
176962306a36Sopenharmony_ci * then stored in the flow profile. When adding flow entries to the associated
177062306a36Sopenharmony_ci * flow profile, these locations can be used to quickly extract the values to
177162306a36Sopenharmony_ci * create the content of a match entry. This function should only be used for
177262306a36Sopenharmony_ci * fixed-size data structures.
177362306a36Sopenharmony_ci */
177462306a36Sopenharmony_civoid
177562306a36Sopenharmony_ciice_flow_add_fld_raw(struct ice_flow_seg_info *seg, u16 off, u8 len,
177662306a36Sopenharmony_ci		     u16 val_loc, u16 mask_loc)
177762306a36Sopenharmony_ci{
177862306a36Sopenharmony_ci	if (seg->raws_cnt < ICE_FLOW_SEG_RAW_FLD_MAX) {
177962306a36Sopenharmony_ci		seg->raws[seg->raws_cnt].off = off;
178062306a36Sopenharmony_ci		seg->raws[seg->raws_cnt].info.type = ICE_FLOW_FLD_TYPE_SIZE;
178162306a36Sopenharmony_ci		seg->raws[seg->raws_cnt].info.src.val = val_loc;
178262306a36Sopenharmony_ci		seg->raws[seg->raws_cnt].info.src.mask = mask_loc;
178362306a36Sopenharmony_ci		/* The "last" field is used to store the length of the field */
178462306a36Sopenharmony_ci		seg->raws[seg->raws_cnt].info.src.last = len;
178562306a36Sopenharmony_ci	}
178662306a36Sopenharmony_ci
178762306a36Sopenharmony_ci	/* Overflows of "raws" will be handled as an error condition later in
178862306a36Sopenharmony_ci	 * the flow when this information is processed.
178962306a36Sopenharmony_ci	 */
179062306a36Sopenharmony_ci	seg->raws_cnt++;
179162306a36Sopenharmony_ci}
179262306a36Sopenharmony_ci
179362306a36Sopenharmony_ci/**
179462306a36Sopenharmony_ci * ice_flow_rem_vsi_prof - remove VSI from flow profile
179562306a36Sopenharmony_ci * @hw: pointer to the hardware structure
179662306a36Sopenharmony_ci * @vsi_handle: software VSI handle
179762306a36Sopenharmony_ci * @prof_id: unique ID to identify this flow profile
179862306a36Sopenharmony_ci *
179962306a36Sopenharmony_ci * This function removes the flow entries associated to the input
180062306a36Sopenharmony_ci * VSI handle and disassociate the VSI from the flow profile.
180162306a36Sopenharmony_ci */
180262306a36Sopenharmony_ciint ice_flow_rem_vsi_prof(struct ice_hw *hw, u16 vsi_handle, u64 prof_id)
180362306a36Sopenharmony_ci{
180462306a36Sopenharmony_ci	struct ice_flow_prof *prof;
180562306a36Sopenharmony_ci	int status = 0;
180662306a36Sopenharmony_ci
180762306a36Sopenharmony_ci	if (!ice_is_vsi_valid(hw, vsi_handle))
180862306a36Sopenharmony_ci		return -EINVAL;
180962306a36Sopenharmony_ci
181062306a36Sopenharmony_ci	/* find flow profile pointer with input package block and profile ID */
181162306a36Sopenharmony_ci	prof = ice_flow_find_prof_id(hw, ICE_BLK_FD, prof_id);
181262306a36Sopenharmony_ci	if (!prof) {
181362306a36Sopenharmony_ci		ice_debug(hw, ICE_DBG_PKG, "Cannot find flow profile id=%llu\n",
181462306a36Sopenharmony_ci			  prof_id);
181562306a36Sopenharmony_ci		return -ENOENT;
181662306a36Sopenharmony_ci	}
181762306a36Sopenharmony_ci
181862306a36Sopenharmony_ci	/* Remove all remaining flow entries before removing the flow profile */
181962306a36Sopenharmony_ci	if (!list_empty(&prof->entries)) {
182062306a36Sopenharmony_ci		struct ice_flow_entry *e, *t;
182162306a36Sopenharmony_ci
182262306a36Sopenharmony_ci		mutex_lock(&prof->entries_lock);
182362306a36Sopenharmony_ci		list_for_each_entry_safe(e, t, &prof->entries, l_entry) {
182462306a36Sopenharmony_ci			if (e->vsi_handle != vsi_handle)
182562306a36Sopenharmony_ci				continue;
182662306a36Sopenharmony_ci
182762306a36Sopenharmony_ci			status = ice_flow_rem_entry_sync(hw, ICE_BLK_FD, e);
182862306a36Sopenharmony_ci			if (status)
182962306a36Sopenharmony_ci				break;
183062306a36Sopenharmony_ci		}
183162306a36Sopenharmony_ci		mutex_unlock(&prof->entries_lock);
183262306a36Sopenharmony_ci	}
183362306a36Sopenharmony_ci	if (status)
183462306a36Sopenharmony_ci		return status;
183562306a36Sopenharmony_ci
183662306a36Sopenharmony_ci	/* disassociate the flow profile from sw VSI handle */
183762306a36Sopenharmony_ci	status = ice_flow_disassoc_prof(hw, ICE_BLK_FD, prof, vsi_handle);
183862306a36Sopenharmony_ci	if (status)
183962306a36Sopenharmony_ci		ice_debug(hw, ICE_DBG_PKG, "ice_flow_disassoc_prof() failed with status=%d\n",
184062306a36Sopenharmony_ci			  status);
184162306a36Sopenharmony_ci	return status;
184262306a36Sopenharmony_ci}
184362306a36Sopenharmony_ci
184462306a36Sopenharmony_ci#define ICE_FLOW_RSS_SEG_HDR_L2_MASKS \
184562306a36Sopenharmony_ci	(ICE_FLOW_SEG_HDR_ETH | ICE_FLOW_SEG_HDR_VLAN)
184662306a36Sopenharmony_ci
184762306a36Sopenharmony_ci#define ICE_FLOW_RSS_SEG_HDR_L3_MASKS \
184862306a36Sopenharmony_ci	(ICE_FLOW_SEG_HDR_IPV4 | ICE_FLOW_SEG_HDR_IPV6)
184962306a36Sopenharmony_ci
185062306a36Sopenharmony_ci#define ICE_FLOW_RSS_SEG_HDR_L4_MASKS \
185162306a36Sopenharmony_ci	(ICE_FLOW_SEG_HDR_TCP | ICE_FLOW_SEG_HDR_UDP | ICE_FLOW_SEG_HDR_SCTP)
185262306a36Sopenharmony_ci
185362306a36Sopenharmony_ci#define ICE_FLOW_RSS_SEG_HDR_VAL_MASKS \
185462306a36Sopenharmony_ci	(ICE_FLOW_RSS_SEG_HDR_L2_MASKS | \
185562306a36Sopenharmony_ci	 ICE_FLOW_RSS_SEG_HDR_L3_MASKS | \
185662306a36Sopenharmony_ci	 ICE_FLOW_RSS_SEG_HDR_L4_MASKS)
185762306a36Sopenharmony_ci
185862306a36Sopenharmony_ci/**
185962306a36Sopenharmony_ci * ice_flow_set_rss_seg_info - setup packet segments for RSS
186062306a36Sopenharmony_ci * @segs: pointer to the flow field segment(s)
186162306a36Sopenharmony_ci * @hash_fields: fields to be hashed on for the segment(s)
186262306a36Sopenharmony_ci * @flow_hdr: protocol header fields within a packet segment
186362306a36Sopenharmony_ci *
186462306a36Sopenharmony_ci * Helper function to extract fields from hash bitmap and use flow
186562306a36Sopenharmony_ci * header value to set flow field segment for further use in flow
186662306a36Sopenharmony_ci * profile entry or removal.
186762306a36Sopenharmony_ci */
186862306a36Sopenharmony_cistatic int
186962306a36Sopenharmony_ciice_flow_set_rss_seg_info(struct ice_flow_seg_info *segs, u64 hash_fields,
187062306a36Sopenharmony_ci			  u32 flow_hdr)
187162306a36Sopenharmony_ci{
187262306a36Sopenharmony_ci	u64 val;
187362306a36Sopenharmony_ci	u8 i;
187462306a36Sopenharmony_ci
187562306a36Sopenharmony_ci	for_each_set_bit(i, (unsigned long *)&hash_fields,
187662306a36Sopenharmony_ci			 ICE_FLOW_FIELD_IDX_MAX)
187762306a36Sopenharmony_ci		ice_flow_set_fld(segs, (enum ice_flow_field)i,
187862306a36Sopenharmony_ci				 ICE_FLOW_FLD_OFF_INVAL, ICE_FLOW_FLD_OFF_INVAL,
187962306a36Sopenharmony_ci				 ICE_FLOW_FLD_OFF_INVAL, false);
188062306a36Sopenharmony_ci
188162306a36Sopenharmony_ci	ICE_FLOW_SET_HDRS(segs, flow_hdr);
188262306a36Sopenharmony_ci
188362306a36Sopenharmony_ci	if (segs->hdrs & ~ICE_FLOW_RSS_SEG_HDR_VAL_MASKS &
188462306a36Sopenharmony_ci	    ~ICE_FLOW_RSS_HDRS_INNER_MASK & ~ICE_FLOW_SEG_HDR_IPV_OTHER)
188562306a36Sopenharmony_ci		return -EINVAL;
188662306a36Sopenharmony_ci
188762306a36Sopenharmony_ci	val = (u64)(segs->hdrs & ICE_FLOW_RSS_SEG_HDR_L3_MASKS);
188862306a36Sopenharmony_ci	if (val && !is_power_of_2(val))
188962306a36Sopenharmony_ci		return -EIO;
189062306a36Sopenharmony_ci
189162306a36Sopenharmony_ci	val = (u64)(segs->hdrs & ICE_FLOW_RSS_SEG_HDR_L4_MASKS);
189262306a36Sopenharmony_ci	if (val && !is_power_of_2(val))
189362306a36Sopenharmony_ci		return -EIO;
189462306a36Sopenharmony_ci
189562306a36Sopenharmony_ci	return 0;
189662306a36Sopenharmony_ci}
189762306a36Sopenharmony_ci
189862306a36Sopenharmony_ci/**
189962306a36Sopenharmony_ci * ice_rem_vsi_rss_list - remove VSI from RSS list
190062306a36Sopenharmony_ci * @hw: pointer to the hardware structure
190162306a36Sopenharmony_ci * @vsi_handle: software VSI handle
190262306a36Sopenharmony_ci *
190362306a36Sopenharmony_ci * Remove the VSI from all RSS configurations in the list.
190462306a36Sopenharmony_ci */
190562306a36Sopenharmony_civoid ice_rem_vsi_rss_list(struct ice_hw *hw, u16 vsi_handle)
190662306a36Sopenharmony_ci{
190762306a36Sopenharmony_ci	struct ice_rss_cfg *r, *tmp;
190862306a36Sopenharmony_ci
190962306a36Sopenharmony_ci	if (list_empty(&hw->rss_list_head))
191062306a36Sopenharmony_ci		return;
191162306a36Sopenharmony_ci
191262306a36Sopenharmony_ci	mutex_lock(&hw->rss_locks);
191362306a36Sopenharmony_ci	list_for_each_entry_safe(r, tmp, &hw->rss_list_head, l_entry)
191462306a36Sopenharmony_ci		if (test_and_clear_bit(vsi_handle, r->vsis))
191562306a36Sopenharmony_ci			if (bitmap_empty(r->vsis, ICE_MAX_VSI)) {
191662306a36Sopenharmony_ci				list_del(&r->l_entry);
191762306a36Sopenharmony_ci				devm_kfree(ice_hw_to_dev(hw), r);
191862306a36Sopenharmony_ci			}
191962306a36Sopenharmony_ci	mutex_unlock(&hw->rss_locks);
192062306a36Sopenharmony_ci}
192162306a36Sopenharmony_ci
192262306a36Sopenharmony_ci/**
192362306a36Sopenharmony_ci * ice_rem_vsi_rss_cfg - remove RSS configurations associated with VSI
192462306a36Sopenharmony_ci * @hw: pointer to the hardware structure
192562306a36Sopenharmony_ci * @vsi_handle: software VSI handle
192662306a36Sopenharmony_ci *
192762306a36Sopenharmony_ci * This function will iterate through all flow profiles and disassociate
192862306a36Sopenharmony_ci * the VSI from that profile. If the flow profile has no VSIs it will
192962306a36Sopenharmony_ci * be removed.
193062306a36Sopenharmony_ci */
193162306a36Sopenharmony_ciint ice_rem_vsi_rss_cfg(struct ice_hw *hw, u16 vsi_handle)
193262306a36Sopenharmony_ci{
193362306a36Sopenharmony_ci	const enum ice_block blk = ICE_BLK_RSS;
193462306a36Sopenharmony_ci	struct ice_flow_prof *p, *t;
193562306a36Sopenharmony_ci	int status = 0;
193662306a36Sopenharmony_ci
193762306a36Sopenharmony_ci	if (!ice_is_vsi_valid(hw, vsi_handle))
193862306a36Sopenharmony_ci		return -EINVAL;
193962306a36Sopenharmony_ci
194062306a36Sopenharmony_ci	if (list_empty(&hw->fl_profs[blk]))
194162306a36Sopenharmony_ci		return 0;
194262306a36Sopenharmony_ci
194362306a36Sopenharmony_ci	mutex_lock(&hw->rss_locks);
194462306a36Sopenharmony_ci	list_for_each_entry_safe(p, t, &hw->fl_profs[blk], l_entry)
194562306a36Sopenharmony_ci		if (test_bit(vsi_handle, p->vsis)) {
194662306a36Sopenharmony_ci			status = ice_flow_disassoc_prof(hw, blk, p, vsi_handle);
194762306a36Sopenharmony_ci			if (status)
194862306a36Sopenharmony_ci				break;
194962306a36Sopenharmony_ci
195062306a36Sopenharmony_ci			if (bitmap_empty(p->vsis, ICE_MAX_VSI)) {
195162306a36Sopenharmony_ci				status = ice_flow_rem_prof(hw, blk, p->id);
195262306a36Sopenharmony_ci				if (status)
195362306a36Sopenharmony_ci					break;
195462306a36Sopenharmony_ci			}
195562306a36Sopenharmony_ci		}
195662306a36Sopenharmony_ci	mutex_unlock(&hw->rss_locks);
195762306a36Sopenharmony_ci
195862306a36Sopenharmony_ci	return status;
195962306a36Sopenharmony_ci}
196062306a36Sopenharmony_ci
196162306a36Sopenharmony_ci/**
196262306a36Sopenharmony_ci * ice_rem_rss_list - remove RSS configuration from list
196362306a36Sopenharmony_ci * @hw: pointer to the hardware structure
196462306a36Sopenharmony_ci * @vsi_handle: software VSI handle
196562306a36Sopenharmony_ci * @prof: pointer to flow profile
196662306a36Sopenharmony_ci *
196762306a36Sopenharmony_ci * Assumption: lock has already been acquired for RSS list
196862306a36Sopenharmony_ci */
196962306a36Sopenharmony_cistatic void
197062306a36Sopenharmony_ciice_rem_rss_list(struct ice_hw *hw, u16 vsi_handle, struct ice_flow_prof *prof)
197162306a36Sopenharmony_ci{
197262306a36Sopenharmony_ci	struct ice_rss_cfg *r, *tmp;
197362306a36Sopenharmony_ci
197462306a36Sopenharmony_ci	/* Search for RSS hash fields associated to the VSI that match the
197562306a36Sopenharmony_ci	 * hash configurations associated to the flow profile. If found
197662306a36Sopenharmony_ci	 * remove from the RSS entry list of the VSI context and delete entry.
197762306a36Sopenharmony_ci	 */
197862306a36Sopenharmony_ci	list_for_each_entry_safe(r, tmp, &hw->rss_list_head, l_entry)
197962306a36Sopenharmony_ci		if (r->hashed_flds == prof->segs[prof->segs_cnt - 1].match &&
198062306a36Sopenharmony_ci		    r->packet_hdr == prof->segs[prof->segs_cnt - 1].hdrs) {
198162306a36Sopenharmony_ci			clear_bit(vsi_handle, r->vsis);
198262306a36Sopenharmony_ci			if (bitmap_empty(r->vsis, ICE_MAX_VSI)) {
198362306a36Sopenharmony_ci				list_del(&r->l_entry);
198462306a36Sopenharmony_ci				devm_kfree(ice_hw_to_dev(hw), r);
198562306a36Sopenharmony_ci			}
198662306a36Sopenharmony_ci			return;
198762306a36Sopenharmony_ci		}
198862306a36Sopenharmony_ci}
198962306a36Sopenharmony_ci
199062306a36Sopenharmony_ci/**
199162306a36Sopenharmony_ci * ice_add_rss_list - add RSS configuration to list
199262306a36Sopenharmony_ci * @hw: pointer to the hardware structure
199362306a36Sopenharmony_ci * @vsi_handle: software VSI handle
199462306a36Sopenharmony_ci * @prof: pointer to flow profile
199562306a36Sopenharmony_ci *
199662306a36Sopenharmony_ci * Assumption: lock has already been acquired for RSS list
199762306a36Sopenharmony_ci */
199862306a36Sopenharmony_cistatic int
199962306a36Sopenharmony_ciice_add_rss_list(struct ice_hw *hw, u16 vsi_handle, struct ice_flow_prof *prof)
200062306a36Sopenharmony_ci{
200162306a36Sopenharmony_ci	struct ice_rss_cfg *r, *rss_cfg;
200262306a36Sopenharmony_ci
200362306a36Sopenharmony_ci	list_for_each_entry(r, &hw->rss_list_head, l_entry)
200462306a36Sopenharmony_ci		if (r->hashed_flds == prof->segs[prof->segs_cnt - 1].match &&
200562306a36Sopenharmony_ci		    r->packet_hdr == prof->segs[prof->segs_cnt - 1].hdrs) {
200662306a36Sopenharmony_ci			set_bit(vsi_handle, r->vsis);
200762306a36Sopenharmony_ci			return 0;
200862306a36Sopenharmony_ci		}
200962306a36Sopenharmony_ci
201062306a36Sopenharmony_ci	rss_cfg = devm_kzalloc(ice_hw_to_dev(hw), sizeof(*rss_cfg),
201162306a36Sopenharmony_ci			       GFP_KERNEL);
201262306a36Sopenharmony_ci	if (!rss_cfg)
201362306a36Sopenharmony_ci		return -ENOMEM;
201462306a36Sopenharmony_ci
201562306a36Sopenharmony_ci	rss_cfg->hashed_flds = prof->segs[prof->segs_cnt - 1].match;
201662306a36Sopenharmony_ci	rss_cfg->packet_hdr = prof->segs[prof->segs_cnt - 1].hdrs;
201762306a36Sopenharmony_ci	set_bit(vsi_handle, rss_cfg->vsis);
201862306a36Sopenharmony_ci
201962306a36Sopenharmony_ci	list_add_tail(&rss_cfg->l_entry, &hw->rss_list_head);
202062306a36Sopenharmony_ci
202162306a36Sopenharmony_ci	return 0;
202262306a36Sopenharmony_ci}
202362306a36Sopenharmony_ci
202462306a36Sopenharmony_ci#define ICE_FLOW_PROF_HASH_S	0
202562306a36Sopenharmony_ci#define ICE_FLOW_PROF_HASH_M	(0xFFFFFFFFULL << ICE_FLOW_PROF_HASH_S)
202662306a36Sopenharmony_ci#define ICE_FLOW_PROF_HDR_S	32
202762306a36Sopenharmony_ci#define ICE_FLOW_PROF_HDR_M	(0x3FFFFFFFULL << ICE_FLOW_PROF_HDR_S)
202862306a36Sopenharmony_ci#define ICE_FLOW_PROF_ENCAP_S	63
202962306a36Sopenharmony_ci#define ICE_FLOW_PROF_ENCAP_M	(BIT_ULL(ICE_FLOW_PROF_ENCAP_S))
203062306a36Sopenharmony_ci
203162306a36Sopenharmony_ci#define ICE_RSS_OUTER_HEADERS	1
203262306a36Sopenharmony_ci#define ICE_RSS_INNER_HEADERS	2
203362306a36Sopenharmony_ci
203462306a36Sopenharmony_ci/* Flow profile ID format:
203562306a36Sopenharmony_ci * [0:31] - Packet match fields
203662306a36Sopenharmony_ci * [32:62] - Protocol header
203762306a36Sopenharmony_ci * [63] - Encapsulation flag, 0 if non-tunneled, 1 if tunneled
203862306a36Sopenharmony_ci */
203962306a36Sopenharmony_ci#define ICE_FLOW_GEN_PROFID(hash, hdr, segs_cnt) \
204062306a36Sopenharmony_ci	((u64)(((u64)(hash) & ICE_FLOW_PROF_HASH_M) | \
204162306a36Sopenharmony_ci	       (((u64)(hdr) << ICE_FLOW_PROF_HDR_S) & ICE_FLOW_PROF_HDR_M) | \
204262306a36Sopenharmony_ci	       ((u8)((segs_cnt) - 1) ? ICE_FLOW_PROF_ENCAP_M : 0)))
204362306a36Sopenharmony_ci
204462306a36Sopenharmony_ci/**
204562306a36Sopenharmony_ci * ice_add_rss_cfg_sync - add an RSS configuration
204662306a36Sopenharmony_ci * @hw: pointer to the hardware structure
204762306a36Sopenharmony_ci * @vsi_handle: software VSI handle
204862306a36Sopenharmony_ci * @hashed_flds: hash bit fields (ICE_FLOW_HASH_*) to configure
204962306a36Sopenharmony_ci * @addl_hdrs: protocol header fields
205062306a36Sopenharmony_ci * @segs_cnt: packet segment count
205162306a36Sopenharmony_ci *
205262306a36Sopenharmony_ci * Assumption: lock has already been acquired for RSS list
205362306a36Sopenharmony_ci */
205462306a36Sopenharmony_cistatic int
205562306a36Sopenharmony_ciice_add_rss_cfg_sync(struct ice_hw *hw, u16 vsi_handle, u64 hashed_flds,
205662306a36Sopenharmony_ci		     u32 addl_hdrs, u8 segs_cnt)
205762306a36Sopenharmony_ci{
205862306a36Sopenharmony_ci	const enum ice_block blk = ICE_BLK_RSS;
205962306a36Sopenharmony_ci	struct ice_flow_prof *prof = NULL;
206062306a36Sopenharmony_ci	struct ice_flow_seg_info *segs;
206162306a36Sopenharmony_ci	int status;
206262306a36Sopenharmony_ci
206362306a36Sopenharmony_ci	if (!segs_cnt || segs_cnt > ICE_FLOW_SEG_MAX)
206462306a36Sopenharmony_ci		return -EINVAL;
206562306a36Sopenharmony_ci
206662306a36Sopenharmony_ci	segs = kcalloc(segs_cnt, sizeof(*segs), GFP_KERNEL);
206762306a36Sopenharmony_ci	if (!segs)
206862306a36Sopenharmony_ci		return -ENOMEM;
206962306a36Sopenharmony_ci
207062306a36Sopenharmony_ci	/* Construct the packet segment info from the hashed fields */
207162306a36Sopenharmony_ci	status = ice_flow_set_rss_seg_info(&segs[segs_cnt - 1], hashed_flds,
207262306a36Sopenharmony_ci					   addl_hdrs);
207362306a36Sopenharmony_ci	if (status)
207462306a36Sopenharmony_ci		goto exit;
207562306a36Sopenharmony_ci
207662306a36Sopenharmony_ci	/* Search for a flow profile that has matching headers, hash fields
207762306a36Sopenharmony_ci	 * and has the input VSI associated to it. If found, no further
207862306a36Sopenharmony_ci	 * operations required and exit.
207962306a36Sopenharmony_ci	 */
208062306a36Sopenharmony_ci	prof = ice_flow_find_prof_conds(hw, blk, ICE_FLOW_RX, segs, segs_cnt,
208162306a36Sopenharmony_ci					vsi_handle,
208262306a36Sopenharmony_ci					ICE_FLOW_FIND_PROF_CHK_FLDS |
208362306a36Sopenharmony_ci					ICE_FLOW_FIND_PROF_CHK_VSI);
208462306a36Sopenharmony_ci	if (prof)
208562306a36Sopenharmony_ci		goto exit;
208662306a36Sopenharmony_ci
208762306a36Sopenharmony_ci	/* Check if a flow profile exists with the same protocol headers and
208862306a36Sopenharmony_ci	 * associated with the input VSI. If so disassociate the VSI from
208962306a36Sopenharmony_ci	 * this profile. The VSI will be added to a new profile created with
209062306a36Sopenharmony_ci	 * the protocol header and new hash field configuration.
209162306a36Sopenharmony_ci	 */
209262306a36Sopenharmony_ci	prof = ice_flow_find_prof_conds(hw, blk, ICE_FLOW_RX, segs, segs_cnt,
209362306a36Sopenharmony_ci					vsi_handle, ICE_FLOW_FIND_PROF_CHK_VSI);
209462306a36Sopenharmony_ci	if (prof) {
209562306a36Sopenharmony_ci		status = ice_flow_disassoc_prof(hw, blk, prof, vsi_handle);
209662306a36Sopenharmony_ci		if (!status)
209762306a36Sopenharmony_ci			ice_rem_rss_list(hw, vsi_handle, prof);
209862306a36Sopenharmony_ci		else
209962306a36Sopenharmony_ci			goto exit;
210062306a36Sopenharmony_ci
210162306a36Sopenharmony_ci		/* Remove profile if it has no VSIs associated */
210262306a36Sopenharmony_ci		if (bitmap_empty(prof->vsis, ICE_MAX_VSI)) {
210362306a36Sopenharmony_ci			status = ice_flow_rem_prof(hw, blk, prof->id);
210462306a36Sopenharmony_ci			if (status)
210562306a36Sopenharmony_ci				goto exit;
210662306a36Sopenharmony_ci		}
210762306a36Sopenharmony_ci	}
210862306a36Sopenharmony_ci
210962306a36Sopenharmony_ci	/* Search for a profile that has same match fields only. If this
211062306a36Sopenharmony_ci	 * exists then associate the VSI to this profile.
211162306a36Sopenharmony_ci	 */
211262306a36Sopenharmony_ci	prof = ice_flow_find_prof_conds(hw, blk, ICE_FLOW_RX, segs, segs_cnt,
211362306a36Sopenharmony_ci					vsi_handle,
211462306a36Sopenharmony_ci					ICE_FLOW_FIND_PROF_CHK_FLDS);
211562306a36Sopenharmony_ci	if (prof) {
211662306a36Sopenharmony_ci		status = ice_flow_assoc_prof(hw, blk, prof, vsi_handle);
211762306a36Sopenharmony_ci		if (!status)
211862306a36Sopenharmony_ci			status = ice_add_rss_list(hw, vsi_handle, prof);
211962306a36Sopenharmony_ci		goto exit;
212062306a36Sopenharmony_ci	}
212162306a36Sopenharmony_ci
212262306a36Sopenharmony_ci	/* Create a new flow profile with generated profile and packet
212362306a36Sopenharmony_ci	 * segment information.
212462306a36Sopenharmony_ci	 */
212562306a36Sopenharmony_ci	status = ice_flow_add_prof(hw, blk, ICE_FLOW_RX,
212662306a36Sopenharmony_ci				   ICE_FLOW_GEN_PROFID(hashed_flds,
212762306a36Sopenharmony_ci						       segs[segs_cnt - 1].hdrs,
212862306a36Sopenharmony_ci						       segs_cnt),
212962306a36Sopenharmony_ci				   segs, segs_cnt, &prof);
213062306a36Sopenharmony_ci	if (status)
213162306a36Sopenharmony_ci		goto exit;
213262306a36Sopenharmony_ci
213362306a36Sopenharmony_ci	status = ice_flow_assoc_prof(hw, blk, prof, vsi_handle);
213462306a36Sopenharmony_ci	/* If association to a new flow profile failed then this profile can
213562306a36Sopenharmony_ci	 * be removed.
213662306a36Sopenharmony_ci	 */
213762306a36Sopenharmony_ci	if (status) {
213862306a36Sopenharmony_ci		ice_flow_rem_prof(hw, blk, prof->id);
213962306a36Sopenharmony_ci		goto exit;
214062306a36Sopenharmony_ci	}
214162306a36Sopenharmony_ci
214262306a36Sopenharmony_ci	status = ice_add_rss_list(hw, vsi_handle, prof);
214362306a36Sopenharmony_ci
214462306a36Sopenharmony_ciexit:
214562306a36Sopenharmony_ci	kfree(segs);
214662306a36Sopenharmony_ci	return status;
214762306a36Sopenharmony_ci}
214862306a36Sopenharmony_ci
214962306a36Sopenharmony_ci/**
215062306a36Sopenharmony_ci * ice_add_rss_cfg - add an RSS configuration with specified hashed fields
215162306a36Sopenharmony_ci * @hw: pointer to the hardware structure
215262306a36Sopenharmony_ci * @vsi_handle: software VSI handle
215362306a36Sopenharmony_ci * @hashed_flds: hash bit fields (ICE_FLOW_HASH_*) to configure
215462306a36Sopenharmony_ci * @addl_hdrs: protocol header fields
215562306a36Sopenharmony_ci *
215662306a36Sopenharmony_ci * This function will generate a flow profile based on fields associated with
215762306a36Sopenharmony_ci * the input fields to hash on, the flow type and use the VSI number to add
215862306a36Sopenharmony_ci * a flow entry to the profile.
215962306a36Sopenharmony_ci */
216062306a36Sopenharmony_ciint
216162306a36Sopenharmony_ciice_add_rss_cfg(struct ice_hw *hw, u16 vsi_handle, u64 hashed_flds,
216262306a36Sopenharmony_ci		u32 addl_hdrs)
216362306a36Sopenharmony_ci{
216462306a36Sopenharmony_ci	int status;
216562306a36Sopenharmony_ci
216662306a36Sopenharmony_ci	if (hashed_flds == ICE_HASH_INVALID ||
216762306a36Sopenharmony_ci	    !ice_is_vsi_valid(hw, vsi_handle))
216862306a36Sopenharmony_ci		return -EINVAL;
216962306a36Sopenharmony_ci
217062306a36Sopenharmony_ci	mutex_lock(&hw->rss_locks);
217162306a36Sopenharmony_ci	status = ice_add_rss_cfg_sync(hw, vsi_handle, hashed_flds, addl_hdrs,
217262306a36Sopenharmony_ci				      ICE_RSS_OUTER_HEADERS);
217362306a36Sopenharmony_ci	if (!status)
217462306a36Sopenharmony_ci		status = ice_add_rss_cfg_sync(hw, vsi_handle, hashed_flds,
217562306a36Sopenharmony_ci					      addl_hdrs, ICE_RSS_INNER_HEADERS);
217662306a36Sopenharmony_ci	mutex_unlock(&hw->rss_locks);
217762306a36Sopenharmony_ci
217862306a36Sopenharmony_ci	return status;
217962306a36Sopenharmony_ci}
218062306a36Sopenharmony_ci
218162306a36Sopenharmony_ci/**
218262306a36Sopenharmony_ci * ice_rem_rss_cfg_sync - remove an existing RSS configuration
218362306a36Sopenharmony_ci * @hw: pointer to the hardware structure
218462306a36Sopenharmony_ci * @vsi_handle: software VSI handle
218562306a36Sopenharmony_ci * @hashed_flds: Packet hash types (ICE_FLOW_HASH_*) to remove
218662306a36Sopenharmony_ci * @addl_hdrs: Protocol header fields within a packet segment
218762306a36Sopenharmony_ci * @segs_cnt: packet segment count
218862306a36Sopenharmony_ci *
218962306a36Sopenharmony_ci * Assumption: lock has already been acquired for RSS list
219062306a36Sopenharmony_ci */
219162306a36Sopenharmony_cistatic int
219262306a36Sopenharmony_ciice_rem_rss_cfg_sync(struct ice_hw *hw, u16 vsi_handle, u64 hashed_flds,
219362306a36Sopenharmony_ci		     u32 addl_hdrs, u8 segs_cnt)
219462306a36Sopenharmony_ci{
219562306a36Sopenharmony_ci	const enum ice_block blk = ICE_BLK_RSS;
219662306a36Sopenharmony_ci	struct ice_flow_seg_info *segs;
219762306a36Sopenharmony_ci	struct ice_flow_prof *prof;
219862306a36Sopenharmony_ci	int status;
219962306a36Sopenharmony_ci
220062306a36Sopenharmony_ci	segs = kcalloc(segs_cnt, sizeof(*segs), GFP_KERNEL);
220162306a36Sopenharmony_ci	if (!segs)
220262306a36Sopenharmony_ci		return -ENOMEM;
220362306a36Sopenharmony_ci
220462306a36Sopenharmony_ci	/* Construct the packet segment info from the hashed fields */
220562306a36Sopenharmony_ci	status = ice_flow_set_rss_seg_info(&segs[segs_cnt - 1], hashed_flds,
220662306a36Sopenharmony_ci					   addl_hdrs);
220762306a36Sopenharmony_ci	if (status)
220862306a36Sopenharmony_ci		goto out;
220962306a36Sopenharmony_ci
221062306a36Sopenharmony_ci	prof = ice_flow_find_prof_conds(hw, blk, ICE_FLOW_RX, segs, segs_cnt,
221162306a36Sopenharmony_ci					vsi_handle,
221262306a36Sopenharmony_ci					ICE_FLOW_FIND_PROF_CHK_FLDS);
221362306a36Sopenharmony_ci	if (!prof) {
221462306a36Sopenharmony_ci		status = -ENOENT;
221562306a36Sopenharmony_ci		goto out;
221662306a36Sopenharmony_ci	}
221762306a36Sopenharmony_ci
221862306a36Sopenharmony_ci	status = ice_flow_disassoc_prof(hw, blk, prof, vsi_handle);
221962306a36Sopenharmony_ci	if (status)
222062306a36Sopenharmony_ci		goto out;
222162306a36Sopenharmony_ci
222262306a36Sopenharmony_ci	/* Remove RSS configuration from VSI context before deleting
222362306a36Sopenharmony_ci	 * the flow profile.
222462306a36Sopenharmony_ci	 */
222562306a36Sopenharmony_ci	ice_rem_rss_list(hw, vsi_handle, prof);
222662306a36Sopenharmony_ci
222762306a36Sopenharmony_ci	if (bitmap_empty(prof->vsis, ICE_MAX_VSI))
222862306a36Sopenharmony_ci		status = ice_flow_rem_prof(hw, blk, prof->id);
222962306a36Sopenharmony_ci
223062306a36Sopenharmony_ciout:
223162306a36Sopenharmony_ci	kfree(segs);
223262306a36Sopenharmony_ci	return status;
223362306a36Sopenharmony_ci}
223462306a36Sopenharmony_ci
223562306a36Sopenharmony_ci/**
223662306a36Sopenharmony_ci * ice_rem_rss_cfg - remove an existing RSS config with matching hashed fields
223762306a36Sopenharmony_ci * @hw: pointer to the hardware structure
223862306a36Sopenharmony_ci * @vsi_handle: software VSI handle
223962306a36Sopenharmony_ci * @hashed_flds: Packet hash types (ICE_FLOW_HASH_*) to remove
224062306a36Sopenharmony_ci * @addl_hdrs: Protocol header fields within a packet segment
224162306a36Sopenharmony_ci *
224262306a36Sopenharmony_ci * This function will lookup the flow profile based on the input
224362306a36Sopenharmony_ci * hash field bitmap, iterate through the profile entry list of
224462306a36Sopenharmony_ci * that profile and find entry associated with input VSI to be
224562306a36Sopenharmony_ci * removed. Calls are made to underlying flow s which will APIs
224662306a36Sopenharmony_ci * turn build or update buffers for RSS XLT1 section.
224762306a36Sopenharmony_ci */
224862306a36Sopenharmony_ciint __maybe_unused
224962306a36Sopenharmony_ciice_rem_rss_cfg(struct ice_hw *hw, u16 vsi_handle, u64 hashed_flds,
225062306a36Sopenharmony_ci		u32 addl_hdrs)
225162306a36Sopenharmony_ci{
225262306a36Sopenharmony_ci	int status;
225362306a36Sopenharmony_ci
225462306a36Sopenharmony_ci	if (hashed_flds == ICE_HASH_INVALID ||
225562306a36Sopenharmony_ci	    !ice_is_vsi_valid(hw, vsi_handle))
225662306a36Sopenharmony_ci		return -EINVAL;
225762306a36Sopenharmony_ci
225862306a36Sopenharmony_ci	mutex_lock(&hw->rss_locks);
225962306a36Sopenharmony_ci	status = ice_rem_rss_cfg_sync(hw, vsi_handle, hashed_flds, addl_hdrs,
226062306a36Sopenharmony_ci				      ICE_RSS_OUTER_HEADERS);
226162306a36Sopenharmony_ci	if (!status)
226262306a36Sopenharmony_ci		status = ice_rem_rss_cfg_sync(hw, vsi_handle, hashed_flds,
226362306a36Sopenharmony_ci					      addl_hdrs, ICE_RSS_INNER_HEADERS);
226462306a36Sopenharmony_ci	mutex_unlock(&hw->rss_locks);
226562306a36Sopenharmony_ci
226662306a36Sopenharmony_ci	return status;
226762306a36Sopenharmony_ci}
226862306a36Sopenharmony_ci
226962306a36Sopenharmony_ci/* Mapping of AVF hash bit fields to an L3-L4 hash combination.
227062306a36Sopenharmony_ci * As the ice_flow_avf_hdr_field represent individual bit shifts in a hash,
227162306a36Sopenharmony_ci * convert its values to their appropriate flow L3, L4 values.
227262306a36Sopenharmony_ci */
227362306a36Sopenharmony_ci#define ICE_FLOW_AVF_RSS_IPV4_MASKS \
227462306a36Sopenharmony_ci	(BIT_ULL(ICE_AVF_FLOW_FIELD_IPV4_OTHER) | \
227562306a36Sopenharmony_ci	 BIT_ULL(ICE_AVF_FLOW_FIELD_FRAG_IPV4))
227662306a36Sopenharmony_ci#define ICE_FLOW_AVF_RSS_TCP_IPV4_MASKS \
227762306a36Sopenharmony_ci	(BIT_ULL(ICE_AVF_FLOW_FIELD_IPV4_TCP_SYN_NO_ACK) | \
227862306a36Sopenharmony_ci	 BIT_ULL(ICE_AVF_FLOW_FIELD_IPV4_TCP))
227962306a36Sopenharmony_ci#define ICE_FLOW_AVF_RSS_UDP_IPV4_MASKS \
228062306a36Sopenharmony_ci	(BIT_ULL(ICE_AVF_FLOW_FIELD_UNICAST_IPV4_UDP) | \
228162306a36Sopenharmony_ci	 BIT_ULL(ICE_AVF_FLOW_FIELD_MULTICAST_IPV4_UDP) | \
228262306a36Sopenharmony_ci	 BIT_ULL(ICE_AVF_FLOW_FIELD_IPV4_UDP))
228362306a36Sopenharmony_ci#define ICE_FLOW_AVF_RSS_ALL_IPV4_MASKS \
228462306a36Sopenharmony_ci	(ICE_FLOW_AVF_RSS_TCP_IPV4_MASKS | ICE_FLOW_AVF_RSS_UDP_IPV4_MASKS | \
228562306a36Sopenharmony_ci	 ICE_FLOW_AVF_RSS_IPV4_MASKS | BIT_ULL(ICE_AVF_FLOW_FIELD_IPV4_SCTP))
228662306a36Sopenharmony_ci
228762306a36Sopenharmony_ci#define ICE_FLOW_AVF_RSS_IPV6_MASKS \
228862306a36Sopenharmony_ci	(BIT_ULL(ICE_AVF_FLOW_FIELD_IPV6_OTHER) | \
228962306a36Sopenharmony_ci	 BIT_ULL(ICE_AVF_FLOW_FIELD_FRAG_IPV6))
229062306a36Sopenharmony_ci#define ICE_FLOW_AVF_RSS_UDP_IPV6_MASKS \
229162306a36Sopenharmony_ci	(BIT_ULL(ICE_AVF_FLOW_FIELD_UNICAST_IPV6_UDP) | \
229262306a36Sopenharmony_ci	 BIT_ULL(ICE_AVF_FLOW_FIELD_MULTICAST_IPV6_UDP) | \
229362306a36Sopenharmony_ci	 BIT_ULL(ICE_AVF_FLOW_FIELD_IPV6_UDP))
229462306a36Sopenharmony_ci#define ICE_FLOW_AVF_RSS_TCP_IPV6_MASKS \
229562306a36Sopenharmony_ci	(BIT_ULL(ICE_AVF_FLOW_FIELD_IPV6_TCP_SYN_NO_ACK) | \
229662306a36Sopenharmony_ci	 BIT_ULL(ICE_AVF_FLOW_FIELD_IPV6_TCP))
229762306a36Sopenharmony_ci#define ICE_FLOW_AVF_RSS_ALL_IPV6_MASKS \
229862306a36Sopenharmony_ci	(ICE_FLOW_AVF_RSS_TCP_IPV6_MASKS | ICE_FLOW_AVF_RSS_UDP_IPV6_MASKS | \
229962306a36Sopenharmony_ci	 ICE_FLOW_AVF_RSS_IPV6_MASKS | BIT_ULL(ICE_AVF_FLOW_FIELD_IPV6_SCTP))
230062306a36Sopenharmony_ci
230162306a36Sopenharmony_ci/**
230262306a36Sopenharmony_ci * ice_add_avf_rss_cfg - add an RSS configuration for AVF driver
230362306a36Sopenharmony_ci * @hw: pointer to the hardware structure
230462306a36Sopenharmony_ci * @vsi_handle: software VSI handle
230562306a36Sopenharmony_ci * @avf_hash: hash bit fields (ICE_AVF_FLOW_FIELD_*) to configure
230662306a36Sopenharmony_ci *
230762306a36Sopenharmony_ci * This function will take the hash bitmap provided by the AVF driver via a
230862306a36Sopenharmony_ci * message, convert it to ICE-compatible values, and configure RSS flow
230962306a36Sopenharmony_ci * profiles.
231062306a36Sopenharmony_ci */
231162306a36Sopenharmony_ciint ice_add_avf_rss_cfg(struct ice_hw *hw, u16 vsi_handle, u64 avf_hash)
231262306a36Sopenharmony_ci{
231362306a36Sopenharmony_ci	int status = 0;
231462306a36Sopenharmony_ci	u64 hash_flds;
231562306a36Sopenharmony_ci
231662306a36Sopenharmony_ci	if (avf_hash == ICE_AVF_FLOW_FIELD_INVALID ||
231762306a36Sopenharmony_ci	    !ice_is_vsi_valid(hw, vsi_handle))
231862306a36Sopenharmony_ci		return -EINVAL;
231962306a36Sopenharmony_ci
232062306a36Sopenharmony_ci	/* Make sure no unsupported bits are specified */
232162306a36Sopenharmony_ci	if (avf_hash & ~(ICE_FLOW_AVF_RSS_ALL_IPV4_MASKS |
232262306a36Sopenharmony_ci			 ICE_FLOW_AVF_RSS_ALL_IPV6_MASKS))
232362306a36Sopenharmony_ci		return -EIO;
232462306a36Sopenharmony_ci
232562306a36Sopenharmony_ci	hash_flds = avf_hash;
232662306a36Sopenharmony_ci
232762306a36Sopenharmony_ci	/* Always create an L3 RSS configuration for any L4 RSS configuration */
232862306a36Sopenharmony_ci	if (hash_flds & ICE_FLOW_AVF_RSS_ALL_IPV4_MASKS)
232962306a36Sopenharmony_ci		hash_flds |= ICE_FLOW_AVF_RSS_IPV4_MASKS;
233062306a36Sopenharmony_ci
233162306a36Sopenharmony_ci	if (hash_flds & ICE_FLOW_AVF_RSS_ALL_IPV6_MASKS)
233262306a36Sopenharmony_ci		hash_flds |= ICE_FLOW_AVF_RSS_IPV6_MASKS;
233362306a36Sopenharmony_ci
233462306a36Sopenharmony_ci	/* Create the corresponding RSS configuration for each valid hash bit */
233562306a36Sopenharmony_ci	while (hash_flds) {
233662306a36Sopenharmony_ci		u64 rss_hash = ICE_HASH_INVALID;
233762306a36Sopenharmony_ci
233862306a36Sopenharmony_ci		if (hash_flds & ICE_FLOW_AVF_RSS_ALL_IPV4_MASKS) {
233962306a36Sopenharmony_ci			if (hash_flds & ICE_FLOW_AVF_RSS_IPV4_MASKS) {
234062306a36Sopenharmony_ci				rss_hash = ICE_FLOW_HASH_IPV4;
234162306a36Sopenharmony_ci				hash_flds &= ~ICE_FLOW_AVF_RSS_IPV4_MASKS;
234262306a36Sopenharmony_ci			} else if (hash_flds &
234362306a36Sopenharmony_ci				   ICE_FLOW_AVF_RSS_TCP_IPV4_MASKS) {
234462306a36Sopenharmony_ci				rss_hash = ICE_FLOW_HASH_IPV4 |
234562306a36Sopenharmony_ci					ICE_FLOW_HASH_TCP_PORT;
234662306a36Sopenharmony_ci				hash_flds &= ~ICE_FLOW_AVF_RSS_TCP_IPV4_MASKS;
234762306a36Sopenharmony_ci			} else if (hash_flds &
234862306a36Sopenharmony_ci				   ICE_FLOW_AVF_RSS_UDP_IPV4_MASKS) {
234962306a36Sopenharmony_ci				rss_hash = ICE_FLOW_HASH_IPV4 |
235062306a36Sopenharmony_ci					ICE_FLOW_HASH_UDP_PORT;
235162306a36Sopenharmony_ci				hash_flds &= ~ICE_FLOW_AVF_RSS_UDP_IPV4_MASKS;
235262306a36Sopenharmony_ci			} else if (hash_flds &
235362306a36Sopenharmony_ci				   BIT_ULL(ICE_AVF_FLOW_FIELD_IPV4_SCTP)) {
235462306a36Sopenharmony_ci				rss_hash = ICE_FLOW_HASH_IPV4 |
235562306a36Sopenharmony_ci					ICE_FLOW_HASH_SCTP_PORT;
235662306a36Sopenharmony_ci				hash_flds &=
235762306a36Sopenharmony_ci					~BIT_ULL(ICE_AVF_FLOW_FIELD_IPV4_SCTP);
235862306a36Sopenharmony_ci			}
235962306a36Sopenharmony_ci		} else if (hash_flds & ICE_FLOW_AVF_RSS_ALL_IPV6_MASKS) {
236062306a36Sopenharmony_ci			if (hash_flds & ICE_FLOW_AVF_RSS_IPV6_MASKS) {
236162306a36Sopenharmony_ci				rss_hash = ICE_FLOW_HASH_IPV6;
236262306a36Sopenharmony_ci				hash_flds &= ~ICE_FLOW_AVF_RSS_IPV6_MASKS;
236362306a36Sopenharmony_ci			} else if (hash_flds &
236462306a36Sopenharmony_ci				   ICE_FLOW_AVF_RSS_TCP_IPV6_MASKS) {
236562306a36Sopenharmony_ci				rss_hash = ICE_FLOW_HASH_IPV6 |
236662306a36Sopenharmony_ci					ICE_FLOW_HASH_TCP_PORT;
236762306a36Sopenharmony_ci				hash_flds &= ~ICE_FLOW_AVF_RSS_TCP_IPV6_MASKS;
236862306a36Sopenharmony_ci			} else if (hash_flds &
236962306a36Sopenharmony_ci				   ICE_FLOW_AVF_RSS_UDP_IPV6_MASKS) {
237062306a36Sopenharmony_ci				rss_hash = ICE_FLOW_HASH_IPV6 |
237162306a36Sopenharmony_ci					ICE_FLOW_HASH_UDP_PORT;
237262306a36Sopenharmony_ci				hash_flds &= ~ICE_FLOW_AVF_RSS_UDP_IPV6_MASKS;
237362306a36Sopenharmony_ci			} else if (hash_flds &
237462306a36Sopenharmony_ci				   BIT_ULL(ICE_AVF_FLOW_FIELD_IPV6_SCTP)) {
237562306a36Sopenharmony_ci				rss_hash = ICE_FLOW_HASH_IPV6 |
237662306a36Sopenharmony_ci					ICE_FLOW_HASH_SCTP_PORT;
237762306a36Sopenharmony_ci				hash_flds &=
237862306a36Sopenharmony_ci					~BIT_ULL(ICE_AVF_FLOW_FIELD_IPV6_SCTP);
237962306a36Sopenharmony_ci			}
238062306a36Sopenharmony_ci		}
238162306a36Sopenharmony_ci
238262306a36Sopenharmony_ci		if (rss_hash == ICE_HASH_INVALID)
238362306a36Sopenharmony_ci			return -EIO;
238462306a36Sopenharmony_ci
238562306a36Sopenharmony_ci		status = ice_add_rss_cfg(hw, vsi_handle, rss_hash,
238662306a36Sopenharmony_ci					 ICE_FLOW_SEG_HDR_NONE);
238762306a36Sopenharmony_ci		if (status)
238862306a36Sopenharmony_ci			break;
238962306a36Sopenharmony_ci	}
239062306a36Sopenharmony_ci
239162306a36Sopenharmony_ci	return status;
239262306a36Sopenharmony_ci}
239362306a36Sopenharmony_ci
239462306a36Sopenharmony_ci/**
239562306a36Sopenharmony_ci * ice_replay_rss_cfg - replay RSS configurations associated with VSI
239662306a36Sopenharmony_ci * @hw: pointer to the hardware structure
239762306a36Sopenharmony_ci * @vsi_handle: software VSI handle
239862306a36Sopenharmony_ci */
239962306a36Sopenharmony_ciint ice_replay_rss_cfg(struct ice_hw *hw, u16 vsi_handle)
240062306a36Sopenharmony_ci{
240162306a36Sopenharmony_ci	struct ice_rss_cfg *r;
240262306a36Sopenharmony_ci	int status = 0;
240362306a36Sopenharmony_ci
240462306a36Sopenharmony_ci	if (!ice_is_vsi_valid(hw, vsi_handle))
240562306a36Sopenharmony_ci		return -EINVAL;
240662306a36Sopenharmony_ci
240762306a36Sopenharmony_ci	mutex_lock(&hw->rss_locks);
240862306a36Sopenharmony_ci	list_for_each_entry(r, &hw->rss_list_head, l_entry) {
240962306a36Sopenharmony_ci		if (test_bit(vsi_handle, r->vsis)) {
241062306a36Sopenharmony_ci			status = ice_add_rss_cfg_sync(hw, vsi_handle,
241162306a36Sopenharmony_ci						      r->hashed_flds,
241262306a36Sopenharmony_ci						      r->packet_hdr,
241362306a36Sopenharmony_ci						      ICE_RSS_OUTER_HEADERS);
241462306a36Sopenharmony_ci			if (status)
241562306a36Sopenharmony_ci				break;
241662306a36Sopenharmony_ci			status = ice_add_rss_cfg_sync(hw, vsi_handle,
241762306a36Sopenharmony_ci						      r->hashed_flds,
241862306a36Sopenharmony_ci						      r->packet_hdr,
241962306a36Sopenharmony_ci						      ICE_RSS_INNER_HEADERS);
242062306a36Sopenharmony_ci			if (status)
242162306a36Sopenharmony_ci				break;
242262306a36Sopenharmony_ci		}
242362306a36Sopenharmony_ci	}
242462306a36Sopenharmony_ci	mutex_unlock(&hw->rss_locks);
242562306a36Sopenharmony_ci
242662306a36Sopenharmony_ci	return status;
242762306a36Sopenharmony_ci}
242862306a36Sopenharmony_ci
242962306a36Sopenharmony_ci/**
243062306a36Sopenharmony_ci * ice_get_rss_cfg - returns hashed fields for the given header types
243162306a36Sopenharmony_ci * @hw: pointer to the hardware structure
243262306a36Sopenharmony_ci * @vsi_handle: software VSI handle
243362306a36Sopenharmony_ci * @hdrs: protocol header type
243462306a36Sopenharmony_ci *
243562306a36Sopenharmony_ci * This function will return the match fields of the first instance of flow
243662306a36Sopenharmony_ci * profile having the given header types and containing input VSI
243762306a36Sopenharmony_ci */
243862306a36Sopenharmony_ciu64 ice_get_rss_cfg(struct ice_hw *hw, u16 vsi_handle, u32 hdrs)
243962306a36Sopenharmony_ci{
244062306a36Sopenharmony_ci	u64 rss_hash = ICE_HASH_INVALID;
244162306a36Sopenharmony_ci	struct ice_rss_cfg *r;
244262306a36Sopenharmony_ci
244362306a36Sopenharmony_ci	/* verify if the protocol header is non zero and VSI is valid */
244462306a36Sopenharmony_ci	if (hdrs == ICE_FLOW_SEG_HDR_NONE || !ice_is_vsi_valid(hw, vsi_handle))
244562306a36Sopenharmony_ci		return ICE_HASH_INVALID;
244662306a36Sopenharmony_ci
244762306a36Sopenharmony_ci	mutex_lock(&hw->rss_locks);
244862306a36Sopenharmony_ci	list_for_each_entry(r, &hw->rss_list_head, l_entry)
244962306a36Sopenharmony_ci		if (test_bit(vsi_handle, r->vsis) &&
245062306a36Sopenharmony_ci		    r->packet_hdr == hdrs) {
245162306a36Sopenharmony_ci			rss_hash = r->hashed_flds;
245262306a36Sopenharmony_ci			break;
245362306a36Sopenharmony_ci		}
245462306a36Sopenharmony_ci	mutex_unlock(&hw->rss_locks);
245562306a36Sopenharmony_ci
245662306a36Sopenharmony_ci	return rss_hash;
245762306a36Sopenharmony_ci}
2458