]> www.pilppa.org Git - linux-2.6-omap-h63xx.git/blobdiff - drivers/infiniband/hw/ipath/ipath_intr.c
IB/ipath: Use counters in ipath_poll and cleanup interrupts in ipath_close
[linux-2.6-omap-h63xx.git] / drivers / infiniband / hw / ipath / ipath_intr.c
index 0c075cf8316ba1c0bd77b5ea043863c9c1e6a05b..61eac8cc0d9f1836909087149c81e8f697fe2d3d 100644 (file)
@@ -517,10 +517,7 @@ static int handle_errors(struct ipath_devdata *dd, ipath_err_t errs)
 
        supp_msgs = handle_frequent_errors(dd, errs, msg, &noprint);
 
-       /*
-        * don't report errors that are masked (includes those always
-        * ignored)
-        */
+       /* don't report errors that are masked */
        errs &= ~dd->ipath_maskederrs;
 
        /* do these first, they are most important */
@@ -566,19 +563,19 @@ static int handle_errors(struct ipath_devdata *dd, ipath_err_t errs)
                 * ones on this particular interrupt, which also isn't great
                 */
                dd->ipath_maskederrs |= dd->ipath_lasterror | errs;
+               dd->ipath_errormask &= ~dd->ipath_maskederrs;
                ipath_write_kreg(dd, dd->ipath_kregs->kr_errormask,
-                                ~dd->ipath_maskederrs);
+                       dd->ipath_errormask);
                s_iserr = ipath_decode_err(msg, sizeof msg,
-                                (dd->ipath_maskederrs & ~dd->
-                                 ipath_ignorederrs));
+                       dd->ipath_maskederrs);
 
-               if ((dd->ipath_maskederrs & ~dd->ipath_ignorederrs) &
+               if (dd->ipath_maskederrs &
                        ~(INFINIPATH_E_RRCVEGRFULL |
                        INFINIPATH_E_RRCVHDRFULL | INFINIPATH_E_PKTERRS))
                        ipath_dev_err(dd, "Temporarily disabling "
                            "error(s) %llx reporting; too frequent (%s)\n",
-                               (unsigned long long) (dd->ipath_maskederrs &
-                               ~dd->ipath_ignorederrs), msg);
+                               (unsigned long long)dd->ipath_maskederrs,
+                               msg);
                else {
                        /*
                         * rcvegrfull and rcvhdrqfull are "normal",
@@ -691,17 +688,9 @@ static int handle_errors(struct ipath_devdata *dd, ipath_err_t errs)
                                        chkerrpkts = 1;
                                dd->ipath_lastrcvhdrqtails[i] = tl;
                                pd->port_hdrqfull++;
-                               if (test_bit(IPATH_PORT_WAITING_OVERFLOW,
-                                            &pd->port_flag)) {
-                                       clear_bit(
-                                         IPATH_PORT_WAITING_OVERFLOW,
-                                         &pd->port_flag);
-                                       set_bit(
-                                         IPATH_PORT_WAITING_OVERFLOW,
-                                         &pd->int_flag);
-                                       wake_up_interruptible(
-                                         &pd->port_wait);
-                               }
+                               /* flush hdrqfull so that poll() sees it */
+                               wmb();
+                               wake_up_interruptible(&pd->port_wait);
                        }
                }
        }
@@ -793,6 +782,9 @@ void ipath_clear_freeze(struct ipath_devdata *dd)
        /* disable error interrupts, to avoid confusion */
        ipath_write_kreg(dd, dd->ipath_kregs->kr_errormask, 0ULL);
 
+       /* also disable interrupts; errormask is sometimes overwriten */
+       ipath_write_kreg(dd, dd->ipath_kregs->kr_intmask, 0ULL);
+
        /*
         * clear all sends, because they have may been
         * completed by usercode while in freeze mode, and
@@ -817,7 +809,7 @@ void ipath_clear_freeze(struct ipath_devdata *dd)
        for (i = 0; i < dd->ipath_pioavregs; i++) {
                /* deal with 6110 chip bug */
                im = i > 3 ? ((i&1) ? i-1 : i+1) : i;
-               val = ipath_read_kreg64(dd, 0x1000+(im*sizeof(u64)));
+               val = ipath_read_kreg64(dd, (0x1000/sizeof(u64))+im);
                dd->ipath_pioavailregs_dma[i] = dd->ipath_pioavailshadow[i]
                        = le64_to_cpu(val);
        }
@@ -832,7 +824,8 @@ void ipath_clear_freeze(struct ipath_devdata *dd)
        ipath_write_kreg(dd, dd->ipath_kregs->kr_errorclear,
                E_SPKT_ERRS_IGNORE);
        ipath_write_kreg(dd, dd->ipath_kregs->kr_errormask,
-               ~dd->ipath_maskederrs);
+               dd->ipath_errormask);
+       ipath_write_kreg(dd, dd->ipath_kregs->kr_intmask, -1LL);
        ipath_write_kreg(dd, dd->ipath_kregs->kr_intclear, 0ULL);
 }
 
@@ -959,6 +952,8 @@ static void handle_urcv(struct ipath_devdata *dd, u32 istat)
        int i;
        int rcvdint = 0;
 
+       /* test_bit below needs this... */
+       rmb();
        portr = ((istat >> INFINIPATH_I_RCVAVAIL_SHIFT) &
                 dd->ipath_i_rcvavail_mask)
                | ((istat >> INFINIPATH_I_RCVURG_SHIFT) &
@@ -966,22 +961,15 @@ static void handle_urcv(struct ipath_devdata *dd, u32 istat)
        for (i = 1; i < dd->ipath_cfgports; i++) {
                struct ipath_portdata *pd = dd->ipath_pd[i];
                if (portr & (1 << i) && pd && pd->port_cnt) {
-                       if (test_bit(IPATH_PORT_WAITING_RCV,
-                                    &pd->port_flag)) {
-                               clear_bit(IPATH_PORT_WAITING_RCV,
-                                         &pd->port_flag);
-                               set_bit(IPATH_PORT_WAITING_RCV,
-                                       &pd->int_flag);
+                       if (test_and_clear_bit(IPATH_PORT_WAITING_RCV,
+                                              &pd->port_flag)) {
                                clear_bit(i + INFINIPATH_R_INTRAVAIL_SHIFT,
                                          &dd->ipath_rcvctrl);
                                wake_up_interruptible(&pd->port_wait);
                                rcvdint = 1;
-                       } else if (test_bit(IPATH_PORT_WAITING_URG,
-                                           &pd->port_flag)) {
-                               clear_bit(IPATH_PORT_WAITING_URG,
-                                         &pd->port_flag);
-                               set_bit(IPATH_PORT_WAITING_URG,
-                                       &pd->int_flag);
+                       } else if (test_and_clear_bit(IPATH_PORT_WAITING_URG,
+                                                     &pd->port_flag)) {
+                               pd->port_urgent++;
                                wake_up_interruptible(&pd->port_wait);
                        }
                }
@@ -1084,8 +1072,8 @@ irqreturn_t ipath_intr(int irq, void *data)
                 * GPIO_2 indicates (on some HT4xx boards) that a packet
                 *        has arrived for Port 0. Checking for this
                 *        is controlled by flag IPATH_GPIO_INTR.
-                * GPIO_3..5 on IBA6120 Rev2 chips indicate errors
-                *        that we need to count. Checking for this
+                * GPIO_3..5 on IBA6120 Rev2 and IBA6110 Rev4 chips indicate
+                *        errors that we need to count. Checking for this
                 *        is controlled by flag IPATH_GPIO_ERRINTRS.
                 */
                u32 gpiostatus;