1c90ed40cSTony Nguyen // SPDX-License-Identifier: GPL-2.0
2c90ed40cSTony Nguyen /* Copyright (c) 2019, Intel Corporation. */
3c90ed40cSTony Nguyen 
4c90ed40cSTony Nguyen #include "ice_common.h"
5c90ed40cSTony Nguyen #include "ice_flow.h"
6c90ed40cSTony Nguyen 
7c90ed40cSTony Nguyen /* Describe properties of a protocol header field */
8c90ed40cSTony Nguyen struct ice_flow_field_info {
9c90ed40cSTony Nguyen 	enum ice_flow_seg_hdr hdr;
10c90ed40cSTony Nguyen 	s16 off;	/* Offset from start of a protocol header, in bits */
11c90ed40cSTony Nguyen 	u16 size;	/* Size of fields in bits */
12b199dddbSQi Zhang 	u16 mask;	/* 16-bit mask for field */
13c90ed40cSTony Nguyen };
14c90ed40cSTony Nguyen 
15c90ed40cSTony Nguyen #define ICE_FLOW_FLD_INFO(_hdr, _offset_bytes, _size_bytes) { \
16c90ed40cSTony Nguyen 	.hdr = _hdr, \
17c90ed40cSTony Nguyen 	.off = (_offset_bytes) * BITS_PER_BYTE, \
18c90ed40cSTony Nguyen 	.size = (_size_bytes) * BITS_PER_BYTE, \
19b199dddbSQi Zhang 	.mask = 0, \
20b199dddbSQi Zhang }
21b199dddbSQi Zhang 
22b199dddbSQi Zhang #define ICE_FLOW_FLD_INFO_MSK(_hdr, _offset_bytes, _size_bytes, _mask) { \
23b199dddbSQi Zhang 	.hdr = _hdr, \
24b199dddbSQi Zhang 	.off = (_offset_bytes) * BITS_PER_BYTE, \
25b199dddbSQi Zhang 	.size = (_size_bytes) * BITS_PER_BYTE, \
26b199dddbSQi Zhang 	.mask = _mask, \
27c90ed40cSTony Nguyen }
28c90ed40cSTony Nguyen 
29c90ed40cSTony Nguyen /* Table containing properties of supported protocol header fields */
30c90ed40cSTony Nguyen static const
31c90ed40cSTony Nguyen struct ice_flow_field_info ice_flds_info[ICE_FLOW_FIELD_IDX_MAX] = {
32390bd141SQi Zhang 	/* Ether */
33390bd141SQi Zhang 	/* ICE_FLOW_FIELD_IDX_ETH_DA */
34390bd141SQi Zhang 	ICE_FLOW_FLD_INFO(ICE_FLOW_SEG_HDR_ETH, 0, ETH_ALEN),
35390bd141SQi Zhang 	/* ICE_FLOW_FIELD_IDX_ETH_SA */
36390bd141SQi Zhang 	ICE_FLOW_FLD_INFO(ICE_FLOW_SEG_HDR_ETH, ETH_ALEN, ETH_ALEN),
37390bd141SQi Zhang 	/* ICE_FLOW_FIELD_IDX_S_VLAN */
38390bd141SQi Zhang 	ICE_FLOW_FLD_INFO(ICE_FLOW_SEG_HDR_VLAN, 12, sizeof(__be16)),
39390bd141SQi Zhang 	/* ICE_FLOW_FIELD_IDX_C_VLAN */
40390bd141SQi Zhang 	ICE_FLOW_FLD_INFO(ICE_FLOW_SEG_HDR_VLAN, 14, sizeof(__be16)),
41390bd141SQi Zhang 	/* ICE_FLOW_FIELD_IDX_ETH_TYPE */
42390bd141SQi Zhang 	ICE_FLOW_FLD_INFO(ICE_FLOW_SEG_HDR_ETH, 0, sizeof(__be16)),
43c90ed40cSTony Nguyen 	/* IPv4 / IPv6 */
44b199dddbSQi Zhang 	/* ICE_FLOW_FIELD_IDX_IPV4_DSCP */
45b199dddbSQi Zhang 	ICE_FLOW_FLD_INFO_MSK(ICE_FLOW_SEG_HDR_IPV4, 0, 1, 0x00fc),
46b199dddbSQi Zhang 	/* ICE_FLOW_FIELD_IDX_IPV6_DSCP */
47b199dddbSQi Zhang 	ICE_FLOW_FLD_INFO_MSK(ICE_FLOW_SEG_HDR_IPV6, 0, 1, 0x0ff0),
48b199dddbSQi Zhang 	/* ICE_FLOW_FIELD_IDX_IPV4_TTL */
49b199dddbSQi Zhang 	ICE_FLOW_FLD_INFO_MSK(ICE_FLOW_SEG_HDR_NONE, 8, 1, 0xff00),
50b199dddbSQi Zhang 	/* ICE_FLOW_FIELD_IDX_IPV4_PROT */
51b199dddbSQi Zhang 	ICE_FLOW_FLD_INFO_MSK(ICE_FLOW_SEG_HDR_NONE, 8, 1, 0x00ff),
52b199dddbSQi Zhang 	/* ICE_FLOW_FIELD_IDX_IPV6_TTL */
53b199dddbSQi Zhang 	ICE_FLOW_FLD_INFO_MSK(ICE_FLOW_SEG_HDR_NONE, 6, 1, 0x00ff),
54b199dddbSQi Zhang 	/* ICE_FLOW_FIELD_IDX_IPV6_PROT */
55b199dddbSQi Zhang 	ICE_FLOW_FLD_INFO_MSK(ICE_FLOW_SEG_HDR_NONE, 6, 1, 0xff00),
56c90ed40cSTony Nguyen 	/* ICE_FLOW_FIELD_IDX_IPV4_SA */
57c90ed40cSTony Nguyen 	ICE_FLOW_FLD_INFO(ICE_FLOW_SEG_HDR_IPV4, 12, sizeof(struct in_addr)),
58c90ed40cSTony Nguyen 	/* ICE_FLOW_FIELD_IDX_IPV4_DA */
59c90ed40cSTony Nguyen 	ICE_FLOW_FLD_INFO(ICE_FLOW_SEG_HDR_IPV4, 16, sizeof(struct in_addr)),
60c90ed40cSTony Nguyen 	/* ICE_FLOW_FIELD_IDX_IPV6_SA */
61c90ed40cSTony Nguyen 	ICE_FLOW_FLD_INFO(ICE_FLOW_SEG_HDR_IPV6, 8, sizeof(struct in6_addr)),
62c90ed40cSTony Nguyen 	/* ICE_FLOW_FIELD_IDX_IPV6_DA */
63c90ed40cSTony Nguyen 	ICE_FLOW_FLD_INFO(ICE_FLOW_SEG_HDR_IPV6, 24, sizeof(struct in6_addr)),
64c90ed40cSTony Nguyen 	/* Transport */
65c90ed40cSTony Nguyen 	/* ICE_FLOW_FIELD_IDX_TCP_SRC_PORT */
66c90ed40cSTony Nguyen 	ICE_FLOW_FLD_INFO(ICE_FLOW_SEG_HDR_TCP, 0, sizeof(__be16)),
67c90ed40cSTony Nguyen 	/* ICE_FLOW_FIELD_IDX_TCP_DST_PORT */
68c90ed40cSTony Nguyen 	ICE_FLOW_FLD_INFO(ICE_FLOW_SEG_HDR_TCP, 2, sizeof(__be16)),
69c90ed40cSTony Nguyen 	/* ICE_FLOW_FIELD_IDX_UDP_SRC_PORT */
70c90ed40cSTony Nguyen 	ICE_FLOW_FLD_INFO(ICE_FLOW_SEG_HDR_UDP, 0, sizeof(__be16)),
71c90ed40cSTony Nguyen 	/* ICE_FLOW_FIELD_IDX_UDP_DST_PORT */
72c90ed40cSTony Nguyen 	ICE_FLOW_FLD_INFO(ICE_FLOW_SEG_HDR_UDP, 2, sizeof(__be16)),
731c01c8c6SMd Fahad Iqbal Polash 	/* ICE_FLOW_FIELD_IDX_SCTP_SRC_PORT */
741c01c8c6SMd Fahad Iqbal Polash 	ICE_FLOW_FLD_INFO(ICE_FLOW_SEG_HDR_SCTP, 0, sizeof(__be16)),
751c01c8c6SMd Fahad Iqbal Polash 	/* ICE_FLOW_FIELD_IDX_SCTP_DST_PORT */
761c01c8c6SMd Fahad Iqbal Polash 	ICE_FLOW_FLD_INFO(ICE_FLOW_SEG_HDR_SCTP, 2, sizeof(__be16)),
77390bd141SQi Zhang 	/* ICE_FLOW_FIELD_IDX_TCP_FLAGS */
78390bd141SQi Zhang 	ICE_FLOW_FLD_INFO(ICE_FLOW_SEG_HDR_TCP, 13, 1),
79390bd141SQi Zhang 	/* ARP */
80390bd141SQi Zhang 	/* ICE_FLOW_FIELD_IDX_ARP_SIP */
81390bd141SQi Zhang 	ICE_FLOW_FLD_INFO(ICE_FLOW_SEG_HDR_ARP, 14, sizeof(struct in_addr)),
82390bd141SQi Zhang 	/* ICE_FLOW_FIELD_IDX_ARP_DIP */
83390bd141SQi Zhang 	ICE_FLOW_FLD_INFO(ICE_FLOW_SEG_HDR_ARP, 24, sizeof(struct in_addr)),
84390bd141SQi Zhang 	/* ICE_FLOW_FIELD_IDX_ARP_SHA */
85390bd141SQi Zhang 	ICE_FLOW_FLD_INFO(ICE_FLOW_SEG_HDR_ARP, 8, ETH_ALEN),
86390bd141SQi Zhang 	/* ICE_FLOW_FIELD_IDX_ARP_DHA */
87390bd141SQi Zhang 	ICE_FLOW_FLD_INFO(ICE_FLOW_SEG_HDR_ARP, 18, ETH_ALEN),
88390bd141SQi Zhang 	/* ICE_FLOW_FIELD_IDX_ARP_OP */
89390bd141SQi Zhang 	ICE_FLOW_FLD_INFO(ICE_FLOW_SEG_HDR_ARP, 6, sizeof(__be16)),
90390bd141SQi Zhang 	/* ICMP */
91390bd141SQi Zhang 	/* ICE_FLOW_FIELD_IDX_ICMP_TYPE */
92390bd141SQi Zhang 	ICE_FLOW_FLD_INFO(ICE_FLOW_SEG_HDR_ICMP, 0, 1),
93390bd141SQi Zhang 	/* ICE_FLOW_FIELD_IDX_ICMP_CODE */
94390bd141SQi Zhang 	ICE_FLOW_FLD_INFO(ICE_FLOW_SEG_HDR_ICMP, 1, 1),
95a4e82a81STony Nguyen 	/* GRE */
96a4e82a81STony Nguyen 	/* ICE_FLOW_FIELD_IDX_GRE_KEYID */
97a4e82a81STony Nguyen 	ICE_FLOW_FLD_INFO(ICE_FLOW_SEG_HDR_GRE, 12,
98a4e82a81STony Nguyen 			  sizeof_field(struct gre_full_hdr, key)),
990577313eSQi Zhang 	/* GTP */
1000577313eSQi Zhang 	/* ICE_FLOW_FIELD_IDX_GTPC_TEID */
1010577313eSQi Zhang 	ICE_FLOW_FLD_INFO(ICE_FLOW_SEG_HDR_GTPC_TEID, 12, sizeof(__be32)),
1020577313eSQi Zhang 	/* ICE_FLOW_FIELD_IDX_GTPU_IP_TEID */
1030577313eSQi Zhang 	ICE_FLOW_FLD_INFO(ICE_FLOW_SEG_HDR_GTPU_IP, 12, sizeof(__be32)),
1040577313eSQi Zhang 	/* ICE_FLOW_FIELD_IDX_GTPU_EH_TEID */
1050577313eSQi Zhang 	ICE_FLOW_FLD_INFO(ICE_FLOW_SEG_HDR_GTPU_EH, 12, sizeof(__be32)),
1060577313eSQi Zhang 	/* ICE_FLOW_FIELD_IDX_GTPU_EH_QFI */
1070577313eSQi Zhang 	ICE_FLOW_FLD_INFO_MSK(ICE_FLOW_SEG_HDR_GTPU_EH, 22, sizeof(__be16),
1080577313eSQi Zhang 			      0x3f00),
1090577313eSQi Zhang 	/* ICE_FLOW_FIELD_IDX_GTPU_UP_TEID */
1100577313eSQi Zhang 	ICE_FLOW_FLD_INFO(ICE_FLOW_SEG_HDR_GTPU_UP, 12, sizeof(__be32)),
1110577313eSQi Zhang 	/* ICE_FLOW_FIELD_IDX_GTPU_DWN_TEID */
1120577313eSQi Zhang 	ICE_FLOW_FLD_INFO(ICE_FLOW_SEG_HDR_GTPU_DWN, 12, sizeof(__be32)),
1130577313eSQi Zhang 	/* PPPoE */
1140577313eSQi Zhang 	/* ICE_FLOW_FIELD_IDX_PPPOE_SESS_ID */
1150577313eSQi Zhang 	ICE_FLOW_FLD_INFO(ICE_FLOW_SEG_HDR_PPPOE, 2, sizeof(__be16)),
1160577313eSQi Zhang 	/* PFCP */
1170577313eSQi Zhang 	/* ICE_FLOW_FIELD_IDX_PFCP_SEID */
1180577313eSQi Zhang 	ICE_FLOW_FLD_INFO(ICE_FLOW_SEG_HDR_PFCP_SESSION, 12, sizeof(__be64)),
1190577313eSQi Zhang 	/* L2TPv3 */
1200577313eSQi Zhang 	/* ICE_FLOW_FIELD_IDX_L2TPV3_SESS_ID */
1210577313eSQi Zhang 	ICE_FLOW_FLD_INFO(ICE_FLOW_SEG_HDR_L2TPV3, 0, sizeof(__be32)),
1220577313eSQi Zhang 	/* ESP */
1230577313eSQi Zhang 	/* ICE_FLOW_FIELD_IDX_ESP_SPI */
1240577313eSQi Zhang 	ICE_FLOW_FLD_INFO(ICE_FLOW_SEG_HDR_ESP, 0, sizeof(__be32)),
1250577313eSQi Zhang 	/* AH */
1260577313eSQi Zhang 	/* ICE_FLOW_FIELD_IDX_AH_SPI */
1270577313eSQi Zhang 	ICE_FLOW_FLD_INFO(ICE_FLOW_SEG_HDR_AH, 4, sizeof(__be32)),
1280577313eSQi Zhang 	/* NAT_T_ESP */
1290577313eSQi Zhang 	/* ICE_FLOW_FIELD_IDX_NAT_T_ESP_SPI */
1300577313eSQi Zhang 	ICE_FLOW_FLD_INFO(ICE_FLOW_SEG_HDR_NAT_T_ESP, 8, sizeof(__be32)),
131c90ed40cSTony Nguyen };
132c90ed40cSTony Nguyen 
13331ad4e4eSTony Nguyen /* Bitmaps indicating relevant packet types for a particular protocol header
13431ad4e4eSTony Nguyen  *
135390bd141SQi Zhang  * Packet types for packets with an Outer/First/Single MAC header
13631ad4e4eSTony Nguyen  */
137390bd141SQi Zhang static const u32 ice_ptypes_mac_ofos[] = {
138390bd141SQi Zhang 	0xFDC00846, 0xBFBF7F7E, 0xF70001DF, 0xFEFDFDFB,
139390bd141SQi Zhang 	0x0000077E, 0x00000000, 0x00000000, 0x00000000,
140390bd141SQi Zhang 	0x00400000, 0x03FFF000, 0x7FFFFFE0, 0x00000000,
141390bd141SQi Zhang 	0x00000000, 0x00000000, 0x00000000, 0x00000000,
142390bd141SQi Zhang 	0x00000000, 0x00000000, 0x00000000, 0x00000000,
143390bd141SQi Zhang 	0x00000000, 0x00000000, 0x00000000, 0x00000000,
144390bd141SQi Zhang 	0x00000000, 0x00000000, 0x00000000, 0x00000000,
145390bd141SQi Zhang 	0x00000000, 0x00000000, 0x00000000, 0x00000000,
146390bd141SQi Zhang };
147390bd141SQi Zhang 
148390bd141SQi Zhang /* Packet types for packets with an Innermost/Last MAC VLAN header */
149390bd141SQi Zhang static const u32 ice_ptypes_macvlan_il[] = {
150390bd141SQi Zhang 	0x00000000, 0xBC000000, 0x000001DF, 0xF0000000,
151390bd141SQi Zhang 	0x0000077E, 0x00000000, 0x00000000, 0x00000000,
152390bd141SQi Zhang 	0x00000000, 0x00000000, 0x00000000, 0x00000000,
153390bd141SQi Zhang 	0x00000000, 0x00000000, 0x00000000, 0x00000000,
154390bd141SQi Zhang 	0x00000000, 0x00000000, 0x00000000, 0x00000000,
155390bd141SQi Zhang 	0x00000000, 0x00000000, 0x00000000, 0x00000000,
156390bd141SQi Zhang 	0x00000000, 0x00000000, 0x00000000, 0x00000000,
157390bd141SQi Zhang 	0x00000000, 0x00000000, 0x00000000, 0x00000000,
158390bd141SQi Zhang };
159390bd141SQi Zhang 
1607012dfd1SQi Zhang /* Packet types for packets with an Outer/First/Single IPv4 header, does NOT
1617012dfd1SQi Zhang  * include IPv4 other PTYPEs
1627012dfd1SQi Zhang  */
16331ad4e4eSTony Nguyen static const u32 ice_ptypes_ipv4_ofos[] = {
16431ad4e4eSTony Nguyen 	0x1DC00000, 0x04000800, 0x00000000, 0x00000000,
1650577313eSQi Zhang 	0x00000000, 0x00000155, 0x00000000, 0x00000000,
1660577313eSQi Zhang 	0x00000000, 0x000FC000, 0x00000000, 0x00000000,
16731ad4e4eSTony Nguyen 	0x00000000, 0x00000000, 0x00000000, 0x00000000,
16831ad4e4eSTony Nguyen 	0x00000000, 0x00000000, 0x00000000, 0x00000000,
16931ad4e4eSTony Nguyen 	0x00000000, 0x00000000, 0x00000000, 0x00000000,
17031ad4e4eSTony Nguyen 	0x00000000, 0x00000000, 0x00000000, 0x00000000,
17131ad4e4eSTony Nguyen 	0x00000000, 0x00000000, 0x00000000, 0x00000000,
1727012dfd1SQi Zhang };
1737012dfd1SQi Zhang 
1747012dfd1SQi Zhang /* Packet types for packets with an Outer/First/Single IPv4 header, includes
1757012dfd1SQi Zhang  * IPv4 other PTYPEs
1767012dfd1SQi Zhang  */
1777012dfd1SQi Zhang static const u32 ice_ptypes_ipv4_ofos_all[] = {
1787012dfd1SQi Zhang 	0x1DC00000, 0x04000800, 0x00000000, 0x00000000,
1797012dfd1SQi Zhang 	0x00000000, 0x00000155, 0x00000000, 0x00000000,
1807012dfd1SQi Zhang 	0x00000000, 0x000FC000, 0x83E0F800, 0x00000101,
1817012dfd1SQi Zhang 	0x00000000, 0x00000000, 0x00000000, 0x00000000,
1827012dfd1SQi Zhang 	0x00000000, 0x00000000, 0x00000000, 0x00000000,
1837012dfd1SQi Zhang 	0x00000000, 0x00000000, 0x00000000, 0x00000000,
18431ad4e4eSTony Nguyen 	0x00000000, 0x00000000, 0x00000000, 0x00000000,
18531ad4e4eSTony Nguyen 	0x00000000, 0x00000000, 0x00000000, 0x00000000,
18631ad4e4eSTony Nguyen };
18731ad4e4eSTony Nguyen 
18831ad4e4eSTony Nguyen /* Packet types for packets with an Innermost/Last IPv4 header */
18931ad4e4eSTony Nguyen static const u32 ice_ptypes_ipv4_il[] = {
19031ad4e4eSTony Nguyen 	0xE0000000, 0xB807700E, 0x80000003, 0xE01DC03B,
19131ad4e4eSTony Nguyen 	0x0000000E, 0x00000000, 0x00000000, 0x00000000,
1920577313eSQi Zhang 	0x00000000, 0x00000000, 0x001FF800, 0x00000000,
19331ad4e4eSTony Nguyen 	0x00000000, 0x00000000, 0x00000000, 0x00000000,
19431ad4e4eSTony Nguyen 	0x00000000, 0x00000000, 0x00000000, 0x00000000,
19531ad4e4eSTony Nguyen 	0x00000000, 0x00000000, 0x00000000, 0x00000000,
19631ad4e4eSTony Nguyen 	0x00000000, 0x00000000, 0x00000000, 0x00000000,
19731ad4e4eSTony Nguyen 	0x00000000, 0x00000000, 0x00000000, 0x00000000,
19831ad4e4eSTony Nguyen };
19931ad4e4eSTony Nguyen 
2007012dfd1SQi Zhang /* Packet types for packets with an Outer/First/Single IPv6 header, does NOT
2017012dfd1SQi Zhang  * include IPv6 other PTYPEs
2027012dfd1SQi Zhang  */
20331ad4e4eSTony Nguyen static const u32 ice_ptypes_ipv6_ofos[] = {
20431ad4e4eSTony Nguyen 	0x00000000, 0x00000000, 0x77000000, 0x10002000,
2050577313eSQi Zhang 	0x00000000, 0x000002AA, 0x00000000, 0x00000000,
2060577313eSQi Zhang 	0x00000000, 0x03F00000, 0x00000000, 0x00000000,
20731ad4e4eSTony Nguyen 	0x00000000, 0x00000000, 0x00000000, 0x00000000,
20831ad4e4eSTony Nguyen 	0x00000000, 0x00000000, 0x00000000, 0x00000000,
20931ad4e4eSTony Nguyen 	0x00000000, 0x00000000, 0x00000000, 0x00000000,
21031ad4e4eSTony Nguyen 	0x00000000, 0x00000000, 0x00000000, 0x00000000,
21131ad4e4eSTony Nguyen 	0x00000000, 0x00000000, 0x00000000, 0x00000000,
2127012dfd1SQi Zhang };
2137012dfd1SQi Zhang 
2147012dfd1SQi Zhang /* Packet types for packets with an Outer/First/Single IPv6 header, includes
2157012dfd1SQi Zhang  * IPv6 other PTYPEs
2167012dfd1SQi Zhang  */
2177012dfd1SQi Zhang static const u32 ice_ptypes_ipv6_ofos_all[] = {
2187012dfd1SQi Zhang 	0x00000000, 0x00000000, 0x77000000, 0x10002000,
2197012dfd1SQi Zhang 	0x00000000, 0x000002AA, 0x00000000, 0x00000000,
2207012dfd1SQi Zhang 	0x00080F00, 0x03F00000, 0x7C1F0000, 0x00000206,
2217012dfd1SQi Zhang 	0x00000000, 0x00000000, 0x00000000, 0x00000000,
2227012dfd1SQi Zhang 	0x00000000, 0x00000000, 0x00000000, 0x00000000,
2237012dfd1SQi Zhang 	0x00000000, 0x00000000, 0x00000000, 0x00000000,
22431ad4e4eSTony Nguyen 	0x00000000, 0x00000000, 0x00000000, 0x00000000,
22531ad4e4eSTony Nguyen 	0x00000000, 0x00000000, 0x00000000, 0x00000000,
22631ad4e4eSTony Nguyen };
22731ad4e4eSTony Nguyen 
22831ad4e4eSTony Nguyen /* Packet types for packets with an Innermost/Last IPv6 header */
22931ad4e4eSTony Nguyen static const u32 ice_ptypes_ipv6_il[] = {
23031ad4e4eSTony Nguyen 	0x00000000, 0x03B80770, 0x000001DC, 0x0EE00000,
23131ad4e4eSTony Nguyen 	0x00000770, 0x00000000, 0x00000000, 0x00000000,
2320577313eSQi Zhang 	0x00000000, 0x00000000, 0x7FE00000, 0x00000000,
23331ad4e4eSTony Nguyen 	0x00000000, 0x00000000, 0x00000000, 0x00000000,
23431ad4e4eSTony Nguyen 	0x00000000, 0x00000000, 0x00000000, 0x00000000,
23531ad4e4eSTony Nguyen 	0x00000000, 0x00000000, 0x00000000, 0x00000000,
23631ad4e4eSTony Nguyen 	0x00000000, 0x00000000, 0x00000000, 0x00000000,
23731ad4e4eSTony Nguyen 	0x00000000, 0x00000000, 0x00000000, 0x00000000,
23831ad4e4eSTony Nguyen };
23931ad4e4eSTony Nguyen 
240051d2b5cSDan Nowlin /* Packet types for packets with an Outer/First/Single IPv4 header - no L4 */
241*94a93698SQi Zhang static const u32 ice_ptypes_ipv4_ofos_no_l4[] = {
242051d2b5cSDan Nowlin 	0x10C00000, 0x04000800, 0x00000000, 0x00000000,
243051d2b5cSDan Nowlin 	0x00000000, 0x00000000, 0x00000000, 0x00000000,
244051d2b5cSDan Nowlin 	0x00000000, 0x00000000, 0x00000000, 0x00000000,
245051d2b5cSDan Nowlin 	0x00000000, 0x00000000, 0x00000000, 0x00000000,
246051d2b5cSDan Nowlin 	0x00000000, 0x00000000, 0x00000000, 0x00000000,
247051d2b5cSDan Nowlin 	0x00000000, 0x00000000, 0x00000000, 0x00000000,
248051d2b5cSDan Nowlin 	0x00000000, 0x00000000, 0x00000000, 0x00000000,
249051d2b5cSDan Nowlin 	0x00000000, 0x00000000, 0x00000000, 0x00000000,
250051d2b5cSDan Nowlin };
251051d2b5cSDan Nowlin 
252390bd141SQi Zhang /* Packet types for packets with an Outermost/First ARP header */
253390bd141SQi Zhang static const u32 ice_ptypes_arp_of[] = {
254390bd141SQi Zhang 	0x00000800, 0x00000000, 0x00000000, 0x00000000,
255390bd141SQi Zhang 	0x00000000, 0x00000000, 0x00000000, 0x00000000,
256390bd141SQi Zhang 	0x00000000, 0x00000000, 0x00000000, 0x00000000,
257390bd141SQi Zhang 	0x00000000, 0x00000000, 0x00000000, 0x00000000,
258390bd141SQi Zhang 	0x00000000, 0x00000000, 0x00000000, 0x00000000,
259390bd141SQi Zhang 	0x00000000, 0x00000000, 0x00000000, 0x00000000,
260390bd141SQi Zhang 	0x00000000, 0x00000000, 0x00000000, 0x00000000,
261390bd141SQi Zhang 	0x00000000, 0x00000000, 0x00000000, 0x00000000,
262390bd141SQi Zhang };
263390bd141SQi Zhang 
264051d2b5cSDan Nowlin /* Packet types for packets with an Innermost/Last IPv4 header - no L4 */
265*94a93698SQi Zhang static const u32 ice_ptypes_ipv4_il_no_l4[] = {
266051d2b5cSDan Nowlin 	0x60000000, 0x18043008, 0x80000002, 0x6010c021,
267051d2b5cSDan Nowlin 	0x00000008, 0x00000000, 0x00000000, 0x00000000,
268051d2b5cSDan Nowlin 	0x00000000, 0x00000000, 0x00000000, 0x00000000,
269051d2b5cSDan Nowlin 	0x00000000, 0x00000000, 0x00000000, 0x00000000,
270051d2b5cSDan Nowlin 	0x00000000, 0x00000000, 0x00000000, 0x00000000,
271051d2b5cSDan Nowlin 	0x00000000, 0x00000000, 0x00000000, 0x00000000,
272051d2b5cSDan Nowlin 	0x00000000, 0x00000000, 0x00000000, 0x00000000,
273051d2b5cSDan Nowlin 	0x00000000, 0x00000000, 0x00000000, 0x00000000,
274051d2b5cSDan Nowlin };
275051d2b5cSDan Nowlin 
276051d2b5cSDan Nowlin /* Packet types for packets with an Outer/First/Single IPv6 header - no L4 */
277*94a93698SQi Zhang static const u32 ice_ptypes_ipv6_ofos_no_l4[] = {
278051d2b5cSDan Nowlin 	0x00000000, 0x00000000, 0x43000000, 0x10002000,
279051d2b5cSDan Nowlin 	0x00000000, 0x00000000, 0x00000000, 0x00000000,
280051d2b5cSDan Nowlin 	0x00000000, 0x00000000, 0x00000000, 0x00000000,
281051d2b5cSDan Nowlin 	0x00000000, 0x00000000, 0x00000000, 0x00000000,
282051d2b5cSDan Nowlin 	0x00000000, 0x00000000, 0x00000000, 0x00000000,
283051d2b5cSDan Nowlin 	0x00000000, 0x00000000, 0x00000000, 0x00000000,
284051d2b5cSDan Nowlin 	0x00000000, 0x00000000, 0x00000000, 0x00000000,
285051d2b5cSDan Nowlin 	0x00000000, 0x00000000, 0x00000000, 0x00000000,
286051d2b5cSDan Nowlin };
287051d2b5cSDan Nowlin 
288051d2b5cSDan Nowlin /* Packet types for packets with an Innermost/Last IPv6 header - no L4 */
289*94a93698SQi Zhang static const u32 ice_ptypes_ipv6_il_no_l4[] = {
290051d2b5cSDan Nowlin 	0x00000000, 0x02180430, 0x0000010c, 0x086010c0,
291051d2b5cSDan Nowlin 	0x00000430, 0x00000000, 0x00000000, 0x00000000,
292051d2b5cSDan Nowlin 	0x00000000, 0x00000000, 0x00000000, 0x00000000,
293051d2b5cSDan Nowlin 	0x00000000, 0x00000000, 0x00000000, 0x00000000,
294051d2b5cSDan Nowlin 	0x00000000, 0x00000000, 0x00000000, 0x00000000,
295051d2b5cSDan Nowlin 	0x00000000, 0x00000000, 0x00000000, 0x00000000,
296051d2b5cSDan Nowlin 	0x00000000, 0x00000000, 0x00000000, 0x00000000,
297051d2b5cSDan Nowlin 	0x00000000, 0x00000000, 0x00000000, 0x00000000,
298051d2b5cSDan Nowlin };
299051d2b5cSDan Nowlin 
30031ad4e4eSTony Nguyen /* UDP Packet types for non-tunneled packets or tunneled
30131ad4e4eSTony Nguyen  * packets with inner UDP.
30231ad4e4eSTony Nguyen  */
30331ad4e4eSTony Nguyen static const u32 ice_ptypes_udp_il[] = {
30431ad4e4eSTony Nguyen 	0x81000000, 0x20204040, 0x04000010, 0x80810102,
30531ad4e4eSTony Nguyen 	0x00000040, 0x00000000, 0x00000000, 0x00000000,
3060577313eSQi Zhang 	0x00000000, 0x00410000, 0x90842000, 0x00000007,
30731ad4e4eSTony Nguyen 	0x00000000, 0x00000000, 0x00000000, 0x00000000,
30831ad4e4eSTony Nguyen 	0x00000000, 0x00000000, 0x00000000, 0x00000000,
30931ad4e4eSTony Nguyen 	0x00000000, 0x00000000, 0x00000000, 0x00000000,
31031ad4e4eSTony Nguyen 	0x00000000, 0x00000000, 0x00000000, 0x00000000,
31131ad4e4eSTony Nguyen 	0x00000000, 0x00000000, 0x00000000, 0x00000000,
31231ad4e4eSTony Nguyen };
31331ad4e4eSTony Nguyen 
31431ad4e4eSTony Nguyen /* Packet types for packets with an Innermost/Last TCP header */
31531ad4e4eSTony Nguyen static const u32 ice_ptypes_tcp_il[] = {
31631ad4e4eSTony Nguyen 	0x04000000, 0x80810102, 0x10000040, 0x02040408,
31731ad4e4eSTony Nguyen 	0x00000102, 0x00000000, 0x00000000, 0x00000000,
3180577313eSQi Zhang 	0x00000000, 0x00820000, 0x21084000, 0x00000000,
31931ad4e4eSTony Nguyen 	0x00000000, 0x00000000, 0x00000000, 0x00000000,
32031ad4e4eSTony Nguyen 	0x00000000, 0x00000000, 0x00000000, 0x00000000,
32131ad4e4eSTony Nguyen 	0x00000000, 0x00000000, 0x00000000, 0x00000000,
32231ad4e4eSTony Nguyen 	0x00000000, 0x00000000, 0x00000000, 0x00000000,
32331ad4e4eSTony Nguyen 	0x00000000, 0x00000000, 0x00000000, 0x00000000,
32431ad4e4eSTony Nguyen };
32531ad4e4eSTony Nguyen 
32631ad4e4eSTony Nguyen /* Packet types for packets with an Innermost/Last SCTP header */
32731ad4e4eSTony Nguyen static const u32 ice_ptypes_sctp_il[] = {
32831ad4e4eSTony Nguyen 	0x08000000, 0x01020204, 0x20000081, 0x04080810,
32931ad4e4eSTony Nguyen 	0x00000204, 0x00000000, 0x00000000, 0x00000000,
3300577313eSQi Zhang 	0x00000000, 0x01040000, 0x00000000, 0x00000000,
33131ad4e4eSTony Nguyen 	0x00000000, 0x00000000, 0x00000000, 0x00000000,
33231ad4e4eSTony Nguyen 	0x00000000, 0x00000000, 0x00000000, 0x00000000,
33331ad4e4eSTony Nguyen 	0x00000000, 0x00000000, 0x00000000, 0x00000000,
33431ad4e4eSTony Nguyen 	0x00000000, 0x00000000, 0x00000000, 0x00000000,
33531ad4e4eSTony Nguyen 	0x00000000, 0x00000000, 0x00000000, 0x00000000,
336390bd141SQi Zhang };
337390bd141SQi Zhang 
338390bd141SQi Zhang /* Packet types for packets with an Outermost/First ICMP header */
339390bd141SQi Zhang static const u32 ice_ptypes_icmp_of[] = {
340390bd141SQi Zhang 	0x10000000, 0x00000000, 0x00000000, 0x00000000,
341390bd141SQi Zhang 	0x00000000, 0x00000000, 0x00000000, 0x00000000,
342390bd141SQi Zhang 	0x00000000, 0x00000000, 0x00000000, 0x00000000,
343390bd141SQi Zhang 	0x00000000, 0x00000000, 0x00000000, 0x00000000,
344390bd141SQi Zhang 	0x00000000, 0x00000000, 0x00000000, 0x00000000,
345390bd141SQi Zhang 	0x00000000, 0x00000000, 0x00000000, 0x00000000,
346390bd141SQi Zhang 	0x00000000, 0x00000000, 0x00000000, 0x00000000,
347390bd141SQi Zhang 	0x00000000, 0x00000000, 0x00000000, 0x00000000,
348390bd141SQi Zhang };
349390bd141SQi Zhang 
350390bd141SQi Zhang /* Packet types for packets with an Innermost/Last ICMP header */
351390bd141SQi Zhang static const u32 ice_ptypes_icmp_il[] = {
352390bd141SQi Zhang 	0x00000000, 0x02040408, 0x40000102, 0x08101020,
353390bd141SQi Zhang 	0x00000408, 0x00000000, 0x00000000, 0x00000000,
354390bd141SQi Zhang 	0x00000000, 0x00000000, 0x42108000, 0x00000000,
355390bd141SQi Zhang 	0x00000000, 0x00000000, 0x00000000, 0x00000000,
356390bd141SQi Zhang 	0x00000000, 0x00000000, 0x00000000, 0x00000000,
357390bd141SQi Zhang 	0x00000000, 0x00000000, 0x00000000, 0x00000000,
358390bd141SQi Zhang 	0x00000000, 0x00000000, 0x00000000, 0x00000000,
35931ad4e4eSTony Nguyen 	0x00000000, 0x00000000, 0x00000000, 0x00000000,
36031ad4e4eSTony Nguyen };
36131ad4e4eSTony Nguyen 
362a4e82a81STony Nguyen /* Packet types for packets with an Outermost/First GRE header */
363a4e82a81STony Nguyen static const u32 ice_ptypes_gre_of[] = {
364a4e82a81STony Nguyen 	0x00000000, 0xBFBF7800, 0x000001DF, 0xFEFDE000,
365a4e82a81STony Nguyen 	0x0000017E, 0x00000000, 0x00000000, 0x00000000,
366a4e82a81STony Nguyen 	0x00000000, 0x00000000, 0x00000000, 0x00000000,
367a4e82a81STony Nguyen 	0x00000000, 0x00000000, 0x00000000, 0x00000000,
368a4e82a81STony Nguyen 	0x00000000, 0x00000000, 0x00000000, 0x00000000,
369a4e82a81STony Nguyen 	0x00000000, 0x00000000, 0x00000000, 0x00000000,
370a4e82a81STony Nguyen 	0x00000000, 0x00000000, 0x00000000, 0x00000000,
371a4e82a81STony Nguyen 	0x00000000, 0x00000000, 0x00000000, 0x00000000,
372a4e82a81STony Nguyen };
373a4e82a81STony Nguyen 
374390bd141SQi Zhang /* Packet types for packets with an Innermost/Last MAC header */
375390bd141SQi Zhang static const u32 ice_ptypes_mac_il[] = {
376390bd141SQi Zhang 	0x00000000, 0x00000000, 0x00000000, 0x00000000,
377390bd141SQi Zhang 	0x00000000, 0x00000000, 0x00000000, 0x00000000,
378390bd141SQi Zhang 	0x00000000, 0x00000000, 0x00000000, 0x00000000,
379390bd141SQi Zhang 	0x00000000, 0x00000000, 0x00000000, 0x00000000,
380390bd141SQi Zhang 	0x00000000, 0x00000000, 0x00000000, 0x00000000,
381390bd141SQi Zhang 	0x00000000, 0x00000000, 0x00000000, 0x00000000,
382390bd141SQi Zhang 	0x00000000, 0x00000000, 0x00000000, 0x00000000,
383390bd141SQi Zhang 	0x00000000, 0x00000000, 0x00000000, 0x00000000,
384390bd141SQi Zhang };
385390bd141SQi Zhang 
3860577313eSQi Zhang /* Packet types for GTPC */
3870577313eSQi Zhang static const u32 ice_ptypes_gtpc[] = {
3880577313eSQi Zhang 	0x00000000, 0x00000000, 0x00000000, 0x00000000,
3890577313eSQi Zhang 	0x00000000, 0x00000000, 0x00000000, 0x00000000,
3900577313eSQi Zhang 	0x00000000, 0x00000000, 0x00000180, 0x00000000,
3910577313eSQi Zhang 	0x00000000, 0x00000000, 0x00000000, 0x00000000,
3920577313eSQi Zhang 	0x00000000, 0x00000000, 0x00000000, 0x00000000,
3930577313eSQi Zhang 	0x00000000, 0x00000000, 0x00000000, 0x00000000,
3940577313eSQi Zhang 	0x00000000, 0x00000000, 0x00000000, 0x00000000,
3950577313eSQi Zhang 	0x00000000, 0x00000000, 0x00000000, 0x00000000,
3960577313eSQi Zhang };
3970577313eSQi Zhang 
3980577313eSQi Zhang /* Packet types for GTPC with TEID */
3990577313eSQi Zhang static const u32 ice_ptypes_gtpc_tid[] = {
4000577313eSQi Zhang 	0x00000000, 0x00000000, 0x00000000, 0x00000000,
4010577313eSQi Zhang 	0x00000000, 0x00000000, 0x00000000, 0x00000000,
4020577313eSQi Zhang 	0x00000000, 0x00000000, 0x00000060, 0x00000000,
4030577313eSQi Zhang 	0x00000000, 0x00000000, 0x00000000, 0x00000000,
4040577313eSQi Zhang 	0x00000000, 0x00000000, 0x00000000, 0x00000000,
4050577313eSQi Zhang 	0x00000000, 0x00000000, 0x00000000, 0x00000000,
4060577313eSQi Zhang 	0x00000000, 0x00000000, 0x00000000, 0x00000000,
4070577313eSQi Zhang 	0x00000000, 0x00000000, 0x00000000, 0x00000000,
4080577313eSQi Zhang };
4090577313eSQi Zhang 
410cbad5db8SQi Zhang /* Packet types for GTPU */
411cbad5db8SQi Zhang static const struct ice_ptype_attributes ice_attr_gtpu_eh[] = {
412cbad5db8SQi Zhang 	{ ICE_MAC_IPV4_GTPU_IPV4_FRAG,	  ICE_PTYPE_ATTR_GTP_PDU_EH },
413cbad5db8SQi Zhang 	{ ICE_MAC_IPV4_GTPU_IPV4_PAY,	  ICE_PTYPE_ATTR_GTP_PDU_EH },
414cbad5db8SQi Zhang 	{ ICE_MAC_IPV4_GTPU_IPV4_UDP_PAY, ICE_PTYPE_ATTR_GTP_PDU_EH },
415cbad5db8SQi Zhang 	{ ICE_MAC_IPV4_GTPU_IPV4_TCP,	  ICE_PTYPE_ATTR_GTP_PDU_EH },
416cbad5db8SQi Zhang 	{ ICE_MAC_IPV4_GTPU_IPV4_ICMP,	  ICE_PTYPE_ATTR_GTP_PDU_EH },
417cbad5db8SQi Zhang 	{ ICE_MAC_IPV6_GTPU_IPV4_FRAG,	  ICE_PTYPE_ATTR_GTP_PDU_EH },
418cbad5db8SQi Zhang 	{ ICE_MAC_IPV6_GTPU_IPV4_PAY,	  ICE_PTYPE_ATTR_GTP_PDU_EH },
419cbad5db8SQi Zhang 	{ ICE_MAC_IPV6_GTPU_IPV4_UDP_PAY, ICE_PTYPE_ATTR_GTP_PDU_EH },
420cbad5db8SQi Zhang 	{ ICE_MAC_IPV6_GTPU_IPV4_TCP,	  ICE_PTYPE_ATTR_GTP_PDU_EH },
421cbad5db8SQi Zhang 	{ ICE_MAC_IPV6_GTPU_IPV4_ICMP,	  ICE_PTYPE_ATTR_GTP_PDU_EH },
422cbad5db8SQi Zhang 	{ ICE_MAC_IPV4_GTPU_IPV6_FRAG,	  ICE_PTYPE_ATTR_GTP_PDU_EH },
423cbad5db8SQi Zhang 	{ ICE_MAC_IPV4_GTPU_IPV6_PAY,	  ICE_PTYPE_ATTR_GTP_PDU_EH },
424cbad5db8SQi Zhang 	{ ICE_MAC_IPV4_GTPU_IPV6_UDP_PAY, ICE_PTYPE_ATTR_GTP_PDU_EH },
425cbad5db8SQi Zhang 	{ ICE_MAC_IPV4_GTPU_IPV6_TCP,	  ICE_PTYPE_ATTR_GTP_PDU_EH },
426cbad5db8SQi Zhang 	{ ICE_MAC_IPV4_GTPU_IPV6_ICMPV6,  ICE_PTYPE_ATTR_GTP_PDU_EH },
427cbad5db8SQi Zhang 	{ ICE_MAC_IPV6_GTPU_IPV6_FRAG,	  ICE_PTYPE_ATTR_GTP_PDU_EH },
428cbad5db8SQi Zhang 	{ ICE_MAC_IPV6_GTPU_IPV6_PAY,	  ICE_PTYPE_ATTR_GTP_PDU_EH },
429cbad5db8SQi Zhang 	{ ICE_MAC_IPV6_GTPU_IPV6_UDP_PAY, ICE_PTYPE_ATTR_GTP_PDU_EH },
430cbad5db8SQi Zhang 	{ ICE_MAC_IPV6_GTPU_IPV6_TCP,	  ICE_PTYPE_ATTR_GTP_PDU_EH },
431cbad5db8SQi Zhang 	{ ICE_MAC_IPV6_GTPU_IPV6_ICMPV6,  ICE_PTYPE_ATTR_GTP_PDU_EH },
432cbad5db8SQi Zhang };
433cbad5db8SQi Zhang 
434cbad5db8SQi Zhang static const struct ice_ptype_attributes ice_attr_gtpu_down[] = {
435cbad5db8SQi Zhang 	{ ICE_MAC_IPV4_GTPU_IPV4_FRAG,	  ICE_PTYPE_ATTR_GTP_DOWNLINK },
436cbad5db8SQi Zhang 	{ ICE_MAC_IPV4_GTPU_IPV4_PAY,	  ICE_PTYPE_ATTR_GTP_DOWNLINK },
437cbad5db8SQi Zhang 	{ ICE_MAC_IPV4_GTPU_IPV4_UDP_PAY, ICE_PTYPE_ATTR_GTP_DOWNLINK },
438cbad5db8SQi Zhang 	{ ICE_MAC_IPV4_GTPU_IPV4_TCP,	  ICE_PTYPE_ATTR_GTP_DOWNLINK },
439cbad5db8SQi Zhang 	{ ICE_MAC_IPV4_GTPU_IPV4_ICMP,	  ICE_PTYPE_ATTR_GTP_DOWNLINK },
440cbad5db8SQi Zhang 	{ ICE_MAC_IPV6_GTPU_IPV4_FRAG,	  ICE_PTYPE_ATTR_GTP_DOWNLINK },
441cbad5db8SQi Zhang 	{ ICE_MAC_IPV6_GTPU_IPV4_PAY,	  ICE_PTYPE_ATTR_GTP_DOWNLINK },
442cbad5db8SQi Zhang 	{ ICE_MAC_IPV6_GTPU_IPV4_UDP_PAY, ICE_PTYPE_ATTR_GTP_DOWNLINK },
443cbad5db8SQi Zhang 	{ ICE_MAC_IPV6_GTPU_IPV4_TCP,	  ICE_PTYPE_ATTR_GTP_DOWNLINK },
444cbad5db8SQi Zhang 	{ ICE_MAC_IPV6_GTPU_IPV4_ICMP,	  ICE_PTYPE_ATTR_GTP_DOWNLINK },
445cbad5db8SQi Zhang 	{ ICE_MAC_IPV4_GTPU_IPV6_FRAG,	  ICE_PTYPE_ATTR_GTP_DOWNLINK },
446cbad5db8SQi Zhang 	{ ICE_MAC_IPV4_GTPU_IPV6_PAY,	  ICE_PTYPE_ATTR_GTP_DOWNLINK },
447cbad5db8SQi Zhang 	{ ICE_MAC_IPV4_GTPU_IPV6_UDP_PAY, ICE_PTYPE_ATTR_GTP_DOWNLINK },
448cbad5db8SQi Zhang 	{ ICE_MAC_IPV4_GTPU_IPV6_TCP,	  ICE_PTYPE_ATTR_GTP_DOWNLINK },
449cbad5db8SQi Zhang 	{ ICE_MAC_IPV4_GTPU_IPV6_ICMPV6,  ICE_PTYPE_ATTR_GTP_DOWNLINK },
450cbad5db8SQi Zhang 	{ ICE_MAC_IPV6_GTPU_IPV6_FRAG,	  ICE_PTYPE_ATTR_GTP_DOWNLINK },
451cbad5db8SQi Zhang 	{ ICE_MAC_IPV6_GTPU_IPV6_PAY,	  ICE_PTYPE_ATTR_GTP_DOWNLINK },
452cbad5db8SQi Zhang 	{ ICE_MAC_IPV6_GTPU_IPV6_UDP_PAY, ICE_PTYPE_ATTR_GTP_DOWNLINK },
453cbad5db8SQi Zhang 	{ ICE_MAC_IPV6_GTPU_IPV6_TCP,	  ICE_PTYPE_ATTR_GTP_DOWNLINK },
454cbad5db8SQi Zhang 	{ ICE_MAC_IPV6_GTPU_IPV6_ICMPV6,  ICE_PTYPE_ATTR_GTP_DOWNLINK },
455cbad5db8SQi Zhang };
456cbad5db8SQi Zhang 
457cbad5db8SQi Zhang static const struct ice_ptype_attributes ice_attr_gtpu_up[] = {
458cbad5db8SQi Zhang 	{ ICE_MAC_IPV4_GTPU_IPV4_FRAG,	  ICE_PTYPE_ATTR_GTP_UPLINK },
459cbad5db8SQi Zhang 	{ ICE_MAC_IPV4_GTPU_IPV4_PAY,	  ICE_PTYPE_ATTR_GTP_UPLINK },
460cbad5db8SQi Zhang 	{ ICE_MAC_IPV4_GTPU_IPV4_UDP_PAY, ICE_PTYPE_ATTR_GTP_UPLINK },
461cbad5db8SQi Zhang 	{ ICE_MAC_IPV4_GTPU_IPV4_TCP,	  ICE_PTYPE_ATTR_GTP_UPLINK },
462cbad5db8SQi Zhang 	{ ICE_MAC_IPV4_GTPU_IPV4_ICMP,	  ICE_PTYPE_ATTR_GTP_UPLINK },
463cbad5db8SQi Zhang 	{ ICE_MAC_IPV6_GTPU_IPV4_FRAG,	  ICE_PTYPE_ATTR_GTP_UPLINK },
464cbad5db8SQi Zhang 	{ ICE_MAC_IPV6_GTPU_IPV4_PAY,	  ICE_PTYPE_ATTR_GTP_UPLINK },
465cbad5db8SQi Zhang 	{ ICE_MAC_IPV6_GTPU_IPV4_UDP_PAY, ICE_PTYPE_ATTR_GTP_UPLINK },
466cbad5db8SQi Zhang 	{ ICE_MAC_IPV6_GTPU_IPV4_TCP,	  ICE_PTYPE_ATTR_GTP_UPLINK },
467cbad5db8SQi Zhang 	{ ICE_MAC_IPV6_GTPU_IPV4_ICMP,	  ICE_PTYPE_ATTR_GTP_UPLINK },
468cbad5db8SQi Zhang 	{ ICE_MAC_IPV4_GTPU_IPV6_FRAG,	  ICE_PTYPE_ATTR_GTP_UPLINK },
469cbad5db8SQi Zhang 	{ ICE_MAC_IPV4_GTPU_IPV6_PAY,	  ICE_PTYPE_ATTR_GTP_UPLINK },
470cbad5db8SQi Zhang 	{ ICE_MAC_IPV4_GTPU_IPV6_UDP_PAY, ICE_PTYPE_ATTR_GTP_UPLINK },
471cbad5db8SQi Zhang 	{ ICE_MAC_IPV4_GTPU_IPV6_TCP,	  ICE_PTYPE_ATTR_GTP_UPLINK },
472cbad5db8SQi Zhang 	{ ICE_MAC_IPV4_GTPU_IPV6_ICMPV6,  ICE_PTYPE_ATTR_GTP_UPLINK },
473cbad5db8SQi Zhang 	{ ICE_MAC_IPV6_GTPU_IPV6_FRAG,	  ICE_PTYPE_ATTR_GTP_UPLINK },
474cbad5db8SQi Zhang 	{ ICE_MAC_IPV6_GTPU_IPV6_PAY,	  ICE_PTYPE_ATTR_GTP_UPLINK },
475cbad5db8SQi Zhang 	{ ICE_MAC_IPV6_GTPU_IPV6_UDP_PAY, ICE_PTYPE_ATTR_GTP_UPLINK },
476cbad5db8SQi Zhang 	{ ICE_MAC_IPV6_GTPU_IPV6_TCP,	  ICE_PTYPE_ATTR_GTP_UPLINK },
477cbad5db8SQi Zhang 	{ ICE_MAC_IPV6_GTPU_IPV6_ICMPV6,  ICE_PTYPE_ATTR_GTP_UPLINK },
478cbad5db8SQi Zhang };
479cbad5db8SQi Zhang 
4800577313eSQi Zhang static const u32 ice_ptypes_gtpu[] = {
4810577313eSQi Zhang 	0x00000000, 0x00000000, 0x00000000, 0x00000000,
4820577313eSQi Zhang 	0x00000000, 0x00000000, 0x00000000, 0x00000000,
4830577313eSQi Zhang 	0x00000000, 0x00000000, 0x7FFFFE00, 0x00000000,
4840577313eSQi Zhang 	0x00000000, 0x00000000, 0x00000000, 0x00000000,
4850577313eSQi Zhang 	0x00000000, 0x00000000, 0x00000000, 0x00000000,
4860577313eSQi Zhang 	0x00000000, 0x00000000, 0x00000000, 0x00000000,
4870577313eSQi Zhang 	0x00000000, 0x00000000, 0x00000000, 0x00000000,
4880577313eSQi Zhang 	0x00000000, 0x00000000, 0x00000000, 0x00000000,
4890577313eSQi Zhang };
4900577313eSQi Zhang 
4910577313eSQi Zhang /* Packet types for PPPoE */
4920577313eSQi Zhang static const u32 ice_ptypes_pppoe[] = {
4930577313eSQi Zhang 	0x00000000, 0x00000000, 0x00000000, 0x00000000,
4940577313eSQi Zhang 	0x00000000, 0x00000000, 0x00000000, 0x00000000,
4950577313eSQi Zhang 	0x00000000, 0x03ffe000, 0x00000000, 0x00000000,
4960577313eSQi Zhang 	0x00000000, 0x00000000, 0x00000000, 0x00000000,
4970577313eSQi Zhang 	0x00000000, 0x00000000, 0x00000000, 0x00000000,
4980577313eSQi Zhang 	0x00000000, 0x00000000, 0x00000000, 0x00000000,
4990577313eSQi Zhang 	0x00000000, 0x00000000, 0x00000000, 0x00000000,
5000577313eSQi Zhang 	0x00000000, 0x00000000, 0x00000000, 0x00000000,
5010577313eSQi Zhang };
5020577313eSQi Zhang 
5030577313eSQi Zhang /* Packet types for packets with PFCP NODE header */
5040577313eSQi Zhang static const u32 ice_ptypes_pfcp_node[] = {
5050577313eSQi Zhang 	0x00000000, 0x00000000, 0x00000000, 0x00000000,
5060577313eSQi Zhang 	0x00000000, 0x00000000, 0x00000000, 0x00000000,
5070577313eSQi Zhang 	0x00000000, 0x00000000, 0x80000000, 0x00000002,
5080577313eSQi Zhang 	0x00000000, 0x00000000, 0x00000000, 0x00000000,
5090577313eSQi Zhang 	0x00000000, 0x00000000, 0x00000000, 0x00000000,
5100577313eSQi Zhang 	0x00000000, 0x00000000, 0x00000000, 0x00000000,
5110577313eSQi Zhang 	0x00000000, 0x00000000, 0x00000000, 0x00000000,
5120577313eSQi Zhang 	0x00000000, 0x00000000, 0x00000000, 0x00000000,
5130577313eSQi Zhang };
5140577313eSQi Zhang 
5150577313eSQi Zhang /* Packet types for packets with PFCP SESSION header */
5160577313eSQi Zhang static const u32 ice_ptypes_pfcp_session[] = {
5170577313eSQi Zhang 	0x00000000, 0x00000000, 0x00000000, 0x00000000,
5180577313eSQi Zhang 	0x00000000, 0x00000000, 0x00000000, 0x00000000,
5190577313eSQi Zhang 	0x00000000, 0x00000000, 0x00000000, 0x00000005,
5200577313eSQi Zhang 	0x00000000, 0x00000000, 0x00000000, 0x00000000,
5210577313eSQi Zhang 	0x00000000, 0x00000000, 0x00000000, 0x00000000,
5220577313eSQi Zhang 	0x00000000, 0x00000000, 0x00000000, 0x00000000,
5230577313eSQi Zhang 	0x00000000, 0x00000000, 0x00000000, 0x00000000,
5240577313eSQi Zhang 	0x00000000, 0x00000000, 0x00000000, 0x00000000,
5250577313eSQi Zhang };
5260577313eSQi Zhang 
5270577313eSQi Zhang /* Packet types for L2TPv3 */
5280577313eSQi Zhang static const u32 ice_ptypes_l2tpv3[] = {
5290577313eSQi Zhang 	0x00000000, 0x00000000, 0x00000000, 0x00000000,
5300577313eSQi Zhang 	0x00000000, 0x00000000, 0x00000000, 0x00000000,
5310577313eSQi Zhang 	0x00000000, 0x00000000, 0x00000000, 0x00000300,
5320577313eSQi Zhang 	0x00000000, 0x00000000, 0x00000000, 0x00000000,
5330577313eSQi Zhang 	0x00000000, 0x00000000, 0x00000000, 0x00000000,
5340577313eSQi Zhang 	0x00000000, 0x00000000, 0x00000000, 0x00000000,
5350577313eSQi Zhang 	0x00000000, 0x00000000, 0x00000000, 0x00000000,
5360577313eSQi Zhang 	0x00000000, 0x00000000, 0x00000000, 0x00000000,
5370577313eSQi Zhang };
5380577313eSQi Zhang 
5390577313eSQi Zhang /* Packet types for ESP */
5400577313eSQi Zhang static const u32 ice_ptypes_esp[] = {
5410577313eSQi Zhang 	0x00000000, 0x00000000, 0x00000000, 0x00000000,
5420577313eSQi Zhang 	0x00000000, 0x00000003, 0x00000000, 0x00000000,
5430577313eSQi Zhang 	0x00000000, 0x00000000, 0x00000000, 0x00000000,
5440577313eSQi Zhang 	0x00000000, 0x00000000, 0x00000000, 0x00000000,
5450577313eSQi Zhang 	0x00000000, 0x00000000, 0x00000000, 0x00000000,
5460577313eSQi Zhang 	0x00000000, 0x00000000, 0x00000000, 0x00000000,
5470577313eSQi Zhang 	0x00000000, 0x00000000, 0x00000000, 0x00000000,
5480577313eSQi Zhang 	0x00000000, 0x00000000, 0x00000000, 0x00000000,
5490577313eSQi Zhang };
5500577313eSQi Zhang 
5510577313eSQi Zhang /* Packet types for AH */
5520577313eSQi Zhang static const u32 ice_ptypes_ah[] = {
5530577313eSQi Zhang 	0x00000000, 0x00000000, 0x00000000, 0x00000000,
5540577313eSQi Zhang 	0x00000000, 0x0000000C, 0x00000000, 0x00000000,
5550577313eSQi Zhang 	0x00000000, 0x00000000, 0x00000000, 0x00000000,
5560577313eSQi Zhang 	0x00000000, 0x00000000, 0x00000000, 0x00000000,
5570577313eSQi Zhang 	0x00000000, 0x00000000, 0x00000000, 0x00000000,
5580577313eSQi Zhang 	0x00000000, 0x00000000, 0x00000000, 0x00000000,
5590577313eSQi Zhang 	0x00000000, 0x00000000, 0x00000000, 0x00000000,
5600577313eSQi Zhang 	0x00000000, 0x00000000, 0x00000000, 0x00000000,
5610577313eSQi Zhang };
5620577313eSQi Zhang 
5630577313eSQi Zhang /* Packet types for packets with NAT_T ESP header */
5640577313eSQi Zhang static const u32 ice_ptypes_nat_t_esp[] = {
5650577313eSQi Zhang 	0x00000000, 0x00000000, 0x00000000, 0x00000000,
5660577313eSQi Zhang 	0x00000000, 0x00000030, 0x00000000, 0x00000000,
5670577313eSQi Zhang 	0x00000000, 0x00000000, 0x00000000, 0x00000000,
5680577313eSQi Zhang 	0x00000000, 0x00000000, 0x00000000, 0x00000000,
5690577313eSQi Zhang 	0x00000000, 0x00000000, 0x00000000, 0x00000000,
5700577313eSQi Zhang 	0x00000000, 0x00000000, 0x00000000, 0x00000000,
5710577313eSQi Zhang 	0x00000000, 0x00000000, 0x00000000, 0x00000000,
5720577313eSQi Zhang 	0x00000000, 0x00000000, 0x00000000, 0x00000000,
5730577313eSQi Zhang };
5740577313eSQi Zhang 
57521606584SQi Zhang static const u32 ice_ptypes_mac_non_ip_ofos[] = {
57621606584SQi Zhang 	0x00000846, 0x00000000, 0x00000000, 0x00000000,
57721606584SQi Zhang 	0x00000000, 0x00000000, 0x00000000, 0x00000000,
57821606584SQi Zhang 	0x00400000, 0x03FFF000, 0x00000000, 0x00000000,
57921606584SQi Zhang 	0x00000000, 0x00000000, 0x00000000, 0x00000000,
58021606584SQi Zhang 	0x00000000, 0x00000000, 0x00000000, 0x00000000,
58121606584SQi Zhang 	0x00000000, 0x00000000, 0x00000000, 0x00000000,
58221606584SQi Zhang 	0x00000000, 0x00000000, 0x00000000, 0x00000000,
58321606584SQi Zhang 	0x00000000, 0x00000000, 0x00000000, 0x00000000,
58421606584SQi Zhang };
58521606584SQi Zhang 
58631ad4e4eSTony Nguyen /* Manage parameters and info. used during the creation of a flow profile */
58731ad4e4eSTony Nguyen struct ice_flow_prof_params {
58831ad4e4eSTony Nguyen 	enum ice_block blk;
58931ad4e4eSTony Nguyen 	u16 entry_length; /* # of bytes formatted entry will require */
59031ad4e4eSTony Nguyen 	u8 es_cnt;
59131ad4e4eSTony Nguyen 	struct ice_flow_prof *prof;
59231ad4e4eSTony Nguyen 
59331ad4e4eSTony Nguyen 	/* For ACL, the es[0] will have the data of ICE_RX_MDID_PKT_FLAGS_15_0
59431ad4e4eSTony Nguyen 	 * This will give us the direction flags.
59531ad4e4eSTony Nguyen 	 */
59631ad4e4eSTony Nguyen 	struct ice_fv_word es[ICE_MAX_FV_WORDS];
597cbad5db8SQi Zhang 	/* attributes can be used to add attributes to a particular PTYPE */
598cbad5db8SQi Zhang 	const struct ice_ptype_attributes *attr;
599cbad5db8SQi Zhang 	u16 attr_cnt;
600b199dddbSQi Zhang 
601b199dddbSQi Zhang 	u16 mask[ICE_MAX_FV_WORDS];
60231ad4e4eSTony Nguyen 	DECLARE_BITMAP(ptypes, ICE_FLOW_PTYPE_MAX);
60331ad4e4eSTony Nguyen };
60431ad4e4eSTony Nguyen 
6050577313eSQi Zhang #define ICE_FLOW_RSS_HDRS_INNER_MASK \
6060577313eSQi Zhang 	(ICE_FLOW_SEG_HDR_PPPOE | ICE_FLOW_SEG_HDR_GTPC | \
6070577313eSQi Zhang 	ICE_FLOW_SEG_HDR_GTPC_TEID | ICE_FLOW_SEG_HDR_GTPU | \
6080577313eSQi Zhang 	ICE_FLOW_SEG_HDR_PFCP_SESSION | ICE_FLOW_SEG_HDR_L2TPV3 | \
6090577313eSQi Zhang 	ICE_FLOW_SEG_HDR_ESP | ICE_FLOW_SEG_HDR_AH | \
6100577313eSQi Zhang 	ICE_FLOW_SEG_HDR_NAT_T_ESP)
6110577313eSQi Zhang 
6120577313eSQi Zhang #define ICE_FLOW_SEG_HDRS_L2_MASK	\
6130577313eSQi Zhang 	(ICE_FLOW_SEG_HDR_ETH | ICE_FLOW_SEG_HDR_VLAN)
61431ad4e4eSTony Nguyen #define ICE_FLOW_SEG_HDRS_L3_MASK	\
615390bd141SQi Zhang 	(ICE_FLOW_SEG_HDR_IPV4 | ICE_FLOW_SEG_HDR_IPV6 | ICE_FLOW_SEG_HDR_ARP)
61631ad4e4eSTony Nguyen #define ICE_FLOW_SEG_HDRS_L4_MASK	\
617390bd141SQi Zhang 	(ICE_FLOW_SEG_HDR_ICMP | ICE_FLOW_SEG_HDR_TCP | ICE_FLOW_SEG_HDR_UDP | \
618390bd141SQi Zhang 	 ICE_FLOW_SEG_HDR_SCTP)
6197012dfd1SQi Zhang /* mask for L4 protocols that are NOT part of IPv4/6 OTHER PTYPE groups */
6207012dfd1SQi Zhang #define ICE_FLOW_SEG_HDRS_L4_MASK_NO_OTHER	\
6217012dfd1SQi Zhang 	(ICE_FLOW_SEG_HDR_TCP | ICE_FLOW_SEG_HDR_UDP | ICE_FLOW_SEG_HDR_SCTP)
62231ad4e4eSTony Nguyen 
62331ad4e4eSTony Nguyen /**
62431ad4e4eSTony Nguyen  * ice_flow_val_hdrs - validates packet segments for valid protocol headers
62531ad4e4eSTony Nguyen  * @segs: array of one or more packet segments that describe the flow
62631ad4e4eSTony Nguyen  * @segs_cnt: number of packet segments provided
62731ad4e4eSTony Nguyen  */
62831ad4e4eSTony Nguyen static enum ice_status
62931ad4e4eSTony Nguyen ice_flow_val_hdrs(struct ice_flow_seg_info *segs, u8 segs_cnt)
63031ad4e4eSTony Nguyen {
63131ad4e4eSTony Nguyen 	u8 i;
63231ad4e4eSTony Nguyen 
63331ad4e4eSTony Nguyen 	for (i = 0; i < segs_cnt; i++) {
63431ad4e4eSTony Nguyen 		/* Multiple L3 headers */
63531ad4e4eSTony Nguyen 		if (segs[i].hdrs & ICE_FLOW_SEG_HDRS_L3_MASK &&
63631ad4e4eSTony Nguyen 		    !is_power_of_2(segs[i].hdrs & ICE_FLOW_SEG_HDRS_L3_MASK))
63731ad4e4eSTony Nguyen 			return ICE_ERR_PARAM;
63831ad4e4eSTony Nguyen 
63931ad4e4eSTony Nguyen 		/* Multiple L4 headers */
64031ad4e4eSTony Nguyen 		if (segs[i].hdrs & ICE_FLOW_SEG_HDRS_L4_MASK &&
64131ad4e4eSTony Nguyen 		    !is_power_of_2(segs[i].hdrs & ICE_FLOW_SEG_HDRS_L4_MASK))
64231ad4e4eSTony Nguyen 			return ICE_ERR_PARAM;
64331ad4e4eSTony Nguyen 	}
64431ad4e4eSTony Nguyen 
64531ad4e4eSTony Nguyen 	return 0;
64631ad4e4eSTony Nguyen }
64731ad4e4eSTony Nguyen 
6482c57ffcbSHenry Tieman /* Sizes of fixed known protocol headers without header options */
6492c57ffcbSHenry Tieman #define ICE_FLOW_PROT_HDR_SZ_MAC	14
650390bd141SQi Zhang #define ICE_FLOW_PROT_HDR_SZ_MAC_VLAN	(ICE_FLOW_PROT_HDR_SZ_MAC + 2)
6512c57ffcbSHenry Tieman #define ICE_FLOW_PROT_HDR_SZ_IPV4	20
6522c57ffcbSHenry Tieman #define ICE_FLOW_PROT_HDR_SZ_IPV6	40
653390bd141SQi Zhang #define ICE_FLOW_PROT_HDR_SZ_ARP	28
654390bd141SQi Zhang #define ICE_FLOW_PROT_HDR_SZ_ICMP	8
6552c57ffcbSHenry Tieman #define ICE_FLOW_PROT_HDR_SZ_TCP	20
6562c57ffcbSHenry Tieman #define ICE_FLOW_PROT_HDR_SZ_UDP	8
6572c57ffcbSHenry Tieman #define ICE_FLOW_PROT_HDR_SZ_SCTP	12
6582c57ffcbSHenry Tieman 
6592c57ffcbSHenry Tieman /**
6602c57ffcbSHenry Tieman  * ice_flow_calc_seg_sz - calculates size of a packet segment based on headers
6612c57ffcbSHenry Tieman  * @params: information about the flow to be processed
6622c57ffcbSHenry Tieman  * @seg: index of packet segment whose header size is to be determined
6632c57ffcbSHenry Tieman  */
6642c57ffcbSHenry Tieman static u16 ice_flow_calc_seg_sz(struct ice_flow_prof_params *params, u8 seg)
6652c57ffcbSHenry Tieman {
666390bd141SQi Zhang 	u16 sz;
667390bd141SQi Zhang 
668390bd141SQi Zhang 	/* L2 headers */
669390bd141SQi Zhang 	sz = (params->prof->segs[seg].hdrs & ICE_FLOW_SEG_HDR_VLAN) ?
670390bd141SQi Zhang 		ICE_FLOW_PROT_HDR_SZ_MAC_VLAN : ICE_FLOW_PROT_HDR_SZ_MAC;
6712c57ffcbSHenry Tieman 
6722c57ffcbSHenry Tieman 	/* L3 headers */
6732c57ffcbSHenry Tieman 	if (params->prof->segs[seg].hdrs & ICE_FLOW_SEG_HDR_IPV4)
6742c57ffcbSHenry Tieman 		sz += ICE_FLOW_PROT_HDR_SZ_IPV4;
6752c57ffcbSHenry Tieman 	else if (params->prof->segs[seg].hdrs & ICE_FLOW_SEG_HDR_IPV6)
6762c57ffcbSHenry Tieman 		sz += ICE_FLOW_PROT_HDR_SZ_IPV6;
677390bd141SQi Zhang 	else if (params->prof->segs[seg].hdrs & ICE_FLOW_SEG_HDR_ARP)
678390bd141SQi Zhang 		sz += ICE_FLOW_PROT_HDR_SZ_ARP;
679390bd141SQi Zhang 	else if (params->prof->segs[seg].hdrs & ICE_FLOW_SEG_HDRS_L4_MASK)
680390bd141SQi Zhang 		/* An L3 header is required if L4 is specified */
681390bd141SQi Zhang 		return 0;
6822c57ffcbSHenry Tieman 
6832c57ffcbSHenry Tieman 	/* L4 headers */
684390bd141SQi Zhang 	if (params->prof->segs[seg].hdrs & ICE_FLOW_SEG_HDR_ICMP)
685390bd141SQi Zhang 		sz += ICE_FLOW_PROT_HDR_SZ_ICMP;
686390bd141SQi Zhang 	else if (params->prof->segs[seg].hdrs & ICE_FLOW_SEG_HDR_TCP)
6872c57ffcbSHenry Tieman 		sz += ICE_FLOW_PROT_HDR_SZ_TCP;
6882c57ffcbSHenry Tieman 	else if (params->prof->segs[seg].hdrs & ICE_FLOW_SEG_HDR_UDP)
6892c57ffcbSHenry Tieman 		sz += ICE_FLOW_PROT_HDR_SZ_UDP;
6902c57ffcbSHenry Tieman 	else if (params->prof->segs[seg].hdrs & ICE_FLOW_SEG_HDR_SCTP)
6912c57ffcbSHenry Tieman 		sz += ICE_FLOW_PROT_HDR_SZ_SCTP;
6922c57ffcbSHenry Tieman 
6932c57ffcbSHenry Tieman 	return sz;
6942c57ffcbSHenry Tieman }
6952c57ffcbSHenry Tieman 
69631ad4e4eSTony Nguyen /**
69731ad4e4eSTony Nguyen  * ice_flow_proc_seg_hdrs - process protocol headers present in pkt segments
69831ad4e4eSTony Nguyen  * @params: information about the flow to be processed
69931ad4e4eSTony Nguyen  *
70031ad4e4eSTony Nguyen  * This function identifies the packet types associated with the protocol
70131ad4e4eSTony Nguyen  * headers being present in packet segments of the specified flow profile.
70231ad4e4eSTony Nguyen  */
70331ad4e4eSTony Nguyen static enum ice_status
70431ad4e4eSTony Nguyen ice_flow_proc_seg_hdrs(struct ice_flow_prof_params *params)
70531ad4e4eSTony Nguyen {
70631ad4e4eSTony Nguyen 	struct ice_flow_prof *prof;
70731ad4e4eSTony Nguyen 	u8 i;
70831ad4e4eSTony Nguyen 
70931ad4e4eSTony Nguyen 	memset(params->ptypes, 0xff, sizeof(params->ptypes));
71031ad4e4eSTony Nguyen 
71131ad4e4eSTony Nguyen 	prof = params->prof;
71231ad4e4eSTony Nguyen 
71331ad4e4eSTony Nguyen 	for (i = 0; i < params->prof->segs_cnt; i++) {
71431ad4e4eSTony Nguyen 		const unsigned long *src;
71531ad4e4eSTony Nguyen 		u32 hdrs;
71631ad4e4eSTony Nguyen 
71731ad4e4eSTony Nguyen 		hdrs = prof->segs[i].hdrs;
71831ad4e4eSTony Nguyen 
719390bd141SQi Zhang 		if (hdrs & ICE_FLOW_SEG_HDR_ETH) {
720390bd141SQi Zhang 			src = !i ? (const unsigned long *)ice_ptypes_mac_ofos :
721390bd141SQi Zhang 				(const unsigned long *)ice_ptypes_mac_il;
722390bd141SQi Zhang 			bitmap_and(params->ptypes, params->ptypes, src,
723390bd141SQi Zhang 				   ICE_FLOW_PTYPE_MAX);
724390bd141SQi Zhang 		}
725390bd141SQi Zhang 
726390bd141SQi Zhang 		if (i && hdrs & ICE_FLOW_SEG_HDR_VLAN) {
727390bd141SQi Zhang 			src = (const unsigned long *)ice_ptypes_macvlan_il;
728390bd141SQi Zhang 			bitmap_and(params->ptypes, params->ptypes, src,
729390bd141SQi Zhang 				   ICE_FLOW_PTYPE_MAX);
730390bd141SQi Zhang 		}
731390bd141SQi Zhang 
732390bd141SQi Zhang 		if (!i && hdrs & ICE_FLOW_SEG_HDR_ARP) {
733390bd141SQi Zhang 			bitmap_and(params->ptypes, params->ptypes,
734390bd141SQi Zhang 				   (const unsigned long *)ice_ptypes_arp_of,
735390bd141SQi Zhang 				   ICE_FLOW_PTYPE_MAX);
736390bd141SQi Zhang 		}
7377012dfd1SQi Zhang 
738051d2b5cSDan Nowlin 		if ((hdrs & ICE_FLOW_SEG_HDR_IPV4) &&
7397012dfd1SQi Zhang 		    (hdrs & ICE_FLOW_SEG_HDR_IPV_OTHER)) {
7407012dfd1SQi Zhang 			src = i ? (const unsigned long *)ice_ptypes_ipv4_il :
7417012dfd1SQi Zhang 				(const unsigned long *)ice_ptypes_ipv4_ofos_all;
7427012dfd1SQi Zhang 			bitmap_and(params->ptypes, params->ptypes, src,
7437012dfd1SQi Zhang 				   ICE_FLOW_PTYPE_MAX);
7447012dfd1SQi Zhang 		} else if ((hdrs & ICE_FLOW_SEG_HDR_IPV6) &&
7457012dfd1SQi Zhang 			   (hdrs & ICE_FLOW_SEG_HDR_IPV_OTHER)) {
7467012dfd1SQi Zhang 			src = i ? (const unsigned long *)ice_ptypes_ipv6_il :
7477012dfd1SQi Zhang 				(const unsigned long *)ice_ptypes_ipv6_ofos_all;
7487012dfd1SQi Zhang 			bitmap_and(params->ptypes, params->ptypes, src,
7497012dfd1SQi Zhang 				   ICE_FLOW_PTYPE_MAX);
7507012dfd1SQi Zhang 		} else if ((hdrs & ICE_FLOW_SEG_HDR_IPV4) &&
7517012dfd1SQi Zhang 			   !(hdrs & ICE_FLOW_SEG_HDRS_L4_MASK_NO_OTHER)) {
752*94a93698SQi Zhang 			src = !i ? (const unsigned long *)ice_ptypes_ipv4_ofos_no_l4 :
753*94a93698SQi Zhang 				(const unsigned long *)ice_ptypes_ipv4_il_no_l4;
754051d2b5cSDan Nowlin 			bitmap_and(params->ptypes, params->ptypes, src,
755051d2b5cSDan Nowlin 				   ICE_FLOW_PTYPE_MAX);
756051d2b5cSDan Nowlin 		} else if (hdrs & ICE_FLOW_SEG_HDR_IPV4) {
75731ad4e4eSTony Nguyen 			src = !i ? (const unsigned long *)ice_ptypes_ipv4_ofos :
75831ad4e4eSTony Nguyen 				(const unsigned long *)ice_ptypes_ipv4_il;
75931ad4e4eSTony Nguyen 			bitmap_and(params->ptypes, params->ptypes, src,
76031ad4e4eSTony Nguyen 				   ICE_FLOW_PTYPE_MAX);
761051d2b5cSDan Nowlin 		} else if ((hdrs & ICE_FLOW_SEG_HDR_IPV6) &&
7627012dfd1SQi Zhang 			   !(hdrs & ICE_FLOW_SEG_HDRS_L4_MASK_NO_OTHER)) {
763*94a93698SQi Zhang 			src = !i ? (const unsigned long *)ice_ptypes_ipv6_ofos_no_l4 :
764*94a93698SQi Zhang 				(const unsigned long *)ice_ptypes_ipv6_il_no_l4;
765051d2b5cSDan Nowlin 			bitmap_and(params->ptypes, params->ptypes, src,
766051d2b5cSDan Nowlin 				   ICE_FLOW_PTYPE_MAX);
76731ad4e4eSTony Nguyen 		} else if (hdrs & ICE_FLOW_SEG_HDR_IPV6) {
76831ad4e4eSTony Nguyen 			src = !i ? (const unsigned long *)ice_ptypes_ipv6_ofos :
76931ad4e4eSTony Nguyen 				(const unsigned long *)ice_ptypes_ipv6_il;
77031ad4e4eSTony Nguyen 			bitmap_and(params->ptypes, params->ptypes, src,
77131ad4e4eSTony Nguyen 				   ICE_FLOW_PTYPE_MAX);
77231ad4e4eSTony Nguyen 		}
77331ad4e4eSTony Nguyen 
77421606584SQi Zhang 		if (hdrs & ICE_FLOW_SEG_HDR_ETH_NON_IP) {
77521606584SQi Zhang 			src = (const unsigned long *)ice_ptypes_mac_non_ip_ofos;
77621606584SQi Zhang 			bitmap_and(params->ptypes, params->ptypes, src,
77721606584SQi Zhang 				   ICE_FLOW_PTYPE_MAX);
77821606584SQi Zhang 		} else if (hdrs & ICE_FLOW_SEG_HDR_PPPOE) {
7790577313eSQi Zhang 			src = (const unsigned long *)ice_ptypes_pppoe;
7800577313eSQi Zhang 			bitmap_and(params->ptypes, params->ptypes, src,
7810577313eSQi Zhang 				   ICE_FLOW_PTYPE_MAX);
7820577313eSQi Zhang 		} else {
7830577313eSQi Zhang 			src = (const unsigned long *)ice_ptypes_pppoe;
7840577313eSQi Zhang 			bitmap_andnot(params->ptypes, params->ptypes, src,
7850577313eSQi Zhang 				      ICE_FLOW_PTYPE_MAX);
7860577313eSQi Zhang 		}
7870577313eSQi Zhang 
78831ad4e4eSTony Nguyen 		if (hdrs & ICE_FLOW_SEG_HDR_UDP) {
78931ad4e4eSTony Nguyen 			src = (const unsigned long *)ice_ptypes_udp_il;
79031ad4e4eSTony Nguyen 			bitmap_and(params->ptypes, params->ptypes, src,
79131ad4e4eSTony Nguyen 				   ICE_FLOW_PTYPE_MAX);
79231ad4e4eSTony Nguyen 		} else if (hdrs & ICE_FLOW_SEG_HDR_TCP) {
79331ad4e4eSTony Nguyen 			bitmap_and(params->ptypes, params->ptypes,
79431ad4e4eSTony Nguyen 				   (const unsigned long *)ice_ptypes_tcp_il,
79531ad4e4eSTony Nguyen 				   ICE_FLOW_PTYPE_MAX);
79631ad4e4eSTony Nguyen 		} else if (hdrs & ICE_FLOW_SEG_HDR_SCTP) {
79731ad4e4eSTony Nguyen 			src = (const unsigned long *)ice_ptypes_sctp_il;
79831ad4e4eSTony Nguyen 			bitmap_and(params->ptypes, params->ptypes, src,
79931ad4e4eSTony Nguyen 				   ICE_FLOW_PTYPE_MAX);
800390bd141SQi Zhang 		}
801390bd141SQi Zhang 
802390bd141SQi Zhang 		if (hdrs & ICE_FLOW_SEG_HDR_ICMP) {
803390bd141SQi Zhang 			src = !i ? (const unsigned long *)ice_ptypes_icmp_of :
804390bd141SQi Zhang 				(const unsigned long *)ice_ptypes_icmp_il;
805390bd141SQi Zhang 			bitmap_and(params->ptypes, params->ptypes, src,
806390bd141SQi Zhang 				   ICE_FLOW_PTYPE_MAX);
807a4e82a81STony Nguyen 		} else if (hdrs & ICE_FLOW_SEG_HDR_GRE) {
808a4e82a81STony Nguyen 			if (!i) {
809a4e82a81STony Nguyen 				src = (const unsigned long *)ice_ptypes_gre_of;
810a4e82a81STony Nguyen 				bitmap_and(params->ptypes, params->ptypes,
811a4e82a81STony Nguyen 					   src, ICE_FLOW_PTYPE_MAX);
812a4e82a81STony Nguyen 			}
8130577313eSQi Zhang 		} else if (hdrs & ICE_FLOW_SEG_HDR_GTPC) {
8140577313eSQi Zhang 			src = (const unsigned long *)ice_ptypes_gtpc;
8150577313eSQi Zhang 			bitmap_and(params->ptypes, params->ptypes, src,
8160577313eSQi Zhang 				   ICE_FLOW_PTYPE_MAX);
8170577313eSQi Zhang 		} else if (hdrs & ICE_FLOW_SEG_HDR_GTPC_TEID) {
8180577313eSQi Zhang 			src = (const unsigned long *)ice_ptypes_gtpc_tid;
8190577313eSQi Zhang 			bitmap_and(params->ptypes, params->ptypes, src,
8200577313eSQi Zhang 				   ICE_FLOW_PTYPE_MAX);
8210577313eSQi Zhang 		} else if (hdrs & ICE_FLOW_SEG_HDR_GTPU_DWN) {
8220577313eSQi Zhang 			src = (const unsigned long *)ice_ptypes_gtpu;
8230577313eSQi Zhang 			bitmap_and(params->ptypes, params->ptypes, src,
8240577313eSQi Zhang 				   ICE_FLOW_PTYPE_MAX);
825cbad5db8SQi Zhang 
826cbad5db8SQi Zhang 			/* Attributes for GTP packet with downlink */
827cbad5db8SQi Zhang 			params->attr = ice_attr_gtpu_down;
828cbad5db8SQi Zhang 			params->attr_cnt = ARRAY_SIZE(ice_attr_gtpu_down);
8290577313eSQi Zhang 		} else if (hdrs & ICE_FLOW_SEG_HDR_GTPU_UP) {
8300577313eSQi Zhang 			src = (const unsigned long *)ice_ptypes_gtpu;
8310577313eSQi Zhang 			bitmap_and(params->ptypes, params->ptypes, src,
8320577313eSQi Zhang 				   ICE_FLOW_PTYPE_MAX);
833cbad5db8SQi Zhang 
834cbad5db8SQi Zhang 			/* Attributes for GTP packet with uplink */
835cbad5db8SQi Zhang 			params->attr = ice_attr_gtpu_up;
836cbad5db8SQi Zhang 			params->attr_cnt = ARRAY_SIZE(ice_attr_gtpu_up);
8370577313eSQi Zhang 		} else if (hdrs & ICE_FLOW_SEG_HDR_GTPU_EH) {
8380577313eSQi Zhang 			src = (const unsigned long *)ice_ptypes_gtpu;
8390577313eSQi Zhang 			bitmap_and(params->ptypes, params->ptypes, src,
8400577313eSQi Zhang 				   ICE_FLOW_PTYPE_MAX);
841cbad5db8SQi Zhang 
842cbad5db8SQi Zhang 			/* Attributes for GTP packet with Extension Header */
843cbad5db8SQi Zhang 			params->attr = ice_attr_gtpu_eh;
844cbad5db8SQi Zhang 			params->attr_cnt = ARRAY_SIZE(ice_attr_gtpu_eh);
8450577313eSQi Zhang 		} else if (hdrs & ICE_FLOW_SEG_HDR_GTPU_IP) {
8460577313eSQi Zhang 			src = (const unsigned long *)ice_ptypes_gtpu;
8470577313eSQi Zhang 			bitmap_and(params->ptypes, params->ptypes, src,
8480577313eSQi Zhang 				   ICE_FLOW_PTYPE_MAX);
8490577313eSQi Zhang 		} else if (hdrs & ICE_FLOW_SEG_HDR_L2TPV3) {
8500577313eSQi Zhang 			src = (const unsigned long *)ice_ptypes_l2tpv3;
8510577313eSQi Zhang 			bitmap_and(params->ptypes, params->ptypes, src,
8520577313eSQi Zhang 				   ICE_FLOW_PTYPE_MAX);
8530577313eSQi Zhang 		} else if (hdrs & ICE_FLOW_SEG_HDR_ESP) {
8540577313eSQi Zhang 			src = (const unsigned long *)ice_ptypes_esp;
8550577313eSQi Zhang 			bitmap_and(params->ptypes, params->ptypes, src,
8560577313eSQi Zhang 				   ICE_FLOW_PTYPE_MAX);
8570577313eSQi Zhang 		} else if (hdrs & ICE_FLOW_SEG_HDR_AH) {
8580577313eSQi Zhang 			src = (const unsigned long *)ice_ptypes_ah;
8590577313eSQi Zhang 			bitmap_and(params->ptypes, params->ptypes, src,
8600577313eSQi Zhang 				   ICE_FLOW_PTYPE_MAX);
8610577313eSQi Zhang 		} else if (hdrs & ICE_FLOW_SEG_HDR_NAT_T_ESP) {
8620577313eSQi Zhang 			src = (const unsigned long *)ice_ptypes_nat_t_esp;
8630577313eSQi Zhang 			bitmap_and(params->ptypes, params->ptypes, src,
8640577313eSQi Zhang 				   ICE_FLOW_PTYPE_MAX);
8650577313eSQi Zhang 		}
8660577313eSQi Zhang 
8670577313eSQi Zhang 		if (hdrs & ICE_FLOW_SEG_HDR_PFCP) {
8680577313eSQi Zhang 			if (hdrs & ICE_FLOW_SEG_HDR_PFCP_NODE)
8690577313eSQi Zhang 				src = (const unsigned long *)ice_ptypes_pfcp_node;
8700577313eSQi Zhang 			else
8710577313eSQi Zhang 				src = (const unsigned long *)ice_ptypes_pfcp_session;
8720577313eSQi Zhang 
8730577313eSQi Zhang 			bitmap_and(params->ptypes, params->ptypes, src,
8740577313eSQi Zhang 				   ICE_FLOW_PTYPE_MAX);
8750577313eSQi Zhang 		} else {
8760577313eSQi Zhang 			src = (const unsigned long *)ice_ptypes_pfcp_node;
8770577313eSQi Zhang 			bitmap_andnot(params->ptypes, params->ptypes, src,
8780577313eSQi Zhang 				      ICE_FLOW_PTYPE_MAX);
8790577313eSQi Zhang 
8800577313eSQi Zhang 			src = (const unsigned long *)ice_ptypes_pfcp_session;
8810577313eSQi Zhang 			bitmap_andnot(params->ptypes, params->ptypes, src,
8820577313eSQi Zhang 				      ICE_FLOW_PTYPE_MAX);
88331ad4e4eSTony Nguyen 		}
88431ad4e4eSTony Nguyen 	}
88531ad4e4eSTony Nguyen 
88631ad4e4eSTony Nguyen 	return 0;
88731ad4e4eSTony Nguyen }
88831ad4e4eSTony Nguyen 
88931ad4e4eSTony Nguyen /**
89031ad4e4eSTony Nguyen  * ice_flow_xtract_fld - Create an extraction sequence entry for the given field
89131ad4e4eSTony Nguyen  * @hw: pointer to the HW struct
89231ad4e4eSTony Nguyen  * @params: information about the flow to be processed
89331ad4e4eSTony Nguyen  * @seg: packet segment index of the field to be extracted
89431ad4e4eSTony Nguyen  * @fld: ID of field to be extracted
895b199dddbSQi Zhang  * @match: bit field of all fields
89631ad4e4eSTony Nguyen  *
89731ad4e4eSTony Nguyen  * This function determines the protocol ID, offset, and size of the given
89831ad4e4eSTony Nguyen  * field. It then allocates one or more extraction sequence entries for the
89931ad4e4eSTony Nguyen  * given field, and fill the entries with protocol ID and offset information.
90031ad4e4eSTony Nguyen  */
90131ad4e4eSTony Nguyen static enum ice_status
90231ad4e4eSTony Nguyen ice_flow_xtract_fld(struct ice_hw *hw, struct ice_flow_prof_params *params,
903b199dddbSQi Zhang 		    u8 seg, enum ice_flow_field fld, u64 match)
90431ad4e4eSTony Nguyen {
905b199dddbSQi Zhang 	enum ice_flow_field sib = ICE_FLOW_FIELD_IDX_MAX;
90631ad4e4eSTony Nguyen 	enum ice_prot_id prot_id = ICE_PROT_ID_INVAL;
90731ad4e4eSTony Nguyen 	u8 fv_words = hw->blk[params->blk].es.fvw;
90831ad4e4eSTony Nguyen 	struct ice_flow_fld_info *flds;
90931ad4e4eSTony Nguyen 	u16 cnt, ese_bits, i;
910b199dddbSQi Zhang 	u16 sib_mask = 0;
911b199dddbSQi Zhang 	u16 mask;
91231ad4e4eSTony Nguyen 	u16 off;
91331ad4e4eSTony Nguyen 
91431ad4e4eSTony Nguyen 	flds = params->prof->segs[seg].fields;
91531ad4e4eSTony Nguyen 
91631ad4e4eSTony Nguyen 	switch (fld) {
917390bd141SQi Zhang 	case ICE_FLOW_FIELD_IDX_ETH_DA:
918390bd141SQi Zhang 	case ICE_FLOW_FIELD_IDX_ETH_SA:
919390bd141SQi Zhang 	case ICE_FLOW_FIELD_IDX_S_VLAN:
920390bd141SQi Zhang 	case ICE_FLOW_FIELD_IDX_C_VLAN:
921390bd141SQi Zhang 		prot_id = seg == 0 ? ICE_PROT_MAC_OF_OR_S : ICE_PROT_MAC_IL;
922390bd141SQi Zhang 		break;
923390bd141SQi Zhang 	case ICE_FLOW_FIELD_IDX_ETH_TYPE:
924390bd141SQi Zhang 		prot_id = seg == 0 ? ICE_PROT_ETYPE_OL : ICE_PROT_ETYPE_IL;
925390bd141SQi Zhang 		break;
926b199dddbSQi Zhang 	case ICE_FLOW_FIELD_IDX_IPV4_DSCP:
927b199dddbSQi Zhang 		prot_id = seg == 0 ? ICE_PROT_IPV4_OF_OR_S : ICE_PROT_IPV4_IL;
928b199dddbSQi Zhang 		break;
929b199dddbSQi Zhang 	case ICE_FLOW_FIELD_IDX_IPV6_DSCP:
930b199dddbSQi Zhang 		prot_id = seg == 0 ? ICE_PROT_IPV6_OF_OR_S : ICE_PROT_IPV6_IL;
931b199dddbSQi Zhang 		break;
932b199dddbSQi Zhang 	case ICE_FLOW_FIELD_IDX_IPV4_TTL:
933b199dddbSQi Zhang 	case ICE_FLOW_FIELD_IDX_IPV4_PROT:
934b199dddbSQi Zhang 		prot_id = seg == 0 ? ICE_PROT_IPV4_OF_OR_S : ICE_PROT_IPV4_IL;
935b199dddbSQi Zhang 
936b199dddbSQi Zhang 		/* TTL and PROT share the same extraction seq. entry.
937b199dddbSQi Zhang 		 * Each is considered a sibling to the other in terms of sharing
938b199dddbSQi Zhang 		 * the same extraction sequence entry.
939b199dddbSQi Zhang 		 */
940b199dddbSQi Zhang 		if (fld == ICE_FLOW_FIELD_IDX_IPV4_TTL)
941b199dddbSQi Zhang 			sib = ICE_FLOW_FIELD_IDX_IPV4_PROT;
942b199dddbSQi Zhang 		else if (fld == ICE_FLOW_FIELD_IDX_IPV4_PROT)
943b199dddbSQi Zhang 			sib = ICE_FLOW_FIELD_IDX_IPV4_TTL;
944b199dddbSQi Zhang 
945b199dddbSQi Zhang 		/* If the sibling field is also included, that field's
946b199dddbSQi Zhang 		 * mask needs to be included.
947b199dddbSQi Zhang 		 */
948b199dddbSQi Zhang 		if (match & BIT(sib))
949b199dddbSQi Zhang 			sib_mask = ice_flds_info[sib].mask;
950b199dddbSQi Zhang 		break;
951b199dddbSQi Zhang 	case ICE_FLOW_FIELD_IDX_IPV6_TTL:
952b199dddbSQi Zhang 	case ICE_FLOW_FIELD_IDX_IPV6_PROT:
953b199dddbSQi Zhang 		prot_id = seg == 0 ? ICE_PROT_IPV6_OF_OR_S : ICE_PROT_IPV6_IL;
954b199dddbSQi Zhang 
955b199dddbSQi Zhang 		/* TTL and PROT share the same extraction seq. entry.
956b199dddbSQi Zhang 		 * Each is considered a sibling to the other in terms of sharing
957b199dddbSQi Zhang 		 * the same extraction sequence entry.
958b199dddbSQi Zhang 		 */
959b199dddbSQi Zhang 		if (fld == ICE_FLOW_FIELD_IDX_IPV6_TTL)
960b199dddbSQi Zhang 			sib = ICE_FLOW_FIELD_IDX_IPV6_PROT;
961b199dddbSQi Zhang 		else if (fld == ICE_FLOW_FIELD_IDX_IPV6_PROT)
962b199dddbSQi Zhang 			sib = ICE_FLOW_FIELD_IDX_IPV6_TTL;
963b199dddbSQi Zhang 
964b199dddbSQi Zhang 		/* If the sibling field is also included, that field's
965b199dddbSQi Zhang 		 * mask needs to be included.
966b199dddbSQi Zhang 		 */
967b199dddbSQi Zhang 		if (match & BIT(sib))
968b199dddbSQi Zhang 			sib_mask = ice_flds_info[sib].mask;
969b199dddbSQi Zhang 		break;
97031ad4e4eSTony Nguyen 	case ICE_FLOW_FIELD_IDX_IPV4_SA:
97131ad4e4eSTony Nguyen 	case ICE_FLOW_FIELD_IDX_IPV4_DA:
97231ad4e4eSTony Nguyen 		prot_id = seg == 0 ? ICE_PROT_IPV4_OF_OR_S : ICE_PROT_IPV4_IL;
97331ad4e4eSTony Nguyen 		break;
97431ad4e4eSTony Nguyen 	case ICE_FLOW_FIELD_IDX_IPV6_SA:
97531ad4e4eSTony Nguyen 	case ICE_FLOW_FIELD_IDX_IPV6_DA:
97631ad4e4eSTony Nguyen 		prot_id = seg == 0 ? ICE_PROT_IPV6_OF_OR_S : ICE_PROT_IPV6_IL;
97731ad4e4eSTony Nguyen 		break;
97831ad4e4eSTony Nguyen 	case ICE_FLOW_FIELD_IDX_TCP_SRC_PORT:
97931ad4e4eSTony Nguyen 	case ICE_FLOW_FIELD_IDX_TCP_DST_PORT:
980390bd141SQi Zhang 	case ICE_FLOW_FIELD_IDX_TCP_FLAGS:
98131ad4e4eSTony Nguyen 		prot_id = ICE_PROT_TCP_IL;
98231ad4e4eSTony Nguyen 		break;
98331ad4e4eSTony Nguyen 	case ICE_FLOW_FIELD_IDX_UDP_SRC_PORT:
98431ad4e4eSTony Nguyen 	case ICE_FLOW_FIELD_IDX_UDP_DST_PORT:
98531ad4e4eSTony Nguyen 		prot_id = ICE_PROT_UDP_IL_OR_S;
98631ad4e4eSTony Nguyen 		break;
9871c01c8c6SMd Fahad Iqbal Polash 	case ICE_FLOW_FIELD_IDX_SCTP_SRC_PORT:
9881c01c8c6SMd Fahad Iqbal Polash 	case ICE_FLOW_FIELD_IDX_SCTP_DST_PORT:
9891c01c8c6SMd Fahad Iqbal Polash 		prot_id = ICE_PROT_SCTP_IL;
9901c01c8c6SMd Fahad Iqbal Polash 		break;
9910577313eSQi Zhang 	case ICE_FLOW_FIELD_IDX_GTPC_TEID:
9920577313eSQi Zhang 	case ICE_FLOW_FIELD_IDX_GTPU_IP_TEID:
9930577313eSQi Zhang 	case ICE_FLOW_FIELD_IDX_GTPU_UP_TEID:
9940577313eSQi Zhang 	case ICE_FLOW_FIELD_IDX_GTPU_DWN_TEID:
9950577313eSQi Zhang 	case ICE_FLOW_FIELD_IDX_GTPU_EH_TEID:
9960577313eSQi Zhang 	case ICE_FLOW_FIELD_IDX_GTPU_EH_QFI:
9970577313eSQi Zhang 		/* GTP is accessed through UDP OF protocol */
9980577313eSQi Zhang 		prot_id = ICE_PROT_UDP_OF;
9990577313eSQi Zhang 		break;
10000577313eSQi Zhang 	case ICE_FLOW_FIELD_IDX_PPPOE_SESS_ID:
10010577313eSQi Zhang 		prot_id = ICE_PROT_PPPOE;
10020577313eSQi Zhang 		break;
10030577313eSQi Zhang 	case ICE_FLOW_FIELD_IDX_PFCP_SEID:
10040577313eSQi Zhang 		prot_id = ICE_PROT_UDP_IL_OR_S;
10050577313eSQi Zhang 		break;
10060577313eSQi Zhang 	case ICE_FLOW_FIELD_IDX_L2TPV3_SESS_ID:
10070577313eSQi Zhang 		prot_id = ICE_PROT_L2TPV3;
10080577313eSQi Zhang 		break;
10090577313eSQi Zhang 	case ICE_FLOW_FIELD_IDX_ESP_SPI:
10100577313eSQi Zhang 		prot_id = ICE_PROT_ESP_F;
10110577313eSQi Zhang 		break;
10120577313eSQi Zhang 	case ICE_FLOW_FIELD_IDX_AH_SPI:
10130577313eSQi Zhang 		prot_id = ICE_PROT_ESP_2;
10140577313eSQi Zhang 		break;
10150577313eSQi Zhang 	case ICE_FLOW_FIELD_IDX_NAT_T_ESP_SPI:
10160577313eSQi Zhang 		prot_id = ICE_PROT_UDP_IL_OR_S;
10170577313eSQi Zhang 		break;
1018390bd141SQi Zhang 	case ICE_FLOW_FIELD_IDX_ARP_SIP:
1019390bd141SQi Zhang 	case ICE_FLOW_FIELD_IDX_ARP_DIP:
1020390bd141SQi Zhang 	case ICE_FLOW_FIELD_IDX_ARP_SHA:
1021390bd141SQi Zhang 	case ICE_FLOW_FIELD_IDX_ARP_DHA:
1022390bd141SQi Zhang 	case ICE_FLOW_FIELD_IDX_ARP_OP:
1023390bd141SQi Zhang 		prot_id = ICE_PROT_ARP_OF;
1024390bd141SQi Zhang 		break;
1025390bd141SQi Zhang 	case ICE_FLOW_FIELD_IDX_ICMP_TYPE:
1026390bd141SQi Zhang 	case ICE_FLOW_FIELD_IDX_ICMP_CODE:
1027390bd141SQi Zhang 		/* ICMP type and code share the same extraction seq. entry */
1028390bd141SQi Zhang 		prot_id = (params->prof->segs[seg].hdrs & ICE_FLOW_SEG_HDR_IPV4) ?
1029390bd141SQi Zhang 				ICE_PROT_ICMP_IL : ICE_PROT_ICMPV6_IL;
1030b199dddbSQi Zhang 		sib = fld == ICE_FLOW_FIELD_IDX_ICMP_TYPE ?
1031b199dddbSQi Zhang 			ICE_FLOW_FIELD_IDX_ICMP_CODE :
1032b199dddbSQi Zhang 			ICE_FLOW_FIELD_IDX_ICMP_TYPE;
1033390bd141SQi Zhang 		break;
1034a4e82a81STony Nguyen 	case ICE_FLOW_FIELD_IDX_GRE_KEYID:
1035a4e82a81STony Nguyen 		prot_id = ICE_PROT_GRE_OF;
1036a4e82a81STony Nguyen 		break;
103731ad4e4eSTony Nguyen 	default:
103831ad4e4eSTony Nguyen 		return ICE_ERR_NOT_IMPL;
103931ad4e4eSTony Nguyen 	}
104031ad4e4eSTony Nguyen 
104131ad4e4eSTony Nguyen 	/* Each extraction sequence entry is a word in size, and extracts a
104231ad4e4eSTony Nguyen 	 * word-aligned offset from a protocol header.
104331ad4e4eSTony Nguyen 	 */
104431ad4e4eSTony Nguyen 	ese_bits = ICE_FLOW_FV_EXTRACT_SZ * BITS_PER_BYTE;
104531ad4e4eSTony Nguyen 
104631ad4e4eSTony Nguyen 	flds[fld].xtrct.prot_id = prot_id;
104731ad4e4eSTony Nguyen 	flds[fld].xtrct.off = (ice_flds_info[fld].off / ese_bits) *
104831ad4e4eSTony Nguyen 		ICE_FLOW_FV_EXTRACT_SZ;
104931ad4e4eSTony Nguyen 	flds[fld].xtrct.disp = (u8)(ice_flds_info[fld].off % ese_bits);
105031ad4e4eSTony Nguyen 	flds[fld].xtrct.idx = params->es_cnt;
1051b199dddbSQi Zhang 	flds[fld].xtrct.mask = ice_flds_info[fld].mask;
105231ad4e4eSTony Nguyen 
105331ad4e4eSTony Nguyen 	/* Adjust the next field-entry index after accommodating the number of
105431ad4e4eSTony Nguyen 	 * entries this field consumes
105531ad4e4eSTony Nguyen 	 */
105631ad4e4eSTony Nguyen 	cnt = DIV_ROUND_UP(flds[fld].xtrct.disp + ice_flds_info[fld].size,
105731ad4e4eSTony Nguyen 			   ese_bits);
105831ad4e4eSTony Nguyen 
105931ad4e4eSTony Nguyen 	/* Fill in the extraction sequence entries needed for this field */
106031ad4e4eSTony Nguyen 	off = flds[fld].xtrct.off;
1061b199dddbSQi Zhang 	mask = flds[fld].xtrct.mask;
106231ad4e4eSTony Nguyen 	for (i = 0; i < cnt; i++) {
1063b199dddbSQi Zhang 		/* Only consume an extraction sequence entry if there is no
1064b199dddbSQi Zhang 		 * sibling field associated with this field or the sibling entry
1065b199dddbSQi Zhang 		 * already extracts the word shared with this field.
1066b199dddbSQi Zhang 		 */
1067b199dddbSQi Zhang 		if (sib == ICE_FLOW_FIELD_IDX_MAX ||
1068b199dddbSQi Zhang 		    flds[sib].xtrct.prot_id == ICE_PROT_ID_INVAL ||
1069b199dddbSQi Zhang 		    flds[sib].xtrct.off != off) {
107031ad4e4eSTony Nguyen 			u8 idx;
107131ad4e4eSTony Nguyen 
107231ad4e4eSTony Nguyen 			/* Make sure the number of extraction sequence required
107331ad4e4eSTony Nguyen 			 * does not exceed the block's capability
107431ad4e4eSTony Nguyen 			 */
107531ad4e4eSTony Nguyen 			if (params->es_cnt >= fv_words)
107631ad4e4eSTony Nguyen 				return ICE_ERR_MAX_LIMIT;
107731ad4e4eSTony Nguyen 
107831ad4e4eSTony Nguyen 			/* some blocks require a reversed field vector layout */
107931ad4e4eSTony Nguyen 			if (hw->blk[params->blk].es.reverse)
108031ad4e4eSTony Nguyen 				idx = fv_words - params->es_cnt - 1;
108131ad4e4eSTony Nguyen 			else
108231ad4e4eSTony Nguyen 				idx = params->es_cnt;
108331ad4e4eSTony Nguyen 
108431ad4e4eSTony Nguyen 			params->es[idx].prot_id = prot_id;
108531ad4e4eSTony Nguyen 			params->es[idx].off = off;
1086b199dddbSQi Zhang 			params->mask[idx] = mask | sib_mask;
108731ad4e4eSTony Nguyen 			params->es_cnt++;
1088b199dddbSQi Zhang 		}
108931ad4e4eSTony Nguyen 
109031ad4e4eSTony Nguyen 		off += ICE_FLOW_FV_EXTRACT_SZ;
109131ad4e4eSTony Nguyen 	}
109231ad4e4eSTony Nguyen 
109331ad4e4eSTony Nguyen 	return 0;
109431ad4e4eSTony Nguyen }
109531ad4e4eSTony Nguyen 
109631ad4e4eSTony Nguyen /**
10972c57ffcbSHenry Tieman  * ice_flow_xtract_raws - Create extract sequence entries for raw bytes
10982c57ffcbSHenry Tieman  * @hw: pointer to the HW struct
10992c57ffcbSHenry Tieman  * @params: information about the flow to be processed
1100ac382a09SBruce Allan  * @seg: index of packet segment whose raw fields are to be extracted
11012c57ffcbSHenry Tieman  */
11022c57ffcbSHenry Tieman static enum ice_status
11032c57ffcbSHenry Tieman ice_flow_xtract_raws(struct ice_hw *hw, struct ice_flow_prof_params *params,
11042c57ffcbSHenry Tieman 		     u8 seg)
11052c57ffcbSHenry Tieman {
11062c57ffcbSHenry Tieman 	u16 fv_words;
11072c57ffcbSHenry Tieman 	u16 hdrs_sz;
11082c57ffcbSHenry Tieman 	u8 i;
11092c57ffcbSHenry Tieman 
11102c57ffcbSHenry Tieman 	if (!params->prof->segs[seg].raws_cnt)
11112c57ffcbSHenry Tieman 		return 0;
11122c57ffcbSHenry Tieman 
11132c57ffcbSHenry Tieman 	if (params->prof->segs[seg].raws_cnt >
11142c57ffcbSHenry Tieman 	    ARRAY_SIZE(params->prof->segs[seg].raws))
11152c57ffcbSHenry Tieman 		return ICE_ERR_MAX_LIMIT;
11162c57ffcbSHenry Tieman 
11172c57ffcbSHenry Tieman 	/* Offsets within the segment headers are not supported */
11182c57ffcbSHenry Tieman 	hdrs_sz = ice_flow_calc_seg_sz(params, seg);
11192c57ffcbSHenry Tieman 	if (!hdrs_sz)
11202c57ffcbSHenry Tieman 		return ICE_ERR_PARAM;
11212c57ffcbSHenry Tieman 
11222c57ffcbSHenry Tieman 	fv_words = hw->blk[params->blk].es.fvw;
11232c57ffcbSHenry Tieman 
11242c57ffcbSHenry Tieman 	for (i = 0; i < params->prof->segs[seg].raws_cnt; i++) {
11252c57ffcbSHenry Tieman 		struct ice_flow_seg_fld_raw *raw;
11262c57ffcbSHenry Tieman 		u16 off, cnt, j;
11272c57ffcbSHenry Tieman 
11282c57ffcbSHenry Tieman 		raw = &params->prof->segs[seg].raws[i];
11292c57ffcbSHenry Tieman 
11302c57ffcbSHenry Tieman 		/* Storing extraction information */
11312c57ffcbSHenry Tieman 		raw->info.xtrct.prot_id = ICE_PROT_MAC_OF_OR_S;
11322c57ffcbSHenry Tieman 		raw->info.xtrct.off = (raw->off / ICE_FLOW_FV_EXTRACT_SZ) *
11332c57ffcbSHenry Tieman 			ICE_FLOW_FV_EXTRACT_SZ;
11342c57ffcbSHenry Tieman 		raw->info.xtrct.disp = (raw->off % ICE_FLOW_FV_EXTRACT_SZ) *
11352c57ffcbSHenry Tieman 			BITS_PER_BYTE;
11362c57ffcbSHenry Tieman 		raw->info.xtrct.idx = params->es_cnt;
11372c57ffcbSHenry Tieman 
11382c57ffcbSHenry Tieman 		/* Determine the number of field vector entries this raw field
11392c57ffcbSHenry Tieman 		 * consumes.
11402c57ffcbSHenry Tieman 		 */
11412c57ffcbSHenry Tieman 		cnt = DIV_ROUND_UP(raw->info.xtrct.disp +
11422c57ffcbSHenry Tieman 				   (raw->info.src.last * BITS_PER_BYTE),
11432c57ffcbSHenry Tieman 				   (ICE_FLOW_FV_EXTRACT_SZ * BITS_PER_BYTE));
11442c57ffcbSHenry Tieman 		off = raw->info.xtrct.off;
11452c57ffcbSHenry Tieman 		for (j = 0; j < cnt; j++) {
11462c57ffcbSHenry Tieman 			u16 idx;
11472c57ffcbSHenry Tieman 
11482c57ffcbSHenry Tieman 			/* Make sure the number of extraction sequence required
11492c57ffcbSHenry Tieman 			 * does not exceed the block's capability
11502c57ffcbSHenry Tieman 			 */
11512c57ffcbSHenry Tieman 			if (params->es_cnt >= hw->blk[params->blk].es.count ||
11522c57ffcbSHenry Tieman 			    params->es_cnt >= ICE_MAX_FV_WORDS)
11532c57ffcbSHenry Tieman 				return ICE_ERR_MAX_LIMIT;
11542c57ffcbSHenry Tieman 
11552c57ffcbSHenry Tieman 			/* some blocks require a reversed field vector layout */
11562c57ffcbSHenry Tieman 			if (hw->blk[params->blk].es.reverse)
11572c57ffcbSHenry Tieman 				idx = fv_words - params->es_cnt - 1;
11582c57ffcbSHenry Tieman 			else
11592c57ffcbSHenry Tieman 				idx = params->es_cnt;
11602c57ffcbSHenry Tieman 
11612c57ffcbSHenry Tieman 			params->es[idx].prot_id = raw->info.xtrct.prot_id;
11622c57ffcbSHenry Tieman 			params->es[idx].off = off;
11632c57ffcbSHenry Tieman 			params->es_cnt++;
11642c57ffcbSHenry Tieman 			off += ICE_FLOW_FV_EXTRACT_SZ;
11652c57ffcbSHenry Tieman 		}
11662c57ffcbSHenry Tieman 	}
11672c57ffcbSHenry Tieman 
11682c57ffcbSHenry Tieman 	return 0;
11692c57ffcbSHenry Tieman }
11702c57ffcbSHenry Tieman 
11712c57ffcbSHenry Tieman /**
117231ad4e4eSTony Nguyen  * ice_flow_create_xtrct_seq - Create an extraction sequence for given segments
117331ad4e4eSTony Nguyen  * @hw: pointer to the HW struct
117431ad4e4eSTony Nguyen  * @params: information about the flow to be processed
117531ad4e4eSTony Nguyen  *
117631ad4e4eSTony Nguyen  * This function iterates through all matched fields in the given segments, and
117731ad4e4eSTony Nguyen  * creates an extraction sequence for the fields.
117831ad4e4eSTony Nguyen  */
117931ad4e4eSTony Nguyen static enum ice_status
118031ad4e4eSTony Nguyen ice_flow_create_xtrct_seq(struct ice_hw *hw,
118131ad4e4eSTony Nguyen 			  struct ice_flow_prof_params *params)
118231ad4e4eSTony Nguyen {
118331ad4e4eSTony Nguyen 	struct ice_flow_prof *prof = params->prof;
118431ad4e4eSTony Nguyen 	enum ice_status status = 0;
118531ad4e4eSTony Nguyen 	u8 i;
118631ad4e4eSTony Nguyen 
118731ad4e4eSTony Nguyen 	for (i = 0; i < prof->segs_cnt; i++) {
1188b199dddbSQi Zhang 		u64 match = params->prof->segs[i].match;
1189b199dddbSQi Zhang 		enum ice_flow_field j;
119031ad4e4eSTony Nguyen 
1191b199dddbSQi Zhang 		for_each_set_bit(j, (unsigned long *)&match,
119231ad4e4eSTony Nguyen 				 ICE_FLOW_FIELD_IDX_MAX) {
1193b199dddbSQi Zhang 			status = ice_flow_xtract_fld(hw, params, i, j, match);
119431ad4e4eSTony Nguyen 			if (status)
119531ad4e4eSTony Nguyen 				return status;
1196b199dddbSQi Zhang 			clear_bit(j, (unsigned long *)&match);
119731ad4e4eSTony Nguyen 		}
11982c57ffcbSHenry Tieman 
11992c57ffcbSHenry Tieman 		/* Process raw matching bytes */
12002c57ffcbSHenry Tieman 		status = ice_flow_xtract_raws(hw, params, i);
12012c57ffcbSHenry Tieman 		if (status)
12022c57ffcbSHenry Tieman 			return status;
120331ad4e4eSTony Nguyen 	}
120431ad4e4eSTony Nguyen 
120531ad4e4eSTony Nguyen 	return status;
120631ad4e4eSTony Nguyen }
120731ad4e4eSTony Nguyen 
120831ad4e4eSTony Nguyen /**
120931ad4e4eSTony Nguyen  * ice_flow_proc_segs - process all packet segments associated with a profile
121031ad4e4eSTony Nguyen  * @hw: pointer to the HW struct
121131ad4e4eSTony Nguyen  * @params: information about the flow to be processed
121231ad4e4eSTony Nguyen  */
121331ad4e4eSTony Nguyen static enum ice_status
121431ad4e4eSTony Nguyen ice_flow_proc_segs(struct ice_hw *hw, struct ice_flow_prof_params *params)
121531ad4e4eSTony Nguyen {
121631ad4e4eSTony Nguyen 	enum ice_status status;
121731ad4e4eSTony Nguyen 
121831ad4e4eSTony Nguyen 	status = ice_flow_proc_seg_hdrs(params);
121931ad4e4eSTony Nguyen 	if (status)
122031ad4e4eSTony Nguyen 		return status;
122131ad4e4eSTony Nguyen 
122231ad4e4eSTony Nguyen 	status = ice_flow_create_xtrct_seq(hw, params);
122331ad4e4eSTony Nguyen 	if (status)
122431ad4e4eSTony Nguyen 		return status;
122531ad4e4eSTony Nguyen 
122631ad4e4eSTony Nguyen 	switch (params->blk) {
1227148beb61SHenry Tieman 	case ICE_BLK_FD:
122831ad4e4eSTony Nguyen 	case ICE_BLK_RSS:
122931ad4e4eSTony Nguyen 		status = 0;
123031ad4e4eSTony Nguyen 		break;
123131ad4e4eSTony Nguyen 	default:
123231ad4e4eSTony Nguyen 		return ICE_ERR_NOT_IMPL;
123331ad4e4eSTony Nguyen 	}
123431ad4e4eSTony Nguyen 
123531ad4e4eSTony Nguyen 	return status;
123631ad4e4eSTony Nguyen }
123731ad4e4eSTony Nguyen 
12382c61054cSTony Nguyen #define ICE_FLOW_FIND_PROF_CHK_FLDS	0x00000001
12392c61054cSTony Nguyen #define ICE_FLOW_FIND_PROF_CHK_VSI	0x00000002
12402c61054cSTony Nguyen #define ICE_FLOW_FIND_PROF_NOT_CHK_DIR	0x00000004
12412c61054cSTony Nguyen 
12422c61054cSTony Nguyen /**
12432c61054cSTony Nguyen  * ice_flow_find_prof_conds - Find a profile matching headers and conditions
12442c61054cSTony Nguyen  * @hw: pointer to the HW struct
12452c61054cSTony Nguyen  * @blk: classification stage
12462c61054cSTony Nguyen  * @dir: flow direction
12472c61054cSTony Nguyen  * @segs: array of one or more packet segments that describe the flow
12482c61054cSTony Nguyen  * @segs_cnt: number of packet segments provided
12492c61054cSTony Nguyen  * @vsi_handle: software VSI handle to check VSI (ICE_FLOW_FIND_PROF_CHK_VSI)
12502c61054cSTony Nguyen  * @conds: additional conditions to be checked (ICE_FLOW_FIND_PROF_CHK_*)
12512c61054cSTony Nguyen  */
12522c61054cSTony Nguyen static struct ice_flow_prof *
12532c61054cSTony Nguyen ice_flow_find_prof_conds(struct ice_hw *hw, enum ice_block blk,
12542c61054cSTony Nguyen 			 enum ice_flow_dir dir, struct ice_flow_seg_info *segs,
12552c61054cSTony Nguyen 			 u8 segs_cnt, u16 vsi_handle, u32 conds)
12562c61054cSTony Nguyen {
12572c61054cSTony Nguyen 	struct ice_flow_prof *p, *prof = NULL;
12582c61054cSTony Nguyen 
12592c61054cSTony Nguyen 	mutex_lock(&hw->fl_profs_locks[blk]);
12602c61054cSTony Nguyen 	list_for_each_entry(p, &hw->fl_profs[blk], l_entry)
12612c61054cSTony Nguyen 		if ((p->dir == dir || conds & ICE_FLOW_FIND_PROF_NOT_CHK_DIR) &&
12622c61054cSTony Nguyen 		    segs_cnt && segs_cnt == p->segs_cnt) {
12632c61054cSTony Nguyen 			u8 i;
12642c61054cSTony Nguyen 
12652c61054cSTony Nguyen 			/* Check for profile-VSI association if specified */
12662c61054cSTony Nguyen 			if ((conds & ICE_FLOW_FIND_PROF_CHK_VSI) &&
12672c61054cSTony Nguyen 			    ice_is_vsi_valid(hw, vsi_handle) &&
12682c61054cSTony Nguyen 			    !test_bit(vsi_handle, p->vsis))
12692c61054cSTony Nguyen 				continue;
12702c61054cSTony Nguyen 
12712c61054cSTony Nguyen 			/* Protocol headers must be checked. Matched fields are
12722c61054cSTony Nguyen 			 * checked if specified.
12732c61054cSTony Nguyen 			 */
12742c61054cSTony Nguyen 			for (i = 0; i < segs_cnt; i++)
12752c61054cSTony Nguyen 				if (segs[i].hdrs != p->segs[i].hdrs ||
12762c61054cSTony Nguyen 				    ((conds & ICE_FLOW_FIND_PROF_CHK_FLDS) &&
12772c61054cSTony Nguyen 				     segs[i].match != p->segs[i].match))
12782c61054cSTony Nguyen 					break;
12792c61054cSTony Nguyen 
12802c61054cSTony Nguyen 			/* A match is found if all segments are matched */
12812c61054cSTony Nguyen 			if (i == segs_cnt) {
12822c61054cSTony Nguyen 				prof = p;
12832c61054cSTony Nguyen 				break;
12842c61054cSTony Nguyen 			}
12852c61054cSTony Nguyen 		}
12862c61054cSTony Nguyen 	mutex_unlock(&hw->fl_profs_locks[blk]);
12872c61054cSTony Nguyen 
12882c61054cSTony Nguyen 	return prof;
12892c61054cSTony Nguyen }
12902c61054cSTony Nguyen 
12912c61054cSTony Nguyen /**
12922c61054cSTony Nguyen  * ice_flow_find_prof_id - Look up a profile with given profile ID
12932c61054cSTony Nguyen  * @hw: pointer to the HW struct
12942c61054cSTony Nguyen  * @blk: classification stage
12952c61054cSTony Nguyen  * @prof_id: unique ID to identify this flow profile
12962c61054cSTony Nguyen  */
12972c61054cSTony Nguyen static struct ice_flow_prof *
12982c61054cSTony Nguyen ice_flow_find_prof_id(struct ice_hw *hw, enum ice_block blk, u64 prof_id)
12992c61054cSTony Nguyen {
13002c61054cSTony Nguyen 	struct ice_flow_prof *p;
13012c61054cSTony Nguyen 
13022c61054cSTony Nguyen 	list_for_each_entry(p, &hw->fl_profs[blk], l_entry)
13032c61054cSTony Nguyen 		if (p->id == prof_id)
13042c61054cSTony Nguyen 			return p;
13052c61054cSTony Nguyen 
13062c61054cSTony Nguyen 	return NULL;
13072c61054cSTony Nguyen }
13082c61054cSTony Nguyen 
130931ad4e4eSTony Nguyen /**
1310148beb61SHenry Tieman  * ice_dealloc_flow_entry - Deallocate flow entry memory
1311148beb61SHenry Tieman  * @hw: pointer to the HW struct
1312148beb61SHenry Tieman  * @entry: flow entry to be removed
1313148beb61SHenry Tieman  */
1314148beb61SHenry Tieman static void
1315148beb61SHenry Tieman ice_dealloc_flow_entry(struct ice_hw *hw, struct ice_flow_entry *entry)
1316148beb61SHenry Tieman {
1317148beb61SHenry Tieman 	if (!entry)
1318148beb61SHenry Tieman 		return;
1319148beb61SHenry Tieman 
1320148beb61SHenry Tieman 	if (entry->entry)
1321148beb61SHenry Tieman 		devm_kfree(ice_hw_to_dev(hw), entry->entry);
1322148beb61SHenry Tieman 
1323148beb61SHenry Tieman 	devm_kfree(ice_hw_to_dev(hw), entry);
1324148beb61SHenry Tieman }
1325148beb61SHenry Tieman 
1326148beb61SHenry Tieman /**
1327148beb61SHenry Tieman  * ice_flow_rem_entry_sync - Remove a flow entry
1328148beb61SHenry Tieman  * @hw: pointer to the HW struct
1329148beb61SHenry Tieman  * @blk: classification stage
1330148beb61SHenry Tieman  * @entry: flow entry to be removed
1331148beb61SHenry Tieman  */
1332148beb61SHenry Tieman static enum ice_status
1333148beb61SHenry Tieman ice_flow_rem_entry_sync(struct ice_hw *hw, enum ice_block __always_unused blk,
1334148beb61SHenry Tieman 			struct ice_flow_entry *entry)
1335148beb61SHenry Tieman {
1336148beb61SHenry Tieman 	if (!entry)
1337148beb61SHenry Tieman 		return ICE_ERR_BAD_PTR;
1338148beb61SHenry Tieman 
1339148beb61SHenry Tieman 	list_del(&entry->l_entry);
1340148beb61SHenry Tieman 
1341148beb61SHenry Tieman 	ice_dealloc_flow_entry(hw, entry);
1342148beb61SHenry Tieman 
1343148beb61SHenry Tieman 	return 0;
1344148beb61SHenry Tieman }
1345148beb61SHenry Tieman 
1346148beb61SHenry Tieman /**
134731ad4e4eSTony Nguyen  * ice_flow_add_prof_sync - Add a flow profile for packet segments and fields
134831ad4e4eSTony Nguyen  * @hw: pointer to the HW struct
134931ad4e4eSTony Nguyen  * @blk: classification stage
135031ad4e4eSTony Nguyen  * @dir: flow direction
135131ad4e4eSTony Nguyen  * @prof_id: unique ID to identify this flow profile
135231ad4e4eSTony Nguyen  * @segs: array of one or more packet segments that describe the flow
135331ad4e4eSTony Nguyen  * @segs_cnt: number of packet segments provided
135431ad4e4eSTony Nguyen  * @prof: stores the returned flow profile added
135531ad4e4eSTony Nguyen  *
135631ad4e4eSTony Nguyen  * Assumption: the caller has acquired the lock to the profile list
135731ad4e4eSTony Nguyen  */
135831ad4e4eSTony Nguyen static enum ice_status
135931ad4e4eSTony Nguyen ice_flow_add_prof_sync(struct ice_hw *hw, enum ice_block blk,
136031ad4e4eSTony Nguyen 		       enum ice_flow_dir dir, u64 prof_id,
136131ad4e4eSTony Nguyen 		       struct ice_flow_seg_info *segs, u8 segs_cnt,
136231ad4e4eSTony Nguyen 		       struct ice_flow_prof **prof)
136331ad4e4eSTony Nguyen {
136488dcfdb4SBruce Allan 	struct ice_flow_prof_params *params;
136531ad4e4eSTony Nguyen 	enum ice_status status;
136631ad4e4eSTony Nguyen 	u8 i;
136731ad4e4eSTony Nguyen 
136831ad4e4eSTony Nguyen 	if (!prof)
136931ad4e4eSTony Nguyen 		return ICE_ERR_BAD_PTR;
137031ad4e4eSTony Nguyen 
137188dcfdb4SBruce Allan 	params = kzalloc(sizeof(*params), GFP_KERNEL);
137288dcfdb4SBruce Allan 	if (!params)
137331ad4e4eSTony Nguyen 		return ICE_ERR_NO_MEMORY;
137431ad4e4eSTony Nguyen 
137588dcfdb4SBruce Allan 	params->prof = devm_kzalloc(ice_hw_to_dev(hw), sizeof(*params->prof),
137688dcfdb4SBruce Allan 				    GFP_KERNEL);
137788dcfdb4SBruce Allan 	if (!params->prof) {
137888dcfdb4SBruce Allan 		status = ICE_ERR_NO_MEMORY;
137988dcfdb4SBruce Allan 		goto free_params;
138088dcfdb4SBruce Allan 	}
138188dcfdb4SBruce Allan 
138231ad4e4eSTony Nguyen 	/* initialize extraction sequence to all invalid (0xff) */
138331ad4e4eSTony Nguyen 	for (i = 0; i < ICE_MAX_FV_WORDS; i++) {
138488dcfdb4SBruce Allan 		params->es[i].prot_id = ICE_PROT_INVALID;
138588dcfdb4SBruce Allan 		params->es[i].off = ICE_FV_OFFSET_INVAL;
138631ad4e4eSTony Nguyen 	}
138731ad4e4eSTony Nguyen 
138888dcfdb4SBruce Allan 	params->blk = blk;
138988dcfdb4SBruce Allan 	params->prof->id = prof_id;
139088dcfdb4SBruce Allan 	params->prof->dir = dir;
139188dcfdb4SBruce Allan 	params->prof->segs_cnt = segs_cnt;
139231ad4e4eSTony Nguyen 
139331ad4e4eSTony Nguyen 	/* Make a copy of the segments that need to be persistent in the flow
139431ad4e4eSTony Nguyen 	 * profile instance
139531ad4e4eSTony Nguyen 	 */
139631ad4e4eSTony Nguyen 	for (i = 0; i < segs_cnt; i++)
139788dcfdb4SBruce Allan 		memcpy(&params->prof->segs[i], &segs[i], sizeof(*segs));
139831ad4e4eSTony Nguyen 
139988dcfdb4SBruce Allan 	status = ice_flow_proc_segs(hw, params);
140031ad4e4eSTony Nguyen 	if (status) {
14019228d8b2SJacob Keller 		ice_debug(hw, ICE_DBG_FLOW, "Error processing a flow's packet segments\n");
140231ad4e4eSTony Nguyen 		goto out;
140331ad4e4eSTony Nguyen 	}
140431ad4e4eSTony Nguyen 
140531ad4e4eSTony Nguyen 	/* Add a HW profile for this flow profile */
140688dcfdb4SBruce Allan 	status = ice_add_prof(hw, blk, prof_id, (u8 *)params->ptypes,
1407cbad5db8SQi Zhang 			      params->attr, params->attr_cnt, params->es,
1408cbad5db8SQi Zhang 			      params->mask);
140931ad4e4eSTony Nguyen 	if (status) {
141031ad4e4eSTony Nguyen 		ice_debug(hw, ICE_DBG_FLOW, "Error adding a HW flow profile\n");
141131ad4e4eSTony Nguyen 		goto out;
141231ad4e4eSTony Nguyen 	}
141331ad4e4eSTony Nguyen 
141488dcfdb4SBruce Allan 	INIT_LIST_HEAD(&params->prof->entries);
141588dcfdb4SBruce Allan 	mutex_init(&params->prof->entries_lock);
141688dcfdb4SBruce Allan 	*prof = params->prof;
141731ad4e4eSTony Nguyen 
141831ad4e4eSTony Nguyen out:
141931ad4e4eSTony Nguyen 	if (status)
142088dcfdb4SBruce Allan 		devm_kfree(ice_hw_to_dev(hw), params->prof);
142188dcfdb4SBruce Allan free_params:
142288dcfdb4SBruce Allan 	kfree(params);
142331ad4e4eSTony Nguyen 
142431ad4e4eSTony Nguyen 	return status;
142531ad4e4eSTony Nguyen }
142631ad4e4eSTony Nguyen 
142731ad4e4eSTony Nguyen /**
14282c61054cSTony Nguyen  * ice_flow_rem_prof_sync - remove a flow profile
14292c61054cSTony Nguyen  * @hw: pointer to the hardware structure
14302c61054cSTony Nguyen  * @blk: classification stage
14312c61054cSTony Nguyen  * @prof: pointer to flow profile to remove
14322c61054cSTony Nguyen  *
14332c61054cSTony Nguyen  * Assumption: the caller has acquired the lock to the profile list
14342c61054cSTony Nguyen  */
14352c61054cSTony Nguyen static enum ice_status
14362c61054cSTony Nguyen ice_flow_rem_prof_sync(struct ice_hw *hw, enum ice_block blk,
14372c61054cSTony Nguyen 		       struct ice_flow_prof *prof)
14382c61054cSTony Nguyen {
14392c61054cSTony Nguyen 	enum ice_status status;
14402c61054cSTony Nguyen 
1441148beb61SHenry Tieman 	/* Remove all remaining flow entries before removing the flow profile */
1442148beb61SHenry Tieman 	if (!list_empty(&prof->entries)) {
1443148beb61SHenry Tieman 		struct ice_flow_entry *e, *t;
1444148beb61SHenry Tieman 
1445148beb61SHenry Tieman 		mutex_lock(&prof->entries_lock);
1446148beb61SHenry Tieman 
1447148beb61SHenry Tieman 		list_for_each_entry_safe(e, t, &prof->entries, l_entry) {
1448148beb61SHenry Tieman 			status = ice_flow_rem_entry_sync(hw, blk, e);
1449148beb61SHenry Tieman 			if (status)
1450148beb61SHenry Tieman 				break;
1451148beb61SHenry Tieman 		}
1452148beb61SHenry Tieman 
1453148beb61SHenry Tieman 		mutex_unlock(&prof->entries_lock);
1454148beb61SHenry Tieman 	}
1455148beb61SHenry Tieman 
14562c61054cSTony Nguyen 	/* Remove all hardware profiles associated with this flow profile */
14572c61054cSTony Nguyen 	status = ice_rem_prof(hw, blk, prof->id);
14582c61054cSTony Nguyen 	if (!status) {
14592c61054cSTony Nguyen 		list_del(&prof->l_entry);
14602c61054cSTony Nguyen 		mutex_destroy(&prof->entries_lock);
14612c61054cSTony Nguyen 		devm_kfree(ice_hw_to_dev(hw), prof);
14622c61054cSTony Nguyen 	}
14632c61054cSTony Nguyen 
14642c61054cSTony Nguyen 	return status;
14652c61054cSTony Nguyen }
14662c61054cSTony Nguyen 
14672c61054cSTony Nguyen /**
1468451f2c44STony Nguyen  * ice_flow_assoc_prof - associate a VSI with a flow profile
1469451f2c44STony Nguyen  * @hw: pointer to the hardware structure
1470451f2c44STony Nguyen  * @blk: classification stage
1471451f2c44STony Nguyen  * @prof: pointer to flow profile
1472451f2c44STony Nguyen  * @vsi_handle: software VSI handle
1473451f2c44STony Nguyen  *
1474451f2c44STony Nguyen  * Assumption: the caller has acquired the lock to the profile list
1475451f2c44STony Nguyen  * and the software VSI handle has been validated
1476451f2c44STony Nguyen  */
1477451f2c44STony Nguyen static enum ice_status
1478451f2c44STony Nguyen ice_flow_assoc_prof(struct ice_hw *hw, enum ice_block blk,
1479451f2c44STony Nguyen 		    struct ice_flow_prof *prof, u16 vsi_handle)
1480451f2c44STony Nguyen {
1481451f2c44STony Nguyen 	enum ice_status status = 0;
1482451f2c44STony Nguyen 
1483451f2c44STony Nguyen 	if (!test_bit(vsi_handle, prof->vsis)) {
1484451f2c44STony Nguyen 		status = ice_add_prof_id_flow(hw, blk,
1485451f2c44STony Nguyen 					      ice_get_hw_vsi_num(hw,
1486451f2c44STony Nguyen 								 vsi_handle),
1487451f2c44STony Nguyen 					      prof->id);
1488451f2c44STony Nguyen 		if (!status)
1489451f2c44STony Nguyen 			set_bit(vsi_handle, prof->vsis);
1490451f2c44STony Nguyen 		else
14919228d8b2SJacob Keller 			ice_debug(hw, ICE_DBG_FLOW, "HW profile add failed, %d\n",
1492451f2c44STony Nguyen 				  status);
1493451f2c44STony Nguyen 	}
1494451f2c44STony Nguyen 
1495451f2c44STony Nguyen 	return status;
1496451f2c44STony Nguyen }
1497451f2c44STony Nguyen 
1498451f2c44STony Nguyen /**
14992c61054cSTony Nguyen  * ice_flow_disassoc_prof - disassociate a VSI from a flow profile
15002c61054cSTony Nguyen  * @hw: pointer to the hardware structure
15012c61054cSTony Nguyen  * @blk: classification stage
15022c61054cSTony Nguyen  * @prof: pointer to flow profile
15032c61054cSTony Nguyen  * @vsi_handle: software VSI handle
15042c61054cSTony Nguyen  *
15052c61054cSTony Nguyen  * Assumption: the caller has acquired the lock to the profile list
15062c61054cSTony Nguyen  * and the software VSI handle has been validated
15072c61054cSTony Nguyen  */
15082c61054cSTony Nguyen static enum ice_status
15092c61054cSTony Nguyen ice_flow_disassoc_prof(struct ice_hw *hw, enum ice_block blk,
15102c61054cSTony Nguyen 		       struct ice_flow_prof *prof, u16 vsi_handle)
15112c61054cSTony Nguyen {
15122c61054cSTony Nguyen 	enum ice_status status = 0;
15132c61054cSTony Nguyen 
15142c61054cSTony Nguyen 	if (test_bit(vsi_handle, prof->vsis)) {
15152c61054cSTony Nguyen 		status = ice_rem_prof_id_flow(hw, blk,
15162c61054cSTony Nguyen 					      ice_get_hw_vsi_num(hw,
15172c61054cSTony Nguyen 								 vsi_handle),
15182c61054cSTony Nguyen 					      prof->id);
15192c61054cSTony Nguyen 		if (!status)
15202c61054cSTony Nguyen 			clear_bit(vsi_handle, prof->vsis);
15212c61054cSTony Nguyen 		else
15229228d8b2SJacob Keller 			ice_debug(hw, ICE_DBG_FLOW, "HW profile remove failed, %d\n",
15232c61054cSTony Nguyen 				  status);
15242c61054cSTony Nguyen 	}
15252c61054cSTony Nguyen 
15262c61054cSTony Nguyen 	return status;
15272c61054cSTony Nguyen }
15282c61054cSTony Nguyen 
15292c61054cSTony Nguyen /**
153031ad4e4eSTony Nguyen  * ice_flow_add_prof - Add a flow profile for packet segments and matched fields
153131ad4e4eSTony Nguyen  * @hw: pointer to the HW struct
153231ad4e4eSTony Nguyen  * @blk: classification stage
153331ad4e4eSTony Nguyen  * @dir: flow direction
153431ad4e4eSTony Nguyen  * @prof_id: unique ID to identify this flow profile
153531ad4e4eSTony Nguyen  * @segs: array of one or more packet segments that describe the flow
153631ad4e4eSTony Nguyen  * @segs_cnt: number of packet segments provided
1537451f2c44STony Nguyen  * @prof: stores the returned flow profile added
153831ad4e4eSTony Nguyen  */
1539148beb61SHenry Tieman enum ice_status
154031ad4e4eSTony Nguyen ice_flow_add_prof(struct ice_hw *hw, enum ice_block blk, enum ice_flow_dir dir,
1541451f2c44STony Nguyen 		  u64 prof_id, struct ice_flow_seg_info *segs, u8 segs_cnt,
1542451f2c44STony Nguyen 		  struct ice_flow_prof **prof)
154331ad4e4eSTony Nguyen {
154431ad4e4eSTony Nguyen 	enum ice_status status;
154531ad4e4eSTony Nguyen 
154631ad4e4eSTony Nguyen 	if (segs_cnt > ICE_FLOW_SEG_MAX)
154731ad4e4eSTony Nguyen 		return ICE_ERR_MAX_LIMIT;
154831ad4e4eSTony Nguyen 
154931ad4e4eSTony Nguyen 	if (!segs_cnt)
155031ad4e4eSTony Nguyen 		return ICE_ERR_PARAM;
155131ad4e4eSTony Nguyen 
155231ad4e4eSTony Nguyen 	if (!segs)
155331ad4e4eSTony Nguyen 		return ICE_ERR_BAD_PTR;
155431ad4e4eSTony Nguyen 
155531ad4e4eSTony Nguyen 	status = ice_flow_val_hdrs(segs, segs_cnt);
155631ad4e4eSTony Nguyen 	if (status)
155731ad4e4eSTony Nguyen 		return status;
155831ad4e4eSTony Nguyen 
155931ad4e4eSTony Nguyen 	mutex_lock(&hw->fl_profs_locks[blk]);
156031ad4e4eSTony Nguyen 
156131ad4e4eSTony Nguyen 	status = ice_flow_add_prof_sync(hw, blk, dir, prof_id, segs, segs_cnt,
1562451f2c44STony Nguyen 					prof);
156331ad4e4eSTony Nguyen 	if (!status)
1564451f2c44STony Nguyen 		list_add(&(*prof)->l_entry, &hw->fl_profs[blk]);
156531ad4e4eSTony Nguyen 
156631ad4e4eSTony Nguyen 	mutex_unlock(&hw->fl_profs_locks[blk]);
156731ad4e4eSTony Nguyen 
156831ad4e4eSTony Nguyen 	return status;
156931ad4e4eSTony Nguyen }
157031ad4e4eSTony Nguyen 
1571c90ed40cSTony Nguyen /**
15722c61054cSTony Nguyen  * ice_flow_rem_prof - Remove a flow profile and all entries associated with it
15732c61054cSTony Nguyen  * @hw: pointer to the HW struct
15742c61054cSTony Nguyen  * @blk: the block for which the flow profile is to be removed
15752c61054cSTony Nguyen  * @prof_id: unique ID of the flow profile to be removed
15762c61054cSTony Nguyen  */
1577148beb61SHenry Tieman enum ice_status
15782c61054cSTony Nguyen ice_flow_rem_prof(struct ice_hw *hw, enum ice_block blk, u64 prof_id)
15792c61054cSTony Nguyen {
15802c61054cSTony Nguyen 	struct ice_flow_prof *prof;
15812c61054cSTony Nguyen 	enum ice_status status;
15822c61054cSTony Nguyen 
15832c61054cSTony Nguyen 	mutex_lock(&hw->fl_profs_locks[blk]);
15842c61054cSTony Nguyen 
15852c61054cSTony Nguyen 	prof = ice_flow_find_prof_id(hw, blk, prof_id);
15862c61054cSTony Nguyen 	if (!prof) {
15872c61054cSTony Nguyen 		status = ICE_ERR_DOES_NOT_EXIST;
15882c61054cSTony Nguyen 		goto out;
15892c61054cSTony Nguyen 	}
15902c61054cSTony Nguyen 
15912c61054cSTony Nguyen 	/* prof becomes invalid after the call */
15922c61054cSTony Nguyen 	status = ice_flow_rem_prof_sync(hw, blk, prof);
15932c61054cSTony Nguyen 
15942c61054cSTony Nguyen out:
15952c61054cSTony Nguyen 	mutex_unlock(&hw->fl_profs_locks[blk]);
15962c61054cSTony Nguyen 
15972c61054cSTony Nguyen 	return status;
15982c61054cSTony Nguyen }
15992c61054cSTony Nguyen 
16002c61054cSTony Nguyen /**
1601148beb61SHenry Tieman  * ice_flow_add_entry - Add a flow entry
1602148beb61SHenry Tieman  * @hw: pointer to the HW struct
1603148beb61SHenry Tieman  * @blk: classification stage
1604148beb61SHenry Tieman  * @prof_id: ID of the profile to add a new flow entry to
1605148beb61SHenry Tieman  * @entry_id: unique ID to identify this flow entry
1606148beb61SHenry Tieman  * @vsi_handle: software VSI handle for the flow entry
1607148beb61SHenry Tieman  * @prio: priority of the flow entry
1608148beb61SHenry Tieman  * @data: pointer to a data buffer containing flow entry's match values/masks
1609148beb61SHenry Tieman  * @entry_h: pointer to buffer that receives the new flow entry's handle
1610148beb61SHenry Tieman  */
1611148beb61SHenry Tieman enum ice_status
1612148beb61SHenry Tieman ice_flow_add_entry(struct ice_hw *hw, enum ice_block blk, u64 prof_id,
1613148beb61SHenry Tieman 		   u64 entry_id, u16 vsi_handle, enum ice_flow_priority prio,
1614148beb61SHenry Tieman 		   void *data, u64 *entry_h)
1615148beb61SHenry Tieman {
1616148beb61SHenry Tieman 	struct ice_flow_entry *e = NULL;
1617148beb61SHenry Tieman 	struct ice_flow_prof *prof;
1618148beb61SHenry Tieman 	enum ice_status status;
1619148beb61SHenry Tieman 
1620148beb61SHenry Tieman 	/* No flow entry data is expected for RSS */
1621148beb61SHenry Tieman 	if (!entry_h || (!data && blk != ICE_BLK_RSS))
1622148beb61SHenry Tieman 		return ICE_ERR_BAD_PTR;
1623148beb61SHenry Tieman 
1624148beb61SHenry Tieman 	if (!ice_is_vsi_valid(hw, vsi_handle))
1625148beb61SHenry Tieman 		return ICE_ERR_PARAM;
1626148beb61SHenry Tieman 
1627148beb61SHenry Tieman 	mutex_lock(&hw->fl_profs_locks[blk]);
1628148beb61SHenry Tieman 
1629148beb61SHenry Tieman 	prof = ice_flow_find_prof_id(hw, blk, prof_id);
1630148beb61SHenry Tieman 	if (!prof) {
1631148beb61SHenry Tieman 		status = ICE_ERR_DOES_NOT_EXIST;
1632148beb61SHenry Tieman 	} else {
1633148beb61SHenry Tieman 		/* Allocate memory for the entry being added and associate
1634148beb61SHenry Tieman 		 * the VSI to the found flow profile
1635148beb61SHenry Tieman 		 */
1636148beb61SHenry Tieman 		e = devm_kzalloc(ice_hw_to_dev(hw), sizeof(*e), GFP_KERNEL);
1637148beb61SHenry Tieman 		if (!e)
1638148beb61SHenry Tieman 			status = ICE_ERR_NO_MEMORY;
1639148beb61SHenry Tieman 		else
1640148beb61SHenry Tieman 			status = ice_flow_assoc_prof(hw, blk, prof, vsi_handle);
1641148beb61SHenry Tieman 	}
1642148beb61SHenry Tieman 
1643148beb61SHenry Tieman 	mutex_unlock(&hw->fl_profs_locks[blk]);
1644148beb61SHenry Tieman 	if (status)
1645148beb61SHenry Tieman 		goto out;
1646148beb61SHenry Tieman 
1647148beb61SHenry Tieman 	e->id = entry_id;
1648148beb61SHenry Tieman 	e->vsi_handle = vsi_handle;
1649148beb61SHenry Tieman 	e->prof = prof;
1650148beb61SHenry Tieman 	e->priority = prio;
1651148beb61SHenry Tieman 
1652148beb61SHenry Tieman 	switch (blk) {
1653148beb61SHenry Tieman 	case ICE_BLK_FD:
1654148beb61SHenry Tieman 	case ICE_BLK_RSS:
1655148beb61SHenry Tieman 		break;
1656148beb61SHenry Tieman 	default:
1657148beb61SHenry Tieman 		status = ICE_ERR_NOT_IMPL;
1658148beb61SHenry Tieman 		goto out;
1659148beb61SHenry Tieman 	}
1660148beb61SHenry Tieman 
1661148beb61SHenry Tieman 	mutex_lock(&prof->entries_lock);
1662148beb61SHenry Tieman 	list_add(&e->l_entry, &prof->entries);
1663148beb61SHenry Tieman 	mutex_unlock(&prof->entries_lock);
1664148beb61SHenry Tieman 
1665148beb61SHenry Tieman 	*entry_h = ICE_FLOW_ENTRY_HNDL(e);
1666148beb61SHenry Tieman 
1667148beb61SHenry Tieman out:
1668148beb61SHenry Tieman 	if (status && e) {
1669148beb61SHenry Tieman 		if (e->entry)
1670148beb61SHenry Tieman 			devm_kfree(ice_hw_to_dev(hw), e->entry);
1671148beb61SHenry Tieman 		devm_kfree(ice_hw_to_dev(hw), e);
1672148beb61SHenry Tieman 	}
1673148beb61SHenry Tieman 
1674148beb61SHenry Tieman 	return status;
1675148beb61SHenry Tieman }
1676148beb61SHenry Tieman 
1677148beb61SHenry Tieman /**
1678148beb61SHenry Tieman  * ice_flow_rem_entry - Remove a flow entry
1679148beb61SHenry Tieman  * @hw: pointer to the HW struct
1680148beb61SHenry Tieman  * @blk: classification stage
1681148beb61SHenry Tieman  * @entry_h: handle to the flow entry to be removed
1682148beb61SHenry Tieman  */
1683148beb61SHenry Tieman enum ice_status ice_flow_rem_entry(struct ice_hw *hw, enum ice_block blk,
1684148beb61SHenry Tieman 				   u64 entry_h)
1685148beb61SHenry Tieman {
1686148beb61SHenry Tieman 	struct ice_flow_entry *entry;
1687148beb61SHenry Tieman 	struct ice_flow_prof *prof;
1688148beb61SHenry Tieman 	enum ice_status status = 0;
1689148beb61SHenry Tieman 
1690148beb61SHenry Tieman 	if (entry_h == ICE_FLOW_ENTRY_HANDLE_INVAL)
1691148beb61SHenry Tieman 		return ICE_ERR_PARAM;
1692148beb61SHenry Tieman 
1693148beb61SHenry Tieman 	entry = ICE_FLOW_ENTRY_PTR(entry_h);
1694148beb61SHenry Tieman 
1695148beb61SHenry Tieman 	/* Retain the pointer to the flow profile as the entry will be freed */
1696148beb61SHenry Tieman 	prof = entry->prof;
1697148beb61SHenry Tieman 
1698148beb61SHenry Tieman 	if (prof) {
1699148beb61SHenry Tieman 		mutex_lock(&prof->entries_lock);
1700148beb61SHenry Tieman 		status = ice_flow_rem_entry_sync(hw, blk, entry);
1701148beb61SHenry Tieman 		mutex_unlock(&prof->entries_lock);
1702148beb61SHenry Tieman 	}
1703148beb61SHenry Tieman 
1704148beb61SHenry Tieman 	return status;
1705148beb61SHenry Tieman }
1706148beb61SHenry Tieman 
1707148beb61SHenry Tieman /**
1708c90ed40cSTony Nguyen  * ice_flow_set_fld_ext - specifies locations of field from entry's input buffer
1709c90ed40cSTony Nguyen  * @seg: packet segment the field being set belongs to
1710c90ed40cSTony Nguyen  * @fld: field to be set
17116dae8aa0SBruce Allan  * @field_type: type of the field
1712c90ed40cSTony Nguyen  * @val_loc: if not ICE_FLOW_FLD_OFF_INVAL, location of the value to match from
1713c90ed40cSTony Nguyen  *           entry's input buffer
1714c90ed40cSTony Nguyen  * @mask_loc: if not ICE_FLOW_FLD_OFF_INVAL, location of mask value from entry's
1715c90ed40cSTony Nguyen  *            input buffer
1716c90ed40cSTony Nguyen  * @last_loc: if not ICE_FLOW_FLD_OFF_INVAL, location of last/upper value from
1717c90ed40cSTony Nguyen  *            entry's input buffer
1718c90ed40cSTony Nguyen  *
1719c90ed40cSTony Nguyen  * This helper function stores information of a field being matched, including
1720c90ed40cSTony Nguyen  * the type of the field and the locations of the value to match, the mask, and
1721ac382a09SBruce Allan  * the upper-bound value in the start of the input buffer for a flow entry.
1722c90ed40cSTony Nguyen  * This function should only be used for fixed-size data structures.
1723c90ed40cSTony Nguyen  *
1724c90ed40cSTony Nguyen  * This function also opportunistically determines the protocol headers to be
1725c90ed40cSTony Nguyen  * present based on the fields being set. Some fields cannot be used alone to
1726c90ed40cSTony Nguyen  * determine the protocol headers present. Sometimes, fields for particular
1727c90ed40cSTony Nguyen  * protocol headers are not matched. In those cases, the protocol headers
1728c90ed40cSTony Nguyen  * must be explicitly set.
1729c90ed40cSTony Nguyen  */
1730c90ed40cSTony Nguyen static void
1731c90ed40cSTony Nguyen ice_flow_set_fld_ext(struct ice_flow_seg_info *seg, enum ice_flow_field fld,
17326dae8aa0SBruce Allan 		     enum ice_flow_fld_match_type field_type, u16 val_loc,
1733c90ed40cSTony Nguyen 		     u16 mask_loc, u16 last_loc)
1734c90ed40cSTony Nguyen {
1735c90ed40cSTony Nguyen 	u64 bit = BIT_ULL(fld);
1736c90ed40cSTony Nguyen 
1737c90ed40cSTony Nguyen 	seg->match |= bit;
17386dae8aa0SBruce Allan 	if (field_type == ICE_FLOW_FLD_TYPE_RANGE)
1739c90ed40cSTony Nguyen 		seg->range |= bit;
1740c90ed40cSTony Nguyen 
17416dae8aa0SBruce Allan 	seg->fields[fld].type = field_type;
1742c90ed40cSTony Nguyen 	seg->fields[fld].src.val = val_loc;
1743c90ed40cSTony Nguyen 	seg->fields[fld].src.mask = mask_loc;
1744c90ed40cSTony Nguyen 	seg->fields[fld].src.last = last_loc;
1745c90ed40cSTony Nguyen 
1746c90ed40cSTony Nguyen 	ICE_FLOW_SET_HDRS(seg, ice_flds_info[fld].hdr);
1747c90ed40cSTony Nguyen }
1748c90ed40cSTony Nguyen 
1749c90ed40cSTony Nguyen /**
1750c90ed40cSTony Nguyen  * ice_flow_set_fld - specifies locations of field from entry's input buffer
1751c90ed40cSTony Nguyen  * @seg: packet segment the field being set belongs to
1752c90ed40cSTony Nguyen  * @fld: field to be set
1753c90ed40cSTony Nguyen  * @val_loc: if not ICE_FLOW_FLD_OFF_INVAL, location of the value to match from
1754c90ed40cSTony Nguyen  *           entry's input buffer
1755c90ed40cSTony Nguyen  * @mask_loc: if not ICE_FLOW_FLD_OFF_INVAL, location of mask value from entry's
1756c90ed40cSTony Nguyen  *            input buffer
1757c90ed40cSTony Nguyen  * @last_loc: if not ICE_FLOW_FLD_OFF_INVAL, location of last/upper value from
1758c90ed40cSTony Nguyen  *            entry's input buffer
1759c90ed40cSTony Nguyen  * @range: indicate if field being matched is to be in a range
1760c90ed40cSTony Nguyen  *
1761c90ed40cSTony Nguyen  * This function specifies the locations, in the form of byte offsets from the
1762c90ed40cSTony Nguyen  * start of the input buffer for a flow entry, from where the value to match,
1763c90ed40cSTony Nguyen  * the mask value, and upper value can be extracted. These locations are then
1764c90ed40cSTony Nguyen  * stored in the flow profile. When adding a flow entry associated with the
1765c90ed40cSTony Nguyen  * flow profile, these locations will be used to quickly extract the values and
1766c90ed40cSTony Nguyen  * create the content of a match entry. This function should only be used for
1767c90ed40cSTony Nguyen  * fixed-size data structures.
1768c90ed40cSTony Nguyen  */
1769148beb61SHenry Tieman void
1770c90ed40cSTony Nguyen ice_flow_set_fld(struct ice_flow_seg_info *seg, enum ice_flow_field fld,
1771c90ed40cSTony Nguyen 		 u16 val_loc, u16 mask_loc, u16 last_loc, bool range)
1772c90ed40cSTony Nguyen {
1773c90ed40cSTony Nguyen 	enum ice_flow_fld_match_type t = range ?
1774c90ed40cSTony Nguyen 		ICE_FLOW_FLD_TYPE_RANGE : ICE_FLOW_FLD_TYPE_REG;
1775c90ed40cSTony Nguyen 
1776c90ed40cSTony Nguyen 	ice_flow_set_fld_ext(seg, fld, t, val_loc, mask_loc, last_loc);
1777c90ed40cSTony Nguyen }
1778c90ed40cSTony Nguyen 
17792c57ffcbSHenry Tieman /**
17802c57ffcbSHenry Tieman  * ice_flow_add_fld_raw - sets locations of a raw field from entry's input buf
17812c57ffcbSHenry Tieman  * @seg: packet segment the field being set belongs to
17822c57ffcbSHenry Tieman  * @off: offset of the raw field from the beginning of the segment in bytes
17832c57ffcbSHenry Tieman  * @len: length of the raw pattern to be matched
17842c57ffcbSHenry Tieman  * @val_loc: location of the value to match from entry's input buffer
17852c57ffcbSHenry Tieman  * @mask_loc: location of mask value from entry's input buffer
17862c57ffcbSHenry Tieman  *
17872c57ffcbSHenry Tieman  * This function specifies the offset of the raw field to be match from the
17882c57ffcbSHenry Tieman  * beginning of the specified packet segment, and the locations, in the form of
17892c57ffcbSHenry Tieman  * byte offsets from the start of the input buffer for a flow entry, from where
17902c57ffcbSHenry Tieman  * the value to match and the mask value to be extracted. These locations are
17912c57ffcbSHenry Tieman  * then stored in the flow profile. When adding flow entries to the associated
17922c57ffcbSHenry Tieman  * flow profile, these locations can be used to quickly extract the values to
17932c57ffcbSHenry Tieman  * create the content of a match entry. This function should only be used for
17942c57ffcbSHenry Tieman  * fixed-size data structures.
17952c57ffcbSHenry Tieman  */
17962c57ffcbSHenry Tieman void
17972c57ffcbSHenry Tieman ice_flow_add_fld_raw(struct ice_flow_seg_info *seg, u16 off, u8 len,
17982c57ffcbSHenry Tieman 		     u16 val_loc, u16 mask_loc)
17992c57ffcbSHenry Tieman {
18002c57ffcbSHenry Tieman 	if (seg->raws_cnt < ICE_FLOW_SEG_RAW_FLD_MAX) {
18012c57ffcbSHenry Tieman 		seg->raws[seg->raws_cnt].off = off;
18022c57ffcbSHenry Tieman 		seg->raws[seg->raws_cnt].info.type = ICE_FLOW_FLD_TYPE_SIZE;
18032c57ffcbSHenry Tieman 		seg->raws[seg->raws_cnt].info.src.val = val_loc;
18042c57ffcbSHenry Tieman 		seg->raws[seg->raws_cnt].info.src.mask = mask_loc;
18052c57ffcbSHenry Tieman 		/* The "last" field is used to store the length of the field */
18062c57ffcbSHenry Tieman 		seg->raws[seg->raws_cnt].info.src.last = len;
18072c57ffcbSHenry Tieman 	}
18082c57ffcbSHenry Tieman 
18092c57ffcbSHenry Tieman 	/* Overflows of "raws" will be handled as an error condition later in
18102c57ffcbSHenry Tieman 	 * the flow when this information is processed.
18112c57ffcbSHenry Tieman 	 */
18122c57ffcbSHenry Tieman 	seg->raws_cnt++;
18132c57ffcbSHenry Tieman }
18142c57ffcbSHenry Tieman 
1815390bd141SQi Zhang #define ICE_FLOW_RSS_SEG_HDR_L2_MASKS \
1816390bd141SQi Zhang 	(ICE_FLOW_SEG_HDR_ETH | ICE_FLOW_SEG_HDR_VLAN)
1817390bd141SQi Zhang 
1818c90ed40cSTony Nguyen #define ICE_FLOW_RSS_SEG_HDR_L3_MASKS \
1819c90ed40cSTony Nguyen 	(ICE_FLOW_SEG_HDR_IPV4 | ICE_FLOW_SEG_HDR_IPV6)
1820c90ed40cSTony Nguyen 
1821c90ed40cSTony Nguyen #define ICE_FLOW_RSS_SEG_HDR_L4_MASKS \
1822c90ed40cSTony Nguyen 	(ICE_FLOW_SEG_HDR_TCP | ICE_FLOW_SEG_HDR_UDP | ICE_FLOW_SEG_HDR_SCTP)
1823c90ed40cSTony Nguyen 
1824c90ed40cSTony Nguyen #define ICE_FLOW_RSS_SEG_HDR_VAL_MASKS \
1825390bd141SQi Zhang 	(ICE_FLOW_RSS_SEG_HDR_L2_MASKS | \
1826390bd141SQi Zhang 	 ICE_FLOW_RSS_SEG_HDR_L3_MASKS | \
1827c90ed40cSTony Nguyen 	 ICE_FLOW_RSS_SEG_HDR_L4_MASKS)
1828c90ed40cSTony Nguyen 
1829c90ed40cSTony Nguyen /**
1830c90ed40cSTony Nguyen  * ice_flow_set_rss_seg_info - setup packet segments for RSS
1831c90ed40cSTony Nguyen  * @segs: pointer to the flow field segment(s)
1832c90ed40cSTony Nguyen  * @hash_fields: fields to be hashed on for the segment(s)
1833c90ed40cSTony Nguyen  * @flow_hdr: protocol header fields within a packet segment
1834c90ed40cSTony Nguyen  *
1835c90ed40cSTony Nguyen  * Helper function to extract fields from hash bitmap and use flow
1836c90ed40cSTony Nguyen  * header value to set flow field segment for further use in flow
1837c90ed40cSTony Nguyen  * profile entry or removal.
1838c90ed40cSTony Nguyen  */
1839c90ed40cSTony Nguyen static enum ice_status
1840c90ed40cSTony Nguyen ice_flow_set_rss_seg_info(struct ice_flow_seg_info *segs, u64 hash_fields,
1841c90ed40cSTony Nguyen 			  u32 flow_hdr)
1842c90ed40cSTony Nguyen {
1843c90ed40cSTony Nguyen 	u64 val;
1844c90ed40cSTony Nguyen 	u8 i;
1845c90ed40cSTony Nguyen 
1846c90ed40cSTony Nguyen 	for_each_set_bit(i, (unsigned long *)&hash_fields,
1847c90ed40cSTony Nguyen 			 ICE_FLOW_FIELD_IDX_MAX)
1848c90ed40cSTony Nguyen 		ice_flow_set_fld(segs, (enum ice_flow_field)i,
1849c90ed40cSTony Nguyen 				 ICE_FLOW_FLD_OFF_INVAL, ICE_FLOW_FLD_OFF_INVAL,
1850c90ed40cSTony Nguyen 				 ICE_FLOW_FLD_OFF_INVAL, false);
1851c90ed40cSTony Nguyen 
1852c90ed40cSTony Nguyen 	ICE_FLOW_SET_HDRS(segs, flow_hdr);
1853c90ed40cSTony Nguyen 
18540577313eSQi Zhang 	if (segs->hdrs & ~ICE_FLOW_RSS_SEG_HDR_VAL_MASKS &
18557012dfd1SQi Zhang 	    ~ICE_FLOW_RSS_HDRS_INNER_MASK & ~ICE_FLOW_SEG_HDR_IPV_OTHER)
1856c90ed40cSTony Nguyen 		return ICE_ERR_PARAM;
1857c90ed40cSTony Nguyen 
1858c90ed40cSTony Nguyen 	val = (u64)(segs->hdrs & ICE_FLOW_RSS_SEG_HDR_L3_MASKS);
1859c90ed40cSTony Nguyen 	if (val && !is_power_of_2(val))
1860c90ed40cSTony Nguyen 		return ICE_ERR_CFG;
1861c90ed40cSTony Nguyen 
1862c90ed40cSTony Nguyen 	val = (u64)(segs->hdrs & ICE_FLOW_RSS_SEG_HDR_L4_MASKS);
1863c90ed40cSTony Nguyen 	if (val && !is_power_of_2(val))
1864c90ed40cSTony Nguyen 		return ICE_ERR_CFG;
1865c90ed40cSTony Nguyen 
1866c90ed40cSTony Nguyen 	return 0;
1867c90ed40cSTony Nguyen }
1868c90ed40cSTony Nguyen 
18692c61054cSTony Nguyen /**
18702c61054cSTony Nguyen  * ice_rem_vsi_rss_list - remove VSI from RSS list
18712c61054cSTony Nguyen  * @hw: pointer to the hardware structure
18722c61054cSTony Nguyen  * @vsi_handle: software VSI handle
18732c61054cSTony Nguyen  *
18742c61054cSTony Nguyen  * Remove the VSI from all RSS configurations in the list.
18752c61054cSTony Nguyen  */
18762c61054cSTony Nguyen void ice_rem_vsi_rss_list(struct ice_hw *hw, u16 vsi_handle)
18772c61054cSTony Nguyen {
18782c61054cSTony Nguyen 	struct ice_rss_cfg *r, *tmp;
18792c61054cSTony Nguyen 
18802c61054cSTony Nguyen 	if (list_empty(&hw->rss_list_head))
18812c61054cSTony Nguyen 		return;
18822c61054cSTony Nguyen 
18832c61054cSTony Nguyen 	mutex_lock(&hw->rss_locks);
18842c61054cSTony Nguyen 	list_for_each_entry_safe(r, tmp, &hw->rss_list_head, l_entry)
18852c61054cSTony Nguyen 		if (test_and_clear_bit(vsi_handle, r->vsis))
18862c61054cSTony Nguyen 			if (bitmap_empty(r->vsis, ICE_MAX_VSI)) {
18872c61054cSTony Nguyen 				list_del(&r->l_entry);
18882c61054cSTony Nguyen 				devm_kfree(ice_hw_to_dev(hw), r);
18892c61054cSTony Nguyen 			}
18902c61054cSTony Nguyen 	mutex_unlock(&hw->rss_locks);
18912c61054cSTony Nguyen }
18922c61054cSTony Nguyen 
18932c61054cSTony Nguyen /**
18942c61054cSTony Nguyen  * ice_rem_vsi_rss_cfg - remove RSS configurations associated with VSI
18952c61054cSTony Nguyen  * @hw: pointer to the hardware structure
18962c61054cSTony Nguyen  * @vsi_handle: software VSI handle
18972c61054cSTony Nguyen  *
18982c61054cSTony Nguyen  * This function will iterate through all flow profiles and disassociate
18992c61054cSTony Nguyen  * the VSI from that profile. If the flow profile has no VSIs it will
19002c61054cSTony Nguyen  * be removed.
19012c61054cSTony Nguyen  */
19022c61054cSTony Nguyen enum ice_status ice_rem_vsi_rss_cfg(struct ice_hw *hw, u16 vsi_handle)
19032c61054cSTony Nguyen {
19042c61054cSTony Nguyen 	const enum ice_block blk = ICE_BLK_RSS;
19052c61054cSTony Nguyen 	struct ice_flow_prof *p, *t;
19062c61054cSTony Nguyen 	enum ice_status status = 0;
19072c61054cSTony Nguyen 
19082c61054cSTony Nguyen 	if (!ice_is_vsi_valid(hw, vsi_handle))
19092c61054cSTony Nguyen 		return ICE_ERR_PARAM;
19102c61054cSTony Nguyen 
19112c61054cSTony Nguyen 	if (list_empty(&hw->fl_profs[blk]))
19122c61054cSTony Nguyen 		return 0;
19132c61054cSTony Nguyen 
1914cdedbab9SVignesh Sridhar 	mutex_lock(&hw->rss_locks);
19152c61054cSTony Nguyen 	list_for_each_entry_safe(p, t, &hw->fl_profs[blk], l_entry)
19162c61054cSTony Nguyen 		if (test_bit(vsi_handle, p->vsis)) {
19172c61054cSTony Nguyen 			status = ice_flow_disassoc_prof(hw, blk, p, vsi_handle);
19182c61054cSTony Nguyen 			if (status)
19192c61054cSTony Nguyen 				break;
19202c61054cSTony Nguyen 
19212c61054cSTony Nguyen 			if (bitmap_empty(p->vsis, ICE_MAX_VSI)) {
1922cdedbab9SVignesh Sridhar 				status = ice_flow_rem_prof(hw, blk, p->id);
19232c61054cSTony Nguyen 				if (status)
19242c61054cSTony Nguyen 					break;
19252c61054cSTony Nguyen 			}
19262c61054cSTony Nguyen 		}
1927cdedbab9SVignesh Sridhar 	mutex_unlock(&hw->rss_locks);
19282c61054cSTony Nguyen 
19292c61054cSTony Nguyen 	return status;
19302c61054cSTony Nguyen }
19312c61054cSTony Nguyen 
19322c61054cSTony Nguyen /**
19332c61054cSTony Nguyen  * ice_rem_rss_list - remove RSS configuration from list
19342c61054cSTony Nguyen  * @hw: pointer to the hardware structure
19352c61054cSTony Nguyen  * @vsi_handle: software VSI handle
19362c61054cSTony Nguyen  * @prof: pointer to flow profile
19372c61054cSTony Nguyen  *
19382c61054cSTony Nguyen  * Assumption: lock has already been acquired for RSS list
19392c61054cSTony Nguyen  */
19402c61054cSTony Nguyen static void
19412c61054cSTony Nguyen ice_rem_rss_list(struct ice_hw *hw, u16 vsi_handle, struct ice_flow_prof *prof)
19422c61054cSTony Nguyen {
19432c61054cSTony Nguyen 	struct ice_rss_cfg *r, *tmp;
19442c61054cSTony Nguyen 
19452c61054cSTony Nguyen 	/* Search for RSS hash fields associated to the VSI that match the
19462c61054cSTony Nguyen 	 * hash configurations associated to the flow profile. If found
19472c61054cSTony Nguyen 	 * remove from the RSS entry list of the VSI context and delete entry.
19482c61054cSTony Nguyen 	 */
19492c61054cSTony Nguyen 	list_for_each_entry_safe(r, tmp, &hw->rss_list_head, l_entry)
19502c61054cSTony Nguyen 		if (r->hashed_flds == prof->segs[prof->segs_cnt - 1].match &&
19512c61054cSTony Nguyen 		    r->packet_hdr == prof->segs[prof->segs_cnt - 1].hdrs) {
19522c61054cSTony Nguyen 			clear_bit(vsi_handle, r->vsis);
19532c61054cSTony Nguyen 			if (bitmap_empty(r->vsis, ICE_MAX_VSI)) {
19542c61054cSTony Nguyen 				list_del(&r->l_entry);
19552c61054cSTony Nguyen 				devm_kfree(ice_hw_to_dev(hw), r);
19562c61054cSTony Nguyen 			}
19572c61054cSTony Nguyen 			return;
19582c61054cSTony Nguyen 		}
19592c61054cSTony Nguyen }
19602c61054cSTony Nguyen 
19612c61054cSTony Nguyen /**
19622c61054cSTony Nguyen  * ice_add_rss_list - add RSS configuration to list
19632c61054cSTony Nguyen  * @hw: pointer to the hardware structure
19642c61054cSTony Nguyen  * @vsi_handle: software VSI handle
19652c61054cSTony Nguyen  * @prof: pointer to flow profile
19662c61054cSTony Nguyen  *
19672c61054cSTony Nguyen  * Assumption: lock has already been acquired for RSS list
19682c61054cSTony Nguyen  */
19692c61054cSTony Nguyen static enum ice_status
19702c61054cSTony Nguyen ice_add_rss_list(struct ice_hw *hw, u16 vsi_handle, struct ice_flow_prof *prof)
19712c61054cSTony Nguyen {
19722c61054cSTony Nguyen 	struct ice_rss_cfg *r, *rss_cfg;
19732c61054cSTony Nguyen 
19742c61054cSTony Nguyen 	list_for_each_entry(r, &hw->rss_list_head, l_entry)
19752c61054cSTony Nguyen 		if (r->hashed_flds == prof->segs[prof->segs_cnt - 1].match &&
19762c61054cSTony Nguyen 		    r->packet_hdr == prof->segs[prof->segs_cnt - 1].hdrs) {
19772c61054cSTony Nguyen 			set_bit(vsi_handle, r->vsis);
19782c61054cSTony Nguyen 			return 0;
19792c61054cSTony Nguyen 		}
19802c61054cSTony Nguyen 
19812c61054cSTony Nguyen 	rss_cfg = devm_kzalloc(ice_hw_to_dev(hw), sizeof(*rss_cfg),
19822c61054cSTony Nguyen 			       GFP_KERNEL);
19832c61054cSTony Nguyen 	if (!rss_cfg)
19842c61054cSTony Nguyen 		return ICE_ERR_NO_MEMORY;
19852c61054cSTony Nguyen 
19862c61054cSTony Nguyen 	rss_cfg->hashed_flds = prof->segs[prof->segs_cnt - 1].match;
19872c61054cSTony Nguyen 	rss_cfg->packet_hdr = prof->segs[prof->segs_cnt - 1].hdrs;
19882c61054cSTony Nguyen 	set_bit(vsi_handle, rss_cfg->vsis);
19892c61054cSTony Nguyen 
19902c61054cSTony Nguyen 	list_add_tail(&rss_cfg->l_entry, &hw->rss_list_head);
19912c61054cSTony Nguyen 
19922c61054cSTony Nguyen 	return 0;
19932c61054cSTony Nguyen }
19942c61054cSTony Nguyen 
199531ad4e4eSTony Nguyen #define ICE_FLOW_PROF_HASH_S	0
199631ad4e4eSTony Nguyen #define ICE_FLOW_PROF_HASH_M	(0xFFFFFFFFULL << ICE_FLOW_PROF_HASH_S)
199731ad4e4eSTony Nguyen #define ICE_FLOW_PROF_HDR_S	32
199831ad4e4eSTony Nguyen #define ICE_FLOW_PROF_HDR_M	(0x3FFFFFFFULL << ICE_FLOW_PROF_HDR_S)
199931ad4e4eSTony Nguyen #define ICE_FLOW_PROF_ENCAP_S	63
200031ad4e4eSTony Nguyen #define ICE_FLOW_PROF_ENCAP_M	(BIT_ULL(ICE_FLOW_PROF_ENCAP_S))
200131ad4e4eSTony Nguyen 
2002c90ed40cSTony Nguyen #define ICE_RSS_OUTER_HEADERS	1
2003a4e82a81STony Nguyen #define ICE_RSS_INNER_HEADERS	2
2004c90ed40cSTony Nguyen 
200531ad4e4eSTony Nguyen /* Flow profile ID format:
200631ad4e4eSTony Nguyen  * [0:31] - Packet match fields
200731ad4e4eSTony Nguyen  * [32:62] - Protocol header
200831ad4e4eSTony Nguyen  * [63] - Encapsulation flag, 0 if non-tunneled, 1 if tunneled
200931ad4e4eSTony Nguyen  */
201031ad4e4eSTony Nguyen #define ICE_FLOW_GEN_PROFID(hash, hdr, segs_cnt) \
201131ad4e4eSTony Nguyen 	(u64)(((u64)(hash) & ICE_FLOW_PROF_HASH_M) | \
201231ad4e4eSTony Nguyen 	      (((u64)(hdr) << ICE_FLOW_PROF_HDR_S) & ICE_FLOW_PROF_HDR_M) | \
201331ad4e4eSTony Nguyen 	      ((u8)((segs_cnt) - 1) ? ICE_FLOW_PROF_ENCAP_M : 0))
201431ad4e4eSTony Nguyen 
2015c90ed40cSTony Nguyen /**
2016c90ed40cSTony Nguyen  * ice_add_rss_cfg_sync - add an RSS configuration
201731ad4e4eSTony Nguyen  * @hw: pointer to the hardware structure
2018451f2c44STony Nguyen  * @vsi_handle: software VSI handle
2019c90ed40cSTony Nguyen  * @hashed_flds: hash bit fields (ICE_FLOW_HASH_*) to configure
2020c90ed40cSTony Nguyen  * @addl_hdrs: protocol header fields
2021c90ed40cSTony Nguyen  * @segs_cnt: packet segment count
2022c90ed40cSTony Nguyen  *
2023c90ed40cSTony Nguyen  * Assumption: lock has already been acquired for RSS list
2024c90ed40cSTony Nguyen  */
2025c90ed40cSTony Nguyen static enum ice_status
2026451f2c44STony Nguyen ice_add_rss_cfg_sync(struct ice_hw *hw, u16 vsi_handle, u64 hashed_flds,
2027451f2c44STony Nguyen 		     u32 addl_hdrs, u8 segs_cnt)
2028c90ed40cSTony Nguyen {
2029451f2c44STony Nguyen 	const enum ice_block blk = ICE_BLK_RSS;
2030451f2c44STony Nguyen 	struct ice_flow_prof *prof = NULL;
2031c90ed40cSTony Nguyen 	struct ice_flow_seg_info *segs;
2032c90ed40cSTony Nguyen 	enum ice_status status;
2033c90ed40cSTony Nguyen 
2034c90ed40cSTony Nguyen 	if (!segs_cnt || segs_cnt > ICE_FLOW_SEG_MAX)
2035c90ed40cSTony Nguyen 		return ICE_ERR_PARAM;
2036c90ed40cSTony Nguyen 
2037c90ed40cSTony Nguyen 	segs = kcalloc(segs_cnt, sizeof(*segs), GFP_KERNEL);
2038c90ed40cSTony Nguyen 	if (!segs)
2039c90ed40cSTony Nguyen 		return ICE_ERR_NO_MEMORY;
2040c90ed40cSTony Nguyen 
2041c90ed40cSTony Nguyen 	/* Construct the packet segment info from the hashed fields */
2042c90ed40cSTony Nguyen 	status = ice_flow_set_rss_seg_info(&segs[segs_cnt - 1], hashed_flds,
2043c90ed40cSTony Nguyen 					   addl_hdrs);
204431ad4e4eSTony Nguyen 	if (status)
204531ad4e4eSTony Nguyen 		goto exit;
2046c90ed40cSTony Nguyen 
20472c61054cSTony Nguyen 	/* Search for a flow profile that has matching headers, hash fields
20482c61054cSTony Nguyen 	 * and has the input VSI associated to it. If found, no further
20492c61054cSTony Nguyen 	 * operations required and exit.
20502c61054cSTony Nguyen 	 */
20512c61054cSTony Nguyen 	prof = ice_flow_find_prof_conds(hw, blk, ICE_FLOW_RX, segs, segs_cnt,
20522c61054cSTony Nguyen 					vsi_handle,
20532c61054cSTony Nguyen 					ICE_FLOW_FIND_PROF_CHK_FLDS |
20542c61054cSTony Nguyen 					ICE_FLOW_FIND_PROF_CHK_VSI);
20552c61054cSTony Nguyen 	if (prof)
20562c61054cSTony Nguyen 		goto exit;
20572c61054cSTony Nguyen 
20582c61054cSTony Nguyen 	/* Check if a flow profile exists with the same protocol headers and
20592c61054cSTony Nguyen 	 * associated with the input VSI. If so disassociate the VSI from
20602c61054cSTony Nguyen 	 * this profile. The VSI will be added to a new profile created with
20612c61054cSTony Nguyen 	 * the protocol header and new hash field configuration.
20622c61054cSTony Nguyen 	 */
20632c61054cSTony Nguyen 	prof = ice_flow_find_prof_conds(hw, blk, ICE_FLOW_RX, segs, segs_cnt,
20642c61054cSTony Nguyen 					vsi_handle, ICE_FLOW_FIND_PROF_CHK_VSI);
20652c61054cSTony Nguyen 	if (prof) {
20662c61054cSTony Nguyen 		status = ice_flow_disassoc_prof(hw, blk, prof, vsi_handle);
20672c61054cSTony Nguyen 		if (!status)
20682c61054cSTony Nguyen 			ice_rem_rss_list(hw, vsi_handle, prof);
20692c61054cSTony Nguyen 		else
20702c61054cSTony Nguyen 			goto exit;
20712c61054cSTony Nguyen 
20722c61054cSTony Nguyen 		/* Remove profile if it has no VSIs associated */
20732c61054cSTony Nguyen 		if (bitmap_empty(prof->vsis, ICE_MAX_VSI)) {
20742c61054cSTony Nguyen 			status = ice_flow_rem_prof(hw, blk, prof->id);
20752c61054cSTony Nguyen 			if (status)
20762c61054cSTony Nguyen 				goto exit;
20772c61054cSTony Nguyen 		}
20782c61054cSTony Nguyen 	}
20792c61054cSTony Nguyen 
20802c61054cSTony Nguyen 	/* Search for a profile that has same match fields only. If this
20812c61054cSTony Nguyen 	 * exists then associate the VSI to this profile.
20822c61054cSTony Nguyen 	 */
20832c61054cSTony Nguyen 	prof = ice_flow_find_prof_conds(hw, blk, ICE_FLOW_RX, segs, segs_cnt,
20842c61054cSTony Nguyen 					vsi_handle,
20852c61054cSTony Nguyen 					ICE_FLOW_FIND_PROF_CHK_FLDS);
20862c61054cSTony Nguyen 	if (prof) {
20872c61054cSTony Nguyen 		status = ice_flow_assoc_prof(hw, blk, prof, vsi_handle);
20882c61054cSTony Nguyen 		if (!status)
20892c61054cSTony Nguyen 			status = ice_add_rss_list(hw, vsi_handle, prof);
20902c61054cSTony Nguyen 		goto exit;
20912c61054cSTony Nguyen 	}
20922c61054cSTony Nguyen 
209331ad4e4eSTony Nguyen 	/* Create a new flow profile with generated profile and packet
209431ad4e4eSTony Nguyen 	 * segment information.
209531ad4e4eSTony Nguyen 	 */
2096451f2c44STony Nguyen 	status = ice_flow_add_prof(hw, blk, ICE_FLOW_RX,
209731ad4e4eSTony Nguyen 				   ICE_FLOW_GEN_PROFID(hashed_flds,
209831ad4e4eSTony Nguyen 						       segs[segs_cnt - 1].hdrs,
209931ad4e4eSTony Nguyen 						       segs_cnt),
2100451f2c44STony Nguyen 				   segs, segs_cnt, &prof);
2101451f2c44STony Nguyen 	if (status)
2102451f2c44STony Nguyen 		goto exit;
2103451f2c44STony Nguyen 
2104451f2c44STony Nguyen 	status = ice_flow_assoc_prof(hw, blk, prof, vsi_handle);
21052c61054cSTony Nguyen 	/* If association to a new flow profile failed then this profile can
21062c61054cSTony Nguyen 	 * be removed.
21072c61054cSTony Nguyen 	 */
21082c61054cSTony Nguyen 	if (status) {
21092c61054cSTony Nguyen 		ice_flow_rem_prof(hw, blk, prof->id);
21102c61054cSTony Nguyen 		goto exit;
21112c61054cSTony Nguyen 	}
21122c61054cSTony Nguyen 
21132c61054cSTony Nguyen 	status = ice_add_rss_list(hw, vsi_handle, prof);
211431ad4e4eSTony Nguyen 
211531ad4e4eSTony Nguyen exit:
2116c90ed40cSTony Nguyen 	kfree(segs);
2117c90ed40cSTony Nguyen 	return status;
2118c90ed40cSTony Nguyen }
2119c90ed40cSTony Nguyen 
2120c90ed40cSTony Nguyen /**
2121c90ed40cSTony Nguyen  * ice_add_rss_cfg - add an RSS configuration with specified hashed fields
2122c90ed40cSTony Nguyen  * @hw: pointer to the hardware structure
2123c90ed40cSTony Nguyen  * @vsi_handle: software VSI handle
2124c90ed40cSTony Nguyen  * @hashed_flds: hash bit fields (ICE_FLOW_HASH_*) to configure
2125c90ed40cSTony Nguyen  * @addl_hdrs: protocol header fields
2126c90ed40cSTony Nguyen  *
2127c90ed40cSTony Nguyen  * This function will generate a flow profile based on fields associated with
2128c90ed40cSTony Nguyen  * the input fields to hash on, the flow type and use the VSI number to add
2129c90ed40cSTony Nguyen  * a flow entry to the profile.
2130c90ed40cSTony Nguyen  */
2131c90ed40cSTony Nguyen enum ice_status
2132c90ed40cSTony Nguyen ice_add_rss_cfg(struct ice_hw *hw, u16 vsi_handle, u64 hashed_flds,
2133c90ed40cSTony Nguyen 		u32 addl_hdrs)
2134c90ed40cSTony Nguyen {
2135c90ed40cSTony Nguyen 	enum ice_status status;
2136c90ed40cSTony Nguyen 
2137c90ed40cSTony Nguyen 	if (hashed_flds == ICE_HASH_INVALID ||
2138c90ed40cSTony Nguyen 	    !ice_is_vsi_valid(hw, vsi_handle))
2139c90ed40cSTony Nguyen 		return ICE_ERR_PARAM;
2140c90ed40cSTony Nguyen 
2141c90ed40cSTony Nguyen 	mutex_lock(&hw->rss_locks);
2142451f2c44STony Nguyen 	status = ice_add_rss_cfg_sync(hw, vsi_handle, hashed_flds, addl_hdrs,
2143c90ed40cSTony Nguyen 				      ICE_RSS_OUTER_HEADERS);
2144a4e82a81STony Nguyen 	if (!status)
2145a4e82a81STony Nguyen 		status = ice_add_rss_cfg_sync(hw, vsi_handle, hashed_flds,
2146a4e82a81STony Nguyen 					      addl_hdrs, ICE_RSS_INNER_HEADERS);
2147c90ed40cSTony Nguyen 	mutex_unlock(&hw->rss_locks);
2148c90ed40cSTony Nguyen 
2149c90ed40cSTony Nguyen 	return status;
2150c90ed40cSTony Nguyen }
2151c90ed40cSTony Nguyen 
21521c01c8c6SMd Fahad Iqbal Polash /* Mapping of AVF hash bit fields to an L3-L4 hash combination.
21531c01c8c6SMd Fahad Iqbal Polash  * As the ice_flow_avf_hdr_field represent individual bit shifts in a hash,
21541c01c8c6SMd Fahad Iqbal Polash  * convert its values to their appropriate flow L3, L4 values.
21551c01c8c6SMd Fahad Iqbal Polash  */
21561c01c8c6SMd Fahad Iqbal Polash #define ICE_FLOW_AVF_RSS_IPV4_MASKS \
21571c01c8c6SMd Fahad Iqbal Polash 	(BIT_ULL(ICE_AVF_FLOW_FIELD_IPV4_OTHER) | \
21581c01c8c6SMd Fahad Iqbal Polash 	 BIT_ULL(ICE_AVF_FLOW_FIELD_FRAG_IPV4))
21591c01c8c6SMd Fahad Iqbal Polash #define ICE_FLOW_AVF_RSS_TCP_IPV4_MASKS \
21601c01c8c6SMd Fahad Iqbal Polash 	(BIT_ULL(ICE_AVF_FLOW_FIELD_IPV4_TCP_SYN_NO_ACK) | \
21611c01c8c6SMd Fahad Iqbal Polash 	 BIT_ULL(ICE_AVF_FLOW_FIELD_IPV4_TCP))
21621c01c8c6SMd Fahad Iqbal Polash #define ICE_FLOW_AVF_RSS_UDP_IPV4_MASKS \
21631c01c8c6SMd Fahad Iqbal Polash 	(BIT_ULL(ICE_AVF_FLOW_FIELD_UNICAST_IPV4_UDP) | \
21641c01c8c6SMd Fahad Iqbal Polash 	 BIT_ULL(ICE_AVF_FLOW_FIELD_MULTICAST_IPV4_UDP) | \
21651c01c8c6SMd Fahad Iqbal Polash 	 BIT_ULL(ICE_AVF_FLOW_FIELD_IPV4_UDP))
21661c01c8c6SMd Fahad Iqbal Polash #define ICE_FLOW_AVF_RSS_ALL_IPV4_MASKS \
21671c01c8c6SMd Fahad Iqbal Polash 	(ICE_FLOW_AVF_RSS_TCP_IPV4_MASKS | ICE_FLOW_AVF_RSS_UDP_IPV4_MASKS | \
21681c01c8c6SMd Fahad Iqbal Polash 	 ICE_FLOW_AVF_RSS_IPV4_MASKS | BIT_ULL(ICE_AVF_FLOW_FIELD_IPV4_SCTP))
21691c01c8c6SMd Fahad Iqbal Polash 
21701c01c8c6SMd Fahad Iqbal Polash #define ICE_FLOW_AVF_RSS_IPV6_MASKS \
21711c01c8c6SMd Fahad Iqbal Polash 	(BIT_ULL(ICE_AVF_FLOW_FIELD_IPV6_OTHER) | \
21721c01c8c6SMd Fahad Iqbal Polash 	 BIT_ULL(ICE_AVF_FLOW_FIELD_FRAG_IPV6))
21731c01c8c6SMd Fahad Iqbal Polash #define ICE_FLOW_AVF_RSS_UDP_IPV6_MASKS \
21741c01c8c6SMd Fahad Iqbal Polash 	(BIT_ULL(ICE_AVF_FLOW_FIELD_UNICAST_IPV6_UDP) | \
21751c01c8c6SMd Fahad Iqbal Polash 	 BIT_ULL(ICE_AVF_FLOW_FIELD_MULTICAST_IPV6_UDP) | \
21761c01c8c6SMd Fahad Iqbal Polash 	 BIT_ULL(ICE_AVF_FLOW_FIELD_IPV6_UDP))
21771c01c8c6SMd Fahad Iqbal Polash #define ICE_FLOW_AVF_RSS_TCP_IPV6_MASKS \
21781c01c8c6SMd Fahad Iqbal Polash 	(BIT_ULL(ICE_AVF_FLOW_FIELD_IPV6_TCP_SYN_NO_ACK) | \
21791c01c8c6SMd Fahad Iqbal Polash 	 BIT_ULL(ICE_AVF_FLOW_FIELD_IPV6_TCP))
21801c01c8c6SMd Fahad Iqbal Polash #define ICE_FLOW_AVF_RSS_ALL_IPV6_MASKS \
21811c01c8c6SMd Fahad Iqbal Polash 	(ICE_FLOW_AVF_RSS_TCP_IPV6_MASKS | ICE_FLOW_AVF_RSS_UDP_IPV6_MASKS | \
21821c01c8c6SMd Fahad Iqbal Polash 	 ICE_FLOW_AVF_RSS_IPV6_MASKS | BIT_ULL(ICE_AVF_FLOW_FIELD_IPV6_SCTP))
21831c01c8c6SMd Fahad Iqbal Polash 
21841c01c8c6SMd Fahad Iqbal Polash /**
21851c01c8c6SMd Fahad Iqbal Polash  * ice_add_avf_rss_cfg - add an RSS configuration for AVF driver
21861c01c8c6SMd Fahad Iqbal Polash  * @hw: pointer to the hardware structure
21871c01c8c6SMd Fahad Iqbal Polash  * @vsi_handle: software VSI handle
21881c01c8c6SMd Fahad Iqbal Polash  * @avf_hash: hash bit fields (ICE_AVF_FLOW_FIELD_*) to configure
21891c01c8c6SMd Fahad Iqbal Polash  *
21901c01c8c6SMd Fahad Iqbal Polash  * This function will take the hash bitmap provided by the AVF driver via a
21911c01c8c6SMd Fahad Iqbal Polash  * message, convert it to ICE-compatible values, and configure RSS flow
21921c01c8c6SMd Fahad Iqbal Polash  * profiles.
21931c01c8c6SMd Fahad Iqbal Polash  */
21941c01c8c6SMd Fahad Iqbal Polash enum ice_status
21951c01c8c6SMd Fahad Iqbal Polash ice_add_avf_rss_cfg(struct ice_hw *hw, u16 vsi_handle, u64 avf_hash)
21961c01c8c6SMd Fahad Iqbal Polash {
21971c01c8c6SMd Fahad Iqbal Polash 	enum ice_status status = 0;
21981c01c8c6SMd Fahad Iqbal Polash 	u64 hash_flds;
21991c01c8c6SMd Fahad Iqbal Polash 
22001c01c8c6SMd Fahad Iqbal Polash 	if (avf_hash == ICE_AVF_FLOW_FIELD_INVALID ||
22011c01c8c6SMd Fahad Iqbal Polash 	    !ice_is_vsi_valid(hw, vsi_handle))
22021c01c8c6SMd Fahad Iqbal Polash 		return ICE_ERR_PARAM;
22031c01c8c6SMd Fahad Iqbal Polash 
22041c01c8c6SMd Fahad Iqbal Polash 	/* Make sure no unsupported bits are specified */
22051c01c8c6SMd Fahad Iqbal Polash 	if (avf_hash & ~(ICE_FLOW_AVF_RSS_ALL_IPV4_MASKS |
22061c01c8c6SMd Fahad Iqbal Polash 			 ICE_FLOW_AVF_RSS_ALL_IPV6_MASKS))
22071c01c8c6SMd Fahad Iqbal Polash 		return ICE_ERR_CFG;
22081c01c8c6SMd Fahad Iqbal Polash 
22091c01c8c6SMd Fahad Iqbal Polash 	hash_flds = avf_hash;
22101c01c8c6SMd Fahad Iqbal Polash 
22111c01c8c6SMd Fahad Iqbal Polash 	/* Always create an L3 RSS configuration for any L4 RSS configuration */
22121c01c8c6SMd Fahad Iqbal Polash 	if (hash_flds & ICE_FLOW_AVF_RSS_ALL_IPV4_MASKS)
22131c01c8c6SMd Fahad Iqbal Polash 		hash_flds |= ICE_FLOW_AVF_RSS_IPV4_MASKS;
22141c01c8c6SMd Fahad Iqbal Polash 
22151c01c8c6SMd Fahad Iqbal Polash 	if (hash_flds & ICE_FLOW_AVF_RSS_ALL_IPV6_MASKS)
22161c01c8c6SMd Fahad Iqbal Polash 		hash_flds |= ICE_FLOW_AVF_RSS_IPV6_MASKS;
22171c01c8c6SMd Fahad Iqbal Polash 
22181c01c8c6SMd Fahad Iqbal Polash 	/* Create the corresponding RSS configuration for each valid hash bit */
22191c01c8c6SMd Fahad Iqbal Polash 	while (hash_flds) {
22201c01c8c6SMd Fahad Iqbal Polash 		u64 rss_hash = ICE_HASH_INVALID;
22211c01c8c6SMd Fahad Iqbal Polash 
22221c01c8c6SMd Fahad Iqbal Polash 		if (hash_flds & ICE_FLOW_AVF_RSS_ALL_IPV4_MASKS) {
22231c01c8c6SMd Fahad Iqbal Polash 			if (hash_flds & ICE_FLOW_AVF_RSS_IPV4_MASKS) {
22241c01c8c6SMd Fahad Iqbal Polash 				rss_hash = ICE_FLOW_HASH_IPV4;
22251c01c8c6SMd Fahad Iqbal Polash 				hash_flds &= ~ICE_FLOW_AVF_RSS_IPV4_MASKS;
22261c01c8c6SMd Fahad Iqbal Polash 			} else if (hash_flds &
22271c01c8c6SMd Fahad Iqbal Polash 				   ICE_FLOW_AVF_RSS_TCP_IPV4_MASKS) {
22281c01c8c6SMd Fahad Iqbal Polash 				rss_hash = ICE_FLOW_HASH_IPV4 |
22291c01c8c6SMd Fahad Iqbal Polash 					ICE_FLOW_HASH_TCP_PORT;
22301c01c8c6SMd Fahad Iqbal Polash 				hash_flds &= ~ICE_FLOW_AVF_RSS_TCP_IPV4_MASKS;
22311c01c8c6SMd Fahad Iqbal Polash 			} else if (hash_flds &
22321c01c8c6SMd Fahad Iqbal Polash 				   ICE_FLOW_AVF_RSS_UDP_IPV4_MASKS) {
22331c01c8c6SMd Fahad Iqbal Polash 				rss_hash = ICE_FLOW_HASH_IPV4 |
22341c01c8c6SMd Fahad Iqbal Polash 					ICE_FLOW_HASH_UDP_PORT;
22351c01c8c6SMd Fahad Iqbal Polash 				hash_flds &= ~ICE_FLOW_AVF_RSS_UDP_IPV4_MASKS;
22361c01c8c6SMd Fahad Iqbal Polash 			} else if (hash_flds &
22371c01c8c6SMd Fahad Iqbal Polash 				   BIT_ULL(ICE_AVF_FLOW_FIELD_IPV4_SCTP)) {
22381c01c8c6SMd Fahad Iqbal Polash 				rss_hash = ICE_FLOW_HASH_IPV4 |
22391c01c8c6SMd Fahad Iqbal Polash 					ICE_FLOW_HASH_SCTP_PORT;
22401c01c8c6SMd Fahad Iqbal Polash 				hash_flds &=
22411c01c8c6SMd Fahad Iqbal Polash 					~BIT_ULL(ICE_AVF_FLOW_FIELD_IPV4_SCTP);
22421c01c8c6SMd Fahad Iqbal Polash 			}
22431c01c8c6SMd Fahad Iqbal Polash 		} else if (hash_flds & ICE_FLOW_AVF_RSS_ALL_IPV6_MASKS) {
22441c01c8c6SMd Fahad Iqbal Polash 			if (hash_flds & ICE_FLOW_AVF_RSS_IPV6_MASKS) {
22451c01c8c6SMd Fahad Iqbal Polash 				rss_hash = ICE_FLOW_HASH_IPV6;
22461c01c8c6SMd Fahad Iqbal Polash 				hash_flds &= ~ICE_FLOW_AVF_RSS_IPV6_MASKS;
22471c01c8c6SMd Fahad Iqbal Polash 			} else if (hash_flds &
22481c01c8c6SMd Fahad Iqbal Polash 				   ICE_FLOW_AVF_RSS_TCP_IPV6_MASKS) {
22491c01c8c6SMd Fahad Iqbal Polash 				rss_hash = ICE_FLOW_HASH_IPV6 |
22501c01c8c6SMd Fahad Iqbal Polash 					ICE_FLOW_HASH_TCP_PORT;
22511c01c8c6SMd Fahad Iqbal Polash 				hash_flds &= ~ICE_FLOW_AVF_RSS_TCP_IPV6_MASKS;
22521c01c8c6SMd Fahad Iqbal Polash 			} else if (hash_flds &
22531c01c8c6SMd Fahad Iqbal Polash 				   ICE_FLOW_AVF_RSS_UDP_IPV6_MASKS) {
22541c01c8c6SMd Fahad Iqbal Polash 				rss_hash = ICE_FLOW_HASH_IPV6 |
22551c01c8c6SMd Fahad Iqbal Polash 					ICE_FLOW_HASH_UDP_PORT;
22561c01c8c6SMd Fahad Iqbal Polash 				hash_flds &= ~ICE_FLOW_AVF_RSS_UDP_IPV6_MASKS;
22571c01c8c6SMd Fahad Iqbal Polash 			} else if (hash_flds &
22581c01c8c6SMd Fahad Iqbal Polash 				   BIT_ULL(ICE_AVF_FLOW_FIELD_IPV6_SCTP)) {
22591c01c8c6SMd Fahad Iqbal Polash 				rss_hash = ICE_FLOW_HASH_IPV6 |
22601c01c8c6SMd Fahad Iqbal Polash 					ICE_FLOW_HASH_SCTP_PORT;
22611c01c8c6SMd Fahad Iqbal Polash 				hash_flds &=
22621c01c8c6SMd Fahad Iqbal Polash 					~BIT_ULL(ICE_AVF_FLOW_FIELD_IPV6_SCTP);
22631c01c8c6SMd Fahad Iqbal Polash 			}
22641c01c8c6SMd Fahad Iqbal Polash 		}
22651c01c8c6SMd Fahad Iqbal Polash 
22661c01c8c6SMd Fahad Iqbal Polash 		if (rss_hash == ICE_HASH_INVALID)
22671c01c8c6SMd Fahad Iqbal Polash 			return ICE_ERR_OUT_OF_RANGE;
22681c01c8c6SMd Fahad Iqbal Polash 
22691c01c8c6SMd Fahad Iqbal Polash 		status = ice_add_rss_cfg(hw, vsi_handle, rss_hash,
22701c01c8c6SMd Fahad Iqbal Polash 					 ICE_FLOW_SEG_HDR_NONE);
22711c01c8c6SMd Fahad Iqbal Polash 		if (status)
22721c01c8c6SMd Fahad Iqbal Polash 			break;
22731c01c8c6SMd Fahad Iqbal Polash 	}
22741c01c8c6SMd Fahad Iqbal Polash 
22751c01c8c6SMd Fahad Iqbal Polash 	return status;
22761c01c8c6SMd Fahad Iqbal Polash }
22771c01c8c6SMd Fahad Iqbal Polash 
2278c90ed40cSTony Nguyen /**
2279c90ed40cSTony Nguyen  * ice_replay_rss_cfg - replay RSS configurations associated with VSI
2280c90ed40cSTony Nguyen  * @hw: pointer to the hardware structure
2281c90ed40cSTony Nguyen  * @vsi_handle: software VSI handle
2282c90ed40cSTony Nguyen  */
2283c90ed40cSTony Nguyen enum ice_status ice_replay_rss_cfg(struct ice_hw *hw, u16 vsi_handle)
2284c90ed40cSTony Nguyen {
2285c90ed40cSTony Nguyen 	enum ice_status status = 0;
2286c90ed40cSTony Nguyen 	struct ice_rss_cfg *r;
2287c90ed40cSTony Nguyen 
2288c90ed40cSTony Nguyen 	if (!ice_is_vsi_valid(hw, vsi_handle))
2289c90ed40cSTony Nguyen 		return ICE_ERR_PARAM;
2290c90ed40cSTony Nguyen 
2291c90ed40cSTony Nguyen 	mutex_lock(&hw->rss_locks);
2292c90ed40cSTony Nguyen 	list_for_each_entry(r, &hw->rss_list_head, l_entry) {
2293c90ed40cSTony Nguyen 		if (test_bit(vsi_handle, r->vsis)) {
2294451f2c44STony Nguyen 			status = ice_add_rss_cfg_sync(hw, vsi_handle,
2295451f2c44STony Nguyen 						      r->hashed_flds,
2296c90ed40cSTony Nguyen 						      r->packet_hdr,
2297c90ed40cSTony Nguyen 						      ICE_RSS_OUTER_HEADERS);
2298c90ed40cSTony Nguyen 			if (status)
2299c90ed40cSTony Nguyen 				break;
2300a4e82a81STony Nguyen 			status = ice_add_rss_cfg_sync(hw, vsi_handle,
2301a4e82a81STony Nguyen 						      r->hashed_flds,
2302a4e82a81STony Nguyen 						      r->packet_hdr,
2303a4e82a81STony Nguyen 						      ICE_RSS_INNER_HEADERS);
2304a4e82a81STony Nguyen 			if (status)
2305a4e82a81STony Nguyen 				break;
2306c90ed40cSTony Nguyen 		}
2307c90ed40cSTony Nguyen 	}
2308c90ed40cSTony Nguyen 	mutex_unlock(&hw->rss_locks);
2309c90ed40cSTony Nguyen 
2310c90ed40cSTony Nguyen 	return status;
2311c90ed40cSTony Nguyen }
23126876fb64SMd Fahad Iqbal Polash 
23136876fb64SMd Fahad Iqbal Polash /**
23146876fb64SMd Fahad Iqbal Polash  * ice_get_rss_cfg - returns hashed fields for the given header types
23156876fb64SMd Fahad Iqbal Polash  * @hw: pointer to the hardware structure
23166876fb64SMd Fahad Iqbal Polash  * @vsi_handle: software VSI handle
23176876fb64SMd Fahad Iqbal Polash  * @hdrs: protocol header type
23186876fb64SMd Fahad Iqbal Polash  *
23196876fb64SMd Fahad Iqbal Polash  * This function will return the match fields of the first instance of flow
23206876fb64SMd Fahad Iqbal Polash  * profile having the given header types and containing input VSI
23216876fb64SMd Fahad Iqbal Polash  */
23226876fb64SMd Fahad Iqbal Polash u64 ice_get_rss_cfg(struct ice_hw *hw, u16 vsi_handle, u32 hdrs)
23236876fb64SMd Fahad Iqbal Polash {
2324cdedbab9SVignesh Sridhar 	u64 rss_hash = ICE_HASH_INVALID;
2325cdedbab9SVignesh Sridhar 	struct ice_rss_cfg *r;
23266876fb64SMd Fahad Iqbal Polash 
23276876fb64SMd Fahad Iqbal Polash 	/* verify if the protocol header is non zero and VSI is valid */
23286876fb64SMd Fahad Iqbal Polash 	if (hdrs == ICE_FLOW_SEG_HDR_NONE || !ice_is_vsi_valid(hw, vsi_handle))
23296876fb64SMd Fahad Iqbal Polash 		return ICE_HASH_INVALID;
23306876fb64SMd Fahad Iqbal Polash 
23316876fb64SMd Fahad Iqbal Polash 	mutex_lock(&hw->rss_locks);
23326876fb64SMd Fahad Iqbal Polash 	list_for_each_entry(r, &hw->rss_list_head, l_entry)
23336876fb64SMd Fahad Iqbal Polash 		if (test_bit(vsi_handle, r->vsis) &&
23346876fb64SMd Fahad Iqbal Polash 		    r->packet_hdr == hdrs) {
2335cdedbab9SVignesh Sridhar 			rss_hash = r->hashed_flds;
23366876fb64SMd Fahad Iqbal Polash 			break;
23376876fb64SMd Fahad Iqbal Polash 		}
23386876fb64SMd Fahad Iqbal Polash 	mutex_unlock(&hw->rss_locks);
23396876fb64SMd Fahad Iqbal Polash 
2340cdedbab9SVignesh Sridhar 	return rss_hash;
23416876fb64SMd Fahad Iqbal Polash }
2342