diff options
author | Mitko Haralanov <mitko@qlogic.com> | 2011-10-19 18:46:47 -0400 |
---|---|---|
committer | Roland Dreier <roland@purestorage.com> | 2011-10-31 13:57:59 -0400 |
commit | 16d99812d58b8af2df29cd337a74cd965b53da04 (patch) | |
tree | b370dec6b40a274ef2192414ce6377c974dea8d5 /drivers/infiniband/hw/qib | |
parent | dde05cbdf8b1c404344c370fe6e18ff160d6da6a (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.c | 30 | ||||
-rw-r--r-- | drivers/infiniband/hw/qib/qib_qsfp.h | 1 |
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 | ||
183 | extern int qib_refresh_qsfp_cache(struct qib_pportdata *ppd, | 184 | extern int qib_refresh_qsfp_cache(struct qib_pportdata *ppd, |