]> git.karo-electronics.de Git - linux-beck.git/commitdiff
IB/hfi1: Explain state complete frame details
authorDean Luick <dean.luick@intel.com>
Mon, 25 Jul 2016 20:38:56 +0000 (13:38 -0700)
committerDoug Ledford <dledford@redhat.com>
Tue, 2 Aug 2016 20:00:58 +0000 (16:00 -0400)
When link up fails in LNI, the local and peer state complete
frames are reported as numbers.  Explain what the values mean
so the operator can better diagnose the problem.

Reviewed-by: Easwar Hariharan <easwar.hariharan@intel.com>
Signed-off-by: Dean Luick <dean.luick@intel.com>
Signed-off-by: Dennis Dalessandro <dennis.dalessandro@intel.com>
Signed-off-by: Doug Ledford <dledford@redhat.com>
drivers/infiniband/hw/hfi1/chip.c

index e5f49eff47ea4e4cc167b647be6bd5eafa6b5160..f3782b37ef78d20883c6eb1d4d48c9315ca55caf 100644 (file)
@@ -9918,6 +9918,131 @@ static int wait_phy_linkstate(struct hfi1_devdata *dd, u32 state, u32 msecs)
        return 0;
 }
 
+static const char *state_completed_string(u32 completed)
+{
+       static const char * const state_completed[] = {
+               "EstablishComm",
+               "OptimizeEQ",
+               "VerifyCap"
+       };
+
+       if (completed < ARRAY_SIZE(state_completed))
+               return state_completed[completed];
+
+       return "unknown";
+}
+
+static const char all_lanes_dead_timeout_expired[] =
+       "All lanes were inactive – was the interconnect media removed?";
+static const char tx_out_of_policy[] =
+       "Passing lanes on local port do not meet the local link width policy";
+static const char no_state_complete[] =
+       "State timeout occurred before link partner completed the state";
+static const char * const state_complete_reasons[] = {
+       [0x00] = "Reason unknown",
+       [0x01] = "Link was halted by driver, refer to LinkDownReason",
+       [0x02] = "Link partner reported failure",
+       [0x10] = "Unable to achieve frame sync on any lane",
+       [0x11] =
+         "Unable to find a common bit rate with the link partner",
+       [0x12] =
+         "Unable to achieve frame sync on sufficient lanes to meet the local link width policy",
+       [0x13] =
+         "Unable to identify preset equalization on sufficient lanes to meet the local link width policy",
+       [0x14] = no_state_complete,
+       [0x15] =
+         "State timeout occurred before link partner identified equalization presets",
+       [0x16] =
+         "Link partner completed the EstablishComm state, but the passing lanes do not meet the local link width policy",
+       [0x17] = tx_out_of_policy,
+       [0x20] = all_lanes_dead_timeout_expired,
+       [0x21] =
+         "Unable to achieve acceptable BER on sufficient lanes to meet the local link width policy",
+       [0x22] = no_state_complete,
+       [0x23] =
+         "Link partner completed the OptimizeEq state, but the passing lanes do not meet the local link width policy",
+       [0x24] = tx_out_of_policy,
+       [0x30] = all_lanes_dead_timeout_expired,
+       [0x31] =
+         "State timeout occurred waiting for host to process received frames",
+       [0x32] = no_state_complete,
+       [0x33] =
+         "Link partner completed the VerifyCap state, but the passing lanes do not meet the local link width policy",
+       [0x34] = tx_out_of_policy,
+};
+
+static const char *state_complete_reason_code_string(struct hfi1_pportdata *ppd,
+                                                    u32 code)
+{
+       const char *str = NULL;
+
+       if (code < ARRAY_SIZE(state_complete_reasons))
+               str = state_complete_reasons[code];
+
+       if (str)
+               return str;
+       return "Reserved";
+}
+
+/* describe the given last state complete frame */
+static void decode_state_complete(struct hfi1_pportdata *ppd, u32 frame,
+                                 const char *prefix)
+{
+       struct hfi1_devdata *dd = ppd->dd;
+       u32 success;
+       u32 state;
+       u32 reason;
+       u32 lanes;
+
+       /*
+        * Decode frame:
+        *  [ 0: 0] - success
+        *  [ 3: 1] - state
+        *  [ 7: 4] - next state timeout
+        *  [15: 8] - reason code
+        *  [31:16] - lanes
+        */
+       success = frame & 0x1;
+       state = (frame >> 1) & 0x7;
+       reason = (frame >> 8) & 0xff;
+       lanes = (frame >> 16) & 0xffff;
+
+       dd_dev_err(dd, "Last %s LNI state complete frame 0x%08x:\n",
+                  prefix, frame);
+       dd_dev_err(dd, "    last reported state state: %s (0x%x)\n",
+                  state_completed_string(state), state);
+       dd_dev_err(dd, "    state successfully completed: %s\n",
+                  success ? "yes" : "no");
+       dd_dev_err(dd, "    fail reason 0x%x: %s\n",
+                  reason, state_complete_reason_code_string(ppd, reason));
+       dd_dev_err(dd, "    passing lane mask: 0x%x", lanes);
+}
+
+/*
+ * Read the last state complete frames and explain them.  This routine
+ * expects to be called if the link went down during link negotiation
+ * and initialization (LNI).  That is, anywhere between polling and link up.
+ */
+static void check_lni_states(struct hfi1_pportdata *ppd)
+{
+       u32 last_local_state;
+       u32 last_remote_state;
+
+       read_last_local_state(ppd->dd, &last_local_state);
+       read_last_remote_state(ppd->dd, &last_remote_state);
+
+       /*
+        * Don't report anything if there is nothing to report.  A value of
+        * 0 means the link was taken down while polling and there was no
+        * training in-process.
+        */
+       if (last_local_state == 0 && last_remote_state == 0)
+               return;
+
+       decode_state_complete(ppd, last_local_state, "transmitted");
+       decode_state_complete(ppd, last_remote_state, "received");
+}
+
 /*
  * Helper for set_link_state().  Do not call except from that routine.
  * Expects ppd->hls_mutex to be held.
@@ -9930,8 +10055,6 @@ static int goto_offline(struct hfi1_pportdata *ppd, u8 rem_reason)
 {
        struct hfi1_devdata *dd = ppd->dd;
        u32 pstate, previous_state;
-       u32 last_local_state;
-       u32 last_remote_state;
        int ret;
        int do_transition;
        int do_wait;
@@ -10031,12 +10154,7 @@ static int goto_offline(struct hfi1_pportdata *ppd, u8 rem_reason)
        } else if (previous_state
                        & (HLS_DN_POLL | HLS_VERIFY_CAP | HLS_GOING_UP)) {
                /* went down while attempting link up */
-               /* byte 1 of last_*_state is the failure reason */
-               read_last_local_state(dd, &last_local_state);
-               read_last_remote_state(dd, &last_remote_state);
-               dd_dev_err(dd,
-                          "LNI failure last states: local 0x%08x, remote 0x%08x\n",
-                          last_local_state, last_remote_state);
+               check_lni_states(ppd);
        }
 
        /* the active link width (downgrade) is 0 on link down */