Back to home page

OSCL-LXR

 
 

    


0001 // SPDX-License-Identifier: GPL-2.0
0002 /* Copyright (c) 2019, Intel Corporation. */
0003 
0004 #include "ice_common.h"
0005 #include "ice_flow.h"
0006 #include <net/gre.h>
0007 
0008 /* Describe properties of a protocol header field */
0009 struct ice_flow_field_info {
0010     enum ice_flow_seg_hdr hdr;
0011     s16 off;    /* Offset from start of a protocol header, in bits */
0012     u16 size;   /* Size of fields in bits */
0013     u16 mask;   /* 16-bit mask for field */
0014 };
0015 
0016 #define ICE_FLOW_FLD_INFO(_hdr, _offset_bytes, _size_bytes) { \
0017     .hdr = _hdr, \
0018     .off = (_offset_bytes) * BITS_PER_BYTE, \
0019     .size = (_size_bytes) * BITS_PER_BYTE, \
0020     .mask = 0, \
0021 }
0022 
0023 #define ICE_FLOW_FLD_INFO_MSK(_hdr, _offset_bytes, _size_bytes, _mask) { \
0024     .hdr = _hdr, \
0025     .off = (_offset_bytes) * BITS_PER_BYTE, \
0026     .size = (_size_bytes) * BITS_PER_BYTE, \
0027     .mask = _mask, \
0028 }
0029 
0030 /* Table containing properties of supported protocol header fields */
0031 static const
0032 struct ice_flow_field_info ice_flds_info[ICE_FLOW_FIELD_IDX_MAX] = {
0033     /* Ether */
0034     /* ICE_FLOW_FIELD_IDX_ETH_DA */
0035     ICE_FLOW_FLD_INFO(ICE_FLOW_SEG_HDR_ETH, 0, ETH_ALEN),
0036     /* ICE_FLOW_FIELD_IDX_ETH_SA */
0037     ICE_FLOW_FLD_INFO(ICE_FLOW_SEG_HDR_ETH, ETH_ALEN, ETH_ALEN),
0038     /* ICE_FLOW_FIELD_IDX_S_VLAN */
0039     ICE_FLOW_FLD_INFO(ICE_FLOW_SEG_HDR_VLAN, 12, sizeof(__be16)),
0040     /* ICE_FLOW_FIELD_IDX_C_VLAN */
0041     ICE_FLOW_FLD_INFO(ICE_FLOW_SEG_HDR_VLAN, 14, sizeof(__be16)),
0042     /* ICE_FLOW_FIELD_IDX_ETH_TYPE */
0043     ICE_FLOW_FLD_INFO(ICE_FLOW_SEG_HDR_ETH, 0, sizeof(__be16)),
0044     /* IPv4 / IPv6 */
0045     /* ICE_FLOW_FIELD_IDX_IPV4_DSCP */
0046     ICE_FLOW_FLD_INFO_MSK(ICE_FLOW_SEG_HDR_IPV4, 0, 1, 0x00fc),
0047     /* ICE_FLOW_FIELD_IDX_IPV6_DSCP */
0048     ICE_FLOW_FLD_INFO_MSK(ICE_FLOW_SEG_HDR_IPV6, 0, 1, 0x0ff0),
0049     /* ICE_FLOW_FIELD_IDX_IPV4_TTL */
0050     ICE_FLOW_FLD_INFO_MSK(ICE_FLOW_SEG_HDR_NONE, 8, 1, 0xff00),
0051     /* ICE_FLOW_FIELD_IDX_IPV4_PROT */
0052     ICE_FLOW_FLD_INFO_MSK(ICE_FLOW_SEG_HDR_NONE, 8, 1, 0x00ff),
0053     /* ICE_FLOW_FIELD_IDX_IPV6_TTL */
0054     ICE_FLOW_FLD_INFO_MSK(ICE_FLOW_SEG_HDR_NONE, 6, 1, 0x00ff),
0055     /* ICE_FLOW_FIELD_IDX_IPV6_PROT */
0056     ICE_FLOW_FLD_INFO_MSK(ICE_FLOW_SEG_HDR_NONE, 6, 1, 0xff00),
0057     /* ICE_FLOW_FIELD_IDX_IPV4_SA */
0058     ICE_FLOW_FLD_INFO(ICE_FLOW_SEG_HDR_IPV4, 12, sizeof(struct in_addr)),
0059     /* ICE_FLOW_FIELD_IDX_IPV4_DA */
0060     ICE_FLOW_FLD_INFO(ICE_FLOW_SEG_HDR_IPV4, 16, sizeof(struct in_addr)),
0061     /* ICE_FLOW_FIELD_IDX_IPV6_SA */
0062     ICE_FLOW_FLD_INFO(ICE_FLOW_SEG_HDR_IPV6, 8, sizeof(struct in6_addr)),
0063     /* ICE_FLOW_FIELD_IDX_IPV6_DA */
0064     ICE_FLOW_FLD_INFO(ICE_FLOW_SEG_HDR_IPV6, 24, sizeof(struct in6_addr)),
0065     /* Transport */
0066     /* ICE_FLOW_FIELD_IDX_TCP_SRC_PORT */
0067     ICE_FLOW_FLD_INFO(ICE_FLOW_SEG_HDR_TCP, 0, sizeof(__be16)),
0068     /* ICE_FLOW_FIELD_IDX_TCP_DST_PORT */
0069     ICE_FLOW_FLD_INFO(ICE_FLOW_SEG_HDR_TCP, 2, sizeof(__be16)),
0070     /* ICE_FLOW_FIELD_IDX_UDP_SRC_PORT */
0071     ICE_FLOW_FLD_INFO(ICE_FLOW_SEG_HDR_UDP, 0, sizeof(__be16)),
0072     /* ICE_FLOW_FIELD_IDX_UDP_DST_PORT */
0073     ICE_FLOW_FLD_INFO(ICE_FLOW_SEG_HDR_UDP, 2, sizeof(__be16)),
0074     /* ICE_FLOW_FIELD_IDX_SCTP_SRC_PORT */
0075     ICE_FLOW_FLD_INFO(ICE_FLOW_SEG_HDR_SCTP, 0, sizeof(__be16)),
0076     /* ICE_FLOW_FIELD_IDX_SCTP_DST_PORT */
0077     ICE_FLOW_FLD_INFO(ICE_FLOW_SEG_HDR_SCTP, 2, sizeof(__be16)),
0078     /* ICE_FLOW_FIELD_IDX_TCP_FLAGS */
0079     ICE_FLOW_FLD_INFO(ICE_FLOW_SEG_HDR_TCP, 13, 1),
0080     /* ARP */
0081     /* ICE_FLOW_FIELD_IDX_ARP_SIP */
0082     ICE_FLOW_FLD_INFO(ICE_FLOW_SEG_HDR_ARP, 14, sizeof(struct in_addr)),
0083     /* ICE_FLOW_FIELD_IDX_ARP_DIP */
0084     ICE_FLOW_FLD_INFO(ICE_FLOW_SEG_HDR_ARP, 24, sizeof(struct in_addr)),
0085     /* ICE_FLOW_FIELD_IDX_ARP_SHA */
0086     ICE_FLOW_FLD_INFO(ICE_FLOW_SEG_HDR_ARP, 8, ETH_ALEN),
0087     /* ICE_FLOW_FIELD_IDX_ARP_DHA */
0088     ICE_FLOW_FLD_INFO(ICE_FLOW_SEG_HDR_ARP, 18, ETH_ALEN),
0089     /* ICE_FLOW_FIELD_IDX_ARP_OP */
0090     ICE_FLOW_FLD_INFO(ICE_FLOW_SEG_HDR_ARP, 6, sizeof(__be16)),
0091     /* ICMP */
0092     /* ICE_FLOW_FIELD_IDX_ICMP_TYPE */
0093     ICE_FLOW_FLD_INFO(ICE_FLOW_SEG_HDR_ICMP, 0, 1),
0094     /* ICE_FLOW_FIELD_IDX_ICMP_CODE */
0095     ICE_FLOW_FLD_INFO(ICE_FLOW_SEG_HDR_ICMP, 1, 1),
0096     /* GRE */
0097     /* ICE_FLOW_FIELD_IDX_GRE_KEYID */
0098     ICE_FLOW_FLD_INFO(ICE_FLOW_SEG_HDR_GRE, 12,
0099               sizeof_field(struct gre_full_hdr, key)),
0100     /* GTP */
0101     /* ICE_FLOW_FIELD_IDX_GTPC_TEID */
0102     ICE_FLOW_FLD_INFO(ICE_FLOW_SEG_HDR_GTPC_TEID, 12, sizeof(__be32)),
0103     /* ICE_FLOW_FIELD_IDX_GTPU_IP_TEID */
0104     ICE_FLOW_FLD_INFO(ICE_FLOW_SEG_HDR_GTPU_IP, 12, sizeof(__be32)),
0105     /* ICE_FLOW_FIELD_IDX_GTPU_EH_TEID */
0106     ICE_FLOW_FLD_INFO(ICE_FLOW_SEG_HDR_GTPU_EH, 12, sizeof(__be32)),
0107     /* ICE_FLOW_FIELD_IDX_GTPU_EH_QFI */
0108     ICE_FLOW_FLD_INFO_MSK(ICE_FLOW_SEG_HDR_GTPU_EH, 22, sizeof(__be16),
0109                   0x3f00),
0110     /* ICE_FLOW_FIELD_IDX_GTPU_UP_TEID */
0111     ICE_FLOW_FLD_INFO(ICE_FLOW_SEG_HDR_GTPU_UP, 12, sizeof(__be32)),
0112     /* ICE_FLOW_FIELD_IDX_GTPU_DWN_TEID */
0113     ICE_FLOW_FLD_INFO(ICE_FLOW_SEG_HDR_GTPU_DWN, 12, sizeof(__be32)),
0114     /* PPPoE */
0115     /* ICE_FLOW_FIELD_IDX_PPPOE_SESS_ID */
0116     ICE_FLOW_FLD_INFO(ICE_FLOW_SEG_HDR_PPPOE, 2, sizeof(__be16)),
0117     /* PFCP */
0118     /* ICE_FLOW_FIELD_IDX_PFCP_SEID */
0119     ICE_FLOW_FLD_INFO(ICE_FLOW_SEG_HDR_PFCP_SESSION, 12, sizeof(__be64)),
0120     /* L2TPv3 */
0121     /* ICE_FLOW_FIELD_IDX_L2TPV3_SESS_ID */
0122     ICE_FLOW_FLD_INFO(ICE_FLOW_SEG_HDR_L2TPV3, 0, sizeof(__be32)),
0123     /* ESP */
0124     /* ICE_FLOW_FIELD_IDX_ESP_SPI */
0125     ICE_FLOW_FLD_INFO(ICE_FLOW_SEG_HDR_ESP, 0, sizeof(__be32)),
0126     /* AH */
0127     /* ICE_FLOW_FIELD_IDX_AH_SPI */
0128     ICE_FLOW_FLD_INFO(ICE_FLOW_SEG_HDR_AH, 4, sizeof(__be32)),
0129     /* NAT_T_ESP */
0130     /* ICE_FLOW_FIELD_IDX_NAT_T_ESP_SPI */
0131     ICE_FLOW_FLD_INFO(ICE_FLOW_SEG_HDR_NAT_T_ESP, 8, sizeof(__be32)),
0132 };
0133 
0134 /* Bitmaps indicating relevant packet types for a particular protocol header
0135  *
0136  * Packet types for packets with an Outer/First/Single MAC header
0137  */
0138 static const u32 ice_ptypes_mac_ofos[] = {
0139     0xFDC00846, 0xBFBF7F7E, 0xF70001DF, 0xFEFDFDFB,
0140     0x0000077E, 0x00000000, 0x00000000, 0x00000000,
0141     0x00400000, 0x03FFF000, 0x7FFFFFE0, 0x00000000,
0142     0x00000000, 0x00000000, 0x00000000, 0x00000000,
0143     0x00000000, 0x00000000, 0x00000000, 0x00000000,
0144     0x00000000, 0x00000000, 0x00000000, 0x00000000,
0145     0x00000000, 0x00000000, 0x00000000, 0x00000000,
0146     0x00000000, 0x00000000, 0x00000000, 0x00000000,
0147 };
0148 
0149 /* Packet types for packets with an Innermost/Last MAC VLAN header */
0150 static const u32 ice_ptypes_macvlan_il[] = {
0151     0x00000000, 0xBC000000, 0x000001DF, 0xF0000000,
0152     0x0000077E, 0x00000000, 0x00000000, 0x00000000,
0153     0x00000000, 0x00000000, 0x00000000, 0x00000000,
0154     0x00000000, 0x00000000, 0x00000000, 0x00000000,
0155     0x00000000, 0x00000000, 0x00000000, 0x00000000,
0156     0x00000000, 0x00000000, 0x00000000, 0x00000000,
0157     0x00000000, 0x00000000, 0x00000000, 0x00000000,
0158     0x00000000, 0x00000000, 0x00000000, 0x00000000,
0159 };
0160 
0161 /* Packet types for packets with an Outer/First/Single IPv4 header, does NOT
0162  * include IPv4 other PTYPEs
0163  */
0164 static const u32 ice_ptypes_ipv4_ofos[] = {
0165     0x1DC00000, 0x04000800, 0x00000000, 0x00000000,
0166     0x00000000, 0x00000155, 0x00000000, 0x00000000,
0167     0x00000000, 0x000FC000, 0x00000000, 0x00000000,
0168     0x00000000, 0x00000000, 0x00000000, 0x00000000,
0169     0x00000000, 0x00000000, 0x00000000, 0x00000000,
0170     0x00000000, 0x00000000, 0x00000000, 0x00000000,
0171     0x00000000, 0x00000000, 0x00000000, 0x00000000,
0172     0x00000000, 0x00000000, 0x00000000, 0x00000000,
0173 };
0174 
0175 /* Packet types for packets with an Outer/First/Single IPv4 header, includes
0176  * IPv4 other PTYPEs
0177  */
0178 static const u32 ice_ptypes_ipv4_ofos_all[] = {
0179     0x1DC00000, 0x04000800, 0x00000000, 0x00000000,
0180     0x00000000, 0x00000155, 0x00000000, 0x00000000,
0181     0x00000000, 0x000FC000, 0x83E0F800, 0x00000101,
0182     0x00000000, 0x00000000, 0x00000000, 0x00000000,
0183     0x00000000, 0x00000000, 0x00000000, 0x00000000,
0184     0x00000000, 0x00000000, 0x00000000, 0x00000000,
0185     0x00000000, 0x00000000, 0x00000000, 0x00000000,
0186     0x00000000, 0x00000000, 0x00000000, 0x00000000,
0187 };
0188 
0189 /* Packet types for packets with an Innermost/Last IPv4 header */
0190 static const u32 ice_ptypes_ipv4_il[] = {
0191     0xE0000000, 0xB807700E, 0x80000003, 0xE01DC03B,
0192     0x0000000E, 0x00000000, 0x00000000, 0x00000000,
0193     0x00000000, 0x00000000, 0x001FF800, 0x00000000,
0194     0x00000000, 0x00000000, 0x00000000, 0x00000000,
0195     0x00000000, 0x00000000, 0x00000000, 0x00000000,
0196     0x00000000, 0x00000000, 0x00000000, 0x00000000,
0197     0x00000000, 0x00000000, 0x00000000, 0x00000000,
0198     0x00000000, 0x00000000, 0x00000000, 0x00000000,
0199 };
0200 
0201 /* Packet types for packets with an Outer/First/Single IPv6 header, does NOT
0202  * include IPv6 other PTYPEs
0203  */
0204 static const u32 ice_ptypes_ipv6_ofos[] = {
0205     0x00000000, 0x00000000, 0x77000000, 0x10002000,
0206     0x00000000, 0x000002AA, 0x00000000, 0x00000000,
0207     0x00000000, 0x03F00000, 0x00000000, 0x00000000,
0208     0x00000000, 0x00000000, 0x00000000, 0x00000000,
0209     0x00000000, 0x00000000, 0x00000000, 0x00000000,
0210     0x00000000, 0x00000000, 0x00000000, 0x00000000,
0211     0x00000000, 0x00000000, 0x00000000, 0x00000000,
0212     0x00000000, 0x00000000, 0x00000000, 0x00000000,
0213 };
0214 
0215 /* Packet types for packets with an Outer/First/Single IPv6 header, includes
0216  * IPv6 other PTYPEs
0217  */
0218 static const u32 ice_ptypes_ipv6_ofos_all[] = {
0219     0x00000000, 0x00000000, 0x77000000, 0x10002000,
0220     0x00000000, 0x000002AA, 0x00000000, 0x00000000,
0221     0x00080F00, 0x03F00000, 0x7C1F0000, 0x00000206,
0222     0x00000000, 0x00000000, 0x00000000, 0x00000000,
0223     0x00000000, 0x00000000, 0x00000000, 0x00000000,
0224     0x00000000, 0x00000000, 0x00000000, 0x00000000,
0225     0x00000000, 0x00000000, 0x00000000, 0x00000000,
0226     0x00000000, 0x00000000, 0x00000000, 0x00000000,
0227 };
0228 
0229 /* Packet types for packets with an Innermost/Last IPv6 header */
0230 static const u32 ice_ptypes_ipv6_il[] = {
0231     0x00000000, 0x03B80770, 0x000001DC, 0x0EE00000,
0232     0x00000770, 0x00000000, 0x00000000, 0x00000000,
0233     0x00000000, 0x00000000, 0x7FE00000, 0x00000000,
0234     0x00000000, 0x00000000, 0x00000000, 0x00000000,
0235     0x00000000, 0x00000000, 0x00000000, 0x00000000,
0236     0x00000000, 0x00000000, 0x00000000, 0x00000000,
0237     0x00000000, 0x00000000, 0x00000000, 0x00000000,
0238     0x00000000, 0x00000000, 0x00000000, 0x00000000,
0239 };
0240 
0241 /* Packet types for packets with an Outer/First/Single IPv4 header - no L4 */
0242 static const u32 ice_ptypes_ipv4_ofos_no_l4[] = {
0243     0x10C00000, 0x04000800, 0x00000000, 0x00000000,
0244     0x00000000, 0x00000000, 0x00000000, 0x00000000,
0245     0x00000000, 0x00000000, 0x00000000, 0x00000000,
0246     0x00000000, 0x00000000, 0x00000000, 0x00000000,
0247     0x00000000, 0x00000000, 0x00000000, 0x00000000,
0248     0x00000000, 0x00000000, 0x00000000, 0x00000000,
0249     0x00000000, 0x00000000, 0x00000000, 0x00000000,
0250     0x00000000, 0x00000000, 0x00000000, 0x00000000,
0251 };
0252 
0253 /* Packet types for packets with an Outermost/First ARP header */
0254 static const u32 ice_ptypes_arp_of[] = {
0255     0x00000800, 0x00000000, 0x00000000, 0x00000000,
0256     0x00000000, 0x00000000, 0x00000000, 0x00000000,
0257     0x00000000, 0x00000000, 0x00000000, 0x00000000,
0258     0x00000000, 0x00000000, 0x00000000, 0x00000000,
0259     0x00000000, 0x00000000, 0x00000000, 0x00000000,
0260     0x00000000, 0x00000000, 0x00000000, 0x00000000,
0261     0x00000000, 0x00000000, 0x00000000, 0x00000000,
0262     0x00000000, 0x00000000, 0x00000000, 0x00000000,
0263 };
0264 
0265 /* Packet types for packets with an Innermost/Last IPv4 header - no L4 */
0266 static const u32 ice_ptypes_ipv4_il_no_l4[] = {
0267     0x60000000, 0x18043008, 0x80000002, 0x6010c021,
0268     0x00000008, 0x00000000, 0x00000000, 0x00000000,
0269     0x00000000, 0x00000000, 0x00000000, 0x00000000,
0270     0x00000000, 0x00000000, 0x00000000, 0x00000000,
0271     0x00000000, 0x00000000, 0x00000000, 0x00000000,
0272     0x00000000, 0x00000000, 0x00000000, 0x00000000,
0273     0x00000000, 0x00000000, 0x00000000, 0x00000000,
0274     0x00000000, 0x00000000, 0x00000000, 0x00000000,
0275 };
0276 
0277 /* Packet types for packets with an Outer/First/Single IPv6 header - no L4 */
0278 static const u32 ice_ptypes_ipv6_ofos_no_l4[] = {
0279     0x00000000, 0x00000000, 0x43000000, 0x10002000,
0280     0x00000000, 0x00000000, 0x00000000, 0x00000000,
0281     0x00000000, 0x00000000, 0x00000000, 0x00000000,
0282     0x00000000, 0x00000000, 0x00000000, 0x00000000,
0283     0x00000000, 0x00000000, 0x00000000, 0x00000000,
0284     0x00000000, 0x00000000, 0x00000000, 0x00000000,
0285     0x00000000, 0x00000000, 0x00000000, 0x00000000,
0286     0x00000000, 0x00000000, 0x00000000, 0x00000000,
0287 };
0288 
0289 /* Packet types for packets with an Innermost/Last IPv6 header - no L4 */
0290 static const u32 ice_ptypes_ipv6_il_no_l4[] = {
0291     0x00000000, 0x02180430, 0x0000010c, 0x086010c0,
0292     0x00000430, 0x00000000, 0x00000000, 0x00000000,
0293     0x00000000, 0x00000000, 0x00000000, 0x00000000,
0294     0x00000000, 0x00000000, 0x00000000, 0x00000000,
0295     0x00000000, 0x00000000, 0x00000000, 0x00000000,
0296     0x00000000, 0x00000000, 0x00000000, 0x00000000,
0297     0x00000000, 0x00000000, 0x00000000, 0x00000000,
0298     0x00000000, 0x00000000, 0x00000000, 0x00000000,
0299 };
0300 
0301 /* UDP Packet types for non-tunneled packets or tunneled
0302  * packets with inner UDP.
0303  */
0304 static const u32 ice_ptypes_udp_il[] = {
0305     0x81000000, 0x20204040, 0x04000010, 0x80810102,
0306     0x00000040, 0x00000000, 0x00000000, 0x00000000,
0307     0x00000000, 0x00410000, 0x90842000, 0x00000007,
0308     0x00000000, 0x00000000, 0x00000000, 0x00000000,
0309     0x00000000, 0x00000000, 0x00000000, 0x00000000,
0310     0x00000000, 0x00000000, 0x00000000, 0x00000000,
0311     0x00000000, 0x00000000, 0x00000000, 0x00000000,
0312     0x00000000, 0x00000000, 0x00000000, 0x00000000,
0313 };
0314 
0315 /* Packet types for packets with an Innermost/Last TCP header */
0316 static const u32 ice_ptypes_tcp_il[] = {
0317     0x04000000, 0x80810102, 0x10000040, 0x02040408,
0318     0x00000102, 0x00000000, 0x00000000, 0x00000000,
0319     0x00000000, 0x00820000, 0x21084000, 0x00000000,
0320     0x00000000, 0x00000000, 0x00000000, 0x00000000,
0321     0x00000000, 0x00000000, 0x00000000, 0x00000000,
0322     0x00000000, 0x00000000, 0x00000000, 0x00000000,
0323     0x00000000, 0x00000000, 0x00000000, 0x00000000,
0324     0x00000000, 0x00000000, 0x00000000, 0x00000000,
0325 };
0326 
0327 /* Packet types for packets with an Innermost/Last SCTP header */
0328 static const u32 ice_ptypes_sctp_il[] = {
0329     0x08000000, 0x01020204, 0x20000081, 0x04080810,
0330     0x00000204, 0x00000000, 0x00000000, 0x00000000,
0331     0x00000000, 0x01040000, 0x00000000, 0x00000000,
0332     0x00000000, 0x00000000, 0x00000000, 0x00000000,
0333     0x00000000, 0x00000000, 0x00000000, 0x00000000,
0334     0x00000000, 0x00000000, 0x00000000, 0x00000000,
0335     0x00000000, 0x00000000, 0x00000000, 0x00000000,
0336     0x00000000, 0x00000000, 0x00000000, 0x00000000,
0337 };
0338 
0339 /* Packet types for packets with an Outermost/First ICMP header */
0340 static const u32 ice_ptypes_icmp_of[] = {
0341     0x10000000, 0x00000000, 0x00000000, 0x00000000,
0342     0x00000000, 0x00000000, 0x00000000, 0x00000000,
0343     0x00000000, 0x00000000, 0x00000000, 0x00000000,
0344     0x00000000, 0x00000000, 0x00000000, 0x00000000,
0345     0x00000000, 0x00000000, 0x00000000, 0x00000000,
0346     0x00000000, 0x00000000, 0x00000000, 0x00000000,
0347     0x00000000, 0x00000000, 0x00000000, 0x00000000,
0348     0x00000000, 0x00000000, 0x00000000, 0x00000000,
0349 };
0350 
0351 /* Packet types for packets with an Innermost/Last ICMP header */
0352 static const u32 ice_ptypes_icmp_il[] = {
0353     0x00000000, 0x02040408, 0x40000102, 0x08101020,
0354     0x00000408, 0x00000000, 0x00000000, 0x00000000,
0355     0x00000000, 0x00000000, 0x42108000, 0x00000000,
0356     0x00000000, 0x00000000, 0x00000000, 0x00000000,
0357     0x00000000, 0x00000000, 0x00000000, 0x00000000,
0358     0x00000000, 0x00000000, 0x00000000, 0x00000000,
0359     0x00000000, 0x00000000, 0x00000000, 0x00000000,
0360     0x00000000, 0x00000000, 0x00000000, 0x00000000,
0361 };
0362 
0363 /* Packet types for packets with an Outermost/First GRE header */
0364 static const u32 ice_ptypes_gre_of[] = {
0365     0x00000000, 0xBFBF7800, 0x000001DF, 0xFEFDE000,
0366     0x0000017E, 0x00000000, 0x00000000, 0x00000000,
0367     0x00000000, 0x00000000, 0x00000000, 0x00000000,
0368     0x00000000, 0x00000000, 0x00000000, 0x00000000,
0369     0x00000000, 0x00000000, 0x00000000, 0x00000000,
0370     0x00000000, 0x00000000, 0x00000000, 0x00000000,
0371     0x00000000, 0x00000000, 0x00000000, 0x00000000,
0372     0x00000000, 0x00000000, 0x00000000, 0x00000000,
0373 };
0374 
0375 /* Packet types for packets with an Innermost/Last MAC header */
0376 static const u32 ice_ptypes_mac_il[] = {
0377     0x00000000, 0x00000000, 0x00000000, 0x00000000,
0378     0x00000000, 0x00000000, 0x00000000, 0x00000000,
0379     0x00000000, 0x00000000, 0x00000000, 0x00000000,
0380     0x00000000, 0x00000000, 0x00000000, 0x00000000,
0381     0x00000000, 0x00000000, 0x00000000, 0x00000000,
0382     0x00000000, 0x00000000, 0x00000000, 0x00000000,
0383     0x00000000, 0x00000000, 0x00000000, 0x00000000,
0384     0x00000000, 0x00000000, 0x00000000, 0x00000000,
0385 };
0386 
0387 /* Packet types for GTPC */
0388 static const u32 ice_ptypes_gtpc[] = {
0389     0x00000000, 0x00000000, 0x00000000, 0x00000000,
0390     0x00000000, 0x00000000, 0x00000000, 0x00000000,
0391     0x00000000, 0x00000000, 0x00000180, 0x00000000,
0392     0x00000000, 0x00000000, 0x00000000, 0x00000000,
0393     0x00000000, 0x00000000, 0x00000000, 0x00000000,
0394     0x00000000, 0x00000000, 0x00000000, 0x00000000,
0395     0x00000000, 0x00000000, 0x00000000, 0x00000000,
0396     0x00000000, 0x00000000, 0x00000000, 0x00000000,
0397 };
0398 
0399 /* Packet types for GTPC with TEID */
0400 static const u32 ice_ptypes_gtpc_tid[] = {
0401     0x00000000, 0x00000000, 0x00000000, 0x00000000,
0402     0x00000000, 0x00000000, 0x00000000, 0x00000000,
0403     0x00000000, 0x00000000, 0x00000060, 0x00000000,
0404     0x00000000, 0x00000000, 0x00000000, 0x00000000,
0405     0x00000000, 0x00000000, 0x00000000, 0x00000000,
0406     0x00000000, 0x00000000, 0x00000000, 0x00000000,
0407     0x00000000, 0x00000000, 0x00000000, 0x00000000,
0408     0x00000000, 0x00000000, 0x00000000, 0x00000000,
0409 };
0410 
0411 /* Packet types for GTPU */
0412 static const struct ice_ptype_attributes ice_attr_gtpu_eh[] = {
0413     { ICE_MAC_IPV4_GTPU_IPV4_FRAG,    ICE_PTYPE_ATTR_GTP_PDU_EH },
0414     { ICE_MAC_IPV4_GTPU_IPV4_PAY,     ICE_PTYPE_ATTR_GTP_PDU_EH },
0415     { ICE_MAC_IPV4_GTPU_IPV4_UDP_PAY, ICE_PTYPE_ATTR_GTP_PDU_EH },
0416     { ICE_MAC_IPV4_GTPU_IPV4_TCP,     ICE_PTYPE_ATTR_GTP_PDU_EH },
0417     { ICE_MAC_IPV4_GTPU_IPV4_ICMP,    ICE_PTYPE_ATTR_GTP_PDU_EH },
0418     { ICE_MAC_IPV6_GTPU_IPV4_FRAG,    ICE_PTYPE_ATTR_GTP_PDU_EH },
0419     { ICE_MAC_IPV6_GTPU_IPV4_PAY,     ICE_PTYPE_ATTR_GTP_PDU_EH },
0420     { ICE_MAC_IPV6_GTPU_IPV4_UDP_PAY, ICE_PTYPE_ATTR_GTP_PDU_EH },
0421     { ICE_MAC_IPV6_GTPU_IPV4_TCP,     ICE_PTYPE_ATTR_GTP_PDU_EH },
0422     { ICE_MAC_IPV6_GTPU_IPV4_ICMP,    ICE_PTYPE_ATTR_GTP_PDU_EH },
0423     { ICE_MAC_IPV4_GTPU_IPV6_FRAG,    ICE_PTYPE_ATTR_GTP_PDU_EH },
0424     { ICE_MAC_IPV4_GTPU_IPV6_PAY,     ICE_PTYPE_ATTR_GTP_PDU_EH },
0425     { ICE_MAC_IPV4_GTPU_IPV6_UDP_PAY, ICE_PTYPE_ATTR_GTP_PDU_EH },
0426     { ICE_MAC_IPV4_GTPU_IPV6_TCP,     ICE_PTYPE_ATTR_GTP_PDU_EH },
0427     { ICE_MAC_IPV4_GTPU_IPV6_ICMPV6,  ICE_PTYPE_ATTR_GTP_PDU_EH },
0428     { ICE_MAC_IPV6_GTPU_IPV6_FRAG,    ICE_PTYPE_ATTR_GTP_PDU_EH },
0429     { ICE_MAC_IPV6_GTPU_IPV6_PAY,     ICE_PTYPE_ATTR_GTP_PDU_EH },
0430     { ICE_MAC_IPV6_GTPU_IPV6_UDP_PAY, ICE_PTYPE_ATTR_GTP_PDU_EH },
0431     { ICE_MAC_IPV6_GTPU_IPV6_TCP,     ICE_PTYPE_ATTR_GTP_PDU_EH },
0432     { ICE_MAC_IPV6_GTPU_IPV6_ICMPV6,  ICE_PTYPE_ATTR_GTP_PDU_EH },
0433 };
0434 
0435 static const struct ice_ptype_attributes ice_attr_gtpu_down[] = {
0436     { ICE_MAC_IPV4_GTPU_IPV4_FRAG,    ICE_PTYPE_ATTR_GTP_DOWNLINK },
0437     { ICE_MAC_IPV4_GTPU_IPV4_PAY,     ICE_PTYPE_ATTR_GTP_DOWNLINK },
0438     { ICE_MAC_IPV4_GTPU_IPV4_UDP_PAY, ICE_PTYPE_ATTR_GTP_DOWNLINK },
0439     { ICE_MAC_IPV4_GTPU_IPV4_TCP,     ICE_PTYPE_ATTR_GTP_DOWNLINK },
0440     { ICE_MAC_IPV4_GTPU_IPV4_ICMP,    ICE_PTYPE_ATTR_GTP_DOWNLINK },
0441     { ICE_MAC_IPV6_GTPU_IPV4_FRAG,    ICE_PTYPE_ATTR_GTP_DOWNLINK },
0442     { ICE_MAC_IPV6_GTPU_IPV4_PAY,     ICE_PTYPE_ATTR_GTP_DOWNLINK },
0443     { ICE_MAC_IPV6_GTPU_IPV4_UDP_PAY, ICE_PTYPE_ATTR_GTP_DOWNLINK },
0444     { ICE_MAC_IPV6_GTPU_IPV4_TCP,     ICE_PTYPE_ATTR_GTP_DOWNLINK },
0445     { ICE_MAC_IPV6_GTPU_IPV4_ICMP,    ICE_PTYPE_ATTR_GTP_DOWNLINK },
0446     { ICE_MAC_IPV4_GTPU_IPV6_FRAG,    ICE_PTYPE_ATTR_GTP_DOWNLINK },
0447     { ICE_MAC_IPV4_GTPU_IPV6_PAY,     ICE_PTYPE_ATTR_GTP_DOWNLINK },
0448     { ICE_MAC_IPV4_GTPU_IPV6_UDP_PAY, ICE_PTYPE_ATTR_GTP_DOWNLINK },
0449     { ICE_MAC_IPV4_GTPU_IPV6_TCP,     ICE_PTYPE_ATTR_GTP_DOWNLINK },
0450     { ICE_MAC_IPV4_GTPU_IPV6_ICMPV6,  ICE_PTYPE_ATTR_GTP_DOWNLINK },
0451     { ICE_MAC_IPV6_GTPU_IPV6_FRAG,    ICE_PTYPE_ATTR_GTP_DOWNLINK },
0452     { ICE_MAC_IPV6_GTPU_IPV6_PAY,     ICE_PTYPE_ATTR_GTP_DOWNLINK },
0453     { ICE_MAC_IPV6_GTPU_IPV6_UDP_PAY, ICE_PTYPE_ATTR_GTP_DOWNLINK },
0454     { ICE_MAC_IPV6_GTPU_IPV6_TCP,     ICE_PTYPE_ATTR_GTP_DOWNLINK },
0455     { ICE_MAC_IPV6_GTPU_IPV6_ICMPV6,  ICE_PTYPE_ATTR_GTP_DOWNLINK },
0456 };
0457 
0458 static const struct ice_ptype_attributes ice_attr_gtpu_up[] = {
0459     { ICE_MAC_IPV4_GTPU_IPV4_FRAG,    ICE_PTYPE_ATTR_GTP_UPLINK },
0460     { ICE_MAC_IPV4_GTPU_IPV4_PAY,     ICE_PTYPE_ATTR_GTP_UPLINK },
0461     { ICE_MAC_IPV4_GTPU_IPV4_UDP_PAY, ICE_PTYPE_ATTR_GTP_UPLINK },
0462     { ICE_MAC_IPV4_GTPU_IPV4_TCP,     ICE_PTYPE_ATTR_GTP_UPLINK },
0463     { ICE_MAC_IPV4_GTPU_IPV4_ICMP,    ICE_PTYPE_ATTR_GTP_UPLINK },
0464     { ICE_MAC_IPV6_GTPU_IPV4_FRAG,    ICE_PTYPE_ATTR_GTP_UPLINK },
0465     { ICE_MAC_IPV6_GTPU_IPV4_PAY,     ICE_PTYPE_ATTR_GTP_UPLINK },
0466     { ICE_MAC_IPV6_GTPU_IPV4_UDP_PAY, ICE_PTYPE_ATTR_GTP_UPLINK },
0467     { ICE_MAC_IPV6_GTPU_IPV4_TCP,     ICE_PTYPE_ATTR_GTP_UPLINK },
0468     { ICE_MAC_IPV6_GTPU_IPV4_ICMP,    ICE_PTYPE_ATTR_GTP_UPLINK },
0469     { ICE_MAC_IPV4_GTPU_IPV6_FRAG,    ICE_PTYPE_ATTR_GTP_UPLINK },
0470     { ICE_MAC_IPV4_GTPU_IPV6_PAY,     ICE_PTYPE_ATTR_GTP_UPLINK },
0471     { ICE_MAC_IPV4_GTPU_IPV6_UDP_PAY, ICE_PTYPE_ATTR_GTP_UPLINK },
0472     { ICE_MAC_IPV4_GTPU_IPV6_TCP,     ICE_PTYPE_ATTR_GTP_UPLINK },
0473     { ICE_MAC_IPV4_GTPU_IPV6_ICMPV6,  ICE_PTYPE_ATTR_GTP_UPLINK },
0474     { ICE_MAC_IPV6_GTPU_IPV6_FRAG,    ICE_PTYPE_ATTR_GTP_UPLINK },
0475     { ICE_MAC_IPV6_GTPU_IPV6_PAY,     ICE_PTYPE_ATTR_GTP_UPLINK },
0476     { ICE_MAC_IPV6_GTPU_IPV6_UDP_PAY, ICE_PTYPE_ATTR_GTP_UPLINK },
0477     { ICE_MAC_IPV6_GTPU_IPV6_TCP,     ICE_PTYPE_ATTR_GTP_UPLINK },
0478     { ICE_MAC_IPV6_GTPU_IPV6_ICMPV6,  ICE_PTYPE_ATTR_GTP_UPLINK },
0479 };
0480 
0481 static const u32 ice_ptypes_gtpu[] = {
0482     0x00000000, 0x00000000, 0x00000000, 0x00000000,
0483     0x00000000, 0x00000000, 0x00000000, 0x00000000,
0484     0x00000000, 0x00000000, 0x7FFFFE00, 0x00000000,
0485     0x00000000, 0x00000000, 0x00000000, 0x00000000,
0486     0x00000000, 0x00000000, 0x00000000, 0x00000000,
0487     0x00000000, 0x00000000, 0x00000000, 0x00000000,
0488     0x00000000, 0x00000000, 0x00000000, 0x00000000,
0489     0x00000000, 0x00000000, 0x00000000, 0x00000000,
0490 };
0491 
0492 /* Packet types for PPPoE */
0493 static const u32 ice_ptypes_pppoe[] = {
0494     0x00000000, 0x00000000, 0x00000000, 0x00000000,
0495     0x00000000, 0x00000000, 0x00000000, 0x00000000,
0496     0x00000000, 0x03ffe000, 0x00000000, 0x00000000,
0497     0x00000000, 0x00000000, 0x00000000, 0x00000000,
0498     0x00000000, 0x00000000, 0x00000000, 0x00000000,
0499     0x00000000, 0x00000000, 0x00000000, 0x00000000,
0500     0x00000000, 0x00000000, 0x00000000, 0x00000000,
0501     0x00000000, 0x00000000, 0x00000000, 0x00000000,
0502 };
0503 
0504 /* Packet types for packets with PFCP NODE header */
0505 static const u32 ice_ptypes_pfcp_node[] = {
0506     0x00000000, 0x00000000, 0x00000000, 0x00000000,
0507     0x00000000, 0x00000000, 0x00000000, 0x00000000,
0508     0x00000000, 0x00000000, 0x80000000, 0x00000002,
0509     0x00000000, 0x00000000, 0x00000000, 0x00000000,
0510     0x00000000, 0x00000000, 0x00000000, 0x00000000,
0511     0x00000000, 0x00000000, 0x00000000, 0x00000000,
0512     0x00000000, 0x00000000, 0x00000000, 0x00000000,
0513     0x00000000, 0x00000000, 0x00000000, 0x00000000,
0514 };
0515 
0516 /* Packet types for packets with PFCP SESSION header */
0517 static const u32 ice_ptypes_pfcp_session[] = {
0518     0x00000000, 0x00000000, 0x00000000, 0x00000000,
0519     0x00000000, 0x00000000, 0x00000000, 0x00000000,
0520     0x00000000, 0x00000000, 0x00000000, 0x00000005,
0521     0x00000000, 0x00000000, 0x00000000, 0x00000000,
0522     0x00000000, 0x00000000, 0x00000000, 0x00000000,
0523     0x00000000, 0x00000000, 0x00000000, 0x00000000,
0524     0x00000000, 0x00000000, 0x00000000, 0x00000000,
0525     0x00000000, 0x00000000, 0x00000000, 0x00000000,
0526 };
0527 
0528 /* Packet types for L2TPv3 */
0529 static const u32 ice_ptypes_l2tpv3[] = {
0530     0x00000000, 0x00000000, 0x00000000, 0x00000000,
0531     0x00000000, 0x00000000, 0x00000000, 0x00000000,
0532     0x00000000, 0x00000000, 0x00000000, 0x00000300,
0533     0x00000000, 0x00000000, 0x00000000, 0x00000000,
0534     0x00000000, 0x00000000, 0x00000000, 0x00000000,
0535     0x00000000, 0x00000000, 0x00000000, 0x00000000,
0536     0x00000000, 0x00000000, 0x00000000, 0x00000000,
0537     0x00000000, 0x00000000, 0x00000000, 0x00000000,
0538 };
0539 
0540 /* Packet types for ESP */
0541 static const u32 ice_ptypes_esp[] = {
0542     0x00000000, 0x00000000, 0x00000000, 0x00000000,
0543     0x00000000, 0x00000003, 0x00000000, 0x00000000,
0544     0x00000000, 0x00000000, 0x00000000, 0x00000000,
0545     0x00000000, 0x00000000, 0x00000000, 0x00000000,
0546     0x00000000, 0x00000000, 0x00000000, 0x00000000,
0547     0x00000000, 0x00000000, 0x00000000, 0x00000000,
0548     0x00000000, 0x00000000, 0x00000000, 0x00000000,
0549     0x00000000, 0x00000000, 0x00000000, 0x00000000,
0550 };
0551 
0552 /* Packet types for AH */
0553 static const u32 ice_ptypes_ah[] = {
0554     0x00000000, 0x00000000, 0x00000000, 0x00000000,
0555     0x00000000, 0x0000000C, 0x00000000, 0x00000000,
0556     0x00000000, 0x00000000, 0x00000000, 0x00000000,
0557     0x00000000, 0x00000000, 0x00000000, 0x00000000,
0558     0x00000000, 0x00000000, 0x00000000, 0x00000000,
0559     0x00000000, 0x00000000, 0x00000000, 0x00000000,
0560     0x00000000, 0x00000000, 0x00000000, 0x00000000,
0561     0x00000000, 0x00000000, 0x00000000, 0x00000000,
0562 };
0563 
0564 /* Packet types for packets with NAT_T ESP header */
0565 static const u32 ice_ptypes_nat_t_esp[] = {
0566     0x00000000, 0x00000000, 0x00000000, 0x00000000,
0567     0x00000000, 0x00000030, 0x00000000, 0x00000000,
0568     0x00000000, 0x00000000, 0x00000000, 0x00000000,
0569     0x00000000, 0x00000000, 0x00000000, 0x00000000,
0570     0x00000000, 0x00000000, 0x00000000, 0x00000000,
0571     0x00000000, 0x00000000, 0x00000000, 0x00000000,
0572     0x00000000, 0x00000000, 0x00000000, 0x00000000,
0573     0x00000000, 0x00000000, 0x00000000, 0x00000000,
0574 };
0575 
0576 static const u32 ice_ptypes_mac_non_ip_ofos[] = {
0577     0x00000846, 0x00000000, 0x00000000, 0x00000000,
0578     0x00000000, 0x00000000, 0x00000000, 0x00000000,
0579     0x00400000, 0x03FFF000, 0x00000000, 0x00000000,
0580     0x00000000, 0x00000000, 0x00000000, 0x00000000,
0581     0x00000000, 0x00000000, 0x00000000, 0x00000000,
0582     0x00000000, 0x00000000, 0x00000000, 0x00000000,
0583     0x00000000, 0x00000000, 0x00000000, 0x00000000,
0584     0x00000000, 0x00000000, 0x00000000, 0x00000000,
0585 };
0586 
0587 /* Manage parameters and info. used during the creation of a flow profile */
0588 struct ice_flow_prof_params {
0589     enum ice_block blk;
0590     u16 entry_length; /* # of bytes formatted entry will require */
0591     u8 es_cnt;
0592     struct ice_flow_prof *prof;
0593 
0594     /* For ACL, the es[0] will have the data of ICE_RX_MDID_PKT_FLAGS_15_0
0595      * This will give us the direction flags.
0596      */
0597     struct ice_fv_word es[ICE_MAX_FV_WORDS];
0598     /* attributes can be used to add attributes to a particular PTYPE */
0599     const struct ice_ptype_attributes *attr;
0600     u16 attr_cnt;
0601 
0602     u16 mask[ICE_MAX_FV_WORDS];
0603     DECLARE_BITMAP(ptypes, ICE_FLOW_PTYPE_MAX);
0604 };
0605 
0606 #define ICE_FLOW_RSS_HDRS_INNER_MASK \
0607     (ICE_FLOW_SEG_HDR_PPPOE | ICE_FLOW_SEG_HDR_GTPC | \
0608     ICE_FLOW_SEG_HDR_GTPC_TEID | ICE_FLOW_SEG_HDR_GTPU | \
0609     ICE_FLOW_SEG_HDR_PFCP_SESSION | ICE_FLOW_SEG_HDR_L2TPV3 | \
0610     ICE_FLOW_SEG_HDR_ESP | ICE_FLOW_SEG_HDR_AH | \
0611     ICE_FLOW_SEG_HDR_NAT_T_ESP)
0612 
0613 #define ICE_FLOW_SEG_HDRS_L3_MASK   \
0614     (ICE_FLOW_SEG_HDR_IPV4 | ICE_FLOW_SEG_HDR_IPV6 | ICE_FLOW_SEG_HDR_ARP)
0615 #define ICE_FLOW_SEG_HDRS_L4_MASK   \
0616     (ICE_FLOW_SEG_HDR_ICMP | ICE_FLOW_SEG_HDR_TCP | ICE_FLOW_SEG_HDR_UDP | \
0617      ICE_FLOW_SEG_HDR_SCTP)
0618 /* mask for L4 protocols that are NOT part of IPv4/6 OTHER PTYPE groups */
0619 #define ICE_FLOW_SEG_HDRS_L4_MASK_NO_OTHER  \
0620     (ICE_FLOW_SEG_HDR_TCP | ICE_FLOW_SEG_HDR_UDP | ICE_FLOW_SEG_HDR_SCTP)
0621 
0622 /**
0623  * ice_flow_val_hdrs - validates packet segments for valid protocol headers
0624  * @segs: array of one or more packet segments that describe the flow
0625  * @segs_cnt: number of packet segments provided
0626  */
0627 static int ice_flow_val_hdrs(struct ice_flow_seg_info *segs, u8 segs_cnt)
0628 {
0629     u8 i;
0630 
0631     for (i = 0; i < segs_cnt; i++) {
0632         /* Multiple L3 headers */
0633         if (segs[i].hdrs & ICE_FLOW_SEG_HDRS_L3_MASK &&
0634             !is_power_of_2(segs[i].hdrs & ICE_FLOW_SEG_HDRS_L3_MASK))
0635             return -EINVAL;
0636 
0637         /* Multiple L4 headers */
0638         if (segs[i].hdrs & ICE_FLOW_SEG_HDRS_L4_MASK &&
0639             !is_power_of_2(segs[i].hdrs & ICE_FLOW_SEG_HDRS_L4_MASK))
0640             return -EINVAL;
0641     }
0642 
0643     return 0;
0644 }
0645 
0646 /* Sizes of fixed known protocol headers without header options */
0647 #define ICE_FLOW_PROT_HDR_SZ_MAC    14
0648 #define ICE_FLOW_PROT_HDR_SZ_MAC_VLAN   (ICE_FLOW_PROT_HDR_SZ_MAC + 2)
0649 #define ICE_FLOW_PROT_HDR_SZ_IPV4   20
0650 #define ICE_FLOW_PROT_HDR_SZ_IPV6   40
0651 #define ICE_FLOW_PROT_HDR_SZ_ARP    28
0652 #define ICE_FLOW_PROT_HDR_SZ_ICMP   8
0653 #define ICE_FLOW_PROT_HDR_SZ_TCP    20
0654 #define ICE_FLOW_PROT_HDR_SZ_UDP    8
0655 #define ICE_FLOW_PROT_HDR_SZ_SCTP   12
0656 
0657 /**
0658  * ice_flow_calc_seg_sz - calculates size of a packet segment based on headers
0659  * @params: information about the flow to be processed
0660  * @seg: index of packet segment whose header size is to be determined
0661  */
0662 static u16 ice_flow_calc_seg_sz(struct ice_flow_prof_params *params, u8 seg)
0663 {
0664     u16 sz;
0665 
0666     /* L2 headers */
0667     sz = (params->prof->segs[seg].hdrs & ICE_FLOW_SEG_HDR_VLAN) ?
0668         ICE_FLOW_PROT_HDR_SZ_MAC_VLAN : ICE_FLOW_PROT_HDR_SZ_MAC;
0669 
0670     /* L3 headers */
0671     if (params->prof->segs[seg].hdrs & ICE_FLOW_SEG_HDR_IPV4)
0672         sz += ICE_FLOW_PROT_HDR_SZ_IPV4;
0673     else if (params->prof->segs[seg].hdrs & ICE_FLOW_SEG_HDR_IPV6)
0674         sz += ICE_FLOW_PROT_HDR_SZ_IPV6;
0675     else if (params->prof->segs[seg].hdrs & ICE_FLOW_SEG_HDR_ARP)
0676         sz += ICE_FLOW_PROT_HDR_SZ_ARP;
0677     else if (params->prof->segs[seg].hdrs & ICE_FLOW_SEG_HDRS_L4_MASK)
0678         /* An L3 header is required if L4 is specified */
0679         return 0;
0680 
0681     /* L4 headers */
0682     if (params->prof->segs[seg].hdrs & ICE_FLOW_SEG_HDR_ICMP)
0683         sz += ICE_FLOW_PROT_HDR_SZ_ICMP;
0684     else if (params->prof->segs[seg].hdrs & ICE_FLOW_SEG_HDR_TCP)
0685         sz += ICE_FLOW_PROT_HDR_SZ_TCP;
0686     else if (params->prof->segs[seg].hdrs & ICE_FLOW_SEG_HDR_UDP)
0687         sz += ICE_FLOW_PROT_HDR_SZ_UDP;
0688     else if (params->prof->segs[seg].hdrs & ICE_FLOW_SEG_HDR_SCTP)
0689         sz += ICE_FLOW_PROT_HDR_SZ_SCTP;
0690 
0691     return sz;
0692 }
0693 
0694 /**
0695  * ice_flow_proc_seg_hdrs - process protocol headers present in pkt segments
0696  * @params: information about the flow to be processed
0697  *
0698  * This function identifies the packet types associated with the protocol
0699  * headers being present in packet segments of the specified flow profile.
0700  */
0701 static int ice_flow_proc_seg_hdrs(struct ice_flow_prof_params *params)
0702 {
0703     struct ice_flow_prof *prof;
0704     u8 i;
0705 
0706     memset(params->ptypes, 0xff, sizeof(params->ptypes));
0707 
0708     prof = params->prof;
0709 
0710     for (i = 0; i < params->prof->segs_cnt; i++) {
0711         const unsigned long *src;
0712         u32 hdrs;
0713 
0714         hdrs = prof->segs[i].hdrs;
0715 
0716         if (hdrs & ICE_FLOW_SEG_HDR_ETH) {
0717             src = !i ? (const unsigned long *)ice_ptypes_mac_ofos :
0718                 (const unsigned long *)ice_ptypes_mac_il;
0719             bitmap_and(params->ptypes, params->ptypes, src,
0720                    ICE_FLOW_PTYPE_MAX);
0721         }
0722 
0723         if (i && hdrs & ICE_FLOW_SEG_HDR_VLAN) {
0724             src = (const unsigned long *)ice_ptypes_macvlan_il;
0725             bitmap_and(params->ptypes, params->ptypes, src,
0726                    ICE_FLOW_PTYPE_MAX);
0727         }
0728 
0729         if (!i && hdrs & ICE_FLOW_SEG_HDR_ARP) {
0730             bitmap_and(params->ptypes, params->ptypes,
0731                    (const unsigned long *)ice_ptypes_arp_of,
0732                    ICE_FLOW_PTYPE_MAX);
0733         }
0734 
0735         if ((hdrs & ICE_FLOW_SEG_HDR_IPV4) &&
0736             (hdrs & ICE_FLOW_SEG_HDR_IPV_OTHER)) {
0737             src = i ? (const unsigned long *)ice_ptypes_ipv4_il :
0738                 (const unsigned long *)ice_ptypes_ipv4_ofos_all;
0739             bitmap_and(params->ptypes, params->ptypes, src,
0740                    ICE_FLOW_PTYPE_MAX);
0741         } else if ((hdrs & ICE_FLOW_SEG_HDR_IPV6) &&
0742                (hdrs & ICE_FLOW_SEG_HDR_IPV_OTHER)) {
0743             src = i ? (const unsigned long *)ice_ptypes_ipv6_il :
0744                 (const unsigned long *)ice_ptypes_ipv6_ofos_all;
0745             bitmap_and(params->ptypes, params->ptypes, src,
0746                    ICE_FLOW_PTYPE_MAX);
0747         } else if ((hdrs & ICE_FLOW_SEG_HDR_IPV4) &&
0748                !(hdrs & ICE_FLOW_SEG_HDRS_L4_MASK_NO_OTHER)) {
0749             src = !i ? (const unsigned long *)ice_ptypes_ipv4_ofos_no_l4 :
0750                 (const unsigned long *)ice_ptypes_ipv4_il_no_l4;
0751             bitmap_and(params->ptypes, params->ptypes, src,
0752                    ICE_FLOW_PTYPE_MAX);
0753         } else if (hdrs & ICE_FLOW_SEG_HDR_IPV4) {
0754             src = !i ? (const unsigned long *)ice_ptypes_ipv4_ofos :
0755                 (const unsigned long *)ice_ptypes_ipv4_il;
0756             bitmap_and(params->ptypes, params->ptypes, src,
0757                    ICE_FLOW_PTYPE_MAX);
0758         } else if ((hdrs & ICE_FLOW_SEG_HDR_IPV6) &&
0759                !(hdrs & ICE_FLOW_SEG_HDRS_L4_MASK_NO_OTHER)) {
0760             src = !i ? (const unsigned long *)ice_ptypes_ipv6_ofos_no_l4 :
0761                 (const unsigned long *)ice_ptypes_ipv6_il_no_l4;
0762             bitmap_and(params->ptypes, params->ptypes, src,
0763                    ICE_FLOW_PTYPE_MAX);
0764         } else if (hdrs & ICE_FLOW_SEG_HDR_IPV6) {
0765             src = !i ? (const unsigned long *)ice_ptypes_ipv6_ofos :
0766                 (const unsigned long *)ice_ptypes_ipv6_il;
0767             bitmap_and(params->ptypes, params->ptypes, src,
0768                    ICE_FLOW_PTYPE_MAX);
0769         }
0770 
0771         if (hdrs & ICE_FLOW_SEG_HDR_ETH_NON_IP) {
0772             src = (const unsigned long *)ice_ptypes_mac_non_ip_ofos;
0773             bitmap_and(params->ptypes, params->ptypes, src,
0774                    ICE_FLOW_PTYPE_MAX);
0775         } else if (hdrs & ICE_FLOW_SEG_HDR_PPPOE) {
0776             src = (const unsigned long *)ice_ptypes_pppoe;
0777             bitmap_and(params->ptypes, params->ptypes, src,
0778                    ICE_FLOW_PTYPE_MAX);
0779         } else {
0780             src = (const unsigned long *)ice_ptypes_pppoe;
0781             bitmap_andnot(params->ptypes, params->ptypes, src,
0782                       ICE_FLOW_PTYPE_MAX);
0783         }
0784 
0785         if (hdrs & ICE_FLOW_SEG_HDR_UDP) {
0786             src = (const unsigned long *)ice_ptypes_udp_il;
0787             bitmap_and(params->ptypes, params->ptypes, src,
0788                    ICE_FLOW_PTYPE_MAX);
0789         } else if (hdrs & ICE_FLOW_SEG_HDR_TCP) {
0790             bitmap_and(params->ptypes, params->ptypes,
0791                    (const unsigned long *)ice_ptypes_tcp_il,
0792                    ICE_FLOW_PTYPE_MAX);
0793         } else if (hdrs & ICE_FLOW_SEG_HDR_SCTP) {
0794             src = (const unsigned long *)ice_ptypes_sctp_il;
0795             bitmap_and(params->ptypes, params->ptypes, src,
0796                    ICE_FLOW_PTYPE_MAX);
0797         }
0798 
0799         if (hdrs & ICE_FLOW_SEG_HDR_ICMP) {
0800             src = !i ? (const unsigned long *)ice_ptypes_icmp_of :
0801                 (const unsigned long *)ice_ptypes_icmp_il;
0802             bitmap_and(params->ptypes, params->ptypes, src,
0803                    ICE_FLOW_PTYPE_MAX);
0804         } else if (hdrs & ICE_FLOW_SEG_HDR_GRE) {
0805             if (!i) {
0806                 src = (const unsigned long *)ice_ptypes_gre_of;
0807                 bitmap_and(params->ptypes, params->ptypes,
0808                        src, ICE_FLOW_PTYPE_MAX);
0809             }
0810         } else if (hdrs & ICE_FLOW_SEG_HDR_GTPC) {
0811             src = (const unsigned long *)ice_ptypes_gtpc;
0812             bitmap_and(params->ptypes, params->ptypes, src,
0813                    ICE_FLOW_PTYPE_MAX);
0814         } else if (hdrs & ICE_FLOW_SEG_HDR_GTPC_TEID) {
0815             src = (const unsigned long *)ice_ptypes_gtpc_tid;
0816             bitmap_and(params->ptypes, params->ptypes, src,
0817                    ICE_FLOW_PTYPE_MAX);
0818         } else if (hdrs & ICE_FLOW_SEG_HDR_GTPU_DWN) {
0819             src = (const unsigned long *)ice_ptypes_gtpu;
0820             bitmap_and(params->ptypes, params->ptypes, src,
0821                    ICE_FLOW_PTYPE_MAX);
0822 
0823             /* Attributes for GTP packet with downlink */
0824             params->attr = ice_attr_gtpu_down;
0825             params->attr_cnt = ARRAY_SIZE(ice_attr_gtpu_down);
0826         } else if (hdrs & ICE_FLOW_SEG_HDR_GTPU_UP) {
0827             src = (const unsigned long *)ice_ptypes_gtpu;
0828             bitmap_and(params->ptypes, params->ptypes, src,
0829                    ICE_FLOW_PTYPE_MAX);
0830 
0831             /* Attributes for GTP packet with uplink */
0832             params->attr = ice_attr_gtpu_up;
0833             params->attr_cnt = ARRAY_SIZE(ice_attr_gtpu_up);
0834         } else if (hdrs & ICE_FLOW_SEG_HDR_GTPU_EH) {
0835             src = (const unsigned long *)ice_ptypes_gtpu;
0836             bitmap_and(params->ptypes, params->ptypes, src,
0837                    ICE_FLOW_PTYPE_MAX);
0838 
0839             /* Attributes for GTP packet with Extension Header */
0840             params->attr = ice_attr_gtpu_eh;
0841             params->attr_cnt = ARRAY_SIZE(ice_attr_gtpu_eh);
0842         } else if (hdrs & ICE_FLOW_SEG_HDR_GTPU_IP) {
0843             src = (const unsigned long *)ice_ptypes_gtpu;
0844             bitmap_and(params->ptypes, params->ptypes, src,
0845                    ICE_FLOW_PTYPE_MAX);
0846         } else if (hdrs & ICE_FLOW_SEG_HDR_L2TPV3) {
0847             src = (const unsigned long *)ice_ptypes_l2tpv3;
0848             bitmap_and(params->ptypes, params->ptypes, src,
0849                    ICE_FLOW_PTYPE_MAX);
0850         } else if (hdrs & ICE_FLOW_SEG_HDR_ESP) {
0851             src = (const unsigned long *)ice_ptypes_esp;
0852             bitmap_and(params->ptypes, params->ptypes, src,
0853                    ICE_FLOW_PTYPE_MAX);
0854         } else if (hdrs & ICE_FLOW_SEG_HDR_AH) {
0855             src = (const unsigned long *)ice_ptypes_ah;
0856             bitmap_and(params->ptypes, params->ptypes, src,
0857                    ICE_FLOW_PTYPE_MAX);
0858         } else if (hdrs & ICE_FLOW_SEG_HDR_NAT_T_ESP) {
0859             src = (const unsigned long *)ice_ptypes_nat_t_esp;
0860             bitmap_and(params->ptypes, params->ptypes, src,
0861                    ICE_FLOW_PTYPE_MAX);
0862         }
0863 
0864         if (hdrs & ICE_FLOW_SEG_HDR_PFCP) {
0865             if (hdrs & ICE_FLOW_SEG_HDR_PFCP_NODE)
0866                 src = (const unsigned long *)ice_ptypes_pfcp_node;
0867             else
0868                 src = (const unsigned long *)ice_ptypes_pfcp_session;
0869 
0870             bitmap_and(params->ptypes, params->ptypes, src,
0871                    ICE_FLOW_PTYPE_MAX);
0872         } else {
0873             src = (const unsigned long *)ice_ptypes_pfcp_node;
0874             bitmap_andnot(params->ptypes, params->ptypes, src,
0875                       ICE_FLOW_PTYPE_MAX);
0876 
0877             src = (const unsigned long *)ice_ptypes_pfcp_session;
0878             bitmap_andnot(params->ptypes, params->ptypes, src,
0879                       ICE_FLOW_PTYPE_MAX);
0880         }
0881     }
0882 
0883     return 0;
0884 }
0885 
0886 /**
0887  * ice_flow_xtract_fld - Create an extraction sequence entry for the given field
0888  * @hw: pointer to the HW struct
0889  * @params: information about the flow to be processed
0890  * @seg: packet segment index of the field to be extracted
0891  * @fld: ID of field to be extracted
0892  * @match: bit field of all fields
0893  *
0894  * This function determines the protocol ID, offset, and size of the given
0895  * field. It then allocates one or more extraction sequence entries for the
0896  * given field, and fill the entries with protocol ID and offset information.
0897  */
0898 static int
0899 ice_flow_xtract_fld(struct ice_hw *hw, struct ice_flow_prof_params *params,
0900             u8 seg, enum ice_flow_field fld, u64 match)
0901 {
0902     enum ice_flow_field sib = ICE_FLOW_FIELD_IDX_MAX;
0903     enum ice_prot_id prot_id = ICE_PROT_ID_INVAL;
0904     u8 fv_words = hw->blk[params->blk].es.fvw;
0905     struct ice_flow_fld_info *flds;
0906     u16 cnt, ese_bits, i;
0907     u16 sib_mask = 0;
0908     u16 mask;
0909     u16 off;
0910 
0911     flds = params->prof->segs[seg].fields;
0912 
0913     switch (fld) {
0914     case ICE_FLOW_FIELD_IDX_ETH_DA:
0915     case ICE_FLOW_FIELD_IDX_ETH_SA:
0916     case ICE_FLOW_FIELD_IDX_S_VLAN:
0917     case ICE_FLOW_FIELD_IDX_C_VLAN:
0918         prot_id = seg == 0 ? ICE_PROT_MAC_OF_OR_S : ICE_PROT_MAC_IL;
0919         break;
0920     case ICE_FLOW_FIELD_IDX_ETH_TYPE:
0921         prot_id = seg == 0 ? ICE_PROT_ETYPE_OL : ICE_PROT_ETYPE_IL;
0922         break;
0923     case ICE_FLOW_FIELD_IDX_IPV4_DSCP:
0924         prot_id = seg == 0 ? ICE_PROT_IPV4_OF_OR_S : ICE_PROT_IPV4_IL;
0925         break;
0926     case ICE_FLOW_FIELD_IDX_IPV6_DSCP:
0927         prot_id = seg == 0 ? ICE_PROT_IPV6_OF_OR_S : ICE_PROT_IPV6_IL;
0928         break;
0929     case ICE_FLOW_FIELD_IDX_IPV4_TTL:
0930     case ICE_FLOW_FIELD_IDX_IPV4_PROT:
0931         prot_id = seg == 0 ? ICE_PROT_IPV4_OF_OR_S : ICE_PROT_IPV4_IL;
0932 
0933         /* TTL and PROT share the same extraction seq. entry.
0934          * Each is considered a sibling to the other in terms of sharing
0935          * the same extraction sequence entry.
0936          */
0937         if (fld == ICE_FLOW_FIELD_IDX_IPV4_TTL)
0938             sib = ICE_FLOW_FIELD_IDX_IPV4_PROT;
0939         else if (fld == ICE_FLOW_FIELD_IDX_IPV4_PROT)
0940             sib = ICE_FLOW_FIELD_IDX_IPV4_TTL;
0941 
0942         /* If the sibling field is also included, that field's
0943          * mask needs to be included.
0944          */
0945         if (match & BIT(sib))
0946             sib_mask = ice_flds_info[sib].mask;
0947         break;
0948     case ICE_FLOW_FIELD_IDX_IPV6_TTL:
0949     case ICE_FLOW_FIELD_IDX_IPV6_PROT:
0950         prot_id = seg == 0 ? ICE_PROT_IPV6_OF_OR_S : ICE_PROT_IPV6_IL;
0951 
0952         /* TTL and PROT share the same extraction seq. entry.
0953          * Each is considered a sibling to the other in terms of sharing
0954          * the same extraction sequence entry.
0955          */
0956         if (fld == ICE_FLOW_FIELD_IDX_IPV6_TTL)
0957             sib = ICE_FLOW_FIELD_IDX_IPV6_PROT;
0958         else if (fld == ICE_FLOW_FIELD_IDX_IPV6_PROT)
0959             sib = ICE_FLOW_FIELD_IDX_IPV6_TTL;
0960 
0961         /* If the sibling field is also included, that field's
0962          * mask needs to be included.
0963          */
0964         if (match & BIT(sib))
0965             sib_mask = ice_flds_info[sib].mask;
0966         break;
0967     case ICE_FLOW_FIELD_IDX_IPV4_SA:
0968     case ICE_FLOW_FIELD_IDX_IPV4_DA:
0969         prot_id = seg == 0 ? ICE_PROT_IPV4_OF_OR_S : ICE_PROT_IPV4_IL;
0970         break;
0971     case ICE_FLOW_FIELD_IDX_IPV6_SA:
0972     case ICE_FLOW_FIELD_IDX_IPV6_DA:
0973         prot_id = seg == 0 ? ICE_PROT_IPV6_OF_OR_S : ICE_PROT_IPV6_IL;
0974         break;
0975     case ICE_FLOW_FIELD_IDX_TCP_SRC_PORT:
0976     case ICE_FLOW_FIELD_IDX_TCP_DST_PORT:
0977     case ICE_FLOW_FIELD_IDX_TCP_FLAGS:
0978         prot_id = ICE_PROT_TCP_IL;
0979         break;
0980     case ICE_FLOW_FIELD_IDX_UDP_SRC_PORT:
0981     case ICE_FLOW_FIELD_IDX_UDP_DST_PORT:
0982         prot_id = ICE_PROT_UDP_IL_OR_S;
0983         break;
0984     case ICE_FLOW_FIELD_IDX_SCTP_SRC_PORT:
0985     case ICE_FLOW_FIELD_IDX_SCTP_DST_PORT:
0986         prot_id = ICE_PROT_SCTP_IL;
0987         break;
0988     case ICE_FLOW_FIELD_IDX_GTPC_TEID:
0989     case ICE_FLOW_FIELD_IDX_GTPU_IP_TEID:
0990     case ICE_FLOW_FIELD_IDX_GTPU_UP_TEID:
0991     case ICE_FLOW_FIELD_IDX_GTPU_DWN_TEID:
0992     case ICE_FLOW_FIELD_IDX_GTPU_EH_TEID:
0993     case ICE_FLOW_FIELD_IDX_GTPU_EH_QFI:
0994         /* GTP is accessed through UDP OF protocol */
0995         prot_id = ICE_PROT_UDP_OF;
0996         break;
0997     case ICE_FLOW_FIELD_IDX_PPPOE_SESS_ID:
0998         prot_id = ICE_PROT_PPPOE;
0999         break;
1000     case ICE_FLOW_FIELD_IDX_PFCP_SEID:
1001         prot_id = ICE_PROT_UDP_IL_OR_S;
1002         break;
1003     case ICE_FLOW_FIELD_IDX_L2TPV3_SESS_ID:
1004         prot_id = ICE_PROT_L2TPV3;
1005         break;
1006     case ICE_FLOW_FIELD_IDX_ESP_SPI:
1007         prot_id = ICE_PROT_ESP_F;
1008         break;
1009     case ICE_FLOW_FIELD_IDX_AH_SPI:
1010         prot_id = ICE_PROT_ESP_2;
1011         break;
1012     case ICE_FLOW_FIELD_IDX_NAT_T_ESP_SPI:
1013         prot_id = ICE_PROT_UDP_IL_OR_S;
1014         break;
1015     case ICE_FLOW_FIELD_IDX_ARP_SIP:
1016     case ICE_FLOW_FIELD_IDX_ARP_DIP:
1017     case ICE_FLOW_FIELD_IDX_ARP_SHA:
1018     case ICE_FLOW_FIELD_IDX_ARP_DHA:
1019     case ICE_FLOW_FIELD_IDX_ARP_OP:
1020         prot_id = ICE_PROT_ARP_OF;
1021         break;
1022     case ICE_FLOW_FIELD_IDX_ICMP_TYPE:
1023     case ICE_FLOW_FIELD_IDX_ICMP_CODE:
1024         /* ICMP type and code share the same extraction seq. entry */
1025         prot_id = (params->prof->segs[seg].hdrs & ICE_FLOW_SEG_HDR_IPV4) ?
1026                 ICE_PROT_ICMP_IL : ICE_PROT_ICMPV6_IL;
1027         sib = fld == ICE_FLOW_FIELD_IDX_ICMP_TYPE ?
1028             ICE_FLOW_FIELD_IDX_ICMP_CODE :
1029             ICE_FLOW_FIELD_IDX_ICMP_TYPE;
1030         break;
1031     case ICE_FLOW_FIELD_IDX_GRE_KEYID:
1032         prot_id = ICE_PROT_GRE_OF;
1033         break;
1034     default:
1035         return -EOPNOTSUPP;
1036     }
1037 
1038     /* Each extraction sequence entry is a word in size, and extracts a
1039      * word-aligned offset from a protocol header.
1040      */
1041     ese_bits = ICE_FLOW_FV_EXTRACT_SZ * BITS_PER_BYTE;
1042 
1043     flds[fld].xtrct.prot_id = prot_id;
1044     flds[fld].xtrct.off = (ice_flds_info[fld].off / ese_bits) *
1045         ICE_FLOW_FV_EXTRACT_SZ;
1046     flds[fld].xtrct.disp = (u8)(ice_flds_info[fld].off % ese_bits);
1047     flds[fld].xtrct.idx = params->es_cnt;
1048     flds[fld].xtrct.mask = ice_flds_info[fld].mask;
1049 
1050     /* Adjust the next field-entry index after accommodating the number of
1051      * entries this field consumes
1052      */
1053     cnt = DIV_ROUND_UP(flds[fld].xtrct.disp + ice_flds_info[fld].size,
1054                ese_bits);
1055 
1056     /* Fill in the extraction sequence entries needed for this field */
1057     off = flds[fld].xtrct.off;
1058     mask = flds[fld].xtrct.mask;
1059     for (i = 0; i < cnt; i++) {
1060         /* Only consume an extraction sequence entry if there is no
1061          * sibling field associated with this field or the sibling entry
1062          * already extracts the word shared with this field.
1063          */
1064         if (sib == ICE_FLOW_FIELD_IDX_MAX ||
1065             flds[sib].xtrct.prot_id == ICE_PROT_ID_INVAL ||
1066             flds[sib].xtrct.off != off) {
1067             u8 idx;
1068 
1069             /* Make sure the number of extraction sequence required
1070              * does not exceed the block's capability
1071              */
1072             if (params->es_cnt >= fv_words)
1073                 return -ENOSPC;
1074 
1075             /* some blocks require a reversed field vector layout */
1076             if (hw->blk[params->blk].es.reverse)
1077                 idx = fv_words - params->es_cnt - 1;
1078             else
1079                 idx = params->es_cnt;
1080 
1081             params->es[idx].prot_id = prot_id;
1082             params->es[idx].off = off;
1083             params->mask[idx] = mask | sib_mask;
1084             params->es_cnt++;
1085         }
1086 
1087         off += ICE_FLOW_FV_EXTRACT_SZ;
1088     }
1089 
1090     return 0;
1091 }
1092 
1093 /**
1094  * ice_flow_xtract_raws - Create extract sequence entries for raw bytes
1095  * @hw: pointer to the HW struct
1096  * @params: information about the flow to be processed
1097  * @seg: index of packet segment whose raw fields are to be extracted
1098  */
1099 static int
1100 ice_flow_xtract_raws(struct ice_hw *hw, struct ice_flow_prof_params *params,
1101              u8 seg)
1102 {
1103     u16 fv_words;
1104     u16 hdrs_sz;
1105     u8 i;
1106 
1107     if (!params->prof->segs[seg].raws_cnt)
1108         return 0;
1109 
1110     if (params->prof->segs[seg].raws_cnt >
1111         ARRAY_SIZE(params->prof->segs[seg].raws))
1112         return -ENOSPC;
1113 
1114     /* Offsets within the segment headers are not supported */
1115     hdrs_sz = ice_flow_calc_seg_sz(params, seg);
1116     if (!hdrs_sz)
1117         return -EINVAL;
1118 
1119     fv_words = hw->blk[params->blk].es.fvw;
1120 
1121     for (i = 0; i < params->prof->segs[seg].raws_cnt; i++) {
1122         struct ice_flow_seg_fld_raw *raw;
1123         u16 off, cnt, j;
1124 
1125         raw = &params->prof->segs[seg].raws[i];
1126 
1127         /* Storing extraction information */
1128         raw->info.xtrct.prot_id = ICE_PROT_MAC_OF_OR_S;
1129         raw->info.xtrct.off = (raw->off / ICE_FLOW_FV_EXTRACT_SZ) *
1130             ICE_FLOW_FV_EXTRACT_SZ;
1131         raw->info.xtrct.disp = (raw->off % ICE_FLOW_FV_EXTRACT_SZ) *
1132             BITS_PER_BYTE;
1133         raw->info.xtrct.idx = params->es_cnt;
1134 
1135         /* Determine the number of field vector entries this raw field
1136          * consumes.
1137          */
1138         cnt = DIV_ROUND_UP(raw->info.xtrct.disp +
1139                    (raw->info.src.last * BITS_PER_BYTE),
1140                    (ICE_FLOW_FV_EXTRACT_SZ * BITS_PER_BYTE));
1141         off = raw->info.xtrct.off;
1142         for (j = 0; j < cnt; j++) {
1143             u16 idx;
1144 
1145             /* Make sure the number of extraction sequence required
1146              * does not exceed the block's capability
1147              */
1148             if (params->es_cnt >= hw->blk[params->blk].es.count ||
1149                 params->es_cnt >= ICE_MAX_FV_WORDS)
1150                 return -ENOSPC;
1151 
1152             /* some blocks require a reversed field vector layout */
1153             if (hw->blk[params->blk].es.reverse)
1154                 idx = fv_words - params->es_cnt - 1;
1155             else
1156                 idx = params->es_cnt;
1157 
1158             params->es[idx].prot_id = raw->info.xtrct.prot_id;
1159             params->es[idx].off = off;
1160             params->es_cnt++;
1161             off += ICE_FLOW_FV_EXTRACT_SZ;
1162         }
1163     }
1164 
1165     return 0;
1166 }
1167 
1168 /**
1169  * ice_flow_create_xtrct_seq - Create an extraction sequence for given segments
1170  * @hw: pointer to the HW struct
1171  * @params: information about the flow to be processed
1172  *
1173  * This function iterates through all matched fields in the given segments, and
1174  * creates an extraction sequence for the fields.
1175  */
1176 static int
1177 ice_flow_create_xtrct_seq(struct ice_hw *hw,
1178               struct ice_flow_prof_params *params)
1179 {
1180     struct ice_flow_prof *prof = params->prof;
1181     int status = 0;
1182     u8 i;
1183 
1184     for (i = 0; i < prof->segs_cnt; i++) {
1185         u64 match = params->prof->segs[i].match;
1186         enum ice_flow_field j;
1187 
1188         for_each_set_bit(j, (unsigned long *)&match,
1189                  ICE_FLOW_FIELD_IDX_MAX) {
1190             status = ice_flow_xtract_fld(hw, params, i, j, match);
1191             if (status)
1192                 return status;
1193             clear_bit(j, (unsigned long *)&match);
1194         }
1195 
1196         /* Process raw matching bytes */
1197         status = ice_flow_xtract_raws(hw, params, i);
1198         if (status)
1199             return status;
1200     }
1201 
1202     return status;
1203 }
1204 
1205 /**
1206  * ice_flow_proc_segs - process all packet segments associated with a profile
1207  * @hw: pointer to the HW struct
1208  * @params: information about the flow to be processed
1209  */
1210 static int
1211 ice_flow_proc_segs(struct ice_hw *hw, struct ice_flow_prof_params *params)
1212 {
1213     int status;
1214 
1215     status = ice_flow_proc_seg_hdrs(params);
1216     if (status)
1217         return status;
1218 
1219     status = ice_flow_create_xtrct_seq(hw, params);
1220     if (status)
1221         return status;
1222 
1223     switch (params->blk) {
1224     case ICE_BLK_FD:
1225     case ICE_BLK_RSS:
1226         status = 0;
1227         break;
1228     default:
1229         return -EOPNOTSUPP;
1230     }
1231 
1232     return status;
1233 }
1234 
1235 #define ICE_FLOW_FIND_PROF_CHK_FLDS 0x00000001
1236 #define ICE_FLOW_FIND_PROF_CHK_VSI  0x00000002
1237 #define ICE_FLOW_FIND_PROF_NOT_CHK_DIR  0x00000004
1238 
1239 /**
1240  * ice_flow_find_prof_conds - Find a profile matching headers and conditions
1241  * @hw: pointer to the HW struct
1242  * @blk: classification stage
1243  * @dir: flow direction
1244  * @segs: array of one or more packet segments that describe the flow
1245  * @segs_cnt: number of packet segments provided
1246  * @vsi_handle: software VSI handle to check VSI (ICE_FLOW_FIND_PROF_CHK_VSI)
1247  * @conds: additional conditions to be checked (ICE_FLOW_FIND_PROF_CHK_*)
1248  */
1249 static struct ice_flow_prof *
1250 ice_flow_find_prof_conds(struct ice_hw *hw, enum ice_block blk,
1251              enum ice_flow_dir dir, struct ice_flow_seg_info *segs,
1252              u8 segs_cnt, u16 vsi_handle, u32 conds)
1253 {
1254     struct ice_flow_prof *p, *prof = NULL;
1255 
1256     mutex_lock(&hw->fl_profs_locks[blk]);
1257     list_for_each_entry(p, &hw->fl_profs[blk], l_entry)
1258         if ((p->dir == dir || conds & ICE_FLOW_FIND_PROF_NOT_CHK_DIR) &&
1259             segs_cnt && segs_cnt == p->segs_cnt) {
1260             u8 i;
1261 
1262             /* Check for profile-VSI association if specified */
1263             if ((conds & ICE_FLOW_FIND_PROF_CHK_VSI) &&
1264                 ice_is_vsi_valid(hw, vsi_handle) &&
1265                 !test_bit(vsi_handle, p->vsis))
1266                 continue;
1267 
1268             /* Protocol headers must be checked. Matched fields are
1269              * checked if specified.
1270              */
1271             for (i = 0; i < segs_cnt; i++)
1272                 if (segs[i].hdrs != p->segs[i].hdrs ||
1273                     ((conds & ICE_FLOW_FIND_PROF_CHK_FLDS) &&
1274                      segs[i].match != p->segs[i].match))
1275                     break;
1276 
1277             /* A match is found if all segments are matched */
1278             if (i == segs_cnt) {
1279                 prof = p;
1280                 break;
1281             }
1282         }
1283     mutex_unlock(&hw->fl_profs_locks[blk]);
1284 
1285     return prof;
1286 }
1287 
1288 /**
1289  * ice_flow_find_prof_id - Look up a profile with given profile ID
1290  * @hw: pointer to the HW struct
1291  * @blk: classification stage
1292  * @prof_id: unique ID to identify this flow profile
1293  */
1294 static struct ice_flow_prof *
1295 ice_flow_find_prof_id(struct ice_hw *hw, enum ice_block blk, u64 prof_id)
1296 {
1297     struct ice_flow_prof *p;
1298 
1299     list_for_each_entry(p, &hw->fl_profs[blk], l_entry)
1300         if (p->id == prof_id)
1301             return p;
1302 
1303     return NULL;
1304 }
1305 
1306 /**
1307  * ice_dealloc_flow_entry - Deallocate flow entry memory
1308  * @hw: pointer to the HW struct
1309  * @entry: flow entry to be removed
1310  */
1311 static void
1312 ice_dealloc_flow_entry(struct ice_hw *hw, struct ice_flow_entry *entry)
1313 {
1314     if (!entry)
1315         return;
1316 
1317     if (entry->entry)
1318         devm_kfree(ice_hw_to_dev(hw), entry->entry);
1319 
1320     devm_kfree(ice_hw_to_dev(hw), entry);
1321 }
1322 
1323 /**
1324  * ice_flow_rem_entry_sync - Remove a flow entry
1325  * @hw: pointer to the HW struct
1326  * @blk: classification stage
1327  * @entry: flow entry to be removed
1328  */
1329 static int
1330 ice_flow_rem_entry_sync(struct ice_hw *hw, enum ice_block __always_unused blk,
1331             struct ice_flow_entry *entry)
1332 {
1333     if (!entry)
1334         return -EINVAL;
1335 
1336     list_del(&entry->l_entry);
1337 
1338     ice_dealloc_flow_entry(hw, entry);
1339 
1340     return 0;
1341 }
1342 
1343 /**
1344  * ice_flow_add_prof_sync - Add a flow profile for packet segments and fields
1345  * @hw: pointer to the HW struct
1346  * @blk: classification stage
1347  * @dir: flow direction
1348  * @prof_id: unique ID to identify this flow profile
1349  * @segs: array of one or more packet segments that describe the flow
1350  * @segs_cnt: number of packet segments provided
1351  * @prof: stores the returned flow profile added
1352  *
1353  * Assumption: the caller has acquired the lock to the profile list
1354  */
1355 static int
1356 ice_flow_add_prof_sync(struct ice_hw *hw, enum ice_block blk,
1357                enum ice_flow_dir dir, u64 prof_id,
1358                struct ice_flow_seg_info *segs, u8 segs_cnt,
1359                struct ice_flow_prof **prof)
1360 {
1361     struct ice_flow_prof_params *params;
1362     int status;
1363     u8 i;
1364 
1365     if (!prof)
1366         return -EINVAL;
1367 
1368     params = kzalloc(sizeof(*params), GFP_KERNEL);
1369     if (!params)
1370         return -ENOMEM;
1371 
1372     params->prof = devm_kzalloc(ice_hw_to_dev(hw), sizeof(*params->prof),
1373                     GFP_KERNEL);
1374     if (!params->prof) {
1375         status = -ENOMEM;
1376         goto free_params;
1377     }
1378 
1379     /* initialize extraction sequence to all invalid (0xff) */
1380     for (i = 0; i < ICE_MAX_FV_WORDS; i++) {
1381         params->es[i].prot_id = ICE_PROT_INVALID;
1382         params->es[i].off = ICE_FV_OFFSET_INVAL;
1383     }
1384 
1385     params->blk = blk;
1386     params->prof->id = prof_id;
1387     params->prof->dir = dir;
1388     params->prof->segs_cnt = segs_cnt;
1389 
1390     /* Make a copy of the segments that need to be persistent in the flow
1391      * profile instance
1392      */
1393     for (i = 0; i < segs_cnt; i++)
1394         memcpy(&params->prof->segs[i], &segs[i], sizeof(*segs));
1395 
1396     status = ice_flow_proc_segs(hw, params);
1397     if (status) {
1398         ice_debug(hw, ICE_DBG_FLOW, "Error processing a flow's packet segments\n");
1399         goto out;
1400     }
1401 
1402     /* Add a HW profile for this flow profile */
1403     status = ice_add_prof(hw, blk, prof_id, (u8 *)params->ptypes,
1404                   params->attr, params->attr_cnt, params->es,
1405                   params->mask);
1406     if (status) {
1407         ice_debug(hw, ICE_DBG_FLOW, "Error adding a HW flow profile\n");
1408         goto out;
1409     }
1410 
1411     INIT_LIST_HEAD(&params->prof->entries);
1412     mutex_init(&params->prof->entries_lock);
1413     *prof = params->prof;
1414 
1415 out:
1416     if (status)
1417         devm_kfree(ice_hw_to_dev(hw), params->prof);
1418 free_params:
1419     kfree(params);
1420 
1421     return status;
1422 }
1423 
1424 /**
1425  * ice_flow_rem_prof_sync - remove a flow profile
1426  * @hw: pointer to the hardware structure
1427  * @blk: classification stage
1428  * @prof: pointer to flow profile to remove
1429  *
1430  * Assumption: the caller has acquired the lock to the profile list
1431  */
1432 static int
1433 ice_flow_rem_prof_sync(struct ice_hw *hw, enum ice_block blk,
1434                struct ice_flow_prof *prof)
1435 {
1436     int status;
1437 
1438     /* Remove all remaining flow entries before removing the flow profile */
1439     if (!list_empty(&prof->entries)) {
1440         struct ice_flow_entry *e, *t;
1441 
1442         mutex_lock(&prof->entries_lock);
1443 
1444         list_for_each_entry_safe(e, t, &prof->entries, l_entry) {
1445             status = ice_flow_rem_entry_sync(hw, blk, e);
1446             if (status)
1447                 break;
1448         }
1449 
1450         mutex_unlock(&prof->entries_lock);
1451     }
1452 
1453     /* Remove all hardware profiles associated with this flow profile */
1454     status = ice_rem_prof(hw, blk, prof->id);
1455     if (!status) {
1456         list_del(&prof->l_entry);
1457         mutex_destroy(&prof->entries_lock);
1458         devm_kfree(ice_hw_to_dev(hw), prof);
1459     }
1460 
1461     return status;
1462 }
1463 
1464 /**
1465  * ice_flow_assoc_prof - associate a VSI with a flow profile
1466  * @hw: pointer to the hardware structure
1467  * @blk: classification stage
1468  * @prof: pointer to flow profile
1469  * @vsi_handle: software VSI handle
1470  *
1471  * Assumption: the caller has acquired the lock to the profile list
1472  * and the software VSI handle has been validated
1473  */
1474 static int
1475 ice_flow_assoc_prof(struct ice_hw *hw, enum ice_block blk,
1476             struct ice_flow_prof *prof, u16 vsi_handle)
1477 {
1478     int status = 0;
1479 
1480     if (!test_bit(vsi_handle, prof->vsis)) {
1481         status = ice_add_prof_id_flow(hw, blk,
1482                           ice_get_hw_vsi_num(hw,
1483                                  vsi_handle),
1484                           prof->id);
1485         if (!status)
1486             set_bit(vsi_handle, prof->vsis);
1487         else
1488             ice_debug(hw, ICE_DBG_FLOW, "HW profile add failed, %d\n",
1489                   status);
1490     }
1491 
1492     return status;
1493 }
1494 
1495 /**
1496  * ice_flow_disassoc_prof - disassociate a VSI from a flow profile
1497  * @hw: pointer to the hardware structure
1498  * @blk: classification stage
1499  * @prof: pointer to flow profile
1500  * @vsi_handle: software VSI handle
1501  *
1502  * Assumption: the caller has acquired the lock to the profile list
1503  * and the software VSI handle has been validated
1504  */
1505 static int
1506 ice_flow_disassoc_prof(struct ice_hw *hw, enum ice_block blk,
1507                struct ice_flow_prof *prof, u16 vsi_handle)
1508 {
1509     int status = 0;
1510 
1511     if (test_bit(vsi_handle, prof->vsis)) {
1512         status = ice_rem_prof_id_flow(hw, blk,
1513                           ice_get_hw_vsi_num(hw,
1514                                  vsi_handle),
1515                           prof->id);
1516         if (!status)
1517             clear_bit(vsi_handle, prof->vsis);
1518         else
1519             ice_debug(hw, ICE_DBG_FLOW, "HW profile remove failed, %d\n",
1520                   status);
1521     }
1522 
1523     return status;
1524 }
1525 
1526 /**
1527  * ice_flow_add_prof - Add a flow profile for packet segments and matched fields
1528  * @hw: pointer to the HW struct
1529  * @blk: classification stage
1530  * @dir: flow direction
1531  * @prof_id: unique ID to identify this flow profile
1532  * @segs: array of one or more packet segments that describe the flow
1533  * @segs_cnt: number of packet segments provided
1534  * @prof: stores the returned flow profile added
1535  */
1536 int
1537 ice_flow_add_prof(struct ice_hw *hw, enum ice_block blk, enum ice_flow_dir dir,
1538           u64 prof_id, struct ice_flow_seg_info *segs, u8 segs_cnt,
1539           struct ice_flow_prof **prof)
1540 {
1541     int status;
1542 
1543     if (segs_cnt > ICE_FLOW_SEG_MAX)
1544         return -ENOSPC;
1545 
1546     if (!segs_cnt)
1547         return -EINVAL;
1548 
1549     if (!segs)
1550         return -EINVAL;
1551 
1552     status = ice_flow_val_hdrs(segs, segs_cnt);
1553     if (status)
1554         return status;
1555 
1556     mutex_lock(&hw->fl_profs_locks[blk]);
1557 
1558     status = ice_flow_add_prof_sync(hw, blk, dir, prof_id, segs, segs_cnt,
1559                     prof);
1560     if (!status)
1561         list_add(&(*prof)->l_entry, &hw->fl_profs[blk]);
1562 
1563     mutex_unlock(&hw->fl_profs_locks[blk]);
1564 
1565     return status;
1566 }
1567 
1568 /**
1569  * ice_flow_rem_prof - Remove a flow profile and all entries associated with it
1570  * @hw: pointer to the HW struct
1571  * @blk: the block for which the flow profile is to be removed
1572  * @prof_id: unique ID of the flow profile to be removed
1573  */
1574 int ice_flow_rem_prof(struct ice_hw *hw, enum ice_block blk, u64 prof_id)
1575 {
1576     struct ice_flow_prof *prof;
1577     int status;
1578 
1579     mutex_lock(&hw->fl_profs_locks[blk]);
1580 
1581     prof = ice_flow_find_prof_id(hw, blk, prof_id);
1582     if (!prof) {
1583         status = -ENOENT;
1584         goto out;
1585     }
1586 
1587     /* prof becomes invalid after the call */
1588     status = ice_flow_rem_prof_sync(hw, blk, prof);
1589 
1590 out:
1591     mutex_unlock(&hw->fl_profs_locks[blk]);
1592 
1593     return status;
1594 }
1595 
1596 /**
1597  * ice_flow_add_entry - Add a flow entry
1598  * @hw: pointer to the HW struct
1599  * @blk: classification stage
1600  * @prof_id: ID of the profile to add a new flow entry to
1601  * @entry_id: unique ID to identify this flow entry
1602  * @vsi_handle: software VSI handle for the flow entry
1603  * @prio: priority of the flow entry
1604  * @data: pointer to a data buffer containing flow entry's match values/masks
1605  * @entry_h: pointer to buffer that receives the new flow entry's handle
1606  */
1607 int
1608 ice_flow_add_entry(struct ice_hw *hw, enum ice_block blk, u64 prof_id,
1609            u64 entry_id, u16 vsi_handle, enum ice_flow_priority prio,
1610            void *data, u64 *entry_h)
1611 {
1612     struct ice_flow_entry *e = NULL;
1613     struct ice_flow_prof *prof;
1614     int status;
1615 
1616     /* No flow entry data is expected for RSS */
1617     if (!entry_h || (!data && blk != ICE_BLK_RSS))
1618         return -EINVAL;
1619 
1620     if (!ice_is_vsi_valid(hw, vsi_handle))
1621         return -EINVAL;
1622 
1623     mutex_lock(&hw->fl_profs_locks[blk]);
1624 
1625     prof = ice_flow_find_prof_id(hw, blk, prof_id);
1626     if (!prof) {
1627         status = -ENOENT;
1628     } else {
1629         /* Allocate memory for the entry being added and associate
1630          * the VSI to the found flow profile
1631          */
1632         e = devm_kzalloc(ice_hw_to_dev(hw), sizeof(*e), GFP_KERNEL);
1633         if (!e)
1634             status = -ENOMEM;
1635         else
1636             status = ice_flow_assoc_prof(hw, blk, prof, vsi_handle);
1637     }
1638 
1639     mutex_unlock(&hw->fl_profs_locks[blk]);
1640     if (status)
1641         goto out;
1642 
1643     e->id = entry_id;
1644     e->vsi_handle = vsi_handle;
1645     e->prof = prof;
1646     e->priority = prio;
1647 
1648     switch (blk) {
1649     case ICE_BLK_FD:
1650     case ICE_BLK_RSS:
1651         break;
1652     default:
1653         status = -EOPNOTSUPP;
1654         goto out;
1655     }
1656 
1657     mutex_lock(&prof->entries_lock);
1658     list_add(&e->l_entry, &prof->entries);
1659     mutex_unlock(&prof->entries_lock);
1660 
1661     *entry_h = ICE_FLOW_ENTRY_HNDL(e);
1662 
1663 out:
1664     if (status && e) {
1665         if (e->entry)
1666             devm_kfree(ice_hw_to_dev(hw), e->entry);
1667         devm_kfree(ice_hw_to_dev(hw), e);
1668     }
1669 
1670     return status;
1671 }
1672 
1673 /**
1674  * ice_flow_rem_entry - Remove a flow entry
1675  * @hw: pointer to the HW struct
1676  * @blk: classification stage
1677  * @entry_h: handle to the flow entry to be removed
1678  */
1679 int ice_flow_rem_entry(struct ice_hw *hw, enum ice_block blk, u64 entry_h)
1680 {
1681     struct ice_flow_entry *entry;
1682     struct ice_flow_prof *prof;
1683     int status = 0;
1684 
1685     if (entry_h == ICE_FLOW_ENTRY_HANDLE_INVAL)
1686         return -EINVAL;
1687 
1688     entry = ICE_FLOW_ENTRY_PTR(entry_h);
1689 
1690     /* Retain the pointer to the flow profile as the entry will be freed */
1691     prof = entry->prof;
1692 
1693     if (prof) {
1694         mutex_lock(&prof->entries_lock);
1695         status = ice_flow_rem_entry_sync(hw, blk, entry);
1696         mutex_unlock(&prof->entries_lock);
1697     }
1698 
1699     return status;
1700 }
1701 
1702 /**
1703  * ice_flow_set_fld_ext - specifies locations of field from entry's input buffer
1704  * @seg: packet segment the field being set belongs to
1705  * @fld: field to be set
1706  * @field_type: type of the field
1707  * @val_loc: if not ICE_FLOW_FLD_OFF_INVAL, location of the value to match from
1708  *           entry's input buffer
1709  * @mask_loc: if not ICE_FLOW_FLD_OFF_INVAL, location of mask value from entry's
1710  *            input buffer
1711  * @last_loc: if not ICE_FLOW_FLD_OFF_INVAL, location of last/upper value from
1712  *            entry's input buffer
1713  *
1714  * This helper function stores information of a field being matched, including
1715  * the type of the field and the locations of the value to match, the mask, and
1716  * the upper-bound value in the start of the input buffer for a flow entry.
1717  * This function should only be used for fixed-size data structures.
1718  *
1719  * This function also opportunistically determines the protocol headers to be
1720  * present based on the fields being set. Some fields cannot be used alone to
1721  * determine the protocol headers present. Sometimes, fields for particular
1722  * protocol headers are not matched. In those cases, the protocol headers
1723  * must be explicitly set.
1724  */
1725 static void
1726 ice_flow_set_fld_ext(struct ice_flow_seg_info *seg, enum ice_flow_field fld,
1727              enum ice_flow_fld_match_type field_type, u16 val_loc,
1728              u16 mask_loc, u16 last_loc)
1729 {
1730     u64 bit = BIT_ULL(fld);
1731 
1732     seg->match |= bit;
1733     if (field_type == ICE_FLOW_FLD_TYPE_RANGE)
1734         seg->range |= bit;
1735 
1736     seg->fields[fld].type = field_type;
1737     seg->fields[fld].src.val = val_loc;
1738     seg->fields[fld].src.mask = mask_loc;
1739     seg->fields[fld].src.last = last_loc;
1740 
1741     ICE_FLOW_SET_HDRS(seg, ice_flds_info[fld].hdr);
1742 }
1743 
1744 /**
1745  * ice_flow_set_fld - specifies locations of field from entry's input buffer
1746  * @seg: packet segment the field being set belongs to
1747  * @fld: field to be set
1748  * @val_loc: if not ICE_FLOW_FLD_OFF_INVAL, location of the value to match from
1749  *           entry's input buffer
1750  * @mask_loc: if not ICE_FLOW_FLD_OFF_INVAL, location of mask value from entry's
1751  *            input buffer
1752  * @last_loc: if not ICE_FLOW_FLD_OFF_INVAL, location of last/upper value from
1753  *            entry's input buffer
1754  * @range: indicate if field being matched is to be in a range
1755  *
1756  * This function specifies the locations, in the form of byte offsets from the
1757  * start of the input buffer for a flow entry, from where the value to match,
1758  * the mask value, and upper value can be extracted. These locations are then
1759  * stored in the flow profile. When adding a flow entry associated with the
1760  * flow profile, these locations will be used to quickly extract the values and
1761  * create the content of a match entry. This function should only be used for
1762  * fixed-size data structures.
1763  */
1764 void
1765 ice_flow_set_fld(struct ice_flow_seg_info *seg, enum ice_flow_field fld,
1766          u16 val_loc, u16 mask_loc, u16 last_loc, bool range)
1767 {
1768     enum ice_flow_fld_match_type t = range ?
1769         ICE_FLOW_FLD_TYPE_RANGE : ICE_FLOW_FLD_TYPE_REG;
1770 
1771     ice_flow_set_fld_ext(seg, fld, t, val_loc, mask_loc, last_loc);
1772 }
1773 
1774 /**
1775  * ice_flow_add_fld_raw - sets locations of a raw field from entry's input buf
1776  * @seg: packet segment the field being set belongs to
1777  * @off: offset of the raw field from the beginning of the segment in bytes
1778  * @len: length of the raw pattern to be matched
1779  * @val_loc: location of the value to match from entry's input buffer
1780  * @mask_loc: location of mask value from entry's input buffer
1781  *
1782  * This function specifies the offset of the raw field to be match from the
1783  * beginning of the specified packet segment, and the locations, in the form of
1784  * byte offsets from the start of the input buffer for a flow entry, from where
1785  * the value to match and the mask value to be extracted. These locations are
1786  * then stored in the flow profile. When adding flow entries to the associated
1787  * flow profile, these locations can be used to quickly extract the values to
1788  * create the content of a match entry. This function should only be used for
1789  * fixed-size data structures.
1790  */
1791 void
1792 ice_flow_add_fld_raw(struct ice_flow_seg_info *seg, u16 off, u8 len,
1793              u16 val_loc, u16 mask_loc)
1794 {
1795     if (seg->raws_cnt < ICE_FLOW_SEG_RAW_FLD_MAX) {
1796         seg->raws[seg->raws_cnt].off = off;
1797         seg->raws[seg->raws_cnt].info.type = ICE_FLOW_FLD_TYPE_SIZE;
1798         seg->raws[seg->raws_cnt].info.src.val = val_loc;
1799         seg->raws[seg->raws_cnt].info.src.mask = mask_loc;
1800         /* The "last" field is used to store the length of the field */
1801         seg->raws[seg->raws_cnt].info.src.last = len;
1802     }
1803 
1804     /* Overflows of "raws" will be handled as an error condition later in
1805      * the flow when this information is processed.
1806      */
1807     seg->raws_cnt++;
1808 }
1809 
1810 /**
1811  * ice_flow_rem_vsi_prof - remove VSI from flow profile
1812  * @hw: pointer to the hardware structure
1813  * @vsi_handle: software VSI handle
1814  * @prof_id: unique ID to identify this flow profile
1815  *
1816  * This function removes the flow entries associated to the input
1817  * VSI handle and disassociate the VSI from the flow profile.
1818  */
1819 int ice_flow_rem_vsi_prof(struct ice_hw *hw, u16 vsi_handle, u64 prof_id)
1820 {
1821     struct ice_flow_prof *prof;
1822     int status = 0;
1823 
1824     if (!ice_is_vsi_valid(hw, vsi_handle))
1825         return -EINVAL;
1826 
1827     /* find flow profile pointer with input package block and profile ID */
1828     prof = ice_flow_find_prof_id(hw, ICE_BLK_FD, prof_id);
1829     if (!prof) {
1830         ice_debug(hw, ICE_DBG_PKG, "Cannot find flow profile id=%llu\n",
1831               prof_id);
1832         return -ENOENT;
1833     }
1834 
1835     /* Remove all remaining flow entries before removing the flow profile */
1836     if (!list_empty(&prof->entries)) {
1837         struct ice_flow_entry *e, *t;
1838 
1839         mutex_lock(&prof->entries_lock);
1840         list_for_each_entry_safe(e, t, &prof->entries, l_entry) {
1841             if (e->vsi_handle != vsi_handle)
1842                 continue;
1843 
1844             status = ice_flow_rem_entry_sync(hw, ICE_BLK_FD, e);
1845             if (status)
1846                 break;
1847         }
1848         mutex_unlock(&prof->entries_lock);
1849     }
1850     if (status)
1851         return status;
1852 
1853     /* disassociate the flow profile from sw VSI handle */
1854     status = ice_flow_disassoc_prof(hw, ICE_BLK_FD, prof, vsi_handle);
1855     if (status)
1856         ice_debug(hw, ICE_DBG_PKG, "ice_flow_disassoc_prof() failed with status=%d\n",
1857               status);
1858     return status;
1859 }
1860 
1861 #define ICE_FLOW_RSS_SEG_HDR_L2_MASKS \
1862     (ICE_FLOW_SEG_HDR_ETH | ICE_FLOW_SEG_HDR_VLAN)
1863 
1864 #define ICE_FLOW_RSS_SEG_HDR_L3_MASKS \
1865     (ICE_FLOW_SEG_HDR_IPV4 | ICE_FLOW_SEG_HDR_IPV6)
1866 
1867 #define ICE_FLOW_RSS_SEG_HDR_L4_MASKS \
1868     (ICE_FLOW_SEG_HDR_TCP | ICE_FLOW_SEG_HDR_UDP | ICE_FLOW_SEG_HDR_SCTP)
1869 
1870 #define ICE_FLOW_RSS_SEG_HDR_VAL_MASKS \
1871     (ICE_FLOW_RSS_SEG_HDR_L2_MASKS | \
1872      ICE_FLOW_RSS_SEG_HDR_L3_MASKS | \
1873      ICE_FLOW_RSS_SEG_HDR_L4_MASKS)
1874 
1875 /**
1876  * ice_flow_set_rss_seg_info - setup packet segments for RSS
1877  * @segs: pointer to the flow field segment(s)
1878  * @hash_fields: fields to be hashed on for the segment(s)
1879  * @flow_hdr: protocol header fields within a packet segment
1880  *
1881  * Helper function to extract fields from hash bitmap and use flow
1882  * header value to set flow field segment for further use in flow
1883  * profile entry or removal.
1884  */
1885 static int
1886 ice_flow_set_rss_seg_info(struct ice_flow_seg_info *segs, u64 hash_fields,
1887               u32 flow_hdr)
1888 {
1889     u64 val;
1890     u8 i;
1891 
1892     for_each_set_bit(i, (unsigned long *)&hash_fields,
1893              ICE_FLOW_FIELD_IDX_MAX)
1894         ice_flow_set_fld(segs, (enum ice_flow_field)i,
1895                  ICE_FLOW_FLD_OFF_INVAL, ICE_FLOW_FLD_OFF_INVAL,
1896                  ICE_FLOW_FLD_OFF_INVAL, false);
1897 
1898     ICE_FLOW_SET_HDRS(segs, flow_hdr);
1899 
1900     if (segs->hdrs & ~ICE_FLOW_RSS_SEG_HDR_VAL_MASKS &
1901         ~ICE_FLOW_RSS_HDRS_INNER_MASK & ~ICE_FLOW_SEG_HDR_IPV_OTHER)
1902         return -EINVAL;
1903 
1904     val = (u64)(segs->hdrs & ICE_FLOW_RSS_SEG_HDR_L3_MASKS);
1905     if (val && !is_power_of_2(val))
1906         return -EIO;
1907 
1908     val = (u64)(segs->hdrs & ICE_FLOW_RSS_SEG_HDR_L4_MASKS);
1909     if (val && !is_power_of_2(val))
1910         return -EIO;
1911 
1912     return 0;
1913 }
1914 
1915 /**
1916  * ice_rem_vsi_rss_list - remove VSI from RSS list
1917  * @hw: pointer to the hardware structure
1918  * @vsi_handle: software VSI handle
1919  *
1920  * Remove the VSI from all RSS configurations in the list.
1921  */
1922 void ice_rem_vsi_rss_list(struct ice_hw *hw, u16 vsi_handle)
1923 {
1924     struct ice_rss_cfg *r, *tmp;
1925 
1926     if (list_empty(&hw->rss_list_head))
1927         return;
1928 
1929     mutex_lock(&hw->rss_locks);
1930     list_for_each_entry_safe(r, tmp, &hw->rss_list_head, l_entry)
1931         if (test_and_clear_bit(vsi_handle, r->vsis))
1932             if (bitmap_empty(r->vsis, ICE_MAX_VSI)) {
1933                 list_del(&r->l_entry);
1934                 devm_kfree(ice_hw_to_dev(hw), r);
1935             }
1936     mutex_unlock(&hw->rss_locks);
1937 }
1938 
1939 /**
1940  * ice_rem_vsi_rss_cfg - remove RSS configurations associated with VSI
1941  * @hw: pointer to the hardware structure
1942  * @vsi_handle: software VSI handle
1943  *
1944  * This function will iterate through all flow profiles and disassociate
1945  * the VSI from that profile. If the flow profile has no VSIs it will
1946  * be removed.
1947  */
1948 int ice_rem_vsi_rss_cfg(struct ice_hw *hw, u16 vsi_handle)
1949 {
1950     const enum ice_block blk = ICE_BLK_RSS;
1951     struct ice_flow_prof *p, *t;
1952     int status = 0;
1953 
1954     if (!ice_is_vsi_valid(hw, vsi_handle))
1955         return -EINVAL;
1956 
1957     if (list_empty(&hw->fl_profs[blk]))
1958         return 0;
1959 
1960     mutex_lock(&hw->rss_locks);
1961     list_for_each_entry_safe(p, t, &hw->fl_profs[blk], l_entry)
1962         if (test_bit(vsi_handle, p->vsis)) {
1963             status = ice_flow_disassoc_prof(hw, blk, p, vsi_handle);
1964             if (status)
1965                 break;
1966 
1967             if (bitmap_empty(p->vsis, ICE_MAX_VSI)) {
1968                 status = ice_flow_rem_prof(hw, blk, p->id);
1969                 if (status)
1970                     break;
1971             }
1972         }
1973     mutex_unlock(&hw->rss_locks);
1974 
1975     return status;
1976 }
1977 
1978 /**
1979  * ice_rem_rss_list - remove RSS configuration from list
1980  * @hw: pointer to the hardware structure
1981  * @vsi_handle: software VSI handle
1982  * @prof: pointer to flow profile
1983  *
1984  * Assumption: lock has already been acquired for RSS list
1985  */
1986 static void
1987 ice_rem_rss_list(struct ice_hw *hw, u16 vsi_handle, struct ice_flow_prof *prof)
1988 {
1989     struct ice_rss_cfg *r, *tmp;
1990 
1991     /* Search for RSS hash fields associated to the VSI that match the
1992      * hash configurations associated to the flow profile. If found
1993      * remove from the RSS entry list of the VSI context and delete entry.
1994      */
1995     list_for_each_entry_safe(r, tmp, &hw->rss_list_head, l_entry)
1996         if (r->hashed_flds == prof->segs[prof->segs_cnt - 1].match &&
1997             r->packet_hdr == prof->segs[prof->segs_cnt - 1].hdrs) {
1998             clear_bit(vsi_handle, r->vsis);
1999             if (bitmap_empty(r->vsis, ICE_MAX_VSI)) {
2000                 list_del(&r->l_entry);
2001                 devm_kfree(ice_hw_to_dev(hw), r);
2002             }
2003             return;
2004         }
2005 }
2006 
2007 /**
2008  * ice_add_rss_list - add RSS configuration to list
2009  * @hw: pointer to the hardware structure
2010  * @vsi_handle: software VSI handle
2011  * @prof: pointer to flow profile
2012  *
2013  * Assumption: lock has already been acquired for RSS list
2014  */
2015 static int
2016 ice_add_rss_list(struct ice_hw *hw, u16 vsi_handle, struct ice_flow_prof *prof)
2017 {
2018     struct ice_rss_cfg *r, *rss_cfg;
2019 
2020     list_for_each_entry(r, &hw->rss_list_head, l_entry)
2021         if (r->hashed_flds == prof->segs[prof->segs_cnt - 1].match &&
2022             r->packet_hdr == prof->segs[prof->segs_cnt - 1].hdrs) {
2023             set_bit(vsi_handle, r->vsis);
2024             return 0;
2025         }
2026 
2027     rss_cfg = devm_kzalloc(ice_hw_to_dev(hw), sizeof(*rss_cfg),
2028                    GFP_KERNEL);
2029     if (!rss_cfg)
2030         return -ENOMEM;
2031 
2032     rss_cfg->hashed_flds = prof->segs[prof->segs_cnt - 1].match;
2033     rss_cfg->packet_hdr = prof->segs[prof->segs_cnt - 1].hdrs;
2034     set_bit(vsi_handle, rss_cfg->vsis);
2035 
2036     list_add_tail(&rss_cfg->l_entry, &hw->rss_list_head);
2037 
2038     return 0;
2039 }
2040 
2041 #define ICE_FLOW_PROF_HASH_S    0
2042 #define ICE_FLOW_PROF_HASH_M    (0xFFFFFFFFULL << ICE_FLOW_PROF_HASH_S)
2043 #define ICE_FLOW_PROF_HDR_S 32
2044 #define ICE_FLOW_PROF_HDR_M (0x3FFFFFFFULL << ICE_FLOW_PROF_HDR_S)
2045 #define ICE_FLOW_PROF_ENCAP_S   63
2046 #define ICE_FLOW_PROF_ENCAP_M   (BIT_ULL(ICE_FLOW_PROF_ENCAP_S))
2047 
2048 #define ICE_RSS_OUTER_HEADERS   1
2049 #define ICE_RSS_INNER_HEADERS   2
2050 
2051 /* Flow profile ID format:
2052  * [0:31] - Packet match fields
2053  * [32:62] - Protocol header
2054  * [63] - Encapsulation flag, 0 if non-tunneled, 1 if tunneled
2055  */
2056 #define ICE_FLOW_GEN_PROFID(hash, hdr, segs_cnt) \
2057     ((u64)(((u64)(hash) & ICE_FLOW_PROF_HASH_M) | \
2058            (((u64)(hdr) << ICE_FLOW_PROF_HDR_S) & ICE_FLOW_PROF_HDR_M) | \
2059            ((u8)((segs_cnt) - 1) ? ICE_FLOW_PROF_ENCAP_M : 0)))
2060 
2061 /**
2062  * ice_add_rss_cfg_sync - add an RSS configuration
2063  * @hw: pointer to the hardware structure
2064  * @vsi_handle: software VSI handle
2065  * @hashed_flds: hash bit fields (ICE_FLOW_HASH_*) to configure
2066  * @addl_hdrs: protocol header fields
2067  * @segs_cnt: packet segment count
2068  *
2069  * Assumption: lock has already been acquired for RSS list
2070  */
2071 static int
2072 ice_add_rss_cfg_sync(struct ice_hw *hw, u16 vsi_handle, u64 hashed_flds,
2073              u32 addl_hdrs, u8 segs_cnt)
2074 {
2075     const enum ice_block blk = ICE_BLK_RSS;
2076     struct ice_flow_prof *prof = NULL;
2077     struct ice_flow_seg_info *segs;
2078     int status;
2079 
2080     if (!segs_cnt || segs_cnt > ICE_FLOW_SEG_MAX)
2081         return -EINVAL;
2082 
2083     segs = kcalloc(segs_cnt, sizeof(*segs), GFP_KERNEL);
2084     if (!segs)
2085         return -ENOMEM;
2086 
2087     /* Construct the packet segment info from the hashed fields */
2088     status = ice_flow_set_rss_seg_info(&segs[segs_cnt - 1], hashed_flds,
2089                        addl_hdrs);
2090     if (status)
2091         goto exit;
2092 
2093     /* Search for a flow profile that has matching headers, hash fields
2094      * and has the input VSI associated to it. If found, no further
2095      * operations required and exit.
2096      */
2097     prof = ice_flow_find_prof_conds(hw, blk, ICE_FLOW_RX, segs, segs_cnt,
2098                     vsi_handle,
2099                     ICE_FLOW_FIND_PROF_CHK_FLDS |
2100                     ICE_FLOW_FIND_PROF_CHK_VSI);
2101     if (prof)
2102         goto exit;
2103 
2104     /* Check if a flow profile exists with the same protocol headers and
2105      * associated with the input VSI. If so disassociate the VSI from
2106      * this profile. The VSI will be added to a new profile created with
2107      * the protocol header and new hash field configuration.
2108      */
2109     prof = ice_flow_find_prof_conds(hw, blk, ICE_FLOW_RX, segs, segs_cnt,
2110                     vsi_handle, ICE_FLOW_FIND_PROF_CHK_VSI);
2111     if (prof) {
2112         status = ice_flow_disassoc_prof(hw, blk, prof, vsi_handle);
2113         if (!status)
2114             ice_rem_rss_list(hw, vsi_handle, prof);
2115         else
2116             goto exit;
2117 
2118         /* Remove profile if it has no VSIs associated */
2119         if (bitmap_empty(prof->vsis, ICE_MAX_VSI)) {
2120             status = ice_flow_rem_prof(hw, blk, prof->id);
2121             if (status)
2122                 goto exit;
2123         }
2124     }
2125 
2126     /* Search for a profile that has same match fields only. If this
2127      * exists then associate the VSI to this profile.
2128      */
2129     prof = ice_flow_find_prof_conds(hw, blk, ICE_FLOW_RX, segs, segs_cnt,
2130                     vsi_handle,
2131                     ICE_FLOW_FIND_PROF_CHK_FLDS);
2132     if (prof) {
2133         status = ice_flow_assoc_prof(hw, blk, prof, vsi_handle);
2134         if (!status)
2135             status = ice_add_rss_list(hw, vsi_handle, prof);
2136         goto exit;
2137     }
2138 
2139     /* Create a new flow profile with generated profile and packet
2140      * segment information.
2141      */
2142     status = ice_flow_add_prof(hw, blk, ICE_FLOW_RX,
2143                    ICE_FLOW_GEN_PROFID(hashed_flds,
2144                                segs[segs_cnt - 1].hdrs,
2145                                segs_cnt),
2146                    segs, segs_cnt, &prof);
2147     if (status)
2148         goto exit;
2149 
2150     status = ice_flow_assoc_prof(hw, blk, prof, vsi_handle);
2151     /* If association to a new flow profile failed then this profile can
2152      * be removed.
2153      */
2154     if (status) {
2155         ice_flow_rem_prof(hw, blk, prof->id);
2156         goto exit;
2157     }
2158 
2159     status = ice_add_rss_list(hw, vsi_handle, prof);
2160 
2161 exit:
2162     kfree(segs);
2163     return status;
2164 }
2165 
2166 /**
2167  * ice_add_rss_cfg - add an RSS configuration with specified hashed fields
2168  * @hw: pointer to the hardware structure
2169  * @vsi_handle: software VSI handle
2170  * @hashed_flds: hash bit fields (ICE_FLOW_HASH_*) to configure
2171  * @addl_hdrs: protocol header fields
2172  *
2173  * This function will generate a flow profile based on fields associated with
2174  * the input fields to hash on, the flow type and use the VSI number to add
2175  * a flow entry to the profile.
2176  */
2177 int
2178 ice_add_rss_cfg(struct ice_hw *hw, u16 vsi_handle, u64 hashed_flds,
2179         u32 addl_hdrs)
2180 {
2181     int status;
2182 
2183     if (hashed_flds == ICE_HASH_INVALID ||
2184         !ice_is_vsi_valid(hw, vsi_handle))
2185         return -EINVAL;
2186 
2187     mutex_lock(&hw->rss_locks);
2188     status = ice_add_rss_cfg_sync(hw, vsi_handle, hashed_flds, addl_hdrs,
2189                       ICE_RSS_OUTER_HEADERS);
2190     if (!status)
2191         status = ice_add_rss_cfg_sync(hw, vsi_handle, hashed_flds,
2192                           addl_hdrs, ICE_RSS_INNER_HEADERS);
2193     mutex_unlock(&hw->rss_locks);
2194 
2195     return status;
2196 }
2197 
2198 /**
2199  * ice_rem_rss_cfg_sync - remove an existing RSS configuration
2200  * @hw: pointer to the hardware structure
2201  * @vsi_handle: software VSI handle
2202  * @hashed_flds: Packet hash types (ICE_FLOW_HASH_*) to remove
2203  * @addl_hdrs: Protocol header fields within a packet segment
2204  * @segs_cnt: packet segment count
2205  *
2206  * Assumption: lock has already been acquired for RSS list
2207  */
2208 static int
2209 ice_rem_rss_cfg_sync(struct ice_hw *hw, u16 vsi_handle, u64 hashed_flds,
2210              u32 addl_hdrs, u8 segs_cnt)
2211 {
2212     const enum ice_block blk = ICE_BLK_RSS;
2213     struct ice_flow_seg_info *segs;
2214     struct ice_flow_prof *prof;
2215     int status;
2216 
2217     segs = kcalloc(segs_cnt, sizeof(*segs), GFP_KERNEL);
2218     if (!segs)
2219         return -ENOMEM;
2220 
2221     /* Construct the packet segment info from the hashed fields */
2222     status = ice_flow_set_rss_seg_info(&segs[segs_cnt - 1], hashed_flds,
2223                        addl_hdrs);
2224     if (status)
2225         goto out;
2226 
2227     prof = ice_flow_find_prof_conds(hw, blk, ICE_FLOW_RX, segs, segs_cnt,
2228                     vsi_handle,
2229                     ICE_FLOW_FIND_PROF_CHK_FLDS);
2230     if (!prof) {
2231         status = -ENOENT;
2232         goto out;
2233     }
2234 
2235     status = ice_flow_disassoc_prof(hw, blk, prof, vsi_handle);
2236     if (status)
2237         goto out;
2238 
2239     /* Remove RSS configuration from VSI context before deleting
2240      * the flow profile.
2241      */
2242     ice_rem_rss_list(hw, vsi_handle, prof);
2243 
2244     if (bitmap_empty(prof->vsis, ICE_MAX_VSI))
2245         status = ice_flow_rem_prof(hw, blk, prof->id);
2246 
2247 out:
2248     kfree(segs);
2249     return status;
2250 }
2251 
2252 /**
2253  * ice_rem_rss_cfg - remove an existing RSS config with matching hashed fields
2254  * @hw: pointer to the hardware structure
2255  * @vsi_handle: software VSI handle
2256  * @hashed_flds: Packet hash types (ICE_FLOW_HASH_*) to remove
2257  * @addl_hdrs: Protocol header fields within a packet segment
2258  *
2259  * This function will lookup the flow profile based on the input
2260  * hash field bitmap, iterate through the profile entry list of
2261  * that profile and find entry associated with input VSI to be
2262  * removed. Calls are made to underlying flow s which will APIs
2263  * turn build or update buffers for RSS XLT1 section.
2264  */
2265 int __maybe_unused
2266 ice_rem_rss_cfg(struct ice_hw *hw, u16 vsi_handle, u64 hashed_flds,
2267         u32 addl_hdrs)
2268 {
2269     int status;
2270 
2271     if (hashed_flds == ICE_HASH_INVALID ||
2272         !ice_is_vsi_valid(hw, vsi_handle))
2273         return -EINVAL;
2274 
2275     mutex_lock(&hw->rss_locks);
2276     status = ice_rem_rss_cfg_sync(hw, vsi_handle, hashed_flds, addl_hdrs,
2277                       ICE_RSS_OUTER_HEADERS);
2278     if (!status)
2279         status = ice_rem_rss_cfg_sync(hw, vsi_handle, hashed_flds,
2280                           addl_hdrs, ICE_RSS_INNER_HEADERS);
2281     mutex_unlock(&hw->rss_locks);
2282 
2283     return status;
2284 }
2285 
2286 /* Mapping of AVF hash bit fields to an L3-L4 hash combination.
2287  * As the ice_flow_avf_hdr_field represent individual bit shifts in a hash,
2288  * convert its values to their appropriate flow L3, L4 values.
2289  */
2290 #define ICE_FLOW_AVF_RSS_IPV4_MASKS \
2291     (BIT_ULL(ICE_AVF_FLOW_FIELD_IPV4_OTHER) | \
2292      BIT_ULL(ICE_AVF_FLOW_FIELD_FRAG_IPV4))
2293 #define ICE_FLOW_AVF_RSS_TCP_IPV4_MASKS \
2294     (BIT_ULL(ICE_AVF_FLOW_FIELD_IPV4_TCP_SYN_NO_ACK) | \
2295      BIT_ULL(ICE_AVF_FLOW_FIELD_IPV4_TCP))
2296 #define ICE_FLOW_AVF_RSS_UDP_IPV4_MASKS \
2297     (BIT_ULL(ICE_AVF_FLOW_FIELD_UNICAST_IPV4_UDP) | \
2298      BIT_ULL(ICE_AVF_FLOW_FIELD_MULTICAST_IPV4_UDP) | \
2299      BIT_ULL(ICE_AVF_FLOW_FIELD_IPV4_UDP))
2300 #define ICE_FLOW_AVF_RSS_ALL_IPV4_MASKS \
2301     (ICE_FLOW_AVF_RSS_TCP_IPV4_MASKS | ICE_FLOW_AVF_RSS_UDP_IPV4_MASKS | \
2302      ICE_FLOW_AVF_RSS_IPV4_MASKS | BIT_ULL(ICE_AVF_FLOW_FIELD_IPV4_SCTP))
2303 
2304 #define ICE_FLOW_AVF_RSS_IPV6_MASKS \
2305     (BIT_ULL(ICE_AVF_FLOW_FIELD_IPV6_OTHER) | \
2306      BIT_ULL(ICE_AVF_FLOW_FIELD_FRAG_IPV6))
2307 #define ICE_FLOW_AVF_RSS_UDP_IPV6_MASKS \
2308     (BIT_ULL(ICE_AVF_FLOW_FIELD_UNICAST_IPV6_UDP) | \
2309      BIT_ULL(ICE_AVF_FLOW_FIELD_MULTICAST_IPV6_UDP) | \
2310      BIT_ULL(ICE_AVF_FLOW_FIELD_IPV6_UDP))
2311 #define ICE_FLOW_AVF_RSS_TCP_IPV6_MASKS \
2312     (BIT_ULL(ICE_AVF_FLOW_FIELD_IPV6_TCP_SYN_NO_ACK) | \
2313      BIT_ULL(ICE_AVF_FLOW_FIELD_IPV6_TCP))
2314 #define ICE_FLOW_AVF_RSS_ALL_IPV6_MASKS \
2315     (ICE_FLOW_AVF_RSS_TCP_IPV6_MASKS | ICE_FLOW_AVF_RSS_UDP_IPV6_MASKS | \
2316      ICE_FLOW_AVF_RSS_IPV6_MASKS | BIT_ULL(ICE_AVF_FLOW_FIELD_IPV6_SCTP))
2317 
2318 /**
2319  * ice_add_avf_rss_cfg - add an RSS configuration for AVF driver
2320  * @hw: pointer to the hardware structure
2321  * @vsi_handle: software VSI handle
2322  * @avf_hash: hash bit fields (ICE_AVF_FLOW_FIELD_*) to configure
2323  *
2324  * This function will take the hash bitmap provided by the AVF driver via a
2325  * message, convert it to ICE-compatible values, and configure RSS flow
2326  * profiles.
2327  */
2328 int ice_add_avf_rss_cfg(struct ice_hw *hw, u16 vsi_handle, u64 avf_hash)
2329 {
2330     int status = 0;
2331     u64 hash_flds;
2332 
2333     if (avf_hash == ICE_AVF_FLOW_FIELD_INVALID ||
2334         !ice_is_vsi_valid(hw, vsi_handle))
2335         return -EINVAL;
2336 
2337     /* Make sure no unsupported bits are specified */
2338     if (avf_hash & ~(ICE_FLOW_AVF_RSS_ALL_IPV4_MASKS |
2339              ICE_FLOW_AVF_RSS_ALL_IPV6_MASKS))
2340         return -EIO;
2341 
2342     hash_flds = avf_hash;
2343 
2344     /* Always create an L3 RSS configuration for any L4 RSS configuration */
2345     if (hash_flds & ICE_FLOW_AVF_RSS_ALL_IPV4_MASKS)
2346         hash_flds |= ICE_FLOW_AVF_RSS_IPV4_MASKS;
2347 
2348     if (hash_flds & ICE_FLOW_AVF_RSS_ALL_IPV6_MASKS)
2349         hash_flds |= ICE_FLOW_AVF_RSS_IPV6_MASKS;
2350 
2351     /* Create the corresponding RSS configuration for each valid hash bit */
2352     while (hash_flds) {
2353         u64 rss_hash = ICE_HASH_INVALID;
2354 
2355         if (hash_flds & ICE_FLOW_AVF_RSS_ALL_IPV4_MASKS) {
2356             if (hash_flds & ICE_FLOW_AVF_RSS_IPV4_MASKS) {
2357                 rss_hash = ICE_FLOW_HASH_IPV4;
2358                 hash_flds &= ~ICE_FLOW_AVF_RSS_IPV4_MASKS;
2359             } else if (hash_flds &
2360                    ICE_FLOW_AVF_RSS_TCP_IPV4_MASKS) {
2361                 rss_hash = ICE_FLOW_HASH_IPV4 |
2362                     ICE_FLOW_HASH_TCP_PORT;
2363                 hash_flds &= ~ICE_FLOW_AVF_RSS_TCP_IPV4_MASKS;
2364             } else if (hash_flds &
2365                    ICE_FLOW_AVF_RSS_UDP_IPV4_MASKS) {
2366                 rss_hash = ICE_FLOW_HASH_IPV4 |
2367                     ICE_FLOW_HASH_UDP_PORT;
2368                 hash_flds &= ~ICE_FLOW_AVF_RSS_UDP_IPV4_MASKS;
2369             } else if (hash_flds &
2370                    BIT_ULL(ICE_AVF_FLOW_FIELD_IPV4_SCTP)) {
2371                 rss_hash = ICE_FLOW_HASH_IPV4 |
2372                     ICE_FLOW_HASH_SCTP_PORT;
2373                 hash_flds &=
2374                     ~BIT_ULL(ICE_AVF_FLOW_FIELD_IPV4_SCTP);
2375             }
2376         } else if (hash_flds & ICE_FLOW_AVF_RSS_ALL_IPV6_MASKS) {
2377             if (hash_flds & ICE_FLOW_AVF_RSS_IPV6_MASKS) {
2378                 rss_hash = ICE_FLOW_HASH_IPV6;
2379                 hash_flds &= ~ICE_FLOW_AVF_RSS_IPV6_MASKS;
2380             } else if (hash_flds &
2381                    ICE_FLOW_AVF_RSS_TCP_IPV6_MASKS) {
2382                 rss_hash = ICE_FLOW_HASH_IPV6 |
2383                     ICE_FLOW_HASH_TCP_PORT;
2384                 hash_flds &= ~ICE_FLOW_AVF_RSS_TCP_IPV6_MASKS;
2385             } else if (hash_flds &
2386                    ICE_FLOW_AVF_RSS_UDP_IPV6_MASKS) {
2387                 rss_hash = ICE_FLOW_HASH_IPV6 |
2388                     ICE_FLOW_HASH_UDP_PORT;
2389                 hash_flds &= ~ICE_FLOW_AVF_RSS_UDP_IPV6_MASKS;
2390             } else if (hash_flds &
2391                    BIT_ULL(ICE_AVF_FLOW_FIELD_IPV6_SCTP)) {
2392                 rss_hash = ICE_FLOW_HASH_IPV6 |
2393                     ICE_FLOW_HASH_SCTP_PORT;
2394                 hash_flds &=
2395                     ~BIT_ULL(ICE_AVF_FLOW_FIELD_IPV6_SCTP);
2396             }
2397         }
2398 
2399         if (rss_hash == ICE_HASH_INVALID)
2400             return -EIO;
2401 
2402         status = ice_add_rss_cfg(hw, vsi_handle, rss_hash,
2403                      ICE_FLOW_SEG_HDR_NONE);
2404         if (status)
2405             break;
2406     }
2407 
2408     return status;
2409 }
2410 
2411 /**
2412  * ice_replay_rss_cfg - replay RSS configurations associated with VSI
2413  * @hw: pointer to the hardware structure
2414  * @vsi_handle: software VSI handle
2415  */
2416 int ice_replay_rss_cfg(struct ice_hw *hw, u16 vsi_handle)
2417 {
2418     struct ice_rss_cfg *r;
2419     int status = 0;
2420 
2421     if (!ice_is_vsi_valid(hw, vsi_handle))
2422         return -EINVAL;
2423 
2424     mutex_lock(&hw->rss_locks);
2425     list_for_each_entry(r, &hw->rss_list_head, l_entry) {
2426         if (test_bit(vsi_handle, r->vsis)) {
2427             status = ice_add_rss_cfg_sync(hw, vsi_handle,
2428                               r->hashed_flds,
2429                               r->packet_hdr,
2430                               ICE_RSS_OUTER_HEADERS);
2431             if (status)
2432                 break;
2433             status = ice_add_rss_cfg_sync(hw, vsi_handle,
2434                               r->hashed_flds,
2435                               r->packet_hdr,
2436                               ICE_RSS_INNER_HEADERS);
2437             if (status)
2438                 break;
2439         }
2440     }
2441     mutex_unlock(&hw->rss_locks);
2442 
2443     return status;
2444 }
2445 
2446 /**
2447  * ice_get_rss_cfg - returns hashed fields for the given header types
2448  * @hw: pointer to the hardware structure
2449  * @vsi_handle: software VSI handle
2450  * @hdrs: protocol header type
2451  *
2452  * This function will return the match fields of the first instance of flow
2453  * profile having the given header types and containing input VSI
2454  */
2455 u64 ice_get_rss_cfg(struct ice_hw *hw, u16 vsi_handle, u32 hdrs)
2456 {
2457     u64 rss_hash = ICE_HASH_INVALID;
2458     struct ice_rss_cfg *r;
2459 
2460     /* verify if the protocol header is non zero and VSI is valid */
2461     if (hdrs == ICE_FLOW_SEG_HDR_NONE || !ice_is_vsi_valid(hw, vsi_handle))
2462         return ICE_HASH_INVALID;
2463 
2464     mutex_lock(&hw->rss_locks);
2465     list_for_each_entry(r, &hw->rss_list_head, l_entry)
2466         if (test_bit(vsi_handle, r->vsis) &&
2467             r->packet_hdr == hdrs) {
2468             rss_hash = r->hashed_flds;
2469             break;
2470         }
2471     mutex_unlock(&hw->rss_locks);
2472 
2473     return rss_hash;
2474 }