Re: [PATCH v7 08/12] vdpa: Move command buffers map to start of net device
On Tue, Aug 9, 2022 at 4:04 PM Eugenio Perez Martin wrote: > > On Tue, Aug 9, 2022 at 9:49 AM Jason Wang wrote: > > > > On Tue, Aug 9, 2022 at 3:34 PM Eugenio Perez Martin > > wrote: > > > > > > On Tue, Aug 9, 2022 at 9:04 AM Jason Wang wrote: > > > > > > > > On Fri, Aug 5, 2022 at 2:29 AM Eugenio Pérez > > > > wrote: > > > > > > > > > > As this series will reuse them to restore the device state at the end > > > > > of > > > > > a migration (or a device start), let's allocate only once at the > > > > > device > > > > > start so we don't duplicate their map and unmap. > > > > > > > > > > Signed-off-by: Eugenio Pérez > > > > > --- > > > > > net/vhost-vdpa.c | 123 > > > > > ++- > > > > > 1 file changed, 58 insertions(+), 65 deletions(-) > > > > > > > > > > diff --git a/net/vhost-vdpa.c b/net/vhost-vdpa.c > > > > > index 55e8a39a56..2c6a26cca0 100644 > > > > > --- a/net/vhost-vdpa.c > > > > > +++ b/net/vhost-vdpa.c > > > > > @@ -263,29 +263,20 @@ static size_t > > > > > vhost_vdpa_net_cvq_cmd_page_len(void) > > > > > return ROUND_UP(vhost_vdpa_net_cvq_cmd_len(), > > > > > qemu_real_host_page_size()); > > > > > } > > > > > > > > > > -/** Copy and map a guest buffer. */ > > > > > -static bool vhost_vdpa_cvq_map_buf(struct vhost_vdpa *v, > > > > > - const struct iovec *out_data, > > > > > - size_t out_num, size_t data_len, > > > > > void *buf, > > > > > - size_t *written, bool write) > > > > > +/** Map CVQ buffer. */ > > > > > +static int vhost_vdpa_cvq_map_buf(struct vhost_vdpa *v, void *buf, > > > > > size_t size, > > > > > + bool write) > > > > > { > > > > > DMAMap map = {}; > > > > > int r; > > > > > > > > > > -if (unlikely(!data_len)) { > > > > > -qemu_log_mask(LOG_GUEST_ERROR, "%s: invalid legnth of %s > > > > > buffer\n", > > > > > - __func__, write ? "in" : "out"); > > > > > -return false; > > > > > -} > > > > > - > > > > > -*written = iov_to_buf(out_data, out_num, 0, buf, data_len); > > > > > map.translated_addr = (hwaddr)(uintptr_t)buf; > > > > > -map.size = vhost_vdpa_net_cvq_cmd_page_len() - 1; > > > > > +map.size = size - 1; > > > > > > > > Just noticed this, I think I've asked for the reason before but I > > > > don't remember the answer. > > > > > > > > But it looks like a hint of a defect of the current API design. > > > > > > > > > > I can look for it in the mail list, but long story short: > > > vDPA DMA API is *not* inclusive: To map the first page, you map (.iova > > > = 0, .size = 4096). > > > IOVA tree API has been inclusive forever: To map the first page, you > > > map (.iova = 0, .size = 4095). If we map with .size = 4096, .iova = > > > 4096 is considered mapped too. > > > > This looks like a bug. > > > > {.iova=0, size=0} should be illegal but if I understand you correctly, > > it means [0, 1)? > > > > On iova_tree it works the way you point here, yes. Maybe the member's > name should have been length or something like that. > > On intel_iommu the address *mask* is actually used to fill the size, > not the actual DMA entry length. > > For SVQ I think it would be beneficial to declare two different types, > size_inclusive and size_non_inclusive, and check at compile time if > the caller is using the right type. That's sub-optimal, we'd better go with a single type of size or switch to use [start, end]. > But it's not top priority at the > moment. Yes, let's optimize it on top. Thanks > > Thanks! > > > Thanks > > > > > > > > To adapt one to the other would have been an API change even before > > > the introduction of vhost-iova-tree. > > > > > > Thanks! > > > > > > > > > > Thanks > > > > > > > > > map.perm = write ? IOMMU_RW : IOMMU_RO, > > > > > r = vhost_iova_tree_map_alloc(v->iova_tree, ); > > > > > if (unlikely(r != IOVA_OK)) { > > > > > error_report("Cannot map injected element"); > > > > > -return false; > > > > > +return r; > > > > > } > > > > > > > > > > r = vhost_vdpa_dma_map(v, map.iova, > > > > > vhost_vdpa_net_cvq_cmd_page_len(), buf, > > > > > @@ -294,50 +285,58 @@ static bool vhost_vdpa_cvq_map_buf(struct > > > > > vhost_vdpa *v, > > > > > goto dma_map_err; > > > > > } > > > > > > > > > > -return true; > > > > > +return 0; > > > > > > > > > > dma_map_err: > > > > > vhost_iova_tree_remove(v->iova_tree, ); > > > > > -return false; > > > > > +return r; > > > > > } > > > > > > > > > > -/** > > > > > - * Copy the guest element into a dedicated buffer suitable to be > > > > > sent to NIC > > > > > - * > > > > > - * @iov: [0] is the out buffer, [1] is the in one > > > > > - */ > > > > > -static bool vhost_vdpa_net_cvq_map_elem(VhostVDPAState *s, > > > > > -VirtQueueElement *elem,
Re: [PATCH v7 08/12] vdpa: Move command buffers map to start of net device
On Tue, Aug 9, 2022 at 9:49 AM Jason Wang wrote: > > On Tue, Aug 9, 2022 at 3:34 PM Eugenio Perez Martin > wrote: > > > > On Tue, Aug 9, 2022 at 9:04 AM Jason Wang wrote: > > > > > > On Fri, Aug 5, 2022 at 2:29 AM Eugenio Pérez wrote: > > > > > > > > As this series will reuse them to restore the device state at the end of > > > > a migration (or a device start), let's allocate only once at the device > > > > start so we don't duplicate their map and unmap. > > > > > > > > Signed-off-by: Eugenio Pérez > > > > --- > > > > net/vhost-vdpa.c | 123 ++- > > > > 1 file changed, 58 insertions(+), 65 deletions(-) > > > > > > > > diff --git a/net/vhost-vdpa.c b/net/vhost-vdpa.c > > > > index 55e8a39a56..2c6a26cca0 100644 > > > > --- a/net/vhost-vdpa.c > > > > +++ b/net/vhost-vdpa.c > > > > @@ -263,29 +263,20 @@ static size_t > > > > vhost_vdpa_net_cvq_cmd_page_len(void) > > > > return ROUND_UP(vhost_vdpa_net_cvq_cmd_len(), > > > > qemu_real_host_page_size()); > > > > } > > > > > > > > -/** Copy and map a guest buffer. */ > > > > -static bool vhost_vdpa_cvq_map_buf(struct vhost_vdpa *v, > > > > - const struct iovec *out_data, > > > > - size_t out_num, size_t data_len, > > > > void *buf, > > > > - size_t *written, bool write) > > > > +/** Map CVQ buffer. */ > > > > +static int vhost_vdpa_cvq_map_buf(struct vhost_vdpa *v, void *buf, > > > > size_t size, > > > > + bool write) > > > > { > > > > DMAMap map = {}; > > > > int r; > > > > > > > > -if (unlikely(!data_len)) { > > > > -qemu_log_mask(LOG_GUEST_ERROR, "%s: invalid legnth of %s > > > > buffer\n", > > > > - __func__, write ? "in" : "out"); > > > > -return false; > > > > -} > > > > - > > > > -*written = iov_to_buf(out_data, out_num, 0, buf, data_len); > > > > map.translated_addr = (hwaddr)(uintptr_t)buf; > > > > -map.size = vhost_vdpa_net_cvq_cmd_page_len() - 1; > > > > +map.size = size - 1; > > > > > > Just noticed this, I think I've asked for the reason before but I > > > don't remember the answer. > > > > > > But it looks like a hint of a defect of the current API design. > > > > > > > I can look for it in the mail list, but long story short: > > vDPA DMA API is *not* inclusive: To map the first page, you map (.iova > > = 0, .size = 4096). > > IOVA tree API has been inclusive forever: To map the first page, you > > map (.iova = 0, .size = 4095). If we map with .size = 4096, .iova = > > 4096 is considered mapped too. > > This looks like a bug. > > {.iova=0, size=0} should be illegal but if I understand you correctly, > it means [0, 1)? > On iova_tree it works the way you point here, yes. Maybe the member's name should have been length or something like that. On intel_iommu the address *mask* is actually used to fill the size, not the actual DMA entry length. For SVQ I think it would be beneficial to declare two different types, size_inclusive and size_non_inclusive, and check at compile time if the caller is using the right type. But it's not top priority at the moment. Thanks! > Thanks > > > > > To adapt one to the other would have been an API change even before > > the introduction of vhost-iova-tree. > > > > Thanks! > > > > > > > Thanks > > > > > > > map.perm = write ? IOMMU_RW : IOMMU_RO, > > > > r = vhost_iova_tree_map_alloc(v->iova_tree, ); > > > > if (unlikely(r != IOVA_OK)) { > > > > error_report("Cannot map injected element"); > > > > -return false; > > > > +return r; > > > > } > > > > > > > > r = vhost_vdpa_dma_map(v, map.iova, > > > > vhost_vdpa_net_cvq_cmd_page_len(), buf, > > > > @@ -294,50 +285,58 @@ static bool vhost_vdpa_cvq_map_buf(struct > > > > vhost_vdpa *v, > > > > goto dma_map_err; > > > > } > > > > > > > > -return true; > > > > +return 0; > > > > > > > > dma_map_err: > > > > vhost_iova_tree_remove(v->iova_tree, ); > > > > -return false; > > > > +return r; > > > > } > > > > > > > > -/** > > > > - * Copy the guest element into a dedicated buffer suitable to be sent > > > > to NIC > > > > - * > > > > - * @iov: [0] is the out buffer, [1] is the in one > > > > - */ > > > > -static bool vhost_vdpa_net_cvq_map_elem(VhostVDPAState *s, > > > > -VirtQueueElement *elem, > > > > -struct iovec *iov) > > > > +static int vhost_vdpa_net_cvq_prepare(NetClientState *nc) > > > > { > > > > -size_t in_copied; > > > > -bool ok; > > > > +VhostVDPAState *s; > > > > +int r; > > > > > > > > -iov[0].iov_base = s->cvq_cmd_out_buffer; > > > > -ok = vhost_vdpa_cvq_map_buf(>vhost_vdpa, elem->out_sg, > > > > elem->out_num, > > > > -vhost_vdpa_net_cvq_cmd_len(), > > > >
Re: [PATCH v7 08/12] vdpa: Move command buffers map to start of net device
On Tue, Aug 9, 2022 at 3:34 PM Eugenio Perez Martin wrote: > > On Tue, Aug 9, 2022 at 9:04 AM Jason Wang wrote: > > > > On Fri, Aug 5, 2022 at 2:29 AM Eugenio Pérez wrote: > > > > > > As this series will reuse them to restore the device state at the end of > > > a migration (or a device start), let's allocate only once at the device > > > start so we don't duplicate their map and unmap. > > > > > > Signed-off-by: Eugenio Pérez > > > --- > > > net/vhost-vdpa.c | 123 ++- > > > 1 file changed, 58 insertions(+), 65 deletions(-) > > > > > > diff --git a/net/vhost-vdpa.c b/net/vhost-vdpa.c > > > index 55e8a39a56..2c6a26cca0 100644 > > > --- a/net/vhost-vdpa.c > > > +++ b/net/vhost-vdpa.c > > > @@ -263,29 +263,20 @@ static size_t vhost_vdpa_net_cvq_cmd_page_len(void) > > > return ROUND_UP(vhost_vdpa_net_cvq_cmd_len(), > > > qemu_real_host_page_size()); > > > } > > > > > > -/** Copy and map a guest buffer. */ > > > -static bool vhost_vdpa_cvq_map_buf(struct vhost_vdpa *v, > > > - const struct iovec *out_data, > > > - size_t out_num, size_t data_len, void > > > *buf, > > > - size_t *written, bool write) > > > +/** Map CVQ buffer. */ > > > +static int vhost_vdpa_cvq_map_buf(struct vhost_vdpa *v, void *buf, > > > size_t size, > > > + bool write) > > > { > > > DMAMap map = {}; > > > int r; > > > > > > -if (unlikely(!data_len)) { > > > -qemu_log_mask(LOG_GUEST_ERROR, "%s: invalid legnth of %s > > > buffer\n", > > > - __func__, write ? "in" : "out"); > > > -return false; > > > -} > > > - > > > -*written = iov_to_buf(out_data, out_num, 0, buf, data_len); > > > map.translated_addr = (hwaddr)(uintptr_t)buf; > > > -map.size = vhost_vdpa_net_cvq_cmd_page_len() - 1; > > > +map.size = size - 1; > > > > Just noticed this, I think I've asked for the reason before but I > > don't remember the answer. > > > > But it looks like a hint of a defect of the current API design. > > > > I can look for it in the mail list, but long story short: > vDPA DMA API is *not* inclusive: To map the first page, you map (.iova > = 0, .size = 4096). > IOVA tree API has been inclusive forever: To map the first page, you > map (.iova = 0, .size = 4095). If we map with .size = 4096, .iova = > 4096 is considered mapped too. This looks like a bug. {.iova=0, size=0} should be illegal but if I understand you correctly, it means [0, 1)? Thanks > > To adapt one to the other would have been an API change even before > the introduction of vhost-iova-tree. > > Thanks! > > > > Thanks > > > > > map.perm = write ? IOMMU_RW : IOMMU_RO, > > > r = vhost_iova_tree_map_alloc(v->iova_tree, ); > > > if (unlikely(r != IOVA_OK)) { > > > error_report("Cannot map injected element"); > > > -return false; > > > +return r; > > > } > > > > > > r = vhost_vdpa_dma_map(v, map.iova, > > > vhost_vdpa_net_cvq_cmd_page_len(), buf, > > > @@ -294,50 +285,58 @@ static bool vhost_vdpa_cvq_map_buf(struct > > > vhost_vdpa *v, > > > goto dma_map_err; > > > } > > > > > > -return true; > > > +return 0; > > > > > > dma_map_err: > > > vhost_iova_tree_remove(v->iova_tree, ); > > > -return false; > > > +return r; > > > } > > > > > > -/** > > > - * Copy the guest element into a dedicated buffer suitable to be sent to > > > NIC > > > - * > > > - * @iov: [0] is the out buffer, [1] is the in one > > > - */ > > > -static bool vhost_vdpa_net_cvq_map_elem(VhostVDPAState *s, > > > -VirtQueueElement *elem, > > > -struct iovec *iov) > > > +static int vhost_vdpa_net_cvq_prepare(NetClientState *nc) > > > { > > > -size_t in_copied; > > > -bool ok; > > > +VhostVDPAState *s; > > > +int r; > > > > > > -iov[0].iov_base = s->cvq_cmd_out_buffer; > > > -ok = vhost_vdpa_cvq_map_buf(>vhost_vdpa, elem->out_sg, > > > elem->out_num, > > > -vhost_vdpa_net_cvq_cmd_len(), > > > iov[0].iov_base, > > > -[0].iov_len, false); > > > -if (unlikely(!ok)) { > > > -return false; > > > +assert(nc->info->type == NET_CLIENT_DRIVER_VHOST_VDPA); > > > + > > > +s = DO_UPCAST(VhostVDPAState, nc, nc); > > > +if (!s->vhost_vdpa.shadow_vqs_enabled) { > > > +return 0; > > > } > > > > > > -iov[1].iov_base = s->cvq_cmd_in_buffer; > > > -ok = vhost_vdpa_cvq_map_buf(>vhost_vdpa, NULL, 0, > > > -sizeof(virtio_net_ctrl_ack), > > > iov[1].iov_base, > > > -_copied, true); > > > -if (unlikely(!ok)) { > > > +r = vhost_vdpa_cvq_map_buf(>vhost_vdpa, s->cvq_cmd_out_buffer, > > > +
Re: [PATCH v7 08/12] vdpa: Move command buffers map to start of net device
On Tue, Aug 9, 2022 at 9:04 AM Jason Wang wrote: > > On Fri, Aug 5, 2022 at 2:29 AM Eugenio Pérez wrote: > > > > As this series will reuse them to restore the device state at the end of > > a migration (or a device start), let's allocate only once at the device > > start so we don't duplicate their map and unmap. > > > > Signed-off-by: Eugenio Pérez > > --- > > net/vhost-vdpa.c | 123 ++- > > 1 file changed, 58 insertions(+), 65 deletions(-) > > > > diff --git a/net/vhost-vdpa.c b/net/vhost-vdpa.c > > index 55e8a39a56..2c6a26cca0 100644 > > --- a/net/vhost-vdpa.c > > +++ b/net/vhost-vdpa.c > > @@ -263,29 +263,20 @@ static size_t vhost_vdpa_net_cvq_cmd_page_len(void) > > return ROUND_UP(vhost_vdpa_net_cvq_cmd_len(), > > qemu_real_host_page_size()); > > } > > > > -/** Copy and map a guest buffer. */ > > -static bool vhost_vdpa_cvq_map_buf(struct vhost_vdpa *v, > > - const struct iovec *out_data, > > - size_t out_num, size_t data_len, void > > *buf, > > - size_t *written, bool write) > > +/** Map CVQ buffer. */ > > +static int vhost_vdpa_cvq_map_buf(struct vhost_vdpa *v, void *buf, size_t > > size, > > + bool write) > > { > > DMAMap map = {}; > > int r; > > > > -if (unlikely(!data_len)) { > > -qemu_log_mask(LOG_GUEST_ERROR, "%s: invalid legnth of %s buffer\n", > > - __func__, write ? "in" : "out"); > > -return false; > > -} > > - > > -*written = iov_to_buf(out_data, out_num, 0, buf, data_len); > > map.translated_addr = (hwaddr)(uintptr_t)buf; > > -map.size = vhost_vdpa_net_cvq_cmd_page_len() - 1; > > +map.size = size - 1; > > Just noticed this, I think I've asked for the reason before but I > don't remember the answer. > > But it looks like a hint of a defect of the current API design. > I can look for it in the mail list, but long story short: vDPA DMA API is *not* inclusive: To map the first page, you map (.iova = 0, .size = 4096). IOVA tree API has been inclusive forever: To map the first page, you map (.iova = 0, .size = 4095). If we map with .size = 4096, .iova = 4096 is considered mapped too. To adapt one to the other would have been an API change even before the introduction of vhost-iova-tree. Thanks! > Thanks > > > map.perm = write ? IOMMU_RW : IOMMU_RO, > > r = vhost_iova_tree_map_alloc(v->iova_tree, ); > > if (unlikely(r != IOVA_OK)) { > > error_report("Cannot map injected element"); > > -return false; > > +return r; > > } > > > > r = vhost_vdpa_dma_map(v, map.iova, vhost_vdpa_net_cvq_cmd_page_len(), > > buf, > > @@ -294,50 +285,58 @@ static bool vhost_vdpa_cvq_map_buf(struct vhost_vdpa > > *v, > > goto dma_map_err; > > } > > > > -return true; > > +return 0; > > > > dma_map_err: > > vhost_iova_tree_remove(v->iova_tree, ); > > -return false; > > +return r; > > } > > > > -/** > > - * Copy the guest element into a dedicated buffer suitable to be sent to > > NIC > > - * > > - * @iov: [0] is the out buffer, [1] is the in one > > - */ > > -static bool vhost_vdpa_net_cvq_map_elem(VhostVDPAState *s, > > -VirtQueueElement *elem, > > -struct iovec *iov) > > +static int vhost_vdpa_net_cvq_prepare(NetClientState *nc) > > { > > -size_t in_copied; > > -bool ok; > > +VhostVDPAState *s; > > +int r; > > > > -iov[0].iov_base = s->cvq_cmd_out_buffer; > > -ok = vhost_vdpa_cvq_map_buf(>vhost_vdpa, elem->out_sg, > > elem->out_num, > > -vhost_vdpa_net_cvq_cmd_len(), > > iov[0].iov_base, > > -[0].iov_len, false); > > -if (unlikely(!ok)) { > > -return false; > > +assert(nc->info->type == NET_CLIENT_DRIVER_VHOST_VDPA); > > + > > +s = DO_UPCAST(VhostVDPAState, nc, nc); > > +if (!s->vhost_vdpa.shadow_vqs_enabled) { > > +return 0; > > } > > > > -iov[1].iov_base = s->cvq_cmd_in_buffer; > > -ok = vhost_vdpa_cvq_map_buf(>vhost_vdpa, NULL, 0, > > -sizeof(virtio_net_ctrl_ack), > > iov[1].iov_base, > > -_copied, true); > > -if (unlikely(!ok)) { > > +r = vhost_vdpa_cvq_map_buf(>vhost_vdpa, s->cvq_cmd_out_buffer, > > + vhost_vdpa_net_cvq_cmd_page_len(), false); > > +if (unlikely(r < 0)) { > > +return r; > > +} > > + > > +r = vhost_vdpa_cvq_map_buf(>vhost_vdpa, s->cvq_cmd_in_buffer, > > + vhost_vdpa_net_cvq_cmd_page_len(), true); > > +if (unlikely(r < 0)) { > > vhost_vdpa_cvq_unmap_buf(>vhost_vdpa, s->cvq_cmd_out_buffer); > > -return false; > > } > > > > -iov[1].iov_len =
Re: [PATCH v7 08/12] vdpa: Move command buffers map to start of net device
On Fri, Aug 5, 2022 at 2:29 AM Eugenio Pérez wrote: > > As this series will reuse them to restore the device state at the end of > a migration (or a device start), let's allocate only once at the device > start so we don't duplicate their map and unmap. > > Signed-off-by: Eugenio Pérez > --- > net/vhost-vdpa.c | 123 ++- > 1 file changed, 58 insertions(+), 65 deletions(-) > > diff --git a/net/vhost-vdpa.c b/net/vhost-vdpa.c > index 55e8a39a56..2c6a26cca0 100644 > --- a/net/vhost-vdpa.c > +++ b/net/vhost-vdpa.c > @@ -263,29 +263,20 @@ static size_t vhost_vdpa_net_cvq_cmd_page_len(void) > return ROUND_UP(vhost_vdpa_net_cvq_cmd_len(), > qemu_real_host_page_size()); > } > > -/** Copy and map a guest buffer. */ > -static bool vhost_vdpa_cvq_map_buf(struct vhost_vdpa *v, > - const struct iovec *out_data, > - size_t out_num, size_t data_len, void > *buf, > - size_t *written, bool write) > +/** Map CVQ buffer. */ > +static int vhost_vdpa_cvq_map_buf(struct vhost_vdpa *v, void *buf, size_t > size, > + bool write) > { > DMAMap map = {}; > int r; > > -if (unlikely(!data_len)) { > -qemu_log_mask(LOG_GUEST_ERROR, "%s: invalid legnth of %s buffer\n", > - __func__, write ? "in" : "out"); > -return false; > -} > - > -*written = iov_to_buf(out_data, out_num, 0, buf, data_len); > map.translated_addr = (hwaddr)(uintptr_t)buf; > -map.size = vhost_vdpa_net_cvq_cmd_page_len() - 1; > +map.size = size - 1; Just noticed this, I think I've asked for the reason before but I don't remember the answer. But it looks like a hint of a defect of the current API design. Thanks > map.perm = write ? IOMMU_RW : IOMMU_RO, > r = vhost_iova_tree_map_alloc(v->iova_tree, ); > if (unlikely(r != IOVA_OK)) { > error_report("Cannot map injected element"); > -return false; > +return r; > } > > r = vhost_vdpa_dma_map(v, map.iova, vhost_vdpa_net_cvq_cmd_page_len(), > buf, > @@ -294,50 +285,58 @@ static bool vhost_vdpa_cvq_map_buf(struct vhost_vdpa *v, > goto dma_map_err; > } > > -return true; > +return 0; > > dma_map_err: > vhost_iova_tree_remove(v->iova_tree, ); > -return false; > +return r; > } > > -/** > - * Copy the guest element into a dedicated buffer suitable to be sent to NIC > - * > - * @iov: [0] is the out buffer, [1] is the in one > - */ > -static bool vhost_vdpa_net_cvq_map_elem(VhostVDPAState *s, > -VirtQueueElement *elem, > -struct iovec *iov) > +static int vhost_vdpa_net_cvq_prepare(NetClientState *nc) > { > -size_t in_copied; > -bool ok; > +VhostVDPAState *s; > +int r; > > -iov[0].iov_base = s->cvq_cmd_out_buffer; > -ok = vhost_vdpa_cvq_map_buf(>vhost_vdpa, elem->out_sg, elem->out_num, > -vhost_vdpa_net_cvq_cmd_len(), > iov[0].iov_base, > -[0].iov_len, false); > -if (unlikely(!ok)) { > -return false; > +assert(nc->info->type == NET_CLIENT_DRIVER_VHOST_VDPA); > + > +s = DO_UPCAST(VhostVDPAState, nc, nc); > +if (!s->vhost_vdpa.shadow_vqs_enabled) { > +return 0; > } > > -iov[1].iov_base = s->cvq_cmd_in_buffer; > -ok = vhost_vdpa_cvq_map_buf(>vhost_vdpa, NULL, 0, > -sizeof(virtio_net_ctrl_ack), iov[1].iov_base, > -_copied, true); > -if (unlikely(!ok)) { > +r = vhost_vdpa_cvq_map_buf(>vhost_vdpa, s->cvq_cmd_out_buffer, > + vhost_vdpa_net_cvq_cmd_page_len(), false); > +if (unlikely(r < 0)) { > +return r; > +} > + > +r = vhost_vdpa_cvq_map_buf(>vhost_vdpa, s->cvq_cmd_in_buffer, > + vhost_vdpa_net_cvq_cmd_page_len(), true); > +if (unlikely(r < 0)) { > vhost_vdpa_cvq_unmap_buf(>vhost_vdpa, s->cvq_cmd_out_buffer); > -return false; > } > > -iov[1].iov_len = sizeof(virtio_net_ctrl_ack); > -return true; > +return r; > +} > + > +static void vhost_vdpa_net_cvq_stop(NetClientState *nc) > +{ > +VhostVDPAState *s = DO_UPCAST(VhostVDPAState, nc, nc); > + > +assert(nc->info->type == NET_CLIENT_DRIVER_VHOST_VDPA); > + > +if (s->vhost_vdpa.shadow_vqs_enabled) { > +vhost_vdpa_cvq_unmap_buf(>vhost_vdpa, s->cvq_cmd_out_buffer); > +vhost_vdpa_cvq_unmap_buf(>vhost_vdpa, s->cvq_cmd_in_buffer); > +} > } > > static NetClientInfo net_vhost_vdpa_cvq_info = { > .type = NET_CLIENT_DRIVER_VHOST_VDPA, > .size = sizeof(VhostVDPAState), > .receive = vhost_vdpa_receive, > +.prepare = vhost_vdpa_net_cvq_prepare, > +.stop = vhost_vdpa_net_cvq_stop, > .cleanup =