From 0046c76e436889ed212cbcc9bbbb5457b7f0c873 Mon Sep 17 00:00:00 2001 From: Admin Pupkin Date: Wed, 20 May 2026 22:15:03 +0300 Subject: [PATCH] base: Add e1000d interrupt throttling rate (ITR) coalescing (P53) Re-implements work that was lost due to ephemeral source/ subdirectory. ITR dynamically adjusts interrupt coalescing based on packet rate. - Add ITR register (0xC4) and set_itr() to device.rs - Add itr.rs tracker with hysteresis-based rate adaptation - Wire tracker into IRQ handler in main.rs - Document in AGENTS.md: source/ is ALWAYS rewritten --- AGENTS.md | 8 +- .../base/P53-e1000d-itr-coalescing.patch | 118 ++++++++++++++++++ .../core/base/P53-e1000d-itr-coalescing.patch | 1 + recipes/core/base/recipe.toml | 2 + 4 files changed, 126 insertions(+), 3 deletions(-) create mode 100644 local/patches/base/P53-e1000d-itr-coalescing.patch create mode 120000 recipes/core/base/P53-e1000d-itr-coalescing.patch diff --git a/AGENTS.md b/AGENTS.md index 6085771c11..ac1e2fe1c6 100644 --- a/AGENTS.md +++ b/AGENTS.md @@ -21,9 +21,11 @@ All recipe sources are pinned and archived in `sources/redbear-0.1.0/`. ## BUILD SYSTEM DURABILITY — THE CARDINAL RULE -**Never edit files under `recipes/*/source/` directly. Those trees are ephemeral — they are -destroyed and regenerated on every `repo fetch`, `repo cook`, `make clean`, and -`make distclean`. Any edit made there will be silently lost on the next build.** +**THE `recipes/*/source/` DIRECTORY WILL ALWAYS BE REWRITTEN. DO NOT EVER USE IT FOR ANY +WORK THAT YOU INTEND TO KEEP. THOSE TREES ARE EPHEMERAL — THEY ARE DESTROYED AND REGENERATED +ON EVERY `repo fetch`, `repo cook`, `make clean`, AND `make distclean`. ANY EDIT MADE THERE +WILL BE SILENTLY LOST ON THE NEXT BUILD. COMMITTING TO A SUBMODULE INSIDE `source/` DOES NOT +PROTECT YOUR WORK — THE ENTIRE DIRECTORY IS DELETED AND RE-CLONED/RE-EXTRACTED FROM SCRATCH.** This is the #1 mistake AI agents and new contributors make. It has caused repeated work loss in this project. The rule is: diff --git a/local/patches/base/P53-e1000d-itr-coalescing.patch b/local/patches/base/P53-e1000d-itr-coalescing.patch new file mode 100644 index 0000000000..2a5cd61511 --- /dev/null +++ b/local/patches/base/P53-e1000d-itr-coalescing.patch @@ -0,0 +1,118 @@ +diff --git a/drivers/net/e1000d/src/device.rs b/drivers/net/e1000d/src/device.rs +index 4c518f30..7ba100dd 100644 +--- a/drivers/net/e1000d/src/device.rs ++++ b/drivers/net/e1000d/src/device.rs +@@ -26,0 +27 @@ const ICR: u32 = 0xC0; ++const ITR: u32 = 0xC4; +@@ -241,0 +243,6 @@ impl Intel8254x { ++ /// Set the Interrupt Throttling Rate (ITR) register. ++ /// `interval` is in 256-ns increments. 0 disables throttling. ++ pub unsafe fn set_itr(&self, interval: u16) { ++ self.write_reg(ITR, interval as u32); ++ } ++ +diff --git a/drivers/net/e1000d/src/itr.rs b/drivers/net/e1000d/src/itr.rs +new file mode 100644 +index 00000000..aa85a6f2 +--- /dev/null ++++ b/drivers/net/e1000d/src/itr.rs +@@ -0,0 +1,81 @@ ++/// Interrupt Throttling Rate (ITR) tracker for e1000d. ++/// ++/// Dynamically adjusts the interrupt coalescing interval based on packet rate ++/// to balance latency and CPU overhead. ++#[derive(Debug)] ++pub struct ItrTracker { ++ last_irq_count: u64, ++ current_itr: u16, ++ consecutive_low: u32, ++ consecutive_high: u32, ++} ++ ++impl ItrTracker { ++ /// Target ~8000 interrupts/sec max for low latency. ++ const LOW_LATENCY_THRESHOLD: u64 = 8000; ++ /// Target ~2000 interrupts/sec min for CPU efficiency. ++ const HIGH_THROUGHPUT_THRESHOLD: u64 = 2000; ++ /// Minimum ITR interval in 256-ns units (~50 µs). ++ const MIN_ITR: u16 = 200; ++ /// Default ITR interval in 256-ns units (~256 µs). ++ const DEFAULT_ITR: u16 = 1000; ++ /// Maximum ITR interval in 256-ns units (~2 ms). ++ const MAX_ITR: u16 = 8000; ++ /// Number of consecutive measurements before adjusting. ++ const HYSTERESIS: u32 = 3; ++ ++ pub fn new() -> Self { ++ Self { ++ last_irq_count: 0, ++ current_itr: Self::DEFAULT_ITR, ++ consecutive_low: 0, ++ consecutive_high: 0, ++ } ++ } ++ ++ /// Call once per IRQ to update the tracker and return the new ITR value. ++ /// Returns `None` if no change is needed. ++ pub fn update(&mut self, irq_count: u64) -> Option { ++ let delta = irq_count.saturating_sub(self.last_irq_count); ++ self.last_irq_count = irq_count; ++ ++ if delta > Self::LOW_LATENCY_THRESHOLD { ++ self.consecutive_high += 1; ++ self.consecutive_low = 0; ++ if self.consecutive_high >= Self::HYSTERESIS { ++ self.consecutive_high = 0; ++ let new_itr = self.current_itr.saturating_mul(2).min(Self::MAX_ITR); ++ if new_itr != self.current_itr { ++ self.current_itr = new_itr; ++ return Some(self.current_itr); ++ } ++ } ++ } else if delta < Self::HIGH_THROUGHPUT_THRESHOLD { ++ self.consecutive_low += 1; ++ self.consecutive_high = 0; ++ if self.consecutive_low >= Self::HYSTERESIS { ++ self.consecutive_low = 0; ++ let new_itr = self.current_itr.saturating_div(2).max(Self::MIN_ITR); ++ if new_itr != self.current_itr { ++ self.current_itr = new_itr; ++ return Some(self.current_itr); ++ } ++ } ++ } else { ++ self.consecutive_low = 0; ++ self.consecutive_high = 0; ++ } ++ ++ None ++ } ++ ++ pub fn current_itr(&self) -> u16 { ++ self.current_itr ++ } ++} ++ ++impl Default for ItrTracker { ++ fn default() -> Self { ++ Self::new() ++ } ++} +diff --git a/drivers/net/e1000d/src/main.rs b/drivers/net/e1000d/src/main.rs +index 373ea9b3..1a4b0667 100644 +--- a/drivers/net/e1000d/src/main.rs ++++ b/drivers/net/e1000d/src/main.rs +@@ -8,0 +9 @@ pub mod device; ++pub mod itr; +@@ -46,0 +48,2 @@ fn daemon(daemon: daemon::Daemon, mut pcid_handle: PciFunctionHandle) -> ! { ++ let mut itr_tracker = itr::ItrTracker::new(); ++ +@@ -74,0 +78 @@ fn daemon(daemon: daemon::Daemon, mut pcid_handle: PciFunctionHandle) -> ! { ++ let mut irq_count: u64 = 0; +@@ -77,0 +82 @@ fn daemon(daemon: daemon::Daemon, mut pcid_handle: PciFunctionHandle) -> ! { ++ irq_count += 1; +@@ -82,0 +88,4 @@ fn daemon(daemon: daemon::Daemon, mut pcid_handle: PciFunctionHandle) -> ! { ++ if let Some(new_itr) = itr_tracker.update(irq_count) { ++ unsafe { scheme.adapter().set_itr(new_itr) }; ++ } ++ diff --git a/recipes/core/base/P53-e1000d-itr-coalescing.patch b/recipes/core/base/P53-e1000d-itr-coalescing.patch new file mode 120000 index 0000000000..66d44eb4a8 --- /dev/null +++ b/recipes/core/base/P53-e1000d-itr-coalescing.patch @@ -0,0 +1 @@ +../../../local/patches/base/P53-e1000d-itr-coalescing.patch \ No newline at end of file diff --git a/recipes/core/base/recipe.toml b/recipes/core/base/recipe.toml index 6183ef8c58..b0bc668f23 100644 --- a/recipes/core/base/recipe.toml +++ b/recipes/core/base/recipe.toml @@ -105,6 +105,8 @@ patches = [ "P51-logd-rotation.patch", # P52: Add ACPI C-state discovery and thermal-based C-state policy "P52-acpid-cstates.patch", + # P53: Add e1000d interrupt throttling rate (ITR) coalescing + "P53-e1000d-itr-coalescing.patch", ] [package]