X-Git-Url: http://git.droids-corp.org/?a=blobdiff_plain;f=drivers%2Fvdpa%2Fmlx5%2Fmlx5_vdpa_event.c;h=0414c9129ab6ffe5a4498fae83934fe56464e4ff;hb=ca4cc612d7b0faf1b93db57e303d8ca351c97f90;hp=743e52a6d5cebeab2b86f69fe57e543d6a58fa5e;hpb=a9dd7275a14962beb32e223910678512eed16022;p=dpdk.git diff --git a/drivers/vdpa/mlx5/mlx5_vdpa_event.c b/drivers/vdpa/mlx5/mlx5_vdpa_event.c index 743e52a6d5..0414c9129a 100644 --- a/drivers/vdpa/mlx5/mlx5_vdpa_event.c +++ b/drivers/vdpa/mlx5/mlx5_vdpa_event.c @@ -20,9 +20,6 @@ #include "mlx5_vdpa.h" -#define MLX5_VDPA_DEFAULT_TIMER_DELAY_US 500u -#define MLX5_VDPA_NO_TRAFFIC_TIME_S 2LLU - void mlx5_vdpa_event_qp_global_release(struct mlx5_vdpa_priv *priv) { @@ -127,12 +124,12 @@ mlx5_vdpa_cq_create(struct mlx5_vdpa_priv *priv, uint16_t log_desc_n, struct mlx5_devx_cq_attr attr; size_t pgsize = sysconf(_SC_PAGESIZE); uint32_t umem_size; - int ret; uint16_t event_nums[1] = {0}; + uint16_t cq_size = 1 << log_desc_n; + int ret; cq->log_desc_n = log_desc_n; - umem_size = sizeof(struct mlx5_cqe) * (1 << log_desc_n) + - sizeof(*cq->db_rec) * 2; + umem_size = sizeof(struct mlx5_cqe) * cq_size + 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."); @@ -149,13 +146,13 @@ mlx5_vdpa_cq_create(struct mlx5_vdpa_priv *priv, uint16_t log_desc_n, } attr.q_umem_valid = 1; attr.db_umem_valid = 1; - attr.use_first_only = 0; + attr.use_first_only = 1; 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.db_umem_offset = sizeof(struct mlx5_cqe) * cq_size; attr.eqn = priv->eqn; attr.log_cq_size = log_desc_n; attr.log_page_size = rte_log2_u32(pgsize); @@ -175,19 +172,10 @@ mlx5_vdpa_cq_create(struct mlx5_vdpa_priv *priv, uint16_t log_desc_n, rte_errno = errno; goto error; } - 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. */ - memset((void *)(uintptr_t)cq->umem_buf, 0xFF, attr.db_umem_offset); + cq->cqes[0].op_own = MLX5_CQE_OWNER_MASK; + cq->cqes[0].wqe_counter = rte_cpu_to_be_16(cq_size - 1); /* First arming. */ mlx5_vdpa_cq_arm(priv, cq); return 0; @@ -203,34 +191,40 @@ mlx5_vdpa_cq_poll(struct mlx5_vdpa_cq *cq) 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; - uint32_t total = 0; - int ret; - - do { - volatile struct mlx5_cqe *cqe = cq->cqes + ((cq->cq_ci + total) - & cq_mask); - - ret = check_cqe(cqe, cq_size, cq->cq_ci + total); - switch (ret) { - case MLX5_CQE_STATUS_ERR: + 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 & cq_mask; + uint16_t cur_wqe_counter; + uint16_t comp; + + last_word.word = rte_read32(&cq->cqes[0].wqe_counter); + cur_wqe_counter = rte_be_to_cpu_16(last_word.wqe_counter); + comp = (cur_wqe_counter + 1u - next_wqe_counter) & cq_mask; + if (comp) { + cq->cq_ci += comp; + MLX5_ASSERT(!!(cq->cq_ci & cq_size) == + MLX5_CQE_OWNER(last_word.op_own)); + 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: - total++; - break; - case MLX5_CQE_STATUS_HW_OWN: - default: - break; - } - } while (ret != MLX5_CQE_STATUS_HW_OWN); - rte_io_wmb(); - cq->cq_ci += total; - /* 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); - return total; + 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); + } + return comp; } static void @@ -246,21 +240,43 @@ mlx5_vdpa_arm_all_cqs(struct mlx5_vdpa_priv *priv) } } +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; + default: + priv->timer_delay_us /= max; + break; + } + } + usleep(priv->timer_delay_us); +} + static void * mlx5_vdpa_poll_handle(void *arg) { struct mlx5_vdpa_priv *priv = arg; int i; struct mlx5_vdpa_cq *cq; - uint32_t total; + uint32_t max; uint64_t current_tic; pthread_mutex_lock(&priv->timer_lock); while (!priv->timer_on) pthread_cond_wait(&priv->timer_cond, &priv->timer_lock); pthread_mutex_unlock(&priv->timer_lock); + priv->timer_delay_us = priv->event_mode == + MLX5_VDPA_EVENT_MODE_DYNAMIC_TIMER ? + MLX5_VDPA_DEFAULT_TIMER_DELAY_US : + priv->event_us; while (1) { - total = 0; + max = 0; for (i = 0; i < priv->nr_virtqs; i++) { cq = &priv->virtqs[i].eqp.cq; if (cq->cq && !cq->armed) { @@ -271,15 +287,16 @@ mlx5_vdpa_poll_handle(void *arg) if (cq->callfd != -1) eventfd_write(cq->callfd, (eventfd_t)1); - total += comp; + if (comp > max) + max = comp; } } } current_tic = rte_rdtsc(); - if (!total) { + if (!max) { /* No traffic ? stop timer and load interrupts. */ if (current_tic - priv->last_traffic_tic >= - rte_get_timer_hz() * MLX5_VDPA_NO_TRAFFIC_TIME_S) { + rte_get_timer_hz() * priv->no_traffic_time_s) { DRV_LOG(DEBUG, "Device %s traffic was stopped.", priv->vdev->device->name); mlx5_vdpa_arm_all_cqs(priv); @@ -289,12 +306,16 @@ mlx5_vdpa_poll_handle(void *arg) pthread_cond_wait(&priv->timer_cond, &priv->timer_lock); pthread_mutex_unlock(&priv->timer_lock); + priv->timer_delay_us = priv->event_mode == + MLX5_VDPA_EVENT_MODE_DYNAMIC_TIMER ? + MLX5_VDPA_DEFAULT_TIMER_DELAY_US : + priv->event_us; continue; } } else { priv->last_traffic_tic = current_tic; } - usleep(priv->timer_delay_us); + mlx5_vdpa_timer_sleep(priv, max); } return NULL; } @@ -320,6 +341,13 @@ mlx5_vdpa_interrupt_handler(void *cb_arg) struct mlx5_vdpa_virtq, eqp); mlx5_vdpa_cq_poll(cq); + /* Notify guest for descs consuming. */ + if (cq->callfd != -1) + eventfd_write(cq->callfd, (eventfd_t)1); + if (priv->event_mode == MLX5_VDPA_EVENT_MODE_ONLY_INTERRUPT) { + mlx5_vdpa_cq_arm(priv, cq); + return; + } /* Don't arm again - timer will take control. */ DRV_LOG(DEBUG, "Device %s virtq %d cq %d event was captured." " Timer is %s, cq ci is %u.\n", @@ -349,15 +377,16 @@ mlx5_vdpa_cqe_event_setup(struct mlx5_vdpa_priv *priv) if (!priv->eventc) /* All virtqs are in poll mode. */ return 0; - pthread_mutex_init(&priv->timer_lock, NULL); - pthread_cond_init(&priv->timer_cond, NULL); - priv->timer_on = 0; - priv->timer_delay_us = MLX5_VDPA_DEFAULT_TIMER_DELAY_US; - ret = pthread_create(&priv->timer_tid, NULL, mlx5_vdpa_poll_handle, - (void *)priv); - if (ret) { - DRV_LOG(ERR, "Failed to create timer thread."); - return -1; + if (priv->event_mode != MLX5_VDPA_EVENT_MODE_ONLY_INTERRUPT) { + pthread_mutex_init(&priv->timer_lock, NULL); + pthread_cond_init(&priv->timer_cond, NULL); + priv->timer_on = 0; + ret = pthread_create(&priv->timer_tid, NULL, + mlx5_vdpa_poll_handle, (void *)priv); + if (ret) { + DRV_LOG(ERR, "Failed to create timer thread."); + return -1; + } } flags = fcntl(priv->eventc->fd, F_GETFL); ret = fcntl(priv->eventc->fd, F_SETFL, flags | O_NONBLOCK);