aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorVladimir Sokolovsky <vlad@dev.mellanox.co.il>2008-03-31 11:51:18 +0300
committerRoland Dreier <rolandd@cisco.com>2008-04-23 11:30:47 -0700
commitcb026cc2b080322a51f23fe06a661c1f31afde0d (patch)
treedcaff5a9902ce40a93b2fe120877806e19e62bc0
parent5936553a34198878d9c898b1563315c92a72d83b (diff)
downloadlibmlx4-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.c34
-rw-r--r--src/mlx4.h3
-rw-r--r--src/verbs.c60
3 files changed, 91 insertions, 6 deletions
diff --git a/src/cq.c b/src/cq.c
index 53c6e06..68e16e9 100644
--- a/src/cq.c
+++ b/src/cq.c
@@ -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;
}
diff --git a/src/mlx4.h b/src/mlx4.h
index dda34ba..827a201 100644
--- a/src/mlx4.h
+++ b/src/mlx4.h
@@ -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)