11d09792aSZiyang Xuan /* SPDX-License-Identifier: BSD-3-Clause 21d09792aSZiyang Xuan * Copyright(c) 2017 Huawei Technologies Co., Ltd 31d09792aSZiyang Xuan */ 41d09792aSZiyang Xuan 51d09792aSZiyang Xuan #include <rte_pci.h> 61d09792aSZiyang Xuan #include <rte_bus_pci.h> 7df96fd0dSBruce Richardson #include <ethdev_pci.h> 864727024SZiyang Xuan #include <rte_mbuf.h> 91d09792aSZiyang Xuan #include <rte_malloc.h> 101d09792aSZiyang Xuan #include <rte_memcpy.h> 1164727024SZiyang Xuan #include <rte_mempool.h> 1264727024SZiyang Xuan #include <rte_errno.h> 13fdba3bf1SXiaoyun Wang #include <rte_ether.h> 141d09792aSZiyang Xuan 151d09792aSZiyang Xuan #include "base/hinic_compat.h" 161d09792aSZiyang Xuan #include "base/hinic_pmd_hwdev.h" 1764727024SZiyang Xuan #include "base/hinic_pmd_hwif.h" 1864727024SZiyang Xuan #include "base/hinic_pmd_wq.h" 1964727024SZiyang Xuan #include "base/hinic_pmd_cfg.h" 2064727024SZiyang Xuan #include "base/hinic_pmd_mgmt.h" 2164727024SZiyang Xuan #include "base/hinic_pmd_cmdq.h" 221d09792aSZiyang Xuan #include "base/hinic_pmd_niccfg.h" 2364727024SZiyang Xuan #include "base/hinic_pmd_nicio.h" 246691acefSXiaoyun Wang #include "base/hinic_pmd_mbox.h" 251d09792aSZiyang Xuan #include "hinic_pmd_ethdev.h" 2664727024SZiyang Xuan #include "hinic_pmd_tx.h" 2764727024SZiyang Xuan #include "hinic_pmd_rx.h" 281d09792aSZiyang Xuan 291d09792aSZiyang Xuan /* Vendor ID used by Huawei devices */ 301d09792aSZiyang Xuan #define HINIC_HUAWEI_VENDOR_ID 0x19E5 311d09792aSZiyang Xuan 321d09792aSZiyang Xuan /* Hinic devices */ 331d09792aSZiyang Xuan #define HINIC_DEV_ID_PRD 0x1822 346691acefSXiaoyun Wang #define HINIC_DEV_ID_VF 0x375E 356691acefSXiaoyun Wang #define HINIC_DEV_ID_VF_HV 0x379E 366691acefSXiaoyun Wang 376691acefSXiaoyun Wang /* Mezz card for Blade Server */ 381d09792aSZiyang Xuan #define HINIC_DEV_ID_MEZZ_25GE 0x0210 391d09792aSZiyang Xuan #define HINIC_DEV_ID_MEZZ_100GE 0x0205 401d09792aSZiyang Xuan 416691acefSXiaoyun Wang /* 2*25G and 2*100G card */ 426691acefSXiaoyun Wang #define HINIC_DEV_ID_1822_DUAL_25GE 0x0206 436691acefSXiaoyun Wang #define HINIC_DEV_ID_1822_100GE 0x0200 446691acefSXiaoyun Wang 4564727024SZiyang Xuan #define HINIC_SERVICE_MODE_NIC 2 4664727024SZiyang Xuan 4764727024SZiyang Xuan #define HINIC_INTR_CB_UNREG_MAX_RETRIES 10 4864727024SZiyang Xuan 4964727024SZiyang Xuan #define DEFAULT_BASE_COS 4 5064727024SZiyang Xuan #define NR_MAX_COS 8 5164727024SZiyang Xuan 521d09792aSZiyang Xuan #define HINIC_MIN_RX_BUF_SIZE 1024 5300499a22SXiaoyun Wang #define HINIC_MAX_UC_MAC_ADDRS 128 5400499a22SXiaoyun Wang #define HINIC_MAX_MC_MAC_ADDRS 2048 55483b4817SXiaoyun Wang 56483b4817SXiaoyun Wang #define HINIC_DEFAULT_BURST_SIZE 32 57483b4817SXiaoyun Wang #define HINIC_DEFAULT_NB_QUEUES 1 58483b4817SXiaoyun Wang #define HINIC_DEFAULT_RING_SIZE 1024 591b7b9f17SXiaoyun Wang #define HINIC_MAX_LRO_SIZE 65536 60483b4817SXiaoyun Wang 61fdba3bf1SXiaoyun Wang /* 62fdba3bf1SXiaoyun Wang * vlan_id is a 12 bit number. 63fdba3bf1SXiaoyun Wang * The VFTA array is actually a 4096 bit array, 128 of 32bit elements. 64fdba3bf1SXiaoyun Wang * 2^5 = 32. The val of lower 5 bits specifies the bit in the 32bit element. 65fdba3bf1SXiaoyun Wang * The higher 7 bit val specifies VFTA array index. 66fdba3bf1SXiaoyun Wang */ 67fdba3bf1SXiaoyun Wang #define HINIC_VFTA_BIT(vlan_id) (1 << ((vlan_id) & 0x1F)) 68fdba3bf1SXiaoyun Wang #define HINIC_VFTA_IDX(vlan_id) ((vlan_id) >> 5) 69fdba3bf1SXiaoyun Wang 70fdba3bf1SXiaoyun Wang #define HINIC_VLAN_FILTER_EN (1U << 0) 71fdba3bf1SXiaoyun Wang 728260eba6SXiaoyun Wang #define HINIC_MTU_TO_PKTLEN(mtu) \ 738260eba6SXiaoyun Wang ((mtu) + ETH_HLEN + ETH_CRC_LEN) 748260eba6SXiaoyun Wang 758260eba6SXiaoyun Wang #define HINIC_PKTLEN_TO_MTU(pktlen) \ 768260eba6SXiaoyun Wang ((pktlen) - (ETH_HLEN + ETH_CRC_LEN)) 778260eba6SXiaoyun Wang 78e542ab51SSteve Yang /* The max frame size with default MTU */ 79e542ab51SSteve Yang #define HINIC_ETH_MAX_LEN (RTE_ETHER_MTU + ETH_HLEN + ETH_CRC_LEN) 80e542ab51SSteve Yang 819d4878efSXiaoyun Wang /* lro numer limit for one packet */ 829d4878efSXiaoyun Wang #define HINIC_LRO_WQE_NUM_DEFAULT 8 839d4878efSXiaoyun Wang 84cb7b6606SZiyang Xuan struct hinic_xstats_name_off { 85cb7b6606SZiyang Xuan char name[RTE_ETH_XSTATS_NAME_SIZE]; 86cb7b6606SZiyang Xuan u32 offset; 87cb7b6606SZiyang Xuan }; 88cb7b6606SZiyang Xuan 89cb7b6606SZiyang Xuan #define HINIC_FUNC_STAT(_stat_item) { \ 90cb7b6606SZiyang Xuan .name = #_stat_item, \ 91cb7b6606SZiyang Xuan .offset = offsetof(struct hinic_vport_stats, _stat_item) \ 92cb7b6606SZiyang Xuan } 93cb7b6606SZiyang Xuan 94cb7b6606SZiyang Xuan #define HINIC_PORT_STAT(_stat_item) { \ 95cb7b6606SZiyang Xuan .name = #_stat_item, \ 96cb7b6606SZiyang Xuan .offset = offsetof(struct hinic_phy_port_stats, _stat_item) \ 97cb7b6606SZiyang Xuan } 98cb7b6606SZiyang Xuan 99cb7b6606SZiyang Xuan static const struct hinic_xstats_name_off hinic_vport_stats_strings[] = { 100cb7b6606SZiyang Xuan HINIC_FUNC_STAT(tx_unicast_pkts_vport), 101cb7b6606SZiyang Xuan HINIC_FUNC_STAT(tx_unicast_bytes_vport), 102cb7b6606SZiyang Xuan HINIC_FUNC_STAT(tx_multicast_pkts_vport), 103cb7b6606SZiyang Xuan HINIC_FUNC_STAT(tx_multicast_bytes_vport), 104cb7b6606SZiyang Xuan HINIC_FUNC_STAT(tx_broadcast_pkts_vport), 105cb7b6606SZiyang Xuan HINIC_FUNC_STAT(tx_broadcast_bytes_vport), 106cb7b6606SZiyang Xuan 107cb7b6606SZiyang Xuan HINIC_FUNC_STAT(rx_unicast_pkts_vport), 108cb7b6606SZiyang Xuan HINIC_FUNC_STAT(rx_unicast_bytes_vport), 109cb7b6606SZiyang Xuan HINIC_FUNC_STAT(rx_multicast_pkts_vport), 110cb7b6606SZiyang Xuan HINIC_FUNC_STAT(rx_multicast_bytes_vport), 111cb7b6606SZiyang Xuan HINIC_FUNC_STAT(rx_broadcast_pkts_vport), 112cb7b6606SZiyang Xuan HINIC_FUNC_STAT(rx_broadcast_bytes_vport), 113cb7b6606SZiyang Xuan 114cb7b6606SZiyang Xuan HINIC_FUNC_STAT(tx_discard_vport), 115cb7b6606SZiyang Xuan HINIC_FUNC_STAT(rx_discard_vport), 116cb7b6606SZiyang Xuan HINIC_FUNC_STAT(tx_err_vport), 117cb7b6606SZiyang Xuan HINIC_FUNC_STAT(rx_err_vport), 118cb7b6606SZiyang Xuan }; 119cb7b6606SZiyang Xuan 120cb7b6606SZiyang Xuan #define HINIC_VPORT_XSTATS_NUM (sizeof(hinic_vport_stats_strings) / \ 121cb7b6606SZiyang Xuan sizeof(hinic_vport_stats_strings[0])) 122cb7b6606SZiyang Xuan 123cb7b6606SZiyang Xuan static const struct hinic_xstats_name_off hinic_phyport_stats_strings[] = { 124cb7b6606SZiyang Xuan HINIC_PORT_STAT(mac_rx_total_pkt_num), 125cb7b6606SZiyang Xuan HINIC_PORT_STAT(mac_rx_total_oct_num), 126cb7b6606SZiyang Xuan HINIC_PORT_STAT(mac_rx_bad_pkt_num), 127cb7b6606SZiyang Xuan HINIC_PORT_STAT(mac_rx_bad_oct_num), 128cb7b6606SZiyang Xuan HINIC_PORT_STAT(mac_rx_good_pkt_num), 129cb7b6606SZiyang Xuan HINIC_PORT_STAT(mac_rx_good_oct_num), 130cb7b6606SZiyang Xuan HINIC_PORT_STAT(mac_rx_uni_pkt_num), 131cb7b6606SZiyang Xuan HINIC_PORT_STAT(mac_rx_multi_pkt_num), 132cb7b6606SZiyang Xuan HINIC_PORT_STAT(mac_rx_broad_pkt_num), 133cb7b6606SZiyang Xuan HINIC_PORT_STAT(mac_tx_total_pkt_num), 134cb7b6606SZiyang Xuan HINIC_PORT_STAT(mac_tx_total_oct_num), 135cb7b6606SZiyang Xuan HINIC_PORT_STAT(mac_tx_bad_pkt_num), 136cb7b6606SZiyang Xuan HINIC_PORT_STAT(mac_tx_bad_oct_num), 137cb7b6606SZiyang Xuan HINIC_PORT_STAT(mac_tx_good_pkt_num), 138cb7b6606SZiyang Xuan HINIC_PORT_STAT(mac_tx_good_oct_num), 139cb7b6606SZiyang Xuan HINIC_PORT_STAT(mac_tx_uni_pkt_num), 140cb7b6606SZiyang Xuan HINIC_PORT_STAT(mac_tx_multi_pkt_num), 141cb7b6606SZiyang Xuan HINIC_PORT_STAT(mac_tx_broad_pkt_num), 142cb7b6606SZiyang Xuan HINIC_PORT_STAT(mac_rx_fragment_pkt_num), 143cb7b6606SZiyang Xuan HINIC_PORT_STAT(mac_rx_undersize_pkt_num), 144cb7b6606SZiyang Xuan HINIC_PORT_STAT(mac_rx_undermin_pkt_num), 145cb7b6606SZiyang Xuan HINIC_PORT_STAT(mac_rx_64_oct_pkt_num), 146cb7b6606SZiyang Xuan HINIC_PORT_STAT(mac_rx_65_127_oct_pkt_num), 147cb7b6606SZiyang Xuan HINIC_PORT_STAT(mac_rx_128_255_oct_pkt_num), 148cb7b6606SZiyang Xuan HINIC_PORT_STAT(mac_rx_256_511_oct_pkt_num), 149cb7b6606SZiyang Xuan HINIC_PORT_STAT(mac_rx_512_1023_oct_pkt_num), 150cb7b6606SZiyang Xuan HINIC_PORT_STAT(mac_rx_1024_1518_oct_pkt_num), 151cb7b6606SZiyang Xuan HINIC_PORT_STAT(mac_rx_1519_2047_oct_pkt_num), 152cb7b6606SZiyang Xuan HINIC_PORT_STAT(mac_rx_2048_4095_oct_pkt_num), 153cb7b6606SZiyang Xuan HINIC_PORT_STAT(mac_rx_4096_8191_oct_pkt_num), 154cb7b6606SZiyang Xuan HINIC_PORT_STAT(mac_rx_8192_9216_oct_pkt_num), 155cb7b6606SZiyang Xuan HINIC_PORT_STAT(mac_rx_9217_12287_oct_pkt_num), 156cb7b6606SZiyang Xuan HINIC_PORT_STAT(mac_rx_12288_16383_oct_pkt_num), 157cb7b6606SZiyang Xuan HINIC_PORT_STAT(mac_rx_1519_max_bad_pkt_num), 158cb7b6606SZiyang Xuan HINIC_PORT_STAT(mac_rx_1519_max_good_pkt_num), 159cb7b6606SZiyang Xuan HINIC_PORT_STAT(mac_rx_oversize_pkt_num), 160cb7b6606SZiyang Xuan HINIC_PORT_STAT(mac_rx_jabber_pkt_num), 161cb7b6606SZiyang Xuan HINIC_PORT_STAT(mac_rx_mac_pause_num), 162cb7b6606SZiyang Xuan HINIC_PORT_STAT(mac_rx_pfc_pkt_num), 163cb7b6606SZiyang Xuan HINIC_PORT_STAT(mac_rx_pfc_pri0_pkt_num), 164cb7b6606SZiyang Xuan HINIC_PORT_STAT(mac_rx_pfc_pri1_pkt_num), 165cb7b6606SZiyang Xuan HINIC_PORT_STAT(mac_rx_pfc_pri2_pkt_num), 166cb7b6606SZiyang Xuan HINIC_PORT_STAT(mac_rx_pfc_pri3_pkt_num), 167cb7b6606SZiyang Xuan HINIC_PORT_STAT(mac_rx_pfc_pri4_pkt_num), 168cb7b6606SZiyang Xuan HINIC_PORT_STAT(mac_rx_pfc_pri5_pkt_num), 169cb7b6606SZiyang Xuan HINIC_PORT_STAT(mac_rx_pfc_pri6_pkt_num), 170cb7b6606SZiyang Xuan HINIC_PORT_STAT(mac_rx_pfc_pri7_pkt_num), 171cb7b6606SZiyang Xuan HINIC_PORT_STAT(mac_rx_mac_control_pkt_num), 172cb7b6606SZiyang Xuan HINIC_PORT_STAT(mac_rx_sym_err_pkt_num), 173cb7b6606SZiyang Xuan HINIC_PORT_STAT(mac_rx_fcs_err_pkt_num), 174cb7b6606SZiyang Xuan HINIC_PORT_STAT(mac_rx_send_app_good_pkt_num), 175cb7b6606SZiyang Xuan HINIC_PORT_STAT(mac_rx_send_app_bad_pkt_num), 176cb7b6606SZiyang Xuan HINIC_PORT_STAT(mac_tx_fragment_pkt_num), 177cb7b6606SZiyang Xuan HINIC_PORT_STAT(mac_tx_undersize_pkt_num), 178cb7b6606SZiyang Xuan HINIC_PORT_STAT(mac_tx_undermin_pkt_num), 179cb7b6606SZiyang Xuan HINIC_PORT_STAT(mac_tx_64_oct_pkt_num), 180cb7b6606SZiyang Xuan HINIC_PORT_STAT(mac_tx_65_127_oct_pkt_num), 181cb7b6606SZiyang Xuan HINIC_PORT_STAT(mac_tx_128_255_oct_pkt_num), 182cb7b6606SZiyang Xuan HINIC_PORT_STAT(mac_tx_256_511_oct_pkt_num), 183cb7b6606SZiyang Xuan HINIC_PORT_STAT(mac_tx_512_1023_oct_pkt_num), 184cb7b6606SZiyang Xuan HINIC_PORT_STAT(mac_tx_1024_1518_oct_pkt_num), 185cb7b6606SZiyang Xuan HINIC_PORT_STAT(mac_tx_1519_2047_oct_pkt_num), 186cb7b6606SZiyang Xuan HINIC_PORT_STAT(mac_tx_2048_4095_oct_pkt_num), 187cb7b6606SZiyang Xuan HINIC_PORT_STAT(mac_tx_4096_8191_oct_pkt_num), 188cb7b6606SZiyang Xuan HINIC_PORT_STAT(mac_tx_8192_9216_oct_pkt_num), 189cb7b6606SZiyang Xuan HINIC_PORT_STAT(mac_tx_9217_12287_oct_pkt_num), 190cb7b6606SZiyang Xuan HINIC_PORT_STAT(mac_tx_12288_16383_oct_pkt_num), 191cb7b6606SZiyang Xuan HINIC_PORT_STAT(mac_tx_1519_max_bad_pkt_num), 192cb7b6606SZiyang Xuan HINIC_PORT_STAT(mac_tx_1519_max_good_pkt_num), 193cb7b6606SZiyang Xuan HINIC_PORT_STAT(mac_tx_oversize_pkt_num), 194cb7b6606SZiyang Xuan HINIC_PORT_STAT(mac_trans_jabber_pkt_num), 195cb7b6606SZiyang Xuan HINIC_PORT_STAT(mac_tx_mac_pause_num), 196cb7b6606SZiyang Xuan HINIC_PORT_STAT(mac_tx_pfc_pkt_num), 197cb7b6606SZiyang Xuan HINIC_PORT_STAT(mac_tx_pfc_pri0_pkt_num), 198cb7b6606SZiyang Xuan HINIC_PORT_STAT(mac_tx_pfc_pri1_pkt_num), 199cb7b6606SZiyang Xuan HINIC_PORT_STAT(mac_tx_pfc_pri2_pkt_num), 200cb7b6606SZiyang Xuan HINIC_PORT_STAT(mac_tx_pfc_pri3_pkt_num), 201cb7b6606SZiyang Xuan HINIC_PORT_STAT(mac_tx_pfc_pri4_pkt_num), 202cb7b6606SZiyang Xuan HINIC_PORT_STAT(mac_tx_pfc_pri5_pkt_num), 203cb7b6606SZiyang Xuan HINIC_PORT_STAT(mac_tx_pfc_pri6_pkt_num), 204cb7b6606SZiyang Xuan HINIC_PORT_STAT(mac_tx_pfc_pri7_pkt_num), 205cb7b6606SZiyang Xuan HINIC_PORT_STAT(mac_tx_mac_control_pkt_num), 206cb7b6606SZiyang Xuan HINIC_PORT_STAT(mac_tx_err_all_pkt_num), 207cb7b6606SZiyang Xuan HINIC_PORT_STAT(mac_tx_from_app_good_pkt_num), 208cb7b6606SZiyang Xuan HINIC_PORT_STAT(mac_tx_from_app_bad_pkt_num), 209cb7b6606SZiyang Xuan }; 210cb7b6606SZiyang Xuan 211cb7b6606SZiyang Xuan #define HINIC_PHYPORT_XSTATS_NUM (sizeof(hinic_phyport_stats_strings) / \ 212cb7b6606SZiyang Xuan sizeof(hinic_phyport_stats_strings[0])) 213cb7b6606SZiyang Xuan 214cb7b6606SZiyang Xuan static const struct hinic_xstats_name_off hinic_rxq_stats_strings[] = { 215cb7b6606SZiyang Xuan {"rx_nombuf", offsetof(struct hinic_rxq_stats, rx_nombuf)}, 216cb7b6606SZiyang Xuan {"burst_pkt", offsetof(struct hinic_rxq_stats, burst_pkts)}, 217cb7b6606SZiyang Xuan }; 218cb7b6606SZiyang Xuan 219cb7b6606SZiyang Xuan #define HINIC_RXQ_XSTATS_NUM (sizeof(hinic_rxq_stats_strings) / \ 220cb7b6606SZiyang Xuan sizeof(hinic_rxq_stats_strings[0])) 221cb7b6606SZiyang Xuan 222cb7b6606SZiyang Xuan static const struct hinic_xstats_name_off hinic_txq_stats_strings[] = { 223cb7b6606SZiyang Xuan {"tx_busy", offsetof(struct hinic_txq_stats, tx_busy)}, 224cb7b6606SZiyang Xuan {"offload_errors", offsetof(struct hinic_txq_stats, off_errs)}, 225cb7b6606SZiyang Xuan {"copy_pkts", offsetof(struct hinic_txq_stats, cpy_pkts)}, 226cb7b6606SZiyang Xuan {"rl_drop", offsetof(struct hinic_txq_stats, rl_drop)}, 227cb7b6606SZiyang Xuan {"burst_pkts", offsetof(struct hinic_txq_stats, burst_pkts)}, 22854faba22SXiaoyun Wang {"sge_len0", offsetof(struct hinic_txq_stats, sge_len0)}, 22954faba22SXiaoyun Wang {"mbuf_null", offsetof(struct hinic_txq_stats, mbuf_null)}, 230cb7b6606SZiyang Xuan }; 231cb7b6606SZiyang Xuan 232cb7b6606SZiyang Xuan #define HINIC_TXQ_XSTATS_NUM (sizeof(hinic_txq_stats_strings) / \ 233cb7b6606SZiyang Xuan sizeof(hinic_txq_stats_strings[0])) 234cb7b6606SZiyang Xuan 235cb7b6606SZiyang Xuan static int hinic_xstats_calc_num(struct hinic_nic_dev *nic_dev) 236cb7b6606SZiyang Xuan { 2376691acefSXiaoyun Wang if (HINIC_IS_VF(nic_dev->hwdev)) { 2386691acefSXiaoyun Wang return (HINIC_VPORT_XSTATS_NUM + 2396691acefSXiaoyun Wang HINIC_RXQ_XSTATS_NUM * nic_dev->num_rq + 2406691acefSXiaoyun Wang HINIC_TXQ_XSTATS_NUM * nic_dev->num_sq); 2416691acefSXiaoyun Wang } else { 242cb7b6606SZiyang Xuan return (HINIC_VPORT_XSTATS_NUM + 243cb7b6606SZiyang Xuan HINIC_PHYPORT_XSTATS_NUM + 244cb7b6606SZiyang Xuan HINIC_RXQ_XSTATS_NUM * nic_dev->num_rq + 245cb7b6606SZiyang Xuan HINIC_TXQ_XSTATS_NUM * nic_dev->num_sq); 246cb7b6606SZiyang Xuan } 2476691acefSXiaoyun Wang } 248cb7b6606SZiyang Xuan 2491d09792aSZiyang Xuan static const struct rte_eth_desc_lim hinic_rx_desc_lim = { 2501d09792aSZiyang Xuan .nb_max = HINIC_MAX_QUEUE_DEPTH, 2511d09792aSZiyang Xuan .nb_min = HINIC_MIN_QUEUE_DEPTH, 2521d09792aSZiyang Xuan .nb_align = HINIC_RXD_ALIGN, 2531d09792aSZiyang Xuan }; 2541d09792aSZiyang Xuan 2551d09792aSZiyang Xuan static const struct rte_eth_desc_lim hinic_tx_desc_lim = { 2561d09792aSZiyang Xuan .nb_max = HINIC_MAX_QUEUE_DEPTH, 2571d09792aSZiyang Xuan .nb_min = HINIC_MIN_QUEUE_DEPTH, 2581d09792aSZiyang Xuan .nb_align = HINIC_TXD_ALIGN, 2591d09792aSZiyang Xuan }; 2601d09792aSZiyang Xuan 261fdba3bf1SXiaoyun Wang static int hinic_vlan_offload_set(struct rte_eth_dev *dev, int mask); 2622c473729SZiyang Xuan 2631d09792aSZiyang Xuan /** 26464727024SZiyang Xuan * Interrupt handler triggered by NIC for handling 26564727024SZiyang Xuan * specific event. 26664727024SZiyang Xuan * 26764727024SZiyang Xuan * @param: The address of parameter (struct rte_eth_dev *) regsitered before. 268c3ba1f0fSXiaoyun Wang */ 26964727024SZiyang Xuan static void hinic_dev_interrupt_handler(void *param) 27064727024SZiyang Xuan { 27164727024SZiyang Xuan struct rte_eth_dev *dev = param; 27264727024SZiyang Xuan struct hinic_nic_dev *nic_dev = HINIC_ETH_DEV_TO_PRIVATE_NIC_DEV(dev); 27364727024SZiyang Xuan 2740371535dSJoyce Kong if (!rte_bit_relaxed_get32(HINIC_DEV_INTR_EN, &nic_dev->dev_status)) { 27564727024SZiyang Xuan PMD_DRV_LOG(WARNING, "Device's interrupt is disabled, ignore interrupt event, dev_name: %s, port_id: %d", 27664727024SZiyang Xuan nic_dev->proc_dev_name, dev->data->port_id); 27764727024SZiyang Xuan return; 27864727024SZiyang Xuan } 27964727024SZiyang Xuan 28064727024SZiyang Xuan /* aeq0 msg handler */ 28164727024SZiyang Xuan hinic_dev_handle_aeq_event(nic_dev->hwdev, param); 28264727024SZiyang Xuan } 28364727024SZiyang Xuan 28464727024SZiyang Xuan /** 28564727024SZiyang Xuan * Ethernet device configuration. 28664727024SZiyang Xuan * 28764727024SZiyang Xuan * Prepare the driver for a given number of TX and RX queues, mtu size 28864727024SZiyang Xuan * and configure RSS. 28964727024SZiyang Xuan * 29064727024SZiyang Xuan * @param dev 29164727024SZiyang Xuan * Pointer to Ethernet device structure. 29264727024SZiyang Xuan * 29364727024SZiyang Xuan * @return 29464727024SZiyang Xuan * 0 on success, negative error value otherwise. 29564727024SZiyang Xuan */ 29664727024SZiyang Xuan static int hinic_dev_configure(struct rte_eth_dev *dev) 29764727024SZiyang Xuan { 29864727024SZiyang Xuan struct hinic_nic_dev *nic_dev; 29964727024SZiyang Xuan struct hinic_nic_io *nic_io; 30064727024SZiyang Xuan int err; 30164727024SZiyang Xuan 30264727024SZiyang Xuan nic_dev = HINIC_ETH_DEV_TO_PRIVATE_NIC_DEV(dev); 30364727024SZiyang Xuan nic_io = nic_dev->hwdev->nic_io; 30464727024SZiyang Xuan 30564727024SZiyang Xuan nic_dev->num_sq = dev->data->nb_tx_queues; 30664727024SZiyang Xuan nic_dev->num_rq = dev->data->nb_rx_queues; 30764727024SZiyang Xuan 30864727024SZiyang Xuan nic_io->num_sqs = dev->data->nb_tx_queues; 30964727024SZiyang Xuan nic_io->num_rqs = dev->data->nb_rx_queues; 31064727024SZiyang Xuan 31164727024SZiyang Xuan /* queue pair is max_num(sq, rq) */ 31264727024SZiyang Xuan nic_dev->num_qps = (nic_dev->num_sq > nic_dev->num_rq) ? 31364727024SZiyang Xuan nic_dev->num_sq : nic_dev->num_rq; 31464727024SZiyang Xuan nic_io->num_qps = nic_dev->num_qps; 31564727024SZiyang Xuan 31664727024SZiyang Xuan if (nic_dev->num_qps > nic_io->max_qps) { 31764727024SZiyang Xuan PMD_DRV_LOG(ERR, 31864727024SZiyang Xuan "Queue number out of range, get queue_num:%d, max_queue_num:%d", 31964727024SZiyang Xuan nic_dev->num_qps, nic_io->max_qps); 32064727024SZiyang Xuan return -EINVAL; 32164727024SZiyang Xuan } 32264727024SZiyang Xuan 32373fb89ddSAndrew Rybchenko if (dev->data->dev_conf.rxmode.mq_mode & ETH_MQ_RX_RSS_FLAG) 3248b945a7fSPavan Nikhilesh dev->data->dev_conf.rxmode.offloads |= DEV_RX_OFFLOAD_RSS_HASH; 3258b945a7fSPavan Nikhilesh 32664727024SZiyang Xuan /* mtu size is 256~9600 */ 32764727024SZiyang Xuan if (dev->data->dev_conf.rxmode.max_rx_pkt_len < HINIC_MIN_FRAME_SIZE || 32864727024SZiyang Xuan dev->data->dev_conf.rxmode.max_rx_pkt_len > 32964727024SZiyang Xuan HINIC_MAX_JUMBO_FRAME_SIZE) { 33064727024SZiyang Xuan PMD_DRV_LOG(ERR, 33164727024SZiyang Xuan "Max rx pkt len out of range, get max_rx_pkt_len:%d, " 33264727024SZiyang Xuan "expect between %d and %d", 33364727024SZiyang Xuan dev->data->dev_conf.rxmode.max_rx_pkt_len, 33464727024SZiyang Xuan HINIC_MIN_FRAME_SIZE, HINIC_MAX_JUMBO_FRAME_SIZE); 33564727024SZiyang Xuan return -EINVAL; 33664727024SZiyang Xuan } 33764727024SZiyang Xuan 33864727024SZiyang Xuan nic_dev->mtu_size = 33964727024SZiyang Xuan HINIC_PKTLEN_TO_MTU(dev->data->dev_conf.rxmode.max_rx_pkt_len); 34064727024SZiyang Xuan 34164727024SZiyang Xuan /* rss template */ 34264727024SZiyang Xuan err = hinic_config_mq_mode(dev, TRUE); 34364727024SZiyang Xuan if (err) { 34464727024SZiyang Xuan PMD_DRV_LOG(ERR, "Config multi-queue failed"); 34564727024SZiyang Xuan return err; 34664727024SZiyang Xuan } 34764727024SZiyang Xuan 348fdba3bf1SXiaoyun Wang /* init vlan offoad */ 349fdba3bf1SXiaoyun Wang err = hinic_vlan_offload_set(dev, 350fdba3bf1SXiaoyun Wang ETH_VLAN_STRIP_MASK | ETH_VLAN_FILTER_MASK); 351fdba3bf1SXiaoyun Wang if (err) { 3524f1af3cbSXiaoyun Wang PMD_DRV_LOG(ERR, "Initialize vlan filter and strip failed"); 353fdba3bf1SXiaoyun Wang (void)hinic_config_mq_mode(dev, FALSE); 354fdba3bf1SXiaoyun Wang return err; 355fdba3bf1SXiaoyun Wang } 356fdba3bf1SXiaoyun Wang 3571742421bSXiaoyun Wang /* clear fdir filter flag in function table */ 3581742421bSXiaoyun Wang hinic_free_fdir_filter(nic_dev); 3591742421bSXiaoyun Wang 36064727024SZiyang Xuan return HINIC_OK; 36164727024SZiyang Xuan } 36264727024SZiyang Xuan 36364727024SZiyang Xuan /** 3642c473729SZiyang Xuan * DPDK callback to create the receive queue. 3652c473729SZiyang Xuan * 3662c473729SZiyang Xuan * @param dev 3672c473729SZiyang Xuan * Pointer to Ethernet device structure. 3682c473729SZiyang Xuan * @param queue_idx 3692c473729SZiyang Xuan * RX queue index. 3702c473729SZiyang Xuan * @param nb_desc 3712c473729SZiyang Xuan * Number of descriptors for receive queue. 3722c473729SZiyang Xuan * @param socket_id 3732c473729SZiyang Xuan * NUMA socket on which memory must be allocated. 3742c473729SZiyang Xuan * @param rx_conf 3752c473729SZiyang Xuan * Thresholds parameters (unused_). 3762c473729SZiyang Xuan * @param mp 3772c473729SZiyang Xuan * Memory pool for buffer allocations. 3782c473729SZiyang Xuan * 3792c473729SZiyang Xuan * @return 3802c473729SZiyang Xuan * 0 on success, negative error value otherwise. 3812c473729SZiyang Xuan */ 3822c473729SZiyang Xuan static int hinic_rx_queue_setup(struct rte_eth_dev *dev, uint16_t queue_idx, 3832c473729SZiyang Xuan uint16_t nb_desc, unsigned int socket_id, 3842c473729SZiyang Xuan __rte_unused const struct rte_eth_rxconf *rx_conf, 3852c473729SZiyang Xuan struct rte_mempool *mp) 3862c473729SZiyang Xuan { 3872c473729SZiyang Xuan int rc; 3882c473729SZiyang Xuan struct hinic_nic_dev *nic_dev; 3892c473729SZiyang Xuan struct hinic_hwdev *hwdev; 3902c473729SZiyang Xuan struct hinic_rxq *rxq; 3912c473729SZiyang Xuan u16 rq_depth, rx_free_thresh; 3922c473729SZiyang Xuan u32 buf_size; 3932c473729SZiyang Xuan 3942c473729SZiyang Xuan nic_dev = HINIC_ETH_DEV_TO_PRIVATE_NIC_DEV(dev); 3952c473729SZiyang Xuan hwdev = nic_dev->hwdev; 3962c473729SZiyang Xuan 3972c473729SZiyang Xuan /* queue depth must be power of 2, otherwise will be aligned up */ 3982c473729SZiyang Xuan rq_depth = (nb_desc & (nb_desc - 1)) ? 3992c473729SZiyang Xuan ((u16)(1U << (ilog2(nb_desc) + 1))) : nb_desc; 4002c473729SZiyang Xuan 4012c473729SZiyang Xuan /* 4022c473729SZiyang Xuan * Validate number of receive descriptors. 4032c473729SZiyang Xuan * It must not exceed hardware maximum and minimum. 4042c473729SZiyang Xuan */ 4052c473729SZiyang Xuan if (rq_depth > HINIC_MAX_QUEUE_DEPTH || 4062c473729SZiyang Xuan rq_depth < HINIC_MIN_QUEUE_DEPTH) { 4072c473729SZiyang Xuan PMD_DRV_LOG(ERR, "RX queue depth is out of range from %d to %d, (nb_desc=%d, q_depth=%d, port=%d queue=%d)", 4082c473729SZiyang Xuan HINIC_MIN_QUEUE_DEPTH, HINIC_MAX_QUEUE_DEPTH, 4092c473729SZiyang Xuan (int)nb_desc, (int)rq_depth, 4102c473729SZiyang Xuan (int)dev->data->port_id, (int)queue_idx); 4112c473729SZiyang Xuan return -EINVAL; 4122c473729SZiyang Xuan } 4132c473729SZiyang Xuan 4142c473729SZiyang Xuan /* 4152c473729SZiyang Xuan * The RX descriptor ring will be cleaned after rxq->rx_free_thresh 4162c473729SZiyang Xuan * descriptors are used or if the number of descriptors required 4172c473729SZiyang Xuan * to transmit a packet is greater than the number of free RX 4182c473729SZiyang Xuan * descriptors. 4192c473729SZiyang Xuan * The following constraints must be satisfied: 4202c473729SZiyang Xuan * rx_free_thresh must be greater than 0. 4212c473729SZiyang Xuan * rx_free_thresh must be less than the size of the ring minus 1. 4222c473729SZiyang Xuan * When set to zero use default values. 4232c473729SZiyang Xuan */ 4242c473729SZiyang Xuan rx_free_thresh = (u16)((rx_conf->rx_free_thresh) ? 4252c473729SZiyang Xuan rx_conf->rx_free_thresh : HINIC_DEFAULT_RX_FREE_THRESH); 4262c473729SZiyang Xuan if (rx_free_thresh >= (rq_depth - 1)) { 4272c473729SZiyang Xuan PMD_DRV_LOG(ERR, "rx_free_thresh must be less than the number of RX descriptors minus 1. (rx_free_thresh=%u port=%d queue=%d)", 4282c473729SZiyang Xuan (unsigned int)rx_free_thresh, 4292c473729SZiyang Xuan (int)dev->data->port_id, 4302c473729SZiyang Xuan (int)queue_idx); 4312c473729SZiyang Xuan return -EINVAL; 4322c473729SZiyang Xuan } 4332c473729SZiyang Xuan 4342c473729SZiyang Xuan rxq = rte_zmalloc_socket("hinic_rx_queue", sizeof(struct hinic_rxq), 4352c473729SZiyang Xuan RTE_CACHE_LINE_SIZE, socket_id); 4362c473729SZiyang Xuan if (!rxq) { 4372c473729SZiyang Xuan PMD_DRV_LOG(ERR, "Allocate rxq[%d] failed, dev_name: %s", 4382c473729SZiyang Xuan queue_idx, dev->data->name); 4392c473729SZiyang Xuan return -ENOMEM; 4402c473729SZiyang Xuan } 4412c473729SZiyang Xuan nic_dev->rxqs[queue_idx] = rxq; 4422c473729SZiyang Xuan 4432c473729SZiyang Xuan /* alloc rx sq hw wqe page */ 4441b7b9f17SXiaoyun Wang rc = hinic_create_rq(hwdev, queue_idx, rq_depth, socket_id); 4452c473729SZiyang Xuan if (rc) { 4462c473729SZiyang Xuan PMD_DRV_LOG(ERR, "Create rxq[%d] failed, dev_name: %s, rq_depth: %d", 4472c473729SZiyang Xuan queue_idx, dev->data->name, rq_depth); 4482c473729SZiyang Xuan goto ceate_rq_fail; 4492c473729SZiyang Xuan } 4502c473729SZiyang Xuan 4512c473729SZiyang Xuan /* mbuf pool must be assigned before setup rx resources */ 4522c473729SZiyang Xuan rxq->mb_pool = mp; 4532c473729SZiyang Xuan 4542c473729SZiyang Xuan rc = 4552c473729SZiyang Xuan hinic_convert_rx_buf_size(rte_pktmbuf_data_room_size(rxq->mb_pool) - 4562c473729SZiyang Xuan RTE_PKTMBUF_HEADROOM, &buf_size); 4572c473729SZiyang Xuan if (rc) { 4582c473729SZiyang Xuan PMD_DRV_LOG(ERR, "Adjust buf size failed, dev_name: %s", 4592c473729SZiyang Xuan dev->data->name); 4602c473729SZiyang Xuan goto adjust_bufsize_fail; 4612c473729SZiyang Xuan } 4622c473729SZiyang Xuan 4632c473729SZiyang Xuan /* rx queue info, rearm control */ 4642c473729SZiyang Xuan rxq->wq = &hwdev->nic_io->rq_wq[queue_idx]; 4652c473729SZiyang Xuan rxq->pi_virt_addr = hwdev->nic_io->qps[queue_idx].rq.pi_virt_addr; 4662c473729SZiyang Xuan rxq->nic_dev = nic_dev; 4672c473729SZiyang Xuan rxq->q_id = queue_idx; 4682c473729SZiyang Xuan rxq->q_depth = rq_depth; 4692c473729SZiyang Xuan rxq->buf_len = (u16)buf_size; 4702c473729SZiyang Xuan rxq->rx_free_thresh = rx_free_thresh; 4711b7b9f17SXiaoyun Wang rxq->socket_id = socket_id; 4722c473729SZiyang Xuan 4732c473729SZiyang Xuan /* the last point cant do mbuf rearm in bulk */ 4742c473729SZiyang Xuan rxq->rxinfo_align_end = rxq->q_depth - rxq->rx_free_thresh; 4752c473729SZiyang Xuan 4762c473729SZiyang Xuan /* device port identifier */ 4772c473729SZiyang Xuan rxq->port_id = dev->data->port_id; 4782c473729SZiyang Xuan 4792c473729SZiyang Xuan /* alloc rx_cqe and prepare rq_wqe */ 4802c473729SZiyang Xuan rc = hinic_setup_rx_resources(rxq); 4812c473729SZiyang Xuan if (rc) { 4822c473729SZiyang Xuan PMD_DRV_LOG(ERR, "Setup rxq[%d] rx_resources failed, dev_name: %s", 4832c473729SZiyang Xuan queue_idx, dev->data->name); 4842c473729SZiyang Xuan goto setup_rx_res_err; 4852c473729SZiyang Xuan } 4862c473729SZiyang Xuan 4872c473729SZiyang Xuan /* record nic_dev rxq in rte_eth rx_queues */ 4882c473729SZiyang Xuan dev->data->rx_queues[queue_idx] = rxq; 4892c473729SZiyang Xuan 4902c473729SZiyang Xuan return 0; 4912c473729SZiyang Xuan 4922c473729SZiyang Xuan setup_rx_res_err: 4932c473729SZiyang Xuan adjust_bufsize_fail: 4942c473729SZiyang Xuan hinic_destroy_rq(hwdev, queue_idx); 4952c473729SZiyang Xuan 4962c473729SZiyang Xuan ceate_rq_fail: 4972c473729SZiyang Xuan rte_free(rxq); 4982c473729SZiyang Xuan 4992c473729SZiyang Xuan return rc; 5002c473729SZiyang Xuan } 5012c473729SZiyang Xuan 5022c473729SZiyang Xuan static void hinic_reset_rx_queue(struct rte_eth_dev *dev) 5032c473729SZiyang Xuan { 5042c473729SZiyang Xuan struct hinic_rxq *rxq; 5052c473729SZiyang Xuan struct hinic_nic_dev *nic_dev; 5062c473729SZiyang Xuan int q_id = 0; 5072c473729SZiyang Xuan 5082c473729SZiyang Xuan nic_dev = HINIC_ETH_DEV_TO_PRIVATE_NIC_DEV(dev); 5092c473729SZiyang Xuan 5102c473729SZiyang Xuan for (q_id = 0; q_id < nic_dev->num_rq; q_id++) { 5112c473729SZiyang Xuan rxq = dev->data->rx_queues[q_id]; 5122c473729SZiyang Xuan 5132c473729SZiyang Xuan rxq->wq->cons_idx = 0; 5142c473729SZiyang Xuan rxq->wq->prod_idx = 0; 5152c473729SZiyang Xuan rxq->wq->delta = rxq->q_depth; 5162c473729SZiyang Xuan rxq->wq->mask = rxq->q_depth - 1; 5172c473729SZiyang Xuan 5182c473729SZiyang Xuan /* alloc mbuf to rq */ 5192c473729SZiyang Xuan hinic_rx_alloc_pkts(rxq); 5202c473729SZiyang Xuan } 5212c473729SZiyang Xuan } 5222c473729SZiyang Xuan 5232c473729SZiyang Xuan /** 5242c473729SZiyang Xuan * DPDK callback to configure the transmit queue. 5252c473729SZiyang Xuan * 5262c473729SZiyang Xuan * @param dev 5272c473729SZiyang Xuan * Pointer to Ethernet device structure. 5282c473729SZiyang Xuan * @param queue_idx 5292c473729SZiyang Xuan * Transmit queue index. 5302c473729SZiyang Xuan * @param nb_desc 5312c473729SZiyang Xuan * Number of descriptors for transmit queue. 5322c473729SZiyang Xuan * @param socket_id 5332c473729SZiyang Xuan * NUMA socket on which memory must be allocated. 5342c473729SZiyang Xuan * @param tx_conf 5352c473729SZiyang Xuan * Tx queue configuration parameters. 5362c473729SZiyang Xuan * 5372c473729SZiyang Xuan * @return 5382c473729SZiyang Xuan * 0 on success, negative error value otherwise. 5392c473729SZiyang Xuan */ 5402c473729SZiyang Xuan static int hinic_tx_queue_setup(struct rte_eth_dev *dev, uint16_t queue_idx, 5412c473729SZiyang Xuan uint16_t nb_desc, unsigned int socket_id, 5422c473729SZiyang Xuan __rte_unused const struct rte_eth_txconf *tx_conf) 5432c473729SZiyang Xuan { 5442c473729SZiyang Xuan int rc; 5452c473729SZiyang Xuan struct hinic_nic_dev *nic_dev; 5462c473729SZiyang Xuan struct hinic_hwdev *hwdev; 5472c473729SZiyang Xuan struct hinic_txq *txq; 5482c473729SZiyang Xuan u16 sq_depth, tx_free_thresh; 5492c473729SZiyang Xuan 5502c473729SZiyang Xuan nic_dev = HINIC_ETH_DEV_TO_PRIVATE_NIC_DEV(dev); 5512c473729SZiyang Xuan hwdev = nic_dev->hwdev; 5522c473729SZiyang Xuan 5532c473729SZiyang Xuan /* queue depth must be power of 2, otherwise will be aligned up */ 5542c473729SZiyang Xuan sq_depth = (nb_desc & (nb_desc - 1)) ? 5552c473729SZiyang Xuan ((u16)(1U << (ilog2(nb_desc) + 1))) : nb_desc; 5562c473729SZiyang Xuan 5572c473729SZiyang Xuan /* 5582c473729SZiyang Xuan * Validate number of transmit descriptors. 5592c473729SZiyang Xuan * It must not exceed hardware maximum and minimum. 5602c473729SZiyang Xuan */ 5612c473729SZiyang Xuan if (sq_depth > HINIC_MAX_QUEUE_DEPTH || 5622c473729SZiyang Xuan sq_depth < HINIC_MIN_QUEUE_DEPTH) { 5632c473729SZiyang Xuan PMD_DRV_LOG(ERR, "TX queue depth is out of range from %d to %d, (nb_desc=%d, q_depth=%d, port=%d queue=%d)", 5642c473729SZiyang Xuan HINIC_MIN_QUEUE_DEPTH, HINIC_MAX_QUEUE_DEPTH, 5652c473729SZiyang Xuan (int)nb_desc, (int)sq_depth, 5662c473729SZiyang Xuan (int)dev->data->port_id, (int)queue_idx); 5672c473729SZiyang Xuan return -EINVAL; 5682c473729SZiyang Xuan } 5692c473729SZiyang Xuan 5702c473729SZiyang Xuan /* 5712c473729SZiyang Xuan * The TX descriptor ring will be cleaned after txq->tx_free_thresh 5722c473729SZiyang Xuan * descriptors are used or if the number of descriptors required 5732c473729SZiyang Xuan * to transmit a packet is greater than the number of free TX 5742c473729SZiyang Xuan * descriptors. 5752c473729SZiyang Xuan * The following constraints must be satisfied: 5762c473729SZiyang Xuan * tx_free_thresh must be greater than 0. 5772c473729SZiyang Xuan * tx_free_thresh must be less than the size of the ring minus 1. 5782c473729SZiyang Xuan * When set to zero use default values. 5792c473729SZiyang Xuan */ 5802c473729SZiyang Xuan tx_free_thresh = (u16)((tx_conf->tx_free_thresh) ? 5812c473729SZiyang Xuan tx_conf->tx_free_thresh : HINIC_DEFAULT_TX_FREE_THRESH); 5822c473729SZiyang Xuan if (tx_free_thresh >= (sq_depth - 1)) { 5832c473729SZiyang Xuan PMD_DRV_LOG(ERR, "tx_free_thresh must be less than the number of TX descriptors minus 1. (tx_free_thresh=%u port=%d queue=%d)", 5842c473729SZiyang Xuan (unsigned int)tx_free_thresh, (int)dev->data->port_id, 5852c473729SZiyang Xuan (int)queue_idx); 5862c473729SZiyang Xuan return -EINVAL; 5872c473729SZiyang Xuan } 5882c473729SZiyang Xuan 5892c473729SZiyang Xuan txq = rte_zmalloc_socket("hinic_tx_queue", sizeof(struct hinic_txq), 5902c473729SZiyang Xuan RTE_CACHE_LINE_SIZE, socket_id); 5912c473729SZiyang Xuan if (!txq) { 5922c473729SZiyang Xuan PMD_DRV_LOG(ERR, "Allocate txq[%d] failed, dev_name: %s", 5932c473729SZiyang Xuan queue_idx, dev->data->name); 5942c473729SZiyang Xuan return -ENOMEM; 5952c473729SZiyang Xuan } 5962c473729SZiyang Xuan nic_dev->txqs[queue_idx] = txq; 5972c473729SZiyang Xuan 5982c473729SZiyang Xuan /* alloc tx sq hw wqepage */ 5991b7b9f17SXiaoyun Wang rc = hinic_create_sq(hwdev, queue_idx, sq_depth, socket_id); 6002c473729SZiyang Xuan if (rc) { 6012c473729SZiyang Xuan PMD_DRV_LOG(ERR, "Create txq[%d] failed, dev_name: %s, sq_depth: %d", 6022c473729SZiyang Xuan queue_idx, dev->data->name, sq_depth); 6032c473729SZiyang Xuan goto create_sq_fail; 6042c473729SZiyang Xuan } 6052c473729SZiyang Xuan 6062c473729SZiyang Xuan txq->q_id = queue_idx; 6072c473729SZiyang Xuan txq->q_depth = sq_depth; 6082c473729SZiyang Xuan txq->port_id = dev->data->port_id; 6092c473729SZiyang Xuan txq->tx_free_thresh = tx_free_thresh; 6102c473729SZiyang Xuan txq->nic_dev = nic_dev; 6112c473729SZiyang Xuan txq->wq = &hwdev->nic_io->sq_wq[queue_idx]; 6122c473729SZiyang Xuan txq->sq = &hwdev->nic_io->qps[queue_idx].sq; 6132c473729SZiyang Xuan txq->cons_idx_addr = hwdev->nic_io->qps[queue_idx].sq.cons_idx_addr; 6142c473729SZiyang Xuan txq->sq_head_addr = HINIC_GET_WQ_HEAD(txq); 6152c473729SZiyang Xuan txq->sq_bot_sge_addr = HINIC_GET_WQ_TAIL(txq) - 6162c473729SZiyang Xuan sizeof(struct hinic_sq_bufdesc); 6172c473729SZiyang Xuan txq->cos = nic_dev->default_cos; 6181b7b9f17SXiaoyun Wang txq->socket_id = socket_id; 6192c473729SZiyang Xuan 6202c473729SZiyang Xuan /* alloc software txinfo */ 6212c473729SZiyang Xuan rc = hinic_setup_tx_resources(txq); 6222c473729SZiyang Xuan if (rc) { 6232c473729SZiyang Xuan PMD_DRV_LOG(ERR, "Setup txq[%d] tx_resources failed, dev_name: %s", 6242c473729SZiyang Xuan queue_idx, dev->data->name); 6252c473729SZiyang Xuan goto setup_tx_res_fail; 6262c473729SZiyang Xuan } 6272c473729SZiyang Xuan 6282c473729SZiyang Xuan /* record nic_dev txq in rte_eth tx_queues */ 6292c473729SZiyang Xuan dev->data->tx_queues[queue_idx] = txq; 6302c473729SZiyang Xuan 6312c473729SZiyang Xuan return HINIC_OK; 6322c473729SZiyang Xuan 6332c473729SZiyang Xuan setup_tx_res_fail: 6342c473729SZiyang Xuan hinic_destroy_sq(hwdev, queue_idx); 6352c473729SZiyang Xuan 6362c473729SZiyang Xuan create_sq_fail: 6372c473729SZiyang Xuan rte_free(txq); 6382c473729SZiyang Xuan 6392c473729SZiyang Xuan return rc; 6402c473729SZiyang Xuan } 6412c473729SZiyang Xuan 6422c473729SZiyang Xuan static void hinic_reset_tx_queue(struct rte_eth_dev *dev) 6432c473729SZiyang Xuan { 6442c473729SZiyang Xuan struct hinic_nic_dev *nic_dev; 6452c473729SZiyang Xuan struct hinic_txq *txq; 6462c473729SZiyang Xuan struct hinic_nic_io *nic_io; 6472c473729SZiyang Xuan struct hinic_hwdev *hwdev; 6482c473729SZiyang Xuan volatile u32 *ci_addr; 6492c473729SZiyang Xuan int q_id = 0; 6502c473729SZiyang Xuan 6512c473729SZiyang Xuan nic_dev = HINIC_ETH_DEV_TO_PRIVATE_NIC_DEV(dev); 6522c473729SZiyang Xuan hwdev = nic_dev->hwdev; 6532c473729SZiyang Xuan nic_io = hwdev->nic_io; 6542c473729SZiyang Xuan 6552c473729SZiyang Xuan for (q_id = 0; q_id < nic_dev->num_sq; q_id++) { 6562c473729SZiyang Xuan txq = dev->data->tx_queues[q_id]; 6572c473729SZiyang Xuan 6582c473729SZiyang Xuan txq->wq->cons_idx = 0; 6592c473729SZiyang Xuan txq->wq->prod_idx = 0; 6602c473729SZiyang Xuan txq->wq->delta = txq->q_depth; 6612c473729SZiyang Xuan txq->wq->mask = txq->q_depth - 1; 6622c473729SZiyang Xuan 6632c473729SZiyang Xuan /* clear hardware ci */ 6642c473729SZiyang Xuan ci_addr = (volatile u32 *)HINIC_CI_VADDR(nic_io->ci_vaddr_base, 6652c473729SZiyang Xuan q_id); 6662c473729SZiyang Xuan *ci_addr = 0; 6672c473729SZiyang Xuan } 6682c473729SZiyang Xuan } 6692c473729SZiyang Xuan 6702c473729SZiyang Xuan /** 6711d09792aSZiyang Xuan * Get link speed from NIC. 6721d09792aSZiyang Xuan * 6731d09792aSZiyang Xuan * @param dev 6741d09792aSZiyang Xuan * Pointer to Ethernet device structure. 6751d09792aSZiyang Xuan * @param speed_capa 6761d09792aSZiyang Xuan * Pointer to link speed structure. 6771d09792aSZiyang Xuan */ 6781d09792aSZiyang Xuan static void hinic_get_speed_capa(struct rte_eth_dev *dev, uint32_t *speed_capa) 6791d09792aSZiyang Xuan { 6801d09792aSZiyang Xuan struct hinic_nic_dev *nic_dev = HINIC_ETH_DEV_TO_PRIVATE_NIC_DEV(dev); 6811d09792aSZiyang Xuan u32 supported_link, advertised_link; 6821d09792aSZiyang Xuan int err; 6831d09792aSZiyang Xuan 6841d09792aSZiyang Xuan #define HINIC_LINK_MODE_SUPPORT_1G (1U << HINIC_GE_BASE_KX) 6851d09792aSZiyang Xuan 6861d09792aSZiyang Xuan #define HINIC_LINK_MODE_SUPPORT_10G (1U << HINIC_10GE_BASE_KR) 6871d09792aSZiyang Xuan 6881d09792aSZiyang Xuan #define HINIC_LINK_MODE_SUPPORT_25G ((1U << HINIC_25GE_BASE_KR_S) | \ 6891d09792aSZiyang Xuan (1U << HINIC_25GE_BASE_CR_S) | \ 6901d09792aSZiyang Xuan (1U << HINIC_25GE_BASE_KR) | \ 6911d09792aSZiyang Xuan (1U << HINIC_25GE_BASE_CR)) 6921d09792aSZiyang Xuan 6931d09792aSZiyang Xuan #define HINIC_LINK_MODE_SUPPORT_40G ((1U << HINIC_40GE_BASE_KR4) | \ 6941d09792aSZiyang Xuan (1U << HINIC_40GE_BASE_CR4)) 6951d09792aSZiyang Xuan 6961d09792aSZiyang Xuan #define HINIC_LINK_MODE_SUPPORT_100G ((1U << HINIC_100GE_BASE_KR4) | \ 6971d09792aSZiyang Xuan (1U << HINIC_100GE_BASE_CR4)) 6981d09792aSZiyang Xuan 6991d09792aSZiyang Xuan err = hinic_get_link_mode(nic_dev->hwdev, 7001d09792aSZiyang Xuan &supported_link, &advertised_link); 7011d09792aSZiyang Xuan if (err || supported_link == HINIC_SUPPORTED_UNKNOWN || 7021d09792aSZiyang Xuan advertised_link == HINIC_SUPPORTED_UNKNOWN) { 7031d09792aSZiyang Xuan PMD_DRV_LOG(WARNING, "Get speed capability info failed, device: %s, port_id: %u", 7041d09792aSZiyang Xuan nic_dev->proc_dev_name, dev->data->port_id); 7051d09792aSZiyang Xuan } else { 7061d09792aSZiyang Xuan *speed_capa = 0; 7071d09792aSZiyang Xuan if (!!(supported_link & HINIC_LINK_MODE_SUPPORT_1G)) 7081d09792aSZiyang Xuan *speed_capa |= ETH_LINK_SPEED_1G; 7091d09792aSZiyang Xuan if (!!(supported_link & HINIC_LINK_MODE_SUPPORT_10G)) 7101d09792aSZiyang Xuan *speed_capa |= ETH_LINK_SPEED_10G; 7111d09792aSZiyang Xuan if (!!(supported_link & HINIC_LINK_MODE_SUPPORT_25G)) 7121d09792aSZiyang Xuan *speed_capa |= ETH_LINK_SPEED_25G; 7131d09792aSZiyang Xuan if (!!(supported_link & HINIC_LINK_MODE_SUPPORT_40G)) 7141d09792aSZiyang Xuan *speed_capa |= ETH_LINK_SPEED_40G; 7151d09792aSZiyang Xuan if (!!(supported_link & HINIC_LINK_MODE_SUPPORT_100G)) 7161d09792aSZiyang Xuan *speed_capa |= ETH_LINK_SPEED_100G; 7171d09792aSZiyang Xuan } 7181d09792aSZiyang Xuan } 7191d09792aSZiyang Xuan 7201d09792aSZiyang Xuan /** 7211d09792aSZiyang Xuan * DPDK callback to get information about the device. 7221d09792aSZiyang Xuan * 7231d09792aSZiyang Xuan * @param dev 7241d09792aSZiyang Xuan * Pointer to Ethernet device structure. 7251d09792aSZiyang Xuan * @param info 7261d09792aSZiyang Xuan * Pointer to Info structure output buffer. 7271d09792aSZiyang Xuan */ 728bdad90d1SIvan Ilchenko static int 7291d09792aSZiyang Xuan hinic_dev_infos_get(struct rte_eth_dev *dev, struct rte_eth_dev_info *info) 7301d09792aSZiyang Xuan { 7311d09792aSZiyang Xuan struct hinic_nic_dev *nic_dev = HINIC_ETH_DEV_TO_PRIVATE_NIC_DEV(dev); 7321d09792aSZiyang Xuan 7331d09792aSZiyang Xuan info->max_rx_queues = nic_dev->nic_cap.max_rqs; 7341d09792aSZiyang Xuan info->max_tx_queues = nic_dev->nic_cap.max_sqs; 7351d09792aSZiyang Xuan info->min_rx_bufsize = HINIC_MIN_RX_BUF_SIZE; 7361d09792aSZiyang Xuan info->max_rx_pktlen = HINIC_MAX_JUMBO_FRAME_SIZE; 73700499a22SXiaoyun Wang info->max_mac_addrs = HINIC_MAX_UC_MAC_ADDRS; 7388260eba6SXiaoyun Wang info->min_mtu = HINIC_MIN_MTU_SIZE; 7398260eba6SXiaoyun Wang info->max_mtu = HINIC_MAX_MTU_SIZE; 7409d02f40dSXiaoyun Wang info->max_lro_pkt_size = HINIC_MAX_LRO_SIZE; 7411d09792aSZiyang Xuan 7421d09792aSZiyang Xuan hinic_get_speed_capa(dev, &info->speed_capa); 7431d09792aSZiyang Xuan info->rx_queue_offload_capa = 0; 7441d09792aSZiyang Xuan info->rx_offload_capa = DEV_RX_OFFLOAD_VLAN_STRIP | 7451d09792aSZiyang Xuan DEV_RX_OFFLOAD_IPV4_CKSUM | 7461d09792aSZiyang Xuan DEV_RX_OFFLOAD_UDP_CKSUM | 747fdba3bf1SXiaoyun Wang DEV_RX_OFFLOAD_TCP_CKSUM | 7488260eba6SXiaoyun Wang DEV_RX_OFFLOAD_VLAN_FILTER | 7498260eba6SXiaoyun Wang DEV_RX_OFFLOAD_SCATTER | 7509d4878efSXiaoyun Wang DEV_RX_OFFLOAD_JUMBO_FRAME | 7518b945a7fSPavan Nikhilesh DEV_RX_OFFLOAD_TCP_LRO | 7528b945a7fSPavan Nikhilesh DEV_RX_OFFLOAD_RSS_HASH; 7531d09792aSZiyang Xuan 7541d09792aSZiyang Xuan info->tx_queue_offload_capa = 0; 7551d09792aSZiyang Xuan info->tx_offload_capa = DEV_TX_OFFLOAD_VLAN_INSERT | 7561d09792aSZiyang Xuan DEV_TX_OFFLOAD_IPV4_CKSUM | 7571d09792aSZiyang Xuan DEV_TX_OFFLOAD_UDP_CKSUM | 7581d09792aSZiyang Xuan DEV_TX_OFFLOAD_TCP_CKSUM | 7591d09792aSZiyang Xuan DEV_TX_OFFLOAD_SCTP_CKSUM | 7601d09792aSZiyang Xuan DEV_TX_OFFLOAD_OUTER_IPV4_CKSUM | 7611d09792aSZiyang Xuan DEV_TX_OFFLOAD_TCP_TSO | 7621d09792aSZiyang Xuan DEV_TX_OFFLOAD_MULTI_SEGS; 7631d09792aSZiyang Xuan 7641d09792aSZiyang Xuan info->hash_key_size = HINIC_RSS_KEY_SIZE; 7651d09792aSZiyang Xuan info->reta_size = HINIC_RSS_INDIR_SIZE; 76664727024SZiyang Xuan info->flow_type_rss_offloads = HINIC_RSS_OFFLOAD_ALL; 7671d09792aSZiyang Xuan info->rx_desc_lim = hinic_rx_desc_lim; 7681d09792aSZiyang Xuan info->tx_desc_lim = hinic_tx_desc_lim; 769bdad90d1SIvan Ilchenko 770483b4817SXiaoyun Wang /* Driver-preferred Rx/Tx parameters */ 771483b4817SXiaoyun Wang info->default_rxportconf.burst_size = HINIC_DEFAULT_BURST_SIZE; 772483b4817SXiaoyun Wang info->default_txportconf.burst_size = HINIC_DEFAULT_BURST_SIZE; 773483b4817SXiaoyun Wang info->default_rxportconf.nb_queues = HINIC_DEFAULT_NB_QUEUES; 774483b4817SXiaoyun Wang info->default_txportconf.nb_queues = HINIC_DEFAULT_NB_QUEUES; 775483b4817SXiaoyun Wang info->default_rxportconf.ring_size = HINIC_DEFAULT_RING_SIZE; 776483b4817SXiaoyun Wang info->default_txportconf.ring_size = HINIC_DEFAULT_RING_SIZE; 777483b4817SXiaoyun Wang 778bdad90d1SIvan Ilchenko return 0; 7791d09792aSZiyang Xuan } 7801d09792aSZiyang Xuan 781dbf524abSXiaoyun Wang static int hinic_fw_version_get(struct rte_eth_dev *dev, char *fw_version, 782dbf524abSXiaoyun Wang size_t fw_size) 783dbf524abSXiaoyun Wang { 784dbf524abSXiaoyun Wang struct hinic_nic_dev *nic_dev = HINIC_ETH_DEV_TO_PRIVATE_NIC_DEV(dev); 785dbf524abSXiaoyun Wang char fw_ver[HINIC_MGMT_VERSION_MAX_LEN] = {0}; 786dbf524abSXiaoyun Wang int err; 787dbf524abSXiaoyun Wang 788dbf524abSXiaoyun Wang err = hinic_get_mgmt_version(nic_dev->hwdev, fw_ver); 789dbf524abSXiaoyun Wang if (err) { 7904f1af3cbSXiaoyun Wang PMD_DRV_LOG(ERR, "Failed to get fw version"); 791dbf524abSXiaoyun Wang return -EINVAL; 792dbf524abSXiaoyun Wang } 793dbf524abSXiaoyun Wang 794dbf524abSXiaoyun Wang if (fw_size < strlen(fw_ver) + 1) 795dbf524abSXiaoyun Wang return (strlen(fw_ver) + 1); 796dbf524abSXiaoyun Wang 797dbf524abSXiaoyun Wang snprintf(fw_version, fw_size, "%s", fw_ver); 798dbf524abSXiaoyun Wang 799dbf524abSXiaoyun Wang return 0; 800dbf524abSXiaoyun Wang } 801dbf524abSXiaoyun Wang 8022c473729SZiyang Xuan static int hinic_config_rx_mode(struct hinic_nic_dev *nic_dev, u32 rx_mode_ctrl) 8032c473729SZiyang Xuan { 8042c473729SZiyang Xuan int err; 8052c473729SZiyang Xuan 8062c473729SZiyang Xuan err = hinic_set_rx_mode(nic_dev->hwdev, rx_mode_ctrl); 8072c473729SZiyang Xuan if (err) { 8082c473729SZiyang Xuan PMD_DRV_LOG(ERR, "Failed to set rx mode"); 8092c473729SZiyang Xuan return -EINVAL; 8102c473729SZiyang Xuan } 8112c473729SZiyang Xuan nic_dev->rx_mode_status = rx_mode_ctrl; 8122c473729SZiyang Xuan 8132c473729SZiyang Xuan return 0; 8142c473729SZiyang Xuan } 8152c473729SZiyang Xuan 8162c473729SZiyang Xuan static int hinic_rxtx_configure(struct rte_eth_dev *dev) 8172c473729SZiyang Xuan { 8182c473729SZiyang Xuan struct hinic_nic_dev *nic_dev = HINIC_ETH_DEV_TO_PRIVATE_NIC_DEV(dev); 8199d02f40dSXiaoyun Wang int err; 8202c473729SZiyang Xuan 8212c473729SZiyang Xuan /* rx configure, if rss enable, need to init default configuration */ 8222c473729SZiyang Xuan err = hinic_rx_configure(dev); 8232c473729SZiyang Xuan if (err) { 8242c473729SZiyang Xuan PMD_DRV_LOG(ERR, "Configure rss failed"); 8252c473729SZiyang Xuan return err; 8262c473729SZiyang Xuan } 8272c473729SZiyang Xuan 8282c473729SZiyang Xuan /* rx mode init */ 8292c473729SZiyang Xuan err = hinic_config_rx_mode(nic_dev, HINIC_DEFAULT_RX_MODE); 8302c473729SZiyang Xuan if (err) { 8312c473729SZiyang Xuan PMD_DRV_LOG(ERR, "Configure rx_mode:0x%x failed", 8322c473729SZiyang Xuan HINIC_DEFAULT_RX_MODE); 8332c473729SZiyang Xuan goto set_rx_mode_fail; 8342c473729SZiyang Xuan } 8352c473729SZiyang Xuan 8362c473729SZiyang Xuan return HINIC_OK; 8372c473729SZiyang Xuan 8382c473729SZiyang Xuan set_rx_mode_fail: 8392c473729SZiyang Xuan hinic_rx_remove_configure(dev); 8402c473729SZiyang Xuan 8412c473729SZiyang Xuan return err; 8422c473729SZiyang Xuan } 8432c473729SZiyang Xuan 8442c473729SZiyang Xuan static void hinic_remove_rxtx_configure(struct rte_eth_dev *dev) 8452c473729SZiyang Xuan { 8462c473729SZiyang Xuan struct hinic_nic_dev *nic_dev = HINIC_ETH_DEV_TO_PRIVATE_NIC_DEV(dev); 8472c473729SZiyang Xuan 8482c473729SZiyang Xuan (void)hinic_config_rx_mode(nic_dev, 0); 8492c473729SZiyang Xuan hinic_rx_remove_configure(dev); 8502c473729SZiyang Xuan } 8512c473729SZiyang Xuan 8522c473729SZiyang Xuan static int hinic_priv_get_dev_link_status(struct hinic_nic_dev *nic_dev, 8532c473729SZiyang Xuan struct rte_eth_link *link) 8542c473729SZiyang Xuan { 8552c473729SZiyang Xuan int rc; 8562c473729SZiyang Xuan u8 port_link_status = 0; 8572c473729SZiyang Xuan struct nic_port_info port_link_info; 8582c473729SZiyang Xuan struct hinic_hwdev *nic_hwdev = nic_dev->hwdev; 8592c473729SZiyang Xuan uint32_t port_speed[LINK_SPEED_MAX] = {ETH_SPEED_NUM_10M, 8602c473729SZiyang Xuan ETH_SPEED_NUM_100M, ETH_SPEED_NUM_1G, 8612c473729SZiyang Xuan ETH_SPEED_NUM_10G, ETH_SPEED_NUM_25G, 8622c473729SZiyang Xuan ETH_SPEED_NUM_40G, ETH_SPEED_NUM_100G}; 8632c473729SZiyang Xuan 8642c473729SZiyang Xuan rc = hinic_get_link_status(nic_hwdev, &port_link_status); 8652c473729SZiyang Xuan if (rc) 8662c473729SZiyang Xuan return rc; 8672c473729SZiyang Xuan 8682c473729SZiyang Xuan if (!port_link_status) { 8692c473729SZiyang Xuan link->link_status = ETH_LINK_DOWN; 8702c473729SZiyang Xuan link->link_speed = 0; 8712c473729SZiyang Xuan link->link_duplex = ETH_LINK_HALF_DUPLEX; 8722c473729SZiyang Xuan link->link_autoneg = ETH_LINK_FIXED; 8732c473729SZiyang Xuan return HINIC_OK; 8742c473729SZiyang Xuan } 8752c473729SZiyang Xuan 8762c473729SZiyang Xuan memset(&port_link_info, 0, sizeof(port_link_info)); 8772c473729SZiyang Xuan rc = hinic_get_port_info(nic_hwdev, &port_link_info); 8782c473729SZiyang Xuan if (rc) 8792c473729SZiyang Xuan return rc; 8802c473729SZiyang Xuan 8812c473729SZiyang Xuan link->link_speed = port_speed[port_link_info.speed % LINK_SPEED_MAX]; 8822c473729SZiyang Xuan link->link_duplex = port_link_info.duplex; 8832c473729SZiyang Xuan link->link_autoneg = port_link_info.autoneg_state; 8842c473729SZiyang Xuan link->link_status = port_link_status; 8852c473729SZiyang Xuan 8862c473729SZiyang Xuan return HINIC_OK; 8872c473729SZiyang Xuan } 8882c473729SZiyang Xuan 8892c473729SZiyang Xuan /** 8902c473729SZiyang Xuan * DPDK callback to retrieve physical link information. 8912c473729SZiyang Xuan * 8922c473729SZiyang Xuan * @param dev 8932c473729SZiyang Xuan * Pointer to Ethernet device structure. 8942c473729SZiyang Xuan * @param wait_to_complete 8952c473729SZiyang Xuan * Wait for request completion. 8962c473729SZiyang Xuan * 8972c473729SZiyang Xuan * @return 8982c473729SZiyang Xuan * 0 link status changed, -1 link status not changed 8992c473729SZiyang Xuan */ 9002c473729SZiyang Xuan static int hinic_link_update(struct rte_eth_dev *dev, int wait_to_complete) 9012c473729SZiyang Xuan { 9022c473729SZiyang Xuan #define CHECK_INTERVAL 10 /* 10ms */ 9032c473729SZiyang Xuan #define MAX_REPEAT_TIME 100 /* 1s (100 * 10ms) in total */ 9042c473729SZiyang Xuan int rc = HINIC_OK; 9052c473729SZiyang Xuan struct rte_eth_link link; 9062c473729SZiyang Xuan struct hinic_nic_dev *nic_dev = HINIC_ETH_DEV_TO_PRIVATE_NIC_DEV(dev); 9072c473729SZiyang Xuan unsigned int rep_cnt = MAX_REPEAT_TIME; 9082c473729SZiyang Xuan 9092c473729SZiyang Xuan memset(&link, 0, sizeof(link)); 9102c473729SZiyang Xuan do { 9112c473729SZiyang Xuan /* Get link status information from hardware */ 9122c473729SZiyang Xuan rc = hinic_priv_get_dev_link_status(nic_dev, &link); 9132c473729SZiyang Xuan if (rc != HINIC_OK) { 9142c473729SZiyang Xuan link.link_speed = ETH_SPEED_NUM_NONE; 9152c473729SZiyang Xuan link.link_duplex = ETH_LINK_FULL_DUPLEX; 9162c473729SZiyang Xuan PMD_DRV_LOG(ERR, "Get link status failed"); 9172c473729SZiyang Xuan goto out; 9182c473729SZiyang Xuan } 9192c473729SZiyang Xuan 9202c473729SZiyang Xuan if (!wait_to_complete || link.link_status) 9212c473729SZiyang Xuan break; 9222c473729SZiyang Xuan 9232c473729SZiyang Xuan rte_delay_ms(CHECK_INTERVAL); 9242c473729SZiyang Xuan } while (rep_cnt--); 9252c473729SZiyang Xuan 9262c473729SZiyang Xuan out: 9272c473729SZiyang Xuan rc = rte_eth_linkstatus_set(dev, &link); 9282c473729SZiyang Xuan return rc; 9292c473729SZiyang Xuan } 9302c473729SZiyang Xuan 9312c473729SZiyang Xuan /** 93254ac3386SXiaoyun Wang * DPDK callback to bring the link UP. 93354ac3386SXiaoyun Wang * 93454ac3386SXiaoyun Wang * @param dev 93554ac3386SXiaoyun Wang * Pointer to Ethernet device structure. 93654ac3386SXiaoyun Wang * 93754ac3386SXiaoyun Wang * @return 93854ac3386SXiaoyun Wang * 0 on success, negative errno value on failure. 93954ac3386SXiaoyun Wang */ 94054ac3386SXiaoyun Wang static int hinic_dev_set_link_up(struct rte_eth_dev *dev) 94154ac3386SXiaoyun Wang { 94254ac3386SXiaoyun Wang struct hinic_nic_dev *nic_dev = HINIC_ETH_DEV_TO_PRIVATE_NIC_DEV(dev); 94354ac3386SXiaoyun Wang int ret; 94454ac3386SXiaoyun Wang 94554ac3386SXiaoyun Wang /* link status follow phy port status, up will open pma */ 94654ac3386SXiaoyun Wang ret = hinic_set_port_enable(nic_dev->hwdev, true); 94754ac3386SXiaoyun Wang if (ret) 94854ac3386SXiaoyun Wang PMD_DRV_LOG(ERR, "Set mac link up failed, dev_name: %s, port_id: %d", 94954ac3386SXiaoyun Wang nic_dev->proc_dev_name, dev->data->port_id); 95054ac3386SXiaoyun Wang 95154ac3386SXiaoyun Wang return ret; 95254ac3386SXiaoyun Wang } 95354ac3386SXiaoyun Wang 95454ac3386SXiaoyun Wang /** 95554ac3386SXiaoyun Wang * DPDK callback to bring the link DOWN. 95654ac3386SXiaoyun Wang * 95754ac3386SXiaoyun Wang * @param dev 95854ac3386SXiaoyun Wang * Pointer to Ethernet device structure. 95954ac3386SXiaoyun Wang * 96054ac3386SXiaoyun Wang * @return 96154ac3386SXiaoyun Wang * 0 on success, negative errno value on failure. 96254ac3386SXiaoyun Wang */ 96354ac3386SXiaoyun Wang static int hinic_dev_set_link_down(struct rte_eth_dev *dev) 96454ac3386SXiaoyun Wang { 96554ac3386SXiaoyun Wang struct hinic_nic_dev *nic_dev = HINIC_ETH_DEV_TO_PRIVATE_NIC_DEV(dev); 96654ac3386SXiaoyun Wang int ret; 96754ac3386SXiaoyun Wang 96854ac3386SXiaoyun Wang /* link status follow phy port status, up will close pma */ 96954ac3386SXiaoyun Wang ret = hinic_set_port_enable(nic_dev->hwdev, false); 97054ac3386SXiaoyun Wang if (ret) 97154ac3386SXiaoyun Wang PMD_DRV_LOG(ERR, "Set mac link down failed, dev_name: %s, port_id: %d", 97254ac3386SXiaoyun Wang nic_dev->proc_dev_name, dev->data->port_id); 97354ac3386SXiaoyun Wang 97454ac3386SXiaoyun Wang return ret; 97554ac3386SXiaoyun Wang } 97654ac3386SXiaoyun Wang 97754ac3386SXiaoyun Wang /** 9782c473729SZiyang Xuan * DPDK callback to start the device. 9792c473729SZiyang Xuan * 9802c473729SZiyang Xuan * @param dev 9812c473729SZiyang Xuan * Pointer to Ethernet device structure. 9822c473729SZiyang Xuan * 9832c473729SZiyang Xuan * @return 9842c473729SZiyang Xuan * 0 on success, negative errno value on failure. 9852c473729SZiyang Xuan */ 9862c473729SZiyang Xuan static int hinic_dev_start(struct rte_eth_dev *dev) 9872c473729SZiyang Xuan { 9882c473729SZiyang Xuan int rc; 9892c473729SZiyang Xuan char *name; 9902c473729SZiyang Xuan struct hinic_nic_dev *nic_dev; 9912c473729SZiyang Xuan 9922c473729SZiyang Xuan nic_dev = HINIC_ETH_DEV_TO_PRIVATE_NIC_DEV(dev); 9932c473729SZiyang Xuan name = dev->data->name; 9942c473729SZiyang Xuan 9952c473729SZiyang Xuan /* reset rx and tx queue */ 9962c473729SZiyang Xuan hinic_reset_rx_queue(dev); 9972c473729SZiyang Xuan hinic_reset_tx_queue(dev); 9982c473729SZiyang Xuan 9992c473729SZiyang Xuan /* get func rx buf size */ 10002c473729SZiyang Xuan hinic_get_func_rx_buf_size(nic_dev); 10012c473729SZiyang Xuan 10022c473729SZiyang Xuan /* init txq and rxq context */ 10032c473729SZiyang Xuan rc = hinic_init_qp_ctxts(nic_dev->hwdev); 10042c473729SZiyang Xuan if (rc) { 10052c473729SZiyang Xuan PMD_DRV_LOG(ERR, "Initialize qp context failed, dev_name: %s", 10062c473729SZiyang Xuan name); 10072c473729SZiyang Xuan goto init_qp_fail; 10082c473729SZiyang Xuan } 10092c473729SZiyang Xuan 10102c473729SZiyang Xuan /* rss template */ 10112c473729SZiyang Xuan rc = hinic_config_mq_mode(dev, TRUE); 10122c473729SZiyang Xuan if (rc) { 10132c473729SZiyang Xuan PMD_DRV_LOG(ERR, "Configure mq mode failed, dev_name: %s", 10142c473729SZiyang Xuan name); 10152c473729SZiyang Xuan goto cfg_mq_mode_fail; 10162c473729SZiyang Xuan } 10172c473729SZiyang Xuan 10182c473729SZiyang Xuan /* set default mtu */ 10192c473729SZiyang Xuan rc = hinic_set_port_mtu(nic_dev->hwdev, nic_dev->mtu_size); 10202c473729SZiyang Xuan if (rc) { 10212c473729SZiyang Xuan PMD_DRV_LOG(ERR, "Set mtu_size[%d] failed, dev_name: %s", 10222c473729SZiyang Xuan nic_dev->mtu_size, name); 10232c473729SZiyang Xuan goto set_mtu_fail; 10242c473729SZiyang Xuan } 10252c473729SZiyang Xuan 10262c473729SZiyang Xuan /* configure rss rx_mode and other rx or tx default feature */ 10272c473729SZiyang Xuan rc = hinic_rxtx_configure(dev); 10282c473729SZiyang Xuan if (rc) { 10292c473729SZiyang Xuan PMD_DRV_LOG(ERR, "Configure tx and rx failed, dev_name: %s", 10302c473729SZiyang Xuan name); 10312c473729SZiyang Xuan goto cfg_rxtx_fail; 10322c473729SZiyang Xuan } 10332c473729SZiyang Xuan 10346691acefSXiaoyun Wang /* reactive pf status, so that uP report asyn event */ 10356691acefSXiaoyun Wang hinic_set_pf_status(nic_dev->hwdev->hwif, HINIC_PF_STATUS_ACTIVE_FLAG); 10366691acefSXiaoyun Wang 10372c473729SZiyang Xuan /* open virtual port and ready to start packet receiving */ 10382c473729SZiyang Xuan rc = hinic_set_vport_enable(nic_dev->hwdev, true); 10392c473729SZiyang Xuan if (rc) { 10402c473729SZiyang Xuan PMD_DRV_LOG(ERR, "Enable vport failed, dev_name:%s", name); 10412c473729SZiyang Xuan goto en_vport_fail; 10422c473729SZiyang Xuan } 10432c473729SZiyang Xuan 10442c473729SZiyang Xuan /* open physical port and start packet receiving */ 10452c473729SZiyang Xuan rc = hinic_set_port_enable(nic_dev->hwdev, true); 10462c473729SZiyang Xuan if (rc) { 10472c473729SZiyang Xuan PMD_DRV_LOG(ERR, "Enable physical port failed, dev_name: %s", 10482c473729SZiyang Xuan name); 10492c473729SZiyang Xuan goto en_port_fail; 10502c473729SZiyang Xuan } 10512c473729SZiyang Xuan 10522c473729SZiyang Xuan /* update eth_dev link status */ 10532c473729SZiyang Xuan if (dev->data->dev_conf.intr_conf.lsc != 0) 10542c473729SZiyang Xuan (void)hinic_link_update(dev, 0); 10552c473729SZiyang Xuan 10560371535dSJoyce Kong rte_bit_relaxed_set32(HINIC_DEV_START, &nic_dev->dev_status); 10572c473729SZiyang Xuan 10582c473729SZiyang Xuan return 0; 10592c473729SZiyang Xuan 10602c473729SZiyang Xuan en_port_fail: 10612c473729SZiyang Xuan (void)hinic_set_vport_enable(nic_dev->hwdev, false); 10622c473729SZiyang Xuan 10632c473729SZiyang Xuan en_vport_fail: 10646691acefSXiaoyun Wang hinic_set_pf_status(nic_dev->hwdev->hwif, HINIC_PF_STATUS_INIT); 10656691acefSXiaoyun Wang 10662c473729SZiyang Xuan /* Flush tx && rx chip resources in case of set vport fake fail */ 10672c473729SZiyang Xuan (void)hinic_flush_qp_res(nic_dev->hwdev); 10682c473729SZiyang Xuan rte_delay_ms(100); 10692c473729SZiyang Xuan 10702c473729SZiyang Xuan hinic_remove_rxtx_configure(dev); 10712c473729SZiyang Xuan 10722c473729SZiyang Xuan cfg_rxtx_fail: 10732c473729SZiyang Xuan set_mtu_fail: 10742c473729SZiyang Xuan cfg_mq_mode_fail: 10752c473729SZiyang Xuan hinic_free_qp_ctxts(nic_dev->hwdev); 10762c473729SZiyang Xuan 10772c473729SZiyang Xuan init_qp_fail: 10782c473729SZiyang Xuan hinic_free_all_rx_mbuf(dev); 10792c473729SZiyang Xuan hinic_free_all_tx_mbuf(dev); 10802c473729SZiyang Xuan 10812c473729SZiyang Xuan return rc; 10822c473729SZiyang Xuan } 10832c473729SZiyang Xuan 10842c473729SZiyang Xuan /** 10852c473729SZiyang Xuan * DPDK callback to release the receive queue. 10862c473729SZiyang Xuan * 10872c473729SZiyang Xuan * @param queue 10882c473729SZiyang Xuan * Generic receive queue pointer. 10892c473729SZiyang Xuan */ 10902c473729SZiyang Xuan static void hinic_rx_queue_release(void *queue) 10912c473729SZiyang Xuan { 10922c473729SZiyang Xuan struct hinic_rxq *rxq = queue; 10932c473729SZiyang Xuan struct hinic_nic_dev *nic_dev; 10942c473729SZiyang Xuan 10952c473729SZiyang Xuan if (!rxq) { 10962c473729SZiyang Xuan PMD_DRV_LOG(WARNING, "Rxq is null when release"); 10972c473729SZiyang Xuan return; 10982c473729SZiyang Xuan } 10992c473729SZiyang Xuan nic_dev = rxq->nic_dev; 11002c473729SZiyang Xuan 11012c473729SZiyang Xuan /* free rxq_pkt mbuf */ 1102c3ba1f0fSXiaoyun Wang hinic_free_all_rx_mbufs(rxq); 11032c473729SZiyang Xuan 11042c473729SZiyang Xuan /* free rxq_cqe, rxq_info */ 11052c473729SZiyang Xuan hinic_free_rx_resources(rxq); 11062c473729SZiyang Xuan 11072c473729SZiyang Xuan /* free root rq wq */ 11082c473729SZiyang Xuan hinic_destroy_rq(nic_dev->hwdev, rxq->q_id); 11092c473729SZiyang Xuan 11102c473729SZiyang Xuan nic_dev->rxqs[rxq->q_id] = NULL; 11112c473729SZiyang Xuan 11122c473729SZiyang Xuan /* free rxq */ 11132c473729SZiyang Xuan rte_free(rxq); 11142c473729SZiyang Xuan } 11152c473729SZiyang Xuan 11162c473729SZiyang Xuan /** 11172c473729SZiyang Xuan * DPDK callback to release the transmit queue. 11182c473729SZiyang Xuan * 11192c473729SZiyang Xuan * @param queue 11202c473729SZiyang Xuan * Generic transmit queue pointer. 11212c473729SZiyang Xuan */ 11222c473729SZiyang Xuan static void hinic_tx_queue_release(void *queue) 11232c473729SZiyang Xuan { 11242c473729SZiyang Xuan struct hinic_txq *txq = queue; 11252c473729SZiyang Xuan struct hinic_nic_dev *nic_dev; 11262c473729SZiyang Xuan 11272c473729SZiyang Xuan if (!txq) { 11282c473729SZiyang Xuan PMD_DRV_LOG(WARNING, "Txq is null when release"); 11292c473729SZiyang Xuan return; 11302c473729SZiyang Xuan } 11312c473729SZiyang Xuan nic_dev = txq->nic_dev; 11322c473729SZiyang Xuan 11332c473729SZiyang Xuan /* free txq_pkt mbuf */ 1134c3ba1f0fSXiaoyun Wang hinic_free_all_tx_mbufs(txq); 11352c473729SZiyang Xuan 11362c473729SZiyang Xuan /* free txq_info */ 11372c473729SZiyang Xuan hinic_free_tx_resources(txq); 11382c473729SZiyang Xuan 11392c473729SZiyang Xuan /* free root sq wq */ 11402c473729SZiyang Xuan hinic_destroy_sq(nic_dev->hwdev, txq->q_id); 11412c473729SZiyang Xuan nic_dev->txqs[txq->q_id] = NULL; 11422c473729SZiyang Xuan 11432c473729SZiyang Xuan /* free txq */ 11442c473729SZiyang Xuan rte_free(txq); 11452c473729SZiyang Xuan } 11462c473729SZiyang Xuan 114764727024SZiyang Xuan static void hinic_free_all_rq(struct hinic_nic_dev *nic_dev) 11481d09792aSZiyang Xuan { 114964727024SZiyang Xuan u16 q_id; 115064727024SZiyang Xuan 115164727024SZiyang Xuan for (q_id = 0; q_id < nic_dev->num_rq; q_id++) 115264727024SZiyang Xuan hinic_destroy_rq(nic_dev->hwdev, q_id); 115364727024SZiyang Xuan } 115464727024SZiyang Xuan 115564727024SZiyang Xuan static void hinic_free_all_sq(struct hinic_nic_dev *nic_dev) 115664727024SZiyang Xuan { 115764727024SZiyang Xuan u16 q_id; 115864727024SZiyang Xuan 115964727024SZiyang Xuan for (q_id = 0; q_id < nic_dev->num_sq; q_id++) 116064727024SZiyang Xuan hinic_destroy_sq(nic_dev->hwdev, q_id); 116164727024SZiyang Xuan } 116264727024SZiyang Xuan 11632c473729SZiyang Xuan /** 11642c473729SZiyang Xuan * DPDK callback to stop the device. 11652c473729SZiyang Xuan * 11662c473729SZiyang Xuan * @param dev 11672c473729SZiyang Xuan * Pointer to Ethernet device structure. 11682c473729SZiyang Xuan */ 116962024eb8SIvan Ilchenko static int hinic_dev_stop(struct rte_eth_dev *dev) 11702c473729SZiyang Xuan { 11712c473729SZiyang Xuan int rc; 11722c473729SZiyang Xuan char *name; 11732c473729SZiyang Xuan uint16_t port_id; 11742c473729SZiyang Xuan struct hinic_nic_dev *nic_dev; 11752c473729SZiyang Xuan struct rte_eth_link link; 11762c473729SZiyang Xuan 11772c473729SZiyang Xuan nic_dev = HINIC_ETH_DEV_TO_PRIVATE_NIC_DEV(dev); 11782c473729SZiyang Xuan name = dev->data->name; 11792c473729SZiyang Xuan port_id = dev->data->port_id; 11802c473729SZiyang Xuan 1181b8f5d2aeSThomas Monjalon dev->data->dev_started = 0; 1182b8f5d2aeSThomas Monjalon 11830371535dSJoyce Kong if (!rte_bit_relaxed_test_and_clear32(HINIC_DEV_START, 11840371535dSJoyce Kong &nic_dev->dev_status)) { 11852c473729SZiyang Xuan PMD_DRV_LOG(INFO, "Device %s already stopped", name); 118662024eb8SIvan Ilchenko return 0; 11872c473729SZiyang Xuan } 11882c473729SZiyang Xuan 11892c473729SZiyang Xuan /* just stop phy port and vport */ 11902c473729SZiyang Xuan rc = hinic_set_port_enable(nic_dev->hwdev, false); 11912c473729SZiyang Xuan if (rc) 11922c473729SZiyang Xuan PMD_DRV_LOG(WARNING, "Disable phy port failed, error: %d, dev_name: %s, port_id: %d", 11932c473729SZiyang Xuan rc, name, port_id); 11942c473729SZiyang Xuan 11952c473729SZiyang Xuan rc = hinic_set_vport_enable(nic_dev->hwdev, false); 11962c473729SZiyang Xuan if (rc) 11972c473729SZiyang Xuan PMD_DRV_LOG(WARNING, "Disable vport failed, error: %d, dev_name: %s, port_id: %d", 11982c473729SZiyang Xuan rc, name, port_id); 11992c473729SZiyang Xuan 12002c473729SZiyang Xuan /* Clear recorded link status */ 12012c473729SZiyang Xuan memset(&link, 0, sizeof(link)); 12022c473729SZiyang Xuan (void)rte_eth_linkstatus_set(dev, &link); 12032c473729SZiyang Xuan 12042c473729SZiyang Xuan /* flush pending io request */ 12052c473729SZiyang Xuan rc = hinic_rx_tx_flush(nic_dev->hwdev); 12062c473729SZiyang Xuan if (rc) 12072c473729SZiyang Xuan PMD_DRV_LOG(WARNING, "Flush pending io failed, error: %d, dev_name: %s, port_id: %d", 12082c473729SZiyang Xuan rc, name, port_id); 12092c473729SZiyang Xuan 12102c473729SZiyang Xuan /* clean rss table and rx_mode */ 12112c473729SZiyang Xuan hinic_remove_rxtx_configure(dev); 12122c473729SZiyang Xuan 12132c473729SZiyang Xuan /* clean root context */ 12142c473729SZiyang Xuan hinic_free_qp_ctxts(nic_dev->hwdev); 12152c473729SZiyang Xuan 12161fe89aa3SXiaoyun Wang hinic_destroy_fdir_filter(dev); 12171742421bSXiaoyun Wang 12182c473729SZiyang Xuan /* free mbuf */ 12192c473729SZiyang Xuan hinic_free_all_rx_mbuf(dev); 12202c473729SZiyang Xuan hinic_free_all_tx_mbuf(dev); 122162024eb8SIvan Ilchenko 122262024eb8SIvan Ilchenko return 0; 12232c473729SZiyang Xuan } 12242c473729SZiyang Xuan 122564727024SZiyang Xuan static void hinic_disable_interrupt(struct rte_eth_dev *dev) 122664727024SZiyang Xuan { 122764727024SZiyang Xuan struct hinic_nic_dev *nic_dev = HINIC_ETH_DEV_TO_PRIVATE_NIC_DEV(dev); 122864727024SZiyang Xuan struct rte_pci_device *pci_dev = RTE_ETH_DEV_TO_PCI(dev); 122964727024SZiyang Xuan int ret, retries = 0; 123064727024SZiyang Xuan 12310371535dSJoyce Kong rte_bit_relaxed_clear32(HINIC_DEV_INTR_EN, &nic_dev->dev_status); 123264727024SZiyang Xuan 123364727024SZiyang Xuan /* disable msix interrupt in hardware */ 123464727024SZiyang Xuan hinic_set_msix_state(nic_dev->hwdev, 0, HINIC_MSIX_DISABLE); 123564727024SZiyang Xuan 123664727024SZiyang Xuan /* disable rte interrupt */ 123764727024SZiyang Xuan ret = rte_intr_disable(&pci_dev->intr_handle); 123864727024SZiyang Xuan if (ret) 123964727024SZiyang Xuan PMD_DRV_LOG(ERR, "Disable intr failed: %d", ret); 124064727024SZiyang Xuan 124164727024SZiyang Xuan do { 124264727024SZiyang Xuan ret = 124364727024SZiyang Xuan rte_intr_callback_unregister(&pci_dev->intr_handle, 124464727024SZiyang Xuan hinic_dev_interrupt_handler, dev); 124564727024SZiyang Xuan if (ret >= 0) { 124664727024SZiyang Xuan break; 124764727024SZiyang Xuan } else if (ret == -EAGAIN) { 124864727024SZiyang Xuan rte_delay_ms(100); 124964727024SZiyang Xuan retries++; 125064727024SZiyang Xuan } else { 125164727024SZiyang Xuan PMD_DRV_LOG(ERR, "intr callback unregister failed: %d", 125264727024SZiyang Xuan ret); 125364727024SZiyang Xuan break; 125464727024SZiyang Xuan } 125564727024SZiyang Xuan } while (retries < HINIC_INTR_CB_UNREG_MAX_RETRIES); 125664727024SZiyang Xuan 125764727024SZiyang Xuan if (retries == HINIC_INTR_CB_UNREG_MAX_RETRIES) 125864727024SZiyang Xuan PMD_DRV_LOG(ERR, "Unregister intr callback failed after %d retries", 125964727024SZiyang Xuan retries); 1260511b7371SGuoyang Zhou 1261511b7371SGuoyang Zhou rte_bit_relaxed_clear32(HINIC_DEV_INIT, &nic_dev->dev_status); 126264727024SZiyang Xuan } 126364727024SZiyang Xuan 1264cb7b6606SZiyang Xuan static int hinic_set_dev_promiscuous(struct hinic_nic_dev *nic_dev, bool enable) 1265cb7b6606SZiyang Xuan { 1266224cff4bSXiaoyun Wang u32 rx_mode_ctrl; 1267224cff4bSXiaoyun Wang int err; 1268224cff4bSXiaoyun Wang 1269224cff4bSXiaoyun Wang err = hinic_mutex_lock(&nic_dev->rx_mode_mutex); 1270224cff4bSXiaoyun Wang if (err) 1271224cff4bSXiaoyun Wang return err; 1272224cff4bSXiaoyun Wang 1273224cff4bSXiaoyun Wang rx_mode_ctrl = nic_dev->rx_mode_status; 1274cb7b6606SZiyang Xuan 1275cb7b6606SZiyang Xuan if (enable) 1276cb7b6606SZiyang Xuan rx_mode_ctrl |= HINIC_RX_MODE_PROMISC; 1277cb7b6606SZiyang Xuan else 1278cb7b6606SZiyang Xuan rx_mode_ctrl &= (~HINIC_RX_MODE_PROMISC); 1279cb7b6606SZiyang Xuan 1280224cff4bSXiaoyun Wang err = hinic_config_rx_mode(nic_dev, rx_mode_ctrl); 1281224cff4bSXiaoyun Wang 1282224cff4bSXiaoyun Wang (void)hinic_mutex_unlock(&nic_dev->rx_mode_mutex); 1283224cff4bSXiaoyun Wang 1284224cff4bSXiaoyun Wang return err; 1285cb7b6606SZiyang Xuan } 1286cb7b6606SZiyang Xuan 1287cb7b6606SZiyang Xuan /** 1288cb7b6606SZiyang Xuan * DPDK callback to get device statistics. 1289cb7b6606SZiyang Xuan * 1290cb7b6606SZiyang Xuan * @param dev 1291cb7b6606SZiyang Xuan * Pointer to Ethernet device structure. 1292cb7b6606SZiyang Xuan * @param stats 1293cb7b6606SZiyang Xuan * Stats structure output buffer. 1294cb7b6606SZiyang Xuan * 1295cb7b6606SZiyang Xuan * @return 1296cb7b6606SZiyang Xuan * 0 on success and stats is filled, 1297cb7b6606SZiyang Xuan * negative error value otherwise. 1298cb7b6606SZiyang Xuan */ 1299cb7b6606SZiyang Xuan static int 1300cb7b6606SZiyang Xuan hinic_dev_stats_get(struct rte_eth_dev *dev, struct rte_eth_stats *stats) 1301cb7b6606SZiyang Xuan { 1302cb7b6606SZiyang Xuan int i, err, q_num; 1303cb7b6606SZiyang Xuan u64 rx_discards_pmd = 0; 1304cb7b6606SZiyang Xuan struct hinic_nic_dev *nic_dev = HINIC_ETH_DEV_TO_PRIVATE_NIC_DEV(dev); 1305cb7b6606SZiyang Xuan struct hinic_vport_stats vport_stats; 1306cb7b6606SZiyang Xuan struct hinic_rxq *rxq = NULL; 1307cb7b6606SZiyang Xuan struct hinic_rxq_stats rxq_stats; 1308cb7b6606SZiyang Xuan struct hinic_txq *txq = NULL; 1309cb7b6606SZiyang Xuan struct hinic_txq_stats txq_stats; 1310cb7b6606SZiyang Xuan 1311cb7b6606SZiyang Xuan err = hinic_get_vport_stats(nic_dev->hwdev, &vport_stats); 1312cb7b6606SZiyang Xuan if (err) { 1313cb7b6606SZiyang Xuan PMD_DRV_LOG(ERR, "Get vport stats from fw failed, nic_dev: %s", 1314cb7b6606SZiyang Xuan nic_dev->proc_dev_name); 1315cb7b6606SZiyang Xuan return err; 1316cb7b6606SZiyang Xuan } 1317cb7b6606SZiyang Xuan 13183930d9ceSXiaoyun Wang dev->data->rx_mbuf_alloc_failed = 0; 13193930d9ceSXiaoyun Wang 1320cb7b6606SZiyang Xuan /* rx queue stats */ 1321cb7b6606SZiyang Xuan q_num = (nic_dev->num_rq < RTE_ETHDEV_QUEUE_STAT_CNTRS) ? 1322cb7b6606SZiyang Xuan nic_dev->num_rq : RTE_ETHDEV_QUEUE_STAT_CNTRS; 1323cb7b6606SZiyang Xuan for (i = 0; i < q_num; i++) { 1324cb7b6606SZiyang Xuan rxq = nic_dev->rxqs[i]; 1325cb7b6606SZiyang Xuan hinic_rxq_get_stats(rxq, &rxq_stats); 1326cb7b6606SZiyang Xuan stats->q_ipackets[i] = rxq_stats.packets; 1327cb7b6606SZiyang Xuan stats->q_ibytes[i] = rxq_stats.bytes; 1328cb7b6606SZiyang Xuan stats->q_errors[i] = rxq_stats.rx_discards; 1329cb7b6606SZiyang Xuan 1330cb7b6606SZiyang Xuan stats->ierrors += rxq_stats.errors; 1331cb7b6606SZiyang Xuan rx_discards_pmd += rxq_stats.rx_discards; 1332cb7b6606SZiyang Xuan dev->data->rx_mbuf_alloc_failed += rxq_stats.rx_nombuf; 1333cb7b6606SZiyang Xuan } 1334cb7b6606SZiyang Xuan 1335cb7b6606SZiyang Xuan /* tx queue stats */ 1336cb7b6606SZiyang Xuan q_num = (nic_dev->num_sq < RTE_ETHDEV_QUEUE_STAT_CNTRS) ? 1337cb7b6606SZiyang Xuan nic_dev->num_sq : RTE_ETHDEV_QUEUE_STAT_CNTRS; 1338cb7b6606SZiyang Xuan for (i = 0; i < q_num; i++) { 1339cb7b6606SZiyang Xuan txq = nic_dev->txqs[i]; 1340cb7b6606SZiyang Xuan hinic_txq_get_stats(txq, &txq_stats); 1341cb7b6606SZiyang Xuan stats->q_opackets[i] = txq_stats.packets; 1342cb7b6606SZiyang Xuan stats->q_obytes[i] = txq_stats.bytes; 1343cb7b6606SZiyang Xuan stats->oerrors += (txq_stats.tx_busy + txq_stats.off_errs); 1344cb7b6606SZiyang Xuan } 1345cb7b6606SZiyang Xuan 1346cb7b6606SZiyang Xuan /* vport stats */ 1347cb7b6606SZiyang Xuan stats->oerrors += vport_stats.tx_discard_vport; 1348cb7b6606SZiyang Xuan 1349cb7b6606SZiyang Xuan stats->imissed = vport_stats.rx_discard_vport + rx_discards_pmd; 1350cb7b6606SZiyang Xuan 1351cb7b6606SZiyang Xuan stats->ipackets = (vport_stats.rx_unicast_pkts_vport + 1352cb7b6606SZiyang Xuan vport_stats.rx_multicast_pkts_vport + 1353cb7b6606SZiyang Xuan vport_stats.rx_broadcast_pkts_vport - 1354cb7b6606SZiyang Xuan rx_discards_pmd); 1355cb7b6606SZiyang Xuan 1356cb7b6606SZiyang Xuan stats->opackets = (vport_stats.tx_unicast_pkts_vport + 1357cb7b6606SZiyang Xuan vport_stats.tx_multicast_pkts_vport + 1358cb7b6606SZiyang Xuan vport_stats.tx_broadcast_pkts_vport); 1359cb7b6606SZiyang Xuan 1360cb7b6606SZiyang Xuan stats->ibytes = (vport_stats.rx_unicast_bytes_vport + 1361cb7b6606SZiyang Xuan vport_stats.rx_multicast_bytes_vport + 1362cb7b6606SZiyang Xuan vport_stats.rx_broadcast_bytes_vport); 1363cb7b6606SZiyang Xuan 1364cb7b6606SZiyang Xuan stats->obytes = (vport_stats.tx_unicast_bytes_vport + 1365cb7b6606SZiyang Xuan vport_stats.tx_multicast_bytes_vport + 1366cb7b6606SZiyang Xuan vport_stats.tx_broadcast_bytes_vport); 1367cb7b6606SZiyang Xuan return 0; 1368cb7b6606SZiyang Xuan } 1369cb7b6606SZiyang Xuan 1370cb7b6606SZiyang Xuan /** 1371cb7b6606SZiyang Xuan * DPDK callback to clear device statistics. 1372cb7b6606SZiyang Xuan * 1373cb7b6606SZiyang Xuan * @param dev 1374cb7b6606SZiyang Xuan * Pointer to Ethernet device structure. 1375cb7b6606SZiyang Xuan */ 13769970a9adSIgor Romanov static int hinic_dev_stats_reset(struct rte_eth_dev *dev) 1377cb7b6606SZiyang Xuan { 1378cb7b6606SZiyang Xuan int qid; 1379cb7b6606SZiyang Xuan struct hinic_rxq *rxq = NULL; 1380cb7b6606SZiyang Xuan struct hinic_txq *txq = NULL; 1381cb7b6606SZiyang Xuan struct hinic_nic_dev *nic_dev = HINIC_ETH_DEV_TO_PRIVATE_NIC_DEV(dev); 13829970a9adSIgor Romanov int ret; 1383cb7b6606SZiyang Xuan 13849970a9adSIgor Romanov ret = hinic_clear_vport_stats(nic_dev->hwdev); 13859970a9adSIgor Romanov if (ret != 0) 13869970a9adSIgor Romanov return ret; 1387cb7b6606SZiyang Xuan 1388cb7b6606SZiyang Xuan for (qid = 0; qid < nic_dev->num_rq; qid++) { 1389cb7b6606SZiyang Xuan rxq = nic_dev->rxqs[qid]; 1390cb7b6606SZiyang Xuan hinic_rxq_stats_reset(rxq); 1391cb7b6606SZiyang Xuan } 1392cb7b6606SZiyang Xuan 1393cb7b6606SZiyang Xuan for (qid = 0; qid < nic_dev->num_sq; qid++) { 1394cb7b6606SZiyang Xuan txq = nic_dev->txqs[qid]; 1395cb7b6606SZiyang Xuan hinic_txq_stats_reset(txq); 1396cb7b6606SZiyang Xuan } 13979970a9adSIgor Romanov 13989970a9adSIgor Romanov return 0; 1399cb7b6606SZiyang Xuan } 1400cb7b6606SZiyang Xuan 1401cb7b6606SZiyang Xuan /** 1402cb7b6606SZiyang Xuan * DPDK callback to clear device extended statistics. 1403cb7b6606SZiyang Xuan * 1404cb7b6606SZiyang Xuan * @param dev 1405cb7b6606SZiyang Xuan * Pointer to Ethernet device structure. 14066691acefSXiaoyun Wang */ 14079970a9adSIgor Romanov static int hinic_dev_xstats_reset(struct rte_eth_dev *dev) 1408cb7b6606SZiyang Xuan { 1409cb7b6606SZiyang Xuan struct hinic_nic_dev *nic_dev = HINIC_ETH_DEV_TO_PRIVATE_NIC_DEV(dev); 14109970a9adSIgor Romanov int ret; 1411cb7b6606SZiyang Xuan 14129970a9adSIgor Romanov ret = hinic_dev_stats_reset(dev); 14139970a9adSIgor Romanov if (ret != 0) 14149970a9adSIgor Romanov return ret; 1415cb7b6606SZiyang Xuan 14169970a9adSIgor Romanov if (hinic_func_type(nic_dev->hwdev) != TYPE_VF) { 14179970a9adSIgor Romanov ret = hinic_clear_phy_port_stats(nic_dev->hwdev); 14189970a9adSIgor Romanov if (ret != 0) 14199970a9adSIgor Romanov return ret; 14209970a9adSIgor Romanov } 14219970a9adSIgor Romanov 14229970a9adSIgor Romanov return 0; 1423cb7b6606SZiyang Xuan } 1424cb7b6606SZiyang Xuan 14252c473729SZiyang Xuan static void hinic_gen_random_mac_addr(struct rte_ether_addr *mac_addr) 14262c473729SZiyang Xuan { 14272c473729SZiyang Xuan uint64_t random_value; 14282c473729SZiyang Xuan 14292c473729SZiyang Xuan /* Set Organizationally Unique Identifier (OUI) prefix */ 14302c473729SZiyang Xuan mac_addr->addr_bytes[0] = 0x00; 14312c473729SZiyang Xuan mac_addr->addr_bytes[1] = 0x09; 14322c473729SZiyang Xuan mac_addr->addr_bytes[2] = 0xC0; 14332c473729SZiyang Xuan /* Force indication of locally assigned MAC address. */ 14342c473729SZiyang Xuan mac_addr->addr_bytes[0] |= RTE_ETHER_LOCAL_ADMIN_ADDR; 14352c473729SZiyang Xuan /* Generate the last 3 bytes of the MAC address with a random number. */ 14362c473729SZiyang Xuan random_value = rte_rand(); 14372c473729SZiyang Xuan memcpy(&mac_addr->addr_bytes[3], &random_value, 3); 14382c473729SZiyang Xuan } 14392c473729SZiyang Xuan 144064727024SZiyang Xuan /** 144164727024SZiyang Xuan * Init mac_vlan table in NIC. 144264727024SZiyang Xuan * 144364727024SZiyang Xuan * @param dev 144464727024SZiyang Xuan * Pointer to Ethernet device structure. 144564727024SZiyang Xuan * 144664727024SZiyang Xuan * @return 144764727024SZiyang Xuan * 0 on success and stats is filled, 144864727024SZiyang Xuan * negative error value otherwise. 144964727024SZiyang Xuan */ 145064727024SZiyang Xuan static int hinic_init_mac_addr(struct rte_eth_dev *eth_dev) 145164727024SZiyang Xuan { 145264727024SZiyang Xuan struct hinic_nic_dev *nic_dev = 145364727024SZiyang Xuan HINIC_ETH_DEV_TO_PRIVATE_NIC_DEV(eth_dev); 145464727024SZiyang Xuan uint8_t addr_bytes[RTE_ETHER_ADDR_LEN]; 145564727024SZiyang Xuan u16 func_id = 0; 145664727024SZiyang Xuan int rc = 0; 145764727024SZiyang Xuan 145864727024SZiyang Xuan rc = hinic_get_default_mac(nic_dev->hwdev, addr_bytes); 145964727024SZiyang Xuan if (rc) 146064727024SZiyang Xuan return rc; 146164727024SZiyang Xuan 146200499a22SXiaoyun Wang rte_ether_addr_copy((struct rte_ether_addr *)addr_bytes, 146300499a22SXiaoyun Wang ð_dev->data->mac_addrs[0]); 146400499a22SXiaoyun Wang if (rte_is_zero_ether_addr(ð_dev->data->mac_addrs[0])) 146500499a22SXiaoyun Wang hinic_gen_random_mac_addr(ð_dev->data->mac_addrs[0]); 14662c473729SZiyang Xuan 146764727024SZiyang Xuan func_id = hinic_global_func_id(nic_dev->hwdev); 146800499a22SXiaoyun Wang rc = hinic_set_mac(nic_dev->hwdev, 146900499a22SXiaoyun Wang eth_dev->data->mac_addrs[0].addr_bytes, 147064727024SZiyang Xuan 0, func_id); 147164727024SZiyang Xuan if (rc && rc != HINIC_PF_SET_VF_ALREADY) 147264727024SZiyang Xuan return rc; 147364727024SZiyang Xuan 147400499a22SXiaoyun Wang rte_ether_addr_copy(ð_dev->data->mac_addrs[0], 147500499a22SXiaoyun Wang &nic_dev->default_addr); 147600499a22SXiaoyun Wang 14771d09792aSZiyang Xuan return 0; 14781d09792aSZiyang Xuan } 14791d09792aSZiyang Xuan 148000499a22SXiaoyun Wang static void hinic_delete_mc_addr_list(struct hinic_nic_dev *nic_dev) 148100499a22SXiaoyun Wang { 148200499a22SXiaoyun Wang u16 func_id; 148300499a22SXiaoyun Wang u32 i; 148400499a22SXiaoyun Wang 148500499a22SXiaoyun Wang func_id = hinic_global_func_id(nic_dev->hwdev); 148600499a22SXiaoyun Wang 148700499a22SXiaoyun Wang for (i = 0; i < HINIC_MAX_MC_MAC_ADDRS; i++) { 148800499a22SXiaoyun Wang if (rte_is_zero_ether_addr(&nic_dev->mc_list[i])) 148900499a22SXiaoyun Wang break; 149000499a22SXiaoyun Wang 149100499a22SXiaoyun Wang hinic_del_mac(nic_dev->hwdev, nic_dev->mc_list[i].addr_bytes, 149200499a22SXiaoyun Wang 0, func_id); 149300499a22SXiaoyun Wang memset(&nic_dev->mc_list[i], 0, sizeof(struct rte_ether_addr)); 149400499a22SXiaoyun Wang } 149500499a22SXiaoyun Wang } 149600499a22SXiaoyun Wang 14971d09792aSZiyang Xuan /** 149864727024SZiyang Xuan * Deinit mac_vlan table in NIC. 149964727024SZiyang Xuan * 150064727024SZiyang Xuan * @param dev 150164727024SZiyang Xuan * Pointer to Ethernet device structure. 150264727024SZiyang Xuan * 150364727024SZiyang Xuan * @return 150464727024SZiyang Xuan * 0 on success and stats is filled, 150564727024SZiyang Xuan * negative error value otherwise. 150664727024SZiyang Xuan */ 150764727024SZiyang Xuan static void hinic_deinit_mac_addr(struct rte_eth_dev *eth_dev) 150864727024SZiyang Xuan { 150964727024SZiyang Xuan struct hinic_nic_dev *nic_dev = 151064727024SZiyang Xuan HINIC_ETH_DEV_TO_PRIVATE_NIC_DEV(eth_dev); 151164727024SZiyang Xuan u16 func_id = 0; 151200499a22SXiaoyun Wang int rc; 151300499a22SXiaoyun Wang int i; 151464727024SZiyang Xuan 151564727024SZiyang Xuan func_id = hinic_global_func_id(nic_dev->hwdev); 151600499a22SXiaoyun Wang 151700499a22SXiaoyun Wang for (i = 0; i < HINIC_MAX_UC_MAC_ADDRS; i++) { 151800499a22SXiaoyun Wang if (rte_is_zero_ether_addr(ð_dev->data->mac_addrs[i])) 151900499a22SXiaoyun Wang continue; 152000499a22SXiaoyun Wang 152164727024SZiyang Xuan rc = hinic_del_mac(nic_dev->hwdev, 152200499a22SXiaoyun Wang eth_dev->data->mac_addrs[i].addr_bytes, 152364727024SZiyang Xuan 0, func_id); 152464727024SZiyang Xuan if (rc && rc != HINIC_PF_SET_VF_ALREADY) 152564727024SZiyang Xuan PMD_DRV_LOG(ERR, "Delete mac table failed, dev_name: %s", 152664727024SZiyang Xuan eth_dev->data->name); 152700499a22SXiaoyun Wang 152800499a22SXiaoyun Wang memset(ð_dev->data->mac_addrs[i], 0, 152900499a22SXiaoyun Wang sizeof(struct rte_ether_addr)); 153000499a22SXiaoyun Wang } 153100499a22SXiaoyun Wang 153200499a22SXiaoyun Wang /* delete multicast mac addrs */ 153300499a22SXiaoyun Wang hinic_delete_mc_addr_list(nic_dev); 1534511b7371SGuoyang Zhou 1535511b7371SGuoyang Zhou rte_free(nic_dev->mc_list); 1536511b7371SGuoyang Zhou 153764727024SZiyang Xuan } 153864727024SZiyang Xuan 15398260eba6SXiaoyun Wang static int hinic_dev_set_mtu(struct rte_eth_dev *dev, uint16_t mtu) 15408260eba6SXiaoyun Wang { 15418260eba6SXiaoyun Wang struct hinic_nic_dev *nic_dev = HINIC_ETH_DEV_TO_PRIVATE_NIC_DEV(dev); 1542254bd849SXiaoyun Wang uint32_t frame_size; 1543254bd849SXiaoyun Wang int ret = 0; 15448260eba6SXiaoyun Wang 15458260eba6SXiaoyun Wang PMD_DRV_LOG(INFO, "Set port mtu, port_id: %d, mtu: %d, max_pkt_len: %d", 15468260eba6SXiaoyun Wang dev->data->port_id, mtu, HINIC_MTU_TO_PKTLEN(mtu)); 15478260eba6SXiaoyun Wang 15488260eba6SXiaoyun Wang if (mtu < HINIC_MIN_MTU_SIZE || mtu > HINIC_MAX_MTU_SIZE) { 15498260eba6SXiaoyun Wang PMD_DRV_LOG(ERR, "Invalid mtu: %d, must between %d and %d", 15508260eba6SXiaoyun Wang mtu, HINIC_MIN_MTU_SIZE, HINIC_MAX_MTU_SIZE); 15518260eba6SXiaoyun Wang return -EINVAL; 15528260eba6SXiaoyun Wang } 15538260eba6SXiaoyun Wang 15548260eba6SXiaoyun Wang ret = hinic_set_port_mtu(nic_dev->hwdev, mtu); 15558260eba6SXiaoyun Wang if (ret) { 15568260eba6SXiaoyun Wang PMD_DRV_LOG(ERR, "Set port mtu failed, ret: %d", ret); 15578260eba6SXiaoyun Wang return ret; 15588260eba6SXiaoyun Wang } 15598260eba6SXiaoyun Wang 15608260eba6SXiaoyun Wang /* update max frame size */ 1561254bd849SXiaoyun Wang frame_size = HINIC_MTU_TO_PKTLEN(mtu); 1562e542ab51SSteve Yang if (frame_size > HINIC_ETH_MAX_LEN) 1563254bd849SXiaoyun Wang dev->data->dev_conf.rxmode.offloads |= 1564254bd849SXiaoyun Wang DEV_RX_OFFLOAD_JUMBO_FRAME; 1565254bd849SXiaoyun Wang else 1566254bd849SXiaoyun Wang dev->data->dev_conf.rxmode.offloads &= 1567254bd849SXiaoyun Wang ~DEV_RX_OFFLOAD_JUMBO_FRAME; 1568254bd849SXiaoyun Wang 1569254bd849SXiaoyun Wang dev->data->dev_conf.rxmode.max_rx_pkt_len = frame_size; 15708260eba6SXiaoyun Wang nic_dev->mtu_size = mtu; 15718260eba6SXiaoyun Wang 15728260eba6SXiaoyun Wang return ret; 15738260eba6SXiaoyun Wang } 15748260eba6SXiaoyun Wang 1575fdba3bf1SXiaoyun Wang static void hinic_store_vlan_filter(struct hinic_nic_dev *nic_dev, 1576fdba3bf1SXiaoyun Wang u16 vlan_id, bool on) 1577fdba3bf1SXiaoyun Wang { 1578fdba3bf1SXiaoyun Wang u32 vid_idx, vid_bit; 1579fdba3bf1SXiaoyun Wang 1580fdba3bf1SXiaoyun Wang vid_idx = HINIC_VFTA_IDX(vlan_id); 1581fdba3bf1SXiaoyun Wang vid_bit = HINIC_VFTA_BIT(vlan_id); 1582fdba3bf1SXiaoyun Wang 1583fdba3bf1SXiaoyun Wang if (on) 1584fdba3bf1SXiaoyun Wang nic_dev->vfta[vid_idx] |= vid_bit; 1585fdba3bf1SXiaoyun Wang else 1586fdba3bf1SXiaoyun Wang nic_dev->vfta[vid_idx] &= ~vid_bit; 1587fdba3bf1SXiaoyun Wang } 1588fdba3bf1SXiaoyun Wang 1589fdba3bf1SXiaoyun Wang static bool hinic_find_vlan_filter(struct hinic_nic_dev *nic_dev, 1590fdba3bf1SXiaoyun Wang uint16_t vlan_id) 1591fdba3bf1SXiaoyun Wang { 1592fdba3bf1SXiaoyun Wang u32 vid_idx, vid_bit; 1593fdba3bf1SXiaoyun Wang 1594fdba3bf1SXiaoyun Wang vid_idx = HINIC_VFTA_IDX(vlan_id); 1595fdba3bf1SXiaoyun Wang vid_bit = HINIC_VFTA_BIT(vlan_id); 1596fdba3bf1SXiaoyun Wang 1597fdba3bf1SXiaoyun Wang return (nic_dev->vfta[vid_idx] & vid_bit) ? TRUE : FALSE; 1598fdba3bf1SXiaoyun Wang } 1599fdba3bf1SXiaoyun Wang 1600fdba3bf1SXiaoyun Wang /** 1601fdba3bf1SXiaoyun Wang * DPDK callback to set vlan filter. 1602fdba3bf1SXiaoyun Wang * 1603fdba3bf1SXiaoyun Wang * @param dev 1604fdba3bf1SXiaoyun Wang * Pointer to Ethernet device structure. 1605fdba3bf1SXiaoyun Wang * @param vlan_id 1606fdba3bf1SXiaoyun Wang * vlan id is used to filter vlan packets 1607fdba3bf1SXiaoyun Wang * @param enable 1608fdba3bf1SXiaoyun Wang * enable disable or enable vlan filter function 1609fdba3bf1SXiaoyun Wang */ 1610fdba3bf1SXiaoyun Wang static int hinic_vlan_filter_set(struct rte_eth_dev *dev, 1611fdba3bf1SXiaoyun Wang uint16_t vlan_id, int enable) 1612fdba3bf1SXiaoyun Wang { 1613fdba3bf1SXiaoyun Wang struct hinic_nic_dev *nic_dev = HINIC_ETH_DEV_TO_PRIVATE_NIC_DEV(dev); 1614fdba3bf1SXiaoyun Wang int err = 0; 1615fdba3bf1SXiaoyun Wang u16 func_id; 1616fdba3bf1SXiaoyun Wang 1617fdba3bf1SXiaoyun Wang if (vlan_id > RTE_ETHER_MAX_VLAN_ID) 1618fdba3bf1SXiaoyun Wang return -EINVAL; 1619fdba3bf1SXiaoyun Wang 1620*2cfd68ecSGuoyang Zhou if (vlan_id == 0) 1621*2cfd68ecSGuoyang Zhou return 0; 1622*2cfd68ecSGuoyang Zhou 1623fdba3bf1SXiaoyun Wang func_id = hinic_global_func_id(nic_dev->hwdev); 1624fdba3bf1SXiaoyun Wang 1625fdba3bf1SXiaoyun Wang if (enable) { 1626fdba3bf1SXiaoyun Wang /* If vlanid is already set, just return */ 1627fdba3bf1SXiaoyun Wang if (hinic_find_vlan_filter(nic_dev, vlan_id)) { 1628fdba3bf1SXiaoyun Wang PMD_DRV_LOG(INFO, "Vlan %u has been added, device: %s", 1629fdba3bf1SXiaoyun Wang vlan_id, nic_dev->proc_dev_name); 1630fdba3bf1SXiaoyun Wang return 0; 1631fdba3bf1SXiaoyun Wang } 1632fdba3bf1SXiaoyun Wang 1633fdba3bf1SXiaoyun Wang err = hinic_add_remove_vlan(nic_dev->hwdev, vlan_id, 1634fdba3bf1SXiaoyun Wang func_id, TRUE); 1635fdba3bf1SXiaoyun Wang } else { 1636fdba3bf1SXiaoyun Wang /* If vlanid can't be found, just return */ 1637fdba3bf1SXiaoyun Wang if (!hinic_find_vlan_filter(nic_dev, vlan_id)) { 1638fdba3bf1SXiaoyun Wang PMD_DRV_LOG(INFO, "Vlan %u is not in the vlan filter list, device: %s", 1639fdba3bf1SXiaoyun Wang vlan_id, nic_dev->proc_dev_name); 1640fdba3bf1SXiaoyun Wang return 0; 1641fdba3bf1SXiaoyun Wang } 1642fdba3bf1SXiaoyun Wang 1643fdba3bf1SXiaoyun Wang err = hinic_add_remove_vlan(nic_dev->hwdev, vlan_id, 1644fdba3bf1SXiaoyun Wang func_id, FALSE); 1645fdba3bf1SXiaoyun Wang } 1646fdba3bf1SXiaoyun Wang 1647fdba3bf1SXiaoyun Wang if (err) { 1648fdba3bf1SXiaoyun Wang PMD_DRV_LOG(ERR, "%s vlan failed, func_id: %d, vlan_id: %d, err: %d", 1649fdba3bf1SXiaoyun Wang enable ? "Add" : "Remove", func_id, vlan_id, err); 1650fdba3bf1SXiaoyun Wang return err; 1651fdba3bf1SXiaoyun Wang } 1652fdba3bf1SXiaoyun Wang 1653fdba3bf1SXiaoyun Wang hinic_store_vlan_filter(nic_dev, vlan_id, enable); 1654fdba3bf1SXiaoyun Wang 1655fdba3bf1SXiaoyun Wang PMD_DRV_LOG(INFO, "%s vlan %u succeed, device: %s", 1656fdba3bf1SXiaoyun Wang enable ? "Add" : "Remove", vlan_id, nic_dev->proc_dev_name); 1657fdba3bf1SXiaoyun Wang return 0; 1658fdba3bf1SXiaoyun Wang } 1659fdba3bf1SXiaoyun Wang 1660fdba3bf1SXiaoyun Wang /** 1661fdba3bf1SXiaoyun Wang * DPDK callback to enable or disable vlan offload. 1662fdba3bf1SXiaoyun Wang * 1663fdba3bf1SXiaoyun Wang * @param dev 1664fdba3bf1SXiaoyun Wang * Pointer to Ethernet device structure. 1665fdba3bf1SXiaoyun Wang * @param mask 1666fdba3bf1SXiaoyun Wang * Definitions used for VLAN setting 1667fdba3bf1SXiaoyun Wang */ 1668fdba3bf1SXiaoyun Wang static int hinic_vlan_offload_set(struct rte_eth_dev *dev, int mask) 1669fdba3bf1SXiaoyun Wang { 1670fdba3bf1SXiaoyun Wang struct hinic_nic_dev *nic_dev = HINIC_ETH_DEV_TO_PRIVATE_NIC_DEV(dev); 1671fdba3bf1SXiaoyun Wang struct rte_eth_rxmode *rxmode = &dev->data->dev_conf.rxmode; 1672fdba3bf1SXiaoyun Wang bool on; 1673fdba3bf1SXiaoyun Wang int err; 1674fdba3bf1SXiaoyun Wang 1675fdba3bf1SXiaoyun Wang /* Enable or disable VLAN filter */ 1676fdba3bf1SXiaoyun Wang if (mask & ETH_VLAN_FILTER_MASK) { 1677fdba3bf1SXiaoyun Wang on = (rxmode->offloads & DEV_RX_OFFLOAD_VLAN_FILTER) ? 1678fdba3bf1SXiaoyun Wang TRUE : FALSE; 1679fdba3bf1SXiaoyun Wang err = hinic_config_vlan_filter(nic_dev->hwdev, on); 1680fdba3bf1SXiaoyun Wang if (err == HINIC_MGMT_CMD_UNSUPPORTED) { 1681fdba3bf1SXiaoyun Wang PMD_DRV_LOG(WARNING, 1682fdba3bf1SXiaoyun Wang "Current matching version does not support vlan filter configuration, device: %s, port_id: %d", 1683fdba3bf1SXiaoyun Wang nic_dev->proc_dev_name, dev->data->port_id); 1684fdba3bf1SXiaoyun Wang } else if (err) { 1685fdba3bf1SXiaoyun Wang PMD_DRV_LOG(ERR, "Failed to %s vlan filter, device: %s, port_id: %d, err: %d", 1686fdba3bf1SXiaoyun Wang on ? "enable" : "disable", 1687fdba3bf1SXiaoyun Wang nic_dev->proc_dev_name, 1688fdba3bf1SXiaoyun Wang dev->data->port_id, err); 1689fdba3bf1SXiaoyun Wang return err; 1690fdba3bf1SXiaoyun Wang } 1691fdba3bf1SXiaoyun Wang 1692fdba3bf1SXiaoyun Wang PMD_DRV_LOG(INFO, "%s vlan filter succeed, device: %s, port_id: %d", 1693fdba3bf1SXiaoyun Wang on ? "Enable" : "Disable", 1694fdba3bf1SXiaoyun Wang nic_dev->proc_dev_name, dev->data->port_id); 1695fdba3bf1SXiaoyun Wang } 1696fdba3bf1SXiaoyun Wang 1697fdba3bf1SXiaoyun Wang /* Enable or disable VLAN stripping */ 1698fdba3bf1SXiaoyun Wang if (mask & ETH_VLAN_STRIP_MASK) { 1699fdba3bf1SXiaoyun Wang on = (rxmode->offloads & DEV_RX_OFFLOAD_VLAN_STRIP) ? 1700fdba3bf1SXiaoyun Wang TRUE : FALSE; 1701fdba3bf1SXiaoyun Wang err = hinic_set_rx_vlan_offload(nic_dev->hwdev, on); 1702fdba3bf1SXiaoyun Wang if (err) { 1703fdba3bf1SXiaoyun Wang PMD_DRV_LOG(ERR, "Failed to %s vlan strip, device: %s, port_id: %d, err: %d", 1704fdba3bf1SXiaoyun Wang on ? "enable" : "disable", 1705fdba3bf1SXiaoyun Wang nic_dev->proc_dev_name, 1706fdba3bf1SXiaoyun Wang dev->data->port_id, err); 1707fdba3bf1SXiaoyun Wang return err; 1708fdba3bf1SXiaoyun Wang } 1709fdba3bf1SXiaoyun Wang 1710fdba3bf1SXiaoyun Wang PMD_DRV_LOG(INFO, "%s vlan strip succeed, device: %s, port_id: %d", 1711fdba3bf1SXiaoyun Wang on ? "Enable" : "Disable", 1712fdba3bf1SXiaoyun Wang nic_dev->proc_dev_name, dev->data->port_id); 1713fdba3bf1SXiaoyun Wang } 1714fdba3bf1SXiaoyun Wang 1715fdba3bf1SXiaoyun Wang return 0; 1716fdba3bf1SXiaoyun Wang } 1717fdba3bf1SXiaoyun Wang 1718fdba3bf1SXiaoyun Wang static void hinic_remove_all_vlanid(struct rte_eth_dev *eth_dev) 1719fdba3bf1SXiaoyun Wang { 1720fdba3bf1SXiaoyun Wang struct hinic_nic_dev *nic_dev = 1721fdba3bf1SXiaoyun Wang HINIC_ETH_DEV_TO_PRIVATE_NIC_DEV(eth_dev); 1722fdba3bf1SXiaoyun Wang u16 func_id; 1723fdba3bf1SXiaoyun Wang int i; 1724fdba3bf1SXiaoyun Wang 1725fdba3bf1SXiaoyun Wang func_id = hinic_global_func_id(nic_dev->hwdev); 1726fdba3bf1SXiaoyun Wang for (i = 0; i <= RTE_ETHER_MAX_VLAN_ID; i++) { 1727fdba3bf1SXiaoyun Wang /* If can't find it, continue */ 1728fdba3bf1SXiaoyun Wang if (!hinic_find_vlan_filter(nic_dev, i)) 1729fdba3bf1SXiaoyun Wang continue; 1730fdba3bf1SXiaoyun Wang 1731fdba3bf1SXiaoyun Wang (void)hinic_add_remove_vlan(nic_dev->hwdev, i, func_id, FALSE); 1732fdba3bf1SXiaoyun Wang hinic_store_vlan_filter(nic_dev, i, false); 1733fdba3bf1SXiaoyun Wang } 1734fdba3bf1SXiaoyun Wang } 1735fdba3bf1SXiaoyun Wang 17368260eba6SXiaoyun Wang static int hinic_set_dev_allmulticast(struct hinic_nic_dev *nic_dev, 17378260eba6SXiaoyun Wang bool enable) 17388260eba6SXiaoyun Wang { 1739224cff4bSXiaoyun Wang u32 rx_mode_ctrl; 1740224cff4bSXiaoyun Wang int err; 1741224cff4bSXiaoyun Wang 1742224cff4bSXiaoyun Wang err = hinic_mutex_lock(&nic_dev->rx_mode_mutex); 1743224cff4bSXiaoyun Wang if (err) 1744224cff4bSXiaoyun Wang return err; 1745224cff4bSXiaoyun Wang 1746224cff4bSXiaoyun Wang rx_mode_ctrl = nic_dev->rx_mode_status; 17478260eba6SXiaoyun Wang 17488260eba6SXiaoyun Wang if (enable) 17498260eba6SXiaoyun Wang rx_mode_ctrl |= HINIC_RX_MODE_MC_ALL; 17508260eba6SXiaoyun Wang else 17518260eba6SXiaoyun Wang rx_mode_ctrl &= (~HINIC_RX_MODE_MC_ALL); 17528260eba6SXiaoyun Wang 1753224cff4bSXiaoyun Wang err = hinic_config_rx_mode(nic_dev, rx_mode_ctrl); 1754224cff4bSXiaoyun Wang 1755224cff4bSXiaoyun Wang (void)hinic_mutex_unlock(&nic_dev->rx_mode_mutex); 1756224cff4bSXiaoyun Wang 1757224cff4bSXiaoyun Wang return err; 17588260eba6SXiaoyun Wang } 17598260eba6SXiaoyun Wang 17608260eba6SXiaoyun Wang /** 17618260eba6SXiaoyun Wang * DPDK callback to enable allmulticast mode. 17628260eba6SXiaoyun Wang * 17638260eba6SXiaoyun Wang * @param dev 17648260eba6SXiaoyun Wang * Pointer to Ethernet device structure. 17658260eba6SXiaoyun Wang * 17668260eba6SXiaoyun Wang * @return 17678260eba6SXiaoyun Wang * 0 on success, 17688260eba6SXiaoyun Wang * negative error value otherwise. 17698260eba6SXiaoyun Wang */ 17708260eba6SXiaoyun Wang static int hinic_dev_allmulticast_enable(struct rte_eth_dev *dev) 17718260eba6SXiaoyun Wang { 17728260eba6SXiaoyun Wang int ret = HINIC_OK; 17738260eba6SXiaoyun Wang struct hinic_nic_dev *nic_dev = HINIC_ETH_DEV_TO_PRIVATE_NIC_DEV(dev); 17748260eba6SXiaoyun Wang 17758260eba6SXiaoyun Wang ret = hinic_set_dev_allmulticast(nic_dev, true); 17768260eba6SXiaoyun Wang if (ret) { 17778260eba6SXiaoyun Wang PMD_DRV_LOG(ERR, "Enable allmulticast failed, error: %d", ret); 17788260eba6SXiaoyun Wang return ret; 17798260eba6SXiaoyun Wang } 17808260eba6SXiaoyun Wang 17818260eba6SXiaoyun Wang PMD_DRV_LOG(INFO, "Enable allmulticast succeed, nic_dev: %s, port_id: %d", 17828260eba6SXiaoyun Wang nic_dev->proc_dev_name, dev->data->port_id); 17838260eba6SXiaoyun Wang return 0; 17848260eba6SXiaoyun Wang } 17858260eba6SXiaoyun Wang 17868260eba6SXiaoyun Wang /** 17878260eba6SXiaoyun Wang * DPDK callback to disable allmulticast mode. 17888260eba6SXiaoyun Wang * 17898260eba6SXiaoyun Wang * @param dev 17908260eba6SXiaoyun Wang * Pointer to Ethernet device structure. 17918260eba6SXiaoyun Wang * 17928260eba6SXiaoyun Wang * @return 17938260eba6SXiaoyun Wang * 0 on success, 17948260eba6SXiaoyun Wang * negative error value otherwise. 17958260eba6SXiaoyun Wang */ 17968260eba6SXiaoyun Wang static int hinic_dev_allmulticast_disable(struct rte_eth_dev *dev) 17978260eba6SXiaoyun Wang { 17988260eba6SXiaoyun Wang int ret = HINIC_OK; 17998260eba6SXiaoyun Wang struct hinic_nic_dev *nic_dev = HINIC_ETH_DEV_TO_PRIVATE_NIC_DEV(dev); 18008260eba6SXiaoyun Wang 18018260eba6SXiaoyun Wang ret = hinic_set_dev_allmulticast(nic_dev, false); 18028260eba6SXiaoyun Wang if (ret) { 18038260eba6SXiaoyun Wang PMD_DRV_LOG(ERR, "Disable allmulticast failed, error: %d", ret); 18048260eba6SXiaoyun Wang return ret; 18058260eba6SXiaoyun Wang } 18068260eba6SXiaoyun Wang 18078260eba6SXiaoyun Wang PMD_DRV_LOG(INFO, "Disable allmulticast succeed, nic_dev: %s, port_id: %d", 18088260eba6SXiaoyun Wang nic_dev->proc_dev_name, dev->data->port_id); 18098260eba6SXiaoyun Wang return 0; 18108260eba6SXiaoyun Wang } 18118260eba6SXiaoyun Wang 1812cb7b6606SZiyang Xuan /** 1813cb7b6606SZiyang Xuan * DPDK callback to enable promiscuous mode. 1814cb7b6606SZiyang Xuan * 1815cb7b6606SZiyang Xuan * @param dev 1816cb7b6606SZiyang Xuan * Pointer to Ethernet device structure. 18179039c812SAndrew Rybchenko * 18189039c812SAndrew Rybchenko * @return 18199039c812SAndrew Rybchenko * 0 on success, 18209039c812SAndrew Rybchenko * negative error value otherwise. 1821cb7b6606SZiyang Xuan */ 18229039c812SAndrew Rybchenko static int hinic_dev_promiscuous_enable(struct rte_eth_dev *dev) 1823cb7b6606SZiyang Xuan { 1824cb7b6606SZiyang Xuan int rc = HINIC_OK; 1825cb7b6606SZiyang Xuan struct hinic_nic_dev *nic_dev = HINIC_ETH_DEV_TO_PRIVATE_NIC_DEV(dev); 1826cb7b6606SZiyang Xuan 1827cb7b6606SZiyang Xuan PMD_DRV_LOG(INFO, "Enable promiscuous, nic_dev: %s, port_id: %d, promisc: %d", 1828cb7b6606SZiyang Xuan nic_dev->proc_dev_name, dev->data->port_id, 1829cb7b6606SZiyang Xuan dev->data->promiscuous); 1830cb7b6606SZiyang Xuan 1831cb7b6606SZiyang Xuan rc = hinic_set_dev_promiscuous(nic_dev, true); 1832cb7b6606SZiyang Xuan if (rc) 1833cb7b6606SZiyang Xuan PMD_DRV_LOG(ERR, "Enable promiscuous failed"); 18349039c812SAndrew Rybchenko 18359039c812SAndrew Rybchenko return rc; 1836cb7b6606SZiyang Xuan } 1837cb7b6606SZiyang Xuan 1838cb7b6606SZiyang Xuan /** 1839cb7b6606SZiyang Xuan * DPDK callback to disable promiscuous mode. 1840cb7b6606SZiyang Xuan * 1841cb7b6606SZiyang Xuan * @param dev 1842cb7b6606SZiyang Xuan * Pointer to Ethernet device structure. 18439039c812SAndrew Rybchenko * 18449039c812SAndrew Rybchenko * @return 18459039c812SAndrew Rybchenko * 0 on success, 18469039c812SAndrew Rybchenko * negative error value otherwise. 1847cb7b6606SZiyang Xuan */ 18489039c812SAndrew Rybchenko static int hinic_dev_promiscuous_disable(struct rte_eth_dev *dev) 1849cb7b6606SZiyang Xuan { 1850cb7b6606SZiyang Xuan int rc = HINIC_OK; 1851cb7b6606SZiyang Xuan struct hinic_nic_dev *nic_dev = HINIC_ETH_DEV_TO_PRIVATE_NIC_DEV(dev); 1852cb7b6606SZiyang Xuan 1853cb7b6606SZiyang Xuan PMD_DRV_LOG(INFO, "Disable promiscuous, nic_dev: %s, port_id: %d, promisc: %d", 1854cb7b6606SZiyang Xuan nic_dev->proc_dev_name, dev->data->port_id, 1855cb7b6606SZiyang Xuan dev->data->promiscuous); 1856cb7b6606SZiyang Xuan 1857cb7b6606SZiyang Xuan rc = hinic_set_dev_promiscuous(nic_dev, false); 1858cb7b6606SZiyang Xuan if (rc) 1859cb7b6606SZiyang Xuan PMD_DRV_LOG(ERR, "Disable promiscuous failed"); 18609039c812SAndrew Rybchenko 18619039c812SAndrew Rybchenko return rc; 1862cb7b6606SZiyang Xuan } 1863cb7b6606SZiyang Xuan 1864ef6f2f5cSXiaoyun Wang static int hinic_flow_ctrl_get(struct rte_eth_dev *dev, 1865ef6f2f5cSXiaoyun Wang struct rte_eth_fc_conf *fc_conf) 1866ef6f2f5cSXiaoyun Wang { 1867ef6f2f5cSXiaoyun Wang struct hinic_nic_dev *nic_dev = HINIC_ETH_DEV_TO_PRIVATE_NIC_DEV(dev); 1868ef6f2f5cSXiaoyun Wang struct nic_pause_config nic_pause; 1869ef6f2f5cSXiaoyun Wang int err; 1870ef6f2f5cSXiaoyun Wang 1871ef6f2f5cSXiaoyun Wang memset(&nic_pause, 0, sizeof(nic_pause)); 1872ef6f2f5cSXiaoyun Wang 1873ef6f2f5cSXiaoyun Wang err = hinic_get_pause_info(nic_dev->hwdev, &nic_pause); 1874ef6f2f5cSXiaoyun Wang if (err) 1875ef6f2f5cSXiaoyun Wang return err; 1876ef6f2f5cSXiaoyun Wang 1877ef6f2f5cSXiaoyun Wang if (nic_dev->pause_set || !nic_pause.auto_neg) { 1878ef6f2f5cSXiaoyun Wang nic_pause.rx_pause = nic_dev->nic_pause.rx_pause; 1879ef6f2f5cSXiaoyun Wang nic_pause.tx_pause = nic_dev->nic_pause.tx_pause; 1880ef6f2f5cSXiaoyun Wang } 1881ef6f2f5cSXiaoyun Wang 1882ef6f2f5cSXiaoyun Wang fc_conf->autoneg = nic_pause.auto_neg; 1883ef6f2f5cSXiaoyun Wang 1884ef6f2f5cSXiaoyun Wang if (nic_pause.tx_pause && nic_pause.rx_pause) 1885ef6f2f5cSXiaoyun Wang fc_conf->mode = RTE_FC_FULL; 1886ef6f2f5cSXiaoyun Wang else if (nic_pause.tx_pause) 1887ef6f2f5cSXiaoyun Wang fc_conf->mode = RTE_FC_TX_PAUSE; 1888ef6f2f5cSXiaoyun Wang else if (nic_pause.rx_pause) 1889ef6f2f5cSXiaoyun Wang fc_conf->mode = RTE_FC_RX_PAUSE; 1890ef6f2f5cSXiaoyun Wang else 1891ef6f2f5cSXiaoyun Wang fc_conf->mode = RTE_FC_NONE; 1892ef6f2f5cSXiaoyun Wang 1893ef6f2f5cSXiaoyun Wang return 0; 1894ef6f2f5cSXiaoyun Wang } 1895ef6f2f5cSXiaoyun Wang 1896ef6f2f5cSXiaoyun Wang static int hinic_flow_ctrl_set(struct rte_eth_dev *dev, 1897ef6f2f5cSXiaoyun Wang struct rte_eth_fc_conf *fc_conf) 1898ef6f2f5cSXiaoyun Wang { 1899ef6f2f5cSXiaoyun Wang struct hinic_nic_dev *nic_dev = HINIC_ETH_DEV_TO_PRIVATE_NIC_DEV(dev); 1900ef6f2f5cSXiaoyun Wang struct nic_pause_config nic_pause; 1901ef6f2f5cSXiaoyun Wang int err; 1902ef6f2f5cSXiaoyun Wang 1903ef6f2f5cSXiaoyun Wang nic_pause.auto_neg = fc_conf->autoneg; 1904ef6f2f5cSXiaoyun Wang 1905ef6f2f5cSXiaoyun Wang if (((fc_conf->mode & RTE_FC_FULL) == RTE_FC_FULL) || 1906ef6f2f5cSXiaoyun Wang (fc_conf->mode & RTE_FC_TX_PAUSE)) 1907ef6f2f5cSXiaoyun Wang nic_pause.tx_pause = true; 1908ef6f2f5cSXiaoyun Wang else 1909ef6f2f5cSXiaoyun Wang nic_pause.tx_pause = false; 1910ef6f2f5cSXiaoyun Wang 1911ef6f2f5cSXiaoyun Wang if (((fc_conf->mode & RTE_FC_FULL) == RTE_FC_FULL) || 1912ef6f2f5cSXiaoyun Wang (fc_conf->mode & RTE_FC_RX_PAUSE)) 1913ef6f2f5cSXiaoyun Wang nic_pause.rx_pause = true; 1914ef6f2f5cSXiaoyun Wang else 1915ef6f2f5cSXiaoyun Wang nic_pause.rx_pause = false; 1916ef6f2f5cSXiaoyun Wang 1917ef6f2f5cSXiaoyun Wang err = hinic_set_pause_config(nic_dev->hwdev, nic_pause); 1918ef6f2f5cSXiaoyun Wang if (err) 1919ef6f2f5cSXiaoyun Wang return err; 1920ef6f2f5cSXiaoyun Wang 1921ef6f2f5cSXiaoyun Wang nic_dev->pause_set = true; 1922ef6f2f5cSXiaoyun Wang nic_dev->nic_pause.auto_neg = nic_pause.auto_neg; 1923ef6f2f5cSXiaoyun Wang nic_dev->nic_pause.rx_pause = nic_pause.rx_pause; 1924ef6f2f5cSXiaoyun Wang nic_dev->nic_pause.tx_pause = nic_pause.tx_pause; 1925ef6f2f5cSXiaoyun Wang 1926036b61d8SXiaoyun Wang PMD_DRV_LOG(INFO, "Set pause options, tx: %s, rx: %s, auto: %s\n", 1927ef6f2f5cSXiaoyun Wang nic_pause.tx_pause ? "on" : "off", 1928ef6f2f5cSXiaoyun Wang nic_pause.rx_pause ? "on" : "off", 1929ef6f2f5cSXiaoyun Wang nic_pause.auto_neg ? "on" : "off"); 1930ef6f2f5cSXiaoyun Wang 1931ef6f2f5cSXiaoyun Wang return 0; 1932ef6f2f5cSXiaoyun Wang } 1933ef6f2f5cSXiaoyun Wang 1934cb7b6606SZiyang Xuan /** 1935cb7b6606SZiyang Xuan * DPDK callback to update the RSS hash key and RSS hash type. 1936cb7b6606SZiyang Xuan * 1937cb7b6606SZiyang Xuan * @param dev 1938cb7b6606SZiyang Xuan * Pointer to Ethernet device structure. 1939cb7b6606SZiyang Xuan * @param rss_conf 1940cb7b6606SZiyang Xuan * RSS configuration data. 1941cb7b6606SZiyang Xuan * 1942cb7b6606SZiyang Xuan * @return 1943cb7b6606SZiyang Xuan * 0 on success, negative error value otherwise. 1944cb7b6606SZiyang Xuan */ 1945cb7b6606SZiyang Xuan static int hinic_rss_hash_update(struct rte_eth_dev *dev, 1946cb7b6606SZiyang Xuan struct rte_eth_rss_conf *rss_conf) 1947cb7b6606SZiyang Xuan { 1948cb7b6606SZiyang Xuan struct hinic_nic_dev *nic_dev = HINIC_ETH_DEV_TO_PRIVATE_NIC_DEV(dev); 1949cb7b6606SZiyang Xuan u8 tmpl_idx = nic_dev->rss_tmpl_idx; 1950cb7b6606SZiyang Xuan u8 hashkey[HINIC_RSS_KEY_SIZE] = {0}; 1951cb7b6606SZiyang Xuan u8 prio_tc[HINIC_DCB_UP_MAX] = {0}; 1952cb7b6606SZiyang Xuan u64 rss_hf = rss_conf->rss_hf; 1953cb7b6606SZiyang Xuan struct nic_rss_type rss_type = {0}; 1954cb7b6606SZiyang Xuan int err = 0; 1955cb7b6606SZiyang Xuan 1956cb7b6606SZiyang Xuan if (!(nic_dev->flags & ETH_MQ_RX_RSS_FLAG)) { 1957cb7b6606SZiyang Xuan PMD_DRV_LOG(WARNING, "RSS is not enabled"); 1958cb7b6606SZiyang Xuan return HINIC_OK; 1959cb7b6606SZiyang Xuan } 1960cb7b6606SZiyang Xuan 1961cb7b6606SZiyang Xuan if (rss_conf->rss_key_len > HINIC_RSS_KEY_SIZE) { 1962cb7b6606SZiyang Xuan PMD_DRV_LOG(ERR, "Invalid rss key, rss_key_len: %d", 1963cb7b6606SZiyang Xuan rss_conf->rss_key_len); 1964cb7b6606SZiyang Xuan return HINIC_ERROR; 1965cb7b6606SZiyang Xuan } 1966cb7b6606SZiyang Xuan 1967cb7b6606SZiyang Xuan if (rss_conf->rss_key) { 1968cb7b6606SZiyang Xuan memcpy(hashkey, rss_conf->rss_key, rss_conf->rss_key_len); 1969cb7b6606SZiyang Xuan err = hinic_rss_set_template_tbl(nic_dev->hwdev, tmpl_idx, 1970cb7b6606SZiyang Xuan hashkey); 1971cb7b6606SZiyang Xuan if (err) { 1972cb7b6606SZiyang Xuan PMD_DRV_LOG(ERR, "Set rss template table failed"); 1973cb7b6606SZiyang Xuan goto disable_rss; 1974cb7b6606SZiyang Xuan } 1975cb7b6606SZiyang Xuan } 1976cb7b6606SZiyang Xuan 1977cb7b6606SZiyang Xuan rss_type.ipv4 = (rss_hf & (ETH_RSS_IPV4 | ETH_RSS_FRAG_IPV4)) ? 1 : 0; 1978cb7b6606SZiyang Xuan rss_type.tcp_ipv4 = (rss_hf & ETH_RSS_NONFRAG_IPV4_TCP) ? 1 : 0; 1979cb7b6606SZiyang Xuan rss_type.ipv6 = (rss_hf & (ETH_RSS_IPV6 | ETH_RSS_FRAG_IPV6)) ? 1 : 0; 1980cb7b6606SZiyang Xuan rss_type.ipv6_ext = (rss_hf & ETH_RSS_IPV6_EX) ? 1 : 0; 1981cb7b6606SZiyang Xuan rss_type.tcp_ipv6 = (rss_hf & ETH_RSS_NONFRAG_IPV6_TCP) ? 1 : 0; 1982cb7b6606SZiyang Xuan rss_type.tcp_ipv6_ext = (rss_hf & ETH_RSS_IPV6_TCP_EX) ? 1 : 0; 1983cb7b6606SZiyang Xuan rss_type.udp_ipv4 = (rss_hf & ETH_RSS_NONFRAG_IPV4_UDP) ? 1 : 0; 1984cb7b6606SZiyang Xuan rss_type.udp_ipv6 = (rss_hf & ETH_RSS_NONFRAG_IPV6_UDP) ? 1 : 0; 1985cb7b6606SZiyang Xuan 1986cb7b6606SZiyang Xuan err = hinic_set_rss_type(nic_dev->hwdev, tmpl_idx, rss_type); 1987cb7b6606SZiyang Xuan if (err) { 1988cb7b6606SZiyang Xuan PMD_DRV_LOG(ERR, "Set rss type table failed"); 1989cb7b6606SZiyang Xuan goto disable_rss; 1990cb7b6606SZiyang Xuan } 1991cb7b6606SZiyang Xuan 1992cb7b6606SZiyang Xuan return 0; 1993cb7b6606SZiyang Xuan 1994cb7b6606SZiyang Xuan disable_rss: 1995cb7b6606SZiyang Xuan memset(prio_tc, 0, sizeof(prio_tc)); 1996cb7b6606SZiyang Xuan (void)hinic_rss_cfg(nic_dev->hwdev, 0, tmpl_idx, 0, prio_tc); 1997cb7b6606SZiyang Xuan return err; 1998cb7b6606SZiyang Xuan } 1999cb7b6606SZiyang Xuan 2000cb7b6606SZiyang Xuan /** 2001cb7b6606SZiyang Xuan * DPDK callback to get the RSS hash configuration. 2002cb7b6606SZiyang Xuan * 2003cb7b6606SZiyang Xuan * @param dev 2004cb7b6606SZiyang Xuan * Pointer to Ethernet device structure. 2005cb7b6606SZiyang Xuan * @param rss_conf 2006cb7b6606SZiyang Xuan * RSS configuration data. 2007cb7b6606SZiyang Xuan * 2008cb7b6606SZiyang Xuan * @return 2009cb7b6606SZiyang Xuan * 0 on success, negative error value otherwise. 2010cb7b6606SZiyang Xuan */ 2011cb7b6606SZiyang Xuan static int hinic_rss_conf_get(struct rte_eth_dev *dev, 2012cb7b6606SZiyang Xuan struct rte_eth_rss_conf *rss_conf) 2013cb7b6606SZiyang Xuan { 2014cb7b6606SZiyang Xuan struct hinic_nic_dev *nic_dev = HINIC_ETH_DEV_TO_PRIVATE_NIC_DEV(dev); 2015cb7b6606SZiyang Xuan u8 tmpl_idx = nic_dev->rss_tmpl_idx; 2016cb7b6606SZiyang Xuan u8 hashkey[HINIC_RSS_KEY_SIZE] = {0}; 2017cb7b6606SZiyang Xuan struct nic_rss_type rss_type = {0}; 2018cb7b6606SZiyang Xuan int err; 2019cb7b6606SZiyang Xuan 2020cb7b6606SZiyang Xuan if (!(nic_dev->flags & ETH_MQ_RX_RSS_FLAG)) { 2021cb7b6606SZiyang Xuan PMD_DRV_LOG(WARNING, "RSS is not enabled"); 2022cb7b6606SZiyang Xuan return HINIC_ERROR; 2023cb7b6606SZiyang Xuan } 2024cb7b6606SZiyang Xuan 2025cb7b6606SZiyang Xuan err = hinic_rss_get_template_tbl(nic_dev->hwdev, tmpl_idx, hashkey); 2026cb7b6606SZiyang Xuan if (err) 2027cb7b6606SZiyang Xuan return err; 2028cb7b6606SZiyang Xuan 2029cb7b6606SZiyang Xuan if (rss_conf->rss_key && 2030cb7b6606SZiyang Xuan rss_conf->rss_key_len >= HINIC_RSS_KEY_SIZE) { 2031cb7b6606SZiyang Xuan memcpy(rss_conf->rss_key, hashkey, sizeof(hashkey)); 2032cb7b6606SZiyang Xuan rss_conf->rss_key_len = sizeof(hashkey); 2033cb7b6606SZiyang Xuan } 2034cb7b6606SZiyang Xuan 2035cb7b6606SZiyang Xuan err = hinic_get_rss_type(nic_dev->hwdev, tmpl_idx, &rss_type); 2036cb7b6606SZiyang Xuan if (err) 2037cb7b6606SZiyang Xuan return err; 2038cb7b6606SZiyang Xuan 2039cb7b6606SZiyang Xuan rss_conf->rss_hf = 0; 2040cb7b6606SZiyang Xuan rss_conf->rss_hf |= rss_type.ipv4 ? 2041cb7b6606SZiyang Xuan (ETH_RSS_IPV4 | ETH_RSS_FRAG_IPV4) : 0; 2042cb7b6606SZiyang Xuan rss_conf->rss_hf |= rss_type.tcp_ipv4 ? ETH_RSS_NONFRAG_IPV4_TCP : 0; 2043cb7b6606SZiyang Xuan rss_conf->rss_hf |= rss_type.ipv6 ? 2044cb7b6606SZiyang Xuan (ETH_RSS_IPV6 | ETH_RSS_FRAG_IPV6) : 0; 2045cb7b6606SZiyang Xuan rss_conf->rss_hf |= rss_type.ipv6_ext ? ETH_RSS_IPV6_EX : 0; 2046cb7b6606SZiyang Xuan rss_conf->rss_hf |= rss_type.tcp_ipv6 ? ETH_RSS_NONFRAG_IPV6_TCP : 0; 2047cb7b6606SZiyang Xuan rss_conf->rss_hf |= rss_type.tcp_ipv6_ext ? ETH_RSS_IPV6_TCP_EX : 0; 2048cb7b6606SZiyang Xuan rss_conf->rss_hf |= rss_type.udp_ipv4 ? ETH_RSS_NONFRAG_IPV4_UDP : 0; 2049cb7b6606SZiyang Xuan rss_conf->rss_hf |= rss_type.udp_ipv6 ? ETH_RSS_NONFRAG_IPV6_UDP : 0; 2050cb7b6606SZiyang Xuan 2051cb7b6606SZiyang Xuan return HINIC_OK; 2052cb7b6606SZiyang Xuan } 2053cb7b6606SZiyang Xuan 2054cb7b6606SZiyang Xuan /** 2055f372a65fSXiaoyun Wang * DPDK callback to update the RSS redirection table. 2056cb7b6606SZiyang Xuan * 2057cb7b6606SZiyang Xuan * @param dev 2058cb7b6606SZiyang Xuan * Pointer to Ethernet device structure. 2059cb7b6606SZiyang Xuan * @param reta_conf 2060f372a65fSXiaoyun Wang * Pointer to RSS reta configuration data. 2061cb7b6606SZiyang Xuan * @param reta_size 2062cb7b6606SZiyang Xuan * Size of the RETA table. 2063cb7b6606SZiyang Xuan * 2064cb7b6606SZiyang Xuan * @return 2065cb7b6606SZiyang Xuan * 0 on success, negative error value otherwise. 2066cb7b6606SZiyang Xuan */ 2067cb7b6606SZiyang Xuan static int hinic_rss_indirtbl_update(struct rte_eth_dev *dev, 2068cb7b6606SZiyang Xuan struct rte_eth_rss_reta_entry64 *reta_conf, 2069cb7b6606SZiyang Xuan uint16_t reta_size) 2070cb7b6606SZiyang Xuan { 2071cb7b6606SZiyang Xuan struct hinic_nic_dev *nic_dev = HINIC_ETH_DEV_TO_PRIVATE_NIC_DEV(dev); 2072cb7b6606SZiyang Xuan u8 tmpl_idx = nic_dev->rss_tmpl_idx; 2073cb7b6606SZiyang Xuan u8 prio_tc[HINIC_DCB_UP_MAX] = {0}; 2074cb7b6606SZiyang Xuan u32 indirtbl[NIC_RSS_INDIR_SIZE] = {0}; 2075cb7b6606SZiyang Xuan int err = 0; 2076cb7b6606SZiyang Xuan u16 i = 0; 2077cb7b6606SZiyang Xuan u16 idx, shift; 2078cb7b6606SZiyang Xuan 2079cb7b6606SZiyang Xuan if (!(nic_dev->flags & ETH_MQ_RX_RSS_FLAG)) 2080cb7b6606SZiyang Xuan return HINIC_OK; 2081cb7b6606SZiyang Xuan 2082cb7b6606SZiyang Xuan if (reta_size != NIC_RSS_INDIR_SIZE) { 2083cb7b6606SZiyang Xuan PMD_DRV_LOG(ERR, "Invalid reta size, reta_size: %d", reta_size); 2084cb7b6606SZiyang Xuan return HINIC_ERROR; 2085cb7b6606SZiyang Xuan } 2086cb7b6606SZiyang Xuan 2087cb7b6606SZiyang Xuan err = hinic_rss_get_indir_tbl(nic_dev->hwdev, tmpl_idx, indirtbl); 2088cb7b6606SZiyang Xuan if (err) 2089cb7b6606SZiyang Xuan return err; 2090cb7b6606SZiyang Xuan 2091cb7b6606SZiyang Xuan /* update rss indir_tbl */ 2092cb7b6606SZiyang Xuan for (i = 0; i < reta_size; i++) { 2093cb7b6606SZiyang Xuan idx = i / RTE_RETA_GROUP_SIZE; 2094cb7b6606SZiyang Xuan shift = i % RTE_RETA_GROUP_SIZE; 209572babbc0SXiaoyun Wang 209672babbc0SXiaoyun Wang if (reta_conf[idx].reta[shift] >= nic_dev->num_rq) { 209772babbc0SXiaoyun Wang PMD_DRV_LOG(ERR, "Invalid reta entry, indirtbl[%d]: %d " 209872babbc0SXiaoyun Wang "exceeds the maximum rxq num: %d", i, 209972babbc0SXiaoyun Wang reta_conf[idx].reta[shift], nic_dev->num_rq); 210072babbc0SXiaoyun Wang return -EINVAL; 2101cb7b6606SZiyang Xuan } 2102cb7b6606SZiyang Xuan 210372babbc0SXiaoyun Wang if (reta_conf[idx].mask & (1ULL << shift)) 210472babbc0SXiaoyun Wang indirtbl[i] = reta_conf[idx].reta[shift]; 2105cb7b6606SZiyang Xuan } 2106cb7b6606SZiyang Xuan 2107cb7b6606SZiyang Xuan err = hinic_rss_set_indir_tbl(nic_dev->hwdev, tmpl_idx, indirtbl); 2108cb7b6606SZiyang Xuan if (err) 2109cb7b6606SZiyang Xuan goto disable_rss; 2110cb7b6606SZiyang Xuan 2111cb7b6606SZiyang Xuan nic_dev->rss_indir_flag = true; 2112cb7b6606SZiyang Xuan 2113cb7b6606SZiyang Xuan return 0; 2114cb7b6606SZiyang Xuan 2115cb7b6606SZiyang Xuan disable_rss: 2116cb7b6606SZiyang Xuan memset(prio_tc, 0, sizeof(prio_tc)); 2117cb7b6606SZiyang Xuan (void)hinic_rss_cfg(nic_dev->hwdev, 0, tmpl_idx, 0, prio_tc); 2118cb7b6606SZiyang Xuan 2119cb7b6606SZiyang Xuan return HINIC_ERROR; 2120cb7b6606SZiyang Xuan } 2121cb7b6606SZiyang Xuan 2122cb7b6606SZiyang Xuan /** 2123f372a65fSXiaoyun Wang * DPDK callback to get the RSS indirection table. 2124cb7b6606SZiyang Xuan * 2125cb7b6606SZiyang Xuan * @param dev 2126cb7b6606SZiyang Xuan * Pointer to Ethernet device structure. 2127cb7b6606SZiyang Xuan * @param reta_conf 2128f372a65fSXiaoyun Wang * Pointer to RSS reta configuration data. 2129cb7b6606SZiyang Xuan * @param reta_size 2130cb7b6606SZiyang Xuan * Size of the RETA table. 2131cb7b6606SZiyang Xuan * 2132cb7b6606SZiyang Xuan * @return 2133cb7b6606SZiyang Xuan * 0 on success, negative error value otherwise. 2134cb7b6606SZiyang Xuan */ 2135cb7b6606SZiyang Xuan static int hinic_rss_indirtbl_query(struct rte_eth_dev *dev, 2136cb7b6606SZiyang Xuan struct rte_eth_rss_reta_entry64 *reta_conf, 2137cb7b6606SZiyang Xuan uint16_t reta_size) 2138cb7b6606SZiyang Xuan { 2139cb7b6606SZiyang Xuan struct hinic_nic_dev *nic_dev = HINIC_ETH_DEV_TO_PRIVATE_NIC_DEV(dev); 2140cb7b6606SZiyang Xuan u8 tmpl_idx = nic_dev->rss_tmpl_idx; 2141cb7b6606SZiyang Xuan int err = 0; 2142cb7b6606SZiyang Xuan u32 indirtbl[NIC_RSS_INDIR_SIZE] = {0}; 2143cb7b6606SZiyang Xuan u16 idx, shift; 2144cb7b6606SZiyang Xuan u16 i = 0; 2145cb7b6606SZiyang Xuan 2146cb7b6606SZiyang Xuan if (reta_size != NIC_RSS_INDIR_SIZE) { 2147cb7b6606SZiyang Xuan PMD_DRV_LOG(ERR, "Invalid reta size, reta_size: %d", reta_size); 2148cb7b6606SZiyang Xuan return HINIC_ERROR; 2149cb7b6606SZiyang Xuan } 2150cb7b6606SZiyang Xuan 2151cb7b6606SZiyang Xuan err = hinic_rss_get_indir_tbl(nic_dev->hwdev, tmpl_idx, indirtbl); 2152cb7b6606SZiyang Xuan if (err) { 2153cb7b6606SZiyang Xuan PMD_DRV_LOG(ERR, "Get rss indirect table failed, error: %d", 2154cb7b6606SZiyang Xuan err); 2155cb7b6606SZiyang Xuan return err; 2156cb7b6606SZiyang Xuan } 2157cb7b6606SZiyang Xuan 2158cb7b6606SZiyang Xuan for (i = 0; i < reta_size; i++) { 2159cb7b6606SZiyang Xuan idx = i / RTE_RETA_GROUP_SIZE; 2160cb7b6606SZiyang Xuan shift = i % RTE_RETA_GROUP_SIZE; 2161cb7b6606SZiyang Xuan if (reta_conf[idx].mask & (1ULL << shift)) 2162cb7b6606SZiyang Xuan reta_conf[idx].reta[shift] = (uint16_t)indirtbl[i]; 2163cb7b6606SZiyang Xuan } 2164cb7b6606SZiyang Xuan 2165cb7b6606SZiyang Xuan return HINIC_OK; 2166cb7b6606SZiyang Xuan } 2167cb7b6606SZiyang Xuan 2168cb7b6606SZiyang Xuan /** 2169cb7b6606SZiyang Xuan * DPDK callback to get extended device statistics. 2170cb7b6606SZiyang Xuan * 2171cb7b6606SZiyang Xuan * @param dev 2172cb7b6606SZiyang Xuan * Pointer to Ethernet device. 2173cb7b6606SZiyang Xuan * @param xstats 2174cb7b6606SZiyang Xuan * Pointer to rte extended stats table. 2175cb7b6606SZiyang Xuan * @param n 2176cb7b6606SZiyang Xuan * The size of the stats table. 2177cb7b6606SZiyang Xuan * 2178cb7b6606SZiyang Xuan * @return 2179cb7b6606SZiyang Xuan * Number of extended stats on success and stats is filled, 2180cb7b6606SZiyang Xuan * negative error value otherwise. 2181cb7b6606SZiyang Xuan */ 2182cb7b6606SZiyang Xuan static int hinic_dev_xstats_get(struct rte_eth_dev *dev, 2183cb7b6606SZiyang Xuan struct rte_eth_xstat *xstats, 2184cb7b6606SZiyang Xuan unsigned int n) 2185cb7b6606SZiyang Xuan { 2186cb7b6606SZiyang Xuan u16 qid = 0; 2187cb7b6606SZiyang Xuan u32 i; 2188cb7b6606SZiyang Xuan int err, count; 2189cb7b6606SZiyang Xuan struct hinic_nic_dev *nic_dev; 2190cb7b6606SZiyang Xuan struct hinic_phy_port_stats port_stats; 2191cb7b6606SZiyang Xuan struct hinic_vport_stats vport_stats; 2192cb7b6606SZiyang Xuan struct hinic_rxq *rxq = NULL; 2193cb7b6606SZiyang Xuan struct hinic_rxq_stats rxq_stats; 2194cb7b6606SZiyang Xuan struct hinic_txq *txq = NULL; 2195cb7b6606SZiyang Xuan struct hinic_txq_stats txq_stats; 2196cb7b6606SZiyang Xuan 2197cb7b6606SZiyang Xuan nic_dev = HINIC_ETH_DEV_TO_PRIVATE_NIC_DEV(dev); 2198cb7b6606SZiyang Xuan count = hinic_xstats_calc_num(nic_dev); 2199cb7b6606SZiyang Xuan if ((int)n < count) 2200cb7b6606SZiyang Xuan return count; 2201cb7b6606SZiyang Xuan 2202cb7b6606SZiyang Xuan count = 0; 2203cb7b6606SZiyang Xuan 2204cb7b6606SZiyang Xuan /* Get stats from hinic_rxq_stats */ 2205cb7b6606SZiyang Xuan for (qid = 0; qid < nic_dev->num_rq; qid++) { 2206cb7b6606SZiyang Xuan rxq = nic_dev->rxqs[qid]; 2207cb7b6606SZiyang Xuan hinic_rxq_get_stats(rxq, &rxq_stats); 2208cb7b6606SZiyang Xuan 2209cb7b6606SZiyang Xuan for (i = 0; i < HINIC_RXQ_XSTATS_NUM; i++) { 2210cb7b6606SZiyang Xuan xstats[count].value = 2211cb7b6606SZiyang Xuan *(uint64_t *)(((char *)&rxq_stats) + 2212cb7b6606SZiyang Xuan hinic_rxq_stats_strings[i].offset); 2213cb7b6606SZiyang Xuan xstats[count].id = count; 2214cb7b6606SZiyang Xuan count++; 2215cb7b6606SZiyang Xuan } 2216cb7b6606SZiyang Xuan } 2217cb7b6606SZiyang Xuan 2218cb7b6606SZiyang Xuan /* Get stats from hinic_txq_stats */ 2219cb7b6606SZiyang Xuan for (qid = 0; qid < nic_dev->num_sq; qid++) { 2220cb7b6606SZiyang Xuan txq = nic_dev->txqs[qid]; 2221cb7b6606SZiyang Xuan hinic_txq_get_stats(txq, &txq_stats); 2222cb7b6606SZiyang Xuan 2223cb7b6606SZiyang Xuan for (i = 0; i < HINIC_TXQ_XSTATS_NUM; i++) { 2224cb7b6606SZiyang Xuan xstats[count].value = 2225cb7b6606SZiyang Xuan *(uint64_t *)(((char *)&txq_stats) + 2226cb7b6606SZiyang Xuan hinic_txq_stats_strings[i].offset); 2227cb7b6606SZiyang Xuan xstats[count].id = count; 2228cb7b6606SZiyang Xuan count++; 2229cb7b6606SZiyang Xuan } 2230cb7b6606SZiyang Xuan } 2231cb7b6606SZiyang Xuan 2232cb7b6606SZiyang Xuan /* Get stats from hinic_vport_stats */ 2233cb7b6606SZiyang Xuan err = hinic_get_vport_stats(nic_dev->hwdev, &vport_stats); 2234cb7b6606SZiyang Xuan if (err) 2235cb7b6606SZiyang Xuan return err; 2236cb7b6606SZiyang Xuan 2237cb7b6606SZiyang Xuan for (i = 0; i < HINIC_VPORT_XSTATS_NUM; i++) { 2238cb7b6606SZiyang Xuan xstats[count].value = 2239cb7b6606SZiyang Xuan *(uint64_t *)(((char *)&vport_stats) + 2240cb7b6606SZiyang Xuan hinic_vport_stats_strings[i].offset); 2241cb7b6606SZiyang Xuan xstats[count].id = count; 2242cb7b6606SZiyang Xuan count++; 2243cb7b6606SZiyang Xuan } 2244cb7b6606SZiyang Xuan 22456691acefSXiaoyun Wang if (HINIC_IS_VF(nic_dev->hwdev)) 22466691acefSXiaoyun Wang return count; 22476691acefSXiaoyun Wang 2248cb7b6606SZiyang Xuan /* Get stats from hinic_phy_port_stats */ 2249cb7b6606SZiyang Xuan err = hinic_get_phy_port_stats(nic_dev->hwdev, &port_stats); 2250cb7b6606SZiyang Xuan if (err) 2251cb7b6606SZiyang Xuan return err; 2252cb7b6606SZiyang Xuan 2253cb7b6606SZiyang Xuan for (i = 0; i < HINIC_PHYPORT_XSTATS_NUM; i++) { 2254cb7b6606SZiyang Xuan xstats[count].value = *(uint64_t *)(((char *)&port_stats) + 2255cb7b6606SZiyang Xuan hinic_phyport_stats_strings[i].offset); 2256cb7b6606SZiyang Xuan xstats[count].id = count; 2257cb7b6606SZiyang Xuan count++; 2258cb7b6606SZiyang Xuan } 2259cb7b6606SZiyang Xuan 2260cb7b6606SZiyang Xuan return count; 2261cb7b6606SZiyang Xuan } 2262cb7b6606SZiyang Xuan 2263483b4817SXiaoyun Wang static void hinic_rxq_info_get(struct rte_eth_dev *dev, uint16_t queue_id, 2264483b4817SXiaoyun Wang struct rte_eth_rxq_info *qinfo) 2265483b4817SXiaoyun Wang { 2266483b4817SXiaoyun Wang struct hinic_rxq *rxq = dev->data->rx_queues[queue_id]; 2267483b4817SXiaoyun Wang 2268483b4817SXiaoyun Wang qinfo->mp = rxq->mb_pool; 2269483b4817SXiaoyun Wang qinfo->nb_desc = rxq->q_depth; 2270483b4817SXiaoyun Wang } 2271483b4817SXiaoyun Wang 2272483b4817SXiaoyun Wang static void hinic_txq_info_get(struct rte_eth_dev *dev, uint16_t queue_id, 2273483b4817SXiaoyun Wang struct rte_eth_txq_info *qinfo) 2274483b4817SXiaoyun Wang { 2275483b4817SXiaoyun Wang struct hinic_txq *txq = dev->data->tx_queues[queue_id]; 2276483b4817SXiaoyun Wang 2277483b4817SXiaoyun Wang qinfo->nb_desc = txq->q_depth; 2278483b4817SXiaoyun Wang } 2279483b4817SXiaoyun Wang 2280cb7b6606SZiyang Xuan /** 2281cb7b6606SZiyang Xuan * DPDK callback to retrieve names of extended device statistics 2282cb7b6606SZiyang Xuan * 2283cb7b6606SZiyang Xuan * @param dev 2284cb7b6606SZiyang Xuan * Pointer to Ethernet device structure. 2285cb7b6606SZiyang Xuan * @param xstats_names 2286cb7b6606SZiyang Xuan * Buffer to insert names into. 2287cb7b6606SZiyang Xuan * 2288cb7b6606SZiyang Xuan * @return 2289cb7b6606SZiyang Xuan * Number of xstats names. 2290cb7b6606SZiyang Xuan */ 2291cb7b6606SZiyang Xuan static int hinic_dev_xstats_get_names(struct rte_eth_dev *dev, 2292cb7b6606SZiyang Xuan struct rte_eth_xstat_name *xstats_names, 2293cb7b6606SZiyang Xuan __rte_unused unsigned int limit) 2294cb7b6606SZiyang Xuan { 2295cb7b6606SZiyang Xuan struct hinic_nic_dev *nic_dev = HINIC_ETH_DEV_TO_PRIVATE_NIC_DEV(dev); 2296cb7b6606SZiyang Xuan int count = 0; 2297cb7b6606SZiyang Xuan u16 i = 0, q_num; 2298cb7b6606SZiyang Xuan 2299cb7b6606SZiyang Xuan if (xstats_names == NULL) 2300cb7b6606SZiyang Xuan return hinic_xstats_calc_num(nic_dev); 2301cb7b6606SZiyang Xuan 2302cb7b6606SZiyang Xuan /* get pmd rxq stats */ 2303cb7b6606SZiyang Xuan for (q_num = 0; q_num < nic_dev->num_rq; q_num++) { 2304cb7b6606SZiyang Xuan for (i = 0; i < HINIC_RXQ_XSTATS_NUM; i++) { 2305cb7b6606SZiyang Xuan snprintf(xstats_names[count].name, 2306cb7b6606SZiyang Xuan sizeof(xstats_names[count].name), 2307cb7b6606SZiyang Xuan "rxq%d_%s_pmd", 2308cb7b6606SZiyang Xuan q_num, hinic_rxq_stats_strings[i].name); 2309cb7b6606SZiyang Xuan count++; 2310cb7b6606SZiyang Xuan } 2311cb7b6606SZiyang Xuan } 2312cb7b6606SZiyang Xuan 2313cb7b6606SZiyang Xuan /* get pmd txq stats */ 2314cb7b6606SZiyang Xuan for (q_num = 0; q_num < nic_dev->num_sq; q_num++) { 2315cb7b6606SZiyang Xuan for (i = 0; i < HINIC_TXQ_XSTATS_NUM; i++) { 2316cb7b6606SZiyang Xuan snprintf(xstats_names[count].name, 2317cb7b6606SZiyang Xuan sizeof(xstats_names[count].name), 2318cb7b6606SZiyang Xuan "txq%d_%s_pmd", 2319cb7b6606SZiyang Xuan q_num, hinic_txq_stats_strings[i].name); 2320cb7b6606SZiyang Xuan count++; 2321cb7b6606SZiyang Xuan } 2322cb7b6606SZiyang Xuan } 2323cb7b6606SZiyang Xuan 2324cb7b6606SZiyang Xuan /* get vport stats */ 2325cb7b6606SZiyang Xuan for (i = 0; i < HINIC_VPORT_XSTATS_NUM; i++) { 2326cb7b6606SZiyang Xuan snprintf(xstats_names[count].name, 2327cb7b6606SZiyang Xuan sizeof(xstats_names[count].name), 2328f372a65fSXiaoyun Wang "%s", hinic_vport_stats_strings[i].name); 2329cb7b6606SZiyang Xuan count++; 2330cb7b6606SZiyang Xuan } 2331cb7b6606SZiyang Xuan 23326691acefSXiaoyun Wang if (HINIC_IS_VF(nic_dev->hwdev)) 23336691acefSXiaoyun Wang return count; 23346691acefSXiaoyun Wang 2335cb7b6606SZiyang Xuan /* get phy port stats */ 2336cb7b6606SZiyang Xuan for (i = 0; i < HINIC_PHYPORT_XSTATS_NUM; i++) { 2337cb7b6606SZiyang Xuan snprintf(xstats_names[count].name, 2338cb7b6606SZiyang Xuan sizeof(xstats_names[count].name), 2339f372a65fSXiaoyun Wang "%s", hinic_phyport_stats_strings[i].name); 2340cb7b6606SZiyang Xuan count++; 2341cb7b6606SZiyang Xuan } 2342cb7b6606SZiyang Xuan 2343cb7b6606SZiyang Xuan return count; 2344cb7b6606SZiyang Xuan } 2345f372a65fSXiaoyun Wang 234600499a22SXiaoyun Wang /** 234700499a22SXiaoyun Wang * DPDK callback to set mac address 234800499a22SXiaoyun Wang * 234900499a22SXiaoyun Wang * @param dev 235000499a22SXiaoyun Wang * Pointer to Ethernet device structure. 235100499a22SXiaoyun Wang * @param addr 235200499a22SXiaoyun Wang * Pointer to mac address 235300499a22SXiaoyun Wang * @return 235400499a22SXiaoyun Wang * 0 on success, negative error value otherwise. 235500499a22SXiaoyun Wang */ 235600499a22SXiaoyun Wang static int hinic_set_mac_addr(struct rte_eth_dev *dev, 235700499a22SXiaoyun Wang struct rte_ether_addr *addr) 235800499a22SXiaoyun Wang { 235900499a22SXiaoyun Wang struct hinic_nic_dev *nic_dev = HINIC_ETH_DEV_TO_PRIVATE_NIC_DEV(dev); 236000499a22SXiaoyun Wang u16 func_id; 236100499a22SXiaoyun Wang int err; 236200499a22SXiaoyun Wang 236300499a22SXiaoyun Wang func_id = hinic_global_func_id(nic_dev->hwdev); 236400499a22SXiaoyun Wang err = hinic_update_mac(nic_dev->hwdev, nic_dev->default_addr.addr_bytes, 236500499a22SXiaoyun Wang addr->addr_bytes, 0, func_id); 236600499a22SXiaoyun Wang if (err) 236700499a22SXiaoyun Wang return err; 236800499a22SXiaoyun Wang 236900499a22SXiaoyun Wang rte_ether_addr_copy(addr, &nic_dev->default_addr); 237000499a22SXiaoyun Wang 23714f1af3cbSXiaoyun Wang PMD_DRV_LOG(INFO, "Set new mac address %02x:%02x:%02x:%02x:%02x:%02x", 237200499a22SXiaoyun Wang addr->addr_bytes[0], addr->addr_bytes[1], 237300499a22SXiaoyun Wang addr->addr_bytes[2], addr->addr_bytes[3], 237400499a22SXiaoyun Wang addr->addr_bytes[4], addr->addr_bytes[5]); 237500499a22SXiaoyun Wang 237600499a22SXiaoyun Wang return 0; 237700499a22SXiaoyun Wang } 237800499a22SXiaoyun Wang 237900499a22SXiaoyun Wang /** 238000499a22SXiaoyun Wang * DPDK callback to remove a MAC address. 238100499a22SXiaoyun Wang * 238200499a22SXiaoyun Wang * @param dev 238300499a22SXiaoyun Wang * Pointer to Ethernet device structure. 238400499a22SXiaoyun Wang * @param index 23854f1af3cbSXiaoyun Wang * MAC address index, should less than 128. 238600499a22SXiaoyun Wang */ 238700499a22SXiaoyun Wang static void hinic_mac_addr_remove(struct rte_eth_dev *dev, uint32_t index) 238800499a22SXiaoyun Wang { 238900499a22SXiaoyun Wang struct hinic_nic_dev *nic_dev = HINIC_ETH_DEV_TO_PRIVATE_NIC_DEV(dev); 239000499a22SXiaoyun Wang u16 func_id; 239100499a22SXiaoyun Wang int ret; 239200499a22SXiaoyun Wang 239300499a22SXiaoyun Wang if (index >= HINIC_MAX_UC_MAC_ADDRS) { 239400499a22SXiaoyun Wang PMD_DRV_LOG(INFO, "Remove mac index(%u) is out of range", 239500499a22SXiaoyun Wang index); 239600499a22SXiaoyun Wang return; 239700499a22SXiaoyun Wang } 239800499a22SXiaoyun Wang 239900499a22SXiaoyun Wang func_id = hinic_global_func_id(nic_dev->hwdev); 240000499a22SXiaoyun Wang ret = hinic_del_mac(nic_dev->hwdev, 240100499a22SXiaoyun Wang dev->data->mac_addrs[index].addr_bytes, 0, func_id); 240200499a22SXiaoyun Wang if (ret) 240300499a22SXiaoyun Wang return; 240400499a22SXiaoyun Wang 240500499a22SXiaoyun Wang memset(&dev->data->mac_addrs[index], 0, sizeof(struct rte_ether_addr)); 240600499a22SXiaoyun Wang } 240700499a22SXiaoyun Wang 240800499a22SXiaoyun Wang /** 240900499a22SXiaoyun Wang * DPDK callback to add a MAC address. 241000499a22SXiaoyun Wang * 241100499a22SXiaoyun Wang * @param dev 241200499a22SXiaoyun Wang * Pointer to Ethernet device structure. 241300499a22SXiaoyun Wang * @param mac_addr 24144f1af3cbSXiaoyun Wang * Pointer to MAC address 241500499a22SXiaoyun Wang * @param index 24164f1af3cbSXiaoyun Wang * MAC address index, should less than 128. 241700499a22SXiaoyun Wang * @param vmdq 24184f1af3cbSXiaoyun Wang * VMDq pool index(not used). 241900499a22SXiaoyun Wang * 242000499a22SXiaoyun Wang * @return 24214f1af3cbSXiaoyun Wang * 0 on success, negative error value otherwise. 242200499a22SXiaoyun Wang */ 242300499a22SXiaoyun Wang static int hinic_mac_addr_add(struct rte_eth_dev *dev, 242400499a22SXiaoyun Wang struct rte_ether_addr *mac_addr, uint32_t index, 242500499a22SXiaoyun Wang __rte_unused uint32_t vmdq) 242600499a22SXiaoyun Wang { 242700499a22SXiaoyun Wang struct hinic_nic_dev *nic_dev = HINIC_ETH_DEV_TO_PRIVATE_NIC_DEV(dev); 242800499a22SXiaoyun Wang unsigned int i; 242900499a22SXiaoyun Wang u16 func_id; 243000499a22SXiaoyun Wang int ret; 243100499a22SXiaoyun Wang 243200499a22SXiaoyun Wang if (index >= HINIC_MAX_UC_MAC_ADDRS) { 24334f1af3cbSXiaoyun Wang PMD_DRV_LOG(INFO, "Add mac index(%u) is out of range", index); 243400499a22SXiaoyun Wang return -EINVAL; 243500499a22SXiaoyun Wang } 243600499a22SXiaoyun Wang 243700499a22SXiaoyun Wang /* First, make sure this address isn't already configured. */ 243800499a22SXiaoyun Wang for (i = 0; (i != HINIC_MAX_UC_MAC_ADDRS); ++i) { 243900499a22SXiaoyun Wang /* Skip this index, it's going to be reconfigured. */ 244000499a22SXiaoyun Wang if (i == index) 244100499a22SXiaoyun Wang continue; 244200499a22SXiaoyun Wang 244300499a22SXiaoyun Wang if (memcmp(&dev->data->mac_addrs[i], 244400499a22SXiaoyun Wang mac_addr, sizeof(*mac_addr))) 244500499a22SXiaoyun Wang continue; 244600499a22SXiaoyun Wang 244700499a22SXiaoyun Wang PMD_DRV_LOG(INFO, "MAC address already configured"); 244800499a22SXiaoyun Wang return -EADDRINUSE; 244900499a22SXiaoyun Wang } 245000499a22SXiaoyun Wang 245100499a22SXiaoyun Wang func_id = hinic_global_func_id(nic_dev->hwdev); 245200499a22SXiaoyun Wang ret = hinic_set_mac(nic_dev->hwdev, mac_addr->addr_bytes, 0, func_id); 245300499a22SXiaoyun Wang if (ret) 245400499a22SXiaoyun Wang return ret; 245500499a22SXiaoyun Wang 245600499a22SXiaoyun Wang dev->data->mac_addrs[index] = *mac_addr; 245700499a22SXiaoyun Wang return 0; 245800499a22SXiaoyun Wang } 245900499a22SXiaoyun Wang 246000499a22SXiaoyun Wang /** 246100499a22SXiaoyun Wang * DPDK callback to set multicast mac address 246200499a22SXiaoyun Wang * 246300499a22SXiaoyun Wang * @param dev 246400499a22SXiaoyun Wang * Pointer to Ethernet device structure. 246500499a22SXiaoyun Wang * @param mc_addr_set 246600499a22SXiaoyun Wang * Pointer to multicast mac address 246700499a22SXiaoyun Wang * @param nb_mc_addr 246800499a22SXiaoyun Wang * mc addr count 246900499a22SXiaoyun Wang * @return 247000499a22SXiaoyun Wang * 0 on success, negative error value otherwise. 247100499a22SXiaoyun Wang */ 247200499a22SXiaoyun Wang static int hinic_set_mc_addr_list(struct rte_eth_dev *dev, 247300499a22SXiaoyun Wang struct rte_ether_addr *mc_addr_set, 247400499a22SXiaoyun Wang uint32_t nb_mc_addr) 247500499a22SXiaoyun Wang { 247600499a22SXiaoyun Wang struct hinic_nic_dev *nic_dev = HINIC_ETH_DEV_TO_PRIVATE_NIC_DEV(dev); 247700499a22SXiaoyun Wang u16 func_id; 247800499a22SXiaoyun Wang int ret; 247900499a22SXiaoyun Wang u32 i; 248000499a22SXiaoyun Wang 248100499a22SXiaoyun Wang func_id = hinic_global_func_id(nic_dev->hwdev); 248200499a22SXiaoyun Wang 248300499a22SXiaoyun Wang /* delete old multi_cast addrs firstly */ 248400499a22SXiaoyun Wang hinic_delete_mc_addr_list(nic_dev); 248500499a22SXiaoyun Wang 248600499a22SXiaoyun Wang if (nb_mc_addr > HINIC_MAX_MC_MAC_ADDRS) 248700499a22SXiaoyun Wang goto allmulti; 248800499a22SXiaoyun Wang 248900499a22SXiaoyun Wang for (i = 0; i < nb_mc_addr; i++) { 249000499a22SXiaoyun Wang ret = hinic_set_mac(nic_dev->hwdev, mc_addr_set[i].addr_bytes, 249100499a22SXiaoyun Wang 0, func_id); 249200499a22SXiaoyun Wang /* if add mc addr failed, set all multi_cast */ 249300499a22SXiaoyun Wang if (ret) { 249400499a22SXiaoyun Wang hinic_delete_mc_addr_list(nic_dev); 249500499a22SXiaoyun Wang goto allmulti; 249600499a22SXiaoyun Wang } 249700499a22SXiaoyun Wang 249800499a22SXiaoyun Wang rte_ether_addr_copy(&mc_addr_set[i], &nic_dev->mc_list[i]); 249900499a22SXiaoyun Wang } 250000499a22SXiaoyun Wang 250100499a22SXiaoyun Wang return 0; 250200499a22SXiaoyun Wang 250300499a22SXiaoyun Wang allmulti: 250400499a22SXiaoyun Wang hinic_dev_allmulticast_enable(dev); 250500499a22SXiaoyun Wang 250600499a22SXiaoyun Wang return 0; 250700499a22SXiaoyun Wang } 2508cb7b6606SZiyang Xuan 250973122b52SXiaoyun Wang /** 2510fb7ad441SThomas Monjalon * DPDK callback to get flow operations 251173122b52SXiaoyun Wang * 251273122b52SXiaoyun Wang * @param dev 251373122b52SXiaoyun Wang * Pointer to Ethernet device structure. 2514fb7ad441SThomas Monjalon * @param ops 251573122b52SXiaoyun Wang * Pointer to operation-specific structure. 251673122b52SXiaoyun Wang * 251773122b52SXiaoyun Wang * @return 2518f372a65fSXiaoyun Wang * 0 on success, negative error value otherwise. 251973122b52SXiaoyun Wang */ 2520fb7ad441SThomas Monjalon static int hinic_dev_flow_ops_get(struct rte_eth_dev *dev __rte_unused, 2521fb7ad441SThomas Monjalon const struct rte_flow_ops **ops) 252273122b52SXiaoyun Wang { 2523fb7ad441SThomas Monjalon *ops = &hinic_flow_ops; 252473122b52SXiaoyun Wang return 0; 252573122b52SXiaoyun Wang } 252673122b52SXiaoyun Wang 252764727024SZiyang Xuan static int hinic_set_default_pause_feature(struct hinic_nic_dev *nic_dev) 252864727024SZiyang Xuan { 252964727024SZiyang Xuan struct nic_pause_config pause_config = {0}; 2530ef6f2f5cSXiaoyun Wang int err; 253164727024SZiyang Xuan 253264727024SZiyang Xuan pause_config.auto_neg = 0; 253364727024SZiyang Xuan pause_config.rx_pause = HINIC_DEFAUT_PAUSE_CONFIG; 253464727024SZiyang Xuan pause_config.tx_pause = HINIC_DEFAUT_PAUSE_CONFIG; 253564727024SZiyang Xuan 2536ef6f2f5cSXiaoyun Wang err = hinic_set_pause_config(nic_dev->hwdev, pause_config); 2537ef6f2f5cSXiaoyun Wang if (err) 2538ef6f2f5cSXiaoyun Wang return err; 2539ef6f2f5cSXiaoyun Wang 2540ef6f2f5cSXiaoyun Wang nic_dev->pause_set = true; 2541ef6f2f5cSXiaoyun Wang nic_dev->nic_pause.auto_neg = pause_config.auto_neg; 2542ef6f2f5cSXiaoyun Wang nic_dev->nic_pause.rx_pause = pause_config.rx_pause; 2543ef6f2f5cSXiaoyun Wang nic_dev->nic_pause.tx_pause = pause_config.tx_pause; 2544ef6f2f5cSXiaoyun Wang 2545ef6f2f5cSXiaoyun Wang return 0; 254664727024SZiyang Xuan } 254764727024SZiyang Xuan 254864727024SZiyang Xuan static int hinic_set_default_dcb_feature(struct hinic_nic_dev *nic_dev) 254964727024SZiyang Xuan { 255064727024SZiyang Xuan u8 up_tc[HINIC_DCB_UP_MAX] = {0}; 255164727024SZiyang Xuan u8 up_pgid[HINIC_DCB_UP_MAX] = {0}; 255264727024SZiyang Xuan u8 up_bw[HINIC_DCB_UP_MAX] = {0}; 255364727024SZiyang Xuan u8 pg_bw[HINIC_DCB_UP_MAX] = {0}; 255464727024SZiyang Xuan u8 up_strict[HINIC_DCB_UP_MAX] = {0}; 255564727024SZiyang Xuan int i = 0; 255664727024SZiyang Xuan 255764727024SZiyang Xuan pg_bw[0] = 100; 255864727024SZiyang Xuan for (i = 0; i < HINIC_DCB_UP_MAX; i++) 255964727024SZiyang Xuan up_bw[i] = 100; 256064727024SZiyang Xuan 256164727024SZiyang Xuan return hinic_dcb_set_ets(nic_dev->hwdev, up_tc, pg_bw, 256264727024SZiyang Xuan up_pgid, up_bw, up_strict); 256364727024SZiyang Xuan } 256464727024SZiyang Xuan 2565d4002360SXiaoyun Wang static int hinic_pf_get_default_cos(struct hinic_hwdev *hwdev, u8 *cos_id) 2566d4002360SXiaoyun Wang { 2567d4002360SXiaoyun Wang u8 default_cos = 0; 2568d4002360SXiaoyun Wang u8 valid_cos_bitmap; 2569d4002360SXiaoyun Wang u8 i; 2570d4002360SXiaoyun Wang 2571d4002360SXiaoyun Wang valid_cos_bitmap = hwdev->cfg_mgmt->svc_cap.valid_cos_bitmap; 2572d4002360SXiaoyun Wang if (!valid_cos_bitmap) { 2573d4002360SXiaoyun Wang PMD_DRV_LOG(ERR, "PF has none cos to support\n"); 2574d4002360SXiaoyun Wang return -EFAULT; 2575d4002360SXiaoyun Wang } 2576d4002360SXiaoyun Wang 2577d4002360SXiaoyun Wang for (i = 0; i < NR_MAX_COS; i++) { 2578d4002360SXiaoyun Wang if (valid_cos_bitmap & BIT(i)) 2579d4002360SXiaoyun Wang default_cos = i; /* Find max cos id as default cos */ 2580d4002360SXiaoyun Wang } 2581d4002360SXiaoyun Wang 2582d4002360SXiaoyun Wang *cos_id = default_cos; 2583d4002360SXiaoyun Wang 2584d4002360SXiaoyun Wang return 0; 2585d4002360SXiaoyun Wang } 2586d4002360SXiaoyun Wang 25876691acefSXiaoyun Wang static int hinic_init_default_cos(struct hinic_nic_dev *nic_dev) 258864727024SZiyang Xuan { 25896691acefSXiaoyun Wang u8 cos_id = 0; 25906691acefSXiaoyun Wang int err; 25916691acefSXiaoyun Wang 25926691acefSXiaoyun Wang if (!HINIC_IS_VF(nic_dev->hwdev)) { 2593d4002360SXiaoyun Wang err = hinic_pf_get_default_cos(nic_dev->hwdev, &cos_id); 2594d4002360SXiaoyun Wang if (err) { 2595d4002360SXiaoyun Wang PMD_DRV_LOG(ERR, "Get PF default cos failed, err: %d", 2596d4002360SXiaoyun Wang err); 2597d4002360SXiaoyun Wang return HINIC_ERROR; 2598d4002360SXiaoyun Wang } 25996691acefSXiaoyun Wang } else { 26006691acefSXiaoyun Wang err = hinic_vf_get_default_cos(nic_dev->hwdev, &cos_id); 26016691acefSXiaoyun Wang if (err) { 26026691acefSXiaoyun Wang PMD_DRV_LOG(ERR, "Get VF default cos failed, err: %d", 26036691acefSXiaoyun Wang err); 26046691acefSXiaoyun Wang return HINIC_ERROR; 26056691acefSXiaoyun Wang } 2606d4002360SXiaoyun Wang } 26076691acefSXiaoyun Wang 26086691acefSXiaoyun Wang nic_dev->default_cos = cos_id; 2609d4002360SXiaoyun Wang 2610d4002360SXiaoyun Wang PMD_DRV_LOG(INFO, "Default cos %d", nic_dev->default_cos); 26116691acefSXiaoyun Wang 26126691acefSXiaoyun Wang return 0; 261364727024SZiyang Xuan } 261464727024SZiyang Xuan 261564727024SZiyang Xuan static int hinic_set_default_hw_feature(struct hinic_nic_dev *nic_dev) 261664727024SZiyang Xuan { 261764727024SZiyang Xuan int err; 261864727024SZiyang Xuan 26196691acefSXiaoyun Wang err = hinic_init_default_cos(nic_dev); 26206691acefSXiaoyun Wang if (err) 26216691acefSXiaoyun Wang return err; 26226691acefSXiaoyun Wang 26236691acefSXiaoyun Wang if (hinic_func_type(nic_dev->hwdev) == TYPE_VF) 26246691acefSXiaoyun Wang return 0; 262564727024SZiyang Xuan 262664727024SZiyang Xuan /* Restore DCB configure to default status */ 262764727024SZiyang Xuan err = hinic_set_default_dcb_feature(nic_dev); 262864727024SZiyang Xuan if (err) 262964727024SZiyang Xuan return err; 263064727024SZiyang Xuan 263164727024SZiyang Xuan /* Set pause enable, and up will disable pfc. */ 263264727024SZiyang Xuan err = hinic_set_default_pause_feature(nic_dev); 263364727024SZiyang Xuan if (err) 263464727024SZiyang Xuan return err; 263564727024SZiyang Xuan 263664727024SZiyang Xuan err = hinic_reset_port_link_cfg(nic_dev->hwdev); 263764727024SZiyang Xuan if (err) 263864727024SZiyang Xuan return err; 263964727024SZiyang Xuan 264064727024SZiyang Xuan err = hinic_set_link_status_follow(nic_dev->hwdev, 264164727024SZiyang Xuan HINIC_LINK_FOLLOW_PORT); 264264727024SZiyang Xuan if (err == HINIC_MGMT_CMD_UNSUPPORTED) 264364727024SZiyang Xuan PMD_DRV_LOG(WARNING, "Don't support to set link status follow phy port status"); 264464727024SZiyang Xuan else if (err) 264564727024SZiyang Xuan return err; 264664727024SZiyang Xuan 264764727024SZiyang Xuan return hinic_set_anti_attack(nic_dev->hwdev, true); 264864727024SZiyang Xuan } 264964727024SZiyang Xuan 265064727024SZiyang Xuan static int32_t hinic_card_workmode_check(struct hinic_nic_dev *nic_dev) 265164727024SZiyang Xuan { 265264727024SZiyang Xuan struct hinic_board_info info = { 0 }; 265364727024SZiyang Xuan int rc; 265464727024SZiyang Xuan 26556691acefSXiaoyun Wang if (hinic_func_type(nic_dev->hwdev) == TYPE_VF) 26566691acefSXiaoyun Wang return 0; 26576691acefSXiaoyun Wang 265864727024SZiyang Xuan rc = hinic_get_board_info(nic_dev->hwdev, &info); 265964727024SZiyang Xuan if (rc) 266064727024SZiyang Xuan return rc; 266164727024SZiyang Xuan 266264727024SZiyang Xuan return (info.service_mode == HINIC_SERVICE_MODE_NIC ? HINIC_OK : 266364727024SZiyang Xuan HINIC_ERROR); 266464727024SZiyang Xuan } 266564727024SZiyang Xuan 266664727024SZiyang Xuan static int hinic_copy_mempool_init(struct hinic_nic_dev *nic_dev) 266764727024SZiyang Xuan { 266864727024SZiyang Xuan nic_dev->cpy_mpool = rte_mempool_lookup(nic_dev->proc_dev_name); 266964727024SZiyang Xuan if (nic_dev->cpy_mpool == NULL) { 267064727024SZiyang Xuan nic_dev->cpy_mpool = 267164727024SZiyang Xuan rte_pktmbuf_pool_create(nic_dev->proc_dev_name, 267264727024SZiyang Xuan HINIC_COPY_MEMPOOL_DEPTH, 26736691acefSXiaoyun Wang 0, 0, 267464727024SZiyang Xuan HINIC_COPY_MBUF_SIZE, 267564727024SZiyang Xuan rte_socket_id()); 267664727024SZiyang Xuan if (!nic_dev->cpy_mpool) { 267764727024SZiyang Xuan PMD_DRV_LOG(ERR, "Create copy mempool failed, errno: %d, dev_name: %s", 267864727024SZiyang Xuan rte_errno, nic_dev->proc_dev_name); 267964727024SZiyang Xuan return -ENOMEM; 268064727024SZiyang Xuan } 268164727024SZiyang Xuan } 268264727024SZiyang Xuan 268364727024SZiyang Xuan return 0; 268464727024SZiyang Xuan } 268564727024SZiyang Xuan 268664727024SZiyang Xuan static void hinic_copy_mempool_uninit(struct hinic_nic_dev *nic_dev) 268764727024SZiyang Xuan { 268864727024SZiyang Xuan if (nic_dev->cpy_mpool != NULL) 268964727024SZiyang Xuan rte_mempool_free(nic_dev->cpy_mpool); 269064727024SZiyang Xuan } 269164727024SZiyang Xuan 269264727024SZiyang Xuan static int hinic_init_sw_rxtxqs(struct hinic_nic_dev *nic_dev) 269364727024SZiyang Xuan { 269464727024SZiyang Xuan u32 txq_size; 269564727024SZiyang Xuan u32 rxq_size; 269664727024SZiyang Xuan 269764727024SZiyang Xuan /* allocate software txq array */ 269864727024SZiyang Xuan txq_size = nic_dev->nic_cap.max_sqs * sizeof(*nic_dev->txqs); 269964727024SZiyang Xuan nic_dev->txqs = kzalloc_aligned(txq_size, GFP_KERNEL); 270064727024SZiyang Xuan if (!nic_dev->txqs) { 270164727024SZiyang Xuan PMD_DRV_LOG(ERR, "Allocate txqs failed"); 270264727024SZiyang Xuan return -ENOMEM; 270364727024SZiyang Xuan } 270464727024SZiyang Xuan 270564727024SZiyang Xuan /* allocate software rxq array */ 270664727024SZiyang Xuan rxq_size = nic_dev->nic_cap.max_rqs * sizeof(*nic_dev->rxqs); 270764727024SZiyang Xuan nic_dev->rxqs = kzalloc_aligned(rxq_size, GFP_KERNEL); 270864727024SZiyang Xuan if (!nic_dev->rxqs) { 270964727024SZiyang Xuan /* free txqs */ 271064727024SZiyang Xuan kfree(nic_dev->txqs); 271164727024SZiyang Xuan nic_dev->txqs = NULL; 271264727024SZiyang Xuan 271364727024SZiyang Xuan PMD_DRV_LOG(ERR, "Allocate rxqs failed"); 271464727024SZiyang Xuan return -ENOMEM; 271564727024SZiyang Xuan } 271664727024SZiyang Xuan 271764727024SZiyang Xuan return HINIC_OK; 271864727024SZiyang Xuan } 271964727024SZiyang Xuan 272064727024SZiyang Xuan static void hinic_deinit_sw_rxtxqs(struct hinic_nic_dev *nic_dev) 272164727024SZiyang Xuan { 272264727024SZiyang Xuan kfree(nic_dev->txqs); 272364727024SZiyang Xuan nic_dev->txqs = NULL; 272464727024SZiyang Xuan 272564727024SZiyang Xuan kfree(nic_dev->rxqs); 272664727024SZiyang Xuan nic_dev->rxqs = NULL; 272764727024SZiyang Xuan } 272864727024SZiyang Xuan 272964727024SZiyang Xuan static int hinic_nic_dev_create(struct rte_eth_dev *eth_dev) 273064727024SZiyang Xuan { 273164727024SZiyang Xuan struct hinic_nic_dev *nic_dev = 273264727024SZiyang Xuan HINIC_ETH_DEV_TO_PRIVATE_NIC_DEV(eth_dev); 273364727024SZiyang Xuan int rc; 273464727024SZiyang Xuan 273564727024SZiyang Xuan nic_dev->hwdev = rte_zmalloc("hinic_hwdev", sizeof(*nic_dev->hwdev), 273664727024SZiyang Xuan RTE_CACHE_LINE_SIZE); 273764727024SZiyang Xuan if (!nic_dev->hwdev) { 273864727024SZiyang Xuan PMD_DRV_LOG(ERR, "Allocate hinic hwdev memory failed, dev_name: %s", 273964727024SZiyang Xuan eth_dev->data->name); 274064727024SZiyang Xuan return -ENOMEM; 274164727024SZiyang Xuan } 274264727024SZiyang Xuan nic_dev->hwdev->pcidev_hdl = RTE_ETH_DEV_TO_PCI(eth_dev); 274364727024SZiyang Xuan 274464727024SZiyang Xuan /* init osdep*/ 274564727024SZiyang Xuan rc = hinic_osdep_init(nic_dev->hwdev); 274664727024SZiyang Xuan if (rc) { 274764727024SZiyang Xuan PMD_DRV_LOG(ERR, "Initialize os_dep failed, dev_name: %s", 274864727024SZiyang Xuan eth_dev->data->name); 274964727024SZiyang Xuan goto init_osdep_fail; 275064727024SZiyang Xuan } 275164727024SZiyang Xuan 275264727024SZiyang Xuan /* init_hwif */ 275364727024SZiyang Xuan rc = hinic_hwif_res_init(nic_dev->hwdev); 275464727024SZiyang Xuan if (rc) { 275564727024SZiyang Xuan PMD_DRV_LOG(ERR, "Initialize hwif failed, dev_name: %s", 275664727024SZiyang Xuan eth_dev->data->name); 275764727024SZiyang Xuan goto init_hwif_fail; 275864727024SZiyang Xuan } 275964727024SZiyang Xuan 276064727024SZiyang Xuan /* init_cfg_mgmt */ 276164727024SZiyang Xuan rc = init_cfg_mgmt(nic_dev->hwdev); 276264727024SZiyang Xuan if (rc) { 276364727024SZiyang Xuan PMD_DRV_LOG(ERR, "Initialize cfg_mgmt failed, dev_name: %s", 276464727024SZiyang Xuan eth_dev->data->name); 276564727024SZiyang Xuan goto init_cfgmgnt_fail; 276664727024SZiyang Xuan } 276764727024SZiyang Xuan 276864727024SZiyang Xuan /* init_aeqs */ 276964727024SZiyang Xuan rc = hinic_comm_aeqs_init(nic_dev->hwdev); 277064727024SZiyang Xuan if (rc) { 277164727024SZiyang Xuan PMD_DRV_LOG(ERR, "Initialize aeqs failed, dev_name: %s", 277264727024SZiyang Xuan eth_dev->data->name); 277364727024SZiyang Xuan goto init_aeqs_fail; 277464727024SZiyang Xuan } 277564727024SZiyang Xuan 277664727024SZiyang Xuan /* init_pf_to_mgnt */ 277764727024SZiyang Xuan rc = hinic_comm_pf_to_mgmt_init(nic_dev->hwdev); 277864727024SZiyang Xuan if (rc) { 277964727024SZiyang Xuan PMD_DRV_LOG(ERR, "Initialize pf_to_mgmt failed, dev_name: %s", 278064727024SZiyang Xuan eth_dev->data->name); 278164727024SZiyang Xuan goto init_pf_to_mgmt_fail; 278264727024SZiyang Xuan } 278364727024SZiyang Xuan 27846691acefSXiaoyun Wang /* init mailbox */ 27856691acefSXiaoyun Wang rc = hinic_comm_func_to_func_init(nic_dev->hwdev); 27866691acefSXiaoyun Wang if (rc) { 27876691acefSXiaoyun Wang PMD_DRV_LOG(ERR, "Initialize func_to_func failed, dev_name: %s", 27886691acefSXiaoyun Wang eth_dev->data->name); 27896691acefSXiaoyun Wang goto init_func_to_func_fail; 27906691acefSXiaoyun Wang } 27916691acefSXiaoyun Wang 279264727024SZiyang Xuan rc = hinic_card_workmode_check(nic_dev); 279364727024SZiyang Xuan if (rc) { 279464727024SZiyang Xuan PMD_DRV_LOG(ERR, "Check card workmode failed, dev_name: %s", 279564727024SZiyang Xuan eth_dev->data->name); 279664727024SZiyang Xuan goto workmode_check_fail; 279764727024SZiyang Xuan } 279864727024SZiyang Xuan 279964727024SZiyang Xuan /* do l2nic reset to make chip clear */ 280064727024SZiyang Xuan rc = hinic_l2nic_reset(nic_dev->hwdev); 280164727024SZiyang Xuan if (rc) { 280264727024SZiyang Xuan PMD_DRV_LOG(ERR, "Do l2nic reset failed, dev_name: %s", 280364727024SZiyang Xuan eth_dev->data->name); 280464727024SZiyang Xuan goto l2nic_reset_fail; 280564727024SZiyang Xuan } 280664727024SZiyang Xuan 280764727024SZiyang Xuan /* init dma and aeq msix attribute table */ 280864727024SZiyang Xuan (void)hinic_init_attr_table(nic_dev->hwdev); 280964727024SZiyang Xuan 281064727024SZiyang Xuan /* init_cmdqs */ 281164727024SZiyang Xuan rc = hinic_comm_cmdqs_init(nic_dev->hwdev); 281264727024SZiyang Xuan if (rc) { 281364727024SZiyang Xuan PMD_DRV_LOG(ERR, "Initialize cmdq failed, dev_name: %s", 281464727024SZiyang Xuan eth_dev->data->name); 281564727024SZiyang Xuan goto init_cmdq_fail; 281664727024SZiyang Xuan } 281764727024SZiyang Xuan 281864727024SZiyang Xuan /* set hardware state active */ 281964727024SZiyang Xuan rc = hinic_activate_hwdev_state(nic_dev->hwdev); 282064727024SZiyang Xuan if (rc) { 282164727024SZiyang Xuan PMD_DRV_LOG(ERR, "Initialize resources state failed, dev_name: %s", 282264727024SZiyang Xuan eth_dev->data->name); 282364727024SZiyang Xuan goto init_resources_state_fail; 282464727024SZiyang Xuan } 282564727024SZiyang Xuan 282664727024SZiyang Xuan /* init_capability */ 282764727024SZiyang Xuan rc = hinic_init_capability(nic_dev->hwdev); 282864727024SZiyang Xuan if (rc) { 282964727024SZiyang Xuan PMD_DRV_LOG(ERR, "Initialize capability failed, dev_name: %s", 283064727024SZiyang Xuan eth_dev->data->name); 283164727024SZiyang Xuan goto init_cap_fail; 283264727024SZiyang Xuan } 283364727024SZiyang Xuan 283464727024SZiyang Xuan /* get nic capability */ 283513850e88SXiaoyun Wang if (!hinic_support_nic(nic_dev->hwdev, &nic_dev->nic_cap)) { 283613850e88SXiaoyun Wang PMD_DRV_LOG(ERR, "Hw doesn't support nic, dev_name: %s", 283713850e88SXiaoyun Wang eth_dev->data->name); 283813850e88SXiaoyun Wang rc = -EINVAL; 283964727024SZiyang Xuan goto nic_check_fail; 284013850e88SXiaoyun Wang } 284164727024SZiyang Xuan 284264727024SZiyang Xuan /* init root cla and function table */ 284364727024SZiyang Xuan rc = hinic_init_nicio(nic_dev->hwdev); 284464727024SZiyang Xuan if (rc) { 284564727024SZiyang Xuan PMD_DRV_LOG(ERR, "Initialize nic_io failed, dev_name: %s", 284664727024SZiyang Xuan eth_dev->data->name); 284764727024SZiyang Xuan goto init_nicio_fail; 284864727024SZiyang Xuan } 284964727024SZiyang Xuan 285064727024SZiyang Xuan /* init_software_txrxq */ 285164727024SZiyang Xuan rc = hinic_init_sw_rxtxqs(nic_dev); 285264727024SZiyang Xuan if (rc) { 285364727024SZiyang Xuan PMD_DRV_LOG(ERR, "Initialize sw_rxtxqs failed, dev_name: %s", 285464727024SZiyang Xuan eth_dev->data->name); 285564727024SZiyang Xuan goto init_sw_rxtxqs_fail; 285664727024SZiyang Xuan } 285764727024SZiyang Xuan 285864727024SZiyang Xuan rc = hinic_copy_mempool_init(nic_dev); 285964727024SZiyang Xuan if (rc) { 286064727024SZiyang Xuan PMD_DRV_LOG(ERR, "Create copy mempool failed, dev_name: %s", 286164727024SZiyang Xuan eth_dev->data->name); 286264727024SZiyang Xuan goto init_mpool_fail; 286364727024SZiyang Xuan } 286464727024SZiyang Xuan 286564727024SZiyang Xuan /* set hardware feature to default status */ 286664727024SZiyang Xuan rc = hinic_set_default_hw_feature(nic_dev); 286764727024SZiyang Xuan if (rc) { 286864727024SZiyang Xuan PMD_DRV_LOG(ERR, "Initialize hardware default features failed, dev_name: %s", 286964727024SZiyang Xuan eth_dev->data->name); 287064727024SZiyang Xuan goto set_default_hw_feature_fail; 287164727024SZiyang Xuan } 287264727024SZiyang Xuan 287364727024SZiyang Xuan return 0; 287464727024SZiyang Xuan 287564727024SZiyang Xuan set_default_hw_feature_fail: 287664727024SZiyang Xuan hinic_copy_mempool_uninit(nic_dev); 287764727024SZiyang Xuan 287864727024SZiyang Xuan init_mpool_fail: 287964727024SZiyang Xuan hinic_deinit_sw_rxtxqs(nic_dev); 288064727024SZiyang Xuan 288164727024SZiyang Xuan init_sw_rxtxqs_fail: 288264727024SZiyang Xuan hinic_deinit_nicio(nic_dev->hwdev); 288364727024SZiyang Xuan 288464727024SZiyang Xuan nic_check_fail: 288564727024SZiyang Xuan init_nicio_fail: 288664727024SZiyang Xuan init_cap_fail: 288764727024SZiyang Xuan hinic_deactivate_hwdev_state(nic_dev->hwdev); 288864727024SZiyang Xuan 288964727024SZiyang Xuan init_resources_state_fail: 289064727024SZiyang Xuan hinic_comm_cmdqs_free(nic_dev->hwdev); 289164727024SZiyang Xuan 289264727024SZiyang Xuan init_cmdq_fail: 289364727024SZiyang Xuan l2nic_reset_fail: 289464727024SZiyang Xuan workmode_check_fail: 28956691acefSXiaoyun Wang hinic_comm_func_to_func_free(nic_dev->hwdev); 28966691acefSXiaoyun Wang 28976691acefSXiaoyun Wang init_func_to_func_fail: 289864727024SZiyang Xuan hinic_comm_pf_to_mgmt_free(nic_dev->hwdev); 289964727024SZiyang Xuan 290064727024SZiyang Xuan init_pf_to_mgmt_fail: 290164727024SZiyang Xuan hinic_comm_aeqs_free(nic_dev->hwdev); 290264727024SZiyang Xuan 290364727024SZiyang Xuan init_aeqs_fail: 290464727024SZiyang Xuan free_cfg_mgmt(nic_dev->hwdev); 290564727024SZiyang Xuan 290664727024SZiyang Xuan init_cfgmgnt_fail: 290764727024SZiyang Xuan hinic_hwif_res_free(nic_dev->hwdev); 290864727024SZiyang Xuan 290964727024SZiyang Xuan init_hwif_fail: 291064727024SZiyang Xuan hinic_osdep_deinit(nic_dev->hwdev); 291164727024SZiyang Xuan 291264727024SZiyang Xuan init_osdep_fail: 291364727024SZiyang Xuan rte_free(nic_dev->hwdev); 291464727024SZiyang Xuan nic_dev->hwdev = NULL; 291564727024SZiyang Xuan 291664727024SZiyang Xuan return rc; 291764727024SZiyang Xuan } 291864727024SZiyang Xuan 291964727024SZiyang Xuan static void hinic_nic_dev_destroy(struct rte_eth_dev *eth_dev) 292064727024SZiyang Xuan { 292164727024SZiyang Xuan struct hinic_nic_dev *nic_dev = 292264727024SZiyang Xuan HINIC_ETH_DEV_TO_PRIVATE_NIC_DEV(eth_dev); 292364727024SZiyang Xuan 292464727024SZiyang Xuan (void)hinic_set_link_status_follow(nic_dev->hwdev, 292564727024SZiyang Xuan HINIC_LINK_FOLLOW_DEFAULT); 292664727024SZiyang Xuan hinic_copy_mempool_uninit(nic_dev); 292764727024SZiyang Xuan hinic_deinit_sw_rxtxqs(nic_dev); 292864727024SZiyang Xuan hinic_deinit_nicio(nic_dev->hwdev); 292964727024SZiyang Xuan hinic_deactivate_hwdev_state(nic_dev->hwdev); 293064727024SZiyang Xuan hinic_comm_cmdqs_free(nic_dev->hwdev); 29316691acefSXiaoyun Wang hinic_comm_func_to_func_free(nic_dev->hwdev); 293264727024SZiyang Xuan hinic_comm_pf_to_mgmt_free(nic_dev->hwdev); 293364727024SZiyang Xuan hinic_comm_aeqs_free(nic_dev->hwdev); 293464727024SZiyang Xuan free_cfg_mgmt(nic_dev->hwdev); 293564727024SZiyang Xuan hinic_hwif_res_free(nic_dev->hwdev); 293664727024SZiyang Xuan hinic_osdep_deinit(nic_dev->hwdev); 293764727024SZiyang Xuan rte_free(nic_dev->hwdev); 293864727024SZiyang Xuan nic_dev->hwdev = NULL; 293964727024SZiyang Xuan } 294064727024SZiyang Xuan 294164727024SZiyang Xuan /** 29421d09792aSZiyang Xuan * DPDK callback to close the device. 29431d09792aSZiyang Xuan * 29441d09792aSZiyang Xuan * @param dev 29451d09792aSZiyang Xuan * Pointer to Ethernet device structure. 29461d09792aSZiyang Xuan */ 2947b142387bSThomas Monjalon static int hinic_dev_close(struct rte_eth_dev *dev) 29481d09792aSZiyang Xuan { 294964727024SZiyang Xuan struct hinic_nic_dev *nic_dev = HINIC_ETH_DEV_TO_PRIVATE_NIC_DEV(dev); 295062024eb8SIvan Ilchenko int ret; 295164727024SZiyang Xuan 295230410493SThomas Monjalon if (rte_eal_process_type() != RTE_PROC_PRIMARY) 295330410493SThomas Monjalon return 0; 295430410493SThomas Monjalon 29550371535dSJoyce Kong if (rte_bit_relaxed_test_and_set32(HINIC_DEV_CLOSE, 29560371535dSJoyce Kong &nic_dev->dev_status)) { 295764727024SZiyang Xuan PMD_DRV_LOG(WARNING, "Device %s already closed", 295864727024SZiyang Xuan dev->data->name); 2959b142387bSThomas Monjalon return 0; 296064727024SZiyang Xuan } 296164727024SZiyang Xuan 29622c473729SZiyang Xuan /* stop device first */ 296362024eb8SIvan Ilchenko ret = hinic_dev_stop(dev); 29642c473729SZiyang Xuan 296564727024SZiyang Xuan /* rx_cqe, rx_info */ 296664727024SZiyang Xuan hinic_free_all_rx_resources(dev); 296764727024SZiyang Xuan 296864727024SZiyang Xuan /* tx_info */ 296964727024SZiyang Xuan hinic_free_all_tx_resources(dev); 297064727024SZiyang Xuan 297164727024SZiyang Xuan /* free wq, pi_dma_addr */ 297264727024SZiyang Xuan hinic_free_all_rq(nic_dev); 297364727024SZiyang Xuan 297464727024SZiyang Xuan /* free wq, db_addr */ 297564727024SZiyang Xuan hinic_free_all_sq(nic_dev); 297664727024SZiyang Xuan 297764727024SZiyang Xuan /* deinit mac vlan tbl */ 297864727024SZiyang Xuan hinic_deinit_mac_addr(dev); 2979fdba3bf1SXiaoyun Wang hinic_remove_all_vlanid(dev); 298064727024SZiyang Xuan 298164727024SZiyang Xuan /* disable hardware and uio interrupt */ 298264727024SZiyang Xuan hinic_disable_interrupt(dev); 298364727024SZiyang Xuan 2984511b7371SGuoyang Zhou /* destroy rx mode mutex */ 2985511b7371SGuoyang Zhou hinic_mutex_destroy(&nic_dev->rx_mode_mutex); 2986511b7371SGuoyang Zhou 298764727024SZiyang Xuan /* deinit nic hardware device */ 298864727024SZiyang Xuan hinic_nic_dev_destroy(dev); 2989b142387bSThomas Monjalon 299062024eb8SIvan Ilchenko return ret; 29911d09792aSZiyang Xuan } 29921d09792aSZiyang Xuan 29931d09792aSZiyang Xuan static const struct eth_dev_ops hinic_pmd_ops = { 299464727024SZiyang Xuan .dev_configure = hinic_dev_configure, 29951d09792aSZiyang Xuan .dev_infos_get = hinic_dev_infos_get, 2996dbf524abSXiaoyun Wang .fw_version_get = hinic_fw_version_get, 29972c473729SZiyang Xuan .rx_queue_setup = hinic_rx_queue_setup, 29982c473729SZiyang Xuan .tx_queue_setup = hinic_tx_queue_setup, 29992c473729SZiyang Xuan .dev_start = hinic_dev_start, 300054ac3386SXiaoyun Wang .dev_set_link_up = hinic_dev_set_link_up, 300154ac3386SXiaoyun Wang .dev_set_link_down = hinic_dev_set_link_down, 30022c473729SZiyang Xuan .link_update = hinic_link_update, 30032c473729SZiyang Xuan .rx_queue_release = hinic_rx_queue_release, 30042c473729SZiyang Xuan .tx_queue_release = hinic_tx_queue_release, 30052c473729SZiyang Xuan .dev_stop = hinic_dev_stop, 300664727024SZiyang Xuan .dev_close = hinic_dev_close, 30078260eba6SXiaoyun Wang .mtu_set = hinic_dev_set_mtu, 3008fdba3bf1SXiaoyun Wang .vlan_filter_set = hinic_vlan_filter_set, 3009fdba3bf1SXiaoyun Wang .vlan_offload_set = hinic_vlan_offload_set, 30108260eba6SXiaoyun Wang .allmulticast_enable = hinic_dev_allmulticast_enable, 30118260eba6SXiaoyun Wang .allmulticast_disable = hinic_dev_allmulticast_disable, 3012cb7b6606SZiyang Xuan .promiscuous_enable = hinic_dev_promiscuous_enable, 3013cb7b6606SZiyang Xuan .promiscuous_disable = hinic_dev_promiscuous_disable, 3014ef6f2f5cSXiaoyun Wang .flow_ctrl_get = hinic_flow_ctrl_get, 3015ef6f2f5cSXiaoyun Wang .flow_ctrl_set = hinic_flow_ctrl_set, 3016cb7b6606SZiyang Xuan .rss_hash_update = hinic_rss_hash_update, 3017cb7b6606SZiyang Xuan .rss_hash_conf_get = hinic_rss_conf_get, 3018cb7b6606SZiyang Xuan .reta_update = hinic_rss_indirtbl_update, 3019cb7b6606SZiyang Xuan .reta_query = hinic_rss_indirtbl_query, 3020cb7b6606SZiyang Xuan .stats_get = hinic_dev_stats_get, 3021cb7b6606SZiyang Xuan .stats_reset = hinic_dev_stats_reset, 3022cb7b6606SZiyang Xuan .xstats_get = hinic_dev_xstats_get, 3023cb7b6606SZiyang Xuan .xstats_reset = hinic_dev_xstats_reset, 3024cb7b6606SZiyang Xuan .xstats_get_names = hinic_dev_xstats_get_names, 3025483b4817SXiaoyun Wang .rxq_info_get = hinic_rxq_info_get, 3026483b4817SXiaoyun Wang .txq_info_get = hinic_txq_info_get, 302700499a22SXiaoyun Wang .mac_addr_set = hinic_set_mac_addr, 302800499a22SXiaoyun Wang .mac_addr_remove = hinic_mac_addr_remove, 302900499a22SXiaoyun Wang .mac_addr_add = hinic_mac_addr_add, 303000499a22SXiaoyun Wang .set_mc_addr_list = hinic_set_mc_addr_list, 3031fb7ad441SThomas Monjalon .flow_ops_get = hinic_dev_flow_ops_get, 30321d09792aSZiyang Xuan }; 30331d09792aSZiyang Xuan 30346691acefSXiaoyun Wang static const struct eth_dev_ops hinic_pmd_vf_ops = { 30356691acefSXiaoyun Wang .dev_configure = hinic_dev_configure, 30366691acefSXiaoyun Wang .dev_infos_get = hinic_dev_infos_get, 3037dbf524abSXiaoyun Wang .fw_version_get = hinic_fw_version_get, 30386691acefSXiaoyun Wang .rx_queue_setup = hinic_rx_queue_setup, 30396691acefSXiaoyun Wang .tx_queue_setup = hinic_tx_queue_setup, 30406691acefSXiaoyun Wang .dev_start = hinic_dev_start, 30416691acefSXiaoyun Wang .link_update = hinic_link_update, 30426691acefSXiaoyun Wang .rx_queue_release = hinic_rx_queue_release, 30436691acefSXiaoyun Wang .tx_queue_release = hinic_tx_queue_release, 30446691acefSXiaoyun Wang .dev_stop = hinic_dev_stop, 30456691acefSXiaoyun Wang .dev_close = hinic_dev_close, 30468260eba6SXiaoyun Wang .mtu_set = hinic_dev_set_mtu, 3047fdba3bf1SXiaoyun Wang .vlan_filter_set = hinic_vlan_filter_set, 3048fdba3bf1SXiaoyun Wang .vlan_offload_set = hinic_vlan_offload_set, 30498260eba6SXiaoyun Wang .allmulticast_enable = hinic_dev_allmulticast_enable, 30508260eba6SXiaoyun Wang .allmulticast_disable = hinic_dev_allmulticast_disable, 30516691acefSXiaoyun Wang .rss_hash_update = hinic_rss_hash_update, 30526691acefSXiaoyun Wang .rss_hash_conf_get = hinic_rss_conf_get, 30536691acefSXiaoyun Wang .reta_update = hinic_rss_indirtbl_update, 30546691acefSXiaoyun Wang .reta_query = hinic_rss_indirtbl_query, 30556691acefSXiaoyun Wang .stats_get = hinic_dev_stats_get, 30566691acefSXiaoyun Wang .stats_reset = hinic_dev_stats_reset, 30576691acefSXiaoyun Wang .xstats_get = hinic_dev_xstats_get, 30586691acefSXiaoyun Wang .xstats_reset = hinic_dev_xstats_reset, 30596691acefSXiaoyun Wang .xstats_get_names = hinic_dev_xstats_get_names, 3060483b4817SXiaoyun Wang .rxq_info_get = hinic_rxq_info_get, 3061483b4817SXiaoyun Wang .txq_info_get = hinic_txq_info_get, 306200499a22SXiaoyun Wang .mac_addr_set = hinic_set_mac_addr, 306300499a22SXiaoyun Wang .mac_addr_remove = hinic_mac_addr_remove, 306400499a22SXiaoyun Wang .mac_addr_add = hinic_mac_addr_add, 306500499a22SXiaoyun Wang .set_mc_addr_list = hinic_set_mc_addr_list, 3066fb7ad441SThomas Monjalon .flow_ops_get = hinic_dev_flow_ops_get, 30676691acefSXiaoyun Wang }; 30686691acefSXiaoyun Wang 30694c670dfaSGuoyang Zhou static const struct eth_dev_ops hinic_dev_sec_ops = { 30704c670dfaSGuoyang Zhou .dev_infos_get = hinic_dev_infos_get, 30714c670dfaSGuoyang Zhou }; 30724c670dfaSGuoyang Zhou 30736691acefSXiaoyun Wang static int hinic_func_init(struct rte_eth_dev *eth_dev) 30746691acefSXiaoyun Wang { 30756691acefSXiaoyun Wang struct rte_pci_device *pci_dev; 30766691acefSXiaoyun Wang struct rte_ether_addr *eth_addr; 30776691acefSXiaoyun Wang struct hinic_nic_dev *nic_dev; 30781742421bSXiaoyun Wang struct hinic_filter_info *filter_info; 30791fe89aa3SXiaoyun Wang struct hinic_tcam_info *tcam_info; 308000499a22SXiaoyun Wang u32 mac_size; 30816691acefSXiaoyun Wang int rc; 30826691acefSXiaoyun Wang 30836691acefSXiaoyun Wang pci_dev = RTE_ETH_DEV_TO_PCI(eth_dev); 30846691acefSXiaoyun Wang 30856691acefSXiaoyun Wang /* EAL is SECONDARY and eth_dev is already created */ 30866691acefSXiaoyun Wang if (rte_eal_process_type() != RTE_PROC_PRIMARY) { 30874c670dfaSGuoyang Zhou eth_dev->dev_ops = &hinic_dev_sec_ops; 308866f64dd6SXiaoyun Wang PMD_DRV_LOG(INFO, "Initialize %s in secondary process", 30896691acefSXiaoyun Wang eth_dev->data->name); 30906691acefSXiaoyun Wang 309166f64dd6SXiaoyun Wang return 0; 30926691acefSXiaoyun Wang } 30936691acefSXiaoyun Wang 3094f30e69b4SFerruh Yigit eth_dev->data->dev_flags |= RTE_ETH_DEV_AUTOFILL_QUEUE_XSTATS; 3095f30e69b4SFerruh Yigit 30966691acefSXiaoyun Wang nic_dev = HINIC_ETH_DEV_TO_PRIVATE_NIC_DEV(eth_dev); 30976691acefSXiaoyun Wang memset(nic_dev, 0, sizeof(*nic_dev)); 30986691acefSXiaoyun Wang 30996691acefSXiaoyun Wang snprintf(nic_dev->proc_dev_name, 31006691acefSXiaoyun Wang sizeof(nic_dev->proc_dev_name), 31016691acefSXiaoyun Wang "hinic-%.4x:%.2x:%.2x.%x", 31026691acefSXiaoyun Wang pci_dev->addr.domain, pci_dev->addr.bus, 31036691acefSXiaoyun Wang pci_dev->addr.devid, pci_dev->addr.function); 31046691acefSXiaoyun Wang 31056691acefSXiaoyun Wang /* alloc mac_addrs */ 310600499a22SXiaoyun Wang mac_size = HINIC_MAX_UC_MAC_ADDRS * sizeof(struct rte_ether_addr); 310700499a22SXiaoyun Wang eth_addr = rte_zmalloc("hinic_mac", mac_size, 0); 31086691acefSXiaoyun Wang if (!eth_addr) { 31096691acefSXiaoyun Wang PMD_DRV_LOG(ERR, "Allocate ethernet addresses' memory failed, dev_name: %s", 31106691acefSXiaoyun Wang eth_dev->data->name); 31116691acefSXiaoyun Wang rc = -ENOMEM; 31126691acefSXiaoyun Wang goto eth_addr_fail; 31136691acefSXiaoyun Wang } 31146691acefSXiaoyun Wang eth_dev->data->mac_addrs = eth_addr; 31156691acefSXiaoyun Wang 311600499a22SXiaoyun Wang mac_size = HINIC_MAX_MC_MAC_ADDRS * sizeof(struct rte_ether_addr); 311700499a22SXiaoyun Wang nic_dev->mc_list = rte_zmalloc("hinic_mc", mac_size, 0); 311800499a22SXiaoyun Wang if (!nic_dev->mc_list) { 311900499a22SXiaoyun Wang PMD_DRV_LOG(ERR, "Allocate mcast address' memory failed, dev_name: %s", 312000499a22SXiaoyun Wang eth_dev->data->name); 312100499a22SXiaoyun Wang rc = -ENOMEM; 312200499a22SXiaoyun Wang goto mc_addr_fail; 312300499a22SXiaoyun Wang } 312400499a22SXiaoyun Wang 31256691acefSXiaoyun Wang /* create hardware nic_device */ 31266691acefSXiaoyun Wang rc = hinic_nic_dev_create(eth_dev); 31276691acefSXiaoyun Wang if (rc) { 31286691acefSXiaoyun Wang PMD_DRV_LOG(ERR, "Create nic device failed, dev_name: %s", 31296691acefSXiaoyun Wang eth_dev->data->name); 31306691acefSXiaoyun Wang goto create_nic_dev_fail; 31316691acefSXiaoyun Wang } 31326691acefSXiaoyun Wang 31336691acefSXiaoyun Wang if (HINIC_IS_VF(nic_dev->hwdev)) 31346691acefSXiaoyun Wang eth_dev->dev_ops = &hinic_pmd_vf_ops; 31356691acefSXiaoyun Wang else 31366691acefSXiaoyun Wang eth_dev->dev_ops = &hinic_pmd_ops; 31376691acefSXiaoyun Wang 31386691acefSXiaoyun Wang rc = hinic_init_mac_addr(eth_dev); 31396691acefSXiaoyun Wang if (rc) { 31406691acefSXiaoyun Wang PMD_DRV_LOG(ERR, "Initialize mac table failed, dev_name: %s", 31416691acefSXiaoyun Wang eth_dev->data->name); 31426691acefSXiaoyun Wang goto init_mac_fail; 31436691acefSXiaoyun Wang } 31446691acefSXiaoyun Wang 31456691acefSXiaoyun Wang /* register callback func to eal lib */ 31466691acefSXiaoyun Wang rc = rte_intr_callback_register(&pci_dev->intr_handle, 31476691acefSXiaoyun Wang hinic_dev_interrupt_handler, 31486691acefSXiaoyun Wang (void *)eth_dev); 31496691acefSXiaoyun Wang if (rc) { 31506691acefSXiaoyun Wang PMD_DRV_LOG(ERR, "Register rte interrupt callback failed, dev_name: %s", 31516691acefSXiaoyun Wang eth_dev->data->name); 31526691acefSXiaoyun Wang goto reg_intr_cb_fail; 31536691acefSXiaoyun Wang } 31546691acefSXiaoyun Wang 31556691acefSXiaoyun Wang /* enable uio/vfio intr/eventfd mapping */ 31566691acefSXiaoyun Wang rc = rte_intr_enable(&pci_dev->intr_handle); 31576691acefSXiaoyun Wang if (rc) { 31586691acefSXiaoyun Wang PMD_DRV_LOG(ERR, "Enable rte interrupt failed, dev_name: %s", 31596691acefSXiaoyun Wang eth_dev->data->name); 31606691acefSXiaoyun Wang goto enable_intr_fail; 31616691acefSXiaoyun Wang } 31620371535dSJoyce Kong rte_bit_relaxed_set32(HINIC_DEV_INTR_EN, &nic_dev->dev_status); 31636691acefSXiaoyun Wang 3164224cff4bSXiaoyun Wang hinic_mutex_init(&nic_dev->rx_mode_mutex, NULL); 3165224cff4bSXiaoyun Wang 31661742421bSXiaoyun Wang /* initialize filter info */ 31671742421bSXiaoyun Wang filter_info = &nic_dev->filter; 31681fe89aa3SXiaoyun Wang tcam_info = &nic_dev->tcam; 31691742421bSXiaoyun Wang memset(filter_info, 0, sizeof(struct hinic_filter_info)); 31701fe89aa3SXiaoyun Wang memset(tcam_info, 0, sizeof(struct hinic_tcam_info)); 31711742421bSXiaoyun Wang /* initialize 5tuple filter list */ 31721742421bSXiaoyun Wang TAILQ_INIT(&filter_info->fivetuple_list); 31731fe89aa3SXiaoyun Wang TAILQ_INIT(&tcam_info->tcam_list); 31741742421bSXiaoyun Wang TAILQ_INIT(&nic_dev->filter_ntuple_list); 31751742421bSXiaoyun Wang TAILQ_INIT(&nic_dev->filter_ethertype_list); 31761742421bSXiaoyun Wang TAILQ_INIT(&nic_dev->filter_fdir_rule_list); 31771742421bSXiaoyun Wang TAILQ_INIT(&nic_dev->hinic_flow_list); 31781742421bSXiaoyun Wang 31790371535dSJoyce Kong rte_bit_relaxed_set32(HINIC_DEV_INIT, &nic_dev->dev_status); 31806691acefSXiaoyun Wang PMD_DRV_LOG(INFO, "Initialize %s in primary successfully", 31816691acefSXiaoyun Wang eth_dev->data->name); 31826691acefSXiaoyun Wang 31836691acefSXiaoyun Wang return 0; 31846691acefSXiaoyun Wang 31856691acefSXiaoyun Wang enable_intr_fail: 31866691acefSXiaoyun Wang (void)rte_intr_callback_unregister(&pci_dev->intr_handle, 31876691acefSXiaoyun Wang hinic_dev_interrupt_handler, 31886691acefSXiaoyun Wang (void *)eth_dev); 31896691acefSXiaoyun Wang 31906691acefSXiaoyun Wang reg_intr_cb_fail: 31916691acefSXiaoyun Wang hinic_deinit_mac_addr(eth_dev); 31926691acefSXiaoyun Wang 31936691acefSXiaoyun Wang init_mac_fail: 31946691acefSXiaoyun Wang eth_dev->dev_ops = NULL; 31956691acefSXiaoyun Wang hinic_nic_dev_destroy(eth_dev); 31966691acefSXiaoyun Wang 31976691acefSXiaoyun Wang create_nic_dev_fail: 319800499a22SXiaoyun Wang rte_free(nic_dev->mc_list); 319900499a22SXiaoyun Wang nic_dev->mc_list = NULL; 320000499a22SXiaoyun Wang 320100499a22SXiaoyun Wang mc_addr_fail: 32026691acefSXiaoyun Wang rte_free(eth_addr); 32036691acefSXiaoyun Wang eth_dev->data->mac_addrs = NULL; 32046691acefSXiaoyun Wang 32056691acefSXiaoyun Wang eth_addr_fail: 32066691acefSXiaoyun Wang PMD_DRV_LOG(ERR, "Initialize %s in primary failed", 32076691acefSXiaoyun Wang eth_dev->data->name); 32086691acefSXiaoyun Wang return rc; 32096691acefSXiaoyun Wang } 32106691acefSXiaoyun Wang 32111d09792aSZiyang Xuan static int hinic_dev_init(struct rte_eth_dev *eth_dev) 32121d09792aSZiyang Xuan { 32131d09792aSZiyang Xuan struct rte_pci_device *pci_dev; 32141d09792aSZiyang Xuan 32151d09792aSZiyang Xuan pci_dev = RTE_ETH_DEV_TO_PCI(eth_dev); 32161d09792aSZiyang Xuan 32171d09792aSZiyang Xuan PMD_DRV_LOG(INFO, "Initializing pf hinic-%.4x:%.2x:%.2x.%x in %s process", 32181d09792aSZiyang Xuan pci_dev->addr.domain, pci_dev->addr.bus, 32191d09792aSZiyang Xuan pci_dev->addr.devid, pci_dev->addr.function, 32201d09792aSZiyang Xuan (rte_eal_process_type() == RTE_PROC_PRIMARY) ? 32211d09792aSZiyang Xuan "primary" : "secondary"); 32221d09792aSZiyang Xuan 32236691acefSXiaoyun Wang /* rte_eth_dev rx_burst and tx_burst */ 3224076221c8SZiyang Xuan eth_dev->rx_pkt_burst = hinic_recv_pkts; 3225076221c8SZiyang Xuan eth_dev->tx_pkt_burst = hinic_xmit_pkts; 32261d09792aSZiyang Xuan 32271d09792aSZiyang Xuan return hinic_func_init(eth_dev); 32281d09792aSZiyang Xuan } 32291d09792aSZiyang Xuan 32301d09792aSZiyang Xuan static int hinic_dev_uninit(struct rte_eth_dev *dev) 32311d09792aSZiyang Xuan { 32321d09792aSZiyang Xuan if (rte_eal_process_type() != RTE_PROC_PRIMARY) 32331d09792aSZiyang Xuan return 0; 32341d09792aSZiyang Xuan 32351d09792aSZiyang Xuan hinic_dev_close(dev); 32361d09792aSZiyang Xuan 32371d09792aSZiyang Xuan return HINIC_OK; 32381d09792aSZiyang Xuan } 32391d09792aSZiyang Xuan 32401d09792aSZiyang Xuan static struct rte_pci_id pci_id_hinic_map[] = { 32411d09792aSZiyang Xuan { RTE_PCI_DEVICE(HINIC_HUAWEI_VENDOR_ID, HINIC_DEV_ID_PRD) }, 32421d09792aSZiyang Xuan { RTE_PCI_DEVICE(HINIC_HUAWEI_VENDOR_ID, HINIC_DEV_ID_MEZZ_25GE) }, 32431d09792aSZiyang Xuan { RTE_PCI_DEVICE(HINIC_HUAWEI_VENDOR_ID, HINIC_DEV_ID_MEZZ_100GE) }, 32446691acefSXiaoyun Wang { RTE_PCI_DEVICE(HINIC_HUAWEI_VENDOR_ID, HINIC_DEV_ID_VF) }, 32456691acefSXiaoyun Wang { RTE_PCI_DEVICE(HINIC_HUAWEI_VENDOR_ID, HINIC_DEV_ID_VF_HV) }, 32466691acefSXiaoyun Wang { RTE_PCI_DEVICE(HINIC_HUAWEI_VENDOR_ID, HINIC_DEV_ID_1822_DUAL_25GE) }, 32476691acefSXiaoyun Wang { RTE_PCI_DEVICE(HINIC_HUAWEI_VENDOR_ID, HINIC_DEV_ID_1822_100GE) }, 32481d09792aSZiyang Xuan {.vendor_id = 0}, 32491d09792aSZiyang Xuan }; 32501d09792aSZiyang Xuan 32511d09792aSZiyang Xuan static int hinic_pci_probe(struct rte_pci_driver *pci_drv __rte_unused, 32521d09792aSZiyang Xuan struct rte_pci_device *pci_dev) 32531d09792aSZiyang Xuan { 32541d09792aSZiyang Xuan return rte_eth_dev_pci_generic_probe(pci_dev, 32551d09792aSZiyang Xuan sizeof(struct hinic_nic_dev), hinic_dev_init); 32561d09792aSZiyang Xuan } 32571d09792aSZiyang Xuan 32581d09792aSZiyang Xuan static int hinic_pci_remove(struct rte_pci_device *pci_dev) 32591d09792aSZiyang Xuan { 32601d09792aSZiyang Xuan return rte_eth_dev_pci_generic_remove(pci_dev, hinic_dev_uninit); 32611d09792aSZiyang Xuan } 32621d09792aSZiyang Xuan 32631d09792aSZiyang Xuan static struct rte_pci_driver rte_hinic_pmd = { 32641d09792aSZiyang Xuan .id_table = pci_id_hinic_map, 32651d09792aSZiyang Xuan .drv_flags = RTE_PCI_DRV_NEED_MAPPING | RTE_PCI_DRV_INTR_LSC, 32661d09792aSZiyang Xuan .probe = hinic_pci_probe, 32671d09792aSZiyang Xuan .remove = hinic_pci_remove, 32681d09792aSZiyang Xuan }; 32691d09792aSZiyang Xuan 32701d09792aSZiyang Xuan RTE_PMD_REGISTER_PCI(net_hinic, rte_hinic_pmd); 32711d09792aSZiyang Xuan RTE_PMD_REGISTER_PCI_TABLE(net_hinic, pci_id_hinic_map); 3272eeded204SDavid Marchand RTE_LOG_REGISTER_DEFAULT(hinic_logtype, INFO); 3273