diff options
author | Vladimir Sokolovsky <vlad@dev.mellanox.co.il> | 2008-03-31 11:51:18 +0300 |
---|---|---|
committer | Roland Dreier <rolandd@cisco.com> | 2008-04-23 11:30:47 -0700 |
commit | cb026cc2b080322a51f23fe06a661c1f31afde0d (patch) | |
tree | dcaff5a9902ce40a93b2fe120877806e19e62bc0 | |
parent | 5936553a34198878d9c898b1563315c92a72d83b (diff) | |
download | libmlx4-cb026cc2b080322a51f23fe06a661c1f31afde0d.tar.gz |
Implement resize CQ
Signed-off-by: Vladimir Sokolovsky <vlad@mellanox.co.il>
Signed-off-by: Roland Dreier <rolandd@cisco.com>
-rw-r--r-- | src/cq.c | 34 | ||||
-rw-r--r-- | src/mlx4.h | 3 | ||||
-rw-r--r-- | src/verbs.c | 60 |
3 files changed, 91 insertions, 6 deletions
@@ -436,6 +436,40 @@ void mlx4_cq_clean(struct mlx4_cq *cq, uint32_t qpn, struct mlx4_srq *srq) pthread_spin_unlock(&cq->lock); } +int mlx4_get_outstanding_cqes(struct mlx4_cq *cq) +{ + uint32_t i; + + for (i = cq->cons_index; get_sw_cqe(cq, (i & cq->ibv_cq.cqe)); ++i) + ; + + return i - cq->cons_index; +} + void mlx4_cq_resize_copy_cqes(struct mlx4_cq *cq, void *buf, int old_cqe) { + struct mlx4_cqe *cqe; + int i; + + i = cq->cons_index; + cqe = get_cqe(cq, (i & old_cqe)); + + while ((cqe->owner_sr_opcode & MLX4_CQE_OPCODE_MASK) != MLX4_CQE_OPCODE_RESIZE) { + memcpy(buf + ((i + 1) & cq->ibv_cq.cqe) * MLX4_CQ_ENTRY_SIZE, + cqe, MLX4_CQ_ENTRY_SIZE); + ++i; + cqe = get_cqe(cq, (i & old_cqe)); + } + + ++cq->cons_index; +} + +int mlx4_alloc_cq_buf(struct mlx4_device *dev, struct mlx4_buf *buf, int nent) +{ + if (mlx4_alloc_buf(buf, align(nent * MLX4_CQ_ENTRY_SIZE, dev->page_size), + dev->page_size)) + return -1; + memset(buf->buf, 0, nent * MLX4_CQ_ENTRY_SIZE); + + return 0; } @@ -174,6 +174,7 @@ struct mlx4_pd { struct mlx4_cq { struct ibv_cq ibv_cq; struct mlx4_buf buf; + struct mlx4_buf resize_buf; pthread_spinlock_t lock; uint32_t cqn; uint32_t cons_index; @@ -307,6 +308,7 @@ int mlx4_dereg_mr(struct ibv_mr *mr); struct ibv_cq *mlx4_create_cq(struct ibv_context *context, int cqe, struct ibv_comp_channel *channel, int comp_vector); +int mlx4_alloc_cq_buf(struct mlx4_device *dev, struct mlx4_buf *buf, int nent); int mlx4_resize_cq(struct ibv_cq *cq, int cqe); int mlx4_destroy_cq(struct ibv_cq *cq); int mlx4_poll_cq(struct ibv_cq *cq, int ne, struct ibv_wc *wc); @@ -314,6 +316,7 @@ int mlx4_arm_cq(struct ibv_cq *cq, int solicited); void mlx4_cq_event(struct ibv_cq *cq); void __mlx4_cq_clean(struct mlx4_cq *cq, uint32_t qpn, struct mlx4_srq *srq); void mlx4_cq_clean(struct mlx4_cq *cq, uint32_t qpn, struct mlx4_srq *srq); +int mlx4_get_outstanding_cqes(struct mlx4_cq *cq); void mlx4_cq_resize_copy_cqes(struct mlx4_cq *cq, void *buf, int new_cqe); struct ibv_srq *mlx4_create_srq(struct ibv_pd *pd, diff --git a/src/verbs.c b/src/verbs.c index 26174f8..3935ed5 100644 --- a/src/verbs.c +++ b/src/verbs.c @@ -184,12 +184,9 @@ struct ibv_cq *mlx4_create_cq(struct ibv_context *context, int cqe, cqe = align_queue_size(cqe + 1); - if (mlx4_alloc_buf(&cq->buf, cqe * MLX4_CQ_ENTRY_SIZE, - to_mdev(context->device)->page_size)) + if (mlx4_alloc_cq_buf(to_mdev(context->device), &cq->buf, cqe)) goto err; - memset(cq->buf.buf, 0, cqe * MLX4_CQ_ENTRY_SIZE); - cq->set_ci_db = mlx4_alloc_db(to_mctx(context), MLX4_DB_TYPE_CQ); if (!cq->set_ci_db) goto err_buf; @@ -226,8 +223,59 @@ err: int mlx4_resize_cq(struct ibv_cq *ibcq, int cqe) { - /* XXX resize CQ not implemented */ - return ENOSYS; + struct mlx4_cq *cq = to_mcq(ibcq); + struct mlx4_resize_cq cmd; + struct mlx4_buf buf; + int old_cqe, outst_cqe, ret; + + /* Sanity check CQ size before proceeding */ + if (cqe > 0x3fffff) + return EINVAL; + + pthread_spin_lock(&cq->lock); + + cqe = align_queue_size(cqe + 1); + if (cqe == ibcq->cqe + 1) { + ret = 0; + goto out; + } + + /* Can't be smaller then the number of outstanding CQEs */ + outst_cqe = mlx4_get_outstanding_cqes(cq); + if (cqe < outst_cqe + 1) { + ret = 0; + goto out; + } + + ret = mlx4_alloc_cq_buf(to_mdev(ibcq->context->device), &buf, cqe); + if (ret) + goto out; + + old_cqe = ibcq->cqe; + cmd.buf_addr = (uintptr_t) buf.buf; + +#ifdef IBV_CMD_RESIZE_CQ_HAS_RESP_PARAMS + { + struct ibv_resize_cq_resp resp; + ret = ibv_cmd_resize_cq(ibcq, cqe - 1, &cmd.ibv_cmd, sizeof cmd, + &resp, sizeof resp); + } +#else + ret = ibv_cmd_resize_cq(ibcq, cqe - 1, &cmd.ibv_cmd, sizeof cmd); +#endif + if (ret) { + mlx4_free_buf(&buf); + goto out; + } + + mlx4_cq_resize_copy_cqes(cq, buf.buf, old_cqe); + + mlx4_free_buf(&cq->buf); + cq->buf = buf; + +out: + pthread_spin_unlock(&cq->lock); + return ret; } int mlx4_destroy_cq(struct ibv_cq *cq) |