Donate to e Foundation | Murena handsets with /e/OS | Own a part of Murena! Learn more

Commit 5ee21fe0 authored by Don Wood's avatar Don Wood Committed by Roland Dreier
Browse files

RDMA/nes: Clean out CQ completions when QP is destroyed



When a QP is destroyed, unprocessed CQ entries could still reference
the QP.  This change zeroes the context value at QP destroy time.  By
skipping over cqe's with a zero context, poll_cq no longer processes a
cqe for a destroyed QP.

Signed-off-by: default avatarDon Wood <donald.e.wood@intel.com>
Signed-off-by: default avatarRoland Dreier <rolandd@cisco.com>
parent ba0c5d9a
Loading
Loading
Loading
Loading
+80 −39
Original line number Diff line number Diff line
@@ -1505,13 +1505,46 @@ static struct ib_qp *nes_create_qp(struct ib_pd *ibpd,
}


/**
 * nes_clean_cq
 */
static void nes_clean_cq(struct nes_qp *nesqp, struct nes_cq *nescq)
{
	u32 cq_head;
	u32 lo;
	u32 hi;
	u64 u64temp;
	unsigned long flags = 0;

	spin_lock_irqsave(&nescq->lock, flags);

	cq_head = nescq->hw_cq.cq_head;
	while (le32_to_cpu(nescq->hw_cq.cq_vbase[cq_head].cqe_words[NES_CQE_OPCODE_IDX]) & NES_CQE_VALID) {
		rmb();
		lo = le32_to_cpu(nescq->hw_cq.cq_vbase[cq_head].cqe_words[NES_CQE_COMP_COMP_CTX_LOW_IDX]);
		hi = le32_to_cpu(nescq->hw_cq.cq_vbase[cq_head].cqe_words[NES_CQE_COMP_COMP_CTX_HIGH_IDX]);
		u64temp = (((u64)hi) << 32) | ((u64)lo);
		u64temp &= ~(NES_SW_CONTEXT_ALIGN-1);
		if (u64temp == (u64)(unsigned long)nesqp) {
			/* Zero the context value so cqe will be ignored */
			nescq->hw_cq.cq_vbase[cq_head].cqe_words[NES_CQE_COMP_COMP_CTX_LOW_IDX] = 0;
			nescq->hw_cq.cq_vbase[cq_head].cqe_words[NES_CQE_COMP_COMP_CTX_HIGH_IDX] = 0;
		}

		if (++cq_head >= nescq->hw_cq.cq_size)
			cq_head = 0;
	}

	spin_unlock_irqrestore(&nescq->lock, flags);
}


/**
 * nes_destroy_qp
 */
static int nes_destroy_qp(struct ib_qp *ibqp)
{
	struct nes_qp *nesqp = to_nesqp(ibqp);
	/* struct nes_vnic *nesvnic = to_nesvnic(ibqp->device); */
	struct nes_ucontext *nes_ucontext;
	struct ib_qp_attr attr;
	struct iw_cm_id *cm_id;
@@ -1548,7 +1581,6 @@ static int nes_destroy_qp(struct ib_qp *ibqp)
			nes_debug(NES_DBG_QP, "OFA CM event_handler returned, ret=%d\n", ret);
	}


	if (nesqp->user_mode) {
		if ((ibqp->uobject)&&(ibqp->uobject->context)) {
			nes_ucontext = to_nesucontext(ibqp->uobject->context);
@@ -1560,6 +1592,13 @@ static int nes_destroy_qp(struct ib_qp *ibqp)
		}
		if (nesqp->pbl_pbase)
			kunmap(nesqp->page);
	} else {
		/* Clean any pending completions from the cq(s) */
		if (nesqp->nesscq)
			nes_clean_cq(nesqp, nesqp->nesscq);

		if ((nesqp->nesrcq) && (nesqp->nesrcq != nesqp->nesscq))
			nes_clean_cq(nesqp, nesqp->nesrcq);
	}

	nes_rem_ref(&nesqp->ibqp);
