diff --git a/kernel/include/kernel/Networking/E1000/E1000.h b/kernel/include/kernel/Networking/E1000/E1000.h index 4e131b1a..c14f6462 100644 --- a/kernel/include/kernel/Networking/E1000/E1000.h +++ b/kernel/include/kernel/Networking/E1000/E1000.h @@ -74,8 +74,8 @@ namespace Kernel BAN::UniqPtr m_rx_descriptor_region; BAN::UniqPtr m_tx_descriptor_region; - BAN::Atomic m_tx_head1 { 0 }; - BAN::Atomic m_tx_head2 { 0 }; + BAN::Atomic m_tx_head { 0 }; + BAN::Atomic m_tx_commit { 0 }; SpinLock m_rx_lock; ThreadBlocker m_rx_blocker; diff --git a/kernel/kernel/Networking/E1000/E1000.cpp b/kernel/kernel/Networking/E1000/E1000.cpp index d11441e7..fac13f61 100644 --- a/kernel/kernel/Networking/E1000/E1000.cpp +++ b/kernel/kernel/Networking/E1000/E1000.cpp @@ -281,7 +281,11 @@ namespace Kernel BAN::ErrorOr E1000::send_bytes(BAN::MACAddress destination, EtherType protocol, BAN::Span payload) { - const uint32_t tx_current = m_tx_head1.fetch_add(1) % E1000_TX_DESCRIPTOR_COUNT; + const auto interrupt_state = Processor::get_interrupt_state(); + Processor::set_interrupt_state(InterruptState::Disabled); + + const uint32_t tx_current_nowrap = m_tx_head.fetch_add(1); + const uint32_t tx_current = tx_current_nowrap % E1000_TX_DESCRIPTOR_COUNT; auto& descriptor = reinterpret_cast(m_tx_descriptor_region->vaddr())[tx_current]; while (descriptor.status == 0) @@ -306,8 +310,12 @@ namespace Kernel descriptor.status = 0; descriptor.cmd = CMD_EOP | CMD_IFCS | CMD_RS; - if (tx_current == m_tx_head2.fetch_add(1) % E1000_TX_DESCRIPTOR_COUNT) - write32(REG_TDT, (tx_current + 1) % E1000_TX_DESCRIPTOR_COUNT); + while (tx_current_nowrap != m_tx_commit.load()) + Processor::pause(); + write32(REG_TDT, (tx_current + 1) % E1000_TX_DESCRIPTOR_COUNT); + m_tx_commit.add_fetch(1); + + Processor::set_interrupt_state(interrupt_state); dprintln_if(DEBUG_E1000, "sent {} bytes", packet_size);