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

Generated by: LCOV version 1.14