IB/qib: Improve SERDES tunning on QMH boards
authorMike Marciniszyn <mike.marciniszyn@qlogic.com>
Tue, 11 Jan 2011 01:42:22 +0000 (17:42 -0800)
committerRoland Dreier <rolandd@cisco.com>
Tue, 11 Jan 2011 01:42:22 +0000 (17:42 -0800)
Improve the QMH SERDES tunning on initial driver load by having the
driver go through a link state change.

Signed-off-by: Mike Marciniszyn <mike.marciniszyn@qlogic.com>
Signed-off-by: Roland Dreier <rolandd@cisco.com>
drivers/infiniband/hw/qib/qib_iba7322.c

index d3b493824cdcd0a34a27833034ce234f4b5f6180..dbbb0e85afe438317a05954a9b043d984694271f 100644 (file)
@@ -623,6 +623,7 @@ struct qib_chippport_specific {
        u8 ibmalfusesnap;
        struct qib_qsfp_data qsfp_data;
        char epmsgbuf[192]; /* for port error interrupt msg buffer */
+       u8 bounced;
 };
 
 static struct {
@@ -1742,6 +1743,8 @@ static void handle_serdes_issues(struct qib_pportdata *ppd, u64 ibcst)
        }
 }
 
+static int qib_7322_set_ib_cfg(struct qib_pportdata *, int, u32);
+
 /*
  * This is per-pport error handling.
  * will likely get it's own MSIx interrupt (one for each port,
@@ -1878,7 +1881,23 @@ static noinline void handle_7322_p_errors(struct qib_pportdata *ppd)
                    IB_PHYSPORTSTATE_DISABLED)
                        qib_set_ib_7322_lstate(ppd, 0,
                               QLOGIC_IB_IBCC_LINKINITCMD_DISABLE);
-               else
+               else {
+                       u32 lstate;
+                       /*
+                        * We need the current logical link state before
+                        * lflags are set in handle_e_ibstatuschanged.
+                        */
+                       lstate = qib_7322_iblink_state(ibcs);
+
+                       if (IS_QMH(dd) && !ppd->cpspec->bounced &&
+                           ltstate == IB_PHYSPORTSTATE_LINKUP &&
+                           (lstate >= IB_PORT_INIT &&
+                               lstate <= IB_PORT_ACTIVE)) {
+                               ppd->cpspec->bounced = 1;
+                               qib_7322_set_ib_cfg(ppd, QIB_IB_CFG_LSTATE,
+                                       IB_LINKCMD_DOWN | IB_LINKINITCMD_POLL);
+                       }
+
                        /*
                         * Since going into a recovery state causes the link
                         * state to go down and since recovery is transitory,
@@ -1892,6 +1911,7 @@ static noinline void handle_7322_p_errors(struct qib_pportdata *ppd)
                            ltstate != IB_PHYSPORTSTATE_RECOVERY_WAITRMT &&
                            ltstate != IB_PHYSPORTSTATE_RECOVERY_IDLE)
                                qib_handle_e_ibstatuschanged(ppd, ibcs);
+               }
        }
        if (*msg && iserr)
                qib_dev_porterr(dd, ppd->port, "%s error\n", msg);
@@ -7282,8 +7302,8 @@ static void ibsd_wr_allchans(struct qib_pportdata *ppd, int addr, unsigned data,
 static void serdes_7322_los_enable(struct qib_pportdata *ppd, int enable)
 {
        u64 data = qib_read_kreg_port(ppd, krp_serdesctrl);
-       printk(KERN_INFO QIB_DRV_NAME " Turning LOS %s for port %d\n",
-                (enable ? "on" : "off"), ppd->port);
+       printk(KERN_INFO QIB_DRV_NAME " IB%u:%u Turning LOS %s\n",
+               ppd->dd->unit, ppd->port, (enable ? "on" : "off"));
        if (enable)
                data |= SYM_MASK(IBSerdesCtrl_0, RXLOSEN);
        else