LCOV - code coverage report
Current view: top level - drivers/net/intel/cpfl - cpfl_ethdev.c (source / functions) Hit Total Coverage
Test: Code coverage Lines: 3 1288 0.2 %
Date: 2025-02-01 18:54:23 Functions: 3 76 3.9 %
Legend: Lines: hit not hit | Branches: + taken - not taken # not executed Branches: 2 670 0.3 %

           Branch data     Line data    Source code
       1                 :            : /* SPDX-License-Identifier: BSD-3-Clause
       2                 :            :  * Copyright(c) 2023 Intel Corporation
       3                 :            :  */
       4                 :            : 
       5                 :            : #include <rte_atomic.h>
       6                 :            : #include <rte_eal.h>
       7                 :            : #include <rte_ether.h>
       8                 :            : #include <rte_malloc.h>
       9                 :            : #include <rte_memzone.h>
      10                 :            : #include <rte_dev.h>
      11                 :            : #include <errno.h>
      12                 :            : #include <rte_alarm.h>
      13                 :            : #include <rte_hash_crc.h>
      14                 :            : 
      15                 :            : #include "cpfl_ethdev.h"
      16                 :            : #include <ethdev_private.h>
      17                 :            : #include <sys/utsname.h>
      18                 :            : #include "cpfl_rxtx.h"
      19                 :            : #include "cpfl_flow.h"
      20                 :            : #include "cpfl_rules.h"
      21                 :            : 
      22                 :            : #define CPFL_REPRESENTOR        "representor"
      23                 :            : #define CPFL_TX_SINGLE_Q        "tx_single"
      24                 :            : #define CPFL_RX_SINGLE_Q        "rx_single"
      25                 :            : #define CPFL_VPORT              "vport"
      26                 :            : 
      27                 :            : #ifdef RTE_HAS_JANSSON
      28                 :            : #define CPFL_FLOW_PARSER        "flow_parser"
      29                 :            : #endif
      30                 :            : 
      31                 :            : rte_spinlock_t cpfl_adapter_lock;
      32                 :            : /* A list for all adapters, one adapter matches one PCI device */
      33                 :            : struct cpfl_adapter_list cpfl_adapter_list;
      34                 :            : bool cpfl_adapter_list_init;
      35                 :            : 
      36                 :            : static const char * const cpfl_valid_args_first[] = {
      37                 :            :         CPFL_REPRESENTOR,
      38                 :            :         CPFL_TX_SINGLE_Q,
      39                 :            :         CPFL_RX_SINGLE_Q,
      40                 :            :         CPFL_VPORT,
      41                 :            : #ifdef RTE_HAS_JANSSON
      42                 :            :         CPFL_FLOW_PARSER,
      43                 :            : #endif
      44                 :            :         NULL
      45                 :            : };
      46                 :            : 
      47                 :            : static const char * const cpfl_valid_args_again[] = {
      48                 :            :         CPFL_REPRESENTOR,
      49                 :            :         NULL
      50                 :            : };
      51                 :            : 
      52                 :            : uint32_t cpfl_supported_speeds[] = {
      53                 :            :         RTE_ETH_SPEED_NUM_NONE,
      54                 :            :         RTE_ETH_SPEED_NUM_10M,
      55                 :            :         RTE_ETH_SPEED_NUM_100M,
      56                 :            :         RTE_ETH_SPEED_NUM_1G,
      57                 :            :         RTE_ETH_SPEED_NUM_2_5G,
      58                 :            :         RTE_ETH_SPEED_NUM_5G,
      59                 :            :         RTE_ETH_SPEED_NUM_10G,
      60                 :            :         RTE_ETH_SPEED_NUM_20G,
      61                 :            :         RTE_ETH_SPEED_NUM_25G,
      62                 :            :         RTE_ETH_SPEED_NUM_40G,
      63                 :            :         RTE_ETH_SPEED_NUM_50G,
      64                 :            :         RTE_ETH_SPEED_NUM_56G,
      65                 :            :         RTE_ETH_SPEED_NUM_100G,
      66                 :            :         RTE_ETH_SPEED_NUM_200G
      67                 :            : };
      68                 :            : 
      69                 :            : static const uint64_t cpfl_map_hena_rss[] = {
      70                 :            :         [IDPF_HASH_NONF_UNICAST_IPV4_UDP] =
      71                 :            :                         RTE_ETH_RSS_NONFRAG_IPV4_UDP,
      72                 :            :         [IDPF_HASH_NONF_MULTICAST_IPV4_UDP] =
      73                 :            :                         RTE_ETH_RSS_NONFRAG_IPV4_UDP,
      74                 :            :         [IDPF_HASH_NONF_IPV4_UDP] =
      75                 :            :                         RTE_ETH_RSS_NONFRAG_IPV4_UDP,
      76                 :            :         [IDPF_HASH_NONF_IPV4_TCP_SYN_NO_ACK] =
      77                 :            :                         RTE_ETH_RSS_NONFRAG_IPV4_TCP,
      78                 :            :         [IDPF_HASH_NONF_IPV4_TCP] =
      79                 :            :                         RTE_ETH_RSS_NONFRAG_IPV4_TCP,
      80                 :            :         [IDPF_HASH_NONF_IPV4_SCTP] =
      81                 :            :                         RTE_ETH_RSS_NONFRAG_IPV4_SCTP,
      82                 :            :         [IDPF_HASH_NONF_IPV4_OTHER] =
      83                 :            :                         RTE_ETH_RSS_NONFRAG_IPV4_OTHER,
      84                 :            :         [IDPF_HASH_FRAG_IPV4] = RTE_ETH_RSS_FRAG_IPV4,
      85                 :            : 
      86                 :            :         /* IPv6 */
      87                 :            :         [IDPF_HASH_NONF_UNICAST_IPV6_UDP] =
      88                 :            :                         RTE_ETH_RSS_NONFRAG_IPV6_UDP,
      89                 :            :         [IDPF_HASH_NONF_MULTICAST_IPV6_UDP] =
      90                 :            :                         RTE_ETH_RSS_NONFRAG_IPV6_UDP,
      91                 :            :         [IDPF_HASH_NONF_IPV6_UDP] =
      92                 :            :                         RTE_ETH_RSS_NONFRAG_IPV6_UDP,
      93                 :            :         [IDPF_HASH_NONF_IPV6_TCP_SYN_NO_ACK] =
      94                 :            :                         RTE_ETH_RSS_NONFRAG_IPV6_TCP,
      95                 :            :         [IDPF_HASH_NONF_IPV6_TCP] =
      96                 :            :                         RTE_ETH_RSS_NONFRAG_IPV6_TCP,
      97                 :            :         [IDPF_HASH_NONF_IPV6_SCTP] =
      98                 :            :                         RTE_ETH_RSS_NONFRAG_IPV6_SCTP,
      99                 :            :         [IDPF_HASH_NONF_IPV6_OTHER] =
     100                 :            :                         RTE_ETH_RSS_NONFRAG_IPV6_OTHER,
     101                 :            :         [IDPF_HASH_FRAG_IPV6] = RTE_ETH_RSS_FRAG_IPV6,
     102                 :            : 
     103                 :            :         /* L2 Payload */
     104                 :            :         [IDPF_HASH_L2_PAYLOAD] = RTE_ETH_RSS_L2_PAYLOAD
     105                 :            : };
     106                 :            : 
     107                 :            : static const uint64_t cpfl_ipv4_rss = RTE_ETH_RSS_NONFRAG_IPV4_UDP |
     108                 :            :                           RTE_ETH_RSS_NONFRAG_IPV4_TCP |
     109                 :            :                           RTE_ETH_RSS_NONFRAG_IPV4_SCTP |
     110                 :            :                           RTE_ETH_RSS_NONFRAG_IPV4_OTHER |
     111                 :            :                           RTE_ETH_RSS_FRAG_IPV4;
     112                 :            : 
     113                 :            : static const uint64_t cpfl_ipv6_rss = RTE_ETH_RSS_NONFRAG_IPV6_UDP |
     114                 :            :                           RTE_ETH_RSS_NONFRAG_IPV6_TCP |
     115                 :            :                           RTE_ETH_RSS_NONFRAG_IPV6_SCTP |
     116                 :            :                           RTE_ETH_RSS_NONFRAG_IPV6_OTHER |
     117                 :            :                           RTE_ETH_RSS_FRAG_IPV6;
     118                 :            : 
     119                 :            : struct rte_cpfl_xstats_name_off {
     120                 :            :         char name[RTE_ETH_XSTATS_NAME_SIZE];
     121                 :            :         unsigned int offset;
     122                 :            : };
     123                 :            : 
     124                 :            : static const struct rte_cpfl_xstats_name_off rte_cpfl_stats_strings[] = {
     125                 :            :         {"rx_bytes", offsetof(struct virtchnl2_vport_stats, rx_bytes)},
     126                 :            :         {"rx_unicast_packets", offsetof(struct virtchnl2_vport_stats, rx_unicast)},
     127                 :            :         {"rx_multicast_packets", offsetof(struct virtchnl2_vport_stats, rx_multicast)},
     128                 :            :         {"rx_broadcast_packets", offsetof(struct virtchnl2_vport_stats, rx_broadcast)},
     129                 :            :         {"rx_dropped_packets", offsetof(struct virtchnl2_vport_stats, rx_discards)},
     130                 :            :         {"rx_errors", offsetof(struct virtchnl2_vport_stats, rx_errors)},
     131                 :            :         {"rx_unknown_protocol_packets", offsetof(struct virtchnl2_vport_stats,
     132                 :            :                                                  rx_unknown_protocol)},
     133                 :            :         {"tx_bytes", offsetof(struct virtchnl2_vport_stats, tx_bytes)},
     134                 :            :         {"tx_unicast_packets", offsetof(struct virtchnl2_vport_stats, tx_unicast)},
     135                 :            :         {"tx_multicast_packets", offsetof(struct virtchnl2_vport_stats, tx_multicast)},
     136                 :            :         {"tx_broadcast_packets", offsetof(struct virtchnl2_vport_stats, tx_broadcast)},
     137                 :            :         {"tx_dropped_packets", offsetof(struct virtchnl2_vport_stats, tx_discards)},
     138                 :            :         {"tx_error_packets", offsetof(struct virtchnl2_vport_stats, tx_errors)}};
     139                 :            : 
     140                 :            : #define CPFL_NB_XSTATS                  RTE_DIM(rte_cpfl_stats_strings)
     141                 :            : 
     142                 :            : static int
     143                 :          0 : cpfl_dev_link_update(struct rte_eth_dev *dev,
     144                 :            :                      __rte_unused int wait_to_complete)
     145                 :            : {
     146                 :          0 :         struct cpfl_vport *cpfl_vport = dev->data->dev_private;
     147                 :            :         struct idpf_vport *vport = &cpfl_vport->base;
     148                 :            :         struct rte_eth_link new_link;
     149                 :            :         unsigned int i;
     150                 :            : 
     151                 :            :         memset(&new_link, 0, sizeof(new_link));
     152                 :            : 
     153         [ #  # ]:          0 :         for (i = 0; i < RTE_DIM(cpfl_supported_speeds); i++) {
     154         [ #  # ]:          0 :                 if (vport->link_speed == cpfl_supported_speeds[i]) {
     155                 :          0 :                         new_link.link_speed = vport->link_speed;
     156                 :          0 :                         break;
     157                 :            :                 }
     158                 :            :         }
     159                 :            : 
     160         [ #  # ]:          0 :         if (i == RTE_DIM(cpfl_supported_speeds)) {
     161         [ #  # ]:          0 :                 if (vport->link_up)
     162                 :          0 :                         new_link.link_speed = RTE_ETH_SPEED_NUM_UNKNOWN;
     163                 :            :                 else
     164                 :          0 :                         new_link.link_speed = RTE_ETH_SPEED_NUM_NONE;
     165                 :            :         }
     166                 :            : 
     167                 :          0 :         new_link.link_duplex = RTE_ETH_LINK_FULL_DUPLEX;
     168                 :          0 :         new_link.link_status = vport->link_up ? RTE_ETH_LINK_UP :
     169                 :            :                 RTE_ETH_LINK_DOWN;
     170                 :          0 :         new_link.link_autoneg = (dev->data->dev_conf.link_speeds & RTE_ETH_LINK_SPEED_FIXED) ?
     171         [ #  # ]:          0 :                                  RTE_ETH_LINK_FIXED : RTE_ETH_LINK_AUTONEG;
     172                 :            : 
     173                 :          0 :         return rte_eth_linkstatus_set(dev, &new_link);
     174                 :            : }
     175                 :            : 
     176                 :            : static int
     177                 :          0 : cpfl_hairpin_cap_get(struct rte_eth_dev *dev,
     178                 :            :                      struct rte_eth_hairpin_cap *cap)
     179                 :            : {
     180                 :          0 :         struct cpfl_vport *cpfl_vport = dev->data->dev_private;
     181                 :            : 
     182         [ #  # ]:          0 :         if (cpfl_vport->p2p_q_chunks_info == NULL)
     183                 :            :                 return -ENOTSUP;
     184                 :            : 
     185                 :          0 :         cap->max_nb_queues = CPFL_MAX_P2P_NB_QUEUES;
     186                 :          0 :         cap->max_rx_2_tx = CPFL_MAX_HAIRPINQ_RX_2_TX;
     187                 :          0 :         cap->max_tx_2_rx = CPFL_MAX_HAIRPINQ_TX_2_RX;
     188                 :          0 :         cap->max_nb_desc = CPFL_MAX_HAIRPINQ_NB_DESC;
     189                 :            : 
     190                 :          0 :         return 0;
     191                 :            : }
     192                 :            : 
     193                 :            : static int
     194                 :          0 : cpfl_dev_info_get(struct rte_eth_dev *dev, struct rte_eth_dev_info *dev_info)
     195                 :            : {
     196                 :          0 :         struct cpfl_vport *cpfl_vport = dev->data->dev_private;
     197                 :            :         struct idpf_vport *vport = &cpfl_vport->base;
     198                 :          0 :         struct idpf_adapter *base = vport->adapter;
     199                 :            : 
     200                 :          0 :         dev_info->max_rx_queues = base->caps.max_rx_q;
     201                 :          0 :         dev_info->max_tx_queues = base->caps.max_tx_q;
     202                 :          0 :         dev_info->min_rx_bufsize = CPFL_MIN_BUF_SIZE;
     203                 :          0 :         dev_info->max_rx_pktlen = vport->max_mtu + CPFL_ETH_OVERHEAD;
     204                 :            : 
     205                 :          0 :         dev_info->max_mtu = vport->max_mtu;
     206                 :          0 :         dev_info->min_mtu = RTE_ETHER_MIN_MTU;
     207                 :            : 
     208                 :          0 :         dev_info->hash_key_size = vport->rss_key_size;
     209                 :          0 :         dev_info->reta_size = vport->rss_lut_size;
     210                 :            : 
     211                 :          0 :         dev_info->flow_type_rss_offloads = CPFL_RSS_OFFLOAD_ALL;
     212                 :            : 
     213                 :          0 :         dev_info->rx_offload_capa =
     214                 :            :                 RTE_ETH_RX_OFFLOAD_IPV4_CKSUM           |
     215                 :            :                 RTE_ETH_RX_OFFLOAD_UDP_CKSUM            |
     216                 :            :                 RTE_ETH_RX_OFFLOAD_TCP_CKSUM            |
     217                 :            :                 RTE_ETH_RX_OFFLOAD_OUTER_IPV4_CKSUM     |
     218                 :            :                 RTE_ETH_RX_OFFLOAD_TIMESTAMP            |
     219                 :            :                 RTE_ETH_RX_OFFLOAD_SCATTER;
     220                 :            : 
     221                 :          0 :         dev_info->tx_offload_capa =
     222                 :            :                 RTE_ETH_TX_OFFLOAD_IPV4_CKSUM           |
     223                 :            :                 RTE_ETH_TX_OFFLOAD_UDP_CKSUM            |
     224                 :            :                 RTE_ETH_TX_OFFLOAD_TCP_CKSUM            |
     225                 :            :                 RTE_ETH_TX_OFFLOAD_SCTP_CKSUM           |
     226                 :            :                 RTE_ETH_TX_OFFLOAD_TCP_TSO              |
     227                 :            :                 RTE_ETH_TX_OFFLOAD_MULTI_SEGS           |
     228                 :            :                 RTE_ETH_TX_OFFLOAD_MBUF_FAST_FREE;
     229                 :            : 
     230                 :          0 :         dev_info->default_txconf = (struct rte_eth_txconf) {
     231                 :            :                 .tx_free_thresh = CPFL_DEFAULT_TX_FREE_THRESH,
     232                 :            :                 .tx_rs_thresh = CPFL_DEFAULT_TX_RS_THRESH,
     233                 :            :         };
     234                 :            : 
     235                 :          0 :         dev_info->default_rxconf = (struct rte_eth_rxconf) {
     236                 :            :                 .rx_free_thresh = CPFL_DEFAULT_RX_FREE_THRESH,
     237                 :            :         };
     238                 :            : 
     239                 :          0 :         dev_info->tx_desc_lim = (struct rte_eth_desc_lim) {
     240                 :            :                 .nb_max = CPFL_MAX_RING_DESC,
     241                 :            :                 .nb_min = CPFL_MIN_RING_DESC,
     242                 :            :                 .nb_align = CPFL_ALIGN_RING_DESC,
     243                 :            :         };
     244                 :            : 
     245                 :          0 :         dev_info->rx_desc_lim = (struct rte_eth_desc_lim) {
     246                 :            :                 .nb_max = CPFL_MAX_RING_DESC,
     247                 :            :                 .nb_min = CPFL_MIN_RING_DESC,
     248                 :            :                 .nb_align = CPFL_ALIGN_RING_DESC,
     249                 :            :         };
     250                 :            : 
     251                 :          0 :         return 0;
     252                 :            : }
     253                 :            : 
     254                 :            : static int
     255                 :          0 : cpfl_dev_mtu_set(struct rte_eth_dev *dev, uint16_t mtu)
     256                 :            : {
     257                 :          0 :         struct cpfl_vport *cpfl_vport = dev->data->dev_private;
     258                 :            :         struct idpf_vport *vport = &cpfl_vport->base;
     259                 :            : 
     260                 :            :         /* mtu setting is forbidden if port is start */
     261         [ #  # ]:          0 :         if (dev->data->dev_started) {
     262                 :          0 :                 PMD_DRV_LOG(ERR, "port must be stopped before configuration");
     263                 :          0 :                 return -EBUSY;
     264                 :            :         }
     265                 :            : 
     266         [ #  # ]:          0 :         if (mtu > vport->max_mtu) {
     267                 :          0 :                 PMD_DRV_LOG(ERR, "MTU should be less than %d", vport->max_mtu);
     268                 :          0 :                 return -EINVAL;
     269                 :            :         }
     270                 :            : 
     271                 :          0 :         vport->max_pkt_len = mtu + CPFL_ETH_OVERHEAD;
     272                 :            : 
     273                 :          0 :         return 0;
     274                 :            : }
     275                 :            : 
     276                 :            : static const uint32_t *
     277                 :          0 : cpfl_dev_supported_ptypes_get(struct rte_eth_dev *dev __rte_unused,
     278                 :            :                               size_t *no_of_elements)
     279                 :            : {
     280                 :            :         static const uint32_t ptypes[] = {
     281                 :            :                 RTE_PTYPE_L2_ETHER,
     282                 :            :                 RTE_PTYPE_L3_IPV4_EXT_UNKNOWN,
     283                 :            :                 RTE_PTYPE_L3_IPV6_EXT_UNKNOWN,
     284                 :            :                 RTE_PTYPE_L4_FRAG,
     285                 :            :                 RTE_PTYPE_L4_UDP,
     286                 :            :                 RTE_PTYPE_L4_TCP,
     287                 :            :                 RTE_PTYPE_L4_SCTP,
     288                 :            :                 RTE_PTYPE_L4_ICMP,
     289                 :            :         };
     290                 :            : 
     291                 :          0 :         *no_of_elements = RTE_DIM(ptypes);
     292                 :          0 :         return ptypes;
     293                 :            : }
     294                 :            : 
     295                 :            : static uint64_t
     296                 :          0 : cpfl_get_mbuf_alloc_failed_stats(struct rte_eth_dev *dev)
     297                 :            : {
     298                 :            :         uint64_t mbuf_alloc_failed = 0;
     299                 :            :         struct cpfl_rx_queue *cpfl_rxq;
     300                 :            :         int i = 0;
     301                 :            : 
     302         [ #  # ]:          0 :         for (i = 0; i < dev->data->nb_rx_queues; i++) {
     303                 :          0 :                 cpfl_rxq = dev->data->rx_queues[i];
     304                 :          0 :                 mbuf_alloc_failed +=
     305                 :          0 :                         rte_atomic_load_explicit(&cpfl_rxq->base.rx_stats.mbuf_alloc_failed,
     306                 :            :                                                  rte_memory_order_relaxed);
     307                 :            :         }
     308                 :            : 
     309                 :          0 :         return mbuf_alloc_failed;
     310                 :            : }
     311                 :            : 
     312                 :            : static int
     313                 :          0 : cpfl_dev_stats_get(struct rte_eth_dev *dev, struct rte_eth_stats *stats)
     314                 :            : {
     315                 :          0 :         struct cpfl_vport *cpfl_vport = dev->data->dev_private;
     316                 :          0 :         struct idpf_vport *vport = &cpfl_vport->base;
     317                 :          0 :         struct virtchnl2_vport_stats *pstats = NULL;
     318                 :            :         int ret;
     319                 :            : 
     320                 :          0 :         ret = idpf_vc_stats_query(vport, &pstats);
     321         [ #  # ]:          0 :         if (ret == 0) {
     322         [ #  # ]:          0 :                 uint8_t crc_stats_len = (dev->data->dev_conf.rxmode.offloads &
     323                 :            :                                          RTE_ETH_RX_OFFLOAD_KEEP_CRC) ? 0 :
     324                 :            :                                          RTE_ETHER_CRC_LEN;
     325                 :            : 
     326                 :          0 :                 idpf_vport_stats_update(&vport->eth_stats_offset, pstats);
     327                 :          0 :                 stats->ipackets = pstats->rx_unicast + pstats->rx_multicast +
     328                 :          0 :                                   pstats->rx_broadcast;
     329                 :          0 :                 stats->opackets = pstats->tx_broadcast + pstats->tx_multicast +
     330                 :          0 :                                                 pstats->tx_unicast;
     331                 :          0 :                 stats->imissed = pstats->rx_discards;
     332                 :          0 :                 stats->ierrors = pstats->rx_errors;
     333                 :          0 :                 stats->oerrors = pstats->tx_errors + pstats->tx_discards;
     334                 :          0 :                 stats->ibytes = pstats->rx_bytes;
     335                 :          0 :                 stats->ibytes -= stats->ipackets * crc_stats_len;
     336                 :          0 :                 stats->obytes = pstats->tx_bytes;
     337                 :            : 
     338                 :          0 :                 dev->data->rx_mbuf_alloc_failed = cpfl_get_mbuf_alloc_failed_stats(dev);
     339                 :          0 :                 stats->rx_nombuf = dev->data->rx_mbuf_alloc_failed;
     340                 :            :         } else {
     341                 :          0 :                 PMD_DRV_LOG(ERR, "Get statistics failed");
     342                 :            :         }
     343                 :          0 :         return ret;
     344                 :            : }
     345                 :            : 
     346                 :            : static void
     347                 :          0 : cpfl_reset_mbuf_alloc_failed_stats(struct rte_eth_dev *dev)
     348                 :            : {
     349                 :            :         struct cpfl_rx_queue *cpfl_rxq;
     350                 :            :         int i;
     351                 :            : 
     352         [ #  # ]:          0 :         for (i = 0; i < dev->data->nb_rx_queues; i++) {
     353                 :          0 :                 cpfl_rxq = dev->data->rx_queues[i];
     354                 :          0 :                 rte_atomic_store_explicit(&cpfl_rxq->base.rx_stats.mbuf_alloc_failed, 0,
     355                 :            :                                           rte_memory_order_relaxed);
     356                 :            :         }
     357                 :          0 : }
     358                 :            : 
     359                 :            : static int
     360                 :          0 : cpfl_dev_stats_reset(struct rte_eth_dev *dev)
     361                 :            : {
     362                 :          0 :         struct cpfl_vport *cpfl_vport = dev->data->dev_private;
     363                 :          0 :         struct idpf_vport *vport = &cpfl_vport->base;
     364                 :          0 :         struct virtchnl2_vport_stats *pstats = NULL;
     365                 :            :         int ret;
     366                 :            : 
     367                 :          0 :         ret = idpf_vc_stats_query(vport, &pstats);
     368         [ #  # ]:          0 :         if (ret != 0)
     369                 :            :                 return ret;
     370                 :            : 
     371                 :            :         /* set stats offset base on current values */
     372                 :          0 :         vport->eth_stats_offset = *pstats;
     373                 :            : 
     374                 :          0 :         cpfl_reset_mbuf_alloc_failed_stats(dev);
     375                 :            : 
     376                 :          0 :         return 0;
     377                 :            : }
     378                 :            : 
     379                 :          0 : static int cpfl_dev_xstats_reset(struct rte_eth_dev *dev)
     380                 :            : {
     381                 :          0 :         cpfl_dev_stats_reset(dev);
     382                 :          0 :         return 0;
     383                 :            : }
     384                 :            : 
     385                 :          0 : static int cpfl_dev_xstats_get(struct rte_eth_dev *dev,
     386                 :            :                                struct rte_eth_xstat *xstats, unsigned int n)
     387                 :            : {
     388                 :          0 :         struct cpfl_vport *cpfl_vport = dev->data->dev_private;
     389                 :          0 :         struct idpf_vport *vport = &cpfl_vport->base;
     390                 :          0 :         struct virtchnl2_vport_stats *pstats = NULL;
     391                 :            :         unsigned int i;
     392                 :            :         int ret;
     393                 :            : 
     394         [ #  # ]:          0 :         if (n < CPFL_NB_XSTATS)
     395                 :            :                 return CPFL_NB_XSTATS;
     396                 :            : 
     397         [ #  # ]:          0 :         if (!xstats)
     398                 :            :                 return CPFL_NB_XSTATS;
     399                 :            : 
     400                 :          0 :         ret = idpf_vc_stats_query(vport, &pstats);
     401         [ #  # ]:          0 :         if (ret) {
     402                 :          0 :                 PMD_DRV_LOG(ERR, "Get statistics failed");
     403                 :          0 :                 return 0;
     404                 :            :         }
     405                 :            : 
     406                 :          0 :         idpf_vport_stats_update(&vport->eth_stats_offset, pstats);
     407                 :            : 
     408                 :            :         /* loop over xstats array and values from pstats */
     409         [ #  # ]:          0 :         for (i = 0; i < CPFL_NB_XSTATS; i++) {
     410                 :          0 :                 xstats[i].id = i;
     411                 :          0 :                 xstats[i].value = *(uint64_t *)(((char *)pstats) +
     412                 :          0 :                         rte_cpfl_stats_strings[i].offset);
     413                 :            :         }
     414                 :            :         return CPFL_NB_XSTATS;
     415                 :            : }
     416                 :            : 
     417                 :          0 : static int cpfl_dev_xstats_get_names(__rte_unused struct rte_eth_dev *dev,
     418                 :            :                                      struct rte_eth_xstat_name *xstats_names,
     419                 :            :                                      __rte_unused unsigned int limit)
     420                 :            : {
     421                 :            :         unsigned int i;
     422                 :            : 
     423         [ #  # ]:          0 :         if (xstats_names) {
     424         [ #  # ]:          0 :                 for (i = 0; i < CPFL_NB_XSTATS; i++) {
     425                 :          0 :                         snprintf(xstats_names[i].name,
     426                 :            :                                  sizeof(xstats_names[i].name),
     427                 :          0 :                                  "%s", rte_cpfl_stats_strings[i].name);
     428                 :            :                 }
     429                 :            :         }
     430                 :          0 :         return CPFL_NB_XSTATS;
     431                 :            : }
     432                 :            : 
     433                 :          0 : static int cpfl_config_rss_hf(struct idpf_vport *vport, uint64_t rss_hf)
     434                 :            : {
     435                 :            :         uint64_t hena = 0;
     436                 :            :         uint16_t i;
     437                 :            : 
     438                 :            :         /**
     439                 :            :          * RTE_ETH_RSS_IPV4 and RTE_ETH_RSS_IPV6 can be considered as 2
     440                 :            :          * generalizations of all other IPv4 and IPv6 RSS types.
     441                 :            :          */
     442         [ #  # ]:          0 :         if (rss_hf & RTE_ETH_RSS_IPV4)
     443                 :          0 :                 rss_hf |= cpfl_ipv4_rss;
     444                 :            : 
     445         [ #  # ]:          0 :         if (rss_hf & RTE_ETH_RSS_IPV6)
     446                 :          0 :                 rss_hf |= cpfl_ipv6_rss;
     447                 :            : 
     448         [ #  # ]:          0 :         for (i = 0; i < RTE_DIM(cpfl_map_hena_rss); i++) {
     449         [ #  # ]:          0 :                 if (cpfl_map_hena_rss[i] & rss_hf)
     450                 :          0 :                         hena |= BIT_ULL(i);
     451                 :            :         }
     452                 :            : 
     453                 :            :         /**
     454                 :            :          * At present, cp doesn't process the virtual channel msg of rss_hf configuration,
     455                 :            :          * tips are given below.
     456                 :            :          */
     457         [ #  # ]:          0 :         if (hena != vport->rss_hf)
     458                 :          0 :                 PMD_DRV_LOG(WARNING, "Updating RSS Hash Function is not supported at present.");
     459                 :            : 
     460                 :          0 :         return 0;
     461                 :            : }
     462                 :            : 
     463                 :            : static int
     464                 :          0 : cpfl_init_rss(struct idpf_vport *vport)
     465                 :            : {
     466                 :            :         struct rte_eth_rss_conf *rss_conf;
     467                 :            :         struct rte_eth_dev_data *dev_data;
     468                 :            :         uint16_t i, nb_q;
     469                 :            :         int ret = 0;
     470                 :            : 
     471                 :          0 :         dev_data = vport->dev_data;
     472                 :            :         rss_conf = &dev_data->dev_conf.rx_adv_conf.rss_conf;
     473                 :          0 :         nb_q = dev_data->nb_rx_queues;
     474                 :            : 
     475         [ #  # ]:          0 :         if (rss_conf->rss_key == NULL) {
     476         [ #  # ]:          0 :                 for (i = 0; i < vport->rss_key_size; i++)
     477                 :          0 :                         vport->rss_key[i] = (uint8_t)rte_rand();
     478         [ #  # ]:          0 :         } else if (rss_conf->rss_key_len != vport->rss_key_size) {
     479                 :          0 :                 PMD_INIT_LOG(ERR, "Invalid RSS key length in RSS configuration, should be %d",
     480                 :            :                              vport->rss_key_size);
     481                 :          0 :                 return -EINVAL;
     482                 :            :         } else {
     483                 :          0 :                 memcpy(vport->rss_key, rss_conf->rss_key,
     484                 :            :                            vport->rss_key_size);
     485                 :            :         }
     486                 :            : 
     487         [ #  # ]:          0 :         for (i = 0; i < vport->rss_lut_size; i++)
     488                 :          0 :                 vport->rss_lut[i] = i % nb_q;
     489                 :            : 
     490                 :          0 :         vport->rss_hf = IDPF_DEFAULT_RSS_HASH_EXPANDED;
     491                 :            : 
     492                 :          0 :         ret = idpf_vport_rss_config(vport);
     493         [ #  # ]:          0 :         if (ret != 0)
     494                 :          0 :                 PMD_INIT_LOG(ERR, "Failed to configure RSS");
     495                 :            : 
     496                 :            :         return ret;
     497                 :            : }
     498                 :            : 
     499                 :            : static int
     500                 :          0 : cpfl_rss_reta_update(struct rte_eth_dev *dev,
     501                 :            :                      struct rte_eth_rss_reta_entry64 *reta_conf,
     502                 :            :                      uint16_t reta_size)
     503                 :            : {
     504                 :          0 :         struct cpfl_vport *cpfl_vport = dev->data->dev_private;
     505                 :          0 :         struct idpf_vport *vport = &cpfl_vport->base;
     506                 :          0 :         struct idpf_adapter *base = vport->adapter;
     507                 :            :         uint16_t idx, shift;
     508                 :            :         int ret = 0;
     509                 :            :         uint16_t i;
     510                 :            : 
     511   [ #  #  #  # ]:          0 :         if (base->caps.rss_caps == 0 || dev->data->nb_rx_queues == 0) {
     512                 :          0 :                 PMD_DRV_LOG(DEBUG, "RSS is not supported");
     513                 :          0 :                 return -ENOTSUP;
     514                 :            :         }
     515                 :            : 
     516         [ #  # ]:          0 :         if (reta_size != vport->rss_lut_size) {
     517                 :          0 :                 PMD_DRV_LOG(ERR, "The size of hash lookup table configured "
     518                 :            :                                  "(%d) doesn't match the number of hardware can "
     519                 :            :                                  "support (%d)",
     520                 :            :                             reta_size, vport->rss_lut_size);
     521                 :          0 :                 return -EINVAL;
     522                 :            :         }
     523                 :            : 
     524         [ #  # ]:          0 :         for (i = 0; i < reta_size; i++) {
     525                 :          0 :                 idx = i / RTE_ETH_RETA_GROUP_SIZE;
     526                 :          0 :                 shift = i % RTE_ETH_RETA_GROUP_SIZE;
     527         [ #  # ]:          0 :                 if (reta_conf[idx].mask & (1ULL << shift))
     528                 :          0 :                         vport->rss_lut[i] = reta_conf[idx].reta[shift];
     529                 :            :         }
     530                 :            : 
     531                 :            :         /* send virtchnl ops to configure RSS */
     532                 :          0 :         ret = idpf_vc_rss_lut_set(vport);
     533         [ #  # ]:          0 :         if (ret)
     534                 :          0 :                 PMD_INIT_LOG(ERR, "Failed to configure RSS lut");
     535                 :            : 
     536                 :            :         return ret;
     537                 :            : }
     538                 :            : 
     539                 :            : static int
     540                 :          0 : cpfl_rss_reta_query(struct rte_eth_dev *dev,
     541                 :            :                     struct rte_eth_rss_reta_entry64 *reta_conf,
     542                 :            :                     uint16_t reta_size)
     543                 :            : {
     544                 :          0 :         struct cpfl_vport *cpfl_vport = dev->data->dev_private;
     545                 :          0 :         struct idpf_vport *vport = &cpfl_vport->base;
     546                 :          0 :         struct idpf_adapter *base = vport->adapter;
     547                 :            :         uint16_t idx, shift;
     548                 :            :         int ret = 0;
     549                 :            :         uint16_t i;
     550                 :            : 
     551   [ #  #  #  # ]:          0 :         if (base->caps.rss_caps == 0 || dev->data->nb_rx_queues == 0) {
     552                 :          0 :                 PMD_DRV_LOG(DEBUG, "RSS is not supported");
     553                 :          0 :                 return -ENOTSUP;
     554                 :            :         }
     555                 :            : 
     556         [ #  # ]:          0 :         if (reta_size != vport->rss_lut_size) {
     557                 :          0 :                 PMD_DRV_LOG(ERR, "The size of hash lookup table configured "
     558                 :            :                         "(%d) doesn't match the number of hardware can "
     559                 :            :                         "support (%d)", reta_size, vport->rss_lut_size);
     560                 :          0 :                 return -EINVAL;
     561                 :            :         }
     562                 :            : 
     563                 :          0 :         ret = idpf_vc_rss_lut_get(vport);
     564         [ #  # ]:          0 :         if (ret) {
     565                 :          0 :                 PMD_DRV_LOG(ERR, "Failed to get RSS LUT");
     566                 :          0 :                 return ret;
     567                 :            :         }
     568                 :            : 
     569         [ #  # ]:          0 :         for (i = 0; i < reta_size; i++) {
     570                 :          0 :                 idx = i / RTE_ETH_RETA_GROUP_SIZE;
     571                 :          0 :                 shift = i % RTE_ETH_RETA_GROUP_SIZE;
     572         [ #  # ]:          0 :                 if (reta_conf[idx].mask & (1ULL << shift))
     573                 :          0 :                         reta_conf[idx].reta[shift] = vport->rss_lut[i];
     574                 :            :         }
     575                 :            : 
     576                 :            :         return 0;
     577                 :            : }
     578                 :            : 
     579                 :            : static int
     580                 :          0 : cpfl_rss_hash_update(struct rte_eth_dev *dev,
     581                 :            :                      struct rte_eth_rss_conf *rss_conf)
     582                 :            : {
     583                 :          0 :         struct cpfl_vport *cpfl_vport = dev->data->dev_private;
     584                 :          0 :         struct idpf_vport *vport = &cpfl_vport->base;
     585                 :          0 :         struct idpf_adapter *base = vport->adapter;
     586                 :            :         int ret = 0;
     587                 :            : 
     588   [ #  #  #  # ]:          0 :         if (base->caps.rss_caps == 0 || dev->data->nb_rx_queues == 0) {
     589                 :          0 :                 PMD_DRV_LOG(DEBUG, "RSS is not supported");
     590                 :          0 :                 return -ENOTSUP;
     591                 :            :         }
     592                 :            : 
     593   [ #  #  #  # ]:          0 :         if (!rss_conf->rss_key || rss_conf->rss_key_len == 0) {
     594                 :          0 :                 PMD_DRV_LOG(DEBUG, "No key to be configured");
     595                 :          0 :                 goto skip_rss_key;
     596         [ #  # ]:          0 :         } else if (rss_conf->rss_key_len != vport->rss_key_size) {
     597                 :          0 :                 PMD_DRV_LOG(ERR, "The size of hash key configured "
     598                 :            :                                  "(%d) doesn't match the size of hardware can "
     599                 :            :                                  "support (%d)",
     600                 :            :                             rss_conf->rss_key_len,
     601                 :            :                             vport->rss_key_size);
     602                 :          0 :                 return -EINVAL;
     603                 :            :         }
     604                 :            : 
     605                 :          0 :         memcpy(vport->rss_key, rss_conf->rss_key,
     606                 :            :                    vport->rss_key_size);
     607                 :          0 :         ret = idpf_vc_rss_key_set(vport);
     608         [ #  # ]:          0 :         if (ret != 0) {
     609                 :          0 :                 PMD_INIT_LOG(ERR, "Failed to configure RSS key");
     610                 :          0 :                 return ret;
     611                 :            :         }
     612                 :            : 
     613                 :          0 : skip_rss_key:
     614                 :          0 :         ret = cpfl_config_rss_hf(vport, rss_conf->rss_hf);
     615         [ #  # ]:          0 :         if (ret != 0) {
     616                 :          0 :                 PMD_INIT_LOG(ERR, "Failed to configure RSS hash");
     617                 :          0 :                 return ret;
     618                 :            :         }
     619                 :            : 
     620                 :            :         return 0;
     621                 :            : }
     622                 :            : 
     623                 :            : static uint64_t
     624                 :          0 : cpfl_map_general_rss_hf(uint64_t config_rss_hf, uint64_t last_general_rss_hf)
     625                 :            : {
     626                 :            :         uint64_t valid_rss_hf = 0;
     627                 :            :         uint16_t i;
     628                 :            : 
     629         [ #  # ]:          0 :         for (i = 0; i < RTE_DIM(cpfl_map_hena_rss); i++) {
     630                 :          0 :                 uint64_t bit = BIT_ULL(i);
     631                 :            : 
     632         [ #  # ]:          0 :                 if (bit & config_rss_hf)
     633                 :          0 :                         valid_rss_hf |= cpfl_map_hena_rss[i];
     634                 :            :         }
     635                 :            : 
     636         [ #  # ]:          0 :         if (valid_rss_hf & cpfl_ipv4_rss)
     637                 :          0 :                 valid_rss_hf |= last_general_rss_hf & RTE_ETH_RSS_IPV4;
     638                 :            : 
     639         [ #  # ]:          0 :         if (valid_rss_hf & cpfl_ipv6_rss)
     640                 :          0 :                 valid_rss_hf |= last_general_rss_hf & RTE_ETH_RSS_IPV6;
     641                 :            : 
     642                 :          0 :         return valid_rss_hf;
     643                 :            : }
     644                 :            : 
     645                 :            : static int
     646                 :          0 : cpfl_rss_hash_conf_get(struct rte_eth_dev *dev,
     647                 :            :                        struct rte_eth_rss_conf *rss_conf)
     648                 :            : {
     649                 :          0 :         struct cpfl_vport *cpfl_vport = dev->data->dev_private;
     650                 :          0 :         struct idpf_vport *vport = &cpfl_vport->base;
     651                 :          0 :         struct idpf_adapter *base = vport->adapter;
     652                 :            :         int ret = 0;
     653                 :            : 
     654   [ #  #  #  # ]:          0 :         if (base->caps.rss_caps == 0 || dev->data->nb_rx_queues == 0) {
     655                 :          0 :                 PMD_DRV_LOG(DEBUG, "RSS is not supported");
     656                 :          0 :                 return -ENOTSUP;
     657                 :            :         }
     658                 :            : 
     659                 :          0 :         ret = idpf_vc_rss_hash_get(vport);
     660         [ #  # ]:          0 :         if (ret) {
     661                 :          0 :                 PMD_DRV_LOG(ERR, "Failed to get RSS hf");
     662                 :          0 :                 return ret;
     663                 :            :         }
     664                 :            : 
     665                 :          0 :         rss_conf->rss_hf = cpfl_map_general_rss_hf(vport->rss_hf, vport->last_general_rss_hf);
     666                 :            : 
     667         [ #  # ]:          0 :         if (!rss_conf->rss_key)
     668                 :            :                 return 0;
     669                 :            : 
     670                 :          0 :         ret = idpf_vc_rss_key_get(vport);
     671         [ #  # ]:          0 :         if (ret) {
     672                 :          0 :                 PMD_DRV_LOG(ERR, "Failed to get RSS key");
     673                 :          0 :                 return ret;
     674                 :            :         }
     675                 :            : 
     676         [ #  # ]:          0 :         if (rss_conf->rss_key_len > vport->rss_key_size)
     677                 :          0 :                 rss_conf->rss_key_len = vport->rss_key_size;
     678                 :            : 
     679                 :          0 :         memcpy(rss_conf->rss_key, vport->rss_key, rss_conf->rss_key_len);
     680                 :            : 
     681                 :          0 :         return 0;
     682                 :            : }
     683                 :            : 
     684                 :            : static int
     685                 :          0 : cpfl_dev_configure(struct rte_eth_dev *dev)
     686                 :            : {
     687                 :          0 :         struct cpfl_vport *cpfl_vport = dev->data->dev_private;
     688                 :          0 :         struct idpf_vport *vport = &cpfl_vport->base;
     689                 :            :         struct rte_eth_conf *conf = &dev->data->dev_conf;
     690                 :          0 :         struct idpf_adapter *base = vport->adapter;
     691                 :            :         int ret;
     692                 :            : 
     693         [ #  # ]:          0 :         if (conf->link_speeds & RTE_ETH_LINK_SPEED_FIXED) {
     694                 :          0 :                 PMD_INIT_LOG(ERR, "Setting link speed is not supported");
     695                 :          0 :                 return -ENOTSUP;
     696                 :            :         }
     697                 :            : 
     698         [ #  # ]:          0 :         if (conf->txmode.mq_mode != RTE_ETH_MQ_TX_NONE) {
     699                 :          0 :                 PMD_INIT_LOG(ERR, "Multi-queue TX mode %d is not supported",
     700                 :            :                              conf->txmode.mq_mode);
     701                 :          0 :                 return -ENOTSUP;
     702                 :            :         }
     703                 :            : 
     704         [ #  # ]:          0 :         if (conf->lpbk_mode != 0) {
     705                 :          0 :                 PMD_INIT_LOG(ERR, "Loopback operation mode %d is not supported",
     706                 :            :                              conf->lpbk_mode);
     707                 :          0 :                 return -ENOTSUP;
     708                 :            :         }
     709                 :            : 
     710         [ #  # ]:          0 :         if (conf->dcb_capability_en != 0) {
     711                 :          0 :                 PMD_INIT_LOG(ERR, "Priority Flow Control(PFC) if not supported");
     712                 :          0 :                 return -ENOTSUP;
     713                 :            :         }
     714                 :            : 
     715         [ #  # ]:          0 :         if (conf->intr_conf.lsc != 0) {
     716                 :          0 :                 PMD_INIT_LOG(ERR, "LSC interrupt is not supported");
     717                 :          0 :                 return -ENOTSUP;
     718                 :            :         }
     719                 :            : 
     720         [ #  # ]:          0 :         if (conf->intr_conf.rxq != 0) {
     721                 :          0 :                 PMD_INIT_LOG(ERR, "RXQ interrupt is not supported");
     722                 :          0 :                 return -ENOTSUP;
     723                 :            :         }
     724                 :            : 
     725         [ #  # ]:          0 :         if (conf->intr_conf.rmv != 0) {
     726                 :          0 :                 PMD_INIT_LOG(ERR, "RMV interrupt is not supported");
     727                 :          0 :                 return -ENOTSUP;
     728                 :            :         }
     729                 :            : 
     730         [ #  # ]:          0 :         if (conf->rxmode.mq_mode != RTE_ETH_MQ_RX_RSS &&
     731                 :            :             conf->rxmode.mq_mode != RTE_ETH_MQ_RX_NONE) {
     732                 :          0 :                 PMD_INIT_LOG(ERR, "RX mode %d is not supported.",
     733                 :            :                              conf->rxmode.mq_mode);
     734                 :          0 :                 return -EINVAL;
     735                 :            :         }
     736                 :            : 
     737   [ #  #  #  # ]:          0 :         if (base->caps.rss_caps != 0 && dev->data->nb_rx_queues != 0) {
     738                 :          0 :                 ret = cpfl_init_rss(vport);
     739         [ #  # ]:          0 :                 if (ret != 0) {
     740                 :          0 :                         PMD_INIT_LOG(ERR, "Failed to init rss");
     741                 :          0 :                         return ret;
     742                 :            :                 }
     743         [ #  # ]:          0 :         } else if (conf->rxmode.mq_mode == RTE_ETH_MQ_RX_RSS) {
     744                 :          0 :                 PMD_INIT_LOG(ERR, "RSS is not supported.");
     745                 :          0 :                 return -ENOTSUP;
     746                 :            :         }
     747                 :            : 
     748                 :          0 :         vport->max_pkt_len =
     749         [ #  # ]:          0 :                 (dev->data->mtu == 0) ? CPFL_DEFAULT_MTU : dev->data->mtu +
     750                 :            :                 CPFL_ETH_OVERHEAD;
     751                 :            : 
     752                 :          0 :         return 0;
     753                 :            : }
     754                 :            : 
     755                 :            : static int
     756                 :          0 : cpfl_config_rx_queues_irqs(struct rte_eth_dev *dev)
     757                 :            : {
     758                 :          0 :         uint32_t qids[CPFL_MAX_P2P_NB_QUEUES + IDPF_DEFAULT_RXQ_NUM] = {0};
     759                 :          0 :         struct cpfl_vport *cpfl_vport = dev->data->dev_private;
     760                 :          0 :         struct idpf_vport *vport = &cpfl_vport->base;
     761                 :          0 :         uint16_t nb_rx_queues = dev->data->nb_rx_queues;
     762                 :            :         struct cpfl_rx_queue *cpfl_rxq;
     763                 :            :         int i;
     764                 :            : 
     765         [ #  # ]:          0 :         for (i = 0; i < nb_rx_queues; i++) {
     766                 :          0 :                 cpfl_rxq = dev->data->rx_queues[i];
     767         [ #  # ]:          0 :                 if (cpfl_rxq->hairpin_info.hairpin_q)
     768                 :          0 :                         qids[i] = cpfl_hw_qid_get(cpfl_vport->p2p_q_chunks_info->rx_start_qid,
     769                 :          0 :                                                   (i - cpfl_vport->nb_data_rxq));
     770                 :            :                 else
     771                 :          0 :                         qids[i] = cpfl_hw_qid_get(vport->chunks_info.rx_start_qid, i);
     772                 :            :         }
     773                 :          0 :         return idpf_vport_irq_map_config_by_qids(vport, qids, nb_rx_queues);
     774                 :            : }
     775                 :            : 
     776                 :            : /* Update hairpin_info for dev's tx hairpin queue */
     777                 :            : static int
     778                 :          0 : cpfl_txq_hairpin_info_update(struct rte_eth_dev *dev, uint16_t rx_port)
     779                 :            : {
     780                 :          0 :         struct cpfl_vport *cpfl_tx_vport = dev->data->dev_private;
     781                 :          0 :         struct rte_eth_dev *peer_dev = &rte_eth_devices[rx_port];
     782                 :          0 :         struct cpfl_vport *cpfl_rx_vport = peer_dev->data->dev_private;
     783                 :            :         struct cpfl_txq_hairpin_info *hairpin_info;
     784                 :            :         struct cpfl_tx_queue *cpfl_txq;
     785                 :            :         int i;
     786                 :            : 
     787         [ #  # ]:          0 :         for (i = cpfl_tx_vport->nb_data_txq; i < dev->data->nb_tx_queues; i++) {
     788                 :          0 :                 cpfl_txq = dev->data->tx_queues[i];
     789                 :            :                 hairpin_info = &cpfl_txq->hairpin_info;
     790         [ #  # ]:          0 :                 if (hairpin_info->peer_rxp != rx_port) {
     791                 :          0 :                         PMD_DRV_LOG(ERR, "port %d is not the peer port", rx_port);
     792                 :          0 :                         return -EINVAL;
     793                 :            :                 }
     794                 :          0 :                 hairpin_info->peer_rxq_id =
     795                 :          0 :                         cpfl_hw_qid_get(cpfl_rx_vport->p2p_q_chunks_info->rx_start_qid,
     796                 :          0 :                                         hairpin_info->peer_rxq_id - cpfl_rx_vport->nb_data_rxq);
     797                 :            :         }
     798                 :            : 
     799                 :            :         return 0;
     800                 :            : }
     801                 :            : 
     802                 :            : /* Bind Rx hairpin queue's memory zone to peer Tx hairpin queue's memory zone */
     803                 :            : static void
     804                 :          0 : cpfl_rxq_hairpin_mz_bind(struct rte_eth_dev *dev)
     805                 :            : {
     806                 :          0 :         struct cpfl_vport *cpfl_rx_vport = dev->data->dev_private;
     807                 :            :         struct idpf_vport *vport = &cpfl_rx_vport->base;
     808                 :          0 :         struct idpf_adapter *adapter = vport->adapter;
     809                 :            :         struct idpf_hw *hw = &adapter->hw;
     810                 :            :         struct cpfl_rx_queue *cpfl_rxq;
     811                 :            :         struct cpfl_tx_queue *cpfl_txq;
     812                 :            :         struct rte_eth_dev *peer_dev;
     813                 :            :         const struct rte_memzone *mz;
     814                 :            :         uint16_t peer_tx_port;
     815                 :            :         uint16_t peer_tx_qid;
     816                 :            :         int i;
     817                 :            : 
     818         [ #  # ]:          0 :         for (i = cpfl_rx_vport->nb_data_rxq; i < dev->data->nb_rx_queues; i++) {
     819                 :          0 :                 cpfl_rxq = dev->data->rx_queues[i];
     820                 :          0 :                 peer_tx_port = cpfl_rxq->hairpin_info.peer_txp;
     821                 :          0 :                 peer_tx_qid = cpfl_rxq->hairpin_info.peer_txq_id;
     822                 :          0 :                 peer_dev = &rte_eth_devices[peer_tx_port];
     823                 :          0 :                 cpfl_txq = peer_dev->data->tx_queues[peer_tx_qid];
     824                 :            : 
     825                 :            :                 /* bind rx queue */
     826                 :          0 :                 mz = cpfl_txq->base.mz;
     827                 :          0 :                 cpfl_rxq->base.rx_ring_phys_addr = mz->iova;
     828                 :          0 :                 cpfl_rxq->base.rx_ring = mz->addr;
     829                 :          0 :                 cpfl_rxq->base.mz = mz;
     830                 :            : 
     831                 :            :                 /* bind rx buffer queue */
     832                 :          0 :                 mz = cpfl_txq->base.complq->mz;
     833                 :          0 :                 cpfl_rxq->base.bufq1->rx_ring_phys_addr = mz->iova;
     834                 :          0 :                 cpfl_rxq->base.bufq1->rx_ring = mz->addr;
     835                 :          0 :                 cpfl_rxq->base.bufq1->mz = mz;
     836                 :          0 :                 cpfl_rxq->base.bufq1->qrx_tail = hw->hw_addr +
     837                 :          0 :                         cpfl_hw_qtail_get(cpfl_rx_vport->p2p_q_chunks_info->rx_buf_qtail_start,
     838                 :          0 :                                         0, cpfl_rx_vport->p2p_q_chunks_info->rx_buf_qtail_spacing);
     839                 :            :         }
     840                 :          0 : }
     841                 :            : 
     842                 :            : static int
     843                 :          0 : cpfl_rss_lut_config(struct cpfl_vport *cpfl_vport, uint16_t nb_q)
     844                 :            : {
     845                 :          0 :         struct idpf_vport *vport = &cpfl_vport->base;
     846                 :          0 :         uint16_t lut_size = vport->rss_lut_size;
     847                 :            :         uint16_t i;
     848                 :            :         int ret;
     849                 :            : 
     850         [ #  # ]:          0 :         for (i = 0; i < lut_size; i++)
     851                 :          0 :                 vport->rss_lut[i] = i % nb_q;
     852                 :            : 
     853                 :          0 :         ret = idpf_vc_rss_lut_set(vport);
     854         [ #  # ]:          0 :         if (ret)
     855                 :          0 :                 PMD_INIT_LOG(ERR, "Failed to configure RSS lut");
     856                 :            : 
     857                 :          0 :         return ret;
     858                 :            : }
     859                 :            : 
     860                 :            : static int
     861                 :          0 : cpfl_start_queues(struct rte_eth_dev *dev)
     862                 :            : {
     863                 :          0 :         struct cpfl_vport *cpfl_vport = dev->data->dev_private;
     864                 :          0 :         struct idpf_vport *vport = &cpfl_vport->base;
     865                 :            :         struct cpfl_rx_queue *cpfl_rxq;
     866                 :            :         struct cpfl_tx_queue *cpfl_txq;
     867                 :            :         int update_flag = 0;
     868                 :            :         int err = 0;
     869                 :            :         int i;
     870                 :            : 
     871                 :            :         /* For normal data queues, configure, init and enale Txq.
     872                 :            :          * For non-manual bind hairpin queues, configure Txq.
     873                 :            :          */
     874         [ #  # ]:          0 :         for (i = 0; i < dev->data->nb_tx_queues; i++) {
     875                 :          0 :                 cpfl_txq = dev->data->tx_queues[i];
     876   [ #  #  #  # ]:          0 :                 if (cpfl_txq == NULL || cpfl_txq->base.tx_deferred_start)
     877                 :          0 :                         continue;
     878         [ #  # ]:          0 :                 if (!cpfl_txq->hairpin_info.hairpin_q) {
     879                 :          0 :                         err = cpfl_tx_queue_start(dev, i);
     880         [ #  # ]:          0 :                         if (err != 0) {
     881                 :          0 :                                 PMD_DRV_LOG(ERR, "Fail to start Tx queue %u", i);
     882                 :          0 :                                 return err;
     883                 :            :                         }
     884         [ #  # ]:          0 :                 } else if (!cpfl_vport->p2p_manual_bind) {
     885         [ #  # ]:          0 :                         if (update_flag == 0) {
     886                 :          0 :                                 err = cpfl_txq_hairpin_info_update(dev,
     887                 :          0 :                                                                    cpfl_txq->hairpin_info.peer_rxp);
     888         [ #  # ]:          0 :                                 if (err != 0) {
     889                 :          0 :                                         PMD_DRV_LOG(ERR, "Fail to update Tx hairpin queue info");
     890                 :          0 :                                         return err;
     891                 :            :                                 }
     892                 :            :                                 update_flag = 1;
     893                 :            :                         }
     894                 :          0 :                         err = cpfl_hairpin_txq_config(vport, cpfl_txq);
     895         [ #  # ]:          0 :                         if (err != 0) {
     896                 :          0 :                                 PMD_DRV_LOG(ERR, "Fail to configure hairpin Tx queue %u", i);
     897                 :          0 :                                 return err;
     898                 :            :                         }
     899                 :            :                 }
     900                 :            :         }
     901                 :            : 
     902                 :            :         /* For non-manual bind hairpin queues, configure Tx completion queue first.*/
     903   [ #  #  #  # ]:          0 :         if (!cpfl_vport->p2p_manual_bind && cpfl_vport->p2p_tx_complq != NULL) {
     904                 :          0 :                 err = cpfl_hairpin_tx_complq_config(cpfl_vport);
     905         [ #  # ]:          0 :                 if (err != 0) {
     906                 :          0 :                         PMD_DRV_LOG(ERR, "Fail to config Tx completion queue");
     907                 :          0 :                         return err;
     908                 :            :                 }
     909                 :            :         }
     910                 :            : 
     911                 :            :         /* For non-manual bind hairpin queues, configure Rx buffer queue.*/
     912   [ #  #  #  # ]:          0 :         if (!cpfl_vport->p2p_manual_bind && cpfl_vport->p2p_rx_bufq != NULL) {
     913                 :          0 :                 cpfl_rxq_hairpin_mz_bind(dev);
     914                 :          0 :                 err = cpfl_hairpin_rx_bufq_config(cpfl_vport);
     915         [ #  # ]:          0 :                 if (err != 0) {
     916                 :          0 :                         PMD_DRV_LOG(ERR, "Fail to config Rx buffer queue");
     917                 :          0 :                         return err;
     918                 :            :                 }
     919                 :            :         }
     920                 :            : 
     921                 :            :         /* For normal data queues, configure, init and enale Rxq.
     922                 :            :          * For non-manual bind hairpin queues, configure Rxq, and then init Rxq.
     923                 :            :          */
     924         [ #  # ]:          0 :         for (i = 0; i < dev->data->nb_rx_queues; i++) {
     925                 :          0 :                 cpfl_rxq = dev->data->rx_queues[i];
     926   [ #  #  #  # ]:          0 :                 if (cpfl_rxq == NULL || cpfl_rxq->base.rx_deferred_start)
     927                 :          0 :                         continue;
     928         [ #  # ]:          0 :                 if (!cpfl_rxq->hairpin_info.hairpin_q) {
     929                 :          0 :                         err = cpfl_rx_queue_start(dev, i);
     930         [ #  # ]:          0 :                         if (err != 0) {
     931                 :          0 :                                 PMD_DRV_LOG(ERR, "Fail to start Rx queue %u", i);
     932                 :          0 :                                 return err;
     933                 :            :                         }
     934         [ #  # ]:          0 :                 } else if (!cpfl_vport->p2p_manual_bind) {
     935                 :          0 :                         err = cpfl_hairpin_rxq_config(vport, cpfl_rxq);
     936         [ #  # ]:          0 :                         if (err != 0) {
     937                 :          0 :                                 PMD_DRV_LOG(ERR, "Fail to configure hairpin Rx queue %u", i);
     938                 :          0 :                                 return err;
     939                 :            :                         }
     940                 :          0 :                         err = cpfl_rx_queue_init(dev, i);
     941         [ #  # ]:          0 :                         if (err != 0) {
     942                 :          0 :                                 PMD_DRV_LOG(ERR, "Fail to init hairpin Rx queue %u", i);
     943                 :          0 :                                 return err;
     944                 :            :                         }
     945                 :            :                 }
     946                 :            :         }
     947                 :            : 
     948                 :            :         /* For non-manual bind hairpin queues, enable Tx queue and Rx queue,
     949                 :            :          * then enable Tx completion queue and Rx buffer queue.
     950                 :            :          */
     951         [ #  # ]:          0 :         for (i = cpfl_vport->nb_data_txq; i < dev->data->nb_tx_queues; i++) {
     952                 :          0 :                 cpfl_txq = dev->data->tx_queues[i];
     953   [ #  #  #  # ]:          0 :                 if (cpfl_txq->hairpin_info.hairpin_q && !cpfl_vport->p2p_manual_bind) {
     954                 :          0 :                         err = cpfl_switch_hairpin_rxtx_queue(cpfl_vport,
     955                 :          0 :                                                              i - cpfl_vport->nb_data_txq,
     956                 :            :                                                              false, true);
     957         [ #  # ]:          0 :                         if (err)
     958                 :          0 :                                 PMD_DRV_LOG(ERR, "Failed to switch hairpin TX queue %u on",
     959                 :            :                                             i);
     960                 :            :                         else
     961                 :          0 :                                 cpfl_txq->base.q_started = true;
     962                 :            :                 }
     963                 :            :         }
     964                 :            : 
     965         [ #  # ]:          0 :         for (i = cpfl_vport->nb_data_rxq; i < dev->data->nb_rx_queues; i++) {
     966                 :          0 :                 cpfl_rxq = dev->data->rx_queues[i];
     967   [ #  #  #  # ]:          0 :                 if (cpfl_rxq->hairpin_info.hairpin_q && !cpfl_vport->p2p_manual_bind) {
     968                 :          0 :                         err = cpfl_switch_hairpin_rxtx_queue(cpfl_vport,
     969                 :          0 :                                                              i - cpfl_vport->nb_data_rxq,
     970                 :            :                                                              true, true);
     971         [ #  # ]:          0 :                         if (err)
     972                 :          0 :                                 PMD_DRV_LOG(ERR, "Failed to switch hairpin RX queue %u on",
     973                 :            :                                             i);
     974                 :            :                         else
     975                 :          0 :                                 cpfl_rxq->base.q_started = true;
     976                 :            :                 }
     977                 :            :         }
     978                 :            : 
     979         [ #  # ]:          0 :         if (!cpfl_vport->p2p_manual_bind &&
     980         [ #  # ]:          0 :             cpfl_vport->p2p_tx_complq != NULL &&
     981         [ #  # ]:          0 :             cpfl_vport->p2p_rx_bufq != NULL) {
     982                 :          0 :                 err = cpfl_switch_hairpin_complq(cpfl_vport, true);
     983         [ #  # ]:          0 :                 if (err != 0) {
     984                 :          0 :                         PMD_DRV_LOG(ERR, "Failed to switch hairpin Tx complq");
     985                 :          0 :                         return err;
     986                 :            :                 }
     987                 :          0 :                 err = cpfl_switch_hairpin_bufq(cpfl_vport, true);
     988         [ #  # ]:          0 :                 if (err != 0) {
     989                 :          0 :                         PMD_DRV_LOG(ERR, "Failed to switch hairpin Rx bufq");
     990                 :          0 :                         return err;
     991                 :            :                 }
     992                 :            :         }
     993                 :            : 
     994                 :            :         /* re-configure RSS lut if there's hairpin queue */
     995         [ #  # ]:          0 :         if (cpfl_vport->nb_p2p_rxq > 0)
     996                 :          0 :                 err = cpfl_rss_lut_config(cpfl_vport, cpfl_vport->nb_data_rxq);
     997                 :            : 
     998                 :            :         return err;
     999                 :            : }
    1000                 :            : 
    1001                 :            : static int
    1002                 :          0 : cpfl_dev_start(struct rte_eth_dev *dev)
    1003                 :            : {
    1004                 :          0 :         struct cpfl_vport *cpfl_vport = dev->data->dev_private;
    1005                 :          0 :         struct idpf_vport *vport = &cpfl_vport->base;
    1006                 :          0 :         struct idpf_adapter *base = vport->adapter;
    1007                 :          0 :         struct cpfl_adapter_ext *adapter = CPFL_ADAPTER_TO_EXT(base);
    1008                 :          0 :         uint16_t num_allocated_vectors = base->caps.num_allocated_vectors;
    1009                 :            :         uint16_t req_vecs_num;
    1010                 :            :         int ret;
    1011                 :            : 
    1012                 :            :         req_vecs_num = CPFL_DFLT_Q_VEC_NUM;
    1013         [ #  # ]:          0 :         if (req_vecs_num + adapter->used_vecs_num > num_allocated_vectors) {
    1014                 :          0 :                 PMD_DRV_LOG(ERR, "The accumulated request vectors' number should be less than %d",
    1015                 :            :                             num_allocated_vectors);
    1016                 :            :                 ret = -EINVAL;
    1017                 :          0 :                 goto err_vec;
    1018                 :            :         }
    1019                 :            : 
    1020                 :          0 :         ret = idpf_vc_vectors_alloc(vport, req_vecs_num);
    1021         [ #  # ]:          0 :         if (ret != 0) {
    1022                 :          0 :                 PMD_DRV_LOG(ERR, "Failed to allocate interrupt vectors");
    1023                 :          0 :                 goto err_vec;
    1024                 :            :         }
    1025                 :          0 :         adapter->used_vecs_num += req_vecs_num;
    1026                 :            : 
    1027                 :          0 :         ret = cpfl_config_rx_queues_irqs(dev);
    1028         [ #  # ]:          0 :         if (ret != 0) {
    1029                 :          0 :                 PMD_DRV_LOG(ERR, "Failed to configure irqs");
    1030                 :          0 :                 goto err_irq;
    1031                 :            :         }
    1032                 :            : 
    1033                 :          0 :         ret = cpfl_start_queues(dev);
    1034         [ #  # ]:          0 :         if (ret != 0) {
    1035                 :          0 :                 PMD_DRV_LOG(ERR, "Failed to start queues");
    1036                 :          0 :                 goto err_startq;
    1037                 :            :         }
    1038                 :            : 
    1039                 :          0 :         cpfl_set_rx_function(dev);
    1040                 :          0 :         cpfl_set_tx_function(dev);
    1041                 :            : 
    1042                 :          0 :         ret = idpf_vc_vport_ena_dis(vport, true);
    1043         [ #  # ]:          0 :         if (ret != 0) {
    1044                 :          0 :                 PMD_DRV_LOG(ERR, "Failed to enable vport");
    1045                 :          0 :                 goto err_vport;
    1046                 :            :         }
    1047                 :            : 
    1048         [ #  # ]:          0 :         if (cpfl_dev_stats_reset(dev))
    1049                 :          0 :                 PMD_DRV_LOG(ERR, "Failed to reset stats");
    1050                 :            : 
    1051                 :            :         return 0;
    1052                 :            : 
    1053                 :            : err_vport:
    1054                 :          0 :         cpfl_stop_queues(dev);
    1055                 :          0 : err_startq:
    1056                 :          0 :         idpf_vport_irq_unmap_config(vport, dev->data->nb_rx_queues);
    1057                 :          0 : err_irq:
    1058                 :          0 :         idpf_vc_vectors_dealloc(vport);
    1059                 :            : err_vec:
    1060                 :            :         return ret;
    1061                 :            : }
    1062                 :            : 
    1063                 :            : static int
    1064                 :          0 : cpfl_dev_stop(struct rte_eth_dev *dev)
    1065                 :            : {
    1066                 :          0 :         struct cpfl_vport *cpfl_vport = dev->data->dev_private;
    1067                 :          0 :         struct idpf_vport *vport = &cpfl_vport->base;
    1068                 :            : 
    1069         [ #  # ]:          0 :         if (dev->data->dev_started == 0)
    1070                 :            :                 return 0;
    1071                 :            : 
    1072                 :          0 :         idpf_vc_vport_ena_dis(vport, false);
    1073                 :            : 
    1074                 :          0 :         cpfl_stop_queues(dev);
    1075                 :            : 
    1076                 :          0 :         idpf_vport_irq_unmap_config(vport, dev->data->nb_rx_queues);
    1077                 :            : 
    1078                 :          0 :         idpf_vc_vectors_dealloc(vport);
    1079                 :            : 
    1080                 :          0 :         return 0;
    1081                 :            : }
    1082                 :            : 
    1083                 :            : static void
    1084                 :          0 : cpfl_flow_free(struct cpfl_vport *vport)
    1085                 :            : {
    1086                 :            :         struct rte_flow *p_flow;
    1087                 :            : 
    1088         [ #  # ]:          0 :         while ((p_flow = TAILQ_FIRST(&vport->itf.flow_list))) {
    1089         [ #  # ]:          0 :                 TAILQ_REMOVE(&vport->itf.flow_list, p_flow, next);
    1090         [ #  # ]:          0 :                 if (p_flow->engine->free)
    1091                 :          0 :                         p_flow->engine->free(p_flow);
    1092                 :          0 :                 rte_free(p_flow);
    1093                 :            :         }
    1094                 :          0 : }
    1095                 :            : 
    1096                 :            : static int
    1097                 :          0 : cpfl_p2p_queue_grps_del(struct idpf_vport *vport)
    1098                 :            : {
    1099                 :            :         struct virtchnl2_queue_group_id qg_ids;
    1100                 :            :         int ret = 0;
    1101                 :            : 
    1102                 :            :         memset(&qg_ids, 0, sizeof(qg_ids));
    1103                 :          0 :         qg_ids.queue_group_id = CPFL_P2P_QUEUE_GRP_ID;
    1104                 :          0 :         qg_ids.queue_group_type = VIRTCHNL2_QUEUE_GROUP_P2P;
    1105                 :          0 :         ret = idpf_vc_queue_grps_del(vport, CPFL_P2P_NB_QUEUE_GRPS, &qg_ids);
    1106         [ #  # ]:          0 :         if (ret)
    1107                 :          0 :                 PMD_DRV_LOG(ERR, "Failed to delete p2p queue groups");
    1108                 :          0 :         return ret;
    1109                 :            : }
    1110                 :            : 
    1111                 :            : static int
    1112                 :          0 : cpfl_dev_close(struct rte_eth_dev *dev)
    1113                 :            : {
    1114                 :          0 :         struct cpfl_vport *cpfl_vport = dev->data->dev_private;
    1115                 :          0 :         struct idpf_vport *vport = &cpfl_vport->base;
    1116                 :          0 :         struct cpfl_adapter_ext *adapter = CPFL_ADAPTER_TO_EXT(vport->adapter);
    1117                 :            : 
    1118                 :          0 :         cpfl_dev_stop(dev);
    1119         [ #  # ]:          0 :         if (cpfl_vport->p2p_mp) {
    1120                 :          0 :                 rte_mempool_free(cpfl_vport->p2p_mp);
    1121                 :          0 :                 cpfl_vport->p2p_mp = NULL;
    1122                 :            :         }
    1123                 :            : 
    1124   [ #  #  #  # ]:          0 :         if (!adapter->base.is_rx_singleq && !adapter->base.is_tx_singleq)
    1125                 :          0 :                 cpfl_p2p_queue_grps_del(vport);
    1126                 :            : 
    1127                 :          0 :         cpfl_flow_free(cpfl_vport);
    1128                 :          0 :         idpf_vport_deinit(vport);
    1129                 :          0 :         rte_free(cpfl_vport->p2p_q_chunks_info);
    1130                 :            : 
    1131                 :          0 :         adapter->cur_vports &= ~RTE_BIT32(vport->devarg_id);
    1132                 :          0 :         adapter->cur_vport_nb--;
    1133                 :          0 :         dev->data->dev_private = NULL;
    1134                 :          0 :         adapter->vports[vport->sw_idx] = NULL;
    1135                 :            :         idpf_free_dma_mem(NULL, &cpfl_vport->itf.flow_dma);
    1136                 :          0 :         rte_free(cpfl_vport);
    1137                 :            : 
    1138                 :          0 :         return 0;
    1139                 :            : }
    1140                 :            : 
    1141                 :            : static int
    1142                 :          0 : cpfl_dev_flow_ops_get(struct rte_eth_dev *dev,
    1143                 :            :                       const struct rte_flow_ops **ops)
    1144                 :            : {
    1145                 :            :         struct cpfl_itf *itf;
    1146                 :            : 
    1147         [ #  # ]:          0 :         if (!dev)
    1148                 :            :                 return -EINVAL;
    1149                 :            : 
    1150                 :          0 :         itf = CPFL_DEV_TO_ITF(dev);
    1151                 :            : 
    1152                 :            :         /* only vport support rte_flow */
    1153         [ #  # ]:          0 :         if (itf->type != CPFL_ITF_TYPE_VPORT)
    1154                 :            :                 return -ENOTSUP;
    1155                 :            : #ifdef RTE_HAS_JANSSON
    1156                 :          0 :         *ops = &cpfl_flow_ops;
    1157                 :            : #else
    1158                 :            :         *ops = NULL;
    1159                 :            :         PMD_DRV_LOG(NOTICE, "not support rte_flow, please install json-c library.");
    1160                 :            : #endif
    1161                 :          0 :         return 0;
    1162                 :            : }
    1163                 :            : 
    1164                 :            : static int
    1165                 :          0 : cpfl_hairpin_get_peer_ports(struct rte_eth_dev *dev, uint16_t *peer_ports,
    1166                 :            :                             size_t len, uint32_t tx)
    1167                 :            : {
    1168                 :          0 :         struct cpfl_vport *cpfl_vport =
    1169                 :          0 :                 (struct cpfl_vport *)dev->data->dev_private;
    1170                 :            :         struct idpf_tx_queue *txq;
    1171                 :            :         struct idpf_rx_queue *rxq;
    1172                 :            :         struct cpfl_tx_queue *cpfl_txq;
    1173                 :            :         struct cpfl_rx_queue *cpfl_rxq;
    1174                 :            :         uint16_t i;
    1175                 :            :         uint16_t j = 0;
    1176                 :            : 
    1177         [ #  # ]:          0 :         if (len <= 0)
    1178                 :            :                 return -EINVAL;
    1179                 :            : 
    1180         [ #  # ]:          0 :         if (cpfl_vport->p2p_q_chunks_info == NULL)
    1181                 :            :                 return -ENOTSUP;
    1182                 :            : 
    1183         [ #  # ]:          0 :         if (tx > 0) {
    1184         [ #  # ]:          0 :                 for (i = cpfl_vport->nb_data_txq, j = 0; i < dev->data->nb_tx_queues; i++, j++) {
    1185                 :          0 :                         txq = dev->data->tx_queues[i];
    1186   [ #  #  #  # ]:          0 :                         if (txq == NULL || j >= len)
    1187                 :            :                                 return -EINVAL;
    1188                 :            :                         cpfl_txq = (struct cpfl_tx_queue *)txq;
    1189                 :          0 :                         peer_ports[j] = cpfl_txq->hairpin_info.peer_rxp;
    1190                 :            :                 }
    1191                 :            :         } else if (tx == 0) {
    1192         [ #  # ]:          0 :                 for (i = cpfl_vport->nb_data_rxq, j = 0; i < dev->data->nb_rx_queues; i++, j++) {
    1193                 :          0 :                         rxq = dev->data->rx_queues[i];
    1194   [ #  #  #  # ]:          0 :                         if (rxq == NULL || j >= len)
    1195                 :            :                                 return -EINVAL;
    1196                 :            :                         cpfl_rxq = (struct cpfl_rx_queue *)rxq;
    1197                 :          0 :                         peer_ports[j] = cpfl_rxq->hairpin_info.peer_txp;
    1198                 :            :                 }
    1199                 :            :         }
    1200                 :            : 
    1201                 :          0 :         return j;
    1202                 :            : }
    1203                 :            : 
    1204                 :            : static int
    1205                 :          0 : cpfl_hairpin_bind(struct rte_eth_dev *dev, uint16_t rx_port)
    1206                 :            : {
    1207                 :          0 :         struct cpfl_vport *cpfl_tx_vport = dev->data->dev_private;
    1208                 :          0 :         struct idpf_vport *tx_vport = &cpfl_tx_vport->base;
    1209                 :            :         struct cpfl_vport *cpfl_rx_vport;
    1210                 :            :         struct cpfl_tx_queue *cpfl_txq;
    1211                 :            :         struct cpfl_rx_queue *cpfl_rxq;
    1212                 :            :         struct rte_eth_dev *peer_dev;
    1213                 :            :         struct idpf_vport *rx_vport;
    1214                 :            :         int err = 0;
    1215                 :            :         int i;
    1216                 :            : 
    1217                 :          0 :         err = cpfl_txq_hairpin_info_update(dev, rx_port);
    1218         [ #  # ]:          0 :         if (err != 0) {
    1219                 :          0 :                 PMD_DRV_LOG(ERR, "Fail to update Tx hairpin queue info.");
    1220                 :          0 :                 return err;
    1221                 :            :         }
    1222                 :            : 
    1223                 :            :         /* configure hairpin queues */
    1224         [ #  # ]:          0 :         for (i = cpfl_tx_vport->nb_data_txq; i < dev->data->nb_tx_queues; i++) {
    1225                 :          0 :                 cpfl_txq = dev->data->tx_queues[i];
    1226                 :          0 :                 err = cpfl_hairpin_txq_config(tx_vport, cpfl_txq);
    1227         [ #  # ]:          0 :                 if (err != 0) {
    1228                 :          0 :                         PMD_DRV_LOG(ERR, "Fail to configure hairpin Tx queue %u", i);
    1229                 :          0 :                         return err;
    1230                 :            :                 }
    1231                 :            :         }
    1232                 :            : 
    1233                 :          0 :         err = cpfl_hairpin_tx_complq_config(cpfl_tx_vport);
    1234         [ #  # ]:          0 :         if (err != 0) {
    1235                 :          0 :                 PMD_DRV_LOG(ERR, "Fail to config Tx completion queue");
    1236                 :          0 :                 return err;
    1237                 :            :         }
    1238                 :            : 
    1239                 :          0 :         peer_dev = &rte_eth_devices[rx_port];
    1240                 :          0 :         cpfl_rx_vport = (struct cpfl_vport *)peer_dev->data->dev_private;
    1241                 :          0 :         rx_vport = &cpfl_rx_vport->base;
    1242                 :          0 :         cpfl_rxq_hairpin_mz_bind(peer_dev);
    1243                 :            : 
    1244                 :          0 :         err = cpfl_hairpin_rx_bufq_config(cpfl_rx_vport);
    1245         [ #  # ]:          0 :         if (err != 0) {
    1246                 :          0 :                 PMD_DRV_LOG(ERR, "Fail to config Rx buffer queue");
    1247                 :          0 :                 return err;
    1248                 :            :         }
    1249                 :            : 
    1250         [ #  # ]:          0 :         for (i = cpfl_rx_vport->nb_data_rxq; i < peer_dev->data->nb_rx_queues; i++) {
    1251                 :          0 :                 cpfl_rxq = peer_dev->data->rx_queues[i];
    1252                 :          0 :                 err = cpfl_hairpin_rxq_config(rx_vport, cpfl_rxq);
    1253         [ #  # ]:          0 :                 if (err != 0) {
    1254                 :          0 :                         PMD_DRV_LOG(ERR, "Fail to configure hairpin Rx queue %u", i);
    1255                 :          0 :                         return err;
    1256                 :            :                 }
    1257                 :          0 :                 err = cpfl_rx_queue_init(peer_dev, i);
    1258         [ #  # ]:          0 :                 if (err != 0) {
    1259                 :          0 :                         PMD_DRV_LOG(ERR, "Fail to init hairpin Rx queue %u", i);
    1260                 :          0 :                         return err;
    1261                 :            :                 }
    1262                 :            :         }
    1263                 :            : 
    1264                 :            :         /* enable hairpin queues */
    1265         [ #  # ]:          0 :         for (i = cpfl_tx_vport->nb_data_txq; i < dev->data->nb_tx_queues; i++) {
    1266                 :          0 :                 cpfl_txq = dev->data->tx_queues[i];
    1267                 :          0 :                 err = cpfl_switch_hairpin_rxtx_queue(cpfl_tx_vport,
    1268                 :          0 :                                                      i - cpfl_tx_vport->nb_data_txq,
    1269                 :            :                                                      false, true);
    1270         [ #  # ]:          0 :                 if (err != 0) {
    1271                 :          0 :                         PMD_DRV_LOG(ERR, "Failed to switch hairpin TX queue %u on",
    1272                 :            :                                     i);
    1273                 :          0 :                         return err;
    1274                 :            :                 }
    1275                 :          0 :                 cpfl_txq->base.q_started = true;
    1276                 :            :         }
    1277                 :            : 
    1278                 :          0 :         err = cpfl_switch_hairpin_complq(cpfl_tx_vport, true);
    1279         [ #  # ]:          0 :         if (err != 0) {
    1280                 :          0 :                 PMD_DRV_LOG(ERR, "Failed to switch hairpin Tx complq");
    1281                 :          0 :                 return err;
    1282                 :            :         }
    1283                 :            : 
    1284         [ #  # ]:          0 :         for (i = cpfl_rx_vport->nb_data_rxq; i < peer_dev->data->nb_rx_queues; i++) {
    1285                 :          0 :                 cpfl_rxq = peer_dev->data->rx_queues[i];
    1286                 :          0 :                 err = cpfl_switch_hairpin_rxtx_queue(cpfl_rx_vport,
    1287                 :          0 :                                                      i - cpfl_rx_vport->nb_data_rxq,
    1288                 :            :                                                      true, true);
    1289         [ #  # ]:          0 :                 if (err != 0) {
    1290                 :          0 :                         PMD_DRV_LOG(ERR, "Failed to switch hairpin RX queue %u on",
    1291                 :            :                                     i);
    1292                 :            :                 }
    1293                 :          0 :                 cpfl_rxq->base.q_started = true;
    1294                 :            :         }
    1295                 :            : 
    1296                 :          0 :         err = cpfl_switch_hairpin_bufq(cpfl_rx_vport, true);
    1297         [ #  # ]:          0 :         if (err != 0) {
    1298                 :          0 :                 PMD_DRV_LOG(ERR, "Failed to switch hairpin Rx buffer queue");
    1299                 :          0 :                 return err;
    1300                 :            :         }
    1301                 :            : 
    1302                 :            :         return 0;
    1303                 :            : }
    1304                 :            : 
    1305                 :            : static int
    1306                 :          0 : cpfl_hairpin_unbind(struct rte_eth_dev *dev, uint16_t rx_port)
    1307                 :            : {
    1308                 :          0 :         struct cpfl_vport *cpfl_tx_vport = dev->data->dev_private;
    1309                 :          0 :         struct rte_eth_dev *peer_dev = &rte_eth_devices[rx_port];
    1310                 :          0 :         struct cpfl_vport *cpfl_rx_vport = peer_dev->data->dev_private;
    1311                 :            :         struct cpfl_tx_queue *cpfl_txq;
    1312                 :            :         struct cpfl_rx_queue *cpfl_rxq;
    1313                 :            :         int i;
    1314                 :            : 
    1315                 :            :         /* disable hairpin queues */
    1316         [ #  # ]:          0 :         for (i = cpfl_tx_vport->nb_data_txq; i < dev->data->nb_tx_queues; i++) {
    1317                 :          0 :                 cpfl_txq = dev->data->tx_queues[i];
    1318                 :          0 :                 cpfl_switch_hairpin_rxtx_queue(cpfl_tx_vport,
    1319                 :          0 :                                                i - cpfl_tx_vport->nb_data_txq,
    1320                 :            :                                                false, false);
    1321                 :          0 :                 cpfl_txq->base.q_started = false;
    1322                 :            :         }
    1323                 :            : 
    1324                 :          0 :         cpfl_switch_hairpin_complq(cpfl_tx_vport, false);
    1325                 :            : 
    1326         [ #  # ]:          0 :         for (i = cpfl_rx_vport->nb_data_rxq; i < peer_dev->data->nb_rx_queues; i++) {
    1327                 :          0 :                 cpfl_rxq = peer_dev->data->rx_queues[i];
    1328                 :          0 :                 cpfl_switch_hairpin_rxtx_queue(cpfl_rx_vport,
    1329                 :          0 :                                                i - cpfl_rx_vport->nb_data_rxq,
    1330                 :            :                                                true, false);
    1331                 :          0 :                 cpfl_rxq->base.q_started = false;
    1332                 :            :         }
    1333                 :            : 
    1334                 :          0 :         cpfl_switch_hairpin_bufq(cpfl_rx_vport, false);
    1335                 :            : 
    1336                 :          0 :         return 0;
    1337                 :            : }
    1338                 :            : 
    1339                 :            : static const struct eth_dev_ops cpfl_eth_dev_ops = {
    1340                 :            :         .dev_configure                  = cpfl_dev_configure,
    1341                 :            :         .dev_close                      = cpfl_dev_close,
    1342                 :            :         .rx_queue_setup                 = cpfl_rx_queue_setup,
    1343                 :            :         .tx_queue_setup                 = cpfl_tx_queue_setup,
    1344                 :            :         .dev_infos_get                  = cpfl_dev_info_get,
    1345                 :            :         .dev_start                      = cpfl_dev_start,
    1346                 :            :         .dev_stop                       = cpfl_dev_stop,
    1347                 :            :         .link_update                    = cpfl_dev_link_update,
    1348                 :            :         .rx_queue_start                 = cpfl_rx_queue_start,
    1349                 :            :         .tx_queue_start                 = cpfl_tx_queue_start,
    1350                 :            :         .rx_queue_stop                  = cpfl_rx_queue_stop,
    1351                 :            :         .tx_queue_stop                  = cpfl_tx_queue_stop,
    1352                 :            :         .rx_queue_release               = cpfl_dev_rx_queue_release,
    1353                 :            :         .tx_queue_release               = cpfl_dev_tx_queue_release,
    1354                 :            :         .mtu_set                        = cpfl_dev_mtu_set,
    1355                 :            :         .dev_supported_ptypes_get       = cpfl_dev_supported_ptypes_get,
    1356                 :            :         .stats_get                      = cpfl_dev_stats_get,
    1357                 :            :         .stats_reset                    = cpfl_dev_stats_reset,
    1358                 :            :         .reta_update                    = cpfl_rss_reta_update,
    1359                 :            :         .reta_query                     = cpfl_rss_reta_query,
    1360                 :            :         .rss_hash_update                = cpfl_rss_hash_update,
    1361                 :            :         .rss_hash_conf_get              = cpfl_rss_hash_conf_get,
    1362                 :            :         .xstats_get                     = cpfl_dev_xstats_get,
    1363                 :            :         .xstats_get_names               = cpfl_dev_xstats_get_names,
    1364                 :            :         .xstats_reset                   = cpfl_dev_xstats_reset,
    1365                 :            :         .flow_ops_get                   = cpfl_dev_flow_ops_get,
    1366                 :            :         .hairpin_cap_get                = cpfl_hairpin_cap_get,
    1367                 :            :         .rx_hairpin_queue_setup         = cpfl_rx_hairpin_queue_setup,
    1368                 :            :         .tx_hairpin_queue_setup         = cpfl_tx_hairpin_queue_setup,
    1369                 :            :         .hairpin_get_peer_ports         = cpfl_hairpin_get_peer_ports,
    1370                 :            :         .hairpin_bind                   = cpfl_hairpin_bind,
    1371                 :            :         .hairpin_unbind                 = cpfl_hairpin_unbind,
    1372                 :            : };
    1373                 :            : 
    1374                 :            : static int
    1375                 :            : insert_value(struct cpfl_devargs *devargs, uint16_t id)
    1376                 :            : {
    1377                 :            :         uint16_t i;
    1378                 :            : 
    1379                 :            :         /* ignore duplicate */
    1380   [ #  #  #  # ]:          0 :         for (i = 0; i < devargs->req_vport_nb; i++) {
    1381   [ #  #  #  # ]:          0 :                 if (devargs->req_vports[i] == id)
    1382                 :            :                         return 0;
    1383                 :            :         }
    1384                 :            : 
    1385                 :          0 :         devargs->req_vports[devargs->req_vport_nb] = id;
    1386                 :          0 :         devargs->req_vport_nb++;
    1387                 :            : 
    1388                 :          0 :         return 0;
    1389                 :            : }
    1390                 :            : 
    1391                 :            : static const char *
    1392                 :          0 : parse_range(const char *value, struct cpfl_devargs *devargs)
    1393                 :            : {
    1394                 :            :         uint16_t lo, hi, i;
    1395                 :          0 :         int n = 0;
    1396                 :            :         int result;
    1397                 :            :         const char *pos = value;
    1398                 :            : 
    1399                 :          0 :         result = sscanf(value, "%hu%n-%hu%n", &lo, &n, &hi, &n);
    1400         [ #  # ]:          0 :         if (result == 1) {
    1401                 :          0 :                 if (insert_value(devargs, lo) != 0)
    1402                 :            :                         return NULL;
    1403         [ #  # ]:          0 :         } else if (result == 2) {
    1404         [ #  # ]:          0 :                 if (lo > hi)
    1405                 :            :                         return NULL;
    1406         [ #  # ]:          0 :                 for (i = lo; i <= hi; i++) {
    1407                 :            :                         if (insert_value(devargs, i) != 0)
    1408                 :            :                                 return NULL;
    1409                 :            :                 }
    1410                 :            :         } else {
    1411                 :            :                 return NULL;
    1412                 :            :         }
    1413                 :            : 
    1414                 :          0 :         return pos + n;
    1415                 :            : }
    1416                 :            : 
    1417                 :            : static int
    1418                 :          0 : parse_vport(const char *key, const char *value, void *args)
    1419                 :            : {
    1420                 :            :         struct cpfl_devargs *devargs = args;
    1421                 :            :         const char *pos = value;
    1422                 :            : 
    1423                 :          0 :         devargs->req_vport_nb = 0;
    1424                 :            : 
    1425         [ #  # ]:          0 :         if (*pos == '[')
    1426                 :          0 :                 pos++;
    1427                 :            : 
    1428                 :            :         while (1) {
    1429                 :          0 :                 pos = parse_range(pos, devargs);
    1430         [ #  # ]:          0 :                 if (pos == NULL) {
    1431                 :          0 :                         PMD_INIT_LOG(ERR, "invalid value:\"%s\" for key:\"%s\", ",
    1432                 :            :                                      value, key);
    1433                 :          0 :                         return -EINVAL;
    1434                 :            :                 }
    1435         [ #  # ]:          0 :                 if (*pos != ',')
    1436                 :            :                         break;
    1437                 :          0 :                 pos++;
    1438                 :            :         }
    1439                 :            : 
    1440   [ #  #  #  # ]:          0 :         if (*value == '[' && *pos != ']') {
    1441                 :          0 :                 PMD_INIT_LOG(ERR, "invalid value:\"%s\" for key:\"%s\", ",
    1442                 :            :                              value, key);
    1443                 :          0 :                 return -EINVAL;
    1444                 :            :         }
    1445                 :            : 
    1446                 :            :         return 0;
    1447                 :            : }
    1448                 :            : 
    1449                 :            : static int
    1450                 :          0 : parse_bool(const char *key, const char *value, void *args)
    1451                 :            : {
    1452                 :            :         int *i = args;
    1453                 :            :         char *end;
    1454                 :            :         int num;
    1455                 :            : 
    1456                 :          0 :         errno = 0;
    1457                 :            : 
    1458                 :          0 :         num = strtoul(value, &end, 10);
    1459                 :            : 
    1460   [ #  #  #  # ]:          0 :         if (errno == ERANGE || (num != 0 && num != 1)) {
    1461                 :          0 :                 PMD_INIT_LOG(ERR, "invalid value:\"%s\" for key:\"%s\", value must be 0 or 1",
    1462                 :            :                         value, key);
    1463                 :          0 :                 return -EINVAL;
    1464                 :            :         }
    1465                 :            : 
    1466                 :          0 :         *i = num;
    1467                 :          0 :         return 0;
    1468                 :            : }
    1469                 :            : 
    1470                 :            : static int
    1471                 :            : enlist(uint16_t *list, uint16_t *len_list, const uint16_t max_list, uint16_t val)
    1472                 :            : {
    1473                 :            :         uint16_t i;
    1474                 :            : 
    1475   [ #  #  #  # ]:          0 :         for (i = 0; i < *len_list; i++) {
    1476   [ #  #  #  # ]:          0 :                 if (list[i] == val)
    1477                 :            :                         return 0;
    1478                 :            :         }
    1479   [ #  #  #  # ]:          0 :         if (*len_list >= max_list)
    1480                 :            :                 return -1;
    1481                 :          0 :         list[(*len_list)++] = val;
    1482                 :            :         return 0;
    1483                 :            : }
    1484                 :            : 
    1485                 :            : static const char *
    1486                 :          0 : process_range(const char *str, uint16_t *list, uint16_t *len_list,
    1487                 :            :         const uint16_t max_list)
    1488                 :            : {
    1489                 :            :         uint16_t lo, hi, val;
    1490                 :          0 :         int result, n = 0;
    1491                 :            :         const char *pos = str;
    1492                 :            : 
    1493                 :          0 :         result = sscanf(str, "%hu%n-%hu%n", &lo, &n, &hi, &n);
    1494         [ #  # ]:          0 :         if (result == 1) {
    1495                 :          0 :                 if (enlist(list, len_list, max_list, lo) != 0)
    1496                 :            :                         return NULL;
    1497         [ #  # ]:          0 :         } else if (result == 2) {
    1498         [ #  # ]:          0 :                 if (lo > hi)
    1499                 :            :                         return NULL;
    1500         [ #  # ]:          0 :                 for (val = lo; val <= hi; val++) {
    1501                 :            :                         if (enlist(list, len_list, max_list, val) != 0)
    1502                 :            :                                 return NULL;
    1503                 :            :                 }
    1504                 :            :         } else {
    1505                 :            :                 return NULL;
    1506                 :            :         }
    1507                 :          0 :         return pos + n;
    1508                 :            : }
    1509                 :            : 
    1510                 :            : static const char *
    1511                 :          0 : process_list(const char *str, uint16_t *list, uint16_t *len_list, const uint16_t max_list)
    1512                 :            : {
    1513                 :            :         const char *pos = str;
    1514                 :            : 
    1515         [ #  # ]:          0 :         if (*pos == '[')
    1516                 :          0 :                 pos++;
    1517                 :            :         while (1) {
    1518                 :          0 :                 pos = process_range(pos, list, len_list, max_list);
    1519         [ #  # ]:          0 :                 if (pos == NULL)
    1520                 :            :                         return NULL;
    1521         [ #  # ]:          0 :                 if (*pos != ',') /* end of list */
    1522                 :            :                         break;
    1523                 :          0 :                 pos++;
    1524                 :            :         }
    1525   [ #  #  #  # ]:          0 :         if (*str == '[' && *pos != ']')
    1526                 :            :                 return NULL;
    1527         [ #  # ]:          0 :         if (*pos == ']')
    1528                 :          0 :                 pos++;
    1529                 :            :         return pos;
    1530                 :            : }
    1531                 :            : 
    1532                 :            : static int
    1533                 :          0 : parse_repr(const char *key __rte_unused, const char *value, void *args)
    1534                 :            : {
    1535                 :            :         struct cpfl_devargs *devargs = args;
    1536                 :            :         struct rte_eth_devargs *eth_da;
    1537                 :            :         const char *str = value;
    1538                 :            : 
    1539         [ #  # ]:          0 :         if (devargs->repr_args_num == CPFL_REPR_ARG_NUM_MAX)
    1540                 :            :                 return -EINVAL;
    1541                 :            : 
    1542                 :          0 :         eth_da = &devargs->repr_args[devargs->repr_args_num];
    1543                 :            : 
    1544         [ #  # ]:          0 :         if (str[0] == 'c') {
    1545                 :          0 :                 str += 1;
    1546                 :          0 :                 str = process_list(str, eth_da->mh_controllers,
    1547                 :            :                                 &eth_da->nb_mh_controllers,
    1548                 :            :                                 RTE_DIM(eth_da->mh_controllers));
    1549         [ #  # ]:          0 :                 if (str == NULL)
    1550                 :          0 :                         goto done;
    1551                 :            :         }
    1552   [ #  #  #  # ]:          0 :         if (str[0] == 'p' && str[1] == 'f') {
    1553                 :          0 :                 eth_da->type = RTE_ETH_REPRESENTOR_PF;
    1554                 :          0 :                 str += 2;
    1555                 :          0 :                 str = process_list(str, eth_da->ports,
    1556                 :            :                                 &eth_da->nb_ports, RTE_DIM(eth_da->ports));
    1557   [ #  #  #  # ]:          0 :                 if (str == NULL || str[0] == '\0')
    1558                 :          0 :                         goto done;
    1559         [ #  # ]:          0 :         } else if (eth_da->nb_mh_controllers > 0) {
    1560                 :            :                 /* 'c' must followed by 'pf'. */
    1561                 :            :                 str = NULL;
    1562                 :          0 :                 goto done;
    1563                 :            :         }
    1564   [ #  #  #  # ]:          0 :         if (str[0] == 'v' && str[1] == 'f') {
    1565                 :          0 :                 eth_da->type = RTE_ETH_REPRESENTOR_VF;
    1566                 :          0 :                 str += 2;
    1567   [ #  #  #  # ]:          0 :         } else if (str[0] == 's' && str[1] == 'f') {
    1568                 :          0 :                 eth_da->type = RTE_ETH_REPRESENTOR_SF;
    1569                 :          0 :                 str += 2;
    1570                 :            :         } else {
    1571                 :            :                 /* 'pf' must followed by 'vf' or 'sf'. */
    1572         [ #  # ]:          0 :                 if (eth_da->type == RTE_ETH_REPRESENTOR_PF) {
    1573                 :            :                         str = NULL;
    1574                 :          0 :                         goto done;
    1575                 :            :                 }
    1576                 :          0 :                 eth_da->type = RTE_ETH_REPRESENTOR_VF;
    1577                 :            :         }
    1578                 :          0 :         str = process_list(str, eth_da->representor_ports,
    1579                 :            :                 &eth_da->nb_representor_ports,
    1580                 :            :                 RTE_DIM(eth_da->representor_ports));
    1581                 :          0 : done:
    1582         [ #  # ]:          0 :         if (str == NULL) {
    1583                 :          0 :                 PMD_DRV_LOG(ERR, "wrong representor format: %s", str);
    1584                 :          0 :                 return -1;
    1585                 :            :         }
    1586                 :            : 
    1587                 :          0 :         devargs->repr_args_num++;
    1588                 :            : 
    1589                 :          0 :         return 0;
    1590                 :            : }
    1591                 :            : 
    1592                 :            : #ifdef RTE_HAS_JANSSON
    1593                 :            : static int
    1594                 :          0 : parse_file(const char *key, const char *value, void *args)
    1595                 :            : {
    1596                 :            :         char *name = args;
    1597                 :            : 
    1598         [ #  # ]:          0 :         if (strlen(value) > CPFL_FLOW_FILE_LEN - 1) {
    1599                 :          0 :                 PMD_DRV_LOG(ERR, "file path(%s) is too long.", value);
    1600                 :          0 :                 return -1;
    1601                 :            :         }
    1602                 :            : 
    1603                 :          0 :         PMD_DRV_LOG(DEBUG, "value:\"%s\" for key:\"%s\"", value, key);
    1604                 :            :         strlcpy(name, value, CPFL_FLOW_FILE_LEN);
    1605                 :            : 
    1606                 :          0 :         return 0;
    1607                 :            : }
    1608                 :            : #endif
    1609                 :            : 
    1610                 :            : static int
    1611                 :          0 : cpfl_parse_devargs(struct rte_pci_device *pci_dev, struct cpfl_adapter_ext *adapter,
    1612                 :            :                    bool first, struct cpfl_devargs *cpfl_args)
    1613                 :            : {
    1614                 :          0 :         struct rte_devargs *devargs = pci_dev->device.devargs;
    1615                 :            :         struct rte_kvargs *kvlist;
    1616                 :            :         int ret;
    1617                 :            : 
    1618         [ #  # ]:          0 :         if (devargs == NULL)
    1619                 :            :                 return 0;
    1620                 :            : 
    1621         [ #  # ]:          0 :         kvlist = rte_kvargs_parse(devargs->args,
    1622                 :            :                         first ? cpfl_valid_args_first : cpfl_valid_args_again);
    1623         [ #  # ]:          0 :         if (kvlist == NULL) {
    1624                 :          0 :                 PMD_INIT_LOG(ERR, "invalid kvargs key");
    1625                 :          0 :                 return -EINVAL;
    1626                 :            :         }
    1627                 :            : 
    1628         [ #  # ]:          0 :         if (rte_kvargs_count(kvlist, CPFL_VPORT) > 1) {
    1629                 :          0 :                 PMD_INIT_LOG(ERR, "devarg vport is duplicated.");
    1630                 :            :                 ret = -EINVAL;
    1631                 :          0 :                 goto fail;
    1632                 :            :         }
    1633                 :            : 
    1634                 :          0 :         ret = rte_kvargs_process(kvlist, CPFL_REPRESENTOR, &parse_repr, cpfl_args);
    1635                 :            : 
    1636         [ #  # ]:          0 :         if (ret != 0)
    1637                 :          0 :                 goto fail;
    1638                 :            : 
    1639         [ #  # ]:          0 :         if (!first)
    1640                 :          0 :                 goto finish;
    1641                 :            : 
    1642                 :          0 :         ret = rte_kvargs_process(kvlist, CPFL_VPORT, &parse_vport,
    1643                 :            :                                  cpfl_args);
    1644         [ #  # ]:          0 :         if (ret != 0)
    1645                 :          0 :                 goto fail;
    1646                 :            : 
    1647                 :          0 :         ret = rte_kvargs_process(kvlist, CPFL_TX_SINGLE_Q, &parse_bool,
    1648                 :          0 :                                  &adapter->base.is_tx_singleq);
    1649         [ #  # ]:          0 :         if (ret != 0)
    1650                 :          0 :                 goto fail;
    1651                 :            : 
    1652                 :          0 :         ret = rte_kvargs_process(kvlist, CPFL_RX_SINGLE_Q, &parse_bool,
    1653                 :          0 :                                  &adapter->base.is_rx_singleq);
    1654         [ #  # ]:          0 :         if (ret != 0)
    1655                 :          0 :                 goto fail;
    1656                 :            : #ifdef RTE_HAS_JANSSON
    1657         [ #  # ]:          0 :         if (rte_kvargs_get(kvlist, CPFL_FLOW_PARSER)) {
    1658                 :          0 :                 ret = rte_kvargs_process(kvlist, CPFL_FLOW_PARSER,
    1659                 :          0 :                                          &parse_file, cpfl_args->flow_parser);
    1660         [ #  # ]:          0 :                 if (ret) {
    1661                 :          0 :                         PMD_DRV_LOG(ERR, "Failed to parser flow_parser, ret: %d", ret);
    1662                 :          0 :                         goto fail;
    1663                 :            :                 }
    1664                 :            :         } else {
    1665                 :          0 :                 cpfl_args->flow_parser[0] = '\0';
    1666                 :            :         }
    1667                 :            : #endif
    1668                 :          0 : finish:
    1669                 :          0 : fail:
    1670                 :          0 :         rte_kvargs_free(kvlist);
    1671                 :          0 :         return ret;
    1672                 :            : }
    1673                 :            : 
    1674                 :            : static struct cpfl_vport *
    1675                 :            : cpfl_find_vport(struct cpfl_adapter_ext *adapter, uint32_t vport_id)
    1676                 :            : {
    1677                 :            :         struct cpfl_vport *vport = NULL;
    1678                 :            :         int i;
    1679                 :            : 
    1680         [ #  # ]:          0 :         for (i = 0; i < adapter->cur_vport_nb; i++) {
    1681                 :          0 :                 vport = adapter->vports[i];
    1682         [ #  # ]:          0 :                 if (vport == NULL)
    1683                 :          0 :                         continue;
    1684         [ #  # ]:          0 :                 if (vport->base.vport_id != vport_id)
    1685                 :          0 :                         continue;
    1686                 :            :                 else
    1687                 :            :                         return vport;
    1688                 :            :         }
    1689                 :            : 
    1690                 :            :         return NULL;
    1691                 :            : }
    1692                 :            : 
    1693                 :            : static void
    1694                 :          0 : cpfl_handle_vchnl_event_msg(struct cpfl_adapter_ext *adapter, uint8_t *msg, uint16_t msglen)
    1695                 :            : {
    1696                 :            :         struct virtchnl2_event *vc_event = (struct virtchnl2_event *)msg;
    1697                 :            :         struct cpfl_vport *vport;
    1698                 :            :         struct rte_eth_dev_data *data;
    1699                 :            :         struct rte_eth_dev *dev;
    1700                 :            : 
    1701         [ #  # ]:          0 :         if (msglen < sizeof(struct virtchnl2_event)) {
    1702                 :          0 :                 PMD_DRV_LOG(ERR, "Error event");
    1703                 :          0 :                 return;
    1704                 :            :         }
    1705                 :            : 
    1706                 :            :         /* ignore if it is ctrl vport */
    1707         [ #  # ]:          0 :         if (adapter->ctrl_vport.base.vport_id == vc_event->vport_id)
    1708                 :            :                 return;
    1709                 :            : 
    1710                 :            :         vport = cpfl_find_vport(adapter, vc_event->vport_id);
    1711         [ #  # ]:          0 :         if (!vport) {
    1712                 :          0 :                 PMD_DRV_LOG(ERR, "Can't find vport.");
    1713                 :          0 :                 return;
    1714                 :            :         }
    1715                 :            : 
    1716                 :          0 :         data = vport->itf.data;
    1717                 :          0 :         dev = &rte_eth_devices[data->port_id];
    1718                 :            : 
    1719         [ #  # ]:          0 :         switch (vc_event->event) {
    1720                 :          0 :         case VIRTCHNL2_EVENT_LINK_CHANGE:
    1721                 :          0 :                 PMD_DRV_LOG(DEBUG, "VIRTCHNL2_EVENT_LINK_CHANGE");
    1722                 :          0 :                 vport->base.link_up = !!(vc_event->link_status);
    1723                 :          0 :                 vport->base.link_speed = vc_event->link_speed;
    1724                 :          0 :                 cpfl_dev_link_update(dev, 0);
    1725                 :          0 :                 break;
    1726                 :          0 :         default:
    1727                 :          0 :                 PMD_DRV_LOG(ERR, " unknown event received %u", vc_event->event);
    1728                 :          0 :                 break;
    1729                 :            :         }
    1730                 :            : }
    1731                 :            : 
    1732                 :            : int
    1733                 :          0 : cpfl_vport_info_create(struct cpfl_adapter_ext *adapter,
    1734                 :            :                        struct cpfl_vport_id *vport_identity,
    1735                 :            :                        struct cpchnl2_event_vport_created *vport_created)
    1736                 :            : {
    1737                 :          0 :         struct cpfl_vport_info *info = NULL;
    1738                 :            :         int ret;
    1739                 :            : 
    1740                 :          0 :         rte_spinlock_lock(&adapter->vport_map_lock);
    1741                 :          0 :         ret = rte_hash_lookup_data(adapter->vport_map_hash, vport_identity, (void **)&info);
    1742         [ #  # ]:          0 :         if (ret >= 0) {
    1743                 :          0 :                 PMD_DRV_LOG(WARNING, "vport already exist, overwrite info anyway");
    1744                 :            :                 /* overwrite info */
    1745         [ #  # ]:          0 :                 if (info)
    1746                 :          0 :                         info->vport = *vport_created;
    1747                 :          0 :                 goto fini;
    1748                 :            :         }
    1749                 :            : 
    1750                 :          0 :         info = rte_zmalloc(NULL, sizeof(*info), 0);
    1751         [ #  # ]:          0 :         if (info == NULL) {
    1752                 :          0 :                 PMD_DRV_LOG(ERR, "Failed to alloc memory for vport map info");
    1753                 :            :                 ret = -ENOMEM;
    1754                 :          0 :                 goto err;
    1755                 :            :         }
    1756                 :            : 
    1757                 :          0 :         info->vport = *vport_created;
    1758                 :            : 
    1759                 :          0 :         ret = rte_hash_add_key_data(adapter->vport_map_hash, vport_identity, info);
    1760         [ #  # ]:          0 :         if (ret < 0) {
    1761                 :          0 :                 PMD_DRV_LOG(ERR, "Failed to add vport map into hash");
    1762                 :          0 :                 rte_free(info);
    1763                 :          0 :                 goto err;
    1764                 :            :         }
    1765                 :            : 
    1766                 :          0 : fini:
    1767                 :            :         rte_spinlock_unlock(&adapter->vport_map_lock);
    1768                 :          0 :         return 0;
    1769                 :          0 : err:
    1770                 :            :         rte_spinlock_unlock(&adapter->vport_map_lock);
    1771                 :          0 :         return ret;
    1772                 :            : }
    1773                 :            : 
    1774                 :            : static int
    1775                 :          0 : cpfl_vport_info_destroy(struct cpfl_adapter_ext *adapter, struct cpfl_vport_id *vport_identity)
    1776                 :            : {
    1777                 :            :         struct cpfl_vport_info *info;
    1778                 :            :         int ret;
    1779                 :            : 
    1780                 :          0 :         rte_spinlock_lock(&adapter->vport_map_lock);
    1781                 :          0 :         ret = rte_hash_lookup_data(adapter->vport_map_hash, vport_identity, (void **)&info);
    1782         [ #  # ]:          0 :         if (ret < 0) {
    1783                 :          0 :                 PMD_DRV_LOG(ERR, "vport id doesn't exist");
    1784                 :          0 :                 goto err;
    1785                 :            :         }
    1786                 :            : 
    1787                 :          0 :         rte_hash_del_key(adapter->vport_map_hash, vport_identity);
    1788                 :            :         rte_spinlock_unlock(&adapter->vport_map_lock);
    1789                 :          0 :         rte_free(info);
    1790                 :            : 
    1791                 :          0 :         return 0;
    1792                 :            : 
    1793                 :            : err:
    1794                 :            :         rte_spinlock_unlock(&adapter->vport_map_lock);
    1795                 :          0 :         return ret;
    1796                 :            : }
    1797                 :            : 
    1798                 :            : static void
    1799                 :          0 : cpfl_handle_cpchnl_event_msg(struct cpfl_adapter_ext *adapter, uint8_t *msg, uint16_t msglen)
    1800                 :            : {
    1801                 :            :         struct cpchnl2_event_info *cpchnl2_event = (struct cpchnl2_event_info *)msg;
    1802                 :            :         struct cpchnl2_event_vport_created *vport_created;
    1803                 :          0 :         struct cpfl_vport_id vport_identity = { 0 };
    1804                 :            : 
    1805         [ #  # ]:          0 :         if (msglen < sizeof(struct cpchnl2_event_info)) {
    1806                 :          0 :                 PMD_DRV_LOG(ERR, "Error event");
    1807                 :          0 :                 return;
    1808                 :            :         }
    1809                 :            : 
    1810      [ #  #  # ]:          0 :         switch (cpchnl2_event->header.type) {
    1811                 :          0 :         case CPCHNL2_EVENT_VPORT_CREATED:
    1812                 :          0 :                 vport_identity.vport_id = cpchnl2_event->data.vport_created.vport.vport_id;
    1813                 :          0 :                 vport_created = &cpchnl2_event->data.vport_created;
    1814                 :          0 :                 vport_identity.func_type = vport_created->info.func_type;
    1815                 :          0 :                 vport_identity.pf_id = vport_created->info.pf_id;
    1816                 :          0 :                 vport_identity.vf_id = vport_created->info.vf_id;
    1817         [ #  # ]:          0 :                 if (cpfl_vport_info_create(adapter, &vport_identity, vport_created))
    1818                 :          0 :                         PMD_DRV_LOG(WARNING, "Failed to handle CPCHNL2_EVENT_VPORT_CREATED");
    1819                 :            :                 break;
    1820                 :          0 :         case CPCHNL2_EVENT_VPORT_DESTROYED:
    1821                 :          0 :                 vport_identity.vport_id = cpchnl2_event->data.vport_destroyed.vport.vport_id;
    1822                 :          0 :                 vport_identity.func_type = cpchnl2_event->data.vport_destroyed.func.func_type;
    1823                 :          0 :                 vport_identity.pf_id = cpchnl2_event->data.vport_destroyed.func.pf_id;
    1824                 :          0 :                 vport_identity.vf_id = cpchnl2_event->data.vport_destroyed.func.vf_id;
    1825         [ #  # ]:          0 :                 if (cpfl_vport_info_destroy(adapter, &vport_identity))
    1826                 :          0 :                         PMD_DRV_LOG(WARNING, "Failed to handle CPCHNL2_EVENT_VPORT_DESTROY");
    1827                 :            :                 break;
    1828                 :          0 :         default:
    1829                 :          0 :                 PMD_DRV_LOG(ERR, " unknown event received %u", cpchnl2_event->header.type);
    1830                 :          0 :                 break;
    1831                 :            :         }
    1832                 :            : }
    1833                 :            : 
    1834                 :            : static void
    1835                 :          0 : cpfl_handle_virtchnl_msg(struct cpfl_adapter_ext *adapter)
    1836                 :            : {
    1837                 :            :         struct idpf_adapter *base = &adapter->base;
    1838                 :          0 :         struct idpf_dma_mem *dma_mem = NULL;
    1839                 :          0 :         struct idpf_hw *hw = &base->hw;
    1840                 :            :         struct idpf_ctlq_msg ctlq_msg;
    1841                 :            :         enum idpf_mbx_opc mbx_op;
    1842                 :          0 :         uint16_t pending = 1;
    1843                 :            :         uint32_t vc_op;
    1844                 :            :         int ret;
    1845                 :            : 
    1846         [ #  # ]:          0 :         while (pending) {
    1847                 :          0 :                 ret = idpf_vc_ctlq_recv(hw->arq, &pending, &ctlq_msg);
    1848         [ #  # ]:          0 :                 if (ret) {
    1849                 :          0 :                         PMD_DRV_LOG(INFO, "Failed to read msg from virtual channel, ret: %d", ret);
    1850                 :          0 :                         return;
    1851                 :            :                 }
    1852                 :            : 
    1853         [ #  # ]:          0 :                 memcpy(base->mbx_resp, ctlq_msg.ctx.indirect.payload->va,
    1854                 :            :                            IDPF_DFLT_MBX_BUF_SIZE);
    1855                 :            : 
    1856                 :          0 :                 mbx_op = rte_le_to_cpu_16(ctlq_msg.opcode);
    1857                 :          0 :                 vc_op = rte_le_to_cpu_32(ctlq_msg.cookie.mbx.chnl_opcode);
    1858                 :          0 :                 base->cmd_retval = rte_le_to_cpu_32(ctlq_msg.cookie.mbx.chnl_retval);
    1859                 :            : 
    1860         [ #  # ]:          0 :                 switch (mbx_op) {
    1861                 :          0 :                 case idpf_mbq_opc_send_msg_to_peer_pf:
    1862         [ #  # ]:          0 :                         if (vc_op == VIRTCHNL2_OP_EVENT) {
    1863                 :          0 :                                 cpfl_handle_vchnl_event_msg(adapter, adapter->base.mbx_resp,
    1864                 :          0 :                                                             ctlq_msg.data_len);
    1865         [ #  # ]:          0 :                         } else if (vc_op == CPCHNL2_OP_EVENT) {
    1866                 :          0 :                                 cpfl_handle_cpchnl_event_msg(adapter, adapter->base.mbx_resp,
    1867                 :          0 :                                                              ctlq_msg.data_len);
    1868                 :            :                         } else {
    1869         [ #  # ]:          0 :                                 if (vc_op == base->pend_cmd)
    1870                 :            :                                         notify_cmd(base, base->cmd_retval);
    1871                 :            :                                 else
    1872                 :          0 :                                         PMD_DRV_LOG(ERR, "command mismatch, expect %u, get %u",
    1873                 :            :                                                     base->pend_cmd, vc_op);
    1874                 :            : 
    1875                 :          0 :                                 PMD_DRV_LOG(DEBUG, " Virtual channel response is received,"
    1876                 :            :                                             "opcode = %d", vc_op);
    1877                 :            :                         }
    1878                 :          0 :                         goto post_buf;
    1879                 :          0 :                 default:
    1880                 :          0 :                         PMD_DRV_LOG(DEBUG, "Request %u is not supported yet", mbx_op);
    1881                 :            :                 }
    1882                 :            :         }
    1883                 :            : 
    1884                 :          0 : post_buf:
    1885         [ #  # ]:          0 :         if (ctlq_msg.data_len)
    1886                 :          0 :                 dma_mem = ctlq_msg.ctx.indirect.payload;
    1887                 :            :         else
    1888                 :          0 :                 pending = 0;
    1889                 :            : 
    1890                 :          0 :         ret = idpf_vc_ctlq_post_rx_buffs(hw, hw->arq, &pending, &dma_mem);
    1891   [ #  #  #  # ]:          0 :         if (ret && dma_mem)
    1892                 :            :                 idpf_free_dma_mem(hw, dma_mem);
    1893                 :            : }
    1894                 :            : 
    1895                 :            : static void
    1896                 :          0 : cpfl_dev_alarm_handler(void *param)
    1897                 :            : {
    1898                 :            :         struct cpfl_adapter_ext *adapter = param;
    1899                 :            : 
    1900                 :          0 :         cpfl_handle_virtchnl_msg(adapter);
    1901                 :            : 
    1902                 :          0 :         rte_eal_alarm_set(CPFL_ALARM_INTERVAL, cpfl_dev_alarm_handler, adapter);
    1903                 :          0 : }
    1904                 :            : 
    1905                 :            : static int
    1906                 :          0 : cpfl_stop_cfgqs(struct cpfl_adapter_ext *adapter)
    1907                 :            : {
    1908                 :            :         int i, ret;
    1909                 :            : 
    1910         [ #  # ]:          0 :         for (i = 0; i < CPFL_TX_CFGQ_NUM; i++) {
    1911                 :          0 :                 ret = idpf_vc_queue_switch(&adapter->ctrl_vport.base, i, false, false,
    1912                 :            :                                                                 VIRTCHNL2_QUEUE_TYPE_CONFIG_TX);
    1913         [ #  # ]:          0 :                 if (ret) {
    1914                 :          0 :                         PMD_DRV_LOG(ERR, "Fail to disable Tx config queue.");
    1915                 :          0 :                         return ret;
    1916                 :            :                 }
    1917                 :            :         }
    1918                 :            : 
    1919         [ #  # ]:          0 :         for (i = 0; i < CPFL_RX_CFGQ_NUM; i++) {
    1920                 :          0 :                 ret = idpf_vc_queue_switch(&adapter->ctrl_vport.base, i, true, false,
    1921                 :            :                                                                 VIRTCHNL2_QUEUE_TYPE_CONFIG_RX);
    1922         [ #  # ]:          0 :                 if (ret) {
    1923                 :          0 :                         PMD_DRV_LOG(ERR, "Fail to disable Rx config queue.");
    1924                 :          0 :                         return ret;
    1925                 :            :                 }
    1926                 :            :         }
    1927                 :            : 
    1928                 :            :         return 0;
    1929                 :            : }
    1930                 :            : 
    1931                 :            : static int
    1932                 :          0 : cpfl_start_cfgqs(struct cpfl_adapter_ext *adapter)
    1933                 :            : {
    1934                 :            :         int i, ret;
    1935                 :            : 
    1936                 :          0 :         ret = cpfl_config_ctlq_tx(adapter);
    1937         [ #  # ]:          0 :         if (ret) {
    1938                 :          0 :                 PMD_DRV_LOG(ERR, "Fail to configure Tx config queue.");
    1939                 :          0 :                 return ret;
    1940                 :            :         }
    1941                 :            : 
    1942                 :          0 :         ret = cpfl_config_ctlq_rx(adapter);
    1943         [ #  # ]:          0 :         if (ret) {
    1944                 :          0 :                 PMD_DRV_LOG(ERR, "Fail to configure Rx config queue.");
    1945                 :          0 :                 return ret;
    1946                 :            :         }
    1947                 :            : 
    1948         [ #  # ]:          0 :         for (i = 0; i < CPFL_TX_CFGQ_NUM; i++) {
    1949                 :          0 :                 ret = idpf_vc_queue_switch(&adapter->ctrl_vport.base, i, false, true,
    1950                 :            :                                                                 VIRTCHNL2_QUEUE_TYPE_CONFIG_TX);
    1951         [ #  # ]:          0 :                 if (ret) {
    1952                 :          0 :                         PMD_DRV_LOG(ERR, "Fail to enable Tx config queue.");
    1953                 :          0 :                         return ret;
    1954                 :            :                 }
    1955                 :            :         }
    1956                 :            : 
    1957         [ #  # ]:          0 :         for (i = 0; i < CPFL_RX_CFGQ_NUM; i++) {
    1958                 :          0 :                 ret = idpf_vc_queue_switch(&adapter->ctrl_vport.base, i, true, true,
    1959                 :            :                                                                 VIRTCHNL2_QUEUE_TYPE_CONFIG_RX);
    1960         [ #  # ]:          0 :                 if (ret) {
    1961                 :          0 :                         PMD_DRV_LOG(ERR, "Fail to enable Rx config queue.");
    1962                 :          0 :                         return ret;
    1963                 :            :                 }
    1964                 :            :         }
    1965                 :            : 
    1966                 :            :         return 0;
    1967                 :            : }
    1968                 :            : 
    1969                 :            : static void
    1970                 :          0 : cpfl_remove_cfgqs(struct cpfl_adapter_ext *adapter)
    1971                 :            : {
    1972                 :          0 :         struct idpf_hw *hw = (struct idpf_hw *)(&adapter->base.hw);
    1973                 :            :         struct cpfl_ctlq_create_info *create_cfgq_info;
    1974                 :            :         int i;
    1975                 :            : 
    1976                 :          0 :         create_cfgq_info = adapter->cfgq_info;
    1977                 :            : 
    1978         [ #  # ]:          0 :         for (i = 0; i < CPFL_CFGQ_NUM; i++) {
    1979         [ #  # ]:          0 :                 if (adapter->ctlqp[i])
    1980                 :          0 :                         cpfl_vport_ctlq_remove(hw, adapter->ctlqp[i]);
    1981         [ #  # ]:          0 :                 if (create_cfgq_info[i].ring_mem.va)
    1982                 :            :                         idpf_free_dma_mem(&adapter->base.hw, &create_cfgq_info[i].ring_mem);
    1983         [ #  # ]:          0 :                 if (create_cfgq_info[i].buf_mem.va)
    1984                 :            :                         idpf_free_dma_mem(&adapter->base.hw, &create_cfgq_info[i].buf_mem);
    1985                 :            :         }
    1986                 :          0 : }
    1987                 :            : 
    1988                 :            : static int
    1989                 :          0 : cpfl_add_cfgqs(struct cpfl_adapter_ext *adapter)
    1990                 :            : {
    1991                 :            :         struct idpf_ctlq_info *cfg_cq;
    1992                 :            :         int ret = 0;
    1993                 :            :         int i = 0;
    1994                 :            : 
    1995         [ #  # ]:          0 :         for (i = 0; i < CPFL_CFGQ_NUM; i++) {
    1996                 :          0 :                 cfg_cq = NULL;
    1997                 :          0 :                 ret = cpfl_vport_ctlq_add((struct idpf_hw *)(&adapter->base.hw),
    1998                 :            :                                           &adapter->cfgq_info[i],
    1999                 :            :                                           &cfg_cq);
    2000   [ #  #  #  # ]:          0 :                 if (ret || !cfg_cq) {
    2001                 :          0 :                         PMD_DRV_LOG(ERR, "ctlq add failed for queue id: %d",
    2002                 :            :                                     adapter->cfgq_info[i].id);
    2003                 :          0 :                         cpfl_remove_cfgqs(adapter);
    2004                 :          0 :                         return ret;
    2005                 :            :                 }
    2006                 :          0 :                 PMD_DRV_LOG(INFO, "added cfgq to hw. queue id: %d",
    2007                 :            :                             adapter->cfgq_info[i].id);
    2008                 :          0 :                 adapter->ctlqp[i] = cfg_cq;
    2009                 :            :         }
    2010                 :            : 
    2011                 :            :         return ret;
    2012                 :            : }
    2013                 :            : 
    2014                 :            : #define CPFL_CFGQ_RING_LEN              512
    2015                 :            : #define CPFL_CFGQ_DESCRIPTOR_SIZE       32
    2016                 :            : #define CPFL_CFGQ_BUFFER_SIZE           256
    2017                 :            : #define CPFL_CFGQ_RING_SIZE             512
    2018                 :            : 
    2019                 :            : static int
    2020                 :          0 : cpfl_cfgq_setup(struct cpfl_adapter_ext *adapter)
    2021                 :            : {
    2022                 :            :         struct cpfl_ctlq_create_info *create_cfgq_info;
    2023                 :            :         struct cpfl_vport *vport;
    2024                 :            :         int i, err;
    2025                 :            :         uint32_t ring_size = CPFL_CFGQ_RING_SIZE * sizeof(struct idpf_ctlq_desc);
    2026                 :            :         uint32_t buf_size = CPFL_CFGQ_RING_SIZE * CPFL_CFGQ_BUFFER_SIZE;
    2027                 :            : 
    2028                 :            :         vport = &adapter->ctrl_vport;
    2029                 :          0 :         create_cfgq_info = adapter->cfgq_info;
    2030                 :            : 
    2031         [ #  # ]:          0 :         for (i = 0; i < CPFL_CFGQ_NUM; i++) {
    2032         [ #  # ]:          0 :                 if (i % 2 == 0) {
    2033                 :            :                         /* Setup Tx config queue */
    2034                 :          0 :                         create_cfgq_info[i].id = vport->base.chunks_info.tx_start_qid + i / 2;
    2035                 :          0 :                         create_cfgq_info[i].type = IDPF_CTLQ_TYPE_CONFIG_TX;
    2036                 :          0 :                         create_cfgq_info[i].len = CPFL_CFGQ_RING_SIZE;
    2037                 :          0 :                         create_cfgq_info[i].buf_size = CPFL_CFGQ_BUFFER_SIZE;
    2038                 :          0 :                         memset(&create_cfgq_info[i].reg, 0, sizeof(struct idpf_ctlq_reg));
    2039                 :          0 :                         create_cfgq_info[i].reg.tail = vport->base.chunks_info.tx_qtail_start +
    2040                 :          0 :                                 i / 2 * vport->base.chunks_info.tx_qtail_spacing;
    2041                 :            :                 } else {
    2042                 :            :                         /* Setup Rx config queue */
    2043                 :          0 :                         create_cfgq_info[i].id = vport->base.chunks_info.rx_start_qid + i / 2;
    2044                 :          0 :                         create_cfgq_info[i].type = IDPF_CTLQ_TYPE_CONFIG_RX;
    2045                 :          0 :                         create_cfgq_info[i].len = CPFL_CFGQ_RING_SIZE;
    2046                 :          0 :                         create_cfgq_info[i].buf_size = CPFL_CFGQ_BUFFER_SIZE;
    2047                 :          0 :                         memset(&create_cfgq_info[i].reg, 0, sizeof(struct idpf_ctlq_reg));
    2048                 :          0 :                         create_cfgq_info[i].reg.tail = vport->base.chunks_info.rx_qtail_start +
    2049                 :          0 :                                 i / 2 * vport->base.chunks_info.rx_qtail_spacing;
    2050         [ #  # ]:          0 :                         if (!idpf_alloc_dma_mem(&adapter->base.hw, &create_cfgq_info[i].buf_mem,
    2051                 :            :                                                 buf_size)) {
    2052                 :            :                                 err = -ENOMEM;
    2053                 :          0 :                                 goto free_mem;
    2054                 :            :                         }
    2055                 :            :                 }
    2056         [ #  # ]:          0 :                 if (!idpf_alloc_dma_mem(&adapter->base.hw, &create_cfgq_info[i].ring_mem,
    2057                 :            :                                         ring_size)) {
    2058                 :            :                         err = -ENOMEM;
    2059                 :          0 :                         goto free_mem;
    2060                 :            :                 }
    2061                 :            :         }
    2062                 :            :         return 0;
    2063                 :            : free_mem:
    2064         [ #  # ]:          0 :         for (i = 0; i < CPFL_CFGQ_NUM; i++) {
    2065         [ #  # ]:          0 :                 if (create_cfgq_info[i].ring_mem.va)
    2066                 :            :                         idpf_free_dma_mem(&adapter->base.hw, &create_cfgq_info[i].ring_mem);
    2067         [ #  # ]:          0 :                 if (create_cfgq_info[i].buf_mem.va)
    2068                 :            :                         idpf_free_dma_mem(&adapter->base.hw, &create_cfgq_info[i].buf_mem);
    2069                 :            :         }
    2070                 :            :         return err;
    2071                 :            : }
    2072                 :            : 
    2073                 :            : static int
    2074                 :          0 : cpfl_init_ctrl_vport(struct cpfl_adapter_ext *adapter)
    2075                 :            : {
    2076                 :            :         struct cpfl_vport *vport = &adapter->ctrl_vport;
    2077                 :            :         struct virtchnl2_create_vport *vport_info =
    2078                 :            :                 (struct virtchnl2_create_vport *)adapter->ctrl_vport_recv_info;
    2079                 :            :         int i;
    2080                 :            : 
    2081                 :          0 :         vport->itf.adapter = adapter;
    2082                 :          0 :         vport->base.adapter = &adapter->base;
    2083                 :          0 :         vport->base.vport_id = vport_info->vport_id;
    2084                 :            : 
    2085         [ #  # ]:          0 :         for (i = 0; i < vport_info->chunks.num_chunks; i++) {
    2086         [ #  # ]:          0 :                 if (vport_info->chunks.chunks[i].type == VIRTCHNL2_QUEUE_TYPE_TX) {
    2087                 :          0 :                         vport->base.chunks_info.tx_start_qid =
    2088                 :          0 :                                 vport_info->chunks.chunks[i].start_queue_id;
    2089                 :          0 :                         vport->base.chunks_info.tx_qtail_start =
    2090                 :          0 :                         vport_info->chunks.chunks[i].qtail_reg_start;
    2091                 :          0 :                         vport->base.chunks_info.tx_qtail_spacing =
    2092                 :          0 :                         vport_info->chunks.chunks[i].qtail_reg_spacing;
    2093         [ #  # ]:          0 :                 } else if (vport_info->chunks.chunks[i].type == VIRTCHNL2_QUEUE_TYPE_RX) {
    2094                 :          0 :                         vport->base.chunks_info.rx_start_qid =
    2095                 :          0 :                                 vport_info->chunks.chunks[i].start_queue_id;
    2096                 :          0 :                         vport->base.chunks_info.rx_qtail_start =
    2097                 :          0 :                         vport_info->chunks.chunks[i].qtail_reg_start;
    2098                 :          0 :                         vport->base.chunks_info.rx_qtail_spacing =
    2099                 :          0 :                         vport_info->chunks.chunks[i].qtail_reg_spacing;
    2100                 :            :                 } else {
    2101                 :          0 :                         PMD_INIT_LOG(ERR, "Unsupported chunk type");
    2102                 :          0 :                         return -EINVAL;
    2103                 :            :                 }
    2104                 :            :         }
    2105                 :            : 
    2106                 :            :         return 0;
    2107                 :            : }
    2108                 :            : 
    2109                 :            : static void
    2110                 :          0 : cpfl_ctrl_path_close(struct cpfl_adapter_ext *adapter)
    2111                 :            : {
    2112                 :          0 :         cpfl_stop_cfgqs(adapter);
    2113                 :          0 :         cpfl_remove_cfgqs(adapter);
    2114                 :          0 :         idpf_vc_vport_destroy(&adapter->ctrl_vport.base);
    2115                 :          0 : }
    2116                 :            : 
    2117                 :            : static int
    2118                 :          0 : cpfl_ctrl_path_open(struct cpfl_adapter_ext *adapter)
    2119                 :            : {
    2120                 :            :         int ret;
    2121                 :            : 
    2122                 :          0 :         ret = cpfl_vc_create_ctrl_vport(adapter);
    2123         [ #  # ]:          0 :         if (ret) {
    2124                 :          0 :                 PMD_INIT_LOG(ERR, "Failed to create control vport");
    2125                 :          0 :                 return ret;
    2126                 :            :         }
    2127                 :            : 
    2128                 :          0 :         ret = cpfl_init_ctrl_vport(adapter);
    2129         [ #  # ]:          0 :         if (ret) {
    2130                 :          0 :                 PMD_INIT_LOG(ERR, "Failed to init control vport");
    2131                 :          0 :                 goto err_init_ctrl_vport;
    2132                 :            :         }
    2133                 :            : 
    2134                 :          0 :         ret = cpfl_cfgq_setup(adapter);
    2135         [ #  # ]:          0 :         if (ret) {
    2136                 :          0 :                 PMD_INIT_LOG(ERR, "Failed to setup control queues");
    2137                 :          0 :                 goto err_cfgq_setup;
    2138                 :            :         }
    2139                 :            : 
    2140                 :          0 :         ret = cpfl_add_cfgqs(adapter);
    2141         [ #  # ]:          0 :         if (ret) {
    2142                 :          0 :                 PMD_INIT_LOG(ERR, "Failed to add control queues");
    2143                 :          0 :                 goto err_add_cfgq;
    2144                 :            :         }
    2145                 :            : 
    2146                 :          0 :         ret = cpfl_start_cfgqs(adapter);
    2147         [ #  # ]:          0 :         if (ret) {
    2148                 :          0 :                 PMD_INIT_LOG(ERR, "Failed to start control queues");
    2149                 :          0 :                 goto err_start_cfgqs;
    2150                 :            :         }
    2151                 :            : 
    2152                 :            :         return 0;
    2153                 :            : 
    2154                 :            : err_start_cfgqs:
    2155                 :          0 :         cpfl_stop_cfgqs(adapter);
    2156                 :          0 : err_add_cfgq:
    2157                 :          0 :         cpfl_remove_cfgqs(adapter);
    2158                 :          0 : err_cfgq_setup:
    2159                 :          0 : err_init_ctrl_vport:
    2160                 :          0 :         idpf_vc_vport_destroy(&adapter->ctrl_vport.base);
    2161                 :            : 
    2162                 :          0 :         return ret;
    2163                 :            : }
    2164                 :            : 
    2165                 :            : static struct virtchnl2_get_capabilities req_caps = {
    2166                 :            :         .csum_caps =
    2167                 :            :         VIRTCHNL2_CAP_TX_CSUM_L3_IPV4          |
    2168                 :            :         VIRTCHNL2_CAP_TX_CSUM_L4_IPV4_TCP      |
    2169                 :            :         VIRTCHNL2_CAP_TX_CSUM_L4_IPV4_UDP      |
    2170                 :            :         VIRTCHNL2_CAP_TX_CSUM_L4_IPV4_SCTP     |
    2171                 :            :         VIRTCHNL2_CAP_TX_CSUM_L4_IPV6_TCP      |
    2172                 :            :         VIRTCHNL2_CAP_TX_CSUM_L4_IPV6_UDP      |
    2173                 :            :         VIRTCHNL2_CAP_TX_CSUM_L4_IPV6_SCTP     |
    2174                 :            :         VIRTCHNL2_CAP_TX_CSUM_GENERIC          |
    2175                 :            :         VIRTCHNL2_CAP_RX_CSUM_L3_IPV4          |
    2176                 :            :         VIRTCHNL2_CAP_RX_CSUM_L4_IPV4_TCP      |
    2177                 :            :         VIRTCHNL2_CAP_RX_CSUM_L4_IPV4_UDP      |
    2178                 :            :         VIRTCHNL2_CAP_RX_CSUM_L4_IPV4_SCTP     |
    2179                 :            :         VIRTCHNL2_CAP_RX_CSUM_L4_IPV6_TCP      |
    2180                 :            :         VIRTCHNL2_CAP_RX_CSUM_L4_IPV6_UDP      |
    2181                 :            :         VIRTCHNL2_CAP_RX_CSUM_L4_IPV6_SCTP     |
    2182                 :            :         VIRTCHNL2_CAP_RX_CSUM_GENERIC,
    2183                 :            : 
    2184                 :            :         .rss_caps =
    2185                 :            :         VIRTCHNL2_CAP_RSS_IPV4_TCP             |
    2186                 :            :         VIRTCHNL2_CAP_RSS_IPV4_UDP             |
    2187                 :            :         VIRTCHNL2_CAP_RSS_IPV4_SCTP            |
    2188                 :            :         VIRTCHNL2_CAP_RSS_IPV4_OTHER           |
    2189                 :            :         VIRTCHNL2_CAP_RSS_IPV6_TCP             |
    2190                 :            :         VIRTCHNL2_CAP_RSS_IPV6_UDP             |
    2191                 :            :         VIRTCHNL2_CAP_RSS_IPV6_SCTP            |
    2192                 :            :         VIRTCHNL2_CAP_RSS_IPV6_OTHER           |
    2193                 :            :         VIRTCHNL2_CAP_RSS_IPV4_AH              |
    2194                 :            :         VIRTCHNL2_CAP_RSS_IPV4_ESP             |
    2195                 :            :         VIRTCHNL2_CAP_RSS_IPV4_AH_ESP          |
    2196                 :            :         VIRTCHNL2_CAP_RSS_IPV6_AH              |
    2197                 :            :         VIRTCHNL2_CAP_RSS_IPV6_ESP             |
    2198                 :            :         VIRTCHNL2_CAP_RSS_IPV6_AH_ESP,
    2199                 :            : 
    2200                 :            :         .other_caps = VIRTCHNL2_CAP_WB_ON_ITR
    2201                 :            : };
    2202                 :            : 
    2203                 :            : static int
    2204                 :          0 : cpfl_vport_map_init(struct cpfl_adapter_ext *adapter)
    2205                 :            : {
    2206                 :            :         char hname[32];
    2207                 :            : 
    2208                 :          0 :         snprintf(hname, 32, "%s-vport", adapter->name);
    2209                 :            : 
    2210                 :            :         rte_spinlock_init(&adapter->vport_map_lock);
    2211                 :            : 
    2212                 :            : #define CPFL_VPORT_MAP_HASH_ENTRY_NUM 2048
    2213                 :            : 
    2214                 :          0 :         struct rte_hash_parameters params = {
    2215                 :            :                 .name = adapter->name,
    2216                 :            :                 .entries = CPFL_VPORT_MAP_HASH_ENTRY_NUM,
    2217                 :            :                 .key_len = sizeof(struct cpfl_vport_id),
    2218                 :            :                 .hash_func = rte_hash_crc,
    2219                 :            :                 .socket_id = SOCKET_ID_ANY,
    2220                 :            :         };
    2221                 :            : 
    2222                 :          0 :         adapter->vport_map_hash = rte_hash_create(&params);
    2223                 :            : 
    2224         [ #  # ]:          0 :         if (adapter->vport_map_hash == NULL) {
    2225                 :          0 :                 PMD_INIT_LOG(ERR, "Failed to create vport map hash");
    2226                 :          0 :                 return -EINVAL;
    2227                 :            :         }
    2228                 :            : 
    2229                 :            :         return 0;
    2230                 :            : }
    2231                 :            : 
    2232                 :            : static void
    2233                 :          0 : cpfl_vport_map_uninit(struct cpfl_adapter_ext *adapter)
    2234                 :            : {
    2235                 :          0 :         const void *key = NULL;
    2236                 :            :         struct cpfl_vport_map_info *info;
    2237                 :          0 :         uint32_t iter = 0;
    2238                 :            : 
    2239         [ #  # ]:          0 :         while (rte_hash_iterate(adapter->vport_map_hash, &key, (void **)&info, &iter) >= 0)
    2240                 :          0 :                 rte_free(info);
    2241                 :            : 
    2242                 :          0 :         rte_hash_free(adapter->vport_map_hash);
    2243                 :          0 : }
    2244                 :            : 
    2245                 :            : static int
    2246                 :          0 : cpfl_repr_allowlist_init(struct cpfl_adapter_ext *adapter)
    2247                 :            : {
    2248                 :            :         char hname[32];
    2249                 :            : 
    2250                 :          0 :         snprintf(hname, 32, "%s-repr_al", adapter->name);
    2251                 :            : 
    2252                 :            :         rte_spinlock_init(&adapter->repr_lock);
    2253                 :            : 
    2254                 :            : #define CPFL_REPR_HASH_ENTRY_NUM 2048
    2255                 :            : 
    2256                 :          0 :         struct rte_hash_parameters params = {
    2257                 :            :                 .name = hname,
    2258                 :            :                 .entries = CPFL_REPR_HASH_ENTRY_NUM,
    2259                 :            :                 .key_len = sizeof(struct cpfl_repr_id),
    2260                 :            :                 .hash_func = rte_hash_crc,
    2261                 :            :                 .socket_id = SOCKET_ID_ANY,
    2262                 :            :         };
    2263                 :            : 
    2264                 :          0 :         adapter->repr_allowlist_hash = rte_hash_create(&params);
    2265                 :            : 
    2266         [ #  # ]:          0 :         if (adapter->repr_allowlist_hash == NULL) {
    2267                 :          0 :                 PMD_INIT_LOG(ERR, "Failed to create repr allowlist hash");
    2268                 :          0 :                 return -EINVAL;
    2269                 :            :         }
    2270                 :            : 
    2271                 :            :         return 0;
    2272                 :            : }
    2273                 :            : 
    2274                 :            : static void
    2275                 :            : cpfl_repr_allowlist_uninit(struct cpfl_adapter_ext *adapter)
    2276                 :            : {
    2277                 :          0 :         rte_hash_free(adapter->repr_allowlist_hash);
    2278                 :          0 : }
    2279                 :            : 
    2280                 :            : static uint8_t
    2281                 :          0 : get_running_host_id(void)
    2282                 :            : {
    2283                 :            :         struct utsname unamedata;
    2284                 :            :         uint8_t host_id = CPFL_INVALID_HOST_ID;
    2285                 :            : 
    2286         [ #  # ]:          0 :         if (uname(&unamedata) != 0)
    2287                 :          0 :                 PMD_INIT_LOG(ERR, "Cannot fetch node_name for host");
    2288         [ #  # ]:          0 :         else if (strstr(unamedata.nodename, "ipu-imc"))
    2289                 :          0 :                 PMD_INIT_LOG(ERR, "CPFL PMD cannot be running on IMC.");
    2290         [ #  # ]:          0 :         else if (strstr(unamedata.nodename, "ipu-acc"))
    2291                 :            :                 host_id = CPFL_HOST_ID_ACC;
    2292                 :            :         else
    2293                 :            :                 host_id = CPFL_HOST_ID_HOST;
    2294                 :            : 
    2295                 :          0 :         return host_id;
    2296                 :            : }
    2297                 :            : 
    2298                 :            : static int
    2299                 :          0 : cpfl_adapter_ext_init(struct rte_pci_device *pci_dev, struct cpfl_adapter_ext *adapter,
    2300                 :            :                       struct cpfl_devargs *devargs)
    2301                 :            : {
    2302                 :          0 :         struct idpf_adapter *base = &adapter->base;
    2303                 :            :         struct idpf_hw *hw = &base->hw;
    2304                 :            :         int ret = 0;
    2305                 :            : 
    2306                 :            : #ifndef RTE_HAS_JANSSON
    2307                 :            :         RTE_SET_USED(devargs);
    2308                 :            : #endif
    2309                 :            : 
    2310                 :          0 :         hw->hw_addr = (void *)pci_dev->mem_resource[0].addr;
    2311                 :          0 :         hw->hw_addr_len = pci_dev->mem_resource[0].len;
    2312                 :          0 :         hw->back = base;
    2313                 :          0 :         hw->vendor_id = pci_dev->id.vendor_id;
    2314                 :          0 :         hw->device_id = pci_dev->id.device_id;
    2315                 :          0 :         hw->subsystem_vendor_id = pci_dev->id.subsystem_vendor_id;
    2316                 :          0 :         adapter->host_id = get_running_host_id();
    2317                 :            : 
    2318         [ #  # ]:          0 :         strncpy(adapter->name, pci_dev->device.name, PCI_PRI_STR_SIZE);
    2319                 :            : 
    2320         [ #  # ]:          0 :         rte_memcpy(&base->caps, &req_caps, sizeof(struct virtchnl2_get_capabilities));
    2321                 :            : 
    2322                 :          0 :         ret = idpf_adapter_init(base);
    2323         [ #  # ]:          0 :         if (ret != 0) {
    2324                 :          0 :                 PMD_INIT_LOG(ERR, "Failed to init adapter");
    2325                 :          0 :                 goto err_adapter_init;
    2326                 :            :         }
    2327                 :            : 
    2328                 :          0 :         ret = cpfl_vport_map_init(adapter);
    2329         [ #  # ]:          0 :         if (ret) {
    2330                 :          0 :                 PMD_INIT_LOG(ERR, "Failed to init vport map");
    2331                 :          0 :                 goto err_vport_map_init;
    2332                 :            :         }
    2333                 :            : 
    2334                 :          0 :         ret = cpfl_repr_allowlist_init(adapter);
    2335         [ #  # ]:          0 :         if (ret) {
    2336                 :          0 :                 PMD_INIT_LOG(ERR, "Failed to init representor allowlist");
    2337                 :          0 :                 goto err_repr_allowlist_init;
    2338                 :            :         }
    2339                 :            : 
    2340                 :          0 :         rte_eal_alarm_set(CPFL_ALARM_INTERVAL, cpfl_dev_alarm_handler, adapter);
    2341                 :            : 
    2342                 :          0 :         adapter->max_vport_nb = adapter->base.caps.max_vports > CPFL_MAX_VPORT_NUM ?
    2343                 :          0 :                                 CPFL_MAX_VPORT_NUM : adapter->base.caps.max_vports;
    2344                 :            : 
    2345                 :          0 :         adapter->vports = rte_zmalloc("vports",
    2346                 :          0 :                                       adapter->max_vport_nb *
    2347                 :            :                                       sizeof(*adapter->vports),
    2348                 :            :                                       0);
    2349         [ #  # ]:          0 :         if (adapter->vports == NULL) {
    2350                 :          0 :                 PMD_INIT_LOG(ERR, "Failed to allocate vports memory");
    2351                 :            :                 ret = -ENOMEM;
    2352                 :          0 :                 goto err_vports_alloc;
    2353                 :            :         }
    2354                 :            : 
    2355                 :          0 :         ret = cpfl_ctrl_path_open(adapter);
    2356         [ #  # ]:          0 :         if (ret) {
    2357                 :          0 :                 PMD_INIT_LOG(ERR, "Failed to setup control path");
    2358                 :          0 :                 goto err_create_ctrl_vport;
    2359                 :            :         }
    2360                 :            : 
    2361                 :            : #ifdef RTE_HAS_JANSSON
    2362                 :          0 :         ret = cpfl_flow_init(adapter, devargs);
    2363         [ #  # ]:          0 :         if (ret) {
    2364                 :          0 :                 PMD_INIT_LOG(ERR, "Failed to init flow module");
    2365                 :          0 :                 goto err_flow_init;
    2366                 :            :         }
    2367                 :            : #endif
    2368                 :          0 :         adapter->cur_vports = 0;
    2369                 :          0 :         adapter->cur_vport_nb = 0;
    2370                 :            : 
    2371                 :          0 :         adapter->used_vecs_num = 0;
    2372                 :            : 
    2373                 :          0 :         return ret;
    2374                 :            : 
    2375                 :            : #ifdef RTE_HAS_JANSSON
    2376                 :            : err_flow_init:
    2377                 :          0 :         cpfl_ctrl_path_close(adapter);
    2378                 :            : #endif
    2379                 :          0 : err_create_ctrl_vport:
    2380                 :          0 :         rte_free(adapter->vports);
    2381                 :          0 : err_vports_alloc:
    2382                 :          0 :         rte_eal_alarm_cancel(cpfl_dev_alarm_handler, adapter);
    2383                 :            :         cpfl_repr_allowlist_uninit(adapter);
    2384                 :          0 : err_repr_allowlist_init:
    2385                 :          0 :         cpfl_vport_map_uninit(adapter);
    2386                 :          0 : err_vport_map_init:
    2387                 :          0 :         idpf_adapter_deinit(base);
    2388                 :            : err_adapter_init:
    2389                 :            :         return ret;
    2390                 :            : }
    2391                 :            : 
    2392                 :            : static uint16_t
    2393                 :            : cpfl_vport_idx_alloc(struct cpfl_adapter_ext *adapter)
    2394                 :            : {
    2395                 :            :         uint16_t vport_idx;
    2396                 :            :         uint16_t i;
    2397                 :            : 
    2398         [ #  # ]:          0 :         for (i = 0; i < adapter->max_vport_nb; i++) {
    2399         [ #  # ]:          0 :                 if (adapter->vports[i] == NULL)
    2400                 :            :                         break;
    2401                 :            :         }
    2402                 :            : 
    2403         [ #  # ]:          0 :         if (i == adapter->max_vport_nb)
    2404                 :            :                 vport_idx = CPFL_INVALID_VPORT_IDX;
    2405                 :            :         else
    2406                 :            :                 vport_idx = i;
    2407                 :            : 
    2408                 :            :         return vport_idx;
    2409                 :            : }
    2410                 :            : 
    2411                 :            : static int
    2412                 :          0 : cpfl_p2p_q_grps_add(struct idpf_vport *vport,
    2413                 :            :                     struct virtchnl2_add_queue_groups *p2p_queue_grps_info,
    2414                 :            :                     uint8_t *p2p_q_vc_out_info)
    2415                 :            : {
    2416                 :            :         int ret;
    2417                 :            : 
    2418                 :          0 :         p2p_queue_grps_info->vport_id = vport->vport_id;
    2419                 :          0 :         p2p_queue_grps_info->num_queue_groups = CPFL_P2P_NB_QUEUE_GRPS;
    2420                 :          0 :         p2p_queue_grps_info->groups[0].num_rx_q = CPFL_MAX_P2P_NB_QUEUES;
    2421                 :          0 :         p2p_queue_grps_info->groups[0].num_rx_bufq = CPFL_P2P_NB_RX_BUFQ;
    2422                 :          0 :         p2p_queue_grps_info->groups[0].num_tx_q = CPFL_MAX_P2P_NB_QUEUES;
    2423                 :          0 :         p2p_queue_grps_info->groups[0].num_tx_complq = CPFL_P2P_NB_TX_COMPLQ;
    2424                 :          0 :         p2p_queue_grps_info->groups[0].qg_id.queue_group_id = CPFL_P2P_QUEUE_GRP_ID;
    2425                 :          0 :         p2p_queue_grps_info->groups[0].qg_id.queue_group_type = VIRTCHNL2_QUEUE_GROUP_P2P;
    2426                 :          0 :         p2p_queue_grps_info->groups[0].rx_q_grp_info.rss_lut_size = 0;
    2427                 :          0 :         p2p_queue_grps_info->groups[0].tx_q_grp_info.tx_tc = 0;
    2428                 :          0 :         p2p_queue_grps_info->groups[0].tx_q_grp_info.priority = 0;
    2429                 :          0 :         p2p_queue_grps_info->groups[0].tx_q_grp_info.is_sp = 0;
    2430                 :          0 :         p2p_queue_grps_info->groups[0].tx_q_grp_info.pir_weight = 0;
    2431                 :            : 
    2432                 :          0 :         ret = idpf_vc_queue_grps_add(vport, p2p_queue_grps_info, p2p_q_vc_out_info);
    2433         [ #  # ]:          0 :         if (ret != 0) {
    2434                 :          0 :                 PMD_DRV_LOG(ERR, "Failed to add p2p queue groups.");
    2435                 :          0 :                 return ret;
    2436                 :            :         }
    2437                 :            : 
    2438                 :            :         return ret;
    2439                 :            : }
    2440                 :            : 
    2441                 :            : static int
    2442                 :          0 : cpfl_p2p_queue_info_init(struct cpfl_vport *cpfl_vport,
    2443                 :            :                          struct virtchnl2_add_queue_groups *p2p_q_vc_out_info)
    2444                 :            : {
    2445                 :          0 :         struct p2p_queue_chunks_info *p2p_q_chunks_info = cpfl_vport->p2p_q_chunks_info;
    2446                 :            :         struct virtchnl2_queue_reg_chunks *vc_chunks_out;
    2447                 :            :         int i, type;
    2448                 :            : 
    2449         [ #  # ]:          0 :         if (p2p_q_vc_out_info->groups[0].qg_id.queue_group_type !=
    2450                 :            :             VIRTCHNL2_QUEUE_GROUP_P2P) {
    2451                 :          0 :                 PMD_DRV_LOG(ERR, "Add queue group response mismatch.");
    2452                 :          0 :                 return -EINVAL;
    2453                 :            :         }
    2454                 :            : 
    2455                 :            :         vc_chunks_out = &p2p_q_vc_out_info->groups[0].chunks;
    2456                 :            : 
    2457         [ #  # ]:          0 :         for (i = 0; i < vc_chunks_out->num_chunks; i++) {
    2458                 :          0 :                 type = vc_chunks_out->chunks[i].type;
    2459   [ #  #  #  #  :          0 :                 switch (type) {
                      # ]
    2460                 :          0 :                 case VIRTCHNL2_QUEUE_TYPE_TX:
    2461                 :          0 :                         p2p_q_chunks_info->tx_start_qid =
    2462                 :          0 :                                 vc_chunks_out->chunks[i].start_queue_id;
    2463                 :          0 :                         p2p_q_chunks_info->tx_qtail_start =
    2464                 :          0 :                                 vc_chunks_out->chunks[i].qtail_reg_start;
    2465                 :          0 :                         p2p_q_chunks_info->tx_qtail_spacing =
    2466                 :          0 :                                 vc_chunks_out->chunks[i].qtail_reg_spacing;
    2467                 :          0 :                         break;
    2468                 :          0 :                 case VIRTCHNL2_QUEUE_TYPE_RX:
    2469                 :          0 :                         p2p_q_chunks_info->rx_start_qid =
    2470                 :          0 :                                 vc_chunks_out->chunks[i].start_queue_id;
    2471                 :          0 :                         p2p_q_chunks_info->rx_qtail_start =
    2472                 :          0 :                                 vc_chunks_out->chunks[i].qtail_reg_start;
    2473                 :          0 :                         p2p_q_chunks_info->rx_qtail_spacing =
    2474                 :          0 :                                 vc_chunks_out->chunks[i].qtail_reg_spacing;
    2475                 :          0 :                         break;
    2476                 :          0 :                 case VIRTCHNL2_QUEUE_TYPE_TX_COMPLETION:
    2477                 :          0 :                         p2p_q_chunks_info->tx_compl_start_qid =
    2478                 :          0 :                                 vc_chunks_out->chunks[i].start_queue_id;
    2479                 :          0 :                         p2p_q_chunks_info->tx_compl_qtail_start =
    2480                 :          0 :                                 vc_chunks_out->chunks[i].qtail_reg_start;
    2481                 :          0 :                         p2p_q_chunks_info->tx_compl_qtail_spacing =
    2482                 :          0 :                                 vc_chunks_out->chunks[i].qtail_reg_spacing;
    2483                 :          0 :                         break;
    2484                 :          0 :                 case VIRTCHNL2_QUEUE_TYPE_RX_BUFFER:
    2485                 :          0 :                         p2p_q_chunks_info->rx_buf_start_qid =
    2486                 :          0 :                                 vc_chunks_out->chunks[i].start_queue_id;
    2487                 :          0 :                         p2p_q_chunks_info->rx_buf_qtail_start =
    2488                 :          0 :                                 vc_chunks_out->chunks[i].qtail_reg_start;
    2489                 :          0 :                         p2p_q_chunks_info->rx_buf_qtail_spacing =
    2490                 :          0 :                                 vc_chunks_out->chunks[i].qtail_reg_spacing;
    2491                 :          0 :                         break;
    2492                 :          0 :                 default:
    2493                 :          0 :                         PMD_DRV_LOG(ERR, "Unsupported queue type");
    2494                 :          0 :                         break;
    2495                 :            :                 }
    2496                 :            :         }
    2497                 :            : 
    2498                 :            :         return 0;
    2499                 :            : }
    2500                 :            : 
    2501                 :            : int
    2502                 :          0 : cpfl_alloc_dma_mem_batch(struct idpf_dma_mem *orig_dma, struct idpf_dma_mem *dma, uint32_t size,
    2503                 :            :                          int batch_size)
    2504                 :            : {
    2505                 :            :         int i;
    2506                 :            : 
    2507         [ #  # ]:          0 :         if (!idpf_alloc_dma_mem(NULL, orig_dma, (uint64_t)size * (1 + batch_size))) {
    2508                 :          0 :                 PMD_INIT_LOG(ERR, "Could not alloc dma memory");
    2509                 :          0 :                 return -ENOMEM;
    2510                 :            :         }
    2511                 :            : 
    2512         [ #  # ]:          0 :         for (i = 0; i < batch_size; i++) {
    2513                 :          0 :                 dma[i].va = (void *)((char *)orig_dma->va + size * (i + 1));
    2514                 :          0 :                 dma[i].pa = orig_dma->pa + size * (i + 1);
    2515                 :          0 :                 dma[i].size = size;
    2516                 :          0 :                 dma[i].zone = NULL;
    2517                 :            :         }
    2518                 :            :         return 0;
    2519                 :            : }
    2520                 :            : 
    2521                 :            : static int
    2522                 :          0 : cpfl_dev_vport_init(struct rte_eth_dev *dev, void *init_params)
    2523                 :            : {
    2524                 :          0 :         struct cpfl_vport *cpfl_vport = dev->data->dev_private;
    2525                 :          0 :         struct idpf_vport *vport = &cpfl_vport->base;
    2526                 :            :         struct cpfl_vport_param *param = init_params;
    2527                 :          0 :         struct cpfl_adapter_ext *adapter = param->adapter;
    2528                 :            :         /* for sending create vport virtchnl msg prepare */
    2529                 :            :         struct virtchnl2_create_vport create_vport_info;
    2530                 :            :         struct virtchnl2_add_queue_groups p2p_queue_grps_info;
    2531                 :          0 :         uint8_t p2p_q_vc_out_info[IDPF_DFLT_MBX_BUF_SIZE] = {0};
    2532                 :            :         int ret = 0;
    2533                 :            : 
    2534                 :          0 :         dev->dev_ops = &cpfl_eth_dev_ops;
    2535                 :          0 :         vport->adapter = &adapter->base;
    2536                 :          0 :         vport->sw_idx = param->idx;
    2537                 :          0 :         vport->devarg_id = param->devarg_id;
    2538                 :            : 
    2539                 :            :         memset(&create_vport_info, 0, sizeof(create_vport_info));
    2540                 :          0 :         ret = idpf_vport_info_init(vport, &create_vport_info);
    2541         [ #  # ]:          0 :         if (ret != 0) {
    2542                 :          0 :                 PMD_INIT_LOG(ERR, "Failed to init vport req_info.");
    2543                 :          0 :                 goto err;
    2544                 :            :         }
    2545                 :            : 
    2546                 :          0 :         ret = idpf_vport_init(vport, &create_vport_info, dev->data);
    2547         [ #  # ]:          0 :         if (ret != 0) {
    2548                 :          0 :                 PMD_INIT_LOG(ERR, "Failed to init vports.");
    2549                 :          0 :                 goto err;
    2550                 :            :         }
    2551                 :            : 
    2552                 :          0 :         cpfl_vport->itf.type = CPFL_ITF_TYPE_VPORT;
    2553                 :          0 :         cpfl_vport->itf.adapter = adapter;
    2554                 :          0 :         cpfl_vport->itf.data = dev->data;
    2555                 :          0 :         TAILQ_INIT(&cpfl_vport->itf.flow_list);
    2556                 :          0 :         adapter->vports[param->idx] = cpfl_vport;
    2557                 :          0 :         adapter->cur_vports |= RTE_BIT32(param->devarg_id);
    2558                 :          0 :         adapter->cur_vport_nb++;
    2559                 :            : 
    2560                 :          0 :         dev->data->mac_addrs = rte_zmalloc(NULL, RTE_ETHER_ADDR_LEN, 0);
    2561         [ #  # ]:          0 :         if (dev->data->mac_addrs == NULL) {
    2562                 :          0 :                 PMD_INIT_LOG(ERR, "Cannot allocate mac_addr memory.");
    2563                 :            :                 ret = -ENOMEM;
    2564                 :          0 :                 goto err_mac_addrs;
    2565                 :            :         }
    2566                 :            : 
    2567                 :            :         rte_ether_addr_copy((struct rte_ether_addr *)vport->default_mac_addr,
    2568                 :            :                             &dev->data->mac_addrs[0]);
    2569                 :            : 
    2570                 :          0 :         memset(cpfl_vport->itf.dma, 0, sizeof(cpfl_vport->itf.dma));
    2571                 :          0 :         memset(cpfl_vport->itf.msg, 0, sizeof(cpfl_vport->itf.msg));
    2572                 :          0 :         ret = cpfl_alloc_dma_mem_batch(&cpfl_vport->itf.flow_dma,
    2573                 :            :                                        cpfl_vport->itf.dma,
    2574                 :            :                                        sizeof(union cpfl_rule_cfg_pkt_record),
    2575                 :            :                                        CPFL_FLOW_BATCH_SIZE);
    2576         [ #  # ]:          0 :         if (ret < 0)
    2577                 :          0 :                 goto err_mac_addrs;
    2578                 :            : 
    2579   [ #  #  #  # ]:          0 :         if (!adapter->base.is_rx_singleq && !adapter->base.is_tx_singleq) {
    2580                 :            :                 memset(&p2p_queue_grps_info, 0, sizeof(p2p_queue_grps_info));
    2581                 :          0 :                 ret = cpfl_p2p_q_grps_add(vport, &p2p_queue_grps_info, p2p_q_vc_out_info);
    2582         [ #  # ]:          0 :                 if (ret != 0) {
    2583                 :          0 :                         PMD_INIT_LOG(WARNING, "Failed to add p2p queue group.");
    2584                 :          0 :                         return 0;
    2585                 :            :                 }
    2586                 :          0 :                 cpfl_vport->p2p_q_chunks_info = rte_zmalloc(NULL,
    2587                 :            :                                                     sizeof(struct p2p_queue_chunks_info), 0);
    2588         [ #  # ]:          0 :                 if (cpfl_vport->p2p_q_chunks_info == NULL) {
    2589                 :          0 :                         PMD_INIT_LOG(WARNING, "Failed to allocate p2p queue info.");
    2590                 :          0 :                         cpfl_p2p_queue_grps_del(vport);
    2591                 :          0 :                         return 0;
    2592                 :            :                 }
    2593                 :          0 :                 ret = cpfl_p2p_queue_info_init(cpfl_vport,
    2594                 :            :                                        (struct virtchnl2_add_queue_groups *)p2p_q_vc_out_info);
    2595         [ #  # ]:          0 :                 if (ret != 0) {
    2596                 :          0 :                         PMD_INIT_LOG(WARNING, "Failed to init p2p queue info.");
    2597                 :          0 :                         rte_free(cpfl_vport->p2p_q_chunks_info);
    2598                 :          0 :                         cpfl_p2p_queue_grps_del(vport);
    2599                 :            :                 }
    2600                 :            :         }
    2601                 :            : 
    2602                 :            :         return 0;
    2603                 :            : 
    2604                 :          0 : err_mac_addrs:
    2605                 :          0 :         adapter->vports[param->idx] = NULL;  /* reset */
    2606                 :          0 :         idpf_vport_deinit(vport);
    2607                 :          0 :         adapter->cur_vports &= ~RTE_BIT32(param->devarg_id);
    2608                 :          0 :         adapter->cur_vport_nb--;
    2609                 :            : err:
    2610                 :            :         return ret;
    2611                 :            : }
    2612                 :            : 
    2613                 :            : static const struct rte_pci_id pci_id_cpfl_map[] = {
    2614                 :            :         { RTE_PCI_DEVICE(IDPF_INTEL_VENDOR_ID, IDPF_DEV_ID_CPF) },
    2615                 :            :         { .vendor_id = 0, /* sentinel */ },
    2616                 :            : };
    2617                 :            : 
    2618                 :            : static struct cpfl_adapter_ext *
    2619                 :          0 : cpfl_find_adapter_ext(struct rte_pci_device *pci_dev)
    2620                 :            : {
    2621                 :            :         struct cpfl_adapter_ext *adapter;
    2622                 :            :         int found = 0;
    2623                 :            : 
    2624         [ #  # ]:          0 :         if (pci_dev == NULL)
    2625                 :            :                 return NULL;
    2626                 :            : 
    2627                 :            :         rte_spinlock_lock(&cpfl_adapter_lock);
    2628         [ #  # ]:          0 :         TAILQ_FOREACH(adapter, &cpfl_adapter_list, next) {
    2629         [ #  # ]:          0 :                 if (strncmp(adapter->name, pci_dev->device.name, PCI_PRI_STR_SIZE) == 0) {
    2630                 :            :                         found = 1;
    2631                 :            :                         break;
    2632                 :            :                 }
    2633                 :            :         }
    2634                 :            :         rte_spinlock_unlock(&cpfl_adapter_lock);
    2635                 :            : 
    2636         [ #  # ]:          0 :         if (found == 0)
    2637                 :          0 :                 return NULL;
    2638                 :            : 
    2639                 :            :         return adapter;
    2640                 :            : }
    2641                 :            : 
    2642                 :            : static void
    2643                 :          0 : cpfl_adapter_ext_deinit(struct cpfl_adapter_ext *adapter)
    2644                 :            : {
    2645                 :            : #ifdef RTE_HAS_JANSSON
    2646                 :          0 :         cpfl_flow_uninit(adapter);
    2647                 :            : #endif
    2648                 :          0 :         cpfl_ctrl_path_close(adapter);
    2649                 :          0 :         rte_eal_alarm_cancel(cpfl_dev_alarm_handler, adapter);
    2650                 :          0 :         cpfl_vport_map_uninit(adapter);
    2651                 :          0 :         idpf_adapter_deinit(&adapter->base);
    2652                 :            : 
    2653                 :          0 :         rte_free(adapter->vports);
    2654                 :          0 :         adapter->vports = NULL;
    2655                 :          0 : }
    2656                 :            : 
    2657                 :            : static int
    2658                 :          0 : cpfl_vport_devargs_process(struct cpfl_adapter_ext *adapter, struct cpfl_devargs *devargs)
    2659                 :            : {
    2660                 :            :         int i;
    2661                 :            : 
    2662                 :            :         /* refine vport number, at least 1 vport */
    2663         [ #  # ]:          0 :         if (devargs->req_vport_nb == 0) {
    2664                 :          0 :                 devargs->req_vport_nb = 1;
    2665                 :          0 :                 devargs->req_vports[0] = 0;
    2666                 :            :         }
    2667                 :            : 
    2668                 :            :         /* check parsed devargs */
    2669                 :          0 :         if (adapter->cur_vport_nb + devargs->req_vport_nb >
    2670         [ #  # ]:          0 :             adapter->max_vport_nb) {
    2671                 :          0 :                 PMD_INIT_LOG(ERR, "Total vport number can't be > %d",
    2672                 :            :                              adapter->max_vport_nb);
    2673                 :          0 :                 return -EINVAL;
    2674                 :            :         }
    2675                 :            : 
    2676         [ #  # ]:          0 :         for (i = 0; i < devargs->req_vport_nb; i++) {
    2677         [ #  # ]:          0 :                 if (devargs->req_vports[i] > adapter->max_vport_nb - 1) {
    2678                 :          0 :                         PMD_INIT_LOG(ERR, "Invalid vport id %d, it should be 0 ~ %d",
    2679                 :            :                                      devargs->req_vports[i], adapter->max_vport_nb - 1);
    2680                 :          0 :                         return -EINVAL;
    2681                 :            :                 }
    2682                 :            : 
    2683         [ #  # ]:          0 :                 if (adapter->cur_vports & RTE_BIT32(devargs->req_vports[i])) {
    2684                 :          0 :                         PMD_INIT_LOG(ERR, "Vport %d has been requested",
    2685                 :            :                                      devargs->req_vports[i]);
    2686                 :          0 :                         return -EINVAL;
    2687                 :            :                 }
    2688                 :            :         }
    2689                 :            : 
    2690                 :            :         return 0;
    2691                 :            : }
    2692                 :            : 
    2693                 :            : static int
    2694                 :          0 : cpfl_vport_create(struct rte_pci_device *pci_dev, struct cpfl_adapter_ext *adapter,
    2695                 :            :                   struct cpfl_devargs *devargs)
    2696                 :            : {
    2697                 :            :         struct cpfl_vport_param vport_param;
    2698                 :            :         char name[RTE_ETH_NAME_MAX_LEN];
    2699                 :            :         int ret, i;
    2700                 :            : 
    2701         [ #  # ]:          0 :         for (i = 0; i < devargs->req_vport_nb; i++) {
    2702                 :          0 :                 vport_param.adapter = adapter;
    2703                 :          0 :                 vport_param.devarg_id = devargs->req_vports[i];
    2704                 :          0 :                 vport_param.idx = cpfl_vport_idx_alloc(adapter);
    2705         [ #  # ]:          0 :                 if (vport_param.idx == CPFL_INVALID_VPORT_IDX) {
    2706                 :          0 :                         PMD_INIT_LOG(ERR, "No space for vport %u", vport_param.devarg_id);
    2707                 :          0 :                         break;
    2708                 :            :                 }
    2709                 :          0 :                 snprintf(name, sizeof(name), "net_%s_vport_%d",
    2710                 :            :                          pci_dev->device.name,
    2711                 :            :                          devargs->req_vports[i]);
    2712                 :          0 :                 ret = rte_eth_dev_create(&pci_dev->device, name,
    2713                 :            :                                             sizeof(struct cpfl_vport),
    2714                 :            :                                             NULL, NULL, cpfl_dev_vport_init,
    2715                 :            :                                             &vport_param);
    2716         [ #  # ]:          0 :                 if (ret != 0)
    2717                 :          0 :                         PMD_DRV_LOG(ERR, "Failed to create vport %d",
    2718                 :            :                                     vport_param.devarg_id);
    2719                 :            :         }
    2720                 :            : 
    2721                 :          0 :         return 0;
    2722                 :            : }
    2723                 :            : 
    2724                 :            : static int
    2725                 :          0 : cpfl_pci_probe_first(struct rte_pci_device *pci_dev)
    2726                 :            : {
    2727                 :            :         struct cpfl_adapter_ext *adapter;
    2728                 :            :         struct cpfl_devargs devargs;
    2729                 :            :         int retval;
    2730                 :            :         uint16_t port_id;
    2731                 :            : 
    2732                 :          0 :         adapter = rte_zmalloc("cpfl_adapter_ext",
    2733                 :            :                               sizeof(struct cpfl_adapter_ext), 0);
    2734         [ #  # ]:          0 :         if (adapter == NULL) {
    2735                 :          0 :                 PMD_INIT_LOG(ERR, "Failed to allocate adapter.");
    2736                 :          0 :                 return -ENOMEM;
    2737                 :            :         }
    2738                 :            : 
    2739                 :            :         memset(&devargs, 0, sizeof(devargs));
    2740                 :            : 
    2741                 :          0 :         retval = cpfl_parse_devargs(pci_dev, adapter, true, &devargs);
    2742         [ #  # ]:          0 :         if (retval != 0) {
    2743                 :          0 :                 PMD_INIT_LOG(ERR, "Failed to parse private devargs");
    2744                 :          0 :                 return retval;
    2745                 :            :         }
    2746                 :            : 
    2747                 :          0 :         retval = cpfl_adapter_ext_init(pci_dev, adapter, &devargs);
    2748         [ #  # ]:          0 :         if (retval != 0) {
    2749                 :          0 :                 PMD_INIT_LOG(ERR, "Failed to init adapter.");
    2750                 :          0 :                 return retval;
    2751                 :            :         }
    2752                 :            : 
    2753                 :            :         rte_spinlock_lock(&cpfl_adapter_lock);
    2754                 :          0 :         TAILQ_INSERT_TAIL(&cpfl_adapter_list, adapter, next);
    2755                 :            :         rte_spinlock_unlock(&cpfl_adapter_lock);
    2756                 :            : 
    2757                 :          0 :         retval = cpfl_vport_devargs_process(adapter, &devargs);
    2758         [ #  # ]:          0 :         if (retval != 0) {
    2759                 :          0 :                 PMD_INIT_LOG(ERR, "Failed to process vport devargs");
    2760                 :          0 :                 goto err;
    2761                 :            :         }
    2762                 :            : 
    2763                 :          0 :         retval = cpfl_vport_create(pci_dev, adapter, &devargs);
    2764         [ #  # ]:          0 :         if (retval != 0) {
    2765                 :          0 :                 PMD_INIT_LOG(ERR, "Failed to create vports.");
    2766                 :          0 :                 goto err;
    2767                 :            :         }
    2768                 :            : 
    2769                 :          0 :         retval = cpfl_repr_devargs_process(adapter, &devargs);
    2770         [ #  # ]:          0 :         if (retval != 0) {
    2771                 :          0 :                 PMD_INIT_LOG(ERR, "Failed to process repr devargs");
    2772                 :          0 :                 goto close_ethdev;
    2773                 :            :         }
    2774                 :            : 
    2775                 :          0 :         retval = cpfl_repr_create(pci_dev, adapter);
    2776         [ #  # ]:          0 :         if (retval != 0) {
    2777                 :          0 :                 PMD_INIT_LOG(ERR, "Failed to create representors ");
    2778                 :          0 :                 goto close_ethdev;
    2779                 :            :         }
    2780                 :            : 
    2781                 :            : 
    2782                 :            :         return 0;
    2783                 :            : 
    2784                 :          0 : close_ethdev:
    2785                 :            :         /* Ethdev created can be found RTE_ETH_FOREACH_DEV_OF through rte_device */
    2786         [ #  # ]:          0 :         RTE_ETH_FOREACH_DEV_OF(port_id, &pci_dev->device) {
    2787                 :          0 :                 rte_eth_dev_close(port_id);
    2788                 :            :         }
    2789                 :          0 : err:
    2790                 :            :         rte_spinlock_lock(&cpfl_adapter_lock);
    2791         [ #  # ]:          0 :         TAILQ_REMOVE(&cpfl_adapter_list, adapter, next);
    2792                 :            :         rte_spinlock_unlock(&cpfl_adapter_lock);
    2793                 :          0 :         cpfl_adapter_ext_deinit(adapter);
    2794                 :          0 :         rte_free(adapter);
    2795                 :          0 :         return retval;
    2796                 :            : }
    2797                 :            : 
    2798                 :            : static int
    2799                 :          0 : cpfl_pci_probe_again(struct rte_pci_device *pci_dev, struct cpfl_adapter_ext *adapter)
    2800                 :            : {
    2801                 :            :         struct cpfl_devargs devargs;
    2802                 :            :         int ret;
    2803                 :            : 
    2804                 :            :         memset(&devargs, 0, sizeof(devargs));
    2805                 :          0 :         ret = cpfl_parse_devargs(pci_dev, adapter, false, &devargs);
    2806         [ #  # ]:          0 :         if (ret != 0) {
    2807                 :          0 :                 PMD_INIT_LOG(ERR, "Failed to parse private devargs");
    2808                 :          0 :                 return ret;
    2809                 :            :         }
    2810                 :            : 
    2811                 :          0 :         ret = cpfl_repr_devargs_process(adapter, &devargs);
    2812         [ #  # ]:          0 :         if (ret != 0) {
    2813                 :          0 :                 PMD_INIT_LOG(ERR, "Failed to process reprenstor devargs");
    2814                 :          0 :                 return ret;
    2815                 :            :         }
    2816                 :            : 
    2817                 :          0 :         ret = cpfl_repr_create(pci_dev, adapter);
    2818         [ #  # ]:          0 :         if (ret != 0) {
    2819                 :          0 :                 PMD_INIT_LOG(ERR, "Failed to create representors ");
    2820                 :          0 :                 return ret;
    2821                 :            :         }
    2822                 :            : 
    2823                 :            :         return 0;
    2824                 :            : }
    2825                 :            : 
    2826                 :            : static int
    2827                 :          0 : cpfl_pci_probe(struct rte_pci_driver *pci_drv __rte_unused,
    2828                 :            :                struct rte_pci_device *pci_dev)
    2829                 :            : {
    2830                 :            :         struct cpfl_adapter_ext *adapter;
    2831                 :            : 
    2832         [ #  # ]:          0 :         if (!cpfl_adapter_list_init) {
    2833                 :            :                 rte_spinlock_init(&cpfl_adapter_lock);
    2834                 :          0 :                 TAILQ_INIT(&cpfl_adapter_list);
    2835                 :          0 :                 cpfl_adapter_list_init = true;
    2836                 :            :         }
    2837                 :            : 
    2838                 :          0 :         adapter = cpfl_find_adapter_ext(pci_dev);
    2839                 :            : 
    2840         [ #  # ]:          0 :         if (adapter == NULL)
    2841                 :          0 :                 return cpfl_pci_probe_first(pci_dev);
    2842                 :            :         else
    2843                 :          0 :                 return cpfl_pci_probe_again(pci_dev, adapter);
    2844                 :            : }
    2845                 :            : 
    2846                 :            : static int
    2847                 :          0 : cpfl_pci_remove(struct rte_pci_device *pci_dev)
    2848                 :            : {
    2849                 :          0 :         struct cpfl_adapter_ext *adapter = cpfl_find_adapter_ext(pci_dev);
    2850                 :            :         uint16_t port_id;
    2851                 :            : 
    2852                 :            :         /* Ethdev created can be found RTE_ETH_FOREACH_DEV_OF through rte_device */
    2853         [ #  # ]:          0 :         RTE_ETH_FOREACH_DEV_OF(port_id, &pci_dev->device) {
    2854                 :          0 :                         rte_eth_dev_close(port_id);
    2855                 :            :         }
    2856                 :            : 
    2857                 :            :         rte_spinlock_lock(&cpfl_adapter_lock);
    2858         [ #  # ]:          0 :         TAILQ_REMOVE(&cpfl_adapter_list, adapter, next);
    2859                 :            :         rte_spinlock_unlock(&cpfl_adapter_lock);
    2860                 :          0 :         cpfl_adapter_ext_deinit(adapter);
    2861                 :          0 :         rte_free(adapter);
    2862                 :            : 
    2863                 :          0 :         return 0;
    2864                 :            : }
    2865                 :            : 
    2866                 :            : static struct rte_pci_driver rte_cpfl_pmd = {
    2867                 :            :         .id_table       = pci_id_cpfl_map,
    2868                 :            :         .drv_flags      = RTE_PCI_DRV_NEED_MAPPING |
    2869                 :            :                           RTE_PCI_DRV_PROBE_AGAIN,
    2870                 :            :         .probe          = cpfl_pci_probe,
    2871                 :            :         .remove         = cpfl_pci_remove,
    2872                 :            : };
    2873                 :            : 
    2874                 :            : /**
    2875                 :            :  * Driver initialization routine.
    2876                 :            :  * Invoked once at EAL init time.
    2877                 :            :  * Register itself as the [Poll Mode] Driver of PCI devices.
    2878                 :            :  */
    2879                 :        252 : RTE_PMD_REGISTER_PCI(net_cpfl, rte_cpfl_pmd);
    2880                 :            : RTE_PMD_REGISTER_PCI_TABLE(net_cpfl, pci_id_cpfl_map);
    2881                 :            : RTE_PMD_REGISTER_KMOD_DEP(net_cpfl, "* igb_uio | vfio-pci");
    2882                 :            : RTE_PMD_REGISTER_PARAM_STRING(net_cpfl,
    2883                 :            :         CPFL_TX_SINGLE_Q "=<0|1> "
    2884                 :            :         CPFL_RX_SINGLE_Q "=<0|1> "
    2885                 :            :         CPFL_VPORT "=[vport0_begin[-vport0_end][,vport1_begin[-vport1_end]][,..]]");
    2886                 :            : 
    2887         [ -  + ]:        252 : RTE_LOG_REGISTER_SUFFIX(cpfl_logtype_init, init, NOTICE);
    2888         [ -  + ]:        252 : RTE_LOG_REGISTER_SUFFIX(cpfl_logtype_driver, driver, NOTICE);

Generated by: LCOV version 1.14