RDMA/cxgb4: Fix overflow bug in CQ arm
authorSteve Wise <swise@opengridcomputing.com>
Thu, 20 May 2010 21:57:49 +0000 (16:57 -0500)
committerRoland Dreier <rolandd@cisco.com>
Tue, 25 May 2010 04:08:01 +0000 (21:08 -0700)
- wrap cq->cqidx_inc based on cq size.
- optimize t4_arm_cq logic.

Signed-off-by: Steve Wise <swise@opengridcomputing.com>
Signed-off-by: Roland Dreier <rolandd@cisco.com>
drivers/infiniband/hw/cxgb4/t4.h

index 712bc5620d3ea2af266924b6e61c4df1b3ecf7ef..333abd3c7264f2cc2adab781ca1f49ca07059114 100644 (file)
@@ -449,25 +449,17 @@ struct t4_cq {
 static inline int t4_arm_cq(struct t4_cq *cq, int se)
 {
        u32 val;
-       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;
+
+       while (cq->cidx_inc > CIDXINC_MASK) {
+               val = SEINTARM(0) | CIDXINC(CIDXINC_MASK) | TIMERREG(7) |
+                     INGRESSQID(cq->cqid);
                writel(val, cq->gts);
-       } while (cq->cidx_inc);
+               cq->cidx_inc -= CIDXINC_MASK;
+       }
+       val = SEINTARM(se) | CIDXINC(cq->cidx_inc) | TIMERREG(6) |
+             INGRESSQID(cq->cqid);
+       writel(val, cq->gts);
+       cq->cidx_inc = 0;
        return 0;
 }
 
@@ -488,7 +480,8 @@ static inline void t4_swcq_consume(struct t4_cq *cq)
 static inline void t4_hwcq_consume(struct t4_cq *cq)
 {
        cq->bits_type_ts = cq->queue[cq->cidx].bits_type_ts;
-       cq->cidx_inc++;
+       if (++cq->cidx_inc == cq->size)
+               cq->cidx_inc = 0;
        if (++cq->cidx == cq->size) {
                cq->cidx = 0;
                cq->gen ^= 1;