mirror of
https://github.com/LadybirdBrowser/ladybird.git
synced 2025-01-07 19:57:45 +03:00
Kernel: Limit IRQ rate within E1000 network adapter
This is not a complete fix, since spurious IRQs under heavy loads can still occur. However, this fix limits the amount of spurious IRQs. It is encouraged to provide a better fix in the future, probably something that takes into account handling of PCI level-triggered interrupts.
This commit is contained in:
parent
dbc536e917
commit
06e7fc9dee
Notes:
sideshowbarker
2024-07-19 08:09:13 +09:00
Author: https://github.com/supercomputer7 Commit: https://github.com/SerenityOS/serenity/commit/06e7fc9deea Pull-request: https://github.com/SerenityOS/serenity/pull/1361 Reviewed-by: https://github.com/awesomekling
@ -36,7 +36,10 @@ namespace Kernel {
|
||||
#define REG_STATUS 0x0008
|
||||
#define REG_EEPROM 0x0014
|
||||
#define REG_CTRL_EXT 0x0018
|
||||
#define REG_IMASK 0x00D0
|
||||
#define REG_INTERRUPT_CAUSE_READ 0x00C0
|
||||
#define REG_INTERRUPT_RATE 0x00C4
|
||||
#define REG_INTERRUPT_MASK_SET 0x00D0
|
||||
#define REG_INTERRUPT_MASK_CLEAR 0x00D8
|
||||
#define REG_RCTRL 0x0100
|
||||
#define REG_RXDESCLO 0x2800
|
||||
#define REG_RXDESCHI 0x2804
|
||||
@ -121,6 +124,21 @@ namespace Kernel {
|
||||
#define STATUS_SPEED_1000MB1 0x80
|
||||
#define STATUS_SPEED_1000MB2 0xC0
|
||||
|
||||
// Interrupt Masks
|
||||
|
||||
#define INTERRUPT_TXDW (1 << 0)
|
||||
#define INTERRUPT_TXQE (1 << 1)
|
||||
#define INTERRUPT_LSC (1 << 2)
|
||||
#define INTERRUPT_RXSEQ (1 << 3)
|
||||
#define INTERRUPT_RXDMT0 (1 << 4)
|
||||
#define INTERRUPT_RXO (1 << 6)
|
||||
#define INTERRUPT_RXT0 (1 << 7)
|
||||
#define INTERRUPT_MDAC (1 << 9)
|
||||
#define INTERRUPT_RXCFG (1 << 10)
|
||||
#define INTERRUPT_PHYINT (1 << 12)
|
||||
#define INTERRUPT_TXD_LOW (1 << 15)
|
||||
#define INTERRUPT_SRPD (1 << 16)
|
||||
|
||||
void E1000NetworkAdapter::detect(const PCI::Address& address)
|
||||
{
|
||||
if (address.is_null())
|
||||
@ -163,12 +181,14 @@ E1000NetworkAdapter::E1000NetworkAdapter(PCI::Address address, u8 irq)
|
||||
u32 flags = in32(REG_CTRL);
|
||||
out32(REG_CTRL, flags | ECTRL_SLU);
|
||||
|
||||
out16(REG_INTERRUPT_RATE, 6000); // Interrupt rate of 1.536 milliseconds
|
||||
|
||||
initialize_rx_descriptors();
|
||||
initialize_tx_descriptors();
|
||||
|
||||
out32(REG_IMASK, 0x1f6dc);
|
||||
out32(REG_IMASK, 0xff & ~4);
|
||||
in32(0xc0);
|
||||
out32(REG_INTERRUPT_MASK_SET, 0x1f6dc);
|
||||
out32(REG_INTERRUPT_MASK_SET, INTERRUPT_LSC | INTERRUPT_RXT0);
|
||||
in32(REG_INTERRUPT_CAUSE_READ);
|
||||
|
||||
enable_irq();
|
||||
}
|
||||
@ -179,21 +199,23 @@ E1000NetworkAdapter::~E1000NetworkAdapter()
|
||||
|
||||
void E1000NetworkAdapter::handle_irq(const RegisterState&)
|
||||
{
|
||||
out32(REG_IMASK, 0x1);
|
||||
out32(REG_INTERRUPT_MASK_CLEAR, 0xffffffff);
|
||||
|
||||
u32 status = in32(0xc0);
|
||||
u32 status = in32(REG_INTERRUPT_CAUSE_READ);
|
||||
if (status & 4) {
|
||||
u32 flags = in32(REG_CTRL);
|
||||
out32(REG_CTRL, flags | ECTRL_SLU);
|
||||
}
|
||||
if (status & 0x10) {
|
||||
// Threshold OK?
|
||||
}
|
||||
if (status & 0x80) {
|
||||
receive();
|
||||
}
|
||||
if (status & 0x10) {
|
||||
// Threshold OK?
|
||||
}
|
||||
|
||||
m_wait_queue.wake_all();
|
||||
|
||||
out32(REG_INTERRUPT_MASK_SET, INTERRUPT_LSC | INTERRUPT_RXT0 | INTERRUPT_RXO);
|
||||
}
|
||||
|
||||
void E1000NetworkAdapter::detect_eeprom()
|
||||
|
Loading…
Reference in New Issue
Block a user