aboutsummaryrefslogtreecommitdiffstats
path: root/drivers/infiniband/hw/nes
diff options
context:
space:
mode:
authorDon Wood <donald.e.wood@intel.com>2009-09-05 23:36:37 -0400
committerRoland Dreier <rolandd@cisco.com>2009-09-05 23:36:37 -0400
commit5ee21fe0eaf68fb840f442131ab7addced1a31c3 (patch)
treec2161f284345f6f993b6e467b3840676c1141169 /drivers/infiniband/hw/nes
parentba0c5d9a8975cf740a4a4b8c579cc4b325f8b852 (diff)
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: Don Wood <donald.e.wood@intel.com> Signed-off-by: Roland Dreier <rolandd@cisco.com>
Diffstat (limited to 'drivers/infiniband/hw/nes')
-rw-r--r--drivers/infiniband/hw/nes/nes_verbs.c119
1 files changed, 80 insertions, 39 deletions
diff --git a/drivers/infiniband/hw/nes/nes_verbs.c b/drivers/infiniband/hw/nes/nes_verbs.c
index 21e0fd336cf7..c6b5873416eb 100644
--- a/drivers/infiniband/hw/nes/nes_verbs.c
+++ b/drivers/infiniband/hw/nes/nes_verbs.c
@@ -1506,12 +1506,45 @@ static struct ib_qp *nes_create_qp(struct ib_pd *ibpd,
1506 1506
1507 1507
1508/** 1508/**
1509 * nes_clean_cq
1510 */
1511static void nes_clean_cq(struct nes_qp *nesqp, struct nes_cq *nescq)
1512{
1513 u32 cq_head;
1514 u32 lo;
1515 u32 hi;
1516 u64 u64temp;
1517 unsigned long flags = 0;
1518
1519 spin_lock_irqsave(&nescq->lock, flags);
1520
1521 cq_head = nescq->hw_cq.cq_head;
1522 while (le32_to_cpu(nescq->hw_cq.cq_vbase[cq_head].cqe_words[NES_CQE_OPCODE_IDX]) & NES_CQE_VALID) {
1523 rmb();
1524 lo = le32_to_cpu(nescq->hw_cq.cq_vbase[cq_head].cqe_words[NES_CQE_COMP_COMP_CTX_LOW_IDX]);
1525 hi = le32_to_cpu(nescq->hw_cq.cq_vbase[cq_head].cqe_words[NES_CQE_COMP_COMP_CTX_HIGH_IDX]);
1526 u64temp = (((u64)hi) << 32) | ((u64)lo);
1527 u64temp &= ~(NES_SW_CONTEXT_ALIGN-1);
1528 if (u64temp == (u64)(unsigned long)nesqp) {
1529 /* Zero the context value so cqe will be ignored */
1530 nescq->hw_cq.cq_vbase[cq_head].cqe_words[NES_CQE_COMP_COMP_CTX_LOW_IDX] = 0;
1531 nescq->hw_cq.cq_vbase[cq_head].cqe_words[NES_CQE_COMP_COMP_CTX_HIGH_IDX] = 0;
1532 }
1533
1534 if (++cq_head >= nescq->hw_cq.cq_size)
1535 cq_head = 0;
1536 }
1537
1538 spin_unlock_irqrestore(&nescq->lock, flags);
1539}
1540
1541
1542/**
1509 * nes_destroy_qp 1543 * nes_destroy_qp
1510 */ 1544 */
1511static int nes_destroy_qp(struct ib_qp *ibqp) 1545static int nes_destroy_qp(struct ib_qp *ibqp)
1512{ 1546{
1513 struct nes_qp *nesqp = to_nesqp(ibqp); 1547 struct nes_qp *nesqp = to_nesqp(ibqp);
1514 /* struct nes_vnic *nesvnic = to_nesvnic(ibqp->device); */
1515 struct nes_ucontext *nes_ucontext; 1548 struct nes_ucontext *nes_ucontext;
1516 struct ib_qp_attr attr; 1549 struct ib_qp_attr attr;
1517 struct iw_cm_id *cm_id; 1550 struct iw_cm_id *cm_id;
@@ -1548,7 +1581,6 @@ static int nes_destroy_qp(struct ib_qp *ibqp)
1548 nes_debug(NES_DBG_QP, "OFA CM event_handler returned, ret=%d\n", ret); 1581 nes_debug(NES_DBG_QP, "OFA CM event_handler returned, ret=%d\n", ret);
1549 } 1582 }
1550 1583
1551
1552 if (nesqp->user_mode) { 1584 if (nesqp->user_mode) {
1553 if ((ibqp->uobject)&&(ibqp->uobject->context)) { 1585 if ((ibqp->uobject)&&(ibqp->uobject->context)) {
1554 nes_ucontext = to_nesucontext(ibqp->uobject->context); 1586 nes_ucontext = to_nesucontext(ibqp->uobject->context);
@@ -1560,6 +1592,13 @@ static int nes_destroy_qp(struct ib_qp *ibqp)
1560 } 1592 }
1561 if (nesqp->pbl_pbase) 1593 if (nesqp->pbl_pbase)
1562 kunmap(nesqp->page); 1594 kunmap(nesqp->page);
1595 } else {
1596 /* Clean any pending completions from the cq(s) */
1597 if (nesqp->nesscq)
1598 nes_clean_cq(nesqp, nesqp->nesscq);
1599
1600 if ((nesqp->nesrcq) && (nesqp->nesrcq != nesqp->nesscq))
1601 nes_clean_cq(nesqp, nesqp->nesrcq);
1563 } 1602 }
1564 1603
1565 nes_rem_ref(&nesqp->ibqp); 1604 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)
3547{ 3586{
3548 u64 u64temp; 3587 u64 u64temp;
3549 u64 wrid; 3588 u64 wrid;
3550 /* u64 u64temp; */
3551 unsigned long flags = 0; 3589 unsigned long flags = 0;
3552 struct nes_vnic *nesvnic = to_nesvnic(ibcq->device); 3590 struct nes_vnic *nesvnic = to_nesvnic(ibcq->device);
3553 struct nes_device *nesdev = nesvnic->nesdev; 3591 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)
3560 u32 cqe_count = 0; 3598 u32 cqe_count = 0;
3561 u32 wqe_index; 3599 u32 wqe_index;
3562 u32 u32temp; 3600 u32 u32temp;
3563 /* u32 counter; */
3564 3601
3565 nes_debug(NES_DBG_CQ, "\n"); 3602 nes_debug(NES_DBG_CQ, "\n");
3566 3603
@@ -3570,24 +3607,27 @@ static int nes_poll_cq(struct ib_cq *ibcq, int num_entries, struct ib_wc *entry)
3570 cq_size = nescq->hw_cq.cq_size; 3607 cq_size = nescq->hw_cq.cq_size;
3571 3608
3572 while (cqe_count < num_entries) { 3609 while (cqe_count < num_entries) {
3573 if (le32_to_cpu(nescq->hw_cq.cq_vbase[head].cqe_words[NES_CQE_OPCODE_IDX]) & 3610 if ((le32_to_cpu(nescq->hw_cq.cq_vbase[head].cqe_words[NES_CQE_OPCODE_IDX]) &
3574 NES_CQE_VALID) { 3611 NES_CQE_VALID) == 0)
3575 /* 3612 break;
3576 * Make sure we read CQ entry contents *after* 3613
3577 * we've checked the valid bit. 3614 /*
3578 */ 3615 * Make sure we read CQ entry contents *after*
3579 rmb(); 3616 * we've checked the valid bit.
3580 3617 */
3581 cqe = nescq->hw_cq.cq_vbase[head]; 3618 rmb();
3582 nescq->hw_cq.cq_vbase[head].cqe_words[NES_CQE_OPCODE_IDX] = 0; 3619
3583 u32temp = le32_to_cpu(cqe.cqe_words[NES_CQE_COMP_COMP_CTX_LOW_IDX]); 3620 cqe = nescq->hw_cq.cq_vbase[head];
3584 wqe_index = u32temp & 3621 nescq->hw_cq.cq_vbase[head].cqe_words[NES_CQE_OPCODE_IDX] = 0;
3585 (nesdev->nesadapter->max_qp_wr - 1); 3622 u32temp = le32_to_cpu(cqe.cqe_words[NES_CQE_COMP_COMP_CTX_LOW_IDX]);
3586 u32temp &= ~(NES_SW_CONTEXT_ALIGN-1); 3623 wqe_index = u32temp & (nesdev->nesadapter->max_qp_wr - 1);
3587 /* parse CQE, get completion context from WQE (either rq or sq */ 3624 u32temp &= ~(NES_SW_CONTEXT_ALIGN-1);
3588 u64temp = (((u64)(le32_to_cpu(cqe.cqe_words[NES_CQE_COMP_COMP_CTX_HIGH_IDX])))<<32) | 3625 /* parse CQE, get completion context from WQE (either rq or sq) */
3589 ((u64)u32temp); 3626 u64temp = (((u64)(le32_to_cpu(cqe.cqe_words[NES_CQE_COMP_COMP_CTX_HIGH_IDX])))<<32) |
3590 nesqp = *((struct nes_qp **)&u64temp); 3627 ((u64)u32temp);
3628
3629 if (u64temp) {
3630 nesqp = (struct nes_qp *)(unsigned long)u64temp;
3591 memset(entry, 0, sizeof *entry); 3631 memset(entry, 0, sizeof *entry);
3592 if (cqe.cqe_words[NES_CQE_ERROR_CODE_IDX] == 0) { 3632 if (cqe.cqe_words[NES_CQE_ERROR_CODE_IDX] == 0) {
3593 entry->status = IB_WC_SUCCESS; 3633 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)
3601 if (le32_to_cpu(cqe.cqe_words[NES_CQE_OPCODE_IDX]) & NES_CQE_SQ) { 3641 if (le32_to_cpu(cqe.cqe_words[NES_CQE_OPCODE_IDX]) & NES_CQE_SQ) {
3602 if (nesqp->skip_lsmm) { 3642 if (nesqp->skip_lsmm) {
3603 nesqp->skip_lsmm = 0; 3643 nesqp->skip_lsmm = 0;
3604 wq_tail = nesqp->hwqp.sq_tail++; 3644 nesqp->hwqp.sq_tail++;
3605 } 3645 }
3606 3646
3607 /* Working on a SQ Completion*/ 3647 /* Working on a SQ Completion*/
@@ -3643,24 +3683,25 @@ static int nes_poll_cq(struct ib_cq *ibcq, int num_entries, struct ib_wc *entry)
3643 ((u64)(le32_to_cpu(nesqp->hwqp.rq_vbase[wq_tail].wqe_words[NES_IWARP_RQ_WQE_COMP_SCRATCH_HIGH_IDX]))<<32); 3683 ((u64)(le32_to_cpu(nesqp->hwqp.rq_vbase[wq_tail].wqe_words[NES_IWARP_RQ_WQE_COMP_SCRATCH_HIGH_IDX]))<<32);
3644 entry->opcode = IB_WC_RECV; 3684 entry->opcode = IB_WC_RECV;
3645 } 3685 }
3646 entry->wr_id = wrid;
3647 3686
3648 if (++head >= cq_size) 3687 entry->wr_id = wrid;
3649 head = 0;
3650 cqe_count++;
3651 nescq->polled_completions++;
3652 if ((nescq->polled_completions > (cq_size / 2)) ||
3653 (nescq->polled_completions == 255)) {
3654 nes_debug(NES_DBG_CQ, "CQ%u Issuing CQE Allocate since more than half of cqes"
3655 " are pending %u of %u.\n",
3656 nescq->hw_cq.cq_number, nescq->polled_completions, cq_size);
3657 nes_write32(nesdev->regs+NES_CQE_ALLOC,
3658 nescq->hw_cq.cq_number | (nescq->polled_completions << 16));
3659 nescq->polled_completions = 0;
3660 }
3661 entry++; 3688 entry++;
3662 } else 3689 cqe_count++;
3663 break; 3690 }
3691
3692 if (++head >= cq_size)
3693 head = 0;
3694 nescq->polled_completions++;
3695
3696 if ((nescq->polled_completions > (cq_size / 2)) ||
3697 (nescq->polled_completions == 255)) {
3698 nes_debug(NES_DBG_CQ, "CQ%u Issuing CQE Allocate since more than half of cqes"
3699 " are pending %u of %u.\n",
3700 nescq->hw_cq.cq_number, nescq->polled_completions, cq_size);
3701 nes_write32(nesdev->regs+NES_CQE_ALLOC,
3702 nescq->hw_cq.cq_number | (nescq->polled_completions << 16));
3703 nescq->polled_completions = 0;
3704 }
3664 } 3705 }
3665 3706
3666 if (nescq->polled_completions) { 3707 if (nescq->polled_completions) {