/** * ipath_get_faststats - get word counters from chip before they overflow * @opaque - contains a pointer to the infinipath device ipath_devdata * * called from add_timer */ void ipath_get_faststats(unsigned long opaque) { struct ipath_devdata *dd = (struct ipath_devdata *) opaque; u32 val; static unsigned cnt; unsigned long flags; /* * don't access the chip while running diags, or memory diags can * fail */ if (!dd->ipath_kregbase || !(dd->ipath_flags & IPATH_INITTED) || ipath_diag_inuse) /* but re-arm the timer, for diags case; won't hurt other */ goto done; /* * We now try to maintain a "active timer", based on traffic * 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); spin_lock_irqsave(&dd->ipath_eep_st_lock, flags); if (dd->ipath_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) { ipath_snap_cntr(dd, dd->ipath_cregs->cr_pktsendcnt); ipath_snap_cntr(dd, dd->ipath_cregs->cr_pktrcvcnt); } ipath_qcheck(dd); /* * deal with repeat error suppression. Doesn't really matter if * last error was almost a full interval ago, or just a few usecs * ago; still won't get more than 2 per interval. We may want * longer intervals for this eventually, could do with mod, counter * or separate timer. Also see code in ipath_handle_errors() and * ipath_handle_hwerrors(). */ if (dd->ipath_lasterror) dd->ipath_lasterror = 0; if (dd->ipath_lasthwerror) dd->ipath_lasthwerror = 0; 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); if (dd->ipath_maskederrs & ~(INFINIPATH_E_RRCVEGRFULL | INFINIPATH_E_RRCVHDRFULL | INFINIPATH_E_PKTERRS )) ipath_dev_err(dd, "Re-enabling masked errors " "(%s)\n", ebuf); else { /* * rcvegrfull and rcvhdrqfull are "normal", for some * types of processes (mostly benchmarks) that send * huge numbers of messages, while not processing * them. So only complain about these at debug * level. */ if (iserr) ipath_dbg("Re-enabling queue full errors (%s)\n", ebuf); else ipath_cdbg(ERRPKT, "Re-enabling packet" " problem interrupt (%s)\n", ebuf); } /* re-enable masked errors */ dd->ipath_errormask |= dd->ipath_maskederrs; ipath_write_kreg(dd, dd->ipath_kregs->kr_errormask, dd->ipath_errormask); dd->ipath_maskederrs = 0; } /* limit qfull messages to ~one per minute per port */ if ((++cnt & 0x10)) { for (val = dd->ipath_cfgports - 1; ((int)val) >= 0; val--) { if (dd->ipath_lastegrheads[val] != -1) dd->ipath_lastegrheads[val] = -1; if (dd->ipath_lastrcvhdrqtails[val] != -1) dd->ipath_lastrcvhdrqtails[val] = -1; } } ipath_chk_errormask(dd); done: mod_timer(&dd->ipath_stats_timer, jiffies + HZ * 5); }
/** * ipath_get_faststats - get word counters from chip before they overflow * @opaque - contains a pointer to the infinipath device ipath_devdata * * called from add_timer */ void ipath_get_faststats(unsigned long opaque) { struct ipath_devdata *dd = (struct ipath_devdata *) opaque; u32 val; static unsigned cnt; /* * don't access the chip while running diags, or memory diags can * fail */ if (!dd->ipath_kregbase || !(dd->ipath_flags & IPATH_PRESENT) || ipath_diag_inuse) /* but re-arm the timer, for diags case; won't hurt other */ goto done; if (dd->ipath_flags & IPATH_32BITCOUNTERS) { ipath_snap_cntr(dd, dd->ipath_cregs->cr_wordsendcnt); ipath_snap_cntr(dd, dd->ipath_cregs->cr_wordrcvcnt); ipath_snap_cntr(dd, dd->ipath_cregs->cr_pktsendcnt); ipath_snap_cntr(dd, dd->ipath_cregs->cr_pktrcvcnt); } ipath_qcheck(dd); /* * deal with repeat error suppression. Doesn't really matter if * last error was almost a full interval ago, or just a few usecs * ago; still won't get more than 2 per interval. We may want * longer intervals for this eventually, could do with mod, counter * or separate timer. Also see code in ipath_handle_errors() and * ipath_handle_hwerrors(). */ if (dd->ipath_lasterror) dd->ipath_lasterror = 0; if (dd->ipath_lasthwerror) dd->ipath_lasthwerror = 0; if ((dd->ipath_maskederrs & ~dd->ipath_ignorederrs) && time_after(jiffies, dd->ipath_unmasktime)) { char ebuf[256]; ipath_decode_err(ebuf, sizeof ebuf, (dd->ipath_maskederrs & ~dd-> ipath_ignorederrs)); if ((dd->ipath_maskederrs & ~dd->ipath_ignorederrs) & ~(INFINIPATH_E_RRCVEGRFULL | INFINIPATH_E_RRCVHDRFULL)) ipath_dev_err(dd, "Re-enabling masked errors " "(%s)\n", ebuf); else { /* * rcvegrfull and rcvhdrqfull are "normal", for some * types of processes (mostly benchmarks) that send * huge numbers of messages, while not processing * them. So only complain about these at debug * level. */ ipath_dbg("Disabling frequent queue full errors " "(%s)\n", ebuf); } dd->ipath_maskederrs = dd->ipath_ignorederrs; ipath_write_kreg(dd, dd->ipath_kregs->kr_errormask, ~dd->ipath_maskederrs); } /* limit qfull messages to ~one per minute per port */ if ((++cnt & 0x10)) { for (val = dd->ipath_cfgports - 1; ((int)val) >= 0; val--) { if (dd->ipath_lastegrheads[val] != -1) dd->ipath_lastegrheads[val] = -1; if (dd->ipath_lastrcvhdrqtails[val] != -1) dd->ipath_lastrcvhdrqtails[val] = -1; } } if (dd->ipath_nosma_bufs) { dd->ipath_nosma_secs += 5; if (dd->ipath_nosma_secs >= 30) { ipath_cdbg(SMA, "No SMA bufs avail %u seconds; " "cancelling pending sends\n", dd->ipath_nosma_secs); /* * issue an abort as well, in case we have a packet * stuck in launch fifo. This could corrupt an * outgoing user packet in the worst case, * but this is a pretty catastrophic, anyway. */ ipath_write_kreg(dd, dd->ipath_kregs->kr_sendctrl, INFINIPATH_S_ABORT); ipath_disarm_piobufs(dd, dd->ipath_lastport_piobuf, dd->ipath_piobcnt2k + dd->ipath_piobcnt4k - dd->ipath_lastport_piobuf); /* start again, if necessary */ dd->ipath_nosma_secs = 0; } else ipath_cdbg(SMA, "No SMA bufs avail %u tries, " "after %u seconds\n", dd->ipath_nosma_bufs, dd->ipath_nosma_secs); } done: mod_timer(&dd->ipath_stats_timer, jiffies + HZ * 5); }