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"
6649c87c6SJacob Keller #include <net/gre.h>
7c90ed40cSTony Nguyen 
8c90ed40cSTony Nguyen /* Describe properties of a protocol header field */
9c90ed40cSTony Nguyen struct ice_flow_field_info {
10c90ed40cSTony Nguyen 	enum ice_flow_seg_hdr hdr;
11c90ed40cSTony Nguyen 	s16 off;	/* Offset from start of a protocol header, in bits */
12c90ed40cSTony Nguyen 	u16 size;	/* Size of fields in bits */
13b199dddbSQi Zhang 	u16 mask;	/* 16-bit mask for field */
14c90ed40cSTony Nguyen };
15c90ed40cSTony Nguyen 
16c90ed40cSTony Nguyen #define ICE_FLOW_FLD_INFO(_hdr, _offset_bytes, _size_bytes) { \
17c90ed40cSTony Nguyen 	.hdr = _hdr, \
18c90ed40cSTony Nguyen 	.off = (_offset_bytes) * BITS_PER_BYTE, \
19c90ed40cSTony Nguyen 	.size = (_size_bytes) * BITS_PER_BYTE, \
20b199dddbSQi Zhang 	.mask = 0, \
21b199dddbSQi Zhang }
22b199dddbSQi Zhang 
23b199dddbSQi Zhang #define ICE_FLOW_FLD_INFO_MSK(_hdr, _offset_bytes, _size_bytes, _mask) { \
24b199dddbSQi Zhang 	.hdr = _hdr, \
25b199dddbSQi Zhang 	.off = (_offset_bytes) * BITS_PER_BYTE, \
26b199dddbSQi Zhang 	.size = (_size_bytes) * BITS_PER_BYTE, \
27b199dddbSQi Zhang 	.mask = _mask, \
28c90ed40cSTony Nguyen }
29c90ed40cSTony Nguyen 
30c90ed40cSTony Nguyen /* Table containing properties of supported protocol header fields */
31c90ed40cSTony Nguyen static const
32c90ed40cSTony Nguyen struct ice_flow_field_info ice_flds_info[ICE_FLOW_FIELD_IDX_MAX] = {
33390bd141SQi Zhang 	/* Ether */
34390bd141SQi Zhang 	/* ICE_FLOW_FIELD_IDX_ETH_DA */
35390bd141SQi Zhang 	ICE_FLOW_FLD_INFO(ICE_FLOW_SEG_HDR_ETH, 0, ETH_ALEN),
36390bd141SQi Zhang 	/* ICE_FLOW_FIELD_IDX_ETH_SA */
37390bd141SQi Zhang 	ICE_FLOW_FLD_INFO(ICE_FLOW_SEG_HDR_ETH, ETH_ALEN, ETH_ALEN),
38390bd141SQi Zhang 	/* ICE_FLOW_FIELD_IDX_S_VLAN */
39390bd141SQi Zhang 	ICE_FLOW_FLD_INFO(ICE_FLOW_SEG_HDR_VLAN, 12, sizeof(__be16)),
40390bd141SQi Zhang 	/* ICE_FLOW_FIELD_IDX_C_VLAN */
41390bd141SQi Zhang 	ICE_FLOW_FLD_INFO(ICE_FLOW_SEG_HDR_VLAN, 14, sizeof(__be16)),
42390bd141SQi Zhang 	/* ICE_FLOW_FIELD_IDX_ETH_TYPE */
43390bd141SQi Zhang 	ICE_FLOW_FLD_INFO(ICE_FLOW_SEG_HDR_ETH, 0, sizeof(__be16)),
44c90ed40cSTony Nguyen 	/* IPv4 / IPv6 */
45b199dddbSQi Zhang 	/* ICE_FLOW_FIELD_IDX_IPV4_DSCP */
46b199dddbSQi Zhang 	ICE_FLOW_FLD_INFO_MSK(ICE_FLOW_SEG_HDR_IPV4, 0, 1, 0x00fc),
47b199dddbSQi Zhang 	/* ICE_FLOW_FIELD_IDX_IPV6_DSCP */
48b199dddbSQi Zhang 	ICE_FLOW_FLD_INFO_MSK(ICE_FLOW_SEG_HDR_IPV6, 0, 1, 0x0ff0),
49b199dddbSQi Zhang 	/* ICE_FLOW_FIELD_IDX_IPV4_TTL */
50b199dddbSQi Zhang 	ICE_FLOW_FLD_INFO_MSK(ICE_FLOW_SEG_HDR_NONE, 8, 1, 0xff00),
51b199dddbSQi Zhang 	/* ICE_FLOW_FIELD_IDX_IPV4_PROT */
52b199dddbSQi Zhang 	ICE_FLOW_FLD_INFO_MSK(ICE_FLOW_SEG_HDR_NONE, 8, 1, 0x00ff),
53b199dddbSQi Zhang 	/* ICE_FLOW_FIELD_IDX_IPV6_TTL */
54b199dddbSQi Zhang 	ICE_FLOW_FLD_INFO_MSK(ICE_FLOW_SEG_HDR_NONE, 6, 1, 0x00ff),
55b199dddbSQi Zhang 	/* ICE_FLOW_FIELD_IDX_IPV6_PROT */
56b199dddbSQi Zhang 	ICE_FLOW_FLD_INFO_MSK(ICE_FLOW_SEG_HDR_NONE, 6, 1, 0xff00),
57c90ed40cSTony Nguyen 	/* ICE_FLOW_FIELD_IDX_IPV4_SA */
58c90ed40cSTony Nguyen 	ICE_FLOW_FLD_INFO(ICE_FLOW_SEG_HDR_IPV4, 12, sizeof(struct in_addr)),
59c90ed40cSTony Nguyen 	/* ICE_FLOW_FIELD_IDX_IPV4_DA */
60c90ed40cSTony Nguyen 	ICE_FLOW_FLD_INFO(ICE_FLOW_SEG_HDR_IPV4, 16, sizeof(struct in_addr)),
61c90ed40cSTony Nguyen 	/* ICE_FLOW_FIELD_IDX_IPV6_SA */
62c90ed40cSTony Nguyen 	ICE_FLOW_FLD_INFO(ICE_FLOW_SEG_HDR_IPV6, 8, sizeof(struct in6_addr)),
63c90ed40cSTony Nguyen 	/* ICE_FLOW_FIELD_IDX_IPV6_DA */
64c90ed40cSTony Nguyen 	ICE_FLOW_FLD_INFO(ICE_FLOW_SEG_HDR_IPV6, 24, sizeof(struct in6_addr)),
65c90ed40cSTony Nguyen 	/* Transport */
66c90ed40cSTony Nguyen 	/* ICE_FLOW_FIELD_IDX_TCP_SRC_PORT */
67c90ed40cSTony Nguyen 	ICE_FLOW_FLD_INFO(ICE_FLOW_SEG_HDR_TCP, 0, sizeof(__be16)),
68c90ed40cSTony Nguyen 	/* ICE_FLOW_FIELD_IDX_TCP_DST_PORT */
69c90ed40cSTony Nguyen 	ICE_FLOW_FLD_INFO(ICE_FLOW_SEG_HDR_TCP, 2, sizeof(__be16)),
70c90ed40cSTony Nguyen 	/* ICE_FLOW_FIELD_IDX_UDP_SRC_PORT */
71c90ed40cSTony Nguyen 	ICE_FLOW_FLD_INFO(ICE_FLOW_SEG_HDR_UDP, 0, sizeof(__be16)),
72c90ed40cSTony Nguyen 	/* ICE_FLOW_FIELD_IDX_UDP_DST_PORT */
73c90ed40cSTony Nguyen 	ICE_FLOW_FLD_INFO(ICE_FLOW_SEG_HDR_UDP, 2, sizeof(__be16)),
741c01c8c6SMd Fahad Iqbal Polash 	/* ICE_FLOW_FIELD_IDX_SCTP_SRC_PORT */
751c01c8c6SMd Fahad Iqbal Polash 	ICE_FLOW_FLD_INFO(ICE_FLOW_SEG_HDR_SCTP, 0, sizeof(__be16)),
761c01c8c6SMd Fahad Iqbal Polash 	/* ICE_FLOW_FIELD_IDX_SCTP_DST_PORT */
771c01c8c6SMd Fahad Iqbal Polash 	ICE_FLOW_FLD_INFO(ICE_FLOW_SEG_HDR_SCTP, 2, sizeof(__be16)),
78390bd141SQi Zhang 	/* ICE_FLOW_FIELD_IDX_TCP_FLAGS */
79390bd141SQi Zhang 	ICE_FLOW_FLD_INFO(ICE_FLOW_SEG_HDR_TCP, 13, 1),
80390bd141SQi Zhang 	/* ARP */
81390bd141SQi Zhang 	/* ICE_FLOW_FIELD_IDX_ARP_SIP */
82390bd141SQi Zhang 	ICE_FLOW_FLD_INFO(ICE_FLOW_SEG_HDR_ARP, 14, sizeof(struct in_addr)),
83390bd141SQi Zhang 	/* ICE_FLOW_FIELD_IDX_ARP_DIP */
84390bd141SQi Zhang 	ICE_FLOW_FLD_INFO(ICE_FLOW_SEG_HDR_ARP, 24, sizeof(struct in_addr)),
85390bd141SQi Zhang 	/* ICE_FLOW_FIELD_IDX_ARP_SHA */
86390bd141SQi Zhang 	ICE_FLOW_FLD_INFO(ICE_FLOW_SEG_HDR_ARP, 8, ETH_ALEN),
87390bd141SQi Zhang 	/* ICE_FLOW_FIELD_IDX_ARP_DHA */
88390bd141SQi Zhang 	ICE_FLOW_FLD_INFO(ICE_FLOW_SEG_HDR_ARP, 18, ETH_ALEN),
89390bd141SQi Zhang 	/* ICE_FLOW_FIELD_IDX_ARP_OP */
90390bd141SQi Zhang 	ICE_FLOW_FLD_INFO(ICE_FLOW_SEG_HDR_ARP, 6, sizeof(__be16)),
91390bd141SQi Zhang 	/* ICMP */
92390bd141SQi Zhang 	/* ICE_FLOW_FIELD_IDX_ICMP_TYPE */
93390bd141SQi Zhang 	ICE_FLOW_FLD_INFO(ICE_FLOW_SEG_HDR_ICMP, 0, 1),
94390bd141SQi Zhang 	/* ICE_FLOW_FIELD_IDX_ICMP_CODE */
95390bd141SQi Zhang 	ICE_FLOW_FLD_INFO(ICE_FLOW_SEG_HDR_ICMP, 1, 1),
96a4e82a81STony Nguyen 	/* GRE */
97a4e82a81STony Nguyen 	/* ICE_FLOW_FIELD_IDX_GRE_KEYID */
98a4e82a81STony Nguyen 	ICE_FLOW_FLD_INFO(ICE_FLOW_SEG_HDR_GRE, 12,
99a4e82a81STony Nguyen 			  sizeof_field(struct gre_full_hdr, key)),
1000577313eSQi Zhang 	/* GTP */
1010577313eSQi Zhang 	/* ICE_FLOW_FIELD_IDX_GTPC_TEID */
1020577313eSQi Zhang 	ICE_FLOW_FLD_INFO(ICE_FLOW_SEG_HDR_GTPC_TEID, 12, sizeof(__be32)),
1030577313eSQi Zhang 	/* ICE_FLOW_FIELD_IDX_GTPU_IP_TEID */
1040577313eSQi Zhang 	ICE_FLOW_FLD_INFO(ICE_FLOW_SEG_HDR_GTPU_IP, 12, sizeof(__be32)),
1050577313eSQi Zhang 	/* ICE_FLOW_FIELD_IDX_GTPU_EH_TEID */
1060577313eSQi Zhang 	ICE_FLOW_FLD_INFO(ICE_FLOW_SEG_HDR_GTPU_EH, 12, sizeof(__be32)),
1070577313eSQi Zhang 	/* ICE_FLOW_FIELD_IDX_GTPU_EH_QFI */
1080577313eSQi Zhang 	ICE_FLOW_FLD_INFO_MSK(ICE_FLOW_SEG_HDR_GTPU_EH, 22, sizeof(__be16),
1090577313eSQi Zhang 			      0x3f00),
1100577313eSQi Zhang 	/* ICE_FLOW_FIELD_IDX_GTPU_UP_TEID */
1110577313eSQi Zhang 	ICE_FLOW_FLD_INFO(ICE_FLOW_SEG_HDR_GTPU_UP, 12, sizeof(__be32)),
1120577313eSQi Zhang 	/* ICE_FLOW_FIELD_IDX_GTPU_DWN_TEID */
1130577313eSQi Zhang 	ICE_FLOW_FLD_INFO(ICE_FLOW_SEG_HDR_GTPU_DWN, 12, sizeof(__be32)),
1140577313eSQi Zhang 	/* PPPoE */
1150577313eSQi Zhang 	/* ICE_FLOW_FIELD_IDX_PPPOE_SESS_ID */
1160577313eSQi Zhang 	ICE_FLOW_FLD_INFO(ICE_FLOW_SEG_HDR_PPPOE, 2, sizeof(__be16)),
1170577313eSQi Zhang 	/* PFCP */
1180577313eSQi Zhang 	/* ICE_FLOW_FIELD_IDX_PFCP_SEID */
1190577313eSQi Zhang 	ICE_FLOW_FLD_INFO(ICE_FLOW_SEG_HDR_PFCP_SESSION, 12, sizeof(__be64)),
1200577313eSQi Zhang 	/* L2TPv3 */
1210577313eSQi Zhang 	/* ICE_FLOW_FIELD_IDX_L2TPV3_SESS_ID */
1220577313eSQi Zhang 	ICE_FLOW_FLD_INFO(ICE_FLOW_SEG_HDR_L2TPV3, 0, sizeof(__be32)),
1230577313eSQi Zhang 	/* ESP */
1240577313eSQi Zhang 	/* ICE_FLOW_FIELD_IDX_ESP_SPI */
1250577313eSQi Zhang 	ICE_FLOW_FLD_INFO(ICE_FLOW_SEG_HDR_ESP, 0, sizeof(__be32)),
1260577313eSQi Zhang 	/* AH */
1270577313eSQi Zhang 	/* ICE_FLOW_FIELD_IDX_AH_SPI */
1280577313eSQi Zhang 	ICE_FLOW_FLD_INFO(ICE_FLOW_SEG_HDR_AH, 4, sizeof(__be32)),
1290577313eSQi Zhang 	/* NAT_T_ESP */
1300577313eSQi Zhang 	/* ICE_FLOW_FIELD_IDX_NAT_T_ESP_SPI */
1310577313eSQi Zhang 	ICE_FLOW_FLD_INFO(ICE_FLOW_SEG_HDR_NAT_T_ESP, 8, sizeof(__be32)),
132c90ed40cSTony Nguyen };
133c90ed40cSTony Nguyen 
13431ad4e4eSTony Nguyen /* Bitmaps indicating relevant packet types for a particular protocol header
13531ad4e4eSTony Nguyen  *
136390bd141SQi Zhang  * Packet types for packets with an Outer/First/Single MAC header
13731ad4e4eSTony Nguyen  */
138390bd141SQi Zhang static const u32 ice_ptypes_mac_ofos[] = {
139390bd141SQi Zhang 	0xFDC00846, 0xBFBF7F7E, 0xF70001DF, 0xFEFDFDFB,
140390bd141SQi Zhang 	0x0000077E, 0x00000000, 0x00000000, 0x00000000,
141390bd141SQi Zhang 	0x00400000, 0x03FFF000, 0x7FFFFFE0, 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 	0x00000000, 0x00000000, 0x00000000, 0x00000000,
147390bd141SQi Zhang };
148390bd141SQi Zhang 
149390bd141SQi Zhang /* Packet types for packets with an Innermost/Last MAC VLAN header */
150390bd141SQi Zhang static const u32 ice_ptypes_macvlan_il[] = {
151390bd141SQi Zhang 	0x00000000, 0xBC000000, 0x000001DF, 0xF0000000,
152390bd141SQi Zhang 	0x0000077E, 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 	0x00000000, 0x00000000, 0x00000000, 0x00000000,
159390bd141SQi Zhang };
160390bd141SQi Zhang 
1617012dfd1SQi Zhang /* Packet types for packets with an Outer/First/Single IPv4 header, does NOT
1627012dfd1SQi Zhang  * include IPv4 other PTYPEs
1637012dfd1SQi Zhang  */
16431ad4e4eSTony Nguyen static const u32 ice_ptypes_ipv4_ofos[] = {
16531ad4e4eSTony Nguyen 	0x1DC00000, 0x04000800, 0x00000000, 0x00000000,
1660577313eSQi Zhang 	0x00000000, 0x00000155, 0x00000000, 0x00000000,
1670577313eSQi Zhang 	0x00000000, 0x000FC000, 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,
17231ad4e4eSTony Nguyen 	0x00000000, 0x00000000, 0x00000000, 0x00000000,
1737012dfd1SQi Zhang };
1747012dfd1SQi Zhang 
1757012dfd1SQi Zhang /* Packet types for packets with an Outer/First/Single IPv4 header, includes
1767012dfd1SQi Zhang  * IPv4 other PTYPEs
1777012dfd1SQi Zhang  */
1787012dfd1SQi Zhang static const u32 ice_ptypes_ipv4_ofos_all[] = {
1797012dfd1SQi Zhang 	0x1DC00000, 0x04000800, 0x00000000, 0x00000000,
1807012dfd1SQi Zhang 	0x00000000, 0x00000155, 0x00000000, 0x00000000,
1817012dfd1SQi Zhang 	0x00000000, 0x000FC000, 0x83E0F800, 0x00000101,
1827012dfd1SQi Zhang 	0x00000000, 0x00000000, 0x00000000, 0x00000000,
1837012dfd1SQi Zhang 	0x00000000, 0x00000000, 0x00000000, 0x00000000,
1847012dfd1SQi Zhang 	0x00000000, 0x00000000, 0x00000000, 0x00000000,
18531ad4e4eSTony Nguyen 	0x00000000, 0x00000000, 0x00000000, 0x00000000,
18631ad4e4eSTony Nguyen 	0x00000000, 0x00000000, 0x00000000, 0x00000000,
18731ad4e4eSTony Nguyen };
18831ad4e4eSTony Nguyen 
18931ad4e4eSTony Nguyen /* Packet types for packets with an Innermost/Last IPv4 header */
19031ad4e4eSTony Nguyen static const u32 ice_ptypes_ipv4_il[] = {
19131ad4e4eSTony Nguyen 	0xE0000000, 0xB807700E, 0x80000003, 0xE01DC03B,
19231ad4e4eSTony Nguyen 	0x0000000E, 0x00000000, 0x00000000, 0x00000000,
1930577313eSQi Zhang 	0x00000000, 0x00000000, 0x001FF800, 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 	0x00000000, 0x00000000, 0x00000000, 0x00000000,
19931ad4e4eSTony Nguyen };
20031ad4e4eSTony Nguyen 
2017012dfd1SQi Zhang /* Packet types for packets with an Outer/First/Single IPv6 header, does NOT
2027012dfd1SQi Zhang  * include IPv6 other PTYPEs
2037012dfd1SQi Zhang  */
20431ad4e4eSTony Nguyen static const u32 ice_ptypes_ipv6_ofos[] = {
20531ad4e4eSTony Nguyen 	0x00000000, 0x00000000, 0x77000000, 0x10002000,
2060577313eSQi Zhang 	0x00000000, 0x000002AA, 0x00000000, 0x00000000,
2070577313eSQi Zhang 	0x00000000, 0x03F00000, 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,
21231ad4e4eSTony Nguyen 	0x00000000, 0x00000000, 0x00000000, 0x00000000,
2137012dfd1SQi Zhang };
2147012dfd1SQi Zhang 
2157012dfd1SQi Zhang /* Packet types for packets with an Outer/First/Single IPv6 header, includes
2167012dfd1SQi Zhang  * IPv6 other PTYPEs
2177012dfd1SQi Zhang  */
2187012dfd1SQi Zhang static const u32 ice_ptypes_ipv6_ofos_all[] = {
2197012dfd1SQi Zhang 	0x00000000, 0x00000000, 0x77000000, 0x10002000,
2207012dfd1SQi Zhang 	0x00000000, 0x000002AA, 0x00000000, 0x00000000,
2217012dfd1SQi Zhang 	0x00080F00, 0x03F00000, 0x7C1F0000, 0x00000206,
2227012dfd1SQi Zhang 	0x00000000, 0x00000000, 0x00000000, 0x00000000,
2237012dfd1SQi Zhang 	0x00000000, 0x00000000, 0x00000000, 0x00000000,
2247012dfd1SQi Zhang 	0x00000000, 0x00000000, 0x00000000, 0x00000000,
22531ad4e4eSTony Nguyen 	0x00000000, 0x00000000, 0x00000000, 0x00000000,
22631ad4e4eSTony Nguyen 	0x00000000, 0x00000000, 0x00000000, 0x00000000,
22731ad4e4eSTony Nguyen };
22831ad4e4eSTony Nguyen 
22931ad4e4eSTony Nguyen /* Packet types for packets with an Innermost/Last IPv6 header */
23031ad4e4eSTony Nguyen static const u32 ice_ptypes_ipv6_il[] = {
23131ad4e4eSTony Nguyen 	0x00000000, 0x03B80770, 0x000001DC, 0x0EE00000,
23231ad4e4eSTony Nguyen 	0x00000770, 0x00000000, 0x00000000, 0x00000000,
2330577313eSQi Zhang 	0x00000000, 0x00000000, 0x7FE00000, 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 	0x00000000, 0x00000000, 0x00000000, 0x00000000,
23931ad4e4eSTony Nguyen };
24031ad4e4eSTony Nguyen 
241051d2b5cSDan Nowlin /* Packet types for packets with an Outer/First/Single IPv4 header - no L4 */
24294a93698SQi Zhang static const u32 ice_ptypes_ipv4_ofos_no_l4[] = {
243051d2b5cSDan Nowlin 	0x10C00000, 0x04000800, 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 	0x00000000, 0x00000000, 0x00000000, 0x00000000,
251051d2b5cSDan Nowlin };
252051d2b5cSDan Nowlin 
253390bd141SQi Zhang /* Packet types for packets with an Outermost/First ARP header */
254390bd141SQi Zhang static const u32 ice_ptypes_arp_of[] = {
255390bd141SQi Zhang 	0x00000800, 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 	0x00000000, 0x00000000, 0x00000000, 0x00000000,
263390bd141SQi Zhang };
264390bd141SQi Zhang 
265051d2b5cSDan Nowlin /* Packet types for packets with an Innermost/Last IPv4 header - no L4 */
26694a93698SQi Zhang static const u32 ice_ptypes_ipv4_il_no_l4[] = {
267051d2b5cSDan Nowlin 	0x60000000, 0x18043008, 0x80000002, 0x6010c021,
268051d2b5cSDan Nowlin 	0x00000008, 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 	0x00000000, 0x00000000, 0x00000000, 0x00000000,
275051d2b5cSDan Nowlin };
276051d2b5cSDan Nowlin 
277051d2b5cSDan Nowlin /* Packet types for packets with an Outer/First/Single IPv6 header - no L4 */
27894a93698SQi Zhang static const u32 ice_ptypes_ipv6_ofos_no_l4[] = {
279051d2b5cSDan Nowlin 	0x00000000, 0x00000000, 0x43000000, 0x10002000,
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 	0x00000000, 0x00000000, 0x00000000, 0x00000000,
287051d2b5cSDan Nowlin };
288051d2b5cSDan Nowlin 
289051d2b5cSDan Nowlin /* Packet types for packets with an Innermost/Last IPv6 header - no L4 */
29094a93698SQi Zhang static const u32 ice_ptypes_ipv6_il_no_l4[] = {
291051d2b5cSDan Nowlin 	0x00000000, 0x02180430, 0x0000010c, 0x086010c0,
292051d2b5cSDan Nowlin 	0x00000430, 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 	0x00000000, 0x00000000, 0x00000000, 0x00000000,
299051d2b5cSDan Nowlin };
300051d2b5cSDan Nowlin 
30131ad4e4eSTony Nguyen /* UDP Packet types for non-tunneled packets or tunneled
30231ad4e4eSTony Nguyen  * packets with inner UDP.
30331ad4e4eSTony Nguyen  */
30431ad4e4eSTony Nguyen static const u32 ice_ptypes_udp_il[] = {
30531ad4e4eSTony Nguyen 	0x81000000, 0x20204040, 0x04000010, 0x80810102,
30631ad4e4eSTony Nguyen 	0x00000040, 0x00000000, 0x00000000, 0x00000000,
3070577313eSQi Zhang 	0x00000000, 0x00410000, 0x90842000, 0x00000007,
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 	0x00000000, 0x00000000, 0x00000000, 0x00000000,
31331ad4e4eSTony Nguyen };
31431ad4e4eSTony Nguyen 
31531ad4e4eSTony Nguyen /* Packet types for packets with an Innermost/Last TCP header */
31631ad4e4eSTony Nguyen static const u32 ice_ptypes_tcp_il[] = {
31731ad4e4eSTony Nguyen 	0x04000000, 0x80810102, 0x10000040, 0x02040408,
31831ad4e4eSTony Nguyen 	0x00000102, 0x00000000, 0x00000000, 0x00000000,
3190577313eSQi Zhang 	0x00000000, 0x00820000, 0x21084000, 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 	0x00000000, 0x00000000, 0x00000000, 0x00000000,
32531ad4e4eSTony Nguyen };
32631ad4e4eSTony Nguyen 
32731ad4e4eSTony Nguyen /* Packet types for packets with an Innermost/Last SCTP header */
32831ad4e4eSTony Nguyen static const u32 ice_ptypes_sctp_il[] = {
32931ad4e4eSTony Nguyen 	0x08000000, 0x01020204, 0x20000081, 0x04080810,
33031ad4e4eSTony Nguyen 	0x00000204, 0x00000000, 0x00000000, 0x00000000,
3310577313eSQi Zhang 	0x00000000, 0x01040000, 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,
33631ad4e4eSTony Nguyen 	0x00000000, 0x00000000, 0x00000000, 0x00000000,
337390bd141SQi Zhang };
338390bd141SQi Zhang 
339390bd141SQi Zhang /* Packet types for packets with an Outermost/First ICMP header */
340390bd141SQi Zhang static const u32 ice_ptypes_icmp_of[] = {
341390bd141SQi Zhang 	0x10000000, 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 	0x00000000, 0x00000000, 0x00000000, 0x00000000,
349390bd141SQi Zhang };
350390bd141SQi Zhang 
351390bd141SQi Zhang /* Packet types for packets with an Innermost/Last ICMP header */
352390bd141SQi Zhang static const u32 ice_ptypes_icmp_il[] = {
353390bd141SQi Zhang 	0x00000000, 0x02040408, 0x40000102, 0x08101020,
354390bd141SQi Zhang 	0x00000408, 0x00000000, 0x00000000, 0x00000000,
355390bd141SQi Zhang 	0x00000000, 0x00000000, 0x42108000, 0x00000000,
356390bd141SQi Zhang 	0x00000000, 0x00000000, 0x00000000, 0x00000000,
357390bd141SQi Zhang 	0x00000000, 0x00000000, 0x00000000, 0x00000000,
358390bd141SQi Zhang 	0x00000000, 0x00000000, 0x00000000, 0x00000000,
359390bd141SQi Zhang 	0x00000000, 0x00000000, 0x00000000, 0x00000000,
36031ad4e4eSTony Nguyen 	0x00000000, 0x00000000, 0x00000000, 0x00000000,
36131ad4e4eSTony Nguyen };
36231ad4e4eSTony Nguyen 
363a4e82a81STony Nguyen /* Packet types for packets with an Outermost/First GRE header */
364a4e82a81STony Nguyen static const u32 ice_ptypes_gre_of[] = {
365a4e82a81STony Nguyen 	0x00000000, 0xBFBF7800, 0x000001DF, 0xFEFDE000,
366a4e82a81STony Nguyen 	0x0000017E, 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 	0x00000000, 0x00000000, 0x00000000, 0x00000000,
373a4e82a81STony Nguyen };
374a4e82a81STony Nguyen 
375390bd141SQi Zhang /* Packet types for packets with an Innermost/Last MAC header */
376390bd141SQi Zhang static const u32 ice_ptypes_mac_il[] = {
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 	0x00000000, 0x00000000, 0x00000000, 0x00000000,
385390bd141SQi Zhang };
386390bd141SQi Zhang 
3870577313eSQi Zhang /* Packet types for GTPC */
3880577313eSQi Zhang static const u32 ice_ptypes_gtpc[] = {
3890577313eSQi Zhang 	0x00000000, 0x00000000, 0x00000000, 0x00000000,
3900577313eSQi Zhang 	0x00000000, 0x00000000, 0x00000000, 0x00000000,
3910577313eSQi Zhang 	0x00000000, 0x00000000, 0x00000180, 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 	0x00000000, 0x00000000, 0x00000000, 0x00000000,
3970577313eSQi Zhang };
3980577313eSQi Zhang 
3990577313eSQi Zhang /* Packet types for GTPC with TEID */
4000577313eSQi Zhang static const u32 ice_ptypes_gtpc_tid[] = {
4010577313eSQi Zhang 	0x00000000, 0x00000000, 0x00000000, 0x00000000,
4020577313eSQi Zhang 	0x00000000, 0x00000000, 0x00000000, 0x00000000,
4030577313eSQi Zhang 	0x00000000, 0x00000000, 0x00000060, 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 	0x00000000, 0x00000000, 0x00000000, 0x00000000,
4090577313eSQi Zhang };
4100577313eSQi Zhang 
411cbad5db8SQi Zhang /* Packet types for GTPU */
412cbad5db8SQi Zhang static const struct ice_ptype_attributes ice_attr_gtpu_eh[] = {
413cbad5db8SQi Zhang 	{ ICE_MAC_IPV4_GTPU_IPV4_FRAG,	  ICE_PTYPE_ATTR_GTP_PDU_EH },
414cbad5db8SQi Zhang 	{ ICE_MAC_IPV4_GTPU_IPV4_PAY,	  ICE_PTYPE_ATTR_GTP_PDU_EH },
415cbad5db8SQi Zhang 	{ ICE_MAC_IPV4_GTPU_IPV4_UDP_PAY, ICE_PTYPE_ATTR_GTP_PDU_EH },
416cbad5db8SQi Zhang 	{ ICE_MAC_IPV4_GTPU_IPV4_TCP,	  ICE_PTYPE_ATTR_GTP_PDU_EH },
417cbad5db8SQi Zhang 	{ ICE_MAC_IPV4_GTPU_IPV4_ICMP,	  ICE_PTYPE_ATTR_GTP_PDU_EH },
418cbad5db8SQi Zhang 	{ ICE_MAC_IPV6_GTPU_IPV4_FRAG,	  ICE_PTYPE_ATTR_GTP_PDU_EH },
419cbad5db8SQi Zhang 	{ ICE_MAC_IPV6_GTPU_IPV4_PAY,	  ICE_PTYPE_ATTR_GTP_PDU_EH },
420cbad5db8SQi Zhang 	{ ICE_MAC_IPV6_GTPU_IPV4_UDP_PAY, ICE_PTYPE_ATTR_GTP_PDU_EH },
421cbad5db8SQi Zhang 	{ ICE_MAC_IPV6_GTPU_IPV4_TCP,	  ICE_PTYPE_ATTR_GTP_PDU_EH },
422cbad5db8SQi Zhang 	{ ICE_MAC_IPV6_GTPU_IPV4_ICMP,	  ICE_PTYPE_ATTR_GTP_PDU_EH },
423cbad5db8SQi Zhang 	{ ICE_MAC_IPV4_GTPU_IPV6_FRAG,	  ICE_PTYPE_ATTR_GTP_PDU_EH },
424cbad5db8SQi Zhang 	{ ICE_MAC_IPV4_GTPU_IPV6_PAY,	  ICE_PTYPE_ATTR_GTP_PDU_EH },
425cbad5db8SQi Zhang 	{ ICE_MAC_IPV4_GTPU_IPV6_UDP_PAY, ICE_PTYPE_ATTR_GTP_PDU_EH },
426cbad5db8SQi Zhang 	{ ICE_MAC_IPV4_GTPU_IPV6_TCP,	  ICE_PTYPE_ATTR_GTP_PDU_EH },
427cbad5db8SQi Zhang 	{ ICE_MAC_IPV4_GTPU_IPV6_ICMPV6,  ICE_PTYPE_ATTR_GTP_PDU_EH },
428cbad5db8SQi Zhang 	{ ICE_MAC_IPV6_GTPU_IPV6_FRAG,	  ICE_PTYPE_ATTR_GTP_PDU_EH },
429cbad5db8SQi Zhang 	{ ICE_MAC_IPV6_GTPU_IPV6_PAY,	  ICE_PTYPE_ATTR_GTP_PDU_EH },
430cbad5db8SQi Zhang 	{ ICE_MAC_IPV6_GTPU_IPV6_UDP_PAY, ICE_PTYPE_ATTR_GTP_PDU_EH },
431cbad5db8SQi Zhang 	{ ICE_MAC_IPV6_GTPU_IPV6_TCP,	  ICE_PTYPE_ATTR_GTP_PDU_EH },
432cbad5db8SQi Zhang 	{ ICE_MAC_IPV6_GTPU_IPV6_ICMPV6,  ICE_PTYPE_ATTR_GTP_PDU_EH },
433cbad5db8SQi Zhang };
434cbad5db8SQi Zhang 
435cbad5db8SQi Zhang static const struct ice_ptype_attributes ice_attr_gtpu_down[] = {
436cbad5db8SQi Zhang 	{ ICE_MAC_IPV4_GTPU_IPV4_FRAG,	  ICE_PTYPE_ATTR_GTP_DOWNLINK },
437cbad5db8SQi Zhang 	{ ICE_MAC_IPV4_GTPU_IPV4_PAY,	  ICE_PTYPE_ATTR_GTP_DOWNLINK },
438cbad5db8SQi Zhang 	{ ICE_MAC_IPV4_GTPU_IPV4_UDP_PAY, ICE_PTYPE_ATTR_GTP_DOWNLINK },
439cbad5db8SQi Zhang 	{ ICE_MAC_IPV4_GTPU_IPV4_TCP,	  ICE_PTYPE_ATTR_GTP_DOWNLINK },
440cbad5db8SQi Zhang 	{ ICE_MAC_IPV4_GTPU_IPV4_ICMP,	  ICE_PTYPE_ATTR_GTP_DOWNLINK },
441cbad5db8SQi Zhang 	{ ICE_MAC_IPV6_GTPU_IPV4_FRAG,	  ICE_PTYPE_ATTR_GTP_DOWNLINK },
442cbad5db8SQi Zhang 	{ ICE_MAC_IPV6_GTPU_IPV4_PAY,	  ICE_PTYPE_ATTR_GTP_DOWNLINK },
443cbad5db8SQi Zhang 	{ ICE_MAC_IPV6_GTPU_IPV4_UDP_PAY, ICE_PTYPE_ATTR_GTP_DOWNLINK },
444cbad5db8SQi Zhang 	{ ICE_MAC_IPV6_GTPU_IPV4_TCP,	  ICE_PTYPE_ATTR_GTP_DOWNLINK },
445cbad5db8SQi Zhang 	{ ICE_MAC_IPV6_GTPU_IPV4_ICMP,	  ICE_PTYPE_ATTR_GTP_DOWNLINK },
446cbad5db8SQi Zhang 	{ ICE_MAC_IPV4_GTPU_IPV6_FRAG,	  ICE_PTYPE_ATTR_GTP_DOWNLINK },
447cbad5db8SQi Zhang 	{ ICE_MAC_IPV4_GTPU_IPV6_PAY,	  ICE_PTYPE_ATTR_GTP_DOWNLINK },
448cbad5db8SQi Zhang 	{ ICE_MAC_IPV4_GTPU_IPV6_UDP_PAY, ICE_PTYPE_ATTR_GTP_DOWNLINK },
449cbad5db8SQi Zhang 	{ ICE_MAC_IPV4_GTPU_IPV6_TCP,	  ICE_PTYPE_ATTR_GTP_DOWNLINK },
450cbad5db8SQi Zhang 	{ ICE_MAC_IPV4_GTPU_IPV6_ICMPV6,  ICE_PTYPE_ATTR_GTP_DOWNLINK },
451cbad5db8SQi Zhang 	{ ICE_MAC_IPV6_GTPU_IPV6_FRAG,	  ICE_PTYPE_ATTR_GTP_DOWNLINK },
452cbad5db8SQi Zhang 	{ ICE_MAC_IPV6_GTPU_IPV6_PAY,	  ICE_PTYPE_ATTR_GTP_DOWNLINK },
453cbad5db8SQi Zhang 	{ ICE_MAC_IPV6_GTPU_IPV6_UDP_PAY, ICE_PTYPE_ATTR_GTP_DOWNLINK },
454cbad5db8SQi Zhang 	{ ICE_MAC_IPV6_GTPU_IPV6_TCP,	  ICE_PTYPE_ATTR_GTP_DOWNLINK },
455cbad5db8SQi Zhang 	{ ICE_MAC_IPV6_GTPU_IPV6_ICMPV6,  ICE_PTYPE_ATTR_GTP_DOWNLINK },
456cbad5db8SQi Zhang };
457cbad5db8SQi Zhang 
458cbad5db8SQi Zhang static const struct ice_ptype_attributes ice_attr_gtpu_up[] = {
459cbad5db8SQi Zhang 	{ ICE_MAC_IPV4_GTPU_IPV4_FRAG,	  ICE_PTYPE_ATTR_GTP_UPLINK },
460cbad5db8SQi Zhang 	{ ICE_MAC_IPV4_GTPU_IPV4_PAY,	  ICE_PTYPE_ATTR_GTP_UPLINK },
461cbad5db8SQi Zhang 	{ ICE_MAC_IPV4_GTPU_IPV4_UDP_PAY, ICE_PTYPE_ATTR_GTP_UPLINK },
462cbad5db8SQi Zhang 	{ ICE_MAC_IPV4_GTPU_IPV4_TCP,	  ICE_PTYPE_ATTR_GTP_UPLINK },
463cbad5db8SQi Zhang 	{ ICE_MAC_IPV4_GTPU_IPV4_ICMP,	  ICE_PTYPE_ATTR_GTP_UPLINK },
464cbad5db8SQi Zhang 	{ ICE_MAC_IPV6_GTPU_IPV4_FRAG,	  ICE_PTYPE_ATTR_GTP_UPLINK },
465cbad5db8SQi Zhang 	{ ICE_MAC_IPV6_GTPU_IPV4_PAY,	  ICE_PTYPE_ATTR_GTP_UPLINK },
466cbad5db8SQi Zhang 	{ ICE_MAC_IPV6_GTPU_IPV4_UDP_PAY, ICE_PTYPE_ATTR_GTP_UPLINK },
467cbad5db8SQi Zhang 	{ ICE_MAC_IPV6_GTPU_IPV4_TCP,	  ICE_PTYPE_ATTR_GTP_UPLINK },
468cbad5db8SQi Zhang 	{ ICE_MAC_IPV6_GTPU_IPV4_ICMP,	  ICE_PTYPE_ATTR_GTP_UPLINK },
469cbad5db8SQi Zhang 	{ ICE_MAC_IPV4_GTPU_IPV6_FRAG,	  ICE_PTYPE_ATTR_GTP_UPLINK },
470cbad5db8SQi Zhang 	{ ICE_MAC_IPV4_GTPU_IPV6_PAY,	  ICE_PTYPE_ATTR_GTP_UPLINK },
471cbad5db8SQi Zhang 	{ ICE_MAC_IPV4_GTPU_IPV6_UDP_PAY, ICE_PTYPE_ATTR_GTP_UPLINK },
472cbad5db8SQi Zhang 	{ ICE_MAC_IPV4_GTPU_IPV6_TCP,	  ICE_PTYPE_ATTR_GTP_UPLINK },
473cbad5db8SQi Zhang 	{ ICE_MAC_IPV4_GTPU_IPV6_ICMPV6,  ICE_PTYPE_ATTR_GTP_UPLINK },
474cbad5db8SQi Zhang 	{ ICE_MAC_IPV6_GTPU_IPV6_FRAG,	  ICE_PTYPE_ATTR_GTP_UPLINK },
475cbad5db8SQi Zhang 	{ ICE_MAC_IPV6_GTPU_IPV6_PAY,	  ICE_PTYPE_ATTR_GTP_UPLINK },
476cbad5db8SQi Zhang 	{ ICE_MAC_IPV6_GTPU_IPV6_UDP_PAY, ICE_PTYPE_ATTR_GTP_UPLINK },
477cbad5db8SQi Zhang 	{ ICE_MAC_IPV6_GTPU_IPV6_TCP,	  ICE_PTYPE_ATTR_GTP_UPLINK },
478cbad5db8SQi Zhang 	{ ICE_MAC_IPV6_GTPU_IPV6_ICMPV6,  ICE_PTYPE_ATTR_GTP_UPLINK },
479cbad5db8SQi Zhang };
480cbad5db8SQi Zhang 
4810577313eSQi Zhang static const u32 ice_ptypes_gtpu[] = {
4820577313eSQi Zhang 	0x00000000, 0x00000000, 0x00000000, 0x00000000,
4830577313eSQi Zhang 	0x00000000, 0x00000000, 0x00000000, 0x00000000,
4840577313eSQi Zhang 	0x00000000, 0x00000000, 0x7FFFFE00, 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 	0x00000000, 0x00000000, 0x00000000, 0x00000000,
4900577313eSQi Zhang };
4910577313eSQi Zhang 
4920577313eSQi Zhang /* Packet types for PPPoE */
4930577313eSQi Zhang static const u32 ice_ptypes_pppoe[] = {
4940577313eSQi Zhang 	0x00000000, 0x00000000, 0x00000000, 0x00000000,
4950577313eSQi Zhang 	0x00000000, 0x00000000, 0x00000000, 0x00000000,
4960577313eSQi Zhang 	0x00000000, 0x03ffe000, 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 	0x00000000, 0x00000000, 0x00000000, 0x00000000,
5020577313eSQi Zhang };
5030577313eSQi Zhang 
5040577313eSQi Zhang /* Packet types for packets with PFCP NODE header */
5050577313eSQi Zhang static const u32 ice_ptypes_pfcp_node[] = {
5060577313eSQi Zhang 	0x00000000, 0x00000000, 0x00000000, 0x00000000,
5070577313eSQi Zhang 	0x00000000, 0x00000000, 0x00000000, 0x00000000,
5080577313eSQi Zhang 	0x00000000, 0x00000000, 0x80000000, 0x00000002,
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 	0x00000000, 0x00000000, 0x00000000, 0x00000000,
5140577313eSQi Zhang };
5150577313eSQi Zhang 
5160577313eSQi Zhang /* Packet types for packets with PFCP SESSION header */
5170577313eSQi Zhang static const u32 ice_ptypes_pfcp_session[] = {
5180577313eSQi Zhang 	0x00000000, 0x00000000, 0x00000000, 0x00000000,
5190577313eSQi Zhang 	0x00000000, 0x00000000, 0x00000000, 0x00000000,
5200577313eSQi Zhang 	0x00000000, 0x00000000, 0x00000000, 0x00000005,
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 	0x00000000, 0x00000000, 0x00000000, 0x00000000,
5260577313eSQi Zhang };
5270577313eSQi Zhang 
5280577313eSQi Zhang /* Packet types for L2TPv3 */
5290577313eSQi Zhang static const u32 ice_ptypes_l2tpv3[] = {
5300577313eSQi Zhang 	0x00000000, 0x00000000, 0x00000000, 0x00000000,
5310577313eSQi Zhang 	0x00000000, 0x00000000, 0x00000000, 0x00000000,
5320577313eSQi Zhang 	0x00000000, 0x00000000, 0x00000000, 0x00000300,
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 	0x00000000, 0x00000000, 0x00000000, 0x00000000,
5380577313eSQi Zhang };
5390577313eSQi Zhang 
5400577313eSQi Zhang /* Packet types for ESP */
5410577313eSQi Zhang static const u32 ice_ptypes_esp[] = {
5420577313eSQi Zhang 	0x00000000, 0x00000000, 0x00000000, 0x00000000,
5430577313eSQi Zhang 	0x00000000, 0x00000003, 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 	0x00000000, 0x00000000, 0x00000000, 0x00000000,
5500577313eSQi Zhang };
5510577313eSQi Zhang 
5520577313eSQi Zhang /* Packet types for AH */
5530577313eSQi Zhang static const u32 ice_ptypes_ah[] = {
5540577313eSQi Zhang 	0x00000000, 0x00000000, 0x00000000, 0x00000000,
5550577313eSQi Zhang 	0x00000000, 0x0000000C, 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 	0x00000000, 0x00000000, 0x00000000, 0x00000000,
5620577313eSQi Zhang };
5630577313eSQi Zhang 
5640577313eSQi Zhang /* Packet types for packets with NAT_T ESP header */
5650577313eSQi Zhang static const u32 ice_ptypes_nat_t_esp[] = {
5660577313eSQi Zhang 	0x00000000, 0x00000000, 0x00000000, 0x00000000,
5670577313eSQi Zhang 	0x00000000, 0x00000030, 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 	0x00000000, 0x00000000, 0x00000000, 0x00000000,
5740577313eSQi Zhang };
5750577313eSQi Zhang 
57621606584SQi Zhang static const u32 ice_ptypes_mac_non_ip_ofos[] = {
57721606584SQi Zhang 	0x00000846, 0x00000000, 0x00000000, 0x00000000,
57821606584SQi Zhang 	0x00000000, 0x00000000, 0x00000000, 0x00000000,
57921606584SQi Zhang 	0x00400000, 0x03FFF000, 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 	0x00000000, 0x00000000, 0x00000000, 0x00000000,
58521606584SQi Zhang };
58621606584SQi Zhang 
58731ad4e4eSTony Nguyen /* Manage parameters and info. used during the creation of a flow profile */
58831ad4e4eSTony Nguyen struct ice_flow_prof_params {
58931ad4e4eSTony Nguyen 	enum ice_block blk;
59031ad4e4eSTony Nguyen 	u16 entry_length; /* # of bytes formatted entry will require */
59131ad4e4eSTony Nguyen 	u8 es_cnt;
59231ad4e4eSTony Nguyen 	struct ice_flow_prof *prof;
59331ad4e4eSTony Nguyen 
59431ad4e4eSTony Nguyen 	/* For ACL, the es[0] will have the data of ICE_RX_MDID_PKT_FLAGS_15_0
59531ad4e4eSTony Nguyen 	 * This will give us the direction flags.
59631ad4e4eSTony Nguyen 	 */
59731ad4e4eSTony Nguyen 	struct ice_fv_word es[ICE_MAX_FV_WORDS];
598cbad5db8SQi Zhang 	/* attributes can be used to add attributes to a particular PTYPE */
599cbad5db8SQi Zhang 	const struct ice_ptype_attributes *attr;
600cbad5db8SQi Zhang 	u16 attr_cnt;
601b199dddbSQi Zhang 
602b199dddbSQi Zhang 	u16 mask[ICE_MAX_FV_WORDS];
60331ad4e4eSTony Nguyen 	DECLARE_BITMAP(ptypes, ICE_FLOW_PTYPE_MAX);
60431ad4e4eSTony Nguyen };
60531ad4e4eSTony Nguyen 
6060577313eSQi Zhang #define ICE_FLOW_RSS_HDRS_INNER_MASK \
6070577313eSQi Zhang 	(ICE_FLOW_SEG_HDR_PPPOE | ICE_FLOW_SEG_HDR_GTPC | \
6080577313eSQi Zhang 	ICE_FLOW_SEG_HDR_GTPC_TEID | ICE_FLOW_SEG_HDR_GTPU | \
6090577313eSQi Zhang 	ICE_FLOW_SEG_HDR_PFCP_SESSION | ICE_FLOW_SEG_HDR_L2TPV3 | \
6100577313eSQi Zhang 	ICE_FLOW_SEG_HDR_ESP | ICE_FLOW_SEG_HDR_AH | \
6110577313eSQi Zhang 	ICE_FLOW_SEG_HDR_NAT_T_ESP)
6120577313eSQi Zhang 
61331ad4e4eSTony Nguyen #define ICE_FLOW_SEG_HDRS_L3_MASK	\
614390bd141SQi Zhang 	(ICE_FLOW_SEG_HDR_IPV4 | ICE_FLOW_SEG_HDR_IPV6 | ICE_FLOW_SEG_HDR_ARP)
61531ad4e4eSTony Nguyen #define ICE_FLOW_SEG_HDRS_L4_MASK	\
616390bd141SQi Zhang 	(ICE_FLOW_SEG_HDR_ICMP | ICE_FLOW_SEG_HDR_TCP | ICE_FLOW_SEG_HDR_UDP | \
617390bd141SQi Zhang 	 ICE_FLOW_SEG_HDR_SCTP)
6187012dfd1SQi Zhang /* mask for L4 protocols that are NOT part of IPv4/6 OTHER PTYPE groups */
6197012dfd1SQi Zhang #define ICE_FLOW_SEG_HDRS_L4_MASK_NO_OTHER	\
6207012dfd1SQi Zhang 	(ICE_FLOW_SEG_HDR_TCP | ICE_FLOW_SEG_HDR_UDP | ICE_FLOW_SEG_HDR_SCTP)
62131ad4e4eSTony Nguyen 
62231ad4e4eSTony Nguyen /**
62331ad4e4eSTony Nguyen  * ice_flow_val_hdrs - validates packet segments for valid protocol headers
62431ad4e4eSTony Nguyen  * @segs: array of one or more packet segments that describe the flow
62531ad4e4eSTony Nguyen  * @segs_cnt: number of packet segments provided
62631ad4e4eSTony Nguyen  */
ice_flow_val_hdrs(struct ice_flow_seg_info * segs,u8 segs_cnt)6275518ac2aSTony Nguyen static int ice_flow_val_hdrs(struct ice_flow_seg_info *segs, u8 segs_cnt)
62831ad4e4eSTony Nguyen {
62931ad4e4eSTony Nguyen 	u8 i;
63031ad4e4eSTony Nguyen 
63131ad4e4eSTony Nguyen 	for (i = 0; i < segs_cnt; i++) {
63231ad4e4eSTony Nguyen 		/* Multiple L3 headers */
63331ad4e4eSTony Nguyen 		if (segs[i].hdrs & ICE_FLOW_SEG_HDRS_L3_MASK &&
63431ad4e4eSTony Nguyen 		    !is_power_of_2(segs[i].hdrs & ICE_FLOW_SEG_HDRS_L3_MASK))
635d54699e2STony Nguyen 			return -EINVAL;
63631ad4e4eSTony Nguyen 
63731ad4e4eSTony Nguyen 		/* Multiple L4 headers */
63831ad4e4eSTony Nguyen 		if (segs[i].hdrs & ICE_FLOW_SEG_HDRS_L4_MASK &&
63931ad4e4eSTony Nguyen 		    !is_power_of_2(segs[i].hdrs & ICE_FLOW_SEG_HDRS_L4_MASK))
640d54699e2STony Nguyen 			return -EINVAL;
64131ad4e4eSTony Nguyen 	}
64231ad4e4eSTony Nguyen 
64331ad4e4eSTony Nguyen 	return 0;
64431ad4e4eSTony Nguyen }
64531ad4e4eSTony Nguyen 
6462c57ffcbSHenry Tieman /* Sizes of fixed known protocol headers without header options */
6472c57ffcbSHenry Tieman #define ICE_FLOW_PROT_HDR_SZ_MAC	14
648390bd141SQi Zhang #define ICE_FLOW_PROT_HDR_SZ_MAC_VLAN	(ICE_FLOW_PROT_HDR_SZ_MAC + 2)
6492c57ffcbSHenry Tieman #define ICE_FLOW_PROT_HDR_SZ_IPV4	20
6502c57ffcbSHenry Tieman #define ICE_FLOW_PROT_HDR_SZ_IPV6	40
651390bd141SQi Zhang #define ICE_FLOW_PROT_HDR_SZ_ARP	28
652390bd141SQi Zhang #define ICE_FLOW_PROT_HDR_SZ_ICMP	8
6532c57ffcbSHenry Tieman #define ICE_FLOW_PROT_HDR_SZ_TCP	20
6542c57ffcbSHenry Tieman #define ICE_FLOW_PROT_HDR_SZ_UDP	8
6552c57ffcbSHenry Tieman #define ICE_FLOW_PROT_HDR_SZ_SCTP	12
6562c57ffcbSHenry Tieman 
6572c57ffcbSHenry Tieman /**
6582c57ffcbSHenry Tieman  * ice_flow_calc_seg_sz - calculates size of a packet segment based on headers
6592c57ffcbSHenry Tieman  * @params: information about the flow to be processed
6602c57ffcbSHenry Tieman  * @seg: index of packet segment whose header size is to be determined
6612c57ffcbSHenry Tieman  */
ice_flow_calc_seg_sz(struct ice_flow_prof_params * params,u8 seg)6622c57ffcbSHenry Tieman static u16 ice_flow_calc_seg_sz(struct ice_flow_prof_params *params, u8 seg)
6632c57ffcbSHenry Tieman {
664390bd141SQi Zhang 	u16 sz;
665390bd141SQi Zhang 
666390bd141SQi Zhang 	/* L2 headers */
667390bd141SQi Zhang 	sz = (params->prof->segs[seg].hdrs & ICE_FLOW_SEG_HDR_VLAN) ?
668390bd141SQi Zhang 		ICE_FLOW_PROT_HDR_SZ_MAC_VLAN : ICE_FLOW_PROT_HDR_SZ_MAC;
6692c57ffcbSHenry Tieman 
6702c57ffcbSHenry Tieman 	/* L3 headers */
6712c57ffcbSHenry Tieman 	if (params->prof->segs[seg].hdrs & ICE_FLOW_SEG_HDR_IPV4)
6722c57ffcbSHenry Tieman 		sz += ICE_FLOW_PROT_HDR_SZ_IPV4;
6732c57ffcbSHenry Tieman 	else if (params->prof->segs[seg].hdrs & ICE_FLOW_SEG_HDR_IPV6)
6742c57ffcbSHenry Tieman 		sz += ICE_FLOW_PROT_HDR_SZ_IPV6;
675390bd141SQi Zhang 	else if (params->prof->segs[seg].hdrs & ICE_FLOW_SEG_HDR_ARP)
676390bd141SQi Zhang 		sz += ICE_FLOW_PROT_HDR_SZ_ARP;
677390bd141SQi Zhang 	else if (params->prof->segs[seg].hdrs & ICE_FLOW_SEG_HDRS_L4_MASK)
678390bd141SQi Zhang 		/* An L3 header is required if L4 is specified */
679390bd141SQi Zhang 		return 0;
6802c57ffcbSHenry Tieman 
6812c57ffcbSHenry Tieman 	/* L4 headers */
682390bd141SQi Zhang 	if (params->prof->segs[seg].hdrs & ICE_FLOW_SEG_HDR_ICMP)
683390bd141SQi Zhang 		sz += ICE_FLOW_PROT_HDR_SZ_ICMP;
684390bd141SQi Zhang 	else if (params->prof->segs[seg].hdrs & ICE_FLOW_SEG_HDR_TCP)
6852c57ffcbSHenry Tieman 		sz += ICE_FLOW_PROT_HDR_SZ_TCP;
6862c57ffcbSHenry Tieman 	else if (params->prof->segs[seg].hdrs & ICE_FLOW_SEG_HDR_UDP)
6872c57ffcbSHenry Tieman 		sz += ICE_FLOW_PROT_HDR_SZ_UDP;
6882c57ffcbSHenry Tieman 	else if (params->prof->segs[seg].hdrs & ICE_FLOW_SEG_HDR_SCTP)
6892c57ffcbSHenry Tieman 		sz += ICE_FLOW_PROT_HDR_SZ_SCTP;
6902c57ffcbSHenry Tieman 
6912c57ffcbSHenry Tieman 	return sz;
6922c57ffcbSHenry Tieman }
6932c57ffcbSHenry Tieman 
69431ad4e4eSTony Nguyen /**
69531ad4e4eSTony Nguyen  * ice_flow_proc_seg_hdrs - process protocol headers present in pkt segments
69631ad4e4eSTony Nguyen  * @params: information about the flow to be processed
69731ad4e4eSTony Nguyen  *
69831ad4e4eSTony Nguyen  * This function identifies the packet types associated with the protocol
69931ad4e4eSTony Nguyen  * headers being present in packet segments of the specified flow profile.
70031ad4e4eSTony Nguyen  */
ice_flow_proc_seg_hdrs(struct ice_flow_prof_params * params)7015518ac2aSTony Nguyen static int ice_flow_proc_seg_hdrs(struct ice_flow_prof_params *params)
70231ad4e4eSTony Nguyen {
70331ad4e4eSTony Nguyen 	struct ice_flow_prof *prof;
70431ad4e4eSTony Nguyen 	u8 i;
70531ad4e4eSTony Nguyen 
70631ad4e4eSTony Nguyen 	memset(params->ptypes, 0xff, sizeof(params->ptypes));
70731ad4e4eSTony Nguyen 
70831ad4e4eSTony Nguyen 	prof = params->prof;
70931ad4e4eSTony Nguyen 
71031ad4e4eSTony Nguyen 	for (i = 0; i < params->prof->segs_cnt; i++) {
71131ad4e4eSTony Nguyen 		const unsigned long *src;
71231ad4e4eSTony Nguyen 		u32 hdrs;
71331ad4e4eSTony Nguyen 
71431ad4e4eSTony Nguyen 		hdrs = prof->segs[i].hdrs;
71531ad4e4eSTony Nguyen 
716390bd141SQi Zhang 		if (hdrs & ICE_FLOW_SEG_HDR_ETH) {
717390bd141SQi Zhang 			src = !i ? (const unsigned long *)ice_ptypes_mac_ofos :
718390bd141SQi Zhang 				(const unsigned long *)ice_ptypes_mac_il;
719390bd141SQi Zhang 			bitmap_and(params->ptypes, params->ptypes, src,
720390bd141SQi Zhang 				   ICE_FLOW_PTYPE_MAX);
721390bd141SQi Zhang 		}
722390bd141SQi Zhang 
723390bd141SQi Zhang 		if (i && hdrs & ICE_FLOW_SEG_HDR_VLAN) {
724390bd141SQi Zhang 			src = (const unsigned long *)ice_ptypes_macvlan_il;
725390bd141SQi Zhang 			bitmap_and(params->ptypes, params->ptypes, src,
726390bd141SQi Zhang 				   ICE_FLOW_PTYPE_MAX);
727390bd141SQi Zhang 		}
728390bd141SQi Zhang 
729390bd141SQi Zhang 		if (!i && hdrs & ICE_FLOW_SEG_HDR_ARP) {
730390bd141SQi Zhang 			bitmap_and(params->ptypes, params->ptypes,
731390bd141SQi Zhang 				   (const unsigned long *)ice_ptypes_arp_of,
732390bd141SQi Zhang 				   ICE_FLOW_PTYPE_MAX);
733390bd141SQi Zhang 		}
7347012dfd1SQi Zhang 
735051d2b5cSDan Nowlin 		if ((hdrs & ICE_FLOW_SEG_HDR_IPV4) &&
7367012dfd1SQi Zhang 		    (hdrs & ICE_FLOW_SEG_HDR_IPV_OTHER)) {
7377012dfd1SQi Zhang 			src = i ? (const unsigned long *)ice_ptypes_ipv4_il :
7387012dfd1SQi Zhang 				(const unsigned long *)ice_ptypes_ipv4_ofos_all;
7397012dfd1SQi Zhang 			bitmap_and(params->ptypes, params->ptypes, src,
7407012dfd1SQi Zhang 				   ICE_FLOW_PTYPE_MAX);
7417012dfd1SQi Zhang 		} else if ((hdrs & ICE_FLOW_SEG_HDR_IPV6) &&
7427012dfd1SQi Zhang 			   (hdrs & ICE_FLOW_SEG_HDR_IPV_OTHER)) {
7437012dfd1SQi Zhang 			src = i ? (const unsigned long *)ice_ptypes_ipv6_il :
7447012dfd1SQi Zhang 				(const unsigned long *)ice_ptypes_ipv6_ofos_all;
7457012dfd1SQi Zhang 			bitmap_and(params->ptypes, params->ptypes, src,
7467012dfd1SQi Zhang 				   ICE_FLOW_PTYPE_MAX);
7477012dfd1SQi Zhang 		} else if ((hdrs & ICE_FLOW_SEG_HDR_IPV4) &&
7487012dfd1SQi Zhang 			   !(hdrs & ICE_FLOW_SEG_HDRS_L4_MASK_NO_OTHER)) {
74994a93698SQi Zhang 			src = !i ? (const unsigned long *)ice_ptypes_ipv4_ofos_no_l4 :
75094a93698SQi Zhang 				(const unsigned long *)ice_ptypes_ipv4_il_no_l4;
751051d2b5cSDan Nowlin 			bitmap_and(params->ptypes, params->ptypes, src,
752051d2b5cSDan Nowlin 				   ICE_FLOW_PTYPE_MAX);
753051d2b5cSDan Nowlin 		} else if (hdrs & ICE_FLOW_SEG_HDR_IPV4) {
75431ad4e4eSTony Nguyen 			src = !i ? (const unsigned long *)ice_ptypes_ipv4_ofos :
75531ad4e4eSTony Nguyen 				(const unsigned long *)ice_ptypes_ipv4_il;
75631ad4e4eSTony Nguyen 			bitmap_and(params->ptypes, params->ptypes, src,
75731ad4e4eSTony Nguyen 				   ICE_FLOW_PTYPE_MAX);
758051d2b5cSDan Nowlin 		} else if ((hdrs & ICE_FLOW_SEG_HDR_IPV6) &&
7597012dfd1SQi Zhang 			   !(hdrs & ICE_FLOW_SEG_HDRS_L4_MASK_NO_OTHER)) {
76094a93698SQi Zhang 			src = !i ? (const unsigned long *)ice_ptypes_ipv6_ofos_no_l4 :
76194a93698SQi Zhang 				(const unsigned long *)ice_ptypes_ipv6_il_no_l4;
762051d2b5cSDan Nowlin 			bitmap_and(params->ptypes, params->ptypes, src,
763051d2b5cSDan Nowlin 				   ICE_FLOW_PTYPE_MAX);
76431ad4e4eSTony Nguyen 		} else if (hdrs & ICE_FLOW_SEG_HDR_IPV6) {
76531ad4e4eSTony Nguyen 			src = !i ? (const unsigned long *)ice_ptypes_ipv6_ofos :
76631ad4e4eSTony Nguyen 				(const unsigned long *)ice_ptypes_ipv6_il;
76731ad4e4eSTony Nguyen 			bitmap_and(params->ptypes, params->ptypes, src,
76831ad4e4eSTony Nguyen 				   ICE_FLOW_PTYPE_MAX);
76931ad4e4eSTony Nguyen 		}
77031ad4e4eSTony Nguyen 
77121606584SQi Zhang 		if (hdrs & ICE_FLOW_SEG_HDR_ETH_NON_IP) {
77221606584SQi Zhang 			src = (const unsigned long *)ice_ptypes_mac_non_ip_ofos;
77321606584SQi Zhang 			bitmap_and(params->ptypes, params->ptypes, src,
77421606584SQi Zhang 				   ICE_FLOW_PTYPE_MAX);
77521606584SQi Zhang 		} else if (hdrs & ICE_FLOW_SEG_HDR_PPPOE) {
7760577313eSQi Zhang 			src = (const unsigned long *)ice_ptypes_pppoe;
7770577313eSQi Zhang 			bitmap_and(params->ptypes, params->ptypes, src,
7780577313eSQi Zhang 				   ICE_FLOW_PTYPE_MAX);
7790577313eSQi Zhang 		} else {
7800577313eSQi Zhang 			src = (const unsigned long *)ice_ptypes_pppoe;
7810577313eSQi Zhang 			bitmap_andnot(params->ptypes, params->ptypes, src,
7820577313eSQi Zhang 				      ICE_FLOW_PTYPE_MAX);
7830577313eSQi Zhang 		}
7840577313eSQi Zhang 
78531ad4e4eSTony Nguyen 		if (hdrs & ICE_FLOW_SEG_HDR_UDP) {
78631ad4e4eSTony Nguyen 			src = (const unsigned long *)ice_ptypes_udp_il;
78731ad4e4eSTony Nguyen 			bitmap_and(params->ptypes, params->ptypes, src,
78831ad4e4eSTony Nguyen 				   ICE_FLOW_PTYPE_MAX);
78931ad4e4eSTony Nguyen 		} else if (hdrs & ICE_FLOW_SEG_HDR_TCP) {
79031ad4e4eSTony Nguyen 			bitmap_and(params->ptypes, params->ptypes,
79131ad4e4eSTony Nguyen 				   (const unsigned long *)ice_ptypes_tcp_il,
79231ad4e4eSTony Nguyen 				   ICE_FLOW_PTYPE_MAX);
79331ad4e4eSTony Nguyen 		} else if (hdrs & ICE_FLOW_SEG_HDR_SCTP) {
79431ad4e4eSTony Nguyen 			src = (const unsigned long *)ice_ptypes_sctp_il;
79531ad4e4eSTony Nguyen 			bitmap_and(params->ptypes, params->ptypes, src,
79631ad4e4eSTony Nguyen 				   ICE_FLOW_PTYPE_MAX);
797390bd141SQi Zhang 		}
798390bd141SQi Zhang 
799390bd141SQi Zhang 		if (hdrs & ICE_FLOW_SEG_HDR_ICMP) {
800390bd141SQi Zhang 			src = !i ? (const unsigned long *)ice_ptypes_icmp_of :
801390bd141SQi Zhang 				(const unsigned long *)ice_ptypes_icmp_il;
802390bd141SQi Zhang 			bitmap_and(params->ptypes, params->ptypes, src,
803390bd141SQi Zhang 				   ICE_FLOW_PTYPE_MAX);
804a4e82a81STony Nguyen 		} else if (hdrs & ICE_FLOW_SEG_HDR_GRE) {
805a4e82a81STony Nguyen 			if (!i) {
806a4e82a81STony Nguyen 				src = (const unsigned long *)ice_ptypes_gre_of;
807a4e82a81STony Nguyen 				bitmap_and(params->ptypes, params->ptypes,
808a4e82a81STony Nguyen 					   src, ICE_FLOW_PTYPE_MAX);
809a4e82a81STony Nguyen 			}
8100577313eSQi Zhang 		} else if (hdrs & ICE_FLOW_SEG_HDR_GTPC) {
8110577313eSQi Zhang 			src = (const unsigned long *)ice_ptypes_gtpc;
8120577313eSQi Zhang 			bitmap_and(params->ptypes, params->ptypes, src,
8130577313eSQi Zhang 				   ICE_FLOW_PTYPE_MAX);
8140577313eSQi Zhang 		} else if (hdrs & ICE_FLOW_SEG_HDR_GTPC_TEID) {
8150577313eSQi Zhang 			src = (const unsigned long *)ice_ptypes_gtpc_tid;
8160577313eSQi Zhang 			bitmap_and(params->ptypes, params->ptypes, src,
8170577313eSQi Zhang 				   ICE_FLOW_PTYPE_MAX);
8180577313eSQi Zhang 		} else if (hdrs & ICE_FLOW_SEG_HDR_GTPU_DWN) {
8190577313eSQi Zhang 			src = (const unsigned long *)ice_ptypes_gtpu;
8200577313eSQi Zhang 			bitmap_and(params->ptypes, params->ptypes, src,
8210577313eSQi Zhang 				   ICE_FLOW_PTYPE_MAX);
822cbad5db8SQi Zhang 
823cbad5db8SQi Zhang 			/* Attributes for GTP packet with downlink */
824cbad5db8SQi Zhang 			params->attr = ice_attr_gtpu_down;
825cbad5db8SQi Zhang 			params->attr_cnt = ARRAY_SIZE(ice_attr_gtpu_down);
8260577313eSQi Zhang 		} else if (hdrs & ICE_FLOW_SEG_HDR_GTPU_UP) {
8270577313eSQi Zhang 			src = (const unsigned long *)ice_ptypes_gtpu;
8280577313eSQi Zhang 			bitmap_and(params->ptypes, params->ptypes, src,
8290577313eSQi Zhang 				   ICE_FLOW_PTYPE_MAX);
830cbad5db8SQi Zhang 
831cbad5db8SQi Zhang 			/* Attributes for GTP packet with uplink */
832cbad5db8SQi Zhang 			params->attr = ice_attr_gtpu_up;
833cbad5db8SQi Zhang 			params->attr_cnt = ARRAY_SIZE(ice_attr_gtpu_up);
8340577313eSQi Zhang 		} else if (hdrs & ICE_FLOW_SEG_HDR_GTPU_EH) {
8350577313eSQi Zhang 			src = (const unsigned long *)ice_ptypes_gtpu;
8360577313eSQi Zhang 			bitmap_and(params->ptypes, params->ptypes, src,
8370577313eSQi Zhang 				   ICE_FLOW_PTYPE_MAX);
838cbad5db8SQi Zhang 
839cbad5db8SQi Zhang 			/* Attributes for GTP packet with Extension Header */
840cbad5db8SQi Zhang 			params->attr = ice_attr_gtpu_eh;
841cbad5db8SQi Zhang 			params->attr_cnt = ARRAY_SIZE(ice_attr_gtpu_eh);
8420577313eSQi Zhang 		} else if (hdrs & ICE_FLOW_SEG_HDR_GTPU_IP) {
8430577313eSQi Zhang 			src = (const unsigned long *)ice_ptypes_gtpu;
8440577313eSQi Zhang 			bitmap_and(params->ptypes, params->ptypes, src,
8450577313eSQi Zhang 				   ICE_FLOW_PTYPE_MAX);
8460577313eSQi Zhang 		} else if (hdrs & ICE_FLOW_SEG_HDR_L2TPV3) {
8470577313eSQi Zhang 			src = (const unsigned long *)ice_ptypes_l2tpv3;
8480577313eSQi Zhang 			bitmap_and(params->ptypes, params->ptypes, src,
8490577313eSQi Zhang 				   ICE_FLOW_PTYPE_MAX);
8500577313eSQi Zhang 		} else if (hdrs & ICE_FLOW_SEG_HDR_ESP) {
8510577313eSQi Zhang 			src = (const unsigned long *)ice_ptypes_esp;
8520577313eSQi Zhang 			bitmap_and(params->ptypes, params->ptypes, src,
8530577313eSQi Zhang 				   ICE_FLOW_PTYPE_MAX);
8540577313eSQi Zhang 		} else if (hdrs & ICE_FLOW_SEG_HDR_AH) {
8550577313eSQi Zhang 			src = (const unsigned long *)ice_ptypes_ah;
8560577313eSQi Zhang 			bitmap_and(params->ptypes, params->ptypes, src,
8570577313eSQi Zhang 				   ICE_FLOW_PTYPE_MAX);
8580577313eSQi Zhang 		} else if (hdrs & ICE_FLOW_SEG_HDR_NAT_T_ESP) {
8590577313eSQi Zhang 			src = (const unsigned long *)ice_ptypes_nat_t_esp;
8600577313eSQi Zhang 			bitmap_and(params->ptypes, params->ptypes, src,
8610577313eSQi Zhang 				   ICE_FLOW_PTYPE_MAX);
8620577313eSQi Zhang 		}
8630577313eSQi Zhang 
8640577313eSQi Zhang 		if (hdrs & ICE_FLOW_SEG_HDR_PFCP) {
8650577313eSQi Zhang 			if (hdrs & ICE_FLOW_SEG_HDR_PFCP_NODE)
8660577313eSQi Zhang 				src = (const unsigned long *)ice_ptypes_pfcp_node;
8670577313eSQi Zhang 			else
8680577313eSQi Zhang 				src = (const unsigned long *)ice_ptypes_pfcp_session;
8690577313eSQi Zhang 
8700577313eSQi Zhang 			bitmap_and(params->ptypes, params->ptypes, src,
8710577313eSQi Zhang 				   ICE_FLOW_PTYPE_MAX);
8720577313eSQi Zhang 		} else {
8730577313eSQi Zhang 			src = (const unsigned long *)ice_ptypes_pfcp_node;
8740577313eSQi Zhang 			bitmap_andnot(params->ptypes, params->ptypes, src,
8750577313eSQi Zhang 				      ICE_FLOW_PTYPE_MAX);
8760577313eSQi Zhang 
8770577313eSQi Zhang 			src = (const unsigned long *)ice_ptypes_pfcp_session;
8780577313eSQi Zhang 			bitmap_andnot(params->ptypes, params->ptypes, src,
8790577313eSQi Zhang 				      ICE_FLOW_PTYPE_MAX);
88031ad4e4eSTony Nguyen 		}
88131ad4e4eSTony Nguyen 	}
88231ad4e4eSTony Nguyen 
88331ad4e4eSTony Nguyen 	return 0;
88431ad4e4eSTony Nguyen }
88531ad4e4eSTony Nguyen 
88631ad4e4eSTony Nguyen /**
88731ad4e4eSTony Nguyen  * ice_flow_xtract_fld - Create an extraction sequence entry for the given field
88831ad4e4eSTony Nguyen  * @hw: pointer to the HW struct
88931ad4e4eSTony Nguyen  * @params: information about the flow to be processed
89031ad4e4eSTony Nguyen  * @seg: packet segment index of the field to be extracted
89131ad4e4eSTony Nguyen  * @fld: ID of field to be extracted
892b199dddbSQi Zhang  * @match: bit field of all fields
89331ad4e4eSTony Nguyen  *
89431ad4e4eSTony Nguyen  * This function determines the protocol ID, offset, and size of the given
89531ad4e4eSTony Nguyen  * field. It then allocates one or more extraction sequence entries for the
89631ad4e4eSTony Nguyen  * given field, and fill the entries with protocol ID and offset information.
89731ad4e4eSTony Nguyen  */
8985e24d598STony Nguyen static int
ice_flow_xtract_fld(struct ice_hw * hw,struct ice_flow_prof_params * params,u8 seg,enum ice_flow_field fld,u64 match)89931ad4e4eSTony Nguyen ice_flow_xtract_fld(struct ice_hw *hw, struct ice_flow_prof_params *params,
900b199dddbSQi Zhang 		    u8 seg, enum ice_flow_field fld, u64 match)
90131ad4e4eSTony Nguyen {
902b199dddbSQi Zhang 	enum ice_flow_field sib = ICE_FLOW_FIELD_IDX_MAX;
90331ad4e4eSTony Nguyen 	enum ice_prot_id prot_id = ICE_PROT_ID_INVAL;
90431ad4e4eSTony Nguyen 	u8 fv_words = hw->blk[params->blk].es.fvw;
90531ad4e4eSTony Nguyen 	struct ice_flow_fld_info *flds;
90631ad4e4eSTony Nguyen 	u16 cnt, ese_bits, i;
907b199dddbSQi Zhang 	u16 sib_mask = 0;
908b199dddbSQi Zhang 	u16 mask;
90931ad4e4eSTony Nguyen 	u16 off;
91031ad4e4eSTony Nguyen 
91131ad4e4eSTony Nguyen 	flds = params->prof->segs[seg].fields;
91231ad4e4eSTony Nguyen 
91331ad4e4eSTony Nguyen 	switch (fld) {
914390bd141SQi Zhang 	case ICE_FLOW_FIELD_IDX_ETH_DA:
915390bd141SQi Zhang 	case ICE_FLOW_FIELD_IDX_ETH_SA:
916390bd141SQi Zhang 	case ICE_FLOW_FIELD_IDX_S_VLAN:
917390bd141SQi Zhang 	case ICE_FLOW_FIELD_IDX_C_VLAN:
918390bd141SQi Zhang 		prot_id = seg == 0 ? ICE_PROT_MAC_OF_OR_S : ICE_PROT_MAC_IL;
919390bd141SQi Zhang 		break;
920390bd141SQi Zhang 	case ICE_FLOW_FIELD_IDX_ETH_TYPE:
921390bd141SQi Zhang 		prot_id = seg == 0 ? ICE_PROT_ETYPE_OL : ICE_PROT_ETYPE_IL;
922390bd141SQi Zhang 		break;
923b199dddbSQi Zhang 	case ICE_FLOW_FIELD_IDX_IPV4_DSCP:
924b199dddbSQi Zhang 		prot_id = seg == 0 ? ICE_PROT_IPV4_OF_OR_S : ICE_PROT_IPV4_IL;
925b199dddbSQi Zhang 		break;
926b199dddbSQi Zhang 	case ICE_FLOW_FIELD_IDX_IPV6_DSCP:
927b199dddbSQi Zhang 		prot_id = seg == 0 ? ICE_PROT_IPV6_OF_OR_S : ICE_PROT_IPV6_IL;
928b199dddbSQi Zhang 		break;
929b199dddbSQi Zhang 	case ICE_FLOW_FIELD_IDX_IPV4_TTL:
930b199dddbSQi Zhang 	case ICE_FLOW_FIELD_IDX_IPV4_PROT:
931b199dddbSQi Zhang 		prot_id = seg == 0 ? ICE_PROT_IPV4_OF_OR_S : ICE_PROT_IPV4_IL;
932b199dddbSQi Zhang 
933b199dddbSQi Zhang 		/* TTL and PROT share the same extraction seq. entry.
934b199dddbSQi Zhang 		 * Each is considered a sibling to the other in terms of sharing
935b199dddbSQi Zhang 		 * the same extraction sequence entry.
936b199dddbSQi Zhang 		 */
937b199dddbSQi Zhang 		if (fld == ICE_FLOW_FIELD_IDX_IPV4_TTL)
938b199dddbSQi Zhang 			sib = ICE_FLOW_FIELD_IDX_IPV4_PROT;
939b199dddbSQi Zhang 		else if (fld == ICE_FLOW_FIELD_IDX_IPV4_PROT)
940b199dddbSQi Zhang 			sib = ICE_FLOW_FIELD_IDX_IPV4_TTL;
941b199dddbSQi Zhang 
942b199dddbSQi Zhang 		/* If the sibling field is also included, that field's
943b199dddbSQi Zhang 		 * mask needs to be included.
944b199dddbSQi Zhang 		 */
945b199dddbSQi Zhang 		if (match & BIT(sib))
946b199dddbSQi Zhang 			sib_mask = ice_flds_info[sib].mask;
947b199dddbSQi Zhang 		break;
948b199dddbSQi Zhang 	case ICE_FLOW_FIELD_IDX_IPV6_TTL:
949b199dddbSQi Zhang 	case ICE_FLOW_FIELD_IDX_IPV6_PROT:
950b199dddbSQi Zhang 		prot_id = seg == 0 ? ICE_PROT_IPV6_OF_OR_S : ICE_PROT_IPV6_IL;
951b199dddbSQi Zhang 
952b199dddbSQi Zhang 		/* TTL and PROT share the same extraction seq. entry.
953b199dddbSQi Zhang 		 * Each is considered a sibling to the other in terms of sharing
954b199dddbSQi Zhang 		 * the same extraction sequence entry.
955b199dddbSQi Zhang 		 */
956b199dddbSQi Zhang 		if (fld == ICE_FLOW_FIELD_IDX_IPV6_TTL)
957b199dddbSQi Zhang 			sib = ICE_FLOW_FIELD_IDX_IPV6_PROT;
958b199dddbSQi Zhang 		else if (fld == ICE_FLOW_FIELD_IDX_IPV6_PROT)
959b199dddbSQi Zhang 			sib = ICE_FLOW_FIELD_IDX_IPV6_TTL;
960b199dddbSQi Zhang 
961b199dddbSQi Zhang 		/* If the sibling field is also included, that field's
962b199dddbSQi Zhang 		 * mask needs to be included.
963b199dddbSQi Zhang 		 */
964b199dddbSQi Zhang 		if (match & BIT(sib))
965b199dddbSQi Zhang 			sib_mask = ice_flds_info[sib].mask;
966b199dddbSQi Zhang 		break;
96731ad4e4eSTony Nguyen 	case ICE_FLOW_FIELD_IDX_IPV4_SA:
96831ad4e4eSTony Nguyen 	case ICE_FLOW_FIELD_IDX_IPV4_DA:
96931ad4e4eSTony Nguyen 		prot_id = seg == 0 ? ICE_PROT_IPV4_OF_OR_S : ICE_PROT_IPV4_IL;
97031ad4e4eSTony Nguyen 		break;
97131ad4e4eSTony Nguyen 	case ICE_FLOW_FIELD_IDX_IPV6_SA:
97231ad4e4eSTony Nguyen 	case ICE_FLOW_FIELD_IDX_IPV6_DA:
97331ad4e4eSTony Nguyen 		prot_id = seg == 0 ? ICE_PROT_IPV6_OF_OR_S : ICE_PROT_IPV6_IL;
97431ad4e4eSTony Nguyen 		break;
97531ad4e4eSTony Nguyen 	case ICE_FLOW_FIELD_IDX_TCP_SRC_PORT:
97631ad4e4eSTony Nguyen 	case ICE_FLOW_FIELD_IDX_TCP_DST_PORT:
977390bd141SQi Zhang 	case ICE_FLOW_FIELD_IDX_TCP_FLAGS:
97831ad4e4eSTony Nguyen 		prot_id = ICE_PROT_TCP_IL;
97931ad4e4eSTony Nguyen 		break;
98031ad4e4eSTony Nguyen 	case ICE_FLOW_FIELD_IDX_UDP_SRC_PORT:
98131ad4e4eSTony Nguyen 	case ICE_FLOW_FIELD_IDX_UDP_DST_PORT:
98231ad4e4eSTony Nguyen 		prot_id = ICE_PROT_UDP_IL_OR_S;
98331ad4e4eSTony Nguyen 		break;
9841c01c8c6SMd Fahad Iqbal Polash 	case ICE_FLOW_FIELD_IDX_SCTP_SRC_PORT:
9851c01c8c6SMd Fahad Iqbal Polash 	case ICE_FLOW_FIELD_IDX_SCTP_DST_PORT:
9861c01c8c6SMd Fahad Iqbal Polash 		prot_id = ICE_PROT_SCTP_IL;
9871c01c8c6SMd Fahad Iqbal Polash 		break;
9880577313eSQi Zhang 	case ICE_FLOW_FIELD_IDX_GTPC_TEID:
9890577313eSQi Zhang 	case ICE_FLOW_FIELD_IDX_GTPU_IP_TEID:
9900577313eSQi Zhang 	case ICE_FLOW_FIELD_IDX_GTPU_UP_TEID:
9910577313eSQi Zhang 	case ICE_FLOW_FIELD_IDX_GTPU_DWN_TEID:
9920577313eSQi Zhang 	case ICE_FLOW_FIELD_IDX_GTPU_EH_TEID:
9930577313eSQi Zhang 	case ICE_FLOW_FIELD_IDX_GTPU_EH_QFI:
9940577313eSQi Zhang 		/* GTP is accessed through UDP OF protocol */
9950577313eSQi Zhang 		prot_id = ICE_PROT_UDP_OF;
9960577313eSQi Zhang 		break;
9970577313eSQi Zhang 	case ICE_FLOW_FIELD_IDX_PPPOE_SESS_ID:
9980577313eSQi Zhang 		prot_id = ICE_PROT_PPPOE;
9990577313eSQi Zhang 		break;
10000577313eSQi Zhang 	case ICE_FLOW_FIELD_IDX_PFCP_SEID:
10010577313eSQi Zhang 		prot_id = ICE_PROT_UDP_IL_OR_S;
10020577313eSQi Zhang 		break;
10030577313eSQi Zhang 	case ICE_FLOW_FIELD_IDX_L2TPV3_SESS_ID:
10040577313eSQi Zhang 		prot_id = ICE_PROT_L2TPV3;
10050577313eSQi Zhang 		break;
10060577313eSQi Zhang 	case ICE_FLOW_FIELD_IDX_ESP_SPI:
10070577313eSQi Zhang 		prot_id = ICE_PROT_ESP_F;
10080577313eSQi Zhang 		break;
10090577313eSQi Zhang 	case ICE_FLOW_FIELD_IDX_AH_SPI:
10100577313eSQi Zhang 		prot_id = ICE_PROT_ESP_2;
10110577313eSQi Zhang 		break;
10120577313eSQi Zhang 	case ICE_FLOW_FIELD_IDX_NAT_T_ESP_SPI:
10130577313eSQi Zhang 		prot_id = ICE_PROT_UDP_IL_OR_S;
10140577313eSQi Zhang 		break;
1015390bd141SQi Zhang 	case ICE_FLOW_FIELD_IDX_ARP_SIP:
1016390bd141SQi Zhang 	case ICE_FLOW_FIELD_IDX_ARP_DIP:
1017390bd141SQi Zhang 	case ICE_FLOW_FIELD_IDX_ARP_SHA:
1018390bd141SQi Zhang 	case ICE_FLOW_FIELD_IDX_ARP_DHA:
1019390bd141SQi Zhang 	case ICE_FLOW_FIELD_IDX_ARP_OP:
1020390bd141SQi Zhang 		prot_id = ICE_PROT_ARP_OF;
1021390bd141SQi Zhang 		break;
1022390bd141SQi Zhang 	case ICE_FLOW_FIELD_IDX_ICMP_TYPE:
1023390bd141SQi Zhang 	case ICE_FLOW_FIELD_IDX_ICMP_CODE:
1024390bd141SQi Zhang 		/* ICMP type and code share the same extraction seq. entry */
1025390bd141SQi Zhang 		prot_id = (params->prof->segs[seg].hdrs & ICE_FLOW_SEG_HDR_IPV4) ?
1026390bd141SQi Zhang 				ICE_PROT_ICMP_IL : ICE_PROT_ICMPV6_IL;
1027b199dddbSQi Zhang 		sib = fld == ICE_FLOW_FIELD_IDX_ICMP_TYPE ?
1028b199dddbSQi Zhang 			ICE_FLOW_FIELD_IDX_ICMP_CODE :
1029b199dddbSQi Zhang 			ICE_FLOW_FIELD_IDX_ICMP_TYPE;
1030390bd141SQi Zhang 		break;
1031a4e82a81STony Nguyen 	case ICE_FLOW_FIELD_IDX_GRE_KEYID:
1032a4e82a81STony Nguyen 		prot_id = ICE_PROT_GRE_OF;
1033a4e82a81STony Nguyen 		break;
103431ad4e4eSTony Nguyen 	default:
1035d54699e2STony Nguyen 		return -EOPNOTSUPP;
103631ad4e4eSTony Nguyen 	}
103731ad4e4eSTony Nguyen 
103831ad4e4eSTony Nguyen 	/* Each extraction sequence entry is a word in size, and extracts a
103931ad4e4eSTony Nguyen 	 * word-aligned offset from a protocol header.
104031ad4e4eSTony Nguyen 	 */
104131ad4e4eSTony Nguyen 	ese_bits = ICE_FLOW_FV_EXTRACT_SZ * BITS_PER_BYTE;
104231ad4e4eSTony Nguyen 
104331ad4e4eSTony Nguyen 	flds[fld].xtrct.prot_id = prot_id;
104431ad4e4eSTony Nguyen 	flds[fld].xtrct.off = (ice_flds_info[fld].off / ese_bits) *
104531ad4e4eSTony Nguyen 		ICE_FLOW_FV_EXTRACT_SZ;
104631ad4e4eSTony Nguyen 	flds[fld].xtrct.disp = (u8)(ice_flds_info[fld].off % ese_bits);
104731ad4e4eSTony Nguyen 	flds[fld].xtrct.idx = params->es_cnt;
1048b199dddbSQi Zhang 	flds[fld].xtrct.mask = ice_flds_info[fld].mask;
104931ad4e4eSTony Nguyen 
105031ad4e4eSTony Nguyen 	/* Adjust the next field-entry index after accommodating the number of
105131ad4e4eSTony Nguyen 	 * entries this field consumes
105231ad4e4eSTony Nguyen 	 */
105331ad4e4eSTony Nguyen 	cnt = DIV_ROUND_UP(flds[fld].xtrct.disp + ice_flds_info[fld].size,
105431ad4e4eSTony Nguyen 			   ese_bits);
105531ad4e4eSTony Nguyen 
105631ad4e4eSTony Nguyen 	/* Fill in the extraction sequence entries needed for this field */
105731ad4e4eSTony Nguyen 	off = flds[fld].xtrct.off;
1058b199dddbSQi Zhang 	mask = flds[fld].xtrct.mask;
105931ad4e4eSTony Nguyen 	for (i = 0; i < cnt; i++) {
1060b199dddbSQi Zhang 		/* Only consume an extraction sequence entry if there is no
1061b199dddbSQi Zhang 		 * sibling field associated with this field or the sibling entry
1062b199dddbSQi Zhang 		 * already extracts the word shared with this field.
1063b199dddbSQi Zhang 		 */
1064b199dddbSQi Zhang 		if (sib == ICE_FLOW_FIELD_IDX_MAX ||
1065b199dddbSQi Zhang 		    flds[sib].xtrct.prot_id == ICE_PROT_ID_INVAL ||
1066b199dddbSQi Zhang 		    flds[sib].xtrct.off != off) {
106731ad4e4eSTony Nguyen 			u8 idx;
106831ad4e4eSTony Nguyen 
106931ad4e4eSTony Nguyen 			/* Make sure the number of extraction sequence required
107031ad4e4eSTony Nguyen 			 * does not exceed the block's capability
107131ad4e4eSTony Nguyen 			 */
107231ad4e4eSTony Nguyen 			if (params->es_cnt >= fv_words)
1073d54699e2STony Nguyen 				return -ENOSPC;
107431ad4e4eSTony Nguyen 
107531ad4e4eSTony Nguyen 			/* some blocks require a reversed field vector layout */
107631ad4e4eSTony Nguyen 			if (hw->blk[params->blk].es.reverse)
107731ad4e4eSTony Nguyen 				idx = fv_words - params->es_cnt - 1;
107831ad4e4eSTony Nguyen 			else
107931ad4e4eSTony Nguyen 				idx = params->es_cnt;
108031ad4e4eSTony Nguyen 
108131ad4e4eSTony Nguyen 			params->es[idx].prot_id = prot_id;
108231ad4e4eSTony Nguyen 			params->es[idx].off = off;
1083b199dddbSQi Zhang 			params->mask[idx] = mask | sib_mask;
108431ad4e4eSTony Nguyen 			params->es_cnt++;
1085b199dddbSQi Zhang 		}
108631ad4e4eSTony Nguyen 
108731ad4e4eSTony Nguyen 		off += ICE_FLOW_FV_EXTRACT_SZ;
108831ad4e4eSTony Nguyen 	}
108931ad4e4eSTony Nguyen 
109031ad4e4eSTony Nguyen 	return 0;
109131ad4e4eSTony Nguyen }
109231ad4e4eSTony Nguyen 
109331ad4e4eSTony Nguyen /**
10942c57ffcbSHenry Tieman  * ice_flow_xtract_raws - Create extract sequence entries for raw bytes
10952c57ffcbSHenry Tieman  * @hw: pointer to the HW struct
10962c57ffcbSHenry Tieman  * @params: information about the flow to be processed
1097ac382a09SBruce Allan  * @seg: index of packet segment whose raw fields are to be extracted
10982c57ffcbSHenry Tieman  */
10995e24d598STony Nguyen static int
ice_flow_xtract_raws(struct ice_hw * hw,struct ice_flow_prof_params * params,u8 seg)11002c57ffcbSHenry Tieman ice_flow_xtract_raws(struct ice_hw *hw, struct ice_flow_prof_params *params,
11012c57ffcbSHenry Tieman 		     u8 seg)
11022c57ffcbSHenry Tieman {
11032c57ffcbSHenry Tieman 	u16 fv_words;
11042c57ffcbSHenry Tieman 	u16 hdrs_sz;
11052c57ffcbSHenry Tieman 	u8 i;
11062c57ffcbSHenry Tieman 
11072c57ffcbSHenry Tieman 	if (!params->prof->segs[seg].raws_cnt)
11082c57ffcbSHenry Tieman 		return 0;
11092c57ffcbSHenry Tieman 
11102c57ffcbSHenry Tieman 	if (params->prof->segs[seg].raws_cnt >
11112c57ffcbSHenry Tieman 	    ARRAY_SIZE(params->prof->segs[seg].raws))
1112d54699e2STony Nguyen 		return -ENOSPC;
11132c57ffcbSHenry Tieman 
11142c57ffcbSHenry Tieman 	/* Offsets within the segment headers are not supported */
11152c57ffcbSHenry Tieman 	hdrs_sz = ice_flow_calc_seg_sz(params, seg);
11162c57ffcbSHenry Tieman 	if (!hdrs_sz)
1117d54699e2STony Nguyen 		return -EINVAL;
11182c57ffcbSHenry Tieman 
11192c57ffcbSHenry Tieman 	fv_words = hw->blk[params->blk].es.fvw;
11202c57ffcbSHenry Tieman 
11212c57ffcbSHenry Tieman 	for (i = 0; i < params->prof->segs[seg].raws_cnt; i++) {
11222c57ffcbSHenry Tieman 		struct ice_flow_seg_fld_raw *raw;
11232c57ffcbSHenry Tieman 		u16 off, cnt, j;
11242c57ffcbSHenry Tieman 
11252c57ffcbSHenry Tieman 		raw = &params->prof->segs[seg].raws[i];
11262c57ffcbSHenry Tieman 
11272c57ffcbSHenry Tieman 		/* Storing extraction information */
11282c57ffcbSHenry Tieman 		raw->info.xtrct.prot_id = ICE_PROT_MAC_OF_OR_S;
11292c57ffcbSHenry Tieman 		raw->info.xtrct.off = (raw->off / ICE_FLOW_FV_EXTRACT_SZ) *
11302c57ffcbSHenry Tieman 			ICE_FLOW_FV_EXTRACT_SZ;
11312c57ffcbSHenry Tieman 		raw->info.xtrct.disp = (raw->off % ICE_FLOW_FV_EXTRACT_SZ) *
11322c57ffcbSHenry Tieman 			BITS_PER_BYTE;
11332c57ffcbSHenry Tieman 		raw->info.xtrct.idx = params->es_cnt;
11342c57ffcbSHenry Tieman 
11352c57ffcbSHenry Tieman 		/* Determine the number of field vector entries this raw field
11362c57ffcbSHenry Tieman 		 * consumes.
11372c57ffcbSHenry Tieman 		 */
11382c57ffcbSHenry Tieman 		cnt = DIV_ROUND_UP(raw->info.xtrct.disp +
11392c57ffcbSHenry Tieman 				   (raw->info.src.last * BITS_PER_BYTE),
11402c57ffcbSHenry Tieman 				   (ICE_FLOW_FV_EXTRACT_SZ * BITS_PER_BYTE));
11412c57ffcbSHenry Tieman 		off = raw->info.xtrct.off;
11422c57ffcbSHenry Tieman 		for (j = 0; j < cnt; j++) {
11432c57ffcbSHenry Tieman 			u16 idx;
11442c57ffcbSHenry Tieman 
11452c57ffcbSHenry Tieman 			/* Make sure the number of extraction sequence required
11462c57ffcbSHenry Tieman 			 * does not exceed the block's capability
11472c57ffcbSHenry Tieman 			 */
11482c57ffcbSHenry Tieman 			if (params->es_cnt >= hw->blk[params->blk].es.count ||
11492c57ffcbSHenry Tieman 			    params->es_cnt >= ICE_MAX_FV_WORDS)
1150d54699e2STony Nguyen 				return -ENOSPC;
11512c57ffcbSHenry Tieman 
11522c57ffcbSHenry Tieman 			/* some blocks require a reversed field vector layout */
11532c57ffcbSHenry Tieman 			if (hw->blk[params->blk].es.reverse)
11542c57ffcbSHenry Tieman 				idx = fv_words - params->es_cnt - 1;
11552c57ffcbSHenry Tieman 			else
11562c57ffcbSHenry Tieman 				idx = params->es_cnt;
11572c57ffcbSHenry Tieman 
11582c57ffcbSHenry Tieman 			params->es[idx].prot_id = raw->info.xtrct.prot_id;
11592c57ffcbSHenry Tieman 			params->es[idx].off = off;
11602c57ffcbSHenry Tieman 			params->es_cnt++;
11612c57ffcbSHenry Tieman 			off += ICE_FLOW_FV_EXTRACT_SZ;
11622c57ffcbSHenry Tieman 		}
11632c57ffcbSHenry Tieman 	}
11642c57ffcbSHenry Tieman 
11652c57ffcbSHenry Tieman 	return 0;
11662c57ffcbSHenry Tieman }
11672c57ffcbSHenry Tieman 
11682c57ffcbSHenry Tieman /**
116931ad4e4eSTony Nguyen  * ice_flow_create_xtrct_seq - Create an extraction sequence for given segments
117031ad4e4eSTony Nguyen  * @hw: pointer to the HW struct
117131ad4e4eSTony Nguyen  * @params: information about the flow to be processed
117231ad4e4eSTony Nguyen  *
117331ad4e4eSTony Nguyen  * This function iterates through all matched fields in the given segments, and
117431ad4e4eSTony Nguyen  * creates an extraction sequence for the fields.
117531ad4e4eSTony Nguyen  */
11765e24d598STony Nguyen static int
ice_flow_create_xtrct_seq(struct ice_hw * hw,struct ice_flow_prof_params * params)117731ad4e4eSTony Nguyen ice_flow_create_xtrct_seq(struct ice_hw *hw,
117831ad4e4eSTony Nguyen 			  struct ice_flow_prof_params *params)
117931ad4e4eSTony Nguyen {
118031ad4e4eSTony Nguyen 	struct ice_flow_prof *prof = params->prof;
11815e24d598STony Nguyen 	int status = 0;
118231ad4e4eSTony Nguyen 	u8 i;
118331ad4e4eSTony Nguyen 
118431ad4e4eSTony Nguyen 	for (i = 0; i < prof->segs_cnt; i++) {
1185b199dddbSQi Zhang 		u64 match = params->prof->segs[i].match;
1186b199dddbSQi Zhang 		enum ice_flow_field j;
118731ad4e4eSTony Nguyen 
1188b199dddbSQi Zhang 		for_each_set_bit(j, (unsigned long *)&match,
118931ad4e4eSTony Nguyen 				 ICE_FLOW_FIELD_IDX_MAX) {
1190b199dddbSQi Zhang 			status = ice_flow_xtract_fld(hw, params, i, j, match);
119131ad4e4eSTony Nguyen 			if (status)
119231ad4e4eSTony Nguyen 				return status;
1193b199dddbSQi Zhang 			clear_bit(j, (unsigned long *)&match);
119431ad4e4eSTony Nguyen 		}
11952c57ffcbSHenry Tieman 
11962c57ffcbSHenry Tieman 		/* Process raw matching bytes */
11972c57ffcbSHenry Tieman 		status = ice_flow_xtract_raws(hw, params, i);
11982c57ffcbSHenry Tieman 		if (status)
11992c57ffcbSHenry Tieman 			return status;
120031ad4e4eSTony Nguyen 	}
120131ad4e4eSTony Nguyen 
120231ad4e4eSTony Nguyen 	return status;
120331ad4e4eSTony Nguyen }
120431ad4e4eSTony Nguyen 
120531ad4e4eSTony Nguyen /**
120631ad4e4eSTony Nguyen  * ice_flow_proc_segs - process all packet segments associated with a profile
120731ad4e4eSTony Nguyen  * @hw: pointer to the HW struct
120831ad4e4eSTony Nguyen  * @params: information about the flow to be processed
120931ad4e4eSTony Nguyen  */
12105e24d598STony Nguyen static int
ice_flow_proc_segs(struct ice_hw * hw,struct ice_flow_prof_params * params)121131ad4e4eSTony Nguyen ice_flow_proc_segs(struct ice_hw *hw, struct ice_flow_prof_params *params)
121231ad4e4eSTony Nguyen {
12135e24d598STony Nguyen 	int status;
121431ad4e4eSTony Nguyen 
121531ad4e4eSTony Nguyen 	status = ice_flow_proc_seg_hdrs(params);
121631ad4e4eSTony Nguyen 	if (status)
121731ad4e4eSTony Nguyen 		return status;
121831ad4e4eSTony Nguyen 
121931ad4e4eSTony Nguyen 	status = ice_flow_create_xtrct_seq(hw, params);
122031ad4e4eSTony Nguyen 	if (status)
122131ad4e4eSTony Nguyen 		return status;
122231ad4e4eSTony Nguyen 
122331ad4e4eSTony Nguyen 	switch (params->blk) {
1224148beb61SHenry Tieman 	case ICE_BLK_FD:
122531ad4e4eSTony Nguyen 	case ICE_BLK_RSS:
122631ad4e4eSTony Nguyen 		status = 0;
122731ad4e4eSTony Nguyen 		break;
122831ad4e4eSTony Nguyen 	default:
1229d54699e2STony Nguyen 		return -EOPNOTSUPP;
123031ad4e4eSTony Nguyen 	}
123131ad4e4eSTony Nguyen 
123231ad4e4eSTony Nguyen 	return status;
123331ad4e4eSTony Nguyen }
123431ad4e4eSTony Nguyen 
12352c61054cSTony Nguyen #define ICE_FLOW_FIND_PROF_CHK_FLDS	0x00000001
12362c61054cSTony Nguyen #define ICE_FLOW_FIND_PROF_CHK_VSI	0x00000002
12372c61054cSTony Nguyen #define ICE_FLOW_FIND_PROF_NOT_CHK_DIR	0x00000004
12382c61054cSTony Nguyen 
12392c61054cSTony Nguyen /**
12402c61054cSTony Nguyen  * ice_flow_find_prof_conds - Find a profile matching headers and conditions
12412c61054cSTony Nguyen  * @hw: pointer to the HW struct
12422c61054cSTony Nguyen  * @blk: classification stage
12432c61054cSTony Nguyen  * @dir: flow direction
12442c61054cSTony Nguyen  * @segs: array of one or more packet segments that describe the flow
12452c61054cSTony Nguyen  * @segs_cnt: number of packet segments provided
12462c61054cSTony Nguyen  * @vsi_handle: software VSI handle to check VSI (ICE_FLOW_FIND_PROF_CHK_VSI)
12472c61054cSTony Nguyen  * @conds: additional conditions to be checked (ICE_FLOW_FIND_PROF_CHK_*)
12482c61054cSTony Nguyen  */
12492c61054cSTony Nguyen static struct ice_flow_prof *
ice_flow_find_prof_conds(struct ice_hw * hw,enum ice_block blk,enum ice_flow_dir dir,struct ice_flow_seg_info * segs,u8 segs_cnt,u16 vsi_handle,u32 conds)12502c61054cSTony Nguyen ice_flow_find_prof_conds(struct ice_hw *hw, enum ice_block blk,
12512c61054cSTony Nguyen 			 enum ice_flow_dir dir, struct ice_flow_seg_info *segs,
12522c61054cSTony Nguyen 			 u8 segs_cnt, u16 vsi_handle, u32 conds)
12532c61054cSTony Nguyen {
12542c61054cSTony Nguyen 	struct ice_flow_prof *p, *prof = NULL;
12552c61054cSTony Nguyen 
12562c61054cSTony Nguyen 	mutex_lock(&hw->fl_profs_locks[blk]);
12572c61054cSTony Nguyen 	list_for_each_entry(p, &hw->fl_profs[blk], l_entry)
12582c61054cSTony Nguyen 		if ((p->dir == dir || conds & ICE_FLOW_FIND_PROF_NOT_CHK_DIR) &&
12592c61054cSTony Nguyen 		    segs_cnt && segs_cnt == p->segs_cnt) {
12602c61054cSTony Nguyen 			u8 i;
12612c61054cSTony Nguyen 
12622c61054cSTony Nguyen 			/* Check for profile-VSI association if specified */
12632c61054cSTony Nguyen 			if ((conds & ICE_FLOW_FIND_PROF_CHK_VSI) &&
12642c61054cSTony Nguyen 			    ice_is_vsi_valid(hw, vsi_handle) &&
12652c61054cSTony Nguyen 			    !test_bit(vsi_handle, p->vsis))
12662c61054cSTony Nguyen 				continue;
12672c61054cSTony Nguyen 
12682c61054cSTony Nguyen 			/* Protocol headers must be checked. Matched fields are
12692c61054cSTony Nguyen 			 * checked if specified.
12702c61054cSTony Nguyen 			 */
12712c61054cSTony Nguyen 			for (i = 0; i < segs_cnt; i++)
12722c61054cSTony Nguyen 				if (segs[i].hdrs != p->segs[i].hdrs ||
12732c61054cSTony Nguyen 				    ((conds & ICE_FLOW_FIND_PROF_CHK_FLDS) &&
12742c61054cSTony Nguyen 				     segs[i].match != p->segs[i].match))
12752c61054cSTony Nguyen 					break;
12762c61054cSTony Nguyen 
12772c61054cSTony Nguyen 			/* A match is found if all segments are matched */
12782c61054cSTony Nguyen 			if (i == segs_cnt) {
12792c61054cSTony Nguyen 				prof = p;
12802c61054cSTony Nguyen 				break;
12812c61054cSTony Nguyen 			}
12822c61054cSTony Nguyen 		}
12832c61054cSTony Nguyen 	mutex_unlock(&hw->fl_profs_locks[blk]);
12842c61054cSTony Nguyen 
12852c61054cSTony Nguyen 	return prof;
12862c61054cSTony Nguyen }
12872c61054cSTony Nguyen 
12882c61054cSTony Nguyen /**
12892c61054cSTony Nguyen  * ice_flow_find_prof_id - Look up a profile with given profile ID
12902c61054cSTony Nguyen  * @hw: pointer to the HW struct
12912c61054cSTony Nguyen  * @blk: classification stage
12922c61054cSTony Nguyen  * @prof_id: unique ID to identify this flow profile
12932c61054cSTony Nguyen  */
12942c61054cSTony Nguyen static struct ice_flow_prof *
ice_flow_find_prof_id(struct ice_hw * hw,enum ice_block blk,u64 prof_id)12952c61054cSTony Nguyen ice_flow_find_prof_id(struct ice_hw *hw, enum ice_block blk, u64 prof_id)
12962c61054cSTony Nguyen {
12972c61054cSTony Nguyen 	struct ice_flow_prof *p;
12982c61054cSTony Nguyen 
12992c61054cSTony Nguyen 	list_for_each_entry(p, &hw->fl_profs[blk], l_entry)
13002c61054cSTony Nguyen 		if (p->id == prof_id)
13012c61054cSTony Nguyen 			return p;
13022c61054cSTony Nguyen 
13032c61054cSTony Nguyen 	return NULL;
13042c61054cSTony Nguyen }
13052c61054cSTony Nguyen 
130631ad4e4eSTony Nguyen /**
1307148beb61SHenry Tieman  * ice_flow_rem_entry_sync - Remove a flow entry
1308148beb61SHenry Tieman  * @hw: pointer to the HW struct
1309148beb61SHenry Tieman  * @blk: classification stage
1310148beb61SHenry Tieman  * @entry: flow entry to be removed
1311148beb61SHenry Tieman  */
13125e24d598STony Nguyen static int
ice_flow_rem_entry_sync(struct ice_hw * hw,enum ice_block __always_unused blk,struct ice_flow_entry * entry)1313148beb61SHenry Tieman ice_flow_rem_entry_sync(struct ice_hw *hw, enum ice_block __always_unused blk,
1314148beb61SHenry Tieman 			struct ice_flow_entry *entry)
1315148beb61SHenry Tieman {
1316148beb61SHenry Tieman 	if (!entry)
1317d54699e2STony Nguyen 		return -EINVAL;
1318148beb61SHenry Tieman 
1319148beb61SHenry Tieman 	list_del(&entry->l_entry);
1320148beb61SHenry Tieman 
1321*ad667d62SPrzemek Kitszel 	devm_kfree(ice_hw_to_dev(hw), entry->entry);
1322*ad667d62SPrzemek Kitszel 	devm_kfree(ice_hw_to_dev(hw), entry);
1323148beb61SHenry Tieman 
1324148beb61SHenry Tieman 	return 0;
1325148beb61SHenry Tieman }
1326148beb61SHenry Tieman 
1327148beb61SHenry Tieman /**
132831ad4e4eSTony Nguyen  * ice_flow_add_prof_sync - Add a flow profile for packet segments and fields
132931ad4e4eSTony Nguyen  * @hw: pointer to the HW struct
133031ad4e4eSTony Nguyen  * @blk: classification stage
133131ad4e4eSTony Nguyen  * @dir: flow direction
133231ad4e4eSTony Nguyen  * @prof_id: unique ID to identify this flow profile
133331ad4e4eSTony Nguyen  * @segs: array of one or more packet segments that describe the flow
133431ad4e4eSTony Nguyen  * @segs_cnt: number of packet segments provided
133531ad4e4eSTony Nguyen  * @prof: stores the returned flow profile added
133631ad4e4eSTony Nguyen  *
133731ad4e4eSTony Nguyen  * Assumption: the caller has acquired the lock to the profile list
133831ad4e4eSTony Nguyen  */
13395e24d598STony Nguyen static int
ice_flow_add_prof_sync(struct ice_hw * hw,enum ice_block blk,enum ice_flow_dir dir,u64 prof_id,struct ice_flow_seg_info * segs,u8 segs_cnt,struct ice_flow_prof ** prof)134031ad4e4eSTony Nguyen ice_flow_add_prof_sync(struct ice_hw *hw, enum ice_block blk,
134131ad4e4eSTony Nguyen 		       enum ice_flow_dir dir, u64 prof_id,
134231ad4e4eSTony Nguyen 		       struct ice_flow_seg_info *segs, u8 segs_cnt,
134331ad4e4eSTony Nguyen 		       struct ice_flow_prof **prof)
134431ad4e4eSTony Nguyen {
134588dcfdb4SBruce Allan 	struct ice_flow_prof_params *params;
13465e24d598STony Nguyen 	int status;
134731ad4e4eSTony Nguyen 	u8 i;
134831ad4e4eSTony Nguyen 
134931ad4e4eSTony Nguyen 	if (!prof)
1350d54699e2STony Nguyen 		return -EINVAL;
135131ad4e4eSTony Nguyen 
135288dcfdb4SBruce Allan 	params = kzalloc(sizeof(*params), GFP_KERNEL);
135388dcfdb4SBruce Allan 	if (!params)
1354d54699e2STony Nguyen 		return -ENOMEM;
135531ad4e4eSTony Nguyen 
135688dcfdb4SBruce Allan 	params->prof = devm_kzalloc(ice_hw_to_dev(hw), sizeof(*params->prof),
135788dcfdb4SBruce Allan 				    GFP_KERNEL);
135888dcfdb4SBruce Allan 	if (!params->prof) {
1359d54699e2STony Nguyen 		status = -ENOMEM;
136088dcfdb4SBruce Allan 		goto free_params;
136188dcfdb4SBruce Allan 	}
136288dcfdb4SBruce Allan 
136331ad4e4eSTony Nguyen 	/* initialize extraction sequence to all invalid (0xff) */
136431ad4e4eSTony Nguyen 	for (i = 0; i < ICE_MAX_FV_WORDS; i++) {
136588dcfdb4SBruce Allan 		params->es[i].prot_id = ICE_PROT_INVALID;
136688dcfdb4SBruce Allan 		params->es[i].off = ICE_FV_OFFSET_INVAL;
136731ad4e4eSTony Nguyen 	}
136831ad4e4eSTony Nguyen 
136988dcfdb4SBruce Allan 	params->blk = blk;
137088dcfdb4SBruce Allan 	params->prof->id = prof_id;
137188dcfdb4SBruce Allan 	params->prof->dir = dir;
137288dcfdb4SBruce Allan 	params->prof->segs_cnt = segs_cnt;
137331ad4e4eSTony Nguyen 
137431ad4e4eSTony Nguyen 	/* Make a copy of the segments that need to be persistent in the flow
137531ad4e4eSTony Nguyen 	 * profile instance
137631ad4e4eSTony Nguyen 	 */
137731ad4e4eSTony Nguyen 	for (i = 0; i < segs_cnt; i++)
137888dcfdb4SBruce Allan 		memcpy(&params->prof->segs[i], &segs[i], sizeof(*segs));
137931ad4e4eSTony Nguyen 
138088dcfdb4SBruce Allan 	status = ice_flow_proc_segs(hw, params);
138131ad4e4eSTony Nguyen 	if (status) {
13829228d8b2SJacob Keller 		ice_debug(hw, ICE_DBG_FLOW, "Error processing a flow's packet segments\n");
138331ad4e4eSTony Nguyen 		goto out;
138431ad4e4eSTony Nguyen 	}
138531ad4e4eSTony Nguyen 
138631ad4e4eSTony Nguyen 	/* Add a HW profile for this flow profile */
138788dcfdb4SBruce Allan 	status = ice_add_prof(hw, blk, prof_id, (u8 *)params->ptypes,
1388cbad5db8SQi Zhang 			      params->attr, params->attr_cnt, params->es,
1389cbad5db8SQi Zhang 			      params->mask);
139031ad4e4eSTony Nguyen 	if (status) {
139131ad4e4eSTony Nguyen 		ice_debug(hw, ICE_DBG_FLOW, "Error adding a HW flow profile\n");
139231ad4e4eSTony Nguyen 		goto out;
139331ad4e4eSTony Nguyen 	}
139431ad4e4eSTony Nguyen 
139588dcfdb4SBruce Allan 	INIT_LIST_HEAD(&params->prof->entries);
139688dcfdb4SBruce Allan 	mutex_init(&params->prof->entries_lock);
139788dcfdb4SBruce Allan 	*prof = params->prof;
139831ad4e4eSTony Nguyen 
139931ad4e4eSTony Nguyen out:
140031ad4e4eSTony Nguyen 	if (status)
140188dcfdb4SBruce Allan 		devm_kfree(ice_hw_to_dev(hw), params->prof);
140288dcfdb4SBruce Allan free_params:
140388dcfdb4SBruce Allan 	kfree(params);
140431ad4e4eSTony Nguyen 
140531ad4e4eSTony Nguyen 	return status;
140631ad4e4eSTony Nguyen }
140731ad4e4eSTony Nguyen 
140831ad4e4eSTony Nguyen /**
14092c61054cSTony Nguyen  * ice_flow_rem_prof_sync - remove a flow profile
14102c61054cSTony Nguyen  * @hw: pointer to the hardware structure
14112c61054cSTony Nguyen  * @blk: classification stage
14122c61054cSTony Nguyen  * @prof: pointer to flow profile to remove
14132c61054cSTony Nguyen  *
14142c61054cSTony Nguyen  * Assumption: the caller has acquired the lock to the profile list
14152c61054cSTony Nguyen  */
14165e24d598STony Nguyen static int
ice_flow_rem_prof_sync(struct ice_hw * hw,enum ice_block blk,struct ice_flow_prof * prof)14172c61054cSTony Nguyen ice_flow_rem_prof_sync(struct ice_hw *hw, enum ice_block blk,
14182c61054cSTony Nguyen 		       struct ice_flow_prof *prof)
14192c61054cSTony Nguyen {
14205e24d598STony Nguyen 	int status;
14212c61054cSTony Nguyen 
1422148beb61SHenry Tieman 	/* Remove all remaining flow entries before removing the flow profile */
1423148beb61SHenry Tieman 	if (!list_empty(&prof->entries)) {
1424148beb61SHenry Tieman 		struct ice_flow_entry *e, *t;
1425148beb61SHenry Tieman 
1426148beb61SHenry Tieman 		mutex_lock(&prof->entries_lock);
1427148beb61SHenry Tieman 
1428148beb61SHenry Tieman 		list_for_each_entry_safe(e, t, &prof->entries, l_entry) {
1429148beb61SHenry Tieman 			status = ice_flow_rem_entry_sync(hw, blk, e);
1430148beb61SHenry Tieman 			if (status)
1431148beb61SHenry Tieman 				break;
1432148beb61SHenry Tieman 		}
1433148beb61SHenry Tieman 
1434148beb61SHenry Tieman 		mutex_unlock(&prof->entries_lock);
1435148beb61SHenry Tieman 	}
1436148beb61SHenry Tieman 
14372c61054cSTony Nguyen 	/* Remove all hardware profiles associated with this flow profile */
14382c61054cSTony Nguyen 	status = ice_rem_prof(hw, blk, prof->id);
14392c61054cSTony Nguyen 	if (!status) {
14402c61054cSTony Nguyen 		list_del(&prof->l_entry);
14412c61054cSTony Nguyen 		mutex_destroy(&prof->entries_lock);
14422c61054cSTony Nguyen 		devm_kfree(ice_hw_to_dev(hw), prof);
14432c61054cSTony Nguyen 	}
14442c61054cSTony Nguyen 
14452c61054cSTony Nguyen 	return status;
14462c61054cSTony Nguyen }
14472c61054cSTony Nguyen 
14482c61054cSTony Nguyen /**
1449451f2c44STony Nguyen  * ice_flow_assoc_prof - associate a VSI with a flow profile
1450451f2c44STony Nguyen  * @hw: pointer to the hardware structure
1451451f2c44STony Nguyen  * @blk: classification stage
1452451f2c44STony Nguyen  * @prof: pointer to flow profile
1453451f2c44STony Nguyen  * @vsi_handle: software VSI handle
1454451f2c44STony Nguyen  *
1455451f2c44STony Nguyen  * Assumption: the caller has acquired the lock to the profile list
1456451f2c44STony Nguyen  * and the software VSI handle has been validated
1457451f2c44STony Nguyen  */
14585e24d598STony Nguyen static int
ice_flow_assoc_prof(struct ice_hw * hw,enum ice_block blk,struct ice_flow_prof * prof,u16 vsi_handle)1459451f2c44STony Nguyen ice_flow_assoc_prof(struct ice_hw *hw, enum ice_block blk,
1460451f2c44STony Nguyen 		    struct ice_flow_prof *prof, u16 vsi_handle)
1461451f2c44STony Nguyen {
14625e24d598STony Nguyen 	int status = 0;
1463451f2c44STony Nguyen 
1464451f2c44STony Nguyen 	if (!test_bit(vsi_handle, prof->vsis)) {
1465451f2c44STony Nguyen 		status = ice_add_prof_id_flow(hw, blk,
1466451f2c44STony Nguyen 					      ice_get_hw_vsi_num(hw,
1467451f2c44STony Nguyen 								 vsi_handle),
1468451f2c44STony Nguyen 					      prof->id);
1469451f2c44STony Nguyen 		if (!status)
1470451f2c44STony Nguyen 			set_bit(vsi_handle, prof->vsis);
1471451f2c44STony Nguyen 		else
14729228d8b2SJacob Keller 			ice_debug(hw, ICE_DBG_FLOW, "HW profile add failed, %d\n",
1473451f2c44STony Nguyen 				  status);
1474451f2c44STony Nguyen 	}
1475451f2c44STony Nguyen 
1476451f2c44STony Nguyen 	return status;
1477451f2c44STony Nguyen }
1478451f2c44STony Nguyen 
1479451f2c44STony Nguyen /**
14802c61054cSTony Nguyen  * ice_flow_disassoc_prof - disassociate a VSI from a flow profile
14812c61054cSTony Nguyen  * @hw: pointer to the hardware structure
14822c61054cSTony Nguyen  * @blk: classification stage
14832c61054cSTony Nguyen  * @prof: pointer to flow profile
14842c61054cSTony Nguyen  * @vsi_handle: software VSI handle
14852c61054cSTony Nguyen  *
14862c61054cSTony Nguyen  * Assumption: the caller has acquired the lock to the profile list
14872c61054cSTony Nguyen  * and the software VSI handle has been validated
14882c61054cSTony Nguyen  */
14895e24d598STony Nguyen static int
ice_flow_disassoc_prof(struct ice_hw * hw,enum ice_block blk,struct ice_flow_prof * prof,u16 vsi_handle)14902c61054cSTony Nguyen ice_flow_disassoc_prof(struct ice_hw *hw, enum ice_block blk,
14912c61054cSTony Nguyen 		       struct ice_flow_prof *prof, u16 vsi_handle)
14922c61054cSTony Nguyen {
14935e24d598STony Nguyen 	int status = 0;
14942c61054cSTony Nguyen 
14952c61054cSTony Nguyen 	if (test_bit(vsi_handle, prof->vsis)) {
14962c61054cSTony Nguyen 		status = ice_rem_prof_id_flow(hw, blk,
14972c61054cSTony Nguyen 					      ice_get_hw_vsi_num(hw,
14982c61054cSTony Nguyen 								 vsi_handle),
14992c61054cSTony Nguyen 					      prof->id);
15002c61054cSTony Nguyen 		if (!status)
15012c61054cSTony Nguyen 			clear_bit(vsi_handle, prof->vsis);
15022c61054cSTony Nguyen 		else
15039228d8b2SJacob Keller 			ice_debug(hw, ICE_DBG_FLOW, "HW profile remove failed, %d\n",
15042c61054cSTony Nguyen 				  status);
15052c61054cSTony Nguyen 	}
15062c61054cSTony Nguyen 
15072c61054cSTony Nguyen 	return status;
15082c61054cSTony Nguyen }
15092c61054cSTony Nguyen 
15102c61054cSTony Nguyen /**
151131ad4e4eSTony Nguyen  * ice_flow_add_prof - Add a flow profile for packet segments and matched fields
151231ad4e4eSTony Nguyen  * @hw: pointer to the HW struct
151331ad4e4eSTony Nguyen  * @blk: classification stage
151431ad4e4eSTony Nguyen  * @dir: flow direction
151531ad4e4eSTony Nguyen  * @prof_id: unique ID to identify this flow profile
151631ad4e4eSTony Nguyen  * @segs: array of one or more packet segments that describe the flow
151731ad4e4eSTony Nguyen  * @segs_cnt: number of packet segments provided
1518451f2c44STony Nguyen  * @prof: stores the returned flow profile added
151931ad4e4eSTony Nguyen  */
15205e24d598STony Nguyen int
ice_flow_add_prof(struct ice_hw * hw,enum ice_block blk,enum ice_flow_dir dir,u64 prof_id,struct ice_flow_seg_info * segs,u8 segs_cnt,struct ice_flow_prof ** prof)152131ad4e4eSTony Nguyen ice_flow_add_prof(struct ice_hw *hw, enum ice_block blk, enum ice_flow_dir dir,
1522451f2c44STony Nguyen 		  u64 prof_id, struct ice_flow_seg_info *segs, u8 segs_cnt,
1523451f2c44STony Nguyen 		  struct ice_flow_prof **prof)
152431ad4e4eSTony Nguyen {
15255e24d598STony Nguyen 	int status;
152631ad4e4eSTony Nguyen 
152731ad4e4eSTony Nguyen 	if (segs_cnt > ICE_FLOW_SEG_MAX)
1528d54699e2STony Nguyen 		return -ENOSPC;
152931ad4e4eSTony Nguyen 
153031ad4e4eSTony Nguyen 	if (!segs_cnt)
1531d54699e2STony Nguyen 		return -EINVAL;
153231ad4e4eSTony Nguyen 
153331ad4e4eSTony Nguyen 	if (!segs)
1534d54699e2STony Nguyen 		return -EINVAL;
153531ad4e4eSTony Nguyen 
153631ad4e4eSTony Nguyen 	status = ice_flow_val_hdrs(segs, segs_cnt);
153731ad4e4eSTony Nguyen 	if (status)
153831ad4e4eSTony Nguyen 		return status;
153931ad4e4eSTony Nguyen 
154031ad4e4eSTony Nguyen 	mutex_lock(&hw->fl_profs_locks[blk]);
154131ad4e4eSTony Nguyen 
154231ad4e4eSTony Nguyen 	status = ice_flow_add_prof_sync(hw, blk, dir, prof_id, segs, segs_cnt,
1543451f2c44STony Nguyen 					prof);
154431ad4e4eSTony Nguyen 	if (!status)
1545451f2c44STony Nguyen 		list_add(&(*prof)->l_entry, &hw->fl_profs[blk]);
154631ad4e4eSTony Nguyen 
154731ad4e4eSTony Nguyen 	mutex_unlock(&hw->fl_profs_locks[blk]);
154831ad4e4eSTony Nguyen 
154931ad4e4eSTony Nguyen 	return status;
155031ad4e4eSTony Nguyen }
155131ad4e4eSTony Nguyen 
1552c90ed40cSTony Nguyen /**
15532c61054cSTony Nguyen  * ice_flow_rem_prof - Remove a flow profile and all entries associated with it
15542c61054cSTony Nguyen  * @hw: pointer to the HW struct
15552c61054cSTony Nguyen  * @blk: the block for which the flow profile is to be removed
15562c61054cSTony Nguyen  * @prof_id: unique ID of the flow profile to be removed
15572c61054cSTony Nguyen  */
ice_flow_rem_prof(struct ice_hw * hw,enum ice_block blk,u64 prof_id)15585518ac2aSTony Nguyen int ice_flow_rem_prof(struct ice_hw *hw, enum ice_block blk, u64 prof_id)
15592c61054cSTony Nguyen {
15602c61054cSTony Nguyen 	struct ice_flow_prof *prof;
15615e24d598STony Nguyen 	int status;
15622c61054cSTony Nguyen 
15632c61054cSTony Nguyen 	mutex_lock(&hw->fl_profs_locks[blk]);
15642c61054cSTony Nguyen 
15652c61054cSTony Nguyen 	prof = ice_flow_find_prof_id(hw, blk, prof_id);
15662c61054cSTony Nguyen 	if (!prof) {
1567d54699e2STony Nguyen 		status = -ENOENT;
15682c61054cSTony Nguyen 		goto out;
15692c61054cSTony Nguyen 	}
15702c61054cSTony Nguyen 
15712c61054cSTony Nguyen 	/* prof becomes invalid after the call */
15722c61054cSTony Nguyen 	status = ice_flow_rem_prof_sync(hw, blk, prof);
15732c61054cSTony Nguyen 
15742c61054cSTony Nguyen out:
15752c61054cSTony Nguyen 	mutex_unlock(&hw->fl_profs_locks[blk]);
15762c61054cSTony Nguyen 
15772c61054cSTony Nguyen 	return status;
15782c61054cSTony Nguyen }
15792c61054cSTony Nguyen 
15802c61054cSTony Nguyen /**
1581148beb61SHenry Tieman  * ice_flow_add_entry - Add a flow entry
1582148beb61SHenry Tieman  * @hw: pointer to the HW struct
1583148beb61SHenry Tieman  * @blk: classification stage
1584148beb61SHenry Tieman  * @prof_id: ID of the profile to add a new flow entry to
1585148beb61SHenry Tieman  * @entry_id: unique ID to identify this flow entry
1586148beb61SHenry Tieman  * @vsi_handle: software VSI handle for the flow entry
1587148beb61SHenry Tieman  * @prio: priority of the flow entry
1588148beb61SHenry Tieman  * @data: pointer to a data buffer containing flow entry's match values/masks
1589148beb61SHenry Tieman  * @entry_h: pointer to buffer that receives the new flow entry's handle
1590148beb61SHenry Tieman  */
15915e24d598STony Nguyen int
ice_flow_add_entry(struct ice_hw * hw,enum ice_block blk,u64 prof_id,u64 entry_id,u16 vsi_handle,enum ice_flow_priority prio,void * data,u64 * entry_h)1592148beb61SHenry Tieman ice_flow_add_entry(struct ice_hw *hw, enum ice_block blk, u64 prof_id,
1593148beb61SHenry Tieman 		   u64 entry_id, u16 vsi_handle, enum ice_flow_priority prio,
1594148beb61SHenry Tieman 		   void *data, u64 *entry_h)
1595148beb61SHenry Tieman {
1596148beb61SHenry Tieman 	struct ice_flow_entry *e = NULL;
1597148beb61SHenry Tieman 	struct ice_flow_prof *prof;
15985e24d598STony Nguyen 	int status;
1599148beb61SHenry Tieman 
1600148beb61SHenry Tieman 	/* No flow entry data is expected for RSS */
1601148beb61SHenry Tieman 	if (!entry_h || (!data && blk != ICE_BLK_RSS))
1602d54699e2STony Nguyen 		return -EINVAL;
1603148beb61SHenry Tieman 
1604148beb61SHenry Tieman 	if (!ice_is_vsi_valid(hw, vsi_handle))
1605d54699e2STony Nguyen 		return -EINVAL;
1606148beb61SHenry Tieman 
1607148beb61SHenry Tieman 	mutex_lock(&hw->fl_profs_locks[blk]);
1608148beb61SHenry Tieman 
1609148beb61SHenry Tieman 	prof = ice_flow_find_prof_id(hw, blk, prof_id);
1610148beb61SHenry Tieman 	if (!prof) {
1611d54699e2STony Nguyen 		status = -ENOENT;
1612148beb61SHenry Tieman 	} else {
1613148beb61SHenry Tieman 		/* Allocate memory for the entry being added and associate
1614148beb61SHenry Tieman 		 * the VSI to the found flow profile
1615148beb61SHenry Tieman 		 */
1616148beb61SHenry Tieman 		e = devm_kzalloc(ice_hw_to_dev(hw), sizeof(*e), GFP_KERNEL);
1617148beb61SHenry Tieman 		if (!e)
1618d54699e2STony Nguyen 			status = -ENOMEM;
1619148beb61SHenry Tieman 		else
1620148beb61SHenry Tieman 			status = ice_flow_assoc_prof(hw, blk, prof, vsi_handle);
1621148beb61SHenry Tieman 	}
1622148beb61SHenry Tieman 
1623148beb61SHenry Tieman 	mutex_unlock(&hw->fl_profs_locks[blk]);
1624148beb61SHenry Tieman 	if (status)
1625148beb61SHenry Tieman 		goto out;
1626148beb61SHenry Tieman 
1627148beb61SHenry Tieman 	e->id = entry_id;
1628148beb61SHenry Tieman 	e->vsi_handle = vsi_handle;
1629148beb61SHenry Tieman 	e->prof = prof;
1630148beb61SHenry Tieman 	e->priority = prio;
1631148beb61SHenry Tieman 
1632148beb61SHenry Tieman 	switch (blk) {
1633148beb61SHenry Tieman 	case ICE_BLK_FD:
1634148beb61SHenry Tieman 	case ICE_BLK_RSS:
1635148beb61SHenry Tieman 		break;
1636148beb61SHenry Tieman 	default:
1637d54699e2STony Nguyen 		status = -EOPNOTSUPP;
1638148beb61SHenry Tieman 		goto out;
1639148beb61SHenry Tieman 	}
1640148beb61SHenry Tieman 
1641148beb61SHenry Tieman 	mutex_lock(&prof->entries_lock);
1642148beb61SHenry Tieman 	list_add(&e->l_entry, &prof->entries);
1643148beb61SHenry Tieman 	mutex_unlock(&prof->entries_lock);
1644148beb61SHenry Tieman 
1645148beb61SHenry Tieman 	*entry_h = ICE_FLOW_ENTRY_HNDL(e);
1646148beb61SHenry Tieman 
1647148beb61SHenry Tieman out:
1648148beb61SHenry Tieman 	if (status && e) {
1649148beb61SHenry Tieman 		devm_kfree(ice_hw_to_dev(hw), e->entry);
1650148beb61SHenry Tieman 		devm_kfree(ice_hw_to_dev(hw), e);
1651148beb61SHenry Tieman 	}
1652148beb61SHenry Tieman 
1653148beb61SHenry Tieman 	return status;
1654148beb61SHenry Tieman }
1655148beb61SHenry Tieman 
1656148beb61SHenry Tieman /**
1657148beb61SHenry Tieman  * ice_flow_rem_entry - Remove a flow entry
1658148beb61SHenry Tieman  * @hw: pointer to the HW struct
1659148beb61SHenry Tieman  * @blk: classification stage
1660148beb61SHenry Tieman  * @entry_h: handle to the flow entry to be removed
1661148beb61SHenry Tieman  */
ice_flow_rem_entry(struct ice_hw * hw,enum ice_block blk,u64 entry_h)16625518ac2aSTony Nguyen int ice_flow_rem_entry(struct ice_hw *hw, enum ice_block blk, u64 entry_h)
1663148beb61SHenry Tieman {
1664148beb61SHenry Tieman 	struct ice_flow_entry *entry;
1665148beb61SHenry Tieman 	struct ice_flow_prof *prof;
16665e24d598STony Nguyen 	int status = 0;
1667148beb61SHenry Tieman 
1668148beb61SHenry Tieman 	if (entry_h == ICE_FLOW_ENTRY_HANDLE_INVAL)
1669d54699e2STony Nguyen 		return -EINVAL;
1670148beb61SHenry Tieman 
1671148beb61SHenry Tieman 	entry = ICE_FLOW_ENTRY_PTR(entry_h);
1672148beb61SHenry Tieman 
1673148beb61SHenry Tieman 	/* Retain the pointer to the flow profile as the entry will be freed */
1674148beb61SHenry Tieman 	prof = entry->prof;
1675148beb61SHenry Tieman 
1676148beb61SHenry Tieman 	if (prof) {
1677148beb61SHenry Tieman 		mutex_lock(&prof->entries_lock);
1678148beb61SHenry Tieman 		status = ice_flow_rem_entry_sync(hw, blk, entry);
1679148beb61SHenry Tieman 		mutex_unlock(&prof->entries_lock);
1680148beb61SHenry Tieman 	}
1681148beb61SHenry Tieman 
1682148beb61SHenry Tieman 	return status;
1683148beb61SHenry Tieman }
1684148beb61SHenry Tieman 
1685148beb61SHenry Tieman /**
1686c90ed40cSTony Nguyen  * ice_flow_set_fld_ext - specifies locations of field from entry's input buffer
1687c90ed40cSTony Nguyen  * @seg: packet segment the field being set belongs to
1688c90ed40cSTony Nguyen  * @fld: field to be set
16896dae8aa0SBruce Allan  * @field_type: type of the field
1690c90ed40cSTony Nguyen  * @val_loc: if not ICE_FLOW_FLD_OFF_INVAL, location of the value to match from
1691c90ed40cSTony Nguyen  *           entry's input buffer
1692c90ed40cSTony Nguyen  * @mask_loc: if not ICE_FLOW_FLD_OFF_INVAL, location of mask value from entry's
1693c90ed40cSTony Nguyen  *            input buffer
1694c90ed40cSTony Nguyen  * @last_loc: if not ICE_FLOW_FLD_OFF_INVAL, location of last/upper value from
1695c90ed40cSTony Nguyen  *            entry's input buffer
1696c90ed40cSTony Nguyen  *
1697c90ed40cSTony Nguyen  * This helper function stores information of a field being matched, including
1698c90ed40cSTony Nguyen  * the type of the field and the locations of the value to match, the mask, and
1699ac382a09SBruce Allan  * the upper-bound value in the start of the input buffer for a flow entry.
1700c90ed40cSTony Nguyen  * This function should only be used for fixed-size data structures.
1701c90ed40cSTony Nguyen  *
1702c90ed40cSTony Nguyen  * This function also opportunistically determines the protocol headers to be
1703c90ed40cSTony Nguyen  * present based on the fields being set. Some fields cannot be used alone to
1704c90ed40cSTony Nguyen  * determine the protocol headers present. Sometimes, fields for particular
1705c90ed40cSTony Nguyen  * protocol headers are not matched. In those cases, the protocol headers
1706c90ed40cSTony Nguyen  * must be explicitly set.
1707c90ed40cSTony Nguyen  */
1708c90ed40cSTony Nguyen static void
ice_flow_set_fld_ext(struct ice_flow_seg_info * seg,enum ice_flow_field fld,enum ice_flow_fld_match_type field_type,u16 val_loc,u16 mask_loc,u16 last_loc)1709c90ed40cSTony Nguyen ice_flow_set_fld_ext(struct ice_flow_seg_info *seg, enum ice_flow_field fld,
17106dae8aa0SBruce Allan 		     enum ice_flow_fld_match_type field_type, u16 val_loc,
1711c90ed40cSTony Nguyen 		     u16 mask_loc, u16 last_loc)
1712c90ed40cSTony Nguyen {
1713c90ed40cSTony Nguyen 	u64 bit = BIT_ULL(fld);
1714c90ed40cSTony Nguyen 
1715c90ed40cSTony Nguyen 	seg->match |= bit;
17166dae8aa0SBruce Allan 	if (field_type == ICE_FLOW_FLD_TYPE_RANGE)
1717c90ed40cSTony Nguyen 		seg->range |= bit;
1718c90ed40cSTony Nguyen 
17196dae8aa0SBruce Allan 	seg->fields[fld].type = field_type;
1720c90ed40cSTony Nguyen 	seg->fields[fld].src.val = val_loc;
1721c90ed40cSTony Nguyen 	seg->fields[fld].src.mask = mask_loc;
1722c90ed40cSTony Nguyen 	seg->fields[fld].src.last = last_loc;
1723c90ed40cSTony Nguyen 
1724c90ed40cSTony Nguyen 	ICE_FLOW_SET_HDRS(seg, ice_flds_info[fld].hdr);
1725c90ed40cSTony Nguyen }
1726c90ed40cSTony Nguyen 
1727c90ed40cSTony Nguyen /**
1728c90ed40cSTony Nguyen  * ice_flow_set_fld - specifies locations of field from entry's input buffer
1729c90ed40cSTony Nguyen  * @seg: packet segment the field being set belongs to
1730c90ed40cSTony Nguyen  * @fld: field to be set
1731c90ed40cSTony Nguyen  * @val_loc: if not ICE_FLOW_FLD_OFF_INVAL, location of the value to match from
1732c90ed40cSTony Nguyen  *           entry's input buffer
1733c90ed40cSTony Nguyen  * @mask_loc: if not ICE_FLOW_FLD_OFF_INVAL, location of mask value from entry's
1734c90ed40cSTony Nguyen  *            input buffer
1735c90ed40cSTony Nguyen  * @last_loc: if not ICE_FLOW_FLD_OFF_INVAL, location of last/upper value from
1736c90ed40cSTony Nguyen  *            entry's input buffer
1737c90ed40cSTony Nguyen  * @range: indicate if field being matched is to be in a range
1738c90ed40cSTony Nguyen  *
1739c90ed40cSTony Nguyen  * This function specifies the locations, in the form of byte offsets from the
1740c90ed40cSTony Nguyen  * start of the input buffer for a flow entry, from where the value to match,
1741c90ed40cSTony Nguyen  * the mask value, and upper value can be extracted. These locations are then
1742c90ed40cSTony Nguyen  * stored in the flow profile. When adding a flow entry associated with the
1743c90ed40cSTony Nguyen  * flow profile, these locations will be used to quickly extract the values and
1744c90ed40cSTony Nguyen  * create the content of a match entry. This function should only be used for
1745c90ed40cSTony Nguyen  * fixed-size data structures.
1746c90ed40cSTony Nguyen  */
1747148beb61SHenry Tieman void
ice_flow_set_fld(struct ice_flow_seg_info * seg,enum ice_flow_field fld,u16 val_loc,u16 mask_loc,u16 last_loc,bool range)1748c90ed40cSTony Nguyen ice_flow_set_fld(struct ice_flow_seg_info *seg, enum ice_flow_field fld,
1749c90ed40cSTony Nguyen 		 u16 val_loc, u16 mask_loc, u16 last_loc, bool range)
1750c90ed40cSTony Nguyen {
1751c90ed40cSTony Nguyen 	enum ice_flow_fld_match_type t = range ?
1752c90ed40cSTony Nguyen 		ICE_FLOW_FLD_TYPE_RANGE : ICE_FLOW_FLD_TYPE_REG;
1753c90ed40cSTony Nguyen 
1754c90ed40cSTony Nguyen 	ice_flow_set_fld_ext(seg, fld, t, val_loc, mask_loc, last_loc);
1755c90ed40cSTony Nguyen }
1756c90ed40cSTony Nguyen 
17572c57ffcbSHenry Tieman /**
17582c57ffcbSHenry Tieman  * ice_flow_add_fld_raw - sets locations of a raw field from entry's input buf
17592c57ffcbSHenry Tieman  * @seg: packet segment the field being set belongs to
17602c57ffcbSHenry Tieman  * @off: offset of the raw field from the beginning of the segment in bytes
17612c57ffcbSHenry Tieman  * @len: length of the raw pattern to be matched
17622c57ffcbSHenry Tieman  * @val_loc: location of the value to match from entry's input buffer
17632c57ffcbSHenry Tieman  * @mask_loc: location of mask value from entry's input buffer
17642c57ffcbSHenry Tieman  *
17652c57ffcbSHenry Tieman  * This function specifies the offset of the raw field to be match from the
17662c57ffcbSHenry Tieman  * beginning of the specified packet segment, and the locations, in the form of
17672c57ffcbSHenry Tieman  * byte offsets from the start of the input buffer for a flow entry, from where
17682c57ffcbSHenry Tieman  * the value to match and the mask value to be extracted. These locations are
17692c57ffcbSHenry Tieman  * then stored in the flow profile. When adding flow entries to the associated
17702c57ffcbSHenry Tieman  * flow profile, these locations can be used to quickly extract the values to
17712c57ffcbSHenry Tieman  * create the content of a match entry. This function should only be used for
17722c57ffcbSHenry Tieman  * fixed-size data structures.
17732c57ffcbSHenry Tieman  */
17742c57ffcbSHenry Tieman void
ice_flow_add_fld_raw(struct ice_flow_seg_info * seg,u16 off,u8 len,u16 val_loc,u16 mask_loc)17752c57ffcbSHenry Tieman ice_flow_add_fld_raw(struct ice_flow_seg_info *seg, u16 off, u8 len,
17762c57ffcbSHenry Tieman 		     u16 val_loc, u16 mask_loc)
17772c57ffcbSHenry Tieman {
17782c57ffcbSHenry Tieman 	if (seg->raws_cnt < ICE_FLOW_SEG_RAW_FLD_MAX) {
17792c57ffcbSHenry Tieman 		seg->raws[seg->raws_cnt].off = off;
17802c57ffcbSHenry Tieman 		seg->raws[seg->raws_cnt].info.type = ICE_FLOW_FLD_TYPE_SIZE;
17812c57ffcbSHenry Tieman 		seg->raws[seg->raws_cnt].info.src.val = val_loc;
17822c57ffcbSHenry Tieman 		seg->raws[seg->raws_cnt].info.src.mask = mask_loc;
17832c57ffcbSHenry Tieman 		/* The "last" field is used to store the length of the field */
17842c57ffcbSHenry Tieman 		seg->raws[seg->raws_cnt].info.src.last = len;
17852c57ffcbSHenry Tieman 	}
17862c57ffcbSHenry Tieman 
17872c57ffcbSHenry Tieman 	/* Overflows of "raws" will be handled as an error condition later in
17882c57ffcbSHenry Tieman 	 * the flow when this information is processed.
17892c57ffcbSHenry Tieman 	 */
17902c57ffcbSHenry Tieman 	seg->raws_cnt++;
17912c57ffcbSHenry Tieman }
17922c57ffcbSHenry Tieman 
179340319796SKiran Patil /**
179440319796SKiran Patil  * ice_flow_rem_vsi_prof - remove VSI from flow profile
179540319796SKiran Patil  * @hw: pointer to the hardware structure
179640319796SKiran Patil  * @vsi_handle: software VSI handle
179740319796SKiran Patil  * @prof_id: unique ID to identify this flow profile
179840319796SKiran Patil  *
179940319796SKiran Patil  * This function removes the flow entries associated to the input
180040319796SKiran Patil  * VSI handle and disassociate the VSI from the flow profile.
180140319796SKiran Patil  */
ice_flow_rem_vsi_prof(struct ice_hw * hw,u16 vsi_handle,u64 prof_id)180240319796SKiran Patil int ice_flow_rem_vsi_prof(struct ice_hw *hw, u16 vsi_handle, u64 prof_id)
180340319796SKiran Patil {
180440319796SKiran Patil 	struct ice_flow_prof *prof;
180540319796SKiran Patil 	int status = 0;
180640319796SKiran Patil 
180740319796SKiran Patil 	if (!ice_is_vsi_valid(hw, vsi_handle))
180840319796SKiran Patil 		return -EINVAL;
180940319796SKiran Patil 
181040319796SKiran Patil 	/* find flow profile pointer with input package block and profile ID */
181140319796SKiran Patil 	prof = ice_flow_find_prof_id(hw, ICE_BLK_FD, prof_id);
181240319796SKiran Patil 	if (!prof) {
181340319796SKiran Patil 		ice_debug(hw, ICE_DBG_PKG, "Cannot find flow profile id=%llu\n",
181440319796SKiran Patil 			  prof_id);
181540319796SKiran Patil 		return -ENOENT;
181640319796SKiran Patil 	}
181740319796SKiran Patil 
181840319796SKiran Patil 	/* Remove all remaining flow entries before removing the flow profile */
181940319796SKiran Patil 	if (!list_empty(&prof->entries)) {
182040319796SKiran Patil 		struct ice_flow_entry *e, *t;
182140319796SKiran Patil 
182240319796SKiran Patil 		mutex_lock(&prof->entries_lock);
182340319796SKiran Patil 		list_for_each_entry_safe(e, t, &prof->entries, l_entry) {
182440319796SKiran Patil 			if (e->vsi_handle != vsi_handle)
182540319796SKiran Patil 				continue;
182640319796SKiran Patil 
182740319796SKiran Patil 			status = ice_flow_rem_entry_sync(hw, ICE_BLK_FD, e);
182840319796SKiran Patil 			if (status)
182940319796SKiran Patil 				break;
183040319796SKiran Patil 		}
183140319796SKiran Patil 		mutex_unlock(&prof->entries_lock);
183240319796SKiran Patil 	}
183340319796SKiran Patil 	if (status)
183440319796SKiran Patil 		return status;
183540319796SKiran Patil 
183640319796SKiran Patil 	/* disassociate the flow profile from sw VSI handle */
183740319796SKiran Patil 	status = ice_flow_disassoc_prof(hw, ICE_BLK_FD, prof, vsi_handle);
183840319796SKiran Patil 	if (status)
183940319796SKiran Patil 		ice_debug(hw, ICE_DBG_PKG, "ice_flow_disassoc_prof() failed with status=%d\n",
184040319796SKiran Patil 			  status);
184140319796SKiran Patil 	return status;
184240319796SKiran Patil }
184340319796SKiran Patil 
1844390bd141SQi Zhang #define ICE_FLOW_RSS_SEG_HDR_L2_MASKS \
1845390bd141SQi Zhang 	(ICE_FLOW_SEG_HDR_ETH | ICE_FLOW_SEG_HDR_VLAN)
1846390bd141SQi Zhang 
1847c90ed40cSTony Nguyen #define ICE_FLOW_RSS_SEG_HDR_L3_MASKS \
1848c90ed40cSTony Nguyen 	(ICE_FLOW_SEG_HDR_IPV4 | ICE_FLOW_SEG_HDR_IPV6)
1849c90ed40cSTony Nguyen 
1850c90ed40cSTony Nguyen #define ICE_FLOW_RSS_SEG_HDR_L4_MASKS \
1851c90ed40cSTony Nguyen 	(ICE_FLOW_SEG_HDR_TCP | ICE_FLOW_SEG_HDR_UDP | ICE_FLOW_SEG_HDR_SCTP)
1852c90ed40cSTony Nguyen 
1853c90ed40cSTony Nguyen #define ICE_FLOW_RSS_SEG_HDR_VAL_MASKS \
1854390bd141SQi Zhang 	(ICE_FLOW_RSS_SEG_HDR_L2_MASKS | \
1855390bd141SQi Zhang 	 ICE_FLOW_RSS_SEG_HDR_L3_MASKS | \
1856c90ed40cSTony Nguyen 	 ICE_FLOW_RSS_SEG_HDR_L4_MASKS)
1857c90ed40cSTony Nguyen 
1858c90ed40cSTony Nguyen /**
1859c90ed40cSTony Nguyen  * ice_flow_set_rss_seg_info - setup packet segments for RSS
1860c90ed40cSTony Nguyen  * @segs: pointer to the flow field segment(s)
1861c90ed40cSTony Nguyen  * @hash_fields: fields to be hashed on for the segment(s)
1862c90ed40cSTony Nguyen  * @flow_hdr: protocol header fields within a packet segment
1863c90ed40cSTony Nguyen  *
1864c90ed40cSTony Nguyen  * Helper function to extract fields from hash bitmap and use flow
1865c90ed40cSTony Nguyen  * header value to set flow field segment for further use in flow
1866c90ed40cSTony Nguyen  * profile entry or removal.
1867c90ed40cSTony Nguyen  */
18685e24d598STony Nguyen static int
ice_flow_set_rss_seg_info(struct ice_flow_seg_info * segs,u64 hash_fields,u32 flow_hdr)1869c90ed40cSTony Nguyen ice_flow_set_rss_seg_info(struct ice_flow_seg_info *segs, u64 hash_fields,
1870c90ed40cSTony Nguyen 			  u32 flow_hdr)
1871c90ed40cSTony Nguyen {
1872c90ed40cSTony Nguyen 	u64 val;
1873c90ed40cSTony Nguyen 	u8 i;
1874c90ed40cSTony Nguyen 
1875c90ed40cSTony Nguyen 	for_each_set_bit(i, (unsigned long *)&hash_fields,
1876c90ed40cSTony Nguyen 			 ICE_FLOW_FIELD_IDX_MAX)
1877c90ed40cSTony Nguyen 		ice_flow_set_fld(segs, (enum ice_flow_field)i,
1878c90ed40cSTony Nguyen 				 ICE_FLOW_FLD_OFF_INVAL, ICE_FLOW_FLD_OFF_INVAL,
1879c90ed40cSTony Nguyen 				 ICE_FLOW_FLD_OFF_INVAL, false);
1880c90ed40cSTony Nguyen 
1881c90ed40cSTony Nguyen 	ICE_FLOW_SET_HDRS(segs, flow_hdr);
1882c90ed40cSTony Nguyen 
18830577313eSQi Zhang 	if (segs->hdrs & ~ICE_FLOW_RSS_SEG_HDR_VAL_MASKS &
18847012dfd1SQi Zhang 	    ~ICE_FLOW_RSS_HDRS_INNER_MASK & ~ICE_FLOW_SEG_HDR_IPV_OTHER)
1885d54699e2STony Nguyen 		return -EINVAL;
1886c90ed40cSTony Nguyen 
1887c90ed40cSTony Nguyen 	val = (u64)(segs->hdrs & ICE_FLOW_RSS_SEG_HDR_L3_MASKS);
1888c90ed40cSTony Nguyen 	if (val && !is_power_of_2(val))
1889d54699e2STony Nguyen 		return -EIO;
1890c90ed40cSTony Nguyen 
1891c90ed40cSTony Nguyen 	val = (u64)(segs->hdrs & ICE_FLOW_RSS_SEG_HDR_L4_MASKS);
1892c90ed40cSTony Nguyen 	if (val && !is_power_of_2(val))
1893d54699e2STony Nguyen 		return -EIO;
1894c90ed40cSTony Nguyen 
1895c90ed40cSTony Nguyen 	return 0;
1896c90ed40cSTony Nguyen }
1897c90ed40cSTony Nguyen 
18982c61054cSTony Nguyen /**
18992c61054cSTony Nguyen  * ice_rem_vsi_rss_list - remove VSI from RSS list
19002c61054cSTony Nguyen  * @hw: pointer to the hardware structure
19012c61054cSTony Nguyen  * @vsi_handle: software VSI handle
19022c61054cSTony Nguyen  *
19032c61054cSTony Nguyen  * Remove the VSI from all RSS configurations in the list.
19042c61054cSTony Nguyen  */
ice_rem_vsi_rss_list(struct ice_hw * hw,u16 vsi_handle)19052c61054cSTony Nguyen void ice_rem_vsi_rss_list(struct ice_hw *hw, u16 vsi_handle)
19062c61054cSTony Nguyen {
19072c61054cSTony Nguyen 	struct ice_rss_cfg *r, *tmp;
19082c61054cSTony Nguyen 
19092c61054cSTony Nguyen 	if (list_empty(&hw->rss_list_head))
19102c61054cSTony Nguyen 		return;
19112c61054cSTony Nguyen 
19122c61054cSTony Nguyen 	mutex_lock(&hw->rss_locks);
19132c61054cSTony Nguyen 	list_for_each_entry_safe(r, tmp, &hw->rss_list_head, l_entry)
19142c61054cSTony Nguyen 		if (test_and_clear_bit(vsi_handle, r->vsis))
19152c61054cSTony Nguyen 			if (bitmap_empty(r->vsis, ICE_MAX_VSI)) {
19162c61054cSTony Nguyen 				list_del(&r->l_entry);
19172c61054cSTony Nguyen 				devm_kfree(ice_hw_to_dev(hw), r);
19182c61054cSTony Nguyen 			}
19192c61054cSTony Nguyen 	mutex_unlock(&hw->rss_locks);
19202c61054cSTony Nguyen }
19212c61054cSTony Nguyen 
19222c61054cSTony Nguyen /**
19232c61054cSTony Nguyen  * ice_rem_vsi_rss_cfg - remove RSS configurations associated with VSI
19242c61054cSTony Nguyen  * @hw: pointer to the hardware structure
19252c61054cSTony Nguyen  * @vsi_handle: software VSI handle
19262c61054cSTony Nguyen  *
19272c61054cSTony Nguyen  * This function will iterate through all flow profiles and disassociate
19282c61054cSTony Nguyen  * the VSI from that profile. If the flow profile has no VSIs it will
19292c61054cSTony Nguyen  * be removed.
19302c61054cSTony Nguyen  */
ice_rem_vsi_rss_cfg(struct ice_hw * hw,u16 vsi_handle)19315e24d598STony Nguyen int ice_rem_vsi_rss_cfg(struct ice_hw *hw, u16 vsi_handle)
19322c61054cSTony Nguyen {
19332c61054cSTony Nguyen 	const enum ice_block blk = ICE_BLK_RSS;
19342c61054cSTony Nguyen 	struct ice_flow_prof *p, *t;
19355e24d598STony Nguyen 	int status = 0;
19362c61054cSTony Nguyen 
19372c61054cSTony Nguyen 	if (!ice_is_vsi_valid(hw, vsi_handle))
1938d54699e2STony Nguyen 		return -EINVAL;
19392c61054cSTony Nguyen 
19402c61054cSTony Nguyen 	if (list_empty(&hw->fl_profs[blk]))
19412c61054cSTony Nguyen 		return 0;
19422c61054cSTony Nguyen 
1943cdedbab9SVignesh Sridhar 	mutex_lock(&hw->rss_locks);
19442c61054cSTony Nguyen 	list_for_each_entry_safe(p, t, &hw->fl_profs[blk], l_entry)
19452c61054cSTony Nguyen 		if (test_bit(vsi_handle, p->vsis)) {
19462c61054cSTony Nguyen 			status = ice_flow_disassoc_prof(hw, blk, p, vsi_handle);
19472c61054cSTony Nguyen 			if (status)
19482c61054cSTony Nguyen 				break;
19492c61054cSTony Nguyen 
19502c61054cSTony Nguyen 			if (bitmap_empty(p->vsis, ICE_MAX_VSI)) {
1951cdedbab9SVignesh Sridhar 				status = ice_flow_rem_prof(hw, blk, p->id);
19522c61054cSTony Nguyen 				if (status)
19532c61054cSTony Nguyen 					break;
19542c61054cSTony Nguyen 			}
19552c61054cSTony Nguyen 		}
1956cdedbab9SVignesh Sridhar 	mutex_unlock(&hw->rss_locks);
19572c61054cSTony Nguyen 
19582c61054cSTony Nguyen 	return status;
19592c61054cSTony Nguyen }
19602c61054cSTony Nguyen 
19612c61054cSTony Nguyen /**
19622c61054cSTony Nguyen  * ice_rem_rss_list - remove RSS configuration from 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 void
ice_rem_rss_list(struct ice_hw * hw,u16 vsi_handle,struct ice_flow_prof * prof)19702c61054cSTony Nguyen ice_rem_rss_list(struct ice_hw *hw, u16 vsi_handle, struct ice_flow_prof *prof)
19712c61054cSTony Nguyen {
19722c61054cSTony Nguyen 	struct ice_rss_cfg *r, *tmp;
19732c61054cSTony Nguyen 
19742c61054cSTony Nguyen 	/* Search for RSS hash fields associated to the VSI that match the
19752c61054cSTony Nguyen 	 * hash configurations associated to the flow profile. If found
19762c61054cSTony Nguyen 	 * remove from the RSS entry list of the VSI context and delete entry.
19772c61054cSTony Nguyen 	 */
19782c61054cSTony Nguyen 	list_for_each_entry_safe(r, tmp, &hw->rss_list_head, l_entry)
19792c61054cSTony Nguyen 		if (r->hashed_flds == prof->segs[prof->segs_cnt - 1].match &&
19802c61054cSTony Nguyen 		    r->packet_hdr == prof->segs[prof->segs_cnt - 1].hdrs) {
19812c61054cSTony Nguyen 			clear_bit(vsi_handle, r->vsis);
19822c61054cSTony Nguyen 			if (bitmap_empty(r->vsis, ICE_MAX_VSI)) {
19832c61054cSTony Nguyen 				list_del(&r->l_entry);
19842c61054cSTony Nguyen 				devm_kfree(ice_hw_to_dev(hw), r);
19852c61054cSTony Nguyen 			}
19862c61054cSTony Nguyen 			return;
19872c61054cSTony Nguyen 		}
19882c61054cSTony Nguyen }
19892c61054cSTony Nguyen 
19902c61054cSTony Nguyen /**
19912c61054cSTony Nguyen  * ice_add_rss_list - add RSS configuration to list
19922c61054cSTony Nguyen  * @hw: pointer to the hardware structure
19932c61054cSTony Nguyen  * @vsi_handle: software VSI handle
19942c61054cSTony Nguyen  * @prof: pointer to flow profile
19952c61054cSTony Nguyen  *
19962c61054cSTony Nguyen  * Assumption: lock has already been acquired for RSS list
19972c61054cSTony Nguyen  */
19985e24d598STony Nguyen static int
ice_add_rss_list(struct ice_hw * hw,u16 vsi_handle,struct ice_flow_prof * prof)19992c61054cSTony Nguyen ice_add_rss_list(struct ice_hw *hw, u16 vsi_handle, struct ice_flow_prof *prof)
20002c61054cSTony Nguyen {
20012c61054cSTony Nguyen 	struct ice_rss_cfg *r, *rss_cfg;
20022c61054cSTony Nguyen 
20032c61054cSTony Nguyen 	list_for_each_entry(r, &hw->rss_list_head, l_entry)
20042c61054cSTony Nguyen 		if (r->hashed_flds == prof->segs[prof->segs_cnt - 1].match &&
20052c61054cSTony Nguyen 		    r->packet_hdr == prof->segs[prof->segs_cnt - 1].hdrs) {
20062c61054cSTony Nguyen 			set_bit(vsi_handle, r->vsis);
20072c61054cSTony Nguyen 			return 0;
20082c61054cSTony Nguyen 		}
20092c61054cSTony Nguyen 
20102c61054cSTony Nguyen 	rss_cfg = devm_kzalloc(ice_hw_to_dev(hw), sizeof(*rss_cfg),
20112c61054cSTony Nguyen 			       GFP_KERNEL);
20122c61054cSTony Nguyen 	if (!rss_cfg)
2013d54699e2STony Nguyen 		return -ENOMEM;
20142c61054cSTony Nguyen 
20152c61054cSTony Nguyen 	rss_cfg->hashed_flds = prof->segs[prof->segs_cnt - 1].match;
20162c61054cSTony Nguyen 	rss_cfg->packet_hdr = prof->segs[prof->segs_cnt - 1].hdrs;
20172c61054cSTony Nguyen 	set_bit(vsi_handle, rss_cfg->vsis);
20182c61054cSTony Nguyen 
20192c61054cSTony Nguyen 	list_add_tail(&rss_cfg->l_entry, &hw->rss_list_head);
20202c61054cSTony Nguyen 
20212c61054cSTony Nguyen 	return 0;
20222c61054cSTony Nguyen }
20232c61054cSTony Nguyen 
202431ad4e4eSTony Nguyen #define ICE_FLOW_PROF_HASH_S	0
202531ad4e4eSTony Nguyen #define ICE_FLOW_PROF_HASH_M	(0xFFFFFFFFULL << ICE_FLOW_PROF_HASH_S)
202631ad4e4eSTony Nguyen #define ICE_FLOW_PROF_HDR_S	32
202731ad4e4eSTony Nguyen #define ICE_FLOW_PROF_HDR_M	(0x3FFFFFFFULL << ICE_FLOW_PROF_HDR_S)
202831ad4e4eSTony Nguyen #define ICE_FLOW_PROF_ENCAP_S	63
202931ad4e4eSTony Nguyen #define ICE_FLOW_PROF_ENCAP_M	(BIT_ULL(ICE_FLOW_PROF_ENCAP_S))
203031ad4e4eSTony Nguyen 
2031c90ed40cSTony Nguyen #define ICE_RSS_OUTER_HEADERS	1
2032a4e82a81STony Nguyen #define ICE_RSS_INNER_HEADERS	2
2033c90ed40cSTony Nguyen 
203431ad4e4eSTony Nguyen /* Flow profile ID format:
203531ad4e4eSTony Nguyen  * [0:31] - Packet match fields
203631ad4e4eSTony Nguyen  * [32:62] - Protocol header
203731ad4e4eSTony Nguyen  * [63] - Encapsulation flag, 0 if non-tunneled, 1 if tunneled
203831ad4e4eSTony Nguyen  */
203931ad4e4eSTony Nguyen #define ICE_FLOW_GEN_PROFID(hash, hdr, segs_cnt) \
20400c3e94c2SBruce Allan 	((u64)(((u64)(hash) & ICE_FLOW_PROF_HASH_M) | \
204131ad4e4eSTony Nguyen 	       (((u64)(hdr) << ICE_FLOW_PROF_HDR_S) & ICE_FLOW_PROF_HDR_M) | \
20420c3e94c2SBruce Allan 	       ((u8)((segs_cnt) - 1) ? ICE_FLOW_PROF_ENCAP_M : 0)))
204331ad4e4eSTony Nguyen 
2044c90ed40cSTony Nguyen /**
2045c90ed40cSTony Nguyen  * ice_add_rss_cfg_sync - add an RSS configuration
204631ad4e4eSTony Nguyen  * @hw: pointer to the hardware structure
2047451f2c44STony Nguyen  * @vsi_handle: software VSI handle
2048c90ed40cSTony Nguyen  * @hashed_flds: hash bit fields (ICE_FLOW_HASH_*) to configure
2049c90ed40cSTony Nguyen  * @addl_hdrs: protocol header fields
2050c90ed40cSTony Nguyen  * @segs_cnt: packet segment count
2051c90ed40cSTony Nguyen  *
2052c90ed40cSTony Nguyen  * Assumption: lock has already been acquired for RSS list
2053c90ed40cSTony Nguyen  */
20545e24d598STony Nguyen static int
ice_add_rss_cfg_sync(struct ice_hw * hw,u16 vsi_handle,u64 hashed_flds,u32 addl_hdrs,u8 segs_cnt)2055451f2c44STony Nguyen ice_add_rss_cfg_sync(struct ice_hw *hw, u16 vsi_handle, u64 hashed_flds,
2056451f2c44STony Nguyen 		     u32 addl_hdrs, u8 segs_cnt)
2057c90ed40cSTony Nguyen {
2058451f2c44STony Nguyen 	const enum ice_block blk = ICE_BLK_RSS;
2059451f2c44STony Nguyen 	struct ice_flow_prof *prof = NULL;
2060c90ed40cSTony Nguyen 	struct ice_flow_seg_info *segs;
20615e24d598STony Nguyen 	int status;
2062c90ed40cSTony Nguyen 
2063c90ed40cSTony Nguyen 	if (!segs_cnt || segs_cnt > ICE_FLOW_SEG_MAX)
2064d54699e2STony Nguyen 		return -EINVAL;
2065c90ed40cSTony Nguyen 
2066c90ed40cSTony Nguyen 	segs = kcalloc(segs_cnt, sizeof(*segs), GFP_KERNEL);
2067c90ed40cSTony Nguyen 	if (!segs)
2068d54699e2STony Nguyen 		return -ENOMEM;
2069c90ed40cSTony Nguyen 
2070c90ed40cSTony Nguyen 	/* Construct the packet segment info from the hashed fields */
2071c90ed40cSTony Nguyen 	status = ice_flow_set_rss_seg_info(&segs[segs_cnt - 1], hashed_flds,
2072c90ed40cSTony Nguyen 					   addl_hdrs);
207331ad4e4eSTony Nguyen 	if (status)
207431ad4e4eSTony Nguyen 		goto exit;
2075c90ed40cSTony Nguyen 
20762c61054cSTony Nguyen 	/* Search for a flow profile that has matching headers, hash fields
20772c61054cSTony Nguyen 	 * and has the input VSI associated to it. If found, no further
20782c61054cSTony Nguyen 	 * operations required and exit.
20792c61054cSTony Nguyen 	 */
20802c61054cSTony Nguyen 	prof = ice_flow_find_prof_conds(hw, blk, ICE_FLOW_RX, segs, segs_cnt,
20812c61054cSTony Nguyen 					vsi_handle,
20822c61054cSTony Nguyen 					ICE_FLOW_FIND_PROF_CHK_FLDS |
20832c61054cSTony Nguyen 					ICE_FLOW_FIND_PROF_CHK_VSI);
20842c61054cSTony Nguyen 	if (prof)
20852c61054cSTony Nguyen 		goto exit;
20862c61054cSTony Nguyen 
20872c61054cSTony Nguyen 	/* Check if a flow profile exists with the same protocol headers and
20882c61054cSTony Nguyen 	 * associated with the input VSI. If so disassociate the VSI from
20892c61054cSTony Nguyen 	 * this profile. The VSI will be added to a new profile created with
20902c61054cSTony Nguyen 	 * the protocol header and new hash field configuration.
20912c61054cSTony Nguyen 	 */
20922c61054cSTony Nguyen 	prof = ice_flow_find_prof_conds(hw, blk, ICE_FLOW_RX, segs, segs_cnt,
20932c61054cSTony Nguyen 					vsi_handle, ICE_FLOW_FIND_PROF_CHK_VSI);
20942c61054cSTony Nguyen 	if (prof) {
20952c61054cSTony Nguyen 		status = ice_flow_disassoc_prof(hw, blk, prof, vsi_handle);
20962c61054cSTony Nguyen 		if (!status)
20972c61054cSTony Nguyen 			ice_rem_rss_list(hw, vsi_handle, prof);
20982c61054cSTony Nguyen 		else
20992c61054cSTony Nguyen 			goto exit;
21002c61054cSTony Nguyen 
21012c61054cSTony Nguyen 		/* Remove profile if it has no VSIs associated */
21022c61054cSTony Nguyen 		if (bitmap_empty(prof->vsis, ICE_MAX_VSI)) {
21032c61054cSTony Nguyen 			status = ice_flow_rem_prof(hw, blk, prof->id);
21042c61054cSTony Nguyen 			if (status)
21052c61054cSTony Nguyen 				goto exit;
21062c61054cSTony Nguyen 		}
21072c61054cSTony Nguyen 	}
21082c61054cSTony Nguyen 
21092c61054cSTony Nguyen 	/* Search for a profile that has same match fields only. If this
21102c61054cSTony Nguyen 	 * exists then associate the VSI to this profile.
21112c61054cSTony Nguyen 	 */
21122c61054cSTony Nguyen 	prof = ice_flow_find_prof_conds(hw, blk, ICE_FLOW_RX, segs, segs_cnt,
21132c61054cSTony Nguyen 					vsi_handle,
21142c61054cSTony Nguyen 					ICE_FLOW_FIND_PROF_CHK_FLDS);
21152c61054cSTony Nguyen 	if (prof) {
21162c61054cSTony Nguyen 		status = ice_flow_assoc_prof(hw, blk, prof, vsi_handle);
21172c61054cSTony Nguyen 		if (!status)
21182c61054cSTony Nguyen 			status = ice_add_rss_list(hw, vsi_handle, prof);
21192c61054cSTony Nguyen 		goto exit;
21202c61054cSTony Nguyen 	}
21212c61054cSTony Nguyen 
212231ad4e4eSTony Nguyen 	/* Create a new flow profile with generated profile and packet
212331ad4e4eSTony Nguyen 	 * segment information.
212431ad4e4eSTony Nguyen 	 */
2125451f2c44STony Nguyen 	status = ice_flow_add_prof(hw, blk, ICE_FLOW_RX,
212631ad4e4eSTony Nguyen 				   ICE_FLOW_GEN_PROFID(hashed_flds,
212731ad4e4eSTony Nguyen 						       segs[segs_cnt - 1].hdrs,
212831ad4e4eSTony Nguyen 						       segs_cnt),
2129451f2c44STony Nguyen 				   segs, segs_cnt, &prof);
2130451f2c44STony Nguyen 	if (status)
2131451f2c44STony Nguyen 		goto exit;
2132451f2c44STony Nguyen 
2133451f2c44STony Nguyen 	status = ice_flow_assoc_prof(hw, blk, prof, vsi_handle);
21342c61054cSTony Nguyen 	/* If association to a new flow profile failed then this profile can
21352c61054cSTony Nguyen 	 * be removed.
21362c61054cSTony Nguyen 	 */
21372c61054cSTony Nguyen 	if (status) {
21382c61054cSTony Nguyen 		ice_flow_rem_prof(hw, blk, prof->id);
21392c61054cSTony Nguyen 		goto exit;
21402c61054cSTony Nguyen 	}
21412c61054cSTony Nguyen 
21422c61054cSTony Nguyen 	status = ice_add_rss_list(hw, vsi_handle, prof);
214331ad4e4eSTony Nguyen 
214431ad4e4eSTony Nguyen exit:
2145c90ed40cSTony Nguyen 	kfree(segs);
2146c90ed40cSTony Nguyen 	return status;
2147c90ed40cSTony Nguyen }
2148c90ed40cSTony Nguyen 
2149c90ed40cSTony Nguyen /**
2150c90ed40cSTony Nguyen  * ice_add_rss_cfg - add an RSS configuration with specified hashed fields
2151c90ed40cSTony Nguyen  * @hw: pointer to the hardware structure
2152c90ed40cSTony Nguyen  * @vsi_handle: software VSI handle
2153c90ed40cSTony Nguyen  * @hashed_flds: hash bit fields (ICE_FLOW_HASH_*) to configure
2154c90ed40cSTony Nguyen  * @addl_hdrs: protocol header fields
2155c90ed40cSTony Nguyen  *
2156c90ed40cSTony Nguyen  * This function will generate a flow profile based on fields associated with
2157c90ed40cSTony Nguyen  * the input fields to hash on, the flow type and use the VSI number to add
2158c90ed40cSTony Nguyen  * a flow entry to the profile.
2159c90ed40cSTony Nguyen  */
21605e24d598STony Nguyen int
ice_add_rss_cfg(struct ice_hw * hw,u16 vsi_handle,u64 hashed_flds,u32 addl_hdrs)2161c90ed40cSTony Nguyen ice_add_rss_cfg(struct ice_hw *hw, u16 vsi_handle, u64 hashed_flds,
2162c90ed40cSTony Nguyen 		u32 addl_hdrs)
2163c90ed40cSTony Nguyen {
21645e24d598STony Nguyen 	int status;
2165c90ed40cSTony Nguyen 
2166c90ed40cSTony Nguyen 	if (hashed_flds == ICE_HASH_INVALID ||
2167c90ed40cSTony Nguyen 	    !ice_is_vsi_valid(hw, vsi_handle))
2168d54699e2STony Nguyen 		return -EINVAL;
2169c90ed40cSTony Nguyen 
2170c90ed40cSTony Nguyen 	mutex_lock(&hw->rss_locks);
2171451f2c44STony Nguyen 	status = ice_add_rss_cfg_sync(hw, vsi_handle, hashed_flds, addl_hdrs,
2172c90ed40cSTony Nguyen 				      ICE_RSS_OUTER_HEADERS);
2173a4e82a81STony Nguyen 	if (!status)
2174a4e82a81STony Nguyen 		status = ice_add_rss_cfg_sync(hw, vsi_handle, hashed_flds,
2175a4e82a81STony Nguyen 					      addl_hdrs, ICE_RSS_INNER_HEADERS);
2176c90ed40cSTony Nguyen 	mutex_unlock(&hw->rss_locks);
2177c90ed40cSTony Nguyen 
2178c90ed40cSTony Nguyen 	return status;
2179c90ed40cSTony Nguyen }
2180c90ed40cSTony Nguyen 
2181ddd1f3cfSQi Zhang /**
2182ddd1f3cfSQi Zhang  * ice_rem_rss_cfg_sync - remove an existing RSS configuration
2183ddd1f3cfSQi Zhang  * @hw: pointer to the hardware structure
2184ddd1f3cfSQi Zhang  * @vsi_handle: software VSI handle
2185ddd1f3cfSQi Zhang  * @hashed_flds: Packet hash types (ICE_FLOW_HASH_*) to remove
2186ddd1f3cfSQi Zhang  * @addl_hdrs: Protocol header fields within a packet segment
2187ddd1f3cfSQi Zhang  * @segs_cnt: packet segment count
2188ddd1f3cfSQi Zhang  *
2189ddd1f3cfSQi Zhang  * Assumption: lock has already been acquired for RSS list
2190ddd1f3cfSQi Zhang  */
21915e24d598STony Nguyen static int
ice_rem_rss_cfg_sync(struct ice_hw * hw,u16 vsi_handle,u64 hashed_flds,u32 addl_hdrs,u8 segs_cnt)2192ddd1f3cfSQi Zhang ice_rem_rss_cfg_sync(struct ice_hw *hw, u16 vsi_handle, u64 hashed_flds,
2193ddd1f3cfSQi Zhang 		     u32 addl_hdrs, u8 segs_cnt)
2194ddd1f3cfSQi Zhang {
2195ddd1f3cfSQi Zhang 	const enum ice_block blk = ICE_BLK_RSS;
2196ddd1f3cfSQi Zhang 	struct ice_flow_seg_info *segs;
2197ddd1f3cfSQi Zhang 	struct ice_flow_prof *prof;
21985e24d598STony Nguyen 	int status;
2199ddd1f3cfSQi Zhang 
2200ddd1f3cfSQi Zhang 	segs = kcalloc(segs_cnt, sizeof(*segs), GFP_KERNEL);
2201ddd1f3cfSQi Zhang 	if (!segs)
2202d54699e2STony Nguyen 		return -ENOMEM;
2203ddd1f3cfSQi Zhang 
2204ddd1f3cfSQi Zhang 	/* Construct the packet segment info from the hashed fields */
2205ddd1f3cfSQi Zhang 	status = ice_flow_set_rss_seg_info(&segs[segs_cnt - 1], hashed_flds,
2206ddd1f3cfSQi Zhang 					   addl_hdrs);
2207ddd1f3cfSQi Zhang 	if (status)
2208ddd1f3cfSQi Zhang 		goto out;
2209ddd1f3cfSQi Zhang 
2210ddd1f3cfSQi Zhang 	prof = ice_flow_find_prof_conds(hw, blk, ICE_FLOW_RX, segs, segs_cnt,
2211ddd1f3cfSQi Zhang 					vsi_handle,
2212ddd1f3cfSQi Zhang 					ICE_FLOW_FIND_PROF_CHK_FLDS);
2213ddd1f3cfSQi Zhang 	if (!prof) {
2214d54699e2STony Nguyen 		status = -ENOENT;
2215ddd1f3cfSQi Zhang 		goto out;
2216ddd1f3cfSQi Zhang 	}
2217ddd1f3cfSQi Zhang 
2218ddd1f3cfSQi Zhang 	status = ice_flow_disassoc_prof(hw, blk, prof, vsi_handle);
2219ddd1f3cfSQi Zhang 	if (status)
2220ddd1f3cfSQi Zhang 		goto out;
2221ddd1f3cfSQi Zhang 
2222ddd1f3cfSQi Zhang 	/* Remove RSS configuration from VSI context before deleting
2223ddd1f3cfSQi Zhang 	 * the flow profile.
2224ddd1f3cfSQi Zhang 	 */
2225ddd1f3cfSQi Zhang 	ice_rem_rss_list(hw, vsi_handle, prof);
2226ddd1f3cfSQi Zhang 
2227ddd1f3cfSQi Zhang 	if (bitmap_empty(prof->vsis, ICE_MAX_VSI))
2228ddd1f3cfSQi Zhang 		status = ice_flow_rem_prof(hw, blk, prof->id);
2229ddd1f3cfSQi Zhang 
2230ddd1f3cfSQi Zhang out:
2231ddd1f3cfSQi Zhang 	kfree(segs);
2232ddd1f3cfSQi Zhang 	return status;
2233ddd1f3cfSQi Zhang }
2234ddd1f3cfSQi Zhang 
2235ddd1f3cfSQi Zhang /**
2236ddd1f3cfSQi Zhang  * ice_rem_rss_cfg - remove an existing RSS config with matching hashed fields
2237ddd1f3cfSQi Zhang  * @hw: pointer to the hardware structure
2238ddd1f3cfSQi Zhang  * @vsi_handle: software VSI handle
2239ddd1f3cfSQi Zhang  * @hashed_flds: Packet hash types (ICE_FLOW_HASH_*) to remove
2240ddd1f3cfSQi Zhang  * @addl_hdrs: Protocol header fields within a packet segment
2241ddd1f3cfSQi Zhang  *
2242ddd1f3cfSQi Zhang  * This function will lookup the flow profile based on the input
2243ddd1f3cfSQi Zhang  * hash field bitmap, iterate through the profile entry list of
2244ddd1f3cfSQi Zhang  * that profile and find entry associated with input VSI to be
2245ddd1f3cfSQi Zhang  * removed. Calls are made to underlying flow s which will APIs
2246ddd1f3cfSQi Zhang  * turn build or update buffers for RSS XLT1 section.
2247ddd1f3cfSQi Zhang  */
22485e24d598STony Nguyen int __maybe_unused
ice_rem_rss_cfg(struct ice_hw * hw,u16 vsi_handle,u64 hashed_flds,u32 addl_hdrs)2249ddd1f3cfSQi Zhang ice_rem_rss_cfg(struct ice_hw *hw, u16 vsi_handle, u64 hashed_flds,
2250ddd1f3cfSQi Zhang 		u32 addl_hdrs)
2251ddd1f3cfSQi Zhang {
22525e24d598STony Nguyen 	int status;
2253ddd1f3cfSQi Zhang 
2254ddd1f3cfSQi Zhang 	if (hashed_flds == ICE_HASH_INVALID ||
2255ddd1f3cfSQi Zhang 	    !ice_is_vsi_valid(hw, vsi_handle))
2256d54699e2STony Nguyen 		return -EINVAL;
2257ddd1f3cfSQi Zhang 
2258ddd1f3cfSQi Zhang 	mutex_lock(&hw->rss_locks);
2259ddd1f3cfSQi Zhang 	status = ice_rem_rss_cfg_sync(hw, vsi_handle, hashed_flds, addl_hdrs,
2260ddd1f3cfSQi Zhang 				      ICE_RSS_OUTER_HEADERS);
2261ddd1f3cfSQi Zhang 	if (!status)
2262ddd1f3cfSQi Zhang 		status = ice_rem_rss_cfg_sync(hw, vsi_handle, hashed_flds,
2263ddd1f3cfSQi Zhang 					      addl_hdrs, ICE_RSS_INNER_HEADERS);
2264ddd1f3cfSQi Zhang 	mutex_unlock(&hw->rss_locks);
2265ddd1f3cfSQi Zhang 
2266ddd1f3cfSQi Zhang 	return status;
2267ddd1f3cfSQi Zhang }
2268ddd1f3cfSQi Zhang 
22691c01c8c6SMd Fahad Iqbal Polash /* Mapping of AVF hash bit fields to an L3-L4 hash combination.
22701c01c8c6SMd Fahad Iqbal Polash  * As the ice_flow_avf_hdr_field represent individual bit shifts in a hash,
22711c01c8c6SMd Fahad Iqbal Polash  * convert its values to their appropriate flow L3, L4 values.
22721c01c8c6SMd Fahad Iqbal Polash  */
22731c01c8c6SMd Fahad Iqbal Polash #define ICE_FLOW_AVF_RSS_IPV4_MASKS \
22741c01c8c6SMd Fahad Iqbal Polash 	(BIT_ULL(ICE_AVF_FLOW_FIELD_IPV4_OTHER) | \
22751c01c8c6SMd Fahad Iqbal Polash 	 BIT_ULL(ICE_AVF_FLOW_FIELD_FRAG_IPV4))
22761c01c8c6SMd Fahad Iqbal Polash #define ICE_FLOW_AVF_RSS_TCP_IPV4_MASKS \
22771c01c8c6SMd Fahad Iqbal Polash 	(BIT_ULL(ICE_AVF_FLOW_FIELD_IPV4_TCP_SYN_NO_ACK) | \
22781c01c8c6SMd Fahad Iqbal Polash 	 BIT_ULL(ICE_AVF_FLOW_FIELD_IPV4_TCP))
22791c01c8c6SMd Fahad Iqbal Polash #define ICE_FLOW_AVF_RSS_UDP_IPV4_MASKS \
22801c01c8c6SMd Fahad Iqbal Polash 	(BIT_ULL(ICE_AVF_FLOW_FIELD_UNICAST_IPV4_UDP) | \
22811c01c8c6SMd Fahad Iqbal Polash 	 BIT_ULL(ICE_AVF_FLOW_FIELD_MULTICAST_IPV4_UDP) | \
22821c01c8c6SMd Fahad Iqbal Polash 	 BIT_ULL(ICE_AVF_FLOW_FIELD_IPV4_UDP))
22831c01c8c6SMd Fahad Iqbal Polash #define ICE_FLOW_AVF_RSS_ALL_IPV4_MASKS \
22841c01c8c6SMd Fahad Iqbal Polash 	(ICE_FLOW_AVF_RSS_TCP_IPV4_MASKS | ICE_FLOW_AVF_RSS_UDP_IPV4_MASKS | \
22851c01c8c6SMd Fahad Iqbal Polash 	 ICE_FLOW_AVF_RSS_IPV4_MASKS | BIT_ULL(ICE_AVF_FLOW_FIELD_IPV4_SCTP))
22861c01c8c6SMd Fahad Iqbal Polash 
22871c01c8c6SMd Fahad Iqbal Polash #define ICE_FLOW_AVF_RSS_IPV6_MASKS \
22881c01c8c6SMd Fahad Iqbal Polash 	(BIT_ULL(ICE_AVF_FLOW_FIELD_IPV6_OTHER) | \
22891c01c8c6SMd Fahad Iqbal Polash 	 BIT_ULL(ICE_AVF_FLOW_FIELD_FRAG_IPV6))
22901c01c8c6SMd Fahad Iqbal Polash #define ICE_FLOW_AVF_RSS_UDP_IPV6_MASKS \
22911c01c8c6SMd Fahad Iqbal Polash 	(BIT_ULL(ICE_AVF_FLOW_FIELD_UNICAST_IPV6_UDP) | \
22921c01c8c6SMd Fahad Iqbal Polash 	 BIT_ULL(ICE_AVF_FLOW_FIELD_MULTICAST_IPV6_UDP) | \
22931c01c8c6SMd Fahad Iqbal Polash 	 BIT_ULL(ICE_AVF_FLOW_FIELD_IPV6_UDP))
22941c01c8c6SMd Fahad Iqbal Polash #define ICE_FLOW_AVF_RSS_TCP_IPV6_MASKS \
22951c01c8c6SMd Fahad Iqbal Polash 	(BIT_ULL(ICE_AVF_FLOW_FIELD_IPV6_TCP_SYN_NO_ACK) | \
22961c01c8c6SMd Fahad Iqbal Polash 	 BIT_ULL(ICE_AVF_FLOW_FIELD_IPV6_TCP))
22971c01c8c6SMd Fahad Iqbal Polash #define ICE_FLOW_AVF_RSS_ALL_IPV6_MASKS \
22981c01c8c6SMd Fahad Iqbal Polash 	(ICE_FLOW_AVF_RSS_TCP_IPV6_MASKS | ICE_FLOW_AVF_RSS_UDP_IPV6_MASKS | \
22991c01c8c6SMd Fahad Iqbal Polash 	 ICE_FLOW_AVF_RSS_IPV6_MASKS | BIT_ULL(ICE_AVF_FLOW_FIELD_IPV6_SCTP))
23001c01c8c6SMd Fahad Iqbal Polash 
23011c01c8c6SMd Fahad Iqbal Polash /**
23021c01c8c6SMd Fahad Iqbal Polash  * ice_add_avf_rss_cfg - add an RSS configuration for AVF driver
23031c01c8c6SMd Fahad Iqbal Polash  * @hw: pointer to the hardware structure
23041c01c8c6SMd Fahad Iqbal Polash  * @vsi_handle: software VSI handle
23051c01c8c6SMd Fahad Iqbal Polash  * @avf_hash: hash bit fields (ICE_AVF_FLOW_FIELD_*) to configure
23061c01c8c6SMd Fahad Iqbal Polash  *
23071c01c8c6SMd Fahad Iqbal Polash  * This function will take the hash bitmap provided by the AVF driver via a
23081c01c8c6SMd Fahad Iqbal Polash  * message, convert it to ICE-compatible values, and configure RSS flow
23091c01c8c6SMd Fahad Iqbal Polash  * profiles.
23101c01c8c6SMd Fahad Iqbal Polash  */
ice_add_avf_rss_cfg(struct ice_hw * hw,u16 vsi_handle,u64 avf_hash)23115518ac2aSTony Nguyen int ice_add_avf_rss_cfg(struct ice_hw *hw, u16 vsi_handle, u64 avf_hash)
23121c01c8c6SMd Fahad Iqbal Polash {
23135e24d598STony Nguyen 	int status = 0;
23141c01c8c6SMd Fahad Iqbal Polash 	u64 hash_flds;
23151c01c8c6SMd Fahad Iqbal Polash 
23161c01c8c6SMd Fahad Iqbal Polash 	if (avf_hash == ICE_AVF_FLOW_FIELD_INVALID ||
23171c01c8c6SMd Fahad Iqbal Polash 	    !ice_is_vsi_valid(hw, vsi_handle))
2318d54699e2STony Nguyen 		return -EINVAL;
23191c01c8c6SMd Fahad Iqbal Polash 
23201c01c8c6SMd Fahad Iqbal Polash 	/* Make sure no unsupported bits are specified */
23211c01c8c6SMd Fahad Iqbal Polash 	if (avf_hash & ~(ICE_FLOW_AVF_RSS_ALL_IPV4_MASKS |
23221c01c8c6SMd Fahad Iqbal Polash 			 ICE_FLOW_AVF_RSS_ALL_IPV6_MASKS))
2323d54699e2STony Nguyen 		return -EIO;
23241c01c8c6SMd Fahad Iqbal Polash 
23251c01c8c6SMd Fahad Iqbal Polash 	hash_flds = avf_hash;
23261c01c8c6SMd Fahad Iqbal Polash 
23271c01c8c6SMd Fahad Iqbal Polash 	/* Always create an L3 RSS configuration for any L4 RSS configuration */
23281c01c8c6SMd Fahad Iqbal Polash 	if (hash_flds & ICE_FLOW_AVF_RSS_ALL_IPV4_MASKS)
23291c01c8c6SMd Fahad Iqbal Polash 		hash_flds |= ICE_FLOW_AVF_RSS_IPV4_MASKS;
23301c01c8c6SMd Fahad Iqbal Polash 
23311c01c8c6SMd Fahad Iqbal Polash 	if (hash_flds & ICE_FLOW_AVF_RSS_ALL_IPV6_MASKS)
23321c01c8c6SMd Fahad Iqbal Polash 		hash_flds |= ICE_FLOW_AVF_RSS_IPV6_MASKS;
23331c01c8c6SMd Fahad Iqbal Polash 
23341c01c8c6SMd Fahad Iqbal Polash 	/* Create the corresponding RSS configuration for each valid hash bit */
23351c01c8c6SMd Fahad Iqbal Polash 	while (hash_flds) {
23361c01c8c6SMd Fahad Iqbal Polash 		u64 rss_hash = ICE_HASH_INVALID;
23371c01c8c6SMd Fahad Iqbal Polash 
23381c01c8c6SMd Fahad Iqbal Polash 		if (hash_flds & ICE_FLOW_AVF_RSS_ALL_IPV4_MASKS) {
23391c01c8c6SMd Fahad Iqbal Polash 			if (hash_flds & ICE_FLOW_AVF_RSS_IPV4_MASKS) {
23401c01c8c6SMd Fahad Iqbal Polash 				rss_hash = ICE_FLOW_HASH_IPV4;
23411c01c8c6SMd Fahad Iqbal Polash 				hash_flds &= ~ICE_FLOW_AVF_RSS_IPV4_MASKS;
23421c01c8c6SMd Fahad Iqbal Polash 			} else if (hash_flds &
23431c01c8c6SMd Fahad Iqbal Polash 				   ICE_FLOW_AVF_RSS_TCP_IPV4_MASKS) {
23441c01c8c6SMd Fahad Iqbal Polash 				rss_hash = ICE_FLOW_HASH_IPV4 |
23451c01c8c6SMd Fahad Iqbal Polash 					ICE_FLOW_HASH_TCP_PORT;
23461c01c8c6SMd Fahad Iqbal Polash 				hash_flds &= ~ICE_FLOW_AVF_RSS_TCP_IPV4_MASKS;
23471c01c8c6SMd Fahad Iqbal Polash 			} else if (hash_flds &
23481c01c8c6SMd Fahad Iqbal Polash 				   ICE_FLOW_AVF_RSS_UDP_IPV4_MASKS) {
23491c01c8c6SMd Fahad Iqbal Polash 				rss_hash = ICE_FLOW_HASH_IPV4 |
23501c01c8c6SMd Fahad Iqbal Polash 					ICE_FLOW_HASH_UDP_PORT;
23511c01c8c6SMd Fahad Iqbal Polash 				hash_flds &= ~ICE_FLOW_AVF_RSS_UDP_IPV4_MASKS;
23521c01c8c6SMd Fahad Iqbal Polash 			} else if (hash_flds &
23531c01c8c6SMd Fahad Iqbal Polash 				   BIT_ULL(ICE_AVF_FLOW_FIELD_IPV4_SCTP)) {
23541c01c8c6SMd Fahad Iqbal Polash 				rss_hash = ICE_FLOW_HASH_IPV4 |
23551c01c8c6SMd Fahad Iqbal Polash 					ICE_FLOW_HASH_SCTP_PORT;
23561c01c8c6SMd Fahad Iqbal Polash 				hash_flds &=
23571c01c8c6SMd Fahad Iqbal Polash 					~BIT_ULL(ICE_AVF_FLOW_FIELD_IPV4_SCTP);
23581c01c8c6SMd Fahad Iqbal Polash 			}
23591c01c8c6SMd Fahad Iqbal Polash 		} else if (hash_flds & ICE_FLOW_AVF_RSS_ALL_IPV6_MASKS) {
23601c01c8c6SMd Fahad Iqbal Polash 			if (hash_flds & ICE_FLOW_AVF_RSS_IPV6_MASKS) {
23611c01c8c6SMd Fahad Iqbal Polash 				rss_hash = ICE_FLOW_HASH_IPV6;
23621c01c8c6SMd Fahad Iqbal Polash 				hash_flds &= ~ICE_FLOW_AVF_RSS_IPV6_MASKS;
23631c01c8c6SMd Fahad Iqbal Polash 			} else if (hash_flds &
23641c01c8c6SMd Fahad Iqbal Polash 				   ICE_FLOW_AVF_RSS_TCP_IPV6_MASKS) {
23651c01c8c6SMd Fahad Iqbal Polash 				rss_hash = ICE_FLOW_HASH_IPV6 |
23661c01c8c6SMd Fahad Iqbal Polash 					ICE_FLOW_HASH_TCP_PORT;
23671c01c8c6SMd Fahad Iqbal Polash 				hash_flds &= ~ICE_FLOW_AVF_RSS_TCP_IPV6_MASKS;
23681c01c8c6SMd Fahad Iqbal Polash 			} else if (hash_flds &
23691c01c8c6SMd Fahad Iqbal Polash 				   ICE_FLOW_AVF_RSS_UDP_IPV6_MASKS) {
23701c01c8c6SMd Fahad Iqbal Polash 				rss_hash = ICE_FLOW_HASH_IPV6 |
23711c01c8c6SMd Fahad Iqbal Polash 					ICE_FLOW_HASH_UDP_PORT;
23721c01c8c6SMd Fahad Iqbal Polash 				hash_flds &= ~ICE_FLOW_AVF_RSS_UDP_IPV6_MASKS;
23731c01c8c6SMd Fahad Iqbal Polash 			} else if (hash_flds &
23741c01c8c6SMd Fahad Iqbal Polash 				   BIT_ULL(ICE_AVF_FLOW_FIELD_IPV6_SCTP)) {
23751c01c8c6SMd Fahad Iqbal Polash 				rss_hash = ICE_FLOW_HASH_IPV6 |
23761c01c8c6SMd Fahad Iqbal Polash 					ICE_FLOW_HASH_SCTP_PORT;
23771c01c8c6SMd Fahad Iqbal Polash 				hash_flds &=
23781c01c8c6SMd Fahad Iqbal Polash 					~BIT_ULL(ICE_AVF_FLOW_FIELD_IPV6_SCTP);
23791c01c8c6SMd Fahad Iqbal Polash 			}
23801c01c8c6SMd Fahad Iqbal Polash 		}
23811c01c8c6SMd Fahad Iqbal Polash 
23821c01c8c6SMd Fahad Iqbal Polash 		if (rss_hash == ICE_HASH_INVALID)
2383d54699e2STony Nguyen 			return -EIO;
23841c01c8c6SMd Fahad Iqbal Polash 
23851c01c8c6SMd Fahad Iqbal Polash 		status = ice_add_rss_cfg(hw, vsi_handle, rss_hash,
23861c01c8c6SMd Fahad Iqbal Polash 					 ICE_FLOW_SEG_HDR_NONE);
23871c01c8c6SMd Fahad Iqbal Polash 		if (status)
23881c01c8c6SMd Fahad Iqbal Polash 			break;
23891c01c8c6SMd Fahad Iqbal Polash 	}
23901c01c8c6SMd Fahad Iqbal Polash 
23911c01c8c6SMd Fahad Iqbal Polash 	return status;
23921c01c8c6SMd Fahad Iqbal Polash }
23931c01c8c6SMd Fahad Iqbal Polash 
2394c90ed40cSTony Nguyen /**
2395c90ed40cSTony Nguyen  * ice_replay_rss_cfg - replay RSS configurations associated with VSI
2396c90ed40cSTony Nguyen  * @hw: pointer to the hardware structure
2397c90ed40cSTony Nguyen  * @vsi_handle: software VSI handle
2398c90ed40cSTony Nguyen  */
ice_replay_rss_cfg(struct ice_hw * hw,u16 vsi_handle)23995e24d598STony Nguyen int ice_replay_rss_cfg(struct ice_hw *hw, u16 vsi_handle)
2400c90ed40cSTony Nguyen {
2401c90ed40cSTony Nguyen 	struct ice_rss_cfg *r;
24025518ac2aSTony Nguyen 	int status = 0;
2403c90ed40cSTony Nguyen 
2404c90ed40cSTony Nguyen 	if (!ice_is_vsi_valid(hw, vsi_handle))
2405d54699e2STony Nguyen 		return -EINVAL;
2406c90ed40cSTony Nguyen 
2407c90ed40cSTony Nguyen 	mutex_lock(&hw->rss_locks);
2408c90ed40cSTony Nguyen 	list_for_each_entry(r, &hw->rss_list_head, l_entry) {
2409c90ed40cSTony Nguyen 		if (test_bit(vsi_handle, r->vsis)) {
2410451f2c44STony Nguyen 			status = ice_add_rss_cfg_sync(hw, vsi_handle,
2411451f2c44STony Nguyen 						      r->hashed_flds,
2412c90ed40cSTony Nguyen 						      r->packet_hdr,
2413c90ed40cSTony Nguyen 						      ICE_RSS_OUTER_HEADERS);
2414c90ed40cSTony Nguyen 			if (status)
2415c90ed40cSTony Nguyen 				break;
2416a4e82a81STony Nguyen 			status = ice_add_rss_cfg_sync(hw, vsi_handle,
2417a4e82a81STony Nguyen 						      r->hashed_flds,
2418a4e82a81STony Nguyen 						      r->packet_hdr,
2419a4e82a81STony Nguyen 						      ICE_RSS_INNER_HEADERS);
2420a4e82a81STony Nguyen 			if (status)
2421a4e82a81STony Nguyen 				break;
2422c90ed40cSTony Nguyen 		}
2423c90ed40cSTony Nguyen 	}
2424c90ed40cSTony Nguyen 	mutex_unlock(&hw->rss_locks);
2425c90ed40cSTony Nguyen 
2426c90ed40cSTony Nguyen 	return status;
2427c90ed40cSTony Nguyen }
24286876fb64SMd Fahad Iqbal Polash 
24296876fb64SMd Fahad Iqbal Polash /**
24306876fb64SMd Fahad Iqbal Polash  * ice_get_rss_cfg - returns hashed fields for the given header types
24316876fb64SMd Fahad Iqbal Polash  * @hw: pointer to the hardware structure
24326876fb64SMd Fahad Iqbal Polash  * @vsi_handle: software VSI handle
24336876fb64SMd Fahad Iqbal Polash  * @hdrs: protocol header type
24346876fb64SMd Fahad Iqbal Polash  *
24356876fb64SMd Fahad Iqbal Polash  * This function will return the match fields of the first instance of flow
24366876fb64SMd Fahad Iqbal Polash  * profile having the given header types and containing input VSI
24376876fb64SMd Fahad Iqbal Polash  */
ice_get_rss_cfg(struct ice_hw * hw,u16 vsi_handle,u32 hdrs)24386876fb64SMd Fahad Iqbal Polash u64 ice_get_rss_cfg(struct ice_hw *hw, u16 vsi_handle, u32 hdrs)
24396876fb64SMd Fahad Iqbal Polash {
2440cdedbab9SVignesh Sridhar 	u64 rss_hash = ICE_HASH_INVALID;
2441cdedbab9SVignesh Sridhar 	struct ice_rss_cfg *r;
24426876fb64SMd Fahad Iqbal Polash 
24436876fb64SMd Fahad Iqbal Polash 	/* verify if the protocol header is non zero and VSI is valid */
24446876fb64SMd Fahad Iqbal Polash 	if (hdrs == ICE_FLOW_SEG_HDR_NONE || !ice_is_vsi_valid(hw, vsi_handle))
24456876fb64SMd Fahad Iqbal Polash 		return ICE_HASH_INVALID;
24466876fb64SMd Fahad Iqbal Polash 
24476876fb64SMd Fahad Iqbal Polash 	mutex_lock(&hw->rss_locks);
24486876fb64SMd Fahad Iqbal Polash 	list_for_each_entry(r, &hw->rss_list_head, l_entry)
24496876fb64SMd Fahad Iqbal Polash 		if (test_bit(vsi_handle, r->vsis) &&
24506876fb64SMd Fahad Iqbal Polash 		    r->packet_hdr == hdrs) {
2451cdedbab9SVignesh Sridhar 			rss_hash = r->hashed_flds;
24526876fb64SMd Fahad Iqbal Polash 			break;
24536876fb64SMd Fahad Iqbal Polash 		}
24546876fb64SMd Fahad Iqbal Polash 	mutex_unlock(&hw->rss_locks);
24556876fb64SMd Fahad Iqbal Polash 
2456cdedbab9SVignesh Sridhar 	return rss_hash;
24576876fb64SMd Fahad Iqbal Polash }
2458