eth: add memory barriers, reorder access

This commit is contained in:
Björn Stein 2019-10-18 00:04:22 +02:00 committed by Astro
parent 9053166acc
commit d87b874b21
2 changed files with 19 additions and 1 deletions

View File

@ -2,6 +2,8 @@ use core::ops::Deref;
use crate::{register, register_bit, register_bits, regs::*}; use crate::{register, register_bit, register_bits, regs::*};
use super::MTU; use super::MTU;
use crate::cortex_a9::asm;
#[derive(Debug)] #[derive(Debug)]
pub enum Error { pub enum Error {
HrespNotOk, HrespNotOk,
@ -67,6 +69,8 @@ impl<'a> DescList<'a> {
DescWord1::zeroed() DescWord1::zeroed()
); );
} }
// Ensure descriptors get written before they are read.
asm::dmb();
DescList { DescList {
// Shorten the list of descriptors to the required number. // Shorten the list of descriptors to the required number.
@ -86,6 +90,7 @@ impl<'a> DescList<'a> {
if entry.word0.read().used() { if entry.word0.read().used() {
let word1 = entry.word1.read(); let word1 = entry.word1.read();
let len = word1.frame_length_lsbs().into(); let len = word1.frame_length_lsbs().into();
asm::dmb();
let buffer = &mut self.buffers[self.next][0..len]; let buffer = &mut self.buffers[self.next][0..len];
self.next += 1; self.next += 1;
@ -113,6 +118,9 @@ pub struct PktRef<'a> {
impl<'a> Drop for PktRef<'a> { impl<'a> Drop for PktRef<'a> {
fn drop(&mut self) { 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)); self.entry.word0.modify(|_, w| w.used(false));
} }
} }

View File

@ -1,5 +1,6 @@
use core::ops::{Deref, DerefMut}; use core::ops::{Deref, DerefMut};
use crate::{register, register_bit, register_bits, regs::*}; use crate::{register, register_bit, register_bits, regs::*};
use crate::cortex_a9::asm;
use super::{MTU, regs}; use super::{MTU, regs};
/// Descriptor entry /// Descriptor entry
@ -62,6 +63,8 @@ impl<'a> DescList<'a> {
.last_buffer(true) .last_buffer(true)
); );
} }
// Ensure the descriptor words get written before they are read.
asm::dsb();
DescList { DescList {
// Shorten the list of descriptors to the required number. // Shorten the list of descriptors to the required number.
@ -79,8 +82,8 @@ impl<'a> DescList<'a> {
let list_len = self.list.len(); let list_len = self.list.len();
let entry = &mut self.list[self.next]; let entry = &mut self.list[self.next];
if entry.word1.read().used() { if entry.word1.read().used() {
entry.word1.modify(|_, w| w.length(length as u16));
let buffer = &mut self.buffers[self.next][0..length]; let buffer = &mut self.buffers[self.next][0..length];
entry.word1.modify(|_, w| w.length(length as u16));
self.next += 1; self.next += 1;
if self.next >= list_len { if self.next >= list_len {
@ -105,7 +108,14 @@ pub struct PktRef<'a> {
impl<'a> Drop for PktRef<'a> { impl<'a> Drop for PktRef<'a> {
fn drop(&mut self) { 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)); 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() { if ! self.regs.tx_status.read().tx_go() {
self.regs.net_ctrl.modify(|_, w| self.regs.net_ctrl.modify(|_, w|
w.start_tx(true) w.start_tx(true)