LCOV - code coverage report
Current view: top level - drivers/net/ntnic - ntnic_ethdev.c (source / functions) Hit Total Coverage
Test: Code coverage Lines: 5 1138 0.4 %
Date: 2026-10-01 18:19:24 Functions: 5 56 8.9 %
Legend: Lines: hit not hit | Branches: + taken - not taken # not executed Branches: 4 584 0.7 %

           Branch data     Line data    Source code
       1                 :            : /* SPDX-License-Identifier: BSD-3-Clause
       2                 :            :  * Copyright(c) 2023 Napatech A/S
       3                 :            :  */
       4                 :            : 
       5                 :            : #include <stdint.h>
       6                 :            : #include <stdarg.h>
       7                 :            : 
       8                 :            : #include <rte_eal.h>
       9                 :            : #include <rte_dev.h>
      10                 :            : #include <rte_vfio.h>
      11                 :            : #include <rte_ethdev.h>
      12                 :            : #include <rte_bus_pci.h>
      13                 :            : #include <ethdev_pci.h>
      14                 :            : #include <rte_kvargs.h>
      15                 :            : 
      16                 :            : #include <sys/queue.h>
      17                 :            : 
      18                 :            : #include "rte_spinlock.h"
      19                 :            : #include "ntlog.h"
      20                 :            : #include "ntdrv_4ga.h"
      21                 :            : #include "ntos_drv.h"
      22                 :            : #include "ntos_system.h"
      23                 :            : #include "nthw_fpga_instances.h"
      24                 :            : #include "ntnic_vfio.h"
      25                 :            : #include "ntnic_mod_reg.h"
      26                 :            : #include "nt_util.h"
      27                 :            : #include "flow_hsh_cfg.h"
      28                 :            : #include "profile_inline/flm_age_queue.h"
      29                 :            : #include "profile_inline/flm_evt_queue.h"
      30                 :            : #include "rte_pmd_ntnic.h"
      31                 :            : #include "nt_service.h"
      32                 :            : 
      33                 :            : #define HW_MAX_PKT_LEN (10000)
      34                 :            : #define MAX_MTU (HW_MAX_PKT_LEN - RTE_ETHER_HDR_LEN - RTE_ETHER_CRC_LEN)
      35                 :            : #define MIN_MTU_INLINE 512
      36                 :            : 
      37                 :            : #define EXCEPTION_PATH_HID 0
      38                 :            : 
      39                 :            : #define MAX_TOTAL_QUEUES       128
      40                 :            : 
      41                 :            : #define SG_NB_HW_RX_DESCRIPTORS 1024
      42                 :            : #define SG_NB_HW_TX_DESCRIPTORS 1024
      43                 :            : #define SG_HW_RX_PKT_BUFFER_SIZE (1024 << 1)
      44                 :            : #define SG_HW_TX_PKT_BUFFER_SIZE (1024 << 1)
      45                 :            : 
      46                 :            : #define NUM_VQ_SEGS(_data_size_)                                                                  \
      47                 :            :         ({                                                                                        \
      48                 :            :                 size_t _size = (_data_size_);                                                     \
      49                 :            :                 size_t _segment_count = ((_size + SG_HDR_SIZE) > SG_HW_TX_PKT_BUFFER_SIZE)        \
      50                 :            :                         ? (((_size + SG_HDR_SIZE) + SG_HW_TX_PKT_BUFFER_SIZE - 1) /               \
      51                 :            :                            SG_HW_TX_PKT_BUFFER_SIZE)                                              \
      52                 :            :                         : 1;                                                                      \
      53                 :            :                 _segment_count;                                                                   \
      54                 :            :         })
      55                 :            : 
      56                 :            : #define VIRTQ_DESCR_IDX(_tx_pkt_idx_)                                                             \
      57                 :            :         (((_tx_pkt_idx_) + first_vq_descr_idx) % SG_NB_HW_TX_DESCRIPTORS)
      58                 :            : 
      59                 :            : #define VIRTQ_DESCR_IDX_NEXT(_vq_descr_idx_) (((_vq_descr_idx_) + 1) % SG_NB_HW_TX_DESCRIPTORS)
      60                 :            : 
      61                 :            : #define ONE_G_SIZE  0x40000000
      62                 :            : #define ONE_G_MASK  (ONE_G_SIZE - 1)
      63                 :            : 
      64                 :            : #define MAX_RX_PACKETS   128
      65                 :            : #define MAX_TX_PACKETS   128
      66                 :            : 
      67                 :            : #define MTUINITVAL 1500
      68                 :            : 
      69                 :            : uint64_t nthw_tsc_freq;
      70                 :            : 
      71                 :            : 
      72                 :            : #define ETH_DEV_NTNIC_HELP_ARG "help"
      73                 :            : #define ETH_DEV_NTHW_RXQUEUES_ARG "rxqs"
      74                 :            : #define ETH_DEV_NTHW_TXQUEUES_ARG "txqs"
      75                 :            : #define ETH_DEV_NTHW_EXCEPTION_PATH_ARG "exception_path"
      76                 :            : 
      77                 :            : static const char *const valid_arguments[] = {
      78                 :            :         ETH_DEV_NTNIC_HELP_ARG,
      79                 :            :         ETH_DEV_NTHW_RXQUEUES_ARG,
      80                 :            :         ETH_DEV_NTHW_TXQUEUES_ARG,
      81                 :            :         ETH_DEV_NTHW_EXCEPTION_PATH_ARG,
      82                 :            :         NULL,
      83                 :            : };
      84                 :            : 
      85                 :            : 
      86                 :            : static const struct rte_pci_id nthw_pci_id_map[] = {
      87                 :            :         { RTE_PCI_DEVICE(NT_HW_PCI_VENDOR_ID, NT_HW_PCI_DEVICE_ID_NT200A02) },
      88                 :            :         { RTE_PCI_DEVICE(NT_HW_PCI_VENDOR_ID, NT_HW_PCI_DEVICE_ID_NT400D11) },
      89                 :            :         { RTE_PCI_DEVICE(NT_HW_PCI_VENDOR_ID, NT_HW_PCI_DEVICE_ID_NT400D13) },
      90                 :            :         {
      91                 :            :                 .vendor_id = 0,
      92                 :            :         },      /* sentinel */
      93                 :            : };
      94                 :            : 
      95                 :            : static const struct sg_ops_s *sg_ops;
      96                 :            : 
      97                 :            : rte_spinlock_t nthw_lock = RTE_SPINLOCK_INITIALIZER;
      98                 :            : 
      99                 :            : /*
     100                 :            :  * Store and get adapter info
     101                 :            :  */
     102                 :            : 
     103                 :            : static struct drv_s *_g_p_drv[NUM_ADAPTER_MAX] = { NULL };
     104                 :            : 
     105                 :            : static void
     106                 :          0 : store_pdrv(struct drv_s *p_drv)
     107                 :            : {
     108         [ #  # ]:          0 :         if (p_drv->adapter_no >= NUM_ADAPTER_MAX) {
     109                 :          0 :                 NT_LOG(ERR, NTNIC,
     110                 :            :                         "Internal error adapter number %u out of range. Max number of adapters: %u",
     111                 :            :                         p_drv->adapter_no, NUM_ADAPTER_MAX);
     112                 :          0 :                 return;
     113                 :            :         }
     114                 :            : 
     115         [ #  # ]:          0 :         if (_g_p_drv[p_drv->adapter_no] != 0) {
     116                 :          0 :                 NT_LOG(WRN, NTNIC,
     117                 :            :                         "Overwriting adapter structure for PCI  " PCIIDENT_PRINT_STR
     118                 :            :                         " with adapter structure for PCI  " PCIIDENT_PRINT_STR,
     119                 :            :                         PCIIDENT_TO_DOMAIN(_g_p_drv[p_drv->adapter_no]->ntdrv.pciident),
     120                 :            :                         PCIIDENT_TO_BUSNR(_g_p_drv[p_drv->adapter_no]->ntdrv.pciident),
     121                 :            :                         PCIIDENT_TO_DEVNR(_g_p_drv[p_drv->adapter_no]->ntdrv.pciident),
     122                 :            :                         PCIIDENT_TO_FUNCNR(_g_p_drv[p_drv->adapter_no]->ntdrv.pciident),
     123                 :            :                         PCIIDENT_TO_DOMAIN(p_drv->ntdrv.pciident),
     124                 :            :                         PCIIDENT_TO_BUSNR(p_drv->ntdrv.pciident),
     125                 :            :                         PCIIDENT_TO_DEVNR(p_drv->ntdrv.pciident),
     126                 :            :                         PCIIDENT_TO_FUNCNR(p_drv->ntdrv.pciident));
     127                 :            :         }
     128                 :            : 
     129                 :            :         rte_spinlock_lock(&nthw_lock);
     130                 :          0 :         _g_p_drv[p_drv->adapter_no] = p_drv;
     131                 :            :         rte_spinlock_unlock(&nthw_lock);
     132                 :            : }
     133                 :            : 
     134                 :          0 : static void clear_pdrv(struct drv_s *p_drv)
     135                 :            : {
     136         [ #  # ]:          0 :         if (p_drv->adapter_no >= NUM_ADAPTER_MAX)
     137                 :            :                 return;
     138                 :            : 
     139                 :            :         rte_spinlock_lock(&nthw_lock);
     140                 :          0 :         _g_p_drv[p_drv->adapter_no] = NULL;
     141                 :            :         rte_spinlock_unlock(&nthw_lock);
     142                 :            : }
     143                 :            : 
     144                 :            : static struct drv_s *
     145                 :          0 : get_pdrv_from_pci(struct rte_pci_addr addr)
     146                 :            : {
     147                 :            :         int i;
     148                 :            :         struct drv_s *p_drv = NULL;
     149                 :            :         rte_spinlock_lock(&nthw_lock);
     150                 :            : 
     151         [ #  # ]:          0 :         for (i = 0; i < NUM_ADAPTER_MAX; i++) {
     152         [ #  # ]:          0 :                 if (_g_p_drv[i]) {
     153         [ #  # ]:          0 :                         if (PCIIDENT_TO_DOMAIN(_g_p_drv[i]->ntdrv.pciident) == addr.domain &&
     154         [ #  # ]:          0 :                                 PCIIDENT_TO_BUSNR(_g_p_drv[i]->ntdrv.pciident) == addr.bus) {
     155                 :            :                                 p_drv = _g_p_drv[i];
     156                 :            :                                 break;
     157                 :            :                         }
     158                 :            :                 }
     159                 :            :         }
     160                 :            : 
     161                 :            :         rte_spinlock_unlock(&nthw_lock);
     162                 :          0 :         return p_drv;
     163                 :            : }
     164                 :            : 
     165                 :          0 : static int dpdk_stats_collect(struct pmd_internals *internals, struct rte_eth_stats *stats,
     166                 :            :                 struct eth_queue_stats *qstats)
     167                 :            : {
     168                 :          0 :         const struct ntnic_filter_ops *ntnic_filter_ops = nthw_get_filter_ops();
     169                 :            : 
     170         [ #  # ]:          0 :         if (ntnic_filter_ops == NULL) {
     171                 :          0 :                 NT_LOG_DBGX(ERR, NTNIC, "ntnic_filter_ops uninitialized");
     172                 :          0 :                 return -1;
     173                 :            :         }
     174                 :            : 
     175                 :            :         unsigned int i;
     176                 :          0 :         struct drv_s *p_drv = internals->p_drv;
     177                 :            :         struct ntdrv_4ga_s *p_nt_drv = &p_drv->ntdrv;
     178                 :            :         nt4ga_stat_t *p_nt4ga_stat = &p_nt_drv->adapter_info.nt4ga_stat;
     179                 :          0 :         nthw_stat_t *p_nthw_stat = p_nt4ga_stat->mp_nthw_stat;
     180                 :          0 :         const int n_intf_no = internals->n_intf_no;
     181                 :            :         uint64_t rx_total = 0;
     182                 :            :         uint64_t rx_total_b = 0;
     183                 :            :         uint64_t tx_total = 0;
     184                 :            :         uint64_t tx_total_b = 0;
     185                 :            :         uint64_t tx_err_total = 0;
     186                 :            : 
     187   [ #  #  #  #  :          0 :         if (!p_nthw_stat || !p_nt4ga_stat || !stats || n_intf_no < 0 ||
                   #  # ]
     188                 :            :                 n_intf_no > NUM_ADAPTER_PORTS_MAX) {
     189                 :          0 :                 NT_LOG_DBGX(WRN, NTNIC, "error exit");
     190                 :          0 :                 return -1;
     191                 :            :         }
     192                 :            : 
     193                 :            :         /*
     194                 :            :          * Pull the latest port statistic numbers (Rx/Tx pkts and bytes)
     195                 :            :          * Return values are in the "internals->rxq_scg[]" and "internals->txq_scg[]" arrays
     196                 :            :          */
     197                 :          0 :         ntnic_filter_ops->poll_statistics(internals);
     198                 :            : 
     199         [ #  # ]:          0 :         for (i = 0; i < internals->nb_rx_queues; i++) {
     200         [ #  # ]:          0 :                 if (qstats != NULL) {
     201                 :          0 :                         qstats[i].q_ipackets = internals->rxq_scg[i].rx_pkts;
     202                 :          0 :                         qstats[i].q_ibytes = internals->rxq_scg[i].rx_bytes;
     203                 :            :                 }
     204                 :          0 :                 rx_total += internals->rxq_scg[i].rx_pkts;
     205                 :          0 :                 rx_total_b += internals->rxq_scg[i].rx_bytes;
     206                 :            :         }
     207                 :            : 
     208         [ #  # ]:          0 :         for (i = 0; i < internals->nb_tx_queues; i++) {
     209         [ #  # ]:          0 :                 if (qstats != NULL) {
     210                 :          0 :                         qstats[i].q_opackets = internals->txq_scg[i].tx_pkts;
     211                 :          0 :                         qstats[i].q_obytes = internals->txq_scg[i].tx_bytes;
     212                 :            :                 }
     213                 :          0 :                 tx_total += internals->txq_scg[i].tx_pkts;
     214                 :          0 :                 tx_total_b += internals->txq_scg[i].tx_bytes;
     215                 :          0 :                 tx_err_total += internals->txq_scg[i].err_pkts;
     216                 :            :         }
     217                 :            : 
     218                 :          0 :         stats->imissed = internals->rx_missed;
     219                 :          0 :         stats->ipackets = rx_total;
     220                 :          0 :         stats->ibytes = rx_total_b;
     221                 :          0 :         stats->opackets = tx_total;
     222                 :          0 :         stats->obytes = tx_total_b;
     223                 :          0 :         stats->oerrors = tx_err_total;
     224                 :            : 
     225                 :          0 :         return 0;
     226                 :            : }
     227                 :            : 
     228                 :          0 : static int dpdk_stats_reset(struct pmd_internals *internals, struct ntdrv_4ga_s *p_nt_drv,
     229                 :            :         int n_intf_no)
     230                 :            : {
     231                 :            :         nt4ga_stat_t *p_nt4ga_stat = &p_nt_drv->adapter_info.nt4ga_stat;
     232                 :          0 :         nthw_stat_t *p_nthw_stat = p_nt4ga_stat->mp_nthw_stat;
     233                 :            :         unsigned int i;
     234                 :            : 
     235   [ #  #  #  # ]:          0 :         if (!p_nthw_stat || !p_nt4ga_stat || n_intf_no < 0 || n_intf_no > NUM_ADAPTER_PORTS_MAX)
     236                 :            :                 return -1;
     237                 :            : 
     238                 :          0 :         rte_spinlock_lock(&p_nt_drv->stat_lck);
     239                 :            : 
     240                 :            :         /* Rx */
     241         [ #  # ]:          0 :         for (i = 0; i < internals->nb_rx_queues; i++) {
     242                 :          0 :                 internals->rxq_scg[i].rx_pkts = 0;
     243                 :          0 :                 internals->rxq_scg[i].rx_bytes = 0;
     244                 :          0 :                 internals->rxq_scg[i].err_pkts = 0;
     245                 :            :         }
     246                 :            : 
     247                 :          0 :         internals->rx_missed = 0;
     248                 :            : 
     249                 :            :         /* Tx */
     250         [ #  # ]:          0 :         for (i = 0; i < internals->nb_tx_queues; i++) {
     251                 :          0 :                 internals->txq_scg[i].tx_pkts = 0;
     252                 :          0 :                 internals->txq_scg[i].tx_bytes = 0;
     253                 :          0 :                 internals->txq_scg[i].err_pkts = 0;
     254                 :            :         }
     255                 :            : 
     256                 :          0 :         p_nt4ga_stat->n_totals_reset_timestamp = time(NULL);
     257                 :            : 
     258                 :            :         rte_spinlock_unlock(&p_nt_drv->stat_lck);
     259                 :            : 
     260                 :          0 :         return 0;
     261                 :            : }
     262                 :            : 
     263                 :            : static int
     264                 :          0 : eth_link_update(struct rte_eth_dev *eth_dev, int wait_to_complete __rte_unused)
     265                 :            : {
     266                 :          0 :         const struct port_ops *port_ops = nthw_get_port_ops();
     267                 :            : 
     268         [ #  # ]:          0 :         if (port_ops == NULL) {
     269                 :          0 :                 NT_LOG(ERR, NTNIC, "Link management module uninitialized");
     270                 :          0 :                 return -1;
     271                 :            :         }
     272                 :            : 
     273                 :          0 :         struct pmd_internals *internals = eth_dev->data->dev_private;
     274                 :            : 
     275                 :          0 :         const int n_intf_no = internals->n_intf_no;
     276                 :          0 :         struct adapter_info_s *p_adapter_info = &internals->p_drv->ntdrv.adapter_info;
     277                 :            : 
     278         [ #  # ]:          0 :         if (eth_dev->data->dev_started) {
     279                 :          0 :                 const bool port_link_status = port_ops->get_link_status(p_adapter_info, n_intf_no);
     280                 :          0 :                 eth_dev->data->dev_link.link_status =
     281                 :            :                         port_link_status ? RTE_ETH_LINK_UP : RTE_ETH_LINK_DOWN;
     282                 :            : 
     283                 :            :                 nt_link_speed_t port_link_speed =
     284                 :          0 :                         port_ops->get_link_speed(p_adapter_info, n_intf_no);
     285                 :          0 :                 eth_dev->data->dev_link.link_speed =
     286                 :          0 :                         nthw_link_speed_to_eth_speed_num(port_link_speed);
     287                 :            : 
     288                 :            :                 nt_link_duplex_t nt_link_duplex =
     289                 :          0 :                         port_ops->get_link_duplex(p_adapter_info, n_intf_no);
     290                 :          0 :                 eth_dev->data->dev_link.link_duplex =
     291                 :          0 :                         nthw_link_duplex_to_eth_duplex(nt_link_duplex);
     292                 :            : 
     293                 :            :         } else {
     294                 :          0 :                 eth_dev->data->dev_link.link_status = RTE_ETH_LINK_DOWN;
     295                 :          0 :                 eth_dev->data->dev_link.link_speed = RTE_ETH_SPEED_NUM_NONE;
     296                 :          0 :                 eth_dev->data->dev_link.link_duplex = RTE_ETH_LINK_FULL_DUPLEX;
     297                 :            :         }
     298                 :            : 
     299                 :            :         return 0;
     300                 :            : }
     301                 :            : 
     302                 :          0 : static int eth_stats_get(struct rte_eth_dev *eth_dev, struct rte_eth_stats *stats,
     303                 :            :                 struct eth_queue_stats *qstats)
     304                 :            : {
     305                 :          0 :         struct pmd_internals *internals = eth_dev->data->dev_private;
     306                 :          0 :         dpdk_stats_collect(internals, stats, qstats);
     307                 :          0 :         return 0;
     308                 :            : }
     309                 :            : 
     310                 :          0 : static int eth_stats_reset(struct rte_eth_dev *eth_dev)
     311                 :            : {
     312                 :          0 :         struct pmd_internals *internals = eth_dev->data->dev_private;
     313                 :          0 :         struct drv_s *p_drv = internals->p_drv;
     314                 :          0 :         struct ntdrv_4ga_s *p_nt_drv = &p_drv->ntdrv;
     315                 :          0 :         const int n_intf_no = internals->n_intf_no;
     316                 :          0 :         dpdk_stats_reset(internals, p_nt_drv, n_intf_no);
     317                 :          0 :         return 0;
     318                 :            : }
     319                 :            : 
     320                 :            : static int
     321                 :          0 : eth_dev_infos_get(struct rte_eth_dev *eth_dev, struct rte_eth_dev_info *dev_info)
     322                 :            : {
     323                 :          0 :         const struct port_ops *port_ops = nthw_get_port_ops();
     324                 :            : 
     325         [ #  # ]:          0 :         if (port_ops == NULL) {
     326                 :          0 :                 NT_LOG(ERR, NTNIC, "Link management module uninitialized");
     327                 :          0 :                 return -1;
     328                 :            :         }
     329                 :            : 
     330                 :          0 :         struct pmd_internals *internals = eth_dev->data->dev_private;
     331                 :            : 
     332         [ #  # ]:          0 :         if (internals == NULL) {
     333                 :          0 :                 NT_LOG(ERR, NTNIC, "PMD-specific private data not initialized");
     334                 :          0 :                 return -1;
     335                 :            :         }
     336                 :            : 
     337                 :          0 :         const int n_intf_no = internals->n_intf_no;
     338                 :          0 :         struct adapter_info_s *p_adapter_info = &internals->p_drv->ntdrv.adapter_info;
     339                 :            : 
     340                 :          0 :         dev_info->driver_name = internals->name;
     341                 :          0 :         dev_info->max_mac_addrs = NUM_MAC_ADDRS_PER_PORT;
     342                 :          0 :         dev_info->max_rx_pktlen = HW_MAX_PKT_LEN;
     343                 :          0 :         dev_info->max_mtu = MAX_MTU;
     344                 :            : 
     345         [ #  # ]:          0 :         if (p_adapter_info->fpga_info.profile == FPGA_INFO_PROFILE_INLINE) {
     346                 :          0 :                 dev_info->min_mtu = MIN_MTU_INLINE;
     347                 :          0 :                 dev_info->flow_type_rss_offloads = NT_ETH_RSS_OFFLOAD_MASK;
     348                 :          0 :                 dev_info->hash_key_size = MAX_RSS_KEY_LEN;
     349                 :            : 
     350                 :          0 :                 dev_info->rss_algo_capa = RTE_ETH_HASH_ALGO_CAPA_MASK(DEFAULT) |
     351                 :            :                         RTE_ETH_HASH_ALGO_CAPA_MASK(TOEPLITZ);
     352                 :            :         }
     353                 :            : 
     354                 :            :         if (internals->p_drv) {
     355                 :          0 :                 dev_info->max_rx_queues = internals->nb_rx_queues;
     356                 :          0 :                 dev_info->max_tx_queues = internals->nb_tx_queues;
     357                 :            : 
     358                 :          0 :                 dev_info->min_rx_bufsize = 64;
     359                 :            : 
     360                 :            :                 const uint32_t nt_port_speed_capa =
     361                 :          0 :                         port_ops->get_link_speed_capabilities(p_adapter_info, n_intf_no);
     362                 :          0 :                 dev_info->speed_capa = nthw_link_speed_capa_to_eth_speed_capa(nt_port_speed_capa);
     363                 :            :         }
     364                 :            : 
     365                 :          0 :         return 0;
     366                 :            : }
     367                 :            : 
     368                 :            : static __rte_always_inline int copy_virtqueue_to_mbuf(struct rte_mbuf *mbuf,
     369                 :            :         struct rte_mempool *mb_pool,
     370                 :            :         struct nthw_received_packets *hw_recv,
     371                 :            :         int max_segs,
     372                 :            :         uint16_t data_len)
     373                 :            : {
     374                 :            :         int src_pkt = 0;
     375                 :            :         /*
     376                 :            :          * 1. virtqueue packets may be segmented
     377                 :            :          * 2. the mbuf size may be too small and may need to be segmented
     378                 :            :          */
     379                 :          0 :         char *data = (char *)hw_recv[src_pkt].addr + SG_HDR_SIZE;
     380                 :          0 :         char *dst = (char *)mbuf->buf_addr + RTE_PKTMBUF_HEADROOM;
     381                 :            : 
     382                 :            :         /* set packet length */
     383                 :          0 :         mbuf->pkt_len = data_len - SG_HDR_SIZE;
     384                 :            : 
     385                 :            :         int remain = mbuf->pkt_len;
     386                 :            :         /* First cpy_size is without header */
     387                 :            :         int cpy_size = (data_len > SG_HW_RX_PKT_BUFFER_SIZE)
     388                 :            :                 ? SG_HW_RX_PKT_BUFFER_SIZE - SG_HDR_SIZE
     389                 :          0 :                 : remain;
     390                 :            : 
     391                 :            :         struct rte_mbuf *m = mbuf;      /* if mbuf segmentation is needed */
     392                 :            : 
     393         [ #  # ]:          0 :         while (++src_pkt <= max_segs) {
     394                 :            :                 /* keep track of space in dst */
     395                 :          0 :                 int cpto_size = rte_pktmbuf_tailroom(m);
     396                 :            : 
     397         [ #  # ]:          0 :                 if (cpy_size > cpto_size) {
     398                 :            :                         int new_cpy_size = cpto_size;
     399                 :            : 
     400         [ #  # ]:          0 :                         rte_memcpy((void *)dst, (void *)data, new_cpy_size);
     401                 :          0 :                         m->data_len += new_cpy_size;
     402                 :          0 :                         remain -= new_cpy_size;
     403                 :          0 :                         cpy_size -= new_cpy_size;
     404                 :            : 
     405                 :          0 :                         data += new_cpy_size;
     406                 :            : 
     407                 :            :                         /*
     408                 :            :                          * loop if remaining data from this virtqueue seg
     409                 :            :                          * cannot fit in one extra mbuf
     410                 :            :                          */
     411                 :            :                         do {
     412                 :          0 :                                 m->next = rte_pktmbuf_alloc(mb_pool);
     413                 :            : 
     414         [ #  # ]:          0 :                                 if (unlikely(!m->next))
     415                 :            :                                         return -1;
     416                 :            : 
     417                 :            :                                 m = m->next;
     418                 :            : 
     419                 :            :                                 /* Headroom is not needed in chained mbufs */
     420                 :          0 :                                 rte_pktmbuf_prepend(m, rte_pktmbuf_headroom(m));
     421                 :          0 :                                 dst = (char *)m->buf_addr;
     422                 :          0 :                                 m->data_len = 0;
     423         [ #  # ]:          0 :                                 m->pkt_len = 0;
     424                 :            : 
     425                 :          0 :                                 cpto_size = rte_pktmbuf_tailroom(m);
     426                 :            : 
     427                 :          0 :                                 int actual_cpy_size =
     428                 :            :                                         (cpy_size > cpto_size) ? cpto_size : cpy_size;
     429                 :            : 
     430         [ #  # ]:          0 :                                 rte_memcpy((void *)dst, (void *)data, actual_cpy_size);
     431                 :          0 :                                 m->pkt_len += actual_cpy_size;
     432                 :          0 :                                 m->data_len += actual_cpy_size;
     433                 :            : 
     434                 :          0 :                                 remain -= actual_cpy_size;
     435                 :          0 :                                 cpy_size -= actual_cpy_size;
     436                 :            : 
     437                 :          0 :                                 data += actual_cpy_size;
     438                 :            : 
     439                 :          0 :                                 mbuf->nb_segs++;
     440                 :            : 
     441         [ #  # ]:          0 :                         } while (cpy_size && remain);
     442                 :            : 
     443                 :            :                 } else {
     444                 :            :                         /* all data from this virtqueue segment can fit in current mbuf */
     445         [ #  # ]:          0 :                         rte_memcpy((void *)dst, (void *)data, cpy_size);
     446                 :          0 :                         m->data_len += cpy_size;
     447                 :            : 
     448         [ #  # ]:          0 :                         if (mbuf->nb_segs > 1)
     449                 :          0 :                                 m->pkt_len += cpy_size;
     450                 :            : 
     451                 :          0 :                         remain -= cpy_size;
     452                 :            :                 }
     453                 :            : 
     454                 :            :                 /* packet complete - all data from current virtqueue packet has been copied */
     455         [ #  # ]:          0 :                 if (remain == 0)
     456                 :            :                         break;
     457                 :            : 
     458                 :            :                 /* increment dst to data end */
     459                 :          0 :                 dst = rte_pktmbuf_mtod_offset(m, char *, m->data_len);
     460                 :            :                 /* prepare for next virtqueue segment */
     461                 :          0 :                 data = (char *)hw_recv[src_pkt].addr;   /* following packets are full data */
     462                 :            : 
     463                 :          0 :                 cpy_size = (remain > SG_HW_RX_PKT_BUFFER_SIZE) ? SG_HW_RX_PKT_BUFFER_SIZE : remain;
     464                 :            :         };
     465                 :            : 
     466         [ #  # ]:          0 :         if (src_pkt > max_segs) {
     467                 :          0 :                 NT_LOG(ERR, NTNIC,
     468                 :            :                         "Did not receive correct number of segment for a whole packet");
     469                 :            :                 return -1;
     470                 :            :         }
     471                 :            : 
     472                 :            :         return src_pkt;
     473                 :            : }
     474                 :            : 
     475                 :          0 : static uint16_t eth_dev_rx_scg(void *queue, struct rte_mbuf **bufs, uint16_t nb_pkts)
     476                 :            : {
     477                 :            :         unsigned int i;
     478                 :            :         struct rte_mbuf *mbuf;
     479                 :            :         struct ntnic_rx_queue *rx_q = queue;
     480                 :            :         uint16_t num_rx = 0;
     481                 :            : 
     482                 :            :         struct nthw_received_packets hw_recv[MAX_RX_PACKETS];
     483                 :            : 
     484         [ #  # ]:          0 :         if (unlikely(nb_pkts == 0))
     485                 :            :                 return 0;
     486                 :            : 
     487                 :            :         if (nb_pkts > MAX_RX_PACKETS)
     488                 :            :                 nb_pkts = MAX_RX_PACKETS;
     489                 :            : 
     490                 :          0 :         uint16_t whole_pkts = 0;
     491                 :            :         uint16_t hw_recv_pkt_segs = 0;
     492                 :            : 
     493         [ #  # ]:          0 :         if (sg_ops != NULL) {
     494                 :            :                 hw_recv_pkt_segs =
     495                 :          0 :                         sg_ops->nthw_get_rx_packets(rx_q->vq, nb_pkts, hw_recv, &whole_pkts);
     496                 :            : 
     497         [ #  # ]:          0 :                 if (!hw_recv_pkt_segs)
     498                 :            :                         return 0;
     499                 :            :         }
     500                 :            : 
     501                 :          0 :         nb_pkts = whole_pkts;
     502                 :            : 
     503                 :            :         int src_pkt = 0;/* from 0 to hw_recv_pkt_segs */
     504                 :            : 
     505         [ #  # ]:          0 :         for (i = 0; i < nb_pkts; i++) {
     506                 :          0 :                 bufs[i] = rte_pktmbuf_alloc(rx_q->mb_pool);
     507                 :            : 
     508         [ #  # ]:          0 :                 if (!bufs[i]) {
     509                 :          0 :                         NT_LOG(ERR, NTNIC, "ERROR - no more buffers mbuf in mempool");
     510                 :          0 :                         goto err_exit;
     511                 :            :                 }
     512                 :            : 
     513                 :            :                 mbuf = bufs[i];
     514                 :            : 
     515                 :          0 :                 struct _pkt_hdr_rx *phdr = (struct _pkt_hdr_rx *)hw_recv[src_pkt].addr;
     516                 :            : 
     517         [ #  # ]:          0 :                 if (phdr->cap_len < SG_HDR_SIZE) {
     518                 :          0 :                         NT_LOG(ERR, NTNIC,
     519                 :            :                                 "Pkt len of zero received. No header!! - dropping packets");
     520                 :          0 :                         rte_pktmbuf_free(mbuf);
     521                 :          0 :                         goto err_exit;
     522                 :            :                 }
     523                 :            : 
     524                 :            :                 {
     525   [ #  #  #  # ]:          0 :                         if (phdr->cap_len <= SG_HW_RX_PKT_BUFFER_SIZE &&
     526         [ #  # ]:          0 :                                 (phdr->cap_len - SG_HDR_SIZE) <= rte_pktmbuf_tailroom(mbuf)) {
     527                 :          0 :                                 mbuf->data_len = phdr->cap_len - SG_HDR_SIZE;
     528         [ #  # ]:          0 :                                 rte_memcpy(rte_pktmbuf_mtod(mbuf, char *),
     529                 :            :                                         (char *)hw_recv[src_pkt].addr + SG_HDR_SIZE,
     530                 :            :                                         mbuf->data_len);
     531                 :            : 
     532                 :          0 :                                 mbuf->pkt_len = mbuf->data_len;
     533                 :          0 :                                 src_pkt++;
     534                 :            : 
     535                 :            :                         } else {
     536         [ #  # ]:          0 :                                 int cpy_segs = copy_virtqueue_to_mbuf(mbuf, rx_q->mb_pool,
     537                 :            :                                                 &hw_recv[src_pkt],
     538                 :            :                                                 hw_recv_pkt_segs - src_pkt,
     539                 :            :                                                 phdr->cap_len);
     540                 :            : 
     541         [ #  # ]:          0 :                                 if (cpy_segs < 0) {
     542                 :            :                                         /* Error */
     543                 :          0 :                                         rte_pktmbuf_free(mbuf);
     544                 :          0 :                                         goto err_exit;
     545                 :            :                                 }
     546                 :            : 
     547                 :          0 :                                 src_pkt += cpy_segs;
     548                 :            :                         }
     549                 :            : 
     550                 :          0 :                         num_rx++;
     551                 :            : 
     552                 :          0 :                         mbuf->ol_flags &= ~(RTE_MBUF_F_RX_FDIR_ID | RTE_MBUF_F_RX_FDIR);
     553                 :          0 :                         mbuf->port = (uint16_t)-1;
     554                 :            :                 }
     555                 :            :         }
     556                 :            : 
     557                 :          0 : err_exit:
     558                 :            : 
     559         [ #  # ]:          0 :         if (sg_ops != NULL)
     560                 :          0 :                 sg_ops->nthw_release_rx_packets(rx_q->vq, hw_recv_pkt_segs);
     561                 :            : 
     562                 :            :         return num_rx;
     563                 :            : }
     564                 :            : 
     565                 :          0 : static int copy_mbuf_to_virtqueue(struct nthw_cvirtq_desc *cvq_desc,
     566                 :            :         uint16_t vq_descr_idx,
     567                 :            :         struct nthw_memory_descriptor *vq_bufs,
     568                 :            :         int max_segs,
     569                 :            :         struct rte_mbuf *mbuf)
     570                 :            : {
     571                 :            :         /*
     572                 :            :          * 1. mbuf packet may be segmented
     573                 :            :          * 2. the virtqueue buffer size may be too small and may need to be segmented
     574                 :            :          */
     575                 :            : 
     576                 :          0 :         char *data = rte_pktmbuf_mtod(mbuf, char *);
     577                 :          0 :         char *dst = (char *)vq_bufs[vq_descr_idx].virt_addr + SG_HDR_SIZE;
     578                 :            : 
     579                 :          0 :         int remain = mbuf->pkt_len;
     580                 :          0 :         int cpy_size = mbuf->data_len;
     581                 :            : 
     582                 :            :         struct rte_mbuf *m = mbuf;
     583                 :            :         int cpto_size = SG_HW_TX_PKT_BUFFER_SIZE - SG_HDR_SIZE;
     584                 :            : 
     585                 :          0 :         cvq_desc->b[vq_descr_idx].len = SG_HDR_SIZE;
     586                 :            : 
     587                 :            :         int cur_seg_num = 0;    /* start from 0 */
     588                 :            : 
     589         [ #  # ]:          0 :         while (m) {
     590                 :            :                 /* Can all data in current src segment be in current dest segment */
     591         [ #  # ]:          0 :                 if (cpy_size > cpto_size) {
     592                 :            :                         int new_cpy_size = cpto_size;
     593                 :            : 
     594         [ #  # ]:          0 :                         rte_memcpy((void *)dst, (void *)data, new_cpy_size);
     595                 :            : 
     596                 :          0 :                         cvq_desc->b[vq_descr_idx].len += new_cpy_size;
     597                 :            : 
     598                 :          0 :                         remain -= new_cpy_size;
     599                 :          0 :                         cpy_size -= new_cpy_size;
     600                 :            : 
     601                 :          0 :                         data += new_cpy_size;
     602                 :            : 
     603                 :            :                         /*
     604                 :            :                          * Loop if remaining data from this virtqueue seg cannot fit in one extra
     605                 :            :                          * mbuf
     606                 :            :                          */
     607                 :            :                         do {
     608   [ #  #  #  # ]:          0 :                                 vq_add_flags(cvq_desc, vq_descr_idx, VIRTQ_DESC_F_NEXT);
     609                 :            : 
     610                 :          0 :                                 int next_vq_descr_idx = VIRTQ_DESCR_IDX_NEXT(vq_descr_idx);
     611                 :            : 
     612         [ #  # ]:          0 :                                 vq_set_next(cvq_desc, vq_descr_idx, next_vq_descr_idx);
     613                 :            : 
     614                 :          0 :                                 vq_descr_idx = next_vq_descr_idx;
     615                 :            : 
     616   [ #  #  #  # ]:          0 :                                 vq_set_flags(cvq_desc, vq_descr_idx, 0);
     617         [ #  # ]:          0 :                                 vq_set_next(cvq_desc, vq_descr_idx, 0);
     618                 :            : 
     619         [ #  # ]:          0 :                                 if (++cur_seg_num > max_segs)
     620                 :            :                                         break;
     621                 :            : 
     622                 :          0 :                                 dst = (char *)vq_bufs[vq_descr_idx].virt_addr;
     623                 :            :                                 cpto_size = SG_HW_TX_PKT_BUFFER_SIZE;
     624                 :            : 
     625                 :          0 :                                 int actual_cpy_size =
     626                 :            :                                         (cpy_size > cpto_size) ? cpto_size : cpy_size;
     627         [ #  # ]:          0 :                                 rte_memcpy((void *)dst, (void *)data, actual_cpy_size);
     628                 :            : 
     629                 :          0 :                                 cvq_desc->b[vq_descr_idx].len = actual_cpy_size;
     630                 :            : 
     631                 :          0 :                                 remain -= actual_cpy_size;
     632                 :          0 :                                 cpy_size -= actual_cpy_size;
     633                 :          0 :                                 cpto_size -= actual_cpy_size;
     634                 :            : 
     635                 :          0 :                                 data += actual_cpy_size;
     636                 :            : 
     637         [ #  # ]:          0 :                         } while (cpy_size && remain);
     638                 :            : 
     639                 :            :                 } else {
     640                 :            :                         /* All data from this segment can fit in current virtqueue buffer */
     641         [ #  # ]:          0 :                         rte_memcpy((void *)dst, (void *)data, cpy_size);
     642                 :            : 
     643                 :          0 :                         cvq_desc->b[vq_descr_idx].len += cpy_size;
     644                 :            : 
     645                 :          0 :                         remain -= cpy_size;
     646                 :          0 :                         cpto_size -= cpy_size;
     647                 :            :                 }
     648                 :            : 
     649                 :            :                 /* Packet complete - all segments from current mbuf has been copied */
     650         [ #  # ]:          0 :                 if (remain == 0)
     651                 :            :                         break;
     652                 :            : 
     653                 :            :                 /* increment dst to data end */
     654                 :          0 :                 dst = (char *)vq_bufs[vq_descr_idx].virt_addr + cvq_desc->b[vq_descr_idx].len;
     655                 :            : 
     656                 :          0 :                 m = m->next;
     657                 :            : 
     658         [ #  # ]:          0 :                 if (!m) {
     659                 :          0 :                         NT_LOG(ERR, NTNIC, "ERROR: invalid packet size");
     660                 :          0 :                         break;
     661                 :            :                 }
     662                 :            : 
     663                 :            :                 /* Prepare for next mbuf segment */
     664                 :          0 :                 data = rte_pktmbuf_mtod(m, char *);
     665                 :          0 :                 cpy_size = m->data_len;
     666                 :            :         };
     667                 :            : 
     668                 :          0 :         cur_seg_num++;
     669                 :            : 
     670         [ #  # ]:          0 :         if (cur_seg_num > max_segs) {
     671                 :          0 :                 NT_LOG(ERR, NTNIC,
     672                 :            :                         "Did not receive correct number of segment for a whole packet");
     673                 :          0 :                 return -1;
     674                 :            :         }
     675                 :            : 
     676                 :            :         return cur_seg_num;
     677                 :            : }
     678                 :            : 
     679                 :          0 : static uint16_t eth_dev_tx_scg(void *queue, struct rte_mbuf **bufs, uint16_t nb_pkts)
     680                 :            : {
     681                 :            :         uint16_t pkt;
     682                 :          0 :         uint16_t first_vq_descr_idx = 0;
     683                 :            : 
     684                 :            :         struct nthw_cvirtq_desc cvq_desc;
     685                 :            : 
     686                 :            :         struct nthw_memory_descriptor *vq_bufs;
     687                 :            : 
     688                 :            :         struct ntnic_tx_queue *tx_q = queue;
     689                 :            : 
     690                 :            :         int nb_segs = 0, i;
     691                 :            :         int pkts_sent = 0;
     692                 :            :         uint16_t nb_segs_arr[MAX_TX_PACKETS];
     693                 :            : 
     694                 :            :         if (nb_pkts > MAX_TX_PACKETS)
     695                 :            :                 nb_pkts = MAX_TX_PACKETS;
     696                 :            : 
     697                 :            :         /*
     698                 :            :          * count all segments needed to contain all packets in vq buffers
     699                 :            :          */
     700         [ #  # ]:          0 :         for (i = 0; i < nb_pkts; i++) {
     701                 :            :                 /* build the num segments array for segmentation control and release function */
     702         [ #  # ]:          0 :                 int vq_segs = NUM_VQ_SEGS(bufs[i]->pkt_len);
     703                 :          0 :                 nb_segs_arr[i] = vq_segs;
     704                 :          0 :                 nb_segs += vq_segs;
     705                 :            :         }
     706                 :            : 
     707         [ #  # ]:          0 :         if (!nb_segs)
     708                 :          0 :                 goto exit_out;
     709                 :            : 
     710         [ #  # ]:          0 :         if (sg_ops == NULL)
     711                 :          0 :                 goto exit_out;
     712                 :            : 
     713                 :          0 :         int got_nb_segs = sg_ops->nthw_get_tx_packets(tx_q->vq, nb_segs, &first_vq_descr_idx,
     714                 :            :                         &cvq_desc /*&vq_descr,*/, &vq_bufs);
     715                 :            : 
     716         [ #  # ]:          0 :         if (!got_nb_segs)
     717                 :          0 :                 goto exit_out;
     718                 :            : 
     719                 :            :         /*
     720                 :            :          * we may get less vq buffers than we have asked for
     721                 :            :          * calculate last whole packet that can fit into what
     722                 :            :          * we have got
     723                 :            :          */
     724         [ #  # ]:          0 :         while (got_nb_segs < nb_segs) {
     725         [ #  # ]:          0 :                 if (!--nb_pkts)
     726                 :          0 :                         goto exit_out;
     727                 :            : 
     728         [ #  # ]:          0 :                 nb_segs -= NUM_VQ_SEGS(bufs[nb_pkts]->pkt_len);
     729                 :            : 
     730         [ #  # ]:          0 :                 if (nb_segs <= 0)
     731                 :          0 :                         goto exit_out;
     732                 :            :         }
     733                 :            : 
     734                 :            :         /*
     735                 :            :          * nb_pkts & nb_segs, got it all, ready to copy
     736                 :            :          */
     737                 :            :         int seg_idx = 0;
     738                 :            :         int last_seg_idx = seg_idx;
     739                 :            : 
     740         [ #  # ]:          0 :         for (pkt = 0; pkt < nb_pkts; ++pkt) {
     741                 :          0 :                 uint16_t vq_descr_idx = VIRTQ_DESCR_IDX(seg_idx);
     742                 :            : 
     743   [ #  #  #  # ]:          0 :                 vq_set_flags(&cvq_desc, vq_descr_idx, 0);
     744         [ #  # ]:          0 :                 vq_set_next(&cvq_desc, vq_descr_idx, 0);
     745                 :            : 
     746   [ #  #  #  # ]:          0 :                 if (bufs[pkt]->nb_segs == 1 && nb_segs_arr[pkt] == 1) {
     747                 :          0 :                         rte_memcpy((void *)((char *)vq_bufs[vq_descr_idx].virt_addr + SG_HDR_SIZE),
     748         [ #  # ]:          0 :                                 rte_pktmbuf_mtod(bufs[pkt], void *), bufs[pkt]->pkt_len);
     749                 :            : 
     750                 :          0 :                         cvq_desc.b[vq_descr_idx].len = bufs[pkt]->pkt_len + SG_HDR_SIZE;
     751                 :            : 
     752                 :          0 :                         seg_idx++;
     753                 :            : 
     754                 :            :                 } else {
     755                 :          0 :                         int cpy_segs = copy_mbuf_to_virtqueue(&cvq_desc, vq_descr_idx, vq_bufs,
     756                 :            :                                         nb_segs - last_seg_idx, bufs[pkt]);
     757                 :            : 
     758         [ #  # ]:          0 :                         if (cpy_segs < 0)
     759                 :            :                                 break;
     760                 :            : 
     761                 :          0 :                         seg_idx += cpy_segs;
     762                 :            :                 }
     763                 :            : 
     764                 :            :                 last_seg_idx = seg_idx;
     765                 :          0 :                 rte_pktmbuf_free(bufs[pkt]);
     766                 :          0 :                 pkts_sent++;
     767                 :            :         }
     768                 :            : 
     769                 :          0 : exit_out:
     770                 :            : 
     771         [ #  # ]:          0 :         if (sg_ops != NULL) {
     772         [ #  # ]:          0 :                 if (pkts_sent)
     773                 :          0 :                         sg_ops->nthw_release_tx_packets(tx_q->vq, pkts_sent, nb_segs_arr);
     774                 :            :         }
     775                 :            : 
     776                 :          0 :         return pkts_sent;
     777                 :            : }
     778                 :            : 
     779                 :          0 : static int allocate_hw_virtio_queues(struct rte_eth_dev *eth_dev, int vf_num, struct hwq_s *hwq,
     780                 :            :         int num_descr, int buf_size)
     781                 :            : {
     782                 :            :         int i, res;
     783                 :            :         uint32_t size;
     784                 :            :         uint64_t iova_addr;
     785                 :            : 
     786                 :          0 :         NT_LOG(DBG, NTNIC, "***** Configure IOMMU for HW queues on VF %i *****", vf_num);
     787                 :            : 
     788                 :            :         /* Just allocate 1MB to hold all combined descr rings */
     789                 :          0 :         uint64_t tot_alloc_size = 0x100000 + (uint64_t)buf_size * (uint64_t)num_descr;
     790                 :            : 
     791                 :            :         void *virt =
     792                 :          0 :                 rte_malloc_socket("VirtQDescr", tot_alloc_size,
     793                 :          0 :                         nthw_util_align_size(tot_alloc_size),
     794                 :          0 :                         eth_dev->data->numa_node);
     795                 :            : 
     796         [ #  # ]:          0 :         if (!virt)
     797                 :            :                 return -1;
     798                 :            : 
     799                 :          0 :         uint64_t gp_offset = (uint64_t)virt & ONE_G_MASK;
     800                 :          0 :         rte_iova_t hpa = rte_malloc_virt2iova(virt);
     801                 :            : 
     802                 :          0 :         NT_LOG(DBG, NTNIC, "Allocated virtio descr rings : virt "
     803                 :            :                 "%p [0x%" PRIX64 "],hpa %" PRIX64 " [0x%" PRIX64 "]",
     804                 :            :                 virt, gp_offset, hpa, hpa & ONE_G_MASK);
     805                 :            : 
     806                 :            :         /*
     807                 :            :          * Same offset on both HPA and IOVA
     808                 :            :          * Make sure 1G boundary is never crossed
     809                 :            :          */
     810         [ #  # ]:          0 :         if (((hpa & ONE_G_MASK) != gp_offset) ||
     811         [ #  # ]:          0 :                 (((uint64_t)virt + tot_alloc_size) & ~ONE_G_MASK) !=
     812                 :            :                 ((uint64_t)virt & ~ONE_G_MASK)) {
     813                 :          0 :                 NT_LOG(ERR, NTNIC, "*********************************************************");
     814                 :          0 :                 NT_LOG(ERR, NTNIC, "ERROR, no optimal IOMMU mapping available hpa: %016" PRIX64
     815                 :            :                         "(%016" PRIX64 "), gp_offset: %016" PRIX64 " size: %" PRIu64,
     816                 :            :                         hpa, hpa & ONE_G_MASK, gp_offset, tot_alloc_size);
     817                 :          0 :                 NT_LOG(ERR, NTNIC, "*********************************************************");
     818                 :            : 
     819                 :          0 :                 rte_free(virt);
     820                 :            : 
     821                 :            :                 /* Just allocate 1MB to hold all combined descr rings */
     822                 :            :                 size = 0x100000;
     823                 :          0 :                 void *virt = rte_malloc_socket("VirtQDescr", size, 4096, eth_dev->data->numa_node);
     824                 :            : 
     825         [ #  # ]:          0 :                 if (!virt)
     826                 :            :                         return -1;
     827                 :            : 
     828                 :          0 :                 res = nthw_vfio_dma_map(vf_num, virt, &iova_addr, size);
     829                 :            : 
     830                 :          0 :                 NT_LOG(DBG, NTNIC, "VFIO MMAP res %i, vf_num %i", res, vf_num);
     831                 :            : 
     832         [ #  # ]:          0 :                 if (res != 0)
     833                 :            :                         return -1;
     834                 :            : 
     835                 :          0 :                 hwq->vf_num = vf_num;
     836                 :          0 :                 hwq->virt_queues_ctrl.virt_addr = virt;
     837                 :          0 :                 hwq->virt_queues_ctrl.phys_addr = (void *)iova_addr;
     838                 :          0 :                 hwq->virt_queues_ctrl.len = size;
     839                 :            : 
     840                 :          0 :                 NT_LOG(DBG, NTNIC,
     841                 :            :                         "Allocated for virtio descr rings combined 1MB : %p, IOVA %016" PRIX64 "",
     842                 :            :                         virt, iova_addr);
     843                 :            : 
     844                 :          0 :                 size = num_descr * sizeof(struct nthw_memory_descriptor);
     845                 :          0 :                 hwq->pkt_buffers =
     846                 :          0 :                         rte_zmalloc_socket("rx_pkt_buffers", size, 64, eth_dev->data->numa_node);
     847                 :            : 
     848         [ #  # ]:          0 :                 if (!hwq->pkt_buffers) {
     849                 :          0 :                         NT_LOG(ERR, NTNIC,
     850                 :            :                                 "Failed to allocated buffer array for hw-queue %p, total size %"
     851                 :            :                                 PRIu32 ", elements %i",
     852                 :            :                                 hwq->pkt_buffers, size, num_descr);
     853                 :          0 :                         rte_free(virt);
     854                 :          0 :                         return -1;
     855                 :            :                 }
     856                 :            : 
     857                 :          0 :                 size = buf_size * num_descr;
     858                 :            :                 void *virt_addr =
     859                 :          0 :                         rte_malloc_socket("pkt_buffer_pkts", size, 4096, eth_dev->data->numa_node);
     860                 :            : 
     861         [ #  # ]:          0 :                 if (!virt_addr) {
     862                 :          0 :                         NT_LOG(ERR, NTNIC,
     863                 :            :                                 "Failed allocate packet buffers for hw-queue %p, buf size %i, elements %i",
     864                 :            :                                 hwq->pkt_buffers, buf_size, num_descr);
     865                 :          0 :                         rte_free(hwq->pkt_buffers);
     866                 :          0 :                         rte_free(virt);
     867                 :          0 :                         return -1;
     868                 :            :                 }
     869                 :            : 
     870                 :          0 :                 res = nthw_vfio_dma_map(vf_num, virt_addr, &iova_addr, size);
     871                 :            : 
     872                 :          0 :                 NT_LOG(DBG, NTNIC,
     873                 :            :                         "VFIO MMAP res %i, virt %p, iova %016"
     874                 :            :                         PRIX64 ", vf_num %i, num pkt bufs %i, tot size %" PRIu32 "",
     875                 :            :                         res, virt_addr, iova_addr, vf_num, num_descr, size);
     876                 :            : 
     877         [ #  # ]:          0 :                 if (res != 0)
     878                 :            :                         return -1;
     879                 :            : 
     880                 :          0 :                 hwq->pkt_buffers_ctrl.virt_addr = virt_addr;
     881                 :          0 :                 hwq->pkt_buffers_ctrl.phys_addr = (void *)iova_addr;
     882                 :          0 :                 hwq->pkt_buffers_ctrl.len = size;
     883                 :            : 
     884         [ #  # ]:          0 :                 for (i = 0; i < num_descr; i++) {
     885                 :          0 :                         hwq->pkt_buffers[i].virt_addr =
     886                 :          0 :                                 (void *)((char *)virt_addr + ((uint64_t)(i) * buf_size));
     887                 :          0 :                         hwq->pkt_buffers[i].phys_addr =
     888                 :          0 :                                 (void *)(iova_addr + ((uint64_t)(i) * buf_size));
     889                 :          0 :                         hwq->pkt_buffers[i].len = buf_size;
     890                 :            :                 }
     891                 :            : 
     892                 :            :                 return 0;
     893                 :            :         }       /* End of: no optimal IOMMU mapping available */
     894                 :            : 
     895                 :          0 :         res = nthw_vfio_dma_map(vf_num, virt, &iova_addr, ONE_G_SIZE);
     896                 :            : 
     897         [ #  # ]:          0 :         if (res != 0) {
     898                 :          0 :                 NT_LOG(ERR, NTNIC, "VFIO MMAP FAILED! res %i, vf_num %i", res, vf_num);
     899                 :          0 :                 return -1;
     900                 :            :         }
     901                 :            : 
     902                 :          0 :         hwq->vf_num = vf_num;
     903                 :          0 :         hwq->virt_queues_ctrl.virt_addr = virt;
     904                 :          0 :         hwq->virt_queues_ctrl.phys_addr = (void *)(iova_addr);
     905                 :          0 :         hwq->virt_queues_ctrl.len = ONE_G_SIZE;
     906                 :          0 :         iova_addr += 0x100000;
     907                 :            : 
     908                 :          0 :         hwq->pkt_buffers_ctrl.virt_addr = NULL;
     909                 :          0 :         hwq->pkt_buffers_ctrl.phys_addr = NULL;
     910                 :          0 :         hwq->pkt_buffers_ctrl.len = 0;
     911                 :            : 
     912                 :          0 :         NT_LOG(DBG, NTNIC,
     913                 :            :                 "VFIO MMAP: virt_addr=%p phys_addr=%p size=%" PRIX32 " hpa=%" PRIX64 "",
     914                 :            :                 hwq->virt_queues_ctrl.virt_addr, hwq->virt_queues_ctrl.phys_addr,
     915                 :            :                 hwq->virt_queues_ctrl.len, rte_malloc_virt2iova(hwq->virt_queues_ctrl.virt_addr));
     916                 :            : 
     917                 :          0 :         size = num_descr * sizeof(struct nthw_memory_descriptor);
     918                 :          0 :         hwq->pkt_buffers =
     919                 :          0 :                 rte_zmalloc_socket("rx_pkt_buffers", size, 64, eth_dev->data->numa_node);
     920                 :            : 
     921         [ #  # ]:          0 :         if (!hwq->pkt_buffers) {
     922                 :          0 :                 NT_LOG(ERR, NTNIC,
     923                 :            :                         "Failed to allocated buffer array for hw-queue %p, total size %"
     924                 :            :                         PRIu32 ", elements %i",
     925                 :            :                         hwq->pkt_buffers, size, num_descr);
     926                 :          0 :                 rte_free(virt);
     927                 :          0 :                 return -1;
     928                 :            :         }
     929                 :            : 
     930                 :          0 :         void *virt_addr = (void *)((uint64_t)virt + 0x100000);
     931                 :            : 
     932         [ #  # ]:          0 :         for (i = 0; i < num_descr; i++) {
     933                 :          0 :                 hwq->pkt_buffers[i].virt_addr =
     934                 :          0 :                         (void *)((char *)virt_addr + ((uint64_t)(i) * buf_size));
     935                 :          0 :                 hwq->pkt_buffers[i].phys_addr = (void *)(iova_addr + ((uint64_t)(i) * buf_size));
     936                 :          0 :                 hwq->pkt_buffers[i].len = buf_size;
     937                 :            :         }
     938                 :            : 
     939                 :            :         return 0;
     940                 :            : }
     941                 :            : 
     942                 :            : static void release_hw_virtio_queues(struct hwq_s *hwq)
     943                 :            : {
     944         [ #  # ]:          0 :         if (!hwq || hwq->vf_num == 0)
     945                 :            :                 return;
     946                 :            : 
     947                 :          0 :         hwq->vf_num = 0;
     948                 :            : }
     949                 :            : 
     950                 :          0 : static int deallocate_hw_virtio_queues(struct hwq_s *hwq)
     951                 :            : {
     952                 :          0 :         int vf_num = hwq->vf_num;
     953                 :            : 
     954                 :          0 :         void *virt = hwq->virt_queues_ctrl.virt_addr;
     955                 :            : 
     956                 :          0 :         int res = nthw_vfio_dma_unmap(vf_num, hwq->virt_queues_ctrl.virt_addr,
     957                 :          0 :                         (uint64_t)hwq->virt_queues_ctrl.phys_addr, hwq->virt_queues_ctrl.len);
     958                 :            : 
     959         [ #  # ]:          0 :         if (res != 0) {
     960                 :          0 :                 NT_LOG(ERR, NTNIC, "VFIO UNMMAP FAILED! res %i, vf_num %i", res, vf_num);
     961                 :          0 :                 return -1;
     962                 :            :         }
     963                 :            : 
     964         [ #  # ]:          0 :         if (hwq->pkt_buffers_ctrl.virt_addr != NULL &&
     965         [ #  # ]:          0 :                         hwq->pkt_buffers_ctrl.phys_addr != NULL &&
     966         [ #  # ]:          0 :                         hwq->pkt_buffers_ctrl.len > 0) {
     967                 :          0 :                 int res = nthw_vfio_dma_unmap(vf_num,
     968                 :            :                                 hwq->pkt_buffers_ctrl.virt_addr,
     969                 :            :                                 (uint64_t)hwq->pkt_buffers_ctrl.phys_addr,
     970                 :            :                                 hwq->pkt_buffers_ctrl.len);
     971                 :            : 
     972         [ #  # ]:          0 :                 if (res != 0) {
     973                 :          0 :                         NT_LOG(ERR, NTNIC, "VFIO UNMMAP FAILED! res %i, vf_num %i", res, vf_num);
     974                 :          0 :                         return -1;
     975                 :            :                 }
     976                 :            :         }
     977                 :            : 
     978                 :            :         release_hw_virtio_queues(hwq);
     979                 :          0 :         rte_free(hwq->pkt_buffers);
     980                 :          0 :         rte_free(virt);
     981                 :          0 :         return 0;
     982                 :            : }
     983                 :            : 
     984                 :          0 : static void eth_tx_queue_release(struct rte_eth_dev *eth_dev, uint16_t queue_id)
     985                 :            : {
     986                 :          0 :         struct pmd_internals *internals = eth_dev->data->dev_private;
     987                 :          0 :         struct ntnic_tx_queue *tx_q = &internals->txq_scg[queue_id];
     988                 :            : 
     989                 :            :         /* Stop the HW queue and free its state before the rings are unmapped */
     990   [ #  #  #  # ]:          0 :         if (sg_ops != NULL && tx_q->vq != NULL) {
     991                 :          0 :                 sg_ops->nthw_release_mngd_tx_virt_queue(tx_q->vq);
     992                 :          0 :                 tx_q->vq = NULL;
     993                 :            :         }
     994                 :            : 
     995                 :          0 :         deallocate_hw_virtio_queues(&tx_q->hwq);
     996                 :          0 : }
     997                 :            : 
     998                 :          0 : static void eth_rx_queue_release(struct rte_eth_dev *eth_dev, uint16_t queue_id)
     999                 :            : {
    1000                 :          0 :         struct pmd_internals *internals = eth_dev->data->dev_private;
    1001                 :          0 :         struct ntnic_rx_queue *rx_q = &internals->rxq_scg[queue_id];
    1002                 :            : 
    1003                 :            :         /* Stop the HW queue and free its state before the rings are unmapped */
    1004   [ #  #  #  # ]:          0 :         if (sg_ops != NULL && rx_q->vq != NULL) {
    1005                 :          0 :                 sg_ops->nthw_release_mngd_rx_virt_queue(rx_q->vq);
    1006                 :          0 :                 rx_q->vq = NULL;
    1007                 :            :         }
    1008                 :            : 
    1009                 :          0 :         deallocate_hw_virtio_queues(&rx_q->hwq);
    1010                 :          0 : }
    1011                 :            : 
    1012                 :            : static int num_queues_allocated;
    1013                 :            : 
    1014                 :            : /* Returns num queue starting at returned queue num or -1 on fail */
    1015                 :          0 : static int allocate_queue(int num)
    1016                 :            : {
    1017                 :          0 :         int next_free = num_queues_allocated;
    1018                 :          0 :         NT_LOG_DBGX(DBG, NTNIC, "num_queues_allocated=%i, New queues=%i, Max queues=%d",
    1019                 :            :                 num_queues_allocated, num, MAX_TOTAL_QUEUES);
    1020                 :            : 
    1021         [ #  # ]:          0 :         if (num_queues_allocated + num > MAX_TOTAL_QUEUES)
    1022                 :            :                 return -1;
    1023                 :            : 
    1024                 :          0 :         num_queues_allocated += num;
    1025                 :          0 :         return next_free;
    1026                 :            : }
    1027                 :            : 
    1028                 :          0 : static int eth_rx_scg_queue_setup(struct rte_eth_dev *eth_dev,
    1029                 :            :         uint16_t rx_queue_id,
    1030                 :            :         uint16_t nb_rx_desc __rte_unused,
    1031                 :            :         unsigned int socket_id __rte_unused,
    1032                 :            :         const struct rte_eth_rxconf *rx_conf,
    1033                 :            :         struct rte_mempool *mb_pool)
    1034                 :            : {
    1035                 :          0 :         NT_LOG_DBGX(DBG, NTNIC, "Rx queue setup");
    1036                 :            :         struct rte_pktmbuf_pool_private *mbp_priv;
    1037                 :          0 :         struct pmd_internals *internals = eth_dev->data->dev_private;
    1038                 :          0 :         struct ntnic_rx_queue *rx_q = &internals->rxq_scg[rx_queue_id];
    1039                 :          0 :         struct drv_s *p_drv = internals->p_drv;
    1040                 :            :         struct ntdrv_4ga_s *p_nt_drv = &p_drv->ntdrv;
    1041                 :            : 
    1042         [ #  # ]:          0 :         if (sg_ops == NULL) {
    1043                 :          0 :                 NT_LOG_DBGX(DBG, NTNIC, "SG module is not initialized");
    1044                 :          0 :                 return 0;
    1045                 :            :         }
    1046                 :            : 
    1047         [ #  # ]:          0 :         if (internals->type == PORT_TYPE_OVERRIDE) {
    1048                 :          0 :                 rx_q->mb_pool = mb_pool;
    1049                 :          0 :                 eth_dev->data->rx_queues[rx_queue_id] = rx_q;
    1050         [ #  # ]:          0 :                 mbp_priv = rte_mempool_get_priv(rx_q->mb_pool);
    1051                 :          0 :                 rx_q->buf_size = (uint16_t)(mbp_priv->mbuf_data_room_size - RTE_PKTMBUF_HEADROOM);
    1052                 :          0 :                 rx_q->enabled = 1;
    1053                 :          0 :                 return 0;
    1054                 :            :         }
    1055                 :            : 
    1056                 :          0 :         NT_LOG(DBG, NTNIC, "(%" PRIu32 ") NTNIC RX OVS-SW queue setup: queue id %"
    1057                 :            :                 PRIu16 ", hw queue index %i",
    1058                 :            :                 internals->port, rx_queue_id, rx_q->queue.hw_id);
    1059                 :            : 
    1060         [ #  # ]:          0 :         rx_q->mb_pool = mb_pool;
    1061                 :            : 
    1062                 :            :         mbp_priv = rte_mempool_get_priv(rx_q->mb_pool);
    1063                 :          0 :         rx_q->buf_size = (uint16_t)(mbp_priv->mbuf_data_room_size - RTE_PKTMBUF_HEADROOM);
    1064                 :          0 :         rx_q->enabled = !rx_conf->rx_deferred_start;
    1065                 :          0 :         rx_q->rx_deferred_start = rx_conf->rx_deferred_start;
    1066                 :            : 
    1067         [ #  # ]:          0 :         if (allocate_hw_virtio_queues(eth_dev, EXCEPTION_PATH_HID, &rx_q->hwq,
    1068                 :            :                         SG_NB_HW_RX_DESCRIPTORS, SG_HW_RX_PKT_BUFFER_SIZE) < 0)
    1069                 :            :                 return -1;
    1070                 :            : 
    1071                 :          0 :         rx_q->nb_hw_rx_descr = SG_NB_HW_RX_DESCRIPTORS;
    1072                 :            : 
    1073                 :          0 :         rx_q->profile = p_drv->ntdrv.adapter_info.fpga_info.profile;
    1074                 :            : 
    1075                 :          0 :         rx_q->vq =
    1076                 :          0 :                 sg_ops->nthw_setup_mngd_rx_virt_queue(p_nt_drv->adapter_info.fpga_info.mp_nthw_dbs,
    1077                 :          0 :                         rx_q->queue.hw_id,   /* index */
    1078                 :            :                         rx_q->nb_hw_rx_descr,
    1079                 :            :                         EXCEPTION_PATH_HID,     /* host_id */
    1080                 :            :                         1,      /* header NT DVIO header for exception path */
    1081                 :            :                         &rx_q->hwq.virt_queues_ctrl,
    1082                 :            :                         rx_q->hwq.pkt_buffers,
    1083                 :            :                         SPLIT_RING,
    1084                 :            :                         -1,
    1085                 :          0 :                         rx_conf->rx_deferred_start);
    1086                 :            : 
    1087         [ #  # ]:          0 :         if (rx_q->vq == NULL) {
    1088                 :          0 :                 NT_LOG(ERR, NTNIC, "(%u) NTNIC RX queue %u virt queue setup failed",
    1089                 :            :                         internals->port, rx_queue_id);
    1090                 :          0 :                 deallocate_hw_virtio_queues(&rx_q->hwq);
    1091                 :          0 :                 return -1;
    1092                 :            :         }
    1093                 :            : 
    1094                 :            :         /*
    1095                 :            :          * Hand the queue to ethdev only once it is fully set up. ethdev does not
    1096                 :            :          * clear the entry when setup fails, and the release callback would then
    1097                 :            :          * tear down rings that were already freed above.
    1098                 :            :          */
    1099                 :          0 :         eth_dev->data->rx_queues[rx_queue_id] = rx_q;
    1100                 :            : 
    1101                 :          0 :         NT_LOG(DBG, NTNIC, "(%" PRIu32 ") NTNIC RX OVS-SW queues successfully setup",
    1102                 :            :                 internals->port);
    1103                 :            : 
    1104                 :          0 :         return 0;
    1105                 :            : }
    1106                 :            : 
    1107                 :          0 : static int eth_tx_scg_queue_setup(struct rte_eth_dev *eth_dev,
    1108                 :            :         uint16_t tx_queue_id,
    1109                 :            :         uint16_t nb_tx_desc __rte_unused,
    1110                 :            :         unsigned int socket_id __rte_unused,
    1111                 :            :         const struct rte_eth_txconf *tx_conf)
    1112                 :            : {
    1113                 :          0 :         const struct port_ops *port_ops = nthw_get_port_ops();
    1114                 :            : 
    1115         [ #  # ]:          0 :         if (port_ops == NULL) {
    1116                 :          0 :                 NT_LOG_DBGX(ERR, NTNIC, "Link management module uninitialized");
    1117                 :          0 :                 return -1;
    1118                 :            :         }
    1119                 :            : 
    1120                 :          0 :         NT_LOG_DBGX(DBG, NTNIC, "Tx queue setup");
    1121                 :          0 :         struct pmd_internals *internals = eth_dev->data->dev_private;
    1122                 :          0 :         struct drv_s *p_drv = internals->p_drv;
    1123                 :            :         struct ntdrv_4ga_s *p_nt_drv = &p_drv->ntdrv;
    1124                 :          0 :         struct ntnic_tx_queue *tx_q = &internals->txq_scg[tx_queue_id];
    1125                 :            : 
    1126         [ #  # ]:          0 :         if (internals->type == PORT_TYPE_OVERRIDE) {
    1127                 :          0 :                 eth_dev->data->tx_queues[tx_queue_id] = tx_q;
    1128                 :          0 :                 return 0;
    1129                 :            :         }
    1130                 :            : 
    1131         [ #  # ]:          0 :         if (sg_ops == NULL) {
    1132                 :          0 :                 NT_LOG_DBGX(DBG, NTNIC, "SG module is not initialized");
    1133                 :          0 :                 return 0;
    1134                 :            :         }
    1135                 :            : 
    1136                 :          0 :         NT_LOG(DBG, NTNIC, "(%" PRIu32 ") NTNIC TX OVS-SW queue setup: queue id %" PRIu16 ", hw queue index %i",
    1137                 :            :                 tx_q->port, tx_queue_id, tx_q->queue.hw_id);
    1138                 :            : 
    1139         [ #  # ]:          0 :         if (tx_queue_id > internals->nb_tx_queues) {
    1140                 :          0 :                 NT_LOG(ERR, NTNIC, "Error invalid tx queue id");
    1141                 :          0 :                 return -1;
    1142                 :            :         }
    1143                 :            : 
    1144                 :            :         /* Calculate target ID for HW  - to be used in NTDVIO0 header bypass_port */
    1145         [ #  # ]:          0 :         if (tx_q->rss_target_id >= 0) {
    1146                 :            :                 /* bypass to a multiqueue port - qsl-hsh index */
    1147                 :          0 :                 tx_q->target_id = tx_q->rss_target_id + 0x90;
    1148                 :            : 
    1149         [ #  # ]:          0 :         } else if (internals->vpq[tx_queue_id].hw_id > -1) {
    1150                 :            :                 /* virtual port - queue index */
    1151                 :          0 :                 tx_q->target_id = internals->vpq[tx_queue_id].hw_id;
    1152                 :            : 
    1153                 :            :         } else {
    1154                 :            :                 /* Phy port - phy port identifier */
    1155                 :            :                 /* output/bypass to MAC */
    1156                 :          0 :                 tx_q->target_id = (int)(tx_q->port + 0x80);
    1157                 :            :         }
    1158                 :            : 
    1159         [ #  # ]:          0 :         if (allocate_hw_virtio_queues(eth_dev, EXCEPTION_PATH_HID, &tx_q->hwq,
    1160                 :            :                         SG_NB_HW_TX_DESCRIPTORS, SG_HW_TX_PKT_BUFFER_SIZE) < 0) {
    1161                 :            :                 return -1;
    1162                 :            :         }
    1163                 :            : 
    1164                 :          0 :         tx_q->nb_hw_tx_descr = SG_NB_HW_TX_DESCRIPTORS;
    1165                 :            : 
    1166                 :          0 :         tx_q->profile = p_drv->ntdrv.adapter_info.fpga_info.profile;
    1167                 :            : 
    1168                 :            :         uint32_t port, header;
    1169                 :          0 :         port = tx_q->port;   /* transmit port */
    1170                 :            :         header = 0;     /* header type VirtIO-Net */
    1171                 :            : 
    1172                 :          0 :         tx_q->vq =
    1173                 :          0 :                 sg_ops->nthw_setup_mngd_tx_virt_queue(p_nt_drv->adapter_info.fpga_info.mp_nthw_dbs,
    1174                 :          0 :                         tx_q->queue.hw_id,   /* index */
    1175                 :            :                         tx_q->nb_hw_tx_descr,        /* queue size */
    1176                 :            :                         EXCEPTION_PATH_HID,     /* host_id always VF4 */
    1177                 :            :                         port,
    1178                 :            :                         /*
    1179                 :            :                          * in_port - in vswitch mode has
    1180                 :            :                          * to move tx port from OVS excep.
    1181                 :            :                          * away from VM tx port,
    1182                 :            :                          * because of QoS is matched by port id!
    1183                 :            :                          */
    1184                 :            :                         tx_q->port + 128,
    1185                 :            :                         header,
    1186                 :            :                         &tx_q->hwq.virt_queues_ctrl,
    1187                 :            :                         tx_q->hwq.pkt_buffers,
    1188                 :            :                         SPLIT_RING,
    1189                 :            :                         -1,
    1190                 :            :                         IN_ORDER,
    1191                 :          0 :                         tx_conf->tx_deferred_start);
    1192                 :            : 
    1193         [ #  # ]:          0 :         if (tx_q->vq == NULL) {
    1194                 :          0 :                 NT_LOG(ERR, NTNIC, "(%u) NTNIC TX queue %u virt queue setup failed",
    1195                 :            :                         tx_q->port, tx_queue_id);
    1196                 :          0 :                 deallocate_hw_virtio_queues(&tx_q->hwq);
    1197                 :          0 :                 return -1;
    1198                 :            :         }
    1199                 :            : 
    1200                 :            :         /* See eth_rx_scg_queue_setup() */
    1201                 :          0 :         eth_dev->data->tx_queues[tx_queue_id] = tx_q;
    1202                 :            : 
    1203                 :          0 :         tx_q->enabled = !tx_conf->tx_deferred_start;
    1204                 :          0 :         tx_q->tx_deferred_start = tx_conf->tx_deferred_start;
    1205                 :            : 
    1206                 :          0 :         NT_LOG(DBG, NTNIC, "(%" PRIu32 ") NTNIC TX OVS-SW queues successfully setup",
    1207                 :            :                 internals->port);
    1208                 :            : 
    1209         [ #  # ]:          0 :         if (internals->type == PORT_TYPE_PHYSICAL) {
    1210                 :          0 :                 struct adapter_info_s *p_adapter_info = &internals->p_drv->ntdrv.adapter_info;
    1211                 :          0 :                 NT_LOG(DBG, NTNIC, "Port %i is ready for data. Enable port",
    1212                 :            :                         internals->n_intf_no);
    1213                 :          0 :                 port_ops->set_adm_state(p_adapter_info, internals->n_intf_no, true);
    1214                 :            :         }
    1215                 :            : 
    1216                 :            :         return 0;
    1217                 :            : }
    1218                 :            : 
    1219                 :          0 : static int dev_set_mtu_inline(struct rte_eth_dev *eth_dev, uint16_t mtu)
    1220                 :            : {
    1221                 :          0 :         const struct profile_inline_ops *profile_inline_ops = nthw_get_profile_inline_ops();
    1222                 :            : 
    1223         [ #  # ]:          0 :         if (profile_inline_ops == NULL) {
    1224                 :          0 :                 NT_LOG_DBGX(ERR, NTNIC, "profile_inline module uninitialized");
    1225                 :          0 :                 return -1;
    1226                 :            :         }
    1227                 :            : 
    1228                 :          0 :         struct pmd_internals *internals = (struct pmd_internals *)eth_dev->data->dev_private;
    1229                 :            : 
    1230                 :          0 :         struct flow_eth_dev *flw_dev = internals->flw_dev;
    1231                 :            :         int ret = -1;
    1232                 :            : 
    1233   [ #  #  #  # ]:          0 :         if (internals->type == PORT_TYPE_PHYSICAL && mtu >= MIN_MTU_INLINE && mtu <= MAX_MTU)
    1234                 :          0 :                 ret = profile_inline_ops->nthw_flow_set_mtu_inline(flw_dev, internals->port, mtu);
    1235                 :            : 
    1236         [ #  # ]:          0 :         return ret ? -EINVAL : 0;
    1237                 :            : }
    1238                 :            : 
    1239                 :          0 : static int eth_rx_queue_start(struct rte_eth_dev *eth_dev, uint16_t rx_queue_id)
    1240                 :            : {
    1241         [ #  # ]:          0 :         if (sg_ops == NULL) {
    1242                 :          0 :                 NT_LOG_DBGX(DBG, NTNIC, "SG module is not initialized");
    1243                 :          0 :                 return -1;
    1244                 :            :         }
    1245                 :            : 
    1246                 :          0 :         struct pmd_internals *internals = eth_dev->data->dev_private;
    1247                 :          0 :         struct drv_s *p_drv = internals->p_drv;
    1248                 :            :         struct ntdrv_4ga_s *p_nt_drv = &p_drv->ntdrv;
    1249                 :          0 :         nthw_dbs_t *p_nthw_dbs = p_nt_drv->adapter_info.fpga_info.mp_nthw_dbs;
    1250                 :          0 :         struct ntnic_rx_queue *rx_q = &internals->rxq_scg[rx_queue_id];
    1251                 :          0 :         int index = rx_q->queue.hw_id;
    1252                 :            : 
    1253         [ #  # ]:          0 :         if (sg_ops->nthw_switch_rx_virt_queue(p_nthw_dbs, index, 1) != 0) {
    1254                 :          0 :                 NT_LOG_DBGX(DBG, NTNIC, "Failed to start Rx queue #%d", index);
    1255                 :          0 :                 return -1;
    1256                 :            :         }
    1257                 :            : 
    1258                 :          0 :         rx_q->enabled = 1;
    1259                 :          0 :         eth_dev->data->rx_queue_state[rx_queue_id] = RTE_ETH_QUEUE_STATE_STARTED;
    1260                 :          0 :         return 0;
    1261                 :            : }
    1262                 :            : 
    1263                 :          0 : static int eth_rx_queue_stop(struct rte_eth_dev *eth_dev, uint16_t rx_queue_id)
    1264                 :            : {
    1265         [ #  # ]:          0 :         if (sg_ops == NULL) {
    1266                 :          0 :                 NT_LOG_DBGX(DBG, NTNIC, "SG module is not initialized");
    1267                 :          0 :                 return -1;
    1268                 :            :         }
    1269                 :            : 
    1270                 :          0 :         struct pmd_internals *internals = eth_dev->data->dev_private;
    1271                 :          0 :         struct drv_s *p_drv = internals->p_drv;
    1272                 :            :         struct ntdrv_4ga_s *p_nt_drv = &p_drv->ntdrv;
    1273                 :          0 :         nthw_dbs_t *p_nthw_dbs = p_nt_drv->adapter_info.fpga_info.mp_nthw_dbs;
    1274                 :          0 :         struct ntnic_rx_queue *rx_q = &internals->rxq_scg[rx_queue_id];
    1275                 :          0 :         int index = rx_q->queue.hw_id;
    1276                 :            : 
    1277         [ #  # ]:          0 :         if (sg_ops->nthw_switch_rx_virt_queue(p_nthw_dbs, index, 0) != 0) {
    1278                 :          0 :                 NT_LOG_DBGX(DBG, NTNIC, "Failed to stop Rx queue #%d", index);
    1279                 :          0 :                 return -1;
    1280                 :            :         }
    1281                 :            : 
    1282                 :          0 :         rx_q->enabled = 0;
    1283                 :          0 :         eth_dev->data->rx_queue_state[rx_queue_id] = RTE_ETH_QUEUE_STATE_STOPPED;
    1284                 :          0 :         return 0;
    1285                 :            : }
    1286                 :            : 
    1287                 :          0 : static int eth_tx_queue_start(struct rte_eth_dev *eth_dev, uint16_t tx_queue_id)
    1288                 :            : {
    1289         [ #  # ]:          0 :         if (sg_ops == NULL) {
    1290                 :          0 :                 NT_LOG_DBGX(DBG, NTNIC, "SG module is not initialized");
    1291                 :          0 :                 return -1;
    1292                 :            :         }
    1293                 :            : 
    1294                 :          0 :         struct pmd_internals *internals = eth_dev->data->dev_private;
    1295                 :          0 :         struct drv_s *p_drv = internals->p_drv;
    1296                 :            :         struct ntdrv_4ga_s *p_nt_drv = &p_drv->ntdrv;
    1297                 :          0 :         nthw_dbs_t *p_nthw_dbs = p_nt_drv->adapter_info.fpga_info.mp_nthw_dbs;
    1298                 :          0 :         struct ntnic_tx_queue *tx_q = &internals->txq_scg[tx_queue_id];
    1299                 :          0 :         int index = tx_q->queue.hw_id;
    1300                 :            : 
    1301         [ #  # ]:          0 :         if (sg_ops->nthw_switch_tx_virt_queue(p_nthw_dbs, index, 1) != 0) {
    1302                 :          0 :                 NT_LOG_DBGX(DBG, NTNIC, "Failed to start Tx queue #%d", index);
    1303                 :          0 :                 return -1;
    1304                 :            :         }
    1305                 :            : 
    1306                 :          0 :         tx_q->enabled = 1;
    1307                 :          0 :         eth_dev->data->tx_queue_state[tx_queue_id] = RTE_ETH_QUEUE_STATE_STARTED;
    1308                 :          0 :         return 0;
    1309                 :            : }
    1310                 :            : 
    1311                 :          0 : static int eth_tx_queue_stop(struct rte_eth_dev *eth_dev, uint16_t tx_queue_id)
    1312                 :            : {
    1313         [ #  # ]:          0 :         if (sg_ops == NULL) {
    1314                 :          0 :                 NT_LOG_DBGX(DBG, NTNIC, "SG module is not initialized");
    1315                 :          0 :                 return -1;
    1316                 :            :         }
    1317                 :            : 
    1318                 :          0 :         struct pmd_internals *internals = eth_dev->data->dev_private;
    1319                 :          0 :         struct drv_s *p_drv = internals->p_drv;
    1320                 :            :         struct ntdrv_4ga_s *p_nt_drv = &p_drv->ntdrv;
    1321                 :          0 :         nthw_dbs_t *p_nthw_dbs = p_nt_drv->adapter_info.fpga_info.mp_nthw_dbs;
    1322                 :          0 :         struct ntnic_tx_queue *tx_q = &internals->txq_scg[tx_queue_id];
    1323                 :          0 :         int index = tx_q->queue.hw_id;
    1324                 :            : 
    1325         [ #  # ]:          0 :         if (sg_ops->nthw_switch_tx_virt_queue(p_nthw_dbs, index, 0) != 0) {
    1326                 :          0 :                 NT_LOG_DBGX(DBG, NTNIC, "Failed to stop Tx queue #%d", index);
    1327                 :          0 :                 return -1;
    1328                 :            :         }
    1329                 :            : 
    1330                 :          0 :         tx_q->enabled = 0;
    1331                 :          0 :         eth_dev->data->tx_queue_state[tx_queue_id] = RTE_ETH_QUEUE_STATE_STOPPED;
    1332                 :          0 :         return 0;
    1333                 :            : }
    1334                 :            : 
    1335                 :            : static int
    1336                 :          0 : eth_mac_addr_add(struct rte_eth_dev *eth_dev,
    1337                 :            :         struct rte_ether_addr *mac_addr,
    1338                 :            :         uint32_t index,
    1339                 :            :         uint32_t vmdq __rte_unused)
    1340                 :            : {
    1341                 :          0 :         struct rte_ether_addr *const eth_addrs = eth_dev->data->mac_addrs;
    1342                 :            : 
    1343                 :            :         RTE_ASSERT(index < NUM_MAC_ADDRS_PER_PORT);
    1344                 :            : 
    1345         [ #  # ]:          0 :         if (index >= NUM_MAC_ADDRS_PER_PORT) {
    1346                 :          0 :                 const struct pmd_internals *const internals =
    1347                 :            :                         eth_dev->data->dev_private;
    1348                 :          0 :                 NT_LOG_DBGX(DBG, NTNIC, "Port %i: illegal index %u (>= %u)",
    1349                 :            :                         internals->n_intf_no, index, NUM_MAC_ADDRS_PER_PORT);
    1350                 :          0 :                 return -1;
    1351                 :            :         }
    1352                 :            : 
    1353                 :          0 :         eth_addrs[index] = *mac_addr;
    1354                 :            : 
    1355                 :          0 :         return 0;
    1356                 :            : }
    1357                 :            : 
    1358                 :            : static int
    1359                 :          0 : eth_mac_addr_set(struct rte_eth_dev *dev, struct rte_ether_addr *mac_addr)
    1360                 :            : {
    1361                 :          0 :         struct rte_ether_addr *const eth_addrs = dev->data->mac_addrs;
    1362                 :            : 
    1363                 :          0 :         eth_addrs[0U] = *mac_addr;
    1364                 :            : 
    1365                 :          0 :         return 0;
    1366                 :            : }
    1367                 :            : 
    1368                 :            : static int
    1369                 :          0 : eth_set_mc_addr_list(struct rte_eth_dev *eth_dev,
    1370                 :            :         struct rte_ether_addr *mc_addr_set,
    1371                 :            :         uint32_t nb_mc_addr)
    1372                 :            : {
    1373                 :          0 :         struct pmd_internals *const internals = eth_dev->data->dev_private;
    1374                 :          0 :         struct rte_ether_addr *const mc_addrs = internals->mc_addrs;
    1375                 :            :         size_t i;
    1376                 :            : 
    1377         [ #  # ]:          0 :         if (nb_mc_addr >= NUM_MULTICAST_ADDRS_PER_PORT) {
    1378                 :          0 :                 NT_LOG_DBGX(DBG, NTNIC,
    1379                 :            :                         "Port %i: too many multicast addresses %u (>= %u)",
    1380                 :            :                         internals->n_intf_no, nb_mc_addr, NUM_MULTICAST_ADDRS_PER_PORT);
    1381                 :          0 :                 return -1;
    1382                 :            :         }
    1383                 :            : 
    1384         [ #  # ]:          0 :         for (i = 0U; i < NUM_MULTICAST_ADDRS_PER_PORT; i++)
    1385         [ #  # ]:          0 :                 if (i < nb_mc_addr)
    1386                 :          0 :                         mc_addrs[i] = mc_addr_set[i];
    1387                 :            : 
    1388                 :            :                 else
    1389                 :          0 :                         memset(&mc_addrs[i], 0, sizeof(mc_addrs[i]));
    1390                 :            : 
    1391                 :            :         return 0;
    1392                 :            : }
    1393                 :            : 
    1394                 :            : static int
    1395                 :          0 : eth_dev_configure(struct rte_eth_dev *eth_dev)
    1396                 :            : {
    1397                 :          0 :         NT_LOG_DBGX(DBG, NTNIC, "Called for eth_dev %p", eth_dev);
    1398                 :            : 
    1399                 :            :         /* The device is ALWAYS running promiscuous mode. */
    1400                 :          0 :         eth_dev->data->promiscuous ^= ~eth_dev->data->promiscuous;
    1401                 :          0 :         return 0;
    1402                 :            : }
    1403                 :            : 
    1404                 :            : static int
    1405                 :          0 : eth_dev_start(struct rte_eth_dev *eth_dev)
    1406                 :            : {
    1407                 :          0 :         const struct port_ops *port_ops = nthw_get_port_ops();
    1408                 :            : 
    1409         [ #  # ]:          0 :         if (port_ops == NULL) {
    1410                 :          0 :                 NT_LOG(ERR, NTNIC, "Link management module uninitialized");
    1411                 :          0 :                 return -1;
    1412                 :            :         }
    1413                 :            : 
    1414                 :          0 :         eth_dev->flow_fp_ops = nthw_get_dev_fp_flow_ops();
    1415                 :          0 :         struct pmd_internals *internals = eth_dev->data->dev_private;
    1416                 :            : 
    1417                 :          0 :         const int n_intf_no = internals->n_intf_no;
    1418                 :          0 :         struct adapter_info_s *p_adapter_info = &internals->p_drv->ntdrv.adapter_info;
    1419                 :            : 
    1420                 :          0 :         NT_LOG_DBGX(DBG, NTNIC, "Port %i", internals->n_intf_no);
    1421                 :            : 
    1422                 :            :         /* Start queues */
    1423                 :            :         uint q;
    1424                 :            : 
    1425         [ #  # ]:          0 :         for (q = 0; q < internals->nb_rx_queues; q++)
    1426         [ #  # ]:          0 :                 if (!internals->rxq_scg[q].rx_deferred_start)
    1427                 :          0 :                         eth_rx_queue_start(eth_dev, q);
    1428                 :            : 
    1429         [ #  # ]:          0 :         for (q = 0; q < internals->nb_tx_queues; q++)
    1430         [ #  # ]:          0 :                 if (!internals->txq_scg[q].tx_deferred_start)
    1431                 :          0 :                         eth_tx_queue_start(eth_dev, q);
    1432                 :            : 
    1433         [ #  # ]:          0 :         if (internals->type == PORT_TYPE_VIRTUAL || internals->type == PORT_TYPE_OVERRIDE) {
    1434                 :          0 :                 eth_dev->data->dev_link.link_status = RTE_ETH_LINK_UP;
    1435                 :            : 
    1436                 :            :         } else {
    1437                 :            :                 /* Enable the port */
    1438                 :          0 :                 port_ops->set_adm_state(p_adapter_info, internals->n_intf_no, true);
    1439                 :            : 
    1440                 :            :                 /*
    1441                 :            :                  * wait for link on port
    1442                 :            :                  * If application starts sending too soon before FPGA port is ready, garbage is
    1443                 :            :                  * produced
    1444                 :            :                  */
    1445                 :            :                 int loop = 0;
    1446                 :            : 
    1447         [ #  # ]:          0 :                 while (port_ops->get_link_status(p_adapter_info, n_intf_no) == RTE_ETH_LINK_DOWN) {
    1448                 :            :                         /* break out after 5 sec */
    1449         [ #  # ]:          0 :                         if (++loop >= 50) {
    1450                 :          0 :                                 NT_LOG_DBGX(DBG, NTNIC,
    1451                 :            :                                         "TIMEOUT No link on port %i (5sec timeout)",
    1452                 :            :                                         internals->n_intf_no);
    1453                 :          0 :                                 break;
    1454                 :            :                         }
    1455                 :            : 
    1456                 :          0 :                         nthw_os_wait_usec(100 * 1000);
    1457                 :            :                 }
    1458                 :            : 
    1459         [ #  # ]:          0 :                 if (internals->lpbk_mode) {
    1460         [ #  # ]:          0 :                         if (internals->lpbk_mode & 1 << 0) {
    1461                 :          0 :                                 port_ops->set_loopback_mode(p_adapter_info, n_intf_no,
    1462                 :            :                                         NT_LINK_LOOPBACK_HOST);
    1463                 :            :                         }
    1464                 :            : 
    1465         [ #  # ]:          0 :                         if (internals->lpbk_mode & 1 << 1) {
    1466                 :          0 :                                 port_ops->set_loopback_mode(p_adapter_info, n_intf_no,
    1467                 :            :                                         NT_LINK_LOOPBACK_LINE);
    1468                 :            :                         }
    1469                 :            :                 }
    1470                 :            :         }
    1471                 :            : 
    1472                 :            :         return 0;
    1473                 :            : }
    1474                 :            : 
    1475                 :            : static int
    1476                 :          0 : eth_dev_stop(struct rte_eth_dev *eth_dev)
    1477                 :            : {
    1478                 :          0 :         struct pmd_internals *internals = eth_dev->data->dev_private;
    1479                 :            : 
    1480                 :          0 :         NT_LOG_DBGX(DBG, NTNIC, "Port %i", internals->n_intf_no);
    1481                 :            : 
    1482         [ #  # ]:          0 :         if (internals->type != PORT_TYPE_VIRTUAL) {
    1483                 :            :                 uint q;
    1484                 :            : 
    1485         [ #  # ]:          0 :                 for (q = 0; q < internals->nb_rx_queues; q++)
    1486                 :          0 :                         eth_rx_queue_stop(eth_dev, q);
    1487                 :            : 
    1488         [ #  # ]:          0 :                 for (q = 0; q < internals->nb_tx_queues; q++)
    1489                 :          0 :                         eth_tx_queue_stop(eth_dev, q);
    1490                 :            :         }
    1491                 :            : 
    1492                 :          0 :         eth_dev->data->dev_link.link_status = RTE_ETH_LINK_DOWN;
    1493                 :          0 :         return 0;
    1494                 :            : }
    1495                 :            : 
    1496                 :            : static int
    1497                 :          0 : eth_dev_set_link_up(struct rte_eth_dev *eth_dev)
    1498                 :            : {
    1499                 :          0 :         const struct port_ops *port_ops = nthw_get_port_ops();
    1500                 :            : 
    1501         [ #  # ]:          0 :         if (port_ops == NULL) {
    1502                 :          0 :                 NT_LOG(ERR, NTNIC, "Link management module uninitialized");
    1503                 :          0 :                 return -1;
    1504                 :            :         }
    1505                 :            : 
    1506                 :          0 :         struct pmd_internals *const internals = eth_dev->data->dev_private;
    1507                 :            : 
    1508                 :          0 :         struct adapter_info_s *p_adapter_info = &internals->p_drv->ntdrv.adapter_info;
    1509                 :          0 :         const int port = internals->n_intf_no;
    1510                 :            : 
    1511         [ #  # ]:          0 :         if (internals->type == PORT_TYPE_VIRTUAL || internals->type == PORT_TYPE_OVERRIDE)
    1512                 :            :                 return 0;
    1513                 :            : 
    1514                 :            :         RTE_ASSERT(port >= 0 && port < NUM_ADAPTER_PORTS_MAX);
    1515                 :            : 
    1516                 :          0 :         port_ops->set_adm_state(p_adapter_info, port, true);
    1517                 :            : 
    1518                 :          0 :         return 0;
    1519                 :            : }
    1520                 :            : 
    1521                 :            : static int
    1522                 :          0 : eth_dev_set_link_down(struct rte_eth_dev *eth_dev)
    1523                 :            : {
    1524                 :          0 :         const struct port_ops *port_ops = nthw_get_port_ops();
    1525                 :            : 
    1526         [ #  # ]:          0 :         if (port_ops == NULL) {
    1527                 :          0 :                 NT_LOG(ERR, NTNIC, "Link management module uninitialized");
    1528                 :          0 :                 return -1;
    1529                 :            :         }
    1530                 :            : 
    1531                 :          0 :         struct pmd_internals *const internals = eth_dev->data->dev_private;
    1532                 :            : 
    1533                 :          0 :         struct adapter_info_s *p_adapter_info = &internals->p_drv->ntdrv.adapter_info;
    1534                 :          0 :         const int port = internals->n_intf_no;
    1535                 :            : 
    1536         [ #  # ]:          0 :         if (internals->type == PORT_TYPE_VIRTUAL || internals->type == PORT_TYPE_OVERRIDE)
    1537                 :            :                 return 0;
    1538                 :            : 
    1539                 :            :         RTE_ASSERT(port >= 0 && port < NUM_ADAPTER_PORTS_MAX);
    1540                 :            : 
    1541                 :          0 :         port_ops->set_link_status(p_adapter_info, port, false);
    1542                 :            : 
    1543                 :          0 :         return 0;
    1544                 :            : }
    1545                 :            : 
    1546                 :            : static void
    1547                 :          0 : drv_deinit(struct drv_s *p_drv)
    1548                 :            : {
    1549                 :          0 :         const struct profile_inline_ops *profile_inline_ops = nthw_get_profile_inline_ops();
    1550                 :            : 
    1551         [ #  # ]:          0 :         if (profile_inline_ops == NULL) {
    1552                 :          0 :                 NT_LOG_DBGX(ERR, NTNIC, "profile_inline module uninitialized");
    1553                 :          0 :                 return;
    1554                 :            :         }
    1555                 :            : 
    1556                 :          0 :         const struct adapter_ops *adapter_ops = nthw_get_adapter_ops();
    1557                 :            : 
    1558         [ #  # ]:          0 :         if (adapter_ops == NULL) {
    1559                 :          0 :                 NT_LOG(ERR, NTNIC, "Adapter module uninitialized");
    1560                 :          0 :                 return;
    1561                 :            :         }
    1562                 :            : 
    1563         [ #  # ]:          0 :         if (p_drv == NULL)
    1564                 :            :                 return;
    1565                 :            : 
    1566                 :            :         ntdrv_4ga_t *p_nt_drv = &p_drv->ntdrv;
    1567                 :            :         fpga_info_t *fpga_info = &p_nt_drv->adapter_info.fpga_info;
    1568                 :            : 
    1569                 :            :         /*
    1570                 :            :          * Mark the global pdrv for cleared. Used by some services to terminate.
    1571                 :            :          * 1 second to give the services a chance to see the termonation.
    1572                 :            :          */
    1573                 :          0 :         clear_pdrv(p_drv);
    1574                 :          0 :         nthw_os_wait_usec(1000000);
    1575                 :            : 
    1576                 :            :         /* stop statistics service */
    1577                 :          0 :         nthw_service_del(RTE_NTNIC_SERVICE_STAT);
    1578                 :            : 
    1579         [ #  # ]:          0 :         if (fpga_info->profile == FPGA_INFO_PROFILE_INLINE) {
    1580                 :          0 :                 nthw_service_del(RTE_NTNIC_SERVICE_FLM_UPDATE);
    1581                 :          0 :                 profile_inline_ops->flm_free_queues();
    1582                 :          0 :                 nthw_service_del(RTE_NTNIC_SERVICE_PORT_0_EVENT);
    1583                 :          0 :                 nthw_service_del(RTE_NTNIC_SERVICE_PORT_1_EVENT);
    1584                 :            :                 /* Free all local flm event queues */
    1585                 :          0 :                 nthw_flm_inf_sta_queue_free_all(FLM_INFO_LOCAL);
    1586                 :            :                 /* Free all remote flm event queues */
    1587                 :          0 :                 nthw_flm_inf_sta_queue_free_all(FLM_INFO_REMOTE);
    1588                 :            :                 /* Free all aged flow event queues */
    1589                 :          0 :                 nthw_flm_age_queue_free_all();
    1590                 :            :         }
    1591                 :            : 
    1592                 :            :         /* stop adapter */
    1593                 :          0 :         adapter_ops->deinit(&p_nt_drv->adapter_info);
    1594                 :            : 
    1595                 :            :         /* clean memory */
    1596                 :          0 :         rte_free(p_drv);
    1597                 :            :         p_drv = NULL;
    1598                 :            : }
    1599                 :            : 
    1600                 :            : static int
    1601                 :          0 : eth_dev_close(struct rte_eth_dev *eth_dev)
    1602                 :            : {
    1603                 :          0 :         struct pmd_internals *internals = eth_dev->data->dev_private;
    1604                 :          0 :         struct drv_s *p_drv = internals->p_drv;
    1605                 :            : 
    1606         [ #  # ]:          0 :         if (internals->type != PORT_TYPE_VIRTUAL) {
    1607                 :          0 :                 struct ntnic_rx_queue *rx_q = internals->rxq_scg;
    1608                 :          0 :                 struct ntnic_tx_queue *tx_q = internals->txq_scg;
    1609                 :            : 
    1610                 :            :                 uint q;
    1611                 :            : 
    1612         [ #  # ]:          0 :                 if (sg_ops != NULL) {
    1613         [ #  # ]:          0 :                         for (q = 0; q < internals->nb_rx_queues; q++) {
    1614                 :          0 :                                 sg_ops->nthw_release_mngd_rx_virt_queue(rx_q[q].vq);
    1615                 :          0 :                                 rx_q[q].vq = NULL;
    1616                 :            :                         }
    1617                 :            : 
    1618         [ #  # ]:          0 :                         for (q = 0; q < internals->nb_tx_queues; q++) {
    1619                 :          0 :                                 sg_ops->nthw_release_mngd_tx_virt_queue(tx_q[q].vq);
    1620                 :          0 :                                 tx_q[q].vq = NULL;
    1621                 :            :                         }
    1622                 :            :                 }
    1623                 :            :         }
    1624                 :            : 
    1625                 :          0 :         internals->p_drv = NULL;
    1626                 :            : 
    1627         [ #  # ]:          0 :         if (p_drv) {
    1628                 :            :                 /* decrease initialized ethernet devices */
    1629                 :          0 :                 p_drv->n_eth_dev_init_count--;
    1630                 :            : 
    1631                 :            :                 /*
    1632                 :            :                  * rte_pci_dev has no private member for p_drv
    1633                 :            :                  * wait until all rte_eth_dev's are closed - then close adapters via p_drv
    1634                 :            :                  */
    1635         [ #  # ]:          0 :                 if (!p_drv->n_eth_dev_init_count)
    1636                 :          0 :                         drv_deinit(p_drv);
    1637                 :            :         }
    1638                 :            : 
    1639                 :          0 :         return 0;
    1640                 :            : }
    1641                 :            : 
    1642                 :            : static int
    1643                 :          0 : eth_fw_version_get(struct rte_eth_dev *eth_dev, char *fw_version, size_t fw_size)
    1644                 :            : {
    1645                 :          0 :         struct pmd_internals *internals = eth_dev->data->dev_private;
    1646                 :            : 
    1647         [ #  # ]:          0 :         if (internals->type == PORT_TYPE_VIRTUAL || internals->type == PORT_TYPE_OVERRIDE)
    1648                 :            :                 return 0;
    1649                 :            : 
    1650                 :          0 :         fpga_info_t *fpga_info = &internals->p_drv->ntdrv.adapter_info.fpga_info;
    1651         [ #  # ]:          0 :         const int length = snprintf(fw_version, fw_size, "%03d-%04d-%02d-%02d",
    1652                 :            :                         fpga_info->n_fpga_type_id, fpga_info->n_fpga_prod_id,
    1653                 :            :                         fpga_info->n_fpga_ver_id, fpga_info->n_fpga_rev_id);
    1654                 :            : 
    1655         [ #  # ]:          0 :         if ((size_t)length < fw_size) {
    1656                 :            :                 /* We have space for the version string */
    1657                 :            :                 return 0;
    1658                 :            : 
    1659                 :            :         } else {
    1660                 :            :                 /* We do not have space for the version string -return the needed space */
    1661                 :          0 :                 return length + 1;
    1662                 :            :         }
    1663                 :            : }
    1664                 :            : 
    1665                 :          0 : static int dev_flow_ops_get(struct rte_eth_dev *dev __rte_unused, const struct rte_flow_ops **ops)
    1666                 :            : {
    1667                 :          0 :         *ops = nthw_get_dev_flow_ops();
    1668                 :          0 :         return 0;
    1669                 :            : }
    1670                 :            : 
    1671                 :          0 : static int eth_xstats_get(struct rte_eth_dev *eth_dev, struct rte_eth_xstat *stats, unsigned int n)
    1672                 :            : {
    1673                 :          0 :         struct pmd_internals *internals = eth_dev->data->dev_private;
    1674                 :          0 :         struct drv_s *p_drv = internals->p_drv;
    1675                 :            :         ntdrv_4ga_t *p_nt_drv = &p_drv->ntdrv;
    1676                 :          0 :         nt4ga_stat_t *p_nt4ga_stat = &p_nt_drv->adapter_info.nt4ga_stat;
    1677                 :          0 :         int n_intf_no = internals->n_intf_no;
    1678                 :            :         int nb_xstats;
    1679                 :            : 
    1680                 :          0 :         const struct ntnic_xstats_ops *ntnic_xstats_ops = nthw_get_xstats_ops();
    1681                 :            : 
    1682         [ #  # ]:          0 :         if (ntnic_xstats_ops == NULL) {
    1683                 :          0 :                 NT_LOG(INF, NTNIC, "ntnic_xstats module not included");
    1684                 :          0 :                 return -1;
    1685                 :            :         }
    1686                 :            : 
    1687                 :          0 :         rte_spinlock_lock(&p_nt_drv->stat_lck);
    1688                 :          0 :         nb_xstats = ntnic_xstats_ops->nthw_xstats_get(p_nt4ga_stat, stats, n, n_intf_no);
    1689                 :            :         rte_spinlock_unlock(&p_nt_drv->stat_lck);
    1690                 :          0 :         return nb_xstats;
    1691                 :            : }
    1692                 :            : 
    1693                 :          0 : static int eth_xstats_get_by_id(struct rte_eth_dev *eth_dev,
    1694                 :            :         const uint64_t *ids,
    1695                 :            :         uint64_t *values,
    1696                 :            :         unsigned int n)
    1697                 :            : {
    1698                 :          0 :         struct pmd_internals *internals = eth_dev->data->dev_private;
    1699                 :          0 :         struct drv_s *p_drv = internals->p_drv;
    1700                 :            :         ntdrv_4ga_t *p_nt_drv = &p_drv->ntdrv;
    1701                 :          0 :         nt4ga_stat_t *p_nt4ga_stat = &p_nt_drv->adapter_info.nt4ga_stat;
    1702                 :          0 :         int n_intf_no = internals->n_intf_no;
    1703                 :            :         int nb_xstats;
    1704                 :            : 
    1705                 :          0 :         const struct ntnic_xstats_ops *ntnic_xstats_ops = nthw_get_xstats_ops();
    1706                 :            : 
    1707         [ #  # ]:          0 :         if (ntnic_xstats_ops == NULL) {
    1708                 :          0 :                 NT_LOG(INF, NTNIC, "ntnic_xstats module not included");
    1709                 :          0 :                 return -1;
    1710                 :            :         }
    1711                 :            : 
    1712                 :          0 :         rte_spinlock_lock(&p_nt_drv->stat_lck);
    1713                 :            :         nb_xstats =
    1714                 :          0 :                 ntnic_xstats_ops->nthw_xstats_get_by_id(p_nt4ga_stat, ids, values, n, n_intf_no);
    1715                 :            :         rte_spinlock_unlock(&p_nt_drv->stat_lck);
    1716                 :          0 :         return nb_xstats;
    1717                 :            : }
    1718                 :            : 
    1719                 :          0 : static int eth_xstats_reset(struct rte_eth_dev *eth_dev)
    1720                 :            : {
    1721                 :          0 :         struct pmd_internals *internals = eth_dev->data->dev_private;
    1722                 :          0 :         struct drv_s *p_drv = internals->p_drv;
    1723                 :          0 :         ntdrv_4ga_t *p_nt_drv = &p_drv->ntdrv;
    1724                 :          0 :         nt4ga_stat_t *p_nt4ga_stat = &p_nt_drv->adapter_info.nt4ga_stat;
    1725                 :          0 :         int n_intf_no = internals->n_intf_no;
    1726                 :            : 
    1727                 :          0 :         struct ntnic_xstats_ops *ntnic_xstats_ops = nthw_get_xstats_ops();
    1728                 :            : 
    1729         [ #  # ]:          0 :         if (ntnic_xstats_ops == NULL) {
    1730                 :          0 :                 NT_LOG(INF, NTNIC, "ntnic_xstats module not included");
    1731                 :          0 :                 return -1;
    1732                 :            :         }
    1733                 :            : 
    1734                 :          0 :         rte_spinlock_lock(&p_nt_drv->stat_lck);
    1735                 :          0 :         ntnic_xstats_ops->nthw_xstats_reset(p_nt4ga_stat, n_intf_no);
    1736                 :            :         rte_spinlock_unlock(&p_nt_drv->stat_lck);
    1737                 :          0 :         return dpdk_stats_reset(internals, p_nt_drv, n_intf_no);
    1738                 :            : }
    1739                 :            : 
    1740                 :          0 : static int eth_xstats_get_names(struct rte_eth_dev *eth_dev,
    1741                 :            :         struct rte_eth_xstat_name *xstats_names, unsigned int size)
    1742                 :            : {
    1743                 :          0 :         struct pmd_internals *internals = eth_dev->data->dev_private;
    1744                 :          0 :         struct drv_s *p_drv = internals->p_drv;
    1745                 :            :         ntdrv_4ga_t *p_nt_drv = &p_drv->ntdrv;
    1746                 :          0 :         nt4ga_stat_t *p_nt4ga_stat = &p_nt_drv->adapter_info.nt4ga_stat;
    1747                 :            : 
    1748                 :          0 :         const struct ntnic_xstats_ops *ntnic_xstats_ops = nthw_get_xstats_ops();
    1749                 :            : 
    1750         [ #  # ]:          0 :         if (ntnic_xstats_ops == NULL) {
    1751                 :          0 :                 NT_LOG(INF, NTNIC, "ntnic_xstats module not included");
    1752                 :          0 :                 return -1;
    1753                 :            :         }
    1754                 :            : 
    1755                 :          0 :         return ntnic_xstats_ops->nthw_xstats_get_names(p_nt4ga_stat, xstats_names, size);
    1756                 :            : }
    1757                 :            : 
    1758                 :          0 : static int eth_xstats_get_names_by_id(struct rte_eth_dev *eth_dev,
    1759                 :            :         const uint64_t *ids,
    1760                 :            :         struct rte_eth_xstat_name *xstats_names,
    1761                 :            :         unsigned int size)
    1762                 :            : {
    1763                 :          0 :         struct pmd_internals *internals = eth_dev->data->dev_private;
    1764                 :          0 :         struct drv_s *p_drv = internals->p_drv;
    1765                 :            :         ntdrv_4ga_t *p_nt_drv = &p_drv->ntdrv;
    1766                 :          0 :         nt4ga_stat_t *p_nt4ga_stat = &p_nt_drv->adapter_info.nt4ga_stat;
    1767                 :          0 :         const struct ntnic_xstats_ops *ntnic_xstats_ops = nthw_get_xstats_ops();
    1768                 :            : 
    1769         [ #  # ]:          0 :         if (ntnic_xstats_ops == NULL) {
    1770                 :          0 :                 NT_LOG(INF, NTNIC, "ntnic_xstats module not included");
    1771                 :          0 :                 return -1;
    1772                 :            :         }
    1773                 :            : 
    1774                 :          0 :         return ntnic_xstats_ops->nthw_xstats_get_names_by_id(p_nt4ga_stat, xstats_names, ids,
    1775                 :            :                         size);
    1776                 :            : }
    1777                 :            : 
    1778                 :            : static int
    1779                 :          0 : promiscuous_enable(struct rte_eth_dev __rte_unused(*dev))
    1780                 :            : {
    1781                 :          0 :         NT_LOG(DBG, NTHW, "The device always run promiscuous mode");
    1782                 :          0 :         return 0;
    1783                 :            : }
    1784                 :            : 
    1785                 :          0 : static int eth_dev_rss_hash_update(struct rte_eth_dev *eth_dev, struct rte_eth_rss_conf *rss_conf)
    1786                 :            : {
    1787                 :          0 :         const struct flow_filter_ops *flow_filter_ops = nthw_get_flow_filter_ops();
    1788                 :            : 
    1789         [ #  # ]:          0 :         if (flow_filter_ops == NULL) {
    1790                 :          0 :                 NT_LOG_DBGX(ERR, NTNIC, "flow_filter module uninitialized");
    1791                 :          0 :                 return -1;
    1792                 :            :         }
    1793                 :            : 
    1794                 :          0 :         struct pmd_internals *internals = eth_dev->data->dev_private;
    1795                 :            : 
    1796                 :          0 :         struct flow_nic_dev *ndev = internals->flw_dev->ndev;
    1797                 :          0 :         struct nt_eth_rss_conf tmp_rss_conf = { 0 };
    1798                 :            :         const int hsh_idx = 0;  /* hsh index 0 means the default receipt in HSH module */
    1799                 :            : 
    1800         [ #  # ]:          0 :         if (rss_conf->rss_key != NULL) {
    1801         [ #  # ]:          0 :                 if (rss_conf->rss_key_len > MAX_RSS_KEY_LEN) {
    1802                 :          0 :                         NT_LOG(ERR, NTNIC,
    1803                 :            :                                 "ERROR: - RSS hash key length %u exceeds maximum value %u",
    1804                 :            :                                 rss_conf->rss_key_len, MAX_RSS_KEY_LEN);
    1805                 :          0 :                         return -1;
    1806                 :            :                 }
    1807                 :            : 
    1808         [ #  # ]:          0 :                 rte_memcpy(&tmp_rss_conf.rss_key, rss_conf->rss_key, rss_conf->rss_key_len);
    1809                 :            :         }
    1810                 :            : 
    1811                 :          0 :         tmp_rss_conf.algorithm = rss_conf->algorithm;
    1812                 :            : 
    1813                 :          0 :         tmp_rss_conf.rss_hf = rss_conf->rss_hf;
    1814                 :          0 :         int res = nthw_hsh_set(ndev, hsh_idx, tmp_rss_conf);
    1815                 :            : 
    1816         [ #  # ]:          0 :         if (res == 0) {
    1817                 :          0 :                 flow_filter_ops->nthw_mod_hsh_rcp_flush(&ndev->be, hsh_idx, 1);
    1818                 :            :                 rte_memcpy(&ndev->rss_conf, &tmp_rss_conf, sizeof(struct nt_eth_rss_conf));
    1819                 :            : 
    1820                 :            :         } else {
    1821                 :          0 :                 NT_LOG(ERR, NTNIC, "ERROR: - RSS hash update failed with error %i", res);
    1822                 :            :         }
    1823                 :            : 
    1824                 :            :         return res;
    1825                 :            : }
    1826                 :            : 
    1827                 :          0 : static int rss_hash_conf_get(struct rte_eth_dev *eth_dev, struct rte_eth_rss_conf *rss_conf)
    1828                 :            : {
    1829                 :          0 :         struct pmd_internals *internals = eth_dev->data->dev_private;
    1830                 :          0 :         struct flow_nic_dev *ndev = internals->flw_dev->ndev;
    1831                 :            : 
    1832                 :          0 :         rss_conf->algorithm = (enum rte_eth_hash_function)ndev->rss_conf.algorithm;
    1833                 :            : 
    1834                 :          0 :         rss_conf->rss_hf = ndev->rss_conf.rss_hf;
    1835                 :            : 
    1836                 :            :         /*
    1837                 :            :          * copy full stored key into rss_key and pad it with
    1838                 :            :          * zeros up to rss_key_len / MAX_RSS_KEY_LEN
    1839                 :            :          */
    1840         [ #  # ]:          0 :         if (rss_conf->rss_key != NULL) {
    1841                 :          0 :                 int key_len = RTE_MIN(rss_conf->rss_key_len, MAX_RSS_KEY_LEN);
    1842         [ #  # ]:          0 :                 memset(rss_conf->rss_key, 0, rss_conf->rss_key_len);
    1843         [ #  # ]:          0 :                 rte_memcpy(rss_conf->rss_key, &ndev->rss_conf.rss_key, key_len);
    1844                 :          0 :                 rss_conf->rss_key_len = key_len;
    1845                 :            :         }
    1846                 :            : 
    1847                 :          0 :         return 0;
    1848                 :            : }
    1849                 :            : 
    1850                 :            : static struct eth_dev_ops nthw_eth_dev_ops = {
    1851                 :            :         .dev_configure = eth_dev_configure,
    1852                 :            :         .dev_start = eth_dev_start,
    1853                 :            :         .dev_stop = eth_dev_stop,
    1854                 :            :         .dev_set_link_up = eth_dev_set_link_up,
    1855                 :            :         .dev_set_link_down = eth_dev_set_link_down,
    1856                 :            :         .dev_close = eth_dev_close,
    1857                 :            :         .link_update = eth_link_update,
    1858                 :            :         .stats_get = eth_stats_get,
    1859                 :            :         .stats_reset = eth_stats_reset,
    1860                 :            :         .dev_infos_get = eth_dev_infos_get,
    1861                 :            :         .fw_version_get = eth_fw_version_get,
    1862                 :            :         .rx_queue_setup = eth_rx_scg_queue_setup,
    1863                 :            :         .rx_queue_start = eth_rx_queue_start,
    1864                 :            :         .rx_queue_stop = eth_rx_queue_stop,
    1865                 :            :         .rx_queue_release = eth_rx_queue_release,
    1866                 :            :         .tx_queue_setup = eth_tx_scg_queue_setup,
    1867                 :            :         .tx_queue_start = eth_tx_queue_start,
    1868                 :            :         .tx_queue_stop = eth_tx_queue_stop,
    1869                 :            :         .tx_queue_release = eth_tx_queue_release,
    1870                 :            :         .mac_addr_add = eth_mac_addr_add,
    1871                 :            :         .mac_addr_set = eth_mac_addr_set,
    1872                 :            :         .set_mc_addr_list = eth_set_mc_addr_list,
    1873                 :            :         .mtr_ops_get = NULL,
    1874                 :            :         .flow_ops_get = dev_flow_ops_get,
    1875                 :            :         .xstats_get = eth_xstats_get,
    1876                 :            :         .xstats_get_names = eth_xstats_get_names,
    1877                 :            :         .xstats_reset = eth_xstats_reset,
    1878                 :            :         .xstats_get_by_id = eth_xstats_get_by_id,
    1879                 :            :         .xstats_get_names_by_id = eth_xstats_get_names_by_id,
    1880                 :            :         .mtu_set = NULL,
    1881                 :            :         .promiscuous_enable = promiscuous_enable,
    1882                 :            :         .rss_hash_update = eth_dev_rss_hash_update,
    1883                 :            :         .rss_hash_conf_get = rss_hash_conf_get,
    1884                 :            : };
    1885                 :            : 
    1886                 :            : /*
    1887                 :            :  * Port event service
    1888                 :            :  */
    1889                 :          0 : static int port_event_service(void *context)
    1890                 :            : {
    1891                 :            :         struct pmd_internals *internals = context;
    1892                 :            :         RTE_ASSERT(internals != NULL);
    1893                 :            : 
    1894                 :          0 :         const uint8_t port_no = internals->port;
    1895         [ #  # ]:          0 :         if (port_no >= NUM_ADAPTER_PORTS_MAX) {
    1896                 :          0 :                 NT_LOG(ERR, NTNIC, "Invalid Port number");
    1897                 :          0 :                 return -1;
    1898                 :            :         }
    1899                 :            : 
    1900                 :            :         static ntdrv_4ga_t *p_nt_drv[NUM_ADAPTER_PORTS_MAX] = {NULL, NULL};
    1901                 :            :         static struct rte_eth_dev *eth_dev[NUM_ADAPTER_PORTS_MAX] = {NULL, NULL};
    1902                 :            :         static nt4ga_stat_t *p_nt4ga_stat[NUM_ADAPTER_PORTS_MAX] = {NULL, NULL};
    1903                 :            :         static ntnic_flm_load_t flmdata[NUM_ADAPTER_PORTS_MAX];
    1904                 :            :         static ntnic_port_load_t portdata[NUM_ADAPTER_PORTS_MAX];
    1905                 :            : 
    1906                 :          0 :         const int port_srv_tag[2] = {
    1907                 :            :                 RTE_NTNIC_SERVICE_PORT_0_EVENT,
    1908                 :            :                 RTE_NTNIC_SERVICE_PORT_1_EVENT
    1909                 :            :         };
    1910                 :            : 
    1911                 :          0 :         struct nt_service *port_event_srv = nthw_service_get_info(port_srv_tag[port_no]);
    1912                 :            :         RTE_ASSERT(port_event_srv != NULL);
    1913                 :            : 
    1914         [ #  # ]:          0 :         if (!NT_SERVICE_GET_STATE(port_event_srv)) {
    1915                 :          0 :                 struct drv_s *p_drv = internals->p_drv;
    1916                 :          0 :                 p_nt_drv[port_no] = &p_drv->ntdrv;
    1917                 :            :                 struct adapter_info_s *p_adapter_info = &p_nt_drv[port_no]->adapter_info;
    1918                 :          0 :                 struct flow_nic_dev *ndev = p_adapter_info->nt4ga_filter.mp_flow_device;
    1919                 :          0 :                 p_nt4ga_stat[port_no] = &p_nt_drv[port_no]->adapter_info.nt4ga_stat;
    1920                 :          0 :                 eth_dev[port_no] = &rte_eth_devices[internals->port_id];
    1921   [ #  #  #  # ]:          0 :                 if (ndev != NULL && ndev->eth_base == NULL)
    1922                 :            :                         return -1;
    1923                 :            : 
    1924                 :            :                 memset(&flmdata, 0, sizeof(flmdata));
    1925                 :            :                 memset(&portdata, 0, sizeof(portdata));
    1926                 :            : 
    1927                 :            : 
    1928                 :          0 :                 NT_LOG(INF, NTNIC, "port[%u] event service started on lcore %i",
    1929                 :            :                         port_no, rte_lcore_id());
    1930                 :          0 :                 port_event_srv->lcore = rte_lcore_id();
    1931                 :          0 :                 NT_SERVICE_SET_STATE(port_event_srv, true);
    1932                 :          0 :                 return 0;
    1933                 :            :         }
    1934                 :            : 
    1935                 :            :         /*
    1936                 :            :          * FLM load measurement
    1937                 :            :          * Do only send event, if there has been a change
    1938                 :            :          */
    1939                 :            : 
    1940                 :          0 :         nt4ga_stat_t *port_stat = p_nt4ga_stat[port_no];
    1941                 :            :         ntnic_flm_load_t *port_flm_load = &flmdata[port_no];
    1942                 :            :         ntnic_port_load_t *port_load = &portdata[port_no];
    1943                 :            : 
    1944   [ #  #  #  # ]:          0 :         if (port_stat->flm_stat_ver > 22 && port_stat->mp_stat_structs_flm) {
    1945         [ #  # ]:          0 :                 if (port_flm_load->lookup != port_stat->mp_stat_structs_flm->load_lps ||
    1946         [ #  # ]:          0 :                         port_flm_load->access != port_stat->mp_stat_structs_flm->load_aps) {
    1947                 :          0 :                         rte_spinlock_lock(&p_nt_drv[port_no]->stat_lck);
    1948                 :          0 :                         port_flm_load->lookup = port_stat->mp_stat_structs_flm->load_lps;
    1949                 :          0 :                         port_flm_load->access = port_stat->mp_stat_structs_flm->load_aps;
    1950                 :          0 :                         port_flm_load->lookup_maximum =
    1951                 :          0 :                                 port_stat->mp_stat_structs_flm->max_lps;
    1952                 :          0 :                         port_flm_load->access_maximum =
    1953                 :          0 :                                 port_stat->mp_stat_structs_flm->max_aps;
    1954                 :          0 :                         rte_spinlock_unlock(&p_nt_drv[port_no]->stat_lck);
    1955                 :            : 
    1956         [ #  # ]:          0 :                         if (eth_dev[port_no] &&
    1957         [ #  # ]:          0 :                                 eth_dev[port_no]->data &&
    1958         [ #  # ]:          0 :                                 eth_dev[port_no]->data->dev_private) {
    1959                 :          0 :                                 rte_eth_dev_callback_process(eth_dev[port_no],
    1960                 :            :                                         (enum rte_eth_event_type)RTE_NTNIC_FLM_LOAD_EVENT,
    1961                 :            :                                         &flmdata);
    1962                 :            :                         }
    1963                 :            :                 }
    1964                 :            :         }
    1965                 :            : 
    1966                 :            :         /*
    1967                 :            :          * Port load measurement
    1968                 :            :          * Do only send event, if there has been a change.
    1969                 :            :          */
    1970         [ #  # ]:          0 :         if (port_stat->mp_port_load) {
    1971         [ #  # ]:          0 :                 if (port_load->rx_bps != port_stat->mp_port_load[port_no].rx_bps ||
    1972         [ #  # ]:          0 :                         port_load->tx_bps != port_stat->mp_port_load[port_no].tx_bps) {
    1973                 :          0 :                         rte_spinlock_lock(&p_nt_drv[port_no]->stat_lck);
    1974                 :          0 :                         port_load->rx_bps = port_stat->mp_port_load[port_no].rx_bps;
    1975                 :          0 :                         port_load->tx_bps = port_stat->mp_port_load[port_no].tx_bps;
    1976                 :          0 :                         port_load->rx_pps = port_stat->mp_port_load[port_no].rx_pps;
    1977                 :          0 :                         port_load->tx_pps = port_stat->mp_port_load[port_no].tx_pps;
    1978                 :          0 :                         port_load->rx_pps_maximum =
    1979                 :          0 :                                 port_stat->mp_port_load[port_no].rx_pps_max;
    1980                 :          0 :                         port_load->tx_pps_maximum =
    1981                 :          0 :                                 port_stat->mp_port_load[port_no].tx_pps_max;
    1982                 :          0 :                         port_load->rx_bps_maximum =
    1983                 :          0 :                                 port_stat->mp_port_load[port_no].rx_bps_max;
    1984                 :          0 :                         port_load->tx_bps_maximum =
    1985                 :          0 :                                 port_stat->mp_port_load[port_no].tx_bps_max;
    1986                 :          0 :                         rte_spinlock_unlock(&p_nt_drv[port_no]->stat_lck);
    1987                 :            : 
    1988   [ #  #  #  # ]:          0 :                         if (eth_dev[port_no] && eth_dev[port_no]->data &&
    1989         [ #  # ]:          0 :                                 eth_dev[port_no]->data->dev_private) {
    1990                 :          0 :                                 rte_eth_dev_callback_process(eth_dev[port_no],
    1991                 :            :                                         (enum rte_eth_event_type)RTE_NTNIC_PORT_LOAD_EVENT,
    1992                 :            :                                         &portdata);
    1993                 :            :                         }
    1994                 :            :                 }
    1995                 :            :         }
    1996                 :            : 
    1997                 :            :         /* Process events */
    1998                 :            :         {
    1999                 :            :                 int count = 0;
    2000                 :            :                 bool do_wait = true;
    2001                 :            : 
    2002         [ #  # ]:          0 :                 while (count < 5000) {
    2003                 :            :                         /* Local FLM statistic events */
    2004                 :            :                         struct flm_info_event_s data;
    2005                 :            : 
    2006         [ #  # ]:          0 :                         if (nthw_flm_inf_queue_get(port_no, FLM_INFO_LOCAL, &data) == 0) {
    2007   [ #  #  #  # ]:          0 :                                 if (eth_dev[port_no] && eth_dev[port_no]->data &&
    2008         [ #  # ]:          0 :                                         eth_dev[port_no]->data->dev_private) {
    2009                 :            :                                         struct ntnic_flm_statistic_s event_data;
    2010                 :          0 :                                         event_data.bytes = data.bytes;
    2011                 :          0 :                                         event_data.packets = data.packets;
    2012                 :          0 :                                         event_data.cause = data.cause;
    2013                 :          0 :                                         event_data.id = data.id;
    2014                 :          0 :                                         event_data.timestamp = data.timestamp;
    2015                 :          0 :                                         rte_eth_dev_callback_process(eth_dev[port_no],
    2016                 :            :                                                 (enum rte_eth_event_type)
    2017                 :            :                                                 RTE_NTNIC_FLM_STATS_EVENT,
    2018                 :            :                                                 &event_data);
    2019                 :            :                                         do_wait = false;
    2020                 :            :                                 }
    2021                 :            :                         }
    2022                 :            : 
    2023                 :            :                         /* AGED event */
    2024                 :            :                         /* Note: RTE_FLOW_PORT_FLAG_STRICT_QUEUE flag is not supported so
    2025                 :            :                          * event is always generated
    2026                 :            :                          */
    2027                 :          0 :                         int aged_event_count = nthw_flm_age_event_get(port_no);
    2028                 :            : 
    2029         [ #  # ]:          0 :                         if (aged_event_count > 0 &&
    2030         [ #  # ]:          0 :                                 eth_dev[port_no] &&
    2031         [ #  # ]:          0 :                                 eth_dev[port_no]->data &&
    2032         [ #  # ]:          0 :                                 eth_dev[port_no]->data->dev_private) {
    2033                 :          0 :                                 rte_eth_dev_callback_process(eth_dev[port_no],
    2034                 :            :                                         RTE_ETH_EVENT_FLOW_AGED,
    2035                 :            :                                         NULL);
    2036                 :          0 :                                 nthw_flm_age_event_clear(port_no);
    2037                 :            :                                 do_wait = false;
    2038                 :            :                         }
    2039                 :            : 
    2040         [ #  # ]:          0 :                         if (do_wait)
    2041                 :          0 :                                 nthw_os_wait_usec(10);
    2042                 :            : 
    2043                 :          0 :                         count++;
    2044                 :            :                         do_wait = true;
    2045                 :            :                 }
    2046                 :            :         }
    2047                 :            : 
    2048                 :            :         return 0;
    2049                 :            : }
    2050                 :            : 
    2051                 :            : /*
    2052                 :            :  * Adapter flm update service
    2053                 :            :  */
    2054                 :          0 : static int adapter_flm_update_service(void *context)
    2055                 :            : {
    2056                 :            :         static struct flow_eth_dev *dev;
    2057                 :            :         static const struct profile_inline_ops *profile_inline_ops;
    2058                 :            : 
    2059                 :          0 :         struct nt_service *flm_update_srv = nthw_service_get_info(RTE_NTNIC_SERVICE_FLM_UPDATE);
    2060                 :            :         RTE_ASSERT(flm_update_srv != NULL);
    2061                 :            : 
    2062         [ #  # ]:          0 :         if (!NT_SERVICE_GET_STATE(flm_update_srv)) {
    2063                 :            :                 struct drv_s *p_drv = context;
    2064                 :            :                 RTE_ASSERT(p_drv != NULL);
    2065                 :            : 
    2066                 :            :                 struct ntdrv_4ga_s *p_nt_drv = &p_drv->ntdrv;
    2067                 :            :                 struct adapter_info_s *p_adapter_info = &p_nt_drv->adapter_info;
    2068                 :            :                 struct nt4ga_filter_s *p_nt4ga_filter = &p_adapter_info->nt4ga_filter;
    2069                 :          0 :                 struct flow_nic_dev *p_flow_nic_dev = p_nt4ga_filter->mp_flow_device;
    2070                 :            : 
    2071                 :          0 :                 NT_LOG(DBG, NTNIC, "%s: %s: waiting for port configuration",
    2072                 :            :                         p_adapter_info->mp_adapter_id_str, __func__);
    2073                 :            : 
    2074         [ #  # ]:          0 :                 if (p_flow_nic_dev->eth_base == NULL)
    2075                 :            :                         return -1;
    2076                 :            : 
    2077                 :          0 :                 dev = p_flow_nic_dev->eth_base;
    2078                 :            : 
    2079                 :          0 :                 profile_inline_ops = nthw_get_profile_inline_ops();
    2080                 :            :                 RTE_ASSERT(profile_inline_ops != NULL);
    2081                 :            : 
    2082                 :          0 :                 NT_LOG(INF, NTNIC, "flm update service started on lcore %i",  rte_lcore_id());
    2083                 :          0 :                 flm_update_srv->lcore = rte_lcore_id();
    2084                 :          0 :                 NT_SERVICE_SET_STATE(flm_update_srv, true);
    2085                 :          0 :                 return 0;
    2086                 :            :         }
    2087                 :            : 
    2088         [ #  # ]:          0 :         if (profile_inline_ops->flm_update(dev) == 0)
    2089                 :          0 :                 nthw_os_wait_usec(10);
    2090                 :            : 
    2091                 :            :         return 0;
    2092                 :            : }
    2093                 :            : 
    2094                 :            : /*
    2095                 :            :  * Adapter stat service
    2096                 :            :  */
    2097                 :          0 : static int adapter_stat_service(void *context)
    2098                 :            : {
    2099                 :            :         static struct ntdrv_4ga_s *p_nt_drv;
    2100                 :            :         static nt4ga_stat_t *p_nt4ga_stat;
    2101                 :            :         static nthw_stat_t *p_nthw_stat;
    2102                 :            :         static const struct nt4ga_stat_ops *nt4ga_stat_ops;
    2103                 :            : 
    2104                 :          0 :         struct nt_service *stat_srv = nthw_service_get_info(RTE_NTNIC_SERVICE_STAT);
    2105                 :            :         RTE_ASSERT(stat_srv != NULL);
    2106                 :            : 
    2107         [ #  # ]:          0 :         if (!NT_SERVICE_GET_STATE(stat_srv)) {
    2108                 :            :                 struct drv_s *p_drv = context;
    2109                 :            :                 RTE_ASSERT(p_drv != NULL);
    2110                 :            : 
    2111                 :          0 :                 nt4ga_stat_ops = nthw_get_nt4ga_stat_ops();
    2112                 :            :                 RTE_ASSERT(nt4ga_stat_ops != NULL);
    2113                 :            : 
    2114                 :          0 :                 p_nt_drv = &p_drv->ntdrv;
    2115                 :          0 :                 p_nt4ga_stat = &p_nt_drv->adapter_info.nt4ga_stat;
    2116                 :          0 :                 p_nthw_stat = p_nt4ga_stat->mp_nthw_stat;
    2117                 :            : 
    2118         [ #  # ]:          0 :                 if (!p_nthw_stat)
    2119                 :            :                         return 0;
    2120                 :            : 
    2121                 :          0 :                 NT_LOG(INF, NTNIC, "statistic service started on lcore %u",  rte_lcore_id());
    2122                 :          0 :                 stat_srv->lcore = rte_lcore_id();
    2123                 :          0 :                 NT_SERVICE_SET_STATE(stat_srv, true);
    2124                 :          0 :                 return 0;
    2125                 :            :         }
    2126                 :            : 
    2127                 :          0 :         nthw_os_wait_usec(10 * 1000);
    2128                 :            : 
    2129                 :          0 :         nthw_stat_trigger(p_nthw_stat);
    2130                 :            : 
    2131                 :            :         uint32_t loop = 0;
    2132                 :            : 
    2133         [ #  # ]:          0 :         while (rte_service_runstate_get(stat_srv->id) &&
    2134         [ #  # ]:          0 :                 (*p_nthw_stat->mp_timestamp == (uint64_t)-1)) {
    2135                 :          0 :                 nthw_os_wait_usec(1 * 100);
    2136                 :            : 
    2137         [ #  # ]:          0 :                 if ((++loop & 0x3fff) == 0) {
    2138         [ #  # ]:          0 :                         if (p_nt4ga_stat->mp_nthw_rpf) {
    2139                 :          0 :                                 NT_LOG(DBG, NTNIC, "Statistics DMA frozen");
    2140                 :            : 
    2141         [ #  # ]:          0 :                         } else if (p_nt4ga_stat->mp_nthw_rmc) {
    2142                 :            :                                 uint32_t sf_ram_of =
    2143                 :          0 :                                         nthw_rmc_get_status_sf_ram_of(p_nt4ga_stat
    2144                 :            :                                                 ->mp_nthw_rmc);
    2145                 :            :                                 uint32_t descr_fifo_of =
    2146                 :          0 :                                         nthw_rmc_get_status_descr_fifo_of(p_nt4ga_stat
    2147                 :          0 :                                                 ->mp_nthw_rmc);
    2148                 :            : 
    2149                 :            :                                 uint32_t dbg_merge =
    2150                 :          0 :                                         nthw_rmc_get_dbg_merge(p_nt4ga_stat->mp_nthw_rmc);
    2151                 :            :                                 uint32_t mac_if_err =
    2152                 :          0 :                                         nthw_rmc_get_mac_if_err(p_nt4ga_stat->mp_nthw_rmc);
    2153                 :            : 
    2154                 :          0 :                                 NT_LOG(DBG, NTNIC, "Statistics DMA frozen");
    2155                 :          0 :                                 NT_LOG(DBG, NTNIC, "SF RAM Overflow     : %08x",
    2156                 :            :                                         sf_ram_of);
    2157                 :          0 :                                 NT_LOG(DBG, NTNIC, "Descr Fifo Overflow : %08x",
    2158                 :            :                                         descr_fifo_of);
    2159                 :          0 :                                 NT_LOG(DBG, NTNIC, "DBG Merge           : %08x",
    2160                 :            :                                         dbg_merge);
    2161                 :          0 :                                 NT_LOG(DBG, NTNIC, "MAC If Errors       : %08x",
    2162                 :            :                                         mac_if_err);
    2163                 :            :                         }
    2164                 :            :                 }
    2165                 :            :         }
    2166                 :            : 
    2167                 :            :         /* Check then collect */
    2168                 :            :         {
    2169                 :          0 :                 rte_spinlock_lock(&p_nt_drv->stat_lck);
    2170                 :          0 :                 nt4ga_stat_ops->nt4ga_stat_collect(&p_nt_drv->adapter_info, p_nt4ga_stat);
    2171                 :          0 :                 rte_spinlock_unlock(&p_nt_drv->stat_lck);
    2172                 :            :         }
    2173                 :            : 
    2174                 :          0 :         return 0;
    2175                 :            : }
    2176                 :            : 
    2177                 :            : static int
    2178                 :          0 : nthw_pci_dev_init(struct rte_pci_device *pci_dev)
    2179                 :            : {
    2180                 :          0 :         const struct flow_filter_ops *flow_filter_ops = nthw_get_flow_filter_ops();
    2181                 :            : 
    2182         [ #  # ]:          0 :         if (flow_filter_ops == NULL) {
    2183                 :          0 :                 NT_LOG_DBGX(ERR, NTNIC, "flow_filter module uninitialized");
    2184                 :            :                 /* Return statement is not necessary here to allow traffic processing by SW  */
    2185                 :            :         }
    2186                 :            : 
    2187                 :          0 :         const struct profile_inline_ops *profile_inline_ops = nthw_get_profile_inline_ops();
    2188                 :            : 
    2189         [ #  # ]:          0 :         if (profile_inline_ops == NULL) {
    2190                 :          0 :                 NT_LOG_DBGX(ERR, NTNIC, "profile_inline module uninitialized");
    2191                 :            :                 /* Return statement is not necessary here to allow traffic processing by SW  */
    2192                 :            :         }
    2193                 :            : 
    2194                 :          0 :         nthw_vfio_init();
    2195                 :          0 :         const struct port_ops *port_ops = nthw_get_port_ops();
    2196                 :            : 
    2197         [ #  # ]:          0 :         if (port_ops == NULL) {
    2198                 :          0 :                 NT_LOG(ERR, NTNIC, "Link management module uninitialized");
    2199                 :          0 :                 return -1;
    2200                 :            :         }
    2201                 :            : 
    2202                 :          0 :         const struct adapter_ops *adapter_ops = nthw_get_adapter_ops();
    2203                 :            : 
    2204         [ #  # ]:          0 :         if (adapter_ops == NULL) {
    2205                 :          0 :                 NT_LOG(ERR, NTNIC, "Adapter module uninitialized");
    2206                 :          0 :                 return -1;
    2207                 :            :         }
    2208                 :            : 
    2209                 :            :         int res;
    2210                 :            :         struct drv_s *p_drv;
    2211                 :            :         ntdrv_4ga_t *p_nt_drv;
    2212                 :            :         hw_info_t *p_hw_info;
    2213                 :            :         fpga_info_t *fpga_info;
    2214                 :            :         uint32_t n_port_mask = -1;      /* All ports enabled by default */
    2215                 :          0 :         uint32_t nb_rx_queues = 1;
    2216                 :          0 :         uint32_t nb_tx_queues = 1;
    2217                 :          0 :         uint32_t exception_path = 0;
    2218                 :            :         struct flow_queue_id_s queue_ids[MAX_QUEUES];
    2219                 :            :         int n_phy_ports;
    2220                 :            :         enum flow_eth_dev_profile profile = FLOW_ETH_DEV_PROFILE_INLINE;
    2221                 :            : 
    2222                 :          0 :         NT_LOG_DBGX(DBG, NTNIC, "Dev %s PF #%i Init : %02x:%02x:%i", pci_dev->name,
    2223                 :            :                 pci_dev->addr.function, pci_dev->addr.bus, pci_dev->addr.devid,
    2224                 :            :                 pci_dev->addr.function);
    2225                 :            : 
    2226                 :            :         /*
    2227                 :            :          * Process options/arguments
    2228                 :            :          */
    2229   [ #  #  #  # ]:          0 :         if (pci_dev->device.devargs && pci_dev->device.devargs->args) {
    2230                 :            :                 int kvargs_count;
    2231                 :            :                 struct rte_kvargs *kvlist =
    2232                 :          0 :                         rte_kvargs_parse(pci_dev->device.devargs->args, valid_arguments);
    2233                 :            : 
    2234         [ #  # ]:          0 :                 if (kvlist == NULL)
    2235                 :            :                         return -1;
    2236                 :            : 
    2237                 :            :                 /*
    2238                 :            :                  * Argument: help
    2239                 :            :                  * NOTE: this argument/option check should be the first as it will stop
    2240                 :            :                  * execution after producing its output
    2241                 :            :                  */
    2242                 :            :                 {
    2243         [ #  # ]:          0 :                         if (rte_kvargs_get(kvlist, ETH_DEV_NTNIC_HELP_ARG)) {
    2244                 :            :                                 size_t i;
    2245                 :            : 
    2246                 :            :                                 for (i = 0; i < RTE_DIM(valid_arguments); i++)
    2247                 :            :                                         if (valid_arguments[i] == NULL)
    2248                 :            :                                                 break;
    2249                 :            : 
    2250                 :          0 :                                 exit(0);
    2251                 :            :                         }
    2252                 :            :                 }
    2253                 :            : 
    2254                 :            :                 /*
    2255                 :            :                  * rxq option/argument
    2256                 :            :                  * The number of rxq (hostbuffers) allocated in memory.
    2257                 :            :                  * Default is 32 RX Hostbuffers
    2258                 :            :                  */
    2259                 :          0 :                 kvargs_count = rte_kvargs_count(kvlist, ETH_DEV_NTHW_RXQUEUES_ARG);
    2260                 :            : 
    2261         [ #  # ]:          0 :                 if (kvargs_count != 0) {
    2262                 :            :                         RTE_ASSERT(kvargs_count == 1);
    2263                 :          0 :                         res = rte_kvargs_process(kvlist, ETH_DEV_NTHW_RXQUEUES_ARG,
    2264                 :            :                                         &nthw_string_to_u32,
    2265                 :            :                                         &nb_rx_queues);
    2266                 :            : 
    2267         [ #  # ]:          0 :                         if (res < 0) {
    2268                 :          0 :                                 NT_LOG_DBGX(ERR, NTNIC,
    2269                 :            :                                         "problem with command line arguments: res=%d",
    2270                 :            :                                         res);
    2271                 :          0 :                                 free(kvlist);
    2272                 :          0 :                                 return -1;
    2273                 :            :                         }
    2274                 :            : 
    2275                 :          0 :                         NT_LOG_DBGX(DBG, NTNIC, "devargs: %s=%u",
    2276                 :            :                                 ETH_DEV_NTHW_RXQUEUES_ARG, nb_rx_queues);
    2277                 :            :                 }
    2278                 :            : 
    2279                 :            :                 /*
    2280                 :            :                  * txq option/argument
    2281                 :            :                  * The number of txq (hostbuffers) allocated in memory.
    2282                 :            :                  * Default is 32 TX Hostbuffers
    2283                 :            :                  */
    2284                 :          0 :                 kvargs_count = rte_kvargs_count(kvlist, ETH_DEV_NTHW_TXQUEUES_ARG);
    2285                 :            : 
    2286         [ #  # ]:          0 :                 if (kvargs_count != 0) {
    2287                 :            :                         RTE_ASSERT(kvargs_count == 1);
    2288                 :          0 :                         res = rte_kvargs_process(kvlist, ETH_DEV_NTHW_TXQUEUES_ARG,
    2289                 :            :                                         &nthw_string_to_u32,
    2290                 :            :                                         &nb_tx_queues);
    2291                 :            : 
    2292         [ #  # ]:          0 :                         if (res < 0) {
    2293                 :          0 :                                 NT_LOG_DBGX(ERR, NTNIC,
    2294                 :            :                                         "problem with command line arguments: res=%d",
    2295                 :            :                                         res);
    2296                 :          0 :                                 free(kvlist);
    2297                 :          0 :                                 return -1;
    2298                 :            :                         }
    2299                 :            : 
    2300                 :          0 :                         NT_LOG_DBGX(DBG, NTNIC, "devargs: %s=%u",
    2301                 :            :                                 ETH_DEV_NTHW_TXQUEUES_ARG, nb_tx_queues);
    2302                 :            :                 }
    2303                 :            : 
    2304                 :          0 :                 kvargs_count = rte_kvargs_count(kvlist, ETH_DEV_NTHW_EXCEPTION_PATH_ARG);
    2305                 :            : 
    2306         [ #  # ]:          0 :                 if (kvargs_count != 0) {
    2307         [ #  # ]:          0 :                         assert(kvargs_count == 1);
    2308                 :          0 :                         res = rte_kvargs_process(kvlist, ETH_DEV_NTHW_EXCEPTION_PATH_ARG,
    2309                 :            :                                         &nthw_string_to_u32, &exception_path);
    2310                 :            : 
    2311         [ #  # ]:          0 :                         if (res < 0) {
    2312                 :          0 :                                 NT_LOG_DBGX(ERR, NTNIC,
    2313                 :            :                                         "problem with command line arguments: res=%d", res);
    2314                 :          0 :                                 return -1;
    2315                 :            :                         }
    2316                 :            : 
    2317                 :          0 :                         NT_LOG_DBGX(DBG, NTNIC, "devargs: %s=%u",
    2318                 :            :                                 ETH_DEV_NTHW_EXCEPTION_PATH_ARG, exception_path);
    2319                 :            :                 }
    2320                 :            : 
    2321                 :          0 :                 rte_kvargs_free(kvlist);
    2322                 :            :         }
    2323                 :            : 
    2324                 :            : 
    2325                 :            :         /* alloc */
    2326                 :          0 :         p_drv = rte_zmalloc_socket(pci_dev->name, sizeof(struct drv_s), RTE_CACHE_LINE_SIZE,
    2327                 :            :                         pci_dev->device.numa_node);
    2328                 :            : 
    2329         [ #  # ]:          0 :         if (!p_drv) {
    2330         [ #  # ]:          0 :                 NT_LOG_DBGX(ERR, NTNIC, "%s: error %d",
    2331                 :            :                         (pci_dev->name[0] ? pci_dev->name : "NA"), -1);
    2332                 :          0 :                 return -1;
    2333                 :            :         }
    2334                 :            : 
    2335                 :            :         /* Setup VFIO context */
    2336                 :          0 :         int vfio = nthw_vfio_setup(pci_dev);
    2337                 :            : 
    2338         [ #  # ]:          0 :         if (vfio < 0) {
    2339         [ #  # ]:          0 :                 NT_LOG_DBGX(ERR, NTNIC, "%s: vfio_setup error %d",
    2340                 :            :                         (pci_dev->name[0] ? pci_dev->name : "NA"), -1);
    2341                 :          0 :                 rte_free(p_drv);
    2342                 :          0 :                 return -1;
    2343                 :            :         }
    2344                 :            : 
    2345                 :            :         /* context */
    2346                 :            :         p_nt_drv = &p_drv->ntdrv;
    2347                 :            :         p_hw_info = &p_nt_drv->adapter_info.hw_info;
    2348                 :          0 :         fpga_info = &p_nt_drv->adapter_info.fpga_info;
    2349                 :            : 
    2350                 :          0 :         p_drv->p_dev = pci_dev;
    2351                 :            : 
    2352                 :            :         /* Set context for NtDrv */
    2353                 :          0 :         p_nt_drv->pciident = BDF_TO_PCIIDENT(pci_dev->addr.domain, pci_dev->addr.bus,
    2354                 :            :                         pci_dev->addr.devid, pci_dev->addr.function);
    2355                 :          0 :         p_nt_drv->adapter_info.n_rx_host_buffers = nb_rx_queues;
    2356                 :          0 :         p_nt_drv->adapter_info.n_tx_host_buffers = nb_tx_queues;
    2357                 :            : 
    2358                 :          0 :         fpga_info->bar0_addr = (void *)pci_dev->mem_resource[0].addr;
    2359                 :          0 :         fpga_info->bar0_size = pci_dev->mem_resource[0].len;
    2360                 :          0 :         fpga_info->numa_node = pci_dev->device.numa_node;
    2361                 :          0 :         fpga_info->pciident = p_nt_drv->pciident;
    2362                 :          0 :         fpga_info->adapter_no = p_drv->adapter_no;
    2363                 :            : 
    2364                 :          0 :         p_nt_drv->adapter_info.hw_info.pci_class_id = pci_dev->id.class_id;
    2365                 :          0 :         p_nt_drv->adapter_info.hw_info.pci_vendor_id = pci_dev->id.vendor_id;
    2366                 :          0 :         p_nt_drv->adapter_info.hw_info.pci_device_id = pci_dev->id.device_id;
    2367                 :          0 :         p_nt_drv->adapter_info.hw_info.pci_sub_vendor_id = pci_dev->id.subsystem_vendor_id;
    2368                 :          0 :         p_nt_drv->adapter_info.hw_info.pci_sub_device_id = pci_dev->id.subsystem_device_id;
    2369                 :            : 
    2370                 :          0 :         NT_LOG(DBG, NTNIC, "%s: " PCIIDENT_PRINT_STR " %04X:%04X: %04X:%04X:",
    2371                 :            :                 p_nt_drv->adapter_info.mp_adapter_id_str, PCIIDENT_TO_DOMAIN(p_nt_drv->pciident),
    2372                 :            :                 PCIIDENT_TO_BUSNR(p_nt_drv->pciident), PCIIDENT_TO_DEVNR(p_nt_drv->pciident),
    2373                 :            :                 PCIIDENT_TO_FUNCNR(p_nt_drv->pciident),
    2374                 :            :                 p_nt_drv->adapter_info.hw_info.pci_vendor_id,
    2375                 :            :                 p_nt_drv->adapter_info.hw_info.pci_device_id,
    2376                 :            :                 p_nt_drv->adapter_info.hw_info.pci_sub_vendor_id,
    2377                 :            :                 p_nt_drv->adapter_info.hw_info.pci_sub_device_id);
    2378                 :            : 
    2379                 :            :         /* store context */
    2380                 :          0 :         store_pdrv(p_drv);
    2381                 :            : 
    2382                 :            :         /* initialize nt4ga nthw fpga module instance in drv */
    2383                 :          0 :         int err = adapter_ops->init(&p_nt_drv->adapter_info);
    2384                 :            : 
    2385         [ #  # ]:          0 :         if (err != 0) {
    2386                 :          0 :                 NT_LOG(ERR, NTNIC, "%s: Cannot initialize the adapter instance",
    2387                 :            :                         p_nt_drv->adapter_info.mp_adapter_id_str);
    2388                 :          0 :                 return -1;
    2389                 :            :         }
    2390                 :            : 
    2391                 :          0 :         const struct meter_ops_s *meter_ops = nthw_get_meter_ops();
    2392                 :            : 
    2393         [ #  # ]:          0 :         if (meter_ops != NULL)
    2394                 :          0 :                 nthw_eth_dev_ops.mtr_ops_get = meter_ops->eth_mtr_ops_get;
    2395                 :            : 
    2396                 :            :         else
    2397                 :          0 :                 NT_LOG(DBG, NTNIC, "Meter module is not initialized");
    2398                 :            : 
    2399                 :            :         /* Initialize the queue system */
    2400                 :          0 :         sg_ops = nthw_get_sg_ops();
    2401                 :            : 
    2402         [ #  # ]:          0 :         if (sg_ops != NULL) {
    2403                 :          0 :                 err = sg_ops->nthw_virt_queue_init(fpga_info);
    2404                 :            : 
    2405         [ #  # ]:          0 :                 if (err != 0) {
    2406                 :          0 :                         NT_LOG(ERR, NTNIC,
    2407                 :            :                                 "%s: Cannot initialize scatter-gather queues",
    2408                 :            :                                 p_nt_drv->adapter_info.mp_adapter_id_str);
    2409                 :            : 
    2410                 :            :                 } else {
    2411                 :          0 :                         NT_LOG(DBG, NTNIC, "%s: Initialized scatter-gather queues",
    2412                 :            :                                 p_nt_drv->adapter_info.mp_adapter_id_str);
    2413                 :            :                 }
    2414                 :            : 
    2415                 :            :         } else {
    2416                 :          0 :                 NT_LOG_DBGX(DBG, NTNIC, "SG module is not initialized");
    2417                 :            :         }
    2418                 :            : 
    2419                 :            :         /* Start ctrl, monitor, stat service only for primary process. */
    2420         [ #  # ]:          0 :         if (err == 0) {
    2421                 :            :                 /* mp_adapter_id_str is initialized after nt4ga_adapter_init(p_nt_drv) */
    2422                 :          0 :                 const char *const p_adapter_id_str = p_nt_drv->adapter_info.mp_adapter_id_str;
    2423                 :            :                 (void)p_adapter_id_str;
    2424         [ #  # ]:          0 :                 NT_LOG(DBG, NTNIC,
    2425                 :            :                         "%s: %s: AdapterPCI=" PCIIDENT_PRINT_STR " Hw=0x%02X_rev%d PhyPorts=%d",
    2426                 :            :                         (pci_dev->name[0] ? pci_dev->name : "NA"), p_adapter_id_str,
    2427                 :            :                         PCIIDENT_TO_DOMAIN(p_nt_drv->adapter_info.fpga_info.pciident),
    2428                 :            :                         PCIIDENT_TO_BUSNR(p_nt_drv->adapter_info.fpga_info.pciident),
    2429                 :            :                         PCIIDENT_TO_DEVNR(p_nt_drv->adapter_info.fpga_info.pciident),
    2430                 :            :                         PCIIDENT_TO_FUNCNR(p_nt_drv->adapter_info.fpga_info.pciident),
    2431                 :            :                         p_hw_info->hw_platform_id, fpga_info->nthw_hw_info.hw_id,
    2432                 :            :                         fpga_info->n_phy_ports);
    2433                 :            : 
    2434                 :            :         } else {
    2435         [ #  # ]:          0 :                 NT_LOG_DBGX(ERR, NTNIC, "%s: error=%d",
    2436                 :            :                         (pci_dev->name[0] ? pci_dev->name : "NA"), err);
    2437                 :          0 :                 return -1;
    2438                 :            :         }
    2439                 :            : 
    2440   [ #  #  #  # ]:          0 :         if (profile_inline_ops != NULL && fpga_info->profile == FPGA_INFO_PROFILE_INLINE) {
    2441                 :          0 :                 profile_inline_ops->flm_setup_queues();
    2442                 :            : 
    2443                 :          0 :                 struct rte_service_spec flm_update_spec = {
    2444                 :            :                         .name = "ntnic-flm_update_service",
    2445                 :            :                         .callback = adapter_flm_update_service,
    2446                 :            :                         .socket_id = SOCKET_ID_ANY,
    2447                 :            :                         .capabilities = RTE_SERVICE_CAP_MT_SAFE,
    2448                 :            :                         .callback_userdata = p_drv
    2449                 :            :                 };
    2450                 :            : 
    2451                 :          0 :                 res = nthw_service_add(&flm_update_spec, RTE_NTNIC_SERVICE_FLM_UPDATE);
    2452                 :            : 
    2453         [ #  # ]:          0 :                 if (res) {
    2454         [ #  # ]:          0 :                         NT_LOG_DBGX(ERR, NTNIC, "%s: error=%d",
    2455                 :            :                                 (pci_dev->name[0] ? pci_dev->name : "NA"), res);
    2456                 :          0 :                         return -1;
    2457                 :            :                 }
    2458                 :            :         }
    2459                 :            : 
    2460                 :          0 :         struct rte_service_spec stat_spec = {
    2461                 :            :                 .name = "ntnic-stat_collect_service",
    2462                 :            :                 .callback = adapter_stat_service,
    2463                 :            :                 .socket_id = SOCKET_ID_ANY,
    2464                 :            :                 .capabilities = RTE_SERVICE_CAP_MT_SAFE,
    2465                 :            :                 .callback_userdata = p_drv
    2466                 :            :         };
    2467                 :            : 
    2468                 :          0 :         res = nthw_service_add(&stat_spec, RTE_NTNIC_SERVICE_STAT);
    2469                 :            : 
    2470         [ #  # ]:          0 :         if (res) {
    2471         [ #  # ]:          0 :                 NT_LOG(ERR, NTNIC, "%s: error=%d",
    2472                 :            :                         (pci_dev->name[0] ? pci_dev->name : "NA"), res);
    2473                 :          0 :                 return -1;
    2474                 :            :         }
    2475                 :            : 
    2476                 :          0 :         n_phy_ports = fpga_info->n_phy_ports;
    2477                 :            : 
    2478         [ #  # ]:          0 :         for (int n_intf_no = 0; n_intf_no < n_phy_ports; n_intf_no++) {
    2479         [ #  # ]:          0 :                 const char *const p_port_id_str = p_nt_drv->adapter_info.mp_port_id_str[n_intf_no];
    2480                 :            :                 (void)p_port_id_str;
    2481                 :            :                 struct pmd_internals *internals = NULL;
    2482                 :            :                 struct rte_eth_dev *eth_dev = NULL;
    2483                 :            :                 char name[32];
    2484                 :            :                 int i;
    2485                 :            : 
    2486                 :            :                 if ((1 << n_intf_no) & ~n_port_mask) {
    2487                 :            :                         NT_LOG_DBGX(DBG, NTNIC,
    2488                 :            :                                 "%s: interface #%d: skipping due to portmask 0x%02X",
    2489                 :            :                                 p_port_id_str, n_intf_no, n_port_mask);
    2490                 :            :                         continue;
    2491                 :            :                 }
    2492                 :            : 
    2493                 :            :                 snprintf(name, sizeof(name), "ntnic%d", n_intf_no);
    2494         [ #  # ]:          0 :                 NT_LOG_DBGX(DBG, NTNIC, "%s: interface #%d: %s: '%s'", p_port_id_str,
    2495                 :            :                         n_intf_no, (pci_dev->name[0] ? pci_dev->name : "NA"), name);
    2496                 :            : 
    2497                 :          0 :                 internals = rte_zmalloc_socket(name, sizeof(struct pmd_internals),
    2498                 :            :                                 RTE_CACHE_LINE_SIZE, pci_dev->device.numa_node);
    2499                 :            : 
    2500         [ #  # ]:          0 :                 if (!internals) {
    2501         [ #  # ]:          0 :                         NT_LOG_DBGX(ERR, NTNIC, "%s: %s: error=%d",
    2502                 :            :                                 (pci_dev->name[0] ? pci_dev->name : "NA"), name, -1);
    2503                 :          0 :                         return -1;
    2504                 :            :                 }
    2505                 :            : 
    2506                 :          0 :                 internals->pci_dev = pci_dev;
    2507                 :          0 :                 internals->n_intf_no = n_intf_no;
    2508                 :          0 :                 internals->type = PORT_TYPE_PHYSICAL;
    2509                 :          0 :                 internals->port = n_intf_no;
    2510                 :          0 :                 internals->nb_rx_queues = nb_rx_queues;
    2511                 :          0 :                 internals->nb_tx_queues = nb_tx_queues;
    2512                 :            : 
    2513                 :            :                 /* Not used queue index as dest port in bypass - use 0x80 + port nr */
    2514         [ #  # ]:          0 :                 for (i = 0; i < MAX_QUEUES; i++)
    2515                 :          0 :                         internals->vpq[i].hw_id = -1;
    2516                 :            : 
    2517                 :            : 
    2518                 :            :                 /* Setup queue_ids */
    2519         [ #  # ]:          0 :                 if (nb_rx_queues > 1) {
    2520                 :          0 :                         NT_LOG(DBG, NTNIC,
    2521                 :            :                                 "(%i) NTNIC configured with Rx multi queues. %" PRIu32 " queues",
    2522                 :            :                                 internals->n_intf_no, nb_rx_queues);
    2523                 :            :                 }
    2524                 :            : 
    2525         [ #  # ]:          0 :                 if (nb_tx_queues > 1) {
    2526                 :          0 :                         NT_LOG(DBG, NTNIC,
    2527                 :            :                                 "(%i) NTNIC configured with Tx multi queues. %" PRIu32 " queues",
    2528                 :            :                                 internals->n_intf_no, nb_tx_queues);
    2529                 :            :                 }
    2530                 :            : 
    2531                 :          0 :                 int max_num_queues = (nb_rx_queues > nb_tx_queues) ? nb_rx_queues : nb_tx_queues;
    2532                 :          0 :                 int start_queue = allocate_queue(max_num_queues);
    2533                 :            : 
    2534         [ #  # ]:          0 :                 if (start_queue < 0)
    2535                 :            :                         return -1;
    2536                 :            : 
    2537         [ #  # ]:          0 :                 for (i = 0; i < (int)max_num_queues; i++) {
    2538                 :          0 :                         queue_ids[i].id = i;
    2539                 :          0 :                         queue_ids[i].hw_id = start_queue + i;
    2540                 :            : 
    2541                 :          0 :                         internals->rxq_scg[i].queue = queue_ids[i];
    2542                 :            :                         /* use same index in Rx and Tx rings */
    2543                 :          0 :                         internals->txq_scg[i].queue = queue_ids[i];
    2544                 :          0 :                         internals->rxq_scg[i].enabled = 0;
    2545                 :          0 :                         internals->txq_scg[i].type = internals->type;
    2546                 :          0 :                         internals->rxq_scg[i].type = internals->type;
    2547                 :          0 :                         internals->rxq_scg[i].port = internals->port;
    2548                 :            :                 }
    2549                 :            : 
    2550                 :            :                 /* no tx queues - tx data goes out on phy */
    2551                 :          0 :                 internals->vpq_nb_vq = 0;
    2552                 :            : 
    2553         [ #  # ]:          0 :                 for (i = 0; i < (int)nb_tx_queues; i++) {
    2554                 :          0 :                         internals->txq_scg[i].port = internals->port;
    2555                 :          0 :                         internals->txq_scg[i].enabled = 0;
    2556                 :            :                 }
    2557                 :            : 
    2558                 :            :                 /* Set MAC address (but only if the MAC address is permitted) */
    2559         [ #  # ]:          0 :                 if (n_intf_no < fpga_info->nthw_hw_info.vpd_info.mn_mac_addr_count) {
    2560                 :          0 :                         const uint64_t mac =
    2561                 :          0 :                                 fpga_info->nthw_hw_info.vpd_info.mn_mac_addr_value + n_intf_no;
    2562                 :          0 :                         internals->eth_addrs[0].addr_bytes[0] = (mac >> 40) & 0xFFu;
    2563                 :          0 :                         internals->eth_addrs[0].addr_bytes[1] = (mac >> 32) & 0xFFu;
    2564                 :          0 :                         internals->eth_addrs[0].addr_bytes[2] = (mac >> 24) & 0xFFu;
    2565                 :          0 :                         internals->eth_addrs[0].addr_bytes[3] = (mac >> 16) & 0xFFu;
    2566                 :          0 :                         internals->eth_addrs[0].addr_bytes[4] = (mac >> 8) & 0xFFu;
    2567                 :          0 :                         internals->eth_addrs[0].addr_bytes[5] = (mac >> 0) & 0xFFu;
    2568                 :            :                 }
    2569                 :            : 
    2570                 :          0 :                 eth_dev = rte_eth_dev_allocate(name);
    2571                 :            : 
    2572         [ #  # ]:          0 :                 if (!eth_dev) {
    2573         [ #  # ]:          0 :                         NT_LOG_DBGX(ERR, NTNIC, "%s: %s: error=%d",
    2574                 :            :                                 (pci_dev->name[0] ? pci_dev->name : "NA"), name, -1);
    2575                 :          0 :                         return -1;
    2576                 :            :                 }
    2577                 :            : 
    2578         [ #  # ]:          0 :                 if (flow_filter_ops != NULL) {
    2579                 :          0 :                         internals->flw_dev = flow_filter_ops->flow_get_eth_dev(0, n_intf_no,
    2580                 :          0 :                                 eth_dev->data->port_id, nb_rx_queues, queue_ids,
    2581                 :            :                                 &internals->txq_scg[0].rss_target_id, profile, exception_path);
    2582                 :            : 
    2583         [ #  # ]:          0 :                         if (!internals->flw_dev) {
    2584                 :          0 :                                 NT_LOG(ERR, NTNIC,
    2585                 :            :                                         "Error creating port. Resource exhaustion in HW");
    2586                 :          0 :                                 return -1;
    2587                 :            :                         }
    2588                 :            :                 }
    2589                 :            : 
    2590                 :            :                 /* connect structs */
    2591                 :          0 :                 internals->p_drv = p_drv;
    2592                 :          0 :                 eth_dev->data->dev_private = internals;
    2593                 :          0 :                 eth_dev->data->mac_addrs = rte_malloc(NULL,
    2594                 :            :                                         NUM_MAC_ADDRS_PER_PORT * sizeof(struct rte_ether_addr), 0);
    2595                 :          0 :                 rte_memcpy(&eth_dev->data->mac_addrs[0],
    2596                 :            :                                         &internals->eth_addrs[0], RTE_ETHER_ADDR_LEN);
    2597                 :            : 
    2598                 :          0 :                 NT_LOG_DBGX(DBG, NTNIC, "Setting up RX functions for SCG");
    2599                 :          0 :                 eth_dev->rx_pkt_burst = eth_dev_rx_scg;
    2600                 :          0 :                 eth_dev->tx_pkt_burst = eth_dev_tx_scg;
    2601                 :            : 
    2602                 :            :                 struct rte_eth_link pmd_link;
    2603                 :            :                 pmd_link.link_speed = RTE_ETH_SPEED_NUM_NONE;
    2604                 :            :                 pmd_link.link_duplex = RTE_ETH_LINK_FULL_DUPLEX;
    2605                 :            :                 pmd_link.link_status = RTE_ETH_LINK_DOWN;
    2606                 :            :                 pmd_link.link_autoneg = RTE_ETH_LINK_AUTONEG;
    2607                 :            : 
    2608                 :          0 :                 eth_dev->device = &pci_dev->device;
    2609                 :          0 :                 eth_dev->data->dev_link = pmd_link;
    2610                 :          0 :                 eth_dev->dev_ops = &nthw_eth_dev_ops;
    2611                 :            : 
    2612                 :            :                 eth_dev_pci_specific_init(eth_dev, pci_dev);
    2613                 :          0 :                 rte_eth_dev_probing_finish(eth_dev);
    2614                 :            : 
    2615                 :            :                 /* increase initialized ethernet devices - PF */
    2616                 :          0 :                 p_drv->n_eth_dev_init_count++;
    2617                 :            : 
    2618         [ #  # ]:          0 :                 if (nthw_get_flow_filter_ops() != NULL) {
    2619         [ #  # ]:          0 :                         if (fpga_info->profile == FPGA_INFO_PROFILE_INLINE &&
    2620         [ #  # ]:          0 :                                 internals->flw_dev->ndev->be.tpe.ver >= 2) {
    2621                 :            :                                 RTE_ASSERT(nthw_eth_dev_ops.mtu_set == dev_set_mtu_inline ||
    2622                 :            :                                         nthw_eth_dev_ops.mtu_set == NULL);
    2623                 :          0 :                                 nthw_eth_dev_ops.mtu_set = dev_set_mtu_inline;
    2624                 :          0 :                                 dev_set_mtu_inline(eth_dev, MTUINITVAL);
    2625                 :          0 :                                 NT_LOG_DBGX(DBG, NTNIC, "INLINE MTU supported, tpe version %d",
    2626                 :            :                                         internals->flw_dev->ndev->be.tpe.ver);
    2627                 :            : 
    2628                 :            :                         } else {
    2629                 :          0 :                                 NT_LOG(DBG, NTNIC, "INLINE MTU not supported");
    2630                 :            :                         }
    2631                 :            :                 }
    2632                 :            : 
    2633                 :            :                 /* Port event service */
    2634         [ #  # ]:          0 :                 if (fpga_info->profile == FPGA_INFO_PROFILE_INLINE) {
    2635                 :          0 :                         struct rte_service_spec port_event_spec = {
    2636                 :            :                                 .callback = port_event_service,
    2637                 :            :                                 .socket_id = SOCKET_ID_ANY,
    2638                 :            :                                 .capabilities = RTE_SERVICE_CAP_MT_SAFE,
    2639                 :            :                                 .callback_userdata = internals
    2640                 :            :                         };
    2641                 :            : 
    2642                 :            :                         snprintf(port_event_spec.name, RTE_SERVICE_NAME_MAX,
    2643                 :            :                                  "ntnic-port_%d_event_service", n_intf_no);
    2644                 :            : 
    2645                 :          0 :                         const int port_srv_tag[2] = {
    2646                 :            :                                 RTE_NTNIC_SERVICE_PORT_0_EVENT,
    2647                 :            :                                 RTE_NTNIC_SERVICE_PORT_1_EVENT
    2648                 :            :                         };
    2649                 :            : 
    2650                 :          0 :                         res = nthw_service_add(&port_event_spec, port_srv_tag[n_intf_no]);
    2651                 :            : 
    2652         [ #  # ]:          0 :                         if (res) {
    2653         [ #  # ]:          0 :                                 NT_LOG(ERR, NTNIC, "%s: error=%d",
    2654                 :            :                                         (pci_dev->name[0] ? pci_dev->name : "NA"), res);
    2655                 :          0 :                                 return -1;
    2656                 :            :                         }
    2657                 :            :                 }
    2658                 :            :         }
    2659                 :            : 
    2660                 :          0 :         uint32_t cores[RTE_MAX_LCORE] = {0};
    2661                 :          0 :         int32_t lcore_count = rte_service_lcore_list(cores, RTE_MAX_LCORE);
    2662                 :            : 
    2663         [ #  # ]:          0 :         if (lcore_count <= 0) {
    2664                 :          0 :                 NT_LOG(WRN, NTNIC, "No service cores available. "
    2665                 :            :                         "Please check if all NTNIC services are started");
    2666                 :            :         }
    2667                 :            : 
    2668                 :            :         return 0;
    2669                 :            : }
    2670                 :            : 
    2671                 :            : static int
    2672                 :          0 : nthw_pci_dev_deinit(struct rte_eth_dev *eth_dev __rte_unused)
    2673                 :            : {
    2674                 :          0 :         NT_LOG_DBGX(DBG, NTNIC, "PCI device deinitialization");
    2675                 :            : 
    2676                 :            :         int i;
    2677                 :            :         char name[RTE_ETH_NAME_MAX_LEN];
    2678                 :            : 
    2679                 :          0 :         struct pmd_internals *internals = eth_dev->data->dev_private;
    2680                 :          0 :         ntdrv_4ga_t *p_ntdrv = &internals->p_drv->ntdrv;
    2681                 :            :         fpga_info_t *fpga_info = &p_ntdrv->adapter_info.fpga_info;
    2682                 :          0 :         const int n_phy_ports = fpga_info->n_phy_ports;
    2683                 :            : 
    2684                 :            :         /* let running services end Rx and Tx activity */
    2685         [ #  # ]:          0 :         if (sg_ops != NULL) {
    2686                 :          0 :                 nthw_os_wait_usec(1 * 1000 * 1000);
    2687                 :            : 
    2688         [ #  # ]:          0 :                 while (internals) {
    2689         [ #  # ]:          0 :                         for (i = internals->nb_tx_queues - 1; i >= 0; i--) {
    2690                 :          0 :                                 sg_ops->nthw_release_mngd_tx_virt_queue(internals->txq_scg[i].vq);
    2691         [ #  # ]:          0 :                                 internals->txq_scg[i].vq = NULL;
    2692                 :            :                                 release_hw_virtio_queues(&internals->txq_scg[i].hwq);
    2693                 :            :                         }
    2694                 :            : 
    2695         [ #  # ]:          0 :                         for (i = internals->nb_rx_queues - 1; i >= 0; i--) {
    2696                 :          0 :                                 sg_ops->nthw_release_mngd_rx_virt_queue(internals->rxq_scg[i].vq);
    2697         [ #  # ]:          0 :                                 internals->rxq_scg[i].vq = NULL;
    2698                 :            :                                 release_hw_virtio_queues(&internals->rxq_scg[i].hwq);
    2699                 :            :                         }
    2700                 :            : 
    2701                 :          0 :                         internals = internals->next;
    2702                 :            :                 }
    2703                 :            :         }
    2704                 :            : 
    2705         [ #  # ]:          0 :         for (i = 0; i < n_phy_ports; i++) {
    2706                 :            :                 snprintf(name, sizeof(name), "ntnic%d", i);
    2707                 :          0 :                 eth_dev = rte_eth_dev_allocated(name);
    2708         [ #  # ]:          0 :                 if (eth_dev == NULL)
    2709                 :          0 :                         continue; /* port already released */
    2710                 :          0 :                 rte_eth_dev_release_port(eth_dev);
    2711                 :            :         }
    2712                 :            : 
    2713                 :          0 :         nthw_vfio_remove(EXCEPTION_PATH_HID);
    2714                 :          0 :         return 0;
    2715                 :            : }
    2716                 :            : 
    2717                 :            : static int
    2718                 :          0 : nthw_pci_probe(struct rte_pci_driver *pci_drv, struct rte_pci_device *pci_dev)
    2719                 :            : {
    2720                 :            :         int ret;
    2721                 :            : 
    2722                 :          0 :         NT_LOG_DBGX(DBG, NTNIC, "pcidev: name: '%s'", pci_dev->name);
    2723                 :          0 :         NT_LOG_DBGX(DBG, NTNIC, "devargs: name: '%s'", pci_dev->device.name);
    2724                 :            : 
    2725         [ #  # ]:          0 :         if (pci_dev->device.devargs) {
    2726         [ #  # ]:          0 :                 NT_LOG_DBGX(DBG, NTNIC, "devargs: args: '%s'",
    2727                 :            :                         (pci_dev->device.devargs->args ? pci_dev->device.devargs->args : "NULL"));
    2728         [ #  # ]:          0 :                 NT_LOG_DBGX(DBG, NTNIC, "devargs: data: '%s'",
    2729                 :            :                         (pci_dev->device.devargs->data ? pci_dev->device.devargs->data : "NULL"));
    2730                 :            :         }
    2731                 :            : 
    2732                 :          0 :         const int n_rte_vfio_no_io_mmu_enabled = rte_vfio_noiommu_is_enabled();
    2733                 :          0 :         NT_LOG(DBG, NTNIC, "vfio_no_iommu_enabled=%d", n_rte_vfio_no_io_mmu_enabled);
    2734                 :            : 
    2735         [ #  # ]:          0 :         if (n_rte_vfio_no_io_mmu_enabled) {
    2736                 :          0 :                 NT_LOG(ERR, NTNIC, "vfio_no_iommu_enabled=%d: this PMD needs VFIO IOMMU",
    2737                 :            :                         n_rte_vfio_no_io_mmu_enabled);
    2738                 :          0 :                 return -1;
    2739                 :            :         }
    2740                 :            : 
    2741                 :          0 :         const enum rte_iova_mode n_rte_io_va_mode = rte_eal_iova_mode();
    2742                 :          0 :         NT_LOG(DBG, NTNIC, "iova mode=%d", n_rte_io_va_mode);
    2743                 :            : 
    2744   [ #  #  #  #  :          0 :         NT_LOG(DBG, NTNIC,
                   #  # ]
    2745                 :            :                 "busid=" PCI_PRI_FMT
    2746                 :            :                 " pciid=%04x:%04x_%04x:%04x locstr=%s @ numanode=%d: drv=%s drvalias=%s",
    2747                 :            :                 pci_dev->addr.domain, pci_dev->addr.bus, pci_dev->addr.devid,
    2748                 :            :                 pci_dev->addr.function, pci_dev->id.vendor_id, pci_dev->id.device_id,
    2749                 :            :                 pci_dev->id.subsystem_vendor_id, pci_dev->id.subsystem_device_id,
    2750                 :            :                 pci_dev->name[0] ? pci_dev->name : "NA",
    2751                 :            :                 pci_dev->device.numa_node,
    2752                 :            :                 (pci_drv->driver.name != NULL) ? pci_drv->driver.name : "NA",
    2753                 :            :                 (pci_drv->driver.alias != NULL) ? pci_drv->driver.alias : "NA");
    2754                 :            : 
    2755                 :          0 :         ret = nthw_pci_dev_init(pci_dev);
    2756                 :            : 
    2757                 :            :         /*
    2758                 :            :          * 1 time calculation of 1 sec stat update rtc cycles to prevent stat poll
    2759                 :            :          * flooding by OVS from multiple virtual port services - no need to be precise
    2760                 :            :          */
    2761                 :            :         uint64_t now_rtc = rte_get_tsc_cycles();
    2762                 :          0 :         nthw_os_wait_usec(10 * 1000);
    2763                 :          0 :         nthw_tsc_freq = 100 * (rte_get_tsc_cycles() - now_rtc);
    2764                 :            : 
    2765                 :          0 :         NT_LOG_DBGX(DBG, NTNIC, "leave: ret=%d", ret);
    2766                 :          0 :         return ret;
    2767                 :            : }
    2768                 :            : 
    2769                 :            : static int
    2770                 :          0 : nthw_pci_remove(struct rte_pci_device *pci_dev)
    2771                 :            : {
    2772                 :          0 :         NT_LOG_DBGX(DBG, NTNIC);
    2773                 :            : 
    2774                 :          0 :         struct drv_s *p_drv = get_pdrv_from_pci(pci_dev->addr);
    2775                 :          0 :         drv_deinit(p_drv);
    2776                 :            : 
    2777                 :          0 :         return rte_eth_dev_pci_generic_remove(pci_dev, nthw_pci_dev_deinit);
    2778                 :            : }
    2779                 :            : 
    2780                 :            : static struct rte_pci_driver rte_nthw_pmd = {
    2781                 :            :         .id_table = nthw_pci_id_map,
    2782                 :            :         .drv_flags = RTE_PCI_DRV_NEED_MAPPING,
    2783                 :            :         .probe = nthw_pci_probe,
    2784                 :            :         .remove = nthw_pci_remove,
    2785                 :            : };
    2786                 :            : 
    2787                 :        302 : RTE_PMD_REGISTER_PCI(net_ntnic, rte_nthw_pmd);
    2788                 :            : RTE_PMD_REGISTER_PCI_TABLE(net_ntnic, nthw_pci_id_map);
    2789                 :            : RTE_PMD_REGISTER_KMOD_DEP(net_ntnic, "* vfio-pci");
    2790                 :            : 
    2791         [ -  + ]:        302 : RTE_LOG_REGISTER_SUFFIX(nthw_logtype_general, general, INFO);
    2792         [ -  + ]:        302 : RTE_LOG_REGISTER_SUFFIX(nthw_logtype_nthw, nthw, INFO);
    2793         [ -  + ]:        302 : RTE_LOG_REGISTER_SUFFIX(nthw_logtype_filter, filter, INFO);
    2794         [ -  + ]:        302 : RTE_LOG_REGISTER_SUFFIX(nthw_logtype_ntnic, ntnic, INFO);

Generated by: LCOV version 1.14