LCOV - code coverage report
Current view: top level - drivers/net/vmxnet3 - vmxnet3_ethdev.c (source / functions) Hit Total Coverage
Test: Code coverage Lines: 3 853 0.4 %
Date: 2025-11-01 17:50:34 Functions: 3 52 5.8 %
Legend: Lines: hit not hit | Branches: + taken - not taken # not executed Branches: 2 354 0.6 %

           Branch data     Line data    Source code
       1                 :            : /* SPDX-License-Identifier: BSD-3-Clause
       2                 :            :  * Copyright(c) 2010-2015 Intel Corporation
       3                 :            :  */
       4                 :            : 
       5                 :            : #include <sys/queue.h>
       6                 :            : #include <stdalign.h>
       7                 :            : #include <stdio.h>
       8                 :            : #include <errno.h>
       9                 :            : #include <stdint.h>
      10                 :            : #include <string.h>
      11                 :            : #include <unistd.h>
      12                 :            : #include <stdarg.h>
      13                 :            : #include <fcntl.h>
      14                 :            : #include <inttypes.h>
      15                 :            : #include <rte_byteorder.h>
      16                 :            : #include <rte_common.h>
      17                 :            : #include <rte_cycles.h>
      18                 :            : 
      19                 :            : #include <rte_interrupts.h>
      20                 :            : #include <rte_log.h>
      21                 :            : #include <rte_debug.h>
      22                 :            : #include <rte_pci.h>
      23                 :            : #include <bus_pci_driver.h>
      24                 :            : #include <rte_branch_prediction.h>
      25                 :            : #include <rte_memory.h>
      26                 :            : #include <rte_memzone.h>
      27                 :            : #include <rte_eal.h>
      28                 :            : #include <rte_alarm.h>
      29                 :            : #include <rte_ether.h>
      30                 :            : #include <ethdev_driver.h>
      31                 :            : #include <ethdev_pci.h>
      32                 :            : #include <rte_string_fns.h>
      33                 :            : #include <rte_malloc.h>
      34                 :            : #include <dev_driver.h>
      35                 :            : 
      36                 :            : #include "base/vmxnet3_defs.h"
      37                 :            : 
      38                 :            : #include "vmxnet3_ring.h"
      39                 :            : #include "vmxnet3_logs.h"
      40                 :            : #include "vmxnet3_ethdev.h"
      41                 :            : 
      42                 :            : #define VMXNET3_TX_MAX_SEG      UINT8_MAX
      43                 :            : 
      44                 :            : #define VMXNET3_TX_OFFLOAD_CAP          \
      45                 :            :         (RTE_ETH_TX_OFFLOAD_VLAN_INSERT |       \
      46                 :            :          RTE_ETH_TX_OFFLOAD_TCP_CKSUM | \
      47                 :            :          RTE_ETH_TX_OFFLOAD_UDP_CKSUM | \
      48                 :            :          RTE_ETH_TX_OFFLOAD_TCP_TSO |   \
      49                 :            :          RTE_ETH_TX_OFFLOAD_MULTI_SEGS)
      50                 :            : 
      51                 :            : #define VMXNET3_RX_OFFLOAD_CAP          \
      52                 :            :         (RTE_ETH_RX_OFFLOAD_VLAN_STRIP |        \
      53                 :            :          RTE_ETH_RX_OFFLOAD_VLAN_FILTER |   \
      54                 :            :          RTE_ETH_RX_OFFLOAD_SCATTER |   \
      55                 :            :          RTE_ETH_RX_OFFLOAD_UDP_CKSUM | \
      56                 :            :          RTE_ETH_RX_OFFLOAD_TCP_CKSUM | \
      57                 :            :          RTE_ETH_RX_OFFLOAD_TCP_LRO |   \
      58                 :            :          RTE_ETH_RX_OFFLOAD_RSS_HASH)
      59                 :            : 
      60                 :            : int vmxnet3_segs_dynfield_offset = -1;
      61                 :            : 
      62                 :            : static int eth_vmxnet3_dev_init(struct rte_eth_dev *eth_dev);
      63                 :            : static int eth_vmxnet3_dev_uninit(struct rte_eth_dev *eth_dev);
      64                 :            : static int vmxnet3_dev_configure(struct rte_eth_dev *dev);
      65                 :            : static int vmxnet3_dev_start(struct rte_eth_dev *dev);
      66                 :            : static int vmxnet3_dev_stop(struct rte_eth_dev *dev);
      67                 :            : static int vmxnet3_dev_close(struct rte_eth_dev *dev);
      68                 :            : static int vmxnet3_dev_reset(struct rte_eth_dev *dev);
      69                 :            : static void vmxnet3_dev_set_rxmode(struct vmxnet3_hw *hw, uint32_t feature, int set);
      70                 :            : static int vmxnet3_dev_promiscuous_enable(struct rte_eth_dev *dev);
      71                 :            : static int vmxnet3_dev_promiscuous_disable(struct rte_eth_dev *dev);
      72                 :            : static int vmxnet3_dev_allmulticast_enable(struct rte_eth_dev *dev);
      73                 :            : static int vmxnet3_dev_allmulticast_disable(struct rte_eth_dev *dev);
      74                 :            : static int __vmxnet3_dev_link_update(struct rte_eth_dev *dev,
      75                 :            :                                      int wait_to_complete);
      76                 :            : static int vmxnet3_dev_link_update(struct rte_eth_dev *dev,
      77                 :            :                                    int wait_to_complete);
      78                 :            : static void vmxnet3_hw_stats_save(struct vmxnet3_hw *hw);
      79                 :            : static int vmxnet3_dev_stats_get(struct rte_eth_dev *dev,
      80                 :            :                                   struct rte_eth_stats *stats,
      81                 :            :                                   struct eth_queue_stats *qstats);
      82                 :            : static int vmxnet3_dev_stats_reset(struct rte_eth_dev *dev);
      83                 :            : static int vmxnet3_dev_xstats_get_names(struct rte_eth_dev *dev,
      84                 :            :                                         struct rte_eth_xstat_name *xstats,
      85                 :            :                                         unsigned int n);
      86                 :            : static int vmxnet3_dev_xstats_get(struct rte_eth_dev *dev,
      87                 :            :                                   struct rte_eth_xstat *xstats, unsigned int n);
      88                 :            : static int vmxnet3_dev_info_get(struct rte_eth_dev *dev,
      89                 :            :                                 struct rte_eth_dev_info *dev_info);
      90                 :            : static int vmxnet3_hw_ver_get(struct rte_eth_dev *dev,
      91                 :            :                               char *fw_version, size_t fw_size);
      92                 :            : static const uint32_t *
      93                 :            : vmxnet3_dev_supported_ptypes_get(struct rte_eth_dev *dev,
      94                 :            :                                  size_t *no_of_elements);
      95                 :            : static int vmxnet3_dev_mtu_set(struct rte_eth_dev *dev, uint16_t mtu);
      96                 :            : static int vmxnet3_dev_vlan_filter_set(struct rte_eth_dev *dev,
      97                 :            :                                        uint16_t vid, int on);
      98                 :            : static int vmxnet3_dev_vlan_offload_set(struct rte_eth_dev *dev, int mask);
      99                 :            : static int vmxnet3_mac_addr_set(struct rte_eth_dev *dev,
     100                 :            :                                  struct rte_ether_addr *mac_addr);
     101                 :            : static void vmxnet3_process_events(struct rte_eth_dev *dev);
     102                 :            : static void vmxnet3_interrupt_handler(void *param);
     103                 :            : static int
     104                 :            : vmxnet3_rss_reta_update(struct rte_eth_dev *dev,
     105                 :            :                         struct rte_eth_rss_reta_entry64 *reta_conf,
     106                 :            :                         uint16_t reta_size);
     107                 :            : static int
     108                 :            : vmxnet3_rss_reta_query(struct rte_eth_dev *dev,
     109                 :            :                        struct rte_eth_rss_reta_entry64 *reta_conf,
     110                 :            :                        uint16_t reta_size);
     111                 :            : 
     112                 :            : static int vmxnet3_dev_rx_queue_intr_enable(struct rte_eth_dev *dev,
     113                 :            :                                                 uint16_t queue_id);
     114                 :            : static int vmxnet3_dev_rx_queue_intr_disable(struct rte_eth_dev *dev,
     115                 :            :                                                 uint16_t queue_id);
     116                 :            : 
     117                 :            : /*
     118                 :            :  * The set of PCI devices this driver supports
     119                 :            :  */
     120                 :            : #define VMWARE_PCI_VENDOR_ID 0x15AD
     121                 :            : #define VMWARE_DEV_ID_VMXNET3 0x07B0
     122                 :            : static const struct rte_pci_id pci_id_vmxnet3_map[] = {
     123                 :            :         { RTE_PCI_DEVICE(VMWARE_PCI_VENDOR_ID, VMWARE_DEV_ID_VMXNET3) },
     124                 :            :         { .vendor_id = 0, /* sentinel */ },
     125                 :            : };
     126                 :            : 
     127                 :            : static const struct eth_dev_ops vmxnet3_eth_dev_ops = {
     128                 :            :         .dev_configure        = vmxnet3_dev_configure,
     129                 :            :         .dev_start            = vmxnet3_dev_start,
     130                 :            :         .dev_stop             = vmxnet3_dev_stop,
     131                 :            :         .dev_close            = vmxnet3_dev_close,
     132                 :            :         .dev_reset            = vmxnet3_dev_reset,
     133                 :            :         .link_update          = vmxnet3_dev_link_update,
     134                 :            :         .promiscuous_enable   = vmxnet3_dev_promiscuous_enable,
     135                 :            :         .promiscuous_disable  = vmxnet3_dev_promiscuous_disable,
     136                 :            :         .allmulticast_enable  = vmxnet3_dev_allmulticast_enable,
     137                 :            :         .allmulticast_disable = vmxnet3_dev_allmulticast_disable,
     138                 :            :         .mac_addr_set         = vmxnet3_mac_addr_set,
     139                 :            :         .mtu_set              = vmxnet3_dev_mtu_set,
     140                 :            :         .stats_get            = vmxnet3_dev_stats_get,
     141                 :            :         .stats_reset          = vmxnet3_dev_stats_reset,
     142                 :            :         .xstats_get           = vmxnet3_dev_xstats_get,
     143                 :            :         .xstats_get_names     = vmxnet3_dev_xstats_get_names,
     144                 :            :         .dev_infos_get        = vmxnet3_dev_info_get,
     145                 :            :         .fw_version_get       = vmxnet3_hw_ver_get,
     146                 :            :         .dev_supported_ptypes_get = vmxnet3_dev_supported_ptypes_get,
     147                 :            :         .vlan_filter_set      = vmxnet3_dev_vlan_filter_set,
     148                 :            :         .vlan_offload_set     = vmxnet3_dev_vlan_offload_set,
     149                 :            :         .rx_queue_setup       = vmxnet3_dev_rx_queue_setup,
     150                 :            :         .rx_queue_release     = vmxnet3_dev_rx_queue_release,
     151                 :            :         .rx_queue_intr_enable = vmxnet3_dev_rx_queue_intr_enable,
     152                 :            :         .rx_queue_intr_disable = vmxnet3_dev_rx_queue_intr_disable,
     153                 :            :         .tx_queue_setup       = vmxnet3_dev_tx_queue_setup,
     154                 :            :         .tx_queue_release     = vmxnet3_dev_tx_queue_release,
     155                 :            :         .reta_update          = vmxnet3_rss_reta_update,
     156                 :            :         .reta_query           = vmxnet3_rss_reta_query,
     157                 :            : };
     158                 :            : 
     159                 :            : struct vmxnet3_xstats_name_off {
     160                 :            :         char name[RTE_ETH_XSTATS_NAME_SIZE];
     161                 :            :         unsigned int offset;
     162                 :            : };
     163                 :            : 
     164                 :            : /* tx_qX_ is prepended to the name string here */
     165                 :            : static const struct vmxnet3_xstats_name_off vmxnet3_txq_stat_strings[] = {
     166                 :            :         {"drop_total",         offsetof(struct vmxnet3_txq_stats, drop_total)},
     167                 :            :         {"drop_too_many_segs", offsetof(struct vmxnet3_txq_stats, drop_too_many_segs)},
     168                 :            :         {"drop_tso",           offsetof(struct vmxnet3_txq_stats, drop_tso)},
     169                 :            :         {"tx_ring_full",       offsetof(struct vmxnet3_txq_stats, tx_ring_full)},
     170                 :            : };
     171                 :            : 
     172                 :            : /* rx_qX_ is prepended to the name string here */
     173                 :            : static const struct vmxnet3_xstats_name_off vmxnet3_rxq_stat_strings[] = {
     174                 :            :         {"drop_total",           offsetof(struct vmxnet3_rxq_stats, drop_total)},
     175                 :            :         {"drop_err",             offsetof(struct vmxnet3_rxq_stats, drop_err)},
     176                 :            :         {"drop_fcs",             offsetof(struct vmxnet3_rxq_stats, drop_fcs)},
     177                 :            :         {"rx_buf_alloc_failure", offsetof(struct vmxnet3_rxq_stats, rx_buf_alloc_failure)},
     178                 :            : };
     179                 :            : 
     180                 :            : static const struct rte_memzone *
     181                 :          0 : gpa_zone_reserve(struct rte_eth_dev *dev, uint32_t size,
     182                 :            :                  const char *post_string, int socket_id,
     183                 :            :                  uint16_t align, bool reuse)
     184                 :            : {
     185                 :            :         char z_name[RTE_MEMZONE_NAMESIZE];
     186                 :            :         const struct rte_memzone *mz;
     187                 :            : 
     188                 :          0 :         snprintf(z_name, sizeof(z_name), "eth_p%d_%s",
     189                 :          0 :                         dev->data->port_id, post_string);
     190                 :            : 
     191                 :          0 :         mz = rte_memzone_lookup(z_name);
     192         [ #  # ]:          0 :         if (!reuse) {
     193                 :          0 :                 rte_memzone_free(mz);
     194                 :          0 :                 return rte_memzone_reserve_aligned(z_name, size, socket_id,
     195                 :            :                                 RTE_MEMZONE_IOVA_CONTIG, align);
     196                 :            :         }
     197                 :            : 
     198         [ #  # ]:          0 :         if (mz)
     199                 :            :                 return mz;
     200                 :            : 
     201                 :          0 :         return rte_memzone_reserve_aligned(z_name, size, socket_id,
     202                 :            :                         RTE_MEMZONE_IOVA_CONTIG, align);
     203                 :            : }
     204                 :            : 
     205                 :            : /*
     206                 :            :  * Enable the given interrupt
     207                 :            :  */
     208                 :            : static void
     209                 :          0 : vmxnet3_enable_intr(struct vmxnet3_hw *hw, unsigned int intr_idx)
     210                 :            : {
     211                 :          0 :         PMD_INIT_FUNC_TRACE();
     212                 :          0 :         VMXNET3_WRITE_BAR0_REG(hw, VMXNET3_REG_IMR + intr_idx * 8, 0);
     213                 :          0 : }
     214                 :            : 
     215                 :            : /*
     216                 :            :  * Disable the given interrupt
     217                 :            :  */
     218                 :            : static void
     219                 :          0 : vmxnet3_disable_intr(struct vmxnet3_hw *hw, unsigned int intr_idx)
     220                 :            : {
     221                 :          0 :         PMD_INIT_FUNC_TRACE();
     222                 :          0 :         VMXNET3_WRITE_BAR0_REG(hw, VMXNET3_REG_IMR + intr_idx * 8, 1);
     223                 :          0 : }
     224                 :            : 
     225                 :            : /*
     226                 :            :  * Simple helper to get intrCtrl and eventIntrIdx based on config and hw version
     227                 :            :  */
     228                 :            : static void
     229                 :            : vmxnet3_get_intr_ctrl_ev(struct vmxnet3_hw *hw,
     230                 :            :                          uint8 **out_eventIntrIdx,
     231                 :            :                          uint32 **out_intrCtrl)
     232                 :            : {
     233                 :            : 
     234   [ #  #  #  #  :          0 :         if (VMXNET3_VERSION_GE_6(hw) && hw->queuesExtEnabled) {
          #  #  #  #  #  
                #  #  # ]
     235                 :          0 :                 *out_eventIntrIdx = &hw->shared->devReadExt.intrConfExt.eventIntrIdx;
     236                 :          0 :                 *out_intrCtrl = &hw->shared->devReadExt.intrConfExt.intrCtrl;
     237                 :            :         } else {
     238                 :          0 :                 *out_eventIntrIdx = &hw->shared->devRead.intrConf.eventIntrIdx;
     239                 :          0 :                 *out_intrCtrl = &hw->shared->devRead.intrConf.intrCtrl;
     240                 :            :         }
     241                 :            : }
     242                 :            : 
     243                 :            : /*
     244                 :            :  * Disable all intrs used by the device
     245                 :            :  */
     246                 :            : static void
     247                 :          0 : vmxnet3_disable_all_intrs(struct vmxnet3_hw *hw)
     248                 :            : {
     249                 :            :         int i;
     250                 :            :         uint8 *eventIntrIdx;
     251                 :            :         uint32 *intrCtrl;
     252                 :            : 
     253                 :          0 :         PMD_INIT_FUNC_TRACE();
     254                 :            :         vmxnet3_get_intr_ctrl_ev(hw, &eventIntrIdx, &intrCtrl);
     255                 :            : 
     256                 :          0 :         *intrCtrl |= rte_cpu_to_le_32(VMXNET3_IC_DISABLE_ALL);
     257                 :            : 
     258         [ #  # ]:          0 :         for (i = 0; i < hw->intr.num_intrs; i++)
     259                 :          0 :                 vmxnet3_disable_intr(hw, i);
     260                 :          0 : }
     261                 :            : 
     262                 :            : #ifndef RTE_EXEC_ENV_FREEBSD
     263                 :            : /*
     264                 :            :  * Enable all intrs used by the device
     265                 :            :  */
     266                 :            : static void
     267                 :          0 : vmxnet3_enable_all_intrs(struct vmxnet3_hw *hw)
     268                 :            : {
     269                 :            :         uint8 *eventIntrIdx;
     270                 :            :         uint32 *intrCtrl;
     271                 :            : 
     272                 :          0 :         PMD_INIT_FUNC_TRACE();
     273                 :            :         vmxnet3_get_intr_ctrl_ev(hw, &eventIntrIdx, &intrCtrl);
     274                 :            : 
     275                 :          0 :         *intrCtrl &= rte_cpu_to_le_32(~VMXNET3_IC_DISABLE_ALL);
     276                 :            : 
     277         [ #  # ]:          0 :         if (hw->intr.lsc_only) {
     278                 :          0 :                 vmxnet3_enable_intr(hw, *eventIntrIdx);
     279                 :            :         } else {
     280                 :            :                 int i;
     281                 :            : 
     282         [ #  # ]:          0 :                 for (i = 0; i < hw->intr.num_intrs; i++)
     283                 :          0 :                         vmxnet3_enable_intr(hw, i);
     284                 :            :         }
     285                 :          0 : }
     286                 :            : #endif
     287                 :            : 
     288                 :            : /*
     289                 :            :  * Gets tx data ring descriptor size.
     290                 :            :  */
     291                 :            : static uint16_t
     292                 :            : eth_vmxnet3_txdata_get(struct vmxnet3_hw *hw)
     293                 :            : {
     294                 :            :         uint16 txdata_desc_size;
     295                 :            : 
     296                 :          0 :         VMXNET3_WRITE_BAR1_REG(hw, VMXNET3_REG_CMD,
     297                 :            :                                VMXNET3_CMD_GET_TXDATA_DESC_SIZE);
     298                 :          0 :         txdata_desc_size = VMXNET3_READ_BAR1_REG(hw, VMXNET3_REG_CMD);
     299                 :            : 
     300                 :          0 :         return (txdata_desc_size < VMXNET3_TXDATA_DESC_MIN_SIZE ||
     301                 :          0 :                 txdata_desc_size > VMXNET3_TXDATA_DESC_MAX_SIZE ||
     302         [ #  # ]:          0 :                 txdata_desc_size & VMXNET3_TXDATA_DESC_SIZE_MASK) ?
     303         [ #  # ]:          0 :                 sizeof(struct Vmxnet3_TxDataDesc) : txdata_desc_size;
     304                 :            : }
     305                 :            : 
     306                 :            : static int
     307                 :          0 : eth_vmxnet3_setup_capabilities(struct vmxnet3_hw *hw,
     308                 :            :                                struct rte_eth_dev *eth_dev)
     309                 :            : {
     310                 :            :         uint32_t dcr, ptcr, value;
     311                 :          0 :         struct rte_pci_device *pci_dev = RTE_ETH_DEV_TO_PCI(eth_dev);
     312                 :            : 
     313                 :          0 :         VMXNET3_WRITE_BAR1_REG(hw, VMXNET3_REG_CMD,
     314                 :            :                                VMXNET3_CMD_GET_MAX_CAPABILITIES);
     315                 :          0 :         value = VMXNET3_READ_BAR1_REG(hw, VMXNET3_REG_CMD);
     316                 :          0 :         hw->max_capabilities[0] = value;
     317                 :          0 :         dcr = VMXNET3_READ_BAR1_REG(hw, VMXNET3_REG_DCR);
     318                 :          0 :         hw->DCR_capabilities[0] = dcr;
     319                 :          0 :         hw->used_DCR_capabilities[0] = 0;
     320                 :          0 :         ptcr = VMXNET3_READ_BAR1_REG(hw, VMXNET3_REG_PTCR);
     321                 :          0 :         hw->PTCR_capabilities[0] = ptcr;
     322                 :          0 :         hw->used_PTCR_capabilities[0] = 0;
     323                 :            : 
     324   [ #  #  #  # ]:          0 :         if (hw->uptv2_enabled && !(ptcr & (1 << VMXNET3_DCR_ERROR))) {
     325                 :          0 :                 PMD_DRV_LOG(NOTICE, "UPTv2 enabled");
     326                 :          0 :                 hw->used_PTCR_capabilities[0] = ptcr;
     327                 :            :         } else {
     328                 :            :                 /* Use all DCR capabilities, but disable large bar */
     329                 :          0 :                 hw->used_DCR_capabilities[0] = dcr &
     330                 :            :                                         (~(1UL << VMXNET3_CAP_LARGE_BAR));
     331                 :          0 :                 PMD_DRV_LOG(NOTICE, "UPTv2 disabled");
     332                 :            :         }
     333         [ #  # ]:          0 :         if (hw->DCR_capabilities[0] & (1UL << VMXNET3_CAP_OOORX_COMP) &&
     334         [ #  # ]:          0 :             hw->PTCR_capabilities[0] & (1UL << VMXNET3_CAP_OOORX_COMP)) {
     335         [ #  # ]:          0 :                 if (hw->uptv2_enabled) {
     336                 :          0 :                         hw->used_PTCR_capabilities[0] |=
     337                 :            :                                 (1UL << VMXNET3_CAP_OOORX_COMP);
     338                 :            :                 }
     339                 :            :         }
     340         [ #  # ]:          0 :         if (hw->used_PTCR_capabilities[0]) {
     341                 :          0 :                 VMXNET3_WRITE_BAR1_REG(hw, VMXNET3_REG_DCR,
     342                 :            :                                        hw->used_PTCR_capabilities[0]);
     343         [ #  # ]:          0 :         } else if (hw->used_DCR_capabilities[0]) {
     344                 :          0 :                 VMXNET3_WRITE_BAR1_REG(hw, VMXNET3_REG_DCR,
     345                 :            :                                        hw->used_DCR_capabilities[0]);
     346                 :            :         }
     347                 :          0 :         VMXNET3_WRITE_BAR1_REG(hw, VMXNET3_REG_CMD, VMXNET3_CMD_GET_DCR0_REG);
     348                 :          0 :         dcr = VMXNET3_READ_BAR1_REG(hw, VMXNET3_REG_CMD);
     349                 :          0 :         hw->used_DCR_capabilities[0] = dcr;
     350         [ #  # ]:          0 :         PMD_DRV_LOG(DEBUG, "Dev " PCI_PRI_FMT ", vmxnet3 v%d, UPT enabled: %s, "
     351                 :            :                     "DCR0=0x%08x, used DCR=0x%08x, "
     352                 :            :                     "PTCR=0x%08x, used PTCR=0x%08x",
     353                 :            :                     pci_dev->addr.domain, pci_dev->addr.bus,
     354                 :            :                     pci_dev->addr.devid, pci_dev->addr.function, hw->version,
     355                 :            :                     hw->uptv2_enabled ? "true" : "false",
     356                 :            :                     hw->DCR_capabilities[0], hw->used_DCR_capabilities[0],
     357                 :            :                     hw->PTCR_capabilities[0], hw->used_PTCR_capabilities[0]);
     358                 :          0 :         return 0;
     359                 :            : }
     360                 :            : 
     361                 :            : /*
     362                 :            :  * It returns 0 on success.
     363                 :            :  */
     364                 :            : static int
     365                 :          0 : eth_vmxnet3_dev_init(struct rte_eth_dev *eth_dev)
     366                 :            : {
     367                 :            :         struct rte_pci_device *pci_dev;
     368                 :          0 :         struct vmxnet3_hw *hw = eth_dev->data->dev_private;
     369                 :            :         uint32_t mac_hi, mac_lo, ver;
     370                 :            :         struct rte_eth_link link;
     371                 :            :         static const struct rte_mbuf_dynfield vmxnet3_segs_dynfield_desc = {
     372                 :            :                 .name = VMXNET3_SEGS_DYNFIELD_NAME,
     373                 :            :                 .size = sizeof(vmxnet3_segs_dynfield_t),
     374                 :            :                 .align = alignof(vmxnet3_segs_dynfield_t),
     375                 :            :         };
     376                 :            : 
     377                 :          0 :         PMD_INIT_FUNC_TRACE();
     378                 :            : 
     379                 :          0 :         eth_dev->dev_ops = &vmxnet3_eth_dev_ops;
     380                 :          0 :         eth_dev->rx_pkt_burst = &vmxnet3_recv_pkts;
     381                 :          0 :         eth_dev->tx_pkt_burst = &vmxnet3_xmit_pkts;
     382                 :          0 :         eth_dev->tx_pkt_prepare = vmxnet3_prep_pkts;
     383                 :          0 :         eth_dev->rx_queue_count = vmxnet3_dev_rx_queue_count;
     384                 :          0 :         pci_dev = RTE_ETH_DEV_TO_PCI(eth_dev);
     385                 :            : 
     386                 :            :         /* extra mbuf field is required to guess MSS */
     387                 :          0 :         vmxnet3_segs_dynfield_offset =
     388                 :          0 :                 rte_mbuf_dynfield_register(&vmxnet3_segs_dynfield_desc);
     389         [ #  # ]:          0 :         if (vmxnet3_segs_dynfield_offset < 0) {
     390                 :          0 :                 PMD_INIT_LOG(ERR, "Cannot register mbuf field.");
     391                 :          0 :                 return -rte_errno;
     392                 :            :         }
     393                 :            : 
     394                 :            :         /*
     395                 :            :          * for secondary processes, we don't initialize any further as primary
     396                 :            :          * has already done this work.
     397                 :            :          */
     398         [ #  # ]:          0 :         if (rte_eal_process_type() != RTE_PROC_PRIMARY)
     399                 :            :                 return 0;
     400                 :            : 
     401                 :          0 :         rte_eth_copy_pci_info(eth_dev, pci_dev);
     402                 :          0 :         eth_dev->data->dev_flags |= RTE_ETH_DEV_AUTOFILL_QUEUE_XSTATS;
     403                 :            : 
     404                 :            :         /* Vendor and Device ID need to be set before init of shared code */
     405                 :          0 :         hw->device_id = pci_dev->id.device_id;
     406                 :          0 :         hw->vendor_id = pci_dev->id.vendor_id;
     407                 :          0 :         hw->adapter_stopped = TRUE;
     408                 :          0 :         hw->hw_addr0 = (void *)pci_dev->mem_resource[0].addr;
     409                 :          0 :         hw->hw_addr1 = (void *)pci_dev->mem_resource[1].addr;
     410                 :            : 
     411                 :          0 :         hw->num_rx_queues = 1;
     412                 :          0 :         hw->num_tx_queues = 1;
     413                 :          0 :         hw->bufs_per_pkt = 1;
     414                 :            : 
     415                 :            :         /* Check h/w version compatibility with driver. */
     416                 :            :         ver = VMXNET3_READ_BAR1_REG(hw, VMXNET3_REG_VRRS);
     417                 :            : 
     418         [ #  # ]:          0 :         if (ver & (1 << VMXNET3_REV_7)) {
     419                 :          0 :                 VMXNET3_WRITE_BAR1_REG(hw, VMXNET3_REG_VRRS,
     420                 :            :                                        1 << VMXNET3_REV_7);
     421                 :          0 :                 hw->version = VMXNET3_REV_7 + 1;
     422         [ #  # ]:          0 :         } else if (ver & (1 << VMXNET3_REV_6)) {
     423                 :          0 :                 VMXNET3_WRITE_BAR1_REG(hw, VMXNET3_REG_VRRS,
     424                 :            :                                        1 << VMXNET3_REV_6);
     425                 :          0 :                 hw->version = VMXNET3_REV_6 + 1;
     426         [ #  # ]:          0 :         } else if (ver & (1 << VMXNET3_REV_5)) {
     427                 :          0 :                 VMXNET3_WRITE_BAR1_REG(hw, VMXNET3_REG_VRRS,
     428                 :            :                                        1 << VMXNET3_REV_5);
     429                 :          0 :                 hw->version = VMXNET3_REV_5 + 1;
     430         [ #  # ]:          0 :         } else if (ver & (1 << VMXNET3_REV_4)) {
     431                 :          0 :                 VMXNET3_WRITE_BAR1_REG(hw, VMXNET3_REG_VRRS,
     432                 :            :                                        1 << VMXNET3_REV_4);
     433                 :          0 :                 hw->version = VMXNET3_REV_4 + 1;
     434         [ #  # ]:          0 :         } else if (ver & (1 << VMXNET3_REV_3)) {
     435                 :          0 :                 VMXNET3_WRITE_BAR1_REG(hw, VMXNET3_REG_VRRS,
     436                 :            :                                        1 << VMXNET3_REV_3);
     437                 :          0 :                 hw->version = VMXNET3_REV_3 + 1;
     438         [ #  # ]:          0 :         } else if (ver & (1 << VMXNET3_REV_2)) {
     439                 :          0 :                 VMXNET3_WRITE_BAR1_REG(hw, VMXNET3_REG_VRRS,
     440                 :            :                                        1 << VMXNET3_REV_2);
     441                 :          0 :                 hw->version = VMXNET3_REV_2 + 1;
     442         [ #  # ]:          0 :         } else if (ver & (1 << VMXNET3_REV_1)) {
     443                 :          0 :                 VMXNET3_WRITE_BAR1_REG(hw, VMXNET3_REG_VRRS,
     444                 :            :                                        1 << VMXNET3_REV_1);
     445                 :          0 :                 hw->version = VMXNET3_REV_1 + 1;
     446                 :            :         } else {
     447                 :          0 :                 PMD_INIT_LOG(ERR, "Incompatible hardware version: %d", ver);
     448                 :          0 :                 return -EIO;
     449                 :            :         }
     450                 :            : 
     451                 :          0 :         PMD_INIT_LOG(INFO, "Using device v%d", hw->version);
     452                 :            : 
     453                 :            :         /* Check UPT version compatibility with driver. */
     454                 :          0 :         ver = VMXNET3_READ_BAR1_REG(hw, VMXNET3_REG_UVRS);
     455                 :          0 :         PMD_INIT_LOG(DEBUG, "UPT hardware version : %d", ver);
     456         [ #  # ]:          0 :         if (ver & 0x1)
     457                 :          0 :                 VMXNET3_WRITE_BAR1_REG(hw, VMXNET3_REG_UVRS, 1);
     458                 :            :         else {
     459                 :          0 :                 PMD_INIT_LOG(ERR, "Incompatible UPT version.");
     460                 :          0 :                 return -EIO;
     461                 :            :         }
     462                 :            : 
     463         [ #  # ]:          0 :         if (VMXNET3_VERSION_GE_7(hw)) {
     464                 :            :                 /* start with UPTv2 enabled to avoid ESXi issues */
     465                 :          0 :                 hw->uptv2_enabled = TRUE;
     466                 :          0 :                 eth_vmxnet3_setup_capabilities(hw, eth_dev);
     467                 :            :         }
     468                 :            : 
     469         [ #  # ]:          0 :         if (hw->used_DCR_capabilities[0] & (1 << VMXNET3_CAP_LARGE_BAR)) {
     470                 :          0 :                 hw->tx_prod_offset = VMXNET3_REG_LB_TXPROD;
     471                 :          0 :                 hw->rx_prod_offset[0] = VMXNET3_REG_LB_RXPROD;
     472                 :          0 :                 hw->rx_prod_offset[1] = VMXNET3_REG_LB_RXPROD2;
     473                 :            :         } else {
     474                 :          0 :                 hw->tx_prod_offset = VMXNET3_REG_TXPROD;
     475                 :          0 :                 hw->rx_prod_offset[0] = VMXNET3_REG_RXPROD;
     476                 :          0 :                 hw->rx_prod_offset[1] = VMXNET3_REG_RXPROD2;
     477                 :            :         }
     478                 :            : 
     479                 :            :         /* Getting MAC Address */
     480                 :          0 :         mac_lo = VMXNET3_READ_BAR1_REG(hw, VMXNET3_REG_MACL);
     481                 :          0 :         mac_hi = VMXNET3_READ_BAR1_REG(hw, VMXNET3_REG_MACH);
     482                 :          0 :         memcpy(hw->perm_addr, &mac_lo, 4);
     483                 :          0 :         memcpy(hw->perm_addr + 4, &mac_hi, 2);
     484                 :            : 
     485                 :            :         /* Allocate memory for storing MAC addresses */
     486                 :          0 :         eth_dev->data->mac_addrs = rte_zmalloc("vmxnet3", RTE_ETHER_ADDR_LEN *
     487                 :            :                                                VMXNET3_MAX_MAC_ADDRS, 0);
     488         [ #  # ]:          0 :         if (eth_dev->data->mac_addrs == NULL) {
     489                 :          0 :                 PMD_INIT_LOG(ERR,
     490                 :            :                              "Failed to allocate %d bytes needed to store MAC addresses",
     491                 :            :                              RTE_ETHER_ADDR_LEN * VMXNET3_MAX_MAC_ADDRS);
     492                 :          0 :                 return -ENOMEM;
     493                 :            :         }
     494                 :            :         /* Copy the permanent MAC address */
     495                 :            :         rte_ether_addr_copy((struct rte_ether_addr *)hw->perm_addr,
     496                 :            :                         &eth_dev->data->mac_addrs[0]);
     497                 :            : 
     498                 :          0 :         PMD_INIT_LOG(DEBUG, "MAC Address : " RTE_ETHER_ADDR_PRT_FMT,
     499                 :            :                      hw->perm_addr[0], hw->perm_addr[1], hw->perm_addr[2],
     500                 :            :                      hw->perm_addr[3], hw->perm_addr[4], hw->perm_addr[5]);
     501                 :            : 
     502                 :            :         /* Put device in Quiesce Mode */
     503                 :          0 :         VMXNET3_WRITE_BAR1_REG(hw, VMXNET3_REG_CMD, VMXNET3_CMD_QUIESCE_DEV);
     504                 :            : 
     505                 :            :         /* allow untagged pkts */
     506                 :          0 :         VMXNET3_SET_VFTABLE_ENTRY(hw->shadow_vfta, 0);
     507                 :            : 
     508         [ #  # ]:          0 :         hw->txdata_desc_size = VMXNET3_VERSION_GE_3(hw) ?
     509                 :            :                 eth_vmxnet3_txdata_get(hw) : sizeof(struct Vmxnet3_TxDataDesc);
     510                 :            : 
     511         [ #  # ]:          0 :         hw->rxdata_desc_size = VMXNET3_VERSION_GE_3(hw) ?
     512                 :            :                 VMXNET3_DEF_RXDATA_DESC_SIZE : 0;
     513                 :            :         RTE_ASSERT((hw->rxdata_desc_size & ~VMXNET3_RXDATA_DESC_SIZE_MASK) ==
     514                 :            :                    hw->rxdata_desc_size);
     515                 :            : 
     516                 :            :         /* clear shadow stats */
     517                 :          0 :         memset(hw->saved_tx_stats, 0, sizeof(hw->saved_tx_stats));
     518                 :          0 :         memset(hw->saved_rx_stats, 0, sizeof(hw->saved_rx_stats));
     519                 :            : 
     520                 :            :         /* clear snapshot stats */
     521                 :          0 :         memset(hw->snapshot_tx_stats, 0, sizeof(hw->snapshot_tx_stats));
     522                 :          0 :         memset(hw->snapshot_rx_stats, 0, sizeof(hw->snapshot_rx_stats));
     523                 :            : 
     524                 :            :         /* set the initial link status */
     525                 :            :         memset(&link, 0, sizeof(link));
     526                 :          0 :         link.link_duplex = RTE_ETH_LINK_FULL_DUPLEX;
     527                 :          0 :         link.link_speed = RTE_ETH_SPEED_NUM_10G;
     528                 :            :         link.link_autoneg = RTE_ETH_LINK_FIXED;
     529                 :          0 :         rte_eth_linkstatus_set(eth_dev, &link);
     530                 :            : 
     531                 :          0 :         return 0;
     532                 :            : }
     533                 :            : 
     534                 :            : static int
     535                 :          0 : eth_vmxnet3_dev_uninit(struct rte_eth_dev *eth_dev)
     536                 :            : {
     537                 :          0 :         struct vmxnet3_hw *hw = eth_dev->data->dev_private;
     538                 :            : 
     539                 :          0 :         PMD_INIT_FUNC_TRACE();
     540                 :            : 
     541         [ #  # ]:          0 :         if (rte_eal_process_type() != RTE_PROC_PRIMARY)
     542                 :            :                 return 0;
     543                 :            : 
     544         [ #  # ]:          0 :         if (hw->adapter_stopped == 0) {
     545                 :          0 :                 PMD_INIT_LOG(DEBUG, "Device has not been closed.");
     546                 :          0 :                 return -EBUSY;
     547                 :            :         }
     548                 :            : 
     549                 :            :         return 0;
     550                 :            : }
     551                 :            : 
     552                 :          0 : static int eth_vmxnet3_pci_probe(struct rte_pci_driver *pci_drv __rte_unused,
     553                 :            :         struct rte_pci_device *pci_dev)
     554                 :            : {
     555                 :          0 :         return rte_eth_dev_pci_generic_probe(pci_dev,
     556                 :            :                 sizeof(struct vmxnet3_hw), eth_vmxnet3_dev_init);
     557                 :            : }
     558                 :            : 
     559                 :          0 : static int eth_vmxnet3_pci_remove(struct rte_pci_device *pci_dev)
     560                 :            : {
     561                 :          0 :         return rte_eth_dev_pci_generic_remove(pci_dev, eth_vmxnet3_dev_uninit);
     562                 :            : }
     563                 :            : 
     564                 :            : static struct rte_pci_driver rte_vmxnet3_pmd = {
     565                 :            :         .id_table = pci_id_vmxnet3_map,
     566                 :            :         .drv_flags = RTE_PCI_DRV_NEED_MAPPING | RTE_PCI_DRV_INTR_LSC,
     567                 :            :         .probe = eth_vmxnet3_pci_probe,
     568                 :            :         .remove = eth_vmxnet3_pci_remove,
     569                 :            : };
     570                 :            : 
     571                 :            : static void
     572                 :          0 : vmxnet3_alloc_intr_resources(struct rte_eth_dev *dev)
     573                 :            : {
     574                 :          0 :         struct vmxnet3_hw *hw = dev->data->dev_private;
     575                 :            :         uint32_t cfg;
     576                 :            :         int nvec = 1; /* for link event */
     577                 :            : 
     578                 :            :         /* intr settings */
     579                 :          0 :         VMXNET3_WRITE_BAR1_REG(hw, VMXNET3_REG_CMD,
     580                 :            :                                VMXNET3_CMD_GET_CONF_INTR);
     581                 :          0 :         cfg = VMXNET3_READ_BAR1_REG(hw, VMXNET3_REG_CMD);
     582                 :          0 :         hw->intr.type = cfg & 0x3;
     583                 :          0 :         hw->intr.mask_mode = (cfg >> 2) & 0x3;
     584                 :            : 
     585         [ #  # ]:          0 :         if (hw->intr.type == VMXNET3_IT_AUTO)
     586                 :          0 :                 hw->intr.type = VMXNET3_IT_MSIX;
     587                 :            : 
     588         [ #  # ]:          0 :         if (hw->intr.type == VMXNET3_IT_MSIX) {
     589                 :            :                 /* only support shared tx/rx intr */
     590         [ #  # ]:          0 :                 if (hw->num_tx_queues != hw->num_rx_queues)
     591                 :          0 :                         goto msix_err;
     592                 :            : 
     593                 :            :                 nvec += hw->num_rx_queues;
     594                 :          0 :                 hw->intr.num_intrs = nvec;
     595                 :          0 :                 return;
     596                 :            :         }
     597                 :            : 
     598                 :          0 : msix_err:
     599                 :            :         /* the tx/rx queue interrupt will be disabled */
     600                 :          0 :         hw->intr.num_intrs = 2;
     601                 :          0 :         hw->intr.lsc_only = TRUE;
     602                 :          0 :         PMD_INIT_LOG(INFO, "Enabled MSI-X with %d vectors", hw->intr.num_intrs);
     603                 :            : }
     604                 :            : 
     605                 :            : static int
     606                 :          0 : vmxnet3_dev_configure(struct rte_eth_dev *dev)
     607                 :            : {
     608                 :            :         const struct rte_memzone *mz;
     609                 :          0 :         struct vmxnet3_hw *hw = dev->data->dev_private;
     610                 :            :         size_t size;
     611                 :            : 
     612                 :          0 :         PMD_INIT_FUNC_TRACE();
     613                 :            : 
     614         [ #  # ]:          0 :         if (dev->data->dev_conf.rxmode.mq_mode & RTE_ETH_MQ_RX_RSS_FLAG)
     615                 :          0 :                 dev->data->dev_conf.rxmode.offloads |= RTE_ETH_RX_OFFLOAD_RSS_HASH;
     616                 :            : 
     617         [ #  # ]:          0 :         if (!VMXNET3_VERSION_GE_6(hw)) {
     618         [ #  # ]:          0 :                 if (!rte_is_power_of_2(dev->data->nb_rx_queues)) {
     619                 :          0 :                         PMD_INIT_LOG(ERR,
     620                 :            :                                      "ERROR: Number of rx queues not power of 2");
     621                 :          0 :                         return -EINVAL;
     622                 :            :                 }
     623                 :            :         }
     624                 :            : 
     625                 :            :         /* At this point, the number of queues requested has already
     626                 :            :          * been validated against dev_infos max queues by EAL
     627                 :            :          */
     628         [ #  # ]:          0 :         if (dev->data->nb_rx_queues > VMXNET3_MAX_RX_QUEUES ||
     629         [ #  # ]:          0 :             dev->data->nb_tx_queues > VMXNET3_MAX_TX_QUEUES) {
     630                 :          0 :                 hw->queuesExtEnabled = 1;
     631                 :            :         } else {
     632                 :          0 :                 hw->queuesExtEnabled = 0;
     633                 :            :         }
     634                 :            : 
     635                 :          0 :         size = dev->data->nb_rx_queues * sizeof(struct Vmxnet3_TxQueueDesc) +
     636                 :          0 :                 dev->data->nb_tx_queues * sizeof(struct Vmxnet3_RxQueueDesc);
     637                 :            : 
     638         [ #  # ]:          0 :         if (size > UINT16_MAX)
     639                 :            :                 return -EINVAL;
     640                 :            : 
     641                 :          0 :         hw->num_rx_queues = (uint8_t)dev->data->nb_rx_queues;
     642                 :          0 :         hw->num_tx_queues = (uint8_t)dev->data->nb_tx_queues;
     643                 :            : 
     644                 :            :         /*
     645                 :            :          * Allocate a memzone for Vmxnet3_DriverShared - Vmxnet3_DSDevRead
     646                 :            :          * on current socket
     647                 :            :          */
     648                 :          0 :         mz = gpa_zone_reserve(dev, sizeof(struct Vmxnet3_DriverShared),
     649                 :          0 :                               "shared", rte_socket_id(), 8, 1);
     650                 :            : 
     651         [ #  # ]:          0 :         if (mz == NULL) {
     652                 :          0 :                 PMD_INIT_LOG(ERR, "ERROR: Creating shared zone");
     653                 :          0 :                 return -ENOMEM;
     654                 :            :         }
     655                 :          0 :         memset(mz->addr, 0, mz->len);
     656                 :            : 
     657                 :          0 :         hw->shared = mz->addr;
     658                 :          0 :         hw->sharedPA = mz->iova;
     659                 :            : 
     660                 :            :         /*
     661                 :            :          * Allocate a memzone for Vmxnet3_RxQueueDesc - Vmxnet3_TxQueueDesc
     662                 :            :          * on current socket.
     663                 :            :          *
     664                 :            :          * We cannot reuse this memzone from previous allocation as its size
     665                 :            :          * depends on the number of tx and rx queues, which could be different
     666                 :            :          * from one config to another.
     667                 :            :          */
     668                 :          0 :         mz = gpa_zone_reserve(dev, size, "queuedesc", rte_socket_id(),
     669                 :            :                               VMXNET3_QUEUE_DESC_ALIGN, 0);
     670         [ #  # ]:          0 :         if (mz == NULL) {
     671                 :          0 :                 PMD_INIT_LOG(ERR, "ERROR: Creating queue descriptors zone");
     672                 :          0 :                 return -ENOMEM;
     673                 :            :         }
     674         [ #  # ]:          0 :         memset(mz->addr, 0, mz->len);
     675                 :            : 
     676                 :          0 :         hw->tqd_start = (Vmxnet3_TxQueueDesc *)mz->addr;
     677                 :          0 :         hw->rqd_start = (Vmxnet3_RxQueueDesc *)(hw->tqd_start + hw->num_tx_queues);
     678                 :            : 
     679                 :          0 :         hw->queueDescPA = mz->iova;
     680                 :          0 :         hw->queue_desc_len = (uint16_t)size;
     681                 :            : 
     682         [ #  # ]:          0 :         if (dev->data->dev_conf.rxmode.mq_mode == RTE_ETH_MQ_RX_RSS) {
     683                 :            :                 /* Allocate memory structure for UPT1_RSSConf and configure */
     684                 :          0 :                 mz = gpa_zone_reserve(dev, sizeof(struct VMXNET3_RSSConf),
     685                 :          0 :                                       "rss_conf", rte_socket_id(),
     686                 :            :                                       RTE_CACHE_LINE_SIZE, 1);
     687         [ #  # ]:          0 :                 if (mz == NULL) {
     688                 :          0 :                         PMD_INIT_LOG(ERR,
     689                 :            :                                      "ERROR: Creating rss_conf structure zone");
     690                 :          0 :                         return -ENOMEM;
     691                 :            :                 }
     692                 :          0 :                 memset(mz->addr, 0, mz->len);
     693                 :            : 
     694                 :          0 :                 hw->rss_conf = mz->addr;
     695                 :          0 :                 hw->rss_confPA = mz->iova;
     696                 :            :         }
     697                 :            : 
     698                 :          0 :         vmxnet3_alloc_intr_resources(dev);
     699                 :            : 
     700                 :          0 :         return 0;
     701                 :            : }
     702                 :            : 
     703                 :            : static void
     704                 :          0 : vmxnet3_write_mac(struct vmxnet3_hw *hw, const uint8_t *addr)
     705                 :            : {
     706                 :            :         uint32_t val;
     707                 :            : 
     708                 :          0 :         PMD_INIT_LOG(DEBUG,
     709                 :            :                      "Writing MAC Address : " RTE_ETHER_ADDR_PRT_FMT,
     710                 :            :                      addr[0], addr[1], addr[2],
     711                 :            :                      addr[3], addr[4], addr[5]);
     712                 :            : 
     713                 :            :         memcpy(&val, addr, 4);
     714                 :          0 :         VMXNET3_WRITE_BAR1_REG(hw, VMXNET3_REG_MACL, val);
     715                 :            : 
     716                 :            :         memcpy(&val, addr + 4, 2);
     717                 :          0 :         VMXNET3_WRITE_BAR1_REG(hw, VMXNET3_REG_MACH, val);
     718                 :          0 : }
     719                 :            : 
     720                 :            : /*
     721                 :            :  * Configure the hardware to generate MSI-X interrupts.
     722                 :            :  * If setting up MSIx fails, try setting up MSI (only 1 interrupt vector
     723                 :            :  * which will be disabled to allow lsc to work).
     724                 :            :  *
     725                 :            :  * Returns 0 on success and -1 otherwise.
     726                 :            :  */
     727                 :            : static int
     728                 :          0 : vmxnet3_configure_msix(struct rte_eth_dev *dev)
     729                 :            : {
     730                 :          0 :         struct vmxnet3_hw *hw = dev->data->dev_private;
     731                 :          0 :         struct rte_intr_handle *intr_handle = dev->intr_handle;
     732                 :            :         uint16_t intr_vector;
     733                 :            :         int i;
     734                 :            : 
     735                 :          0 :         hw->intr.event_intr_idx = 0;
     736                 :            : 
     737                 :            :         /* only vfio-pci driver can support interrupt mode. */
     738         [ #  # ]:          0 :         if (!rte_intr_cap_multiple(intr_handle) ||
     739         [ #  # ]:          0 :             dev->data->dev_conf.intr_conf.rxq == 0)
     740                 :            :                 return -1;
     741                 :            : 
     742                 :          0 :         intr_vector = dev->data->nb_rx_queues;
     743   [ #  #  #  # ]:          0 :         if (intr_vector > MAX_RX_QUEUES(hw)) {
     744                 :          0 :                 PMD_INIT_LOG(ERR, "At most %d intr queues supported",
     745                 :            :                              MAX_RX_QUEUES(hw));
     746                 :          0 :                 return -ENOTSUP;
     747                 :            :         }
     748                 :            : 
     749         [ #  # ]:          0 :         if (rte_intr_efd_enable(intr_handle, intr_vector)) {
     750                 :          0 :                 PMD_INIT_LOG(ERR, "Failed to enable fastpath event fd");
     751                 :          0 :                 return -1;
     752                 :            :         }
     753                 :            : 
     754         [ #  # ]:          0 :         if (rte_intr_dp_is_en(intr_handle)) {
     755         [ #  # ]:          0 :                 if (rte_intr_vec_list_alloc(intr_handle, "intr_vec",
     756                 :          0 :                                                    dev->data->nb_rx_queues)) {
     757                 :          0 :                         PMD_INIT_LOG(ERR, "Failed to allocate %d Rx queues intr_vec",
     758                 :            :                                         dev->data->nb_rx_queues);
     759                 :          0 :                         rte_intr_efd_disable(intr_handle);
     760                 :          0 :                         return -ENOMEM;
     761                 :            :                 }
     762                 :            :         }
     763                 :            : 
     764         [ #  # ]:          0 :         if (!rte_intr_allow_others(intr_handle) &&
     765         [ #  # ]:          0 :             dev->data->dev_conf.intr_conf.lsc != 0) {
     766                 :          0 :                 PMD_INIT_LOG(ERR, "not enough intr vector to support both Rx interrupt and LSC");
     767                 :          0 :                 rte_intr_vec_list_free(intr_handle);
     768                 :          0 :                 rte_intr_efd_disable(intr_handle);
     769                 :          0 :                 return -1;
     770                 :            :         }
     771                 :            : 
     772                 :            :         /* if we cannot allocate one MSI-X vector per queue, don't enable
     773                 :            :          * interrupt mode.
     774                 :            :          */
     775                 :          0 :         if (hw->intr.num_intrs !=
     776         [ #  # ]:          0 :                                 (rte_intr_nb_efd_get(intr_handle) + 1)) {
     777                 :          0 :                 PMD_INIT_LOG(ERR, "Device configured with %d Rx intr vectors, expecting %d",
     778                 :            :                                 hw->intr.num_intrs,
     779                 :            :                                 rte_intr_nb_efd_get(intr_handle) + 1);
     780                 :          0 :                 rte_intr_vec_list_free(intr_handle);
     781                 :          0 :                 rte_intr_efd_disable(intr_handle);
     782                 :          0 :                 return -1;
     783                 :            :         }
     784                 :            : 
     785         [ #  # ]:          0 :         for (i = 0; i < dev->data->nb_rx_queues; i++)
     786         [ #  # ]:          0 :                 if (rte_intr_vec_list_index_set(intr_handle, i, i + 1))
     787                 :          0 :                         return -rte_errno;
     788                 :            : 
     789         [ #  # ]:          0 :         for (i = 0; i < hw->intr.num_intrs; i++)
     790                 :          0 :                 hw->intr.mod_levels[i] = UPT1_IML_ADAPTIVE;
     791                 :            : 
     792                 :          0 :         PMD_INIT_LOG(INFO, "intr type %u, mode %u, %u vectors allocated",
     793                 :            :                     hw->intr.type, hw->intr.mask_mode, hw->intr.num_intrs);
     794                 :            : 
     795                 :          0 :         return 0;
     796                 :            : }
     797                 :            : 
     798                 :            : static int
     799                 :          0 : vmxnet3_dev_setup_memreg(struct rte_eth_dev *dev)
     800                 :            : {
     801                 :          0 :         struct vmxnet3_hw *hw = dev->data->dev_private;
     802                 :          0 :         Vmxnet3_DriverShared *shared = hw->shared;
     803                 :            :         Vmxnet3_CmdInfo *cmdInfo;
     804                 :            :         struct rte_mempool *mp[VMXNET3_MAX_RX_QUEUES];
     805                 :            :         uint16_t index[VMXNET3_MAX_MEMREG_QUEUES];
     806                 :            :         uint16_t tx_index_mask;
     807                 :            :         uint32_t num, tx_num, i, j, size;
     808                 :            : 
     809         [ #  # ]:          0 :         if (hw->memRegsPA == 0) {
     810                 :            :                 const struct rte_memzone *mz;
     811                 :            : 
     812                 :            :                 size = sizeof(Vmxnet3_MemRegs) +
     813                 :            :                         (2 * VMXNET3_MAX_MEMREG_QUEUES) *
     814                 :            :                         sizeof(Vmxnet3_MemoryRegion);
     815                 :            : 
     816                 :          0 :                 mz = gpa_zone_reserve(dev, size, "memRegs", rte_socket_id(), 8,
     817                 :            :                                       1);
     818         [ #  # ]:          0 :                 if (mz == NULL) {
     819                 :          0 :                         PMD_INIT_LOG(ERR, "ERROR: Creating memRegs zone");
     820                 :          0 :                         return -ENOMEM;
     821                 :            :                 }
     822                 :          0 :                 memset(mz->addr, 0, mz->len);
     823                 :          0 :                 hw->memRegs = mz->addr;
     824                 :          0 :                 hw->memRegsPA = mz->iova;
     825                 :            :         }
     826                 :            : 
     827                 :          0 :         num = RTE_MIN(hw->num_rx_queues, VMXNET3_MAX_MEMREG_QUEUES);
     828                 :          0 :         tx_num = RTE_MIN(hw->num_tx_queues, VMXNET3_MAX_MEMREG_QUEUES);
     829                 :          0 :         tx_index_mask = (uint16_t)((1UL << tx_num) - 1);
     830                 :            : 
     831         [ #  # ]:          0 :         for (i = 0; i < num; i++) {
     832                 :          0 :                 vmxnet3_rx_queue_t *rxq = dev->data->rx_queues[i];
     833                 :            : 
     834                 :          0 :                 mp[i] = rxq->mp;
     835                 :          0 :                 index[i] = 1 << i;
     836                 :            :         }
     837                 :            : 
     838                 :            :         /*
     839                 :            :          * The same mempool could be used by multiple queues. In such a case,
     840                 :            :          * remove duplicate mempool entries. Only one entry is kept with
     841                 :            :          * bitmask indicating queues that are using this mempool.
     842                 :            :          */
     843         [ #  # ]:          0 :         for (i = 1; i < num; i++) {
     844         [ #  # ]:          0 :                 for (j = 0; j < i; j++) {
     845         [ #  # ]:          0 :                         if (mp[i] == mp[j]) {
     846                 :          0 :                                 mp[i] = NULL;
     847                 :          0 :                                 index[j] |= 1 << i;
     848                 :          0 :                                 break;
     849                 :            :                         }
     850                 :            :                 }
     851                 :            :         }
     852                 :            : 
     853                 :            :         j = 0;
     854         [ #  # ]:          0 :         for (i = 0; i < num; i++) {
     855         [ #  # ]:          0 :                 if (mp[i] == NULL)
     856                 :          0 :                         continue;
     857                 :            : 
     858                 :          0 :                 Vmxnet3_MemoryRegion *mr = &hw->memRegs->memRegs[j];
     859                 :            : 
     860                 :          0 :                 mr->startPA =
     861                 :          0 :                         (uintptr_t)STAILQ_FIRST(&mp[i]->mem_list)->iova;
     862                 :          0 :                 mr->length = STAILQ_FIRST(&mp[i]->mem_list)->len <= INT32_MAX ?
     863                 :          0 :                         STAILQ_FIRST(&mp[i]->mem_list)->len : INT32_MAX;
     864                 :          0 :                 mr->rxQueueBits = index[i];
     865                 :            :                 /* tx uses same pool, but there may be fewer tx queues */
     866                 :          0 :                 mr->txQueueBits = index[i] & tx_index_mask;
     867                 :            : 
     868                 :          0 :                 PMD_INIT_LOG(INFO,
     869                 :            :                              "index: %u startPA: %" PRIu64 " length: %u, "
     870                 :            :                              "rxBits: %x, txBits: %x",
     871                 :            :                              j, mr->startPA, mr->length,
     872                 :            :                              mr->rxQueueBits, mr->txQueueBits);
     873                 :          0 :                 j++;
     874                 :            :         }
     875                 :          0 :         hw->memRegs->numRegs = j;
     876                 :          0 :         PMD_INIT_LOG(INFO, "numRegs: %u", j);
     877                 :            : 
     878                 :          0 :         size = sizeof(Vmxnet3_MemRegs) +
     879                 :          0 :                 (j - 1) * sizeof(Vmxnet3_MemoryRegion);
     880                 :            : 
     881                 :            :         cmdInfo = &shared->cu.cmdInfo;
     882                 :          0 :         cmdInfo->varConf.confVer = 1;
     883                 :          0 :         cmdInfo->varConf.confLen = size;
     884                 :          0 :         cmdInfo->varConf.confPA = hw->memRegsPA;
     885                 :            : 
     886                 :          0 :         return 0;
     887                 :            : }
     888                 :            : 
     889                 :            : static int
     890                 :          0 : vmxnet3_setup_driver_shared(struct rte_eth_dev *dev)
     891                 :            : {
     892                 :          0 :         struct rte_eth_conf port_conf = dev->data->dev_conf;
     893                 :          0 :         struct vmxnet3_hw *hw = dev->data->dev_private;
     894                 :          0 :         struct rte_intr_handle *intr_handle = dev->intr_handle;
     895                 :          0 :         uint32_t mtu = dev->data->mtu;
     896                 :          0 :         Vmxnet3_DriverShared *shared = hw->shared;
     897                 :            :         Vmxnet3_DSDevRead *devRead = &shared->devRead;
     898                 :            :         struct Vmxnet3_DSDevReadExt *devReadExt = &shared->devReadExt;
     899                 :          0 :         uint64_t rx_offloads = dev->data->dev_conf.rxmode.offloads;
     900                 :            :         uint32_t i;
     901                 :            :         int ret;
     902                 :            : 
     903                 :          0 :         hw->mtu = mtu;
     904                 :            : 
     905                 :          0 :         shared->magic = VMXNET3_REV1_MAGIC;
     906                 :          0 :         devRead->misc.driverInfo.version = VMXNET3_DRIVER_VERSION_NUM;
     907                 :            : 
     908                 :            :         /* Setting up Guest OS information */
     909                 :          0 :         devRead->misc.driverInfo.gos.gosBits   = sizeof(void *) == 4 ?
     910                 :            :                 VMXNET3_GOS_BITS_32 : VMXNET3_GOS_BITS_64;
     911                 :          0 :         devRead->misc.driverInfo.gos.gosType   = VMXNET3_GOS_TYPE_LINUX;
     912                 :          0 :         devRead->misc.driverInfo.vmxnet3RevSpt = 1;
     913                 :          0 :         devRead->misc.driverInfo.uptVerSpt     = 1;
     914                 :            : 
     915                 :          0 :         devRead->misc.mtu = rte_le_to_cpu_32(mtu);
     916                 :          0 :         devRead->misc.queueDescPA  = hw->queueDescPA;
     917                 :          0 :         devRead->misc.queueDescLen = hw->queue_desc_len;
     918                 :          0 :         devRead->misc.numTxQueues  = hw->num_tx_queues;
     919                 :          0 :         devRead->misc.numRxQueues  = hw->num_rx_queues;
     920                 :            : 
     921         [ #  # ]:          0 :         for (i = 0; i < hw->num_tx_queues; i++) {
     922                 :          0 :                 Vmxnet3_TxQueueDesc *tqd = &hw->tqd_start[i];
     923                 :          0 :                 vmxnet3_tx_queue_t *txq  = dev->data->tx_queues[i];
     924                 :            : 
     925                 :          0 :                 txq->shared = &hw->tqd_start[i];
     926                 :            : 
     927                 :          0 :                 tqd->ctrl.txNumDeferred  = 0;
     928                 :          0 :                 tqd->ctrl.txThreshold    = 1;
     929                 :          0 :                 tqd->conf.txRingBasePA   = txq->cmd_ring.basePA;
     930                 :          0 :                 tqd->conf.compRingBasePA = txq->comp_ring.basePA;
     931                 :          0 :                 tqd->conf.dataRingBasePA = txq->data_ring.basePA;
     932                 :            : 
     933                 :          0 :                 tqd->conf.txRingSize   = txq->cmd_ring.size;
     934                 :          0 :                 tqd->conf.compRingSize = txq->comp_ring.size;
     935                 :          0 :                 tqd->conf.dataRingSize = txq->data_ring.size;
     936                 :          0 :                 tqd->conf.txDataRingDescSize = txq->txdata_desc_size;
     937                 :            : 
     938         [ #  # ]:          0 :                 if (hw->intr.lsc_only)
     939                 :          0 :                         tqd->conf.intrIdx = 1;
     940                 :            :                 else
     941                 :          0 :                         tqd->conf.intrIdx =
     942                 :          0 :                                 rte_intr_vec_list_index_get(intr_handle,
     943                 :            :                                                                    i);
     944                 :          0 :                 tqd->status.stopped = TRUE;
     945                 :          0 :                 tqd->status.error   = 0;
     946                 :          0 :                 memset(&tqd->stats, 0, sizeof(tqd->stats));
     947                 :            :         }
     948                 :            : 
     949         [ #  # ]:          0 :         for (i = 0; i < hw->num_rx_queues; i++) {
     950                 :          0 :                 Vmxnet3_RxQueueDesc *rqd  = &hw->rqd_start[i];
     951                 :          0 :                 vmxnet3_rx_queue_t *rxq   = dev->data->rx_queues[i];
     952                 :            : 
     953                 :          0 :                 rxq->shared = &hw->rqd_start[i];
     954                 :            : 
     955                 :          0 :                 rqd->conf.rxRingBasePA[0] = rxq->cmd_ring[0].basePA;
     956                 :          0 :                 rqd->conf.rxRingBasePA[1] = rxq->cmd_ring[1].basePA;
     957                 :          0 :                 rqd->conf.compRingBasePA  = rxq->comp_ring.basePA;
     958                 :            : 
     959                 :          0 :                 rqd->conf.rxRingSize[0]   = rxq->cmd_ring[0].size;
     960                 :          0 :                 rqd->conf.rxRingSize[1]   = rxq->cmd_ring[1].size;
     961                 :          0 :                 rqd->conf.compRingSize    = rxq->comp_ring.size;
     962                 :            : 
     963         [ #  # ]:          0 :                 if (VMXNET3_VERSION_GE_3(hw)) {
     964                 :          0 :                         rqd->conf.rxDataRingBasePA = rxq->data_ring.basePA;
     965                 :          0 :                         rqd->conf.rxDataRingDescSize = rxq->data_desc_size;
     966                 :            :                 }
     967                 :            : 
     968         [ #  # ]:          0 :                 if (hw->intr.lsc_only)
     969                 :          0 :                         rqd->conf.intrIdx = 1;
     970                 :            :                 else
     971                 :          0 :                         rqd->conf.intrIdx =
     972                 :          0 :                                 rte_intr_vec_list_index_get(intr_handle,
     973                 :            :                                                                    i);
     974                 :          0 :                 rqd->status.stopped = TRUE;
     975                 :          0 :                 rqd->status.error   = 0;
     976                 :          0 :                 memset(&rqd->stats, 0, sizeof(rqd->stats));
     977                 :            :         }
     978                 :            : 
     979                 :            :         /* intr settings */
     980   [ #  #  #  # ]:          0 :         if (VMXNET3_VERSION_GE_6(hw) && hw->queuesExtEnabled) {
     981                 :          0 :                 devReadExt->intrConfExt.autoMask = hw->intr.mask_mode ==
     982                 :            :                                                    VMXNET3_IMM_AUTO;
     983                 :          0 :                 devReadExt->intrConfExt.numIntrs = hw->intr.num_intrs;
     984         [ #  # ]:          0 :                 for (i = 0; i < hw->intr.num_intrs; i++)
     985                 :          0 :                         devReadExt->intrConfExt.modLevels[i] =
     986                 :          0 :                                 hw->intr.mod_levels[i];
     987                 :            : 
     988                 :          0 :                 devReadExt->intrConfExt.eventIntrIdx = hw->intr.event_intr_idx;
     989                 :          0 :                 devReadExt->intrConfExt.intrCtrl |=
     990                 :            :                         rte_cpu_to_le_32(VMXNET3_IC_DISABLE_ALL);
     991                 :            :         } else {
     992                 :          0 :                 devRead->intrConf.autoMask = hw->intr.mask_mode ==
     993                 :            :                                              VMXNET3_IMM_AUTO;
     994                 :          0 :                 devRead->intrConf.numIntrs = hw->intr.num_intrs;
     995         [ #  # ]:          0 :                 for (i = 0; i < hw->intr.num_intrs; i++)
     996                 :          0 :                         devRead->intrConf.modLevels[i] = hw->intr.mod_levels[i];
     997                 :            : 
     998                 :          0 :                 devRead->intrConf.eventIntrIdx = hw->intr.event_intr_idx;
     999                 :          0 :                 devRead->intrConf.intrCtrl |= rte_cpu_to_le_32(VMXNET3_IC_DISABLE_ALL);
    1000                 :            :         }
    1001                 :            : 
    1002                 :            :         /* RxMode set to 0 of VMXNET3_RXM_xxx */
    1003                 :          0 :         devRead->rxFilterConf.rxMode = 0;
    1004                 :            : 
    1005                 :            :         /* Setting up feature flags */
    1006         [ #  # ]:          0 :         if (rx_offloads & RTE_ETH_RX_OFFLOAD_CHECKSUM)
    1007                 :          0 :                 devRead->misc.uptFeatures |= VMXNET3_F_RXCSUM;
    1008                 :            : 
    1009         [ #  # ]:          0 :         if (rx_offloads & RTE_ETH_RX_OFFLOAD_TCP_LRO) {
    1010                 :          0 :                 devRead->misc.uptFeatures |= VMXNET3_F_LRO;
    1011                 :          0 :                 devRead->misc.maxNumRxSG = 0;
    1012                 :            :         }
    1013                 :            : 
    1014         [ #  # ]:          0 :         if (port_conf.rxmode.mq_mode == RTE_ETH_MQ_RX_RSS) {
    1015                 :          0 :                 ret = vmxnet3_rss_configure(dev);
    1016         [ #  # ]:          0 :                 if (ret != VMXNET3_SUCCESS)
    1017                 :            :                         return ret;
    1018                 :            : 
    1019                 :          0 :                 devRead->misc.uptFeatures |= VMXNET3_F_RSS;
    1020                 :          0 :                 devRead->rssConfDesc.confVer = 1;
    1021                 :          0 :                 devRead->rssConfDesc.confLen = sizeof(struct VMXNET3_RSSConf);
    1022                 :          0 :                 devRead->rssConfDesc.confPA  = hw->rss_confPA;
    1023                 :            :         }
    1024                 :            : 
    1025                 :          0 :         ret = vmxnet3_dev_vlan_offload_set(dev,
    1026                 :            :                         RTE_ETH_VLAN_STRIP_MASK | RTE_ETH_VLAN_FILTER_MASK);
    1027         [ #  # ]:          0 :         if (ret)
    1028                 :            :                 return ret;
    1029                 :            : 
    1030                 :          0 :         vmxnet3_write_mac(hw, dev->data->mac_addrs->addr_bytes);
    1031                 :            : 
    1032                 :          0 :         return VMXNET3_SUCCESS;
    1033                 :            : }
    1034                 :            : 
    1035                 :            : static void
    1036                 :            : vmxnet3_init_bufsize(struct vmxnet3_hw *hw)
    1037                 :            : {
    1038                 :          0 :         struct Vmxnet3_DriverShared *shared = hw->shared;
    1039                 :            :         union Vmxnet3_CmdInfo *cmd_info = &shared->cu.cmdInfo;
    1040                 :            : 
    1041         [ #  # ]:          0 :         if (!VMXNET3_VERSION_GE_7(hw))
    1042                 :            :                 return;
    1043                 :            : 
    1044                 :          0 :         cmd_info->ringBufSize.ring1BufSizeType0 = hw->rxdata_buf_size;
    1045                 :          0 :         cmd_info->ringBufSize.ring1BufSizeType1 = 0;
    1046                 :          0 :         cmd_info->ringBufSize.ring2BufSizeType1 = hw->rxdata_buf_size;
    1047                 :          0 :         VMXNET3_WRITE_BAR1_REG(hw, VMXNET3_REG_CMD,
    1048                 :            :                                VMXNET3_CMD_SET_RING_BUFFER_SIZE);
    1049                 :            : }
    1050                 :            : 
    1051                 :            : /*
    1052                 :            :  * Configure device link speed and setup link.
    1053                 :            :  * Must be called after eth_vmxnet3_dev_init. Other wise it might fail
    1054                 :            :  * It returns 0 on success.
    1055                 :            :  */
    1056                 :            : static int
    1057                 :          0 : vmxnet3_dev_start(struct rte_eth_dev *dev)
    1058                 :            : {
    1059                 :            :         int ret;
    1060                 :          0 :         struct vmxnet3_hw *hw = dev->data->dev_private;
    1061                 :            :         uint16_t i;
    1062                 :            : 
    1063                 :          0 :         PMD_INIT_FUNC_TRACE();
    1064                 :            : 
    1065                 :            :         /* Save stats before it is reset by CMD_ACTIVATE */
    1066                 :          0 :         vmxnet3_hw_stats_save(hw);
    1067                 :            : 
    1068                 :            :         /* configure MSI-X */
    1069                 :          0 :         ret = vmxnet3_configure_msix(dev);
    1070         [ #  # ]:          0 :         if (ret < 0) {
    1071                 :            :                 /* revert to lsc only */
    1072                 :          0 :                 hw->intr.num_intrs = 2;
    1073                 :          0 :                 hw->intr.lsc_only = TRUE;
    1074                 :            :         }
    1075                 :            : 
    1076                 :          0 :         ret = vmxnet3_setup_driver_shared(dev);
    1077         [ #  # ]:          0 :         if (ret != VMXNET3_SUCCESS)
    1078                 :            :                 return ret;
    1079                 :            : 
    1080                 :            :         /* Exchange shared data with device */
    1081                 :          0 :         VMXNET3_WRITE_BAR1_REG(hw, VMXNET3_REG_DSAL,
    1082                 :            :                                VMXNET3_GET_ADDR_LO(hw->sharedPA));
    1083                 :          0 :         VMXNET3_WRITE_BAR1_REG(hw, VMXNET3_REG_DSAH,
    1084                 :            :                                VMXNET3_GET_ADDR_HI(hw->sharedPA));
    1085                 :            : 
    1086                 :            :         /* Activate device by register write */
    1087                 :          0 :         VMXNET3_WRITE_BAR1_REG(hw, VMXNET3_REG_CMD, VMXNET3_CMD_ACTIVATE_DEV);
    1088                 :          0 :         ret = VMXNET3_READ_BAR1_REG(hw, VMXNET3_REG_CMD);
    1089                 :            : 
    1090         [ #  # ]:          0 :         if (ret != 0) {
    1091                 :          0 :                 PMD_INIT_LOG(ERR, "Device activation: UNSUCCESSFUL");
    1092                 :          0 :                 return -EINVAL;
    1093                 :            :         }
    1094                 :            : 
    1095                 :            :         /* Check memregs restrictions first */
    1096         [ #  # ]:          0 :         if (dev->data->nb_rx_queues <= VMXNET3_MAX_MEMREG_QUEUES &&
    1097         [ #  # ]:          0 :             dev->data->nb_tx_queues <= VMXNET3_MAX_MEMREG_QUEUES) {
    1098                 :          0 :                 ret = vmxnet3_dev_setup_memreg(dev);
    1099         [ #  # ]:          0 :                 if (ret == 0) {
    1100                 :          0 :                         VMXNET3_WRITE_BAR1_REG(hw, VMXNET3_REG_CMD,
    1101                 :            :                                         VMXNET3_CMD_REGISTER_MEMREGS);
    1102                 :          0 :                         ret = VMXNET3_READ_BAR1_REG(hw, VMXNET3_REG_CMD);
    1103         [ #  # ]:          0 :                         if (ret != 0)
    1104                 :          0 :                                 PMD_INIT_LOG(DEBUG,
    1105                 :            :                                         "Failed in setup memory region cmd");
    1106                 :            :                         ret = 0;
    1107                 :            :                 } else {
    1108                 :          0 :                         PMD_INIT_LOG(DEBUG, "Failed to setup memory region");
    1109                 :            :                 }
    1110                 :            :         } else {
    1111                 :          0 :                 PMD_INIT_LOG(WARNING, "Memregs can't init (rx: %d, tx: %d)",
    1112                 :            :                              dev->data->nb_rx_queues, dev->data->nb_tx_queues);
    1113                 :            :         }
    1114                 :            : 
    1115         [ #  # ]:          0 :         if (VMXNET3_VERSION_GE_4(hw) &&
    1116         [ #  # ]:          0 :             dev->data->dev_conf.rxmode.mq_mode == RTE_ETH_MQ_RX_RSS) {
    1117                 :            :                 /* Check for additional RSS  */
    1118                 :          0 :                 ret = vmxnet3_v4_rss_configure(dev);
    1119         [ #  # ]:          0 :                 if (ret != VMXNET3_SUCCESS) {
    1120                 :          0 :                         PMD_INIT_LOG(ERR, "Failed to configure v4 RSS");
    1121                 :          0 :                         return ret;
    1122                 :            :                 }
    1123                 :            :         }
    1124                 :            : 
    1125                 :            :         /*
    1126                 :            :          * Load RX queues with blank mbufs and update next2fill index for device
    1127                 :            :          * Update RxMode of the device
    1128                 :            :          */
    1129                 :          0 :         ret = vmxnet3_dev_rxtx_init(dev);
    1130         [ #  # ]:          0 :         if (ret != VMXNET3_SUCCESS) {
    1131                 :          0 :                 PMD_INIT_LOG(ERR, "Device queue init: UNSUCCESSFUL");
    1132                 :          0 :                 return ret;
    1133                 :            :         }
    1134                 :            : 
    1135                 :            :         vmxnet3_init_bufsize(hw);
    1136                 :            : 
    1137                 :          0 :         hw->adapter_stopped = FALSE;
    1138                 :            : 
    1139                 :            :         /* Setting proper Rx Mode and issue Rx Mode Update command */
    1140                 :            :         vmxnet3_dev_set_rxmode(hw, VMXNET3_RXM_UCAST | VMXNET3_RXM_BCAST, 1);
    1141                 :            : 
    1142                 :            : #ifndef RTE_EXEC_ENV_FREEBSD
    1143                 :            :         /* Setup interrupt callback  */
    1144                 :          0 :         rte_intr_callback_register(dev->intr_handle,
    1145                 :            :                                    vmxnet3_interrupt_handler, dev);
    1146                 :            : 
    1147         [ #  # ]:          0 :         if (rte_intr_enable(dev->intr_handle) < 0) {
    1148                 :          0 :                 PMD_INIT_LOG(ERR, "interrupt enable failed");
    1149                 :          0 :                 return -EIO;
    1150                 :            :         }
    1151                 :            : 
    1152                 :            :         /* enable all intrs */
    1153                 :          0 :         vmxnet3_enable_all_intrs(hw);
    1154                 :            : #endif
    1155                 :            : 
    1156                 :          0 :         vmxnet3_process_events(dev);
    1157                 :            : 
    1158                 :            :         /*
    1159                 :            :          * Update link state from device since this won't be
    1160                 :            :          * done upon starting with lsc in use. This is done
    1161                 :            :          * only after enabling interrupts to avoid any race
    1162                 :            :          * where the link state could change without an
    1163                 :            :          * interrupt being fired.
    1164                 :            :          */
    1165                 :          0 :         __vmxnet3_dev_link_update(dev, 0);
    1166                 :            : 
    1167         [ #  # ]:          0 :         for (i = 0; i < dev->data->nb_rx_queues; i++)
    1168                 :          0 :                 dev->data->rx_queue_state[i] = RTE_ETH_QUEUE_STATE_STARTED;
    1169         [ #  # ]:          0 :         for (i = 0; i < dev->data->nb_tx_queues; i++)
    1170                 :          0 :                 dev->data->tx_queue_state[i] = RTE_ETH_QUEUE_STATE_STARTED;
    1171                 :            : 
    1172                 :            :         return VMXNET3_SUCCESS;
    1173                 :            : }
    1174                 :            : 
    1175                 :            : /*
    1176                 :            :  * Stop device: disable rx and tx functions to allow for reconfiguring.
    1177                 :            :  */
    1178                 :            : static int
    1179                 :          0 : vmxnet3_dev_stop(struct rte_eth_dev *dev)
    1180                 :            : {
    1181                 :            :         struct rte_eth_link link;
    1182                 :          0 :         struct vmxnet3_hw *hw = dev->data->dev_private;
    1183                 :          0 :         struct rte_intr_handle *intr_handle = dev->intr_handle;
    1184                 :            :         uint16_t i;
    1185                 :            :         int ret;
    1186                 :            : 
    1187                 :          0 :         PMD_INIT_FUNC_TRACE();
    1188                 :            : 
    1189         [ #  # ]:          0 :         if (hw->adapter_stopped == 1) {
    1190                 :          0 :                 PMD_INIT_LOG(DEBUG, "Device already stopped.");
    1191                 :          0 :                 return 0;
    1192                 :            :         }
    1193                 :            : 
    1194                 :            :         do {
    1195                 :            :                 /* Unregister has lock to make sure there is no running cb.
    1196                 :            :                  * This has to happen first since vmxnet3_interrupt_handler
    1197                 :            :                  * reenables interrupts by calling vmxnet3_enable_intr
    1198                 :            :                  */
    1199                 :          0 :                 ret = rte_intr_callback_unregister(intr_handle,
    1200                 :            :                                                    vmxnet3_interrupt_handler,
    1201                 :            :                                                    (void *)-1);
    1202         [ #  # ]:          0 :         } while (ret == -EAGAIN);
    1203                 :            : 
    1204         [ #  # ]:          0 :         if (ret < 0)
    1205                 :          0 :                 PMD_DRV_LOG(ERR, "Error attempting to unregister intr cb: %d",
    1206                 :            :                             ret);
    1207                 :            : 
    1208                 :          0 :         PMD_INIT_LOG(DEBUG, "Disabled %d intr callbacks", ret);
    1209                 :            : 
    1210                 :            :         /* disable interrupts */
    1211                 :          0 :         vmxnet3_disable_all_intrs(hw);
    1212                 :            : 
    1213                 :          0 :         rte_intr_disable(intr_handle);
    1214                 :            : 
    1215                 :            :         /* Clean datapath event and queue/vector mapping */
    1216                 :          0 :         rte_intr_efd_disable(intr_handle);
    1217                 :          0 :         rte_intr_vec_list_free(intr_handle);
    1218                 :            : 
    1219                 :            :         /* quiesce the device first */
    1220                 :          0 :         VMXNET3_WRITE_BAR1_REG(hw, VMXNET3_REG_CMD, VMXNET3_CMD_QUIESCE_DEV);
    1221                 :          0 :         VMXNET3_WRITE_BAR1_REG(hw, VMXNET3_REG_DSAL, 0);
    1222                 :          0 :         VMXNET3_WRITE_BAR1_REG(hw, VMXNET3_REG_DSAH, 0);
    1223                 :            : 
    1224                 :            :         /* reset the device */
    1225                 :          0 :         VMXNET3_WRITE_BAR1_REG(hw, VMXNET3_REG_CMD, VMXNET3_CMD_RESET_DEV);
    1226                 :          0 :         PMD_INIT_LOG(DEBUG, "Device reset.");
    1227                 :            : 
    1228                 :          0 :         vmxnet3_dev_clear_queues(dev);
    1229                 :            : 
    1230                 :            :         /* Clear recorded link status */
    1231                 :            :         memset(&link, 0, sizeof(link));
    1232                 :          0 :         link.link_duplex = RTE_ETH_LINK_FULL_DUPLEX;
    1233                 :          0 :         link.link_speed = RTE_ETH_SPEED_NUM_10G;
    1234                 :            :         link.link_autoneg = RTE_ETH_LINK_FIXED;
    1235                 :          0 :         rte_eth_linkstatus_set(dev, &link);
    1236                 :            : 
    1237                 :          0 :         hw->adapter_stopped = 1;
    1238                 :          0 :         dev->data->dev_started = 0;
    1239                 :            : 
    1240         [ #  # ]:          0 :         for (i = 0; i < dev->data->nb_rx_queues; i++)
    1241                 :          0 :                 dev->data->rx_queue_state[i] = RTE_ETH_QUEUE_STATE_STOPPED;
    1242         [ #  # ]:          0 :         for (i = 0; i < dev->data->nb_tx_queues; i++)
    1243                 :          0 :                 dev->data->tx_queue_state[i] = RTE_ETH_QUEUE_STATE_STOPPED;
    1244                 :            : 
    1245                 :            :         return 0;
    1246                 :            : }
    1247                 :            : 
    1248                 :            : static void
    1249                 :          0 : vmxnet3_free_queues(struct rte_eth_dev *dev)
    1250                 :            : {
    1251                 :            :         int i;
    1252                 :            : 
    1253                 :          0 :         PMD_INIT_FUNC_TRACE();
    1254                 :            : 
    1255         [ #  # ]:          0 :         for (i = 0; i < dev->data->nb_rx_queues; i++)
    1256                 :          0 :                 vmxnet3_dev_rx_queue_release(dev, i);
    1257                 :          0 :         dev->data->nb_rx_queues = 0;
    1258                 :            : 
    1259         [ #  # ]:          0 :         for (i = 0; i < dev->data->nb_tx_queues; i++)
    1260                 :          0 :                 vmxnet3_dev_tx_queue_release(dev, i);
    1261                 :          0 :         dev->data->nb_tx_queues = 0;
    1262                 :          0 : }
    1263                 :            : 
    1264                 :            : /*
    1265                 :            :  * Reset and stop device.
    1266                 :            :  */
    1267                 :            : static int
    1268                 :          0 : vmxnet3_dev_close(struct rte_eth_dev *dev)
    1269                 :            : {
    1270                 :            :         int ret;
    1271                 :          0 :         PMD_INIT_FUNC_TRACE();
    1272         [ #  # ]:          0 :         if (rte_eal_process_type() != RTE_PROC_PRIMARY)
    1273                 :            :                 return 0;
    1274                 :            : 
    1275                 :          0 :         ret = vmxnet3_dev_stop(dev);
    1276                 :          0 :         vmxnet3_free_queues(dev);
    1277                 :            : 
    1278                 :          0 :         return ret;
    1279                 :            : }
    1280                 :            : 
    1281                 :            : static int
    1282                 :          0 : vmxnet3_dev_reset(struct rte_eth_dev *dev)
    1283                 :            : {
    1284                 :            :         int ret;
    1285                 :            : 
    1286                 :          0 :         ret = eth_vmxnet3_dev_uninit(dev);
    1287         [ #  # ]:          0 :         if (ret)
    1288                 :            :                 return ret;
    1289                 :          0 :         ret = eth_vmxnet3_dev_init(dev);
    1290                 :          0 :         return ret;
    1291                 :            : }
    1292                 :            : 
    1293                 :            : static void
    1294                 :          0 : vmxnet3_hw_tx_stats_get(struct vmxnet3_hw *hw, unsigned int q,
    1295                 :            :                         struct UPT1_TxStats *res)
    1296                 :            : {
    1297                 :            : #define VMXNET3_UPDATE_TX_STAT(h, i, f, r)              \
    1298                 :            :                 ((r)->f = (h)->tqd_start[(i)].stats.f +   \
    1299                 :            :                         (h)->saved_tx_stats[(i)].f)
    1300                 :            : 
    1301                 :          0 :         VMXNET3_UPDATE_TX_STAT(hw, q, ucastPktsTxOK, res);
    1302                 :          0 :         VMXNET3_UPDATE_TX_STAT(hw, q, mcastPktsTxOK, res);
    1303                 :          0 :         VMXNET3_UPDATE_TX_STAT(hw, q, bcastPktsTxOK, res);
    1304                 :          0 :         VMXNET3_UPDATE_TX_STAT(hw, q, ucastBytesTxOK, res);
    1305                 :          0 :         VMXNET3_UPDATE_TX_STAT(hw, q, mcastBytesTxOK, res);
    1306                 :          0 :         VMXNET3_UPDATE_TX_STAT(hw, q, bcastBytesTxOK, res);
    1307                 :          0 :         VMXNET3_UPDATE_TX_STAT(hw, q, pktsTxError, res);
    1308                 :          0 :         VMXNET3_UPDATE_TX_STAT(hw, q, pktsTxDiscard, res);
    1309                 :            : 
    1310                 :            : #undef VMXNET3_UPDATE_TX_STAT
    1311                 :          0 : }
    1312                 :            : 
    1313                 :            : static void
    1314                 :          0 : vmxnet3_hw_rx_stats_get(struct vmxnet3_hw *hw, unsigned int q,
    1315                 :            :                         struct UPT1_RxStats *res)
    1316                 :            : {
    1317                 :            : #define VMXNET3_UPDATE_RX_STAT(h, i, f, r)              \
    1318                 :            :                 ((r)->f = (h)->rqd_start[(i)].stats.f +   \
    1319                 :            :                         (h)->saved_rx_stats[(i)].f)
    1320                 :            : 
    1321                 :          0 :         VMXNET3_UPDATE_RX_STAT(hw, q, ucastPktsRxOK, res);
    1322                 :          0 :         VMXNET3_UPDATE_RX_STAT(hw, q, mcastPktsRxOK, res);
    1323                 :          0 :         VMXNET3_UPDATE_RX_STAT(hw, q, bcastPktsRxOK, res);
    1324                 :          0 :         VMXNET3_UPDATE_RX_STAT(hw, q, ucastBytesRxOK, res);
    1325                 :          0 :         VMXNET3_UPDATE_RX_STAT(hw, q, mcastBytesRxOK, res);
    1326                 :          0 :         VMXNET3_UPDATE_RX_STAT(hw, q, bcastBytesRxOK, res);
    1327                 :          0 :         VMXNET3_UPDATE_RX_STAT(hw, q, pktsRxError, res);
    1328                 :          0 :         VMXNET3_UPDATE_RX_STAT(hw, q, pktsRxOutOfBuf, res);
    1329                 :            : 
    1330                 :            : #undef VMXNET3_UPDATE_RX_STAT
    1331                 :          0 : }
    1332                 :            : 
    1333                 :            : static void
    1334                 :          0 : vmxnet3_tx_stats_get(struct vmxnet3_hw *hw, unsigned int q,
    1335                 :            :                                         struct UPT1_TxStats *res)
    1336                 :            : {
    1337                 :          0 :                 vmxnet3_hw_tx_stats_get(hw, q, res);
    1338                 :            : 
    1339                 :            : #define VMXNET3_REDUCE_SNAPSHOT_TX_STAT(h, i, f, r)     \
    1340                 :            :                 ((r)->f -= (h)->snapshot_tx_stats[(i)].f)
    1341                 :            : 
    1342                 :          0 :         VMXNET3_REDUCE_SNAPSHOT_TX_STAT(hw, q, ucastPktsTxOK, res);
    1343                 :          0 :         VMXNET3_REDUCE_SNAPSHOT_TX_STAT(hw, q, mcastPktsTxOK, res);
    1344                 :          0 :         VMXNET3_REDUCE_SNAPSHOT_TX_STAT(hw, q, bcastPktsTxOK, res);
    1345                 :          0 :         VMXNET3_REDUCE_SNAPSHOT_TX_STAT(hw, q, ucastBytesTxOK, res);
    1346                 :          0 :         VMXNET3_REDUCE_SNAPSHOT_TX_STAT(hw, q, mcastBytesTxOK, res);
    1347                 :          0 :         VMXNET3_REDUCE_SNAPSHOT_TX_STAT(hw, q, bcastBytesTxOK, res);
    1348                 :          0 :         VMXNET3_REDUCE_SNAPSHOT_TX_STAT(hw, q, pktsTxError, res);
    1349                 :          0 :         VMXNET3_REDUCE_SNAPSHOT_TX_STAT(hw, q, pktsTxDiscard, res);
    1350                 :            : 
    1351                 :            : #undef VMXNET3_REDUCE_SNAPSHOT_TX_STAT
    1352                 :          0 : }
    1353                 :            : 
    1354                 :            : static void
    1355                 :          0 : vmxnet3_rx_stats_get(struct vmxnet3_hw *hw, unsigned int q,
    1356                 :            :                                         struct UPT1_RxStats *res)
    1357                 :            : {
    1358                 :          0 :                 vmxnet3_hw_rx_stats_get(hw, q, res);
    1359                 :            : 
    1360                 :            : #define VMXNET3_REDUCE_SNAPSHOT_RX_STAT(h, i, f, r)     \
    1361                 :            :                 ((r)->f -= (h)->snapshot_rx_stats[(i)].f)
    1362                 :            : 
    1363                 :          0 :         VMXNET3_REDUCE_SNAPSHOT_RX_STAT(hw, q, ucastPktsRxOK, res);
    1364                 :          0 :         VMXNET3_REDUCE_SNAPSHOT_RX_STAT(hw, q, mcastPktsRxOK, res);
    1365                 :          0 :         VMXNET3_REDUCE_SNAPSHOT_RX_STAT(hw, q, bcastPktsRxOK, res);
    1366                 :          0 :         VMXNET3_REDUCE_SNAPSHOT_RX_STAT(hw, q, ucastBytesRxOK, res);
    1367                 :          0 :         VMXNET3_REDUCE_SNAPSHOT_RX_STAT(hw, q, mcastBytesRxOK, res);
    1368                 :          0 :         VMXNET3_REDUCE_SNAPSHOT_RX_STAT(hw, q, bcastBytesRxOK, res);
    1369                 :          0 :         VMXNET3_REDUCE_SNAPSHOT_RX_STAT(hw, q, pktsRxError, res);
    1370                 :          0 :         VMXNET3_REDUCE_SNAPSHOT_RX_STAT(hw, q, pktsRxOutOfBuf, res);
    1371                 :            : 
    1372                 :            : #undef VMXNET3_REDUCE_SNAPSHOT_RX_STAT
    1373                 :          0 : }
    1374                 :            : 
    1375                 :            : static void
    1376                 :          0 : vmxnet3_hw_stats_save(struct vmxnet3_hw *hw)
    1377                 :            : {
    1378                 :            :         unsigned int i;
    1379                 :            : 
    1380                 :          0 :         VMXNET3_WRITE_BAR1_REG(hw, VMXNET3_REG_CMD, VMXNET3_CMD_GET_STATS);
    1381                 :            : 
    1382         [ #  # ]:          0 :         for (i = 0; i < hw->num_tx_queues; i++)
    1383                 :          0 :                 vmxnet3_hw_tx_stats_get(hw, i, &hw->saved_tx_stats[i]);
    1384         [ #  # ]:          0 :         for (i = 0; i < hw->num_rx_queues; i++)
    1385                 :          0 :                 vmxnet3_hw_rx_stats_get(hw, i, &hw->saved_rx_stats[i]);
    1386                 :          0 : }
    1387                 :            : 
    1388                 :            : static int
    1389                 :          0 : vmxnet3_dev_xstats_get_names(struct rte_eth_dev *dev,
    1390                 :            :                              struct rte_eth_xstat_name *xstats_names,
    1391                 :            :                              unsigned int n)
    1392                 :            : {
    1393                 :            :         unsigned int i, t, count = 0;
    1394                 :          0 :         unsigned int nstats =
    1395                 :          0 :                 dev->data->nb_tx_queues * RTE_DIM(vmxnet3_txq_stat_strings) +
    1396                 :          0 :                 dev->data->nb_rx_queues * RTE_DIM(vmxnet3_rxq_stat_strings);
    1397                 :            : 
    1398         [ #  # ]:          0 :         if (!xstats_names || n < nstats)
    1399                 :          0 :                 return nstats;
    1400                 :            : 
    1401         [ #  # ]:          0 :         for (i = 0; i < dev->data->nb_rx_queues; i++) {
    1402         [ #  # ]:          0 :                 if (!dev->data->rx_queues[i])
    1403                 :          0 :                         continue;
    1404                 :            : 
    1405         [ #  # ]:          0 :                 for (t = 0; t < RTE_DIM(vmxnet3_rxq_stat_strings); t++) {
    1406                 :          0 :                         snprintf(xstats_names[count].name,
    1407                 :            :                                  sizeof(xstats_names[count].name),
    1408                 :            :                                  "rx_q%u_%s", i,
    1409                 :          0 :                                  vmxnet3_rxq_stat_strings[t].name);
    1410                 :          0 :                         count++;
    1411                 :            :                 }
    1412                 :            :         }
    1413                 :            : 
    1414         [ #  # ]:          0 :         for (i = 0; i < dev->data->nb_tx_queues; i++) {
    1415         [ #  # ]:          0 :                 if (!dev->data->tx_queues[i])
    1416                 :          0 :                         continue;
    1417                 :            : 
    1418         [ #  # ]:          0 :                 for (t = 0; t < RTE_DIM(vmxnet3_txq_stat_strings); t++) {
    1419                 :          0 :                         snprintf(xstats_names[count].name,
    1420                 :            :                                  sizeof(xstats_names[count].name),
    1421                 :            :                                  "tx_q%u_%s", i,
    1422                 :          0 :                                  vmxnet3_txq_stat_strings[t].name);
    1423                 :          0 :                         count++;
    1424                 :            :                 }
    1425                 :            :         }
    1426                 :            : 
    1427                 :          0 :         return count;
    1428                 :            : }
    1429                 :            : 
    1430                 :            : static int
    1431                 :          0 : vmxnet3_dev_xstats_get(struct rte_eth_dev *dev, struct rte_eth_xstat *xstats,
    1432                 :            :                        unsigned int n)
    1433                 :            : {
    1434                 :            :         unsigned int i, t, count = 0;
    1435                 :          0 :         unsigned int nstats =
    1436                 :          0 :                 dev->data->nb_tx_queues * RTE_DIM(vmxnet3_txq_stat_strings) +
    1437                 :          0 :                 dev->data->nb_rx_queues * RTE_DIM(vmxnet3_rxq_stat_strings);
    1438                 :            : 
    1439         [ #  # ]:          0 :         if (n < nstats)
    1440                 :          0 :                 return nstats;
    1441                 :            : 
    1442         [ #  # ]:          0 :         for (i = 0; i < dev->data->nb_rx_queues; i++) {
    1443                 :          0 :                 struct vmxnet3_rx_queue *rxq = dev->data->rx_queues[i];
    1444                 :            : 
    1445         [ #  # ]:          0 :                 if (rxq == NULL)
    1446                 :          0 :                         continue;
    1447                 :            : 
    1448         [ #  # ]:          0 :                 for (t = 0; t < RTE_DIM(vmxnet3_rxq_stat_strings); t++) {
    1449                 :          0 :                         xstats[count].value = *(uint64_t *)(((char *)&rxq->stats) +
    1450                 :          0 :                                 vmxnet3_rxq_stat_strings[t].offset);
    1451                 :          0 :                         xstats[count].id = count;
    1452                 :          0 :                         count++;
    1453                 :            :                 }
    1454                 :            :         }
    1455                 :            : 
    1456         [ #  # ]:          0 :         for (i = 0; i < dev->data->nb_tx_queues; i++) {
    1457                 :          0 :                 struct vmxnet3_tx_queue *txq = dev->data->tx_queues[i];
    1458                 :            : 
    1459         [ #  # ]:          0 :                 if (txq == NULL)
    1460                 :          0 :                         continue;
    1461                 :            : 
    1462         [ #  # ]:          0 :                 for (t = 0; t < RTE_DIM(vmxnet3_txq_stat_strings); t++) {
    1463                 :          0 :                         xstats[count].value = *(uint64_t *)(((char *)&txq->stats) +
    1464                 :          0 :                                 vmxnet3_txq_stat_strings[t].offset);
    1465                 :          0 :                         xstats[count].id = count;
    1466                 :          0 :                         count++;
    1467                 :            :                 }
    1468                 :            :         }
    1469                 :            : 
    1470                 :          0 :         return count;
    1471                 :            : }
    1472                 :            : 
    1473                 :            : static int
    1474                 :          0 : vmxnet3_dev_stats_get(struct rte_eth_dev *dev, struct rte_eth_stats *stats,
    1475                 :            :                 struct eth_queue_stats *qstats)
    1476                 :            : {
    1477                 :            :         unsigned int i;
    1478                 :          0 :         struct vmxnet3_hw *hw = dev->data->dev_private;
    1479                 :            :         struct UPT1_TxStats txStats;
    1480                 :            :         struct UPT1_RxStats rxStats;
    1481                 :            :         uint64_t packets, bytes;
    1482                 :            : 
    1483                 :          0 :         VMXNET3_WRITE_BAR1_REG(hw, VMXNET3_REG_CMD, VMXNET3_CMD_GET_STATS);
    1484                 :            : 
    1485         [ #  # ]:          0 :         for (i = 0; i < hw->num_tx_queues; i++) {
    1486                 :          0 :                 vmxnet3_tx_stats_get(hw, i, &txStats);
    1487                 :            : 
    1488                 :          0 :                 packets = txStats.ucastPktsTxOK +
    1489                 :          0 :                         txStats.mcastPktsTxOK +
    1490                 :          0 :                         txStats.bcastPktsTxOK;
    1491                 :            : 
    1492                 :          0 :                 bytes = txStats.ucastBytesTxOK +
    1493                 :          0 :                         txStats.mcastBytesTxOK +
    1494                 :          0 :                         txStats.bcastBytesTxOK;
    1495                 :            : 
    1496                 :          0 :                 stats->opackets += packets;
    1497                 :          0 :                 stats->obytes += bytes;
    1498                 :          0 :                 stats->oerrors += txStats.pktsTxError + txStats.pktsTxDiscard;
    1499                 :            : 
    1500         [ #  # ]:          0 :                 if (qstats != NULL && i < RTE_ETHDEV_QUEUE_STAT_CNTRS) {
    1501                 :          0 :                         qstats->q_opackets[i] = packets;
    1502                 :          0 :                         qstats->q_obytes[i] = bytes;
    1503                 :            :                 }
    1504                 :            :         }
    1505                 :            : 
    1506         [ #  # ]:          0 :         for (i = 0; i < hw->num_rx_queues; i++) {
    1507                 :          0 :                 vmxnet3_rx_stats_get(hw, i, &rxStats);
    1508                 :            : 
    1509                 :          0 :                 packets = rxStats.ucastPktsRxOK +
    1510                 :          0 :                         rxStats.mcastPktsRxOK +
    1511                 :          0 :                         rxStats.bcastPktsRxOK;
    1512                 :            : 
    1513                 :          0 :                 bytes = rxStats.ucastBytesRxOK +
    1514                 :          0 :                         rxStats.mcastBytesRxOK +
    1515                 :          0 :                         rxStats.bcastBytesRxOK;
    1516                 :            : 
    1517                 :          0 :                 stats->ipackets += packets;
    1518                 :          0 :                 stats->ibytes += bytes;
    1519                 :          0 :                 stats->ierrors += rxStats.pktsRxError;
    1520                 :          0 :                 stats->imissed += rxStats.pktsRxOutOfBuf;
    1521                 :            : 
    1522         [ #  # ]:          0 :                 if (qstats != NULL && i < RTE_ETHDEV_QUEUE_STAT_CNTRS) {
    1523                 :          0 :                         qstats->q_ipackets[i] = packets;
    1524                 :          0 :                         qstats->q_ibytes[i] = bytes;
    1525                 :          0 :                         qstats->q_errors[i] = rxStats.pktsRxError;
    1526                 :            :                 }
    1527                 :            :         }
    1528                 :            : 
    1529                 :          0 :         return 0;
    1530                 :            : }
    1531                 :            : 
    1532                 :            : static int
    1533                 :          0 : vmxnet3_dev_stats_reset(struct rte_eth_dev *dev)
    1534                 :            : {
    1535                 :            :         unsigned int i;
    1536                 :          0 :         struct vmxnet3_hw *hw = dev->data->dev_private;
    1537                 :          0 :         struct UPT1_TxStats txStats = {0};
    1538                 :          0 :         struct UPT1_RxStats rxStats = {0};
    1539                 :            : 
    1540                 :          0 :         VMXNET3_WRITE_BAR1_REG(hw, VMXNET3_REG_CMD, VMXNET3_CMD_GET_STATS);
    1541                 :            : 
    1542         [ #  # ]:          0 :         for (i = 0; i < hw->num_tx_queues; i++) {
    1543                 :          0 :                 vmxnet3_hw_tx_stats_get(hw, i, &txStats);
    1544                 :          0 :                 memcpy(&hw->snapshot_tx_stats[i], &txStats,
    1545                 :            :                         sizeof(hw->snapshot_tx_stats[0]));
    1546                 :            :         }
    1547         [ #  # ]:          0 :         for (i = 0; i < hw->num_rx_queues; i++) {
    1548                 :          0 :                 vmxnet3_hw_rx_stats_get(hw, i, &rxStats);
    1549                 :          0 :                 memcpy(&hw->snapshot_rx_stats[i], &rxStats,
    1550                 :            :                         sizeof(hw->snapshot_rx_stats[0]));
    1551                 :            :         }
    1552                 :            : 
    1553                 :          0 :         return 0;
    1554                 :            : }
    1555                 :            : 
    1556                 :            : static int
    1557                 :          0 : vmxnet3_dev_info_get(struct rte_eth_dev *dev,
    1558                 :            :                      struct rte_eth_dev_info *dev_info)
    1559                 :            : {
    1560                 :          0 :         struct vmxnet3_hw *hw = dev->data->dev_private;
    1561                 :            :         int queues = 0;
    1562                 :            : 
    1563         [ #  # ]:          0 :         if (VMXNET3_VERSION_GE_6(hw)) {
    1564                 :          0 :                 VMXNET3_WRITE_BAR1_REG(hw, VMXNET3_REG_CMD,
    1565                 :            :                                        VMXNET3_CMD_GET_MAX_QUEUES_CONF);
    1566                 :          0 :                 queues = VMXNET3_READ_BAR1_REG(hw, VMXNET3_REG_CMD);
    1567                 :            : 
    1568         [ #  # ]:          0 :                 if (queues > 0) {
    1569                 :          0 :                         dev_info->max_rx_queues =
    1570                 :          0 :                           RTE_MIN(VMXNET3_EXT_MAX_RX_QUEUES, ((queues >> 8) & 0xff));
    1571                 :          0 :                         dev_info->max_tx_queues =
    1572                 :          0 :                           RTE_MIN(VMXNET3_EXT_MAX_TX_QUEUES, (queues & 0xff));
    1573                 :            :                 } else {
    1574                 :          0 :                         dev_info->max_rx_queues = VMXNET3_MAX_RX_QUEUES;
    1575                 :          0 :                         dev_info->max_tx_queues = VMXNET3_MAX_TX_QUEUES;
    1576                 :            :                 }
    1577                 :            :         } else {
    1578                 :          0 :                 dev_info->max_rx_queues = VMXNET3_MAX_RX_QUEUES;
    1579                 :          0 :                 dev_info->max_tx_queues = VMXNET3_MAX_TX_QUEUES;
    1580                 :            :         }
    1581                 :            : 
    1582                 :          0 :         dev_info->min_rx_bufsize = 1518 + RTE_PKTMBUF_HEADROOM;
    1583                 :          0 :         dev_info->max_rx_pktlen = 16384; /* includes CRC, cf MAXFRS register */
    1584                 :          0 :         dev_info->min_mtu = VMXNET3_MIN_MTU;
    1585         [ #  # ]:          0 :         dev_info->max_mtu = VMXNET3_VERSION_GE_6(hw) ? VMXNET3_V6_MAX_MTU : VMXNET3_MAX_MTU;
    1586                 :          0 :         dev_info->speed_capa = RTE_ETH_LINK_SPEED_10G;
    1587                 :          0 :         dev_info->max_mac_addrs = VMXNET3_MAX_MAC_ADDRS;
    1588                 :            : 
    1589                 :          0 :         dev_info->flow_type_rss_offloads = VMXNET3_RSS_OFFLOAD_ALL;
    1590                 :            : 
    1591         [ #  # ]:          0 :         if (VMXNET3_VERSION_GE_4(hw)) {
    1592                 :          0 :                 dev_info->flow_type_rss_offloads |= VMXNET3_V4_RSS_MASK;
    1593                 :            :         }
    1594                 :            : 
    1595                 :          0 :         dev_info->rx_desc_lim = (struct rte_eth_desc_lim) {
    1596                 :            :                 .nb_max = VMXNET3_RX_RING_MAX_SIZE,
    1597                 :            :                 .nb_min = VMXNET3_DEF_RX_RING_SIZE,
    1598                 :            :                 .nb_align = 1,
    1599                 :            :         };
    1600                 :            : 
    1601                 :          0 :         dev_info->tx_desc_lim = (struct rte_eth_desc_lim) {
    1602                 :            :                 .nb_max = VMXNET3_TX_RING_MAX_SIZE,
    1603                 :            :                 .nb_min = VMXNET3_DEF_TX_RING_SIZE,
    1604                 :            :                 .nb_align = 1,
    1605                 :            :                 .nb_seg_max = VMXNET3_TX_MAX_SEG,
    1606                 :            :                 .nb_mtu_seg_max = VMXNET3_MAX_TXD_PER_PKT,
    1607                 :            :         };
    1608                 :            : 
    1609                 :          0 :         dev_info->rx_offload_capa = VMXNET3_RX_OFFLOAD_CAP;
    1610                 :          0 :         dev_info->rx_queue_offload_capa = 0;
    1611                 :          0 :         dev_info->tx_offload_capa = VMXNET3_TX_OFFLOAD_CAP;
    1612                 :          0 :         dev_info->tx_queue_offload_capa = 0;
    1613         [ #  # ]:          0 :         if (hw->rss_conf == NULL) {
    1614                 :            :                 /* RSS not configured */
    1615                 :          0 :                 dev_info->reta_size = 0;
    1616                 :            :         } else {
    1617                 :          0 :                 dev_info->reta_size = hw->rss_conf->indTableSize;
    1618                 :            :         }
    1619                 :          0 :         return 0;
    1620                 :            : }
    1621                 :            : 
    1622                 :            : static int
    1623                 :          0 : vmxnet3_hw_ver_get(struct rte_eth_dev *dev,
    1624                 :            :                    char *fw_version, size_t fw_size)
    1625                 :            : {
    1626                 :            :         int ret;
    1627                 :          0 :         struct vmxnet3_hw *hw = dev->data->dev_private;
    1628                 :            : 
    1629         [ #  # ]:          0 :         ret = snprintf(fw_version, fw_size, "v%d", hw->version);
    1630                 :            : 
    1631                 :          0 :         ret += 1; /* add the size of '\0' */
    1632         [ #  # ]:          0 :         if (fw_size < (uint32_t)ret)
    1633                 :            :                 return ret;
    1634                 :            :         else
    1635                 :          0 :                 return 0;
    1636                 :            : }
    1637                 :            : 
    1638                 :            : static const uint32_t *
    1639                 :          0 : vmxnet3_dev_supported_ptypes_get(struct rte_eth_dev *dev,
    1640                 :            :                                  size_t *no_of_elements)
    1641                 :            : {
    1642                 :            :         static const uint32_t ptypes[] = {
    1643                 :            :                 RTE_PTYPE_L3_IPV4_EXT,
    1644                 :            :                 RTE_PTYPE_L3_IPV4,
    1645                 :            :         };
    1646                 :            : 
    1647         [ #  # ]:          0 :         if (dev->rx_pkt_burst == vmxnet3_recv_pkts) {
    1648                 :          0 :                 *no_of_elements = RTE_DIM(ptypes);
    1649                 :          0 :                 return ptypes;
    1650                 :            :         }
    1651                 :            :         return NULL;
    1652                 :            : }
    1653                 :            : 
    1654                 :            : static int
    1655                 :          0 : vmxnet3_mac_addr_set(struct rte_eth_dev *dev, struct rte_ether_addr *mac_addr)
    1656                 :            : {
    1657                 :          0 :         struct vmxnet3_hw *hw = dev->data->dev_private;
    1658                 :            : 
    1659                 :            :         rte_ether_addr_copy(mac_addr, (struct rte_ether_addr *)(hw->perm_addr));
    1660                 :          0 :         vmxnet3_write_mac(hw, mac_addr->addr_bytes);
    1661                 :          0 :         return 0;
    1662                 :            : }
    1663                 :            : 
    1664                 :            : static int
    1665                 :          0 : vmxnet3_dev_mtu_set(struct rte_eth_dev *dev, uint16_t mtu)
    1666                 :            : {
    1667                 :          0 :         struct vmxnet3_hw *hw = dev->data->dev_private;
    1668                 :          0 :         uint32_t frame_size = mtu + RTE_ETHER_HDR_LEN + RTE_ETHER_CRC_LEN + 4;
    1669                 :            : 
    1670         [ #  # ]:          0 :         if (mtu < VMXNET3_MIN_MTU)
    1671                 :            :                 return -EINVAL;
    1672                 :            : 
    1673         [ #  # ]:          0 :         if (VMXNET3_VERSION_GE_6(hw)) {
    1674         [ #  # ]:          0 :                 if (mtu > VMXNET3_V6_MAX_MTU)
    1675                 :            :                         return -EINVAL;
    1676                 :            :         } else {
    1677         [ #  # ]:          0 :                 if (mtu > VMXNET3_MAX_MTU) {
    1678                 :          0 :                         PMD_DRV_LOG(ERR, "MTU %d too large in device version v%d",
    1679                 :            :                                     mtu, hw->version);
    1680                 :          0 :                         return -EINVAL;
    1681                 :            :                 }
    1682                 :            :         }
    1683                 :            : 
    1684                 :          0 :         dev->data->mtu = mtu;
    1685                 :            :         /* update max frame size */
    1686                 :          0 :         dev->data->dev_conf.rxmode.mtu = frame_size;
    1687                 :            : 
    1688         [ #  # ]:          0 :         if (dev->data->dev_started == 0)
    1689                 :            :                 return 0;
    1690                 :            : 
    1691                 :            :     /* changing mtu for vmxnet3 pmd does not require a restart
    1692                 :            :      * as it does not need to repopulate the rx rings to support
    1693                 :            :      * different mtu size.  We stop and restart the device here
    1694                 :            :      * just to pass the mtu info to the backend.
    1695                 :            :      */
    1696                 :          0 :         vmxnet3_dev_stop(dev);
    1697                 :          0 :         vmxnet3_dev_start(dev);
    1698                 :            : 
    1699                 :          0 :         return 0;
    1700                 :            : }
    1701                 :            : 
    1702                 :            : /* return 0 means link status changed, -1 means not changed */
    1703                 :            : static int
    1704                 :          0 : __vmxnet3_dev_link_update(struct rte_eth_dev *dev,
    1705                 :            :                           __rte_unused int wait_to_complete)
    1706                 :            : {
    1707                 :          0 :         struct vmxnet3_hw *hw = dev->data->dev_private;
    1708                 :            :         struct rte_eth_link link;
    1709                 :            :         uint32_t ret;
    1710                 :            : 
    1711                 :            :         memset(&link, 0, sizeof(link));
    1712                 :            : 
    1713                 :          0 :         VMXNET3_WRITE_BAR1_REG(hw, VMXNET3_REG_CMD, VMXNET3_CMD_GET_LINK);
    1714                 :          0 :         ret = VMXNET3_READ_BAR1_REG(hw, VMXNET3_REG_CMD);
    1715                 :            : 
    1716         [ #  # ]:          0 :         if (ret & 0x1)
    1717                 :          0 :                 link.link_status = RTE_ETH_LINK_UP;
    1718                 :          0 :         link.link_duplex = RTE_ETH_LINK_FULL_DUPLEX;
    1719                 :          0 :         link.link_speed = RTE_ETH_SPEED_NUM_10G;
    1720         [ #  # ]:          0 :         link.link_autoneg = RTE_ETH_LINK_FIXED;
    1721                 :            : 
    1722                 :          0 :         return rte_eth_linkstatus_set(dev, &link);
    1723                 :            : }
    1724                 :            : 
    1725                 :            : static int
    1726                 :          0 : vmxnet3_dev_link_update(struct rte_eth_dev *dev, int wait_to_complete)
    1727                 :            : {
    1728                 :            :         /* Link status doesn't change for stopped dev */
    1729   [ #  #  #  # ]:          0 :         if (dev->data->dev_started == 0)
    1730                 :            :                 return -1;
    1731                 :            : 
    1732                 :          0 :         return __vmxnet3_dev_link_update(dev, wait_to_complete);
    1733                 :            : }
    1734                 :            : 
    1735                 :            : /* Updating rxmode through Vmxnet3_DriverShared structure in adapter */
    1736                 :            : static void
    1737                 :            : vmxnet3_dev_set_rxmode(struct vmxnet3_hw *hw, uint32_t feature, int set)
    1738                 :            : {
    1739                 :          0 :         struct Vmxnet3_RxFilterConf *rxConf = &hw->shared->devRead.rxFilterConf;
    1740                 :            : 
    1741                 :            :         if (set)
    1742                 :          0 :                 rxConf->rxMode = rxConf->rxMode | feature;
    1743                 :            :         else
    1744                 :          0 :                 rxConf->rxMode = rxConf->rxMode & (~feature);
    1745                 :            : 
    1746                 :          0 :         VMXNET3_WRITE_BAR1_REG(hw, VMXNET3_REG_CMD, VMXNET3_CMD_UPDATE_RX_MODE);
    1747                 :            : }
    1748                 :            : 
    1749                 :            : /* Promiscuous supported only if Vmxnet3_DriverShared is initialized in adapter */
    1750                 :            : static int
    1751                 :          0 : vmxnet3_dev_promiscuous_enable(struct rte_eth_dev *dev)
    1752                 :            : {
    1753                 :          0 :         struct vmxnet3_hw *hw = dev->data->dev_private;
    1754                 :          0 :         uint32_t *vf_table = hw->shared->devRead.rxFilterConf.vfTable;
    1755                 :            : 
    1756                 :            :         memset(vf_table, 0, VMXNET3_VFT_TABLE_SIZE);
    1757                 :            :         vmxnet3_dev_set_rxmode(hw, VMXNET3_RXM_PROMISC, 1);
    1758                 :            : 
    1759                 :          0 :         VMXNET3_WRITE_BAR1_REG(hw, VMXNET3_REG_CMD,
    1760                 :            :                                VMXNET3_CMD_UPDATE_VLAN_FILTERS);
    1761                 :            : 
    1762                 :          0 :         return 0;
    1763                 :            : }
    1764                 :            : 
    1765                 :            : /* Promiscuous supported only if Vmxnet3_DriverShared is initialized in adapter */
    1766                 :            : static int
    1767                 :          0 : vmxnet3_dev_promiscuous_disable(struct rte_eth_dev *dev)
    1768                 :            : {
    1769                 :          0 :         struct vmxnet3_hw *hw = dev->data->dev_private;
    1770                 :          0 :         uint32_t *vf_table = hw->shared->devRead.rxFilterConf.vfTable;
    1771                 :          0 :         uint64_t rx_offloads = dev->data->dev_conf.rxmode.offloads;
    1772                 :            : 
    1773         [ #  # ]:          0 :         if (rx_offloads & RTE_ETH_RX_OFFLOAD_VLAN_FILTER)
    1774                 :          0 :                 memcpy(vf_table, hw->shadow_vfta, VMXNET3_VFT_TABLE_SIZE);
    1775                 :            :         else
    1776                 :            :                 memset(vf_table, 0xff, VMXNET3_VFT_TABLE_SIZE);
    1777                 :            :         vmxnet3_dev_set_rxmode(hw, VMXNET3_RXM_PROMISC, 0);
    1778                 :          0 :         VMXNET3_WRITE_BAR1_REG(hw, VMXNET3_REG_CMD,
    1779                 :            :                                VMXNET3_CMD_UPDATE_VLAN_FILTERS);
    1780                 :            : 
    1781                 :          0 :         return 0;
    1782                 :            : }
    1783                 :            : 
    1784                 :            : /* Allmulticast supported only if Vmxnet3_DriverShared is initialized in adapter */
    1785                 :            : static int
    1786                 :          0 : vmxnet3_dev_allmulticast_enable(struct rte_eth_dev *dev)
    1787                 :            : {
    1788                 :          0 :         struct vmxnet3_hw *hw = dev->data->dev_private;
    1789                 :            : 
    1790                 :            :         vmxnet3_dev_set_rxmode(hw, VMXNET3_RXM_ALL_MULTI, 1);
    1791                 :            : 
    1792                 :          0 :         return 0;
    1793                 :            : }
    1794                 :            : 
    1795                 :            : /* Allmulticast supported only if Vmxnet3_DriverShared is initialized in adapter */
    1796                 :            : static int
    1797                 :          0 : vmxnet3_dev_allmulticast_disable(struct rte_eth_dev *dev)
    1798                 :            : {
    1799                 :          0 :         struct vmxnet3_hw *hw = dev->data->dev_private;
    1800                 :            : 
    1801                 :            :         vmxnet3_dev_set_rxmode(hw, VMXNET3_RXM_ALL_MULTI, 0);
    1802                 :            : 
    1803                 :          0 :         return 0;
    1804                 :            : }
    1805                 :            : 
    1806                 :            : /* Enable/disable filter on vlan */
    1807                 :            : static int
    1808                 :          0 : vmxnet3_dev_vlan_filter_set(struct rte_eth_dev *dev, uint16_t vid, int on)
    1809                 :            : {
    1810                 :          0 :         struct vmxnet3_hw *hw = dev->data->dev_private;
    1811                 :          0 :         struct Vmxnet3_RxFilterConf *rxConf = &hw->shared->devRead.rxFilterConf;
    1812                 :          0 :         uint32_t *vf_table = rxConf->vfTable;
    1813                 :            : 
    1814                 :            :         /* save state for restore */
    1815         [ #  # ]:          0 :         if (on)
    1816                 :          0 :                 VMXNET3_SET_VFTABLE_ENTRY(hw->shadow_vfta, vid);
    1817                 :            :         else
    1818                 :          0 :                 VMXNET3_CLEAR_VFTABLE_ENTRY(hw->shadow_vfta, vid);
    1819                 :            : 
    1820                 :            :         /* don't change active filter if in promiscuous mode */
    1821         [ #  # ]:          0 :         if (rxConf->rxMode & VMXNET3_RXM_PROMISC)
    1822                 :            :                 return 0;
    1823                 :            : 
    1824                 :            :         /* set in hardware */
    1825         [ #  # ]:          0 :         if (on)
    1826                 :          0 :                 VMXNET3_SET_VFTABLE_ENTRY(vf_table, vid);
    1827                 :            :         else
    1828                 :          0 :                 VMXNET3_CLEAR_VFTABLE_ENTRY(vf_table, vid);
    1829                 :            : 
    1830                 :          0 :         VMXNET3_WRITE_BAR1_REG(hw, VMXNET3_REG_CMD,
    1831                 :            :                                VMXNET3_CMD_UPDATE_VLAN_FILTERS);
    1832                 :          0 :         return 0;
    1833                 :            : }
    1834                 :            : 
    1835                 :            : static int
    1836                 :          0 : vmxnet3_dev_vlan_offload_set(struct rte_eth_dev *dev, int mask)
    1837                 :            : {
    1838                 :          0 :         struct vmxnet3_hw *hw = dev->data->dev_private;
    1839                 :          0 :         Vmxnet3_DSDevRead *devRead = &hw->shared->devRead;
    1840                 :          0 :         uint32_t *vf_table = devRead->rxFilterConf.vfTable;
    1841                 :          0 :         uint64_t rx_offloads = dev->data->dev_conf.rxmode.offloads;
    1842                 :            : 
    1843         [ #  # ]:          0 :         if (mask & RTE_ETH_VLAN_STRIP_MASK) {
    1844         [ #  # ]:          0 :                 if (rx_offloads & RTE_ETH_RX_OFFLOAD_VLAN_STRIP)
    1845                 :          0 :                         devRead->misc.uptFeatures |= UPT1_F_RXVLAN;
    1846                 :            :                 else
    1847                 :          0 :                         devRead->misc.uptFeatures &= ~UPT1_F_RXVLAN;
    1848                 :            : 
    1849                 :          0 :                 VMXNET3_WRITE_BAR1_REG(hw, VMXNET3_REG_CMD,
    1850                 :            :                                        VMXNET3_CMD_UPDATE_FEATURE);
    1851                 :            :         }
    1852                 :            : 
    1853         [ #  # ]:          0 :         if (mask & RTE_ETH_VLAN_FILTER_MASK) {
    1854         [ #  # ]:          0 :                 if (rx_offloads & RTE_ETH_RX_OFFLOAD_VLAN_FILTER)
    1855                 :          0 :                         memcpy(vf_table, hw->shadow_vfta, VMXNET3_VFT_TABLE_SIZE);
    1856                 :            :                 else
    1857                 :            :                         memset(vf_table, 0xff, VMXNET3_VFT_TABLE_SIZE);
    1858                 :            : 
    1859                 :          0 :                 VMXNET3_WRITE_BAR1_REG(hw, VMXNET3_REG_CMD,
    1860                 :            :                                        VMXNET3_CMD_UPDATE_VLAN_FILTERS);
    1861                 :            :         }
    1862                 :            : 
    1863                 :          0 :         return 0;
    1864                 :            : }
    1865                 :            : 
    1866                 :            : static void
    1867                 :          0 : vmxnet3_process_events(struct rte_eth_dev *dev)
    1868                 :            : {
    1869                 :          0 :         struct vmxnet3_hw *hw = dev->data->dev_private;
    1870                 :          0 :         uint32_t events = hw->shared->ecr;
    1871                 :            :         int i;
    1872                 :            : 
    1873         [ #  # ]:          0 :         if (!events)
    1874                 :            :                 return;
    1875                 :            : 
    1876                 :            :         /*
    1877                 :            :          * ECR bits when written with 1b are cleared. Hence write
    1878                 :            :          * events back to ECR so that the bits which were set will be reset.
    1879                 :            :          */
    1880                 :          0 :         VMXNET3_WRITE_BAR1_REG(hw, VMXNET3_REG_ECR, events);
    1881                 :            : 
    1882                 :            :         /* Check if link state has changed */
    1883         [ #  # ]:          0 :         if (events & VMXNET3_ECR_LINK) {
    1884                 :          0 :                 PMD_DRV_LOG(DEBUG, "Process events: VMXNET3_ECR_LINK event");
    1885         [ #  # ]:          0 :                 if (vmxnet3_dev_link_update(dev, 0) == 0)
    1886                 :          0 :                         rte_eth_dev_callback_process(dev,
    1887                 :            :                                                      RTE_ETH_EVENT_INTR_LSC,
    1888                 :            :                                                      NULL);
    1889                 :            :         }
    1890                 :            : 
    1891                 :            :         /* Check if there is an error on xmit/recv queues */
    1892         [ #  # ]:          0 :         if (events & (VMXNET3_ECR_TQERR | VMXNET3_ECR_RQERR)) {
    1893                 :          0 :                 VMXNET3_WRITE_BAR1_REG(hw, VMXNET3_REG_CMD,
    1894                 :            :                                        VMXNET3_CMD_GET_QUEUE_STATUS);
    1895                 :            : 
    1896                 :          0 :                 PMD_DRV_LOG(ERR, "queue error event 0x%x for "
    1897                 :            :                             RTE_ETHER_ADDR_PRT_FMT, events,
    1898                 :            :                             hw->perm_addr[0], hw->perm_addr[1],
    1899                 :            :                             hw->perm_addr[2], hw->perm_addr[3],
    1900                 :            :                             hw->perm_addr[4], hw->perm_addr[5]);
    1901                 :            : 
    1902         [ #  # ]:          0 :                 for (i = 0; i < hw->num_tx_queues; i++) {
    1903         [ #  # ]:          0 :                         if (hw->tqd_start[i].status.stopped)
    1904                 :          0 :                                 PMD_DRV_LOG(ERR, "tq %d error 0x%x",
    1905                 :            :                                             i, hw->tqd_start[i].status.error);
    1906                 :            :                 }
    1907         [ #  # ]:          0 :                 for (i = 0; i < hw->num_rx_queues; i++) {
    1908         [ #  # ]:          0 :                         if (hw->rqd_start[i].status.stopped)
    1909                 :          0 :                                 PMD_DRV_LOG(ERR, "rq %d error 0x%x",
    1910                 :            :                                             i, hw->rqd_start[i].status.error);
    1911                 :            :                 }
    1912                 :            : 
    1913                 :            :                 /* Have to reset the device */
    1914                 :            :                 /* Notify the application so that it can reset the device */
    1915                 :          0 :                 rte_eth_dev_callback_process(dev,
    1916                 :            :                                              RTE_ETH_EVENT_INTR_RESET,
    1917                 :            :                                              NULL);
    1918                 :            :         }
    1919                 :            : 
    1920         [ #  # ]:          0 :         if (events & VMXNET3_ECR_DIC)
    1921                 :          0 :                 PMD_DRV_LOG(DEBUG, "Device implementation change event.");
    1922                 :            : 
    1923         [ #  # ]:          0 :         if (events & VMXNET3_ECR_DEBUG)
    1924                 :          0 :                 PMD_DRV_LOG(DEBUG, "Debug event generated by device.");
    1925                 :            : }
    1926                 :            : 
    1927                 :            : static void
    1928                 :          0 : vmxnet3_interrupt_handler(void *param)
    1929                 :            : {
    1930                 :            :         struct rte_eth_dev *dev = param;
    1931                 :          0 :         struct vmxnet3_hw *hw = dev->data->dev_private;
    1932                 :            :         uint32_t events;
    1933                 :            :         uint8 *eventIntrIdx;
    1934                 :            :         uint32 *intrCtrl;
    1935                 :            : 
    1936                 :          0 :         PMD_INIT_FUNC_TRACE();
    1937                 :            : 
    1938                 :            :         vmxnet3_get_intr_ctrl_ev(hw, &eventIntrIdx, &intrCtrl);
    1939                 :          0 :         vmxnet3_disable_intr(hw, *eventIntrIdx);
    1940                 :            : 
    1941                 :          0 :         events = VMXNET3_READ_BAR1_REG(hw, VMXNET3_REG_ECR);
    1942         [ #  # ]:          0 :         if (events == 0)
    1943                 :          0 :                 goto done;
    1944                 :            : 
    1945                 :          0 :         PMD_DRV_LOG(DEBUG, "Reading events: 0x%X", events);
    1946                 :          0 :         vmxnet3_process_events(dev);
    1947                 :          0 : done:
    1948                 :          0 :         vmxnet3_enable_intr(hw, *eventIntrIdx);
    1949                 :          0 : }
    1950                 :            : 
    1951                 :            : static int
    1952                 :          0 : vmxnet3_dev_rx_queue_intr_enable(struct rte_eth_dev *dev, uint16_t queue_id)
    1953                 :            : {
    1954                 :            : #ifndef RTE_EXEC_ENV_FREEBSD
    1955                 :          0 :         struct vmxnet3_hw *hw = dev->data->dev_private;
    1956                 :            : 
    1957                 :          0 :         vmxnet3_enable_intr(hw,
    1958                 :          0 :                             rte_intr_vec_list_index_get(dev->intr_handle,
    1959                 :            :                                                                queue_id));
    1960                 :            : #endif
    1961                 :            : 
    1962                 :          0 :         return 0;
    1963                 :            : }
    1964                 :            : 
    1965                 :            : static int
    1966                 :          0 : vmxnet3_dev_rx_queue_intr_disable(struct rte_eth_dev *dev, uint16_t queue_id)
    1967                 :            : {
    1968                 :          0 :         struct vmxnet3_hw *hw = dev->data->dev_private;
    1969                 :            : 
    1970                 :          0 :         vmxnet3_disable_intr(hw,
    1971                 :          0 :                 rte_intr_vec_list_index_get(dev->intr_handle, queue_id));
    1972                 :            : 
    1973                 :          0 :         return 0;
    1974                 :            : }
    1975                 :            : 
    1976                 :        253 : RTE_PMD_REGISTER_PCI(net_vmxnet3, rte_vmxnet3_pmd);
    1977                 :            : RTE_PMD_REGISTER_PCI_TABLE(net_vmxnet3, pci_id_vmxnet3_map);
    1978                 :            : RTE_PMD_REGISTER_KMOD_DEP(net_vmxnet3, "* igb_uio | uio_pci_generic | vfio-pci");
    1979         [ -  + ]:        253 : RTE_LOG_REGISTER_SUFFIX(vmxnet3_logtype_init, init, NOTICE);
    1980         [ -  + ]:        253 : RTE_LOG_REGISTER_SUFFIX(vmxnet3_logtype_driver, driver, NOTICE);
    1981                 :            : 
    1982                 :            : static int
    1983                 :          0 : vmxnet3_rss_reta_update(struct rte_eth_dev *dev,
    1984                 :            :                         struct rte_eth_rss_reta_entry64 *reta_conf,
    1985                 :            :                         uint16_t reta_size)
    1986                 :            : {
    1987                 :            :         int i, idx, shift;
    1988                 :          0 :         struct vmxnet3_hw *hw = dev->data->dev_private;
    1989                 :          0 :         struct VMXNET3_RSSConf *dev_rss_conf = hw->rss_conf;
    1990                 :            : 
    1991         [ #  # ]:          0 :         if (reta_size != dev_rss_conf->indTableSize) {
    1992                 :          0 :                 PMD_DRV_LOG(ERR,
    1993                 :            :                         "The size of hash lookup table configured (%d) doesn't match "
    1994                 :            :                         "the supported number (%d)",
    1995                 :            :                         reta_size, dev_rss_conf->indTableSize);
    1996                 :          0 :                 return -EINVAL;
    1997                 :            :         }
    1998                 :            : 
    1999         [ #  # ]:          0 :         for (i = 0; i < reta_size; i++) {
    2000                 :          0 :                 idx = i / RTE_ETH_RETA_GROUP_SIZE;
    2001                 :          0 :                 shift = i % RTE_ETH_RETA_GROUP_SIZE;
    2002         [ #  # ]:          0 :                 if (reta_conf[idx].mask & RTE_BIT64(shift))
    2003                 :          0 :                         dev_rss_conf->indTable[i] = (uint8_t)reta_conf[idx].reta[shift];
    2004                 :            :         }
    2005                 :            : 
    2006                 :          0 :         VMXNET3_WRITE_BAR1_REG(hw, VMXNET3_REG_CMD,
    2007                 :            :                                 VMXNET3_CMD_UPDATE_RSSIDT);
    2008                 :            : 
    2009                 :          0 :         return 0;
    2010                 :            : }
    2011                 :            : 
    2012                 :            : static int
    2013                 :          0 : vmxnet3_rss_reta_query(struct rte_eth_dev *dev,
    2014                 :            :                        struct rte_eth_rss_reta_entry64 *reta_conf,
    2015                 :            :                        uint16_t reta_size)
    2016                 :            : {
    2017                 :            :         int i, idx, shift;
    2018                 :          0 :         struct vmxnet3_hw *hw = dev->data->dev_private;
    2019                 :          0 :         struct VMXNET3_RSSConf *dev_rss_conf = hw->rss_conf;
    2020                 :            : 
    2021         [ #  # ]:          0 :         if (reta_size != dev_rss_conf->indTableSize) {
    2022                 :          0 :                 PMD_DRV_LOG(ERR,
    2023                 :            :                         "Size of requested hash lookup table (%d) doesn't "
    2024                 :            :                         "match the configured size (%d)",
    2025                 :            :                         reta_size, dev_rss_conf->indTableSize);
    2026                 :          0 :                 return -EINVAL;
    2027                 :            :         }
    2028                 :            : 
    2029         [ #  # ]:          0 :         for (i = 0; i < reta_size; i++) {
    2030                 :          0 :                 idx = i / RTE_ETH_RETA_GROUP_SIZE;
    2031                 :          0 :                 shift = i % RTE_ETH_RETA_GROUP_SIZE;
    2032         [ #  # ]:          0 :                 if (reta_conf[idx].mask & RTE_BIT64(shift))
    2033                 :          0 :                         reta_conf[idx].reta[shift] = dev_rss_conf->indTable[i];
    2034                 :            :         }
    2035                 :            : 
    2036                 :            :         return 0;
    2037                 :            : }

Generated by: LCOV version 1.14