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> 61f37cb2bSDavid Marchand #include <bus_pci_driver.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 729d4878efSXiaoyun Wang /* lro numer limit for one packet */ 739d4878efSXiaoyun Wang #define HINIC_LRO_WQE_NUM_DEFAULT 8 749d4878efSXiaoyun Wang 75cb7b6606SZiyang Xuan struct hinic_xstats_name_off { 76cb7b6606SZiyang Xuan char name[RTE_ETH_XSTATS_NAME_SIZE]; 77cb7b6606SZiyang Xuan u32 offset; 78cb7b6606SZiyang Xuan }; 79cb7b6606SZiyang Xuan 80cb7b6606SZiyang Xuan #define HINIC_FUNC_STAT(_stat_item) { \ 81cb7b6606SZiyang Xuan .name = #_stat_item, \ 82cb7b6606SZiyang Xuan .offset = offsetof(struct hinic_vport_stats, _stat_item) \ 83cb7b6606SZiyang Xuan } 84cb7b6606SZiyang Xuan 85cb7b6606SZiyang Xuan #define HINIC_PORT_STAT(_stat_item) { \ 86cb7b6606SZiyang Xuan .name = #_stat_item, \ 87cb7b6606SZiyang Xuan .offset = offsetof(struct hinic_phy_port_stats, _stat_item) \ 88cb7b6606SZiyang Xuan } 89cb7b6606SZiyang Xuan 90cb7b6606SZiyang Xuan static const struct hinic_xstats_name_off hinic_vport_stats_strings[] = { 91cb7b6606SZiyang Xuan HINIC_FUNC_STAT(tx_unicast_pkts_vport), 92cb7b6606SZiyang Xuan HINIC_FUNC_STAT(tx_unicast_bytes_vport), 93cb7b6606SZiyang Xuan HINIC_FUNC_STAT(tx_multicast_pkts_vport), 94cb7b6606SZiyang Xuan HINIC_FUNC_STAT(tx_multicast_bytes_vport), 95cb7b6606SZiyang Xuan HINIC_FUNC_STAT(tx_broadcast_pkts_vport), 96cb7b6606SZiyang Xuan HINIC_FUNC_STAT(tx_broadcast_bytes_vport), 97cb7b6606SZiyang Xuan 98cb7b6606SZiyang Xuan HINIC_FUNC_STAT(rx_unicast_pkts_vport), 99cb7b6606SZiyang Xuan HINIC_FUNC_STAT(rx_unicast_bytes_vport), 100cb7b6606SZiyang Xuan HINIC_FUNC_STAT(rx_multicast_pkts_vport), 101cb7b6606SZiyang Xuan HINIC_FUNC_STAT(rx_multicast_bytes_vport), 102cb7b6606SZiyang Xuan HINIC_FUNC_STAT(rx_broadcast_pkts_vport), 103cb7b6606SZiyang Xuan HINIC_FUNC_STAT(rx_broadcast_bytes_vport), 104cb7b6606SZiyang Xuan 105cb7b6606SZiyang Xuan HINIC_FUNC_STAT(tx_discard_vport), 106cb7b6606SZiyang Xuan HINIC_FUNC_STAT(rx_discard_vport), 107cb7b6606SZiyang Xuan HINIC_FUNC_STAT(tx_err_vport), 108cb7b6606SZiyang Xuan HINIC_FUNC_STAT(rx_err_vport), 109cb7b6606SZiyang Xuan }; 110cb7b6606SZiyang Xuan 111cb7b6606SZiyang Xuan #define HINIC_VPORT_XSTATS_NUM (sizeof(hinic_vport_stats_strings) / \ 112cb7b6606SZiyang Xuan sizeof(hinic_vport_stats_strings[0])) 113cb7b6606SZiyang Xuan 114cb7b6606SZiyang Xuan static const struct hinic_xstats_name_off hinic_phyport_stats_strings[] = { 115cb7b6606SZiyang Xuan HINIC_PORT_STAT(mac_rx_total_pkt_num), 116cb7b6606SZiyang Xuan HINIC_PORT_STAT(mac_rx_total_oct_num), 117cb7b6606SZiyang Xuan HINIC_PORT_STAT(mac_rx_bad_pkt_num), 118cb7b6606SZiyang Xuan HINIC_PORT_STAT(mac_rx_bad_oct_num), 119cb7b6606SZiyang Xuan HINIC_PORT_STAT(mac_rx_good_pkt_num), 120cb7b6606SZiyang Xuan HINIC_PORT_STAT(mac_rx_good_oct_num), 121cb7b6606SZiyang Xuan HINIC_PORT_STAT(mac_rx_uni_pkt_num), 122cb7b6606SZiyang Xuan HINIC_PORT_STAT(mac_rx_multi_pkt_num), 123cb7b6606SZiyang Xuan HINIC_PORT_STAT(mac_rx_broad_pkt_num), 124cb7b6606SZiyang Xuan HINIC_PORT_STAT(mac_tx_total_pkt_num), 125cb7b6606SZiyang Xuan HINIC_PORT_STAT(mac_tx_total_oct_num), 126cb7b6606SZiyang Xuan HINIC_PORT_STAT(mac_tx_bad_pkt_num), 127cb7b6606SZiyang Xuan HINIC_PORT_STAT(mac_tx_bad_oct_num), 128cb7b6606SZiyang Xuan HINIC_PORT_STAT(mac_tx_good_pkt_num), 129cb7b6606SZiyang Xuan HINIC_PORT_STAT(mac_tx_good_oct_num), 130cb7b6606SZiyang Xuan HINIC_PORT_STAT(mac_tx_uni_pkt_num), 131cb7b6606SZiyang Xuan HINIC_PORT_STAT(mac_tx_multi_pkt_num), 132cb7b6606SZiyang Xuan HINIC_PORT_STAT(mac_tx_broad_pkt_num), 133cb7b6606SZiyang Xuan HINIC_PORT_STAT(mac_rx_fragment_pkt_num), 134cb7b6606SZiyang Xuan HINIC_PORT_STAT(mac_rx_undersize_pkt_num), 135cb7b6606SZiyang Xuan HINIC_PORT_STAT(mac_rx_undermin_pkt_num), 136cb7b6606SZiyang Xuan HINIC_PORT_STAT(mac_rx_64_oct_pkt_num), 137cb7b6606SZiyang Xuan HINIC_PORT_STAT(mac_rx_65_127_oct_pkt_num), 138cb7b6606SZiyang Xuan HINIC_PORT_STAT(mac_rx_128_255_oct_pkt_num), 139cb7b6606SZiyang Xuan HINIC_PORT_STAT(mac_rx_256_511_oct_pkt_num), 140cb7b6606SZiyang Xuan HINIC_PORT_STAT(mac_rx_512_1023_oct_pkt_num), 141cb7b6606SZiyang Xuan HINIC_PORT_STAT(mac_rx_1024_1518_oct_pkt_num), 142cb7b6606SZiyang Xuan HINIC_PORT_STAT(mac_rx_1519_2047_oct_pkt_num), 143cb7b6606SZiyang Xuan HINIC_PORT_STAT(mac_rx_2048_4095_oct_pkt_num), 144cb7b6606SZiyang Xuan HINIC_PORT_STAT(mac_rx_4096_8191_oct_pkt_num), 145cb7b6606SZiyang Xuan HINIC_PORT_STAT(mac_rx_8192_9216_oct_pkt_num), 146cb7b6606SZiyang Xuan HINIC_PORT_STAT(mac_rx_9217_12287_oct_pkt_num), 147cb7b6606SZiyang Xuan HINIC_PORT_STAT(mac_rx_12288_16383_oct_pkt_num), 148cb7b6606SZiyang Xuan HINIC_PORT_STAT(mac_rx_1519_max_bad_pkt_num), 149cb7b6606SZiyang Xuan HINIC_PORT_STAT(mac_rx_1519_max_good_pkt_num), 150cb7b6606SZiyang Xuan HINIC_PORT_STAT(mac_rx_oversize_pkt_num), 151cb7b6606SZiyang Xuan HINIC_PORT_STAT(mac_rx_jabber_pkt_num), 152cb7b6606SZiyang Xuan HINIC_PORT_STAT(mac_rx_mac_pause_num), 153cb7b6606SZiyang Xuan HINIC_PORT_STAT(mac_rx_pfc_pkt_num), 154cb7b6606SZiyang Xuan HINIC_PORT_STAT(mac_rx_pfc_pri0_pkt_num), 155cb7b6606SZiyang Xuan HINIC_PORT_STAT(mac_rx_pfc_pri1_pkt_num), 156cb7b6606SZiyang Xuan HINIC_PORT_STAT(mac_rx_pfc_pri2_pkt_num), 157cb7b6606SZiyang Xuan HINIC_PORT_STAT(mac_rx_pfc_pri3_pkt_num), 158cb7b6606SZiyang Xuan HINIC_PORT_STAT(mac_rx_pfc_pri4_pkt_num), 159cb7b6606SZiyang Xuan HINIC_PORT_STAT(mac_rx_pfc_pri5_pkt_num), 160cb7b6606SZiyang Xuan HINIC_PORT_STAT(mac_rx_pfc_pri6_pkt_num), 161cb7b6606SZiyang Xuan HINIC_PORT_STAT(mac_rx_pfc_pri7_pkt_num), 162cb7b6606SZiyang Xuan HINIC_PORT_STAT(mac_rx_mac_control_pkt_num), 163cb7b6606SZiyang Xuan HINIC_PORT_STAT(mac_rx_sym_err_pkt_num), 164cb7b6606SZiyang Xuan HINIC_PORT_STAT(mac_rx_fcs_err_pkt_num), 165cb7b6606SZiyang Xuan HINIC_PORT_STAT(mac_rx_send_app_good_pkt_num), 166cb7b6606SZiyang Xuan HINIC_PORT_STAT(mac_rx_send_app_bad_pkt_num), 167cb7b6606SZiyang Xuan HINIC_PORT_STAT(mac_tx_fragment_pkt_num), 168cb7b6606SZiyang Xuan HINIC_PORT_STAT(mac_tx_undersize_pkt_num), 169cb7b6606SZiyang Xuan HINIC_PORT_STAT(mac_tx_undermin_pkt_num), 170cb7b6606SZiyang Xuan HINIC_PORT_STAT(mac_tx_64_oct_pkt_num), 171cb7b6606SZiyang Xuan HINIC_PORT_STAT(mac_tx_65_127_oct_pkt_num), 172cb7b6606SZiyang Xuan HINIC_PORT_STAT(mac_tx_128_255_oct_pkt_num), 173cb7b6606SZiyang Xuan HINIC_PORT_STAT(mac_tx_256_511_oct_pkt_num), 174cb7b6606SZiyang Xuan HINIC_PORT_STAT(mac_tx_512_1023_oct_pkt_num), 175cb7b6606SZiyang Xuan HINIC_PORT_STAT(mac_tx_1024_1518_oct_pkt_num), 176cb7b6606SZiyang Xuan HINIC_PORT_STAT(mac_tx_1519_2047_oct_pkt_num), 177cb7b6606SZiyang Xuan HINIC_PORT_STAT(mac_tx_2048_4095_oct_pkt_num), 178cb7b6606SZiyang Xuan HINIC_PORT_STAT(mac_tx_4096_8191_oct_pkt_num), 179cb7b6606SZiyang Xuan HINIC_PORT_STAT(mac_tx_8192_9216_oct_pkt_num), 180cb7b6606SZiyang Xuan HINIC_PORT_STAT(mac_tx_9217_12287_oct_pkt_num), 181cb7b6606SZiyang Xuan HINIC_PORT_STAT(mac_tx_12288_16383_oct_pkt_num), 182cb7b6606SZiyang Xuan HINIC_PORT_STAT(mac_tx_1519_max_bad_pkt_num), 183cb7b6606SZiyang Xuan HINIC_PORT_STAT(mac_tx_1519_max_good_pkt_num), 184cb7b6606SZiyang Xuan HINIC_PORT_STAT(mac_tx_oversize_pkt_num), 185cb7b6606SZiyang Xuan HINIC_PORT_STAT(mac_trans_jabber_pkt_num), 186cb7b6606SZiyang Xuan HINIC_PORT_STAT(mac_tx_mac_pause_num), 187cb7b6606SZiyang Xuan HINIC_PORT_STAT(mac_tx_pfc_pkt_num), 188cb7b6606SZiyang Xuan HINIC_PORT_STAT(mac_tx_pfc_pri0_pkt_num), 189cb7b6606SZiyang Xuan HINIC_PORT_STAT(mac_tx_pfc_pri1_pkt_num), 190cb7b6606SZiyang Xuan HINIC_PORT_STAT(mac_tx_pfc_pri2_pkt_num), 191cb7b6606SZiyang Xuan HINIC_PORT_STAT(mac_tx_pfc_pri3_pkt_num), 192cb7b6606SZiyang Xuan HINIC_PORT_STAT(mac_tx_pfc_pri4_pkt_num), 193cb7b6606SZiyang Xuan HINIC_PORT_STAT(mac_tx_pfc_pri5_pkt_num), 194cb7b6606SZiyang Xuan HINIC_PORT_STAT(mac_tx_pfc_pri6_pkt_num), 195cb7b6606SZiyang Xuan HINIC_PORT_STAT(mac_tx_pfc_pri7_pkt_num), 196cb7b6606SZiyang Xuan HINIC_PORT_STAT(mac_tx_mac_control_pkt_num), 197cb7b6606SZiyang Xuan HINIC_PORT_STAT(mac_tx_err_all_pkt_num), 198cb7b6606SZiyang Xuan HINIC_PORT_STAT(mac_tx_from_app_good_pkt_num), 199cb7b6606SZiyang Xuan HINIC_PORT_STAT(mac_tx_from_app_bad_pkt_num), 200cb7b6606SZiyang Xuan }; 201cb7b6606SZiyang Xuan 202cb7b6606SZiyang Xuan #define HINIC_PHYPORT_XSTATS_NUM (sizeof(hinic_phyport_stats_strings) / \ 203cb7b6606SZiyang Xuan sizeof(hinic_phyport_stats_strings[0])) 204cb7b6606SZiyang Xuan 205cb7b6606SZiyang Xuan static const struct hinic_xstats_name_off hinic_rxq_stats_strings[] = { 206cb7b6606SZiyang Xuan {"rx_nombuf", offsetof(struct hinic_rxq_stats, rx_nombuf)}, 207cb7b6606SZiyang Xuan {"burst_pkt", offsetof(struct hinic_rxq_stats, burst_pkts)}, 208cb7b6606SZiyang Xuan }; 209cb7b6606SZiyang Xuan 210cb7b6606SZiyang Xuan #define HINIC_RXQ_XSTATS_NUM (sizeof(hinic_rxq_stats_strings) / \ 211cb7b6606SZiyang Xuan sizeof(hinic_rxq_stats_strings[0])) 212cb7b6606SZiyang Xuan 213cb7b6606SZiyang Xuan static const struct hinic_xstats_name_off hinic_txq_stats_strings[] = { 214cb7b6606SZiyang Xuan {"tx_busy", offsetof(struct hinic_txq_stats, tx_busy)}, 215cb7b6606SZiyang Xuan {"offload_errors", offsetof(struct hinic_txq_stats, off_errs)}, 216cb7b6606SZiyang Xuan {"copy_pkts", offsetof(struct hinic_txq_stats, cpy_pkts)}, 217cb7b6606SZiyang Xuan {"rl_drop", offsetof(struct hinic_txq_stats, rl_drop)}, 218cb7b6606SZiyang Xuan {"burst_pkts", offsetof(struct hinic_txq_stats, burst_pkts)}, 21954faba22SXiaoyun Wang {"sge_len0", offsetof(struct hinic_txq_stats, sge_len0)}, 22054faba22SXiaoyun Wang {"mbuf_null", offsetof(struct hinic_txq_stats, mbuf_null)}, 221cb7b6606SZiyang Xuan }; 222cb7b6606SZiyang Xuan 223cb7b6606SZiyang Xuan #define HINIC_TXQ_XSTATS_NUM (sizeof(hinic_txq_stats_strings) / \ 224cb7b6606SZiyang Xuan sizeof(hinic_txq_stats_strings[0])) 225cb7b6606SZiyang Xuan 226cb7b6606SZiyang Xuan static int hinic_xstats_calc_num(struct hinic_nic_dev *nic_dev) 227cb7b6606SZiyang Xuan { 2286691acefSXiaoyun Wang if (HINIC_IS_VF(nic_dev->hwdev)) { 2296691acefSXiaoyun Wang return (HINIC_VPORT_XSTATS_NUM + 2306691acefSXiaoyun Wang HINIC_RXQ_XSTATS_NUM * nic_dev->num_rq + 2316691acefSXiaoyun Wang HINIC_TXQ_XSTATS_NUM * nic_dev->num_sq); 2326691acefSXiaoyun Wang } else { 233cb7b6606SZiyang Xuan return (HINIC_VPORT_XSTATS_NUM + 234cb7b6606SZiyang Xuan HINIC_PHYPORT_XSTATS_NUM + 235cb7b6606SZiyang Xuan HINIC_RXQ_XSTATS_NUM * nic_dev->num_rq + 236cb7b6606SZiyang Xuan HINIC_TXQ_XSTATS_NUM * nic_dev->num_sq); 237cb7b6606SZiyang Xuan } 2386691acefSXiaoyun Wang } 239cb7b6606SZiyang Xuan 2401d09792aSZiyang Xuan static const struct rte_eth_desc_lim hinic_rx_desc_lim = { 2411d09792aSZiyang Xuan .nb_max = HINIC_MAX_QUEUE_DEPTH, 2421d09792aSZiyang Xuan .nb_min = HINIC_MIN_QUEUE_DEPTH, 2431d09792aSZiyang Xuan .nb_align = HINIC_RXD_ALIGN, 2441d09792aSZiyang Xuan }; 2451d09792aSZiyang Xuan 2461d09792aSZiyang Xuan static const struct rte_eth_desc_lim hinic_tx_desc_lim = { 2471d09792aSZiyang Xuan .nb_max = HINIC_MAX_QUEUE_DEPTH, 2481d09792aSZiyang Xuan .nb_min = HINIC_MIN_QUEUE_DEPTH, 2491d09792aSZiyang Xuan .nb_align = HINIC_TXD_ALIGN, 2501d09792aSZiyang Xuan }; 2511d09792aSZiyang Xuan 252fdba3bf1SXiaoyun Wang static int hinic_vlan_offload_set(struct rte_eth_dev *dev, int mask); 2532c473729SZiyang Xuan 2541d09792aSZiyang Xuan /** 25564727024SZiyang Xuan * Interrupt handler triggered by NIC for handling 25664727024SZiyang Xuan * specific event. 25764727024SZiyang Xuan * 2587be78d02SJosh Soref * @param: The address of parameter (struct rte_eth_dev *) registered before. 259c3ba1f0fSXiaoyun Wang */ 26064727024SZiyang Xuan static void hinic_dev_interrupt_handler(void *param) 26164727024SZiyang Xuan { 26264727024SZiyang Xuan struct rte_eth_dev *dev = param; 26364727024SZiyang Xuan struct hinic_nic_dev *nic_dev = HINIC_ETH_DEV_TO_PRIVATE_NIC_DEV(dev); 26464727024SZiyang Xuan 2650371535dSJoyce Kong if (!rte_bit_relaxed_get32(HINIC_DEV_INTR_EN, &nic_dev->dev_status)) { 26664727024SZiyang Xuan PMD_DRV_LOG(WARNING, "Device's interrupt is disabled, ignore interrupt event, dev_name: %s, port_id: %d", 26764727024SZiyang Xuan nic_dev->proc_dev_name, dev->data->port_id); 26864727024SZiyang Xuan return; 26964727024SZiyang Xuan } 27064727024SZiyang Xuan 27164727024SZiyang Xuan /* aeq0 msg handler */ 27264727024SZiyang Xuan hinic_dev_handle_aeq_event(nic_dev->hwdev, param); 27364727024SZiyang Xuan } 27464727024SZiyang Xuan 27564727024SZiyang Xuan /** 27664727024SZiyang Xuan * Ethernet device configuration. 27764727024SZiyang Xuan * 27864727024SZiyang Xuan * Prepare the driver for a given number of TX and RX queues, mtu size 27964727024SZiyang Xuan * and configure RSS. 28064727024SZiyang Xuan * 28164727024SZiyang Xuan * @param dev 28264727024SZiyang Xuan * Pointer to Ethernet device structure. 28364727024SZiyang Xuan * 28464727024SZiyang Xuan * @return 28564727024SZiyang Xuan * 0 on success, negative error value otherwise. 28664727024SZiyang Xuan */ 28764727024SZiyang Xuan static int hinic_dev_configure(struct rte_eth_dev *dev) 28864727024SZiyang Xuan { 28964727024SZiyang Xuan struct hinic_nic_dev *nic_dev; 29064727024SZiyang Xuan struct hinic_nic_io *nic_io; 29164727024SZiyang Xuan int err; 29264727024SZiyang Xuan 29364727024SZiyang Xuan nic_dev = HINIC_ETH_DEV_TO_PRIVATE_NIC_DEV(dev); 29464727024SZiyang Xuan nic_io = nic_dev->hwdev->nic_io; 29564727024SZiyang Xuan 29664727024SZiyang Xuan nic_dev->num_sq = dev->data->nb_tx_queues; 29764727024SZiyang Xuan nic_dev->num_rq = dev->data->nb_rx_queues; 29864727024SZiyang Xuan 29964727024SZiyang Xuan nic_io->num_sqs = dev->data->nb_tx_queues; 30064727024SZiyang Xuan nic_io->num_rqs = dev->data->nb_rx_queues; 30164727024SZiyang Xuan 30264727024SZiyang Xuan /* queue pair is max_num(sq, rq) */ 30364727024SZiyang Xuan nic_dev->num_qps = (nic_dev->num_sq > nic_dev->num_rq) ? 30464727024SZiyang Xuan nic_dev->num_sq : nic_dev->num_rq; 30564727024SZiyang Xuan nic_io->num_qps = nic_dev->num_qps; 30664727024SZiyang Xuan 30764727024SZiyang Xuan if (nic_dev->num_qps > nic_io->max_qps) { 30864727024SZiyang Xuan PMD_DRV_LOG(ERR, 30964727024SZiyang Xuan "Queue number out of range, get queue_num:%d, max_queue_num:%d", 31064727024SZiyang Xuan nic_dev->num_qps, nic_io->max_qps); 31164727024SZiyang Xuan return -EINVAL; 31264727024SZiyang Xuan } 31364727024SZiyang Xuan 314295968d1SFerruh Yigit if (dev->data->dev_conf.rxmode.mq_mode & RTE_ETH_MQ_RX_RSS_FLAG) 315295968d1SFerruh Yigit dev->data->dev_conf.rxmode.offloads |= RTE_ETH_RX_OFFLOAD_RSS_HASH; 3168b945a7fSPavan Nikhilesh 31764727024SZiyang Xuan /* mtu size is 256~9600 */ 3181bb4a528SFerruh Yigit if (HINIC_MTU_TO_PKTLEN(dev->data->dev_conf.rxmode.mtu) < 3191bb4a528SFerruh Yigit HINIC_MIN_FRAME_SIZE || 3201bb4a528SFerruh Yigit HINIC_MTU_TO_PKTLEN(dev->data->dev_conf.rxmode.mtu) > 32164727024SZiyang Xuan HINIC_MAX_JUMBO_FRAME_SIZE) { 32264727024SZiyang Xuan PMD_DRV_LOG(ERR, 3231bb4a528SFerruh Yigit "Packet length out of range, get packet length:%d, " 32464727024SZiyang Xuan "expect between %d and %d", 3251bb4a528SFerruh Yigit HINIC_MTU_TO_PKTLEN(dev->data->dev_conf.rxmode.mtu), 32664727024SZiyang Xuan HINIC_MIN_FRAME_SIZE, HINIC_MAX_JUMBO_FRAME_SIZE); 32764727024SZiyang Xuan return -EINVAL; 32864727024SZiyang Xuan } 32964727024SZiyang Xuan 3301bb4a528SFerruh Yigit nic_dev->mtu_size = dev->data->dev_conf.rxmode.mtu; 33164727024SZiyang Xuan 33264727024SZiyang Xuan /* rss template */ 33364727024SZiyang Xuan err = hinic_config_mq_mode(dev, TRUE); 33464727024SZiyang Xuan if (err) { 33564727024SZiyang Xuan PMD_DRV_LOG(ERR, "Config multi-queue failed"); 33664727024SZiyang Xuan return err; 33764727024SZiyang Xuan } 33864727024SZiyang Xuan 3397be78d02SJosh Soref /* init VLAN offload */ 340fdba3bf1SXiaoyun Wang err = hinic_vlan_offload_set(dev, 341295968d1SFerruh Yigit RTE_ETH_VLAN_STRIP_MASK | RTE_ETH_VLAN_FILTER_MASK); 342fdba3bf1SXiaoyun Wang if (err) { 3434f1af3cbSXiaoyun Wang PMD_DRV_LOG(ERR, "Initialize vlan filter and strip failed"); 344fdba3bf1SXiaoyun Wang (void)hinic_config_mq_mode(dev, FALSE); 345fdba3bf1SXiaoyun Wang return err; 346fdba3bf1SXiaoyun Wang } 347fdba3bf1SXiaoyun Wang 3481742421bSXiaoyun Wang /* clear fdir filter flag in function table */ 3491742421bSXiaoyun Wang hinic_free_fdir_filter(nic_dev); 3501742421bSXiaoyun Wang 35164727024SZiyang Xuan return HINIC_OK; 35264727024SZiyang Xuan } 35364727024SZiyang Xuan 35464727024SZiyang Xuan /** 3552c473729SZiyang Xuan * DPDK callback to create the receive queue. 3562c473729SZiyang Xuan * 3572c473729SZiyang Xuan * @param dev 3582c473729SZiyang Xuan * Pointer to Ethernet device structure. 3592c473729SZiyang Xuan * @param queue_idx 3602c473729SZiyang Xuan * RX queue index. 3612c473729SZiyang Xuan * @param nb_desc 3622c473729SZiyang Xuan * Number of descriptors for receive queue. 3632c473729SZiyang Xuan * @param socket_id 3642c473729SZiyang Xuan * NUMA socket on which memory must be allocated. 3652c473729SZiyang Xuan * @param rx_conf 3662c473729SZiyang Xuan * Thresholds parameters (unused_). 3672c473729SZiyang Xuan * @param mp 3682c473729SZiyang Xuan * Memory pool for buffer allocations. 3692c473729SZiyang Xuan * 3702c473729SZiyang Xuan * @return 3712c473729SZiyang Xuan * 0 on success, negative error value otherwise. 3722c473729SZiyang Xuan */ 3732c473729SZiyang Xuan static int hinic_rx_queue_setup(struct rte_eth_dev *dev, uint16_t queue_idx, 3742c473729SZiyang Xuan uint16_t nb_desc, unsigned int socket_id, 3752c473729SZiyang Xuan __rte_unused const struct rte_eth_rxconf *rx_conf, 3762c473729SZiyang Xuan struct rte_mempool *mp) 3772c473729SZiyang Xuan { 3782c473729SZiyang Xuan int rc; 3792c473729SZiyang Xuan struct hinic_nic_dev *nic_dev; 3802c473729SZiyang Xuan struct hinic_hwdev *hwdev; 3812c473729SZiyang Xuan struct hinic_rxq *rxq; 3822c473729SZiyang Xuan u16 rq_depth, rx_free_thresh; 3832c473729SZiyang Xuan u32 buf_size; 3842c473729SZiyang Xuan 3852c473729SZiyang Xuan nic_dev = HINIC_ETH_DEV_TO_PRIVATE_NIC_DEV(dev); 3862c473729SZiyang Xuan hwdev = nic_dev->hwdev; 3872c473729SZiyang Xuan 3882c473729SZiyang Xuan /* queue depth must be power of 2, otherwise will be aligned up */ 3892c473729SZiyang Xuan rq_depth = (nb_desc & (nb_desc - 1)) ? 3902c473729SZiyang Xuan ((u16)(1U << (ilog2(nb_desc) + 1))) : nb_desc; 3912c473729SZiyang Xuan 3922c473729SZiyang Xuan /* 3932c473729SZiyang Xuan * Validate number of receive descriptors. 3942c473729SZiyang Xuan * It must not exceed hardware maximum and minimum. 3952c473729SZiyang Xuan */ 3962c473729SZiyang Xuan if (rq_depth > HINIC_MAX_QUEUE_DEPTH || 3972c473729SZiyang Xuan rq_depth < HINIC_MIN_QUEUE_DEPTH) { 3982c473729SZiyang 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)", 3992c473729SZiyang Xuan HINIC_MIN_QUEUE_DEPTH, HINIC_MAX_QUEUE_DEPTH, 4002c473729SZiyang Xuan (int)nb_desc, (int)rq_depth, 4012c473729SZiyang Xuan (int)dev->data->port_id, (int)queue_idx); 4022c473729SZiyang Xuan return -EINVAL; 4032c473729SZiyang Xuan } 4042c473729SZiyang Xuan 4052c473729SZiyang Xuan /* 4062c473729SZiyang Xuan * The RX descriptor ring will be cleaned after rxq->rx_free_thresh 4072c473729SZiyang Xuan * descriptors are used or if the number of descriptors required 4082c473729SZiyang Xuan * to transmit a packet is greater than the number of free RX 4092c473729SZiyang Xuan * descriptors. 4102c473729SZiyang Xuan * The following constraints must be satisfied: 4112c473729SZiyang Xuan * rx_free_thresh must be greater than 0. 4122c473729SZiyang Xuan * rx_free_thresh must be less than the size of the ring minus 1. 4132c473729SZiyang Xuan * When set to zero use default values. 4142c473729SZiyang Xuan */ 4152c473729SZiyang Xuan rx_free_thresh = (u16)((rx_conf->rx_free_thresh) ? 4162c473729SZiyang Xuan rx_conf->rx_free_thresh : HINIC_DEFAULT_RX_FREE_THRESH); 4172c473729SZiyang Xuan if (rx_free_thresh >= (rq_depth - 1)) { 4182c473729SZiyang 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)", 4192c473729SZiyang Xuan (unsigned int)rx_free_thresh, 4202c473729SZiyang Xuan (int)dev->data->port_id, 4212c473729SZiyang Xuan (int)queue_idx); 4222c473729SZiyang Xuan return -EINVAL; 4232c473729SZiyang Xuan } 4242c473729SZiyang Xuan 4252c473729SZiyang Xuan rxq = rte_zmalloc_socket("hinic_rx_queue", sizeof(struct hinic_rxq), 4262c473729SZiyang Xuan RTE_CACHE_LINE_SIZE, socket_id); 4272c473729SZiyang Xuan if (!rxq) { 4282c473729SZiyang Xuan PMD_DRV_LOG(ERR, "Allocate rxq[%d] failed, dev_name: %s", 4292c473729SZiyang Xuan queue_idx, dev->data->name); 4302c473729SZiyang Xuan return -ENOMEM; 4312c473729SZiyang Xuan } 4322c473729SZiyang Xuan nic_dev->rxqs[queue_idx] = rxq; 4332c473729SZiyang Xuan 4342c473729SZiyang Xuan /* alloc rx sq hw wqe page */ 4351b7b9f17SXiaoyun Wang rc = hinic_create_rq(hwdev, queue_idx, rq_depth, socket_id); 4362c473729SZiyang Xuan if (rc) { 4372c473729SZiyang Xuan PMD_DRV_LOG(ERR, "Create rxq[%d] failed, dev_name: %s, rq_depth: %d", 4382c473729SZiyang Xuan queue_idx, dev->data->name, rq_depth); 4392c473729SZiyang Xuan goto ceate_rq_fail; 4402c473729SZiyang Xuan } 4412c473729SZiyang Xuan 4422c473729SZiyang Xuan /* mbuf pool must be assigned before setup rx resources */ 4432c473729SZiyang Xuan rxq->mb_pool = mp; 4442c473729SZiyang Xuan 4452c473729SZiyang Xuan rc = 4462c473729SZiyang Xuan hinic_convert_rx_buf_size(rte_pktmbuf_data_room_size(rxq->mb_pool) - 4472c473729SZiyang Xuan RTE_PKTMBUF_HEADROOM, &buf_size); 4482c473729SZiyang Xuan if (rc) { 4492c473729SZiyang Xuan PMD_DRV_LOG(ERR, "Adjust buf size failed, dev_name: %s", 4502c473729SZiyang Xuan dev->data->name); 4512c473729SZiyang Xuan goto adjust_bufsize_fail; 4522c473729SZiyang Xuan } 4532c473729SZiyang Xuan 4542c473729SZiyang Xuan /* rx queue info, rearm control */ 4552c473729SZiyang Xuan rxq->wq = &hwdev->nic_io->rq_wq[queue_idx]; 4562c473729SZiyang Xuan rxq->pi_virt_addr = hwdev->nic_io->qps[queue_idx].rq.pi_virt_addr; 4572c473729SZiyang Xuan rxq->nic_dev = nic_dev; 4582c473729SZiyang Xuan rxq->q_id = queue_idx; 4592c473729SZiyang Xuan rxq->q_depth = rq_depth; 4602c473729SZiyang Xuan rxq->buf_len = (u16)buf_size; 4612c473729SZiyang Xuan rxq->rx_free_thresh = rx_free_thresh; 4621b7b9f17SXiaoyun Wang rxq->socket_id = socket_id; 4632c473729SZiyang Xuan 4642c473729SZiyang Xuan /* the last point cant do mbuf rearm in bulk */ 4652c473729SZiyang Xuan rxq->rxinfo_align_end = rxq->q_depth - rxq->rx_free_thresh; 4662c473729SZiyang Xuan 4672c473729SZiyang Xuan /* device port identifier */ 4682c473729SZiyang Xuan rxq->port_id = dev->data->port_id; 4692c473729SZiyang Xuan 4702c473729SZiyang Xuan /* alloc rx_cqe and prepare rq_wqe */ 4712c473729SZiyang Xuan rc = hinic_setup_rx_resources(rxq); 4722c473729SZiyang Xuan if (rc) { 4732c473729SZiyang Xuan PMD_DRV_LOG(ERR, "Setup rxq[%d] rx_resources failed, dev_name: %s", 4742c473729SZiyang Xuan queue_idx, dev->data->name); 4752c473729SZiyang Xuan goto setup_rx_res_err; 4762c473729SZiyang Xuan } 4772c473729SZiyang Xuan 4782c473729SZiyang Xuan /* record nic_dev rxq in rte_eth rx_queues */ 4792c473729SZiyang Xuan dev->data->rx_queues[queue_idx] = rxq; 4802c473729SZiyang Xuan 4812c473729SZiyang Xuan return 0; 4822c473729SZiyang Xuan 4832c473729SZiyang Xuan setup_rx_res_err: 4842c473729SZiyang Xuan adjust_bufsize_fail: 4852c473729SZiyang Xuan hinic_destroy_rq(hwdev, queue_idx); 4862c473729SZiyang Xuan 4872c473729SZiyang Xuan ceate_rq_fail: 4882c473729SZiyang Xuan rte_free(rxq); 4892c473729SZiyang Xuan 4902c473729SZiyang Xuan return rc; 4912c473729SZiyang Xuan } 4922c473729SZiyang Xuan 4932c473729SZiyang Xuan static void hinic_reset_rx_queue(struct rte_eth_dev *dev) 4942c473729SZiyang Xuan { 4952c473729SZiyang Xuan struct hinic_rxq *rxq; 4962c473729SZiyang Xuan struct hinic_nic_dev *nic_dev; 4972c473729SZiyang Xuan int q_id = 0; 4982c473729SZiyang Xuan 4992c473729SZiyang Xuan nic_dev = HINIC_ETH_DEV_TO_PRIVATE_NIC_DEV(dev); 5002c473729SZiyang Xuan 5012c473729SZiyang Xuan for (q_id = 0; q_id < nic_dev->num_rq; q_id++) { 5022c473729SZiyang Xuan rxq = dev->data->rx_queues[q_id]; 5032c473729SZiyang Xuan 5042c473729SZiyang Xuan rxq->wq->cons_idx = 0; 5052c473729SZiyang Xuan rxq->wq->prod_idx = 0; 5062c473729SZiyang Xuan rxq->wq->delta = rxq->q_depth; 5072c473729SZiyang Xuan rxq->wq->mask = rxq->q_depth - 1; 5082c473729SZiyang Xuan 5092c473729SZiyang Xuan /* alloc mbuf to rq */ 5102c473729SZiyang Xuan hinic_rx_alloc_pkts(rxq); 5112c473729SZiyang Xuan } 5122c473729SZiyang Xuan } 5132c473729SZiyang Xuan 5142c473729SZiyang Xuan /** 5152c473729SZiyang Xuan * DPDK callback to configure the transmit queue. 5162c473729SZiyang Xuan * 5172c473729SZiyang Xuan * @param dev 5182c473729SZiyang Xuan * Pointer to Ethernet device structure. 5192c473729SZiyang Xuan * @param queue_idx 5202c473729SZiyang Xuan * Transmit queue index. 5212c473729SZiyang Xuan * @param nb_desc 5222c473729SZiyang Xuan * Number of descriptors for transmit queue. 5232c473729SZiyang Xuan * @param socket_id 5242c473729SZiyang Xuan * NUMA socket on which memory must be allocated. 5252c473729SZiyang Xuan * @param tx_conf 5262c473729SZiyang Xuan * Tx queue configuration parameters. 5272c473729SZiyang Xuan * 5282c473729SZiyang Xuan * @return 5292c473729SZiyang Xuan * 0 on success, negative error value otherwise. 5302c473729SZiyang Xuan */ 5312c473729SZiyang Xuan static int hinic_tx_queue_setup(struct rte_eth_dev *dev, uint16_t queue_idx, 5322c473729SZiyang Xuan uint16_t nb_desc, unsigned int socket_id, 5332c473729SZiyang Xuan __rte_unused const struct rte_eth_txconf *tx_conf) 5342c473729SZiyang Xuan { 5352c473729SZiyang Xuan int rc; 5362c473729SZiyang Xuan struct hinic_nic_dev *nic_dev; 5372c473729SZiyang Xuan struct hinic_hwdev *hwdev; 5382c473729SZiyang Xuan struct hinic_txq *txq; 5392c473729SZiyang Xuan u16 sq_depth, tx_free_thresh; 5402c473729SZiyang Xuan 5412c473729SZiyang Xuan nic_dev = HINIC_ETH_DEV_TO_PRIVATE_NIC_DEV(dev); 5422c473729SZiyang Xuan hwdev = nic_dev->hwdev; 5432c473729SZiyang Xuan 5442c473729SZiyang Xuan /* queue depth must be power of 2, otherwise will be aligned up */ 5452c473729SZiyang Xuan sq_depth = (nb_desc & (nb_desc - 1)) ? 5462c473729SZiyang Xuan ((u16)(1U << (ilog2(nb_desc) + 1))) : nb_desc; 5472c473729SZiyang Xuan 5482c473729SZiyang Xuan /* 5492c473729SZiyang Xuan * Validate number of transmit descriptors. 5502c473729SZiyang Xuan * It must not exceed hardware maximum and minimum. 5512c473729SZiyang Xuan */ 5522c473729SZiyang Xuan if (sq_depth > HINIC_MAX_QUEUE_DEPTH || 5532c473729SZiyang Xuan sq_depth < HINIC_MIN_QUEUE_DEPTH) { 5542c473729SZiyang 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)", 5552c473729SZiyang Xuan HINIC_MIN_QUEUE_DEPTH, HINIC_MAX_QUEUE_DEPTH, 5562c473729SZiyang Xuan (int)nb_desc, (int)sq_depth, 5572c473729SZiyang Xuan (int)dev->data->port_id, (int)queue_idx); 5582c473729SZiyang Xuan return -EINVAL; 5592c473729SZiyang Xuan } 5602c473729SZiyang Xuan 5612c473729SZiyang Xuan /* 5622c473729SZiyang Xuan * The TX descriptor ring will be cleaned after txq->tx_free_thresh 5632c473729SZiyang Xuan * descriptors are used or if the number of descriptors required 5642c473729SZiyang Xuan * to transmit a packet is greater than the number of free TX 5652c473729SZiyang Xuan * descriptors. 5662c473729SZiyang Xuan * The following constraints must be satisfied: 5672c473729SZiyang Xuan * tx_free_thresh must be greater than 0. 5682c473729SZiyang Xuan * tx_free_thresh must be less than the size of the ring minus 1. 5692c473729SZiyang Xuan * When set to zero use default values. 5702c473729SZiyang Xuan */ 5712c473729SZiyang Xuan tx_free_thresh = (u16)((tx_conf->tx_free_thresh) ? 5722c473729SZiyang Xuan tx_conf->tx_free_thresh : HINIC_DEFAULT_TX_FREE_THRESH); 5732c473729SZiyang Xuan if (tx_free_thresh >= (sq_depth - 1)) { 5742c473729SZiyang 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)", 5752c473729SZiyang Xuan (unsigned int)tx_free_thresh, (int)dev->data->port_id, 5762c473729SZiyang Xuan (int)queue_idx); 5772c473729SZiyang Xuan return -EINVAL; 5782c473729SZiyang Xuan } 5792c473729SZiyang Xuan 5802c473729SZiyang Xuan txq = rte_zmalloc_socket("hinic_tx_queue", sizeof(struct hinic_txq), 5812c473729SZiyang Xuan RTE_CACHE_LINE_SIZE, socket_id); 5822c473729SZiyang Xuan if (!txq) { 5832c473729SZiyang Xuan PMD_DRV_LOG(ERR, "Allocate txq[%d] failed, dev_name: %s", 5842c473729SZiyang Xuan queue_idx, dev->data->name); 5852c473729SZiyang Xuan return -ENOMEM; 5862c473729SZiyang Xuan } 5872c473729SZiyang Xuan nic_dev->txqs[queue_idx] = txq; 5882c473729SZiyang Xuan 5892c473729SZiyang Xuan /* alloc tx sq hw wqepage */ 5901b7b9f17SXiaoyun Wang rc = hinic_create_sq(hwdev, queue_idx, sq_depth, socket_id); 5912c473729SZiyang Xuan if (rc) { 5922c473729SZiyang Xuan PMD_DRV_LOG(ERR, "Create txq[%d] failed, dev_name: %s, sq_depth: %d", 5932c473729SZiyang Xuan queue_idx, dev->data->name, sq_depth); 5942c473729SZiyang Xuan goto create_sq_fail; 5952c473729SZiyang Xuan } 5962c473729SZiyang Xuan 5972c473729SZiyang Xuan txq->q_id = queue_idx; 5982c473729SZiyang Xuan txq->q_depth = sq_depth; 5992c473729SZiyang Xuan txq->port_id = dev->data->port_id; 6002c473729SZiyang Xuan txq->tx_free_thresh = tx_free_thresh; 6012c473729SZiyang Xuan txq->nic_dev = nic_dev; 6022c473729SZiyang Xuan txq->wq = &hwdev->nic_io->sq_wq[queue_idx]; 6032c473729SZiyang Xuan txq->sq = &hwdev->nic_io->qps[queue_idx].sq; 6042c473729SZiyang Xuan txq->cons_idx_addr = hwdev->nic_io->qps[queue_idx].sq.cons_idx_addr; 6052c473729SZiyang Xuan txq->sq_head_addr = HINIC_GET_WQ_HEAD(txq); 6062c473729SZiyang Xuan txq->sq_bot_sge_addr = HINIC_GET_WQ_TAIL(txq) - 6072c473729SZiyang Xuan sizeof(struct hinic_sq_bufdesc); 6082c473729SZiyang Xuan txq->cos = nic_dev->default_cos; 6091b7b9f17SXiaoyun Wang txq->socket_id = socket_id; 6102c473729SZiyang Xuan 6112c473729SZiyang Xuan /* alloc software txinfo */ 6122c473729SZiyang Xuan rc = hinic_setup_tx_resources(txq); 6132c473729SZiyang Xuan if (rc) { 6142c473729SZiyang Xuan PMD_DRV_LOG(ERR, "Setup txq[%d] tx_resources failed, dev_name: %s", 6152c473729SZiyang Xuan queue_idx, dev->data->name); 6162c473729SZiyang Xuan goto setup_tx_res_fail; 6172c473729SZiyang Xuan } 6182c473729SZiyang Xuan 6192c473729SZiyang Xuan /* record nic_dev txq in rte_eth tx_queues */ 6202c473729SZiyang Xuan dev->data->tx_queues[queue_idx] = txq; 6212c473729SZiyang Xuan 6222c473729SZiyang Xuan return HINIC_OK; 6232c473729SZiyang Xuan 6242c473729SZiyang Xuan setup_tx_res_fail: 6252c473729SZiyang Xuan hinic_destroy_sq(hwdev, queue_idx); 6262c473729SZiyang Xuan 6272c473729SZiyang Xuan create_sq_fail: 6282c473729SZiyang Xuan rte_free(txq); 6292c473729SZiyang Xuan 6302c473729SZiyang Xuan return rc; 6312c473729SZiyang Xuan } 6322c473729SZiyang Xuan 6332c473729SZiyang Xuan static void hinic_reset_tx_queue(struct rte_eth_dev *dev) 6342c473729SZiyang Xuan { 6352c473729SZiyang Xuan struct hinic_nic_dev *nic_dev; 6362c473729SZiyang Xuan struct hinic_txq *txq; 6372c473729SZiyang Xuan struct hinic_nic_io *nic_io; 6382c473729SZiyang Xuan struct hinic_hwdev *hwdev; 6392c473729SZiyang Xuan volatile u32 *ci_addr; 6402c473729SZiyang Xuan int q_id = 0; 6412c473729SZiyang Xuan 6422c473729SZiyang Xuan nic_dev = HINIC_ETH_DEV_TO_PRIVATE_NIC_DEV(dev); 6432c473729SZiyang Xuan hwdev = nic_dev->hwdev; 6442c473729SZiyang Xuan nic_io = hwdev->nic_io; 6452c473729SZiyang Xuan 6462c473729SZiyang Xuan for (q_id = 0; q_id < nic_dev->num_sq; q_id++) { 6472c473729SZiyang Xuan txq = dev->data->tx_queues[q_id]; 6482c473729SZiyang Xuan 6492c473729SZiyang Xuan txq->wq->cons_idx = 0; 6502c473729SZiyang Xuan txq->wq->prod_idx = 0; 6512c473729SZiyang Xuan txq->wq->delta = txq->q_depth; 6522c473729SZiyang Xuan txq->wq->mask = txq->q_depth - 1; 6532c473729SZiyang Xuan 6542c473729SZiyang Xuan /* clear hardware ci */ 6552c473729SZiyang Xuan ci_addr = (volatile u32 *)HINIC_CI_VADDR(nic_io->ci_vaddr_base, 6562c473729SZiyang Xuan q_id); 6572c473729SZiyang Xuan *ci_addr = 0; 6582c473729SZiyang Xuan } 6592c473729SZiyang Xuan } 6602c473729SZiyang Xuan 6612c473729SZiyang Xuan /** 6621d09792aSZiyang Xuan * Get link speed from NIC. 6631d09792aSZiyang Xuan * 6641d09792aSZiyang Xuan * @param dev 6651d09792aSZiyang Xuan * Pointer to Ethernet device structure. 6661d09792aSZiyang Xuan * @param speed_capa 6671d09792aSZiyang Xuan * Pointer to link speed structure. 6681d09792aSZiyang Xuan */ 6691d09792aSZiyang Xuan static void hinic_get_speed_capa(struct rte_eth_dev *dev, uint32_t *speed_capa) 6701d09792aSZiyang Xuan { 6711d09792aSZiyang Xuan struct hinic_nic_dev *nic_dev = HINIC_ETH_DEV_TO_PRIVATE_NIC_DEV(dev); 6721d09792aSZiyang Xuan u32 supported_link, advertised_link; 6731d09792aSZiyang Xuan int err; 6741d09792aSZiyang Xuan 6751d09792aSZiyang Xuan #define HINIC_LINK_MODE_SUPPORT_1G (1U << HINIC_GE_BASE_KX) 6761d09792aSZiyang Xuan 6771d09792aSZiyang Xuan #define HINIC_LINK_MODE_SUPPORT_10G (1U << HINIC_10GE_BASE_KR) 6781d09792aSZiyang Xuan 6791d09792aSZiyang Xuan #define HINIC_LINK_MODE_SUPPORT_25G ((1U << HINIC_25GE_BASE_KR_S) | \ 6801d09792aSZiyang Xuan (1U << HINIC_25GE_BASE_CR_S) | \ 6811d09792aSZiyang Xuan (1U << HINIC_25GE_BASE_KR) | \ 6821d09792aSZiyang Xuan (1U << HINIC_25GE_BASE_CR)) 6831d09792aSZiyang Xuan 6841d09792aSZiyang Xuan #define HINIC_LINK_MODE_SUPPORT_40G ((1U << HINIC_40GE_BASE_KR4) | \ 6851d09792aSZiyang Xuan (1U << HINIC_40GE_BASE_CR4)) 6861d09792aSZiyang Xuan 6871d09792aSZiyang Xuan #define HINIC_LINK_MODE_SUPPORT_100G ((1U << HINIC_100GE_BASE_KR4) | \ 6881d09792aSZiyang Xuan (1U << HINIC_100GE_BASE_CR4)) 6891d09792aSZiyang Xuan 6901d09792aSZiyang Xuan err = hinic_get_link_mode(nic_dev->hwdev, 6911d09792aSZiyang Xuan &supported_link, &advertised_link); 6921d09792aSZiyang Xuan if (err || supported_link == HINIC_SUPPORTED_UNKNOWN || 6931d09792aSZiyang Xuan advertised_link == HINIC_SUPPORTED_UNKNOWN) { 6941d09792aSZiyang Xuan PMD_DRV_LOG(WARNING, "Get speed capability info failed, device: %s, port_id: %u", 6951d09792aSZiyang Xuan nic_dev->proc_dev_name, dev->data->port_id); 6961d09792aSZiyang Xuan } else { 6971d09792aSZiyang Xuan *speed_capa = 0; 6981d09792aSZiyang Xuan if (!!(supported_link & HINIC_LINK_MODE_SUPPORT_1G)) 699295968d1SFerruh Yigit *speed_capa |= RTE_ETH_LINK_SPEED_1G; 7001d09792aSZiyang Xuan if (!!(supported_link & HINIC_LINK_MODE_SUPPORT_10G)) 701295968d1SFerruh Yigit *speed_capa |= RTE_ETH_LINK_SPEED_10G; 7021d09792aSZiyang Xuan if (!!(supported_link & HINIC_LINK_MODE_SUPPORT_25G)) 703295968d1SFerruh Yigit *speed_capa |= RTE_ETH_LINK_SPEED_25G; 7041d09792aSZiyang Xuan if (!!(supported_link & HINIC_LINK_MODE_SUPPORT_40G)) 705295968d1SFerruh Yigit *speed_capa |= RTE_ETH_LINK_SPEED_40G; 7061d09792aSZiyang Xuan if (!!(supported_link & HINIC_LINK_MODE_SUPPORT_100G)) 707295968d1SFerruh Yigit *speed_capa |= RTE_ETH_LINK_SPEED_100G; 7081d09792aSZiyang Xuan } 7091d09792aSZiyang Xuan } 7101d09792aSZiyang Xuan 7111d09792aSZiyang Xuan /** 7121d09792aSZiyang Xuan * DPDK callback to get information about the device. 7131d09792aSZiyang Xuan * 7141d09792aSZiyang Xuan * @param dev 7151d09792aSZiyang Xuan * Pointer to Ethernet device structure. 7161d09792aSZiyang Xuan * @param info 7171d09792aSZiyang Xuan * Pointer to Info structure output buffer. 7181d09792aSZiyang Xuan */ 719bdad90d1SIvan Ilchenko static int 7201d09792aSZiyang Xuan hinic_dev_infos_get(struct rte_eth_dev *dev, struct rte_eth_dev_info *info) 7211d09792aSZiyang Xuan { 7221d09792aSZiyang Xuan struct hinic_nic_dev *nic_dev = HINIC_ETH_DEV_TO_PRIVATE_NIC_DEV(dev); 7231d09792aSZiyang Xuan 7241d09792aSZiyang Xuan info->max_rx_queues = nic_dev->nic_cap.max_rqs; 7251d09792aSZiyang Xuan info->max_tx_queues = nic_dev->nic_cap.max_sqs; 7261d09792aSZiyang Xuan info->min_rx_bufsize = HINIC_MIN_RX_BUF_SIZE; 7271d09792aSZiyang Xuan info->max_rx_pktlen = HINIC_MAX_JUMBO_FRAME_SIZE; 72800499a22SXiaoyun Wang info->max_mac_addrs = HINIC_MAX_UC_MAC_ADDRS; 7298260eba6SXiaoyun Wang info->min_mtu = HINIC_MIN_MTU_SIZE; 7308260eba6SXiaoyun Wang info->max_mtu = HINIC_MAX_MTU_SIZE; 7319d02f40dSXiaoyun Wang info->max_lro_pkt_size = HINIC_MAX_LRO_SIZE; 7321d09792aSZiyang Xuan 7331d09792aSZiyang Xuan hinic_get_speed_capa(dev, &info->speed_capa); 7341d09792aSZiyang Xuan info->rx_queue_offload_capa = 0; 735295968d1SFerruh Yigit info->rx_offload_capa = RTE_ETH_RX_OFFLOAD_VLAN_STRIP | 736295968d1SFerruh Yigit RTE_ETH_RX_OFFLOAD_IPV4_CKSUM | 737295968d1SFerruh Yigit RTE_ETH_RX_OFFLOAD_UDP_CKSUM | 738295968d1SFerruh Yigit RTE_ETH_RX_OFFLOAD_TCP_CKSUM | 739295968d1SFerruh Yigit RTE_ETH_RX_OFFLOAD_VLAN_FILTER | 740295968d1SFerruh Yigit RTE_ETH_RX_OFFLOAD_SCATTER | 741295968d1SFerruh Yigit RTE_ETH_RX_OFFLOAD_TCP_LRO | 742295968d1SFerruh Yigit RTE_ETH_RX_OFFLOAD_RSS_HASH; 7431d09792aSZiyang Xuan 7441d09792aSZiyang Xuan info->tx_queue_offload_capa = 0; 745295968d1SFerruh Yigit info->tx_offload_capa = RTE_ETH_TX_OFFLOAD_VLAN_INSERT | 746295968d1SFerruh Yigit RTE_ETH_TX_OFFLOAD_IPV4_CKSUM | 747295968d1SFerruh Yigit RTE_ETH_TX_OFFLOAD_UDP_CKSUM | 748295968d1SFerruh Yigit RTE_ETH_TX_OFFLOAD_TCP_CKSUM | 749295968d1SFerruh Yigit RTE_ETH_TX_OFFLOAD_SCTP_CKSUM | 750295968d1SFerruh Yigit RTE_ETH_TX_OFFLOAD_OUTER_IPV4_CKSUM | 751295968d1SFerruh Yigit RTE_ETH_TX_OFFLOAD_TCP_TSO | 752295968d1SFerruh Yigit RTE_ETH_TX_OFFLOAD_MULTI_SEGS; 7531d09792aSZiyang Xuan 7542fe6f1b7SDmitry Kozlyuk info->dev_capa &= ~RTE_ETH_DEV_CAPA_FLOW_RULE_KEEP; 7552fe6f1b7SDmitry Kozlyuk 7561d09792aSZiyang Xuan info->hash_key_size = HINIC_RSS_KEY_SIZE; 7571d09792aSZiyang Xuan info->reta_size = HINIC_RSS_INDIR_SIZE; 75864727024SZiyang Xuan info->flow_type_rss_offloads = HINIC_RSS_OFFLOAD_ALL; 7591d09792aSZiyang Xuan info->rx_desc_lim = hinic_rx_desc_lim; 7601d09792aSZiyang Xuan info->tx_desc_lim = hinic_tx_desc_lim; 761bdad90d1SIvan Ilchenko 762483b4817SXiaoyun Wang /* Driver-preferred Rx/Tx parameters */ 763483b4817SXiaoyun Wang info->default_rxportconf.burst_size = HINIC_DEFAULT_BURST_SIZE; 764483b4817SXiaoyun Wang info->default_txportconf.burst_size = HINIC_DEFAULT_BURST_SIZE; 765483b4817SXiaoyun Wang info->default_rxportconf.nb_queues = HINIC_DEFAULT_NB_QUEUES; 766483b4817SXiaoyun Wang info->default_txportconf.nb_queues = HINIC_DEFAULT_NB_QUEUES; 767483b4817SXiaoyun Wang info->default_rxportconf.ring_size = HINIC_DEFAULT_RING_SIZE; 768483b4817SXiaoyun Wang info->default_txportconf.ring_size = HINIC_DEFAULT_RING_SIZE; 769483b4817SXiaoyun Wang 770bdad90d1SIvan Ilchenko return 0; 7711d09792aSZiyang Xuan } 7721d09792aSZiyang Xuan 773dbf524abSXiaoyun Wang static int hinic_fw_version_get(struct rte_eth_dev *dev, char *fw_version, 774dbf524abSXiaoyun Wang size_t fw_size) 775dbf524abSXiaoyun Wang { 776dbf524abSXiaoyun Wang struct hinic_nic_dev *nic_dev = HINIC_ETH_DEV_TO_PRIVATE_NIC_DEV(dev); 777dbf524abSXiaoyun Wang char fw_ver[HINIC_MGMT_VERSION_MAX_LEN] = {0}; 778dbf524abSXiaoyun Wang int err; 779dbf524abSXiaoyun Wang 780dbf524abSXiaoyun Wang err = hinic_get_mgmt_version(nic_dev->hwdev, fw_ver); 781dbf524abSXiaoyun Wang if (err) { 7824f1af3cbSXiaoyun Wang PMD_DRV_LOG(ERR, "Failed to get fw version"); 783dbf524abSXiaoyun Wang return -EINVAL; 784dbf524abSXiaoyun Wang } 785dbf524abSXiaoyun Wang 786dbf524abSXiaoyun Wang if (fw_size < strlen(fw_ver) + 1) 787dbf524abSXiaoyun Wang return (strlen(fw_ver) + 1); 788dbf524abSXiaoyun Wang 789dbf524abSXiaoyun Wang snprintf(fw_version, fw_size, "%s", fw_ver); 790dbf524abSXiaoyun Wang 791dbf524abSXiaoyun Wang return 0; 792dbf524abSXiaoyun Wang } 793dbf524abSXiaoyun Wang 7942c473729SZiyang Xuan static int hinic_config_rx_mode(struct hinic_nic_dev *nic_dev, u32 rx_mode_ctrl) 7952c473729SZiyang Xuan { 7962c473729SZiyang Xuan int err; 7972c473729SZiyang Xuan 7982c473729SZiyang Xuan err = hinic_set_rx_mode(nic_dev->hwdev, rx_mode_ctrl); 7992c473729SZiyang Xuan if (err) { 8002c473729SZiyang Xuan PMD_DRV_LOG(ERR, "Failed to set rx mode"); 8012c473729SZiyang Xuan return -EINVAL; 8022c473729SZiyang Xuan } 8032c473729SZiyang Xuan nic_dev->rx_mode_status = rx_mode_ctrl; 8042c473729SZiyang Xuan 8052c473729SZiyang Xuan return 0; 8062c473729SZiyang Xuan } 8072c473729SZiyang Xuan 8082c473729SZiyang Xuan static int hinic_rxtx_configure(struct rte_eth_dev *dev) 8092c473729SZiyang Xuan { 8102c473729SZiyang Xuan struct hinic_nic_dev *nic_dev = HINIC_ETH_DEV_TO_PRIVATE_NIC_DEV(dev); 8119d02f40dSXiaoyun Wang int err; 8122c473729SZiyang Xuan 8132c473729SZiyang Xuan /* rx configure, if rss enable, need to init default configuration */ 8142c473729SZiyang Xuan err = hinic_rx_configure(dev); 8152c473729SZiyang Xuan if (err) { 8162c473729SZiyang Xuan PMD_DRV_LOG(ERR, "Configure rss failed"); 8172c473729SZiyang Xuan return err; 8182c473729SZiyang Xuan } 8192c473729SZiyang Xuan 8202c473729SZiyang Xuan /* rx mode init */ 8212c473729SZiyang Xuan err = hinic_config_rx_mode(nic_dev, HINIC_DEFAULT_RX_MODE); 8222c473729SZiyang Xuan if (err) { 8232c473729SZiyang Xuan PMD_DRV_LOG(ERR, "Configure rx_mode:0x%x failed", 8242c473729SZiyang Xuan HINIC_DEFAULT_RX_MODE); 8252c473729SZiyang Xuan goto set_rx_mode_fail; 8262c473729SZiyang Xuan } 8272c473729SZiyang Xuan 8282c473729SZiyang Xuan return HINIC_OK; 8292c473729SZiyang Xuan 8302c473729SZiyang Xuan set_rx_mode_fail: 8312c473729SZiyang Xuan hinic_rx_remove_configure(dev); 8322c473729SZiyang Xuan 8332c473729SZiyang Xuan return err; 8342c473729SZiyang Xuan } 8352c473729SZiyang Xuan 8362c473729SZiyang Xuan static void hinic_remove_rxtx_configure(struct rte_eth_dev *dev) 8372c473729SZiyang Xuan { 8382c473729SZiyang Xuan struct hinic_nic_dev *nic_dev = HINIC_ETH_DEV_TO_PRIVATE_NIC_DEV(dev); 8392c473729SZiyang Xuan 8402c473729SZiyang Xuan (void)hinic_config_rx_mode(nic_dev, 0); 8412c473729SZiyang Xuan hinic_rx_remove_configure(dev); 8422c473729SZiyang Xuan } 8432c473729SZiyang Xuan 8442c473729SZiyang Xuan static int hinic_priv_get_dev_link_status(struct hinic_nic_dev *nic_dev, 8452c473729SZiyang Xuan struct rte_eth_link *link) 8462c473729SZiyang Xuan { 8472c473729SZiyang Xuan int rc; 8482c473729SZiyang Xuan u8 port_link_status = 0; 8492c473729SZiyang Xuan struct nic_port_info port_link_info; 8502c473729SZiyang Xuan struct hinic_hwdev *nic_hwdev = nic_dev->hwdev; 851295968d1SFerruh Yigit uint32_t port_speed[LINK_SPEED_MAX] = {RTE_ETH_SPEED_NUM_10M, 852295968d1SFerruh Yigit RTE_ETH_SPEED_NUM_100M, RTE_ETH_SPEED_NUM_1G, 853295968d1SFerruh Yigit RTE_ETH_SPEED_NUM_10G, RTE_ETH_SPEED_NUM_25G, 854295968d1SFerruh Yigit RTE_ETH_SPEED_NUM_40G, RTE_ETH_SPEED_NUM_100G}; 8552c473729SZiyang Xuan 8562c473729SZiyang Xuan rc = hinic_get_link_status(nic_hwdev, &port_link_status); 8572c473729SZiyang Xuan if (rc) 8582c473729SZiyang Xuan return rc; 8592c473729SZiyang Xuan 8602c473729SZiyang Xuan if (!port_link_status) { 861295968d1SFerruh Yigit link->link_status = RTE_ETH_LINK_DOWN; 8622c473729SZiyang Xuan link->link_speed = 0; 863295968d1SFerruh Yigit link->link_duplex = RTE_ETH_LINK_HALF_DUPLEX; 864295968d1SFerruh Yigit link->link_autoneg = RTE_ETH_LINK_FIXED; 8652c473729SZiyang Xuan return HINIC_OK; 8662c473729SZiyang Xuan } 8672c473729SZiyang Xuan 8682c473729SZiyang Xuan memset(&port_link_info, 0, sizeof(port_link_info)); 8692c473729SZiyang Xuan rc = hinic_get_port_info(nic_hwdev, &port_link_info); 8702c473729SZiyang Xuan if (rc) 8712c473729SZiyang Xuan return rc; 8722c473729SZiyang Xuan 8732c473729SZiyang Xuan link->link_speed = port_speed[port_link_info.speed % LINK_SPEED_MAX]; 8742c473729SZiyang Xuan link->link_duplex = port_link_info.duplex; 8752c473729SZiyang Xuan link->link_autoneg = port_link_info.autoneg_state; 8762c473729SZiyang Xuan link->link_status = port_link_status; 8772c473729SZiyang Xuan 8782c473729SZiyang Xuan return HINIC_OK; 8792c473729SZiyang Xuan } 8802c473729SZiyang Xuan 8812c473729SZiyang Xuan /** 8822c473729SZiyang Xuan * DPDK callback to retrieve physical link information. 8832c473729SZiyang Xuan * 8842c473729SZiyang Xuan * @param dev 8852c473729SZiyang Xuan * Pointer to Ethernet device structure. 8862c473729SZiyang Xuan * @param wait_to_complete 8872c473729SZiyang Xuan * Wait for request completion. 8882c473729SZiyang Xuan * 8892c473729SZiyang Xuan * @return 8902c473729SZiyang Xuan * 0 link status changed, -1 link status not changed 8912c473729SZiyang Xuan */ 8922c473729SZiyang Xuan static int hinic_link_update(struct rte_eth_dev *dev, int wait_to_complete) 8932c473729SZiyang Xuan { 8942c473729SZiyang Xuan #define CHECK_INTERVAL 10 /* 10ms */ 8952c473729SZiyang Xuan #define MAX_REPEAT_TIME 100 /* 1s (100 * 10ms) in total */ 8962c473729SZiyang Xuan int rc = HINIC_OK; 8972c473729SZiyang Xuan struct rte_eth_link link; 8982c473729SZiyang Xuan struct hinic_nic_dev *nic_dev = HINIC_ETH_DEV_TO_PRIVATE_NIC_DEV(dev); 8992c473729SZiyang Xuan unsigned int rep_cnt = MAX_REPEAT_TIME; 9002c473729SZiyang Xuan 9012c473729SZiyang Xuan memset(&link, 0, sizeof(link)); 9022c473729SZiyang Xuan do { 9032c473729SZiyang Xuan /* Get link status information from hardware */ 9042c473729SZiyang Xuan rc = hinic_priv_get_dev_link_status(nic_dev, &link); 9052c473729SZiyang Xuan if (rc != HINIC_OK) { 906295968d1SFerruh Yigit link.link_speed = RTE_ETH_SPEED_NUM_NONE; 907295968d1SFerruh Yigit link.link_duplex = RTE_ETH_LINK_FULL_DUPLEX; 9082c473729SZiyang Xuan PMD_DRV_LOG(ERR, "Get link status failed"); 9092c473729SZiyang Xuan goto out; 9102c473729SZiyang Xuan } 9112c473729SZiyang Xuan 9122c473729SZiyang Xuan if (!wait_to_complete || link.link_status) 9132c473729SZiyang Xuan break; 9142c473729SZiyang Xuan 9152c473729SZiyang Xuan rte_delay_ms(CHECK_INTERVAL); 9162c473729SZiyang Xuan } while (rep_cnt--); 9172c473729SZiyang Xuan 9182c473729SZiyang Xuan out: 9192c473729SZiyang Xuan rc = rte_eth_linkstatus_set(dev, &link); 9202c473729SZiyang Xuan return rc; 9212c473729SZiyang Xuan } 9222c473729SZiyang Xuan 9232c473729SZiyang Xuan /** 92454ac3386SXiaoyun Wang * DPDK callback to bring the link UP. 92554ac3386SXiaoyun Wang * 92654ac3386SXiaoyun Wang * @param dev 92754ac3386SXiaoyun Wang * Pointer to Ethernet device structure. 92854ac3386SXiaoyun Wang * 92954ac3386SXiaoyun Wang * @return 93054ac3386SXiaoyun Wang * 0 on success, negative errno value on failure. 93154ac3386SXiaoyun Wang */ 93254ac3386SXiaoyun Wang static int hinic_dev_set_link_up(struct rte_eth_dev *dev) 93354ac3386SXiaoyun Wang { 93454ac3386SXiaoyun Wang struct hinic_nic_dev *nic_dev = HINIC_ETH_DEV_TO_PRIVATE_NIC_DEV(dev); 93554ac3386SXiaoyun Wang int ret; 93654ac3386SXiaoyun Wang 93754ac3386SXiaoyun Wang /* link status follow phy port status, up will open pma */ 93854ac3386SXiaoyun Wang ret = hinic_set_port_enable(nic_dev->hwdev, true); 93954ac3386SXiaoyun Wang if (ret) 94054ac3386SXiaoyun Wang PMD_DRV_LOG(ERR, "Set mac link up failed, dev_name: %s, port_id: %d", 94154ac3386SXiaoyun Wang nic_dev->proc_dev_name, dev->data->port_id); 94254ac3386SXiaoyun Wang 94354ac3386SXiaoyun Wang return ret; 94454ac3386SXiaoyun Wang } 94554ac3386SXiaoyun Wang 94654ac3386SXiaoyun Wang /** 94754ac3386SXiaoyun Wang * DPDK callback to bring the link DOWN. 94854ac3386SXiaoyun Wang * 94954ac3386SXiaoyun Wang * @param dev 95054ac3386SXiaoyun Wang * Pointer to Ethernet device structure. 95154ac3386SXiaoyun Wang * 95254ac3386SXiaoyun Wang * @return 95354ac3386SXiaoyun Wang * 0 on success, negative errno value on failure. 95454ac3386SXiaoyun Wang */ 95554ac3386SXiaoyun Wang static int hinic_dev_set_link_down(struct rte_eth_dev *dev) 95654ac3386SXiaoyun Wang { 95754ac3386SXiaoyun Wang struct hinic_nic_dev *nic_dev = HINIC_ETH_DEV_TO_PRIVATE_NIC_DEV(dev); 95854ac3386SXiaoyun Wang int ret; 95954ac3386SXiaoyun Wang 96054ac3386SXiaoyun Wang /* link status follow phy port status, up will close pma */ 96154ac3386SXiaoyun Wang ret = hinic_set_port_enable(nic_dev->hwdev, false); 96254ac3386SXiaoyun Wang if (ret) 96354ac3386SXiaoyun Wang PMD_DRV_LOG(ERR, "Set mac link down failed, dev_name: %s, port_id: %d", 96454ac3386SXiaoyun Wang nic_dev->proc_dev_name, dev->data->port_id); 96554ac3386SXiaoyun Wang 96654ac3386SXiaoyun Wang return ret; 96754ac3386SXiaoyun Wang } 96854ac3386SXiaoyun Wang 96954ac3386SXiaoyun Wang /** 9702c473729SZiyang Xuan * DPDK callback to start the device. 9712c473729SZiyang Xuan * 9722c473729SZiyang Xuan * @param dev 9732c473729SZiyang Xuan * Pointer to Ethernet device structure. 9742c473729SZiyang Xuan * 9752c473729SZiyang Xuan * @return 9762c473729SZiyang Xuan * 0 on success, negative errno value on failure. 9772c473729SZiyang Xuan */ 9782c473729SZiyang Xuan static int hinic_dev_start(struct rte_eth_dev *dev) 9792c473729SZiyang Xuan { 9802c473729SZiyang Xuan int rc; 9812c473729SZiyang Xuan char *name; 9822c473729SZiyang Xuan struct hinic_nic_dev *nic_dev; 983b0f9c8e2SJie Hai uint16_t i; 9842c473729SZiyang Xuan 9852c473729SZiyang Xuan nic_dev = HINIC_ETH_DEV_TO_PRIVATE_NIC_DEV(dev); 9862c473729SZiyang Xuan name = dev->data->name; 9872c473729SZiyang Xuan 9882c473729SZiyang Xuan /* reset rx and tx queue */ 9892c473729SZiyang Xuan hinic_reset_rx_queue(dev); 9902c473729SZiyang Xuan hinic_reset_tx_queue(dev); 9912c473729SZiyang Xuan 9922c473729SZiyang Xuan /* get func rx buf size */ 9932c473729SZiyang Xuan hinic_get_func_rx_buf_size(nic_dev); 9942c473729SZiyang Xuan 9952c473729SZiyang Xuan /* init txq and rxq context */ 9962c473729SZiyang Xuan rc = hinic_init_qp_ctxts(nic_dev->hwdev); 9972c473729SZiyang Xuan if (rc) { 9982c473729SZiyang Xuan PMD_DRV_LOG(ERR, "Initialize qp context failed, dev_name: %s", 9992c473729SZiyang Xuan name); 10002c473729SZiyang Xuan goto init_qp_fail; 10012c473729SZiyang Xuan } 10022c473729SZiyang Xuan 10032c473729SZiyang Xuan /* rss template */ 10042c473729SZiyang Xuan rc = hinic_config_mq_mode(dev, TRUE); 10052c473729SZiyang Xuan if (rc) { 10062c473729SZiyang Xuan PMD_DRV_LOG(ERR, "Configure mq mode failed, dev_name: %s", 10072c473729SZiyang Xuan name); 10082c473729SZiyang Xuan goto cfg_mq_mode_fail; 10092c473729SZiyang Xuan } 10102c473729SZiyang Xuan 10112c473729SZiyang Xuan /* set default mtu */ 10122c473729SZiyang Xuan rc = hinic_set_port_mtu(nic_dev->hwdev, nic_dev->mtu_size); 10132c473729SZiyang Xuan if (rc) { 10142c473729SZiyang Xuan PMD_DRV_LOG(ERR, "Set mtu_size[%d] failed, dev_name: %s", 10152c473729SZiyang Xuan nic_dev->mtu_size, name); 10162c473729SZiyang Xuan goto set_mtu_fail; 10172c473729SZiyang Xuan } 10182c473729SZiyang Xuan 10192c473729SZiyang Xuan /* configure rss rx_mode and other rx or tx default feature */ 10202c473729SZiyang Xuan rc = hinic_rxtx_configure(dev); 10212c473729SZiyang Xuan if (rc) { 10222c473729SZiyang Xuan PMD_DRV_LOG(ERR, "Configure tx and rx failed, dev_name: %s", 10232c473729SZiyang Xuan name); 10242c473729SZiyang Xuan goto cfg_rxtx_fail; 10252c473729SZiyang Xuan } 10262c473729SZiyang Xuan 10276691acefSXiaoyun Wang /* reactive pf status, so that uP report asyn event */ 10286691acefSXiaoyun Wang hinic_set_pf_status(nic_dev->hwdev->hwif, HINIC_PF_STATUS_ACTIVE_FLAG); 10296691acefSXiaoyun Wang 10302c473729SZiyang Xuan /* open virtual port and ready to start packet receiving */ 10312c473729SZiyang Xuan rc = hinic_set_vport_enable(nic_dev->hwdev, true); 10322c473729SZiyang Xuan if (rc) { 10332c473729SZiyang Xuan PMD_DRV_LOG(ERR, "Enable vport failed, dev_name:%s", name); 10342c473729SZiyang Xuan goto en_vport_fail; 10352c473729SZiyang Xuan } 10362c473729SZiyang Xuan 10372c473729SZiyang Xuan /* open physical port and start packet receiving */ 10382c473729SZiyang Xuan rc = hinic_set_port_enable(nic_dev->hwdev, true); 10392c473729SZiyang Xuan if (rc) { 10402c473729SZiyang Xuan PMD_DRV_LOG(ERR, "Enable physical port failed, dev_name: %s", 10412c473729SZiyang Xuan name); 10422c473729SZiyang Xuan goto en_port_fail; 10432c473729SZiyang Xuan } 10442c473729SZiyang Xuan 10452c473729SZiyang Xuan /* update eth_dev link status */ 10462c473729SZiyang Xuan if (dev->data->dev_conf.intr_conf.lsc != 0) 10472c473729SZiyang Xuan (void)hinic_link_update(dev, 0); 10482c473729SZiyang Xuan 10490371535dSJoyce Kong rte_bit_relaxed_set32(HINIC_DEV_START, &nic_dev->dev_status); 10502c473729SZiyang Xuan 1051b0f9c8e2SJie Hai for (i = 0; i < dev->data->nb_rx_queues; i++) 1052b0f9c8e2SJie Hai dev->data->rx_queue_state[i] = RTE_ETH_QUEUE_STATE_STARTED; 1053b0f9c8e2SJie Hai for (i = 0; i < dev->data->nb_tx_queues; i++) 1054b0f9c8e2SJie Hai dev->data->tx_queue_state[i] = RTE_ETH_QUEUE_STATE_STARTED; 1055b0f9c8e2SJie Hai 10562c473729SZiyang Xuan return 0; 10572c473729SZiyang Xuan 10582c473729SZiyang Xuan en_port_fail: 10592c473729SZiyang Xuan (void)hinic_set_vport_enable(nic_dev->hwdev, false); 10602c473729SZiyang Xuan 10612c473729SZiyang Xuan en_vport_fail: 10626691acefSXiaoyun Wang hinic_set_pf_status(nic_dev->hwdev->hwif, HINIC_PF_STATUS_INIT); 10636691acefSXiaoyun Wang 10642c473729SZiyang Xuan /* Flush tx && rx chip resources in case of set vport fake fail */ 10652c473729SZiyang Xuan (void)hinic_flush_qp_res(nic_dev->hwdev); 10662c473729SZiyang Xuan rte_delay_ms(100); 10672c473729SZiyang Xuan 10682c473729SZiyang Xuan hinic_remove_rxtx_configure(dev); 10692c473729SZiyang Xuan 10702c473729SZiyang Xuan cfg_rxtx_fail: 10712c473729SZiyang Xuan set_mtu_fail: 10722c473729SZiyang Xuan cfg_mq_mode_fail: 10732c473729SZiyang Xuan hinic_free_qp_ctxts(nic_dev->hwdev); 10742c473729SZiyang Xuan 10752c473729SZiyang Xuan init_qp_fail: 10762c473729SZiyang Xuan hinic_free_all_rx_mbuf(dev); 10772c473729SZiyang Xuan hinic_free_all_tx_mbuf(dev); 10782c473729SZiyang Xuan 10792c473729SZiyang Xuan return rc; 10802c473729SZiyang Xuan } 10812c473729SZiyang Xuan 10822c473729SZiyang Xuan /** 10832c473729SZiyang Xuan * DPDK callback to release the receive queue. 10842c473729SZiyang Xuan * 10857483341aSXueming Li * @param dev 10867483341aSXueming Li * Pointer to Ethernet device structure. 10877483341aSXueming Li * @param qid 10887483341aSXueming Li * Receive queue index. 10892c473729SZiyang Xuan */ 10907483341aSXueming Li static void hinic_rx_queue_release(struct rte_eth_dev *dev, uint16_t qid) 10912c473729SZiyang Xuan { 10927483341aSXueming Li struct hinic_rxq *rxq = dev->data->rx_queues[qid]; 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 * 11197483341aSXueming Li * @param dev 11207483341aSXueming Li * Pointer to Ethernet device structure. 11217483341aSXueming Li * @param qid 11227483341aSXueming Li * Transmit queue index. 11232c473729SZiyang Xuan */ 11247483341aSXueming Li static void hinic_tx_queue_release(struct rte_eth_dev *dev, uint16_t qid) 11252c473729SZiyang Xuan { 11267483341aSXueming Li struct hinic_txq *txq = dev->data->tx_queues[qid]; 11272c473729SZiyang Xuan struct hinic_nic_dev *nic_dev; 11282c473729SZiyang Xuan 11292c473729SZiyang Xuan if (!txq) { 11302c473729SZiyang Xuan PMD_DRV_LOG(WARNING, "Txq is null when release"); 11312c473729SZiyang Xuan return; 11322c473729SZiyang Xuan } 11332c473729SZiyang Xuan nic_dev = txq->nic_dev; 11342c473729SZiyang Xuan 11352c473729SZiyang Xuan /* free txq_pkt mbuf */ 1136c3ba1f0fSXiaoyun Wang hinic_free_all_tx_mbufs(txq); 11372c473729SZiyang Xuan 11382c473729SZiyang Xuan /* free txq_info */ 11392c473729SZiyang Xuan hinic_free_tx_resources(txq); 11402c473729SZiyang Xuan 11412c473729SZiyang Xuan /* free root sq wq */ 11422c473729SZiyang Xuan hinic_destroy_sq(nic_dev->hwdev, txq->q_id); 11432c473729SZiyang Xuan nic_dev->txqs[txq->q_id] = NULL; 11442c473729SZiyang Xuan 11452c473729SZiyang Xuan /* free txq */ 11462c473729SZiyang Xuan rte_free(txq); 11472c473729SZiyang Xuan } 11482c473729SZiyang Xuan 114964727024SZiyang Xuan static void hinic_free_all_rq(struct hinic_nic_dev *nic_dev) 11501d09792aSZiyang Xuan { 115164727024SZiyang Xuan u16 q_id; 115264727024SZiyang Xuan 115364727024SZiyang Xuan for (q_id = 0; q_id < nic_dev->num_rq; q_id++) 115464727024SZiyang Xuan hinic_destroy_rq(nic_dev->hwdev, q_id); 115564727024SZiyang Xuan } 115664727024SZiyang Xuan 115764727024SZiyang Xuan static void hinic_free_all_sq(struct hinic_nic_dev *nic_dev) 115864727024SZiyang Xuan { 115964727024SZiyang Xuan u16 q_id; 116064727024SZiyang Xuan 116164727024SZiyang Xuan for (q_id = 0; q_id < nic_dev->num_sq; q_id++) 116264727024SZiyang Xuan hinic_destroy_sq(nic_dev->hwdev, q_id); 116364727024SZiyang Xuan } 116464727024SZiyang Xuan 11652c473729SZiyang Xuan /** 11662c473729SZiyang Xuan * DPDK callback to stop the device. 11672c473729SZiyang Xuan * 11682c473729SZiyang Xuan * @param dev 11692c473729SZiyang Xuan * Pointer to Ethernet device structure. 11702c473729SZiyang Xuan */ 117162024eb8SIvan Ilchenko static int hinic_dev_stop(struct rte_eth_dev *dev) 11722c473729SZiyang Xuan { 11732c473729SZiyang Xuan int rc; 11742c473729SZiyang Xuan char *name; 11752c473729SZiyang Xuan uint16_t port_id; 11762c473729SZiyang Xuan struct hinic_nic_dev *nic_dev; 11772c473729SZiyang Xuan struct rte_eth_link link; 1178b0f9c8e2SJie Hai uint16_t i; 11792c473729SZiyang Xuan 11802c473729SZiyang Xuan nic_dev = HINIC_ETH_DEV_TO_PRIVATE_NIC_DEV(dev); 11812c473729SZiyang Xuan name = dev->data->name; 11822c473729SZiyang Xuan port_id = dev->data->port_id; 11832c473729SZiyang Xuan 1184b8f5d2aeSThomas Monjalon dev->data->dev_started = 0; 1185b8f5d2aeSThomas Monjalon 11860371535dSJoyce Kong if (!rte_bit_relaxed_test_and_clear32(HINIC_DEV_START, 11870371535dSJoyce Kong &nic_dev->dev_status)) { 11882c473729SZiyang Xuan PMD_DRV_LOG(INFO, "Device %s already stopped", name); 118962024eb8SIvan Ilchenko return 0; 11902c473729SZiyang Xuan } 11912c473729SZiyang Xuan 11922c473729SZiyang Xuan /* just stop phy port and vport */ 11932c473729SZiyang Xuan rc = hinic_set_port_enable(nic_dev->hwdev, false); 11942c473729SZiyang Xuan if (rc) 11952c473729SZiyang Xuan PMD_DRV_LOG(WARNING, "Disable phy port failed, error: %d, dev_name: %s, port_id: %d", 11962c473729SZiyang Xuan rc, name, port_id); 11972c473729SZiyang Xuan 11982c473729SZiyang Xuan rc = hinic_set_vport_enable(nic_dev->hwdev, false); 11992c473729SZiyang Xuan if (rc) 12002c473729SZiyang Xuan PMD_DRV_LOG(WARNING, "Disable vport failed, error: %d, dev_name: %s, port_id: %d", 12012c473729SZiyang Xuan rc, name, port_id); 12022c473729SZiyang Xuan 12032c473729SZiyang Xuan /* Clear recorded link status */ 12042c473729SZiyang Xuan memset(&link, 0, sizeof(link)); 12052c473729SZiyang Xuan (void)rte_eth_linkstatus_set(dev, &link); 12062c473729SZiyang Xuan 12072c473729SZiyang Xuan /* flush pending io request */ 12082c473729SZiyang Xuan rc = hinic_rx_tx_flush(nic_dev->hwdev); 12092c473729SZiyang Xuan if (rc) 12102c473729SZiyang Xuan PMD_DRV_LOG(WARNING, "Flush pending io failed, error: %d, dev_name: %s, port_id: %d", 12112c473729SZiyang Xuan rc, name, port_id); 12122c473729SZiyang Xuan 12132c473729SZiyang Xuan /* clean rss table and rx_mode */ 12142c473729SZiyang Xuan hinic_remove_rxtx_configure(dev); 12152c473729SZiyang Xuan 12162c473729SZiyang Xuan /* clean root context */ 12172c473729SZiyang Xuan hinic_free_qp_ctxts(nic_dev->hwdev); 12182c473729SZiyang Xuan 12191fe89aa3SXiaoyun Wang hinic_destroy_fdir_filter(dev); 12201742421bSXiaoyun Wang 12212c473729SZiyang Xuan /* free mbuf */ 12222c473729SZiyang Xuan hinic_free_all_rx_mbuf(dev); 12232c473729SZiyang Xuan hinic_free_all_tx_mbuf(dev); 122462024eb8SIvan Ilchenko 1225b0f9c8e2SJie Hai for (i = 0; i < dev->data->nb_rx_queues; i++) 1226b0f9c8e2SJie Hai dev->data->rx_queue_state[i] = RTE_ETH_QUEUE_STATE_STOPPED; 1227b0f9c8e2SJie Hai for (i = 0; i < dev->data->nb_tx_queues; i++) 1228b0f9c8e2SJie Hai dev->data->tx_queue_state[i] = RTE_ETH_QUEUE_STATE_STOPPED; 1229b0f9c8e2SJie Hai 123062024eb8SIvan Ilchenko return 0; 12312c473729SZiyang Xuan } 12322c473729SZiyang Xuan 123364727024SZiyang Xuan static void hinic_disable_interrupt(struct rte_eth_dev *dev) 123464727024SZiyang Xuan { 123564727024SZiyang Xuan struct hinic_nic_dev *nic_dev = HINIC_ETH_DEV_TO_PRIVATE_NIC_DEV(dev); 123664727024SZiyang Xuan struct rte_pci_device *pci_dev = RTE_ETH_DEV_TO_PCI(dev); 123764727024SZiyang Xuan int ret, retries = 0; 123864727024SZiyang Xuan 12390371535dSJoyce Kong rte_bit_relaxed_clear32(HINIC_DEV_INTR_EN, &nic_dev->dev_status); 124064727024SZiyang Xuan 124164727024SZiyang Xuan /* disable msix interrupt in hardware */ 124264727024SZiyang Xuan hinic_set_msix_state(nic_dev->hwdev, 0, HINIC_MSIX_DISABLE); 124364727024SZiyang Xuan 124464727024SZiyang Xuan /* disable rte interrupt */ 1245d61138d4SHarman Kalra ret = rte_intr_disable(pci_dev->intr_handle); 124664727024SZiyang Xuan if (ret) 124764727024SZiyang Xuan PMD_DRV_LOG(ERR, "Disable intr failed: %d", ret); 124864727024SZiyang Xuan 124964727024SZiyang Xuan do { 125064727024SZiyang Xuan ret = 1251d61138d4SHarman Kalra rte_intr_callback_unregister(pci_dev->intr_handle, 125264727024SZiyang Xuan hinic_dev_interrupt_handler, dev); 125364727024SZiyang Xuan if (ret >= 0) { 125464727024SZiyang Xuan break; 125564727024SZiyang Xuan } else if (ret == -EAGAIN) { 125664727024SZiyang Xuan rte_delay_ms(100); 125764727024SZiyang Xuan retries++; 125864727024SZiyang Xuan } else { 125964727024SZiyang Xuan PMD_DRV_LOG(ERR, "intr callback unregister failed: %d", 126064727024SZiyang Xuan ret); 126164727024SZiyang Xuan break; 126264727024SZiyang Xuan } 126364727024SZiyang Xuan } while (retries < HINIC_INTR_CB_UNREG_MAX_RETRIES); 126464727024SZiyang Xuan 126564727024SZiyang Xuan if (retries == HINIC_INTR_CB_UNREG_MAX_RETRIES) 126664727024SZiyang Xuan PMD_DRV_LOG(ERR, "Unregister intr callback failed after %d retries", 126764727024SZiyang Xuan retries); 1268511b7371SGuoyang Zhou 1269511b7371SGuoyang Zhou rte_bit_relaxed_clear32(HINIC_DEV_INIT, &nic_dev->dev_status); 127064727024SZiyang Xuan } 127164727024SZiyang Xuan 1272cb7b6606SZiyang Xuan static int hinic_set_dev_promiscuous(struct hinic_nic_dev *nic_dev, bool enable) 1273cb7b6606SZiyang Xuan { 1274224cff4bSXiaoyun Wang u32 rx_mode_ctrl; 1275224cff4bSXiaoyun Wang int err; 1276224cff4bSXiaoyun Wang 1277224cff4bSXiaoyun Wang err = hinic_mutex_lock(&nic_dev->rx_mode_mutex); 1278224cff4bSXiaoyun Wang if (err) 1279224cff4bSXiaoyun Wang return err; 1280224cff4bSXiaoyun Wang 1281224cff4bSXiaoyun Wang rx_mode_ctrl = nic_dev->rx_mode_status; 1282cb7b6606SZiyang Xuan 1283cb7b6606SZiyang Xuan if (enable) 1284cb7b6606SZiyang Xuan rx_mode_ctrl |= HINIC_RX_MODE_PROMISC; 1285cb7b6606SZiyang Xuan else 1286cb7b6606SZiyang Xuan rx_mode_ctrl &= (~HINIC_RX_MODE_PROMISC); 1287cb7b6606SZiyang Xuan 1288224cff4bSXiaoyun Wang err = hinic_config_rx_mode(nic_dev, rx_mode_ctrl); 1289224cff4bSXiaoyun Wang 1290224cff4bSXiaoyun Wang (void)hinic_mutex_unlock(&nic_dev->rx_mode_mutex); 1291224cff4bSXiaoyun Wang 1292224cff4bSXiaoyun Wang return err; 1293cb7b6606SZiyang Xuan } 1294cb7b6606SZiyang Xuan 1295cb7b6606SZiyang Xuan /** 1296cb7b6606SZiyang Xuan * DPDK callback to get device statistics. 1297cb7b6606SZiyang Xuan * 1298cb7b6606SZiyang Xuan * @param dev 1299cb7b6606SZiyang Xuan * Pointer to Ethernet device structure. 1300cb7b6606SZiyang Xuan * @param stats 1301cb7b6606SZiyang Xuan * Stats structure output buffer. 1302cb7b6606SZiyang Xuan * 1303cb7b6606SZiyang Xuan * @return 1304cb7b6606SZiyang Xuan * 0 on success and stats is filled, 1305cb7b6606SZiyang Xuan * negative error value otherwise. 1306cb7b6606SZiyang Xuan */ 1307cb7b6606SZiyang Xuan static int 1308cb7b6606SZiyang Xuan hinic_dev_stats_get(struct rte_eth_dev *dev, struct rte_eth_stats *stats) 1309cb7b6606SZiyang Xuan { 1310cb7b6606SZiyang Xuan int i, err, q_num; 1311cb7b6606SZiyang Xuan u64 rx_discards_pmd = 0; 1312cb7b6606SZiyang Xuan struct hinic_nic_dev *nic_dev = HINIC_ETH_DEV_TO_PRIVATE_NIC_DEV(dev); 1313cb7b6606SZiyang Xuan struct hinic_vport_stats vport_stats; 1314cb7b6606SZiyang Xuan struct hinic_rxq *rxq = NULL; 1315cb7b6606SZiyang Xuan struct hinic_rxq_stats rxq_stats; 1316cb7b6606SZiyang Xuan struct hinic_txq *txq = NULL; 1317cb7b6606SZiyang Xuan struct hinic_txq_stats txq_stats; 1318cb7b6606SZiyang Xuan 1319cb7b6606SZiyang Xuan err = hinic_get_vport_stats(nic_dev->hwdev, &vport_stats); 1320cb7b6606SZiyang Xuan if (err) { 1321cb7b6606SZiyang Xuan PMD_DRV_LOG(ERR, "Get vport stats from fw failed, nic_dev: %s", 1322cb7b6606SZiyang Xuan nic_dev->proc_dev_name); 1323cb7b6606SZiyang Xuan return err; 1324cb7b6606SZiyang Xuan } 1325cb7b6606SZiyang Xuan 13263930d9ceSXiaoyun Wang dev->data->rx_mbuf_alloc_failed = 0; 13273930d9ceSXiaoyun Wang 1328cb7b6606SZiyang Xuan /* rx queue stats */ 1329cb7b6606SZiyang Xuan q_num = (nic_dev->num_rq < RTE_ETHDEV_QUEUE_STAT_CNTRS) ? 1330cb7b6606SZiyang Xuan nic_dev->num_rq : RTE_ETHDEV_QUEUE_STAT_CNTRS; 1331cb7b6606SZiyang Xuan for (i = 0; i < q_num; i++) { 1332cb7b6606SZiyang Xuan rxq = nic_dev->rxqs[i]; 1333cb7b6606SZiyang Xuan hinic_rxq_get_stats(rxq, &rxq_stats); 1334cb7b6606SZiyang Xuan stats->q_ipackets[i] = rxq_stats.packets; 1335cb7b6606SZiyang Xuan stats->q_ibytes[i] = rxq_stats.bytes; 1336cb7b6606SZiyang Xuan stats->q_errors[i] = rxq_stats.rx_discards; 1337cb7b6606SZiyang Xuan 1338cb7b6606SZiyang Xuan stats->ierrors += rxq_stats.errors; 1339cb7b6606SZiyang Xuan rx_discards_pmd += rxq_stats.rx_discards; 1340cb7b6606SZiyang Xuan dev->data->rx_mbuf_alloc_failed += rxq_stats.rx_nombuf; 1341cb7b6606SZiyang Xuan } 1342cb7b6606SZiyang Xuan 1343cb7b6606SZiyang Xuan /* tx queue stats */ 1344cb7b6606SZiyang Xuan q_num = (nic_dev->num_sq < RTE_ETHDEV_QUEUE_STAT_CNTRS) ? 1345cb7b6606SZiyang Xuan nic_dev->num_sq : RTE_ETHDEV_QUEUE_STAT_CNTRS; 1346cb7b6606SZiyang Xuan for (i = 0; i < q_num; i++) { 1347cb7b6606SZiyang Xuan txq = nic_dev->txqs[i]; 1348cb7b6606SZiyang Xuan hinic_txq_get_stats(txq, &txq_stats); 1349cb7b6606SZiyang Xuan stats->q_opackets[i] = txq_stats.packets; 1350cb7b6606SZiyang Xuan stats->q_obytes[i] = txq_stats.bytes; 1351cb7b6606SZiyang Xuan stats->oerrors += (txq_stats.tx_busy + txq_stats.off_errs); 1352cb7b6606SZiyang Xuan } 1353cb7b6606SZiyang Xuan 1354cb7b6606SZiyang Xuan /* vport stats */ 1355cb7b6606SZiyang Xuan stats->oerrors += vport_stats.tx_discard_vport; 1356cb7b6606SZiyang Xuan 1357cb7b6606SZiyang Xuan stats->imissed = vport_stats.rx_discard_vport + rx_discards_pmd; 1358cb7b6606SZiyang Xuan 1359cb7b6606SZiyang Xuan stats->ipackets = (vport_stats.rx_unicast_pkts_vport + 1360cb7b6606SZiyang Xuan vport_stats.rx_multicast_pkts_vport + 1361cb7b6606SZiyang Xuan vport_stats.rx_broadcast_pkts_vport - 1362cb7b6606SZiyang Xuan rx_discards_pmd); 1363cb7b6606SZiyang Xuan 1364cb7b6606SZiyang Xuan stats->opackets = (vport_stats.tx_unicast_pkts_vport + 1365cb7b6606SZiyang Xuan vport_stats.tx_multicast_pkts_vport + 1366cb7b6606SZiyang Xuan vport_stats.tx_broadcast_pkts_vport); 1367cb7b6606SZiyang Xuan 1368cb7b6606SZiyang Xuan stats->ibytes = (vport_stats.rx_unicast_bytes_vport + 1369cb7b6606SZiyang Xuan vport_stats.rx_multicast_bytes_vport + 1370cb7b6606SZiyang Xuan vport_stats.rx_broadcast_bytes_vport); 1371cb7b6606SZiyang Xuan 1372cb7b6606SZiyang Xuan stats->obytes = (vport_stats.tx_unicast_bytes_vport + 1373cb7b6606SZiyang Xuan vport_stats.tx_multicast_bytes_vport + 1374cb7b6606SZiyang Xuan vport_stats.tx_broadcast_bytes_vport); 1375cb7b6606SZiyang Xuan return 0; 1376cb7b6606SZiyang Xuan } 1377cb7b6606SZiyang Xuan 1378cb7b6606SZiyang Xuan /** 1379cb7b6606SZiyang Xuan * DPDK callback to clear device statistics. 1380cb7b6606SZiyang Xuan * 1381cb7b6606SZiyang Xuan * @param dev 1382cb7b6606SZiyang Xuan * Pointer to Ethernet device structure. 1383cb7b6606SZiyang Xuan */ 13849970a9adSIgor Romanov static int hinic_dev_stats_reset(struct rte_eth_dev *dev) 1385cb7b6606SZiyang Xuan { 1386cb7b6606SZiyang Xuan int qid; 1387cb7b6606SZiyang Xuan struct hinic_rxq *rxq = NULL; 1388cb7b6606SZiyang Xuan struct hinic_txq *txq = NULL; 1389cb7b6606SZiyang Xuan struct hinic_nic_dev *nic_dev = HINIC_ETH_DEV_TO_PRIVATE_NIC_DEV(dev); 13909970a9adSIgor Romanov int ret; 1391cb7b6606SZiyang Xuan 13929970a9adSIgor Romanov ret = hinic_clear_vport_stats(nic_dev->hwdev); 13939970a9adSIgor Romanov if (ret != 0) 13949970a9adSIgor Romanov return ret; 1395cb7b6606SZiyang Xuan 1396cb7b6606SZiyang Xuan for (qid = 0; qid < nic_dev->num_rq; qid++) { 1397cb7b6606SZiyang Xuan rxq = nic_dev->rxqs[qid]; 1398cb7b6606SZiyang Xuan hinic_rxq_stats_reset(rxq); 1399cb7b6606SZiyang Xuan } 1400cb7b6606SZiyang Xuan 1401cb7b6606SZiyang Xuan for (qid = 0; qid < nic_dev->num_sq; qid++) { 1402cb7b6606SZiyang Xuan txq = nic_dev->txqs[qid]; 1403cb7b6606SZiyang Xuan hinic_txq_stats_reset(txq); 1404cb7b6606SZiyang Xuan } 14059970a9adSIgor Romanov 14069970a9adSIgor Romanov return 0; 1407cb7b6606SZiyang Xuan } 1408cb7b6606SZiyang Xuan 1409cb7b6606SZiyang Xuan /** 1410cb7b6606SZiyang Xuan * DPDK callback to clear device extended statistics. 1411cb7b6606SZiyang Xuan * 1412cb7b6606SZiyang Xuan * @param dev 1413cb7b6606SZiyang Xuan * Pointer to Ethernet device structure. 14146691acefSXiaoyun Wang */ 14159970a9adSIgor Romanov static int hinic_dev_xstats_reset(struct rte_eth_dev *dev) 1416cb7b6606SZiyang Xuan { 1417cb7b6606SZiyang Xuan struct hinic_nic_dev *nic_dev = HINIC_ETH_DEV_TO_PRIVATE_NIC_DEV(dev); 14189970a9adSIgor Romanov int ret; 1419cb7b6606SZiyang Xuan 14209970a9adSIgor Romanov ret = hinic_dev_stats_reset(dev); 14219970a9adSIgor Romanov if (ret != 0) 14229970a9adSIgor Romanov return ret; 1423cb7b6606SZiyang Xuan 14249970a9adSIgor Romanov if (hinic_func_type(nic_dev->hwdev) != TYPE_VF) { 14259970a9adSIgor Romanov ret = hinic_clear_phy_port_stats(nic_dev->hwdev); 14269970a9adSIgor Romanov if (ret != 0) 14279970a9adSIgor Romanov return ret; 14289970a9adSIgor Romanov } 14299970a9adSIgor Romanov 14309970a9adSIgor Romanov return 0; 1431cb7b6606SZiyang Xuan } 1432cb7b6606SZiyang Xuan 14332c473729SZiyang Xuan static void hinic_gen_random_mac_addr(struct rte_ether_addr *mac_addr) 14342c473729SZiyang Xuan { 14352c473729SZiyang Xuan uint64_t random_value; 14362c473729SZiyang Xuan 14372c473729SZiyang Xuan /* Set Organizationally Unique Identifier (OUI) prefix */ 14382c473729SZiyang Xuan mac_addr->addr_bytes[0] = 0x00; 14392c473729SZiyang Xuan mac_addr->addr_bytes[1] = 0x09; 14402c473729SZiyang Xuan mac_addr->addr_bytes[2] = 0xC0; 14412c473729SZiyang Xuan /* Force indication of locally assigned MAC address. */ 14422c473729SZiyang Xuan mac_addr->addr_bytes[0] |= RTE_ETHER_LOCAL_ADMIN_ADDR; 14432c473729SZiyang Xuan /* Generate the last 3 bytes of the MAC address with a random number. */ 14442c473729SZiyang Xuan random_value = rte_rand(); 14452c473729SZiyang Xuan memcpy(&mac_addr->addr_bytes[3], &random_value, 3); 14462c473729SZiyang Xuan } 14472c473729SZiyang Xuan 144864727024SZiyang Xuan /** 144964727024SZiyang Xuan * Init mac_vlan table in NIC. 145064727024SZiyang Xuan * 145164727024SZiyang Xuan * @param dev 145264727024SZiyang Xuan * Pointer to Ethernet device structure. 145364727024SZiyang Xuan * 145464727024SZiyang Xuan * @return 145564727024SZiyang Xuan * 0 on success and stats is filled, 145664727024SZiyang Xuan * negative error value otherwise. 145764727024SZiyang Xuan */ 145864727024SZiyang Xuan static int hinic_init_mac_addr(struct rte_eth_dev *eth_dev) 145964727024SZiyang Xuan { 146064727024SZiyang Xuan struct hinic_nic_dev *nic_dev = 146164727024SZiyang Xuan HINIC_ETH_DEV_TO_PRIVATE_NIC_DEV(eth_dev); 146264727024SZiyang Xuan uint8_t addr_bytes[RTE_ETHER_ADDR_LEN]; 146364727024SZiyang Xuan u16 func_id = 0; 146464727024SZiyang Xuan int rc = 0; 146564727024SZiyang Xuan 146664727024SZiyang Xuan rc = hinic_get_default_mac(nic_dev->hwdev, addr_bytes); 146764727024SZiyang Xuan if (rc) 146864727024SZiyang Xuan return rc; 146964727024SZiyang Xuan 147000499a22SXiaoyun Wang rte_ether_addr_copy((struct rte_ether_addr *)addr_bytes, 147100499a22SXiaoyun Wang ð_dev->data->mac_addrs[0]); 147200499a22SXiaoyun Wang if (rte_is_zero_ether_addr(ð_dev->data->mac_addrs[0])) 147300499a22SXiaoyun Wang hinic_gen_random_mac_addr(ð_dev->data->mac_addrs[0]); 14742c473729SZiyang Xuan 147564727024SZiyang Xuan func_id = hinic_global_func_id(nic_dev->hwdev); 147600499a22SXiaoyun Wang rc = hinic_set_mac(nic_dev->hwdev, 147700499a22SXiaoyun Wang eth_dev->data->mac_addrs[0].addr_bytes, 147864727024SZiyang Xuan 0, func_id); 147964727024SZiyang Xuan if (rc && rc != HINIC_PF_SET_VF_ALREADY) 148064727024SZiyang Xuan return rc; 148164727024SZiyang Xuan 148200499a22SXiaoyun Wang rte_ether_addr_copy(ð_dev->data->mac_addrs[0], 148300499a22SXiaoyun Wang &nic_dev->default_addr); 148400499a22SXiaoyun Wang 14851d09792aSZiyang Xuan return 0; 14861d09792aSZiyang Xuan } 14871d09792aSZiyang Xuan 148800499a22SXiaoyun Wang static void hinic_delete_mc_addr_list(struct hinic_nic_dev *nic_dev) 148900499a22SXiaoyun Wang { 149000499a22SXiaoyun Wang u16 func_id; 149100499a22SXiaoyun Wang u32 i; 149200499a22SXiaoyun Wang 149300499a22SXiaoyun Wang func_id = hinic_global_func_id(nic_dev->hwdev); 149400499a22SXiaoyun Wang 149500499a22SXiaoyun Wang for (i = 0; i < HINIC_MAX_MC_MAC_ADDRS; i++) { 149600499a22SXiaoyun Wang if (rte_is_zero_ether_addr(&nic_dev->mc_list[i])) 149700499a22SXiaoyun Wang break; 149800499a22SXiaoyun Wang 149900499a22SXiaoyun Wang hinic_del_mac(nic_dev->hwdev, nic_dev->mc_list[i].addr_bytes, 150000499a22SXiaoyun Wang 0, func_id); 150100499a22SXiaoyun Wang memset(&nic_dev->mc_list[i], 0, sizeof(struct rte_ether_addr)); 150200499a22SXiaoyun Wang } 150300499a22SXiaoyun Wang } 150400499a22SXiaoyun Wang 15051d09792aSZiyang Xuan /** 150664727024SZiyang Xuan * Deinit mac_vlan table in NIC. 150764727024SZiyang Xuan * 150864727024SZiyang Xuan * @param dev 150964727024SZiyang Xuan * Pointer to Ethernet device structure. 151064727024SZiyang Xuan * 151164727024SZiyang Xuan * @return 151264727024SZiyang Xuan * 0 on success and stats is filled, 151364727024SZiyang Xuan * negative error value otherwise. 151464727024SZiyang Xuan */ 151564727024SZiyang Xuan static void hinic_deinit_mac_addr(struct rte_eth_dev *eth_dev) 151664727024SZiyang Xuan { 151764727024SZiyang Xuan struct hinic_nic_dev *nic_dev = 151864727024SZiyang Xuan HINIC_ETH_DEV_TO_PRIVATE_NIC_DEV(eth_dev); 151964727024SZiyang Xuan u16 func_id = 0; 152000499a22SXiaoyun Wang int rc; 152100499a22SXiaoyun Wang int i; 152264727024SZiyang Xuan 152364727024SZiyang Xuan func_id = hinic_global_func_id(nic_dev->hwdev); 152400499a22SXiaoyun Wang 152500499a22SXiaoyun Wang for (i = 0; i < HINIC_MAX_UC_MAC_ADDRS; i++) { 152600499a22SXiaoyun Wang if (rte_is_zero_ether_addr(ð_dev->data->mac_addrs[i])) 152700499a22SXiaoyun Wang continue; 152800499a22SXiaoyun Wang 152964727024SZiyang Xuan rc = hinic_del_mac(nic_dev->hwdev, 153000499a22SXiaoyun Wang eth_dev->data->mac_addrs[i].addr_bytes, 153164727024SZiyang Xuan 0, func_id); 153264727024SZiyang Xuan if (rc && rc != HINIC_PF_SET_VF_ALREADY) 153364727024SZiyang Xuan PMD_DRV_LOG(ERR, "Delete mac table failed, dev_name: %s", 153464727024SZiyang Xuan eth_dev->data->name); 153500499a22SXiaoyun Wang 153600499a22SXiaoyun Wang memset(ð_dev->data->mac_addrs[i], 0, 153700499a22SXiaoyun Wang sizeof(struct rte_ether_addr)); 153800499a22SXiaoyun Wang } 153900499a22SXiaoyun Wang 154000499a22SXiaoyun Wang /* delete multicast mac addrs */ 154100499a22SXiaoyun Wang hinic_delete_mc_addr_list(nic_dev); 1542511b7371SGuoyang Zhou 1543511b7371SGuoyang Zhou rte_free(nic_dev->mc_list); 1544511b7371SGuoyang Zhou 154564727024SZiyang Xuan } 154664727024SZiyang Xuan 15478260eba6SXiaoyun Wang static int hinic_dev_set_mtu(struct rte_eth_dev *dev, uint16_t mtu) 15488260eba6SXiaoyun Wang { 15498260eba6SXiaoyun Wang struct hinic_nic_dev *nic_dev = HINIC_ETH_DEV_TO_PRIVATE_NIC_DEV(dev); 1550f7e04f57SFerruh Yigit int ret; 15518260eba6SXiaoyun Wang 15528260eba6SXiaoyun Wang PMD_DRV_LOG(INFO, "Set port mtu, port_id: %d, mtu: %d, max_pkt_len: %d", 15538260eba6SXiaoyun Wang dev->data->port_id, mtu, HINIC_MTU_TO_PKTLEN(mtu)); 15548260eba6SXiaoyun Wang 15558260eba6SXiaoyun Wang ret = hinic_set_port_mtu(nic_dev->hwdev, mtu); 15568260eba6SXiaoyun Wang if (ret) { 15578260eba6SXiaoyun Wang PMD_DRV_LOG(ERR, "Set port mtu failed, ret: %d", ret); 15588260eba6SXiaoyun Wang return ret; 15598260eba6SXiaoyun Wang } 15608260eba6SXiaoyun Wang 15618260eba6SXiaoyun Wang nic_dev->mtu_size = mtu; 15628260eba6SXiaoyun Wang 15638260eba6SXiaoyun Wang return ret; 15648260eba6SXiaoyun Wang } 15658260eba6SXiaoyun Wang 1566fdba3bf1SXiaoyun Wang static void hinic_store_vlan_filter(struct hinic_nic_dev *nic_dev, 1567fdba3bf1SXiaoyun Wang u16 vlan_id, bool on) 1568fdba3bf1SXiaoyun Wang { 1569fdba3bf1SXiaoyun Wang u32 vid_idx, vid_bit; 1570fdba3bf1SXiaoyun Wang 1571fdba3bf1SXiaoyun Wang vid_idx = HINIC_VFTA_IDX(vlan_id); 1572fdba3bf1SXiaoyun Wang vid_bit = HINIC_VFTA_BIT(vlan_id); 1573fdba3bf1SXiaoyun Wang 1574fdba3bf1SXiaoyun Wang if (on) 1575fdba3bf1SXiaoyun Wang nic_dev->vfta[vid_idx] |= vid_bit; 1576fdba3bf1SXiaoyun Wang else 1577fdba3bf1SXiaoyun Wang nic_dev->vfta[vid_idx] &= ~vid_bit; 1578fdba3bf1SXiaoyun Wang } 1579fdba3bf1SXiaoyun Wang 1580fdba3bf1SXiaoyun Wang static bool hinic_find_vlan_filter(struct hinic_nic_dev *nic_dev, 1581fdba3bf1SXiaoyun Wang uint16_t vlan_id) 1582fdba3bf1SXiaoyun Wang { 1583fdba3bf1SXiaoyun Wang u32 vid_idx, vid_bit; 1584fdba3bf1SXiaoyun Wang 1585fdba3bf1SXiaoyun Wang vid_idx = HINIC_VFTA_IDX(vlan_id); 1586fdba3bf1SXiaoyun Wang vid_bit = HINIC_VFTA_BIT(vlan_id); 1587fdba3bf1SXiaoyun Wang 1588fdba3bf1SXiaoyun Wang return (nic_dev->vfta[vid_idx] & vid_bit) ? TRUE : FALSE; 1589fdba3bf1SXiaoyun Wang } 1590fdba3bf1SXiaoyun Wang 1591fdba3bf1SXiaoyun Wang /** 1592fdba3bf1SXiaoyun Wang * DPDK callback to set vlan filter. 1593fdba3bf1SXiaoyun Wang * 1594fdba3bf1SXiaoyun Wang * @param dev 1595fdba3bf1SXiaoyun Wang * Pointer to Ethernet device structure. 1596fdba3bf1SXiaoyun Wang * @param vlan_id 1597fdba3bf1SXiaoyun Wang * vlan id is used to filter vlan packets 1598fdba3bf1SXiaoyun Wang * @param enable 1599fdba3bf1SXiaoyun Wang * enable disable or enable vlan filter function 1600fdba3bf1SXiaoyun Wang */ 1601fdba3bf1SXiaoyun Wang static int hinic_vlan_filter_set(struct rte_eth_dev *dev, 1602fdba3bf1SXiaoyun Wang uint16_t vlan_id, int enable) 1603fdba3bf1SXiaoyun Wang { 1604fdba3bf1SXiaoyun Wang struct hinic_nic_dev *nic_dev = HINIC_ETH_DEV_TO_PRIVATE_NIC_DEV(dev); 1605fdba3bf1SXiaoyun Wang int err = 0; 1606fdba3bf1SXiaoyun Wang u16 func_id; 1607fdba3bf1SXiaoyun Wang 1608fdba3bf1SXiaoyun Wang if (vlan_id > RTE_ETHER_MAX_VLAN_ID) 1609fdba3bf1SXiaoyun Wang return -EINVAL; 1610fdba3bf1SXiaoyun Wang 16112cfd68ecSGuoyang Zhou if (vlan_id == 0) 16122cfd68ecSGuoyang Zhou return 0; 16132cfd68ecSGuoyang Zhou 1614fdba3bf1SXiaoyun Wang func_id = hinic_global_func_id(nic_dev->hwdev); 1615fdba3bf1SXiaoyun Wang 1616fdba3bf1SXiaoyun Wang if (enable) { 1617fdba3bf1SXiaoyun Wang /* If vlanid is already set, just return */ 1618fdba3bf1SXiaoyun Wang if (hinic_find_vlan_filter(nic_dev, vlan_id)) { 1619fdba3bf1SXiaoyun Wang PMD_DRV_LOG(INFO, "Vlan %u has been added, device: %s", 1620fdba3bf1SXiaoyun Wang vlan_id, nic_dev->proc_dev_name); 1621fdba3bf1SXiaoyun Wang return 0; 1622fdba3bf1SXiaoyun Wang } 1623fdba3bf1SXiaoyun Wang 1624fdba3bf1SXiaoyun Wang err = hinic_add_remove_vlan(nic_dev->hwdev, vlan_id, 1625fdba3bf1SXiaoyun Wang func_id, TRUE); 1626fdba3bf1SXiaoyun Wang } else { 1627fdba3bf1SXiaoyun Wang /* If vlanid can't be found, just return */ 1628fdba3bf1SXiaoyun Wang if (!hinic_find_vlan_filter(nic_dev, vlan_id)) { 1629fdba3bf1SXiaoyun Wang PMD_DRV_LOG(INFO, "Vlan %u is not in the vlan filter list, device: %s", 1630fdba3bf1SXiaoyun Wang vlan_id, nic_dev->proc_dev_name); 1631fdba3bf1SXiaoyun Wang return 0; 1632fdba3bf1SXiaoyun Wang } 1633fdba3bf1SXiaoyun Wang 1634fdba3bf1SXiaoyun Wang err = hinic_add_remove_vlan(nic_dev->hwdev, vlan_id, 1635fdba3bf1SXiaoyun Wang func_id, FALSE); 1636fdba3bf1SXiaoyun Wang } 1637fdba3bf1SXiaoyun Wang 1638fdba3bf1SXiaoyun Wang if (err) { 1639fdba3bf1SXiaoyun Wang PMD_DRV_LOG(ERR, "%s vlan failed, func_id: %d, vlan_id: %d, err: %d", 1640fdba3bf1SXiaoyun Wang enable ? "Add" : "Remove", func_id, vlan_id, err); 1641fdba3bf1SXiaoyun Wang return err; 1642fdba3bf1SXiaoyun Wang } 1643fdba3bf1SXiaoyun Wang 1644fdba3bf1SXiaoyun Wang hinic_store_vlan_filter(nic_dev, vlan_id, enable); 1645fdba3bf1SXiaoyun Wang 1646fdba3bf1SXiaoyun Wang PMD_DRV_LOG(INFO, "%s vlan %u succeed, device: %s", 1647fdba3bf1SXiaoyun Wang enable ? "Add" : "Remove", vlan_id, nic_dev->proc_dev_name); 1648fdba3bf1SXiaoyun Wang return 0; 1649fdba3bf1SXiaoyun Wang } 1650fdba3bf1SXiaoyun Wang 1651fdba3bf1SXiaoyun Wang /** 1652fdba3bf1SXiaoyun Wang * DPDK callback to enable or disable vlan offload. 1653fdba3bf1SXiaoyun Wang * 1654fdba3bf1SXiaoyun Wang * @param dev 1655fdba3bf1SXiaoyun Wang * Pointer to Ethernet device structure. 1656fdba3bf1SXiaoyun Wang * @param mask 1657fdba3bf1SXiaoyun Wang * Definitions used for VLAN setting 1658fdba3bf1SXiaoyun Wang */ 1659fdba3bf1SXiaoyun Wang static int hinic_vlan_offload_set(struct rte_eth_dev *dev, int mask) 1660fdba3bf1SXiaoyun Wang { 1661fdba3bf1SXiaoyun Wang struct hinic_nic_dev *nic_dev = HINIC_ETH_DEV_TO_PRIVATE_NIC_DEV(dev); 1662fdba3bf1SXiaoyun Wang struct rte_eth_rxmode *rxmode = &dev->data->dev_conf.rxmode; 1663fdba3bf1SXiaoyun Wang bool on; 1664fdba3bf1SXiaoyun Wang int err; 1665fdba3bf1SXiaoyun Wang 1666fdba3bf1SXiaoyun Wang /* Enable or disable VLAN filter */ 1667295968d1SFerruh Yigit if (mask & RTE_ETH_VLAN_FILTER_MASK) { 1668295968d1SFerruh Yigit on = (rxmode->offloads & RTE_ETH_RX_OFFLOAD_VLAN_FILTER) ? 1669fdba3bf1SXiaoyun Wang TRUE : FALSE; 1670fdba3bf1SXiaoyun Wang err = hinic_config_vlan_filter(nic_dev->hwdev, on); 1671fdba3bf1SXiaoyun Wang if (err == HINIC_MGMT_CMD_UNSUPPORTED) { 1672fdba3bf1SXiaoyun Wang PMD_DRV_LOG(WARNING, 1673fdba3bf1SXiaoyun Wang "Current matching version does not support vlan filter configuration, device: %s, port_id: %d", 1674fdba3bf1SXiaoyun Wang nic_dev->proc_dev_name, dev->data->port_id); 1675fdba3bf1SXiaoyun Wang } else if (err) { 1676fdba3bf1SXiaoyun Wang PMD_DRV_LOG(ERR, "Failed to %s vlan filter, device: %s, port_id: %d, err: %d", 1677fdba3bf1SXiaoyun Wang on ? "enable" : "disable", 1678fdba3bf1SXiaoyun Wang nic_dev->proc_dev_name, 1679fdba3bf1SXiaoyun Wang dev->data->port_id, err); 1680fdba3bf1SXiaoyun Wang return err; 1681fdba3bf1SXiaoyun Wang } 1682fdba3bf1SXiaoyun Wang 1683fdba3bf1SXiaoyun Wang PMD_DRV_LOG(INFO, "%s vlan filter succeed, device: %s, port_id: %d", 1684fdba3bf1SXiaoyun Wang on ? "Enable" : "Disable", 1685fdba3bf1SXiaoyun Wang nic_dev->proc_dev_name, dev->data->port_id); 1686fdba3bf1SXiaoyun Wang } 1687fdba3bf1SXiaoyun Wang 1688fdba3bf1SXiaoyun Wang /* Enable or disable VLAN stripping */ 1689295968d1SFerruh Yigit if (mask & RTE_ETH_VLAN_STRIP_MASK) { 1690295968d1SFerruh Yigit on = (rxmode->offloads & RTE_ETH_RX_OFFLOAD_VLAN_STRIP) ? 1691fdba3bf1SXiaoyun Wang TRUE : FALSE; 1692fdba3bf1SXiaoyun Wang err = hinic_set_rx_vlan_offload(nic_dev->hwdev, on); 1693fdba3bf1SXiaoyun Wang if (err) { 1694fdba3bf1SXiaoyun Wang PMD_DRV_LOG(ERR, "Failed to %s vlan strip, device: %s, port_id: %d, err: %d", 1695fdba3bf1SXiaoyun Wang on ? "enable" : "disable", 1696fdba3bf1SXiaoyun Wang nic_dev->proc_dev_name, 1697fdba3bf1SXiaoyun Wang dev->data->port_id, err); 1698fdba3bf1SXiaoyun Wang return err; 1699fdba3bf1SXiaoyun Wang } 1700fdba3bf1SXiaoyun Wang 1701fdba3bf1SXiaoyun Wang PMD_DRV_LOG(INFO, "%s vlan strip succeed, device: %s, port_id: %d", 1702fdba3bf1SXiaoyun Wang on ? "Enable" : "Disable", 1703fdba3bf1SXiaoyun Wang nic_dev->proc_dev_name, dev->data->port_id); 1704fdba3bf1SXiaoyun Wang } 1705fdba3bf1SXiaoyun Wang 1706fdba3bf1SXiaoyun Wang return 0; 1707fdba3bf1SXiaoyun Wang } 1708fdba3bf1SXiaoyun Wang 1709fdba3bf1SXiaoyun Wang static void hinic_remove_all_vlanid(struct rte_eth_dev *eth_dev) 1710fdba3bf1SXiaoyun Wang { 1711fdba3bf1SXiaoyun Wang struct hinic_nic_dev *nic_dev = 1712fdba3bf1SXiaoyun Wang HINIC_ETH_DEV_TO_PRIVATE_NIC_DEV(eth_dev); 1713fdba3bf1SXiaoyun Wang u16 func_id; 1714fdba3bf1SXiaoyun Wang int i; 1715fdba3bf1SXiaoyun Wang 1716fdba3bf1SXiaoyun Wang func_id = hinic_global_func_id(nic_dev->hwdev); 1717fdba3bf1SXiaoyun Wang for (i = 0; i <= RTE_ETHER_MAX_VLAN_ID; i++) { 1718fdba3bf1SXiaoyun Wang /* If can't find it, continue */ 1719fdba3bf1SXiaoyun Wang if (!hinic_find_vlan_filter(nic_dev, i)) 1720fdba3bf1SXiaoyun Wang continue; 1721fdba3bf1SXiaoyun Wang 1722fdba3bf1SXiaoyun Wang (void)hinic_add_remove_vlan(nic_dev->hwdev, i, func_id, FALSE); 1723fdba3bf1SXiaoyun Wang hinic_store_vlan_filter(nic_dev, i, false); 1724fdba3bf1SXiaoyun Wang } 1725fdba3bf1SXiaoyun Wang } 1726fdba3bf1SXiaoyun Wang 17278260eba6SXiaoyun Wang static int hinic_set_dev_allmulticast(struct hinic_nic_dev *nic_dev, 17288260eba6SXiaoyun Wang bool enable) 17298260eba6SXiaoyun Wang { 1730224cff4bSXiaoyun Wang u32 rx_mode_ctrl; 1731224cff4bSXiaoyun Wang int err; 1732224cff4bSXiaoyun Wang 1733224cff4bSXiaoyun Wang err = hinic_mutex_lock(&nic_dev->rx_mode_mutex); 1734224cff4bSXiaoyun Wang if (err) 1735224cff4bSXiaoyun Wang return err; 1736224cff4bSXiaoyun Wang 1737224cff4bSXiaoyun Wang rx_mode_ctrl = nic_dev->rx_mode_status; 17388260eba6SXiaoyun Wang 17398260eba6SXiaoyun Wang if (enable) 17408260eba6SXiaoyun Wang rx_mode_ctrl |= HINIC_RX_MODE_MC_ALL; 17418260eba6SXiaoyun Wang else 17428260eba6SXiaoyun Wang rx_mode_ctrl &= (~HINIC_RX_MODE_MC_ALL); 17438260eba6SXiaoyun Wang 1744224cff4bSXiaoyun Wang err = hinic_config_rx_mode(nic_dev, rx_mode_ctrl); 1745224cff4bSXiaoyun Wang 1746224cff4bSXiaoyun Wang (void)hinic_mutex_unlock(&nic_dev->rx_mode_mutex); 1747224cff4bSXiaoyun Wang 1748224cff4bSXiaoyun Wang return err; 17498260eba6SXiaoyun Wang } 17508260eba6SXiaoyun Wang 17518260eba6SXiaoyun Wang /** 17528260eba6SXiaoyun Wang * DPDK callback to enable allmulticast mode. 17538260eba6SXiaoyun Wang * 17548260eba6SXiaoyun Wang * @param dev 17558260eba6SXiaoyun Wang * Pointer to Ethernet device structure. 17568260eba6SXiaoyun Wang * 17578260eba6SXiaoyun Wang * @return 17588260eba6SXiaoyun Wang * 0 on success, 17598260eba6SXiaoyun Wang * negative error value otherwise. 17608260eba6SXiaoyun Wang */ 17618260eba6SXiaoyun Wang static int hinic_dev_allmulticast_enable(struct rte_eth_dev *dev) 17628260eba6SXiaoyun Wang { 17638260eba6SXiaoyun Wang int ret = HINIC_OK; 17648260eba6SXiaoyun Wang struct hinic_nic_dev *nic_dev = HINIC_ETH_DEV_TO_PRIVATE_NIC_DEV(dev); 17658260eba6SXiaoyun Wang 17668260eba6SXiaoyun Wang ret = hinic_set_dev_allmulticast(nic_dev, true); 17678260eba6SXiaoyun Wang if (ret) { 17688260eba6SXiaoyun Wang PMD_DRV_LOG(ERR, "Enable allmulticast failed, error: %d", ret); 17698260eba6SXiaoyun Wang return ret; 17708260eba6SXiaoyun Wang } 17718260eba6SXiaoyun Wang 17728260eba6SXiaoyun Wang PMD_DRV_LOG(INFO, "Enable allmulticast succeed, nic_dev: %s, port_id: %d", 17738260eba6SXiaoyun Wang nic_dev->proc_dev_name, dev->data->port_id); 17748260eba6SXiaoyun Wang return 0; 17758260eba6SXiaoyun Wang } 17768260eba6SXiaoyun Wang 17778260eba6SXiaoyun Wang /** 17788260eba6SXiaoyun Wang * DPDK callback to disable allmulticast mode. 17798260eba6SXiaoyun Wang * 17808260eba6SXiaoyun Wang * @param dev 17818260eba6SXiaoyun Wang * Pointer to Ethernet device structure. 17828260eba6SXiaoyun Wang * 17838260eba6SXiaoyun Wang * @return 17848260eba6SXiaoyun Wang * 0 on success, 17858260eba6SXiaoyun Wang * negative error value otherwise. 17868260eba6SXiaoyun Wang */ 17878260eba6SXiaoyun Wang static int hinic_dev_allmulticast_disable(struct rte_eth_dev *dev) 17888260eba6SXiaoyun Wang { 17898260eba6SXiaoyun Wang int ret = HINIC_OK; 17908260eba6SXiaoyun Wang struct hinic_nic_dev *nic_dev = HINIC_ETH_DEV_TO_PRIVATE_NIC_DEV(dev); 17918260eba6SXiaoyun Wang 17928260eba6SXiaoyun Wang ret = hinic_set_dev_allmulticast(nic_dev, false); 17938260eba6SXiaoyun Wang if (ret) { 17948260eba6SXiaoyun Wang PMD_DRV_LOG(ERR, "Disable allmulticast failed, error: %d", ret); 17958260eba6SXiaoyun Wang return ret; 17968260eba6SXiaoyun Wang } 17978260eba6SXiaoyun Wang 17988260eba6SXiaoyun Wang PMD_DRV_LOG(INFO, "Disable allmulticast succeed, nic_dev: %s, port_id: %d", 17998260eba6SXiaoyun Wang nic_dev->proc_dev_name, dev->data->port_id); 18008260eba6SXiaoyun Wang return 0; 18018260eba6SXiaoyun Wang } 18028260eba6SXiaoyun Wang 1803cb7b6606SZiyang Xuan /** 1804cb7b6606SZiyang Xuan * DPDK callback to enable promiscuous mode. 1805cb7b6606SZiyang Xuan * 1806cb7b6606SZiyang Xuan * @param dev 1807cb7b6606SZiyang Xuan * Pointer to Ethernet device structure. 18089039c812SAndrew Rybchenko * 18099039c812SAndrew Rybchenko * @return 18109039c812SAndrew Rybchenko * 0 on success, 18119039c812SAndrew Rybchenko * negative error value otherwise. 1812cb7b6606SZiyang Xuan */ 18139039c812SAndrew Rybchenko static int hinic_dev_promiscuous_enable(struct rte_eth_dev *dev) 1814cb7b6606SZiyang Xuan { 1815cb7b6606SZiyang Xuan int rc = HINIC_OK; 1816cb7b6606SZiyang Xuan struct hinic_nic_dev *nic_dev = HINIC_ETH_DEV_TO_PRIVATE_NIC_DEV(dev); 1817cb7b6606SZiyang Xuan 1818cb7b6606SZiyang Xuan PMD_DRV_LOG(INFO, "Enable promiscuous, nic_dev: %s, port_id: %d, promisc: %d", 1819cb7b6606SZiyang Xuan nic_dev->proc_dev_name, dev->data->port_id, 1820cb7b6606SZiyang Xuan dev->data->promiscuous); 1821cb7b6606SZiyang Xuan 1822cb7b6606SZiyang Xuan rc = hinic_set_dev_promiscuous(nic_dev, true); 1823cb7b6606SZiyang Xuan if (rc) 1824cb7b6606SZiyang Xuan PMD_DRV_LOG(ERR, "Enable promiscuous failed"); 18259039c812SAndrew Rybchenko 18269039c812SAndrew Rybchenko return rc; 1827cb7b6606SZiyang Xuan } 1828cb7b6606SZiyang Xuan 1829cb7b6606SZiyang Xuan /** 1830cb7b6606SZiyang Xuan * DPDK callback to disable promiscuous mode. 1831cb7b6606SZiyang Xuan * 1832cb7b6606SZiyang Xuan * @param dev 1833cb7b6606SZiyang Xuan * Pointer to Ethernet device structure. 18349039c812SAndrew Rybchenko * 18359039c812SAndrew Rybchenko * @return 18369039c812SAndrew Rybchenko * 0 on success, 18379039c812SAndrew Rybchenko * negative error value otherwise. 1838cb7b6606SZiyang Xuan */ 18399039c812SAndrew Rybchenko static int hinic_dev_promiscuous_disable(struct rte_eth_dev *dev) 1840cb7b6606SZiyang Xuan { 1841cb7b6606SZiyang Xuan int rc = HINIC_OK; 1842cb7b6606SZiyang Xuan struct hinic_nic_dev *nic_dev = HINIC_ETH_DEV_TO_PRIVATE_NIC_DEV(dev); 1843cb7b6606SZiyang Xuan 1844cb7b6606SZiyang Xuan PMD_DRV_LOG(INFO, "Disable promiscuous, nic_dev: %s, port_id: %d, promisc: %d", 1845cb7b6606SZiyang Xuan nic_dev->proc_dev_name, dev->data->port_id, 1846cb7b6606SZiyang Xuan dev->data->promiscuous); 1847cb7b6606SZiyang Xuan 1848cb7b6606SZiyang Xuan rc = hinic_set_dev_promiscuous(nic_dev, false); 1849cb7b6606SZiyang Xuan if (rc) 1850cb7b6606SZiyang Xuan PMD_DRV_LOG(ERR, "Disable promiscuous failed"); 18519039c812SAndrew Rybchenko 18529039c812SAndrew Rybchenko return rc; 1853cb7b6606SZiyang Xuan } 1854cb7b6606SZiyang Xuan 1855ef6f2f5cSXiaoyun Wang static int hinic_flow_ctrl_get(struct rte_eth_dev *dev, 1856ef6f2f5cSXiaoyun Wang struct rte_eth_fc_conf *fc_conf) 1857ef6f2f5cSXiaoyun Wang { 1858ef6f2f5cSXiaoyun Wang struct hinic_nic_dev *nic_dev = HINIC_ETH_DEV_TO_PRIVATE_NIC_DEV(dev); 1859ef6f2f5cSXiaoyun Wang struct nic_pause_config nic_pause; 1860ef6f2f5cSXiaoyun Wang int err; 1861ef6f2f5cSXiaoyun Wang 1862ef6f2f5cSXiaoyun Wang memset(&nic_pause, 0, sizeof(nic_pause)); 1863ef6f2f5cSXiaoyun Wang 1864ef6f2f5cSXiaoyun Wang err = hinic_get_pause_info(nic_dev->hwdev, &nic_pause); 1865ef6f2f5cSXiaoyun Wang if (err) 1866ef6f2f5cSXiaoyun Wang return err; 1867ef6f2f5cSXiaoyun Wang 1868ef6f2f5cSXiaoyun Wang if (nic_dev->pause_set || !nic_pause.auto_neg) { 1869ef6f2f5cSXiaoyun Wang nic_pause.rx_pause = nic_dev->nic_pause.rx_pause; 1870ef6f2f5cSXiaoyun Wang nic_pause.tx_pause = nic_dev->nic_pause.tx_pause; 1871ef6f2f5cSXiaoyun Wang } 1872ef6f2f5cSXiaoyun Wang 1873ef6f2f5cSXiaoyun Wang fc_conf->autoneg = nic_pause.auto_neg; 1874ef6f2f5cSXiaoyun Wang 1875ef6f2f5cSXiaoyun Wang if (nic_pause.tx_pause && nic_pause.rx_pause) 1876295968d1SFerruh Yigit fc_conf->mode = RTE_ETH_FC_FULL; 1877ef6f2f5cSXiaoyun Wang else if (nic_pause.tx_pause) 1878295968d1SFerruh Yigit fc_conf->mode = RTE_ETH_FC_TX_PAUSE; 1879ef6f2f5cSXiaoyun Wang else if (nic_pause.rx_pause) 1880295968d1SFerruh Yigit fc_conf->mode = RTE_ETH_FC_RX_PAUSE; 1881ef6f2f5cSXiaoyun Wang else 1882295968d1SFerruh Yigit fc_conf->mode = RTE_ETH_FC_NONE; 1883ef6f2f5cSXiaoyun Wang 1884ef6f2f5cSXiaoyun Wang return 0; 1885ef6f2f5cSXiaoyun Wang } 1886ef6f2f5cSXiaoyun Wang 1887ef6f2f5cSXiaoyun Wang static int hinic_flow_ctrl_set(struct rte_eth_dev *dev, 1888ef6f2f5cSXiaoyun Wang struct rte_eth_fc_conf *fc_conf) 1889ef6f2f5cSXiaoyun Wang { 1890ef6f2f5cSXiaoyun Wang struct hinic_nic_dev *nic_dev = HINIC_ETH_DEV_TO_PRIVATE_NIC_DEV(dev); 1891ef6f2f5cSXiaoyun Wang struct nic_pause_config nic_pause; 1892ef6f2f5cSXiaoyun Wang int err; 1893ef6f2f5cSXiaoyun Wang 1894ef6f2f5cSXiaoyun Wang nic_pause.auto_neg = fc_conf->autoneg; 1895ef6f2f5cSXiaoyun Wang 1896295968d1SFerruh Yigit if (((fc_conf->mode & RTE_ETH_FC_FULL) == RTE_ETH_FC_FULL) || 1897295968d1SFerruh Yigit (fc_conf->mode & RTE_ETH_FC_TX_PAUSE)) 1898ef6f2f5cSXiaoyun Wang nic_pause.tx_pause = true; 1899ef6f2f5cSXiaoyun Wang else 1900ef6f2f5cSXiaoyun Wang nic_pause.tx_pause = false; 1901ef6f2f5cSXiaoyun Wang 1902295968d1SFerruh Yigit if (((fc_conf->mode & RTE_ETH_FC_FULL) == RTE_ETH_FC_FULL) || 1903295968d1SFerruh Yigit (fc_conf->mode & RTE_ETH_FC_RX_PAUSE)) 1904ef6f2f5cSXiaoyun Wang nic_pause.rx_pause = true; 1905ef6f2f5cSXiaoyun Wang else 1906ef6f2f5cSXiaoyun Wang nic_pause.rx_pause = false; 1907ef6f2f5cSXiaoyun Wang 1908ef6f2f5cSXiaoyun Wang err = hinic_set_pause_config(nic_dev->hwdev, nic_pause); 1909ef6f2f5cSXiaoyun Wang if (err) 1910ef6f2f5cSXiaoyun Wang return err; 1911ef6f2f5cSXiaoyun Wang 1912ef6f2f5cSXiaoyun Wang nic_dev->pause_set = true; 1913ef6f2f5cSXiaoyun Wang nic_dev->nic_pause.auto_neg = nic_pause.auto_neg; 1914ef6f2f5cSXiaoyun Wang nic_dev->nic_pause.rx_pause = nic_pause.rx_pause; 1915ef6f2f5cSXiaoyun Wang nic_dev->nic_pause.tx_pause = nic_pause.tx_pause; 1916ef6f2f5cSXiaoyun Wang 1917*f665790aSDavid Marchand PMD_DRV_LOG(INFO, "Set pause options, tx: %s, rx: %s, auto: %s", 1918ef6f2f5cSXiaoyun Wang nic_pause.tx_pause ? "on" : "off", 1919ef6f2f5cSXiaoyun Wang nic_pause.rx_pause ? "on" : "off", 1920ef6f2f5cSXiaoyun Wang nic_pause.auto_neg ? "on" : "off"); 1921ef6f2f5cSXiaoyun Wang 1922ef6f2f5cSXiaoyun Wang return 0; 1923ef6f2f5cSXiaoyun Wang } 1924ef6f2f5cSXiaoyun Wang 1925cb7b6606SZiyang Xuan /** 1926cb7b6606SZiyang Xuan * DPDK callback to update the RSS hash key and RSS hash type. 1927cb7b6606SZiyang Xuan * 1928cb7b6606SZiyang Xuan * @param dev 1929cb7b6606SZiyang Xuan * Pointer to Ethernet device structure. 1930cb7b6606SZiyang Xuan * @param rss_conf 1931cb7b6606SZiyang Xuan * RSS configuration data. 1932cb7b6606SZiyang Xuan * 1933cb7b6606SZiyang Xuan * @return 1934cb7b6606SZiyang Xuan * 0 on success, negative error value otherwise. 1935cb7b6606SZiyang Xuan */ 1936cb7b6606SZiyang Xuan static int hinic_rss_hash_update(struct rte_eth_dev *dev, 1937cb7b6606SZiyang Xuan struct rte_eth_rss_conf *rss_conf) 1938cb7b6606SZiyang Xuan { 1939cb7b6606SZiyang Xuan struct hinic_nic_dev *nic_dev = HINIC_ETH_DEV_TO_PRIVATE_NIC_DEV(dev); 1940cb7b6606SZiyang Xuan u8 tmpl_idx = nic_dev->rss_tmpl_idx; 1941cb7b6606SZiyang Xuan u8 hashkey[HINIC_RSS_KEY_SIZE] = {0}; 1942cb7b6606SZiyang Xuan u8 prio_tc[HINIC_DCB_UP_MAX] = {0}; 1943cb7b6606SZiyang Xuan u64 rss_hf = rss_conf->rss_hf; 1944cb7b6606SZiyang Xuan struct nic_rss_type rss_type = {0}; 1945cb7b6606SZiyang Xuan int err = 0; 1946cb7b6606SZiyang Xuan 1947295968d1SFerruh Yigit if (!(nic_dev->flags & RTE_ETH_MQ_RX_RSS_FLAG)) { 1948cb7b6606SZiyang Xuan PMD_DRV_LOG(WARNING, "RSS is not enabled"); 1949cb7b6606SZiyang Xuan return HINIC_OK; 1950cb7b6606SZiyang Xuan } 1951cb7b6606SZiyang Xuan 1952cb7b6606SZiyang Xuan if (rss_conf->rss_key_len > HINIC_RSS_KEY_SIZE) { 1953cb7b6606SZiyang Xuan PMD_DRV_LOG(ERR, "Invalid rss key, rss_key_len: %d", 1954cb7b6606SZiyang Xuan rss_conf->rss_key_len); 1955cb7b6606SZiyang Xuan return HINIC_ERROR; 1956cb7b6606SZiyang Xuan } 1957cb7b6606SZiyang Xuan 1958cb7b6606SZiyang Xuan if (rss_conf->rss_key) { 1959cb7b6606SZiyang Xuan memcpy(hashkey, rss_conf->rss_key, rss_conf->rss_key_len); 1960cb7b6606SZiyang Xuan err = hinic_rss_set_template_tbl(nic_dev->hwdev, tmpl_idx, 1961cb7b6606SZiyang Xuan hashkey); 1962cb7b6606SZiyang Xuan if (err) { 1963cb7b6606SZiyang Xuan PMD_DRV_LOG(ERR, "Set rss template table failed"); 1964cb7b6606SZiyang Xuan goto disable_rss; 1965cb7b6606SZiyang Xuan } 1966cb7b6606SZiyang Xuan } 1967cb7b6606SZiyang Xuan 1968295968d1SFerruh Yigit rss_type.ipv4 = (rss_hf & (RTE_ETH_RSS_IPV4 | RTE_ETH_RSS_FRAG_IPV4)) ? 1 : 0; 1969295968d1SFerruh Yigit rss_type.tcp_ipv4 = (rss_hf & RTE_ETH_RSS_NONFRAG_IPV4_TCP) ? 1 : 0; 1970295968d1SFerruh Yigit rss_type.ipv6 = (rss_hf & (RTE_ETH_RSS_IPV6 | RTE_ETH_RSS_FRAG_IPV6)) ? 1 : 0; 1971295968d1SFerruh Yigit rss_type.ipv6_ext = (rss_hf & RTE_ETH_RSS_IPV6_EX) ? 1 : 0; 1972295968d1SFerruh Yigit rss_type.tcp_ipv6 = (rss_hf & RTE_ETH_RSS_NONFRAG_IPV6_TCP) ? 1 : 0; 1973295968d1SFerruh Yigit rss_type.tcp_ipv6_ext = (rss_hf & RTE_ETH_RSS_IPV6_TCP_EX) ? 1 : 0; 1974295968d1SFerruh Yigit rss_type.udp_ipv4 = (rss_hf & RTE_ETH_RSS_NONFRAG_IPV4_UDP) ? 1 : 0; 1975295968d1SFerruh Yigit rss_type.udp_ipv6 = (rss_hf & RTE_ETH_RSS_NONFRAG_IPV6_UDP) ? 1 : 0; 1976cb7b6606SZiyang Xuan 1977cb7b6606SZiyang Xuan err = hinic_set_rss_type(nic_dev->hwdev, tmpl_idx, rss_type); 1978cb7b6606SZiyang Xuan if (err) { 1979cb7b6606SZiyang Xuan PMD_DRV_LOG(ERR, "Set rss type table failed"); 1980cb7b6606SZiyang Xuan goto disable_rss; 1981cb7b6606SZiyang Xuan } 1982cb7b6606SZiyang Xuan 1983cb7b6606SZiyang Xuan return 0; 1984cb7b6606SZiyang Xuan 1985cb7b6606SZiyang Xuan disable_rss: 1986cb7b6606SZiyang Xuan memset(prio_tc, 0, sizeof(prio_tc)); 1987cb7b6606SZiyang Xuan (void)hinic_rss_cfg(nic_dev->hwdev, 0, tmpl_idx, 0, prio_tc); 1988cb7b6606SZiyang Xuan return err; 1989cb7b6606SZiyang Xuan } 1990cb7b6606SZiyang Xuan 1991cb7b6606SZiyang Xuan /** 1992cb7b6606SZiyang Xuan * DPDK callback to get the RSS hash configuration. 1993cb7b6606SZiyang Xuan * 1994cb7b6606SZiyang Xuan * @param dev 1995cb7b6606SZiyang Xuan * Pointer to Ethernet device structure. 1996cb7b6606SZiyang Xuan * @param rss_conf 1997cb7b6606SZiyang Xuan * RSS configuration data. 1998cb7b6606SZiyang Xuan * 1999cb7b6606SZiyang Xuan * @return 2000cb7b6606SZiyang Xuan * 0 on success, negative error value otherwise. 2001cb7b6606SZiyang Xuan */ 2002cb7b6606SZiyang Xuan static int hinic_rss_conf_get(struct rte_eth_dev *dev, 2003cb7b6606SZiyang Xuan struct rte_eth_rss_conf *rss_conf) 2004cb7b6606SZiyang Xuan { 2005cb7b6606SZiyang Xuan struct hinic_nic_dev *nic_dev = HINIC_ETH_DEV_TO_PRIVATE_NIC_DEV(dev); 2006cb7b6606SZiyang Xuan u8 tmpl_idx = nic_dev->rss_tmpl_idx; 2007cb7b6606SZiyang Xuan u8 hashkey[HINIC_RSS_KEY_SIZE] = {0}; 2008cb7b6606SZiyang Xuan struct nic_rss_type rss_type = {0}; 2009cb7b6606SZiyang Xuan int err; 2010cb7b6606SZiyang Xuan 2011295968d1SFerruh Yigit if (!(nic_dev->flags & RTE_ETH_MQ_RX_RSS_FLAG)) { 2012cb7b6606SZiyang Xuan PMD_DRV_LOG(WARNING, "RSS is not enabled"); 2013cb7b6606SZiyang Xuan return HINIC_ERROR; 2014cb7b6606SZiyang Xuan } 2015cb7b6606SZiyang Xuan 2016cb7b6606SZiyang Xuan err = hinic_rss_get_template_tbl(nic_dev->hwdev, tmpl_idx, hashkey); 2017cb7b6606SZiyang Xuan if (err) 2018cb7b6606SZiyang Xuan return err; 2019cb7b6606SZiyang Xuan 2020cb7b6606SZiyang Xuan if (rss_conf->rss_key && 2021cb7b6606SZiyang Xuan rss_conf->rss_key_len >= HINIC_RSS_KEY_SIZE) { 2022cb7b6606SZiyang Xuan memcpy(rss_conf->rss_key, hashkey, sizeof(hashkey)); 2023cb7b6606SZiyang Xuan rss_conf->rss_key_len = sizeof(hashkey); 2024cb7b6606SZiyang Xuan } 2025cb7b6606SZiyang Xuan 2026cb7b6606SZiyang Xuan err = hinic_get_rss_type(nic_dev->hwdev, tmpl_idx, &rss_type); 2027cb7b6606SZiyang Xuan if (err) 2028cb7b6606SZiyang Xuan return err; 2029cb7b6606SZiyang Xuan 2030cb7b6606SZiyang Xuan rss_conf->rss_hf = 0; 2031cb7b6606SZiyang Xuan rss_conf->rss_hf |= rss_type.ipv4 ? 2032295968d1SFerruh Yigit (RTE_ETH_RSS_IPV4 | RTE_ETH_RSS_FRAG_IPV4) : 0; 2033295968d1SFerruh Yigit rss_conf->rss_hf |= rss_type.tcp_ipv4 ? RTE_ETH_RSS_NONFRAG_IPV4_TCP : 0; 2034cb7b6606SZiyang Xuan rss_conf->rss_hf |= rss_type.ipv6 ? 2035295968d1SFerruh Yigit (RTE_ETH_RSS_IPV6 | RTE_ETH_RSS_FRAG_IPV6) : 0; 2036295968d1SFerruh Yigit rss_conf->rss_hf |= rss_type.ipv6_ext ? RTE_ETH_RSS_IPV6_EX : 0; 2037295968d1SFerruh Yigit rss_conf->rss_hf |= rss_type.tcp_ipv6 ? RTE_ETH_RSS_NONFRAG_IPV6_TCP : 0; 2038295968d1SFerruh Yigit rss_conf->rss_hf |= rss_type.tcp_ipv6_ext ? RTE_ETH_RSS_IPV6_TCP_EX : 0; 2039295968d1SFerruh Yigit rss_conf->rss_hf |= rss_type.udp_ipv4 ? RTE_ETH_RSS_NONFRAG_IPV4_UDP : 0; 2040295968d1SFerruh Yigit rss_conf->rss_hf |= rss_type.udp_ipv6 ? RTE_ETH_RSS_NONFRAG_IPV6_UDP : 0; 2041cb7b6606SZiyang Xuan 2042cb7b6606SZiyang Xuan return HINIC_OK; 2043cb7b6606SZiyang Xuan } 2044cb7b6606SZiyang Xuan 2045cb7b6606SZiyang Xuan /** 2046f372a65fSXiaoyun Wang * DPDK callback to update the RSS redirection table. 2047cb7b6606SZiyang Xuan * 2048cb7b6606SZiyang Xuan * @param dev 2049cb7b6606SZiyang Xuan * Pointer to Ethernet device structure. 2050cb7b6606SZiyang Xuan * @param reta_conf 2051f372a65fSXiaoyun Wang * Pointer to RSS reta configuration data. 2052cb7b6606SZiyang Xuan * @param reta_size 2053cb7b6606SZiyang Xuan * Size of the RETA table. 2054cb7b6606SZiyang Xuan * 2055cb7b6606SZiyang Xuan * @return 2056cb7b6606SZiyang Xuan * 0 on success, negative error value otherwise. 2057cb7b6606SZiyang Xuan */ 2058cb7b6606SZiyang Xuan static int hinic_rss_indirtbl_update(struct rte_eth_dev *dev, 2059cb7b6606SZiyang Xuan struct rte_eth_rss_reta_entry64 *reta_conf, 2060cb7b6606SZiyang Xuan uint16_t reta_size) 2061cb7b6606SZiyang Xuan { 2062cb7b6606SZiyang Xuan struct hinic_nic_dev *nic_dev = HINIC_ETH_DEV_TO_PRIVATE_NIC_DEV(dev); 2063cb7b6606SZiyang Xuan u8 tmpl_idx = nic_dev->rss_tmpl_idx; 2064cb7b6606SZiyang Xuan u8 prio_tc[HINIC_DCB_UP_MAX] = {0}; 2065cb7b6606SZiyang Xuan u32 indirtbl[NIC_RSS_INDIR_SIZE] = {0}; 2066cb7b6606SZiyang Xuan int err = 0; 2067cb7b6606SZiyang Xuan u16 i = 0; 2068cb7b6606SZiyang Xuan u16 idx, shift; 2069cb7b6606SZiyang Xuan 2070295968d1SFerruh Yigit if (!(nic_dev->flags & RTE_ETH_MQ_RX_RSS_FLAG)) 2071cb7b6606SZiyang Xuan return HINIC_OK; 2072cb7b6606SZiyang Xuan 2073cb7b6606SZiyang Xuan if (reta_size != NIC_RSS_INDIR_SIZE) { 2074cb7b6606SZiyang Xuan PMD_DRV_LOG(ERR, "Invalid reta size, reta_size: %d", reta_size); 2075cb7b6606SZiyang Xuan return HINIC_ERROR; 2076cb7b6606SZiyang Xuan } 2077cb7b6606SZiyang Xuan 2078cb7b6606SZiyang Xuan err = hinic_rss_get_indir_tbl(nic_dev->hwdev, tmpl_idx, indirtbl); 2079cb7b6606SZiyang Xuan if (err) 2080cb7b6606SZiyang Xuan return err; 2081cb7b6606SZiyang Xuan 2082cb7b6606SZiyang Xuan /* update rss indir_tbl */ 2083cb7b6606SZiyang Xuan for (i = 0; i < reta_size; i++) { 2084295968d1SFerruh Yigit idx = i / RTE_ETH_RETA_GROUP_SIZE; 2085295968d1SFerruh Yigit shift = i % RTE_ETH_RETA_GROUP_SIZE; 208672babbc0SXiaoyun Wang 208772babbc0SXiaoyun Wang if (reta_conf[idx].reta[shift] >= nic_dev->num_rq) { 208872babbc0SXiaoyun Wang PMD_DRV_LOG(ERR, "Invalid reta entry, indirtbl[%d]: %d " 208972babbc0SXiaoyun Wang "exceeds the maximum rxq num: %d", i, 209072babbc0SXiaoyun Wang reta_conf[idx].reta[shift], nic_dev->num_rq); 209172babbc0SXiaoyun Wang return -EINVAL; 2092cb7b6606SZiyang Xuan } 2093cb7b6606SZiyang Xuan 209472babbc0SXiaoyun Wang if (reta_conf[idx].mask & (1ULL << shift)) 209572babbc0SXiaoyun Wang indirtbl[i] = reta_conf[idx].reta[shift]; 2096cb7b6606SZiyang Xuan } 2097cb7b6606SZiyang Xuan 2098cb7b6606SZiyang Xuan err = hinic_rss_set_indir_tbl(nic_dev->hwdev, tmpl_idx, indirtbl); 2099cb7b6606SZiyang Xuan if (err) 2100cb7b6606SZiyang Xuan goto disable_rss; 2101cb7b6606SZiyang Xuan 2102cb7b6606SZiyang Xuan nic_dev->rss_indir_flag = true; 2103cb7b6606SZiyang Xuan 2104cb7b6606SZiyang Xuan return 0; 2105cb7b6606SZiyang Xuan 2106cb7b6606SZiyang Xuan disable_rss: 2107cb7b6606SZiyang Xuan memset(prio_tc, 0, sizeof(prio_tc)); 2108cb7b6606SZiyang Xuan (void)hinic_rss_cfg(nic_dev->hwdev, 0, tmpl_idx, 0, prio_tc); 2109cb7b6606SZiyang Xuan 2110cb7b6606SZiyang Xuan return HINIC_ERROR; 2111cb7b6606SZiyang Xuan } 2112cb7b6606SZiyang Xuan 2113cb7b6606SZiyang Xuan /** 2114f372a65fSXiaoyun Wang * DPDK callback to get the RSS indirection table. 2115cb7b6606SZiyang Xuan * 2116cb7b6606SZiyang Xuan * @param dev 2117cb7b6606SZiyang Xuan * Pointer to Ethernet device structure. 2118cb7b6606SZiyang Xuan * @param reta_conf 2119f372a65fSXiaoyun Wang * Pointer to RSS reta configuration data. 2120cb7b6606SZiyang Xuan * @param reta_size 2121cb7b6606SZiyang Xuan * Size of the RETA table. 2122cb7b6606SZiyang Xuan * 2123cb7b6606SZiyang Xuan * @return 2124cb7b6606SZiyang Xuan * 0 on success, negative error value otherwise. 2125cb7b6606SZiyang Xuan */ 2126cb7b6606SZiyang Xuan static int hinic_rss_indirtbl_query(struct rte_eth_dev *dev, 2127cb7b6606SZiyang Xuan struct rte_eth_rss_reta_entry64 *reta_conf, 2128cb7b6606SZiyang Xuan uint16_t reta_size) 2129cb7b6606SZiyang Xuan { 2130cb7b6606SZiyang Xuan struct hinic_nic_dev *nic_dev = HINIC_ETH_DEV_TO_PRIVATE_NIC_DEV(dev); 2131cb7b6606SZiyang Xuan u8 tmpl_idx = nic_dev->rss_tmpl_idx; 2132cb7b6606SZiyang Xuan int err = 0; 2133cb7b6606SZiyang Xuan u32 indirtbl[NIC_RSS_INDIR_SIZE] = {0}; 2134cb7b6606SZiyang Xuan u16 idx, shift; 2135cb7b6606SZiyang Xuan u16 i = 0; 2136cb7b6606SZiyang Xuan 2137cb7b6606SZiyang Xuan if (reta_size != NIC_RSS_INDIR_SIZE) { 2138cb7b6606SZiyang Xuan PMD_DRV_LOG(ERR, "Invalid reta size, reta_size: %d", reta_size); 2139cb7b6606SZiyang Xuan return HINIC_ERROR; 2140cb7b6606SZiyang Xuan } 2141cb7b6606SZiyang Xuan 2142cb7b6606SZiyang Xuan err = hinic_rss_get_indir_tbl(nic_dev->hwdev, tmpl_idx, indirtbl); 2143cb7b6606SZiyang Xuan if (err) { 2144cb7b6606SZiyang Xuan PMD_DRV_LOG(ERR, "Get rss indirect table failed, error: %d", 2145cb7b6606SZiyang Xuan err); 2146cb7b6606SZiyang Xuan return err; 2147cb7b6606SZiyang Xuan } 2148cb7b6606SZiyang Xuan 2149cb7b6606SZiyang Xuan for (i = 0; i < reta_size; i++) { 2150295968d1SFerruh Yigit idx = i / RTE_ETH_RETA_GROUP_SIZE; 2151295968d1SFerruh Yigit shift = i % RTE_ETH_RETA_GROUP_SIZE; 2152cb7b6606SZiyang Xuan if (reta_conf[idx].mask & (1ULL << shift)) 2153cb7b6606SZiyang Xuan reta_conf[idx].reta[shift] = (uint16_t)indirtbl[i]; 2154cb7b6606SZiyang Xuan } 2155cb7b6606SZiyang Xuan 2156cb7b6606SZiyang Xuan return HINIC_OK; 2157cb7b6606SZiyang Xuan } 2158cb7b6606SZiyang Xuan 2159cb7b6606SZiyang Xuan /** 2160cb7b6606SZiyang Xuan * DPDK callback to get extended device statistics. 2161cb7b6606SZiyang Xuan * 2162cb7b6606SZiyang Xuan * @param dev 2163cb7b6606SZiyang Xuan * Pointer to Ethernet device. 2164cb7b6606SZiyang Xuan * @param xstats 2165cb7b6606SZiyang Xuan * Pointer to rte extended stats table. 2166cb7b6606SZiyang Xuan * @param n 2167cb7b6606SZiyang Xuan * The size of the stats table. 2168cb7b6606SZiyang Xuan * 2169cb7b6606SZiyang Xuan * @return 2170cb7b6606SZiyang Xuan * Number of extended stats on success and stats is filled, 2171cb7b6606SZiyang Xuan * negative error value otherwise. 2172cb7b6606SZiyang Xuan */ 2173cb7b6606SZiyang Xuan static int hinic_dev_xstats_get(struct rte_eth_dev *dev, 2174cb7b6606SZiyang Xuan struct rte_eth_xstat *xstats, 2175cb7b6606SZiyang Xuan unsigned int n) 2176cb7b6606SZiyang Xuan { 2177cb7b6606SZiyang Xuan u16 qid = 0; 2178cb7b6606SZiyang Xuan u32 i; 2179cb7b6606SZiyang Xuan int err, count; 2180cb7b6606SZiyang Xuan struct hinic_nic_dev *nic_dev; 2181cb7b6606SZiyang Xuan struct hinic_phy_port_stats port_stats; 2182cb7b6606SZiyang Xuan struct hinic_vport_stats vport_stats; 2183cb7b6606SZiyang Xuan struct hinic_rxq *rxq = NULL; 2184cb7b6606SZiyang Xuan struct hinic_rxq_stats rxq_stats; 2185cb7b6606SZiyang Xuan struct hinic_txq *txq = NULL; 2186cb7b6606SZiyang Xuan struct hinic_txq_stats txq_stats; 2187cb7b6606SZiyang Xuan 2188cb7b6606SZiyang Xuan nic_dev = HINIC_ETH_DEV_TO_PRIVATE_NIC_DEV(dev); 2189cb7b6606SZiyang Xuan count = hinic_xstats_calc_num(nic_dev); 2190cb7b6606SZiyang Xuan if ((int)n < count) 2191cb7b6606SZiyang Xuan return count; 2192cb7b6606SZiyang Xuan 2193cb7b6606SZiyang Xuan count = 0; 2194cb7b6606SZiyang Xuan 2195cb7b6606SZiyang Xuan /* Get stats from hinic_rxq_stats */ 2196cb7b6606SZiyang Xuan for (qid = 0; qid < nic_dev->num_rq; qid++) { 2197cb7b6606SZiyang Xuan rxq = nic_dev->rxqs[qid]; 2198cb7b6606SZiyang Xuan hinic_rxq_get_stats(rxq, &rxq_stats); 2199cb7b6606SZiyang Xuan 2200cb7b6606SZiyang Xuan for (i = 0; i < HINIC_RXQ_XSTATS_NUM; i++) { 2201cb7b6606SZiyang Xuan xstats[count].value = 2202cb7b6606SZiyang Xuan *(uint64_t *)(((char *)&rxq_stats) + 2203cb7b6606SZiyang Xuan hinic_rxq_stats_strings[i].offset); 2204cb7b6606SZiyang Xuan xstats[count].id = count; 2205cb7b6606SZiyang Xuan count++; 2206cb7b6606SZiyang Xuan } 2207cb7b6606SZiyang Xuan } 2208cb7b6606SZiyang Xuan 2209cb7b6606SZiyang Xuan /* Get stats from hinic_txq_stats */ 2210cb7b6606SZiyang Xuan for (qid = 0; qid < nic_dev->num_sq; qid++) { 2211cb7b6606SZiyang Xuan txq = nic_dev->txqs[qid]; 2212cb7b6606SZiyang Xuan hinic_txq_get_stats(txq, &txq_stats); 2213cb7b6606SZiyang Xuan 2214cb7b6606SZiyang Xuan for (i = 0; i < HINIC_TXQ_XSTATS_NUM; i++) { 2215cb7b6606SZiyang Xuan xstats[count].value = 2216cb7b6606SZiyang Xuan *(uint64_t *)(((char *)&txq_stats) + 2217cb7b6606SZiyang Xuan hinic_txq_stats_strings[i].offset); 2218cb7b6606SZiyang Xuan xstats[count].id = count; 2219cb7b6606SZiyang Xuan count++; 2220cb7b6606SZiyang Xuan } 2221cb7b6606SZiyang Xuan } 2222cb7b6606SZiyang Xuan 2223cb7b6606SZiyang Xuan /* Get stats from hinic_vport_stats */ 2224cb7b6606SZiyang Xuan err = hinic_get_vport_stats(nic_dev->hwdev, &vport_stats); 2225cb7b6606SZiyang Xuan if (err) 2226cb7b6606SZiyang Xuan return err; 2227cb7b6606SZiyang Xuan 2228cb7b6606SZiyang Xuan for (i = 0; i < HINIC_VPORT_XSTATS_NUM; i++) { 2229cb7b6606SZiyang Xuan xstats[count].value = 2230cb7b6606SZiyang Xuan *(uint64_t *)(((char *)&vport_stats) + 2231cb7b6606SZiyang Xuan hinic_vport_stats_strings[i].offset); 2232cb7b6606SZiyang Xuan xstats[count].id = count; 2233cb7b6606SZiyang Xuan count++; 2234cb7b6606SZiyang Xuan } 2235cb7b6606SZiyang Xuan 22366691acefSXiaoyun Wang if (HINIC_IS_VF(nic_dev->hwdev)) 22376691acefSXiaoyun Wang return count; 22386691acefSXiaoyun Wang 2239cb7b6606SZiyang Xuan /* Get stats from hinic_phy_port_stats */ 2240cb7b6606SZiyang Xuan err = hinic_get_phy_port_stats(nic_dev->hwdev, &port_stats); 2241cb7b6606SZiyang Xuan if (err) 2242cb7b6606SZiyang Xuan return err; 2243cb7b6606SZiyang Xuan 2244cb7b6606SZiyang Xuan for (i = 0; i < HINIC_PHYPORT_XSTATS_NUM; i++) { 2245cb7b6606SZiyang Xuan xstats[count].value = *(uint64_t *)(((char *)&port_stats) + 2246cb7b6606SZiyang Xuan hinic_phyport_stats_strings[i].offset); 2247cb7b6606SZiyang Xuan xstats[count].id = count; 2248cb7b6606SZiyang Xuan count++; 2249cb7b6606SZiyang Xuan } 2250cb7b6606SZiyang Xuan 2251cb7b6606SZiyang Xuan return count; 2252cb7b6606SZiyang Xuan } 2253cb7b6606SZiyang Xuan 2254483b4817SXiaoyun Wang static void hinic_rxq_info_get(struct rte_eth_dev *dev, uint16_t queue_id, 2255483b4817SXiaoyun Wang struct rte_eth_rxq_info *qinfo) 2256483b4817SXiaoyun Wang { 2257483b4817SXiaoyun Wang struct hinic_rxq *rxq = dev->data->rx_queues[queue_id]; 2258483b4817SXiaoyun Wang 2259483b4817SXiaoyun Wang qinfo->mp = rxq->mb_pool; 2260483b4817SXiaoyun Wang qinfo->nb_desc = rxq->q_depth; 2261483b4817SXiaoyun Wang } 2262483b4817SXiaoyun Wang 2263483b4817SXiaoyun Wang static void hinic_txq_info_get(struct rte_eth_dev *dev, uint16_t queue_id, 2264483b4817SXiaoyun Wang struct rte_eth_txq_info *qinfo) 2265483b4817SXiaoyun Wang { 2266483b4817SXiaoyun Wang struct hinic_txq *txq = dev->data->tx_queues[queue_id]; 2267483b4817SXiaoyun Wang 2268483b4817SXiaoyun Wang qinfo->nb_desc = txq->q_depth; 2269483b4817SXiaoyun Wang } 2270483b4817SXiaoyun Wang 2271cb7b6606SZiyang Xuan /** 2272cb7b6606SZiyang Xuan * DPDK callback to retrieve names of extended device statistics 2273cb7b6606SZiyang Xuan * 2274cb7b6606SZiyang Xuan * @param dev 2275cb7b6606SZiyang Xuan * Pointer to Ethernet device structure. 2276cb7b6606SZiyang Xuan * @param xstats_names 2277cb7b6606SZiyang Xuan * Buffer to insert names into. 2278cb7b6606SZiyang Xuan * 2279cb7b6606SZiyang Xuan * @return 2280cb7b6606SZiyang Xuan * Number of xstats names. 2281cb7b6606SZiyang Xuan */ 2282cb7b6606SZiyang Xuan static int hinic_dev_xstats_get_names(struct rte_eth_dev *dev, 2283cb7b6606SZiyang Xuan struct rte_eth_xstat_name *xstats_names, 2284cb7b6606SZiyang Xuan __rte_unused unsigned int limit) 2285cb7b6606SZiyang Xuan { 2286cb7b6606SZiyang Xuan struct hinic_nic_dev *nic_dev = HINIC_ETH_DEV_TO_PRIVATE_NIC_DEV(dev); 2287cb7b6606SZiyang Xuan int count = 0; 2288cb7b6606SZiyang Xuan u16 i = 0, q_num; 2289cb7b6606SZiyang Xuan 2290cb7b6606SZiyang Xuan if (xstats_names == NULL) 2291cb7b6606SZiyang Xuan return hinic_xstats_calc_num(nic_dev); 2292cb7b6606SZiyang Xuan 2293cb7b6606SZiyang Xuan /* get pmd rxq stats */ 2294cb7b6606SZiyang Xuan for (q_num = 0; q_num < nic_dev->num_rq; q_num++) { 2295cb7b6606SZiyang Xuan for (i = 0; i < HINIC_RXQ_XSTATS_NUM; i++) { 2296cb7b6606SZiyang Xuan snprintf(xstats_names[count].name, 2297cb7b6606SZiyang Xuan sizeof(xstats_names[count].name), 2298cb7b6606SZiyang Xuan "rxq%d_%s_pmd", 2299cb7b6606SZiyang Xuan q_num, hinic_rxq_stats_strings[i].name); 2300cb7b6606SZiyang Xuan count++; 2301cb7b6606SZiyang Xuan } 2302cb7b6606SZiyang Xuan } 2303cb7b6606SZiyang Xuan 2304cb7b6606SZiyang Xuan /* get pmd txq stats */ 2305cb7b6606SZiyang Xuan for (q_num = 0; q_num < nic_dev->num_sq; q_num++) { 2306cb7b6606SZiyang Xuan for (i = 0; i < HINIC_TXQ_XSTATS_NUM; i++) { 2307cb7b6606SZiyang Xuan snprintf(xstats_names[count].name, 2308cb7b6606SZiyang Xuan sizeof(xstats_names[count].name), 2309cb7b6606SZiyang Xuan "txq%d_%s_pmd", 2310cb7b6606SZiyang Xuan q_num, hinic_txq_stats_strings[i].name); 2311cb7b6606SZiyang Xuan count++; 2312cb7b6606SZiyang Xuan } 2313cb7b6606SZiyang Xuan } 2314cb7b6606SZiyang Xuan 2315cb7b6606SZiyang Xuan /* get vport stats */ 2316cb7b6606SZiyang Xuan for (i = 0; i < HINIC_VPORT_XSTATS_NUM; i++) { 2317cb7b6606SZiyang Xuan snprintf(xstats_names[count].name, 2318cb7b6606SZiyang Xuan sizeof(xstats_names[count].name), 2319f372a65fSXiaoyun Wang "%s", hinic_vport_stats_strings[i].name); 2320cb7b6606SZiyang Xuan count++; 2321cb7b6606SZiyang Xuan } 2322cb7b6606SZiyang Xuan 23236691acefSXiaoyun Wang if (HINIC_IS_VF(nic_dev->hwdev)) 23246691acefSXiaoyun Wang return count; 23256691acefSXiaoyun Wang 2326cb7b6606SZiyang Xuan /* get phy port stats */ 2327cb7b6606SZiyang Xuan for (i = 0; i < HINIC_PHYPORT_XSTATS_NUM; i++) { 2328cb7b6606SZiyang Xuan snprintf(xstats_names[count].name, 2329cb7b6606SZiyang Xuan sizeof(xstats_names[count].name), 2330f372a65fSXiaoyun Wang "%s", hinic_phyport_stats_strings[i].name); 2331cb7b6606SZiyang Xuan count++; 2332cb7b6606SZiyang Xuan } 2333cb7b6606SZiyang Xuan 2334cb7b6606SZiyang Xuan return count; 2335cb7b6606SZiyang Xuan } 2336f372a65fSXiaoyun Wang 233700499a22SXiaoyun Wang /** 233800499a22SXiaoyun Wang * DPDK callback to set mac address 233900499a22SXiaoyun Wang * 234000499a22SXiaoyun Wang * @param dev 234100499a22SXiaoyun Wang * Pointer to Ethernet device structure. 234200499a22SXiaoyun Wang * @param addr 234300499a22SXiaoyun Wang * Pointer to mac address 234400499a22SXiaoyun Wang * @return 234500499a22SXiaoyun Wang * 0 on success, negative error value otherwise. 234600499a22SXiaoyun Wang */ 234700499a22SXiaoyun Wang static int hinic_set_mac_addr(struct rte_eth_dev *dev, 234800499a22SXiaoyun Wang struct rte_ether_addr *addr) 234900499a22SXiaoyun Wang { 235000499a22SXiaoyun Wang struct hinic_nic_dev *nic_dev = HINIC_ETH_DEV_TO_PRIVATE_NIC_DEV(dev); 235100499a22SXiaoyun Wang u16 func_id; 235200499a22SXiaoyun Wang int err; 235300499a22SXiaoyun Wang 235400499a22SXiaoyun Wang func_id = hinic_global_func_id(nic_dev->hwdev); 235500499a22SXiaoyun Wang err = hinic_update_mac(nic_dev->hwdev, nic_dev->default_addr.addr_bytes, 235600499a22SXiaoyun Wang addr->addr_bytes, 0, func_id); 235700499a22SXiaoyun Wang if (err) 235800499a22SXiaoyun Wang return err; 235900499a22SXiaoyun Wang 236000499a22SXiaoyun Wang rte_ether_addr_copy(addr, &nic_dev->default_addr); 236100499a22SXiaoyun Wang 2362c2c4f87bSAman Deep Singh PMD_DRV_LOG(INFO, "Set new mac address " RTE_ETHER_ADDR_PRT_FMT, 2363a7db3afcSAman Deep Singh RTE_ETHER_ADDR_BYTES(addr)); 236400499a22SXiaoyun Wang 236500499a22SXiaoyun Wang return 0; 236600499a22SXiaoyun Wang } 236700499a22SXiaoyun Wang 236800499a22SXiaoyun Wang /** 236900499a22SXiaoyun Wang * DPDK callback to remove a MAC address. 237000499a22SXiaoyun Wang * 237100499a22SXiaoyun Wang * @param dev 237200499a22SXiaoyun Wang * Pointer to Ethernet device structure. 237300499a22SXiaoyun Wang * @param index 23744f1af3cbSXiaoyun Wang * MAC address index, should less than 128. 237500499a22SXiaoyun Wang */ 237600499a22SXiaoyun Wang static void hinic_mac_addr_remove(struct rte_eth_dev *dev, uint32_t index) 237700499a22SXiaoyun Wang { 237800499a22SXiaoyun Wang struct hinic_nic_dev *nic_dev = HINIC_ETH_DEV_TO_PRIVATE_NIC_DEV(dev); 237900499a22SXiaoyun Wang u16 func_id; 238000499a22SXiaoyun Wang int ret; 238100499a22SXiaoyun Wang 238200499a22SXiaoyun Wang if (index >= HINIC_MAX_UC_MAC_ADDRS) { 238300499a22SXiaoyun Wang PMD_DRV_LOG(INFO, "Remove mac index(%u) is out of range", 238400499a22SXiaoyun Wang index); 238500499a22SXiaoyun Wang return; 238600499a22SXiaoyun Wang } 238700499a22SXiaoyun Wang 238800499a22SXiaoyun Wang func_id = hinic_global_func_id(nic_dev->hwdev); 238900499a22SXiaoyun Wang ret = hinic_del_mac(nic_dev->hwdev, 239000499a22SXiaoyun Wang dev->data->mac_addrs[index].addr_bytes, 0, func_id); 239100499a22SXiaoyun Wang if (ret) 239200499a22SXiaoyun Wang return; 239300499a22SXiaoyun Wang 239400499a22SXiaoyun Wang memset(&dev->data->mac_addrs[index], 0, sizeof(struct rte_ether_addr)); 239500499a22SXiaoyun Wang } 239600499a22SXiaoyun Wang 239700499a22SXiaoyun Wang /** 239800499a22SXiaoyun Wang * DPDK callback to add a MAC address. 239900499a22SXiaoyun Wang * 240000499a22SXiaoyun Wang * @param dev 240100499a22SXiaoyun Wang * Pointer to Ethernet device structure. 240200499a22SXiaoyun Wang * @param mac_addr 24034f1af3cbSXiaoyun Wang * Pointer to MAC address 240400499a22SXiaoyun Wang * @param index 24054f1af3cbSXiaoyun Wang * MAC address index, should less than 128. 240600499a22SXiaoyun Wang * @param vmdq 24074f1af3cbSXiaoyun Wang * VMDq pool index(not used). 240800499a22SXiaoyun Wang * 240900499a22SXiaoyun Wang * @return 24104f1af3cbSXiaoyun Wang * 0 on success, negative error value otherwise. 241100499a22SXiaoyun Wang */ 241200499a22SXiaoyun Wang static int hinic_mac_addr_add(struct rte_eth_dev *dev, 241300499a22SXiaoyun Wang struct rte_ether_addr *mac_addr, uint32_t index, 241400499a22SXiaoyun Wang __rte_unused uint32_t vmdq) 241500499a22SXiaoyun Wang { 241600499a22SXiaoyun Wang struct hinic_nic_dev *nic_dev = HINIC_ETH_DEV_TO_PRIVATE_NIC_DEV(dev); 241700499a22SXiaoyun Wang unsigned int i; 241800499a22SXiaoyun Wang u16 func_id; 241900499a22SXiaoyun Wang int ret; 242000499a22SXiaoyun Wang 242100499a22SXiaoyun Wang if (index >= HINIC_MAX_UC_MAC_ADDRS) { 24224f1af3cbSXiaoyun Wang PMD_DRV_LOG(INFO, "Add mac index(%u) is out of range", index); 242300499a22SXiaoyun Wang return -EINVAL; 242400499a22SXiaoyun Wang } 242500499a22SXiaoyun Wang 242600499a22SXiaoyun Wang /* First, make sure this address isn't already configured. */ 242700499a22SXiaoyun Wang for (i = 0; (i != HINIC_MAX_UC_MAC_ADDRS); ++i) { 242800499a22SXiaoyun Wang /* Skip this index, it's going to be reconfigured. */ 242900499a22SXiaoyun Wang if (i == index) 243000499a22SXiaoyun Wang continue; 243100499a22SXiaoyun Wang 243200499a22SXiaoyun Wang if (memcmp(&dev->data->mac_addrs[i], 243300499a22SXiaoyun Wang mac_addr, sizeof(*mac_addr))) 243400499a22SXiaoyun Wang continue; 243500499a22SXiaoyun Wang 243600499a22SXiaoyun Wang PMD_DRV_LOG(INFO, "MAC address already configured"); 243700499a22SXiaoyun Wang return -EADDRINUSE; 243800499a22SXiaoyun Wang } 243900499a22SXiaoyun Wang 244000499a22SXiaoyun Wang func_id = hinic_global_func_id(nic_dev->hwdev); 244100499a22SXiaoyun Wang ret = hinic_set_mac(nic_dev->hwdev, mac_addr->addr_bytes, 0, func_id); 244200499a22SXiaoyun Wang if (ret) 244300499a22SXiaoyun Wang return ret; 244400499a22SXiaoyun Wang 244500499a22SXiaoyun Wang dev->data->mac_addrs[index] = *mac_addr; 244600499a22SXiaoyun Wang return 0; 244700499a22SXiaoyun Wang } 244800499a22SXiaoyun Wang 244900499a22SXiaoyun Wang /** 245000499a22SXiaoyun Wang * DPDK callback to set multicast mac address 245100499a22SXiaoyun Wang * 245200499a22SXiaoyun Wang * @param dev 245300499a22SXiaoyun Wang * Pointer to Ethernet device structure. 245400499a22SXiaoyun Wang * @param mc_addr_set 245500499a22SXiaoyun Wang * Pointer to multicast mac address 245600499a22SXiaoyun Wang * @param nb_mc_addr 245700499a22SXiaoyun Wang * mc addr count 245800499a22SXiaoyun Wang * @return 245900499a22SXiaoyun Wang * 0 on success, negative error value otherwise. 246000499a22SXiaoyun Wang */ 246100499a22SXiaoyun Wang static int hinic_set_mc_addr_list(struct rte_eth_dev *dev, 246200499a22SXiaoyun Wang struct rte_ether_addr *mc_addr_set, 246300499a22SXiaoyun Wang uint32_t nb_mc_addr) 246400499a22SXiaoyun Wang { 246500499a22SXiaoyun Wang struct hinic_nic_dev *nic_dev = HINIC_ETH_DEV_TO_PRIVATE_NIC_DEV(dev); 246600499a22SXiaoyun Wang u16 func_id; 246700499a22SXiaoyun Wang int ret; 246800499a22SXiaoyun Wang u32 i; 246900499a22SXiaoyun Wang 247000499a22SXiaoyun Wang func_id = hinic_global_func_id(nic_dev->hwdev); 247100499a22SXiaoyun Wang 247200499a22SXiaoyun Wang /* delete old multi_cast addrs firstly */ 247300499a22SXiaoyun Wang hinic_delete_mc_addr_list(nic_dev); 247400499a22SXiaoyun Wang 247500499a22SXiaoyun Wang if (nb_mc_addr > HINIC_MAX_MC_MAC_ADDRS) 247600499a22SXiaoyun Wang goto allmulti; 247700499a22SXiaoyun Wang 247800499a22SXiaoyun Wang for (i = 0; i < nb_mc_addr; i++) { 247900499a22SXiaoyun Wang ret = hinic_set_mac(nic_dev->hwdev, mc_addr_set[i].addr_bytes, 248000499a22SXiaoyun Wang 0, func_id); 248100499a22SXiaoyun Wang /* if add mc addr failed, set all multi_cast */ 248200499a22SXiaoyun Wang if (ret) { 248300499a22SXiaoyun Wang hinic_delete_mc_addr_list(nic_dev); 248400499a22SXiaoyun Wang goto allmulti; 248500499a22SXiaoyun Wang } 248600499a22SXiaoyun Wang 248700499a22SXiaoyun Wang rte_ether_addr_copy(&mc_addr_set[i], &nic_dev->mc_list[i]); 248800499a22SXiaoyun Wang } 248900499a22SXiaoyun Wang 249000499a22SXiaoyun Wang return 0; 249100499a22SXiaoyun Wang 249200499a22SXiaoyun Wang allmulti: 249300499a22SXiaoyun Wang hinic_dev_allmulticast_enable(dev); 249400499a22SXiaoyun Wang 249500499a22SXiaoyun Wang return 0; 249600499a22SXiaoyun Wang } 2497cb7b6606SZiyang Xuan 249873122b52SXiaoyun Wang /** 2499fb7ad441SThomas Monjalon * DPDK callback to get flow operations 250073122b52SXiaoyun Wang * 250173122b52SXiaoyun Wang * @param dev 250273122b52SXiaoyun Wang * Pointer to Ethernet device structure. 2503fb7ad441SThomas Monjalon * @param ops 250473122b52SXiaoyun Wang * Pointer to operation-specific structure. 250573122b52SXiaoyun Wang * 250673122b52SXiaoyun Wang * @return 2507f372a65fSXiaoyun Wang * 0 on success, negative error value otherwise. 250873122b52SXiaoyun Wang */ 2509fb7ad441SThomas Monjalon static int hinic_dev_flow_ops_get(struct rte_eth_dev *dev __rte_unused, 2510fb7ad441SThomas Monjalon const struct rte_flow_ops **ops) 251173122b52SXiaoyun Wang { 2512fb7ad441SThomas Monjalon *ops = &hinic_flow_ops; 251373122b52SXiaoyun Wang return 0; 251473122b52SXiaoyun Wang } 251573122b52SXiaoyun Wang 251664727024SZiyang Xuan static int hinic_set_default_pause_feature(struct hinic_nic_dev *nic_dev) 251764727024SZiyang Xuan { 251864727024SZiyang Xuan struct nic_pause_config pause_config = {0}; 2519ef6f2f5cSXiaoyun Wang int err; 252064727024SZiyang Xuan 252164727024SZiyang Xuan pause_config.auto_neg = 0; 252264727024SZiyang Xuan pause_config.rx_pause = HINIC_DEFAUT_PAUSE_CONFIG; 252364727024SZiyang Xuan pause_config.tx_pause = HINIC_DEFAUT_PAUSE_CONFIG; 252464727024SZiyang Xuan 2525ef6f2f5cSXiaoyun Wang err = hinic_set_pause_config(nic_dev->hwdev, pause_config); 2526ef6f2f5cSXiaoyun Wang if (err) 2527ef6f2f5cSXiaoyun Wang return err; 2528ef6f2f5cSXiaoyun Wang 2529ef6f2f5cSXiaoyun Wang nic_dev->pause_set = true; 2530ef6f2f5cSXiaoyun Wang nic_dev->nic_pause.auto_neg = pause_config.auto_neg; 2531ef6f2f5cSXiaoyun Wang nic_dev->nic_pause.rx_pause = pause_config.rx_pause; 2532ef6f2f5cSXiaoyun Wang nic_dev->nic_pause.tx_pause = pause_config.tx_pause; 2533ef6f2f5cSXiaoyun Wang 2534ef6f2f5cSXiaoyun Wang return 0; 253564727024SZiyang Xuan } 253664727024SZiyang Xuan 253764727024SZiyang Xuan static int hinic_set_default_dcb_feature(struct hinic_nic_dev *nic_dev) 253864727024SZiyang Xuan { 253964727024SZiyang Xuan u8 up_tc[HINIC_DCB_UP_MAX] = {0}; 254064727024SZiyang Xuan u8 up_pgid[HINIC_DCB_UP_MAX] = {0}; 254164727024SZiyang Xuan u8 up_bw[HINIC_DCB_UP_MAX] = {0}; 254264727024SZiyang Xuan u8 pg_bw[HINIC_DCB_UP_MAX] = {0}; 254364727024SZiyang Xuan u8 up_strict[HINIC_DCB_UP_MAX] = {0}; 254464727024SZiyang Xuan int i = 0; 254564727024SZiyang Xuan 254664727024SZiyang Xuan pg_bw[0] = 100; 254764727024SZiyang Xuan for (i = 0; i < HINIC_DCB_UP_MAX; i++) 254864727024SZiyang Xuan up_bw[i] = 100; 254964727024SZiyang Xuan 255064727024SZiyang Xuan return hinic_dcb_set_ets(nic_dev->hwdev, up_tc, pg_bw, 255164727024SZiyang Xuan up_pgid, up_bw, up_strict); 255264727024SZiyang Xuan } 255364727024SZiyang Xuan 2554d4002360SXiaoyun Wang static int hinic_pf_get_default_cos(struct hinic_hwdev *hwdev, u8 *cos_id) 2555d4002360SXiaoyun Wang { 2556d4002360SXiaoyun Wang u8 default_cos = 0; 2557d4002360SXiaoyun Wang u8 valid_cos_bitmap; 2558d4002360SXiaoyun Wang u8 i; 2559d4002360SXiaoyun Wang 2560d4002360SXiaoyun Wang valid_cos_bitmap = hwdev->cfg_mgmt->svc_cap.valid_cos_bitmap; 2561d4002360SXiaoyun Wang if (!valid_cos_bitmap) { 2562*f665790aSDavid Marchand PMD_DRV_LOG(ERR, "PF has none cos to support"); 2563d4002360SXiaoyun Wang return -EFAULT; 2564d4002360SXiaoyun Wang } 2565d4002360SXiaoyun Wang 2566d4002360SXiaoyun Wang for (i = 0; i < NR_MAX_COS; i++) { 2567d4002360SXiaoyun Wang if (valid_cos_bitmap & BIT(i)) 2568d4002360SXiaoyun Wang default_cos = i; /* Find max cos id as default cos */ 2569d4002360SXiaoyun Wang } 2570d4002360SXiaoyun Wang 2571d4002360SXiaoyun Wang *cos_id = default_cos; 2572d4002360SXiaoyun Wang 2573d4002360SXiaoyun Wang return 0; 2574d4002360SXiaoyun Wang } 2575d4002360SXiaoyun Wang 25766691acefSXiaoyun Wang static int hinic_init_default_cos(struct hinic_nic_dev *nic_dev) 257764727024SZiyang Xuan { 25786691acefSXiaoyun Wang u8 cos_id = 0; 25796691acefSXiaoyun Wang int err; 25806691acefSXiaoyun Wang 25816691acefSXiaoyun Wang if (!HINIC_IS_VF(nic_dev->hwdev)) { 2582d4002360SXiaoyun Wang err = hinic_pf_get_default_cos(nic_dev->hwdev, &cos_id); 2583d4002360SXiaoyun Wang if (err) { 2584d4002360SXiaoyun Wang PMD_DRV_LOG(ERR, "Get PF default cos failed, err: %d", 2585d4002360SXiaoyun Wang err); 2586d4002360SXiaoyun Wang return HINIC_ERROR; 2587d4002360SXiaoyun Wang } 25886691acefSXiaoyun Wang } else { 25896691acefSXiaoyun Wang err = hinic_vf_get_default_cos(nic_dev->hwdev, &cos_id); 25906691acefSXiaoyun Wang if (err) { 25916691acefSXiaoyun Wang PMD_DRV_LOG(ERR, "Get VF default cos failed, err: %d", 25926691acefSXiaoyun Wang err); 25936691acefSXiaoyun Wang return HINIC_ERROR; 25946691acefSXiaoyun Wang } 2595d4002360SXiaoyun Wang } 25966691acefSXiaoyun Wang 25976691acefSXiaoyun Wang nic_dev->default_cos = cos_id; 2598d4002360SXiaoyun Wang 2599d4002360SXiaoyun Wang PMD_DRV_LOG(INFO, "Default cos %d", nic_dev->default_cos); 26006691acefSXiaoyun Wang 26016691acefSXiaoyun Wang return 0; 260264727024SZiyang Xuan } 260364727024SZiyang Xuan 260464727024SZiyang Xuan static int hinic_set_default_hw_feature(struct hinic_nic_dev *nic_dev) 260564727024SZiyang Xuan { 260664727024SZiyang Xuan int err; 260764727024SZiyang Xuan 26086691acefSXiaoyun Wang err = hinic_init_default_cos(nic_dev); 26096691acefSXiaoyun Wang if (err) 26106691acefSXiaoyun Wang return err; 26116691acefSXiaoyun Wang 26126691acefSXiaoyun Wang if (hinic_func_type(nic_dev->hwdev) == TYPE_VF) 26136691acefSXiaoyun Wang return 0; 261464727024SZiyang Xuan 261564727024SZiyang Xuan /* Restore DCB configure to default status */ 261664727024SZiyang Xuan err = hinic_set_default_dcb_feature(nic_dev); 261764727024SZiyang Xuan if (err) 261864727024SZiyang Xuan return err; 261964727024SZiyang Xuan 262064727024SZiyang Xuan /* Set pause enable, and up will disable pfc. */ 262164727024SZiyang Xuan err = hinic_set_default_pause_feature(nic_dev); 262264727024SZiyang Xuan if (err) 262364727024SZiyang Xuan return err; 262464727024SZiyang Xuan 262564727024SZiyang Xuan err = hinic_reset_port_link_cfg(nic_dev->hwdev); 262664727024SZiyang Xuan if (err) 262764727024SZiyang Xuan return err; 262864727024SZiyang Xuan 262964727024SZiyang Xuan err = hinic_set_link_status_follow(nic_dev->hwdev, 263064727024SZiyang Xuan HINIC_LINK_FOLLOW_PORT); 263164727024SZiyang Xuan if (err == HINIC_MGMT_CMD_UNSUPPORTED) 263264727024SZiyang Xuan PMD_DRV_LOG(WARNING, "Don't support to set link status follow phy port status"); 263364727024SZiyang Xuan else if (err) 263464727024SZiyang Xuan return err; 263564727024SZiyang Xuan 263664727024SZiyang Xuan return hinic_set_anti_attack(nic_dev->hwdev, true); 263764727024SZiyang Xuan } 263864727024SZiyang Xuan 263964727024SZiyang Xuan static int32_t hinic_card_workmode_check(struct hinic_nic_dev *nic_dev) 264064727024SZiyang Xuan { 264164727024SZiyang Xuan struct hinic_board_info info = { 0 }; 264264727024SZiyang Xuan int rc; 264364727024SZiyang Xuan 26446691acefSXiaoyun Wang if (hinic_func_type(nic_dev->hwdev) == TYPE_VF) 26456691acefSXiaoyun Wang return 0; 26466691acefSXiaoyun Wang 264764727024SZiyang Xuan rc = hinic_get_board_info(nic_dev->hwdev, &info); 264864727024SZiyang Xuan if (rc) 264964727024SZiyang Xuan return rc; 265064727024SZiyang Xuan 265164727024SZiyang Xuan return (info.service_mode == HINIC_SERVICE_MODE_NIC ? HINIC_OK : 265264727024SZiyang Xuan HINIC_ERROR); 265364727024SZiyang Xuan } 265464727024SZiyang Xuan 265564727024SZiyang Xuan static int hinic_copy_mempool_init(struct hinic_nic_dev *nic_dev) 265664727024SZiyang Xuan { 265764727024SZiyang Xuan nic_dev->cpy_mpool = rte_mempool_lookup(nic_dev->proc_dev_name); 265864727024SZiyang Xuan if (nic_dev->cpy_mpool == NULL) { 265964727024SZiyang Xuan nic_dev->cpy_mpool = 266064727024SZiyang Xuan rte_pktmbuf_pool_create(nic_dev->proc_dev_name, 266164727024SZiyang Xuan HINIC_COPY_MEMPOOL_DEPTH, 26626691acefSXiaoyun Wang 0, 0, 266364727024SZiyang Xuan HINIC_COPY_MBUF_SIZE, 266464727024SZiyang Xuan rte_socket_id()); 266564727024SZiyang Xuan if (!nic_dev->cpy_mpool) { 266664727024SZiyang Xuan PMD_DRV_LOG(ERR, "Create copy mempool failed, errno: %d, dev_name: %s", 266764727024SZiyang Xuan rte_errno, nic_dev->proc_dev_name); 266864727024SZiyang Xuan return -ENOMEM; 266964727024SZiyang Xuan } 267064727024SZiyang Xuan } 267164727024SZiyang Xuan 267264727024SZiyang Xuan return 0; 267364727024SZiyang Xuan } 267464727024SZiyang Xuan 267564727024SZiyang Xuan static void hinic_copy_mempool_uninit(struct hinic_nic_dev *nic_dev) 267664727024SZiyang Xuan { 267764727024SZiyang Xuan rte_mempool_free(nic_dev->cpy_mpool); 267864727024SZiyang Xuan } 267964727024SZiyang Xuan 268064727024SZiyang Xuan static int hinic_init_sw_rxtxqs(struct hinic_nic_dev *nic_dev) 268164727024SZiyang Xuan { 268264727024SZiyang Xuan u32 txq_size; 268364727024SZiyang Xuan u32 rxq_size; 268464727024SZiyang Xuan 268564727024SZiyang Xuan /* allocate software txq array */ 268664727024SZiyang Xuan txq_size = nic_dev->nic_cap.max_sqs * sizeof(*nic_dev->txqs); 268764727024SZiyang Xuan nic_dev->txqs = kzalloc_aligned(txq_size, GFP_KERNEL); 268864727024SZiyang Xuan if (!nic_dev->txqs) { 268964727024SZiyang Xuan PMD_DRV_LOG(ERR, "Allocate txqs failed"); 269064727024SZiyang Xuan return -ENOMEM; 269164727024SZiyang Xuan } 269264727024SZiyang Xuan 269364727024SZiyang Xuan /* allocate software rxq array */ 269464727024SZiyang Xuan rxq_size = nic_dev->nic_cap.max_rqs * sizeof(*nic_dev->rxqs); 269564727024SZiyang Xuan nic_dev->rxqs = kzalloc_aligned(rxq_size, GFP_KERNEL); 269664727024SZiyang Xuan if (!nic_dev->rxqs) { 269764727024SZiyang Xuan /* free txqs */ 269864727024SZiyang Xuan kfree(nic_dev->txqs); 269964727024SZiyang Xuan nic_dev->txqs = NULL; 270064727024SZiyang Xuan 270164727024SZiyang Xuan PMD_DRV_LOG(ERR, "Allocate rxqs failed"); 270264727024SZiyang Xuan return -ENOMEM; 270364727024SZiyang Xuan } 270464727024SZiyang Xuan 270564727024SZiyang Xuan return HINIC_OK; 270664727024SZiyang Xuan } 270764727024SZiyang Xuan 270864727024SZiyang Xuan static void hinic_deinit_sw_rxtxqs(struct hinic_nic_dev *nic_dev) 270964727024SZiyang Xuan { 271064727024SZiyang Xuan kfree(nic_dev->txqs); 271164727024SZiyang Xuan nic_dev->txqs = NULL; 271264727024SZiyang Xuan 271364727024SZiyang Xuan kfree(nic_dev->rxqs); 271464727024SZiyang Xuan nic_dev->rxqs = NULL; 271564727024SZiyang Xuan } 271664727024SZiyang Xuan 271764727024SZiyang Xuan static int hinic_nic_dev_create(struct rte_eth_dev *eth_dev) 271864727024SZiyang Xuan { 271964727024SZiyang Xuan struct hinic_nic_dev *nic_dev = 272064727024SZiyang Xuan HINIC_ETH_DEV_TO_PRIVATE_NIC_DEV(eth_dev); 272164727024SZiyang Xuan int rc; 272264727024SZiyang Xuan 272364727024SZiyang Xuan nic_dev->hwdev = rte_zmalloc("hinic_hwdev", sizeof(*nic_dev->hwdev), 272464727024SZiyang Xuan RTE_CACHE_LINE_SIZE); 272564727024SZiyang Xuan if (!nic_dev->hwdev) { 272664727024SZiyang Xuan PMD_DRV_LOG(ERR, "Allocate hinic hwdev memory failed, dev_name: %s", 272764727024SZiyang Xuan eth_dev->data->name); 272864727024SZiyang Xuan return -ENOMEM; 272964727024SZiyang Xuan } 273064727024SZiyang Xuan nic_dev->hwdev->pcidev_hdl = RTE_ETH_DEV_TO_PCI(eth_dev); 273164727024SZiyang Xuan 273264727024SZiyang Xuan /* init osdep*/ 273364727024SZiyang Xuan rc = hinic_osdep_init(nic_dev->hwdev); 273464727024SZiyang Xuan if (rc) { 273564727024SZiyang Xuan PMD_DRV_LOG(ERR, "Initialize os_dep failed, dev_name: %s", 273664727024SZiyang Xuan eth_dev->data->name); 273764727024SZiyang Xuan goto init_osdep_fail; 273864727024SZiyang Xuan } 273964727024SZiyang Xuan 274064727024SZiyang Xuan /* init_hwif */ 274164727024SZiyang Xuan rc = hinic_hwif_res_init(nic_dev->hwdev); 274264727024SZiyang Xuan if (rc) { 274364727024SZiyang Xuan PMD_DRV_LOG(ERR, "Initialize hwif failed, dev_name: %s", 274464727024SZiyang Xuan eth_dev->data->name); 274564727024SZiyang Xuan goto init_hwif_fail; 274664727024SZiyang Xuan } 274764727024SZiyang Xuan 274864727024SZiyang Xuan /* init_cfg_mgmt */ 274964727024SZiyang Xuan rc = init_cfg_mgmt(nic_dev->hwdev); 275064727024SZiyang Xuan if (rc) { 275164727024SZiyang Xuan PMD_DRV_LOG(ERR, "Initialize cfg_mgmt failed, dev_name: %s", 275264727024SZiyang Xuan eth_dev->data->name); 275364727024SZiyang Xuan goto init_cfgmgnt_fail; 275464727024SZiyang Xuan } 275564727024SZiyang Xuan 275664727024SZiyang Xuan /* init_aeqs */ 275764727024SZiyang Xuan rc = hinic_comm_aeqs_init(nic_dev->hwdev); 275864727024SZiyang Xuan if (rc) { 275964727024SZiyang Xuan PMD_DRV_LOG(ERR, "Initialize aeqs failed, dev_name: %s", 276064727024SZiyang Xuan eth_dev->data->name); 276164727024SZiyang Xuan goto init_aeqs_fail; 276264727024SZiyang Xuan } 276364727024SZiyang Xuan 276464727024SZiyang Xuan /* init_pf_to_mgnt */ 276564727024SZiyang Xuan rc = hinic_comm_pf_to_mgmt_init(nic_dev->hwdev); 276664727024SZiyang Xuan if (rc) { 276764727024SZiyang Xuan PMD_DRV_LOG(ERR, "Initialize pf_to_mgmt failed, dev_name: %s", 276864727024SZiyang Xuan eth_dev->data->name); 276964727024SZiyang Xuan goto init_pf_to_mgmt_fail; 277064727024SZiyang Xuan } 277164727024SZiyang Xuan 27726691acefSXiaoyun Wang /* init mailbox */ 27736691acefSXiaoyun Wang rc = hinic_comm_func_to_func_init(nic_dev->hwdev); 27746691acefSXiaoyun Wang if (rc) { 27756691acefSXiaoyun Wang PMD_DRV_LOG(ERR, "Initialize func_to_func failed, dev_name: %s", 27766691acefSXiaoyun Wang eth_dev->data->name); 27776691acefSXiaoyun Wang goto init_func_to_func_fail; 27786691acefSXiaoyun Wang } 27796691acefSXiaoyun Wang 278064727024SZiyang Xuan rc = hinic_card_workmode_check(nic_dev); 278164727024SZiyang Xuan if (rc) { 278264727024SZiyang Xuan PMD_DRV_LOG(ERR, "Check card workmode failed, dev_name: %s", 278364727024SZiyang Xuan eth_dev->data->name); 278464727024SZiyang Xuan goto workmode_check_fail; 278564727024SZiyang Xuan } 278664727024SZiyang Xuan 278764727024SZiyang Xuan /* do l2nic reset to make chip clear */ 278864727024SZiyang Xuan rc = hinic_l2nic_reset(nic_dev->hwdev); 278964727024SZiyang Xuan if (rc) { 279064727024SZiyang Xuan PMD_DRV_LOG(ERR, "Do l2nic reset failed, dev_name: %s", 279164727024SZiyang Xuan eth_dev->data->name); 279264727024SZiyang Xuan goto l2nic_reset_fail; 279364727024SZiyang Xuan } 279464727024SZiyang Xuan 279564727024SZiyang Xuan /* init dma and aeq msix attribute table */ 279664727024SZiyang Xuan (void)hinic_init_attr_table(nic_dev->hwdev); 279764727024SZiyang Xuan 279864727024SZiyang Xuan /* init_cmdqs */ 279964727024SZiyang Xuan rc = hinic_comm_cmdqs_init(nic_dev->hwdev); 280064727024SZiyang Xuan if (rc) { 280164727024SZiyang Xuan PMD_DRV_LOG(ERR, "Initialize cmdq failed, dev_name: %s", 280264727024SZiyang Xuan eth_dev->data->name); 280364727024SZiyang Xuan goto init_cmdq_fail; 280464727024SZiyang Xuan } 280564727024SZiyang Xuan 280664727024SZiyang Xuan /* set hardware state active */ 280764727024SZiyang Xuan rc = hinic_activate_hwdev_state(nic_dev->hwdev); 280864727024SZiyang Xuan if (rc) { 280964727024SZiyang Xuan PMD_DRV_LOG(ERR, "Initialize resources state failed, dev_name: %s", 281064727024SZiyang Xuan eth_dev->data->name); 281164727024SZiyang Xuan goto init_resources_state_fail; 281264727024SZiyang Xuan } 281364727024SZiyang Xuan 281464727024SZiyang Xuan /* init_capability */ 281564727024SZiyang Xuan rc = hinic_init_capability(nic_dev->hwdev); 281664727024SZiyang Xuan if (rc) { 281764727024SZiyang Xuan PMD_DRV_LOG(ERR, "Initialize capability failed, dev_name: %s", 281864727024SZiyang Xuan eth_dev->data->name); 281964727024SZiyang Xuan goto init_cap_fail; 282064727024SZiyang Xuan } 282164727024SZiyang Xuan 282264727024SZiyang Xuan /* get nic capability */ 282313850e88SXiaoyun Wang if (!hinic_support_nic(nic_dev->hwdev, &nic_dev->nic_cap)) { 282413850e88SXiaoyun Wang PMD_DRV_LOG(ERR, "Hw doesn't support nic, dev_name: %s", 282513850e88SXiaoyun Wang eth_dev->data->name); 282613850e88SXiaoyun Wang rc = -EINVAL; 282764727024SZiyang Xuan goto nic_check_fail; 282813850e88SXiaoyun Wang } 282964727024SZiyang Xuan 283064727024SZiyang Xuan /* init root cla and function table */ 283164727024SZiyang Xuan rc = hinic_init_nicio(nic_dev->hwdev); 283264727024SZiyang Xuan if (rc) { 283364727024SZiyang Xuan PMD_DRV_LOG(ERR, "Initialize nic_io failed, dev_name: %s", 283464727024SZiyang Xuan eth_dev->data->name); 283564727024SZiyang Xuan goto init_nicio_fail; 283664727024SZiyang Xuan } 283764727024SZiyang Xuan 283864727024SZiyang Xuan /* init_software_txrxq */ 283964727024SZiyang Xuan rc = hinic_init_sw_rxtxqs(nic_dev); 284064727024SZiyang Xuan if (rc) { 284164727024SZiyang Xuan PMD_DRV_LOG(ERR, "Initialize sw_rxtxqs failed, dev_name: %s", 284264727024SZiyang Xuan eth_dev->data->name); 284364727024SZiyang Xuan goto init_sw_rxtxqs_fail; 284464727024SZiyang Xuan } 284564727024SZiyang Xuan 284664727024SZiyang Xuan rc = hinic_copy_mempool_init(nic_dev); 284764727024SZiyang Xuan if (rc) { 284864727024SZiyang Xuan PMD_DRV_LOG(ERR, "Create copy mempool failed, dev_name: %s", 284964727024SZiyang Xuan eth_dev->data->name); 285064727024SZiyang Xuan goto init_mpool_fail; 285164727024SZiyang Xuan } 285264727024SZiyang Xuan 285364727024SZiyang Xuan /* set hardware feature to default status */ 285464727024SZiyang Xuan rc = hinic_set_default_hw_feature(nic_dev); 285564727024SZiyang Xuan if (rc) { 285664727024SZiyang Xuan PMD_DRV_LOG(ERR, "Initialize hardware default features failed, dev_name: %s", 285764727024SZiyang Xuan eth_dev->data->name); 285864727024SZiyang Xuan goto set_default_hw_feature_fail; 285964727024SZiyang Xuan } 286064727024SZiyang Xuan 286164727024SZiyang Xuan return 0; 286264727024SZiyang Xuan 286364727024SZiyang Xuan set_default_hw_feature_fail: 286464727024SZiyang Xuan hinic_copy_mempool_uninit(nic_dev); 286564727024SZiyang Xuan 286664727024SZiyang Xuan init_mpool_fail: 286764727024SZiyang Xuan hinic_deinit_sw_rxtxqs(nic_dev); 286864727024SZiyang Xuan 286964727024SZiyang Xuan init_sw_rxtxqs_fail: 287064727024SZiyang Xuan hinic_deinit_nicio(nic_dev->hwdev); 287164727024SZiyang Xuan 287264727024SZiyang Xuan nic_check_fail: 287364727024SZiyang Xuan init_nicio_fail: 287464727024SZiyang Xuan init_cap_fail: 287564727024SZiyang Xuan hinic_deactivate_hwdev_state(nic_dev->hwdev); 287664727024SZiyang Xuan 287764727024SZiyang Xuan init_resources_state_fail: 287864727024SZiyang Xuan hinic_comm_cmdqs_free(nic_dev->hwdev); 287964727024SZiyang Xuan 288064727024SZiyang Xuan init_cmdq_fail: 288164727024SZiyang Xuan l2nic_reset_fail: 288264727024SZiyang Xuan workmode_check_fail: 28836691acefSXiaoyun Wang hinic_comm_func_to_func_free(nic_dev->hwdev); 28846691acefSXiaoyun Wang 28856691acefSXiaoyun Wang init_func_to_func_fail: 288664727024SZiyang Xuan hinic_comm_pf_to_mgmt_free(nic_dev->hwdev); 288764727024SZiyang Xuan 288864727024SZiyang Xuan init_pf_to_mgmt_fail: 288964727024SZiyang Xuan hinic_comm_aeqs_free(nic_dev->hwdev); 289064727024SZiyang Xuan 289164727024SZiyang Xuan init_aeqs_fail: 289264727024SZiyang Xuan free_cfg_mgmt(nic_dev->hwdev); 289364727024SZiyang Xuan 289464727024SZiyang Xuan init_cfgmgnt_fail: 289564727024SZiyang Xuan hinic_hwif_res_free(nic_dev->hwdev); 289664727024SZiyang Xuan 289764727024SZiyang Xuan init_hwif_fail: 289864727024SZiyang Xuan hinic_osdep_deinit(nic_dev->hwdev); 289964727024SZiyang Xuan 290064727024SZiyang Xuan init_osdep_fail: 290164727024SZiyang Xuan rte_free(nic_dev->hwdev); 290264727024SZiyang Xuan nic_dev->hwdev = NULL; 290364727024SZiyang Xuan 290464727024SZiyang Xuan return rc; 290564727024SZiyang Xuan } 290664727024SZiyang Xuan 290764727024SZiyang Xuan static void hinic_nic_dev_destroy(struct rte_eth_dev *eth_dev) 290864727024SZiyang Xuan { 290964727024SZiyang Xuan struct hinic_nic_dev *nic_dev = 291064727024SZiyang Xuan HINIC_ETH_DEV_TO_PRIVATE_NIC_DEV(eth_dev); 291164727024SZiyang Xuan 291264727024SZiyang Xuan (void)hinic_set_link_status_follow(nic_dev->hwdev, 291364727024SZiyang Xuan HINIC_LINK_FOLLOW_DEFAULT); 291464727024SZiyang Xuan hinic_copy_mempool_uninit(nic_dev); 291564727024SZiyang Xuan hinic_deinit_sw_rxtxqs(nic_dev); 291664727024SZiyang Xuan hinic_deinit_nicio(nic_dev->hwdev); 291764727024SZiyang Xuan hinic_deactivate_hwdev_state(nic_dev->hwdev); 291864727024SZiyang Xuan hinic_comm_cmdqs_free(nic_dev->hwdev); 29196691acefSXiaoyun Wang hinic_comm_func_to_func_free(nic_dev->hwdev); 292064727024SZiyang Xuan hinic_comm_pf_to_mgmt_free(nic_dev->hwdev); 292164727024SZiyang Xuan hinic_comm_aeqs_free(nic_dev->hwdev); 292264727024SZiyang Xuan free_cfg_mgmt(nic_dev->hwdev); 292364727024SZiyang Xuan hinic_hwif_res_free(nic_dev->hwdev); 292464727024SZiyang Xuan hinic_osdep_deinit(nic_dev->hwdev); 292564727024SZiyang Xuan rte_free(nic_dev->hwdev); 292664727024SZiyang Xuan nic_dev->hwdev = NULL; 292764727024SZiyang Xuan } 292864727024SZiyang Xuan 292964727024SZiyang Xuan /** 29301d09792aSZiyang Xuan * DPDK callback to close the device. 29311d09792aSZiyang Xuan * 29321d09792aSZiyang Xuan * @param dev 29331d09792aSZiyang Xuan * Pointer to Ethernet device structure. 29341d09792aSZiyang Xuan */ 2935b142387bSThomas Monjalon static int hinic_dev_close(struct rte_eth_dev *dev) 29361d09792aSZiyang Xuan { 293764727024SZiyang Xuan struct hinic_nic_dev *nic_dev = HINIC_ETH_DEV_TO_PRIVATE_NIC_DEV(dev); 293862024eb8SIvan Ilchenko int ret; 293964727024SZiyang Xuan 294030410493SThomas Monjalon if (rte_eal_process_type() != RTE_PROC_PRIMARY) 294130410493SThomas Monjalon return 0; 294230410493SThomas Monjalon 29430371535dSJoyce Kong if (rte_bit_relaxed_test_and_set32(HINIC_DEV_CLOSE, 29440371535dSJoyce Kong &nic_dev->dev_status)) { 294564727024SZiyang Xuan PMD_DRV_LOG(WARNING, "Device %s already closed", 294664727024SZiyang Xuan dev->data->name); 2947b142387bSThomas Monjalon return 0; 294864727024SZiyang Xuan } 294964727024SZiyang Xuan 29502c473729SZiyang Xuan /* stop device first */ 295162024eb8SIvan Ilchenko ret = hinic_dev_stop(dev); 29522c473729SZiyang Xuan 295364727024SZiyang Xuan /* rx_cqe, rx_info */ 295464727024SZiyang Xuan hinic_free_all_rx_resources(dev); 295564727024SZiyang Xuan 295664727024SZiyang Xuan /* tx_info */ 295764727024SZiyang Xuan hinic_free_all_tx_resources(dev); 295864727024SZiyang Xuan 295964727024SZiyang Xuan /* free wq, pi_dma_addr */ 296064727024SZiyang Xuan hinic_free_all_rq(nic_dev); 296164727024SZiyang Xuan 296264727024SZiyang Xuan /* free wq, db_addr */ 296364727024SZiyang Xuan hinic_free_all_sq(nic_dev); 296464727024SZiyang Xuan 296564727024SZiyang Xuan /* deinit mac vlan tbl */ 296664727024SZiyang Xuan hinic_deinit_mac_addr(dev); 2967fdba3bf1SXiaoyun Wang hinic_remove_all_vlanid(dev); 296864727024SZiyang Xuan 296964727024SZiyang Xuan /* disable hardware and uio interrupt */ 297064727024SZiyang Xuan hinic_disable_interrupt(dev); 297164727024SZiyang Xuan 2972511b7371SGuoyang Zhou /* destroy rx mode mutex */ 2973511b7371SGuoyang Zhou hinic_mutex_destroy(&nic_dev->rx_mode_mutex); 2974511b7371SGuoyang Zhou 297564727024SZiyang Xuan /* deinit nic hardware device */ 297664727024SZiyang Xuan hinic_nic_dev_destroy(dev); 2977b142387bSThomas Monjalon 297862024eb8SIvan Ilchenko return ret; 29791d09792aSZiyang Xuan } 29801d09792aSZiyang Xuan 29811d09792aSZiyang Xuan static const struct eth_dev_ops hinic_pmd_ops = { 298264727024SZiyang Xuan .dev_configure = hinic_dev_configure, 29831d09792aSZiyang Xuan .dev_infos_get = hinic_dev_infos_get, 2984dbf524abSXiaoyun Wang .fw_version_get = hinic_fw_version_get, 29852c473729SZiyang Xuan .rx_queue_setup = hinic_rx_queue_setup, 29862c473729SZiyang Xuan .tx_queue_setup = hinic_tx_queue_setup, 29872c473729SZiyang Xuan .dev_start = hinic_dev_start, 298854ac3386SXiaoyun Wang .dev_set_link_up = hinic_dev_set_link_up, 298954ac3386SXiaoyun Wang .dev_set_link_down = hinic_dev_set_link_down, 29902c473729SZiyang Xuan .link_update = hinic_link_update, 29912c473729SZiyang Xuan .rx_queue_release = hinic_rx_queue_release, 29922c473729SZiyang Xuan .tx_queue_release = hinic_tx_queue_release, 29932c473729SZiyang Xuan .dev_stop = hinic_dev_stop, 299464727024SZiyang Xuan .dev_close = hinic_dev_close, 29958260eba6SXiaoyun Wang .mtu_set = hinic_dev_set_mtu, 2996fdba3bf1SXiaoyun Wang .vlan_filter_set = hinic_vlan_filter_set, 2997fdba3bf1SXiaoyun Wang .vlan_offload_set = hinic_vlan_offload_set, 29988260eba6SXiaoyun Wang .allmulticast_enable = hinic_dev_allmulticast_enable, 29998260eba6SXiaoyun Wang .allmulticast_disable = hinic_dev_allmulticast_disable, 3000cb7b6606SZiyang Xuan .promiscuous_enable = hinic_dev_promiscuous_enable, 3001cb7b6606SZiyang Xuan .promiscuous_disable = hinic_dev_promiscuous_disable, 3002ef6f2f5cSXiaoyun Wang .flow_ctrl_get = hinic_flow_ctrl_get, 3003ef6f2f5cSXiaoyun Wang .flow_ctrl_set = hinic_flow_ctrl_set, 3004cb7b6606SZiyang Xuan .rss_hash_update = hinic_rss_hash_update, 3005cb7b6606SZiyang Xuan .rss_hash_conf_get = hinic_rss_conf_get, 3006cb7b6606SZiyang Xuan .reta_update = hinic_rss_indirtbl_update, 3007cb7b6606SZiyang Xuan .reta_query = hinic_rss_indirtbl_query, 3008cb7b6606SZiyang Xuan .stats_get = hinic_dev_stats_get, 3009cb7b6606SZiyang Xuan .stats_reset = hinic_dev_stats_reset, 3010cb7b6606SZiyang Xuan .xstats_get = hinic_dev_xstats_get, 3011cb7b6606SZiyang Xuan .xstats_reset = hinic_dev_xstats_reset, 3012cb7b6606SZiyang Xuan .xstats_get_names = hinic_dev_xstats_get_names, 3013483b4817SXiaoyun Wang .rxq_info_get = hinic_rxq_info_get, 3014483b4817SXiaoyun Wang .txq_info_get = hinic_txq_info_get, 301500499a22SXiaoyun Wang .mac_addr_set = hinic_set_mac_addr, 301600499a22SXiaoyun Wang .mac_addr_remove = hinic_mac_addr_remove, 301700499a22SXiaoyun Wang .mac_addr_add = hinic_mac_addr_add, 301800499a22SXiaoyun Wang .set_mc_addr_list = hinic_set_mc_addr_list, 3019fb7ad441SThomas Monjalon .flow_ops_get = hinic_dev_flow_ops_get, 30201d09792aSZiyang Xuan }; 30211d09792aSZiyang Xuan 30226691acefSXiaoyun Wang static const struct eth_dev_ops hinic_pmd_vf_ops = { 30236691acefSXiaoyun Wang .dev_configure = hinic_dev_configure, 30246691acefSXiaoyun Wang .dev_infos_get = hinic_dev_infos_get, 3025dbf524abSXiaoyun Wang .fw_version_get = hinic_fw_version_get, 30266691acefSXiaoyun Wang .rx_queue_setup = hinic_rx_queue_setup, 30276691acefSXiaoyun Wang .tx_queue_setup = hinic_tx_queue_setup, 30286691acefSXiaoyun Wang .dev_start = hinic_dev_start, 30296691acefSXiaoyun Wang .link_update = hinic_link_update, 30306691acefSXiaoyun Wang .rx_queue_release = hinic_rx_queue_release, 30316691acefSXiaoyun Wang .tx_queue_release = hinic_tx_queue_release, 30326691acefSXiaoyun Wang .dev_stop = hinic_dev_stop, 30336691acefSXiaoyun Wang .dev_close = hinic_dev_close, 30348260eba6SXiaoyun Wang .mtu_set = hinic_dev_set_mtu, 3035fdba3bf1SXiaoyun Wang .vlan_filter_set = hinic_vlan_filter_set, 3036fdba3bf1SXiaoyun Wang .vlan_offload_set = hinic_vlan_offload_set, 30378260eba6SXiaoyun Wang .allmulticast_enable = hinic_dev_allmulticast_enable, 30388260eba6SXiaoyun Wang .allmulticast_disable = hinic_dev_allmulticast_disable, 30396691acefSXiaoyun Wang .rss_hash_update = hinic_rss_hash_update, 30406691acefSXiaoyun Wang .rss_hash_conf_get = hinic_rss_conf_get, 30416691acefSXiaoyun Wang .reta_update = hinic_rss_indirtbl_update, 30426691acefSXiaoyun Wang .reta_query = hinic_rss_indirtbl_query, 30436691acefSXiaoyun Wang .stats_get = hinic_dev_stats_get, 30446691acefSXiaoyun Wang .stats_reset = hinic_dev_stats_reset, 30456691acefSXiaoyun Wang .xstats_get = hinic_dev_xstats_get, 30466691acefSXiaoyun Wang .xstats_reset = hinic_dev_xstats_reset, 30476691acefSXiaoyun Wang .xstats_get_names = hinic_dev_xstats_get_names, 3048483b4817SXiaoyun Wang .rxq_info_get = hinic_rxq_info_get, 3049483b4817SXiaoyun Wang .txq_info_get = hinic_txq_info_get, 305000499a22SXiaoyun Wang .mac_addr_set = hinic_set_mac_addr, 305100499a22SXiaoyun Wang .mac_addr_remove = hinic_mac_addr_remove, 305200499a22SXiaoyun Wang .mac_addr_add = hinic_mac_addr_add, 305300499a22SXiaoyun Wang .set_mc_addr_list = hinic_set_mc_addr_list, 3054fb7ad441SThomas Monjalon .flow_ops_get = hinic_dev_flow_ops_get, 30556691acefSXiaoyun Wang }; 30566691acefSXiaoyun Wang 30574c670dfaSGuoyang Zhou static const struct eth_dev_ops hinic_dev_sec_ops = { 30584c670dfaSGuoyang Zhou .dev_infos_get = hinic_dev_infos_get, 30594c670dfaSGuoyang Zhou }; 30604c670dfaSGuoyang Zhou 30616691acefSXiaoyun Wang static int hinic_func_init(struct rte_eth_dev *eth_dev) 30626691acefSXiaoyun Wang { 30636691acefSXiaoyun Wang struct rte_pci_device *pci_dev; 30646691acefSXiaoyun Wang struct rte_ether_addr *eth_addr; 30656691acefSXiaoyun Wang struct hinic_nic_dev *nic_dev; 30661742421bSXiaoyun Wang struct hinic_filter_info *filter_info; 30671fe89aa3SXiaoyun Wang struct hinic_tcam_info *tcam_info; 306800499a22SXiaoyun Wang u32 mac_size; 30696691acefSXiaoyun Wang int rc; 30706691acefSXiaoyun Wang 30716691acefSXiaoyun Wang pci_dev = RTE_ETH_DEV_TO_PCI(eth_dev); 30726691acefSXiaoyun Wang 30736691acefSXiaoyun Wang /* EAL is SECONDARY and eth_dev is already created */ 30746691acefSXiaoyun Wang if (rte_eal_process_type() != RTE_PROC_PRIMARY) { 30754c670dfaSGuoyang Zhou eth_dev->dev_ops = &hinic_dev_sec_ops; 307666f64dd6SXiaoyun Wang PMD_DRV_LOG(INFO, "Initialize %s in secondary process", 30776691acefSXiaoyun Wang eth_dev->data->name); 30786691acefSXiaoyun Wang 307966f64dd6SXiaoyun Wang return 0; 30806691acefSXiaoyun Wang } 30816691acefSXiaoyun Wang 3082f30e69b4SFerruh Yigit eth_dev->data->dev_flags |= RTE_ETH_DEV_AUTOFILL_QUEUE_XSTATS; 3083f30e69b4SFerruh Yigit 30846691acefSXiaoyun Wang nic_dev = HINIC_ETH_DEV_TO_PRIVATE_NIC_DEV(eth_dev); 30856691acefSXiaoyun Wang memset(nic_dev, 0, sizeof(*nic_dev)); 30866691acefSXiaoyun Wang 30876691acefSXiaoyun Wang snprintf(nic_dev->proc_dev_name, 30886691acefSXiaoyun Wang sizeof(nic_dev->proc_dev_name), 30892fc03b23SThomas Monjalon "hinic-" PCI_PRI_FMT, 30906691acefSXiaoyun Wang pci_dev->addr.domain, pci_dev->addr.bus, 30916691acefSXiaoyun Wang pci_dev->addr.devid, pci_dev->addr.function); 30926691acefSXiaoyun Wang 30936691acefSXiaoyun Wang /* alloc mac_addrs */ 309400499a22SXiaoyun Wang mac_size = HINIC_MAX_UC_MAC_ADDRS * sizeof(struct rte_ether_addr); 309500499a22SXiaoyun Wang eth_addr = rte_zmalloc("hinic_mac", mac_size, 0); 30966691acefSXiaoyun Wang if (!eth_addr) { 30976691acefSXiaoyun Wang PMD_DRV_LOG(ERR, "Allocate ethernet addresses' memory failed, dev_name: %s", 30986691acefSXiaoyun Wang eth_dev->data->name); 30996691acefSXiaoyun Wang rc = -ENOMEM; 31006691acefSXiaoyun Wang goto eth_addr_fail; 31016691acefSXiaoyun Wang } 31026691acefSXiaoyun Wang eth_dev->data->mac_addrs = eth_addr; 31036691acefSXiaoyun Wang 310400499a22SXiaoyun Wang mac_size = HINIC_MAX_MC_MAC_ADDRS * sizeof(struct rte_ether_addr); 310500499a22SXiaoyun Wang nic_dev->mc_list = rte_zmalloc("hinic_mc", mac_size, 0); 310600499a22SXiaoyun Wang if (!nic_dev->mc_list) { 310700499a22SXiaoyun Wang PMD_DRV_LOG(ERR, "Allocate mcast address' memory failed, dev_name: %s", 310800499a22SXiaoyun Wang eth_dev->data->name); 310900499a22SXiaoyun Wang rc = -ENOMEM; 311000499a22SXiaoyun Wang goto mc_addr_fail; 311100499a22SXiaoyun Wang } 311200499a22SXiaoyun Wang 31136691acefSXiaoyun Wang /* create hardware nic_device */ 31146691acefSXiaoyun Wang rc = hinic_nic_dev_create(eth_dev); 31156691acefSXiaoyun Wang if (rc) { 31166691acefSXiaoyun Wang PMD_DRV_LOG(ERR, "Create nic device failed, dev_name: %s", 31176691acefSXiaoyun Wang eth_dev->data->name); 31186691acefSXiaoyun Wang goto create_nic_dev_fail; 31196691acefSXiaoyun Wang } 31206691acefSXiaoyun Wang 31216691acefSXiaoyun Wang if (HINIC_IS_VF(nic_dev->hwdev)) 31226691acefSXiaoyun Wang eth_dev->dev_ops = &hinic_pmd_vf_ops; 31236691acefSXiaoyun Wang else 31246691acefSXiaoyun Wang eth_dev->dev_ops = &hinic_pmd_ops; 31256691acefSXiaoyun Wang 31266691acefSXiaoyun Wang rc = hinic_init_mac_addr(eth_dev); 31276691acefSXiaoyun Wang if (rc) { 31286691acefSXiaoyun Wang PMD_DRV_LOG(ERR, "Initialize mac table failed, dev_name: %s", 31296691acefSXiaoyun Wang eth_dev->data->name); 31306691acefSXiaoyun Wang goto init_mac_fail; 31316691acefSXiaoyun Wang } 31326691acefSXiaoyun Wang 31336691acefSXiaoyun Wang /* register callback func to eal lib */ 3134d61138d4SHarman Kalra rc = rte_intr_callback_register(pci_dev->intr_handle, 31356691acefSXiaoyun Wang hinic_dev_interrupt_handler, 31366691acefSXiaoyun Wang (void *)eth_dev); 31376691acefSXiaoyun Wang if (rc) { 31386691acefSXiaoyun Wang PMD_DRV_LOG(ERR, "Register rte interrupt callback failed, dev_name: %s", 31396691acefSXiaoyun Wang eth_dev->data->name); 31406691acefSXiaoyun Wang goto reg_intr_cb_fail; 31416691acefSXiaoyun Wang } 31426691acefSXiaoyun Wang 31436691acefSXiaoyun Wang /* enable uio/vfio intr/eventfd mapping */ 3144d61138d4SHarman Kalra rc = rte_intr_enable(pci_dev->intr_handle); 31456691acefSXiaoyun Wang if (rc) { 31466691acefSXiaoyun Wang PMD_DRV_LOG(ERR, "Enable rte interrupt failed, dev_name: %s", 31476691acefSXiaoyun Wang eth_dev->data->name); 31486691acefSXiaoyun Wang goto enable_intr_fail; 31496691acefSXiaoyun Wang } 31500371535dSJoyce Kong rte_bit_relaxed_set32(HINIC_DEV_INTR_EN, &nic_dev->dev_status); 31516691acefSXiaoyun Wang 3152224cff4bSXiaoyun Wang hinic_mutex_init(&nic_dev->rx_mode_mutex, NULL); 3153224cff4bSXiaoyun Wang 31541742421bSXiaoyun Wang /* initialize filter info */ 31551742421bSXiaoyun Wang filter_info = &nic_dev->filter; 31561fe89aa3SXiaoyun Wang tcam_info = &nic_dev->tcam; 31571742421bSXiaoyun Wang memset(filter_info, 0, sizeof(struct hinic_filter_info)); 31581fe89aa3SXiaoyun Wang memset(tcam_info, 0, sizeof(struct hinic_tcam_info)); 31591742421bSXiaoyun Wang /* initialize 5tuple filter list */ 31601742421bSXiaoyun Wang TAILQ_INIT(&filter_info->fivetuple_list); 31611fe89aa3SXiaoyun Wang TAILQ_INIT(&tcam_info->tcam_list); 31621742421bSXiaoyun Wang TAILQ_INIT(&nic_dev->filter_ntuple_list); 31631742421bSXiaoyun Wang TAILQ_INIT(&nic_dev->filter_ethertype_list); 31641742421bSXiaoyun Wang TAILQ_INIT(&nic_dev->filter_fdir_rule_list); 31651742421bSXiaoyun Wang TAILQ_INIT(&nic_dev->hinic_flow_list); 31661742421bSXiaoyun Wang 31670371535dSJoyce Kong rte_bit_relaxed_set32(HINIC_DEV_INIT, &nic_dev->dev_status); 31686691acefSXiaoyun Wang PMD_DRV_LOG(INFO, "Initialize %s in primary successfully", 31696691acefSXiaoyun Wang eth_dev->data->name); 31706691acefSXiaoyun Wang 31716691acefSXiaoyun Wang return 0; 31726691acefSXiaoyun Wang 31736691acefSXiaoyun Wang enable_intr_fail: 3174d61138d4SHarman Kalra (void)rte_intr_callback_unregister(pci_dev->intr_handle, 31756691acefSXiaoyun Wang hinic_dev_interrupt_handler, 31766691acefSXiaoyun Wang (void *)eth_dev); 31776691acefSXiaoyun Wang 31786691acefSXiaoyun Wang reg_intr_cb_fail: 31796691acefSXiaoyun Wang hinic_deinit_mac_addr(eth_dev); 31806691acefSXiaoyun Wang 31816691acefSXiaoyun Wang init_mac_fail: 31826691acefSXiaoyun Wang eth_dev->dev_ops = NULL; 31836691acefSXiaoyun Wang hinic_nic_dev_destroy(eth_dev); 31846691acefSXiaoyun Wang 31856691acefSXiaoyun Wang create_nic_dev_fail: 318600499a22SXiaoyun Wang rte_free(nic_dev->mc_list); 318700499a22SXiaoyun Wang nic_dev->mc_list = NULL; 318800499a22SXiaoyun Wang 318900499a22SXiaoyun Wang mc_addr_fail: 31906691acefSXiaoyun Wang rte_free(eth_addr); 31916691acefSXiaoyun Wang eth_dev->data->mac_addrs = NULL; 31926691acefSXiaoyun Wang 31936691acefSXiaoyun Wang eth_addr_fail: 31946691acefSXiaoyun Wang PMD_DRV_LOG(ERR, "Initialize %s in primary failed", 31956691acefSXiaoyun Wang eth_dev->data->name); 31966691acefSXiaoyun Wang return rc; 31976691acefSXiaoyun Wang } 31986691acefSXiaoyun Wang 31991d09792aSZiyang Xuan static int hinic_dev_init(struct rte_eth_dev *eth_dev) 32001d09792aSZiyang Xuan { 32011d09792aSZiyang Xuan struct rte_pci_device *pci_dev; 32021d09792aSZiyang Xuan 32031d09792aSZiyang Xuan pci_dev = RTE_ETH_DEV_TO_PCI(eth_dev); 32041d09792aSZiyang Xuan 32052fc03b23SThomas Monjalon PMD_DRV_LOG(INFO, "Initializing pf hinic-" PCI_PRI_FMT " in %s process", 32061d09792aSZiyang Xuan pci_dev->addr.domain, pci_dev->addr.bus, 32071d09792aSZiyang Xuan pci_dev->addr.devid, pci_dev->addr.function, 32081d09792aSZiyang Xuan (rte_eal_process_type() == RTE_PROC_PRIMARY) ? 32091d09792aSZiyang Xuan "primary" : "secondary"); 32101d09792aSZiyang Xuan 32116691acefSXiaoyun Wang /* rte_eth_dev rx_burst and tx_burst */ 3212076221c8SZiyang Xuan eth_dev->rx_pkt_burst = hinic_recv_pkts; 3213076221c8SZiyang Xuan eth_dev->tx_pkt_burst = hinic_xmit_pkts; 32141d09792aSZiyang Xuan 32151d09792aSZiyang Xuan return hinic_func_init(eth_dev); 32161d09792aSZiyang Xuan } 32171d09792aSZiyang Xuan 32181d09792aSZiyang Xuan static int hinic_dev_uninit(struct rte_eth_dev *dev) 32191d09792aSZiyang Xuan { 32201d09792aSZiyang Xuan if (rte_eal_process_type() != RTE_PROC_PRIMARY) 32211d09792aSZiyang Xuan return 0; 32221d09792aSZiyang Xuan 32231d09792aSZiyang Xuan hinic_dev_close(dev); 32241d09792aSZiyang Xuan 32251d09792aSZiyang Xuan return HINIC_OK; 32261d09792aSZiyang Xuan } 32271d09792aSZiyang Xuan 32281d09792aSZiyang Xuan static struct rte_pci_id pci_id_hinic_map[] = { 32291d09792aSZiyang Xuan { RTE_PCI_DEVICE(HINIC_HUAWEI_VENDOR_ID, HINIC_DEV_ID_PRD) }, 32301d09792aSZiyang Xuan { RTE_PCI_DEVICE(HINIC_HUAWEI_VENDOR_ID, HINIC_DEV_ID_MEZZ_25GE) }, 32311d09792aSZiyang Xuan { RTE_PCI_DEVICE(HINIC_HUAWEI_VENDOR_ID, HINIC_DEV_ID_MEZZ_100GE) }, 32326691acefSXiaoyun Wang { RTE_PCI_DEVICE(HINIC_HUAWEI_VENDOR_ID, HINIC_DEV_ID_VF) }, 32336691acefSXiaoyun Wang { RTE_PCI_DEVICE(HINIC_HUAWEI_VENDOR_ID, HINIC_DEV_ID_VF_HV) }, 32346691acefSXiaoyun Wang { RTE_PCI_DEVICE(HINIC_HUAWEI_VENDOR_ID, HINIC_DEV_ID_1822_DUAL_25GE) }, 32356691acefSXiaoyun Wang { RTE_PCI_DEVICE(HINIC_HUAWEI_VENDOR_ID, HINIC_DEV_ID_1822_100GE) }, 32361d09792aSZiyang Xuan {.vendor_id = 0}, 32371d09792aSZiyang Xuan }; 32381d09792aSZiyang Xuan 32391d09792aSZiyang Xuan static int hinic_pci_probe(struct rte_pci_driver *pci_drv __rte_unused, 32401d09792aSZiyang Xuan struct rte_pci_device *pci_dev) 32411d09792aSZiyang Xuan { 32421d09792aSZiyang Xuan return rte_eth_dev_pci_generic_probe(pci_dev, 32431d09792aSZiyang Xuan sizeof(struct hinic_nic_dev), hinic_dev_init); 32441d09792aSZiyang Xuan } 32451d09792aSZiyang Xuan 32461d09792aSZiyang Xuan static int hinic_pci_remove(struct rte_pci_device *pci_dev) 32471d09792aSZiyang Xuan { 32481d09792aSZiyang Xuan return rte_eth_dev_pci_generic_remove(pci_dev, hinic_dev_uninit); 32491d09792aSZiyang Xuan } 32501d09792aSZiyang Xuan 32511d09792aSZiyang Xuan static struct rte_pci_driver rte_hinic_pmd = { 32521d09792aSZiyang Xuan .id_table = pci_id_hinic_map, 32531d09792aSZiyang Xuan .drv_flags = RTE_PCI_DRV_NEED_MAPPING | RTE_PCI_DRV_INTR_LSC, 32541d09792aSZiyang Xuan .probe = hinic_pci_probe, 32551d09792aSZiyang Xuan .remove = hinic_pci_remove, 32561d09792aSZiyang Xuan }; 32571d09792aSZiyang Xuan 32581d09792aSZiyang Xuan RTE_PMD_REGISTER_PCI(net_hinic, rte_hinic_pmd); 32591d09792aSZiyang Xuan RTE_PMD_REGISTER_PCI_TABLE(net_hinic, pci_id_hinic_map); 3260eeded204SDavid Marchand RTE_LOG_REGISTER_DEFAULT(hinic_logtype, INFO); 3261