aboutsummaryrefslogtreecommitdiffstats
path: root/drivers/infiniband/hw/qib
diff options
context:
space:
mode:
authorMitko Haralanov <mitko@qlogic.com>2011-10-19 18:46:47 -0400
committerRoland Dreier <roland@purestorage.com>2011-10-31 13:57:59 -0400
commit16d99812d58b8af2df29cd337a74cd965b53da04 (patch)
treeb370dec6b40a274ef2192414ce6377c974dea8d5 /drivers/infiniband/hw/qib
parentdde05cbdf8b1c404344c370fe6e18ff160d6da6a (diff)
IB/qib: Fix issue with link states and QSFP cables
Fix an issue where the link would come up after replugging a cable even if it has been DISABLED manually. Signed-off-by: Mitko Haralanov <mitko@qlogic.com> Signed-off-by: Mike Marciniszyn <mike.marciniszyn@qlogic.com> Signed-off-by: Roland Dreier <roland@purestorage.com>
Diffstat (limited to 'drivers/infiniband/hw/qib')
-rw-r--r--drivers/infiniband/hw/qib/qib_iba7322.c30
-rw-r--r--drivers/infiniband/hw/qib/qib_qsfp.h1
2 files changed, 21 insertions, 10 deletions
diff --git a/drivers/infiniband/hw/qib/qib_iba7322.c b/drivers/infiniband/hw/qib/qib_iba7322.c
index 86575fbcaef7..efd0a110091f 100644
--- a/drivers/infiniband/hw/qib/qib_iba7322.c
+++ b/drivers/infiniband/hw/qib/qib_iba7322.c
@@ -2310,12 +2310,15 @@ static int qib_7322_bringup_serdes(struct qib_pportdata *ppd)
2310 val = ppd->cpspec->ibcctrl_a | (QLOGIC_IB_IBCC_LINKINITCMD_DISABLE << 2310 val = ppd->cpspec->ibcctrl_a | (QLOGIC_IB_IBCC_LINKINITCMD_DISABLE <<
2311 QLOGIC_IB_IBCC_LINKINITCMD_SHIFT); 2311 QLOGIC_IB_IBCC_LINKINITCMD_SHIFT);
2312 2312
2313 ppd->cpspec->ibcctrl_a = val;
2313 /* 2314 /*
2314 * Reset the PCS interface to the serdes (and also ibc, which is still 2315 * Reset the PCS interface to the serdes (and also ibc, which is still
2315 * in reset from above). Writes new value of ibcctrl_a as last step. 2316 * in reset from above). Writes new value of ibcctrl_a as last step.
2316 */ 2317 */
2317 qib_7322_mini_pcs_reset(ppd); 2318 qib_7322_mini_pcs_reset(ppd);
2318 qib_write_kreg(dd, kr_scratch, 0ULL); 2319 qib_write_kreg(dd, kr_scratch, 0ULL);
2320 /* clear the linkinit cmds */
2321 ppd->cpspec->ibcctrl_a &= ~SYM_MASK(IBCCtrlA_0, LinkInitCmd);
2319 2322
2320 if (!ppd->cpspec->ibcctrl_b) { 2323 if (!ppd->cpspec->ibcctrl_b) {
2321 unsigned lse = ppd->link_speed_enabled; 2324 unsigned lse = ppd->link_speed_enabled;
@@ -2381,11 +2384,6 @@ static int qib_7322_bringup_serdes(struct qib_pportdata *ppd)
2381 ppd->cpspec->ibcctrl_a |= SYM_MASK(IBCCtrlA_0, IBLinkEn); 2384 ppd->cpspec->ibcctrl_a |= SYM_MASK(IBCCtrlA_0, IBLinkEn);
2382 set_vls(ppd); 2385 set_vls(ppd);
2383 2386
2384 /* Hold the link state machine for mezz boards */
2385 qib_set_ib_7322_lstate(ppd, 0,
2386 QLOGIC_IB_IBCC_LINKINITCMD_DISABLE);
2387
2388
2389 /* be paranoid against later code motion, etc. */ 2387 /* be paranoid against later code motion, etc. */
2390 spin_lock_irqsave(&dd->cspec->rcvmod_lock, flags); 2388 spin_lock_irqsave(&dd->cspec->rcvmod_lock, flags);
2391 ppd->p_rcvctrl |= SYM_MASK(RcvCtrl_0, RcvIBPortEnable); 2389 ppd->p_rcvctrl |= SYM_MASK(RcvCtrl_0, RcvIBPortEnable);
@@ -5594,6 +5592,7 @@ static void qsfp_7322_event(struct work_struct *work)
5594 struct qib_qsfp_data *qd; 5592 struct qib_qsfp_data *qd;
5595 struct qib_pportdata *ppd; 5593 struct qib_pportdata *ppd;
5596 u64 pwrup; 5594 u64 pwrup;
5595 unsigned long flags;
5597 int ret; 5596 int ret;
5598 u32 le2; 5597 u32 le2;
5599 5598
@@ -5605,11 +5604,15 @@ static void qsfp_7322_event(struct work_struct *work)
5605 /* Delay for 20 msecs to allow ModPrs resistor to setup */ 5604 /* Delay for 20 msecs to allow ModPrs resistor to setup */
5606 mdelay(QSFP_MODPRS_LAG_MSEC); 5605 mdelay(QSFP_MODPRS_LAG_MSEC);
5607 5606
5608 if (!qib_qsfp_mod_present(ppd)) 5607 if (!qib_qsfp_mod_present(ppd)) {
5608 ppd->cpspec->qsfp_data.modpresent = 0;
5609 /* Set the physical link to disabled */ 5609 /* Set the physical link to disabled */
5610 qib_set_ib_7322_lstate(ppd, 0, 5610 qib_set_ib_7322_lstate(ppd, 0,
5611 QLOGIC_IB_IBCC_LINKINITCMD_DISABLE); 5611 QLOGIC_IB_IBCC_LINKINITCMD_DISABLE);
5612 else { 5612 spin_lock_irqsave(&ppd->lflags_lock, flags);
5613 ppd->lflags &= ~QIBL_LINKV;
5614 spin_unlock_irqrestore(&ppd->lflags_lock, flags);
5615 } else {
5613 /* 5616 /*
5614 * Some QSFP's not only do not respond until the full power-up 5617 * Some QSFP's not only do not respond until the full power-up
5615 * time, but may behave badly if we try. So hold off responding 5618 * time, but may behave badly if we try. So hold off responding
@@ -5649,11 +5652,18 @@ static void qsfp_7322_event(struct work_struct *work)
5649 */ 5652 */
5650 init_txdds_table(ppd, 0); 5653 init_txdds_table(ppd, 0);
5651 /* The physical link is being re-enabled only when the 5654 /* The physical link is being re-enabled only when the
5652 previous state was DISABLED. This should only happen when 5655 * previous state was DISABLED and the VALID bit is not
5653 the cable has been physically pulled. */ 5656 * set. This should only happen when the cable has been
5654 if (ppd->lflags & QIBL_IB_LINK_DISABLED) 5657 * physically pulled. */
5658 if (!ppd->cpspec->qsfp_data.modpresent &&
5659 (ppd->lflags & (QIBL_LINKV | QIBL_IB_LINK_DISABLED))) {
5660 ppd->cpspec->qsfp_data.modpresent = 1;
5655 qib_set_ib_7322_lstate(ppd, 0, 5661 qib_set_ib_7322_lstate(ppd, 0,
5656 QLOGIC_IB_IBCC_LINKINITCMD_SLEEP); 5662 QLOGIC_IB_IBCC_LINKINITCMD_SLEEP);
5663 spin_lock_irqsave(&ppd->lflags_lock, flags);
5664 ppd->lflags |= QIBL_LINKV;
5665 spin_unlock_irqrestore(&ppd->lflags_lock, flags);
5666 }
5657 } 5667 }
5658} 5668}
5659 5669
diff --git a/drivers/infiniband/hw/qib/qib_qsfp.h b/drivers/infiniband/hw/qib/qib_qsfp.h
index 786a92a25c25..46002a9417c0 100644
--- a/drivers/infiniband/hw/qib/qib_qsfp.h
+++ b/drivers/infiniband/hw/qib/qib_qsfp.h
@@ -178,6 +178,7 @@ struct qib_qsfp_data {
178 struct work_struct work; 178 struct work_struct work;
179 struct qib_qsfp_cache cache; 179 struct qib_qsfp_cache cache;
180 u64 t_insert; 180 u64 t_insert;
181 u8 modpresent;
181}; 182};
182 183
183extern int qib_refresh_qsfp_cache(struct qib_pportdata *ppd, 184extern int qib_refresh_qsfp_cache(struct qib_pportdata *ppd,