diff options
-rw-r--r-- | drivers/infiniband/hw/ipath/ipath_driver.c | 57 | ||||
-rw-r--r-- | drivers/infiniband/hw/ipath/ipath_iba6110.c | 13 | ||||
-rw-r--r-- | drivers/infiniband/hw/ipath/ipath_iba6120.c | 16 | ||||
-rw-r--r-- | drivers/infiniband/hw/ipath/ipath_init_chip.c | 6 | ||||
-rw-r--r-- | drivers/infiniband/hw/ipath/ipath_intr.c | 13 | ||||
-rw-r--r-- | drivers/infiniband/hw/ipath/ipath_kernel.h | 1 |
6 files changed, 68 insertions, 38 deletions
diff --git a/drivers/infiniband/hw/ipath/ipath_driver.c b/drivers/infiniband/hw/ipath/ipath_driver.c index e9639860b48d..8b611796f33e 100644 --- a/drivers/infiniband/hw/ipath/ipath_driver.c +++ b/drivers/infiniband/hw/ipath/ipath_driver.c | |||
@@ -706,9 +706,9 @@ void ipath_disarm_piobufs(struct ipath_devdata *dd, unsigned first, | |||
706 | u64 sendctrl, sendorig; | 706 | u64 sendctrl, sendorig; |
707 | 707 | ||
708 | ipath_cdbg(PKT, "disarm %u PIObufs first=%u\n", cnt, first); | 708 | ipath_cdbg(PKT, "disarm %u PIObufs first=%u\n", cnt, first); |
709 | sendorig = dd->ipath_sendctrl | INFINIPATH_S_DISARM; | 709 | sendorig = dd->ipath_sendctrl; |
710 | for (i = first; i < last; i++) { | 710 | for (i = first; i < last; i++) { |
711 | sendctrl = sendorig | | 711 | sendctrl = sendorig | INFINIPATH_S_DISARM | |
712 | (i << INFINIPATH_S_DISARMPIOBUF_SHIFT); | 712 | (i << INFINIPATH_S_DISARMPIOBUF_SHIFT); |
713 | ipath_write_kreg(dd, dd->ipath_kregs->kr_sendctrl, | 713 | ipath_write_kreg(dd, dd->ipath_kregs->kr_sendctrl, |
714 | sendctrl); | 714 | sendctrl); |
@@ -719,12 +719,12 @@ void ipath_disarm_piobufs(struct ipath_devdata *dd, unsigned first, | |||
719 | * while we were looping; no critical bits that would require | 719 | * while we were looping; no critical bits that would require |
720 | * locking. | 720 | * locking. |
721 | * | 721 | * |
722 | * Write a 0, and then the original value, reading scratch in | 722 | * disable PIOAVAILUPD, then re-enable, reading scratch in |
723 | * between. This seems to avoid a chip timing race that causes | 723 | * between. This seems to avoid a chip timing race that causes |
724 | * pioavail updates to memory to stop. | 724 | * pioavail updates to memory to stop. |
725 | */ | 725 | */ |
726 | ipath_write_kreg(dd, dd->ipath_kregs->kr_sendctrl, | 726 | ipath_write_kreg(dd, dd->ipath_kregs->kr_sendctrl, |
727 | 0); | 727 | sendorig & ~IPATH_S_PIOBUFAVAILUPD); |
728 | sendorig = ipath_read_kreg64(dd, dd->ipath_kregs->kr_scratch); | 728 | sendorig = ipath_read_kreg64(dd, dd->ipath_kregs->kr_scratch); |
729 | ipath_write_kreg(dd, dd->ipath_kregs->kr_sendctrl, | 729 | ipath_write_kreg(dd, dd->ipath_kregs->kr_sendctrl, |
730 | dd->ipath_sendctrl); | 730 | dd->ipath_sendctrl); |
@@ -1596,6 +1596,35 @@ int ipath_waitfor_mdio_cmdready(struct ipath_devdata *dd) | |||
1596 | return ret; | 1596 | return ret; |
1597 | } | 1597 | } |
1598 | 1598 | ||
1599 | |||
1600 | /* | ||
1601 | * Flush all sends that might be in the ready to send state, as well as any | ||
1602 | * that are in the process of being sent. Used whenever we need to be | ||
1603 | * sure the send side is idle. Cleans up all buffer state by canceling | ||
1604 | * all pio buffers, and issuing an abort, which cleans up anything in the | ||
1605 | * launch fifo. The cancel is superfluous on some chip versions, but | ||
1606 | * it's safer to always do it. | ||
1607 | * PIOAvail bits are updated by the chip as if normal send had happened. | ||
1608 | */ | ||
1609 | void ipath_cancel_sends(struct ipath_devdata *dd) | ||
1610 | { | ||
1611 | ipath_dbg("Cancelling all in-progress send buffers\n"); | ||
1612 | dd->ipath_lastcancel = jiffies+HZ/2; /* skip armlaunch errs a bit */ | ||
1613 | /* | ||
1614 | * the abort bit is auto-clearing. We read scratch to be sure | ||
1615 | * that cancels and the abort have taken effect in the chip. | ||
1616 | */ | ||
1617 | ipath_write_kreg(dd, dd->ipath_kregs->kr_sendctrl, | ||
1618 | INFINIPATH_S_ABORT); | ||
1619 | ipath_read_kreg64(dd, dd->ipath_kregs->kr_scratch); | ||
1620 | ipath_disarm_piobufs(dd, 0, | ||
1621 | (unsigned)(dd->ipath_piobcnt2k + dd->ipath_piobcnt4k)); | ||
1622 | |||
1623 | /* and again, be sure all have hit the chip */ | ||
1624 | ipath_read_kreg64(dd, dd->ipath_kregs->kr_scratch); | ||
1625 | } | ||
1626 | |||
1627 | |||
1599 | static void ipath_set_ib_lstate(struct ipath_devdata *dd, int which) | 1628 | static void ipath_set_ib_lstate(struct ipath_devdata *dd, int which) |
1600 | { | 1629 | { |
1601 | static const char *what[4] = { | 1630 | static const char *what[4] = { |
@@ -1617,14 +1646,8 @@ static void ipath_set_ib_lstate(struct ipath_devdata *dd, int which) | |||
1617 | INFINIPATH_IBCS_LINKTRAININGSTATE_MASK]); | 1646 | INFINIPATH_IBCS_LINKTRAININGSTATE_MASK]); |
1618 | /* flush all queued sends when going to DOWN or INIT, to be sure that | 1647 | /* flush all queued sends when going to DOWN or INIT, to be sure that |
1619 | * they don't block MAD packets */ | 1648 | * they don't block MAD packets */ |
1620 | if (!linkcmd || linkcmd == INFINIPATH_IBCC_LINKCMD_INIT) { | 1649 | if (!linkcmd || linkcmd == INFINIPATH_IBCC_LINKCMD_INIT) |
1621 | ipath_write_kreg(dd, dd->ipath_kregs->kr_sendctrl, | 1650 | ipath_cancel_sends(dd); |
1622 | INFINIPATH_S_ABORT); | ||
1623 | ipath_disarm_piobufs(dd, dd->ipath_lastport_piobuf, | ||
1624 | (unsigned)(dd->ipath_piobcnt2k + | ||
1625 | dd->ipath_piobcnt4k) - | ||
1626 | dd->ipath_lastport_piobuf); | ||
1627 | } | ||
1628 | 1651 | ||
1629 | ipath_write_kreg(dd, dd->ipath_kregs->kr_ibcctrl, | 1652 | ipath_write_kreg(dd, dd->ipath_kregs->kr_ibcctrl, |
1630 | dd->ipath_ibcctrl | which); | 1653 | dd->ipath_ibcctrl | which); |
@@ -1967,17 +1990,9 @@ void ipath_shutdown_device(struct ipath_devdata *dd) | |||
1967 | */ | 1990 | */ |
1968 | udelay(5); | 1991 | udelay(5); |
1969 | 1992 | ||
1970 | /* | ||
1971 | * abort any armed or launched PIO buffers that didn't go. (self | ||
1972 | * clearing). Will cause any packet currently being transmitted to | ||
1973 | * go out with an EBP, and may also cause a short packet error on | ||
1974 | * the receiver. | ||
1975 | */ | ||
1976 | ipath_write_kreg(dd, dd->ipath_kregs->kr_sendctrl, | ||
1977 | INFINIPATH_S_ABORT); | ||
1978 | |||
1979 | ipath_set_ib_lstate(dd, INFINIPATH_IBCC_LINKINITCMD_DISABLE << | 1993 | ipath_set_ib_lstate(dd, INFINIPATH_IBCC_LINKINITCMD_DISABLE << |
1980 | INFINIPATH_IBCC_LINKINITCMD_SHIFT); | 1994 | INFINIPATH_IBCC_LINKINITCMD_SHIFT); |
1995 | ipath_cancel_sends(dd); | ||
1981 | 1996 | ||
1982 | /* disable IBC */ | 1997 | /* disable IBC */ |
1983 | dd->ipath_control &= ~INFINIPATH_C_LINKENABLE; | 1998 | dd->ipath_control &= ~INFINIPATH_C_LINKENABLE; |
diff --git a/drivers/infiniband/hw/ipath/ipath_iba6110.c b/drivers/infiniband/hw/ipath/ipath_iba6110.c index d8ac9f18bf49..34d159ad97b4 100644 --- a/drivers/infiniband/hw/ipath/ipath_iba6110.c +++ b/drivers/infiniband/hw/ipath/ipath_iba6110.c | |||
@@ -509,6 +509,13 @@ static void ipath_ht_handle_hwerrors(struct ipath_devdata *dd, char *msg, | |||
509 | if (!hwerrs) { | 509 | if (!hwerrs) { |
510 | ipath_dbg("Clearing freezemode on ignored or " | 510 | ipath_dbg("Clearing freezemode on ignored or " |
511 | "recovered hardware error\n"); | 511 | "recovered hardware error\n"); |
512 | /* | ||
513 | * clear all sends, becauase they have may been | ||
514 | * completed by usercode while in freeze mode, and | ||
515 | * therefore would not be sent, and eventually | ||
516 | * might cause the process to run out of bufs | ||
517 | */ | ||
518 | ipath_cancel_sends(dd); | ||
512 | ctrl &= ~INFINIPATH_C_FREEZEMODE; | 519 | ctrl &= ~INFINIPATH_C_FREEZEMODE; |
513 | ipath_write_kreg(dd, dd->ipath_kregs->kr_control, | 520 | ipath_write_kreg(dd, dd->ipath_kregs->kr_control, |
514 | ctrl); | 521 | ctrl); |
@@ -1566,11 +1573,6 @@ static int ipath_ht_early_init(struct ipath_devdata *dd) | |||
1566 | writel(16, piobuf); | 1573 | writel(16, piobuf); |
1567 | piobuf += pioincr; | 1574 | piobuf += pioincr; |
1568 | } | 1575 | } |
1569 | /* | ||
1570 | * self-clearing | ||
1571 | */ | ||
1572 | ipath_write_kreg(dd, dd->ipath_kregs->kr_sendctrl, | ||
1573 | INFINIPATH_S_ABORT); | ||
1574 | 1576 | ||
1575 | ipath_get_eeprom_info(dd); | 1577 | ipath_get_eeprom_info(dd); |
1576 | if (dd->ipath_boardrev == 5 && dd->ipath_serial[0] == '1' && | 1578 | if (dd->ipath_boardrev == 5 && dd->ipath_serial[0] == '1' && |
@@ -1599,7 +1601,6 @@ static int ipath_ht_txe_recover(struct ipath_devdata *dd) | |||
1599 | } | 1601 | } |
1600 | dev_info(&dd->pcidev->dev, | 1602 | dev_info(&dd->pcidev->dev, |
1601 | "Recovering from TXE PIO parity error\n"); | 1603 | "Recovering from TXE PIO parity error\n"); |
1602 | ipath_disarm_senderrbufs(dd, 1); | ||
1603 | return 1; | 1604 | return 1; |
1604 | } | 1605 | } |
1605 | 1606 | ||
diff --git a/drivers/infiniband/hw/ipath/ipath_iba6120.c b/drivers/infiniband/hw/ipath/ipath_iba6120.c index b931057bb3e8..0c34555d4979 100644 --- a/drivers/infiniband/hw/ipath/ipath_iba6120.c +++ b/drivers/infiniband/hw/ipath/ipath_iba6120.c | |||
@@ -430,8 +430,19 @@ static void ipath_pe_handle_hwerrors(struct ipath_devdata *dd, char *msg, | |||
430 | *dd->ipath_statusp |= IPATH_STATUS_HWERROR; | 430 | *dd->ipath_statusp |= IPATH_STATUS_HWERROR; |
431 | dd->ipath_flags &= ~IPATH_INITTED; | 431 | dd->ipath_flags &= ~IPATH_INITTED; |
432 | } else { | 432 | } else { |
433 | ipath_dbg("Clearing freezemode on ignored hardware " | 433 | static u32 freeze_cnt; |
434 | "error\n"); | 434 | |
435 | freeze_cnt++; | ||
436 | ipath_dbg("Clearing freezemode on ignored or recovered " | ||
437 | "hardware error (%u)\n", freeze_cnt); | ||
438 | /* | ||
439 | * clear all sends, becauase they have may been | ||
440 | * completed by usercode while in freeze mode, and | ||
441 | * therefore would not be sent, and eventually | ||
442 | * might cause the process to run out of bufs | ||
443 | */ | ||
444 | ipath_cancel_sends(dd); | ||
445 | ctrl &= ~INFINIPATH_C_FREEZEMODE; | ||
435 | ipath_write_kreg(dd, dd->ipath_kregs->kr_control, | 446 | ipath_write_kreg(dd, dd->ipath_kregs->kr_control, |
436 | dd->ipath_control); | 447 | dd->ipath_control); |
437 | } | 448 | } |
@@ -1371,7 +1382,6 @@ static int ipath_pe_txe_recover(struct ipath_devdata *dd) | |||
1371 | dev_info(&dd->pcidev->dev, | 1382 | dev_info(&dd->pcidev->dev, |
1372 | "Recovering from TXE PIO parity error\n"); | 1383 | "Recovering from TXE PIO parity error\n"); |
1373 | } | 1384 | } |
1374 | ipath_disarm_senderrbufs(dd, 1); | ||
1375 | return 1; | 1385 | return 1; |
1376 | } | 1386 | } |
1377 | 1387 | ||
diff --git a/drivers/infiniband/hw/ipath/ipath_init_chip.c b/drivers/infiniband/hw/ipath/ipath_init_chip.c index 9f611553ffb3..5193d6945caa 100644 --- a/drivers/infiniband/hw/ipath/ipath_init_chip.c +++ b/drivers/infiniband/hw/ipath/ipath_init_chip.c | |||
@@ -777,6 +777,12 @@ int ipath_init_chip(struct ipath_devdata *dd, int reinit) | |||
777 | piobufs, dd->ipath_pbufsport, uports); | 777 | piobufs, dd->ipath_pbufsport, uports); |
778 | 778 | ||
779 | dd->ipath_f_early_init(dd); | 779 | dd->ipath_f_early_init(dd); |
780 | /* | ||
781 | * cancel any possible active sends from early driver load. | ||
782 | * Follows early_init because some chips have to initialize | ||
783 | * PIO buffers in early_init to avoid false parity errors. | ||
784 | */ | ||
785 | ipath_cancel_sends(dd); | ||
780 | 786 | ||
781 | /* early_init sets rcvhdrentsize and rcvhdrsize, so this must be | 787 | /* early_init sets rcvhdrentsize and rcvhdrsize, so this must be |
782 | * done after early_init */ | 788 | * done after early_init */ |
diff --git a/drivers/infiniband/hw/ipath/ipath_intr.c b/drivers/infiniband/hw/ipath/ipath_intr.c index d9cdd00c8233..948091f7d5ac 100644 --- a/drivers/infiniband/hw/ipath/ipath_intr.c +++ b/drivers/infiniband/hw/ipath/ipath_intr.c | |||
@@ -93,7 +93,8 @@ void ipath_disarm_senderrbufs(struct ipath_devdata *dd, int rewrite) | |||
93 | 93 | ||
94 | if (sbuf[0] || sbuf[1] || (piobcnt > 128 && (sbuf[2] || sbuf[3]))) { | 94 | if (sbuf[0] || sbuf[1] || (piobcnt > 128 && (sbuf[2] || sbuf[3]))) { |
95 | int i; | 95 | int i; |
96 | if (ipath_debug & (__IPATH_PKTDBG|__IPATH_DBG)) { | 96 | if (ipath_debug & (__IPATH_PKTDBG|__IPATH_DBG) && |
97 | dd->ipath_lastcancel > jiffies) { | ||
97 | __IPATH_DBG_WHICH(__IPATH_PKTDBG|__IPATH_DBG, | 98 | __IPATH_DBG_WHICH(__IPATH_PKTDBG|__IPATH_DBG, |
98 | "SendbufErrs %lx %lx", sbuf[0], | 99 | "SendbufErrs %lx %lx", sbuf[0], |
99 | sbuf[1]); | 100 | sbuf[1]); |
@@ -108,7 +109,8 @@ void ipath_disarm_senderrbufs(struct ipath_devdata *dd, int rewrite) | |||
108 | ipath_clrpiobuf(dd, i); | 109 | ipath_clrpiobuf(dd, i); |
109 | ipath_disarm_piobufs(dd, i, 1); | 110 | ipath_disarm_piobufs(dd, i, 1); |
110 | } | 111 | } |
111 | dd->ipath_lastcancel = jiffies+3; /* no armlaunch for a bit */ | 112 | /* ignore armlaunch errs for a bit */ |
113 | dd->ipath_lastcancel = jiffies+3; | ||
112 | } | 114 | } |
113 | } | 115 | } |
114 | 116 | ||
@@ -290,12 +292,7 @@ static void handle_e_ibstatuschanged(struct ipath_devdata *dd, | |||
290 | * Flush all queued sends when link went to DOWN or INIT, | 292 | * Flush all queued sends when link went to DOWN or INIT, |
291 | * to be sure that they don't block SMA and other MAD packets | 293 | * to be sure that they don't block SMA and other MAD packets |
292 | */ | 294 | */ |
293 | ipath_write_kreg(dd, dd->ipath_kregs->kr_sendctrl, | 295 | ipath_cancel_sends(dd); |
294 | INFINIPATH_S_ABORT); | ||
295 | ipath_disarm_piobufs(dd, dd->ipath_lastport_piobuf, | ||
296 | (unsigned)(dd->ipath_piobcnt2k + | ||
297 | dd->ipath_piobcnt4k) - | ||
298 | dd->ipath_lastport_piobuf); | ||
299 | } | 296 | } |
300 | else if (lstate == IPATH_IBSTATE_INIT || lstate == IPATH_IBSTATE_ARM || | 297 | else if (lstate == IPATH_IBSTATE_INIT || lstate == IPATH_IBSTATE_ARM || |
301 | lstate == IPATH_IBSTATE_ACTIVE) { | 298 | lstate == IPATH_IBSTATE_ACTIVE) { |
diff --git a/drivers/infiniband/hw/ipath/ipath_kernel.h b/drivers/infiniband/hw/ipath/ipath_kernel.h index 2a4414b948ee..2e85aeca5eac 100644 --- a/drivers/infiniband/hw/ipath/ipath_kernel.h +++ b/drivers/infiniband/hw/ipath/ipath_kernel.h | |||
@@ -676,6 +676,7 @@ int ipath_unordered_wc(void); | |||
676 | 676 | ||
677 | void ipath_disarm_piobufs(struct ipath_devdata *, unsigned first, | 677 | void ipath_disarm_piobufs(struct ipath_devdata *, unsigned first, |
678 | unsigned cnt); | 678 | unsigned cnt); |
679 | void ipath_cancel_sends(struct ipath_devdata *); | ||
679 | 680 | ||
680 | int ipath_create_rcvhdrq(struct ipath_devdata *, struct ipath_portdata *); | 681 | int ipath_create_rcvhdrq(struct ipath_devdata *, struct ipath_portdata *); |
681 | void ipath_free_pddata(struct ipath_devdata *, struct ipath_portdata *); | 682 | void ipath_free_pddata(struct ipath_devdata *, struct ipath_portdata *); |