Commit a9c05e35 authored by Bryan Morgan's avatar Bryan Morgan Committed by Doug Ledford

staging/rdma/hfi1: HFI reports wrong offline disabled reason when cable removed

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: default avatarMike Marciniszyn <mike.marciniszyn@intel.com>
Reviewed-by: default avatarEaswar Hariharan <easwar.hariharan@intel.com>
Reviewed-by: default avatarDean Luick <dean.luick@intel.com>
Reported-by: default avatarTodd Rimmer <todd.rimmer@intel.com>
Signed-off-by: default avatarBryan Morgan <bryan.c.morgan@intel.com>
Signed-off-by: default avatarJubin John <jubin.john@intel.com>
Signed-off-by: default avatarDoug Ledford <dledford@redhat.com>
parent 9cd70e1b
......@@ -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.
......
......@@ -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.
......
......@@ -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);
......
......@@ -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 =
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment