aboutsummaryrefslogtreecommitdiffstats
path: root/drivers/infiniband
diff options
context:
space:
mode:
authorDave Olson <dave.olson@qlogic.com>2008-04-17 00:09:25 -0400
committerRoland Dreier <rolandd@cisco.com>2008-04-17 00:09:25 -0400
commit72708a0a2b60e83255631f2557a85ac7daf33fac (patch)
treeba0b26fe6842240ed90cecd2fb741dc4c9f82908 /drivers/infiniband
parenta51a2513a8cb201f02d83c37e106909938d2f761 (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.c4
-rw-r--r--drivers/infiniband/hw/ipath/ipath_intr.c18
-rw-r--r--drivers/infiniband/hw/ipath/ipath_kernel.h2
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);
82MODULE_PARM_DESC(hol_timeout_ms, 82MODULE_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
85unsigned ipath_linkrecovery = 1;
86module_param_named(linkrecovery, ipath_linkrecovery, uint, S_IWUSR | S_IRUGO);
87MODULE_PARM_DESC(linkrecovery, "enable workaround for link recovery issue");
88
85MODULE_LICENSE("GPL"); 89MODULE_LICENSE("GPL");
86MODULE_AUTHOR("QLogic <support@pathscale.com>"); 90MODULE_AUTHOR("QLogic <support@pathscale.com>");
87MODULE_DESCRIPTION("QLogic InfiniPath driver"); 91MODULE_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
1101extern unsigned ipath_debug; /* debugging bit mask */ 1102extern unsigned ipath_debug; /* debugging bit mask */
1103extern unsigned ipath_linkrecovery;
1102extern unsigned ipath_mtu4096; 1104extern 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 */