LCOV - code coverage report
Current view: top level - drivers/net/ntnic - ntnic_ethdev.c (source / functions) Hit Total Coverage
Test: Code coverage Lines: 5 1020 0.5 %
Date: 2025-03-01 20:23:48 Functions: 5 56 8.9 %
Legend: Lines: hit not hit | Branches: + taken - not taken # not executed Branches: 4 546 0.7 %

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

Generated by: LCOV version 1.14