diff options
author | Michael Albaugh <Michael.Albaugh@Qlogic.com> | 2008-04-17 00:09:26 -0400 |
---|---|---|
committer | Roland Dreier <rolandd@cisco.com> | 2008-04-17 00:09:26 -0400 |
commit | 4330e4dad780467d930b394b5119c0218a1e2dbe (patch) | |
tree | bd0e113cbdcda5122a056431c084b079e9fe1684 /drivers/infiniband/hw/ipath | |
parent | 8c641d4b5f6653b6c486eab4d8e8d59539066f31 (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.h | 1 | ||||
-rw-r--r-- | drivers/infiniband/hw/ipath/ipath_driver.c | 70 | ||||
-rw-r--r-- | drivers/infiniband/hw/ipath/ipath_init_chip.c | 5 | ||||
-rw-r--r-- | drivers/infiniband/hw/ipath/ipath_intr.c | 2 | ||||
-rw-r--r-- | drivers/infiniband/hw/ipath/ipath_kernel.h | 2 | ||||
-rw-r--r-- | drivers/infiniband/hw/ipath/ipath_mad.c | 4 |
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 | 1667 | static void ipath_set_ib_lstate(struct ipath_devdata *dd, int linkcmd, | |
1668 | static 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 | ||
1693 | int ipath_set_linkstate(struct ipath_devdata *dd, u8 newstate) | 1711 | int 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; |