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 | |
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')
-rw-r--r-- | drivers/infiniband/hw/ipath/ipath_driver.c | 4 | ||||
-rw-r--r-- | drivers/infiniband/hw/ipath/ipath_intr.c | 18 | ||||
-rw-r--r-- | drivers/infiniband/hw/ipath/ipath_kernel.h | 2 |
3 files changed, 24 insertions, 0 deletions
diff --git a/drivers/infiniband/hw/ipath/ipath_driver.c b/drivers/infiniband/hw/ipath/ipath_driver.c index 5605f4f27521..2cad7335681b 100644 --- a/drivers/infiniband/hw/ipath/ipath_driver.c +++ b/drivers/infiniband/hw/ipath/ipath_driver.c | |||
@@ -82,6 +82,10 @@ module_param_named(hol_timeout_ms, ipath_hol_timeout_ms, uint, S_IRUGO); | |||
82 | MODULE_PARM_DESC(hol_timeout_ms, | 82 | MODULE_PARM_DESC(hol_timeout_ms, |
83 | "duration of user app suspension after link failure"); | 83 | "duration of user app suspension after link failure"); |
84 | 84 | ||
85 | unsigned ipath_linkrecovery = 1; | ||
86 | module_param_named(linkrecovery, ipath_linkrecovery, uint, S_IWUSR | S_IRUGO); | ||
87 | MODULE_PARM_DESC(linkrecovery, "enable workaround for link recovery issue"); | ||
88 | |||
85 | MODULE_LICENSE("GPL"); | 89 | MODULE_LICENSE("GPL"); |
86 | MODULE_AUTHOR("QLogic <support@pathscale.com>"); | 90 | MODULE_AUTHOR("QLogic <support@pathscale.com>"); |
87 | MODULE_DESCRIPTION("QLogic InfiniPath driver"); | 91 | MODULE_DESCRIPTION("QLogic InfiniPath driver"); |
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; |
diff --git a/drivers/infiniband/hw/ipath/ipath_kernel.h b/drivers/infiniband/hw/ipath/ipath_kernel.h index 960d5b7e7865..b8b81cb745b9 100644 --- a/drivers/infiniband/hw/ipath/ipath_kernel.h +++ b/drivers/infiniband/hw/ipath/ipath_kernel.h | |||
@@ -309,6 +309,7 @@ struct ipath_devdata { | |||
309 | ipath_err_t ipath_lasthwerror; | 309 | ipath_err_t ipath_lasthwerror; |
310 | /* errors masked because they occur too fast */ | 310 | /* errors masked because they occur too fast */ |
311 | ipath_err_t ipath_maskederrs; | 311 | ipath_err_t ipath_maskederrs; |
312 | u64 ipath_lastlinkrecov; /* link recoveries at last ACTIVE */ | ||
312 | /* time in jiffies at which to re-enable maskederrs */ | 313 | /* time in jiffies at which to re-enable maskederrs */ |
313 | unsigned long ipath_unmasktime; | 314 | unsigned long ipath_unmasktime; |
314 | /* count of egrfull errors, combined for all ports */ | 315 | /* count of egrfull errors, combined for all ports */ |
@@ -1099,6 +1100,7 @@ dma_addr_t ipath_map_single(struct pci_dev *, void *, size_t, int); | |||
1099 | #endif | 1100 | #endif |
1100 | 1101 | ||
1101 | extern unsigned ipath_debug; /* debugging bit mask */ | 1102 | extern unsigned ipath_debug; /* debugging bit mask */ |
1103 | extern unsigned ipath_linkrecovery; | ||
1102 | extern unsigned ipath_mtu4096; | 1104 | extern unsigned ipath_mtu4096; |
1103 | 1105 | ||
1104 | #define IPATH_MAX_PARITY_ATTEMPTS 10000 /* max times to try recovery */ | 1106 | #define IPATH_MAX_PARITY_ATTEMPTS 10000 /* max times to try recovery */ |