]> pilppa.org Git - linux-2.6-omap-h63xx.git/blobdiff - drivers/infiniband/hw/ipath/ipath_stats.c
Merge git://git.kernel.org/pub/scm/linux/kernel/git/lethal/sh-2.6
[linux-2.6-omap-h63xx.git] / drivers / infiniband / hw / ipath / ipath_stats.c
index 73ed17d031887cbf5da73d57ee92f0c8b6aeb457..f0271415cd5b19558f7fae74baaef2330a96490d 100644 (file)
@@ -55,7 +55,6 @@ u64 ipath_snap_cntr(struct ipath_devdata *dd, ipath_creg creg)
        u64 val64;
        unsigned long t0, t1;
        u64 ret;
-       unsigned long flags;
 
        t0 = jiffies;
        /* If fast increment counters are only 32 bits, snapshot them,
@@ -92,18 +91,12 @@ u64 ipath_snap_cntr(struct ipath_devdata *dd, ipath_creg creg)
        if (creg == dd->ipath_cregs->cr_wordsendcnt) {
                if (val != dd->ipath_lastsword) {
                        dd->ipath_sword += val - dd->ipath_lastsword;
-                       spin_lock_irqsave(&dd->ipath_eep_st_lock, flags);
-                       dd->ipath_traffic_wds += val - dd->ipath_lastsword;
-                       spin_unlock_irqrestore(&dd->ipath_eep_st_lock, flags);
                        dd->ipath_lastsword = val;
                }
                val64 = dd->ipath_sword;
        } else if (creg == dd->ipath_cregs->cr_wordrcvcnt) {
                if (val != dd->ipath_lastrword) {
                        dd->ipath_rword += val - dd->ipath_lastrword;
-                       spin_lock_irqsave(&dd->ipath_eep_st_lock, flags);
-                       dd->ipath_traffic_wds += val - dd->ipath_lastrword;
-                       spin_unlock_irqrestore(&dd->ipath_eep_st_lock, flags);
                        dd->ipath_lastrword = val;
                }
                val64 = dd->ipath_rword;
@@ -196,6 +189,45 @@ static void ipath_qcheck(struct ipath_devdata *dd)
        }
 }
 
+static void ipath_chk_errormask(struct ipath_devdata *dd)
+{
+       static u32 fixed;
+       u32 ctrl;
+       unsigned long errormask;
+       unsigned long hwerrs;
+
+       if (!dd->ipath_errormask || !(dd->ipath_flags & IPATH_INITTED))
+               return;
+
+       errormask = ipath_read_kreg64(dd, dd->ipath_kregs->kr_errormask);
+
+       if (errormask == dd->ipath_errormask)
+               return;
+       fixed++;
+
+       hwerrs = ipath_read_kreg64(dd, dd->ipath_kregs->kr_hwerrstatus);
+       ctrl = ipath_read_kreg32(dd, dd->ipath_kregs->kr_control);
+
+       ipath_write_kreg(dd, dd->ipath_kregs->kr_errormask,
+               dd->ipath_errormask);
+
+       if ((hwerrs & dd->ipath_hwerrmask) ||
+               (ctrl & INFINIPATH_C_FREEZEMODE)) {
+               /* force re-interrupt of pending events, just in case */
+               ipath_write_kreg(dd, dd->ipath_kregs->kr_hwerrclear, 0ULL);
+               ipath_write_kreg(dd, dd->ipath_kregs->kr_errorclear, 0ULL);
+               ipath_write_kreg(dd, dd->ipath_kregs->kr_intclear, 0ULL);
+               dev_info(&dd->pcidev->dev,
+                       "errormask fixed(%u) %lx -> %lx, ctrl %x hwerr %lx\n",
+                       fixed, errormask, (unsigned long)dd->ipath_errormask,
+                       ctrl, hwerrs);
+       } else
+               ipath_dbg("errormask fixed(%u) %lx -> %lx, no freeze\n",
+                       fixed, errormask,
+                       (unsigned long)dd->ipath_errormask);
+}
+
+
 /**
  * ipath_get_faststats - get word counters from chip before they overflow
  * @opaque - contains a pointer to the infinipath device ipath_devdata
@@ -208,6 +240,7 @@ void ipath_get_faststats(unsigned long opaque)
        u32 val;
        static unsigned cnt;
        unsigned long flags;
+       u64 traffic_wds;
 
        /*
         * don't access the chip while running diags, or memory diags can
@@ -223,12 +256,13 @@ void ipath_get_faststats(unsigned long opaque)
         * exceeding a threshold, so we need to check the word-counts
         * even if they are 64-bit.
         */
