IB/qib: Fix interrupt mitigation
authorMike Marciniszyn <mike.marciniszyn@qlogic.com>
Tue, 11 Jan 2011 01:42:21 +0000 (17:42 -0800)
committerRoland Dreier <rolandd@cisco.com>
Tue, 11 Jan 2011 01:42:21 +0000 (17:42 -0800)
For SusieQ we need to write to the interrupt timer register before
updating the header queue head with interrupt count.  This is to
ensure that the timer is enabled properly and a receive available
interrupt is delivered.  Otherwise this interrupt can be lost if the
receiver header/eager queues are full before the timer is enabled.

Signed-off-by: Mike Marciniszyn <mike.marciniszyn@qlogic.com>
Signed-off-by: Roland Dreier <rolandd@cisco.com>
drivers/infiniband/hw/qib/qib.h
drivers/infiniband/hw/qib/qib_driver.c
drivers/infiniband/hw/qib/qib_iba6120.c
drivers/infiniband/hw/qib/qib_iba7220.c
drivers/infiniband/hw/qib/qib_iba7322.c

index 64c9e7d02d4a3e667bebf099fd6ed93160329f22..73225eee3cc60c31e239a5c8a9cfab87cd14a4d1 100644 (file)
@@ -766,7 +766,7 @@ struct qib_devdata {
        void (*f_sdma_hw_start_up)(struct qib_pportdata *);
        void (*f_sdma_init_early)(struct qib_pportdata *);
        void (*f_set_cntr_sample)(struct qib_pportdata *, u32, u32);
-       void (*f_update_usrhead)(struct qib_ctxtdata *, u64, u32, u32);
+       void (*f_update_usrhead)(struct qib_ctxtdata *, u64, u32, u32, u32);
        u32 (*f_hdrqempty)(struct qib_ctxtdata *);
        u64 (*f_portcntr)(struct qib_pportdata *, u32);
        u32 (*f_read_cntrs)(struct qib_devdata *, loff_t, char **,
index 3ed0d5a9a566f14c6c8c708ab6e302db3c3bbc9c..816a6bdc0b1c76473801cd808cf92341ddf065f0 100644 (file)
@@ -410,7 +410,7 @@ move_along:
                 */
                lval = l;
                if (!last && !(i & 0xf)) {
-                       dd->f_update_usrhead(rcd, lval, updegr, etail);
+                       dd->f_update_usrhead(rcd, lval, updegr, etail, i);
                        updegr = 0;
                }
        }
@@ -452,7 +452,7 @@ bail:
         * if no packets were processed.
         */
        lval = (u64)rcd->head | dd->rhdrhead_intr_off;
-       dd->f_update_usrhead(rcd, lval, updegr, etail);
+       dd->f_update_usrhead(rcd, lval, updegr, etail, i);
        return crcs;
 }
 
index a5e29dbb9537b128906aae8cb811c6f016c1f42b..774dea897e9c08b8dea72f2557203bcfa60f484c 100644 (file)
@@ -2074,7 +2074,7 @@ static void qib_6120_config_ctxts(struct qib_devdata *dd)
 }
 
 static void qib_update_6120_usrhead(struct qib_ctxtdata *rcd, u64 hd,
-                                   u32 updegr, u32 egrhd)
+                                   u32 updegr, u32 egrhd, u32 npkts)
 {
        qib_write_ureg(rcd->dd, ur_rcvhdrhead, hd, rcd->ctxt);
        if (updegr)
index 6fd8d74e739286b81a196820d6a6330ff21f9400..df49e8e7cc2a640acfdd4d4ba8883aaa58258d52 100644 (file)
@@ -2703,7 +2703,7 @@ static int qib_7220_set_loopback(struct qib_pportdata *ppd, const char *what)
 }
 
 static void qib_update_7220_usrhead(struct qib_ctxtdata *rcd, u64 hd,
-                                   u32 updegr, u32 egrhd)
+                                   u32 updegr, u32 egrhd, u32 npkts)
 {
        qib_write_ureg(rcd->dd, ur_rcvhdrhead, hd, rcd->ctxt);
        if (updegr)
index a9c8c7235fcde2f1509050ba353661c87f7ff881..9bc6d0835e30ac01f5b03d9064070e5f1a9d97d6 100644 (file)
@@ -2823,7 +2823,6 @@ static irqreturn_t qib_7322intr(int irq, void *data)
                                ctxtrbits &= ~rmask;
                                if (dd->rcd[i]) {
                                        qib_kreceive(dd->rcd[i], NULL, &npkts);
-                                       adjust_rcv_timeout(dd->rcd[i], npkts);
                                }
                        }
                        rmask <<= 1;
@@ -2873,7 +2872,6 @@ static irqreturn_t qib_7322pintr(int irq, void *data)
                       (1ULL << QIB_I_RCVURG_LSB)) << rcd->ctxt);
 
        qib_kreceive(rcd, NULL, &npkts);
-       adjust_rcv_timeout(rcd, npkts);
 
        return IRQ_HANDLED;
 }
@@ -4047,8 +4045,14 @@ static int qib_7322_set_ib_table(struct qib_pportdata *ppd, int which, void *t)
 }
 
 static void qib_update_7322_usrhead(struct qib_ctxtdata *rcd, u64 hd,
-                                   u32 updegr, u32 egrhd)
+                                   u32 updegr, u32 egrhd, u32 npkts)
 {
+       /*
+        * Need to write timeout register before updating rcvhdrhead to ensure
+        * that the timer is enabled on reception of a packet.
+        */
+       if (hd >> IBA7322_HDRHEAD_PKTINT_SHIFT)
+               adjust_rcv_timeout(rcd, npkts);
        qib_write_ureg(rcd->dd, ur_rcvhdrhead, hd, rcd->ctxt);
        qib_write_ureg(rcd->dd, ur_rcvhdrhead, hd, rcd->ctxt);
        if (updegr)