@@ -15,6 +15,7 @@ use drv_packrat_vpd_loader::{read_vpd_and_load_packrat, Packrat};
1515use drv_spartan7_loader_api:: Spartan7Loader ;
1616use drv_spi_api:: { SpiDevice , SpiServer } ;
1717use drv_stm32xx_sys_api:: { self as sys_api, Sys } ;
18+ use fixedstr:: FixedStr ;
1819use idol_runtime:: { NotificationHandler , RequestError } ;
1920use task_jefe_api:: Jefe ;
2021use userlib:: {
@@ -102,6 +103,9 @@ enum Trace {
102103 } ,
103104 UnexpectedInterrupt ,
104105 CPUPresent ( bool ) ,
106+ EreportSent ( usize ) ,
107+ EreportLost ( usize , task_packrat_api:: EreportWriteError ) ,
108+ EreportTooBig ,
105109}
106110counted_ringbuf ! ( Trace , 128 , Trace :: None ) ;
107111
@@ -160,13 +164,70 @@ struct StateMachineStates {
160164 nic : Result < fmc_sequencer:: NicSm , u8 > ,
161165}
162166
167+ const EREPORT_BUF_LEN : usize = {
168+ let n = microcbor:: max_cbor_len_for!(
169+ task_packrat_api:: Ereport <EreportClass , EreportKind >,
170+ ) ;
171+ // someday, we will have const max.
172+ if n < 256 {
173+ 256
174+ } else {
175+ n
176+ }
177+ } ;
178+
163179#[ export_name = "main" ]
164180fn main ( ) -> ! {
165181 // Populate packrat with our mac address and identity.
166182 let packrat = Packrat :: from ( PACKRAT . get_task_id ( ) ) ;
167183 read_vpd_and_load_packrat ( & packrat, I2C . get_task_id ( ) ) ;
168184
169- match init ( packrat) {
185+ let ereport_buf = {
186+ use static_cell:: ClaimOnceCell ;
187+ static EREPORT_BUF : ClaimOnceCell < [ u8 ; EREPORT_BUF_LEN ] > =
188+ ClaimOnceCell :: new ( [ 0 ; EREPORT_BUF_LEN ] ) ;
189+ EREPORT_BUF . claim ( )
190+ } ;
191+
192+ //
193+ // Apply the configuration mitigation on the BMR491, if required. This
194+ // is an external device access and may fail. We'll attempt it thrice
195+ // and then allow boot to continue.
196+ //
197+ {
198+ use drv_i2c_devices:: bmr491:: { Bmr491 , ExternalInputVoltageProtection } ;
199+
200+ let dev = i2c_config:: devices:: bmr491_u80 ( I2C . get_task_id ( ) ) ;
201+ let driver = Bmr491 :: new ( & dev, 0 ) ;
202+
203+ // Cosmo provides external undervoltage protection that kicks in at a
204+ // lower voltage than we'd like to tolerate, so, request additional
205+ // protection from the mitigation code.
206+ let protection = ExternalInputVoltageProtection :: CutoffBelow40V ;
207+
208+ let ( failures, last_cause, succeeded) =
209+ match driver. apply_mitigation_for_rma2402311 ( protection) {
210+ Ok ( r) => ( r. failures , r. last_failure , true ) ,
211+ Err ( e) => ( e. retries , Some ( e. last_cause ) , false ) ,
212+ } ;
213+
214+ if let Some ( last_cause) = last_cause {
215+ // Report the failure even if we eventually succeeded.
216+ try_send_ereport (
217+ & packrat,
218+ & mut ereport_buf[ ..] ,
219+ EreportClass :: Bmr491MitigationFailure ,
220+ EreportKind :: Bmr491MitigationFailure {
221+ refdes : FixedStr :: from_str ( dev. component_id ( ) ) ,
222+ failures,
223+ last_cause,
224+ succeeded,
225+ } ,
226+ ) ;
227+ }
228+ }
229+
230+ match init ( packrat, ereport_buf) {
170231 // Set up everything nicely, time to start serving incoming messages.
171232 Ok ( mut server) => {
172233 // Enable the backplane PCIe clock if requested
@@ -208,7 +269,10 @@ fn main() -> ! {
208269 }
209270}
210271
211- fn init ( packrat : Packrat ) -> Result < ServerImpl , SeqError > {
272+ fn init (
273+ packrat : Packrat ,
274+ ereport_buf : & ' static mut [ u8 ; EREPORT_BUF_LEN ] ,
275+ ) -> Result < ServerImpl , SeqError > {
212276 let sys = sys_api:: Sys :: from ( SYS . get_task_id ( ) ) ;
213277
214278 // Pull the fault line low while we're loading
@@ -299,7 +363,7 @@ fn init(packrat: Packrat) -> Result<ServerImpl, SeqError> {
299363 // Turn on the chassis LED!
300364 sys. gpio_set ( SP_CHASSIS_STATUS_LED ) ;
301365
302- Ok ( ServerImpl :: new ( loader, packrat) )
366+ Ok ( ServerImpl :: new ( loader, packrat, ereport_buf ) )
303367}
304368
305369/// Configures the front FPGA pins and holds it in reset
@@ -385,12 +449,27 @@ struct ServerImpl {
385449 ereport_buf : & ' static mut [ u8 ; EREPORT_BUF_LEN ] ,
386450}
387451
388- const EREPORT_BUF_LEN : usize = 256 ;
452+ #[ derive( microcbor:: Encode ) ]
453+ pub enum EreportClass {
454+ #[ cbor( rename = "hw.pwr.bmr491.mitfail" ) ]
455+ Bmr491MitigationFailure ,
456+ }
457+
458+ #[ derive( microcbor:: EncodeFields ) ]
459+ pub ( crate ) enum EreportKind {
460+ Bmr491MitigationFailure {
461+ refdes : FixedStr < { crate :: i2c_config:: MAX_COMPONENT_ID_LEN } > ,
462+ failures : u32 ,
463+ last_cause : drv_i2c_devices:: bmr491:: MitigationFailureKind ,
464+ succeeded : bool ,
465+ } ,
466+ }
389467
390468impl ServerImpl {
391469 fn new (
392470 loader : drv_spartan7_loader_api:: Spartan7Loader ,
393471 packrat : Packrat ,
472+ ereport_buf : & ' static mut [ u8 ; EREPORT_BUF_LEN ] ,
394473 ) -> Self {
395474 let now = sys_get_timer ( ) . now ;
396475
@@ -410,13 +489,6 @@ impl ServerImpl {
410489 let jefe = Jefe :: from ( JEFE . get_task_id ( ) ) ;
411490 jefe. set_state ( PowerState :: A2 as u32 ) ;
412491
413- let ereport_buf = {
414- use static_cell:: ClaimOnceCell ;
415- static EREPORT_BUF : ClaimOnceCell < [ u8 ; EREPORT_BUF_LEN ] > =
416- ClaimOnceCell :: new ( [ 0 ; EREPORT_BUF_LEN ] ) ;
417- EREPORT_BUF . claim ( )
418- } ;
419-
420492 ServerImpl {
421493 state : PowerState :: A2 ,
422494 jefe,
@@ -978,6 +1050,31 @@ impl NotificationHandler for ServerImpl {
9781050 }
9791051}
9801052
1053+ fn try_send_ereport (
1054+ packrat : & task_packrat_api:: Packrat ,
1055+ ereport_buf : & mut [ u8 ] ,
1056+ class : EreportClass ,
1057+ report : EreportKind ,
1058+ ) {
1059+ let eresult = packrat. encode_ereport (
1060+ & task_packrat_api:: Ereport {
1061+ class,
1062+ version : 0 ,
1063+ report,
1064+ } ,
1065+ ereport_buf,
1066+ ) ;
1067+ match eresult {
1068+ Ok ( len) => ringbuf_entry ! ( Trace :: EreportSent ( len) ) ,
1069+ Err ( task_packrat_api:: EreportEncodeError :: Packrat { len, err } ) => {
1070+ ringbuf_entry ! ( Trace :: EreportLost ( len, err) )
1071+ }
1072+ Err ( task_packrat_api:: EreportEncodeError :: Encoder ( _) ) => {
1073+ ringbuf_entry ! ( Trace :: EreportTooBig )
1074+ }
1075+ }
1076+ }
1077+
9811078////////////////////////////////////////////////////////////////////////////////
9821079
9831080mod idl {
0 commit comments