From d87b874b211c5c663f736e24e18a573be2133a67 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Bj=C3=B6rn=20Stein?= Date: Fri, 18 Oct 2019 00:04:22 +0200 Subject: [PATCH] eth: add memory barriers, reorder access --- src/eth/rx.rs | 8 ++++++++ src/eth/tx.rs | 12 +++++++++++- 2 files changed, 19 insertions(+), 1 deletion(-) diff --git a/src/eth/rx.rs b/src/eth/rx.rs index 9022ff9..940f28b 100644 --- a/src/eth/rx.rs +++ b/src/eth/rx.rs @@ -2,6 +2,8 @@ use core::ops::Deref; use crate::{register, register_bit, register_bits, regs::*}; use super::MTU; +use crate::cortex_a9::asm; + #[derive(Debug)] pub enum Error { HrespNotOk, @@ -67,6 +69,8 @@ impl<'a> DescList<'a> { DescWord1::zeroed() ); } + // Ensure descriptors get written before they are read. + asm::dmb(); DescList { // Shorten the list of descriptors to the required number. @@ -86,6 +90,7 @@ impl<'a> DescList<'a> { if entry.word0.read().used() { let word1 = entry.word1.read(); let len = word1.frame_length_lsbs().into(); + asm::dmb(); let buffer = &mut self.buffers[self.next][0..len]; self.next += 1; @@ -113,6 +118,9 @@ pub struct PktRef<'a> { impl<'a> Drop for PktRef<'a> { fn drop(&mut self) { + // Ensure that any buffer reads have finished before we + // release the buffer to the hardware. + asm::dmb(); self.entry.word0.modify(|_, w| w.used(false)); } } diff --git a/src/eth/tx.rs b/src/eth/tx.rs index 4bf0185..5685340 100644 --- a/src/eth/tx.rs +++ b/src/eth/tx.rs @@ -1,5 +1,6 @@ use core::ops::{Deref, DerefMut}; use crate::{register, register_bit, register_bits, regs::*}; +use crate::cortex_a9::asm; use super::{MTU, regs}; /// Descriptor entry @@ -62,6 +63,8 @@ impl<'a> DescList<'a> { .last_buffer(true) ); } + // Ensure the descriptor words get written before they are read. + asm::dsb(); DescList { // Shorten the list of descriptors to the required number. @@ -79,8 +82,8 @@ impl<'a> DescList<'a> { let list_len = self.list.len(); let entry = &mut self.list[self.next]; if entry.word1.read().used() { - entry.word1.modify(|_, w| w.length(length as u16)); let buffer = &mut self.buffers[self.next][0..length]; + entry.word1.modify(|_, w| w.length(length as u16)); self.next += 1; if self.next >= list_len { @@ -105,7 +108,14 @@ pub struct PktRef<'a> { impl<'a> Drop for PktRef<'a> { fn drop(&mut self) { + // Ensure that all writes to the buffer have finished before + // they are read again. + asm::dmb(); self.entry.word1.modify(|_, w| w.used(false)); + // Ensure that the descriptor write has finished before it is + // read again, and (by DSB, not just DMB) that it has been + // written before the register access. + asm::dsb(); if ! self.regs.tx_status.read().tx_go() { self.regs.net_ctrl.modify(|_, w| w.start_tx(true)