staging/rdma/hfi1: HFI reports wrong offline disabled reason when cable removed
authorBryan Morgan <bryan.c.morgan@intel.com>
Wed, 3 Feb 2016 22:30:49 +0000 (14:30 -0800)
committerDoug Ledford <dledford@redhat.com>
Fri, 11 Mar 2016 01:37:45 +0000 (20:37 -0500)
Removing QSFP cable should report 'No Local Media' instead of
'Transient' as reported by 'opaportinfo'.
Workaround is to change the state to
OPA_LINKDOWN_REASON_LOCAL_MEDIA_NOT_INSTALLED in cable handler.

With cable still removed, 'opaportinfo bounce' should not cause a
state change to Polling, as reported by 'opaportinfo'.
Resolution is to prevent physical state change from Offline->Polling.

Use a macro to mask lower nibble of OPA_LINKDOWN_REASON* as needed
for offline_disabled_reason.

Reviewed-by: Mike Marciniszyn <mike.marciniszyn@intel.com>
Reviewed-by: Easwar Hariharan <easwar.hariharan@intel.com>
Reviewed-by: Dean Luick <dean.luick@intel.com>
Reported-by: Todd Rimmer <todd.rimmer@intel.com>
Signed-off-by: Bryan Morgan <bryan.c.morgan@intel.com>
Signed-off-by: Jubin John <jubin.john@intel.com>
Signed-off-by: Doug Ledford <dledford@redhat.com>
drivers/staging/rdma/hfi1/chip.c
drivers/staging/rdma/hfi1/hfi.h
drivers/staging/rdma/hfi1/intr.c
drivers/staging/rdma/hfi1/mad.c

index 93e152dd4228fca43659c95425cfbd089cfdd7c4..16e2ff2b071df1267898f6f351f2604285a677a2 100644 (file)
@@ -5857,6 +5857,16 @@ static void handle_qsfp_int(struct hfi1_devdata *dd, u32 src_ctx, u64 reg)
                                                ASIC_QSFP2_INVERT :
                                                ASIC_QSFP1_INVERT,
                                qsfp_int_mgmt);
