aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorRalph Campbell <ralph.campbell@qlogic.com>2007-12-14 04:53:56 -0500
committerRoland Dreier <rolandd@cisco.com>2008-03-11 16:58:22 -0400
commit140277e9a710202608914b5b731948d2769399bc (patch)
treed30fa34b17ec1f42508c5d046926ed7a717126c4
parentbaadac8b10c5ac15ce3d26b68fa266c8889b163f (diff)
IB/ipath: Fix IB compliance problems with link state vs physical state
Subnet manager SetPortinfo messages distingush between changing the link state (DOWN, ARM, ACTIVE) and the link physical state (POLL, SLEEP, DISABLED). These are somewhat independent commands and affect when link width and speed changes take effect. Without this patch, a link DOWN physical state NOP command was causing the link width and speed settings to take effect which should only happen when the link physical state is goes down (either by a SMP or some link physical error like link errors exceeding the threshold). Signed-off-by: Ralph Campbell <ralph.campbell@qlogic.com> Signed-off-by: Roland Dreier <rolandd@cisco.com>
-rw-r--r--drivers/infiniband/hw/ipath/ipath_common.h2
-rw-r--r--drivers/infiniband/hw/ipath/ipath_driver.c28
-rw-r--r--drivers/infiniband/hw/ipath/ipath_kernel.h1
-rw-r--r--drivers/infiniband/hw/ipath/ipath_mad.c7
-rw-r--r--drivers/infiniband/hw/ipath/ipath_registers.h2
5 files changed, 18 insertions, 22 deletions
diff --git a/drivers/infiniband/hw/ipath/ipath_common.h b/drivers/infiniband/hw/ipath/ipath_common.h
index 414621095540..591901aab6b7 100644
--- a/drivers/infiniband/hw/ipath/ipath_common.h
+++ b/drivers/infiniband/hw/ipath/ipath_common.h
@@ -75,7 +75,7 @@
75#define IPATH_IB_LINKDOWN 0 75#define IPATH_IB_LINKDOWN 0
76#define IPATH_IB_LINKARM 1 76#define IPATH_IB_LINKARM 1
77#define IPATH_IB_LINKACTIVE 2 77#define IPATH_IB_LINKACTIVE 2
78#define IPATH_IB_LINKINIT 3 78#define IPATH_IB_LINKDOWN_ONLY 3
79#define IPATH_IB_LINKDOWN_SLEEP 4 79#define IPATH_IB_LINKDOWN_SLEEP 4
80#define IPATH_IB_LINKDOWN_DISABLE 5 80#define IPATH_IB_LINKDOWN_DISABLE 5
81#define IPATH_IB_LINK_LOOPBACK 6 /* enable local loopback */ 81#define IPATH_IB_LINK_LOOPBACK 6 /* enable local loopback */
diff --git a/drivers/infiniband/hw/ipath/ipath_driver.c b/drivers/infiniband/hw/ipath/ipath_driver.c
index d5ff6ca2db30..ca4d0acc6786 100644
--- a/drivers/infiniband/hw/ipath/ipath_driver.c
+++ b/drivers/infiniband/hw/ipath/ipath_driver.c
@@ -851,8 +851,7 @@ void ipath_disarm_piobufs(struct ipath_devdata *dd, unsigned first,
851 * -ETIMEDOUT state can have multiple states set, for any of several 851 * -ETIMEDOUT state can have multiple states set, for any of several
852 * transitions. 852 * transitions.
853 */ 853 */
854static int ipath_wait_linkstate(struct ipath_devdata *dd, u32 state, 854int ipath_wait_linkstate(struct ipath_devdata *dd, u32 state, int msecs)
855 int msecs)
856{ 855{
857 dd->ipath_state_wanted = state; 856 dd->ipath_state_wanted = state;
858 wait_event_interruptible_timeout(ipath_state_wait, 857 wait_event_interruptible_timeout(ipath_state_wait,
@@ -1656,8 +1655,8 @@ void ipath_cancel_sends(struct ipath_devdata *dd, int restore_sendctrl)
1656static void ipath_set_ib_lstate(struct ipath_devdata *dd, int which) 1655static void ipath_set_ib_lstate(struct ipath_devdata *dd, int which)
1657{ 1656{
1658 static const char *what[4] = { 1657 static const char *what[4] = {
1659 [0] = "DOWN", 1658 [0] = "NOP",
1660 [INFINIPATH_IBCC_LINKCMD_INIT] = "INIT", 1659 [INFINIPATH_IBCC_LINKCMD_DOWN] = "DOWN",
1661 [INFINIPATH_IBCC_LINKCMD_ARMED] = "ARMED", 1660 [INFINIPATH_IBCC_LINKCMD_ARMED] = "ARMED",
1662 [INFINIPATH_IBCC_LINKCMD_ACTIVE] = "ACTIVE" 1661 [INFINIPATH_IBCC_LINKCMD_ACTIVE] = "ACTIVE"
1663 }; 1662 };
@@ -1672,9 +1671,9 @@ static void ipath_set_ib_lstate(struct ipath_devdata *dd, int which)
1672 (dd, dd->ipath_kregs->kr_ibcstatus) >> 1671 (dd, dd->ipath_kregs->kr_ibcstatus) >>
1673 INFINIPATH_IBCS_LINKTRAININGSTATE_SHIFT) & 1672 INFINIPATH_IBCS_LINKTRAININGSTATE_SHIFT) &
1674 INFINIPATH_IBCS_LINKTRAININGSTATE_MASK]); 1673 INFINIPATH_IBCS_LINKTRAININGSTATE_MASK]);
1675 /* flush all queued sends when going to DOWN or INIT, to be sure that 1674 /* flush all queued sends when going to DOWN to be sure that
1676 * they don't block MAD packets */ 1675 * they don't block MAD packets */
1677 if (!linkcmd || linkcmd == INFINIPATH_IBCC_LINKCMD_INIT) 1676 if (linkcmd == INFINIPATH_IBCC_LINKCMD_DOWN)
1678 ipath_cancel_sends(dd, 1); 1677 ipath_cancel_sends(dd, 1);
1679 1678
1680 ipath_write_kreg(dd, dd->ipath_kregs->kr_ibcctrl, 1679 ipath_write_kreg(dd, dd->ipath_kregs->kr_ibcctrl,
@@ -1687,6 +1686,13 @@ int ipath_set_linkstate(struct ipath_devdata *dd, u8 newstate)
1687 int ret; 1686 int ret;
1688 1687
1689 switch (newstate) { 1688 switch (newstate) {
1689 case IPATH_IB_LINKDOWN_ONLY:
1690 ipath_set_ib_lstate(dd, INFINIPATH_IBCC_LINKCMD_DOWN <<
1691 INFINIPATH_IBCC_LINKCMD_SHIFT);
1692 /* don't wait */
1693 ret = 0;
1694 goto bail;
1695
1690 case IPATH_IB_LINKDOWN: 1696 case IPATH_IB_LINKDOWN:
1691 ipath_set_ib_lstate(dd, INFINIPATH_IBCC_LINKINITCMD_POLL << 1697 ipath_set_ib_lstate(dd, INFINIPATH_IBCC_LINKINITCMD_POLL <<
1692 INFINIPATH_IBCC_LINKINITCMD_SHIFT); 1698 INFINIPATH_IBCC_LINKINITCMD_SHIFT);
@@ -1709,16 +1715,6 @@ int ipath_set_linkstate(struct ipath_devdata *dd, u8 newstate)
1709 ret = 0; 1715 ret = 0;
1710 goto bail; 1716 goto bail;
1711 1717
1712 case IPATH_IB_LINKINIT:
1713 if (dd->ipath_flags & IPATH_LINKINIT) {
1714 ret = 0;
1715 goto bail;
1716 }
1717 ipath_set_ib_lstate(dd, INFINIPATH_IBCC_LINKCMD_INIT <<
1718 INFINIPATH_IBCC_LINKCMD_SHIFT);
1719 lstate = IPATH_LINKINIT;
1720 break;
1721
1722 case IPATH_IB_LINKARM: 1718 case IPATH_IB_LINKARM:
1723 if (dd->ipath_flags & IPATH_LINKARMED) { 1719 if (dd->ipath_flags & IPATH_LINKARMED) {
1724 ret = 0; 1720 ret = 0;
diff --git a/drivers/infiniband/hw/ipath/ipath_kernel.h b/drivers/infiniband/hw/ipath/ipath_kernel.h
index 4cc0f95ea877..ecf3f7ff7717 100644
--- a/drivers/infiniband/hw/ipath/ipath_kernel.h
+++ b/drivers/infiniband/hw/ipath/ipath_kernel.h
@@ -767,6 +767,7 @@ void ipath_kreceive(struct ipath_portdata *);
767int ipath_setrcvhdrsize(struct ipath_devdata *, unsigned); 767int ipath_setrcvhdrsize(struct ipath_devdata *, unsigned);
768int ipath_reset_device(int); 768int ipath_reset_device(int);
769void ipath_get_faststats(unsigned long); 769void ipath_get_faststats(unsigned long);
770int ipath_wait_linkstate(struct ipath_devdata *, u32, int);
770int ipath_set_linkstate(struct ipath_devdata *, u8); 771int ipath_set_linkstate(struct ipath_devdata *, u8);
771int ipath_set_mtu(struct ipath_devdata *, u16); 772int ipath_set_mtu(struct ipath_devdata *, u16);
772int ipath_set_lid(struct ipath_devdata *, u32, u8); 773int ipath_set_lid(struct ipath_devdata *, u32, u8);
diff --git a/drivers/infiniband/hw/ipath/ipath_mad.c b/drivers/infiniband/hw/ipath/ipath_mad.c
index d98d5f103700..b34b91d3723a 100644
--- a/drivers/infiniband/hw/ipath/ipath_mad.c
+++ b/drivers/infiniband/hw/ipath/ipath_mad.c
@@ -555,10 +555,7 @@ static int recv_subn_set_portinfo(struct ib_smp *smp,
555 /* FALLTHROUGH */ 555 /* FALLTHROUGH */
556 case IB_PORT_DOWN: 556 case IB_PORT_DOWN:
557 if (lstate == 0) 557 if (lstate == 0)
558 if (get_linkdowndefaultstate(dd)) 558 lstate = IPATH_IB_LINKDOWN_ONLY;
559 lstate = IPATH_IB_LINKDOWN_SLEEP;
560 else
561 lstate = IPATH_IB_LINKDOWN;
562 else if (lstate == 1) 559 else if (lstate == 1)
563 lstate = IPATH_IB_LINKDOWN_SLEEP; 560 lstate = IPATH_IB_LINKDOWN_SLEEP;
564 else if (lstate == 2) 561 else if (lstate == 2)
@@ -568,6 +565,8 @@ static int recv_subn_set_portinfo(struct ib_smp *smp,
568 else 565 else
569 goto err; 566 goto err;
570 ipath_set_linkstate(dd, lstate); 567 ipath_set_linkstate(dd, lstate);
568 ipath_wait_linkstate(dd, IPATH_LINKINIT | IPATH_LINKARMED |
569 IPATH_LINKACTIVE, 1000);
571 break; 570 break;
572 case IB_PORT_ARMED: 571 case IB_PORT_ARMED:
573 ipath_set_linkstate(dd, IPATH_IB_LINKARM); 572 ipath_set_linkstate(dd, IPATH_IB_LINKARM);
diff --git a/drivers/infiniband/hw/ipath/ipath_registers.h b/drivers/infiniband/hw/ipath/ipath_registers.h
index 6d2a17f9c1da..92ad73a7fff0 100644
--- a/drivers/infiniband/hw/ipath/ipath_registers.h
+++ b/drivers/infiniband/hw/ipath/ipath_registers.h
@@ -185,7 +185,7 @@
185#define INFINIPATH_IBCC_LINKINITCMD_SLEEP 3 185#define INFINIPATH_IBCC_LINKINITCMD_SLEEP 3
186#define INFINIPATH_IBCC_LINKINITCMD_SHIFT 16 186#define INFINIPATH_IBCC_LINKINITCMD_SHIFT 16
187#define INFINIPATH_IBCC_LINKCMD_MASK 0x3ULL 187#define INFINIPATH_IBCC_LINKCMD_MASK 0x3ULL
188#define INFINIPATH_IBCC_LINKCMD_INIT 1 /* move to 0x11 */ 188#define INFINIPATH_IBCC_LINKCMD_DOWN 1 /* move to 0x11 */
189#define INFINIPATH_IBCC_LINKCMD_ARMED 2 /* move to 0x21 */ 189#define INFINIPATH_IBCC_LINKCMD_ARMED 2 /* move to 0x21 */
190#define INFINIPATH_IBCC_LINKCMD_ACTIVE 3 /* move to 0x31 */ 190#define INFINIPATH_IBCC_LINKCMD_ACTIVE 3 /* move to 0x31 */
191#define INFINIPATH_IBCC_LINKCMD_SHIFT 18 191#define INFINIPATH_IBCC_LINKCMD_SHIFT 18