162306a36Sopenharmony_ci// SPDX-License-Identifier: GPL-2.0 262306a36Sopenharmony_ci/* Copyright (c) 2019, Intel Corporation. */ 362306a36Sopenharmony_ci 462306a36Sopenharmony_ci#include "ice_common.h" 562306a36Sopenharmony_ci#include "ice_flow.h" 662306a36Sopenharmony_ci#include <net/gre.h> 762306a36Sopenharmony_ci 862306a36Sopenharmony_ci/* Describe properties of a protocol header field */ 962306a36Sopenharmony_cistruct ice_flow_field_info { 1062306a36Sopenharmony_ci enum ice_flow_seg_hdr hdr; 1162306a36Sopenharmony_ci s16 off; /* Offset from start of a protocol header, in bits */ 1262306a36Sopenharmony_ci u16 size; /* Size of fields in bits */ 1362306a36Sopenharmony_ci u16 mask; /* 16-bit mask for field */ 1462306a36Sopenharmony_ci}; 1562306a36Sopenharmony_ci 1662306a36Sopenharmony_ci#define ICE_FLOW_FLD_INFO(_hdr, _offset_bytes, _size_bytes) { \ 1762306a36Sopenharmony_ci .hdr = _hdr, \ 1862306a36Sopenharmony_ci .off = (_offset_bytes) * BITS_PER_BYTE, \ 1962306a36Sopenharmony_ci .size = (_size_bytes) * BITS_PER_BYTE, \ 2062306a36Sopenharmony_ci .mask = 0, \ 2162306a36Sopenharmony_ci} 2262306a36Sopenharmony_ci 2362306a36Sopenharmony_ci#define ICE_FLOW_FLD_INFO_MSK(_hdr, _offset_bytes, _size_bytes, _mask) { \ 2462306a36Sopenharmony_ci .hdr = _hdr, \ 2562306a36Sopenharmony_ci .off = (_offset_bytes) * BITS_PER_BYTE, \ 2662306a36Sopenharmony_ci .size = (_size_bytes) * BITS_PER_BYTE, \ 2762306a36Sopenharmony_ci .mask = _mask, \ 2862306a36Sopenharmony_ci} 2962306a36Sopenharmony_ci 3062306a36Sopenharmony_ci/* Table containing properties of supported protocol header fields */ 3162306a36Sopenharmony_cistatic const 3262306a36Sopenharmony_cistruct ice_flow_field_info ice_flds_info[ICE_FLOW_FIELD_IDX_MAX] = { 3362306a36Sopenharmony_ci /* Ether */ 3462306a36Sopenharmony_ci /* ICE_FLOW_FIELD_IDX_ETH_DA */ 3562306a36Sopenharmony_ci ICE_FLOW_FLD_INFO(ICE_FLOW_SEG_HDR_ETH, 0, ETH_ALEN), 3662306a36Sopenharmony_ci /* ICE_FLOW_FIELD_IDX_ETH_SA */ 3762306a36Sopenharmony_ci ICE_FLOW_FLD_INFO(ICE_FLOW_SEG_HDR_ETH, ETH_ALEN, ETH_ALEN), 3862306a36Sopenharmony_ci /* ICE_FLOW_FIELD_IDX_S_VLAN */ 3962306a36Sopenharmony_ci ICE_FLOW_FLD_INFO(ICE_FLOW_SEG_HDR_VLAN, 12, sizeof(__be16)), 4062306a36Sopenharmony_ci /* ICE_FLOW_FIELD_IDX_C_VLAN */ 4162306a36Sopenharmony_ci ICE_FLOW_FLD_INFO(ICE_FLOW_SEG_HDR_VLAN, 14, sizeof(__be16)), 4262306a36Sopenharmony_ci /* ICE_FLOW_FIELD_IDX_ETH_TYPE */ 4362306a36Sopenharmony_ci ICE_FLOW_FLD_INFO(ICE_FLOW_SEG_HDR_ETH, 0, sizeof(__be16)), 4462306a36Sopenharmony_ci /* IPv4 / IPv6 */ 4562306a36Sopenharmony_ci /* ICE_FLOW_FIELD_IDX_IPV4_DSCP */ 4662306a36Sopenharmony_ci ICE_FLOW_FLD_INFO_MSK(ICE_FLOW_SEG_HDR_IPV4, 0, 1, 0x00fc), 4762306a36Sopenharmony_ci /* ICE_FLOW_FIELD_IDX_IPV6_DSCP */ 4862306a36Sopenharmony_ci ICE_FLOW_FLD_INFO_MSK(ICE_FLOW_SEG_HDR_IPV6, 0, 1, 0x0ff0), 4962306a36Sopenharmony_ci /* ICE_FLOW_FIELD_IDX_IPV4_TTL */ 5062306a36Sopenharmony_ci ICE_FLOW_FLD_INFO_MSK(ICE_FLOW_SEG_HDR_NONE, 8, 1, 0xff00), 5162306a36Sopenharmony_ci /* ICE_FLOW_FIELD_IDX_IPV4_PROT */ 5262306a36Sopenharmony_ci ICE_FLOW_FLD_INFO_MSK(ICE_FLOW_SEG_HDR_NONE, 8, 1, 0x00ff), 5362306a36Sopenharmony_ci /* ICE_FLOW_FIELD_IDX_IPV6_TTL */ 5462306a36Sopenharmony_ci ICE_FLOW_FLD_INFO_MSK(ICE_FLOW_SEG_HDR_NONE, 6, 1, 0x00ff), 5562306a36Sopenharmony_ci /* ICE_FLOW_FIELD_IDX_IPV6_PROT */ 5662306a36Sopenharmony_ci ICE_FLOW_FLD_INFO_MSK(ICE_FLOW_SEG_HDR_NONE, 6, 1, 0xff00), 5762306a36Sopenharmony_ci /* ICE_FLOW_FIELD_IDX_IPV4_SA */ 5862306a36Sopenharmony_ci ICE_FLOW_FLD_INFO(ICE_FLOW_SEG_HDR_IPV4, 12, sizeof(struct in_addr)), 5962306a36Sopenharmony_ci /* ICE_FLOW_FIELD_IDX_IPV4_DA */ 6062306a36Sopenharmony_ci ICE_FLOW_FLD_INFO(ICE_FLOW_SEG_HDR_IPV4, 16, sizeof(struct in_addr)), 6162306a36Sopenharmony_ci /* ICE_FLOW_FIELD_IDX_IPV6_SA */ 6262306a36Sopenharmony_ci ICE_FLOW_FLD_INFO(ICE_FLOW_SEG_HDR_IPV6, 8, sizeof(struct in6_addr)), 6362306a36Sopenharmony_ci /* ICE_FLOW_FIELD_IDX_IPV6_DA */ 6462306a36Sopenharmony_ci ICE_FLOW_FLD_INFO(ICE_FLOW_SEG_HDR_IPV6, 24, sizeof(struct in6_addr)), 6562306a36Sopenharmony_ci /* Transport */ 6662306a36Sopenharmony_ci /* ICE_FLOW_FIELD_IDX_TCP_SRC_PORT */ 6762306a36Sopenharmony_ci ICE_FLOW_FLD_INFO(ICE_FLOW_SEG_HDR_TCP, 0, sizeof(__be16)), 6862306a36Sopenharmony_ci /* ICE_FLOW_FIELD_IDX_TCP_DST_PORT */ 6962306a36Sopenharmony_ci ICE_FLOW_FLD_INFO(ICE_FLOW_SEG_HDR_TCP, 2, sizeof(__be16)), 7062306a36Sopenharmony_ci /* ICE_FLOW_FIELD_IDX_UDP_SRC_PORT */ 7162306a36Sopenharmony_ci ICE_FLOW_FLD_INFO(ICE_FLOW_SEG_HDR_UDP, 0, sizeof(__be16)), 7262306a36Sopenharmony_ci /* ICE_FLOW_FIELD_IDX_UDP_DST_PORT */ 7362306a36Sopenharmony_ci ICE_FLOW_FLD_INFO(ICE_FLOW_SEG_HDR_UDP, 2, sizeof(__be16)), 7462306a36Sopenharmony_ci /* ICE_FLOW_FIELD_IDX_SCTP_SRC_PORT */ 7562306a36Sopenharmony_ci ICE_FLOW_FLD_INFO(ICE_FLOW_SEG_HDR_SCTP, 0, sizeof(__be16)), 7662306a36Sopenharmony_ci /* ICE_FLOW_FIELD_IDX_SCTP_DST_PORT */ 7762306a36Sopenharmony_ci ICE_FLOW_FLD_INFO(ICE_FLOW_SEG_HDR_SCTP, 2, sizeof(__be16)), 7862306a36Sopenharmony_ci /* ICE_FLOW_FIELD_IDX_TCP_FLAGS */ 7962306a36Sopenharmony_ci ICE_FLOW_FLD_INFO(ICE_FLOW_SEG_HDR_TCP, 13, 1), 8062306a36Sopenharmony_ci /* ARP */ 8162306a36Sopenharmony_ci /* ICE_FLOW_FIELD_IDX_ARP_SIP */ 8262306a36Sopenharmony_ci ICE_FLOW_FLD_INFO(ICE_FLOW_SEG_HDR_ARP, 14, sizeof(struct in_addr)), 8362306a36Sopenharmony_ci /* ICE_FLOW_FIELD_IDX_ARP_DIP */ 8462306a36Sopenharmony_ci ICE_FLOW_FLD_INFO(ICE_FLOW_SEG_HDR_ARP, 24, sizeof(struct in_addr)), 8562306a36Sopenharmony_ci /* ICE_FLOW_FIELD_IDX_ARP_SHA */ 8662306a36Sopenharmony_ci ICE_FLOW_FLD_INFO(ICE_FLOW_SEG_HDR_ARP, 8, ETH_ALEN), 8762306a36Sopenharmony_ci /* ICE_FLOW_FIELD_IDX_ARP_DHA */ 8862306a36Sopenharmony_ci ICE_FLOW_FLD_INFO(ICE_FLOW_SEG_HDR_ARP, 18, ETH_ALEN), 8962306a36Sopenharmony_ci /* ICE_FLOW_FIELD_IDX_ARP_OP */ 9062306a36Sopenharmony_ci ICE_FLOW_FLD_INFO(ICE_FLOW_SEG_HDR_ARP, 6, sizeof(__be16)), 9162306a36Sopenharmony_ci /* ICMP */ 9262306a36Sopenharmony_ci /* ICE_FLOW_FIELD_IDX_ICMP_TYPE */ 9362306a36Sopenharmony_ci ICE_FLOW_FLD_INFO(ICE_FLOW_SEG_HDR_ICMP, 0, 1), 9462306a36Sopenharmony_ci /* ICE_FLOW_FIELD_IDX_ICMP_CODE */ 9562306a36Sopenharmony_ci ICE_FLOW_FLD_INFO(ICE_FLOW_SEG_HDR_ICMP, 1, 1), 9662306a36Sopenharmony_ci /* GRE */ 9762306a36Sopenharmony_ci /* ICE_FLOW_FIELD_IDX_GRE_KEYID */ 9862306a36Sopenharmony_ci ICE_FLOW_FLD_INFO(ICE_FLOW_SEG_HDR_GRE, 12, 9962306a36Sopenharmony_ci sizeof_field(struct gre_full_hdr, key)), 10062306a36Sopenharmony_ci /* GTP */ 10162306a36Sopenharmony_ci /* ICE_FLOW_FIELD_IDX_GTPC_TEID */ 10262306a36Sopenharmony_ci ICE_FLOW_FLD_INFO(ICE_FLOW_SEG_HDR_GTPC_TEID, 12, sizeof(__be32)), 10362306a36Sopenharmony_ci /* ICE_FLOW_FIELD_IDX_GTPU_IP_TEID */ 10462306a36Sopenharmony_ci ICE_FLOW_FLD_INFO(ICE_FLOW_SEG_HDR_GTPU_IP, 12, sizeof(__be32)), 10562306a36Sopenharmony_ci /* ICE_FLOW_FIELD_IDX_GTPU_EH_TEID */ 10662306a36Sopenharmony_ci ICE_FLOW_FLD_INFO(ICE_FLOW_SEG_HDR_GTPU_EH, 12, sizeof(__be32)), 10762306a36Sopenharmony_ci /* ICE_FLOW_FIELD_IDX_GTPU_EH_QFI */ 10862306a36Sopenharmony_ci ICE_FLOW_FLD_INFO_MSK(ICE_FLOW_SEG_HDR_GTPU_EH, 22, sizeof(__be16), 10962306a36Sopenharmony_ci 0x3f00), 11062306a36Sopenharmony_ci /* ICE_FLOW_FIELD_IDX_GTPU_UP_TEID */ 11162306a36Sopenharmony_ci ICE_FLOW_FLD_INFO(ICE_FLOW_SEG_HDR_GTPU_UP, 12, sizeof(__be32)), 11262306a36Sopenharmony_ci /* ICE_FLOW_FIELD_IDX_GTPU_DWN_TEID */ 11362306a36Sopenharmony_ci ICE_FLOW_FLD_INFO(ICE_FLOW_SEG_HDR_GTPU_DWN, 12, sizeof(__be32)), 11462306a36Sopenharmony_ci /* PPPoE */ 11562306a36Sopenharmony_ci /* ICE_FLOW_FIELD_IDX_PPPOE_SESS_ID */ 11662306a36Sopenharmony_ci ICE_FLOW_FLD_INFO(ICE_FLOW_SEG_HDR_PPPOE, 2, sizeof(__be16)), 11762306a36Sopenharmony_ci /* PFCP */ 11862306a36Sopenharmony_ci /* ICE_FLOW_FIELD_IDX_PFCP_SEID */ 11962306a36Sopenharmony_ci ICE_FLOW_FLD_INFO(ICE_FLOW_SEG_HDR_PFCP_SESSION, 12, sizeof(__be64)), 12062306a36Sopenharmony_ci /* L2TPv3 */ 12162306a36Sopenharmony_ci /* ICE_FLOW_FIELD_IDX_L2TPV3_SESS_ID */ 12262306a36Sopenharmony_ci ICE_FLOW_FLD_INFO(ICE_FLOW_SEG_HDR_L2TPV3, 0, sizeof(__be32)), 12362306a36Sopenharmony_ci /* ESP */ 12462306a36Sopenharmony_ci /* ICE_FLOW_FIELD_IDX_ESP_SPI */ 12562306a36Sopenharmony_ci ICE_FLOW_FLD_INFO(ICE_FLOW_SEG_HDR_ESP, 0, sizeof(__be32)), 12662306a36Sopenharmony_ci /* AH */ 12762306a36Sopenharmony_ci /* ICE_FLOW_FIELD_IDX_AH_SPI */ 12862306a36Sopenharmony_ci ICE_FLOW_FLD_INFO(ICE_FLOW_SEG_HDR_AH, 4, sizeof(__be32)), 12962306a36Sopenharmony_ci /* NAT_T_ESP */ 13062306a36Sopenharmony_ci /* ICE_FLOW_FIELD_IDX_NAT_T_ESP_SPI */ 13162306a36Sopenharmony_ci ICE_FLOW_FLD_INFO(ICE_FLOW_SEG_HDR_NAT_T_ESP, 8, sizeof(__be32)), 13262306a36Sopenharmony_ci}; 13362306a36Sopenharmony_ci 13462306a36Sopenharmony_ci/* Bitmaps indicating relevant packet types for a particular protocol header 13562306a36Sopenharmony_ci * 13662306a36Sopenharmony_ci * Packet types for packets with an Outer/First/Single MAC header 13762306a36Sopenharmony_ci */ 13862306a36Sopenharmony_cistatic const u32 ice_ptypes_mac_ofos[] = { 13962306a36Sopenharmony_ci 0xFDC00846, 0xBFBF7F7E, 0xF70001DF, 0xFEFDFDFB, 14062306a36Sopenharmony_ci 0x0000077E, 0x00000000, 0x00000000, 0x00000000, 14162306a36Sopenharmony_ci 0x00400000, 0x03FFF000, 0x7FFFFFE0, 0x00000000, 14262306a36Sopenharmony_ci 0x00000000, 0x00000000, 0x00000000, 0x00000000, 14362306a36Sopenharmony_ci 0x00000000, 0x00000000, 0x00000000, 0x00000000, 14462306a36Sopenharmony_ci 0x00000000, 0x00000000, 0x00000000, 0x00000000, 14562306a36Sopenharmony_ci 0x00000000, 0x00000000, 0x00000000, 0x00000000, 14662306a36Sopenharmony_ci 0x00000000, 0x00000000, 0x00000000, 0x00000000, 14762306a36Sopenharmony_ci}; 14862306a36Sopenharmony_ci 14962306a36Sopenharmony_ci/* Packet types for packets with an Innermost/Last MAC VLAN header */ 15062306a36Sopenharmony_cistatic const u32 ice_ptypes_macvlan_il[] = { 15162306a36Sopenharmony_ci 0x00000000, 0xBC000000, 0x000001DF, 0xF0000000, 15262306a36Sopenharmony_ci 0x0000077E, 0x00000000, 0x00000000, 0x00000000, 15362306a36Sopenharmony_ci 0x00000000, 0x00000000, 0x00000000, 0x00000000, 15462306a36Sopenharmony_ci 0x00000000, 0x00000000, 0x00000000, 0x00000000, 15562306a36Sopenharmony_ci 0x00000000, 0x00000000, 0x00000000, 0x00000000, 15662306a36Sopenharmony_ci 0x00000000, 0x00000000, 0x00000000, 0x00000000, 15762306a36Sopenharmony_ci 0x00000000, 0x00000000, 0x00000000, 0x00000000, 15862306a36Sopenharmony_ci 0x00000000, 0x00000000, 0x00000000, 0x00000000, 15962306a36Sopenharmony_ci}; 16062306a36Sopenharmony_ci 16162306a36Sopenharmony_ci/* Packet types for packets with an Outer/First/Single IPv4 header, does NOT 16262306a36Sopenharmony_ci * include IPv4 other PTYPEs 16362306a36Sopenharmony_ci */ 16462306a36Sopenharmony_cistatic const u32 ice_ptypes_ipv4_ofos[] = { 16562306a36Sopenharmony_ci 0x1DC00000, 0x04000800, 0x00000000, 0x00000000, 16662306a36Sopenharmony_ci 0x00000000, 0x00000155, 0x00000000, 0x00000000, 16762306a36Sopenharmony_ci 0x00000000, 0x000FC000, 0x00000000, 0x00000000, 16862306a36Sopenharmony_ci 0x00000000, 0x00000000, 0x00000000, 0x00000000, 16962306a36Sopenharmony_ci 0x00000000, 0x00000000, 0x00000000, 0x00000000, 17062306a36Sopenharmony_ci 0x00000000, 0x00000000, 0x00000000, 0x00000000, 17162306a36Sopenharmony_ci 0x00000000, 0x00000000, 0x00000000, 0x00000000, 17262306a36Sopenharmony_ci 0x00000000, 0x00000000, 0x00000000, 0x00000000, 17362306a36Sopenharmony_ci}; 17462306a36Sopenharmony_ci 17562306a36Sopenharmony_ci/* Packet types for packets with an Outer/First/Single IPv4 header, includes 17662306a36Sopenharmony_ci * IPv4 other PTYPEs 17762306a36Sopenharmony_ci */ 17862306a36Sopenharmony_cistatic const u32 ice_ptypes_ipv4_ofos_all[] = { 17962306a36Sopenharmony_ci 0x1DC00000, 0x04000800, 0x00000000, 0x00000000, 18062306a36Sopenharmony_ci 0x00000000, 0x00000155, 0x00000000, 0x00000000, 18162306a36Sopenharmony_ci 0x00000000, 0x000FC000, 0x83E0F800, 0x00000101, 18262306a36Sopenharmony_ci 0x00000000, 0x00000000, 0x00000000, 0x00000000, 18362306a36Sopenharmony_ci 0x00000000, 0x00000000, 0x00000000, 0x00000000, 18462306a36Sopenharmony_ci 0x00000000, 0x00000000, 0x00000000, 0x00000000, 18562306a36Sopenharmony_ci 0x00000000, 0x00000000, 0x00000000, 0x00000000, 18662306a36Sopenharmony_ci 0x00000000, 0x00000000, 0x00000000, 0x00000000, 18762306a36Sopenharmony_ci}; 18862306a36Sopenharmony_ci 18962306a36Sopenharmony_ci/* Packet types for packets with an Innermost/Last IPv4 header */ 19062306a36Sopenharmony_cistatic const u32 ice_ptypes_ipv4_il[] = { 19162306a36Sopenharmony_ci 0xE0000000, 0xB807700E, 0x80000003, 0xE01DC03B, 19262306a36Sopenharmony_ci 0x0000000E, 0x00000000, 0x00000000, 0x00000000, 19362306a36Sopenharmony_ci 0x00000000, 0x00000000, 0x001FF800, 0x00000000, 19462306a36Sopenharmony_ci 0x00000000, 0x00000000, 0x00000000, 0x00000000, 19562306a36Sopenharmony_ci 0x00000000, 0x00000000, 0x00000000, 0x00000000, 19662306a36Sopenharmony_ci 0x00000000, 0x00000000, 0x00000000, 0x00000000, 19762306a36Sopenharmony_ci 0x00000000, 0x00000000, 0x00000000, 0x00000000, 19862306a36Sopenharmony_ci 0x00000000, 0x00000000, 0x00000000, 0x00000000, 19962306a36Sopenharmony_ci}; 20062306a36Sopenharmony_ci 20162306a36Sopenharmony_ci/* Packet types for packets with an Outer/First/Single IPv6 header, does NOT 20262306a36Sopenharmony_ci * include IPv6 other PTYPEs 20362306a36Sopenharmony_ci */ 20462306a36Sopenharmony_cistatic const u32 ice_ptypes_ipv6_ofos[] = { 20562306a36Sopenharmony_ci 0x00000000, 0x00000000, 0x77000000, 0x10002000, 20662306a36Sopenharmony_ci 0x00000000, 0x000002AA, 0x00000000, 0x00000000, 20762306a36Sopenharmony_ci 0x00000000, 0x03F00000, 0x00000000, 0x00000000, 20862306a36Sopenharmony_ci 0x00000000, 0x00000000, 0x00000000, 0x00000000, 20962306a36Sopenharmony_ci 0x00000000, 0x00000000, 0x00000000, 0x00000000, 21062306a36Sopenharmony_ci 0x00000000, 0x00000000, 0x00000000, 0x00000000, 21162306a36Sopenharmony_ci 0x00000000, 0x00000000, 0x00000000, 0x00000000, 21262306a36Sopenharmony_ci 0x00000000, 0x00000000, 0x00000000, 0x00000000, 21362306a36Sopenharmony_ci}; 21462306a36Sopenharmony_ci 21562306a36Sopenharmony_ci/* Packet types for packets with an Outer/First/Single IPv6 header, includes 21662306a36Sopenharmony_ci * IPv6 other PTYPEs 21762306a36Sopenharmony_ci */ 21862306a36Sopenharmony_cistatic const u32 ice_ptypes_ipv6_ofos_all[] = { 21962306a36Sopenharmony_ci 0x00000000, 0x00000000, 0x77000000, 0x10002000, 22062306a36Sopenharmony_ci 0x00000000, 0x000002AA, 0x00000000, 0x00000000, 22162306a36Sopenharmony_ci 0x00080F00, 0x03F00000, 0x7C1F0000, 0x00000206, 22262306a36Sopenharmony_ci 0x00000000, 0x00000000, 0x00000000, 0x00000000, 22362306a36Sopenharmony_ci 0x00000000, 0x00000000, 0x00000000, 0x00000000, 22462306a36Sopenharmony_ci 0x00000000, 0x00000000, 0x00000000, 0x00000000, 22562306a36Sopenharmony_ci 0x00000000, 0x00000000, 0x00000000, 0x00000000, 22662306a36Sopenharmony_ci 0x00000000, 0x00000000, 0x00000000, 0x00000000, 22762306a36Sopenharmony_ci}; 22862306a36Sopenharmony_ci 22962306a36Sopenharmony_ci/* Packet types for packets with an Innermost/Last IPv6 header */ 23062306a36Sopenharmony_cistatic const u32 ice_ptypes_ipv6_il[] = { 23162306a36Sopenharmony_ci 0x00000000, 0x03B80770, 0x000001DC, 0x0EE00000, 23262306a36Sopenharmony_ci 0x00000770, 0x00000000, 0x00000000, 0x00000000, 23362306a36Sopenharmony_ci 0x00000000, 0x00000000, 0x7FE00000, 0x00000000, 23462306a36Sopenharmony_ci 0x00000000, 0x00000000, 0x00000000, 0x00000000, 23562306a36Sopenharmony_ci 0x00000000, 0x00000000, 0x00000000, 0x00000000, 23662306a36Sopenharmony_ci 0x00000000, 0x00000000, 0x00000000, 0x00000000, 23762306a36Sopenharmony_ci 0x00000000, 0x00000000, 0x00000000, 0x00000000, 23862306a36Sopenharmony_ci 0x00000000, 0x00000000, 0x00000000, 0x00000000, 23962306a36Sopenharmony_ci}; 24062306a36Sopenharmony_ci 24162306a36Sopenharmony_ci/* Packet types for packets with an Outer/First/Single IPv4 header - no L4 */ 24262306a36Sopenharmony_cistatic const u32 ice_ptypes_ipv4_ofos_no_l4[] = { 24362306a36Sopenharmony_ci 0x10C00000, 0x04000800, 0x00000000, 0x00000000, 24462306a36Sopenharmony_ci 0x00000000, 0x00000000, 0x00000000, 0x00000000, 24562306a36Sopenharmony_ci 0x00000000, 0x00000000, 0x00000000, 0x00000000, 24662306a36Sopenharmony_ci 0x00000000, 0x00000000, 0x00000000, 0x00000000, 24762306a36Sopenharmony_ci 0x00000000, 0x00000000, 0x00000000, 0x00000000, 24862306a36Sopenharmony_ci 0x00000000, 0x00000000, 0x00000000, 0x00000000, 24962306a36Sopenharmony_ci 0x00000000, 0x00000000, 0x00000000, 0x00000000, 25062306a36Sopenharmony_ci 0x00000000, 0x00000000, 0x00000000, 0x00000000, 25162306a36Sopenharmony_ci}; 25262306a36Sopenharmony_ci 25362306a36Sopenharmony_ci/* Packet types for packets with an Outermost/First ARP header */ 25462306a36Sopenharmony_cistatic const u32 ice_ptypes_arp_of[] = { 25562306a36Sopenharmony_ci 0x00000800, 0x00000000, 0x00000000, 0x00000000, 25662306a36Sopenharmony_ci 0x00000000, 0x00000000, 0x00000000, 0x00000000, 25762306a36Sopenharmony_ci 0x00000000, 0x00000000, 0x00000000, 0x00000000, 25862306a36Sopenharmony_ci 0x00000000, 0x00000000, 0x00000000, 0x00000000, 25962306a36Sopenharmony_ci 0x00000000, 0x00000000, 0x00000000, 0x00000000, 26062306a36Sopenharmony_ci 0x00000000, 0x00000000, 0x00000000, 0x00000000, 26162306a36Sopenharmony_ci 0x00000000, 0x00000000, 0x00000000, 0x00000000, 26262306a36Sopenharmony_ci 0x00000000, 0x00000000, 0x00000000, 0x00000000, 26362306a36Sopenharmony_ci}; 26462306a36Sopenharmony_ci 26562306a36Sopenharmony_ci/* Packet types for packets with an Innermost/Last IPv4 header - no L4 */ 26662306a36Sopenharmony_cistatic const u32 ice_ptypes_ipv4_il_no_l4[] = { 26762306a36Sopenharmony_ci 0x60000000, 0x18043008, 0x80000002, 0x6010c021, 26862306a36Sopenharmony_ci 0x00000008, 0x00000000, 0x00000000, 0x00000000, 26962306a36Sopenharmony_ci 0x00000000, 0x00000000, 0x00000000, 0x00000000, 27062306a36Sopenharmony_ci 0x00000000, 0x00000000, 0x00000000, 0x00000000, 27162306a36Sopenharmony_ci 0x00000000, 0x00000000, 0x00000000, 0x00000000, 27262306a36Sopenharmony_ci 0x00000000, 0x00000000, 0x00000000, 0x00000000, 27362306a36Sopenharmony_ci 0x00000000, 0x00000000, 0x00000000, 0x00000000, 27462306a36Sopenharmony_ci 0x00000000, 0x00000000, 0x00000000, 0x00000000, 27562306a36Sopenharmony_ci}; 27662306a36Sopenharmony_ci 27762306a36Sopenharmony_ci/* Packet types for packets with an Outer/First/Single IPv6 header - no L4 */ 27862306a36Sopenharmony_cistatic const u32 ice_ptypes_ipv6_ofos_no_l4[] = { 27962306a36Sopenharmony_ci 0x00000000, 0x00000000, 0x43000000, 0x10002000, 28062306a36Sopenharmony_ci 0x00000000, 0x00000000, 0x00000000, 0x00000000, 28162306a36Sopenharmony_ci 0x00000000, 0x00000000, 0x00000000, 0x00000000, 28262306a36Sopenharmony_ci 0x00000000, 0x00000000, 0x00000000, 0x00000000, 28362306a36Sopenharmony_ci 0x00000000, 0x00000000, 0x00000000, 0x00000000, 28462306a36Sopenharmony_ci 0x00000000, 0x00000000, 0x00000000, 0x00000000, 28562306a36Sopenharmony_ci 0x00000000, 0x00000000, 0x00000000, 0x00000000, 28662306a36Sopenharmony_ci 0x00000000, 0x00000000, 0x00000000, 0x00000000, 28762306a36Sopenharmony_ci}; 28862306a36Sopenharmony_ci 28962306a36Sopenharmony_ci/* Packet types for packets with an Innermost/Last IPv6 header - no L4 */ 29062306a36Sopenharmony_cistatic const u32 ice_ptypes_ipv6_il_no_l4[] = { 29162306a36Sopenharmony_ci 0x00000000, 0x02180430, 0x0000010c, 0x086010c0, 29262306a36Sopenharmony_ci 0x00000430, 0x00000000, 0x00000000, 0x00000000, 29362306a36Sopenharmony_ci 0x00000000, 0x00000000, 0x00000000, 0x00000000, 29462306a36Sopenharmony_ci 0x00000000, 0x00000000, 0x00000000, 0x00000000, 29562306a36Sopenharmony_ci 0x00000000, 0x00000000, 0x00000000, 0x00000000, 29662306a36Sopenharmony_ci 0x00000000, 0x00000000, 0x00000000, 0x00000000, 29762306a36Sopenharmony_ci 0x00000000, 0x00000000, 0x00000000, 0x00000000, 29862306a36Sopenharmony_ci 0x00000000, 0x00000000, 0x00000000, 0x00000000, 29962306a36Sopenharmony_ci}; 30062306a36Sopenharmony_ci 30162306a36Sopenharmony_ci/* UDP Packet types for non-tunneled packets or tunneled 30262306a36Sopenharmony_ci * packets with inner UDP. 30362306a36Sopenharmony_ci */ 30462306a36Sopenharmony_cistatic const u32 ice_ptypes_udp_il[] = { 30562306a36Sopenharmony_ci 0x81000000, 0x20204040, 0x04000010, 0x80810102, 30662306a36Sopenharmony_ci 0x00000040, 0x00000000, 0x00000000, 0x00000000, 30762306a36Sopenharmony_ci 0x00000000, 0x00410000, 0x90842000, 0x00000007, 30862306a36Sopenharmony_ci 0x00000000, 0x00000000, 0x00000000, 0x00000000, 30962306a36Sopenharmony_ci 0x00000000, 0x00000000, 0x00000000, 0x00000000, 31062306a36Sopenharmony_ci 0x00000000, 0x00000000, 0x00000000, 0x00000000, 31162306a36Sopenharmony_ci 0x00000000, 0x00000000, 0x00000000, 0x00000000, 31262306a36Sopenharmony_ci 0x00000000, 0x00000000, 0x00000000, 0x00000000, 31362306a36Sopenharmony_ci}; 31462306a36Sopenharmony_ci 31562306a36Sopenharmony_ci/* Packet types for packets with an Innermost/Last TCP header */ 31662306a36Sopenharmony_cistatic const u32 ice_ptypes_tcp_il[] = { 31762306a36Sopenharmony_ci 0x04000000, 0x80810102, 0x10000040, 0x02040408, 31862306a36Sopenharmony_ci 0x00000102, 0x00000000, 0x00000000, 0x00000000, 31962306a36Sopenharmony_ci 0x00000000, 0x00820000, 0x21084000, 0x00000000, 32062306a36Sopenharmony_ci 0x00000000, 0x00000000, 0x00000000, 0x00000000, 32162306a36Sopenharmony_ci 0x00000000, 0x00000000, 0x00000000, 0x00000000, 32262306a36Sopenharmony_ci 0x00000000, 0x00000000, 0x00000000, 0x00000000, 32362306a36Sopenharmony_ci 0x00000000, 0x00000000, 0x00000000, 0x00000000, 32462306a36Sopenharmony_ci 0x00000000, 0x00000000, 0x00000000, 0x00000000, 32562306a36Sopenharmony_ci}; 32662306a36Sopenharmony_ci 32762306a36Sopenharmony_ci/* Packet types for packets with an Innermost/Last SCTP header */ 32862306a36Sopenharmony_cistatic const u32 ice_ptypes_sctp_il[] = { 32962306a36Sopenharmony_ci 0x08000000, 0x01020204, 0x20000081, 0x04080810, 33062306a36Sopenharmony_ci 0x00000204, 0x00000000, 0x00000000, 0x00000000, 33162306a36Sopenharmony_ci 0x00000000, 0x01040000, 0x00000000, 0x00000000, 33262306a36Sopenharmony_ci 0x00000000, 0x00000000, 0x00000000, 0x00000000, 33362306a36Sopenharmony_ci 0x00000000, 0x00000000, 0x00000000, 0x00000000, 33462306a36Sopenharmony_ci 0x00000000, 0x00000000, 0x00000000, 0x00000000, 33562306a36Sopenharmony_ci 0x00000000, 0x00000000, 0x00000000, 0x00000000, 33662306a36Sopenharmony_ci 0x00000000, 0x00000000, 0x00000000, 0x00000000, 33762306a36Sopenharmony_ci}; 33862306a36Sopenharmony_ci 33962306a36Sopenharmony_ci/* Packet types for packets with an Outermost/First ICMP header */ 34062306a36Sopenharmony_cistatic const u32 ice_ptypes_icmp_of[] = { 34162306a36Sopenharmony_ci 0x10000000, 0x00000000, 0x00000000, 0x00000000, 34262306a36Sopenharmony_ci 0x00000000, 0x00000000, 0x00000000, 0x00000000, 34362306a36Sopenharmony_ci 0x00000000, 0x00000000, 0x00000000, 0x00000000, 34462306a36Sopenharmony_ci 0x00000000, 0x00000000, 0x00000000, 0x00000000, 34562306a36Sopenharmony_ci 0x00000000, 0x00000000, 0x00000000, 0x00000000, 34662306a36Sopenharmony_ci 0x00000000, 0x00000000, 0x00000000, 0x00000000, 34762306a36Sopenharmony_ci 0x00000000, 0x00000000, 0x00000000, 0x00000000, 34862306a36Sopenharmony_ci 0x00000000, 0x00000000, 0x00000000, 0x00000000, 34962306a36Sopenharmony_ci}; 35062306a36Sopenharmony_ci 35162306a36Sopenharmony_ci/* Packet types for packets with an Innermost/Last ICMP header */ 35262306a36Sopenharmony_cistatic const u32 ice_ptypes_icmp_il[] = { 35362306a36Sopenharmony_ci 0x00000000, 0x02040408, 0x40000102, 0x08101020, 35462306a36Sopenharmony_ci 0x00000408, 0x00000000, 0x00000000, 0x00000000, 35562306a36Sopenharmony_ci 0x00000000, 0x00000000, 0x42108000, 0x00000000, 35662306a36Sopenharmony_ci 0x00000000, 0x00000000, 0x00000000, 0x00000000, 35762306a36Sopenharmony_ci 0x00000000, 0x00000000, 0x00000000, 0x00000000, 35862306a36Sopenharmony_ci 0x00000000, 0x00000000, 0x00000000, 0x00000000, 35962306a36Sopenharmony_ci 0x00000000, 0x00000000, 0x00000000, 0x00000000, 36062306a36Sopenharmony_ci 0x00000000, 0x00000000, 0x00000000, 0x00000000, 36162306a36Sopenharmony_ci}; 36262306a36Sopenharmony_ci 36362306a36Sopenharmony_ci/* Packet types for packets with an Outermost/First GRE header */ 36462306a36Sopenharmony_cistatic const u32 ice_ptypes_gre_of[] = { 36562306a36Sopenharmony_ci 0x00000000, 0xBFBF7800, 0x000001DF, 0xFEFDE000, 36662306a36Sopenharmony_ci 0x0000017E, 0x00000000, 0x00000000, 0x00000000, 36762306a36Sopenharmony_ci 0x00000000, 0x00000000, 0x00000000, 0x00000000, 36862306a36Sopenharmony_ci 0x00000000, 0x00000000, 0x00000000, 0x00000000, 36962306a36Sopenharmony_ci 0x00000000, 0x00000000, 0x00000000, 0x00000000, 37062306a36Sopenharmony_ci 0x00000000, 0x00000000, 0x00000000, 0x00000000, 37162306a36Sopenharmony_ci 0x00000000, 0x00000000, 0x00000000, 0x00000000, 37262306a36Sopenharmony_ci 0x00000000, 0x00000000, 0x00000000, 0x00000000, 37362306a36Sopenharmony_ci}; 37462306a36Sopenharmony_ci 37562306a36Sopenharmony_ci/* Packet types for packets with an Innermost/Last MAC header */ 37662306a36Sopenharmony_cistatic const u32 ice_ptypes_mac_il[] = { 37762306a36Sopenharmony_ci 0x00000000, 0x00000000, 0x00000000, 0x00000000, 37862306a36Sopenharmony_ci 0x00000000, 0x00000000, 0x00000000, 0x00000000, 37962306a36Sopenharmony_ci 0x00000000, 0x00000000, 0x00000000, 0x00000000, 38062306a36Sopenharmony_ci 0x00000000, 0x00000000, 0x00000000, 0x00000000, 38162306a36Sopenharmony_ci 0x00000000, 0x00000000, 0x00000000, 0x00000000, 38262306a36Sopenharmony_ci 0x00000000, 0x00000000, 0x00000000, 0x00000000, 38362306a36Sopenharmony_ci 0x00000000, 0x00000000, 0x00000000, 0x00000000, 38462306a36Sopenharmony_ci 0x00000000, 0x00000000, 0x00000000, 0x00000000, 38562306a36Sopenharmony_ci}; 38662306a36Sopenharmony_ci 38762306a36Sopenharmony_ci/* Packet types for GTPC */ 38862306a36Sopenharmony_cistatic const u32 ice_ptypes_gtpc[] = { 38962306a36Sopenharmony_ci 0x00000000, 0x00000000, 0x00000000, 0x00000000, 39062306a36Sopenharmony_ci 0x00000000, 0x00000000, 0x00000000, 0x00000000, 39162306a36Sopenharmony_ci 0x00000000, 0x00000000, 0x00000180, 0x00000000, 39262306a36Sopenharmony_ci 0x00000000, 0x00000000, 0x00000000, 0x00000000, 39362306a36Sopenharmony_ci 0x00000000, 0x00000000, 0x00000000, 0x00000000, 39462306a36Sopenharmony_ci 0x00000000, 0x00000000, 0x00000000, 0x00000000, 39562306a36Sopenharmony_ci 0x00000000, 0x00000000, 0x00000000, 0x00000000, 39662306a36Sopenharmony_ci 0x00000000, 0x00000000, 0x00000000, 0x00000000, 39762306a36Sopenharmony_ci}; 39862306a36Sopenharmony_ci 39962306a36Sopenharmony_ci/* Packet types for GTPC with TEID */ 40062306a36Sopenharmony_cistatic const u32 ice_ptypes_gtpc_tid[] = { 40162306a36Sopenharmony_ci 0x00000000, 0x00000000, 0x00000000, 0x00000000, 40262306a36Sopenharmony_ci 0x00000000, 0x00000000, 0x00000000, 0x00000000, 40362306a36Sopenharmony_ci 0x00000000, 0x00000000, 0x00000060, 0x00000000, 40462306a36Sopenharmony_ci 0x00000000, 0x00000000, 0x00000000, 0x00000000, 40562306a36Sopenharmony_ci 0x00000000, 0x00000000, 0x00000000, 0x00000000, 40662306a36Sopenharmony_ci 0x00000000, 0x00000000, 0x00000000, 0x00000000, 40762306a36Sopenharmony_ci 0x00000000, 0x00000000, 0x00000000, 0x00000000, 40862306a36Sopenharmony_ci 0x00000000, 0x00000000, 0x00000000, 0x00000000, 40962306a36Sopenharmony_ci}; 41062306a36Sopenharmony_ci 41162306a36Sopenharmony_ci/* Packet types for GTPU */ 41262306a36Sopenharmony_cistatic const struct ice_ptype_attributes ice_attr_gtpu_eh[] = { 41362306a36Sopenharmony_ci { ICE_MAC_IPV4_GTPU_IPV4_FRAG, ICE_PTYPE_ATTR_GTP_PDU_EH }, 41462306a36Sopenharmony_ci { ICE_MAC_IPV4_GTPU_IPV4_PAY, ICE_PTYPE_ATTR_GTP_PDU_EH }, 41562306a36Sopenharmony_ci { ICE_MAC_IPV4_GTPU_IPV4_UDP_PAY, ICE_PTYPE_ATTR_GTP_PDU_EH }, 41662306a36Sopenharmony_ci { ICE_MAC_IPV4_GTPU_IPV4_TCP, ICE_PTYPE_ATTR_GTP_PDU_EH }, 41762306a36Sopenharmony_ci { ICE_MAC_IPV4_GTPU_IPV4_ICMP, ICE_PTYPE_ATTR_GTP_PDU_EH }, 41862306a36Sopenharmony_ci { ICE_MAC_IPV6_GTPU_IPV4_FRAG, ICE_PTYPE_ATTR_GTP_PDU_EH }, 41962306a36Sopenharmony_ci { ICE_MAC_IPV6_GTPU_IPV4_PAY, ICE_PTYPE_ATTR_GTP_PDU_EH }, 42062306a36Sopenharmony_ci { ICE_MAC_IPV6_GTPU_IPV4_UDP_PAY, ICE_PTYPE_ATTR_GTP_PDU_EH }, 42162306a36Sopenharmony_ci { ICE_MAC_IPV6_GTPU_IPV4_TCP, ICE_PTYPE_ATTR_GTP_PDU_EH }, 42262306a36Sopenharmony_ci { ICE_MAC_IPV6_GTPU_IPV4_ICMP, ICE_PTYPE_ATTR_GTP_PDU_EH }, 42362306a36Sopenharmony_ci { ICE_MAC_IPV4_GTPU_IPV6_FRAG, ICE_PTYPE_ATTR_GTP_PDU_EH }, 42462306a36Sopenharmony_ci { ICE_MAC_IPV4_GTPU_IPV6_PAY, ICE_PTYPE_ATTR_GTP_PDU_EH }, 42562306a36Sopenharmony_ci { ICE_MAC_IPV4_GTPU_IPV6_UDP_PAY, ICE_PTYPE_ATTR_GTP_PDU_EH }, 42662306a36Sopenharmony_ci { ICE_MAC_IPV4_GTPU_IPV6_TCP, ICE_PTYPE_ATTR_GTP_PDU_EH }, 42762306a36Sopenharmony_ci { ICE_MAC_IPV4_GTPU_IPV6_ICMPV6, ICE_PTYPE_ATTR_GTP_PDU_EH }, 42862306a36Sopenharmony_ci { ICE_MAC_IPV6_GTPU_IPV6_FRAG, ICE_PTYPE_ATTR_GTP_PDU_EH }, 42962306a36Sopenharmony_ci { ICE_MAC_IPV6_GTPU_IPV6_PAY, ICE_PTYPE_ATTR_GTP_PDU_EH }, 43062306a36Sopenharmony_ci { ICE_MAC_IPV6_GTPU_IPV6_UDP_PAY, ICE_PTYPE_ATTR_GTP_PDU_EH }, 43162306a36Sopenharmony_ci { ICE_MAC_IPV6_GTPU_IPV6_TCP, ICE_PTYPE_ATTR_GTP_PDU_EH }, 43262306a36Sopenharmony_ci { ICE_MAC_IPV6_GTPU_IPV6_ICMPV6, ICE_PTYPE_ATTR_GTP_PDU_EH }, 43362306a36Sopenharmony_ci}; 43462306a36Sopenharmony_ci 43562306a36Sopenharmony_cistatic const struct ice_ptype_attributes ice_attr_gtpu_down[] = { 43662306a36Sopenharmony_ci { ICE_MAC_IPV4_GTPU_IPV4_FRAG, ICE_PTYPE_ATTR_GTP_DOWNLINK }, 43762306a36Sopenharmony_ci { ICE_MAC_IPV4_GTPU_IPV4_PAY, ICE_PTYPE_ATTR_GTP_DOWNLINK }, 43862306a36Sopenharmony_ci { ICE_MAC_IPV4_GTPU_IPV4_UDP_PAY, ICE_PTYPE_ATTR_GTP_DOWNLINK }, 43962306a36Sopenharmony_ci { ICE_MAC_IPV4_GTPU_IPV4_TCP, ICE_PTYPE_ATTR_GTP_DOWNLINK }, 44062306a36Sopenharmony_ci { ICE_MAC_IPV4_GTPU_IPV4_ICMP, ICE_PTYPE_ATTR_GTP_DOWNLINK }, 44162306a36Sopenharmony_ci { ICE_MAC_IPV6_GTPU_IPV4_FRAG, ICE_PTYPE_ATTR_GTP_DOWNLINK }, 44262306a36Sopenharmony_ci { ICE_MAC_IPV6_GTPU_IPV4_PAY, ICE_PTYPE_ATTR_GTP_DOWNLINK }, 44362306a36Sopenharmony_ci { ICE_MAC_IPV6_GTPU_IPV4_UDP_PAY, ICE_PTYPE_ATTR_GTP_DOWNLINK }, 44462306a36Sopenharmony_ci { ICE_MAC_IPV6_GTPU_IPV4_TCP, ICE_PTYPE_ATTR_GTP_DOWNLINK }, 44562306a36Sopenharmony_ci { ICE_MAC_IPV6_GTPU_IPV4_ICMP, ICE_PTYPE_ATTR_GTP_DOWNLINK }, 44662306a36Sopenharmony_ci { ICE_MAC_IPV4_GTPU_IPV6_FRAG, ICE_PTYPE_ATTR_GTP_DOWNLINK }, 44762306a36Sopenharmony_ci { ICE_MAC_IPV4_GTPU_IPV6_PAY, ICE_PTYPE_ATTR_GTP_DOWNLINK }, 44862306a36Sopenharmony_ci { ICE_MAC_IPV4_GTPU_IPV6_UDP_PAY, ICE_PTYPE_ATTR_GTP_DOWNLINK }, 44962306a36Sopenharmony_ci { ICE_MAC_IPV4_GTPU_IPV6_TCP, ICE_PTYPE_ATTR_GTP_DOWNLINK }, 45062306a36Sopenharmony_ci { ICE_MAC_IPV4_GTPU_IPV6_ICMPV6, ICE_PTYPE_ATTR_GTP_DOWNLINK }, 45162306a36Sopenharmony_ci { ICE_MAC_IPV6_GTPU_IPV6_FRAG, ICE_PTYPE_ATTR_GTP_DOWNLINK }, 45262306a36Sopenharmony_ci { ICE_MAC_IPV6_GTPU_IPV6_PAY, ICE_PTYPE_ATTR_GTP_DOWNLINK }, 45362306a36Sopenharmony_ci { ICE_MAC_IPV6_GTPU_IPV6_UDP_PAY, ICE_PTYPE_ATTR_GTP_DOWNLINK }, 45462306a36Sopenharmony_ci { ICE_MAC_IPV6_GTPU_IPV6_TCP, ICE_PTYPE_ATTR_GTP_DOWNLINK }, 45562306a36Sopenharmony_ci { ICE_MAC_IPV6_GTPU_IPV6_ICMPV6, ICE_PTYPE_ATTR_GTP_DOWNLINK }, 45662306a36Sopenharmony_ci}; 45762306a36Sopenharmony_ci 45862306a36Sopenharmony_cistatic const struct ice_ptype_attributes ice_attr_gtpu_up[] = { 45962306a36Sopenharmony_ci { ICE_MAC_IPV4_GTPU_IPV4_FRAG, ICE_PTYPE_ATTR_GTP_UPLINK }, 46062306a36Sopenharmony_ci { ICE_MAC_IPV4_GTPU_IPV4_PAY, ICE_PTYPE_ATTR_GTP_UPLINK }, 46162306a36Sopenharmony_ci { ICE_MAC_IPV4_GTPU_IPV4_UDP_PAY, ICE_PTYPE_ATTR_GTP_UPLINK }, 46262306a36Sopenharmony_ci { ICE_MAC_IPV4_GTPU_IPV4_TCP, ICE_PTYPE_ATTR_GTP_UPLINK }, 46362306a36Sopenharmony_ci { ICE_MAC_IPV4_GTPU_IPV4_ICMP, ICE_PTYPE_ATTR_GTP_UPLINK }, 46462306a36Sopenharmony_ci { ICE_MAC_IPV6_GTPU_IPV4_FRAG, ICE_PTYPE_ATTR_GTP_UPLINK }, 46562306a36Sopenharmony_ci { ICE_MAC_IPV6_GTPU_IPV4_PAY, ICE_PTYPE_ATTR_GTP_UPLINK }, 46662306a36Sopenharmony_ci { ICE_MAC_IPV6_GTPU_IPV4_UDP_PAY, ICE_PTYPE_ATTR_GTP_UPLINK }, 46762306a36Sopenharmony_ci { ICE_MAC_IPV6_GTPU_IPV4_TCP, ICE_PTYPE_ATTR_GTP_UPLINK }, 46862306a36Sopenharmony_ci { ICE_MAC_IPV6_GTPU_IPV4_ICMP, ICE_PTYPE_ATTR_GTP_UPLINK }, 46962306a36Sopenharmony_ci { ICE_MAC_IPV4_GTPU_IPV6_FRAG, ICE_PTYPE_ATTR_GTP_UPLINK }, 47062306a36Sopenharmony_ci { ICE_MAC_IPV4_GTPU_IPV6_PAY, ICE_PTYPE_ATTR_GTP_UPLINK }, 47162306a36Sopenharmony_ci { ICE_MAC_IPV4_GTPU_IPV6_UDP_PAY, ICE_PTYPE_ATTR_GTP_UPLINK }, 47262306a36Sopenharmony_ci { ICE_MAC_IPV4_GTPU_IPV6_TCP, ICE_PTYPE_ATTR_GTP_UPLINK }, 47362306a36Sopenharmony_ci { ICE_MAC_IPV4_GTPU_IPV6_ICMPV6, ICE_PTYPE_ATTR_GTP_UPLINK }, 47462306a36Sopenharmony_ci { ICE_MAC_IPV6_GTPU_IPV6_FRAG, ICE_PTYPE_ATTR_GTP_UPLINK }, 47562306a36Sopenharmony_ci { ICE_MAC_IPV6_GTPU_IPV6_PAY, ICE_PTYPE_ATTR_GTP_UPLINK }, 47662306a36Sopenharmony_ci { ICE_MAC_IPV6_GTPU_IPV6_UDP_PAY, ICE_PTYPE_ATTR_GTP_UPLINK }, 47762306a36Sopenharmony_ci { ICE_MAC_IPV6_GTPU_IPV6_TCP, ICE_PTYPE_ATTR_GTP_UPLINK }, 47862306a36Sopenharmony_ci { ICE_MAC_IPV6_GTPU_IPV6_ICMPV6, ICE_PTYPE_ATTR_GTP_UPLINK }, 47962306a36Sopenharmony_ci}; 48062306a36Sopenharmony_ci 48162306a36Sopenharmony_cistatic const u32 ice_ptypes_gtpu[] = { 48262306a36Sopenharmony_ci 0x00000000, 0x00000000, 0x00000000, 0x00000000, 48362306a36Sopenharmony_ci 0x00000000, 0x00000000, 0x00000000, 0x00000000, 48462306a36Sopenharmony_ci 0x00000000, 0x00000000, 0x7FFFFE00, 0x00000000, 48562306a36Sopenharmony_ci 0x00000000, 0x00000000, 0x00000000, 0x00000000, 48662306a36Sopenharmony_ci 0x00000000, 0x00000000, 0x00000000, 0x00000000, 48762306a36Sopenharmony_ci 0x00000000, 0x00000000, 0x00000000, 0x00000000, 48862306a36Sopenharmony_ci 0x00000000, 0x00000000, 0x00000000, 0x00000000, 48962306a36Sopenharmony_ci 0x00000000, 0x00000000, 0x00000000, 0x00000000, 49062306a36Sopenharmony_ci}; 49162306a36Sopenharmony_ci 49262306a36Sopenharmony_ci/* Packet types for PPPoE */ 49362306a36Sopenharmony_cistatic const u32 ice_ptypes_pppoe[] = { 49462306a36Sopenharmony_ci 0x00000000, 0x00000000, 0x00000000, 0x00000000, 49562306a36Sopenharmony_ci 0x00000000, 0x00000000, 0x00000000, 0x00000000, 49662306a36Sopenharmony_ci 0x00000000, 0x03ffe000, 0x00000000, 0x00000000, 49762306a36Sopenharmony_ci 0x00000000, 0x00000000, 0x00000000, 0x00000000, 49862306a36Sopenharmony_ci 0x00000000, 0x00000000, 0x00000000, 0x00000000, 49962306a36Sopenharmony_ci 0x00000000, 0x00000000, 0x00000000, 0x00000000, 50062306a36Sopenharmony_ci 0x00000000, 0x00000000, 0x00000000, 0x00000000, 50162306a36Sopenharmony_ci 0x00000000, 0x00000000, 0x00000000, 0x00000000, 50262306a36Sopenharmony_ci}; 50362306a36Sopenharmony_ci 50462306a36Sopenharmony_ci/* Packet types for packets with PFCP NODE header */ 50562306a36Sopenharmony_cistatic const u32 ice_ptypes_pfcp_node[] = { 50662306a36Sopenharmony_ci 0x00000000, 0x00000000, 0x00000000, 0x00000000, 50762306a36Sopenharmony_ci 0x00000000, 0x00000000, 0x00000000, 0x00000000, 50862306a36Sopenharmony_ci 0x00000000, 0x00000000, 0x80000000, 0x00000002, 50962306a36Sopenharmony_ci 0x00000000, 0x00000000, 0x00000000, 0x00000000, 51062306a36Sopenharmony_ci 0x00000000, 0x00000000, 0x00000000, 0x00000000, 51162306a36Sopenharmony_ci 0x00000000, 0x00000000, 0x00000000, 0x00000000, 51262306a36Sopenharmony_ci 0x00000000, 0x00000000, 0x00000000, 0x00000000, 51362306a36Sopenharmony_ci 0x00000000, 0x00000000, 0x00000000, 0x00000000, 51462306a36Sopenharmony_ci}; 51562306a36Sopenharmony_ci 51662306a36Sopenharmony_ci/* Packet types for packets with PFCP SESSION header */ 51762306a36Sopenharmony_cistatic const u32 ice_ptypes_pfcp_session[] = { 51862306a36Sopenharmony_ci 0x00000000, 0x00000000, 0x00000000, 0x00000000, 51962306a36Sopenharmony_ci 0x00000000, 0x00000000, 0x00000000, 0x00000000, 52062306a36Sopenharmony_ci 0x00000000, 0x00000000, 0x00000000, 0x00000005, 52162306a36Sopenharmony_ci 0x00000000, 0x00000000, 0x00000000, 0x00000000, 52262306a36Sopenharmony_ci 0x00000000, 0x00000000, 0x00000000, 0x00000000, 52362306a36Sopenharmony_ci 0x00000000, 0x00000000, 0x00000000, 0x00000000, 52462306a36Sopenharmony_ci 0x00000000, 0x00000000, 0x00000000, 0x00000000, 52562306a36Sopenharmony_ci 0x00000000, 0x00000000, 0x00000000, 0x00000000, 52662306a36Sopenharmony_ci}; 52762306a36Sopenharmony_ci 52862306a36Sopenharmony_ci/* Packet types for L2TPv3 */ 52962306a36Sopenharmony_cistatic const u32 ice_ptypes_l2tpv3[] = { 53062306a36Sopenharmony_ci 0x00000000, 0x00000000, 0x00000000, 0x00000000, 53162306a36Sopenharmony_ci 0x00000000, 0x00000000, 0x00000000, 0x00000000, 53262306a36Sopenharmony_ci 0x00000000, 0x00000000, 0x00000000, 0x00000300, 53362306a36Sopenharmony_ci 0x00000000, 0x00000000, 0x00000000, 0x00000000, 53462306a36Sopenharmony_ci 0x00000000, 0x00000000, 0x00000000, 0x00000000, 53562306a36Sopenharmony_ci 0x00000000, 0x00000000, 0x00000000, 0x00000000, 53662306a36Sopenharmony_ci 0x00000000, 0x00000000, 0x00000000, 0x00000000, 53762306a36Sopenharmony_ci 0x00000000, 0x00000000, 0x00000000, 0x00000000, 53862306a36Sopenharmony_ci}; 53962306a36Sopenharmony_ci 54062306a36Sopenharmony_ci/* Packet types for ESP */ 54162306a36Sopenharmony_cistatic const u32 ice_ptypes_esp[] = { 54262306a36Sopenharmony_ci 0x00000000, 0x00000000, 0x00000000, 0x00000000, 54362306a36Sopenharmony_ci 0x00000000, 0x00000003, 0x00000000, 0x00000000, 54462306a36Sopenharmony_ci 0x00000000, 0x00000000, 0x00000000, 0x00000000, 54562306a36Sopenharmony_ci 0x00000000, 0x00000000, 0x00000000, 0x00000000, 54662306a36Sopenharmony_ci 0x00000000, 0x00000000, 0x00000000, 0x00000000, 54762306a36Sopenharmony_ci 0x00000000, 0x00000000, 0x00000000, 0x00000000, 54862306a36Sopenharmony_ci 0x00000000, 0x00000000, 0x00000000, 0x00000000, 54962306a36Sopenharmony_ci 0x00000000, 0x00000000, 0x00000000, 0x00000000, 55062306a36Sopenharmony_ci}; 55162306a36Sopenharmony_ci 55262306a36Sopenharmony_ci/* Packet types for AH */ 55362306a36Sopenharmony_cistatic const u32 ice_ptypes_ah[] = { 55462306a36Sopenharmony_ci 0x00000000, 0x00000000, 0x00000000, 0x00000000, 55562306a36Sopenharmony_ci 0x00000000, 0x0000000C, 0x00000000, 0x00000000, 55662306a36Sopenharmony_ci 0x00000000, 0x00000000, 0x00000000, 0x00000000, 55762306a36Sopenharmony_ci 0x00000000, 0x00000000, 0x00000000, 0x00000000, 55862306a36Sopenharmony_ci 0x00000000, 0x00000000, 0x00000000, 0x00000000, 55962306a36Sopenharmony_ci 0x00000000, 0x00000000, 0x00000000, 0x00000000, 56062306a36Sopenharmony_ci 0x00000000, 0x00000000, 0x00000000, 0x00000000, 56162306a36Sopenharmony_ci 0x00000000, 0x00000000, 0x00000000, 0x00000000, 56262306a36Sopenharmony_ci}; 56362306a36Sopenharmony_ci 56462306a36Sopenharmony_ci/* Packet types for packets with NAT_T ESP header */ 56562306a36Sopenharmony_cistatic const u32 ice_ptypes_nat_t_esp[] = { 56662306a36Sopenharmony_ci 0x00000000, 0x00000000, 0x00000000, 0x00000000, 56762306a36Sopenharmony_ci 0x00000000, 0x00000030, 0x00000000, 0x00000000, 56862306a36Sopenharmony_ci 0x00000000, 0x00000000, 0x00000000, 0x00000000, 56962306a36Sopenharmony_ci 0x00000000, 0x00000000, 0x00000000, 0x00000000, 57062306a36Sopenharmony_ci 0x00000000, 0x00000000, 0x00000000, 0x00000000, 57162306a36Sopenharmony_ci 0x00000000, 0x00000000, 0x00000000, 0x00000000, 57262306a36Sopenharmony_ci 0x00000000, 0x00000000, 0x00000000, 0x00000000, 57362306a36Sopenharmony_ci 0x00000000, 0x00000000, 0x00000000, 0x00000000, 57462306a36Sopenharmony_ci}; 57562306a36Sopenharmony_ci 57662306a36Sopenharmony_cistatic const u32 ice_ptypes_mac_non_ip_ofos[] = { 57762306a36Sopenharmony_ci 0x00000846, 0x00000000, 0x00000000, 0x00000000, 57862306a36Sopenharmony_ci 0x00000000, 0x00000000, 0x00000000, 0x00000000, 57962306a36Sopenharmony_ci 0x00400000, 0x03FFF000, 0x00000000, 0x00000000, 58062306a36Sopenharmony_ci 0x00000000, 0x00000000, 0x00000000, 0x00000000, 58162306a36Sopenharmony_ci 0x00000000, 0x00000000, 0x00000000, 0x00000000, 58262306a36Sopenharmony_ci 0x00000000, 0x00000000, 0x00000000, 0x00000000, 58362306a36Sopenharmony_ci 0x00000000, 0x00000000, 0x00000000, 0x00000000, 58462306a36Sopenharmony_ci 0x00000000, 0x00000000, 0x00000000, 0x00000000, 58562306a36Sopenharmony_ci}; 58662306a36Sopenharmony_ci 58762306a36Sopenharmony_ci/* Manage parameters and info. used during the creation of a flow profile */ 58862306a36Sopenharmony_cistruct ice_flow_prof_params { 58962306a36Sopenharmony_ci enum ice_block blk; 59062306a36Sopenharmony_ci u16 entry_length; /* # of bytes formatted entry will require */ 59162306a36Sopenharmony_ci u8 es_cnt; 59262306a36Sopenharmony_ci struct ice_flow_prof *prof; 59362306a36Sopenharmony_ci 59462306a36Sopenharmony_ci /* For ACL, the es[0] will have the data of ICE_RX_MDID_PKT_FLAGS_15_0 59562306a36Sopenharmony_ci * This will give us the direction flags. 59662306a36Sopenharmony_ci */ 59762306a36Sopenharmony_ci struct ice_fv_word es[ICE_MAX_FV_WORDS]; 59862306a36Sopenharmony_ci /* attributes can be used to add attributes to a particular PTYPE */ 59962306a36Sopenharmony_ci const struct ice_ptype_attributes *attr; 60062306a36Sopenharmony_ci u16 attr_cnt; 60162306a36Sopenharmony_ci 60262306a36Sopenharmony_ci u16 mask[ICE_MAX_FV_WORDS]; 60362306a36Sopenharmony_ci DECLARE_BITMAP(ptypes, ICE_FLOW_PTYPE_MAX); 60462306a36Sopenharmony_ci}; 60562306a36Sopenharmony_ci 60662306a36Sopenharmony_ci#define ICE_FLOW_RSS_HDRS_INNER_MASK \ 60762306a36Sopenharmony_ci (ICE_FLOW_SEG_HDR_PPPOE | ICE_FLOW_SEG_HDR_GTPC | \ 60862306a36Sopenharmony_ci ICE_FLOW_SEG_HDR_GTPC_TEID | ICE_FLOW_SEG_HDR_GTPU | \ 60962306a36Sopenharmony_ci ICE_FLOW_SEG_HDR_PFCP_SESSION | ICE_FLOW_SEG_HDR_L2TPV3 | \ 61062306a36Sopenharmony_ci ICE_FLOW_SEG_HDR_ESP | ICE_FLOW_SEG_HDR_AH | \ 61162306a36Sopenharmony_ci ICE_FLOW_SEG_HDR_NAT_T_ESP) 61262306a36Sopenharmony_ci 61362306a36Sopenharmony_ci#define ICE_FLOW_SEG_HDRS_L3_MASK \ 61462306a36Sopenharmony_ci (ICE_FLOW_SEG_HDR_IPV4 | ICE_FLOW_SEG_HDR_IPV6 | ICE_FLOW_SEG_HDR_ARP) 61562306a36Sopenharmony_ci#define ICE_FLOW_SEG_HDRS_L4_MASK \ 61662306a36Sopenharmony_ci (ICE_FLOW_SEG_HDR_ICMP | ICE_FLOW_SEG_HDR_TCP | ICE_FLOW_SEG_HDR_UDP | \ 61762306a36Sopenharmony_ci ICE_FLOW_SEG_HDR_SCTP) 61862306a36Sopenharmony_ci/* mask for L4 protocols that are NOT part of IPv4/6 OTHER PTYPE groups */ 61962306a36Sopenharmony_ci#define ICE_FLOW_SEG_HDRS_L4_MASK_NO_OTHER \ 62062306a36Sopenharmony_ci (ICE_FLOW_SEG_HDR_TCP | ICE_FLOW_SEG_HDR_UDP | ICE_FLOW_SEG_HDR_SCTP) 62162306a36Sopenharmony_ci 62262306a36Sopenharmony_ci/** 62362306a36Sopenharmony_ci * ice_flow_val_hdrs - validates packet segments for valid protocol headers 62462306a36Sopenharmony_ci * @segs: array of one or more packet segments that describe the flow 62562306a36Sopenharmony_ci * @segs_cnt: number of packet segments provided 62662306a36Sopenharmony_ci */ 62762306a36Sopenharmony_cistatic int ice_flow_val_hdrs(struct ice_flow_seg_info *segs, u8 segs_cnt) 62862306a36Sopenharmony_ci{ 62962306a36Sopenharmony_ci u8 i; 63062306a36Sopenharmony_ci 63162306a36Sopenharmony_ci for (i = 0; i < segs_cnt; i++) { 63262306a36Sopenharmony_ci /* Multiple L3 headers */ 63362306a36Sopenharmony_ci if (segs[i].hdrs & ICE_FLOW_SEG_HDRS_L3_MASK && 63462306a36Sopenharmony_ci !is_power_of_2(segs[i].hdrs & ICE_FLOW_SEG_HDRS_L3_MASK)) 63562306a36Sopenharmony_ci return -EINVAL; 63662306a36Sopenharmony_ci 63762306a36Sopenharmony_ci /* Multiple L4 headers */ 63862306a36Sopenharmony_ci if (segs[i].hdrs & ICE_FLOW_SEG_HDRS_L4_MASK && 63962306a36Sopenharmony_ci !is_power_of_2(segs[i].hdrs & ICE_FLOW_SEG_HDRS_L4_MASK)) 64062306a36Sopenharmony_ci return -EINVAL; 64162306a36Sopenharmony_ci } 64262306a36Sopenharmony_ci 64362306a36Sopenharmony_ci return 0; 64462306a36Sopenharmony_ci} 64562306a36Sopenharmony_ci 64662306a36Sopenharmony_ci/* Sizes of fixed known protocol headers without header options */ 64762306a36Sopenharmony_ci#define ICE_FLOW_PROT_HDR_SZ_MAC 14 64862306a36Sopenharmony_ci#define ICE_FLOW_PROT_HDR_SZ_MAC_VLAN (ICE_FLOW_PROT_HDR_SZ_MAC + 2) 64962306a36Sopenharmony_ci#define ICE_FLOW_PROT_HDR_SZ_IPV4 20 65062306a36Sopenharmony_ci#define ICE_FLOW_PROT_HDR_SZ_IPV6 40 65162306a36Sopenharmony_ci#define ICE_FLOW_PROT_HDR_SZ_ARP 28 65262306a36Sopenharmony_ci#define ICE_FLOW_PROT_HDR_SZ_ICMP 8 65362306a36Sopenharmony_ci#define ICE_FLOW_PROT_HDR_SZ_TCP 20 65462306a36Sopenharmony_ci#define ICE_FLOW_PROT_HDR_SZ_UDP 8 65562306a36Sopenharmony_ci#define ICE_FLOW_PROT_HDR_SZ_SCTP 12 65662306a36Sopenharmony_ci 65762306a36Sopenharmony_ci/** 65862306a36Sopenharmony_ci * ice_flow_calc_seg_sz - calculates size of a packet segment based on headers 65962306a36Sopenharmony_ci * @params: information about the flow to be processed 66062306a36Sopenharmony_ci * @seg: index of packet segment whose header size is to be determined 66162306a36Sopenharmony_ci */ 66262306a36Sopenharmony_cistatic u16 ice_flow_calc_seg_sz(struct ice_flow_prof_params *params, u8 seg) 66362306a36Sopenharmony_ci{ 66462306a36Sopenharmony_ci u16 sz; 66562306a36Sopenharmony_ci 66662306a36Sopenharmony_ci /* L2 headers */ 66762306a36Sopenharmony_ci sz = (params->prof->segs[seg].hdrs & ICE_FLOW_SEG_HDR_VLAN) ? 66862306a36Sopenharmony_ci ICE_FLOW_PROT_HDR_SZ_MAC_VLAN : ICE_FLOW_PROT_HDR_SZ_MAC; 66962306a36Sopenharmony_ci 67062306a36Sopenharmony_ci /* L3 headers */ 67162306a36Sopenharmony_ci if (params->prof->segs[seg].hdrs & ICE_FLOW_SEG_HDR_IPV4) 67262306a36Sopenharmony_ci sz += ICE_FLOW_PROT_HDR_SZ_IPV4; 67362306a36Sopenharmony_ci else if (params->prof->segs[seg].hdrs & ICE_FLOW_SEG_HDR_IPV6) 67462306a36Sopenharmony_ci sz += ICE_FLOW_PROT_HDR_SZ_IPV6; 67562306a36Sopenharmony_ci else if (params->prof->segs[seg].hdrs & ICE_FLOW_SEG_HDR_ARP) 67662306a36Sopenharmony_ci sz += ICE_FLOW_PROT_HDR_SZ_ARP; 67762306a36Sopenharmony_ci else if (params->prof->segs[seg].hdrs & ICE_FLOW_SEG_HDRS_L4_MASK) 67862306a36Sopenharmony_ci /* An L3 header is required if L4 is specified */ 67962306a36Sopenharmony_ci return 0; 68062306a36Sopenharmony_ci 68162306a36Sopenharmony_ci /* L4 headers */ 68262306a36Sopenharmony_ci if (params->prof->segs[seg].hdrs & ICE_FLOW_SEG_HDR_ICMP) 68362306a36Sopenharmony_ci sz += ICE_FLOW_PROT_HDR_SZ_ICMP; 68462306a36Sopenharmony_ci else if (params->prof->segs[seg].hdrs & ICE_FLOW_SEG_HDR_TCP) 68562306a36Sopenharmony_ci sz += ICE_FLOW_PROT_HDR_SZ_TCP; 68662306a36Sopenharmony_ci else if (params->prof->segs[seg].hdrs & ICE_FLOW_SEG_HDR_UDP) 68762306a36Sopenharmony_ci sz += ICE_FLOW_PROT_HDR_SZ_UDP; 68862306a36Sopenharmony_ci else if (params->prof->segs[seg].hdrs & ICE_FLOW_SEG_HDR_SCTP) 68962306a36Sopenharmony_ci sz += ICE_FLOW_PROT_HDR_SZ_SCTP; 69062306a36Sopenharmony_ci 69162306a36Sopenharmony_ci return sz; 69262306a36Sopenharmony_ci} 69362306a36Sopenharmony_ci 69462306a36Sopenharmony_ci/** 69562306a36Sopenharmony_ci * ice_flow_proc_seg_hdrs - process protocol headers present in pkt segments 69662306a36Sopenharmony_ci * @params: information about the flow to be processed 69762306a36Sopenharmony_ci * 69862306a36Sopenharmony_ci * This function identifies the packet types associated with the protocol 69962306a36Sopenharmony_ci * headers being present in packet segments of the specified flow profile. 70062306a36Sopenharmony_ci */ 70162306a36Sopenharmony_cistatic int ice_flow_proc_seg_hdrs(struct ice_flow_prof_params *params) 70262306a36Sopenharmony_ci{ 70362306a36Sopenharmony_ci struct ice_flow_prof *prof; 70462306a36Sopenharmony_ci u8 i; 70562306a36Sopenharmony_ci 70662306a36Sopenharmony_ci memset(params->ptypes, 0xff, sizeof(params->ptypes)); 70762306a36Sopenharmony_ci 70862306a36Sopenharmony_ci prof = params->prof; 70962306a36Sopenharmony_ci 71062306a36Sopenharmony_ci for (i = 0; i < params->prof->segs_cnt; i++) { 71162306a36Sopenharmony_ci const unsigned long *src; 71262306a36Sopenharmony_ci u32 hdrs; 71362306a36Sopenharmony_ci 71462306a36Sopenharmony_ci hdrs = prof->segs[i].hdrs; 71562306a36Sopenharmony_ci 71662306a36Sopenharmony_ci if (hdrs & ICE_FLOW_SEG_HDR_ETH) { 71762306a36Sopenharmony_ci src = !i ? (const unsigned long *)ice_ptypes_mac_ofos : 71862306a36Sopenharmony_ci (const unsigned long *)ice_ptypes_mac_il; 71962306a36Sopenharmony_ci bitmap_and(params->ptypes, params->ptypes, src, 72062306a36Sopenharmony_ci ICE_FLOW_PTYPE_MAX); 72162306a36Sopenharmony_ci } 72262306a36Sopenharmony_ci 72362306a36Sopenharmony_ci if (i && hdrs & ICE_FLOW_SEG_HDR_VLAN) { 72462306a36Sopenharmony_ci src = (const unsigned long *)ice_ptypes_macvlan_il; 72562306a36Sopenharmony_ci bitmap_and(params->ptypes, params->ptypes, src, 72662306a36Sopenharmony_ci ICE_FLOW_PTYPE_MAX); 72762306a36Sopenharmony_ci } 72862306a36Sopenharmony_ci 72962306a36Sopenharmony_ci if (!i && hdrs & ICE_FLOW_SEG_HDR_ARP) { 73062306a36Sopenharmony_ci bitmap_and(params->ptypes, params->ptypes, 73162306a36Sopenharmony_ci (const unsigned long *)ice_ptypes_arp_of, 73262306a36Sopenharmony_ci ICE_FLOW_PTYPE_MAX); 73362306a36Sopenharmony_ci } 73462306a36Sopenharmony_ci 73562306a36Sopenharmony_ci if ((hdrs & ICE_FLOW_SEG_HDR_IPV4) && 73662306a36Sopenharmony_ci (hdrs & ICE_FLOW_SEG_HDR_IPV_OTHER)) { 73762306a36Sopenharmony_ci src = i ? (const unsigned long *)ice_ptypes_ipv4_il : 73862306a36Sopenharmony_ci (const unsigned long *)ice_ptypes_ipv4_ofos_all; 73962306a36Sopenharmony_ci bitmap_and(params->ptypes, params->ptypes, src, 74062306a36Sopenharmony_ci ICE_FLOW_PTYPE_MAX); 74162306a36Sopenharmony_ci } else if ((hdrs & ICE_FLOW_SEG_HDR_IPV6) && 74262306a36Sopenharmony_ci (hdrs & ICE_FLOW_SEG_HDR_IPV_OTHER)) { 74362306a36Sopenharmony_ci src = i ? (const unsigned long *)ice_ptypes_ipv6_il : 74462306a36Sopenharmony_ci (const unsigned long *)ice_ptypes_ipv6_ofos_all; 74562306a36Sopenharmony_ci bitmap_and(params->ptypes, params->ptypes, src, 74662306a36Sopenharmony_ci ICE_FLOW_PTYPE_MAX); 74762306a36Sopenharmony_ci } else if ((hdrs & ICE_FLOW_SEG_HDR_IPV4) && 74862306a36Sopenharmony_ci !(hdrs & ICE_FLOW_SEG_HDRS_L4_MASK_NO_OTHER)) { 74962306a36Sopenharmony_ci src = !i ? (const unsigned long *)ice_ptypes_ipv4_ofos_no_l4 : 75062306a36Sopenharmony_ci (const unsigned long *)ice_ptypes_ipv4_il_no_l4; 75162306a36Sopenharmony_ci bitmap_and(params->ptypes, params->ptypes, src, 75262306a36Sopenharmony_ci ICE_FLOW_PTYPE_MAX); 75362306a36Sopenharmony_ci } else if (hdrs & ICE_FLOW_SEG_HDR_IPV4) { 75462306a36Sopenharmony_ci src = !i ? (const unsigned long *)ice_ptypes_ipv4_ofos : 75562306a36Sopenharmony_ci (const unsigned long *)ice_ptypes_ipv4_il; 75662306a36Sopenharmony_ci bitmap_and(params->ptypes, params->ptypes, src, 75762306a36Sopenharmony_ci ICE_FLOW_PTYPE_MAX); 75862306a36Sopenharmony_ci } else if ((hdrs & ICE_FLOW_SEG_HDR_IPV6) && 75962306a36Sopenharmony_ci !(hdrs & ICE_FLOW_SEG_HDRS_L4_MASK_NO_OTHER)) { 76062306a36Sopenharmony_ci src = !i ? (const unsigned long *)ice_ptypes_ipv6_ofos_no_l4 : 76162306a36Sopenharmony_ci (const unsigned long *)ice_ptypes_ipv6_il_no_l4; 76262306a36Sopenharmony_ci bitmap_and(params->ptypes, params->ptypes, src, 76362306a36Sopenharmony_ci ICE_FLOW_PTYPE_MAX); 76462306a36Sopenharmony_ci } else if (hdrs & ICE_FLOW_SEG_HDR_IPV6) { 76562306a36Sopenharmony_ci src = !i ? (const unsigned long *)ice_ptypes_ipv6_ofos : 76662306a36Sopenharmony_ci (const unsigned long *)ice_ptypes_ipv6_il; 76762306a36Sopenharmony_ci bitmap_and(params->ptypes, params->ptypes, src, 76862306a36Sopenharmony_ci ICE_FLOW_PTYPE_MAX); 76962306a36Sopenharmony_ci } 77062306a36Sopenharmony_ci 77162306a36Sopenharmony_ci if (hdrs & ICE_FLOW_SEG_HDR_ETH_NON_IP) { 77262306a36Sopenharmony_ci src = (const unsigned long *)ice_ptypes_mac_non_ip_ofos; 77362306a36Sopenharmony_ci bitmap_and(params->ptypes, params->ptypes, src, 77462306a36Sopenharmony_ci ICE_FLOW_PTYPE_MAX); 77562306a36Sopenharmony_ci } else if (hdrs & ICE_FLOW_SEG_HDR_PPPOE) { 77662306a36Sopenharmony_ci src = (const unsigned long *)ice_ptypes_pppoe; 77762306a36Sopenharmony_ci bitmap_and(params->ptypes, params->ptypes, src, 77862306a36Sopenharmony_ci ICE_FLOW_PTYPE_MAX); 77962306a36Sopenharmony_ci } else { 78062306a36Sopenharmony_ci src = (const unsigned long *)ice_ptypes_pppoe; 78162306a36Sopenharmony_ci bitmap_andnot(params->ptypes, params->ptypes, src, 78262306a36Sopenharmony_ci ICE_FLOW_PTYPE_MAX); 78362306a36Sopenharmony_ci } 78462306a36Sopenharmony_ci 78562306a36Sopenharmony_ci if (hdrs & ICE_FLOW_SEG_HDR_UDP) { 78662306a36Sopenharmony_ci src = (const unsigned long *)ice_ptypes_udp_il; 78762306a36Sopenharmony_ci bitmap_and(params->ptypes, params->ptypes, src, 78862306a36Sopenharmony_ci ICE_FLOW_PTYPE_MAX); 78962306a36Sopenharmony_ci } else if (hdrs & ICE_FLOW_SEG_HDR_TCP) { 79062306a36Sopenharmony_ci bitmap_and(params->ptypes, params->ptypes, 79162306a36Sopenharmony_ci (const unsigned long *)ice_ptypes_tcp_il, 79262306a36Sopenharmony_ci ICE_FLOW_PTYPE_MAX); 79362306a36Sopenharmony_ci } else if (hdrs & ICE_FLOW_SEG_HDR_SCTP) { 79462306a36Sopenharmony_ci src = (const unsigned long *)ice_ptypes_sctp_il; 79562306a36Sopenharmony_ci bitmap_and(params->ptypes, params->ptypes, src, 79662306a36Sopenharmony_ci ICE_FLOW_PTYPE_MAX); 79762306a36Sopenharmony_ci } 79862306a36Sopenharmony_ci 79962306a36Sopenharmony_ci if (hdrs & ICE_FLOW_SEG_HDR_ICMP) { 80062306a36Sopenharmony_ci src = !i ? (const unsigned long *)ice_ptypes_icmp_of : 80162306a36Sopenharmony_ci (const unsigned long *)ice_ptypes_icmp_il; 80262306a36Sopenharmony_ci bitmap_and(params->ptypes, params->ptypes, src, 80362306a36Sopenharmony_ci ICE_FLOW_PTYPE_MAX); 80462306a36Sopenharmony_ci } else if (hdrs & ICE_FLOW_SEG_HDR_GRE) { 80562306a36Sopenharmony_ci if (!i) { 80662306a36Sopenharmony_ci src = (const unsigned long *)ice_ptypes_gre_of; 80762306a36Sopenharmony_ci bitmap_and(params->ptypes, params->ptypes, 80862306a36Sopenharmony_ci src, ICE_FLOW_PTYPE_MAX); 80962306a36Sopenharmony_ci } 81062306a36Sopenharmony_ci } else if (hdrs & ICE_FLOW_SEG_HDR_GTPC) { 81162306a36Sopenharmony_ci src = (const unsigned long *)ice_ptypes_gtpc; 81262306a36Sopenharmony_ci bitmap_and(params->ptypes, params->ptypes, src, 81362306a36Sopenharmony_ci ICE_FLOW_PTYPE_MAX); 81462306a36Sopenharmony_ci } else if (hdrs & ICE_FLOW_SEG_HDR_GTPC_TEID) { 81562306a36Sopenharmony_ci src = (const unsigned long *)ice_ptypes_gtpc_tid; 81662306a36Sopenharmony_ci bitmap_and(params->ptypes, params->ptypes, src, 81762306a36Sopenharmony_ci ICE_FLOW_PTYPE_MAX); 81862306a36Sopenharmony_ci } else if (hdrs & ICE_FLOW_SEG_HDR_GTPU_DWN) { 81962306a36Sopenharmony_ci src = (const unsigned long *)ice_ptypes_gtpu; 82062306a36Sopenharmony_ci bitmap_and(params->ptypes, params->ptypes, src, 82162306a36Sopenharmony_ci ICE_FLOW_PTYPE_MAX); 82262306a36Sopenharmony_ci 82362306a36Sopenharmony_ci /* Attributes for GTP packet with downlink */ 82462306a36Sopenharmony_ci params->attr = ice_attr_gtpu_down; 82562306a36Sopenharmony_ci params->attr_cnt = ARRAY_SIZE(ice_attr_gtpu_down); 82662306a36Sopenharmony_ci } else if (hdrs & ICE_FLOW_SEG_HDR_GTPU_UP) { 82762306a36Sopenharmony_ci src = (const unsigned long *)ice_ptypes_gtpu; 82862306a36Sopenharmony_ci bitmap_and(params->ptypes, params->ptypes, src, 82962306a36Sopenharmony_ci ICE_FLOW_PTYPE_MAX); 83062306a36Sopenharmony_ci 83162306a36Sopenharmony_ci /* Attributes for GTP packet with uplink */ 83262306a36Sopenharmony_ci params->attr = ice_attr_gtpu_up; 83362306a36Sopenharmony_ci params->attr_cnt = ARRAY_SIZE(ice_attr_gtpu_up); 83462306a36Sopenharmony_ci } else if (hdrs & ICE_FLOW_SEG_HDR_GTPU_EH) { 83562306a36Sopenharmony_ci src = (const unsigned long *)ice_ptypes_gtpu; 83662306a36Sopenharmony_ci bitmap_and(params->ptypes, params->ptypes, src, 83762306a36Sopenharmony_ci ICE_FLOW_PTYPE_MAX); 83862306a36Sopenharmony_ci 83962306a36Sopenharmony_ci /* Attributes for GTP packet with Extension Header */ 84062306a36Sopenharmony_ci params->attr = ice_attr_gtpu_eh; 84162306a36Sopenharmony_ci params->attr_cnt = ARRAY_SIZE(ice_attr_gtpu_eh); 84262306a36Sopenharmony_ci } else if (hdrs & ICE_FLOW_SEG_HDR_GTPU_IP) { 84362306a36Sopenharmony_ci src = (const unsigned long *)ice_ptypes_gtpu; 84462306a36Sopenharmony_ci bitmap_and(params->ptypes, params->ptypes, src, 84562306a36Sopenharmony_ci ICE_FLOW_PTYPE_MAX); 84662306a36Sopenharmony_ci } else if (hdrs & ICE_FLOW_SEG_HDR_L2TPV3) { 84762306a36Sopenharmony_ci src = (const unsigned long *)ice_ptypes_l2tpv3; 84862306a36Sopenharmony_ci bitmap_and(params->ptypes, params->ptypes, src, 84962306a36Sopenharmony_ci ICE_FLOW_PTYPE_MAX); 85062306a36Sopenharmony_ci } else if (hdrs & ICE_FLOW_SEG_HDR_ESP) { 85162306a36Sopenharmony_ci src = (const unsigned long *)ice_ptypes_esp; 85262306a36Sopenharmony_ci bitmap_and(params->ptypes, params->ptypes, src, 85362306a36Sopenharmony_ci ICE_FLOW_PTYPE_MAX); 85462306a36Sopenharmony_ci } else if (hdrs & ICE_FLOW_SEG_HDR_AH) { 85562306a36Sopenharmony_ci src = (const unsigned long *)ice_ptypes_ah; 85662306a36Sopenharmony_ci bitmap_and(params->ptypes, params->ptypes, src, 85762306a36Sopenharmony_ci ICE_FLOW_PTYPE_MAX); 85862306a36Sopenharmony_ci } else if (hdrs & ICE_FLOW_SEG_HDR_NAT_T_ESP) { 85962306a36Sopenharmony_ci src = (const unsigned long *)ice_ptypes_nat_t_esp; 86062306a36Sopenharmony_ci bitmap_and(params->ptypes, params->ptypes, src, 86162306a36Sopenharmony_ci ICE_FLOW_PTYPE_MAX); 86262306a36Sopenharmony_ci } 86362306a36Sopenharmony_ci 86462306a36Sopenharmony_ci if (hdrs & ICE_FLOW_SEG_HDR_PFCP) { 86562306a36Sopenharmony_ci if (hdrs & ICE_FLOW_SEG_HDR_PFCP_NODE) 86662306a36Sopenharmony_ci src = (const unsigned long *)ice_ptypes_pfcp_node; 86762306a36Sopenharmony_ci else 86862306a36Sopenharmony_ci src = (const unsigned long *)ice_ptypes_pfcp_session; 86962306a36Sopenharmony_ci 87062306a36Sopenharmony_ci bitmap_and(params->ptypes, params->ptypes, src, 87162306a36Sopenharmony_ci ICE_FLOW_PTYPE_MAX); 87262306a36Sopenharmony_ci } else { 87362306a36Sopenharmony_ci src = (const unsigned long *)ice_ptypes_pfcp_node; 87462306a36Sopenharmony_ci bitmap_andnot(params->ptypes, params->ptypes, src, 87562306a36Sopenharmony_ci ICE_FLOW_PTYPE_MAX); 87662306a36Sopenharmony_ci 87762306a36Sopenharmony_ci src = (const unsigned long *)ice_ptypes_pfcp_session; 87862306a36Sopenharmony_ci bitmap_andnot(params->ptypes, params->ptypes, src, 87962306a36Sopenharmony_ci ICE_FLOW_PTYPE_MAX); 88062306a36Sopenharmony_ci } 88162306a36Sopenharmony_ci } 88262306a36Sopenharmony_ci 88362306a36Sopenharmony_ci return 0; 88462306a36Sopenharmony_ci} 88562306a36Sopenharmony_ci 88662306a36Sopenharmony_ci/** 88762306a36Sopenharmony_ci * ice_flow_xtract_fld - Create an extraction sequence entry for the given field 88862306a36Sopenharmony_ci * @hw: pointer to the HW struct 88962306a36Sopenharmony_ci * @params: information about the flow to be processed 89062306a36Sopenharmony_ci * @seg: packet segment index of the field to be extracted 89162306a36Sopenharmony_ci * @fld: ID of field to be extracted 89262306a36Sopenharmony_ci * @match: bit field of all fields 89362306a36Sopenharmony_ci * 89462306a36Sopenharmony_ci * This function determines the protocol ID, offset, and size of the given 89562306a36Sopenharmony_ci * field. It then allocates one or more extraction sequence entries for the 89662306a36Sopenharmony_ci * given field, and fill the entries with protocol ID and offset information. 89762306a36Sopenharmony_ci */ 89862306a36Sopenharmony_cistatic int 89962306a36Sopenharmony_ciice_flow_xtract_fld(struct ice_hw *hw, struct ice_flow_prof_params *params, 90062306a36Sopenharmony_ci u8 seg, enum ice_flow_field fld, u64 match) 90162306a36Sopenharmony_ci{ 90262306a36Sopenharmony_ci enum ice_flow_field sib = ICE_FLOW_FIELD_IDX_MAX; 90362306a36Sopenharmony_ci enum ice_prot_id prot_id = ICE_PROT_ID_INVAL; 90462306a36Sopenharmony_ci u8 fv_words = hw->blk[params->blk].es.fvw; 90562306a36Sopenharmony_ci struct ice_flow_fld_info *flds; 90662306a36Sopenharmony_ci u16 cnt, ese_bits, i; 90762306a36Sopenharmony_ci u16 sib_mask = 0; 90862306a36Sopenharmony_ci u16 mask; 90962306a36Sopenharmony_ci u16 off; 91062306a36Sopenharmony_ci 91162306a36Sopenharmony_ci flds = params->prof->segs[seg].fields; 91262306a36Sopenharmony_ci 91362306a36Sopenharmony_ci switch (fld) { 91462306a36Sopenharmony_ci case ICE_FLOW_FIELD_IDX_ETH_DA: 91562306a36Sopenharmony_ci case ICE_FLOW_FIELD_IDX_ETH_SA: 91662306a36Sopenharmony_ci case ICE_FLOW_FIELD_IDX_S_VLAN: 91762306a36Sopenharmony_ci case ICE_FLOW_FIELD_IDX_C_VLAN: 91862306a36Sopenharmony_ci prot_id = seg == 0 ? ICE_PROT_MAC_OF_OR_S : ICE_PROT_MAC_IL; 91962306a36Sopenharmony_ci break; 92062306a36Sopenharmony_ci case ICE_FLOW_FIELD_IDX_ETH_TYPE: 92162306a36Sopenharmony_ci prot_id = seg == 0 ? ICE_PROT_ETYPE_OL : ICE_PROT_ETYPE_IL; 92262306a36Sopenharmony_ci break; 92362306a36Sopenharmony_ci case ICE_FLOW_FIELD_IDX_IPV4_DSCP: 92462306a36Sopenharmony_ci prot_id = seg == 0 ? ICE_PROT_IPV4_OF_OR_S : ICE_PROT_IPV4_IL; 92562306a36Sopenharmony_ci break; 92662306a36Sopenharmony_ci case ICE_FLOW_FIELD_IDX_IPV6_DSCP: 92762306a36Sopenharmony_ci prot_id = seg == 0 ? ICE_PROT_IPV6_OF_OR_S : ICE_PROT_IPV6_IL; 92862306a36Sopenharmony_ci break; 92962306a36Sopenharmony_ci case ICE_FLOW_FIELD_IDX_IPV4_TTL: 93062306a36Sopenharmony_ci case ICE_FLOW_FIELD_IDX_IPV4_PROT: 93162306a36Sopenharmony_ci prot_id = seg == 0 ? ICE_PROT_IPV4_OF_OR_S : ICE_PROT_IPV4_IL; 93262306a36Sopenharmony_ci 93362306a36Sopenharmony_ci /* TTL and PROT share the same extraction seq. entry. 93462306a36Sopenharmony_ci * Each is considered a sibling to the other in terms of sharing 93562306a36Sopenharmony_ci * the same extraction sequence entry. 93662306a36Sopenharmony_ci */ 93762306a36Sopenharmony_ci if (fld == ICE_FLOW_FIELD_IDX_IPV4_TTL) 93862306a36Sopenharmony_ci sib = ICE_FLOW_FIELD_IDX_IPV4_PROT; 93962306a36Sopenharmony_ci else if (fld == ICE_FLOW_FIELD_IDX_IPV4_PROT) 94062306a36Sopenharmony_ci sib = ICE_FLOW_FIELD_IDX_IPV4_TTL; 94162306a36Sopenharmony_ci 94262306a36Sopenharmony_ci /* If the sibling field is also included, that field's 94362306a36Sopenharmony_ci * mask needs to be included. 94462306a36Sopenharmony_ci */ 94562306a36Sopenharmony_ci if (match & BIT(sib)) 94662306a36Sopenharmony_ci sib_mask = ice_flds_info[sib].mask; 94762306a36Sopenharmony_ci break; 94862306a36Sopenharmony_ci case ICE_FLOW_FIELD_IDX_IPV6_TTL: 94962306a36Sopenharmony_ci case ICE_FLOW_FIELD_IDX_IPV6_PROT: 95062306a36Sopenharmony_ci prot_id = seg == 0 ? ICE_PROT_IPV6_OF_OR_S : ICE_PROT_IPV6_IL; 95162306a36Sopenharmony_ci 95262306a36Sopenharmony_ci /* TTL and PROT share the same extraction seq. entry. 95362306a36Sopenharmony_ci * Each is considered a sibling to the other in terms of sharing 95462306a36Sopenharmony_ci * the same extraction sequence entry. 95562306a36Sopenharmony_ci */ 95662306a36Sopenharmony_ci if (fld == ICE_FLOW_FIELD_IDX_IPV6_TTL) 95762306a36Sopenharmony_ci sib = ICE_FLOW_FIELD_IDX_IPV6_PROT; 95862306a36Sopenharmony_ci else if (fld == ICE_FLOW_FIELD_IDX_IPV6_PROT) 95962306a36Sopenharmony_ci sib = ICE_FLOW_FIELD_IDX_IPV6_TTL; 96062306a36Sopenharmony_ci 96162306a36Sopenharmony_ci /* If the sibling field is also included, that field's 96262306a36Sopenharmony_ci * mask needs to be included. 96362306a36Sopenharmony_ci */ 96462306a36Sopenharmony_ci if (match & BIT(sib)) 96562306a36Sopenharmony_ci sib_mask = ice_flds_info[sib].mask; 96662306a36Sopenharmony_ci break; 96762306a36Sopenharmony_ci case ICE_FLOW_FIELD_IDX_IPV4_SA: 96862306a36Sopenharmony_ci case ICE_FLOW_FIELD_IDX_IPV4_DA: 96962306a36Sopenharmony_ci prot_id = seg == 0 ? ICE_PROT_IPV4_OF_OR_S : ICE_PROT_IPV4_IL; 97062306a36Sopenharmony_ci break; 97162306a36Sopenharmony_ci case ICE_FLOW_FIELD_IDX_IPV6_SA: 97262306a36Sopenharmony_ci case ICE_FLOW_FIELD_IDX_IPV6_DA: 97362306a36Sopenharmony_ci prot_id = seg == 0 ? ICE_PROT_IPV6_OF_OR_S : ICE_PROT_IPV6_IL; 97462306a36Sopenharmony_ci break; 97562306a36Sopenharmony_ci case ICE_FLOW_FIELD_IDX_TCP_SRC_PORT: 97662306a36Sopenharmony_ci case ICE_FLOW_FIELD_IDX_TCP_DST_PORT: 97762306a36Sopenharmony_ci case ICE_FLOW_FIELD_IDX_TCP_FLAGS: 97862306a36Sopenharmony_ci prot_id = ICE_PROT_TCP_IL; 97962306a36Sopenharmony_ci break; 98062306a36Sopenharmony_ci case ICE_FLOW_FIELD_IDX_UDP_SRC_PORT: 98162306a36Sopenharmony_ci case ICE_FLOW_FIELD_IDX_UDP_DST_PORT: 98262306a36Sopenharmony_ci prot_id = ICE_PROT_UDP_IL_OR_S; 98362306a36Sopenharmony_ci break; 98462306a36Sopenharmony_ci case ICE_FLOW_FIELD_IDX_SCTP_SRC_PORT: 98562306a36Sopenharmony_ci case ICE_FLOW_FIELD_IDX_SCTP_DST_PORT: 98662306a36Sopenharmony_ci prot_id = ICE_PROT_SCTP_IL; 98762306a36Sopenharmony_ci break; 98862306a36Sopenharmony_ci case ICE_FLOW_FIELD_IDX_GTPC_TEID: 98962306a36Sopenharmony_ci case ICE_FLOW_FIELD_IDX_GTPU_IP_TEID: 99062306a36Sopenharmony_ci case ICE_FLOW_FIELD_IDX_GTPU_UP_TEID: 99162306a36Sopenharmony_ci case ICE_FLOW_FIELD_IDX_GTPU_DWN_TEID: 99262306a36Sopenharmony_ci case ICE_FLOW_FIELD_IDX_GTPU_EH_TEID: 99362306a36Sopenharmony_ci case ICE_FLOW_FIELD_IDX_GTPU_EH_QFI: 99462306a36Sopenharmony_ci /* GTP is accessed through UDP OF protocol */ 99562306a36Sopenharmony_ci prot_id = ICE_PROT_UDP_OF; 99662306a36Sopenharmony_ci break; 99762306a36Sopenharmony_ci case ICE_FLOW_FIELD_IDX_PPPOE_SESS_ID: 99862306a36Sopenharmony_ci prot_id = ICE_PROT_PPPOE; 99962306a36Sopenharmony_ci break; 100062306a36Sopenharmony_ci case ICE_FLOW_FIELD_IDX_PFCP_SEID: 100162306a36Sopenharmony_ci prot_id = ICE_PROT_UDP_IL_OR_S; 100262306a36Sopenharmony_ci break; 100362306a36Sopenharmony_ci case ICE_FLOW_FIELD_IDX_L2TPV3_SESS_ID: 100462306a36Sopenharmony_ci prot_id = ICE_PROT_L2TPV3; 100562306a36Sopenharmony_ci break; 100662306a36Sopenharmony_ci case ICE_FLOW_FIELD_IDX_ESP_SPI: 100762306a36Sopenharmony_ci prot_id = ICE_PROT_ESP_F; 100862306a36Sopenharmony_ci break; 100962306a36Sopenharmony_ci case ICE_FLOW_FIELD_IDX_AH_SPI: 101062306a36Sopenharmony_ci prot_id = ICE_PROT_ESP_2; 101162306a36Sopenharmony_ci break; 101262306a36Sopenharmony_ci case ICE_FLOW_FIELD_IDX_NAT_T_ESP_SPI: 101362306a36Sopenharmony_ci prot_id = ICE_PROT_UDP_IL_OR_S; 101462306a36Sopenharmony_ci break; 101562306a36Sopenharmony_ci case ICE_FLOW_FIELD_IDX_ARP_SIP: 101662306a36Sopenharmony_ci case ICE_FLOW_FIELD_IDX_ARP_DIP: 101762306a36Sopenharmony_ci case ICE_FLOW_FIELD_IDX_ARP_SHA: 101862306a36Sopenharmony_ci case ICE_FLOW_FIELD_IDX_ARP_DHA: 101962306a36Sopenharmony_ci case ICE_FLOW_FIELD_IDX_ARP_OP: 102062306a36Sopenharmony_ci prot_id = ICE_PROT_ARP_OF; 102162306a36Sopenharmony_ci break; 102262306a36Sopenharmony_ci case ICE_FLOW_FIELD_IDX_ICMP_TYPE: 102362306a36Sopenharmony_ci case ICE_FLOW_FIELD_IDX_ICMP_CODE: 102462306a36Sopenharmony_ci /* ICMP type and code share the same extraction seq. entry */ 102562306a36Sopenharmony_ci prot_id = (params->prof->segs[seg].hdrs & ICE_FLOW_SEG_HDR_IPV4) ? 102662306a36Sopenharmony_ci ICE_PROT_ICMP_IL : ICE_PROT_ICMPV6_IL; 102762306a36Sopenharmony_ci sib = fld == ICE_FLOW_FIELD_IDX_ICMP_TYPE ? 102862306a36Sopenharmony_ci ICE_FLOW_FIELD_IDX_ICMP_CODE : 102962306a36Sopenharmony_ci ICE_FLOW_FIELD_IDX_ICMP_TYPE; 103062306a36Sopenharmony_ci break; 103162306a36Sopenharmony_ci case ICE_FLOW_FIELD_IDX_GRE_KEYID: 103262306a36Sopenharmony_ci prot_id = ICE_PROT_GRE_OF; 103362306a36Sopenharmony_ci break; 103462306a36Sopenharmony_ci default: 103562306a36Sopenharmony_ci return -EOPNOTSUPP; 103662306a36Sopenharmony_ci } 103762306a36Sopenharmony_ci 103862306a36Sopenharmony_ci /* Each extraction sequence entry is a word in size, and extracts a 103962306a36Sopenharmony_ci * word-aligned offset from a protocol header. 104062306a36Sopenharmony_ci */ 104162306a36Sopenharmony_ci ese_bits = ICE_FLOW_FV_EXTRACT_SZ * BITS_PER_BYTE; 104262306a36Sopenharmony_ci 104362306a36Sopenharmony_ci flds[fld].xtrct.prot_id = prot_id; 104462306a36Sopenharmony_ci flds[fld].xtrct.off = (ice_flds_info[fld].off / ese_bits) * 104562306a36Sopenharmony_ci ICE_FLOW_FV_EXTRACT_SZ; 104662306a36Sopenharmony_ci flds[fld].xtrct.disp = (u8)(ice_flds_info[fld].off % ese_bits); 104762306a36Sopenharmony_ci flds[fld].xtrct.idx = params->es_cnt; 104862306a36Sopenharmony_ci flds[fld].xtrct.mask = ice_flds_info[fld].mask; 104962306a36Sopenharmony_ci 105062306a36Sopenharmony_ci /* Adjust the next field-entry index after accommodating the number of 105162306a36Sopenharmony_ci * entries this field consumes 105262306a36Sopenharmony_ci */ 105362306a36Sopenharmony_ci cnt = DIV_ROUND_UP(flds[fld].xtrct.disp + ice_flds_info[fld].size, 105462306a36Sopenharmony_ci ese_bits); 105562306a36Sopenharmony_ci 105662306a36Sopenharmony_ci /* Fill in the extraction sequence entries needed for this field */ 105762306a36Sopenharmony_ci off = flds[fld].xtrct.off; 105862306a36Sopenharmony_ci mask = flds[fld].xtrct.mask; 105962306a36Sopenharmony_ci for (i = 0; i < cnt; i++) { 106062306a36Sopenharmony_ci /* Only consume an extraction sequence entry if there is no 106162306a36Sopenharmony_ci * sibling field associated with this field or the sibling entry 106262306a36Sopenharmony_ci * already extracts the word shared with this field. 106362306a36Sopenharmony_ci */ 106462306a36Sopenharmony_ci if (sib == ICE_FLOW_FIELD_IDX_MAX || 106562306a36Sopenharmony_ci flds[sib].xtrct.prot_id == ICE_PROT_ID_INVAL || 106662306a36Sopenharmony_ci flds[sib].xtrct.off != off) { 106762306a36Sopenharmony_ci u8 idx; 106862306a36Sopenharmony_ci 106962306a36Sopenharmony_ci /* Make sure the number of extraction sequence required 107062306a36Sopenharmony_ci * does not exceed the block's capability 107162306a36Sopenharmony_ci */ 107262306a36Sopenharmony_ci if (params->es_cnt >= fv_words) 107362306a36Sopenharmony_ci return -ENOSPC; 107462306a36Sopenharmony_ci 107562306a36Sopenharmony_ci /* some blocks require a reversed field vector layout */ 107662306a36Sopenharmony_ci if (hw->blk[params->blk].es.reverse) 107762306a36Sopenharmony_ci idx = fv_words - params->es_cnt - 1; 107862306a36Sopenharmony_ci else 107962306a36Sopenharmony_ci idx = params->es_cnt; 108062306a36Sopenharmony_ci 108162306a36Sopenharmony_ci params->es[idx].prot_id = prot_id; 108262306a36Sopenharmony_ci params->es[idx].off = off; 108362306a36Sopenharmony_ci params->mask[idx] = mask | sib_mask; 108462306a36Sopenharmony_ci params->es_cnt++; 108562306a36Sopenharmony_ci } 108662306a36Sopenharmony_ci 108762306a36Sopenharmony_ci off += ICE_FLOW_FV_EXTRACT_SZ; 108862306a36Sopenharmony_ci } 108962306a36Sopenharmony_ci 109062306a36Sopenharmony_ci return 0; 109162306a36Sopenharmony_ci} 109262306a36Sopenharmony_ci 109362306a36Sopenharmony_ci/** 109462306a36Sopenharmony_ci * ice_flow_xtract_raws - Create extract sequence entries for raw bytes 109562306a36Sopenharmony_ci * @hw: pointer to the HW struct 109662306a36Sopenharmony_ci * @params: information about the flow to be processed 109762306a36Sopenharmony_ci * @seg: index of packet segment whose raw fields are to be extracted 109862306a36Sopenharmony_ci */ 109962306a36Sopenharmony_cistatic int 110062306a36Sopenharmony_ciice_flow_xtract_raws(struct ice_hw *hw, struct ice_flow_prof_params *params, 110162306a36Sopenharmony_ci u8 seg) 110262306a36Sopenharmony_ci{ 110362306a36Sopenharmony_ci u16 fv_words; 110462306a36Sopenharmony_ci u16 hdrs_sz; 110562306a36Sopenharmony_ci u8 i; 110662306a36Sopenharmony_ci 110762306a36Sopenharmony_ci if (!params->prof->segs[seg].raws_cnt) 110862306a36Sopenharmony_ci return 0; 110962306a36Sopenharmony_ci 111062306a36Sopenharmony_ci if (params->prof->segs[seg].raws_cnt > 111162306a36Sopenharmony_ci ARRAY_SIZE(params->prof->segs[seg].raws)) 111262306a36Sopenharmony_ci return -ENOSPC; 111362306a36Sopenharmony_ci 111462306a36Sopenharmony_ci /* Offsets within the segment headers are not supported */ 111562306a36Sopenharmony_ci hdrs_sz = ice_flow_calc_seg_sz(params, seg); 111662306a36Sopenharmony_ci if (!hdrs_sz) 111762306a36Sopenharmony_ci return -EINVAL; 111862306a36Sopenharmony_ci 111962306a36Sopenharmony_ci fv_words = hw->blk[params->blk].es.fvw; 112062306a36Sopenharmony_ci 112162306a36Sopenharmony_ci for (i = 0; i < params->prof->segs[seg].raws_cnt; i++) { 112262306a36Sopenharmony_ci struct ice_flow_seg_fld_raw *raw; 112362306a36Sopenharmony_ci u16 off, cnt, j; 112462306a36Sopenharmony_ci 112562306a36Sopenharmony_ci raw = ¶ms->prof->segs[seg].raws[i]; 112662306a36Sopenharmony_ci 112762306a36Sopenharmony_ci /* Storing extraction information */ 112862306a36Sopenharmony_ci raw->info.xtrct.prot_id = ICE_PROT_MAC_OF_OR_S; 112962306a36Sopenharmony_ci raw->info.xtrct.off = (raw->off / ICE_FLOW_FV_EXTRACT_SZ) * 113062306a36Sopenharmony_ci ICE_FLOW_FV_EXTRACT_SZ; 113162306a36Sopenharmony_ci raw->info.xtrct.disp = (raw->off % ICE_FLOW_FV_EXTRACT_SZ) * 113262306a36Sopenharmony_ci BITS_PER_BYTE; 113362306a36Sopenharmony_ci raw->info.xtrct.idx = params->es_cnt; 113462306a36Sopenharmony_ci 113562306a36Sopenharmony_ci /* Determine the number of field vector entries this raw field 113662306a36Sopenharmony_ci * consumes. 113762306a36Sopenharmony_ci */ 113862306a36Sopenharmony_ci cnt = DIV_ROUND_UP(raw->info.xtrct.disp + 113962306a36Sopenharmony_ci (raw->info.src.last * BITS_PER_BYTE), 114062306a36Sopenharmony_ci (ICE_FLOW_FV_EXTRACT_SZ * BITS_PER_BYTE)); 114162306a36Sopenharmony_ci off = raw->info.xtrct.off; 114262306a36Sopenharmony_ci for (j = 0; j < cnt; j++) { 114362306a36Sopenharmony_ci u16 idx; 114462306a36Sopenharmony_ci 114562306a36Sopenharmony_ci /* Make sure the number of extraction sequence required 114662306a36Sopenharmony_ci * does not exceed the block's capability 114762306a36Sopenharmony_ci */ 114862306a36Sopenharmony_ci if (params->es_cnt >= hw->blk[params->blk].es.count || 114962306a36Sopenharmony_ci params->es_cnt >= ICE_MAX_FV_WORDS) 115062306a36Sopenharmony_ci return -ENOSPC; 115162306a36Sopenharmony_ci 115262306a36Sopenharmony_ci /* some blocks require a reversed field vector layout */ 115362306a36Sopenharmony_ci if (hw->blk[params->blk].es.reverse) 115462306a36Sopenharmony_ci idx = fv_words - params->es_cnt - 1; 115562306a36Sopenharmony_ci else 115662306a36Sopenharmony_ci idx = params->es_cnt; 115762306a36Sopenharmony_ci 115862306a36Sopenharmony_ci params->es[idx].prot_id = raw->info.xtrct.prot_id; 115962306a36Sopenharmony_ci params->es[idx].off = off; 116062306a36Sopenharmony_ci params->es_cnt++; 116162306a36Sopenharmony_ci off += ICE_FLOW_FV_EXTRACT_SZ; 116262306a36Sopenharmony_ci } 116362306a36Sopenharmony_ci } 116462306a36Sopenharmony_ci 116562306a36Sopenharmony_ci return 0; 116662306a36Sopenharmony_ci} 116762306a36Sopenharmony_ci 116862306a36Sopenharmony_ci/** 116962306a36Sopenharmony_ci * ice_flow_create_xtrct_seq - Create an extraction sequence for given segments 117062306a36Sopenharmony_ci * @hw: pointer to the HW struct 117162306a36Sopenharmony_ci * @params: information about the flow to be processed 117262306a36Sopenharmony_ci * 117362306a36Sopenharmony_ci * This function iterates through all matched fields in the given segments, and 117462306a36Sopenharmony_ci * creates an extraction sequence for the fields. 117562306a36Sopenharmony_ci */ 117662306a36Sopenharmony_cistatic int 117762306a36Sopenharmony_ciice_flow_create_xtrct_seq(struct ice_hw *hw, 117862306a36Sopenharmony_ci struct ice_flow_prof_params *params) 117962306a36Sopenharmony_ci{ 118062306a36Sopenharmony_ci struct ice_flow_prof *prof = params->prof; 118162306a36Sopenharmony_ci int status = 0; 118262306a36Sopenharmony_ci u8 i; 118362306a36Sopenharmony_ci 118462306a36Sopenharmony_ci for (i = 0; i < prof->segs_cnt; i++) { 118562306a36Sopenharmony_ci u64 match = params->prof->segs[i].match; 118662306a36Sopenharmony_ci enum ice_flow_field j; 118762306a36Sopenharmony_ci 118862306a36Sopenharmony_ci for_each_set_bit(j, (unsigned long *)&match, 118962306a36Sopenharmony_ci ICE_FLOW_FIELD_IDX_MAX) { 119062306a36Sopenharmony_ci status = ice_flow_xtract_fld(hw, params, i, j, match); 119162306a36Sopenharmony_ci if (status) 119262306a36Sopenharmony_ci return status; 119362306a36Sopenharmony_ci clear_bit(j, (unsigned long *)&match); 119462306a36Sopenharmony_ci } 119562306a36Sopenharmony_ci 119662306a36Sopenharmony_ci /* Process raw matching bytes */ 119762306a36Sopenharmony_ci status = ice_flow_xtract_raws(hw, params, i); 119862306a36Sopenharmony_ci if (status) 119962306a36Sopenharmony_ci return status; 120062306a36Sopenharmony_ci } 120162306a36Sopenharmony_ci 120262306a36Sopenharmony_ci return status; 120362306a36Sopenharmony_ci} 120462306a36Sopenharmony_ci 120562306a36Sopenharmony_ci/** 120662306a36Sopenharmony_ci * ice_flow_proc_segs - process all packet segments associated with a profile 120762306a36Sopenharmony_ci * @hw: pointer to the HW struct 120862306a36Sopenharmony_ci * @params: information about the flow to be processed 120962306a36Sopenharmony_ci */ 121062306a36Sopenharmony_cistatic int 121162306a36Sopenharmony_ciice_flow_proc_segs(struct ice_hw *hw, struct ice_flow_prof_params *params) 121262306a36Sopenharmony_ci{ 121362306a36Sopenharmony_ci int status; 121462306a36Sopenharmony_ci 121562306a36Sopenharmony_ci status = ice_flow_proc_seg_hdrs(params); 121662306a36Sopenharmony_ci if (status) 121762306a36Sopenharmony_ci return status; 121862306a36Sopenharmony_ci 121962306a36Sopenharmony_ci status = ice_flow_create_xtrct_seq(hw, params); 122062306a36Sopenharmony_ci if (status) 122162306a36Sopenharmony_ci return status; 122262306a36Sopenharmony_ci 122362306a36Sopenharmony_ci switch (params->blk) { 122462306a36Sopenharmony_ci case ICE_BLK_FD: 122562306a36Sopenharmony_ci case ICE_BLK_RSS: 122662306a36Sopenharmony_ci status = 0; 122762306a36Sopenharmony_ci break; 122862306a36Sopenharmony_ci default: 122962306a36Sopenharmony_ci return -EOPNOTSUPP; 123062306a36Sopenharmony_ci } 123162306a36Sopenharmony_ci 123262306a36Sopenharmony_ci return status; 123362306a36Sopenharmony_ci} 123462306a36Sopenharmony_ci 123562306a36Sopenharmony_ci#define ICE_FLOW_FIND_PROF_CHK_FLDS 0x00000001 123662306a36Sopenharmony_ci#define ICE_FLOW_FIND_PROF_CHK_VSI 0x00000002 123762306a36Sopenharmony_ci#define ICE_FLOW_FIND_PROF_NOT_CHK_DIR 0x00000004 123862306a36Sopenharmony_ci 123962306a36Sopenharmony_ci/** 124062306a36Sopenharmony_ci * ice_flow_find_prof_conds - Find a profile matching headers and conditions 124162306a36Sopenharmony_ci * @hw: pointer to the HW struct 124262306a36Sopenharmony_ci * @blk: classification stage 124362306a36Sopenharmony_ci * @dir: flow direction 124462306a36Sopenharmony_ci * @segs: array of one or more packet segments that describe the flow 124562306a36Sopenharmony_ci * @segs_cnt: number of packet segments provided 124662306a36Sopenharmony_ci * @vsi_handle: software VSI handle to check VSI (ICE_FLOW_FIND_PROF_CHK_VSI) 124762306a36Sopenharmony_ci * @conds: additional conditions to be checked (ICE_FLOW_FIND_PROF_CHK_*) 124862306a36Sopenharmony_ci */ 124962306a36Sopenharmony_cistatic struct ice_flow_prof * 125062306a36Sopenharmony_ciice_flow_find_prof_conds(struct ice_hw *hw, enum ice_block blk, 125162306a36Sopenharmony_ci enum ice_flow_dir dir, struct ice_flow_seg_info *segs, 125262306a36Sopenharmony_ci u8 segs_cnt, u16 vsi_handle, u32 conds) 125362306a36Sopenharmony_ci{ 125462306a36Sopenharmony_ci struct ice_flow_prof *p, *prof = NULL; 125562306a36Sopenharmony_ci 125662306a36Sopenharmony_ci mutex_lock(&hw->fl_profs_locks[blk]); 125762306a36Sopenharmony_ci list_for_each_entry(p, &hw->fl_profs[blk], l_entry) 125862306a36Sopenharmony_ci if ((p->dir == dir || conds & ICE_FLOW_FIND_PROF_NOT_CHK_DIR) && 125962306a36Sopenharmony_ci segs_cnt && segs_cnt == p->segs_cnt) { 126062306a36Sopenharmony_ci u8 i; 126162306a36Sopenharmony_ci 126262306a36Sopenharmony_ci /* Check for profile-VSI association if specified */ 126362306a36Sopenharmony_ci if ((conds & ICE_FLOW_FIND_PROF_CHK_VSI) && 126462306a36Sopenharmony_ci ice_is_vsi_valid(hw, vsi_handle) && 126562306a36Sopenharmony_ci !test_bit(vsi_handle, p->vsis)) 126662306a36Sopenharmony_ci continue; 126762306a36Sopenharmony_ci 126862306a36Sopenharmony_ci /* Protocol headers must be checked. Matched fields are 126962306a36Sopenharmony_ci * checked if specified. 127062306a36Sopenharmony_ci */ 127162306a36Sopenharmony_ci for (i = 0; i < segs_cnt; i++) 127262306a36Sopenharmony_ci if (segs[i].hdrs != p->segs[i].hdrs || 127362306a36Sopenharmony_ci ((conds & ICE_FLOW_FIND_PROF_CHK_FLDS) && 127462306a36Sopenharmony_ci segs[i].match != p->segs[i].match)) 127562306a36Sopenharmony_ci break; 127662306a36Sopenharmony_ci 127762306a36Sopenharmony_ci /* A match is found if all segments are matched */ 127862306a36Sopenharmony_ci if (i == segs_cnt) { 127962306a36Sopenharmony_ci prof = p; 128062306a36Sopenharmony_ci break; 128162306a36Sopenharmony_ci } 128262306a36Sopenharmony_ci } 128362306a36Sopenharmony_ci mutex_unlock(&hw->fl_profs_locks[blk]); 128462306a36Sopenharmony_ci 128562306a36Sopenharmony_ci return prof; 128662306a36Sopenharmony_ci} 128762306a36Sopenharmony_ci 128862306a36Sopenharmony_ci/** 128962306a36Sopenharmony_ci * ice_flow_find_prof_id - Look up a profile with given profile ID 129062306a36Sopenharmony_ci * @hw: pointer to the HW struct 129162306a36Sopenharmony_ci * @blk: classification stage 129262306a36Sopenharmony_ci * @prof_id: unique ID to identify this flow profile 129362306a36Sopenharmony_ci */ 129462306a36Sopenharmony_cistatic struct ice_flow_prof * 129562306a36Sopenharmony_ciice_flow_find_prof_id(struct ice_hw *hw, enum ice_block blk, u64 prof_id) 129662306a36Sopenharmony_ci{ 129762306a36Sopenharmony_ci struct ice_flow_prof *p; 129862306a36Sopenharmony_ci 129962306a36Sopenharmony_ci list_for_each_entry(p, &hw->fl_profs[blk], l_entry) 130062306a36Sopenharmony_ci if (p->id == prof_id) 130162306a36Sopenharmony_ci return p; 130262306a36Sopenharmony_ci 130362306a36Sopenharmony_ci return NULL; 130462306a36Sopenharmony_ci} 130562306a36Sopenharmony_ci 130662306a36Sopenharmony_ci/** 130762306a36Sopenharmony_ci * ice_flow_rem_entry_sync - Remove a flow entry 130862306a36Sopenharmony_ci * @hw: pointer to the HW struct 130962306a36Sopenharmony_ci * @blk: classification stage 131062306a36Sopenharmony_ci * @entry: flow entry to be removed 131162306a36Sopenharmony_ci */ 131262306a36Sopenharmony_cistatic int 131362306a36Sopenharmony_ciice_flow_rem_entry_sync(struct ice_hw *hw, enum ice_block __always_unused blk, 131462306a36Sopenharmony_ci struct ice_flow_entry *entry) 131562306a36Sopenharmony_ci{ 131662306a36Sopenharmony_ci if (!entry) 131762306a36Sopenharmony_ci return -EINVAL; 131862306a36Sopenharmony_ci 131962306a36Sopenharmony_ci list_del(&entry->l_entry); 132062306a36Sopenharmony_ci 132162306a36Sopenharmony_ci devm_kfree(ice_hw_to_dev(hw), entry->entry); 132262306a36Sopenharmony_ci devm_kfree(ice_hw_to_dev(hw), entry); 132362306a36Sopenharmony_ci 132462306a36Sopenharmony_ci return 0; 132562306a36Sopenharmony_ci} 132662306a36Sopenharmony_ci 132762306a36Sopenharmony_ci/** 132862306a36Sopenharmony_ci * ice_flow_add_prof_sync - Add a flow profile for packet segments and fields 132962306a36Sopenharmony_ci * @hw: pointer to the HW struct 133062306a36Sopenharmony_ci * @blk: classification stage 133162306a36Sopenharmony_ci * @dir: flow direction 133262306a36Sopenharmony_ci * @prof_id: unique ID to identify this flow profile 133362306a36Sopenharmony_ci * @segs: array of one or more packet segments that describe the flow 133462306a36Sopenharmony_ci * @segs_cnt: number of packet segments provided 133562306a36Sopenharmony_ci * @prof: stores the returned flow profile added 133662306a36Sopenharmony_ci * 133762306a36Sopenharmony_ci * Assumption: the caller has acquired the lock to the profile list 133862306a36Sopenharmony_ci */ 133962306a36Sopenharmony_cistatic int 134062306a36Sopenharmony_ciice_flow_add_prof_sync(struct ice_hw *hw, enum ice_block blk, 134162306a36Sopenharmony_ci enum ice_flow_dir dir, u64 prof_id, 134262306a36Sopenharmony_ci struct ice_flow_seg_info *segs, u8 segs_cnt, 134362306a36Sopenharmony_ci struct ice_flow_prof **prof) 134462306a36Sopenharmony_ci{ 134562306a36Sopenharmony_ci struct ice_flow_prof_params *params; 134662306a36Sopenharmony_ci int status; 134762306a36Sopenharmony_ci u8 i; 134862306a36Sopenharmony_ci 134962306a36Sopenharmony_ci if (!prof) 135062306a36Sopenharmony_ci return -EINVAL; 135162306a36Sopenharmony_ci 135262306a36Sopenharmony_ci params = kzalloc(sizeof(*params), GFP_KERNEL); 135362306a36Sopenharmony_ci if (!params) 135462306a36Sopenharmony_ci return -ENOMEM; 135562306a36Sopenharmony_ci 135662306a36Sopenharmony_ci params->prof = devm_kzalloc(ice_hw_to_dev(hw), sizeof(*params->prof), 135762306a36Sopenharmony_ci GFP_KERNEL); 135862306a36Sopenharmony_ci if (!params->prof) { 135962306a36Sopenharmony_ci status = -ENOMEM; 136062306a36Sopenharmony_ci goto free_params; 136162306a36Sopenharmony_ci } 136262306a36Sopenharmony_ci 136362306a36Sopenharmony_ci /* initialize extraction sequence to all invalid (0xff) */ 136462306a36Sopenharmony_ci for (i = 0; i < ICE_MAX_FV_WORDS; i++) { 136562306a36Sopenharmony_ci params->es[i].prot_id = ICE_PROT_INVALID; 136662306a36Sopenharmony_ci params->es[i].off = ICE_FV_OFFSET_INVAL; 136762306a36Sopenharmony_ci } 136862306a36Sopenharmony_ci 136962306a36Sopenharmony_ci params->blk = blk; 137062306a36Sopenharmony_ci params->prof->id = prof_id; 137162306a36Sopenharmony_ci params->prof->dir = dir; 137262306a36Sopenharmony_ci params->prof->segs_cnt = segs_cnt; 137362306a36Sopenharmony_ci 137462306a36Sopenharmony_ci /* Make a copy of the segments that need to be persistent in the flow 137562306a36Sopenharmony_ci * profile instance 137662306a36Sopenharmony_ci */ 137762306a36Sopenharmony_ci for (i = 0; i < segs_cnt; i++) 137862306a36Sopenharmony_ci memcpy(¶ms->prof->segs[i], &segs[i], sizeof(*segs)); 137962306a36Sopenharmony_ci 138062306a36Sopenharmony_ci status = ice_flow_proc_segs(hw, params); 138162306a36Sopenharmony_ci if (status) { 138262306a36Sopenharmony_ci ice_debug(hw, ICE_DBG_FLOW, "Error processing a flow's packet segments\n"); 138362306a36Sopenharmony_ci goto out; 138462306a36Sopenharmony_ci } 138562306a36Sopenharmony_ci 138662306a36Sopenharmony_ci /* Add a HW profile for this flow profile */ 138762306a36Sopenharmony_ci status = ice_add_prof(hw, blk, prof_id, (u8 *)params->ptypes, 138862306a36Sopenharmony_ci params->attr, params->attr_cnt, params->es, 138962306a36Sopenharmony_ci params->mask); 139062306a36Sopenharmony_ci if (status) { 139162306a36Sopenharmony_ci ice_debug(hw, ICE_DBG_FLOW, "Error adding a HW flow profile\n"); 139262306a36Sopenharmony_ci goto out; 139362306a36Sopenharmony_ci } 139462306a36Sopenharmony_ci 139562306a36Sopenharmony_ci INIT_LIST_HEAD(¶ms->prof->entries); 139662306a36Sopenharmony_ci mutex_init(¶ms->prof->entries_lock); 139762306a36Sopenharmony_ci *prof = params->prof; 139862306a36Sopenharmony_ci 139962306a36Sopenharmony_ciout: 140062306a36Sopenharmony_ci if (status) 140162306a36Sopenharmony_ci devm_kfree(ice_hw_to_dev(hw), params->prof); 140262306a36Sopenharmony_cifree_params: 140362306a36Sopenharmony_ci kfree(params); 140462306a36Sopenharmony_ci 140562306a36Sopenharmony_ci return status; 140662306a36Sopenharmony_ci} 140762306a36Sopenharmony_ci 140862306a36Sopenharmony_ci/** 140962306a36Sopenharmony_ci * ice_flow_rem_prof_sync - remove a flow profile 141062306a36Sopenharmony_ci * @hw: pointer to the hardware structure 141162306a36Sopenharmony_ci * @blk: classification stage 141262306a36Sopenharmony_ci * @prof: pointer to flow profile to remove 141362306a36Sopenharmony_ci * 141462306a36Sopenharmony_ci * Assumption: the caller has acquired the lock to the profile list 141562306a36Sopenharmony_ci */ 141662306a36Sopenharmony_cistatic int 141762306a36Sopenharmony_ciice_flow_rem_prof_sync(struct ice_hw *hw, enum ice_block blk, 141862306a36Sopenharmony_ci struct ice_flow_prof *prof) 141962306a36Sopenharmony_ci{ 142062306a36Sopenharmony_ci int status; 142162306a36Sopenharmony_ci 142262306a36Sopenharmony_ci /* Remove all remaining flow entries before removing the flow profile */ 142362306a36Sopenharmony_ci if (!list_empty(&prof->entries)) { 142462306a36Sopenharmony_ci struct ice_flow_entry *e, *t; 142562306a36Sopenharmony_ci 142662306a36Sopenharmony_ci mutex_lock(&prof->entries_lock); 142762306a36Sopenharmony_ci 142862306a36Sopenharmony_ci list_for_each_entry_safe(e, t, &prof->entries, l_entry) { 142962306a36Sopenharmony_ci status = ice_flow_rem_entry_sync(hw, blk, e); 143062306a36Sopenharmony_ci if (status) 143162306a36Sopenharmony_ci break; 143262306a36Sopenharmony_ci } 143362306a36Sopenharmony_ci 143462306a36Sopenharmony_ci mutex_unlock(&prof->entries_lock); 143562306a36Sopenharmony_ci } 143662306a36Sopenharmony_ci 143762306a36Sopenharmony_ci /* Remove all hardware profiles associated with this flow profile */ 143862306a36Sopenharmony_ci status = ice_rem_prof(hw, blk, prof->id); 143962306a36Sopenharmony_ci if (!status) { 144062306a36Sopenharmony_ci list_del(&prof->l_entry); 144162306a36Sopenharmony_ci mutex_destroy(&prof->entries_lock); 144262306a36Sopenharmony_ci devm_kfree(ice_hw_to_dev(hw), prof); 144362306a36Sopenharmony_ci } 144462306a36Sopenharmony_ci 144562306a36Sopenharmony_ci return status; 144662306a36Sopenharmony_ci} 144762306a36Sopenharmony_ci 144862306a36Sopenharmony_ci/** 144962306a36Sopenharmony_ci * ice_flow_assoc_prof - associate a VSI with a flow profile 145062306a36Sopenharmony_ci * @hw: pointer to the hardware structure 145162306a36Sopenharmony_ci * @blk: classification stage 145262306a36Sopenharmony_ci * @prof: pointer to flow profile 145362306a36Sopenharmony_ci * @vsi_handle: software VSI handle 145462306a36Sopenharmony_ci * 145562306a36Sopenharmony_ci * Assumption: the caller has acquired the lock to the profile list 145662306a36Sopenharmony_ci * and the software VSI handle has been validated 145762306a36Sopenharmony_ci */ 145862306a36Sopenharmony_cistatic int 145962306a36Sopenharmony_ciice_flow_assoc_prof(struct ice_hw *hw, enum ice_block blk, 146062306a36Sopenharmony_ci struct ice_flow_prof *prof, u16 vsi_handle) 146162306a36Sopenharmony_ci{ 146262306a36Sopenharmony_ci int status = 0; 146362306a36Sopenharmony_ci 146462306a36Sopenharmony_ci if (!test_bit(vsi_handle, prof->vsis)) { 146562306a36Sopenharmony_ci status = ice_add_prof_id_flow(hw, blk, 146662306a36Sopenharmony_ci ice_get_hw_vsi_num(hw, 146762306a36Sopenharmony_ci vsi_handle), 146862306a36Sopenharmony_ci prof->id); 146962306a36Sopenharmony_ci if (!status) 147062306a36Sopenharmony_ci set_bit(vsi_handle, prof->vsis); 147162306a36Sopenharmony_ci else 147262306a36Sopenharmony_ci ice_debug(hw, ICE_DBG_FLOW, "HW profile add failed, %d\n", 147362306a36Sopenharmony_ci status); 147462306a36Sopenharmony_ci } 147562306a36Sopenharmony_ci 147662306a36Sopenharmony_ci return status; 147762306a36Sopenharmony_ci} 147862306a36Sopenharmony_ci 147962306a36Sopenharmony_ci/** 148062306a36Sopenharmony_ci * ice_flow_disassoc_prof - disassociate a VSI from a flow profile 148162306a36Sopenharmony_ci * @hw: pointer to the hardware structure 148262306a36Sopenharmony_ci * @blk: classification stage 148362306a36Sopenharmony_ci * @prof: pointer to flow profile 148462306a36Sopenharmony_ci * @vsi_handle: software VSI handle 148562306a36Sopenharmony_ci * 148662306a36Sopenharmony_ci * Assumption: the caller has acquired the lock to the profile list 148762306a36Sopenharmony_ci * and the software VSI handle has been validated 148862306a36Sopenharmony_ci */ 148962306a36Sopenharmony_cistatic int 149062306a36Sopenharmony_ciice_flow_disassoc_prof(struct ice_hw *hw, enum ice_block blk, 149162306a36Sopenharmony_ci struct ice_flow_prof *prof, u16 vsi_handle) 149262306a36Sopenharmony_ci{ 149362306a36Sopenharmony_ci int status = 0; 149462306a36Sopenharmony_ci 149562306a36Sopenharmony_ci if (test_bit(vsi_handle, prof->vsis)) { 149662306a36Sopenharmony_ci status = ice_rem_prof_id_flow(hw, blk, 149762306a36Sopenharmony_ci ice_get_hw_vsi_num(hw, 149862306a36Sopenharmony_ci vsi_handle), 149962306a36Sopenharmony_ci prof->id); 150062306a36Sopenharmony_ci if (!status) 150162306a36Sopenharmony_ci clear_bit(vsi_handle, prof->vsis); 150262306a36Sopenharmony_ci else 150362306a36Sopenharmony_ci ice_debug(hw, ICE_DBG_FLOW, "HW profile remove failed, %d\n", 150462306a36Sopenharmony_ci status); 150562306a36Sopenharmony_ci } 150662306a36Sopenharmony_ci 150762306a36Sopenharmony_ci return status; 150862306a36Sopenharmony_ci} 150962306a36Sopenharmony_ci 151062306a36Sopenharmony_ci/** 151162306a36Sopenharmony_ci * ice_flow_add_prof - Add a flow profile for packet segments and matched fields 151262306a36Sopenharmony_ci * @hw: pointer to the HW struct 151362306a36Sopenharmony_ci * @blk: classification stage 151462306a36Sopenharmony_ci * @dir: flow direction 151562306a36Sopenharmony_ci * @prof_id: unique ID to identify this flow profile 151662306a36Sopenharmony_ci * @segs: array of one or more packet segments that describe the flow 151762306a36Sopenharmony_ci * @segs_cnt: number of packet segments provided 151862306a36Sopenharmony_ci * @prof: stores the returned flow profile added 151962306a36Sopenharmony_ci */ 152062306a36Sopenharmony_ciint 152162306a36Sopenharmony_ciice_flow_add_prof(struct ice_hw *hw, enum ice_block blk, enum ice_flow_dir dir, 152262306a36Sopenharmony_ci u64 prof_id, struct ice_flow_seg_info *segs, u8 segs_cnt, 152362306a36Sopenharmony_ci struct ice_flow_prof **prof) 152462306a36Sopenharmony_ci{ 152562306a36Sopenharmony_ci int status; 152662306a36Sopenharmony_ci 152762306a36Sopenharmony_ci if (segs_cnt > ICE_FLOW_SEG_MAX) 152862306a36Sopenharmony_ci return -ENOSPC; 152962306a36Sopenharmony_ci 153062306a36Sopenharmony_ci if (!segs_cnt) 153162306a36Sopenharmony_ci return -EINVAL; 153262306a36Sopenharmony_ci 153362306a36Sopenharmony_ci if (!segs) 153462306a36Sopenharmony_ci return -EINVAL; 153562306a36Sopenharmony_ci 153662306a36Sopenharmony_ci status = ice_flow_val_hdrs(segs, segs_cnt); 153762306a36Sopenharmony_ci if (status) 153862306a36Sopenharmony_ci return status; 153962306a36Sopenharmony_ci 154062306a36Sopenharmony_ci mutex_lock(&hw->fl_profs_locks[blk]); 154162306a36Sopenharmony_ci 154262306a36Sopenharmony_ci status = ice_flow_add_prof_sync(hw, blk, dir, prof_id, segs, segs_cnt, 154362306a36Sopenharmony_ci prof); 154462306a36Sopenharmony_ci if (!status) 154562306a36Sopenharmony_ci list_add(&(*prof)->l_entry, &hw->fl_profs[blk]); 154662306a36Sopenharmony_ci 154762306a36Sopenharmony_ci mutex_unlock(&hw->fl_profs_locks[blk]); 154862306a36Sopenharmony_ci 154962306a36Sopenharmony_ci return status; 155062306a36Sopenharmony_ci} 155162306a36Sopenharmony_ci 155262306a36Sopenharmony_ci/** 155362306a36Sopenharmony_ci * ice_flow_rem_prof - Remove a flow profile and all entries associated with it 155462306a36Sopenharmony_ci * @hw: pointer to the HW struct 155562306a36Sopenharmony_ci * @blk: the block for which the flow profile is to be removed 155662306a36Sopenharmony_ci * @prof_id: unique ID of the flow profile to be removed 155762306a36Sopenharmony_ci */ 155862306a36Sopenharmony_ciint ice_flow_rem_prof(struct ice_hw *hw, enum ice_block blk, u64 prof_id) 155962306a36Sopenharmony_ci{ 156062306a36Sopenharmony_ci struct ice_flow_prof *prof; 156162306a36Sopenharmony_ci int status; 156262306a36Sopenharmony_ci 156362306a36Sopenharmony_ci mutex_lock(&hw->fl_profs_locks[blk]); 156462306a36Sopenharmony_ci 156562306a36Sopenharmony_ci prof = ice_flow_find_prof_id(hw, blk, prof_id); 156662306a36Sopenharmony_ci if (!prof) { 156762306a36Sopenharmony_ci status = -ENOENT; 156862306a36Sopenharmony_ci goto out; 156962306a36Sopenharmony_ci } 157062306a36Sopenharmony_ci 157162306a36Sopenharmony_ci /* prof becomes invalid after the call */ 157262306a36Sopenharmony_ci status = ice_flow_rem_prof_sync(hw, blk, prof); 157362306a36Sopenharmony_ci 157462306a36Sopenharmony_ciout: 157562306a36Sopenharmony_ci mutex_unlock(&hw->fl_profs_locks[blk]); 157662306a36Sopenharmony_ci 157762306a36Sopenharmony_ci return status; 157862306a36Sopenharmony_ci} 157962306a36Sopenharmony_ci 158062306a36Sopenharmony_ci/** 158162306a36Sopenharmony_ci * ice_flow_add_entry - Add a flow entry 158262306a36Sopenharmony_ci * @hw: pointer to the HW struct 158362306a36Sopenharmony_ci * @blk: classification stage 158462306a36Sopenharmony_ci * @prof_id: ID of the profile to add a new flow entry to 158562306a36Sopenharmony_ci * @entry_id: unique ID to identify this flow entry 158662306a36Sopenharmony_ci * @vsi_handle: software VSI handle for the flow entry 158762306a36Sopenharmony_ci * @prio: priority of the flow entry 158862306a36Sopenharmony_ci * @data: pointer to a data buffer containing flow entry's match values/masks 158962306a36Sopenharmony_ci * @entry_h: pointer to buffer that receives the new flow entry's handle 159062306a36Sopenharmony_ci */ 159162306a36Sopenharmony_ciint 159262306a36Sopenharmony_ciice_flow_add_entry(struct ice_hw *hw, enum ice_block blk, u64 prof_id, 159362306a36Sopenharmony_ci u64 entry_id, u16 vsi_handle, enum ice_flow_priority prio, 159462306a36Sopenharmony_ci void *data, u64 *entry_h) 159562306a36Sopenharmony_ci{ 159662306a36Sopenharmony_ci struct ice_flow_entry *e = NULL; 159762306a36Sopenharmony_ci struct ice_flow_prof *prof; 159862306a36Sopenharmony_ci int status; 159962306a36Sopenharmony_ci 160062306a36Sopenharmony_ci /* No flow entry data is expected for RSS */ 160162306a36Sopenharmony_ci if (!entry_h || (!data && blk != ICE_BLK_RSS)) 160262306a36Sopenharmony_ci return -EINVAL; 160362306a36Sopenharmony_ci 160462306a36Sopenharmony_ci if (!ice_is_vsi_valid(hw, vsi_handle)) 160562306a36Sopenharmony_ci return -EINVAL; 160662306a36Sopenharmony_ci 160762306a36Sopenharmony_ci mutex_lock(&hw->fl_profs_locks[blk]); 160862306a36Sopenharmony_ci 160962306a36Sopenharmony_ci prof = ice_flow_find_prof_id(hw, blk, prof_id); 161062306a36Sopenharmony_ci if (!prof) { 161162306a36Sopenharmony_ci status = -ENOENT; 161262306a36Sopenharmony_ci } else { 161362306a36Sopenharmony_ci /* Allocate memory for the entry being added and associate 161462306a36Sopenharmony_ci * the VSI to the found flow profile 161562306a36Sopenharmony_ci */ 161662306a36Sopenharmony_ci e = devm_kzalloc(ice_hw_to_dev(hw), sizeof(*e), GFP_KERNEL); 161762306a36Sopenharmony_ci if (!e) 161862306a36Sopenharmony_ci status = -ENOMEM; 161962306a36Sopenharmony_ci else 162062306a36Sopenharmony_ci status = ice_flow_assoc_prof(hw, blk, prof, vsi_handle); 162162306a36Sopenharmony_ci } 162262306a36Sopenharmony_ci 162362306a36Sopenharmony_ci mutex_unlock(&hw->fl_profs_locks[blk]); 162462306a36Sopenharmony_ci if (status) 162562306a36Sopenharmony_ci goto out; 162662306a36Sopenharmony_ci 162762306a36Sopenharmony_ci e->id = entry_id; 162862306a36Sopenharmony_ci e->vsi_handle = vsi_handle; 162962306a36Sopenharmony_ci e->prof = prof; 163062306a36Sopenharmony_ci e->priority = prio; 163162306a36Sopenharmony_ci 163262306a36Sopenharmony_ci switch (blk) { 163362306a36Sopenharmony_ci case ICE_BLK_FD: 163462306a36Sopenharmony_ci case ICE_BLK_RSS: 163562306a36Sopenharmony_ci break; 163662306a36Sopenharmony_ci default: 163762306a36Sopenharmony_ci status = -EOPNOTSUPP; 163862306a36Sopenharmony_ci goto out; 163962306a36Sopenharmony_ci } 164062306a36Sopenharmony_ci 164162306a36Sopenharmony_ci mutex_lock(&prof->entries_lock); 164262306a36Sopenharmony_ci list_add(&e->l_entry, &prof->entries); 164362306a36Sopenharmony_ci mutex_unlock(&prof->entries_lock); 164462306a36Sopenharmony_ci 164562306a36Sopenharmony_ci *entry_h = ICE_FLOW_ENTRY_HNDL(e); 164662306a36Sopenharmony_ci 164762306a36Sopenharmony_ciout: 164862306a36Sopenharmony_ci if (status && e) { 164962306a36Sopenharmony_ci devm_kfree(ice_hw_to_dev(hw), e->entry); 165062306a36Sopenharmony_ci devm_kfree(ice_hw_to_dev(hw), e); 165162306a36Sopenharmony_ci } 165262306a36Sopenharmony_ci 165362306a36Sopenharmony_ci return status; 165462306a36Sopenharmony_ci} 165562306a36Sopenharmony_ci 165662306a36Sopenharmony_ci/** 165762306a36Sopenharmony_ci * ice_flow_rem_entry - Remove a flow entry 165862306a36Sopenharmony_ci * @hw: pointer to the HW struct 165962306a36Sopenharmony_ci * @blk: classification stage 166062306a36Sopenharmony_ci * @entry_h: handle to the flow entry to be removed 166162306a36Sopenharmony_ci */ 166262306a36Sopenharmony_ciint ice_flow_rem_entry(struct ice_hw *hw, enum ice_block blk, u64 entry_h) 166362306a36Sopenharmony_ci{ 166462306a36Sopenharmony_ci struct ice_flow_entry *entry; 166562306a36Sopenharmony_ci struct ice_flow_prof *prof; 166662306a36Sopenharmony_ci int status = 0; 166762306a36Sopenharmony_ci 166862306a36Sopenharmony_ci if (entry_h == ICE_FLOW_ENTRY_HANDLE_INVAL) 166962306a36Sopenharmony_ci return -EINVAL; 167062306a36Sopenharmony_ci 167162306a36Sopenharmony_ci entry = ICE_FLOW_ENTRY_PTR(entry_h); 167262306a36Sopenharmony_ci 167362306a36Sopenharmony_ci /* Retain the pointer to the flow profile as the entry will be freed */ 167462306a36Sopenharmony_ci prof = entry->prof; 167562306a36Sopenharmony_ci 167662306a36Sopenharmony_ci if (prof) { 167762306a36Sopenharmony_ci mutex_lock(&prof->entries_lock); 167862306a36Sopenharmony_ci status = ice_flow_rem_entry_sync(hw, blk, entry); 167962306a36Sopenharmony_ci mutex_unlock(&prof->entries_lock); 168062306a36Sopenharmony_ci } 168162306a36Sopenharmony_ci 168262306a36Sopenharmony_ci return status; 168362306a36Sopenharmony_ci} 168462306a36Sopenharmony_ci 168562306a36Sopenharmony_ci/** 168662306a36Sopenharmony_ci * ice_flow_set_fld_ext - specifies locations of field from entry's input buffer 168762306a36Sopenharmony_ci * @seg: packet segment the field being set belongs to 168862306a36Sopenharmony_ci * @fld: field to be set 168962306a36Sopenharmony_ci * @field_type: type of the field 169062306a36Sopenharmony_ci * @val_loc: if not ICE_FLOW_FLD_OFF_INVAL, location of the value to match from 169162306a36Sopenharmony_ci * entry's input buffer 169262306a36Sopenharmony_ci * @mask_loc: if not ICE_FLOW_FLD_OFF_INVAL, location of mask value from entry's 169362306a36Sopenharmony_ci * input buffer 169462306a36Sopenharmony_ci * @last_loc: if not ICE_FLOW_FLD_OFF_INVAL, location of last/upper value from 169562306a36Sopenharmony_ci * entry's input buffer 169662306a36Sopenharmony_ci * 169762306a36Sopenharmony_ci * This helper function stores information of a field being matched, including 169862306a36Sopenharmony_ci * the type of the field and the locations of the value to match, the mask, and 169962306a36Sopenharmony_ci * the upper-bound value in the start of the input buffer for a flow entry. 170062306a36Sopenharmony_ci * This function should only be used for fixed-size data structures. 170162306a36Sopenharmony_ci * 170262306a36Sopenharmony_ci * This function also opportunistically determines the protocol headers to be 170362306a36Sopenharmony_ci * present based on the fields being set. Some fields cannot be used alone to 170462306a36Sopenharmony_ci * determine the protocol headers present. Sometimes, fields for particular 170562306a36Sopenharmony_ci * protocol headers are not matched. In those cases, the protocol headers 170662306a36Sopenharmony_ci * must be explicitly set. 170762306a36Sopenharmony_ci */ 170862306a36Sopenharmony_cistatic void 170962306a36Sopenharmony_ciice_flow_set_fld_ext(struct ice_flow_seg_info *seg, enum ice_flow_field fld, 171062306a36Sopenharmony_ci enum ice_flow_fld_match_type field_type, u16 val_loc, 171162306a36Sopenharmony_ci u16 mask_loc, u16 last_loc) 171262306a36Sopenharmony_ci{ 171362306a36Sopenharmony_ci u64 bit = BIT_ULL(fld); 171462306a36Sopenharmony_ci 171562306a36Sopenharmony_ci seg->match |= bit; 171662306a36Sopenharmony_ci if (field_type == ICE_FLOW_FLD_TYPE_RANGE) 171762306a36Sopenharmony_ci seg->range |= bit; 171862306a36Sopenharmony_ci 171962306a36Sopenharmony_ci seg->fields[fld].type = field_type; 172062306a36Sopenharmony_ci seg->fields[fld].src.val = val_loc; 172162306a36Sopenharmony_ci seg->fields[fld].src.mask = mask_loc; 172262306a36Sopenharmony_ci seg->fields[fld].src.last = last_loc; 172362306a36Sopenharmony_ci 172462306a36Sopenharmony_ci ICE_FLOW_SET_HDRS(seg, ice_flds_info[fld].hdr); 172562306a36Sopenharmony_ci} 172662306a36Sopenharmony_ci 172762306a36Sopenharmony_ci/** 172862306a36Sopenharmony_ci * ice_flow_set_fld - specifies locations of field from entry's input buffer 172962306a36Sopenharmony_ci * @seg: packet segment the field being set belongs to 173062306a36Sopenharmony_ci * @fld: field to be set 173162306a36Sopenharmony_ci * @val_loc: if not ICE_FLOW_FLD_OFF_INVAL, location of the value to match from 173262306a36Sopenharmony_ci * entry's input buffer 173362306a36Sopenharmony_ci * @mask_loc: if not ICE_FLOW_FLD_OFF_INVAL, location of mask value from entry's 173462306a36Sopenharmony_ci * input buffer 173562306a36Sopenharmony_ci * @last_loc: if not ICE_FLOW_FLD_OFF_INVAL, location of last/upper value from 173662306a36Sopenharmony_ci * entry's input buffer 173762306a36Sopenharmony_ci * @range: indicate if field being matched is to be in a range 173862306a36Sopenharmony_ci * 173962306a36Sopenharmony_ci * This function specifies the locations, in the form of byte offsets from the 174062306a36Sopenharmony_ci * start of the input buffer for a flow entry, from where the value to match, 174162306a36Sopenharmony_ci * the mask value, and upper value can be extracted. These locations are then 174262306a36Sopenharmony_ci * stored in the flow profile. When adding a flow entry associated with the 174362306a36Sopenharmony_ci * flow profile, these locations will be used to quickly extract the values and 174462306a36Sopenharmony_ci * create the content of a match entry. This function should only be used for 174562306a36Sopenharmony_ci * fixed-size data structures. 174662306a36Sopenharmony_ci */ 174762306a36Sopenharmony_civoid 174862306a36Sopenharmony_ciice_flow_set_fld(struct ice_flow_seg_info *seg, enum ice_flow_field fld, 174962306a36Sopenharmony_ci u16 val_loc, u16 mask_loc, u16 last_loc, bool range) 175062306a36Sopenharmony_ci{ 175162306a36Sopenharmony_ci enum ice_flow_fld_match_type t = range ? 175262306a36Sopenharmony_ci ICE_FLOW_FLD_TYPE_RANGE : ICE_FLOW_FLD_TYPE_REG; 175362306a36Sopenharmony_ci 175462306a36Sopenharmony_ci ice_flow_set_fld_ext(seg, fld, t, val_loc, mask_loc, last_loc); 175562306a36Sopenharmony_ci} 175662306a36Sopenharmony_ci 175762306a36Sopenharmony_ci/** 175862306a36Sopenharmony_ci * ice_flow_add_fld_raw - sets locations of a raw field from entry's input buf 175962306a36Sopenharmony_ci * @seg: packet segment the field being set belongs to 176062306a36Sopenharmony_ci * @off: offset of the raw field from the beginning of the segment in bytes 176162306a36Sopenharmony_ci * @len: length of the raw pattern to be matched 176262306a36Sopenharmony_ci * @val_loc: location of the value to match from entry's input buffer 176362306a36Sopenharmony_ci * @mask_loc: location of mask value from entry's input buffer 176462306a36Sopenharmony_ci * 176562306a36Sopenharmony_ci * This function specifies the offset of the raw field to be match from the 176662306a36Sopenharmony_ci * beginning of the specified packet segment, and the locations, in the form of 176762306a36Sopenharmony_ci * byte offsets from the start of the input buffer for a flow entry, from where 176862306a36Sopenharmony_ci * the value to match and the mask value to be extracted. These locations are 176962306a36Sopenharmony_ci * then stored in the flow profile. When adding flow entries to the associated 177062306a36Sopenharmony_ci * flow profile, these locations can be used to quickly extract the values to 177162306a36Sopenharmony_ci * create the content of a match entry. This function should only be used for 177262306a36Sopenharmony_ci * fixed-size data structures. 177362306a36Sopenharmony_ci */ 177462306a36Sopenharmony_civoid 177562306a36Sopenharmony_ciice_flow_add_fld_raw(struct ice_flow_seg_info *seg, u16 off, u8 len, 177662306a36Sopenharmony_ci u16 val_loc, u16 mask_loc) 177762306a36Sopenharmony_ci{ 177862306a36Sopenharmony_ci if (seg->raws_cnt < ICE_FLOW_SEG_RAW_FLD_MAX) { 177962306a36Sopenharmony_ci seg->raws[seg->raws_cnt].off = off; 178062306a36Sopenharmony_ci seg->raws[seg->raws_cnt].info.type = ICE_FLOW_FLD_TYPE_SIZE; 178162306a36Sopenharmony_ci seg->raws[seg->raws_cnt].info.src.val = val_loc; 178262306a36Sopenharmony_ci seg->raws[seg->raws_cnt].info.src.mask = mask_loc; 178362306a36Sopenharmony_ci /* The "last" field is used to store the length of the field */ 178462306a36Sopenharmony_ci seg->raws[seg->raws_cnt].info.src.last = len; 178562306a36Sopenharmony_ci } 178662306a36Sopenharmony_ci 178762306a36Sopenharmony_ci /* Overflows of "raws" will be handled as an error condition later in 178862306a36Sopenharmony_ci * the flow when this information is processed. 178962306a36Sopenharmony_ci */ 179062306a36Sopenharmony_ci seg->raws_cnt++; 179162306a36Sopenharmony_ci} 179262306a36Sopenharmony_ci 179362306a36Sopenharmony_ci/** 179462306a36Sopenharmony_ci * ice_flow_rem_vsi_prof - remove VSI from flow profile 179562306a36Sopenharmony_ci * @hw: pointer to the hardware structure 179662306a36Sopenharmony_ci * @vsi_handle: software VSI handle 179762306a36Sopenharmony_ci * @prof_id: unique ID to identify this flow profile 179862306a36Sopenharmony_ci * 179962306a36Sopenharmony_ci * This function removes the flow entries associated to the input 180062306a36Sopenharmony_ci * VSI handle and disassociate the VSI from the flow profile. 180162306a36Sopenharmony_ci */ 180262306a36Sopenharmony_ciint ice_flow_rem_vsi_prof(struct ice_hw *hw, u16 vsi_handle, u64 prof_id) 180362306a36Sopenharmony_ci{ 180462306a36Sopenharmony_ci struct ice_flow_prof *prof; 180562306a36Sopenharmony_ci int status = 0; 180662306a36Sopenharmony_ci 180762306a36Sopenharmony_ci if (!ice_is_vsi_valid(hw, vsi_handle)) 180862306a36Sopenharmony_ci return -EINVAL; 180962306a36Sopenharmony_ci 181062306a36Sopenharmony_ci /* find flow profile pointer with input package block and profile ID */ 181162306a36Sopenharmony_ci prof = ice_flow_find_prof_id(hw, ICE_BLK_FD, prof_id); 181262306a36Sopenharmony_ci if (!prof) { 181362306a36Sopenharmony_ci ice_debug(hw, ICE_DBG_PKG, "Cannot find flow profile id=%llu\n", 181462306a36Sopenharmony_ci prof_id); 181562306a36Sopenharmony_ci return -ENOENT; 181662306a36Sopenharmony_ci } 181762306a36Sopenharmony_ci 181862306a36Sopenharmony_ci /* Remove all remaining flow entries before removing the flow profile */ 181962306a36Sopenharmony_ci if (!list_empty(&prof->entries)) { 182062306a36Sopenharmony_ci struct ice_flow_entry *e, *t; 182162306a36Sopenharmony_ci 182262306a36Sopenharmony_ci mutex_lock(&prof->entries_lock); 182362306a36Sopenharmony_ci list_for_each_entry_safe(e, t, &prof->entries, l_entry) { 182462306a36Sopenharmony_ci if (e->vsi_handle != vsi_handle) 182562306a36Sopenharmony_ci continue; 182662306a36Sopenharmony_ci 182762306a36Sopenharmony_ci status = ice_flow_rem_entry_sync(hw, ICE_BLK_FD, e); 182862306a36Sopenharmony_ci if (status) 182962306a36Sopenharmony_ci break; 183062306a36Sopenharmony_ci } 183162306a36Sopenharmony_ci mutex_unlock(&prof->entries_lock); 183262306a36Sopenharmony_ci } 183362306a36Sopenharmony_ci if (status) 183462306a36Sopenharmony_ci return status; 183562306a36Sopenharmony_ci 183662306a36Sopenharmony_ci /* disassociate the flow profile from sw VSI handle */ 183762306a36Sopenharmony_ci status = ice_flow_disassoc_prof(hw, ICE_BLK_FD, prof, vsi_handle); 183862306a36Sopenharmony_ci if (status) 183962306a36Sopenharmony_ci ice_debug(hw, ICE_DBG_PKG, "ice_flow_disassoc_prof() failed with status=%d\n", 184062306a36Sopenharmony_ci status); 184162306a36Sopenharmony_ci return status; 184262306a36Sopenharmony_ci} 184362306a36Sopenharmony_ci 184462306a36Sopenharmony_ci#define ICE_FLOW_RSS_SEG_HDR_L2_MASKS \ 184562306a36Sopenharmony_ci (ICE_FLOW_SEG_HDR_ETH | ICE_FLOW_SEG_HDR_VLAN) 184662306a36Sopenharmony_ci 184762306a36Sopenharmony_ci#define ICE_FLOW_RSS_SEG_HDR_L3_MASKS \ 184862306a36Sopenharmony_ci (ICE_FLOW_SEG_HDR_IPV4 | ICE_FLOW_SEG_HDR_IPV6) 184962306a36Sopenharmony_ci 185062306a36Sopenharmony_ci#define ICE_FLOW_RSS_SEG_HDR_L4_MASKS \ 185162306a36Sopenharmony_ci (ICE_FLOW_SEG_HDR_TCP | ICE_FLOW_SEG_HDR_UDP | ICE_FLOW_SEG_HDR_SCTP) 185262306a36Sopenharmony_ci 185362306a36Sopenharmony_ci#define ICE_FLOW_RSS_SEG_HDR_VAL_MASKS \ 185462306a36Sopenharmony_ci (ICE_FLOW_RSS_SEG_HDR_L2_MASKS | \ 185562306a36Sopenharmony_ci ICE_FLOW_RSS_SEG_HDR_L3_MASKS | \ 185662306a36Sopenharmony_ci ICE_FLOW_RSS_SEG_HDR_L4_MASKS) 185762306a36Sopenharmony_ci 185862306a36Sopenharmony_ci/** 185962306a36Sopenharmony_ci * ice_flow_set_rss_seg_info - setup packet segments for RSS 186062306a36Sopenharmony_ci * @segs: pointer to the flow field segment(s) 186162306a36Sopenharmony_ci * @hash_fields: fields to be hashed on for the segment(s) 186262306a36Sopenharmony_ci * @flow_hdr: protocol header fields within a packet segment 186362306a36Sopenharmony_ci * 186462306a36Sopenharmony_ci * Helper function to extract fields from hash bitmap and use flow 186562306a36Sopenharmony_ci * header value to set flow field segment for further use in flow 186662306a36Sopenharmony_ci * profile entry or removal. 186762306a36Sopenharmony_ci */ 186862306a36Sopenharmony_cistatic int 186962306a36Sopenharmony_ciice_flow_set_rss_seg_info(struct ice_flow_seg_info *segs, u64 hash_fields, 187062306a36Sopenharmony_ci u32 flow_hdr) 187162306a36Sopenharmony_ci{ 187262306a36Sopenharmony_ci u64 val; 187362306a36Sopenharmony_ci u8 i; 187462306a36Sopenharmony_ci 187562306a36Sopenharmony_ci for_each_set_bit(i, (unsigned long *)&hash_fields, 187662306a36Sopenharmony_ci ICE_FLOW_FIELD_IDX_MAX) 187762306a36Sopenharmony_ci ice_flow_set_fld(segs, (enum ice_flow_field)i, 187862306a36Sopenharmony_ci ICE_FLOW_FLD_OFF_INVAL, ICE_FLOW_FLD_OFF_INVAL, 187962306a36Sopenharmony_ci ICE_FLOW_FLD_OFF_INVAL, false); 188062306a36Sopenharmony_ci 188162306a36Sopenharmony_ci ICE_FLOW_SET_HDRS(segs, flow_hdr); 188262306a36Sopenharmony_ci 188362306a36Sopenharmony_ci if (segs->hdrs & ~ICE_FLOW_RSS_SEG_HDR_VAL_MASKS & 188462306a36Sopenharmony_ci ~ICE_FLOW_RSS_HDRS_INNER_MASK & ~ICE_FLOW_SEG_HDR_IPV_OTHER) 188562306a36Sopenharmony_ci return -EINVAL; 188662306a36Sopenharmony_ci 188762306a36Sopenharmony_ci val = (u64)(segs->hdrs & ICE_FLOW_RSS_SEG_HDR_L3_MASKS); 188862306a36Sopenharmony_ci if (val && !is_power_of_2(val)) 188962306a36Sopenharmony_ci return -EIO; 189062306a36Sopenharmony_ci 189162306a36Sopenharmony_ci val = (u64)(segs->hdrs & ICE_FLOW_RSS_SEG_HDR_L4_MASKS); 189262306a36Sopenharmony_ci if (val && !is_power_of_2(val)) 189362306a36Sopenharmony_ci return -EIO; 189462306a36Sopenharmony_ci 189562306a36Sopenharmony_ci return 0; 189662306a36Sopenharmony_ci} 189762306a36Sopenharmony_ci 189862306a36Sopenharmony_ci/** 189962306a36Sopenharmony_ci * ice_rem_vsi_rss_list - remove VSI from RSS list 190062306a36Sopenharmony_ci * @hw: pointer to the hardware structure 190162306a36Sopenharmony_ci * @vsi_handle: software VSI handle 190262306a36Sopenharmony_ci * 190362306a36Sopenharmony_ci * Remove the VSI from all RSS configurations in the list. 190462306a36Sopenharmony_ci */ 190562306a36Sopenharmony_civoid ice_rem_vsi_rss_list(struct ice_hw *hw, u16 vsi_handle) 190662306a36Sopenharmony_ci{ 190762306a36Sopenharmony_ci struct ice_rss_cfg *r, *tmp; 190862306a36Sopenharmony_ci 190962306a36Sopenharmony_ci if (list_empty(&hw->rss_list_head)) 191062306a36Sopenharmony_ci return; 191162306a36Sopenharmony_ci 191262306a36Sopenharmony_ci mutex_lock(&hw->rss_locks); 191362306a36Sopenharmony_ci list_for_each_entry_safe(r, tmp, &hw->rss_list_head, l_entry) 191462306a36Sopenharmony_ci if (test_and_clear_bit(vsi_handle, r->vsis)) 191562306a36Sopenharmony_ci if (bitmap_empty(r->vsis, ICE_MAX_VSI)) { 191662306a36Sopenharmony_ci list_del(&r->l_entry); 191762306a36Sopenharmony_ci devm_kfree(ice_hw_to_dev(hw), r); 191862306a36Sopenharmony_ci } 191962306a36Sopenharmony_ci mutex_unlock(&hw->rss_locks); 192062306a36Sopenharmony_ci} 192162306a36Sopenharmony_ci 192262306a36Sopenharmony_ci/** 192362306a36Sopenharmony_ci * ice_rem_vsi_rss_cfg - remove RSS configurations associated with VSI 192462306a36Sopenharmony_ci * @hw: pointer to the hardware structure 192562306a36Sopenharmony_ci * @vsi_handle: software VSI handle 192662306a36Sopenharmony_ci * 192762306a36Sopenharmony_ci * This function will iterate through all flow profiles and disassociate 192862306a36Sopenharmony_ci * the VSI from that profile. If the flow profile has no VSIs it will 192962306a36Sopenharmony_ci * be removed. 193062306a36Sopenharmony_ci */ 193162306a36Sopenharmony_ciint ice_rem_vsi_rss_cfg(struct ice_hw *hw, u16 vsi_handle) 193262306a36Sopenharmony_ci{ 193362306a36Sopenharmony_ci const enum ice_block blk = ICE_BLK_RSS; 193462306a36Sopenharmony_ci struct ice_flow_prof *p, *t; 193562306a36Sopenharmony_ci int status = 0; 193662306a36Sopenharmony_ci 193762306a36Sopenharmony_ci if (!ice_is_vsi_valid(hw, vsi_handle)) 193862306a36Sopenharmony_ci return -EINVAL; 193962306a36Sopenharmony_ci 194062306a36Sopenharmony_ci if (list_empty(&hw->fl_profs[blk])) 194162306a36Sopenharmony_ci return 0; 194262306a36Sopenharmony_ci 194362306a36Sopenharmony_ci mutex_lock(&hw->rss_locks); 194462306a36Sopenharmony_ci list_for_each_entry_safe(p, t, &hw->fl_profs[blk], l_entry) 194562306a36Sopenharmony_ci if (test_bit(vsi_handle, p->vsis)) { 194662306a36Sopenharmony_ci status = ice_flow_disassoc_prof(hw, blk, p, vsi_handle); 194762306a36Sopenharmony_ci if (status) 194862306a36Sopenharmony_ci break; 194962306a36Sopenharmony_ci 195062306a36Sopenharmony_ci if (bitmap_empty(p->vsis, ICE_MAX_VSI)) { 195162306a36Sopenharmony_ci status = ice_flow_rem_prof(hw, blk, p->id); 195262306a36Sopenharmony_ci if (status) 195362306a36Sopenharmony_ci break; 195462306a36Sopenharmony_ci } 195562306a36Sopenharmony_ci } 195662306a36Sopenharmony_ci mutex_unlock(&hw->rss_locks); 195762306a36Sopenharmony_ci 195862306a36Sopenharmony_ci return status; 195962306a36Sopenharmony_ci} 196062306a36Sopenharmony_ci 196162306a36Sopenharmony_ci/** 196262306a36Sopenharmony_ci * ice_rem_rss_list - remove RSS configuration from list 196362306a36Sopenharmony_ci * @hw: pointer to the hardware structure 196462306a36Sopenharmony_ci * @vsi_handle: software VSI handle 196562306a36Sopenharmony_ci * @prof: pointer to flow profile 196662306a36Sopenharmony_ci * 196762306a36Sopenharmony_ci * Assumption: lock has already been acquired for RSS list 196862306a36Sopenharmony_ci */ 196962306a36Sopenharmony_cistatic void 197062306a36Sopenharmony_ciice_rem_rss_list(struct ice_hw *hw, u16 vsi_handle, struct ice_flow_prof *prof) 197162306a36Sopenharmony_ci{ 197262306a36Sopenharmony_ci struct ice_rss_cfg *r, *tmp; 197362306a36Sopenharmony_ci 197462306a36Sopenharmony_ci /* Search for RSS hash fields associated to the VSI that match the 197562306a36Sopenharmony_ci * hash configurations associated to the flow profile. If found 197662306a36Sopenharmony_ci * remove from the RSS entry list of the VSI context and delete entry. 197762306a36Sopenharmony_ci */ 197862306a36Sopenharmony_ci list_for_each_entry_safe(r, tmp, &hw->rss_list_head, l_entry) 197962306a36Sopenharmony_ci if (r->hashed_flds == prof->segs[prof->segs_cnt - 1].match && 198062306a36Sopenharmony_ci r->packet_hdr == prof->segs[prof->segs_cnt - 1].hdrs) { 198162306a36Sopenharmony_ci clear_bit(vsi_handle, r->vsis); 198262306a36Sopenharmony_ci if (bitmap_empty(r->vsis, ICE_MAX_VSI)) { 198362306a36Sopenharmony_ci list_del(&r->l_entry); 198462306a36Sopenharmony_ci devm_kfree(ice_hw_to_dev(hw), r); 198562306a36Sopenharmony_ci } 198662306a36Sopenharmony_ci return; 198762306a36Sopenharmony_ci } 198862306a36Sopenharmony_ci} 198962306a36Sopenharmony_ci 199062306a36Sopenharmony_ci/** 199162306a36Sopenharmony_ci * ice_add_rss_list - add RSS configuration to list 199262306a36Sopenharmony_ci * @hw: pointer to the hardware structure 199362306a36Sopenharmony_ci * @vsi_handle: software VSI handle 199462306a36Sopenharmony_ci * @prof: pointer to flow profile 199562306a36Sopenharmony_ci * 199662306a36Sopenharmony_ci * Assumption: lock has already been acquired for RSS list 199762306a36Sopenharmony_ci */ 199862306a36Sopenharmony_cistatic int 199962306a36Sopenharmony_ciice_add_rss_list(struct ice_hw *hw, u16 vsi_handle, struct ice_flow_prof *prof) 200062306a36Sopenharmony_ci{ 200162306a36Sopenharmony_ci struct ice_rss_cfg *r, *rss_cfg; 200262306a36Sopenharmony_ci 200362306a36Sopenharmony_ci list_for_each_entry(r, &hw->rss_list_head, l_entry) 200462306a36Sopenharmony_ci if (r->hashed_flds == prof->segs[prof->segs_cnt - 1].match && 200562306a36Sopenharmony_ci r->packet_hdr == prof->segs[prof->segs_cnt - 1].hdrs) { 200662306a36Sopenharmony_ci set_bit(vsi_handle, r->vsis); 200762306a36Sopenharmony_ci return 0; 200862306a36Sopenharmony_ci } 200962306a36Sopenharmony_ci 201062306a36Sopenharmony_ci rss_cfg = devm_kzalloc(ice_hw_to_dev(hw), sizeof(*rss_cfg), 201162306a36Sopenharmony_ci GFP_KERNEL); 201262306a36Sopenharmony_ci if (!rss_cfg) 201362306a36Sopenharmony_ci return -ENOMEM; 201462306a36Sopenharmony_ci 201562306a36Sopenharmony_ci rss_cfg->hashed_flds = prof->segs[prof->segs_cnt - 1].match; 201662306a36Sopenharmony_ci rss_cfg->packet_hdr = prof->segs[prof->segs_cnt - 1].hdrs; 201762306a36Sopenharmony_ci set_bit(vsi_handle, rss_cfg->vsis); 201862306a36Sopenharmony_ci 201962306a36Sopenharmony_ci list_add_tail(&rss_cfg->l_entry, &hw->rss_list_head); 202062306a36Sopenharmony_ci 202162306a36Sopenharmony_ci return 0; 202262306a36Sopenharmony_ci} 202362306a36Sopenharmony_ci 202462306a36Sopenharmony_ci#define ICE_FLOW_PROF_HASH_S 0 202562306a36Sopenharmony_ci#define ICE_FLOW_PROF_HASH_M (0xFFFFFFFFULL << ICE_FLOW_PROF_HASH_S) 202662306a36Sopenharmony_ci#define ICE_FLOW_PROF_HDR_S 32 202762306a36Sopenharmony_ci#define ICE_FLOW_PROF_HDR_M (0x3FFFFFFFULL << ICE_FLOW_PROF_HDR_S) 202862306a36Sopenharmony_ci#define ICE_FLOW_PROF_ENCAP_S 63 202962306a36Sopenharmony_ci#define ICE_FLOW_PROF_ENCAP_M (BIT_ULL(ICE_FLOW_PROF_ENCAP_S)) 203062306a36Sopenharmony_ci 203162306a36Sopenharmony_ci#define ICE_RSS_OUTER_HEADERS 1 203262306a36Sopenharmony_ci#define ICE_RSS_INNER_HEADERS 2 203362306a36Sopenharmony_ci 203462306a36Sopenharmony_ci/* Flow profile ID format: 203562306a36Sopenharmony_ci * [0:31] - Packet match fields 203662306a36Sopenharmony_ci * [32:62] - Protocol header 203762306a36Sopenharmony_ci * [63] - Encapsulation flag, 0 if non-tunneled, 1 if tunneled 203862306a36Sopenharmony_ci */ 203962306a36Sopenharmony_ci#define ICE_FLOW_GEN_PROFID(hash, hdr, segs_cnt) \ 204062306a36Sopenharmony_ci ((u64)(((u64)(hash) & ICE_FLOW_PROF_HASH_M) | \ 204162306a36Sopenharmony_ci (((u64)(hdr) << ICE_FLOW_PROF_HDR_S) & ICE_FLOW_PROF_HDR_M) | \ 204262306a36Sopenharmony_ci ((u8)((segs_cnt) - 1) ? ICE_FLOW_PROF_ENCAP_M : 0))) 204362306a36Sopenharmony_ci 204462306a36Sopenharmony_ci/** 204562306a36Sopenharmony_ci * ice_add_rss_cfg_sync - add an RSS configuration 204662306a36Sopenharmony_ci * @hw: pointer to the hardware structure 204762306a36Sopenharmony_ci * @vsi_handle: software VSI handle 204862306a36Sopenharmony_ci * @hashed_flds: hash bit fields (ICE_FLOW_HASH_*) to configure 204962306a36Sopenharmony_ci * @addl_hdrs: protocol header fields 205062306a36Sopenharmony_ci * @segs_cnt: packet segment count 205162306a36Sopenharmony_ci * 205262306a36Sopenharmony_ci * Assumption: lock has already been acquired for RSS list 205362306a36Sopenharmony_ci */ 205462306a36Sopenharmony_cistatic int 205562306a36Sopenharmony_ciice_add_rss_cfg_sync(struct ice_hw *hw, u16 vsi_handle, u64 hashed_flds, 205662306a36Sopenharmony_ci u32 addl_hdrs, u8 segs_cnt) 205762306a36Sopenharmony_ci{ 205862306a36Sopenharmony_ci const enum ice_block blk = ICE_BLK_RSS; 205962306a36Sopenharmony_ci struct ice_flow_prof *prof = NULL; 206062306a36Sopenharmony_ci struct ice_flow_seg_info *segs; 206162306a36Sopenharmony_ci int status; 206262306a36Sopenharmony_ci 206362306a36Sopenharmony_ci if (!segs_cnt || segs_cnt > ICE_FLOW_SEG_MAX) 206462306a36Sopenharmony_ci return -EINVAL; 206562306a36Sopenharmony_ci 206662306a36Sopenharmony_ci segs = kcalloc(segs_cnt, sizeof(*segs), GFP_KERNEL); 206762306a36Sopenharmony_ci if (!segs) 206862306a36Sopenharmony_ci return -ENOMEM; 206962306a36Sopenharmony_ci 207062306a36Sopenharmony_ci /* Construct the packet segment info from the hashed fields */ 207162306a36Sopenharmony_ci status = ice_flow_set_rss_seg_info(&segs[segs_cnt - 1], hashed_flds, 207262306a36Sopenharmony_ci addl_hdrs); 207362306a36Sopenharmony_ci if (status) 207462306a36Sopenharmony_ci goto exit; 207562306a36Sopenharmony_ci 207662306a36Sopenharmony_ci /* Search for a flow profile that has matching headers, hash fields 207762306a36Sopenharmony_ci * and has the input VSI associated to it. If found, no further 207862306a36Sopenharmony_ci * operations required and exit. 207962306a36Sopenharmony_ci */ 208062306a36Sopenharmony_ci prof = ice_flow_find_prof_conds(hw, blk, ICE_FLOW_RX, segs, segs_cnt, 208162306a36Sopenharmony_ci vsi_handle, 208262306a36Sopenharmony_ci ICE_FLOW_FIND_PROF_CHK_FLDS | 208362306a36Sopenharmony_ci ICE_FLOW_FIND_PROF_CHK_VSI); 208462306a36Sopenharmony_ci if (prof) 208562306a36Sopenharmony_ci goto exit; 208662306a36Sopenharmony_ci 208762306a36Sopenharmony_ci /* Check if a flow profile exists with the same protocol headers and 208862306a36Sopenharmony_ci * associated with the input VSI. If so disassociate the VSI from 208962306a36Sopenharmony_ci * this profile. The VSI will be added to a new profile created with 209062306a36Sopenharmony_ci * the protocol header and new hash field configuration. 209162306a36Sopenharmony_ci */ 209262306a36Sopenharmony_ci prof = ice_flow_find_prof_conds(hw, blk, ICE_FLOW_RX, segs, segs_cnt, 209362306a36Sopenharmony_ci vsi_handle, ICE_FLOW_FIND_PROF_CHK_VSI); 209462306a36Sopenharmony_ci if (prof) { 209562306a36Sopenharmony_ci status = ice_flow_disassoc_prof(hw, blk, prof, vsi_handle); 209662306a36Sopenharmony_ci if (!status) 209762306a36Sopenharmony_ci ice_rem_rss_list(hw, vsi_handle, prof); 209862306a36Sopenharmony_ci else 209962306a36Sopenharmony_ci goto exit; 210062306a36Sopenharmony_ci 210162306a36Sopenharmony_ci /* Remove profile if it has no VSIs associated */ 210262306a36Sopenharmony_ci if (bitmap_empty(prof->vsis, ICE_MAX_VSI)) { 210362306a36Sopenharmony_ci status = ice_flow_rem_prof(hw, blk, prof->id); 210462306a36Sopenharmony_ci if (status) 210562306a36Sopenharmony_ci goto exit; 210662306a36Sopenharmony_ci } 210762306a36Sopenharmony_ci } 210862306a36Sopenharmony_ci 210962306a36Sopenharmony_ci /* Search for a profile that has same match fields only. If this 211062306a36Sopenharmony_ci * exists then associate the VSI to this profile. 211162306a36Sopenharmony_ci */ 211262306a36Sopenharmony_ci prof = ice_flow_find_prof_conds(hw, blk, ICE_FLOW_RX, segs, segs_cnt, 211362306a36Sopenharmony_ci vsi_handle, 211462306a36Sopenharmony_ci ICE_FLOW_FIND_PROF_CHK_FLDS); 211562306a36Sopenharmony_ci if (prof) { 211662306a36Sopenharmony_ci status = ice_flow_assoc_prof(hw, blk, prof, vsi_handle); 211762306a36Sopenharmony_ci if (!status) 211862306a36Sopenharmony_ci status = ice_add_rss_list(hw, vsi_handle, prof); 211962306a36Sopenharmony_ci goto exit; 212062306a36Sopenharmony_ci } 212162306a36Sopenharmony_ci 212262306a36Sopenharmony_ci /* Create a new flow profile with generated profile and packet 212362306a36Sopenharmony_ci * segment information. 212462306a36Sopenharmony_ci */ 212562306a36Sopenharmony_ci status = ice_flow_add_prof(hw, blk, ICE_FLOW_RX, 212662306a36Sopenharmony_ci ICE_FLOW_GEN_PROFID(hashed_flds, 212762306a36Sopenharmony_ci segs[segs_cnt - 1].hdrs, 212862306a36Sopenharmony_ci segs_cnt), 212962306a36Sopenharmony_ci segs, segs_cnt, &prof); 213062306a36Sopenharmony_ci if (status) 213162306a36Sopenharmony_ci goto exit; 213262306a36Sopenharmony_ci 213362306a36Sopenharmony_ci status = ice_flow_assoc_prof(hw, blk, prof, vsi_handle); 213462306a36Sopenharmony_ci /* If association to a new flow profile failed then this profile can 213562306a36Sopenharmony_ci * be removed. 213662306a36Sopenharmony_ci */ 213762306a36Sopenharmony_ci if (status) { 213862306a36Sopenharmony_ci ice_flow_rem_prof(hw, blk, prof->id); 213962306a36Sopenharmony_ci goto exit; 214062306a36Sopenharmony_ci } 214162306a36Sopenharmony_ci 214262306a36Sopenharmony_ci status = ice_add_rss_list(hw, vsi_handle, prof); 214362306a36Sopenharmony_ci 214462306a36Sopenharmony_ciexit: 214562306a36Sopenharmony_ci kfree(segs); 214662306a36Sopenharmony_ci return status; 214762306a36Sopenharmony_ci} 214862306a36Sopenharmony_ci 214962306a36Sopenharmony_ci/** 215062306a36Sopenharmony_ci * ice_add_rss_cfg - add an RSS configuration with specified hashed fields 215162306a36Sopenharmony_ci * @hw: pointer to the hardware structure 215262306a36Sopenharmony_ci * @vsi_handle: software VSI handle 215362306a36Sopenharmony_ci * @hashed_flds: hash bit fields (ICE_FLOW_HASH_*) to configure 215462306a36Sopenharmony_ci * @addl_hdrs: protocol header fields 215562306a36Sopenharmony_ci * 215662306a36Sopenharmony_ci * This function will generate a flow profile based on fields associated with 215762306a36Sopenharmony_ci * the input fields to hash on, the flow type and use the VSI number to add 215862306a36Sopenharmony_ci * a flow entry to the profile. 215962306a36Sopenharmony_ci */ 216062306a36Sopenharmony_ciint 216162306a36Sopenharmony_ciice_add_rss_cfg(struct ice_hw *hw, u16 vsi_handle, u64 hashed_flds, 216262306a36Sopenharmony_ci u32 addl_hdrs) 216362306a36Sopenharmony_ci{ 216462306a36Sopenharmony_ci int status; 216562306a36Sopenharmony_ci 216662306a36Sopenharmony_ci if (hashed_flds == ICE_HASH_INVALID || 216762306a36Sopenharmony_ci !ice_is_vsi_valid(hw, vsi_handle)) 216862306a36Sopenharmony_ci return -EINVAL; 216962306a36Sopenharmony_ci 217062306a36Sopenharmony_ci mutex_lock(&hw->rss_locks); 217162306a36Sopenharmony_ci status = ice_add_rss_cfg_sync(hw, vsi_handle, hashed_flds, addl_hdrs, 217262306a36Sopenharmony_ci ICE_RSS_OUTER_HEADERS); 217362306a36Sopenharmony_ci if (!status) 217462306a36Sopenharmony_ci status = ice_add_rss_cfg_sync(hw, vsi_handle, hashed_flds, 217562306a36Sopenharmony_ci addl_hdrs, ICE_RSS_INNER_HEADERS); 217662306a36Sopenharmony_ci mutex_unlock(&hw->rss_locks); 217762306a36Sopenharmony_ci 217862306a36Sopenharmony_ci return status; 217962306a36Sopenharmony_ci} 218062306a36Sopenharmony_ci 218162306a36Sopenharmony_ci/** 218262306a36Sopenharmony_ci * ice_rem_rss_cfg_sync - remove an existing RSS configuration 218362306a36Sopenharmony_ci * @hw: pointer to the hardware structure 218462306a36Sopenharmony_ci * @vsi_handle: software VSI handle 218562306a36Sopenharmony_ci * @hashed_flds: Packet hash types (ICE_FLOW_HASH_*) to remove 218662306a36Sopenharmony_ci * @addl_hdrs: Protocol header fields within a packet segment 218762306a36Sopenharmony_ci * @segs_cnt: packet segment count 218862306a36Sopenharmony_ci * 218962306a36Sopenharmony_ci * Assumption: lock has already been acquired for RSS list 219062306a36Sopenharmony_ci */ 219162306a36Sopenharmony_cistatic int 219262306a36Sopenharmony_ciice_rem_rss_cfg_sync(struct ice_hw *hw, u16 vsi_handle, u64 hashed_flds, 219362306a36Sopenharmony_ci u32 addl_hdrs, u8 segs_cnt) 219462306a36Sopenharmony_ci{ 219562306a36Sopenharmony_ci const enum ice_block blk = ICE_BLK_RSS; 219662306a36Sopenharmony_ci struct ice_flow_seg_info *segs; 219762306a36Sopenharmony_ci struct ice_flow_prof *prof; 219862306a36Sopenharmony_ci int status; 219962306a36Sopenharmony_ci 220062306a36Sopenharmony_ci segs = kcalloc(segs_cnt, sizeof(*segs), GFP_KERNEL); 220162306a36Sopenharmony_ci if (!segs) 220262306a36Sopenharmony_ci return -ENOMEM; 220362306a36Sopenharmony_ci 220462306a36Sopenharmony_ci /* Construct the packet segment info from the hashed fields */ 220562306a36Sopenharmony_ci status = ice_flow_set_rss_seg_info(&segs[segs_cnt - 1], hashed_flds, 220662306a36Sopenharmony_ci addl_hdrs); 220762306a36Sopenharmony_ci if (status) 220862306a36Sopenharmony_ci goto out; 220962306a36Sopenharmony_ci 221062306a36Sopenharmony_ci prof = ice_flow_find_prof_conds(hw, blk, ICE_FLOW_RX, segs, segs_cnt, 221162306a36Sopenharmony_ci vsi_handle, 221262306a36Sopenharmony_ci ICE_FLOW_FIND_PROF_CHK_FLDS); 221362306a36Sopenharmony_ci if (!prof) { 221462306a36Sopenharmony_ci status = -ENOENT; 221562306a36Sopenharmony_ci goto out; 221662306a36Sopenharmony_ci } 221762306a36Sopenharmony_ci 221862306a36Sopenharmony_ci status = ice_flow_disassoc_prof(hw, blk, prof, vsi_handle); 221962306a36Sopenharmony_ci if (status) 222062306a36Sopenharmony_ci goto out; 222162306a36Sopenharmony_ci 222262306a36Sopenharmony_ci /* Remove RSS configuration from VSI context before deleting 222362306a36Sopenharmony_ci * the flow profile. 222462306a36Sopenharmony_ci */ 222562306a36Sopenharmony_ci ice_rem_rss_list(hw, vsi_handle, prof); 222662306a36Sopenharmony_ci 222762306a36Sopenharmony_ci if (bitmap_empty(prof->vsis, ICE_MAX_VSI)) 222862306a36Sopenharmony_ci status = ice_flow_rem_prof(hw, blk, prof->id); 222962306a36Sopenharmony_ci 223062306a36Sopenharmony_ciout: 223162306a36Sopenharmony_ci kfree(segs); 223262306a36Sopenharmony_ci return status; 223362306a36Sopenharmony_ci} 223462306a36Sopenharmony_ci 223562306a36Sopenharmony_ci/** 223662306a36Sopenharmony_ci * ice_rem_rss_cfg - remove an existing RSS config with matching hashed fields 223762306a36Sopenharmony_ci * @hw: pointer to the hardware structure 223862306a36Sopenharmony_ci * @vsi_handle: software VSI handle 223962306a36Sopenharmony_ci * @hashed_flds: Packet hash types (ICE_FLOW_HASH_*) to remove 224062306a36Sopenharmony_ci * @addl_hdrs: Protocol header fields within a packet segment 224162306a36Sopenharmony_ci * 224262306a36Sopenharmony_ci * This function will lookup the flow profile based on the input 224362306a36Sopenharmony_ci * hash field bitmap, iterate through the profile entry list of 224462306a36Sopenharmony_ci * that profile and find entry associated with input VSI to be 224562306a36Sopenharmony_ci * removed. Calls are made to underlying flow s which will APIs 224662306a36Sopenharmony_ci * turn build or update buffers for RSS XLT1 section. 224762306a36Sopenharmony_ci */ 224862306a36Sopenharmony_ciint __maybe_unused 224962306a36Sopenharmony_ciice_rem_rss_cfg(struct ice_hw *hw, u16 vsi_handle, u64 hashed_flds, 225062306a36Sopenharmony_ci u32 addl_hdrs) 225162306a36Sopenharmony_ci{ 225262306a36Sopenharmony_ci int status; 225362306a36Sopenharmony_ci 225462306a36Sopenharmony_ci if (hashed_flds == ICE_HASH_INVALID || 225562306a36Sopenharmony_ci !ice_is_vsi_valid(hw, vsi_handle)) 225662306a36Sopenharmony_ci return -EINVAL; 225762306a36Sopenharmony_ci 225862306a36Sopenharmony_ci mutex_lock(&hw->rss_locks); 225962306a36Sopenharmony_ci status = ice_rem_rss_cfg_sync(hw, vsi_handle, hashed_flds, addl_hdrs, 226062306a36Sopenharmony_ci ICE_RSS_OUTER_HEADERS); 226162306a36Sopenharmony_ci if (!status) 226262306a36Sopenharmony_ci status = ice_rem_rss_cfg_sync(hw, vsi_handle, hashed_flds, 226362306a36Sopenharmony_ci addl_hdrs, ICE_RSS_INNER_HEADERS); 226462306a36Sopenharmony_ci mutex_unlock(&hw->rss_locks); 226562306a36Sopenharmony_ci 226662306a36Sopenharmony_ci return status; 226762306a36Sopenharmony_ci} 226862306a36Sopenharmony_ci 226962306a36Sopenharmony_ci/* Mapping of AVF hash bit fields to an L3-L4 hash combination. 227062306a36Sopenharmony_ci * As the ice_flow_avf_hdr_field represent individual bit shifts in a hash, 227162306a36Sopenharmony_ci * convert its values to their appropriate flow L3, L4 values. 227262306a36Sopenharmony_ci */ 227362306a36Sopenharmony_ci#define ICE_FLOW_AVF_RSS_IPV4_MASKS \ 227462306a36Sopenharmony_ci (BIT_ULL(ICE_AVF_FLOW_FIELD_IPV4_OTHER) | \ 227562306a36Sopenharmony_ci BIT_ULL(ICE_AVF_FLOW_FIELD_FRAG_IPV4)) 227662306a36Sopenharmony_ci#define ICE_FLOW_AVF_RSS_TCP_IPV4_MASKS \ 227762306a36Sopenharmony_ci (BIT_ULL(ICE_AVF_FLOW_FIELD_IPV4_TCP_SYN_NO_ACK) | \ 227862306a36Sopenharmony_ci BIT_ULL(ICE_AVF_FLOW_FIELD_IPV4_TCP)) 227962306a36Sopenharmony_ci#define ICE_FLOW_AVF_RSS_UDP_IPV4_MASKS \ 228062306a36Sopenharmony_ci (BIT_ULL(ICE_AVF_FLOW_FIELD_UNICAST_IPV4_UDP) | \ 228162306a36Sopenharmony_ci BIT_ULL(ICE_AVF_FLOW_FIELD_MULTICAST_IPV4_UDP) | \ 228262306a36Sopenharmony_ci BIT_ULL(ICE_AVF_FLOW_FIELD_IPV4_UDP)) 228362306a36Sopenharmony_ci#define ICE_FLOW_AVF_RSS_ALL_IPV4_MASKS \ 228462306a36Sopenharmony_ci (ICE_FLOW_AVF_RSS_TCP_IPV4_MASKS | ICE_FLOW_AVF_RSS_UDP_IPV4_MASKS | \ 228562306a36Sopenharmony_ci ICE_FLOW_AVF_RSS_IPV4_MASKS | BIT_ULL(ICE_AVF_FLOW_FIELD_IPV4_SCTP)) 228662306a36Sopenharmony_ci 228762306a36Sopenharmony_ci#define ICE_FLOW_AVF_RSS_IPV6_MASKS \ 228862306a36Sopenharmony_ci (BIT_ULL(ICE_AVF_FLOW_FIELD_IPV6_OTHER) | \ 228962306a36Sopenharmony_ci BIT_ULL(ICE_AVF_FLOW_FIELD_FRAG_IPV6)) 229062306a36Sopenharmony_ci#define ICE_FLOW_AVF_RSS_UDP_IPV6_MASKS \ 229162306a36Sopenharmony_ci (BIT_ULL(ICE_AVF_FLOW_FIELD_UNICAST_IPV6_UDP) | \ 229262306a36Sopenharmony_ci BIT_ULL(ICE_AVF_FLOW_FIELD_MULTICAST_IPV6_UDP) | \ 229362306a36Sopenharmony_ci BIT_ULL(ICE_AVF_FLOW_FIELD_IPV6_UDP)) 229462306a36Sopenharmony_ci#define ICE_FLOW_AVF_RSS_TCP_IPV6_MASKS \ 229562306a36Sopenharmony_ci (BIT_ULL(ICE_AVF_FLOW_FIELD_IPV6_TCP_SYN_NO_ACK) | \ 229662306a36Sopenharmony_ci BIT_ULL(ICE_AVF_FLOW_FIELD_IPV6_TCP)) 229762306a36Sopenharmony_ci#define ICE_FLOW_AVF_RSS_ALL_IPV6_MASKS \ 229862306a36Sopenharmony_ci (ICE_FLOW_AVF_RSS_TCP_IPV6_MASKS | ICE_FLOW_AVF_RSS_UDP_IPV6_MASKS | \ 229962306a36Sopenharmony_ci ICE_FLOW_AVF_RSS_IPV6_MASKS | BIT_ULL(ICE_AVF_FLOW_FIELD_IPV6_SCTP)) 230062306a36Sopenharmony_ci 230162306a36Sopenharmony_ci/** 230262306a36Sopenharmony_ci * ice_add_avf_rss_cfg - add an RSS configuration for AVF driver 230362306a36Sopenharmony_ci * @hw: pointer to the hardware structure 230462306a36Sopenharmony_ci * @vsi_handle: software VSI handle 230562306a36Sopenharmony_ci * @avf_hash: hash bit fields (ICE_AVF_FLOW_FIELD_*) to configure 230662306a36Sopenharmony_ci * 230762306a36Sopenharmony_ci * This function will take the hash bitmap provided by the AVF driver via a 230862306a36Sopenharmony_ci * message, convert it to ICE-compatible values, and configure RSS flow 230962306a36Sopenharmony_ci * profiles. 231062306a36Sopenharmony_ci */ 231162306a36Sopenharmony_ciint ice_add_avf_rss_cfg(struct ice_hw *hw, u16 vsi_handle, u64 avf_hash) 231262306a36Sopenharmony_ci{ 231362306a36Sopenharmony_ci int status = 0; 231462306a36Sopenharmony_ci u64 hash_flds; 231562306a36Sopenharmony_ci 231662306a36Sopenharmony_ci if (avf_hash == ICE_AVF_FLOW_FIELD_INVALID || 231762306a36Sopenharmony_ci !ice_is_vsi_valid(hw, vsi_handle)) 231862306a36Sopenharmony_ci return -EINVAL; 231962306a36Sopenharmony_ci 232062306a36Sopenharmony_ci /* Make sure no unsupported bits are specified */ 232162306a36Sopenharmony_ci if (avf_hash & ~(ICE_FLOW_AVF_RSS_ALL_IPV4_MASKS | 232262306a36Sopenharmony_ci ICE_FLOW_AVF_RSS_ALL_IPV6_MASKS)) 232362306a36Sopenharmony_ci return -EIO; 232462306a36Sopenharmony_ci 232562306a36Sopenharmony_ci hash_flds = avf_hash; 232662306a36Sopenharmony_ci 232762306a36Sopenharmony_ci /* Always create an L3 RSS configuration for any L4 RSS configuration */ 232862306a36Sopenharmony_ci if (hash_flds & ICE_FLOW_AVF_RSS_ALL_IPV4_MASKS) 232962306a36Sopenharmony_ci hash_flds |= ICE_FLOW_AVF_RSS_IPV4_MASKS; 233062306a36Sopenharmony_ci 233162306a36Sopenharmony_ci if (hash_flds & ICE_FLOW_AVF_RSS_ALL_IPV6_MASKS) 233262306a36Sopenharmony_ci hash_flds |= ICE_FLOW_AVF_RSS_IPV6_MASKS; 233362306a36Sopenharmony_ci 233462306a36Sopenharmony_ci /* Create the corresponding RSS configuration for each valid hash bit */ 233562306a36Sopenharmony_ci while (hash_flds) { 233662306a36Sopenharmony_ci u64 rss_hash = ICE_HASH_INVALID; 233762306a36Sopenharmony_ci 233862306a36Sopenharmony_ci if (hash_flds & ICE_FLOW_AVF_RSS_ALL_IPV4_MASKS) { 233962306a36Sopenharmony_ci if (hash_flds & ICE_FLOW_AVF_RSS_IPV4_MASKS) { 234062306a36Sopenharmony_ci rss_hash = ICE_FLOW_HASH_IPV4; 234162306a36Sopenharmony_ci hash_flds &= ~ICE_FLOW_AVF_RSS_IPV4_MASKS; 234262306a36Sopenharmony_ci } else if (hash_flds & 234362306a36Sopenharmony_ci ICE_FLOW_AVF_RSS_TCP_IPV4_MASKS) { 234462306a36Sopenharmony_ci rss_hash = ICE_FLOW_HASH_IPV4 | 234562306a36Sopenharmony_ci ICE_FLOW_HASH_TCP_PORT; 234662306a36Sopenharmony_ci hash_flds &= ~ICE_FLOW_AVF_RSS_TCP_IPV4_MASKS; 234762306a36Sopenharmony_ci } else if (hash_flds & 234862306a36Sopenharmony_ci ICE_FLOW_AVF_RSS_UDP_IPV4_MASKS) { 234962306a36Sopenharmony_ci rss_hash = ICE_FLOW_HASH_IPV4 | 235062306a36Sopenharmony_ci ICE_FLOW_HASH_UDP_PORT; 235162306a36Sopenharmony_ci hash_flds &= ~ICE_FLOW_AVF_RSS_UDP_IPV4_MASKS; 235262306a36Sopenharmony_ci } else if (hash_flds & 235362306a36Sopenharmony_ci BIT_ULL(ICE_AVF_FLOW_FIELD_IPV4_SCTP)) { 235462306a36Sopenharmony_ci rss_hash = ICE_FLOW_HASH_IPV4 | 235562306a36Sopenharmony_ci ICE_FLOW_HASH_SCTP_PORT; 235662306a36Sopenharmony_ci hash_flds &= 235762306a36Sopenharmony_ci ~BIT_ULL(ICE_AVF_FLOW_FIELD_IPV4_SCTP); 235862306a36Sopenharmony_ci } 235962306a36Sopenharmony_ci } else if (hash_flds & ICE_FLOW_AVF_RSS_ALL_IPV6_MASKS) { 236062306a36Sopenharmony_ci if (hash_flds & ICE_FLOW_AVF_RSS_IPV6_MASKS) { 236162306a36Sopenharmony_ci rss_hash = ICE_FLOW_HASH_IPV6; 236262306a36Sopenharmony_ci hash_flds &= ~ICE_FLOW_AVF_RSS_IPV6_MASKS; 236362306a36Sopenharmony_ci } else if (hash_flds & 236462306a36Sopenharmony_ci ICE_FLOW_AVF_RSS_TCP_IPV6_MASKS) { 236562306a36Sopenharmony_ci rss_hash = ICE_FLOW_HASH_IPV6 | 236662306a36Sopenharmony_ci ICE_FLOW_HASH_TCP_PORT; 236762306a36Sopenharmony_ci hash_flds &= ~ICE_FLOW_AVF_RSS_TCP_IPV6_MASKS; 236862306a36Sopenharmony_ci } else if (hash_flds & 236962306a36Sopenharmony_ci ICE_FLOW_AVF_RSS_UDP_IPV6_MASKS) { 237062306a36Sopenharmony_ci rss_hash = ICE_FLOW_HASH_IPV6 | 237162306a36Sopenharmony_ci ICE_FLOW_HASH_UDP_PORT; 237262306a36Sopenharmony_ci hash_flds &= ~ICE_FLOW_AVF_RSS_UDP_IPV6_MASKS; 237362306a36Sopenharmony_ci } else if (hash_flds & 237462306a36Sopenharmony_ci BIT_ULL(ICE_AVF_FLOW_FIELD_IPV6_SCTP)) { 237562306a36Sopenharmony_ci rss_hash = ICE_FLOW_HASH_IPV6 | 237662306a36Sopenharmony_ci ICE_FLOW_HASH_SCTP_PORT; 237762306a36Sopenharmony_ci hash_flds &= 237862306a36Sopenharmony_ci ~BIT_ULL(ICE_AVF_FLOW_FIELD_IPV6_SCTP); 237962306a36Sopenharmony_ci } 238062306a36Sopenharmony_ci } 238162306a36Sopenharmony_ci 238262306a36Sopenharmony_ci if (rss_hash == ICE_HASH_INVALID) 238362306a36Sopenharmony_ci return -EIO; 238462306a36Sopenharmony_ci 238562306a36Sopenharmony_ci status = ice_add_rss_cfg(hw, vsi_handle, rss_hash, 238662306a36Sopenharmony_ci ICE_FLOW_SEG_HDR_NONE); 238762306a36Sopenharmony_ci if (status) 238862306a36Sopenharmony_ci break; 238962306a36Sopenharmony_ci } 239062306a36Sopenharmony_ci 239162306a36Sopenharmony_ci return status; 239262306a36Sopenharmony_ci} 239362306a36Sopenharmony_ci 239462306a36Sopenharmony_ci/** 239562306a36Sopenharmony_ci * ice_replay_rss_cfg - replay RSS configurations associated with VSI 239662306a36Sopenharmony_ci * @hw: pointer to the hardware structure 239762306a36Sopenharmony_ci * @vsi_handle: software VSI handle 239862306a36Sopenharmony_ci */ 239962306a36Sopenharmony_ciint ice_replay_rss_cfg(struct ice_hw *hw, u16 vsi_handle) 240062306a36Sopenharmony_ci{ 240162306a36Sopenharmony_ci struct ice_rss_cfg *r; 240262306a36Sopenharmony_ci int status = 0; 240362306a36Sopenharmony_ci 240462306a36Sopenharmony_ci if (!ice_is_vsi_valid(hw, vsi_handle)) 240562306a36Sopenharmony_ci return -EINVAL; 240662306a36Sopenharmony_ci 240762306a36Sopenharmony_ci mutex_lock(&hw->rss_locks); 240862306a36Sopenharmony_ci list_for_each_entry(r, &hw->rss_list_head, l_entry) { 240962306a36Sopenharmony_ci if (test_bit(vsi_handle, r->vsis)) { 241062306a36Sopenharmony_ci status = ice_add_rss_cfg_sync(hw, vsi_handle, 241162306a36Sopenharmony_ci r->hashed_flds, 241262306a36Sopenharmony_ci r->packet_hdr, 241362306a36Sopenharmony_ci ICE_RSS_OUTER_HEADERS); 241462306a36Sopenharmony_ci if (status) 241562306a36Sopenharmony_ci break; 241662306a36Sopenharmony_ci status = ice_add_rss_cfg_sync(hw, vsi_handle, 241762306a36Sopenharmony_ci r->hashed_flds, 241862306a36Sopenharmony_ci r->packet_hdr, 241962306a36Sopenharmony_ci ICE_RSS_INNER_HEADERS); 242062306a36Sopenharmony_ci if (status) 242162306a36Sopenharmony_ci break; 242262306a36Sopenharmony_ci } 242362306a36Sopenharmony_ci } 242462306a36Sopenharmony_ci mutex_unlock(&hw->rss_locks); 242562306a36Sopenharmony_ci 242662306a36Sopenharmony_ci return status; 242762306a36Sopenharmony_ci} 242862306a36Sopenharmony_ci 242962306a36Sopenharmony_ci/** 243062306a36Sopenharmony_ci * ice_get_rss_cfg - returns hashed fields for the given header types 243162306a36Sopenharmony_ci * @hw: pointer to the hardware structure 243262306a36Sopenharmony_ci * @vsi_handle: software VSI handle 243362306a36Sopenharmony_ci * @hdrs: protocol header type 243462306a36Sopenharmony_ci * 243562306a36Sopenharmony_ci * This function will return the match fields of the first instance of flow 243662306a36Sopenharmony_ci * profile having the given header types and containing input VSI 243762306a36Sopenharmony_ci */ 243862306a36Sopenharmony_ciu64 ice_get_rss_cfg(struct ice_hw *hw, u16 vsi_handle, u32 hdrs) 243962306a36Sopenharmony_ci{ 244062306a36Sopenharmony_ci u64 rss_hash = ICE_HASH_INVALID; 244162306a36Sopenharmony_ci struct ice_rss_cfg *r; 244262306a36Sopenharmony_ci 244362306a36Sopenharmony_ci /* verify if the protocol header is non zero and VSI is valid */ 244462306a36Sopenharmony_ci if (hdrs == ICE_FLOW_SEG_HDR_NONE || !ice_is_vsi_valid(hw, vsi_handle)) 244562306a36Sopenharmony_ci return ICE_HASH_INVALID; 244662306a36Sopenharmony_ci 244762306a36Sopenharmony_ci mutex_lock(&hw->rss_locks); 244862306a36Sopenharmony_ci list_for_each_entry(r, &hw->rss_list_head, l_entry) 244962306a36Sopenharmony_ci if (test_bit(vsi_handle, r->vsis) && 245062306a36Sopenharmony_ci r->packet_hdr == hdrs) { 245162306a36Sopenharmony_ci rss_hash = r->hashed_flds; 245262306a36Sopenharmony_ci break; 245362306a36Sopenharmony_ci } 245462306a36Sopenharmony_ci mutex_unlock(&hw->rss_locks); 245562306a36Sopenharmony_ci 245662306a36Sopenharmony_ci return rss_hash; 245762306a36Sopenharmony_ci} 2458