IB/ipath: Shadow the gpio_mask register
authorArthur Jones <arthur.jones@qlogic.com>
Thu, 10 May 2007 19:10:49 +0000 (12:10 -0700)
committerRoland Dreier <rolandd@cisco.com>
Mon, 14 May 2007 20:22:42 +0000 (13:22 -0700)
Once upon a time, GPIO interrupts were rare.  But then a chip bug in
the waldo series forced the use of a GPIO interrupt to signal packet
reception.  This greatly increased the frequency of GPIO interrupts
which have the gpio_mask bits set on the waldo chips.  Other bits in
the gpio_status register are used for I2C clock and data lines, these
bits are usually on.  An "unlikely" annotation leftover from the old
days was improperly applied to these bits, and an unnecessary chip
mmio read was being accessed in the interrupt fast path on waldo.

Remove the stagnant unlikely annotation in the interrupt handler and
keep a shadow copy of the gpio_mask register to avoid the slow mmio
read when testing for interruptable GPIO bits.

Signed-off-by: Arthur Jones <arthur.jones@qlogic.com>
Signed-off-by: Roland Dreier <rolandd@cisco.com>
drivers/infiniband/hw/ipath/ipath_iba6120.c
drivers/infiniband/hw/ipath/ipath_intr.c
drivers/infiniband/hw/ipath/ipath_kernel.h
drivers/infiniband/hw/ipath/ipath_verbs.c

index 1b9c30857754e506495cf6291bae5ff938d8437b..4e2e3dfeb2c8c3f77cb245ee91c2bbeeff470380 100644 (file)
@@ -747,7 +747,6 @@ static void ipath_pe_quiet_serdes(struct ipath_devdata *dd)
 
 static int ipath_pe_intconfig(struct ipath_devdata *dd)
 {
-       u64 val;
        u32 chiprev;
 
        /*
@@ -760,9 +759,9 @@ static int ipath_pe_intconfig(struct ipath_devdata *dd)
        if ((chiprev & INFINIPATH_R_CHIPREVMINOR_MASK) > 1) {
                /* Rev2+ reports extra errors via internal GPIO pins */
                dd->ipath_flags |= IPATH_GPIO_ERRINTRS;
-               val = ipath_read_kreg64(dd, dd->ipath_kregs->kr_gpio_mask);
-               val |= IPATH_GPIO_ERRINTR_MASK;
-               ipath_write_kreg( dd, dd->ipath_kregs->kr_gpio_mask, val);
+               dd->ipath_gpio_mask |= IPATH_GPIO_ERRINTR_MASK;
+               ipath_write_kreg(dd, dd->ipath_kregs->kr_gpio_mask,
+                                dd->ipath_gpio_mask);
        }
        return 0;
 }
index 45d033169c6e5fe765dc402f0981db2cdc5717d6..a90d3b5699c46cc1169faf99ef3c72fbc4a92772 100644 (file)
@@ -1056,7 +1056,7 @@ irqreturn_t ipath_intr(int irq, void *data)
                        gpiostatus &= ~(1 << IPATH_GPIO_PORT0_BIT);
                        chk0rcv = 1;
                }
-               if (unlikely(gpiostatus)) {
+               if (gpiostatus) {
                        /*
                         * Some unexpected bits remain. If they could have
                         * caused the interrupt, complain and clear.
@@ -1065,9 +1065,8 @@ irqreturn_t ipath_intr(int irq, void *data)
                         * GPIO interrupts, possibly on a "three strikes"
                         * basis.
                         */
-                       u32 mask;
-                       mask = ipath_read_kreg32(
-                               dd, dd->ipath_kregs->kr_gpio_mask);
+                       const u32 mask = (u32) dd->ipath_gpio_mask;
+
                        if (mask & gpiostatus) {
                                ipath_dbg("Unexpected GPIO IRQ bits %x\n",
                                  gpiostatus & mask);
index e900c2593f446b58ed41426c12b5538e629c2758..12194f3dd8cc2b12c9909a3e212b7f8a06c5b93b 100644 (file)
@@ -397,6 +397,8 @@ struct ipath_devdata {
        unsigned long ipath_pioavailshadow[8];
        /* shadow of kr_gpio_out, for rmw ops */
        u64 ipath_gpio_out;
+       /* shadow the gpio mask register */
+       u64 ipath_gpio_mask;
        /* kr_revision shadow */
        u64 ipath_revision;
        /*
index 12933e77c7e90bc2f93cbbc16dab1adfe9e43698..bb70845279b8148aba4f2dcf4a769b9429efda48 100644 (file)
@@ -1387,13 +1387,12 @@ static int enable_timer(struct ipath_devdata *dd)
         * processing.
         */
        if (dd->ipath_flags & IPATH_GPIO_INTR) {
-               u64 val;
                ipath_write_kreg(dd, dd->ipath_kregs->kr_debugportselect,
                                 0x2074076542310ULL);
                /* Enable GPIO bit 2 interrupt */
-               val = ipath_read_kreg64(dd, dd->ipath_kregs->kr_gpio_mask);
-               val |= (u64) (1 << IPATH_GPIO_PORT0_BIT);
-               ipath_write_kreg( dd, dd->ipath_kregs->kr_gpio_mask, val);
+               dd->ipath_gpio_mask |= (u64) (1 << IPATH_GPIO_PORT0_BIT);
+               ipath_write_kreg(dd, dd->ipath_kregs->kr_gpio_mask,
+                                dd->ipath_gpio_mask);
        }
 
        init_timer(&dd->verbs_timer);
@@ -1412,8 +1411,9 @@ static int disable_timer(struct ipath_devdata *dd)
                 u64 val;
                 /* Disable GPIO bit 2 interrupt */
                 val = ipath_read_kreg64(dd, dd->ipath_kregs->kr_gpio_mask);
-                val &= ~((u64) (1 << IPATH_GPIO_PORT0_BIT));
-                ipath_write_kreg( dd, dd->ipath_kregs->kr_gpio_mask, val);
+               dd->ipath_gpio_mask &= ~((u64) (1 << IPATH_GPIO_PORT0_BIT));
+               ipath_write_kreg(dd, dd->ipath_kregs->kr_gpio_mask,
+                                dd->ipath_gpio_mask);
                /*
                 * We might want to undo changes to debugportselect,
                 * but how?