aboutsummaryrefslogtreecommitdiffstats
path: root/drivers/infiniband/hw/ipath
diff options
context:
space:
mode:
authorMichael Albaugh <Michael.Albaugh@Qlogic.com>2008-04-17 00:09:26 -0400
committerRoland Dreier <rolandd@cisco.com>2008-04-17 00:09:26 -0400
commit4330e4dad780467d930b394b5119c0218a1e2dbe (patch)
treebd0e113cbdcda5122a056431c084b079e9fe1684 /drivers/infiniband/hw/ipath
parent8c641d4b5f6653b6c486eab4d8e8d59539066f31 (diff)
IB/ipath: Prevent link-recovery code from negating admin disable
The link can be put in LINKDOWN_DISABLE state either locally or via a MAD. However, the link-recovery code will take it out of that state as a side-effect of attempts to clear SerDes/XGXS issues. We add a flag to indicate "link is down on purpose, leave it alone." Signed-off-by: Michael Albaugh <michael.albaugh@qlogic.com> Signed-off-by: Roland Dreier <rolandd@cisco.com>
Diffstat (limited to 'drivers/infiniband/hw/ipath')
-rw-r--r--drivers/infiniband/hw/ipath/ipath_debug.h1
-rw-r--r--drivers/infiniband/hw/ipath/ipath_driver.c70
-rw-r--r--drivers/infiniband/hw/ipath/ipath_init_chip.c5
-rw-r--r--drivers/infiniband/hw/ipath/ipath_intr.c2
-rw-r--r--drivers/infiniband/hw/ipath/ipath_kernel.h2
-rw-r--r--drivers/infiniband/hw/ipath/ipath_mad.c4
6 files changed, 55 insertions, 29 deletions
diff --git a/drivers/infiniband/hw/ipath/ipath_debug.h b/drivers/infiniband/hw/ipath/ipath_debug.h
index 7170bd20cfbb..65926cd35759 100644
--- a/drivers/infiniband/hw/ipath/ipath_debug.h
+++ b/drivers/infiniband/hw/ipath/ipath_debug.h
@@ -90,6 +90,7 @@
90#define __IPATH_IPATHERR 0x0 /* Ethernet (IPATH) errors on */ 90#define __IPATH_IPATHERR 0x0 /* Ethernet (IPATH) errors on */
91#define __IPATH_IPATHPD 0x0 /* Ethernet (IPATH) packet dump on */ 91#define __IPATH_IPATHPD 0x0 /* Ethernet (IPATH) packet dump on */
92#define __IPATH_IPATHTABLE 0x0 /* Ethernet (IPATH) packet dump on */ 92#define __IPATH_IPATHTABLE 0x0 /* Ethernet (IPATH) packet dump on */
93#define __IPATH_LINKVERBDBG 0x0 /* very verbose linkchange debug */
93 94
94#endif /* _IPATH_DEBUGGING */ 95#endif /* _IPATH_DEBUGGING */
95 96
diff --git a/drivers/infiniband/hw/ipath/ipath_driver.c b/drivers/infiniband/hw/ipath/ipath_driver.c
index 130f4db7b8c1..1299171c1e50 100644
--- a/drivers/infiniband/hw/ipath/ipath_driver.c
+++ b/drivers/infiniband/hw/ipath/ipath_driver.c
@@ -1664,30 +1664,48 @@ void ipath_cancel_sends(struct ipath_devdata *dd, int restore_sendctrl)
1664 ipath_read_kreg64(dd, dd->ipath_kregs->kr_scratch); 1664 ipath_read_kreg64(dd, dd->ipath_kregs->kr_scratch);
1665} 1665}
1666 1666
1667 1667static void ipath_set_ib_lstate(struct ipath_devdata *dd, int linkcmd,
1668static void ipath_set_ib_lstate(struct ipath_devdata *dd, int which) 1668 int linitcmd)
1669{ 1669{
1670 u64 mod_wd;
1670 static const char *what[4] = { 1671 static const char *what[4] = {
1671 [0] = "NOP", 1672 [0] = "NOP",
1672 [INFINIPATH_IBCC_LINKCMD_DOWN] = "DOWN", 1673 [INFINIPATH_IBCC_LINKCMD_DOWN] = "DOWN",
1673 [INFINIPATH_IBCC_LINKCMD_ARMED] = "ARMED", 1674 [INFINIPATH_IBCC_LINKCMD_ARMED] = "ARMED",
1674 [INFINIPATH_IBCC_LINKCMD_ACTIVE] = "ACTIVE" 1675 [INFINIPATH_IBCC_LINKCMD_ACTIVE] = "ACTIVE"
1675 }; 1676 };
1676 int linkcmd = (which >> INFINIPATH_IBCC_LINKCMD_SHIFT) &
1677 INFINIPATH_IBCC_LINKCMD_MASK;
1678 1677
1679 ipath_cdbg(VERBOSE, "Trying to move unit %u to %s, current ltstate " 1678 if (linitcmd == INFINIPATH_IBCC_LINKINITCMD_DISABLE) {
1680 "is %s\n", dd->ipath_unit, 1679 /*
1681 what[linkcmd], 1680 * If we are told to disable, note that so link-recovery
1682 ipath_ibcstatus_str[ipath_ib_linktrstate(dd, 1681 * code does not attempt to bring us back up.
1682 */
1683 preempt_disable();
1684 dd->ipath_flags |= IPATH_IB_LINK_DISABLED;
1685 preempt_enable();
1686 } else if (linitcmd) {
1687 /*
1688 * Any other linkinitcmd will lead to LINKDOWN and then
1689 * to INIT (if all is well), so clear flag to let
1690 * link-recovery code attempt to bring us back up.
1691 */
1692 preempt_disable();
1693 dd->ipath_flags &= ~IPATH_IB_LINK_DISABLED;
1694 preempt_enable();
1695 }
1696
1697 mod_wd = (linkcmd << dd->ibcc_lc_shift) |
1698 (linitcmd << INFINIPATH_IBCC_LINKINITCMD_SHIFT);
1699 ipath_cdbg(VERBOSE,
1700 "Moving unit %u to %s (initcmd=0x%x), current ltstate is %s\n",
1701 dd->ipath_unit, what[linkcmd], linitcmd,
1702 ipath_ibcstatus_str[ipath_ib_linktrstate(dd,
1683 ipath_read_kreg64(dd, dd->ipath_kregs->kr_ibcstatus))]); 1703 ipath_read_kreg64(dd, dd->ipath_kregs->kr_ibcstatus))]);
1684 /* flush all queued sends when going to DOWN to be sure that
1685 * they don't block MAD packets */
1686 if (linkcmd == INFINIPATH_IBCC_LINKCMD_DOWN)
1687 ipath_cancel_sends(dd, 1);
1688 1704
1689 ipath_write_kreg(dd, dd->ipath_kregs->kr_ibcctrl, 1705 ipath_write_kreg(dd, dd->ipath_kregs->kr_ibcctrl,
1690 dd->ipath_ibcctrl | which); 1706 dd->ipath_ibcctrl | mod_wd);
1707 /* read from chip so write is flushed */
1708 (void) ipath_read_kreg64(dd, dd->ipath_kregs->kr_ibcstatus);
1691} 1709}
1692 1710
1693int ipath_set_linkstate(struct ipath_devdata *dd, u8 newstate) 1711int ipath_set_linkstate(struct ipath_devdata *dd, u8 newstate)
@@ -1697,30 +1715,28 @@ int ipath_set_linkstate(struct ipath_devdata *dd, u8 newstate)
1697 1715
1698 switch (newstate) { 1716 switch (newstate) {
1699 case IPATH_IB_LINKDOWN_ONLY: 1717 case IPATH_IB_LINKDOWN_ONLY:
1700 ipath_set_ib_lstate(dd, INFINIPATH_IBCC_LINKCMD_DOWN << 1718 ipath_set_ib_lstate(dd, INFINIPATH_IBCC_LINKCMD_DOWN, 0);
1701 INFINIPATH_IBCC_LINKCMD_SHIFT);
1702 /* don't wait */ 1719 /* don't wait */
1703 ret = 0; 1720 ret = 0;
1704 goto bail; 1721 goto bail;
1705 1722
1706 case IPATH_IB_LINKDOWN: 1723 case IPATH_IB_LINKDOWN:
1707 ipath_set_ib_lstate(dd, INFINIPATH_IBCC_LINKINITCMD_POLL << 1724 ipath_set_ib_lstate(dd, INFINIPATH_IBCC_LINKCMD_DOWN,
1708 INFINIPATH_IBCC_LINKINITCMD_SHIFT); 1725 INFINIPATH_IBCC_LINKINITCMD_POLL);
1709 /* don't wait */ 1726 /* don't wait */
1710 ret = 0; 1727 ret = 0;
1711 goto bail; 1728 goto bail;
1712 1729
1713 case IPATH_IB_LINKDOWN_SLEEP: 1730 case IPATH_IB_LINKDOWN_SLEEP:
1714 ipath_set_ib_lstate(dd, INFINIPATH_IBCC_LINKINITCMD_SLEEP << 1731 ipath_set_ib_lstate(dd, INFINIPATH_IBCC_LINKCMD_DOWN,
1715 INFINIPATH_IBCC_LINKINITCMD_SHIFT); 1732 INFINIPATH_IBCC_LINKINITCMD_SLEEP);
1716 /* don't wait */ 1733 /* don't wait */
1717 ret = 0; 1734 ret = 0;
1718 goto bail; 1735 goto bail;
1719 1736
1720 case IPATH_IB_LINKDOWN_DISABLE: 1737 case IPATH_IB_LINKDOWN_DISABLE:
1721 ipath_set_ib_lstate(dd, 1738 ipath_set_ib_lstate(dd, INFINIPATH_IBCC_LINKCMD_DOWN,
1722 INFINIPATH_IBCC_LINKINITCMD_DISABLE << 1739 INFINIPATH_IBCC_LINKINITCMD_DISABLE);
1723 INFINIPATH_IBCC_LINKINITCMD_SHIFT);
1724 /* don't wait */ 1740 /* don't wait */
1725 ret = 0; 1741 ret = 0;
1726 goto bail; 1742 goto bail;
@@ -1735,8 +1751,8 @@ int ipath_set_linkstate(struct ipath_devdata *dd, u8 newstate)
1735 ret = -EINVAL; 1751 ret = -EINVAL;
1736 goto bail; 1752 goto bail;
1737 } 1753 }
1738 ipath_set_ib_lstate(dd, INFINIPATH_IBCC_LINKCMD_ARMED << 1754 ipath_set_ib_lstate(dd, INFINIPATH_IBCC_LINKCMD_ARMED, 0);
1739 INFINIPATH_IBCC_LINKCMD_SHIFT); 1755
1740 /* 1756 /*
1741 * Since the port can transition to ACTIVE by receiving 1757 * Since the port can transition to ACTIVE by receiving
1742 * a non VL 15 packet, wait for either state. 1758 * a non VL 15 packet, wait for either state.
@@ -1753,8 +1769,7 @@ int ipath_set_linkstate(struct ipath_devdata *dd, u8 newstate)
1753 ret = -EINVAL; 1769 ret = -EINVAL;
1754 goto bail; 1770 goto bail;
1755 } 1771 }
1756 ipath_set_ib_lstate(dd, INFINIPATH_IBCC_LINKCMD_ACTIVE << 1772 ipath_set_ib_lstate(dd, INFINIPATH_IBCC_LINKCMD_ACTIVE, 0);
1757 INFINIPATH_IBCC_LINKCMD_SHIFT);
1758 lstate = IPATH_LINKACTIVE; 1773 lstate = IPATH_LINKACTIVE;
1759 break; 1774 break;
1760 1775
@@ -2026,8 +2041,7 @@ void ipath_shutdown_device(struct ipath_devdata *dd)
2026 */ 2041 */
2027 udelay(5); 2042 udelay(5);
2028 2043
2029 ipath_set_ib_lstate(dd, INFINIPATH_IBCC_LINKINITCMD_DISABLE << 2044 ipath_set_ib_lstate(dd, 0, INFINIPATH_IBCC_LINKINITCMD_DISABLE);
2030 INFINIPATH_IBCC_LINKINITCMD_SHIFT);
2031 ipath_cancel_sends(dd, 0); 2045 ipath_cancel_sends(dd, 0);
2032 2046
2033 signal_ib_event(dd, IB_EVENT_PORT_ERR); 2047 signal_ib_event(dd, IB_EVENT_PORT_ERR);
diff --git a/drivers/infiniband/hw/ipath/ipath_init_chip.c b/drivers/infiniband/hw/ipath/ipath_init_chip.c
index 524fdf7d8c88..46c70656d538 100644
--- a/drivers/infiniband/hw/ipath/ipath_init_chip.c
+++ b/drivers/infiniband/hw/ipath/ipath_init_chip.c
@@ -180,10 +180,13 @@ static int bringup_link(struct ipath_devdata *dd)
180 /* 180 /*
181 * Want to start out with both LINKCMD and LINKINITCMD in NOP 181 * Want to start out with both LINKCMD and LINKINITCMD in NOP
182 * (0 and 0). Don't put linkinitcmd in ipath_ibcctrl, want that 182 * (0 and 0). Don't put linkinitcmd in ipath_ibcctrl, want that
183 * to stay a NOP 183 * to stay a NOP. Flag that we are disabled, for the (unlikely)
184 * case that some recovery path is trying to bring the link up
185 * before we are ready.
184 */ 186 */
185 ibc |= INFINIPATH_IBCC_LINKINITCMD_DISABLE << 187 ibc |= INFINIPATH_IBCC_LINKINITCMD_DISABLE <<
186 INFINIPATH_IBCC_LINKINITCMD_SHIFT; 188 INFINIPATH_IBCC_LINKINITCMD_SHIFT;
189 dd->ipath_flags |= IPATH_IB_LINK_DISABLED;
187 ipath_cdbg(VERBOSE, "Writing 0x%llx to ibcctrl\n", 190 ipath_cdbg(VERBOSE, "Writing 0x%llx to ibcctrl\n",
188 (unsigned long long) ibc); 191 (unsigned long long) ibc);
189 ipath_write_kreg(dd, dd->ipath_kregs->kr_ibcctrl, ibc); 192 ipath_write_kreg(dd, dd->ipath_kregs->kr_ibcctrl, ibc);
diff --git a/drivers/infiniband/hw/ipath/ipath_intr.c b/drivers/infiniband/hw/ipath/ipath_intr.c
index ed82ecbb02da..5608e3268a62 100644
--- a/drivers/infiniband/hw/ipath/ipath_intr.c
+++ b/drivers/infiniband/hw/ipath/ipath_intr.c
@@ -309,6 +309,8 @@ static void handle_e_ibstatuschanged(struct ipath_devdata *dd,
309 lastlstate == INFINIPATH_IBCS_L_STATE_DOWN) { 309 lastlstate == INFINIPATH_IBCS_L_STATE_DOWN) {
310 /* transitioned to UP */ 310 /* transitioned to UP */
311 if (dd->ipath_f_ib_updown(dd, 1, ibcs)) { 311 if (dd->ipath_f_ib_updown(dd, 1, ibcs)) {
312 /* link came up, so we must no longer be disabled */
313 dd->ipath_flags &= ~IPATH_IB_LINK_DISABLED;
312 ipath_cdbg(LINKVERB, "LinkUp handled, skipped\n"); 314 ipath_cdbg(LINKVERB, "LinkUp handled, skipped\n");
313 goto skip_ibchange; /* chip-code handled */ 315 goto skip_ibchange; /* chip-code handled */
314 } 316 }
diff --git a/drivers/infiniband/hw/ipath/ipath_kernel.h b/drivers/infiniband/hw/ipath/ipath_kernel.h
index b8b81cb745b9..2510359b1c83 100644
--- a/drivers/infiniband/hw/ipath/ipath_kernel.h
+++ b/drivers/infiniband/hw/ipath/ipath_kernel.h
@@ -848,6 +848,8 @@ void ipath_hol_event(unsigned long);
848 /* Suppress heartbeat, even if turning off loopback */ 848 /* Suppress heartbeat, even if turning off loopback */
849#define IPATH_NO_HRTBT 0x1000000 849#define IPATH_NO_HRTBT 0x1000000
850#define IPATH_HAS_MULT_IB_SPEED 0x8000000 850#define IPATH_HAS_MULT_IB_SPEED 0x8000000
851 /* Linkdown-disable intentionally, Do not attempt to bring up */
852#define IPATH_IB_LINK_DISABLED 0x40000000
851#define IPATH_IB_FORCE_NOTIFY 0x80000000 /* force notify on next ib change */ 853#define IPATH_IB_FORCE_NOTIFY 0x80000000 /* force notify on next ib change */
852 854
853/* Bits in GPIO for the added interrupts */ 855/* Bits in GPIO for the added interrupts */
diff --git a/drivers/infiniband/hw/ipath/ipath_mad.c b/drivers/infiniband/hw/ipath/ipath_mad.c
index 7516a2608988..30b2f44406b1 100644
--- a/drivers/infiniband/hw/ipath/ipath_mad.c
+++ b/drivers/infiniband/hw/ipath/ipath_mad.c
@@ -590,6 +590,10 @@ static int recv_subn_set_portinfo(struct ib_smp *smp,
590 else 590 else
591 goto err; 591 goto err;
592 ipath_set_linkstate(dd, lstate); 592 ipath_set_linkstate(dd, lstate);
593 if (lstate == IPATH_IB_LINKDOWN_DISABLE) {
594 ret = IB_MAD_RESULT_SUCCESS | IB_MAD_RESULT_CONSUMED;
595 goto done;
596 }
593 ipath_wait_linkstate(dd, IPATH_LINKINIT | IPATH_LINKARMED | 597 ipath_wait_linkstate(dd, IPATH_LINKINIT | IPATH_LINKARMED |
594 IPATH_LINKACTIVE, 1000); 598 IPATH_LINKACTIVE, 1000);
595 break; 599 break;