aboutsummaryrefslogtreecommitdiffstats
path: root/drivers/infiniband
diff options
context:
space:
mode:
authorJohn Gregor <john.gregor@qlogic.com>2008-05-07 14:01:10 -0400
committerRoland Dreier <rolandd@cisco.com>2008-05-07 14:01:10 -0400
commitab69b3cf1219e0d07bb4ea373f36b1de38af531c (patch)
treecad988230450defcdc2d598fd70b6f4ed89df044 /drivers/infiniband
parente2ab41cae418108f376ad1634d7507f56379f7a2 (diff)
IB/ipath: Fix SDMA error recovery in absence of link status change
What's fixed: in ipath_cancel_sends() We need to unconditionally set ABORTING. So, swap the tests so the set_bit() isn't shadowed by the &&. If we've disarmed the piobufs, then we need to unconditionally set DISARMED. So, move it out from the overly protective if at the bottom. in sdma_abort_task() Abort_task was written knowing that the SDMA engine would always be reset (and restarted) on error. A recent change broke that fundamental assumption by taking the restart portion and making it conditional on a link status change. But, SDMA can go boom without a link status change in some conditions. Signed-off-by: John Gregor <john.gregor@qlogic.com> Signed-off-by: Roland Dreier <rolandd@cisco.com>
Diffstat (limited to 'drivers/infiniband')
-rw-r--r--drivers/infiniband/hw/ipath/ipath_driver.c8
-rw-r--r--drivers/infiniband/hw/ipath/ipath_sdma.c31
2 files changed, 29 insertions, 10 deletions
diff --git a/drivers/infiniband/hw/ipath/ipath_driver.c b/drivers/infiniband/hw/ipath/ipath_driver.c
index 2036d38fac47..ce7b7c34360e 100644
--- a/drivers/infiniband/hw/ipath/ipath_driver.c
+++ b/drivers/infiniband/hw/ipath/ipath_driver.c
@@ -1898,8 +1898,8 @@ void ipath_cancel_sends(struct ipath_devdata *dd, int restore_sendctrl)
1898 1898
1899 spin_lock_irqsave(&dd->ipath_sdma_lock, flags); 1899 spin_lock_irqsave(&dd->ipath_sdma_lock, flags);
1900 skip_cancel = 1900 skip_cancel =
1901 !test_bit(IPATH_SDMA_DISABLED, statp) && 1901 test_and_set_bit(IPATH_SDMA_ABORTING, statp)
1902 test_and_set_bit(IPATH_SDMA_ABORTING, statp); 1902 && !test_bit(IPATH_SDMA_DISABLED, statp);
1903 spin_unlock_irqrestore(&dd->ipath_sdma_lock, flags); 1903 spin_unlock_irqrestore(&dd->ipath_sdma_lock, flags);
1904 if (skip_cancel) 1904 if (skip_cancel)
1905 goto bail; 1905 goto bail;
@@ -1930,6 +1930,9 @@ void ipath_cancel_sends(struct ipath_devdata *dd, int restore_sendctrl)
1930 ipath_disarm_piobufs(dd, 0, 1930 ipath_disarm_piobufs(dd, 0,
1931 dd->ipath_piobcnt2k + dd->ipath_piobcnt4k); 1931 dd->ipath_piobcnt2k + dd->ipath_piobcnt4k);
1932 1932
1933 if (dd->ipath_flags & IPATH_HAS_SEND_DMA)
1934 set_bit(IPATH_SDMA_DISARMED, &dd->ipath_sdma_status);
1935
1933 if (restore_sendctrl) { 1936 if (restore_sendctrl) {
1934 /* else done by caller later if needed */ 1937 /* else done by caller later if needed */
1935 spin_lock_irqsave(&dd->ipath_sendctrl_lock, flags); 1938 spin_lock_irqsave(&dd->ipath_sendctrl_lock, flags);
@@ -1949,7 +1952,6 @@ void ipath_cancel_sends(struct ipath_devdata *dd, int restore_sendctrl)
1949 /* only wait so long for intr */ 1952 /* only wait so long for intr */
1950 dd->ipath_sdma_abort_intr_timeout = jiffies + HZ; 1953 dd->ipath_sdma_abort_intr_timeout = jiffies + HZ;
1951 dd->ipath_sdma_reset_wait = 200; 1954 dd->ipath_sdma_reset_wait = 200;
1952 __set_bit(IPATH_SDMA_DISARMED, &dd->ipath_sdma_status);
1953 if (!test_bit(IPATH_SDMA_SHUTDOWN, &dd->ipath_sdma_status)) 1955 if (!test_bit(IPATH_SDMA_SHUTDOWN, &dd->ipath_sdma_status))
1954 tasklet_hi_schedule(&dd->ipath_sdma_abort_task); 1956 tasklet_hi_schedule(&dd->ipath_sdma_abort_task);
1955 spin_unlock_irqrestore(&dd->ipath_sdma_lock, flags); 1957 spin_unlock_irqrestore(&dd->ipath_sdma_lock, flags);
diff --git a/drivers/infiniband/hw/ipath/ipath_sdma.c b/drivers/infiniband/hw/ipath/ipath_sdma.c
index 0d07682c7310..3697449c1ba4 100644
--- a/drivers/infiniband/hw/ipath/ipath_sdma.c
+++ b/drivers/infiniband/hw/ipath/ipath_sdma.c
@@ -308,13 +308,15 @@ static void sdma_abort_task(unsigned long opaque)
308 spin_unlock_irqrestore(&dd->ipath_sdma_lock, flags); 308 spin_unlock_irqrestore(&dd->ipath_sdma_lock, flags);
309 309
310 /* 310 /*
311 * Don't restart sdma here. Wait until link is up to ACTIVE. 311 * Don't restart sdma here (with the exception
312 * VL15 MADs used to bring the link up use PIO, and multiple 312 * below). Wait until link is up to ACTIVE. VL15 MADs
313 * link transitions otherwise cause the sdma engine to be 313 * used to bring the link up use PIO, and multiple link
314 * transitions otherwise cause the sdma engine to be
314 * stopped and started multiple times. 315 * stopped and started multiple times.
315 * The disable is done here, including the shadow, so the 316 * The disable is done here, including the shadow,
316 * state is kept consistent. 317 * so the state is kept consistent.
317 * See ipath_restart_sdma() for the actual starting of sdma. 318 * See ipath_restart_sdma() for the actual starting
319 * of sdma.
318 */ 320 */
319 spin_lock_irqsave(&dd->ipath_sendctrl_lock, flags); 321 spin_lock_irqsave(&dd->ipath_sendctrl_lock, flags);
320 dd->ipath_sendctrl &= ~INFINIPATH_S_SDMAENABLE; 322 dd->ipath_sendctrl &= ~INFINIPATH_S_SDMAENABLE;
@@ -326,6 +328,13 @@ static void sdma_abort_task(unsigned long opaque)
326 /* make sure I see next message */ 328 /* make sure I see next message */
327 dd->ipath_sdma_abort_jiffies = 0; 329 dd->ipath_sdma_abort_jiffies = 0;
328 330
331 /*
332 * Not everything that takes SDMA offline is a link
333 * status change. If the link was up, restart SDMA.
334 */
335 if (dd->ipath_flags & IPATH_LINKACTIVE)
336 ipath_restart_sdma(dd);
337
329 goto done; 338 goto done;
330 } 339 }
331 340
@@ -427,7 +436,12 @@ int setup_sdma(struct ipath_devdata *dd)
427 goto done; 436 goto done;
428 } 437 }
429 438
430 dd->ipath_sdma_status = 0; 439 /*
440 * Set initial status as if we had been up, then gone down.
441 * This lets initial start on transition to ACTIVE be the
442 * same as restart after link flap.
443 */
444 dd->ipath_sdma_status = IPATH_SDMA_ABORT_ABORTED;
431 dd->ipath_sdma_abort_jiffies = 0; 445 dd->ipath_sdma_abort_jiffies = 0;
432 dd->ipath_sdma_generation = 0; 446 dd->ipath_sdma_generation = 0;
433 dd->ipath_sdma_descq_tail = 0; 447 dd->ipath_sdma_descq_tail = 0;
@@ -618,6 +632,9 @@ void ipath_restart_sdma(struct ipath_devdata *dd)
618 ipath_read_kreg64(dd, dd->ipath_kregs->kr_scratch); 632 ipath_read_kreg64(dd, dd->ipath_kregs->kr_scratch);
619 spin_unlock_irqrestore(&dd->ipath_sendctrl_lock, flags); 633 spin_unlock_irqrestore(&dd->ipath_sendctrl_lock, flags);
620 634
635 /* notify upper layers */
636 ipath_ib_piobufavail(dd->verbs_dev);
637
621bail: 638bail:
622 return; 639 return;
623} 640}