diff options
author | Dave Olson <dave.olson@qlogic.com> | 2008-04-16 21:09:25 -0700 |
---|---|---|
committer | Roland Dreier <rolandd@cisco.com> | 2008-04-16 21:09:25 -0700 |
commit | 72708a0a2b60e83255631f2557a85ac7daf33fac (patch) | |
tree | ba0b26fe6842240ed90cecd2fb741dc4c9f82908 /drivers/infiniband/hw/ipath/ipath_intr.c | |
parent | a51a2513a8cb201f02d83c37e106909938d2f761 (diff) | |
download | talos-op-linux-72708a0a2b60e83255631f2557a85ac7daf33fac.tar.gz talos-op-linux-72708a0a2b60e83255631f2557a85ac7daf33fac.zip |
IB/ipath: HW workaround for case where chip can send but not receive
Workaround a QLE7140 problem that in rare cases causes flow control
problems after link recovery by forcing a link retrain after recovery.
A module parameter is provided to control the behavior in case it causes
problems.
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_intr.c')
-rw-r--r-- | drivers/infiniband/hw/ipath/ipath_intr.c | 18 |
1 files changed, 18 insertions, 0 deletions
diff --git a/drivers/infiniband/hw/ipath/ipath_intr.c b/drivers/infiniband/hw/ipath/ipath_intr.c index dde5dfc9fcf5..ed82ecbb02da 100644 --- a/drivers/infiniband/hw/ipath/ipath_intr.c +++ b/drivers/infiniband/hw/ipath/ipath_intr.c @@ -366,6 +366,22 @@ static void handle_e_ibstatuschanged(struct ipath_devdata *dd, dd->ipath_ibpollcnt = 0; /* not poll*, now */ ipath_stats.sps_iblink++; + if (ibstate != init && dd->ipath_lastlinkrecov && ipath_linkrecovery) { + u64 linkrecov; + linkrecov = ipath_snap_cntr(dd, + dd->ipath_cregs->cr_iblinkerrrecovcnt); + if (linkrecov != dd->ipath_lastlinkrecov) { + ipath_dbg("IB linkrecov up %Lx (%s %s) recov %Lu\n", + ibcs, ib_linkstate(dd, ibcs), + ipath_ibcstatus_str[ltstate], + linkrecov); + /* and no more until active again */ + dd->ipath_lastlinkrecov = 0; + ipath_set_linkstate(dd, IPATH_IB_LINKDOWN); + goto skip_ibchange; + } + } + if (ibstate == init || ibstate == arm || ibstate == active) { *dd->ipath_statusp &= ~IPATH_STATUS_IB_NOCABLE; if (ibstate == init || ibstate == arm) { @@ -392,6 +408,8 @@ static void handle_e_ibstatuschanged(struct ipath_devdata *dd, IPATH_NOCABLE); ipath_hol_down(dd); } else { /* active */ + dd->ipath_lastlinkrecov = ipath_snap_cntr(dd, + dd->ipath_cregs->cr_iblinkerrrecovcnt); *dd->ipath_statusp |= IPATH_STATUS_IB_READY | IPATH_STATUS_IB_CONF; dd->ipath_flags |= IPATH_LINKACTIVE; |