eth: add memory barriers, reorder access
This commit is contained in:
parent
9053166acc
commit
d87b874b21
|
@ -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));
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -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)
|
||||||
|
|
Loading…
Reference in New Issue