[PATCH v3] vdpa/mlx5: workaround var offset within page
vDPA driver first uses kernel driver to allocate doorbell(VAR) area for each device. Then uses var->mmap_off and var->length to mmap uverbs device file as doorbell userspace virtual address. Current kernel driver provides var->mmap_off equal to page start of VAR. It's fine with x86 4K page server, because VAR physical address is only 4K aligned thus locate in 4K page start. But with aarch64 64K page server, the actual VAR physical address has offset within page(not locate in 64K page start). So vDPA driver need add this within page offset(caps.doorbell_bar_offset) to get right VAR virtual address. Fixes: 62c813706e4 ("vdpa/mlx5: map doorbell") Cc: sta...@dpdk.org Signed-off-by: Yajun Wu Acked-by: Matan Azrad Reviewed-by: Maxime Coquelin --- drivers/vdpa/mlx5/mlx5_vdpa.c | 8 +++- 1 file changed, 7 insertions(+), 1 deletion(-) diff --git a/drivers/vdpa/mlx5/mlx5_vdpa.c b/drivers/vdpa/mlx5/mlx5_vdpa.c index 76fa5d4299..8a33a0c9a1 100644 --- a/drivers/vdpa/mlx5/mlx5_vdpa.c +++ b/drivers/vdpa/mlx5/mlx5_vdpa.c @@ -14,6 +14,7 @@ #include #include #include +#include #include #include @@ -560,6 +561,9 @@ mlx5_vdpa_create_dev_resources(struct mlx5_vdpa_priv *priv) rte_errno = errno; return -rte_errno; } + /* Add within page offset for 64K page system. */ + priv->virtq_db_addr = (char *)priv->virtq_db_addr + + ((rte_mem_page_size() - 1) & priv->caps.doorbell_bar_offset); DRV_LOG(DEBUG, "VAR address of doorbell mapping is %p.", priv->virtq_db_addr); priv->td = mlx5_devx_cmd_create_td(ctx); @@ -705,7 +709,9 @@ mlx5_vdpa_release_dev_resources(struct mlx5_vdpa_priv *priv) if (priv->td) claim_zero(mlx5_devx_cmd_destroy(priv->td)); if (priv->virtq_db_addr) - claim_zero(munmap(priv->virtq_db_addr, priv->var->length)); + /* Mask out the within page offset for munmap. */ + claim_zero(munmap((void *)((uintptr_t)priv->virtq_db_addr & + ~(rte_mem_page_size() - 1)), priv->var->length)); if (priv->var) mlx5_glue->dv_free_var(priv->var); } -- 2.30.2
[PATCH] common/mlx5: fix QP ack timeout configuration
VDPA driver creates two QPs(1 queue pair include 1 send queue and 1 receive queue) per virtio queue to get traffic events from NIC to SW. Two QPs(called FW QP and SW QP) are created as loopback QP and FW QP'SQ is connected to SW QP'RQ internally. When packet receive or send out, HW will send WQE by FW QP'SQ, then SW will get CQE from the CQ of SW QP. With large scale and heavy traffic, the SQ's request may fail to get ACK from RQ HW, because HW is busy. SQ will retry the request with qpc.retry_count times and each time wait for 4.096 uS *2^(ack_timeout) for the response. If still can’t get RQ’s HW response, SQ will go to an error state. 16 is experienced value. It should not be too high or too low. Too high will make QP waits too long in case it’s packet drop. Too low will cause QP to go to an error state(retry-exceeded) easily. Fixes: 15c3807e86a ("common/mlx5: support DevX QP operations") Cc: sta...@dpdk.org Signed-off-by: Yajun Wu Acked-by: Matan Azrad --- drivers/common/mlx5/mlx5_devx_cmds.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/drivers/common/mlx5/mlx5_devx_cmds.c b/drivers/common/mlx5/mlx5_devx_cmds.c index 2e807a0829..7732613c69 100644 --- a/drivers/common/mlx5/mlx5_devx_cmds.c +++ b/drivers/common/mlx5/mlx5_devx_cmds.c @@ -2279,7 +2279,7 @@ mlx5_devx_cmd_modify_qp_state(struct mlx5_devx_obj *qp, uint32_t qp_st_mod_op, case MLX5_CMD_OP_RTR2RTS_QP: qpc = MLX5_ADDR_OF(rtr2rts_qp_in, &in, qpc); MLX5_SET(rtr2rts_qp_in, &in, qpn, qp->id); - MLX5_SET(qpc, qpc, primary_address_path.ack_timeout, 14); + MLX5_SET(qpc, qpc, primary_address_path.ack_timeout, 16); MLX5_SET(qpc, qpc, log_ack_req_freq, 0); MLX5_SET(qpc, qpc, retry_count, 7); MLX5_SET(qpc, qpc, rnr_retry, 7); -- 2.27.0
[PATCH] vdpa/mlx5: fix queue enable drain CQ
For the case: `ethtool -L eth0 combined xxx` in VM, VQ will disable and enable without calling device close. In such case, need add drain CQ before reuse/reset event QP. Fixes: 24969c7b62 ("vdpa/mlx5: reuse event queues") Cc: sta...@dpdk.org Signed-off-by: Yajun Wu Acked-by: Matan Azrad --- drivers/vdpa/mlx5/mlx5_vdpa_event.c | 29 +++-- 1 file changed, 19 insertions(+), 10 deletions(-) diff --git a/drivers/vdpa/mlx5/mlx5_vdpa_event.c b/drivers/vdpa/mlx5/mlx5_vdpa_event.c index 9557c1042e..32430614d5 100644 --- a/drivers/vdpa/mlx5/mlx5_vdpa_event.c +++ b/drivers/vdpa/mlx5/mlx5_vdpa_event.c @@ -244,22 +244,30 @@ mlx5_vdpa_queues_complete(struct mlx5_vdpa_priv *priv) return max; } +static void +mlx5_vdpa_drain_cq_one(struct mlx5_vdpa_priv *priv, + struct mlx5_vdpa_virtq *virtq) +{ + struct mlx5_vdpa_cq *cq = &virtq->eqp.cq; + + mlx5_vdpa_queue_complete(cq); + if (cq->cq_obj.cq) { + cq->cq_obj.cqes[0].wqe_counter = rte_cpu_to_be_16(UINT16_MAX); + virtq->eqp.qp_pi = 0; + if (!cq->armed) + mlx5_vdpa_cq_arm(priv, cq); + } +} + void mlx5_vdpa_drain_cq(struct mlx5_vdpa_priv *priv) { + struct mlx5_vdpa_virtq *virtq; unsigned int i; for (i = 0; i < priv->caps.max_num_virtio_queues; i++) { - struct mlx5_vdpa_cq *cq = &priv->virtqs[i].eqp.cq; - - mlx5_vdpa_queue_complete(cq); - if (cq->cq_obj.cq) { - cq->cq_obj.cqes[0].wqe_counter = - rte_cpu_to_be_16(UINT16_MAX); - priv->virtqs[i].eqp.qp_pi = 0; - if (!cq->armed) - mlx5_vdpa_cq_arm(priv, cq); - } + virtq = &priv->virtqs[i]; + mlx5_vdpa_drain_cq_one(priv, virtq); } } @@ -632,6 +640,7 @@ mlx5_vdpa_event_qp_prepare(struct mlx5_vdpa_priv *priv, uint16_t desc_n, if (eqp->cq.cq_obj.cq != NULL && log_desc_n == eqp->cq.log_desc_n) { /* Reuse existing resources. */ eqp->cq.callfd = callfd; + mlx5_vdpa_drain_cq_one(priv, virtq); /* FW will set event qp to error state in q destroy. */ if (reset && !mlx5_vdpa_qps2rst2rts(eqp)) rte_write32(rte_cpu_to_be_32(RTE_BIT32(log_desc_n)), -- 2.27.0
[PATCH] vdpa/mlx5: fix unregister kick handler order
The mlx5_vdpa_virtq_kick_handler function may still be running and waiting on virtq->virtq_lock while mlx5_vdpa_cqe_event_unset function is trying to re-initialize the virtq->virtq_lock. This causes mlx5_vdpa_virtq_kick_handler thread can't be wake up and can't be unregister. Following print may loop forever when calling rte_vhost_driver_unregister(socket_path): mlx5_vdpa: Try again to unregister fd 154 of virtq 11 interrupt mlx5_vdpa: Try again to unregister fd 154 of virtq 11 interrupt ... The fix is to move mlx5_vdpa_virtq_unregister_intr_handle before mlx5_vdpa_cqe_event_unset. Fixes: 057f7d2084 ("vdpa/mlx5: optimize datapath-control synchronization") Cc: sta...@dpdk.org Signed-off-by: Yajun Wu Acked-by: Matan Azrad --- drivers/vdpa/mlx5/mlx5_vdpa.c | 1 + drivers/vdpa/mlx5/mlx5_vdpa_cthread.c | 1 - 2 files changed, 1 insertion(+), 1 deletion(-) diff --git a/drivers/vdpa/mlx5/mlx5_vdpa.c b/drivers/vdpa/mlx5/mlx5_vdpa.c index f1737f82a8..8b1de8bd62 100644 --- a/drivers/vdpa/mlx5/mlx5_vdpa.c +++ b/drivers/vdpa/mlx5/mlx5_vdpa.c @@ -282,6 +282,7 @@ _internal_mlx5_vdpa_dev_close(struct mlx5_vdpa_priv *priv, int ret = 0; int vid = priv->vid; + mlx5_vdpa_virtq_unreg_intr_handle_all(priv); mlx5_vdpa_cqe_event_unset(priv); if (priv->state == MLX5_VDPA_STATE_CONFIGURED) { ret |= mlx5_vdpa_lm_log(priv); diff --git a/drivers/vdpa/mlx5/mlx5_vdpa_cthread.c b/drivers/vdpa/mlx5/mlx5_vdpa_cthread.c index 6e6624e5a3..1d84e422d4 100644 --- a/drivers/vdpa/mlx5/mlx5_vdpa_cthread.c +++ b/drivers/vdpa/mlx5/mlx5_vdpa_cthread.c @@ -190,7 +190,6 @@ mlx5_vdpa_c_thread_handle(void *arg) pthread_mutex_unlock(&virtq->virtq_lock); break; case MLX5_VDPA_TASK_DEV_CLOSE_NOWAIT: - mlx5_vdpa_virtq_unreg_intr_handle_all(priv); pthread_mutex_lock(&priv->steer_update_lock); mlx5_vdpa_steer_unset(priv); pthread_mutex_unlock(&priv->steer_update_lock); -- 2.27.0
[PATCH] examples/vdpa: fix devices cleanup
Move rte_eal_cleanup to function vdpa_sample_quit which handling all example app quit. Otherwise rte_eal_cleanup won't be called on receiving signal like SIGINT(control + c). Fixes: 10aa3757 ("examples: add eal cleanup to examples") Cc: sta...@dpdk.org Signed-off-by: Yajun Wu Acked-by: Matan Azrad --- examples/vdpa/main.c | 5 ++--- 1 file changed, 2 insertions(+), 3 deletions(-) diff --git a/examples/vdpa/main.c b/examples/vdpa/main.c index 4c7e81d7b6..9149b66538 100644 --- a/examples/vdpa/main.c +++ b/examples/vdpa/main.c @@ -287,6 +287,8 @@ vdpa_sample_quit(void) if (vports[i].ifname[0] != '\0') close_vdpa(&vports[i]); } + /* clean up the EAL */ + rte_eal_cleanup(); } static void @@ -633,8 +635,5 @@ main(int argc, char *argv[]) vdpa_sample_quit(); } - /* clean up the EAL */ - rte_eal_cleanup(); - return 0; } -- 2.27.0
[PATCH] vdpa/mlx5: workaround var offset within page
vDPA driver first uses kernel driver to allocate doorbell(VAR) area for each device. Then uses var->mmap_off and var->length to mmap uverbs device file as doorbell userspace virtual address. Current kernel driver provides var->mmap_off equal to page start of VAR. It's fine with x86 4K page server, because VAR physical address is only 4K aligned thus locate in 4K page start. But with aarch64 64K page server, the actual VAR physical address has offset within page(not locate in 64K page start). So vDPA driver need add this within page offset(caps.doorbell_bar_offset) to get right VAR virtual address. Fixes: 62c813706e4 ("vdpa/mlx5: map doorbell") Cc: sta...@dpdk.org Signed-off-by: Yajun Wu Acked-by: Matan Azrad --- drivers/vdpa/mlx5/mlx5_vdpa_virtq.c | 10 +- 1 file changed, 9 insertions(+), 1 deletion(-) diff --git a/drivers/vdpa/mlx5/mlx5_vdpa_virtq.c b/drivers/vdpa/mlx5/mlx5_vdpa_virtq.c index 3416797d28..0748710a76 100644 --- a/drivers/vdpa/mlx5/mlx5_vdpa_virtq.c +++ b/drivers/vdpa/mlx5/mlx5_vdpa_virtq.c @@ -9,6 +9,7 @@ #include #include #include +#include #include @@ -123,7 +124,10 @@ mlx5_vdpa_virtqs_release(struct mlx5_vdpa_priv *priv) priv->td = NULL; } if (priv->virtq_db_addr) { - claim_zero(munmap(priv->virtq_db_addr, priv->var->length)); + /* Mask out the within page offset for ummap. */ + claim_zero(munmap((void *)((uint64_t)priv->virtq_db_addr & + ~(rte_mem_page_size() - 1ULL)), + priv->var->length)); priv->virtq_db_addr = NULL; } priv->features = 0; @@ -486,6 +490,10 @@ mlx5_vdpa_virtqs_prepare(struct mlx5_vdpa_priv *priv) priv->virtq_db_addr = NULL; goto error; } else { + /* Add within page offset for 64K page system. */ + priv->virtq_db_addr = (char *)priv->virtq_db_addr + + ((rte_mem_page_size() - 1) & + priv->caps.doorbell_bar_offset); DRV_LOG(DEBUG, "VAR address of doorbell mapping is %p.", priv->virtq_db_addr); } -- 2.27.0
[PATCH v2] vdpa/mlx5: workaround var offset within page
vDPA driver first uses kernel driver to allocate doorbell(VAR) area for each device. Then uses var->mmap_off and var->length to mmap uverbs device file as doorbell userspace virtual address. Current kernel driver provides var->mmap_off equal to page start of VAR. It's fine with x86 4K page server, because VAR physical address is only 4K aligned thus locate in 4K page start. But with aarch64 64K page server, the actual VAR physical address has offset within page(not locate in 64K page start). So vDPA driver need add this within page offset(caps.doorbell_bar_offset) to get right VAR virtual address. Fixes: 62c813706e4 ("vdpa/mlx5: map doorbell") Cc: sta...@dpdk.org Signed-off-by: Yajun Wu Acked-by: Matan Azrad --- drivers/vdpa/mlx5/mlx5_vdpa_virtq.c | 9 - 1 file changed, 8 insertions(+), 1 deletion(-) diff --git a/drivers/vdpa/mlx5/mlx5_vdpa_virtq.c b/drivers/vdpa/mlx5/mlx5_vdpa_virtq.c index 3416797d28..52287e7e58 100644 --- a/drivers/vdpa/mlx5/mlx5_vdpa_virtq.c +++ b/drivers/vdpa/mlx5/mlx5_vdpa_virtq.c @@ -9,6 +9,7 @@ #include #include #include +#include #include @@ -123,7 +124,9 @@ mlx5_vdpa_virtqs_release(struct mlx5_vdpa_priv *priv) priv->td = NULL; } if (priv->virtq_db_addr) { - claim_zero(munmap(priv->virtq_db_addr, priv->var->length)); + /* Mask out the within page offset for munmap. */ + claim_zero(munmap((void *)((uintptr_t)priv->virtq_db_addr & + ~(rte_mem_page_size() - 1)), priv->var->length)); priv->virtq_db_addr = NULL; } priv->features = 0; @@ -486,6 +489,10 @@ mlx5_vdpa_virtqs_prepare(struct mlx5_vdpa_priv *priv) priv->virtq_db_addr = NULL; goto error; } else { + /* Add within page offset for 64K page system. */ + priv->virtq_db_addr = (char *)priv->virtq_db_addr + + ((rte_mem_page_size() - 1) & + priv->caps.doorbell_bar_offset); DRV_LOG(DEBUG, "VAR address of doorbell mapping is %p.", priv->virtq_db_addr); } -- 2.27.0