From 95f3484b87d7ae829e14492a43d49a5a0a58f1b8 Mon Sep 17 00:00:00 2001 From: Jan Niehusmann Date: Tue, 6 Sep 2022 11:38:33 +0000 Subject: [PATCH 1/2] Implement minimal tx flow control The credit update code uses constants from https://github.com/Infineon/wifi-host-driver/blob/master/WiFi_Host_Driver/src/whd_sdpcm.c#L307-L317 --- src/lib.rs | 32 ++++++++++++++++++++++++++------ 1 file changed, 26 insertions(+), 6 deletions(-) diff --git a/src/lib.rs b/src/lib.rs index 34170a26..f818caf6 100644 --- a/src/lib.rs +++ b/src/lib.rs @@ -525,6 +525,8 @@ pub struct Runner<'a, PWR, SPI> { ioctl_id: u16, sdpcm_seq: u8, backplane_window: u32, + + tx_seq_max: u8, } pub async fn new<'a, PWR, SPI>( @@ -546,6 +548,8 @@ where ioctl_id: 0, sdpcm_seq: 0, backplane_window: 0xAAAA_AAAA, + + tx_seq_max: 1, }; runner.init(firmware).await; @@ -670,13 +674,17 @@ where loop { // Send stuff // TODO flow control - if let IoctlState::Pending { kind, cmd, iface, buf } = self.state.ioctl_state.get() { - self.send_ioctl(kind, cmd, iface, unsafe { &*buf }).await; - self.state.ioctl_state.set(IoctlState::Sent { buf }); - } + if self.sdpcm_seq == self.tx_seq_max || self.tx_seq_max.wrapping_sub(self.sdpcm_seq) & 0x80 != 0 { + warn!("TX stalled"); + } else { + if let IoctlState::Pending { kind, cmd, iface, buf } = self.state.ioctl_state.get() { + self.send_ioctl(kind, cmd, iface, unsafe { &*buf }).await; + self.state.ioctl_state.set(IoctlState::Sent { buf }); + } - if let Ok(p) = self.state.tx_channel.try_recv() { - self.send_packet(&p).await; + if let Ok(p) = self.state.tx_channel.try_recv() { + self.send_packet(&p).await; + } } // Receive stuff @@ -788,6 +796,8 @@ where return; } + self.update_credit(&sdpcm_header); + let channel = sdpcm_header.channel_and_flags & 0x0f; let payload = &packet[sdpcm_header.header_length as _..]; @@ -894,6 +904,16 @@ where } } + fn update_credit(&mut self, sdpcm_header: &SdpcmHeader) { + if sdpcm_header.channel_and_flags & 0xf < 3 { + let mut tx_seq_max = sdpcm_header.bus_data_credit; + if tx_seq_max - self.sdpcm_seq > 0x40 { + tx_seq_max = self.sdpcm_seq + 2; + } + self.tx_seq_max = tx_seq_max; + } + } + async fn send_ioctl(&mut self, kind: u32, cmd: u32, iface: u32, data: &[u8]) { let mut buf = [0; 512]; let buf8 = slice8_mut(&mut buf); From 5c4d6232ae5822d70cba4dbd60cfe348a7f0d687 Mon Sep 17 00:00:00 2001 From: Jan Niehusmann Date: Tue, 6 Sep 2022 20:50:27 +0000 Subject: [PATCH 2/2] Fixes after review - rename tx_seq_max to sdpcm_seq_max - make sure we have credit for each packet we send --- src/lib.rs | 29 ++++++++++++++++++----------- 1 file changed, 18 insertions(+), 11 deletions(-) diff --git a/src/lib.rs b/src/lib.rs index f818caf6..5e79e6e4 100644 --- a/src/lib.rs +++ b/src/lib.rs @@ -526,7 +526,7 @@ pub struct Runner<'a, PWR, SPI> { sdpcm_seq: u8, backplane_window: u32, - tx_seq_max: u8, + sdpcm_seq_max: u8, } pub async fn new<'a, PWR, SPI>( @@ -549,7 +549,7 @@ where sdpcm_seq: 0, backplane_window: 0xAAAA_AAAA, - tx_seq_max: 1, + sdpcm_seq_max: 1, }; runner.init(firmware).await; @@ -673,17 +673,20 @@ where let mut buf = [0; 512]; loop { // Send stuff - // TODO flow control - if self.sdpcm_seq == self.tx_seq_max || self.tx_seq_max.wrapping_sub(self.sdpcm_seq) & 0x80 != 0 { + // TODO flow control not yet complete + if !self.has_credit() { warn!("TX stalled"); } else { if let IoctlState::Pending { kind, cmd, iface, buf } = self.state.ioctl_state.get() { self.send_ioctl(kind, cmd, iface, unsafe { &*buf }).await; self.state.ioctl_state.set(IoctlState::Sent { buf }); } - - if let Ok(p) = self.state.tx_channel.try_recv() { - self.send_packet(&p).await; + if !self.has_credit() { + warn!("TX stalled"); + } else { + if let Ok(p) = self.state.tx_channel.try_recv() { + self.send_packet(&p).await; + } } } @@ -906,14 +909,18 @@ where fn update_credit(&mut self, sdpcm_header: &SdpcmHeader) { if sdpcm_header.channel_and_flags & 0xf < 3 { - let mut tx_seq_max = sdpcm_header.bus_data_credit; - if tx_seq_max - self.sdpcm_seq > 0x40 { - tx_seq_max = self.sdpcm_seq + 2; + let mut sdpcm_seq_max = sdpcm_header.bus_data_credit; + if sdpcm_seq_max - self.sdpcm_seq > 0x40 { + sdpcm_seq_max = self.sdpcm_seq + 2; } - self.tx_seq_max = tx_seq_max; + self.sdpcm_seq_max = sdpcm_seq_max; } } + fn has_credit(&mut self) -> bool { + self.sdpcm_seq != self.sdpcm_seq_max && self.sdpcm_seq_max.wrapping_sub(self.sdpcm_seq) & 0x80 == 0 + } + async fn send_ioctl(&mut self, kind: u32, cmd: u32, iface: u32, data: &[u8]) { let mut buf = [0; 512]; let buf8 = slice8_mut(&mut buf);