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

Generated by: LCOV version 1.14