Commit 409b1462 authored by Easwar Hariharan's avatar Easwar Hariharan Committed by Doug Ledford

staging/rdma/hfi1: Fix reporting of LED status in Get(LedInfo) and Get(PortInfo)

The LedInfo SMA attribute is redefined to control the LED beaconing
state machine instead of the LED directly. In accordance, we now
return the state of LED beaconing, represented by whether the beaconing
timer is active, instead of the state of the LED itself for SMA queries
Get(LedInfo) and Get(PortInfo). While we are at it, we fix the beaconing
timer control code so that the state of the timer is accurately updated.
Reviewed-by: default avatarIra Weiny <ira.weiny@intel.com>
Reviewed-by: default avatarMike Marciniszyn <mike.marciniszyn@intel.com>
Signed-off-by: default avatarEaswar Hariharan <easwar.hariharan@intel.com>
Signed-off-by: default avatarJubin John <jubin.john@intel.com>
Signed-off-by: default avatarDoug Ledford <dledford@redhat.com>
parent 24487dd3
...@@ -1169,6 +1169,12 @@ void shutdown_led_override(struct hfi1_pportdata *ppd) ...@@ -1169,6 +1169,12 @@ void shutdown_led_override(struct hfi1_pportdata *ppd)
{ {
struct hfi1_devdata *dd = ppd->dd; struct hfi1_devdata *dd = ppd->dd;
/*
* This pairs with the memory barrier implied by the atomic_dec in
* hfi1_set_led_override to ensure that we read the correct state of
* LED beaconing represented by led_override_timer_active
*/
smp_mb();
if (atomic_read(&ppd->led_override_timer_active)) { if (atomic_read(&ppd->led_override_timer_active)) {
del_timer_sync(&ppd->led_override_timer); del_timer_sync(&ppd->led_override_timer);
atomic_set(&ppd->led_override_timer_active, 0); atomic_set(&ppd->led_override_timer_active, 0);
...@@ -1199,11 +1205,14 @@ static void run_led_override(unsigned long opaque) ...@@ -1199,11 +1205,14 @@ static void run_led_override(unsigned long opaque)
* don't re-fire the timer if user asked for it to be off; we let * don't re-fire the timer if user asked for it to be off; we let
* it fire one more time after they turn it off to simplify * it fire one more time after they turn it off to simplify
*/ */
if (ppd->led_override_vals[0] || ppd->led_override_vals[1]) if (ppd->led_override_vals[0] || ppd->led_override_vals[1]) {
mod_timer(&ppd->led_override_timer, jiffies + timeout); mod_timer(&ppd->led_override_timer, jiffies + timeout);
else } else {
/* Hand control of the LED to the DC for normal operation */ /* Hand control of the LED to the DC for normal operation */
write_csr(dd, DCC_CFG_LED_CNTRL, 0); write_csr(dd, DCC_CFG_LED_CNTRL, 0);
/* Record that we did not re-fire the timer */
atomic_dec(&ppd->led_override_timer_active);
}
} }
/* /*
......
...@@ -516,6 +516,7 @@ static int __subn_get_opa_portinfo(struct opa_smp *smp, u32 am, u8 *data, ...@@ -516,6 +516,7 @@ static int __subn_get_opa_portinfo(struct opa_smp *smp, u32 am, u8 *data,
struct opa_port_info *pi = (struct opa_port_info *)data; struct opa_port_info *pi = (struct opa_port_info *)data;
u8 mtu; u8 mtu;
u8 credit_rate; u8 credit_rate;
u8 is_beaconing_active;
u32 state; u32 state;
u32 num_ports = OPA_AM_NPORT(am); u32 num_ports = OPA_AM_NPORT(am);
u32 start_of_sm_config = OPA_AM_START_SM_CFG(am); u32 start_of_sm_config = OPA_AM_START_SM_CFG(am);
...@@ -581,6 +582,14 @@ static int __subn_get_opa_portinfo(struct opa_smp *smp, u32 am, u8 *data, ...@@ -581,6 +582,14 @@ static int __subn_get_opa_portinfo(struct opa_smp *smp, u32 am, u8 *data,
pi->port_states.ledenable_offlinereason = ppd->neighbor_normal << 4; pi->port_states.ledenable_offlinereason = ppd->neighbor_normal << 4;
pi->port_states.ledenable_offlinereason |= pi->port_states.ledenable_offlinereason |=
ppd->is_sm_config_started << 5; ppd->is_sm_config_started << 5;
/*
* This pairs with the memory barrier implied by the atomic_dec in
* hfi1_set_led_override to ensure that we read the correct state of
* LED beaconing represented by led_override_timer_active
*/
smp_mb();
is_beaconing_active = !!atomic_read(&ppd->led_override_timer_active);
pi->port_states.ledenable_offlinereason |= is_beaconing_active << 6;
pi->port_states.ledenable_offlinereason |= pi->port_states.ledenable_offlinereason |=
ppd->offline_disabled_reason; ppd->offline_disabled_reason;
#else #else
...@@ -3578,19 +3587,24 @@ static int __subn_get_opa_led_info(struct opa_smp *smp, u32 am, u8 *data, ...@@ -3578,19 +3587,24 @@ static int __subn_get_opa_led_info(struct opa_smp *smp, u32 am, u8 *data,
u32 *resp_len) u32 *resp_len)
{ {
struct hfi1_devdata *dd = dd_from_ibdev(ibdev); struct hfi1_devdata *dd = dd_from_ibdev(ibdev);
struct hfi1_pportdata *ppd = dd->pport;
struct opa_led_info *p = (struct opa_led_info *)data; struct opa_led_info *p = (struct opa_led_info *)data;
u32 nport = OPA_AM_NPORT(am); u32 nport = OPA_AM_NPORT(am);
u64 reg; u32 is_beaconing_active;
if (nport != 1) { if (nport != 1) {
smp->status |= IB_SMP_INVALID_FIELD; smp->status |= IB_SMP_INVALID_FIELD;
return reply((struct ib_mad_hdr *)smp); return reply((struct ib_mad_hdr *)smp);
} }
reg = read_csr(dd, DCC_CFG_LED_CNTRL); /*
if ((reg & DCC_CFG_LED_CNTRL_LED_CNTRL_SMASK) && * This pairs with the memory barrier implied by the atomic_dec in
((reg & DCC_CFG_LED_CNTRL_LED_SW_BLINK_RATE_SMASK) == 0xf)) * hfi1_set_led_override to ensure that we read the correct state of
p->rsvd_led_mask = cpu_to_be32(OPA_LED_MASK); * LED beaconing represented by led_override_timer_active
*/
smp_mb();
is_beaconing_active = !!atomic_read(&ppd->led_override_timer_active);
p->rsvd_led_mask = cpu_to_be32(is_beaconing_active << OPA_LED_SHIFT);
if (resp_len) if (resp_len)
*resp_len += sizeof(struct opa_led_info); *resp_len += sizeof(struct opa_led_info);
......
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