diff options
author | Devesh Sharma <devesh.sharma@emulex.com> | 2014-02-04 01:26:54 -0500 |
---|---|---|
committer | Roland Dreier <roland@purestorage.com> | 2014-04-03 11:29:34 -0400 |
commit | ea61762679cd4d409dcaa6f502f190f4c8156d09 (patch) | |
tree | 5827d101e41788a4ff93c2368eaa4d3ec5ae337a /drivers/infiniband/hw/ocrdma/ocrdma_verbs.c | |
parent | bc1b04ab34a1485339571242cb0fbad823835685 (diff) |
RDMA/ocrdma: EQ full catastrophe avoidance
Stale entries in the CQ being destroyed causes hardware to generate
EQEs indefinitely for a given CQ. Thus causing uncontrolled execution
of irq_handler. This patch fixes this using following sementics:
* irq_handler will ring EQ doorbell atleast once and implement budgeting scheme.
* cq_destroy will count number of valid entires during destroy and ring
cq-db so that hardware does not generate uncontrolled EQE.
* cq_destroy will synchronize with last running irq_handler instance.
* arm_cq will always defer arming CQ till poll_cq, except for the first arm_cq call.
* poll_cq will always ring cq-db with arm=SET if arm_cq was called prior to enter poll_cq.
* poll_cq will always ring cq-db with arm=UNSET if arm_cq was not called prior to enter poll_cq.
Signed-off-by: Devesh Sharma <devesh.sharma@emulex.com>
Signed-off-by: Selvin Xavier <selvin.xavier@emulex.com>
Signed-off-by: Roland Dreier <roland@purestorage.com>
Diffstat (limited to 'drivers/infiniband/hw/ocrdma/ocrdma_verbs.c')
-rw-r--r-- | drivers/infiniband/hw/ocrdma/ocrdma_verbs.c | 81 |
1 files changed, 61 insertions, 20 deletions
diff --git a/drivers/infiniband/hw/ocrdma/ocrdma_verbs.c b/drivers/infiniband/hw/ocrdma/ocrdma_verbs.c index f1108ebae83a..7d59ed340991 100644 --- a/drivers/infiniband/hw/ocrdma/ocrdma_verbs.c +++ b/drivers/infiniband/hw/ocrdma/ocrdma_verbs.c | |||
@@ -910,6 +910,7 @@ struct ib_cq *ocrdma_create_cq(struct ib_device *ibdev, int entries, int vector, | |||
910 | spin_lock_init(&cq->comp_handler_lock); | 910 | spin_lock_init(&cq->comp_handler_lock); |
911 | INIT_LIST_HEAD(&cq->sq_head); | 911 | INIT_LIST_HEAD(&cq->sq_head); |
912 | INIT_LIST_HEAD(&cq->rq_head); | 912 | INIT_LIST_HEAD(&cq->rq_head); |
913 | cq->first_arm = true; | ||
913 | 914 | ||
914 | if (ib_ctx) { | 915 | if (ib_ctx) { |
915 | uctx = get_ocrdma_ucontext(ib_ctx); | 916 | uctx = get_ocrdma_ucontext(ib_ctx); |
@@ -927,9 +928,7 @@ struct ib_cq *ocrdma_create_cq(struct ib_device *ibdev, int entries, int vector, | |||
927 | goto ctx_err; | 928 | goto ctx_err; |
928 | } | 929 | } |
929 | cq->phase = OCRDMA_CQE_VALID; | 930 | cq->phase = OCRDMA_CQE_VALID; |
930 | cq->arm_needed = true; | ||
931 | dev->cq_tbl[cq->id] = cq; | 931 | dev->cq_tbl[cq->id] = cq; |
932 | |||
933 | return &cq->ibcq; | 932 | return &cq->ibcq; |
934 | 933 | ||
935 | ctx_err: | 934 | ctx_err: |
@@ -952,15 +951,52 @@ int ocrdma_resize_cq(struct ib_cq *ibcq, int new_cnt, | |||
952 | return status; | 951 | return status; |
953 | } | 952 | } |
954 | 953 | ||
954 | static void ocrdma_flush_cq(struct ocrdma_cq *cq) | ||
955 | { | ||
956 | int cqe_cnt; | ||
957 | int valid_count = 0; | ||
958 | unsigned long flags; | ||
959 | |||
960 | struct ocrdma_dev *dev = get_ocrdma_dev(cq->ibcq.device); | ||
961 | struct ocrdma_cqe *cqe = NULL; | ||
962 | |||
963 | cqe = cq->va; | ||
964 | cqe_cnt = cq->cqe_cnt; | ||
965 | |||
966 | /* Last irq might have scheduled a polling thread | ||
967 | * sync-up with it before hard flushing. | ||
968 | */ | ||
969 | spin_lock_irqsave(&cq->cq_lock, flags); | ||
970 | while (cqe_cnt) { | ||
971 | if (is_cqe_valid(cq, cqe)) | ||
972 | valid_count++; | ||
973 | cqe++; | ||
974 | cqe_cnt--; | ||
975 | } | ||
976 | ocrdma_ring_cq_db(dev, cq->id, false, false, valid_count); | ||
977 | spin_unlock_irqrestore(&cq->cq_lock, flags); | ||
978 | } | ||
979 | |||
955 | int ocrdma_destroy_cq(struct ib_cq *ibcq) | 980 | int ocrdma_destroy_cq(struct ib_cq *ibcq) |
956 | { | 981 | { |
957 | int status; | 982 | int status; |
958 | struct ocrdma_cq *cq = get_ocrdma_cq(ibcq); | 983 | struct ocrdma_cq *cq = get_ocrdma_cq(ibcq); |
984 | struct ocrdma_eq *eq = NULL; | ||
959 | struct ocrdma_dev *dev = get_ocrdma_dev(ibcq->device); | 985 | struct ocrdma_dev *dev = get_ocrdma_dev(ibcq->device); |
960 | int pdid = 0; | 986 | int pdid = 0; |
987 | u32 irq, indx; | ||
961 | 988 | ||
962 | status = ocrdma_mbx_destroy_cq(dev, cq); | 989 | dev->cq_tbl[cq->id] = NULL; |
990 | indx = ocrdma_get_eq_table_index(dev, cq->eqn); | ||
991 | if (indx == -EINVAL) | ||
992 | BUG(); | ||
963 | 993 | ||
994 | eq = &dev->eq_tbl[indx]; | ||
995 | irq = ocrdma_get_irq(dev, eq); | ||
996 | synchronize_irq(irq); | ||
997 | ocrdma_flush_cq(cq); | ||
998 | |||
999 | status = ocrdma_mbx_destroy_cq(dev, cq); | ||
964 | if (cq->ucontext) { | 1000 | if (cq->ucontext) { |
965 | pdid = cq->ucontext->cntxt_pd->id; | 1001 | pdid = cq->ucontext->cntxt_pd->id; |
966 | ocrdma_del_mmap(cq->ucontext, (u64) cq->pa, | 1002 | ocrdma_del_mmap(cq->ucontext, (u64) cq->pa, |
@@ -969,7 +1005,6 @@ int ocrdma_destroy_cq(struct ib_cq *ibcq) | |||
969 | ocrdma_get_db_addr(dev, pdid), | 1005 | ocrdma_get_db_addr(dev, pdid), |
970 | dev->nic_info.db_page_size); | 1006 | dev->nic_info.db_page_size); |
971 | } | 1007 | } |
972 | dev->cq_tbl[cq->id] = NULL; | ||
973 | 1008 | ||
974 | kfree(cq); | 1009 | kfree(cq); |
975 | return status; | 1010 | return status; |
@@ -2705,10 +2740,18 @@ expand_cqe: | |||
2705 | } | 2740 | } |
2706 | stop_cqe: | 2741 | stop_cqe: |
2707 | cq->getp = cur_getp; | 2742 | cq->getp = cur_getp; |
2708 | if (polled_hw_cqes || expand || stop) { | 2743 | if (cq->deferred_arm) { |
2709 | ocrdma_ring_cq_db(dev, cq->id, cq->armed, cq->solicited, | 2744 | ocrdma_ring_cq_db(dev, cq->id, true, cq->deferred_sol, |
2745 | polled_hw_cqes); | ||
2746 | cq->deferred_arm = false; | ||
2747 | cq->deferred_sol = false; | ||
2748 | } else { | ||
2749 | /* We need to pop the CQE. No need to arm */ | ||
2750 | ocrdma_ring_cq_db(dev, cq->id, false, cq->deferred_sol, | ||
2710 | polled_hw_cqes); | 2751 | polled_hw_cqes); |
2752 | cq->deferred_sol = false; | ||
2711 | } | 2753 | } |
2754 | |||
2712 | return i; | 2755 | return i; |
2713 | } | 2756 | } |
2714 | 2757 | ||
@@ -2780,30 +2823,28 @@ int ocrdma_arm_cq(struct ib_cq *ibcq, enum ib_cq_notify_flags cq_flags) | |||
2780 | struct ocrdma_cq *cq = get_ocrdma_cq(ibcq); | 2823 | struct ocrdma_cq *cq = get_ocrdma_cq(ibcq); |
2781 | struct ocrdma_dev *dev = get_ocrdma_dev(ibcq->device); | 2824 | struct ocrdma_dev *dev = get_ocrdma_dev(ibcq->device); |
2782 | u16 cq_id; | 2825 | u16 cq_id; |
2783 | u16 cur_getp; | ||
2784 | struct ocrdma_cqe *cqe; | ||
2785 | unsigned long flags; | 2826 | unsigned long flags; |
2827 | bool arm_needed = false, sol_needed = false; | ||
2786 | 2828 | ||
2787 | cq_id = cq->id; | 2829 | cq_id = cq->id; |
2788 | 2830 | ||
2789 | spin_lock_irqsave(&cq->cq_lock, flags); | 2831 | spin_lock_irqsave(&cq->cq_lock, flags); |
2790 | if (cq_flags & IB_CQ_NEXT_COMP || cq_flags & IB_CQ_SOLICITED) | 2832 | if (cq_flags & IB_CQ_NEXT_COMP || cq_flags & IB_CQ_SOLICITED) |
2791 | cq->armed = true; | 2833 | arm_needed = true; |
2792 | if (cq_flags & IB_CQ_SOLICITED) | 2834 | if (cq_flags & IB_CQ_SOLICITED) |
2793 | cq->solicited = true; | 2835 | sol_needed = true; |
2794 | |||
2795 | cur_getp = cq->getp; | ||
2796 | cqe = cq->va + cur_getp; | ||
2797 | 2836 | ||
2798 | /* check whether any valid cqe exist or not, if not then safe to | 2837 | if (cq->first_arm) { |
2799 | * arm. If cqe is not yet consumed, then let it get consumed and then | 2838 | ocrdma_ring_cq_db(dev, cq_id, arm_needed, sol_needed, 0); |
2800 | * we arm it to avoid false interrupts. | 2839 | cq->first_arm = false; |
2801 | */ | 2840 | goto skip_defer; |
2802 | if (!is_cqe_valid(cq, cqe) || cq->arm_needed) { | ||
2803 | cq->arm_needed = false; | ||
2804 | ocrdma_ring_cq_db(dev, cq_id, cq->armed, cq->solicited, 0); | ||
2805 | } | 2841 | } |
2842 | cq->deferred_arm = true; | ||
2843 | |||
2844 | skip_defer: | ||
2845 | cq->deferred_sol = sol_needed; | ||
2806 | spin_unlock_irqrestore(&cq->cq_lock, flags); | 2846 | spin_unlock_irqrestore(&cq->cq_lock, flags); |
2847 | |||
2807 | return 0; | 2848 | return 0; |
2808 | } | 2849 | } |
2809 | 2850 | ||