+
+                       if ((ppd->offline_disabled_reason >
+                         HFI1_ODR_MASK(
+                         OPA_LINKDOWN_REASONLOCAL_MEDIA_NOT_INSTALLED)) ||
+                         (ppd->offline_disabled_reason ==
+                         HFI1_ODR_MASK(OPA_LINKDOWN_REASON_NONE)))
+                               ppd->offline_disabled_reason =
+                               HFI1_ODR_MASK(
+                               OPA_LINKDOWN_REASONLOCAL_MEDIA_NOT_INSTALLED);
+
                        if (ppd->host_link_state == HLS_DN_POLL) {
                                /*
                                 * The link is still in POLL. This means
@@ -9615,9 +9625,10 @@ static int goto_offline(struct hfi1_pportdata *ppd, u8 rem_reason)
                                ret);
                        return -EINVAL;
                }
-               if (ppd->offline_disabled_reason == OPA_LINKDOWN_REASON_NONE)
+               if (ppd->offline_disabled_reason ==
+                               HFI1_ODR_MASK(OPA_LINKDOWN_REASON_NONE))
                        ppd->offline_disabled_reason =
-                       OPA_LINKDOWN_REASON_TRANSIENT;
+                       HFI1_ODR_MASK(OPA_LINKDOWN_REASON_TRANSIENT);
        }
 
        if (do_wait) {
@@ -9972,7 +9983,8 @@ int set_link_state(struct hfi1_pportdata *ppd, u32 state)
                                ret = -EINVAL;
                        }
                }
-               ppd->offline_disabled_reason = OPA_LINKDOWN_REASON_NONE;
+               ppd->offline_disabled_reason =
+                       HFI1_ODR_MASK(OPA_LINKDOWN_REASON_NONE);
                /*
                 * If an error occurred above, go back to offline.  The
                 * caller may reschedule another attempt.
index e6a5fede0c0242b3b80e49eed3a82f9800a73193..57014b017a0db54ab37065c30d0eb1c52c5e5410 100644 (file)
@@ -99,6 +99,8 @@ extern unsigned long hfi1_cap_mask;
 #define HFI1_CAP_IS_USET(cap) (!!HFI1_CAP_UGET(cap))
 #define HFI1_MISC_GET() ((hfi1_cap_mask >> HFI1_CAP_MISC_SHIFT) & \
                        HFI1_CAP_MISC_MASK)
+/* Offline Disabled Reason is 4-bits */
+#define HFI1_ODR_MASK(rsn) ((rsn) & OPA_PI_MASK_OFFLINE_REASON)
 
 /*
  * Control context is always 0 and handles the error packets.
index 1283f2d9136c1f8e634466504d9d15690f1f8fe5..9adab8638f21ab066b12e1247a4a6b52f605f1cc 100644 (file)
@@ -152,7 +152,8 @@ void handle_linkup_change(struct hfi1_devdata *dd, u32 linkup)
 
                /* physical link went up */
                ppd->linkup = 1;
-               ppd->offline_disabled_reason = OPA_LINKDOWN_REASON_NONE;
+               ppd->offline_disabled_reason =
+                       HFI1_ODR_MASK(OPA_LINKDOWN_REASON_NONE);
 
                /* link widths are not available until the link is fully up */
                get_linkup_link_widths(ppd);
index 9cadf77427a2163b0a2ee30a6566b5b69342d1e6..303dfeeed2bc0ab8ccaf5bc75ea8b3cc44faee14 100644 (file)
@@ -590,12 +590,11 @@ static int __subn_get_opa_portinfo(struct opa_smp *smp, u32 am, u8 *data,
        pi->port_states.ledenable_offlinereason |=
                ppd->is_sm_config_started << 5;
        pi->port_states.ledenable_offlinereason |=
-               ppd->offline_disabled_reason & OPA_PI_MASK_OFFLINE_REASON;
+               ppd->offline_disabled_reason;
 #else
        pi->port_states.offline_reason = ppd->neighbor_normal << 4;
        pi->port_states.offline_reason |= ppd->is_sm_config_started << 5;
-       pi->port_states.offline_reason |= ppd->offline_disabled_reason &
-                                               OPA_PI_MASK_OFFLINE_REASON;
+       pi->port_states.offline_reason |= ppd->offline_disabled_reason;
 #endif /* PI_LED_ENABLE_SUP */
 
        pi->port_states.portphysstate_portstate =
@@ -929,6 +928,14 @@ static int port_states_transition_allowed(struct hfi1_pportdata *ppd,
            physical_allowed == HFI_TRANSITION_IGNORED)
                return HFI_TRANSITION_IGNORED;
 
+       /*
+        * A change request of Physical Port State from
+        * 'Offline' to 'Polling' should be ignored.
+        */
+       if ((physical_old == OPA_PORTPHYSSTATE_OFFLINE) &&
+           (physical_new == IB_PORTPHYSSTATE_POLLING))
+               return HFI_TRANSITION_IGNORED;
+
        /*
         * Either physical_allowed or logical_allowed is
         * HFI_TRANSITION_ALLOWED.
@@ -993,11 +1000,11 @@ static int set_port_states(struct hfi1_pportdata *ppd, struct opa_smp *smp,
                set_link_state(ppd, link_state);
                if (link_state == HLS_DN_DISABLE &&
                    (ppd->offline_disabled_reason >
-                    OPA_LINKDOWN_REASON_SMA_DISABLED ||
+                    HFI1_ODR_MASK(OPA_LINKDOWN_REASON_SMA_DISABLED) ||
                     ppd->offline_disabled_reason ==
-                    OPA_LINKDOWN_REASON_NONE))
+                    HFI1_ODR_MASK(OPA_LINKDOWN_REASON_NONE)))
                        ppd->offline_disabled_reason =
-                       OPA_LINKDOWN_REASON_SMA_DISABLED;
+                       HFI1_ODR_MASK(OPA_LINKDOWN_REASON_SMA_DISABLED);
                /*
                 * Don't send a reply if the response would be sent
                 * through the disabled port.
@@ -1710,12 +1717,11 @@ static int __subn_get_opa_psi(struct opa_smp *smp, u32 am, u8 *data,
        psi->port_states.ledenable_offlinereason |=
                ppd->is_sm_config_started << 5;
        psi->port_states.ledenable_offlinereason |=
-               ppd->offline_disabled_reason & OPA_PI_MASK_OFFLINE_REASON;
+               ppd->offline_disabled_reason;
 #else
        psi->port_states.offline_reason = ppd->neighbor_normal << 4;
        psi->port_states.offline_reason |= ppd->is_sm_config_started << 5;
-       psi->port_states.offline_reason |= ppd->offline_disabled_reason &
-                               OPA_PI_MASK_OFFLINE_REASON;
+       psi->port_states.offline_reason |= ppd->offline_disabled_reason;
 #endif /* PI_LED_ENABLE_SUP */
 
        psi->port_states.portphysstate_portstate =