aboutsummaryrefslogtreecommitdiffstats
path: root/drivers/infiniband/hw/ipath/ipath_iba6120.c
diff options
context:
space:
mode:
authorDave Olson <dave.olson@qlogic.com>2008-12-05 11:13:19 -0800
committerRoland Dreier <rolandd@cisco.com>2008-12-05 11:13:19 -0800
commit60e845035a066e81af1a29047530088d59150d8b (patch)
treeb824466835b3d6cf1c8489544094b025d1142f4a /drivers/infiniband/hw/ipath/ipath_iba6120.c
parent890fccb2427d53b48ab9d009fd87d55bcb173f62 (diff)
downloadlinux-60e845035a066e81af1a29047530088d59150d8b.tar.gz
IB/ipath: Don't count IB symbol and link errors unless link is UP
Implement the ignoring of ibsymbol errors and linkrecover errors while the link is at less than INIT (long needed), to get accurate counts. Particularly an issue when doing non-IBTA DDR negotiation with chips from vendors that do not support IBTA mode negotiation. If the driver is unloaded, and there is a delta, the adjusted counters are written back to the chip, so they stay adjusted across driver reload. Signed-off-by: Dave Olson <dave.olson@qlogic.com> Signed-off-by: Roland Dreier <rolandd@cisco.com>
Diffstat (limited to 'drivers/infiniband/hw/ipath/ipath_iba6120.c')
-rw-r--r--drivers/infiniband/hw/ipath/ipath_iba6120.c61
1 files changed, 61 insertions, 0 deletions
diff --git a/drivers/infiniband/hw/ipath/ipath_iba6120.c b/drivers/infiniband/hw/ipath/ipath_iba6120.c
index 421cc2af891f0..fbf8c5379ea84 100644
--- a/drivers/infiniband/hw/ipath/ipath_iba6120.c
+++ b/drivers/infiniband/hw/ipath/ipath_iba6120.c
@@ -721,6 +721,12 @@ static int ipath_pe_bringup_serdes(struct ipath_devdata *dd)
INFINIPATH_HWE_SERDESPLLFAILED);
}
+ dd->ibdeltainprog = 1;
+ dd->ibsymsnap =
+ ipath_read_creg32(dd, dd->ipath_cregs->cr_ibsymbolerrcnt);
+ dd->iblnkerrsnap =
+ ipath_read_creg32(dd, dd->ipath_cregs->cr_iblinkerrrecovcnt);
+
val = ipath_read_kreg64(dd, dd->ipath_kregs->kr_serdesconfig0);
config1 = ipath_read_kreg64(dd, dd->ipath_kregs->kr_serdesconfig1);
@@ -810,6 +816,36 @@ static void ipath_pe_quiet_serdes(struct ipath_devdata *dd)
{
u64 val = ipath_read_kreg64(dd, dd->ipath_kregs->kr_serdesconfig0);
+ if (dd->ibsymdelta || dd->iblnkerrdelta ||
+ dd->ibdeltainprog) {
+ u64 diagc;
+ /* enable counter writes */
+ diagc = ipath_read_kreg64(dd, dd->ipath_kregs->kr_hwdiagctrl);
+ ipath_write_kreg(dd, dd->ipath_kregs->kr_hwdiagctrl,
+ diagc | INFINIPATH_DC_COUNTERWREN);
+
+ if (dd->ibsymdelta || dd->ibdeltainprog) {
+ val = ipath_read_creg32(dd,
+ dd->ipath_cregs->cr_ibsymbolerrcnt);
+ if (dd->ibdeltainprog)
+ val -= val - dd->ibsymsnap;
+ val -= dd->ibsymdelta;
+ ipath_write_creg(dd,
+ dd->ipath_cregs->cr_ibsymbolerrcnt, val);
+ }
+ if (dd->iblnkerrdelta || dd->ibdeltainprog) {
+ val = ipath_read_creg32(dd,
+ dd->ipath_cregs->cr_iblinkerrrecovcnt);
+ if (dd->ibdeltainprog)
+ val -= val - dd->iblnkerrsnap;
+ val -= dd->iblnkerrdelta;
+ ipath_write_creg(dd,
+ dd->ipath_cregs->cr_iblinkerrrecovcnt, val);
+ }
+
+ /* and disable counter writes */
+ ipath_write_kreg(dd, dd->ipath_kregs->kr_hwdiagctrl, diagc);
+ }
val |= INFINIPATH_SERDC0_TXIDLE;
ipath_dbg("Setting TxIdleEn on serdes (config0 = %llx)\n",
(unsigned long long) val);
@@ -1749,6 +1785,31 @@ static void ipath_pe_config_jint(struct ipath_devdata *dd, u16 a, u16 b)
static int ipath_pe_ib_updown(struct ipath_devdata *dd, int ibup, u64 ibcs)
{
+ if (ibup) {
+ if (dd->ibdeltainprog) {
+ dd->ibdeltainprog = 0;
+ dd->ibsymdelta +=
+ ipath_read_creg32(dd,
+ dd->ipath_cregs->cr_ibsymbolerrcnt) -
+ dd->ibsymsnap;
+ dd->iblnkerrdelta +=
+ ipath_read_creg32(dd,
+ dd->ipath_cregs->cr_iblinkerrrecovcnt) -
+ dd->iblnkerrsnap;
+ }
+ } else {
+ dd->ipath_lli_counter = 0;
+ if (!dd->ibdeltainprog) {
+ dd->ibdeltainprog = 1;
+ dd->ibsymsnap =
+ ipath_read_creg32(dd,
+ dd->ipath_cregs->cr_ibsymbolerrcnt);
+ dd->iblnkerrsnap =
+ ipath_read_creg32(dd,
+ dd->ipath_cregs->cr_iblinkerrrecovcnt);
+ }
+ }
+
ipath_setup_pe_setextled(dd, ipath_ib_linkstate(dd, ibcs),
ipath_ib_linktrstate(dd, ibcs));
return 0;