Commit 043e9dee authored by Selvin Xavier's avatar Selvin Xavier Committed by Roland Dreier

RDMA/ocrdma: Allow expansion of the SQ CQEs via buddy CQ expansion of the QP

If the SQ and RQ of the QP in error state uses separate CQs, traverse
the list of QPs using each CQs and invoke the buddy CQ handler for
both SQ and RQ.
Signed-off-by: default avatarSelvin Xavier <selvin.xavier@emulex.com>
Signed-off-by: default avatarDevesh Sharma <devesh.sharma@emulex.com>
Signed-off-by: default avatarMitesh Ahuja <mitesh.ahuja@emulex.com>
Signed-off-by: default avatarRoland Dreier <roland@purestorage.com>
parent 380676ea
......@@ -834,20 +834,20 @@ static int ocrdma_mq_cq_handler(struct ocrdma_dev *dev, u16 cq_id)
return 0;
}
static void ocrdma_qp_buddy_cq_handler(struct ocrdma_dev *dev,
struct ocrdma_cq *cq)
static struct ocrdma_cq *_ocrdma_qp_buddy_cq_handler(struct ocrdma_dev *dev,
struct ocrdma_cq *cq, bool sq)
{
unsigned long flags;
struct ocrdma_qp *qp;
bool buddy_cq_found = false;
/* Go through list of QPs in error state which are using this CQ
* and invoke its callback handler to trigger CQE processing for
* error/flushed CQE. It is rare to find more than few entries in
* this list as most consumers stops after getting error CQE.
* List is traversed only once when a matching buddy cq found for a QP.
*/
spin_lock_irqsave(&dev->flush_q_lock, flags);
list_for_each_entry(qp, &cq->sq_head, sq_entry) {
struct list_head *cur;
struct ocrdma_cq *bcq = NULL;
struct list_head *head = sq?(&cq->sq_head):(&cq->rq_head);
list_for_each(cur, head) {
if (sq)
qp = list_entry(cur, struct ocrdma_qp, sq_entry);
else
qp = list_entry(cur, struct ocrdma_qp, rq_entry);
if (qp->srq)
continue;
/* if wq and rq share the same cq, than comp_handler
......@@ -859,19 +859,41 @@ static void ocrdma_qp_buddy_cq_handler(struct ocrdma_dev *dev,
* if completion came on rq, sq's cq is buddy cq.
*/
if (qp->sq_cq == cq)
cq = qp->rq_cq;
bcq = qp->rq_cq;
else
cq = qp->sq_cq;
buddy_cq_found = true;
break;
bcq = qp->sq_cq;
return bcq;
}
return NULL;
}
static void ocrdma_qp_buddy_cq_handler(struct ocrdma_dev *dev,
struct ocrdma_cq *cq)
{
unsigned long flags;
struct ocrdma_cq *bcq = NULL;
/* Go through list of QPs in error state which are using this CQ
* and invoke its callback handler to trigger CQE processing for
* error/flushed CQE. It is rare to find more than few entries in
* this list as most consumers stops after getting error CQE.
* List is traversed only once when a matching buddy cq found for a QP.
*/
spin_lock_irqsave(&dev->flush_q_lock, flags);
/* Check if buddy CQ is present.
* true - Check for SQ CQ
* false - Check for RQ CQ
*/
bcq = _ocrdma_qp_buddy_cq_handler(dev, cq, true);
if (bcq == NULL)
bcq = _ocrdma_qp_buddy_cq_handler(dev, cq, false);
spin_unlock_irqrestore(&dev->flush_q_lock, flags);
if (buddy_cq_found == false)
return;
if (cq->ibcq.comp_handler) {
spin_lock_irqsave(&cq->comp_handler_lock, flags);
(*cq->ibcq.comp_handler) (&cq->ibcq, cq->ibcq.cq_context);
spin_unlock_irqrestore(&cq->comp_handler_lock, flags);
/* if there is valid buddy cq, look for its completion handler */
if (bcq && bcq->ibcq.comp_handler) {
spin_lock_irqsave(&bcq->comp_handler_lock, flags);
(*bcq->ibcq.comp_handler) (&bcq->ibcq, bcq->ibcq.cq_context);
spin_unlock_irqrestore(&bcq->comp_handler_lock, flags);
}
}
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment