]> www.pilppa.org Git - linux-2.6-omap-h63xx.git/blobdiff - drivers/infiniband/hw/ipath/ipath_intr.c
IB/ipath: Misc sparse warning cleanup
[linux-2.6-omap-h63xx.git] / drivers / infiniband / hw / ipath / ipath_intr.c
index b29fe7e9b11a598686052f3797b8f0b2c1c6f3d1..3b89952066573edaa41fd53e3d9401ff247df1c2 100644 (file)
@@ -59,9 +59,11 @@ static void ipath_clrpiobuf(struct ipath_devdata *dd, u32 pnum)
        dev_info(&dd->pcidev->dev,
                "Rewrite PIO buffer %u, to recover from parity error\n",
                pnum);
-       *pbuf = dwcnt+1; /* no flush required, since already in freeze */
-       while(--dwcnt)
-               *pbuf++ = 0;
+
+       /* no flush required, since already in freeze */
+       writel(dwcnt + 1, pbuf);
+       while (--dwcnt)
+               writel(0, pbuf++);
 }
 
 /*
@@ -275,6 +277,16 @@ static char *ib_linkstate(u32 linkstate)
        return ret;
 }
 
+void signal_ib_event(struct ipath_devdata *dd, enum ib_event_type ev)
+{
+       struct ib_event event;
+
+       event.device = &dd->verbs_dev->ibdev;
+       event.element.port_num = 1;
+       event.event = ev;
+       ib_dispatch_event(&event);
+}
+
 static void handle_e_ibstatuschanged(struct ipath_devdata *dd,
                                     ipath_err_t errs, int noprint)
 {
@@ -373,6 +385,8 @@ static void handle_e_ibstatuschanged(struct ipath_devdata *dd,
        dd->ipath_ibpollcnt = 0;        /* some state other than 2 or 3 */
        ipath_stats.sps_iblink++;
        if (ltstate != INFINIPATH_IBCS_LT_STATE_LINKUP) {
+               if (dd->ipath_flags & IPATH_LINKACTIVE)
+                       signal_ib_event(dd, IB_EVENT_PORT_ERR);
                dd->ipath_flags |= IPATH_LINKDOWN;
                dd->ipath_flags &= ~(IPATH_LINKUNK | IPATH_LINKINIT
                                     | IPATH_LINKACTIVE |
@@ -405,7 +419,10 @@ static void handle_e_ibstatuschanged(struct ipath_devdata *dd,
                *dd->ipath_statusp |=
                        IPATH_STATUS_IB_READY | IPATH_STATUS_IB_CONF;
                dd->ipath_f_setextled(dd, lstate, ltstate);
+               signal_ib_event(dd, IB_EVENT_PORT_ACTIVE);
        } else if ((val & IPATH_IBSTATE_MASK) == IPATH_IBSTATE_INIT) {
+               if (dd->ipath_flags & IPATH_LINKACTIVE)
+                       signal_ib_event(dd, IB_EVENT_PORT_ERR);
                /*
                 * set INIT and DOWN.  Down is checked by most of the other
                 * code, but INIT is useful to know in a few places.
@@ -418,6 +435,8 @@ static void handle_e_ibstatuschanged(struct ipath_devdata *dd,
                                        | IPATH_STATUS_IB_READY);
                dd->ipath_f_setextled(dd, lstate, ltstate);
        } else if ((val & IPATH_IBSTATE_MASK) == IPATH_IBSTATE_ARM) {
+               if (dd->ipath_flags & IPATH_LINKACTIVE)
+                       signal_ib_event(dd, IB_EVENT_PORT_ERR);
                dd->ipath_flags |= IPATH_LINKARMED;
                dd->ipath_flags &=
                        ~(IPATH_LINKUNK | IPATH_LINKDOWN | IPATH_LINKINIT |
@@ -436,7 +455,7 @@ skip_ibchange:
 }
 
 static void handle_supp_msgs(struct ipath_devdata *dd,
-                            unsigned supp_msgs, char msg[512])
+                            unsigned supp_msgs, char *msg, int msgsz)
 {
        /*
         * Print the message unless it's ibc status change only, which
@@ -444,9 +463,9 @@ static void handle_supp_msgs(struct ipath_devdata *dd,
         */
        if (dd->ipath_lasterror & ~INFINIPATH_E_IBSTATUSCHANGED) {
                int iserr;
-               iserr = ipath_decode_err(msg, sizeof msg,
-                               dd->ipath_lasterror &
-                               ~INFINIPATH_E_IBSTATUSCHANGED);
+               iserr = ipath_decode_err(msg, msgsz,
+                                        dd->ipath_lasterror &
+                                        ~INFINIPATH_E_IBSTATUSCHANGED);
                if (dd->ipath_lasterror &
                        ~(INFINIPATH_E_RRCVEGRFULL |
                        INFINIPATH_E_RRCVHDRFULL | INFINIPATH_E_PKTERRS))
@@ -475,8 +494,8 @@ static void handle_supp_msgs(struct ipath_devdata *dd,
 }
 
 static unsigned handle_frequent_errors(struct ipath_devdata *dd,
-                                      ipath_err_t errs, char msg[512],
-                                      int *noprint)
+                                      ipath_err_t errs, char *msg,
+                                      int msgsz, int *noprint)
 {
        unsigned long nc;
        static unsigned long nextmsg_time;
@@ -495,7 +514,7 @@ static unsigned handle_frequent_errors(struct ipath_devdata *dd,
                                nextmsg_time = nc + HZ * 3;
                }
                else if (supp_msgs) {
-                       handle_supp_msgs(dd, supp_msgs, msg);
+                       handle_supp_msgs(dd, supp_msgs, msg, msgsz);
                        supp_msgs = 0;
                        nmsgs = 0;
                }
@@ -508,14 +527,14 @@ static unsigned handle_frequent_errors(struct ipath_devdata *dd,
 
 static int handle_errors(struct ipath_devdata *dd, ipath_err_t errs)
 {
-       char msg[512];
+       char msg[128];
        u64 ignore_this_time = 0;
        int i, iserr = 0;
        int chkerrpkts = 0, noprint = 0;
        unsigned supp_msgs;
        int log_idx;
 
-       supp_msgs = handle_frequent_errors(dd, errs, msg, &noprint);
+       supp_msgs = handle_frequent_errors(dd, errs, msg, sizeof msg, &noprint);
 
        /* don't report errors that are masked */
        errs &= ~dd->ipath_maskederrs;
@@ -666,7 +685,7 @@ static int handle_errors(struct ipath_devdata *dd, ipath_err_t errs)
                for (i = 0; i < dd->ipath_cfgports; i++) {
                        struct ipath_portdata *pd = dd->ipath_pd[i];
                        if (i == 0) {
-                               hd = dd->ipath_port0head;
+                               hd = pd->port_head;
                                tl = (u32) le64_to_cpu(
                                        *dd->ipath_hdrqtailptr);
                        } else if (pd && pd->port_cnt &&
@@ -676,7 +695,7 @@ static int handle_errors(struct ipath_devdata *dd, ipath_err_t errs)
                                 * except kernel
                                 */
                                tl = *(u64 *) pd->port_rcvhdrtail_kvaddr;
-                               if (tl == dd->ipath_lastrcvhdrqtails[i])
+                               if (tl == pd->port_lastrcvhdrqtail)
                                        continue;
                                hd = ipath_read_ureg32(dd, ur_rcvhdrhead,
                                                       i);
@@ -686,23 +705,17 @@ static int handle_errors(struct ipath_devdata *dd, ipath_err_t errs)
                            (!hd && tl == dd->ipath_hdrqlast)) {
                                if (i == 0)
                                        chkerrpkts = 1;
-                               dd->ipath_lastrcvhdrqtails[i] = tl;
+                               pd->port_lastrcvhdrqtail = 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);
                        }
                }
        }
        if (errs & INFINIPATH_E_RRCVEGRFULL) {
+               struct ipath_portdata *pd = dd->ipath_pd[0];
+
                /*
                 * since this is of less importance and not likely to
                 * happen without also getting hdrfull, only count
@@ -710,7 +723,7 @@ static int handle_errors(struct ipath_devdata *dd, ipath_err_t errs)
                 * vs user)
                 */
                ipath_stats.sps_etidfull++;
-               if (dd->ipath_port0head !=
+               if (pd->port_head !=
                    (u32) le64_to_cpu(*dd->ipath_hdrqtailptr))
                        chkerrpkts = 1;
        }
@@ -786,6 +799,7 @@ void ipath_clear_freeze(struct ipath_devdata *dd)
 {
        int i, im;
        __le64 val;
+       unsigned long flags;
 
        /* disable error interrupts, to avoid confusion */
        ipath_write_kreg(dd, dd->ipath_kregs->kr_errormask, 0ULL);
@@ -804,11 +818,14 @@ void ipath_clear_freeze(struct ipath_devdata *dd)
                         dd->ipath_control);
 
        /* ensure pio avail updates continue */
+       spin_lock_irqsave(&dd->ipath_sendctrl_lock, flags);
        ipath_write_kreg(dd, dd->ipath_kregs->kr_sendctrl,
                 dd->ipath_sendctrl & ~INFINIPATH_S_PIOBUFAVAILUPD);
        ipath_read_kreg64(dd, dd->ipath_kregs->kr_scratch);
        ipath_write_kreg(dd, dd->ipath_kregs->kr_sendctrl,
-                dd->ipath_sendctrl);
+                        dd->ipath_sendctrl);
+       ipath_read_kreg64(dd, dd->ipath_kregs->kr_scratch);
+       spin_unlock_irqrestore(&dd->ipath_sendctrl_lock, flags);
 
        /*
         * We just enabled pioavailupdate, so dma copy is almost certainly
@@ -816,8 +833,8 @@ 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/sizeof(u64))+im);
+               im = i > 3 ? i ^ 1 : i;
+               val = ipath_read_kreg64(dd, (0x1000 / sizeof(u64)) + im);
                dd->ipath_pioavailregs_dma[i] = dd->ipath_pioavailshadow[i]
                        = le64_to_cpu(val);
        }
@@ -840,7 +857,7 @@ void ipath_clear_freeze(struct ipath_devdata *dd)
 
 /* this is separate to allow for better optimization of ipath_intr() */
 
-static void ipath_bad_intr(struct ipath_devdata *dd, u32 * unexpectp)
+static noinline void ipath_bad_intr(struct ipath_devdata *dd, u32 *unexpectp)
 {
        /*
         * sometimes happen during driver init and unload, don't want
@@ -868,7 +885,7 @@ static void ipath_bad_intr(struct ipath_devdata *dd, u32 * unexpectp)
                                dd->ipath_f_free_irq(dd);
                        }
                }
-               if (ipath_read_kreg32(dd, dd->ipath_kregs->kr_intmask)) {
+               if (ipath_read_ireg(dd, dd->ipath_kregs->kr_intmask)) {
                        ipath_dev_err(dd, "%u unexpected interrupts, "
                                      "disabling interrupts completely\n",
                                      *unexpectp);
@@ -883,7 +900,7 @@ static void ipath_bad_intr(struct ipath_devdata *dd, u32 * unexpectp)
                          "ignoring\n");
 }
 
-static void ipath_bad_regread(struct ipath_devdata *dd)
+static noinline void ipath_bad_regread(struct ipath_devdata *dd)
 {
        static int allbits;
 
@@ -911,31 +928,9 @@ static void ipath_bad_regread(struct ipath_devdata *dd)
        }
 }
 
-static void handle_port_pioavail(struct ipath_devdata *dd)
-{
-       u32 i;
-       /*
-        * start from port 1, since for now port 0  is never using
-        * wait_event for PIO
-        */
-       for (i = 1; dd->ipath_portpiowait && i < dd->ipath_cfgports; i++) {
-               struct ipath_portdata *pd = dd->ipath_pd[i];
-
-               if (pd && pd->port_cnt &&
-                   dd->ipath_portpiowait & (1U << i)) {
-                       clear_bit(i, &dd->ipath_portpiowait);
-                       if (test_bit(IPATH_PORT_WAITING_PIO,
-                                    &pd->port_flag)) {
-                               clear_bit(IPATH_PORT_WAITING_PIO,
-                                         &pd->port_flag);
-                               wake_up_interruptible(&pd->port_wait);
-                       }
-               }
-       }
-}
-
 static void handle_layer_pioavail(struct ipath_devdata *dd)
 {
+       unsigned long flags;
        int ret;
 
        ret = ipath_ib_piobufavail(dd->verbs_dev);
@@ -944,9 +939,12 @@ static void handle_layer_pioavail(struct ipath_devdata *dd)
 
        return;
 set:
-       set_bit(IPATH_S_PIOINTBUFAVAIL, &dd->ipath_sendctrl);
+       spin_lock_irqsave(&dd->ipath_sendctrl_lock, flags);
+       dd->ipath_sendctrl |= INFINIPATH_S_PIOINTBUFAVAIL;
        ipath_write_kreg(dd, dd->ipath_kregs->kr_sendctrl,
                         dd->ipath_sendctrl);
+       ipath_read_kreg64(dd, dd->ipath_kregs->kr_scratch);
+       spin_unlock_irqrestore(&dd->ipath_sendctrl_lock, flags);
 }
 
 /*
@@ -960,6 +958,16 @@ static void handle_urcv(struct ipath_devdata *dd, u32 istat)
        int i;
        int rcvdint = 0;
 
+       /*
+        * test_and_clear_bit(IPATH_PORT_WAITING_RCV) and
+        * test_and_clear_bit(IPATH_PORT_WAITING_URG) below
+        * would both like timely updates of the bits so that
+        * we don't pass them by unnecessarily.  the rmb()
+        * here ensures that we see them promptly -- the
+        * corresponding wmb()'s are in ipath_poll_urgent()
+        * and ipath_poll_next()...
+        */
+       rmb();
        portr = ((istat >> INFINIPATH_I_RCVAVAIL_SHIFT) &
                 dd->ipath_i_rcvavail_mask)
                | ((istat >> INFINIPATH_I_RCVURG_SHIFT) &
@@ -967,22 +975,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);
-                               clear_bit(i + INFINIPATH_R_INTRAVAIL_SHIFT,
+                       if (test_and_clear_bit(IPATH_PORT_WAITING_RCV,
+                                              &pd->port_flag)) {
+                               clear_bit(i + dd->ipath_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);
                        }
                }
@@ -1035,7 +1036,7 @@ irqreturn_t ipath_intr(int irq, void *data)
                goto bail;
        }
 
-       istat = ipath_read_kreg32(dd, dd->ipath_kregs->kr_intstatus);
+       istat = ipath_read_ireg(dd, dd->ipath_kregs->kr_intstatus);
 
        if (unlikely(!istat)) {
                ipath_stats.sps_nullintr++;
@@ -1085,8 +1086,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;
@@ -1137,10 +1138,8 @@ irqreturn_t ipath_intr(int irq, void *data)
                        /*
                         * Some unexpected bits remain. If they could have
                         * caused the interrupt, complain and clear.
-                        * MEA: this is almost certainly non-ideal.
-                        * we should look into auto-disable of unexpected
-                        * GPIO interrupts, possibly on a "three strikes"
-                        * basis.
+                        * To avoid repetition of this condition, also clear
+                        * the mask. It is almost certainly due to error.
                         */
                        const u32 mask = (u32) dd->ipath_gpio_mask;
 
@@ -1148,6 +1147,10 @@ irqreturn_t ipath_intr(int irq, void *data)
                                ipath_dbg("Unexpected GPIO IRQ bits %x\n",
                                  gpiostatus & mask);
                                to_clear |= (gpiostatus & mask);
+                               dd->ipath_gpio_mask &= ~(gpiostatus & mask);
+                               ipath_write_kreg(dd,
+                                       dd->ipath_kregs->kr_gpio_mask,
+                                       dd->ipath_gpio_mask);
                        }
                }
                if (to_clear) {
@@ -1174,7 +1177,7 @@ irqreturn_t ipath_intr(int irq, void *data)
         * for receive are at the bottom.
         */
        if (chk0rcv) {
-               ipath_kreceive(dd);
+               ipath_kreceive(dd->ipath_pd[0]);
                istat &= ~port0rbits;
        }
 
@@ -1185,12 +1188,14 @@ irqreturn_t ipath_intr(int irq, void *data)
                handle_urcv(dd, istat);
 
        if (istat & INFINIPATH_I_SPIOBUFAVAIL) {
-               clear_bit(IPATH_S_PIOINTBUFAVAIL, &dd->ipath_sendctrl);
+               unsigned long flags;
+
+               spin_lock_irqsave(&dd->ipath_sendctrl_lock, flags);
+               dd->ipath_sendctrl &= ~INFINIPATH_S_PIOINTBUFAVAIL;
                ipath_write_kreg(dd, dd->ipath_kregs->kr_sendctrl,
                                 dd->ipath_sendctrl);
-
-               if (dd->ipath_portpiowait)
-                       handle_port_pioavail(dd);
+               ipath_read_kreg64(dd, dd->ipath_kregs->kr_scratch);
+               spin_unlock_irqrestore(&dd->ipath_sendctrl_lock, flags);
 
                handle_layer_pioavail(dd);
        }