LCOV - code coverage report
Current view: top level - drivers/net/virtio - virtqueue.c (source / functions) Hit Total Coverage
Test: Code coverage Lines: 0 251 0.0 %
Date: 2025-02-01 18:54:23 Functions: 0 14 0.0 %
Legend: Lines: hit not hit | Branches: + taken - not taken # not executed Branches: 0 123 0.0 %

           Branch data     Line data    Source code
       1                 :            : /* SPDX-License-Identifier: BSD-3-Clause
       2                 :            :  * Copyright(c) 2010-2015 Intel Corporation
       3                 :            :  */
       4                 :            : #include <stdint.h>
       5                 :            : #include <unistd.h>
       6                 :            : 
       7                 :            : #include <rte_eal_paging.h>
       8                 :            : #include <rte_malloc.h>
       9                 :            : #include <rte_mbuf.h>
      10                 :            : #include <rte_memzone.h>
      11                 :            : 
      12                 :            : #include "virtqueue.h"
      13                 :            : #include "virtio_logs.h"
      14                 :            : #include "virtio.h"
      15                 :            : #include "virtio_rxtx_simple.h"
      16                 :            : 
      17                 :            : /*
      18                 :            :  * Two types of mbuf to be cleaned:
      19                 :            :  * 1) mbuf that has been consumed by backend but not used by virtio.
      20                 :            :  * 2) mbuf that hasn't been consumed by backend.
      21                 :            :  */
      22                 :            : struct rte_mbuf *
      23                 :          0 : virtqueue_detach_unused(struct virtqueue *vq)
      24                 :            : {
      25                 :            :         struct rte_mbuf *cookie;
      26                 :            :         struct virtio_hw *hw;
      27                 :            :         uint16_t start, end;
      28                 :            :         int type, idx;
      29                 :            : 
      30         [ #  # ]:          0 :         if (vq == NULL)
      31                 :            :                 return NULL;
      32                 :            : 
      33                 :          0 :         hw = vq->hw;
      34         [ #  # ]:          0 :         type = virtio_get_queue_type(hw, vq->vq_queue_index);
      35                 :          0 :         start = vq->vq_avail_idx & (vq->vq_nentries - 1);
      36                 :          0 :         end = (vq->vq_avail_idx + vq->vq_free_cnt) & (vq->vq_nentries - 1);
      37                 :            : 
      38         [ #  # ]:          0 :         for (idx = 0; idx < vq->vq_nentries; idx++) {
      39   [ #  #  #  #  :          0 :                 if (hw->use_vec_rx && !virtio_with_packed_queue(hw) &&
                   #  # ]
      40                 :            :                     type == VTNET_RQ) {
      41   [ #  #  #  #  :          0 :                         if (start <= end && idx >= start && idx < end)
                   #  # ]
      42                 :          0 :                                 continue;
      43   [ #  #  #  #  :          0 :                         if (start > end && (idx >= start || idx < end))
                   #  # ]
      44                 :          0 :                                 continue;
      45                 :          0 :                         cookie = vq->rxq.sw_ring[idx];
      46         [ #  # ]:          0 :                         if (cookie != NULL) {
      47                 :          0 :                                 vq->rxq.sw_ring[idx] = NULL;
      48                 :          0 :                                 return cookie;
      49                 :            :                         }
      50                 :            :                 } else {
      51                 :          0 :                         cookie = vq->vq_descx[idx].cookie;
      52         [ #  # ]:          0 :                         if (cookie != NULL) {
      53                 :          0 :                                 vq->vq_descx[idx].cookie = NULL;
      54                 :          0 :                                 return cookie;
      55                 :            :                         }
      56                 :            :                 }
      57                 :            :         }
      58                 :            : 
      59                 :            :         return NULL;
      60                 :            : }
      61                 :            : 
      62                 :            : /* Flush used descs */
      63                 :            : static void
      64                 :          0 : virtqueue_rxvq_flush_packed(struct virtqueue *vq)
      65                 :            : {
      66                 :            :         struct vq_desc_extra *dxp;
      67                 :            :         uint16_t i;
      68                 :            : 
      69                 :          0 :         struct vring_packed_desc *descs = vq->vq_packed.ring.desc;
      70                 :            :         int cnt = 0;
      71                 :            : 
      72                 :          0 :         i = vq->vq_used_cons_idx;
      73   [ #  #  #  # ]:          0 :         while (desc_is_used(&descs[i], vq) && cnt++ < vq->vq_nentries) {
      74                 :          0 :                 dxp = &vq->vq_descx[descs[i].id];
      75         [ #  # ]:          0 :                 if (dxp->cookie != NULL) {
      76                 :          0 :                         rte_pktmbuf_free(dxp->cookie);
      77                 :          0 :                         dxp->cookie = NULL;
      78                 :            :                 }
      79                 :          0 :                 vq->vq_free_cnt++;
      80                 :          0 :                 vq->vq_used_cons_idx++;
      81         [ #  # ]:          0 :                 if (vq->vq_used_cons_idx >= vq->vq_nentries) {
      82                 :          0 :                         vq->vq_used_cons_idx -= vq->vq_nentries;
      83                 :          0 :                         vq->vq_packed.used_wrap_counter ^= 1;
      84                 :            :                 }
      85                 :          0 :                 i = vq->vq_used_cons_idx;
      86                 :            :         }
      87                 :          0 : }
      88                 :            : 
      89                 :            : /* Flush the elements in the used ring. */
      90                 :            : static void
      91                 :          0 : virtqueue_rxvq_flush_split(struct virtqueue *vq)
      92                 :            : {
      93                 :          0 :         struct virtnet_rx *rxq = &vq->rxq;
      94         [ #  # ]:          0 :         struct virtio_hw *hw = vq->hw;
      95                 :            :         struct vring_used_elem *uep;
      96                 :            :         struct vq_desc_extra *dxp;
      97                 :            :         uint16_t used_idx, desc_idx;
      98                 :            :         uint16_t nb_used, i;
      99                 :            : 
     100                 :            :         nb_used = virtqueue_nused(vq);
     101                 :            : 
     102         [ #  # ]:          0 :         for (i = 0; i < nb_used; i++) {
     103                 :          0 :                 used_idx = vq->vq_used_cons_idx & (vq->vq_nentries - 1);
     104                 :          0 :                 uep = &vq->vq_split.ring.used->ring[used_idx];
     105         [ #  # ]:          0 :                 if (hw->use_vec_rx) {
     106                 :            :                         desc_idx = used_idx;
     107                 :          0 :                         rte_pktmbuf_free(vq->rxq.sw_ring[desc_idx]);
     108                 :          0 :                         vq->vq_free_cnt++;
     109         [ #  # ]:          0 :                 } else if (hw->use_inorder_rx) {
     110                 :          0 :                         desc_idx = (uint16_t)uep->id;
     111                 :          0 :                         dxp = &vq->vq_descx[desc_idx];
     112         [ #  # ]:          0 :                         if (dxp->cookie != NULL) {
     113                 :          0 :                                 rte_pktmbuf_free(dxp->cookie);
     114                 :          0 :                                 dxp->cookie = NULL;
     115                 :            :                         }
     116                 :          0 :                         vq_ring_free_inorder(vq, desc_idx, 1);
     117                 :            :                 } else {
     118                 :          0 :                         desc_idx = (uint16_t)uep->id;
     119                 :          0 :                         dxp = &vq->vq_descx[desc_idx];
     120         [ #  # ]:          0 :                         if (dxp->cookie != NULL) {
     121                 :          0 :                                 rte_pktmbuf_free(dxp->cookie);
     122                 :          0 :                                 dxp->cookie = NULL;
     123                 :            :                         }
     124                 :          0 :                         vq_ring_free_chain(vq, desc_idx);
     125                 :            :                 }
     126                 :          0 :                 vq->vq_used_cons_idx++;
     127                 :            :         }
     128                 :            : 
     129         [ #  # ]:          0 :         if (hw->use_vec_rx) {
     130         [ #  # ]:          0 :                 while (vq->vq_free_cnt >= RTE_VIRTIO_VPMD_RX_REARM_THRESH) {
     131                 :          0 :                         virtio_rxq_rearm_vec(rxq);
     132         [ #  # ]:          0 :                         if (virtqueue_kick_prepare(vq))
     133                 :            :                                 virtqueue_notify(vq);
     134                 :            :                 }
     135                 :            :         }
     136                 :          0 : }
     137                 :            : 
     138                 :            : /* Flush the elements in the used ring. */
     139                 :            : void
     140                 :          0 : virtqueue_rxvq_flush(struct virtqueue *vq)
     141                 :            : {
     142         [ #  # ]:          0 :         struct virtio_hw *hw = vq->hw;
     143                 :            : 
     144         [ #  # ]:          0 :         if (virtio_with_packed_queue(hw))
     145                 :          0 :                 virtqueue_rxvq_flush_packed(vq);
     146                 :            :         else
     147                 :          0 :                 virtqueue_rxvq_flush_split(vq);
     148                 :          0 : }
     149                 :            : 
     150                 :            : static void
     151                 :            : virtqueue_txq_indirect_header_init_packed(struct virtqueue *vq, uint32_t idx)
     152                 :            : {
     153                 :            :         struct virtio_tx_region *txr;
     154                 :            :         struct vring_packed_desc *desc;
     155                 :            :         rte_iova_t hdr_mem;
     156                 :            : 
     157                 :          0 :         txr = vq->txq.hdr_mz->addr;
     158                 :          0 :         hdr_mem = vq->txq.hdr_mem;
     159                 :          0 :         desc = txr[idx].tx_packed_indir;
     160                 :            : 
     161                 :            :         vring_desc_init_indirect_packed(desc, RTE_DIM(txr[idx].tx_packed_indir));
     162                 :          0 :         desc->addr = hdr_mem + idx * sizeof(*txr) + offsetof(struct virtio_tx_region, tx_hdr);
     163                 :          0 :         desc->len = vq->hw->vtnet_hdr_size;
     164                 :          0 : }
     165                 :            : 
     166                 :            : static void
     167                 :          0 : virtqueue_txq_indirect_header_init_split(struct virtqueue *vq, uint32_t idx)
     168                 :            : {
     169                 :            :         struct virtio_tx_region *txr;
     170                 :            :         struct vring_desc *desc;
     171                 :            :         rte_iova_t hdr_mem;
     172                 :            : 
     173                 :          0 :         txr = vq->txq.hdr_mz->addr;
     174                 :          0 :         hdr_mem = vq->txq.hdr_mem;
     175                 :          0 :         desc = txr[idx].tx_indir;
     176                 :            : 
     177                 :            :         vring_desc_init_split(desc, RTE_DIM(txr[idx].tx_indir));
     178                 :          0 :         desc->addr = hdr_mem + idx * sizeof(*txr) + offsetof(struct virtio_tx_region, tx_hdr);
     179                 :          0 :         desc->len = vq->hw->vtnet_hdr_size;
     180                 :          0 :         desc->flags = VRING_DESC_F_NEXT;
     181                 :          0 : }
     182                 :            : 
     183                 :            : void
     184                 :          0 : virtqueue_txq_indirect_headers_init(struct virtqueue *vq)
     185                 :            : {
     186                 :            :         uint32_t i;
     187                 :            : 
     188         [ #  # ]:          0 :         if (!virtio_with_feature(vq->hw, VIRTIO_RING_F_INDIRECT_DESC))
     189                 :            :                 return;
     190                 :            : 
     191         [ #  # ]:          0 :         for (i = 0; i < vq->vq_nentries; i++)
     192         [ #  # ]:          0 :                 if (virtio_with_packed_queue(vq->hw))
     193                 :            :                         virtqueue_txq_indirect_header_init_packed(vq, i);
     194                 :            :                 else
     195                 :          0 :                         virtqueue_txq_indirect_header_init_split(vq, i);
     196                 :            : }
     197                 :            : 
     198                 :            : int
     199                 :          0 : virtqueue_rxvq_reset_packed(struct virtqueue *vq)
     200                 :            : {
     201                 :          0 :         int size = vq->vq_nentries;
     202                 :            :         struct vq_desc_extra *dxp;
     203                 :            :         uint16_t desc_idx;
     204                 :            : 
     205                 :          0 :         vq->vq_used_cons_idx = 0;
     206                 :          0 :         vq->vq_desc_head_idx = 0;
     207                 :          0 :         vq->vq_avail_idx = 0;
     208                 :          0 :         vq->vq_desc_tail_idx = (uint16_t)(vq->vq_nentries - 1);
     209                 :          0 :         vq->vq_free_cnt = vq->vq_nentries;
     210                 :            : 
     211                 :          0 :         vq->vq_packed.used_wrap_counter = 1;
     212                 :            :         vq->vq_packed.cached_flags = VRING_PACKED_DESC_F_AVAIL;
     213                 :          0 :         vq->vq_packed.event_flags_shadow = 0;
     214                 :          0 :         vq->vq_packed.cached_flags |= VRING_DESC_F_WRITE;
     215                 :            : 
     216                 :          0 :         memset(vq->mz->addr, 0, vq->mz->len);
     217                 :            : 
     218         [ #  # ]:          0 :         for (desc_idx = 0; desc_idx < vq->vq_nentries; desc_idx++) {
     219                 :          0 :                 dxp = &vq->vq_descx[desc_idx];
     220         [ #  # ]:          0 :                 if (dxp->cookie != NULL) {
     221                 :          0 :                         rte_pktmbuf_free(dxp->cookie);
     222                 :          0 :                         dxp->cookie = NULL;
     223                 :            :                 }
     224                 :            :         }
     225                 :            : 
     226                 :            :         vring_desc_init_packed(vq, size);
     227                 :            : 
     228                 :            :         virtqueue_disable_intr(vq);
     229                 :          0 :         return 0;
     230                 :            : }
     231                 :            : 
     232                 :            : int
     233                 :          0 : virtqueue_txvq_reset_packed(struct virtqueue *vq)
     234                 :            : {
     235                 :          0 :         int size = vq->vq_nentries;
     236                 :            :         struct vq_desc_extra *dxp;
     237                 :            :         uint16_t desc_idx;
     238                 :            : 
     239                 :          0 :         vq->vq_used_cons_idx = 0;
     240                 :          0 :         vq->vq_desc_head_idx = 0;
     241                 :          0 :         vq->vq_avail_idx = 0;
     242                 :          0 :         vq->vq_desc_tail_idx = (uint16_t)(vq->vq_nentries - 1);
     243                 :          0 :         vq->vq_free_cnt = vq->vq_nentries;
     244                 :            : 
     245                 :          0 :         vq->vq_packed.used_wrap_counter = 1;
     246                 :          0 :         vq->vq_packed.cached_flags = VRING_PACKED_DESC_F_AVAIL;
     247                 :          0 :         vq->vq_packed.event_flags_shadow = 0;
     248                 :            : 
     249                 :          0 :         memset(vq->mz->addr, 0, vq->mz->len);
     250                 :          0 :         memset(vq->txq.hdr_mz->addr, 0, vq->txq.hdr_mz->len);
     251                 :            : 
     252         [ #  # ]:          0 :         for (desc_idx = 0; desc_idx < vq->vq_nentries; desc_idx++) {
     253                 :          0 :                 dxp = &vq->vq_descx[desc_idx];
     254         [ #  # ]:          0 :                 if (dxp->cookie != NULL) {
     255                 :          0 :                         rte_pktmbuf_free(dxp->cookie);
     256                 :          0 :                         dxp->cookie = NULL;
     257                 :            :                 }
     258                 :            :         }
     259                 :            : 
     260                 :          0 :         virtqueue_txq_indirect_headers_init(vq);
     261                 :            :         vring_desc_init_packed(vq, size);
     262                 :            :         virtqueue_disable_intr(vq);
     263                 :            : 
     264                 :          0 :         return 0;
     265                 :            : }
     266                 :            : 
     267                 :            : 
     268                 :            : static void
     269                 :          0 : virtio_init_vring(struct virtqueue *vq)
     270                 :            : {
     271                 :          0 :         int size = vq->vq_nentries;
     272                 :          0 :         uint8_t *ring_mem = vq->vq_ring_virt_mem;
     273                 :            : 
     274                 :          0 :         PMD_INIT_FUNC_TRACE();
     275                 :            : 
     276         [ #  # ]:          0 :         memset(ring_mem, 0, vq->vq_ring_size);
     277                 :            : 
     278                 :          0 :         vq->vq_used_cons_idx = 0;
     279                 :          0 :         vq->vq_desc_head_idx = 0;
     280                 :          0 :         vq->vq_avail_idx = 0;
     281                 :          0 :         vq->vq_desc_tail_idx = (uint16_t)(vq->vq_nentries - 1);
     282                 :          0 :         vq->vq_free_cnt = vq->vq_nentries;
     283                 :          0 :         memset(vq->vq_descx, 0, sizeof(struct vq_desc_extra) * vq->vq_nentries);
     284         [ #  # ]:          0 :         if (virtio_with_packed_queue(vq->hw)) {
     285                 :          0 :                 vring_init_packed(&vq->vq_packed.ring, ring_mem, vq->vq_ring_mem,
     286                 :            :                                   VIRTIO_VRING_ALIGN, size);
     287                 :            :                 vring_desc_init_packed(vq, size);
     288                 :            :         } else {
     289                 :            :                 struct vring *vr = &vq->vq_split.ring;
     290                 :            : 
     291                 :          0 :                 vring_init_split(vr, ring_mem, vq->vq_ring_mem, VIRTIO_VRING_ALIGN, size);
     292                 :            :                 vring_desc_init_split(vr->desc, size);
     293                 :            :         }
     294                 :            :         /*
     295                 :            :          * Disable device(host) interrupting guest
     296                 :            :          */
     297                 :            :         virtqueue_disable_intr(vq);
     298                 :          0 : }
     299                 :            : 
     300                 :            : static int
     301                 :          0 : virtio_alloc_queue_headers(struct virtqueue *vq, int numa_node, const char *name)
     302                 :            : {
     303                 :            :         char hdr_name[VIRTQUEUE_MAX_NAME_SZ];
     304                 :            :         const struct rte_memzone **hdr_mz;
     305                 :            :         rte_iova_t *hdr_mem;
     306                 :            :         ssize_t size;
     307                 :            :         int queue_type;
     308                 :            : 
     309         [ #  # ]:          0 :         queue_type = virtio_get_queue_type(vq->hw, vq->vq_queue_index);
     310                 :            :         switch (queue_type) {
     311                 :            :         case VTNET_TQ:
     312                 :            :                 /*
     313                 :            :                  * For each xmit packet, allocate a virtio_net_hdr
     314                 :            :                  * and indirect ring elements
     315                 :            :                  */
     316                 :          0 :                 size = vq->vq_nentries * sizeof(struct virtio_tx_region);
     317                 :          0 :                 hdr_mz = &vq->txq.hdr_mz;
     318                 :          0 :                 hdr_mem = &vq->txq.hdr_mem;
     319                 :          0 :                 break;
     320                 :            :         case VTNET_CQ:
     321                 :            :                 /* Allocate a page for control vq command, data and status */
     322                 :          0 :                 size = rte_mem_page_size();
     323                 :          0 :                 hdr_mz = &vq->cq.hdr_mz;
     324                 :          0 :                 hdr_mem = &vq->cq.hdr_mem;
     325                 :          0 :                 break;
     326                 :            :         case VTNET_RQ:
     327                 :            :                 /* fallthrough */
     328                 :            :         default:
     329                 :            :                 return 0;
     330                 :            :         }
     331                 :            : 
     332                 :            :         snprintf(hdr_name, sizeof(hdr_name), "%s_hdr", name);
     333                 :          0 :         *hdr_mz = rte_memzone_reserve_aligned(hdr_name, size, numa_node,
     334                 :            :                         RTE_MEMZONE_IOVA_CONTIG, RTE_CACHE_LINE_SIZE);
     335         [ #  # ]:          0 :         if (*hdr_mz == NULL) {
     336         [ #  # ]:          0 :                 if (rte_errno == EEXIST)
     337                 :          0 :                         *hdr_mz = rte_memzone_lookup(hdr_name);
     338         [ #  # ]:          0 :                 if (*hdr_mz == NULL)
     339                 :            :                         return -ENOMEM;
     340                 :            :         }
     341                 :            : 
     342         [ #  # ]:          0 :         memset((*hdr_mz)->addr, 0, size);
     343                 :            : 
     344         [ #  # ]:          0 :         if (vq->hw->use_va)
     345                 :          0 :                 *hdr_mem = (uintptr_t)(*hdr_mz)->addr;
     346                 :            :         else
     347                 :          0 :                 *hdr_mem = (uintptr_t)(*hdr_mz)->iova;
     348                 :            : 
     349                 :            :         return 0;
     350                 :            : }
     351                 :            : 
     352                 :            : static void
     353                 :          0 : virtio_free_queue_headers(struct virtqueue *vq)
     354                 :            : {
     355                 :            :         const struct rte_memzone **hdr_mz;
     356                 :            :         rte_iova_t *hdr_mem;
     357                 :            :         int queue_type;
     358                 :            : 
     359         [ #  # ]:          0 :         queue_type = virtio_get_queue_type(vq->hw, vq->vq_queue_index);
     360                 :            :         switch (queue_type) {
     361                 :            :         case VTNET_TQ:
     362                 :          0 :                 hdr_mz = &vq->txq.hdr_mz;
     363                 :          0 :                 hdr_mem = &vq->txq.hdr_mem;
     364                 :          0 :                 break;
     365                 :            :         case VTNET_CQ:
     366                 :          0 :                 hdr_mz = &vq->cq.hdr_mz;
     367                 :          0 :                 hdr_mem = &vq->cq.hdr_mem;
     368                 :          0 :                 break;
     369                 :            :         case VTNET_RQ:
     370                 :            :                 /* fallthrough */
     371                 :            :         default:
     372                 :            :                 return;
     373                 :            :         }
     374                 :            : 
     375                 :          0 :         rte_memzone_free(*hdr_mz);
     376                 :          0 :         *hdr_mz = NULL;
     377                 :          0 :         *hdr_mem = 0;
     378                 :            : }
     379                 :            : 
     380                 :            : static int
     381                 :          0 : virtio_rxq_sw_ring_alloc(struct virtqueue *vq, int numa_node)
     382                 :            : {
     383                 :            :         void *sw_ring;
     384                 :            :         struct rte_mbuf *mbuf;
     385                 :            :         size_t size;
     386                 :            : 
     387                 :            :         /* SW ring is only used with vectorized datapath */
     388         [ #  # ]:          0 :         if (!vq->hw->use_vec_rx)
     389                 :            :                 return 0;
     390                 :            : 
     391                 :          0 :         size = (RTE_PMD_VIRTIO_RX_MAX_BURST + vq->vq_nentries) * sizeof(vq->rxq.sw_ring[0]);
     392                 :            : 
     393                 :          0 :         sw_ring = rte_zmalloc_socket("sw_ring", size, RTE_CACHE_LINE_SIZE, numa_node);
     394         [ #  # ]:          0 :         if (!sw_ring) {
     395                 :          0 :                 PMD_INIT_LOG(ERR, "can not allocate RX soft ring");
     396                 :          0 :                 return -ENOMEM;
     397                 :            :         }
     398                 :            : 
     399                 :          0 :         mbuf = rte_zmalloc_socket("sw_ring", sizeof(*mbuf), RTE_CACHE_LINE_SIZE, numa_node);
     400         [ #  # ]:          0 :         if (!mbuf) {
     401                 :          0 :                 PMD_INIT_LOG(ERR, "can not allocate fake mbuf");
     402                 :          0 :                 rte_free(sw_ring);
     403                 :          0 :                 return -ENOMEM;
     404                 :            :         }
     405                 :            : 
     406                 :          0 :         vq->rxq.sw_ring = sw_ring;
     407                 :          0 :         vq->rxq.fake_mbuf = mbuf;
     408                 :            : 
     409                 :          0 :         return 0;
     410                 :            : }
     411                 :            : 
     412                 :            : static void
     413                 :            : virtio_rxq_sw_ring_free(struct virtqueue *vq)
     414                 :            : {
     415                 :          0 :         rte_free(vq->rxq.fake_mbuf);
     416                 :          0 :         vq->rxq.fake_mbuf = NULL;
     417                 :          0 :         rte_free(vq->rxq.sw_ring);
     418                 :          0 :         vq->rxq.sw_ring = NULL;
     419                 :          0 : }
     420                 :            : 
     421                 :            : struct virtqueue *
     422                 :          0 : virtqueue_alloc(struct virtio_hw *hw, uint16_t index, uint16_t num, int type,
     423                 :            :                 int node, const char *name)
     424                 :            : {
     425                 :            :         struct virtqueue *vq;
     426                 :            :         const struct rte_memzone *mz;
     427                 :            :         unsigned int size;
     428                 :            : 
     429                 :          0 :         size = sizeof(*vq) + num * sizeof(struct vq_desc_extra);
     430                 :          0 :         size = RTE_ALIGN_CEIL(size, RTE_CACHE_LINE_SIZE);
     431                 :            : 
     432                 :          0 :         vq = rte_zmalloc_socket(name, size, RTE_CACHE_LINE_SIZE, node);
     433         [ #  # ]:          0 :         if (vq == NULL) {
     434                 :          0 :                 PMD_INIT_LOG(ERR, "can not allocate vq");
     435                 :          0 :                 return NULL;
     436                 :            :         }
     437                 :            : 
     438                 :          0 :         vq->hw = hw;
     439                 :          0 :         vq->vq_queue_index = index;
     440         [ #  # ]:          0 :         vq->vq_nentries = num;
     441         [ #  # ]:          0 :         if (virtio_with_packed_queue(hw)) {
     442                 :          0 :                 vq->vq_packed.used_wrap_counter = 1;
     443                 :          0 :                 vq->vq_packed.cached_flags = VRING_PACKED_DESC_F_AVAIL;
     444                 :          0 :                 vq->vq_packed.event_flags_shadow = 0;
     445         [ #  # ]:          0 :                 if (type == VTNET_RQ)
     446                 :          0 :                         vq->vq_packed.cached_flags |= VRING_DESC_F_WRITE;
     447                 :            :         }
     448                 :            : 
     449                 :            :         /*
     450                 :            :          * Reserve a memzone for vring elements
     451                 :            :          */
     452                 :          0 :         size = vring_size(hw, num, VIRTIO_VRING_ALIGN);
     453                 :          0 :         vq->vq_ring_size = RTE_ALIGN_CEIL(size, VIRTIO_VRING_ALIGN);
     454                 :          0 :         PMD_INIT_LOG(DEBUG, "vring_size: %d, rounded_vring_size: %d", size, vq->vq_ring_size);
     455                 :            : 
     456                 :          0 :         mz = rte_memzone_reserve_aligned(name, vq->vq_ring_size, node,
     457                 :            :                         RTE_MEMZONE_IOVA_CONTIG, VIRTIO_VRING_ALIGN);
     458         [ #  # ]:          0 :         if (mz == NULL) {
     459         [ #  # ]:          0 :                 if (rte_errno == EEXIST)
     460                 :          0 :                         mz = rte_memzone_lookup(name);
     461         [ #  # ]:          0 :                 if (mz == NULL)
     462                 :          0 :                         goto free_vq;
     463                 :            :         }
     464                 :            : 
     465         [ #  # ]:          0 :         memset(mz->addr, 0, mz->len);
     466                 :          0 :         vq->mz = mz;
     467                 :          0 :         vq->vq_ring_virt_mem = mz->addr;
     468                 :            : 
     469         [ #  # ]:          0 :         if (hw->use_va) {
     470                 :          0 :                 vq->vq_ring_mem = (uintptr_t)mz->addr;
     471                 :          0 :                 vq->mbuf_addr_offset = offsetof(struct rte_mbuf, buf_addr);
     472                 :          0 :                 vq->mbuf_addr_mask = UINTPTR_MAX;
     473                 :            :         } else {
     474                 :          0 :                 vq->vq_ring_mem = mz->iova;
     475                 :          0 :                 vq->mbuf_addr_offset = offsetof(struct rte_mbuf, buf_iova);
     476                 :          0 :                 vq->mbuf_addr_mask = UINT64_MAX;
     477                 :            :         }
     478                 :            : 
     479                 :          0 :         PMD_INIT_LOG(DEBUG, "vq->vq_ring_mem: 0x%" PRIx64, vq->vq_ring_mem);
     480                 :          0 :         PMD_INIT_LOG(DEBUG, "vq->vq_ring_virt_mem: %p", vq->vq_ring_virt_mem);
     481                 :            : 
     482                 :          0 :         virtio_init_vring(vq);
     483                 :            : 
     484         [ #  # ]:          0 :         if (virtio_alloc_queue_headers(vq, node, name)) {
     485                 :          0 :                 PMD_INIT_LOG(ERR, "Failed to alloc queue headers");
     486                 :          0 :                 goto free_mz;
     487                 :            :         }
     488                 :            : 
     489      [ #  #  # ]:          0 :         switch (type) {
     490                 :          0 :         case VTNET_RQ:
     491         [ #  # ]:          0 :                 if (virtio_rxq_sw_ring_alloc(vq, node))
     492                 :          0 :                         goto free_hdr_mz;
     493                 :            :                 break;
     494                 :          0 :         case VTNET_TQ:
     495                 :          0 :                 virtqueue_txq_indirect_headers_init(vq);
     496                 :          0 :                 break;
     497                 :            :         }
     498                 :            : 
     499                 :            :         return vq;
     500                 :            : 
     501                 :            : free_hdr_mz:
     502                 :          0 :         virtio_free_queue_headers(vq);
     503                 :          0 : free_mz:
     504                 :          0 :         rte_memzone_free(mz);
     505                 :          0 : free_vq:
     506                 :          0 :         rte_free(vq);
     507                 :            : 
     508                 :          0 :         return NULL;
     509                 :            : }
     510                 :            : 
     511                 :            : void
     512                 :          0 : virtqueue_free(struct virtqueue *vq)
     513                 :            : {
     514                 :            :         int type;
     515                 :            : 
     516         [ #  # ]:          0 :         type = virtio_get_queue_type(vq->hw, vq->vq_queue_index);
     517                 :            :         switch (type) {
     518                 :            :         case VTNET_RQ:
     519                 :            :                 virtio_rxq_sw_ring_free(vq);
     520                 :            :                 break;
     521                 :          0 :         case VTNET_TQ:
     522                 :            :         case VTNET_CQ:
     523                 :          0 :                 virtio_free_queue_headers(vq);
     524                 :          0 :                 break;
     525                 :            :         }
     526                 :            : 
     527                 :          0 :         rte_memzone_free(vq->mz);
     528                 :          0 :         rte_free(vq);
     529                 :          0 : }

Generated by: LCOV version 1.14