Skip to content

Commit

Permalink
IB/qib: Fix issue with link states and QSFP cables
Browse files Browse the repository at this point in the history
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>
  • Loading branch information
Mitko Haralanov authored and Roland Dreier committed Oct 31, 2011
1 parent dde05cb commit 16d9981
Show file tree
Hide file tree
Showing 2 changed files with 21 additions and 10 deletions.
30 changes: 20 additions & 10 deletions drivers/infiniband/hw/qib/qib_iba7322.c
Original file line number Diff line number Diff line change
Expand Up @@ -2310,12 +2310,15 @@ static int qib_7322_bringup_serdes(struct qib_pportdata *ppd)
val = ppd->cpspec->ibcctrl_a | (QLOGIC_IB_IBCC_LINKINITCMD_DISABLE <<
QLOGIC_IB_IBCC_LINKINITCMD_SHIFT);

ppd->cpspec->ibcctrl_a = val;
/*
* Reset the PCS interface to the serdes (and also ibc, which is still
* in reset from above). Writes new value of ibcctrl_a as last step.
*/
qib_7322_mini_pcs_reset(ppd);
qib_write_kreg(dd, kr_scratch, 0ULL);
/* clear the linkinit cmds */
ppd->cpspec->ibcctrl_a &= ~SYM_MASK(IBCCtrlA_0, LinkInitCmd);

if (!ppd->cpspec->ibcctrl_b) {
unsigned lse = ppd->link_speed_enabled;
Expand Down Expand Up @@ -2381,11 +2384,6 @@ static int qib_7322_bringup_serdes(struct qib_pportdata *ppd)
ppd->cpspec->ibcctrl_a |= SYM_MASK(IBCCtrlA_0, IBLinkEn);
set_vls(ppd);

/* Hold the link state machine for mezz boards */
qib_set_ib_7322_lstate(ppd, 0,
QLOGIC_IB_IBCC_LINKINITCMD_DISABLE);


/* be paranoid against later code motion, etc. */
spin_lock_irqsave(&dd->cspec->rcvmod_lock, flags);
ppd->p_rcvctrl |= SYM_MASK(RcvCtrl_0, RcvIBPortEnable);
Expand Down Expand Up @@ -5594,6 +5592,7 @@ static void qsfp_7322_event(struct work_struct *work)
struct qib_qsfp_data *qd;
struct qib_pportdata *ppd;
u64 pwrup;
unsigned long flags;
int ret;
u32 le2;

Expand All @@ -5605,11 +5604,15 @@ static void qsfp_7322_event(struct work_struct *work)
/* Delay for 20 msecs to allow ModPrs resistor to setup */
mdelay(QSFP_MODPRS_LAG_MSEC);

if (!qib_qsfp_mod_present(ppd))
if (!qib_qsfp_mod_present(ppd)) {
ppd->cpspec->qsfp_data.modpresent = 0;
/* Set the physical link to disabled */
qib_set_ib_7322_lstate(ppd, 0,
QLOGIC_IB_IBCC_LINKINITCMD_DISABLE);
else {
spin_lock_irqsave(&ppd->lflags_lock, flags);
ppd->lflags &= ~QIBL_LINKV;
spin_unlock_irqrestore(&ppd->lflags_lock, flags);
} else {
/*
* Some QSFP's not only do not respond until the full power-up
* time, but may behave badly if we try. So hold off responding
Expand Down Expand Up @@ -5649,11 +5652,18 @@ static void qsfp_7322_event(struct work_struct *work)
*/
init_txdds_table(ppd, 0);
/* The physical link is being re-enabled only when the
previous state was DISABLED. This should only happen when
the cable has been physically pulled. */
if (ppd->lflags & QIBL_IB_LINK_DISABLED)
* previous state was DISABLED and the VALID bit is not
* set. This should only happen when the cable has been
* physically pulled. */
if (!ppd->cpspec->qsfp_data.modpresent &&
(ppd->lflags & (QIBL_LINKV | QIBL_IB_LINK_DISABLED))) {
ppd->cpspec->qsfp_data.modpresent = 1;
qib_set_ib_7322_lstate(ppd, 0,
QLOGIC_IB_IBCC_LINKINITCMD_SLEEP);
spin_lock_irqsave(&ppd->lflags_lock, flags);
ppd->lflags |= QIBL_LINKV;
spin_unlock_irqrestore(&ppd->lflags_lock, flags);
}
}
}

Expand Down
1 change: 1 addition & 0 deletions drivers/infiniband/hw/qib/qib_qsfp.h
Original file line number Diff line number Diff line change
Expand Up @@ -178,6 +178,7 @@ struct qib_qsfp_data {
struct work_struct work;
struct qib_qsfp_cache cache;
u64 t_insert;
u8 modpresent;
};

extern int qib_refresh_qsfp_cache(struct qib_pportdata *ppd,
Expand Down

0 comments on commit 16d9981

Please sign in to comment.