Skip to content

Commit

Permalink
transceivers-server: keep LEDs off while not in A0 (#1998)
Browse files Browse the repository at this point in the history
While Sidecar is not in A0 the transceivers-server will now keep the
LEDs off. The current behavior is that the LEDs only change state when
Dendrite tells them to, and while the Sidecar is not in Dendrite isn't
doing much at all! An A0->A2 transition left the LEDs in their current
state which is confusing for folks who may have eyes on the switch as it
would indicate Dendrite is running when it is in fact not. The system
attention LED is unaffected by this commit.

fixes #1995
  • Loading branch information
Aaron-Hartwig authored Feb 4, 2025
1 parent c98911c commit 5f34cc5
Showing 1 changed file with 33 additions and 14 deletions.
47 changes: 33 additions & 14 deletions drv/transceivers-server/src/main.rs
Original file line number Diff line number Diff line change
Expand Up @@ -21,7 +21,7 @@ use drv_sidecar_front_io::{
},
Reg,
};
use drv_sidecar_seq_api::{SeqError, Sequencer};
use drv_sidecar_seq_api::{SeqError, Sequencer, TofinoSeqState};
use drv_transceivers_api::{
ModuleStatus, TransceiversError, NUM_PORTS, TRANSCEIVER_TEMPERATURE_SENSORS,
};
Expand Down Expand Up @@ -78,6 +78,7 @@ enum Trace {
DisablingPorts(LogicalPortMask),
DisableFailed(usize, LogicalPortMask),
ClearDisabledPorts(LogicalPortMask),
SeqError(SeqError),
}

counted_ringbuf!(Trace, 16, Trace::None);
Expand Down Expand Up @@ -193,21 +194,26 @@ impl ServerImpl {
self.system_led_state
}

fn update_leds(&mut self) {
// handle port LEDs
fn update_leds(&mut self, seq_state: TofinoSeqState) {
let mut next_state = LogicalPortMask(0);
for (i, state) in self.led_states.0.into_iter().enumerate() {
let i = LogicalPort(i as u8);
match state {
LedState::On => next_state.set(i),
LedState::Blink => {
if self.blink_on {
next_state.set(i)

// We only turn transceiver LEDs on when Sidecar is in A0, since that is when there can be
// meaningful link activity happening. When outside of A0, we default the LEDs to off.
if seq_state == TofinoSeqState::A0 {
for (i, state) in self.led_states.0.into_iter().enumerate() {
let i = LogicalPort(i as u8);
match state {
LedState::On => next_state.set(i),
LedState::Blink => {
if self.blink_on {
next_state.set(i)
}
}
LedState::Off => (),
}
LedState::Off => (),
}
}

if let Err(e) = self.leds.update_led_state(next_state) {
ringbuf_entry!(Trace::LEDUpdateError(e));
}
Expand Down Expand Up @@ -512,9 +518,9 @@ impl ServerImpl {
// the `sensors` and `thermal` tasks.
}

fn handle_i2c_loop(&mut self) {
fn handle_i2c_loop(&mut self, seq_state: TofinoSeqState) {
if self.leds_initialized {
self.update_leds();
self.update_leds(seq_state);
let errors = match self.leds.error_summary() {
Ok(errs) => errs,
Err(e) => {
Expand Down Expand Up @@ -719,10 +725,23 @@ fn main() -> ! {
for t in multitimer.iter_fired() {
match t {
Timers::I2C => {
// Check what power state we are in since that can impact LED state which is
// part of the I2C loop.
let seq_state =
seq.tofino_seq_state().unwrap_or_else(|e| {
// The failure path here is that we cannot get the state from the FPGA.
// If we cannot communicate with the FPGA then something has likely went
// rather wrong, and we are probably not in A0. For handling the error
// we will assume to be in the Init state, since that is what the main
// sequencer does as well.
ringbuf_entry!(Trace::SeqError(e));
TofinoSeqState::Init
});

// Handle the Front IO status checking as part of this
// loop because the frequency is what we had before and
// the server itself has no knowledge of the sequencer.
server.handle_i2c_loop();
server.handle_i2c_loop(seq_state);
}
Timers::SPI => {
if server.front_io_board_present == FrontIOStatus::Ready {
Expand Down

0 comments on commit 5f34cc5

Please sign in to comment.