There are 2 limits that need to be taken into account when arming the CQ. 1) the GTS register limits the delta idx to <= 0xfff. 2) T4 HW limits it to < cq size.
Update t4_arm_cq() to account for these limits. Signed-off-by: Steve Wise <sw...@opengridcomputing.com> --- drivers/infiniband/hw/cxgb4/t4.h | 24 +++++++++++++++++++----- 1 files changed, 19 insertions(+), 5 deletions(-) diff --git a/drivers/infiniband/hw/cxgb4/t4.h b/drivers/infiniband/hw/cxgb4/t4.h index aeeb005..7f04dc5 100644 --- a/drivers/infiniband/hw/cxgb4/t4.h +++ b/drivers/infiniband/hw/cxgb4/t4.h @@ -449,11 +449,25 @@ struct t4_cq { static inline int t4_arm_cq(struct t4_cq *cq, int se) { u32 val; - - val = SEINTARM(se) | CIDXINC(cq->cidx_inc) | TIMERREG(6) | - INGRESSQID(cq->cqid); - cq->cidx_inc = 0; - writel(val, cq->gts); + u16 inc; + + do { + /* + * inc must be less the both the max update value -and- + * the size of the CQ. + */ + inc = cq->cidx_inc <= CIDXINC_MASK ? cq->cidx_inc : + CIDXINC_MASK; + inc = inc <= (cq->size - 1) ? inc : (cq->size - 1); + if (inc == cq->cidx_inc) + val = SEINTARM(se) | CIDXINC(inc) | TIMERREG(6) | + INGRESSQID(cq->cqid); + else + val = SEINTARM(0) | CIDXINC(inc) | TIMERREG(7) | + INGRESSQID(cq->cqid); + cq->cidx_inc -= inc; + writel(val, cq->gts); + } while (cq->cidx_inc); return 0; } -- To unsubscribe from this list: send the line "unsubscribe linux-rdma" in the body of a message to majord...@vger.kernel.org More majordomo info at http://vger.kernel.org/majordomo-info.html