drtio: async messages become synchronous

They are now a reply for DestinationStatusRequest.
This prevents gateware errors and lost packets if the receiver is busy.
This commit is contained in:
mwojcik 2023-08-24 17:34:35 +08:00 committed by Sébastien Bourdeauducq
parent 40ac2e03ab
commit eb57b3b393
8 changed files with 262 additions and 220 deletions

View File

@ -52,16 +52,18 @@ pub mod remote_analyzer {
pub data: Vec<u8> pub data: Vec<u8>
} }
pub fn get_data(io: &Io, aux_mutex: &Mutex, ddma_mutex: &Mutex, pub fn get_data(io: &Io, aux_mutex: &Mutex, routing_table: &drtio_routing::RoutingTable,
routing_table: &drtio_routing::RoutingTable, up_destinations: &Urc<RefCell<[bool; drtio_routing::DEST_COUNT]>>
up_destinations: &Urc<RefCell<[bool; drtio_routing::DEST_COUNT]>>) -> Result<RemoteBuffer, &'static str> { ) -> Result<RemoteBuffer, &'static str> {
// gets data from satellites and returns consolidated data // gets data from satellites and returns consolidated data
let mut remote_data: Vec<u8> = Vec::new(); let mut remote_data: Vec<u8> = Vec::new();
let mut remote_overflow = false; let mut remote_overflow = false;
let mut remote_sent_bytes = 0; let mut remote_sent_bytes = 0;
let mut remote_total_bytes = 0; let mut remote_total_bytes = 0;
let data_vec = match drtio::analyzer_query(io, aux_mutex, ddma_mutex, routing_table, up_destinations) { let data_vec = match drtio::analyzer_query(
io, aux_mutex, routing_table, up_destinations
) {
Ok(data_vec) => data_vec, Ok(data_vec) => data_vec,
Err(e) => return Err(e) Err(e) => return Err(e)
}; };
@ -83,7 +85,7 @@ pub mod remote_analyzer {
fn worker(stream: &mut TcpStream, _io: &Io, _aux_mutex: &Mutex, _ddma_mutex: &Mutex, fn worker(stream: &mut TcpStream, _io: &Io, _aux_mutex: &Mutex,
_routing_table: &drtio_routing::RoutingTable, _routing_table: &drtio_routing::RoutingTable,
_up_destinations: &Urc<RefCell<[bool; drtio_routing::DEST_COUNT]>> _up_destinations: &Urc<RefCell<[bool; drtio_routing::DEST_COUNT]>>
) -> Result<(), IoError<SchedError>> { ) -> Result<(), IoError<SchedError>> {
@ -97,7 +99,7 @@ fn worker(stream: &mut TcpStream, _io: &Io, _aux_mutex: &Mutex, _ddma_mutex: &Mu
#[cfg(has_drtio)] #[cfg(has_drtio)]
let remote = remote_analyzer::get_data( let remote = remote_analyzer::get_data(
_io, _aux_mutex, _ddma_mutex, _routing_table, _up_destinations); _io, _aux_mutex, _routing_table, _up_destinations);
#[cfg(has_drtio)] #[cfg(has_drtio)]
let (header, remote_data) = match remote { let (header, remote_data) = match remote {
Ok(remote) => (Header { Ok(remote) => (Header {
@ -144,7 +146,7 @@ fn worker(stream: &mut TcpStream, _io: &Io, _aux_mutex: &Mutex, _ddma_mutex: &Mu
Ok(()) Ok(())
} }
pub fn thread(io: Io, aux_mutex: &Mutex, ddma_mutex: &Mutex, pub fn thread(io: Io, aux_mutex: &Mutex,
routing_table: &Urc<RefCell<drtio_routing::RoutingTable>>, routing_table: &Urc<RefCell<drtio_routing::RoutingTable>>,
up_destinations: &Urc<RefCell<[bool; drtio_routing::DEST_COUNT]>>) { up_destinations: &Urc<RefCell<[bool; drtio_routing::DEST_COUNT]>>) {
let listener = TcpListener::new(&io, 65535); let listener = TcpListener::new(&io, 65535);
@ -159,7 +161,7 @@ pub fn thread(io: Io, aux_mutex: &Mutex, ddma_mutex: &Mutex,
disarm(); disarm();
let routing_table = routing_table.borrow(); let routing_table = routing_table.borrow();
match worker(&mut stream, &io, aux_mutex, ddma_mutex, &routing_table, up_destinations) { match worker(&mut stream, &io, aux_mutex, &routing_table, up_destinations) {
Ok(()) => (), Ok(()) => (),
Err(err) => error!("analyzer aborted: {}", err) Err(err) => error!("analyzer aborted: {}", err)
} }

View File

@ -14,11 +14,14 @@ mod remote_i2c {
use rtio_mgt::drtio; use rtio_mgt::drtio;
use sched::{Io, Mutex}; use sched::{Io, Mutex};
pub fn start(io: &Io, aux_mutex: &Mutex, ddma_mutex: &Mutex, linkno: u8, destination: u8, busno: u8) -> Result<(), &'static str> { pub fn start(io: &Io, aux_mutex: &Mutex,
let reply = drtio::aux_transact(io, aux_mutex, ddma_mutex, linkno, &drtioaux::Packet::I2cStartRequest { linkno: u8, destination: u8, busno: u8
destination: destination, ) -> Result<(), &'static str> {
busno: busno let reply = drtio::aux_transact(io, aux_mutex, linkno,
}); &drtioaux::Packet::I2cStartRequest {
destination: destination,
busno: busno
});
match reply { match reply {
Ok(drtioaux::Packet::I2cBasicReply { succeeded }) => { Ok(drtioaux::Packet::I2cBasicReply { succeeded }) => {
if succeeded { Ok(()) } else { Err("i2c basic reply error") } if succeeded { Ok(()) } else { Err("i2c basic reply error") }
@ -34,11 +37,14 @@ mod remote_i2c {
} }
} }
pub fn restart(io: &Io, aux_mutex: &Mutex, ddma_mutex: &Mutex, linkno: u8, destination: u8, busno: u8) -> Result<(), &'static str> { pub fn restart(io: &Io, aux_mutex: &Mutex,
let reply = drtio::aux_transact(io, aux_mutex, ddma_mutex, linkno, &drtioaux::Packet::I2cRestartRequest { linkno: u8, destination: u8, busno: u8
destination: destination, ) -> Result<(), &'static str> {
busno: busno let reply = drtio::aux_transact(io, aux_mutex, linkno,
}); &drtioaux::Packet::I2cRestartRequest {
destination: destination,
busno: busno
});
match reply { match reply {
Ok(drtioaux::Packet::I2cBasicReply { succeeded }) => { Ok(drtioaux::Packet::I2cBasicReply { succeeded }) => {
if succeeded { Ok(()) } else { Err("i2c basic reply error") } if succeeded { Ok(()) } else { Err("i2c basic reply error") }
@ -54,11 +60,14 @@ mod remote_i2c {
} }
} }
pub fn stop(io: &Io, aux_mutex: &Mutex, ddma_mutex: &Mutex, linkno: u8, destination: u8, busno: u8) -> Result<(), &'static str> { pub fn stop(io: &Io, aux_mutex: &Mutex,
let reply = drtio::aux_transact(io, aux_mutex, ddma_mutex, linkno, &drtioaux::Packet::I2cStopRequest { linkno: u8, destination: u8, busno: u8
destination: destination, ) -> Result<(), &'static str> {
busno: busno let reply = drtio::aux_transact(io, aux_mutex, linkno,
}); &drtioaux::Packet::I2cStopRequest {
destination: destination,
busno: busno
});
match reply { match reply {
Ok(drtioaux::Packet::I2cBasicReply { succeeded }) => { Ok(drtioaux::Packet::I2cBasicReply { succeeded }) => {
if succeeded { Ok(()) } else { Err("i2c basic reply error") } if succeeded { Ok(()) } else { Err("i2c basic reply error") }
@ -74,12 +83,15 @@ mod remote_i2c {
} }
} }
pub fn write(io: &Io, aux_mutex: &Mutex, ddma_mutex: &Mutex, linkno: u8, destination: u8, busno: u8, data: u8) -> Result<bool, &'static str> { pub fn write(io: &Io, aux_mutex: &Mutex,
let reply = drtio::aux_transact(io, aux_mutex, ddma_mutex, linkno, &drtioaux::Packet::I2cWriteRequest { linkno: u8, destination: u8, busno: u8, data: u8
destination: destination, ) -> Result<bool, &'static str> {
busno: busno, let reply = drtio::aux_transact(io, aux_mutex, linkno,
data: data &drtioaux::Packet::I2cWriteRequest {
}); destination: destination,
busno: busno,
data: data
});
match reply { match reply {
Ok(drtioaux::Packet::I2cWriteReply { succeeded, ack }) => { Ok(drtioaux::Packet::I2cWriteReply { succeeded, ack }) => {
if succeeded { Ok(ack) } else { Err("i2c write reply error") } if succeeded { Ok(ack) } else { Err("i2c write reply error") }
@ -95,12 +107,15 @@ mod remote_i2c {
} }
} }
pub fn read(io: &Io, aux_mutex: &Mutex, ddma_mutex: &Mutex, linkno: u8, destination: u8, busno: u8, ack: bool) -> Result<u8, &'static str> { pub fn read(io: &Io, aux_mutex: &Mutex,
let reply = drtio::aux_transact(io, aux_mutex, ddma_mutex, linkno, &drtioaux::Packet::I2cReadRequest { linkno: u8, destination: u8, busno: u8, ack: bool
destination: destination, ) -> Result<u8, &'static str> {
busno: busno, let reply = drtio::aux_transact(io, aux_mutex, linkno,
ack: ack &drtioaux::Packet::I2cReadRequest {
}); destination: destination,
busno: busno,
ack: ack
});
match reply { match reply {
Ok(drtioaux::Packet::I2cReadReply { succeeded, data }) => { Ok(drtioaux::Packet::I2cReadReply { succeeded, data }) => {
if succeeded { Ok(data) } else { Err("i2c read reply error") } if succeeded { Ok(data) } else { Err("i2c read reply error") }
@ -116,13 +131,16 @@ mod remote_i2c {
} }
} }
pub fn switch_select(io: &Io, aux_mutex: &Mutex, ddma_mutex: &Mutex, linkno: u8, destination: u8, busno: u8, address: u8, mask: u8) -> Result<(), &'static str> { pub fn switch_select(io: &Io, aux_mutex: &Mutex,
let reply = drtio::aux_transact(io, aux_mutex, ddma_mutex, linkno, &drtioaux::Packet::I2cSwitchSelectRequest { linkno: u8, destination: u8, busno: u8, address: u8, mask: u8
destination: destination, ) -> Result<(), &'static str> {
busno: busno, let reply = drtio::aux_transact(io, aux_mutex, linkno,
address: address, &drtioaux::Packet::I2cSwitchSelectRequest {
mask: mask, destination: destination,
}); busno: busno,
address: address,
mask: mask,
});
match reply { match reply {
Ok(drtioaux::Packet::I2cBasicReply { succeeded }) => { Ok(drtioaux::Packet::I2cBasicReply { succeeded }) => {
if succeeded { Ok(()) } else { Err("i2c basic reply error") } if succeeded { Ok(()) } else { Err("i2c basic reply error") }
@ -145,8 +163,10 @@ mod remote_spi {
use rtio_mgt::drtio; use rtio_mgt::drtio;
use sched::{Io, Mutex}; use sched::{Io, Mutex};
pub fn set_config(io: &Io, aux_mutex: &Mutex, ddma_mutex: &Mutex, linkno: u8, destination: u8, busno: u8, flags: u8, length: u8, div: u8, cs: u8) -> Result<(), ()> { pub fn set_config(io: &Io, aux_mutex: &Mutex,
let reply = drtio::aux_transact(io, aux_mutex, ddma_mutex, linkno, &drtioaux::Packet::SpiSetConfigRequest { linkno: u8, destination: u8, busno: u8, flags: u8, length: u8, div: u8, cs: u8
) -> Result<(), ()> {
let reply = drtio::aux_transact(io, aux_mutex, linkno, &drtioaux::Packet::SpiSetConfigRequest {
destination: destination, destination: destination,
busno: busno, busno: busno,
flags: flags, flags: flags,
@ -169,8 +189,10 @@ mod remote_spi {
} }
} }
pub fn write(io: &Io, aux_mutex: &Mutex, ddma_mutex: &Mutex, linkno: u8, destination: u8, busno: u8, data: u32) -> Result<(), ()> { pub fn write(io: &Io, aux_mutex: &Mutex,
let reply = drtio::aux_transact(io, aux_mutex, ddma_mutex, linkno, &drtioaux::Packet::SpiWriteRequest { linkno: u8, destination: u8, busno: u8, data: u32
) -> Result<(), ()> {
let reply = drtio::aux_transact(io, aux_mutex, linkno, &drtioaux::Packet::SpiWriteRequest {
destination: destination, destination: destination,
busno: busno, busno: busno,
data: data data: data
@ -190,11 +212,13 @@ mod remote_spi {
} }
} }
pub fn read(io: &Io, aux_mutex: &Mutex, ddma_mutex: &Mutex, linkno: u8, destination: u8, busno: u8) -> Result<u32, ()> { pub fn read(io: &Io, aux_mutex: &Mutex, linkno: u8, destination: u8, busno: u8
let reply = drtio::aux_transact(io, aux_mutex, ddma_mutex, linkno, &drtioaux::Packet::SpiReadRequest { ) -> Result<u32, ()> {
destination: destination, let reply = drtio::aux_transact(io, aux_mutex, linkno,
busno: busno &drtioaux::Packet::SpiReadRequest {
}); destination: destination,
busno: busno
});
match reply { match reply {
Ok(drtioaux::Packet::SpiReadReply { succeeded, data }) => { Ok(drtioaux::Packet::SpiReadReply { succeeded, data }) => {
if succeeded { Ok(data) } else { Err(()) } if succeeded { Ok(data) } else { Err(()) }
@ -214,7 +238,7 @@ mod remote_spi {
#[cfg(has_drtio)] #[cfg(has_drtio)]
macro_rules! dispatch { macro_rules! dispatch {
($io:ident, $aux_mutex:ident, $ddma_mutex:ident, $mod_local:ident, $mod_remote:ident, $routing_table:ident, $busno:expr, $func:ident $(, $param:expr)*) => {{ ($io:ident, $aux_mutex:ident, $mod_local:ident, $mod_remote:ident, $routing_table:ident, $busno:expr, $func:ident $(, $param:expr)*) => {{
let destination = ($busno >> 16) as u8; let destination = ($busno >> 16) as u8;
let busno = $busno as u8; let busno = $busno as u8;
let hop = $routing_table.0[destination as usize][0]; let hop = $routing_table.0[destination as usize][0];
@ -222,28 +246,27 @@ macro_rules! dispatch {
$mod_local::$func(busno, $($param, )*) $mod_local::$func(busno, $($param, )*)
} else { } else {
let linkno = hop - 1; let linkno = hop - 1;
$mod_remote::$func($io, $aux_mutex, $ddma_mutex, linkno, destination, busno, $($param, )*) $mod_remote::$func($io, $aux_mutex, linkno, destination, busno, $($param, )*)
} }
}} }}
} }
#[cfg(not(has_drtio))] #[cfg(not(has_drtio))]
macro_rules! dispatch { macro_rules! dispatch {
($io:ident, $aux_mutex:ident, $ddma_mutex:ident, $mod_local:ident, $mod_remote:ident, $routing_table:ident, $busno:expr, $func:ident $(, $param:expr)*) => {{ ($io:ident, $aux_mutex:ident, $mod_local:ident, $mod_remote:ident, $routing_table:ident, $busno:expr, $func:ident $(, $param:expr)*) => {{
let busno = $busno as u8; let busno = $busno as u8;
$mod_local::$func(busno, $($param, )*) $mod_local::$func(busno, $($param, )*)
}} }}
} }
pub fn process_kern_hwreq(io: &Io, aux_mutex: &Mutex, pub fn process_kern_hwreq(io: &Io, aux_mutex: &Mutex,
ddma_mutex: &Mutex,
_routing_table: &drtio_routing::RoutingTable, _routing_table: &drtio_routing::RoutingTable,
_up_destinations: &Urc<RefCell<[bool; drtio_routing::DEST_COUNT]>>, _up_destinations: &Urc<RefCell<[bool; drtio_routing::DEST_COUNT]>>,
request: &kern::Message) -> Result<bool, Error<SchedError>> { request: &kern::Message) -> Result<bool, Error<SchedError>> {
match request { match request {
&kern::RtioInitRequest => { &kern::RtioInitRequest => {
info!("resetting RTIO"); info!("resetting RTIO");
rtio_mgt::reset(io, aux_mutex, ddma_mutex); rtio_mgt::reset(io, aux_mutex);
kern_acknowledge() kern_acknowledge()
} }
@ -259,47 +282,47 @@ pub fn process_kern_hwreq(io: &Io, aux_mutex: &Mutex,
} }
&kern::I2cStartRequest { busno } => { &kern::I2cStartRequest { busno } => {
let succeeded = dispatch!(io, aux_mutex, ddma_mutex, local_i2c, remote_i2c, _routing_table, busno, start).is_ok(); let succeeded = dispatch!(io, aux_mutex, local_i2c, remote_i2c, _routing_table, busno, start).is_ok();
kern_send(io, &kern::I2cBasicReply { succeeded: succeeded }) kern_send(io, &kern::I2cBasicReply { succeeded: succeeded })
} }
&kern::I2cRestartRequest { busno } => { &kern::I2cRestartRequest { busno } => {
let succeeded = dispatch!(io, aux_mutex, ddma_mutex, local_i2c, remote_i2c, _routing_table, busno, restart).is_ok(); let succeeded = dispatch!(io, aux_mutex, local_i2c, remote_i2c, _routing_table, busno, restart).is_ok();
kern_send(io, &kern::I2cBasicReply { succeeded: succeeded }) kern_send(io, &kern::I2cBasicReply { succeeded: succeeded })
} }
&kern::I2cStopRequest { busno } => { &kern::I2cStopRequest { busno } => {
let succeeded = dispatch!(io, aux_mutex, ddma_mutex, local_i2c, remote_i2c, _routing_table, busno, stop).is_ok(); let succeeded = dispatch!(io, aux_mutex, local_i2c, remote_i2c, _routing_table, busno, stop).is_ok();
kern_send(io, &kern::I2cBasicReply { succeeded: succeeded }) kern_send(io, &kern::I2cBasicReply { succeeded: succeeded })
} }
&kern::I2cWriteRequest { busno, data } => { &kern::I2cWriteRequest { busno, data } => {
match dispatch!(io, aux_mutex, ddma_mutex, local_i2c, remote_i2c, _routing_table, busno, write, data) { match dispatch!(io, aux_mutex, local_i2c, remote_i2c, _routing_table, busno, write, data) {
Ok(ack) => kern_send(io, &kern::I2cWriteReply { succeeded: true, ack: ack }), Ok(ack) => kern_send(io, &kern::I2cWriteReply { succeeded: true, ack: ack }),
Err(_) => kern_send(io, &kern::I2cWriteReply { succeeded: false, ack: false }) Err(_) => kern_send(io, &kern::I2cWriteReply { succeeded: false, ack: false })
} }
} }
&kern::I2cReadRequest { busno, ack } => { &kern::I2cReadRequest { busno, ack } => {
match dispatch!(io, aux_mutex, ddma_mutex, local_i2c, remote_i2c, _routing_table, busno, read, ack) { match dispatch!(io, aux_mutex, local_i2c, remote_i2c, _routing_table, busno, read, ack) {
Ok(data) => kern_send(io, &kern::I2cReadReply { succeeded: true, data: data }), Ok(data) => kern_send(io, &kern::I2cReadReply { succeeded: true, data: data }),
Err(_) => kern_send(io, &kern::I2cReadReply { succeeded: false, data: 0xff }) Err(_) => kern_send(io, &kern::I2cReadReply { succeeded: false, data: 0xff })
} }
} }
&kern::I2cSwitchSelectRequest { busno, address, mask } => { &kern::I2cSwitchSelectRequest { busno, address, mask } => {
let succeeded = dispatch!(io, aux_mutex, ddma_mutex, local_i2c, remote_i2c, _routing_table, busno, let succeeded = dispatch!(io, aux_mutex, local_i2c, remote_i2c, _routing_table, busno,
switch_select, address, mask).is_ok(); switch_select, address, mask).is_ok();
kern_send(io, &kern::I2cBasicReply { succeeded: succeeded }) kern_send(io, &kern::I2cBasicReply { succeeded: succeeded })
} }
&kern::SpiSetConfigRequest { busno, flags, length, div, cs } => { &kern::SpiSetConfigRequest { busno, flags, length, div, cs } => {
let succeeded = dispatch!(io, aux_mutex, ddma_mutex, local_spi, remote_spi, _routing_table, busno, let succeeded = dispatch!(io, aux_mutex, local_spi, remote_spi, _routing_table, busno,
set_config, flags, length, div, cs).is_ok(); set_config, flags, length, div, cs).is_ok();
kern_send(io, &kern::SpiBasicReply { succeeded: succeeded }) kern_send(io, &kern::SpiBasicReply { succeeded: succeeded })
}, },
&kern::SpiWriteRequest { busno, data } => { &kern::SpiWriteRequest { busno, data } => {
let succeeded = dispatch!(io, aux_mutex, ddma_mutex, local_spi, remote_spi, _routing_table, busno, let succeeded = dispatch!(io, aux_mutex, local_spi, remote_spi, _routing_table, busno,
write, data).is_ok(); write, data).is_ok();
kern_send(io, &kern::SpiBasicReply { succeeded: succeeded }) kern_send(io, &kern::SpiBasicReply { succeeded: succeeded })
} }
&kern::SpiReadRequest { busno } => { &kern::SpiReadRequest { busno } => {
match dispatch!(io, aux_mutex, ddma_mutex, local_spi, remote_spi, _routing_table, busno, read) { match dispatch!(io, aux_mutex, local_spi, remote_spi, _routing_table, busno, read) {
Ok(data) => kern_send(io, &kern::SpiReadReply { succeeded: true, data: data }), Ok(data) => kern_send(io, &kern::SpiReadReply { succeeded: true, data: data }),
Err(_) => kern_send(io, &kern::SpiReadReply { succeeded: false, data: 0 }) Err(_) => kern_send(io, &kern::SpiReadReply { succeeded: false, data: 0 })
} }

View File

@ -210,17 +210,15 @@ fn startup() {
#[cfg(any(has_rtio_moninj, has_drtio))] #[cfg(any(has_rtio_moninj, has_drtio))]
{ {
let aux_mutex = aux_mutex.clone(); let aux_mutex = aux_mutex.clone();
let ddma_mutex = ddma_mutex.clone();
let drtio_routing_table = drtio_routing_table.clone(); let drtio_routing_table = drtio_routing_table.clone();
io.spawn(4096, move |io| { moninj::thread(io, &aux_mutex, &ddma_mutex, &drtio_routing_table) }); io.spawn(4096, move |io| { moninj::thread(io, &aux_mutex, &drtio_routing_table) });
} }
#[cfg(has_rtio_analyzer)] #[cfg(has_rtio_analyzer)]
{ {
let aux_mutex = aux_mutex.clone(); let aux_mutex = aux_mutex.clone();
let drtio_routing_table = drtio_routing_table.clone(); let drtio_routing_table = drtio_routing_table.clone();
let up_destinations = up_destinations.clone(); let up_destinations = up_destinations.clone();
let ddma_mutex = ddma_mutex.clone(); io.spawn(8192, move |io| { analyzer::thread(io, &aux_mutex, &drtio_routing_table, &up_destinations) });
io.spawn(8192, move |io| { analyzer::thread(io, &aux_mutex, &ddma_mutex, &drtio_routing_table, &up_destinations) });
} }
#[cfg(has_grabber)] #[cfg(has_grabber)]

View File

@ -53,12 +53,14 @@ mod remote_moninj {
use rtio_mgt::drtio; use rtio_mgt::drtio;
use sched::{Io, Mutex}; use sched::{Io, Mutex};
pub fn read_probe(io: &Io, aux_mutex: &Mutex, ddma_mutex: &Mutex, linkno: u8, destination: u8, channel: u16, probe: u8) -> u64 { pub fn read_probe(io: &Io, aux_mutex: &Mutex, linkno: u8,
let reply = drtio::aux_transact(io, aux_mutex, ddma_mutex, linkno, &drtioaux::Packet::MonitorRequest { destination: u8, channel: u16, probe: u8) -> u64 {
destination: destination, let reply = drtio::aux_transact(io, aux_mutex, linkno,
channel: channel, &drtioaux::Packet::MonitorRequest {
probe: probe destination: destination,
}); channel: channel,
probe: probe
});
match reply { match reply {
Ok(drtioaux::Packet::MonitorReply { value }) => return value, Ok(drtioaux::Packet::MonitorReply { value }) => return value,
Ok(packet) => error!("received unexpected aux packet: {:?}", packet), Ok(packet) => error!("received unexpected aux packet: {:?}", packet),
@ -67,7 +69,8 @@ mod remote_moninj {
0 0
} }
pub fn inject(io: &Io, aux_mutex: &Mutex, _ddma_mutex: &Mutex, linkno: u8, destination: u8, channel: u16, overrd: u8, value: u8) { pub fn inject(io: &Io, aux_mutex: &Mutex, linkno: u8,
destination: u8, channel: u16, overrd: u8, value: u8) {
let _lock = aux_mutex.lock(io).unwrap(); let _lock = aux_mutex.lock(io).unwrap();
drtioaux::send(linkno, &drtioaux::Packet::InjectionRequest { drtioaux::send(linkno, &drtioaux::Packet::InjectionRequest {
destination: destination, destination: destination,
@ -77,12 +80,14 @@ mod remote_moninj {
}).unwrap(); }).unwrap();
} }
pub fn read_injection_status(io: &Io, aux_mutex: &Mutex, ddma_mutex: &Mutex, linkno: u8, destination: u8, channel: u16, overrd: u8) -> u8 { pub fn read_injection_status(io: &Io, aux_mutex: &Mutex, linkno: u8,
let reply = drtio::aux_transact(io, aux_mutex, ddma_mutex, linkno, &drtioaux::Packet::InjectionStatusRequest { destination: u8, channel: u16, overrd: u8) -> u8 {
destination: destination, let reply = drtio::aux_transact(io, aux_mutex, linkno,
channel: channel, &drtioaux::Packet::InjectionStatusRequest {
overrd: overrd destination: destination,
}); channel: channel,
overrd: overrd
});
match reply { match reply {
Ok(drtioaux::Packet::InjectionStatusReply { value }) => return value, Ok(drtioaux::Packet::InjectionStatusReply { value }) => return value,
Ok(packet) => error!("received unexpected aux packet: {:?}", packet), Ok(packet) => error!("received unexpected aux packet: {:?}", packet),
@ -94,7 +99,7 @@ mod remote_moninj {
#[cfg(has_drtio)] #[cfg(has_drtio)]
macro_rules! dispatch { macro_rules! dispatch {
($io:ident, $aux_mutex:ident, $ddma_mutex:ident, $routing_table:ident, $channel:expr, $func:ident $(, $param:expr)*) => {{ ($io:ident, $aux_mutex:ident, $routing_table:ident, $channel:expr, $func:ident $(, $param:expr)*) => {{
let destination = ($channel >> 16) as u8; let destination = ($channel >> 16) as u8;
let channel = $channel as u16; let channel = $channel as u16;
let hop = $routing_table.0[destination as usize][0]; let hop = $routing_table.0[destination as usize][0];
@ -102,21 +107,21 @@ macro_rules! dispatch {
local_moninj::$func(channel, $($param, )*) local_moninj::$func(channel, $($param, )*)
} else { } else {
let linkno = hop - 1; let linkno = hop - 1;
remote_moninj::$func($io, $aux_mutex, $ddma_mutex, linkno, destination, channel, $($param, )*) remote_moninj::$func($io, $aux_mutex, linkno, destination, channel, $($param, )*)
} }
}} }}
} }
#[cfg(not(has_drtio))] #[cfg(not(has_drtio))]
macro_rules! dispatch { macro_rules! dispatch {
($io:ident, $aux_mutex:ident, $ddma_mutex:ident, $routing_table:ident, $channel:expr, $func:ident $(, $param:expr)*) => {{ ($io:ident, $aux_mutex:ident, $routing_table:ident, $channel:expr, $func:ident $(, $param:expr)*) => {{
let channel = $channel as u16; let channel = $channel as u16;
local_moninj::$func(channel, $($param, )*) local_moninj::$func(channel, $($param, )*)
}} }}
} }
fn connection_worker(io: &Io, _aux_mutex: &Mutex, _ddma_mutex: &Mutex, _routing_table: &drtio_routing::RoutingTable, fn connection_worker(io: &Io, _aux_mutex: &Mutex, _routing_table: &drtio_routing::RoutingTable,
mut stream: &mut TcpStream) -> Result<(), Error<SchedError>> { mut stream: &mut TcpStream) -> Result<(), Error<SchedError>> {
let mut probe_watch_list = BTreeMap::new(); let mut probe_watch_list = BTreeMap::new();
let mut inject_watch_list = BTreeMap::new(); let mut inject_watch_list = BTreeMap::new();
let mut next_check = 0; let mut next_check = 0;
@ -144,9 +149,10 @@ fn connection_worker(io: &Io, _aux_mutex: &Mutex, _ddma_mutex: &Mutex, _routing_
let _ = inject_watch_list.remove(&(channel, overrd)); let _ = inject_watch_list.remove(&(channel, overrd));
} }
}, },
HostMessage::Inject { channel, overrd, value } => dispatch!(io, _aux_mutex, _ddma_mutex, _routing_table, channel, inject, overrd, value), HostMessage::Inject { channel, overrd, value } => dispatch!(
io, _aux_mutex, _routing_table, channel, inject, overrd, value),
HostMessage::GetInjectionStatus { channel, overrd } => { HostMessage::GetInjectionStatus { channel, overrd } => {
let value = dispatch!(io, _aux_mutex, _ddma_mutex, _routing_table, channel, read_injection_status, overrd); let value = dispatch!(io, _aux_mutex, _routing_table, channel, read_injection_status, overrd);
let reply = DeviceMessage::InjectionStatus { let reply = DeviceMessage::InjectionStatus {
channel: channel, channel: channel,
overrd: overrd, overrd: overrd,
@ -163,7 +169,7 @@ fn connection_worker(io: &Io, _aux_mutex: &Mutex, _ddma_mutex: &Mutex, _routing_
if clock::get_ms() > next_check { if clock::get_ms() > next_check {
for (&(channel, probe), previous) in probe_watch_list.iter_mut() { for (&(channel, probe), previous) in probe_watch_list.iter_mut() {
let current = dispatch!(io, _aux_mutex, _ddma_mutex, _routing_table, channel, read_probe, probe); let current = dispatch!(io, _aux_mutex, _routing_table, channel, read_probe, probe);
if previous.is_none() || previous.unwrap() != current { if previous.is_none() || previous.unwrap() != current {
let message = DeviceMessage::MonitorStatus { let message = DeviceMessage::MonitorStatus {
channel: channel, channel: channel,
@ -178,7 +184,7 @@ fn connection_worker(io: &Io, _aux_mutex: &Mutex, _ddma_mutex: &Mutex, _routing_
} }
} }
for (&(channel, overrd), previous) in inject_watch_list.iter_mut() { for (&(channel, overrd), previous) in inject_watch_list.iter_mut() {
let current = dispatch!(io, _aux_mutex, _ddma_mutex, _routing_table, channel, read_injection_status, overrd); let current = dispatch!(io, _aux_mutex, _routing_table, channel, read_injection_status, overrd);
if previous.is_none() || previous.unwrap() != current { if previous.is_none() || previous.unwrap() != current {
let message = DeviceMessage::InjectionStatus { let message = DeviceMessage::InjectionStatus {
channel: channel, channel: channel,
@ -199,19 +205,18 @@ fn connection_worker(io: &Io, _aux_mutex: &Mutex, _ddma_mutex: &Mutex, _routing_
} }
} }
pub fn thread(io: Io, aux_mutex: &Mutex, ddma_mutex: &Mutex, routing_table: &Urc<RefCell<drtio_routing::RoutingTable>>) { pub fn thread(io: Io, aux_mutex: &Mutex, routing_table: &Urc<RefCell<drtio_routing::RoutingTable>>) {
let listener = TcpListener::new(&io, 2047); let listener = TcpListener::new(&io, 2047);
listener.listen(1383).expect("moninj: cannot listen"); listener.listen(1383).expect("moninj: cannot listen");
loop { loop {
let aux_mutex = aux_mutex.clone(); let aux_mutex = aux_mutex.clone();
let ddma_mutex = ddma_mutex.clone();
let routing_table = routing_table.clone(); let routing_table = routing_table.clone();
let stream = listener.accept().expect("moninj: cannot accept").into_handle(); let stream = listener.accept().expect("moninj: cannot accept").into_handle();
io.spawn(16384, move |io| { io.spawn(16384, move |io| {
let routing_table = routing_table.borrow(); let routing_table = routing_table.borrow();
let mut stream = TcpStream::from_handle(&io, stream); let mut stream = TcpStream::from_handle(&io, stream);
match connection_worker(&io, &aux_mutex, &ddma_mutex, &routing_table, &mut stream) { match connection_worker(&io, &aux_mutex, &routing_table, &mut stream) {
Ok(()) => {}, Ok(()) => {},
Err(err) => error!("moninj aborted: {}", err) Err(err) => error!("moninj aborted: {}", err)
} }

View File

@ -91,12 +91,12 @@ pub mod remote_dma {
Ok(playback_state) Ok(playback_state)
} }
pub fn erase(io: &Io, aux_mutex: &Mutex, routing_table: &RoutingTable, pub fn erase(io: &Io, aux_mutex: &Mutex, ddma_mutex: &Mutex,
ddma_mutex: &Mutex, id: u32) { routing_table: &RoutingTable, id: u32) {
let _lock = ddma_mutex.lock(io).unwrap(); let _lock = ddma_mutex.lock(io).unwrap();
let destinations = unsafe { TRACES.get(&id).unwrap() }; let destinations = unsafe { TRACES.get(&id).unwrap() };
for destination in destinations.keys() { for destination in destinations.keys() {
match drtio::ddma_send_erase(io, aux_mutex, ddma_mutex, routing_table, id, *destination) { match drtio::ddma_send_erase(io, aux_mutex, routing_table, id, *destination) {
Ok(_) => (), Ok(_) => (),
Err(e) => error!("Error erasing trace on DMA: {}", e) Err(e) => error!("Error erasing trace on DMA: {}", e)
} }
@ -104,12 +104,12 @@ pub mod remote_dma {
unsafe { TRACES.remove(&id); } unsafe { TRACES.remove(&id); }
} }
pub fn upload_traces(io: &Io, aux_mutex: &Mutex, routing_table: &RoutingTable, pub fn upload_traces(io: &Io, aux_mutex: &Mutex, ddma_mutex: &Mutex,
ddma_mutex: &Mutex, id: u32) { routing_table: &RoutingTable, id: u32) {
let _lock = ddma_mutex.lock(io); let _lock = ddma_mutex.lock(io);
let traces = unsafe { TRACES.get_mut(&id).unwrap() }; let traces = unsafe { TRACES.get_mut(&id).unwrap() };
for (destination, mut trace) in traces { for (destination, mut trace) in traces {
match drtio::ddma_upload_trace(io, aux_mutex, ddma_mutex, routing_table, id, *destination, trace.get_trace()) match drtio::ddma_upload_trace(io, aux_mutex, routing_table, id, *destination, trace.get_trace())
{ {
Ok(_) => trace.state = RemoteState::Loaded, Ok(_) => trace.state = RemoteState::Loaded,
Err(e) => error!("Error adding DMA trace on destination {}: {}", destination, e) Err(e) => error!("Error adding DMA trace on destination {}: {}", destination, e)
@ -117,8 +117,8 @@ pub mod remote_dma {
} }
} }
pub fn playback(io: &Io, aux_mutex: &Mutex, routing_table: &RoutingTable, pub fn playback(io: &Io, aux_mutex: &Mutex, ddma_mutex: &Mutex,
ddma_mutex: &Mutex, id: u32, timestamp: u64) { routing_table: &RoutingTable, id: u32, timestamp: u64) {
// triggers playback on satellites // triggers playback on satellites
let destinations = unsafe { let destinations = unsafe {
let _lock = ddma_mutex.lock(io).unwrap(); let _lock = ddma_mutex.lock(io).unwrap();
@ -133,7 +133,7 @@ pub mod remote_dma {
continue; continue;
} }
} }
match drtio::ddma_send_playback(io, aux_mutex, ddma_mutex, routing_table, id, *destination, timestamp) { match drtio::ddma_send_playback(io, aux_mutex, routing_table, id, *destination, timestamp) {
Ok(_) => (), Ok(_) => (),
Err(e) => error!("Error during remote DMA playback: {}", e) Err(e) => error!("Error during remote DMA playback: {}", e)
} }
@ -152,15 +152,15 @@ pub mod remote_dma {
}; };
} }
pub fn destination_changed(io: &Io, aux_mutex: &Mutex, routing_table: &RoutingTable, pub fn destination_changed(io: &Io, aux_mutex: &Mutex, ddma_mutex: &Mutex,
ddma_mutex: &Mutex, destination: u8, up: bool) { routing_table: &RoutingTable, destination: u8, up: bool) {
// update state of the destination, resend traces if it's up // update state of the destination, resend traces if it's up
let _lock = ddma_mutex.lock(io).unwrap(); let _lock = ddma_mutex.lock(io).unwrap();
let traces_iter = unsafe { TRACES.iter_mut() }; let traces_iter = unsafe { TRACES.iter_mut() };
for (id, dest_traces) in traces_iter { for (id, dest_traces) in traces_iter {
if let Some(trace) = dest_traces.get_mut(&destination) { if let Some(trace) = dest_traces.get_mut(&destination) {
if up { if up {
match drtio::ddma_upload_trace(io, aux_mutex, ddma_mutex, routing_table, *id, destination, trace.get_trace()) match drtio::ddma_upload_trace(io, aux_mutex, routing_table, *id, destination, trace.get_trace())
{ {
Ok(_) => trace.state = RemoteState::Loaded, Ok(_) => trace.state = RemoteState::Loaded,
Err(e) => error!("Error adding DMA trace on destination {}: {}", destination, e) Err(e) => error!("Error adding DMA trace on destination {}: {}", destination, e)

View File

@ -61,23 +61,27 @@ pub mod drtio {
} }
} }
pub fn aux_transact(io: &Io, aux_mutex: &Mutex, ddma_mutex: &Mutex, fn process_async_packets(io: &Io, ddma_mutex: &Mutex, packet: drtioaux::Packet
linkno: u8, request: &drtioaux::Packet ) -> Result<drtioaux::Packet, &'static str> { ) -> Option<drtioaux::Packet> {
let _lock = aux_mutex.lock(io).unwrap(); // returns None if an async packet has been consumed
drtioaux::send(linkno, request).unwrap(); match packet {
loop { drtioaux::Packet::DmaPlaybackStatus { id, destination, error, channel, timestamp } => {
let reply = recv_aux_timeout(io, linkno, 200); remote_dma::playback_done(io, ddma_mutex, id, destination, error, channel, timestamp);
match reply { None
Ok(drtioaux::Packet::DmaPlaybackStatus { id, destination, error, channel, timestamp }) => { },
remote_dma::playback_done(io, ddma_mutex, id, destination, error, channel, timestamp); other => Some(other)
},
Ok(packet) => return Ok(packet),
Err(e) => return Err(e)
}
} }
} }
fn ping_remote(io: &Io, aux_mutex: &Mutex, ddma_mutex: &Mutex, linkno: u8) -> u32 { pub fn aux_transact(io: &Io, aux_mutex: &Mutex, linkno: u8, request: &drtioaux::Packet
) -> Result<drtioaux::Packet, &'static str> {
let _lock = aux_mutex.lock(io).unwrap();
drtioaux::send(linkno, request).unwrap();
let reply = recv_aux_timeout(io, linkno, 200)?;
Ok(reply)
}
fn ping_remote(io: &Io, aux_mutex: &Mutex, linkno: u8) -> u32 {
let mut count = 0; let mut count = 0;
loop { loop {
if !link_rx_up(linkno) { if !link_rx_up(linkno) {
@ -87,7 +91,7 @@ pub mod drtio {
if count > 100 { if count > 100 {
return 0; return 0;
} }
let reply = aux_transact(io, aux_mutex, ddma_mutex, linkno, &drtioaux::Packet::EchoRequest); let reply = aux_transact(io, aux_mutex, linkno, &drtioaux::Packet::EchoRequest);
match reply { match reply {
Ok(drtioaux::Packet::EchoReply) => { Ok(drtioaux::Packet::EchoReply) => {
// make sure receive buffer is drained // make sure receive buffer is drained
@ -123,10 +127,10 @@ pub mod drtio {
} }
} }
fn load_routing_table(io: &Io, aux_mutex: &Mutex, ddma_mutex: &Mutex, fn load_routing_table(io: &Io, aux_mutex: &Mutex,
linkno: u8, routing_table: &drtio_routing::RoutingTable) -> Result<(), &'static str> { linkno: u8, routing_table: &drtio_routing::RoutingTable) -> Result<(), &'static str> {
for i in 0..drtio_routing::DEST_COUNT { for i in 0..drtio_routing::DEST_COUNT {
let reply = aux_transact(io, aux_mutex, ddma_mutex, linkno, &drtioaux::Packet::RoutingSetPath { let reply = aux_transact(io, aux_mutex, linkno, &drtioaux::Packet::RoutingSetPath {
destination: i as u8, destination: i as u8,
hops: routing_table.0[i] hops: routing_table.0[i]
})?; })?;
@ -137,10 +141,12 @@ pub mod drtio {
Ok(()) Ok(())
} }
fn set_rank(io: &Io, aux_mutex: &Mutex, ddma_mutex: &Mutex, linkno: u8, rank: u8) -> Result<(), &'static str> { fn set_rank(io: &Io, aux_mutex: &Mutex,
let reply = aux_transact(io, aux_mutex, ddma_mutex, linkno, &drtioaux::Packet::RoutingSetRank { linkno: u8, rank: u8) -> Result<(), &'static str> {
rank: rank let reply = aux_transact(io, aux_mutex, linkno,
})?; &drtioaux::Packet::RoutingSetRank {
rank: rank
})?;
if reply != drtioaux::Packet::RoutingAck { if reply != drtioaux::Packet::RoutingAck {
return Err("unexpected reply"); return Err("unexpected reply");
} }
@ -229,45 +235,60 @@ pub mod drtio {
let linkno = hop - 1; let linkno = hop - 1;
if destination_up(up_destinations, destination) { if destination_up(up_destinations, destination) {
if up_links[linkno as usize] { if up_links[linkno as usize] {
let reply = aux_transact(io, aux_mutex, ddma_mutex, linkno, &drtioaux::Packet::DestinationStatusRequest { loop {
destination: destination let reply = aux_transact(io, aux_mutex, linkno,
}); &drtioaux::Packet::DestinationStatusRequest {
match reply { destination: destination
Ok(drtioaux::Packet::DestinationDownReply) => { });
destination_set_up(routing_table, up_destinations, destination, false); if let Ok(reply) = reply {
remote_dma::destination_changed(io, aux_mutex, routing_table, ddma_mutex, destination, false); let reply = process_async_packets(io, ddma_mutex, reply);
match reply {
Some(drtioaux::Packet::DestinationDownReply) => {
destination_set_up(routing_table, up_destinations, destination, false);
remote_dma::destination_changed(io, aux_mutex, ddma_mutex, routing_table, destination, false);
}
Some(drtioaux::Packet::DestinationOkReply) => (),
Some(drtioaux::Packet::DestinationSequenceErrorReply { channel }) => {
error!("[DEST#{}] RTIO sequence error involving channel 0x{:04x}:{}", destination, channel, resolve_channel_name(channel as u32));
unsafe { SEEN_ASYNC_ERRORS |= ASYNC_ERROR_SEQUENCE_ERROR };
}
Some(drtioaux::Packet::DestinationCollisionReply { channel }) => {
error!("[DEST#{}] RTIO collision involving channel 0x{:04x}:{}", destination, channel, resolve_channel_name(channel as u32));
unsafe { SEEN_ASYNC_ERRORS |= ASYNC_ERROR_COLLISION };
}
Some(drtioaux::Packet::DestinationBusyReply { channel }) => {
error!("[DEST#{}] RTIO busy error involving channel 0x{:04x}:{}", destination, channel, resolve_channel_name(channel as u32));
unsafe { SEEN_ASYNC_ERRORS |= ASYNC_ERROR_BUSY };
}
Some(packet) => error!("[DEST#{}] received unexpected aux packet: {:?}", destination, packet),
None => {
// continue asking until we get Destination...Reply or error out
// wait a bit not to overwhelm the receiver causing gateway errors
io.sleep(10).unwrap();
continue;
}
}
} else {
error!("[DEST#{}] communication failed ({})", destination, reply.unwrap_err());
} }
Ok(drtioaux::Packet::DestinationOkReply) => (), break;
Ok(drtioaux::Packet::DestinationSequenceErrorReply { channel }) => {
error!("[DEST#{}] RTIO sequence error involving channel 0x{:04x}:{}", destination, channel, resolve_channel_name(channel as u32));
unsafe { SEEN_ASYNC_ERRORS |= ASYNC_ERROR_SEQUENCE_ERROR };
}
Ok(drtioaux::Packet::DestinationCollisionReply { channel }) => {
error!("[DEST#{}] RTIO collision involving channel 0x{:04x}:{}", destination, channel, resolve_channel_name(channel as u32));
unsafe { SEEN_ASYNC_ERRORS |= ASYNC_ERROR_COLLISION };
}
Ok(drtioaux::Packet::DestinationBusyReply { channel }) => {
error!("[DEST#{}] RTIO busy error involving channel 0x{:04x}:{}", destination, channel, resolve_channel_name(channel as u32));
unsafe { SEEN_ASYNC_ERRORS |= ASYNC_ERROR_BUSY };
}
Ok(packet) => error!("[DEST#{}] received unexpected aux packet: {:?}", destination, packet),
Err(e) => error!("[DEST#{}] communication failed ({})", destination, e)
} }
} else { } else {
destination_set_up(routing_table, up_destinations, destination, false); destination_set_up(routing_table, up_destinations, destination, false);
remote_dma::destination_changed(io, aux_mutex, routing_table, ddma_mutex, destination, false); remote_dma::destination_changed(io, aux_mutex, ddma_mutex, routing_table, destination, false);
} }
} else { } else {
if up_links[linkno as usize] { if up_links[linkno as usize] {
let reply = aux_transact(io, aux_mutex, ddma_mutex, linkno, &drtioaux::Packet::DestinationStatusRequest { let reply = aux_transact(io, aux_mutex, linkno,
destination: destination &drtioaux::Packet::DestinationStatusRequest {
}); destination: destination
});
match reply { match reply {
Ok(drtioaux::Packet::DestinationDownReply) => (), Ok(drtioaux::Packet::DestinationDownReply) => (),
Ok(drtioaux::Packet::DestinationOkReply) => { Ok(drtioaux::Packet::DestinationOkReply) => {
destination_set_up(routing_table, up_destinations, destination, true); destination_set_up(routing_table, up_destinations, destination, true);
init_buffer_space(destination as u8, linkno); init_buffer_space(destination as u8, linkno);
remote_dma::destination_changed(io, aux_mutex, routing_table, ddma_mutex, destination, true); remote_dma::destination_changed(io, aux_mutex, ddma_mutex, routing_table, destination, true);
}, },
Ok(packet) => error!("[DEST#{}] received unexpected aux packet: {:?}", destination, packet), Ok(packet) => error!("[DEST#{}] received unexpected aux packet: {:?}", destination, packet),
Err(e) => error!("[DEST#{}] communication failed ({})", destination, e) Err(e) => error!("[DEST#{}] communication failed ({})", destination, e)
@ -299,17 +320,17 @@ pub mod drtio {
/* link was previously down */ /* link was previously down */
if link_rx_up(linkno) { if link_rx_up(linkno) {
info!("[LINK#{}] link RX became up, pinging", linkno); info!("[LINK#{}] link RX became up, pinging", linkno);
let ping_count = ping_remote(&io, aux_mutex, ddma_mutex, linkno); let ping_count = ping_remote(&io, aux_mutex, linkno);
if ping_count > 0 { if ping_count > 0 {
info!("[LINK#{}] remote replied after {} packets", linkno, ping_count); info!("[LINK#{}] remote replied after {} packets", linkno, ping_count);
up_links[linkno as usize] = true; up_links[linkno as usize] = true;
if let Err(e) = sync_tsc(&io, aux_mutex, linkno) { if let Err(e) = sync_tsc(&io, aux_mutex, linkno) {
error!("[LINK#{}] failed to sync TSC ({})", linkno, e); error!("[LINK#{}] failed to sync TSC ({})", linkno, e);
} }
if let Err(e) = load_routing_table(&io, aux_mutex, ddma_mutex, linkno, routing_table) { if let Err(e) = load_routing_table(&io, aux_mutex, linkno, routing_table) {
error!("[LINK#{}] failed to load routing table ({})", linkno, e); error!("[LINK#{}] failed to load routing table ({})", linkno, e);
} }
if let Err(e) = set_rank(&io, aux_mutex, ddma_mutex, linkno, 1) { if let Err(e) = set_rank(&io, aux_mutex, linkno, 1) {
error!("[LINK#{}] failed to set rank ({})", linkno, e); error!("[LINK#{}] failed to set rank ({})", linkno, e);
} }
info!("[LINK#{}] link initialization completed", linkno); info!("[LINK#{}] link initialization completed", linkno);
@ -324,7 +345,7 @@ pub mod drtio {
} }
} }
pub fn reset(io: &Io, aux_mutex: &Mutex, ddma_mutex: &Mutex) { pub fn reset(io: &Io, aux_mutex: &Mutex) {
for linkno in 0..csr::DRTIO.len() { for linkno in 0..csr::DRTIO.len() {
unsafe { unsafe {
(csr::DRTIO[linkno].reset_write)(1); (csr::DRTIO[linkno].reset_write)(1);
@ -340,7 +361,7 @@ pub mod drtio {
for linkno in 0..csr::DRTIO.len() { for linkno in 0..csr::DRTIO.len() {
let linkno = linkno as u8; let linkno = linkno as u8;
if link_rx_up(linkno) { if link_rx_up(linkno) {
let reply = aux_transact(io, aux_mutex, ddma_mutex, linkno, let reply = aux_transact(io, aux_mutex, linkno,
&drtioaux::Packet::ResetRequest); &drtioaux::Packet::ResetRequest);
match reply { match reply {
Ok(drtioaux::Packet::ResetAck) => (), Ok(drtioaux::Packet::ResetAck) => (),
@ -351,8 +372,7 @@ pub mod drtio {
} }
} }
pub fn ddma_upload_trace(io: &Io, aux_mutex: &Mutex, ddma_mutex: &Mutex, pub fn ddma_upload_trace(io: &Io, aux_mutex: &Mutex, routing_table: &drtio_routing::RoutingTable,
routing_table: &drtio_routing::RoutingTable,
id: u32, destination: u8, trace: &Vec<u8>) -> Result<(), &'static str> { id: u32, destination: u8, trace: &Vec<u8>) -> Result<(), &'static str> {
let linkno = routing_table.0[destination as usize][0] - 1; let linkno = routing_table.0[destination as usize][0] - 1;
let mut i = 0; let mut i = 0;
@ -362,7 +382,7 @@ pub mod drtio {
let last = i + len == trace.len(); let last = i + len == trace.len();
trace_slice[..len].clone_from_slice(&trace[i..i+len]); trace_slice[..len].clone_from_slice(&trace[i..i+len]);
i += len; i += len;
let reply = aux_transact(io, aux_mutex, ddma_mutex, linkno, let reply = aux_transact(io, aux_mutex, linkno,
&drtioaux::Packet::DmaAddTraceRequest { &drtioaux::Packet::DmaAddTraceRequest {
id: id, destination: destination, last: last, length: len as u16, trace: trace_slice}); id: id, destination: destination, last: last, length: len as u16, trace: trace_slice});
match reply { match reply {
@ -376,12 +396,10 @@ pub mod drtio {
Ok(()) Ok(())
} }
pub fn ddma_send_erase(io: &Io, aux_mutex: &Mutex, routing_table: &drtio_routing::RoutingTable,
pub fn ddma_send_erase(io: &Io, aux_mutex: &Mutex, ddma_mutex: &Mutex,
routing_table: &drtio_routing::RoutingTable,
id: u32, destination: u8) -> Result<(), &'static str> { id: u32, destination: u8) -> Result<(), &'static str> {
let linkno = routing_table.0[destination as usize][0] - 1; let linkno = routing_table.0[destination as usize][0] - 1;
let reply = aux_transact(io, aux_mutex, ddma_mutex, linkno, let reply = aux_transact(io, aux_mutex, linkno,
&drtioaux::Packet::DmaRemoveTraceRequest { id: id, destination: destination }); &drtioaux::Packet::DmaRemoveTraceRequest { id: id, destination: destination });
match reply { match reply {
Ok(drtioaux::Packet::DmaRemoveTraceReply { succeeded: true }) => Ok(()), Ok(drtioaux::Packet::DmaRemoveTraceReply { succeeded: true }) => Ok(()),
@ -391,12 +409,11 @@ pub mod drtio {
} }
} }
pub fn ddma_send_playback(io: &Io, aux_mutex: &Mutex, ddma_mutex: &Mutex, pub fn ddma_send_playback(io: &Io, aux_mutex: &Mutex, routing_table: &drtio_routing::RoutingTable,
routing_table: &drtio_routing::RoutingTable,
id: u32, destination: u8, timestamp: u64) -> Result<(), &'static str> { id: u32, destination: u8, timestamp: u64) -> Result<(), &'static str> {
let linkno = routing_table.0[destination as usize][0] - 1; let linkno = routing_table.0[destination as usize][0] - 1;
let reply = aux_transact(io, aux_mutex, ddma_mutex, linkno, &drtioaux::Packet::DmaPlaybackRequest{ let reply = aux_transact(io, aux_mutex, linkno,
id: id, destination: destination, timestamp: timestamp }); &drtioaux::Packet::DmaPlaybackRequest{ id: id, destination: destination, timestamp: timestamp });
match reply { match reply {
Ok(drtioaux::Packet::DmaPlaybackReply { succeeded: true }) => return Ok(()), Ok(drtioaux::Packet::DmaPlaybackReply { succeeded: true }) => return Ok(()),
Ok(drtioaux::Packet::DmaPlaybackReply { succeeded: false }) => Ok(drtioaux::Packet::DmaPlaybackReply { succeeded: false }) =>
@ -407,11 +424,10 @@ pub mod drtio {
} }
#[cfg(has_rtio_analyzer)] #[cfg(has_rtio_analyzer)]
fn analyzer_get_data(io: &Io, aux_mutex: &Mutex, ddma_mutex: &Mutex, fn analyzer_get_data(io: &Io, aux_mutex: &Mutex, routing_table: &drtio_routing::RoutingTable,
routing_table: &drtio_routing::RoutingTable, destination: u8 destination: u8) -> Result<RemoteBuffer, &'static str> {
) -> Result<RemoteBuffer, &'static str> {
let linkno = routing_table.0[destination as usize][0] - 1; let linkno = routing_table.0[destination as usize][0] - 1;
let reply = aux_transact(io, aux_mutex, ddma_mutex, linkno, let reply = aux_transact(io, aux_mutex, linkno,
&drtioaux::Packet::AnalyzerHeaderRequest { destination: destination }); &drtioaux::Packet::AnalyzerHeaderRequest { destination: destination });
let (sent, total, overflow) = match reply { let (sent, total, overflow) = match reply {
Ok(drtioaux::Packet::AnalyzerHeader { Ok(drtioaux::Packet::AnalyzerHeader {
@ -425,7 +441,7 @@ pub mod drtio {
if sent > 0 { if sent > 0 {
let mut last_packet = false; let mut last_packet = false;
while !last_packet { while !last_packet {
let reply = aux_transact(io, aux_mutex, ddma_mutex, linkno, let reply = aux_transact(io, aux_mutex, linkno,
&drtioaux::Packet::AnalyzerDataRequest { destination: destination }); &drtioaux::Packet::AnalyzerDataRequest { destination: destination });
match reply { match reply {
Ok(drtioaux::Packet::AnalyzerData { last, length, data }) => { Ok(drtioaux::Packet::AnalyzerData { last, length, data }) => {
@ -447,14 +463,13 @@ pub mod drtio {
} }
#[cfg(has_rtio_analyzer)] #[cfg(has_rtio_analyzer)]
pub fn analyzer_query(io: &Io, aux_mutex: &Mutex, ddma_mutex: &Mutex, pub fn analyzer_query(io: &Io, aux_mutex: &Mutex, routing_table: &drtio_routing::RoutingTable,
routing_table: &drtio_routing::RoutingTable,
up_destinations: &Urc<RefCell<[bool; drtio_routing::DEST_COUNT]>> up_destinations: &Urc<RefCell<[bool; drtio_routing::DEST_COUNT]>>
) -> Result<Vec<RemoteBuffer>, &'static str> { ) -> Result<Vec<RemoteBuffer>, &'static str> {
let mut remote_buffers: Vec<RemoteBuffer> = Vec::new(); let mut remote_buffers: Vec<RemoteBuffer> = Vec::new();
for i in 1..drtio_routing::DEST_COUNT { for i in 1..drtio_routing::DEST_COUNT {
if destination_up(up_destinations, i as u8) { if destination_up(up_destinations, i as u8) {
remote_buffers.push(analyzer_get_data(io, aux_mutex, ddma_mutex, routing_table, i as u8)?); remote_buffers.push(analyzer_get_data(io, aux_mutex, routing_table, i as u8)?);
} }
} }
Ok(remote_buffers) Ok(remote_buffers)
@ -542,9 +557,9 @@ pub fn startup(io: &Io, aux_mutex: &Mutex,
io.spawn(4096, async_error_thread); io.spawn(4096, async_error_thread);
} }
pub fn reset(io: &Io, aux_mutex: &Mutex, ddma_mutex: &Mutex) { pub fn reset(io: &Io, aux_mutex: &Mutex) {
unsafe { unsafe {
csr::rtio_core::reset_write(1); csr::rtio_core::reset_write(1);
} }
drtio::reset(io, aux_mutex, ddma_mutex) drtio::reset(io, aux_mutex)
} }

View File

@ -349,7 +349,7 @@ fn process_kern_message(io: &Io, aux_mutex: &Mutex,
kern_recv_dotrace(request); kern_recv_dotrace(request);
if kern_hwreq::process_kern_hwreq(io, aux_mutex, ddma_mutex, routing_table, up_destinations, request)? { if kern_hwreq::process_kern_hwreq(io, aux_mutex, routing_table, up_destinations, request)? {
return Ok(false) return Ok(false)
} }
@ -373,7 +373,7 @@ fn process_kern_message(io: &Io, aux_mutex: &Mutex,
if let Some(_id) = session.congress.dma_manager.record_start(name) { if let Some(_id) = session.congress.dma_manager.record_start(name) {
// replace the record // replace the record
#[cfg(has_drtio)] #[cfg(has_drtio)]
remote_dma::erase(io, aux_mutex, routing_table, ddma_mutex, _id); remote_dma::erase(io, aux_mutex, ddma_mutex, routing_table, _id);
} }
kern_acknowledge() kern_acknowledge()
} }
@ -385,7 +385,7 @@ fn process_kern_message(io: &Io, aux_mutex: &Mutex,
let _id = session.congress.dma_manager.record_stop(duration, enable_ddma, io, ddma_mutex); let _id = session.congress.dma_manager.record_stop(duration, enable_ddma, io, ddma_mutex);
#[cfg(has_drtio)] #[cfg(has_drtio)]
if enable_ddma { if enable_ddma {
remote_dma::upload_traces(io, aux_mutex, routing_table, ddma_mutex, _id); remote_dma::upload_traces(io, aux_mutex, ddma_mutex, routing_table, _id);
} }
cache::flush_l2_cache(); cache::flush_l2_cache();
kern_acknowledge() kern_acknowledge()
@ -393,7 +393,7 @@ fn process_kern_message(io: &Io, aux_mutex: &Mutex,
&kern::DmaEraseRequest { name } => { &kern::DmaEraseRequest { name } => {
#[cfg(has_drtio)] #[cfg(has_drtio)]
if let Some(id) = session.congress.dma_manager.get_id(name) { if let Some(id) = session.congress.dma_manager.get_id(name) {
remote_dma::erase(io, aux_mutex, routing_table, ddma_mutex, *id); remote_dma::erase(io, aux_mutex, ddma_mutex, routing_table, *id);
} }
session.congress.dma_manager.erase(name); session.congress.dma_manager.erase(name);
kern_acknowledge() kern_acknowledge()
@ -416,7 +416,7 @@ fn process_kern_message(io: &Io, aux_mutex: &Mutex,
} }
&kern::DmaStartRemoteRequest { id: _id, timestamp: _timestamp } => { &kern::DmaStartRemoteRequest { id: _id, timestamp: _timestamp } => {
#[cfg(has_drtio)] #[cfg(has_drtio)]
remote_dma::playback(io, aux_mutex, routing_table, ddma_mutex, _id as u32, _timestamp as u64); remote_dma::playback(io, aux_mutex, ddma_mutex, routing_table, _id as u32, _timestamp as u64);
kern_acknowledge() kern_acknowledge()
} }
&kern::DmaAwaitRemoteRequest { id: _id } => { &kern::DmaAwaitRemoteRequest { id: _id } => {
@ -510,7 +510,6 @@ fn process_kern_message(io: &Io, aux_mutex: &Mutex,
} }
} }
} }
request => unexpected!("unexpected request {:?} from kernel CPU", request) request => unexpected!("unexpected request {:?} from kernel CPU", request)
}.and(Ok(false)) }.and(Ok(false))
}) })

View File

@ -109,37 +109,44 @@ fn process_aux_packet(_manager: &mut DmaManager, analyzer: &mut Analyzer, _repea
let hop = 0; let hop = 0;
if hop == 0 { if hop == 0 {
let errors; // async messages
unsafe { if let Some(status) = _manager.check_state() {
errors = csr::drtiosat::rtio_error_read(); info!("playback done, error: {}, channel: {}, timestamp: {}", status.error, status.channel, status.timestamp);
} drtioaux::send(0, &drtioaux::Packet::DmaPlaybackStatus {
if errors & 1 != 0 { destination: *_rank, id: status.id, error: status.error, channel: status.channel, timestamp: status.timestamp })?;
let channel; } else {
let errors;
unsafe { unsafe {
channel = csr::drtiosat::sequence_error_channel_read(); errors = csr::drtiosat::rtio_error_read();
csr::drtiosat::rtio_error_write(1);
} }
drtioaux::send(0, if errors & 1 != 0 {
&drtioaux::Packet::DestinationSequenceErrorReply { channel })?; let channel;
} else if errors & 2 != 0 { unsafe {
let channel; channel = csr::drtiosat::sequence_error_channel_read();
unsafe { csr::drtiosat::rtio_error_write(1);
channel = csr::drtiosat::collision_channel_read(); }
csr::drtiosat::rtio_error_write(2); drtioaux::send(0,
&drtioaux::Packet::DestinationSequenceErrorReply { channel })?;
} else if errors & 2 != 0 {
let channel;
unsafe {
channel = csr::drtiosat::collision_channel_read();
csr::drtiosat::rtio_error_write(2);
}
drtioaux::send(0,
&drtioaux::Packet::DestinationCollisionReply { channel })?;
} else if errors & 4 != 0 {
let channel;
unsafe {
channel = csr::drtiosat::busy_channel_read();
csr::drtiosat::rtio_error_write(4);
}
drtioaux::send(0,
&drtioaux::Packet::DestinationBusyReply { channel })?;
} }
drtioaux::send(0, else {
&drtioaux::Packet::DestinationCollisionReply { channel })?; drtioaux::send(0, &drtioaux::Packet::DestinationOkReply)?;
} else if errors & 4 != 0 {
let channel;
unsafe {
channel = csr::drtiosat::busy_channel_read();
csr::drtiosat::rtio_error_write(4);
} }
drtioaux::send(0,
&drtioaux::Packet::DestinationBusyReply { channel })?;
}
else {
drtioaux::send(0, &drtioaux::Packet::DestinationOkReply)?;
} }
} }
@ -643,13 +650,6 @@ pub extern fn main() -> i32 {
error!("aux packet error: {}", e); error!("aux packet error: {}", e);
} }
} }
if let Some(status) = dma_manager.check_state() {
info!("playback done, error: {}, channel: {}, timestamp: {}", status.error, status.channel, status.timestamp);
if let Err(e) = drtioaux::send(0, &drtioaux::Packet::DmaPlaybackStatus {
destination: rank, id: status.id, error: status.error, channel: status.channel, timestamp: status.timestamp }) {
error!("error sending DMA playback status: {}", e);
}
}
} }
drtiosat_reset_phy(true); drtiosat_reset_phy(true);