[PATCH rdma-core] libqedr: fix queue wrapping logic

[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]

 



The pointer to a CQ, SQ or RQ may wrap before reaching the end of the
queue for certain queue depths. This is fixed by using a wrapping logic
based on a pointer rather than an index.

Signed-off-by: Ram Amrani <Ram.Amrani@xxxxxxxxxx>
Reviewed-by: Elior, Ariel <Ariel.Elior@xxxxxxxxxx>
---
 providers/qedr/qelr_chain.c | 24 +++++++++++++-----------
 providers/qedr/qelr_chain.h | 22 ++++++++++++----------
 providers/qedr/qelr_verbs.c | 10 +++++-----
 3 files changed, 30 insertions(+), 26 deletions(-)

diff --git a/providers/qedr/qelr_chain.c b/providers/qedr/qelr_chain.c
index 6101f74..edc72f4 100644
--- a/providers/qedr/qelr_chain.c
+++ b/providers/qedr/qelr_chain.c
@@ -44,11 +44,11 @@ void *qelr_chain_get_last_elem(struct qelr_chain *p_chain)
 	void			*p_virt_addr	= NULL;
 	uint32_t		size;
 
-	if (!p_chain->addr)
+	if (!p_chain->first_addr)
 		goto out;
 
 	size		= p_chain->elem_size * (p_chain->n_elems - 1);
-	p_virt_addr	= ((uint8_t *)p_chain->addr + size);
+	p_virt_addr	= ((uint8_t *)p_chain->first_addr + size);
 out:
 	return p_virt_addr;
 }
@@ -58,8 +58,8 @@ void qelr_chain_reset(struct qelr_chain *p_chain)
 	p_chain->prod_idx	= 0;
 	p_chain->cons_idx	= 0;
 
-	p_chain->p_cons_elem	= p_chain->addr;
-	p_chain->p_prod_elem	= p_chain->addr;
+	p_chain->p_cons_elem	= p_chain->first_addr;
+	p_chain->p_prod_elem	= p_chain->first_addr;
 }
 
 #define QELR_ANON_FD		(-1)	/* MAP_ANONYMOUS => file desc.= -1  */
