diff --git a/drivers/net/rtl8139d/src/device.rs b/drivers/net/rtl8139d/src/device.rs index d742813296..7e19e7b651 100644 --- a/drivers/net/rtl8139d/src/device.rs +++ b/drivers/net/rtl8139d/src/device.rs @@ -138,6 +138,11 @@ impl NetworkAdapter for Rtl8139 { fn read_packet(&mut self, buf: &mut [u8]) -> Result> { if !self.regs.cr.readf(CR_BUFE) { + // Acquire fence pairs the device's write of rxsts / size / + // data with our subsequent reads on weakly-ordered + // architectures. + core::sync::atomic::fence(core::sync::atomic::Ordering::Acquire); + let rxsts = (self.rx(0) as u16) | (self.rx(1) as u16) << 8; let size_with_crc = (self.rx(2) as usize) | (self.rx(3) as usize) << 8; @@ -158,6 +163,10 @@ impl NetworkAdapter for Rtl8139 { self.receive_i = (self.receive_i + 4 + size_with_crc).next_multiple_of(4) % RX_BUFFER_SIZE; let capr = self.receive_i.wrapping_sub(16) as u16; + // Release fence ensures the buffer reads above are + // visible to the device before the CAPR doorbell is + // observed. + core::sync::atomic::fence(core::sync::atomic::Ordering::Release); self.regs.capr.write(capr); res @@ -189,6 +198,11 @@ impl NetworkAdapter for Rtl8139 { assert_eq!(i as u32, i as u32 & TSD_SIZE_MASK); self.regs.tsd[self.transmit_i].write(i as u32 & TSD_SIZE_MASK); + // Release fence ensures the buffer writes above are + // visible to the device before the TSD doorbell is + // observed. + core::sync::atomic::fence(core::sync::atomic::Ordering::Release); + //TODO: wait for TSD_TOK or error self.transmit_i += 1;