LCOV - code coverage report
Current view: top level - drivers/net/virtio/virtio_user - virtio_user_dev.c (source / functions) Hit Total Coverage
Test: Code coverage Lines: 0 605 0.0 %
Date: 2024-02-14 00:53:57 Functions: 0 35 0.0 %
Legend: Lines: hit not hit | Branches: + taken - not taken # not executed Branches: 0 298 0.0 %

           Branch data     Line data    Source code
       1                 :            : /* SPDX-License-Identifier: BSD-3-Clause
       2                 :            :  * Copyright(c) 2010-2016 Intel Corporation
       3                 :            :  */
       4                 :            : 
       5                 :            : #include <stdint.h>
       6                 :            : #include <stdio.h>
       7                 :            : #include <stdlib.h>
       8                 :            : #include <fcntl.h>
       9                 :            : #include <string.h>
      10                 :            : #include <errno.h>
      11                 :            : #include <sys/mman.h>
      12                 :            : #include <unistd.h>
      13                 :            : #include <sys/eventfd.h>
      14                 :            : #include <sys/types.h>
      15                 :            : #include <sys/stat.h>
      16                 :            : 
      17                 :            : #include <rte_alarm.h>
      18                 :            : #include <rte_string_fns.h>
      19                 :            : #include <rte_eal_memconfig.h>
      20                 :            : #include <rte_malloc.h>
      21                 :            : 
      22                 :            : #include "vhost.h"
      23                 :            : #include "virtio_user_dev.h"
      24                 :            : #include "../virtio_ethdev.h"
      25                 :            : 
      26                 :            : #define VIRTIO_USER_MEM_EVENT_CLB_NAME "virtio_user_mem_event_clb"
      27                 :            : 
      28                 :            : const char * const virtio_user_backend_strings[] = {
      29                 :            :         [VIRTIO_USER_BACKEND_UNKNOWN] = "VIRTIO_USER_BACKEND_UNKNOWN",
      30                 :            :         [VIRTIO_USER_BACKEND_VHOST_USER] = "VHOST_USER",
      31                 :            :         [VIRTIO_USER_BACKEND_VHOST_KERNEL] = "VHOST_NET",
      32                 :            :         [VIRTIO_USER_BACKEND_VHOST_VDPA] = "VHOST_VDPA",
      33                 :            : };
      34                 :            : 
      35                 :            : static int
      36                 :          0 : virtio_user_create_queue(struct virtio_user_dev *dev, uint32_t queue_sel)
      37                 :            : {
      38                 :            :         /* Of all per virtqueue MSGs, make sure VHOST_SET_VRING_CALL come
      39                 :            :          * firstly because vhost depends on this msg to allocate virtqueue
      40                 :            :          * pair.
      41                 :            :          */
      42                 :            :         struct vhost_vring_file file;
      43                 :            :         int ret;
      44                 :            : 
      45                 :          0 :         file.index = queue_sel;
      46                 :          0 :         file.fd = dev->callfds[queue_sel];
      47                 :          0 :         ret = dev->ops->set_vring_call(dev, &file);
      48         [ #  # ]:          0 :         if (ret < 0) {
      49                 :          0 :                 PMD_INIT_LOG(ERR, "(%s) Failed to create queue %u", dev->path, queue_sel);
      50                 :          0 :                 return -1;
      51                 :            :         }
      52                 :            : 
      53                 :            :         return 0;
      54                 :            : }
      55                 :            : 
      56                 :            : static int
      57                 :          0 : virtio_user_kick_queue(struct virtio_user_dev *dev, uint32_t queue_sel)
      58                 :            : {
      59                 :            :         int ret;
      60                 :            :         struct vhost_vring_file file;
      61                 :            :         struct vhost_vring_state state;
      62                 :          0 :         struct vring *vring = &dev->vrings.split[queue_sel];
      63                 :            :         struct vring_packed *pq_vring = &dev->vrings.packed[queue_sel];
      64                 :          0 :         struct vhost_vring_addr addr = {
      65                 :            :                 .index = queue_sel,
      66                 :            :                 .log_guest_addr = 0,
      67                 :            :                 .flags = 0, /* disable log */
      68                 :            :         };
      69                 :            : 
      70         [ #  # ]:          0 :         if (queue_sel == dev->max_queue_pairs * 2) {
      71         [ #  # ]:          0 :                 if (!dev->scvq) {
      72                 :          0 :                         PMD_INIT_LOG(ERR, "(%s) Shadow control queue expected but missing",
      73                 :            :                                         dev->path);
      74                 :          0 :                         goto err;
      75                 :            :                 }
      76                 :            : 
      77                 :            :                 /* Use shadow control queue information */
      78                 :          0 :                 vring = &dev->scvq->vq_split.ring;
      79                 :          0 :                 pq_vring = &dev->scvq->vq_packed.ring;
      80                 :            :         }
      81                 :            : 
      82         [ #  # ]:          0 :         if (dev->features & (1ULL << VIRTIO_F_RING_PACKED)) {
      83                 :          0 :                 addr.desc_user_addr =
      84                 :          0 :                         (uint64_t)(uintptr_t)pq_vring->desc;
      85                 :          0 :                 addr.avail_user_addr =
      86                 :          0 :                         (uint64_t)(uintptr_t)pq_vring->driver;
      87                 :          0 :                 addr.used_user_addr =
      88                 :          0 :                         (uint64_t)(uintptr_t)pq_vring->device;
      89                 :            :         } else {
      90                 :          0 :                 addr.desc_user_addr = (uint64_t)(uintptr_t)vring->desc;
      91                 :          0 :                 addr.avail_user_addr = (uint64_t)(uintptr_t)vring->avail;
      92                 :          0 :                 addr.used_user_addr = (uint64_t)(uintptr_t)vring->used;
      93                 :            :         }
      94                 :            : 
      95                 :          0 :         state.index = queue_sel;
      96                 :          0 :         state.num = vring->num;
      97                 :          0 :         ret = dev->ops->set_vring_num(dev, &state);
      98         [ #  # ]:          0 :         if (ret < 0)
      99                 :          0 :                 goto err;
     100                 :            : 
     101                 :          0 :         state.index = queue_sel;
     102                 :          0 :         state.num = 0; /* no reservation */
     103         [ #  # ]:          0 :         if (dev->features & (1ULL << VIRTIO_F_RING_PACKED))
     104                 :          0 :                 state.num |= (1 << 15);
     105                 :          0 :         ret = dev->ops->set_vring_base(dev, &state);
     106         [ #  # ]:          0 :         if (ret < 0)
     107                 :          0 :                 goto err;
     108                 :            : 
     109                 :          0 :         ret = dev->ops->set_vring_addr(dev, &addr);
     110         [ #  # ]:          0 :         if (ret < 0)
     111                 :          0 :                 goto err;
     112                 :            : 
     113                 :            :         /* Of all per virtqueue MSGs, make sure VHOST_USER_SET_VRING_KICK comes
     114                 :            :          * lastly because vhost depends on this msg to judge if
     115                 :            :          * virtio is ready.
     116                 :            :          */
     117                 :          0 :         file.index = queue_sel;
     118                 :          0 :         file.fd = dev->kickfds[queue_sel];
     119                 :          0 :         ret = dev->ops->set_vring_kick(dev, &file);
     120         [ #  # ]:          0 :         if (ret < 0)
     121                 :          0 :                 goto err;
     122                 :            : 
     123                 :            :         return 0;
     124                 :          0 : err:
     125                 :          0 :         PMD_INIT_LOG(ERR, "(%s) Failed to kick queue %u", dev->path, queue_sel);
     126                 :            : 
     127                 :          0 :         return -1;
     128                 :            : }
     129                 :            : 
     130                 :            : static int
     131                 :          0 : virtio_user_queue_setup(struct virtio_user_dev *dev,
     132                 :            :                         int (*fn)(struct virtio_user_dev *, uint32_t))
     133                 :            : {
     134                 :            :         uint32_t i, nr_vq;
     135                 :            : 
     136                 :          0 :         nr_vq = dev->max_queue_pairs * 2;
     137         [ #  # ]:          0 :         if (dev->hw_cvq)
     138                 :          0 :                 nr_vq++;
     139                 :            : 
     140         [ #  # ]:          0 :         for (i = 0; i < nr_vq; i++) {
     141         [ #  # ]:          0 :                 if (fn(dev, i) < 0) {
     142                 :          0 :                         PMD_DRV_LOG(ERR, "(%s) setup VQ %u failed", dev->path, i);
     143                 :          0 :                         return -1;
     144                 :            :                 }
     145                 :            :         }
     146                 :            : 
     147                 :            :         return 0;
     148                 :            : }
     149                 :            : 
     150                 :            : int
     151                 :          0 : virtio_user_dev_set_features(struct virtio_user_dev *dev)
     152                 :            : {
     153                 :            :         uint64_t features;
     154                 :            :         int ret = -1;
     155                 :            : 
     156                 :          0 :         pthread_mutex_lock(&dev->mutex);
     157                 :            : 
     158                 :            :         /* Step 0: tell vhost to create queues */
     159         [ #  # ]:          0 :         if (virtio_user_queue_setup(dev, virtio_user_create_queue) < 0)
     160                 :          0 :                 goto error;
     161                 :            : 
     162                 :          0 :         features = dev->features;
     163                 :            : 
     164                 :            :         /* Strip VIRTIO_NET_F_MAC, as MAC address is handled in vdev init */
     165                 :          0 :         features &= ~(1ull << VIRTIO_NET_F_MAC);
     166                 :            :         /* Strip VIRTIO_NET_F_CTRL_VQ if the devices does not really support control VQ */
     167         [ #  # ]:          0 :         if (!dev->hw_cvq)
     168                 :          0 :                 features &= ~(1ull << VIRTIO_NET_F_CTRL_VQ);
     169                 :          0 :         features &= ~(1ull << VIRTIO_NET_F_STATUS);
     170                 :          0 :         ret = dev->ops->set_features(dev, features);
     171         [ #  # ]:          0 :         if (ret < 0)
     172                 :          0 :                 goto error;
     173                 :          0 :         PMD_DRV_LOG(INFO, "(%s) set features: 0x%" PRIx64, dev->path, features);
     174                 :          0 : error:
     175                 :          0 :         pthread_mutex_unlock(&dev->mutex);
     176                 :            : 
     177                 :          0 :         return ret;
     178                 :            : }
     179                 :            : 
     180                 :            : int
     181                 :          0 : virtio_user_start_device(struct virtio_user_dev *dev)
     182                 :            : {
     183                 :            :         int ret;
     184                 :            : 
     185                 :            :         /*
     186                 :            :          * XXX workaround!
     187                 :            :          *
     188                 :            :          * We need to make sure that the locks will be
     189                 :            :          * taken in the correct order to avoid deadlocks.
     190                 :            :          *
     191                 :            :          * Before releasing this lock, this thread should
     192                 :            :          * not trigger any memory hotplug events.
     193                 :            :          *
     194                 :            :          * This is a temporary workaround, and should be
     195                 :            :          * replaced when we get proper supports from the
     196                 :            :          * memory subsystem in the future.
     197                 :            :          */
     198                 :          0 :         rte_mcfg_mem_read_lock();
     199                 :          0 :         pthread_mutex_lock(&dev->mutex);
     200                 :            : 
     201                 :            :         /* Step 2: share memory regions */
     202                 :          0 :         ret = dev->ops->set_memory_table(dev);
     203         [ #  # ]:          0 :         if (ret < 0)
     204                 :          0 :                 goto error;
     205                 :            : 
     206                 :            :         /* Step 3: kick queues */
     207                 :          0 :         ret = virtio_user_queue_setup(dev, virtio_user_kick_queue);
     208         [ #  # ]:          0 :         if (ret < 0)
     209                 :          0 :                 goto error;
     210                 :            : 
     211                 :            :         /* Step 4: enable queues
     212                 :            :          * we enable the 1st queue pair by default.
     213                 :            :          */
     214                 :          0 :         ret = dev->ops->enable_qp(dev, 0, 1);
     215         [ #  # ]:          0 :         if (ret < 0)
     216                 :          0 :                 goto error;
     217                 :            : 
     218                 :          0 :         dev->started = true;
     219                 :            : 
     220                 :          0 :         pthread_mutex_unlock(&dev->mutex);
     221                 :          0 :         rte_mcfg_mem_read_unlock();
     222                 :            : 
     223                 :          0 :         return 0;
     224                 :          0 : error:
     225                 :          0 :         pthread_mutex_unlock(&dev->mutex);
     226                 :          0 :         rte_mcfg_mem_read_unlock();
     227                 :            : 
     228                 :          0 :         PMD_INIT_LOG(ERR, "(%s) Failed to start device", dev->path);
     229                 :            : 
     230                 :            :         /* TODO: free resource here or caller to check */
     231                 :          0 :         return -1;
     232                 :            : }
     233                 :            : 
     234                 :          0 : int virtio_user_stop_device(struct virtio_user_dev *dev)
     235                 :            : {
     236                 :            :         struct vhost_vring_state state;
     237                 :            :         uint32_t i;
     238                 :            :         int ret;
     239                 :            : 
     240                 :          0 :         pthread_mutex_lock(&dev->mutex);
     241         [ #  # ]:          0 :         if (!dev->started)
     242                 :          0 :                 goto out;
     243                 :            : 
     244         [ #  # ]:          0 :         for (i = 0; i < dev->max_queue_pairs; ++i) {
     245                 :          0 :                 ret = dev->ops->enable_qp(dev, i, 0);
     246         [ #  # ]:          0 :                 if (ret < 0)
     247                 :          0 :                         goto err;
     248                 :            :         }
     249                 :            : 
     250                 :            :         /* Stop the backend. */
     251         [ #  # ]:          0 :         for (i = 0; i < dev->max_queue_pairs * 2; ++i) {
     252                 :          0 :                 state.index = i;
     253                 :          0 :                 ret = dev->ops->get_vring_base(dev, &state);
     254         [ #  # ]:          0 :                 if (ret < 0) {
     255                 :          0 :                         PMD_DRV_LOG(ERR, "(%s) get_vring_base failed, index=%u", dev->path, i);
     256                 :          0 :                         goto err;
     257                 :            :                 }
     258                 :            :         }
     259                 :            : 
     260                 :          0 :         dev->started = false;
     261                 :            : 
     262                 :          0 : out:
     263                 :          0 :         pthread_mutex_unlock(&dev->mutex);
     264                 :            : 
     265                 :          0 :         return 0;
     266                 :          0 : err:
     267                 :          0 :         pthread_mutex_unlock(&dev->mutex);
     268                 :            : 
     269                 :          0 :         PMD_INIT_LOG(ERR, "(%s) Failed to stop device", dev->path);
     270                 :            : 
     271                 :          0 :         return -1;
     272                 :            : }
     273                 :            : 
     274                 :            : static int
     275                 :          0 : virtio_user_dev_init_max_queue_pairs(struct virtio_user_dev *dev, uint32_t user_max_qp)
     276                 :            : {
     277                 :            :         int ret;
     278                 :            : 
     279         [ #  # ]:          0 :         if (!(dev->device_features & (1ULL << VIRTIO_NET_F_MQ))) {
     280                 :          0 :                 dev->max_queue_pairs = 1;
     281                 :          0 :                 return 0;
     282                 :            :         }
     283                 :            : 
     284         [ #  # ]:          0 :         if (!dev->ops->get_config) {
     285                 :          0 :                 dev->max_queue_pairs = user_max_qp;
     286                 :          0 :                 return 0;
     287                 :            :         }
     288                 :            : 
     289                 :          0 :         ret = dev->ops->get_config(dev, (uint8_t *)&dev->max_queue_pairs,
     290                 :            :                         offsetof(struct virtio_net_config, max_virtqueue_pairs),
     291                 :            :                         sizeof(uint16_t));
     292         [ #  # ]:          0 :         if (ret) {
     293                 :            :                 /*
     294                 :            :                  * We need to know the max queue pair from the device so that
     295                 :            :                  * the control queue gets the right index.
     296                 :            :                  */
     297                 :          0 :                 dev->max_queue_pairs = 1;
     298                 :          0 :                 PMD_DRV_LOG(ERR, "(%s) Failed to get max queue pairs from device", dev->path);
     299                 :            : 
     300                 :          0 :                 return ret;
     301                 :            :         }
     302                 :            : 
     303                 :            :         return 0;
     304                 :            : }
     305                 :            : 
     306                 :            : int
     307                 :          0 : virtio_user_dev_set_mac(struct virtio_user_dev *dev)
     308                 :            : {
     309                 :            :         int ret = 0;
     310                 :            : 
     311         [ #  # ]:          0 :         if (!(dev->device_features & (1ULL << VIRTIO_NET_F_MAC)))
     312                 :            :                 return -ENOTSUP;
     313                 :            : 
     314         [ #  # ]:          0 :         if (!dev->ops->set_config)
     315                 :            :                 return -ENOTSUP;
     316                 :            : 
     317                 :          0 :         ret = dev->ops->set_config(dev, dev->mac_addr,
     318                 :            :                         offsetof(struct virtio_net_config, mac),
     319                 :            :                         RTE_ETHER_ADDR_LEN);
     320         [ #  # ]:          0 :         if (ret)
     321                 :          0 :                 PMD_DRV_LOG(ERR, "(%s) Failed to set MAC address in device", dev->path);
     322                 :            : 
     323                 :            :         return ret;
     324                 :            : }
     325                 :            : 
     326                 :            : int
     327                 :          0 : virtio_user_dev_get_mac(struct virtio_user_dev *dev)
     328                 :            : {
     329                 :            :         int ret = 0;
     330                 :            : 
     331         [ #  # ]:          0 :         if (!(dev->device_features & (1ULL << VIRTIO_NET_F_MAC)))
     332                 :            :                 return -ENOTSUP;
     333                 :            : 
     334         [ #  # ]:          0 :         if (!dev->ops->get_config)
     335                 :            :                 return -ENOTSUP;
     336                 :            : 
     337                 :          0 :         ret = dev->ops->get_config(dev, dev->mac_addr,
     338                 :            :                         offsetof(struct virtio_net_config, mac),
     339                 :            :                         RTE_ETHER_ADDR_LEN);
     340         [ #  # ]:          0 :         if (ret)
     341                 :          0 :                 PMD_DRV_LOG(ERR, "(%s) Failed to get MAC address from device", dev->path);
     342                 :            : 
     343                 :            :         return ret;
     344                 :            : }
     345                 :            : 
     346                 :            : static void
     347                 :          0 : virtio_user_dev_init_mac(struct virtio_user_dev *dev, const char *mac)
     348                 :            : {
     349                 :            :         struct rte_ether_addr cmdline_mac;
     350                 :            :         char buf[RTE_ETHER_ADDR_FMT_SIZE];
     351                 :            :         int ret;
     352                 :            : 
     353   [ #  #  #  # ]:          0 :         if (mac && rte_ether_unformat_addr(mac, &cmdline_mac) == 0) {
     354                 :            :                 /*
     355                 :            :                  * MAC address was passed from command-line, try to store
     356                 :            :                  * it in the device if it supports it. Otherwise try to use
     357                 :            :                  * the device one.
     358                 :            :                  */
     359                 :          0 :                 memcpy(dev->mac_addr, &cmdline_mac, RTE_ETHER_ADDR_LEN);
     360                 :          0 :                 dev->mac_specified = 1;
     361                 :            : 
     362                 :            :                 /* Setting MAC may fail, continue to get the device one in this case */
     363                 :          0 :                 virtio_user_dev_set_mac(dev);
     364                 :          0 :                 ret = virtio_user_dev_get_mac(dev);
     365         [ #  # ]:          0 :                 if (ret == -ENOTSUP)
     366                 :          0 :                         goto out;
     367                 :            : 
     368         [ #  # ]:          0 :                 if (memcmp(&cmdline_mac, dev->mac_addr, RTE_ETHER_ADDR_LEN))
     369                 :          0 :                         PMD_DRV_LOG(INFO, "(%s) Device MAC update failed", dev->path);
     370                 :            :         } else {
     371                 :          0 :                 ret = virtio_user_dev_get_mac(dev);
     372         [ #  # ]:          0 :                 if (ret) {
     373                 :          0 :                         PMD_DRV_LOG(ERR, "(%s) No valid MAC in devargs or device, use random",
     374                 :            :                                         dev->path);
     375                 :          0 :                         return;
     376                 :            :                 }
     377                 :            : 
     378                 :          0 :                 dev->mac_specified = 1;
     379                 :            :         }
     380                 :          0 : out:
     381                 :          0 :         rte_ether_format_addr(buf, RTE_ETHER_ADDR_FMT_SIZE,
     382                 :          0 :                         (struct rte_ether_addr *)dev->mac_addr);
     383                 :          0 :         PMD_DRV_LOG(INFO, "(%s) MAC %s specified", dev->path, buf);
     384                 :            : }
     385                 :            : 
     386                 :            : static int
     387                 :          0 : virtio_user_dev_init_notify(struct virtio_user_dev *dev)
     388                 :            : {
     389                 :            :         uint32_t i, j, nr_vq;
     390                 :            :         int callfd;
     391                 :            :         int kickfd;
     392                 :            : 
     393                 :          0 :         nr_vq = dev->max_queue_pairs * 2;
     394         [ #  # ]:          0 :         if (dev->hw_cvq)
     395                 :          0 :                 nr_vq++;
     396                 :            : 
     397         [ #  # ]:          0 :         for (i = 0; i < nr_vq; i++) {
     398                 :            :                 /* May use invalid flag, but some backend uses kickfd and
     399                 :            :                  * callfd as criteria to judge if dev is alive. so finally we
     400                 :            :                  * use real event_fd.
     401                 :            :                  */
     402                 :          0 :                 callfd = eventfd(0, EFD_CLOEXEC | EFD_NONBLOCK);
     403         [ #  # ]:          0 :                 if (callfd < 0) {
     404                 :          0 :                         PMD_DRV_LOG(ERR, "(%s) callfd error, %s", dev->path, strerror(errno));
     405                 :          0 :                         goto err;
     406                 :            :                 }
     407                 :          0 :                 kickfd = eventfd(0, EFD_CLOEXEC | EFD_NONBLOCK);
     408         [ #  # ]:          0 :                 if (kickfd < 0) {
     409                 :          0 :                         close(callfd);
     410                 :          0 :                         PMD_DRV_LOG(ERR, "(%s) kickfd error, %s", dev->path, strerror(errno));
     411                 :          0 :                         goto err;
     412                 :            :                 }
     413                 :          0 :                 dev->callfds[i] = callfd;
     414                 :          0 :                 dev->kickfds[i] = kickfd;
     415                 :            :         }
     416                 :            : 
     417                 :            :         return 0;
     418                 :          0 : err:
     419         [ #  # ]:          0 :         for (j = 0; j < i; j++) {
     420         [ #  # ]:          0 :                 if (dev->kickfds[j] >= 0) {
     421                 :          0 :                         close(dev->kickfds[j]);
     422                 :          0 :                         dev->kickfds[j] = -1;
     423                 :            :                 }
     424         [ #  # ]:          0 :                 if (dev->callfds[j] >= 0) {
     425                 :          0 :                         close(dev->callfds[j]);
     426                 :          0 :                         dev->callfds[j] = -1;
     427                 :            :                 }
     428                 :            :         }
     429                 :            : 
     430                 :            :         return -1;
     431                 :            : }
     432                 :            : 
     433                 :            : static void
     434                 :          0 : virtio_user_dev_uninit_notify(struct virtio_user_dev *dev)
     435                 :            : {
     436                 :            :         uint32_t i;
     437                 :            : 
     438         [ #  # ]:          0 :         for (i = 0; i < dev->max_queue_pairs * 2; ++i) {
     439         [ #  # ]:          0 :                 if (dev->kickfds[i] >= 0) {
     440                 :          0 :                         close(dev->kickfds[i]);
     441                 :          0 :                         dev->kickfds[i] = -1;
     442                 :            :                 }
     443         [ #  # ]:          0 :                 if (dev->callfds[i] >= 0) {
     444                 :          0 :                         close(dev->callfds[i]);
     445                 :          0 :                         dev->callfds[i] = -1;
     446                 :            :                 }
     447                 :            :         }
     448                 :          0 : }
     449                 :            : 
     450                 :            : static int
     451                 :          0 : virtio_user_fill_intr_handle(struct virtio_user_dev *dev)
     452                 :            : {
     453                 :            :         uint32_t i;
     454                 :          0 :         struct rte_eth_dev *eth_dev = &rte_eth_devices[dev->hw.port_id];
     455                 :            : 
     456         [ #  # ]:          0 :         if (eth_dev->intr_handle == NULL) {
     457                 :          0 :                 eth_dev->intr_handle =
     458                 :          0 :                         rte_intr_instance_alloc(RTE_INTR_INSTANCE_F_PRIVATE);
     459         [ #  # ]:          0 :                 if (eth_dev->intr_handle == NULL) {
     460                 :          0 :                         PMD_DRV_LOG(ERR, "(%s) failed to allocate intr_handle", dev->path);
     461                 :          0 :                         return -1;
     462                 :            :                 }
     463                 :            :         }
     464                 :            : 
     465         [ #  # ]:          0 :         for (i = 0; i < dev->max_queue_pairs; ++i) {
     466         [ #  # ]:          0 :                 if (rte_intr_efds_index_set(eth_dev->intr_handle, i,
     467                 :          0 :                                 dev->callfds[2 * i + VTNET_SQ_RQ_QUEUE_IDX]))
     468                 :          0 :                         return -rte_errno;
     469                 :            :         }
     470                 :            : 
     471         [ #  # ]:          0 :         if (rte_intr_nb_efd_set(eth_dev->intr_handle, dev->max_queue_pairs))
     472                 :          0 :                 return -rte_errno;
     473                 :            : 
     474         [ #  # ]:          0 :         if (rte_intr_max_intr_set(eth_dev->intr_handle,
     475                 :          0 :                         dev->max_queue_pairs + 1))
     476                 :          0 :                 return -rte_errno;
     477                 :            : 
     478         [ #  # ]:          0 :         if (rte_intr_type_set(eth_dev->intr_handle, RTE_INTR_HANDLE_VDEV))
     479                 :          0 :                 return -rte_errno;
     480                 :            : 
     481                 :            :         /* For virtio vdev, no need to read counter for clean */
     482         [ #  # ]:          0 :         if (rte_intr_efd_counter_size_set(eth_dev->intr_handle, 0))
     483                 :          0 :                 return -rte_errno;
     484                 :            : 
     485         [ #  # ]:          0 :         if (rte_intr_fd_set(eth_dev->intr_handle, dev->ops->get_intr_fd(dev)))
     486                 :          0 :                 return -rte_errno;
     487                 :            : 
     488                 :            :         return 0;
     489                 :            : }
     490                 :            : 
     491                 :            : static void
     492                 :          0 : virtio_user_mem_event_cb(enum rte_mem_event type __rte_unused,
     493                 :            :                          const void *addr,
     494                 :            :                          size_t len __rte_unused,
     495                 :            :                          void *arg)
     496                 :            : {
     497                 :            :         struct virtio_user_dev *dev = arg;
     498                 :            :         struct rte_memseg_list *msl;
     499                 :            :         uint16_t i;
     500                 :            :         int ret = 0;
     501                 :            : 
     502                 :            :         /* ignore externally allocated memory */
     503                 :          0 :         msl = rte_mem_virt2memseg_list(addr);
     504         [ #  # ]:          0 :         if (msl->external)
     505                 :            :                 return;
     506                 :            : 
     507                 :          0 :         pthread_mutex_lock(&dev->mutex);
     508                 :            : 
     509         [ #  # ]:          0 :         if (dev->started == false)
     510                 :          0 :                 goto exit;
     511                 :            : 
     512                 :            :         /* Step 1: pause the active queues */
     513         [ #  # ]:          0 :         for (i = 0; i < dev->queue_pairs; i++) {
     514                 :          0 :                 ret = dev->ops->enable_qp(dev, i, 0);
     515         [ #  # ]:          0 :                 if (ret < 0)
     516                 :          0 :                         goto exit;
     517                 :            :         }
     518                 :            : 
     519                 :            :         /* Step 2: update memory regions */
     520                 :          0 :         ret = dev->ops->set_memory_table(dev);
     521         [ #  # ]:          0 :         if (ret < 0)
     522                 :          0 :                 goto exit;
     523                 :            : 
     524                 :            :         /* Step 3: resume the active queues */
     525         [ #  # ]:          0 :         for (i = 0; i < dev->queue_pairs; i++) {
     526                 :          0 :                 ret = dev->ops->enable_qp(dev, i, 1);
     527         [ #  # ]:          0 :                 if (ret < 0)
     528                 :          0 :                         goto exit;
     529                 :            :         }
     530                 :            : 
     531                 :          0 : exit:
     532                 :          0 :         pthread_mutex_unlock(&dev->mutex);
     533                 :            : 
     534         [ #  # ]:          0 :         if (ret < 0)
     535                 :          0 :                 PMD_DRV_LOG(ERR, "(%s) Failed to update memory table", dev->path);
     536                 :            : }
     537                 :            : 
     538                 :            : static int
     539                 :          0 : virtio_user_dev_setup(struct virtio_user_dev *dev)
     540                 :            : {
     541         [ #  # ]:          0 :         if (dev->is_server) {
     542         [ #  # ]:          0 :                 if (dev->backend_type != VIRTIO_USER_BACKEND_VHOST_USER) {
     543                 :          0 :                         PMD_DRV_LOG(ERR, "Server mode only supports vhost-user!");
     544                 :          0 :                         return -1;
     545                 :            :                 }
     546                 :            :         }
     547                 :            : 
     548   [ #  #  #  # ]:          0 :         switch (dev->backend_type) {
     549                 :          0 :         case VIRTIO_USER_BACKEND_VHOST_USER:
     550                 :          0 :                 dev->ops = &virtio_ops_user;
     551                 :          0 :                 break;
     552                 :          0 :         case VIRTIO_USER_BACKEND_VHOST_KERNEL:
     553                 :          0 :                 dev->ops = &virtio_ops_kernel;
     554                 :          0 :                 break;
     555                 :          0 :         case VIRTIO_USER_BACKEND_VHOST_VDPA:
     556                 :          0 :                 dev->ops = &virtio_ops_vdpa;
     557                 :          0 :                 break;
     558                 :          0 :         default:
     559                 :          0 :                 PMD_DRV_LOG(ERR, "(%s) Unknown backend type", dev->path);
     560                 :          0 :                 return -1;
     561                 :            :         }
     562                 :            : 
     563         [ #  # ]:          0 :         if (dev->ops->setup(dev) < 0) {
     564                 :          0 :                 PMD_INIT_LOG(ERR, "(%s) Failed to setup backend", dev->path);
     565                 :          0 :                 return -1;
     566                 :            :         }
     567                 :            : 
     568                 :            :         return 0;
     569                 :            : }
     570                 :            : 
     571                 :            : static int
     572                 :          0 : virtio_user_alloc_vrings(struct virtio_user_dev *dev)
     573                 :            : {
     574                 :            :         int i, size, nr_vrings;
     575                 :          0 :         bool packed_ring = !!(dev->device_features & (1ull << VIRTIO_F_RING_PACKED));
     576                 :            : 
     577                 :          0 :         nr_vrings = dev->max_queue_pairs * 2;
     578         [ #  # ]:          0 :         if (dev->device_features & (1ull << VIRTIO_NET_F_MQ))
     579                 :          0 :                 nr_vrings++;
     580                 :            : 
     581                 :          0 :         dev->callfds = rte_zmalloc("virtio_user_dev", nr_vrings * sizeof(*dev->callfds), 0);
     582         [ #  # ]:          0 :         if (!dev->callfds) {
     583                 :          0 :                 PMD_INIT_LOG(ERR, "(%s) Failed to alloc callfds", dev->path);
     584                 :          0 :                 return -1;
     585                 :            :         }
     586                 :            : 
     587                 :          0 :         dev->kickfds = rte_zmalloc("virtio_user_dev", nr_vrings * sizeof(*dev->kickfds), 0);
     588         [ #  # ]:          0 :         if (!dev->kickfds) {
     589                 :          0 :                 PMD_INIT_LOG(ERR, "(%s) Failed to alloc kickfds", dev->path);
     590                 :          0 :                 goto free_callfds;
     591                 :            :         }
     592                 :            : 
     593         [ #  # ]:          0 :         for (i = 0; i < nr_vrings; i++) {
     594                 :          0 :                 dev->callfds[i] = -1;
     595                 :          0 :                 dev->kickfds[i] = -1;
     596                 :            :         }
     597                 :            : 
     598                 :            :         if (packed_ring)
     599                 :            :                 size = sizeof(*dev->vrings.packed);
     600                 :            :         else
     601                 :            :                 size = sizeof(*dev->vrings.split);
     602                 :          0 :         dev->vrings.ptr = rte_zmalloc("virtio_user_dev", nr_vrings * size, 0);
     603         [ #  # ]:          0 :         if (!dev->vrings.ptr) {
     604                 :          0 :                 PMD_INIT_LOG(ERR, "(%s) Failed to alloc vrings metadata", dev->path);
     605                 :          0 :                 goto free_kickfds;
     606                 :            :         }
     607                 :            : 
     608         [ #  # ]:          0 :         if (packed_ring) {
     609                 :          0 :                 dev->packed_queues = rte_zmalloc("virtio_user_dev",
     610                 :            :                                 nr_vrings * sizeof(*dev->packed_queues), 0);
     611         [ #  # ]:          0 :                 if (!dev->packed_queues) {
     612                 :          0 :                         PMD_INIT_LOG(ERR, "(%s) Failed to alloc packed queues metadata",
     613                 :            :                                         dev->path);
     614                 :          0 :                         goto free_vrings;
     615                 :            :                 }
     616                 :            :         }
     617                 :            : 
     618                 :          0 :         dev->qp_enabled = rte_zmalloc("virtio_user_dev",
     619                 :          0 :                         dev->max_queue_pairs * sizeof(*dev->qp_enabled), 0);
     620         [ #  # ]:          0 :         if (!dev->qp_enabled) {
     621                 :          0 :                 PMD_INIT_LOG(ERR, "(%s) Failed to alloc QP enable states", dev->path);
     622                 :          0 :                 goto free_packed_queues;
     623                 :            :         }
     624                 :            : 
     625                 :            :         return 0;
     626                 :            : 
     627                 :            : free_packed_queues:
     628                 :          0 :         rte_free(dev->packed_queues);
     629                 :          0 :         dev->packed_queues = NULL;
     630                 :          0 : free_vrings:
     631                 :          0 :         rte_free(dev->vrings.ptr);
     632                 :          0 :         dev->vrings.ptr = NULL;
     633                 :          0 : free_kickfds:
     634                 :          0 :         rte_free(dev->kickfds);
     635                 :          0 :         dev->kickfds = NULL;
     636                 :          0 : free_callfds:
     637                 :          0 :         rte_free(dev->callfds);
     638                 :          0 :         dev->callfds = NULL;
     639                 :            : 
     640                 :          0 :         return -1;
     641                 :            : }
     642                 :            : 
     643                 :            : static void
     644                 :          0 : virtio_user_free_vrings(struct virtio_user_dev *dev)
     645                 :            : {
     646                 :          0 :         rte_free(dev->qp_enabled);
     647                 :          0 :         dev->qp_enabled = NULL;
     648                 :          0 :         rte_free(dev->packed_queues);
     649                 :          0 :         dev->packed_queues = NULL;
     650                 :          0 :         rte_free(dev->vrings.ptr);
     651                 :          0 :         dev->vrings.ptr = NULL;
     652                 :          0 :         rte_free(dev->kickfds);
     653                 :          0 :         dev->kickfds = NULL;
     654                 :          0 :         rte_free(dev->callfds);
     655                 :          0 :         dev->callfds = NULL;
     656                 :          0 : }
     657                 :            : 
     658                 :            : /* Use below macro to filter features from vhost backend */
     659                 :            : #define VIRTIO_USER_SUPPORTED_FEATURES                  \
     660                 :            :         (1ULL << VIRTIO_NET_F_MAC         |       \
     661                 :            :          1ULL << VIRTIO_NET_F_STATUS              |       \
     662                 :            :          1ULL << VIRTIO_NET_F_MQ          |       \
     663                 :            :          1ULL << VIRTIO_NET_F_CTRL_MAC_ADDR       |       \
     664                 :            :          1ULL << VIRTIO_NET_F_CTRL_VQ             |       \
     665                 :            :          1ULL << VIRTIO_NET_F_CTRL_RX             |       \
     666                 :            :          1ULL << VIRTIO_NET_F_CTRL_VLAN           |       \
     667                 :            :          1ULL << VIRTIO_NET_F_CSUM                |       \
     668                 :            :          1ULL << VIRTIO_NET_F_HOST_TSO4           |       \
     669                 :            :          1ULL << VIRTIO_NET_F_HOST_TSO6           |       \
     670                 :            :          1ULL << VIRTIO_NET_F_MRG_RXBUF           |       \
     671                 :            :          1ULL << VIRTIO_RING_F_INDIRECT_DESC      |       \
     672                 :            :          1ULL << VIRTIO_NET_F_GUEST_CSUM  |       \
     673                 :            :          1ULL << VIRTIO_NET_F_GUEST_TSO4  |       \
     674                 :            :          1ULL << VIRTIO_NET_F_GUEST_TSO6  |       \
     675                 :            :          1ULL << VIRTIO_F_IN_ORDER                |       \
     676                 :            :          1ULL << VIRTIO_F_VERSION_1               |       \
     677                 :            :          1ULL << VIRTIO_F_RING_PACKED)
     678                 :            : 
     679                 :            : int
     680                 :          0 : virtio_user_dev_init(struct virtio_user_dev *dev, char *path, uint16_t queues,
     681                 :            :                      int cq, int queue_size, const char *mac, char **ifname,
     682                 :            :                      int server, int mrg_rxbuf, int in_order, int packed_vq,
     683                 :            :                      enum virtio_user_backend_type backend_type)
     684                 :            : {
     685                 :            :         uint64_t backend_features;
     686                 :            : 
     687                 :          0 :         pthread_mutex_init(&dev->mutex, NULL);
     688                 :          0 :         strlcpy(dev->path, path, PATH_MAX);
     689                 :            : 
     690                 :          0 :         dev->started = 0;
     691                 :          0 :         dev->queue_pairs = 1; /* mq disabled by default */
     692                 :          0 :         dev->max_queue_pairs = queues; /* initialize to user requested value for kernel backend */
     693                 :          0 :         dev->queue_size = queue_size;
     694                 :          0 :         dev->is_server = server;
     695                 :          0 :         dev->mac_specified = 0;
     696                 :          0 :         dev->frontend_features = 0;
     697                 :          0 :         dev->unsupported_features = 0;
     698                 :          0 :         dev->backend_type = backend_type;
     699                 :          0 :         dev->ifname = *ifname;
     700                 :            : 
     701         [ #  # ]:          0 :         if (virtio_user_dev_setup(dev) < 0) {
     702                 :          0 :                 PMD_INIT_LOG(ERR, "(%s) backend set up fails", dev->path);
     703                 :          0 :                 return -1;
     704                 :            :         }
     705                 :            : 
     706         [ #  # ]:          0 :         if (dev->ops->set_owner(dev) < 0) {
     707                 :          0 :                 PMD_INIT_LOG(ERR, "(%s) Failed to set backend owner", dev->path);
     708                 :          0 :                 goto destroy;
     709                 :            :         }
     710                 :            : 
     711         [ #  # ]:          0 :         if (dev->ops->get_backend_features(&backend_features) < 0) {
     712                 :          0 :                 PMD_INIT_LOG(ERR, "(%s) Failed to get backend features", dev->path);
     713                 :          0 :                 goto destroy;
     714                 :            :         }
     715                 :            : 
     716                 :          0 :         dev->unsupported_features = ~(VIRTIO_USER_SUPPORTED_FEATURES | backend_features);
     717                 :            : 
     718         [ #  # ]:          0 :         if (dev->ops->get_features(dev, &dev->device_features) < 0) {
     719                 :          0 :                 PMD_INIT_LOG(ERR, "(%s) Failed to get device features", dev->path);
     720                 :          0 :                 goto destroy;
     721                 :            :         }
     722                 :            : 
     723                 :          0 :         virtio_user_dev_init_mac(dev, mac);
     724                 :            : 
     725         [ #  # ]:          0 :         if (virtio_user_dev_init_max_queue_pairs(dev, queues))
     726                 :          0 :                 dev->unsupported_features |= (1ull << VIRTIO_NET_F_MQ);
     727                 :            : 
     728         [ #  # ]:          0 :         if (dev->max_queue_pairs > 1)
     729                 :            :                 cq = 1;
     730                 :            : 
     731         [ #  # ]:          0 :         if (!mrg_rxbuf)
     732                 :          0 :                 dev->unsupported_features |= (1ull << VIRTIO_NET_F_MRG_RXBUF);
     733                 :            : 
     734         [ #  # ]:          0 :         if (!in_order)
     735                 :          0 :                 dev->unsupported_features |= (1ull << VIRTIO_F_IN_ORDER);
     736                 :            : 
     737         [ #  # ]:          0 :         if (!packed_vq)
     738                 :          0 :                 dev->unsupported_features |= (1ull << VIRTIO_F_RING_PACKED);
     739                 :            : 
     740         [ #  # ]:          0 :         if (dev->mac_specified)
     741                 :          0 :                 dev->frontend_features |= (1ull << VIRTIO_NET_F_MAC);
     742                 :            :         else
     743                 :          0 :                 dev->unsupported_features |= (1ull << VIRTIO_NET_F_MAC);
     744                 :            : 
     745         [ #  # ]:          0 :         if (cq) {
     746                 :            :                 /* device does not really need to know anything about CQ,
     747                 :            :                  * so if necessary, we just claim to support CQ
     748                 :            :                  */
     749                 :          0 :                 dev->frontend_features |= (1ull << VIRTIO_NET_F_CTRL_VQ);
     750                 :            :         } else {
     751                 :          0 :                 dev->unsupported_features |= (1ull << VIRTIO_NET_F_CTRL_VQ);
     752                 :            :                 /* Also disable features that depend on VIRTIO_NET_F_CTRL_VQ */
     753                 :          0 :                 dev->unsupported_features |= (1ull << VIRTIO_NET_F_CTRL_RX);
     754                 :          0 :                 dev->unsupported_features |= (1ull << VIRTIO_NET_F_CTRL_VLAN);
     755                 :          0 :                 dev->unsupported_features |=
     756                 :            :                         (1ull << VIRTIO_NET_F_GUEST_ANNOUNCE);
     757                 :          0 :                 dev->unsupported_features |= (1ull << VIRTIO_NET_F_MQ);
     758                 :          0 :                 dev->unsupported_features |=
     759                 :            :                         (1ull << VIRTIO_NET_F_CTRL_MAC_ADDR);
     760                 :            :         }
     761                 :            : 
     762                 :            :         /* The backend will not report this feature, we add it explicitly */
     763         [ #  # ]:          0 :         if (dev->backend_type == VIRTIO_USER_BACKEND_VHOST_USER)
     764                 :          0 :                 dev->frontend_features |= (1ull << VIRTIO_NET_F_STATUS);
     765                 :            : 
     766                 :          0 :         dev->frontend_features &= ~dev->unsupported_features;
     767                 :          0 :         dev->device_features &= ~dev->unsupported_features;
     768                 :            : 
     769         [ #  # ]:          0 :         if (virtio_user_alloc_vrings(dev) < 0) {
     770                 :          0 :                 PMD_INIT_LOG(ERR, "(%s) Failed to allocate vring metadata", dev->path);
     771                 :          0 :                 goto destroy;
     772                 :            :         }
     773                 :            : 
     774         [ #  # ]:          0 :         if (virtio_user_dev_init_notify(dev) < 0) {
     775                 :          0 :                 PMD_INIT_LOG(ERR, "(%s) Failed to init notifiers", dev->path);
     776                 :          0 :                 goto free_vrings;
     777                 :            :         }
     778                 :            : 
     779         [ #  # ]:          0 :         if (virtio_user_fill_intr_handle(dev) < 0) {
     780                 :          0 :                 PMD_INIT_LOG(ERR, "(%s) Failed to init interrupt handler", dev->path);
     781                 :          0 :                 goto notify_uninit;
     782                 :            :         }
     783                 :            : 
     784         [ #  # ]:          0 :         if (rte_mem_event_callback_register(VIRTIO_USER_MEM_EVENT_CLB_NAME,
     785                 :            :                                 virtio_user_mem_event_cb, dev)) {
     786         [ #  # ]:          0 :                 if (rte_errno != ENOTSUP) {
     787                 :          0 :                         PMD_INIT_LOG(ERR, "(%s) Failed to register mem event callback",
     788                 :            :                                         dev->path);
     789                 :          0 :                         goto notify_uninit;
     790                 :            :                 }
     791                 :            :         }
     792                 :            : 
     793                 :          0 :         *ifname = NULL;
     794                 :          0 :         return 0;
     795                 :            : 
     796                 :          0 : notify_uninit:
     797                 :          0 :         virtio_user_dev_uninit_notify(dev);
     798                 :          0 : free_vrings:
     799                 :          0 :         virtio_user_free_vrings(dev);
     800                 :          0 : destroy:
     801                 :          0 :         dev->ops->destroy(dev);
     802                 :            : 
     803                 :          0 :         return -1;
     804                 :            : }
     805                 :            : 
     806                 :            : void
     807                 :          0 : virtio_user_dev_uninit(struct virtio_user_dev *dev)
     808                 :            : {
     809                 :          0 :         struct rte_eth_dev *eth_dev = &rte_eth_devices[dev->hw.port_id];
     810                 :            : 
     811                 :          0 :         rte_intr_instance_free(eth_dev->intr_handle);
     812                 :          0 :         eth_dev->intr_handle = NULL;
     813                 :            : 
     814                 :          0 :         virtio_user_stop_device(dev);
     815                 :            : 
     816                 :          0 :         rte_mem_event_callback_unregister(VIRTIO_USER_MEM_EVENT_CLB_NAME, dev);
     817                 :            : 
     818                 :          0 :         virtio_user_dev_uninit_notify(dev);
     819                 :            : 
     820                 :          0 :         virtio_user_free_vrings(dev);
     821                 :            : 
     822                 :          0 :         free(dev->ifname);
     823                 :            : 
     824         [ #  # ]:          0 :         if (dev->is_server)
     825                 :          0 :                 unlink(dev->path);
     826                 :            : 
     827                 :          0 :         dev->ops->destroy(dev);
     828                 :          0 : }
     829                 :            : 
     830                 :            : static uint8_t
     831                 :          0 : virtio_user_handle_mq(struct virtio_user_dev *dev, uint16_t q_pairs)
     832                 :            : {
     833                 :            :         uint16_t i;
     834                 :            :         uint8_t ret = 0;
     835                 :            : 
     836         [ #  # ]:          0 :         if (q_pairs > dev->max_queue_pairs) {
     837                 :          0 :                 PMD_INIT_LOG(ERR, "(%s) multi-q config %u, but only %u supported",
     838                 :            :                              dev->path, q_pairs, dev->max_queue_pairs);
     839                 :          0 :                 return -1;
     840                 :            :         }
     841                 :            : 
     842         [ #  # ]:          0 :         for (i = 0; i < q_pairs; ++i)
     843                 :          0 :                 ret |= dev->ops->enable_qp(dev, i, 1);
     844         [ #  # ]:          0 :         for (i = q_pairs; i < dev->max_queue_pairs; ++i)
     845                 :          0 :                 ret |= dev->ops->enable_qp(dev, i, 0);
     846                 :            : 
     847         [ #  # ]:          0 :         if (dev->scvq)
     848                 :          0 :                 ret |= dev->ops->cvq_enable(dev, 1);
     849                 :            : 
     850                 :          0 :         dev->queue_pairs = q_pairs;
     851                 :            : 
     852                 :          0 :         return ret;
     853                 :            : }
     854                 :            : 
     855                 :            : #define CVQ_MAX_DATA_DESCS 32
     856                 :            : 
     857                 :            : static uint32_t
     858                 :          0 : virtio_user_handle_ctrl_msg_split(struct virtio_user_dev *dev, struct vring *vring,
     859                 :            :                             uint16_t idx_hdr)
     860                 :            : {
     861                 :            :         struct virtio_net_ctrl_hdr *hdr;
     862                 :            :         virtio_net_ctrl_ack status = ~0;
     863                 :            :         uint16_t i, idx_data, idx_status;
     864                 :            :         uint32_t n_descs = 0;
     865                 :            :         int dlen[CVQ_MAX_DATA_DESCS], nb_dlen = 0;
     866                 :            : 
     867                 :            :         /* locate desc for header, data, and status */
     868                 :          0 :         idx_data = vring->desc[idx_hdr].next;
     869                 :            :         n_descs++;
     870                 :            : 
     871                 :            :         i = idx_data;
     872         [ #  # ]:          0 :         while (vring->desc[i].flags == VRING_DESC_F_NEXT) {
     873                 :          0 :                 dlen[nb_dlen++] = vring->desc[i].len;
     874                 :          0 :                 i = vring->desc[i].next;
     875                 :          0 :                 n_descs++;
     876                 :            :         }
     877                 :            : 
     878                 :            :         /* locate desc for status */
     879                 :            :         idx_status = i;
     880                 :          0 :         n_descs++;
     881                 :            : 
     882                 :          0 :         hdr = (void *)(uintptr_t)vring->desc[idx_hdr].addr;
     883         [ #  # ]:          0 :         if (hdr->class == VIRTIO_NET_CTRL_MQ &&
     884         [ #  # ]:          0 :             hdr->cmd == VIRTIO_NET_CTRL_MQ_VQ_PAIRS_SET) {
     885                 :            :                 uint16_t queues;
     886                 :            : 
     887                 :          0 :                 queues = *(uint16_t *)(uintptr_t)vring->desc[idx_data].addr;
     888                 :          0 :                 status = virtio_user_handle_mq(dev, queues);
     889         [ #  # ]:          0 :         } else if (hdr->class == VIRTIO_NET_CTRL_RX  ||
     890                 :            :                    hdr->class == VIRTIO_NET_CTRL_MAC ||
     891                 :            :                    hdr->class == VIRTIO_NET_CTRL_VLAN) {
     892                 :            :                 status = 0;
     893                 :            :         }
     894                 :            : 
     895   [ #  #  #  # ]:          0 :         if (!status && dev->scvq)
     896                 :          0 :                 status = virtio_send_command(&dev->scvq->cq,
     897                 :            :                                 (struct virtio_pmd_ctrl *)hdr, dlen, nb_dlen);
     898                 :            : 
     899                 :            :         /* Update status */
     900                 :          0 :         *(virtio_net_ctrl_ack *)(uintptr_t)vring->desc[idx_status].addr = status;
     901                 :            : 
     902                 :          0 :         return n_descs;
     903                 :            : }
     904                 :            : 
     905                 :            : static inline int
     906                 :            : desc_is_avail(struct vring_packed_desc *desc, bool wrap_counter)
     907                 :            : {
     908                 :          0 :         uint16_t flags = __atomic_load_n(&desc->flags, __ATOMIC_ACQUIRE);
     909                 :            : 
     910                 :          0 :         return wrap_counter == !!(flags & VRING_PACKED_DESC_F_AVAIL) &&
     911         [ #  # ]:          0 :                 wrap_counter != !!(flags & VRING_PACKED_DESC_F_USED);
     912                 :            : }
     913                 :            : 
     914                 :            : static uint32_t
     915                 :          0 : virtio_user_handle_ctrl_msg_packed(struct virtio_user_dev *dev,
     916                 :            :                                    struct vring_packed *vring,
     917                 :            :                                    uint16_t idx_hdr)
     918                 :            : {
     919                 :            :         struct virtio_net_ctrl_hdr *hdr;
     920                 :            :         virtio_net_ctrl_ack status = ~0;
     921                 :            :         uint16_t idx_data, idx_status;
     922                 :            :         /* initialize to one, header is first */
     923                 :            :         uint32_t n_descs = 1;
     924                 :            :         int dlen[CVQ_MAX_DATA_DESCS], nb_dlen = 0;
     925                 :            : 
     926                 :            :         /* locate desc for header, data, and status */
     927                 :          0 :         idx_data = idx_hdr + 1;
     928         [ #  # ]:          0 :         if (idx_data >= dev->queue_size)
     929                 :          0 :                 idx_data -= dev->queue_size;
     930                 :            : 
     931                 :            :         n_descs++;
     932                 :            : 
     933                 :            :         idx_status = idx_data;
     934         [ #  # ]:          0 :         while (vring->desc[idx_status].flags & VRING_DESC_F_NEXT) {
     935                 :          0 :                 dlen[nb_dlen++] = vring->desc[idx_status].len;
     936                 :          0 :                 idx_status++;
     937         [ #  # ]:          0 :                 if (idx_status >= dev->queue_size)
     938                 :          0 :                         idx_status -= dev->queue_size;
     939                 :          0 :                 n_descs++;
     940                 :            :         }
     941                 :            : 
     942                 :          0 :         hdr = (void *)(uintptr_t)vring->desc[idx_hdr].addr;
     943         [ #  # ]:          0 :         if (hdr->class == VIRTIO_NET_CTRL_MQ &&
     944         [ #  # ]:          0 :             hdr->cmd == VIRTIO_NET_CTRL_MQ_VQ_PAIRS_SET) {
     945                 :            :                 uint16_t queues;
     946                 :            : 
     947                 :          0 :                 queues = *(uint16_t *)(uintptr_t)
     948                 :          0 :                                 vring->desc[idx_data].addr;
     949                 :          0 :                 status = virtio_user_handle_mq(dev, queues);
     950         [ #  # ]:          0 :         } else if (hdr->class == VIRTIO_NET_CTRL_RX  ||
     951                 :            :                    hdr->class == VIRTIO_NET_CTRL_MAC ||
     952                 :            :                    hdr->class == VIRTIO_NET_CTRL_VLAN) {
     953                 :            :                 status = 0;
     954                 :            :         }
     955                 :            : 
     956   [ #  #  #  # ]:          0 :         if (!status && dev->scvq)
     957                 :          0 :                 status = virtio_send_command(&dev->scvq->cq,
     958                 :            :                                 (struct virtio_pmd_ctrl *)hdr, dlen, nb_dlen);
     959                 :            : 
     960                 :            :         /* Update status */
     961                 :          0 :         *(virtio_net_ctrl_ack *)(uintptr_t)
     962                 :          0 :                 vring->desc[idx_status].addr = status;
     963                 :            : 
     964                 :            :         /* Update used descriptor */
     965                 :          0 :         vring->desc[idx_hdr].id = vring->desc[idx_status].id;
     966                 :          0 :         vring->desc[idx_hdr].len = sizeof(status);
     967                 :            : 
     968                 :          0 :         return n_descs;
     969                 :            : }
     970                 :            : 
     971                 :            : static void
     972                 :          0 : virtio_user_handle_cq_packed(struct virtio_user_dev *dev, uint16_t queue_idx)
     973                 :            : {
     974                 :          0 :         struct virtio_user_queue *vq = &dev->packed_queues[queue_idx];
     975                 :          0 :         struct vring_packed *vring = &dev->vrings.packed[queue_idx];
     976                 :            :         uint16_t n_descs, flags;
     977                 :            : 
     978                 :            :         /* Perform a load-acquire barrier in desc_is_avail to
     979                 :            :          * enforce the ordering between desc flags and desc
     980                 :            :          * content.
     981                 :            :          */
     982                 :          0 :         while (desc_is_avail(&vring->desc[vq->used_idx],
     983         [ #  # ]:          0 :                              vq->used_wrap_counter)) {
     984                 :            : 
     985                 :          0 :                 n_descs = virtio_user_handle_ctrl_msg_packed(dev, vring,
     986                 :          0 :                                 vq->used_idx);
     987                 :            : 
     988                 :            :                 flags = VRING_DESC_F_WRITE;
     989         [ #  # ]:          0 :                 if (vq->used_wrap_counter)
     990                 :            :                         flags |= VRING_PACKED_DESC_F_AVAIL_USED;
     991                 :            : 
     992                 :          0 :                 __atomic_store_n(&vring->desc[vq->used_idx].flags, flags,
     993                 :            :                                  __ATOMIC_RELEASE);
     994                 :            : 
     995                 :          0 :                 vq->used_idx += n_descs;
     996         [ #  # ]:          0 :                 if (vq->used_idx >= dev->queue_size) {
     997                 :          0 :                         vq->used_idx -= dev->queue_size;
     998                 :          0 :                         vq->used_wrap_counter ^= 1;
     999                 :            :                 }
    1000                 :            :         }
    1001                 :          0 : }
    1002                 :            : 
    1003                 :            : static void
    1004                 :          0 : virtio_user_handle_cq_split(struct virtio_user_dev *dev, uint16_t queue_idx)
    1005                 :            : {
    1006                 :            :         uint16_t avail_idx, desc_idx;
    1007                 :            :         struct vring_used_elem *uep;
    1008                 :            :         uint32_t n_descs;
    1009                 :          0 :         struct vring *vring = &dev->vrings.split[queue_idx];
    1010                 :            : 
    1011                 :            :         /* Consume avail ring, using used ring idx as first one */
    1012                 :          0 :         while (__atomic_load_n(&vring->used->idx, __ATOMIC_RELAXED)
    1013         [ #  # ]:          0 :                != vring->avail->idx) {
    1014                 :          0 :                 avail_idx = __atomic_load_n(&vring->used->idx, __ATOMIC_RELAXED)
    1015                 :          0 :                             & (vring->num - 1);
    1016                 :          0 :                 desc_idx = vring->avail->ring[avail_idx];
    1017                 :            : 
    1018                 :          0 :                 n_descs = virtio_user_handle_ctrl_msg_split(dev, vring, desc_idx);
    1019                 :            : 
    1020                 :            :                 /* Update used ring */
    1021                 :          0 :                 uep = &vring->used->ring[avail_idx];
    1022                 :          0 :                 uep->id = desc_idx;
    1023                 :          0 :                 uep->len = n_descs;
    1024                 :            : 
    1025                 :          0 :                 __atomic_fetch_add(&vring->used->idx, 1, __ATOMIC_RELAXED);
    1026                 :            :         }
    1027                 :          0 : }
    1028                 :            : 
    1029                 :            : void
    1030         [ #  # ]:          0 : virtio_user_handle_cq(struct virtio_user_dev *dev, uint16_t queue_idx)
    1031                 :            : {
    1032         [ #  # ]:          0 :         if (virtio_with_packed_queue(&dev->hw))
    1033                 :          0 :                 virtio_user_handle_cq_packed(dev, queue_idx);
    1034                 :            :         else
    1035                 :          0 :                 virtio_user_handle_cq_split(dev, queue_idx);
    1036                 :          0 : }
    1037                 :            : 
    1038                 :            : static void
    1039                 :          0 : virtio_user_control_queue_notify(struct virtqueue *vq, void *cookie)
    1040                 :            : {
    1041                 :            :         struct virtio_user_dev *dev = cookie;
    1042                 :          0 :         uint64_t buf = 1;
    1043                 :            : 
    1044         [ #  # ]:          0 :         if (write(dev->kickfds[vq->vq_queue_index], &buf, sizeof(buf)) < 0)
    1045                 :          0 :                 PMD_DRV_LOG(ERR, "failed to kick backend: %s",
    1046                 :            :                             strerror(errno));
    1047                 :          0 : }
    1048                 :            : 
    1049                 :            : int
    1050                 :          0 : virtio_user_dev_create_shadow_cvq(struct virtio_user_dev *dev, struct virtqueue *vq)
    1051                 :            : {
    1052                 :            :         char name[VIRTQUEUE_MAX_NAME_SZ];
    1053                 :            :         struct virtqueue *scvq;
    1054                 :            : 
    1055                 :          0 :         snprintf(name, sizeof(name), "port%d_shadow_cvq", vq->hw->port_id);
    1056                 :          0 :         scvq = virtqueue_alloc(&dev->hw, vq->vq_queue_index, vq->vq_nentries,
    1057                 :            :                         VTNET_CQ, SOCKET_ID_ANY, name);
    1058         [ #  # ]:          0 :         if (!scvq) {
    1059                 :          0 :                 PMD_INIT_LOG(ERR, "(%s) Failed to alloc shadow control vq\n", dev->path);
    1060                 :          0 :                 return -ENOMEM;
    1061                 :            :         }
    1062                 :            : 
    1063                 :          0 :         scvq->cq.notify_queue = &virtio_user_control_queue_notify;
    1064                 :          0 :         scvq->cq.notify_cookie = dev;
    1065                 :          0 :         dev->scvq = scvq;
    1066                 :            : 
    1067                 :          0 :         return 0;
    1068                 :            : }
    1069                 :            : 
    1070                 :            : void
    1071                 :          0 : virtio_user_dev_destroy_shadow_cvq(struct virtio_user_dev *dev)
    1072                 :            : {
    1073         [ #  # ]:          0 :         if (!dev->scvq)
    1074                 :            :                 return;
    1075                 :            : 
    1076                 :          0 :         virtqueue_free(dev->scvq);
    1077                 :          0 :         dev->scvq = NULL;
    1078                 :            : }
    1079                 :            : 
    1080                 :            : int
    1081                 :          0 : virtio_user_dev_set_status(struct virtio_user_dev *dev, uint8_t status)
    1082                 :            : {
    1083                 :            :         int ret;
    1084                 :            : 
    1085                 :          0 :         pthread_mutex_lock(&dev->mutex);
    1086                 :          0 :         dev->status = status;
    1087                 :          0 :         ret = dev->ops->set_status(dev, status);
    1088         [ #  # ]:          0 :         if (ret && ret != -ENOTSUP)
    1089                 :          0 :                 PMD_INIT_LOG(ERR, "(%s) Failed to set backend status", dev->path);
    1090                 :            : 
    1091                 :          0 :         pthread_mutex_unlock(&dev->mutex);
    1092                 :          0 :         return ret;
    1093                 :            : }
    1094                 :            : 
    1095                 :            : int
    1096                 :          0 : virtio_user_dev_update_status(struct virtio_user_dev *dev)
    1097                 :            : {
    1098                 :            :         int ret;
    1099                 :            :         uint8_t status;
    1100                 :            : 
    1101                 :          0 :         pthread_mutex_lock(&dev->mutex);
    1102                 :            : 
    1103                 :          0 :         ret = dev->ops->get_status(dev, &status);
    1104         [ #  # ]:          0 :         if (!ret) {
    1105                 :          0 :                 dev->status = status;
    1106                 :          0 :                 PMD_INIT_LOG(DEBUG, "Updated Device Status(0x%08x):\n"
    1107                 :            :                         "\t-RESET: %u\n"
    1108                 :            :                         "\t-ACKNOWLEDGE: %u\n"
    1109                 :            :                         "\t-DRIVER: %u\n"
    1110                 :            :                         "\t-DRIVER_OK: %u\n"
    1111                 :            :                         "\t-FEATURES_OK: %u\n"
    1112                 :            :                         "\t-DEVICE_NEED_RESET: %u\n"
    1113                 :            :                         "\t-FAILED: %u",
    1114                 :            :                         dev->status,
    1115                 :            :                         (dev->status == VIRTIO_CONFIG_STATUS_RESET),
    1116                 :            :                         !!(dev->status & VIRTIO_CONFIG_STATUS_ACK),
    1117                 :            :                         !!(dev->status & VIRTIO_CONFIG_STATUS_DRIVER),
    1118                 :            :                         !!(dev->status & VIRTIO_CONFIG_STATUS_DRIVER_OK),
    1119                 :            :                         !!(dev->status & VIRTIO_CONFIG_STATUS_FEATURES_OK),
    1120                 :            :                         !!(dev->status & VIRTIO_CONFIG_STATUS_DEV_NEED_RESET),
    1121                 :            :                         !!(dev->status & VIRTIO_CONFIG_STATUS_FAILED));
    1122         [ #  # ]:          0 :         } else if (ret != -ENOTSUP) {
    1123                 :          0 :                 PMD_INIT_LOG(ERR, "(%s) Failed to get backend status", dev->path);
    1124                 :            :         }
    1125                 :            : 
    1126                 :          0 :         pthread_mutex_unlock(&dev->mutex);
    1127                 :          0 :         return ret;
    1128                 :            : }
    1129                 :            : 
    1130                 :            : int
    1131                 :          0 : virtio_user_dev_update_link_state(struct virtio_user_dev *dev)
    1132                 :            : {
    1133         [ #  # ]:          0 :         if (dev->ops->update_link_state)
    1134                 :          0 :                 return dev->ops->update_link_state(dev);
    1135                 :            : 
    1136                 :            :         return 0;
    1137                 :            : }
    1138                 :            : 
    1139                 :            : static void
    1140                 :          0 : virtio_user_dev_reset_queues_packed(struct rte_eth_dev *eth_dev)
    1141                 :            : {
    1142                 :          0 :         struct virtio_user_dev *dev = eth_dev->data->dev_private;
    1143                 :            :         struct virtio_hw *hw = &dev->hw;
    1144                 :            :         struct virtnet_rx *rxvq;
    1145                 :            :         struct virtnet_tx *txvq;
    1146                 :            :         uint16_t i;
    1147                 :            : 
    1148                 :            :         /* Add lock to avoid queue contention. */
    1149                 :          0 :         rte_spinlock_lock(&hw->state_lock);
    1150                 :          0 :         hw->started = 0;
    1151                 :            : 
    1152                 :            :         /*
    1153                 :            :          * Waiting for datapath to complete before resetting queues.
    1154                 :            :          * 1 ms should be enough for the ongoing Tx/Rx function to finish.
    1155                 :            :          */
    1156                 :            :         rte_delay_ms(1);
    1157                 :            : 
    1158                 :            :         /* Vring reset for each Tx queue and Rx queue. */
    1159         [ #  # ]:          0 :         for (i = 0; i < eth_dev->data->nb_rx_queues; i++) {
    1160                 :          0 :                 rxvq = eth_dev->data->rx_queues[i];
    1161                 :          0 :                 virtqueue_rxvq_reset_packed(virtnet_rxq_to_vq(rxvq));
    1162                 :          0 :                 virtio_dev_rx_queue_setup_finish(eth_dev, i);
    1163                 :            :         }
    1164                 :            : 
    1165         [ #  # ]:          0 :         for (i = 0; i < eth_dev->data->nb_tx_queues; i++) {
    1166                 :          0 :                 txvq = eth_dev->data->tx_queues[i];
    1167                 :          0 :                 virtqueue_txvq_reset_packed(virtnet_txq_to_vq(txvq));
    1168                 :            :         }
    1169                 :            : 
    1170                 :          0 :         hw->started = 1;
    1171                 :            :         rte_spinlock_unlock(&hw->state_lock);
    1172                 :          0 : }
    1173                 :            : 
    1174                 :            : void
    1175                 :          0 : virtio_user_dev_delayed_disconnect_handler(void *param)
    1176                 :            : {
    1177                 :            :         struct virtio_user_dev *dev = param;
    1178                 :          0 :         struct rte_eth_dev *eth_dev = &rte_eth_devices[dev->hw.port_id];
    1179                 :            : 
    1180         [ #  # ]:          0 :         if (rte_intr_disable(eth_dev->intr_handle) < 0) {
    1181                 :          0 :                 PMD_DRV_LOG(ERR, "interrupt disable failed");
    1182                 :          0 :                 return;
    1183                 :            :         }
    1184                 :          0 :         PMD_DRV_LOG(DEBUG, "Unregistering intr fd: %d",
    1185                 :            :                     rte_intr_fd_get(eth_dev->intr_handle));
    1186         [ #  # ]:          0 :         if (rte_intr_callback_unregister(eth_dev->intr_handle,
    1187                 :            :                                          virtio_interrupt_handler,
    1188                 :            :                                          eth_dev) != 1)
    1189                 :          0 :                 PMD_DRV_LOG(ERR, "interrupt unregister failed");
    1190                 :            : 
    1191         [ #  # ]:          0 :         if (dev->is_server) {
    1192         [ #  # ]:          0 :                 if (dev->ops->server_disconnect)
    1193                 :          0 :                         dev->ops->server_disconnect(dev);
    1194                 :            : 
    1195                 :          0 :                 rte_intr_fd_set(eth_dev->intr_handle,
    1196                 :          0 :                         dev->ops->get_intr_fd(dev));
    1197                 :            : 
    1198                 :          0 :                 PMD_DRV_LOG(DEBUG, "Registering intr fd: %d",
    1199                 :            :                             rte_intr_fd_get(eth_dev->intr_handle));
    1200                 :            : 
    1201         [ #  # ]:          0 :                 if (rte_intr_callback_register(eth_dev->intr_handle,
    1202                 :            :                                                virtio_interrupt_handler,
    1203                 :            :                                                eth_dev))
    1204                 :          0 :                         PMD_DRV_LOG(ERR, "interrupt register failed");
    1205                 :            : 
    1206         [ #  # ]:          0 :                 if (rte_intr_enable(eth_dev->intr_handle) < 0) {
    1207                 :          0 :                         PMD_DRV_LOG(ERR, "interrupt enable failed");
    1208                 :          0 :                         return;
    1209                 :            :                 }
    1210                 :            :         }
    1211                 :            : }
    1212                 :            : 
    1213                 :            : static void
    1214                 :          0 : virtio_user_dev_delayed_intr_reconfig_handler(void *param)
    1215                 :            : {
    1216                 :            :         struct virtio_user_dev *dev = param;
    1217                 :          0 :         struct rte_eth_dev *eth_dev = &rte_eth_devices[dev->hw.port_id];
    1218                 :            : 
    1219                 :          0 :         PMD_DRV_LOG(DEBUG, "Unregistering intr fd: %d",
    1220                 :            :                     rte_intr_fd_get(eth_dev->intr_handle));
    1221                 :            : 
    1222         [ #  # ]:          0 :         if (rte_intr_callback_unregister(eth_dev->intr_handle,
    1223                 :            :                                          virtio_interrupt_handler,
    1224                 :            :                                          eth_dev) != 1)
    1225                 :          0 :                 PMD_DRV_LOG(ERR, "interrupt unregister failed");
    1226                 :            : 
    1227                 :          0 :         rte_intr_fd_set(eth_dev->intr_handle, dev->ops->get_intr_fd(dev));
    1228                 :            : 
    1229                 :          0 :         PMD_DRV_LOG(DEBUG, "Registering intr fd: %d",
    1230                 :            :                     rte_intr_fd_get(eth_dev->intr_handle));
    1231                 :            : 
    1232         [ #  # ]:          0 :         if (rte_intr_callback_register(eth_dev->intr_handle,
    1233                 :            :                                        virtio_interrupt_handler, eth_dev))
    1234                 :          0 :                 PMD_DRV_LOG(ERR, "interrupt register failed");
    1235                 :            : 
    1236         [ #  # ]:          0 :         if (rte_intr_enable(eth_dev->intr_handle) < 0)
    1237                 :          0 :                 PMD_DRV_LOG(ERR, "interrupt enable failed");
    1238                 :          0 : }
    1239                 :            : 
    1240                 :            : int
    1241                 :          0 : virtio_user_dev_server_reconnect(struct virtio_user_dev *dev)
    1242                 :            : {
    1243                 :            :         int ret, old_status;
    1244                 :          0 :         struct rte_eth_dev *eth_dev = &rte_eth_devices[dev->hw.port_id];
    1245                 :          0 :         struct virtio_hw *hw = &dev->hw;
    1246                 :            : 
    1247         [ #  # ]:          0 :         if (!dev->ops->server_reconnect) {
    1248                 :          0 :                 PMD_DRV_LOG(ERR, "(%s) Missing server reconnect callback", dev->path);
    1249                 :          0 :                 return -1;
    1250                 :            :         }
    1251                 :            : 
    1252         [ #  # ]:          0 :         if (dev->ops->server_reconnect(dev)) {
    1253                 :          0 :                 PMD_DRV_LOG(ERR, "(%s) Reconnect callback call failed", dev->path);
    1254                 :          0 :                 return -1;
    1255                 :            :         }
    1256                 :            : 
    1257                 :          0 :         old_status = dev->status;
    1258                 :            : 
    1259                 :          0 :         virtio_reset(hw);
    1260                 :            : 
    1261                 :          0 :         virtio_set_status(hw, VIRTIO_CONFIG_STATUS_ACK);
    1262                 :            : 
    1263                 :          0 :         virtio_set_status(hw, VIRTIO_CONFIG_STATUS_DRIVER);
    1264                 :            : 
    1265         [ #  # ]:          0 :         if (dev->ops->get_features(dev, &dev->device_features) < 0) {
    1266                 :          0 :                 PMD_INIT_LOG(ERR, "get_features failed: %s",
    1267                 :            :                              strerror(errno));
    1268                 :          0 :                 return -1;
    1269                 :            :         }
    1270                 :            : 
    1271                 :            :         /* unmask vhost-user unsupported features */
    1272                 :          0 :         dev->device_features &= ~(dev->unsupported_features);
    1273                 :            : 
    1274         [ #  # ]:          0 :         dev->features &= (dev->device_features | dev->frontend_features);
    1275                 :            : 
    1276                 :            :         /* For packed ring, resetting queues is required in reconnection. */
    1277   [ #  #  #  # ]:          0 :         if (virtio_with_packed_queue(hw) &&
    1278                 :            :            (old_status & VIRTIO_CONFIG_STATUS_DRIVER_OK)) {
    1279                 :          0 :                 PMD_INIT_LOG(NOTICE, "Packets on the fly will be dropped"
    1280                 :            :                                 " when packed ring reconnecting.");
    1281                 :          0 :                 virtio_user_dev_reset_queues_packed(eth_dev);
    1282                 :            :         }
    1283                 :            : 
    1284                 :          0 :         virtio_set_status(hw, VIRTIO_CONFIG_STATUS_FEATURES_OK);
    1285                 :            : 
    1286                 :            :         /* Start the device */
    1287                 :          0 :         virtio_set_status(hw, VIRTIO_CONFIG_STATUS_DRIVER_OK);
    1288         [ #  # ]:          0 :         if (!dev->started)
    1289                 :            :                 return -1;
    1290                 :            : 
    1291         [ #  # ]:          0 :         if (dev->queue_pairs > 1) {
    1292                 :          0 :                 ret = virtio_user_handle_mq(dev, dev->queue_pairs);
    1293         [ #  # ]:          0 :                 if (ret != 0) {
    1294                 :          0 :                         PMD_INIT_LOG(ERR, "Fails to enable multi-queue pairs!");
    1295                 :          0 :                         return -1;
    1296                 :            :                 }
    1297                 :            :         }
    1298         [ #  # ]:          0 :         if (eth_dev->data->dev_flags & RTE_ETH_DEV_INTR_LSC) {
    1299         [ #  # ]:          0 :                 if (rte_intr_disable(eth_dev->intr_handle) < 0) {
    1300                 :          0 :                         PMD_DRV_LOG(ERR, "interrupt disable failed");
    1301                 :          0 :                         return -1;
    1302                 :            :                 }
    1303                 :            :                 /*
    1304                 :            :                  * This function can be called from the interrupt handler, so
    1305                 :            :                  * we can't unregister interrupt handler here.  Setting
    1306                 :            :                  * alarm to do that later.
    1307                 :            :                  */
    1308                 :          0 :                 rte_eal_alarm_set(1,
    1309                 :            :                         virtio_user_dev_delayed_intr_reconfig_handler,
    1310                 :            :                         (void *)dev);
    1311                 :            :         }
    1312                 :          0 :         PMD_INIT_LOG(NOTICE, "server mode virtio-user reconnection succeeds!");
    1313                 :          0 :         return 0;
    1314                 :            : }

Generated by: LCOV version 1.14