@@ -76,7 +76,7 @@ int qelr_chain_alloc(struct qelr_chain *chain, int chain_size, int page_size,
 	addr = mmap(NULL, a_chain_size, PROT_READ | PROT_WRITE,
 			 MAP_PRIVATE | MAP_ANONYMOUS, QELR_ANON_FD,
 			 QELR_ANON_OFFSET);
-	if (chain->addr == MAP_FAILED)
+	if (chain->first_addr == MAP_FAILED)
 		return errno;
 
 	ret = ibv_dontfork_range(addr, a_chain_size);
@@ -87,13 +87,15 @@ int qelr_chain_alloc(struct qelr_chain *chain, int chain_size, int page_size,
 
 	/* init chain */
 	memset(chain, 0, sizeof(*chain));
-	memset(chain->addr, 0, chain->size);
-	chain->addr = addr;
+	memset(chain->first_addr, 0, chain->size);
+	chain->first_addr = addr;
 	chain->size = a_chain_size;
-	chain->p_cons_elem = chain->addr;
-	chain->p_prod_elem = chain->addr;
+	chain->p_cons_elem = chain->first_addr;
+	chain->p_prod_elem = chain->first_addr;
 	chain->elem_size = elem_size;
 	chain->n_elems = chain->size / elem_size;
+	chain->last_addr = (void *)
+			((uint8_t *)addr + (elem_size * (chain->n_elems -1)));
 
 	return 0;
 }
@@ -101,7 +103,7 @@ int qelr_chain_alloc(struct qelr_chain *chain, int chain_size, int page_size,
 void qelr_chain_free(struct qelr_chain *chain)
 {
 	if (chain->size) {
-		ibv_dofork_range(chain->addr, chain->size);
-		munmap(chain->addr, chain->size);
+		ibv_dofork_range(chain->first_addr, chain->size);
+		munmap(chain->first_addr, chain->size);
 	}
 }
diff --git a/providers/qedr/qelr_chain.h b/providers/qedr/qelr_chain.h
index 2ff5bf5..12a30df 100644
--- a/providers/qedr/qelr_chain.h
+++ b/providers/qedr/qelr_chain.h
@@ -34,8 +34,8 @@
 #define __QELR_CHAIN_H__
 
 struct qelr_chain {
-	/* Address of first page of the chain */
-	void		*addr;
+	void		*first_addr;	/* Address of first element in chain */
+	void		*last_addr;	/* Address of last element in chain */
 
 	/* Point to next element to produce/consume */
 	void		*p_prod_elem;
@@ -64,8 +64,8 @@ static inline void *qelr_chain_produce(struct qelr_chain *p_chain)
 
 	p_ret = p_chain->p_prod_elem;
 
-	if (p_chain->prod_idx % p_chain->n_elems == 0)
-		p_chain->p_prod_elem = p_chain->addr;
+	if (p_chain->p_prod_elem == p_chain->last_addr)
+		p_chain->p_prod_elem = p_chain->first_addr;
 	else
 		p_chain->p_prod_elem = (void *)(((uint8_t *)p_chain->p_prod_elem) +
 				       p_chain->elem_size);
@@ -83,8 +83,9 @@ static inline void *qelr_chain_produce_n(struct qelr_chain *p_chain, int n)
 
 	n_wrap = p_chain->prod_idx % p_chain->n_elems;
 	if (n_wrap < n)
-		p_chain->p_prod_elem = (void *)(((uint8_t *)p_chain->addr) +
-				       (p_chain->elem_size * n_wrap));
+		p_chain->p_prod_elem = (void *)
+				       (((uint8_t *)p_chain->first_addr) +
+					(p_chain->elem_size * n_wrap));
 	else
 		p_chain->p_prod_elem = (void *)(((uint8_t *)p_chain->p_prod_elem) +
 				       (p_chain->elem_size * n));
@@ -100,8 +101,8 @@ static inline void *qelr_chain_consume(struct qelr_chain *p_chain)
 
 	p_ret = p_chain->p_cons_elem;
 
-	if (p_chain->cons_idx % p_chain->n_elems == 0)
-		p_chain->p_cons_elem = p_chain->addr;
+	if (p_chain->p_cons_elem == p_chain->last_addr)
+		p_chain->p_cons_elem = p_chain->first_addr;
 	else
 		p_chain->p_cons_elem	= (void *)
 					  (((uint8_t *)p_chain->p_cons_elem) +
@@ -120,8 +121,9 @@ static inline void *qelr_chain_consume_n(struct qelr_chain *p_chain, int n)
 
 	n_wrap = p_chain->cons_idx % p_chain->n_elems;
 	if (n_wrap < n)
-		p_chain->p_cons_elem = (void *)(((uint8_t *)p_chain->addr) +
-				       (p_chain->elem_size * n_wrap));
+		p_chain->p_cons_elem = (void *)
+				       (((uint8_t *)p_chain->first_addr) +
+					(p_chain->elem_size * n_wrap));
 	else
 		p_chain->p_cons_elem = (void *)(((uint8_t *)p_chain->p_cons_elem) +
 				       (p_chain->elem_size * n));
diff --git a/providers/qedr/qelr_verbs.c b/providers/qedr/qelr_verbs.c
index 415efc0..793b1f4 100644
--- a/providers/qedr/qelr_verbs.c
+++ b/providers/qedr/qelr_verbs.c
@@ -248,7 +248,7 @@ struct ibv_cq *qelr_create_cq(struct ibv_context *context, int cqe,
 	if (rc)
 		goto err_0;
 
-	cmd.addr = (uintptr_t) cq->chain.addr;
+	cmd.addr = (uintptr_t) cq->chain.first_addr;
 	cmd.len = cq->chain.size;
 	rc = ibv_cmd_create_cq(context, cqe, channel, comp_vector,
 			       &cq->ibv_cq, &cmd.ibv_cmd, sizeof(cmd),
@@ -485,7 +485,7 @@ static inline void
 qelr_create_qp_configure_sq_req(struct qelr_qp *qp,
 				struct qelr_create_qp_req *req)
 {
-	req->sq_addr = (uintptr_t)qp->sq.chain.addr;
+	req->sq_addr = (uintptr_t)qp->sq.chain.first_addr;
 	req->sq_len = qp->sq.chain.size;
 }
 
@@ -493,7 +493,7 @@ static inline void
 qelr_create_qp_configure_rq_req(struct qelr_qp *qp,
 				struct qelr_create_qp_req *req)
 {
-	req->rq_addr = (uintptr_t)qp->rq.chain.addr;
+	req->rq_addr = (uintptr_t)qp->rq.chain.first_addr;
 	req->rq_len = qp->rq.chain.size;
 }
 
@@ -1443,8 +1443,8 @@ int qelr_post_recv(struct ibv_qp *ibqp, struct ibv_recv_wr *wr,
 				   wr->sg_list[i].length, flags);
 			FP_DP_VERBOSE(cxt->dbg_fp, QELR_MSG_CQ,
 				      "[%d]: len %d key %x addr %x:%x\n", i,
-				      rqe->length, rqe->flags, rqe->addr.hi,
-				      rqe->addr.lo);
+				      rqe->length, rqe->flags,
+				      rqe->first_addr.hi, rqe->first_addr.lo);
 		}
 		/* Special case of no sges. FW requires between 1-4 sges...
 		 * in this case we need to post 1 sge with length zero. this is
-- 
1.8.3.1

--
To unsubscribe from this list: send the line "unsubscribe linux-rdma" in
the body of a message to majordomo@xxxxxxxxxxxxxxx
More majordomo info at  http://vger.kernel.org/majordomo-info.html



[Index of Archives]     [Linux USB Devel]     [Video for Linux]     [Linux Audio Users]     [Photo]     [Yosemite News]     [Yosemite Photos]     [Linux Kernel]     [Linux SCSI]     [XFree86]
  Powered by Linux