IB/qib: Fix issue with link states and QSFP cables
authorMitko Haralanov <mitko@qlogic.com>
Wed, 19 Oct 2011 22:46:47 +0000 (18:46 -0400)
committerRoland Dreier <roland@purestorage.com>
Mon, 31 Oct 2011 17:57:59 +0000 (10:57 -0700)
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>
drivers/infiniband/hw/qib/qib_iba7322.c
drivers/infiniband/hw/qib/qib_qsfp.h

index 86575fb..efd0a11 100644 (file)
@@ -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;
@@ -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);
@@ -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;
 
@@ -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
@@ -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);
+               }
        }
 }
 
index 786a92a..46002a9 100644 (file)
@@ -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,