xref: /freebsd/sys/dev/ice/ice_flow.c (revision f2635e844dd138ac9dfba676f27d41750049af26)
171d10453SEric Joyner /* SPDX-License-Identifier: BSD-3-Clause */
2015f8cc5SEric Joyner /*  Copyright (c) 2024, Intel Corporation
371d10453SEric Joyner  *  All rights reserved.
471d10453SEric Joyner  *
571d10453SEric Joyner  *  Redistribution and use in source and binary forms, with or without
671d10453SEric Joyner  *  modification, are permitted provided that the following conditions are met:
771d10453SEric Joyner  *
871d10453SEric Joyner  *   1. Redistributions of source code must retain the above copyright notice,
971d10453SEric Joyner  *      this list of conditions and the following disclaimer.
1071d10453SEric Joyner  *
1171d10453SEric Joyner  *   2. Redistributions in binary form must reproduce the above copyright
1271d10453SEric Joyner  *      notice, this list of conditions and the following disclaimer in the
1371d10453SEric Joyner  *      documentation and/or other materials provided with the distribution.
1471d10453SEric Joyner  *
1571d10453SEric Joyner  *   3. Neither the name of the Intel Corporation nor the names of its
1671d10453SEric Joyner  *      contributors may be used to endorse or promote products derived from
1771d10453SEric Joyner  *      this software without specific prior written permission.
1871d10453SEric Joyner  *
1971d10453SEric Joyner  *  THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
2071d10453SEric Joyner  *  AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
2171d10453SEric Joyner  *  IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
2271d10453SEric Joyner  *  ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE
2371d10453SEric Joyner  *  LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
2471d10453SEric Joyner  *  CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
2571d10453SEric Joyner  *  SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
2671d10453SEric Joyner  *  INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
2771d10453SEric Joyner  *  CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
2871d10453SEric Joyner  *  ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
2971d10453SEric Joyner  *  POSSIBILITY OF SUCH DAMAGE.
3071d10453SEric Joyner  */
3171d10453SEric Joyner 
3271d10453SEric Joyner #include "ice_common.h"
3371d10453SEric Joyner #include "ice_flow.h"
3471d10453SEric Joyner 
3571d10453SEric Joyner /* Size of known protocol header fields */
3671d10453SEric Joyner #define ICE_FLOW_FLD_SZ_ETH_TYPE	2
3771d10453SEric Joyner #define ICE_FLOW_FLD_SZ_VLAN		2
3871d10453SEric Joyner #define ICE_FLOW_FLD_SZ_IPV4_ADDR	4
3971d10453SEric Joyner #define ICE_FLOW_FLD_SZ_IPV6_ADDR	16
4071d10453SEric Joyner #define ICE_FLOW_FLD_SZ_IP_DSCP		1
4171d10453SEric Joyner #define ICE_FLOW_FLD_SZ_IP_TTL		1
4271d10453SEric Joyner #define ICE_FLOW_FLD_SZ_IP_PROT		1
4371d10453SEric Joyner #define ICE_FLOW_FLD_SZ_PORT		2
4471d10453SEric Joyner #define ICE_FLOW_FLD_SZ_TCP_FLAGS	1
4571d10453SEric Joyner #define ICE_FLOW_FLD_SZ_ICMP_TYPE	1
4671d10453SEric Joyner #define ICE_FLOW_FLD_SZ_ICMP_CODE	1
4771d10453SEric Joyner #define ICE_FLOW_FLD_SZ_ARP_OPER	2
4871d10453SEric Joyner #define ICE_FLOW_FLD_SZ_GRE_KEYID	4
4971d10453SEric Joyner 
5071d10453SEric Joyner /* Describe properties of a protocol header field */
5171d10453SEric Joyner struct ice_flow_field_info {
5271d10453SEric Joyner 	enum ice_flow_seg_hdr hdr;
5371d10453SEric Joyner 	s16 off;	/* Offset from start of a protocol header, in bits */
5471d10453SEric Joyner 	u16 size;	/* Size of fields in bits */
5571d10453SEric Joyner };
5671d10453SEric Joyner 
5771d10453SEric Joyner #define ICE_FLOW_FLD_INFO(_hdr, _offset_bytes, _size_bytes) { \
5871d10453SEric Joyner 	.hdr = _hdr, \
5971d10453SEric Joyner 	.off = (_offset_bytes) * BITS_PER_BYTE, \
6071d10453SEric Joyner 	.size = (_size_bytes) * BITS_PER_BYTE, \
6171d10453SEric Joyner }
6271d10453SEric Joyner 
6371d10453SEric Joyner /* Table containing properties of supported protocol header fields */
6471d10453SEric Joyner static const
6571d10453SEric Joyner struct ice_flow_field_info ice_flds_info[ICE_FLOW_FIELD_IDX_MAX] = {
6671d10453SEric Joyner 	/* Ether */
6771d10453SEric Joyner 	/* ICE_FLOW_FIELD_IDX_ETH_DA */
6871d10453SEric Joyner 	ICE_FLOW_FLD_INFO(ICE_FLOW_SEG_HDR_ETH, 0, ETH_ALEN),
6971d10453SEric Joyner 	/* ICE_FLOW_FIELD_IDX_ETH_SA */
7071d10453SEric Joyner 	ICE_FLOW_FLD_INFO(ICE_FLOW_SEG_HDR_ETH, ETH_ALEN, ETH_ALEN),
7171d10453SEric Joyner 	/* ICE_FLOW_FIELD_IDX_S_VLAN */
7271d10453SEric Joyner 	ICE_FLOW_FLD_INFO(ICE_FLOW_SEG_HDR_VLAN, 12, ICE_FLOW_FLD_SZ_VLAN),
7371d10453SEric Joyner 	/* ICE_FLOW_FIELD_IDX_C_VLAN */
7471d10453SEric Joyner 	ICE_FLOW_FLD_INFO(ICE_FLOW_SEG_HDR_VLAN, 14, ICE_FLOW_FLD_SZ_VLAN),
7571d10453SEric Joyner 	/* ICE_FLOW_FIELD_IDX_ETH_TYPE */
767d7af7f8SEric Joyner 	ICE_FLOW_FLD_INFO(ICE_FLOW_SEG_HDR_ETH, 0, ICE_FLOW_FLD_SZ_ETH_TYPE),
7771d10453SEric Joyner 	/* IPv4 / IPv6 */
7871d10453SEric Joyner 	/* ICE_FLOW_FIELD_IDX_IPV4_DSCP */
7971d10453SEric Joyner 	ICE_FLOW_FLD_INFO(ICE_FLOW_SEG_HDR_IPV4, 1, ICE_FLOW_FLD_SZ_IP_DSCP),
8071d10453SEric Joyner 	/* ICE_FLOW_FIELD_IDX_IPV6_DSCP */
8171d10453SEric Joyner 	ICE_FLOW_FLD_INFO(ICE_FLOW_SEG_HDR_IPV6, 0, ICE_FLOW_FLD_SZ_IP_DSCP),
8271d10453SEric Joyner 	/* ICE_FLOW_FIELD_IDX_IPV4_TTL */
8371d10453SEric Joyner 	ICE_FLOW_FLD_INFO(ICE_FLOW_SEG_HDR_NONE, 8, ICE_FLOW_FLD_SZ_IP_TTL),
8471d10453SEric Joyner 	/* ICE_FLOW_FIELD_IDX_IPV4_PROT */
8571d10453SEric Joyner 	ICE_FLOW_FLD_INFO(ICE_FLOW_SEG_HDR_NONE, 9, ICE_FLOW_FLD_SZ_IP_PROT),
8671d10453SEric Joyner 	/* ICE_FLOW_FIELD_IDX_IPV6_TTL */
8771d10453SEric Joyner 	ICE_FLOW_FLD_INFO(ICE_FLOW_SEG_HDR_NONE, 7, ICE_FLOW_FLD_SZ_IP_TTL),
8871d10453SEric Joyner 	/* ICE_FLOW_FIELD_IDX_IPV4_PROT */
8971d10453SEric Joyner 	ICE_FLOW_FLD_INFO(ICE_FLOW_SEG_HDR_NONE, 6, ICE_FLOW_FLD_SZ_IP_PROT),
9071d10453SEric Joyner 	/* ICE_FLOW_FIELD_IDX_IPV4_SA */
9171d10453SEric Joyner 	ICE_FLOW_FLD_INFO(ICE_FLOW_SEG_HDR_IPV4, 12, ICE_FLOW_FLD_SZ_IPV4_ADDR),
9271d10453SEric Joyner 	/* ICE_FLOW_FIELD_IDX_IPV4_DA */
9371d10453SEric Joyner 	ICE_FLOW_FLD_INFO(ICE_FLOW_SEG_HDR_IPV4, 16, ICE_FLOW_FLD_SZ_IPV4_ADDR),
9471d10453SEric Joyner 	/* ICE_FLOW_FIELD_IDX_IPV6_SA */
9571d10453SEric Joyner 	ICE_FLOW_FLD_INFO(ICE_FLOW_SEG_HDR_IPV6, 8, ICE_FLOW_FLD_SZ_IPV6_ADDR),
9671d10453SEric Joyner 	/* ICE_FLOW_FIELD_IDX_IPV6_DA */
9771d10453SEric Joyner 	ICE_FLOW_FLD_INFO(ICE_FLOW_SEG_HDR_IPV6, 24, ICE_FLOW_FLD_SZ_IPV6_ADDR),
9871d10453SEric Joyner 	/* Transport */
9971d10453SEric Joyner 	/* ICE_FLOW_FIELD_IDX_TCP_SRC_PORT */
10071d10453SEric Joyner 	ICE_FLOW_FLD_INFO(ICE_FLOW_SEG_HDR_TCP, 0, ICE_FLOW_FLD_SZ_PORT),
10171d10453SEric Joyner 	/* ICE_FLOW_FIELD_IDX_TCP_DST_PORT */
10271d10453SEric Joyner 	ICE_FLOW_FLD_INFO(ICE_FLOW_SEG_HDR_TCP, 2, ICE_FLOW_FLD_SZ_PORT),
10371d10453SEric Joyner 	/* ICE_FLOW_FIELD_IDX_UDP_SRC_PORT */
10471d10453SEric Joyner 	ICE_FLOW_FLD_INFO(ICE_FLOW_SEG_HDR_UDP, 0, ICE_FLOW_FLD_SZ_PORT),
10571d10453SEric Joyner 	/* ICE_FLOW_FIELD_IDX_UDP_DST_PORT */
10671d10453SEric Joyner 	ICE_FLOW_FLD_INFO(ICE_FLOW_SEG_HDR_UDP, 2, ICE_FLOW_FLD_SZ_PORT),
10771d10453SEric Joyner 	/* ICE_FLOW_FIELD_IDX_SCTP_SRC_PORT */
10871d10453SEric Joyner 	ICE_FLOW_FLD_INFO(ICE_FLOW_SEG_HDR_SCTP, 0, ICE_FLOW_FLD_SZ_PORT),
10971d10453SEric Joyner 	/* ICE_FLOW_FIELD_IDX_SCTP_DST_PORT */
11071d10453SEric Joyner 	ICE_FLOW_FLD_INFO(ICE_FLOW_SEG_HDR_SCTP, 2, ICE_FLOW_FLD_SZ_PORT),
11171d10453SEric Joyner 	/* ICE_FLOW_FIELD_IDX_TCP_FLAGS */
11271d10453SEric Joyner 	ICE_FLOW_FLD_INFO(ICE_FLOW_SEG_HDR_TCP, 13, ICE_FLOW_FLD_SZ_TCP_FLAGS),
11371d10453SEric Joyner 	/* ARP */
11471d10453SEric Joyner 	/* ICE_FLOW_FIELD_IDX_ARP_SIP */
11571d10453SEric Joyner 	ICE_FLOW_FLD_INFO(ICE_FLOW_SEG_HDR_ARP, 14, ICE_FLOW_FLD_SZ_IPV4_ADDR),
11671d10453SEric Joyner 	/* ICE_FLOW_FIELD_IDX_ARP_DIP */
11771d10453SEric Joyner 	ICE_FLOW_FLD_INFO(ICE_FLOW_SEG_HDR_ARP, 24, ICE_FLOW_FLD_SZ_IPV4_ADDR),
11871d10453SEric Joyner 	/* ICE_FLOW_FIELD_IDX_ARP_SHA */
11971d10453SEric Joyner 	ICE_FLOW_FLD_INFO(ICE_FLOW_SEG_HDR_ARP, 8, ETH_ALEN),
12071d10453SEric Joyner 	/* ICE_FLOW_FIELD_IDX_ARP_DHA */
12171d10453SEric Joyner 	ICE_FLOW_FLD_INFO(ICE_FLOW_SEG_HDR_ARP, 18, ETH_ALEN),
12271d10453SEric Joyner 	/* ICE_FLOW_FIELD_IDX_ARP_OP */
12371d10453SEric Joyner 	ICE_FLOW_FLD_INFO(ICE_FLOW_SEG_HDR_ARP, 6, ICE_FLOW_FLD_SZ_ARP_OPER),
12471d10453SEric Joyner 	/* ICMP */
12571d10453SEric Joyner 	/* ICE_FLOW_FIELD_IDX_ICMP_TYPE */
12671d10453SEric Joyner 	ICE_FLOW_FLD_INFO(ICE_FLOW_SEG_HDR_ICMP, 0, ICE_FLOW_FLD_SZ_ICMP_TYPE),
12771d10453SEric Joyner 	/* ICE_FLOW_FIELD_IDX_ICMP_CODE */
12871d10453SEric Joyner 	ICE_FLOW_FLD_INFO(ICE_FLOW_SEG_HDR_ICMP, 1, ICE_FLOW_FLD_SZ_ICMP_CODE),
12971d10453SEric Joyner 	/* GRE */
13071d10453SEric Joyner 	/* ICE_FLOW_FIELD_IDX_GRE_KEYID */
13171d10453SEric Joyner 	ICE_FLOW_FLD_INFO(ICE_FLOW_SEG_HDR_GRE, 12, ICE_FLOW_FLD_SZ_GRE_KEYID),
13271d10453SEric Joyner };
13371d10453SEric Joyner 
13471d10453SEric Joyner /* Bitmaps indicating relevant packet types for a particular protocol header
13571d10453SEric Joyner  *
13671d10453SEric Joyner  * Packet types for packets with an Outer/First/Single MAC header
13771d10453SEric Joyner  */
13871d10453SEric Joyner static const u32 ice_ptypes_mac_ofos[] = {
13971d10453SEric Joyner 	0xFDC00846, 0xBFBF7F7E, 0xF70001DF, 0xFEFDFDFB,
14071d10453SEric Joyner 	0x0000077E, 0x00000000, 0x00000000, 0x00000000,
14171d10453SEric Joyner 	0x00000000, 0x00000000, 0x00000000, 0x00000000,
14271d10453SEric Joyner 	0x00000000, 0x00000000, 0x00000000, 0x00000000,
14371d10453SEric Joyner 	0x00000000, 0x00000000, 0x00000000, 0x00000000,
14471d10453SEric Joyner 	0x00000000, 0x00000000, 0x00000000, 0x00000000,
14571d10453SEric Joyner 	0x00000000, 0x00000000, 0x00000000, 0x00000000,
14671d10453SEric Joyner 	0x00000000, 0x00000000, 0x00000000, 0x00000000,
14771d10453SEric Joyner };
14871d10453SEric Joyner 
14971d10453SEric Joyner /* Packet types for packets with an Innermost/Last MAC VLAN header */
15071d10453SEric Joyner static const u32 ice_ptypes_macvlan_il[] = {
15171d10453SEric Joyner 	0x00000000, 0xBC000000, 0x000001DF, 0xF0000000,
15271d10453SEric Joyner 	0x0000077E, 0x00000000, 0x00000000, 0x00000000,
15371d10453SEric Joyner 	0x00000000, 0x00000000, 0x00000000, 0x00000000,
15471d10453SEric Joyner 	0x00000000, 0x00000000, 0x00000000, 0x00000000,
15571d10453SEric Joyner 	0x00000000, 0x00000000, 0x00000000, 0x00000000,
15671d10453SEric Joyner 	0x00000000, 0x00000000, 0x00000000, 0x00000000,
15771d10453SEric Joyner 	0x00000000, 0x00000000, 0x00000000, 0x00000000,
15871d10453SEric Joyner 	0x00000000, 0x00000000, 0x00000000, 0x00000000,
15971d10453SEric Joyner };
16071d10453SEric Joyner 
16156429daeSEric Joyner /* Packet types for packets with an Outer/First/Single non-frag IPv4 header,
16256429daeSEric Joyner  * does NOT include IPV4 other PTYPEs
1637d7af7f8SEric Joyner  */
16471d10453SEric Joyner static const u32 ice_ptypes_ipv4_ofos[] = {
16556429daeSEric Joyner 	0x1D800000, 0x04000800, 0x00000000, 0x00000000,
16671d10453SEric Joyner 	0x00000000, 0x00000000, 0x00000000, 0x00000000,
16771d10453SEric Joyner 	0x00000000, 0x00000000, 0x00000000, 0x00000000,
16871d10453SEric Joyner 	0x00000000, 0x00000000, 0x00000000, 0x00000000,
16971d10453SEric Joyner 	0x00000000, 0x00000000, 0x00000000, 0x00000000,
17071d10453SEric Joyner 	0x00000000, 0x00000000, 0x00000000, 0x00000000,
17171d10453SEric Joyner 	0x00000000, 0x00000000, 0x00000000, 0x00000000,
17271d10453SEric Joyner 	0x00000000, 0x00000000, 0x00000000, 0x00000000,
17371d10453SEric Joyner };
17471d10453SEric Joyner 
17556429daeSEric Joyner /* Packet types for packets with an Outer/First/Single non-frag IPv4 header,
17656429daeSEric Joyner  * includes IPV4 other PTYPEs
1777d7af7f8SEric Joyner  */
1787d7af7f8SEric Joyner static const u32 ice_ptypes_ipv4_ofos_all[] = {
17956429daeSEric Joyner 	0x1D800000, 0x04000800, 0x00000000, 0x00000000,
1807d7af7f8SEric Joyner 	0x00000000, 0x00000000, 0x00000000, 0x00000000,
1817d7af7f8SEric Joyner 	0x00000000, 0x00000000, 0x00000000, 0x00000000,
1827d7af7f8SEric Joyner 	0x00000000, 0x00000000, 0x00000000, 0x00000000,
1837d7af7f8SEric Joyner 	0x00000000, 0x00000000, 0x00000000, 0x00000000,
1847d7af7f8SEric Joyner 	0x00000000, 0x00000000, 0x00000000, 0x00000000,
1857d7af7f8SEric Joyner 	0x00000000, 0x00000000, 0x00000000, 0x00000000,
1867d7af7f8SEric Joyner 	0x00000000, 0x00000000, 0x00000000, 0x00000000,
1877d7af7f8SEric Joyner };
1887d7af7f8SEric Joyner 
18971d10453SEric Joyner /* Packet types for packets with an Innermost/Last IPv4 header */
19071d10453SEric Joyner static const u32 ice_ptypes_ipv4_il[] = {
19171d10453SEric Joyner 	0xE0000000, 0xB807700E, 0x80000003, 0xE01DC03B,
19271d10453SEric Joyner 	0x0000000E, 0x00000000, 0x00000000, 0x00000000,
19371d10453SEric Joyner 	0x00000000, 0x00000000, 0x00000000, 0x00000000,
19471d10453SEric Joyner 	0x00000000, 0x00000000, 0x00000000, 0x00000000,
19571d10453SEric Joyner 	0x00000000, 0x00000000, 0x00000000, 0x00000000,
19671d10453SEric Joyner 	0x00000000, 0x00000000, 0x00000000, 0x00000000,
19771d10453SEric Joyner 	0x00000000, 0x00000000, 0x00000000, 0x00000000,
19871d10453SEric Joyner 	0x00000000, 0x00000000, 0x00000000, 0x00000000,
19971d10453SEric Joyner };
20071d10453SEric Joyner 
20156429daeSEric Joyner /* Packet types for packets with an Outer/First/Single non-frag IPv6 header,
20256429daeSEric Joyner  * does NOT include IVP6 other PTYPEs
2037d7af7f8SEric Joyner  */
20471d10453SEric Joyner static const u32 ice_ptypes_ipv6_ofos[] = {
20556429daeSEric Joyner 	0x00000000, 0x00000000, 0x76000000, 0x10002000,
20671d10453SEric Joyner 	0x00000000, 0x00000000, 0x00000000, 0x00000000,
20771d10453SEric Joyner 	0x00000000, 0x00000000, 0x00000000, 0x00000000,
20871d10453SEric Joyner 	0x00000000, 0x00000000, 0x00000000, 0x00000000,
20971d10453SEric Joyner 	0x00000000, 0x00000000, 0x00000000, 0x00000000,
21071d10453SEric Joyner 	0x00000000, 0x00000000, 0x00000000, 0x00000000,
21171d10453SEric Joyner 	0x00000000, 0x00000000, 0x00000000, 0x00000000,
21271d10453SEric Joyner 	0x00000000, 0x00000000, 0x00000000, 0x00000000,
21371d10453SEric Joyner };
21471d10453SEric Joyner 
21556429daeSEric Joyner /* Packet types for packets with an Outer/First/Single non-frag IPv6 header,
21656429daeSEric Joyner  * includes IPV6 other PTYPEs
2177d7af7f8SEric Joyner  */
2187d7af7f8SEric Joyner static const u32 ice_ptypes_ipv6_ofos_all[] = {
21956429daeSEric Joyner 	0x00000000, 0x00000000, 0x76000000, 0x10002000,
2207d7af7f8SEric Joyner 	0x00000000, 0x00000000, 0x00000000, 0x00000000,
2217d7af7f8SEric Joyner 	0x00000000, 0x00000000, 0x00000000, 0x00000000,
2227d7af7f8SEric Joyner 	0x00000000, 0x00000000, 0x00000000, 0x00000000,
2237d7af7f8SEric Joyner 	0x00000000, 0x00000000, 0x00000000, 0x00000000,
2247d7af7f8SEric Joyner 	0x00000000, 0x00000000, 0x00000000, 0x00000000,
2257d7af7f8SEric Joyner 	0x00000000, 0x00000000, 0x00000000, 0x00000000,
2267d7af7f8SEric Joyner 	0x00000000, 0x00000000, 0x00000000, 0x00000000,
2277d7af7f8SEric Joyner };
2287d7af7f8SEric Joyner 
22971d10453SEric Joyner /* Packet types for packets with an Innermost/Last IPv6 header */
23071d10453SEric Joyner static const u32 ice_ptypes_ipv6_il[] = {
23171d10453SEric Joyner 	0x00000000, 0x03B80770, 0x000001DC, 0x0EE00000,
23271d10453SEric Joyner 	0x00000770, 0x00000000, 0x00000000, 0x00000000,
23371d10453SEric Joyner 	0x00000000, 0x00000000, 0x00000000, 0x00000000,
23471d10453SEric Joyner 	0x00000000, 0x00000000, 0x00000000, 0x00000000,
23571d10453SEric Joyner 	0x00000000, 0x00000000, 0x00000000, 0x00000000,
23671d10453SEric Joyner 	0x00000000, 0x00000000, 0x00000000, 0x00000000,
23771d10453SEric Joyner 	0x00000000, 0x00000000, 0x00000000, 0x00000000,
23871d10453SEric Joyner 	0x00000000, 0x00000000, 0x00000000, 0x00000000,
23971d10453SEric Joyner };
24071d10453SEric Joyner 
24156429daeSEric Joyner /* Packet types for packets with an Outer/First/Single
24256429daeSEric Joyner  * non-frag IPv4 header - no L4
24356429daeSEric Joyner  */
244d08b8680SEric Joyner static const u32 ice_ptypes_ipv4_ofos_no_l4[] = {
24556429daeSEric Joyner 	0x10800000, 0x04000800, 0x00000000, 0x00000000,
2467d7af7f8SEric Joyner 	0x00000000, 0x00000000, 0x00000000, 0x00000000,
2477d7af7f8SEric Joyner 	0x00000000, 0x00000000, 0x00000000, 0x00000000,
2487d7af7f8SEric Joyner 	0x00000000, 0x00000000, 0x00000000, 0x00000000,
2497d7af7f8SEric Joyner 	0x00000000, 0x00000000, 0x00000000, 0x00000000,
2507d7af7f8SEric Joyner 	0x00000000, 0x00000000, 0x00000000, 0x00000000,
2517d7af7f8SEric Joyner 	0x00000000, 0x00000000, 0x00000000, 0x00000000,
2527d7af7f8SEric Joyner 	0x00000000, 0x00000000, 0x00000000, 0x00000000,
2537d7af7f8SEric Joyner };
2547d7af7f8SEric Joyner 
2557d7af7f8SEric Joyner /* Packet types for packets with an Innermost/Last IPv4 header - no L4 */
256d08b8680SEric Joyner static const u32 ice_ptypes_ipv4_il_no_l4[] = {
2577d7af7f8SEric Joyner 	0x60000000, 0x18043008, 0x80000002, 0x6010c021,
2587d7af7f8SEric Joyner 	0x00000008, 0x00000000, 0x00000000, 0x00000000,
2597d7af7f8SEric Joyner 	0x00000000, 0x00000000, 0x00000000, 0x00000000,
2607d7af7f8SEric Joyner 	0x00000000, 0x00000000, 0x00000000, 0x00000000,
2617d7af7f8SEric Joyner 	0x00000000, 0x00000000, 0x00000000, 0x00000000,
2627d7af7f8SEric Joyner 	0x00000000, 0x00000000, 0x00000000, 0x00000000,
2637d7af7f8SEric Joyner 	0x00000000, 0x00000000, 0x00000000, 0x00000000,
2647d7af7f8SEric Joyner 	0x00000000, 0x00000000, 0x00000000, 0x00000000,
2657d7af7f8SEric Joyner };
2667d7af7f8SEric Joyner 
26756429daeSEric Joyner /* Packet types for packets with an Outer/First/Single
26856429daeSEric Joyner  * non-frag IPv6 header - no L4
26956429daeSEric Joyner  */
270d08b8680SEric Joyner static const u32 ice_ptypes_ipv6_ofos_no_l4[] = {
27156429daeSEric Joyner 	0x00000000, 0x00000000, 0x42000000, 0x10002000,
2727d7af7f8SEric Joyner 	0x00000000, 0x00000000, 0x00000000, 0x00000000,
2737d7af7f8SEric Joyner 	0x00000000, 0x00000000, 0x00000000, 0x00000000,
2747d7af7f8SEric Joyner 	0x00000000, 0x00000000, 0x00000000, 0x00000000,
2757d7af7f8SEric Joyner 	0x00000000, 0x00000000, 0x00000000, 0x00000000,
2767d7af7f8SEric Joyner 	0x00000000, 0x00000000, 0x00000000, 0x00000000,
2777d7af7f8SEric Joyner 	0x00000000, 0x00000000, 0x00000000, 0x00000000,
2787d7af7f8SEric Joyner 	0x00000000, 0x00000000, 0x00000000, 0x00000000,
2797d7af7f8SEric Joyner };
2807d7af7f8SEric Joyner 
2817d7af7f8SEric Joyner /* Packet types for packets with an Innermost/Last IPv6 header - no L4 */
282d08b8680SEric Joyner static const u32 ice_ptypes_ipv6_il_no_l4[] = {
2837d7af7f8SEric Joyner 	0x00000000, 0x02180430, 0x0000010c, 0x086010c0,
2847d7af7f8SEric Joyner 	0x00000430, 0x00000000, 0x00000000, 0x00000000,
2857d7af7f8SEric Joyner 	0x00000000, 0x00000000, 0x00000000, 0x00000000,
2867d7af7f8SEric Joyner 	0x00000000, 0x00000000, 0x00000000, 0x00000000,
2877d7af7f8SEric Joyner 	0x00000000, 0x00000000, 0x00000000, 0x00000000,
2887d7af7f8SEric Joyner 	0x00000000, 0x00000000, 0x00000000, 0x00000000,
2897d7af7f8SEric Joyner 	0x00000000, 0x00000000, 0x00000000, 0x00000000,
2907d7af7f8SEric Joyner 	0x00000000, 0x00000000, 0x00000000, 0x00000000,
2917d7af7f8SEric Joyner };
2927d7af7f8SEric Joyner 
29371d10453SEric Joyner /* Packet types for packets with an Outermost/First ARP header */
29471d10453SEric Joyner static const u32 ice_ptypes_arp_of[] = {
29571d10453SEric Joyner 	0x00000800, 0x00000000, 0x00000000, 0x00000000,
29671d10453SEric Joyner 	0x00000000, 0x00000000, 0x00000000, 0x00000000,
29771d10453SEric Joyner 	0x00000000, 0x00000000, 0x00000000, 0x00000000,
29871d10453SEric Joyner 	0x00000000, 0x00000000, 0x00000000, 0x00000000,
29971d10453SEric Joyner 	0x00000000, 0x00000000, 0x00000000, 0x00000000,
30071d10453SEric Joyner 	0x00000000, 0x00000000, 0x00000000, 0x00000000,
30171d10453SEric Joyner 	0x00000000, 0x00000000, 0x00000000, 0x00000000,
30271d10453SEric Joyner 	0x00000000, 0x00000000, 0x00000000, 0x00000000,
30371d10453SEric Joyner };
30471d10453SEric Joyner 
30571d10453SEric Joyner /* UDP Packet types for non-tunneled packets or tunneled
30671d10453SEric Joyner  * packets with inner UDP.
30771d10453SEric Joyner  */
30871d10453SEric Joyner static const u32 ice_ptypes_udp_il[] = {
30971d10453SEric Joyner 	0x81000000, 0x20204040, 0x04000010, 0x80810102,
31071d10453SEric Joyner 	0x00000040, 0x00000000, 0x00000000, 0x00000000,
31171d10453SEric Joyner 	0x00000000, 0x00000000, 0x00000000, 0x00000000,
31271d10453SEric Joyner 	0x00000000, 0x00000000, 0x00000000, 0x00000000,
31371d10453SEric Joyner 	0x00000000, 0x00000000, 0x00000000, 0x00000000,
31471d10453SEric Joyner 	0x00000000, 0x00000000, 0x00000000, 0x00000000,
31571d10453SEric Joyner 	0x00000000, 0x00000000, 0x00000000, 0x00000000,
31671d10453SEric Joyner 	0x00000000, 0x00000000, 0x00000000, 0x00000000,
31771d10453SEric Joyner };
31871d10453SEric Joyner 
31971d10453SEric Joyner /* Packet types for packets with an Innermost/Last TCP header */
32071d10453SEric Joyner static const u32 ice_ptypes_tcp_il[] = {
32171d10453SEric Joyner 	0x04000000, 0x80810102, 0x10000040, 0x02040408,
32271d10453SEric Joyner 	0x00000102, 0x00000000, 0x00000000, 0x00000000,
32371d10453SEric Joyner 	0x00000000, 0x00000000, 0x00000000, 0x00000000,
32471d10453SEric Joyner 	0x00000000, 0x00000000, 0x00000000, 0x00000000,
32571d10453SEric Joyner 	0x00000000, 0x00000000, 0x00000000, 0x00000000,
32671d10453SEric Joyner 	0x00000000, 0x00000000, 0x00000000, 0x00000000,
32771d10453SEric Joyner 	0x00000000, 0x00000000, 0x00000000, 0x00000000,
32871d10453SEric Joyner 	0x00000000, 0x00000000, 0x00000000, 0x00000000,
32971d10453SEric Joyner };
33071d10453SEric Joyner 
33171d10453SEric Joyner /* Packet types for packets with an Innermost/Last SCTP header */
33271d10453SEric Joyner static const u32 ice_ptypes_sctp_il[] = {
33371d10453SEric Joyner 	0x08000000, 0x01020204, 0x20000081, 0x04080810,
33471d10453SEric Joyner 	0x00000204, 0x00000000, 0x00000000, 0x00000000,
33571d10453SEric Joyner 	0x00000000, 0x00000000, 0x00000000, 0x00000000,
33671d10453SEric Joyner 	0x00000000, 0x00000000, 0x00000000, 0x00000000,
33771d10453SEric Joyner 	0x00000000, 0x00000000, 0x00000000, 0x00000000,
33871d10453SEric Joyner 	0x00000000, 0x00000000, 0x00000000, 0x00000000,
33971d10453SEric Joyner 	0x00000000, 0x00000000, 0x00000000, 0x00000000,
34071d10453SEric Joyner 	0x00000000, 0x00000000, 0x00000000, 0x00000000,
34171d10453SEric Joyner };
34271d10453SEric Joyner 
34371d10453SEric Joyner /* Packet types for packets with an Outermost/First ICMP header */
34471d10453SEric Joyner static const u32 ice_ptypes_icmp_of[] = {
34571d10453SEric Joyner 	0x10000000, 0x00000000, 0x00000000, 0x00000000,
34671d10453SEric Joyner 	0x00000000, 0x00000000, 0x00000000, 0x00000000,
34771d10453SEric Joyner 	0x00000000, 0x00000000, 0x00000000, 0x00000000,
34871d10453SEric Joyner 	0x00000000, 0x00000000, 0x00000000, 0x00000000,
34971d10453SEric Joyner 	0x00000000, 0x00000000, 0x00000000, 0x00000000,
35071d10453SEric Joyner 	0x00000000, 0x00000000, 0x00000000, 0x00000000,
35171d10453SEric Joyner 	0x00000000, 0x00000000, 0x00000000, 0x00000000,
35271d10453SEric Joyner 	0x00000000, 0x00000000, 0x00000000, 0x00000000,
35371d10453SEric Joyner };
35471d10453SEric Joyner 
35571d10453SEric Joyner /* Packet types for packets with an Innermost/Last ICMP header */
35671d10453SEric Joyner static const u32 ice_ptypes_icmp_il[] = {
35771d10453SEric Joyner 	0x00000000, 0x02040408, 0x40000102, 0x08101020,
35871d10453SEric Joyner 	0x00000408, 0x00000000, 0x00000000, 0x00000000,
35971d10453SEric Joyner 	0x00000000, 0x00000000, 0x00000000, 0x00000000,
36071d10453SEric Joyner 	0x00000000, 0x00000000, 0x00000000, 0x00000000,
36171d10453SEric Joyner 	0x00000000, 0x00000000, 0x00000000, 0x00000000,
36271d10453SEric Joyner 	0x00000000, 0x00000000, 0x00000000, 0x00000000,
36371d10453SEric Joyner 	0x00000000, 0x00000000, 0x00000000, 0x00000000,
36471d10453SEric Joyner 	0x00000000, 0x00000000, 0x00000000, 0x00000000,
36571d10453SEric Joyner };
36671d10453SEric Joyner 
36771d10453SEric Joyner /* Packet types for packets with an Outermost/First GRE header */
36871d10453SEric Joyner static const u32 ice_ptypes_gre_of[] = {
36971d10453SEric Joyner 	0x00000000, 0xBFBF7800, 0x000001DF, 0xFEFDE000,
37071d10453SEric Joyner 	0x0000017E, 0x00000000, 0x00000000, 0x00000000,
37171d10453SEric Joyner 	0x00000000, 0x00000000, 0x00000000, 0x00000000,
37271d10453SEric Joyner 	0x00000000, 0x00000000, 0x00000000, 0x00000000,
37371d10453SEric Joyner 	0x00000000, 0x00000000, 0x00000000, 0x00000000,
37471d10453SEric Joyner 	0x00000000, 0x00000000, 0x00000000, 0x00000000,
37571d10453SEric Joyner 	0x00000000, 0x00000000, 0x00000000, 0x00000000,
37671d10453SEric Joyner 	0x00000000, 0x00000000, 0x00000000, 0x00000000,
37771d10453SEric Joyner };
37871d10453SEric Joyner 
37971d10453SEric Joyner /* Packet types for packets with an Innermost/Last MAC header */
38071d10453SEric Joyner static const u32 ice_ptypes_mac_il[] = {
38171d10453SEric Joyner 	0x00000000, 0x00000000, 0x00000000, 0x00000000,
38271d10453SEric Joyner 	0x00000000, 0x00000000, 0x00000000, 0x00000000,
38371d10453SEric Joyner 	0x00000000, 0x00000000, 0x00000000, 0x00000000,
38471d10453SEric Joyner 	0x00000000, 0x00000000, 0x00000000, 0x00000000,
38571d10453SEric Joyner 	0x00000000, 0x00000000, 0x00000000, 0x00000000,
38671d10453SEric Joyner 	0x00000000, 0x00000000, 0x00000000, 0x00000000,
38771d10453SEric Joyner 	0x00000000, 0x00000000, 0x00000000, 0x00000000,
38871d10453SEric Joyner 	0x00000000, 0x00000000, 0x00000000, 0x00000000,
38971d10453SEric Joyner };
39071d10453SEric Joyner 
39171d10453SEric Joyner /* Manage parameters and info. used during the creation of a flow profile */
39271d10453SEric Joyner struct ice_flow_prof_params {
39371d10453SEric Joyner 	enum ice_block blk;
39471d10453SEric Joyner 	u16 entry_length; /* # of bytes formatted entry will require */
39571d10453SEric Joyner 	u8 es_cnt;
39671d10453SEric Joyner 	struct ice_flow_prof *prof;
39771d10453SEric Joyner 
39871d10453SEric Joyner 	/* For ACL, the es[0] will have the data of ICE_RX_MDID_PKT_FLAGS_15_0
39971d10453SEric Joyner 	 * This will give us the direction flags.
40071d10453SEric Joyner 	 */
40171d10453SEric Joyner 	struct ice_fv_word es[ICE_MAX_FV_WORDS];
4028923de59SPiotr Kubaj 
40371d10453SEric Joyner 	ice_declare_bitmap(ptypes, ICE_FLOW_PTYPE_MAX);
40471d10453SEric Joyner };
40571d10453SEric Joyner 
40671d10453SEric Joyner #define ICE_FLOW_SEG_HDRS_L3_MASK	\
4079e54973fSEric Joyner 	(ICE_FLOW_SEG_HDR_IPV4 | ICE_FLOW_SEG_HDR_IPV6 | ICE_FLOW_SEG_HDR_ARP)
40871d10453SEric Joyner #define ICE_FLOW_SEG_HDRS_L4_MASK	\
40971d10453SEric Joyner 	(ICE_FLOW_SEG_HDR_ICMP | ICE_FLOW_SEG_HDR_TCP | ICE_FLOW_SEG_HDR_UDP | \
41071d10453SEric Joyner 	 ICE_FLOW_SEG_HDR_SCTP)
4119e54973fSEric Joyner /* mask for L4 protocols that are NOT part of IPv4/6 OTHER PTYPE groups */
4127d7af7f8SEric Joyner #define ICE_FLOW_SEG_HDRS_L4_MASK_NO_OTHER	\
4137d7af7f8SEric Joyner 	(ICE_FLOW_SEG_HDR_TCP | ICE_FLOW_SEG_HDR_UDP | ICE_FLOW_SEG_HDR_SCTP)
41471d10453SEric Joyner 
41571d10453SEric Joyner /**
41671d10453SEric Joyner  * ice_flow_val_hdrs - validates packet segments for valid protocol headers
41771d10453SEric Joyner  * @segs: array of one or more packet segments that describe the flow
41871d10453SEric Joyner  * @segs_cnt: number of packet segments provided
41971d10453SEric Joyner  */
420*f2635e84SEric Joyner static int ice_flow_val_hdrs(struct ice_flow_seg_info *segs, u8 segs_cnt)
42171d10453SEric Joyner {
42271d10453SEric Joyner 	u8 i;
42371d10453SEric Joyner 
42471d10453SEric Joyner 	for (i = 0; i < segs_cnt; i++) {
42571d10453SEric Joyner 		/* Multiple L3 headers */
42671d10453SEric Joyner 		if (segs[i].hdrs & ICE_FLOW_SEG_HDRS_L3_MASK &&
42771d10453SEric Joyner 		    !ice_is_pow2(segs[i].hdrs & ICE_FLOW_SEG_HDRS_L3_MASK))
42871d10453SEric Joyner 			return ICE_ERR_PARAM;
42971d10453SEric Joyner 
43071d10453SEric Joyner 		/* Multiple L4 headers */
43171d10453SEric Joyner 		if (segs[i].hdrs & ICE_FLOW_SEG_HDRS_L4_MASK &&
43271d10453SEric Joyner 		    !ice_is_pow2(segs[i].hdrs & ICE_FLOW_SEG_HDRS_L4_MASK))
43371d10453SEric Joyner 			return ICE_ERR_PARAM;
43471d10453SEric Joyner 	}
43571d10453SEric Joyner 
436*f2635e84SEric Joyner 	return 0;
43771d10453SEric Joyner }
43871d10453SEric Joyner 
43971d10453SEric Joyner /**
44071d10453SEric Joyner  * ice_flow_proc_seg_hdrs - process protocol headers present in pkt segments
44171d10453SEric Joyner  * @params: information about the flow to be processed
44271d10453SEric Joyner  *
44371d10453SEric Joyner  * This function identifies the packet types associated with the protocol
44471d10453SEric Joyner  * headers being present in packet segments of the specified flow profile.
44571d10453SEric Joyner  */
446*f2635e84SEric Joyner static int
44771d10453SEric Joyner ice_flow_proc_seg_hdrs(struct ice_flow_prof_params *params)
44871d10453SEric Joyner {
44971d10453SEric Joyner 	struct ice_flow_prof *prof;
45071d10453SEric Joyner 	u8 i;
45171d10453SEric Joyner 
45271d10453SEric Joyner 	ice_memset(params->ptypes, 0xff, sizeof(params->ptypes),
45371d10453SEric Joyner 		   ICE_NONDMA_MEM);
45471d10453SEric Joyner 
45571d10453SEric Joyner 	prof = params->prof;
45671d10453SEric Joyner 
45771d10453SEric Joyner 	for (i = 0; i < params->prof->segs_cnt; i++) {
45871d10453SEric Joyner 		const ice_bitmap_t *src;
45971d10453SEric Joyner 		u32 hdrs;
46071d10453SEric Joyner 
46171d10453SEric Joyner 		hdrs = prof->segs[i].hdrs;
46271d10453SEric Joyner 
46371d10453SEric Joyner 		if (hdrs & ICE_FLOW_SEG_HDR_ETH) {
46471d10453SEric Joyner 			src = !i ? (const ice_bitmap_t *)ice_ptypes_mac_ofos :
46571d10453SEric Joyner 				(const ice_bitmap_t *)ice_ptypes_mac_il;
46671d10453SEric Joyner 			ice_and_bitmap(params->ptypes, params->ptypes, src,
46771d10453SEric Joyner 				       ICE_FLOW_PTYPE_MAX);
46871d10453SEric Joyner 		}
46971d10453SEric Joyner 
47071d10453SEric Joyner 		if (i && hdrs & ICE_FLOW_SEG_HDR_VLAN) {
47171d10453SEric Joyner 			src = (const ice_bitmap_t *)ice_ptypes_macvlan_il;
47271d10453SEric Joyner 			ice_and_bitmap(params->ptypes, params->ptypes, src,
47371d10453SEric Joyner 				       ICE_FLOW_PTYPE_MAX);
47471d10453SEric Joyner 		}
47571d10453SEric Joyner 
47671d10453SEric Joyner 		if (!i && hdrs & ICE_FLOW_SEG_HDR_ARP) {
47771d10453SEric Joyner 			ice_and_bitmap(params->ptypes, params->ptypes,
47871d10453SEric Joyner 				       (const ice_bitmap_t *)ice_ptypes_arp_of,
47971d10453SEric Joyner 				       ICE_FLOW_PTYPE_MAX);
48071d10453SEric Joyner 		}
48171d10453SEric Joyner 
4827d7af7f8SEric Joyner 		if ((hdrs & ICE_FLOW_SEG_HDR_IPV4) &&
4837d7af7f8SEric Joyner 		    (hdrs & ICE_FLOW_SEG_HDR_IPV_OTHER)) {
4849e54973fSEric Joyner 			src = i ? (const ice_bitmap_t *)ice_ptypes_ipv4_il :
4857d7af7f8SEric Joyner 				(const ice_bitmap_t *)ice_ptypes_ipv4_ofos_all;
4867d7af7f8SEric Joyner 			ice_and_bitmap(params->ptypes, params->ptypes, src,
4877d7af7f8SEric Joyner 				       ICE_FLOW_PTYPE_MAX);
4887d7af7f8SEric Joyner 		} else if ((hdrs & ICE_FLOW_SEG_HDR_IPV6) &&
4897d7af7f8SEric Joyner 			   (hdrs & ICE_FLOW_SEG_HDR_IPV_OTHER)) {
4909e54973fSEric Joyner 			src = i ? (const ice_bitmap_t *)ice_ptypes_ipv6_il :
4917d7af7f8SEric Joyner 				(const ice_bitmap_t *)ice_ptypes_ipv6_ofos_all;
4927d7af7f8SEric Joyner 			ice_and_bitmap(params->ptypes, params->ptypes, src,
4937d7af7f8SEric Joyner 				       ICE_FLOW_PTYPE_MAX);
4947d7af7f8SEric Joyner 		} else if ((hdrs & ICE_FLOW_SEG_HDR_IPV4) &&
4957d7af7f8SEric Joyner 			   !(hdrs & ICE_FLOW_SEG_HDRS_L4_MASK_NO_OTHER)) {
496d08b8680SEric Joyner 			src = !i ? (const ice_bitmap_t *)ice_ptypes_ipv4_ofos_no_l4 :
497d08b8680SEric Joyner 				(const ice_bitmap_t *)ice_ptypes_ipv4_il_no_l4;
4987d7af7f8SEric Joyner 			ice_and_bitmap(params->ptypes, params->ptypes, src,
4997d7af7f8SEric Joyner 				       ICE_FLOW_PTYPE_MAX);
5007d7af7f8SEric Joyner 		} else if (hdrs & ICE_FLOW_SEG_HDR_IPV4) {
50171d10453SEric Joyner 			src = !i ? (const ice_bitmap_t *)ice_ptypes_ipv4_ofos :
50271d10453SEric Joyner 				(const ice_bitmap_t *)ice_ptypes_ipv4_il;
50371d10453SEric Joyner 			ice_and_bitmap(params->ptypes, params->ptypes, src,
50471d10453SEric Joyner 				       ICE_FLOW_PTYPE_MAX);
5057d7af7f8SEric Joyner 		} else if ((hdrs & ICE_FLOW_SEG_HDR_IPV6) &&
5067d7af7f8SEric Joyner 			   !(hdrs & ICE_FLOW_SEG_HDRS_L4_MASK_NO_OTHER)) {
507d08b8680SEric Joyner 			src = !i ? (const ice_bitmap_t *)ice_ptypes_ipv6_ofos_no_l4 :
508d08b8680SEric Joyner 				(const ice_bitmap_t *)ice_ptypes_ipv6_il_no_l4;
5097d7af7f8SEric Joyner 			ice_and_bitmap(params->ptypes, params->ptypes, src,
5107d7af7f8SEric Joyner 				       ICE_FLOW_PTYPE_MAX);
51171d10453SEric Joyner 		} else if (hdrs & ICE_FLOW_SEG_HDR_IPV6) {
51271d10453SEric Joyner 			src = !i ? (const ice_bitmap_t *)ice_ptypes_ipv6_ofos :
51371d10453SEric Joyner 				(const ice_bitmap_t *)ice_ptypes_ipv6_il;
51471d10453SEric Joyner 			ice_and_bitmap(params->ptypes, params->ptypes, src,
51571d10453SEric Joyner 				       ICE_FLOW_PTYPE_MAX);
51671d10453SEric Joyner 		}
51771d10453SEric Joyner 
5187d7af7f8SEric Joyner 		if (hdrs & ICE_FLOW_SEG_HDR_UDP) {
51971d10453SEric Joyner 			src = (const ice_bitmap_t *)ice_ptypes_udp_il;
52071d10453SEric Joyner 			ice_and_bitmap(params->ptypes, params->ptypes, src,
52171d10453SEric Joyner 				       ICE_FLOW_PTYPE_MAX);
52271d10453SEric Joyner 		} else if (hdrs & ICE_FLOW_SEG_HDR_TCP) {
52371d10453SEric Joyner 			ice_and_bitmap(params->ptypes, params->ptypes,
52471d10453SEric Joyner 				       (const ice_bitmap_t *)ice_ptypes_tcp_il,
52571d10453SEric Joyner 				       ICE_FLOW_PTYPE_MAX);
52671d10453SEric Joyner 		} else if (hdrs & ICE_FLOW_SEG_HDR_SCTP) {
52771d10453SEric Joyner 			src = (const ice_bitmap_t *)ice_ptypes_sctp_il;
52871d10453SEric Joyner 			ice_and_bitmap(params->ptypes, params->ptypes, src,
52971d10453SEric Joyner 				       ICE_FLOW_PTYPE_MAX);
5307d7af7f8SEric Joyner 		}
5317d7af7f8SEric Joyner 
5327d7af7f8SEric Joyner 		if (hdrs & ICE_FLOW_SEG_HDR_ICMP) {
5337d7af7f8SEric Joyner 			src = !i ? (const ice_bitmap_t *)ice_ptypes_icmp_of :
5347d7af7f8SEric Joyner 				(const ice_bitmap_t *)ice_ptypes_icmp_il;
5357d7af7f8SEric Joyner 			ice_and_bitmap(params->ptypes, params->ptypes, src,
5367d7af7f8SEric Joyner 				       ICE_FLOW_PTYPE_MAX);
53771d10453SEric Joyner 		} else if (hdrs & ICE_FLOW_SEG_HDR_GRE) {
53871d10453SEric Joyner 			if (!i) {
53971d10453SEric Joyner 				src = (const ice_bitmap_t *)ice_ptypes_gre_of;
54071d10453SEric Joyner 				ice_and_bitmap(params->ptypes, params->ptypes,
54171d10453SEric Joyner 					       src, ICE_FLOW_PTYPE_MAX);
54271d10453SEric Joyner 			}
54371d10453SEric Joyner 		}
54471d10453SEric Joyner 	}
54571d10453SEric Joyner 
546*f2635e84SEric Joyner 	return 0;
54771d10453SEric Joyner }
54871d10453SEric Joyner 
549*f2635e84SEric Joyner /*
55071d10453SEric Joyner  * ice_flow_xtract_fld - Create an extraction sequence entry for the given field
55171d10453SEric Joyner  * @hw: pointer to the HW struct
55271d10453SEric Joyner  * @params: information about the flow to be processed
55371d10453SEric Joyner  * @seg: packet segment index of the field to be extracted
55471d10453SEric Joyner  * @fld: ID of field to be extracted
55571d10453SEric Joyner  *
55671d10453SEric Joyner  * This function determines the protocol ID, offset, and size of the given
55771d10453SEric Joyner  * field. It then allocates one or more extraction sequence entries for the
55871d10453SEric Joyner  * given field, and fill the entries with protocol ID and offset information.
55971d10453SEric Joyner  */
560*f2635e84SEric Joyner static int
56171d10453SEric Joyner ice_flow_xtract_fld(struct ice_hw *hw, struct ice_flow_prof_params *params,
56271d10453SEric Joyner 		    u8 seg, enum ice_flow_field fld)
56371d10453SEric Joyner {
56471d10453SEric Joyner 	enum ice_flow_field sib = ICE_FLOW_FIELD_IDX_MAX;
5658923de59SPiotr Kubaj 	u8 fv_words = (u8)hw->blk[params->blk].es.fvw;
56671d10453SEric Joyner 	enum ice_prot_id prot_id = ICE_PROT_ID_INVAL;
56771d10453SEric Joyner 	struct ice_flow_fld_info *flds;
56871d10453SEric Joyner 	u16 cnt, ese_bits, i;
56971d10453SEric Joyner 	u16 off;
57071d10453SEric Joyner 
57171d10453SEric Joyner 	flds = params->prof->segs[seg].fields;
57271d10453SEric Joyner 
57371d10453SEric Joyner 	switch (fld) {
57471d10453SEric Joyner 	case ICE_FLOW_FIELD_IDX_ETH_DA:
57571d10453SEric Joyner 	case ICE_FLOW_FIELD_IDX_ETH_SA:
57671d10453SEric Joyner 	case ICE_FLOW_FIELD_IDX_S_VLAN:
57771d10453SEric Joyner 	case ICE_FLOW_FIELD_IDX_C_VLAN:
57871d10453SEric Joyner 		prot_id = seg == 0 ? ICE_PROT_MAC_OF_OR_S : ICE_PROT_MAC_IL;
57971d10453SEric Joyner 		break;
58071d10453SEric Joyner 	case ICE_FLOW_FIELD_IDX_ETH_TYPE:
58171d10453SEric Joyner 		prot_id = seg == 0 ? ICE_PROT_ETYPE_OL : ICE_PROT_ETYPE_IL;
58271d10453SEric Joyner 		break;
58371d10453SEric Joyner 	case ICE_FLOW_FIELD_IDX_IPV4_DSCP:
58471d10453SEric Joyner 		prot_id = seg == 0 ? ICE_PROT_IPV4_OF_OR_S : ICE_PROT_IPV4_IL;
58571d10453SEric Joyner 		break;
58671d10453SEric Joyner 	case ICE_FLOW_FIELD_IDX_IPV6_DSCP:
58771d10453SEric Joyner 		prot_id = seg == 0 ? ICE_PROT_IPV6_OF_OR_S : ICE_PROT_IPV6_IL;
58871d10453SEric Joyner 		break;
58971d10453SEric Joyner 	case ICE_FLOW_FIELD_IDX_IPV4_TTL:
59071d10453SEric Joyner 	case ICE_FLOW_FIELD_IDX_IPV4_PROT:
59171d10453SEric Joyner 		prot_id = seg == 0 ? ICE_PROT_IPV4_OF_OR_S : ICE_PROT_IPV4_IL;
59271d10453SEric Joyner 		/* TTL and PROT share the same extraction seq. entry.
59371d10453SEric Joyner 		 * Each is considered a sibling to the other in terms of sharing
59471d10453SEric Joyner 		 * the same extraction sequence entry.
59571d10453SEric Joyner 		 */
59671d10453SEric Joyner 		if (fld == ICE_FLOW_FIELD_IDX_IPV4_TTL)
59771d10453SEric Joyner 			sib = ICE_FLOW_FIELD_IDX_IPV4_PROT;
598d08b8680SEric Joyner 		else
59971d10453SEric Joyner 			sib = ICE_FLOW_FIELD_IDX_IPV4_TTL;
60071d10453SEric Joyner 		break;
60171d10453SEric Joyner 	case ICE_FLOW_FIELD_IDX_IPV6_TTL:
60271d10453SEric Joyner 	case ICE_FLOW_FIELD_IDX_IPV6_PROT:
60371d10453SEric Joyner 		prot_id = seg == 0 ? ICE_PROT_IPV6_OF_OR_S : ICE_PROT_IPV6_IL;
60471d10453SEric Joyner 		/* TTL and PROT share the same extraction seq. entry.
60571d10453SEric Joyner 		 * Each is considered a sibling to the other in terms of sharing
60671d10453SEric Joyner 		 * the same extraction sequence entry.
60771d10453SEric Joyner 		 */
60871d10453SEric Joyner 		if (fld == ICE_FLOW_FIELD_IDX_IPV6_TTL)
60971d10453SEric Joyner 			sib = ICE_FLOW_FIELD_IDX_IPV6_PROT;
610d08b8680SEric Joyner 		else
61171d10453SEric Joyner 			sib = ICE_FLOW_FIELD_IDX_IPV6_TTL;
61271d10453SEric Joyner 		break;
61371d10453SEric Joyner 	case ICE_FLOW_FIELD_IDX_IPV4_SA:
61471d10453SEric Joyner 	case ICE_FLOW_FIELD_IDX_IPV4_DA:
61571d10453SEric Joyner 		prot_id = seg == 0 ? ICE_PROT_IPV4_OF_OR_S : ICE_PROT_IPV4_IL;
61671d10453SEric Joyner 		break;
61771d10453SEric Joyner 	case ICE_FLOW_FIELD_IDX_IPV6_SA:
61871d10453SEric Joyner 	case ICE_FLOW_FIELD_IDX_IPV6_DA:
61971d10453SEric Joyner 		prot_id = seg == 0 ? ICE_PROT_IPV6_OF_OR_S : ICE_PROT_IPV6_IL;
62071d10453SEric Joyner 		break;
62171d10453SEric Joyner 	case ICE_FLOW_FIELD_IDX_TCP_SRC_PORT:
62271d10453SEric Joyner 	case ICE_FLOW_FIELD_IDX_TCP_DST_PORT:
62371d10453SEric Joyner 	case ICE_FLOW_FIELD_IDX_TCP_FLAGS:
62471d10453SEric Joyner 		prot_id = ICE_PROT_TCP_IL;
62571d10453SEric Joyner 		break;
62671d10453SEric Joyner 	case ICE_FLOW_FIELD_IDX_UDP_SRC_PORT:
62771d10453SEric Joyner 	case ICE_FLOW_FIELD_IDX_UDP_DST_PORT:
62871d10453SEric Joyner 		prot_id = ICE_PROT_UDP_IL_OR_S;
62971d10453SEric Joyner 		break;
63071d10453SEric Joyner 	case ICE_FLOW_FIELD_IDX_SCTP_SRC_PORT:
63171d10453SEric Joyner 	case ICE_FLOW_FIELD_IDX_SCTP_DST_PORT:
63271d10453SEric Joyner 		prot_id = ICE_PROT_SCTP_IL;
63371d10453SEric Joyner 		break;
63471d10453SEric Joyner 	case ICE_FLOW_FIELD_IDX_ARP_SIP:
63571d10453SEric Joyner 	case ICE_FLOW_FIELD_IDX_ARP_DIP:
63671d10453SEric Joyner 	case ICE_FLOW_FIELD_IDX_ARP_SHA:
63771d10453SEric Joyner 	case ICE_FLOW_FIELD_IDX_ARP_DHA:
63871d10453SEric Joyner 	case ICE_FLOW_FIELD_IDX_ARP_OP:
63971d10453SEric Joyner 		prot_id = ICE_PROT_ARP_OF;
64071d10453SEric Joyner 		break;
64171d10453SEric Joyner 	case ICE_FLOW_FIELD_IDX_ICMP_TYPE:
64271d10453SEric Joyner 	case ICE_FLOW_FIELD_IDX_ICMP_CODE:
64371d10453SEric Joyner 		/* ICMP type and code share the same extraction seq. entry */
6449e54973fSEric Joyner 		prot_id = (params->prof->segs[seg].hdrs & ICE_FLOW_SEG_HDR_IPV4) ?
64571d10453SEric Joyner 			ICE_PROT_ICMP_IL : ICE_PROT_ICMPV6_IL;
64671d10453SEric Joyner 		sib = fld == ICE_FLOW_FIELD_IDX_ICMP_TYPE ?
64771d10453SEric Joyner 			ICE_FLOW_FIELD_IDX_ICMP_CODE :
64871d10453SEric Joyner 			ICE_FLOW_FIELD_IDX_ICMP_TYPE;
64971d10453SEric Joyner 		break;
65071d10453SEric Joyner 	case ICE_FLOW_FIELD_IDX_GRE_KEYID:
65171d10453SEric Joyner 		prot_id = ICE_PROT_GRE_OF;
65271d10453SEric Joyner 		break;
65371d10453SEric Joyner 	default:
65471d10453SEric Joyner 		return ICE_ERR_NOT_IMPL;
65571d10453SEric Joyner 	}
65671d10453SEric Joyner 
65771d10453SEric Joyner 	/* Each extraction sequence entry is a word in size, and extracts a
65871d10453SEric Joyner 	 * word-aligned offset from a protocol header.
65971d10453SEric Joyner 	 */
66071d10453SEric Joyner 	ese_bits = ICE_FLOW_FV_EXTRACT_SZ * BITS_PER_BYTE;
66171d10453SEric Joyner 
6628923de59SPiotr Kubaj 	flds[fld].xtrct.prot_id = (u8)prot_id;
66371d10453SEric Joyner 	flds[fld].xtrct.off = (ice_flds_info[fld].off / ese_bits) *
66471d10453SEric Joyner 		ICE_FLOW_FV_EXTRACT_SZ;
6657d7af7f8SEric Joyner 	flds[fld].xtrct.disp = (u8)(ice_flds_info[fld].off % ese_bits);
66671d10453SEric Joyner 	flds[fld].xtrct.idx = params->es_cnt;
66771d10453SEric Joyner 
66871d10453SEric Joyner 	/* Adjust the next field-entry index after accommodating the number of
66971d10453SEric Joyner 	 * entries this field consumes
67071d10453SEric Joyner 	 */
67171d10453SEric Joyner 	cnt = DIVIDE_AND_ROUND_UP(flds[fld].xtrct.disp +
67271d10453SEric Joyner 				  ice_flds_info[fld].size, ese_bits);
67371d10453SEric Joyner 
67471d10453SEric Joyner 	/* Fill in the extraction sequence entries needed for this field */
67571d10453SEric Joyner 	off = flds[fld].xtrct.off;
67671d10453SEric Joyner 	for (i = 0; i < cnt; i++) {
67771d10453SEric Joyner 		/* Only consume an extraction sequence entry if there is no
67871d10453SEric Joyner 		 * sibling field associated with this field or the sibling entry
67971d10453SEric Joyner 		 * already extracts the word shared with this field.
68071d10453SEric Joyner 		 */
68171d10453SEric Joyner 		if (sib == ICE_FLOW_FIELD_IDX_MAX ||
68271d10453SEric Joyner 		    flds[sib].xtrct.prot_id == ICE_PROT_ID_INVAL ||
68371d10453SEric Joyner 		    flds[sib].xtrct.off != off) {
68471d10453SEric Joyner 			u8 idx;
68571d10453SEric Joyner 
68671d10453SEric Joyner 			/* Make sure the number of extraction sequence required
68771d10453SEric Joyner 			 * does not exceed the block's capability
68871d10453SEric Joyner 			 */
68971d10453SEric Joyner 			if (params->es_cnt >= fv_words)
69071d10453SEric Joyner 				return ICE_ERR_MAX_LIMIT;
69171d10453SEric Joyner 
69271d10453SEric Joyner 			/* some blocks require a reversed field vector layout */
69371d10453SEric Joyner 			if (hw->blk[params->blk].es.reverse)
69471d10453SEric Joyner 				idx = fv_words - params->es_cnt - 1;
69571d10453SEric Joyner 			else
69671d10453SEric Joyner 				idx = params->es_cnt;
69771d10453SEric Joyner 
6988923de59SPiotr Kubaj 			params->es[idx].prot_id = (u8)prot_id;
69971d10453SEric Joyner 			params->es[idx].off = off;
70071d10453SEric Joyner 			params->es_cnt++;
70171d10453SEric Joyner 		}
70271d10453SEric Joyner 
70371d10453SEric Joyner 		off += ICE_FLOW_FV_EXTRACT_SZ;
70471d10453SEric Joyner 	}
70571d10453SEric Joyner 
706*f2635e84SEric Joyner 	return 0;
70771d10453SEric Joyner }
70871d10453SEric Joyner 
70971d10453SEric Joyner /**
71071d10453SEric Joyner  * ice_flow_create_xtrct_seq - Create an extraction sequence for given segments
71171d10453SEric Joyner  * @hw: pointer to the HW struct
71271d10453SEric Joyner  * @params: information about the flow to be processed
71371d10453SEric Joyner  *
71471d10453SEric Joyner  * This function iterates through all matched fields in the given segments, and
71571d10453SEric Joyner  * creates an extraction sequence for the fields.
71671d10453SEric Joyner  */
717*f2635e84SEric Joyner static int
71871d10453SEric Joyner ice_flow_create_xtrct_seq(struct ice_hw *hw,
71971d10453SEric Joyner 			  struct ice_flow_prof_params *params)
72071d10453SEric Joyner {
721*f2635e84SEric Joyner 	int status = 0;
72271d10453SEric Joyner 	u8 i;
72371d10453SEric Joyner 
72471d10453SEric Joyner 	for (i = 0; i < params->prof->segs_cnt; i++) {
7259c30461dSEric Joyner 		ice_declare_bitmap(match, ICE_FLOW_FIELD_IDX_MAX);
72671d10453SEric Joyner 		enum ice_flow_field j;
72771d10453SEric Joyner 
7289c30461dSEric Joyner 		ice_cp_bitmap(match, params->prof->segs[i].match,
7299c30461dSEric Joyner 			      ICE_FLOW_FIELD_IDX_MAX);
7309c30461dSEric Joyner 		ice_for_each_set_bit(j, match, ICE_FLOW_FIELD_IDX_MAX) {
73171d10453SEric Joyner 			status = ice_flow_xtract_fld(hw, params, i, j);
73271d10453SEric Joyner 			if (status)
73371d10453SEric Joyner 				return status;
7349c30461dSEric Joyner 			ice_clear_bit(j, match);
73571d10453SEric Joyner 		}
73671d10453SEric Joyner 	}
73771d10453SEric Joyner 
73871d10453SEric Joyner 	return status;
73971d10453SEric Joyner }
74071d10453SEric Joyner 
74171d10453SEric Joyner /**
74271d10453SEric Joyner  * ice_flow_proc_segs - process all packet segments associated with a profile
74371d10453SEric Joyner  * @hw: pointer to the HW struct
74471d10453SEric Joyner  * @params: information about the flow to be processed
74571d10453SEric Joyner  */
746*f2635e84SEric Joyner static int
74771d10453SEric Joyner ice_flow_proc_segs(struct ice_hw *hw, struct ice_flow_prof_params *params)
74871d10453SEric Joyner {
749*f2635e84SEric Joyner 	int status;
75071d10453SEric Joyner 
75171d10453SEric Joyner 	status = ice_flow_proc_seg_hdrs(params);
75271d10453SEric Joyner 	if (status)
75371d10453SEric Joyner 		return status;
75471d10453SEric Joyner 
75571d10453SEric Joyner 	status = ice_flow_create_xtrct_seq(hw, params);
75671d10453SEric Joyner 	if (status)
75771d10453SEric Joyner 		return status;
75871d10453SEric Joyner 
75971d10453SEric Joyner 	switch (params->blk) {
76071d10453SEric Joyner 	case ICE_BLK_RSS:
761*f2635e84SEric Joyner 		status = 0;
76271d10453SEric Joyner 		break;
76371d10453SEric Joyner 	default:
76471d10453SEric Joyner 		return ICE_ERR_NOT_IMPL;
76571d10453SEric Joyner 	}
76671d10453SEric Joyner 
76771d10453SEric Joyner 	return status;
76871d10453SEric Joyner }
76971d10453SEric Joyner 
77071d10453SEric Joyner #define ICE_FLOW_FIND_PROF_CHK_FLDS	0x00000001
77171d10453SEric Joyner #define ICE_FLOW_FIND_PROF_CHK_VSI	0x00000002
77271d10453SEric Joyner #define ICE_FLOW_FIND_PROF_NOT_CHK_DIR	0x00000004
77371d10453SEric Joyner 
77471d10453SEric Joyner /**
77571d10453SEric Joyner  * ice_flow_find_prof_conds - Find a profile matching headers and conditions
77671d10453SEric Joyner  * @hw: pointer to the HW struct
77771d10453SEric Joyner  * @blk: classification stage
77871d10453SEric Joyner  * @dir: flow direction
77971d10453SEric Joyner  * @segs: array of one or more packet segments that describe the flow
78071d10453SEric Joyner  * @segs_cnt: number of packet segments provided
78171d10453SEric Joyner  * @vsi_handle: software VSI handle to check VSI (ICE_FLOW_FIND_PROF_CHK_VSI)
78271d10453SEric Joyner  * @conds: additional conditions to be checked (ICE_FLOW_FIND_PROF_CHK_*)
78371d10453SEric Joyner  */
78471d10453SEric Joyner static struct ice_flow_prof *
78571d10453SEric Joyner ice_flow_find_prof_conds(struct ice_hw *hw, enum ice_block blk,
78671d10453SEric Joyner 			 enum ice_flow_dir dir, struct ice_flow_seg_info *segs,
78771d10453SEric Joyner 			 u8 segs_cnt, u16 vsi_handle, u32 conds)
78871d10453SEric Joyner {
78971d10453SEric Joyner 	struct ice_flow_prof *p, *prof = NULL;
79071d10453SEric Joyner 
79171d10453SEric Joyner 	ice_acquire_lock(&hw->fl_profs_locks[blk]);
7927d7af7f8SEric Joyner 	LIST_FOR_EACH_ENTRY(p, &hw->fl_profs[blk], ice_flow_prof, l_entry)
79371d10453SEric Joyner 		if ((p->dir == dir || conds & ICE_FLOW_FIND_PROF_NOT_CHK_DIR) &&
79471d10453SEric Joyner 		    segs_cnt && segs_cnt == p->segs_cnt) {
79571d10453SEric Joyner 			u8 i;
79671d10453SEric Joyner 
79771d10453SEric Joyner 			/* Check for profile-VSI association if specified */
79871d10453SEric Joyner 			if ((conds & ICE_FLOW_FIND_PROF_CHK_VSI) &&
79971d10453SEric Joyner 			    ice_is_vsi_valid(hw, vsi_handle) &&
80071d10453SEric Joyner 			    !ice_is_bit_set(p->vsis, vsi_handle))
80171d10453SEric Joyner 				continue;
80271d10453SEric Joyner 
80371d10453SEric Joyner 			/* Protocol headers must be checked. Matched fields are
80471d10453SEric Joyner 			 * checked if specified.
80571d10453SEric Joyner 			 */
80671d10453SEric Joyner 			for (i = 0; i < segs_cnt; i++)
80771d10453SEric Joyner 				if (segs[i].hdrs != p->segs[i].hdrs ||
80871d10453SEric Joyner 				    ((conds & ICE_FLOW_FIND_PROF_CHK_FLDS) &&
8099c30461dSEric Joyner 				     (ice_cmp_bitmap(segs[i].match,
8109c30461dSEric Joyner 						     p->segs[i].match,
8119c30461dSEric Joyner 						     ICE_FLOW_FIELD_IDX_MAX) ==
8129c30461dSEric Joyner 				       false)))
81371d10453SEric Joyner 					break;
81471d10453SEric Joyner 
81571d10453SEric Joyner 			/* A match is found if all segments are matched */
81671d10453SEric Joyner 			if (i == segs_cnt) {
81771d10453SEric Joyner 				prof = p;
81871d10453SEric Joyner 				break;
81971d10453SEric Joyner 			}
82071d10453SEric Joyner 		}
82171d10453SEric Joyner 	ice_release_lock(&hw->fl_profs_locks[blk]);
82271d10453SEric Joyner 
82371d10453SEric Joyner 	return prof;
82471d10453SEric Joyner }
82571d10453SEric Joyner 
82671d10453SEric Joyner /**
82771d10453SEric Joyner  * ice_flow_find_prof - Look up a profile matching headers and matched fields
82871d10453SEric Joyner  * @hw: pointer to the HW struct
82971d10453SEric Joyner  * @blk: classification stage
83071d10453SEric Joyner  * @dir: flow direction
83171d10453SEric Joyner  * @segs: array of one or more packet segments that describe the flow
83271d10453SEric Joyner  * @segs_cnt: number of packet segments provided
83371d10453SEric Joyner  */
83471d10453SEric Joyner u64
83571d10453SEric Joyner ice_flow_find_prof(struct ice_hw *hw, enum ice_block blk, enum ice_flow_dir dir,
83671d10453SEric Joyner 		   struct ice_flow_seg_info *segs, u8 segs_cnt)
83771d10453SEric Joyner {
83871d10453SEric Joyner 	struct ice_flow_prof *p;
83971d10453SEric Joyner 
84071d10453SEric Joyner 	p = ice_flow_find_prof_conds(hw, blk, dir, segs, segs_cnt,
84171d10453SEric Joyner 				     ICE_MAX_VSI, ICE_FLOW_FIND_PROF_CHK_FLDS);
84271d10453SEric Joyner 
84371d10453SEric Joyner 	return p ? p->id : ICE_FLOW_PROF_ID_INVAL;
84471d10453SEric Joyner }
84571d10453SEric Joyner 
84671d10453SEric Joyner /**
84771d10453SEric Joyner  * ice_flow_find_prof_id - Look up a profile with given profile ID
84871d10453SEric Joyner  * @hw: pointer to the HW struct
84971d10453SEric Joyner  * @blk: classification stage
85071d10453SEric Joyner  * @prof_id: unique ID to identify this flow profile
85171d10453SEric Joyner  */
85271d10453SEric Joyner static struct ice_flow_prof *
85371d10453SEric Joyner ice_flow_find_prof_id(struct ice_hw *hw, enum ice_block blk, u64 prof_id)
85471d10453SEric Joyner {
85571d10453SEric Joyner 	struct ice_flow_prof *p;
85671d10453SEric Joyner 
8577d7af7f8SEric Joyner 	LIST_FOR_EACH_ENTRY(p, &hw->fl_profs[blk], ice_flow_prof, l_entry)
85871d10453SEric Joyner 		if (p->id == prof_id)
85971d10453SEric Joyner 			return p;
86071d10453SEric Joyner 
86171d10453SEric Joyner 	return NULL;
86271d10453SEric Joyner }
86371d10453SEric Joyner 
86471d10453SEric Joyner /**
8657d7af7f8SEric Joyner  * ice_flow_get_hw_prof - return the HW profile for a specific profile ID handle
86671d10453SEric Joyner  * @hw: pointer to the HW struct
86771d10453SEric Joyner  * @blk: classification stage
8687d7af7f8SEric Joyner  * @prof_id: the profile ID handle
8697d7af7f8SEric Joyner  * @hw_prof_id: pointer to variable to receive the HW profile ID
87071d10453SEric Joyner  */
871*f2635e84SEric Joyner int
8727d7af7f8SEric Joyner ice_flow_get_hw_prof(struct ice_hw *hw, enum ice_block blk, u64 prof_id,
8737d7af7f8SEric Joyner 		     u8 *hw_prof_id)
87471d10453SEric Joyner {
8757d7af7f8SEric Joyner 	struct ice_prof_map *map;
876*f2635e84SEric Joyner 	int status = ICE_ERR_DOES_NOT_EXIST;
87771d10453SEric Joyner 
8787d7af7f8SEric Joyner 	ice_acquire_lock(&hw->blk[blk].es.prof_map_lock);
8797d7af7f8SEric Joyner 	map = ice_search_prof_id(hw, blk, prof_id);
8807d7af7f8SEric Joyner 	if (map) {
8817d7af7f8SEric Joyner 		*hw_prof_id = map->prof_id;
882*f2635e84SEric Joyner 		status = 0;
8837d7af7f8SEric Joyner 	}
8847d7af7f8SEric Joyner 	ice_release_lock(&hw->blk[blk].es.prof_map_lock);
8857d7af7f8SEric Joyner 	return status;
88671d10453SEric Joyner }
88771d10453SEric Joyner 
88871d10453SEric Joyner /**
88971d10453SEric Joyner  * ice_flow_add_prof_sync - Add a flow profile for packet segments and fields
89071d10453SEric Joyner  * @hw: pointer to the HW struct
89171d10453SEric Joyner  * @blk: classification stage
89271d10453SEric Joyner  * @dir: flow direction
89371d10453SEric Joyner  * @prof_id: unique ID to identify this flow profile
89471d10453SEric Joyner  * @segs: array of one or more packet segments that describe the flow
89571d10453SEric Joyner  * @segs_cnt: number of packet segments provided
89671d10453SEric Joyner  * @acts: array of default actions
89771d10453SEric Joyner  * @acts_cnt: number of default actions
89871d10453SEric Joyner  * @prof: stores the returned flow profile added
89971d10453SEric Joyner  *
90071d10453SEric Joyner  * Assumption: the caller has acquired the lock to the profile list
90171d10453SEric Joyner  */
902*f2635e84SEric Joyner static int
90371d10453SEric Joyner ice_flow_add_prof_sync(struct ice_hw *hw, enum ice_block blk,
90471d10453SEric Joyner 		       enum ice_flow_dir dir, u64 prof_id,
90571d10453SEric Joyner 		       struct ice_flow_seg_info *segs, u8 segs_cnt,
90671d10453SEric Joyner 		       struct ice_flow_action *acts, u8 acts_cnt,
90771d10453SEric Joyner 		       struct ice_flow_prof **prof)
90871d10453SEric Joyner {
9097d7af7f8SEric Joyner 	struct ice_flow_prof_params *params;
910*f2635e84SEric Joyner 	int status;
91171d10453SEric Joyner 	u8 i;
91271d10453SEric Joyner 
91371d10453SEric Joyner 	if (!prof || (acts_cnt && !acts))
91471d10453SEric Joyner 		return ICE_ERR_BAD_PTR;
91571d10453SEric Joyner 
9167d7af7f8SEric Joyner 	params = (struct ice_flow_prof_params *)ice_malloc(hw, sizeof(*params));
9177d7af7f8SEric Joyner 	if (!params)
91871d10453SEric Joyner 		return ICE_ERR_NO_MEMORY;
91971d10453SEric Joyner 
9207d7af7f8SEric Joyner 	params->prof = (struct ice_flow_prof *)
9217d7af7f8SEric Joyner 		ice_malloc(hw, sizeof(*params->prof));
9227d7af7f8SEric Joyner 	if (!params->prof) {
9237d7af7f8SEric Joyner 		status = ICE_ERR_NO_MEMORY;
9247d7af7f8SEric Joyner 		goto free_params;
9257d7af7f8SEric Joyner 	}
9267d7af7f8SEric Joyner 
92771d10453SEric Joyner 	/* initialize extraction sequence to all invalid (0xff) */
92871d10453SEric Joyner 	for (i = 0; i < ICE_MAX_FV_WORDS; i++) {
9297d7af7f8SEric Joyner 		params->es[i].prot_id = ICE_PROT_INVALID;
9307d7af7f8SEric Joyner 		params->es[i].off = ICE_FV_OFFSET_INVAL;
93171d10453SEric Joyner 	}
93271d10453SEric Joyner 
9337d7af7f8SEric Joyner 	params->blk = blk;
9347d7af7f8SEric Joyner 	params->prof->id = prof_id;
9357d7af7f8SEric Joyner 	params->prof->dir = dir;
9367d7af7f8SEric Joyner 	params->prof->segs_cnt = segs_cnt;
93771d10453SEric Joyner 
93871d10453SEric Joyner 	/* Make a copy of the segments that need to be persistent in the flow
93971d10453SEric Joyner 	 * profile instance
94071d10453SEric Joyner 	 */
94171d10453SEric Joyner 	for (i = 0; i < segs_cnt; i++)
9427d7af7f8SEric Joyner 		ice_memcpy(&params->prof->segs[i], &segs[i], sizeof(*segs),
94371d10453SEric Joyner 			   ICE_NONDMA_TO_NONDMA);
94471d10453SEric Joyner 
9457d7af7f8SEric Joyner 	status = ice_flow_proc_segs(hw, params);
94671d10453SEric Joyner 	if (status) {
9477d7af7f8SEric Joyner 		ice_debug(hw, ICE_DBG_FLOW, "Error processing a flow's packet segments\n");
94871d10453SEric Joyner 		goto out;
94971d10453SEric Joyner 	}
95071d10453SEric Joyner 
95171d10453SEric Joyner 	/* Add a HW profile for this flow profile */
9528923de59SPiotr Kubaj 	status = ice_add_prof(hw, blk, prof_id, params->ptypes, params->es);
95371d10453SEric Joyner 	if (status) {
95471d10453SEric Joyner 		ice_debug(hw, ICE_DBG_FLOW, "Error adding a HW flow profile\n");
95571d10453SEric Joyner 		goto out;
95671d10453SEric Joyner 	}
95771d10453SEric Joyner 
9587d7af7f8SEric Joyner 	*prof = params->prof;
95971d10453SEric Joyner 
96071d10453SEric Joyner out:
96171d10453SEric Joyner 	if (status) {
9627d7af7f8SEric Joyner 		ice_free(hw, params->prof);
96371d10453SEric Joyner 	}
9647d7af7f8SEric Joyner free_params:
9657d7af7f8SEric Joyner 	ice_free(hw, params);
96671d10453SEric Joyner 
96771d10453SEric Joyner 	return status;
96871d10453SEric Joyner }
96971d10453SEric Joyner 
97071d10453SEric Joyner /**
97171d10453SEric Joyner  * ice_flow_rem_prof_sync - remove a flow profile
97271d10453SEric Joyner  * @hw: pointer to the hardware structure
97371d10453SEric Joyner  * @blk: classification stage
97471d10453SEric Joyner  * @prof: pointer to flow profile to remove
97571d10453SEric Joyner  *
97671d10453SEric Joyner  * Assumption: the caller has acquired the lock to the profile list
97771d10453SEric Joyner  */
978*f2635e84SEric Joyner static int
97971d10453SEric Joyner ice_flow_rem_prof_sync(struct ice_hw *hw, enum ice_block blk,
98071d10453SEric Joyner 		       struct ice_flow_prof *prof)
98171d10453SEric Joyner {
982*f2635e84SEric Joyner 	int status;
98371d10453SEric Joyner 
98471d10453SEric Joyner 	/* Remove all hardware profiles associated with this flow profile */
98571d10453SEric Joyner 	status = ice_rem_prof(hw, blk, prof->id);
98671d10453SEric Joyner 	if (!status) {
98771d10453SEric Joyner 		LIST_DEL(&prof->l_entry);
98871d10453SEric Joyner 		ice_free(hw, prof);
98971d10453SEric Joyner 	}
99071d10453SEric Joyner 
99171d10453SEric Joyner 	return status;
99271d10453SEric Joyner }
99371d10453SEric Joyner 
99471d10453SEric Joyner /**
99571d10453SEric Joyner  * ice_flow_assoc_vsig_vsi - associate a VSI with VSIG
99671d10453SEric Joyner  * @hw: pointer to the hardware structure
99771d10453SEric Joyner  * @blk: classification stage
99871d10453SEric Joyner  * @vsi_handle: software VSI handle
99971d10453SEric Joyner  * @vsig: target VSI group
100071d10453SEric Joyner  *
100171d10453SEric Joyner  * Assumption: the caller has already verified that the VSI to
100271d10453SEric Joyner  * be added has the same characteristics as the VSIG and will
100371d10453SEric Joyner  * thereby have access to all resources added to that VSIG.
100471d10453SEric Joyner  */
1005*f2635e84SEric Joyner int
100671d10453SEric Joyner ice_flow_assoc_vsig_vsi(struct ice_hw *hw, enum ice_block blk, u16 vsi_handle,
100771d10453SEric Joyner 			u16 vsig)
100871d10453SEric Joyner {
1009*f2635e84SEric Joyner 	int status;
101071d10453SEric Joyner 
101171d10453SEric Joyner 	if (!ice_is_vsi_valid(hw, vsi_handle) || blk >= ICE_BLK_COUNT)
101271d10453SEric Joyner 		return ICE_ERR_PARAM;
101371d10453SEric Joyner 
101471d10453SEric Joyner 	ice_acquire_lock(&hw->fl_profs_locks[blk]);
101571d10453SEric Joyner 	status = ice_add_vsi_flow(hw, blk, ice_get_hw_vsi_num(hw, vsi_handle),
101671d10453SEric Joyner 				  vsig);
101771d10453SEric Joyner 	ice_release_lock(&hw->fl_profs_locks[blk]);
101871d10453SEric Joyner 
101971d10453SEric Joyner 	return status;
102071d10453SEric Joyner }
102171d10453SEric Joyner 
102271d10453SEric Joyner /**
102371d10453SEric Joyner  * ice_flow_assoc_prof - associate a VSI with a flow profile
102471d10453SEric Joyner  * @hw: pointer to the hardware structure
102571d10453SEric Joyner  * @blk: classification stage
102671d10453SEric Joyner  * @prof: pointer to flow profile
102771d10453SEric Joyner  * @vsi_handle: software VSI handle
102871d10453SEric Joyner  *
102971d10453SEric Joyner  * Assumption: the caller has acquired the lock to the profile list
103071d10453SEric Joyner  * and the software VSI handle has been validated
103171d10453SEric Joyner  */
1032*f2635e84SEric Joyner static int
103371d10453SEric Joyner ice_flow_assoc_prof(struct ice_hw *hw, enum ice_block blk,
103471d10453SEric Joyner 		    struct ice_flow_prof *prof, u16 vsi_handle)
103571d10453SEric Joyner {
1036*f2635e84SEric Joyner 	int status = 0;
103771d10453SEric Joyner 
103871d10453SEric Joyner 	if (!ice_is_bit_set(prof->vsis, vsi_handle)) {
103971d10453SEric Joyner 		status = ice_add_prof_id_flow(hw, blk,
104071d10453SEric Joyner 					      ice_get_hw_vsi_num(hw,
104171d10453SEric Joyner 								 vsi_handle),
104271d10453SEric Joyner 					      prof->id);
104371d10453SEric Joyner 		if (!status)
104471d10453SEric Joyner 			ice_set_bit(vsi_handle, prof->vsis);
104571d10453SEric Joyner 		else
10467d7af7f8SEric Joyner 			ice_debug(hw, ICE_DBG_FLOW, "HW profile add failed, %d\n",
104771d10453SEric Joyner 				  status);
104871d10453SEric Joyner 	}
104971d10453SEric Joyner 
105071d10453SEric Joyner 	return status;
105171d10453SEric Joyner }
105271d10453SEric Joyner 
105371d10453SEric Joyner /**
105471d10453SEric Joyner  * ice_flow_disassoc_prof - disassociate a VSI from a flow profile
105571d10453SEric Joyner  * @hw: pointer to the hardware structure
105671d10453SEric Joyner  * @blk: classification stage
105771d10453SEric Joyner  * @prof: pointer to flow profile
105871d10453SEric Joyner  * @vsi_handle: software VSI handle
105971d10453SEric Joyner  *
106071d10453SEric Joyner  * Assumption: the caller has acquired the lock to the profile list
106171d10453SEric Joyner  * and the software VSI handle has been validated
106271d10453SEric Joyner  */
1063*f2635e84SEric Joyner static int
106471d10453SEric Joyner ice_flow_disassoc_prof(struct ice_hw *hw, enum ice_block blk,
106571d10453SEric Joyner 		       struct ice_flow_prof *prof, u16 vsi_handle)
106671d10453SEric Joyner {
1067*f2635e84SEric Joyner 	int status = 0;
106871d10453SEric Joyner 
106971d10453SEric Joyner 	if (ice_is_bit_set(prof->vsis, vsi_handle)) {
107071d10453SEric Joyner 		status = ice_rem_prof_id_flow(hw, blk,
107171d10453SEric Joyner 					      ice_get_hw_vsi_num(hw,
107271d10453SEric Joyner 								 vsi_handle),
107371d10453SEric Joyner 					      prof->id);
107471d10453SEric Joyner 		if (!status)
107571d10453SEric Joyner 			ice_clear_bit(vsi_handle, prof->vsis);
107671d10453SEric Joyner 		else
10777d7af7f8SEric Joyner 			ice_debug(hw, ICE_DBG_FLOW, "HW profile remove failed, %d\n",
107871d10453SEric Joyner 				  status);
107971d10453SEric Joyner 	}
108071d10453SEric Joyner 
108171d10453SEric Joyner 	return status;
108271d10453SEric Joyner }
108371d10453SEric Joyner 
108471d10453SEric Joyner /**
108571d10453SEric Joyner  * ice_flow_add_prof - Add a flow profile for packet segments and matched fields
108671d10453SEric Joyner  * @hw: pointer to the HW struct
108771d10453SEric Joyner  * @blk: classification stage
108871d10453SEric Joyner  * @dir: flow direction
108971d10453SEric Joyner  * @prof_id: unique ID to identify this flow profile
109071d10453SEric Joyner  * @segs: array of one or more packet segments that describe the flow
109171d10453SEric Joyner  * @segs_cnt: number of packet segments provided
109271d10453SEric Joyner  * @acts: array of default actions
109371d10453SEric Joyner  * @acts_cnt: number of default actions
109471d10453SEric Joyner  * @prof: stores the returned flow profile added
109571d10453SEric Joyner  */
1096*f2635e84SEric Joyner static int
109771d10453SEric Joyner ice_flow_add_prof(struct ice_hw *hw, enum ice_block blk, enum ice_flow_dir dir,
109871d10453SEric Joyner 		  u64 prof_id, struct ice_flow_seg_info *segs, u8 segs_cnt,
109971d10453SEric Joyner 		  struct ice_flow_action *acts, u8 acts_cnt,
110071d10453SEric Joyner 		  struct ice_flow_prof **prof)
110171d10453SEric Joyner {
1102*f2635e84SEric Joyner 	int status;
110371d10453SEric Joyner 
110471d10453SEric Joyner 	if (segs_cnt > ICE_FLOW_SEG_MAX)
110571d10453SEric Joyner 		return ICE_ERR_MAX_LIMIT;
110671d10453SEric Joyner 
110771d10453SEric Joyner 	if (!segs_cnt)
110871d10453SEric Joyner 		return ICE_ERR_PARAM;
110971d10453SEric Joyner 
111071d10453SEric Joyner 	if (!segs)
111171d10453SEric Joyner 		return ICE_ERR_BAD_PTR;
111271d10453SEric Joyner 
111371d10453SEric Joyner 	status = ice_flow_val_hdrs(segs, segs_cnt);
111471d10453SEric Joyner 	if (status)
111571d10453SEric Joyner 		return status;
111671d10453SEric Joyner 
111771d10453SEric Joyner 	ice_acquire_lock(&hw->fl_profs_locks[blk]);
111871d10453SEric Joyner 
111971d10453SEric Joyner 	status = ice_flow_add_prof_sync(hw, blk, dir, prof_id, segs, segs_cnt,
112071d10453SEric Joyner 					acts, acts_cnt, prof);
112171d10453SEric Joyner 	if (!status)
112271d10453SEric Joyner 		LIST_ADD(&(*prof)->l_entry, &hw->fl_profs[blk]);
112371d10453SEric Joyner 
112471d10453SEric Joyner 	ice_release_lock(&hw->fl_profs_locks[blk]);
112571d10453SEric Joyner 
112671d10453SEric Joyner 	return status;
112771d10453SEric Joyner }
112871d10453SEric Joyner 
112971d10453SEric Joyner /**
113071d10453SEric Joyner  * ice_flow_rem_prof - Remove a flow profile and all entries associated with it
113171d10453SEric Joyner  * @hw: pointer to the HW struct
113271d10453SEric Joyner  * @blk: the block for which the flow profile is to be removed
113371d10453SEric Joyner  * @prof_id: unique ID of the flow profile to be removed
113471d10453SEric Joyner  */
1135*f2635e84SEric Joyner static int
113671d10453SEric Joyner ice_flow_rem_prof(struct ice_hw *hw, enum ice_block blk, u64 prof_id)
113771d10453SEric Joyner {
113871d10453SEric Joyner 	struct ice_flow_prof *prof;
1139*f2635e84SEric Joyner 	int status;
114071d10453SEric Joyner 
114171d10453SEric Joyner 	ice_acquire_lock(&hw->fl_profs_locks[blk]);
114271d10453SEric Joyner 
114371d10453SEric Joyner 	prof = ice_flow_find_prof_id(hw, blk, prof_id);
114471d10453SEric Joyner 	if (!prof) {
114571d10453SEric Joyner 		status = ICE_ERR_DOES_NOT_EXIST;
114671d10453SEric Joyner 		goto out;
114771d10453SEric Joyner 	}
114871d10453SEric Joyner 
114971d10453SEric Joyner 	/* prof becomes invalid after the call */
115071d10453SEric Joyner 	status = ice_flow_rem_prof_sync(hw, blk, prof);
115171d10453SEric Joyner 
115271d10453SEric Joyner out:
115371d10453SEric Joyner 	ice_release_lock(&hw->fl_profs_locks[blk]);
115471d10453SEric Joyner 
115571d10453SEric Joyner 	return status;
115671d10453SEric Joyner }
115771d10453SEric Joyner 
115871d10453SEric Joyner /**
115971d10453SEric Joyner  * ice_flow_set_fld_ext - specifies locations of field from entry's input buffer
116071d10453SEric Joyner  * @seg: packet segment the field being set belongs to
116171d10453SEric Joyner  * @fld: field to be set
116271d10453SEric Joyner  * @field_type: type of the field
116371d10453SEric Joyner  * @val_loc: if not ICE_FLOW_FLD_OFF_INVAL, location of the value to match from
116471d10453SEric Joyner  *           entry's input buffer
116571d10453SEric Joyner  * @mask_loc: if not ICE_FLOW_FLD_OFF_INVAL, location of mask value from entry's
116671d10453SEric Joyner  *            input buffer
116771d10453SEric Joyner  * @last_loc: if not ICE_FLOW_FLD_OFF_INVAL, location of last/upper value from
116871d10453SEric Joyner  *            entry's input buffer
116971d10453SEric Joyner  *
117071d10453SEric Joyner  * This helper function stores information of a field being matched, including
117171d10453SEric Joyner  * the type of the field and the locations of the value to match, the mask, and
11727d7af7f8SEric Joyner  * the upper-bound value in the start of the input buffer for a flow entry.
117371d10453SEric Joyner  * This function should only be used for fixed-size data structures.
117471d10453SEric Joyner  *
117571d10453SEric Joyner  * This function also opportunistically determines the protocol headers to be
117671d10453SEric Joyner  * present based on the fields being set. Some fields cannot be used alone to
117771d10453SEric Joyner  * determine the protocol headers present. Sometimes, fields for particular
117871d10453SEric Joyner  * protocol headers are not matched. In those cases, the protocol headers
117971d10453SEric Joyner  * must be explicitly set.
118071d10453SEric Joyner  */
118171d10453SEric Joyner static void
118271d10453SEric Joyner ice_flow_set_fld_ext(struct ice_flow_seg_info *seg, enum ice_flow_field fld,
118371d10453SEric Joyner 		     enum ice_flow_fld_match_type field_type, u16 val_loc,
118471d10453SEric Joyner 		     u16 mask_loc, u16 last_loc)
118571d10453SEric Joyner {
11869c30461dSEric Joyner 	ice_set_bit(fld, seg->match);
118771d10453SEric Joyner 	if (field_type == ICE_FLOW_FLD_TYPE_RANGE)
11889c30461dSEric Joyner 		ice_set_bit(fld, seg->range);
118971d10453SEric Joyner 
119071d10453SEric Joyner 	seg->fields[fld].type = field_type;
119171d10453SEric Joyner 	seg->fields[fld].src.val = val_loc;
119271d10453SEric Joyner 	seg->fields[fld].src.mask = mask_loc;
119371d10453SEric Joyner 	seg->fields[fld].src.last = last_loc;
119471d10453SEric Joyner 
119571d10453SEric Joyner 	ICE_FLOW_SET_HDRS(seg, ice_flds_info[fld].hdr);
119671d10453SEric Joyner }
119771d10453SEric Joyner 
119871d10453SEric Joyner /**
119971d10453SEric Joyner  * ice_flow_set_fld - specifies locations of field from entry's input buffer
120071d10453SEric Joyner  * @seg: packet segment the field being set belongs to
120171d10453SEric Joyner  * @fld: field to be set
120271d10453SEric Joyner  * @val_loc: if not ICE_FLOW_FLD_OFF_INVAL, location of the value to match from
120371d10453SEric Joyner  *           entry's input buffer
120471d10453SEric Joyner  * @mask_loc: if not ICE_FLOW_FLD_OFF_INVAL, location of mask value from entry's
120571d10453SEric Joyner  *            input buffer
120671d10453SEric Joyner  * @last_loc: if not ICE_FLOW_FLD_OFF_INVAL, location of last/upper value from
120771d10453SEric Joyner  *            entry's input buffer
120871d10453SEric Joyner  * @range: indicate if field being matched is to be in a range
120971d10453SEric Joyner  *
121071d10453SEric Joyner  * This function specifies the locations, in the form of byte offsets from the
121171d10453SEric Joyner  * start of the input buffer for a flow entry, from where the value to match,
121271d10453SEric Joyner  * the mask value, and upper value can be extracted. These locations are then
121371d10453SEric Joyner  * stored in the flow profile. When adding a flow entry associated with the
121471d10453SEric Joyner  * flow profile, these locations will be used to quickly extract the values and
121571d10453SEric Joyner  * create the content of a match entry. This function should only be used for
121671d10453SEric Joyner  * fixed-size data structures.
121771d10453SEric Joyner  */
12187d7af7f8SEric Joyner static void
121971d10453SEric Joyner ice_flow_set_fld(struct ice_flow_seg_info *seg, enum ice_flow_field fld,
122071d10453SEric Joyner 		 u16 val_loc, u16 mask_loc, u16 last_loc, bool range)
122171d10453SEric Joyner {
122271d10453SEric Joyner 	enum ice_flow_fld_match_type t = range ?
122371d10453SEric Joyner 		ICE_FLOW_FLD_TYPE_RANGE : ICE_FLOW_FLD_TYPE_REG;
122471d10453SEric Joyner 
122571d10453SEric Joyner 	ice_flow_set_fld_ext(seg, fld, t, val_loc, mask_loc, last_loc);
122671d10453SEric Joyner }
122771d10453SEric Joyner 
122871d10453SEric Joyner /**
122971d10453SEric Joyner  * ice_flow_set_fld_prefix - sets locations of prefix field from entry's buf
123071d10453SEric Joyner  * @seg: packet segment the field being set belongs to
123171d10453SEric Joyner  * @fld: field to be set
123271d10453SEric Joyner  * @val_loc: if not ICE_FLOW_FLD_OFF_INVAL, location of the value to match from
123371d10453SEric Joyner  *           entry's input buffer
123471d10453SEric Joyner  * @pref_loc: location of prefix value from entry's input buffer
123571d10453SEric Joyner  * @pref_sz: size of the location holding the prefix value
123671d10453SEric Joyner  *
123771d10453SEric Joyner  * This function specifies the locations, in the form of byte offsets from the
123871d10453SEric Joyner  * start of the input buffer for a flow entry, from where the value to match
123971d10453SEric Joyner  * and the IPv4 prefix value can be extracted. These locations are then stored
124071d10453SEric Joyner  * in the flow profile. When adding flow entries to the associated flow profile,
124171d10453SEric Joyner  * these locations can be used to quickly extract the values to create the
124271d10453SEric Joyner  * content of a match entry. This function should only be used for fixed-size
124371d10453SEric Joyner  * data structures.
124471d10453SEric Joyner  */
124571d10453SEric Joyner void
124671d10453SEric Joyner ice_flow_set_fld_prefix(struct ice_flow_seg_info *seg, enum ice_flow_field fld,
124771d10453SEric Joyner 			u16 val_loc, u16 pref_loc, u8 pref_sz)
124871d10453SEric Joyner {
124971d10453SEric Joyner 	/* For this type of field, the "mask" location is for the prefix value's
125071d10453SEric Joyner 	 * location and the "last" location is for the size of the location of
125171d10453SEric Joyner 	 * the prefix value.
125271d10453SEric Joyner 	 */
125371d10453SEric Joyner 	ice_flow_set_fld_ext(seg, fld, ICE_FLOW_FLD_TYPE_PREFIX, val_loc,
125471d10453SEric Joyner 			     pref_loc, (u16)pref_sz);
125571d10453SEric Joyner }
125671d10453SEric Joyner 
125771d10453SEric Joyner #define ICE_FLOW_RSS_SEG_HDR_L3_MASKS \
125871d10453SEric Joyner 	(ICE_FLOW_SEG_HDR_IPV4 | ICE_FLOW_SEG_HDR_IPV6)
125971d10453SEric Joyner 
126071d10453SEric Joyner #define ICE_FLOW_RSS_SEG_HDR_L4_MASKS \
12617d7af7f8SEric Joyner 	(ICE_FLOW_SEG_HDR_TCP | ICE_FLOW_SEG_HDR_UDP | ICE_FLOW_SEG_HDR_SCTP)
126271d10453SEric Joyner 
126371d10453SEric Joyner #define ICE_FLOW_RSS_SEG_HDR_VAL_MASKS \
126471d10453SEric Joyner 	(ICE_FLOW_RSS_SEG_HDR_L3_MASKS | \
126571d10453SEric Joyner 	 ICE_FLOW_RSS_SEG_HDR_L4_MASKS)
126671d10453SEric Joyner 
126771d10453SEric Joyner /**
126871d10453SEric Joyner  * ice_flow_set_rss_seg_info - setup packet segments for RSS
126971d10453SEric Joyner  * @segs: pointer to the flow field segment(s)
1270d08b8680SEric Joyner  * @seg_cnt: segment count
1271d08b8680SEric Joyner  * @cfg: configure parameters
127271d10453SEric Joyner  *
127371d10453SEric Joyner  * Helper function to extract fields from hash bitmap and use flow
127471d10453SEric Joyner  * header value to set flow field segment for further use in flow
127571d10453SEric Joyner  * profile entry or removal.
127671d10453SEric Joyner  */
1277*f2635e84SEric Joyner static int
1278d08b8680SEric Joyner ice_flow_set_rss_seg_info(struct ice_flow_seg_info *segs, u8 seg_cnt,
1279d08b8680SEric Joyner 			  const struct ice_rss_hash_cfg *cfg)
128071d10453SEric Joyner {
1281d08b8680SEric Joyner 	struct ice_flow_seg_info *seg;
12827d7af7f8SEric Joyner 	u64 val;
12838923de59SPiotr Kubaj 	u16 i;
128471d10453SEric Joyner 
1285d08b8680SEric Joyner 	/* set inner most segment */
1286d08b8680SEric Joyner 	seg = &segs[seg_cnt - 1];
1287d08b8680SEric Joyner 
1288d08b8680SEric Joyner 	ice_for_each_set_bit(i, (const ice_bitmap_t *)&cfg->hash_flds,
12898923de59SPiotr Kubaj 			     (u16)ICE_FLOW_FIELD_IDX_MAX)
1290d08b8680SEric Joyner 		ice_flow_set_fld(seg, (enum ice_flow_field)i,
12917d7af7f8SEric Joyner 				 ICE_FLOW_FLD_OFF_INVAL, ICE_FLOW_FLD_OFF_INVAL,
129271d10453SEric Joyner 				 ICE_FLOW_FLD_OFF_INVAL, false);
12937d7af7f8SEric Joyner 
1294d08b8680SEric Joyner 	ICE_FLOW_SET_HDRS(seg, cfg->addl_hdrs);
129571d10453SEric Joyner 
1296d08b8680SEric Joyner 	/* set outer most header */
1297d08b8680SEric Joyner 	if (cfg->hdr_type == ICE_RSS_INNER_HEADERS_W_OUTER_IPV4)
1298d08b8680SEric Joyner 		segs[ICE_RSS_OUTER_HEADERS].hdrs |= ICE_FLOW_SEG_HDR_IPV4 |
129956429daeSEric Joyner 						    ICE_FLOW_SEG_HDR_IPV_FRAG |
1300d08b8680SEric Joyner 						    ICE_FLOW_SEG_HDR_IPV_OTHER;
1301d08b8680SEric Joyner 	else if (cfg->hdr_type == ICE_RSS_INNER_HEADERS_W_OUTER_IPV6)
1302d08b8680SEric Joyner 		segs[ICE_RSS_OUTER_HEADERS].hdrs |= ICE_FLOW_SEG_HDR_IPV6 |
130356429daeSEric Joyner 						    ICE_FLOW_SEG_HDR_IPV_FRAG |
130456429daeSEric Joyner 						    ICE_FLOW_SEG_HDR_IPV_OTHER;
130556429daeSEric Joyner 	else if (cfg->hdr_type == ICE_RSS_INNER_HEADERS_W_OUTER_IPV4_GRE)
130656429daeSEric Joyner 		segs[ICE_RSS_OUTER_HEADERS].hdrs |= ICE_FLOW_SEG_HDR_IPV4 |
130756429daeSEric Joyner 						    ICE_FLOW_SEG_HDR_GRE |
130856429daeSEric Joyner 						    ICE_FLOW_SEG_HDR_IPV_OTHER;
130956429daeSEric Joyner 	else if (cfg->hdr_type == ICE_RSS_INNER_HEADERS_W_OUTER_IPV6_GRE)
131056429daeSEric Joyner 		segs[ICE_RSS_OUTER_HEADERS].hdrs |= ICE_FLOW_SEG_HDR_IPV6 |
131156429daeSEric Joyner 						    ICE_FLOW_SEG_HDR_GRE |
1312d08b8680SEric Joyner 						    ICE_FLOW_SEG_HDR_IPV_OTHER;
1313d08b8680SEric Joyner 
1314d08b8680SEric Joyner 	if (seg->hdrs & ~ICE_FLOW_RSS_SEG_HDR_VAL_MASKS)
131571d10453SEric Joyner 		return ICE_ERR_PARAM;
131671d10453SEric Joyner 
1317d08b8680SEric Joyner 	val = (u64)(seg->hdrs & ICE_FLOW_RSS_SEG_HDR_L3_MASKS);
131871d10453SEric Joyner 	if (val && !ice_is_pow2(val))
131971d10453SEric Joyner 		return ICE_ERR_CFG;
132071d10453SEric Joyner 
1321d08b8680SEric Joyner 	val = (u64)(seg->hdrs & ICE_FLOW_RSS_SEG_HDR_L4_MASKS);
132271d10453SEric Joyner 	if (val && !ice_is_pow2(val))
132371d10453SEric Joyner 		return ICE_ERR_CFG;
132471d10453SEric Joyner 
1325*f2635e84SEric Joyner 	return 0;
132671d10453SEric Joyner }
132771d10453SEric Joyner 
132871d10453SEric Joyner /**
132971d10453SEric Joyner  * ice_rem_vsi_rss_list - remove VSI from RSS list
133071d10453SEric Joyner  * @hw: pointer to the hardware structure
133171d10453SEric Joyner  * @vsi_handle: software VSI handle
133271d10453SEric Joyner  *
133371d10453SEric Joyner  * Remove the VSI from all RSS configurations in the list.
133471d10453SEric Joyner  */
133571d10453SEric Joyner void ice_rem_vsi_rss_list(struct ice_hw *hw, u16 vsi_handle)
133671d10453SEric Joyner {
133771d10453SEric Joyner 	struct ice_rss_cfg *r, *tmp;
133871d10453SEric Joyner 
133971d10453SEric Joyner 	if (LIST_EMPTY(&hw->rss_list_head))
134071d10453SEric Joyner 		return;
134171d10453SEric Joyner 
134271d10453SEric Joyner 	ice_acquire_lock(&hw->rss_locks);
134371d10453SEric Joyner 	LIST_FOR_EACH_ENTRY_SAFE(r, tmp, &hw->rss_list_head,
13447d7af7f8SEric Joyner 				 ice_rss_cfg, l_entry)
134571d10453SEric Joyner 		if (ice_test_and_clear_bit(vsi_handle, r->vsis))
134671d10453SEric Joyner 			if (!ice_is_any_bit_set(r->vsis, ICE_MAX_VSI)) {
134771d10453SEric Joyner 				LIST_DEL(&r->l_entry);
134871d10453SEric Joyner 				ice_free(hw, r);
134971d10453SEric Joyner 			}
135071d10453SEric Joyner 	ice_release_lock(&hw->rss_locks);
135171d10453SEric Joyner }
135271d10453SEric Joyner 
135371d10453SEric Joyner /**
135471d10453SEric Joyner  * ice_rem_vsi_rss_cfg - remove RSS configurations associated with VSI
135571d10453SEric Joyner  * @hw: pointer to the hardware structure
135671d10453SEric Joyner  * @vsi_handle: software VSI handle
135771d10453SEric Joyner  *
135871d10453SEric Joyner  * This function will iterate through all flow profiles and disassociate
135971d10453SEric Joyner  * the VSI from that profile. If the flow profile has no VSIs it will
136071d10453SEric Joyner  * be removed.
136171d10453SEric Joyner  */
1362*f2635e84SEric Joyner int ice_rem_vsi_rss_cfg(struct ice_hw *hw, u16 vsi_handle)
136371d10453SEric Joyner {
136471d10453SEric Joyner 	const enum ice_block blk = ICE_BLK_RSS;
136571d10453SEric Joyner 	struct ice_flow_prof *p, *t;
1366*f2635e84SEric Joyner 	int status = 0;
13679dc2f6e2SEric Joyner 	u16 vsig;
136871d10453SEric Joyner 
136971d10453SEric Joyner 	if (!ice_is_vsi_valid(hw, vsi_handle))
137071d10453SEric Joyner 		return ICE_ERR_PARAM;
137171d10453SEric Joyner 
137271d10453SEric Joyner 	if (LIST_EMPTY(&hw->fl_profs[blk]))
1373*f2635e84SEric Joyner 		return 0;
137471d10453SEric Joyner 
13757d7af7f8SEric Joyner 	ice_acquire_lock(&hw->rss_locks);
137671d10453SEric Joyner 	LIST_FOR_EACH_ENTRY_SAFE(p, t, &hw->fl_profs[blk], ice_flow_prof,
13779dc2f6e2SEric Joyner 				 l_entry) {
13789dc2f6e2SEric Joyner 		int ret;
13799dc2f6e2SEric Joyner 
13809dc2f6e2SEric Joyner 		/* check if vsig is already removed */
13819dc2f6e2SEric Joyner 		ret = ice_vsig_find_vsi(hw, blk,
13829dc2f6e2SEric Joyner 					ice_get_hw_vsi_num(hw, vsi_handle),
13839dc2f6e2SEric Joyner 					&vsig);
13849dc2f6e2SEric Joyner 		if (!ret && !vsig)
13859dc2f6e2SEric Joyner 			break;
13869dc2f6e2SEric Joyner 
138771d10453SEric Joyner 		if (ice_is_bit_set(p->vsis, vsi_handle)) {
138871d10453SEric Joyner 			status = ice_flow_disassoc_prof(hw, blk, p, vsi_handle);
138971d10453SEric Joyner 			if (status)
139071d10453SEric Joyner 				break;
139171d10453SEric Joyner 
139271d10453SEric Joyner 			if (!ice_is_any_bit_set(p->vsis, ICE_MAX_VSI)) {
13937d7af7f8SEric Joyner 				status = ice_flow_rem_prof(hw, blk, p->id);
139471d10453SEric Joyner 				if (status)
139571d10453SEric Joyner 					break;
139671d10453SEric Joyner 			}
139771d10453SEric Joyner 		}
13989dc2f6e2SEric Joyner 	}
13997d7af7f8SEric Joyner 	ice_release_lock(&hw->rss_locks);
140071d10453SEric Joyner 
140171d10453SEric Joyner 	return status;
140271d10453SEric Joyner }
140371d10453SEric Joyner 
140471d10453SEric Joyner /**
1405d08b8680SEric Joyner  * ice_get_rss_hdr_type - get a RSS profile's header type
1406d08b8680SEric Joyner  * @prof: RSS flow profile
1407d08b8680SEric Joyner  */
1408d08b8680SEric Joyner static enum ice_rss_cfg_hdr_type
1409d08b8680SEric Joyner ice_get_rss_hdr_type(struct ice_flow_prof *prof)
1410d08b8680SEric Joyner {
1411d08b8680SEric Joyner 	enum ice_rss_cfg_hdr_type hdr_type = ICE_RSS_ANY_HEADERS;
1412d08b8680SEric Joyner 
1413d08b8680SEric Joyner 	if (prof->segs_cnt == ICE_FLOW_SEG_SINGLE) {
1414d08b8680SEric Joyner 		hdr_type = ICE_RSS_OUTER_HEADERS;
1415d08b8680SEric Joyner 	} else if (prof->segs_cnt == ICE_FLOW_SEG_MAX) {
14169e54973fSEric Joyner 		const struct ice_flow_seg_info *s;
14179e54973fSEric Joyner 
14189e54973fSEric Joyner 		s = &prof->segs[ICE_RSS_OUTER_HEADERS];
14199e54973fSEric Joyner 		if (s->hdrs == ICE_FLOW_SEG_HDR_NONE)
1420d08b8680SEric Joyner 			hdr_type = ICE_RSS_INNER_HEADERS;
14219e54973fSEric Joyner 		if (s->hdrs & ICE_FLOW_SEG_HDR_IPV4)
1422d08b8680SEric Joyner 			hdr_type = ICE_RSS_INNER_HEADERS_W_OUTER_IPV4;
14239e54973fSEric Joyner 		if (s->hdrs & ICE_FLOW_SEG_HDR_IPV6)
1424d08b8680SEric Joyner 			hdr_type = ICE_RSS_INNER_HEADERS_W_OUTER_IPV6;
1425d08b8680SEric Joyner 	}
1426d08b8680SEric Joyner 
1427d08b8680SEric Joyner 	return hdr_type;
1428d08b8680SEric Joyner }
1429d08b8680SEric Joyner 
1430d08b8680SEric Joyner /**
143171d10453SEric Joyner  * ice_rem_rss_list - remove RSS configuration from list
143271d10453SEric Joyner  * @hw: pointer to the hardware structure
143371d10453SEric Joyner  * @vsi_handle: software VSI handle
143471d10453SEric Joyner  * @prof: pointer to flow profile
143571d10453SEric Joyner  *
143671d10453SEric Joyner  * Assumption: lock has already been acquired for RSS list
143771d10453SEric Joyner  */
143871d10453SEric Joyner static void
143971d10453SEric Joyner ice_rem_rss_list(struct ice_hw *hw, u16 vsi_handle, struct ice_flow_prof *prof)
144071d10453SEric Joyner {
1441d08b8680SEric Joyner 	enum ice_rss_cfg_hdr_type hdr_type;
144271d10453SEric Joyner 	struct ice_rss_cfg *r, *tmp;
14439c30461dSEric Joyner 	u64 seg_match = 0;
14449c30461dSEric Joyner 	u16 i;
14459c30461dSEric Joyner 
14469c30461dSEric Joyner 	/* convert match bitmap to u64 for hash field comparison */
14479c30461dSEric Joyner 	ice_for_each_set_bit(i, prof->segs[prof->segs_cnt - 1].match,
14489c30461dSEric Joyner 			     ICE_FLOW_FIELD_IDX_MAX) {
14499c30461dSEric Joyner 		seg_match |= 1ULL << i;
14509c30461dSEric Joyner 	}
145171d10453SEric Joyner 
145271d10453SEric Joyner 	/* Search for RSS hash fields associated to the VSI that match the
145371d10453SEric Joyner 	 * hash configurations associated to the flow profile. If found
145471d10453SEric Joyner 	 * remove from the RSS entry list of the VSI context and delete entry.
145571d10453SEric Joyner 	 */
1456d08b8680SEric Joyner 	hdr_type = ice_get_rss_hdr_type(prof);
145771d10453SEric Joyner 	LIST_FOR_EACH_ENTRY_SAFE(r, tmp, &hw->rss_list_head,
14587d7af7f8SEric Joyner 				 ice_rss_cfg, l_entry)
14599c30461dSEric Joyner 		if (r->hash.hash_flds == seg_match &&
1460d08b8680SEric Joyner 		    r->hash.addl_hdrs == prof->segs[prof->segs_cnt - 1].hdrs &&
1461d08b8680SEric Joyner 		    r->hash.hdr_type == hdr_type) {
146271d10453SEric Joyner 			ice_clear_bit(vsi_handle, r->vsis);
146371d10453SEric Joyner 			if (!ice_is_any_bit_set(r->vsis, ICE_MAX_VSI)) {
146471d10453SEric Joyner 				LIST_DEL(&r->l_entry);
146571d10453SEric Joyner 				ice_free(hw, r);
146671d10453SEric Joyner 			}
146771d10453SEric Joyner 			return;
146871d10453SEric Joyner 		}
146971d10453SEric Joyner }
147071d10453SEric Joyner 
147171d10453SEric Joyner /**
147271d10453SEric Joyner  * ice_add_rss_list - add RSS configuration to list
147371d10453SEric Joyner  * @hw: pointer to the hardware structure
147471d10453SEric Joyner  * @vsi_handle: software VSI handle
147571d10453SEric Joyner  * @prof: pointer to flow profile
147671d10453SEric Joyner  *
147771d10453SEric Joyner  * Assumption: lock has already been acquired for RSS list
147871d10453SEric Joyner  */
1479*f2635e84SEric Joyner static int
148071d10453SEric Joyner ice_add_rss_list(struct ice_hw *hw, u16 vsi_handle, struct ice_flow_prof *prof)
148171d10453SEric Joyner {
1482d08b8680SEric Joyner 	enum ice_rss_cfg_hdr_type hdr_type;
148371d10453SEric Joyner 	struct ice_rss_cfg *r, *rss_cfg;
14849c30461dSEric Joyner 	u64 seg_match = 0;
14859c30461dSEric Joyner 	u16 i;
14869c30461dSEric Joyner 
14879c30461dSEric Joyner 	ice_for_each_set_bit(i, prof->segs[prof->segs_cnt - 1].match,
14889c30461dSEric Joyner 			     ICE_FLOW_FIELD_IDX_MAX) {
14899c30461dSEric Joyner 		seg_match |= 1ULL << i;
14909c30461dSEric Joyner 	}
149171d10453SEric Joyner 
1492d08b8680SEric Joyner 	hdr_type = ice_get_rss_hdr_type(prof);
149371d10453SEric Joyner 	LIST_FOR_EACH_ENTRY(r, &hw->rss_list_head,
149471d10453SEric Joyner 			    ice_rss_cfg, l_entry)
14959c30461dSEric Joyner 		if (r->hash.hash_flds == seg_match &&
1496d08b8680SEric Joyner 		    r->hash.addl_hdrs == prof->segs[prof->segs_cnt - 1].hdrs &&
1497d08b8680SEric Joyner 		    r->hash.hdr_type == hdr_type) {
149871d10453SEric Joyner 			ice_set_bit(vsi_handle, r->vsis);
1499*f2635e84SEric Joyner 			return 0;
150071d10453SEric Joyner 		}
150171d10453SEric Joyner 
150271d10453SEric Joyner 	rss_cfg = (struct ice_rss_cfg *)ice_malloc(hw, sizeof(*rss_cfg));
150371d10453SEric Joyner 	if (!rss_cfg)
150471d10453SEric Joyner 		return ICE_ERR_NO_MEMORY;
150571d10453SEric Joyner 
15069c30461dSEric Joyner 	rss_cfg->hash.hash_flds = seg_match;
1507d08b8680SEric Joyner 	rss_cfg->hash.addl_hdrs = prof->segs[prof->segs_cnt - 1].hdrs;
1508d08b8680SEric Joyner 	rss_cfg->hash.hdr_type = hdr_type;
1509d08b8680SEric Joyner 	rss_cfg->hash.symm = prof->cfg.symm;
151071d10453SEric Joyner 	ice_set_bit(vsi_handle, rss_cfg->vsis);
151171d10453SEric Joyner 
151271d10453SEric Joyner 	LIST_ADD_TAIL(&rss_cfg->l_entry, &hw->rss_list_head);
151371d10453SEric Joyner 
1514*f2635e84SEric Joyner 	return 0;
151571d10453SEric Joyner }
151671d10453SEric Joyner 
151771d10453SEric Joyner #define ICE_FLOW_PROF_HASH_S	0
151871d10453SEric Joyner #define ICE_FLOW_PROF_HASH_M	(0xFFFFFFFFULL << ICE_FLOW_PROF_HASH_S)
151971d10453SEric Joyner #define ICE_FLOW_PROF_HDR_S	32
152071d10453SEric Joyner #define ICE_FLOW_PROF_HDR_M	(0x3FFFFFFFULL << ICE_FLOW_PROF_HDR_S)
1521d08b8680SEric Joyner #define ICE_FLOW_PROF_ENCAP_S	62
1522d08b8680SEric Joyner #define ICE_FLOW_PROF_ENCAP_M	(0x3ULL << ICE_FLOW_PROF_ENCAP_S)
152371d10453SEric Joyner 
152471d10453SEric Joyner /* Flow profile ID format:
152571d10453SEric Joyner  * [0:31] - Packet match fields
1526d08b8680SEric Joyner  * [32:61] - Protocol header
1527d08b8680SEric Joyner  * [62:63] - Encapsulation flag:
1528d08b8680SEric Joyner  *	     0 if non-tunneled
1529d08b8680SEric Joyner  *	     1 if tunneled
15309e54973fSEric Joyner  *	     2 for tunneled with outer IPv4
15319e54973fSEric Joyner  *	     3 for tunneled with outer IPv6
153271d10453SEric Joyner  */
1533d08b8680SEric Joyner #define ICE_FLOW_GEN_PROFID(hash, hdr, encap)                                \
15349cf1841cSEric Joyner 	((u64)(((u64)(hash) & ICE_FLOW_PROF_HASH_M) |                        \
153571d10453SEric Joyner 	       (((u64)(hdr) << ICE_FLOW_PROF_HDR_S) & ICE_FLOW_PROF_HDR_M) | \
15369e54973fSEric Joyner 	       (((u64)(encap) << ICE_FLOW_PROF_ENCAP_S) &                    \
15379e54973fSEric Joyner 		ICE_FLOW_PROF_ENCAP_M)))
153871d10453SEric Joyner 
153971d10453SEric Joyner /**
154071d10453SEric Joyner  * ice_add_rss_cfg_sync - add an RSS configuration
154171d10453SEric Joyner  * @hw: pointer to the hardware structure
154271d10453SEric Joyner  * @vsi_handle: software VSI handle
1543d08b8680SEric Joyner  * @cfg: configure parameters
154471d10453SEric Joyner  *
154571d10453SEric Joyner  * Assumption: lock has already been acquired for RSS list
154671d10453SEric Joyner  */
1547*f2635e84SEric Joyner static int
1548d08b8680SEric Joyner ice_add_rss_cfg_sync(struct ice_hw *hw, u16 vsi_handle,
1549d08b8680SEric Joyner 		     const struct ice_rss_hash_cfg *cfg)
155071d10453SEric Joyner {
155171d10453SEric Joyner 	const enum ice_block blk = ICE_BLK_RSS;
155271d10453SEric Joyner 	struct ice_flow_prof *prof = NULL;
155371d10453SEric Joyner 	struct ice_flow_seg_info *segs;
1554d08b8680SEric Joyner 	u8 segs_cnt;
1555*f2635e84SEric Joyner 	int status;
155671d10453SEric Joyner 
1557d08b8680SEric Joyner 	if (cfg->symm)
155871d10453SEric Joyner 		return ICE_ERR_PARAM;
155971d10453SEric Joyner 
1560d08b8680SEric Joyner 	segs_cnt = (cfg->hdr_type == ICE_RSS_OUTER_HEADERS) ?
15619e54973fSEric Joyner 			   ICE_FLOW_SEG_SINGLE :
15629e54973fSEric Joyner 			   ICE_FLOW_SEG_MAX;
1563d08b8680SEric Joyner 
156471d10453SEric Joyner 	segs = (struct ice_flow_seg_info *)ice_calloc(hw, segs_cnt,
156571d10453SEric Joyner 						      sizeof(*segs));
156671d10453SEric Joyner 	if (!segs)
156771d10453SEric Joyner 		return ICE_ERR_NO_MEMORY;
156871d10453SEric Joyner 
156971d10453SEric Joyner 	/* Construct the packet segment info from the hashed fields */
1570d08b8680SEric Joyner 	status = ice_flow_set_rss_seg_info(segs, segs_cnt, cfg);
157171d10453SEric Joyner 	if (status)
157271d10453SEric Joyner 		goto exit;
157371d10453SEric Joyner 
157471d10453SEric Joyner 	/* Search for a flow profile that has matching headers, hash fields
157571d10453SEric Joyner 	 * and has the input VSI associated to it. If found, no further
157671d10453SEric Joyner 	 * operations required and exit.
157771d10453SEric Joyner 	 */
157871d10453SEric Joyner 	prof = ice_flow_find_prof_conds(hw, blk, ICE_FLOW_RX, segs, segs_cnt,
157971d10453SEric Joyner 					vsi_handle,
158071d10453SEric Joyner 					ICE_FLOW_FIND_PROF_CHK_FLDS |
158171d10453SEric Joyner 					ICE_FLOW_FIND_PROF_CHK_VSI);
158271d10453SEric Joyner 	if (prof)
158371d10453SEric Joyner 		goto exit;
158471d10453SEric Joyner 
158571d10453SEric Joyner 	/* Check if a flow profile exists with the same protocol headers and
15867d7af7f8SEric Joyner 	 * associated with the input VSI. If so disassociate the VSI from
158771d10453SEric Joyner 	 * this profile. The VSI will be added to a new profile created with
158871d10453SEric Joyner 	 * the protocol header and new hash field configuration.
158971d10453SEric Joyner 	 */
159071d10453SEric Joyner 	prof = ice_flow_find_prof_conds(hw, blk, ICE_FLOW_RX, segs, segs_cnt,
159171d10453SEric Joyner 					vsi_handle, ICE_FLOW_FIND_PROF_CHK_VSI);
159271d10453SEric Joyner 	if (prof) {
159371d10453SEric Joyner 		status = ice_flow_disassoc_prof(hw, blk, prof, vsi_handle);
159471d10453SEric Joyner 		if (!status)
159571d10453SEric Joyner 			ice_rem_rss_list(hw, vsi_handle, prof);
159671d10453SEric Joyner 		else
159771d10453SEric Joyner 			goto exit;
159871d10453SEric Joyner 
159971d10453SEric Joyner 		/* Remove profile if it has no VSIs associated */
160071d10453SEric Joyner 		if (!ice_is_any_bit_set(prof->vsis, ICE_MAX_VSI)) {
160171d10453SEric Joyner 			status = ice_flow_rem_prof(hw, blk, prof->id);
160271d10453SEric Joyner 			if (status)
160371d10453SEric Joyner 				goto exit;
160471d10453SEric Joyner 		}
160571d10453SEric Joyner 	}
160671d10453SEric Joyner 
160771d10453SEric Joyner 	/* Search for a profile that has same match fields only. If this
160871d10453SEric Joyner 	 * exists then associate the VSI to this profile.
160971d10453SEric Joyner 	 */
161071d10453SEric Joyner 	prof = ice_flow_find_prof_conds(hw, blk, ICE_FLOW_RX, segs, segs_cnt,
161171d10453SEric Joyner 					vsi_handle,
161271d10453SEric Joyner 					ICE_FLOW_FIND_PROF_CHK_FLDS);
161371d10453SEric Joyner 	if (prof) {
161471d10453SEric Joyner 		status = ice_flow_assoc_prof(hw, blk, prof, vsi_handle);
161571d10453SEric Joyner 		if (!status)
161671d10453SEric Joyner 			status = ice_add_rss_list(hw, vsi_handle, prof);
161771d10453SEric Joyner 		goto exit;
161871d10453SEric Joyner 	}
161971d10453SEric Joyner 
162071d10453SEric Joyner 	/* Create a new flow profile with generated profile and packet
162171d10453SEric Joyner 	 * segment information.
162271d10453SEric Joyner 	 */
162371d10453SEric Joyner 	status = ice_flow_add_prof(hw, blk, ICE_FLOW_RX,
1624d08b8680SEric Joyner 				   ICE_FLOW_GEN_PROFID(cfg->hash_flds,
162571d10453SEric Joyner 						       segs[segs_cnt - 1].hdrs,
1626d08b8680SEric Joyner 						       cfg->hdr_type),
162771d10453SEric Joyner 				   segs, segs_cnt, NULL, 0, &prof);
162871d10453SEric Joyner 	if (status)
162971d10453SEric Joyner 		goto exit;
163071d10453SEric Joyner 
163171d10453SEric Joyner 	status = ice_flow_assoc_prof(hw, blk, prof, vsi_handle);
163271d10453SEric Joyner 	/* If association to a new flow profile failed then this profile can
163371d10453SEric Joyner 	 * be removed.
163471d10453SEric Joyner 	 */
163571d10453SEric Joyner 	if (status) {
163671d10453SEric Joyner 		ice_flow_rem_prof(hw, blk, prof->id);
163771d10453SEric Joyner 		goto exit;
163871d10453SEric Joyner 	}
163971d10453SEric Joyner 
164071d10453SEric Joyner 	status = ice_add_rss_list(hw, vsi_handle, prof);
164171d10453SEric Joyner 
1642d08b8680SEric Joyner 	prof->cfg.symm = cfg->symm;
1643d08b8680SEric Joyner 
164471d10453SEric Joyner exit:
164571d10453SEric Joyner 	ice_free(hw, segs);
164671d10453SEric Joyner 	return status;
164771d10453SEric Joyner }
164871d10453SEric Joyner 
164971d10453SEric Joyner /**
165071d10453SEric Joyner  * ice_add_rss_cfg - add an RSS configuration with specified hashed fields
165171d10453SEric Joyner  * @hw: pointer to the hardware structure
165271d10453SEric Joyner  * @vsi_handle: software VSI handle
1653d08b8680SEric Joyner  * @cfg: configure parameters
165471d10453SEric Joyner  *
165571d10453SEric Joyner  * This function will generate a flow profile based on fields associated with
165671d10453SEric Joyner  * the input fields to hash on, the flow type and use the VSI number to add
165771d10453SEric Joyner  * a flow entry to the profile.
165871d10453SEric Joyner  */
1659*f2635e84SEric Joyner int
1660d08b8680SEric Joyner ice_add_rss_cfg(struct ice_hw *hw, u16 vsi_handle,
1661d08b8680SEric Joyner 		const struct ice_rss_hash_cfg *cfg)
166271d10453SEric Joyner {
1663d08b8680SEric Joyner 	struct ice_rss_hash_cfg local_cfg;
1664*f2635e84SEric Joyner 	int status;
166571d10453SEric Joyner 
16669e54973fSEric Joyner 	if (!ice_is_vsi_valid(hw, vsi_handle) || !cfg ||
16679e54973fSEric Joyner 	    cfg->hdr_type > ICE_RSS_ANY_HEADERS ||
1668d08b8680SEric Joyner 	    cfg->hash_flds == ICE_HASH_INVALID)
166971d10453SEric Joyner 		return ICE_ERR_PARAM;
167071d10453SEric Joyner 
16719e54973fSEric Joyner 	ice_acquire_lock(&hw->rss_locks);
1672d08b8680SEric Joyner 	local_cfg = *cfg;
1673d08b8680SEric Joyner 	if (cfg->hdr_type < ICE_RSS_ANY_HEADERS) {
1674d08b8680SEric Joyner 		status = ice_add_rss_cfg_sync(hw, vsi_handle, &local_cfg);
1675d08b8680SEric Joyner 	} else {
1676d08b8680SEric Joyner 		local_cfg.hdr_type = ICE_RSS_OUTER_HEADERS;
1677d08b8680SEric Joyner 		status = ice_add_rss_cfg_sync(hw, vsi_handle, &local_cfg);
1678d08b8680SEric Joyner 		if (!status) {
1679d08b8680SEric Joyner 			local_cfg.hdr_type = ICE_RSS_INNER_HEADERS;
1680d08b8680SEric Joyner 			status = ice_add_rss_cfg_sync(hw, vsi_handle,
1681d08b8680SEric Joyner 						      &local_cfg);
1682d08b8680SEric Joyner 		}
1683d08b8680SEric Joyner 	}
16849e54973fSEric Joyner 	ice_release_lock(&hw->rss_locks);
168571d10453SEric Joyner 
168671d10453SEric Joyner 	return status;
168771d10453SEric Joyner }
168871d10453SEric Joyner 
168971d10453SEric Joyner /**
169071d10453SEric Joyner  * ice_rem_rss_cfg_sync - remove an existing RSS configuration
169171d10453SEric Joyner  * @hw: pointer to the hardware structure
169271d10453SEric Joyner  * @vsi_handle: software VSI handle
1693d08b8680SEric Joyner  * @cfg: configure parameters
169471d10453SEric Joyner  *
169571d10453SEric Joyner  * Assumption: lock has already been acquired for RSS list
169671d10453SEric Joyner  */
1697*f2635e84SEric Joyner static int
1698d08b8680SEric Joyner ice_rem_rss_cfg_sync(struct ice_hw *hw, u16 vsi_handle,
1699d08b8680SEric Joyner 		     const struct ice_rss_hash_cfg *cfg)
170071d10453SEric Joyner {
170171d10453SEric Joyner 	const enum ice_block blk = ICE_BLK_RSS;
170271d10453SEric Joyner 	struct ice_flow_seg_info *segs;
170371d10453SEric Joyner 	struct ice_flow_prof *prof;
1704d08b8680SEric Joyner 	u8 segs_cnt;
1705*f2635e84SEric Joyner 	int status;
170671d10453SEric Joyner 
1707d08b8680SEric Joyner 	segs_cnt = (cfg->hdr_type == ICE_RSS_OUTER_HEADERS) ?
17089e54973fSEric Joyner 			   ICE_FLOW_SEG_SINGLE :
17099e54973fSEric Joyner 			   ICE_FLOW_SEG_MAX;
171071d10453SEric Joyner 	segs = (struct ice_flow_seg_info *)ice_calloc(hw, segs_cnt,
171171d10453SEric Joyner 						      sizeof(*segs));
171271d10453SEric Joyner 	if (!segs)
171371d10453SEric Joyner 		return ICE_ERR_NO_MEMORY;
171471d10453SEric Joyner 
171571d10453SEric Joyner 	/* Construct the packet segment info from the hashed fields */
1716d08b8680SEric Joyner 	status = ice_flow_set_rss_seg_info(segs, segs_cnt, cfg);
171771d10453SEric Joyner 	if (status)
171871d10453SEric Joyner 		goto out;
171971d10453SEric Joyner 
172071d10453SEric Joyner 	prof = ice_flow_find_prof_conds(hw, blk, ICE_FLOW_RX, segs, segs_cnt,
172171d10453SEric Joyner 					vsi_handle,
172271d10453SEric Joyner 					ICE_FLOW_FIND_PROF_CHK_FLDS);
172371d10453SEric Joyner 	if (!prof) {
172471d10453SEric Joyner 		status = ICE_ERR_DOES_NOT_EXIST;
172571d10453SEric Joyner 		goto out;
172671d10453SEric Joyner 	}
172771d10453SEric Joyner 
172871d10453SEric Joyner 	status = ice_flow_disassoc_prof(hw, blk, prof, vsi_handle);
172971d10453SEric Joyner 	if (status)
173071d10453SEric Joyner 		goto out;
173171d10453SEric Joyner 
173271d10453SEric Joyner 	/* Remove RSS configuration from VSI context before deleting
173371d10453SEric Joyner 	 * the flow profile.
173471d10453SEric Joyner 	 */
173571d10453SEric Joyner 	ice_rem_rss_list(hw, vsi_handle, prof);
173671d10453SEric Joyner 
173771d10453SEric Joyner 	if (!ice_is_any_bit_set(prof->vsis, ICE_MAX_VSI))
173871d10453SEric Joyner 		status = ice_flow_rem_prof(hw, blk, prof->id);
173971d10453SEric Joyner 
174071d10453SEric Joyner out:
174171d10453SEric Joyner 	ice_free(hw, segs);
174271d10453SEric Joyner 	return status;
174371d10453SEric Joyner }
174471d10453SEric Joyner 
174571d10453SEric Joyner /**
174671d10453SEric Joyner  * ice_rem_rss_cfg - remove an existing RSS config with matching hashed fields
174771d10453SEric Joyner  * @hw: pointer to the hardware structure
174871d10453SEric Joyner  * @vsi_handle: software VSI handle
1749d08b8680SEric Joyner  * @cfg: configure parameters
175071d10453SEric Joyner  *
175171d10453SEric Joyner  * This function will lookup the flow profile based on the input
175271d10453SEric Joyner  * hash field bitmap, iterate through the profile entry list of
175371d10453SEric Joyner  * that profile and find entry associated with input VSI to be
175471d10453SEric Joyner  * removed. Calls are made to underlying flow apis which will in
175571d10453SEric Joyner  * turn build or update buffers for RSS XLT1 section.
175671d10453SEric Joyner  */
1757*f2635e84SEric Joyner int
1758d08b8680SEric Joyner ice_rem_rss_cfg(struct ice_hw *hw, u16 vsi_handle,
1759d08b8680SEric Joyner 		const struct ice_rss_hash_cfg *cfg)
176071d10453SEric Joyner {
1761d08b8680SEric Joyner 	struct ice_rss_hash_cfg local_cfg;
1762*f2635e84SEric Joyner 	int status;
176371d10453SEric Joyner 
17649e54973fSEric Joyner 	if (!ice_is_vsi_valid(hw, vsi_handle) || !cfg ||
17659e54973fSEric Joyner 	    cfg->hdr_type > ICE_RSS_ANY_HEADERS ||
1766d08b8680SEric Joyner 	    cfg->hash_flds == ICE_HASH_INVALID)
176771d10453SEric Joyner 		return ICE_ERR_PARAM;
176871d10453SEric Joyner 
176971d10453SEric Joyner 	ice_acquire_lock(&hw->rss_locks);
1770d08b8680SEric Joyner 	local_cfg = *cfg;
1771d08b8680SEric Joyner 	if (cfg->hdr_type < ICE_RSS_ANY_HEADERS) {
1772d08b8680SEric Joyner 		status = ice_rem_rss_cfg_sync(hw, vsi_handle, &local_cfg);
1773d08b8680SEric Joyner 	} else {
1774d08b8680SEric Joyner 		local_cfg.hdr_type = ICE_RSS_OUTER_HEADERS;
1775d08b8680SEric Joyner 		status = ice_rem_rss_cfg_sync(hw, vsi_handle, &local_cfg);
1776d08b8680SEric Joyner 		if (!status) {
1777d08b8680SEric Joyner 			local_cfg.hdr_type = ICE_RSS_INNER_HEADERS;
1778d08b8680SEric Joyner 			status = ice_rem_rss_cfg_sync(hw, vsi_handle,
1779d08b8680SEric Joyner 						      &local_cfg);
1780d08b8680SEric Joyner 		}
1781d08b8680SEric Joyner 	}
178271d10453SEric Joyner 	ice_release_lock(&hw->rss_locks);
178371d10453SEric Joyner 
178471d10453SEric Joyner 	return status;
178571d10453SEric Joyner }
178671d10453SEric Joyner 
178771d10453SEric Joyner /* Mapping of AVF hash bit fields to an L3-L4 hash combination.
178871d10453SEric Joyner  * As the ice_flow_avf_hdr_field represent individual bit shifts in a hash,
178971d10453SEric Joyner  * convert its values to their appropriate flow L3, L4 values.
179071d10453SEric Joyner  */
179171d10453SEric Joyner #define ICE_FLOW_AVF_RSS_IPV4_MASKS \
179271d10453SEric Joyner 	(BIT_ULL(ICE_AVF_FLOW_FIELD_IPV4_OTHER) | \
179371d10453SEric Joyner 	 BIT_ULL(ICE_AVF_FLOW_FIELD_FRAG_IPV4))
179471d10453SEric Joyner #define ICE_FLOW_AVF_RSS_TCP_IPV4_MASKS \
179571d10453SEric Joyner 	(BIT_ULL(ICE_AVF_FLOW_FIELD_IPV4_TCP_SYN_NO_ACK) | \
179671d10453SEric Joyner 	 BIT_ULL(ICE_AVF_FLOW_FIELD_IPV4_TCP))
179771d10453SEric Joyner #define ICE_FLOW_AVF_RSS_UDP_IPV4_MASKS \
179871d10453SEric Joyner 	(BIT_ULL(ICE_AVF_FLOW_FIELD_UNICAST_IPV4_UDP) | \
179971d10453SEric Joyner 	 BIT_ULL(ICE_AVF_FLOW_FIELD_MULTICAST_IPV4_UDP) | \
180071d10453SEric Joyner 	 BIT_ULL(ICE_AVF_FLOW_FIELD_IPV4_UDP))
180171d10453SEric Joyner #define ICE_FLOW_AVF_RSS_ALL_IPV4_MASKS \
180271d10453SEric Joyner 	(ICE_FLOW_AVF_RSS_TCP_IPV4_MASKS | ICE_FLOW_AVF_RSS_UDP_IPV4_MASKS | \
180371d10453SEric Joyner 	 ICE_FLOW_AVF_RSS_IPV4_MASKS | BIT_ULL(ICE_AVF_FLOW_FIELD_IPV4_SCTP))
180471d10453SEric Joyner 
180571d10453SEric Joyner #define ICE_FLOW_AVF_RSS_IPV6_MASKS \
180671d10453SEric Joyner 	(BIT_ULL(ICE_AVF_FLOW_FIELD_IPV6_OTHER) | \
180771d10453SEric Joyner 	 BIT_ULL(ICE_AVF_FLOW_FIELD_FRAG_IPV6))
180871d10453SEric Joyner #define ICE_FLOW_AVF_RSS_UDP_IPV6_MASKS \
180971d10453SEric Joyner 	(BIT_ULL(ICE_AVF_FLOW_FIELD_UNICAST_IPV6_UDP) | \
181071d10453SEric Joyner 	 BIT_ULL(ICE_AVF_FLOW_FIELD_MULTICAST_IPV6_UDP) | \
181171d10453SEric Joyner 	 BIT_ULL(ICE_AVF_FLOW_FIELD_IPV6_UDP))
181271d10453SEric Joyner #define ICE_FLOW_AVF_RSS_TCP_IPV6_MASKS \
181371d10453SEric Joyner 	(BIT_ULL(ICE_AVF_FLOW_FIELD_IPV6_TCP_SYN_NO_ACK) | \
181471d10453SEric Joyner 	 BIT_ULL(ICE_AVF_FLOW_FIELD_IPV6_TCP))
181571d10453SEric Joyner #define ICE_FLOW_AVF_RSS_ALL_IPV6_MASKS \
181671d10453SEric Joyner 	(ICE_FLOW_AVF_RSS_TCP_IPV6_MASKS | ICE_FLOW_AVF_RSS_UDP_IPV6_MASKS | \
181771d10453SEric Joyner 	 ICE_FLOW_AVF_RSS_IPV6_MASKS | BIT_ULL(ICE_AVF_FLOW_FIELD_IPV6_SCTP))
181871d10453SEric Joyner 
181971d10453SEric Joyner /**
182071d10453SEric Joyner  * ice_add_avf_rss_cfg - add an RSS configuration for AVF driver
182171d10453SEric Joyner  * @hw: pointer to the hardware structure
182271d10453SEric Joyner  * @vsi_handle: software VSI handle
182371d10453SEric Joyner  * @avf_hash: hash bit fields (ICE_AVF_FLOW_FIELD_*) to configure
182471d10453SEric Joyner  *
182571d10453SEric Joyner  * This function will take the hash bitmap provided by the AVF driver via a
182671d10453SEric Joyner  * message, convert it to ICE-compatible values, and configure RSS flow
182771d10453SEric Joyner  * profiles.
182871d10453SEric Joyner  */
1829*f2635e84SEric Joyner int ice_add_avf_rss_cfg(struct ice_hw *hw, u16 vsi_handle, u64 avf_hash)
183071d10453SEric Joyner {
1831d08b8680SEric Joyner 	struct ice_rss_hash_cfg hcfg;
1832*f2635e84SEric Joyner 	int status = 0;
183371d10453SEric Joyner 	u64 hash_flds;
183471d10453SEric Joyner 
183571d10453SEric Joyner 	if (avf_hash == ICE_AVF_FLOW_FIELD_INVALID ||
183671d10453SEric Joyner 	    !ice_is_vsi_valid(hw, vsi_handle))
183771d10453SEric Joyner 		return ICE_ERR_PARAM;
183871d10453SEric Joyner 
183971d10453SEric Joyner 	/* Make sure no unsupported bits are specified */
184071d10453SEric Joyner 	if (avf_hash & ~(ICE_FLOW_AVF_RSS_ALL_IPV4_MASKS |
184171d10453SEric Joyner 			 ICE_FLOW_AVF_RSS_ALL_IPV6_MASKS))
184271d10453SEric Joyner 		return ICE_ERR_CFG;
184371d10453SEric Joyner 
184471d10453SEric Joyner 	hash_flds = avf_hash;
184571d10453SEric Joyner 
184671d10453SEric Joyner 	/* Always create an L3 RSS configuration for any L4 RSS configuration */
184771d10453SEric Joyner 	if (hash_flds & ICE_FLOW_AVF_RSS_ALL_IPV4_MASKS)
184871d10453SEric Joyner 		hash_flds |= ICE_FLOW_AVF_RSS_IPV4_MASKS;
184971d10453SEric Joyner 
185071d10453SEric Joyner 	if (hash_flds & ICE_FLOW_AVF_RSS_ALL_IPV6_MASKS)
185171d10453SEric Joyner 		hash_flds |= ICE_FLOW_AVF_RSS_IPV6_MASKS;
185271d10453SEric Joyner 
185371d10453SEric Joyner 	/* Create the corresponding RSS configuration for each valid hash bit */
185471d10453SEric Joyner 	while (hash_flds) {
185571d10453SEric Joyner 		u64 rss_hash = ICE_HASH_INVALID;
185671d10453SEric Joyner 
185771d10453SEric Joyner 		if (hash_flds & ICE_FLOW_AVF_RSS_ALL_IPV4_MASKS) {
185871d10453SEric Joyner 			if (hash_flds & ICE_FLOW_AVF_RSS_IPV4_MASKS) {
185971d10453SEric Joyner 				rss_hash = ICE_FLOW_HASH_IPV4;
186071d10453SEric Joyner 				hash_flds &= ~ICE_FLOW_AVF_RSS_IPV4_MASKS;
186171d10453SEric Joyner 			} else if (hash_flds &
186271d10453SEric Joyner 				   ICE_FLOW_AVF_RSS_TCP_IPV4_MASKS) {
186371d10453SEric Joyner 				rss_hash = ICE_FLOW_HASH_IPV4 |
186471d10453SEric Joyner 					ICE_FLOW_HASH_TCP_PORT;
186571d10453SEric Joyner 				hash_flds &= ~ICE_FLOW_AVF_RSS_TCP_IPV4_MASKS;
186671d10453SEric Joyner 			} else if (hash_flds &
186771d10453SEric Joyner 				   ICE_FLOW_AVF_RSS_UDP_IPV4_MASKS) {
186871d10453SEric Joyner 				rss_hash = ICE_FLOW_HASH_IPV4 |
186971d10453SEric Joyner 					ICE_FLOW_HASH_UDP_PORT;
187071d10453SEric Joyner 				hash_flds &= ~ICE_FLOW_AVF_RSS_UDP_IPV4_MASKS;
187171d10453SEric Joyner 			} else if (hash_flds &
187271d10453SEric Joyner 				   BIT_ULL(ICE_AVF_FLOW_FIELD_IPV4_SCTP)) {
187371d10453SEric Joyner 				rss_hash = ICE_FLOW_HASH_IPV4 |
187471d10453SEric Joyner 					ICE_FLOW_HASH_SCTP_PORT;
187571d10453SEric Joyner 				hash_flds &=
187671d10453SEric Joyner 					~BIT_ULL(ICE_AVF_FLOW_FIELD_IPV4_SCTP);
187771d10453SEric Joyner 			}
187871d10453SEric Joyner 		} else if (hash_flds & ICE_FLOW_AVF_RSS_ALL_IPV6_MASKS) {
187971d10453SEric Joyner 			if (hash_flds & ICE_FLOW_AVF_RSS_IPV6_MASKS) {
188071d10453SEric Joyner 				rss_hash = ICE_FLOW_HASH_IPV6;
188171d10453SEric Joyner 				hash_flds &= ~ICE_FLOW_AVF_RSS_IPV6_MASKS;
188271d10453SEric Joyner 			} else if (hash_flds &
188371d10453SEric Joyner 				   ICE_FLOW_AVF_RSS_TCP_IPV6_MASKS) {
188471d10453SEric Joyner 				rss_hash = ICE_FLOW_HASH_IPV6 |
188571d10453SEric Joyner 					ICE_FLOW_HASH_TCP_PORT;
188671d10453SEric Joyner 				hash_flds &= ~ICE_FLOW_AVF_RSS_TCP_IPV6_MASKS;
188771d10453SEric Joyner 			} else if (hash_flds &
188871d10453SEric Joyner 				   ICE_FLOW_AVF_RSS_UDP_IPV6_MASKS) {
188971d10453SEric Joyner 				rss_hash = ICE_FLOW_HASH_IPV6 |
189071d10453SEric Joyner 					ICE_FLOW_HASH_UDP_PORT;
189171d10453SEric Joyner 				hash_flds &= ~ICE_FLOW_AVF_RSS_UDP_IPV6_MASKS;
189271d10453SEric Joyner 			} else if (hash_flds &
189371d10453SEric Joyner 				   BIT_ULL(ICE_AVF_FLOW_FIELD_IPV6_SCTP)) {
189471d10453SEric Joyner 				rss_hash = ICE_FLOW_HASH_IPV6 |
189571d10453SEric Joyner 					ICE_FLOW_HASH_SCTP_PORT;
189671d10453SEric Joyner 				hash_flds &=
189771d10453SEric Joyner 					~BIT_ULL(ICE_AVF_FLOW_FIELD_IPV6_SCTP);
189871d10453SEric Joyner 			}
189971d10453SEric Joyner 		}
190071d10453SEric Joyner 
190171d10453SEric Joyner 		if (rss_hash == ICE_HASH_INVALID)
190271d10453SEric Joyner 			return ICE_ERR_OUT_OF_RANGE;
190371d10453SEric Joyner 
1904d08b8680SEric Joyner 		hcfg.addl_hdrs = ICE_FLOW_SEG_HDR_NONE;
1905d08b8680SEric Joyner 		hcfg.hash_flds = rss_hash;
1906d08b8680SEric Joyner 		hcfg.symm = false;
1907d08b8680SEric Joyner 		hcfg.hdr_type = ICE_RSS_ANY_HEADERS;
1908d08b8680SEric Joyner 		status = ice_add_rss_cfg(hw, vsi_handle, &hcfg);
190971d10453SEric Joyner 		if (status)
191071d10453SEric Joyner 			break;
191171d10453SEric Joyner 	}
191271d10453SEric Joyner 
191371d10453SEric Joyner 	return status;
191471d10453SEric Joyner }
191571d10453SEric Joyner 
191671d10453SEric Joyner /**
191771d10453SEric Joyner  * ice_replay_rss_cfg - replay RSS configurations associated with VSI
191871d10453SEric Joyner  * @hw: pointer to the hardware structure
191971d10453SEric Joyner  * @vsi_handle: software VSI handle
192071d10453SEric Joyner  */
1921*f2635e84SEric Joyner int ice_replay_rss_cfg(struct ice_hw *hw, u16 vsi_handle)
192271d10453SEric Joyner {
192371d10453SEric Joyner 	struct ice_rss_cfg *r;
1924*f2635e84SEric Joyner 	int status = 0;
192571d10453SEric Joyner 
192671d10453SEric Joyner 	if (!ice_is_vsi_valid(hw, vsi_handle))
192771d10453SEric Joyner 		return ICE_ERR_PARAM;
192871d10453SEric Joyner 
192971d10453SEric Joyner 	ice_acquire_lock(&hw->rss_locks);
193071d10453SEric Joyner 	LIST_FOR_EACH_ENTRY(r, &hw->rss_list_head,
193171d10453SEric Joyner 			    ice_rss_cfg, l_entry) {
193271d10453SEric Joyner 		if (ice_is_bit_set(r->vsis, vsi_handle)) {
1933d08b8680SEric Joyner 			status = ice_add_rss_cfg_sync(hw, vsi_handle, &r->hash);
193471d10453SEric Joyner 			if (status)
193571d10453SEric Joyner 				break;
193671d10453SEric Joyner 		}
193771d10453SEric Joyner 	}
193871d10453SEric Joyner 	ice_release_lock(&hw->rss_locks);
193971d10453SEric Joyner 
194071d10453SEric Joyner 	return status;
194171d10453SEric Joyner }
194271d10453SEric Joyner 
194371d10453SEric Joyner /**
194471d10453SEric Joyner  * ice_get_rss_cfg - returns hashed fields for the given header types
194571d10453SEric Joyner  * @hw: pointer to the hardware structure
194671d10453SEric Joyner  * @vsi_handle: software VSI handle
194771d10453SEric Joyner  * @hdrs: protocol header type
194871d10453SEric Joyner  *
194971d10453SEric Joyner  * This function will return the match fields of the first instance of flow
195071d10453SEric Joyner  * profile having the given header types and containing input VSI
195171d10453SEric Joyner  */
195271d10453SEric Joyner u64 ice_get_rss_cfg(struct ice_hw *hw, u16 vsi_handle, u32 hdrs)
195371d10453SEric Joyner {
19547d7af7f8SEric Joyner 	u64 rss_hash = ICE_HASH_INVALID;
19557d7af7f8SEric Joyner 	struct ice_rss_cfg *r;
195671d10453SEric Joyner 
195771d10453SEric Joyner 	/* verify if the protocol header is non zero and VSI is valid */
195871d10453SEric Joyner 	if (hdrs == ICE_FLOW_SEG_HDR_NONE || !ice_is_vsi_valid(hw, vsi_handle))
195971d10453SEric Joyner 		return ICE_HASH_INVALID;
196071d10453SEric Joyner 
196171d10453SEric Joyner 	ice_acquire_lock(&hw->rss_locks);
196271d10453SEric Joyner 	LIST_FOR_EACH_ENTRY(r, &hw->rss_list_head,
196371d10453SEric Joyner 			    ice_rss_cfg, l_entry)
196471d10453SEric Joyner 		if (ice_is_bit_set(r->vsis, vsi_handle) &&
1965d08b8680SEric Joyner 		    r->hash.addl_hdrs == hdrs) {
1966d08b8680SEric Joyner 			rss_hash = r->hash.hash_flds;
196771d10453SEric Joyner 			break;
196871d10453SEric Joyner 		}
196971d10453SEric Joyner 	ice_release_lock(&hw->rss_locks);
197071d10453SEric Joyner 
19717d7af7f8SEric Joyner 	return rss_hash;
197271d10453SEric Joyner }
1973