1c90ed40cSTony Nguyen // SPDX-License-Identifier: GPL-2.0
2c90ed40cSTony Nguyen /* Copyright (c) 2019, Intel Corporation. */
3c90ed40cSTony Nguyen 
4c90ed40cSTony Nguyen #include "ice_common.h"
5c90ed40cSTony Nguyen #include "ice_flow.h"
6c90ed40cSTony Nguyen 
7c90ed40cSTony Nguyen /* Describe properties of a protocol header field */
8c90ed40cSTony Nguyen struct ice_flow_field_info {
9c90ed40cSTony Nguyen 	enum ice_flow_seg_hdr hdr;
10c90ed40cSTony Nguyen 	s16 off;	/* Offset from start of a protocol header, in bits */
11c90ed40cSTony Nguyen 	u16 size;	/* Size of fields in bits */
12b199dddbSQi Zhang 	u16 mask;	/* 16-bit mask for field */
13c90ed40cSTony Nguyen };
14c90ed40cSTony Nguyen 
15c90ed40cSTony Nguyen #define ICE_FLOW_FLD_INFO(_hdr, _offset_bytes, _size_bytes) { \
16c90ed40cSTony Nguyen 	.hdr = _hdr, \
17c90ed40cSTony Nguyen 	.off = (_offset_bytes) * BITS_PER_BYTE, \
18c90ed40cSTony Nguyen 	.size = (_size_bytes) * BITS_PER_BYTE, \
19b199dddbSQi Zhang 	.mask = 0, \
20b199dddbSQi Zhang }
21b199dddbSQi Zhang 
22b199dddbSQi Zhang #define ICE_FLOW_FLD_INFO_MSK(_hdr, _offset_bytes, _size_bytes, _mask) { \
23b199dddbSQi Zhang 	.hdr = _hdr, \
24b199dddbSQi Zhang 	.off = (_offset_bytes) * BITS_PER_BYTE, \
25b199dddbSQi Zhang 	.size = (_size_bytes) * BITS_PER_BYTE, \
26b199dddbSQi Zhang 	.mask = _mask, \
27c90ed40cSTony Nguyen }
28c90ed40cSTony Nguyen 
29c90ed40cSTony Nguyen /* Table containing properties of supported protocol header fields */
30c90ed40cSTony Nguyen static const
31c90ed40cSTony Nguyen struct ice_flow_field_info ice_flds_info[ICE_FLOW_FIELD_IDX_MAX] = {
32390bd141SQi Zhang 	/* Ether */
33390bd141SQi Zhang 	/* ICE_FLOW_FIELD_IDX_ETH_DA */
34390bd141SQi Zhang 	ICE_FLOW_FLD_INFO(ICE_FLOW_SEG_HDR_ETH, 0, ETH_ALEN),
35390bd141SQi Zhang 	/* ICE_FLOW_FIELD_IDX_ETH_SA */
36390bd141SQi Zhang 	ICE_FLOW_FLD_INFO(ICE_FLOW_SEG_HDR_ETH, ETH_ALEN, ETH_ALEN),
37390bd141SQi Zhang 	/* ICE_FLOW_FIELD_IDX_S_VLAN */
38390bd141SQi Zhang 	ICE_FLOW_FLD_INFO(ICE_FLOW_SEG_HDR_VLAN, 12, sizeof(__be16)),
39390bd141SQi Zhang 	/* ICE_FLOW_FIELD_IDX_C_VLAN */
40390bd141SQi Zhang 	ICE_FLOW_FLD_INFO(ICE_FLOW_SEG_HDR_VLAN, 14, sizeof(__be16)),
41390bd141SQi Zhang 	/* ICE_FLOW_FIELD_IDX_ETH_TYPE */
42390bd141SQi Zhang 	ICE_FLOW_FLD_INFO(ICE_FLOW_SEG_HDR_ETH, 0, sizeof(__be16)),
43c90ed40cSTony Nguyen 	/* IPv4 / IPv6 */
44b199dddbSQi Zhang 	/* ICE_FLOW_FIELD_IDX_IPV4_DSCP */
45b199dddbSQi Zhang 	ICE_FLOW_FLD_INFO_MSK(ICE_FLOW_SEG_HDR_IPV4, 0, 1, 0x00fc),
46b199dddbSQi Zhang 	/* ICE_FLOW_FIELD_IDX_IPV6_DSCP */
47b199dddbSQi Zhang 	ICE_FLOW_FLD_INFO_MSK(ICE_FLOW_SEG_HDR_IPV6, 0, 1, 0x0ff0),
48b199dddbSQi Zhang 	/* ICE_FLOW_FIELD_IDX_IPV4_TTL */
49b199dddbSQi Zhang 	ICE_FLOW_FLD_INFO_MSK(ICE_FLOW_SEG_HDR_NONE, 8, 1, 0xff00),
50b199dddbSQi Zhang 	/* ICE_FLOW_FIELD_IDX_IPV4_PROT */
51b199dddbSQi Zhang 	ICE_FLOW_FLD_INFO_MSK(ICE_FLOW_SEG_HDR_NONE, 8, 1, 0x00ff),
52b199dddbSQi Zhang 	/* ICE_FLOW_FIELD_IDX_IPV6_TTL */
53b199dddbSQi Zhang 	ICE_FLOW_FLD_INFO_MSK(ICE_FLOW_SEG_HDR_NONE, 6, 1, 0x00ff),
54b199dddbSQi Zhang 	/* ICE_FLOW_FIELD_IDX_IPV6_PROT */
55b199dddbSQi Zhang 	ICE_FLOW_FLD_INFO_MSK(ICE_FLOW_SEG_HDR_NONE, 6, 1, 0xff00),
56c90ed40cSTony Nguyen 	/* ICE_FLOW_FIELD_IDX_IPV4_SA */
57c90ed40cSTony Nguyen 	ICE_FLOW_FLD_INFO(ICE_FLOW_SEG_HDR_IPV4, 12, sizeof(struct in_addr)),
58c90ed40cSTony Nguyen 	/* ICE_FLOW_FIELD_IDX_IPV4_DA */
59c90ed40cSTony Nguyen 	ICE_FLOW_FLD_INFO(ICE_FLOW_SEG_HDR_IPV4, 16, sizeof(struct in_addr)),
60c90ed40cSTony Nguyen 	/* ICE_FLOW_FIELD_IDX_IPV6_SA */
61c90ed40cSTony Nguyen 	ICE_FLOW_FLD_INFO(ICE_FLOW_SEG_HDR_IPV6, 8, sizeof(struct in6_addr)),
62c90ed40cSTony Nguyen 	/* ICE_FLOW_FIELD_IDX_IPV6_DA */
63c90ed40cSTony Nguyen 	ICE_FLOW_FLD_INFO(ICE_FLOW_SEG_HDR_IPV6, 24, sizeof(struct in6_addr)),
64c90ed40cSTony Nguyen 	/* Transport */
65c90ed40cSTony Nguyen 	/* ICE_FLOW_FIELD_IDX_TCP_SRC_PORT */
66c90ed40cSTony Nguyen 	ICE_FLOW_FLD_INFO(ICE_FLOW_SEG_HDR_TCP, 0, sizeof(__be16)),
67c90ed40cSTony Nguyen 	/* ICE_FLOW_FIELD_IDX_TCP_DST_PORT */
68c90ed40cSTony Nguyen 	ICE_FLOW_FLD_INFO(ICE_FLOW_SEG_HDR_TCP, 2, sizeof(__be16)),
69c90ed40cSTony Nguyen 	/* ICE_FLOW_FIELD_IDX_UDP_SRC_PORT */
70c90ed40cSTony Nguyen 	ICE_FLOW_FLD_INFO(ICE_FLOW_SEG_HDR_UDP, 0, sizeof(__be16)),
71c90ed40cSTony Nguyen 	/* ICE_FLOW_FIELD_IDX_UDP_DST_PORT */
72c90ed40cSTony Nguyen 	ICE_FLOW_FLD_INFO(ICE_FLOW_SEG_HDR_UDP, 2, sizeof(__be16)),
731c01c8c6SMd Fahad Iqbal Polash 	/* ICE_FLOW_FIELD_IDX_SCTP_SRC_PORT */
741c01c8c6SMd Fahad Iqbal Polash 	ICE_FLOW_FLD_INFO(ICE_FLOW_SEG_HDR_SCTP, 0, sizeof(__be16)),
751c01c8c6SMd Fahad Iqbal Polash 	/* ICE_FLOW_FIELD_IDX_SCTP_DST_PORT */
761c01c8c6SMd Fahad Iqbal Polash 	ICE_FLOW_FLD_INFO(ICE_FLOW_SEG_HDR_SCTP, 2, sizeof(__be16)),
77390bd141SQi Zhang 	/* ICE_FLOW_FIELD_IDX_TCP_FLAGS */
78390bd141SQi Zhang 	ICE_FLOW_FLD_INFO(ICE_FLOW_SEG_HDR_TCP, 13, 1),
79390bd141SQi Zhang 	/* ARP */
80390bd141SQi Zhang 	/* ICE_FLOW_FIELD_IDX_ARP_SIP */
81390bd141SQi Zhang 	ICE_FLOW_FLD_INFO(ICE_FLOW_SEG_HDR_ARP, 14, sizeof(struct in_addr)),
82390bd141SQi Zhang 	/* ICE_FLOW_FIELD_IDX_ARP_DIP */
83390bd141SQi Zhang 	ICE_FLOW_FLD_INFO(ICE_FLOW_SEG_HDR_ARP, 24, sizeof(struct in_addr)),
84390bd141SQi Zhang 	/* ICE_FLOW_FIELD_IDX_ARP_SHA */
85390bd141SQi Zhang 	ICE_FLOW_FLD_INFO(ICE_FLOW_SEG_HDR_ARP, 8, ETH_ALEN),
86390bd141SQi Zhang 	/* ICE_FLOW_FIELD_IDX_ARP_DHA */
87390bd141SQi Zhang 	ICE_FLOW_FLD_INFO(ICE_FLOW_SEG_HDR_ARP, 18, ETH_ALEN),
88390bd141SQi Zhang 	/* ICE_FLOW_FIELD_IDX_ARP_OP */
89390bd141SQi Zhang 	ICE_FLOW_FLD_INFO(ICE_FLOW_SEG_HDR_ARP, 6, sizeof(__be16)),
90390bd141SQi Zhang 	/* ICMP */
91390bd141SQi Zhang 	/* ICE_FLOW_FIELD_IDX_ICMP_TYPE */
92390bd141SQi Zhang 	ICE_FLOW_FLD_INFO(ICE_FLOW_SEG_HDR_ICMP, 0, 1),
93390bd141SQi Zhang 	/* ICE_FLOW_FIELD_IDX_ICMP_CODE */
94390bd141SQi Zhang 	ICE_FLOW_FLD_INFO(ICE_FLOW_SEG_HDR_ICMP, 1, 1),
95a4e82a81STony Nguyen 	/* GRE */
96a4e82a81STony Nguyen 	/* ICE_FLOW_FIELD_IDX_GRE_KEYID */
97a4e82a81STony Nguyen 	ICE_FLOW_FLD_INFO(ICE_FLOW_SEG_HDR_GRE, 12,
98a4e82a81STony Nguyen 			  sizeof_field(struct gre_full_hdr, key)),
990577313eSQi Zhang 	/* GTP */
1000577313eSQi Zhang 	/* ICE_FLOW_FIELD_IDX_GTPC_TEID */
1010577313eSQi Zhang 	ICE_FLOW_FLD_INFO(ICE_FLOW_SEG_HDR_GTPC_TEID, 12, sizeof(__be32)),
1020577313eSQi Zhang 	/* ICE_FLOW_FIELD_IDX_GTPU_IP_TEID */
1030577313eSQi Zhang 	ICE_FLOW_FLD_INFO(ICE_FLOW_SEG_HDR_GTPU_IP, 12, sizeof(__be32)),
1040577313eSQi Zhang 	/* ICE_FLOW_FIELD_IDX_GTPU_EH_TEID */
1050577313eSQi Zhang 	ICE_FLOW_FLD_INFO(ICE_FLOW_SEG_HDR_GTPU_EH, 12, sizeof(__be32)),
1060577313eSQi Zhang 	/* ICE_FLOW_FIELD_IDX_GTPU_EH_QFI */
1070577313eSQi Zhang 	ICE_FLOW_FLD_INFO_MSK(ICE_FLOW_SEG_HDR_GTPU_EH, 22, sizeof(__be16),
1080577313eSQi Zhang 			      0x3f00),
1090577313eSQi Zhang 	/* ICE_FLOW_FIELD_IDX_GTPU_UP_TEID */
1100577313eSQi Zhang 	ICE_FLOW_FLD_INFO(ICE_FLOW_SEG_HDR_GTPU_UP, 12, sizeof(__be32)),
1110577313eSQi Zhang 	/* ICE_FLOW_FIELD_IDX_GTPU_DWN_TEID */
1120577313eSQi Zhang 	ICE_FLOW_FLD_INFO(ICE_FLOW_SEG_HDR_GTPU_DWN, 12, sizeof(__be32)),
1130577313eSQi Zhang 	/* PPPoE */
1140577313eSQi Zhang 	/* ICE_FLOW_FIELD_IDX_PPPOE_SESS_ID */
1150577313eSQi Zhang 	ICE_FLOW_FLD_INFO(ICE_FLOW_SEG_HDR_PPPOE, 2, sizeof(__be16)),
1160577313eSQi Zhang 	/* PFCP */
1170577313eSQi Zhang 	/* ICE_FLOW_FIELD_IDX_PFCP_SEID */
1180577313eSQi Zhang 	ICE_FLOW_FLD_INFO(ICE_FLOW_SEG_HDR_PFCP_SESSION, 12, sizeof(__be64)),
1190577313eSQi Zhang 	/* L2TPv3 */
1200577313eSQi Zhang 	/* ICE_FLOW_FIELD_IDX_L2TPV3_SESS_ID */
1210577313eSQi Zhang 	ICE_FLOW_FLD_INFO(ICE_FLOW_SEG_HDR_L2TPV3, 0, sizeof(__be32)),
1220577313eSQi Zhang 	/* ESP */
1230577313eSQi Zhang 	/* ICE_FLOW_FIELD_IDX_ESP_SPI */
1240577313eSQi Zhang 	ICE_FLOW_FLD_INFO(ICE_FLOW_SEG_HDR_ESP, 0, sizeof(__be32)),
1250577313eSQi Zhang 	/* AH */
1260577313eSQi Zhang 	/* ICE_FLOW_FIELD_IDX_AH_SPI */
1270577313eSQi Zhang 	ICE_FLOW_FLD_INFO(ICE_FLOW_SEG_HDR_AH, 4, sizeof(__be32)),
1280577313eSQi Zhang 	/* NAT_T_ESP */
1290577313eSQi Zhang 	/* ICE_FLOW_FIELD_IDX_NAT_T_ESP_SPI */
1300577313eSQi Zhang 	ICE_FLOW_FLD_INFO(ICE_FLOW_SEG_HDR_NAT_T_ESP, 8, sizeof(__be32)),
131c90ed40cSTony Nguyen };
132c90ed40cSTony Nguyen 
13331ad4e4eSTony Nguyen /* Bitmaps indicating relevant packet types for a particular protocol header
13431ad4e4eSTony Nguyen  *
135390bd141SQi Zhang  * Packet types for packets with an Outer/First/Single MAC header
13631ad4e4eSTony Nguyen  */
137390bd141SQi Zhang static const u32 ice_ptypes_mac_ofos[] = {
138390bd141SQi Zhang 	0xFDC00846, 0xBFBF7F7E, 0xF70001DF, 0xFEFDFDFB,
139390bd141SQi Zhang 	0x0000077E, 0x00000000, 0x00000000, 0x00000000,
140390bd141SQi Zhang 	0x00400000, 0x03FFF000, 0x7FFFFFE0, 0x00000000,
141390bd141SQi Zhang 	0x00000000, 0x00000000, 0x00000000, 0x00000000,
142390bd141SQi Zhang 	0x00000000, 0x00000000, 0x00000000, 0x00000000,
143390bd141SQi Zhang 	0x00000000, 0x00000000, 0x00000000, 0x00000000,
144390bd141SQi Zhang 	0x00000000, 0x00000000, 0x00000000, 0x00000000,
145390bd141SQi Zhang 	0x00000000, 0x00000000, 0x00000000, 0x00000000,
146390bd141SQi Zhang };
147390bd141SQi Zhang 
148390bd141SQi Zhang /* Packet types for packets with an Innermost/Last MAC VLAN header */
149390bd141SQi Zhang static const u32 ice_ptypes_macvlan_il[] = {
150390bd141SQi Zhang 	0x00000000, 0xBC000000, 0x000001DF, 0xF0000000,
151390bd141SQi Zhang 	0x0000077E, 0x00000000, 0x00000000, 0x00000000,
152390bd141SQi Zhang 	0x00000000, 0x00000000, 0x00000000, 0x00000000,
153390bd141SQi Zhang 	0x00000000, 0x00000000, 0x00000000, 0x00000000,
154390bd141SQi Zhang 	0x00000000, 0x00000000, 0x00000000, 0x00000000,
155390bd141SQi Zhang 	0x00000000, 0x00000000, 0x00000000, 0x00000000,
156390bd141SQi Zhang 	0x00000000, 0x00000000, 0x00000000, 0x00000000,
157390bd141SQi Zhang 	0x00000000, 0x00000000, 0x00000000, 0x00000000,
158390bd141SQi Zhang };
159390bd141SQi Zhang 
160390bd141SQi Zhang /* Packet types for packets with an Outer/First/Single IPv4 header */
16131ad4e4eSTony Nguyen static const u32 ice_ptypes_ipv4_ofos[] = {
16231ad4e4eSTony Nguyen 	0x1DC00000, 0x04000800, 0x00000000, 0x00000000,
1630577313eSQi Zhang 	0x00000000, 0x00000155, 0x00000000, 0x00000000,
1640577313eSQi Zhang 	0x00000000, 0x000FC000, 0x00000000, 0x00000000,
16531ad4e4eSTony Nguyen 	0x00000000, 0x00000000, 0x00000000, 0x00000000,
16631ad4e4eSTony Nguyen 	0x00000000, 0x00000000, 0x00000000, 0x00000000,
16731ad4e4eSTony Nguyen 	0x00000000, 0x00000000, 0x00000000, 0x00000000,
16831ad4e4eSTony Nguyen 	0x00000000, 0x00000000, 0x00000000, 0x00000000,
16931ad4e4eSTony Nguyen 	0x00000000, 0x00000000, 0x00000000, 0x00000000,
17031ad4e4eSTony Nguyen 	0x00000000, 0x00000000, 0x00000000, 0x00000000,
17131ad4e4eSTony Nguyen 	0x00000000, 0x00000000, 0x00000000, 0x00000000,
17231ad4e4eSTony Nguyen };
17331ad4e4eSTony Nguyen 
17431ad4e4eSTony Nguyen /* Packet types for packets with an Innermost/Last IPv4 header */
17531ad4e4eSTony Nguyen static const u32 ice_ptypes_ipv4_il[] = {
17631ad4e4eSTony Nguyen 	0xE0000000, 0xB807700E, 0x80000003, 0xE01DC03B,
17731ad4e4eSTony Nguyen 	0x0000000E, 0x00000000, 0x00000000, 0x00000000,
1780577313eSQi Zhang 	0x00000000, 0x00000000, 0x001FF800, 0x00000000,
17931ad4e4eSTony Nguyen 	0x00000000, 0x00000000, 0x00000000, 0x00000000,
18031ad4e4eSTony Nguyen 	0x00000000, 0x00000000, 0x00000000, 0x00000000,
18131ad4e4eSTony Nguyen 	0x00000000, 0x00000000, 0x00000000, 0x00000000,
18231ad4e4eSTony Nguyen 	0x00000000, 0x00000000, 0x00000000, 0x00000000,
18331ad4e4eSTony Nguyen 	0x00000000, 0x00000000, 0x00000000, 0x00000000,
18431ad4e4eSTony Nguyen };
18531ad4e4eSTony Nguyen 
18631ad4e4eSTony Nguyen /* Packet types for packets with an Outer/First/Single IPv6 header */
18731ad4e4eSTony Nguyen static const u32 ice_ptypes_ipv6_ofos[] = {
18831ad4e4eSTony Nguyen 	0x00000000, 0x00000000, 0x77000000, 0x10002000,
1890577313eSQi Zhang 	0x00000000, 0x000002AA, 0x00000000, 0x00000000,
1900577313eSQi Zhang 	0x00000000, 0x03F00000, 0x00000000, 0x00000000,
19131ad4e4eSTony Nguyen 	0x00000000, 0x00000000, 0x00000000, 0x00000000,
19231ad4e4eSTony Nguyen 	0x00000000, 0x00000000, 0x00000000, 0x00000000,
19331ad4e4eSTony Nguyen 	0x00000000, 0x00000000, 0x00000000, 0x00000000,
19431ad4e4eSTony Nguyen 	0x00000000, 0x00000000, 0x00000000, 0x00000000,
19531ad4e4eSTony Nguyen 	0x00000000, 0x00000000, 0x00000000, 0x00000000,
19631ad4e4eSTony Nguyen 	0x00000000, 0x00000000, 0x00000000, 0x00000000,
19731ad4e4eSTony Nguyen 	0x00000000, 0x00000000, 0x00000000, 0x00000000,
19831ad4e4eSTony Nguyen };
19931ad4e4eSTony Nguyen 
20031ad4e4eSTony Nguyen /* Packet types for packets with an Innermost/Last IPv6 header */
20131ad4e4eSTony Nguyen static const u32 ice_ptypes_ipv6_il[] = {
20231ad4e4eSTony Nguyen 	0x00000000, 0x03B80770, 0x000001DC, 0x0EE00000,
20331ad4e4eSTony Nguyen 	0x00000770, 0x00000000, 0x00000000, 0x00000000,
2040577313eSQi Zhang 	0x00000000, 0x00000000, 0x7FE00000, 0x00000000,
20531ad4e4eSTony Nguyen 	0x00000000, 0x00000000, 0x00000000, 0x00000000,
20631ad4e4eSTony Nguyen 	0x00000000, 0x00000000, 0x00000000, 0x00000000,
20731ad4e4eSTony Nguyen 	0x00000000, 0x00000000, 0x00000000, 0x00000000,
20831ad4e4eSTony Nguyen 	0x00000000, 0x00000000, 0x00000000, 0x00000000,
20931ad4e4eSTony Nguyen 	0x00000000, 0x00000000, 0x00000000, 0x00000000,
21031ad4e4eSTony Nguyen };
21131ad4e4eSTony Nguyen 
212051d2b5cSDan Nowlin /* Packet types for packets with an Outer/First/Single IPv4 header - no L4 */
213051d2b5cSDan Nowlin static const u32 ice_ipv4_ofos_no_l4[] = {
214051d2b5cSDan Nowlin 	0x10C00000, 0x04000800, 0x00000000, 0x00000000,
215051d2b5cSDan Nowlin 	0x00000000, 0x00000000, 0x00000000, 0x00000000,
216051d2b5cSDan Nowlin 	0x00000000, 0x00000000, 0x00000000, 0x00000000,
217051d2b5cSDan Nowlin 	0x00000000, 0x00000000, 0x00000000, 0x00000000,
218051d2b5cSDan Nowlin 	0x00000000, 0x00000000, 0x00000000, 0x00000000,
219051d2b5cSDan Nowlin 	0x00000000, 0x00000000, 0x00000000, 0x00000000,
220051d2b5cSDan Nowlin 	0x00000000, 0x00000000, 0x00000000, 0x00000000,
221051d2b5cSDan Nowlin 	0x00000000, 0x00000000, 0x00000000, 0x00000000,
222051d2b5cSDan Nowlin };
223051d2b5cSDan Nowlin 
224390bd141SQi Zhang /* Packet types for packets with an Outermost/First ARP header */
225390bd141SQi Zhang static const u32 ice_ptypes_arp_of[] = {
226390bd141SQi Zhang 	0x00000800, 0x00000000, 0x00000000, 0x00000000,
227390bd141SQi Zhang 	0x00000000, 0x00000000, 0x00000000, 0x00000000,
228390bd141SQi Zhang 	0x00000000, 0x00000000, 0x00000000, 0x00000000,
229390bd141SQi Zhang 	0x00000000, 0x00000000, 0x00000000, 0x00000000,
230390bd141SQi Zhang 	0x00000000, 0x00000000, 0x00000000, 0x00000000,
231390bd141SQi Zhang 	0x00000000, 0x00000000, 0x00000000, 0x00000000,
232390bd141SQi Zhang 	0x00000000, 0x00000000, 0x00000000, 0x00000000,
233390bd141SQi Zhang 	0x00000000, 0x00000000, 0x00000000, 0x00000000,
234390bd141SQi Zhang };
235390bd141SQi Zhang 
236051d2b5cSDan Nowlin /* Packet types for packets with an Innermost/Last IPv4 header - no L4 */
237051d2b5cSDan Nowlin static const u32 ice_ipv4_il_no_l4[] = {
238051d2b5cSDan Nowlin 	0x60000000, 0x18043008, 0x80000002, 0x6010c021,
239051d2b5cSDan Nowlin 	0x00000008, 0x00000000, 0x00000000, 0x00000000,
240051d2b5cSDan Nowlin 	0x00000000, 0x00000000, 0x00000000, 0x00000000,
241051d2b5cSDan Nowlin 	0x00000000, 0x00000000, 0x00000000, 0x00000000,
242051d2b5cSDan Nowlin 	0x00000000, 0x00000000, 0x00000000, 0x00000000,
243051d2b5cSDan Nowlin 	0x00000000, 0x00000000, 0x00000000, 0x00000000,
244051d2b5cSDan Nowlin 	0x00000000, 0x00000000, 0x00000000, 0x00000000,
245051d2b5cSDan Nowlin 	0x00000000, 0x00000000, 0x00000000, 0x00000000,
246051d2b5cSDan Nowlin };
247051d2b5cSDan Nowlin 
248051d2b5cSDan Nowlin /* Packet types for packets with an Outer/First/Single IPv6 header - no L4 */
249051d2b5cSDan Nowlin static const u32 ice_ipv6_ofos_no_l4[] = {
250051d2b5cSDan Nowlin 	0x00000000, 0x00000000, 0x43000000, 0x10002000,
251051d2b5cSDan Nowlin 	0x00000000, 0x00000000, 0x00000000, 0x00000000,
252051d2b5cSDan Nowlin 	0x00000000, 0x00000000, 0x00000000, 0x00000000,
253051d2b5cSDan Nowlin 	0x00000000, 0x00000000, 0x00000000, 0x00000000,
254051d2b5cSDan Nowlin 	0x00000000, 0x00000000, 0x00000000, 0x00000000,
255051d2b5cSDan Nowlin 	0x00000000, 0x00000000, 0x00000000, 0x00000000,
256051d2b5cSDan Nowlin 	0x00000000, 0x00000000, 0x00000000, 0x00000000,
257051d2b5cSDan Nowlin 	0x00000000, 0x00000000, 0x00000000, 0x00000000,
258051d2b5cSDan Nowlin };
259051d2b5cSDan Nowlin 
260051d2b5cSDan Nowlin /* Packet types for packets with an Innermost/Last IPv6 header - no L4 */
261051d2b5cSDan Nowlin static const u32 ice_ipv6_il_no_l4[] = {
262051d2b5cSDan Nowlin 	0x00000000, 0x02180430, 0x0000010c, 0x086010c0,
263051d2b5cSDan Nowlin 	0x00000430, 0x00000000, 0x00000000, 0x00000000,
264051d2b5cSDan Nowlin 	0x00000000, 0x00000000, 0x00000000, 0x00000000,
265051d2b5cSDan Nowlin 	0x00000000, 0x00000000, 0x00000000, 0x00000000,
266051d2b5cSDan Nowlin 	0x00000000, 0x00000000, 0x00000000, 0x00000000,
267051d2b5cSDan Nowlin 	0x00000000, 0x00000000, 0x00000000, 0x00000000,
268051d2b5cSDan Nowlin 	0x00000000, 0x00000000, 0x00000000, 0x00000000,
269051d2b5cSDan Nowlin 	0x00000000, 0x00000000, 0x00000000, 0x00000000,
270051d2b5cSDan Nowlin };
271051d2b5cSDan Nowlin 
27231ad4e4eSTony Nguyen /* UDP Packet types for non-tunneled packets or tunneled
27331ad4e4eSTony Nguyen  * packets with inner UDP.
27431ad4e4eSTony Nguyen  */
27531ad4e4eSTony Nguyen static const u32 ice_ptypes_udp_il[] = {
27631ad4e4eSTony Nguyen 	0x81000000, 0x20204040, 0x04000010, 0x80810102,
27731ad4e4eSTony Nguyen 	0x00000040, 0x00000000, 0x00000000, 0x00000000,
2780577313eSQi Zhang 	0x00000000, 0x00410000, 0x90842000, 0x00000007,
27931ad4e4eSTony Nguyen 	0x00000000, 0x00000000, 0x00000000, 0x00000000,
28031ad4e4eSTony Nguyen 	0x00000000, 0x00000000, 0x00000000, 0x00000000,
28131ad4e4eSTony Nguyen 	0x00000000, 0x00000000, 0x00000000, 0x00000000,
28231ad4e4eSTony Nguyen 	0x00000000, 0x00000000, 0x00000000, 0x00000000,
28331ad4e4eSTony Nguyen 	0x00000000, 0x00000000, 0x00000000, 0x00000000,
28431ad4e4eSTony Nguyen };
28531ad4e4eSTony Nguyen 
28631ad4e4eSTony Nguyen /* Packet types for packets with an Innermost/Last TCP header */
28731ad4e4eSTony Nguyen static const u32 ice_ptypes_tcp_il[] = {
28831ad4e4eSTony Nguyen 	0x04000000, 0x80810102, 0x10000040, 0x02040408,
28931ad4e4eSTony Nguyen 	0x00000102, 0x00000000, 0x00000000, 0x00000000,
2900577313eSQi Zhang 	0x00000000, 0x00820000, 0x21084000, 0x00000000,
29131ad4e4eSTony Nguyen 	0x00000000, 0x00000000, 0x00000000, 0x00000000,
29231ad4e4eSTony Nguyen 	0x00000000, 0x00000000, 0x00000000, 0x00000000,
29331ad4e4eSTony Nguyen 	0x00000000, 0x00000000, 0x00000000, 0x00000000,
29431ad4e4eSTony Nguyen 	0x00000000, 0x00000000, 0x00000000, 0x00000000,
29531ad4e4eSTony Nguyen 	0x00000000, 0x00000000, 0x00000000, 0x00000000,
29631ad4e4eSTony Nguyen };
29731ad4e4eSTony Nguyen 
29831ad4e4eSTony Nguyen /* Packet types for packets with an Innermost/Last SCTP header */
29931ad4e4eSTony Nguyen static const u32 ice_ptypes_sctp_il[] = {
30031ad4e4eSTony Nguyen 	0x08000000, 0x01020204, 0x20000081, 0x04080810,
30131ad4e4eSTony Nguyen 	0x00000204, 0x00000000, 0x00000000, 0x00000000,
3020577313eSQi Zhang 	0x00000000, 0x01040000, 0x00000000, 0x00000000,
30331ad4e4eSTony Nguyen 	0x00000000, 0x00000000, 0x00000000, 0x00000000,
30431ad4e4eSTony Nguyen 	0x00000000, 0x00000000, 0x00000000, 0x00000000,
30531ad4e4eSTony Nguyen 	0x00000000, 0x00000000, 0x00000000, 0x00000000,
30631ad4e4eSTony Nguyen 	0x00000000, 0x00000000, 0x00000000, 0x00000000,
30731ad4e4eSTony Nguyen 	0x00000000, 0x00000000, 0x00000000, 0x00000000,
308390bd141SQi Zhang };
309390bd141SQi Zhang 
310390bd141SQi Zhang /* Packet types for packets with an Outermost/First ICMP header */
311390bd141SQi Zhang static const u32 ice_ptypes_icmp_of[] = {
312390bd141SQi Zhang 	0x10000000, 0x00000000, 0x00000000, 0x00000000,
313390bd141SQi Zhang 	0x00000000, 0x00000000, 0x00000000, 0x00000000,
314390bd141SQi Zhang 	0x00000000, 0x00000000, 0x00000000, 0x00000000,
315390bd141SQi Zhang 	0x00000000, 0x00000000, 0x00000000, 0x00000000,
316390bd141SQi Zhang 	0x00000000, 0x00000000, 0x00000000, 0x00000000,
317390bd141SQi Zhang 	0x00000000, 0x00000000, 0x00000000, 0x00000000,
318390bd141SQi Zhang 	0x00000000, 0x00000000, 0x00000000, 0x00000000,
319390bd141SQi Zhang 	0x00000000, 0x00000000, 0x00000000, 0x00000000,
320390bd141SQi Zhang };
321390bd141SQi Zhang 
322390bd141SQi Zhang /* Packet types for packets with an Innermost/Last ICMP header */
323390bd141SQi Zhang static const u32 ice_ptypes_icmp_il[] = {
324390bd141SQi Zhang 	0x00000000, 0x02040408, 0x40000102, 0x08101020,
325390bd141SQi Zhang 	0x00000408, 0x00000000, 0x00000000, 0x00000000,
326390bd141SQi Zhang 	0x00000000, 0x00000000, 0x42108000, 0x00000000,
327390bd141SQi Zhang 	0x00000000, 0x00000000, 0x00000000, 0x00000000,
328390bd141SQi Zhang 	0x00000000, 0x00000000, 0x00000000, 0x00000000,
329390bd141SQi Zhang 	0x00000000, 0x00000000, 0x00000000, 0x00000000,
330390bd141SQi Zhang 	0x00000000, 0x00000000, 0x00000000, 0x00000000,
33131ad4e4eSTony Nguyen 	0x00000000, 0x00000000, 0x00000000, 0x00000000,
33231ad4e4eSTony Nguyen };
33331ad4e4eSTony Nguyen 
334a4e82a81STony Nguyen /* Packet types for packets with an Outermost/First GRE header */
335a4e82a81STony Nguyen static const u32 ice_ptypes_gre_of[] = {
336a4e82a81STony Nguyen 	0x00000000, 0xBFBF7800, 0x000001DF, 0xFEFDE000,
337a4e82a81STony Nguyen 	0x0000017E, 0x00000000, 0x00000000, 0x00000000,
338a4e82a81STony Nguyen 	0x00000000, 0x00000000, 0x00000000, 0x00000000,
339a4e82a81STony Nguyen 	0x00000000, 0x00000000, 0x00000000, 0x00000000,
340a4e82a81STony Nguyen 	0x00000000, 0x00000000, 0x00000000, 0x00000000,
341a4e82a81STony Nguyen 	0x00000000, 0x00000000, 0x00000000, 0x00000000,
342a4e82a81STony Nguyen 	0x00000000, 0x00000000, 0x00000000, 0x00000000,
343a4e82a81STony Nguyen 	0x00000000, 0x00000000, 0x00000000, 0x00000000,
344a4e82a81STony Nguyen };
345a4e82a81STony Nguyen 
346390bd141SQi Zhang /* Packet types for packets with an Innermost/Last MAC header */
347390bd141SQi Zhang static const u32 ice_ptypes_mac_il[] = {
348390bd141SQi Zhang 	0x00000000, 0x00000000, 0x00000000, 0x00000000,
349390bd141SQi Zhang 	0x00000000, 0x00000000, 0x00000000, 0x00000000,
350390bd141SQi Zhang 	0x00000000, 0x00000000, 0x00000000, 0x00000000,
351390bd141SQi Zhang 	0x00000000, 0x00000000, 0x00000000, 0x00000000,
352390bd141SQi Zhang 	0x00000000, 0x00000000, 0x00000000, 0x00000000,
353390bd141SQi Zhang 	0x00000000, 0x00000000, 0x00000000, 0x00000000,
354390bd141SQi Zhang 	0x00000000, 0x00000000, 0x00000000, 0x00000000,
355390bd141SQi Zhang 	0x00000000, 0x00000000, 0x00000000, 0x00000000,
356390bd141SQi Zhang };
357390bd141SQi Zhang 
3580577313eSQi Zhang /* Packet types for GTPC */
3590577313eSQi Zhang static const u32 ice_ptypes_gtpc[] = {
3600577313eSQi Zhang 	0x00000000, 0x00000000, 0x00000000, 0x00000000,
3610577313eSQi Zhang 	0x00000000, 0x00000000, 0x00000000, 0x00000000,
3620577313eSQi Zhang 	0x00000000, 0x00000000, 0x00000180, 0x00000000,
3630577313eSQi Zhang 	0x00000000, 0x00000000, 0x00000000, 0x00000000,
3640577313eSQi Zhang 	0x00000000, 0x00000000, 0x00000000, 0x00000000,
3650577313eSQi Zhang 	0x00000000, 0x00000000, 0x00000000, 0x00000000,
3660577313eSQi Zhang 	0x00000000, 0x00000000, 0x00000000, 0x00000000,
3670577313eSQi Zhang 	0x00000000, 0x00000000, 0x00000000, 0x00000000,
3680577313eSQi Zhang };
3690577313eSQi Zhang 
3700577313eSQi Zhang /* Packet types for GTPC with TEID */
3710577313eSQi Zhang static const u32 ice_ptypes_gtpc_tid[] = {
3720577313eSQi Zhang 	0x00000000, 0x00000000, 0x00000000, 0x00000000,
3730577313eSQi Zhang 	0x00000000, 0x00000000, 0x00000000, 0x00000000,
3740577313eSQi Zhang 	0x00000000, 0x00000000, 0x00000060, 0x00000000,
3750577313eSQi Zhang 	0x00000000, 0x00000000, 0x00000000, 0x00000000,
3760577313eSQi Zhang 	0x00000000, 0x00000000, 0x00000000, 0x00000000,
3770577313eSQi Zhang 	0x00000000, 0x00000000, 0x00000000, 0x00000000,
3780577313eSQi Zhang 	0x00000000, 0x00000000, 0x00000000, 0x00000000,
3790577313eSQi Zhang 	0x00000000, 0x00000000, 0x00000000, 0x00000000,
3800577313eSQi Zhang };
3810577313eSQi Zhang 
382*cbad5db8SQi Zhang /* Packet types for GTPU */
383*cbad5db8SQi Zhang static const struct ice_ptype_attributes ice_attr_gtpu_eh[] = {
384*cbad5db8SQi Zhang 	{ ICE_MAC_IPV4_GTPU_IPV4_FRAG,	  ICE_PTYPE_ATTR_GTP_PDU_EH },
385*cbad5db8SQi Zhang 	{ ICE_MAC_IPV4_GTPU_IPV4_PAY,	  ICE_PTYPE_ATTR_GTP_PDU_EH },
386*cbad5db8SQi Zhang 	{ ICE_MAC_IPV4_GTPU_IPV4_UDP_PAY, ICE_PTYPE_ATTR_GTP_PDU_EH },
387*cbad5db8SQi Zhang 	{ ICE_MAC_IPV4_GTPU_IPV4_TCP,	  ICE_PTYPE_ATTR_GTP_PDU_EH },
388*cbad5db8SQi Zhang 	{ ICE_MAC_IPV4_GTPU_IPV4_ICMP,	  ICE_PTYPE_ATTR_GTP_PDU_EH },
389*cbad5db8SQi Zhang 	{ ICE_MAC_IPV6_GTPU_IPV4_FRAG,	  ICE_PTYPE_ATTR_GTP_PDU_EH },
390*cbad5db8SQi Zhang 	{ ICE_MAC_IPV6_GTPU_IPV4_PAY,	  ICE_PTYPE_ATTR_GTP_PDU_EH },
391*cbad5db8SQi Zhang 	{ ICE_MAC_IPV6_GTPU_IPV4_UDP_PAY, ICE_PTYPE_ATTR_GTP_PDU_EH },
392*cbad5db8SQi Zhang 	{ ICE_MAC_IPV6_GTPU_IPV4_TCP,	  ICE_PTYPE_ATTR_GTP_PDU_EH },
393*cbad5db8SQi Zhang 	{ ICE_MAC_IPV6_GTPU_IPV4_ICMP,	  ICE_PTYPE_ATTR_GTP_PDU_EH },
394*cbad5db8SQi Zhang 	{ ICE_MAC_IPV4_GTPU_IPV6_FRAG,	  ICE_PTYPE_ATTR_GTP_PDU_EH },
395*cbad5db8SQi Zhang 	{ ICE_MAC_IPV4_GTPU_IPV6_PAY,	  ICE_PTYPE_ATTR_GTP_PDU_EH },
396*cbad5db8SQi Zhang 	{ ICE_MAC_IPV4_GTPU_IPV6_UDP_PAY, ICE_PTYPE_ATTR_GTP_PDU_EH },
397*cbad5db8SQi Zhang 	{ ICE_MAC_IPV4_GTPU_IPV6_TCP,	  ICE_PTYPE_ATTR_GTP_PDU_EH },
398*cbad5db8SQi Zhang 	{ ICE_MAC_IPV4_GTPU_IPV6_ICMPV6,  ICE_PTYPE_ATTR_GTP_PDU_EH },
399*cbad5db8SQi Zhang 	{ ICE_MAC_IPV6_GTPU_IPV6_FRAG,	  ICE_PTYPE_ATTR_GTP_PDU_EH },
400*cbad5db8SQi Zhang 	{ ICE_MAC_IPV6_GTPU_IPV6_PAY,	  ICE_PTYPE_ATTR_GTP_PDU_EH },
401*cbad5db8SQi Zhang 	{ ICE_MAC_IPV6_GTPU_IPV6_UDP_PAY, ICE_PTYPE_ATTR_GTP_PDU_EH },
402*cbad5db8SQi Zhang 	{ ICE_MAC_IPV6_GTPU_IPV6_TCP,	  ICE_PTYPE_ATTR_GTP_PDU_EH },
403*cbad5db8SQi Zhang 	{ ICE_MAC_IPV6_GTPU_IPV6_ICMPV6,  ICE_PTYPE_ATTR_GTP_PDU_EH },
404*cbad5db8SQi Zhang };
405*cbad5db8SQi Zhang 
406*cbad5db8SQi Zhang static const struct ice_ptype_attributes ice_attr_gtpu_down[] = {
407*cbad5db8SQi Zhang 	{ ICE_MAC_IPV4_GTPU_IPV4_FRAG,	  ICE_PTYPE_ATTR_GTP_DOWNLINK },
408*cbad5db8SQi Zhang 	{ ICE_MAC_IPV4_GTPU_IPV4_PAY,	  ICE_PTYPE_ATTR_GTP_DOWNLINK },
409*cbad5db8SQi Zhang 	{ ICE_MAC_IPV4_GTPU_IPV4_UDP_PAY, ICE_PTYPE_ATTR_GTP_DOWNLINK },
410*cbad5db8SQi Zhang 	{ ICE_MAC_IPV4_GTPU_IPV4_TCP,	  ICE_PTYPE_ATTR_GTP_DOWNLINK },
411*cbad5db8SQi Zhang 	{ ICE_MAC_IPV4_GTPU_IPV4_ICMP,	  ICE_PTYPE_ATTR_GTP_DOWNLINK },
412*cbad5db8SQi Zhang 	{ ICE_MAC_IPV6_GTPU_IPV4_FRAG,	  ICE_PTYPE_ATTR_GTP_DOWNLINK },
413*cbad5db8SQi Zhang 	{ ICE_MAC_IPV6_GTPU_IPV4_PAY,	  ICE_PTYPE_ATTR_GTP_DOWNLINK },
414*cbad5db8SQi Zhang 	{ ICE_MAC_IPV6_GTPU_IPV4_UDP_PAY, ICE_PTYPE_ATTR_GTP_DOWNLINK },
415*cbad5db8SQi Zhang 	{ ICE_MAC_IPV6_GTPU_IPV4_TCP,	  ICE_PTYPE_ATTR_GTP_DOWNLINK },
416*cbad5db8SQi Zhang 	{ ICE_MAC_IPV6_GTPU_IPV4_ICMP,	  ICE_PTYPE_ATTR_GTP_DOWNLINK },
417*cbad5db8SQi Zhang 	{ ICE_MAC_IPV4_GTPU_IPV6_FRAG,	  ICE_PTYPE_ATTR_GTP_DOWNLINK },
418*cbad5db8SQi Zhang 	{ ICE_MAC_IPV4_GTPU_IPV6_PAY,	  ICE_PTYPE_ATTR_GTP_DOWNLINK },
419*cbad5db8SQi Zhang 	{ ICE_MAC_IPV4_GTPU_IPV6_UDP_PAY, ICE_PTYPE_ATTR_GTP_DOWNLINK },
420*cbad5db8SQi Zhang 	{ ICE_MAC_IPV4_GTPU_IPV6_TCP,	  ICE_PTYPE_ATTR_GTP_DOWNLINK },
421*cbad5db8SQi Zhang 	{ ICE_MAC_IPV4_GTPU_IPV6_ICMPV6,  ICE_PTYPE_ATTR_GTP_DOWNLINK },
422*cbad5db8SQi Zhang 	{ ICE_MAC_IPV6_GTPU_IPV6_FRAG,	  ICE_PTYPE_ATTR_GTP_DOWNLINK },
423*cbad5db8SQi Zhang 	{ ICE_MAC_IPV6_GTPU_IPV6_PAY,	  ICE_PTYPE_ATTR_GTP_DOWNLINK },
424*cbad5db8SQi Zhang 	{ ICE_MAC_IPV6_GTPU_IPV6_UDP_PAY, ICE_PTYPE_ATTR_GTP_DOWNLINK },
425*cbad5db8SQi Zhang 	{ ICE_MAC_IPV6_GTPU_IPV6_TCP,	  ICE_PTYPE_ATTR_GTP_DOWNLINK },
426*cbad5db8SQi Zhang 	{ ICE_MAC_IPV6_GTPU_IPV6_ICMPV6,  ICE_PTYPE_ATTR_GTP_DOWNLINK },
427*cbad5db8SQi Zhang };
428*cbad5db8SQi Zhang 
429*cbad5db8SQi Zhang static const struct ice_ptype_attributes ice_attr_gtpu_up[] = {
430*cbad5db8SQi Zhang 	{ ICE_MAC_IPV4_GTPU_IPV4_FRAG,	  ICE_PTYPE_ATTR_GTP_UPLINK },
431*cbad5db8SQi Zhang 	{ ICE_MAC_IPV4_GTPU_IPV4_PAY,	  ICE_PTYPE_ATTR_GTP_UPLINK },
432*cbad5db8SQi Zhang 	{ ICE_MAC_IPV4_GTPU_IPV4_UDP_PAY, ICE_PTYPE_ATTR_GTP_UPLINK },
433*cbad5db8SQi Zhang 	{ ICE_MAC_IPV4_GTPU_IPV4_TCP,	  ICE_PTYPE_ATTR_GTP_UPLINK },
434*cbad5db8SQi Zhang 	{ ICE_MAC_IPV4_GTPU_IPV4_ICMP,	  ICE_PTYPE_ATTR_GTP_UPLINK },
435*cbad5db8SQi Zhang 	{ ICE_MAC_IPV6_GTPU_IPV4_FRAG,	  ICE_PTYPE_ATTR_GTP_UPLINK },
436*cbad5db8SQi Zhang 	{ ICE_MAC_IPV6_GTPU_IPV4_PAY,	  ICE_PTYPE_ATTR_GTP_UPLINK },
437*cbad5db8SQi Zhang 	{ ICE_MAC_IPV6_GTPU_IPV4_UDP_PAY, ICE_PTYPE_ATTR_GTP_UPLINK },
438*cbad5db8SQi Zhang 	{ ICE_MAC_IPV6_GTPU_IPV4_TCP,	  ICE_PTYPE_ATTR_GTP_UPLINK },
439*cbad5db8SQi Zhang 	{ ICE_MAC_IPV6_GTPU_IPV4_ICMP,	  ICE_PTYPE_ATTR_GTP_UPLINK },
440*cbad5db8SQi Zhang 	{ ICE_MAC_IPV4_GTPU_IPV6_FRAG,	  ICE_PTYPE_ATTR_GTP_UPLINK },
441*cbad5db8SQi Zhang 	{ ICE_MAC_IPV4_GTPU_IPV6_PAY,	  ICE_PTYPE_ATTR_GTP_UPLINK },
442*cbad5db8SQi Zhang 	{ ICE_MAC_IPV4_GTPU_IPV6_UDP_PAY, ICE_PTYPE_ATTR_GTP_UPLINK },
443*cbad5db8SQi Zhang 	{ ICE_MAC_IPV4_GTPU_IPV6_TCP,	  ICE_PTYPE_ATTR_GTP_UPLINK },
444*cbad5db8SQi Zhang 	{ ICE_MAC_IPV4_GTPU_IPV6_ICMPV6,  ICE_PTYPE_ATTR_GTP_UPLINK },
445*cbad5db8SQi Zhang 	{ ICE_MAC_IPV6_GTPU_IPV6_FRAG,	  ICE_PTYPE_ATTR_GTP_UPLINK },
446*cbad5db8SQi Zhang 	{ ICE_MAC_IPV6_GTPU_IPV6_PAY,	  ICE_PTYPE_ATTR_GTP_UPLINK },
447*cbad5db8SQi Zhang 	{ ICE_MAC_IPV6_GTPU_IPV6_UDP_PAY, ICE_PTYPE_ATTR_GTP_UPLINK },
448*cbad5db8SQi Zhang 	{ ICE_MAC_IPV6_GTPU_IPV6_TCP,	  ICE_PTYPE_ATTR_GTP_UPLINK },
449*cbad5db8SQi Zhang 	{ ICE_MAC_IPV6_GTPU_IPV6_ICMPV6,  ICE_PTYPE_ATTR_GTP_UPLINK },
450*cbad5db8SQi Zhang };
451*cbad5db8SQi Zhang 
4520577313eSQi Zhang static const u32 ice_ptypes_gtpu[] = {
4530577313eSQi Zhang 	0x00000000, 0x00000000, 0x00000000, 0x00000000,
4540577313eSQi Zhang 	0x00000000, 0x00000000, 0x00000000, 0x00000000,
4550577313eSQi Zhang 	0x00000000, 0x00000000, 0x7FFFFE00, 0x00000000,
4560577313eSQi Zhang 	0x00000000, 0x00000000, 0x00000000, 0x00000000,
4570577313eSQi Zhang 	0x00000000, 0x00000000, 0x00000000, 0x00000000,
4580577313eSQi Zhang 	0x00000000, 0x00000000, 0x00000000, 0x00000000,
4590577313eSQi Zhang 	0x00000000, 0x00000000, 0x00000000, 0x00000000,
4600577313eSQi Zhang 	0x00000000, 0x00000000, 0x00000000, 0x00000000,
4610577313eSQi Zhang };
4620577313eSQi Zhang 
4630577313eSQi Zhang /* Packet types for PPPoE */
4640577313eSQi Zhang static const u32 ice_ptypes_pppoe[] = {
4650577313eSQi Zhang 	0x00000000, 0x00000000, 0x00000000, 0x00000000,
4660577313eSQi Zhang 	0x00000000, 0x00000000, 0x00000000, 0x00000000,
4670577313eSQi Zhang 	0x00000000, 0x03ffe000, 0x00000000, 0x00000000,
4680577313eSQi Zhang 	0x00000000, 0x00000000, 0x00000000, 0x00000000,
4690577313eSQi Zhang 	0x00000000, 0x00000000, 0x00000000, 0x00000000,
4700577313eSQi Zhang 	0x00000000, 0x00000000, 0x00000000, 0x00000000,
4710577313eSQi Zhang 	0x00000000, 0x00000000, 0x00000000, 0x00000000,
4720577313eSQi Zhang 	0x00000000, 0x00000000, 0x00000000, 0x00000000,
4730577313eSQi Zhang };
4740577313eSQi Zhang 
4750577313eSQi Zhang /* Packet types for packets with PFCP NODE header */
4760577313eSQi Zhang static const u32 ice_ptypes_pfcp_node[] = {
4770577313eSQi Zhang 	0x00000000, 0x00000000, 0x00000000, 0x00000000,
4780577313eSQi Zhang 	0x00000000, 0x00000000, 0x00000000, 0x00000000,
4790577313eSQi Zhang 	0x00000000, 0x00000000, 0x80000000, 0x00000002,
4800577313eSQi Zhang 	0x00000000, 0x00000000, 0x00000000, 0x00000000,
4810577313eSQi Zhang 	0x00000000, 0x00000000, 0x00000000, 0x00000000,
4820577313eSQi Zhang 	0x00000000, 0x00000000, 0x00000000, 0x00000000,
4830577313eSQi Zhang 	0x00000000, 0x00000000, 0x00000000, 0x00000000,
4840577313eSQi Zhang 	0x00000000, 0x00000000, 0x00000000, 0x00000000,
4850577313eSQi Zhang };
4860577313eSQi Zhang 
4870577313eSQi Zhang /* Packet types for packets with PFCP SESSION header */
4880577313eSQi Zhang static const u32 ice_ptypes_pfcp_session[] = {
4890577313eSQi Zhang 	0x00000000, 0x00000000, 0x00000000, 0x00000000,
4900577313eSQi Zhang 	0x00000000, 0x00000000, 0x00000000, 0x00000000,
4910577313eSQi Zhang 	0x00000000, 0x00000000, 0x00000000, 0x00000005,
4920577313eSQi Zhang 	0x00000000, 0x00000000, 0x00000000, 0x00000000,
4930577313eSQi Zhang 	0x00000000, 0x00000000, 0x00000000, 0x00000000,
4940577313eSQi Zhang 	0x00000000, 0x00000000, 0x00000000, 0x00000000,
4950577313eSQi Zhang 	0x00000000, 0x00000000, 0x00000000, 0x00000000,
4960577313eSQi Zhang 	0x00000000, 0x00000000, 0x00000000, 0x00000000,
4970577313eSQi Zhang };
4980577313eSQi Zhang 
4990577313eSQi Zhang /* Packet types for L2TPv3 */
5000577313eSQi Zhang static const u32 ice_ptypes_l2tpv3[] = {
5010577313eSQi Zhang 	0x00000000, 0x00000000, 0x00000000, 0x00000000,
5020577313eSQi Zhang 	0x00000000, 0x00000000, 0x00000000, 0x00000000,
5030577313eSQi Zhang 	0x00000000, 0x00000000, 0x00000000, 0x00000300,
5040577313eSQi Zhang 	0x00000000, 0x00000000, 0x00000000, 0x00000000,
5050577313eSQi Zhang 	0x00000000, 0x00000000, 0x00000000, 0x00000000,
5060577313eSQi Zhang 	0x00000000, 0x00000000, 0x00000000, 0x00000000,
5070577313eSQi Zhang 	0x00000000, 0x00000000, 0x00000000, 0x00000000,
5080577313eSQi Zhang 	0x00000000, 0x00000000, 0x00000000, 0x00000000,
5090577313eSQi Zhang };
5100577313eSQi Zhang 
5110577313eSQi Zhang /* Packet types for ESP */
5120577313eSQi Zhang static const u32 ice_ptypes_esp[] = {
5130577313eSQi Zhang 	0x00000000, 0x00000000, 0x00000000, 0x00000000,
5140577313eSQi Zhang 	0x00000000, 0x00000003, 0x00000000, 0x00000000,
5150577313eSQi Zhang 	0x00000000, 0x00000000, 0x00000000, 0x00000000,
5160577313eSQi Zhang 	0x00000000, 0x00000000, 0x00000000, 0x00000000,
5170577313eSQi Zhang 	0x00000000, 0x00000000, 0x00000000, 0x00000000,
5180577313eSQi Zhang 	0x00000000, 0x00000000, 0x00000000, 0x00000000,
5190577313eSQi Zhang 	0x00000000, 0x00000000, 0x00000000, 0x00000000,
5200577313eSQi Zhang 	0x00000000, 0x00000000, 0x00000000, 0x00000000,
5210577313eSQi Zhang };
5220577313eSQi Zhang 
5230577313eSQi Zhang /* Packet types for AH */
5240577313eSQi Zhang static const u32 ice_ptypes_ah[] = {
5250577313eSQi Zhang 	0x00000000, 0x00000000, 0x00000000, 0x00000000,
5260577313eSQi Zhang 	0x00000000, 0x0000000C, 0x00000000, 0x00000000,
5270577313eSQi Zhang 	0x00000000, 0x00000000, 0x00000000, 0x00000000,
5280577313eSQi Zhang 	0x00000000, 0x00000000, 0x00000000, 0x00000000,
5290577313eSQi Zhang 	0x00000000, 0x00000000, 0x00000000, 0x00000000,
5300577313eSQi Zhang 	0x00000000, 0x00000000, 0x00000000, 0x00000000,
5310577313eSQi Zhang 	0x00000000, 0x00000000, 0x00000000, 0x00000000,
5320577313eSQi Zhang 	0x00000000, 0x00000000, 0x00000000, 0x00000000,
5330577313eSQi Zhang };
5340577313eSQi Zhang 
5350577313eSQi Zhang /* Packet types for packets with NAT_T ESP header */
5360577313eSQi Zhang static const u32 ice_ptypes_nat_t_esp[] = {
5370577313eSQi Zhang 	0x00000000, 0x00000000, 0x00000000, 0x00000000,
5380577313eSQi Zhang 	0x00000000, 0x00000030, 0x00000000, 0x00000000,
5390577313eSQi Zhang 	0x00000000, 0x00000000, 0x00000000, 0x00000000,
5400577313eSQi Zhang 	0x00000000, 0x00000000, 0x00000000, 0x00000000,
5410577313eSQi Zhang 	0x00000000, 0x00000000, 0x00000000, 0x00000000,
5420577313eSQi Zhang 	0x00000000, 0x00000000, 0x00000000, 0x00000000,
5430577313eSQi Zhang 	0x00000000, 0x00000000, 0x00000000, 0x00000000,
5440577313eSQi Zhang 	0x00000000, 0x00000000, 0x00000000, 0x00000000,
5450577313eSQi Zhang };
5460577313eSQi Zhang 
54731ad4e4eSTony Nguyen /* Manage parameters and info. used during the creation of a flow profile */
54831ad4e4eSTony Nguyen struct ice_flow_prof_params {
54931ad4e4eSTony Nguyen 	enum ice_block blk;
55031ad4e4eSTony Nguyen 	u16 entry_length; /* # of bytes formatted entry will require */
55131ad4e4eSTony Nguyen 	u8 es_cnt;
55231ad4e4eSTony Nguyen 	struct ice_flow_prof *prof;
55331ad4e4eSTony Nguyen 
55431ad4e4eSTony Nguyen 	/* For ACL, the es[0] will have the data of ICE_RX_MDID_PKT_FLAGS_15_0
55531ad4e4eSTony Nguyen 	 * This will give us the direction flags.
55631ad4e4eSTony Nguyen 	 */
55731ad4e4eSTony Nguyen 	struct ice_fv_word es[ICE_MAX_FV_WORDS];
558*cbad5db8SQi Zhang 	/* attributes can be used to add attributes to a particular PTYPE */
559*cbad5db8SQi Zhang 	const struct ice_ptype_attributes *attr;
560*cbad5db8SQi Zhang 	u16 attr_cnt;
561b199dddbSQi Zhang 
562b199dddbSQi Zhang 	u16 mask[ICE_MAX_FV_WORDS];
56331ad4e4eSTony Nguyen 	DECLARE_BITMAP(ptypes, ICE_FLOW_PTYPE_MAX);
56431ad4e4eSTony Nguyen };
56531ad4e4eSTony Nguyen 
5660577313eSQi Zhang #define ICE_FLOW_RSS_HDRS_INNER_MASK \
5670577313eSQi Zhang 	(ICE_FLOW_SEG_HDR_PPPOE | ICE_FLOW_SEG_HDR_GTPC | \
5680577313eSQi Zhang 	ICE_FLOW_SEG_HDR_GTPC_TEID | ICE_FLOW_SEG_HDR_GTPU | \
5690577313eSQi Zhang 	ICE_FLOW_SEG_HDR_PFCP_SESSION | ICE_FLOW_SEG_HDR_L2TPV3 | \
5700577313eSQi Zhang 	ICE_FLOW_SEG_HDR_ESP | ICE_FLOW_SEG_HDR_AH | \
5710577313eSQi Zhang 	ICE_FLOW_SEG_HDR_NAT_T_ESP)
5720577313eSQi Zhang 
5730577313eSQi Zhang #define ICE_FLOW_SEG_HDRS_L2_MASK	\
5740577313eSQi Zhang 	(ICE_FLOW_SEG_HDR_ETH | ICE_FLOW_SEG_HDR_VLAN)
57531ad4e4eSTony Nguyen #define ICE_FLOW_SEG_HDRS_L3_MASK	\
576390bd141SQi Zhang 	(ICE_FLOW_SEG_HDR_IPV4 | ICE_FLOW_SEG_HDR_IPV6 | ICE_FLOW_SEG_HDR_ARP)
57731ad4e4eSTony Nguyen #define ICE_FLOW_SEG_HDRS_L4_MASK	\
578390bd141SQi Zhang 	(ICE_FLOW_SEG_HDR_ICMP | ICE_FLOW_SEG_HDR_TCP | ICE_FLOW_SEG_HDR_UDP | \
579390bd141SQi Zhang 	 ICE_FLOW_SEG_HDR_SCTP)
58031ad4e4eSTony Nguyen 
58131ad4e4eSTony Nguyen /**
58231ad4e4eSTony Nguyen  * ice_flow_val_hdrs - validates packet segments for valid protocol headers
58331ad4e4eSTony Nguyen  * @segs: array of one or more packet segments that describe the flow
58431ad4e4eSTony Nguyen  * @segs_cnt: number of packet segments provided
58531ad4e4eSTony Nguyen  */
58631ad4e4eSTony Nguyen static enum ice_status
58731ad4e4eSTony Nguyen ice_flow_val_hdrs(struct ice_flow_seg_info *segs, u8 segs_cnt)
58831ad4e4eSTony Nguyen {
58931ad4e4eSTony Nguyen 	u8 i;
59031ad4e4eSTony Nguyen 
59131ad4e4eSTony Nguyen 	for (i = 0; i < segs_cnt; i++) {
59231ad4e4eSTony Nguyen 		/* Multiple L3 headers */
59331ad4e4eSTony Nguyen 		if (segs[i].hdrs & ICE_FLOW_SEG_HDRS_L3_MASK &&
59431ad4e4eSTony Nguyen 		    !is_power_of_2(segs[i].hdrs & ICE_FLOW_SEG_HDRS_L3_MASK))
59531ad4e4eSTony Nguyen 			return ICE_ERR_PARAM;
59631ad4e4eSTony Nguyen 
59731ad4e4eSTony Nguyen 		/* Multiple L4 headers */
59831ad4e4eSTony Nguyen 		if (segs[i].hdrs & ICE_FLOW_SEG_HDRS_L4_MASK &&
59931ad4e4eSTony Nguyen 		    !is_power_of_2(segs[i].hdrs & ICE_FLOW_SEG_HDRS_L4_MASK))
60031ad4e4eSTony Nguyen 			return ICE_ERR_PARAM;
60131ad4e4eSTony Nguyen 	}
60231ad4e4eSTony Nguyen 
60331ad4e4eSTony Nguyen 	return 0;
60431ad4e4eSTony Nguyen }
60531ad4e4eSTony Nguyen 
6062c57ffcbSHenry Tieman /* Sizes of fixed known protocol headers without header options */
6072c57ffcbSHenry Tieman #define ICE_FLOW_PROT_HDR_SZ_MAC	14
608390bd141SQi Zhang #define ICE_FLOW_PROT_HDR_SZ_MAC_VLAN	(ICE_FLOW_PROT_HDR_SZ_MAC + 2)
6092c57ffcbSHenry Tieman #define ICE_FLOW_PROT_HDR_SZ_IPV4	20
6102c57ffcbSHenry Tieman #define ICE_FLOW_PROT_HDR_SZ_IPV6	40
611390bd141SQi Zhang #define ICE_FLOW_PROT_HDR_SZ_ARP	28
612390bd141SQi Zhang #define ICE_FLOW_PROT_HDR_SZ_ICMP	8
6132c57ffcbSHenry Tieman #define ICE_FLOW_PROT_HDR_SZ_TCP	20
6142c57ffcbSHenry Tieman #define ICE_FLOW_PROT_HDR_SZ_UDP	8
6152c57ffcbSHenry Tieman #define ICE_FLOW_PROT_HDR_SZ_SCTP	12
6162c57ffcbSHenry Tieman 
6172c57ffcbSHenry Tieman /**
6182c57ffcbSHenry Tieman  * ice_flow_calc_seg_sz - calculates size of a packet segment based on headers
6192c57ffcbSHenry Tieman  * @params: information about the flow to be processed
6202c57ffcbSHenry Tieman  * @seg: index of packet segment whose header size is to be determined
6212c57ffcbSHenry Tieman  */
6222c57ffcbSHenry Tieman static u16 ice_flow_calc_seg_sz(struct ice_flow_prof_params *params, u8 seg)
6232c57ffcbSHenry Tieman {
624390bd141SQi Zhang 	u16 sz;
625390bd141SQi Zhang 
626390bd141SQi Zhang 	/* L2 headers */
627390bd141SQi Zhang 	sz = (params->prof->segs[seg].hdrs & ICE_FLOW_SEG_HDR_VLAN) ?
628390bd141SQi Zhang 		ICE_FLOW_PROT_HDR_SZ_MAC_VLAN : ICE_FLOW_PROT_HDR_SZ_MAC;
6292c57ffcbSHenry Tieman 
6302c57ffcbSHenry Tieman 	/* L3 headers */
6312c57ffcbSHenry Tieman 	if (params->prof->segs[seg].hdrs & ICE_FLOW_SEG_HDR_IPV4)
6322c57ffcbSHenry Tieman 		sz += ICE_FLOW_PROT_HDR_SZ_IPV4;
6332c57ffcbSHenry Tieman 	else if (params->prof->segs[seg].hdrs & ICE_FLOW_SEG_HDR_IPV6)
6342c57ffcbSHenry Tieman 		sz += ICE_FLOW_PROT_HDR_SZ_IPV6;
635390bd141SQi Zhang 	else if (params->prof->segs[seg].hdrs & ICE_FLOW_SEG_HDR_ARP)
636390bd141SQi Zhang 		sz += ICE_FLOW_PROT_HDR_SZ_ARP;
637390bd141SQi Zhang 	else if (params->prof->segs[seg].hdrs & ICE_FLOW_SEG_HDRS_L4_MASK)
638390bd141SQi Zhang 		/* An L3 header is required if L4 is specified */
639390bd141SQi Zhang 		return 0;
6402c57ffcbSHenry Tieman 
6412c57ffcbSHenry Tieman 	/* L4 headers */
642390bd141SQi Zhang 	if (params->prof->segs[seg].hdrs & ICE_FLOW_SEG_HDR_ICMP)
643390bd141SQi Zhang 		sz += ICE_FLOW_PROT_HDR_SZ_ICMP;
644390bd141SQi Zhang 	else if (params->prof->segs[seg].hdrs & ICE_FLOW_SEG_HDR_TCP)
6452c57ffcbSHenry Tieman 		sz += ICE_FLOW_PROT_HDR_SZ_TCP;
6462c57ffcbSHenry Tieman 	else if (params->prof->segs[seg].hdrs & ICE_FLOW_SEG_HDR_UDP)
6472c57ffcbSHenry Tieman 		sz += ICE_FLOW_PROT_HDR_SZ_UDP;
6482c57ffcbSHenry Tieman 	else if (params->prof->segs[seg].hdrs & ICE_FLOW_SEG_HDR_SCTP)
6492c57ffcbSHenry Tieman 		sz += ICE_FLOW_PROT_HDR_SZ_SCTP;
6502c57ffcbSHenry Tieman 
6512c57ffcbSHenry Tieman 	return sz;
6522c57ffcbSHenry Tieman }
6532c57ffcbSHenry Tieman 
65431ad4e4eSTony Nguyen /**
65531ad4e4eSTony Nguyen  * ice_flow_proc_seg_hdrs - process protocol headers present in pkt segments
65631ad4e4eSTony Nguyen  * @params: information about the flow to be processed
65731ad4e4eSTony Nguyen  *
65831ad4e4eSTony Nguyen  * This function identifies the packet types associated with the protocol
65931ad4e4eSTony Nguyen  * headers being present in packet segments of the specified flow profile.
66031ad4e4eSTony Nguyen  */
66131ad4e4eSTony Nguyen static enum ice_status
66231ad4e4eSTony Nguyen ice_flow_proc_seg_hdrs(struct ice_flow_prof_params *params)
66331ad4e4eSTony Nguyen {
66431ad4e4eSTony Nguyen 	struct ice_flow_prof *prof;
66531ad4e4eSTony Nguyen 	u8 i;
66631ad4e4eSTony Nguyen 
66731ad4e4eSTony Nguyen 	memset(params->ptypes, 0xff, sizeof(params->ptypes));
66831ad4e4eSTony Nguyen 
66931ad4e4eSTony Nguyen 	prof = params->prof;
67031ad4e4eSTony Nguyen 
67131ad4e4eSTony Nguyen 	for (i = 0; i < params->prof->segs_cnt; i++) {
67231ad4e4eSTony Nguyen 		const unsigned long *src;
67331ad4e4eSTony Nguyen 		u32 hdrs;
67431ad4e4eSTony Nguyen 
67531ad4e4eSTony Nguyen 		hdrs = prof->segs[i].hdrs;
67631ad4e4eSTony Nguyen 
677390bd141SQi Zhang 		if (hdrs & ICE_FLOW_SEG_HDR_ETH) {
678390bd141SQi Zhang 			src = !i ? (const unsigned long *)ice_ptypes_mac_ofos :
679390bd141SQi Zhang 				(const unsigned long *)ice_ptypes_mac_il;
680390bd141SQi Zhang 			bitmap_and(params->ptypes, params->ptypes, src,
681390bd141SQi Zhang 				   ICE_FLOW_PTYPE_MAX);
682390bd141SQi Zhang 		}
683390bd141SQi Zhang 
684390bd141SQi Zhang 		if (i && hdrs & ICE_FLOW_SEG_HDR_VLAN) {
685390bd141SQi Zhang 			src = (const unsigned long *)ice_ptypes_macvlan_il;
686390bd141SQi Zhang 			bitmap_and(params->ptypes, params->ptypes, src,
687390bd141SQi Zhang 				   ICE_FLOW_PTYPE_MAX);
688390bd141SQi Zhang 		}
689390bd141SQi Zhang 
690390bd141SQi Zhang 		if (!i && hdrs & ICE_FLOW_SEG_HDR_ARP) {
691390bd141SQi Zhang 			bitmap_and(params->ptypes, params->ptypes,
692390bd141SQi Zhang 				   (const unsigned long *)ice_ptypes_arp_of,
693390bd141SQi Zhang 				   ICE_FLOW_PTYPE_MAX);
694390bd141SQi Zhang 		}
695051d2b5cSDan Nowlin 		if ((hdrs & ICE_FLOW_SEG_HDR_IPV4) &&
696051d2b5cSDan Nowlin 		    !(hdrs & ICE_FLOW_SEG_HDRS_L4_MASK)) {
697051d2b5cSDan Nowlin 			src = !i ? (const unsigned long *)ice_ipv4_ofos_no_l4 :
698051d2b5cSDan Nowlin 				(const unsigned long *)ice_ipv4_il_no_l4;
699051d2b5cSDan Nowlin 			bitmap_and(params->ptypes, params->ptypes, src,
700051d2b5cSDan Nowlin 				   ICE_FLOW_PTYPE_MAX);
701051d2b5cSDan Nowlin 		} else if (hdrs & ICE_FLOW_SEG_HDR_IPV4) {
70231ad4e4eSTony Nguyen 			src = !i ? (const unsigned long *)ice_ptypes_ipv4_ofos :
70331ad4e4eSTony Nguyen 				(const unsigned long *)ice_ptypes_ipv4_il;
70431ad4e4eSTony Nguyen 			bitmap_and(params->ptypes, params->ptypes, src,
70531ad4e4eSTony Nguyen 				   ICE_FLOW_PTYPE_MAX);
706051d2b5cSDan Nowlin 		} else if ((hdrs & ICE_FLOW_SEG_HDR_IPV6) &&
707051d2b5cSDan Nowlin 			   !(hdrs & ICE_FLOW_SEG_HDRS_L4_MASK)) {
708051d2b5cSDan Nowlin 			src = !i ? (const unsigned long *)ice_ipv6_ofos_no_l4 :
709051d2b5cSDan Nowlin 				(const unsigned long *)ice_ipv6_il_no_l4;
710051d2b5cSDan Nowlin 			bitmap_and(params->ptypes, params->ptypes, src,
711051d2b5cSDan Nowlin 				   ICE_FLOW_PTYPE_MAX);
71231ad4e4eSTony Nguyen 		} else if (hdrs & ICE_FLOW_SEG_HDR_IPV6) {
71331ad4e4eSTony Nguyen 			src = !i ? (const unsigned long *)ice_ptypes_ipv6_ofos :
71431ad4e4eSTony Nguyen 				(const unsigned long *)ice_ptypes_ipv6_il;
71531ad4e4eSTony Nguyen 			bitmap_and(params->ptypes, params->ptypes, src,
71631ad4e4eSTony Nguyen 				   ICE_FLOW_PTYPE_MAX);
71731ad4e4eSTony Nguyen 		}
71831ad4e4eSTony Nguyen 
7190577313eSQi Zhang 		if (hdrs & ICE_FLOW_SEG_HDR_PPPOE) {
7200577313eSQi Zhang 			src = (const unsigned long *)ice_ptypes_pppoe;
7210577313eSQi Zhang 			bitmap_and(params->ptypes, params->ptypes, src,
7220577313eSQi Zhang 				   ICE_FLOW_PTYPE_MAX);
7230577313eSQi Zhang 		} else {
7240577313eSQi Zhang 			src = (const unsigned long *)ice_ptypes_pppoe;
7250577313eSQi Zhang 			bitmap_andnot(params->ptypes, params->ptypes, src,
7260577313eSQi Zhang 				      ICE_FLOW_PTYPE_MAX);
7270577313eSQi Zhang 		}
7280577313eSQi Zhang 
72931ad4e4eSTony Nguyen 		if (hdrs & ICE_FLOW_SEG_HDR_UDP) {
73031ad4e4eSTony Nguyen 			src = (const unsigned long *)ice_ptypes_udp_il;
73131ad4e4eSTony Nguyen 			bitmap_and(params->ptypes, params->ptypes, src,
73231ad4e4eSTony Nguyen 				   ICE_FLOW_PTYPE_MAX);
73331ad4e4eSTony Nguyen 		} else if (hdrs & ICE_FLOW_SEG_HDR_TCP) {
73431ad4e4eSTony Nguyen 			bitmap_and(params->ptypes, params->ptypes,
73531ad4e4eSTony Nguyen 				   (const unsigned long *)ice_ptypes_tcp_il,
73631ad4e4eSTony Nguyen 				   ICE_FLOW_PTYPE_MAX);
73731ad4e4eSTony Nguyen 		} else if (hdrs & ICE_FLOW_SEG_HDR_SCTP) {
73831ad4e4eSTony Nguyen 			src = (const unsigned long *)ice_ptypes_sctp_il;
73931ad4e4eSTony Nguyen 			bitmap_and(params->ptypes, params->ptypes, src,
74031ad4e4eSTony Nguyen 				   ICE_FLOW_PTYPE_MAX);
741390bd141SQi Zhang 		}
742390bd141SQi Zhang 
743390bd141SQi Zhang 		if (hdrs & ICE_FLOW_SEG_HDR_ICMP) {
744390bd141SQi Zhang 			src = !i ? (const unsigned long *)ice_ptypes_icmp_of :
745390bd141SQi Zhang 				(const unsigned long *)ice_ptypes_icmp_il;
746390bd141SQi Zhang 			bitmap_and(params->ptypes, params->ptypes, src,
747390bd141SQi Zhang 				   ICE_FLOW_PTYPE_MAX);
748a4e82a81STony Nguyen 		} else if (hdrs & ICE_FLOW_SEG_HDR_GRE) {
749a4e82a81STony Nguyen 			if (!i) {
750a4e82a81STony Nguyen 				src = (const unsigned long *)ice_ptypes_gre_of;
751a4e82a81STony Nguyen 				bitmap_and(params->ptypes, params->ptypes,
752a4e82a81STony Nguyen 					   src, ICE_FLOW_PTYPE_MAX);
753a4e82a81STony Nguyen 			}
7540577313eSQi Zhang 		} else if (hdrs & ICE_FLOW_SEG_HDR_GTPC) {
7550577313eSQi Zhang 			src = (const unsigned long *)ice_ptypes_gtpc;
7560577313eSQi Zhang 			bitmap_and(params->ptypes, params->ptypes, src,
7570577313eSQi Zhang 				   ICE_FLOW_PTYPE_MAX);
7580577313eSQi Zhang 		} else if (hdrs & ICE_FLOW_SEG_HDR_GTPC_TEID) {
7590577313eSQi Zhang 			src = (const unsigned long *)ice_ptypes_gtpc_tid;
7600577313eSQi Zhang 			bitmap_and(params->ptypes, params->ptypes, src,
7610577313eSQi Zhang 				   ICE_FLOW_PTYPE_MAX);
7620577313eSQi Zhang 		} else if (hdrs & ICE_FLOW_SEG_HDR_GTPU_DWN) {
7630577313eSQi Zhang 			src = (const unsigned long *)ice_ptypes_gtpu;
7640577313eSQi Zhang 			bitmap_and(params->ptypes, params->ptypes, src,
7650577313eSQi Zhang 				   ICE_FLOW_PTYPE_MAX);
766*cbad5db8SQi Zhang 
767*cbad5db8SQi Zhang 			/* Attributes for GTP packet with downlink */
768*cbad5db8SQi Zhang 			params->attr = ice_attr_gtpu_down;
769*cbad5db8SQi Zhang 			params->attr_cnt = ARRAY_SIZE(ice_attr_gtpu_down);
7700577313eSQi Zhang 		} else if (hdrs & ICE_FLOW_SEG_HDR_GTPU_UP) {
7710577313eSQi Zhang 			src = (const unsigned long *)ice_ptypes_gtpu;
7720577313eSQi Zhang 			bitmap_and(params->ptypes, params->ptypes, src,
7730577313eSQi Zhang 				   ICE_FLOW_PTYPE_MAX);
774*cbad5db8SQi Zhang 
775*cbad5db8SQi Zhang 			/* Attributes for GTP packet with uplink */
776*cbad5db8SQi Zhang 			params->attr = ice_attr_gtpu_up;
777*cbad5db8SQi Zhang 			params->attr_cnt = ARRAY_SIZE(ice_attr_gtpu_up);
7780577313eSQi Zhang 		} else if (hdrs & ICE_FLOW_SEG_HDR_GTPU_EH) {
7790577313eSQi Zhang 			src = (const unsigned long *)ice_ptypes_gtpu;
7800577313eSQi Zhang 			bitmap_and(params->ptypes, params->ptypes, src,
7810577313eSQi Zhang 				   ICE_FLOW_PTYPE_MAX);
782*cbad5db8SQi Zhang 
783*cbad5db8SQi Zhang 			/* Attributes for GTP packet with Extension Header */
784*cbad5db8SQi Zhang 			params->attr = ice_attr_gtpu_eh;
785*cbad5db8SQi Zhang 			params->attr_cnt = ARRAY_SIZE(ice_attr_gtpu_eh);
7860577313eSQi Zhang 		} else if (hdrs & ICE_FLOW_SEG_HDR_GTPU_IP) {
7870577313eSQi Zhang 			src = (const unsigned long *)ice_ptypes_gtpu;
7880577313eSQi Zhang 			bitmap_and(params->ptypes, params->ptypes, src,
7890577313eSQi Zhang 				   ICE_FLOW_PTYPE_MAX);
7900577313eSQi Zhang 		} else if (hdrs & ICE_FLOW_SEG_HDR_L2TPV3) {
7910577313eSQi Zhang 			src = (const unsigned long *)ice_ptypes_l2tpv3;
7920577313eSQi Zhang 			bitmap_and(params->ptypes, params->ptypes, src,
7930577313eSQi Zhang 				   ICE_FLOW_PTYPE_MAX);
7940577313eSQi Zhang 		} else if (hdrs & ICE_FLOW_SEG_HDR_ESP) {
7950577313eSQi Zhang 			src = (const unsigned long *)ice_ptypes_esp;
7960577313eSQi Zhang 			bitmap_and(params->ptypes, params->ptypes, src,
7970577313eSQi Zhang 				   ICE_FLOW_PTYPE_MAX);
7980577313eSQi Zhang 		} else if (hdrs & ICE_FLOW_SEG_HDR_AH) {
7990577313eSQi Zhang 			src = (const unsigned long *)ice_ptypes_ah;
8000577313eSQi Zhang 			bitmap_and(params->ptypes, params->ptypes, src,
8010577313eSQi Zhang 				   ICE_FLOW_PTYPE_MAX);
8020577313eSQi Zhang 		} else if (hdrs & ICE_FLOW_SEG_HDR_NAT_T_ESP) {
8030577313eSQi Zhang 			src = (const unsigned long *)ice_ptypes_nat_t_esp;
8040577313eSQi Zhang 			bitmap_and(params->ptypes, params->ptypes, src,
8050577313eSQi Zhang 				   ICE_FLOW_PTYPE_MAX);
8060577313eSQi Zhang 		}
8070577313eSQi Zhang 
8080577313eSQi Zhang 		if (hdrs & ICE_FLOW_SEG_HDR_PFCP) {
8090577313eSQi Zhang 			if (hdrs & ICE_FLOW_SEG_HDR_PFCP_NODE)
8100577313eSQi Zhang 				src = (const unsigned long *)ice_ptypes_pfcp_node;
8110577313eSQi Zhang 			else
8120577313eSQi Zhang 				src = (const unsigned long *)ice_ptypes_pfcp_session;
8130577313eSQi Zhang 
8140577313eSQi Zhang 			bitmap_and(params->ptypes, params->ptypes, src,
8150577313eSQi Zhang 				   ICE_FLOW_PTYPE_MAX);
8160577313eSQi Zhang 		} else {
8170577313eSQi Zhang 			src = (const unsigned long *)ice_ptypes_pfcp_node;
8180577313eSQi Zhang 			bitmap_andnot(params->ptypes, params->ptypes, src,
8190577313eSQi Zhang 				      ICE_FLOW_PTYPE_MAX);
8200577313eSQi Zhang 
8210577313eSQi Zhang 			src = (const unsigned long *)ice_ptypes_pfcp_session;
8220577313eSQi Zhang 			bitmap_andnot(params->ptypes, params->ptypes, src,
8230577313eSQi Zhang 				      ICE_FLOW_PTYPE_MAX);
82431ad4e4eSTony Nguyen 		}
82531ad4e4eSTony Nguyen 	}
82631ad4e4eSTony Nguyen 
82731ad4e4eSTony Nguyen 	return 0;
82831ad4e4eSTony Nguyen }
82931ad4e4eSTony Nguyen 
83031ad4e4eSTony Nguyen /**
83131ad4e4eSTony Nguyen  * ice_flow_xtract_fld - Create an extraction sequence entry for the given field
83231ad4e4eSTony Nguyen  * @hw: pointer to the HW struct
83331ad4e4eSTony Nguyen  * @params: information about the flow to be processed
83431ad4e4eSTony Nguyen  * @seg: packet segment index of the field to be extracted
83531ad4e4eSTony Nguyen  * @fld: ID of field to be extracted
836b199dddbSQi Zhang  * @match: bit field of all fields
83731ad4e4eSTony Nguyen  *
83831ad4e4eSTony Nguyen  * This function determines the protocol ID, offset, and size of the given
83931ad4e4eSTony Nguyen  * field. It then allocates one or more extraction sequence entries for the
84031ad4e4eSTony Nguyen  * given field, and fill the entries with protocol ID and offset information.
84131ad4e4eSTony Nguyen  */
84231ad4e4eSTony Nguyen static enum ice_status
84331ad4e4eSTony Nguyen ice_flow_xtract_fld(struct ice_hw *hw, struct ice_flow_prof_params *params,
844b199dddbSQi Zhang 		    u8 seg, enum ice_flow_field fld, u64 match)
84531ad4e4eSTony Nguyen {
846b199dddbSQi Zhang 	enum ice_flow_field sib = ICE_FLOW_FIELD_IDX_MAX;
84731ad4e4eSTony Nguyen 	enum ice_prot_id prot_id = ICE_PROT_ID_INVAL;
84831ad4e4eSTony Nguyen 	u8 fv_words = hw->blk[params->blk].es.fvw;
84931ad4e4eSTony Nguyen 	struct ice_flow_fld_info *flds;
85031ad4e4eSTony Nguyen 	u16 cnt, ese_bits, i;
851b199dddbSQi Zhang 	u16 sib_mask = 0;
852b199dddbSQi Zhang 	u16 mask;
85331ad4e4eSTony Nguyen 	u16 off;
85431ad4e4eSTony Nguyen 
85531ad4e4eSTony Nguyen 	flds = params->prof->segs[seg].fields;
85631ad4e4eSTony Nguyen 
85731ad4e4eSTony Nguyen 	switch (fld) {
858390bd141SQi Zhang 	case ICE_FLOW_FIELD_IDX_ETH_DA:
859390bd141SQi Zhang 	case ICE_FLOW_FIELD_IDX_ETH_SA:
860390bd141SQi Zhang 	case ICE_FLOW_FIELD_IDX_S_VLAN:
861390bd141SQi Zhang 	case ICE_FLOW_FIELD_IDX_C_VLAN:
862390bd141SQi Zhang 		prot_id = seg == 0 ? ICE_PROT_MAC_OF_OR_S : ICE_PROT_MAC_IL;
863390bd141SQi Zhang 		break;
864390bd141SQi Zhang 	case ICE_FLOW_FIELD_IDX_ETH_TYPE:
865390bd141SQi Zhang 		prot_id = seg == 0 ? ICE_PROT_ETYPE_OL : ICE_PROT_ETYPE_IL;
866390bd141SQi Zhang 		break;
867b199dddbSQi Zhang 	case ICE_FLOW_FIELD_IDX_IPV4_DSCP:
868b199dddbSQi Zhang 		prot_id = seg == 0 ? ICE_PROT_IPV4_OF_OR_S : ICE_PROT_IPV4_IL;
869b199dddbSQi Zhang 		break;
870b199dddbSQi Zhang 	case ICE_FLOW_FIELD_IDX_IPV6_DSCP:
871b199dddbSQi Zhang 		prot_id = seg == 0 ? ICE_PROT_IPV6_OF_OR_S : ICE_PROT_IPV6_IL;
872b199dddbSQi Zhang 		break;
873b199dddbSQi Zhang 	case ICE_FLOW_FIELD_IDX_IPV4_TTL:
874b199dddbSQi Zhang 	case ICE_FLOW_FIELD_IDX_IPV4_PROT:
875b199dddbSQi Zhang 		prot_id = seg == 0 ? ICE_PROT_IPV4_OF_OR_S : ICE_PROT_IPV4_IL;
876b199dddbSQi Zhang 
877b199dddbSQi Zhang 		/* TTL and PROT share the same extraction seq. entry.
878b199dddbSQi Zhang 		 * Each is considered a sibling to the other in terms of sharing
879b199dddbSQi Zhang 		 * the same extraction sequence entry.
880b199dddbSQi Zhang 		 */
881b199dddbSQi Zhang 		if (fld == ICE_FLOW_FIELD_IDX_IPV4_TTL)
882b199dddbSQi Zhang 			sib = ICE_FLOW_FIELD_IDX_IPV4_PROT;
883b199dddbSQi Zhang 		else if (fld == ICE_FLOW_FIELD_IDX_IPV4_PROT)
884b199dddbSQi Zhang 			sib = ICE_FLOW_FIELD_IDX_IPV4_TTL;
885b199dddbSQi Zhang 
886b199dddbSQi Zhang 		/* If the sibling field is also included, that field's
887b199dddbSQi Zhang 		 * mask needs to be included.
888b199dddbSQi Zhang 		 */
889b199dddbSQi Zhang 		if (match & BIT(sib))
890b199dddbSQi Zhang 			sib_mask = ice_flds_info[sib].mask;
891b199dddbSQi Zhang 		break;
892b199dddbSQi Zhang 	case ICE_FLOW_FIELD_IDX_IPV6_TTL:
893b199dddbSQi Zhang 	case ICE_FLOW_FIELD_IDX_IPV6_PROT:
894b199dddbSQi Zhang 		prot_id = seg == 0 ? ICE_PROT_IPV6_OF_OR_S : ICE_PROT_IPV6_IL;
895b199dddbSQi Zhang 
896b199dddbSQi Zhang 		/* TTL and PROT share the same extraction seq. entry.
897b199dddbSQi Zhang 		 * Each is considered a sibling to the other in terms of sharing
898b199dddbSQi Zhang 		 * the same extraction sequence entry.
899b199dddbSQi Zhang 		 */
900b199dddbSQi Zhang 		if (fld == ICE_FLOW_FIELD_IDX_IPV6_TTL)
901b199dddbSQi Zhang 			sib = ICE_FLOW_FIELD_IDX_IPV6_PROT;
902b199dddbSQi Zhang 		else if (fld == ICE_FLOW_FIELD_IDX_IPV6_PROT)
903b199dddbSQi Zhang 			sib = ICE_FLOW_FIELD_IDX_IPV6_TTL;
904b199dddbSQi Zhang 
905b199dddbSQi Zhang 		/* If the sibling field is also included, that field's
906b199dddbSQi Zhang 		 * mask needs to be included.
907b199dddbSQi Zhang 		 */
908b199dddbSQi Zhang 		if (match & BIT(sib))
909b199dddbSQi Zhang 			sib_mask = ice_flds_info[sib].mask;
910b199dddbSQi Zhang 		break;
91131ad4e4eSTony Nguyen 	case ICE_FLOW_FIELD_IDX_IPV4_SA:
91231ad4e4eSTony Nguyen 	case ICE_FLOW_FIELD_IDX_IPV4_DA:
91331ad4e4eSTony Nguyen 		prot_id = seg == 0 ? ICE_PROT_IPV4_OF_OR_S : ICE_PROT_IPV4_IL;
91431ad4e4eSTony Nguyen 		break;
91531ad4e4eSTony Nguyen 	case ICE_FLOW_FIELD_IDX_IPV6_SA:
91631ad4e4eSTony Nguyen 	case ICE_FLOW_FIELD_IDX_IPV6_DA:
91731ad4e4eSTony Nguyen 		prot_id = seg == 0 ? ICE_PROT_IPV6_OF_OR_S : ICE_PROT_IPV6_IL;
91831ad4e4eSTony Nguyen 		break;
91931ad4e4eSTony Nguyen 	case ICE_FLOW_FIELD_IDX_TCP_SRC_PORT:
92031ad4e4eSTony Nguyen 	case ICE_FLOW_FIELD_IDX_TCP_DST_PORT:
921390bd141SQi Zhang 	case ICE_FLOW_FIELD_IDX_TCP_FLAGS:
92231ad4e4eSTony Nguyen 		prot_id = ICE_PROT_TCP_IL;
92331ad4e4eSTony Nguyen 		break;
92431ad4e4eSTony Nguyen 	case ICE_FLOW_FIELD_IDX_UDP_SRC_PORT:
92531ad4e4eSTony Nguyen 	case ICE_FLOW_FIELD_IDX_UDP_DST_PORT:
92631ad4e4eSTony Nguyen 		prot_id = ICE_PROT_UDP_IL_OR_S;
92731ad4e4eSTony Nguyen 		break;
9281c01c8c6SMd Fahad Iqbal Polash 	case ICE_FLOW_FIELD_IDX_SCTP_SRC_PORT:
9291c01c8c6SMd Fahad Iqbal Polash 	case ICE_FLOW_FIELD_IDX_SCTP_DST_PORT:
9301c01c8c6SMd Fahad Iqbal Polash 		prot_id = ICE_PROT_SCTP_IL;
9311c01c8c6SMd Fahad Iqbal Polash 		break;
9320577313eSQi Zhang 	case ICE_FLOW_FIELD_IDX_GTPC_TEID:
9330577313eSQi Zhang 	case ICE_FLOW_FIELD_IDX_GTPU_IP_TEID:
9340577313eSQi Zhang 	case ICE_FLOW_FIELD_IDX_GTPU_UP_TEID:
9350577313eSQi Zhang 	case ICE_FLOW_FIELD_IDX_GTPU_DWN_TEID:
9360577313eSQi Zhang 	case ICE_FLOW_FIELD_IDX_GTPU_EH_TEID:
9370577313eSQi Zhang 	case ICE_FLOW_FIELD_IDX_GTPU_EH_QFI:
9380577313eSQi Zhang 		/* GTP is accessed through UDP OF protocol */
9390577313eSQi Zhang 		prot_id = ICE_PROT_UDP_OF;
9400577313eSQi Zhang 		break;
9410577313eSQi Zhang 	case ICE_FLOW_FIELD_IDX_PPPOE_SESS_ID:
9420577313eSQi Zhang 		prot_id = ICE_PROT_PPPOE;
9430577313eSQi Zhang 		break;
9440577313eSQi Zhang 	case ICE_FLOW_FIELD_IDX_PFCP_SEID:
9450577313eSQi Zhang 		prot_id = ICE_PROT_UDP_IL_OR_S;
9460577313eSQi Zhang 		break;
9470577313eSQi Zhang 	case ICE_FLOW_FIELD_IDX_L2TPV3_SESS_ID:
9480577313eSQi Zhang 		prot_id = ICE_PROT_L2TPV3;
9490577313eSQi Zhang 		break;
9500577313eSQi Zhang 	case ICE_FLOW_FIELD_IDX_ESP_SPI:
9510577313eSQi Zhang 		prot_id = ICE_PROT_ESP_F;
9520577313eSQi Zhang 		break;
9530577313eSQi Zhang 	case ICE_FLOW_FIELD_IDX_AH_SPI:
9540577313eSQi Zhang 		prot_id = ICE_PROT_ESP_2;
9550577313eSQi Zhang 		break;
9560577313eSQi Zhang 	case ICE_FLOW_FIELD_IDX_NAT_T_ESP_SPI:
9570577313eSQi Zhang 		prot_id = ICE_PROT_UDP_IL_OR_S;
9580577313eSQi Zhang 		break;
959390bd141SQi Zhang 	case ICE_FLOW_FIELD_IDX_ARP_SIP:
960390bd141SQi Zhang 	case ICE_FLOW_FIELD_IDX_ARP_DIP:
961390bd141SQi Zhang 	case ICE_FLOW_FIELD_IDX_ARP_SHA:
962390bd141SQi Zhang 	case ICE_FLOW_FIELD_IDX_ARP_DHA:
963390bd141SQi Zhang 	case ICE_FLOW_FIELD_IDX_ARP_OP:
964390bd141SQi Zhang 		prot_id = ICE_PROT_ARP_OF;
965390bd141SQi Zhang 		break;
966390bd141SQi Zhang 	case ICE_FLOW_FIELD_IDX_ICMP_TYPE:
967390bd141SQi Zhang 	case ICE_FLOW_FIELD_IDX_ICMP_CODE:
968390bd141SQi Zhang 		/* ICMP type and code share the same extraction seq. entry */
969390bd141SQi Zhang 		prot_id = (params->prof->segs[seg].hdrs & ICE_FLOW_SEG_HDR_IPV4) ?
970390bd141SQi Zhang 				ICE_PROT_ICMP_IL : ICE_PROT_ICMPV6_IL;
971b199dddbSQi Zhang 		sib = fld == ICE_FLOW_FIELD_IDX_ICMP_TYPE ?
972b199dddbSQi Zhang 			ICE_FLOW_FIELD_IDX_ICMP_CODE :
973b199dddbSQi Zhang 			ICE_FLOW_FIELD_IDX_ICMP_TYPE;
974390bd141SQi Zhang 		break;
975a4e82a81STony Nguyen 	case ICE_FLOW_FIELD_IDX_GRE_KEYID:
976a4e82a81STony Nguyen 		prot_id = ICE_PROT_GRE_OF;
977a4e82a81STony Nguyen 		break;
97831ad4e4eSTony Nguyen 	default:
97931ad4e4eSTony Nguyen 		return ICE_ERR_NOT_IMPL;
98031ad4e4eSTony Nguyen 	}
98131ad4e4eSTony Nguyen 
98231ad4e4eSTony Nguyen 	/* Each extraction sequence entry is a word in size, and extracts a
98331ad4e4eSTony Nguyen 	 * word-aligned offset from a protocol header.
98431ad4e4eSTony Nguyen 	 */
98531ad4e4eSTony Nguyen 	ese_bits = ICE_FLOW_FV_EXTRACT_SZ * BITS_PER_BYTE;
98631ad4e4eSTony Nguyen 
98731ad4e4eSTony Nguyen 	flds[fld].xtrct.prot_id = prot_id;
98831ad4e4eSTony Nguyen 	flds[fld].xtrct.off = (ice_flds_info[fld].off / ese_bits) *
98931ad4e4eSTony Nguyen 		ICE_FLOW_FV_EXTRACT_SZ;
99031ad4e4eSTony Nguyen 	flds[fld].xtrct.disp = (u8)(ice_flds_info[fld].off % ese_bits);
99131ad4e4eSTony Nguyen 	flds[fld].xtrct.idx = params->es_cnt;
992b199dddbSQi Zhang 	flds[fld].xtrct.mask = ice_flds_info[fld].mask;
99331ad4e4eSTony Nguyen 
99431ad4e4eSTony Nguyen 	/* Adjust the next field-entry index after accommodating the number of
99531ad4e4eSTony Nguyen 	 * entries this field consumes
99631ad4e4eSTony Nguyen 	 */
99731ad4e4eSTony Nguyen 	cnt = DIV_ROUND_UP(flds[fld].xtrct.disp + ice_flds_info[fld].size,
99831ad4e4eSTony Nguyen 			   ese_bits);
99931ad4e4eSTony Nguyen 
100031ad4e4eSTony Nguyen 	/* Fill in the extraction sequence entries needed for this field */
100131ad4e4eSTony Nguyen 	off = flds[fld].xtrct.off;
1002b199dddbSQi Zhang 	mask = flds[fld].xtrct.mask;
100331ad4e4eSTony Nguyen 	for (i = 0; i < cnt; i++) {
1004b199dddbSQi Zhang 		/* Only consume an extraction sequence entry if there is no
1005b199dddbSQi Zhang 		 * sibling field associated with this field or the sibling entry
1006b199dddbSQi Zhang 		 * already extracts the word shared with this field.
1007b199dddbSQi Zhang 		 */
1008b199dddbSQi Zhang 		if (sib == ICE_FLOW_FIELD_IDX_MAX ||
1009b199dddbSQi Zhang 		    flds[sib].xtrct.prot_id == ICE_PROT_ID_INVAL ||
1010b199dddbSQi Zhang 		    flds[sib].xtrct.off != off) {
101131ad4e4eSTony Nguyen 			u8 idx;
101231ad4e4eSTony Nguyen 
101331ad4e4eSTony Nguyen 			/* Make sure the number of extraction sequence required
101431ad4e4eSTony Nguyen 			 * does not exceed the block's capability
101531ad4e4eSTony Nguyen 			 */
101631ad4e4eSTony Nguyen 			if (params->es_cnt >= fv_words)
101731ad4e4eSTony Nguyen 				return ICE_ERR_MAX_LIMIT;
101831ad4e4eSTony Nguyen 
101931ad4e4eSTony Nguyen 			/* some blocks require a reversed field vector layout */
102031ad4e4eSTony Nguyen 			if (hw->blk[params->blk].es.reverse)
102131ad4e4eSTony Nguyen 				idx = fv_words - params->es_cnt - 1;
102231ad4e4eSTony Nguyen 			else
102331ad4e4eSTony Nguyen 				idx = params->es_cnt;
102431ad4e4eSTony Nguyen 
102531ad4e4eSTony Nguyen 			params->es[idx].prot_id = prot_id;
102631ad4e4eSTony Nguyen 			params->es[idx].off = off;
1027b199dddbSQi Zhang 			params->mask[idx] = mask | sib_mask;
102831ad4e4eSTony Nguyen 			params->es_cnt++;
1029b199dddbSQi Zhang 		}
103031ad4e4eSTony Nguyen 
103131ad4e4eSTony Nguyen 		off += ICE_FLOW_FV_EXTRACT_SZ;
103231ad4e4eSTony Nguyen 	}
103331ad4e4eSTony Nguyen 
103431ad4e4eSTony Nguyen 	return 0;
103531ad4e4eSTony Nguyen }
103631ad4e4eSTony Nguyen 
103731ad4e4eSTony Nguyen /**
10382c57ffcbSHenry Tieman  * ice_flow_xtract_raws - Create extract sequence entries for raw bytes
10392c57ffcbSHenry Tieman  * @hw: pointer to the HW struct
10402c57ffcbSHenry Tieman  * @params: information about the flow to be processed
1041ac382a09SBruce Allan  * @seg: index of packet segment whose raw fields are to be extracted
10422c57ffcbSHenry Tieman  */
10432c57ffcbSHenry Tieman static enum ice_status
10442c57ffcbSHenry Tieman ice_flow_xtract_raws(struct ice_hw *hw, struct ice_flow_prof_params *params,
10452c57ffcbSHenry Tieman 		     u8 seg)
10462c57ffcbSHenry Tieman {
10472c57ffcbSHenry Tieman 	u16 fv_words;
10482c57ffcbSHenry Tieman 	u16 hdrs_sz;
10492c57ffcbSHenry Tieman 	u8 i;
10502c57ffcbSHenry Tieman 
10512c57ffcbSHenry Tieman 	if (!params->prof->segs[seg].raws_cnt)
10522c57ffcbSHenry Tieman 		return 0;
10532c57ffcbSHenry Tieman 
10542c57ffcbSHenry Tieman 	if (params->prof->segs[seg].raws_cnt >
10552c57ffcbSHenry Tieman 	    ARRAY_SIZE(params->prof->segs[seg].raws))
10562c57ffcbSHenry Tieman 		return ICE_ERR_MAX_LIMIT;
10572c57ffcbSHenry Tieman 
10582c57ffcbSHenry Tieman 	/* Offsets within the segment headers are not supported */
10592c57ffcbSHenry Tieman 	hdrs_sz = ice_flow_calc_seg_sz(params, seg);
10602c57ffcbSHenry Tieman 	if (!hdrs_sz)
10612c57ffcbSHenry Tieman 		return ICE_ERR_PARAM;
10622c57ffcbSHenry Tieman 
10632c57ffcbSHenry Tieman 	fv_words = hw->blk[params->blk].es.fvw;
10642c57ffcbSHenry Tieman 
10652c57ffcbSHenry Tieman 	for (i = 0; i < params->prof->segs[seg].raws_cnt; i++) {
10662c57ffcbSHenry Tieman 		struct ice_flow_seg_fld_raw *raw;
10672c57ffcbSHenry Tieman 		u16 off, cnt, j;
10682c57ffcbSHenry Tieman 
10692c57ffcbSHenry Tieman 		raw = &params->prof->segs[seg].raws[i];
10702c57ffcbSHenry Tieman 
10712c57ffcbSHenry Tieman 		/* Storing extraction information */
10722c57ffcbSHenry Tieman 		raw->info.xtrct.prot_id = ICE_PROT_MAC_OF_OR_S;
10732c57ffcbSHenry Tieman 		raw->info.xtrct.off = (raw->off / ICE_FLOW_FV_EXTRACT_SZ) *
10742c57ffcbSHenry Tieman 			ICE_FLOW_FV_EXTRACT_SZ;
10752c57ffcbSHenry Tieman 		raw->info.xtrct.disp = (raw->off % ICE_FLOW_FV_EXTRACT_SZ) *
10762c57ffcbSHenry Tieman 			BITS_PER_BYTE;
10772c57ffcbSHenry Tieman 		raw->info.xtrct.idx = params->es_cnt;
10782c57ffcbSHenry Tieman 
10792c57ffcbSHenry Tieman 		/* Determine the number of field vector entries this raw field
10802c57ffcbSHenry Tieman 		 * consumes.
10812c57ffcbSHenry Tieman 		 */
10822c57ffcbSHenry Tieman 		cnt = DIV_ROUND_UP(raw->info.xtrct.disp +
10832c57ffcbSHenry Tieman 				   (raw->info.src.last * BITS_PER_BYTE),
10842c57ffcbSHenry Tieman 				   (ICE_FLOW_FV_EXTRACT_SZ * BITS_PER_BYTE));
10852c57ffcbSHenry Tieman 		off = raw->info.xtrct.off;
10862c57ffcbSHenry Tieman 		for (j = 0; j < cnt; j++) {
10872c57ffcbSHenry Tieman 			u16 idx;
10882c57ffcbSHenry Tieman 
10892c57ffcbSHenry Tieman 			/* Make sure the number of extraction sequence required
10902c57ffcbSHenry Tieman 			 * does not exceed the block's capability
10912c57ffcbSHenry Tieman 			 */
10922c57ffcbSHenry Tieman 			if (params->es_cnt >= hw->blk[params->blk].es.count ||
10932c57ffcbSHenry Tieman 			    params->es_cnt >= ICE_MAX_FV_WORDS)
10942c57ffcbSHenry Tieman 				return ICE_ERR_MAX_LIMIT;
10952c57ffcbSHenry Tieman 
10962c57ffcbSHenry Tieman 			/* some blocks require a reversed field vector layout */
10972c57ffcbSHenry Tieman 			if (hw->blk[params->blk].es.reverse)
10982c57ffcbSHenry Tieman 				idx = fv_words - params->es_cnt - 1;
10992c57ffcbSHenry Tieman 			else
11002c57ffcbSHenry Tieman 				idx = params->es_cnt;
11012c57ffcbSHenry Tieman 
11022c57ffcbSHenry Tieman 			params->es[idx].prot_id = raw->info.xtrct.prot_id;
11032c57ffcbSHenry Tieman 			params->es[idx].off = off;
11042c57ffcbSHenry Tieman 			params->es_cnt++;
11052c57ffcbSHenry Tieman 			off += ICE_FLOW_FV_EXTRACT_SZ;
11062c57ffcbSHenry Tieman 		}
11072c57ffcbSHenry Tieman 	}
11082c57ffcbSHenry Tieman 
11092c57ffcbSHenry Tieman 	return 0;
11102c57ffcbSHenry Tieman }
11112c57ffcbSHenry Tieman 
11122c57ffcbSHenry Tieman /**
111331ad4e4eSTony Nguyen  * ice_flow_create_xtrct_seq - Create an extraction sequence for given segments
111431ad4e4eSTony Nguyen  * @hw: pointer to the HW struct
111531ad4e4eSTony Nguyen  * @params: information about the flow to be processed
111631ad4e4eSTony Nguyen  *
111731ad4e4eSTony Nguyen  * This function iterates through all matched fields in the given segments, and
111831ad4e4eSTony Nguyen  * creates an extraction sequence for the fields.
111931ad4e4eSTony Nguyen  */
112031ad4e4eSTony Nguyen static enum ice_status
112131ad4e4eSTony Nguyen ice_flow_create_xtrct_seq(struct ice_hw *hw,
112231ad4e4eSTony Nguyen 			  struct ice_flow_prof_params *params)
112331ad4e4eSTony Nguyen {
112431ad4e4eSTony Nguyen 	struct ice_flow_prof *prof = params->prof;
112531ad4e4eSTony Nguyen 	enum ice_status status = 0;
112631ad4e4eSTony Nguyen 	u8 i;
112731ad4e4eSTony Nguyen 
112831ad4e4eSTony Nguyen 	for (i = 0; i < prof->segs_cnt; i++) {
1129b199dddbSQi Zhang 		u64 match = params->prof->segs[i].match;
1130b199dddbSQi Zhang 		enum ice_flow_field j;
113131ad4e4eSTony Nguyen 
1132b199dddbSQi Zhang 		for_each_set_bit(j, (unsigned long *)&match,
113331ad4e4eSTony Nguyen 				 ICE_FLOW_FIELD_IDX_MAX) {
1134b199dddbSQi Zhang 			status = ice_flow_xtract_fld(hw, params, i, j, match);
113531ad4e4eSTony Nguyen 			if (status)
113631ad4e4eSTony Nguyen 				return status;
1137b199dddbSQi Zhang 			clear_bit(j, (unsigned long *)&match);
113831ad4e4eSTony Nguyen 		}
11392c57ffcbSHenry Tieman 
11402c57ffcbSHenry Tieman 		/* Process raw matching bytes */
11412c57ffcbSHenry Tieman 		status = ice_flow_xtract_raws(hw, params, i);
11422c57ffcbSHenry Tieman 		if (status)
11432c57ffcbSHenry Tieman 			return status;
114431ad4e4eSTony Nguyen 	}
114531ad4e4eSTony Nguyen 
114631ad4e4eSTony Nguyen 	return status;
114731ad4e4eSTony Nguyen }
114831ad4e4eSTony Nguyen 
114931ad4e4eSTony Nguyen /**
115031ad4e4eSTony Nguyen  * ice_flow_proc_segs - process all packet segments associated with a profile
115131ad4e4eSTony Nguyen  * @hw: pointer to the HW struct
115231ad4e4eSTony Nguyen  * @params: information about the flow to be processed
115331ad4e4eSTony Nguyen  */
115431ad4e4eSTony Nguyen static enum ice_status
115531ad4e4eSTony Nguyen ice_flow_proc_segs(struct ice_hw *hw, struct ice_flow_prof_params *params)
115631ad4e4eSTony Nguyen {
115731ad4e4eSTony Nguyen 	enum ice_status status;
115831ad4e4eSTony Nguyen 
115931ad4e4eSTony Nguyen 	status = ice_flow_proc_seg_hdrs(params);
116031ad4e4eSTony Nguyen 	if (status)
116131ad4e4eSTony Nguyen 		return status;
116231ad4e4eSTony Nguyen 
116331ad4e4eSTony Nguyen 	status = ice_flow_create_xtrct_seq(hw, params);
116431ad4e4eSTony Nguyen 	if (status)
116531ad4e4eSTony Nguyen 		return status;
116631ad4e4eSTony Nguyen 
116731ad4e4eSTony Nguyen 	switch (params->blk) {
1168148beb61SHenry Tieman 	case ICE_BLK_FD:
116931ad4e4eSTony Nguyen 	case ICE_BLK_RSS:
117031ad4e4eSTony Nguyen 		status = 0;
117131ad4e4eSTony Nguyen 		break;
117231ad4e4eSTony Nguyen 	default:
117331ad4e4eSTony Nguyen 		return ICE_ERR_NOT_IMPL;
117431ad4e4eSTony Nguyen 	}
117531ad4e4eSTony Nguyen 
117631ad4e4eSTony Nguyen 	return status;
117731ad4e4eSTony Nguyen }
117831ad4e4eSTony Nguyen 
11792c61054cSTony Nguyen #define ICE_FLOW_FIND_PROF_CHK_FLDS	0x00000001
11802c61054cSTony Nguyen #define ICE_FLOW_FIND_PROF_CHK_VSI	0x00000002
11812c61054cSTony Nguyen #define ICE_FLOW_FIND_PROF_NOT_CHK_DIR	0x00000004
11822c61054cSTony Nguyen 
11832c61054cSTony Nguyen /**
11842c61054cSTony Nguyen  * ice_flow_find_prof_conds - Find a profile matching headers and conditions
11852c61054cSTony Nguyen  * @hw: pointer to the HW struct
11862c61054cSTony Nguyen  * @blk: classification stage
11872c61054cSTony Nguyen  * @dir: flow direction
11882c61054cSTony Nguyen  * @segs: array of one or more packet segments that describe the flow
11892c61054cSTony Nguyen  * @segs_cnt: number of packet segments provided
11902c61054cSTony Nguyen  * @vsi_handle: software VSI handle to check VSI (ICE_FLOW_FIND_PROF_CHK_VSI)
11912c61054cSTony Nguyen  * @conds: additional conditions to be checked (ICE_FLOW_FIND_PROF_CHK_*)
11922c61054cSTony Nguyen  */
11932c61054cSTony Nguyen static struct ice_flow_prof *
11942c61054cSTony Nguyen ice_flow_find_prof_conds(struct ice_hw *hw, enum ice_block blk,
11952c61054cSTony Nguyen 			 enum ice_flow_dir dir, struct ice_flow_seg_info *segs,
11962c61054cSTony Nguyen 			 u8 segs_cnt, u16 vsi_handle, u32 conds)
11972c61054cSTony Nguyen {
11982c61054cSTony Nguyen 	struct ice_flow_prof *p, *prof = NULL;
11992c61054cSTony Nguyen 
12002c61054cSTony Nguyen 	mutex_lock(&hw->fl_profs_locks[blk]);
12012c61054cSTony Nguyen 	list_for_each_entry(p, &hw->fl_profs[blk], l_entry)
12022c61054cSTony Nguyen 		if ((p->dir == dir || conds & ICE_FLOW_FIND_PROF_NOT_CHK_DIR) &&
12032c61054cSTony Nguyen 		    segs_cnt && segs_cnt == p->segs_cnt) {
12042c61054cSTony Nguyen 			u8 i;
12052c61054cSTony Nguyen 
12062c61054cSTony Nguyen 			/* Check for profile-VSI association if specified */
12072c61054cSTony Nguyen 			if ((conds & ICE_FLOW_FIND_PROF_CHK_VSI) &&
12082c61054cSTony Nguyen 			    ice_is_vsi_valid(hw, vsi_handle) &&
12092c61054cSTony Nguyen 			    !test_bit(vsi_handle, p->vsis))
12102c61054cSTony Nguyen 				continue;
12112c61054cSTony Nguyen 
12122c61054cSTony Nguyen 			/* Protocol headers must be checked. Matched fields are
12132c61054cSTony Nguyen 			 * checked if specified.
12142c61054cSTony Nguyen 			 */
12152c61054cSTony Nguyen 			for (i = 0; i < segs_cnt; i++)
12162c61054cSTony Nguyen 				if (segs[i].hdrs != p->segs[i].hdrs ||
12172c61054cSTony Nguyen 				    ((conds & ICE_FLOW_FIND_PROF_CHK_FLDS) &&
12182c61054cSTony Nguyen 				     segs[i].match != p->segs[i].match))
12192c61054cSTony Nguyen 					break;
12202c61054cSTony Nguyen 
12212c61054cSTony Nguyen 			/* A match is found if all segments are matched */
12222c61054cSTony Nguyen 			if (i == segs_cnt) {
12232c61054cSTony Nguyen 				prof = p;
12242c61054cSTony Nguyen 				break;
12252c61054cSTony Nguyen 			}
12262c61054cSTony Nguyen 		}
12272c61054cSTony Nguyen 	mutex_unlock(&hw->fl_profs_locks[blk]);
12282c61054cSTony Nguyen 
12292c61054cSTony Nguyen 	return prof;
12302c61054cSTony Nguyen }
12312c61054cSTony Nguyen 
12322c61054cSTony Nguyen /**
12332c61054cSTony Nguyen  * ice_flow_find_prof_id - Look up a profile with given profile ID
12342c61054cSTony Nguyen  * @hw: pointer to the HW struct
12352c61054cSTony Nguyen  * @blk: classification stage
12362c61054cSTony Nguyen  * @prof_id: unique ID to identify this flow profile
12372c61054cSTony Nguyen  */
12382c61054cSTony Nguyen static struct ice_flow_prof *
12392c61054cSTony Nguyen ice_flow_find_prof_id(struct ice_hw *hw, enum ice_block blk, u64 prof_id)
12402c61054cSTony Nguyen {
12412c61054cSTony Nguyen 	struct ice_flow_prof *p;
12422c61054cSTony Nguyen 
12432c61054cSTony Nguyen 	list_for_each_entry(p, &hw->fl_profs[blk], l_entry)
12442c61054cSTony Nguyen 		if (p->id == prof_id)
12452c61054cSTony Nguyen 			return p;
12462c61054cSTony Nguyen 
12472c61054cSTony Nguyen 	return NULL;
12482c61054cSTony Nguyen }
12492c61054cSTony Nguyen 
125031ad4e4eSTony Nguyen /**
1251148beb61SHenry Tieman  * ice_dealloc_flow_entry - Deallocate flow entry memory
1252148beb61SHenry Tieman  * @hw: pointer to the HW struct
1253148beb61SHenry Tieman  * @entry: flow entry to be removed
1254148beb61SHenry Tieman  */
1255148beb61SHenry Tieman static void
1256148beb61SHenry Tieman ice_dealloc_flow_entry(struct ice_hw *hw, struct ice_flow_entry *entry)
1257148beb61SHenry Tieman {
1258148beb61SHenry Tieman 	if (!entry)
1259148beb61SHenry Tieman 		return;
1260148beb61SHenry Tieman 
1261148beb61SHenry Tieman 	if (entry->entry)
1262148beb61SHenry Tieman 		devm_kfree(ice_hw_to_dev(hw), entry->entry);
1263148beb61SHenry Tieman 
1264148beb61SHenry Tieman 	devm_kfree(ice_hw_to_dev(hw), entry);
1265148beb61SHenry Tieman }
1266148beb61SHenry Tieman 
1267148beb61SHenry Tieman /**
1268148beb61SHenry Tieman  * ice_flow_rem_entry_sync - Remove a flow entry
1269148beb61SHenry Tieman  * @hw: pointer to the HW struct
1270148beb61SHenry Tieman  * @blk: classification stage
1271148beb61SHenry Tieman  * @entry: flow entry to be removed
1272148beb61SHenry Tieman  */
1273148beb61SHenry Tieman static enum ice_status
1274148beb61SHenry Tieman ice_flow_rem_entry_sync(struct ice_hw *hw, enum ice_block __always_unused blk,
1275148beb61SHenry Tieman 			struct ice_flow_entry *entry)
1276148beb61SHenry Tieman {
1277148beb61SHenry Tieman 	if (!entry)
1278148beb61SHenry Tieman 		return ICE_ERR_BAD_PTR;
1279148beb61SHenry Tieman 
1280148beb61SHenry Tieman 	list_del(&entry->l_entry);
1281148beb61SHenry Tieman 
1282148beb61SHenry Tieman 	ice_dealloc_flow_entry(hw, entry);
1283148beb61SHenry Tieman 
1284148beb61SHenry Tieman 	return 0;
1285148beb61SHenry Tieman }
1286148beb61SHenry Tieman 
1287148beb61SHenry Tieman /**
128831ad4e4eSTony Nguyen  * ice_flow_add_prof_sync - Add a flow profile for packet segments and fields
128931ad4e4eSTony Nguyen  * @hw: pointer to the HW struct
129031ad4e4eSTony Nguyen  * @blk: classification stage
129131ad4e4eSTony Nguyen  * @dir: flow direction
129231ad4e4eSTony Nguyen  * @prof_id: unique ID to identify this flow profile
129331ad4e4eSTony Nguyen  * @segs: array of one or more packet segments that describe the flow
129431ad4e4eSTony Nguyen  * @segs_cnt: number of packet segments provided
129531ad4e4eSTony Nguyen  * @prof: stores the returned flow profile added
129631ad4e4eSTony Nguyen  *
129731ad4e4eSTony Nguyen  * Assumption: the caller has acquired the lock to the profile list
129831ad4e4eSTony Nguyen  */
129931ad4e4eSTony Nguyen static enum ice_status
130031ad4e4eSTony Nguyen ice_flow_add_prof_sync(struct ice_hw *hw, enum ice_block blk,
130131ad4e4eSTony Nguyen 		       enum ice_flow_dir dir, u64 prof_id,
130231ad4e4eSTony Nguyen 		       struct ice_flow_seg_info *segs, u8 segs_cnt,
130331ad4e4eSTony Nguyen 		       struct ice_flow_prof **prof)
130431ad4e4eSTony Nguyen {
130588dcfdb4SBruce Allan 	struct ice_flow_prof_params *params;
130631ad4e4eSTony Nguyen 	enum ice_status status;
130731ad4e4eSTony Nguyen 	u8 i;
130831ad4e4eSTony Nguyen 
130931ad4e4eSTony Nguyen 	if (!prof)
131031ad4e4eSTony Nguyen 		return ICE_ERR_BAD_PTR;
131131ad4e4eSTony Nguyen 
131288dcfdb4SBruce Allan 	params = kzalloc(sizeof(*params), GFP_KERNEL);
131388dcfdb4SBruce Allan 	if (!params)
131431ad4e4eSTony Nguyen 		return ICE_ERR_NO_MEMORY;
131531ad4e4eSTony Nguyen 
131688dcfdb4SBruce Allan 	params->prof = devm_kzalloc(ice_hw_to_dev(hw), sizeof(*params->prof),
131788dcfdb4SBruce Allan 				    GFP_KERNEL);
131888dcfdb4SBruce Allan 	if (!params->prof) {
131988dcfdb4SBruce Allan 		status = ICE_ERR_NO_MEMORY;
132088dcfdb4SBruce Allan 		goto free_params;
132188dcfdb4SBruce Allan 	}
132288dcfdb4SBruce Allan 
132331ad4e4eSTony Nguyen 	/* initialize extraction sequence to all invalid (0xff) */
132431ad4e4eSTony Nguyen 	for (i = 0; i < ICE_MAX_FV_WORDS; i++) {
132588dcfdb4SBruce Allan 		params->es[i].prot_id = ICE_PROT_INVALID;
132688dcfdb4SBruce Allan 		params->es[i].off = ICE_FV_OFFSET_INVAL;
132731ad4e4eSTony Nguyen 	}
132831ad4e4eSTony Nguyen 
132988dcfdb4SBruce Allan 	params->blk = blk;
133088dcfdb4SBruce Allan 	params->prof->id = prof_id;
133188dcfdb4SBruce Allan 	params->prof->dir = dir;
133288dcfdb4SBruce Allan 	params->prof->segs_cnt = segs_cnt;
133331ad4e4eSTony Nguyen 
133431ad4e4eSTony Nguyen 	/* Make a copy of the segments that need to be persistent in the flow
133531ad4e4eSTony Nguyen 	 * profile instance
133631ad4e4eSTony Nguyen 	 */
133731ad4e4eSTony Nguyen 	for (i = 0; i < segs_cnt; i++)
133888dcfdb4SBruce Allan 		memcpy(&params->prof->segs[i], &segs[i], sizeof(*segs));
133931ad4e4eSTony Nguyen 
134088dcfdb4SBruce Allan 	status = ice_flow_proc_segs(hw, params);
134131ad4e4eSTony Nguyen 	if (status) {
13429228d8b2SJacob Keller 		ice_debug(hw, ICE_DBG_FLOW, "Error processing a flow's packet segments\n");
134331ad4e4eSTony Nguyen 		goto out;
134431ad4e4eSTony Nguyen 	}
134531ad4e4eSTony Nguyen 
134631ad4e4eSTony Nguyen 	/* Add a HW profile for this flow profile */
134788dcfdb4SBruce Allan 	status = ice_add_prof(hw, blk, prof_id, (u8 *)params->ptypes,
1348*cbad5db8SQi Zhang 			      params->attr, params->attr_cnt, params->es,
1349*cbad5db8SQi Zhang 			      params->mask);
135031ad4e4eSTony Nguyen 	if (status) {
135131ad4e4eSTony Nguyen 		ice_debug(hw, ICE_DBG_FLOW, "Error adding a HW flow profile\n");
135231ad4e4eSTony Nguyen 		goto out;
135331ad4e4eSTony Nguyen 	}
135431ad4e4eSTony Nguyen 
135588dcfdb4SBruce Allan 	INIT_LIST_HEAD(&params->prof->entries);
135688dcfdb4SBruce Allan 	mutex_init(&params->prof->entries_lock);
135788dcfdb4SBruce Allan 	*prof = params->prof;
135831ad4e4eSTony Nguyen 
135931ad4e4eSTony Nguyen out:
136031ad4e4eSTony Nguyen 	if (status)
136188dcfdb4SBruce Allan 		devm_kfree(ice_hw_to_dev(hw), params->prof);
136288dcfdb4SBruce Allan free_params:
136388dcfdb4SBruce Allan 	kfree(params);
136431ad4e4eSTony Nguyen 
136531ad4e4eSTony Nguyen 	return status;
136631ad4e4eSTony Nguyen }
136731ad4e4eSTony Nguyen 
136831ad4e4eSTony Nguyen /**
13692c61054cSTony Nguyen  * ice_flow_rem_prof_sync - remove a flow profile
13702c61054cSTony Nguyen  * @hw: pointer to the hardware structure
13712c61054cSTony Nguyen  * @blk: classification stage
13722c61054cSTony Nguyen  * @prof: pointer to flow profile to remove
13732c61054cSTony Nguyen  *
13742c61054cSTony Nguyen  * Assumption: the caller has acquired the lock to the profile list
13752c61054cSTony Nguyen  */
13762c61054cSTony Nguyen static enum ice_status
13772c61054cSTony Nguyen ice_flow_rem_prof_sync(struct ice_hw *hw, enum ice_block blk,
13782c61054cSTony Nguyen 		       struct ice_flow_prof *prof)
13792c61054cSTony Nguyen {
13802c61054cSTony Nguyen 	enum ice_status status;
13812c61054cSTony Nguyen 
1382148beb61SHenry Tieman 	/* Remove all remaining flow entries before removing the flow profile */
1383148beb61SHenry Tieman 	if (!list_empty(&prof->entries)) {
1384148beb61SHenry Tieman 		struct ice_flow_entry *e, *t;
1385148beb61SHenry Tieman 
1386148beb61SHenry Tieman 		mutex_lock(&prof->entries_lock);
1387148beb61SHenry Tieman 
1388148beb61SHenry Tieman 		list_for_each_entry_safe(e, t, &prof->entries, l_entry) {
1389148beb61SHenry Tieman 			status = ice_flow_rem_entry_sync(hw, blk, e);
1390148beb61SHenry Tieman 			if (status)
1391148beb61SHenry Tieman 				break;
1392148beb61SHenry Tieman 		}
1393148beb61SHenry Tieman 
1394148beb61SHenry Tieman 		mutex_unlock(&prof->entries_lock);
1395148beb61SHenry Tieman 	}
1396148beb61SHenry Tieman 
13972c61054cSTony Nguyen 	/* Remove all hardware profiles associated with this flow profile */
13982c61054cSTony Nguyen 	status = ice_rem_prof(hw, blk, prof->id);
13992c61054cSTony Nguyen 	if (!status) {
14002c61054cSTony Nguyen 		list_del(&prof->l_entry);
14012c61054cSTony Nguyen 		mutex_destroy(&prof->entries_lock);
14022c61054cSTony Nguyen 		devm_kfree(ice_hw_to_dev(hw), prof);
14032c61054cSTony Nguyen 	}
14042c61054cSTony Nguyen 
14052c61054cSTony Nguyen 	return status;
14062c61054cSTony Nguyen }
14072c61054cSTony Nguyen 
14082c61054cSTony Nguyen /**
1409451f2c44STony Nguyen  * ice_flow_assoc_prof - associate a VSI with a flow profile
1410451f2c44STony Nguyen  * @hw: pointer to the hardware structure
1411451f2c44STony Nguyen  * @blk: classification stage
1412451f2c44STony Nguyen  * @prof: pointer to flow profile
1413451f2c44STony Nguyen  * @vsi_handle: software VSI handle
1414451f2c44STony Nguyen  *
1415451f2c44STony Nguyen  * Assumption: the caller has acquired the lock to the profile list
1416451f2c44STony Nguyen  * and the software VSI handle has been validated
1417451f2c44STony Nguyen  */
1418451f2c44STony Nguyen static enum ice_status
1419451f2c44STony Nguyen ice_flow_assoc_prof(struct ice_hw *hw, enum ice_block blk,
1420451f2c44STony Nguyen 		    struct ice_flow_prof *prof, u16 vsi_handle)
1421451f2c44STony Nguyen {
1422451f2c44STony Nguyen 	enum ice_status status = 0;
1423451f2c44STony Nguyen 
1424451f2c44STony Nguyen 	if (!test_bit(vsi_handle, prof->vsis)) {
1425451f2c44STony Nguyen 		status = ice_add_prof_id_flow(hw, blk,
1426451f2c44STony Nguyen 					      ice_get_hw_vsi_num(hw,
1427451f2c44STony Nguyen 								 vsi_handle),
1428451f2c44STony Nguyen 					      prof->id);
1429451f2c44STony Nguyen 		if (!status)
1430451f2c44STony Nguyen 			set_bit(vsi_handle, prof->vsis);
1431451f2c44STony Nguyen 		else
14329228d8b2SJacob Keller 			ice_debug(hw, ICE_DBG_FLOW, "HW profile add failed, %d\n",
1433451f2c44STony Nguyen 				  status);
1434451f2c44STony Nguyen 	}
1435451f2c44STony Nguyen 
1436451f2c44STony Nguyen 	return status;
1437451f2c44STony Nguyen }
1438451f2c44STony Nguyen 
1439451f2c44STony Nguyen /**
14402c61054cSTony Nguyen  * ice_flow_disassoc_prof - disassociate a VSI from a flow profile
14412c61054cSTony Nguyen  * @hw: pointer to the hardware structure
14422c61054cSTony Nguyen  * @blk: classification stage
14432c61054cSTony Nguyen  * @prof: pointer to flow profile
14442c61054cSTony Nguyen  * @vsi_handle: software VSI handle
14452c61054cSTony Nguyen  *
14462c61054cSTony Nguyen  * Assumption: the caller has acquired the lock to the profile list
14472c61054cSTony Nguyen  * and the software VSI handle has been validated
14482c61054cSTony Nguyen  */
14492c61054cSTony Nguyen static enum ice_status
14502c61054cSTony Nguyen ice_flow_disassoc_prof(struct ice_hw *hw, enum ice_block blk,
14512c61054cSTony Nguyen 		       struct ice_flow_prof *prof, u16 vsi_handle)
14522c61054cSTony Nguyen {
14532c61054cSTony Nguyen 	enum ice_status status = 0;
14542c61054cSTony Nguyen 
14552c61054cSTony Nguyen 	if (test_bit(vsi_handle, prof->vsis)) {
14562c61054cSTony Nguyen 		status = ice_rem_prof_id_flow(hw, blk,
14572c61054cSTony Nguyen 					      ice_get_hw_vsi_num(hw,
14582c61054cSTony Nguyen 								 vsi_handle),
14592c61054cSTony Nguyen 					      prof->id);
14602c61054cSTony Nguyen 		if (!status)
14612c61054cSTony Nguyen 			clear_bit(vsi_handle, prof->vsis);
14622c61054cSTony Nguyen 		else
14639228d8b2SJacob Keller 			ice_debug(hw, ICE_DBG_FLOW, "HW profile remove failed, %d\n",
14642c61054cSTony Nguyen 				  status);
14652c61054cSTony Nguyen 	}
14662c61054cSTony Nguyen 
14672c61054cSTony Nguyen 	return status;
14682c61054cSTony Nguyen }
14692c61054cSTony Nguyen 
14702c61054cSTony Nguyen /**
147131ad4e4eSTony Nguyen  * ice_flow_add_prof - Add a flow profile for packet segments and matched fields
147231ad4e4eSTony Nguyen  * @hw: pointer to the HW struct
147331ad4e4eSTony Nguyen  * @blk: classification stage
147431ad4e4eSTony Nguyen  * @dir: flow direction
147531ad4e4eSTony Nguyen  * @prof_id: unique ID to identify this flow profile
147631ad4e4eSTony Nguyen  * @segs: array of one or more packet segments that describe the flow
147731ad4e4eSTony Nguyen  * @segs_cnt: number of packet segments provided
1478451f2c44STony Nguyen  * @prof: stores the returned flow profile added
147931ad4e4eSTony Nguyen  */
1480148beb61SHenry Tieman enum ice_status
148131ad4e4eSTony Nguyen ice_flow_add_prof(struct ice_hw *hw, enum ice_block blk, enum ice_flow_dir dir,
1482451f2c44STony Nguyen 		  u64 prof_id, struct ice_flow_seg_info *segs, u8 segs_cnt,
1483451f2c44STony Nguyen 		  struct ice_flow_prof **prof)
148431ad4e4eSTony Nguyen {
148531ad4e4eSTony Nguyen 	enum ice_status status;
148631ad4e4eSTony Nguyen 
148731ad4e4eSTony Nguyen 	if (segs_cnt > ICE_FLOW_SEG_MAX)
148831ad4e4eSTony Nguyen 		return ICE_ERR_MAX_LIMIT;
148931ad4e4eSTony Nguyen 
149031ad4e4eSTony Nguyen 	if (!segs_cnt)
149131ad4e4eSTony Nguyen 		return ICE_ERR_PARAM;
149231ad4e4eSTony Nguyen 
149331ad4e4eSTony Nguyen 	if (!segs)
149431ad4e4eSTony Nguyen 		return ICE_ERR_BAD_PTR;
149531ad4e4eSTony Nguyen 
149631ad4e4eSTony Nguyen 	status = ice_flow_val_hdrs(segs, segs_cnt);
149731ad4e4eSTony Nguyen 	if (status)
149831ad4e4eSTony Nguyen 		return status;
149931ad4e4eSTony Nguyen 
150031ad4e4eSTony Nguyen 	mutex_lock(&hw->fl_profs_locks[blk]);
150131ad4e4eSTony Nguyen 
150231ad4e4eSTony Nguyen 	status = ice_flow_add_prof_sync(hw, blk, dir, prof_id, segs, segs_cnt,
1503451f2c44STony Nguyen 					prof);
150431ad4e4eSTony Nguyen 	if (!status)
1505451f2c44STony Nguyen 		list_add(&(*prof)->l_entry, &hw->fl_profs[blk]);
150631ad4e4eSTony Nguyen 
150731ad4e4eSTony Nguyen 	mutex_unlock(&hw->fl_profs_locks[blk]);
150831ad4e4eSTony Nguyen 
150931ad4e4eSTony Nguyen 	return status;
151031ad4e4eSTony Nguyen }
151131ad4e4eSTony Nguyen 
1512c90ed40cSTony Nguyen /**
15132c61054cSTony Nguyen  * ice_flow_rem_prof - Remove a flow profile and all entries associated with it
15142c61054cSTony Nguyen  * @hw: pointer to the HW struct
15152c61054cSTony Nguyen  * @blk: the block for which the flow profile is to be removed
15162c61054cSTony Nguyen  * @prof_id: unique ID of the flow profile to be removed
15172c61054cSTony Nguyen  */
1518148beb61SHenry Tieman enum ice_status
15192c61054cSTony Nguyen ice_flow_rem_prof(struct ice_hw *hw, enum ice_block blk, u64 prof_id)
15202c61054cSTony Nguyen {
15212c61054cSTony Nguyen 	struct ice_flow_prof *prof;
15222c61054cSTony Nguyen 	enum ice_status status;
15232c61054cSTony Nguyen 
15242c61054cSTony Nguyen 	mutex_lock(&hw->fl_profs_locks[blk]);
15252c61054cSTony Nguyen 
15262c61054cSTony Nguyen 	prof = ice_flow_find_prof_id(hw, blk, prof_id);
15272c61054cSTony Nguyen 	if (!prof) {
15282c61054cSTony Nguyen 		status = ICE_ERR_DOES_NOT_EXIST;
15292c61054cSTony Nguyen 		goto out;
15302c61054cSTony Nguyen 	}
15312c61054cSTony Nguyen 
15322c61054cSTony Nguyen 	/* prof becomes invalid after the call */
15332c61054cSTony Nguyen 	status = ice_flow_rem_prof_sync(hw, blk, prof);
15342c61054cSTony Nguyen 
15352c61054cSTony Nguyen out:
15362c61054cSTony Nguyen 	mutex_unlock(&hw->fl_profs_locks[blk]);
15372c61054cSTony Nguyen 
15382c61054cSTony Nguyen 	return status;
15392c61054cSTony Nguyen }
15402c61054cSTony Nguyen 
15412c61054cSTony Nguyen /**
1542148beb61SHenry Tieman  * ice_flow_add_entry - Add a flow entry
1543148beb61SHenry Tieman  * @hw: pointer to the HW struct
1544148beb61SHenry Tieman  * @blk: classification stage
1545148beb61SHenry Tieman  * @prof_id: ID of the profile to add a new flow entry to
1546148beb61SHenry Tieman  * @entry_id: unique ID to identify this flow entry
1547148beb61SHenry Tieman  * @vsi_handle: software VSI handle for the flow entry
1548148beb61SHenry Tieman  * @prio: priority of the flow entry
1549148beb61SHenry Tieman  * @data: pointer to a data buffer containing flow entry's match values/masks
1550148beb61SHenry Tieman  * @entry_h: pointer to buffer that receives the new flow entry's handle
1551148beb61SHenry Tieman  */
1552148beb61SHenry Tieman enum ice_status
1553148beb61SHenry Tieman ice_flow_add_entry(struct ice_hw *hw, enum ice_block blk, u64 prof_id,
1554148beb61SHenry Tieman 		   u64 entry_id, u16 vsi_handle, enum ice_flow_priority prio,
1555148beb61SHenry Tieman 		   void *data, u64 *entry_h)
1556148beb61SHenry Tieman {
1557148beb61SHenry Tieman 	struct ice_flow_entry *e = NULL;
1558148beb61SHenry Tieman 	struct ice_flow_prof *prof;
1559148beb61SHenry Tieman 	enum ice_status status;
1560148beb61SHenry Tieman 
1561148beb61SHenry Tieman 	/* No flow entry data is expected for RSS */
1562148beb61SHenry Tieman 	if (!entry_h || (!data && blk != ICE_BLK_RSS))
1563148beb61SHenry Tieman 		return ICE_ERR_BAD_PTR;
1564148beb61SHenry Tieman 
1565148beb61SHenry Tieman 	if (!ice_is_vsi_valid(hw, vsi_handle))
1566148beb61SHenry Tieman 		return ICE_ERR_PARAM;
1567148beb61SHenry Tieman 
1568148beb61SHenry Tieman 	mutex_lock(&hw->fl_profs_locks[blk]);
1569148beb61SHenry Tieman 
1570148beb61SHenry Tieman 	prof = ice_flow_find_prof_id(hw, blk, prof_id);
1571148beb61SHenry Tieman 	if (!prof) {
1572148beb61SHenry Tieman 		status = ICE_ERR_DOES_NOT_EXIST;
1573148beb61SHenry Tieman 	} else {
1574148beb61SHenry Tieman 		/* Allocate memory for the entry being added and associate
1575148beb61SHenry Tieman 		 * the VSI to the found flow profile
1576148beb61SHenry Tieman 		 */
1577148beb61SHenry Tieman 		e = devm_kzalloc(ice_hw_to_dev(hw), sizeof(*e), GFP_KERNEL);
1578148beb61SHenry Tieman 		if (!e)
1579148beb61SHenry Tieman 			status = ICE_ERR_NO_MEMORY;
1580148beb61SHenry Tieman 		else
1581148beb61SHenry Tieman 			status = ice_flow_assoc_prof(hw, blk, prof, vsi_handle);
1582148beb61SHenry Tieman 	}
1583148beb61SHenry Tieman 
1584148beb61SHenry Tieman 	mutex_unlock(&hw->fl_profs_locks[blk]);
1585148beb61SHenry Tieman 	if (status)
1586148beb61SHenry Tieman 		goto out;
1587148beb61SHenry Tieman 
1588148beb61SHenry Tieman 	e->id = entry_id;
1589148beb61SHenry Tieman 	e->vsi_handle = vsi_handle;
1590148beb61SHenry Tieman 	e->prof = prof;
1591148beb61SHenry Tieman 	e->priority = prio;
1592148beb61SHenry Tieman 
1593148beb61SHenry Tieman 	switch (blk) {
1594148beb61SHenry Tieman 	case ICE_BLK_FD:
1595148beb61SHenry Tieman 	case ICE_BLK_RSS:
1596148beb61SHenry Tieman 		break;
1597148beb61SHenry Tieman 	default:
1598148beb61SHenry Tieman 		status = ICE_ERR_NOT_IMPL;
1599148beb61SHenry Tieman 		goto out;
1600148beb61SHenry Tieman 	}
1601148beb61SHenry Tieman 
1602148beb61SHenry Tieman 	mutex_lock(&prof->entries_lock);
1603148beb61SHenry Tieman 	list_add(&e->l_entry, &prof->entries);
1604148beb61SHenry Tieman 	mutex_unlock(&prof->entries_lock);
1605148beb61SHenry Tieman 
1606148beb61SHenry Tieman 	*entry_h = ICE_FLOW_ENTRY_HNDL(e);
1607148beb61SHenry Tieman 
1608148beb61SHenry Tieman out:
1609148beb61SHenry Tieman 	if (status && e) {
1610148beb61SHenry Tieman 		if (e->entry)
1611148beb61SHenry Tieman 			devm_kfree(ice_hw_to_dev(hw), e->entry);
1612148beb61SHenry Tieman 		devm_kfree(ice_hw_to_dev(hw), e);
1613148beb61SHenry Tieman 	}
1614148beb61SHenry Tieman 
1615148beb61SHenry Tieman 	return status;
1616148beb61SHenry Tieman }
1617148beb61SHenry Tieman 
1618148beb61SHenry Tieman /**
1619148beb61SHenry Tieman  * ice_flow_rem_entry - Remove a flow entry
1620148beb61SHenry Tieman  * @hw: pointer to the HW struct
1621148beb61SHenry Tieman  * @blk: classification stage
1622148beb61SHenry Tieman  * @entry_h: handle to the flow entry to be removed
1623148beb61SHenry Tieman  */
1624148beb61SHenry Tieman enum ice_status ice_flow_rem_entry(struct ice_hw *hw, enum ice_block blk,
1625148beb61SHenry Tieman 				   u64 entry_h)
1626148beb61SHenry Tieman {
1627148beb61SHenry Tieman 	struct ice_flow_entry *entry;
1628148beb61SHenry Tieman 	struct ice_flow_prof *prof;
1629148beb61SHenry Tieman 	enum ice_status status = 0;
1630148beb61SHenry Tieman 
1631148beb61SHenry Tieman 	if (entry_h == ICE_FLOW_ENTRY_HANDLE_INVAL)
1632148beb61SHenry Tieman 		return ICE_ERR_PARAM;
1633148beb61SHenry Tieman 
1634148beb61SHenry Tieman 	entry = ICE_FLOW_ENTRY_PTR(entry_h);
1635148beb61SHenry Tieman 
1636148beb61SHenry Tieman 	/* Retain the pointer to the flow profile as the entry will be freed */
1637148beb61SHenry Tieman 	prof = entry->prof;
1638148beb61SHenry Tieman 
1639148beb61SHenry Tieman 	if (prof) {
1640148beb61SHenry Tieman 		mutex_lock(&prof->entries_lock);
1641148beb61SHenry Tieman 		status = ice_flow_rem_entry_sync(hw, blk, entry);
1642148beb61SHenry Tieman 		mutex_unlock(&prof->entries_lock);
1643148beb61SHenry Tieman 	}
1644148beb61SHenry Tieman 
1645148beb61SHenry Tieman 	return status;
1646148beb61SHenry Tieman }
1647148beb61SHenry Tieman 
1648148beb61SHenry Tieman /**
1649c90ed40cSTony Nguyen  * ice_flow_set_fld_ext - specifies locations of field from entry's input buffer
1650c90ed40cSTony Nguyen  * @seg: packet segment the field being set belongs to
1651c90ed40cSTony Nguyen  * @fld: field to be set
16526dae8aa0SBruce Allan  * @field_type: type of the field
1653c90ed40cSTony Nguyen  * @val_loc: if not ICE_FLOW_FLD_OFF_INVAL, location of the value to match from
1654c90ed40cSTony Nguyen  *           entry's input buffer
1655c90ed40cSTony Nguyen  * @mask_loc: if not ICE_FLOW_FLD_OFF_INVAL, location of mask value from entry's
1656c90ed40cSTony Nguyen  *            input buffer
1657c90ed40cSTony Nguyen  * @last_loc: if not ICE_FLOW_FLD_OFF_INVAL, location of last/upper value from
1658c90ed40cSTony Nguyen  *            entry's input buffer
1659c90ed40cSTony Nguyen  *
1660c90ed40cSTony Nguyen  * This helper function stores information of a field being matched, including
1661c90ed40cSTony Nguyen  * the type of the field and the locations of the value to match, the mask, and
1662ac382a09SBruce Allan  * the upper-bound value in the start of the input buffer for a flow entry.
1663c90ed40cSTony Nguyen  * This function should only be used for fixed-size data structures.
1664c90ed40cSTony Nguyen  *
1665c90ed40cSTony Nguyen  * This function also opportunistically determines the protocol headers to be
1666c90ed40cSTony Nguyen  * present based on the fields being set. Some fields cannot be used alone to
1667c90ed40cSTony Nguyen  * determine the protocol headers present. Sometimes, fields for particular
1668c90ed40cSTony Nguyen  * protocol headers are not matched. In those cases, the protocol headers
1669c90ed40cSTony Nguyen  * must be explicitly set.
1670c90ed40cSTony Nguyen  */
1671c90ed40cSTony Nguyen static void
1672c90ed40cSTony Nguyen ice_flow_set_fld_ext(struct ice_flow_seg_info *seg, enum ice_flow_field fld,
16736dae8aa0SBruce Allan 		     enum ice_flow_fld_match_type field_type, u16 val_loc,
1674c90ed40cSTony Nguyen 		     u16 mask_loc, u16 last_loc)
1675c90ed40cSTony Nguyen {
1676c90ed40cSTony Nguyen 	u64 bit = BIT_ULL(fld);
1677c90ed40cSTony Nguyen 
1678c90ed40cSTony Nguyen 	seg->match |= bit;
16796dae8aa0SBruce Allan 	if (field_type == ICE_FLOW_FLD_TYPE_RANGE)
1680c90ed40cSTony Nguyen 		seg->range |= bit;
1681c90ed40cSTony Nguyen 
16826dae8aa0SBruce Allan 	seg->fields[fld].type = field_type;
1683c90ed40cSTony Nguyen 	seg->fields[fld].src.val = val_loc;
1684c90ed40cSTony Nguyen 	seg->fields[fld].src.mask = mask_loc;
1685c90ed40cSTony Nguyen 	seg->fields[fld].src.last = last_loc;
1686c90ed40cSTony Nguyen 
1687c90ed40cSTony Nguyen 	ICE_FLOW_SET_HDRS(seg, ice_flds_info[fld].hdr);
1688c90ed40cSTony Nguyen }
1689c90ed40cSTony Nguyen 
1690c90ed40cSTony Nguyen /**
1691c90ed40cSTony Nguyen  * ice_flow_set_fld - specifies locations of field from entry's input buffer
1692c90ed40cSTony Nguyen  * @seg: packet segment the field being set belongs to
1693c90ed40cSTony Nguyen  * @fld: field to be set
1694c90ed40cSTony Nguyen  * @val_loc: if not ICE_FLOW_FLD_OFF_INVAL, location of the value to match from
1695c90ed40cSTony Nguyen  *           entry's input buffer
1696c90ed40cSTony Nguyen  * @mask_loc: if not ICE_FLOW_FLD_OFF_INVAL, location of mask value from entry's
1697c90ed40cSTony Nguyen  *            input buffer
1698c90ed40cSTony Nguyen  * @last_loc: if not ICE_FLOW_FLD_OFF_INVAL, location of last/upper value from
1699c90ed40cSTony Nguyen  *            entry's input buffer
1700c90ed40cSTony Nguyen  * @range: indicate if field being matched is to be in a range
1701c90ed40cSTony Nguyen  *
1702c90ed40cSTony Nguyen  * This function specifies the locations, in the form of byte offsets from the
1703c90ed40cSTony Nguyen  * start of the input buffer for a flow entry, from where the value to match,
1704c90ed40cSTony Nguyen  * the mask value, and upper value can be extracted. These locations are then
1705c90ed40cSTony Nguyen  * stored in the flow profile. When adding a flow entry associated with the
1706c90ed40cSTony Nguyen  * flow profile, these locations will be used to quickly extract the values and
1707c90ed40cSTony Nguyen  * create the content of a match entry. This function should only be used for
1708c90ed40cSTony Nguyen  * fixed-size data structures.
1709c90ed40cSTony Nguyen  */
1710148beb61SHenry Tieman void
1711c90ed40cSTony Nguyen ice_flow_set_fld(struct ice_flow_seg_info *seg, enum ice_flow_field fld,
1712c90ed40cSTony Nguyen 		 u16 val_loc, u16 mask_loc, u16 last_loc, bool range)
1713c90ed40cSTony Nguyen {
1714c90ed40cSTony Nguyen 	enum ice_flow_fld_match_type t = range ?
1715c90ed40cSTony Nguyen 		ICE_FLOW_FLD_TYPE_RANGE : ICE_FLOW_FLD_TYPE_REG;
1716c90ed40cSTony Nguyen 
1717c90ed40cSTony Nguyen 	ice_flow_set_fld_ext(seg, fld, t, val_loc, mask_loc, last_loc);
1718c90ed40cSTony Nguyen }
1719c90ed40cSTony Nguyen 
17202c57ffcbSHenry Tieman /**
17212c57ffcbSHenry Tieman  * ice_flow_add_fld_raw - sets locations of a raw field from entry's input buf
17222c57ffcbSHenry Tieman  * @seg: packet segment the field being set belongs to
17232c57ffcbSHenry Tieman  * @off: offset of the raw field from the beginning of the segment in bytes
17242c57ffcbSHenry Tieman  * @len: length of the raw pattern to be matched
17252c57ffcbSHenry Tieman  * @val_loc: location of the value to match from entry's input buffer
17262c57ffcbSHenry Tieman  * @mask_loc: location of mask value from entry's input buffer
17272c57ffcbSHenry Tieman  *
17282c57ffcbSHenry Tieman  * This function specifies the offset of the raw field to be match from the
17292c57ffcbSHenry Tieman  * beginning of the specified packet segment, and the locations, in the form of
17302c57ffcbSHenry Tieman  * byte offsets from the start of the input buffer for a flow entry, from where
17312c57ffcbSHenry Tieman  * the value to match and the mask value to be extracted. These locations are
17322c57ffcbSHenry Tieman  * then stored in the flow profile. When adding flow entries to the associated
17332c57ffcbSHenry Tieman  * flow profile, these locations can be used to quickly extract the values to
17342c57ffcbSHenry Tieman  * create the content of a match entry. This function should only be used for
17352c57ffcbSHenry Tieman  * fixed-size data structures.
17362c57ffcbSHenry Tieman  */
17372c57ffcbSHenry Tieman void
17382c57ffcbSHenry Tieman ice_flow_add_fld_raw(struct ice_flow_seg_info *seg, u16 off, u8 len,
17392c57ffcbSHenry Tieman 		     u16 val_loc, u16 mask_loc)
17402c57ffcbSHenry Tieman {
17412c57ffcbSHenry Tieman 	if (seg->raws_cnt < ICE_FLOW_SEG_RAW_FLD_MAX) {
17422c57ffcbSHenry Tieman 		seg->raws[seg->raws_cnt].off = off;
17432c57ffcbSHenry Tieman 		seg->raws[seg->raws_cnt].info.type = ICE_FLOW_FLD_TYPE_SIZE;
17442c57ffcbSHenry Tieman 		seg->raws[seg->raws_cnt].info.src.val = val_loc;
17452c57ffcbSHenry Tieman 		seg->raws[seg->raws_cnt].info.src.mask = mask_loc;
17462c57ffcbSHenry Tieman 		/* The "last" field is used to store the length of the field */
17472c57ffcbSHenry Tieman 		seg->raws[seg->raws_cnt].info.src.last = len;
17482c57ffcbSHenry Tieman 	}
17492c57ffcbSHenry Tieman 
17502c57ffcbSHenry Tieman 	/* Overflows of "raws" will be handled as an error condition later in
17512c57ffcbSHenry Tieman 	 * the flow when this information is processed.
17522c57ffcbSHenry Tieman 	 */
17532c57ffcbSHenry Tieman 	seg->raws_cnt++;
17542c57ffcbSHenry Tieman }
17552c57ffcbSHenry Tieman 
1756390bd141SQi Zhang #define ICE_FLOW_RSS_SEG_HDR_L2_MASKS \
1757390bd141SQi Zhang 	(ICE_FLOW_SEG_HDR_ETH | ICE_FLOW_SEG_HDR_VLAN)
1758390bd141SQi Zhang 
1759c90ed40cSTony Nguyen #define ICE_FLOW_RSS_SEG_HDR_L3_MASKS \
1760c90ed40cSTony Nguyen 	(ICE_FLOW_SEG_HDR_IPV4 | ICE_FLOW_SEG_HDR_IPV6)
1761c90ed40cSTony Nguyen 
1762c90ed40cSTony Nguyen #define ICE_FLOW_RSS_SEG_HDR_L4_MASKS \
1763c90ed40cSTony Nguyen 	(ICE_FLOW_SEG_HDR_TCP | ICE_FLOW_SEG_HDR_UDP | ICE_FLOW_SEG_HDR_SCTP)
1764c90ed40cSTony Nguyen 
1765c90ed40cSTony Nguyen #define ICE_FLOW_RSS_SEG_HDR_VAL_MASKS \
1766390bd141SQi Zhang 	(ICE_FLOW_RSS_SEG_HDR_L2_MASKS | \
1767390bd141SQi Zhang 	 ICE_FLOW_RSS_SEG_HDR_L3_MASKS | \
1768c90ed40cSTony Nguyen 	 ICE_FLOW_RSS_SEG_HDR_L4_MASKS)
1769c90ed40cSTony Nguyen 
1770c90ed40cSTony Nguyen /**
1771c90ed40cSTony Nguyen  * ice_flow_set_rss_seg_info - setup packet segments for RSS
1772c90ed40cSTony Nguyen  * @segs: pointer to the flow field segment(s)
1773c90ed40cSTony Nguyen  * @hash_fields: fields to be hashed on for the segment(s)
1774c90ed40cSTony Nguyen  * @flow_hdr: protocol header fields within a packet segment
1775c90ed40cSTony Nguyen  *
1776c90ed40cSTony Nguyen  * Helper function to extract fields from hash bitmap and use flow
1777c90ed40cSTony Nguyen  * header value to set flow field segment for further use in flow
1778c90ed40cSTony Nguyen  * profile entry or removal.
1779c90ed40cSTony Nguyen  */
1780c90ed40cSTony Nguyen static enum ice_status
1781c90ed40cSTony Nguyen ice_flow_set_rss_seg_info(struct ice_flow_seg_info *segs, u64 hash_fields,
1782c90ed40cSTony Nguyen 			  u32 flow_hdr)
1783c90ed40cSTony Nguyen {
1784c90ed40cSTony Nguyen 	u64 val;
1785c90ed40cSTony Nguyen 	u8 i;
1786c90ed40cSTony Nguyen 
1787c90ed40cSTony Nguyen 	for_each_set_bit(i, (unsigned long *)&hash_fields,
1788c90ed40cSTony Nguyen 			 ICE_FLOW_FIELD_IDX_MAX)
1789c90ed40cSTony Nguyen 		ice_flow_set_fld(segs, (enum ice_flow_field)i,
1790c90ed40cSTony Nguyen 				 ICE_FLOW_FLD_OFF_INVAL, ICE_FLOW_FLD_OFF_INVAL,
1791c90ed40cSTony Nguyen 				 ICE_FLOW_FLD_OFF_INVAL, false);
1792c90ed40cSTony Nguyen 
1793c90ed40cSTony Nguyen 	ICE_FLOW_SET_HDRS(segs, flow_hdr);
1794c90ed40cSTony Nguyen 
17950577313eSQi Zhang 	if (segs->hdrs & ~ICE_FLOW_RSS_SEG_HDR_VAL_MASKS &
17960577313eSQi Zhang 	    ~ICE_FLOW_RSS_HDRS_INNER_MASK)
1797c90ed40cSTony Nguyen 		return ICE_ERR_PARAM;
1798c90ed40cSTony Nguyen 
1799c90ed40cSTony Nguyen 	val = (u64)(segs->hdrs & ICE_FLOW_RSS_SEG_HDR_L3_MASKS);
1800c90ed40cSTony Nguyen 	if (val && !is_power_of_2(val))
1801c90ed40cSTony Nguyen 		return ICE_ERR_CFG;
1802c90ed40cSTony Nguyen 
1803c90ed40cSTony Nguyen 	val = (u64)(segs->hdrs & ICE_FLOW_RSS_SEG_HDR_L4_MASKS);
1804c90ed40cSTony Nguyen 	if (val && !is_power_of_2(val))
1805c90ed40cSTony Nguyen 		return ICE_ERR_CFG;
1806c90ed40cSTony Nguyen 
1807c90ed40cSTony Nguyen 	return 0;
1808c90ed40cSTony Nguyen }
1809c90ed40cSTony Nguyen 
18102c61054cSTony Nguyen /**
18112c61054cSTony Nguyen  * ice_rem_vsi_rss_list - remove VSI from RSS list
18122c61054cSTony Nguyen  * @hw: pointer to the hardware structure
18132c61054cSTony Nguyen  * @vsi_handle: software VSI handle
18142c61054cSTony Nguyen  *
18152c61054cSTony Nguyen  * Remove the VSI from all RSS configurations in the list.
18162c61054cSTony Nguyen  */
18172c61054cSTony Nguyen void ice_rem_vsi_rss_list(struct ice_hw *hw, u16 vsi_handle)
18182c61054cSTony Nguyen {
18192c61054cSTony Nguyen 	struct ice_rss_cfg *r, *tmp;
18202c61054cSTony Nguyen 
18212c61054cSTony Nguyen 	if (list_empty(&hw->rss_list_head))
18222c61054cSTony Nguyen 		return;
18232c61054cSTony Nguyen 
18242c61054cSTony Nguyen 	mutex_lock(&hw->rss_locks);
18252c61054cSTony Nguyen 	list_for_each_entry_safe(r, tmp, &hw->rss_list_head, l_entry)
18262c61054cSTony Nguyen 		if (test_and_clear_bit(vsi_handle, r->vsis))
18272c61054cSTony Nguyen 			if (bitmap_empty(r->vsis, ICE_MAX_VSI)) {
18282c61054cSTony Nguyen 				list_del(&r->l_entry);
18292c61054cSTony Nguyen 				devm_kfree(ice_hw_to_dev(hw), r);
18302c61054cSTony Nguyen 			}
18312c61054cSTony Nguyen 	mutex_unlock(&hw->rss_locks);
18322c61054cSTony Nguyen }
18332c61054cSTony Nguyen 
18342c61054cSTony Nguyen /**
18352c61054cSTony Nguyen  * ice_rem_vsi_rss_cfg - remove RSS configurations associated with VSI
18362c61054cSTony Nguyen  * @hw: pointer to the hardware structure
18372c61054cSTony Nguyen  * @vsi_handle: software VSI handle
18382c61054cSTony Nguyen  *
18392c61054cSTony Nguyen  * This function will iterate through all flow profiles and disassociate
18402c61054cSTony Nguyen  * the VSI from that profile. If the flow profile has no VSIs it will
18412c61054cSTony Nguyen  * be removed.
18422c61054cSTony Nguyen  */
18432c61054cSTony Nguyen enum ice_status ice_rem_vsi_rss_cfg(struct ice_hw *hw, u16 vsi_handle)
18442c61054cSTony Nguyen {
18452c61054cSTony Nguyen 	const enum ice_block blk = ICE_BLK_RSS;
18462c61054cSTony Nguyen 	struct ice_flow_prof *p, *t;
18472c61054cSTony Nguyen 	enum ice_status status = 0;
18482c61054cSTony Nguyen 
18492c61054cSTony Nguyen 	if (!ice_is_vsi_valid(hw, vsi_handle))
18502c61054cSTony Nguyen 		return ICE_ERR_PARAM;
18512c61054cSTony Nguyen 
18522c61054cSTony Nguyen 	if (list_empty(&hw->fl_profs[blk]))
18532c61054cSTony Nguyen 		return 0;
18542c61054cSTony Nguyen 
1855cdedbab9SVignesh Sridhar 	mutex_lock(&hw->rss_locks);
18562c61054cSTony Nguyen 	list_for_each_entry_safe(p, t, &hw->fl_profs[blk], l_entry)
18572c61054cSTony Nguyen 		if (test_bit(vsi_handle, p->vsis)) {
18582c61054cSTony Nguyen 			status = ice_flow_disassoc_prof(hw, blk, p, vsi_handle);
18592c61054cSTony Nguyen 			if (status)
18602c61054cSTony Nguyen 				break;
18612c61054cSTony Nguyen 
18622c61054cSTony Nguyen 			if (bitmap_empty(p->vsis, ICE_MAX_VSI)) {
1863cdedbab9SVignesh Sridhar 				status = ice_flow_rem_prof(hw, blk, p->id);
18642c61054cSTony Nguyen 				if (status)
18652c61054cSTony Nguyen 					break;
18662c61054cSTony Nguyen 			}
18672c61054cSTony Nguyen 		}
1868cdedbab9SVignesh Sridhar 	mutex_unlock(&hw->rss_locks);
18692c61054cSTony Nguyen 
18702c61054cSTony Nguyen 	return status;
18712c61054cSTony Nguyen }
18722c61054cSTony Nguyen 
18732c61054cSTony Nguyen /**
18742c61054cSTony Nguyen  * ice_rem_rss_list - remove RSS configuration from list
18752c61054cSTony Nguyen  * @hw: pointer to the hardware structure
18762c61054cSTony Nguyen  * @vsi_handle: software VSI handle
18772c61054cSTony Nguyen  * @prof: pointer to flow profile
18782c61054cSTony Nguyen  *
18792c61054cSTony Nguyen  * Assumption: lock has already been acquired for RSS list
18802c61054cSTony Nguyen  */
18812c61054cSTony Nguyen static void
18822c61054cSTony Nguyen ice_rem_rss_list(struct ice_hw *hw, u16 vsi_handle, struct ice_flow_prof *prof)
18832c61054cSTony Nguyen {
18842c61054cSTony Nguyen 	struct ice_rss_cfg *r, *tmp;
18852c61054cSTony Nguyen 
18862c61054cSTony Nguyen 	/* Search for RSS hash fields associated to the VSI that match the
18872c61054cSTony Nguyen 	 * hash configurations associated to the flow profile. If found
18882c61054cSTony Nguyen 	 * remove from the RSS entry list of the VSI context and delete entry.
18892c61054cSTony Nguyen 	 */
18902c61054cSTony Nguyen 	list_for_each_entry_safe(r, tmp, &hw->rss_list_head, l_entry)
18912c61054cSTony Nguyen 		if (r->hashed_flds == prof->segs[prof->segs_cnt - 1].match &&
18922c61054cSTony Nguyen 		    r->packet_hdr == prof->segs[prof->segs_cnt - 1].hdrs) {
18932c61054cSTony Nguyen 			clear_bit(vsi_handle, r->vsis);
18942c61054cSTony Nguyen 			if (bitmap_empty(r->vsis, ICE_MAX_VSI)) {
18952c61054cSTony Nguyen 				list_del(&r->l_entry);
18962c61054cSTony Nguyen 				devm_kfree(ice_hw_to_dev(hw), r);
18972c61054cSTony Nguyen 			}
18982c61054cSTony Nguyen 			return;
18992c61054cSTony Nguyen 		}
19002c61054cSTony Nguyen }
19012c61054cSTony Nguyen 
19022c61054cSTony Nguyen /**
19032c61054cSTony Nguyen  * ice_add_rss_list - add RSS configuration to list
19042c61054cSTony Nguyen  * @hw: pointer to the hardware structure
19052c61054cSTony Nguyen  * @vsi_handle: software VSI handle
19062c61054cSTony Nguyen  * @prof: pointer to flow profile
19072c61054cSTony Nguyen  *
19082c61054cSTony Nguyen  * Assumption: lock has already been acquired for RSS list
19092c61054cSTony Nguyen  */
19102c61054cSTony Nguyen static enum ice_status
19112c61054cSTony Nguyen ice_add_rss_list(struct ice_hw *hw, u16 vsi_handle, struct ice_flow_prof *prof)
19122c61054cSTony Nguyen {
19132c61054cSTony Nguyen 	struct ice_rss_cfg *r, *rss_cfg;
19142c61054cSTony Nguyen 
19152c61054cSTony Nguyen 	list_for_each_entry(r, &hw->rss_list_head, l_entry)
19162c61054cSTony Nguyen 		if (r->hashed_flds == prof->segs[prof->segs_cnt - 1].match &&
19172c61054cSTony Nguyen 		    r->packet_hdr == prof->segs[prof->segs_cnt - 1].hdrs) {
19182c61054cSTony Nguyen 			set_bit(vsi_handle, r->vsis);
19192c61054cSTony Nguyen 			return 0;
19202c61054cSTony Nguyen 		}
19212c61054cSTony Nguyen 
19222c61054cSTony Nguyen 	rss_cfg = devm_kzalloc(ice_hw_to_dev(hw), sizeof(*rss_cfg),
19232c61054cSTony Nguyen 			       GFP_KERNEL);
19242c61054cSTony Nguyen 	if (!rss_cfg)
19252c61054cSTony Nguyen 		return ICE_ERR_NO_MEMORY;
19262c61054cSTony Nguyen 
19272c61054cSTony Nguyen 	rss_cfg->hashed_flds = prof->segs[prof->segs_cnt - 1].match;
19282c61054cSTony Nguyen 	rss_cfg->packet_hdr = prof->segs[prof->segs_cnt - 1].hdrs;
19292c61054cSTony Nguyen 	set_bit(vsi_handle, rss_cfg->vsis);
19302c61054cSTony Nguyen 
19312c61054cSTony Nguyen 	list_add_tail(&rss_cfg->l_entry, &hw->rss_list_head);
19322c61054cSTony Nguyen 
19332c61054cSTony Nguyen 	return 0;
19342c61054cSTony Nguyen }
19352c61054cSTony Nguyen 
193631ad4e4eSTony Nguyen #define ICE_FLOW_PROF_HASH_S	0
193731ad4e4eSTony Nguyen #define ICE_FLOW_PROF_HASH_M	(0xFFFFFFFFULL << ICE_FLOW_PROF_HASH_S)
193831ad4e4eSTony Nguyen #define ICE_FLOW_PROF_HDR_S	32
193931ad4e4eSTony Nguyen #define ICE_FLOW_PROF_HDR_M	(0x3FFFFFFFULL << ICE_FLOW_PROF_HDR_S)
194031ad4e4eSTony Nguyen #define ICE_FLOW_PROF_ENCAP_S	63
194131ad4e4eSTony Nguyen #define ICE_FLOW_PROF_ENCAP_M	(BIT_ULL(ICE_FLOW_PROF_ENCAP_S))
194231ad4e4eSTony Nguyen 
1943c90ed40cSTony Nguyen #define ICE_RSS_OUTER_HEADERS	1
1944a4e82a81STony Nguyen #define ICE_RSS_INNER_HEADERS	2
1945c90ed40cSTony Nguyen 
194631ad4e4eSTony Nguyen /* Flow profile ID format:
194731ad4e4eSTony Nguyen  * [0:31] - Packet match fields
194831ad4e4eSTony Nguyen  * [32:62] - Protocol header
194931ad4e4eSTony Nguyen  * [63] - Encapsulation flag, 0 if non-tunneled, 1 if tunneled
195031ad4e4eSTony Nguyen  */
195131ad4e4eSTony Nguyen #define ICE_FLOW_GEN_PROFID(hash, hdr, segs_cnt) \
195231ad4e4eSTony Nguyen 	(u64)(((u64)(hash) & ICE_FLOW_PROF_HASH_M) | \
195331ad4e4eSTony Nguyen 	      (((u64)(hdr) << ICE_FLOW_PROF_HDR_S) & ICE_FLOW_PROF_HDR_M) | \
195431ad4e4eSTony Nguyen 	      ((u8)((segs_cnt) - 1) ? ICE_FLOW_PROF_ENCAP_M : 0))
195531ad4e4eSTony Nguyen 
1956c90ed40cSTony Nguyen /**
1957c90ed40cSTony Nguyen  * ice_add_rss_cfg_sync - add an RSS configuration
195831ad4e4eSTony Nguyen  * @hw: pointer to the hardware structure
1959451f2c44STony Nguyen  * @vsi_handle: software VSI handle
1960c90ed40cSTony Nguyen  * @hashed_flds: hash bit fields (ICE_FLOW_HASH_*) to configure
1961c90ed40cSTony Nguyen  * @addl_hdrs: protocol header fields
1962c90ed40cSTony Nguyen  * @segs_cnt: packet segment count
1963c90ed40cSTony Nguyen  *
1964c90ed40cSTony Nguyen  * Assumption: lock has already been acquired for RSS list
1965c90ed40cSTony Nguyen  */
1966c90ed40cSTony Nguyen static enum ice_status
1967451f2c44STony Nguyen ice_add_rss_cfg_sync(struct ice_hw *hw, u16 vsi_handle, u64 hashed_flds,
1968451f2c44STony Nguyen 		     u32 addl_hdrs, u8 segs_cnt)
1969c90ed40cSTony Nguyen {
1970451f2c44STony Nguyen 	const enum ice_block blk = ICE_BLK_RSS;
1971451f2c44STony Nguyen 	struct ice_flow_prof *prof = NULL;
1972c90ed40cSTony Nguyen 	struct ice_flow_seg_info *segs;
1973c90ed40cSTony Nguyen 	enum ice_status status;
1974c90ed40cSTony Nguyen 
1975c90ed40cSTony Nguyen 	if (!segs_cnt || segs_cnt > ICE_FLOW_SEG_MAX)
1976c90ed40cSTony Nguyen 		return ICE_ERR_PARAM;
1977c90ed40cSTony Nguyen 
1978c90ed40cSTony Nguyen 	segs = kcalloc(segs_cnt, sizeof(*segs), GFP_KERNEL);
1979c90ed40cSTony Nguyen 	if (!segs)
1980c90ed40cSTony Nguyen 		return ICE_ERR_NO_MEMORY;
1981c90ed40cSTony Nguyen 
1982c90ed40cSTony Nguyen 	/* Construct the packet segment info from the hashed fields */
1983c90ed40cSTony Nguyen 	status = ice_flow_set_rss_seg_info(&segs[segs_cnt - 1], hashed_flds,
1984c90ed40cSTony Nguyen 					   addl_hdrs);
198531ad4e4eSTony Nguyen 	if (status)
198631ad4e4eSTony Nguyen 		goto exit;
1987c90ed40cSTony Nguyen 
19882c61054cSTony Nguyen 	/* Search for a flow profile that has matching headers, hash fields
19892c61054cSTony Nguyen 	 * and has the input VSI associated to it. If found, no further
19902c61054cSTony Nguyen 	 * operations required and exit.
19912c61054cSTony Nguyen 	 */
19922c61054cSTony Nguyen 	prof = ice_flow_find_prof_conds(hw, blk, ICE_FLOW_RX, segs, segs_cnt,
19932c61054cSTony Nguyen 					vsi_handle,
19942c61054cSTony Nguyen 					ICE_FLOW_FIND_PROF_CHK_FLDS |
19952c61054cSTony Nguyen 					ICE_FLOW_FIND_PROF_CHK_VSI);
19962c61054cSTony Nguyen 	if (prof)
19972c61054cSTony Nguyen 		goto exit;
19982c61054cSTony Nguyen 
19992c61054cSTony Nguyen 	/* Check if a flow profile exists with the same protocol headers and
20002c61054cSTony Nguyen 	 * associated with the input VSI. If so disassociate the VSI from
20012c61054cSTony Nguyen 	 * this profile. The VSI will be added to a new profile created with
20022c61054cSTony Nguyen 	 * the protocol header and new hash field configuration.
20032c61054cSTony Nguyen 	 */
20042c61054cSTony Nguyen 	prof = ice_flow_find_prof_conds(hw, blk, ICE_FLOW_RX, segs, segs_cnt,
20052c61054cSTony Nguyen 					vsi_handle, ICE_FLOW_FIND_PROF_CHK_VSI);
20062c61054cSTony Nguyen 	if (prof) {
20072c61054cSTony Nguyen 		status = ice_flow_disassoc_prof(hw, blk, prof, vsi_handle);
20082c61054cSTony Nguyen 		if (!status)
20092c61054cSTony Nguyen 			ice_rem_rss_list(hw, vsi_handle, prof);
20102c61054cSTony Nguyen 		else
20112c61054cSTony Nguyen 			goto exit;
20122c61054cSTony Nguyen 
20132c61054cSTony Nguyen 		/* Remove profile if it has no VSIs associated */
20142c61054cSTony Nguyen 		if (bitmap_empty(prof->vsis, ICE_MAX_VSI)) {
20152c61054cSTony Nguyen 			status = ice_flow_rem_prof(hw, blk, prof->id);
20162c61054cSTony Nguyen 			if (status)
20172c61054cSTony Nguyen 				goto exit;
20182c61054cSTony Nguyen 		}
20192c61054cSTony Nguyen 	}
20202c61054cSTony Nguyen 
20212c61054cSTony Nguyen 	/* Search for a profile that has same match fields only. If this
20222c61054cSTony Nguyen 	 * exists then associate the VSI to this profile.
20232c61054cSTony Nguyen 	 */
20242c61054cSTony Nguyen 	prof = ice_flow_find_prof_conds(hw, blk, ICE_FLOW_RX, segs, segs_cnt,
20252c61054cSTony Nguyen 					vsi_handle,
20262c61054cSTony Nguyen 					ICE_FLOW_FIND_PROF_CHK_FLDS);
20272c61054cSTony Nguyen 	if (prof) {
20282c61054cSTony Nguyen 		status = ice_flow_assoc_prof(hw, blk, prof, vsi_handle);
20292c61054cSTony Nguyen 		if (!status)
20302c61054cSTony Nguyen 			status = ice_add_rss_list(hw, vsi_handle, prof);
20312c61054cSTony Nguyen 		goto exit;
20322c61054cSTony Nguyen 	}
20332c61054cSTony Nguyen 
203431ad4e4eSTony Nguyen 	/* Create a new flow profile with generated profile and packet
203531ad4e4eSTony Nguyen 	 * segment information.
203631ad4e4eSTony Nguyen 	 */
2037451f2c44STony Nguyen 	status = ice_flow_add_prof(hw, blk, ICE_FLOW_RX,
203831ad4e4eSTony Nguyen 				   ICE_FLOW_GEN_PROFID(hashed_flds,
203931ad4e4eSTony Nguyen 						       segs[segs_cnt - 1].hdrs,
204031ad4e4eSTony Nguyen 						       segs_cnt),
2041451f2c44STony Nguyen 				   segs, segs_cnt, &prof);
2042451f2c44STony Nguyen 	if (status)
2043451f2c44STony Nguyen 		goto exit;
2044451f2c44STony Nguyen 
2045451f2c44STony Nguyen 	status = ice_flow_assoc_prof(hw, blk, prof, vsi_handle);
20462c61054cSTony Nguyen 	/* If association to a new flow profile failed then this profile can
20472c61054cSTony Nguyen 	 * be removed.
20482c61054cSTony Nguyen 	 */
20492c61054cSTony Nguyen 	if (status) {
20502c61054cSTony Nguyen 		ice_flow_rem_prof(hw, blk, prof->id);
20512c61054cSTony Nguyen 		goto exit;
20522c61054cSTony Nguyen 	}
20532c61054cSTony Nguyen 
20542c61054cSTony Nguyen 	status = ice_add_rss_list(hw, vsi_handle, prof);
205531ad4e4eSTony Nguyen 
205631ad4e4eSTony Nguyen exit:
2057c90ed40cSTony Nguyen 	kfree(segs);
2058c90ed40cSTony Nguyen 	return status;
2059c90ed40cSTony Nguyen }
2060c90ed40cSTony Nguyen 
2061c90ed40cSTony Nguyen /**
2062c90ed40cSTony Nguyen  * ice_add_rss_cfg - add an RSS configuration with specified hashed fields
2063c90ed40cSTony Nguyen  * @hw: pointer to the hardware structure
2064c90ed40cSTony Nguyen  * @vsi_handle: software VSI handle
2065c90ed40cSTony Nguyen  * @hashed_flds: hash bit fields (ICE_FLOW_HASH_*) to configure
2066c90ed40cSTony Nguyen  * @addl_hdrs: protocol header fields
2067c90ed40cSTony Nguyen  *
2068c90ed40cSTony Nguyen  * This function will generate a flow profile based on fields associated with
2069c90ed40cSTony Nguyen  * the input fields to hash on, the flow type and use the VSI number to add
2070c90ed40cSTony Nguyen  * a flow entry to the profile.
2071c90ed40cSTony Nguyen  */
2072c90ed40cSTony Nguyen enum ice_status
2073c90ed40cSTony Nguyen ice_add_rss_cfg(struct ice_hw *hw, u16 vsi_handle, u64 hashed_flds,
2074c90ed40cSTony Nguyen 		u32 addl_hdrs)
2075c90ed40cSTony Nguyen {
2076c90ed40cSTony Nguyen 	enum ice_status status;
2077c90ed40cSTony Nguyen 
2078c90ed40cSTony Nguyen 	if (hashed_flds == ICE_HASH_INVALID ||
2079c90ed40cSTony Nguyen 	    !ice_is_vsi_valid(hw, vsi_handle))
2080c90ed40cSTony Nguyen 		return ICE_ERR_PARAM;
2081c90ed40cSTony Nguyen 
2082c90ed40cSTony Nguyen 	mutex_lock(&hw->rss_locks);
2083451f2c44STony Nguyen 	status = ice_add_rss_cfg_sync(hw, vsi_handle, hashed_flds, addl_hdrs,
2084c90ed40cSTony Nguyen 				      ICE_RSS_OUTER_HEADERS);
2085a4e82a81STony Nguyen 	if (!status)
2086a4e82a81STony Nguyen 		status = ice_add_rss_cfg_sync(hw, vsi_handle, hashed_flds,
2087a4e82a81STony Nguyen 					      addl_hdrs, ICE_RSS_INNER_HEADERS);
2088c90ed40cSTony Nguyen 	mutex_unlock(&hw->rss_locks);
2089c90ed40cSTony Nguyen 
2090c90ed40cSTony Nguyen 	return status;
2091c90ed40cSTony Nguyen }
2092c90ed40cSTony Nguyen 
20931c01c8c6SMd Fahad Iqbal Polash /* Mapping of AVF hash bit fields to an L3-L4 hash combination.
20941c01c8c6SMd Fahad Iqbal Polash  * As the ice_flow_avf_hdr_field represent individual bit shifts in a hash,
20951c01c8c6SMd Fahad Iqbal Polash  * convert its values to their appropriate flow L3, L4 values.
20961c01c8c6SMd Fahad Iqbal Polash  */
20971c01c8c6SMd Fahad Iqbal Polash #define ICE_FLOW_AVF_RSS_IPV4_MASKS \
20981c01c8c6SMd Fahad Iqbal Polash 	(BIT_ULL(ICE_AVF_FLOW_FIELD_IPV4_OTHER) | \
20991c01c8c6SMd Fahad Iqbal Polash 	 BIT_ULL(ICE_AVF_FLOW_FIELD_FRAG_IPV4))
21001c01c8c6SMd Fahad Iqbal Polash #define ICE_FLOW_AVF_RSS_TCP_IPV4_MASKS \
21011c01c8c6SMd Fahad Iqbal Polash 	(BIT_ULL(ICE_AVF_FLOW_FIELD_IPV4_TCP_SYN_NO_ACK) | \
21021c01c8c6SMd Fahad Iqbal Polash 	 BIT_ULL(ICE_AVF_FLOW_FIELD_IPV4_TCP))
21031c01c8c6SMd Fahad Iqbal Polash #define ICE_FLOW_AVF_RSS_UDP_IPV4_MASKS \
21041c01c8c6SMd Fahad Iqbal Polash 	(BIT_ULL(ICE_AVF_FLOW_FIELD_UNICAST_IPV4_UDP) | \
21051c01c8c6SMd Fahad Iqbal Polash 	 BIT_ULL(ICE_AVF_FLOW_FIELD_MULTICAST_IPV4_UDP) | \
21061c01c8c6SMd Fahad Iqbal Polash 	 BIT_ULL(ICE_AVF_FLOW_FIELD_IPV4_UDP))
21071c01c8c6SMd Fahad Iqbal Polash #define ICE_FLOW_AVF_RSS_ALL_IPV4_MASKS \
21081c01c8c6SMd Fahad Iqbal Polash 	(ICE_FLOW_AVF_RSS_TCP_IPV4_MASKS | ICE_FLOW_AVF_RSS_UDP_IPV4_MASKS | \
21091c01c8c6SMd Fahad Iqbal Polash 	 ICE_FLOW_AVF_RSS_IPV4_MASKS | BIT_ULL(ICE_AVF_FLOW_FIELD_IPV4_SCTP))
21101c01c8c6SMd Fahad Iqbal Polash 
21111c01c8c6SMd Fahad Iqbal Polash #define ICE_FLOW_AVF_RSS_IPV6_MASKS \
21121c01c8c6SMd Fahad Iqbal Polash 	(BIT_ULL(ICE_AVF_FLOW_FIELD_IPV6_OTHER) | \
21131c01c8c6SMd Fahad Iqbal Polash 	 BIT_ULL(ICE_AVF_FLOW_FIELD_FRAG_IPV6))
21141c01c8c6SMd Fahad Iqbal Polash #define ICE_FLOW_AVF_RSS_UDP_IPV6_MASKS \
21151c01c8c6SMd Fahad Iqbal Polash 	(BIT_ULL(ICE_AVF_FLOW_FIELD_UNICAST_IPV6_UDP) | \
21161c01c8c6SMd Fahad Iqbal Polash 	 BIT_ULL(ICE_AVF_FLOW_FIELD_MULTICAST_IPV6_UDP) | \
21171c01c8c6SMd Fahad Iqbal Polash 	 BIT_ULL(ICE_AVF_FLOW_FIELD_IPV6_UDP))
21181c01c8c6SMd Fahad Iqbal Polash #define ICE_FLOW_AVF_RSS_TCP_IPV6_MASKS \
21191c01c8c6SMd Fahad Iqbal Polash 	(BIT_ULL(ICE_AVF_FLOW_FIELD_IPV6_TCP_SYN_NO_ACK) | \
21201c01c8c6SMd Fahad Iqbal Polash 	 BIT_ULL(ICE_AVF_FLOW_FIELD_IPV6_TCP))
21211c01c8c6SMd Fahad Iqbal Polash #define ICE_FLOW_AVF_RSS_ALL_IPV6_MASKS \
21221c01c8c6SMd Fahad Iqbal Polash 	(ICE_FLOW_AVF_RSS_TCP_IPV6_MASKS | ICE_FLOW_AVF_RSS_UDP_IPV6_MASKS | \
21231c01c8c6SMd Fahad Iqbal Polash 	 ICE_FLOW_AVF_RSS_IPV6_MASKS | BIT_ULL(ICE_AVF_FLOW_FIELD_IPV6_SCTP))
21241c01c8c6SMd Fahad Iqbal Polash 
21251c01c8c6SMd Fahad Iqbal Polash /**
21261c01c8c6SMd Fahad Iqbal Polash  * ice_add_avf_rss_cfg - add an RSS configuration for AVF driver
21271c01c8c6SMd Fahad Iqbal Polash  * @hw: pointer to the hardware structure
21281c01c8c6SMd Fahad Iqbal Polash  * @vsi_handle: software VSI handle
21291c01c8c6SMd Fahad Iqbal Polash  * @avf_hash: hash bit fields (ICE_AVF_FLOW_FIELD_*) to configure
21301c01c8c6SMd Fahad Iqbal Polash  *
21311c01c8c6SMd Fahad Iqbal Polash  * This function will take the hash bitmap provided by the AVF driver via a
21321c01c8c6SMd Fahad Iqbal Polash  * message, convert it to ICE-compatible values, and configure RSS flow
21331c01c8c6SMd Fahad Iqbal Polash  * profiles.
21341c01c8c6SMd Fahad Iqbal Polash  */
21351c01c8c6SMd Fahad Iqbal Polash enum ice_status
21361c01c8c6SMd Fahad Iqbal Polash ice_add_avf_rss_cfg(struct ice_hw *hw, u16 vsi_handle, u64 avf_hash)
21371c01c8c6SMd Fahad Iqbal Polash {
21381c01c8c6SMd Fahad Iqbal Polash 	enum ice_status status = 0;
21391c01c8c6SMd Fahad Iqbal Polash 	u64 hash_flds;
21401c01c8c6SMd Fahad Iqbal Polash 
21411c01c8c6SMd Fahad Iqbal Polash 	if (avf_hash == ICE_AVF_FLOW_FIELD_INVALID ||
21421c01c8c6SMd Fahad Iqbal Polash 	    !ice_is_vsi_valid(hw, vsi_handle))
21431c01c8c6SMd Fahad Iqbal Polash 		return ICE_ERR_PARAM;
21441c01c8c6SMd Fahad Iqbal Polash 
21451c01c8c6SMd Fahad Iqbal Polash 	/* Make sure no unsupported bits are specified */
21461c01c8c6SMd Fahad Iqbal Polash 	if (avf_hash & ~(ICE_FLOW_AVF_RSS_ALL_IPV4_MASKS |
21471c01c8c6SMd Fahad Iqbal Polash 			 ICE_FLOW_AVF_RSS_ALL_IPV6_MASKS))
21481c01c8c6SMd Fahad Iqbal Polash 		return ICE_ERR_CFG;
21491c01c8c6SMd Fahad Iqbal Polash 
21501c01c8c6SMd Fahad Iqbal Polash 	hash_flds = avf_hash;
21511c01c8c6SMd Fahad Iqbal Polash 
21521c01c8c6SMd Fahad Iqbal Polash 	/* Always create an L3 RSS configuration for any L4 RSS configuration */
21531c01c8c6SMd Fahad Iqbal Polash 	if (hash_flds & ICE_FLOW_AVF_RSS_ALL_IPV4_MASKS)
21541c01c8c6SMd Fahad Iqbal Polash 		hash_flds |= ICE_FLOW_AVF_RSS_IPV4_MASKS;
21551c01c8c6SMd Fahad Iqbal Polash 
21561c01c8c6SMd Fahad Iqbal Polash 	if (hash_flds & ICE_FLOW_AVF_RSS_ALL_IPV6_MASKS)
21571c01c8c6SMd Fahad Iqbal Polash 		hash_flds |= ICE_FLOW_AVF_RSS_IPV6_MASKS;
21581c01c8c6SMd Fahad Iqbal Polash 
21591c01c8c6SMd Fahad Iqbal Polash 	/* Create the corresponding RSS configuration for each valid hash bit */
21601c01c8c6SMd Fahad Iqbal Polash 	while (hash_flds) {
21611c01c8c6SMd Fahad Iqbal Polash 		u64 rss_hash = ICE_HASH_INVALID;
21621c01c8c6SMd Fahad Iqbal Polash 
21631c01c8c6SMd Fahad Iqbal Polash 		if (hash_flds & ICE_FLOW_AVF_RSS_ALL_IPV4_MASKS) {
21641c01c8c6SMd Fahad Iqbal Polash 			if (hash_flds & ICE_FLOW_AVF_RSS_IPV4_MASKS) {
21651c01c8c6SMd Fahad Iqbal Polash 				rss_hash = ICE_FLOW_HASH_IPV4;
21661c01c8c6SMd Fahad Iqbal Polash 				hash_flds &= ~ICE_FLOW_AVF_RSS_IPV4_MASKS;
21671c01c8c6SMd Fahad Iqbal Polash 			} else if (hash_flds &
21681c01c8c6SMd Fahad Iqbal Polash 				   ICE_FLOW_AVF_RSS_TCP_IPV4_MASKS) {
21691c01c8c6SMd Fahad Iqbal Polash 				rss_hash = ICE_FLOW_HASH_IPV4 |
21701c01c8c6SMd Fahad Iqbal Polash 					ICE_FLOW_HASH_TCP_PORT;
21711c01c8c6SMd Fahad Iqbal Polash 				hash_flds &= ~ICE_FLOW_AVF_RSS_TCP_IPV4_MASKS;
21721c01c8c6SMd Fahad Iqbal Polash 			} else if (hash_flds &
21731c01c8c6SMd Fahad Iqbal Polash 				   ICE_FLOW_AVF_RSS_UDP_IPV4_MASKS) {
21741c01c8c6SMd Fahad Iqbal Polash 				rss_hash = ICE_FLOW_HASH_IPV4 |
21751c01c8c6SMd Fahad Iqbal Polash 					ICE_FLOW_HASH_UDP_PORT;
21761c01c8c6SMd Fahad Iqbal Polash 				hash_flds &= ~ICE_FLOW_AVF_RSS_UDP_IPV4_MASKS;
21771c01c8c6SMd Fahad Iqbal Polash 			} else if (hash_flds &
21781c01c8c6SMd Fahad Iqbal Polash 				   BIT_ULL(ICE_AVF_FLOW_FIELD_IPV4_SCTP)) {
21791c01c8c6SMd Fahad Iqbal Polash 				rss_hash = ICE_FLOW_HASH_IPV4 |
21801c01c8c6SMd Fahad Iqbal Polash 					ICE_FLOW_HASH_SCTP_PORT;
21811c01c8c6SMd Fahad Iqbal Polash 				hash_flds &=
21821c01c8c6SMd Fahad Iqbal Polash 					~BIT_ULL(ICE_AVF_FLOW_FIELD_IPV4_SCTP);
21831c01c8c6SMd Fahad Iqbal Polash 			}
21841c01c8c6SMd Fahad Iqbal Polash 		} else if (hash_flds & ICE_FLOW_AVF_RSS_ALL_IPV6_MASKS) {
21851c01c8c6SMd Fahad Iqbal Polash 			if (hash_flds & ICE_FLOW_AVF_RSS_IPV6_MASKS) {
21861c01c8c6SMd Fahad Iqbal Polash 				rss_hash = ICE_FLOW_HASH_IPV6;
21871c01c8c6SMd Fahad Iqbal Polash 				hash_flds &= ~ICE_FLOW_AVF_RSS_IPV6_MASKS;
21881c01c8c6SMd Fahad Iqbal Polash 			} else if (hash_flds &
21891c01c8c6SMd Fahad Iqbal Polash 				   ICE_FLOW_AVF_RSS_TCP_IPV6_MASKS) {
21901c01c8c6SMd Fahad Iqbal Polash 				rss_hash = ICE_FLOW_HASH_IPV6 |
21911c01c8c6SMd Fahad Iqbal Polash 					ICE_FLOW_HASH_TCP_PORT;
21921c01c8c6SMd Fahad Iqbal Polash 				hash_flds &= ~ICE_FLOW_AVF_RSS_TCP_IPV6_MASKS;
21931c01c8c6SMd Fahad Iqbal Polash 			} else if (hash_flds &
21941c01c8c6SMd Fahad Iqbal Polash 				   ICE_FLOW_AVF_RSS_UDP_IPV6_MASKS) {
21951c01c8c6SMd Fahad Iqbal Polash 				rss_hash = ICE_FLOW_HASH_IPV6 |
21961c01c8c6SMd Fahad Iqbal Polash 					ICE_FLOW_HASH_UDP_PORT;
21971c01c8c6SMd Fahad Iqbal Polash 				hash_flds &= ~ICE_FLOW_AVF_RSS_UDP_IPV6_MASKS;
21981c01c8c6SMd Fahad Iqbal Polash 			} else if (hash_flds &
21991c01c8c6SMd Fahad Iqbal Polash 				   BIT_ULL(ICE_AVF_FLOW_FIELD_IPV6_SCTP)) {
22001c01c8c6SMd Fahad Iqbal Polash 				rss_hash = ICE_FLOW_HASH_IPV6 |
22011c01c8c6SMd Fahad Iqbal Polash 					ICE_FLOW_HASH_SCTP_PORT;
22021c01c8c6SMd Fahad Iqbal Polash 				hash_flds &=
22031c01c8c6SMd Fahad Iqbal Polash 					~BIT_ULL(ICE_AVF_FLOW_FIELD_IPV6_SCTP);
22041c01c8c6SMd Fahad Iqbal Polash 			}
22051c01c8c6SMd Fahad Iqbal Polash 		}
22061c01c8c6SMd Fahad Iqbal Polash 
22071c01c8c6SMd Fahad Iqbal Polash 		if (rss_hash == ICE_HASH_INVALID)
22081c01c8c6SMd Fahad Iqbal Polash 			return ICE_ERR_OUT_OF_RANGE;
22091c01c8c6SMd Fahad Iqbal Polash 
22101c01c8c6SMd Fahad Iqbal Polash 		status = ice_add_rss_cfg(hw, vsi_handle, rss_hash,
22111c01c8c6SMd Fahad Iqbal Polash 					 ICE_FLOW_SEG_HDR_NONE);
22121c01c8c6SMd Fahad Iqbal Polash 		if (status)
22131c01c8c6SMd Fahad Iqbal Polash 			break;
22141c01c8c6SMd Fahad Iqbal Polash 	}
22151c01c8c6SMd Fahad Iqbal Polash 
22161c01c8c6SMd Fahad Iqbal Polash 	return status;
22171c01c8c6SMd Fahad Iqbal Polash }
22181c01c8c6SMd Fahad Iqbal Polash 
2219c90ed40cSTony Nguyen /**
2220c90ed40cSTony Nguyen  * ice_replay_rss_cfg - replay RSS configurations associated with VSI
2221c90ed40cSTony Nguyen  * @hw: pointer to the hardware structure
2222c90ed40cSTony Nguyen  * @vsi_handle: software VSI handle
2223c90ed40cSTony Nguyen  */
2224c90ed40cSTony Nguyen enum ice_status ice_replay_rss_cfg(struct ice_hw *hw, u16 vsi_handle)
2225c90ed40cSTony Nguyen {
2226c90ed40cSTony Nguyen 	enum ice_status status = 0;
2227c90ed40cSTony Nguyen 	struct ice_rss_cfg *r;
2228c90ed40cSTony Nguyen 
2229c90ed40cSTony Nguyen 	if (!ice_is_vsi_valid(hw, vsi_handle))
2230c90ed40cSTony Nguyen 		return ICE_ERR_PARAM;
2231c90ed40cSTony Nguyen 
2232c90ed40cSTony Nguyen 	mutex_lock(&hw->rss_locks);
2233c90ed40cSTony Nguyen 	list_for_each_entry(r, &hw->rss_list_head, l_entry) {
2234c90ed40cSTony Nguyen 		if (test_bit(vsi_handle, r->vsis)) {
2235451f2c44STony Nguyen 			status = ice_add_rss_cfg_sync(hw, vsi_handle,
2236451f2c44STony Nguyen 						      r->hashed_flds,
2237c90ed40cSTony Nguyen 						      r->packet_hdr,
2238c90ed40cSTony Nguyen 						      ICE_RSS_OUTER_HEADERS);
2239c90ed40cSTony Nguyen 			if (status)
2240c90ed40cSTony Nguyen 				break;
2241a4e82a81STony Nguyen 			status = ice_add_rss_cfg_sync(hw, vsi_handle,
2242a4e82a81STony Nguyen 						      r->hashed_flds,
2243a4e82a81STony Nguyen 						      r->packet_hdr,
2244a4e82a81STony Nguyen 						      ICE_RSS_INNER_HEADERS);
2245a4e82a81STony Nguyen 			if (status)
2246a4e82a81STony Nguyen 				break;
2247c90ed40cSTony Nguyen 		}
2248c90ed40cSTony Nguyen 	}
2249c90ed40cSTony Nguyen 	mutex_unlock(&hw->rss_locks);
2250c90ed40cSTony Nguyen 
2251c90ed40cSTony Nguyen 	return status;
2252c90ed40cSTony Nguyen }
22536876fb64SMd Fahad Iqbal Polash 
22546876fb64SMd Fahad Iqbal Polash /**
22556876fb64SMd Fahad Iqbal Polash  * ice_get_rss_cfg - returns hashed fields for the given header types
22566876fb64SMd Fahad Iqbal Polash  * @hw: pointer to the hardware structure
22576876fb64SMd Fahad Iqbal Polash  * @vsi_handle: software VSI handle
22586876fb64SMd Fahad Iqbal Polash  * @hdrs: protocol header type
22596876fb64SMd Fahad Iqbal Polash  *
22606876fb64SMd Fahad Iqbal Polash  * This function will return the match fields of the first instance of flow
22616876fb64SMd Fahad Iqbal Polash  * profile having the given header types and containing input VSI
22626876fb64SMd Fahad Iqbal Polash  */
22636876fb64SMd Fahad Iqbal Polash u64 ice_get_rss_cfg(struct ice_hw *hw, u16 vsi_handle, u32 hdrs)
22646876fb64SMd Fahad Iqbal Polash {
2265cdedbab9SVignesh Sridhar 	u64 rss_hash = ICE_HASH_INVALID;
2266cdedbab9SVignesh Sridhar 	struct ice_rss_cfg *r;
22676876fb64SMd Fahad Iqbal Polash 
22686876fb64SMd Fahad Iqbal Polash 	/* verify if the protocol header is non zero and VSI is valid */
22696876fb64SMd Fahad Iqbal Polash 	if (hdrs == ICE_FLOW_SEG_HDR_NONE || !ice_is_vsi_valid(hw, vsi_handle))
22706876fb64SMd Fahad Iqbal Polash 		return ICE_HASH_INVALID;
22716876fb64SMd Fahad Iqbal Polash 
22726876fb64SMd Fahad Iqbal Polash 	mutex_lock(&hw->rss_locks);
22736876fb64SMd Fahad Iqbal Polash 	list_for_each_entry(r, &hw->rss_list_head, l_entry)
22746876fb64SMd Fahad Iqbal Polash 		if (test_bit(vsi_handle, r->vsis) &&
22756876fb64SMd Fahad Iqbal Polash 		    r->packet_hdr == hdrs) {
2276cdedbab9SVignesh Sridhar 			rss_hash = r->hashed_flds;
22776876fb64SMd Fahad Iqbal Polash 			break;
22786876fb64SMd Fahad Iqbal Polash 		}
22796876fb64SMd Fahad Iqbal Polash 	mutex_unlock(&hw->rss_locks);
22806876fb64SMd Fahad Iqbal Polash 
2281cdedbab9SVignesh Sridhar 	return rss_hash;
22826876fb64SMd Fahad Iqbal Polash }
2283