-       ipath_snap_cntr(dd, dd->ipath_cregs->cr_wordsendcnt);
-       ipath_snap_cntr(dd, dd->ipath_cregs->cr_wordrcvcnt);
+       traffic_wds = ipath_snap_cntr(dd, dd->ipath_cregs->cr_wordsendcnt) +
+               ipath_snap_cntr(dd, dd->ipath_cregs->cr_wordrcvcnt);
        spin_lock_irqsave(&dd->ipath_eep_st_lock, flags);
-       if (dd->ipath_traffic_wds  >= IPATH_TRAFFIC_ACTIVE_THRESHOLD)
+       traffic_wds -= dd->ipath_traffic_wds;
+       dd->ipath_traffic_wds += traffic_wds;
+       if (traffic_wds  >= IPATH_TRAFFIC_ACTIVE_THRESHOLD)
                atomic_add(5, &dd->ipath_active_time); /* S/B #define */
-       dd->ipath_traffic_wds = 0;
        spin_unlock_irqrestore(&dd->ipath_eep_st_lock, flags);
 
        if (dd->ipath_flags & IPATH_32BITCOUNTERS) {
@@ -251,14 +285,13 @@ void ipath_get_faststats(unsigned long opaque)
                dd->ipath_lasterror = 0;
        if (dd->ipath_lasthwerror)
                dd->ipath_lasthwerror = 0;
-       if ((dd->ipath_maskederrs & ~dd->ipath_ignorederrs)
+       if (dd->ipath_maskederrs
            && time_after(jiffies, dd->ipath_unmasktime)) {
                char ebuf[256];
                int iserr;
                iserr = ipath_decode_err(ebuf, sizeof ebuf,
-                                (dd->ipath_maskederrs & ~dd->
-                                 ipath_ignorederrs));
-               if ((dd->ipath_maskederrs & ~dd->ipath_ignorederrs) &
+                       dd->ipath_maskederrs);
+               if (dd->ipath_maskederrs &
                                ~(INFINIPATH_E_RRCVEGRFULL | INFINIPATH_E_RRCVHDRFULL |
                                INFINIPATH_E_PKTERRS ))
                        ipath_dev_err(dd, "Re-enabling masked errors "
@@ -278,9 +311,12 @@ void ipath_get_faststats(unsigned long opaque)
                                ipath_cdbg(ERRPKT, "Re-enabling packet"
                                                " problem interrupt (%s)\n", ebuf);
                }
-               dd->ipath_maskederrs = dd->ipath_ignorederrs;
+
+               /* re-enable masked errors */
+               dd->ipath_errormask |= dd->ipath_maskederrs;
                ipath_write_kreg(dd, dd->ipath_kregs->kr_errormask,
-                                ~dd->ipath_maskederrs);
+                       dd->ipath_errormask);
+               dd->ipath_maskederrs = 0;
        }
 
        /* limit qfull messages to ~one per minute per port */
@@ -294,6 +330,7 @@ void ipath_get_faststats(unsigned long opaque)
                }
        }
 
+       ipath_chk_errormask(dd);
 done:
        mod_timer(&dd->ipath_stats_timer, jiffies + HZ * 5);
 }