diff options
author | Don Wood <donald.e.wood@intel.com> | 2009-09-05 23:36:37 -0400 |
---|---|---|
committer | Roland Dreier <rolandd@cisco.com> | 2009-09-05 23:36:37 -0400 |
commit | 5ee21fe0eaf68fb840f442131ab7addced1a31c3 (patch) | |
tree | c2161f284345f6f993b6e467b3840676c1141169 /drivers/infiniband | |
parent | ba0c5d9a8975cf740a4a4b8c579cc4b325f8b852 (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')
-rw-r--r-- | drivers/infiniband/hw/nes/nes_verbs.c | 119 |
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 | */ | ||
1511 | static 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 | */ |
1511 | static int nes_destroy_qp(struct ib_qp *ibqp) | 1545 | static 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) { |