LCOV - code coverage report
Current view: top level - drivers/net/enetc - enetc4_vf.c (source / functions) Hit Total Coverage
Test: Code coverage Lines: 2 964 0.2 %
Date: 2026-10-01 18:19:24 Functions: 2 44 4.5 %
Legend: Lines: hit not hit | Branches: + taken - not taken # not executed Branches: 1 391 0.3 %

           Branch data     Line data    Source code
       1                 :            : /* SPDX-License-Identifier: BSD-3-Clause
       2                 :            :  * Copyright 2024-2026 NXP
       3                 :            :  */
       4                 :            : 
       5                 :            : #include <stdbool.h>
       6                 :            : #include <rte_bus_pci.h>
       7                 :            : #include <rte_kvargs.h>
       8                 :            : #include <rte_random.h>
       9                 :            : #include <dpaax_iova_table.h>
      10                 :            : #include "enetc_logs.h"
      11                 :            : #include "enetc.h"
      12                 :            : 
      13                 :            : #define ENETC4_VSI_DISABLE              "enetc4_vsi_disable"
      14                 :            : #define ENETC4_VSI_TIMEOUT              "enetc4_vsi_timeout"
      15                 :            : #define ENETC4_VSI_DELAY                "enetc4_vsi_delay"
      16                 :            : #define ENETC4_NC_MEMORY                "nc"
      17                 :            : 
      18                 :            : static void
      19                 :          0 : enetc4_vf_get_devarg_nc(struct rte_eth_dev *dev)
      20                 :            : {
      21                 :            :         struct enetc_eth_hw *hw =
      22                 :          0 :                 ENETC_DEV_PRIVATE_TO_HW(dev->data->dev_private);
      23                 :          0 :         struct rte_devargs *devargs = dev->device->devargs;
      24                 :            :         struct rte_kvargs *kvlist;
      25                 :            :         const char *val;
      26                 :            : 
      27         [ #  # ]:          0 :         if (!devargs)
      28                 :            :                 return;
      29                 :            : 
      30                 :          0 :         kvlist = rte_kvargs_parse(devargs->args, NULL);
      31         [ #  # ]:          0 :         if (!kvlist)
      32                 :            :                 return;
      33                 :            : 
      34                 :          0 :         val = rte_kvargs_get(kvlist, ENETC4_NC_MEMORY);
      35   [ #  #  #  # ]:          0 :         if (val && atoi(val) == 1)
      36                 :          0 :                 hw->nc_mode = 1;
      37                 :            : 
      38                 :          0 :         rte_kvargs_free(kvlist);
      39                 :            : }
      40                 :            : 
      41                 :            : #define ENETC_CRC_TABLE_SIZE            256
      42                 :            : #define ENETC_POLY                      0x1021
      43                 :            : #define ENETC_CRC_INIT                  0xffff
      44                 :            : #define ENETC_BYTE_SIZE                 8
      45                 :            : #define ENETC_MSB_BIT                   0x8000
      46                 :            : 
      47                 :            : /* Backward-compat devarg for a PF running a kernel before 6.18.37, which uses
      48                 :            :  * the legacy PF-to-VF link message layout (4-bit speed code + 4-bit cookie).
      49                 :            :  * Usage: -a <pci_addr>,vf_link_legacy=1
      50                 :            :  */
      51                 :            : #define ENETC_VF_LINK_LEGACY            "vf_link_legacy"
      52                 :            : 
      53                 :            : uint16_t enetc_crc_table[ENETC_CRC_TABLE_SIZE];
      54                 :            : bool enetc_crc_gen;
      55                 :            : 
      56                 :            : /* Supported Rx offloads */
      57                 :            : static uint64_t dev_rx_offloads_sup =
      58                 :            :         RTE_ETH_RX_OFFLOAD_IPV4_CKSUM |
      59                 :            :         RTE_ETH_RX_OFFLOAD_UDP_CKSUM |
      60                 :            :         RTE_ETH_RX_OFFLOAD_TCP_CKSUM |
      61                 :            :         RTE_ETH_RX_OFFLOAD_VLAN_FILTER |
      62                 :            :         RTE_ETH_RX_OFFLOAD_KEEP_CRC |
      63                 :            :         RTE_ETH_RX_OFFLOAD_TCP_LRO |
      64                 :            :         RTE_ETH_RX_OFFLOAD_SCATTER;
      65                 :            : 
      66                 :            : /* Supported Tx offloads */
      67                 :            : static uint64_t dev_tx_offloads_sup =
      68                 :            :         RTE_ETH_TX_OFFLOAD_IPV4_CKSUM |
      69                 :            :         RTE_ETH_TX_OFFLOAD_UDP_CKSUM |
      70                 :            :         RTE_ETH_TX_OFFLOAD_TCP_CKSUM |
      71                 :            :         RTE_ETH_TX_OFFLOAD_TCP_TSO |
      72                 :            :         RTE_ETH_TX_OFFLOAD_UDP_TSO |
      73                 :            :         RTE_ETH_TX_OFFLOAD_MULTI_SEGS;
      74                 :            : 
      75                 :            : static void
      76                 :          0 : enetc_gen_crc_table(void)
      77                 :            : {
      78                 :            :         uint16_t crc = 0;
      79                 :            :         uint16_t c;
      80                 :            : 
      81         [ #  # ]:          0 :         for (int i = 0; i < ENETC_CRC_TABLE_SIZE; i++) {
      82                 :            :                 crc = 0;
      83                 :          0 :                 c = i << ENETC_BYTE_SIZE;
      84         [ #  # ]:          0 :                 for (int j = 0; j < ENETC_BYTE_SIZE; j++) {
      85         [ #  # ]:          0 :                         if ((crc ^ c) & ENETC_MSB_BIT)
      86                 :          0 :                                 crc = (crc << 1) ^ ENETC_POLY;
      87                 :            :                         else
      88                 :          0 :                                 crc = crc << 1;
      89                 :          0 :                         c = c << 1;
      90                 :            :                 }
      91                 :            : 
      92                 :          0 :                 enetc_crc_table[i] = crc;
      93                 :            :         }
      94                 :            : 
      95                 :          0 :         enetc_crc_gen = true;
      96                 :          0 : }
      97                 :            : 
      98                 :            : static uint16_t
      99                 :            : enetc_crc_calc(uint16_t crc, const uint8_t *buffer, size_t len)
     100                 :            : {
     101                 :            :         uint8_t data;
     102                 :            : 
     103   [ #  #  #  #  :          0 :         while (len--) {
          #  #  #  #  #  
          #  #  #  #  #  
          #  #  #  #  #  
             #  #  #  #  
                      # ]
     104                 :          0 :                 data = *buffer;
     105                 :          0 :                 crc = (crc << 8) ^ enetc_crc_table[((crc >> 8) ^ data) & 0xff];
     106                 :          0 :                 buffer++;
     107                 :            :         }
     108                 :            :         return crc;
     109                 :            : }
     110                 :            : 
     111                 :            : static int
     112                 :          0 : parse_vf_link_legacy(const char *key __rte_unused, const char *value,
     113                 :            :                      void *opaque)
     114                 :            : {
     115                 :            :         struct rte_eth_dev *dev = (struct rte_eth_dev *)opaque;
     116                 :            :         struct enetc_eth_hw *hw =
     117                 :          0 :                         ENETC_DEV_PRIVATE_TO_HW(dev->data->dev_private);
     118                 :            :         char *endptr;
     119                 :            :         unsigned long val;
     120                 :            : 
     121   [ #  #  #  # ]:          0 :         if (!value || *value == '\0') {
     122                 :          0 :                 ENETC_PMD_WARN("Empty value for devarg %s, ignoring",
     123                 :            :                                ENETC_VF_LINK_LEGACY);
     124                 :          0 :                 return -EINVAL;
     125                 :            :         }
     126                 :            : 
     127                 :          0 :         errno = 0;
     128                 :          0 :         val = strtoul(value, &endptr, 0);
     129   [ #  #  #  #  :          0 :         if (errno != 0 || *endptr != '\0' || val > 1) {
                   #  # ]
     130                 :          0 :                 ENETC_PMD_WARN("Invalid value '%s' for devarg %s, expected 0 or 1",
     131                 :            :                                value, ENETC_VF_LINK_LEGACY);
     132                 :          0 :                 return -EINVAL;
     133                 :            :         }
     134                 :            : 
     135                 :          0 :         hw->vf_link_legacy = (uint8_t)val;
     136                 :            : 
     137                 :          0 :         return 0;
     138                 :            : }
     139                 :            : 
     140                 :            : static void
     141                 :          0 : enetc4_vf_get_devargs(struct rte_eth_dev *dev)
     142                 :            : {
     143                 :            :         struct rte_devargs *devargs;
     144                 :            :         struct rte_kvargs *kvlist;
     145                 :            : 
     146                 :          0 :         devargs = dev->device->devargs;
     147         [ #  # ]:          0 :         if (!devargs)
     148                 :            :                 return;
     149                 :            : 
     150                 :          0 :         kvlist = rte_kvargs_parse(devargs->args, NULL);
     151         [ #  # ]:          0 :         if (!kvlist)
     152                 :            :                 return;
     153                 :            : 
     154         [ #  # ]:          0 :         if (rte_kvargs_count(kvlist, ENETC_VF_LINK_LEGACY)) {
     155         [ #  # ]:          0 :                 if (rte_kvargs_process(kvlist, ENETC_VF_LINK_LEGACY,
     156                 :            :                                        parse_vf_link_legacy, (void *)dev) < 0)
     157                 :          0 :                         ENETC_PMD_WARN("Failed to parse devarg %s",
     158                 :            :                                        ENETC_VF_LINK_LEGACY);
     159                 :            :         }
     160                 :            : 
     161                 :          0 :         rte_kvargs_free(kvlist);
     162                 :            : }
     163                 :            : 
     164                 :            : static int
     165                 :          0 : enetc4_vf_dev_infos_get(struct rte_eth_dev *dev,
     166                 :            :                         struct rte_eth_dev_info *dev_info)
     167                 :            : {
     168                 :            :         struct enetc_eth_hw *hw =
     169                 :          0 :                 ENETC_DEV_PRIVATE_TO_HW(dev->data->dev_private);
     170                 :            : 
     171                 :          0 :         PMD_INIT_FUNC_TRACE();
     172                 :            : 
     173                 :          0 :         dev_info->rx_desc_lim = (struct rte_eth_desc_lim) {
     174                 :            :                 .nb_max = MAX_BD_COUNT,
     175                 :            :                 .nb_min = MIN_BD_COUNT,
     176                 :            :                 .nb_align = BD_ALIGN,
     177                 :            :                 .nb_seg_max = ENETC4_MAX_SEGS,
     178                 :            :                 .nb_mtu_seg_max = ENETC4_MAX_SEGS,
     179                 :            :         };
     180                 :          0 :         dev_info->tx_desc_lim = (struct rte_eth_desc_lim) {
     181                 :            :                 .nb_max = MAX_BD_COUNT,
     182                 :            :                 .nb_min = MIN_BD_COUNT,
     183                 :            :                 .nb_align = BD_ALIGN,
     184                 :            :                 .nb_seg_max = ENETC4_MAX_SEGS,
     185                 :            :                 .nb_mtu_seg_max = ENETC4_MAX_SEGS,
     186                 :            :         };
     187                 :          0 :         dev_info->max_rx_queues = hw->max_rx_queues;
     188                 :          0 :         dev_info->max_tx_queues = hw->max_tx_queues;
     189                 :          0 :         dev_info->max_rx_pktlen = ENETC4_MAC_MAXFRM_SIZE;
     190                 :          0 :         dev_info->max_mtu = dev_info->max_rx_pktlen - (RTE_ETHER_HDR_LEN + RTE_ETHER_CRC_LEN);
     191                 :          0 :         dev_info->max_mac_addrs = ENETC4_MAC_ENTRIES;
     192                 :          0 :         dev_info->rx_offload_capa = dev_rx_offloads_sup;
     193                 :          0 :         dev_info->tx_offload_capa = dev_tx_offloads_sup;
     194                 :          0 :         dev_info->flow_type_rss_offloads = ENETC_RSS_OFFLOAD_ALL;
     195                 :            : 
     196                 :          0 :         return 0;
     197                 :            : }
     198                 :            : 
     199                 :            : 
     200                 :            : int
     201                 :          0 : enetc4_vf_dev_stop(struct rte_eth_dev *dev __rte_unused)
     202                 :            : {
     203                 :          0 :         PMD_INIT_FUNC_TRACE();
     204                 :            : 
     205                 :          0 :         return 0;
     206                 :            : }
     207                 :            : 
     208                 :            : static int
     209                 :          0 : enetc4_vf_dev_start(struct rte_eth_dev *dev __rte_unused)
     210                 :            : {
     211                 :          0 :         PMD_INIT_FUNC_TRACE();
     212                 :            : 
     213                 :          0 :         return 0;
     214                 :            : }
     215                 :            : 
     216                 :            : static int
     217                 :          0 : enetc4_vf_stats_get(struct rte_eth_dev *dev, struct rte_eth_stats *stats,
     218                 :            :                     struct eth_queue_stats *qstats __rte_unused)
     219                 :            : {
     220                 :            :         struct enetc_eth_hw *hw =
     221                 :          0 :                 ENETC_DEV_PRIVATE_TO_HW(dev->data->dev_private);
     222                 :            :         struct enetc_hw *enetc_hw = &hw->hw;
     223                 :            :         struct enetc_bdr *rx_ring;
     224                 :            :         uint8_t i;
     225                 :            : 
     226                 :          0 :         PMD_INIT_FUNC_TRACE();
     227                 :            : 
     228                 :            :         /*
     229                 :            :          * The SI-level counters are read-only for a VF; they cannot be
     230                 :            :          * zeroed directly. Instead, stats_reset captures a baseline
     231                 :            :          * snapshot, and stats_get reports the delta so that the reported
     232                 :            :          * values appear to start from zero after each reset call.
     233                 :            :          */
     234                 :          0 :         stats->ipackets = enetc4_rd64(enetc_hw, ENETC4_SIRFRM0) -
     235                 :          0 :                           hw->vf_stats_saved.ipackets;
     236                 :          0 :         stats->opackets = enetc4_rd64(enetc_hw, ENETC4_SITFRM0) -
     237                 :          0 :                           hw->vf_stats_saved.opackets;
     238                 :          0 :         stats->ibytes   = enetc4_rd64(enetc_hw, ENETC4_SIROCT0) -
     239                 :          0 :                           hw->vf_stats_saved.ibytes;
     240                 :          0 :         stats->obytes   = enetc4_rd64(enetc_hw, ENETC4_SITOCT0) -
     241                 :          0 :                           hw->vf_stats_saved.obytes;
     242                 :          0 :         stats->oerrors  = (uint32_t)enetc4_rd(enetc_hw, ENETC4_SITDFCR) -
     243                 :          0 :                           (uint32_t)hw->vf_stats_saved.oerrors;
     244                 :            : 
     245         [ #  # ]:          0 :         for (i = 0; i < dev->data->nb_rx_queues; i++) {
     246                 :          0 :                 rx_ring = dev->data->rx_queues[i];
     247                 :          0 :                 stats->ierrors += rx_ring->ierrors;
     248                 :            :         }
     249                 :            : 
     250                 :          0 :         return 0;
     251                 :            : }
     252                 :            : 
     253                 :            : /*
     254                 :            :  * Reset VF statistics by capturing a new baseline snapshot of the
     255                 :            :  * SI-level hardware counters. Because those counters are read-only
     256                 :            :  * for a VF (hardware erratum prevents reliable clear via FLR/soft
     257                 :            :  * reset too), the driver uses a software delta approach: every
     258                 :            :  * stats_get call reports current_hw_value - saved_baseline.
     259                 :            :  */
     260                 :            : static int
     261                 :          0 : enetc4_vf_stats_reset(struct rte_eth_dev *dev)
     262                 :            : {
     263                 :            :         struct enetc_eth_hw *hw =
     264                 :          0 :                 ENETC_DEV_PRIVATE_TO_HW(dev->data->dev_private);
     265                 :            :         struct enetc_hw *enetc_hw = &hw->hw;
     266                 :            :         struct enetc_bdr *rx_ring;
     267                 :            :         uint8_t i;
     268                 :            : 
     269                 :          0 :         PMD_INIT_FUNC_TRACE();
     270                 :            : 
     271                 :            :         /* Snapshot current HW SI counter values as the new zero baseline. */
     272                 :          0 :         hw->vf_stats_saved.ipackets = enetc4_rd64(enetc_hw, ENETC4_SIRFRM0);
     273                 :          0 :         hw->vf_stats_saved.opackets = enetc4_rd64(enetc_hw, ENETC4_SITFRM0);
     274                 :          0 :         hw->vf_stats_saved.ibytes   = enetc4_rd64(enetc_hw, ENETC4_SIROCT0);
     275                 :          0 :         hw->vf_stats_saved.obytes   = enetc4_rd64(enetc_hw, ENETC4_SITOCT0);
     276                 :          0 :         hw->vf_stats_saved.oerrors  = enetc4_rd(enetc_hw, ENETC4_SITDFCR);
     277                 :            : 
     278                 :            :         /* Reset the per-ring software Rx error accumulators. */
     279         [ #  # ]:          0 :         for (i = 0; i < dev->data->nb_rx_queues; i++) {
     280                 :          0 :                 rx_ring = dev->data->rx_queues[i];
     281         [ #  # ]:          0 :                 if (rx_ring)
     282                 :          0 :                         rx_ring->ierrors = 0;
     283                 :            :         }
     284                 :            : 
     285                 :          0 :         return 0;
     286                 :            : }
     287                 :            : 
     288                 :            : 
     289                 :            : static void
     290                 :            : enetc_msg_vf_fill_common_hdr(struct enetc_msg_swbd *msg,
     291                 :            :                                         uint8_t class_id, uint8_t cmd_id, uint8_t proto_ver,
     292                 :            :                                         uint8_t len, uint8_t cookie)
     293                 :            : {
     294                 :          0 :         struct enetc_msg_cmd_header *hdr = msg->vaddr;
     295                 :            : 
     296                 :          0 :         hdr->class_id = class_id;
     297                 :          0 :         hdr->cmd_id = cmd_id;
     298                 :          0 :         hdr->proto_ver = proto_ver;
     299                 :          0 :         hdr->len = len;
     300                 :          0 :         hdr->cookie = cookie;
     301                 :            :         /* Incrementing msg 2 bytes ahead as the first two bytes are for CRC */
     302                 :          0 :         hdr->csum = rte_cpu_to_be_16(enetc_crc_calc(ENETC_CRC_INIT,
     303                 :            :                                 (uint8_t *)msg->vaddr + sizeof(uint16_t),
     304                 :            :                                 msg->size - sizeof(uint16_t)));
     305                 :            : 
     306                 :            :         dcbf(hdr);
     307                 :          0 : }
     308                 :            : 
     309                 :            : /* Messaging */
     310                 :            : static void
     311                 :            : enetc4_msg_vsi_write_msg(struct enetc_hw *hw,
     312                 :            :                 struct enetc_msg_swbd *msg)
     313                 :            : {
     314                 :            :         uint32_t val;
     315                 :            : 
     316         [ #  # ]:          0 :         val = enetc_vsi_set_msize(msg->size) | lower_32_bits(msg->dma);
     317                 :          0 :         enetc_wr(hw, ENETC4_VSIMSGSNDAR1, upper_32_bits(msg->dma));
     318                 :          0 :         enetc_wr(hw, ENETC4_VSIMSGSNDAR0, val);
     319                 :          0 : }
     320                 :            : 
     321                 :            : static void
     322                 :            : enetc4_msg_vsi_reply_msg(struct enetc_eth_hw *hw, int vsimsgsr,
     323                 :            :                          struct enetc_psi_reply_msg *reply_msg)
     324                 :            : {
     325                 :            :         int8_t class_id = 0;
     326                 :            :         uint8_t status = 0;
     327                 :            : 
     328                 :            :         /* Extracting 8 bits of message result in class_id */
     329                 :          0 :         class_id |= ((ENETC_SIMSGSR_GET_MC(vsimsgsr) >> 8) & 0xff);
     330                 :            : 
     331                 :            :         /* Extracting message result in status. With an older kernel PF
     332                 :            :          * (vf_link_legacy set) the lower byte holds a 4-bit cookie in the
     333                 :            :          * low nibble and a 4-bit result in the high nibble, so extract the
     334                 :            :          * upper 4 bits. Otherwise the full lower byte carries the result.
     335                 :            :          */
     336                 :          0 :         if (hw->vf_link_legacy)
     337                 :          0 :                 status |= ((ENETC_SIMSGSR_GET_MC(vsimsgsr) >> 4) & 0xf);
     338                 :            :         else
     339                 :          0 :                 status |= (ENETC_SIMSGSR_GET_MC(vsimsgsr) & 0xff);
     340                 :            : 
     341                 :          0 :         reply_msg->class_id = class_id;
     342                 :          0 :         reply_msg->status = status;
     343                 :          0 : }
     344                 :            : 
     345                 :            : static void
     346                 :            : enetc4_msg_get_psi_msg(struct enetc_hw *enetc_hw, struct enetc_psi_reply_msg *reply_msg)
     347                 :            : {
     348                 :          0 :         struct enetc_eth_hw *hw = container_of(enetc_hw, struct enetc_eth_hw, hw);
     349                 :            :         int vsimsgrr;
     350                 :            :         int8_t class_id = 0;
     351                 :            :         uint8_t status = 0;
     352                 :            : 
     353                 :          0 :         vsimsgrr = enetc_rd(enetc_hw, ENETC4_VSIMSGRR);
     354                 :            : 
     355                 :            :         /* Extracting 8 bits of message result in class_id */
     356                 :          0 :         class_id |= ((ENETC_SIMSGSR_GET_MC(vsimsgrr) >> 8) & 0xff);
     357                 :            : 
     358                 :            :         /* Extracting message result in status. With an older kernel PF
     359                 :            :          * (vf_link_legacy set) the lower byte holds a 4-bit cookie in the
     360                 :            :          * low nibble and a 4-bit result in the high nibble, so extract the
     361                 :            :          * upper 4 bits. Otherwise the full lower byte carries the result.
     362                 :            :          */
     363         [ #  # ]:          0 :         if (hw->vf_link_legacy)
     364                 :          0 :                 status |= ((ENETC_SIMSGSR_GET_MC(vsimsgrr) >> 4) & 0xf);
     365                 :            :         else
     366                 :          0 :                 status |= (ENETC_SIMSGSR_GET_MC(vsimsgrr) & 0xff);
     367                 :            : 
     368                 :          0 :         reply_msg->class_id = class_id;
     369                 :          0 :         reply_msg->status = status;
     370                 :            : }
     371                 :            : 
     372                 :            : /* Forward declaration: defined later in this file */
     373                 :            : static int enetc4_vf_get_link_speed(struct rte_eth_dev *dev,
     374                 :            :                                      struct enetc_psi_reply_msg *reply_msg);
     375                 :            : 
     376                 :            : /*
     377                 :            :  * Decode a PF-to-VF link-speed status code into the link_speed and
     378                 :            :  * link_duplex fields of *link.  vf_link_legacy selects the older
     379                 :            :  * 4-bit code layout used by kernel PFs before v6.18.37.
     380                 :            :  */
     381                 :            : static void
     382                 :          0 : enetc4_decode_link_speed(uint8_t status, bool vf_link_legacy,
     383                 :            :                          struct rte_eth_link *link)
     384                 :            : {
     385   [ #  #  #  #  :          0 :         switch (status) {
             #  #  #  #  
                      # ]
     386                 :          0 :         case ENETC_SPEED_UNKNOWN:
     387                 :          0 :                 ENETC_PMD_DEBUG("Speed unknown");
     388                 :          0 :                 link->link_speed = RTE_ETH_SPEED_NUM_NONE;
     389                 :          0 :                 break;
     390                 :          0 :         case ENETC_SPEED_10_HALF_DUPLEX:
     391                 :          0 :                 link->link_speed = RTE_ETH_SPEED_NUM_10M;
     392                 :          0 :                 link->link_duplex = RTE_ETH_LINK_HALF_DUPLEX;
     393                 :          0 :                 break;
     394                 :          0 :         case ENETC_SPEED_10_FULL_DUPLEX:
     395                 :          0 :                 link->link_speed = RTE_ETH_SPEED_NUM_10M;
     396                 :          0 :                 link->link_duplex = RTE_ETH_LINK_FULL_DUPLEX;
     397                 :          0 :                 break;
     398                 :          0 :         case ENETC_SPEED_100_HALF_DUPLEX:
     399                 :          0 :                 link->link_speed = RTE_ETH_SPEED_NUM_100M;
     400                 :          0 :                 link->link_duplex = RTE_ETH_LINK_HALF_DUPLEX;
     401                 :          0 :                 break;
     402                 :          0 :         case ENETC_SPEED_100_FULL_DUPLEX:
     403                 :          0 :                 link->link_speed = RTE_ETH_SPEED_NUM_100M;
     404                 :          0 :                 link->link_duplex = RTE_ETH_LINK_FULL_DUPLEX;
     405                 :          0 :                 break;
     406                 :          0 :         case ENETC_SPEED_1000:
     407                 :          0 :                 link->link_speed = RTE_ETH_SPEED_NUM_1G;
     408                 :          0 :                 link->link_duplex = RTE_ETH_LINK_FULL_DUPLEX;
     409                 :          0 :                 break;
     410                 :          0 :         case ENETC_SPEED_2500:
     411                 :          0 :                 link->link_speed = RTE_ETH_SPEED_NUM_2_5G;
     412                 :          0 :                 link->link_duplex = RTE_ETH_LINK_FULL_DUPLEX;
     413                 :          0 :                 break;
     414                 :          0 :         case ENETC_SPEED_5000:
     415                 :          0 :                 link->link_speed = RTE_ETH_SPEED_NUM_5G;
     416                 :          0 :                 link->link_duplex = RTE_ETH_LINK_FULL_DUPLEX;
     417                 :          0 :                 break;
     418                 :          0 :         default:
     419         [ #  # ]:          0 :                 if (vf_link_legacy) {
     420                 :            :                         /* Legacy PF-to-VF message layout (older kernel PF):
     421                 :            :                          * speeds above 5Gbps use fixed 4-bit class codes.
     422                 :            :                          */
     423                 :            :                         switch (status) {
     424                 :          0 :                         case ENETC_SPEED_LEGACY_10G:
     425                 :          0 :                                 link->link_speed = RTE_ETH_SPEED_NUM_10G;
     426                 :          0 :                                 link->link_duplex = RTE_ETH_LINK_FULL_DUPLEX;
     427                 :          0 :                                 break;
     428                 :          0 :                         case ENETC_SPEED_LEGACY_25G:
     429                 :          0 :                                 link->link_speed = RTE_ETH_SPEED_NUM_25G;
     430                 :          0 :                                 link->link_duplex = RTE_ETH_LINK_FULL_DUPLEX;
     431                 :          0 :                                 break;
     432                 :          0 :                         case ENETC_SPEED_LEGACY_50G:
     433                 :          0 :                                 link->link_speed = RTE_ETH_SPEED_NUM_50G;
     434                 :          0 :                                 link->link_duplex = RTE_ETH_LINK_FULL_DUPLEX;
     435                 :          0 :                                 break;
     436                 :          0 :                         case ENETC_SPEED_LEGACY_100G:
     437                 :          0 :                                 link->link_speed = RTE_ETH_SPEED_NUM_100G;
     438                 :          0 :                                 link->link_duplex = RTE_ETH_LINK_FULL_DUPLEX;
     439                 :          0 :                                 break;
     440                 :          0 :                         case ENETC_SPEED_LEGACY_NOT_SUPPORTED:
     441                 :          0 :                                 ENETC_PMD_DEBUG("Speed not supported");
     442                 :          0 :                                 link->link_speed = RTE_ETH_SPEED_NUM_UNKNOWN;
     443                 :          0 :                                 break;
     444                 :          0 :                         default:
     445                 :          0 :                                 ENETC_PMD_ERR("Unknown speed status");
     446                 :          0 :                                 link->link_speed = RTE_ETH_SPEED_NUM_UNKNOWN;
     447                 :          0 :                                 break;
     448                 :            :                         }
     449                 :            :                         break;
     450                 :            :                 }
     451                 :            :                 /* Any status here is > ENETC_SPEED_5000. Validate against
     452                 :            :                  * the set of speeds that the NETC IP is known to support.
     453                 :            :                  * An unrecognised code yields UNKNOWN rather than a
     454                 :            :                  * fabricated speed.
     455                 :            :                  */
     456   [ #  #  #  #  :          0 :                 switch ((status - ENETC_SPEED_5000) * 1000 + 5000) {
                #  #  # ]
     457                 :          0 :                 case RTE_ETH_SPEED_NUM_10G:
     458                 :          0 :                         link->link_speed = RTE_ETH_SPEED_NUM_10G;
     459                 :          0 :                         link->link_duplex = RTE_ETH_LINK_FULL_DUPLEX;
     460                 :          0 :                         break;
     461                 :          0 :                 case RTE_ETH_SPEED_NUM_25G:
     462                 :          0 :                         link->link_speed = RTE_ETH_SPEED_NUM_25G;
     463                 :          0 :                         link->link_duplex = RTE_ETH_LINK_FULL_DUPLEX;
     464                 :          0 :                         break;
     465                 :          0 :                 case RTE_ETH_SPEED_NUM_40G:
     466                 :          0 :                         link->link_speed = RTE_ETH_SPEED_NUM_40G;
     467                 :          0 :                         link->link_duplex = RTE_ETH_LINK_FULL_DUPLEX;
     468                 :          0 :                         break;
     469                 :          0 :                 case RTE_ETH_SPEED_NUM_50G:
     470                 :          0 :                         link->link_speed = RTE_ETH_SPEED_NUM_50G;
     471                 :          0 :                         link->link_duplex = RTE_ETH_LINK_FULL_DUPLEX;
     472                 :          0 :                         break;
     473                 :          0 :                 case RTE_ETH_SPEED_NUM_100G:
     474                 :          0 :                         link->link_speed = RTE_ETH_SPEED_NUM_100G;
     475                 :          0 :                         link->link_duplex = RTE_ETH_LINK_FULL_DUPLEX;
     476                 :          0 :                         break;
     477                 :          0 :                 case RTE_ETH_SPEED_NUM_200G:
     478                 :          0 :                         link->link_speed = RTE_ETH_SPEED_NUM_200G;
     479                 :          0 :                         link->link_duplex = RTE_ETH_LINK_FULL_DUPLEX;
     480                 :          0 :                         break;
     481                 :          0 :                 default:
     482                 :          0 :                         ENETC_PMD_WARN("Unrecognized speed code 0x%x, "
     483                 :            :                                        "reporting unknown", status);
     484                 :          0 :                         link->link_speed = RTE_ETH_SPEED_NUM_UNKNOWN;
     485                 :          0 :                         break;
     486                 :            :                 }
     487                 :            :                 break;
     488                 :            :         }
     489                 :          0 : }
     490                 :            : 
     491                 :            : /*
     492                 :            :  * Set or clear ENETC_RBMR_CM (congestion mode) on all active VF RX rings.
     493                 :            :  * When set, the ring signals congestion to the MAC, causing it to emit TX
     494                 :            :  * PAUSE frames on ingress pressure. hw->tx_pause_active is updated so rings
     495                 :            :  * started later inherit the correct state.
     496                 :            :  */
     497                 :            : static void
     498                 :          0 : enetc4_vf_set_congestion_mode(struct rte_eth_dev *eth_dev, bool enable)
     499                 :            : {
     500                 :            :         struct enetc_eth_hw *hw =
     501                 :          0 :                 ENETC_DEV_PRIVATE_TO_HW(eth_dev->data->dev_private);
     502                 :            :         struct enetc_hw *enetc_hw = &hw->hw;
     503                 :          0 :         uint16_t nb_rx = eth_dev->data->nb_rx_queues;
     504                 :            :         uint16_t i;
     505                 :            :         uint32_t rbmr;
     506                 :            : 
     507                 :          0 :         pthread_mutex_lock(&hw->vsi_lock);
     508                 :            : 
     509                 :          0 :         if (rte_atomic_load_explicit(&hw->tx_pause_active,
     510                 :            :                                      rte_memory_order_relaxed) ==
     511         [ #  # ]:          0 :             (enable ? 1 : 0)) {
     512                 :          0 :                 pthread_mutex_unlock(&hw->vsi_lock);
     513                 :          0 :                 return;
     514                 :            :         }
     515                 :            : 
     516                 :          0 :         rte_atomic_store_explicit(&hw->tx_pause_active, enable ? 1 : 0,
     517                 :            :                                   rte_memory_order_relaxed);
     518                 :            : 
     519         [ #  # ]:          0 :         for (i = 0; i < nb_rx; i++) {
     520                 :          0 :                 rbmr = enetc4_rxbdr_rd(enetc_hw, i, ENETC_RBMR);
     521         [ #  # ]:          0 :                 if (enable)
     522                 :          0 :                         rbmr |= ENETC_RBMR_CM;
     523                 :            :                 else
     524                 :          0 :                         rbmr &= ~(uint32_t)ENETC_RBMR_CM;
     525                 :          0 :                 enetc4_rxbdr_wr(enetc_hw, i, ENETC_RBMR, rbmr);
     526                 :            :         }
     527                 :          0 :         pthread_mutex_unlock(&hw->vsi_lock);
     528                 :            : 
     529         [ #  # ]:          0 :         ENETC_PMD_DEBUG("VF congestion mode %s on %u RX rings",
     530                 :            :                         enable ? "enabled" : "disabled", nb_rx);
     531                 :            : }
     532                 :            : 
     533                 :            : static void
     534                 :          0 : enetc4_process_psi_msg(struct rte_eth_dev *eth_dev, struct enetc_hw *enetc_hw)
     535                 :            : {
     536                 :            :         struct enetc_eth_hw *hw =
     537                 :          0 :                 ENETC_DEV_PRIVATE_TO_HW(eth_dev->data->dev_private);
     538                 :            :         struct enetc_psi_reply_msg *msg;
     539                 :            :         struct rte_eth_link link;
     540                 :            :         bool tx_pause;
     541                 :            :         int ret = 0;
     542                 :            : 
     543                 :          0 :         msg = rte_zmalloc(NULL, sizeof(*msg), RTE_CACHE_LINE_SIZE);
     544         [ #  # ]:          0 :         if (!msg) {
     545                 :          0 :                 ENETC_PMD_ERR("Failed to alloc memory for msg");
     546                 :          0 :                 return;
     547                 :            :         }
     548                 :            : 
     549                 :          0 :         rte_eth_linkstatus_get(eth_dev, &link);
     550                 :            :         enetc4_msg_get_psi_msg(enetc_hw, msg);
     551                 :            : 
     552         [ #  # ]:          0 :         if (msg->class_id == ENETC_CLASS_ID_LINK_STATUS) {
     553         [ #  # ]:          0 :                 if (msg->status & ENETC_LINK_DOWN) {
     554                 :          0 :                         ENETC_PMD_DEBUG("Link is down");
     555                 :          0 :                         link.link_status = RTE_ETH_LINK_DOWN;
     556                 :            :                         /* Clear congestion mode on link-down so VF rings do not
     557                 :            :                          * assert congestion while the port is offline.
     558                 :            :                          */
     559                 :          0 :                         enetc4_vf_set_congestion_mode(eth_dev, false);
     560                 :            :                 } else {
     561                 :            :                         /* BIT(1) is set when the port has negotiated TX PAUSE.
     562                 :            :                          * Legacy PF does not set this bit so tx_pause stays false.
     563                 :            :                          */
     564                 :          0 :                         tx_pause = !!(msg->status & ENETC_LINK_TX_PAUSE);
     565                 :          0 :                         ENETC_PMD_DEBUG("Link is up, tx_pause=%d", tx_pause);
     566                 :          0 :                         link.link_status = RTE_ETH_LINK_UP;
     567                 :            : 
     568                 :            :                         /* Apply congestion mode before raising the carrier so
     569                 :            :                          * the VF rings are ready to emit PAUSE before traffic
     570                 :            :                          * starts flowing.
     571                 :            :                          */
     572                 :          0 :                         enetc4_vf_set_congestion_mode(eth_dev, tx_pause);
     573                 :            : 
     574                 :            :                         /* Re-query speed from PF so the cached value reflects
     575                 :            :                          * the current negotiated speed after link-up. This is a
     576                 :            :                          * mailbox round trip issued from the link-status
     577                 :            :                          * interrupt handler, which runs on the shared EAL
     578                 :            :                          * interrupt thread with the mailbox interrupt masked, so
     579                 :            :                          * it busy-waits up to (vsi_timeout * vsi_delay) us
     580                 :            :                          * (by default 100 * 2000 us = 200 ms). If this stall on
     581                 :            :                          * the EAL interrupt thread ever becomes a problem, reduce
     582                 :            :                          * the wait budget with the "enetc4_vsi_timeout" and
     583                 :            :                          * "enetc4_vsi_delay" devargs.
     584                 :            :                          */
     585                 :            :                         memset(msg, 0, sizeof(*msg));
     586         [ #  # ]:          0 :                         if (!enetc4_vf_get_link_speed(eth_dev, msg) &&
     587         [ #  # ]:          0 :                             msg->class_id == ENETC_CLASS_ID_LINK_SPEED)
     588                 :          0 :                                 enetc4_decode_link_speed(msg->status,
     589                 :          0 :                                                         hw->vf_link_legacy,
     590                 :            :                                                         &link);
     591                 :            :                 }
     592                 :            :                 ret = rte_eth_linkstatus_set(eth_dev, &link);
     593                 :            :                 if (!ret)
     594                 :          0 :                         ENETC_PMD_DEBUG("Link status has been changed");
     595                 :            : 
     596                 :            :                 /* Process user registered callback */
     597                 :          0 :                 rte_eth_dev_callback_process(eth_dev,
     598                 :            :                         RTE_ETH_EVENT_INTR_LSC, NULL);
     599                 :            :         } else {
     600                 :          0 :                 ENETC_PMD_ERR("Wrong message 0x%x", msg->class_id);
     601                 :            :         }
     602                 :            : 
     603                 :          0 :         rte_free(msg);
     604                 :            : }
     605                 :            : 
     606                 :            : static int
     607                 :          0 : enetc4_msg_vsi_send(struct enetc_eth_hw *hw, struct enetc_msg_swbd *msg,
     608                 :            :                     int *vsimsgsr_out)
     609                 :            : {
     610                 :            :         struct enetc_hw *enetc_hw = &hw->hw;
     611         [ #  # ]:          0 :         int timeout = hw->vsi_timeout ? (int)hw->vsi_timeout :
     612                 :            :                                         ENETC4_DEF_VSI_WAIT_TIMEOUT_UPDATE;
     613         [ #  # ]:          0 :         int delay_us = hw->vsi_delay ? (int)hw->vsi_delay :
     614                 :            :                                        ENETC4_DEF_VSI_WAIT_DELAY_UPDATE;
     615                 :            :         uint8_t class_id = 0;
     616                 :            :         int err = 0;
     617                 :            :         int vsimsgsr;
     618                 :            : 
     619                 :          0 :         pthread_mutex_lock(&hw->vsi_lock);
     620                 :            :         enetc4_msg_vsi_write_msg(enetc_hw, msg);
     621                 :            : 
     622                 :            :         do {
     623                 :          0 :                 vsimsgsr = enetc_rd(enetc_hw, ENETC4_VSIMSGSR);
     624         [ #  # ]:          0 :                 if (!(vsimsgsr & ENETC4_VSIMSGSR_MB))
     625                 :            :                         break;
     626                 :          0 :                 rte_delay_us(delay_us);
     627         [ #  # ]:          0 :         } while (--timeout);
     628                 :            : 
     629         [ #  # ]:          0 :         if (!timeout) {
     630                 :          0 :                 ENETC_PMD_ERR("Message not processed by PSI");
     631                 :          0 :                 pthread_mutex_unlock(&hw->vsi_lock);
     632                 :          0 :                 return -ETIMEDOUT;
     633                 :            :         }
     634                 :            :         /* check for message delivery error */
     635         [ #  # ]:          0 :         if (vsimsgsr & ENETC4_VSIMSGSR_MS) {
     636                 :          0 :                 ENETC_PMD_ERR("Transfer error when copying the data");
     637                 :          0 :                 pthread_mutex_unlock(&hw->vsi_lock);
     638                 :          0 :                 return -EIO;
     639                 :            :         }
     640                 :            : 
     641                 :          0 :         class_id |= ((ENETC_SIMSGSR_GET_MC(vsimsgsr) >> 8) & 0xff);
     642                 :            : 
     643                 :            :         /* Check the user-defined completion status. */
     644         [ #  # ]:          0 :         if (class_id != ENETC_MSG_CLASS_ID_CMD_SUCCESS) {
     645   [ #  #  #  #  :          0 :                 switch (class_id) {
             #  #  #  #  
                      # ]
     646                 :          0 :                 case ENETC_MSG_CLASS_ID_PERMISSION_DENY:
     647                 :          0 :                         ENETC_PMD_ERR("Permission denied");
     648                 :            :                         err = -EACCES;
     649                 :          0 :                         break;
     650                 :          0 :                 case ENETC_MSG_CLASS_ID_CMD_NOT_SUPPORT:
     651                 :          0 :                         ENETC_PMD_ERR("Command not supported");
     652                 :            :                         err = -EOPNOTSUPP;
     653                 :          0 :                         break;
     654                 :          0 :                 case ENETC_MSG_CLASS_ID_PSI_BUSY:
     655                 :          0 :                         ENETC_PMD_ERR("PSI Busy");
     656                 :            :                         err = -EBUSY;
     657                 :          0 :                         break;
     658                 :          0 :                 case ENETC_MSG_CLASS_ID_CMD_TIMEOUT:
     659                 :          0 :                         ENETC_PMD_ERR("Command timeout");
     660                 :            :                         err = -ETIME;
     661                 :          0 :                         break;
     662                 :          0 :                 case ENETC_MSG_CLASS_ID_CRC_ERROR:
     663                 :          0 :                         ENETC_PMD_ERR("CRC error");
     664                 :            :                         err = -EIO;
     665                 :          0 :                         break;
     666                 :          0 :                 case ENETC_MSG_CLASS_ID_PROTO_NOT_SUPPORT:
     667                 :          0 :                         ENETC_PMD_ERR("Protocol Version not supported");
     668                 :            :                         err = -EOPNOTSUPP;
     669                 :          0 :                         break;
     670                 :          0 :                 case ENETC_MSG_CLASS_ID_INVALID_MSG_LEN:
     671                 :          0 :                         ENETC_PMD_ERR("Invalid message length");
     672                 :            :                         err = -EINVAL;
     673                 :          0 :                         break;
     674                 :            :                 case ENETC_CLASS_ID_MAC_FILTER:
     675                 :            :                 case ENETC_CLASS_ID_LINK_STATUS:
     676                 :            :                 case ENETC_CLASS_ID_LINK_SPEED:
     677                 :            :                 case ENETC_CLASS_ID_GET_IP_VER:
     678                 :            :                         break;
     679                 :          0 :                 default:
     680                 :            :                         err = -EIO;
     681                 :            :                 }
     682                 :            :         }
     683                 :            : 
     684         [ #  # ]:          0 :         if (vsimsgsr_out != NULL)
     685                 :          0 :                 *vsimsgsr_out = vsimsgsr;
     686                 :          0 :         pthread_mutex_unlock(&hw->vsi_lock);
     687                 :          0 :         return err;
     688                 :            : }
     689                 :            : 
     690                 :            : static int
     691                 :          0 : enetc4_vf_set_mac_addr(struct rte_eth_dev *dev, struct rte_ether_addr *addr)
     692                 :            : {
     693                 :          0 :         struct enetc_eth_hw *hw = ENETC_DEV_PRIVATE_TO_HW(dev->data->dev_private);
     694                 :            :         struct enetc_msg_cmd_set_primary_mac *cmd;
     695                 :            :         struct enetc_msg_swbd *msg;
     696                 :            :         struct enetc_psi_reply_msg *reply_msg;
     697                 :            :         uint32_t msg_size;
     698                 :            :         int err = 0;
     699                 :          0 :         int vsimsgsr_mac_set = 0;
     700                 :            : 
     701                 :          0 :         PMD_INIT_FUNC_TRACE();
     702                 :          0 :         reply_msg = rte_zmalloc(NULL, sizeof(*reply_msg), RTE_CACHE_LINE_SIZE);
     703         [ #  # ]:          0 :         if (!reply_msg) {
     704                 :          0 :                 ENETC_PMD_ERR("Failed to alloc memory for reply_msg");
     705                 :          0 :                 return -ENOMEM;
     706                 :            :         }
     707                 :            : 
     708                 :          0 :         msg = rte_zmalloc(NULL, sizeof(*msg), RTE_CACHE_LINE_SIZE);
     709         [ #  # ]:          0 :         if (!msg) {
     710                 :          0 :                 ENETC_PMD_ERR("Failed to alloc msg");
     711                 :            :                 err = -ENOMEM;
     712                 :          0 :                 rte_free(reply_msg);
     713                 :          0 :                 return err;
     714                 :            :         }
     715                 :            : 
     716                 :            :         msg_size = RTE_ALIGN(sizeof(struct enetc_msg_cmd_set_primary_mac),
     717                 :            :                                 ENETC_VSI_PSI_MSG_SIZE);
     718                 :          0 :         msg->vaddr = rte_zmalloc(NULL, msg_size, 0);
     719         [ #  # ]:          0 :         if (!msg->vaddr) {
     720                 :          0 :                 ENETC_PMD_ERR("Failed to alloc memory for msg");
     721                 :          0 :                 rte_free(msg);
     722                 :          0 :                 rte_free(reply_msg);
     723                 :          0 :                 return -ENOMEM;
     724                 :            :         }
     725                 :            : 
     726                 :          0 :         msg->dma = rte_mem_virt2iova((const void *)msg->vaddr);
     727                 :          0 :         msg->size = msg_size;
     728                 :            : 
     729                 :          0 :         cmd = (struct enetc_msg_cmd_set_primary_mac *)msg->vaddr;
     730                 :            : 
     731                 :          0 :         cmd->count = 0;
     732                 :          0 :         memcpy(&cmd->addr.addr_bytes, addr, sizeof(struct rte_ether_addr));
     733                 :            : 
     734                 :            :         enetc_msg_vf_fill_common_hdr(msg, ENETC_CLASS_ID_MAC_FILTER,
     735                 :            :                                         ENETC_CMD_ID_SET_PRIMARY_MAC, 0, 0, 0);
     736                 :            : 
     737                 :            :         /* send the command and wait */
     738                 :          0 :         err = enetc4_msg_vsi_send(hw, msg, &vsimsgsr_mac_set);
     739         [ #  # ]:          0 :         if (err) {
     740                 :          0 :                 ENETC_PMD_ERR("VSI message send error");
     741                 :          0 :                 goto end;
     742                 :            :         }
     743                 :            : 
     744         [ #  # ]:          0 :         enetc4_msg_vsi_reply_msg(hw, vsimsgsr_mac_set, reply_msg);
     745                 :            : 
     746         [ #  # ]:          0 :         if (reply_msg->class_id == ENETC_CLASS_ID_MAC_FILTER) {
     747      [ #  #  # ]:          0 :                 switch (reply_msg->status) {
     748                 :          0 :                 case ENETC_INVALID_MAC_ADDR:
     749                 :          0 :                         ENETC_PMD_ERR("Invalid MAC address");
     750                 :            :                         err = -EINVAL;
     751                 :            :                         break;
     752                 :          0 :                 case ENETC_DUPLICATE_MAC_ADDR:
     753                 :          0 :                         ENETC_PMD_ERR("Duplicate MAC address");
     754                 :            :                         err = -EINVAL;
     755                 :            :                         break;
     756                 :            :                 default:
     757                 :            :                         err = -EINVAL;
     758                 :            :                         break;
     759                 :            :                 }
     760                 :            :         }
     761                 :            : 
     762                 :            :         if (err) {
     763                 :          0 :                 ENETC_PMD_ERR("VSI command execute error!");
     764                 :          0 :                 goto end;
     765                 :            :         }
     766                 :            : 
     767                 :          0 :         rte_ether_addr_copy((struct rte_ether_addr *)&cmd->addr,
     768                 :          0 :                         &dev->data->mac_addrs[0]);
     769                 :            : 
     770                 :          0 : end:
     771                 :            :         /* free memory no longer required */
     772                 :          0 :         rte_free(msg->vaddr);
     773                 :          0 :         rte_free(reply_msg);
     774                 :          0 :         rte_free(msg);
     775                 :          0 :         return err;
     776                 :            : }
     777                 :            : 
     778                 :            : static int
     779                 :          0 : enetc4_vf_promisc_send_message(struct rte_eth_dev *dev, bool promisc_en)
     780                 :            : {
     781                 :          0 :         struct enetc_eth_hw *hw = ENETC_DEV_PRIVATE_TO_HW(dev->data->dev_private);
     782                 :            :         struct enetc_msg_cmd_set_promisc *cmd;
     783                 :            :         struct enetc_msg_swbd *msg;
     784                 :            :         uint32_t msg_size;
     785                 :            :         int err = 0;
     786                 :            : 
     787                 :          0 :         msg = rte_zmalloc(NULL, sizeof(*msg), RTE_CACHE_LINE_SIZE);
     788         [ #  # ]:          0 :         if (!msg) {
     789                 :          0 :                 ENETC_PMD_ERR("Failed to alloc msg");
     790                 :            :                 err = -ENOMEM;
     791                 :          0 :                 return err;
     792                 :            :         }
     793                 :            : 
     794                 :            :         msg_size = RTE_ALIGN(sizeof(struct enetc_msg_cmd_set_promisc), ENETC_VSI_PSI_MSG_SIZE);
     795                 :          0 :         msg->vaddr = rte_zmalloc(NULL, msg_size, 0);
     796         [ #  # ]:          0 :         if (!msg->vaddr) {
     797                 :          0 :                 ENETC_PMD_ERR("Failed to alloc memory for msg");
     798                 :          0 :                 rte_free(msg);
     799                 :          0 :                 return -ENOMEM;
     800                 :            :         }
     801                 :            : 
     802                 :          0 :         msg->dma = rte_mem_virt2iova((const void *)msg->vaddr);
     803                 :          0 :         msg->size = msg_size;
     804                 :            : 
     805                 :          0 :         cmd = (struct enetc_msg_cmd_set_promisc *)msg->vaddr;
     806                 :            : 
     807                 :            :         /* op_type is based on the result of message format
     808                 :            :          *    7  6      1       0
     809                 :            :               type   promisc  flush
     810                 :            :          */
     811                 :            : 
     812         [ #  # ]:          0 :         if (promisc_en)
     813                 :          0 :                 cmd->op_type = ENETC_PROMISC_ENABLE;
     814                 :            :         else
     815                 :          0 :                 cmd->op_type = ENETC_PROMISC_DISABLE;
     816                 :            : 
     817                 :            :         enetc_msg_vf_fill_common_hdr(msg, ENETC_CLASS_ID_MAC_FILTER,
     818                 :            :                                 ENETC_CMD_ID_SET_MAC_PROMISCUOUS, 0, 0, 0);
     819                 :            : 
     820                 :            :         /* send the command and wait */
     821                 :          0 :         err = enetc4_msg_vsi_send(hw, msg, NULL);
     822         [ #  # ]:          0 :         if (err) {
     823                 :          0 :                 ENETC_PMD_ERR("VSI message send error");
     824                 :          0 :                 goto end;
     825                 :            :         }
     826                 :            : 
     827                 :          0 : end:
     828                 :            :         /* free memory no longer required */
     829                 :          0 :         rte_free(msg->vaddr);
     830                 :          0 :         rte_free(msg);
     831                 :          0 :         return err;
     832                 :            : }
     833                 :            : 
     834                 :            : static int
     835                 :          0 : enetc4_vf_allmulti_send_message(struct rte_eth_dev *dev, bool mc_promisc)
     836                 :            : {
     837                 :          0 :         struct enetc_eth_hw *hw = ENETC_DEV_PRIVATE_TO_HW(dev->data->dev_private);
     838                 :            :         struct enetc_msg_cmd_set_promisc *cmd;
     839                 :            :         struct enetc_msg_swbd *msg;
     840                 :            :         uint32_t msg_size;
     841                 :            :         int err = 0;
     842                 :            : 
     843                 :          0 :         msg = rte_zmalloc(NULL, sizeof(*msg), RTE_CACHE_LINE_SIZE);
     844         [ #  # ]:          0 :         if (!msg) {
     845                 :          0 :                 ENETC_PMD_ERR("Failed to alloc msg");
     846                 :            :                 err = -ENOMEM;
     847                 :          0 :                 return err;
     848                 :            :         }
     849                 :            : 
     850                 :            :         msg_size = RTE_ALIGN(sizeof(struct enetc_msg_cmd_set_promisc),
     851                 :            :                                 ENETC_VSI_PSI_MSG_SIZE);
     852                 :          0 :         msg->vaddr = rte_zmalloc(NULL, msg_size, 0);
     853         [ #  # ]:          0 :         if (!msg->vaddr) {
     854                 :          0 :                 ENETC_PMD_ERR("Failed to alloc memory for msg");
     855                 :          0 :                 rte_free(msg);
     856                 :          0 :                 return -ENOMEM;
     857                 :            :         }
     858                 :            : 
     859                 :          0 :         msg->dma = rte_mem_virt2iova((const void *)msg->vaddr);
     860                 :          0 :         msg->size = msg_size;
     861                 :            : 
     862                 :          0 :         cmd = (struct enetc_msg_cmd_set_promisc *)msg->vaddr;
     863                 :            : 
     864                 :            :         /* op_type is based on the result of message format
     865                 :            :          *    7  6      1       0
     866                 :            :               type   promisc  flush
     867                 :            :          */
     868                 :            : 
     869         [ #  # ]:          0 :         if (mc_promisc)
     870                 :          0 :                 cmd->op_type = ENETC_ALLMULTI_PROMISC_EN;
     871                 :            :         else
     872                 :          0 :                 cmd->op_type = ENETC_ALLMULTI_PROMISC_DIS;
     873                 :            : 
     874                 :            :         enetc_msg_vf_fill_common_hdr(msg, ENETC_CLASS_ID_MAC_FILTER,
     875                 :            :                                 ENETC_CMD_ID_SET_MAC_PROMISCUOUS, 0, 0, 0);
     876                 :            : 
     877                 :            :         /* send the command and wait */
     878                 :          0 :         err = enetc4_msg_vsi_send(hw, msg, NULL);
     879         [ #  # ]:          0 :         if (err) {
     880                 :          0 :                 ENETC_PMD_ERR("VSI message send error");
     881                 :          0 :                 goto end;
     882                 :            :         }
     883                 :            : 
     884                 :          0 : end:
     885                 :            :         /* free memory no longer required */
     886                 :          0 :         rte_free(msg->vaddr);
     887                 :          0 :         rte_free(msg);
     888                 :          0 :         return err;
     889                 :            : }
     890                 :            : 
     891                 :            : 
     892                 :            : static int
     893                 :          0 : enetc4_vf_multicast_enable(struct rte_eth_dev *dev)
     894                 :            : {
     895                 :            :         int err;
     896                 :            : 
     897                 :          0 :         PMD_INIT_FUNC_TRACE();
     898                 :          0 :         err = enetc4_vf_allmulti_send_message(dev, true);
     899         [ #  # ]:          0 :         if (err) {
     900                 :          0 :                 ENETC_PMD_ERR("Failed to enable multicast promiscuous mode");
     901                 :          0 :                 return err;
     902                 :            :         }
     903                 :            : 
     904                 :            :         return 0;
     905                 :            : }
     906                 :            : 
     907                 :            : static int
     908                 :          0 : enetc4_vf_multicast_disable(struct rte_eth_dev *dev)
     909                 :            : {
     910                 :            :         int err;
     911                 :            : 
     912                 :          0 :         PMD_INIT_FUNC_TRACE();
     913                 :          0 :         err = enetc4_vf_allmulti_send_message(dev, false);
     914         [ #  # ]:          0 :         if (err) {
     915                 :          0 :                 ENETC_PMD_ERR("Failed to disable multicast promiscuous mode");
     916                 :          0 :                 return err;
     917                 :            :         }
     918                 :            : 
     919                 :            :         return 0;
     920                 :            : }
     921                 :            : 
     922                 :            : static int
     923                 :          0 : enetc4_vf_promisc_enable(struct rte_eth_dev *dev)
     924                 :            : {
     925                 :            :         int err;
     926                 :            : 
     927                 :          0 :         PMD_INIT_FUNC_TRACE();
     928                 :          0 :         err = enetc4_vf_promisc_send_message(dev, true);
     929         [ #  # ]:          0 :         if (err) {
     930                 :          0 :                 ENETC_PMD_ERR("Failed to enable promiscuous mode");
     931                 :          0 :                 return err;
     932                 :            :         }
     933                 :            : 
     934                 :            :         return 0;
     935                 :            : }
     936                 :            : 
     937                 :            : static int
     938                 :          0 : enetc4_vf_promisc_disable(struct rte_eth_dev *dev)
     939                 :            : {
     940                 :            :         int err;
     941                 :            : 
     942                 :          0 :         PMD_INIT_FUNC_TRACE();
     943                 :          0 :         err = enetc4_vf_promisc_send_message(dev, false);
     944         [ #  # ]:          0 :         if (err) {
     945                 :          0 :                 ENETC_PMD_ERR("Failed to disable promiscuous mode");
     946                 :          0 :                 return err;
     947                 :            :         }
     948                 :            : 
     949                 :            :         return 0;
     950                 :            : }
     951                 :            : 
     952                 :            : static int
     953                 :          0 : enetc4_vf_get_link_status(struct rte_eth_dev *dev, struct enetc_psi_reply_msg *reply_msg)
     954                 :            : {
     955                 :          0 :         struct enetc_eth_hw *hw = ENETC_DEV_PRIVATE_TO_HW(dev->data->dev_private);
     956                 :            :         struct enetc_msg_swbd *msg;
     957                 :            :         uint32_t msg_size;
     958                 :            :         int err = 0;
     959                 :          0 :         int vsimsgsr_link_st = 0;
     960                 :            : 
     961                 :          0 :         msg = rte_zmalloc(NULL, sizeof(*msg), RTE_CACHE_LINE_SIZE);
     962         [ #  # ]:          0 :         if (!msg) {
     963                 :          0 :                 ENETC_PMD_ERR("Failed to alloc msg");
     964                 :            :                 err = -ENOMEM;
     965                 :          0 :                 return err;
     966                 :            :         }
     967                 :            : 
     968                 :            :         msg_size = RTE_ALIGN(sizeof(struct enetc_msg_cmd_get_link_status),
     969                 :            :                         ENETC_VSI_PSI_MSG_SIZE);
     970                 :          0 :         msg->vaddr = rte_zmalloc(NULL, msg_size, 0);
     971         [ #  # ]:          0 :         if (!msg->vaddr) {
     972                 :          0 :                 ENETC_PMD_ERR("Failed to alloc memory for msg");
     973                 :          0 :                 rte_free(msg);
     974                 :          0 :                 return -ENOMEM;
     975                 :            :         }
     976                 :            : 
     977                 :          0 :         msg->dma = rte_mem_virt2iova((const void *)msg->vaddr);
     978                 :          0 :         msg->size = msg_size;
     979                 :            : 
     980                 :            :         enetc_msg_vf_fill_common_hdr(msg, ENETC_CLASS_ID_LINK_STATUS,
     981                 :            :                         ENETC_CMD_ID_GET_LINK_STATUS, 0, 0, 0);
     982                 :            : 
     983                 :            :         /* send the command and wait */
     984                 :          0 :         err = enetc4_msg_vsi_send(hw, msg, &vsimsgsr_link_st);
     985         [ #  # ]:          0 :         if (err) {
     986                 :          0 :                 ENETC_PMD_ERR("VSI message send error");
     987                 :          0 :                 goto end;
     988                 :            :         }
     989                 :            : 
     990         [ #  # ]:          0 :         enetc4_msg_vsi_reply_msg(hw, vsimsgsr_link_st, reply_msg);
     991                 :          0 : end:
     992                 :            :         /* free memory no longer required */
     993                 :          0 :         rte_free(msg->vaddr);
     994                 :          0 :         rte_free(msg);
     995                 :          0 :         return err;
     996                 :            : }
     997                 :            : 
     998                 :            : static int
     999                 :          0 : enetc4_vf_get_link_speed(struct rte_eth_dev *dev, struct enetc_psi_reply_msg *reply_msg)
    1000                 :            : {
    1001                 :          0 :         struct enetc_eth_hw *hw = ENETC_DEV_PRIVATE_TO_HW(dev->data->dev_private);
    1002                 :            :         struct enetc_msg_swbd *msg;
    1003                 :            :         uint32_t msg_size;
    1004                 :            :         int err = 0;
    1005                 :          0 :         int vsimsgsr_link_sp = 0;
    1006                 :            : 
    1007                 :          0 :         msg = rte_zmalloc(NULL, sizeof(*msg), RTE_CACHE_LINE_SIZE);
    1008         [ #  # ]:          0 :         if (!msg) {
    1009                 :          0 :                 ENETC_PMD_ERR("Failed to alloc msg");
    1010                 :            :                 err = -ENOMEM;
    1011                 :          0 :                 return err;
    1012                 :            :         }
    1013                 :            : 
    1014                 :            :         msg_size = RTE_ALIGN(sizeof(struct enetc_msg_cmd_get_link_speed),
    1015                 :            :                                 ENETC_VSI_PSI_MSG_SIZE);
    1016                 :          0 :         msg->vaddr = rte_zmalloc(NULL, msg_size, 0);
    1017         [ #  # ]:          0 :         if (!msg->vaddr) {
    1018                 :          0 :                 ENETC_PMD_ERR("Failed to alloc memory for msg");
    1019                 :          0 :                 rte_free(msg);
    1020                 :          0 :                 return -ENOMEM;
    1021                 :            :         }
    1022                 :            : 
    1023                 :          0 :         msg->dma = rte_mem_virt2iova((const void *)msg->vaddr);
    1024                 :          0 :         msg->size = msg_size;
    1025                 :            : 
    1026                 :            :         enetc_msg_vf_fill_common_hdr(msg, ENETC_CLASS_ID_LINK_SPEED,
    1027                 :            :                         ENETC_CMD_ID_GET_LINK_SPEED, 0, 0, 0);
    1028                 :            : 
    1029                 :            :         /* send the command and wait */
    1030                 :          0 :         err = enetc4_msg_vsi_send(hw, msg, &vsimsgsr_link_sp);
    1031         [ #  # ]:          0 :         if (err) {
    1032                 :          0 :                 ENETC_PMD_ERR("VSI message send error");
    1033                 :          0 :                 goto end;
    1034                 :            :         }
    1035                 :            : 
    1036         [ #  # ]:          0 :         enetc4_msg_vsi_reply_msg(hw, vsimsgsr_link_sp, reply_msg);
    1037                 :          0 : end:
    1038                 :            :         /* free memory no longer required */
    1039                 :          0 :         rte_free(msg->vaddr);
    1040                 :          0 :         rte_free(msg);
    1041                 :          0 :         return err;
    1042                 :            : }
    1043                 :            : 
    1044                 :            : /*
    1045                 :            :  * Get the NETC IP minor revision (IP_MN) from the PSI using the 'Get IP
    1046                 :            :  * version' command class (class ID 0xF0, cmd_id 0x1). In the reply, the
    1047                 :            :  * low 8 bits of the return code carry the minor revision and the upper 8
    1048                 :            :  * bits carry the class code (0xF0). The PSI only implements the IP_MN
    1049                 :            :  * command of this class; the major revision comes from the PCI revision.
    1050                 :            :  */
    1051                 :            : static int
    1052                 :          0 : enetc4_vf_get_ip_minor_revision(struct rte_eth_dev *dev, uint8_t *ip_mn)
    1053                 :            : {
    1054                 :          0 :         struct enetc_eth_hw *hw = ENETC_DEV_PRIVATE_TO_HW(dev->data->dev_private);
    1055                 :            :         struct enetc_msg_swbd *msg;
    1056                 :            :         uint32_t msg_size;
    1057                 :            :         uint16_t mc;
    1058                 :            :         uint8_t class_id;
    1059                 :          0 :         int vsimsgsr = 0;
    1060                 :            :         int err = 0;
    1061                 :            : 
    1062                 :          0 :         msg = rte_zmalloc(NULL, sizeof(*msg), RTE_CACHE_LINE_SIZE);
    1063         [ #  # ]:          0 :         if (!msg) {
    1064                 :          0 :                 ENETC_PMD_ERR("Failed to alloc msg");
    1065                 :          0 :                 return -ENOMEM;
    1066                 :            :         }
    1067                 :            : 
    1068                 :            :         msg_size = RTE_ALIGN(sizeof(struct enetc_msg_cmd_get_ip_ver),
    1069                 :            :                                 ENETC_VSI_PSI_MSG_SIZE);
    1070                 :          0 :         msg->vaddr = rte_zmalloc(NULL, msg_size, 0);
    1071         [ #  # ]:          0 :         if (!msg->vaddr) {
    1072                 :          0 :                 ENETC_PMD_ERR("Failed to alloc memory for msg");
    1073                 :          0 :                 rte_free(msg);
    1074                 :          0 :                 return -ENOMEM;
    1075                 :            :         }
    1076                 :            : 
    1077                 :          0 :         msg->dma = rte_mem_virt2iova((const void *)msg->vaddr);
    1078                 :          0 :         msg->size = msg_size;
    1079                 :            : 
    1080                 :            :         /* COOKIE is 0 so that the command is executed as blocking on PSI */
    1081                 :            :         enetc_msg_vf_fill_common_hdr(msg, ENETC_CLASS_ID_GET_IP_VER,
    1082                 :            :                         ENETC_CMD_ID_GET_IP_MN, 0, 0, 0);
    1083                 :            : 
    1084                 :            :         /* send the command and wait */
    1085                 :          0 :         err = enetc4_msg_vsi_send(hw, msg, &vsimsgsr);
    1086         [ #  # ]:          0 :         if (err) {
    1087                 :          0 :                 ENETC_PMD_ERR("VSI message send error");
    1088                 :          0 :                 goto end;
    1089                 :            :         }
    1090                 :            : 
    1091                 :            :         /*
    1092                 :            :          * For the IP version command class the class-specific field is
    1093                 :            :          * reused to carry the 8-bit version value in the lower byte of the
    1094                 :            :          * return code, so parse the full low byte here instead of using the
    1095                 :            :          * generic reply parser.
    1096                 :            :          */
    1097                 :          0 :         mc = ENETC_SIMSGSR_GET_MC(vsimsgsr);
    1098                 :          0 :         class_id = (mc >> 8) & 0xff;
    1099                 :            : 
    1100         [ #  # ]:          0 :         if (class_id != ENETC_CLASS_ID_GET_IP_VER) {
    1101                 :          0 :                 ENETC_PMD_ERR("Wrong reply message 0x%x", class_id);
    1102                 :            :                 err = -EIO;
    1103                 :          0 :                 goto end;
    1104                 :            :         }
    1105                 :            : 
    1106                 :          0 :         *ip_mn = mc & 0xff;
    1107         [ #  # ]:          0 :         if (*ip_mn == ENETC_IP_VER_NOT_AVAILABLE) {
    1108                 :          0 :                 ENETC_PMD_DEBUG("IP minor revision not available");
    1109                 :            :                 err = -ENOTSUP;
    1110                 :            :         }
    1111                 :            : 
    1112                 :          0 : end:
    1113                 :            :         /* free memory no longer required */
    1114                 :          0 :         rte_free(msg->vaddr);
    1115                 :          0 :         rte_free(msg);
    1116                 :          0 :         return err;
    1117                 :            : }
    1118                 :            : 
    1119                 :            : /*
    1120                 :            :  * Retrieve the NETC firmware/IP version and format it as
    1121                 :            :  * "<major>.<minor>". The IP major revision is taken from the PCI
    1122                 :            :  * revision ID register, and the IP minor revision is fetched from the
    1123                 :            :  * PSI via VSI-PSI messaging ('Get IP version' command class). This
    1124                 :            :  * mirrors the behaviour of the kernel PF/VF drivers, where the PSI only
    1125                 :            :  * implements the IP_MN command of the 0xF0 class.
    1126                 :            :  */
    1127                 :            : static int
    1128                 :          0 : enetc4_vf_fw_version_get(struct rte_eth_dev *dev, char *fw_version, size_t fw_size)
    1129                 :            : {
    1130                 :          0 :         struct rte_pci_device *pci_dev = RTE_CLASS_TO_BUS_DEVICE(dev, *pci_dev);
    1131                 :          0 :         uint8_t ip_mj = 0, ip_mn = 0;
    1132                 :            :         int ret;
    1133                 :            : 
    1134                 :          0 :         PMD_INIT_FUNC_TRACE();
    1135                 :            : 
    1136         [ #  # ]:          0 :         if (fw_version == NULL)
    1137                 :            :                 return -EINVAL;
    1138                 :            : 
    1139                 :            :         /* IP major revision is exposed through the PCI revision ID */
    1140                 :          0 :         ret = rte_pci_read_config(pci_dev, &ip_mj, sizeof(ip_mj),
    1141                 :            :                         RTE_PCI_REVISION_ID);
    1142         [ #  # ]:          0 :         if (ret != sizeof(ip_mj)) {
    1143                 :          0 :                 ENETC_PMD_ERR("Failed to read PCI revision ID");
    1144                 :          0 :                 return -EIO;
    1145                 :            :         }
    1146                 :            : 
    1147                 :            :         /* IP minor revision is fetched from the PSI via VSI-PSI messaging.
    1148                 :            :          * If the PSI reports the version as unavailable, fall back to a
    1149                 :            :          * partial version string so the caller still gets useful output.
    1150                 :            :          */
    1151                 :          0 :         ret = enetc4_vf_get_ip_minor_revision(dev, &ip_mn);
    1152         [ #  # ]:          0 :         if (ret && ret != -ENOTSUP) {
    1153                 :          0 :                 ENETC_PMD_ERR("Failed to get NETC minor revision");
    1154                 :          0 :                 return ret;
    1155                 :            :         }
    1156                 :            : 
    1157         [ #  # ]:          0 :         if (fw_size == 0) {
    1158         [ #  # ]:          0 :                 if (ret == -ENOTSUP)
    1159                 :          0 :                         return snprintf(NULL, 0, "%u.unknown", ip_mj) + 1;
    1160                 :            :                 else
    1161                 :          0 :                         return snprintf(NULL, 0, "%u.%u", ip_mj, ip_mn) + 1;
    1162                 :            :         }
    1163                 :            : 
    1164         [ #  # ]:          0 :         if (ret == -ENOTSUP)
    1165                 :          0 :                 ret = snprintf(fw_version, fw_size, "%u.unknown", ip_mj);
    1166                 :            :         else
    1167                 :          0 :                 ret = snprintf(fw_version, fw_size, "%u.%u", ip_mj, ip_mn);
    1168         [ #  # ]:          0 :         if (ret < 0)
    1169                 :            :                 return -EINVAL;
    1170                 :            : 
    1171                 :          0 :         ret += 1; /* add trailing '\0' */
    1172         [ #  # ]:          0 :         if ((size_t)ret > fw_size)
    1173                 :          0 :                 return ret;
    1174                 :            : 
    1175                 :            :         return 0;
    1176                 :            : }
    1177                 :            : 
    1178                 :            : /* VF station interface registers dumped by .get_reg */
    1179                 :            : static const uint32_t enetc4_vf_si_regs[] = {
    1180                 :            :         ENETC_SIMR, ENETC_SICAPR0, ENETC_SIPMAR0, ENETC_SIPMAR1,
    1181                 :            :         ENETC4_SIROCT0, ENETC4_SIRFRM0, ENETC4_SITOCT0, ENETC4_SITFRM0,
    1182                 :            :         ENETC4_SITDFCR, ENETC4_SIMSIVR, ENETC4_VSIIER, ENETC4_VSIIDR,
    1183                 :            :         ENETC4_VSIMSGSR, ENETC4_VSIMSGRR,
    1184                 :            : };
    1185                 :            : 
    1186                 :            : /*
    1187                 :            :  * Dump the VF-accessible registers. Only station interface and per-ring
    1188                 :            :  * BD ring registers are reachable by a VF; port registers are not.
    1189                 :            :  * When info->data is NULL, only the register count and width are
    1190                 :            :  * reported so the caller can size its buffer.
    1191                 :            :  */
    1192                 :            : static int
    1193                 :          0 : enetc4_vf_get_regs(struct rte_eth_dev *dev, struct rte_dev_reg_info *regs)
    1194                 :            : {
    1195                 :          0 :         struct enetc_eth_hw *hw = ENETC_DEV_PRIVATE_TO_HW(dev->data->dev_private);
    1196                 :            :         struct enetc_hw *enetc_hw = &hw->hw;
    1197                 :            :         uint32_t count, addr;
    1198                 :            :         uint32_t *buf;
    1199                 :            :         uint16_t i, j;
    1200                 :            : 
    1201                 :            :         count = RTE_DIM(enetc4_vf_si_regs);
    1202                 :          0 :         count += RTE_DIM(enetc4_txbdr_regs) * dev->data->nb_tx_queues;
    1203                 :          0 :         count += RTE_DIM(enetc4_rxbdr_regs) * dev->data->nb_rx_queues;
    1204                 :            : 
    1205         [ #  # ]:          0 :         if (regs->data == NULL) {
    1206                 :          0 :                 regs->length = count;
    1207                 :          0 :                 regs->width = sizeof(uint32_t);
    1208                 :          0 :                 return 0;
    1209                 :            :         }
    1210                 :            : 
    1211   [ #  #  #  # ]:          0 :         if (regs->length && regs->length < count)
    1212                 :            :                 return -ENOTSUP;
    1213                 :            : 
    1214                 :            :         buf = regs->data;
    1215                 :            : 
    1216         [ #  # ]:          0 :         for (i = 0; i < RTE_DIM(enetc4_vf_si_regs); i++)
    1217                 :          0 :                 *buf++ = enetc_rd(enetc_hw, enetc4_vf_si_regs[i]);
    1218                 :            : 
    1219         [ #  # ]:          0 :         for (i = 0; i < dev->data->nb_tx_queues; i++) {
    1220         [ #  # ]:          0 :                 for (j = 0; j < RTE_DIM(enetc4_txbdr_regs); j++) {
    1221                 :          0 :                         addr = ENETC_BDR(TX, i, enetc4_txbdr_regs[j]);
    1222                 :          0 :                         *buf++ = enetc_rd(enetc_hw, addr);
    1223                 :            :                 }
    1224                 :            :         }
    1225                 :            : 
    1226         [ #  # ]:          0 :         for (i = 0; i < dev->data->nb_rx_queues; i++) {
    1227         [ #  # ]:          0 :                 for (j = 0; j < RTE_DIM(enetc4_rxbdr_regs); j++) {
    1228                 :          0 :                         addr = ENETC_BDR(RX, i, enetc4_rxbdr_regs[j]);
    1229                 :          0 :                         *buf++ = enetc_rd(enetc_hw, addr);
    1230                 :            :                 }
    1231                 :            :         }
    1232                 :            : 
    1233                 :          0 :         regs->version = (uint32_t)hw->device_id << 16 | hw->revision_id;
    1234                 :            : 
    1235                 :          0 :         return 0;
    1236                 :            : }
    1237                 :            : 
    1238                 :            : static int
    1239                 :          0 : enetc4_vf_link_update_dummy(struct rte_eth_dev *dev __rte_unused,
    1240                 :            :                             int wait_to_complete __rte_unused)
    1241                 :            : {
    1242                 :          0 :         return 0;
    1243                 :            : }
    1244                 :            : 
    1245                 :            : static int
    1246                 :          0 : enetc4_vf_link_update(struct rte_eth_dev *dev, int wait_to_complete __rte_unused)
    1247                 :            : {
    1248                 :            :         struct enetc_eth_hw *hw =
    1249                 :          0 :                         ENETC_DEV_PRIVATE_TO_HW(dev->data->dev_private);
    1250                 :            :         struct enetc_psi_reply_msg *reply_msg;
    1251                 :            :         struct rte_eth_link link;
    1252                 :            :         int err;
    1253                 :            : 
    1254                 :          0 :         PMD_INIT_FUNC_TRACE();
    1255                 :          0 :         reply_msg = rte_zmalloc(NULL, sizeof(*reply_msg), RTE_CACHE_LINE_SIZE);
    1256         [ #  # ]:          0 :         if (!reply_msg) {
    1257                 :          0 :                 ENETC_PMD_ERR("Failed to alloc memory for reply_msg");
    1258                 :          0 :                 return -ENOMEM;
    1259                 :            :         }
    1260                 :            : 
    1261                 :            :         memset(&link, 0, sizeof(struct rte_eth_link));
    1262                 :            : 
    1263                 :          0 :         err = enetc4_vf_get_link_status(dev, reply_msg);
    1264         [ #  # ]:          0 :         if (err) {
    1265                 :          0 :                 ENETC_PMD_ERR("Failed to get link status");
    1266                 :          0 :                 rte_free(reply_msg);
    1267                 :          0 :                 return err;
    1268                 :            :         }
    1269                 :            : 
    1270         [ #  # ]:          0 :         if (reply_msg->class_id == ENETC_CLASS_ID_LINK_STATUS) {
    1271         [ #  # ]:          0 :                 if (reply_msg->status & ENETC_LINK_DOWN) {
    1272                 :            :                         link.link_status = RTE_ETH_LINK_DOWN;
    1273                 :            :                         /* Link is down: disable congestion mode on all RX rings. */
    1274                 :          0 :                         enetc4_vf_set_congestion_mode(dev, false);
    1275                 :            :                 } else {
    1276                 :          0 :                         link.link_status = RTE_ETH_LINK_UP;
    1277                 :            :                         /* Restore congestion mode from the TX PAUSE bit. */
    1278                 :          0 :                         enetc4_vf_set_congestion_mode(dev,
    1279                 :            :                                 !!(reply_msg->status & ENETC_LINK_TX_PAUSE));
    1280                 :            :                 }
    1281                 :            :         } else {
    1282                 :          0 :                 ENETC_PMD_ERR("Wrong reply message");
    1283                 :          0 :                 rte_free(reply_msg);
    1284                 :          0 :                 return -1;
    1285                 :            :         }
    1286                 :            : 
    1287                 :          0 :         err = enetc4_vf_get_link_speed(dev, reply_msg);
    1288         [ #  # ]:          0 :         if (err) {
    1289                 :          0 :                 ENETC_PMD_ERR("Failed to get link speed");
    1290                 :          0 :                 rte_free(reply_msg);
    1291                 :          0 :                 return err;
    1292                 :            :         }
    1293                 :            : 
    1294         [ #  # ]:          0 :         if (reply_msg->class_id == ENETC_CLASS_ID_LINK_SPEED) {
    1295                 :          0 :                 enetc4_decode_link_speed(reply_msg->status,
    1296                 :          0 :                                          hw->vf_link_legacy, &link);
    1297                 :            :         } else {
    1298                 :          0 :                 ENETC_PMD_ERR("Wrong reply message");
    1299                 :          0 :                 rte_free(reply_msg);
    1300                 :          0 :                 return -1;
    1301                 :            :         }
    1302                 :            : 
    1303                 :          0 :         link.link_autoneg = 1;
    1304                 :          0 :         rte_eth_linkstatus_set(dev, &link);
    1305                 :          0 :         rte_free(reply_msg);
    1306                 :            : 
    1307                 :          0 :         return 0;
    1308                 :            : }
    1309                 :            : 
    1310                 :            : static int
    1311                 :          0 : enetc4_vf_vlan_promisc(struct rte_eth_dev *dev, bool promisc_en)
    1312                 :            : {
    1313                 :          0 :         struct enetc_eth_hw *hw = ENETC_DEV_PRIVATE_TO_HW(dev->data->dev_private);
    1314                 :            :         struct enetc_msg_cmd_set_vlan_promisc *cmd;
    1315                 :            :         struct enetc_msg_swbd *msg;
    1316                 :            :         uint32_t msg_size;
    1317                 :            :         int err = 0;
    1318                 :            : 
    1319                 :          0 :         msg = rte_zmalloc(NULL, sizeof(*msg), RTE_CACHE_LINE_SIZE);
    1320         [ #  # ]:          0 :         if (!msg) {
    1321                 :          0 :                 ENETC_PMD_ERR("Failed to alloc msg");
    1322                 :            :                 err = -ENOMEM;
    1323                 :          0 :                 return err;
    1324                 :            :         }
    1325                 :            : 
    1326                 :            :         msg_size = RTE_ALIGN(sizeof(struct enetc_msg_cmd_set_vlan_promisc),
    1327                 :            :                                 ENETC_VSI_PSI_MSG_SIZE);
    1328                 :          0 :         msg->vaddr = rte_zmalloc(NULL, msg_size, 0);
    1329         [ #  # ]:          0 :         if (!msg->vaddr) {
    1330                 :          0 :                 ENETC_PMD_ERR("Failed to alloc memory for msg");
    1331                 :          0 :                 rte_free(msg);
    1332                 :          0 :                 return -ENOMEM;
    1333                 :            :         }
    1334                 :          0 :         msg->dma = rte_mem_virt2iova((const void *)msg->vaddr);
    1335                 :          0 :         msg->size = msg_size;
    1336                 :            : 
    1337                 :          0 :         cmd = (struct enetc_msg_cmd_set_vlan_promisc *)msg->vaddr;
    1338                 :            :         /* op is based on the result of message format
    1339                 :            :          *         1      0
    1340                 :            :          *      promisc flush
    1341                 :            :          */
    1342                 :            : 
    1343         [ #  # ]:          0 :         if (promisc_en)
    1344                 :          0 :                 cmd->op = ENETC_PROMISC_VLAN_ENABLE;
    1345                 :            :         else
    1346                 :          0 :                 cmd->op = ENETC_PROMISC_VLAN_DISABLE;
    1347                 :            : 
    1348                 :            :         enetc_msg_vf_fill_common_hdr(msg, ENETC_CLASS_ID_VLAN_FILTER,
    1349                 :            :                                 ENETC_CMD_ID_SET_VLAN_PROMISCUOUS, 0, 0, 0);
    1350                 :            : 
    1351                 :            :         /* send the command and wait */
    1352                 :          0 :         err = enetc4_msg_vsi_send(hw, msg, NULL);
    1353         [ #  # ]:          0 :         if (err) {
    1354                 :          0 :                 ENETC_PMD_ERR("VSI message send error");
    1355                 :          0 :                 goto end;
    1356                 :            :         }
    1357                 :            : 
    1358                 :          0 : end:
    1359                 :            :         /* free memory no longer required */
    1360                 :          0 :         rte_free(msg->vaddr);
    1361                 :          0 :         rte_free(msg);
    1362                 :          0 :         return err;
    1363                 :            : }
    1364                 :            : 
    1365                 :            : static int
    1366                 :          0 : enetc4_vf_mac_addr_add(struct rte_eth_dev *dev, struct rte_ether_addr *addr,
    1367                 :            :                         uint32_t index __rte_unused, uint32_t pool __rte_unused)
    1368                 :            : {
    1369                 :          0 :         struct enetc_eth_hw *hw = ENETC_DEV_PRIVATE_TO_HW(dev->data->dev_private);
    1370                 :            :         struct enetc_msg_cmd_set_primary_mac *cmd;
    1371                 :            :         struct enetc_msg_swbd *msg;
    1372                 :            :         struct enetc_psi_reply_msg *reply_msg;
    1373                 :            :         uint32_t msg_size;
    1374                 :            :         int err = 0;
    1375                 :          0 :         int vsimsgsr_mac_add = 0;
    1376                 :            : 
    1377                 :          0 :         PMD_INIT_FUNC_TRACE();
    1378                 :            : 
    1379                 :            :         if (!rte_is_valid_assigned_ether_addr(addr))
    1380                 :            :                 return -EINVAL;
    1381                 :            : 
    1382                 :          0 :         reply_msg = rte_zmalloc(NULL, sizeof(*reply_msg), RTE_CACHE_LINE_SIZE);
    1383         [ #  # ]:          0 :         if (!reply_msg) {
    1384                 :          0 :                 ENETC_PMD_ERR("Failed to alloc memory for reply_msg");
    1385                 :          0 :                 return -ENOMEM;
    1386                 :            :         }
    1387                 :            : 
    1388                 :          0 :         msg = rte_zmalloc(NULL, sizeof(*msg), RTE_CACHE_LINE_SIZE);
    1389         [ #  # ]:          0 :         if (!msg) {
    1390                 :          0 :                 ENETC_PMD_ERR("Failed to alloc msg");
    1391                 :            :                 err = -ENOMEM;
    1392                 :          0 :                 rte_free(reply_msg);
    1393                 :          0 :                 return err;
    1394                 :            :         }
    1395                 :            : 
    1396                 :            :         msg_size = RTE_ALIGN(sizeof(struct enetc_msg_cmd_set_primary_mac),
    1397                 :            :                         ENETC_VSI_PSI_MSG_SIZE);
    1398                 :          0 :         msg->vaddr = rte_zmalloc(NULL, msg_size, 0);
    1399         [ #  # ]:          0 :         if (!msg->vaddr) {
    1400                 :          0 :                 ENETC_PMD_ERR("Failed to alloc memory for msg");
    1401                 :          0 :                 rte_free(msg);
    1402                 :          0 :                 rte_free(reply_msg);
    1403                 :          0 :                 return -ENOMEM;
    1404                 :            :         }
    1405                 :          0 :         msg->dma = rte_mem_virt2iova((const void *)msg->vaddr);
    1406                 :          0 :         msg->size = msg_size;
    1407                 :          0 :         cmd = (struct enetc_msg_cmd_set_primary_mac *)msg->vaddr;
    1408                 :          0 :         memcpy(&cmd->addr.addr_bytes, addr, sizeof(struct rte_ether_addr));
    1409                 :          0 :         cmd->count = 1;
    1410                 :            : 
    1411                 :            :         enetc_msg_vf_fill_common_hdr(msg, ENETC_CLASS_ID_MAC_FILTER,
    1412                 :            :                         ENETC_MSG_ADD_EXACT_MAC_ENTRIES, 0, 0, 0);
    1413                 :            : 
    1414                 :            :         /* send the command and wait */
    1415                 :          0 :         err = enetc4_msg_vsi_send(hw, msg, &vsimsgsr_mac_add);
    1416         [ #  # ]:          0 :         if (err) {
    1417                 :          0 :                 ENETC_PMD_ERR("VSI message send error");
    1418                 :          0 :                 goto end;
    1419                 :            :         }
    1420                 :            : 
    1421         [ #  # ]:          0 :         enetc4_msg_vsi_reply_msg(hw, vsimsgsr_mac_add, reply_msg);
    1422                 :            : 
    1423         [ #  # ]:          0 :         if (reply_msg->class_id == ENETC_CLASS_ID_MAC_FILTER) {
    1424   [ #  #  #  # ]:          0 :                 switch (reply_msg->status) {
    1425                 :          0 :                 case ENETC_INVALID_MAC_ADDR:
    1426                 :          0 :                         ENETC_PMD_ERR("Invalid MAC address");
    1427                 :            :                         err = -EINVAL;
    1428                 :            :                         break;
    1429                 :          0 :                 case ENETC_DUPLICATE_MAC_ADDR:
    1430                 :          0 :                         ENETC_PMD_ERR("Duplicate MAC address");
    1431                 :            :                         err = -EINVAL;
    1432                 :            :                         break;
    1433                 :          0 :                 case ENETC_MAC_FILTER_NO_RESOURCE:
    1434                 :          0 :                         ENETC_PMD_ERR("Not enough exact-match entries available");
    1435                 :            :                         err = -EINVAL;
    1436                 :            :                         break;
    1437                 :            :                 default:
    1438                 :            :                         err = -EINVAL;
    1439                 :            :                         break;
    1440                 :            :                 }
    1441                 :            :         }
    1442                 :            : 
    1443                 :            :         if (err) {
    1444                 :          0 :                 ENETC_PMD_ERR("VSI command execute error!");
    1445                 :          0 :                 goto end;
    1446                 :            :         }
    1447                 :            : 
    1448                 :          0 : end:
    1449                 :            :         /* free memory no longer required */
    1450                 :          0 :         rte_free(msg->vaddr);
    1451                 :          0 :         rte_free(reply_msg);
    1452                 :          0 :         rte_free(msg);
    1453                 :          0 :         return err;
    1454                 :            : }
    1455                 :            : 
    1456                 :          0 : static int enetc4_vf_vlan_filter_set(struct rte_eth_dev *dev, uint16_t vlan_id, int on)
    1457                 :            : {
    1458                 :          0 :         struct enetc_eth_hw *hw = ENETC_DEV_PRIVATE_TO_HW(dev->data->dev_private);
    1459                 :            :         struct enetc_msg_vlan_exact_filter *cmd;
    1460                 :            :         struct enetc_msg_swbd *msg;
    1461                 :            :         struct enetc_psi_reply_msg *reply_msg;
    1462                 :            :         uint32_t msg_size;
    1463                 :            :         int err = 0;
    1464                 :          0 :         int vsimsgsr_vlan = 0;
    1465                 :            : 
    1466                 :          0 :         PMD_INIT_FUNC_TRACE();
    1467                 :            : 
    1468                 :          0 :         reply_msg = rte_zmalloc(NULL, sizeof(*reply_msg), RTE_CACHE_LINE_SIZE);
    1469         [ #  # ]:          0 :         if (!reply_msg) {
    1470                 :          0 :                 ENETC_PMD_ERR("Failed to alloc memory for reply_msg");
    1471                 :          0 :                 return -ENOMEM;
    1472                 :            :         }
    1473                 :            : 
    1474                 :          0 :         msg = rte_zmalloc(NULL, sizeof(*msg), RTE_CACHE_LINE_SIZE);
    1475         [ #  # ]:          0 :         if (!msg) {
    1476                 :          0 :                 ENETC_PMD_ERR("Failed to alloc msg");
    1477                 :            :                 err = -ENOMEM;
    1478                 :          0 :                 rte_free(reply_msg);
    1479                 :          0 :                 return err;
    1480                 :            :         }
    1481                 :            : 
    1482                 :            :         msg_size = RTE_ALIGN(sizeof(struct enetc_msg_vlan_exact_filter),
    1483                 :            :                         ENETC_VSI_PSI_MSG_SIZE);
    1484                 :          0 :         msg->vaddr = rte_zmalloc(NULL, msg_size, 0);
    1485         [ #  # ]:          0 :         if (!msg->vaddr) {
    1486                 :          0 :                 ENETC_PMD_ERR("Failed to alloc memory for msg");
    1487                 :          0 :                 rte_free(msg);
    1488                 :          0 :                 rte_free(reply_msg);
    1489                 :          0 :                 return -ENOMEM;
    1490                 :            :         }
    1491                 :          0 :         msg->dma = rte_mem_virt2iova((const void *)msg->vaddr);
    1492                 :          0 :         msg->size = msg_size;
    1493                 :          0 :         cmd = (struct enetc_msg_vlan_exact_filter *)msg->vaddr;
    1494                 :          0 :         cmd->vlan_count = 1;
    1495                 :          0 :         cmd->vlan_id = vlan_id;
    1496                 :            : 
    1497                 :            :         /* TPID 2-bit encoding value is taken from the H/W block guide:
    1498                 :            :          *      00b Standard C-VLAN 0x8100
    1499                 :            :          *      01b Standard S-VLAN 0x88A8
    1500                 :            :          *      10b Custom VLAN as defined by CVLANR1[ETYPE]
    1501                 :            :          *      11b Custom VLAN as defined by CVLANR2[ETYPE]
    1502                 :            :          * Currently Standard C-VLAN is supported. To support others in future.
    1503                 :            :          */
    1504                 :          0 :         cmd->tpid = 0;
    1505                 :            : 
    1506         [ #  # ]:          0 :         if (on) {
    1507                 :            :                 enetc_msg_vf_fill_common_hdr(msg, ENETC_CLASS_ID_VLAN_FILTER,
    1508                 :            :                                 ENETC_MSG_ADD_EXACT_VLAN_ENTRIES, 0, 0, 0);
    1509                 :            :         } else {
    1510                 :            :                 enetc_msg_vf_fill_common_hdr(msg, ENETC_CLASS_ID_VLAN_FILTER,
    1511                 :            :                                 ENETC_MSG_REMOVE_EXACT_VLAN_ENTRIES, 0, 0, 0);
    1512                 :            :         }
    1513                 :            : 
    1514                 :            :         /* send the command and wait */
    1515                 :          0 :         err = enetc4_msg_vsi_send(hw, msg, &vsimsgsr_vlan);
    1516         [ #  # ]:          0 :         if (err) {
    1517                 :          0 :                 ENETC_PMD_ERR("VSI message send error");
    1518                 :          0 :                 goto end;
    1519                 :            :         }
    1520                 :            : 
    1521         [ #  # ]:          0 :         enetc4_msg_vsi_reply_msg(hw, vsimsgsr_vlan, reply_msg);
    1522                 :            : 
    1523         [ #  # ]:          0 :         if (reply_msg->class_id == ENETC_CLASS_ID_VLAN_FILTER) {
    1524   [ #  #  #  #  :          0 :                 switch (reply_msg->status) {
                      # ]
    1525                 :          0 :                 case ENETC_INVALID_VLAN_ENTRY:
    1526                 :          0 :                         ENETC_PMD_ERR("VLAN entry not valid");
    1527                 :            :                         err = -EINVAL;
    1528                 :            :                         break;
    1529                 :          0 :                 case ENETC_DUPLICATE_VLAN_ENTRY:
    1530                 :          0 :                         ENETC_PMD_ERR("Duplicated VLAN entry");
    1531                 :            :                         err = -EINVAL;
    1532                 :            :                         break;
    1533                 :          0 :                 case ENETC_VLAN_ENTRY_NOT_FOUND:
    1534                 :          0 :                         ENETC_PMD_ERR("VLAN entry not found");
    1535                 :            :                         err = -EINVAL;
    1536                 :            :                         break;
    1537                 :          0 :                 case ENETC_VLAN_NO_RESOURCE:
    1538                 :          0 :                         ENETC_PMD_ERR("Not enough exact-match entries available");
    1539                 :            :                         err = -EINVAL;
    1540                 :            :                         break;
    1541                 :            :                 default:
    1542                 :            :                         err = -EINVAL;
    1543                 :            :                         break;
    1544                 :            :                 }
    1545                 :            :         }
    1546                 :            : 
    1547                 :            :         if (err) {
    1548                 :          0 :                 ENETC_PMD_ERR("VSI command execute error!");
    1549                 :          0 :                 goto end;
    1550                 :            :         }
    1551                 :            : 
    1552                 :          0 : end:
    1553                 :            :         /* free memory no longer required */
    1554                 :          0 :         rte_free(msg->vaddr);
    1555                 :          0 :         rte_free(reply_msg);
    1556                 :          0 :         rte_free(msg);
    1557                 :          0 :         return err;
    1558                 :            : }
    1559                 :            : 
    1560                 :          0 : static int enetc4_vf_vlan_offload_set(struct rte_eth_dev *dev, int mask __rte_unused)
    1561                 :            : {
    1562                 :            :         int err = 0;
    1563                 :            : 
    1564                 :          0 :         PMD_INIT_FUNC_TRACE();
    1565                 :            : 
    1566         [ #  # ]:          0 :         if (dev->data->dev_conf.rxmode.offloads) {
    1567                 :          0 :                 ENETC_PMD_DEBUG("VLAN filter table entry inserted:"
    1568                 :            :                                         "Disabling VLAN promisc mode");
    1569                 :          0 :                 err = enetc4_vf_vlan_promisc(dev, false);
    1570         [ #  # ]:          0 :                 if (err) {
    1571                 :          0 :                         ENETC_PMD_ERR("Added VLAN filter table entry:"
    1572                 :            :                                         "Failed to disable promiscuous mode");
    1573                 :          0 :                         return err;
    1574                 :            :                 }
    1575                 :            :         } else {
    1576                 :          0 :                 ENETC_PMD_DEBUG("Enabling VLAN promisc mode");
    1577                 :          0 :                 err = enetc4_vf_vlan_promisc(dev, true);
    1578         [ #  # ]:          0 :                 if (err) {
    1579                 :          0 :                         ENETC_PMD_ERR("Vlan filter table empty:"
    1580                 :            :                                         "Failed to enable promiscuous mode");
    1581                 :          0 :                         return err;
    1582                 :            :                 }
    1583                 :            :         }
    1584                 :            : 
    1585                 :            :         return 0;
    1586                 :            : }
    1587                 :            : 
    1588                 :            : /* Configure SI-based VLAN insertion/removal via VSI-PSI mailbox (class 0x24). */
    1589                 :            : static int
    1590                 :          0 : enetc4_vf_vlan_pvid_set(struct rte_eth_dev *dev, uint16_t vlan_id, int on)
    1591                 :            : {
    1592                 :          0 :         struct enetc_eth_hw *hw = ENETC_DEV_PRIVATE_TO_HW(dev->data->dev_private);
    1593                 :            :         struct enetc_msg_si_vlan_iso *cmd;
    1594                 :            :         struct enetc_msg_swbd *msg;
    1595                 :            :         struct enetc_psi_reply_msg *reply_msg;
    1596                 :            :         uint32_t msg_size;
    1597                 :            :         int err = 0;
    1598                 :          0 :         int vsimsgsr_pvid = 0;
    1599                 :            : 
    1600                 :          0 :         PMD_INIT_FUNC_TRACE();
    1601                 :            : 
    1602         [ #  # ]:          0 :         if (vlan_id > RTE_ETHER_MAX_VLAN_ID) {
    1603                 :          0 :                 ENETC_PMD_ERR("Invalid vlan_id = %u > %d", vlan_id,
    1604                 :            :                               RTE_ETHER_MAX_VLAN_ID);
    1605                 :          0 :                 return -EINVAL;
    1606                 :            :         }
    1607                 :            : 
    1608                 :          0 :         reply_msg = rte_zmalloc(NULL, sizeof(*reply_msg), RTE_CACHE_LINE_SIZE);
    1609         [ #  # ]:          0 :         if (!reply_msg) {
    1610                 :          0 :                 ENETC_PMD_ERR("Failed to alloc memory for reply_msg");
    1611                 :          0 :                 return -ENOMEM;
    1612                 :            :         }
    1613                 :            : 
    1614                 :          0 :         msg = rte_zmalloc(NULL, sizeof(*msg), RTE_CACHE_LINE_SIZE);
    1615         [ #  # ]:          0 :         if (!msg) {
    1616                 :          0 :                 ENETC_PMD_ERR("Failed to alloc msg");
    1617                 :          0 :                 rte_free(reply_msg);
    1618                 :          0 :                 return -ENOMEM;
    1619                 :            :         }
    1620                 :            : 
    1621                 :            :         msg_size = RTE_ALIGN(sizeof(struct enetc_msg_si_vlan_iso),
    1622                 :            :                              ENETC_VSI_PSI_MSG_SIZE);
    1623                 :          0 :         msg->vaddr = rte_zmalloc(NULL, msg_size, 0);
    1624         [ #  # ]:          0 :         if (!msg->vaddr) {
    1625                 :          0 :                 ENETC_PMD_ERR("Failed to alloc memory for msg body");
    1626                 :          0 :                 rte_free(msg);
    1627                 :          0 :                 rte_free(reply_msg);
    1628                 :          0 :                 return -ENOMEM;
    1629                 :            :         }
    1630                 :          0 :         msg->dma = rte_mem_virt2iova((const void *)msg->vaddr);
    1631         [ #  # ]:          0 :         if (msg->dma == RTE_BAD_IOVA) {
    1632                 :          0 :                 ENETC_PMD_ERR("Failed to get IOVA for SI VLAN isolation msg body");
    1633                 :          0 :                 rte_free(msg->vaddr);
    1634                 :          0 :                 rte_free(msg);
    1635                 :          0 :                 rte_free(reply_msg);
    1636                 :          0 :                 return -ENOMEM;
    1637                 :            :         }
    1638                 :          0 :         msg->size = msg_size;
    1639                 :            : 
    1640                 :          0 :         cmd = (struct enetc_msg_si_vlan_iso *)msg->vaddr;
    1641                 :            : 
    1642         [ #  # ]:          0 :         if (on) {
    1643                 :          0 :                 cmd->ctrl = (uint8_t)ENETC_SI_VLAN_ISO_E;
    1644                 :          0 :                 cmd->pcp_dei_vid_hi = (uint8_t)((vlan_id >> 8) & 0x0f);
    1645                 :          0 :                 cmd->vid_lo = (uint8_t)(vlan_id & 0xff);
    1646                 :          0 :                 cmd->flags = (uint8_t)(ENETC_SI_VLAN_ISO_SVIE | ENETC_SI_VLAN_ISO_VTE);
    1647                 :            :         }
    1648                 :            :         /* on=0: all fields zero (rte_zmalloc cleared the buffer) */
    1649                 :            : 
    1650                 :            :         enetc_msg_vf_fill_common_hdr(msg, ENETC_CLASS_ID_SI_VLAN_ISO,
    1651                 :            :                                      ENETC_CMD_ID_SET_SI_VLAN_ISO, 0, 0, 0);
    1652                 :            : 
    1653                 :            :         /* send the command and wait for PSI reply */
    1654                 :          0 :         err = enetc4_msg_vsi_send(hw, msg, &vsimsgsr_pvid);
    1655         [ #  # ]:          0 :         if (err) {
    1656                 :          0 :                 ENETC_PMD_ERR("VSI message send error for SI VLAN isolation");
    1657                 :          0 :                 goto end;
    1658                 :            :         }
    1659                 :            : 
    1660         [ #  # ]:          0 :         enetc4_msg_vsi_reply_msg(hw, vsimsgsr_pvid, reply_msg);
    1661                 :            : 
    1662                 :            :         /*
    1663                 :            :          * The PSI reports command completion in the reply class_id: a
    1664                 :            :          * successful command returns ENETC_MSG_CLASS_ID_CMD_SUCCESS (0x1),
    1665                 :            :          * while any other class_id (e.g. CMD_NOT_SUPPORT 0x3) indicates a
    1666                 :            :          * failure. The command class value (0x24) is only used in the
    1667                 :            :          * outgoing VF-to-PSI header and is never echoed back in the reply,
    1668                 :            :          * so treat class_id != CMD_SUCCESS as failure.
    1669                 :            :          */
    1670         [ #  # ]:          0 :         if (reply_msg->class_id != ENETC_MSG_CLASS_ID_CMD_SUCCESS) {
    1671                 :          0 :                 ENETC_PMD_ERR("SI VLAN isolation command failed: class_id=0x%x status=0x%x",
    1672                 :            :                               reply_msg->class_id, reply_msg->status);
    1673                 :            :                 err = -EINVAL;
    1674                 :            :         }
    1675                 :            : 
    1676                 :          0 : end:
    1677                 :          0 :         rte_free(msg->vaddr);
    1678                 :          0 :         rte_free(msg);
    1679                 :          0 :         rte_free(reply_msg);
    1680                 :          0 :         return err;
    1681                 :            : }
    1682                 :            : 
    1683                 :            : static int
    1684                 :          0 : enetc4_vf_mtu_set(struct rte_eth_dev *dev __rte_unused, uint16_t mtu __rte_unused)
    1685                 :            : {
    1686                 :          0 :         return 0;
    1687                 :            : }
    1688                 :            : 
    1689                 :            : static int
    1690                 :          0 : enetc4_vf_link_register_notif(struct rte_eth_dev *dev, bool enable)
    1691                 :            : {
    1692                 :          0 :         struct enetc_eth_hw *hw = ENETC_DEV_PRIVATE_TO_HW(dev->data->dev_private);
    1693                 :            :         struct enetc_msg_swbd *msg;
    1694                 :            :         struct rte_eth_link link;
    1695                 :            :         uint32_t msg_size;
    1696                 :            :         int err = 0;
    1697                 :            :         uint8_t cmd;
    1698                 :            : 
    1699                 :          0 :         PMD_INIT_FUNC_TRACE();
    1700                 :            :         memset(&link, 0, sizeof(struct rte_eth_link));
    1701                 :          0 :         msg = rte_zmalloc(NULL, sizeof(*msg), RTE_CACHE_LINE_SIZE);
    1702         [ #  # ]:          0 :         if (!msg) {
    1703                 :          0 :                 ENETC_PMD_ERR("Failed to alloc msg");
    1704                 :            :                 err = -ENOMEM;
    1705                 :          0 :                 return err;
    1706                 :            :         }
    1707                 :            : 
    1708                 :            :         msg_size = RTE_ALIGN(sizeof(struct enetc_msg_cmd_get_link_status), ENETC_VSI_PSI_MSG_SIZE);
    1709                 :          0 :         msg->vaddr = rte_zmalloc(NULL, msg_size, 0);
    1710         [ #  # ]:          0 :         if (!msg->vaddr) {
    1711                 :          0 :                 ENETC_PMD_ERR("Failed to alloc memory for msg");
    1712                 :          0 :                 rte_free(msg);
    1713                 :          0 :                 return -ENOMEM;
    1714                 :            :         }
    1715                 :            : 
    1716                 :          0 :         msg->dma = rte_mem_virt2iova((const void *)msg->vaddr);
    1717                 :          0 :         msg->size = msg_size;
    1718         [ #  # ]:          0 :         if (enable)
    1719                 :            :                 cmd = ENETC_CMD_ID_REGISTER_LINK_NOTIF;
    1720                 :            :         else
    1721                 :            :                 cmd = ENETC_CMD_ID_UNREGISTER_LINK_NOTIF;
    1722                 :            :         enetc_msg_vf_fill_common_hdr(msg, ENETC_CLASS_ID_LINK_STATUS,
    1723                 :            :                         cmd, 0, 0, 0);
    1724                 :            : 
    1725                 :            :         /* send the command and wait */
    1726                 :          0 :         err = enetc4_msg_vsi_send(hw, msg, NULL);
    1727         [ #  # ]:          0 :         if (err)
    1728                 :          0 :                 ENETC_PMD_ERR("VSI msg error for link status notification");
    1729                 :            : 
    1730                 :            :         /* free memory no longer required */
    1731                 :          0 :         rte_free(msg->vaddr);
    1732                 :          0 :         rte_free(msg);
    1733                 :            : 
    1734                 :          0 :         return err;
    1735                 :            : }
    1736                 :            : 
    1737                 :            : /*
    1738                 :            :  * The set of PCI devices this driver supports
    1739                 :            :  */
    1740                 :            : static const struct rte_pci_id pci_vf_id_enetc4_map[] = {
    1741                 :            :         { RTE_PCI_DEVICE(PCI_VENDOR_ID_NXP, ENETC4_DEV_ID_VF) },
    1742                 :            :         { .vendor_id = 0, /* sentinel */ },
    1743                 :            : };
    1744                 :            : 
    1745                 :            : static int
    1746                 :          0 : enetc4_vf_rx_queue_intr_enable(struct rte_eth_dev *dev, uint16_t queue_id)
    1747                 :            : {
    1748                 :            :         struct enetc_eth_hw *hw =
    1749                 :          0 :                 ENETC_DEV_PRIVATE_TO_HW(dev->data->dev_private);
    1750                 :            :         struct enetc_hw *enetc_hw = &hw->hw;
    1751                 :            :         struct enetc_bdr *rx_ring;
    1752                 :            :         uint16_t vec;
    1753                 :            : 
    1754         [ #  # ]:          0 :         if (hw->nc_mode)
    1755                 :            :                 return -ENOTSUP;
    1756                 :            : 
    1757         [ #  # ]:          0 :         if (!hw->rxq_intr_en)
    1758                 :            :                 return -ENOTSUP;
    1759                 :            : 
    1760                 :          0 :         vec = queue_id + ENETC4_VF_RX_VEC_BASE;
    1761                 :          0 :         rx_ring = (struct enetc_bdr *)dev->data->rx_queues[queue_id];
    1762                 :            : 
    1763                 :          0 :         enetc_wr(enetc_hw, ENETC_SIMSIRRV(queue_id), vec);
    1764                 :            :         /*
    1765                 :            :          * Do not overwrite RBICR1 when RSC (LRO) is active: the timer
    1766                 :            :          * programmed there is the coalesce-hold window and zeroing it
    1767                 :            :          * would disable coalescing, flushing every segment individually.
    1768                 :            :          */
    1769         [ #  # ]:          0 :         if (!rx_ring->rsc_enable)
    1770                 :          0 :                 enetc4_rxbdr_wr(enetc_hw, queue_id, ENETC4_RBICR1, 0);
    1771                 :          0 :         enetc4_rxbdr_wr(enetc_hw, queue_id, ENETC4_RBICR0,
    1772                 :            :                         ENETC4_RBICR0_ICEN | ENETC4_RBICR0_ICPT(1));
    1773                 :          0 :         enetc_wr(enetc_hw, ENETC_SIRXIDR, BIT(queue_id));
    1774                 :            : 
    1775                 :          0 :         enetc4_rxbdr_wr(enetc_hw, queue_id, ENETC_RBIER, ENETC_RBIER_RXTIE);
    1776                 :            : 
    1777                 :          0 :         return 0;
    1778                 :            : }
    1779                 :            : 
    1780                 :            : static int
    1781                 :          0 : enetc4_vf_rx_queue_intr_disable(struct rte_eth_dev *dev, uint16_t queue_id)
    1782                 :            : {
    1783                 :            :         struct enetc_eth_hw *hw =
    1784                 :          0 :                 ENETC_DEV_PRIVATE_TO_HW(dev->data->dev_private);
    1785                 :            :         struct enetc_hw *enetc_hw = &hw->hw;
    1786                 :            : 
    1787         [ #  # ]:          0 :         if (hw->nc_mode)
    1788                 :            :                 return -ENOTSUP;
    1789                 :            : 
    1790         [ #  # ]:          0 :         if (!hw->rxq_intr_en)
    1791                 :            :                 return 0;
    1792                 :            : 
    1793                 :          0 :         enetc4_rxbdr_wr(enetc_hw, queue_id, ENETC_RBIER, 0);
    1794                 :          0 :         enetc_wr(enetc_hw, ENETC_SIMSIRRV(queue_id), 0);
    1795                 :            : 
    1796                 :          0 :         return 0;
    1797                 :            : }
    1798                 :            : 
    1799                 :            : /* Features supported by this driver */
    1800                 :            : /* ops table used when VSI messaging is disabled */
    1801                 :            : static const struct eth_dev_ops enetc4_vf_ops_no_vsi_m = {
    1802                 :            :         .dev_configure        = enetc4_dev_configure,
    1803                 :            :         .dev_start            = enetc4_vf_dev_start,
    1804                 :            :         .dev_stop             = enetc4_vf_dev_stop,
    1805                 :            :         .dev_close            = enetc4_dev_close,
    1806                 :            :         .stats_get            = enetc4_vf_stats_get,
    1807                 :            :         .stats_reset          = enetc4_vf_stats_reset,
    1808                 :            :         .dev_infos_get        = enetc4_vf_dev_infos_get,
    1809                 :            :         .get_reg              = enetc4_vf_get_regs,
    1810                 :            :         .mtu_set              = enetc4_vf_mtu_set,
    1811                 :            :         .link_update          = enetc4_vf_link_update_dummy,
    1812                 :            :         .rx_queue_setup       = enetc4_rx_queue_setup,
    1813                 :            :         .rx_queue_start       = enetc4_rx_queue_start,
    1814                 :            :         .rx_queue_stop        = enetc4_rx_queue_stop,
    1815                 :            :         .rx_queue_release     = enetc4_rx_queue_release,
    1816                 :            :         .rxq_info_get         = enetc4_rxq_info_get,
    1817                 :            :         .rx_queue_intr_enable  = enetc4_vf_rx_queue_intr_enable,
    1818                 :            :         .rx_queue_intr_disable = enetc4_vf_rx_queue_intr_disable,
    1819                 :            :         .tx_queue_setup       = enetc4_tx_queue_setup,
    1820                 :            :         .tx_queue_start       = enetc4_tx_queue_start,
    1821                 :            :         .tx_queue_stop        = enetc4_tx_queue_stop,
    1822                 :            :         .tx_queue_release     = enetc4_tx_queue_release,
    1823                 :            :         .txq_info_get         = enetc4_txq_info_get,
    1824                 :            :         .dev_supported_ptypes_get = enetc4_supported_ptypes_get,
    1825                 :            : };
    1826                 :            : 
    1827                 :            : static const struct eth_dev_ops enetc4_vf_ops = {
    1828                 :            :         .dev_configure        = enetc4_dev_configure,
    1829                 :            :         .dev_start            = enetc4_vf_dev_start,
    1830                 :            :         .dev_stop             = enetc4_vf_dev_stop,
    1831                 :            :         .dev_close            = enetc4_dev_close,
    1832                 :            :         .stats_get            = enetc4_vf_stats_get,
    1833                 :            :         .stats_reset          = enetc4_vf_stats_reset,
    1834                 :            :         .dev_infos_get        = enetc4_vf_dev_infos_get,
    1835                 :            :         .fw_version_get       = enetc4_vf_fw_version_get,
    1836                 :            :         .get_reg              = enetc4_vf_get_regs,
    1837                 :            :         .mtu_set              = enetc4_vf_mtu_set,
    1838                 :            :         .mac_addr_set         = enetc4_vf_set_mac_addr,
    1839                 :            :         .mac_addr_add         = enetc4_vf_mac_addr_add,
    1840                 :            :         .promiscuous_enable   = enetc4_vf_promisc_enable,
    1841                 :            :         .promiscuous_disable  = enetc4_vf_promisc_disable,
    1842                 :            :         .allmulticast_enable  = enetc4_vf_multicast_enable,
    1843                 :            :         .allmulticast_disable = enetc4_vf_multicast_disable,
    1844                 :            :         .link_update          = enetc4_vf_link_update,
    1845                 :            :         .vlan_filter_set      = enetc4_vf_vlan_filter_set,
    1846                 :            :         .vlan_offload_set     = enetc4_vf_vlan_offload_set,
    1847                 :            :         .vlan_pvid_set        = enetc4_vf_vlan_pvid_set,
    1848                 :            :         .rx_queue_setup       = enetc4_rx_queue_setup,
    1849                 :            :         .rx_queue_start       = enetc4_rx_queue_start,
    1850                 :            :         .rx_queue_stop        = enetc4_rx_queue_stop,
    1851                 :            :         .rx_queue_release     = enetc4_rx_queue_release,
    1852                 :            :         .rxq_info_get         = enetc4_rxq_info_get,
    1853                 :            :         .rx_queue_intr_enable  = enetc4_vf_rx_queue_intr_enable,
    1854                 :            :         .rx_queue_intr_disable = enetc4_vf_rx_queue_intr_disable,
    1855                 :            :         .tx_queue_setup       = enetc4_tx_queue_setup,
    1856                 :            :         .tx_queue_start       = enetc4_tx_queue_start,
    1857                 :            :         .tx_queue_stop        = enetc4_tx_queue_stop,
    1858                 :            :         .tx_queue_release     = enetc4_tx_queue_release,
    1859                 :            :         .txq_info_get         = enetc4_txq_info_get,
    1860                 :            :         .dev_supported_ptypes_get = enetc4_supported_ptypes_get,
    1861                 :            : };
    1862                 :            : 
    1863                 :            : static int
    1864                 :          0 : enetc4_vf_mac_init(struct enetc_eth_hw *hw, struct rte_eth_dev *eth_dev)
    1865                 :            : {
    1866                 :          0 :         uint32_t *mac = (uint32_t *)hw->mac.addr;
    1867                 :            :         struct enetc_hw *enetc_hw = &hw->hw;
    1868                 :            :         uint32_t high_mac = 0;
    1869                 :            :         uint16_t low_mac = 0;
    1870                 :            :         char vf_eth_name[ENETC_ETH_NAMESIZE];
    1871                 :            : 
    1872                 :          0 :         PMD_INIT_FUNC_TRACE();
    1873                 :            : 
    1874                 :            :         /* Enabling Station Interface */
    1875                 :          0 :         enetc4_wr(enetc_hw, ENETC_SIMR, ENETC_SIMR_EN);
    1876                 :          0 :         *mac = (uint32_t)enetc_rd(enetc_hw, ENETC_SIPMAR0);
    1877                 :            :         high_mac = (uint32_t)*mac;
    1878                 :            :         mac++;
    1879                 :          0 :         *mac = (uint16_t)enetc_rd(enetc_hw, ENETC_SIPMAR1);
    1880                 :            :         low_mac = (uint16_t)*mac;
    1881                 :            : 
    1882         [ #  # ]:          0 :         if ((high_mac | low_mac) == 0) {
    1883                 :            :                 char *first_byte;
    1884                 :          0 :                 ENETC_PMD_NOTICE("MAC is not available for this SI, "
    1885                 :            :                                  "set random MAC");
    1886                 :            :                 mac = (uint32_t *)hw->mac.addr;
    1887                 :          0 :                 *mac = (uint32_t)rte_rand();
    1888                 :            :                 first_byte = (char *)mac;
    1889                 :          0 :                 *first_byte &= 0xfe;    /* clear multicast bit */
    1890                 :          0 :                 *first_byte |= 0x02;    /* set local assignment bit (IEEE802) */
    1891                 :          0 :                 enetc4_port_wr(enetc_hw, ENETC4_PMAR0, *mac);
    1892                 :            :                 mac++;
    1893                 :          0 :                 *mac = (uint16_t)rte_rand();
    1894                 :          0 :                 enetc4_port_wr(enetc_hw, ENETC4_PMAR1, *mac);
    1895                 :          0 :                 enetc_print_ethaddr("New address: ",
    1896                 :            :                         (const struct rte_ether_addr *)hw->mac.addr);
    1897                 :            :         }
    1898                 :            : 
    1899                 :            :         /* Allocate memory for storing MAC addresses */
    1900                 :          0 :         snprintf(vf_eth_name, sizeof(vf_eth_name), "enetc4_vf_eth_%d", eth_dev->data->port_id);
    1901                 :          0 :         eth_dev->data->mac_addrs = rte_zmalloc(vf_eth_name,
    1902                 :            :                                         RTE_ETHER_ADDR_LEN, 0);
    1903         [ #  # ]:          0 :         if (!eth_dev->data->mac_addrs) {
    1904                 :          0 :                 ENETC_PMD_ERR("Failed to allocate %d bytes needed to "
    1905                 :            :                               "store MAC addresses",
    1906                 :            :                               RTE_ETHER_ADDR_LEN * 1);
    1907                 :          0 :                 return -ENOMEM;
    1908                 :            :         }
    1909                 :            : 
    1910         [ #  # ]:          0 :         if (!enetc_crc_gen)
    1911                 :          0 :                 enetc_gen_crc_table();
    1912                 :            : 
    1913                 :            :         /* Copy the permanent MAC address */
    1914                 :            :         rte_ether_addr_copy((struct rte_ether_addr *)hw->mac.addr,
    1915                 :            :                              &eth_dev->data->mac_addrs[0]);
    1916                 :            : 
    1917                 :          0 :         return 0;
    1918                 :            : }
    1919                 :            : 
    1920                 :            : static void
    1921                 :          0 : enetc_vf_enable_mr_int(struct enetc_hw *hw, bool en)
    1922                 :            : {
    1923                 :            :         uint32_t val;
    1924                 :            : 
    1925                 :          0 :         val = enetc_rd(hw, ENETC4_VSIIER);
    1926                 :          0 :         val &= ~ENETC4_VSIIER_MRIE;
    1927         [ #  # ]:          0 :         val |= (en) ? ENETC4_VSIIER_MRIE : 0;
    1928                 :          0 :         enetc_wr(hw, ENETC4_VSIIER, val);
    1929                 :          0 :         ENETC_PMD_DEBUG("Interrupt enable status (VSIIER) = 0x%x", val);
    1930                 :          0 : }
    1931                 :            : 
    1932                 :            : static void
    1933                 :          0 : enetc4_dev_interrupt_handler(void *param)
    1934                 :            : {
    1935                 :            :         struct rte_eth_dev *eth_dev = (struct rte_eth_dev *)param;
    1936                 :            :         struct enetc_eth_hw *hw =
    1937                 :          0 :                 ENETC_DEV_PRIVATE_TO_HW(eth_dev->data->dev_private);
    1938                 :          0 :         struct enetc_hw *enetc_hw = &hw->hw;
    1939                 :            :         uint32_t status;
    1940                 :            : 
    1941                 :            :         /* Disable interrupts before process */
    1942                 :          0 :         enetc_vf_enable_mr_int(enetc_hw, false);
    1943                 :            : 
    1944                 :          0 :         status = enetc_rd(enetc_hw, ENETC4_VSIIDR);
    1945                 :          0 :         ENETC_PMD_DEBUG("Got INTR VSIIDR status = 0x%0x", status);
    1946                 :            :         /* Check for PSI to VSI message interrupt */
    1947         [ #  # ]:          0 :         if (!(status & ENETC4_VSIIER_MRIE)) {
    1948                 :          0 :                 ENETC_PMD_ERR("Interrupt is not PSI to VSI");
    1949                 :          0 :                 goto intr_clear;
    1950                 :            :         }
    1951                 :            : 
    1952                 :          0 :         enetc4_process_psi_msg(eth_dev, enetc_hw);
    1953                 :          0 : intr_clear:
    1954                 :            :         /* Clear Interrupts */
    1955                 :          0 :         enetc_wr(enetc_hw, ENETC4_VSIIDR, 0xffffffff);
    1956                 :          0 :         enetc_vf_enable_mr_int(enetc_hw, true);
    1957                 :          0 : }
    1958                 :            : 
    1959                 :            : static int
    1960                 :          0 : enetc4_vf_dev_init(struct rte_eth_dev *eth_dev)
    1961                 :            : {
    1962                 :          0 :         struct enetc_eth_hw *hw =
    1963                 :          0 :                             ENETC_DEV_PRIVATE_TO_HW(eth_dev->data->dev_private);
    1964                 :          0 :         struct rte_pci_device *pci_dev = RTE_CLASS_TO_BUS_DEVICE(eth_dev, *pci_dev);
    1965                 :            :         int error = 0;
    1966                 :            :         uint32_t si_cap;
    1967                 :            :         struct enetc_hw *enetc_hw = &hw->hw;
    1968                 :            :         pthread_mutexattr_t attr;
    1969                 :            : 
    1970                 :          0 :         PMD_INIT_FUNC_TRACE();
    1971                 :            : 
    1972         [ #  # ]:          0 :         if (rte_eal_process_type() != RTE_PROC_PRIMARY) {
    1973                 :          0 :                 eth_dev->dev_ops = &enetc4_vf_ops;
    1974                 :            :                 /*
    1975                 :            :                  * Secondary process: set the fast-path burst pointers here or
    1976                 :            :                  * rte_eth_rx_burst()/rte_eth_tx_burst() would dereference NULL.
    1977                 :            :                  * hw->nc_mode lives in the shared dev_private and has already
    1978                 :            :                  * been set by the primary, so honour it to match the base BD
    1979                 :            :                  * ring layout. The RSC (LRO) and LSO (TSO) bursts use doubled
    1980                 :            :                  * 32B descriptor rings that the primary selects only at queue
    1981                 :            :                  * setup; the secondary cannot observe that choice, so it always
    1982                 :            :                  * uses the base (nc or cacheable) burst. Running the Rx/Tx
    1983                 :            :                  * datapath from a secondary is therefore not supported when LRO
    1984                 :            :                  * or TSO is enabled (see the ENETC4 NIC guide).
    1985                 :            :                  */
    1986         [ #  # ]:          0 :                 if (hw->nc_mode) {
    1987                 :          0 :                         eth_dev->rx_pkt_burst = &enetc_recv_pkts_nc;
    1988                 :          0 :                         eth_dev->tx_pkt_burst = &enetc_xmit_pkts_nc;
    1989                 :            :                 } else {
    1990                 :          0 :                         eth_dev->rx_pkt_burst = &enetc_recv_pkts_cacheable;
    1991                 :          0 :                         eth_dev->tx_pkt_burst = &enetc_xmit_pkts_cacheable;
    1992                 :            :                 }
    1993                 :          0 :                 return 0;
    1994                 :            :         }
    1995                 :            : 
    1996                 :            :         /* check if VSI messaging should be disabled via devarg */
    1997         [ #  # ]:          0 :         if (eth_dev->device->devargs) {
    1998                 :            :                 struct rte_kvargs *kvlist;
    1999                 :            : 
    2000                 :          0 :                 kvlist = rte_kvargs_parse(eth_dev->device->devargs->args,
    2001                 :            :                                           NULL);
    2002         [ #  # ]:          0 :                 if (kvlist) {
    2003                 :            :                         const char *val;
    2004                 :            : 
    2005         [ #  # ]:          0 :                         if (rte_kvargs_count(kvlist, ENETC4_VSI_DISABLE) != 0) {
    2006                 :          0 :                                 ENETC_PMD_NOTICE("VSI messaging disabled by devarg");
    2007                 :          0 :                                 eth_dev->dev_ops = &enetc4_vf_ops_no_vsi_m;
    2008                 :            :                         } else {
    2009                 :          0 :                                 eth_dev->dev_ops = &enetc4_vf_ops;
    2010                 :            :                         }
    2011                 :            : 
    2012                 :            :                         /* parse optional VSI-PSI timeout devarg */
    2013                 :          0 :                         val = rte_kvargs_get(kvlist, ENETC4_VSI_TIMEOUT);
    2014         [ #  # ]:          0 :                         if (val) {
    2015                 :          0 :                                 errno = 0;
    2016                 :          0 :                                 hw->vsi_timeout = (uint32_t)strtoul(val, NULL, 0);
    2017   [ #  #  #  # ]:          0 :                                 if (errno != 0 || hw->vsi_timeout == 0) {
    2018                 :          0 :                                         ENETC_PMD_ERR("Invalid VSI Timeout value = %u",
    2019                 :            :                                                         hw->vsi_timeout);
    2020                 :          0 :                                         rte_kvargs_free(kvlist);
    2021                 :          0 :                                         return -1;
    2022                 :            :                                 }
    2023                 :          0 :                                 ENETC_PMD_NOTICE("VSI timeout set to %u", hw->vsi_timeout);
    2024                 :            :                         }
    2025                 :            : 
    2026                 :            :                         /* parse optional VSI-PSI delay devarg */
    2027                 :          0 :                         val = rte_kvargs_get(kvlist, ENETC4_VSI_DELAY);
    2028         [ #  # ]:          0 :                         if (val) {
    2029                 :          0 :                                 errno = 0;
    2030                 :          0 :                                 hw->vsi_delay = (uint32_t)strtoul(val, NULL, 0);
    2031   [ #  #  #  # ]:          0 :                                 if (errno != 0 || hw->vsi_delay == 0) {
    2032                 :          0 :                                         ENETC_PMD_ERR("Invalid VSI Delay value = %u",
    2033                 :            :                                                         hw->vsi_delay);
    2034                 :          0 :                                         rte_kvargs_free(kvlist);
    2035                 :          0 :                                         return -1;
    2036                 :            :                                 }
    2037                 :          0 :                                 ENETC_PMD_NOTICE("VSI delay set to %u us", hw->vsi_delay);
    2038                 :            :                         }
    2039                 :            : 
    2040                 :          0 :                         rte_kvargs_free(kvlist);
    2041                 :            :                 } else {
    2042                 :          0 :                         eth_dev->dev_ops = &enetc4_vf_ops;
    2043                 :            :                 }
    2044                 :            :         } else {
    2045                 :          0 :                 eth_dev->dev_ops = &enetc4_vf_ops;
    2046                 :            :         }
    2047                 :            : 
    2048                 :          0 :         enetc4_dev_hw_init(eth_dev);
    2049                 :            : 
    2050                 :          0 :         pthread_mutexattr_init(&attr);
    2051                 :          0 :         pthread_mutexattr_setpshared(&attr, PTHREAD_PROCESS_SHARED);
    2052                 :          0 :         pthread_mutex_init(&hw->vsi_lock, &attr);
    2053                 :          0 :         pthread_mutexattr_destroy(&attr);
    2054                 :            : 
    2055                 :          0 :         hw->nc_mode = 0;
    2056                 :          0 :         enetc4_vf_get_devarg_nc(eth_dev);
    2057         [ #  # ]:          0 :         if (hw->nc_mode) {
    2058                 :          0 :                 eth_dev->rx_pkt_burst = &enetc_recv_pkts_nc;
    2059                 :          0 :                 eth_dev->tx_pkt_burst = &enetc_xmit_pkts_nc;
    2060                 :          0 :                 ENETC_PMD_LOG(INFO, "nc=1: using non-cacheable BD ops (_nc)");
    2061                 :            :         }
    2062                 :            : 
    2063                 :          0 :         si_cap = enetc_rd(enetc_hw, ENETC_SICAPR0);
    2064                 :          0 :         hw->max_tx_queues = si_cap & ENETC_SICAPR0_BDR_MASK;
    2065                 :          0 :         hw->max_rx_queues = (si_cap >> 16) & ENETC_SICAPR0_BDR_MASK;
    2066                 :            : 
    2067                 :          0 :         ENETC_PMD_DEBUG("Max RX queues = %d Max TX queues = %d",
    2068                 :            :                         hw->max_rx_queues, hw->max_tx_queues);
    2069                 :          0 :         error = enetc4_vf_mac_init(hw, eth_dev);
    2070         [ #  # ]:          0 :         if (error != 0) {
    2071                 :          0 :                 ENETC_PMD_ERR("MAC initialization failed!!");
    2072                 :          0 :                 return -1;
    2073                 :            :         }
    2074                 :            : 
    2075         [ #  # ]:          0 :         if (rte_eal_iova_mode() == RTE_IOVA_PA)
    2076                 :          0 :                 dpaax_iova_table_populate();
    2077                 :            : 
    2078                 :            :         /* Parse VF specific devargs (e.g. vf_link_legacy) before the first
    2079                 :            :          * link update so that PF-to-VF link messages are interpreted using
    2080                 :            :          * the correct (legacy or current) layout.
    2081                 :            :          */
    2082                 :          0 :         enetc4_vf_get_devargs(eth_dev);
    2083                 :            : 
    2084                 :          0 :         ENETC_PMD_DEBUG("port_id %d vendorID=0x%x deviceID=0x%x",
    2085                 :            :                         eth_dev->data->port_id, pci_dev->id.vendor_id,
    2086                 :            :                         pci_dev->id.device_id);
    2087                 :            :         /* update link if VSI messaging is enabled */
    2088         [ #  # ]:          0 :         if (eth_dev->dev_ops == &enetc4_vf_ops)
    2089                 :          0 :                 enetc4_vf_link_update(eth_dev, 0);
    2090                 :            : 
    2091                 :            :         return 0;
    2092                 :            : }
    2093                 :            : 
    2094                 :            : static int
    2095                 :          0 : enetc4_vf_pci_probe(struct rte_pci_driver *pci_drv __rte_unused,
    2096                 :            :                     struct rte_pci_device *pci_dev)
    2097                 :            : {
    2098                 :          0 :         return rte_eth_dev_pci_generic_probe(pci_dev,
    2099                 :            :                                              sizeof(struct enetc_eth_adapter),
    2100                 :            :                                              enetc4_vf_dev_init);
    2101                 :            : }
    2102                 :            : 
    2103                 :            : int
    2104                 :          0 : enetc4_vf_dev_intr(struct rte_eth_dev *eth_dev, bool enable)
    2105                 :            : {
    2106                 :            :         struct enetc_eth_hw *hw =
    2107                 :          0 :                 ENETC_DEV_PRIVATE_TO_HW(eth_dev->data->dev_private);
    2108                 :          0 :         struct enetc_hw *enetc_hw = &hw->hw;
    2109                 :          0 :         struct rte_pci_device *pci_dev = RTE_CLASS_TO_BUS_DEVICE(eth_dev, *pci_dev);
    2110                 :          0 :         struct rte_intr_handle *intr_handle = pci_dev->intr_handle;
    2111                 :            :         int ret = 0;
    2112                 :            : 
    2113                 :          0 :         PMD_INIT_FUNC_TRACE();
    2114   [ #  #  #  # ]:          0 :         if (!(intr_handle && rte_intr_fd_get(intr_handle))) {
    2115                 :          0 :                 ENETC_PMD_ERR("No INTR handle");
    2116                 :          0 :                 return -1;
    2117                 :            :         }
    2118         [ #  # ]:          0 :         if (enable) {
    2119                 :            :                 /* if the interrupts were configured on this devices*/
    2120                 :          0 :                 ret = rte_intr_callback_register(intr_handle,
    2121                 :            :                                 enetc4_dev_interrupt_handler, eth_dev);
    2122         [ #  # ]:          0 :                 if (ret) {
    2123                 :          0 :                         ENETC_PMD_ERR("Failed to register INTR callback %d", ret);
    2124                 :          0 :                         return ret;
    2125                 :            :                 }
    2126                 :            :                 /* set one IRQ entry for PSI-to-VSI messaging */
    2127                 :            :                 /* Vector index 0 */
    2128                 :          0 :                 enetc_wr(enetc_hw, ENETC4_SIMSIVR, ENETC4_SI_INT_IDX);
    2129                 :            : 
    2130         [ #  # ]:          0 :                 if (rte_intr_cap_multiple(intr_handle) &&
    2131         [ #  # ]:          0 :                     eth_dev->data->nb_rx_queues > 0) {
    2132                 :            :                         uint16_t nb_rx = eth_dev->data->nb_rx_queues;
    2133                 :            :                         uint16_t i;
    2134                 :            : 
    2135                 :          0 :                         ret = rte_intr_efd_enable(intr_handle,
    2136                 :          0 :                                         nb_rx + ENETC4_VF_RX_VEC_BASE);
    2137         [ #  # ]:          0 :                         if (ret) {
    2138                 :          0 :                                 ENETC_PMD_WARN("Failed to enable per-queue Rx eventfds: %d",
    2139                 :            :                                                ret);
    2140                 :          0 :                                 hw->rxq_intr_en = 0;
    2141                 :            :                         } else {
    2142                 :          0 :                                 ret = rte_intr_vec_list_alloc(intr_handle,
    2143                 :            :                                                 "enetc4_vf_rx_intr", nb_rx);
    2144         [ #  # ]:          0 :                                 if (ret) {
    2145                 :          0 :                                         ENETC_PMD_WARN("Failed to alloc intr vec list: %d",
    2146                 :            :                                                        ret);
    2147                 :          0 :                                         rte_intr_efd_disable(intr_handle);
    2148                 :          0 :                                         hw->rxq_intr_en = 0;
    2149                 :            :                                 } else {
    2150         [ #  # ]:          0 :                                         for (i = 0; i < nb_rx; i++)
    2151                 :          0 :                                                 rte_intr_vec_list_index_set(intr_handle, i,
    2152                 :            :                                                         i + ENETC4_VF_RX_VEC_BASE);
    2153                 :          0 :                                         hw->rxq_intr_en = 1;
    2154                 :            :                                 }
    2155                 :            :                         }
    2156                 :            :                 }
    2157                 :            : 
    2158                 :            :                 /* enable uio/vfio intr/eventfd mapping */
    2159                 :          0 :                 ret = rte_intr_enable(intr_handle);
    2160         [ #  # ]:          0 :                 if (ret) {
    2161                 :          0 :                         ENETC_PMD_ERR("Failed to enable INTR %d", ret);
    2162                 :          0 :                         goto intr_enable_fail;
    2163                 :            :                 }
    2164                 :            : 
    2165                 :            :                 /* Enable message received interrupt */
    2166                 :          0 :                 enetc_vf_enable_mr_int(enetc_hw, true);
    2167                 :          0 :                 ret = enetc4_vf_link_register_notif(eth_dev, true);
    2168         [ #  # ]:          0 :                 if (ret) {
    2169                 :          0 :                         ENETC_PMD_ERR("Failed to register link notifications %d", ret);
    2170                 :          0 :                         goto disable;
    2171                 :            :                 }
    2172                 :            : 
    2173                 :            :                 return ret;
    2174                 :            :         }
    2175                 :            : 
    2176                 :          0 :         ret = enetc4_vf_link_register_notif(eth_dev, false);
    2177         [ #  # ]:          0 :         if (ret)
    2178                 :          0 :                 ENETC_PMD_WARN("Failed to un-register link notification %d", ret);
    2179                 :          0 : disable:
    2180                 :          0 :         enetc_vf_enable_mr_int(enetc_hw, false);
    2181                 :          0 :         hw->rxq_intr_en = 0;
    2182                 :          0 :         ret = rte_intr_disable(intr_handle);
    2183         [ #  # ]:          0 :         if (ret)
    2184                 :          0 :                 ENETC_PMD_WARN("Failed to disable INTR %d", ret);
    2185                 :          0 : intr_enable_fail:
    2186                 :          0 :         rte_intr_vec_list_free(intr_handle);
    2187                 :          0 :         rte_intr_efd_disable(intr_handle);
    2188                 :          0 :         ret = rte_intr_callback_unregister(intr_handle,
    2189                 :            :                         enetc4_dev_interrupt_handler, eth_dev);
    2190         [ #  # ]:          0 :         if (ret < 0)
    2191                 :          0 :                 ENETC_PMD_WARN("Failed to unregister intr callback: %d", ret);
    2192                 :            : 
    2193                 :            :         return ret;
    2194                 :            : }
    2195                 :            : 
    2196                 :            : static struct rte_pci_driver rte_enetc4_vf_pmd = {
    2197                 :            :         .id_table = pci_vf_id_enetc4_map,
    2198                 :            :         .drv_flags = RTE_PCI_DRV_NEED_MAPPING | RTE_PCI_DRV_INTR_LSC,
    2199                 :            :         .probe = enetc4_vf_pci_probe,
    2200                 :            :         .remove = enetc4_pci_remove,
    2201                 :            : };
    2202                 :            : 
    2203                 :        302 : RTE_PMD_REGISTER_PCI(net_enetc4_vf, rte_enetc4_vf_pmd);
    2204                 :            : RTE_PMD_REGISTER_PCI_TABLE(net_enetc4_vf, pci_vf_id_enetc4_map);
    2205                 :            : RTE_PMD_REGISTER_KMOD_DEP(net_enetc4_vf, "* igb_uio | uio_pci_generic | vfio-pci");
    2206                 :            : RTE_PMD_REGISTER_PARAM_STRING(net_enetc4_vf,
    2207                 :            :                               ENETC4_VSI_DISABLE "=<any> "
    2208                 :            :                               ENETC4_VSI_TIMEOUT "=<uint> "
    2209                 :            :                               ENETC4_VSI_DELAY "=<uint> "
    2210                 :            :                               ENETC4_NC_MEMORY "=<int> "
    2211                 :            :                               ENETC4_TXQ_PRIORITIES "=<string> "
    2212                 :            :                               ENETC4_TXQ_WRR "=<string> "
    2213                 :            :                               ENETC_VF_LINK_LEGACY "=<0|1>");
    2214         [ -  + ]:        302 : RTE_LOG_REGISTER_DEFAULT(enetc4_vf_logtype_pmd, NOTICE);

Generated by: LCOV version 1.14