Skip to content
Draft
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
2 changes: 1 addition & 1 deletion .helix/languages.toml
Original file line number Diff line number Diff line change
Expand Up @@ -4,4 +4,4 @@ name = "rust"
# default to tofino_sde, can change this to any other feature such as softnpu
# as needed during development but in source control this should probably
# remain as tofino_sde
features = [ "tofino_sde" ]
features = [ "tofino_asic" ]
2 changes: 2 additions & 0 deletions Cargo.lock

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

1 change: 1 addition & 0 deletions aal/src/lib.rs
Original file line number Diff line number Diff line change
Expand Up @@ -43,6 +43,7 @@ pub trait SidecarIdentifiers {
fn asic_backend(&self) -> &str;
fn fab(&self) -> Option<char>;
fn lot(&self) -> Option<char>;
fn lotnum(&self) -> Option<[char; 4]>;
fn wafer(&self) -> Option<u8>;
fn wafer_loc(&self) -> Option<(i16, i16)>;
}
Expand Down
7 changes: 7 additions & 0 deletions asic/src/lib.rs
Original file line number Diff line number Diff line change
Expand Up @@ -36,6 +36,8 @@ pub struct Identifiers {
fab: Option<char>,
/// Lot identifier.
lot: Option<char>,
/// Lot number
lotnum: Option<[char; 4]>,
/// Wafer number within the lot.
wafer: Option<u8>,
/// The wafer location as (x, y) coordinates on the wafer, represented as
Expand All @@ -49,6 +51,7 @@ impl Default for Identifiers {
id: Uuid::new_v4(),
asic_backend: "chaos".to_string(),
fab: None,
lotnum: None,
lot: None,
wafer: None,
wafer_loc: None,
Expand All @@ -73,6 +76,10 @@ impl aal::SidecarIdentifiers for Identifiers {
self.lot
}

fn lotnum(&self) -> Option<[char; 4]> {
self.lotnum
}

fn wafer(&self) -> Option<u8> {
self.wafer
}
Expand Down
6 changes: 5 additions & 1 deletion asic/src/tofino_asic/bf_wrapper.rs
Original file line number Diff line number Diff line change
Expand Up @@ -356,6 +356,7 @@ pub fn bf_init(
devpath: &Option<String>,
p4_dir: &str,
sidecar_revision: &str,
skip_p4: bool,
) -> AsicResult<BfCommon> {
// Initialize the global callback state
{
Expand Down Expand Up @@ -388,7 +389,10 @@ pub fn bf_init(
rev.as_ptr(),
&mut ctx,
) {
0 => Box::new(ctx),
0 => {
ctx.skip_p4 = skip_p4;
Box::new(ctx)
}
rval => {
return Err(crate::tofino_asic::sde_error(
"initializing bf context",
Expand Down
112 changes: 112 additions & 0 deletions asic/src/tofino_asic/c/bf_wrapper.h
Original file line number Diff line number Diff line change
Expand Up @@ -27,6 +27,117 @@ int32_t bfw_init(const char *, bfw_common_t *hdl);
int32_t bfw_register();
void bfw_fini(bfw_common_t *hdl);

/*
* Memory test machinery
*/

typedef enum bf_diag_test_type_ {
BF_DIAG_TEST_TYPE_PIO,
BF_DIAG_TEST_TYPE_DMA,
} bf_diag_test_type_t;

typedef enum bf_diag_test_pattern_ {
BF_DIAG_TEST_PATTERN_RANDOM,
BF_DIAG_TEST_PATTERN_ZEROES,
BF_DIAG_TEST_PATTERN_ONES,
BF_DIAG_TEST_PATTERN_CHECKERBOARD,
BF_DIAG_TEST_PATTERN_INV_CHECKERBOARD,
BF_DIAG_TEST_PATTERN_PRBS,
BF_DIAG_TEST_PATTERN_USER_DEFINED,
} bf_diag_test_pattern_t;

typedef struct bf_diag_mem_data_error_ {
uint64_t addr;
uint64_t exp_0;
uint64_t exp_1;
uint64_t data_0;
uint64_t data_1;
uint64_t mask_0;
uint64_t mask_1;
} bf_diag_mem_data_error_t;

#define BF_DIAG_MEM_MAX_DATA_ERR 400
typedef struct bf_diag_mem_results_ {
bool overall_success;
bool ind_write_error;
bool ind_read_error;
bool write_list_error;
bool write_block_error;
uint64_t ind_write_error_addr;
uint64_t ind_read_error_addr;
uint32_t num_data_errors;
bf_diag_mem_data_error_t data_error[BF_DIAG_MEM_MAX_DATA_ERR];
uint32_t num_dma_msgs_sent;
uint32_t num_dma_cmplts_rcvd;
} bf_diag_mem_results_t;

bf_status_t
bf_diag_mem_test_mau(
bf_dev_id_t dev_id,
bf_diag_test_type_t test_type,
bool quick,
uint32_t pipe_bmp,
bf_diag_test_pattern_t pattern,
uint64_t pattern_data0,
uint64_t pattern_data1
);

bf_status_t
bf_diag_mem_test_result_get(
bf_dev_id_t dev_id,
bf_diag_mem_results_t *results,
bool *pass
);

pipe_status_t
pipe_mgr_tcam_scrub_timer_set(
bf_dev_id_t dev,
uint32_t msec_timer
);

uint32_t
pipe_mgr_tcam_scrub_timer_get(
bf_dev_id_t dev
);

bf_status_t
lld_enable_all_ints(
bf_dev_id_t dev_id,
bf_subdev_id_t subdev_id
);

bf_status_t
lld_dump_new_ints(
bf_dev_id_t dev_id,
bf_subdev_id_t subdev_id
);

bf_status_t
lld_int_poll(
bf_dev_id_t dev_id,
bf_subdev_id_t subdev_id,
bool all_ints
);

bf_status_t
bf_err_interrupt_handling_mode_set(
bf_dev_id_t dev_id,
bool enable
);

int
lld_write_register(
bf_dev_id_t dev_id,
uint32_t reg,
uint32_t data
);

bool
pipe_mgr_is_device_locked(
bf_dev_id_t dev_id
);


/*
* The SDE doesn't export this interface, so we define it here,
*/
Expand All @@ -43,4 +154,5 @@ struct driver_version {
uint32_t patch;
};


#endif /* BF_WRAPPER_H */
12 changes: 12 additions & 0 deletions asic/src/tofino_asic/imported_bf_functions
Original file line number Diff line number Diff line change
Expand Up @@ -160,3 +160,15 @@ bf_pm_fsm_transition_callback
bf_sys_log_callback

lld_sku_map_dev_port_id_to_mac_ch

# memory testing
bf_diag_mem_test_result_get
bf_diag_mem_test_mau
pipe_mgr_tcam_scrub_timer_set
pipe_mgr_tcam_scrub_timer_get
lld_enable_all_ints
lld_dump_new_ints
lld_int_poll
bf_err_interrupt_handling_mode_set
lld_write_register
pipe_mgr_is_device_locked
112 changes: 112 additions & 0 deletions asic/src/tofino_asic/interrupt_monitor.rs
Original file line number Diff line number Diff line change
@@ -0,0 +1,112 @@
// This Source Code Form is subject to the terms of the Mozilla Public
// License, v. 2.0. If a copy of the MPL was not distributed with this
// file, You can obtain one at https://mozilla.org/MPL/2.0/
//
// Copyright 2026 Oxide Computer Company

use std::{thread::sleep, time::Duration};

use crate::tofino_asic::{
BF_INVALID_ARG, BF_SUCCESS,
bf_wrapper::bf_error_str,
genpd::{
bf_dev_id_t, bf_err_interrupt_handling_mode_set, bf_subdev_id_t,
lld_dump_new_ints, lld_enable_all_ints, lld_int_poll,
pipe_mgr_is_device_locked, pipe_mgr_tcam_scrub_timer_set,
},
};
use slog::{Logger, info, warn};

const DEV_ID: bf_dev_id_t = 0;
const SUBDEV_ID: bf_subdev_id_t = 0;
const INTERVAL: Duration = Duration::from_secs(5);

pub fn monitor_interrupts(log: Logger) -> ! {
let log = log.new(slog::o!("unit" => "interrupt monitor"));
info!(log, "starring interrupt monitor");

wait_for_unlock(&log);
enable_tcam_scrub(&log);
set_interrupt_handling_mode(&log);
enable_lld_interrupts(&log);

monitoring_loop(&log)
}

fn wait_for_unlock(log: &Logger) {
loop {
if unsafe { pipe_mgr_is_device_locked(DEV_ID) } {
warn!(log, "asic is locked, cannot start");
sleep(INTERVAL);
continue;
}
info!(log, "asic is unlocked starting interrupt monitor");
break;
}
}

fn enable_tcam_scrub(log: &Logger) {
loop {
let rc = unsafe { pipe_mgr_tcam_scrub_timer_set(DEV_ID, 5000) };
if rc == BF_SUCCESS {
info!(log, "tcam scrub set to 5 second interval");
break;
}
warn!(
log,
"failed to enable tcam scrub";
"error" => bf_error_str(rc)
);
sleep(INTERVAL)
}
}

fn set_interrupt_handling_mode(log: &Logger) {
loop {
let rc = unsafe { bf_err_interrupt_handling_mode_set(DEV_ID, true) };
if rc == BF_SUCCESS {
info!(log, "interrupt handling mode set");
break;
}
warn!(
log,
"failed to set interrupt handling mode";
"error" => bf_error_str(rc)
);
sleep(INTERVAL);
}
}

fn enable_lld_interrupts(log: &Logger) {
loop {
let rc = unsafe { lld_enable_all_ints(DEV_ID, SUBDEV_ID) };
if rc == BF_SUCCESS {
info!(log, "enabled lld interrupts");
break;
}
warn!(
log,
"failed to enable lld interrupts";
"error" => bf_error_str(rc)
);
sleep(INTERVAL);
}
}

fn monitoring_loop(log: &Logger) -> ! {
loop {
let rc = unsafe { lld_int_poll(DEV_ID, SUBDEV_ID, true) };
if rc != BF_SUCCESS {
warn!(log, "lld_int_poll: {}", bf_error_str(rc));
}

let rc = unsafe { lld_dump_new_ints(DEV_ID, SUBDEV_ID) };
// BF_INVALID_ARG means interrupts were found and dumped (yes, really)
// BF_SUCCESS means no new interrupts
// Anything else is an actual error
if rc != BF_SUCCESS && rc != BF_INVALID_ARG {
warn!(log, "lld_dump_new_ints: {}", bf_error_str(rc));
}
sleep(INTERVAL);
}
}
Loading