diff --git a/kernel/driver/net/core/src/util/queue.rs b/kernel/driver/net/core/src/util/queue.rs index 8177b484..9d5c1673 100644 --- a/kernel/driver/net/core/src/util/queue.rs +++ b/kernel/driver/net/core/src/util/queue.rs @@ -158,7 +158,6 @@ impl GenericTxRing { let buffer_len = frame.len(); let index = inner.wr % self.capacity; - assert!(inner.in_flight[index].is_none()); frame.cache_flush_all(true); inner.entries[index].setup_tx(buffer_address, buffer_len, index, self.capacity)?; diff --git a/kernel/driver/net/stmmac/src/lib.rs b/kernel/driver/net/stmmac/src/lib.rs index 5a5ea7b1..8bab40e3 100644 --- a/kernel/driver/net/stmmac/src/lib.rs +++ b/kernel/driver/net/stmmac/src/lib.rs @@ -29,12 +29,13 @@ use regs::{ }, mtl::{MTLOMR, MTLRXQiOMR, MTLTXQiOMR}, }; -use ring::{RxDescriptor, RxRing, TxDescriptor, TxRing}; +use ring::{RxDescriptor, TxDescriptor}; use tock_registers::interfaces::{ReadWriteable, Readable, Writeable}; use ygg_driver_net_core::{ RxPacket, ephy::{GBESR, PhyAccess}, interface::{NetworkDevice, NetworkInterfaceType}, + util::GenericQueue, }; use yggdrasil_abi::net::{ MacAddress, @@ -48,9 +49,7 @@ pub mod ring; struct Inner { regs: IrqSafeSpinlock>, - - tx_ring: IrqSafeSpinlock, - rx_ring: IrqSafeSpinlock, + queue: GenericQueue, } struct Stmmac { @@ -105,12 +104,12 @@ impl Stmmac { pub fn start_xmit(&self, frame: DmaBuffer<[u8]>) -> Result<(), Error> { let inner = self.inner.get(); - let regs = inner.regs.lock(); + let index = inner.queue.try_push_xmit(frame)?; - let mut tx_ring = inner.tx_ring.lock(); - let index = tx_ring.push_xmit(frame)?; - let ring_pos = tx_ring - .buffer_base() + let regs = inner.regs.lock(); + let ring_pos = inner + .queue + .tx_buffer_base() .add(size_of::() * index) .try_into_u32() .unwrap(); @@ -134,17 +133,17 @@ impl Stmmac { } if events & Self::SOFTIRQ_TX_STATUS != 0 { - inner.tx_ring.lock().consume().ok(); + inner.queue.consume_tx().ok(); } if events & Self::SOFTIRQ_RX_STATUS != 0 { - let mut rx_ring = inner.rx_ring.lock(); - rx_ring - .consume(dma.as_ref(), |packet| { + inner + .queue + .consume_rx(dma.as_ref(), None, |packet, _| { let packet = RxPacket::new(packet, 0, iface); ygg_driver_net_core::receive_packet(packet).ok(); }) - .ok(); + .expect("Rx failed"); } } } @@ -230,10 +229,10 @@ impl Device for Stmmac { ); // Setup DMA Tx/Rx rings - let tx_ring = TxRing::with_capacity(dma.as_ref(), tx_ring_capacity)?; - let rx_ring = RxRing::with_capacity(dma.as_ref(), rx_ring_capacity)?; - let tx_ring_base = tx_ring.buffer_base().try_into_u32().unwrap(); - let rx_ring_base = rx_ring.buffer_base().try_into_u32().unwrap(); + let queue = + GenericQueue::with_capacity(dma.as_ref(), tx_ring_capacity, rx_ring_capacity, 4096)?; + let tx_ring_base = queue.tx_buffer_base().try_into_u32()?; + let rx_ring_base = queue.rx_buffer_base().try_into_u32()?; regs.DMA.DMAC0TXRLR.set(tx_ring_capacity as u32 - 1); regs.DMA.DMAC0TXDLAR.set(tx_ring_base); @@ -338,9 +337,7 @@ impl Device for Stmmac { self.inner.init(Inner { regs: IrqSafeSpinlock::new(regs), - - tx_ring: IrqSafeSpinlock::new(tx_ring), - rx_ring: IrqSafeSpinlock::new(rx_ring), + queue, }); let iface = diff --git a/kernel/driver/net/stmmac/src/ring.rs b/kernel/driver/net/stmmac/src/ring.rs index 3de58cee..f1421c39 100644 --- a/kernel/driver/net/stmmac/src/ring.rs +++ b/kernel/driver/net/stmmac/src/ring.rs @@ -1,26 +1,5 @@ -use core::mem::{self, MaybeUninit}; - -use alloc::vec::Vec; -use device_api::dma::DmaAllocator; -use libk::{ - dma::{BusAddress, DmaBuffer}, - error::Error, -}; - -pub struct TxRing { - entries: DmaBuffer<[TxDescriptor]>, - buffers: Vec>>, - - wr: usize, - rd: usize, -} - -pub struct RxRing { - entries: DmaBuffer<[RxDescriptor]>, - buffers: Vec]>>, - - rd: usize, -} +use libk::{dma::BusAddress, error::Error}; +use ygg_driver_net_core::util::{GenericRxDescriptor, GenericTxDescriptor}; #[derive(Clone, Copy, Debug)] #[repr(C)] @@ -40,215 +19,79 @@ pub struct RxDescriptor { rdes3: u32, } -impl TxRing { - pub fn with_capacity(dma: &dyn DmaAllocator, capacity: usize) -> Result { - let entries = DmaBuffer::new_slice(dma, TxDescriptor::empty(), capacity)?; - let buffers = (0..capacity).map(|_| None).collect(); - Ok(Self { - entries, - buffers, - - wr: 0, - rd: 0, - }) - } - - pub fn buffer_base(&self) -> BusAddress { - self.entries.bus_address() - } - - pub fn capacity(&self) -> usize { - self.entries.len() - } - - pub fn can_xmit(&self) -> bool { - self.wr.wrapping_add(1) != self.rd - } - - pub fn outstanding_tx(&self) -> bool { - self.wr != self.rd - } - - pub fn push_xmit(&mut self, frame: DmaBuffer<[u8]>) -> Result { - if !self.can_xmit() { - return Err(Error::WouldBlock); - } - - let address = frame.bus_address(); - let frame_len = frame.len(); - - let capacity = self.entries.len(); - let index = self.wr % capacity; - assert!(self.buffers[index].is_none()); - - frame.cache_flush_all(true); - self.entries[index].setup_tx(address, frame_len, true)?; - self.entries.cache_flush_element(index, true); - - self.buffers[index] = Some(frame); - self.wr = self.wr.wrapping_add(1); - - Ok(self.wr % self.capacity()) - } - - pub fn consume(&mut self) -> Result { - let mut count = 0; - - loop { - let index = self.rd % self.entries.len(); - let entry = &self.entries[index]; - - if self.rd == self.wr { - break; - } - - if let Some(status) = entry.tx_status() { - if status != 0 { - log::warn!("tx_ring[{index}] error: {status:#x}"); - } - let _ = self.buffers[index].take().unwrap(); - self.rd = self.rd.wrapping_add(1); - count += 1; - } else { - break; - } - } - - Ok(count) - } -} - impl TxDescriptor { const TDES3_OWN: u32 = 1 << 31; const TDES3_FD: u32 = 1 << 29; const TDES3_LD: u32 = 1 << 28; const TDES2_IOC: u32 = 1 << 31; +} - pub const fn empty() -> Self { - Self { - tdes0: 0, - tdes1: 0, - tdes2: 0, - tdes3: 0, - } - } +impl GenericTxDescriptor for TxDescriptor { + const EMPTY: Self = Self { + tdes0: 0, + tdes1: 0, + tdes2: 0, + tdes3: 0, + }; - pub fn tx_status(&self) -> Option { + fn consume(&mut self) -> Option> { if self.tdes3 & Self::TDES3_OWN == 0 { - Some(self.tdes3 & !(0xFFFF << 16)) + // Some(self.tdes3 & !(0xFFFF << 16)) + Some(Ok(())) } else { None } } - pub fn setup_tx( + fn setup_tx( &mut self, - frame: BusAddress, - frame_len: usize, - ioc: bool, + buffer_address: BusAddress, + size: usize, + _index: usize, + _capacity: usize, ) -> Result<(), Error> { - let tdes0 = frame.try_into_u32().map_err(|_| Error::InvalidArgument)?; - if frame_len & !0x3FFF != 0 { + if size & !0x3FFF != 0 { return Err(Error::InvalidArgument); } - let mut tdes2 = frame_len as u32; - if ioc { - tdes2 |= Self::TDES2_IOC; - } - let tdes3 = Self::TDES3_OWN | Self::TDES3_FD | Self::TDES3_LD; - - self.tdes0 = tdes0; + // TODO ioc only on quarter buffer + self.tdes0 = buffer_address.try_into_u32()?; self.tdes1 = 0; - self.tdes2 = tdes2; - self.tdes3 = tdes3; + self.tdes2 = size as u32 | Self::TDES2_IOC; + self.tdes3 = Self::TDES3_OWN | Self::TDES3_LD | Self::TDES3_FD; Ok(()) } } -impl RxRing { - pub fn with_capacity(dma: &dyn DmaAllocator, capacity: usize) -> Result { - let mut entries = DmaBuffer::new_slice(dma, RxDescriptor::empty(), capacity)?; - let buffers = (0..capacity) - .map(|_| DmaBuffer::new_uninit_slice(dma, 4096)) - .collect::, _>>()?; - for i in 0..capacity { - entries[i].setup_rx(buffers[i].bus_address(), true)?; - } - Ok(Self { - buffers, - entries, - - rd: 0, - }) - } - - pub fn buffer_base(&self) -> BusAddress { - self.entries.bus_address() - } - - pub fn consume)>( - &mut self, - dma: &dyn DmaAllocator, - packet_handler: F, - ) -> Result { - let mut count = 0; - - loop { - let index = self.rd % self.entries.len(); - let entry = &mut self.entries[index]; - - if entry.rx_completed().is_some() { - // Grab the current buffer (the one just written to by the DMA), replace it - // with the newly allocated one, and mark the descriptor as DMA-owned again - let new_buffer = DmaBuffer::new_uninit_slice(dma, 4096)?; - let new_buffer_address = new_buffer.bus_address(); - let buffer = mem::replace(&mut self.buffers[index], new_buffer); - let buffer = unsafe { DmaBuffer::assume_init_slice(buffer) }; - // TODO packet size hint - packet_handler(buffer); - entry.setup_rx(new_buffer_address, true)?; - self.rd = self.rd.wrapping_add(1); - count += 1; - } else { - break; - } - } - - Ok(count) - } -} - impl RxDescriptor { const RDES3_OWN: u32 = 1 << 31; const RDES3_IOC: u32 = 1 << 30; const RDES3_BUF1V: u32 = 1 << 24; +} - pub const fn empty() -> Self { - Self { - rdes0: 0, - rdes1: 0, - rdes2: 0, - rdes3: 0, - } - } - - pub fn rx_completed(&self) -> Option { +impl GenericRxDescriptor for RxDescriptor { + fn consume(&mut self) -> Option> { if self.rdes3 & Self::RDES3_OWN == 0 { - Some((self.rdes3 & 0x7FFF) as usize) + Some(Ok((self.rdes3 & 0x7FFF) as usize)) } else { None } } - pub fn setup_rx(&mut self, buffer: BusAddress, ioc: bool) -> Result<(), Error> { - self.rdes0 = buffer.try_into_u32().map_err(|_| Error::InvalidArgument)?; - self.rdes1 = 0; - self.rdes2 = 0; - self.rdes3 = Self::RDES3_BUF1V; - if ioc { - self.rdes3 |= Self::RDES3_IOC; - } - self.rdes3 |= Self::RDES3_OWN; - Ok(()) + fn setup_rx( + buffer_address: BusAddress, + _buffer_size: usize, + _last: bool, + ) -> Result { + let rdes0 = buffer_address.try_into_u32()?; + let rdes1 = 0; + let rdes2 = 0; + // TODO ioc + let rdes3 = Self::RDES3_BUF1V | Self::RDES3_IOC | Self::RDES3_OWN; + Ok(Self { + rdes0, + rdes1, + rdes2, + rdes3, + }) } }