diff options
author | Dave Olson <dave.olson@qlogic.com> | 2008-04-17 00:09:25 -0400 |
---|---|---|
committer | Roland Dreier <rolandd@cisco.com> | 2008-04-17 00:09:25 -0400 |
commit | 72708a0a2b60e83255631f2557a85ac7daf33fac (patch) | |
tree | ba0b26fe6842240ed90cecd2fb741dc4c9f82908 /drivers/infiniband/hw/ipath/ipath_intr.c | |
parent | a51a2513a8cb201f02d83c37e106909938d2f761 (diff) |
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, | |||
366 | dd->ipath_ibpollcnt = 0; /* not poll*, now */ | 366 | dd->ipath_ibpollcnt = 0; /* not poll*, now */ |
367 | ipath_stats.sps_iblink++; | 367 | ipath_stats.sps_iblink++; |
368 | 368 | ||
369 | if (ibstate != init && dd->ipath_lastlinkrecov && ipath_linkrecovery) { | ||
370 | u64 linkrecov; | ||
371 | linkrecov = ipath_snap_cntr(dd, | ||
372 | dd->ipath_cregs->cr_iblinkerrrecovcnt); | ||
373 | if (linkrecov != dd->ipath_lastlinkrecov) { | ||
374 | ipath_dbg("IB linkrecov up %Lx (%s %s) recov %Lu\n", | ||
375 | ibcs, ib_linkstate(dd, ibcs), | ||
376 | ipath_ibcstatus_str[ltstate], | ||
377 | linkrecov); | ||
378 | /* and no more until active again */ | ||
379 | dd->ipath_lastlinkrecov = 0; | ||
380 | ipath_set_linkstate(dd, IPATH_IB_LINKDOWN); | ||
381 | goto skip_ibchange; | ||
382 | } | ||
383 | } | ||
384 | |||
369 | if (ibstate == init || ibstate == arm || ibstate == active) { | 385 | if (ibstate == init || ibstate == arm || ibstate == active) { |
370 | *dd->ipath_statusp &= ~IPATH_STATUS_IB_NOCABLE; | 386 | *dd->ipath_statusp &= ~IPATH_STATUS_IB_NOCABLE; |
371 | if (ibstate == init || ibstate == arm) { | 387 | if (ibstate == init || ibstate == arm) { |
@@ -392,6 +408,8 @@ static void handle_e_ibstatuschanged(struct ipath_devdata *dd, | |||
392 | IPATH_NOCABLE); | 408 | IPATH_NOCABLE); |
393 | ipath_hol_down(dd); | 409 | ipath_hol_down(dd); |
394 | } else { /* active */ | 410 | } else { /* active */ |
411 | dd->ipath_lastlinkrecov = ipath_snap_cntr(dd, | ||
412 | dd->ipath_cregs->cr_iblinkerrrecovcnt); | ||
395 | *dd->ipath_statusp |= | 413 | *dd->ipath_statusp |= |
396 | IPATH_STATUS_IB_READY | IPATH_STATUS_IB_CONF; | 414 | IPATH_STATUS_IB_READY | IPATH_STATUS_IB_CONF; |
397 | dd->ipath_flags |= IPATH_LINKACTIVE; | 415 | dd->ipath_flags |= IPATH_LINKACTIVE; |