backport Ethernet bugfixes from master

This commit is contained in:
Sebastien Bourdeauducq 2017-12-07 12:21:21 +08:00
parent 0e5a5441aa
commit 76a908c8a9
5 changed files with 155 additions and 79 deletions

View File

@ -1,7 +1,3 @@
[root]
name = "std_artiq"
version = "0.0.0"
[[package]] [[package]]
name = "alloc_list" name = "alloc_list"
version = "0.0.0" version = "0.0.0"
@ -17,10 +13,16 @@ dependencies = [
"board 0.0.0", "board 0.0.0",
] ]
[[package]]
name = "bitflags"
version = "1.0.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
[[package]] [[package]]
name = "board" name = "board"
version = "0.0.0" version = "0.0.0"
dependencies = [ dependencies = [
"bitflags 1.0.0 (registry+https://github.com/rust-lang/crates.io-index)",
"build_artiq 0.0.0", "build_artiq 0.0.0",
"log 0.3.6 (registry+https://github.com/rust-lang/crates.io-index)", "log 0.3.6 (registry+https://github.com/rust-lang/crates.io-index)",
] ]
@ -129,7 +131,7 @@ dependencies = [
[[package]] [[package]]
name = "managed" name = "managed"
version = "0.4.0" version = "0.4.0"
source = "registry+https://github.com/rust-lang/crates.io-index" source = "git+https://github.com/m-labs/rust-managed.git?rev=629a6786a1cf1692015f464ed16c04eafa5cb8d1#629a6786a1cf1692015f464ed16c04eafa5cb8d1"
[[package]] [[package]]
name = "proto" name = "proto"
@ -158,7 +160,7 @@ dependencies = [
"log 0.3.6 (registry+https://github.com/rust-lang/crates.io-index)", "log 0.3.6 (registry+https://github.com/rust-lang/crates.io-index)",
"logger_artiq 0.0.0", "logger_artiq 0.0.0",
"proto 0.0.0", "proto 0.0.0",
"smoltcp 0.4.0 (git+https://github.com/m-labs/smoltcp?rev=1e18c03)", "smoltcp 0.4.0 (git+https://github.com/m-labs/smoltcp?rev=9914616)",
"std_artiq 0.0.0", "std_artiq 0.0.0",
] ]
@ -184,13 +186,17 @@ dependencies = [
[[package]] [[package]]
name = "smoltcp" name = "smoltcp"
version = "0.4.0" version = "0.4.0"
source = "git+https://github.com/m-labs/smoltcp?rev=1e18c03#1e18c03d3452daf63040924d01c3ce63865939bd" source = "git+https://github.com/m-labs/smoltcp?rev=9914616#9914616893c373de3fb52fcd2f06e0fffb4c8904"
dependencies = [ dependencies = [
"byteorder 1.0.0 (registry+https://github.com/rust-lang/crates.io-index)", "byteorder 1.0.0 (registry+https://github.com/rust-lang/crates.io-index)",
"log 0.3.6 (registry+https://github.com/rust-lang/crates.io-index)", "log 0.3.6 (registry+https://github.com/rust-lang/crates.io-index)",
"managed 0.4.0 (registry+https://github.com/rust-lang/crates.io-index)", "managed 0.4.0 (git+https://github.com/m-labs/rust-managed.git?rev=629a6786a1cf1692015f464ed16c04eafa5cb8d1)",
] ]
[[package]]
name = "std_artiq"
version = "0.0.0"
[[package]] [[package]]
name = "walkdir" name = "walkdir"
version = "1.0.3" version = "1.0.3"
@ -211,6 +217,7 @@ version = "0.1.1"
source = "registry+https://github.com/rust-lang/crates.io-index" source = "registry+https://github.com/rust-lang/crates.io-index"
[metadata] [metadata]
"checksum bitflags 1.0.0 (registry+https://github.com/rust-lang/crates.io-index)" = "f5cde24d1b2e2216a726368b2363a273739c91f4e3eb4e0dd12d672d396ad989"
"checksum byteorder 1.0.0 (registry+https://github.com/rust-lang/crates.io-index)" = "c40977b0ee6b9885c9013cd41d9feffdd22deb3bb4dc3a71d901cc7a77de18c8" "checksum byteorder 1.0.0 (registry+https://github.com/rust-lang/crates.io-index)" = "c40977b0ee6b9885c9013cd41d9feffdd22deb3bb4dc3a71d901cc7a77de18c8"
"checksum compiler_builtins 0.1.0 (git+https://github.com/rust-lang-nursery/compiler-builtins?rev=631b568)" = "<none>" "checksum compiler_builtins 0.1.0 (git+https://github.com/rust-lang-nursery/compiler-builtins?rev=631b568)" = "<none>"
"checksum cslice 0.3.0 (registry+https://github.com/rust-lang/crates.io-index)" = "0f8cb7306107e4b10e64994de6d3274bd08996a7c1322a27b86482392f96be0a" "checksum cslice 0.3.0 (registry+https://github.com/rust-lang/crates.io-index)" = "0f8cb7306107e4b10e64994de6d3274bd08996a7c1322a27b86482392f96be0a"
@ -220,9 +227,9 @@ source = "registry+https://github.com/rust-lang/crates.io-index"
"checksum libc 0.2.18 (registry+https://github.com/rust-lang/crates.io-index)" = "a51822fc847e7a8101514d1d44e354ba2ffa7d4c194dcab48870740e327cac70" "checksum libc 0.2.18 (registry+https://github.com/rust-lang/crates.io-index)" = "a51822fc847e7a8101514d1d44e354ba2ffa7d4c194dcab48870740e327cac70"
"checksum log 0.3.6 (registry+https://github.com/rust-lang/crates.io-index)" = "ab83497bf8bf4ed2a74259c1c802351fcd67a65baa86394b6ba73c36f4838054" "checksum log 0.3.6 (registry+https://github.com/rust-lang/crates.io-index)" = "ab83497bf8bf4ed2a74259c1c802351fcd67a65baa86394b6ba73c36f4838054"
"checksum log_buffer 1.1.0 (registry+https://github.com/rust-lang/crates.io-index)" = "ec57723b84bbe7bdf76aa93169c9b59e67473317c6de3a83cb2a0f8ccb2aa493" "checksum log_buffer 1.1.0 (registry+https://github.com/rust-lang/crates.io-index)" = "ec57723b84bbe7bdf76aa93169c9b59e67473317c6de3a83cb2a0f8ccb2aa493"
"checksum managed 0.4.0 (registry+https://github.com/rust-lang/crates.io-index)" = "b5d48e8c30a4363e2981fe4db20527f6ab0f32a243bbc75379dea5a64f60dae4" "checksum managed 0.4.0 (git+https://github.com/m-labs/rust-managed.git?rev=629a6786a1cf1692015f464ed16c04eafa5cb8d1)" = "<none>"
"checksum rustc-cfg 0.3.0 (registry+https://github.com/rust-lang/crates.io-index)" = "56a596b5718bf5e059d59a30af12f7f462a152de147aa462b70892849ee18704" "checksum rustc-cfg 0.3.0 (registry+https://github.com/rust-lang/crates.io-index)" = "56a596b5718bf5e059d59a30af12f7f462a152de147aa462b70892849ee18704"
"checksum smoltcp 0.4.0 (git+https://github.com/m-labs/smoltcp?rev=1e18c03)" = "<none>" "checksum smoltcp 0.4.0 (git+https://github.com/m-labs/smoltcp?rev=9914616)" = "<none>"
"checksum walkdir 1.0.3 (registry+https://github.com/rust-lang/crates.io-index)" = "dd7c16466ecc507c7cb5988db03e6eab4aaeab89a5c37a29251fcfd3ac9b7afe" "checksum walkdir 1.0.3 (registry+https://github.com/rust-lang/crates.io-index)" = "dd7c16466ecc507c7cb5988db03e6eab4aaeab89a5c37a29251fcfd3ac9b7afe"
"checksum winapi 0.2.8 (registry+https://github.com/rust-lang/crates.io-index)" = "167dc9d6949a9b857f3451275e911c3f44255842c1f7a76f33c55103a909087a" "checksum winapi 0.2.8 (registry+https://github.com/rust-lang/crates.io-index)" = "167dc9d6949a9b857f3451275e911c3f44255842c1f7a76f33c55103a909087a"
"checksum winapi-build 0.1.1 (registry+https://github.com/rust-lang/crates.io-index)" = "2d315eee3b34aca4797b2da6b13ed88266e6d612562a0c46390af8299fc699bc" "checksum winapi-build 0.1.1 (registry+https://github.com/rust-lang/crates.io-index)" = "2d315eee3b34aca4797b2da6b13ed88266e6d612562a0c46390af8299fc699bc"

View File

@ -37,6 +37,6 @@ features = ["alloc"]
[dependencies.smoltcp] [dependencies.smoltcp]
git = "https://github.com/m-labs/smoltcp" git = "https://github.com/m-labs/smoltcp"
rev = "1e18c03" rev = "9914616"
default-features = false default-features = false
features = ["alloc", "log", "proto-tcp"] features = ["alloc", "log", "socket-tcp"]

View File

@ -1,88 +1,158 @@
use core::slice; use core::{slice, fmt};
use smoltcp::Result;
use smoltcp::phy::{self, DeviceCapabilities, Device};
use board::{csr, mem}; use board::{csr, mem};
use smoltcp::Error;
use smoltcp::phy::{DeviceCapabilities, Device};
const RX0_BASE: usize = mem::ETHMAC_BASE + 0x0000; const RX_SLOTS: usize = csr::ETHMAC_RX_SLOTS as usize;
const RX1_BASE: usize = mem::ETHMAC_BASE + 0x0800; const TX_SLOTS: usize = csr::ETHMAC_TX_SLOTS as usize;
const RX2_BASE: usize = mem::ETHMAC_BASE + 0x1000; const SLOT_SIZE: usize = csr::ETHMAC_SLOT_SIZE as usize;
const RX3_BASE: usize = mem::ETHMAC_BASE + 0x1800;
const TX0_BASE: usize = mem::ETHMAC_BASE + 0x2000;
const TX1_BASE: usize = mem::ETHMAC_BASE + 0x2800;
const TX2_BASE: usize = mem::ETHMAC_BASE + 0x3000;
const TX3_BASE: usize = mem::ETHMAC_BASE + 0x3800;
const RX_BUFFERS: [*mut u8; 4] = [RX0_BASE as *mut u8, RX1_BASE as *mut u8, fn next_rx_slot() -> Option<usize> {
RX2_BASE as *mut u8, RX3_BASE as *mut u8]; unsafe {
const TX_BUFFERS: [*mut u8; 4] = [TX0_BASE as *mut u8, TX1_BASE as *mut u8, if csr::ethmac::sram_writer_ev_pending_read() == 0 {
TX2_BASE as *mut u8, TX3_BASE as *mut u8]; None
} else {
Some(csr::ethmac::sram_writer_slot_read() as usize)
}
}
}
pub struct EthernetDevice; fn next_tx_slot() -> Option<usize> {
unsafe {
if csr::ethmac::sram_reader_ready_read() == 0 {
None
} else {
Some((csr::ethmac::sram_reader_slot_read() as usize + 1) % TX_SLOTS)
}
}
}
impl Device for EthernetDevice { fn rx_buffer(slot: usize) -> *const u8 {
type RxBuffer = RxBuffer; debug_assert!(slot < RX_SLOTS);
type TxBuffer = TxBuffer; (mem::ETHMAC_BASE + SLOT_SIZE * slot) as _
}
fn tx_buffer(slot: usize) -> *mut u8 {
debug_assert!(slot < TX_SLOTS);
(mem::ETHMAC_BASE + SLOT_SIZE * (RX_SLOTS + slot)) as _
}
pub struct EthernetDevice(());
impl EthernetDevice {
pub unsafe fn new() -> EthernetDevice {
EthernetDevice(())
}
}
impl<'a> Device<'a> for EthernetDevice {
type RxToken = EthernetRxSlot;
type TxToken = EthernetTxSlot;
fn capabilities(&self) -> DeviceCapabilities { fn capabilities(&self) -> DeviceCapabilities {
let mut caps = DeviceCapabilities::default(); let mut caps = DeviceCapabilities::default();
caps.max_transmission_unit = 1514; caps.max_transmission_unit = 1514;
caps.max_burst_size = Some(RX_BUFFERS.len()); caps.max_burst_size = Some(RX_SLOTS);
caps caps
} }
fn receive(&mut self, _timestamp: u64) -> Result<Self::RxBuffer, Error> { fn receive(&mut self) -> Option<(Self::RxToken, Self::TxToken)> {
unsafe { if let (Some(rx_slot), Some(tx_slot)) = (next_rx_slot(), next_tx_slot()) {
if csr::ethmac::sram_writer_ev_pending_read() != 0 { Some((EthernetRxSlot(rx_slot), EthernetTxSlot(tx_slot)))
let slot = csr::ethmac::sram_writer_slot_read(); } else {
let length = csr::ethmac::sram_writer_length_read(); None
Ok(RxBuffer(slice::from_raw_parts(RX_BUFFERS[slot as usize],
length as usize)))
} else {
Err(Error::Exhausted)
}
} }
} }
fn transmit(&mut self, _timestamp: u64, length: usize) -> Result<Self::TxBuffer, Error> { fn transmit(&mut self) -> Option<Self::TxToken> {
unsafe { if let Some(tx_slot) = next_tx_slot() {
if csr::ethmac::sram_reader_ready_read() != 0 { Some(EthernetTxSlot(tx_slot))
let slot = csr::ethmac::sram_reader_slot_read(); } else {
let slot = (slot + 1) % (TX_BUFFERS.len() as u8); None
csr::ethmac::sram_reader_slot_write(slot);
csr::ethmac::sram_reader_length_write(length as u16);
Ok(TxBuffer(slice::from_raw_parts_mut(TX_BUFFERS[slot as usize],
length as usize)))
} else {
Err(Error::Exhausted)
}
} }
} }
} }
pub struct RxBuffer(&'static [u8]); pub struct EthernetRxSlot(usize);
impl AsRef<[u8]> for RxBuffer { impl phy::RxToken for EthernetRxSlot {
fn as_ref(&self) -> &[u8] { self.0 } fn consume<R, F>(self, _timestamp: u64, f: F) -> Result<R>
} where F: FnOnce(&[u8]) -> Result<R>
{
impl Drop for RxBuffer { unsafe {
fn drop(&mut self) { let length = csr::ethmac::sram_writer_length_read() as usize;
unsafe { csr::ethmac::sram_writer_ev_pending_write(1) } let result = f(slice::from_raw_parts(rx_buffer(self.0), length));
csr::ethmac::sram_writer_ev_pending_write(1);
result
}
} }
} }
pub struct TxBuffer(&'static mut [u8]); pub struct EthernetTxSlot(usize);
impl AsRef<[u8]> for TxBuffer { impl phy::TxToken for EthernetTxSlot {
fn as_ref(&self) -> &[u8] { self.0 } fn consume<R, F>(self, _timestamp: u64, length: usize, f: F) -> Result<R>
} where F: FnOnce(&mut [u8]) -> Result<R>
{
debug_assert!(length < SLOT_SIZE);
impl AsMut<[u8]> for TxBuffer { unsafe {
fn as_mut(&mut self) -> &mut [u8] { self.0 } let result = f(slice::from_raw_parts_mut(tx_buffer(self.0), length))?;
} csr::ethmac::sram_reader_slot_write(self.0 as u8);
csr::ethmac::sram_reader_length_write(length as u16);
impl Drop for TxBuffer { csr::ethmac::sram_reader_start_write(1);
fn drop(&mut self) { Ok(result)
unsafe { csr::ethmac::sram_reader_start_write(1) } }
}
}
#[derive(Debug, Clone, PartialEq, Eq, Default)]
pub struct EthernetStatistics {
rx_preamble_errors: u32,
rx_crc_errors: u32,
rx_dropped: u32,
}
impl EthernetStatistics {
pub fn new() -> Self {
unsafe {
EthernetStatistics {
rx_preamble_errors: csr::ethmac::preamble_errors_read(),
rx_crc_errors: csr::ethmac::crc_errors_read(),
rx_dropped: csr::ethmac::sram_writer_errors_read(),
}
}
}
pub fn update(&mut self) -> Option<Self> {
let old = self.clone();
*self = Self::new();
let diff = EthernetStatistics {
rx_preamble_errors: self.rx_preamble_errors.wrapping_sub(old.rx_preamble_errors),
rx_crc_errors: self.rx_crc_errors.wrapping_sub(old.rx_crc_errors),
rx_dropped: self.rx_dropped.wrapping_sub(old.rx_dropped),
};
if diff == EthernetStatistics::default() {
None
} else {
Some(diff)
}
}
}
impl fmt::Display for EthernetStatistics {
fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
if self.rx_preamble_errors > 0 {
write!(f, " rx preamble errors: {}", self.rx_preamble_errors)?
}
if self.rx_crc_errors > 0 {
write!(f, " rx crc errors: {}", self.rx_crc_errors)?
}
if self.rx_dropped > 0 {
write!(f, " rx dropped: {}", self.rx_dropped)?
}
Ok(())
} }
} }

View File

@ -21,7 +21,6 @@ extern crate amp;
#[cfg(has_drtio)] #[cfg(has_drtio)]
extern crate drtioaux; extern crate drtioaux;
use std::boxed::Box;
use smoltcp::wire::{EthernetAddress, IpAddress, IpCidr}; use smoltcp::wire::{EthernetAddress, IpAddress, IpCidr};
use proto::{mgmt_proto, analyzer_proto, moninj_proto, rpc_proto, session_proto, kernel_proto}; use proto::{mgmt_proto, analyzer_proto, moninj_proto, rpc_proto, session_proto, kernel_proto};
use amp::{mailbox, rpc_queue}; use amp::{mailbox, rpc_queue};
@ -112,12 +111,12 @@ fn startup() {
// print!("\x1b[37m[{:6}.{:06}s]\n{}\x1b[0m", seconds, micros, printer) // print!("\x1b[37m[{:6}.{:06}s]\n{}\x1b[0m", seconds, micros, printer)
// } // }
let net_device = ethmac::EthernetDevice; let net_device = unsafe { ethmac::EthernetDevice::new() };
// let net_device = smoltcp::phy::EthernetTracer::new(net_device, _net_trace_writer); // let net_device = smoltcp::phy::EthernetTracer::new(net_device, _net_trace_writer);
let arp_cache = smoltcp::iface::SliceArpCache::new([Default::default(); 8]); let mut neighbor_cache_storage = [None; 8];
let neighbor_cache = smoltcp::iface::NeighborCache::new(&mut neighbor_cache_storage[..]);
let mut interface = smoltcp::iface::EthernetInterface::new( let mut interface = smoltcp::iface::EthernetInterface::new(
Box::new(net_device), Box::new(arp_cache) as Box<smoltcp::iface::ArpCache>, net_device, neighbor_cache, hardware_addr, [IpCidr::new(protocol_addr, 0)], None);
hardware_addr, [IpCidr::new(protocol_addr, 0)], None);
let mut scheduler = sched::Scheduler::new(); let mut scheduler = sched::Scheduler::new();
let io = scheduler.io(); let io = scheduler.io();

View File

@ -15,7 +15,7 @@ requirements:
- python >=3.5.3,<3.6 - python >=3.5.3,<3.6
- setuptools 33.1.1 - setuptools 33.1.1
- migen 0.5 - migen 0.5
- misoc 0.6 - misoc 0.7
- jesd204b 0.3 - jesd204b 0.3
- binutils-or1k-linux >=2.27 - binutils-or1k-linux >=2.27
- llvm-or1k - llvm-or1k