diff options
-rw-r--r-- | drivers/infiniband/hw/cxgb4/ev.c | 1 | ||||
-rw-r--r-- | drivers/infiniband/hw/cxgb4/qp.c | 37 | ||||
-rw-r--r-- | drivers/infiniband/hw/cxgb4/t4.h | 11 |
3 files changed, 37 insertions, 12 deletions
diff --git a/drivers/infiniband/hw/cxgb4/ev.c b/drivers/infiniband/hw/cxgb4/ev.c index d61d0a18f784..a98426fed9ee 100644 --- a/drivers/infiniband/hw/cxgb4/ev.c +++ b/drivers/infiniband/hw/cxgb4/ev.c | |||
@@ -182,6 +182,7 @@ int c4iw_ev_handler(struct c4iw_dev *dev, u32 qid) | |||
182 | 182 | ||
183 | chp = get_chp(dev, qid); | 183 | chp = get_chp(dev, qid); |
184 | if (chp) { | 184 | if (chp) { |
185 | t4_clear_cq_armed(&chp->cq); | ||
185 | spin_lock_irqsave(&chp->comp_handler_lock, flag); | 186 | spin_lock_irqsave(&chp->comp_handler_lock, flag); |
186 | (*chp->ibcq.comp_handler)(&chp->ibcq, chp->ibcq.cq_context); | 187 | (*chp->ibcq.comp_handler)(&chp->ibcq, chp->ibcq.cq_context); |
187 | spin_unlock_irqrestore(&chp->comp_handler_lock, flag); | 188 | spin_unlock_irqrestore(&chp->comp_handler_lock, flag); |
diff --git a/drivers/infiniband/hw/cxgb4/qp.c b/drivers/infiniband/hw/cxgb4/qp.c index 086f62f5dc9e..60cfc11a66e4 100644 --- a/drivers/infiniband/hw/cxgb4/qp.c +++ b/drivers/infiniband/hw/cxgb4/qp.c | |||
@@ -1066,7 +1066,7 @@ static void __flush_qp(struct c4iw_qp *qhp, struct c4iw_cq *rchp, | |||
1066 | struct c4iw_cq *schp) | 1066 | struct c4iw_cq *schp) |
1067 | { | 1067 | { |
1068 | int count; | 1068 | int count; |
1069 | int flushed; | 1069 | int rq_flushed, sq_flushed; |
1070 | unsigned long flag; | 1070 | unsigned long flag; |
1071 | 1071 | ||
1072 | PDBG("%s qhp %p rchp %p schp %p\n", __func__, qhp, rchp, schp); | 1072 | PDBG("%s qhp %p rchp %p schp %p\n", __func__, qhp, rchp, schp); |
@@ -1084,27 +1084,40 @@ static void __flush_qp(struct c4iw_qp *qhp, struct c4iw_cq *rchp, | |||
1084 | 1084 | ||
1085 | c4iw_flush_hw_cq(rchp); | 1085 | c4iw_flush_hw_cq(rchp); |
1086 | c4iw_count_rcqes(&rchp->cq, &qhp->wq, &count); | 1086 | c4iw_count_rcqes(&rchp->cq, &qhp->wq, &count); |
1087 | flushed = c4iw_flush_rq(&qhp->wq, &rchp->cq, count); | 1087 | rq_flushed = c4iw_flush_rq(&qhp->wq, &rchp->cq, count); |
1088 | spin_unlock(&qhp->lock); | 1088 | spin_unlock(&qhp->lock); |
1089 | spin_unlock_irqrestore(&rchp->lock, flag); | 1089 | spin_unlock_irqrestore(&rchp->lock, flag); |
1090 | if (flushed) { | ||
1091 | spin_lock_irqsave(&rchp->comp_handler_lock, flag); | ||
1092 | (*rchp->ibcq.comp_handler)(&rchp->ibcq, rchp->ibcq.cq_context); | ||
1093 | spin_unlock_irqrestore(&rchp->comp_handler_lock, flag); | ||
1094 | } | ||
1095 | 1090 | ||
1096 | /* locking hierarchy: cq lock first, then qp lock. */ | 1091 | /* locking hierarchy: cq lock first, then qp lock. */ |
1097 | spin_lock_irqsave(&schp->lock, flag); | 1092 | spin_lock_irqsave(&schp->lock, flag); |
1098 | spin_lock(&qhp->lock); | 1093 | spin_lock(&qhp->lock); |
1099 | if (schp != rchp) | 1094 | if (schp != rchp) |
1100 | c4iw_flush_hw_cq(schp); | 1095 | c4iw_flush_hw_cq(schp); |
1101 | flushed = c4iw_flush_sq(qhp); | 1096 | sq_flushed = c4iw_flush_sq(qhp); |
1102 | spin_unlock(&qhp->lock); | 1097 | spin_unlock(&qhp->lock); |
1103 | spin_unlock_irqrestore(&schp->lock, flag); | 1098 | spin_unlock_irqrestore(&schp->lock, flag); |
1104 | if (flushed) { | 1099 | |
1105 | spin_lock_irqsave(&schp->comp_handler_lock, flag); | 1100 | if (schp == rchp) { |
1106 | (*schp->ibcq.comp_handler)(&schp->ibcq, schp->ibcq.cq_context); | 1101 | if (t4_clear_cq_armed(&rchp->cq) && |
1107 | spin_unlock_irqrestore(&schp->comp_handler_lock, flag); | 1102 | (rq_flushed || sq_flushed)) { |
1103 | spin_lock_irqsave(&rchp->comp_handler_lock, flag); | ||
1104 | (*rchp->ibcq.comp_handler)(&rchp->ibcq, | ||
1105 | rchp->ibcq.cq_context); | ||
1106 | spin_unlock_irqrestore(&rchp->comp_handler_lock, flag); | ||
1107 | } | ||
1108 | } else { | ||
1109 | if (t4_clear_cq_armed(&rchp->cq) && rq_flushed) { | ||
1110 | spin_lock_irqsave(&rchp->comp_handler_lock, flag); | ||
1111 | (*rchp->ibcq.comp_handler)(&rchp->ibcq, | ||
1112 | rchp->ibcq.cq_context); | ||
1113 | spin_unlock_irqrestore(&rchp->comp_handler_lock, flag); | ||
1114 | } | ||
1115 | if (t4_clear_cq_armed(&schp->cq) && sq_flushed) { | ||
1116 | spin_lock_irqsave(&schp->comp_handler_lock, flag); | ||
1117 | (*schp->ibcq.comp_handler)(&schp->ibcq, | ||
1118 | schp->ibcq.cq_context); | ||
1119 | spin_unlock_irqrestore(&schp->comp_handler_lock, flag); | ||
1120 | } | ||
1108 | } | 1121 | } |
1109 | } | 1122 | } |
1110 | 1123 | ||
diff --git a/drivers/infiniband/hw/cxgb4/t4.h b/drivers/infiniband/hw/cxgb4/t4.h index 68b0a6bf4eb0..d8d7fa3e446d 100644 --- a/drivers/infiniband/hw/cxgb4/t4.h +++ b/drivers/infiniband/hw/cxgb4/t4.h | |||
@@ -531,6 +531,10 @@ static inline int t4_wq_db_enabled(struct t4_wq *wq) | |||
531 | return !wq->rq.queue[wq->rq.size].status.db_off; | 531 | return !wq->rq.queue[wq->rq.size].status.db_off; |
532 | } | 532 | } |
533 | 533 | ||
534 | enum t4_cq_flags { | ||
535 | CQ_ARMED = 1, | ||
536 | }; | ||
537 | |||
534 | struct t4_cq { | 538 | struct t4_cq { |
535 | struct t4_cqe *queue; | 539 | struct t4_cqe *queue; |
536 | dma_addr_t dma_addr; | 540 | dma_addr_t dma_addr; |
@@ -551,12 +555,19 @@ struct t4_cq { | |||
551 | u16 cidx_inc; | 555 | u16 cidx_inc; |
552 | u8 gen; | 556 | u8 gen; |
553 | u8 error; | 557 | u8 error; |
558 | unsigned long flags; | ||
554 | }; | 559 | }; |
555 | 560 | ||
561 | static inline int t4_clear_cq_armed(struct t4_cq *cq) | ||
562 | { | ||
563 | return test_and_clear_bit(CQ_ARMED, &cq->flags); | ||
564 | } | ||
565 | |||
556 | static inline int t4_arm_cq(struct t4_cq *cq, int se) | 566 | static inline int t4_arm_cq(struct t4_cq *cq, int se) |
557 | { | 567 | { |
558 | u32 val; | 568 | u32 val; |
559 | 569 | ||
570 | set_bit(CQ_ARMED, &cq->flags); | ||
560 | while (cq->cidx_inc > CIDXINC_MASK) { | 571 | while (cq->cidx_inc > CIDXINC_MASK) { |
561 | val = SEINTARM(0) | CIDXINC(CIDXINC_MASK) | TIMERREG(7) | | 572 | val = SEINTARM(0) | CIDXINC(CIDXINC_MASK) | TIMERREG(7) | |
562 | INGRESSQID(cq->cqid); | 573 | INGRESSQID(cq->cqid); |