forked from M-Labs/zynq-rs
eth: always just allocate desc list + buffers
buffers are allocated vec anyway. this removes the lifetime hack and further prepares work on cache-line alignment to enable L1 writeback.
This commit is contained in:
parent
187ef703f2
commit
a1a211334f
|
@ -4,7 +4,7 @@
|
||||||
extern crate alloc;
|
extern crate alloc;
|
||||||
|
|
||||||
use alloc::{borrow::ToOwned, collections::BTreeMap, format};
|
use alloc::{borrow::ToOwned, collections::BTreeMap, format};
|
||||||
use core::{mem::transmute, task::Poll};
|
use core::task::Poll;
|
||||||
use libasync::{
|
use libasync::{
|
||||||
delay,
|
delay,
|
||||||
smoltcp::{Sockets, TcpStream},
|
smoltcp::{Sockets, TcpStream},
|
||||||
|
@ -30,7 +30,6 @@ use libcortex_a9::{
|
||||||
};
|
};
|
||||||
use libregister::RegisterR;
|
use libregister::RegisterR;
|
||||||
use libsupport_zynq::{
|
use libsupport_zynq::{
|
||||||
alloc::{vec, vec::Vec},
|
|
||||||
boot, ram,
|
boot, ram,
|
||||||
};
|
};
|
||||||
use log::info;
|
use log::info;
|
||||||
|
@ -181,24 +180,11 @@ pub fn main_core0() {
|
||||||
println!("Eth on");
|
println!("Eth on");
|
||||||
|
|
||||||
const RX_LEN: usize = 8;
|
const RX_LEN: usize = 8;
|
||||||
let mut rx_descs = (0..RX_LEN)
|
|
||||||
.map(|_| zynq::eth::rx::DescEntry::zeroed())
|
|
||||||
.collect::<Vec<_>>();
|
|
||||||
let mut rx_buffers = vec![zynq::eth::Buffer::new(); RX_LEN];
|
|
||||||
// Number of transmission buffers (minimum is two because with
|
// Number of transmission buffers (minimum is two because with
|
||||||
// one, duplicate packet transmission occurs)
|
// one, duplicate packet transmission occurs)
|
||||||
const TX_LEN: usize = 8;
|
const TX_LEN: usize = 8;
|
||||||
let mut tx_descs = (0..TX_LEN)
|
let eth = eth.start_rx(RX_LEN);
|
||||||
.map(|_| zynq::eth::tx::DescEntry::zeroed())
|
let mut eth = eth.start_tx(TX_LEN);
|
||||||
.collect::<Vec<_>>();
|
|
||||||
let mut tx_buffers = vec![zynq::eth::Buffer::new(); TX_LEN];
|
|
||||||
let eth = eth.start_rx(&mut rx_descs, &mut rx_buffers);
|
|
||||||
// let mut eth = eth.start_tx(&mut tx_descs, &mut tx_buffers);
|
|
||||||
let mut eth = eth.start_tx(
|
|
||||||
// HACK
|
|
||||||
unsafe { transmute(tx_descs.as_mut_slice()) },
|
|
||||||
unsafe { transmute(tx_buffers.as_mut_slice()) },
|
|
||||||
);
|
|
||||||
|
|
||||||
let ethernet_addr = EthernetAddress(HWADDR);
|
let ethernet_addr = EthernetAddress(HWADDR);
|
||||||
// IP stack
|
// IP stack
|
||||||
|
|
|
@ -263,9 +263,9 @@ impl<'r, RX, TX> Eth<'r, RX, TX> {
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn start_rx<'rx>(self, rx_list: &'rx mut [rx::DescEntry], rx_buffers: &'rx mut [Buffer]) -> Eth<'r, rx::DescList<'rx>, TX> {
|
pub fn start_rx(self, rx_size: usize) -> Eth<'r, rx::DescList, TX> {
|
||||||
let new_self = Eth {
|
let new_self = Eth {
|
||||||
rx: rx::DescList::new(rx_list, rx_buffers),
|
rx: rx::DescList::new(rx_size),
|
||||||
tx: self.tx,
|
tx: self.tx,
|
||||||
inner: self.inner,
|
inner: self.inner,
|
||||||
phy: self.phy,
|
phy: self.phy,
|
||||||
|
@ -282,10 +282,10 @@ impl<'r, RX, TX> Eth<'r, RX, TX> {
|
||||||
new_self
|
new_self
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn start_tx<'tx>(self, tx_list: &'tx mut [tx::DescEntry], tx_buffers: &'tx mut [Buffer]) -> Eth<'r, RX, tx::DescList<'tx>> {
|
pub fn start_tx(self, tx_size: usize) -> Eth<'r, RX, tx::DescList> {
|
||||||
let new_self = Eth {
|
let new_self = Eth {
|
||||||
rx: self.rx,
|
rx: self.rx,
|
||||||
tx: tx::DescList::new(tx_list, tx_buffers),
|
tx: tx::DescList::new(tx_size),
|
||||||
inner: self.inner,
|
inner: self.inner,
|
||||||
phy: self.phy,
|
phy: self.phy,
|
||||||
};
|
};
|
||||||
|
@ -302,7 +302,7 @@ impl<'r, RX, TX> Eth<'r, RX, TX> {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
impl<'r, 'rx, TX> Eth<'r, rx::DescList<'rx>, TX> {
|
impl<'r, TX> Eth<'r, rx::DescList, TX> {
|
||||||
pub fn recv_next<'s: 'p, 'p>(&'s mut self) -> Result<Option<rx::PktRef<'p>>, rx::Error> {
|
pub fn recv_next<'s: 'p, 'p>(&'s mut self) -> Result<Option<rx::PktRef<'p>>, rx::Error> {
|
||||||
let status = self.inner.regs.rx_status.read();
|
let status = self.inner.regs.rx_status.read();
|
||||||
if status.hresp_not_ok() {
|
if status.hresp_not_ok() {
|
||||||
|
@ -350,15 +350,15 @@ impl<'r, 'rx, TX> Eth<'r, rx::DescList<'rx>, TX> {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
impl<'r, 'tx, RX> Eth<'r, RX, tx::DescList<'tx>> {
|
impl<'r, RX> Eth<'r, RX, tx::DescList> {
|
||||||
pub fn send<'s: 'p, 'p>(&'s mut self, length: usize) -> Option<tx::PktRef<'p>> {
|
pub fn send<'s: 'p, 'p>(&'s mut self, length: usize) -> Option<tx::PktRef<'p>> {
|
||||||
self.tx.send(self.inner.regs, length)
|
self.tx.send(self.inner.regs, length)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
impl<'r, 'rx, 'tx: 'a, 'a> smoltcp::phy::Device<'a> for &mut Eth<'r, rx::DescList<'rx>, tx::DescList<'tx>> {
|
impl<'r, 'a> smoltcp::phy::Device<'a> for &mut Eth<'r, rx::DescList, tx::DescList> {
|
||||||
type RxToken = rx::PktRef<'a>;
|
type RxToken = rx::PktRef<'a>;
|
||||||
type TxToken = tx::Token<'a, 'tx>;
|
type TxToken = tx::Token<'a>;
|
||||||
|
|
||||||
fn capabilities(&self) -> smoltcp::phy::DeviceCapabilities {
|
fn capabilities(&self) -> smoltcp::phy::DeviceCapabilities {
|
||||||
use smoltcp::phy::{DeviceCapabilities, ChecksumCapabilities, Checksum};
|
use smoltcp::phy::{DeviceCapabilities, ChecksumCapabilities, Checksum};
|
||||||
|
|
|
@ -1,4 +1,5 @@
|
||||||
use core::ops::Deref;
|
use core::ops::Deref;
|
||||||
|
use alloc::{vec, vec::Vec};
|
||||||
use libregister::*;
|
use libregister::*;
|
||||||
use super::Buffer;
|
use super::Buffer;
|
||||||
|
|
||||||
|
@ -53,14 +54,18 @@ register_bit!(desc_word1, multi_hash_match, 30);
|
||||||
register_bit!(desc_word1, global_broadcast, 31);
|
register_bit!(desc_word1, global_broadcast, 31);
|
||||||
|
|
||||||
#[repr(C)]
|
#[repr(C)]
|
||||||
pub struct DescList<'a> {
|
pub struct DescList {
|
||||||
list: &'a mut [DescEntry],
|
list: Vec<DescEntry>,
|
||||||
buffers: &'a mut [Buffer],
|
buffers: Vec<Buffer>,
|
||||||
next: usize,
|
next: usize,
|
||||||
}
|
}
|
||||||
|
|
||||||
impl<'a> DescList<'a> {
|
impl DescList {
|
||||||
pub fn new(list: &'a mut [DescEntry], buffers: &'a mut [Buffer]) -> Self {
|
pub fn new(size: usize) -> Self {
|
||||||
|
let mut list: Vec<_> = (0..size).map(|_| DescEntry::zeroed())
|
||||||
|
.collect();
|
||||||
|
let mut buffers = vec![Buffer::new(); size];
|
||||||
|
|
||||||
let last = list.len().min(buffers.len()) - 1;
|
let last = list.len().min(buffers.len()) - 1;
|
||||||
for (i, (entry, buffer)) in list.iter_mut().zip(buffers.iter_mut()).enumerate() {
|
for (i, (entry, buffer)) in list.iter_mut().zip(buffers.iter_mut()).enumerate() {
|
||||||
let is_last = i == last;
|
let is_last = i == last;
|
||||||
|
@ -78,8 +83,7 @@ impl<'a> DescList<'a> {
|
||||||
}
|
}
|
||||||
|
|
||||||
DescList {
|
DescList {
|
||||||
// Shorten the list of descriptors to the required number.
|
list,
|
||||||
list: &mut list[0..=last],
|
|
||||||
buffers,
|
buffers,
|
||||||
next: 0,
|
next: 0,
|
||||||
}
|
}
|
||||||
|
|
|
@ -1,4 +1,5 @@
|
||||||
use core::ops::{Deref, DerefMut};
|
use core::ops::{Deref, DerefMut};
|
||||||
|
use alloc::{vec, vec::Vec};
|
||||||
use libregister::*;
|
use libregister::*;
|
||||||
use super::{Buffer, regs};
|
use super::{Buffer, regs};
|
||||||
|
|
||||||
|
@ -40,14 +41,18 @@ impl DescEntry {
|
||||||
pub const DESCS: usize = 8;
|
pub const DESCS: usize = 8;
|
||||||
|
|
||||||
#[repr(C)]
|
#[repr(C)]
|
||||||
pub struct DescList<'a> {
|
pub struct DescList {
|
||||||
list: &'a mut [DescEntry],
|
list: Vec<DescEntry>,
|
||||||
buffers: &'a mut [Buffer],
|
buffers: Vec<Buffer>,
|
||||||
next: usize,
|
next: usize,
|
||||||
}
|
}
|
||||||
|
|
||||||
impl<'a> DescList<'a> {
|
impl DescList {
|
||||||
pub fn new(list: &'a mut [DescEntry], buffers: &'a mut [Buffer]) -> Self {
|
pub fn new(size: usize) -> Self {
|
||||||
|
let mut list: Vec<_> = (0..size).map(|_| DescEntry::zeroed())
|
||||||
|
.collect();
|
||||||
|
let mut buffers = vec![Buffer::new(); size];
|
||||||
|
|
||||||
let last = list.len().min(buffers.len()) - 1;
|
let last = list.len().min(buffers.len()) - 1;
|
||||||
// Sending seems to not work properly with only one packet
|
// Sending seems to not work properly with only one packet
|
||||||
// buffer (two duplicates get send with every packet), so
|
// buffer (two duplicates get send with every packet), so
|
||||||
|
@ -73,8 +78,7 @@ impl<'a> DescList<'a> {
|
||||||
}
|
}
|
||||||
|
|
||||||
DescList {
|
DescList {
|
||||||
// Shorten the list of descriptors to the required number.
|
list,
|
||||||
list: &mut list[0..=last],
|
|
||||||
buffers,
|
buffers,
|
||||||
next: 0,
|
next: 0,
|
||||||
}
|
}
|
||||||
|
@ -142,12 +146,12 @@ impl<'a> DerefMut for PktRef<'a> {
|
||||||
}
|
}
|
||||||
|
|
||||||
/// TxToken for smoltcp support
|
/// TxToken for smoltcp support
|
||||||
pub struct Token<'a, 'tx: 'a> {
|
pub struct Token<'a> {
|
||||||
pub regs: &'a mut regs::RegisterBlock,
|
pub regs: &'a mut regs::RegisterBlock,
|
||||||
pub desc_list: &'a mut DescList<'tx>,
|
pub desc_list: &'a mut DescList,
|
||||||
}
|
}
|
||||||
|
|
||||||
impl<'a, 'tx: 'a> smoltcp::phy::TxToken for Token<'a, 'tx> {
|
impl<'a> smoltcp::phy::TxToken for Token<'a> {
|
||||||
fn consume<R, F>(self, _timestamp: smoltcp::time::Instant, len: usize, f: F) -> smoltcp::Result<R>
|
fn consume<R, F>(self, _timestamp: smoltcp::time::Instant, len: usize, f: F) -> smoltcp::Result<R>
|
||||||
where F: FnOnce(&mut [u8]) -> smoltcp::Result<R>
|
where F: FnOnce(&mut [u8]) -> smoltcp::Result<R>
|
||||||
{
|
{
|
||||||
|
|
|
@ -1,5 +1,7 @@
|
||||||
#![no_std]
|
#![no_std]
|
||||||
|
|
||||||
|
extern crate alloc;
|
||||||
|
|
||||||
/// Re-export so that dependents can always use the same version
|
/// Re-export so that dependents can always use the same version
|
||||||
pub use smoltcp;
|
pub use smoltcp;
|
||||||
|
|
||||||
|
|
Loading…
Reference in New Issue