Skip to content

Commit

Permalink
IB/ipath: Don't count IB symbol and link errors unless link is UP
Browse files Browse the repository at this point in the history
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>
  • Loading branch information
Dave Olson authored and Roland Dreier committed Dec 5, 2008
1 parent 890fccb commit 60e8450
Show file tree
Hide file tree
Showing 4 changed files with 155 additions and 3 deletions.
61 changes: 61 additions & 0 deletions drivers/infiniband/hw/ipath/ipath_iba6120.c
Original file line number Diff line number Diff line change
Expand Up @@ -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);

Expand Down Expand Up @@ -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);
Expand Down Expand Up @@ -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;
Expand Down
76 changes: 73 additions & 3 deletions drivers/infiniband/hw/ipath/ipath_iba7220.c
Original file line number Diff line number Diff line change
Expand Up @@ -951,6 +951,12 @@ static int ipath_7220_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);

if (!dd->ipath_ibcddrctrl) {
/* not on re-init after reset */
dd->ipath_ibcddrctrl =
Expand Down Expand Up @@ -1084,6 +1090,37 @@ static void ipath_7220_config_jint(struct ipath_devdata *dd,
static void ipath_7220_quiet_serdes(struct ipath_devdata *dd)
{
u64 val;
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);
}

dd->ipath_flags &= ~IPATH_IB_AUTONEG_INPROG;
wake_up(&dd->ipath_autoneg_wait);
cancel_delayed_work(&dd->ipath_autoneg_work);
Expand Down Expand Up @@ -2325,7 +2362,7 @@ static void try_auto_neg(struct ipath_devdata *dd)

static int ipath_7220_ib_updown(struct ipath_devdata *dd, int ibup, u64 ibcs)
{
int ret = 0;
int ret = 0, symadj = 0;
u32 ltstate = ipath_ib_linkstate(dd, ibcs);

dd->ipath_link_width_active =
Expand Down Expand Up @@ -2368,6 +2405,13 @@ static int ipath_7220_ib_updown(struct ipath_devdata *dd, int ibup, u64 ibcs)
ipath_dbg("DDR negotiation try, %u/%u\n",
dd->ipath_autoneg_tries,
IPATH_AUTONEG_TRIES);
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);
}
try_auto_neg(dd);
ret = 1; /* no other IB status change processing */
} else if ((dd->ipath_flags & IPATH_IB_AUTONEG_INPROG)
Expand All @@ -2388,6 +2432,7 @@ static int ipath_7220_ib_updown(struct ipath_devdata *dd, int ibup, u64 ibcs)
set_speed_fast(dd,
dd->ipath_link_speed_enabled);
wake_up(&dd->ipath_autoneg_wait);
symadj = 1;
} else if (dd->ipath_flags & IPATH_IB_AUTONEG_FAILED) {
/*
* clear autoneg failure flag, and do setup
Expand All @@ -2403,6 +2448,7 @@ static int ipath_7220_ib_updown(struct ipath_devdata *dd, int ibup, u64 ibcs)
IBA7220_IBC_IBTA_1_2_MASK;
ipath_write_kreg(dd,
IPATH_KREG_OFFSET(IBNCModeCtrl), 0);
symadj = 1;
}
}
/*
Expand All @@ -2416,9 +2462,13 @@ static int ipath_7220_ib_updown(struct ipath_devdata *dd, int ibup, u64 ibcs)
IB_WIDTH_4X)) == (IB_WIDTH_1X | IB_WIDTH_4X)
&& dd->ipath_link_width_active == IB_WIDTH_1X
&& dd->ipath_x1_fix_tries < 3) {
if (++dd->ipath_x1_fix_tries == 3)
if (++dd->ipath_x1_fix_tries == 3) {
dev_info(&dd->pcidev->dev,
"IB link is in 1X mode\n");
if (!(dd->ipath_flags &
IPATH_IB_AUTONEG_INPROG))
symadj = 1;
}
else {
ipath_cdbg(VERBOSE, "IB 1X in "
"auto-width, try %u to be "
Expand All @@ -2429,7 +2479,8 @@ static int ipath_7220_ib_updown(struct ipath_devdata *dd, int ibup, u64 ibcs)
dd->ipath_f_xgxs_reset(dd);
ret = 1; /* skip other processing */
}
}
} else if (!(dd->ipath_flags & IPATH_IB_AUTONEG_INPROG))
symadj = 1;

if (!ret) {
dd->delay_mult = rate_to_delay
Expand All @@ -2440,6 +2491,25 @@ static int ipath_7220_ib_updown(struct ipath_devdata *dd, int ibup, u64 ibcs)
}
}

if (symadj) {
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 if (!ibup && !dd->ibdeltainprog
&& !(dd->ipath_flags & IPATH_IB_AUTONEG_INPROG)) {
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);
}

if (!ret)
ipath_setup_7220_setextled(dd, ipath_ib_linkstate(dd, ibcs),
ltstate);
Expand Down
13 changes: 13 additions & 0 deletions drivers/infiniband/hw/ipath/ipath_kernel.h
Original file line number Diff line number Diff line change
Expand Up @@ -355,6 +355,19 @@ struct ipath_devdata {
/* errors masked because they occur too fast */
ipath_err_t ipath_maskederrs;
u64 ipath_lastlinkrecov; /* link recoveries at last ACTIVE */
/* these 5 fields are used to establish deltas for IB Symbol
* errors and linkrecovery errors. They can be reported on
* some chips during link negotiation prior to INIT, and with
* DDR when faking DDR negotiations with non-IBTA switches.
* The chip counters are adjusted at driver unload if there is
* a non-zero delta.
*/
u64 ibdeltainprog;
u64 ibsymdelta;
u64 ibsymsnap;
u64 iblnkerrdelta;
u64 iblnkerrsnap;

/* time in jiffies at which to re-enable maskederrs */
unsigned long ipath_unmasktime;
/* count of egrfull errors, combined for all ports */
Expand Down
8 changes: 8 additions & 0 deletions drivers/infiniband/hw/ipath/ipath_stats.c
Original file line number Diff line number Diff line change
Expand Up @@ -112,6 +112,14 @@ u64 ipath_snap_cntr(struct ipath_devdata *dd, ipath_creg creg)
dd->ipath_lastrpkts = val;
}
val64 = dd->ipath_rpkts;
} else if (creg == dd->ipath_cregs->cr_ibsymbolerrcnt) {
if (dd->ibdeltainprog)
val64 -= val64 - dd->ibsymsnap;
val64 -= dd->ibsymdelta;
} else if (creg == dd->ipath_cregs->cr_iblinkerrrecovcnt) {
if (dd->ibdeltainprog)
val64 -= val64 - dd->iblnkerrsnap;
val64 -= dd->iblnkerrdelta;
} else
val64 = (u64) val;

Expand Down

0 comments on commit 60e8450

Please sign in to comment.