162306a36Sopenharmony_ci// SPDX-License-Identifier: GPL-2.0 262306a36Sopenharmony_ci/* Copyright (c) 2018, Intel Corporation. */ 362306a36Sopenharmony_ci 462306a36Sopenharmony_ci#include "ice_lib.h" 562306a36Sopenharmony_ci#include "ice_switch.h" 662306a36Sopenharmony_ci 762306a36Sopenharmony_ci#define ICE_ETH_DA_OFFSET 0 862306a36Sopenharmony_ci#define ICE_ETH_ETHTYPE_OFFSET 12 962306a36Sopenharmony_ci#define ICE_ETH_VLAN_TCI_OFFSET 14 1062306a36Sopenharmony_ci#define ICE_MAX_VLAN_ID 0xFFF 1162306a36Sopenharmony_ci#define ICE_IPV6_ETHER_ID 0x86DD 1262306a36Sopenharmony_ci 1362306a36Sopenharmony_ci/* Dummy ethernet header needed in the ice_aqc_sw_rules_elem 1462306a36Sopenharmony_ci * struct to configure any switch filter rules. 1562306a36Sopenharmony_ci * {DA (6 bytes), SA(6 bytes), 1662306a36Sopenharmony_ci * Ether type (2 bytes for header without VLAN tag) OR 1762306a36Sopenharmony_ci * VLAN tag (4 bytes for header with VLAN tag) } 1862306a36Sopenharmony_ci * 1962306a36Sopenharmony_ci * Word on Hardcoded values 2062306a36Sopenharmony_ci * byte 0 = 0x2: to identify it as locally administered DA MAC 2162306a36Sopenharmony_ci * byte 6 = 0x2: to identify it as locally administered SA MAC 2262306a36Sopenharmony_ci * byte 12 = 0x81 & byte 13 = 0x00: 2362306a36Sopenharmony_ci * In case of VLAN filter first two bytes defines ether type (0x8100) 2462306a36Sopenharmony_ci * and remaining two bytes are placeholder for programming a given VLAN ID 2562306a36Sopenharmony_ci * In case of Ether type filter it is treated as header without VLAN tag 2662306a36Sopenharmony_ci * and byte 12 and 13 is used to program a given Ether type instead 2762306a36Sopenharmony_ci */ 2862306a36Sopenharmony_cistatic const u8 dummy_eth_header[DUMMY_ETH_HDR_LEN] = { 0x2, 0, 0, 0, 0, 0, 2962306a36Sopenharmony_ci 0x2, 0, 0, 0, 0, 0, 3062306a36Sopenharmony_ci 0x81, 0, 0, 0}; 3162306a36Sopenharmony_ci 3262306a36Sopenharmony_cienum { 3362306a36Sopenharmony_ci ICE_PKT_OUTER_IPV6 = BIT(0), 3462306a36Sopenharmony_ci ICE_PKT_TUN_GTPC = BIT(1), 3562306a36Sopenharmony_ci ICE_PKT_TUN_GTPU = BIT(2), 3662306a36Sopenharmony_ci ICE_PKT_TUN_NVGRE = BIT(3), 3762306a36Sopenharmony_ci ICE_PKT_TUN_UDP = BIT(4), 3862306a36Sopenharmony_ci ICE_PKT_INNER_IPV6 = BIT(5), 3962306a36Sopenharmony_ci ICE_PKT_INNER_TCP = BIT(6), 4062306a36Sopenharmony_ci ICE_PKT_INNER_UDP = BIT(7), 4162306a36Sopenharmony_ci ICE_PKT_GTP_NOPAY = BIT(8), 4262306a36Sopenharmony_ci ICE_PKT_KMALLOC = BIT(9), 4362306a36Sopenharmony_ci ICE_PKT_PPPOE = BIT(10), 4462306a36Sopenharmony_ci ICE_PKT_L2TPV3 = BIT(11), 4562306a36Sopenharmony_ci}; 4662306a36Sopenharmony_ci 4762306a36Sopenharmony_cistruct ice_dummy_pkt_offsets { 4862306a36Sopenharmony_ci enum ice_protocol_type type; 4962306a36Sopenharmony_ci u16 offset; /* ICE_PROTOCOL_LAST indicates end of list */ 5062306a36Sopenharmony_ci}; 5162306a36Sopenharmony_ci 5262306a36Sopenharmony_cistruct ice_dummy_pkt_profile { 5362306a36Sopenharmony_ci const struct ice_dummy_pkt_offsets *offsets; 5462306a36Sopenharmony_ci const u8 *pkt; 5562306a36Sopenharmony_ci u32 match; 5662306a36Sopenharmony_ci u16 pkt_len; 5762306a36Sopenharmony_ci u16 offsets_len; 5862306a36Sopenharmony_ci}; 5962306a36Sopenharmony_ci 6062306a36Sopenharmony_ci#define ICE_DECLARE_PKT_OFFSETS(type) \ 6162306a36Sopenharmony_ci static const struct ice_dummy_pkt_offsets \ 6262306a36Sopenharmony_ci ice_dummy_##type##_packet_offsets[] 6362306a36Sopenharmony_ci 6462306a36Sopenharmony_ci#define ICE_DECLARE_PKT_TEMPLATE(type) \ 6562306a36Sopenharmony_ci static const u8 ice_dummy_##type##_packet[] 6662306a36Sopenharmony_ci 6762306a36Sopenharmony_ci#define ICE_PKT_PROFILE(type, m) { \ 6862306a36Sopenharmony_ci .match = (m), \ 6962306a36Sopenharmony_ci .pkt = ice_dummy_##type##_packet, \ 7062306a36Sopenharmony_ci .pkt_len = sizeof(ice_dummy_##type##_packet), \ 7162306a36Sopenharmony_ci .offsets = ice_dummy_##type##_packet_offsets, \ 7262306a36Sopenharmony_ci .offsets_len = sizeof(ice_dummy_##type##_packet_offsets), \ 7362306a36Sopenharmony_ci} 7462306a36Sopenharmony_ci 7562306a36Sopenharmony_ciICE_DECLARE_PKT_OFFSETS(vlan) = { 7662306a36Sopenharmony_ci { ICE_VLAN_OFOS, 12 }, 7762306a36Sopenharmony_ci}; 7862306a36Sopenharmony_ci 7962306a36Sopenharmony_ciICE_DECLARE_PKT_TEMPLATE(vlan) = { 8062306a36Sopenharmony_ci 0x81, 0x00, 0x00, 0x00, /* ICE_VLAN_OFOS 12 */ 8162306a36Sopenharmony_ci}; 8262306a36Sopenharmony_ci 8362306a36Sopenharmony_ciICE_DECLARE_PKT_OFFSETS(qinq) = { 8462306a36Sopenharmony_ci { ICE_VLAN_EX, 12 }, 8562306a36Sopenharmony_ci { ICE_VLAN_IN, 16 }, 8662306a36Sopenharmony_ci}; 8762306a36Sopenharmony_ci 8862306a36Sopenharmony_ciICE_DECLARE_PKT_TEMPLATE(qinq) = { 8962306a36Sopenharmony_ci 0x91, 0x00, 0x00, 0x00, /* ICE_VLAN_EX 12 */ 9062306a36Sopenharmony_ci 0x81, 0x00, 0x00, 0x00, /* ICE_VLAN_IN 16 */ 9162306a36Sopenharmony_ci}; 9262306a36Sopenharmony_ci 9362306a36Sopenharmony_ciICE_DECLARE_PKT_OFFSETS(gre_tcp) = { 9462306a36Sopenharmony_ci { ICE_MAC_OFOS, 0 }, 9562306a36Sopenharmony_ci { ICE_ETYPE_OL, 12 }, 9662306a36Sopenharmony_ci { ICE_IPV4_OFOS, 14 }, 9762306a36Sopenharmony_ci { ICE_NVGRE, 34 }, 9862306a36Sopenharmony_ci { ICE_MAC_IL, 42 }, 9962306a36Sopenharmony_ci { ICE_ETYPE_IL, 54 }, 10062306a36Sopenharmony_ci { ICE_IPV4_IL, 56 }, 10162306a36Sopenharmony_ci { ICE_TCP_IL, 76 }, 10262306a36Sopenharmony_ci { ICE_PROTOCOL_LAST, 0 }, 10362306a36Sopenharmony_ci}; 10462306a36Sopenharmony_ci 10562306a36Sopenharmony_ciICE_DECLARE_PKT_TEMPLATE(gre_tcp) = { 10662306a36Sopenharmony_ci 0x00, 0x00, 0x00, 0x00, /* ICE_MAC_OFOS 0 */ 10762306a36Sopenharmony_ci 0x00, 0x00, 0x00, 0x00, 10862306a36Sopenharmony_ci 0x00, 0x00, 0x00, 0x00, 10962306a36Sopenharmony_ci 11062306a36Sopenharmony_ci 0x08, 0x00, /* ICE_ETYPE_OL 12 */ 11162306a36Sopenharmony_ci 11262306a36Sopenharmony_ci 0x45, 0x00, 0x00, 0x3E, /* ICE_IPV4_OFOS 14 */ 11362306a36Sopenharmony_ci 0x00, 0x00, 0x00, 0x00, 11462306a36Sopenharmony_ci 0x00, 0x2F, 0x00, 0x00, 11562306a36Sopenharmony_ci 0x00, 0x00, 0x00, 0x00, 11662306a36Sopenharmony_ci 0x00, 0x00, 0x00, 0x00, 11762306a36Sopenharmony_ci 11862306a36Sopenharmony_ci 0x80, 0x00, 0x65, 0x58, /* ICE_NVGRE 34 */ 11962306a36Sopenharmony_ci 0x00, 0x00, 0x00, 0x00, 12062306a36Sopenharmony_ci 12162306a36Sopenharmony_ci 0x00, 0x00, 0x00, 0x00, /* ICE_MAC_IL 42 */ 12262306a36Sopenharmony_ci 0x00, 0x00, 0x00, 0x00, 12362306a36Sopenharmony_ci 0x00, 0x00, 0x00, 0x00, 12462306a36Sopenharmony_ci 12562306a36Sopenharmony_ci 0x08, 0x00, /* ICE_ETYPE_IL 54 */ 12662306a36Sopenharmony_ci 12762306a36Sopenharmony_ci 0x45, 0x00, 0x00, 0x14, /* ICE_IPV4_IL 56 */ 12862306a36Sopenharmony_ci 0x00, 0x00, 0x00, 0x00, 12962306a36Sopenharmony_ci 0x00, 0x06, 0x00, 0x00, 13062306a36Sopenharmony_ci 0x00, 0x00, 0x00, 0x00, 13162306a36Sopenharmony_ci 0x00, 0x00, 0x00, 0x00, 13262306a36Sopenharmony_ci 13362306a36Sopenharmony_ci 0x00, 0x00, 0x00, 0x00, /* ICE_TCP_IL 76 */ 13462306a36Sopenharmony_ci 0x00, 0x00, 0x00, 0x00, 13562306a36Sopenharmony_ci 0x00, 0x00, 0x00, 0x00, 13662306a36Sopenharmony_ci 0x50, 0x02, 0x20, 0x00, 13762306a36Sopenharmony_ci 0x00, 0x00, 0x00, 0x00 13862306a36Sopenharmony_ci}; 13962306a36Sopenharmony_ci 14062306a36Sopenharmony_ciICE_DECLARE_PKT_OFFSETS(gre_udp) = { 14162306a36Sopenharmony_ci { ICE_MAC_OFOS, 0 }, 14262306a36Sopenharmony_ci { ICE_ETYPE_OL, 12 }, 14362306a36Sopenharmony_ci { ICE_IPV4_OFOS, 14 }, 14462306a36Sopenharmony_ci { ICE_NVGRE, 34 }, 14562306a36Sopenharmony_ci { ICE_MAC_IL, 42 }, 14662306a36Sopenharmony_ci { ICE_ETYPE_IL, 54 }, 14762306a36Sopenharmony_ci { ICE_IPV4_IL, 56 }, 14862306a36Sopenharmony_ci { ICE_UDP_ILOS, 76 }, 14962306a36Sopenharmony_ci { ICE_PROTOCOL_LAST, 0 }, 15062306a36Sopenharmony_ci}; 15162306a36Sopenharmony_ci 15262306a36Sopenharmony_ciICE_DECLARE_PKT_TEMPLATE(gre_udp) = { 15362306a36Sopenharmony_ci 0x00, 0x00, 0x00, 0x00, /* ICE_MAC_OFOS 0 */ 15462306a36Sopenharmony_ci 0x00, 0x00, 0x00, 0x00, 15562306a36Sopenharmony_ci 0x00, 0x00, 0x00, 0x00, 15662306a36Sopenharmony_ci 15762306a36Sopenharmony_ci 0x08, 0x00, /* ICE_ETYPE_OL 12 */ 15862306a36Sopenharmony_ci 15962306a36Sopenharmony_ci 0x45, 0x00, 0x00, 0x3E, /* ICE_IPV4_OFOS 14 */ 16062306a36Sopenharmony_ci 0x00, 0x00, 0x00, 0x00, 16162306a36Sopenharmony_ci 0x00, 0x2F, 0x00, 0x00, 16262306a36Sopenharmony_ci 0x00, 0x00, 0x00, 0x00, 16362306a36Sopenharmony_ci 0x00, 0x00, 0x00, 0x00, 16462306a36Sopenharmony_ci 16562306a36Sopenharmony_ci 0x80, 0x00, 0x65, 0x58, /* ICE_NVGRE 34 */ 16662306a36Sopenharmony_ci 0x00, 0x00, 0x00, 0x00, 16762306a36Sopenharmony_ci 16862306a36Sopenharmony_ci 0x00, 0x00, 0x00, 0x00, /* ICE_MAC_IL 42 */ 16962306a36Sopenharmony_ci 0x00, 0x00, 0x00, 0x00, 17062306a36Sopenharmony_ci 0x00, 0x00, 0x00, 0x00, 17162306a36Sopenharmony_ci 17262306a36Sopenharmony_ci 0x08, 0x00, /* ICE_ETYPE_IL 54 */ 17362306a36Sopenharmony_ci 17462306a36Sopenharmony_ci 0x45, 0x00, 0x00, 0x14, /* ICE_IPV4_IL 56 */ 17562306a36Sopenharmony_ci 0x00, 0x00, 0x00, 0x00, 17662306a36Sopenharmony_ci 0x00, 0x11, 0x00, 0x00, 17762306a36Sopenharmony_ci 0x00, 0x00, 0x00, 0x00, 17862306a36Sopenharmony_ci 0x00, 0x00, 0x00, 0x00, 17962306a36Sopenharmony_ci 18062306a36Sopenharmony_ci 0x00, 0x00, 0x00, 0x00, /* ICE_UDP_ILOS 76 */ 18162306a36Sopenharmony_ci 0x00, 0x08, 0x00, 0x00, 18262306a36Sopenharmony_ci}; 18362306a36Sopenharmony_ci 18462306a36Sopenharmony_ciICE_DECLARE_PKT_OFFSETS(udp_tun_tcp) = { 18562306a36Sopenharmony_ci { ICE_MAC_OFOS, 0 }, 18662306a36Sopenharmony_ci { ICE_ETYPE_OL, 12 }, 18762306a36Sopenharmony_ci { ICE_IPV4_OFOS, 14 }, 18862306a36Sopenharmony_ci { ICE_UDP_OF, 34 }, 18962306a36Sopenharmony_ci { ICE_VXLAN, 42 }, 19062306a36Sopenharmony_ci { ICE_GENEVE, 42 }, 19162306a36Sopenharmony_ci { ICE_VXLAN_GPE, 42 }, 19262306a36Sopenharmony_ci { ICE_MAC_IL, 50 }, 19362306a36Sopenharmony_ci { ICE_ETYPE_IL, 62 }, 19462306a36Sopenharmony_ci { ICE_IPV4_IL, 64 }, 19562306a36Sopenharmony_ci { ICE_TCP_IL, 84 }, 19662306a36Sopenharmony_ci { ICE_PROTOCOL_LAST, 0 }, 19762306a36Sopenharmony_ci}; 19862306a36Sopenharmony_ci 19962306a36Sopenharmony_ciICE_DECLARE_PKT_TEMPLATE(udp_tun_tcp) = { 20062306a36Sopenharmony_ci 0x00, 0x00, 0x00, 0x00, /* ICE_MAC_OFOS 0 */ 20162306a36Sopenharmony_ci 0x00, 0x00, 0x00, 0x00, 20262306a36Sopenharmony_ci 0x00, 0x00, 0x00, 0x00, 20362306a36Sopenharmony_ci 20462306a36Sopenharmony_ci 0x08, 0x00, /* ICE_ETYPE_OL 12 */ 20562306a36Sopenharmony_ci 20662306a36Sopenharmony_ci 0x45, 0x00, 0x00, 0x5a, /* ICE_IPV4_OFOS 14 */ 20762306a36Sopenharmony_ci 0x00, 0x01, 0x00, 0x00, 20862306a36Sopenharmony_ci 0x40, 0x11, 0x00, 0x00, 20962306a36Sopenharmony_ci 0x00, 0x00, 0x00, 0x00, 21062306a36Sopenharmony_ci 0x00, 0x00, 0x00, 0x00, 21162306a36Sopenharmony_ci 21262306a36Sopenharmony_ci 0x00, 0x00, 0x12, 0xb5, /* ICE_UDP_OF 34 */ 21362306a36Sopenharmony_ci 0x00, 0x46, 0x00, 0x00, 21462306a36Sopenharmony_ci 21562306a36Sopenharmony_ci 0x00, 0x00, 0x65, 0x58, /* ICE_VXLAN 42 */ 21662306a36Sopenharmony_ci 0x00, 0x00, 0x00, 0x00, 21762306a36Sopenharmony_ci 21862306a36Sopenharmony_ci 0x00, 0x00, 0x00, 0x00, /* ICE_MAC_IL 50 */ 21962306a36Sopenharmony_ci 0x00, 0x00, 0x00, 0x00, 22062306a36Sopenharmony_ci 0x00, 0x00, 0x00, 0x00, 22162306a36Sopenharmony_ci 22262306a36Sopenharmony_ci 0x08, 0x00, /* ICE_ETYPE_IL 62 */ 22362306a36Sopenharmony_ci 22462306a36Sopenharmony_ci 0x45, 0x00, 0x00, 0x28, /* ICE_IPV4_IL 64 */ 22562306a36Sopenharmony_ci 0x00, 0x01, 0x00, 0x00, 22662306a36Sopenharmony_ci 0x40, 0x06, 0x00, 0x00, 22762306a36Sopenharmony_ci 0x00, 0x00, 0x00, 0x00, 22862306a36Sopenharmony_ci 0x00, 0x00, 0x00, 0x00, 22962306a36Sopenharmony_ci 23062306a36Sopenharmony_ci 0x00, 0x00, 0x00, 0x00, /* ICE_TCP_IL 84 */ 23162306a36Sopenharmony_ci 0x00, 0x00, 0x00, 0x00, 23262306a36Sopenharmony_ci 0x00, 0x00, 0x00, 0x00, 23362306a36Sopenharmony_ci 0x50, 0x02, 0x20, 0x00, 23462306a36Sopenharmony_ci 0x00, 0x00, 0x00, 0x00 23562306a36Sopenharmony_ci}; 23662306a36Sopenharmony_ci 23762306a36Sopenharmony_ciICE_DECLARE_PKT_OFFSETS(udp_tun_udp) = { 23862306a36Sopenharmony_ci { ICE_MAC_OFOS, 0 }, 23962306a36Sopenharmony_ci { ICE_ETYPE_OL, 12 }, 24062306a36Sopenharmony_ci { ICE_IPV4_OFOS, 14 }, 24162306a36Sopenharmony_ci { ICE_UDP_OF, 34 }, 24262306a36Sopenharmony_ci { ICE_VXLAN, 42 }, 24362306a36Sopenharmony_ci { ICE_GENEVE, 42 }, 24462306a36Sopenharmony_ci { ICE_VXLAN_GPE, 42 }, 24562306a36Sopenharmony_ci { ICE_MAC_IL, 50 }, 24662306a36Sopenharmony_ci { ICE_ETYPE_IL, 62 }, 24762306a36Sopenharmony_ci { ICE_IPV4_IL, 64 }, 24862306a36Sopenharmony_ci { ICE_UDP_ILOS, 84 }, 24962306a36Sopenharmony_ci { ICE_PROTOCOL_LAST, 0 }, 25062306a36Sopenharmony_ci}; 25162306a36Sopenharmony_ci 25262306a36Sopenharmony_ciICE_DECLARE_PKT_TEMPLATE(udp_tun_udp) = { 25362306a36Sopenharmony_ci 0x00, 0x00, 0x00, 0x00, /* ICE_MAC_OFOS 0 */ 25462306a36Sopenharmony_ci 0x00, 0x00, 0x00, 0x00, 25562306a36Sopenharmony_ci 0x00, 0x00, 0x00, 0x00, 25662306a36Sopenharmony_ci 25762306a36Sopenharmony_ci 0x08, 0x00, /* ICE_ETYPE_OL 12 */ 25862306a36Sopenharmony_ci 25962306a36Sopenharmony_ci 0x45, 0x00, 0x00, 0x4e, /* ICE_IPV4_OFOS 14 */ 26062306a36Sopenharmony_ci 0x00, 0x01, 0x00, 0x00, 26162306a36Sopenharmony_ci 0x00, 0x11, 0x00, 0x00, 26262306a36Sopenharmony_ci 0x00, 0x00, 0x00, 0x00, 26362306a36Sopenharmony_ci 0x00, 0x00, 0x00, 0x00, 26462306a36Sopenharmony_ci 26562306a36Sopenharmony_ci 0x00, 0x00, 0x12, 0xb5, /* ICE_UDP_OF 34 */ 26662306a36Sopenharmony_ci 0x00, 0x3a, 0x00, 0x00, 26762306a36Sopenharmony_ci 26862306a36Sopenharmony_ci 0x00, 0x00, 0x65, 0x58, /* ICE_VXLAN 42 */ 26962306a36Sopenharmony_ci 0x00, 0x00, 0x00, 0x00, 27062306a36Sopenharmony_ci 27162306a36Sopenharmony_ci 0x00, 0x00, 0x00, 0x00, /* ICE_MAC_IL 50 */ 27262306a36Sopenharmony_ci 0x00, 0x00, 0x00, 0x00, 27362306a36Sopenharmony_ci 0x00, 0x00, 0x00, 0x00, 27462306a36Sopenharmony_ci 27562306a36Sopenharmony_ci 0x08, 0x00, /* ICE_ETYPE_IL 62 */ 27662306a36Sopenharmony_ci 27762306a36Sopenharmony_ci 0x45, 0x00, 0x00, 0x1c, /* ICE_IPV4_IL 64 */ 27862306a36Sopenharmony_ci 0x00, 0x01, 0x00, 0x00, 27962306a36Sopenharmony_ci 0x00, 0x11, 0x00, 0x00, 28062306a36Sopenharmony_ci 0x00, 0x00, 0x00, 0x00, 28162306a36Sopenharmony_ci 0x00, 0x00, 0x00, 0x00, 28262306a36Sopenharmony_ci 28362306a36Sopenharmony_ci 0x00, 0x00, 0x00, 0x00, /* ICE_UDP_ILOS 84 */ 28462306a36Sopenharmony_ci 0x00, 0x08, 0x00, 0x00, 28562306a36Sopenharmony_ci}; 28662306a36Sopenharmony_ci 28762306a36Sopenharmony_ciICE_DECLARE_PKT_OFFSETS(gre_ipv6_tcp) = { 28862306a36Sopenharmony_ci { ICE_MAC_OFOS, 0 }, 28962306a36Sopenharmony_ci { ICE_ETYPE_OL, 12 }, 29062306a36Sopenharmony_ci { ICE_IPV4_OFOS, 14 }, 29162306a36Sopenharmony_ci { ICE_NVGRE, 34 }, 29262306a36Sopenharmony_ci { ICE_MAC_IL, 42 }, 29362306a36Sopenharmony_ci { ICE_ETYPE_IL, 54 }, 29462306a36Sopenharmony_ci { ICE_IPV6_IL, 56 }, 29562306a36Sopenharmony_ci { ICE_TCP_IL, 96 }, 29662306a36Sopenharmony_ci { ICE_PROTOCOL_LAST, 0 }, 29762306a36Sopenharmony_ci}; 29862306a36Sopenharmony_ci 29962306a36Sopenharmony_ciICE_DECLARE_PKT_TEMPLATE(gre_ipv6_tcp) = { 30062306a36Sopenharmony_ci 0x00, 0x00, 0x00, 0x00, /* ICE_MAC_OFOS 0 */ 30162306a36Sopenharmony_ci 0x00, 0x00, 0x00, 0x00, 30262306a36Sopenharmony_ci 0x00, 0x00, 0x00, 0x00, 30362306a36Sopenharmony_ci 30462306a36Sopenharmony_ci 0x08, 0x00, /* ICE_ETYPE_OL 12 */ 30562306a36Sopenharmony_ci 30662306a36Sopenharmony_ci 0x45, 0x00, 0x00, 0x66, /* ICE_IPV4_OFOS 14 */ 30762306a36Sopenharmony_ci 0x00, 0x00, 0x00, 0x00, 30862306a36Sopenharmony_ci 0x00, 0x2F, 0x00, 0x00, 30962306a36Sopenharmony_ci 0x00, 0x00, 0x00, 0x00, 31062306a36Sopenharmony_ci 0x00, 0x00, 0x00, 0x00, 31162306a36Sopenharmony_ci 31262306a36Sopenharmony_ci 0x80, 0x00, 0x65, 0x58, /* ICE_NVGRE 34 */ 31362306a36Sopenharmony_ci 0x00, 0x00, 0x00, 0x00, 31462306a36Sopenharmony_ci 31562306a36Sopenharmony_ci 0x00, 0x00, 0x00, 0x00, /* ICE_MAC_IL 42 */ 31662306a36Sopenharmony_ci 0x00, 0x00, 0x00, 0x00, 31762306a36Sopenharmony_ci 0x00, 0x00, 0x00, 0x00, 31862306a36Sopenharmony_ci 31962306a36Sopenharmony_ci 0x86, 0xdd, /* ICE_ETYPE_IL 54 */ 32062306a36Sopenharmony_ci 32162306a36Sopenharmony_ci 0x60, 0x00, 0x00, 0x00, /* ICE_IPV6_IL 56 */ 32262306a36Sopenharmony_ci 0x00, 0x08, 0x06, 0x40, 32362306a36Sopenharmony_ci 0x00, 0x00, 0x00, 0x00, 32462306a36Sopenharmony_ci 0x00, 0x00, 0x00, 0x00, 32562306a36Sopenharmony_ci 0x00, 0x00, 0x00, 0x00, 32662306a36Sopenharmony_ci 0x00, 0x00, 0x00, 0x00, 32762306a36Sopenharmony_ci 0x00, 0x00, 0x00, 0x00, 32862306a36Sopenharmony_ci 0x00, 0x00, 0x00, 0x00, 32962306a36Sopenharmony_ci 0x00, 0x00, 0x00, 0x00, 33062306a36Sopenharmony_ci 0x00, 0x00, 0x00, 0x00, 33162306a36Sopenharmony_ci 33262306a36Sopenharmony_ci 0x00, 0x00, 0x00, 0x00, /* ICE_TCP_IL 96 */ 33362306a36Sopenharmony_ci 0x00, 0x00, 0x00, 0x00, 33462306a36Sopenharmony_ci 0x00, 0x00, 0x00, 0x00, 33562306a36Sopenharmony_ci 0x50, 0x02, 0x20, 0x00, 33662306a36Sopenharmony_ci 0x00, 0x00, 0x00, 0x00 33762306a36Sopenharmony_ci}; 33862306a36Sopenharmony_ci 33962306a36Sopenharmony_ciICE_DECLARE_PKT_OFFSETS(gre_ipv6_udp) = { 34062306a36Sopenharmony_ci { ICE_MAC_OFOS, 0 }, 34162306a36Sopenharmony_ci { ICE_ETYPE_OL, 12 }, 34262306a36Sopenharmony_ci { ICE_IPV4_OFOS, 14 }, 34362306a36Sopenharmony_ci { ICE_NVGRE, 34 }, 34462306a36Sopenharmony_ci { ICE_MAC_IL, 42 }, 34562306a36Sopenharmony_ci { ICE_ETYPE_IL, 54 }, 34662306a36Sopenharmony_ci { ICE_IPV6_IL, 56 }, 34762306a36Sopenharmony_ci { ICE_UDP_ILOS, 96 }, 34862306a36Sopenharmony_ci { ICE_PROTOCOL_LAST, 0 }, 34962306a36Sopenharmony_ci}; 35062306a36Sopenharmony_ci 35162306a36Sopenharmony_ciICE_DECLARE_PKT_TEMPLATE(gre_ipv6_udp) = { 35262306a36Sopenharmony_ci 0x00, 0x00, 0x00, 0x00, /* ICE_MAC_OFOS 0 */ 35362306a36Sopenharmony_ci 0x00, 0x00, 0x00, 0x00, 35462306a36Sopenharmony_ci 0x00, 0x00, 0x00, 0x00, 35562306a36Sopenharmony_ci 35662306a36Sopenharmony_ci 0x08, 0x00, /* ICE_ETYPE_OL 12 */ 35762306a36Sopenharmony_ci 35862306a36Sopenharmony_ci 0x45, 0x00, 0x00, 0x5a, /* ICE_IPV4_OFOS 14 */ 35962306a36Sopenharmony_ci 0x00, 0x00, 0x00, 0x00, 36062306a36Sopenharmony_ci 0x00, 0x2F, 0x00, 0x00, 36162306a36Sopenharmony_ci 0x00, 0x00, 0x00, 0x00, 36262306a36Sopenharmony_ci 0x00, 0x00, 0x00, 0x00, 36362306a36Sopenharmony_ci 36462306a36Sopenharmony_ci 0x80, 0x00, 0x65, 0x58, /* ICE_NVGRE 34 */ 36562306a36Sopenharmony_ci 0x00, 0x00, 0x00, 0x00, 36662306a36Sopenharmony_ci 36762306a36Sopenharmony_ci 0x00, 0x00, 0x00, 0x00, /* ICE_MAC_IL 42 */ 36862306a36Sopenharmony_ci 0x00, 0x00, 0x00, 0x00, 36962306a36Sopenharmony_ci 0x00, 0x00, 0x00, 0x00, 37062306a36Sopenharmony_ci 37162306a36Sopenharmony_ci 0x86, 0xdd, /* ICE_ETYPE_IL 54 */ 37262306a36Sopenharmony_ci 37362306a36Sopenharmony_ci 0x60, 0x00, 0x00, 0x00, /* ICE_IPV6_IL 56 */ 37462306a36Sopenharmony_ci 0x00, 0x08, 0x11, 0x40, 37562306a36Sopenharmony_ci 0x00, 0x00, 0x00, 0x00, 37662306a36Sopenharmony_ci 0x00, 0x00, 0x00, 0x00, 37762306a36Sopenharmony_ci 0x00, 0x00, 0x00, 0x00, 37862306a36Sopenharmony_ci 0x00, 0x00, 0x00, 0x00, 37962306a36Sopenharmony_ci 0x00, 0x00, 0x00, 0x00, 38062306a36Sopenharmony_ci 0x00, 0x00, 0x00, 0x00, 38162306a36Sopenharmony_ci 0x00, 0x00, 0x00, 0x00, 38262306a36Sopenharmony_ci 0x00, 0x00, 0x00, 0x00, 38362306a36Sopenharmony_ci 38462306a36Sopenharmony_ci 0x00, 0x00, 0x00, 0x00, /* ICE_UDP_ILOS 96 */ 38562306a36Sopenharmony_ci 0x00, 0x08, 0x00, 0x00, 38662306a36Sopenharmony_ci}; 38762306a36Sopenharmony_ci 38862306a36Sopenharmony_ciICE_DECLARE_PKT_OFFSETS(udp_tun_ipv6_tcp) = { 38962306a36Sopenharmony_ci { ICE_MAC_OFOS, 0 }, 39062306a36Sopenharmony_ci { ICE_ETYPE_OL, 12 }, 39162306a36Sopenharmony_ci { ICE_IPV4_OFOS, 14 }, 39262306a36Sopenharmony_ci { ICE_UDP_OF, 34 }, 39362306a36Sopenharmony_ci { ICE_VXLAN, 42 }, 39462306a36Sopenharmony_ci { ICE_GENEVE, 42 }, 39562306a36Sopenharmony_ci { ICE_VXLAN_GPE, 42 }, 39662306a36Sopenharmony_ci { ICE_MAC_IL, 50 }, 39762306a36Sopenharmony_ci { ICE_ETYPE_IL, 62 }, 39862306a36Sopenharmony_ci { ICE_IPV6_IL, 64 }, 39962306a36Sopenharmony_ci { ICE_TCP_IL, 104 }, 40062306a36Sopenharmony_ci { ICE_PROTOCOL_LAST, 0 }, 40162306a36Sopenharmony_ci}; 40262306a36Sopenharmony_ci 40362306a36Sopenharmony_ciICE_DECLARE_PKT_TEMPLATE(udp_tun_ipv6_tcp) = { 40462306a36Sopenharmony_ci 0x00, 0x00, 0x00, 0x00, /* ICE_MAC_OFOS 0 */ 40562306a36Sopenharmony_ci 0x00, 0x00, 0x00, 0x00, 40662306a36Sopenharmony_ci 0x00, 0x00, 0x00, 0x00, 40762306a36Sopenharmony_ci 40862306a36Sopenharmony_ci 0x08, 0x00, /* ICE_ETYPE_OL 12 */ 40962306a36Sopenharmony_ci 41062306a36Sopenharmony_ci 0x45, 0x00, 0x00, 0x6e, /* ICE_IPV4_OFOS 14 */ 41162306a36Sopenharmony_ci 0x00, 0x01, 0x00, 0x00, 41262306a36Sopenharmony_ci 0x40, 0x11, 0x00, 0x00, 41362306a36Sopenharmony_ci 0x00, 0x00, 0x00, 0x00, 41462306a36Sopenharmony_ci 0x00, 0x00, 0x00, 0x00, 41562306a36Sopenharmony_ci 41662306a36Sopenharmony_ci 0x00, 0x00, 0x12, 0xb5, /* ICE_UDP_OF 34 */ 41762306a36Sopenharmony_ci 0x00, 0x5a, 0x00, 0x00, 41862306a36Sopenharmony_ci 41962306a36Sopenharmony_ci 0x00, 0x00, 0x65, 0x58, /* ICE_VXLAN 42 */ 42062306a36Sopenharmony_ci 0x00, 0x00, 0x00, 0x00, 42162306a36Sopenharmony_ci 42262306a36Sopenharmony_ci 0x00, 0x00, 0x00, 0x00, /* ICE_MAC_IL 50 */ 42362306a36Sopenharmony_ci 0x00, 0x00, 0x00, 0x00, 42462306a36Sopenharmony_ci 0x00, 0x00, 0x00, 0x00, 42562306a36Sopenharmony_ci 42662306a36Sopenharmony_ci 0x86, 0xdd, /* ICE_ETYPE_IL 62 */ 42762306a36Sopenharmony_ci 42862306a36Sopenharmony_ci 0x60, 0x00, 0x00, 0x00, /* ICE_IPV6_IL 64 */ 42962306a36Sopenharmony_ci 0x00, 0x08, 0x06, 0x40, 43062306a36Sopenharmony_ci 0x00, 0x00, 0x00, 0x00, 43162306a36Sopenharmony_ci 0x00, 0x00, 0x00, 0x00, 43262306a36Sopenharmony_ci 0x00, 0x00, 0x00, 0x00, 43362306a36Sopenharmony_ci 0x00, 0x00, 0x00, 0x00, 43462306a36Sopenharmony_ci 0x00, 0x00, 0x00, 0x00, 43562306a36Sopenharmony_ci 0x00, 0x00, 0x00, 0x00, 43662306a36Sopenharmony_ci 0x00, 0x00, 0x00, 0x00, 43762306a36Sopenharmony_ci 0x00, 0x00, 0x00, 0x00, 43862306a36Sopenharmony_ci 43962306a36Sopenharmony_ci 0x00, 0x00, 0x00, 0x00, /* ICE_TCP_IL 104 */ 44062306a36Sopenharmony_ci 0x00, 0x00, 0x00, 0x00, 44162306a36Sopenharmony_ci 0x00, 0x00, 0x00, 0x00, 44262306a36Sopenharmony_ci 0x50, 0x02, 0x20, 0x00, 44362306a36Sopenharmony_ci 0x00, 0x00, 0x00, 0x00 44462306a36Sopenharmony_ci}; 44562306a36Sopenharmony_ci 44662306a36Sopenharmony_ciICE_DECLARE_PKT_OFFSETS(udp_tun_ipv6_udp) = { 44762306a36Sopenharmony_ci { ICE_MAC_OFOS, 0 }, 44862306a36Sopenharmony_ci { ICE_ETYPE_OL, 12 }, 44962306a36Sopenharmony_ci { ICE_IPV4_OFOS, 14 }, 45062306a36Sopenharmony_ci { ICE_UDP_OF, 34 }, 45162306a36Sopenharmony_ci { ICE_VXLAN, 42 }, 45262306a36Sopenharmony_ci { ICE_GENEVE, 42 }, 45362306a36Sopenharmony_ci { ICE_VXLAN_GPE, 42 }, 45462306a36Sopenharmony_ci { ICE_MAC_IL, 50 }, 45562306a36Sopenharmony_ci { ICE_ETYPE_IL, 62 }, 45662306a36Sopenharmony_ci { ICE_IPV6_IL, 64 }, 45762306a36Sopenharmony_ci { ICE_UDP_ILOS, 104 }, 45862306a36Sopenharmony_ci { ICE_PROTOCOL_LAST, 0 }, 45962306a36Sopenharmony_ci}; 46062306a36Sopenharmony_ci 46162306a36Sopenharmony_ciICE_DECLARE_PKT_TEMPLATE(udp_tun_ipv6_udp) = { 46262306a36Sopenharmony_ci 0x00, 0x00, 0x00, 0x00, /* ICE_MAC_OFOS 0 */ 46362306a36Sopenharmony_ci 0x00, 0x00, 0x00, 0x00, 46462306a36Sopenharmony_ci 0x00, 0x00, 0x00, 0x00, 46562306a36Sopenharmony_ci 46662306a36Sopenharmony_ci 0x08, 0x00, /* ICE_ETYPE_OL 12 */ 46762306a36Sopenharmony_ci 46862306a36Sopenharmony_ci 0x45, 0x00, 0x00, 0x62, /* ICE_IPV4_OFOS 14 */ 46962306a36Sopenharmony_ci 0x00, 0x01, 0x00, 0x00, 47062306a36Sopenharmony_ci 0x00, 0x11, 0x00, 0x00, 47162306a36Sopenharmony_ci 0x00, 0x00, 0x00, 0x00, 47262306a36Sopenharmony_ci 0x00, 0x00, 0x00, 0x00, 47362306a36Sopenharmony_ci 47462306a36Sopenharmony_ci 0x00, 0x00, 0x12, 0xb5, /* ICE_UDP_OF 34 */ 47562306a36Sopenharmony_ci 0x00, 0x4e, 0x00, 0x00, 47662306a36Sopenharmony_ci 47762306a36Sopenharmony_ci 0x00, 0x00, 0x65, 0x58, /* ICE_VXLAN 42 */ 47862306a36Sopenharmony_ci 0x00, 0x00, 0x00, 0x00, 47962306a36Sopenharmony_ci 48062306a36Sopenharmony_ci 0x00, 0x00, 0x00, 0x00, /* ICE_MAC_IL 50 */ 48162306a36Sopenharmony_ci 0x00, 0x00, 0x00, 0x00, 48262306a36Sopenharmony_ci 0x00, 0x00, 0x00, 0x00, 48362306a36Sopenharmony_ci 48462306a36Sopenharmony_ci 0x86, 0xdd, /* ICE_ETYPE_IL 62 */ 48562306a36Sopenharmony_ci 48662306a36Sopenharmony_ci 0x60, 0x00, 0x00, 0x00, /* ICE_IPV6_IL 64 */ 48762306a36Sopenharmony_ci 0x00, 0x08, 0x11, 0x40, 48862306a36Sopenharmony_ci 0x00, 0x00, 0x00, 0x00, 48962306a36Sopenharmony_ci 0x00, 0x00, 0x00, 0x00, 49062306a36Sopenharmony_ci 0x00, 0x00, 0x00, 0x00, 49162306a36Sopenharmony_ci 0x00, 0x00, 0x00, 0x00, 49262306a36Sopenharmony_ci 0x00, 0x00, 0x00, 0x00, 49362306a36Sopenharmony_ci 0x00, 0x00, 0x00, 0x00, 49462306a36Sopenharmony_ci 0x00, 0x00, 0x00, 0x00, 49562306a36Sopenharmony_ci 0x00, 0x00, 0x00, 0x00, 49662306a36Sopenharmony_ci 49762306a36Sopenharmony_ci 0x00, 0x00, 0x00, 0x00, /* ICE_UDP_ILOS 104 */ 49862306a36Sopenharmony_ci 0x00, 0x08, 0x00, 0x00, 49962306a36Sopenharmony_ci}; 50062306a36Sopenharmony_ci 50162306a36Sopenharmony_ci/* offset info for MAC + IPv4 + UDP dummy packet */ 50262306a36Sopenharmony_ciICE_DECLARE_PKT_OFFSETS(udp) = { 50362306a36Sopenharmony_ci { ICE_MAC_OFOS, 0 }, 50462306a36Sopenharmony_ci { ICE_ETYPE_OL, 12 }, 50562306a36Sopenharmony_ci { ICE_IPV4_OFOS, 14 }, 50662306a36Sopenharmony_ci { ICE_UDP_ILOS, 34 }, 50762306a36Sopenharmony_ci { ICE_PROTOCOL_LAST, 0 }, 50862306a36Sopenharmony_ci}; 50962306a36Sopenharmony_ci 51062306a36Sopenharmony_ci/* Dummy packet for MAC + IPv4 + UDP */ 51162306a36Sopenharmony_ciICE_DECLARE_PKT_TEMPLATE(udp) = { 51262306a36Sopenharmony_ci 0x00, 0x00, 0x00, 0x00, /* ICE_MAC_OFOS 0 */ 51362306a36Sopenharmony_ci 0x00, 0x00, 0x00, 0x00, 51462306a36Sopenharmony_ci 0x00, 0x00, 0x00, 0x00, 51562306a36Sopenharmony_ci 51662306a36Sopenharmony_ci 0x08, 0x00, /* ICE_ETYPE_OL 12 */ 51762306a36Sopenharmony_ci 51862306a36Sopenharmony_ci 0x45, 0x00, 0x00, 0x1c, /* ICE_IPV4_OFOS 14 */ 51962306a36Sopenharmony_ci 0x00, 0x01, 0x00, 0x00, 52062306a36Sopenharmony_ci 0x00, 0x11, 0x00, 0x00, 52162306a36Sopenharmony_ci 0x00, 0x00, 0x00, 0x00, 52262306a36Sopenharmony_ci 0x00, 0x00, 0x00, 0x00, 52362306a36Sopenharmony_ci 52462306a36Sopenharmony_ci 0x00, 0x00, 0x00, 0x00, /* ICE_UDP_ILOS 34 */ 52562306a36Sopenharmony_ci 0x00, 0x08, 0x00, 0x00, 52662306a36Sopenharmony_ci 52762306a36Sopenharmony_ci 0x00, 0x00, /* 2 bytes for 4 byte alignment */ 52862306a36Sopenharmony_ci}; 52962306a36Sopenharmony_ci 53062306a36Sopenharmony_ci/* offset info for MAC + IPv4 + TCP dummy packet */ 53162306a36Sopenharmony_ciICE_DECLARE_PKT_OFFSETS(tcp) = { 53262306a36Sopenharmony_ci { ICE_MAC_OFOS, 0 }, 53362306a36Sopenharmony_ci { ICE_ETYPE_OL, 12 }, 53462306a36Sopenharmony_ci { ICE_IPV4_OFOS, 14 }, 53562306a36Sopenharmony_ci { ICE_TCP_IL, 34 }, 53662306a36Sopenharmony_ci { ICE_PROTOCOL_LAST, 0 }, 53762306a36Sopenharmony_ci}; 53862306a36Sopenharmony_ci 53962306a36Sopenharmony_ci/* Dummy packet for MAC + IPv4 + TCP */ 54062306a36Sopenharmony_ciICE_DECLARE_PKT_TEMPLATE(tcp) = { 54162306a36Sopenharmony_ci 0x00, 0x00, 0x00, 0x00, /* ICE_MAC_OFOS 0 */ 54262306a36Sopenharmony_ci 0x00, 0x00, 0x00, 0x00, 54362306a36Sopenharmony_ci 0x00, 0x00, 0x00, 0x00, 54462306a36Sopenharmony_ci 54562306a36Sopenharmony_ci 0x08, 0x00, /* ICE_ETYPE_OL 12 */ 54662306a36Sopenharmony_ci 54762306a36Sopenharmony_ci 0x45, 0x00, 0x00, 0x28, /* ICE_IPV4_OFOS 14 */ 54862306a36Sopenharmony_ci 0x00, 0x01, 0x00, 0x00, 54962306a36Sopenharmony_ci 0x00, 0x06, 0x00, 0x00, 55062306a36Sopenharmony_ci 0x00, 0x00, 0x00, 0x00, 55162306a36Sopenharmony_ci 0x00, 0x00, 0x00, 0x00, 55262306a36Sopenharmony_ci 55362306a36Sopenharmony_ci 0x00, 0x00, 0x00, 0x00, /* ICE_TCP_IL 34 */ 55462306a36Sopenharmony_ci 0x00, 0x00, 0x00, 0x00, 55562306a36Sopenharmony_ci 0x00, 0x00, 0x00, 0x00, 55662306a36Sopenharmony_ci 0x50, 0x00, 0x00, 0x00, 55762306a36Sopenharmony_ci 0x00, 0x00, 0x00, 0x00, 55862306a36Sopenharmony_ci 55962306a36Sopenharmony_ci 0x00, 0x00, /* 2 bytes for 4 byte alignment */ 56062306a36Sopenharmony_ci}; 56162306a36Sopenharmony_ci 56262306a36Sopenharmony_ciICE_DECLARE_PKT_OFFSETS(tcp_ipv6) = { 56362306a36Sopenharmony_ci { ICE_MAC_OFOS, 0 }, 56462306a36Sopenharmony_ci { ICE_ETYPE_OL, 12 }, 56562306a36Sopenharmony_ci { ICE_IPV6_OFOS, 14 }, 56662306a36Sopenharmony_ci { ICE_TCP_IL, 54 }, 56762306a36Sopenharmony_ci { ICE_PROTOCOL_LAST, 0 }, 56862306a36Sopenharmony_ci}; 56962306a36Sopenharmony_ci 57062306a36Sopenharmony_ciICE_DECLARE_PKT_TEMPLATE(tcp_ipv6) = { 57162306a36Sopenharmony_ci 0x00, 0x00, 0x00, 0x00, /* ICE_MAC_OFOS 0 */ 57262306a36Sopenharmony_ci 0x00, 0x00, 0x00, 0x00, 57362306a36Sopenharmony_ci 0x00, 0x00, 0x00, 0x00, 57462306a36Sopenharmony_ci 57562306a36Sopenharmony_ci 0x86, 0xDD, /* ICE_ETYPE_OL 12 */ 57662306a36Sopenharmony_ci 57762306a36Sopenharmony_ci 0x60, 0x00, 0x00, 0x00, /* ICE_IPV6_OFOS 40 */ 57862306a36Sopenharmony_ci 0x00, 0x14, 0x06, 0x00, /* Next header is TCP */ 57962306a36Sopenharmony_ci 0x00, 0x00, 0x00, 0x00, 58062306a36Sopenharmony_ci 0x00, 0x00, 0x00, 0x00, 58162306a36Sopenharmony_ci 0x00, 0x00, 0x00, 0x00, 58262306a36Sopenharmony_ci 0x00, 0x00, 0x00, 0x00, 58362306a36Sopenharmony_ci 0x00, 0x00, 0x00, 0x00, 58462306a36Sopenharmony_ci 0x00, 0x00, 0x00, 0x00, 58562306a36Sopenharmony_ci 0x00, 0x00, 0x00, 0x00, 58662306a36Sopenharmony_ci 0x00, 0x00, 0x00, 0x00, 58762306a36Sopenharmony_ci 58862306a36Sopenharmony_ci 0x00, 0x00, 0x00, 0x00, /* ICE_TCP_IL 54 */ 58962306a36Sopenharmony_ci 0x00, 0x00, 0x00, 0x00, 59062306a36Sopenharmony_ci 0x00, 0x00, 0x00, 0x00, 59162306a36Sopenharmony_ci 0x50, 0x00, 0x00, 0x00, 59262306a36Sopenharmony_ci 0x00, 0x00, 0x00, 0x00, 59362306a36Sopenharmony_ci 59462306a36Sopenharmony_ci 0x00, 0x00, /* 2 bytes for 4 byte alignment */ 59562306a36Sopenharmony_ci}; 59662306a36Sopenharmony_ci 59762306a36Sopenharmony_ci/* IPv6 + UDP */ 59862306a36Sopenharmony_ciICE_DECLARE_PKT_OFFSETS(udp_ipv6) = { 59962306a36Sopenharmony_ci { ICE_MAC_OFOS, 0 }, 60062306a36Sopenharmony_ci { ICE_ETYPE_OL, 12 }, 60162306a36Sopenharmony_ci { ICE_IPV6_OFOS, 14 }, 60262306a36Sopenharmony_ci { ICE_UDP_ILOS, 54 }, 60362306a36Sopenharmony_ci { ICE_PROTOCOL_LAST, 0 }, 60462306a36Sopenharmony_ci}; 60562306a36Sopenharmony_ci 60662306a36Sopenharmony_ci/* IPv6 + UDP dummy packet */ 60762306a36Sopenharmony_ciICE_DECLARE_PKT_TEMPLATE(udp_ipv6) = { 60862306a36Sopenharmony_ci 0x00, 0x00, 0x00, 0x00, /* ICE_MAC_OFOS 0 */ 60962306a36Sopenharmony_ci 0x00, 0x00, 0x00, 0x00, 61062306a36Sopenharmony_ci 0x00, 0x00, 0x00, 0x00, 61162306a36Sopenharmony_ci 61262306a36Sopenharmony_ci 0x86, 0xDD, /* ICE_ETYPE_OL 12 */ 61362306a36Sopenharmony_ci 61462306a36Sopenharmony_ci 0x60, 0x00, 0x00, 0x00, /* ICE_IPV6_OFOS 40 */ 61562306a36Sopenharmony_ci 0x00, 0x10, 0x11, 0x00, /* Next header UDP */ 61662306a36Sopenharmony_ci 0x00, 0x00, 0x00, 0x00, 61762306a36Sopenharmony_ci 0x00, 0x00, 0x00, 0x00, 61862306a36Sopenharmony_ci 0x00, 0x00, 0x00, 0x00, 61962306a36Sopenharmony_ci 0x00, 0x00, 0x00, 0x00, 62062306a36Sopenharmony_ci 0x00, 0x00, 0x00, 0x00, 62162306a36Sopenharmony_ci 0x00, 0x00, 0x00, 0x00, 62262306a36Sopenharmony_ci 0x00, 0x00, 0x00, 0x00, 62362306a36Sopenharmony_ci 0x00, 0x00, 0x00, 0x00, 62462306a36Sopenharmony_ci 62562306a36Sopenharmony_ci 0x00, 0x00, 0x00, 0x00, /* ICE_UDP_ILOS 54 */ 62662306a36Sopenharmony_ci 0x00, 0x10, 0x00, 0x00, 62762306a36Sopenharmony_ci 62862306a36Sopenharmony_ci 0x00, 0x00, 0x00, 0x00, /* needed for ESP packets */ 62962306a36Sopenharmony_ci 0x00, 0x00, 0x00, 0x00, 63062306a36Sopenharmony_ci 63162306a36Sopenharmony_ci 0x00, 0x00, /* 2 bytes for 4 byte alignment */ 63262306a36Sopenharmony_ci}; 63362306a36Sopenharmony_ci 63462306a36Sopenharmony_ci/* Outer IPv4 + Outer UDP + GTP + Inner IPv4 + Inner TCP */ 63562306a36Sopenharmony_ciICE_DECLARE_PKT_OFFSETS(ipv4_gtpu_ipv4_tcp) = { 63662306a36Sopenharmony_ci { ICE_MAC_OFOS, 0 }, 63762306a36Sopenharmony_ci { ICE_IPV4_OFOS, 14 }, 63862306a36Sopenharmony_ci { ICE_UDP_OF, 34 }, 63962306a36Sopenharmony_ci { ICE_GTP, 42 }, 64062306a36Sopenharmony_ci { ICE_IPV4_IL, 62 }, 64162306a36Sopenharmony_ci { ICE_TCP_IL, 82 }, 64262306a36Sopenharmony_ci { ICE_PROTOCOL_LAST, 0 }, 64362306a36Sopenharmony_ci}; 64462306a36Sopenharmony_ci 64562306a36Sopenharmony_ciICE_DECLARE_PKT_TEMPLATE(ipv4_gtpu_ipv4_tcp) = { 64662306a36Sopenharmony_ci 0x00, 0x00, 0x00, 0x00, /* Ethernet 0 */ 64762306a36Sopenharmony_ci 0x00, 0x00, 0x00, 0x00, 64862306a36Sopenharmony_ci 0x00, 0x00, 0x00, 0x00, 64962306a36Sopenharmony_ci 0x08, 0x00, 65062306a36Sopenharmony_ci 65162306a36Sopenharmony_ci 0x45, 0x00, 0x00, 0x58, /* IP 14 */ 65262306a36Sopenharmony_ci 0x00, 0x00, 0x00, 0x00, 65362306a36Sopenharmony_ci 0x00, 0x11, 0x00, 0x00, 65462306a36Sopenharmony_ci 0x00, 0x00, 0x00, 0x00, 65562306a36Sopenharmony_ci 0x00, 0x00, 0x00, 0x00, 65662306a36Sopenharmony_ci 65762306a36Sopenharmony_ci 0x00, 0x00, 0x08, 0x68, /* UDP 34 */ 65862306a36Sopenharmony_ci 0x00, 0x44, 0x00, 0x00, 65962306a36Sopenharmony_ci 66062306a36Sopenharmony_ci 0x34, 0xff, 0x00, 0x34, /* ICE_GTP Header 42 */ 66162306a36Sopenharmony_ci 0x00, 0x00, 0x00, 0x00, 66262306a36Sopenharmony_ci 0x00, 0x00, 0x00, 0x85, 66362306a36Sopenharmony_ci 66462306a36Sopenharmony_ci 0x02, 0x00, 0x00, 0x00, /* GTP_PDUSession_ExtensionHeader 54 */ 66562306a36Sopenharmony_ci 0x00, 0x00, 0x00, 0x00, 66662306a36Sopenharmony_ci 66762306a36Sopenharmony_ci 0x45, 0x00, 0x00, 0x28, /* IP 62 */ 66862306a36Sopenharmony_ci 0x00, 0x00, 0x00, 0x00, 66962306a36Sopenharmony_ci 0x00, 0x06, 0x00, 0x00, 67062306a36Sopenharmony_ci 0x00, 0x00, 0x00, 0x00, 67162306a36Sopenharmony_ci 0x00, 0x00, 0x00, 0x00, 67262306a36Sopenharmony_ci 67362306a36Sopenharmony_ci 0x00, 0x00, 0x00, 0x00, /* TCP 82 */ 67462306a36Sopenharmony_ci 0x00, 0x00, 0x00, 0x00, 67562306a36Sopenharmony_ci 0x00, 0x00, 0x00, 0x00, 67662306a36Sopenharmony_ci 0x50, 0x00, 0x00, 0x00, 67762306a36Sopenharmony_ci 0x00, 0x00, 0x00, 0x00, 67862306a36Sopenharmony_ci 67962306a36Sopenharmony_ci 0x00, 0x00, /* 2 bytes for 4 byte alignment */ 68062306a36Sopenharmony_ci}; 68162306a36Sopenharmony_ci 68262306a36Sopenharmony_ci/* Outer IPv4 + Outer UDP + GTP + Inner IPv4 + Inner UDP */ 68362306a36Sopenharmony_ciICE_DECLARE_PKT_OFFSETS(ipv4_gtpu_ipv4_udp) = { 68462306a36Sopenharmony_ci { ICE_MAC_OFOS, 0 }, 68562306a36Sopenharmony_ci { ICE_IPV4_OFOS, 14 }, 68662306a36Sopenharmony_ci { ICE_UDP_OF, 34 }, 68762306a36Sopenharmony_ci { ICE_GTP, 42 }, 68862306a36Sopenharmony_ci { ICE_IPV4_IL, 62 }, 68962306a36Sopenharmony_ci { ICE_UDP_ILOS, 82 }, 69062306a36Sopenharmony_ci { ICE_PROTOCOL_LAST, 0 }, 69162306a36Sopenharmony_ci}; 69262306a36Sopenharmony_ci 69362306a36Sopenharmony_ciICE_DECLARE_PKT_TEMPLATE(ipv4_gtpu_ipv4_udp) = { 69462306a36Sopenharmony_ci 0x00, 0x00, 0x00, 0x00, /* Ethernet 0 */ 69562306a36Sopenharmony_ci 0x00, 0x00, 0x00, 0x00, 69662306a36Sopenharmony_ci 0x00, 0x00, 0x00, 0x00, 69762306a36Sopenharmony_ci 0x08, 0x00, 69862306a36Sopenharmony_ci 69962306a36Sopenharmony_ci 0x45, 0x00, 0x00, 0x4c, /* IP 14 */ 70062306a36Sopenharmony_ci 0x00, 0x00, 0x00, 0x00, 70162306a36Sopenharmony_ci 0x00, 0x11, 0x00, 0x00, 70262306a36Sopenharmony_ci 0x00, 0x00, 0x00, 0x00, 70362306a36Sopenharmony_ci 0x00, 0x00, 0x00, 0x00, 70462306a36Sopenharmony_ci 70562306a36Sopenharmony_ci 0x00, 0x00, 0x08, 0x68, /* UDP 34 */ 70662306a36Sopenharmony_ci 0x00, 0x38, 0x00, 0x00, 70762306a36Sopenharmony_ci 70862306a36Sopenharmony_ci 0x34, 0xff, 0x00, 0x28, /* ICE_GTP Header 42 */ 70962306a36Sopenharmony_ci 0x00, 0x00, 0x00, 0x00, 71062306a36Sopenharmony_ci 0x00, 0x00, 0x00, 0x85, 71162306a36Sopenharmony_ci 71262306a36Sopenharmony_ci 0x02, 0x00, 0x00, 0x00, /* GTP_PDUSession_ExtensionHeader 54 */ 71362306a36Sopenharmony_ci 0x00, 0x00, 0x00, 0x00, 71462306a36Sopenharmony_ci 71562306a36Sopenharmony_ci 0x45, 0x00, 0x00, 0x1c, /* IP 62 */ 71662306a36Sopenharmony_ci 0x00, 0x00, 0x00, 0x00, 71762306a36Sopenharmony_ci 0x00, 0x11, 0x00, 0x00, 71862306a36Sopenharmony_ci 0x00, 0x00, 0x00, 0x00, 71962306a36Sopenharmony_ci 0x00, 0x00, 0x00, 0x00, 72062306a36Sopenharmony_ci 72162306a36Sopenharmony_ci 0x00, 0x00, 0x00, 0x00, /* UDP 82 */ 72262306a36Sopenharmony_ci 0x00, 0x08, 0x00, 0x00, 72362306a36Sopenharmony_ci 72462306a36Sopenharmony_ci 0x00, 0x00, /* 2 bytes for 4 byte alignment */ 72562306a36Sopenharmony_ci}; 72662306a36Sopenharmony_ci 72762306a36Sopenharmony_ci/* Outer IPv6 + Outer UDP + GTP + Inner IPv4 + Inner TCP */ 72862306a36Sopenharmony_ciICE_DECLARE_PKT_OFFSETS(ipv4_gtpu_ipv6_tcp) = { 72962306a36Sopenharmony_ci { ICE_MAC_OFOS, 0 }, 73062306a36Sopenharmony_ci { ICE_IPV4_OFOS, 14 }, 73162306a36Sopenharmony_ci { ICE_UDP_OF, 34 }, 73262306a36Sopenharmony_ci { ICE_GTP, 42 }, 73362306a36Sopenharmony_ci { ICE_IPV6_IL, 62 }, 73462306a36Sopenharmony_ci { ICE_TCP_IL, 102 }, 73562306a36Sopenharmony_ci { ICE_PROTOCOL_LAST, 0 }, 73662306a36Sopenharmony_ci}; 73762306a36Sopenharmony_ci 73862306a36Sopenharmony_ciICE_DECLARE_PKT_TEMPLATE(ipv4_gtpu_ipv6_tcp) = { 73962306a36Sopenharmony_ci 0x00, 0x00, 0x00, 0x00, /* Ethernet 0 */ 74062306a36Sopenharmony_ci 0x00, 0x00, 0x00, 0x00, 74162306a36Sopenharmony_ci 0x00, 0x00, 0x00, 0x00, 74262306a36Sopenharmony_ci 0x08, 0x00, 74362306a36Sopenharmony_ci 74462306a36Sopenharmony_ci 0x45, 0x00, 0x00, 0x6c, /* IP 14 */ 74562306a36Sopenharmony_ci 0x00, 0x00, 0x00, 0x00, 74662306a36Sopenharmony_ci 0x00, 0x11, 0x00, 0x00, 74762306a36Sopenharmony_ci 0x00, 0x00, 0x00, 0x00, 74862306a36Sopenharmony_ci 0x00, 0x00, 0x00, 0x00, 74962306a36Sopenharmony_ci 75062306a36Sopenharmony_ci 0x00, 0x00, 0x08, 0x68, /* UDP 34 */ 75162306a36Sopenharmony_ci 0x00, 0x58, 0x00, 0x00, 75262306a36Sopenharmony_ci 75362306a36Sopenharmony_ci 0x34, 0xff, 0x00, 0x48, /* ICE_GTP Header 42 */ 75462306a36Sopenharmony_ci 0x00, 0x00, 0x00, 0x00, 75562306a36Sopenharmony_ci 0x00, 0x00, 0x00, 0x85, 75662306a36Sopenharmony_ci 75762306a36Sopenharmony_ci 0x02, 0x00, 0x00, 0x00, /* GTP_PDUSession_ExtensionHeader 54 */ 75862306a36Sopenharmony_ci 0x00, 0x00, 0x00, 0x00, 75962306a36Sopenharmony_ci 76062306a36Sopenharmony_ci 0x60, 0x00, 0x00, 0x00, /* IPv6 62 */ 76162306a36Sopenharmony_ci 0x00, 0x14, 0x06, 0x00, 76262306a36Sopenharmony_ci 0x00, 0x00, 0x00, 0x00, 76362306a36Sopenharmony_ci 0x00, 0x00, 0x00, 0x00, 76462306a36Sopenharmony_ci 0x00, 0x00, 0x00, 0x00, 76562306a36Sopenharmony_ci 0x00, 0x00, 0x00, 0x00, 76662306a36Sopenharmony_ci 0x00, 0x00, 0x00, 0x00, 76762306a36Sopenharmony_ci 0x00, 0x00, 0x00, 0x00, 76862306a36Sopenharmony_ci 0x00, 0x00, 0x00, 0x00, 76962306a36Sopenharmony_ci 0x00, 0x00, 0x00, 0x00, 77062306a36Sopenharmony_ci 77162306a36Sopenharmony_ci 0x00, 0x00, 0x00, 0x00, /* TCP 102 */ 77262306a36Sopenharmony_ci 0x00, 0x00, 0x00, 0x00, 77362306a36Sopenharmony_ci 0x00, 0x00, 0x00, 0x00, 77462306a36Sopenharmony_ci 0x50, 0x00, 0x00, 0x00, 77562306a36Sopenharmony_ci 0x00, 0x00, 0x00, 0x00, 77662306a36Sopenharmony_ci 77762306a36Sopenharmony_ci 0x00, 0x00, /* 2 bytes for 4 byte alignment */ 77862306a36Sopenharmony_ci}; 77962306a36Sopenharmony_ci 78062306a36Sopenharmony_ciICE_DECLARE_PKT_OFFSETS(ipv4_gtpu_ipv6_udp) = { 78162306a36Sopenharmony_ci { ICE_MAC_OFOS, 0 }, 78262306a36Sopenharmony_ci { ICE_IPV4_OFOS, 14 }, 78362306a36Sopenharmony_ci { ICE_UDP_OF, 34 }, 78462306a36Sopenharmony_ci { ICE_GTP, 42 }, 78562306a36Sopenharmony_ci { ICE_IPV6_IL, 62 }, 78662306a36Sopenharmony_ci { ICE_UDP_ILOS, 102 }, 78762306a36Sopenharmony_ci { ICE_PROTOCOL_LAST, 0 }, 78862306a36Sopenharmony_ci}; 78962306a36Sopenharmony_ci 79062306a36Sopenharmony_ciICE_DECLARE_PKT_TEMPLATE(ipv4_gtpu_ipv6_udp) = { 79162306a36Sopenharmony_ci 0x00, 0x00, 0x00, 0x00, /* Ethernet 0 */ 79262306a36Sopenharmony_ci 0x00, 0x00, 0x00, 0x00, 79362306a36Sopenharmony_ci 0x00, 0x00, 0x00, 0x00, 79462306a36Sopenharmony_ci 0x08, 0x00, 79562306a36Sopenharmony_ci 79662306a36Sopenharmony_ci 0x45, 0x00, 0x00, 0x60, /* IP 14 */ 79762306a36Sopenharmony_ci 0x00, 0x00, 0x00, 0x00, 79862306a36Sopenharmony_ci 0x00, 0x11, 0x00, 0x00, 79962306a36Sopenharmony_ci 0x00, 0x00, 0x00, 0x00, 80062306a36Sopenharmony_ci 0x00, 0x00, 0x00, 0x00, 80162306a36Sopenharmony_ci 80262306a36Sopenharmony_ci 0x00, 0x00, 0x08, 0x68, /* UDP 34 */ 80362306a36Sopenharmony_ci 0x00, 0x4c, 0x00, 0x00, 80462306a36Sopenharmony_ci 80562306a36Sopenharmony_ci 0x34, 0xff, 0x00, 0x3c, /* ICE_GTP Header 42 */ 80662306a36Sopenharmony_ci 0x00, 0x00, 0x00, 0x00, 80762306a36Sopenharmony_ci 0x00, 0x00, 0x00, 0x85, 80862306a36Sopenharmony_ci 80962306a36Sopenharmony_ci 0x02, 0x00, 0x00, 0x00, /* GTP_PDUSession_ExtensionHeader 54 */ 81062306a36Sopenharmony_ci 0x00, 0x00, 0x00, 0x00, 81162306a36Sopenharmony_ci 81262306a36Sopenharmony_ci 0x60, 0x00, 0x00, 0x00, /* IPv6 62 */ 81362306a36Sopenharmony_ci 0x00, 0x08, 0x11, 0x00, 81462306a36Sopenharmony_ci 0x00, 0x00, 0x00, 0x00, 81562306a36Sopenharmony_ci 0x00, 0x00, 0x00, 0x00, 81662306a36Sopenharmony_ci 0x00, 0x00, 0x00, 0x00, 81762306a36Sopenharmony_ci 0x00, 0x00, 0x00, 0x00, 81862306a36Sopenharmony_ci 0x00, 0x00, 0x00, 0x00, 81962306a36Sopenharmony_ci 0x00, 0x00, 0x00, 0x00, 82062306a36Sopenharmony_ci 0x00, 0x00, 0x00, 0x00, 82162306a36Sopenharmony_ci 0x00, 0x00, 0x00, 0x00, 82262306a36Sopenharmony_ci 82362306a36Sopenharmony_ci 0x00, 0x00, 0x00, 0x00, /* UDP 102 */ 82462306a36Sopenharmony_ci 0x00, 0x08, 0x00, 0x00, 82562306a36Sopenharmony_ci 82662306a36Sopenharmony_ci 0x00, 0x00, /* 2 bytes for 4 byte alignment */ 82762306a36Sopenharmony_ci}; 82862306a36Sopenharmony_ci 82962306a36Sopenharmony_ciICE_DECLARE_PKT_OFFSETS(ipv6_gtpu_ipv4_tcp) = { 83062306a36Sopenharmony_ci { ICE_MAC_OFOS, 0 }, 83162306a36Sopenharmony_ci { ICE_IPV6_OFOS, 14 }, 83262306a36Sopenharmony_ci { ICE_UDP_OF, 54 }, 83362306a36Sopenharmony_ci { ICE_GTP, 62 }, 83462306a36Sopenharmony_ci { ICE_IPV4_IL, 82 }, 83562306a36Sopenharmony_ci { ICE_TCP_IL, 102 }, 83662306a36Sopenharmony_ci { ICE_PROTOCOL_LAST, 0 }, 83762306a36Sopenharmony_ci}; 83862306a36Sopenharmony_ci 83962306a36Sopenharmony_ciICE_DECLARE_PKT_TEMPLATE(ipv6_gtpu_ipv4_tcp) = { 84062306a36Sopenharmony_ci 0x00, 0x00, 0x00, 0x00, /* Ethernet 0 */ 84162306a36Sopenharmony_ci 0x00, 0x00, 0x00, 0x00, 84262306a36Sopenharmony_ci 0x00, 0x00, 0x00, 0x00, 84362306a36Sopenharmony_ci 0x86, 0xdd, 84462306a36Sopenharmony_ci 84562306a36Sopenharmony_ci 0x60, 0x00, 0x00, 0x00, /* IPv6 14 */ 84662306a36Sopenharmony_ci 0x00, 0x44, 0x11, 0x00, 84762306a36Sopenharmony_ci 0x00, 0x00, 0x00, 0x00, 84862306a36Sopenharmony_ci 0x00, 0x00, 0x00, 0x00, 84962306a36Sopenharmony_ci 0x00, 0x00, 0x00, 0x00, 85062306a36Sopenharmony_ci 0x00, 0x00, 0x00, 0x00, 85162306a36Sopenharmony_ci 0x00, 0x00, 0x00, 0x00, 85262306a36Sopenharmony_ci 0x00, 0x00, 0x00, 0x00, 85362306a36Sopenharmony_ci 0x00, 0x00, 0x00, 0x00, 85462306a36Sopenharmony_ci 0x00, 0x00, 0x00, 0x00, 85562306a36Sopenharmony_ci 85662306a36Sopenharmony_ci 0x00, 0x00, 0x08, 0x68, /* UDP 54 */ 85762306a36Sopenharmony_ci 0x00, 0x44, 0x00, 0x00, 85862306a36Sopenharmony_ci 85962306a36Sopenharmony_ci 0x34, 0xff, 0x00, 0x34, /* ICE_GTP Header 62 */ 86062306a36Sopenharmony_ci 0x00, 0x00, 0x00, 0x00, 86162306a36Sopenharmony_ci 0x00, 0x00, 0x00, 0x85, 86262306a36Sopenharmony_ci 86362306a36Sopenharmony_ci 0x02, 0x00, 0x00, 0x00, /* GTP_PDUSession_ExtensionHeader 74 */ 86462306a36Sopenharmony_ci 0x00, 0x00, 0x00, 0x00, 86562306a36Sopenharmony_ci 86662306a36Sopenharmony_ci 0x45, 0x00, 0x00, 0x28, /* IP 82 */ 86762306a36Sopenharmony_ci 0x00, 0x00, 0x00, 0x00, 86862306a36Sopenharmony_ci 0x00, 0x06, 0x00, 0x00, 86962306a36Sopenharmony_ci 0x00, 0x00, 0x00, 0x00, 87062306a36Sopenharmony_ci 0x00, 0x00, 0x00, 0x00, 87162306a36Sopenharmony_ci 87262306a36Sopenharmony_ci 0x00, 0x00, 0x00, 0x00, /* TCP 102 */ 87362306a36Sopenharmony_ci 0x00, 0x00, 0x00, 0x00, 87462306a36Sopenharmony_ci 0x00, 0x00, 0x00, 0x00, 87562306a36Sopenharmony_ci 0x50, 0x00, 0x00, 0x00, 87662306a36Sopenharmony_ci 0x00, 0x00, 0x00, 0x00, 87762306a36Sopenharmony_ci 87862306a36Sopenharmony_ci 0x00, 0x00, /* 2 bytes for 4 byte alignment */ 87962306a36Sopenharmony_ci}; 88062306a36Sopenharmony_ci 88162306a36Sopenharmony_ciICE_DECLARE_PKT_OFFSETS(ipv6_gtpu_ipv4_udp) = { 88262306a36Sopenharmony_ci { ICE_MAC_OFOS, 0 }, 88362306a36Sopenharmony_ci { ICE_IPV6_OFOS, 14 }, 88462306a36Sopenharmony_ci { ICE_UDP_OF, 54 }, 88562306a36Sopenharmony_ci { ICE_GTP, 62 }, 88662306a36Sopenharmony_ci { ICE_IPV4_IL, 82 }, 88762306a36Sopenharmony_ci { ICE_UDP_ILOS, 102 }, 88862306a36Sopenharmony_ci { ICE_PROTOCOL_LAST, 0 }, 88962306a36Sopenharmony_ci}; 89062306a36Sopenharmony_ci 89162306a36Sopenharmony_ciICE_DECLARE_PKT_TEMPLATE(ipv6_gtpu_ipv4_udp) = { 89262306a36Sopenharmony_ci 0x00, 0x00, 0x00, 0x00, /* Ethernet 0 */ 89362306a36Sopenharmony_ci 0x00, 0x00, 0x00, 0x00, 89462306a36Sopenharmony_ci 0x00, 0x00, 0x00, 0x00, 89562306a36Sopenharmony_ci 0x86, 0xdd, 89662306a36Sopenharmony_ci 89762306a36Sopenharmony_ci 0x60, 0x00, 0x00, 0x00, /* IPv6 14 */ 89862306a36Sopenharmony_ci 0x00, 0x38, 0x11, 0x00, 89962306a36Sopenharmony_ci 0x00, 0x00, 0x00, 0x00, 90062306a36Sopenharmony_ci 0x00, 0x00, 0x00, 0x00, 90162306a36Sopenharmony_ci 0x00, 0x00, 0x00, 0x00, 90262306a36Sopenharmony_ci 0x00, 0x00, 0x00, 0x00, 90362306a36Sopenharmony_ci 0x00, 0x00, 0x00, 0x00, 90462306a36Sopenharmony_ci 0x00, 0x00, 0x00, 0x00, 90562306a36Sopenharmony_ci 0x00, 0x00, 0x00, 0x00, 90662306a36Sopenharmony_ci 0x00, 0x00, 0x00, 0x00, 90762306a36Sopenharmony_ci 90862306a36Sopenharmony_ci 0x00, 0x00, 0x08, 0x68, /* UDP 54 */ 90962306a36Sopenharmony_ci 0x00, 0x38, 0x00, 0x00, 91062306a36Sopenharmony_ci 91162306a36Sopenharmony_ci 0x34, 0xff, 0x00, 0x28, /* ICE_GTP Header 62 */ 91262306a36Sopenharmony_ci 0x00, 0x00, 0x00, 0x00, 91362306a36Sopenharmony_ci 0x00, 0x00, 0x00, 0x85, 91462306a36Sopenharmony_ci 91562306a36Sopenharmony_ci 0x02, 0x00, 0x00, 0x00, /* GTP_PDUSession_ExtensionHeader 74 */ 91662306a36Sopenharmony_ci 0x00, 0x00, 0x00, 0x00, 91762306a36Sopenharmony_ci 91862306a36Sopenharmony_ci 0x45, 0x00, 0x00, 0x1c, /* IP 82 */ 91962306a36Sopenharmony_ci 0x00, 0x00, 0x00, 0x00, 92062306a36Sopenharmony_ci 0x00, 0x11, 0x00, 0x00, 92162306a36Sopenharmony_ci 0x00, 0x00, 0x00, 0x00, 92262306a36Sopenharmony_ci 0x00, 0x00, 0x00, 0x00, 92362306a36Sopenharmony_ci 92462306a36Sopenharmony_ci 0x00, 0x00, 0x00, 0x00, /* UDP 102 */ 92562306a36Sopenharmony_ci 0x00, 0x08, 0x00, 0x00, 92662306a36Sopenharmony_ci 92762306a36Sopenharmony_ci 0x00, 0x00, /* 2 bytes for 4 byte alignment */ 92862306a36Sopenharmony_ci}; 92962306a36Sopenharmony_ci 93062306a36Sopenharmony_ciICE_DECLARE_PKT_OFFSETS(ipv6_gtpu_ipv6_tcp) = { 93162306a36Sopenharmony_ci { ICE_MAC_OFOS, 0 }, 93262306a36Sopenharmony_ci { ICE_IPV6_OFOS, 14 }, 93362306a36Sopenharmony_ci { ICE_UDP_OF, 54 }, 93462306a36Sopenharmony_ci { ICE_GTP, 62 }, 93562306a36Sopenharmony_ci { ICE_IPV6_IL, 82 }, 93662306a36Sopenharmony_ci { ICE_TCP_IL, 122 }, 93762306a36Sopenharmony_ci { ICE_PROTOCOL_LAST, 0 }, 93862306a36Sopenharmony_ci}; 93962306a36Sopenharmony_ci 94062306a36Sopenharmony_ciICE_DECLARE_PKT_TEMPLATE(ipv6_gtpu_ipv6_tcp) = { 94162306a36Sopenharmony_ci 0x00, 0x00, 0x00, 0x00, /* Ethernet 0 */ 94262306a36Sopenharmony_ci 0x00, 0x00, 0x00, 0x00, 94362306a36Sopenharmony_ci 0x00, 0x00, 0x00, 0x00, 94462306a36Sopenharmony_ci 0x86, 0xdd, 94562306a36Sopenharmony_ci 94662306a36Sopenharmony_ci 0x60, 0x00, 0x00, 0x00, /* IPv6 14 */ 94762306a36Sopenharmony_ci 0x00, 0x58, 0x11, 0x00, 94862306a36Sopenharmony_ci 0x00, 0x00, 0x00, 0x00, 94962306a36Sopenharmony_ci 0x00, 0x00, 0x00, 0x00, 95062306a36Sopenharmony_ci 0x00, 0x00, 0x00, 0x00, 95162306a36Sopenharmony_ci 0x00, 0x00, 0x00, 0x00, 95262306a36Sopenharmony_ci 0x00, 0x00, 0x00, 0x00, 95362306a36Sopenharmony_ci 0x00, 0x00, 0x00, 0x00, 95462306a36Sopenharmony_ci 0x00, 0x00, 0x00, 0x00, 95562306a36Sopenharmony_ci 0x00, 0x00, 0x00, 0x00, 95662306a36Sopenharmony_ci 95762306a36Sopenharmony_ci 0x00, 0x00, 0x08, 0x68, /* UDP 54 */ 95862306a36Sopenharmony_ci 0x00, 0x58, 0x00, 0x00, 95962306a36Sopenharmony_ci 96062306a36Sopenharmony_ci 0x34, 0xff, 0x00, 0x48, /* ICE_GTP Header 62 */ 96162306a36Sopenharmony_ci 0x00, 0x00, 0x00, 0x00, 96262306a36Sopenharmony_ci 0x00, 0x00, 0x00, 0x85, 96362306a36Sopenharmony_ci 96462306a36Sopenharmony_ci 0x02, 0x00, 0x00, 0x00, /* GTP_PDUSession_ExtensionHeader 74 */ 96562306a36Sopenharmony_ci 0x00, 0x00, 0x00, 0x00, 96662306a36Sopenharmony_ci 96762306a36Sopenharmony_ci 0x60, 0x00, 0x00, 0x00, /* IPv6 82 */ 96862306a36Sopenharmony_ci 0x00, 0x14, 0x06, 0x00, 96962306a36Sopenharmony_ci 0x00, 0x00, 0x00, 0x00, 97062306a36Sopenharmony_ci 0x00, 0x00, 0x00, 0x00, 97162306a36Sopenharmony_ci 0x00, 0x00, 0x00, 0x00, 97262306a36Sopenharmony_ci 0x00, 0x00, 0x00, 0x00, 97362306a36Sopenharmony_ci 0x00, 0x00, 0x00, 0x00, 97462306a36Sopenharmony_ci 0x00, 0x00, 0x00, 0x00, 97562306a36Sopenharmony_ci 0x00, 0x00, 0x00, 0x00, 97662306a36Sopenharmony_ci 0x00, 0x00, 0x00, 0x00, 97762306a36Sopenharmony_ci 97862306a36Sopenharmony_ci 0x00, 0x00, 0x00, 0x00, /* TCP 122 */ 97962306a36Sopenharmony_ci 0x00, 0x00, 0x00, 0x00, 98062306a36Sopenharmony_ci 0x00, 0x00, 0x00, 0x00, 98162306a36Sopenharmony_ci 0x50, 0x00, 0x00, 0x00, 98262306a36Sopenharmony_ci 0x00, 0x00, 0x00, 0x00, 98362306a36Sopenharmony_ci 98462306a36Sopenharmony_ci 0x00, 0x00, /* 2 bytes for 4 byte alignment */ 98562306a36Sopenharmony_ci}; 98662306a36Sopenharmony_ci 98762306a36Sopenharmony_ciICE_DECLARE_PKT_OFFSETS(ipv6_gtpu_ipv6_udp) = { 98862306a36Sopenharmony_ci { ICE_MAC_OFOS, 0 }, 98962306a36Sopenharmony_ci { ICE_IPV6_OFOS, 14 }, 99062306a36Sopenharmony_ci { ICE_UDP_OF, 54 }, 99162306a36Sopenharmony_ci { ICE_GTP, 62 }, 99262306a36Sopenharmony_ci { ICE_IPV6_IL, 82 }, 99362306a36Sopenharmony_ci { ICE_UDP_ILOS, 122 }, 99462306a36Sopenharmony_ci { ICE_PROTOCOL_LAST, 0 }, 99562306a36Sopenharmony_ci}; 99662306a36Sopenharmony_ci 99762306a36Sopenharmony_ciICE_DECLARE_PKT_TEMPLATE(ipv6_gtpu_ipv6_udp) = { 99862306a36Sopenharmony_ci 0x00, 0x00, 0x00, 0x00, /* Ethernet 0 */ 99962306a36Sopenharmony_ci 0x00, 0x00, 0x00, 0x00, 100062306a36Sopenharmony_ci 0x00, 0x00, 0x00, 0x00, 100162306a36Sopenharmony_ci 0x86, 0xdd, 100262306a36Sopenharmony_ci 100362306a36Sopenharmony_ci 0x60, 0x00, 0x00, 0x00, /* IPv6 14 */ 100462306a36Sopenharmony_ci 0x00, 0x4c, 0x11, 0x00, 100562306a36Sopenharmony_ci 0x00, 0x00, 0x00, 0x00, 100662306a36Sopenharmony_ci 0x00, 0x00, 0x00, 0x00, 100762306a36Sopenharmony_ci 0x00, 0x00, 0x00, 0x00, 100862306a36Sopenharmony_ci 0x00, 0x00, 0x00, 0x00, 100962306a36Sopenharmony_ci 0x00, 0x00, 0x00, 0x00, 101062306a36Sopenharmony_ci 0x00, 0x00, 0x00, 0x00, 101162306a36Sopenharmony_ci 0x00, 0x00, 0x00, 0x00, 101262306a36Sopenharmony_ci 0x00, 0x00, 0x00, 0x00, 101362306a36Sopenharmony_ci 101462306a36Sopenharmony_ci 0x00, 0x00, 0x08, 0x68, /* UDP 54 */ 101562306a36Sopenharmony_ci 0x00, 0x4c, 0x00, 0x00, 101662306a36Sopenharmony_ci 101762306a36Sopenharmony_ci 0x34, 0xff, 0x00, 0x3c, /* ICE_GTP Header 62 */ 101862306a36Sopenharmony_ci 0x00, 0x00, 0x00, 0x00, 101962306a36Sopenharmony_ci 0x00, 0x00, 0x00, 0x85, 102062306a36Sopenharmony_ci 102162306a36Sopenharmony_ci 0x02, 0x00, 0x00, 0x00, /* GTP_PDUSession_ExtensionHeader 74 */ 102262306a36Sopenharmony_ci 0x00, 0x00, 0x00, 0x00, 102362306a36Sopenharmony_ci 102462306a36Sopenharmony_ci 0x60, 0x00, 0x00, 0x00, /* IPv6 82 */ 102562306a36Sopenharmony_ci 0x00, 0x08, 0x11, 0x00, 102662306a36Sopenharmony_ci 0x00, 0x00, 0x00, 0x00, 102762306a36Sopenharmony_ci 0x00, 0x00, 0x00, 0x00, 102862306a36Sopenharmony_ci 0x00, 0x00, 0x00, 0x00, 102962306a36Sopenharmony_ci 0x00, 0x00, 0x00, 0x00, 103062306a36Sopenharmony_ci 0x00, 0x00, 0x00, 0x00, 103162306a36Sopenharmony_ci 0x00, 0x00, 0x00, 0x00, 103262306a36Sopenharmony_ci 0x00, 0x00, 0x00, 0x00, 103362306a36Sopenharmony_ci 0x00, 0x00, 0x00, 0x00, 103462306a36Sopenharmony_ci 103562306a36Sopenharmony_ci 0x00, 0x00, 0x00, 0x00, /* UDP 122 */ 103662306a36Sopenharmony_ci 0x00, 0x08, 0x00, 0x00, 103762306a36Sopenharmony_ci 103862306a36Sopenharmony_ci 0x00, 0x00, /* 2 bytes for 4 byte alignment */ 103962306a36Sopenharmony_ci}; 104062306a36Sopenharmony_ci 104162306a36Sopenharmony_ciICE_DECLARE_PKT_OFFSETS(ipv4_gtpu_ipv4) = { 104262306a36Sopenharmony_ci { ICE_MAC_OFOS, 0 }, 104362306a36Sopenharmony_ci { ICE_IPV4_OFOS, 14 }, 104462306a36Sopenharmony_ci { ICE_UDP_OF, 34 }, 104562306a36Sopenharmony_ci { ICE_GTP_NO_PAY, 42 }, 104662306a36Sopenharmony_ci { ICE_PROTOCOL_LAST, 0 }, 104762306a36Sopenharmony_ci}; 104862306a36Sopenharmony_ci 104962306a36Sopenharmony_ciICE_DECLARE_PKT_TEMPLATE(ipv4_gtpu_ipv4) = { 105062306a36Sopenharmony_ci 0x00, 0x00, 0x00, 0x00, /* ICE_MAC_OFOS 0 */ 105162306a36Sopenharmony_ci 0x00, 0x00, 0x00, 0x00, 105262306a36Sopenharmony_ci 0x00, 0x00, 0x00, 0x00, 105362306a36Sopenharmony_ci 0x08, 0x00, 105462306a36Sopenharmony_ci 105562306a36Sopenharmony_ci 0x45, 0x00, 0x00, 0x44, /* ICE_IPV4_OFOS 14 */ 105662306a36Sopenharmony_ci 0x00, 0x00, 0x40, 0x00, 105762306a36Sopenharmony_ci 0x40, 0x11, 0x00, 0x00, 105862306a36Sopenharmony_ci 0x00, 0x00, 0x00, 0x00, 105962306a36Sopenharmony_ci 0x00, 0x00, 0x00, 0x00, 106062306a36Sopenharmony_ci 106162306a36Sopenharmony_ci 0x08, 0x68, 0x08, 0x68, /* ICE_UDP_OF 34 */ 106262306a36Sopenharmony_ci 0x00, 0x00, 0x00, 0x00, 106362306a36Sopenharmony_ci 106462306a36Sopenharmony_ci 0x34, 0xff, 0x00, 0x28, /* ICE_GTP 42 */ 106562306a36Sopenharmony_ci 0x00, 0x00, 0x00, 0x00, 106662306a36Sopenharmony_ci 0x00, 0x00, 0x00, 0x85, 106762306a36Sopenharmony_ci 106862306a36Sopenharmony_ci 0x02, 0x00, 0x00, 0x00, /* PDU Session extension header */ 106962306a36Sopenharmony_ci 0x00, 0x00, 0x00, 0x00, 107062306a36Sopenharmony_ci 107162306a36Sopenharmony_ci 0x45, 0x00, 0x00, 0x14, /* ICE_IPV4_IL 62 */ 107262306a36Sopenharmony_ci 0x00, 0x00, 0x40, 0x00, 107362306a36Sopenharmony_ci 0x40, 0x00, 0x00, 0x00, 107462306a36Sopenharmony_ci 0x00, 0x00, 0x00, 0x00, 107562306a36Sopenharmony_ci 0x00, 0x00, 0x00, 0x00, 107662306a36Sopenharmony_ci 0x00, 0x00, 107762306a36Sopenharmony_ci}; 107862306a36Sopenharmony_ci 107962306a36Sopenharmony_ciICE_DECLARE_PKT_OFFSETS(ipv6_gtp) = { 108062306a36Sopenharmony_ci { ICE_MAC_OFOS, 0 }, 108162306a36Sopenharmony_ci { ICE_IPV6_OFOS, 14 }, 108262306a36Sopenharmony_ci { ICE_UDP_OF, 54 }, 108362306a36Sopenharmony_ci { ICE_GTP_NO_PAY, 62 }, 108462306a36Sopenharmony_ci { ICE_PROTOCOL_LAST, 0 }, 108562306a36Sopenharmony_ci}; 108662306a36Sopenharmony_ci 108762306a36Sopenharmony_ciICE_DECLARE_PKT_TEMPLATE(ipv6_gtp) = { 108862306a36Sopenharmony_ci 0x00, 0x00, 0x00, 0x00, /* ICE_MAC_OFOS 0 */ 108962306a36Sopenharmony_ci 0x00, 0x00, 0x00, 0x00, 109062306a36Sopenharmony_ci 0x00, 0x00, 0x00, 0x00, 109162306a36Sopenharmony_ci 0x86, 0xdd, 109262306a36Sopenharmony_ci 109362306a36Sopenharmony_ci 0x60, 0x00, 0x00, 0x00, /* ICE_IPV6_OFOS 14 */ 109462306a36Sopenharmony_ci 0x00, 0x6c, 0x11, 0x00, /* Next header UDP*/ 109562306a36Sopenharmony_ci 0x00, 0x00, 0x00, 0x00, 109662306a36Sopenharmony_ci 0x00, 0x00, 0x00, 0x00, 109762306a36Sopenharmony_ci 0x00, 0x00, 0x00, 0x00, 109862306a36Sopenharmony_ci 0x00, 0x00, 0x00, 0x00, 109962306a36Sopenharmony_ci 0x00, 0x00, 0x00, 0x00, 110062306a36Sopenharmony_ci 0x00, 0x00, 0x00, 0x00, 110162306a36Sopenharmony_ci 0x00, 0x00, 0x00, 0x00, 110262306a36Sopenharmony_ci 0x00, 0x00, 0x00, 0x00, 110362306a36Sopenharmony_ci 110462306a36Sopenharmony_ci 0x08, 0x68, 0x08, 0x68, /* ICE_UDP_OF 54 */ 110562306a36Sopenharmony_ci 0x00, 0x00, 0x00, 0x00, 110662306a36Sopenharmony_ci 110762306a36Sopenharmony_ci 0x30, 0x00, 0x00, 0x28, /* ICE_GTP 62 */ 110862306a36Sopenharmony_ci 0x00, 0x00, 0x00, 0x00, 110962306a36Sopenharmony_ci 111062306a36Sopenharmony_ci 0x00, 0x00, 111162306a36Sopenharmony_ci}; 111262306a36Sopenharmony_ci 111362306a36Sopenharmony_ciICE_DECLARE_PKT_OFFSETS(pppoe_ipv4_tcp) = { 111462306a36Sopenharmony_ci { ICE_MAC_OFOS, 0 }, 111562306a36Sopenharmony_ci { ICE_ETYPE_OL, 12 }, 111662306a36Sopenharmony_ci { ICE_PPPOE, 14 }, 111762306a36Sopenharmony_ci { ICE_IPV4_OFOS, 22 }, 111862306a36Sopenharmony_ci { ICE_TCP_IL, 42 }, 111962306a36Sopenharmony_ci { ICE_PROTOCOL_LAST, 0 }, 112062306a36Sopenharmony_ci}; 112162306a36Sopenharmony_ci 112262306a36Sopenharmony_ciICE_DECLARE_PKT_TEMPLATE(pppoe_ipv4_tcp) = { 112362306a36Sopenharmony_ci 0x00, 0x00, 0x00, 0x00, /* ICE_MAC_OFOS 0 */ 112462306a36Sopenharmony_ci 0x00, 0x00, 0x00, 0x00, 112562306a36Sopenharmony_ci 0x00, 0x00, 0x00, 0x00, 112662306a36Sopenharmony_ci 112762306a36Sopenharmony_ci 0x88, 0x64, /* ICE_ETYPE_OL 12 */ 112862306a36Sopenharmony_ci 112962306a36Sopenharmony_ci 0x11, 0x00, 0x00, 0x00, /* ICE_PPPOE 14 */ 113062306a36Sopenharmony_ci 0x00, 0x16, 113162306a36Sopenharmony_ci 113262306a36Sopenharmony_ci 0x00, 0x21, /* PPP Link Layer 20 */ 113362306a36Sopenharmony_ci 113462306a36Sopenharmony_ci 0x45, 0x00, 0x00, 0x28, /* ICE_IPV4_OFOS 22 */ 113562306a36Sopenharmony_ci 0x00, 0x01, 0x00, 0x00, 113662306a36Sopenharmony_ci 0x00, 0x06, 0x00, 0x00, 113762306a36Sopenharmony_ci 0x00, 0x00, 0x00, 0x00, 113862306a36Sopenharmony_ci 0x00, 0x00, 0x00, 0x00, 113962306a36Sopenharmony_ci 114062306a36Sopenharmony_ci 0x00, 0x00, 0x00, 0x00, /* ICE_TCP_IL 42 */ 114162306a36Sopenharmony_ci 0x00, 0x00, 0x00, 0x00, 114262306a36Sopenharmony_ci 0x00, 0x00, 0x00, 0x00, 114362306a36Sopenharmony_ci 0x50, 0x00, 0x00, 0x00, 114462306a36Sopenharmony_ci 0x00, 0x00, 0x00, 0x00, 114562306a36Sopenharmony_ci 114662306a36Sopenharmony_ci 0x00, 0x00, /* 2 bytes for 4 bytes alignment */ 114762306a36Sopenharmony_ci}; 114862306a36Sopenharmony_ci 114962306a36Sopenharmony_ciICE_DECLARE_PKT_OFFSETS(pppoe_ipv4_udp) = { 115062306a36Sopenharmony_ci { ICE_MAC_OFOS, 0 }, 115162306a36Sopenharmony_ci { ICE_ETYPE_OL, 12 }, 115262306a36Sopenharmony_ci { ICE_PPPOE, 14 }, 115362306a36Sopenharmony_ci { ICE_IPV4_OFOS, 22 }, 115462306a36Sopenharmony_ci { ICE_UDP_ILOS, 42 }, 115562306a36Sopenharmony_ci { ICE_PROTOCOL_LAST, 0 }, 115662306a36Sopenharmony_ci}; 115762306a36Sopenharmony_ci 115862306a36Sopenharmony_ciICE_DECLARE_PKT_TEMPLATE(pppoe_ipv4_udp) = { 115962306a36Sopenharmony_ci 0x00, 0x00, 0x00, 0x00, /* ICE_MAC_OFOS 0 */ 116062306a36Sopenharmony_ci 0x00, 0x00, 0x00, 0x00, 116162306a36Sopenharmony_ci 0x00, 0x00, 0x00, 0x00, 116262306a36Sopenharmony_ci 116362306a36Sopenharmony_ci 0x88, 0x64, /* ICE_ETYPE_OL 12 */ 116462306a36Sopenharmony_ci 116562306a36Sopenharmony_ci 0x11, 0x00, 0x00, 0x00, /* ICE_PPPOE 14 */ 116662306a36Sopenharmony_ci 0x00, 0x16, 116762306a36Sopenharmony_ci 116862306a36Sopenharmony_ci 0x00, 0x21, /* PPP Link Layer 20 */ 116962306a36Sopenharmony_ci 117062306a36Sopenharmony_ci 0x45, 0x00, 0x00, 0x1c, /* ICE_IPV4_OFOS 22 */ 117162306a36Sopenharmony_ci 0x00, 0x01, 0x00, 0x00, 117262306a36Sopenharmony_ci 0x00, 0x11, 0x00, 0x00, 117362306a36Sopenharmony_ci 0x00, 0x00, 0x00, 0x00, 117462306a36Sopenharmony_ci 0x00, 0x00, 0x00, 0x00, 117562306a36Sopenharmony_ci 117662306a36Sopenharmony_ci 0x00, 0x00, 0x00, 0x00, /* ICE_UDP_ILOS 42 */ 117762306a36Sopenharmony_ci 0x00, 0x08, 0x00, 0x00, 117862306a36Sopenharmony_ci 117962306a36Sopenharmony_ci 0x00, 0x00, /* 2 bytes for 4 bytes alignment */ 118062306a36Sopenharmony_ci}; 118162306a36Sopenharmony_ci 118262306a36Sopenharmony_ciICE_DECLARE_PKT_OFFSETS(pppoe_ipv6_tcp) = { 118362306a36Sopenharmony_ci { ICE_MAC_OFOS, 0 }, 118462306a36Sopenharmony_ci { ICE_ETYPE_OL, 12 }, 118562306a36Sopenharmony_ci { ICE_PPPOE, 14 }, 118662306a36Sopenharmony_ci { ICE_IPV6_OFOS, 22 }, 118762306a36Sopenharmony_ci { ICE_TCP_IL, 62 }, 118862306a36Sopenharmony_ci { ICE_PROTOCOL_LAST, 0 }, 118962306a36Sopenharmony_ci}; 119062306a36Sopenharmony_ci 119162306a36Sopenharmony_ciICE_DECLARE_PKT_TEMPLATE(pppoe_ipv6_tcp) = { 119262306a36Sopenharmony_ci 0x00, 0x00, 0x00, 0x00, /* ICE_MAC_OFOS 0 */ 119362306a36Sopenharmony_ci 0x00, 0x00, 0x00, 0x00, 119462306a36Sopenharmony_ci 0x00, 0x00, 0x00, 0x00, 119562306a36Sopenharmony_ci 119662306a36Sopenharmony_ci 0x88, 0x64, /* ICE_ETYPE_OL 12 */ 119762306a36Sopenharmony_ci 119862306a36Sopenharmony_ci 0x11, 0x00, 0x00, 0x00, /* ICE_PPPOE 14 */ 119962306a36Sopenharmony_ci 0x00, 0x2a, 120062306a36Sopenharmony_ci 120162306a36Sopenharmony_ci 0x00, 0x57, /* PPP Link Layer 20 */ 120262306a36Sopenharmony_ci 120362306a36Sopenharmony_ci 0x60, 0x00, 0x00, 0x00, /* ICE_IPV6_OFOS 22 */ 120462306a36Sopenharmony_ci 0x00, 0x14, 0x06, 0x00, /* Next header is TCP */ 120562306a36Sopenharmony_ci 0x00, 0x00, 0x00, 0x00, 120662306a36Sopenharmony_ci 0x00, 0x00, 0x00, 0x00, 120762306a36Sopenharmony_ci 0x00, 0x00, 0x00, 0x00, 120862306a36Sopenharmony_ci 0x00, 0x00, 0x00, 0x00, 120962306a36Sopenharmony_ci 0x00, 0x00, 0x00, 0x00, 121062306a36Sopenharmony_ci 0x00, 0x00, 0x00, 0x00, 121162306a36Sopenharmony_ci 0x00, 0x00, 0x00, 0x00, 121262306a36Sopenharmony_ci 0x00, 0x00, 0x00, 0x00, 121362306a36Sopenharmony_ci 121462306a36Sopenharmony_ci 0x00, 0x00, 0x00, 0x00, /* ICE_TCP_IL 62 */ 121562306a36Sopenharmony_ci 0x00, 0x00, 0x00, 0x00, 121662306a36Sopenharmony_ci 0x00, 0x00, 0x00, 0x00, 121762306a36Sopenharmony_ci 0x50, 0x00, 0x00, 0x00, 121862306a36Sopenharmony_ci 0x00, 0x00, 0x00, 0x00, 121962306a36Sopenharmony_ci 122062306a36Sopenharmony_ci 0x00, 0x00, /* 2 bytes for 4 bytes alignment */ 122162306a36Sopenharmony_ci}; 122262306a36Sopenharmony_ci 122362306a36Sopenharmony_ciICE_DECLARE_PKT_OFFSETS(pppoe_ipv6_udp) = { 122462306a36Sopenharmony_ci { ICE_MAC_OFOS, 0 }, 122562306a36Sopenharmony_ci { ICE_ETYPE_OL, 12 }, 122662306a36Sopenharmony_ci { ICE_PPPOE, 14 }, 122762306a36Sopenharmony_ci { ICE_IPV6_OFOS, 22 }, 122862306a36Sopenharmony_ci { ICE_UDP_ILOS, 62 }, 122962306a36Sopenharmony_ci { ICE_PROTOCOL_LAST, 0 }, 123062306a36Sopenharmony_ci}; 123162306a36Sopenharmony_ci 123262306a36Sopenharmony_ciICE_DECLARE_PKT_TEMPLATE(pppoe_ipv6_udp) = { 123362306a36Sopenharmony_ci 0x00, 0x00, 0x00, 0x00, /* ICE_MAC_OFOS 0 */ 123462306a36Sopenharmony_ci 0x00, 0x00, 0x00, 0x00, 123562306a36Sopenharmony_ci 0x00, 0x00, 0x00, 0x00, 123662306a36Sopenharmony_ci 123762306a36Sopenharmony_ci 0x88, 0x64, /* ICE_ETYPE_OL 12 */ 123862306a36Sopenharmony_ci 123962306a36Sopenharmony_ci 0x11, 0x00, 0x00, 0x00, /* ICE_PPPOE 14 */ 124062306a36Sopenharmony_ci 0x00, 0x2a, 124162306a36Sopenharmony_ci 124262306a36Sopenharmony_ci 0x00, 0x57, /* PPP Link Layer 20 */ 124362306a36Sopenharmony_ci 124462306a36Sopenharmony_ci 0x60, 0x00, 0x00, 0x00, /* ICE_IPV6_OFOS 22 */ 124562306a36Sopenharmony_ci 0x00, 0x08, 0x11, 0x00, /* Next header UDP*/ 124662306a36Sopenharmony_ci 0x00, 0x00, 0x00, 0x00, 124762306a36Sopenharmony_ci 0x00, 0x00, 0x00, 0x00, 124862306a36Sopenharmony_ci 0x00, 0x00, 0x00, 0x00, 124962306a36Sopenharmony_ci 0x00, 0x00, 0x00, 0x00, 125062306a36Sopenharmony_ci 0x00, 0x00, 0x00, 0x00, 125162306a36Sopenharmony_ci 0x00, 0x00, 0x00, 0x00, 125262306a36Sopenharmony_ci 0x00, 0x00, 0x00, 0x00, 125362306a36Sopenharmony_ci 0x00, 0x00, 0x00, 0x00, 125462306a36Sopenharmony_ci 125562306a36Sopenharmony_ci 0x00, 0x00, 0x00, 0x00, /* ICE_UDP_ILOS 62 */ 125662306a36Sopenharmony_ci 0x00, 0x08, 0x00, 0x00, 125762306a36Sopenharmony_ci 125862306a36Sopenharmony_ci 0x00, 0x00, /* 2 bytes for 4 bytes alignment */ 125962306a36Sopenharmony_ci}; 126062306a36Sopenharmony_ci 126162306a36Sopenharmony_ciICE_DECLARE_PKT_OFFSETS(ipv4_l2tpv3) = { 126262306a36Sopenharmony_ci { ICE_MAC_OFOS, 0 }, 126362306a36Sopenharmony_ci { ICE_ETYPE_OL, 12 }, 126462306a36Sopenharmony_ci { ICE_IPV4_OFOS, 14 }, 126562306a36Sopenharmony_ci { ICE_L2TPV3, 34 }, 126662306a36Sopenharmony_ci { ICE_PROTOCOL_LAST, 0 }, 126762306a36Sopenharmony_ci}; 126862306a36Sopenharmony_ci 126962306a36Sopenharmony_ciICE_DECLARE_PKT_TEMPLATE(ipv4_l2tpv3) = { 127062306a36Sopenharmony_ci 0x00, 0x00, 0x00, 0x00, /* ICE_MAC_OFOS 0 */ 127162306a36Sopenharmony_ci 0x00, 0x00, 0x00, 0x00, 127262306a36Sopenharmony_ci 0x00, 0x00, 0x00, 0x00, 127362306a36Sopenharmony_ci 127462306a36Sopenharmony_ci 0x08, 0x00, /* ICE_ETYPE_OL 12 */ 127562306a36Sopenharmony_ci 127662306a36Sopenharmony_ci 0x45, 0x00, 0x00, 0x20, /* ICE_IPV4_IL 14 */ 127762306a36Sopenharmony_ci 0x00, 0x00, 0x40, 0x00, 127862306a36Sopenharmony_ci 0x40, 0x73, 0x00, 0x00, 127962306a36Sopenharmony_ci 0x00, 0x00, 0x00, 0x00, 128062306a36Sopenharmony_ci 0x00, 0x00, 0x00, 0x00, 128162306a36Sopenharmony_ci 128262306a36Sopenharmony_ci 0x00, 0x00, 0x00, 0x00, /* ICE_L2TPV3 34 */ 128362306a36Sopenharmony_ci 0x00, 0x00, 0x00, 0x00, 128462306a36Sopenharmony_ci 0x00, 0x00, 0x00, 0x00, 128562306a36Sopenharmony_ci 0x00, 0x00, /* 2 bytes for 4 bytes alignment */ 128662306a36Sopenharmony_ci}; 128762306a36Sopenharmony_ci 128862306a36Sopenharmony_ciICE_DECLARE_PKT_OFFSETS(ipv6_l2tpv3) = { 128962306a36Sopenharmony_ci { ICE_MAC_OFOS, 0 }, 129062306a36Sopenharmony_ci { ICE_ETYPE_OL, 12 }, 129162306a36Sopenharmony_ci { ICE_IPV6_OFOS, 14 }, 129262306a36Sopenharmony_ci { ICE_L2TPV3, 54 }, 129362306a36Sopenharmony_ci { ICE_PROTOCOL_LAST, 0 }, 129462306a36Sopenharmony_ci}; 129562306a36Sopenharmony_ci 129662306a36Sopenharmony_ciICE_DECLARE_PKT_TEMPLATE(ipv6_l2tpv3) = { 129762306a36Sopenharmony_ci 0x00, 0x00, 0x00, 0x00, /* ICE_MAC_OFOS 0 */ 129862306a36Sopenharmony_ci 0x00, 0x00, 0x00, 0x00, 129962306a36Sopenharmony_ci 0x00, 0x00, 0x00, 0x00, 130062306a36Sopenharmony_ci 130162306a36Sopenharmony_ci 0x86, 0xDD, /* ICE_ETYPE_OL 12 */ 130262306a36Sopenharmony_ci 130362306a36Sopenharmony_ci 0x60, 0x00, 0x00, 0x00, /* ICE_IPV6_IL 14 */ 130462306a36Sopenharmony_ci 0x00, 0x0c, 0x73, 0x40, 130562306a36Sopenharmony_ci 0x00, 0x00, 0x00, 0x00, 130662306a36Sopenharmony_ci 0x00, 0x00, 0x00, 0x00, 130762306a36Sopenharmony_ci 0x00, 0x00, 0x00, 0x00, 130862306a36Sopenharmony_ci 0x00, 0x00, 0x00, 0x00, 130962306a36Sopenharmony_ci 0x00, 0x00, 0x00, 0x00, 131062306a36Sopenharmony_ci 0x00, 0x00, 0x00, 0x00, 131162306a36Sopenharmony_ci 0x00, 0x00, 0x00, 0x00, 131262306a36Sopenharmony_ci 0x00, 0x00, 0x00, 0x00, 131362306a36Sopenharmony_ci 131462306a36Sopenharmony_ci 0x00, 0x00, 0x00, 0x00, /* ICE_L2TPV3 54 */ 131562306a36Sopenharmony_ci 0x00, 0x00, 0x00, 0x00, 131662306a36Sopenharmony_ci 0x00, 0x00, 0x00, 0x00, 131762306a36Sopenharmony_ci 0x00, 0x00, /* 2 bytes for 4 bytes alignment */ 131862306a36Sopenharmony_ci}; 131962306a36Sopenharmony_ci 132062306a36Sopenharmony_cistatic const struct ice_dummy_pkt_profile ice_dummy_pkt_profiles[] = { 132162306a36Sopenharmony_ci ICE_PKT_PROFILE(ipv6_gtp, ICE_PKT_TUN_GTPU | ICE_PKT_OUTER_IPV6 | 132262306a36Sopenharmony_ci ICE_PKT_GTP_NOPAY), 132362306a36Sopenharmony_ci ICE_PKT_PROFILE(ipv6_gtpu_ipv6_udp, ICE_PKT_TUN_GTPU | 132462306a36Sopenharmony_ci ICE_PKT_OUTER_IPV6 | 132562306a36Sopenharmony_ci ICE_PKT_INNER_IPV6 | 132662306a36Sopenharmony_ci ICE_PKT_INNER_UDP), 132762306a36Sopenharmony_ci ICE_PKT_PROFILE(ipv6_gtpu_ipv6_tcp, ICE_PKT_TUN_GTPU | 132862306a36Sopenharmony_ci ICE_PKT_OUTER_IPV6 | 132962306a36Sopenharmony_ci ICE_PKT_INNER_IPV6), 133062306a36Sopenharmony_ci ICE_PKT_PROFILE(ipv6_gtpu_ipv4_udp, ICE_PKT_TUN_GTPU | 133162306a36Sopenharmony_ci ICE_PKT_OUTER_IPV6 | 133262306a36Sopenharmony_ci ICE_PKT_INNER_UDP), 133362306a36Sopenharmony_ci ICE_PKT_PROFILE(ipv6_gtpu_ipv4_tcp, ICE_PKT_TUN_GTPU | 133462306a36Sopenharmony_ci ICE_PKT_OUTER_IPV6), 133562306a36Sopenharmony_ci ICE_PKT_PROFILE(ipv4_gtpu_ipv4, ICE_PKT_TUN_GTPU | ICE_PKT_GTP_NOPAY), 133662306a36Sopenharmony_ci ICE_PKT_PROFILE(ipv4_gtpu_ipv6_udp, ICE_PKT_TUN_GTPU | 133762306a36Sopenharmony_ci ICE_PKT_INNER_IPV6 | 133862306a36Sopenharmony_ci ICE_PKT_INNER_UDP), 133962306a36Sopenharmony_ci ICE_PKT_PROFILE(ipv4_gtpu_ipv6_tcp, ICE_PKT_TUN_GTPU | 134062306a36Sopenharmony_ci ICE_PKT_INNER_IPV6), 134162306a36Sopenharmony_ci ICE_PKT_PROFILE(ipv4_gtpu_ipv4_udp, ICE_PKT_TUN_GTPU | 134262306a36Sopenharmony_ci ICE_PKT_INNER_UDP), 134362306a36Sopenharmony_ci ICE_PKT_PROFILE(ipv4_gtpu_ipv4_tcp, ICE_PKT_TUN_GTPU), 134462306a36Sopenharmony_ci ICE_PKT_PROFILE(ipv6_gtp, ICE_PKT_TUN_GTPC | ICE_PKT_OUTER_IPV6), 134562306a36Sopenharmony_ci ICE_PKT_PROFILE(ipv4_gtpu_ipv4, ICE_PKT_TUN_GTPC), 134662306a36Sopenharmony_ci ICE_PKT_PROFILE(pppoe_ipv6_udp, ICE_PKT_PPPOE | ICE_PKT_OUTER_IPV6 | 134762306a36Sopenharmony_ci ICE_PKT_INNER_UDP), 134862306a36Sopenharmony_ci ICE_PKT_PROFILE(pppoe_ipv6_tcp, ICE_PKT_PPPOE | ICE_PKT_OUTER_IPV6), 134962306a36Sopenharmony_ci ICE_PKT_PROFILE(pppoe_ipv4_udp, ICE_PKT_PPPOE | ICE_PKT_INNER_UDP), 135062306a36Sopenharmony_ci ICE_PKT_PROFILE(pppoe_ipv4_tcp, ICE_PKT_PPPOE), 135162306a36Sopenharmony_ci ICE_PKT_PROFILE(gre_ipv6_tcp, ICE_PKT_TUN_NVGRE | ICE_PKT_INNER_IPV6 | 135262306a36Sopenharmony_ci ICE_PKT_INNER_TCP), 135362306a36Sopenharmony_ci ICE_PKT_PROFILE(gre_tcp, ICE_PKT_TUN_NVGRE | ICE_PKT_INNER_TCP), 135462306a36Sopenharmony_ci ICE_PKT_PROFILE(gre_ipv6_udp, ICE_PKT_TUN_NVGRE | ICE_PKT_INNER_IPV6), 135562306a36Sopenharmony_ci ICE_PKT_PROFILE(gre_udp, ICE_PKT_TUN_NVGRE), 135662306a36Sopenharmony_ci ICE_PKT_PROFILE(udp_tun_ipv6_tcp, ICE_PKT_TUN_UDP | 135762306a36Sopenharmony_ci ICE_PKT_INNER_IPV6 | 135862306a36Sopenharmony_ci ICE_PKT_INNER_TCP), 135962306a36Sopenharmony_ci ICE_PKT_PROFILE(ipv6_l2tpv3, ICE_PKT_L2TPV3 | ICE_PKT_OUTER_IPV6), 136062306a36Sopenharmony_ci ICE_PKT_PROFILE(ipv4_l2tpv3, ICE_PKT_L2TPV3), 136162306a36Sopenharmony_ci ICE_PKT_PROFILE(udp_tun_tcp, ICE_PKT_TUN_UDP | ICE_PKT_INNER_TCP), 136262306a36Sopenharmony_ci ICE_PKT_PROFILE(udp_tun_ipv6_udp, ICE_PKT_TUN_UDP | 136362306a36Sopenharmony_ci ICE_PKT_INNER_IPV6), 136462306a36Sopenharmony_ci ICE_PKT_PROFILE(udp_tun_udp, ICE_PKT_TUN_UDP), 136562306a36Sopenharmony_ci ICE_PKT_PROFILE(udp_ipv6, ICE_PKT_OUTER_IPV6 | ICE_PKT_INNER_UDP), 136662306a36Sopenharmony_ci ICE_PKT_PROFILE(udp, ICE_PKT_INNER_UDP), 136762306a36Sopenharmony_ci ICE_PKT_PROFILE(tcp_ipv6, ICE_PKT_OUTER_IPV6), 136862306a36Sopenharmony_ci ICE_PKT_PROFILE(tcp, 0), 136962306a36Sopenharmony_ci}; 137062306a36Sopenharmony_ci 137162306a36Sopenharmony_ci/* this is a recipe to profile association bitmap */ 137262306a36Sopenharmony_cistatic DECLARE_BITMAP(recipe_to_profile[ICE_MAX_NUM_RECIPES], 137362306a36Sopenharmony_ci ICE_MAX_NUM_PROFILES); 137462306a36Sopenharmony_ci 137562306a36Sopenharmony_ci/* this is a profile to recipe association bitmap */ 137662306a36Sopenharmony_cistatic DECLARE_BITMAP(profile_to_recipe[ICE_MAX_NUM_PROFILES], 137762306a36Sopenharmony_ci ICE_MAX_NUM_RECIPES); 137862306a36Sopenharmony_ci 137962306a36Sopenharmony_ci/** 138062306a36Sopenharmony_ci * ice_init_def_sw_recp - initialize the recipe book keeping tables 138162306a36Sopenharmony_ci * @hw: pointer to the HW struct 138262306a36Sopenharmony_ci * 138362306a36Sopenharmony_ci * Allocate memory for the entire recipe table and initialize the structures/ 138462306a36Sopenharmony_ci * entries corresponding to basic recipes. 138562306a36Sopenharmony_ci */ 138662306a36Sopenharmony_ciint ice_init_def_sw_recp(struct ice_hw *hw) 138762306a36Sopenharmony_ci{ 138862306a36Sopenharmony_ci struct ice_sw_recipe *recps; 138962306a36Sopenharmony_ci u8 i; 139062306a36Sopenharmony_ci 139162306a36Sopenharmony_ci recps = devm_kcalloc(ice_hw_to_dev(hw), ICE_MAX_NUM_RECIPES, 139262306a36Sopenharmony_ci sizeof(*recps), GFP_KERNEL); 139362306a36Sopenharmony_ci if (!recps) 139462306a36Sopenharmony_ci return -ENOMEM; 139562306a36Sopenharmony_ci 139662306a36Sopenharmony_ci for (i = 0; i < ICE_MAX_NUM_RECIPES; i++) { 139762306a36Sopenharmony_ci recps[i].root_rid = i; 139862306a36Sopenharmony_ci INIT_LIST_HEAD(&recps[i].filt_rules); 139962306a36Sopenharmony_ci INIT_LIST_HEAD(&recps[i].filt_replay_rules); 140062306a36Sopenharmony_ci INIT_LIST_HEAD(&recps[i].rg_list); 140162306a36Sopenharmony_ci mutex_init(&recps[i].filt_rule_lock); 140262306a36Sopenharmony_ci } 140362306a36Sopenharmony_ci 140462306a36Sopenharmony_ci hw->switch_info->recp_list = recps; 140562306a36Sopenharmony_ci 140662306a36Sopenharmony_ci return 0; 140762306a36Sopenharmony_ci} 140862306a36Sopenharmony_ci 140962306a36Sopenharmony_ci/** 141062306a36Sopenharmony_ci * ice_aq_get_sw_cfg - get switch configuration 141162306a36Sopenharmony_ci * @hw: pointer to the hardware structure 141262306a36Sopenharmony_ci * @buf: pointer to the result buffer 141362306a36Sopenharmony_ci * @buf_size: length of the buffer available for response 141462306a36Sopenharmony_ci * @req_desc: pointer to requested descriptor 141562306a36Sopenharmony_ci * @num_elems: pointer to number of elements 141662306a36Sopenharmony_ci * @cd: pointer to command details structure or NULL 141762306a36Sopenharmony_ci * 141862306a36Sopenharmony_ci * Get switch configuration (0x0200) to be placed in buf. 141962306a36Sopenharmony_ci * This admin command returns information such as initial VSI/port number 142062306a36Sopenharmony_ci * and switch ID it belongs to. 142162306a36Sopenharmony_ci * 142262306a36Sopenharmony_ci * NOTE: *req_desc is both an input/output parameter. 142362306a36Sopenharmony_ci * The caller of this function first calls this function with *request_desc set 142462306a36Sopenharmony_ci * to 0. If the response from f/w has *req_desc set to 0, all the switch 142562306a36Sopenharmony_ci * configuration information has been returned; if non-zero (meaning not all 142662306a36Sopenharmony_ci * the information was returned), the caller should call this function again 142762306a36Sopenharmony_ci * with *req_desc set to the previous value returned by f/w to get the 142862306a36Sopenharmony_ci * next block of switch configuration information. 142962306a36Sopenharmony_ci * 143062306a36Sopenharmony_ci * *num_elems is output only parameter. This reflects the number of elements 143162306a36Sopenharmony_ci * in response buffer. The caller of this function to use *num_elems while 143262306a36Sopenharmony_ci * parsing the response buffer. 143362306a36Sopenharmony_ci */ 143462306a36Sopenharmony_cistatic int 143562306a36Sopenharmony_ciice_aq_get_sw_cfg(struct ice_hw *hw, struct ice_aqc_get_sw_cfg_resp_elem *buf, 143662306a36Sopenharmony_ci u16 buf_size, u16 *req_desc, u16 *num_elems, 143762306a36Sopenharmony_ci struct ice_sq_cd *cd) 143862306a36Sopenharmony_ci{ 143962306a36Sopenharmony_ci struct ice_aqc_get_sw_cfg *cmd; 144062306a36Sopenharmony_ci struct ice_aq_desc desc; 144162306a36Sopenharmony_ci int status; 144262306a36Sopenharmony_ci 144362306a36Sopenharmony_ci ice_fill_dflt_direct_cmd_desc(&desc, ice_aqc_opc_get_sw_cfg); 144462306a36Sopenharmony_ci cmd = &desc.params.get_sw_conf; 144562306a36Sopenharmony_ci cmd->element = cpu_to_le16(*req_desc); 144662306a36Sopenharmony_ci 144762306a36Sopenharmony_ci status = ice_aq_send_cmd(hw, &desc, buf, buf_size, cd); 144862306a36Sopenharmony_ci if (!status) { 144962306a36Sopenharmony_ci *req_desc = le16_to_cpu(cmd->element); 145062306a36Sopenharmony_ci *num_elems = le16_to_cpu(cmd->num_elems); 145162306a36Sopenharmony_ci } 145262306a36Sopenharmony_ci 145362306a36Sopenharmony_ci return status; 145462306a36Sopenharmony_ci} 145562306a36Sopenharmony_ci 145662306a36Sopenharmony_ci/** 145762306a36Sopenharmony_ci * ice_aq_add_vsi 145862306a36Sopenharmony_ci * @hw: pointer to the HW struct 145962306a36Sopenharmony_ci * @vsi_ctx: pointer to a VSI context struct 146062306a36Sopenharmony_ci * @cd: pointer to command details structure or NULL 146162306a36Sopenharmony_ci * 146262306a36Sopenharmony_ci * Add a VSI context to the hardware (0x0210) 146362306a36Sopenharmony_ci */ 146462306a36Sopenharmony_cistatic int 146562306a36Sopenharmony_ciice_aq_add_vsi(struct ice_hw *hw, struct ice_vsi_ctx *vsi_ctx, 146662306a36Sopenharmony_ci struct ice_sq_cd *cd) 146762306a36Sopenharmony_ci{ 146862306a36Sopenharmony_ci struct ice_aqc_add_update_free_vsi_resp *res; 146962306a36Sopenharmony_ci struct ice_aqc_add_get_update_free_vsi *cmd; 147062306a36Sopenharmony_ci struct ice_aq_desc desc; 147162306a36Sopenharmony_ci int status; 147262306a36Sopenharmony_ci 147362306a36Sopenharmony_ci cmd = &desc.params.vsi_cmd; 147462306a36Sopenharmony_ci res = &desc.params.add_update_free_vsi_res; 147562306a36Sopenharmony_ci 147662306a36Sopenharmony_ci ice_fill_dflt_direct_cmd_desc(&desc, ice_aqc_opc_add_vsi); 147762306a36Sopenharmony_ci 147862306a36Sopenharmony_ci if (!vsi_ctx->alloc_from_pool) 147962306a36Sopenharmony_ci cmd->vsi_num = cpu_to_le16(vsi_ctx->vsi_num | 148062306a36Sopenharmony_ci ICE_AQ_VSI_IS_VALID); 148162306a36Sopenharmony_ci cmd->vf_id = vsi_ctx->vf_num; 148262306a36Sopenharmony_ci 148362306a36Sopenharmony_ci cmd->vsi_flags = cpu_to_le16(vsi_ctx->flags); 148462306a36Sopenharmony_ci 148562306a36Sopenharmony_ci desc.flags |= cpu_to_le16(ICE_AQ_FLAG_RD); 148662306a36Sopenharmony_ci 148762306a36Sopenharmony_ci status = ice_aq_send_cmd(hw, &desc, &vsi_ctx->info, 148862306a36Sopenharmony_ci sizeof(vsi_ctx->info), cd); 148962306a36Sopenharmony_ci 149062306a36Sopenharmony_ci if (!status) { 149162306a36Sopenharmony_ci vsi_ctx->vsi_num = le16_to_cpu(res->vsi_num) & ICE_AQ_VSI_NUM_M; 149262306a36Sopenharmony_ci vsi_ctx->vsis_allocd = le16_to_cpu(res->vsi_used); 149362306a36Sopenharmony_ci vsi_ctx->vsis_unallocated = le16_to_cpu(res->vsi_free); 149462306a36Sopenharmony_ci } 149562306a36Sopenharmony_ci 149662306a36Sopenharmony_ci return status; 149762306a36Sopenharmony_ci} 149862306a36Sopenharmony_ci 149962306a36Sopenharmony_ci/** 150062306a36Sopenharmony_ci * ice_aq_free_vsi 150162306a36Sopenharmony_ci * @hw: pointer to the HW struct 150262306a36Sopenharmony_ci * @vsi_ctx: pointer to a VSI context struct 150362306a36Sopenharmony_ci * @keep_vsi_alloc: keep VSI allocation as part of this PF's resources 150462306a36Sopenharmony_ci * @cd: pointer to command details structure or NULL 150562306a36Sopenharmony_ci * 150662306a36Sopenharmony_ci * Free VSI context info from hardware (0x0213) 150762306a36Sopenharmony_ci */ 150862306a36Sopenharmony_cistatic int 150962306a36Sopenharmony_ciice_aq_free_vsi(struct ice_hw *hw, struct ice_vsi_ctx *vsi_ctx, 151062306a36Sopenharmony_ci bool keep_vsi_alloc, struct ice_sq_cd *cd) 151162306a36Sopenharmony_ci{ 151262306a36Sopenharmony_ci struct ice_aqc_add_update_free_vsi_resp *resp; 151362306a36Sopenharmony_ci struct ice_aqc_add_get_update_free_vsi *cmd; 151462306a36Sopenharmony_ci struct ice_aq_desc desc; 151562306a36Sopenharmony_ci int status; 151662306a36Sopenharmony_ci 151762306a36Sopenharmony_ci cmd = &desc.params.vsi_cmd; 151862306a36Sopenharmony_ci resp = &desc.params.add_update_free_vsi_res; 151962306a36Sopenharmony_ci 152062306a36Sopenharmony_ci ice_fill_dflt_direct_cmd_desc(&desc, ice_aqc_opc_free_vsi); 152162306a36Sopenharmony_ci 152262306a36Sopenharmony_ci cmd->vsi_num = cpu_to_le16(vsi_ctx->vsi_num | ICE_AQ_VSI_IS_VALID); 152362306a36Sopenharmony_ci if (keep_vsi_alloc) 152462306a36Sopenharmony_ci cmd->cmd_flags = cpu_to_le16(ICE_AQ_VSI_KEEP_ALLOC); 152562306a36Sopenharmony_ci 152662306a36Sopenharmony_ci status = ice_aq_send_cmd(hw, &desc, NULL, 0, cd); 152762306a36Sopenharmony_ci if (!status) { 152862306a36Sopenharmony_ci vsi_ctx->vsis_allocd = le16_to_cpu(resp->vsi_used); 152962306a36Sopenharmony_ci vsi_ctx->vsis_unallocated = le16_to_cpu(resp->vsi_free); 153062306a36Sopenharmony_ci } 153162306a36Sopenharmony_ci 153262306a36Sopenharmony_ci return status; 153362306a36Sopenharmony_ci} 153462306a36Sopenharmony_ci 153562306a36Sopenharmony_ci/** 153662306a36Sopenharmony_ci * ice_aq_update_vsi 153762306a36Sopenharmony_ci * @hw: pointer to the HW struct 153862306a36Sopenharmony_ci * @vsi_ctx: pointer to a VSI context struct 153962306a36Sopenharmony_ci * @cd: pointer to command details structure or NULL 154062306a36Sopenharmony_ci * 154162306a36Sopenharmony_ci * Update VSI context in the hardware (0x0211) 154262306a36Sopenharmony_ci */ 154362306a36Sopenharmony_cistatic int 154462306a36Sopenharmony_ciice_aq_update_vsi(struct ice_hw *hw, struct ice_vsi_ctx *vsi_ctx, 154562306a36Sopenharmony_ci struct ice_sq_cd *cd) 154662306a36Sopenharmony_ci{ 154762306a36Sopenharmony_ci struct ice_aqc_add_update_free_vsi_resp *resp; 154862306a36Sopenharmony_ci struct ice_aqc_add_get_update_free_vsi *cmd; 154962306a36Sopenharmony_ci struct ice_aq_desc desc; 155062306a36Sopenharmony_ci int status; 155162306a36Sopenharmony_ci 155262306a36Sopenharmony_ci cmd = &desc.params.vsi_cmd; 155362306a36Sopenharmony_ci resp = &desc.params.add_update_free_vsi_res; 155462306a36Sopenharmony_ci 155562306a36Sopenharmony_ci ice_fill_dflt_direct_cmd_desc(&desc, ice_aqc_opc_update_vsi); 155662306a36Sopenharmony_ci 155762306a36Sopenharmony_ci cmd->vsi_num = cpu_to_le16(vsi_ctx->vsi_num | ICE_AQ_VSI_IS_VALID); 155862306a36Sopenharmony_ci 155962306a36Sopenharmony_ci desc.flags |= cpu_to_le16(ICE_AQ_FLAG_RD); 156062306a36Sopenharmony_ci 156162306a36Sopenharmony_ci status = ice_aq_send_cmd(hw, &desc, &vsi_ctx->info, 156262306a36Sopenharmony_ci sizeof(vsi_ctx->info), cd); 156362306a36Sopenharmony_ci 156462306a36Sopenharmony_ci if (!status) { 156562306a36Sopenharmony_ci vsi_ctx->vsis_allocd = le16_to_cpu(resp->vsi_used); 156662306a36Sopenharmony_ci vsi_ctx->vsis_unallocated = le16_to_cpu(resp->vsi_free); 156762306a36Sopenharmony_ci } 156862306a36Sopenharmony_ci 156962306a36Sopenharmony_ci return status; 157062306a36Sopenharmony_ci} 157162306a36Sopenharmony_ci 157262306a36Sopenharmony_ci/** 157362306a36Sopenharmony_ci * ice_is_vsi_valid - check whether the VSI is valid or not 157462306a36Sopenharmony_ci * @hw: pointer to the HW struct 157562306a36Sopenharmony_ci * @vsi_handle: VSI handle 157662306a36Sopenharmony_ci * 157762306a36Sopenharmony_ci * check whether the VSI is valid or not 157862306a36Sopenharmony_ci */ 157962306a36Sopenharmony_cibool ice_is_vsi_valid(struct ice_hw *hw, u16 vsi_handle) 158062306a36Sopenharmony_ci{ 158162306a36Sopenharmony_ci return vsi_handle < ICE_MAX_VSI && hw->vsi_ctx[vsi_handle]; 158262306a36Sopenharmony_ci} 158362306a36Sopenharmony_ci 158462306a36Sopenharmony_ci/** 158562306a36Sopenharmony_ci * ice_get_hw_vsi_num - return the HW VSI number 158662306a36Sopenharmony_ci * @hw: pointer to the HW struct 158762306a36Sopenharmony_ci * @vsi_handle: VSI handle 158862306a36Sopenharmony_ci * 158962306a36Sopenharmony_ci * return the HW VSI number 159062306a36Sopenharmony_ci * Caution: call this function only if VSI is valid (ice_is_vsi_valid) 159162306a36Sopenharmony_ci */ 159262306a36Sopenharmony_ciu16 ice_get_hw_vsi_num(struct ice_hw *hw, u16 vsi_handle) 159362306a36Sopenharmony_ci{ 159462306a36Sopenharmony_ci return hw->vsi_ctx[vsi_handle]->vsi_num; 159562306a36Sopenharmony_ci} 159662306a36Sopenharmony_ci 159762306a36Sopenharmony_ci/** 159862306a36Sopenharmony_ci * ice_get_vsi_ctx - return the VSI context entry for a given VSI handle 159962306a36Sopenharmony_ci * @hw: pointer to the HW struct 160062306a36Sopenharmony_ci * @vsi_handle: VSI handle 160162306a36Sopenharmony_ci * 160262306a36Sopenharmony_ci * return the VSI context entry for a given VSI handle 160362306a36Sopenharmony_ci */ 160462306a36Sopenharmony_cistruct ice_vsi_ctx *ice_get_vsi_ctx(struct ice_hw *hw, u16 vsi_handle) 160562306a36Sopenharmony_ci{ 160662306a36Sopenharmony_ci return (vsi_handle >= ICE_MAX_VSI) ? NULL : hw->vsi_ctx[vsi_handle]; 160762306a36Sopenharmony_ci} 160862306a36Sopenharmony_ci 160962306a36Sopenharmony_ci/** 161062306a36Sopenharmony_ci * ice_save_vsi_ctx - save the VSI context for a given VSI handle 161162306a36Sopenharmony_ci * @hw: pointer to the HW struct 161262306a36Sopenharmony_ci * @vsi_handle: VSI handle 161362306a36Sopenharmony_ci * @vsi: VSI context pointer 161462306a36Sopenharmony_ci * 161562306a36Sopenharmony_ci * save the VSI context entry for a given VSI handle 161662306a36Sopenharmony_ci */ 161762306a36Sopenharmony_cistatic void 161862306a36Sopenharmony_ciice_save_vsi_ctx(struct ice_hw *hw, u16 vsi_handle, struct ice_vsi_ctx *vsi) 161962306a36Sopenharmony_ci{ 162062306a36Sopenharmony_ci hw->vsi_ctx[vsi_handle] = vsi; 162162306a36Sopenharmony_ci} 162262306a36Sopenharmony_ci 162362306a36Sopenharmony_ci/** 162462306a36Sopenharmony_ci * ice_clear_vsi_q_ctx - clear VSI queue contexts for all TCs 162562306a36Sopenharmony_ci * @hw: pointer to the HW struct 162662306a36Sopenharmony_ci * @vsi_handle: VSI handle 162762306a36Sopenharmony_ci */ 162862306a36Sopenharmony_cistatic void ice_clear_vsi_q_ctx(struct ice_hw *hw, u16 vsi_handle) 162962306a36Sopenharmony_ci{ 163062306a36Sopenharmony_ci struct ice_vsi_ctx *vsi = ice_get_vsi_ctx(hw, vsi_handle); 163162306a36Sopenharmony_ci u8 i; 163262306a36Sopenharmony_ci 163362306a36Sopenharmony_ci if (!vsi) 163462306a36Sopenharmony_ci return; 163562306a36Sopenharmony_ci ice_for_each_traffic_class(i) { 163662306a36Sopenharmony_ci devm_kfree(ice_hw_to_dev(hw), vsi->lan_q_ctx[i]); 163762306a36Sopenharmony_ci vsi->lan_q_ctx[i] = NULL; 163862306a36Sopenharmony_ci devm_kfree(ice_hw_to_dev(hw), vsi->rdma_q_ctx[i]); 163962306a36Sopenharmony_ci vsi->rdma_q_ctx[i] = NULL; 164062306a36Sopenharmony_ci } 164162306a36Sopenharmony_ci} 164262306a36Sopenharmony_ci 164362306a36Sopenharmony_ci/** 164462306a36Sopenharmony_ci * ice_clear_vsi_ctx - clear the VSI context entry 164562306a36Sopenharmony_ci * @hw: pointer to the HW struct 164662306a36Sopenharmony_ci * @vsi_handle: VSI handle 164762306a36Sopenharmony_ci * 164862306a36Sopenharmony_ci * clear the VSI context entry 164962306a36Sopenharmony_ci */ 165062306a36Sopenharmony_cistatic void ice_clear_vsi_ctx(struct ice_hw *hw, u16 vsi_handle) 165162306a36Sopenharmony_ci{ 165262306a36Sopenharmony_ci struct ice_vsi_ctx *vsi; 165362306a36Sopenharmony_ci 165462306a36Sopenharmony_ci vsi = ice_get_vsi_ctx(hw, vsi_handle); 165562306a36Sopenharmony_ci if (vsi) { 165662306a36Sopenharmony_ci ice_clear_vsi_q_ctx(hw, vsi_handle); 165762306a36Sopenharmony_ci devm_kfree(ice_hw_to_dev(hw), vsi); 165862306a36Sopenharmony_ci hw->vsi_ctx[vsi_handle] = NULL; 165962306a36Sopenharmony_ci } 166062306a36Sopenharmony_ci} 166162306a36Sopenharmony_ci 166262306a36Sopenharmony_ci/** 166362306a36Sopenharmony_ci * ice_clear_all_vsi_ctx - clear all the VSI context entries 166462306a36Sopenharmony_ci * @hw: pointer to the HW struct 166562306a36Sopenharmony_ci */ 166662306a36Sopenharmony_civoid ice_clear_all_vsi_ctx(struct ice_hw *hw) 166762306a36Sopenharmony_ci{ 166862306a36Sopenharmony_ci u16 i; 166962306a36Sopenharmony_ci 167062306a36Sopenharmony_ci for (i = 0; i < ICE_MAX_VSI; i++) 167162306a36Sopenharmony_ci ice_clear_vsi_ctx(hw, i); 167262306a36Sopenharmony_ci} 167362306a36Sopenharmony_ci 167462306a36Sopenharmony_ci/** 167562306a36Sopenharmony_ci * ice_add_vsi - add VSI context to the hardware and VSI handle list 167662306a36Sopenharmony_ci * @hw: pointer to the HW struct 167762306a36Sopenharmony_ci * @vsi_handle: unique VSI handle provided by drivers 167862306a36Sopenharmony_ci * @vsi_ctx: pointer to a VSI context struct 167962306a36Sopenharmony_ci * @cd: pointer to command details structure or NULL 168062306a36Sopenharmony_ci * 168162306a36Sopenharmony_ci * Add a VSI context to the hardware also add it into the VSI handle list. 168262306a36Sopenharmony_ci * If this function gets called after reset for existing VSIs then update 168362306a36Sopenharmony_ci * with the new HW VSI number in the corresponding VSI handle list entry. 168462306a36Sopenharmony_ci */ 168562306a36Sopenharmony_ciint 168662306a36Sopenharmony_ciice_add_vsi(struct ice_hw *hw, u16 vsi_handle, struct ice_vsi_ctx *vsi_ctx, 168762306a36Sopenharmony_ci struct ice_sq_cd *cd) 168862306a36Sopenharmony_ci{ 168962306a36Sopenharmony_ci struct ice_vsi_ctx *tmp_vsi_ctx; 169062306a36Sopenharmony_ci int status; 169162306a36Sopenharmony_ci 169262306a36Sopenharmony_ci if (vsi_handle >= ICE_MAX_VSI) 169362306a36Sopenharmony_ci return -EINVAL; 169462306a36Sopenharmony_ci status = ice_aq_add_vsi(hw, vsi_ctx, cd); 169562306a36Sopenharmony_ci if (status) 169662306a36Sopenharmony_ci return status; 169762306a36Sopenharmony_ci tmp_vsi_ctx = ice_get_vsi_ctx(hw, vsi_handle); 169862306a36Sopenharmony_ci if (!tmp_vsi_ctx) { 169962306a36Sopenharmony_ci /* Create a new VSI context */ 170062306a36Sopenharmony_ci tmp_vsi_ctx = devm_kzalloc(ice_hw_to_dev(hw), 170162306a36Sopenharmony_ci sizeof(*tmp_vsi_ctx), GFP_KERNEL); 170262306a36Sopenharmony_ci if (!tmp_vsi_ctx) { 170362306a36Sopenharmony_ci ice_aq_free_vsi(hw, vsi_ctx, false, cd); 170462306a36Sopenharmony_ci return -ENOMEM; 170562306a36Sopenharmony_ci } 170662306a36Sopenharmony_ci *tmp_vsi_ctx = *vsi_ctx; 170762306a36Sopenharmony_ci ice_save_vsi_ctx(hw, vsi_handle, tmp_vsi_ctx); 170862306a36Sopenharmony_ci } else { 170962306a36Sopenharmony_ci /* update with new HW VSI num */ 171062306a36Sopenharmony_ci tmp_vsi_ctx->vsi_num = vsi_ctx->vsi_num; 171162306a36Sopenharmony_ci } 171262306a36Sopenharmony_ci 171362306a36Sopenharmony_ci return 0; 171462306a36Sopenharmony_ci} 171562306a36Sopenharmony_ci 171662306a36Sopenharmony_ci/** 171762306a36Sopenharmony_ci * ice_free_vsi- free VSI context from hardware and VSI handle list 171862306a36Sopenharmony_ci * @hw: pointer to the HW struct 171962306a36Sopenharmony_ci * @vsi_handle: unique VSI handle 172062306a36Sopenharmony_ci * @vsi_ctx: pointer to a VSI context struct 172162306a36Sopenharmony_ci * @keep_vsi_alloc: keep VSI allocation as part of this PF's resources 172262306a36Sopenharmony_ci * @cd: pointer to command details structure or NULL 172362306a36Sopenharmony_ci * 172462306a36Sopenharmony_ci * Free VSI context info from hardware as well as from VSI handle list 172562306a36Sopenharmony_ci */ 172662306a36Sopenharmony_ciint 172762306a36Sopenharmony_ciice_free_vsi(struct ice_hw *hw, u16 vsi_handle, struct ice_vsi_ctx *vsi_ctx, 172862306a36Sopenharmony_ci bool keep_vsi_alloc, struct ice_sq_cd *cd) 172962306a36Sopenharmony_ci{ 173062306a36Sopenharmony_ci int status; 173162306a36Sopenharmony_ci 173262306a36Sopenharmony_ci if (!ice_is_vsi_valid(hw, vsi_handle)) 173362306a36Sopenharmony_ci return -EINVAL; 173462306a36Sopenharmony_ci vsi_ctx->vsi_num = ice_get_hw_vsi_num(hw, vsi_handle); 173562306a36Sopenharmony_ci status = ice_aq_free_vsi(hw, vsi_ctx, keep_vsi_alloc, cd); 173662306a36Sopenharmony_ci if (!status) 173762306a36Sopenharmony_ci ice_clear_vsi_ctx(hw, vsi_handle); 173862306a36Sopenharmony_ci return status; 173962306a36Sopenharmony_ci} 174062306a36Sopenharmony_ci 174162306a36Sopenharmony_ci/** 174262306a36Sopenharmony_ci * ice_update_vsi 174362306a36Sopenharmony_ci * @hw: pointer to the HW struct 174462306a36Sopenharmony_ci * @vsi_handle: unique VSI handle 174562306a36Sopenharmony_ci * @vsi_ctx: pointer to a VSI context struct 174662306a36Sopenharmony_ci * @cd: pointer to command details structure or NULL 174762306a36Sopenharmony_ci * 174862306a36Sopenharmony_ci * Update VSI context in the hardware 174962306a36Sopenharmony_ci */ 175062306a36Sopenharmony_ciint 175162306a36Sopenharmony_ciice_update_vsi(struct ice_hw *hw, u16 vsi_handle, struct ice_vsi_ctx *vsi_ctx, 175262306a36Sopenharmony_ci struct ice_sq_cd *cd) 175362306a36Sopenharmony_ci{ 175462306a36Sopenharmony_ci if (!ice_is_vsi_valid(hw, vsi_handle)) 175562306a36Sopenharmony_ci return -EINVAL; 175662306a36Sopenharmony_ci vsi_ctx->vsi_num = ice_get_hw_vsi_num(hw, vsi_handle); 175762306a36Sopenharmony_ci return ice_aq_update_vsi(hw, vsi_ctx, cd); 175862306a36Sopenharmony_ci} 175962306a36Sopenharmony_ci 176062306a36Sopenharmony_ci/** 176162306a36Sopenharmony_ci * ice_cfg_rdma_fltr - enable/disable RDMA filtering on VSI 176262306a36Sopenharmony_ci * @hw: pointer to HW struct 176362306a36Sopenharmony_ci * @vsi_handle: VSI SW index 176462306a36Sopenharmony_ci * @enable: boolean for enable/disable 176562306a36Sopenharmony_ci */ 176662306a36Sopenharmony_ciint 176762306a36Sopenharmony_ciice_cfg_rdma_fltr(struct ice_hw *hw, u16 vsi_handle, bool enable) 176862306a36Sopenharmony_ci{ 176962306a36Sopenharmony_ci struct ice_vsi_ctx *ctx, *cached_ctx; 177062306a36Sopenharmony_ci int status; 177162306a36Sopenharmony_ci 177262306a36Sopenharmony_ci cached_ctx = ice_get_vsi_ctx(hw, vsi_handle); 177362306a36Sopenharmony_ci if (!cached_ctx) 177462306a36Sopenharmony_ci return -ENOENT; 177562306a36Sopenharmony_ci 177662306a36Sopenharmony_ci ctx = kzalloc(sizeof(*ctx), GFP_KERNEL); 177762306a36Sopenharmony_ci if (!ctx) 177862306a36Sopenharmony_ci return -ENOMEM; 177962306a36Sopenharmony_ci 178062306a36Sopenharmony_ci ctx->info.q_opt_rss = cached_ctx->info.q_opt_rss; 178162306a36Sopenharmony_ci ctx->info.q_opt_tc = cached_ctx->info.q_opt_tc; 178262306a36Sopenharmony_ci ctx->info.q_opt_flags = cached_ctx->info.q_opt_flags; 178362306a36Sopenharmony_ci 178462306a36Sopenharmony_ci ctx->info.valid_sections = cpu_to_le16(ICE_AQ_VSI_PROP_Q_OPT_VALID); 178562306a36Sopenharmony_ci 178662306a36Sopenharmony_ci if (enable) 178762306a36Sopenharmony_ci ctx->info.q_opt_flags |= ICE_AQ_VSI_Q_OPT_PE_FLTR_EN; 178862306a36Sopenharmony_ci else 178962306a36Sopenharmony_ci ctx->info.q_opt_flags &= ~ICE_AQ_VSI_Q_OPT_PE_FLTR_EN; 179062306a36Sopenharmony_ci 179162306a36Sopenharmony_ci status = ice_update_vsi(hw, vsi_handle, ctx, NULL); 179262306a36Sopenharmony_ci if (!status) { 179362306a36Sopenharmony_ci cached_ctx->info.q_opt_flags = ctx->info.q_opt_flags; 179462306a36Sopenharmony_ci cached_ctx->info.valid_sections |= ctx->info.valid_sections; 179562306a36Sopenharmony_ci } 179662306a36Sopenharmony_ci 179762306a36Sopenharmony_ci kfree(ctx); 179862306a36Sopenharmony_ci return status; 179962306a36Sopenharmony_ci} 180062306a36Sopenharmony_ci 180162306a36Sopenharmony_ci/** 180262306a36Sopenharmony_ci * ice_aq_alloc_free_vsi_list 180362306a36Sopenharmony_ci * @hw: pointer to the HW struct 180462306a36Sopenharmony_ci * @vsi_list_id: VSI list ID returned or used for lookup 180562306a36Sopenharmony_ci * @lkup_type: switch rule filter lookup type 180662306a36Sopenharmony_ci * @opc: switch rules population command type - pass in the command opcode 180762306a36Sopenharmony_ci * 180862306a36Sopenharmony_ci * allocates or free a VSI list resource 180962306a36Sopenharmony_ci */ 181062306a36Sopenharmony_cistatic int 181162306a36Sopenharmony_ciice_aq_alloc_free_vsi_list(struct ice_hw *hw, u16 *vsi_list_id, 181262306a36Sopenharmony_ci enum ice_sw_lkup_type lkup_type, 181362306a36Sopenharmony_ci enum ice_adminq_opc opc) 181462306a36Sopenharmony_ci{ 181562306a36Sopenharmony_ci struct ice_aqc_alloc_free_res_elem *sw_buf; 181662306a36Sopenharmony_ci struct ice_aqc_res_elem *vsi_ele; 181762306a36Sopenharmony_ci u16 buf_len; 181862306a36Sopenharmony_ci int status; 181962306a36Sopenharmony_ci 182062306a36Sopenharmony_ci buf_len = struct_size(sw_buf, elem, 1); 182162306a36Sopenharmony_ci sw_buf = devm_kzalloc(ice_hw_to_dev(hw), buf_len, GFP_KERNEL); 182262306a36Sopenharmony_ci if (!sw_buf) 182362306a36Sopenharmony_ci return -ENOMEM; 182462306a36Sopenharmony_ci sw_buf->num_elems = cpu_to_le16(1); 182562306a36Sopenharmony_ci 182662306a36Sopenharmony_ci if (lkup_type == ICE_SW_LKUP_MAC || 182762306a36Sopenharmony_ci lkup_type == ICE_SW_LKUP_MAC_VLAN || 182862306a36Sopenharmony_ci lkup_type == ICE_SW_LKUP_ETHERTYPE || 182962306a36Sopenharmony_ci lkup_type == ICE_SW_LKUP_ETHERTYPE_MAC || 183062306a36Sopenharmony_ci lkup_type == ICE_SW_LKUP_PROMISC || 183162306a36Sopenharmony_ci lkup_type == ICE_SW_LKUP_PROMISC_VLAN || 183262306a36Sopenharmony_ci lkup_type == ICE_SW_LKUP_DFLT) { 183362306a36Sopenharmony_ci sw_buf->res_type = cpu_to_le16(ICE_AQC_RES_TYPE_VSI_LIST_REP); 183462306a36Sopenharmony_ci } else if (lkup_type == ICE_SW_LKUP_VLAN) { 183562306a36Sopenharmony_ci if (opc == ice_aqc_opc_alloc_res) 183662306a36Sopenharmony_ci sw_buf->res_type = 183762306a36Sopenharmony_ci cpu_to_le16(ICE_AQC_RES_TYPE_VSI_LIST_PRUNE | 183862306a36Sopenharmony_ci ICE_AQC_RES_TYPE_FLAG_SHARED); 183962306a36Sopenharmony_ci else 184062306a36Sopenharmony_ci sw_buf->res_type = 184162306a36Sopenharmony_ci cpu_to_le16(ICE_AQC_RES_TYPE_VSI_LIST_PRUNE); 184262306a36Sopenharmony_ci } else { 184362306a36Sopenharmony_ci status = -EINVAL; 184462306a36Sopenharmony_ci goto ice_aq_alloc_free_vsi_list_exit; 184562306a36Sopenharmony_ci } 184662306a36Sopenharmony_ci 184762306a36Sopenharmony_ci if (opc == ice_aqc_opc_free_res) 184862306a36Sopenharmony_ci sw_buf->elem[0].e.sw_resp = cpu_to_le16(*vsi_list_id); 184962306a36Sopenharmony_ci 185062306a36Sopenharmony_ci status = ice_aq_alloc_free_res(hw, sw_buf, buf_len, opc); 185162306a36Sopenharmony_ci if (status) 185262306a36Sopenharmony_ci goto ice_aq_alloc_free_vsi_list_exit; 185362306a36Sopenharmony_ci 185462306a36Sopenharmony_ci if (opc == ice_aqc_opc_alloc_res) { 185562306a36Sopenharmony_ci vsi_ele = &sw_buf->elem[0]; 185662306a36Sopenharmony_ci *vsi_list_id = le16_to_cpu(vsi_ele->e.sw_resp); 185762306a36Sopenharmony_ci } 185862306a36Sopenharmony_ci 185962306a36Sopenharmony_ciice_aq_alloc_free_vsi_list_exit: 186062306a36Sopenharmony_ci devm_kfree(ice_hw_to_dev(hw), sw_buf); 186162306a36Sopenharmony_ci return status; 186262306a36Sopenharmony_ci} 186362306a36Sopenharmony_ci 186462306a36Sopenharmony_ci/** 186562306a36Sopenharmony_ci * ice_aq_sw_rules - add/update/remove switch rules 186662306a36Sopenharmony_ci * @hw: pointer to the HW struct 186762306a36Sopenharmony_ci * @rule_list: pointer to switch rule population list 186862306a36Sopenharmony_ci * @rule_list_sz: total size of the rule list in bytes 186962306a36Sopenharmony_ci * @num_rules: number of switch rules in the rule_list 187062306a36Sopenharmony_ci * @opc: switch rules population command type - pass in the command opcode 187162306a36Sopenharmony_ci * @cd: pointer to command details structure or NULL 187262306a36Sopenharmony_ci * 187362306a36Sopenharmony_ci * Add(0x02a0)/Update(0x02a1)/Remove(0x02a2) switch rules commands to firmware 187462306a36Sopenharmony_ci */ 187562306a36Sopenharmony_ciint 187662306a36Sopenharmony_ciice_aq_sw_rules(struct ice_hw *hw, void *rule_list, u16 rule_list_sz, 187762306a36Sopenharmony_ci u8 num_rules, enum ice_adminq_opc opc, struct ice_sq_cd *cd) 187862306a36Sopenharmony_ci{ 187962306a36Sopenharmony_ci struct ice_aq_desc desc; 188062306a36Sopenharmony_ci int status; 188162306a36Sopenharmony_ci 188262306a36Sopenharmony_ci if (opc != ice_aqc_opc_add_sw_rules && 188362306a36Sopenharmony_ci opc != ice_aqc_opc_update_sw_rules && 188462306a36Sopenharmony_ci opc != ice_aqc_opc_remove_sw_rules) 188562306a36Sopenharmony_ci return -EINVAL; 188662306a36Sopenharmony_ci 188762306a36Sopenharmony_ci ice_fill_dflt_direct_cmd_desc(&desc, opc); 188862306a36Sopenharmony_ci 188962306a36Sopenharmony_ci desc.flags |= cpu_to_le16(ICE_AQ_FLAG_RD); 189062306a36Sopenharmony_ci desc.params.sw_rules.num_rules_fltr_entry_index = 189162306a36Sopenharmony_ci cpu_to_le16(num_rules); 189262306a36Sopenharmony_ci status = ice_aq_send_cmd(hw, &desc, rule_list, rule_list_sz, cd); 189362306a36Sopenharmony_ci if (opc != ice_aqc_opc_add_sw_rules && 189462306a36Sopenharmony_ci hw->adminq.sq_last_status == ICE_AQ_RC_ENOENT) 189562306a36Sopenharmony_ci status = -ENOENT; 189662306a36Sopenharmony_ci 189762306a36Sopenharmony_ci return status; 189862306a36Sopenharmony_ci} 189962306a36Sopenharmony_ci 190062306a36Sopenharmony_ci/** 190162306a36Sopenharmony_ci * ice_aq_add_recipe - add switch recipe 190262306a36Sopenharmony_ci * @hw: pointer to the HW struct 190362306a36Sopenharmony_ci * @s_recipe_list: pointer to switch rule population list 190462306a36Sopenharmony_ci * @num_recipes: number of switch recipes in the list 190562306a36Sopenharmony_ci * @cd: pointer to command details structure or NULL 190662306a36Sopenharmony_ci * 190762306a36Sopenharmony_ci * Add(0x0290) 190862306a36Sopenharmony_ci */ 190962306a36Sopenharmony_ciint 191062306a36Sopenharmony_ciice_aq_add_recipe(struct ice_hw *hw, 191162306a36Sopenharmony_ci struct ice_aqc_recipe_data_elem *s_recipe_list, 191262306a36Sopenharmony_ci u16 num_recipes, struct ice_sq_cd *cd) 191362306a36Sopenharmony_ci{ 191462306a36Sopenharmony_ci struct ice_aqc_add_get_recipe *cmd; 191562306a36Sopenharmony_ci struct ice_aq_desc desc; 191662306a36Sopenharmony_ci u16 buf_size; 191762306a36Sopenharmony_ci 191862306a36Sopenharmony_ci cmd = &desc.params.add_get_recipe; 191962306a36Sopenharmony_ci ice_fill_dflt_direct_cmd_desc(&desc, ice_aqc_opc_add_recipe); 192062306a36Sopenharmony_ci 192162306a36Sopenharmony_ci cmd->num_sub_recipes = cpu_to_le16(num_recipes); 192262306a36Sopenharmony_ci desc.flags |= cpu_to_le16(ICE_AQ_FLAG_RD); 192362306a36Sopenharmony_ci 192462306a36Sopenharmony_ci buf_size = num_recipes * sizeof(*s_recipe_list); 192562306a36Sopenharmony_ci 192662306a36Sopenharmony_ci return ice_aq_send_cmd(hw, &desc, s_recipe_list, buf_size, cd); 192762306a36Sopenharmony_ci} 192862306a36Sopenharmony_ci 192962306a36Sopenharmony_ci/** 193062306a36Sopenharmony_ci * ice_aq_get_recipe - get switch recipe 193162306a36Sopenharmony_ci * @hw: pointer to the HW struct 193262306a36Sopenharmony_ci * @s_recipe_list: pointer to switch rule population list 193362306a36Sopenharmony_ci * @num_recipes: pointer to the number of recipes (input and output) 193462306a36Sopenharmony_ci * @recipe_root: root recipe number of recipe(s) to retrieve 193562306a36Sopenharmony_ci * @cd: pointer to command details structure or NULL 193662306a36Sopenharmony_ci * 193762306a36Sopenharmony_ci * Get(0x0292) 193862306a36Sopenharmony_ci * 193962306a36Sopenharmony_ci * On input, *num_recipes should equal the number of entries in s_recipe_list. 194062306a36Sopenharmony_ci * On output, *num_recipes will equal the number of entries returned in 194162306a36Sopenharmony_ci * s_recipe_list. 194262306a36Sopenharmony_ci * 194362306a36Sopenharmony_ci * The caller must supply enough space in s_recipe_list to hold all possible 194462306a36Sopenharmony_ci * recipes and *num_recipes must equal ICE_MAX_NUM_RECIPES. 194562306a36Sopenharmony_ci */ 194662306a36Sopenharmony_ciint 194762306a36Sopenharmony_ciice_aq_get_recipe(struct ice_hw *hw, 194862306a36Sopenharmony_ci struct ice_aqc_recipe_data_elem *s_recipe_list, 194962306a36Sopenharmony_ci u16 *num_recipes, u16 recipe_root, struct ice_sq_cd *cd) 195062306a36Sopenharmony_ci{ 195162306a36Sopenharmony_ci struct ice_aqc_add_get_recipe *cmd; 195262306a36Sopenharmony_ci struct ice_aq_desc desc; 195362306a36Sopenharmony_ci u16 buf_size; 195462306a36Sopenharmony_ci int status; 195562306a36Sopenharmony_ci 195662306a36Sopenharmony_ci if (*num_recipes != ICE_MAX_NUM_RECIPES) 195762306a36Sopenharmony_ci return -EINVAL; 195862306a36Sopenharmony_ci 195962306a36Sopenharmony_ci cmd = &desc.params.add_get_recipe; 196062306a36Sopenharmony_ci ice_fill_dflt_direct_cmd_desc(&desc, ice_aqc_opc_get_recipe); 196162306a36Sopenharmony_ci 196262306a36Sopenharmony_ci cmd->return_index = cpu_to_le16(recipe_root); 196362306a36Sopenharmony_ci cmd->num_sub_recipes = 0; 196462306a36Sopenharmony_ci 196562306a36Sopenharmony_ci buf_size = *num_recipes * sizeof(*s_recipe_list); 196662306a36Sopenharmony_ci 196762306a36Sopenharmony_ci status = ice_aq_send_cmd(hw, &desc, s_recipe_list, buf_size, cd); 196862306a36Sopenharmony_ci *num_recipes = le16_to_cpu(cmd->num_sub_recipes); 196962306a36Sopenharmony_ci 197062306a36Sopenharmony_ci return status; 197162306a36Sopenharmony_ci} 197262306a36Sopenharmony_ci 197362306a36Sopenharmony_ci/** 197462306a36Sopenharmony_ci * ice_update_recipe_lkup_idx - update a default recipe based on the lkup_idx 197562306a36Sopenharmony_ci * @hw: pointer to the HW struct 197662306a36Sopenharmony_ci * @params: parameters used to update the default recipe 197762306a36Sopenharmony_ci * 197862306a36Sopenharmony_ci * This function only supports updating default recipes and it only supports 197962306a36Sopenharmony_ci * updating a single recipe based on the lkup_idx at a time. 198062306a36Sopenharmony_ci * 198162306a36Sopenharmony_ci * This is done as a read-modify-write operation. First, get the current recipe 198262306a36Sopenharmony_ci * contents based on the recipe's ID. Then modify the field vector index and 198362306a36Sopenharmony_ci * mask if it's valid at the lkup_idx. Finally, use the add recipe AQ to update 198462306a36Sopenharmony_ci * the pre-existing recipe with the modifications. 198562306a36Sopenharmony_ci */ 198662306a36Sopenharmony_ciint 198762306a36Sopenharmony_ciice_update_recipe_lkup_idx(struct ice_hw *hw, 198862306a36Sopenharmony_ci struct ice_update_recipe_lkup_idx_params *params) 198962306a36Sopenharmony_ci{ 199062306a36Sopenharmony_ci struct ice_aqc_recipe_data_elem *rcp_list; 199162306a36Sopenharmony_ci u16 num_recps = ICE_MAX_NUM_RECIPES; 199262306a36Sopenharmony_ci int status; 199362306a36Sopenharmony_ci 199462306a36Sopenharmony_ci rcp_list = kcalloc(num_recps, sizeof(*rcp_list), GFP_KERNEL); 199562306a36Sopenharmony_ci if (!rcp_list) 199662306a36Sopenharmony_ci return -ENOMEM; 199762306a36Sopenharmony_ci 199862306a36Sopenharmony_ci /* read current recipe list from firmware */ 199962306a36Sopenharmony_ci rcp_list->recipe_indx = params->rid; 200062306a36Sopenharmony_ci status = ice_aq_get_recipe(hw, rcp_list, &num_recps, params->rid, NULL); 200162306a36Sopenharmony_ci if (status) { 200262306a36Sopenharmony_ci ice_debug(hw, ICE_DBG_SW, "Failed to get recipe %d, status %d\n", 200362306a36Sopenharmony_ci params->rid, status); 200462306a36Sopenharmony_ci goto error_out; 200562306a36Sopenharmony_ci } 200662306a36Sopenharmony_ci 200762306a36Sopenharmony_ci /* only modify existing recipe's lkup_idx and mask if valid, while 200862306a36Sopenharmony_ci * leaving all other fields the same, then update the recipe firmware 200962306a36Sopenharmony_ci */ 201062306a36Sopenharmony_ci rcp_list->content.lkup_indx[params->lkup_idx] = params->fv_idx; 201162306a36Sopenharmony_ci if (params->mask_valid) 201262306a36Sopenharmony_ci rcp_list->content.mask[params->lkup_idx] = 201362306a36Sopenharmony_ci cpu_to_le16(params->mask); 201462306a36Sopenharmony_ci 201562306a36Sopenharmony_ci if (params->ignore_valid) 201662306a36Sopenharmony_ci rcp_list->content.lkup_indx[params->lkup_idx] |= 201762306a36Sopenharmony_ci ICE_AQ_RECIPE_LKUP_IGNORE; 201862306a36Sopenharmony_ci 201962306a36Sopenharmony_ci status = ice_aq_add_recipe(hw, &rcp_list[0], 1, NULL); 202062306a36Sopenharmony_ci if (status) 202162306a36Sopenharmony_ci ice_debug(hw, ICE_DBG_SW, "Failed to update recipe %d lkup_idx %d fv_idx %d mask %d mask_valid %s, status %d\n", 202262306a36Sopenharmony_ci params->rid, params->lkup_idx, params->fv_idx, 202362306a36Sopenharmony_ci params->mask, params->mask_valid ? "true" : "false", 202462306a36Sopenharmony_ci status); 202562306a36Sopenharmony_ci 202662306a36Sopenharmony_cierror_out: 202762306a36Sopenharmony_ci kfree(rcp_list); 202862306a36Sopenharmony_ci return status; 202962306a36Sopenharmony_ci} 203062306a36Sopenharmony_ci 203162306a36Sopenharmony_ci/** 203262306a36Sopenharmony_ci * ice_aq_map_recipe_to_profile - Map recipe to packet profile 203362306a36Sopenharmony_ci * @hw: pointer to the HW struct 203462306a36Sopenharmony_ci * @profile_id: package profile ID to associate the recipe with 203562306a36Sopenharmony_ci * @r_bitmap: Recipe bitmap filled in and need to be returned as response 203662306a36Sopenharmony_ci * @cd: pointer to command details structure or NULL 203762306a36Sopenharmony_ci * Recipe to profile association (0x0291) 203862306a36Sopenharmony_ci */ 203962306a36Sopenharmony_ciint 204062306a36Sopenharmony_ciice_aq_map_recipe_to_profile(struct ice_hw *hw, u32 profile_id, u8 *r_bitmap, 204162306a36Sopenharmony_ci struct ice_sq_cd *cd) 204262306a36Sopenharmony_ci{ 204362306a36Sopenharmony_ci struct ice_aqc_recipe_to_profile *cmd; 204462306a36Sopenharmony_ci struct ice_aq_desc desc; 204562306a36Sopenharmony_ci 204662306a36Sopenharmony_ci cmd = &desc.params.recipe_to_profile; 204762306a36Sopenharmony_ci ice_fill_dflt_direct_cmd_desc(&desc, ice_aqc_opc_recipe_to_profile); 204862306a36Sopenharmony_ci cmd->profile_id = cpu_to_le16(profile_id); 204962306a36Sopenharmony_ci /* Set the recipe ID bit in the bitmask to let the device know which 205062306a36Sopenharmony_ci * profile we are associating the recipe to 205162306a36Sopenharmony_ci */ 205262306a36Sopenharmony_ci memcpy(cmd->recipe_assoc, r_bitmap, sizeof(cmd->recipe_assoc)); 205362306a36Sopenharmony_ci 205462306a36Sopenharmony_ci return ice_aq_send_cmd(hw, &desc, NULL, 0, cd); 205562306a36Sopenharmony_ci} 205662306a36Sopenharmony_ci 205762306a36Sopenharmony_ci/** 205862306a36Sopenharmony_ci * ice_aq_get_recipe_to_profile - Map recipe to packet profile 205962306a36Sopenharmony_ci * @hw: pointer to the HW struct 206062306a36Sopenharmony_ci * @profile_id: package profile ID to associate the recipe with 206162306a36Sopenharmony_ci * @r_bitmap: Recipe bitmap filled in and need to be returned as response 206262306a36Sopenharmony_ci * @cd: pointer to command details structure or NULL 206362306a36Sopenharmony_ci * Associate profile ID with given recipe (0x0293) 206462306a36Sopenharmony_ci */ 206562306a36Sopenharmony_ciint 206662306a36Sopenharmony_ciice_aq_get_recipe_to_profile(struct ice_hw *hw, u32 profile_id, u8 *r_bitmap, 206762306a36Sopenharmony_ci struct ice_sq_cd *cd) 206862306a36Sopenharmony_ci{ 206962306a36Sopenharmony_ci struct ice_aqc_recipe_to_profile *cmd; 207062306a36Sopenharmony_ci struct ice_aq_desc desc; 207162306a36Sopenharmony_ci int status; 207262306a36Sopenharmony_ci 207362306a36Sopenharmony_ci cmd = &desc.params.recipe_to_profile; 207462306a36Sopenharmony_ci ice_fill_dflt_direct_cmd_desc(&desc, ice_aqc_opc_get_recipe_to_profile); 207562306a36Sopenharmony_ci cmd->profile_id = cpu_to_le16(profile_id); 207662306a36Sopenharmony_ci 207762306a36Sopenharmony_ci status = ice_aq_send_cmd(hw, &desc, NULL, 0, cd); 207862306a36Sopenharmony_ci if (!status) 207962306a36Sopenharmony_ci memcpy(r_bitmap, cmd->recipe_assoc, sizeof(cmd->recipe_assoc)); 208062306a36Sopenharmony_ci 208162306a36Sopenharmony_ci return status; 208262306a36Sopenharmony_ci} 208362306a36Sopenharmony_ci 208462306a36Sopenharmony_ci/** 208562306a36Sopenharmony_ci * ice_alloc_recipe - add recipe resource 208662306a36Sopenharmony_ci * @hw: pointer to the hardware structure 208762306a36Sopenharmony_ci * @rid: recipe ID returned as response to AQ call 208862306a36Sopenharmony_ci */ 208962306a36Sopenharmony_ciint ice_alloc_recipe(struct ice_hw *hw, u16 *rid) 209062306a36Sopenharmony_ci{ 209162306a36Sopenharmony_ci struct ice_aqc_alloc_free_res_elem *sw_buf; 209262306a36Sopenharmony_ci u16 buf_len; 209362306a36Sopenharmony_ci int status; 209462306a36Sopenharmony_ci 209562306a36Sopenharmony_ci buf_len = struct_size(sw_buf, elem, 1); 209662306a36Sopenharmony_ci sw_buf = kzalloc(buf_len, GFP_KERNEL); 209762306a36Sopenharmony_ci if (!sw_buf) 209862306a36Sopenharmony_ci return -ENOMEM; 209962306a36Sopenharmony_ci 210062306a36Sopenharmony_ci sw_buf->num_elems = cpu_to_le16(1); 210162306a36Sopenharmony_ci sw_buf->res_type = cpu_to_le16((ICE_AQC_RES_TYPE_RECIPE << 210262306a36Sopenharmony_ci ICE_AQC_RES_TYPE_S) | 210362306a36Sopenharmony_ci ICE_AQC_RES_TYPE_FLAG_SHARED); 210462306a36Sopenharmony_ci status = ice_aq_alloc_free_res(hw, sw_buf, buf_len, 210562306a36Sopenharmony_ci ice_aqc_opc_alloc_res); 210662306a36Sopenharmony_ci if (!status) 210762306a36Sopenharmony_ci *rid = le16_to_cpu(sw_buf->elem[0].e.sw_resp); 210862306a36Sopenharmony_ci kfree(sw_buf); 210962306a36Sopenharmony_ci 211062306a36Sopenharmony_ci return status; 211162306a36Sopenharmony_ci} 211262306a36Sopenharmony_ci 211362306a36Sopenharmony_ci/** 211462306a36Sopenharmony_ci * ice_get_recp_to_prof_map - updates recipe to profile mapping 211562306a36Sopenharmony_ci * @hw: pointer to hardware structure 211662306a36Sopenharmony_ci * 211762306a36Sopenharmony_ci * This function is used to populate recipe_to_profile matrix where index to 211862306a36Sopenharmony_ci * this array is the recipe ID and the element is the mapping of which profiles 211962306a36Sopenharmony_ci * is this recipe mapped to. 212062306a36Sopenharmony_ci */ 212162306a36Sopenharmony_cistatic void ice_get_recp_to_prof_map(struct ice_hw *hw) 212262306a36Sopenharmony_ci{ 212362306a36Sopenharmony_ci DECLARE_BITMAP(r_bitmap, ICE_MAX_NUM_RECIPES); 212462306a36Sopenharmony_ci u16 i; 212562306a36Sopenharmony_ci 212662306a36Sopenharmony_ci for (i = 0; i < hw->switch_info->max_used_prof_index + 1; i++) { 212762306a36Sopenharmony_ci u16 j; 212862306a36Sopenharmony_ci 212962306a36Sopenharmony_ci bitmap_zero(profile_to_recipe[i], ICE_MAX_NUM_RECIPES); 213062306a36Sopenharmony_ci bitmap_zero(r_bitmap, ICE_MAX_NUM_RECIPES); 213162306a36Sopenharmony_ci if (ice_aq_get_recipe_to_profile(hw, i, (u8 *)r_bitmap, NULL)) 213262306a36Sopenharmony_ci continue; 213362306a36Sopenharmony_ci bitmap_copy(profile_to_recipe[i], r_bitmap, 213462306a36Sopenharmony_ci ICE_MAX_NUM_RECIPES); 213562306a36Sopenharmony_ci for_each_set_bit(j, r_bitmap, ICE_MAX_NUM_RECIPES) 213662306a36Sopenharmony_ci set_bit(i, recipe_to_profile[j]); 213762306a36Sopenharmony_ci } 213862306a36Sopenharmony_ci} 213962306a36Sopenharmony_ci 214062306a36Sopenharmony_ci/** 214162306a36Sopenharmony_ci * ice_collect_result_idx - copy result index values 214262306a36Sopenharmony_ci * @buf: buffer that contains the result index 214362306a36Sopenharmony_ci * @recp: the recipe struct to copy data into 214462306a36Sopenharmony_ci */ 214562306a36Sopenharmony_cistatic void 214662306a36Sopenharmony_ciice_collect_result_idx(struct ice_aqc_recipe_data_elem *buf, 214762306a36Sopenharmony_ci struct ice_sw_recipe *recp) 214862306a36Sopenharmony_ci{ 214962306a36Sopenharmony_ci if (buf->content.result_indx & ICE_AQ_RECIPE_RESULT_EN) 215062306a36Sopenharmony_ci set_bit(buf->content.result_indx & ~ICE_AQ_RECIPE_RESULT_EN, 215162306a36Sopenharmony_ci recp->res_idxs); 215262306a36Sopenharmony_ci} 215362306a36Sopenharmony_ci 215462306a36Sopenharmony_ci/** 215562306a36Sopenharmony_ci * ice_get_recp_frm_fw - update SW bookkeeping from FW recipe entries 215662306a36Sopenharmony_ci * @hw: pointer to hardware structure 215762306a36Sopenharmony_ci * @recps: struct that we need to populate 215862306a36Sopenharmony_ci * @rid: recipe ID that we are populating 215962306a36Sopenharmony_ci * @refresh_required: true if we should get recipe to profile mapping from FW 216062306a36Sopenharmony_ci * 216162306a36Sopenharmony_ci * This function is used to populate all the necessary entries into our 216262306a36Sopenharmony_ci * bookkeeping so that we have a current list of all the recipes that are 216362306a36Sopenharmony_ci * programmed in the firmware. 216462306a36Sopenharmony_ci */ 216562306a36Sopenharmony_cistatic int 216662306a36Sopenharmony_ciice_get_recp_frm_fw(struct ice_hw *hw, struct ice_sw_recipe *recps, u8 rid, 216762306a36Sopenharmony_ci bool *refresh_required) 216862306a36Sopenharmony_ci{ 216962306a36Sopenharmony_ci DECLARE_BITMAP(result_bm, ICE_MAX_FV_WORDS); 217062306a36Sopenharmony_ci struct ice_aqc_recipe_data_elem *tmp; 217162306a36Sopenharmony_ci u16 num_recps = ICE_MAX_NUM_RECIPES; 217262306a36Sopenharmony_ci struct ice_prot_lkup_ext *lkup_exts; 217362306a36Sopenharmony_ci u8 fv_word_idx = 0; 217462306a36Sopenharmony_ci u16 sub_recps; 217562306a36Sopenharmony_ci int status; 217662306a36Sopenharmony_ci 217762306a36Sopenharmony_ci bitmap_zero(result_bm, ICE_MAX_FV_WORDS); 217862306a36Sopenharmony_ci 217962306a36Sopenharmony_ci /* we need a buffer big enough to accommodate all the recipes */ 218062306a36Sopenharmony_ci tmp = kcalloc(ICE_MAX_NUM_RECIPES, sizeof(*tmp), GFP_KERNEL); 218162306a36Sopenharmony_ci if (!tmp) 218262306a36Sopenharmony_ci return -ENOMEM; 218362306a36Sopenharmony_ci 218462306a36Sopenharmony_ci tmp[0].recipe_indx = rid; 218562306a36Sopenharmony_ci status = ice_aq_get_recipe(hw, tmp, &num_recps, rid, NULL); 218662306a36Sopenharmony_ci /* non-zero status meaning recipe doesn't exist */ 218762306a36Sopenharmony_ci if (status) 218862306a36Sopenharmony_ci goto err_unroll; 218962306a36Sopenharmony_ci 219062306a36Sopenharmony_ci /* Get recipe to profile map so that we can get the fv from lkups that 219162306a36Sopenharmony_ci * we read for a recipe from FW. Since we want to minimize the number of 219262306a36Sopenharmony_ci * times we make this FW call, just make one call and cache the copy 219362306a36Sopenharmony_ci * until a new recipe is added. This operation is only required the 219462306a36Sopenharmony_ci * first time to get the changes from FW. Then to search existing 219562306a36Sopenharmony_ci * entries we don't need to update the cache again until another recipe 219662306a36Sopenharmony_ci * gets added. 219762306a36Sopenharmony_ci */ 219862306a36Sopenharmony_ci if (*refresh_required) { 219962306a36Sopenharmony_ci ice_get_recp_to_prof_map(hw); 220062306a36Sopenharmony_ci *refresh_required = false; 220162306a36Sopenharmony_ci } 220262306a36Sopenharmony_ci 220362306a36Sopenharmony_ci /* Start populating all the entries for recps[rid] based on lkups from 220462306a36Sopenharmony_ci * firmware. Note that we are only creating the root recipe in our 220562306a36Sopenharmony_ci * database. 220662306a36Sopenharmony_ci */ 220762306a36Sopenharmony_ci lkup_exts = &recps[rid].lkup_exts; 220862306a36Sopenharmony_ci 220962306a36Sopenharmony_ci for (sub_recps = 0; sub_recps < num_recps; sub_recps++) { 221062306a36Sopenharmony_ci struct ice_aqc_recipe_data_elem root_bufs = tmp[sub_recps]; 221162306a36Sopenharmony_ci struct ice_recp_grp_entry *rg_entry; 221262306a36Sopenharmony_ci u8 i, prof, idx, prot = 0; 221362306a36Sopenharmony_ci bool is_root; 221462306a36Sopenharmony_ci u16 off = 0; 221562306a36Sopenharmony_ci 221662306a36Sopenharmony_ci rg_entry = devm_kzalloc(ice_hw_to_dev(hw), sizeof(*rg_entry), 221762306a36Sopenharmony_ci GFP_KERNEL); 221862306a36Sopenharmony_ci if (!rg_entry) { 221962306a36Sopenharmony_ci status = -ENOMEM; 222062306a36Sopenharmony_ci goto err_unroll; 222162306a36Sopenharmony_ci } 222262306a36Sopenharmony_ci 222362306a36Sopenharmony_ci idx = root_bufs.recipe_indx; 222462306a36Sopenharmony_ci is_root = root_bufs.content.rid & ICE_AQ_RECIPE_ID_IS_ROOT; 222562306a36Sopenharmony_ci 222662306a36Sopenharmony_ci /* Mark all result indices in this chain */ 222762306a36Sopenharmony_ci if (root_bufs.content.result_indx & ICE_AQ_RECIPE_RESULT_EN) 222862306a36Sopenharmony_ci set_bit(root_bufs.content.result_indx & ~ICE_AQ_RECIPE_RESULT_EN, 222962306a36Sopenharmony_ci result_bm); 223062306a36Sopenharmony_ci 223162306a36Sopenharmony_ci /* get the first profile that is associated with rid */ 223262306a36Sopenharmony_ci prof = find_first_bit(recipe_to_profile[idx], 223362306a36Sopenharmony_ci ICE_MAX_NUM_PROFILES); 223462306a36Sopenharmony_ci for (i = 0; i < ICE_NUM_WORDS_RECIPE; i++) { 223562306a36Sopenharmony_ci u8 lkup_indx = root_bufs.content.lkup_indx[i + 1]; 223662306a36Sopenharmony_ci 223762306a36Sopenharmony_ci rg_entry->fv_idx[i] = lkup_indx; 223862306a36Sopenharmony_ci rg_entry->fv_mask[i] = 223962306a36Sopenharmony_ci le16_to_cpu(root_bufs.content.mask[i + 1]); 224062306a36Sopenharmony_ci 224162306a36Sopenharmony_ci /* If the recipe is a chained recipe then all its 224262306a36Sopenharmony_ci * child recipe's result will have a result index. 224362306a36Sopenharmony_ci * To fill fv_words we should not use those result 224462306a36Sopenharmony_ci * index, we only need the protocol ids and offsets. 224562306a36Sopenharmony_ci * We will skip all the fv_idx which stores result 224662306a36Sopenharmony_ci * index in them. We also need to skip any fv_idx which 224762306a36Sopenharmony_ci * has ICE_AQ_RECIPE_LKUP_IGNORE or 0 since it isn't a 224862306a36Sopenharmony_ci * valid offset value. 224962306a36Sopenharmony_ci */ 225062306a36Sopenharmony_ci if (test_bit(rg_entry->fv_idx[i], hw->switch_info->prof_res_bm[prof]) || 225162306a36Sopenharmony_ci rg_entry->fv_idx[i] & ICE_AQ_RECIPE_LKUP_IGNORE || 225262306a36Sopenharmony_ci rg_entry->fv_idx[i] == 0) 225362306a36Sopenharmony_ci continue; 225462306a36Sopenharmony_ci 225562306a36Sopenharmony_ci ice_find_prot_off(hw, ICE_BLK_SW, prof, 225662306a36Sopenharmony_ci rg_entry->fv_idx[i], &prot, &off); 225762306a36Sopenharmony_ci lkup_exts->fv_words[fv_word_idx].prot_id = prot; 225862306a36Sopenharmony_ci lkup_exts->fv_words[fv_word_idx].off = off; 225962306a36Sopenharmony_ci lkup_exts->field_mask[fv_word_idx] = 226062306a36Sopenharmony_ci rg_entry->fv_mask[i]; 226162306a36Sopenharmony_ci fv_word_idx++; 226262306a36Sopenharmony_ci } 226362306a36Sopenharmony_ci /* populate rg_list with the data from the child entry of this 226462306a36Sopenharmony_ci * recipe 226562306a36Sopenharmony_ci */ 226662306a36Sopenharmony_ci list_add(&rg_entry->l_entry, &recps[rid].rg_list); 226762306a36Sopenharmony_ci 226862306a36Sopenharmony_ci /* Propagate some data to the recipe database */ 226962306a36Sopenharmony_ci recps[idx].is_root = !!is_root; 227062306a36Sopenharmony_ci recps[idx].priority = root_bufs.content.act_ctrl_fwd_priority; 227162306a36Sopenharmony_ci recps[idx].need_pass_l2 = root_bufs.content.act_ctrl & 227262306a36Sopenharmony_ci ICE_AQ_RECIPE_ACT_NEED_PASS_L2; 227362306a36Sopenharmony_ci recps[idx].allow_pass_l2 = root_bufs.content.act_ctrl & 227462306a36Sopenharmony_ci ICE_AQ_RECIPE_ACT_ALLOW_PASS_L2; 227562306a36Sopenharmony_ci bitmap_zero(recps[idx].res_idxs, ICE_MAX_FV_WORDS); 227662306a36Sopenharmony_ci if (root_bufs.content.result_indx & ICE_AQ_RECIPE_RESULT_EN) { 227762306a36Sopenharmony_ci recps[idx].chain_idx = root_bufs.content.result_indx & 227862306a36Sopenharmony_ci ~ICE_AQ_RECIPE_RESULT_EN; 227962306a36Sopenharmony_ci set_bit(recps[idx].chain_idx, recps[idx].res_idxs); 228062306a36Sopenharmony_ci } else { 228162306a36Sopenharmony_ci recps[idx].chain_idx = ICE_INVAL_CHAIN_IND; 228262306a36Sopenharmony_ci } 228362306a36Sopenharmony_ci 228462306a36Sopenharmony_ci if (!is_root) 228562306a36Sopenharmony_ci continue; 228662306a36Sopenharmony_ci 228762306a36Sopenharmony_ci /* Only do the following for root recipes entries */ 228862306a36Sopenharmony_ci memcpy(recps[idx].r_bitmap, root_bufs.recipe_bitmap, 228962306a36Sopenharmony_ci sizeof(recps[idx].r_bitmap)); 229062306a36Sopenharmony_ci recps[idx].root_rid = root_bufs.content.rid & 229162306a36Sopenharmony_ci ~ICE_AQ_RECIPE_ID_IS_ROOT; 229262306a36Sopenharmony_ci recps[idx].priority = root_bufs.content.act_ctrl_fwd_priority; 229362306a36Sopenharmony_ci } 229462306a36Sopenharmony_ci 229562306a36Sopenharmony_ci /* Complete initialization of the root recipe entry */ 229662306a36Sopenharmony_ci lkup_exts->n_val_words = fv_word_idx; 229762306a36Sopenharmony_ci recps[rid].big_recp = (num_recps > 1); 229862306a36Sopenharmony_ci recps[rid].n_grp_count = (u8)num_recps; 229962306a36Sopenharmony_ci recps[rid].root_buf = devm_kmemdup(ice_hw_to_dev(hw), tmp, 230062306a36Sopenharmony_ci recps[rid].n_grp_count * sizeof(*recps[rid].root_buf), 230162306a36Sopenharmony_ci GFP_KERNEL); 230262306a36Sopenharmony_ci if (!recps[rid].root_buf) { 230362306a36Sopenharmony_ci status = -ENOMEM; 230462306a36Sopenharmony_ci goto err_unroll; 230562306a36Sopenharmony_ci } 230662306a36Sopenharmony_ci 230762306a36Sopenharmony_ci /* Copy result indexes */ 230862306a36Sopenharmony_ci bitmap_copy(recps[rid].res_idxs, result_bm, ICE_MAX_FV_WORDS); 230962306a36Sopenharmony_ci recps[rid].recp_created = true; 231062306a36Sopenharmony_ci 231162306a36Sopenharmony_cierr_unroll: 231262306a36Sopenharmony_ci kfree(tmp); 231362306a36Sopenharmony_ci return status; 231462306a36Sopenharmony_ci} 231562306a36Sopenharmony_ci 231662306a36Sopenharmony_ci/* ice_init_port_info - Initialize port_info with switch configuration data 231762306a36Sopenharmony_ci * @pi: pointer to port_info 231862306a36Sopenharmony_ci * @vsi_port_num: VSI number or port number 231962306a36Sopenharmony_ci * @type: Type of switch element (port or VSI) 232062306a36Sopenharmony_ci * @swid: switch ID of the switch the element is attached to 232162306a36Sopenharmony_ci * @pf_vf_num: PF or VF number 232262306a36Sopenharmony_ci * @is_vf: true if the element is a VF, false otherwise 232362306a36Sopenharmony_ci */ 232462306a36Sopenharmony_cistatic void 232562306a36Sopenharmony_ciice_init_port_info(struct ice_port_info *pi, u16 vsi_port_num, u8 type, 232662306a36Sopenharmony_ci u16 swid, u16 pf_vf_num, bool is_vf) 232762306a36Sopenharmony_ci{ 232862306a36Sopenharmony_ci switch (type) { 232962306a36Sopenharmony_ci case ICE_AQC_GET_SW_CONF_RESP_PHYS_PORT: 233062306a36Sopenharmony_ci pi->lport = (u8)(vsi_port_num & ICE_LPORT_MASK); 233162306a36Sopenharmony_ci pi->sw_id = swid; 233262306a36Sopenharmony_ci pi->pf_vf_num = pf_vf_num; 233362306a36Sopenharmony_ci pi->is_vf = is_vf; 233462306a36Sopenharmony_ci break; 233562306a36Sopenharmony_ci default: 233662306a36Sopenharmony_ci ice_debug(pi->hw, ICE_DBG_SW, "incorrect VSI/port type received\n"); 233762306a36Sopenharmony_ci break; 233862306a36Sopenharmony_ci } 233962306a36Sopenharmony_ci} 234062306a36Sopenharmony_ci 234162306a36Sopenharmony_ci/* ice_get_initial_sw_cfg - Get initial port and default VSI data 234262306a36Sopenharmony_ci * @hw: pointer to the hardware structure 234362306a36Sopenharmony_ci */ 234462306a36Sopenharmony_ciint ice_get_initial_sw_cfg(struct ice_hw *hw) 234562306a36Sopenharmony_ci{ 234662306a36Sopenharmony_ci struct ice_aqc_get_sw_cfg_resp_elem *rbuf; 234762306a36Sopenharmony_ci u16 req_desc = 0; 234862306a36Sopenharmony_ci u16 num_elems; 234962306a36Sopenharmony_ci int status; 235062306a36Sopenharmony_ci u16 i; 235162306a36Sopenharmony_ci 235262306a36Sopenharmony_ci rbuf = kzalloc(ICE_SW_CFG_MAX_BUF_LEN, GFP_KERNEL); 235362306a36Sopenharmony_ci if (!rbuf) 235462306a36Sopenharmony_ci return -ENOMEM; 235562306a36Sopenharmony_ci 235662306a36Sopenharmony_ci /* Multiple calls to ice_aq_get_sw_cfg may be required 235762306a36Sopenharmony_ci * to get all the switch configuration information. The need 235862306a36Sopenharmony_ci * for additional calls is indicated by ice_aq_get_sw_cfg 235962306a36Sopenharmony_ci * writing a non-zero value in req_desc 236062306a36Sopenharmony_ci */ 236162306a36Sopenharmony_ci do { 236262306a36Sopenharmony_ci struct ice_aqc_get_sw_cfg_resp_elem *ele; 236362306a36Sopenharmony_ci 236462306a36Sopenharmony_ci status = ice_aq_get_sw_cfg(hw, rbuf, ICE_SW_CFG_MAX_BUF_LEN, 236562306a36Sopenharmony_ci &req_desc, &num_elems, NULL); 236662306a36Sopenharmony_ci 236762306a36Sopenharmony_ci if (status) 236862306a36Sopenharmony_ci break; 236962306a36Sopenharmony_ci 237062306a36Sopenharmony_ci for (i = 0, ele = rbuf; i < num_elems; i++, ele++) { 237162306a36Sopenharmony_ci u16 pf_vf_num, swid, vsi_port_num; 237262306a36Sopenharmony_ci bool is_vf = false; 237362306a36Sopenharmony_ci u8 res_type; 237462306a36Sopenharmony_ci 237562306a36Sopenharmony_ci vsi_port_num = le16_to_cpu(ele->vsi_port_num) & 237662306a36Sopenharmony_ci ICE_AQC_GET_SW_CONF_RESP_VSI_PORT_NUM_M; 237762306a36Sopenharmony_ci 237862306a36Sopenharmony_ci pf_vf_num = le16_to_cpu(ele->pf_vf_num) & 237962306a36Sopenharmony_ci ICE_AQC_GET_SW_CONF_RESP_FUNC_NUM_M; 238062306a36Sopenharmony_ci 238162306a36Sopenharmony_ci swid = le16_to_cpu(ele->swid); 238262306a36Sopenharmony_ci 238362306a36Sopenharmony_ci if (le16_to_cpu(ele->pf_vf_num) & 238462306a36Sopenharmony_ci ICE_AQC_GET_SW_CONF_RESP_IS_VF) 238562306a36Sopenharmony_ci is_vf = true; 238662306a36Sopenharmony_ci 238762306a36Sopenharmony_ci res_type = (u8)(le16_to_cpu(ele->vsi_port_num) >> 238862306a36Sopenharmony_ci ICE_AQC_GET_SW_CONF_RESP_TYPE_S); 238962306a36Sopenharmony_ci 239062306a36Sopenharmony_ci if (res_type == ICE_AQC_GET_SW_CONF_RESP_VSI) { 239162306a36Sopenharmony_ci /* FW VSI is not needed. Just continue. */ 239262306a36Sopenharmony_ci continue; 239362306a36Sopenharmony_ci } 239462306a36Sopenharmony_ci 239562306a36Sopenharmony_ci ice_init_port_info(hw->port_info, vsi_port_num, 239662306a36Sopenharmony_ci res_type, swid, pf_vf_num, is_vf); 239762306a36Sopenharmony_ci } 239862306a36Sopenharmony_ci } while (req_desc && !status); 239962306a36Sopenharmony_ci 240062306a36Sopenharmony_ci kfree(rbuf); 240162306a36Sopenharmony_ci return status; 240262306a36Sopenharmony_ci} 240362306a36Sopenharmony_ci 240462306a36Sopenharmony_ci/** 240562306a36Sopenharmony_ci * ice_fill_sw_info - Helper function to populate lb_en and lan_en 240662306a36Sopenharmony_ci * @hw: pointer to the hardware structure 240762306a36Sopenharmony_ci * @fi: filter info structure to fill/update 240862306a36Sopenharmony_ci * 240962306a36Sopenharmony_ci * This helper function populates the lb_en and lan_en elements of the provided 241062306a36Sopenharmony_ci * ice_fltr_info struct using the switch's type and characteristics of the 241162306a36Sopenharmony_ci * switch rule being configured. 241262306a36Sopenharmony_ci */ 241362306a36Sopenharmony_cistatic void ice_fill_sw_info(struct ice_hw *hw, struct ice_fltr_info *fi) 241462306a36Sopenharmony_ci{ 241562306a36Sopenharmony_ci fi->lb_en = false; 241662306a36Sopenharmony_ci fi->lan_en = false; 241762306a36Sopenharmony_ci if ((fi->flag & ICE_FLTR_TX) && 241862306a36Sopenharmony_ci (fi->fltr_act == ICE_FWD_TO_VSI || 241962306a36Sopenharmony_ci fi->fltr_act == ICE_FWD_TO_VSI_LIST || 242062306a36Sopenharmony_ci fi->fltr_act == ICE_FWD_TO_Q || 242162306a36Sopenharmony_ci fi->fltr_act == ICE_FWD_TO_QGRP)) { 242262306a36Sopenharmony_ci /* Setting LB for prune actions will result in replicated 242362306a36Sopenharmony_ci * packets to the internal switch that will be dropped. 242462306a36Sopenharmony_ci */ 242562306a36Sopenharmony_ci if (fi->lkup_type != ICE_SW_LKUP_VLAN) 242662306a36Sopenharmony_ci fi->lb_en = true; 242762306a36Sopenharmony_ci 242862306a36Sopenharmony_ci /* Set lan_en to TRUE if 242962306a36Sopenharmony_ci * 1. The switch is a VEB AND 243062306a36Sopenharmony_ci * 2 243162306a36Sopenharmony_ci * 2.1 The lookup is a directional lookup like ethertype, 243262306a36Sopenharmony_ci * promiscuous, ethertype-MAC, promiscuous-VLAN 243362306a36Sopenharmony_ci * and default-port OR 243462306a36Sopenharmony_ci * 2.2 The lookup is VLAN, OR 243562306a36Sopenharmony_ci * 2.3 The lookup is MAC with mcast or bcast addr for MAC, OR 243662306a36Sopenharmony_ci * 2.4 The lookup is MAC_VLAN with mcast or bcast addr for MAC. 243762306a36Sopenharmony_ci * 243862306a36Sopenharmony_ci * OR 243962306a36Sopenharmony_ci * 244062306a36Sopenharmony_ci * The switch is a VEPA. 244162306a36Sopenharmony_ci * 244262306a36Sopenharmony_ci * In all other cases, the LAN enable has to be set to false. 244362306a36Sopenharmony_ci */ 244462306a36Sopenharmony_ci if (hw->evb_veb) { 244562306a36Sopenharmony_ci if (fi->lkup_type == ICE_SW_LKUP_ETHERTYPE || 244662306a36Sopenharmony_ci fi->lkup_type == ICE_SW_LKUP_PROMISC || 244762306a36Sopenharmony_ci fi->lkup_type == ICE_SW_LKUP_ETHERTYPE_MAC || 244862306a36Sopenharmony_ci fi->lkup_type == ICE_SW_LKUP_PROMISC_VLAN || 244962306a36Sopenharmony_ci fi->lkup_type == ICE_SW_LKUP_DFLT || 245062306a36Sopenharmony_ci fi->lkup_type == ICE_SW_LKUP_VLAN || 245162306a36Sopenharmony_ci (fi->lkup_type == ICE_SW_LKUP_MAC && 245262306a36Sopenharmony_ci !is_unicast_ether_addr(fi->l_data.mac.mac_addr)) || 245362306a36Sopenharmony_ci (fi->lkup_type == ICE_SW_LKUP_MAC_VLAN && 245462306a36Sopenharmony_ci !is_unicast_ether_addr(fi->l_data.mac.mac_addr))) 245562306a36Sopenharmony_ci fi->lan_en = true; 245662306a36Sopenharmony_ci } else { 245762306a36Sopenharmony_ci fi->lan_en = true; 245862306a36Sopenharmony_ci } 245962306a36Sopenharmony_ci } 246062306a36Sopenharmony_ci} 246162306a36Sopenharmony_ci 246262306a36Sopenharmony_ci/** 246362306a36Sopenharmony_ci * ice_fill_eth_hdr - helper to copy dummy_eth_hdr into supplied buffer 246462306a36Sopenharmony_ci * @eth_hdr: pointer to buffer to populate 246562306a36Sopenharmony_ci */ 246662306a36Sopenharmony_civoid ice_fill_eth_hdr(u8 *eth_hdr) 246762306a36Sopenharmony_ci{ 246862306a36Sopenharmony_ci memcpy(eth_hdr, dummy_eth_header, DUMMY_ETH_HDR_LEN); 246962306a36Sopenharmony_ci} 247062306a36Sopenharmony_ci 247162306a36Sopenharmony_ci/** 247262306a36Sopenharmony_ci * ice_fill_sw_rule - Helper function to fill switch rule structure 247362306a36Sopenharmony_ci * @hw: pointer to the hardware structure 247462306a36Sopenharmony_ci * @f_info: entry containing packet forwarding information 247562306a36Sopenharmony_ci * @s_rule: switch rule structure to be filled in based on mac_entry 247662306a36Sopenharmony_ci * @opc: switch rules population command type - pass in the command opcode 247762306a36Sopenharmony_ci */ 247862306a36Sopenharmony_cistatic void 247962306a36Sopenharmony_ciice_fill_sw_rule(struct ice_hw *hw, struct ice_fltr_info *f_info, 248062306a36Sopenharmony_ci struct ice_sw_rule_lkup_rx_tx *s_rule, 248162306a36Sopenharmony_ci enum ice_adminq_opc opc) 248262306a36Sopenharmony_ci{ 248362306a36Sopenharmony_ci u16 vlan_id = ICE_MAX_VLAN_ID + 1; 248462306a36Sopenharmony_ci u16 vlan_tpid = ETH_P_8021Q; 248562306a36Sopenharmony_ci void *daddr = NULL; 248662306a36Sopenharmony_ci u16 eth_hdr_sz; 248762306a36Sopenharmony_ci u8 *eth_hdr; 248862306a36Sopenharmony_ci u32 act = 0; 248962306a36Sopenharmony_ci __be16 *off; 249062306a36Sopenharmony_ci u8 q_rgn; 249162306a36Sopenharmony_ci 249262306a36Sopenharmony_ci if (opc == ice_aqc_opc_remove_sw_rules) { 249362306a36Sopenharmony_ci s_rule->act = 0; 249462306a36Sopenharmony_ci s_rule->index = cpu_to_le16(f_info->fltr_rule_id); 249562306a36Sopenharmony_ci s_rule->hdr_len = 0; 249662306a36Sopenharmony_ci return; 249762306a36Sopenharmony_ci } 249862306a36Sopenharmony_ci 249962306a36Sopenharmony_ci eth_hdr_sz = sizeof(dummy_eth_header); 250062306a36Sopenharmony_ci eth_hdr = s_rule->hdr_data; 250162306a36Sopenharmony_ci 250262306a36Sopenharmony_ci /* initialize the ether header with a dummy header */ 250362306a36Sopenharmony_ci memcpy(eth_hdr, dummy_eth_header, eth_hdr_sz); 250462306a36Sopenharmony_ci ice_fill_sw_info(hw, f_info); 250562306a36Sopenharmony_ci 250662306a36Sopenharmony_ci switch (f_info->fltr_act) { 250762306a36Sopenharmony_ci case ICE_FWD_TO_VSI: 250862306a36Sopenharmony_ci act |= (f_info->fwd_id.hw_vsi_id << ICE_SINGLE_ACT_VSI_ID_S) & 250962306a36Sopenharmony_ci ICE_SINGLE_ACT_VSI_ID_M; 251062306a36Sopenharmony_ci if (f_info->lkup_type != ICE_SW_LKUP_VLAN) 251162306a36Sopenharmony_ci act |= ICE_SINGLE_ACT_VSI_FORWARDING | 251262306a36Sopenharmony_ci ICE_SINGLE_ACT_VALID_BIT; 251362306a36Sopenharmony_ci break; 251462306a36Sopenharmony_ci case ICE_FWD_TO_VSI_LIST: 251562306a36Sopenharmony_ci act |= ICE_SINGLE_ACT_VSI_LIST; 251662306a36Sopenharmony_ci act |= (f_info->fwd_id.vsi_list_id << 251762306a36Sopenharmony_ci ICE_SINGLE_ACT_VSI_LIST_ID_S) & 251862306a36Sopenharmony_ci ICE_SINGLE_ACT_VSI_LIST_ID_M; 251962306a36Sopenharmony_ci if (f_info->lkup_type != ICE_SW_LKUP_VLAN) 252062306a36Sopenharmony_ci act |= ICE_SINGLE_ACT_VSI_FORWARDING | 252162306a36Sopenharmony_ci ICE_SINGLE_ACT_VALID_BIT; 252262306a36Sopenharmony_ci break; 252362306a36Sopenharmony_ci case ICE_FWD_TO_Q: 252462306a36Sopenharmony_ci act |= ICE_SINGLE_ACT_TO_Q; 252562306a36Sopenharmony_ci act |= (f_info->fwd_id.q_id << ICE_SINGLE_ACT_Q_INDEX_S) & 252662306a36Sopenharmony_ci ICE_SINGLE_ACT_Q_INDEX_M; 252762306a36Sopenharmony_ci break; 252862306a36Sopenharmony_ci case ICE_DROP_PACKET: 252962306a36Sopenharmony_ci act |= ICE_SINGLE_ACT_VSI_FORWARDING | ICE_SINGLE_ACT_DROP | 253062306a36Sopenharmony_ci ICE_SINGLE_ACT_VALID_BIT; 253162306a36Sopenharmony_ci break; 253262306a36Sopenharmony_ci case ICE_FWD_TO_QGRP: 253362306a36Sopenharmony_ci q_rgn = f_info->qgrp_size > 0 ? 253462306a36Sopenharmony_ci (u8)ilog2(f_info->qgrp_size) : 0; 253562306a36Sopenharmony_ci act |= ICE_SINGLE_ACT_TO_Q; 253662306a36Sopenharmony_ci act |= (f_info->fwd_id.q_id << ICE_SINGLE_ACT_Q_INDEX_S) & 253762306a36Sopenharmony_ci ICE_SINGLE_ACT_Q_INDEX_M; 253862306a36Sopenharmony_ci act |= (q_rgn << ICE_SINGLE_ACT_Q_REGION_S) & 253962306a36Sopenharmony_ci ICE_SINGLE_ACT_Q_REGION_M; 254062306a36Sopenharmony_ci break; 254162306a36Sopenharmony_ci default: 254262306a36Sopenharmony_ci return; 254362306a36Sopenharmony_ci } 254462306a36Sopenharmony_ci 254562306a36Sopenharmony_ci if (f_info->lb_en) 254662306a36Sopenharmony_ci act |= ICE_SINGLE_ACT_LB_ENABLE; 254762306a36Sopenharmony_ci if (f_info->lan_en) 254862306a36Sopenharmony_ci act |= ICE_SINGLE_ACT_LAN_ENABLE; 254962306a36Sopenharmony_ci 255062306a36Sopenharmony_ci switch (f_info->lkup_type) { 255162306a36Sopenharmony_ci case ICE_SW_LKUP_MAC: 255262306a36Sopenharmony_ci daddr = f_info->l_data.mac.mac_addr; 255362306a36Sopenharmony_ci break; 255462306a36Sopenharmony_ci case ICE_SW_LKUP_VLAN: 255562306a36Sopenharmony_ci vlan_id = f_info->l_data.vlan.vlan_id; 255662306a36Sopenharmony_ci if (f_info->l_data.vlan.tpid_valid) 255762306a36Sopenharmony_ci vlan_tpid = f_info->l_data.vlan.tpid; 255862306a36Sopenharmony_ci if (f_info->fltr_act == ICE_FWD_TO_VSI || 255962306a36Sopenharmony_ci f_info->fltr_act == ICE_FWD_TO_VSI_LIST) { 256062306a36Sopenharmony_ci act |= ICE_SINGLE_ACT_PRUNE; 256162306a36Sopenharmony_ci act |= ICE_SINGLE_ACT_EGRESS | ICE_SINGLE_ACT_INGRESS; 256262306a36Sopenharmony_ci } 256362306a36Sopenharmony_ci break; 256462306a36Sopenharmony_ci case ICE_SW_LKUP_ETHERTYPE_MAC: 256562306a36Sopenharmony_ci daddr = f_info->l_data.ethertype_mac.mac_addr; 256662306a36Sopenharmony_ci fallthrough; 256762306a36Sopenharmony_ci case ICE_SW_LKUP_ETHERTYPE: 256862306a36Sopenharmony_ci off = (__force __be16 *)(eth_hdr + ICE_ETH_ETHTYPE_OFFSET); 256962306a36Sopenharmony_ci *off = cpu_to_be16(f_info->l_data.ethertype_mac.ethertype); 257062306a36Sopenharmony_ci break; 257162306a36Sopenharmony_ci case ICE_SW_LKUP_MAC_VLAN: 257262306a36Sopenharmony_ci daddr = f_info->l_data.mac_vlan.mac_addr; 257362306a36Sopenharmony_ci vlan_id = f_info->l_data.mac_vlan.vlan_id; 257462306a36Sopenharmony_ci break; 257562306a36Sopenharmony_ci case ICE_SW_LKUP_PROMISC_VLAN: 257662306a36Sopenharmony_ci vlan_id = f_info->l_data.mac_vlan.vlan_id; 257762306a36Sopenharmony_ci fallthrough; 257862306a36Sopenharmony_ci case ICE_SW_LKUP_PROMISC: 257962306a36Sopenharmony_ci daddr = f_info->l_data.mac_vlan.mac_addr; 258062306a36Sopenharmony_ci break; 258162306a36Sopenharmony_ci default: 258262306a36Sopenharmony_ci break; 258362306a36Sopenharmony_ci } 258462306a36Sopenharmony_ci 258562306a36Sopenharmony_ci s_rule->hdr.type = (f_info->flag & ICE_FLTR_RX) ? 258662306a36Sopenharmony_ci cpu_to_le16(ICE_AQC_SW_RULES_T_LKUP_RX) : 258762306a36Sopenharmony_ci cpu_to_le16(ICE_AQC_SW_RULES_T_LKUP_TX); 258862306a36Sopenharmony_ci 258962306a36Sopenharmony_ci /* Recipe set depending on lookup type */ 259062306a36Sopenharmony_ci s_rule->recipe_id = cpu_to_le16(f_info->lkup_type); 259162306a36Sopenharmony_ci s_rule->src = cpu_to_le16(f_info->src); 259262306a36Sopenharmony_ci s_rule->act = cpu_to_le32(act); 259362306a36Sopenharmony_ci 259462306a36Sopenharmony_ci if (daddr) 259562306a36Sopenharmony_ci ether_addr_copy(eth_hdr + ICE_ETH_DA_OFFSET, daddr); 259662306a36Sopenharmony_ci 259762306a36Sopenharmony_ci if (!(vlan_id > ICE_MAX_VLAN_ID)) { 259862306a36Sopenharmony_ci off = (__force __be16 *)(eth_hdr + ICE_ETH_VLAN_TCI_OFFSET); 259962306a36Sopenharmony_ci *off = cpu_to_be16(vlan_id); 260062306a36Sopenharmony_ci off = (__force __be16 *)(eth_hdr + ICE_ETH_ETHTYPE_OFFSET); 260162306a36Sopenharmony_ci *off = cpu_to_be16(vlan_tpid); 260262306a36Sopenharmony_ci } 260362306a36Sopenharmony_ci 260462306a36Sopenharmony_ci /* Create the switch rule with the final dummy Ethernet header */ 260562306a36Sopenharmony_ci if (opc != ice_aqc_opc_update_sw_rules) 260662306a36Sopenharmony_ci s_rule->hdr_len = cpu_to_le16(eth_hdr_sz); 260762306a36Sopenharmony_ci} 260862306a36Sopenharmony_ci 260962306a36Sopenharmony_ci/** 261062306a36Sopenharmony_ci * ice_add_marker_act 261162306a36Sopenharmony_ci * @hw: pointer to the hardware structure 261262306a36Sopenharmony_ci * @m_ent: the management entry for which sw marker needs to be added 261362306a36Sopenharmony_ci * @sw_marker: sw marker to tag the Rx descriptor with 261462306a36Sopenharmony_ci * @l_id: large action resource ID 261562306a36Sopenharmony_ci * 261662306a36Sopenharmony_ci * Create a large action to hold software marker and update the switch rule 261762306a36Sopenharmony_ci * entry pointed by m_ent with newly created large action 261862306a36Sopenharmony_ci */ 261962306a36Sopenharmony_cistatic int 262062306a36Sopenharmony_ciice_add_marker_act(struct ice_hw *hw, struct ice_fltr_mgmt_list_entry *m_ent, 262162306a36Sopenharmony_ci u16 sw_marker, u16 l_id) 262262306a36Sopenharmony_ci{ 262362306a36Sopenharmony_ci struct ice_sw_rule_lkup_rx_tx *rx_tx; 262462306a36Sopenharmony_ci struct ice_sw_rule_lg_act *lg_act; 262562306a36Sopenharmony_ci /* For software marker we need 3 large actions 262662306a36Sopenharmony_ci * 1. FWD action: FWD TO VSI or VSI LIST 262762306a36Sopenharmony_ci * 2. GENERIC VALUE action to hold the profile ID 262862306a36Sopenharmony_ci * 3. GENERIC VALUE action to hold the software marker ID 262962306a36Sopenharmony_ci */ 263062306a36Sopenharmony_ci const u16 num_lg_acts = 3; 263162306a36Sopenharmony_ci u16 lg_act_size; 263262306a36Sopenharmony_ci u16 rules_size; 263362306a36Sopenharmony_ci int status; 263462306a36Sopenharmony_ci u32 act; 263562306a36Sopenharmony_ci u16 id; 263662306a36Sopenharmony_ci 263762306a36Sopenharmony_ci if (m_ent->fltr_info.lkup_type != ICE_SW_LKUP_MAC) 263862306a36Sopenharmony_ci return -EINVAL; 263962306a36Sopenharmony_ci 264062306a36Sopenharmony_ci /* Create two back-to-back switch rules and submit them to the HW using 264162306a36Sopenharmony_ci * one memory buffer: 264262306a36Sopenharmony_ci * 1. Large Action 264362306a36Sopenharmony_ci * 2. Look up Tx Rx 264462306a36Sopenharmony_ci */ 264562306a36Sopenharmony_ci lg_act_size = (u16)ICE_SW_RULE_LG_ACT_SIZE(lg_act, num_lg_acts); 264662306a36Sopenharmony_ci rules_size = lg_act_size + ICE_SW_RULE_RX_TX_ETH_HDR_SIZE(rx_tx); 264762306a36Sopenharmony_ci lg_act = devm_kzalloc(ice_hw_to_dev(hw), rules_size, GFP_KERNEL); 264862306a36Sopenharmony_ci if (!lg_act) 264962306a36Sopenharmony_ci return -ENOMEM; 265062306a36Sopenharmony_ci 265162306a36Sopenharmony_ci rx_tx = (typeof(rx_tx))((u8 *)lg_act + lg_act_size); 265262306a36Sopenharmony_ci 265362306a36Sopenharmony_ci /* Fill in the first switch rule i.e. large action */ 265462306a36Sopenharmony_ci lg_act->hdr.type = cpu_to_le16(ICE_AQC_SW_RULES_T_LG_ACT); 265562306a36Sopenharmony_ci lg_act->index = cpu_to_le16(l_id); 265662306a36Sopenharmony_ci lg_act->size = cpu_to_le16(num_lg_acts); 265762306a36Sopenharmony_ci 265862306a36Sopenharmony_ci /* First action VSI forwarding or VSI list forwarding depending on how 265962306a36Sopenharmony_ci * many VSIs 266062306a36Sopenharmony_ci */ 266162306a36Sopenharmony_ci id = (m_ent->vsi_count > 1) ? m_ent->fltr_info.fwd_id.vsi_list_id : 266262306a36Sopenharmony_ci m_ent->fltr_info.fwd_id.hw_vsi_id; 266362306a36Sopenharmony_ci 266462306a36Sopenharmony_ci act = ICE_LG_ACT_VSI_FORWARDING | ICE_LG_ACT_VALID_BIT; 266562306a36Sopenharmony_ci act |= (id << ICE_LG_ACT_VSI_LIST_ID_S) & ICE_LG_ACT_VSI_LIST_ID_M; 266662306a36Sopenharmony_ci if (m_ent->vsi_count > 1) 266762306a36Sopenharmony_ci act |= ICE_LG_ACT_VSI_LIST; 266862306a36Sopenharmony_ci lg_act->act[0] = cpu_to_le32(act); 266962306a36Sopenharmony_ci 267062306a36Sopenharmony_ci /* Second action descriptor type */ 267162306a36Sopenharmony_ci act = ICE_LG_ACT_GENERIC; 267262306a36Sopenharmony_ci 267362306a36Sopenharmony_ci act |= (1 << ICE_LG_ACT_GENERIC_VALUE_S) & ICE_LG_ACT_GENERIC_VALUE_M; 267462306a36Sopenharmony_ci lg_act->act[1] = cpu_to_le32(act); 267562306a36Sopenharmony_ci 267662306a36Sopenharmony_ci act = (ICE_LG_ACT_GENERIC_OFF_RX_DESC_PROF_IDX << 267762306a36Sopenharmony_ci ICE_LG_ACT_GENERIC_OFFSET_S) & ICE_LG_ACT_GENERIC_OFFSET_M; 267862306a36Sopenharmony_ci 267962306a36Sopenharmony_ci /* Third action Marker value */ 268062306a36Sopenharmony_ci act |= ICE_LG_ACT_GENERIC; 268162306a36Sopenharmony_ci act |= (sw_marker << ICE_LG_ACT_GENERIC_VALUE_S) & 268262306a36Sopenharmony_ci ICE_LG_ACT_GENERIC_VALUE_M; 268362306a36Sopenharmony_ci 268462306a36Sopenharmony_ci lg_act->act[2] = cpu_to_le32(act); 268562306a36Sopenharmony_ci 268662306a36Sopenharmony_ci /* call the fill switch rule to fill the lookup Tx Rx structure */ 268762306a36Sopenharmony_ci ice_fill_sw_rule(hw, &m_ent->fltr_info, rx_tx, 268862306a36Sopenharmony_ci ice_aqc_opc_update_sw_rules); 268962306a36Sopenharmony_ci 269062306a36Sopenharmony_ci /* Update the action to point to the large action ID */ 269162306a36Sopenharmony_ci rx_tx->act = cpu_to_le32(ICE_SINGLE_ACT_PTR | 269262306a36Sopenharmony_ci ((l_id << ICE_SINGLE_ACT_PTR_VAL_S) & 269362306a36Sopenharmony_ci ICE_SINGLE_ACT_PTR_VAL_M)); 269462306a36Sopenharmony_ci 269562306a36Sopenharmony_ci /* Use the filter rule ID of the previously created rule with single 269662306a36Sopenharmony_ci * act. Once the update happens, hardware will treat this as large 269762306a36Sopenharmony_ci * action 269862306a36Sopenharmony_ci */ 269962306a36Sopenharmony_ci rx_tx->index = cpu_to_le16(m_ent->fltr_info.fltr_rule_id); 270062306a36Sopenharmony_ci 270162306a36Sopenharmony_ci status = ice_aq_sw_rules(hw, lg_act, rules_size, 2, 270262306a36Sopenharmony_ci ice_aqc_opc_update_sw_rules, NULL); 270362306a36Sopenharmony_ci if (!status) { 270462306a36Sopenharmony_ci m_ent->lg_act_idx = l_id; 270562306a36Sopenharmony_ci m_ent->sw_marker_id = sw_marker; 270662306a36Sopenharmony_ci } 270762306a36Sopenharmony_ci 270862306a36Sopenharmony_ci devm_kfree(ice_hw_to_dev(hw), lg_act); 270962306a36Sopenharmony_ci return status; 271062306a36Sopenharmony_ci} 271162306a36Sopenharmony_ci 271262306a36Sopenharmony_ci/** 271362306a36Sopenharmony_ci * ice_create_vsi_list_map 271462306a36Sopenharmony_ci * @hw: pointer to the hardware structure 271562306a36Sopenharmony_ci * @vsi_handle_arr: array of VSI handles to set in the VSI mapping 271662306a36Sopenharmony_ci * @num_vsi: number of VSI handles in the array 271762306a36Sopenharmony_ci * @vsi_list_id: VSI list ID generated as part of allocate resource 271862306a36Sopenharmony_ci * 271962306a36Sopenharmony_ci * Helper function to create a new entry of VSI list ID to VSI mapping 272062306a36Sopenharmony_ci * using the given VSI list ID 272162306a36Sopenharmony_ci */ 272262306a36Sopenharmony_cistatic struct ice_vsi_list_map_info * 272362306a36Sopenharmony_ciice_create_vsi_list_map(struct ice_hw *hw, u16 *vsi_handle_arr, u16 num_vsi, 272462306a36Sopenharmony_ci u16 vsi_list_id) 272562306a36Sopenharmony_ci{ 272662306a36Sopenharmony_ci struct ice_switch_info *sw = hw->switch_info; 272762306a36Sopenharmony_ci struct ice_vsi_list_map_info *v_map; 272862306a36Sopenharmony_ci int i; 272962306a36Sopenharmony_ci 273062306a36Sopenharmony_ci v_map = devm_kzalloc(ice_hw_to_dev(hw), sizeof(*v_map), GFP_KERNEL); 273162306a36Sopenharmony_ci if (!v_map) 273262306a36Sopenharmony_ci return NULL; 273362306a36Sopenharmony_ci 273462306a36Sopenharmony_ci v_map->vsi_list_id = vsi_list_id; 273562306a36Sopenharmony_ci v_map->ref_cnt = 1; 273662306a36Sopenharmony_ci for (i = 0; i < num_vsi; i++) 273762306a36Sopenharmony_ci set_bit(vsi_handle_arr[i], v_map->vsi_map); 273862306a36Sopenharmony_ci 273962306a36Sopenharmony_ci list_add(&v_map->list_entry, &sw->vsi_list_map_head); 274062306a36Sopenharmony_ci return v_map; 274162306a36Sopenharmony_ci} 274262306a36Sopenharmony_ci 274362306a36Sopenharmony_ci/** 274462306a36Sopenharmony_ci * ice_update_vsi_list_rule 274562306a36Sopenharmony_ci * @hw: pointer to the hardware structure 274662306a36Sopenharmony_ci * @vsi_handle_arr: array of VSI handles to form a VSI list 274762306a36Sopenharmony_ci * @num_vsi: number of VSI handles in the array 274862306a36Sopenharmony_ci * @vsi_list_id: VSI list ID generated as part of allocate resource 274962306a36Sopenharmony_ci * @remove: Boolean value to indicate if this is a remove action 275062306a36Sopenharmony_ci * @opc: switch rules population command type - pass in the command opcode 275162306a36Sopenharmony_ci * @lkup_type: lookup type of the filter 275262306a36Sopenharmony_ci * 275362306a36Sopenharmony_ci * Call AQ command to add a new switch rule or update existing switch rule 275462306a36Sopenharmony_ci * using the given VSI list ID 275562306a36Sopenharmony_ci */ 275662306a36Sopenharmony_cistatic int 275762306a36Sopenharmony_ciice_update_vsi_list_rule(struct ice_hw *hw, u16 *vsi_handle_arr, u16 num_vsi, 275862306a36Sopenharmony_ci u16 vsi_list_id, bool remove, enum ice_adminq_opc opc, 275962306a36Sopenharmony_ci enum ice_sw_lkup_type lkup_type) 276062306a36Sopenharmony_ci{ 276162306a36Sopenharmony_ci struct ice_sw_rule_vsi_list *s_rule; 276262306a36Sopenharmony_ci u16 s_rule_size; 276362306a36Sopenharmony_ci u16 rule_type; 276462306a36Sopenharmony_ci int status; 276562306a36Sopenharmony_ci int i; 276662306a36Sopenharmony_ci 276762306a36Sopenharmony_ci if (!num_vsi) 276862306a36Sopenharmony_ci return -EINVAL; 276962306a36Sopenharmony_ci 277062306a36Sopenharmony_ci if (lkup_type == ICE_SW_LKUP_MAC || 277162306a36Sopenharmony_ci lkup_type == ICE_SW_LKUP_MAC_VLAN || 277262306a36Sopenharmony_ci lkup_type == ICE_SW_LKUP_ETHERTYPE || 277362306a36Sopenharmony_ci lkup_type == ICE_SW_LKUP_ETHERTYPE_MAC || 277462306a36Sopenharmony_ci lkup_type == ICE_SW_LKUP_PROMISC || 277562306a36Sopenharmony_ci lkup_type == ICE_SW_LKUP_PROMISC_VLAN || 277662306a36Sopenharmony_ci lkup_type == ICE_SW_LKUP_DFLT) 277762306a36Sopenharmony_ci rule_type = remove ? ICE_AQC_SW_RULES_T_VSI_LIST_CLEAR : 277862306a36Sopenharmony_ci ICE_AQC_SW_RULES_T_VSI_LIST_SET; 277962306a36Sopenharmony_ci else if (lkup_type == ICE_SW_LKUP_VLAN) 278062306a36Sopenharmony_ci rule_type = remove ? ICE_AQC_SW_RULES_T_PRUNE_LIST_CLEAR : 278162306a36Sopenharmony_ci ICE_AQC_SW_RULES_T_PRUNE_LIST_SET; 278262306a36Sopenharmony_ci else 278362306a36Sopenharmony_ci return -EINVAL; 278462306a36Sopenharmony_ci 278562306a36Sopenharmony_ci s_rule_size = (u16)ICE_SW_RULE_VSI_LIST_SIZE(s_rule, num_vsi); 278662306a36Sopenharmony_ci s_rule = devm_kzalloc(ice_hw_to_dev(hw), s_rule_size, GFP_KERNEL); 278762306a36Sopenharmony_ci if (!s_rule) 278862306a36Sopenharmony_ci return -ENOMEM; 278962306a36Sopenharmony_ci for (i = 0; i < num_vsi; i++) { 279062306a36Sopenharmony_ci if (!ice_is_vsi_valid(hw, vsi_handle_arr[i])) { 279162306a36Sopenharmony_ci status = -EINVAL; 279262306a36Sopenharmony_ci goto exit; 279362306a36Sopenharmony_ci } 279462306a36Sopenharmony_ci /* AQ call requires hw_vsi_id(s) */ 279562306a36Sopenharmony_ci s_rule->vsi[i] = 279662306a36Sopenharmony_ci cpu_to_le16(ice_get_hw_vsi_num(hw, vsi_handle_arr[i])); 279762306a36Sopenharmony_ci } 279862306a36Sopenharmony_ci 279962306a36Sopenharmony_ci s_rule->hdr.type = cpu_to_le16(rule_type); 280062306a36Sopenharmony_ci s_rule->number_vsi = cpu_to_le16(num_vsi); 280162306a36Sopenharmony_ci s_rule->index = cpu_to_le16(vsi_list_id); 280262306a36Sopenharmony_ci 280362306a36Sopenharmony_ci status = ice_aq_sw_rules(hw, s_rule, s_rule_size, 1, opc, NULL); 280462306a36Sopenharmony_ci 280562306a36Sopenharmony_ciexit: 280662306a36Sopenharmony_ci devm_kfree(ice_hw_to_dev(hw), s_rule); 280762306a36Sopenharmony_ci return status; 280862306a36Sopenharmony_ci} 280962306a36Sopenharmony_ci 281062306a36Sopenharmony_ci/** 281162306a36Sopenharmony_ci * ice_create_vsi_list_rule - Creates and populates a VSI list rule 281262306a36Sopenharmony_ci * @hw: pointer to the HW struct 281362306a36Sopenharmony_ci * @vsi_handle_arr: array of VSI handles to form a VSI list 281462306a36Sopenharmony_ci * @num_vsi: number of VSI handles in the array 281562306a36Sopenharmony_ci * @vsi_list_id: stores the ID of the VSI list to be created 281662306a36Sopenharmony_ci * @lkup_type: switch rule filter's lookup type 281762306a36Sopenharmony_ci */ 281862306a36Sopenharmony_cistatic int 281962306a36Sopenharmony_ciice_create_vsi_list_rule(struct ice_hw *hw, u16 *vsi_handle_arr, u16 num_vsi, 282062306a36Sopenharmony_ci u16 *vsi_list_id, enum ice_sw_lkup_type lkup_type) 282162306a36Sopenharmony_ci{ 282262306a36Sopenharmony_ci int status; 282362306a36Sopenharmony_ci 282462306a36Sopenharmony_ci status = ice_aq_alloc_free_vsi_list(hw, vsi_list_id, lkup_type, 282562306a36Sopenharmony_ci ice_aqc_opc_alloc_res); 282662306a36Sopenharmony_ci if (status) 282762306a36Sopenharmony_ci return status; 282862306a36Sopenharmony_ci 282962306a36Sopenharmony_ci /* Update the newly created VSI list to include the specified VSIs */ 283062306a36Sopenharmony_ci return ice_update_vsi_list_rule(hw, vsi_handle_arr, num_vsi, 283162306a36Sopenharmony_ci *vsi_list_id, false, 283262306a36Sopenharmony_ci ice_aqc_opc_add_sw_rules, lkup_type); 283362306a36Sopenharmony_ci} 283462306a36Sopenharmony_ci 283562306a36Sopenharmony_ci/** 283662306a36Sopenharmony_ci * ice_create_pkt_fwd_rule 283762306a36Sopenharmony_ci * @hw: pointer to the hardware structure 283862306a36Sopenharmony_ci * @f_entry: entry containing packet forwarding information 283962306a36Sopenharmony_ci * 284062306a36Sopenharmony_ci * Create switch rule with given filter information and add an entry 284162306a36Sopenharmony_ci * to the corresponding filter management list to track this switch rule 284262306a36Sopenharmony_ci * and VSI mapping 284362306a36Sopenharmony_ci */ 284462306a36Sopenharmony_cistatic int 284562306a36Sopenharmony_ciice_create_pkt_fwd_rule(struct ice_hw *hw, 284662306a36Sopenharmony_ci struct ice_fltr_list_entry *f_entry) 284762306a36Sopenharmony_ci{ 284862306a36Sopenharmony_ci struct ice_fltr_mgmt_list_entry *fm_entry; 284962306a36Sopenharmony_ci struct ice_sw_rule_lkup_rx_tx *s_rule; 285062306a36Sopenharmony_ci enum ice_sw_lkup_type l_type; 285162306a36Sopenharmony_ci struct ice_sw_recipe *recp; 285262306a36Sopenharmony_ci int status; 285362306a36Sopenharmony_ci 285462306a36Sopenharmony_ci s_rule = devm_kzalloc(ice_hw_to_dev(hw), 285562306a36Sopenharmony_ci ICE_SW_RULE_RX_TX_ETH_HDR_SIZE(s_rule), 285662306a36Sopenharmony_ci GFP_KERNEL); 285762306a36Sopenharmony_ci if (!s_rule) 285862306a36Sopenharmony_ci return -ENOMEM; 285962306a36Sopenharmony_ci fm_entry = devm_kzalloc(ice_hw_to_dev(hw), sizeof(*fm_entry), 286062306a36Sopenharmony_ci GFP_KERNEL); 286162306a36Sopenharmony_ci if (!fm_entry) { 286262306a36Sopenharmony_ci status = -ENOMEM; 286362306a36Sopenharmony_ci goto ice_create_pkt_fwd_rule_exit; 286462306a36Sopenharmony_ci } 286562306a36Sopenharmony_ci 286662306a36Sopenharmony_ci fm_entry->fltr_info = f_entry->fltr_info; 286762306a36Sopenharmony_ci 286862306a36Sopenharmony_ci /* Initialize all the fields for the management entry */ 286962306a36Sopenharmony_ci fm_entry->vsi_count = 1; 287062306a36Sopenharmony_ci fm_entry->lg_act_idx = ICE_INVAL_LG_ACT_INDEX; 287162306a36Sopenharmony_ci fm_entry->sw_marker_id = ICE_INVAL_SW_MARKER_ID; 287262306a36Sopenharmony_ci fm_entry->counter_index = ICE_INVAL_COUNTER_ID; 287362306a36Sopenharmony_ci 287462306a36Sopenharmony_ci ice_fill_sw_rule(hw, &fm_entry->fltr_info, s_rule, 287562306a36Sopenharmony_ci ice_aqc_opc_add_sw_rules); 287662306a36Sopenharmony_ci 287762306a36Sopenharmony_ci status = ice_aq_sw_rules(hw, s_rule, 287862306a36Sopenharmony_ci ICE_SW_RULE_RX_TX_ETH_HDR_SIZE(s_rule), 1, 287962306a36Sopenharmony_ci ice_aqc_opc_add_sw_rules, NULL); 288062306a36Sopenharmony_ci if (status) { 288162306a36Sopenharmony_ci devm_kfree(ice_hw_to_dev(hw), fm_entry); 288262306a36Sopenharmony_ci goto ice_create_pkt_fwd_rule_exit; 288362306a36Sopenharmony_ci } 288462306a36Sopenharmony_ci 288562306a36Sopenharmony_ci f_entry->fltr_info.fltr_rule_id = le16_to_cpu(s_rule->index); 288662306a36Sopenharmony_ci fm_entry->fltr_info.fltr_rule_id = le16_to_cpu(s_rule->index); 288762306a36Sopenharmony_ci 288862306a36Sopenharmony_ci /* The book keeping entries will get removed when base driver 288962306a36Sopenharmony_ci * calls remove filter AQ command 289062306a36Sopenharmony_ci */ 289162306a36Sopenharmony_ci l_type = fm_entry->fltr_info.lkup_type; 289262306a36Sopenharmony_ci recp = &hw->switch_info->recp_list[l_type]; 289362306a36Sopenharmony_ci list_add(&fm_entry->list_entry, &recp->filt_rules); 289462306a36Sopenharmony_ci 289562306a36Sopenharmony_ciice_create_pkt_fwd_rule_exit: 289662306a36Sopenharmony_ci devm_kfree(ice_hw_to_dev(hw), s_rule); 289762306a36Sopenharmony_ci return status; 289862306a36Sopenharmony_ci} 289962306a36Sopenharmony_ci 290062306a36Sopenharmony_ci/** 290162306a36Sopenharmony_ci * ice_update_pkt_fwd_rule 290262306a36Sopenharmony_ci * @hw: pointer to the hardware structure 290362306a36Sopenharmony_ci * @f_info: filter information for switch rule 290462306a36Sopenharmony_ci * 290562306a36Sopenharmony_ci * Call AQ command to update a previously created switch rule with a 290662306a36Sopenharmony_ci * VSI list ID 290762306a36Sopenharmony_ci */ 290862306a36Sopenharmony_cistatic int 290962306a36Sopenharmony_ciice_update_pkt_fwd_rule(struct ice_hw *hw, struct ice_fltr_info *f_info) 291062306a36Sopenharmony_ci{ 291162306a36Sopenharmony_ci struct ice_sw_rule_lkup_rx_tx *s_rule; 291262306a36Sopenharmony_ci int status; 291362306a36Sopenharmony_ci 291462306a36Sopenharmony_ci s_rule = devm_kzalloc(ice_hw_to_dev(hw), 291562306a36Sopenharmony_ci ICE_SW_RULE_RX_TX_ETH_HDR_SIZE(s_rule), 291662306a36Sopenharmony_ci GFP_KERNEL); 291762306a36Sopenharmony_ci if (!s_rule) 291862306a36Sopenharmony_ci return -ENOMEM; 291962306a36Sopenharmony_ci 292062306a36Sopenharmony_ci ice_fill_sw_rule(hw, f_info, s_rule, ice_aqc_opc_update_sw_rules); 292162306a36Sopenharmony_ci 292262306a36Sopenharmony_ci s_rule->index = cpu_to_le16(f_info->fltr_rule_id); 292362306a36Sopenharmony_ci 292462306a36Sopenharmony_ci /* Update switch rule with new rule set to forward VSI list */ 292562306a36Sopenharmony_ci status = ice_aq_sw_rules(hw, s_rule, 292662306a36Sopenharmony_ci ICE_SW_RULE_RX_TX_ETH_HDR_SIZE(s_rule), 1, 292762306a36Sopenharmony_ci ice_aqc_opc_update_sw_rules, NULL); 292862306a36Sopenharmony_ci 292962306a36Sopenharmony_ci devm_kfree(ice_hw_to_dev(hw), s_rule); 293062306a36Sopenharmony_ci return status; 293162306a36Sopenharmony_ci} 293262306a36Sopenharmony_ci 293362306a36Sopenharmony_ci/** 293462306a36Sopenharmony_ci * ice_update_sw_rule_bridge_mode 293562306a36Sopenharmony_ci * @hw: pointer to the HW struct 293662306a36Sopenharmony_ci * 293762306a36Sopenharmony_ci * Updates unicast switch filter rules based on VEB/VEPA mode 293862306a36Sopenharmony_ci */ 293962306a36Sopenharmony_ciint ice_update_sw_rule_bridge_mode(struct ice_hw *hw) 294062306a36Sopenharmony_ci{ 294162306a36Sopenharmony_ci struct ice_switch_info *sw = hw->switch_info; 294262306a36Sopenharmony_ci struct ice_fltr_mgmt_list_entry *fm_entry; 294362306a36Sopenharmony_ci struct list_head *rule_head; 294462306a36Sopenharmony_ci struct mutex *rule_lock; /* Lock to protect filter rule list */ 294562306a36Sopenharmony_ci int status = 0; 294662306a36Sopenharmony_ci 294762306a36Sopenharmony_ci rule_lock = &sw->recp_list[ICE_SW_LKUP_MAC].filt_rule_lock; 294862306a36Sopenharmony_ci rule_head = &sw->recp_list[ICE_SW_LKUP_MAC].filt_rules; 294962306a36Sopenharmony_ci 295062306a36Sopenharmony_ci mutex_lock(rule_lock); 295162306a36Sopenharmony_ci list_for_each_entry(fm_entry, rule_head, list_entry) { 295262306a36Sopenharmony_ci struct ice_fltr_info *fi = &fm_entry->fltr_info; 295362306a36Sopenharmony_ci u8 *addr = fi->l_data.mac.mac_addr; 295462306a36Sopenharmony_ci 295562306a36Sopenharmony_ci /* Update unicast Tx rules to reflect the selected 295662306a36Sopenharmony_ci * VEB/VEPA mode 295762306a36Sopenharmony_ci */ 295862306a36Sopenharmony_ci if ((fi->flag & ICE_FLTR_TX) && is_unicast_ether_addr(addr) && 295962306a36Sopenharmony_ci (fi->fltr_act == ICE_FWD_TO_VSI || 296062306a36Sopenharmony_ci fi->fltr_act == ICE_FWD_TO_VSI_LIST || 296162306a36Sopenharmony_ci fi->fltr_act == ICE_FWD_TO_Q || 296262306a36Sopenharmony_ci fi->fltr_act == ICE_FWD_TO_QGRP)) { 296362306a36Sopenharmony_ci status = ice_update_pkt_fwd_rule(hw, fi); 296462306a36Sopenharmony_ci if (status) 296562306a36Sopenharmony_ci break; 296662306a36Sopenharmony_ci } 296762306a36Sopenharmony_ci } 296862306a36Sopenharmony_ci 296962306a36Sopenharmony_ci mutex_unlock(rule_lock); 297062306a36Sopenharmony_ci 297162306a36Sopenharmony_ci return status; 297262306a36Sopenharmony_ci} 297362306a36Sopenharmony_ci 297462306a36Sopenharmony_ci/** 297562306a36Sopenharmony_ci * ice_add_update_vsi_list 297662306a36Sopenharmony_ci * @hw: pointer to the hardware structure 297762306a36Sopenharmony_ci * @m_entry: pointer to current filter management list entry 297862306a36Sopenharmony_ci * @cur_fltr: filter information from the book keeping entry 297962306a36Sopenharmony_ci * @new_fltr: filter information with the new VSI to be added 298062306a36Sopenharmony_ci * 298162306a36Sopenharmony_ci * Call AQ command to add or update previously created VSI list with new VSI. 298262306a36Sopenharmony_ci * 298362306a36Sopenharmony_ci * Helper function to do book keeping associated with adding filter information 298462306a36Sopenharmony_ci * The algorithm to do the book keeping is described below : 298562306a36Sopenharmony_ci * When a VSI needs to subscribe to a given filter (MAC/VLAN/Ethtype etc.) 298662306a36Sopenharmony_ci * if only one VSI has been added till now 298762306a36Sopenharmony_ci * Allocate a new VSI list and add two VSIs 298862306a36Sopenharmony_ci * to this list using switch rule command 298962306a36Sopenharmony_ci * Update the previously created switch rule with the 299062306a36Sopenharmony_ci * newly created VSI list ID 299162306a36Sopenharmony_ci * if a VSI list was previously created 299262306a36Sopenharmony_ci * Add the new VSI to the previously created VSI list set 299362306a36Sopenharmony_ci * using the update switch rule command 299462306a36Sopenharmony_ci */ 299562306a36Sopenharmony_cistatic int 299662306a36Sopenharmony_ciice_add_update_vsi_list(struct ice_hw *hw, 299762306a36Sopenharmony_ci struct ice_fltr_mgmt_list_entry *m_entry, 299862306a36Sopenharmony_ci struct ice_fltr_info *cur_fltr, 299962306a36Sopenharmony_ci struct ice_fltr_info *new_fltr) 300062306a36Sopenharmony_ci{ 300162306a36Sopenharmony_ci u16 vsi_list_id = 0; 300262306a36Sopenharmony_ci int status = 0; 300362306a36Sopenharmony_ci 300462306a36Sopenharmony_ci if ((cur_fltr->fltr_act == ICE_FWD_TO_Q || 300562306a36Sopenharmony_ci cur_fltr->fltr_act == ICE_FWD_TO_QGRP)) 300662306a36Sopenharmony_ci return -EOPNOTSUPP; 300762306a36Sopenharmony_ci 300862306a36Sopenharmony_ci if ((new_fltr->fltr_act == ICE_FWD_TO_Q || 300962306a36Sopenharmony_ci new_fltr->fltr_act == ICE_FWD_TO_QGRP) && 301062306a36Sopenharmony_ci (cur_fltr->fltr_act == ICE_FWD_TO_VSI || 301162306a36Sopenharmony_ci cur_fltr->fltr_act == ICE_FWD_TO_VSI_LIST)) 301262306a36Sopenharmony_ci return -EOPNOTSUPP; 301362306a36Sopenharmony_ci 301462306a36Sopenharmony_ci if (m_entry->vsi_count < 2 && !m_entry->vsi_list_info) { 301562306a36Sopenharmony_ci /* Only one entry existed in the mapping and it was not already 301662306a36Sopenharmony_ci * a part of a VSI list. So, create a VSI list with the old and 301762306a36Sopenharmony_ci * new VSIs. 301862306a36Sopenharmony_ci */ 301962306a36Sopenharmony_ci struct ice_fltr_info tmp_fltr; 302062306a36Sopenharmony_ci u16 vsi_handle_arr[2]; 302162306a36Sopenharmony_ci 302262306a36Sopenharmony_ci /* A rule already exists with the new VSI being added */ 302362306a36Sopenharmony_ci if (cur_fltr->fwd_id.hw_vsi_id == new_fltr->fwd_id.hw_vsi_id) 302462306a36Sopenharmony_ci return -EEXIST; 302562306a36Sopenharmony_ci 302662306a36Sopenharmony_ci vsi_handle_arr[0] = cur_fltr->vsi_handle; 302762306a36Sopenharmony_ci vsi_handle_arr[1] = new_fltr->vsi_handle; 302862306a36Sopenharmony_ci status = ice_create_vsi_list_rule(hw, &vsi_handle_arr[0], 2, 302962306a36Sopenharmony_ci &vsi_list_id, 303062306a36Sopenharmony_ci new_fltr->lkup_type); 303162306a36Sopenharmony_ci if (status) 303262306a36Sopenharmony_ci return status; 303362306a36Sopenharmony_ci 303462306a36Sopenharmony_ci tmp_fltr = *new_fltr; 303562306a36Sopenharmony_ci tmp_fltr.fltr_rule_id = cur_fltr->fltr_rule_id; 303662306a36Sopenharmony_ci tmp_fltr.fltr_act = ICE_FWD_TO_VSI_LIST; 303762306a36Sopenharmony_ci tmp_fltr.fwd_id.vsi_list_id = vsi_list_id; 303862306a36Sopenharmony_ci /* Update the previous switch rule of "MAC forward to VSI" to 303962306a36Sopenharmony_ci * "MAC fwd to VSI list" 304062306a36Sopenharmony_ci */ 304162306a36Sopenharmony_ci status = ice_update_pkt_fwd_rule(hw, &tmp_fltr); 304262306a36Sopenharmony_ci if (status) 304362306a36Sopenharmony_ci return status; 304462306a36Sopenharmony_ci 304562306a36Sopenharmony_ci cur_fltr->fwd_id.vsi_list_id = vsi_list_id; 304662306a36Sopenharmony_ci cur_fltr->fltr_act = ICE_FWD_TO_VSI_LIST; 304762306a36Sopenharmony_ci m_entry->vsi_list_info = 304862306a36Sopenharmony_ci ice_create_vsi_list_map(hw, &vsi_handle_arr[0], 2, 304962306a36Sopenharmony_ci vsi_list_id); 305062306a36Sopenharmony_ci 305162306a36Sopenharmony_ci if (!m_entry->vsi_list_info) 305262306a36Sopenharmony_ci return -ENOMEM; 305362306a36Sopenharmony_ci 305462306a36Sopenharmony_ci /* If this entry was large action then the large action needs 305562306a36Sopenharmony_ci * to be updated to point to FWD to VSI list 305662306a36Sopenharmony_ci */ 305762306a36Sopenharmony_ci if (m_entry->sw_marker_id != ICE_INVAL_SW_MARKER_ID) 305862306a36Sopenharmony_ci status = 305962306a36Sopenharmony_ci ice_add_marker_act(hw, m_entry, 306062306a36Sopenharmony_ci m_entry->sw_marker_id, 306162306a36Sopenharmony_ci m_entry->lg_act_idx); 306262306a36Sopenharmony_ci } else { 306362306a36Sopenharmony_ci u16 vsi_handle = new_fltr->vsi_handle; 306462306a36Sopenharmony_ci enum ice_adminq_opc opcode; 306562306a36Sopenharmony_ci 306662306a36Sopenharmony_ci if (!m_entry->vsi_list_info) 306762306a36Sopenharmony_ci return -EIO; 306862306a36Sopenharmony_ci 306962306a36Sopenharmony_ci /* A rule already exists with the new VSI being added */ 307062306a36Sopenharmony_ci if (test_bit(vsi_handle, m_entry->vsi_list_info->vsi_map)) 307162306a36Sopenharmony_ci return 0; 307262306a36Sopenharmony_ci 307362306a36Sopenharmony_ci /* Update the previously created VSI list set with 307462306a36Sopenharmony_ci * the new VSI ID passed in 307562306a36Sopenharmony_ci */ 307662306a36Sopenharmony_ci vsi_list_id = cur_fltr->fwd_id.vsi_list_id; 307762306a36Sopenharmony_ci opcode = ice_aqc_opc_update_sw_rules; 307862306a36Sopenharmony_ci 307962306a36Sopenharmony_ci status = ice_update_vsi_list_rule(hw, &vsi_handle, 1, 308062306a36Sopenharmony_ci vsi_list_id, false, opcode, 308162306a36Sopenharmony_ci new_fltr->lkup_type); 308262306a36Sopenharmony_ci /* update VSI list mapping info with new VSI ID */ 308362306a36Sopenharmony_ci if (!status) 308462306a36Sopenharmony_ci set_bit(vsi_handle, m_entry->vsi_list_info->vsi_map); 308562306a36Sopenharmony_ci } 308662306a36Sopenharmony_ci if (!status) 308762306a36Sopenharmony_ci m_entry->vsi_count++; 308862306a36Sopenharmony_ci return status; 308962306a36Sopenharmony_ci} 309062306a36Sopenharmony_ci 309162306a36Sopenharmony_ci/** 309262306a36Sopenharmony_ci * ice_find_rule_entry - Search a rule entry 309362306a36Sopenharmony_ci * @hw: pointer to the hardware structure 309462306a36Sopenharmony_ci * @recp_id: lookup type for which the specified rule needs to be searched 309562306a36Sopenharmony_ci * @f_info: rule information 309662306a36Sopenharmony_ci * 309762306a36Sopenharmony_ci * Helper function to search for a given rule entry 309862306a36Sopenharmony_ci * Returns pointer to entry storing the rule if found 309962306a36Sopenharmony_ci */ 310062306a36Sopenharmony_cistatic struct ice_fltr_mgmt_list_entry * 310162306a36Sopenharmony_ciice_find_rule_entry(struct ice_hw *hw, u8 recp_id, struct ice_fltr_info *f_info) 310262306a36Sopenharmony_ci{ 310362306a36Sopenharmony_ci struct ice_fltr_mgmt_list_entry *list_itr, *ret = NULL; 310462306a36Sopenharmony_ci struct ice_switch_info *sw = hw->switch_info; 310562306a36Sopenharmony_ci struct list_head *list_head; 310662306a36Sopenharmony_ci 310762306a36Sopenharmony_ci list_head = &sw->recp_list[recp_id].filt_rules; 310862306a36Sopenharmony_ci list_for_each_entry(list_itr, list_head, list_entry) { 310962306a36Sopenharmony_ci if (!memcmp(&f_info->l_data, &list_itr->fltr_info.l_data, 311062306a36Sopenharmony_ci sizeof(f_info->l_data)) && 311162306a36Sopenharmony_ci f_info->flag == list_itr->fltr_info.flag) { 311262306a36Sopenharmony_ci ret = list_itr; 311362306a36Sopenharmony_ci break; 311462306a36Sopenharmony_ci } 311562306a36Sopenharmony_ci } 311662306a36Sopenharmony_ci return ret; 311762306a36Sopenharmony_ci} 311862306a36Sopenharmony_ci 311962306a36Sopenharmony_ci/** 312062306a36Sopenharmony_ci * ice_find_vsi_list_entry - Search VSI list map with VSI count 1 312162306a36Sopenharmony_ci * @hw: pointer to the hardware structure 312262306a36Sopenharmony_ci * @recp_id: lookup type for which VSI lists needs to be searched 312362306a36Sopenharmony_ci * @vsi_handle: VSI handle to be found in VSI list 312462306a36Sopenharmony_ci * @vsi_list_id: VSI list ID found containing vsi_handle 312562306a36Sopenharmony_ci * 312662306a36Sopenharmony_ci * Helper function to search a VSI list with single entry containing given VSI 312762306a36Sopenharmony_ci * handle element. This can be extended further to search VSI list with more 312862306a36Sopenharmony_ci * than 1 vsi_count. Returns pointer to VSI list entry if found. 312962306a36Sopenharmony_ci */ 313062306a36Sopenharmony_cistruct ice_vsi_list_map_info * 313162306a36Sopenharmony_ciice_find_vsi_list_entry(struct ice_hw *hw, u8 recp_id, u16 vsi_handle, 313262306a36Sopenharmony_ci u16 *vsi_list_id) 313362306a36Sopenharmony_ci{ 313462306a36Sopenharmony_ci struct ice_vsi_list_map_info *map_info = NULL; 313562306a36Sopenharmony_ci struct ice_switch_info *sw = hw->switch_info; 313662306a36Sopenharmony_ci struct ice_fltr_mgmt_list_entry *list_itr; 313762306a36Sopenharmony_ci struct list_head *list_head; 313862306a36Sopenharmony_ci 313962306a36Sopenharmony_ci list_head = &sw->recp_list[recp_id].filt_rules; 314062306a36Sopenharmony_ci list_for_each_entry(list_itr, list_head, list_entry) { 314162306a36Sopenharmony_ci if (list_itr->vsi_list_info) { 314262306a36Sopenharmony_ci map_info = list_itr->vsi_list_info; 314362306a36Sopenharmony_ci if (test_bit(vsi_handle, map_info->vsi_map)) { 314462306a36Sopenharmony_ci *vsi_list_id = map_info->vsi_list_id; 314562306a36Sopenharmony_ci return map_info; 314662306a36Sopenharmony_ci } 314762306a36Sopenharmony_ci } 314862306a36Sopenharmony_ci } 314962306a36Sopenharmony_ci return NULL; 315062306a36Sopenharmony_ci} 315162306a36Sopenharmony_ci 315262306a36Sopenharmony_ci/** 315362306a36Sopenharmony_ci * ice_add_rule_internal - add rule for a given lookup type 315462306a36Sopenharmony_ci * @hw: pointer to the hardware structure 315562306a36Sopenharmony_ci * @recp_id: lookup type (recipe ID) for which rule has to be added 315662306a36Sopenharmony_ci * @f_entry: structure containing MAC forwarding information 315762306a36Sopenharmony_ci * 315862306a36Sopenharmony_ci * Adds or updates the rule lists for a given recipe 315962306a36Sopenharmony_ci */ 316062306a36Sopenharmony_cistatic int 316162306a36Sopenharmony_ciice_add_rule_internal(struct ice_hw *hw, u8 recp_id, 316262306a36Sopenharmony_ci struct ice_fltr_list_entry *f_entry) 316362306a36Sopenharmony_ci{ 316462306a36Sopenharmony_ci struct ice_switch_info *sw = hw->switch_info; 316562306a36Sopenharmony_ci struct ice_fltr_info *new_fltr, *cur_fltr; 316662306a36Sopenharmony_ci struct ice_fltr_mgmt_list_entry *m_entry; 316762306a36Sopenharmony_ci struct mutex *rule_lock; /* Lock to protect filter rule list */ 316862306a36Sopenharmony_ci int status = 0; 316962306a36Sopenharmony_ci 317062306a36Sopenharmony_ci if (!ice_is_vsi_valid(hw, f_entry->fltr_info.vsi_handle)) 317162306a36Sopenharmony_ci return -EINVAL; 317262306a36Sopenharmony_ci f_entry->fltr_info.fwd_id.hw_vsi_id = 317362306a36Sopenharmony_ci ice_get_hw_vsi_num(hw, f_entry->fltr_info.vsi_handle); 317462306a36Sopenharmony_ci 317562306a36Sopenharmony_ci rule_lock = &sw->recp_list[recp_id].filt_rule_lock; 317662306a36Sopenharmony_ci 317762306a36Sopenharmony_ci mutex_lock(rule_lock); 317862306a36Sopenharmony_ci new_fltr = &f_entry->fltr_info; 317962306a36Sopenharmony_ci if (new_fltr->flag & ICE_FLTR_RX) 318062306a36Sopenharmony_ci new_fltr->src = hw->port_info->lport; 318162306a36Sopenharmony_ci else if (new_fltr->flag & ICE_FLTR_TX) 318262306a36Sopenharmony_ci new_fltr->src = f_entry->fltr_info.fwd_id.hw_vsi_id; 318362306a36Sopenharmony_ci 318462306a36Sopenharmony_ci m_entry = ice_find_rule_entry(hw, recp_id, new_fltr); 318562306a36Sopenharmony_ci if (!m_entry) { 318662306a36Sopenharmony_ci mutex_unlock(rule_lock); 318762306a36Sopenharmony_ci return ice_create_pkt_fwd_rule(hw, f_entry); 318862306a36Sopenharmony_ci } 318962306a36Sopenharmony_ci 319062306a36Sopenharmony_ci cur_fltr = &m_entry->fltr_info; 319162306a36Sopenharmony_ci status = ice_add_update_vsi_list(hw, m_entry, cur_fltr, new_fltr); 319262306a36Sopenharmony_ci mutex_unlock(rule_lock); 319362306a36Sopenharmony_ci 319462306a36Sopenharmony_ci return status; 319562306a36Sopenharmony_ci} 319662306a36Sopenharmony_ci 319762306a36Sopenharmony_ci/** 319862306a36Sopenharmony_ci * ice_remove_vsi_list_rule 319962306a36Sopenharmony_ci * @hw: pointer to the hardware structure 320062306a36Sopenharmony_ci * @vsi_list_id: VSI list ID generated as part of allocate resource 320162306a36Sopenharmony_ci * @lkup_type: switch rule filter lookup type 320262306a36Sopenharmony_ci * 320362306a36Sopenharmony_ci * The VSI list should be emptied before this function is called to remove the 320462306a36Sopenharmony_ci * VSI list. 320562306a36Sopenharmony_ci */ 320662306a36Sopenharmony_cistatic int 320762306a36Sopenharmony_ciice_remove_vsi_list_rule(struct ice_hw *hw, u16 vsi_list_id, 320862306a36Sopenharmony_ci enum ice_sw_lkup_type lkup_type) 320962306a36Sopenharmony_ci{ 321062306a36Sopenharmony_ci struct ice_sw_rule_vsi_list *s_rule; 321162306a36Sopenharmony_ci u16 s_rule_size; 321262306a36Sopenharmony_ci int status; 321362306a36Sopenharmony_ci 321462306a36Sopenharmony_ci s_rule_size = (u16)ICE_SW_RULE_VSI_LIST_SIZE(s_rule, 0); 321562306a36Sopenharmony_ci s_rule = devm_kzalloc(ice_hw_to_dev(hw), s_rule_size, GFP_KERNEL); 321662306a36Sopenharmony_ci if (!s_rule) 321762306a36Sopenharmony_ci return -ENOMEM; 321862306a36Sopenharmony_ci 321962306a36Sopenharmony_ci s_rule->hdr.type = cpu_to_le16(ICE_AQC_SW_RULES_T_VSI_LIST_CLEAR); 322062306a36Sopenharmony_ci s_rule->index = cpu_to_le16(vsi_list_id); 322162306a36Sopenharmony_ci 322262306a36Sopenharmony_ci /* Free the vsi_list resource that we allocated. It is assumed that the 322362306a36Sopenharmony_ci * list is empty at this point. 322462306a36Sopenharmony_ci */ 322562306a36Sopenharmony_ci status = ice_aq_alloc_free_vsi_list(hw, &vsi_list_id, lkup_type, 322662306a36Sopenharmony_ci ice_aqc_opc_free_res); 322762306a36Sopenharmony_ci 322862306a36Sopenharmony_ci devm_kfree(ice_hw_to_dev(hw), s_rule); 322962306a36Sopenharmony_ci return status; 323062306a36Sopenharmony_ci} 323162306a36Sopenharmony_ci 323262306a36Sopenharmony_ci/** 323362306a36Sopenharmony_ci * ice_rem_update_vsi_list 323462306a36Sopenharmony_ci * @hw: pointer to the hardware structure 323562306a36Sopenharmony_ci * @vsi_handle: VSI handle of the VSI to remove 323662306a36Sopenharmony_ci * @fm_list: filter management entry for which the VSI list management needs to 323762306a36Sopenharmony_ci * be done 323862306a36Sopenharmony_ci */ 323962306a36Sopenharmony_cistatic int 324062306a36Sopenharmony_ciice_rem_update_vsi_list(struct ice_hw *hw, u16 vsi_handle, 324162306a36Sopenharmony_ci struct ice_fltr_mgmt_list_entry *fm_list) 324262306a36Sopenharmony_ci{ 324362306a36Sopenharmony_ci enum ice_sw_lkup_type lkup_type; 324462306a36Sopenharmony_ci u16 vsi_list_id; 324562306a36Sopenharmony_ci int status = 0; 324662306a36Sopenharmony_ci 324762306a36Sopenharmony_ci if (fm_list->fltr_info.fltr_act != ICE_FWD_TO_VSI_LIST || 324862306a36Sopenharmony_ci fm_list->vsi_count == 0) 324962306a36Sopenharmony_ci return -EINVAL; 325062306a36Sopenharmony_ci 325162306a36Sopenharmony_ci /* A rule with the VSI being removed does not exist */ 325262306a36Sopenharmony_ci if (!test_bit(vsi_handle, fm_list->vsi_list_info->vsi_map)) 325362306a36Sopenharmony_ci return -ENOENT; 325462306a36Sopenharmony_ci 325562306a36Sopenharmony_ci lkup_type = fm_list->fltr_info.lkup_type; 325662306a36Sopenharmony_ci vsi_list_id = fm_list->fltr_info.fwd_id.vsi_list_id; 325762306a36Sopenharmony_ci status = ice_update_vsi_list_rule(hw, &vsi_handle, 1, vsi_list_id, true, 325862306a36Sopenharmony_ci ice_aqc_opc_update_sw_rules, 325962306a36Sopenharmony_ci lkup_type); 326062306a36Sopenharmony_ci if (status) 326162306a36Sopenharmony_ci return status; 326262306a36Sopenharmony_ci 326362306a36Sopenharmony_ci fm_list->vsi_count--; 326462306a36Sopenharmony_ci clear_bit(vsi_handle, fm_list->vsi_list_info->vsi_map); 326562306a36Sopenharmony_ci 326662306a36Sopenharmony_ci if (fm_list->vsi_count == 1 && lkup_type != ICE_SW_LKUP_VLAN) { 326762306a36Sopenharmony_ci struct ice_fltr_info tmp_fltr_info = fm_list->fltr_info; 326862306a36Sopenharmony_ci struct ice_vsi_list_map_info *vsi_list_info = 326962306a36Sopenharmony_ci fm_list->vsi_list_info; 327062306a36Sopenharmony_ci u16 rem_vsi_handle; 327162306a36Sopenharmony_ci 327262306a36Sopenharmony_ci rem_vsi_handle = find_first_bit(vsi_list_info->vsi_map, 327362306a36Sopenharmony_ci ICE_MAX_VSI); 327462306a36Sopenharmony_ci if (!ice_is_vsi_valid(hw, rem_vsi_handle)) 327562306a36Sopenharmony_ci return -EIO; 327662306a36Sopenharmony_ci 327762306a36Sopenharmony_ci /* Make sure VSI list is empty before removing it below */ 327862306a36Sopenharmony_ci status = ice_update_vsi_list_rule(hw, &rem_vsi_handle, 1, 327962306a36Sopenharmony_ci vsi_list_id, true, 328062306a36Sopenharmony_ci ice_aqc_opc_update_sw_rules, 328162306a36Sopenharmony_ci lkup_type); 328262306a36Sopenharmony_ci if (status) 328362306a36Sopenharmony_ci return status; 328462306a36Sopenharmony_ci 328562306a36Sopenharmony_ci tmp_fltr_info.fltr_act = ICE_FWD_TO_VSI; 328662306a36Sopenharmony_ci tmp_fltr_info.fwd_id.hw_vsi_id = 328762306a36Sopenharmony_ci ice_get_hw_vsi_num(hw, rem_vsi_handle); 328862306a36Sopenharmony_ci tmp_fltr_info.vsi_handle = rem_vsi_handle; 328962306a36Sopenharmony_ci status = ice_update_pkt_fwd_rule(hw, &tmp_fltr_info); 329062306a36Sopenharmony_ci if (status) { 329162306a36Sopenharmony_ci ice_debug(hw, ICE_DBG_SW, "Failed to update pkt fwd rule to FWD_TO_VSI on HW VSI %d, error %d\n", 329262306a36Sopenharmony_ci tmp_fltr_info.fwd_id.hw_vsi_id, status); 329362306a36Sopenharmony_ci return status; 329462306a36Sopenharmony_ci } 329562306a36Sopenharmony_ci 329662306a36Sopenharmony_ci fm_list->fltr_info = tmp_fltr_info; 329762306a36Sopenharmony_ci } 329862306a36Sopenharmony_ci 329962306a36Sopenharmony_ci if ((fm_list->vsi_count == 1 && lkup_type != ICE_SW_LKUP_VLAN) || 330062306a36Sopenharmony_ci (fm_list->vsi_count == 0 && lkup_type == ICE_SW_LKUP_VLAN)) { 330162306a36Sopenharmony_ci struct ice_vsi_list_map_info *vsi_list_info = 330262306a36Sopenharmony_ci fm_list->vsi_list_info; 330362306a36Sopenharmony_ci 330462306a36Sopenharmony_ci /* Remove the VSI list since it is no longer used */ 330562306a36Sopenharmony_ci status = ice_remove_vsi_list_rule(hw, vsi_list_id, lkup_type); 330662306a36Sopenharmony_ci if (status) { 330762306a36Sopenharmony_ci ice_debug(hw, ICE_DBG_SW, "Failed to remove VSI list %d, error %d\n", 330862306a36Sopenharmony_ci vsi_list_id, status); 330962306a36Sopenharmony_ci return status; 331062306a36Sopenharmony_ci } 331162306a36Sopenharmony_ci 331262306a36Sopenharmony_ci list_del(&vsi_list_info->list_entry); 331362306a36Sopenharmony_ci devm_kfree(ice_hw_to_dev(hw), vsi_list_info); 331462306a36Sopenharmony_ci fm_list->vsi_list_info = NULL; 331562306a36Sopenharmony_ci } 331662306a36Sopenharmony_ci 331762306a36Sopenharmony_ci return status; 331862306a36Sopenharmony_ci} 331962306a36Sopenharmony_ci 332062306a36Sopenharmony_ci/** 332162306a36Sopenharmony_ci * ice_remove_rule_internal - Remove a filter rule of a given type 332262306a36Sopenharmony_ci * @hw: pointer to the hardware structure 332362306a36Sopenharmony_ci * @recp_id: recipe ID for which the rule needs to removed 332462306a36Sopenharmony_ci * @f_entry: rule entry containing filter information 332562306a36Sopenharmony_ci */ 332662306a36Sopenharmony_cistatic int 332762306a36Sopenharmony_ciice_remove_rule_internal(struct ice_hw *hw, u8 recp_id, 332862306a36Sopenharmony_ci struct ice_fltr_list_entry *f_entry) 332962306a36Sopenharmony_ci{ 333062306a36Sopenharmony_ci struct ice_switch_info *sw = hw->switch_info; 333162306a36Sopenharmony_ci struct ice_fltr_mgmt_list_entry *list_elem; 333262306a36Sopenharmony_ci struct mutex *rule_lock; /* Lock to protect filter rule list */ 333362306a36Sopenharmony_ci bool remove_rule = false; 333462306a36Sopenharmony_ci u16 vsi_handle; 333562306a36Sopenharmony_ci int status = 0; 333662306a36Sopenharmony_ci 333762306a36Sopenharmony_ci if (!ice_is_vsi_valid(hw, f_entry->fltr_info.vsi_handle)) 333862306a36Sopenharmony_ci return -EINVAL; 333962306a36Sopenharmony_ci f_entry->fltr_info.fwd_id.hw_vsi_id = 334062306a36Sopenharmony_ci ice_get_hw_vsi_num(hw, f_entry->fltr_info.vsi_handle); 334162306a36Sopenharmony_ci 334262306a36Sopenharmony_ci rule_lock = &sw->recp_list[recp_id].filt_rule_lock; 334362306a36Sopenharmony_ci mutex_lock(rule_lock); 334462306a36Sopenharmony_ci list_elem = ice_find_rule_entry(hw, recp_id, &f_entry->fltr_info); 334562306a36Sopenharmony_ci if (!list_elem) { 334662306a36Sopenharmony_ci status = -ENOENT; 334762306a36Sopenharmony_ci goto exit; 334862306a36Sopenharmony_ci } 334962306a36Sopenharmony_ci 335062306a36Sopenharmony_ci if (list_elem->fltr_info.fltr_act != ICE_FWD_TO_VSI_LIST) { 335162306a36Sopenharmony_ci remove_rule = true; 335262306a36Sopenharmony_ci } else if (!list_elem->vsi_list_info) { 335362306a36Sopenharmony_ci status = -ENOENT; 335462306a36Sopenharmony_ci goto exit; 335562306a36Sopenharmony_ci } else if (list_elem->vsi_list_info->ref_cnt > 1) { 335662306a36Sopenharmony_ci /* a ref_cnt > 1 indicates that the vsi_list is being 335762306a36Sopenharmony_ci * shared by multiple rules. Decrement the ref_cnt and 335862306a36Sopenharmony_ci * remove this rule, but do not modify the list, as it 335962306a36Sopenharmony_ci * is in-use by other rules. 336062306a36Sopenharmony_ci */ 336162306a36Sopenharmony_ci list_elem->vsi_list_info->ref_cnt--; 336262306a36Sopenharmony_ci remove_rule = true; 336362306a36Sopenharmony_ci } else { 336462306a36Sopenharmony_ci /* a ref_cnt of 1 indicates the vsi_list is only used 336562306a36Sopenharmony_ci * by one rule. However, the original removal request is only 336662306a36Sopenharmony_ci * for a single VSI. Update the vsi_list first, and only 336762306a36Sopenharmony_ci * remove the rule if there are no further VSIs in this list. 336862306a36Sopenharmony_ci */ 336962306a36Sopenharmony_ci vsi_handle = f_entry->fltr_info.vsi_handle; 337062306a36Sopenharmony_ci status = ice_rem_update_vsi_list(hw, vsi_handle, list_elem); 337162306a36Sopenharmony_ci if (status) 337262306a36Sopenharmony_ci goto exit; 337362306a36Sopenharmony_ci /* if VSI count goes to zero after updating the VSI list */ 337462306a36Sopenharmony_ci if (list_elem->vsi_count == 0) 337562306a36Sopenharmony_ci remove_rule = true; 337662306a36Sopenharmony_ci } 337762306a36Sopenharmony_ci 337862306a36Sopenharmony_ci if (remove_rule) { 337962306a36Sopenharmony_ci /* Remove the lookup rule */ 338062306a36Sopenharmony_ci struct ice_sw_rule_lkup_rx_tx *s_rule; 338162306a36Sopenharmony_ci 338262306a36Sopenharmony_ci s_rule = devm_kzalloc(ice_hw_to_dev(hw), 338362306a36Sopenharmony_ci ICE_SW_RULE_RX_TX_NO_HDR_SIZE(s_rule), 338462306a36Sopenharmony_ci GFP_KERNEL); 338562306a36Sopenharmony_ci if (!s_rule) { 338662306a36Sopenharmony_ci status = -ENOMEM; 338762306a36Sopenharmony_ci goto exit; 338862306a36Sopenharmony_ci } 338962306a36Sopenharmony_ci 339062306a36Sopenharmony_ci ice_fill_sw_rule(hw, &list_elem->fltr_info, s_rule, 339162306a36Sopenharmony_ci ice_aqc_opc_remove_sw_rules); 339262306a36Sopenharmony_ci 339362306a36Sopenharmony_ci status = ice_aq_sw_rules(hw, s_rule, 339462306a36Sopenharmony_ci ICE_SW_RULE_RX_TX_NO_HDR_SIZE(s_rule), 339562306a36Sopenharmony_ci 1, ice_aqc_opc_remove_sw_rules, NULL); 339662306a36Sopenharmony_ci 339762306a36Sopenharmony_ci /* Remove a book keeping from the list */ 339862306a36Sopenharmony_ci devm_kfree(ice_hw_to_dev(hw), s_rule); 339962306a36Sopenharmony_ci 340062306a36Sopenharmony_ci if (status) 340162306a36Sopenharmony_ci goto exit; 340262306a36Sopenharmony_ci 340362306a36Sopenharmony_ci list_del(&list_elem->list_entry); 340462306a36Sopenharmony_ci devm_kfree(ice_hw_to_dev(hw), list_elem); 340562306a36Sopenharmony_ci } 340662306a36Sopenharmony_ciexit: 340762306a36Sopenharmony_ci mutex_unlock(rule_lock); 340862306a36Sopenharmony_ci return status; 340962306a36Sopenharmony_ci} 341062306a36Sopenharmony_ci 341162306a36Sopenharmony_ci/** 341262306a36Sopenharmony_ci * ice_vlan_fltr_exist - does this VLAN filter exist for given VSI 341362306a36Sopenharmony_ci * @hw: pointer to the hardware structure 341462306a36Sopenharmony_ci * @vlan_id: VLAN ID 341562306a36Sopenharmony_ci * @vsi_handle: check MAC filter for this VSI 341662306a36Sopenharmony_ci */ 341762306a36Sopenharmony_cibool ice_vlan_fltr_exist(struct ice_hw *hw, u16 vlan_id, u16 vsi_handle) 341862306a36Sopenharmony_ci{ 341962306a36Sopenharmony_ci struct ice_fltr_mgmt_list_entry *entry; 342062306a36Sopenharmony_ci struct list_head *rule_head; 342162306a36Sopenharmony_ci struct ice_switch_info *sw; 342262306a36Sopenharmony_ci struct mutex *rule_lock; /* Lock to protect filter rule list */ 342362306a36Sopenharmony_ci u16 hw_vsi_id; 342462306a36Sopenharmony_ci 342562306a36Sopenharmony_ci if (vlan_id > ICE_MAX_VLAN_ID) 342662306a36Sopenharmony_ci return false; 342762306a36Sopenharmony_ci 342862306a36Sopenharmony_ci if (!ice_is_vsi_valid(hw, vsi_handle)) 342962306a36Sopenharmony_ci return false; 343062306a36Sopenharmony_ci 343162306a36Sopenharmony_ci hw_vsi_id = ice_get_hw_vsi_num(hw, vsi_handle); 343262306a36Sopenharmony_ci sw = hw->switch_info; 343362306a36Sopenharmony_ci rule_head = &sw->recp_list[ICE_SW_LKUP_VLAN].filt_rules; 343462306a36Sopenharmony_ci if (!rule_head) 343562306a36Sopenharmony_ci return false; 343662306a36Sopenharmony_ci 343762306a36Sopenharmony_ci rule_lock = &sw->recp_list[ICE_SW_LKUP_VLAN].filt_rule_lock; 343862306a36Sopenharmony_ci mutex_lock(rule_lock); 343962306a36Sopenharmony_ci list_for_each_entry(entry, rule_head, list_entry) { 344062306a36Sopenharmony_ci struct ice_fltr_info *f_info = &entry->fltr_info; 344162306a36Sopenharmony_ci u16 entry_vlan_id = f_info->l_data.vlan.vlan_id; 344262306a36Sopenharmony_ci struct ice_vsi_list_map_info *map_info; 344362306a36Sopenharmony_ci 344462306a36Sopenharmony_ci if (entry_vlan_id > ICE_MAX_VLAN_ID) 344562306a36Sopenharmony_ci continue; 344662306a36Sopenharmony_ci 344762306a36Sopenharmony_ci if (f_info->flag != ICE_FLTR_TX || 344862306a36Sopenharmony_ci f_info->src_id != ICE_SRC_ID_VSI || 344962306a36Sopenharmony_ci f_info->lkup_type != ICE_SW_LKUP_VLAN) 345062306a36Sopenharmony_ci continue; 345162306a36Sopenharmony_ci 345262306a36Sopenharmony_ci /* Only allowed filter action are FWD_TO_VSI/_VSI_LIST */ 345362306a36Sopenharmony_ci if (f_info->fltr_act != ICE_FWD_TO_VSI && 345462306a36Sopenharmony_ci f_info->fltr_act != ICE_FWD_TO_VSI_LIST) 345562306a36Sopenharmony_ci continue; 345662306a36Sopenharmony_ci 345762306a36Sopenharmony_ci if (f_info->fltr_act == ICE_FWD_TO_VSI) { 345862306a36Sopenharmony_ci if (hw_vsi_id != f_info->fwd_id.hw_vsi_id) 345962306a36Sopenharmony_ci continue; 346062306a36Sopenharmony_ci } else if (f_info->fltr_act == ICE_FWD_TO_VSI_LIST) { 346162306a36Sopenharmony_ci /* If filter_action is FWD_TO_VSI_LIST, make sure 346262306a36Sopenharmony_ci * that VSI being checked is part of VSI list 346362306a36Sopenharmony_ci */ 346462306a36Sopenharmony_ci if (entry->vsi_count == 1 && 346562306a36Sopenharmony_ci entry->vsi_list_info) { 346662306a36Sopenharmony_ci map_info = entry->vsi_list_info; 346762306a36Sopenharmony_ci if (!test_bit(vsi_handle, map_info->vsi_map)) 346862306a36Sopenharmony_ci continue; 346962306a36Sopenharmony_ci } 347062306a36Sopenharmony_ci } 347162306a36Sopenharmony_ci 347262306a36Sopenharmony_ci if (vlan_id == entry_vlan_id) { 347362306a36Sopenharmony_ci mutex_unlock(rule_lock); 347462306a36Sopenharmony_ci return true; 347562306a36Sopenharmony_ci } 347662306a36Sopenharmony_ci } 347762306a36Sopenharmony_ci mutex_unlock(rule_lock); 347862306a36Sopenharmony_ci 347962306a36Sopenharmony_ci return false; 348062306a36Sopenharmony_ci} 348162306a36Sopenharmony_ci 348262306a36Sopenharmony_ci/** 348362306a36Sopenharmony_ci * ice_add_mac - Add a MAC address based filter rule 348462306a36Sopenharmony_ci * @hw: pointer to the hardware structure 348562306a36Sopenharmony_ci * @m_list: list of MAC addresses and forwarding information 348662306a36Sopenharmony_ci */ 348762306a36Sopenharmony_ciint ice_add_mac(struct ice_hw *hw, struct list_head *m_list) 348862306a36Sopenharmony_ci{ 348962306a36Sopenharmony_ci struct ice_fltr_list_entry *m_list_itr; 349062306a36Sopenharmony_ci int status = 0; 349162306a36Sopenharmony_ci 349262306a36Sopenharmony_ci if (!m_list || !hw) 349362306a36Sopenharmony_ci return -EINVAL; 349462306a36Sopenharmony_ci 349562306a36Sopenharmony_ci list_for_each_entry(m_list_itr, m_list, list_entry) { 349662306a36Sopenharmony_ci u8 *add = &m_list_itr->fltr_info.l_data.mac.mac_addr[0]; 349762306a36Sopenharmony_ci u16 vsi_handle; 349862306a36Sopenharmony_ci u16 hw_vsi_id; 349962306a36Sopenharmony_ci 350062306a36Sopenharmony_ci m_list_itr->fltr_info.flag = ICE_FLTR_TX; 350162306a36Sopenharmony_ci vsi_handle = m_list_itr->fltr_info.vsi_handle; 350262306a36Sopenharmony_ci if (!ice_is_vsi_valid(hw, vsi_handle)) 350362306a36Sopenharmony_ci return -EINVAL; 350462306a36Sopenharmony_ci hw_vsi_id = ice_get_hw_vsi_num(hw, vsi_handle); 350562306a36Sopenharmony_ci m_list_itr->fltr_info.fwd_id.hw_vsi_id = hw_vsi_id; 350662306a36Sopenharmony_ci /* update the src in case it is VSI num */ 350762306a36Sopenharmony_ci if (m_list_itr->fltr_info.src_id != ICE_SRC_ID_VSI) 350862306a36Sopenharmony_ci return -EINVAL; 350962306a36Sopenharmony_ci m_list_itr->fltr_info.src = hw_vsi_id; 351062306a36Sopenharmony_ci if (m_list_itr->fltr_info.lkup_type != ICE_SW_LKUP_MAC || 351162306a36Sopenharmony_ci is_zero_ether_addr(add)) 351262306a36Sopenharmony_ci return -EINVAL; 351362306a36Sopenharmony_ci 351462306a36Sopenharmony_ci m_list_itr->status = ice_add_rule_internal(hw, ICE_SW_LKUP_MAC, 351562306a36Sopenharmony_ci m_list_itr); 351662306a36Sopenharmony_ci if (m_list_itr->status) 351762306a36Sopenharmony_ci return m_list_itr->status; 351862306a36Sopenharmony_ci } 351962306a36Sopenharmony_ci 352062306a36Sopenharmony_ci return status; 352162306a36Sopenharmony_ci} 352262306a36Sopenharmony_ci 352362306a36Sopenharmony_ci/** 352462306a36Sopenharmony_ci * ice_add_vlan_internal - Add one VLAN based filter rule 352562306a36Sopenharmony_ci * @hw: pointer to the hardware structure 352662306a36Sopenharmony_ci * @f_entry: filter entry containing one VLAN information 352762306a36Sopenharmony_ci */ 352862306a36Sopenharmony_cistatic int 352962306a36Sopenharmony_ciice_add_vlan_internal(struct ice_hw *hw, struct ice_fltr_list_entry *f_entry) 353062306a36Sopenharmony_ci{ 353162306a36Sopenharmony_ci struct ice_switch_info *sw = hw->switch_info; 353262306a36Sopenharmony_ci struct ice_fltr_mgmt_list_entry *v_list_itr; 353362306a36Sopenharmony_ci struct ice_fltr_info *new_fltr, *cur_fltr; 353462306a36Sopenharmony_ci enum ice_sw_lkup_type lkup_type; 353562306a36Sopenharmony_ci u16 vsi_list_id = 0, vsi_handle; 353662306a36Sopenharmony_ci struct mutex *rule_lock; /* Lock to protect filter rule list */ 353762306a36Sopenharmony_ci int status = 0; 353862306a36Sopenharmony_ci 353962306a36Sopenharmony_ci if (!ice_is_vsi_valid(hw, f_entry->fltr_info.vsi_handle)) 354062306a36Sopenharmony_ci return -EINVAL; 354162306a36Sopenharmony_ci 354262306a36Sopenharmony_ci f_entry->fltr_info.fwd_id.hw_vsi_id = 354362306a36Sopenharmony_ci ice_get_hw_vsi_num(hw, f_entry->fltr_info.vsi_handle); 354462306a36Sopenharmony_ci new_fltr = &f_entry->fltr_info; 354562306a36Sopenharmony_ci 354662306a36Sopenharmony_ci /* VLAN ID should only be 12 bits */ 354762306a36Sopenharmony_ci if (new_fltr->l_data.vlan.vlan_id > ICE_MAX_VLAN_ID) 354862306a36Sopenharmony_ci return -EINVAL; 354962306a36Sopenharmony_ci 355062306a36Sopenharmony_ci if (new_fltr->src_id != ICE_SRC_ID_VSI) 355162306a36Sopenharmony_ci return -EINVAL; 355262306a36Sopenharmony_ci 355362306a36Sopenharmony_ci new_fltr->src = new_fltr->fwd_id.hw_vsi_id; 355462306a36Sopenharmony_ci lkup_type = new_fltr->lkup_type; 355562306a36Sopenharmony_ci vsi_handle = new_fltr->vsi_handle; 355662306a36Sopenharmony_ci rule_lock = &sw->recp_list[ICE_SW_LKUP_VLAN].filt_rule_lock; 355762306a36Sopenharmony_ci mutex_lock(rule_lock); 355862306a36Sopenharmony_ci v_list_itr = ice_find_rule_entry(hw, ICE_SW_LKUP_VLAN, new_fltr); 355962306a36Sopenharmony_ci if (!v_list_itr) { 356062306a36Sopenharmony_ci struct ice_vsi_list_map_info *map_info = NULL; 356162306a36Sopenharmony_ci 356262306a36Sopenharmony_ci if (new_fltr->fltr_act == ICE_FWD_TO_VSI) { 356362306a36Sopenharmony_ci /* All VLAN pruning rules use a VSI list. Check if 356462306a36Sopenharmony_ci * there is already a VSI list containing VSI that we 356562306a36Sopenharmony_ci * want to add. If found, use the same vsi_list_id for 356662306a36Sopenharmony_ci * this new VLAN rule or else create a new list. 356762306a36Sopenharmony_ci */ 356862306a36Sopenharmony_ci map_info = ice_find_vsi_list_entry(hw, ICE_SW_LKUP_VLAN, 356962306a36Sopenharmony_ci vsi_handle, 357062306a36Sopenharmony_ci &vsi_list_id); 357162306a36Sopenharmony_ci if (!map_info) { 357262306a36Sopenharmony_ci status = ice_create_vsi_list_rule(hw, 357362306a36Sopenharmony_ci &vsi_handle, 357462306a36Sopenharmony_ci 1, 357562306a36Sopenharmony_ci &vsi_list_id, 357662306a36Sopenharmony_ci lkup_type); 357762306a36Sopenharmony_ci if (status) 357862306a36Sopenharmony_ci goto exit; 357962306a36Sopenharmony_ci } 358062306a36Sopenharmony_ci /* Convert the action to forwarding to a VSI list. */ 358162306a36Sopenharmony_ci new_fltr->fltr_act = ICE_FWD_TO_VSI_LIST; 358262306a36Sopenharmony_ci new_fltr->fwd_id.vsi_list_id = vsi_list_id; 358362306a36Sopenharmony_ci } 358462306a36Sopenharmony_ci 358562306a36Sopenharmony_ci status = ice_create_pkt_fwd_rule(hw, f_entry); 358662306a36Sopenharmony_ci if (!status) { 358762306a36Sopenharmony_ci v_list_itr = ice_find_rule_entry(hw, ICE_SW_LKUP_VLAN, 358862306a36Sopenharmony_ci new_fltr); 358962306a36Sopenharmony_ci if (!v_list_itr) { 359062306a36Sopenharmony_ci status = -ENOENT; 359162306a36Sopenharmony_ci goto exit; 359262306a36Sopenharmony_ci } 359362306a36Sopenharmony_ci /* reuse VSI list for new rule and increment ref_cnt */ 359462306a36Sopenharmony_ci if (map_info) { 359562306a36Sopenharmony_ci v_list_itr->vsi_list_info = map_info; 359662306a36Sopenharmony_ci map_info->ref_cnt++; 359762306a36Sopenharmony_ci } else { 359862306a36Sopenharmony_ci v_list_itr->vsi_list_info = 359962306a36Sopenharmony_ci ice_create_vsi_list_map(hw, &vsi_handle, 360062306a36Sopenharmony_ci 1, vsi_list_id); 360162306a36Sopenharmony_ci } 360262306a36Sopenharmony_ci } 360362306a36Sopenharmony_ci } else if (v_list_itr->vsi_list_info->ref_cnt == 1) { 360462306a36Sopenharmony_ci /* Update existing VSI list to add new VSI ID only if it used 360562306a36Sopenharmony_ci * by one VLAN rule. 360662306a36Sopenharmony_ci */ 360762306a36Sopenharmony_ci cur_fltr = &v_list_itr->fltr_info; 360862306a36Sopenharmony_ci status = ice_add_update_vsi_list(hw, v_list_itr, cur_fltr, 360962306a36Sopenharmony_ci new_fltr); 361062306a36Sopenharmony_ci } else { 361162306a36Sopenharmony_ci /* If VLAN rule exists and VSI list being used by this rule is 361262306a36Sopenharmony_ci * referenced by more than 1 VLAN rule. Then create a new VSI 361362306a36Sopenharmony_ci * list appending previous VSI with new VSI and update existing 361462306a36Sopenharmony_ci * VLAN rule to point to new VSI list ID 361562306a36Sopenharmony_ci */ 361662306a36Sopenharmony_ci struct ice_fltr_info tmp_fltr; 361762306a36Sopenharmony_ci u16 vsi_handle_arr[2]; 361862306a36Sopenharmony_ci u16 cur_handle; 361962306a36Sopenharmony_ci 362062306a36Sopenharmony_ci /* Current implementation only supports reusing VSI list with 362162306a36Sopenharmony_ci * one VSI count. We should never hit below condition 362262306a36Sopenharmony_ci */ 362362306a36Sopenharmony_ci if (v_list_itr->vsi_count > 1 && 362462306a36Sopenharmony_ci v_list_itr->vsi_list_info->ref_cnt > 1) { 362562306a36Sopenharmony_ci ice_debug(hw, ICE_DBG_SW, "Invalid configuration: Optimization to reuse VSI list with more than one VSI is not being done yet\n"); 362662306a36Sopenharmony_ci status = -EIO; 362762306a36Sopenharmony_ci goto exit; 362862306a36Sopenharmony_ci } 362962306a36Sopenharmony_ci 363062306a36Sopenharmony_ci cur_handle = 363162306a36Sopenharmony_ci find_first_bit(v_list_itr->vsi_list_info->vsi_map, 363262306a36Sopenharmony_ci ICE_MAX_VSI); 363362306a36Sopenharmony_ci 363462306a36Sopenharmony_ci /* A rule already exists with the new VSI being added */ 363562306a36Sopenharmony_ci if (cur_handle == vsi_handle) { 363662306a36Sopenharmony_ci status = -EEXIST; 363762306a36Sopenharmony_ci goto exit; 363862306a36Sopenharmony_ci } 363962306a36Sopenharmony_ci 364062306a36Sopenharmony_ci vsi_handle_arr[0] = cur_handle; 364162306a36Sopenharmony_ci vsi_handle_arr[1] = vsi_handle; 364262306a36Sopenharmony_ci status = ice_create_vsi_list_rule(hw, &vsi_handle_arr[0], 2, 364362306a36Sopenharmony_ci &vsi_list_id, lkup_type); 364462306a36Sopenharmony_ci if (status) 364562306a36Sopenharmony_ci goto exit; 364662306a36Sopenharmony_ci 364762306a36Sopenharmony_ci tmp_fltr = v_list_itr->fltr_info; 364862306a36Sopenharmony_ci tmp_fltr.fltr_rule_id = v_list_itr->fltr_info.fltr_rule_id; 364962306a36Sopenharmony_ci tmp_fltr.fwd_id.vsi_list_id = vsi_list_id; 365062306a36Sopenharmony_ci tmp_fltr.fltr_act = ICE_FWD_TO_VSI_LIST; 365162306a36Sopenharmony_ci /* Update the previous switch rule to a new VSI list which 365262306a36Sopenharmony_ci * includes current VSI that is requested 365362306a36Sopenharmony_ci */ 365462306a36Sopenharmony_ci status = ice_update_pkt_fwd_rule(hw, &tmp_fltr); 365562306a36Sopenharmony_ci if (status) 365662306a36Sopenharmony_ci goto exit; 365762306a36Sopenharmony_ci 365862306a36Sopenharmony_ci /* before overriding VSI list map info. decrement ref_cnt of 365962306a36Sopenharmony_ci * previous VSI list 366062306a36Sopenharmony_ci */ 366162306a36Sopenharmony_ci v_list_itr->vsi_list_info->ref_cnt--; 366262306a36Sopenharmony_ci 366362306a36Sopenharmony_ci /* now update to newly created list */ 366462306a36Sopenharmony_ci v_list_itr->fltr_info.fwd_id.vsi_list_id = vsi_list_id; 366562306a36Sopenharmony_ci v_list_itr->vsi_list_info = 366662306a36Sopenharmony_ci ice_create_vsi_list_map(hw, &vsi_handle_arr[0], 2, 366762306a36Sopenharmony_ci vsi_list_id); 366862306a36Sopenharmony_ci v_list_itr->vsi_count++; 366962306a36Sopenharmony_ci } 367062306a36Sopenharmony_ci 367162306a36Sopenharmony_ciexit: 367262306a36Sopenharmony_ci mutex_unlock(rule_lock); 367362306a36Sopenharmony_ci return status; 367462306a36Sopenharmony_ci} 367562306a36Sopenharmony_ci 367662306a36Sopenharmony_ci/** 367762306a36Sopenharmony_ci * ice_add_vlan - Add VLAN based filter rule 367862306a36Sopenharmony_ci * @hw: pointer to the hardware structure 367962306a36Sopenharmony_ci * @v_list: list of VLAN entries and forwarding information 368062306a36Sopenharmony_ci */ 368162306a36Sopenharmony_ciint ice_add_vlan(struct ice_hw *hw, struct list_head *v_list) 368262306a36Sopenharmony_ci{ 368362306a36Sopenharmony_ci struct ice_fltr_list_entry *v_list_itr; 368462306a36Sopenharmony_ci 368562306a36Sopenharmony_ci if (!v_list || !hw) 368662306a36Sopenharmony_ci return -EINVAL; 368762306a36Sopenharmony_ci 368862306a36Sopenharmony_ci list_for_each_entry(v_list_itr, v_list, list_entry) { 368962306a36Sopenharmony_ci if (v_list_itr->fltr_info.lkup_type != ICE_SW_LKUP_VLAN) 369062306a36Sopenharmony_ci return -EINVAL; 369162306a36Sopenharmony_ci v_list_itr->fltr_info.flag = ICE_FLTR_TX; 369262306a36Sopenharmony_ci v_list_itr->status = ice_add_vlan_internal(hw, v_list_itr); 369362306a36Sopenharmony_ci if (v_list_itr->status) 369462306a36Sopenharmony_ci return v_list_itr->status; 369562306a36Sopenharmony_ci } 369662306a36Sopenharmony_ci return 0; 369762306a36Sopenharmony_ci} 369862306a36Sopenharmony_ci 369962306a36Sopenharmony_ci/** 370062306a36Sopenharmony_ci * ice_add_eth_mac - Add ethertype and MAC based filter rule 370162306a36Sopenharmony_ci * @hw: pointer to the hardware structure 370262306a36Sopenharmony_ci * @em_list: list of ether type MAC filter, MAC is optional 370362306a36Sopenharmony_ci * 370462306a36Sopenharmony_ci * This function requires the caller to populate the entries in 370562306a36Sopenharmony_ci * the filter list with the necessary fields (including flags to 370662306a36Sopenharmony_ci * indicate Tx or Rx rules). 370762306a36Sopenharmony_ci */ 370862306a36Sopenharmony_ciint ice_add_eth_mac(struct ice_hw *hw, struct list_head *em_list) 370962306a36Sopenharmony_ci{ 371062306a36Sopenharmony_ci struct ice_fltr_list_entry *em_list_itr; 371162306a36Sopenharmony_ci 371262306a36Sopenharmony_ci if (!em_list || !hw) 371362306a36Sopenharmony_ci return -EINVAL; 371462306a36Sopenharmony_ci 371562306a36Sopenharmony_ci list_for_each_entry(em_list_itr, em_list, list_entry) { 371662306a36Sopenharmony_ci enum ice_sw_lkup_type l_type = 371762306a36Sopenharmony_ci em_list_itr->fltr_info.lkup_type; 371862306a36Sopenharmony_ci 371962306a36Sopenharmony_ci if (l_type != ICE_SW_LKUP_ETHERTYPE_MAC && 372062306a36Sopenharmony_ci l_type != ICE_SW_LKUP_ETHERTYPE) 372162306a36Sopenharmony_ci return -EINVAL; 372262306a36Sopenharmony_ci 372362306a36Sopenharmony_ci em_list_itr->status = ice_add_rule_internal(hw, l_type, 372462306a36Sopenharmony_ci em_list_itr); 372562306a36Sopenharmony_ci if (em_list_itr->status) 372662306a36Sopenharmony_ci return em_list_itr->status; 372762306a36Sopenharmony_ci } 372862306a36Sopenharmony_ci return 0; 372962306a36Sopenharmony_ci} 373062306a36Sopenharmony_ci 373162306a36Sopenharmony_ci/** 373262306a36Sopenharmony_ci * ice_remove_eth_mac - Remove an ethertype (or MAC) based filter rule 373362306a36Sopenharmony_ci * @hw: pointer to the hardware structure 373462306a36Sopenharmony_ci * @em_list: list of ethertype or ethertype MAC entries 373562306a36Sopenharmony_ci */ 373662306a36Sopenharmony_ciint ice_remove_eth_mac(struct ice_hw *hw, struct list_head *em_list) 373762306a36Sopenharmony_ci{ 373862306a36Sopenharmony_ci struct ice_fltr_list_entry *em_list_itr, *tmp; 373962306a36Sopenharmony_ci 374062306a36Sopenharmony_ci if (!em_list || !hw) 374162306a36Sopenharmony_ci return -EINVAL; 374262306a36Sopenharmony_ci 374362306a36Sopenharmony_ci list_for_each_entry_safe(em_list_itr, tmp, em_list, list_entry) { 374462306a36Sopenharmony_ci enum ice_sw_lkup_type l_type = 374562306a36Sopenharmony_ci em_list_itr->fltr_info.lkup_type; 374662306a36Sopenharmony_ci 374762306a36Sopenharmony_ci if (l_type != ICE_SW_LKUP_ETHERTYPE_MAC && 374862306a36Sopenharmony_ci l_type != ICE_SW_LKUP_ETHERTYPE) 374962306a36Sopenharmony_ci return -EINVAL; 375062306a36Sopenharmony_ci 375162306a36Sopenharmony_ci em_list_itr->status = ice_remove_rule_internal(hw, l_type, 375262306a36Sopenharmony_ci em_list_itr); 375362306a36Sopenharmony_ci if (em_list_itr->status) 375462306a36Sopenharmony_ci return em_list_itr->status; 375562306a36Sopenharmony_ci } 375662306a36Sopenharmony_ci return 0; 375762306a36Sopenharmony_ci} 375862306a36Sopenharmony_ci 375962306a36Sopenharmony_ci/** 376062306a36Sopenharmony_ci * ice_rem_sw_rule_info 376162306a36Sopenharmony_ci * @hw: pointer to the hardware structure 376262306a36Sopenharmony_ci * @rule_head: pointer to the switch list structure that we want to delete 376362306a36Sopenharmony_ci */ 376462306a36Sopenharmony_cistatic void 376562306a36Sopenharmony_ciice_rem_sw_rule_info(struct ice_hw *hw, struct list_head *rule_head) 376662306a36Sopenharmony_ci{ 376762306a36Sopenharmony_ci if (!list_empty(rule_head)) { 376862306a36Sopenharmony_ci struct ice_fltr_mgmt_list_entry *entry; 376962306a36Sopenharmony_ci struct ice_fltr_mgmt_list_entry *tmp; 377062306a36Sopenharmony_ci 377162306a36Sopenharmony_ci list_for_each_entry_safe(entry, tmp, rule_head, list_entry) { 377262306a36Sopenharmony_ci list_del(&entry->list_entry); 377362306a36Sopenharmony_ci devm_kfree(ice_hw_to_dev(hw), entry); 377462306a36Sopenharmony_ci } 377562306a36Sopenharmony_ci } 377662306a36Sopenharmony_ci} 377762306a36Sopenharmony_ci 377862306a36Sopenharmony_ci/** 377962306a36Sopenharmony_ci * ice_rem_adv_rule_info 378062306a36Sopenharmony_ci * @hw: pointer to the hardware structure 378162306a36Sopenharmony_ci * @rule_head: pointer to the switch list structure that we want to delete 378262306a36Sopenharmony_ci */ 378362306a36Sopenharmony_cistatic void 378462306a36Sopenharmony_ciice_rem_adv_rule_info(struct ice_hw *hw, struct list_head *rule_head) 378562306a36Sopenharmony_ci{ 378662306a36Sopenharmony_ci struct ice_adv_fltr_mgmt_list_entry *tmp_entry; 378762306a36Sopenharmony_ci struct ice_adv_fltr_mgmt_list_entry *lst_itr; 378862306a36Sopenharmony_ci 378962306a36Sopenharmony_ci if (list_empty(rule_head)) 379062306a36Sopenharmony_ci return; 379162306a36Sopenharmony_ci 379262306a36Sopenharmony_ci list_for_each_entry_safe(lst_itr, tmp_entry, rule_head, list_entry) { 379362306a36Sopenharmony_ci list_del(&lst_itr->list_entry); 379462306a36Sopenharmony_ci devm_kfree(ice_hw_to_dev(hw), lst_itr->lkups); 379562306a36Sopenharmony_ci devm_kfree(ice_hw_to_dev(hw), lst_itr); 379662306a36Sopenharmony_ci } 379762306a36Sopenharmony_ci} 379862306a36Sopenharmony_ci 379962306a36Sopenharmony_ci/** 380062306a36Sopenharmony_ci * ice_cfg_dflt_vsi - change state of VSI to set/clear default 380162306a36Sopenharmony_ci * @pi: pointer to the port_info structure 380262306a36Sopenharmony_ci * @vsi_handle: VSI handle to set as default 380362306a36Sopenharmony_ci * @set: true to add the above mentioned switch rule, false to remove it 380462306a36Sopenharmony_ci * @direction: ICE_FLTR_RX or ICE_FLTR_TX 380562306a36Sopenharmony_ci * 380662306a36Sopenharmony_ci * add filter rule to set/unset given VSI as default VSI for the switch 380762306a36Sopenharmony_ci * (represented by swid) 380862306a36Sopenharmony_ci */ 380962306a36Sopenharmony_ciint 381062306a36Sopenharmony_ciice_cfg_dflt_vsi(struct ice_port_info *pi, u16 vsi_handle, bool set, 381162306a36Sopenharmony_ci u8 direction) 381262306a36Sopenharmony_ci{ 381362306a36Sopenharmony_ci struct ice_fltr_list_entry f_list_entry; 381462306a36Sopenharmony_ci struct ice_fltr_info f_info; 381562306a36Sopenharmony_ci struct ice_hw *hw = pi->hw; 381662306a36Sopenharmony_ci u16 hw_vsi_id; 381762306a36Sopenharmony_ci int status; 381862306a36Sopenharmony_ci 381962306a36Sopenharmony_ci if (!ice_is_vsi_valid(hw, vsi_handle)) 382062306a36Sopenharmony_ci return -EINVAL; 382162306a36Sopenharmony_ci 382262306a36Sopenharmony_ci hw_vsi_id = ice_get_hw_vsi_num(hw, vsi_handle); 382362306a36Sopenharmony_ci 382462306a36Sopenharmony_ci memset(&f_info, 0, sizeof(f_info)); 382562306a36Sopenharmony_ci 382662306a36Sopenharmony_ci f_info.lkup_type = ICE_SW_LKUP_DFLT; 382762306a36Sopenharmony_ci f_info.flag = direction; 382862306a36Sopenharmony_ci f_info.fltr_act = ICE_FWD_TO_VSI; 382962306a36Sopenharmony_ci f_info.fwd_id.hw_vsi_id = hw_vsi_id; 383062306a36Sopenharmony_ci f_info.vsi_handle = vsi_handle; 383162306a36Sopenharmony_ci 383262306a36Sopenharmony_ci if (f_info.flag & ICE_FLTR_RX) { 383362306a36Sopenharmony_ci f_info.src = hw->port_info->lport; 383462306a36Sopenharmony_ci f_info.src_id = ICE_SRC_ID_LPORT; 383562306a36Sopenharmony_ci } else if (f_info.flag & ICE_FLTR_TX) { 383662306a36Sopenharmony_ci f_info.src_id = ICE_SRC_ID_VSI; 383762306a36Sopenharmony_ci f_info.src = hw_vsi_id; 383862306a36Sopenharmony_ci } 383962306a36Sopenharmony_ci f_list_entry.fltr_info = f_info; 384062306a36Sopenharmony_ci 384162306a36Sopenharmony_ci if (set) 384262306a36Sopenharmony_ci status = ice_add_rule_internal(hw, ICE_SW_LKUP_DFLT, 384362306a36Sopenharmony_ci &f_list_entry); 384462306a36Sopenharmony_ci else 384562306a36Sopenharmony_ci status = ice_remove_rule_internal(hw, ICE_SW_LKUP_DFLT, 384662306a36Sopenharmony_ci &f_list_entry); 384762306a36Sopenharmony_ci 384862306a36Sopenharmony_ci return status; 384962306a36Sopenharmony_ci} 385062306a36Sopenharmony_ci 385162306a36Sopenharmony_ci/** 385262306a36Sopenharmony_ci * ice_vsi_uses_fltr - Determine if given VSI uses specified filter 385362306a36Sopenharmony_ci * @fm_entry: filter entry to inspect 385462306a36Sopenharmony_ci * @vsi_handle: VSI handle to compare with filter info 385562306a36Sopenharmony_ci */ 385662306a36Sopenharmony_cistatic bool 385762306a36Sopenharmony_ciice_vsi_uses_fltr(struct ice_fltr_mgmt_list_entry *fm_entry, u16 vsi_handle) 385862306a36Sopenharmony_ci{ 385962306a36Sopenharmony_ci return ((fm_entry->fltr_info.fltr_act == ICE_FWD_TO_VSI && 386062306a36Sopenharmony_ci fm_entry->fltr_info.vsi_handle == vsi_handle) || 386162306a36Sopenharmony_ci (fm_entry->fltr_info.fltr_act == ICE_FWD_TO_VSI_LIST && 386262306a36Sopenharmony_ci fm_entry->vsi_list_info && 386362306a36Sopenharmony_ci (test_bit(vsi_handle, fm_entry->vsi_list_info->vsi_map)))); 386462306a36Sopenharmony_ci} 386562306a36Sopenharmony_ci 386662306a36Sopenharmony_ci/** 386762306a36Sopenharmony_ci * ice_check_if_dflt_vsi - check if VSI is default VSI 386862306a36Sopenharmony_ci * @pi: pointer to the port_info structure 386962306a36Sopenharmony_ci * @vsi_handle: vsi handle to check for in filter list 387062306a36Sopenharmony_ci * @rule_exists: indicates if there are any VSI's in the rule list 387162306a36Sopenharmony_ci * 387262306a36Sopenharmony_ci * checks if the VSI is in a default VSI list, and also indicates 387362306a36Sopenharmony_ci * if the default VSI list is empty 387462306a36Sopenharmony_ci */ 387562306a36Sopenharmony_cibool 387662306a36Sopenharmony_ciice_check_if_dflt_vsi(struct ice_port_info *pi, u16 vsi_handle, 387762306a36Sopenharmony_ci bool *rule_exists) 387862306a36Sopenharmony_ci{ 387962306a36Sopenharmony_ci struct ice_fltr_mgmt_list_entry *fm_entry; 388062306a36Sopenharmony_ci struct ice_sw_recipe *recp_list; 388162306a36Sopenharmony_ci struct list_head *rule_head; 388262306a36Sopenharmony_ci struct mutex *rule_lock; /* Lock to protect filter rule list */ 388362306a36Sopenharmony_ci bool ret = false; 388462306a36Sopenharmony_ci 388562306a36Sopenharmony_ci recp_list = &pi->hw->switch_info->recp_list[ICE_SW_LKUP_DFLT]; 388662306a36Sopenharmony_ci rule_lock = &recp_list->filt_rule_lock; 388762306a36Sopenharmony_ci rule_head = &recp_list->filt_rules; 388862306a36Sopenharmony_ci 388962306a36Sopenharmony_ci mutex_lock(rule_lock); 389062306a36Sopenharmony_ci 389162306a36Sopenharmony_ci if (rule_exists && !list_empty(rule_head)) 389262306a36Sopenharmony_ci *rule_exists = true; 389362306a36Sopenharmony_ci 389462306a36Sopenharmony_ci list_for_each_entry(fm_entry, rule_head, list_entry) { 389562306a36Sopenharmony_ci if (ice_vsi_uses_fltr(fm_entry, vsi_handle)) { 389662306a36Sopenharmony_ci ret = true; 389762306a36Sopenharmony_ci break; 389862306a36Sopenharmony_ci } 389962306a36Sopenharmony_ci } 390062306a36Sopenharmony_ci 390162306a36Sopenharmony_ci mutex_unlock(rule_lock); 390262306a36Sopenharmony_ci 390362306a36Sopenharmony_ci return ret; 390462306a36Sopenharmony_ci} 390562306a36Sopenharmony_ci 390662306a36Sopenharmony_ci/** 390762306a36Sopenharmony_ci * ice_remove_mac - remove a MAC address based filter rule 390862306a36Sopenharmony_ci * @hw: pointer to the hardware structure 390962306a36Sopenharmony_ci * @m_list: list of MAC addresses and forwarding information 391062306a36Sopenharmony_ci * 391162306a36Sopenharmony_ci * This function removes either a MAC filter rule or a specific VSI from a 391262306a36Sopenharmony_ci * VSI list for a multicast MAC address. 391362306a36Sopenharmony_ci * 391462306a36Sopenharmony_ci * Returns -ENOENT if a given entry was not added by ice_add_mac. Caller should 391562306a36Sopenharmony_ci * be aware that this call will only work if all the entries passed into m_list 391662306a36Sopenharmony_ci * were added previously. It will not attempt to do a partial remove of entries 391762306a36Sopenharmony_ci * that were found. 391862306a36Sopenharmony_ci */ 391962306a36Sopenharmony_ciint ice_remove_mac(struct ice_hw *hw, struct list_head *m_list) 392062306a36Sopenharmony_ci{ 392162306a36Sopenharmony_ci struct ice_fltr_list_entry *list_itr, *tmp; 392262306a36Sopenharmony_ci 392362306a36Sopenharmony_ci if (!m_list) 392462306a36Sopenharmony_ci return -EINVAL; 392562306a36Sopenharmony_ci 392662306a36Sopenharmony_ci list_for_each_entry_safe(list_itr, tmp, m_list, list_entry) { 392762306a36Sopenharmony_ci enum ice_sw_lkup_type l_type = list_itr->fltr_info.lkup_type; 392862306a36Sopenharmony_ci u16 vsi_handle; 392962306a36Sopenharmony_ci 393062306a36Sopenharmony_ci if (l_type != ICE_SW_LKUP_MAC) 393162306a36Sopenharmony_ci return -EINVAL; 393262306a36Sopenharmony_ci 393362306a36Sopenharmony_ci vsi_handle = list_itr->fltr_info.vsi_handle; 393462306a36Sopenharmony_ci if (!ice_is_vsi_valid(hw, vsi_handle)) 393562306a36Sopenharmony_ci return -EINVAL; 393662306a36Sopenharmony_ci 393762306a36Sopenharmony_ci list_itr->fltr_info.fwd_id.hw_vsi_id = 393862306a36Sopenharmony_ci ice_get_hw_vsi_num(hw, vsi_handle); 393962306a36Sopenharmony_ci 394062306a36Sopenharmony_ci list_itr->status = ice_remove_rule_internal(hw, 394162306a36Sopenharmony_ci ICE_SW_LKUP_MAC, 394262306a36Sopenharmony_ci list_itr); 394362306a36Sopenharmony_ci if (list_itr->status) 394462306a36Sopenharmony_ci return list_itr->status; 394562306a36Sopenharmony_ci } 394662306a36Sopenharmony_ci return 0; 394762306a36Sopenharmony_ci} 394862306a36Sopenharmony_ci 394962306a36Sopenharmony_ci/** 395062306a36Sopenharmony_ci * ice_remove_vlan - Remove VLAN based filter rule 395162306a36Sopenharmony_ci * @hw: pointer to the hardware structure 395262306a36Sopenharmony_ci * @v_list: list of VLAN entries and forwarding information 395362306a36Sopenharmony_ci */ 395462306a36Sopenharmony_ciint ice_remove_vlan(struct ice_hw *hw, struct list_head *v_list) 395562306a36Sopenharmony_ci{ 395662306a36Sopenharmony_ci struct ice_fltr_list_entry *v_list_itr, *tmp; 395762306a36Sopenharmony_ci 395862306a36Sopenharmony_ci if (!v_list || !hw) 395962306a36Sopenharmony_ci return -EINVAL; 396062306a36Sopenharmony_ci 396162306a36Sopenharmony_ci list_for_each_entry_safe(v_list_itr, tmp, v_list, list_entry) { 396262306a36Sopenharmony_ci enum ice_sw_lkup_type l_type = v_list_itr->fltr_info.lkup_type; 396362306a36Sopenharmony_ci 396462306a36Sopenharmony_ci if (l_type != ICE_SW_LKUP_VLAN) 396562306a36Sopenharmony_ci return -EINVAL; 396662306a36Sopenharmony_ci v_list_itr->status = ice_remove_rule_internal(hw, 396762306a36Sopenharmony_ci ICE_SW_LKUP_VLAN, 396862306a36Sopenharmony_ci v_list_itr); 396962306a36Sopenharmony_ci if (v_list_itr->status) 397062306a36Sopenharmony_ci return v_list_itr->status; 397162306a36Sopenharmony_ci } 397262306a36Sopenharmony_ci return 0; 397362306a36Sopenharmony_ci} 397462306a36Sopenharmony_ci 397562306a36Sopenharmony_ci/** 397662306a36Sopenharmony_ci * ice_add_entry_to_vsi_fltr_list - Add copy of fltr_list_entry to remove list 397762306a36Sopenharmony_ci * @hw: pointer to the hardware structure 397862306a36Sopenharmony_ci * @vsi_handle: VSI handle to remove filters from 397962306a36Sopenharmony_ci * @vsi_list_head: pointer to the list to add entry to 398062306a36Sopenharmony_ci * @fi: pointer to fltr_info of filter entry to copy & add 398162306a36Sopenharmony_ci * 398262306a36Sopenharmony_ci * Helper function, used when creating a list of filters to remove from 398362306a36Sopenharmony_ci * a specific VSI. The entry added to vsi_list_head is a COPY of the 398462306a36Sopenharmony_ci * original filter entry, with the exception of fltr_info.fltr_act and 398562306a36Sopenharmony_ci * fltr_info.fwd_id fields. These are set such that later logic can 398662306a36Sopenharmony_ci * extract which VSI to remove the fltr from, and pass on that information. 398762306a36Sopenharmony_ci */ 398862306a36Sopenharmony_cistatic int 398962306a36Sopenharmony_ciice_add_entry_to_vsi_fltr_list(struct ice_hw *hw, u16 vsi_handle, 399062306a36Sopenharmony_ci struct list_head *vsi_list_head, 399162306a36Sopenharmony_ci struct ice_fltr_info *fi) 399262306a36Sopenharmony_ci{ 399362306a36Sopenharmony_ci struct ice_fltr_list_entry *tmp; 399462306a36Sopenharmony_ci 399562306a36Sopenharmony_ci /* this memory is freed up in the caller function 399662306a36Sopenharmony_ci * once filters for this VSI are removed 399762306a36Sopenharmony_ci */ 399862306a36Sopenharmony_ci tmp = devm_kzalloc(ice_hw_to_dev(hw), sizeof(*tmp), GFP_KERNEL); 399962306a36Sopenharmony_ci if (!tmp) 400062306a36Sopenharmony_ci return -ENOMEM; 400162306a36Sopenharmony_ci 400262306a36Sopenharmony_ci tmp->fltr_info = *fi; 400362306a36Sopenharmony_ci 400462306a36Sopenharmony_ci /* Overwrite these fields to indicate which VSI to remove filter from, 400562306a36Sopenharmony_ci * so find and remove logic can extract the information from the 400662306a36Sopenharmony_ci * list entries. Note that original entries will still have proper 400762306a36Sopenharmony_ci * values. 400862306a36Sopenharmony_ci */ 400962306a36Sopenharmony_ci tmp->fltr_info.fltr_act = ICE_FWD_TO_VSI; 401062306a36Sopenharmony_ci tmp->fltr_info.vsi_handle = vsi_handle; 401162306a36Sopenharmony_ci tmp->fltr_info.fwd_id.hw_vsi_id = ice_get_hw_vsi_num(hw, vsi_handle); 401262306a36Sopenharmony_ci 401362306a36Sopenharmony_ci list_add(&tmp->list_entry, vsi_list_head); 401462306a36Sopenharmony_ci 401562306a36Sopenharmony_ci return 0; 401662306a36Sopenharmony_ci} 401762306a36Sopenharmony_ci 401862306a36Sopenharmony_ci/** 401962306a36Sopenharmony_ci * ice_add_to_vsi_fltr_list - Add VSI filters to the list 402062306a36Sopenharmony_ci * @hw: pointer to the hardware structure 402162306a36Sopenharmony_ci * @vsi_handle: VSI handle to remove filters from 402262306a36Sopenharmony_ci * @lkup_list_head: pointer to the list that has certain lookup type filters 402362306a36Sopenharmony_ci * @vsi_list_head: pointer to the list pertaining to VSI with vsi_handle 402462306a36Sopenharmony_ci * 402562306a36Sopenharmony_ci * Locates all filters in lkup_list_head that are used by the given VSI, 402662306a36Sopenharmony_ci * and adds COPIES of those entries to vsi_list_head (intended to be used 402762306a36Sopenharmony_ci * to remove the listed filters). 402862306a36Sopenharmony_ci * Note that this means all entries in vsi_list_head must be explicitly 402962306a36Sopenharmony_ci * deallocated by the caller when done with list. 403062306a36Sopenharmony_ci */ 403162306a36Sopenharmony_cistatic int 403262306a36Sopenharmony_ciice_add_to_vsi_fltr_list(struct ice_hw *hw, u16 vsi_handle, 403362306a36Sopenharmony_ci struct list_head *lkup_list_head, 403462306a36Sopenharmony_ci struct list_head *vsi_list_head) 403562306a36Sopenharmony_ci{ 403662306a36Sopenharmony_ci struct ice_fltr_mgmt_list_entry *fm_entry; 403762306a36Sopenharmony_ci int status = 0; 403862306a36Sopenharmony_ci 403962306a36Sopenharmony_ci /* check to make sure VSI ID is valid and within boundary */ 404062306a36Sopenharmony_ci if (!ice_is_vsi_valid(hw, vsi_handle)) 404162306a36Sopenharmony_ci return -EINVAL; 404262306a36Sopenharmony_ci 404362306a36Sopenharmony_ci list_for_each_entry(fm_entry, lkup_list_head, list_entry) { 404462306a36Sopenharmony_ci if (!ice_vsi_uses_fltr(fm_entry, vsi_handle)) 404562306a36Sopenharmony_ci continue; 404662306a36Sopenharmony_ci 404762306a36Sopenharmony_ci status = ice_add_entry_to_vsi_fltr_list(hw, vsi_handle, 404862306a36Sopenharmony_ci vsi_list_head, 404962306a36Sopenharmony_ci &fm_entry->fltr_info); 405062306a36Sopenharmony_ci if (status) 405162306a36Sopenharmony_ci return status; 405262306a36Sopenharmony_ci } 405362306a36Sopenharmony_ci return status; 405462306a36Sopenharmony_ci} 405562306a36Sopenharmony_ci 405662306a36Sopenharmony_ci/** 405762306a36Sopenharmony_ci * ice_determine_promisc_mask 405862306a36Sopenharmony_ci * @fi: filter info to parse 405962306a36Sopenharmony_ci * 406062306a36Sopenharmony_ci * Helper function to determine which ICE_PROMISC_ mask corresponds 406162306a36Sopenharmony_ci * to given filter into. 406262306a36Sopenharmony_ci */ 406362306a36Sopenharmony_cistatic u8 ice_determine_promisc_mask(struct ice_fltr_info *fi) 406462306a36Sopenharmony_ci{ 406562306a36Sopenharmony_ci u16 vid = fi->l_data.mac_vlan.vlan_id; 406662306a36Sopenharmony_ci u8 *macaddr = fi->l_data.mac.mac_addr; 406762306a36Sopenharmony_ci bool is_tx_fltr = false; 406862306a36Sopenharmony_ci u8 promisc_mask = 0; 406962306a36Sopenharmony_ci 407062306a36Sopenharmony_ci if (fi->flag == ICE_FLTR_TX) 407162306a36Sopenharmony_ci is_tx_fltr = true; 407262306a36Sopenharmony_ci 407362306a36Sopenharmony_ci if (is_broadcast_ether_addr(macaddr)) 407462306a36Sopenharmony_ci promisc_mask |= is_tx_fltr ? 407562306a36Sopenharmony_ci ICE_PROMISC_BCAST_TX : ICE_PROMISC_BCAST_RX; 407662306a36Sopenharmony_ci else if (is_multicast_ether_addr(macaddr)) 407762306a36Sopenharmony_ci promisc_mask |= is_tx_fltr ? 407862306a36Sopenharmony_ci ICE_PROMISC_MCAST_TX : ICE_PROMISC_MCAST_RX; 407962306a36Sopenharmony_ci else if (is_unicast_ether_addr(macaddr)) 408062306a36Sopenharmony_ci promisc_mask |= is_tx_fltr ? 408162306a36Sopenharmony_ci ICE_PROMISC_UCAST_TX : ICE_PROMISC_UCAST_RX; 408262306a36Sopenharmony_ci if (vid) 408362306a36Sopenharmony_ci promisc_mask |= is_tx_fltr ? 408462306a36Sopenharmony_ci ICE_PROMISC_VLAN_TX : ICE_PROMISC_VLAN_RX; 408562306a36Sopenharmony_ci 408662306a36Sopenharmony_ci return promisc_mask; 408762306a36Sopenharmony_ci} 408862306a36Sopenharmony_ci 408962306a36Sopenharmony_ci/** 409062306a36Sopenharmony_ci * ice_remove_promisc - Remove promisc based filter rules 409162306a36Sopenharmony_ci * @hw: pointer to the hardware structure 409262306a36Sopenharmony_ci * @recp_id: recipe ID for which the rule needs to removed 409362306a36Sopenharmony_ci * @v_list: list of promisc entries 409462306a36Sopenharmony_ci */ 409562306a36Sopenharmony_cistatic int 409662306a36Sopenharmony_ciice_remove_promisc(struct ice_hw *hw, u8 recp_id, struct list_head *v_list) 409762306a36Sopenharmony_ci{ 409862306a36Sopenharmony_ci struct ice_fltr_list_entry *v_list_itr, *tmp; 409962306a36Sopenharmony_ci 410062306a36Sopenharmony_ci list_for_each_entry_safe(v_list_itr, tmp, v_list, list_entry) { 410162306a36Sopenharmony_ci v_list_itr->status = 410262306a36Sopenharmony_ci ice_remove_rule_internal(hw, recp_id, v_list_itr); 410362306a36Sopenharmony_ci if (v_list_itr->status) 410462306a36Sopenharmony_ci return v_list_itr->status; 410562306a36Sopenharmony_ci } 410662306a36Sopenharmony_ci return 0; 410762306a36Sopenharmony_ci} 410862306a36Sopenharmony_ci 410962306a36Sopenharmony_ci/** 411062306a36Sopenharmony_ci * ice_clear_vsi_promisc - clear specified promiscuous mode(s) for given VSI 411162306a36Sopenharmony_ci * @hw: pointer to the hardware structure 411262306a36Sopenharmony_ci * @vsi_handle: VSI handle to clear mode 411362306a36Sopenharmony_ci * @promisc_mask: mask of promiscuous config bits to clear 411462306a36Sopenharmony_ci * @vid: VLAN ID to clear VLAN promiscuous 411562306a36Sopenharmony_ci */ 411662306a36Sopenharmony_ciint 411762306a36Sopenharmony_ciice_clear_vsi_promisc(struct ice_hw *hw, u16 vsi_handle, u8 promisc_mask, 411862306a36Sopenharmony_ci u16 vid) 411962306a36Sopenharmony_ci{ 412062306a36Sopenharmony_ci struct ice_switch_info *sw = hw->switch_info; 412162306a36Sopenharmony_ci struct ice_fltr_list_entry *fm_entry, *tmp; 412262306a36Sopenharmony_ci struct list_head remove_list_head; 412362306a36Sopenharmony_ci struct ice_fltr_mgmt_list_entry *itr; 412462306a36Sopenharmony_ci struct list_head *rule_head; 412562306a36Sopenharmony_ci struct mutex *rule_lock; /* Lock to protect filter rule list */ 412662306a36Sopenharmony_ci int status = 0; 412762306a36Sopenharmony_ci u8 recipe_id; 412862306a36Sopenharmony_ci 412962306a36Sopenharmony_ci if (!ice_is_vsi_valid(hw, vsi_handle)) 413062306a36Sopenharmony_ci return -EINVAL; 413162306a36Sopenharmony_ci 413262306a36Sopenharmony_ci if (promisc_mask & (ICE_PROMISC_VLAN_RX | ICE_PROMISC_VLAN_TX)) 413362306a36Sopenharmony_ci recipe_id = ICE_SW_LKUP_PROMISC_VLAN; 413462306a36Sopenharmony_ci else 413562306a36Sopenharmony_ci recipe_id = ICE_SW_LKUP_PROMISC; 413662306a36Sopenharmony_ci 413762306a36Sopenharmony_ci rule_head = &sw->recp_list[recipe_id].filt_rules; 413862306a36Sopenharmony_ci rule_lock = &sw->recp_list[recipe_id].filt_rule_lock; 413962306a36Sopenharmony_ci 414062306a36Sopenharmony_ci INIT_LIST_HEAD(&remove_list_head); 414162306a36Sopenharmony_ci 414262306a36Sopenharmony_ci mutex_lock(rule_lock); 414362306a36Sopenharmony_ci list_for_each_entry(itr, rule_head, list_entry) { 414462306a36Sopenharmony_ci struct ice_fltr_info *fltr_info; 414562306a36Sopenharmony_ci u8 fltr_promisc_mask = 0; 414662306a36Sopenharmony_ci 414762306a36Sopenharmony_ci if (!ice_vsi_uses_fltr(itr, vsi_handle)) 414862306a36Sopenharmony_ci continue; 414962306a36Sopenharmony_ci fltr_info = &itr->fltr_info; 415062306a36Sopenharmony_ci 415162306a36Sopenharmony_ci if (recipe_id == ICE_SW_LKUP_PROMISC_VLAN && 415262306a36Sopenharmony_ci vid != fltr_info->l_data.mac_vlan.vlan_id) 415362306a36Sopenharmony_ci continue; 415462306a36Sopenharmony_ci 415562306a36Sopenharmony_ci fltr_promisc_mask |= ice_determine_promisc_mask(fltr_info); 415662306a36Sopenharmony_ci 415762306a36Sopenharmony_ci /* Skip if filter is not completely specified by given mask */ 415862306a36Sopenharmony_ci if (fltr_promisc_mask & ~promisc_mask) 415962306a36Sopenharmony_ci continue; 416062306a36Sopenharmony_ci 416162306a36Sopenharmony_ci status = ice_add_entry_to_vsi_fltr_list(hw, vsi_handle, 416262306a36Sopenharmony_ci &remove_list_head, 416362306a36Sopenharmony_ci fltr_info); 416462306a36Sopenharmony_ci if (status) { 416562306a36Sopenharmony_ci mutex_unlock(rule_lock); 416662306a36Sopenharmony_ci goto free_fltr_list; 416762306a36Sopenharmony_ci } 416862306a36Sopenharmony_ci } 416962306a36Sopenharmony_ci mutex_unlock(rule_lock); 417062306a36Sopenharmony_ci 417162306a36Sopenharmony_ci status = ice_remove_promisc(hw, recipe_id, &remove_list_head); 417262306a36Sopenharmony_ci 417362306a36Sopenharmony_cifree_fltr_list: 417462306a36Sopenharmony_ci list_for_each_entry_safe(fm_entry, tmp, &remove_list_head, list_entry) { 417562306a36Sopenharmony_ci list_del(&fm_entry->list_entry); 417662306a36Sopenharmony_ci devm_kfree(ice_hw_to_dev(hw), fm_entry); 417762306a36Sopenharmony_ci } 417862306a36Sopenharmony_ci 417962306a36Sopenharmony_ci return status; 418062306a36Sopenharmony_ci} 418162306a36Sopenharmony_ci 418262306a36Sopenharmony_ci/** 418362306a36Sopenharmony_ci * ice_set_vsi_promisc - set given VSI to given promiscuous mode(s) 418462306a36Sopenharmony_ci * @hw: pointer to the hardware structure 418562306a36Sopenharmony_ci * @vsi_handle: VSI handle to configure 418662306a36Sopenharmony_ci * @promisc_mask: mask of promiscuous config bits 418762306a36Sopenharmony_ci * @vid: VLAN ID to set VLAN promiscuous 418862306a36Sopenharmony_ci */ 418962306a36Sopenharmony_ciint 419062306a36Sopenharmony_ciice_set_vsi_promisc(struct ice_hw *hw, u16 vsi_handle, u8 promisc_mask, u16 vid) 419162306a36Sopenharmony_ci{ 419262306a36Sopenharmony_ci enum { UCAST_FLTR = 1, MCAST_FLTR, BCAST_FLTR }; 419362306a36Sopenharmony_ci struct ice_fltr_list_entry f_list_entry; 419462306a36Sopenharmony_ci struct ice_fltr_info new_fltr; 419562306a36Sopenharmony_ci bool is_tx_fltr; 419662306a36Sopenharmony_ci int status = 0; 419762306a36Sopenharmony_ci u16 hw_vsi_id; 419862306a36Sopenharmony_ci int pkt_type; 419962306a36Sopenharmony_ci u8 recipe_id; 420062306a36Sopenharmony_ci 420162306a36Sopenharmony_ci if (!ice_is_vsi_valid(hw, vsi_handle)) 420262306a36Sopenharmony_ci return -EINVAL; 420362306a36Sopenharmony_ci hw_vsi_id = ice_get_hw_vsi_num(hw, vsi_handle); 420462306a36Sopenharmony_ci 420562306a36Sopenharmony_ci memset(&new_fltr, 0, sizeof(new_fltr)); 420662306a36Sopenharmony_ci 420762306a36Sopenharmony_ci if (promisc_mask & (ICE_PROMISC_VLAN_RX | ICE_PROMISC_VLAN_TX)) { 420862306a36Sopenharmony_ci new_fltr.lkup_type = ICE_SW_LKUP_PROMISC_VLAN; 420962306a36Sopenharmony_ci new_fltr.l_data.mac_vlan.vlan_id = vid; 421062306a36Sopenharmony_ci recipe_id = ICE_SW_LKUP_PROMISC_VLAN; 421162306a36Sopenharmony_ci } else { 421262306a36Sopenharmony_ci new_fltr.lkup_type = ICE_SW_LKUP_PROMISC; 421362306a36Sopenharmony_ci recipe_id = ICE_SW_LKUP_PROMISC; 421462306a36Sopenharmony_ci } 421562306a36Sopenharmony_ci 421662306a36Sopenharmony_ci /* Separate filters must be set for each direction/packet type 421762306a36Sopenharmony_ci * combination, so we will loop over the mask value, store the 421862306a36Sopenharmony_ci * individual type, and clear it out in the input mask as it 421962306a36Sopenharmony_ci * is found. 422062306a36Sopenharmony_ci */ 422162306a36Sopenharmony_ci while (promisc_mask) { 422262306a36Sopenharmony_ci u8 *mac_addr; 422362306a36Sopenharmony_ci 422462306a36Sopenharmony_ci pkt_type = 0; 422562306a36Sopenharmony_ci is_tx_fltr = false; 422662306a36Sopenharmony_ci 422762306a36Sopenharmony_ci if (promisc_mask & ICE_PROMISC_UCAST_RX) { 422862306a36Sopenharmony_ci promisc_mask &= ~ICE_PROMISC_UCAST_RX; 422962306a36Sopenharmony_ci pkt_type = UCAST_FLTR; 423062306a36Sopenharmony_ci } else if (promisc_mask & ICE_PROMISC_UCAST_TX) { 423162306a36Sopenharmony_ci promisc_mask &= ~ICE_PROMISC_UCAST_TX; 423262306a36Sopenharmony_ci pkt_type = UCAST_FLTR; 423362306a36Sopenharmony_ci is_tx_fltr = true; 423462306a36Sopenharmony_ci } else if (promisc_mask & ICE_PROMISC_MCAST_RX) { 423562306a36Sopenharmony_ci promisc_mask &= ~ICE_PROMISC_MCAST_RX; 423662306a36Sopenharmony_ci pkt_type = MCAST_FLTR; 423762306a36Sopenharmony_ci } else if (promisc_mask & ICE_PROMISC_MCAST_TX) { 423862306a36Sopenharmony_ci promisc_mask &= ~ICE_PROMISC_MCAST_TX; 423962306a36Sopenharmony_ci pkt_type = MCAST_FLTR; 424062306a36Sopenharmony_ci is_tx_fltr = true; 424162306a36Sopenharmony_ci } else if (promisc_mask & ICE_PROMISC_BCAST_RX) { 424262306a36Sopenharmony_ci promisc_mask &= ~ICE_PROMISC_BCAST_RX; 424362306a36Sopenharmony_ci pkt_type = BCAST_FLTR; 424462306a36Sopenharmony_ci } else if (promisc_mask & ICE_PROMISC_BCAST_TX) { 424562306a36Sopenharmony_ci promisc_mask &= ~ICE_PROMISC_BCAST_TX; 424662306a36Sopenharmony_ci pkt_type = BCAST_FLTR; 424762306a36Sopenharmony_ci is_tx_fltr = true; 424862306a36Sopenharmony_ci } 424962306a36Sopenharmony_ci 425062306a36Sopenharmony_ci /* Check for VLAN promiscuous flag */ 425162306a36Sopenharmony_ci if (promisc_mask & ICE_PROMISC_VLAN_RX) { 425262306a36Sopenharmony_ci promisc_mask &= ~ICE_PROMISC_VLAN_RX; 425362306a36Sopenharmony_ci } else if (promisc_mask & ICE_PROMISC_VLAN_TX) { 425462306a36Sopenharmony_ci promisc_mask &= ~ICE_PROMISC_VLAN_TX; 425562306a36Sopenharmony_ci is_tx_fltr = true; 425662306a36Sopenharmony_ci } 425762306a36Sopenharmony_ci 425862306a36Sopenharmony_ci /* Set filter DA based on packet type */ 425962306a36Sopenharmony_ci mac_addr = new_fltr.l_data.mac.mac_addr; 426062306a36Sopenharmony_ci if (pkt_type == BCAST_FLTR) { 426162306a36Sopenharmony_ci eth_broadcast_addr(mac_addr); 426262306a36Sopenharmony_ci } else if (pkt_type == MCAST_FLTR || 426362306a36Sopenharmony_ci pkt_type == UCAST_FLTR) { 426462306a36Sopenharmony_ci /* Use the dummy ether header DA */ 426562306a36Sopenharmony_ci ether_addr_copy(mac_addr, dummy_eth_header); 426662306a36Sopenharmony_ci if (pkt_type == MCAST_FLTR) 426762306a36Sopenharmony_ci mac_addr[0] |= 0x1; /* Set multicast bit */ 426862306a36Sopenharmony_ci } 426962306a36Sopenharmony_ci 427062306a36Sopenharmony_ci /* Need to reset this to zero for all iterations */ 427162306a36Sopenharmony_ci new_fltr.flag = 0; 427262306a36Sopenharmony_ci if (is_tx_fltr) { 427362306a36Sopenharmony_ci new_fltr.flag |= ICE_FLTR_TX; 427462306a36Sopenharmony_ci new_fltr.src = hw_vsi_id; 427562306a36Sopenharmony_ci } else { 427662306a36Sopenharmony_ci new_fltr.flag |= ICE_FLTR_RX; 427762306a36Sopenharmony_ci new_fltr.src = hw->port_info->lport; 427862306a36Sopenharmony_ci } 427962306a36Sopenharmony_ci 428062306a36Sopenharmony_ci new_fltr.fltr_act = ICE_FWD_TO_VSI; 428162306a36Sopenharmony_ci new_fltr.vsi_handle = vsi_handle; 428262306a36Sopenharmony_ci new_fltr.fwd_id.hw_vsi_id = hw_vsi_id; 428362306a36Sopenharmony_ci f_list_entry.fltr_info = new_fltr; 428462306a36Sopenharmony_ci 428562306a36Sopenharmony_ci status = ice_add_rule_internal(hw, recipe_id, &f_list_entry); 428662306a36Sopenharmony_ci if (status) 428762306a36Sopenharmony_ci goto set_promisc_exit; 428862306a36Sopenharmony_ci } 428962306a36Sopenharmony_ci 429062306a36Sopenharmony_ciset_promisc_exit: 429162306a36Sopenharmony_ci return status; 429262306a36Sopenharmony_ci} 429362306a36Sopenharmony_ci 429462306a36Sopenharmony_ci/** 429562306a36Sopenharmony_ci * ice_set_vlan_vsi_promisc 429662306a36Sopenharmony_ci * @hw: pointer to the hardware structure 429762306a36Sopenharmony_ci * @vsi_handle: VSI handle to configure 429862306a36Sopenharmony_ci * @promisc_mask: mask of promiscuous config bits 429962306a36Sopenharmony_ci * @rm_vlan_promisc: Clear VLANs VSI promisc mode 430062306a36Sopenharmony_ci * 430162306a36Sopenharmony_ci * Configure VSI with all associated VLANs to given promiscuous mode(s) 430262306a36Sopenharmony_ci */ 430362306a36Sopenharmony_ciint 430462306a36Sopenharmony_ciice_set_vlan_vsi_promisc(struct ice_hw *hw, u16 vsi_handle, u8 promisc_mask, 430562306a36Sopenharmony_ci bool rm_vlan_promisc) 430662306a36Sopenharmony_ci{ 430762306a36Sopenharmony_ci struct ice_switch_info *sw = hw->switch_info; 430862306a36Sopenharmony_ci struct ice_fltr_list_entry *list_itr, *tmp; 430962306a36Sopenharmony_ci struct list_head vsi_list_head; 431062306a36Sopenharmony_ci struct list_head *vlan_head; 431162306a36Sopenharmony_ci struct mutex *vlan_lock; /* Lock to protect filter rule list */ 431262306a36Sopenharmony_ci u16 vlan_id; 431362306a36Sopenharmony_ci int status; 431462306a36Sopenharmony_ci 431562306a36Sopenharmony_ci INIT_LIST_HEAD(&vsi_list_head); 431662306a36Sopenharmony_ci vlan_lock = &sw->recp_list[ICE_SW_LKUP_VLAN].filt_rule_lock; 431762306a36Sopenharmony_ci vlan_head = &sw->recp_list[ICE_SW_LKUP_VLAN].filt_rules; 431862306a36Sopenharmony_ci mutex_lock(vlan_lock); 431962306a36Sopenharmony_ci status = ice_add_to_vsi_fltr_list(hw, vsi_handle, vlan_head, 432062306a36Sopenharmony_ci &vsi_list_head); 432162306a36Sopenharmony_ci mutex_unlock(vlan_lock); 432262306a36Sopenharmony_ci if (status) 432362306a36Sopenharmony_ci goto free_fltr_list; 432462306a36Sopenharmony_ci 432562306a36Sopenharmony_ci list_for_each_entry(list_itr, &vsi_list_head, list_entry) { 432662306a36Sopenharmony_ci /* Avoid enabling or disabling VLAN zero twice when in double 432762306a36Sopenharmony_ci * VLAN mode 432862306a36Sopenharmony_ci */ 432962306a36Sopenharmony_ci if (ice_is_dvm_ena(hw) && 433062306a36Sopenharmony_ci list_itr->fltr_info.l_data.vlan.tpid == 0) 433162306a36Sopenharmony_ci continue; 433262306a36Sopenharmony_ci 433362306a36Sopenharmony_ci vlan_id = list_itr->fltr_info.l_data.vlan.vlan_id; 433462306a36Sopenharmony_ci if (rm_vlan_promisc) 433562306a36Sopenharmony_ci status = ice_clear_vsi_promisc(hw, vsi_handle, 433662306a36Sopenharmony_ci promisc_mask, vlan_id); 433762306a36Sopenharmony_ci else 433862306a36Sopenharmony_ci status = ice_set_vsi_promisc(hw, vsi_handle, 433962306a36Sopenharmony_ci promisc_mask, vlan_id); 434062306a36Sopenharmony_ci if (status && status != -EEXIST) 434162306a36Sopenharmony_ci break; 434262306a36Sopenharmony_ci } 434362306a36Sopenharmony_ci 434462306a36Sopenharmony_cifree_fltr_list: 434562306a36Sopenharmony_ci list_for_each_entry_safe(list_itr, tmp, &vsi_list_head, list_entry) { 434662306a36Sopenharmony_ci list_del(&list_itr->list_entry); 434762306a36Sopenharmony_ci devm_kfree(ice_hw_to_dev(hw), list_itr); 434862306a36Sopenharmony_ci } 434962306a36Sopenharmony_ci return status; 435062306a36Sopenharmony_ci} 435162306a36Sopenharmony_ci 435262306a36Sopenharmony_ci/** 435362306a36Sopenharmony_ci * ice_remove_vsi_lkup_fltr - Remove lookup type filters for a VSI 435462306a36Sopenharmony_ci * @hw: pointer to the hardware structure 435562306a36Sopenharmony_ci * @vsi_handle: VSI handle to remove filters from 435662306a36Sopenharmony_ci * @lkup: switch rule filter lookup type 435762306a36Sopenharmony_ci */ 435862306a36Sopenharmony_cistatic void 435962306a36Sopenharmony_ciice_remove_vsi_lkup_fltr(struct ice_hw *hw, u16 vsi_handle, 436062306a36Sopenharmony_ci enum ice_sw_lkup_type lkup) 436162306a36Sopenharmony_ci{ 436262306a36Sopenharmony_ci struct ice_switch_info *sw = hw->switch_info; 436362306a36Sopenharmony_ci struct ice_fltr_list_entry *fm_entry; 436462306a36Sopenharmony_ci struct list_head remove_list_head; 436562306a36Sopenharmony_ci struct list_head *rule_head; 436662306a36Sopenharmony_ci struct ice_fltr_list_entry *tmp; 436762306a36Sopenharmony_ci struct mutex *rule_lock; /* Lock to protect filter rule list */ 436862306a36Sopenharmony_ci int status; 436962306a36Sopenharmony_ci 437062306a36Sopenharmony_ci INIT_LIST_HEAD(&remove_list_head); 437162306a36Sopenharmony_ci rule_lock = &sw->recp_list[lkup].filt_rule_lock; 437262306a36Sopenharmony_ci rule_head = &sw->recp_list[lkup].filt_rules; 437362306a36Sopenharmony_ci mutex_lock(rule_lock); 437462306a36Sopenharmony_ci status = ice_add_to_vsi_fltr_list(hw, vsi_handle, rule_head, 437562306a36Sopenharmony_ci &remove_list_head); 437662306a36Sopenharmony_ci mutex_unlock(rule_lock); 437762306a36Sopenharmony_ci if (status) 437862306a36Sopenharmony_ci goto free_fltr_list; 437962306a36Sopenharmony_ci 438062306a36Sopenharmony_ci switch (lkup) { 438162306a36Sopenharmony_ci case ICE_SW_LKUP_MAC: 438262306a36Sopenharmony_ci ice_remove_mac(hw, &remove_list_head); 438362306a36Sopenharmony_ci break; 438462306a36Sopenharmony_ci case ICE_SW_LKUP_VLAN: 438562306a36Sopenharmony_ci ice_remove_vlan(hw, &remove_list_head); 438662306a36Sopenharmony_ci break; 438762306a36Sopenharmony_ci case ICE_SW_LKUP_PROMISC: 438862306a36Sopenharmony_ci case ICE_SW_LKUP_PROMISC_VLAN: 438962306a36Sopenharmony_ci ice_remove_promisc(hw, lkup, &remove_list_head); 439062306a36Sopenharmony_ci break; 439162306a36Sopenharmony_ci case ICE_SW_LKUP_MAC_VLAN: 439262306a36Sopenharmony_ci case ICE_SW_LKUP_ETHERTYPE: 439362306a36Sopenharmony_ci case ICE_SW_LKUP_ETHERTYPE_MAC: 439462306a36Sopenharmony_ci case ICE_SW_LKUP_DFLT: 439562306a36Sopenharmony_ci case ICE_SW_LKUP_LAST: 439662306a36Sopenharmony_ci default: 439762306a36Sopenharmony_ci ice_debug(hw, ICE_DBG_SW, "Unsupported lookup type %d\n", lkup); 439862306a36Sopenharmony_ci break; 439962306a36Sopenharmony_ci } 440062306a36Sopenharmony_ci 440162306a36Sopenharmony_cifree_fltr_list: 440262306a36Sopenharmony_ci list_for_each_entry_safe(fm_entry, tmp, &remove_list_head, list_entry) { 440362306a36Sopenharmony_ci list_del(&fm_entry->list_entry); 440462306a36Sopenharmony_ci devm_kfree(ice_hw_to_dev(hw), fm_entry); 440562306a36Sopenharmony_ci } 440662306a36Sopenharmony_ci} 440762306a36Sopenharmony_ci 440862306a36Sopenharmony_ci/** 440962306a36Sopenharmony_ci * ice_remove_vsi_fltr - Remove all filters for a VSI 441062306a36Sopenharmony_ci * @hw: pointer to the hardware structure 441162306a36Sopenharmony_ci * @vsi_handle: VSI handle to remove filters from 441262306a36Sopenharmony_ci */ 441362306a36Sopenharmony_civoid ice_remove_vsi_fltr(struct ice_hw *hw, u16 vsi_handle) 441462306a36Sopenharmony_ci{ 441562306a36Sopenharmony_ci ice_remove_vsi_lkup_fltr(hw, vsi_handle, ICE_SW_LKUP_MAC); 441662306a36Sopenharmony_ci ice_remove_vsi_lkup_fltr(hw, vsi_handle, ICE_SW_LKUP_MAC_VLAN); 441762306a36Sopenharmony_ci ice_remove_vsi_lkup_fltr(hw, vsi_handle, ICE_SW_LKUP_PROMISC); 441862306a36Sopenharmony_ci ice_remove_vsi_lkup_fltr(hw, vsi_handle, ICE_SW_LKUP_VLAN); 441962306a36Sopenharmony_ci ice_remove_vsi_lkup_fltr(hw, vsi_handle, ICE_SW_LKUP_DFLT); 442062306a36Sopenharmony_ci ice_remove_vsi_lkup_fltr(hw, vsi_handle, ICE_SW_LKUP_ETHERTYPE); 442162306a36Sopenharmony_ci ice_remove_vsi_lkup_fltr(hw, vsi_handle, ICE_SW_LKUP_ETHERTYPE_MAC); 442262306a36Sopenharmony_ci ice_remove_vsi_lkup_fltr(hw, vsi_handle, ICE_SW_LKUP_PROMISC_VLAN); 442362306a36Sopenharmony_ci} 442462306a36Sopenharmony_ci 442562306a36Sopenharmony_ci/** 442662306a36Sopenharmony_ci * ice_alloc_res_cntr - allocating resource counter 442762306a36Sopenharmony_ci * @hw: pointer to the hardware structure 442862306a36Sopenharmony_ci * @type: type of resource 442962306a36Sopenharmony_ci * @alloc_shared: if set it is shared else dedicated 443062306a36Sopenharmony_ci * @num_items: number of entries requested for FD resource type 443162306a36Sopenharmony_ci * @counter_id: counter index returned by AQ call 443262306a36Sopenharmony_ci */ 443362306a36Sopenharmony_ciint 443462306a36Sopenharmony_ciice_alloc_res_cntr(struct ice_hw *hw, u8 type, u8 alloc_shared, u16 num_items, 443562306a36Sopenharmony_ci u16 *counter_id) 443662306a36Sopenharmony_ci{ 443762306a36Sopenharmony_ci struct ice_aqc_alloc_free_res_elem *buf; 443862306a36Sopenharmony_ci u16 buf_len; 443962306a36Sopenharmony_ci int status; 444062306a36Sopenharmony_ci 444162306a36Sopenharmony_ci /* Allocate resource */ 444262306a36Sopenharmony_ci buf_len = struct_size(buf, elem, 1); 444362306a36Sopenharmony_ci buf = kzalloc(buf_len, GFP_KERNEL); 444462306a36Sopenharmony_ci if (!buf) 444562306a36Sopenharmony_ci return -ENOMEM; 444662306a36Sopenharmony_ci 444762306a36Sopenharmony_ci buf->num_elems = cpu_to_le16(num_items); 444862306a36Sopenharmony_ci buf->res_type = cpu_to_le16(((type << ICE_AQC_RES_TYPE_S) & 444962306a36Sopenharmony_ci ICE_AQC_RES_TYPE_M) | alloc_shared); 445062306a36Sopenharmony_ci 445162306a36Sopenharmony_ci status = ice_aq_alloc_free_res(hw, buf, buf_len, ice_aqc_opc_alloc_res); 445262306a36Sopenharmony_ci if (status) 445362306a36Sopenharmony_ci goto exit; 445462306a36Sopenharmony_ci 445562306a36Sopenharmony_ci *counter_id = le16_to_cpu(buf->elem[0].e.sw_resp); 445662306a36Sopenharmony_ci 445762306a36Sopenharmony_ciexit: 445862306a36Sopenharmony_ci kfree(buf); 445962306a36Sopenharmony_ci return status; 446062306a36Sopenharmony_ci} 446162306a36Sopenharmony_ci 446262306a36Sopenharmony_ci/** 446362306a36Sopenharmony_ci * ice_free_res_cntr - free resource counter 446462306a36Sopenharmony_ci * @hw: pointer to the hardware structure 446562306a36Sopenharmony_ci * @type: type of resource 446662306a36Sopenharmony_ci * @alloc_shared: if set it is shared else dedicated 446762306a36Sopenharmony_ci * @num_items: number of entries to be freed for FD resource type 446862306a36Sopenharmony_ci * @counter_id: counter ID resource which needs to be freed 446962306a36Sopenharmony_ci */ 447062306a36Sopenharmony_ciint 447162306a36Sopenharmony_ciice_free_res_cntr(struct ice_hw *hw, u8 type, u8 alloc_shared, u16 num_items, 447262306a36Sopenharmony_ci u16 counter_id) 447362306a36Sopenharmony_ci{ 447462306a36Sopenharmony_ci struct ice_aqc_alloc_free_res_elem *buf; 447562306a36Sopenharmony_ci u16 buf_len; 447662306a36Sopenharmony_ci int status; 447762306a36Sopenharmony_ci 447862306a36Sopenharmony_ci /* Free resource */ 447962306a36Sopenharmony_ci buf_len = struct_size(buf, elem, 1); 448062306a36Sopenharmony_ci buf = kzalloc(buf_len, GFP_KERNEL); 448162306a36Sopenharmony_ci if (!buf) 448262306a36Sopenharmony_ci return -ENOMEM; 448362306a36Sopenharmony_ci 448462306a36Sopenharmony_ci buf->num_elems = cpu_to_le16(num_items); 448562306a36Sopenharmony_ci buf->res_type = cpu_to_le16(((type << ICE_AQC_RES_TYPE_S) & 448662306a36Sopenharmony_ci ICE_AQC_RES_TYPE_M) | alloc_shared); 448762306a36Sopenharmony_ci buf->elem[0].e.sw_resp = cpu_to_le16(counter_id); 448862306a36Sopenharmony_ci 448962306a36Sopenharmony_ci status = ice_aq_alloc_free_res(hw, buf, buf_len, ice_aqc_opc_free_res); 449062306a36Sopenharmony_ci if (status) 449162306a36Sopenharmony_ci ice_debug(hw, ICE_DBG_SW, "counter resource could not be freed\n"); 449262306a36Sopenharmony_ci 449362306a36Sopenharmony_ci kfree(buf); 449462306a36Sopenharmony_ci return status; 449562306a36Sopenharmony_ci} 449662306a36Sopenharmony_ci 449762306a36Sopenharmony_ci#define ICE_PROTOCOL_ENTRY(id, ...) { \ 449862306a36Sopenharmony_ci .prot_type = id, \ 449962306a36Sopenharmony_ci .offs = {__VA_ARGS__}, \ 450062306a36Sopenharmony_ci} 450162306a36Sopenharmony_ci 450262306a36Sopenharmony_ci/** 450362306a36Sopenharmony_ci * ice_share_res - set a resource as shared or dedicated 450462306a36Sopenharmony_ci * @hw: hw struct of original owner of resource 450562306a36Sopenharmony_ci * @type: resource type 450662306a36Sopenharmony_ci * @shared: is the resource being set to shared 450762306a36Sopenharmony_ci * @res_id: resource id (descriptor) 450862306a36Sopenharmony_ci */ 450962306a36Sopenharmony_ciint ice_share_res(struct ice_hw *hw, u16 type, u8 shared, u16 res_id) 451062306a36Sopenharmony_ci{ 451162306a36Sopenharmony_ci struct ice_aqc_alloc_free_res_elem *buf; 451262306a36Sopenharmony_ci u16 buf_len; 451362306a36Sopenharmony_ci int status; 451462306a36Sopenharmony_ci 451562306a36Sopenharmony_ci buf_len = struct_size(buf, elem, 1); 451662306a36Sopenharmony_ci buf = kzalloc(buf_len, GFP_KERNEL); 451762306a36Sopenharmony_ci if (!buf) 451862306a36Sopenharmony_ci return -ENOMEM; 451962306a36Sopenharmony_ci 452062306a36Sopenharmony_ci buf->num_elems = cpu_to_le16(1); 452162306a36Sopenharmony_ci if (shared) 452262306a36Sopenharmony_ci buf->res_type = cpu_to_le16(((type << ICE_AQC_RES_TYPE_S) & 452362306a36Sopenharmony_ci ICE_AQC_RES_TYPE_M) | 452462306a36Sopenharmony_ci ICE_AQC_RES_TYPE_FLAG_SHARED); 452562306a36Sopenharmony_ci else 452662306a36Sopenharmony_ci buf->res_type = cpu_to_le16(((type << ICE_AQC_RES_TYPE_S) & 452762306a36Sopenharmony_ci ICE_AQC_RES_TYPE_M) & 452862306a36Sopenharmony_ci ~ICE_AQC_RES_TYPE_FLAG_SHARED); 452962306a36Sopenharmony_ci 453062306a36Sopenharmony_ci buf->elem[0].e.sw_resp = cpu_to_le16(res_id); 453162306a36Sopenharmony_ci status = ice_aq_alloc_free_res(hw, buf, buf_len, 453262306a36Sopenharmony_ci ice_aqc_opc_share_res); 453362306a36Sopenharmony_ci if (status) 453462306a36Sopenharmony_ci ice_debug(hw, ICE_DBG_SW, "Could not set resource type %u id %u to %s\n", 453562306a36Sopenharmony_ci type, res_id, shared ? "SHARED" : "DEDICATED"); 453662306a36Sopenharmony_ci 453762306a36Sopenharmony_ci kfree(buf); 453862306a36Sopenharmony_ci return status; 453962306a36Sopenharmony_ci} 454062306a36Sopenharmony_ci 454162306a36Sopenharmony_ci/* This is mapping table entry that maps every word within a given protocol 454262306a36Sopenharmony_ci * structure to the real byte offset as per the specification of that 454362306a36Sopenharmony_ci * protocol header. 454462306a36Sopenharmony_ci * for example dst address is 3 words in ethertype header and corresponding 454562306a36Sopenharmony_ci * bytes are 0, 2, 3 in the actual packet header and src address is at 4, 6, 8 454662306a36Sopenharmony_ci * IMPORTANT: Every structure part of "ice_prot_hdr" union should have a 454762306a36Sopenharmony_ci * matching entry describing its field. This needs to be updated if new 454862306a36Sopenharmony_ci * structure is added to that union. 454962306a36Sopenharmony_ci */ 455062306a36Sopenharmony_cistatic const struct ice_prot_ext_tbl_entry ice_prot_ext[ICE_PROTOCOL_LAST] = { 455162306a36Sopenharmony_ci ICE_PROTOCOL_ENTRY(ICE_MAC_OFOS, 0, 2, 4, 6, 8, 10, 12), 455262306a36Sopenharmony_ci ICE_PROTOCOL_ENTRY(ICE_MAC_IL, 0, 2, 4, 6, 8, 10, 12), 455362306a36Sopenharmony_ci ICE_PROTOCOL_ENTRY(ICE_ETYPE_OL, 0), 455462306a36Sopenharmony_ci ICE_PROTOCOL_ENTRY(ICE_ETYPE_IL, 0), 455562306a36Sopenharmony_ci ICE_PROTOCOL_ENTRY(ICE_VLAN_OFOS, 2, 0), 455662306a36Sopenharmony_ci ICE_PROTOCOL_ENTRY(ICE_IPV4_OFOS, 0, 2, 4, 6, 8, 10, 12, 14, 16, 18), 455762306a36Sopenharmony_ci ICE_PROTOCOL_ENTRY(ICE_IPV4_IL, 0, 2, 4, 6, 8, 10, 12, 14, 16, 18), 455862306a36Sopenharmony_ci ICE_PROTOCOL_ENTRY(ICE_IPV6_OFOS, 0, 2, 4, 6, 8, 10, 12, 14, 16, 18, 455962306a36Sopenharmony_ci 20, 22, 24, 26, 28, 30, 32, 34, 36, 38), 456062306a36Sopenharmony_ci ICE_PROTOCOL_ENTRY(ICE_IPV6_IL, 0, 2, 4, 6, 8, 10, 12, 14, 16, 18, 20, 456162306a36Sopenharmony_ci 22, 24, 26, 28, 30, 32, 34, 36, 38), 456262306a36Sopenharmony_ci ICE_PROTOCOL_ENTRY(ICE_TCP_IL, 0, 2), 456362306a36Sopenharmony_ci ICE_PROTOCOL_ENTRY(ICE_UDP_OF, 0, 2), 456462306a36Sopenharmony_ci ICE_PROTOCOL_ENTRY(ICE_UDP_ILOS, 0, 2), 456562306a36Sopenharmony_ci ICE_PROTOCOL_ENTRY(ICE_VXLAN, 8, 10, 12, 14), 456662306a36Sopenharmony_ci ICE_PROTOCOL_ENTRY(ICE_GENEVE, 8, 10, 12, 14), 456762306a36Sopenharmony_ci ICE_PROTOCOL_ENTRY(ICE_NVGRE, 0, 2, 4, 6), 456862306a36Sopenharmony_ci ICE_PROTOCOL_ENTRY(ICE_GTP, 8, 10, 12, 14, 16, 18, 20, 22), 456962306a36Sopenharmony_ci ICE_PROTOCOL_ENTRY(ICE_GTP_NO_PAY, 8, 10, 12, 14), 457062306a36Sopenharmony_ci ICE_PROTOCOL_ENTRY(ICE_PPPOE, 0, 2, 4, 6), 457162306a36Sopenharmony_ci ICE_PROTOCOL_ENTRY(ICE_L2TPV3, 0, 2, 4, 6, 8, 10), 457262306a36Sopenharmony_ci ICE_PROTOCOL_ENTRY(ICE_VLAN_EX, 2, 0), 457362306a36Sopenharmony_ci ICE_PROTOCOL_ENTRY(ICE_VLAN_IN, 2, 0), 457462306a36Sopenharmony_ci ICE_PROTOCOL_ENTRY(ICE_HW_METADATA, 457562306a36Sopenharmony_ci ICE_SOURCE_PORT_MDID_OFFSET, 457662306a36Sopenharmony_ci ICE_PTYPE_MDID_OFFSET, 457762306a36Sopenharmony_ci ICE_PACKET_LENGTH_MDID_OFFSET, 457862306a36Sopenharmony_ci ICE_SOURCE_VSI_MDID_OFFSET, 457962306a36Sopenharmony_ci ICE_PKT_VLAN_MDID_OFFSET, 458062306a36Sopenharmony_ci ICE_PKT_TUNNEL_MDID_OFFSET, 458162306a36Sopenharmony_ci ICE_PKT_TCP_MDID_OFFSET, 458262306a36Sopenharmony_ci ICE_PKT_ERROR_MDID_OFFSET), 458362306a36Sopenharmony_ci}; 458462306a36Sopenharmony_ci 458562306a36Sopenharmony_cistatic struct ice_protocol_entry ice_prot_id_tbl[ICE_PROTOCOL_LAST] = { 458662306a36Sopenharmony_ci { ICE_MAC_OFOS, ICE_MAC_OFOS_HW }, 458762306a36Sopenharmony_ci { ICE_MAC_IL, ICE_MAC_IL_HW }, 458862306a36Sopenharmony_ci { ICE_ETYPE_OL, ICE_ETYPE_OL_HW }, 458962306a36Sopenharmony_ci { ICE_ETYPE_IL, ICE_ETYPE_IL_HW }, 459062306a36Sopenharmony_ci { ICE_VLAN_OFOS, ICE_VLAN_OL_HW }, 459162306a36Sopenharmony_ci { ICE_IPV4_OFOS, ICE_IPV4_OFOS_HW }, 459262306a36Sopenharmony_ci { ICE_IPV4_IL, ICE_IPV4_IL_HW }, 459362306a36Sopenharmony_ci { ICE_IPV6_OFOS, ICE_IPV6_OFOS_HW }, 459462306a36Sopenharmony_ci { ICE_IPV6_IL, ICE_IPV6_IL_HW }, 459562306a36Sopenharmony_ci { ICE_TCP_IL, ICE_TCP_IL_HW }, 459662306a36Sopenharmony_ci { ICE_UDP_OF, ICE_UDP_OF_HW }, 459762306a36Sopenharmony_ci { ICE_UDP_ILOS, ICE_UDP_ILOS_HW }, 459862306a36Sopenharmony_ci { ICE_VXLAN, ICE_UDP_OF_HW }, 459962306a36Sopenharmony_ci { ICE_GENEVE, ICE_UDP_OF_HW }, 460062306a36Sopenharmony_ci { ICE_NVGRE, ICE_GRE_OF_HW }, 460162306a36Sopenharmony_ci { ICE_GTP, ICE_UDP_OF_HW }, 460262306a36Sopenharmony_ci { ICE_GTP_NO_PAY, ICE_UDP_ILOS_HW }, 460362306a36Sopenharmony_ci { ICE_PPPOE, ICE_PPPOE_HW }, 460462306a36Sopenharmony_ci { ICE_L2TPV3, ICE_L2TPV3_HW }, 460562306a36Sopenharmony_ci { ICE_VLAN_EX, ICE_VLAN_OF_HW }, 460662306a36Sopenharmony_ci { ICE_VLAN_IN, ICE_VLAN_OL_HW }, 460762306a36Sopenharmony_ci { ICE_HW_METADATA, ICE_META_DATA_ID_HW }, 460862306a36Sopenharmony_ci}; 460962306a36Sopenharmony_ci 461062306a36Sopenharmony_ci/** 461162306a36Sopenharmony_ci * ice_find_recp - find a recipe 461262306a36Sopenharmony_ci * @hw: pointer to the hardware structure 461362306a36Sopenharmony_ci * @lkup_exts: extension sequence to match 461462306a36Sopenharmony_ci * @rinfo: information regarding the rule e.g. priority and action info 461562306a36Sopenharmony_ci * 461662306a36Sopenharmony_ci * Returns index of matching recipe, or ICE_MAX_NUM_RECIPES if not found. 461762306a36Sopenharmony_ci */ 461862306a36Sopenharmony_cistatic u16 461962306a36Sopenharmony_ciice_find_recp(struct ice_hw *hw, struct ice_prot_lkup_ext *lkup_exts, 462062306a36Sopenharmony_ci const struct ice_adv_rule_info *rinfo) 462162306a36Sopenharmony_ci{ 462262306a36Sopenharmony_ci bool refresh_required = true; 462362306a36Sopenharmony_ci struct ice_sw_recipe *recp; 462462306a36Sopenharmony_ci u8 i; 462562306a36Sopenharmony_ci 462662306a36Sopenharmony_ci /* Walk through existing recipes to find a match */ 462762306a36Sopenharmony_ci recp = hw->switch_info->recp_list; 462862306a36Sopenharmony_ci for (i = 0; i < ICE_MAX_NUM_RECIPES; i++) { 462962306a36Sopenharmony_ci /* If recipe was not created for this ID, in SW bookkeeping, 463062306a36Sopenharmony_ci * check if FW has an entry for this recipe. If the FW has an 463162306a36Sopenharmony_ci * entry update it in our SW bookkeeping and continue with the 463262306a36Sopenharmony_ci * matching. 463362306a36Sopenharmony_ci */ 463462306a36Sopenharmony_ci if (!recp[i].recp_created) 463562306a36Sopenharmony_ci if (ice_get_recp_frm_fw(hw, 463662306a36Sopenharmony_ci hw->switch_info->recp_list, i, 463762306a36Sopenharmony_ci &refresh_required)) 463862306a36Sopenharmony_ci continue; 463962306a36Sopenharmony_ci 464062306a36Sopenharmony_ci /* Skip inverse action recipes */ 464162306a36Sopenharmony_ci if (recp[i].root_buf && recp[i].root_buf->content.act_ctrl & 464262306a36Sopenharmony_ci ICE_AQ_RECIPE_ACT_INV_ACT) 464362306a36Sopenharmony_ci continue; 464462306a36Sopenharmony_ci 464562306a36Sopenharmony_ci /* if number of words we are looking for match */ 464662306a36Sopenharmony_ci if (lkup_exts->n_val_words == recp[i].lkup_exts.n_val_words) { 464762306a36Sopenharmony_ci struct ice_fv_word *ar = recp[i].lkup_exts.fv_words; 464862306a36Sopenharmony_ci struct ice_fv_word *be = lkup_exts->fv_words; 464962306a36Sopenharmony_ci u16 *cr = recp[i].lkup_exts.field_mask; 465062306a36Sopenharmony_ci u16 *de = lkup_exts->field_mask; 465162306a36Sopenharmony_ci bool found = true; 465262306a36Sopenharmony_ci u8 pe, qr; 465362306a36Sopenharmony_ci 465462306a36Sopenharmony_ci /* ar, cr, and qr are related to the recipe words, while 465562306a36Sopenharmony_ci * be, de, and pe are related to the lookup words 465662306a36Sopenharmony_ci */ 465762306a36Sopenharmony_ci for (pe = 0; pe < lkup_exts->n_val_words; pe++) { 465862306a36Sopenharmony_ci for (qr = 0; qr < recp[i].lkup_exts.n_val_words; 465962306a36Sopenharmony_ci qr++) { 466062306a36Sopenharmony_ci if (ar[qr].off == be[pe].off && 466162306a36Sopenharmony_ci ar[qr].prot_id == be[pe].prot_id && 466262306a36Sopenharmony_ci cr[qr] == de[pe]) 466362306a36Sopenharmony_ci /* Found the "pe"th word in the 466462306a36Sopenharmony_ci * given recipe 466562306a36Sopenharmony_ci */ 466662306a36Sopenharmony_ci break; 466762306a36Sopenharmony_ci } 466862306a36Sopenharmony_ci /* After walking through all the words in the 466962306a36Sopenharmony_ci * "i"th recipe if "p"th word was not found then 467062306a36Sopenharmony_ci * this recipe is not what we are looking for. 467162306a36Sopenharmony_ci * So break out from this loop and try the next 467262306a36Sopenharmony_ci * recipe 467362306a36Sopenharmony_ci */ 467462306a36Sopenharmony_ci if (qr >= recp[i].lkup_exts.n_val_words) { 467562306a36Sopenharmony_ci found = false; 467662306a36Sopenharmony_ci break; 467762306a36Sopenharmony_ci } 467862306a36Sopenharmony_ci } 467962306a36Sopenharmony_ci /* If for "i"th recipe the found was never set to false 468062306a36Sopenharmony_ci * then it means we found our match 468162306a36Sopenharmony_ci * Also tun type and *_pass_l2 of recipe needs to be 468262306a36Sopenharmony_ci * checked 468362306a36Sopenharmony_ci */ 468462306a36Sopenharmony_ci if (found && recp[i].tun_type == rinfo->tun_type && 468562306a36Sopenharmony_ci recp[i].need_pass_l2 == rinfo->need_pass_l2 && 468662306a36Sopenharmony_ci recp[i].allow_pass_l2 == rinfo->allow_pass_l2) 468762306a36Sopenharmony_ci return i; /* Return the recipe ID */ 468862306a36Sopenharmony_ci } 468962306a36Sopenharmony_ci } 469062306a36Sopenharmony_ci return ICE_MAX_NUM_RECIPES; 469162306a36Sopenharmony_ci} 469262306a36Sopenharmony_ci 469362306a36Sopenharmony_ci/** 469462306a36Sopenharmony_ci * ice_change_proto_id_to_dvm - change proto id in prot_id_tbl 469562306a36Sopenharmony_ci * 469662306a36Sopenharmony_ci * As protocol id for outer vlan is different in dvm and svm, if dvm is 469762306a36Sopenharmony_ci * supported protocol array record for outer vlan has to be modified to 469862306a36Sopenharmony_ci * reflect the value proper for DVM. 469962306a36Sopenharmony_ci */ 470062306a36Sopenharmony_civoid ice_change_proto_id_to_dvm(void) 470162306a36Sopenharmony_ci{ 470262306a36Sopenharmony_ci u8 i; 470362306a36Sopenharmony_ci 470462306a36Sopenharmony_ci for (i = 0; i < ARRAY_SIZE(ice_prot_id_tbl); i++) 470562306a36Sopenharmony_ci if (ice_prot_id_tbl[i].type == ICE_VLAN_OFOS && 470662306a36Sopenharmony_ci ice_prot_id_tbl[i].protocol_id != ICE_VLAN_OF_HW) 470762306a36Sopenharmony_ci ice_prot_id_tbl[i].protocol_id = ICE_VLAN_OF_HW; 470862306a36Sopenharmony_ci} 470962306a36Sopenharmony_ci 471062306a36Sopenharmony_ci/** 471162306a36Sopenharmony_ci * ice_prot_type_to_id - get protocol ID from protocol type 471262306a36Sopenharmony_ci * @type: protocol type 471362306a36Sopenharmony_ci * @id: pointer to variable that will receive the ID 471462306a36Sopenharmony_ci * 471562306a36Sopenharmony_ci * Returns true if found, false otherwise 471662306a36Sopenharmony_ci */ 471762306a36Sopenharmony_cistatic bool ice_prot_type_to_id(enum ice_protocol_type type, u8 *id) 471862306a36Sopenharmony_ci{ 471962306a36Sopenharmony_ci u8 i; 472062306a36Sopenharmony_ci 472162306a36Sopenharmony_ci for (i = 0; i < ARRAY_SIZE(ice_prot_id_tbl); i++) 472262306a36Sopenharmony_ci if (ice_prot_id_tbl[i].type == type) { 472362306a36Sopenharmony_ci *id = ice_prot_id_tbl[i].protocol_id; 472462306a36Sopenharmony_ci return true; 472562306a36Sopenharmony_ci } 472662306a36Sopenharmony_ci return false; 472762306a36Sopenharmony_ci} 472862306a36Sopenharmony_ci 472962306a36Sopenharmony_ci/** 473062306a36Sopenharmony_ci * ice_fill_valid_words - count valid words 473162306a36Sopenharmony_ci * @rule: advanced rule with lookup information 473262306a36Sopenharmony_ci * @lkup_exts: byte offset extractions of the words that are valid 473362306a36Sopenharmony_ci * 473462306a36Sopenharmony_ci * calculate valid words in a lookup rule using mask value 473562306a36Sopenharmony_ci */ 473662306a36Sopenharmony_cistatic u8 473762306a36Sopenharmony_ciice_fill_valid_words(struct ice_adv_lkup_elem *rule, 473862306a36Sopenharmony_ci struct ice_prot_lkup_ext *lkup_exts) 473962306a36Sopenharmony_ci{ 474062306a36Sopenharmony_ci u8 j, word, prot_id, ret_val; 474162306a36Sopenharmony_ci 474262306a36Sopenharmony_ci if (!ice_prot_type_to_id(rule->type, &prot_id)) 474362306a36Sopenharmony_ci return 0; 474462306a36Sopenharmony_ci 474562306a36Sopenharmony_ci word = lkup_exts->n_val_words; 474662306a36Sopenharmony_ci 474762306a36Sopenharmony_ci for (j = 0; j < sizeof(rule->m_u) / sizeof(u16); j++) 474862306a36Sopenharmony_ci if (((u16 *)&rule->m_u)[j] && 474962306a36Sopenharmony_ci rule->type < ARRAY_SIZE(ice_prot_ext)) { 475062306a36Sopenharmony_ci /* No more space to accommodate */ 475162306a36Sopenharmony_ci if (word >= ICE_MAX_CHAIN_WORDS) 475262306a36Sopenharmony_ci return 0; 475362306a36Sopenharmony_ci lkup_exts->fv_words[word].off = 475462306a36Sopenharmony_ci ice_prot_ext[rule->type].offs[j]; 475562306a36Sopenharmony_ci lkup_exts->fv_words[word].prot_id = 475662306a36Sopenharmony_ci ice_prot_id_tbl[rule->type].protocol_id; 475762306a36Sopenharmony_ci lkup_exts->field_mask[word] = 475862306a36Sopenharmony_ci be16_to_cpu(((__force __be16 *)&rule->m_u)[j]); 475962306a36Sopenharmony_ci word++; 476062306a36Sopenharmony_ci } 476162306a36Sopenharmony_ci 476262306a36Sopenharmony_ci ret_val = word - lkup_exts->n_val_words; 476362306a36Sopenharmony_ci lkup_exts->n_val_words = word; 476462306a36Sopenharmony_ci 476562306a36Sopenharmony_ci return ret_val; 476662306a36Sopenharmony_ci} 476762306a36Sopenharmony_ci 476862306a36Sopenharmony_ci/** 476962306a36Sopenharmony_ci * ice_create_first_fit_recp_def - Create a recipe grouping 477062306a36Sopenharmony_ci * @hw: pointer to the hardware structure 477162306a36Sopenharmony_ci * @lkup_exts: an array of protocol header extractions 477262306a36Sopenharmony_ci * @rg_list: pointer to a list that stores new recipe groups 477362306a36Sopenharmony_ci * @recp_cnt: pointer to a variable that stores returned number of recipe groups 477462306a36Sopenharmony_ci * 477562306a36Sopenharmony_ci * Using first fit algorithm, take all the words that are still not done 477662306a36Sopenharmony_ci * and start grouping them in 4-word groups. Each group makes up one 477762306a36Sopenharmony_ci * recipe. 477862306a36Sopenharmony_ci */ 477962306a36Sopenharmony_cistatic int 478062306a36Sopenharmony_ciice_create_first_fit_recp_def(struct ice_hw *hw, 478162306a36Sopenharmony_ci struct ice_prot_lkup_ext *lkup_exts, 478262306a36Sopenharmony_ci struct list_head *rg_list, 478362306a36Sopenharmony_ci u8 *recp_cnt) 478462306a36Sopenharmony_ci{ 478562306a36Sopenharmony_ci struct ice_pref_recipe_group *grp = NULL; 478662306a36Sopenharmony_ci u8 j; 478762306a36Sopenharmony_ci 478862306a36Sopenharmony_ci *recp_cnt = 0; 478962306a36Sopenharmony_ci 479062306a36Sopenharmony_ci /* Walk through every word in the rule to check if it is not done. If so 479162306a36Sopenharmony_ci * then this word needs to be part of a new recipe. 479262306a36Sopenharmony_ci */ 479362306a36Sopenharmony_ci for (j = 0; j < lkup_exts->n_val_words; j++) 479462306a36Sopenharmony_ci if (!test_bit(j, lkup_exts->done)) { 479562306a36Sopenharmony_ci if (!grp || 479662306a36Sopenharmony_ci grp->n_val_pairs == ICE_NUM_WORDS_RECIPE) { 479762306a36Sopenharmony_ci struct ice_recp_grp_entry *entry; 479862306a36Sopenharmony_ci 479962306a36Sopenharmony_ci entry = devm_kzalloc(ice_hw_to_dev(hw), 480062306a36Sopenharmony_ci sizeof(*entry), 480162306a36Sopenharmony_ci GFP_KERNEL); 480262306a36Sopenharmony_ci if (!entry) 480362306a36Sopenharmony_ci return -ENOMEM; 480462306a36Sopenharmony_ci list_add(&entry->l_entry, rg_list); 480562306a36Sopenharmony_ci grp = &entry->r_group; 480662306a36Sopenharmony_ci (*recp_cnt)++; 480762306a36Sopenharmony_ci } 480862306a36Sopenharmony_ci 480962306a36Sopenharmony_ci grp->pairs[grp->n_val_pairs].prot_id = 481062306a36Sopenharmony_ci lkup_exts->fv_words[j].prot_id; 481162306a36Sopenharmony_ci grp->pairs[grp->n_val_pairs].off = 481262306a36Sopenharmony_ci lkup_exts->fv_words[j].off; 481362306a36Sopenharmony_ci grp->mask[grp->n_val_pairs] = lkup_exts->field_mask[j]; 481462306a36Sopenharmony_ci grp->n_val_pairs++; 481562306a36Sopenharmony_ci } 481662306a36Sopenharmony_ci 481762306a36Sopenharmony_ci return 0; 481862306a36Sopenharmony_ci} 481962306a36Sopenharmony_ci 482062306a36Sopenharmony_ci/** 482162306a36Sopenharmony_ci * ice_fill_fv_word_index - fill in the field vector indices for a recipe group 482262306a36Sopenharmony_ci * @hw: pointer to the hardware structure 482362306a36Sopenharmony_ci * @fv_list: field vector with the extraction sequence information 482462306a36Sopenharmony_ci * @rg_list: recipe groupings with protocol-offset pairs 482562306a36Sopenharmony_ci * 482662306a36Sopenharmony_ci * Helper function to fill in the field vector indices for protocol-offset 482762306a36Sopenharmony_ci * pairs. These indexes are then ultimately programmed into a recipe. 482862306a36Sopenharmony_ci */ 482962306a36Sopenharmony_cistatic int 483062306a36Sopenharmony_ciice_fill_fv_word_index(struct ice_hw *hw, struct list_head *fv_list, 483162306a36Sopenharmony_ci struct list_head *rg_list) 483262306a36Sopenharmony_ci{ 483362306a36Sopenharmony_ci struct ice_sw_fv_list_entry *fv; 483462306a36Sopenharmony_ci struct ice_recp_grp_entry *rg; 483562306a36Sopenharmony_ci struct ice_fv_word *fv_ext; 483662306a36Sopenharmony_ci 483762306a36Sopenharmony_ci if (list_empty(fv_list)) 483862306a36Sopenharmony_ci return 0; 483962306a36Sopenharmony_ci 484062306a36Sopenharmony_ci fv = list_first_entry(fv_list, struct ice_sw_fv_list_entry, 484162306a36Sopenharmony_ci list_entry); 484262306a36Sopenharmony_ci fv_ext = fv->fv_ptr->ew; 484362306a36Sopenharmony_ci 484462306a36Sopenharmony_ci list_for_each_entry(rg, rg_list, l_entry) { 484562306a36Sopenharmony_ci u8 i; 484662306a36Sopenharmony_ci 484762306a36Sopenharmony_ci for (i = 0; i < rg->r_group.n_val_pairs; i++) { 484862306a36Sopenharmony_ci struct ice_fv_word *pr; 484962306a36Sopenharmony_ci bool found = false; 485062306a36Sopenharmony_ci u16 mask; 485162306a36Sopenharmony_ci u8 j; 485262306a36Sopenharmony_ci 485362306a36Sopenharmony_ci pr = &rg->r_group.pairs[i]; 485462306a36Sopenharmony_ci mask = rg->r_group.mask[i]; 485562306a36Sopenharmony_ci 485662306a36Sopenharmony_ci for (j = 0; j < hw->blk[ICE_BLK_SW].es.fvw; j++) 485762306a36Sopenharmony_ci if (fv_ext[j].prot_id == pr->prot_id && 485862306a36Sopenharmony_ci fv_ext[j].off == pr->off) { 485962306a36Sopenharmony_ci found = true; 486062306a36Sopenharmony_ci 486162306a36Sopenharmony_ci /* Store index of field vector */ 486262306a36Sopenharmony_ci rg->fv_idx[i] = j; 486362306a36Sopenharmony_ci rg->fv_mask[i] = mask; 486462306a36Sopenharmony_ci break; 486562306a36Sopenharmony_ci } 486662306a36Sopenharmony_ci 486762306a36Sopenharmony_ci /* Protocol/offset could not be found, caller gave an 486862306a36Sopenharmony_ci * invalid pair 486962306a36Sopenharmony_ci */ 487062306a36Sopenharmony_ci if (!found) 487162306a36Sopenharmony_ci return -EINVAL; 487262306a36Sopenharmony_ci } 487362306a36Sopenharmony_ci } 487462306a36Sopenharmony_ci 487562306a36Sopenharmony_ci return 0; 487662306a36Sopenharmony_ci} 487762306a36Sopenharmony_ci 487862306a36Sopenharmony_ci/** 487962306a36Sopenharmony_ci * ice_find_free_recp_res_idx - find free result indexes for recipe 488062306a36Sopenharmony_ci * @hw: pointer to hardware structure 488162306a36Sopenharmony_ci * @profiles: bitmap of profiles that will be associated with the new recipe 488262306a36Sopenharmony_ci * @free_idx: pointer to variable to receive the free index bitmap 488362306a36Sopenharmony_ci * 488462306a36Sopenharmony_ci * The algorithm used here is: 488562306a36Sopenharmony_ci * 1. When creating a new recipe, create a set P which contains all 488662306a36Sopenharmony_ci * Profiles that will be associated with our new recipe 488762306a36Sopenharmony_ci * 488862306a36Sopenharmony_ci * 2. For each Profile p in set P: 488962306a36Sopenharmony_ci * a. Add all recipes associated with Profile p into set R 489062306a36Sopenharmony_ci * b. Optional : PossibleIndexes &= profile[p].possibleIndexes 489162306a36Sopenharmony_ci * [initially PossibleIndexes should be 0xFFFFFFFFFFFFFFFF] 489262306a36Sopenharmony_ci * i. Or just assume they all have the same possible indexes: 489362306a36Sopenharmony_ci * 44, 45, 46, 47 489462306a36Sopenharmony_ci * i.e., PossibleIndexes = 0x0000F00000000000 489562306a36Sopenharmony_ci * 489662306a36Sopenharmony_ci * 3. For each Recipe r in set R: 489762306a36Sopenharmony_ci * a. UsedIndexes |= (bitwise or ) recipe[r].res_indexes 489862306a36Sopenharmony_ci * b. FreeIndexes = UsedIndexes ^ PossibleIndexes 489962306a36Sopenharmony_ci * 490062306a36Sopenharmony_ci * FreeIndexes will contain the bits indicating the indexes free for use, 490162306a36Sopenharmony_ci * then the code needs to update the recipe[r].used_result_idx_bits to 490262306a36Sopenharmony_ci * indicate which indexes were selected for use by this recipe. 490362306a36Sopenharmony_ci */ 490462306a36Sopenharmony_cistatic u16 490562306a36Sopenharmony_ciice_find_free_recp_res_idx(struct ice_hw *hw, const unsigned long *profiles, 490662306a36Sopenharmony_ci unsigned long *free_idx) 490762306a36Sopenharmony_ci{ 490862306a36Sopenharmony_ci DECLARE_BITMAP(possible_idx, ICE_MAX_FV_WORDS); 490962306a36Sopenharmony_ci DECLARE_BITMAP(recipes, ICE_MAX_NUM_RECIPES); 491062306a36Sopenharmony_ci DECLARE_BITMAP(used_idx, ICE_MAX_FV_WORDS); 491162306a36Sopenharmony_ci u16 bit; 491262306a36Sopenharmony_ci 491362306a36Sopenharmony_ci bitmap_zero(recipes, ICE_MAX_NUM_RECIPES); 491462306a36Sopenharmony_ci bitmap_zero(used_idx, ICE_MAX_FV_WORDS); 491562306a36Sopenharmony_ci 491662306a36Sopenharmony_ci bitmap_fill(possible_idx, ICE_MAX_FV_WORDS); 491762306a36Sopenharmony_ci 491862306a36Sopenharmony_ci /* For each profile we are going to associate the recipe with, add the 491962306a36Sopenharmony_ci * recipes that are associated with that profile. This will give us 492062306a36Sopenharmony_ci * the set of recipes that our recipe may collide with. Also, determine 492162306a36Sopenharmony_ci * what possible result indexes are usable given this set of profiles. 492262306a36Sopenharmony_ci */ 492362306a36Sopenharmony_ci for_each_set_bit(bit, profiles, ICE_MAX_NUM_PROFILES) { 492462306a36Sopenharmony_ci bitmap_or(recipes, recipes, profile_to_recipe[bit], 492562306a36Sopenharmony_ci ICE_MAX_NUM_RECIPES); 492662306a36Sopenharmony_ci bitmap_and(possible_idx, possible_idx, 492762306a36Sopenharmony_ci hw->switch_info->prof_res_bm[bit], 492862306a36Sopenharmony_ci ICE_MAX_FV_WORDS); 492962306a36Sopenharmony_ci } 493062306a36Sopenharmony_ci 493162306a36Sopenharmony_ci /* For each recipe that our new recipe may collide with, determine 493262306a36Sopenharmony_ci * which indexes have been used. 493362306a36Sopenharmony_ci */ 493462306a36Sopenharmony_ci for_each_set_bit(bit, recipes, ICE_MAX_NUM_RECIPES) 493562306a36Sopenharmony_ci bitmap_or(used_idx, used_idx, 493662306a36Sopenharmony_ci hw->switch_info->recp_list[bit].res_idxs, 493762306a36Sopenharmony_ci ICE_MAX_FV_WORDS); 493862306a36Sopenharmony_ci 493962306a36Sopenharmony_ci bitmap_xor(free_idx, used_idx, possible_idx, ICE_MAX_FV_WORDS); 494062306a36Sopenharmony_ci 494162306a36Sopenharmony_ci /* return number of free indexes */ 494262306a36Sopenharmony_ci return (u16)bitmap_weight(free_idx, ICE_MAX_FV_WORDS); 494362306a36Sopenharmony_ci} 494462306a36Sopenharmony_ci 494562306a36Sopenharmony_ci/** 494662306a36Sopenharmony_ci * ice_add_sw_recipe - function to call AQ calls to create switch recipe 494762306a36Sopenharmony_ci * @hw: pointer to hardware structure 494862306a36Sopenharmony_ci * @rm: recipe management list entry 494962306a36Sopenharmony_ci * @profiles: bitmap of profiles that will be associated. 495062306a36Sopenharmony_ci */ 495162306a36Sopenharmony_cistatic int 495262306a36Sopenharmony_ciice_add_sw_recipe(struct ice_hw *hw, struct ice_sw_recipe *rm, 495362306a36Sopenharmony_ci unsigned long *profiles) 495462306a36Sopenharmony_ci{ 495562306a36Sopenharmony_ci DECLARE_BITMAP(result_idx_bm, ICE_MAX_FV_WORDS); 495662306a36Sopenharmony_ci struct ice_aqc_recipe_content *content; 495762306a36Sopenharmony_ci struct ice_aqc_recipe_data_elem *tmp; 495862306a36Sopenharmony_ci struct ice_aqc_recipe_data_elem *buf; 495962306a36Sopenharmony_ci struct ice_recp_grp_entry *entry; 496062306a36Sopenharmony_ci u16 free_res_idx; 496162306a36Sopenharmony_ci u16 recipe_count; 496262306a36Sopenharmony_ci u8 chain_idx; 496362306a36Sopenharmony_ci u8 recps = 0; 496462306a36Sopenharmony_ci int status; 496562306a36Sopenharmony_ci 496662306a36Sopenharmony_ci /* When more than one recipe are required, another recipe is needed to 496762306a36Sopenharmony_ci * chain them together. Matching a tunnel metadata ID takes up one of 496862306a36Sopenharmony_ci * the match fields in the chaining recipe reducing the number of 496962306a36Sopenharmony_ci * chained recipes by one. 497062306a36Sopenharmony_ci */ 497162306a36Sopenharmony_ci /* check number of free result indices */ 497262306a36Sopenharmony_ci bitmap_zero(result_idx_bm, ICE_MAX_FV_WORDS); 497362306a36Sopenharmony_ci free_res_idx = ice_find_free_recp_res_idx(hw, profiles, result_idx_bm); 497462306a36Sopenharmony_ci 497562306a36Sopenharmony_ci ice_debug(hw, ICE_DBG_SW, "Result idx slots: %d, need %d\n", 497662306a36Sopenharmony_ci free_res_idx, rm->n_grp_count); 497762306a36Sopenharmony_ci 497862306a36Sopenharmony_ci if (rm->n_grp_count > 1) { 497962306a36Sopenharmony_ci if (rm->n_grp_count > free_res_idx) 498062306a36Sopenharmony_ci return -ENOSPC; 498162306a36Sopenharmony_ci 498262306a36Sopenharmony_ci rm->n_grp_count++; 498362306a36Sopenharmony_ci } 498462306a36Sopenharmony_ci 498562306a36Sopenharmony_ci if (rm->n_grp_count > ICE_MAX_CHAIN_RECIPE) 498662306a36Sopenharmony_ci return -ENOSPC; 498762306a36Sopenharmony_ci 498862306a36Sopenharmony_ci tmp = kcalloc(ICE_MAX_NUM_RECIPES, sizeof(*tmp), GFP_KERNEL); 498962306a36Sopenharmony_ci if (!tmp) 499062306a36Sopenharmony_ci return -ENOMEM; 499162306a36Sopenharmony_ci 499262306a36Sopenharmony_ci buf = devm_kcalloc(ice_hw_to_dev(hw), rm->n_grp_count, sizeof(*buf), 499362306a36Sopenharmony_ci GFP_KERNEL); 499462306a36Sopenharmony_ci if (!buf) { 499562306a36Sopenharmony_ci status = -ENOMEM; 499662306a36Sopenharmony_ci goto err_mem; 499762306a36Sopenharmony_ci } 499862306a36Sopenharmony_ci 499962306a36Sopenharmony_ci bitmap_zero(rm->r_bitmap, ICE_MAX_NUM_RECIPES); 500062306a36Sopenharmony_ci recipe_count = ICE_MAX_NUM_RECIPES; 500162306a36Sopenharmony_ci status = ice_aq_get_recipe(hw, tmp, &recipe_count, ICE_SW_LKUP_MAC, 500262306a36Sopenharmony_ci NULL); 500362306a36Sopenharmony_ci if (status || recipe_count == 0) 500462306a36Sopenharmony_ci goto err_unroll; 500562306a36Sopenharmony_ci 500662306a36Sopenharmony_ci /* Allocate the recipe resources, and configure them according to the 500762306a36Sopenharmony_ci * match fields from protocol headers and extracted field vectors. 500862306a36Sopenharmony_ci */ 500962306a36Sopenharmony_ci chain_idx = find_first_bit(result_idx_bm, ICE_MAX_FV_WORDS); 501062306a36Sopenharmony_ci list_for_each_entry(entry, &rm->rg_list, l_entry) { 501162306a36Sopenharmony_ci u8 i; 501262306a36Sopenharmony_ci 501362306a36Sopenharmony_ci status = ice_alloc_recipe(hw, &entry->rid); 501462306a36Sopenharmony_ci if (status) 501562306a36Sopenharmony_ci goto err_unroll; 501662306a36Sopenharmony_ci 501762306a36Sopenharmony_ci content = &buf[recps].content; 501862306a36Sopenharmony_ci 501962306a36Sopenharmony_ci /* Clear the result index of the located recipe, as this will be 502062306a36Sopenharmony_ci * updated, if needed, later in the recipe creation process. 502162306a36Sopenharmony_ci */ 502262306a36Sopenharmony_ci tmp[0].content.result_indx = 0; 502362306a36Sopenharmony_ci 502462306a36Sopenharmony_ci buf[recps] = tmp[0]; 502562306a36Sopenharmony_ci buf[recps].recipe_indx = (u8)entry->rid; 502662306a36Sopenharmony_ci /* if the recipe is a non-root recipe RID should be programmed 502762306a36Sopenharmony_ci * as 0 for the rules to be applied correctly. 502862306a36Sopenharmony_ci */ 502962306a36Sopenharmony_ci content->rid = 0; 503062306a36Sopenharmony_ci memset(&content->lkup_indx, 0, 503162306a36Sopenharmony_ci sizeof(content->lkup_indx)); 503262306a36Sopenharmony_ci 503362306a36Sopenharmony_ci /* All recipes use look-up index 0 to match switch ID. */ 503462306a36Sopenharmony_ci content->lkup_indx[0] = ICE_AQ_SW_ID_LKUP_IDX; 503562306a36Sopenharmony_ci content->mask[0] = cpu_to_le16(ICE_AQ_SW_ID_LKUP_MASK); 503662306a36Sopenharmony_ci /* Setup lkup_indx 1..4 to INVALID/ignore and set the mask 503762306a36Sopenharmony_ci * to be 0 503862306a36Sopenharmony_ci */ 503962306a36Sopenharmony_ci for (i = 1; i <= ICE_NUM_WORDS_RECIPE; i++) { 504062306a36Sopenharmony_ci content->lkup_indx[i] = 0x80; 504162306a36Sopenharmony_ci content->mask[i] = 0; 504262306a36Sopenharmony_ci } 504362306a36Sopenharmony_ci 504462306a36Sopenharmony_ci for (i = 0; i < entry->r_group.n_val_pairs; i++) { 504562306a36Sopenharmony_ci content->lkup_indx[i + 1] = entry->fv_idx[i]; 504662306a36Sopenharmony_ci content->mask[i + 1] = cpu_to_le16(entry->fv_mask[i]); 504762306a36Sopenharmony_ci } 504862306a36Sopenharmony_ci 504962306a36Sopenharmony_ci if (rm->n_grp_count > 1) { 505062306a36Sopenharmony_ci /* Checks to see if there really is a valid result index 505162306a36Sopenharmony_ci * that can be used. 505262306a36Sopenharmony_ci */ 505362306a36Sopenharmony_ci if (chain_idx >= ICE_MAX_FV_WORDS) { 505462306a36Sopenharmony_ci ice_debug(hw, ICE_DBG_SW, "No chain index available\n"); 505562306a36Sopenharmony_ci status = -ENOSPC; 505662306a36Sopenharmony_ci goto err_unroll; 505762306a36Sopenharmony_ci } 505862306a36Sopenharmony_ci 505962306a36Sopenharmony_ci entry->chain_idx = chain_idx; 506062306a36Sopenharmony_ci content->result_indx = 506162306a36Sopenharmony_ci ICE_AQ_RECIPE_RESULT_EN | 506262306a36Sopenharmony_ci ((chain_idx << ICE_AQ_RECIPE_RESULT_DATA_S) & 506362306a36Sopenharmony_ci ICE_AQ_RECIPE_RESULT_DATA_M); 506462306a36Sopenharmony_ci clear_bit(chain_idx, result_idx_bm); 506562306a36Sopenharmony_ci chain_idx = find_first_bit(result_idx_bm, 506662306a36Sopenharmony_ci ICE_MAX_FV_WORDS); 506762306a36Sopenharmony_ci } 506862306a36Sopenharmony_ci 506962306a36Sopenharmony_ci /* fill recipe dependencies */ 507062306a36Sopenharmony_ci bitmap_zero((unsigned long *)buf[recps].recipe_bitmap, 507162306a36Sopenharmony_ci ICE_MAX_NUM_RECIPES); 507262306a36Sopenharmony_ci set_bit(buf[recps].recipe_indx, 507362306a36Sopenharmony_ci (unsigned long *)buf[recps].recipe_bitmap); 507462306a36Sopenharmony_ci content->act_ctrl_fwd_priority = rm->priority; 507562306a36Sopenharmony_ci 507662306a36Sopenharmony_ci if (rm->need_pass_l2) 507762306a36Sopenharmony_ci content->act_ctrl |= ICE_AQ_RECIPE_ACT_NEED_PASS_L2; 507862306a36Sopenharmony_ci 507962306a36Sopenharmony_ci if (rm->allow_pass_l2) 508062306a36Sopenharmony_ci content->act_ctrl |= ICE_AQ_RECIPE_ACT_ALLOW_PASS_L2; 508162306a36Sopenharmony_ci recps++; 508262306a36Sopenharmony_ci } 508362306a36Sopenharmony_ci 508462306a36Sopenharmony_ci if (rm->n_grp_count == 1) { 508562306a36Sopenharmony_ci rm->root_rid = buf[0].recipe_indx; 508662306a36Sopenharmony_ci set_bit(buf[0].recipe_indx, rm->r_bitmap); 508762306a36Sopenharmony_ci buf[0].content.rid = rm->root_rid | ICE_AQ_RECIPE_ID_IS_ROOT; 508862306a36Sopenharmony_ci if (sizeof(buf[0].recipe_bitmap) >= sizeof(rm->r_bitmap)) { 508962306a36Sopenharmony_ci memcpy(buf[0].recipe_bitmap, rm->r_bitmap, 509062306a36Sopenharmony_ci sizeof(buf[0].recipe_bitmap)); 509162306a36Sopenharmony_ci } else { 509262306a36Sopenharmony_ci status = -EINVAL; 509362306a36Sopenharmony_ci goto err_unroll; 509462306a36Sopenharmony_ci } 509562306a36Sopenharmony_ci /* Applicable only for ROOT_RECIPE, set the fwd_priority for 509662306a36Sopenharmony_ci * the recipe which is getting created if specified 509762306a36Sopenharmony_ci * by user. Usually any advanced switch filter, which results 509862306a36Sopenharmony_ci * into new extraction sequence, ended up creating a new recipe 509962306a36Sopenharmony_ci * of type ROOT and usually recipes are associated with profiles 510062306a36Sopenharmony_ci * Switch rule referreing newly created recipe, needs to have 510162306a36Sopenharmony_ci * either/or 'fwd' or 'join' priority, otherwise switch rule 510262306a36Sopenharmony_ci * evaluation will not happen correctly. In other words, if 510362306a36Sopenharmony_ci * switch rule to be evaluated on priority basis, then recipe 510462306a36Sopenharmony_ci * needs to have priority, otherwise it will be evaluated last. 510562306a36Sopenharmony_ci */ 510662306a36Sopenharmony_ci buf[0].content.act_ctrl_fwd_priority = rm->priority; 510762306a36Sopenharmony_ci } else { 510862306a36Sopenharmony_ci struct ice_recp_grp_entry *last_chain_entry; 510962306a36Sopenharmony_ci u16 rid, i; 511062306a36Sopenharmony_ci 511162306a36Sopenharmony_ci /* Allocate the last recipe that will chain the outcomes of the 511262306a36Sopenharmony_ci * other recipes together 511362306a36Sopenharmony_ci */ 511462306a36Sopenharmony_ci status = ice_alloc_recipe(hw, &rid); 511562306a36Sopenharmony_ci if (status) 511662306a36Sopenharmony_ci goto err_unroll; 511762306a36Sopenharmony_ci 511862306a36Sopenharmony_ci content = &buf[recps].content; 511962306a36Sopenharmony_ci 512062306a36Sopenharmony_ci buf[recps].recipe_indx = (u8)rid; 512162306a36Sopenharmony_ci content->rid = (u8)rid; 512262306a36Sopenharmony_ci content->rid |= ICE_AQ_RECIPE_ID_IS_ROOT; 512362306a36Sopenharmony_ci /* the new entry created should also be part of rg_list to 512462306a36Sopenharmony_ci * make sure we have complete recipe 512562306a36Sopenharmony_ci */ 512662306a36Sopenharmony_ci last_chain_entry = devm_kzalloc(ice_hw_to_dev(hw), 512762306a36Sopenharmony_ci sizeof(*last_chain_entry), 512862306a36Sopenharmony_ci GFP_KERNEL); 512962306a36Sopenharmony_ci if (!last_chain_entry) { 513062306a36Sopenharmony_ci status = -ENOMEM; 513162306a36Sopenharmony_ci goto err_unroll; 513262306a36Sopenharmony_ci } 513362306a36Sopenharmony_ci last_chain_entry->rid = rid; 513462306a36Sopenharmony_ci memset(&content->lkup_indx, 0, sizeof(content->lkup_indx)); 513562306a36Sopenharmony_ci /* All recipes use look-up index 0 to match switch ID. */ 513662306a36Sopenharmony_ci content->lkup_indx[0] = ICE_AQ_SW_ID_LKUP_IDX; 513762306a36Sopenharmony_ci content->mask[0] = cpu_to_le16(ICE_AQ_SW_ID_LKUP_MASK); 513862306a36Sopenharmony_ci for (i = 1; i <= ICE_NUM_WORDS_RECIPE; i++) { 513962306a36Sopenharmony_ci content->lkup_indx[i] = ICE_AQ_RECIPE_LKUP_IGNORE; 514062306a36Sopenharmony_ci content->mask[i] = 0; 514162306a36Sopenharmony_ci } 514262306a36Sopenharmony_ci 514362306a36Sopenharmony_ci i = 1; 514462306a36Sopenharmony_ci /* update r_bitmap with the recp that is used for chaining */ 514562306a36Sopenharmony_ci set_bit(rid, rm->r_bitmap); 514662306a36Sopenharmony_ci /* this is the recipe that chains all the other recipes so it 514762306a36Sopenharmony_ci * should not have a chaining ID to indicate the same 514862306a36Sopenharmony_ci */ 514962306a36Sopenharmony_ci last_chain_entry->chain_idx = ICE_INVAL_CHAIN_IND; 515062306a36Sopenharmony_ci list_for_each_entry(entry, &rm->rg_list, l_entry) { 515162306a36Sopenharmony_ci last_chain_entry->fv_idx[i] = entry->chain_idx; 515262306a36Sopenharmony_ci content->lkup_indx[i] = entry->chain_idx; 515362306a36Sopenharmony_ci content->mask[i++] = cpu_to_le16(0xFFFF); 515462306a36Sopenharmony_ci set_bit(entry->rid, rm->r_bitmap); 515562306a36Sopenharmony_ci } 515662306a36Sopenharmony_ci list_add(&last_chain_entry->l_entry, &rm->rg_list); 515762306a36Sopenharmony_ci if (sizeof(buf[recps].recipe_bitmap) >= 515862306a36Sopenharmony_ci sizeof(rm->r_bitmap)) { 515962306a36Sopenharmony_ci memcpy(buf[recps].recipe_bitmap, rm->r_bitmap, 516062306a36Sopenharmony_ci sizeof(buf[recps].recipe_bitmap)); 516162306a36Sopenharmony_ci } else { 516262306a36Sopenharmony_ci status = -EINVAL; 516362306a36Sopenharmony_ci goto err_unroll; 516462306a36Sopenharmony_ci } 516562306a36Sopenharmony_ci content->act_ctrl_fwd_priority = rm->priority; 516662306a36Sopenharmony_ci 516762306a36Sopenharmony_ci recps++; 516862306a36Sopenharmony_ci rm->root_rid = (u8)rid; 516962306a36Sopenharmony_ci } 517062306a36Sopenharmony_ci status = ice_acquire_change_lock(hw, ICE_RES_WRITE); 517162306a36Sopenharmony_ci if (status) 517262306a36Sopenharmony_ci goto err_unroll; 517362306a36Sopenharmony_ci 517462306a36Sopenharmony_ci status = ice_aq_add_recipe(hw, buf, rm->n_grp_count, NULL); 517562306a36Sopenharmony_ci ice_release_change_lock(hw); 517662306a36Sopenharmony_ci if (status) 517762306a36Sopenharmony_ci goto err_unroll; 517862306a36Sopenharmony_ci 517962306a36Sopenharmony_ci /* Every recipe that just got created add it to the recipe 518062306a36Sopenharmony_ci * book keeping list 518162306a36Sopenharmony_ci */ 518262306a36Sopenharmony_ci list_for_each_entry(entry, &rm->rg_list, l_entry) { 518362306a36Sopenharmony_ci struct ice_switch_info *sw = hw->switch_info; 518462306a36Sopenharmony_ci bool is_root, idx_found = false; 518562306a36Sopenharmony_ci struct ice_sw_recipe *recp; 518662306a36Sopenharmony_ci u16 idx, buf_idx = 0; 518762306a36Sopenharmony_ci 518862306a36Sopenharmony_ci /* find buffer index for copying some data */ 518962306a36Sopenharmony_ci for (idx = 0; idx < rm->n_grp_count; idx++) 519062306a36Sopenharmony_ci if (buf[idx].recipe_indx == entry->rid) { 519162306a36Sopenharmony_ci buf_idx = idx; 519262306a36Sopenharmony_ci idx_found = true; 519362306a36Sopenharmony_ci } 519462306a36Sopenharmony_ci 519562306a36Sopenharmony_ci if (!idx_found) { 519662306a36Sopenharmony_ci status = -EIO; 519762306a36Sopenharmony_ci goto err_unroll; 519862306a36Sopenharmony_ci } 519962306a36Sopenharmony_ci 520062306a36Sopenharmony_ci recp = &sw->recp_list[entry->rid]; 520162306a36Sopenharmony_ci is_root = (rm->root_rid == entry->rid); 520262306a36Sopenharmony_ci recp->is_root = is_root; 520362306a36Sopenharmony_ci 520462306a36Sopenharmony_ci recp->root_rid = entry->rid; 520562306a36Sopenharmony_ci recp->big_recp = (is_root && rm->n_grp_count > 1); 520662306a36Sopenharmony_ci 520762306a36Sopenharmony_ci memcpy(&recp->ext_words, entry->r_group.pairs, 520862306a36Sopenharmony_ci entry->r_group.n_val_pairs * sizeof(struct ice_fv_word)); 520962306a36Sopenharmony_ci 521062306a36Sopenharmony_ci memcpy(recp->r_bitmap, buf[buf_idx].recipe_bitmap, 521162306a36Sopenharmony_ci sizeof(recp->r_bitmap)); 521262306a36Sopenharmony_ci 521362306a36Sopenharmony_ci /* Copy non-result fv index values and masks to recipe. This 521462306a36Sopenharmony_ci * call will also update the result recipe bitmask. 521562306a36Sopenharmony_ci */ 521662306a36Sopenharmony_ci ice_collect_result_idx(&buf[buf_idx], recp); 521762306a36Sopenharmony_ci 521862306a36Sopenharmony_ci /* for non-root recipes, also copy to the root, this allows 521962306a36Sopenharmony_ci * easier matching of a complete chained recipe 522062306a36Sopenharmony_ci */ 522162306a36Sopenharmony_ci if (!is_root) 522262306a36Sopenharmony_ci ice_collect_result_idx(&buf[buf_idx], 522362306a36Sopenharmony_ci &sw->recp_list[rm->root_rid]); 522462306a36Sopenharmony_ci 522562306a36Sopenharmony_ci recp->n_ext_words = entry->r_group.n_val_pairs; 522662306a36Sopenharmony_ci recp->chain_idx = entry->chain_idx; 522762306a36Sopenharmony_ci recp->priority = buf[buf_idx].content.act_ctrl_fwd_priority; 522862306a36Sopenharmony_ci recp->n_grp_count = rm->n_grp_count; 522962306a36Sopenharmony_ci recp->tun_type = rm->tun_type; 523062306a36Sopenharmony_ci recp->need_pass_l2 = rm->need_pass_l2; 523162306a36Sopenharmony_ci recp->allow_pass_l2 = rm->allow_pass_l2; 523262306a36Sopenharmony_ci recp->recp_created = true; 523362306a36Sopenharmony_ci } 523462306a36Sopenharmony_ci rm->root_buf = buf; 523562306a36Sopenharmony_ci kfree(tmp); 523662306a36Sopenharmony_ci return status; 523762306a36Sopenharmony_ci 523862306a36Sopenharmony_cierr_unroll: 523962306a36Sopenharmony_cierr_mem: 524062306a36Sopenharmony_ci kfree(tmp); 524162306a36Sopenharmony_ci devm_kfree(ice_hw_to_dev(hw), buf); 524262306a36Sopenharmony_ci return status; 524362306a36Sopenharmony_ci} 524462306a36Sopenharmony_ci 524562306a36Sopenharmony_ci/** 524662306a36Sopenharmony_ci * ice_create_recipe_group - creates recipe group 524762306a36Sopenharmony_ci * @hw: pointer to hardware structure 524862306a36Sopenharmony_ci * @rm: recipe management list entry 524962306a36Sopenharmony_ci * @lkup_exts: lookup elements 525062306a36Sopenharmony_ci */ 525162306a36Sopenharmony_cistatic int 525262306a36Sopenharmony_ciice_create_recipe_group(struct ice_hw *hw, struct ice_sw_recipe *rm, 525362306a36Sopenharmony_ci struct ice_prot_lkup_ext *lkup_exts) 525462306a36Sopenharmony_ci{ 525562306a36Sopenharmony_ci u8 recp_count = 0; 525662306a36Sopenharmony_ci int status; 525762306a36Sopenharmony_ci 525862306a36Sopenharmony_ci rm->n_grp_count = 0; 525962306a36Sopenharmony_ci 526062306a36Sopenharmony_ci /* Create recipes for words that are marked not done by packing them 526162306a36Sopenharmony_ci * as best fit. 526262306a36Sopenharmony_ci */ 526362306a36Sopenharmony_ci status = ice_create_first_fit_recp_def(hw, lkup_exts, 526462306a36Sopenharmony_ci &rm->rg_list, &recp_count); 526562306a36Sopenharmony_ci if (!status) { 526662306a36Sopenharmony_ci rm->n_grp_count += recp_count; 526762306a36Sopenharmony_ci rm->n_ext_words = lkup_exts->n_val_words; 526862306a36Sopenharmony_ci memcpy(&rm->ext_words, lkup_exts->fv_words, 526962306a36Sopenharmony_ci sizeof(rm->ext_words)); 527062306a36Sopenharmony_ci memcpy(rm->word_masks, lkup_exts->field_mask, 527162306a36Sopenharmony_ci sizeof(rm->word_masks)); 527262306a36Sopenharmony_ci } 527362306a36Sopenharmony_ci 527462306a36Sopenharmony_ci return status; 527562306a36Sopenharmony_ci} 527662306a36Sopenharmony_ci 527762306a36Sopenharmony_ci/* ice_get_compat_fv_bitmap - Get compatible field vector bitmap for rule 527862306a36Sopenharmony_ci * @hw: pointer to hardware structure 527962306a36Sopenharmony_ci * @rinfo: other information regarding the rule e.g. priority and action info 528062306a36Sopenharmony_ci * @bm: pointer to memory for returning the bitmap of field vectors 528162306a36Sopenharmony_ci */ 528262306a36Sopenharmony_cistatic void 528362306a36Sopenharmony_ciice_get_compat_fv_bitmap(struct ice_hw *hw, struct ice_adv_rule_info *rinfo, 528462306a36Sopenharmony_ci unsigned long *bm) 528562306a36Sopenharmony_ci{ 528662306a36Sopenharmony_ci enum ice_prof_type prof_type; 528762306a36Sopenharmony_ci 528862306a36Sopenharmony_ci bitmap_zero(bm, ICE_MAX_NUM_PROFILES); 528962306a36Sopenharmony_ci 529062306a36Sopenharmony_ci switch (rinfo->tun_type) { 529162306a36Sopenharmony_ci case ICE_NON_TUN: 529262306a36Sopenharmony_ci prof_type = ICE_PROF_NON_TUN; 529362306a36Sopenharmony_ci break; 529462306a36Sopenharmony_ci case ICE_ALL_TUNNELS: 529562306a36Sopenharmony_ci prof_type = ICE_PROF_TUN_ALL; 529662306a36Sopenharmony_ci break; 529762306a36Sopenharmony_ci case ICE_SW_TUN_GENEVE: 529862306a36Sopenharmony_ci case ICE_SW_TUN_VXLAN: 529962306a36Sopenharmony_ci prof_type = ICE_PROF_TUN_UDP; 530062306a36Sopenharmony_ci break; 530162306a36Sopenharmony_ci case ICE_SW_TUN_NVGRE: 530262306a36Sopenharmony_ci prof_type = ICE_PROF_TUN_GRE; 530362306a36Sopenharmony_ci break; 530462306a36Sopenharmony_ci case ICE_SW_TUN_GTPU: 530562306a36Sopenharmony_ci prof_type = ICE_PROF_TUN_GTPU; 530662306a36Sopenharmony_ci break; 530762306a36Sopenharmony_ci case ICE_SW_TUN_GTPC: 530862306a36Sopenharmony_ci prof_type = ICE_PROF_TUN_GTPC; 530962306a36Sopenharmony_ci break; 531062306a36Sopenharmony_ci case ICE_SW_TUN_AND_NON_TUN: 531162306a36Sopenharmony_ci default: 531262306a36Sopenharmony_ci prof_type = ICE_PROF_ALL; 531362306a36Sopenharmony_ci break; 531462306a36Sopenharmony_ci } 531562306a36Sopenharmony_ci 531662306a36Sopenharmony_ci ice_get_sw_fv_bitmap(hw, prof_type, bm); 531762306a36Sopenharmony_ci} 531862306a36Sopenharmony_ci 531962306a36Sopenharmony_ci/** 532062306a36Sopenharmony_ci * ice_add_adv_recipe - Add an advanced recipe that is not part of the default 532162306a36Sopenharmony_ci * @hw: pointer to hardware structure 532262306a36Sopenharmony_ci * @lkups: lookup elements or match criteria for the advanced recipe, one 532362306a36Sopenharmony_ci * structure per protocol header 532462306a36Sopenharmony_ci * @lkups_cnt: number of protocols 532562306a36Sopenharmony_ci * @rinfo: other information regarding the rule e.g. priority and action info 532662306a36Sopenharmony_ci * @rid: return the recipe ID of the recipe created 532762306a36Sopenharmony_ci */ 532862306a36Sopenharmony_cistatic int 532962306a36Sopenharmony_ciice_add_adv_recipe(struct ice_hw *hw, struct ice_adv_lkup_elem *lkups, 533062306a36Sopenharmony_ci u16 lkups_cnt, struct ice_adv_rule_info *rinfo, u16 *rid) 533162306a36Sopenharmony_ci{ 533262306a36Sopenharmony_ci DECLARE_BITMAP(fv_bitmap, ICE_MAX_NUM_PROFILES); 533362306a36Sopenharmony_ci DECLARE_BITMAP(profiles, ICE_MAX_NUM_PROFILES); 533462306a36Sopenharmony_ci struct ice_prot_lkup_ext *lkup_exts; 533562306a36Sopenharmony_ci struct ice_recp_grp_entry *r_entry; 533662306a36Sopenharmony_ci struct ice_sw_fv_list_entry *fvit; 533762306a36Sopenharmony_ci struct ice_recp_grp_entry *r_tmp; 533862306a36Sopenharmony_ci struct ice_sw_fv_list_entry *tmp; 533962306a36Sopenharmony_ci struct ice_sw_recipe *rm; 534062306a36Sopenharmony_ci int status = 0; 534162306a36Sopenharmony_ci u8 i; 534262306a36Sopenharmony_ci 534362306a36Sopenharmony_ci if (!lkups_cnt) 534462306a36Sopenharmony_ci return -EINVAL; 534562306a36Sopenharmony_ci 534662306a36Sopenharmony_ci lkup_exts = kzalloc(sizeof(*lkup_exts), GFP_KERNEL); 534762306a36Sopenharmony_ci if (!lkup_exts) 534862306a36Sopenharmony_ci return -ENOMEM; 534962306a36Sopenharmony_ci 535062306a36Sopenharmony_ci /* Determine the number of words to be matched and if it exceeds a 535162306a36Sopenharmony_ci * recipe's restrictions 535262306a36Sopenharmony_ci */ 535362306a36Sopenharmony_ci for (i = 0; i < lkups_cnt; i++) { 535462306a36Sopenharmony_ci u16 count; 535562306a36Sopenharmony_ci 535662306a36Sopenharmony_ci if (lkups[i].type >= ICE_PROTOCOL_LAST) { 535762306a36Sopenharmony_ci status = -EIO; 535862306a36Sopenharmony_ci goto err_free_lkup_exts; 535962306a36Sopenharmony_ci } 536062306a36Sopenharmony_ci 536162306a36Sopenharmony_ci count = ice_fill_valid_words(&lkups[i], lkup_exts); 536262306a36Sopenharmony_ci if (!count) { 536362306a36Sopenharmony_ci status = -EIO; 536462306a36Sopenharmony_ci goto err_free_lkup_exts; 536562306a36Sopenharmony_ci } 536662306a36Sopenharmony_ci } 536762306a36Sopenharmony_ci 536862306a36Sopenharmony_ci rm = kzalloc(sizeof(*rm), GFP_KERNEL); 536962306a36Sopenharmony_ci if (!rm) { 537062306a36Sopenharmony_ci status = -ENOMEM; 537162306a36Sopenharmony_ci goto err_free_lkup_exts; 537262306a36Sopenharmony_ci } 537362306a36Sopenharmony_ci 537462306a36Sopenharmony_ci /* Get field vectors that contain fields extracted from all the protocol 537562306a36Sopenharmony_ci * headers being programmed. 537662306a36Sopenharmony_ci */ 537762306a36Sopenharmony_ci INIT_LIST_HEAD(&rm->fv_list); 537862306a36Sopenharmony_ci INIT_LIST_HEAD(&rm->rg_list); 537962306a36Sopenharmony_ci 538062306a36Sopenharmony_ci /* Get bitmap of field vectors (profiles) that are compatible with the 538162306a36Sopenharmony_ci * rule request; only these will be searched in the subsequent call to 538262306a36Sopenharmony_ci * ice_get_sw_fv_list. 538362306a36Sopenharmony_ci */ 538462306a36Sopenharmony_ci ice_get_compat_fv_bitmap(hw, rinfo, fv_bitmap); 538562306a36Sopenharmony_ci 538662306a36Sopenharmony_ci status = ice_get_sw_fv_list(hw, lkup_exts, fv_bitmap, &rm->fv_list); 538762306a36Sopenharmony_ci if (status) 538862306a36Sopenharmony_ci goto err_unroll; 538962306a36Sopenharmony_ci 539062306a36Sopenharmony_ci /* Group match words into recipes using preferred recipe grouping 539162306a36Sopenharmony_ci * criteria. 539262306a36Sopenharmony_ci */ 539362306a36Sopenharmony_ci status = ice_create_recipe_group(hw, rm, lkup_exts); 539462306a36Sopenharmony_ci if (status) 539562306a36Sopenharmony_ci goto err_unroll; 539662306a36Sopenharmony_ci 539762306a36Sopenharmony_ci /* set the recipe priority if specified */ 539862306a36Sopenharmony_ci rm->priority = (u8)rinfo->priority; 539962306a36Sopenharmony_ci 540062306a36Sopenharmony_ci rm->need_pass_l2 = rinfo->need_pass_l2; 540162306a36Sopenharmony_ci rm->allow_pass_l2 = rinfo->allow_pass_l2; 540262306a36Sopenharmony_ci 540362306a36Sopenharmony_ci /* Find offsets from the field vector. Pick the first one for all the 540462306a36Sopenharmony_ci * recipes. 540562306a36Sopenharmony_ci */ 540662306a36Sopenharmony_ci status = ice_fill_fv_word_index(hw, &rm->fv_list, &rm->rg_list); 540762306a36Sopenharmony_ci if (status) 540862306a36Sopenharmony_ci goto err_unroll; 540962306a36Sopenharmony_ci 541062306a36Sopenharmony_ci /* get bitmap of all profiles the recipe will be associated with */ 541162306a36Sopenharmony_ci bitmap_zero(profiles, ICE_MAX_NUM_PROFILES); 541262306a36Sopenharmony_ci list_for_each_entry(fvit, &rm->fv_list, list_entry) { 541362306a36Sopenharmony_ci ice_debug(hw, ICE_DBG_SW, "profile: %d\n", fvit->profile_id); 541462306a36Sopenharmony_ci set_bit((u16)fvit->profile_id, profiles); 541562306a36Sopenharmony_ci } 541662306a36Sopenharmony_ci 541762306a36Sopenharmony_ci /* Look for a recipe which matches our requested fv / mask list */ 541862306a36Sopenharmony_ci *rid = ice_find_recp(hw, lkup_exts, rinfo); 541962306a36Sopenharmony_ci if (*rid < ICE_MAX_NUM_RECIPES) 542062306a36Sopenharmony_ci /* Success if found a recipe that match the existing criteria */ 542162306a36Sopenharmony_ci goto err_unroll; 542262306a36Sopenharmony_ci 542362306a36Sopenharmony_ci rm->tun_type = rinfo->tun_type; 542462306a36Sopenharmony_ci /* Recipe we need does not exist, add a recipe */ 542562306a36Sopenharmony_ci status = ice_add_sw_recipe(hw, rm, profiles); 542662306a36Sopenharmony_ci if (status) 542762306a36Sopenharmony_ci goto err_unroll; 542862306a36Sopenharmony_ci 542962306a36Sopenharmony_ci /* Associate all the recipes created with all the profiles in the 543062306a36Sopenharmony_ci * common field vector. 543162306a36Sopenharmony_ci */ 543262306a36Sopenharmony_ci list_for_each_entry(fvit, &rm->fv_list, list_entry) { 543362306a36Sopenharmony_ci DECLARE_BITMAP(r_bitmap, ICE_MAX_NUM_RECIPES); 543462306a36Sopenharmony_ci u16 j; 543562306a36Sopenharmony_ci 543662306a36Sopenharmony_ci status = ice_aq_get_recipe_to_profile(hw, fvit->profile_id, 543762306a36Sopenharmony_ci (u8 *)r_bitmap, NULL); 543862306a36Sopenharmony_ci if (status) 543962306a36Sopenharmony_ci goto err_unroll; 544062306a36Sopenharmony_ci 544162306a36Sopenharmony_ci bitmap_or(r_bitmap, r_bitmap, rm->r_bitmap, 544262306a36Sopenharmony_ci ICE_MAX_NUM_RECIPES); 544362306a36Sopenharmony_ci status = ice_acquire_change_lock(hw, ICE_RES_WRITE); 544462306a36Sopenharmony_ci if (status) 544562306a36Sopenharmony_ci goto err_unroll; 544662306a36Sopenharmony_ci 544762306a36Sopenharmony_ci status = ice_aq_map_recipe_to_profile(hw, fvit->profile_id, 544862306a36Sopenharmony_ci (u8 *)r_bitmap, 544962306a36Sopenharmony_ci NULL); 545062306a36Sopenharmony_ci ice_release_change_lock(hw); 545162306a36Sopenharmony_ci 545262306a36Sopenharmony_ci if (status) 545362306a36Sopenharmony_ci goto err_unroll; 545462306a36Sopenharmony_ci 545562306a36Sopenharmony_ci /* Update profile to recipe bitmap array */ 545662306a36Sopenharmony_ci bitmap_copy(profile_to_recipe[fvit->profile_id], r_bitmap, 545762306a36Sopenharmony_ci ICE_MAX_NUM_RECIPES); 545862306a36Sopenharmony_ci 545962306a36Sopenharmony_ci /* Update recipe to profile bitmap array */ 546062306a36Sopenharmony_ci for_each_set_bit(j, rm->r_bitmap, ICE_MAX_NUM_RECIPES) 546162306a36Sopenharmony_ci set_bit((u16)fvit->profile_id, recipe_to_profile[j]); 546262306a36Sopenharmony_ci } 546362306a36Sopenharmony_ci 546462306a36Sopenharmony_ci *rid = rm->root_rid; 546562306a36Sopenharmony_ci memcpy(&hw->switch_info->recp_list[*rid].lkup_exts, lkup_exts, 546662306a36Sopenharmony_ci sizeof(*lkup_exts)); 546762306a36Sopenharmony_cierr_unroll: 546862306a36Sopenharmony_ci list_for_each_entry_safe(r_entry, r_tmp, &rm->rg_list, l_entry) { 546962306a36Sopenharmony_ci list_del(&r_entry->l_entry); 547062306a36Sopenharmony_ci devm_kfree(ice_hw_to_dev(hw), r_entry); 547162306a36Sopenharmony_ci } 547262306a36Sopenharmony_ci 547362306a36Sopenharmony_ci list_for_each_entry_safe(fvit, tmp, &rm->fv_list, list_entry) { 547462306a36Sopenharmony_ci list_del(&fvit->list_entry); 547562306a36Sopenharmony_ci devm_kfree(ice_hw_to_dev(hw), fvit); 547662306a36Sopenharmony_ci } 547762306a36Sopenharmony_ci 547862306a36Sopenharmony_ci devm_kfree(ice_hw_to_dev(hw), rm->root_buf); 547962306a36Sopenharmony_ci kfree(rm); 548062306a36Sopenharmony_ci 548162306a36Sopenharmony_cierr_free_lkup_exts: 548262306a36Sopenharmony_ci kfree(lkup_exts); 548362306a36Sopenharmony_ci 548462306a36Sopenharmony_ci return status; 548562306a36Sopenharmony_ci} 548662306a36Sopenharmony_ci 548762306a36Sopenharmony_ci/** 548862306a36Sopenharmony_ci * ice_dummy_packet_add_vlan - insert VLAN header to dummy pkt 548962306a36Sopenharmony_ci * 549062306a36Sopenharmony_ci * @dummy_pkt: dummy packet profile pattern to which VLAN tag(s) will be added 549162306a36Sopenharmony_ci * @num_vlan: number of VLAN tags 549262306a36Sopenharmony_ci */ 549362306a36Sopenharmony_cistatic struct ice_dummy_pkt_profile * 549462306a36Sopenharmony_ciice_dummy_packet_add_vlan(const struct ice_dummy_pkt_profile *dummy_pkt, 549562306a36Sopenharmony_ci u32 num_vlan) 549662306a36Sopenharmony_ci{ 549762306a36Sopenharmony_ci struct ice_dummy_pkt_profile *profile; 549862306a36Sopenharmony_ci struct ice_dummy_pkt_offsets *offsets; 549962306a36Sopenharmony_ci u32 buf_len, off, etype_off, i; 550062306a36Sopenharmony_ci u8 *pkt; 550162306a36Sopenharmony_ci 550262306a36Sopenharmony_ci if (num_vlan < 1 || num_vlan > 2) 550362306a36Sopenharmony_ci return ERR_PTR(-EINVAL); 550462306a36Sopenharmony_ci 550562306a36Sopenharmony_ci off = num_vlan * VLAN_HLEN; 550662306a36Sopenharmony_ci 550762306a36Sopenharmony_ci buf_len = array_size(num_vlan, sizeof(ice_dummy_vlan_packet_offsets)) + 550862306a36Sopenharmony_ci dummy_pkt->offsets_len; 550962306a36Sopenharmony_ci offsets = kzalloc(buf_len, GFP_KERNEL); 551062306a36Sopenharmony_ci if (!offsets) 551162306a36Sopenharmony_ci return ERR_PTR(-ENOMEM); 551262306a36Sopenharmony_ci 551362306a36Sopenharmony_ci offsets[0] = dummy_pkt->offsets[0]; 551462306a36Sopenharmony_ci if (num_vlan == 2) { 551562306a36Sopenharmony_ci offsets[1] = ice_dummy_qinq_packet_offsets[0]; 551662306a36Sopenharmony_ci offsets[2] = ice_dummy_qinq_packet_offsets[1]; 551762306a36Sopenharmony_ci } else if (num_vlan == 1) { 551862306a36Sopenharmony_ci offsets[1] = ice_dummy_vlan_packet_offsets[0]; 551962306a36Sopenharmony_ci } 552062306a36Sopenharmony_ci 552162306a36Sopenharmony_ci for (i = 1; dummy_pkt->offsets[i].type != ICE_PROTOCOL_LAST; i++) { 552262306a36Sopenharmony_ci offsets[i + num_vlan].type = dummy_pkt->offsets[i].type; 552362306a36Sopenharmony_ci offsets[i + num_vlan].offset = 552462306a36Sopenharmony_ci dummy_pkt->offsets[i].offset + off; 552562306a36Sopenharmony_ci } 552662306a36Sopenharmony_ci offsets[i + num_vlan] = dummy_pkt->offsets[i]; 552762306a36Sopenharmony_ci 552862306a36Sopenharmony_ci etype_off = dummy_pkt->offsets[1].offset; 552962306a36Sopenharmony_ci 553062306a36Sopenharmony_ci buf_len = array_size(num_vlan, sizeof(ice_dummy_vlan_packet)) + 553162306a36Sopenharmony_ci dummy_pkt->pkt_len; 553262306a36Sopenharmony_ci pkt = kzalloc(buf_len, GFP_KERNEL); 553362306a36Sopenharmony_ci if (!pkt) { 553462306a36Sopenharmony_ci kfree(offsets); 553562306a36Sopenharmony_ci return ERR_PTR(-ENOMEM); 553662306a36Sopenharmony_ci } 553762306a36Sopenharmony_ci 553862306a36Sopenharmony_ci memcpy(pkt, dummy_pkt->pkt, etype_off); 553962306a36Sopenharmony_ci memcpy(pkt + etype_off, 554062306a36Sopenharmony_ci num_vlan == 2 ? ice_dummy_qinq_packet : ice_dummy_vlan_packet, 554162306a36Sopenharmony_ci off); 554262306a36Sopenharmony_ci memcpy(pkt + etype_off + off, dummy_pkt->pkt + etype_off, 554362306a36Sopenharmony_ci dummy_pkt->pkt_len - etype_off); 554462306a36Sopenharmony_ci 554562306a36Sopenharmony_ci profile = kzalloc(sizeof(*profile), GFP_KERNEL); 554662306a36Sopenharmony_ci if (!profile) { 554762306a36Sopenharmony_ci kfree(offsets); 554862306a36Sopenharmony_ci kfree(pkt); 554962306a36Sopenharmony_ci return ERR_PTR(-ENOMEM); 555062306a36Sopenharmony_ci } 555162306a36Sopenharmony_ci 555262306a36Sopenharmony_ci profile->offsets = offsets; 555362306a36Sopenharmony_ci profile->pkt = pkt; 555462306a36Sopenharmony_ci profile->pkt_len = buf_len; 555562306a36Sopenharmony_ci profile->match |= ICE_PKT_KMALLOC; 555662306a36Sopenharmony_ci 555762306a36Sopenharmony_ci return profile; 555862306a36Sopenharmony_ci} 555962306a36Sopenharmony_ci 556062306a36Sopenharmony_ci/** 556162306a36Sopenharmony_ci * ice_find_dummy_packet - find dummy packet 556262306a36Sopenharmony_ci * 556362306a36Sopenharmony_ci * @lkups: lookup elements or match criteria for the advanced recipe, one 556462306a36Sopenharmony_ci * structure per protocol header 556562306a36Sopenharmony_ci * @lkups_cnt: number of protocols 556662306a36Sopenharmony_ci * @tun_type: tunnel type 556762306a36Sopenharmony_ci * 556862306a36Sopenharmony_ci * Returns the &ice_dummy_pkt_profile corresponding to these lookup params. 556962306a36Sopenharmony_ci */ 557062306a36Sopenharmony_cistatic const struct ice_dummy_pkt_profile * 557162306a36Sopenharmony_ciice_find_dummy_packet(struct ice_adv_lkup_elem *lkups, u16 lkups_cnt, 557262306a36Sopenharmony_ci enum ice_sw_tunnel_type tun_type) 557362306a36Sopenharmony_ci{ 557462306a36Sopenharmony_ci const struct ice_dummy_pkt_profile *ret = ice_dummy_pkt_profiles; 557562306a36Sopenharmony_ci u32 match = 0, vlan_count = 0; 557662306a36Sopenharmony_ci u16 i; 557762306a36Sopenharmony_ci 557862306a36Sopenharmony_ci switch (tun_type) { 557962306a36Sopenharmony_ci case ICE_SW_TUN_GTPC: 558062306a36Sopenharmony_ci match |= ICE_PKT_TUN_GTPC; 558162306a36Sopenharmony_ci break; 558262306a36Sopenharmony_ci case ICE_SW_TUN_GTPU: 558362306a36Sopenharmony_ci match |= ICE_PKT_TUN_GTPU; 558462306a36Sopenharmony_ci break; 558562306a36Sopenharmony_ci case ICE_SW_TUN_NVGRE: 558662306a36Sopenharmony_ci match |= ICE_PKT_TUN_NVGRE; 558762306a36Sopenharmony_ci break; 558862306a36Sopenharmony_ci case ICE_SW_TUN_GENEVE: 558962306a36Sopenharmony_ci case ICE_SW_TUN_VXLAN: 559062306a36Sopenharmony_ci match |= ICE_PKT_TUN_UDP; 559162306a36Sopenharmony_ci break; 559262306a36Sopenharmony_ci default: 559362306a36Sopenharmony_ci break; 559462306a36Sopenharmony_ci } 559562306a36Sopenharmony_ci 559662306a36Sopenharmony_ci for (i = 0; i < lkups_cnt; i++) { 559762306a36Sopenharmony_ci if (lkups[i].type == ICE_UDP_ILOS) 559862306a36Sopenharmony_ci match |= ICE_PKT_INNER_UDP; 559962306a36Sopenharmony_ci else if (lkups[i].type == ICE_TCP_IL) 560062306a36Sopenharmony_ci match |= ICE_PKT_INNER_TCP; 560162306a36Sopenharmony_ci else if (lkups[i].type == ICE_IPV6_OFOS) 560262306a36Sopenharmony_ci match |= ICE_PKT_OUTER_IPV6; 560362306a36Sopenharmony_ci else if (lkups[i].type == ICE_VLAN_OFOS || 560462306a36Sopenharmony_ci lkups[i].type == ICE_VLAN_EX) 560562306a36Sopenharmony_ci vlan_count++; 560662306a36Sopenharmony_ci else if (lkups[i].type == ICE_VLAN_IN) 560762306a36Sopenharmony_ci vlan_count++; 560862306a36Sopenharmony_ci else if (lkups[i].type == ICE_ETYPE_OL && 560962306a36Sopenharmony_ci lkups[i].h_u.ethertype.ethtype_id == 561062306a36Sopenharmony_ci cpu_to_be16(ICE_IPV6_ETHER_ID) && 561162306a36Sopenharmony_ci lkups[i].m_u.ethertype.ethtype_id == 561262306a36Sopenharmony_ci cpu_to_be16(0xFFFF)) 561362306a36Sopenharmony_ci match |= ICE_PKT_OUTER_IPV6; 561462306a36Sopenharmony_ci else if (lkups[i].type == ICE_ETYPE_IL && 561562306a36Sopenharmony_ci lkups[i].h_u.ethertype.ethtype_id == 561662306a36Sopenharmony_ci cpu_to_be16(ICE_IPV6_ETHER_ID) && 561762306a36Sopenharmony_ci lkups[i].m_u.ethertype.ethtype_id == 561862306a36Sopenharmony_ci cpu_to_be16(0xFFFF)) 561962306a36Sopenharmony_ci match |= ICE_PKT_INNER_IPV6; 562062306a36Sopenharmony_ci else if (lkups[i].type == ICE_IPV6_IL) 562162306a36Sopenharmony_ci match |= ICE_PKT_INNER_IPV6; 562262306a36Sopenharmony_ci else if (lkups[i].type == ICE_GTP_NO_PAY) 562362306a36Sopenharmony_ci match |= ICE_PKT_GTP_NOPAY; 562462306a36Sopenharmony_ci else if (lkups[i].type == ICE_PPPOE) { 562562306a36Sopenharmony_ci match |= ICE_PKT_PPPOE; 562662306a36Sopenharmony_ci if (lkups[i].h_u.pppoe_hdr.ppp_prot_id == 562762306a36Sopenharmony_ci htons(PPP_IPV6)) 562862306a36Sopenharmony_ci match |= ICE_PKT_OUTER_IPV6; 562962306a36Sopenharmony_ci } else if (lkups[i].type == ICE_L2TPV3) 563062306a36Sopenharmony_ci match |= ICE_PKT_L2TPV3; 563162306a36Sopenharmony_ci } 563262306a36Sopenharmony_ci 563362306a36Sopenharmony_ci while (ret->match && (match & ret->match) != ret->match) 563462306a36Sopenharmony_ci ret++; 563562306a36Sopenharmony_ci 563662306a36Sopenharmony_ci if (vlan_count != 0) 563762306a36Sopenharmony_ci ret = ice_dummy_packet_add_vlan(ret, vlan_count); 563862306a36Sopenharmony_ci 563962306a36Sopenharmony_ci return ret; 564062306a36Sopenharmony_ci} 564162306a36Sopenharmony_ci 564262306a36Sopenharmony_ci/** 564362306a36Sopenharmony_ci * ice_fill_adv_dummy_packet - fill a dummy packet with given match criteria 564462306a36Sopenharmony_ci * 564562306a36Sopenharmony_ci * @lkups: lookup elements or match criteria for the advanced recipe, one 564662306a36Sopenharmony_ci * structure per protocol header 564762306a36Sopenharmony_ci * @lkups_cnt: number of protocols 564862306a36Sopenharmony_ci * @s_rule: stores rule information from the match criteria 564962306a36Sopenharmony_ci * @profile: dummy packet profile (the template, its size and header offsets) 565062306a36Sopenharmony_ci */ 565162306a36Sopenharmony_cistatic int 565262306a36Sopenharmony_ciice_fill_adv_dummy_packet(struct ice_adv_lkup_elem *lkups, u16 lkups_cnt, 565362306a36Sopenharmony_ci struct ice_sw_rule_lkup_rx_tx *s_rule, 565462306a36Sopenharmony_ci const struct ice_dummy_pkt_profile *profile) 565562306a36Sopenharmony_ci{ 565662306a36Sopenharmony_ci u8 *pkt; 565762306a36Sopenharmony_ci u16 i; 565862306a36Sopenharmony_ci 565962306a36Sopenharmony_ci /* Start with a packet with a pre-defined/dummy content. Then, fill 566062306a36Sopenharmony_ci * in the header values to be looked up or matched. 566162306a36Sopenharmony_ci */ 566262306a36Sopenharmony_ci pkt = s_rule->hdr_data; 566362306a36Sopenharmony_ci 566462306a36Sopenharmony_ci memcpy(pkt, profile->pkt, profile->pkt_len); 566562306a36Sopenharmony_ci 566662306a36Sopenharmony_ci for (i = 0; i < lkups_cnt; i++) { 566762306a36Sopenharmony_ci const struct ice_dummy_pkt_offsets *offsets = profile->offsets; 566862306a36Sopenharmony_ci enum ice_protocol_type type; 566962306a36Sopenharmony_ci u16 offset = 0, len = 0, j; 567062306a36Sopenharmony_ci bool found = false; 567162306a36Sopenharmony_ci 567262306a36Sopenharmony_ci /* find the start of this layer; it should be found since this 567362306a36Sopenharmony_ci * was already checked when search for the dummy packet 567462306a36Sopenharmony_ci */ 567562306a36Sopenharmony_ci type = lkups[i].type; 567662306a36Sopenharmony_ci /* metadata isn't present in the packet */ 567762306a36Sopenharmony_ci if (type == ICE_HW_METADATA) 567862306a36Sopenharmony_ci continue; 567962306a36Sopenharmony_ci 568062306a36Sopenharmony_ci for (j = 0; offsets[j].type != ICE_PROTOCOL_LAST; j++) { 568162306a36Sopenharmony_ci if (type == offsets[j].type) { 568262306a36Sopenharmony_ci offset = offsets[j].offset; 568362306a36Sopenharmony_ci found = true; 568462306a36Sopenharmony_ci break; 568562306a36Sopenharmony_ci } 568662306a36Sopenharmony_ci } 568762306a36Sopenharmony_ci /* this should never happen in a correct calling sequence */ 568862306a36Sopenharmony_ci if (!found) 568962306a36Sopenharmony_ci return -EINVAL; 569062306a36Sopenharmony_ci 569162306a36Sopenharmony_ci switch (lkups[i].type) { 569262306a36Sopenharmony_ci case ICE_MAC_OFOS: 569362306a36Sopenharmony_ci case ICE_MAC_IL: 569462306a36Sopenharmony_ci len = sizeof(struct ice_ether_hdr); 569562306a36Sopenharmony_ci break; 569662306a36Sopenharmony_ci case ICE_ETYPE_OL: 569762306a36Sopenharmony_ci case ICE_ETYPE_IL: 569862306a36Sopenharmony_ci len = sizeof(struct ice_ethtype_hdr); 569962306a36Sopenharmony_ci break; 570062306a36Sopenharmony_ci case ICE_VLAN_OFOS: 570162306a36Sopenharmony_ci case ICE_VLAN_EX: 570262306a36Sopenharmony_ci case ICE_VLAN_IN: 570362306a36Sopenharmony_ci len = sizeof(struct ice_vlan_hdr); 570462306a36Sopenharmony_ci break; 570562306a36Sopenharmony_ci case ICE_IPV4_OFOS: 570662306a36Sopenharmony_ci case ICE_IPV4_IL: 570762306a36Sopenharmony_ci len = sizeof(struct ice_ipv4_hdr); 570862306a36Sopenharmony_ci break; 570962306a36Sopenharmony_ci case ICE_IPV6_OFOS: 571062306a36Sopenharmony_ci case ICE_IPV6_IL: 571162306a36Sopenharmony_ci len = sizeof(struct ice_ipv6_hdr); 571262306a36Sopenharmony_ci break; 571362306a36Sopenharmony_ci case ICE_TCP_IL: 571462306a36Sopenharmony_ci case ICE_UDP_OF: 571562306a36Sopenharmony_ci case ICE_UDP_ILOS: 571662306a36Sopenharmony_ci len = sizeof(struct ice_l4_hdr); 571762306a36Sopenharmony_ci break; 571862306a36Sopenharmony_ci case ICE_SCTP_IL: 571962306a36Sopenharmony_ci len = sizeof(struct ice_sctp_hdr); 572062306a36Sopenharmony_ci break; 572162306a36Sopenharmony_ci case ICE_NVGRE: 572262306a36Sopenharmony_ci len = sizeof(struct ice_nvgre_hdr); 572362306a36Sopenharmony_ci break; 572462306a36Sopenharmony_ci case ICE_VXLAN: 572562306a36Sopenharmony_ci case ICE_GENEVE: 572662306a36Sopenharmony_ci len = sizeof(struct ice_udp_tnl_hdr); 572762306a36Sopenharmony_ci break; 572862306a36Sopenharmony_ci case ICE_GTP_NO_PAY: 572962306a36Sopenharmony_ci case ICE_GTP: 573062306a36Sopenharmony_ci len = sizeof(struct ice_udp_gtp_hdr); 573162306a36Sopenharmony_ci break; 573262306a36Sopenharmony_ci case ICE_PPPOE: 573362306a36Sopenharmony_ci len = sizeof(struct ice_pppoe_hdr); 573462306a36Sopenharmony_ci break; 573562306a36Sopenharmony_ci case ICE_L2TPV3: 573662306a36Sopenharmony_ci len = sizeof(struct ice_l2tpv3_sess_hdr); 573762306a36Sopenharmony_ci break; 573862306a36Sopenharmony_ci default: 573962306a36Sopenharmony_ci return -EINVAL; 574062306a36Sopenharmony_ci } 574162306a36Sopenharmony_ci 574262306a36Sopenharmony_ci /* the length should be a word multiple */ 574362306a36Sopenharmony_ci if (len % ICE_BYTES_PER_WORD) 574462306a36Sopenharmony_ci return -EIO; 574562306a36Sopenharmony_ci 574662306a36Sopenharmony_ci /* We have the offset to the header start, the length, the 574762306a36Sopenharmony_ci * caller's header values and mask. Use this information to 574862306a36Sopenharmony_ci * copy the data into the dummy packet appropriately based on 574962306a36Sopenharmony_ci * the mask. Note that we need to only write the bits as 575062306a36Sopenharmony_ci * indicated by the mask to make sure we don't improperly write 575162306a36Sopenharmony_ci * over any significant packet data. 575262306a36Sopenharmony_ci */ 575362306a36Sopenharmony_ci for (j = 0; j < len / sizeof(u16); j++) { 575462306a36Sopenharmony_ci u16 *ptr = (u16 *)(pkt + offset); 575562306a36Sopenharmony_ci u16 mask = lkups[i].m_raw[j]; 575662306a36Sopenharmony_ci 575762306a36Sopenharmony_ci if (!mask) 575862306a36Sopenharmony_ci continue; 575962306a36Sopenharmony_ci 576062306a36Sopenharmony_ci ptr[j] = (ptr[j] & ~mask) | (lkups[i].h_raw[j] & mask); 576162306a36Sopenharmony_ci } 576262306a36Sopenharmony_ci } 576362306a36Sopenharmony_ci 576462306a36Sopenharmony_ci s_rule->hdr_len = cpu_to_le16(profile->pkt_len); 576562306a36Sopenharmony_ci 576662306a36Sopenharmony_ci return 0; 576762306a36Sopenharmony_ci} 576862306a36Sopenharmony_ci 576962306a36Sopenharmony_ci/** 577062306a36Sopenharmony_ci * ice_fill_adv_packet_tun - fill dummy packet with udp tunnel port 577162306a36Sopenharmony_ci * @hw: pointer to the hardware structure 577262306a36Sopenharmony_ci * @tun_type: tunnel type 577362306a36Sopenharmony_ci * @pkt: dummy packet to fill in 577462306a36Sopenharmony_ci * @offsets: offset info for the dummy packet 577562306a36Sopenharmony_ci */ 577662306a36Sopenharmony_cistatic int 577762306a36Sopenharmony_ciice_fill_adv_packet_tun(struct ice_hw *hw, enum ice_sw_tunnel_type tun_type, 577862306a36Sopenharmony_ci u8 *pkt, const struct ice_dummy_pkt_offsets *offsets) 577962306a36Sopenharmony_ci{ 578062306a36Sopenharmony_ci u16 open_port, i; 578162306a36Sopenharmony_ci 578262306a36Sopenharmony_ci switch (tun_type) { 578362306a36Sopenharmony_ci case ICE_SW_TUN_VXLAN: 578462306a36Sopenharmony_ci if (!ice_get_open_tunnel_port(hw, &open_port, TNL_VXLAN)) 578562306a36Sopenharmony_ci return -EIO; 578662306a36Sopenharmony_ci break; 578762306a36Sopenharmony_ci case ICE_SW_TUN_GENEVE: 578862306a36Sopenharmony_ci if (!ice_get_open_tunnel_port(hw, &open_port, TNL_GENEVE)) 578962306a36Sopenharmony_ci return -EIO; 579062306a36Sopenharmony_ci break; 579162306a36Sopenharmony_ci default: 579262306a36Sopenharmony_ci /* Nothing needs to be done for this tunnel type */ 579362306a36Sopenharmony_ci return 0; 579462306a36Sopenharmony_ci } 579562306a36Sopenharmony_ci 579662306a36Sopenharmony_ci /* Find the outer UDP protocol header and insert the port number */ 579762306a36Sopenharmony_ci for (i = 0; offsets[i].type != ICE_PROTOCOL_LAST; i++) { 579862306a36Sopenharmony_ci if (offsets[i].type == ICE_UDP_OF) { 579962306a36Sopenharmony_ci struct ice_l4_hdr *hdr; 580062306a36Sopenharmony_ci u16 offset; 580162306a36Sopenharmony_ci 580262306a36Sopenharmony_ci offset = offsets[i].offset; 580362306a36Sopenharmony_ci hdr = (struct ice_l4_hdr *)&pkt[offset]; 580462306a36Sopenharmony_ci hdr->dst_port = cpu_to_be16(open_port); 580562306a36Sopenharmony_ci 580662306a36Sopenharmony_ci return 0; 580762306a36Sopenharmony_ci } 580862306a36Sopenharmony_ci } 580962306a36Sopenharmony_ci 581062306a36Sopenharmony_ci return -EIO; 581162306a36Sopenharmony_ci} 581262306a36Sopenharmony_ci 581362306a36Sopenharmony_ci/** 581462306a36Sopenharmony_ci * ice_fill_adv_packet_vlan - fill dummy packet with VLAN tag type 581562306a36Sopenharmony_ci * @hw: pointer to hw structure 581662306a36Sopenharmony_ci * @vlan_type: VLAN tag type 581762306a36Sopenharmony_ci * @pkt: dummy packet to fill in 581862306a36Sopenharmony_ci * @offsets: offset info for the dummy packet 581962306a36Sopenharmony_ci */ 582062306a36Sopenharmony_cistatic int 582162306a36Sopenharmony_ciice_fill_adv_packet_vlan(struct ice_hw *hw, u16 vlan_type, u8 *pkt, 582262306a36Sopenharmony_ci const struct ice_dummy_pkt_offsets *offsets) 582362306a36Sopenharmony_ci{ 582462306a36Sopenharmony_ci u16 i; 582562306a36Sopenharmony_ci 582662306a36Sopenharmony_ci /* Check if there is something to do */ 582762306a36Sopenharmony_ci if (!vlan_type || !ice_is_dvm_ena(hw)) 582862306a36Sopenharmony_ci return 0; 582962306a36Sopenharmony_ci 583062306a36Sopenharmony_ci /* Find VLAN header and insert VLAN TPID */ 583162306a36Sopenharmony_ci for (i = 0; offsets[i].type != ICE_PROTOCOL_LAST; i++) { 583262306a36Sopenharmony_ci if (offsets[i].type == ICE_VLAN_OFOS || 583362306a36Sopenharmony_ci offsets[i].type == ICE_VLAN_EX) { 583462306a36Sopenharmony_ci struct ice_vlan_hdr *hdr; 583562306a36Sopenharmony_ci u16 offset; 583662306a36Sopenharmony_ci 583762306a36Sopenharmony_ci offset = offsets[i].offset; 583862306a36Sopenharmony_ci hdr = (struct ice_vlan_hdr *)&pkt[offset]; 583962306a36Sopenharmony_ci hdr->type = cpu_to_be16(vlan_type); 584062306a36Sopenharmony_ci 584162306a36Sopenharmony_ci return 0; 584262306a36Sopenharmony_ci } 584362306a36Sopenharmony_ci } 584462306a36Sopenharmony_ci 584562306a36Sopenharmony_ci return -EIO; 584662306a36Sopenharmony_ci} 584762306a36Sopenharmony_ci 584862306a36Sopenharmony_cistatic bool ice_rules_equal(const struct ice_adv_rule_info *first, 584962306a36Sopenharmony_ci const struct ice_adv_rule_info *second) 585062306a36Sopenharmony_ci{ 585162306a36Sopenharmony_ci return first->sw_act.flag == second->sw_act.flag && 585262306a36Sopenharmony_ci first->tun_type == second->tun_type && 585362306a36Sopenharmony_ci first->vlan_type == second->vlan_type && 585462306a36Sopenharmony_ci first->src_vsi == second->src_vsi && 585562306a36Sopenharmony_ci first->need_pass_l2 == second->need_pass_l2 && 585662306a36Sopenharmony_ci first->allow_pass_l2 == second->allow_pass_l2; 585762306a36Sopenharmony_ci} 585862306a36Sopenharmony_ci 585962306a36Sopenharmony_ci/** 586062306a36Sopenharmony_ci * ice_find_adv_rule_entry - Search a rule entry 586162306a36Sopenharmony_ci * @hw: pointer to the hardware structure 586262306a36Sopenharmony_ci * @lkups: lookup elements or match criteria for the advanced recipe, one 586362306a36Sopenharmony_ci * structure per protocol header 586462306a36Sopenharmony_ci * @lkups_cnt: number of protocols 586562306a36Sopenharmony_ci * @recp_id: recipe ID for which we are finding the rule 586662306a36Sopenharmony_ci * @rinfo: other information regarding the rule e.g. priority and action info 586762306a36Sopenharmony_ci * 586862306a36Sopenharmony_ci * Helper function to search for a given advance rule entry 586962306a36Sopenharmony_ci * Returns pointer to entry storing the rule if found 587062306a36Sopenharmony_ci */ 587162306a36Sopenharmony_cistatic struct ice_adv_fltr_mgmt_list_entry * 587262306a36Sopenharmony_ciice_find_adv_rule_entry(struct ice_hw *hw, struct ice_adv_lkup_elem *lkups, 587362306a36Sopenharmony_ci u16 lkups_cnt, u16 recp_id, 587462306a36Sopenharmony_ci struct ice_adv_rule_info *rinfo) 587562306a36Sopenharmony_ci{ 587662306a36Sopenharmony_ci struct ice_adv_fltr_mgmt_list_entry *list_itr; 587762306a36Sopenharmony_ci struct ice_switch_info *sw = hw->switch_info; 587862306a36Sopenharmony_ci int i; 587962306a36Sopenharmony_ci 588062306a36Sopenharmony_ci list_for_each_entry(list_itr, &sw->recp_list[recp_id].filt_rules, 588162306a36Sopenharmony_ci list_entry) { 588262306a36Sopenharmony_ci bool lkups_matched = true; 588362306a36Sopenharmony_ci 588462306a36Sopenharmony_ci if (lkups_cnt != list_itr->lkups_cnt) 588562306a36Sopenharmony_ci continue; 588662306a36Sopenharmony_ci for (i = 0; i < list_itr->lkups_cnt; i++) 588762306a36Sopenharmony_ci if (memcmp(&list_itr->lkups[i], &lkups[i], 588862306a36Sopenharmony_ci sizeof(*lkups))) { 588962306a36Sopenharmony_ci lkups_matched = false; 589062306a36Sopenharmony_ci break; 589162306a36Sopenharmony_ci } 589262306a36Sopenharmony_ci if (ice_rules_equal(rinfo, &list_itr->rule_info) && 589362306a36Sopenharmony_ci lkups_matched) 589462306a36Sopenharmony_ci return list_itr; 589562306a36Sopenharmony_ci } 589662306a36Sopenharmony_ci return NULL; 589762306a36Sopenharmony_ci} 589862306a36Sopenharmony_ci 589962306a36Sopenharmony_ci/** 590062306a36Sopenharmony_ci * ice_adv_add_update_vsi_list 590162306a36Sopenharmony_ci * @hw: pointer to the hardware structure 590262306a36Sopenharmony_ci * @m_entry: pointer to current adv filter management list entry 590362306a36Sopenharmony_ci * @cur_fltr: filter information from the book keeping entry 590462306a36Sopenharmony_ci * @new_fltr: filter information with the new VSI to be added 590562306a36Sopenharmony_ci * 590662306a36Sopenharmony_ci * Call AQ command to add or update previously created VSI list with new VSI. 590762306a36Sopenharmony_ci * 590862306a36Sopenharmony_ci * Helper function to do book keeping associated with adding filter information 590962306a36Sopenharmony_ci * The algorithm to do the booking keeping is described below : 591062306a36Sopenharmony_ci * When a VSI needs to subscribe to a given advanced filter 591162306a36Sopenharmony_ci * if only one VSI has been added till now 591262306a36Sopenharmony_ci * Allocate a new VSI list and add two VSIs 591362306a36Sopenharmony_ci * to this list using switch rule command 591462306a36Sopenharmony_ci * Update the previously created switch rule with the 591562306a36Sopenharmony_ci * newly created VSI list ID 591662306a36Sopenharmony_ci * if a VSI list was previously created 591762306a36Sopenharmony_ci * Add the new VSI to the previously created VSI list set 591862306a36Sopenharmony_ci * using the update switch rule command 591962306a36Sopenharmony_ci */ 592062306a36Sopenharmony_cistatic int 592162306a36Sopenharmony_ciice_adv_add_update_vsi_list(struct ice_hw *hw, 592262306a36Sopenharmony_ci struct ice_adv_fltr_mgmt_list_entry *m_entry, 592362306a36Sopenharmony_ci struct ice_adv_rule_info *cur_fltr, 592462306a36Sopenharmony_ci struct ice_adv_rule_info *new_fltr) 592562306a36Sopenharmony_ci{ 592662306a36Sopenharmony_ci u16 vsi_list_id = 0; 592762306a36Sopenharmony_ci int status; 592862306a36Sopenharmony_ci 592962306a36Sopenharmony_ci if (cur_fltr->sw_act.fltr_act == ICE_FWD_TO_Q || 593062306a36Sopenharmony_ci cur_fltr->sw_act.fltr_act == ICE_FWD_TO_QGRP || 593162306a36Sopenharmony_ci cur_fltr->sw_act.fltr_act == ICE_DROP_PACKET) 593262306a36Sopenharmony_ci return -EOPNOTSUPP; 593362306a36Sopenharmony_ci 593462306a36Sopenharmony_ci if ((new_fltr->sw_act.fltr_act == ICE_FWD_TO_Q || 593562306a36Sopenharmony_ci new_fltr->sw_act.fltr_act == ICE_FWD_TO_QGRP) && 593662306a36Sopenharmony_ci (cur_fltr->sw_act.fltr_act == ICE_FWD_TO_VSI || 593762306a36Sopenharmony_ci cur_fltr->sw_act.fltr_act == ICE_FWD_TO_VSI_LIST)) 593862306a36Sopenharmony_ci return -EOPNOTSUPP; 593962306a36Sopenharmony_ci 594062306a36Sopenharmony_ci if (m_entry->vsi_count < 2 && !m_entry->vsi_list_info) { 594162306a36Sopenharmony_ci /* Only one entry existed in the mapping and it was not already 594262306a36Sopenharmony_ci * a part of a VSI list. So, create a VSI list with the old and 594362306a36Sopenharmony_ci * new VSIs. 594462306a36Sopenharmony_ci */ 594562306a36Sopenharmony_ci struct ice_fltr_info tmp_fltr; 594662306a36Sopenharmony_ci u16 vsi_handle_arr[2]; 594762306a36Sopenharmony_ci 594862306a36Sopenharmony_ci /* A rule already exists with the new VSI being added */ 594962306a36Sopenharmony_ci if (cur_fltr->sw_act.fwd_id.hw_vsi_id == 595062306a36Sopenharmony_ci new_fltr->sw_act.fwd_id.hw_vsi_id) 595162306a36Sopenharmony_ci return -EEXIST; 595262306a36Sopenharmony_ci 595362306a36Sopenharmony_ci vsi_handle_arr[0] = cur_fltr->sw_act.vsi_handle; 595462306a36Sopenharmony_ci vsi_handle_arr[1] = new_fltr->sw_act.vsi_handle; 595562306a36Sopenharmony_ci status = ice_create_vsi_list_rule(hw, &vsi_handle_arr[0], 2, 595662306a36Sopenharmony_ci &vsi_list_id, 595762306a36Sopenharmony_ci ICE_SW_LKUP_LAST); 595862306a36Sopenharmony_ci if (status) 595962306a36Sopenharmony_ci return status; 596062306a36Sopenharmony_ci 596162306a36Sopenharmony_ci memset(&tmp_fltr, 0, sizeof(tmp_fltr)); 596262306a36Sopenharmony_ci tmp_fltr.flag = m_entry->rule_info.sw_act.flag; 596362306a36Sopenharmony_ci tmp_fltr.fltr_rule_id = cur_fltr->fltr_rule_id; 596462306a36Sopenharmony_ci tmp_fltr.fltr_act = ICE_FWD_TO_VSI_LIST; 596562306a36Sopenharmony_ci tmp_fltr.fwd_id.vsi_list_id = vsi_list_id; 596662306a36Sopenharmony_ci tmp_fltr.lkup_type = ICE_SW_LKUP_LAST; 596762306a36Sopenharmony_ci 596862306a36Sopenharmony_ci /* Update the previous switch rule of "forward to VSI" to 596962306a36Sopenharmony_ci * "fwd to VSI list" 597062306a36Sopenharmony_ci */ 597162306a36Sopenharmony_ci status = ice_update_pkt_fwd_rule(hw, &tmp_fltr); 597262306a36Sopenharmony_ci if (status) 597362306a36Sopenharmony_ci return status; 597462306a36Sopenharmony_ci 597562306a36Sopenharmony_ci cur_fltr->sw_act.fwd_id.vsi_list_id = vsi_list_id; 597662306a36Sopenharmony_ci cur_fltr->sw_act.fltr_act = ICE_FWD_TO_VSI_LIST; 597762306a36Sopenharmony_ci m_entry->vsi_list_info = 597862306a36Sopenharmony_ci ice_create_vsi_list_map(hw, &vsi_handle_arr[0], 2, 597962306a36Sopenharmony_ci vsi_list_id); 598062306a36Sopenharmony_ci } else { 598162306a36Sopenharmony_ci u16 vsi_handle = new_fltr->sw_act.vsi_handle; 598262306a36Sopenharmony_ci 598362306a36Sopenharmony_ci if (!m_entry->vsi_list_info) 598462306a36Sopenharmony_ci return -EIO; 598562306a36Sopenharmony_ci 598662306a36Sopenharmony_ci /* A rule already exists with the new VSI being added */ 598762306a36Sopenharmony_ci if (test_bit(vsi_handle, m_entry->vsi_list_info->vsi_map)) 598862306a36Sopenharmony_ci return 0; 598962306a36Sopenharmony_ci 599062306a36Sopenharmony_ci /* Update the previously created VSI list set with 599162306a36Sopenharmony_ci * the new VSI ID passed in 599262306a36Sopenharmony_ci */ 599362306a36Sopenharmony_ci vsi_list_id = cur_fltr->sw_act.fwd_id.vsi_list_id; 599462306a36Sopenharmony_ci 599562306a36Sopenharmony_ci status = ice_update_vsi_list_rule(hw, &vsi_handle, 1, 599662306a36Sopenharmony_ci vsi_list_id, false, 599762306a36Sopenharmony_ci ice_aqc_opc_update_sw_rules, 599862306a36Sopenharmony_ci ICE_SW_LKUP_LAST); 599962306a36Sopenharmony_ci /* update VSI list mapping info with new VSI ID */ 600062306a36Sopenharmony_ci if (!status) 600162306a36Sopenharmony_ci set_bit(vsi_handle, m_entry->vsi_list_info->vsi_map); 600262306a36Sopenharmony_ci } 600362306a36Sopenharmony_ci if (!status) 600462306a36Sopenharmony_ci m_entry->vsi_count++; 600562306a36Sopenharmony_ci return status; 600662306a36Sopenharmony_ci} 600762306a36Sopenharmony_ci 600862306a36Sopenharmony_civoid ice_rule_add_tunnel_metadata(struct ice_adv_lkup_elem *lkup) 600962306a36Sopenharmony_ci{ 601062306a36Sopenharmony_ci lkup->type = ICE_HW_METADATA; 601162306a36Sopenharmony_ci lkup->m_u.metadata.flags[ICE_PKT_FLAGS_MDID21] |= 601262306a36Sopenharmony_ci cpu_to_be16(ICE_PKT_TUNNEL_MASK); 601362306a36Sopenharmony_ci} 601462306a36Sopenharmony_ci 601562306a36Sopenharmony_civoid ice_rule_add_direction_metadata(struct ice_adv_lkup_elem *lkup) 601662306a36Sopenharmony_ci{ 601762306a36Sopenharmony_ci lkup->type = ICE_HW_METADATA; 601862306a36Sopenharmony_ci lkup->m_u.metadata.flags[ICE_PKT_FLAGS_MDID20] |= 601962306a36Sopenharmony_ci cpu_to_be16(ICE_PKT_FROM_NETWORK); 602062306a36Sopenharmony_ci} 602162306a36Sopenharmony_ci 602262306a36Sopenharmony_civoid ice_rule_add_vlan_metadata(struct ice_adv_lkup_elem *lkup) 602362306a36Sopenharmony_ci{ 602462306a36Sopenharmony_ci lkup->type = ICE_HW_METADATA; 602562306a36Sopenharmony_ci lkup->m_u.metadata.flags[ICE_PKT_FLAGS_MDID20] |= 602662306a36Sopenharmony_ci cpu_to_be16(ICE_PKT_VLAN_MASK); 602762306a36Sopenharmony_ci} 602862306a36Sopenharmony_ci 602962306a36Sopenharmony_civoid ice_rule_add_src_vsi_metadata(struct ice_adv_lkup_elem *lkup) 603062306a36Sopenharmony_ci{ 603162306a36Sopenharmony_ci lkup->type = ICE_HW_METADATA; 603262306a36Sopenharmony_ci lkup->m_u.metadata.source_vsi = cpu_to_be16(ICE_MDID_SOURCE_VSI_MASK); 603362306a36Sopenharmony_ci} 603462306a36Sopenharmony_ci 603562306a36Sopenharmony_ci/** 603662306a36Sopenharmony_ci * ice_add_adv_rule - helper function to create an advanced switch rule 603762306a36Sopenharmony_ci * @hw: pointer to the hardware structure 603862306a36Sopenharmony_ci * @lkups: information on the words that needs to be looked up. All words 603962306a36Sopenharmony_ci * together makes one recipe 604062306a36Sopenharmony_ci * @lkups_cnt: num of entries in the lkups array 604162306a36Sopenharmony_ci * @rinfo: other information related to the rule that needs to be programmed 604262306a36Sopenharmony_ci * @added_entry: this will return recipe_id, rule_id and vsi_handle. should be 604362306a36Sopenharmony_ci * ignored is case of error. 604462306a36Sopenharmony_ci * 604562306a36Sopenharmony_ci * This function can program only 1 rule at a time. The lkups is used to 604662306a36Sopenharmony_ci * describe the all the words that forms the "lookup" portion of the recipe. 604762306a36Sopenharmony_ci * These words can span multiple protocols. Callers to this function need to 604862306a36Sopenharmony_ci * pass in a list of protocol headers with lookup information along and mask 604962306a36Sopenharmony_ci * that determines which words are valid from the given protocol header. 605062306a36Sopenharmony_ci * rinfo describes other information related to this rule such as forwarding 605162306a36Sopenharmony_ci * IDs, priority of this rule, etc. 605262306a36Sopenharmony_ci */ 605362306a36Sopenharmony_ciint 605462306a36Sopenharmony_ciice_add_adv_rule(struct ice_hw *hw, struct ice_adv_lkup_elem *lkups, 605562306a36Sopenharmony_ci u16 lkups_cnt, struct ice_adv_rule_info *rinfo, 605662306a36Sopenharmony_ci struct ice_rule_query_data *added_entry) 605762306a36Sopenharmony_ci{ 605862306a36Sopenharmony_ci struct ice_adv_fltr_mgmt_list_entry *m_entry, *adv_fltr = NULL; 605962306a36Sopenharmony_ci struct ice_sw_rule_lkup_rx_tx *s_rule = NULL; 606062306a36Sopenharmony_ci const struct ice_dummy_pkt_profile *profile; 606162306a36Sopenharmony_ci u16 rid = 0, i, rule_buf_sz, vsi_handle; 606262306a36Sopenharmony_ci struct list_head *rule_head; 606362306a36Sopenharmony_ci struct ice_switch_info *sw; 606462306a36Sopenharmony_ci u16 word_cnt; 606562306a36Sopenharmony_ci u32 act = 0; 606662306a36Sopenharmony_ci int status; 606762306a36Sopenharmony_ci u8 q_rgn; 606862306a36Sopenharmony_ci 606962306a36Sopenharmony_ci /* Initialize profile to result index bitmap */ 607062306a36Sopenharmony_ci if (!hw->switch_info->prof_res_bm_init) { 607162306a36Sopenharmony_ci hw->switch_info->prof_res_bm_init = 1; 607262306a36Sopenharmony_ci ice_init_prof_result_bm(hw); 607362306a36Sopenharmony_ci } 607462306a36Sopenharmony_ci 607562306a36Sopenharmony_ci if (!lkups_cnt) 607662306a36Sopenharmony_ci return -EINVAL; 607762306a36Sopenharmony_ci 607862306a36Sopenharmony_ci /* get # of words we need to match */ 607962306a36Sopenharmony_ci word_cnt = 0; 608062306a36Sopenharmony_ci for (i = 0; i < lkups_cnt; i++) { 608162306a36Sopenharmony_ci u16 j; 608262306a36Sopenharmony_ci 608362306a36Sopenharmony_ci for (j = 0; j < ARRAY_SIZE(lkups->m_raw); j++) 608462306a36Sopenharmony_ci if (lkups[i].m_raw[j]) 608562306a36Sopenharmony_ci word_cnt++; 608662306a36Sopenharmony_ci } 608762306a36Sopenharmony_ci 608862306a36Sopenharmony_ci if (!word_cnt) 608962306a36Sopenharmony_ci return -EINVAL; 609062306a36Sopenharmony_ci 609162306a36Sopenharmony_ci if (word_cnt > ICE_MAX_CHAIN_WORDS) 609262306a36Sopenharmony_ci return -ENOSPC; 609362306a36Sopenharmony_ci 609462306a36Sopenharmony_ci /* locate a dummy packet */ 609562306a36Sopenharmony_ci profile = ice_find_dummy_packet(lkups, lkups_cnt, rinfo->tun_type); 609662306a36Sopenharmony_ci if (IS_ERR(profile)) 609762306a36Sopenharmony_ci return PTR_ERR(profile); 609862306a36Sopenharmony_ci 609962306a36Sopenharmony_ci if (!(rinfo->sw_act.fltr_act == ICE_FWD_TO_VSI || 610062306a36Sopenharmony_ci rinfo->sw_act.fltr_act == ICE_FWD_TO_Q || 610162306a36Sopenharmony_ci rinfo->sw_act.fltr_act == ICE_FWD_TO_QGRP || 610262306a36Sopenharmony_ci rinfo->sw_act.fltr_act == ICE_DROP_PACKET || 610362306a36Sopenharmony_ci rinfo->sw_act.fltr_act == ICE_NOP)) { 610462306a36Sopenharmony_ci status = -EIO; 610562306a36Sopenharmony_ci goto free_pkt_profile; 610662306a36Sopenharmony_ci } 610762306a36Sopenharmony_ci 610862306a36Sopenharmony_ci vsi_handle = rinfo->sw_act.vsi_handle; 610962306a36Sopenharmony_ci if (!ice_is_vsi_valid(hw, vsi_handle)) { 611062306a36Sopenharmony_ci status = -EINVAL; 611162306a36Sopenharmony_ci goto free_pkt_profile; 611262306a36Sopenharmony_ci } 611362306a36Sopenharmony_ci 611462306a36Sopenharmony_ci if (rinfo->sw_act.fltr_act == ICE_FWD_TO_VSI || 611562306a36Sopenharmony_ci rinfo->sw_act.fltr_act == ICE_NOP) 611662306a36Sopenharmony_ci rinfo->sw_act.fwd_id.hw_vsi_id = 611762306a36Sopenharmony_ci ice_get_hw_vsi_num(hw, vsi_handle); 611862306a36Sopenharmony_ci 611962306a36Sopenharmony_ci if (rinfo->src_vsi) 612062306a36Sopenharmony_ci rinfo->sw_act.src = ice_get_hw_vsi_num(hw, rinfo->src_vsi); 612162306a36Sopenharmony_ci else 612262306a36Sopenharmony_ci rinfo->sw_act.src = ice_get_hw_vsi_num(hw, vsi_handle); 612362306a36Sopenharmony_ci 612462306a36Sopenharmony_ci status = ice_add_adv_recipe(hw, lkups, lkups_cnt, rinfo, &rid); 612562306a36Sopenharmony_ci if (status) 612662306a36Sopenharmony_ci goto free_pkt_profile; 612762306a36Sopenharmony_ci m_entry = ice_find_adv_rule_entry(hw, lkups, lkups_cnt, rid, rinfo); 612862306a36Sopenharmony_ci if (m_entry) { 612962306a36Sopenharmony_ci /* we have to add VSI to VSI_LIST and increment vsi_count. 613062306a36Sopenharmony_ci * Also Update VSI list so that we can change forwarding rule 613162306a36Sopenharmony_ci * if the rule already exists, we will check if it exists with 613262306a36Sopenharmony_ci * same vsi_id, if not then add it to the VSI list if it already 613362306a36Sopenharmony_ci * exists if not then create a VSI list and add the existing VSI 613462306a36Sopenharmony_ci * ID and the new VSI ID to the list 613562306a36Sopenharmony_ci * We will add that VSI to the list 613662306a36Sopenharmony_ci */ 613762306a36Sopenharmony_ci status = ice_adv_add_update_vsi_list(hw, m_entry, 613862306a36Sopenharmony_ci &m_entry->rule_info, 613962306a36Sopenharmony_ci rinfo); 614062306a36Sopenharmony_ci if (added_entry) { 614162306a36Sopenharmony_ci added_entry->rid = rid; 614262306a36Sopenharmony_ci added_entry->rule_id = m_entry->rule_info.fltr_rule_id; 614362306a36Sopenharmony_ci added_entry->vsi_handle = rinfo->sw_act.vsi_handle; 614462306a36Sopenharmony_ci } 614562306a36Sopenharmony_ci goto free_pkt_profile; 614662306a36Sopenharmony_ci } 614762306a36Sopenharmony_ci rule_buf_sz = ICE_SW_RULE_RX_TX_HDR_SIZE(s_rule, profile->pkt_len); 614862306a36Sopenharmony_ci s_rule = kzalloc(rule_buf_sz, GFP_KERNEL); 614962306a36Sopenharmony_ci if (!s_rule) { 615062306a36Sopenharmony_ci status = -ENOMEM; 615162306a36Sopenharmony_ci goto free_pkt_profile; 615262306a36Sopenharmony_ci } 615362306a36Sopenharmony_ci if (!rinfo->flags_info.act_valid) { 615462306a36Sopenharmony_ci act |= ICE_SINGLE_ACT_LAN_ENABLE; 615562306a36Sopenharmony_ci act |= ICE_SINGLE_ACT_LB_ENABLE; 615662306a36Sopenharmony_ci } else { 615762306a36Sopenharmony_ci act |= rinfo->flags_info.act & (ICE_SINGLE_ACT_LAN_ENABLE | 615862306a36Sopenharmony_ci ICE_SINGLE_ACT_LB_ENABLE); 615962306a36Sopenharmony_ci } 616062306a36Sopenharmony_ci 616162306a36Sopenharmony_ci switch (rinfo->sw_act.fltr_act) { 616262306a36Sopenharmony_ci case ICE_FWD_TO_VSI: 616362306a36Sopenharmony_ci act |= (rinfo->sw_act.fwd_id.hw_vsi_id << 616462306a36Sopenharmony_ci ICE_SINGLE_ACT_VSI_ID_S) & ICE_SINGLE_ACT_VSI_ID_M; 616562306a36Sopenharmony_ci act |= ICE_SINGLE_ACT_VSI_FORWARDING | ICE_SINGLE_ACT_VALID_BIT; 616662306a36Sopenharmony_ci break; 616762306a36Sopenharmony_ci case ICE_FWD_TO_Q: 616862306a36Sopenharmony_ci act |= ICE_SINGLE_ACT_TO_Q; 616962306a36Sopenharmony_ci act |= (rinfo->sw_act.fwd_id.q_id << ICE_SINGLE_ACT_Q_INDEX_S) & 617062306a36Sopenharmony_ci ICE_SINGLE_ACT_Q_INDEX_M; 617162306a36Sopenharmony_ci break; 617262306a36Sopenharmony_ci case ICE_FWD_TO_QGRP: 617362306a36Sopenharmony_ci q_rgn = rinfo->sw_act.qgrp_size > 0 ? 617462306a36Sopenharmony_ci (u8)ilog2(rinfo->sw_act.qgrp_size) : 0; 617562306a36Sopenharmony_ci act |= ICE_SINGLE_ACT_TO_Q; 617662306a36Sopenharmony_ci act |= (rinfo->sw_act.fwd_id.q_id << ICE_SINGLE_ACT_Q_INDEX_S) & 617762306a36Sopenharmony_ci ICE_SINGLE_ACT_Q_INDEX_M; 617862306a36Sopenharmony_ci act |= (q_rgn << ICE_SINGLE_ACT_Q_REGION_S) & 617962306a36Sopenharmony_ci ICE_SINGLE_ACT_Q_REGION_M; 618062306a36Sopenharmony_ci break; 618162306a36Sopenharmony_ci case ICE_DROP_PACKET: 618262306a36Sopenharmony_ci act |= ICE_SINGLE_ACT_VSI_FORWARDING | ICE_SINGLE_ACT_DROP | 618362306a36Sopenharmony_ci ICE_SINGLE_ACT_VALID_BIT; 618462306a36Sopenharmony_ci break; 618562306a36Sopenharmony_ci case ICE_NOP: 618662306a36Sopenharmony_ci act |= FIELD_PREP(ICE_SINGLE_ACT_VSI_ID_M, 618762306a36Sopenharmony_ci rinfo->sw_act.fwd_id.hw_vsi_id); 618862306a36Sopenharmony_ci act &= ~ICE_SINGLE_ACT_VALID_BIT; 618962306a36Sopenharmony_ci break; 619062306a36Sopenharmony_ci default: 619162306a36Sopenharmony_ci status = -EIO; 619262306a36Sopenharmony_ci goto err_ice_add_adv_rule; 619362306a36Sopenharmony_ci } 619462306a36Sopenharmony_ci 619562306a36Sopenharmony_ci /* If there is no matching criteria for direction there 619662306a36Sopenharmony_ci * is only one difference between Rx and Tx: 619762306a36Sopenharmony_ci * - get switch id base on VSI number from source field (Tx) 619862306a36Sopenharmony_ci * - get switch id base on port number (Rx) 619962306a36Sopenharmony_ci * 620062306a36Sopenharmony_ci * If matching on direction metadata is chose rule direction is 620162306a36Sopenharmony_ci * extracted from type value set here. 620262306a36Sopenharmony_ci */ 620362306a36Sopenharmony_ci if (rinfo->sw_act.flag & ICE_FLTR_TX) { 620462306a36Sopenharmony_ci s_rule->hdr.type = cpu_to_le16(ICE_AQC_SW_RULES_T_LKUP_TX); 620562306a36Sopenharmony_ci s_rule->src = cpu_to_le16(rinfo->sw_act.src); 620662306a36Sopenharmony_ci } else { 620762306a36Sopenharmony_ci s_rule->hdr.type = cpu_to_le16(ICE_AQC_SW_RULES_T_LKUP_RX); 620862306a36Sopenharmony_ci s_rule->src = cpu_to_le16(hw->port_info->lport); 620962306a36Sopenharmony_ci } 621062306a36Sopenharmony_ci 621162306a36Sopenharmony_ci s_rule->recipe_id = cpu_to_le16(rid); 621262306a36Sopenharmony_ci s_rule->act = cpu_to_le32(act); 621362306a36Sopenharmony_ci 621462306a36Sopenharmony_ci status = ice_fill_adv_dummy_packet(lkups, lkups_cnt, s_rule, profile); 621562306a36Sopenharmony_ci if (status) 621662306a36Sopenharmony_ci goto err_ice_add_adv_rule; 621762306a36Sopenharmony_ci 621862306a36Sopenharmony_ci status = ice_fill_adv_packet_tun(hw, rinfo->tun_type, s_rule->hdr_data, 621962306a36Sopenharmony_ci profile->offsets); 622062306a36Sopenharmony_ci if (status) 622162306a36Sopenharmony_ci goto err_ice_add_adv_rule; 622262306a36Sopenharmony_ci 622362306a36Sopenharmony_ci status = ice_fill_adv_packet_vlan(hw, rinfo->vlan_type, 622462306a36Sopenharmony_ci s_rule->hdr_data, 622562306a36Sopenharmony_ci profile->offsets); 622662306a36Sopenharmony_ci if (status) 622762306a36Sopenharmony_ci goto err_ice_add_adv_rule; 622862306a36Sopenharmony_ci 622962306a36Sopenharmony_ci status = ice_aq_sw_rules(hw, (struct ice_aqc_sw_rules *)s_rule, 623062306a36Sopenharmony_ci rule_buf_sz, 1, ice_aqc_opc_add_sw_rules, 623162306a36Sopenharmony_ci NULL); 623262306a36Sopenharmony_ci if (status) 623362306a36Sopenharmony_ci goto err_ice_add_adv_rule; 623462306a36Sopenharmony_ci adv_fltr = devm_kzalloc(ice_hw_to_dev(hw), 623562306a36Sopenharmony_ci sizeof(struct ice_adv_fltr_mgmt_list_entry), 623662306a36Sopenharmony_ci GFP_KERNEL); 623762306a36Sopenharmony_ci if (!adv_fltr) { 623862306a36Sopenharmony_ci status = -ENOMEM; 623962306a36Sopenharmony_ci goto err_ice_add_adv_rule; 624062306a36Sopenharmony_ci } 624162306a36Sopenharmony_ci 624262306a36Sopenharmony_ci adv_fltr->lkups = devm_kmemdup(ice_hw_to_dev(hw), lkups, 624362306a36Sopenharmony_ci lkups_cnt * sizeof(*lkups), GFP_KERNEL); 624462306a36Sopenharmony_ci if (!adv_fltr->lkups) { 624562306a36Sopenharmony_ci status = -ENOMEM; 624662306a36Sopenharmony_ci goto err_ice_add_adv_rule; 624762306a36Sopenharmony_ci } 624862306a36Sopenharmony_ci 624962306a36Sopenharmony_ci adv_fltr->lkups_cnt = lkups_cnt; 625062306a36Sopenharmony_ci adv_fltr->rule_info = *rinfo; 625162306a36Sopenharmony_ci adv_fltr->rule_info.fltr_rule_id = le16_to_cpu(s_rule->index); 625262306a36Sopenharmony_ci sw = hw->switch_info; 625362306a36Sopenharmony_ci sw->recp_list[rid].adv_rule = true; 625462306a36Sopenharmony_ci rule_head = &sw->recp_list[rid].filt_rules; 625562306a36Sopenharmony_ci 625662306a36Sopenharmony_ci if (rinfo->sw_act.fltr_act == ICE_FWD_TO_VSI) 625762306a36Sopenharmony_ci adv_fltr->vsi_count = 1; 625862306a36Sopenharmony_ci 625962306a36Sopenharmony_ci /* Add rule entry to book keeping list */ 626062306a36Sopenharmony_ci list_add(&adv_fltr->list_entry, rule_head); 626162306a36Sopenharmony_ci if (added_entry) { 626262306a36Sopenharmony_ci added_entry->rid = rid; 626362306a36Sopenharmony_ci added_entry->rule_id = adv_fltr->rule_info.fltr_rule_id; 626462306a36Sopenharmony_ci added_entry->vsi_handle = rinfo->sw_act.vsi_handle; 626562306a36Sopenharmony_ci } 626662306a36Sopenharmony_cierr_ice_add_adv_rule: 626762306a36Sopenharmony_ci if (status && adv_fltr) { 626862306a36Sopenharmony_ci devm_kfree(ice_hw_to_dev(hw), adv_fltr->lkups); 626962306a36Sopenharmony_ci devm_kfree(ice_hw_to_dev(hw), adv_fltr); 627062306a36Sopenharmony_ci } 627162306a36Sopenharmony_ci 627262306a36Sopenharmony_ci kfree(s_rule); 627362306a36Sopenharmony_ci 627462306a36Sopenharmony_cifree_pkt_profile: 627562306a36Sopenharmony_ci if (profile->match & ICE_PKT_KMALLOC) { 627662306a36Sopenharmony_ci kfree(profile->offsets); 627762306a36Sopenharmony_ci kfree(profile->pkt); 627862306a36Sopenharmony_ci kfree(profile); 627962306a36Sopenharmony_ci } 628062306a36Sopenharmony_ci 628162306a36Sopenharmony_ci return status; 628262306a36Sopenharmony_ci} 628362306a36Sopenharmony_ci 628462306a36Sopenharmony_ci/** 628562306a36Sopenharmony_ci * ice_replay_vsi_fltr - Replay filters for requested VSI 628662306a36Sopenharmony_ci * @hw: pointer to the hardware structure 628762306a36Sopenharmony_ci * @vsi_handle: driver VSI handle 628862306a36Sopenharmony_ci * @recp_id: Recipe ID for which rules need to be replayed 628962306a36Sopenharmony_ci * @list_head: list for which filters need to be replayed 629062306a36Sopenharmony_ci * 629162306a36Sopenharmony_ci * Replays the filter of recipe recp_id for a VSI represented via vsi_handle. 629262306a36Sopenharmony_ci * It is required to pass valid VSI handle. 629362306a36Sopenharmony_ci */ 629462306a36Sopenharmony_cistatic int 629562306a36Sopenharmony_ciice_replay_vsi_fltr(struct ice_hw *hw, u16 vsi_handle, u8 recp_id, 629662306a36Sopenharmony_ci struct list_head *list_head) 629762306a36Sopenharmony_ci{ 629862306a36Sopenharmony_ci struct ice_fltr_mgmt_list_entry *itr; 629962306a36Sopenharmony_ci int status = 0; 630062306a36Sopenharmony_ci u16 hw_vsi_id; 630162306a36Sopenharmony_ci 630262306a36Sopenharmony_ci if (list_empty(list_head)) 630362306a36Sopenharmony_ci return status; 630462306a36Sopenharmony_ci hw_vsi_id = ice_get_hw_vsi_num(hw, vsi_handle); 630562306a36Sopenharmony_ci 630662306a36Sopenharmony_ci list_for_each_entry(itr, list_head, list_entry) { 630762306a36Sopenharmony_ci struct ice_fltr_list_entry f_entry; 630862306a36Sopenharmony_ci 630962306a36Sopenharmony_ci f_entry.fltr_info = itr->fltr_info; 631062306a36Sopenharmony_ci if (itr->vsi_count < 2 && recp_id != ICE_SW_LKUP_VLAN && 631162306a36Sopenharmony_ci itr->fltr_info.vsi_handle == vsi_handle) { 631262306a36Sopenharmony_ci /* update the src in case it is VSI num */ 631362306a36Sopenharmony_ci if (f_entry.fltr_info.src_id == ICE_SRC_ID_VSI) 631462306a36Sopenharmony_ci f_entry.fltr_info.src = hw_vsi_id; 631562306a36Sopenharmony_ci status = ice_add_rule_internal(hw, recp_id, &f_entry); 631662306a36Sopenharmony_ci if (status) 631762306a36Sopenharmony_ci goto end; 631862306a36Sopenharmony_ci continue; 631962306a36Sopenharmony_ci } 632062306a36Sopenharmony_ci if (!itr->vsi_list_info || 632162306a36Sopenharmony_ci !test_bit(vsi_handle, itr->vsi_list_info->vsi_map)) 632262306a36Sopenharmony_ci continue; 632362306a36Sopenharmony_ci /* Clearing it so that the logic can add it back */ 632462306a36Sopenharmony_ci clear_bit(vsi_handle, itr->vsi_list_info->vsi_map); 632562306a36Sopenharmony_ci f_entry.fltr_info.vsi_handle = vsi_handle; 632662306a36Sopenharmony_ci f_entry.fltr_info.fltr_act = ICE_FWD_TO_VSI; 632762306a36Sopenharmony_ci /* update the src in case it is VSI num */ 632862306a36Sopenharmony_ci if (f_entry.fltr_info.src_id == ICE_SRC_ID_VSI) 632962306a36Sopenharmony_ci f_entry.fltr_info.src = hw_vsi_id; 633062306a36Sopenharmony_ci if (recp_id == ICE_SW_LKUP_VLAN) 633162306a36Sopenharmony_ci status = ice_add_vlan_internal(hw, &f_entry); 633262306a36Sopenharmony_ci else 633362306a36Sopenharmony_ci status = ice_add_rule_internal(hw, recp_id, &f_entry); 633462306a36Sopenharmony_ci if (status) 633562306a36Sopenharmony_ci goto end; 633662306a36Sopenharmony_ci } 633762306a36Sopenharmony_ciend: 633862306a36Sopenharmony_ci return status; 633962306a36Sopenharmony_ci} 634062306a36Sopenharmony_ci 634162306a36Sopenharmony_ci/** 634262306a36Sopenharmony_ci * ice_adv_rem_update_vsi_list 634362306a36Sopenharmony_ci * @hw: pointer to the hardware structure 634462306a36Sopenharmony_ci * @vsi_handle: VSI handle of the VSI to remove 634562306a36Sopenharmony_ci * @fm_list: filter management entry for which the VSI list management needs to 634662306a36Sopenharmony_ci * be done 634762306a36Sopenharmony_ci */ 634862306a36Sopenharmony_cistatic int 634962306a36Sopenharmony_ciice_adv_rem_update_vsi_list(struct ice_hw *hw, u16 vsi_handle, 635062306a36Sopenharmony_ci struct ice_adv_fltr_mgmt_list_entry *fm_list) 635162306a36Sopenharmony_ci{ 635262306a36Sopenharmony_ci struct ice_vsi_list_map_info *vsi_list_info; 635362306a36Sopenharmony_ci enum ice_sw_lkup_type lkup_type; 635462306a36Sopenharmony_ci u16 vsi_list_id; 635562306a36Sopenharmony_ci int status; 635662306a36Sopenharmony_ci 635762306a36Sopenharmony_ci if (fm_list->rule_info.sw_act.fltr_act != ICE_FWD_TO_VSI_LIST || 635862306a36Sopenharmony_ci fm_list->vsi_count == 0) 635962306a36Sopenharmony_ci return -EINVAL; 636062306a36Sopenharmony_ci 636162306a36Sopenharmony_ci /* A rule with the VSI being removed does not exist */ 636262306a36Sopenharmony_ci if (!test_bit(vsi_handle, fm_list->vsi_list_info->vsi_map)) 636362306a36Sopenharmony_ci return -ENOENT; 636462306a36Sopenharmony_ci 636562306a36Sopenharmony_ci lkup_type = ICE_SW_LKUP_LAST; 636662306a36Sopenharmony_ci vsi_list_id = fm_list->rule_info.sw_act.fwd_id.vsi_list_id; 636762306a36Sopenharmony_ci status = ice_update_vsi_list_rule(hw, &vsi_handle, 1, vsi_list_id, true, 636862306a36Sopenharmony_ci ice_aqc_opc_update_sw_rules, 636962306a36Sopenharmony_ci lkup_type); 637062306a36Sopenharmony_ci if (status) 637162306a36Sopenharmony_ci return status; 637262306a36Sopenharmony_ci 637362306a36Sopenharmony_ci fm_list->vsi_count--; 637462306a36Sopenharmony_ci clear_bit(vsi_handle, fm_list->vsi_list_info->vsi_map); 637562306a36Sopenharmony_ci vsi_list_info = fm_list->vsi_list_info; 637662306a36Sopenharmony_ci if (fm_list->vsi_count == 1) { 637762306a36Sopenharmony_ci struct ice_fltr_info tmp_fltr; 637862306a36Sopenharmony_ci u16 rem_vsi_handle; 637962306a36Sopenharmony_ci 638062306a36Sopenharmony_ci rem_vsi_handle = find_first_bit(vsi_list_info->vsi_map, 638162306a36Sopenharmony_ci ICE_MAX_VSI); 638262306a36Sopenharmony_ci if (!ice_is_vsi_valid(hw, rem_vsi_handle)) 638362306a36Sopenharmony_ci return -EIO; 638462306a36Sopenharmony_ci 638562306a36Sopenharmony_ci /* Make sure VSI list is empty before removing it below */ 638662306a36Sopenharmony_ci status = ice_update_vsi_list_rule(hw, &rem_vsi_handle, 1, 638762306a36Sopenharmony_ci vsi_list_id, true, 638862306a36Sopenharmony_ci ice_aqc_opc_update_sw_rules, 638962306a36Sopenharmony_ci lkup_type); 639062306a36Sopenharmony_ci if (status) 639162306a36Sopenharmony_ci return status; 639262306a36Sopenharmony_ci 639362306a36Sopenharmony_ci memset(&tmp_fltr, 0, sizeof(tmp_fltr)); 639462306a36Sopenharmony_ci tmp_fltr.flag = fm_list->rule_info.sw_act.flag; 639562306a36Sopenharmony_ci tmp_fltr.fltr_rule_id = fm_list->rule_info.fltr_rule_id; 639662306a36Sopenharmony_ci fm_list->rule_info.sw_act.fltr_act = ICE_FWD_TO_VSI; 639762306a36Sopenharmony_ci tmp_fltr.fltr_act = ICE_FWD_TO_VSI; 639862306a36Sopenharmony_ci tmp_fltr.fwd_id.hw_vsi_id = 639962306a36Sopenharmony_ci ice_get_hw_vsi_num(hw, rem_vsi_handle); 640062306a36Sopenharmony_ci fm_list->rule_info.sw_act.fwd_id.hw_vsi_id = 640162306a36Sopenharmony_ci ice_get_hw_vsi_num(hw, rem_vsi_handle); 640262306a36Sopenharmony_ci fm_list->rule_info.sw_act.vsi_handle = rem_vsi_handle; 640362306a36Sopenharmony_ci 640462306a36Sopenharmony_ci /* Update the previous switch rule of "MAC forward to VSI" to 640562306a36Sopenharmony_ci * "MAC fwd to VSI list" 640662306a36Sopenharmony_ci */ 640762306a36Sopenharmony_ci status = ice_update_pkt_fwd_rule(hw, &tmp_fltr); 640862306a36Sopenharmony_ci if (status) { 640962306a36Sopenharmony_ci ice_debug(hw, ICE_DBG_SW, "Failed to update pkt fwd rule to FWD_TO_VSI on HW VSI %d, error %d\n", 641062306a36Sopenharmony_ci tmp_fltr.fwd_id.hw_vsi_id, status); 641162306a36Sopenharmony_ci return status; 641262306a36Sopenharmony_ci } 641362306a36Sopenharmony_ci fm_list->vsi_list_info->ref_cnt--; 641462306a36Sopenharmony_ci 641562306a36Sopenharmony_ci /* Remove the VSI list since it is no longer used */ 641662306a36Sopenharmony_ci status = ice_remove_vsi_list_rule(hw, vsi_list_id, lkup_type); 641762306a36Sopenharmony_ci if (status) { 641862306a36Sopenharmony_ci ice_debug(hw, ICE_DBG_SW, "Failed to remove VSI list %d, error %d\n", 641962306a36Sopenharmony_ci vsi_list_id, status); 642062306a36Sopenharmony_ci return status; 642162306a36Sopenharmony_ci } 642262306a36Sopenharmony_ci 642362306a36Sopenharmony_ci list_del(&vsi_list_info->list_entry); 642462306a36Sopenharmony_ci devm_kfree(ice_hw_to_dev(hw), vsi_list_info); 642562306a36Sopenharmony_ci fm_list->vsi_list_info = NULL; 642662306a36Sopenharmony_ci } 642762306a36Sopenharmony_ci 642862306a36Sopenharmony_ci return status; 642962306a36Sopenharmony_ci} 643062306a36Sopenharmony_ci 643162306a36Sopenharmony_ci/** 643262306a36Sopenharmony_ci * ice_rem_adv_rule - removes existing advanced switch rule 643362306a36Sopenharmony_ci * @hw: pointer to the hardware structure 643462306a36Sopenharmony_ci * @lkups: information on the words that needs to be looked up. All words 643562306a36Sopenharmony_ci * together makes one recipe 643662306a36Sopenharmony_ci * @lkups_cnt: num of entries in the lkups array 643762306a36Sopenharmony_ci * @rinfo: Its the pointer to the rule information for the rule 643862306a36Sopenharmony_ci * 643962306a36Sopenharmony_ci * This function can be used to remove 1 rule at a time. The lkups is 644062306a36Sopenharmony_ci * used to describe all the words that forms the "lookup" portion of the 644162306a36Sopenharmony_ci * rule. These words can span multiple protocols. Callers to this function 644262306a36Sopenharmony_ci * need to pass in a list of protocol headers with lookup information along 644362306a36Sopenharmony_ci * and mask that determines which words are valid from the given protocol 644462306a36Sopenharmony_ci * header. rinfo describes other information related to this rule such as 644562306a36Sopenharmony_ci * forwarding IDs, priority of this rule, etc. 644662306a36Sopenharmony_ci */ 644762306a36Sopenharmony_cistatic int 644862306a36Sopenharmony_ciice_rem_adv_rule(struct ice_hw *hw, struct ice_adv_lkup_elem *lkups, 644962306a36Sopenharmony_ci u16 lkups_cnt, struct ice_adv_rule_info *rinfo) 645062306a36Sopenharmony_ci{ 645162306a36Sopenharmony_ci struct ice_adv_fltr_mgmt_list_entry *list_elem; 645262306a36Sopenharmony_ci struct ice_prot_lkup_ext lkup_exts; 645362306a36Sopenharmony_ci bool remove_rule = false; 645462306a36Sopenharmony_ci struct mutex *rule_lock; /* Lock to protect filter rule list */ 645562306a36Sopenharmony_ci u16 i, rid, vsi_handle; 645662306a36Sopenharmony_ci int status = 0; 645762306a36Sopenharmony_ci 645862306a36Sopenharmony_ci memset(&lkup_exts, 0, sizeof(lkup_exts)); 645962306a36Sopenharmony_ci for (i = 0; i < lkups_cnt; i++) { 646062306a36Sopenharmony_ci u16 count; 646162306a36Sopenharmony_ci 646262306a36Sopenharmony_ci if (lkups[i].type >= ICE_PROTOCOL_LAST) 646362306a36Sopenharmony_ci return -EIO; 646462306a36Sopenharmony_ci 646562306a36Sopenharmony_ci count = ice_fill_valid_words(&lkups[i], &lkup_exts); 646662306a36Sopenharmony_ci if (!count) 646762306a36Sopenharmony_ci return -EIO; 646862306a36Sopenharmony_ci } 646962306a36Sopenharmony_ci 647062306a36Sopenharmony_ci rid = ice_find_recp(hw, &lkup_exts, rinfo); 647162306a36Sopenharmony_ci /* If did not find a recipe that match the existing criteria */ 647262306a36Sopenharmony_ci if (rid == ICE_MAX_NUM_RECIPES) 647362306a36Sopenharmony_ci return -EINVAL; 647462306a36Sopenharmony_ci 647562306a36Sopenharmony_ci rule_lock = &hw->switch_info->recp_list[rid].filt_rule_lock; 647662306a36Sopenharmony_ci list_elem = ice_find_adv_rule_entry(hw, lkups, lkups_cnt, rid, rinfo); 647762306a36Sopenharmony_ci /* the rule is already removed */ 647862306a36Sopenharmony_ci if (!list_elem) 647962306a36Sopenharmony_ci return 0; 648062306a36Sopenharmony_ci mutex_lock(rule_lock); 648162306a36Sopenharmony_ci if (list_elem->rule_info.sw_act.fltr_act != ICE_FWD_TO_VSI_LIST) { 648262306a36Sopenharmony_ci remove_rule = true; 648362306a36Sopenharmony_ci } else if (list_elem->vsi_count > 1) { 648462306a36Sopenharmony_ci remove_rule = false; 648562306a36Sopenharmony_ci vsi_handle = rinfo->sw_act.vsi_handle; 648662306a36Sopenharmony_ci status = ice_adv_rem_update_vsi_list(hw, vsi_handle, list_elem); 648762306a36Sopenharmony_ci } else { 648862306a36Sopenharmony_ci vsi_handle = rinfo->sw_act.vsi_handle; 648962306a36Sopenharmony_ci status = ice_adv_rem_update_vsi_list(hw, vsi_handle, list_elem); 649062306a36Sopenharmony_ci if (status) { 649162306a36Sopenharmony_ci mutex_unlock(rule_lock); 649262306a36Sopenharmony_ci return status; 649362306a36Sopenharmony_ci } 649462306a36Sopenharmony_ci if (list_elem->vsi_count == 0) 649562306a36Sopenharmony_ci remove_rule = true; 649662306a36Sopenharmony_ci } 649762306a36Sopenharmony_ci mutex_unlock(rule_lock); 649862306a36Sopenharmony_ci if (remove_rule) { 649962306a36Sopenharmony_ci struct ice_sw_rule_lkup_rx_tx *s_rule; 650062306a36Sopenharmony_ci u16 rule_buf_sz; 650162306a36Sopenharmony_ci 650262306a36Sopenharmony_ci rule_buf_sz = ICE_SW_RULE_RX_TX_NO_HDR_SIZE(s_rule); 650362306a36Sopenharmony_ci s_rule = kzalloc(rule_buf_sz, GFP_KERNEL); 650462306a36Sopenharmony_ci if (!s_rule) 650562306a36Sopenharmony_ci return -ENOMEM; 650662306a36Sopenharmony_ci s_rule->act = 0; 650762306a36Sopenharmony_ci s_rule->index = cpu_to_le16(list_elem->rule_info.fltr_rule_id); 650862306a36Sopenharmony_ci s_rule->hdr_len = 0; 650962306a36Sopenharmony_ci status = ice_aq_sw_rules(hw, (struct ice_aqc_sw_rules *)s_rule, 651062306a36Sopenharmony_ci rule_buf_sz, 1, 651162306a36Sopenharmony_ci ice_aqc_opc_remove_sw_rules, NULL); 651262306a36Sopenharmony_ci if (!status || status == -ENOENT) { 651362306a36Sopenharmony_ci struct ice_switch_info *sw = hw->switch_info; 651462306a36Sopenharmony_ci 651562306a36Sopenharmony_ci mutex_lock(rule_lock); 651662306a36Sopenharmony_ci list_del(&list_elem->list_entry); 651762306a36Sopenharmony_ci devm_kfree(ice_hw_to_dev(hw), list_elem->lkups); 651862306a36Sopenharmony_ci devm_kfree(ice_hw_to_dev(hw), list_elem); 651962306a36Sopenharmony_ci mutex_unlock(rule_lock); 652062306a36Sopenharmony_ci if (list_empty(&sw->recp_list[rid].filt_rules)) 652162306a36Sopenharmony_ci sw->recp_list[rid].adv_rule = false; 652262306a36Sopenharmony_ci } 652362306a36Sopenharmony_ci kfree(s_rule); 652462306a36Sopenharmony_ci } 652562306a36Sopenharmony_ci return status; 652662306a36Sopenharmony_ci} 652762306a36Sopenharmony_ci 652862306a36Sopenharmony_ci/** 652962306a36Sopenharmony_ci * ice_rem_adv_rule_by_id - removes existing advanced switch rule by ID 653062306a36Sopenharmony_ci * @hw: pointer to the hardware structure 653162306a36Sopenharmony_ci * @remove_entry: data struct which holds rule_id, VSI handle and recipe ID 653262306a36Sopenharmony_ci * 653362306a36Sopenharmony_ci * This function is used to remove 1 rule at a time. The removal is based on 653462306a36Sopenharmony_ci * the remove_entry parameter. This function will remove rule for a given 653562306a36Sopenharmony_ci * vsi_handle with a given rule_id which is passed as parameter in remove_entry 653662306a36Sopenharmony_ci */ 653762306a36Sopenharmony_ciint 653862306a36Sopenharmony_ciice_rem_adv_rule_by_id(struct ice_hw *hw, 653962306a36Sopenharmony_ci struct ice_rule_query_data *remove_entry) 654062306a36Sopenharmony_ci{ 654162306a36Sopenharmony_ci struct ice_adv_fltr_mgmt_list_entry *list_itr; 654262306a36Sopenharmony_ci struct list_head *list_head; 654362306a36Sopenharmony_ci struct ice_adv_rule_info rinfo; 654462306a36Sopenharmony_ci struct ice_switch_info *sw; 654562306a36Sopenharmony_ci 654662306a36Sopenharmony_ci sw = hw->switch_info; 654762306a36Sopenharmony_ci if (!sw->recp_list[remove_entry->rid].recp_created) 654862306a36Sopenharmony_ci return -EINVAL; 654962306a36Sopenharmony_ci list_head = &sw->recp_list[remove_entry->rid].filt_rules; 655062306a36Sopenharmony_ci list_for_each_entry(list_itr, list_head, list_entry) { 655162306a36Sopenharmony_ci if (list_itr->rule_info.fltr_rule_id == 655262306a36Sopenharmony_ci remove_entry->rule_id) { 655362306a36Sopenharmony_ci rinfo = list_itr->rule_info; 655462306a36Sopenharmony_ci rinfo.sw_act.vsi_handle = remove_entry->vsi_handle; 655562306a36Sopenharmony_ci return ice_rem_adv_rule(hw, list_itr->lkups, 655662306a36Sopenharmony_ci list_itr->lkups_cnt, &rinfo); 655762306a36Sopenharmony_ci } 655862306a36Sopenharmony_ci } 655962306a36Sopenharmony_ci /* either list is empty or unable to find rule */ 656062306a36Sopenharmony_ci return -ENOENT; 656162306a36Sopenharmony_ci} 656262306a36Sopenharmony_ci 656362306a36Sopenharmony_ci/** 656462306a36Sopenharmony_ci * ice_replay_vsi_adv_rule - Replay advanced rule for requested VSI 656562306a36Sopenharmony_ci * @hw: pointer to the hardware structure 656662306a36Sopenharmony_ci * @vsi_handle: driver VSI handle 656762306a36Sopenharmony_ci * @list_head: list for which filters need to be replayed 656862306a36Sopenharmony_ci * 656962306a36Sopenharmony_ci * Replay the advanced rule for the given VSI. 657062306a36Sopenharmony_ci */ 657162306a36Sopenharmony_cistatic int 657262306a36Sopenharmony_ciice_replay_vsi_adv_rule(struct ice_hw *hw, u16 vsi_handle, 657362306a36Sopenharmony_ci struct list_head *list_head) 657462306a36Sopenharmony_ci{ 657562306a36Sopenharmony_ci struct ice_rule_query_data added_entry = { 0 }; 657662306a36Sopenharmony_ci struct ice_adv_fltr_mgmt_list_entry *adv_fltr; 657762306a36Sopenharmony_ci int status = 0; 657862306a36Sopenharmony_ci 657962306a36Sopenharmony_ci if (list_empty(list_head)) 658062306a36Sopenharmony_ci return status; 658162306a36Sopenharmony_ci list_for_each_entry(adv_fltr, list_head, list_entry) { 658262306a36Sopenharmony_ci struct ice_adv_rule_info *rinfo = &adv_fltr->rule_info; 658362306a36Sopenharmony_ci u16 lk_cnt = adv_fltr->lkups_cnt; 658462306a36Sopenharmony_ci 658562306a36Sopenharmony_ci if (vsi_handle != rinfo->sw_act.vsi_handle) 658662306a36Sopenharmony_ci continue; 658762306a36Sopenharmony_ci status = ice_add_adv_rule(hw, adv_fltr->lkups, lk_cnt, rinfo, 658862306a36Sopenharmony_ci &added_entry); 658962306a36Sopenharmony_ci if (status) 659062306a36Sopenharmony_ci break; 659162306a36Sopenharmony_ci } 659262306a36Sopenharmony_ci return status; 659362306a36Sopenharmony_ci} 659462306a36Sopenharmony_ci 659562306a36Sopenharmony_ci/** 659662306a36Sopenharmony_ci * ice_replay_vsi_all_fltr - replay all filters stored in bookkeeping lists 659762306a36Sopenharmony_ci * @hw: pointer to the hardware structure 659862306a36Sopenharmony_ci * @vsi_handle: driver VSI handle 659962306a36Sopenharmony_ci * 660062306a36Sopenharmony_ci * Replays filters for requested VSI via vsi_handle. 660162306a36Sopenharmony_ci */ 660262306a36Sopenharmony_ciint ice_replay_vsi_all_fltr(struct ice_hw *hw, u16 vsi_handle) 660362306a36Sopenharmony_ci{ 660462306a36Sopenharmony_ci struct ice_switch_info *sw = hw->switch_info; 660562306a36Sopenharmony_ci int status; 660662306a36Sopenharmony_ci u8 i; 660762306a36Sopenharmony_ci 660862306a36Sopenharmony_ci for (i = 0; i < ICE_MAX_NUM_RECIPES; i++) { 660962306a36Sopenharmony_ci struct list_head *head; 661062306a36Sopenharmony_ci 661162306a36Sopenharmony_ci head = &sw->recp_list[i].filt_replay_rules; 661262306a36Sopenharmony_ci if (!sw->recp_list[i].adv_rule) 661362306a36Sopenharmony_ci status = ice_replay_vsi_fltr(hw, vsi_handle, i, head); 661462306a36Sopenharmony_ci else 661562306a36Sopenharmony_ci status = ice_replay_vsi_adv_rule(hw, vsi_handle, head); 661662306a36Sopenharmony_ci if (status) 661762306a36Sopenharmony_ci return status; 661862306a36Sopenharmony_ci } 661962306a36Sopenharmony_ci return status; 662062306a36Sopenharmony_ci} 662162306a36Sopenharmony_ci 662262306a36Sopenharmony_ci/** 662362306a36Sopenharmony_ci * ice_rm_all_sw_replay_rule_info - deletes filter replay rules 662462306a36Sopenharmony_ci * @hw: pointer to the HW struct 662562306a36Sopenharmony_ci * 662662306a36Sopenharmony_ci * Deletes the filter replay rules. 662762306a36Sopenharmony_ci */ 662862306a36Sopenharmony_civoid ice_rm_all_sw_replay_rule_info(struct ice_hw *hw) 662962306a36Sopenharmony_ci{ 663062306a36Sopenharmony_ci struct ice_switch_info *sw = hw->switch_info; 663162306a36Sopenharmony_ci u8 i; 663262306a36Sopenharmony_ci 663362306a36Sopenharmony_ci if (!sw) 663462306a36Sopenharmony_ci return; 663562306a36Sopenharmony_ci 663662306a36Sopenharmony_ci for (i = 0; i < ICE_MAX_NUM_RECIPES; i++) { 663762306a36Sopenharmony_ci if (!list_empty(&sw->recp_list[i].filt_replay_rules)) { 663862306a36Sopenharmony_ci struct list_head *l_head; 663962306a36Sopenharmony_ci 664062306a36Sopenharmony_ci l_head = &sw->recp_list[i].filt_replay_rules; 664162306a36Sopenharmony_ci if (!sw->recp_list[i].adv_rule) 664262306a36Sopenharmony_ci ice_rem_sw_rule_info(hw, l_head); 664362306a36Sopenharmony_ci else 664462306a36Sopenharmony_ci ice_rem_adv_rule_info(hw, l_head); 664562306a36Sopenharmony_ci } 664662306a36Sopenharmony_ci } 664762306a36Sopenharmony_ci} 6648