@@ -3547,7 +3586,6 @@ static int nes_poll_cq(struct ib_cq *ibcq, int num_entries, struct ib_wc *entry)
{
	u64 u64temp;
	u64 wrid;
	/* u64 u64temp; */
	unsigned long flags = 0;
	struct nes_vnic *nesvnic = to_nesvnic(ibcq->device);
	struct nes_device *nesdev = nesvnic->nesdev;
@@ -3560,7 +3598,6 @@ static int nes_poll_cq(struct ib_cq *ibcq, int num_entries, struct ib_wc *entry)
	u32 cqe_count = 0;
	u32 wqe_index;
	u32 u32temp;
	/* u32 counter; */

	nes_debug(NES_DBG_CQ, "\n");

@@ -3570,8 +3607,10 @@ static int nes_poll_cq(struct ib_cq *ibcq, int num_entries, struct ib_wc *entry)
	cq_size = nescq->hw_cq.cq_size;

	while (cqe_count < num_entries) {
		if (le32_to_cpu(nescq->hw_cq.cq_vbase[head].cqe_words[NES_CQE_OPCODE_IDX]) &
				NES_CQE_VALID) {
		if ((le32_to_cpu(nescq->hw_cq.cq_vbase[head].cqe_words[NES_CQE_OPCODE_IDX]) &
				NES_CQE_VALID) == 0)
			break;

		/*
		 * Make sure we read CQ entry contents *after*
		 * we've checked the valid bit.
@@ -3581,13 +3620,14 @@ static int nes_poll_cq(struct ib_cq *ibcq, int num_entries, struct ib_wc *entry)
		cqe = nescq->hw_cq.cq_vbase[head];
		nescq->hw_cq.cq_vbase[head].cqe_words[NES_CQE_OPCODE_IDX] = 0;
		u32temp = le32_to_cpu(cqe.cqe_words[NES_CQE_COMP_COMP_CTX_LOW_IDX]);
			wqe_index = u32temp &
					(nesdev->nesadapter->max_qp_wr - 1);
		wqe_index = u32temp & (nesdev->nesadapter->max_qp_wr - 1);
		u32temp &= ~(NES_SW_CONTEXT_ALIGN-1);
			/* parse CQE, get completion context from WQE (either rq or sq */
		/* parse CQE, get completion context from WQE (either rq or sq) */
		u64temp = (((u64)(le32_to_cpu(cqe.cqe_words[NES_CQE_COMP_COMP_CTX_HIGH_IDX])))<<32) |
				((u64)u32temp);
			nesqp = *((struct nes_qp **)&u64temp);

		if (u64temp) {
			nesqp = (struct nes_qp *)(unsigned long)u64temp;
			memset(entry, 0, sizeof *entry);
			if (cqe.cqe_words[NES_CQE_ERROR_CODE_IDX] == 0) {
				entry->status = IB_WC_SUCCESS;
@@ -3601,7 +3641,7 @@ static int nes_poll_cq(struct ib_cq *ibcq, int num_entries, struct ib_wc *entry)
			if (le32_to_cpu(cqe.cqe_words[NES_CQE_OPCODE_IDX]) & NES_CQE_SQ) {
				if (nesqp->skip_lsmm) {
					nesqp->skip_lsmm = 0;
					wq_tail = nesqp->hwqp.sq_tail++;
					nesqp->hwqp.sq_tail++;
				}

				/* Working on a SQ Completion*/
@@ -3643,12 +3683,16 @@ static int nes_poll_cq(struct ib_cq *ibcq, int num_entries, struct ib_wc *entry)
					((u64)(le32_to_cpu(nesqp->hwqp.rq_vbase[wq_tail].wqe_words[NES_IWARP_RQ_WQE_COMP_SCRATCH_HIGH_IDX]))<<32);
					entry->opcode = IB_WC_RECV;
			}

			entry->wr_id = wrid;
			entry++;
			cqe_count++;
		}

		if (++head >= cq_size)
			head = 0;
			cqe_count++;
		nescq->polled_completions++;

		if ((nescq->polled_completions > (cq_size / 2)) ||
				(nescq->polled_completions == 255)) {
			nes_debug(NES_DBG_CQ, "CQ%u Issuing CQE Allocate since more than half of cqes"
@@ -3658,9 +3702,6 @@ static int nes_poll_cq(struct ib_cq *ibcq, int num_entries, struct ib_wc *entry)
					nescq->hw_cq.cq_number | (nescq->polled_completions << 16));
			nescq->polled_completions = 0;
		}
			entry++;
		} else
			break;
	}

	if (nescq->polled_completions) {