[v2,5/7] vdpa/mlx5: cache and reuse hardware resources
Checks
Commit Message
During device suspend and resume, resources are not changed normally.
When huge resources allocated to VM, like huge memory size or lots of
queues, time spent on release and recreate became significant.
To speed up, this patch reuse resoruces like VM MR and VirtQ memory if
not changed.
Signed-off-by: Xueming Li <xuemingl@nvidia.com>
---
drivers/vdpa/mlx5/mlx5_vdpa.c | 11 ++++-
drivers/vdpa/mlx5/mlx5_vdpa.h | 12 ++++-
drivers/vdpa/mlx5/mlx5_vdpa_mem.c | 27 ++++++++++-
drivers/vdpa/mlx5/mlx5_vdpa_virtq.c | 73 +++++++++++++++++++++--------
4 files changed, 99 insertions(+), 24 deletions(-)
Comments
On 2/24/22 16:50, Xueming Li wrote:
> During device suspend and resume, resources are not changed normally.
> When huge resources allocated to VM, like huge memory size or lots of
"When huge resources were allocated"
> queues, time spent on release and recreate became significant.
>
> To speed up, this patch reuse resoruces like VM MR and VirtQ memory if
"reuses resources"
> not changed.
>
> Signed-off-by: Xueming Li <xuemingl@nvidia.com>
> ---
> drivers/vdpa/mlx5/mlx5_vdpa.c | 11 ++++-
> drivers/vdpa/mlx5/mlx5_vdpa.h | 12 ++++-
> drivers/vdpa/mlx5/mlx5_vdpa_mem.c | 27 ++++++++++-
> drivers/vdpa/mlx5/mlx5_vdpa_virtq.c | 73 +++++++++++++++++++++--------
> 4 files changed, 99 insertions(+), 24 deletions(-)
>
Reviewed-by: Maxime Coquelin <maxime.coquelin@redhat.com>
Thanks,
Maxime
Hi Maxime,
Thanks for the suggestion, I'll send out a new version.
Regards,
Xueming Li
> -----Original Message-----
> From: Maxime Coquelin <maxime.coquelin@redhat.com>
> Sent: Wednesday, April 20, 2022 11:03 PM
> To: Xueming(Steven) Li <xuemingl@nvidia.com>; dev@dpdk.org
> Cc: Matan Azrad <matan@nvidia.com>; Slava Ovsiienko <viacheslavo@nvidia.com>
> Subject: Re: [PATCH v2 5/7] vdpa/mlx5: cache and reuse hardware resources
>
>
>
> On 2/24/22 16:50, Xueming Li wrote:
> > During device suspend and resume, resources are not changed normally.
> > When huge resources allocated to VM, like huge memory size or lots of
>
> "When huge resources were allocated"
>
> > queues, time spent on release and recreate became significant.
> >
> > To speed up, this patch reuse resoruces like VM MR and VirtQ memory if
>
> "reuses resources"
>
> > not changed.
> >
> > Signed-off-by: Xueming Li <xuemingl@nvidia.com>
> > ---
> > drivers/vdpa/mlx5/mlx5_vdpa.c | 11 ++++-
> > drivers/vdpa/mlx5/mlx5_vdpa.h | 12 ++++-
> > drivers/vdpa/mlx5/mlx5_vdpa_mem.c | 27 ++++++++++-
> > drivers/vdpa/mlx5/mlx5_vdpa_virtq.c | 73 +++++++++++++++++++++--------
> > 4 files changed, 99 insertions(+), 24 deletions(-)
> >
>
> Reviewed-by: Maxime Coquelin <maxime.coquelin@redhat.com>
>
> Thanks,
> Maxime
Hi Xueming,
On 4/25/22 15:28, Xueming(Steven) Li wrote:
> Hi Maxime,
>
> Thanks for the suggestion, I'll send out a new version.
Ok, if you sent it early next week, it could be part of next week's PR.
Thanks,
Maxime
> Regards,
> Xueming Li
>
>> -----Original Message-----
>> From: Maxime Coquelin <maxime.coquelin@redhat.com>
>> Sent: Wednesday, April 20, 2022 11:03 PM
>> To: Xueming(Steven) Li <xuemingl@nvidia.com>; dev@dpdk.org
>> Cc: Matan Azrad <matan@nvidia.com>; Slava Ovsiienko <viacheslavo@nvidia.com>
>> Subject: Re: [PATCH v2 5/7] vdpa/mlx5: cache and reuse hardware resources
>>
>>
>>
>> On 2/24/22 16:50, Xueming Li wrote:
>>> During device suspend and resume, resources are not changed normally.
>>> When huge resources allocated to VM, like huge memory size or lots of
>>
>> "When huge resources were allocated"
>>
>>> queues, time spent on release and recreate became significant.
>>>
>>> To speed up, this patch reuse resoruces like VM MR and VirtQ memory if
>>
>> "reuses resources"
>>
>>> not changed.
>>>
>>> Signed-off-by: Xueming Li <xuemingl@nvidia.com>
>>> ---
>>> drivers/vdpa/mlx5/mlx5_vdpa.c | 11 ++++-
>>> drivers/vdpa/mlx5/mlx5_vdpa.h | 12 ++++-
>>> drivers/vdpa/mlx5/mlx5_vdpa_mem.c | 27 ++++++++++-
>>> drivers/vdpa/mlx5/mlx5_vdpa_virtq.c | 73 +++++++++++++++++++++--------
>>> 4 files changed, 99 insertions(+), 24 deletions(-)
>>>
>>
>> Reviewed-by: Maxime Coquelin <maxime.coquelin@redhat.com>
>>
>> Thanks,
>> Maxime
>
@@ -241,6 +241,13 @@ mlx5_vdpa_mtu_set(struct mlx5_vdpa_priv *priv)
return kern_mtu == vhost_mtu ? 0 : -1;
}
+static void
+mlx5_vdpa_dev_cache_clean(struct mlx5_vdpa_priv *priv)
+{
+ mlx5_vdpa_virtqs_cleanup(priv);
+ mlx5_vdpa_mem_dereg(priv);
+}
+
static int
mlx5_vdpa_dev_close(int vid)
{
@@ -260,7 +267,8 @@ mlx5_vdpa_dev_close(int vid)
}
mlx5_vdpa_steer_unset(priv);
mlx5_vdpa_virtqs_release(priv);
- mlx5_vdpa_mem_dereg(priv);
+ if (priv->lm_mr.addr)
+ mlx5_os_wrapped_mkey_destroy(&priv->lm_mr);
priv->state = MLX5_VDPA_STATE_PROBED;
priv->vid = 0;
/* The mutex may stay locked after event thread cancel - initiate it. */
@@ -659,6 +667,7 @@ mlx5_vdpa_release_dev_resources(struct mlx5_vdpa_priv *priv)
{
uint32_t i;
+ mlx5_vdpa_dev_cache_clean(priv);
mlx5_vdpa_event_qp_global_release(priv);
mlx5_vdpa_err_event_unset(priv);
if (priv->steer.tbl)
@@ -289,13 +289,21 @@ int mlx5_vdpa_err_event_setup(struct mlx5_vdpa_priv *priv);
void mlx5_vdpa_err_event_unset(struct mlx5_vdpa_priv *priv);
/**
- * Release a virtq and all its related resources.
+ * Release virtqs and resources except that to be reused.
*
* @param[in] priv
* The vdpa driver private structure.
*/
void mlx5_vdpa_virtqs_release(struct mlx5_vdpa_priv *priv);
+/**
+ * Cleanup cached resources of all virtqs.
+ *
+ * @param[in] priv
+ * The vdpa driver private structure.
+ */
+void mlx5_vdpa_virtqs_cleanup(struct mlx5_vdpa_priv *priv);
+
/**
* Create all the HW virtqs resources and all their related resources.
*
@@ -323,7 +331,7 @@ int mlx5_vdpa_virtqs_prepare(struct mlx5_vdpa_priv *priv);
int mlx5_vdpa_virtq_enable(struct mlx5_vdpa_priv *priv, int index, int enable);
/**
- * Unset steering and release all its related resources- stop traffic.
+ * Unset steering - stop traffic.
*
* @param[in] priv
* The vdpa driver private structure.
@@ -32,8 +32,6 @@ mlx5_vdpa_mem_dereg(struct mlx5_vdpa_priv *priv)
entry = next;
}
SLIST_INIT(&priv->mr_list);
- if (priv->lm_mr.addr)
- mlx5_os_wrapped_mkey_destroy(&priv->lm_mr);
if (priv->vmem) {
free(priv->vmem);
priv->vmem = NULL;
@@ -149,6 +147,23 @@ mlx5_vdpa_vhost_mem_regions_prepare(int vid, uint8_t *mode, uint64_t *mem_size,
return mem;
}
+static int
+mlx5_vdpa_mem_cmp(struct rte_vhost_memory *mem1, struct rte_vhost_memory *mem2)
+{
+ uint32_t i;
+
+ if (mem1->nregions != mem2->nregions)
+ return -1;
+ for (i = 0; i < mem1->nregions; i++) {
+ if (mem1->regions[i].guest_phys_addr !=
+ mem2->regions[i].guest_phys_addr)
+ return -1;
+ if (mem1->regions[i].size != mem2->regions[i].size)
+ return -1;
+ }
+ return 0;
+}
+
#define KLM_SIZE_MAX_ALIGN(sz) ((sz) > MLX5_MAX_KLM_BYTE_COUNT ? \
MLX5_MAX_KLM_BYTE_COUNT : (sz))
@@ -191,6 +206,14 @@ mlx5_vdpa_mem_register(struct mlx5_vdpa_priv *priv)
if (!mem)
return -rte_errno;
+ if (priv->vmem != NULL) {
+ if (mlx5_vdpa_mem_cmp(mem, priv->vmem) == 0) {
+ /* VM memory not changed, reuse resources. */
+ free(mem);
+ return 0;
+ }
+ mlx5_vdpa_mem_dereg(priv);
+ }
priv->vmem = mem;
for (i = 0; i < mem->nregions; i++) {
reg = &mem->regions[i];
@@ -66,10 +66,33 @@ mlx5_vdpa_virtq_kick_handler(void *cb_arg)
DRV_LOG(DEBUG, "Ring virtq %u doorbell.", virtq->index);
}
+/* Release cached VQ resources. */
+void
+mlx5_vdpa_virtqs_cleanup(struct mlx5_vdpa_priv *priv)
+{
+ unsigned int i, j;
+
+ for (i = 0; i < priv->caps.max_num_virtio_queues * 2; i++) {
+ struct mlx5_vdpa_virtq *virtq = &priv->virtqs[i];
+
+ for (j = 0; j < RTE_DIM(virtq->umems); ++j) {
+ if (virtq->umems[j].obj) {
+ claim_zero(mlx5_glue->devx_umem_dereg
+ (virtq->umems[j].obj));
+ virtq->umems[j].obj = NULL;
+ }
+ if (virtq->umems[j].buf) {
+ rte_free(virtq->umems[j].buf);
+ virtq->umems[j].buf = NULL;
+ }
+ virtq->umems[j].size = 0;
+ }
+ }
+}
+
static int
mlx5_vdpa_virtq_unset(struct mlx5_vdpa_virtq *virtq)
{
- unsigned int i;
int ret = -EAGAIN;
if (rte_intr_fd_get(virtq->intr_handle) >= 0) {
@@ -94,13 +117,6 @@ mlx5_vdpa_virtq_unset(struct mlx5_vdpa_virtq *virtq)
claim_zero(mlx5_devx_cmd_destroy(virtq->virtq));
}
virtq->virtq = NULL;
- for (i = 0; i < RTE_DIM(virtq->umems); ++i) {
- if (virtq->umems[i].obj)
- claim_zero(mlx5_glue->devx_umem_dereg
- (virtq->umems[i].obj));
- rte_free(virtq->umems[i].buf);
- }
- memset(&virtq->umems, 0, sizeof(virtq->umems));
if (virtq->eqp.fw_qp)
mlx5_vdpa_event_qp_destroy(&virtq->eqp);
virtq->notifier_state = MLX5_VDPA_NOTIFIER_STATE_DISABLED;
@@ -120,7 +136,6 @@ mlx5_vdpa_virtqs_release(struct mlx5_vdpa_priv *priv)
claim_zero(mlx5_devx_cmd_destroy(virtq->counters));
}
priv->features = 0;
- memset(priv->virtqs, 0, sizeof(*virtq) * priv->nr_virtqs);
priv->nr_virtqs = 0;
}
@@ -215,6 +230,8 @@ mlx5_vdpa_virtq_setup(struct mlx5_vdpa_priv *priv, int index)
ret = rte_vhost_get_vhost_vring(priv->vid, index, &vq);
if (ret)
return -1;
+ if (vq.size == 0)
+ return 0;
virtq->index = index;
virtq->vq_size = vq.size;
attr.tso_ipv4 = !!(priv->features & (1ULL << VIRTIO_NET_F_HOST_TSO4));
@@ -259,24 +276,42 @@ mlx5_vdpa_virtq_setup(struct mlx5_vdpa_priv *priv, int index)
}
/* Setup 3 UMEMs for each virtq. */
for (i = 0; i < RTE_DIM(virtq->umems); ++i) {
- virtq->umems[i].size = priv->caps.umems[i].a * vq.size +
- priv->caps.umems[i].b;
- virtq->umems[i].buf = rte_zmalloc(__func__,
- virtq->umems[i].size, 4096);
- if (!virtq->umems[i].buf) {
+ uint32_t size;
+ void *buf;
+ struct mlx5dv_devx_umem *obj;
+
+ size = priv->caps.umems[i].a * vq.size + priv->caps.umems[i].b;
+ if (virtq->umems[i].size == size &&
+ virtq->umems[i].obj != NULL) {
+ /* Reuse registered memory. */
+ memset(virtq->umems[i].buf, 0, size);
+ goto reuse;
+ }
+ if (virtq->umems[i].obj)
+ claim_zero(mlx5_glue->devx_umem_dereg
+ (virtq->umems[i].obj));
+ if (virtq->umems[i].buf)
+ rte_free(virtq->umems[i].buf);
+ virtq->umems[i].size = 0;
+ virtq->umems[i].obj = NULL;
+ virtq->umems[i].buf = NULL;
+ buf = rte_zmalloc(__func__, size, 4096);
+ if (buf == NULL) {
DRV_LOG(ERR, "Cannot allocate umem %d memory for virtq"
" %u.", i, index);
goto error;
}
- virtq->umems[i].obj = mlx5_glue->devx_umem_reg(priv->cdev->ctx,
- virtq->umems[i].buf,
- virtq->umems[i].size,
- IBV_ACCESS_LOCAL_WRITE);
- if (!virtq->umems[i].obj) {
+ obj = mlx5_glue->devx_umem_reg(priv->cdev->ctx, buf, size,
+ IBV_ACCESS_LOCAL_WRITE);
+ if (obj == NULL) {
DRV_LOG(ERR, "Failed to register umem %d for virtq %u.",
i, index);
goto error;
}
+ virtq->umems[i].size = size;
+ virtq->umems[i].buf = buf;
+ virtq->umems[i].obj = obj;
+reuse:
attr.umems[i].id = virtq->umems[i].obj->umem_id;
attr.umems[i].offset = 0;
attr.umems[i].size = virtq->umems[i].size;