LCOV - code coverage report
Current view: top level - drivers/vdpa/sfc - sfc_vdpa_ops.c (source / functions) Hit Total Coverage
Test: Code coverage Lines: 0 375 0.0 %
Date: 2025-11-01 17:50:34 Functions: 0 24 0.0 %
Legend: Lines: hit not hit | Branches: + taken - not taken # not executed Branches: 0 136 0.0 %

           Branch data     Line data    Source code
       1                 :            : /* SPDX-License-Identifier: BSD-3-Clause
       2                 :            :  * Copyright(c) 2020-2021 Xilinx, Inc.
       3                 :            :  */
       4                 :            : 
       5                 :            : #include <uapi/linux/vfio.h>
       6                 :            : 
       7                 :            : #include <pthread.h>
       8                 :            : #include <unistd.h>
       9                 :            : #include <sys/ioctl.h>
      10                 :            : 
      11                 :            : #include <rte_errno.h>
      12                 :            : #include <rte_malloc.h>
      13                 :            : #include <rte_vdpa.h>
      14                 :            : #include <rte_vhost.h>
      15                 :            : 
      16                 :            : #include <vdpa_driver.h>
      17                 :            : 
      18                 :            : #include "efx.h"
      19                 :            : #include "sfc_vdpa_ops.h"
      20                 :            : #include "sfc_vdpa.h"
      21                 :            : 
      22                 :            : /* These protocol features are needed to enable notifier ctrl */
      23                 :            : #define SFC_VDPA_PROTOCOL_FEATURES \
      24                 :            :                 ((1ULL << VHOST_USER_PROTOCOL_F_REPLY_ACK) | \
      25                 :            :                  (1ULL << VHOST_USER_PROTOCOL_F_BACKEND_REQ) | \
      26                 :            :                  (1ULL << VHOST_USER_PROTOCOL_F_BACKEND_SEND_FD) | \
      27                 :            :                  (1ULL << VHOST_USER_PROTOCOL_F_HOST_NOTIFIER) | \
      28                 :            :                  (1ULL << VHOST_USER_PROTOCOL_F_LOG_SHMFD) | \
      29                 :            :                  (1ULL << VHOST_USER_PROTOCOL_F_MQ))
      30                 :            : 
      31                 :            : /*
      32                 :            :  * Set of features which are enabled by default.
      33                 :            :  * Protocol feature bit is needed to enable notification notifier ctrl.
      34                 :            :  */
      35                 :            : #define SFC_VDPA_DEFAULT_FEATURES \
      36                 :            :                 ((1ULL << VHOST_USER_F_PROTOCOL_FEATURES) | \
      37                 :            :                  (1ULL << VIRTIO_NET_F_MQ))
      38                 :            : 
      39                 :            : #define SFC_VDPA_MSIX_IRQ_SET_BUF_LEN \
      40                 :            :                 (sizeof(struct vfio_irq_set) + \
      41                 :            :                 sizeof(int) * (SFC_VDPA_MAX_QUEUE_PAIRS * 2 + 1))
      42                 :            : 
      43                 :            : /* It will be used for target VF when calling function is not PF */
      44                 :            : #define SFC_VDPA_VF_NULL                0xFFFF
      45                 :            : 
      46                 :            : static int
      47                 :          0 : sfc_vdpa_get_device_features(struct sfc_vdpa_ops_data *ops_data)
      48                 :            : {
      49                 :            :         int rc;
      50                 :            :         uint64_t dev_features;
      51                 :            :         efx_nic_t *nic;
      52                 :            : 
      53                 :          0 :         nic = sfc_vdpa_adapter_by_dev_handle(ops_data->dev_handle)->nic;
      54                 :            : 
      55                 :          0 :         rc = efx_virtio_get_features(nic, EFX_VIRTIO_DEVICE_TYPE_NET,
      56                 :            :                                      &dev_features);
      57         [ #  # ]:          0 :         if (rc != 0) {
      58                 :          0 :                 sfc_vdpa_err(ops_data->dev_handle,
      59                 :            :                              "could not read device feature: %s",
      60                 :            :                              rte_strerror(rc));
      61                 :          0 :                 return rc;
      62                 :            :         }
      63                 :            : 
      64                 :          0 :         ops_data->dev_features = dev_features;
      65                 :            : 
      66                 :          0 :         sfc_vdpa_info(ops_data->dev_handle,
      67                 :            :                       "device supported virtio features : 0x%" PRIx64,
      68                 :            :                       ops_data->dev_features);
      69                 :            : 
      70                 :          0 :         return 0;
      71                 :            : }
      72                 :            : 
      73                 :            : static uint64_t
      74                 :          0 : hva_to_gpa(int vid, uint64_t hva)
      75                 :            : {
      76                 :          0 :         struct rte_vhost_memory *vhost_mem = NULL;
      77                 :            :         struct rte_vhost_mem_region *mem_reg = NULL;
      78                 :            :         uint32_t i;
      79                 :            :         uint64_t gpa = 0;
      80                 :            : 
      81         [ #  # ]:          0 :         if (rte_vhost_get_mem_table(vid, &vhost_mem) < 0)
      82                 :          0 :                 goto error;
      83                 :            : 
      84         [ #  # ]:          0 :         for (i = 0; i < vhost_mem->nregions; i++) {
      85                 :            :                 mem_reg = &vhost_mem->regions[i];
      86                 :            : 
      87         [ #  # ]:          0 :                 if (hva >= mem_reg->host_user_addr &&
      88         [ #  # ]:          0 :                                 hva < mem_reg->host_user_addr + mem_reg->size) {
      89                 :          0 :                         gpa = (hva - mem_reg->host_user_addr) +
      90                 :          0 :                                 mem_reg->guest_phys_addr;
      91                 :          0 :                         break;
      92                 :            :                 }
      93                 :            :         }
      94                 :            : 
      95                 :          0 : error:
      96                 :          0 :         free(vhost_mem);
      97                 :          0 :         return gpa;
      98                 :            : }
      99                 :            : 
     100                 :            : static int
     101                 :          0 : sfc_vdpa_enable_vfio_intr(struct sfc_vdpa_ops_data *ops_data)
     102                 :            : {
     103                 :            :         int rc;
     104                 :            :         int *irq_fd_ptr;
     105                 :            :         int vfio_dev_fd;
     106                 :            :         uint32_t i, num_vring;
     107                 :            :         struct rte_vhost_vring vring;
     108                 :            :         struct vfio_irq_set *irq_set;
     109                 :            :         struct rte_pci_device *pci_dev;
     110                 :            :         char irq_set_buf[SFC_VDPA_MSIX_IRQ_SET_BUF_LEN];
     111                 :            :         void *dev;
     112                 :            : 
     113                 :          0 :         num_vring = rte_vhost_get_vring_num(ops_data->vid);
     114                 :          0 :         dev = ops_data->dev_handle;
     115                 :          0 :         vfio_dev_fd = sfc_vdpa_adapter_by_dev_handle(dev)->vfio_dev_fd;
     116                 :          0 :         pci_dev = sfc_vdpa_adapter_by_dev_handle(dev)->pdev;
     117                 :            : 
     118                 :            :         irq_set = (struct vfio_irq_set *)irq_set_buf;
     119                 :          0 :         irq_set->argsz = sizeof(irq_set_buf);
     120                 :          0 :         irq_set->count = num_vring + 1;
     121                 :          0 :         irq_set->flags = VFIO_IRQ_SET_DATA_EVENTFD |
     122                 :            :                          VFIO_IRQ_SET_ACTION_TRIGGER;
     123                 :          0 :         irq_set->index = VFIO_PCI_MSIX_IRQ_INDEX;
     124                 :          0 :         irq_set->start = 0;
     125                 :            :         irq_fd_ptr = (int *)&irq_set->data;
     126                 :          0 :         irq_fd_ptr[RTE_INTR_VEC_ZERO_OFFSET] =
     127                 :          0 :                 rte_intr_fd_get(pci_dev->intr_handle);
     128                 :            : 
     129         [ #  # ]:          0 :         for (i = 0; i < num_vring; i++) {
     130                 :          0 :                 rc = rte_vhost_get_vhost_vring(ops_data->vid, i, &vring);
     131         [ #  # ]:          0 :                 if (rc)
     132                 :            :                         return -1;
     133                 :            : 
     134                 :          0 :                 irq_fd_ptr[RTE_INTR_VEC_RXTX_OFFSET + i] = vring.callfd;
     135                 :            :         }
     136                 :            : 
     137                 :          0 :         rc = ioctl(vfio_dev_fd, VFIO_DEVICE_SET_IRQS, irq_set);
     138         [ #  # ]:          0 :         if (rc) {
     139                 :          0 :                 sfc_vdpa_err(ops_data->dev_handle,
     140                 :            :                              "error enabling MSI-X interrupts: %s",
     141                 :            :                              strerror(errno));
     142                 :          0 :                 return -1;
     143                 :            :         }
     144                 :            : 
     145                 :            :         return 0;
     146                 :            : }
     147                 :            : 
     148                 :            : static int
     149                 :          0 : sfc_vdpa_disable_vfio_intr(struct sfc_vdpa_ops_data *ops_data)
     150                 :            : {
     151                 :            :         int rc;
     152                 :            :         int vfio_dev_fd;
     153                 :            :         struct vfio_irq_set irq_set;
     154                 :            :         void *dev;
     155                 :            : 
     156                 :          0 :         dev = ops_data->dev_handle;
     157                 :          0 :         vfio_dev_fd = sfc_vdpa_adapter_by_dev_handle(dev)->vfio_dev_fd;
     158                 :            : 
     159                 :          0 :         irq_set.argsz = sizeof(irq_set);
     160                 :          0 :         irq_set.count = 0;
     161                 :          0 :         irq_set.flags = VFIO_IRQ_SET_DATA_NONE | VFIO_IRQ_SET_ACTION_TRIGGER;
     162                 :          0 :         irq_set.index = VFIO_PCI_MSIX_IRQ_INDEX;
     163                 :          0 :         irq_set.start = 0;
     164                 :            : 
     165                 :          0 :         rc = ioctl(vfio_dev_fd, VFIO_DEVICE_SET_IRQS, &irq_set);
     166         [ #  # ]:          0 :         if (rc) {
     167                 :          0 :                 sfc_vdpa_err(ops_data->dev_handle,
     168                 :            :                              "error disabling MSI-X interrupts: %s",
     169                 :            :                              strerror(errno));
     170                 :          0 :                 return -1;
     171                 :            :         }
     172                 :            : 
     173                 :            :         return 0;
     174                 :            : }
     175                 :            : 
     176                 :            : static int
     177                 :          0 : sfc_vdpa_get_vring_info(struct sfc_vdpa_ops_data *ops_data,
     178                 :            :                         int vq_num, struct sfc_vdpa_vring_info *vring)
     179                 :            : {
     180                 :            :         int rc;
     181                 :            :         uint64_t gpa;
     182                 :            :         struct rte_vhost_vring vq;
     183                 :            : 
     184                 :          0 :         rc = rte_vhost_get_vhost_vring(ops_data->vid, vq_num, &vq);
     185         [ #  # ]:          0 :         if (rc < 0) {
     186                 :          0 :                 sfc_vdpa_err(ops_data->dev_handle,
     187                 :            :                              "get vhost vring failed: %s", rte_strerror(rc));
     188                 :          0 :                 return rc;
     189                 :            :         }
     190                 :            : 
     191                 :          0 :         gpa = hva_to_gpa(ops_data->vid, (uint64_t)(uintptr_t)vq.desc);
     192         [ #  # ]:          0 :         if (gpa == 0) {
     193                 :          0 :                 sfc_vdpa_err(ops_data->dev_handle,
     194                 :            :                              "fail to get GPA for descriptor ring.");
     195                 :          0 :                 return -1;
     196                 :            :         }
     197                 :          0 :         vring->desc = gpa;
     198                 :            : 
     199                 :          0 :         gpa = hva_to_gpa(ops_data->vid, (uint64_t)(uintptr_t)vq.avail);
     200         [ #  # ]:          0 :         if (gpa == 0) {
     201                 :          0 :                 sfc_vdpa_err(ops_data->dev_handle,
     202                 :            :                              "fail to get GPA for available ring.");
     203                 :          0 :                 return -1;
     204                 :            :         }
     205                 :          0 :         vring->avail = gpa;
     206                 :            : 
     207                 :          0 :         gpa = hva_to_gpa(ops_data->vid, (uint64_t)(uintptr_t)vq.used);
     208         [ #  # ]:          0 :         if (gpa == 0) {
     209                 :          0 :                 sfc_vdpa_err(ops_data->dev_handle,
     210                 :            :                              "fail to get GPA for used ring.");
     211                 :          0 :                 return -1;
     212                 :            :         }
     213                 :          0 :         vring->used = gpa;
     214                 :            : 
     215                 :          0 :         vring->size = vq.size;
     216                 :            : 
     217                 :          0 :         rc = rte_vhost_get_vring_base(ops_data->vid, vq_num,
     218                 :            :                                       &vring->last_avail_idx,
     219                 :            :                                       &vring->last_used_idx);
     220                 :            : 
     221                 :          0 :         return rc;
     222                 :            : }
     223                 :            : 
     224                 :            : static int
     225                 :          0 : sfc_vdpa_virtq_start(struct sfc_vdpa_ops_data *ops_data, int vq_num)
     226                 :            : {
     227                 :            :         int rc;
     228                 :            :         uint32_t doorbell;
     229                 :            :         efx_virtio_vq_t *vq;
     230                 :            :         struct sfc_vdpa_vring_info vring;
     231                 :            :         efx_virtio_vq_cfg_t vq_cfg;
     232                 :            :         efx_virtio_vq_dyncfg_t vq_dyncfg;
     233                 :            : 
     234                 :          0 :         vq = ops_data->vq_cxt[vq_num].vq;
     235         [ #  # ]:          0 :         if (vq == NULL)
     236                 :            :                 return -1;
     237                 :            : 
     238                 :          0 :         rc = sfc_vdpa_get_vring_info(ops_data, vq_num, &vring);
     239         [ #  # ]:          0 :         if (rc < 0) {
     240                 :          0 :                 sfc_vdpa_err(ops_data->dev_handle,
     241                 :            :                              "get vring info failed: %s", rte_strerror(rc));
     242                 :          0 :                 goto fail_vring_info;
     243                 :            :         }
     244                 :            : 
     245                 :          0 :         vq_cfg.evvc_target_vf = SFC_VDPA_VF_NULL;
     246                 :            : 
     247                 :            :         /* even virtqueue for RX and odd for TX */
     248         [ #  # ]:          0 :         if (vq_num % 2) {
     249                 :          0 :                 vq_cfg.evvc_type = EFX_VIRTIO_VQ_TYPE_NET_TXQ;
     250                 :          0 :                 sfc_vdpa_info(ops_data->dev_handle,
     251                 :            :                               "configure virtqueue # %d (TXQ)", vq_num);
     252                 :            :         } else {
     253                 :          0 :                 vq_cfg.evvc_type = EFX_VIRTIO_VQ_TYPE_NET_RXQ;
     254                 :          0 :                 sfc_vdpa_info(ops_data->dev_handle,
     255                 :            :                               "configure virtqueue # %d (RXQ)", vq_num);
     256                 :            :         }
     257                 :            : 
     258                 :          0 :         vq_cfg.evvc_vq_num = vq_num;
     259                 :          0 :         vq_cfg.evvc_desc_tbl_addr   = vring.desc;
     260                 :          0 :         vq_cfg.evvc_avail_ring_addr = vring.avail;
     261                 :          0 :         vq_cfg.evvc_used_ring_addr  = vring.used;
     262                 :          0 :         vq_cfg.evvc_vq_size = vring.size;
     263                 :            : 
     264                 :          0 :         vq_dyncfg.evvd_vq_used_idx  = vring.last_used_idx;
     265                 :          0 :         vq_dyncfg.evvd_vq_avail_idx = vring.last_avail_idx;
     266                 :            : 
     267                 :            :         /* MSI-X vector is function-relative */
     268                 :          0 :         vq_cfg.evvc_msix_vector = RTE_INTR_VEC_RXTX_OFFSET + vq_num;
     269         [ #  # ]:          0 :         if (ops_data->vdpa_context == SFC_VDPA_AS_VF)
     270                 :          0 :                 vq_cfg.evvc_pas_id = 0;
     271                 :          0 :         vq_cfg.evcc_features = ops_data->dev_features &
     272                 :          0 :                                ops_data->req_features;
     273                 :            : 
     274                 :            :         /* Start virtqueue */
     275                 :          0 :         rc = efx_virtio_qstart(vq, &vq_cfg, &vq_dyncfg);
     276         [ #  # ]:          0 :         if (rc != 0) {
     277                 :          0 :                 sfc_vdpa_err(ops_data->dev_handle,
     278                 :            :                              "virtqueue start failed: %s",
     279                 :            :                              rte_strerror(rc));
     280                 :          0 :                 goto fail_virtio_qstart;
     281                 :            :         }
     282                 :            : 
     283                 :          0 :         sfc_vdpa_info(ops_data->dev_handle,
     284                 :            :                       "virtqueue started successfully for vq_num %d", vq_num);
     285                 :            : 
     286                 :          0 :         rc = efx_virtio_get_doorbell_offset(vq, &doorbell);
     287         [ #  # ]:          0 :         if (rc != 0) {
     288                 :          0 :                 sfc_vdpa_err(ops_data->dev_handle,
     289                 :            :                              "failed to get doorbell offset: %s",
     290                 :            :                              rte_strerror(rc));
     291                 :          0 :                 goto fail_doorbell;
     292                 :            :         }
     293                 :            : 
     294                 :            :         /*
     295                 :            :          * Cache the bar_offset here for each VQ here, it will come
     296                 :            :          * in handy when sfc_vdpa_get_notify_area() is invoked.
     297                 :            :          */
     298                 :          0 :         ops_data->vq_cxt[vq_num].doorbell = (void *)(uintptr_t)doorbell;
     299                 :          0 :         ops_data->vq_cxt[vq_num].enable = B_TRUE;
     300                 :            : 
     301                 :          0 :         return rc;
     302                 :            : 
     303                 :            : fail_doorbell:
     304                 :          0 : fail_virtio_qstart:
     305                 :          0 :         efx_virtio_qdestroy(vq);
     306                 :            : fail_vring_info:
     307                 :            :         return rc;
     308                 :            : }
     309                 :            : 
     310                 :            : static int
     311                 :          0 : sfc_vdpa_virtq_stop(struct sfc_vdpa_ops_data *ops_data, int vq_num)
     312                 :            : {
     313                 :            :         int rc;
     314                 :            :         efx_virtio_vq_dyncfg_t vq_idx;
     315                 :            :         efx_virtio_vq_t *vq;
     316                 :            : 
     317         [ #  # ]:          0 :         if (ops_data->vq_cxt[vq_num].enable != B_TRUE)
     318                 :            :                 return -1;
     319                 :            : 
     320                 :          0 :         vq = ops_data->vq_cxt[vq_num].vq;
     321         [ #  # ]:          0 :         if (vq == NULL)
     322                 :            :                 return -1;
     323                 :            : 
     324                 :            :         /* stop the vq */
     325                 :          0 :         rc = efx_virtio_qstop(vq, &vq_idx);
     326         [ #  # ]:          0 :         if (rc == 0) {
     327                 :          0 :                 ops_data->vq_cxt[vq_num].cidx = vq_idx.evvd_vq_used_idx;
     328                 :          0 :                 ops_data->vq_cxt[vq_num].pidx = vq_idx.evvd_vq_avail_idx;
     329                 :            :         }
     330                 :          0 :         ops_data->vq_cxt[vq_num].enable = B_FALSE;
     331                 :            : 
     332                 :          0 :         return rc;
     333                 :            : }
     334                 :            : 
     335                 :            : static int
     336                 :          0 : sfc_vdpa_configure(struct sfc_vdpa_ops_data *ops_data)
     337                 :            : {
     338                 :            :         int rc, i;
     339                 :            :         int nr_vring;
     340                 :            :         int max_vring_cnt;
     341                 :            :         efx_virtio_vq_t *vq;
     342                 :            :         efx_nic_t *nic;
     343                 :            :         void *dev;
     344                 :            : 
     345                 :          0 :         dev = ops_data->dev_handle;
     346                 :          0 :         nic = sfc_vdpa_adapter_by_dev_handle(dev)->nic;
     347                 :            : 
     348         [ #  # ]:          0 :         SFC_EFX_ASSERT(ops_data->state == SFC_VDPA_STATE_INITIALIZED);
     349                 :            : 
     350                 :          0 :         ops_data->state = SFC_VDPA_STATE_CONFIGURING;
     351                 :            : 
     352                 :          0 :         nr_vring = rte_vhost_get_vring_num(ops_data->vid);
     353                 :          0 :         max_vring_cnt =
     354                 :          0 :                 (sfc_vdpa_adapter_by_dev_handle(dev)->max_queue_count * 2);
     355                 :            : 
     356                 :            :         /* number of vring should not be more than supported max vq count */
     357         [ #  # ]:          0 :         if (nr_vring > max_vring_cnt) {
     358                 :          0 :                 sfc_vdpa_err(dev,
     359                 :            :                              "nr_vring (%d) is > max vring count (%d)",
     360                 :            :                              nr_vring, max_vring_cnt);
     361                 :          0 :                 goto fail_vring_num;
     362                 :            :         }
     363                 :            : 
     364                 :          0 :         rc = sfc_vdpa_dma_map(ops_data, true);
     365         [ #  # ]:          0 :         if (rc) {
     366                 :          0 :                 sfc_vdpa_err(dev,
     367                 :            :                              "DMA map failed: %s", rte_strerror(rc));
     368                 :          0 :                 goto fail_dma_map;
     369                 :            :         }
     370                 :            : 
     371         [ #  # ]:          0 :         for (i = 0; i < nr_vring; i++) {
     372                 :          0 :                 rc = efx_virtio_qcreate(nic, &vq);
     373   [ #  #  #  # ]:          0 :                 if ((rc != 0) || (vq == NULL)) {
     374                 :          0 :                         sfc_vdpa_err(dev,
     375                 :            :                                      "virtqueue create failed: %s",
     376                 :            :                                      rte_strerror(rc));
     377                 :          0 :                         goto fail_vq_create;
     378                 :            :                 }
     379                 :            : 
     380                 :            :                 /* store created virtqueue context */
     381                 :          0 :                 ops_data->vq_cxt[i].vq = vq;
     382                 :            :         }
     383                 :            : 
     384                 :          0 :         ops_data->vq_count = i;
     385                 :            : 
     386                 :          0 :         ops_data->state = SFC_VDPA_STATE_CONFIGURED;
     387                 :            : 
     388                 :          0 :         return 0;
     389                 :            : 
     390                 :            : fail_vq_create:
     391                 :          0 :         sfc_vdpa_dma_map(ops_data, false);
     392                 :            : 
     393                 :          0 : fail_dma_map:
     394                 :          0 : fail_vring_num:
     395                 :          0 :         ops_data->state = SFC_VDPA_STATE_INITIALIZED;
     396                 :            : 
     397                 :          0 :         return -1;
     398                 :            : }
     399                 :            : 
     400                 :            : static void
     401                 :          0 : sfc_vdpa_close(struct sfc_vdpa_ops_data *ops_data)
     402                 :            : {
     403                 :            :         int i;
     404                 :            : 
     405         [ #  # ]:          0 :         if (ops_data->state != SFC_VDPA_STATE_CONFIGURED)
     406                 :            :                 return;
     407                 :            : 
     408                 :          0 :         ops_data->state = SFC_VDPA_STATE_CLOSING;
     409                 :            : 
     410         [ #  # ]:          0 :         for (i = 0; i < ops_data->vq_count; i++) {
     411         [ #  # ]:          0 :                 if (ops_data->vq_cxt[i].vq == NULL)
     412                 :          0 :                         continue;
     413                 :            : 
     414                 :          0 :                 efx_virtio_qdestroy(ops_data->vq_cxt[i].vq);
     415                 :            :         }
     416                 :            : 
     417                 :          0 :         sfc_vdpa_dma_map(ops_data, false);
     418                 :            : 
     419                 :          0 :         ops_data->state = SFC_VDPA_STATE_INITIALIZED;
     420                 :            : }
     421                 :            : 
     422                 :            : static void
     423                 :          0 : sfc_vdpa_stop(struct sfc_vdpa_ops_data *ops_data)
     424                 :            : {
     425                 :            :         int i;
     426                 :            :         int rc;
     427                 :            : 
     428         [ #  # ]:          0 :         if (ops_data->state != SFC_VDPA_STATE_STARTED)
     429                 :            :                 return;
     430                 :            : 
     431                 :          0 :         ops_data->state = SFC_VDPA_STATE_STOPPING;
     432                 :            : 
     433         [ #  # ]:          0 :         for (i = 0; i < ops_data->vq_count; i++) {
     434                 :          0 :                 rc = sfc_vdpa_virtq_stop(ops_data, i);
     435                 :            :                 if (rc != 0)
     436                 :            :                         continue;
     437                 :            :         }
     438                 :            : 
     439                 :          0 :         sfc_vdpa_disable_vfio_intr(ops_data);
     440                 :            : 
     441                 :          0 :         sfc_vdpa_filter_remove(ops_data);
     442                 :            : 
     443                 :          0 :         ops_data->state = SFC_VDPA_STATE_CONFIGURED;
     444                 :            : }
     445                 :            : 
     446                 :            : static int
     447                 :          0 : sfc_vdpa_start(struct sfc_vdpa_ops_data *ops_data)
     448                 :            : {
     449                 :            :         int i, j;
     450                 :            :         int rc;
     451                 :            : 
     452         [ #  # ]:          0 :         SFC_EFX_ASSERT(ops_data->state == SFC_VDPA_STATE_CONFIGURED);
     453                 :            : 
     454                 :          0 :         sfc_vdpa_log_init(ops_data->dev_handle, "entry");
     455                 :            : 
     456                 :          0 :         ops_data->state = SFC_VDPA_STATE_STARTING;
     457                 :            : 
     458                 :          0 :         sfc_vdpa_log_init(ops_data->dev_handle, "enable interrupts");
     459                 :          0 :         rc = sfc_vdpa_enable_vfio_intr(ops_data);
     460         [ #  # ]:          0 :         if (rc < 0) {
     461                 :          0 :                 sfc_vdpa_err(ops_data->dev_handle,
     462                 :            :                              "vfio intr allocation failed: %s",
     463                 :            :                              rte_strerror(rc));
     464                 :          0 :                 goto fail_enable_vfio_intr;
     465                 :            :         }
     466                 :            : 
     467                 :          0 :         rte_vhost_get_negotiated_features(ops_data->vid,
     468                 :            :                                           &ops_data->req_features);
     469                 :            : 
     470                 :          0 :         sfc_vdpa_info(ops_data->dev_handle,
     471                 :            :                       "negotiated feature : 0x%" PRIx64,
     472                 :            :                       ops_data->req_features);
     473                 :            : 
     474         [ #  # ]:          0 :         for (i = 0; i < ops_data->vq_count; i++) {
     475                 :          0 :                 sfc_vdpa_log_init(ops_data->dev_handle,
     476                 :            :                                   "starting vq# %d", i);
     477                 :          0 :                 rc = sfc_vdpa_virtq_start(ops_data, i);
     478         [ #  # ]:          0 :                 if (rc != 0)
     479                 :          0 :                         goto fail_vq_start;
     480                 :            :         }
     481                 :            : 
     482                 :          0 :         ops_data->vq_count = i;
     483                 :            : 
     484                 :          0 :         sfc_vdpa_log_init(ops_data->dev_handle,
     485                 :            :                           "configure MAC filters");
     486                 :          0 :         rc = sfc_vdpa_filter_config(ops_data);
     487         [ #  # ]:          0 :         if (rc != 0) {
     488                 :          0 :                 sfc_vdpa_err(ops_data->dev_handle,
     489                 :            :                              "MAC filter config failed: %s",
     490                 :            :                              rte_strerror(rc));
     491                 :          0 :                 goto fail_filter_cfg;
     492                 :            :         }
     493                 :            : 
     494                 :          0 :         ops_data->state = SFC_VDPA_STATE_STARTED;
     495                 :            : 
     496                 :          0 :         sfc_vdpa_log_init(ops_data->dev_handle, "done");
     497                 :            : 
     498                 :          0 :         return 0;
     499                 :            : 
     500                 :            : fail_filter_cfg:
     501                 :            :         /* remove already created filters */
     502                 :          0 :         sfc_vdpa_filter_remove(ops_data);
     503                 :          0 : fail_vq_start:
     504                 :            :         /* stop already started virtqueues */
     505         [ #  # ]:          0 :         for (j = 0; j < i; j++)
     506                 :          0 :                 sfc_vdpa_virtq_stop(ops_data, j);
     507                 :          0 :         sfc_vdpa_disable_vfio_intr(ops_data);
     508                 :            : 
     509                 :          0 : fail_enable_vfio_intr:
     510                 :          0 :         ops_data->state = SFC_VDPA_STATE_CONFIGURED;
     511                 :            : 
     512                 :          0 :         return rc;
     513                 :            : }
     514                 :            : 
     515                 :            : static int
     516                 :          0 : sfc_vdpa_get_queue_num(struct rte_vdpa_device *vdpa_dev, uint32_t *queue_num)
     517                 :            : {
     518                 :            :         struct sfc_vdpa_ops_data *ops_data;
     519                 :            :         void *dev;
     520                 :            : 
     521                 :          0 :         ops_data = sfc_vdpa_get_data_by_dev(vdpa_dev);
     522         [ #  # ]:          0 :         if (ops_data == NULL)
     523                 :            :                 return -1;
     524                 :            : 
     525                 :          0 :         dev = ops_data->dev_handle;
     526                 :          0 :         *queue_num = sfc_vdpa_adapter_by_dev_handle(dev)->max_queue_count;
     527                 :            : 
     528                 :          0 :         sfc_vdpa_info(dev, "vDPA ops get_queue_num :: supported queue num : %u",
     529                 :            :                       *queue_num);
     530                 :            : 
     531                 :          0 :         return 0;
     532                 :            : }
     533                 :            : 
     534                 :            : static int
     535                 :          0 : sfc_vdpa_get_features(struct rte_vdpa_device *vdpa_dev, uint64_t *features)
     536                 :            : {
     537                 :            :         struct sfc_vdpa_ops_data *ops_data;
     538                 :            : 
     539                 :          0 :         ops_data = sfc_vdpa_get_data_by_dev(vdpa_dev);
     540         [ #  # ]:          0 :         if (ops_data == NULL)
     541                 :            :                 return -1;
     542                 :            : 
     543                 :          0 :         *features = ops_data->drv_features;
     544                 :            : 
     545                 :          0 :         sfc_vdpa_info(ops_data->dev_handle,
     546                 :            :                       "vDPA ops get_feature :: features : 0x%" PRIx64,
     547                 :            :                       *features);
     548                 :            : 
     549                 :          0 :         return 0;
     550                 :            : }
     551                 :            : 
     552                 :            : static int
     553                 :          0 : sfc_vdpa_get_protocol_features(struct rte_vdpa_device *vdpa_dev,
     554                 :            :                                uint64_t *features)
     555                 :            : {
     556                 :            :         struct sfc_vdpa_ops_data *ops_data;
     557                 :            : 
     558                 :          0 :         ops_data = sfc_vdpa_get_data_by_dev(vdpa_dev);
     559         [ #  # ]:          0 :         if (ops_data == NULL)
     560                 :            :                 return -1;
     561                 :            : 
     562                 :          0 :         *features = SFC_VDPA_PROTOCOL_FEATURES;
     563                 :            : 
     564                 :          0 :         sfc_vdpa_info(ops_data->dev_handle,
     565                 :            :                       "vDPA ops get_protocol_feature :: features : 0x%" PRIx64,
     566                 :            :                       *features);
     567                 :            : 
     568                 :          0 :         return 0;
     569                 :            : }
     570                 :            : 
     571                 :            : static uint32_t
     572                 :          0 : sfc_vdpa_notify_ctrl(void *arg)
     573                 :            : {
     574                 :            :         struct sfc_vdpa_ops_data *ops_data;
     575                 :            :         int vid;
     576                 :            : 
     577                 :            :         ops_data = arg;
     578         [ #  # ]:          0 :         if (ops_data == NULL)
     579                 :            :                 return 0;
     580                 :            : 
     581                 :          0 :         sfc_vdpa_adapter_lock(sfc_vdpa_adapter_by_dev_handle(ops_data->dev_handle));
     582                 :            : 
     583                 :          0 :         vid = ops_data->vid;
     584                 :            : 
     585         [ #  # ]:          0 :         if (rte_vhost_host_notifier_ctrl(vid, RTE_VHOST_QUEUE_ALL, true) != 0)
     586                 :          0 :                 sfc_vdpa_info(ops_data->dev_handle,
     587                 :            :                               "vDPA (%s): Notifier could not get configured",
     588                 :            :                               ops_data->vdpa_dev->device->name);
     589                 :            : 
     590                 :          0 :         sfc_vdpa_adapter_unlock(sfc_vdpa_adapter_by_dev_handle(ops_data->dev_handle));
     591                 :            : 
     592                 :          0 :         return 0;
     593                 :            : }
     594                 :            : 
     595                 :            : static int
     596                 :          0 : sfc_vdpa_setup_notify_ctrl(struct sfc_vdpa_ops_data *ops_data)
     597                 :            : {
     598                 :            :         int ret;
     599                 :            : 
     600                 :          0 :         ops_data->is_notify_thread_started = false;
     601                 :            : 
     602                 :            :         /*
     603                 :            :          * Use rte_vhost_host_notifier_ctrl in a thread to avoid
     604                 :            :          * dead lock scenario when multiple VFs are used in single vdpa
     605                 :            :          * application and multiple VFs are passed to a single VM.
     606                 :            :          */
     607                 :          0 :         ret = rte_thread_create_internal_control(&ops_data->notify_tid,
     608                 :            :                              "sfc-vdpa", sfc_vdpa_notify_ctrl, ops_data);
     609         [ #  # ]:          0 :         if (ret != 0) {
     610                 :          0 :                 sfc_vdpa_err(ops_data->dev_handle,
     611                 :            :                              "failed to create notify_ctrl thread: %s",
     612                 :            :                              rte_strerror(ret));
     613                 :          0 :                 return -1;
     614                 :            :         }
     615                 :          0 :         ops_data->is_notify_thread_started = true;
     616                 :            : 
     617                 :          0 :         return 0;
     618                 :            : }
     619                 :            : 
     620                 :            : static int
     621                 :          0 : sfc_vdpa_dev_config(int vid)
     622                 :            : {
     623                 :            :         struct rte_vdpa_device *vdpa_dev;
     624                 :            :         int rc;
     625                 :            :         struct sfc_vdpa_ops_data *ops_data;
     626                 :            : 
     627                 :          0 :         vdpa_dev = rte_vhost_get_vdpa_device(vid);
     628                 :            : 
     629                 :          0 :         ops_data = sfc_vdpa_get_data_by_dev(vdpa_dev);
     630         [ #  # ]:          0 :         if (ops_data == NULL) {
     631                 :          0 :                 SFC_VDPA_GENERIC_LOG(ERR,
     632                 :            :                              "invalid vDPA device : %p, vid : %d",
     633                 :            :                              vdpa_dev, vid);
     634                 :          0 :                 return -1;
     635                 :            :         }
     636                 :            : 
     637                 :          0 :         sfc_vdpa_log_init(ops_data->dev_handle, "entry");
     638                 :            : 
     639                 :          0 :         ops_data->vid = vid;
     640                 :            : 
     641                 :          0 :         sfc_vdpa_adapter_lock(sfc_vdpa_adapter_by_dev_handle(ops_data->dev_handle));
     642                 :            : 
     643                 :          0 :         sfc_vdpa_log_init(ops_data->dev_handle, "configuring");
     644                 :          0 :         rc = sfc_vdpa_configure(ops_data);
     645         [ #  # ]:          0 :         if (rc != 0)
     646                 :          0 :                 goto fail_vdpa_config;
     647                 :            : 
     648                 :          0 :         sfc_vdpa_log_init(ops_data->dev_handle, "starting");
     649                 :          0 :         rc = sfc_vdpa_start(ops_data);
     650         [ #  # ]:          0 :         if (rc != 0)
     651                 :          0 :                 goto fail_vdpa_start;
     652                 :            : 
     653                 :          0 :         rc = sfc_vdpa_setup_notify_ctrl(ops_data);
     654         [ #  # ]:          0 :         if (rc != 0)
     655                 :          0 :                 goto fail_vdpa_notify;
     656                 :            : 
     657                 :          0 :         sfc_vdpa_adapter_unlock(sfc_vdpa_adapter_by_dev_handle(ops_data->dev_handle));
     658                 :            : 
     659                 :          0 :         sfc_vdpa_log_init(ops_data->dev_handle, "done");
     660                 :            : 
     661                 :          0 :         return 0;
     662                 :            : 
     663                 :            : fail_vdpa_notify:
     664                 :          0 :         sfc_vdpa_stop(ops_data);
     665                 :            : 
     666                 :          0 : fail_vdpa_start:
     667                 :          0 :         sfc_vdpa_close(ops_data);
     668                 :            : 
     669                 :          0 : fail_vdpa_config:
     670                 :          0 :         sfc_vdpa_adapter_unlock(sfc_vdpa_adapter_by_dev_handle(ops_data->dev_handle));
     671                 :            : 
     672                 :          0 :         return -1;
     673                 :            : }
     674                 :            : 
     675                 :            : static int
     676                 :          0 : sfc_vdpa_dev_close(int vid)
     677                 :            : {
     678                 :            :         int ret;
     679                 :            :         struct rte_vdpa_device *vdpa_dev;
     680                 :            :         struct sfc_vdpa_ops_data *ops_data;
     681                 :            : 
     682                 :          0 :         vdpa_dev = rte_vhost_get_vdpa_device(vid);
     683                 :            : 
     684                 :          0 :         ops_data = sfc_vdpa_get_data_by_dev(vdpa_dev);
     685         [ #  # ]:          0 :         if (ops_data == NULL) {
     686                 :          0 :                 SFC_VDPA_GENERIC_LOG(ERR,
     687                 :            :                              "invalid vDPA device : %p, vid : %d",
     688                 :            :                              vdpa_dev, vid);
     689                 :          0 :                 return -1;
     690                 :            :         }
     691                 :            : 
     692                 :          0 :         sfc_vdpa_adapter_lock(sfc_vdpa_adapter_by_dev_handle(ops_data->dev_handle));
     693         [ #  # ]:          0 :         if (ops_data->is_notify_thread_started == true) {
     694                 :          0 :                 ret = pthread_cancel((pthread_t)ops_data->notify_tid.opaque_id);
     695         [ #  # ]:          0 :                 if (ret != 0) {
     696                 :          0 :                         sfc_vdpa_err(ops_data->dev_handle,
     697                 :            :                                      "failed to cancel notify_ctrl thread: %s",
     698                 :            :                                      rte_strerror(ret));
     699                 :            :                 }
     700                 :            : 
     701                 :          0 :                 ret = rte_thread_join(ops_data->notify_tid, NULL);
     702         [ #  # ]:          0 :                 if (ret != 0) {
     703                 :          0 :                         sfc_vdpa_err(ops_data->dev_handle,
     704                 :            :                                      "failed to join terminated notify_ctrl thread: %s",
     705                 :            :                                      rte_strerror(ret));
     706                 :            :                 }
     707                 :            :         }
     708                 :          0 :         ops_data->is_notify_thread_started = false;
     709                 :            : 
     710                 :          0 :         sfc_vdpa_stop(ops_data);
     711                 :          0 :         sfc_vdpa_close(ops_data);
     712                 :            : 
     713                 :          0 :         sfc_vdpa_adapter_unlock(sfc_vdpa_adapter_by_dev_handle(ops_data->dev_handle));
     714                 :            : 
     715                 :          0 :         return 0;
     716                 :            : }
     717                 :            : 
     718                 :            : static int
     719                 :          0 : sfc_vdpa_set_vring_state(int vid, int vring, int state)
     720                 :            : {
     721                 :            :         struct sfc_vdpa_ops_data *ops_data;
     722                 :            :         struct rte_vdpa_device *vdpa_dev;
     723                 :            :         efx_rc_t rc;
     724                 :            :         int vring_max;
     725                 :            :         void *dev;
     726                 :            : 
     727                 :          0 :         vdpa_dev = rte_vhost_get_vdpa_device(vid);
     728                 :            : 
     729                 :          0 :         ops_data = sfc_vdpa_get_data_by_dev(vdpa_dev);
     730         [ #  # ]:          0 :         if (ops_data == NULL)
     731                 :            :                 return -1;
     732                 :            : 
     733                 :          0 :         dev = ops_data->dev_handle;
     734                 :            : 
     735                 :          0 :         sfc_vdpa_info(dev,
     736                 :            :                       "vDPA ops set_vring_state: vid: %d, vring: %d, state:%d",
     737                 :            :                       vid, vring, state);
     738                 :            : 
     739                 :          0 :         vring_max = (sfc_vdpa_adapter_by_dev_handle(dev)->max_queue_count * 2);
     740                 :            : 
     741         [ #  # ]:          0 :         if (vring < 0 || vring > vring_max) {
     742                 :          0 :                 sfc_vdpa_err(dev, "received invalid vring id : %d to set state",
     743                 :            :                              vring);
     744                 :          0 :                 return -1;
     745                 :            :         }
     746                 :            : 
     747                 :            :         /*
     748                 :            :          * Skip if device is not yet started. virtqueues state can be
     749                 :            :          * changed once it is created and other configurations are done.
     750                 :            :          */
     751         [ #  # ]:          0 :         if (ops_data->state != SFC_VDPA_STATE_STARTED)
     752                 :            :                 return 0;
     753                 :            : 
     754         [ #  # ]:          0 :         if (ops_data->vq_cxt[vring].enable == state)
     755                 :            :                 return 0;
     756                 :            : 
     757         [ #  # ]:          0 :         if (state == 0) {
     758                 :          0 :                 rc = sfc_vdpa_virtq_stop(ops_data, vring);
     759         [ #  # ]:          0 :                 if (rc != 0) {
     760                 :          0 :                         sfc_vdpa_err(dev, "virtqueue stop failed: %s",
     761                 :            :                                      rte_strerror(rc));
     762                 :            :                 }
     763                 :            :         } else {
     764                 :          0 :                 rc = sfc_vdpa_virtq_start(ops_data, vring);
     765         [ #  # ]:          0 :                 if (rc != 0) {
     766                 :          0 :                         sfc_vdpa_err(dev, "virtqueue start failed: %s",
     767                 :            :                                      rte_strerror(rc));
     768                 :            :                 }
     769                 :            :         }
     770                 :            : 
     771                 :            :         return rc;
     772                 :            : }
     773                 :            : 
     774                 :            : static int
     775                 :          0 : sfc_vdpa_set_features(int vid)
     776                 :            : {
     777                 :            :         RTE_SET_USED(vid);
     778                 :            : 
     779                 :          0 :         return -1;
     780                 :            : }
     781                 :            : 
     782                 :            : static int
     783                 :          0 : sfc_vdpa_get_vfio_device_fd(int vid)
     784                 :            : {
     785                 :            :         struct rte_vdpa_device *vdpa_dev;
     786                 :            :         struct sfc_vdpa_ops_data *ops_data;
     787                 :            :         int vfio_dev_fd;
     788                 :            :         void *dev;
     789                 :            : 
     790                 :          0 :         vdpa_dev = rte_vhost_get_vdpa_device(vid);
     791                 :            : 
     792                 :          0 :         ops_data = sfc_vdpa_get_data_by_dev(vdpa_dev);
     793         [ #  # ]:          0 :         if (ops_data == NULL)
     794                 :            :                 return -1;
     795                 :            : 
     796                 :          0 :         dev = ops_data->dev_handle;
     797                 :          0 :         vfio_dev_fd = sfc_vdpa_adapter_by_dev_handle(dev)->vfio_dev_fd;
     798                 :            : 
     799                 :          0 :         sfc_vdpa_info(dev, "vDPA ops get_vfio_device_fd :: vfio fd : %d",
     800                 :            :                       vfio_dev_fd);
     801                 :            : 
     802                 :          0 :         return vfio_dev_fd;
     803                 :            : }
     804                 :            : 
     805                 :            : static int
     806                 :          0 : sfc_vdpa_get_notify_area(int vid, int qid, uint64_t *offset, uint64_t *size)
     807                 :            : {
     808                 :            :         int ret;
     809                 :            :         efx_nic_t *nic;
     810                 :            :         int vfio_dev_fd;
     811                 :            :         volatile void *doorbell;
     812                 :            :         struct rte_pci_device *pci_dev;
     813                 :            :         struct rte_vdpa_device *vdpa_dev;
     814                 :            :         struct sfc_vdpa_ops_data *ops_data;
     815                 :          0 :         struct vfio_region_info reg = { .argsz = sizeof(reg) };
     816                 :            :         const efx_nic_cfg_t *encp;
     817                 :            :         int max_vring_cnt;
     818                 :            :         int64_t len;
     819                 :            :         void *dev;
     820                 :            : 
     821                 :          0 :         vdpa_dev = rte_vhost_get_vdpa_device(vid);
     822                 :            : 
     823                 :          0 :         ops_data = sfc_vdpa_get_data_by_dev(vdpa_dev);
     824         [ #  # ]:          0 :         if (ops_data == NULL)
     825                 :            :                 return -1;
     826                 :            : 
     827                 :          0 :         dev = ops_data->dev_handle;
     828                 :            : 
     829                 :          0 :         vfio_dev_fd = sfc_vdpa_adapter_by_dev_handle(dev)->vfio_dev_fd;
     830                 :          0 :         max_vring_cnt =
     831                 :          0 :                 (sfc_vdpa_adapter_by_dev_handle(dev)->max_queue_count * 2);
     832                 :            : 
     833                 :          0 :         nic = sfc_vdpa_adapter_by_dev_handle(ops_data->dev_handle)->nic;
     834                 :          0 :         encp = efx_nic_cfg_get(nic);
     835                 :            : 
     836         [ #  # ]:          0 :         if (qid >= max_vring_cnt) {
     837                 :          0 :                 sfc_vdpa_err(dev, "invalid qid : %d", qid);
     838                 :          0 :                 return -1;
     839                 :            :         }
     840                 :            : 
     841                 :          0 :         reg.index = sfc_vdpa_adapter_by_dev_handle(dev)->mem_bar.esb_rid;
     842                 :          0 :         ret = ioctl(vfio_dev_fd, VFIO_DEVICE_GET_REGION_INFO, &reg);
     843         [ #  # ]:          0 :         if (ret != 0) {
     844                 :          0 :                 sfc_vdpa_err(dev, "could not get device region info: %s",
     845                 :            :                              strerror(errno));
     846                 :          0 :                 return ret;
     847                 :            :         }
     848                 :            : 
     849                 :            :         /* Use bar_offset that was cached during sfc_vdpa_virtq_start() */
     850                 :          0 :         *offset = reg.offset + (uint64_t)ops_data->vq_cxt[qid].doorbell;
     851                 :            : 
     852                 :          0 :         len = (1U << encp->enc_vi_window_shift) / 2;
     853         [ #  # ]:          0 :         if (len >= sysconf(_SC_PAGESIZE)) {
     854                 :          0 :                 *size = sysconf(_SC_PAGESIZE);
     855                 :            :         } else {
     856                 :          0 :                 sfc_vdpa_err(dev, "invalid VI window size : 0x%" PRIx64, len);
     857                 :          0 :                 return -1;
     858                 :            :         }
     859                 :            : 
     860                 :          0 :         sfc_vdpa_info(dev, "vDPA ops get_notify_area :: offset : 0x%" PRIx64,
     861                 :            :                       *offset);
     862                 :            : 
     863                 :          0 :         pci_dev = sfc_vdpa_adapter_by_dev_handle(dev)->pdev;
     864                 :          0 :         doorbell = (uint8_t *)pci_dev->mem_resource[reg.index].addr + *offset;
     865                 :            : 
     866                 :            :         /*
     867                 :            :          * virtio-net driver in VM sends queue notifications before
     868                 :            :          * vDPA has a chance to setup the queues and notification area,
     869                 :            :          * and hence the HW misses these doorbell notifications.
     870                 :            :          * Since, it is safe to send duplicate doorbell, send another
     871                 :            :          * doorbell from vDPA driver as workaround for this timing issue.
     872                 :            :          */
     873                 :          0 :         rte_write16(qid, doorbell);
     874                 :            : 
     875                 :          0 :         return 0;
     876                 :            : }
     877                 :            : 
     878                 :            : static struct rte_vdpa_dev_ops sfc_vdpa_ops = {
     879                 :            :         .get_queue_num = sfc_vdpa_get_queue_num,
     880                 :            :         .get_features = sfc_vdpa_get_features,
     881                 :            :         .get_protocol_features = sfc_vdpa_get_protocol_features,
     882                 :            :         .dev_conf = sfc_vdpa_dev_config,
     883                 :            :         .dev_close = sfc_vdpa_dev_close,
     884                 :            :         .set_vring_state = sfc_vdpa_set_vring_state,
     885                 :            :         .set_features = sfc_vdpa_set_features,
     886                 :            :         .get_vfio_device_fd = sfc_vdpa_get_vfio_device_fd,
     887                 :            :         .get_notify_area = sfc_vdpa_get_notify_area,
     888                 :            : };
     889                 :            : 
     890                 :            : struct sfc_vdpa_ops_data *
     891                 :          0 : sfc_vdpa_device_init(void *dev_handle, enum sfc_vdpa_context context)
     892                 :            : {
     893                 :            :         struct sfc_vdpa_ops_data *ops_data;
     894                 :            :         struct rte_pci_device *pci_dev;
     895                 :            :         int rc;
     896                 :            : 
     897                 :            :         /* Create vDPA ops context */
     898                 :          0 :         ops_data = rte_zmalloc("vdpa", sizeof(struct sfc_vdpa_ops_data), 0);
     899         [ #  # ]:          0 :         if (ops_data == NULL)
     900                 :            :                 return NULL;
     901                 :            : 
     902                 :          0 :         ops_data->vdpa_context = context;
     903                 :          0 :         ops_data->dev_handle = dev_handle;
     904                 :            : 
     905                 :          0 :         pci_dev = sfc_vdpa_adapter_by_dev_handle(dev_handle)->pdev;
     906                 :            : 
     907                 :            :         /* Register vDPA Device */
     908                 :          0 :         sfc_vdpa_log_init(dev_handle, "register vDPA device");
     909                 :          0 :         ops_data->vdpa_dev =
     910                 :          0 :                 rte_vdpa_register_device(&pci_dev->device, &sfc_vdpa_ops);
     911         [ #  # ]:          0 :         if (ops_data->vdpa_dev == NULL) {
     912                 :          0 :                 sfc_vdpa_err(dev_handle, "vDPA device registration failed");
     913                 :          0 :                 goto fail_register_device;
     914                 :            :         }
     915                 :            : 
     916                 :            :         /* Read supported device features */
     917                 :          0 :         sfc_vdpa_log_init(dev_handle, "get device feature");
     918                 :          0 :         rc = sfc_vdpa_get_device_features(ops_data);
     919         [ #  # ]:          0 :         if (rc != 0)
     920                 :          0 :                 goto fail_get_dev_feature;
     921                 :            : 
     922                 :            :         /* Driver features are superset of device supported feature
     923                 :            :          * and any additional features supported by the driver.
     924                 :            :          */
     925                 :          0 :         ops_data->drv_features =
     926                 :          0 :                 ops_data->dev_features | SFC_VDPA_DEFAULT_FEATURES;
     927                 :            : 
     928                 :          0 :         ops_data->state = SFC_VDPA_STATE_INITIALIZED;
     929                 :            : 
     930                 :          0 :         return ops_data;
     931                 :            : 
     932                 :            : fail_get_dev_feature:
     933                 :          0 :         rte_vdpa_unregister_device(ops_data->vdpa_dev);
     934                 :            : 
     935                 :          0 : fail_register_device:
     936                 :          0 :         rte_free(ops_data);
     937                 :          0 :         return NULL;
     938                 :            : }
     939                 :            : 
     940                 :            : void
     941                 :          0 : sfc_vdpa_device_fini(struct sfc_vdpa_ops_data *ops_data)
     942                 :            : {
     943                 :          0 :         rte_vdpa_unregister_device(ops_data->vdpa_dev);
     944                 :            : 
     945                 :          0 :         rte_free(ops_data);
     946                 :          0 : }

Generated by: LCOV version 1.14