X-Git-Url: http://git.droids-corp.org/?a=blobdiff_plain;f=drivers%2Fvdpa%2Fmlx5%2Fmlx5_vdpa_event.c;h=bb6722839aa3fe715f511cc6f53bc0f0d2e9a911;hb=4ad8bc2fc7857a92aa0bb147529859358c5acc4f;hp=17fd9dd4fc6fe54b4a09e5d39c1933538945bbbb;hpb=30b6974441b09665617db5ce67d5d0100590a520;p=dpdk.git diff --git a/drivers/vdpa/mlx5/mlx5_vdpa_event.c b/drivers/vdpa/mlx5/mlx5_vdpa_event.c index 17fd9dd4fc..bb6722839a 100644 --- a/drivers/vdpa/mlx5/mlx5_vdpa_event.c +++ b/drivers/vdpa/mlx5/mlx5_vdpa_event.c @@ -3,21 +3,30 @@ */ #include #include +#include #include +#include #include +#include #include #include #include #include #include +#include #include +#include +#include +#include #include "mlx5_vdpa_utils.h" #include "mlx5_vdpa.h" +#define MLX5_VDPA_ERROR_TIME_SEC 3u + void mlx5_vdpa_event_qp_global_release(struct mlx5_vdpa_priv *priv) { @@ -25,28 +34,21 @@ mlx5_vdpa_event_qp_global_release(struct mlx5_vdpa_priv *priv) mlx5_glue->devx_free_uar(priv->uar); priv->uar = NULL; } +#ifdef HAVE_IBV_DEVX_EVENT if (priv->eventc) { - mlx5_glue->devx_destroy_event_channel(priv->eventc); + mlx5_os_devx_destroy_event_channel(priv->eventc); priv->eventc = NULL; } - priv->eqn = 0; +#endif } /* Prepare all the global resources for all the event objects.*/ static int mlx5_vdpa_event_qp_global_prepare(struct mlx5_vdpa_priv *priv) { - uint32_t lcore; - if (priv->eventc) return 0; - lcore = (uint32_t)rte_lcore_to_cpu_id(-1); - if (mlx5_glue->devx_query_eqn(priv->ctx, lcore, &priv->eqn)) { - rte_errno = errno; - DRV_LOG(ERR, "Failed to query EQ number %d.", rte_errno); - return -1; - } - priv->eventc = mlx5_glue->devx_create_event_channel(priv->ctx, + priv->eventc = mlx5_os_devx_create_event_channel(priv->ctx, MLX5DV_DEVX_CREATE_EVENT_CHANNEL_FLAGS_OMIT_EV_DATA); if (!priv->eventc) { rte_errno = errno; @@ -54,7 +56,12 @@ mlx5_vdpa_event_qp_global_prepare(struct mlx5_vdpa_priv *priv) rte_errno); goto error; } - priv->uar = mlx5_glue->devx_alloc_uar(priv->ctx, 0); + /* + * This PMD always claims the write memory barrier on UAR + * registers writings, it is safe to allocate UAR with any + * memory mapping type. + */ + priv->uar = mlx5_devx_alloc_uar(priv->ctx, -1); if (!priv->uar) { rte_errno = errno; DRV_LOG(ERR, "Failed to allocate UAR."); @@ -69,27 +76,22 @@ error: static void mlx5_vdpa_cq_destroy(struct mlx5_vdpa_cq *cq) { - if (cq->cq) - claim_zero(mlx5_devx_cmd_destroy(cq->cq)); - if (cq->umem_obj) - claim_zero(mlx5_glue->devx_umem_dereg(cq->umem_obj)); - if (cq->umem_buf) - rte_free((void *)(uintptr_t)cq->umem_buf); + mlx5_devx_cq_destroy(&cq->cq_obj); memset(cq, 0, sizeof(*cq)); } -static inline void +static inline void __rte_unused mlx5_vdpa_cq_arm(struct mlx5_vdpa_priv *priv, struct mlx5_vdpa_cq *cq) { uint32_t arm_sn = cq->arm_sn << MLX5_CQ_SQN_OFFSET; uint32_t cq_ci = cq->cq_ci & MLX5_CI_MASK; uint32_t doorbell_hi = arm_sn | MLX5_CQ_DBR_CMD_ALL | cq_ci; - uint64_t doorbell = ((uint64_t)doorbell_hi << 32) | cq->cq->id; + uint64_t doorbell = ((uint64_t)doorbell_hi << 32) | cq->cq_obj.cq->id; uint64_t db_be = rte_cpu_to_be_64(doorbell); uint32_t *addr = RTE_PTR_ADD(priv->uar->base_addr, MLX5_CQ_DOORBELL); rte_io_wmb(); - cq->db_rec[MLX5_CQ_ARM_DB] = rte_cpu_to_be_32(doorbell_hi); + cq->cq_obj.db_rec[MLX5_CQ_ARM_DB] = rte_cpu_to_be_32(doorbell_hi); rte_wmb(); #ifdef RTE_ARCH_64 *(uint64_t *)addr = db_be; @@ -99,74 +101,41 @@ mlx5_vdpa_cq_arm(struct mlx5_vdpa_priv *priv, struct mlx5_vdpa_cq *cq) *((uint32_t *)addr + 1) = db_be >> 32; #endif cq->arm_sn++; + cq->armed = 1; } static int mlx5_vdpa_cq_create(struct mlx5_vdpa_priv *priv, uint16_t log_desc_n, int callfd, struct mlx5_vdpa_cq *cq) { - struct mlx5_devx_cq_attr attr; - size_t pgsize = sysconf(_SC_PAGESIZE); - uint32_t umem_size; - int ret; + struct mlx5_devx_cq_attr attr = { + .use_first_only = 1, + .uar_page_id = priv->uar->page_id, + }; uint16_t event_nums[1] = {0}; + int ret; - cq->log_desc_n = log_desc_n; - umem_size = sizeof(struct mlx5_cqe) * (1 << log_desc_n) + - sizeof(*cq->db_rec) * 2; - cq->umem_buf = rte_zmalloc(__func__, umem_size, 4096); - if (!cq->umem_buf) { - DRV_LOG(ERR, "Failed to allocate memory for CQ."); - rte_errno = ENOMEM; - return -ENOMEM; - } - cq->umem_obj = mlx5_glue->devx_umem_reg(priv->ctx, - (void *)(uintptr_t)cq->umem_buf, - umem_size, - IBV_ACCESS_LOCAL_WRITE); - if (!cq->umem_obj) { - DRV_LOG(ERR, "Failed to register umem for CQ."); - goto error; - } - attr.q_umem_valid = 1; - attr.db_umem_valid = 1; - attr.use_first_only = 0; - attr.overrun_ignore = 0; - attr.uar_page_id = priv->uar->page_id; - attr.q_umem_id = cq->umem_obj->umem_id; - attr.q_umem_offset = 0; - attr.db_umem_id = cq->umem_obj->umem_id; - attr.db_umem_offset = sizeof(struct mlx5_cqe) * (1 << log_desc_n); - attr.eqn = priv->eqn; - attr.log_cq_size = log_desc_n; - attr.log_page_size = rte_log2_u32(pgsize); - cq->cq = mlx5_devx_cmd_create_cq(priv->ctx, &attr); - if (!cq->cq) + ret = mlx5_devx_cq_create(priv->ctx, &cq->cq_obj, log_desc_n, &attr, + SOCKET_ID_ANY); + if (ret) goto error; - cq->db_rec = RTE_PTR_ADD(cq->umem_buf, (uintptr_t)attr.db_umem_offset); cq->cq_ci = 0; + cq->log_desc_n = log_desc_n; rte_spinlock_init(&cq->sl); /* Subscribe CQ event to the event channel controlled by the driver. */ - ret = mlx5_glue->devx_subscribe_devx_event(priv->eventc, cq->cq->obj, - sizeof(event_nums), - event_nums, - (uint64_t)(uintptr_t)cq); + ret = mlx5_os_devx_subscribe_devx_event(priv->eventc, + cq->cq_obj.cq->obj, + sizeof(event_nums), event_nums, + (uint64_t)(uintptr_t)cq); if (ret) { DRV_LOG(ERR, "Failed to subscribe CQE event."); rte_errno = errno; goto error; } - /* Subscribe CQ event to the guest FD only if it is not in poll mode. */ - if (callfd != -1) { - ret = mlx5_glue->devx_subscribe_devx_event_fd(priv->eventc, - callfd, - cq->cq->obj, 0); - if (ret) { - DRV_LOG(ERR, "Failed to subscribe CQE event fd."); - rte_errno = errno; - goto error; - } - } + cq->callfd = callfd; + /* Init CQ to ones to be in HW owner in the start. */ + cq->cq_obj.cqes[0].op_own = MLX5_CQE_OWNER_MASK; + cq->cq_obj.cqes[0].wqe_counter = rte_cpu_to_be_16(UINT16_MAX); /* First arming. */ mlx5_vdpa_cq_arm(priv, cq); return 0; @@ -175,121 +144,394 @@ error: return -1; } -static inline void __rte_unused -mlx5_vdpa_cq_poll(struct mlx5_vdpa_priv *priv __rte_unused, - struct mlx5_vdpa_cq *cq) +static inline uint32_t +mlx5_vdpa_cq_poll(struct mlx5_vdpa_cq *cq) { struct mlx5_vdpa_event_qp *eqp = container_of(cq, struct mlx5_vdpa_event_qp, cq); const unsigned int cq_size = 1 << cq->log_desc_n; - const unsigned int cq_mask = cq_size - 1; - int ret; - - do { - volatile struct mlx5_cqe *cqe = cq->cqes + (cq->cq_ci & - cq_mask); + union { + struct { + uint16_t wqe_counter; + uint8_t rsvd5; + uint8_t op_own; + }; + uint32_t word; + } last_word; + uint16_t next_wqe_counter = cq->cq_ci; + uint16_t cur_wqe_counter; + uint16_t comp; - ret = check_cqe(cqe, cq_size, cq->cq_ci); - switch (ret) { - case MLX5_CQE_STATUS_ERR: + last_word.word = rte_read32(&cq->cq_obj.cqes[0].wqe_counter); + cur_wqe_counter = rte_be_to_cpu_16(last_word.wqe_counter); + comp = cur_wqe_counter + (uint16_t)1 - next_wqe_counter; + if (comp) { + cq->cq_ci += comp; + MLX5_ASSERT(MLX5_CQE_OPCODE(last_word.op_own) != + MLX5_CQE_INVALID); + if (unlikely(!(MLX5_CQE_OPCODE(last_word.op_own) == + MLX5_CQE_RESP_ERR || + MLX5_CQE_OPCODE(last_word.op_own) == + MLX5_CQE_REQ_ERR))) cq->errors++; - /*fall-through*/ - case MLX5_CQE_STATUS_SW_OWN: - cq->cq_ci++; + rte_io_wmb(); + /* Ring CQ doorbell record. */ + cq->cq_obj.db_rec[0] = rte_cpu_to_be_32(cq->cq_ci); + rte_io_wmb(); + /* Ring SW QP doorbell record. */ + eqp->sw_qp.db_rec[0] = rte_cpu_to_be_32(cq->cq_ci + cq_size); + } + return comp; +} + +static void +mlx5_vdpa_arm_all_cqs(struct mlx5_vdpa_priv *priv) +{ + struct mlx5_vdpa_cq *cq; + int i; + + for (i = 0; i < priv->nr_virtqs; i++) { + cq = &priv->virtqs[i].eqp.cq; + if (cq->cq_obj.cq && !cq->armed) + mlx5_vdpa_cq_arm(priv, cq); + } +} + +static void +mlx5_vdpa_timer_sleep(struct mlx5_vdpa_priv *priv, uint32_t max) +{ + if (priv->event_mode == MLX5_VDPA_EVENT_MODE_DYNAMIC_TIMER) { + switch (max) { + case 0: + priv->timer_delay_us += priv->event_us; + break; + case 1: break; - case MLX5_CQE_STATUS_HW_OWN: default: + priv->timer_delay_us /= max; break; } - } while (ret != MLX5_CQE_STATUS_HW_OWN); - rte_io_wmb(); - /* Ring CQ doorbell record. */ - cq->db_rec[0] = rte_cpu_to_be_32(cq->cq_ci); - rte_io_wmb(); - /* Ring SW QP doorbell record. */ - eqp->db_rec[0] = rte_cpu_to_be_32(cq->cq_ci + cq_size); + } + if (priv->timer_delay_us) + usleep(priv->timer_delay_us); + else + /* Give-up CPU to improve polling threads scheduling. */ + sched_yield(); +} + +/* Notify virtio device for specific virtq new traffic. */ +static uint32_t +mlx5_vdpa_queue_complete(struct mlx5_vdpa_cq *cq) +{ + uint32_t comp = 0; + + if (cq->cq_obj.cq) { + comp = mlx5_vdpa_cq_poll(cq); + if (comp) { + if (cq->callfd != -1) + eventfd_write(cq->callfd, (eventfd_t)1); + cq->armed = 0; + } + } + return comp; +} + +/* Notify virtio device for any virtq new traffic. */ +static uint32_t +mlx5_vdpa_queues_complete(struct mlx5_vdpa_priv *priv) +{ + int i; + uint32_t max = 0; + + for (i = 0; i < priv->nr_virtqs; i++) { + struct mlx5_vdpa_cq *cq = &priv->virtqs[i].eqp.cq; + uint32_t comp = mlx5_vdpa_queue_complete(cq); + + if (comp > max) + max = comp; + } + return max; +} + +/* Wait on all CQs channel for completion event. */ +static struct mlx5_vdpa_cq * +mlx5_vdpa_event_wait(struct mlx5_vdpa_priv *priv __rte_unused) +{ +#ifdef HAVE_IBV_DEVX_EVENT + union { + struct mlx5dv_devx_async_event_hdr event_resp; + uint8_t buf[sizeof(struct mlx5dv_devx_async_event_hdr) + 128]; + } out; + int ret = mlx5_glue->devx_get_event(priv->eventc, &out.event_resp, + sizeof(out.buf)); + + if (ret >= 0) + return (struct mlx5_vdpa_cq *)(uintptr_t)out.event_resp.cookie; + DRV_LOG(INFO, "Got error in devx_get_event, ret = %d, errno = %d.", + ret, errno); +#endif + return NULL; +} + +static void * +mlx5_vdpa_event_handle(void *arg) +{ + struct mlx5_vdpa_priv *priv = arg; + struct mlx5_vdpa_cq *cq; + uint32_t max; + + switch (priv->event_mode) { + case MLX5_VDPA_EVENT_MODE_DYNAMIC_TIMER: + case MLX5_VDPA_EVENT_MODE_FIXED_TIMER: + priv->timer_delay_us = priv->event_us; + while (1) { + pthread_mutex_lock(&priv->vq_config_lock); + max = mlx5_vdpa_queues_complete(priv); + if (max == 0 && priv->no_traffic_counter++ >= + priv->no_traffic_max) { + DRV_LOG(DEBUG, "Device %s traffic was stopped.", + priv->vdev->device->name); + mlx5_vdpa_arm_all_cqs(priv); + do { + pthread_mutex_unlock + (&priv->vq_config_lock); + cq = mlx5_vdpa_event_wait(priv); + pthread_mutex_lock + (&priv->vq_config_lock); + if (cq == NULL || + mlx5_vdpa_queue_complete(cq) > 0) + break; + } while (1); + priv->timer_delay_us = priv->event_us; + priv->no_traffic_counter = 0; + } else if (max != 0) { + priv->no_traffic_counter = 0; + } + pthread_mutex_unlock(&priv->vq_config_lock); + mlx5_vdpa_timer_sleep(priv, max); + } + return NULL; + case MLX5_VDPA_EVENT_MODE_ONLY_INTERRUPT: + do { + cq = mlx5_vdpa_event_wait(priv); + if (cq != NULL) { + pthread_mutex_lock(&priv->vq_config_lock); + if (mlx5_vdpa_queue_complete(cq) > 0) + mlx5_vdpa_cq_arm(priv, cq); + pthread_mutex_unlock(&priv->vq_config_lock); + } + } while (1); + return NULL; + default: + return NULL; + } } static void -mlx5_vdpa_interrupt_handler(void *cb_arg) +mlx5_vdpa_err_interrupt_handler(void *cb_arg __rte_unused) { -#ifndef HAVE_IBV_DEVX_EVENT - (void)cb_arg; - return; -#else +#ifdef HAVE_IBV_DEVX_EVENT struct mlx5_vdpa_priv *priv = cb_arg; union { struct mlx5dv_devx_async_event_hdr event_resp; uint8_t buf[sizeof(struct mlx5dv_devx_async_event_hdr) + 128]; } out; + uint32_t vq_index, i, version; + struct mlx5_vdpa_virtq *virtq; + uint64_t sec; - while (mlx5_glue->devx_get_event(priv->eventc, &out.event_resp, + pthread_mutex_lock(&priv->vq_config_lock); + while (mlx5_glue->devx_get_event(priv->err_chnl, &out.event_resp, sizeof(out.buf)) >= (ssize_t)sizeof(out.event_resp.cookie)) { - struct mlx5_vdpa_cq *cq = (struct mlx5_vdpa_cq *) - (uintptr_t)out.event_resp.cookie; - rte_spinlock_lock(&cq->sl); - mlx5_vdpa_cq_poll(priv, cq); - mlx5_vdpa_cq_arm(priv, cq); - rte_spinlock_unlock(&cq->sl); - DRV_LOG(DEBUG, "CQ %d event: new cq_ci = %u.", cq->cq->id, - cq->cq_ci); + vq_index = out.event_resp.cookie & UINT32_MAX; + version = out.event_resp.cookie >> 32; + if (vq_index >= priv->nr_virtqs) { + DRV_LOG(ERR, "Invalid device %s error event virtq %d.", + priv->vdev->device->name, vq_index); + continue; + } + virtq = &priv->virtqs[vq_index]; + if (!virtq->enable || virtq->version != version) + continue; + if (rte_rdtsc() / rte_get_tsc_hz() < MLX5_VDPA_ERROR_TIME_SEC) + continue; + virtq->stopped = true; + /* Query error info. */ + if (mlx5_vdpa_virtq_query(priv, vq_index)) + goto log; + /* Disable vq. */ + if (mlx5_vdpa_virtq_enable(priv, vq_index, 0)) { + DRV_LOG(ERR, "Failed to disable virtq %d.", vq_index); + goto log; + } + /* Retry if error happens less than N times in 3 seconds. */ + sec = (rte_rdtsc() - virtq->err_time[0]) / rte_get_tsc_hz(); + if (sec > MLX5_VDPA_ERROR_TIME_SEC) { + /* Retry. */ + if (mlx5_vdpa_virtq_enable(priv, vq_index, 1)) + DRV_LOG(ERR, "Failed to enable virtq %d.", + vq_index); + else + DRV_LOG(WARNING, "Recover virtq %d: %u.", + vq_index, ++virtq->n_retry); + } else { + /* Retry timeout, give up. */ + DRV_LOG(ERR, "Device %s virtq %d failed to recover.", + priv->vdev->device->name, vq_index); + } +log: + /* Shift in current time to error time log end. */ + for (i = 1; i < RTE_DIM(virtq->err_time); i++) + virtq->err_time[i - 1] = virtq->err_time[i]; + virtq->err_time[RTE_DIM(virtq->err_time) - 1] = rte_rdtsc(); } -#endif /* HAVE_IBV_DEVX_ASYNC */ + pthread_mutex_unlock(&priv->vq_config_lock); +#endif } int -mlx5_vdpa_cqe_event_setup(struct mlx5_vdpa_priv *priv) +mlx5_vdpa_err_event_setup(struct mlx5_vdpa_priv *priv) { - int flags = fcntl(priv->eventc->fd, F_GETFL); - int ret = fcntl(priv->eventc->fd, F_SETFL, flags | O_NONBLOCK); - if (ret) { - DRV_LOG(ERR, "Failed to change event channel FD."); + int ret; + int flags; + + /* Setup device event channel. */ + priv->err_chnl = mlx5_glue->devx_create_event_channel(priv->ctx, 0); + if (!priv->err_chnl) { rte_errno = errno; - return -rte_errno; + DRV_LOG(ERR, "Failed to create device event channel %d.", + rte_errno); + goto error; + } + flags = fcntl(priv->err_chnl->fd, F_GETFL); + ret = fcntl(priv->err_chnl->fd, F_SETFL, flags | O_NONBLOCK); + if (ret) { + DRV_LOG(ERR, "Failed to change device event channel FD."); + goto error; } - priv->intr_handle.fd = priv->eventc->fd; - priv->intr_handle.type = RTE_INTR_HANDLE_EXT; - if (rte_intr_callback_register(&priv->intr_handle, - mlx5_vdpa_interrupt_handler, priv)) { - priv->intr_handle.fd = 0; - DRV_LOG(ERR, "Failed to register CQE interrupt %d.", rte_errno); - return -rte_errno; + priv->err_intr_handle.fd = priv->err_chnl->fd; + priv->err_intr_handle.type = RTE_INTR_HANDLE_EXT; + if (rte_intr_callback_register(&priv->err_intr_handle, + mlx5_vdpa_err_interrupt_handler, + priv)) { + priv->err_intr_handle.fd = 0; + DRV_LOG(ERR, "Failed to register error interrupt for device %d.", + priv->vid); + goto error; + } else { + DRV_LOG(DEBUG, "Registered error interrupt for device%d.", + priv->vid); } return 0; +error: + mlx5_vdpa_err_event_unset(priv); + return -1; } void -mlx5_vdpa_cqe_event_unset(struct mlx5_vdpa_priv *priv) +mlx5_vdpa_err_event_unset(struct mlx5_vdpa_priv *priv) { int retries = MLX5_VDPA_INTR_RETRIES; int ret = -EAGAIN; - if (priv->intr_handle.fd) { - while (retries-- && ret == -EAGAIN) { - ret = rte_intr_callback_unregister(&priv->intr_handle, - mlx5_vdpa_interrupt_handler, - priv); - if (ret == -EAGAIN) { - DRV_LOG(DEBUG, "Try again to unregister fd %d " - "of CQ interrupt, retries = %d.", - priv->intr_handle.fd, retries); - usleep(MLX5_VDPA_INTR_RETRIES_USEC); - } + if (!priv->err_intr_handle.fd) + return; + while (retries-- && ret == -EAGAIN) { + ret = rte_intr_callback_unregister(&priv->err_intr_handle, + mlx5_vdpa_err_interrupt_handler, + priv); + if (ret == -EAGAIN) { + DRV_LOG(DEBUG, "Try again to unregister fd %d " + "of error interrupt, retries = %d.", + priv->err_intr_handle.fd, retries); + rte_pause(); } - memset(&priv->intr_handle, 0, sizeof(priv->intr_handle)); } + memset(&priv->err_intr_handle, 0, sizeof(priv->err_intr_handle)); + if (priv->err_chnl) { +#ifdef HAVE_IBV_DEVX_EVENT + union { + struct mlx5dv_devx_async_event_hdr event_resp; + uint8_t buf[sizeof(struct mlx5dv_devx_async_event_hdr) + + 128]; + } out; + + /* Clean all pending events. */ + while (mlx5_glue->devx_get_event(priv->err_chnl, + &out.event_resp, sizeof(out.buf)) >= + (ssize_t)sizeof(out.event_resp.cookie)) + ; +#endif + mlx5_glue->devx_destroy_event_channel(priv->err_chnl); + priv->err_chnl = NULL; + } +} + +int +mlx5_vdpa_cqe_event_setup(struct mlx5_vdpa_priv *priv) +{ + int ret; + rte_cpuset_t cpuset; + pthread_attr_t attr; + char name[16]; + const struct sched_param sp = { + .sched_priority = sched_get_priority_max(SCHED_RR), + }; + + if (!priv->eventc) + /* All virtqs are in poll mode. */ + return 0; + pthread_attr_init(&attr); + ret = pthread_attr_setschedpolicy(&attr, SCHED_RR); + if (ret) { + DRV_LOG(ERR, "Failed to set thread sched policy = RR."); + return -1; + } + ret = pthread_attr_setschedparam(&attr, &sp); + if (ret) { + DRV_LOG(ERR, "Failed to set thread priority."); + return -1; + } + ret = pthread_create(&priv->timer_tid, &attr, mlx5_vdpa_event_handle, + (void *)priv); + if (ret) { + DRV_LOG(ERR, "Failed to create timer thread."); + return -1; + } + CPU_ZERO(&cpuset); + if (priv->event_core != -1) + CPU_SET(priv->event_core, &cpuset); + else + cpuset = rte_lcore_cpuset(rte_get_main_lcore()); + ret = pthread_setaffinity_np(priv->timer_tid, sizeof(cpuset), &cpuset); + if (ret) { + DRV_LOG(ERR, "Failed to set thread affinity."); + return -1; + } + snprintf(name, sizeof(name), "vDPA-mlx5-%d", priv->vid); + ret = rte_thread_setname(priv->timer_tid, name); + if (ret) + DRV_LOG(DEBUG, "Cannot set timer thread name."); + return 0; +} + +void +mlx5_vdpa_cqe_event_unset(struct mlx5_vdpa_priv *priv) +{ + void *status; + + if (priv->timer_tid) { + pthread_cancel(priv->timer_tid); + pthread_join(priv->timer_tid, &status); + } + priv->timer_tid = 0; } void mlx5_vdpa_event_qp_destroy(struct mlx5_vdpa_event_qp *eqp) { - if (eqp->sw_qp) - claim_zero(mlx5_devx_cmd_destroy(eqp->sw_qp)); - if (eqp->umem_obj) - claim_zero(mlx5_glue->devx_umem_dereg(eqp->umem_obj)); - if (eqp->umem_buf) - rte_free(eqp->umem_buf); + mlx5_devx_qp_destroy(&eqp->sw_qp); if (eqp->fw_qp) claim_zero(mlx5_devx_cmd_destroy(eqp->fw_qp)); mlx5_vdpa_cq_destroy(&eqp->cq); @@ -300,36 +542,36 @@ static int mlx5_vdpa_qps2rts(struct mlx5_vdpa_event_qp *eqp) { if (mlx5_devx_cmd_modify_qp_state(eqp->fw_qp, MLX5_CMD_OP_RST2INIT_QP, - eqp->sw_qp->id)) { + eqp->sw_qp.qp->id)) { DRV_LOG(ERR, "Failed to modify FW QP to INIT state(%u).", rte_errno); return -1; } - if (mlx5_devx_cmd_modify_qp_state(eqp->sw_qp, MLX5_CMD_OP_RST2INIT_QP, - eqp->fw_qp->id)) { + if (mlx5_devx_cmd_modify_qp_state(eqp->sw_qp.qp, + MLX5_CMD_OP_RST2INIT_QP, eqp->fw_qp->id)) { DRV_LOG(ERR, "Failed to modify SW QP to INIT state(%u).", rte_errno); return -1; } if (mlx5_devx_cmd_modify_qp_state(eqp->fw_qp, MLX5_CMD_OP_INIT2RTR_QP, - eqp->sw_qp->id)) { + eqp->sw_qp.qp->id)) { DRV_LOG(ERR, "Failed to modify FW QP to RTR state(%u).", rte_errno); return -1; } - if (mlx5_devx_cmd_modify_qp_state(eqp->sw_qp, MLX5_CMD_OP_INIT2RTR_QP, - eqp->fw_qp->id)) { + if (mlx5_devx_cmd_modify_qp_state(eqp->sw_qp.qp, + MLX5_CMD_OP_INIT2RTR_QP, eqp->fw_qp->id)) { DRV_LOG(ERR, "Failed to modify SW QP to RTR state(%u).", rte_errno); return -1; } if (mlx5_devx_cmd_modify_qp_state(eqp->fw_qp, MLX5_CMD_OP_RTR2RTS_QP, - eqp->sw_qp->id)) { + eqp->sw_qp.qp->id)) { DRV_LOG(ERR, "Failed to modify FW QP to RTS state(%u).", rte_errno); return -1; } - if (mlx5_devx_cmd_modify_qp_state(eqp->sw_qp, MLX5_CMD_OP_RTR2RTS_QP, + if (mlx5_devx_cmd_modify_qp_state(eqp->sw_qp.qp, MLX5_CMD_OP_RTR2RTS_QP, eqp->fw_qp->id)) { DRV_LOG(ERR, "Failed to modify SW QP to RTS state(%u).", rte_errno); @@ -344,54 +586,36 @@ mlx5_vdpa_event_qp_create(struct mlx5_vdpa_priv *priv, uint16_t desc_n, { struct mlx5_devx_qp_attr attr = {0}; uint16_t log_desc_n = rte_log2_u32(desc_n); - uint32_t umem_size = (1 << log_desc_n) * MLX5_WSEG_SIZE + - sizeof(*eqp->db_rec) * 2; + uint32_t ret; if (mlx5_vdpa_event_qp_global_prepare(priv)) return -1; if (mlx5_vdpa_cq_create(priv, log_desc_n, callfd, &eqp->cq)) return -1; attr.pd = priv->pdn; + attr.ts_format = mlx5_ts_format_conv(priv->qp_ts_format); eqp->fw_qp = mlx5_devx_cmd_create_qp(priv->ctx, &attr); if (!eqp->fw_qp) { DRV_LOG(ERR, "Failed to create FW QP(%u).", rte_errno); goto error; } - eqp->umem_buf = rte_zmalloc(__func__, umem_size, 4096); - if (!eqp->umem_buf) { - DRV_LOG(ERR, "Failed to allocate memory for SW QP."); - rte_errno = ENOMEM; - goto error; - } - eqp->umem_obj = mlx5_glue->devx_umem_reg(priv->ctx, - (void *)(uintptr_t)eqp->umem_buf, - umem_size, - IBV_ACCESS_LOCAL_WRITE); - if (!eqp->umem_obj) { - DRV_LOG(ERR, "Failed to register umem for SW QP."); - goto error; - } attr.uar_index = priv->uar->page_id; - attr.cqn = eqp->cq.cq->id; - attr.log_page_size = rte_log2_u32(sysconf(_SC_PAGESIZE)); - attr.rq_size = 1 << log_desc_n; + attr.cqn = eqp->cq.cq_obj.cq->id; + attr.rq_size = RTE_BIT32(log_desc_n); attr.log_rq_stride = rte_log2_u32(MLX5_WSEG_SIZE); attr.sq_size = 0; /* No need SQ. */ - attr.dbr_umem_valid = 1; - attr.wq_umem_id = eqp->umem_obj->umem_id; - attr.wq_umem_offset = 0; - attr.dbr_umem_id = eqp->umem_obj->umem_id; - attr.dbr_address = (1 << log_desc_n) * MLX5_WSEG_SIZE; - eqp->sw_qp = mlx5_devx_cmd_create_qp(priv->ctx, &attr); - if (!eqp->sw_qp) { + attr.ts_format = mlx5_ts_format_conv(priv->qp_ts_format); + ret = mlx5_devx_qp_create(priv->ctx, &(eqp->sw_qp), log_desc_n, &attr, + SOCKET_ID_ANY); + if (ret) { DRV_LOG(ERR, "Failed to create SW QP(%u).", rte_errno); goto error; } - eqp->db_rec = RTE_PTR_ADD(eqp->umem_buf, (uintptr_t)attr.dbr_address); if (mlx5_vdpa_qps2rts(eqp)) goto error; /* First ringing. */ - rte_write32(rte_cpu_to_be_32(1 << log_desc_n), &eqp->db_rec[0]); + rte_write32(rte_cpu_to_be_32(RTE_BIT32(log_desc_n)), + &eqp->sw_qp.db_rec[0]); return 0; error: mlx5_vdpa_event_qp_destroy(eqp);