[PATCH iwl-next v2 2/4] ixgbe: add ixgbe_container_is_rx() helper and refine RX adaptive ITR
From: Aleksandr Loktionov <hidden>
Date: 2026-09-18 13:33:25
Also in:
intel-wired-lan
Subsystem:
intel ethernet drivers, networking drivers, the rest · Maintainers:
Tony Nguyen, Przemek Kitszel, Andrew Lunn, "David S. Miller", Eric Dumazet, Jakub Kicinski, Paolo Abeni, Linus Torvalds
From: Alexander Duyck <redacted> Add an ixgbe_container_is_rx() helper to cleanly distinguish RX from TX ring containers inside ixgbe_update_itr(). Refine the RX-specific latency-detection path: - Replace the shared "packets < 4 or bytes < 9000" threshold with an RX-specific check of "1..23 packets and bytes < 12112". When that condition holds, target 8x the observed byte count in the next interval by computing avg_wire_size = (bytes + packets * 24) * 2, clamped to [2560, 12800], and jumping directly to the speed-based ITR calculation. This provides finer-grained control over low-rate RX latency workloads without affecting TX. - Remove the separate "no packets" special-case block. When packets is 0 it falls into the "< 48" branch. The mode-tracking logic in that branch is extended: fewer than 8 packets forces latency mode; 8..47 packets preserves the current mode. This replaces the old unconditional "add LATENCY flag from ring_container->itr" carried over from the removed block. - Remove the adjust_by_size label and the associated "halve avg_wire_size in latency mode" step. The Rx latency path now pre-calculates avg_wire_size independently and the bulk path no longer needs the halving to compensate for incorrect thresholds. Rename the jump target to adjust_for_speed to reflect its purpose. Signed-off-by: Alexander Duyck <redacted> Signed-off-by: Aleksandr Loktionov <redacted> Reviewed-by: Simon Horman <horms@kernel.org> --- drivers/net/ethernet/intel/ixgbe/ixgbe_main.c | 67 ++++++++++--------- 1 file changed, 35 insertions(+), 32 deletions(-)
diff --git a/drivers/net/ethernet/intel/ixgbe/ixgbe_main.c b/drivers/net/ethernet/intel/ixgbe/ixgbe_main.c
index f918564..ddc18e1 100644
--- a/drivers/net/ethernet/intel/ixgbe/ixgbe_main.c
+++ b/drivers/net/ethernet/intel/ixgbe/ixgbe_main.c@@ -2711,6 +2711,12 @@ static void ixgbe_configure_msix(struct ixgbe_adapter *adapter) IXGBE_WRITE_REG(&adapter->hw, IXGBE_EIAC, mask); } +static bool ixgbe_container_is_rx(struct ixgbe_q_vector *q_vector, + struct ixgbe_ring_container *rc) +{ + return &q_vector->rx == rc; +} + /** * ixgbe_update_itr - update the dynamic ITR value based on statistics * @q_vector: structure containing interrupt and ring information
@@ -2747,35 +2753,24 @@ static void ixgbe_update_itr(struct ixgbe_q_vector *q_vector, goto clear_counts; packets = ring_container->total_packets; - - /* We have no packets to actually measure against. This means - * either one of the other queues on this vector is active or - * we are a Tx queue doing TSO with too high of an interrupt rate. - * - * When this occurs just tick up our delay by the minimum value - * and hope that this extra delay will prevent us from being called - * without any work on our queue. - */ - if (!packets) { - itr = (q_vector->itr >> 2) + IXGBE_ITR_ADAPTIVE_MIN_INC; - if (itr > IXGBE_ITR_ADAPTIVE_MAX_USECS) - itr = IXGBE_ITR_ADAPTIVE_MAX_USECS; - itr += ring_container->itr & IXGBE_ITR_ADAPTIVE_LATENCY; - goto clear_counts; - } - bytes = ring_container->total_bytes; - /* If packets are less than 4 or bytes are less than 9000 assume - * insufficient data to use bulk rate limiting approach. We are - * likely latency driven. - */ - if (packets < 4 && bytes < 9000) { - itr = IXGBE_ITR_ADAPTIVE_LATENCY; - goto adjust_by_size; + if (ixgbe_container_is_rx(q_vector, ring_container)) { + /* If Rx and there are 1 to 23 packets and bytes are less than + * 12112 assume insufficient data to use bulk rate limiting + * approach. Instead we will focus on simply trying to target + * receiving 8 times as much data in the next interrupt. + */ + if (packets && packets < 24 && bytes < 12112) { + itr = IXGBE_ITR_ADAPTIVE_LATENCY; + avg_wire_size = (bytes + packets * 24) * 2; + avg_wire_size = clamp_t(unsigned int, + avg_wire_size, 2560, 12800); + goto adjust_for_speed; + } } - /* Between 4 and 48 we can assume that our current interrupt delay + /* Less than 48 packets we can assume that our current interrupt delay * is only slightly too low. As such we should increase it by a small * fixed amount. */
@@ -2783,6 +2778,20 @@ static void ixgbe_update_itr(struct ixgbe_q_vector *q_vector, itr = (q_vector->itr >> 2) + IXGBE_ITR_ADAPTIVE_MIN_INC; if (itr > IXGBE_ITR_ADAPTIVE_MAX_USECS) itr = IXGBE_ITR_ADAPTIVE_MAX_USECS; + + /* If sample size is 0 - 7 we should probably switch + * to latency mode instead of trying to control + * things as though we are in bulk. + * + * Otherwise if the number of packets is less than 48 + * we should maintain whatever mode we are currently + * in. The range between 8 and 48 is the cross-over + * point between latency and bulk traffic. + */ + if (packets < 8) + itr += IXGBE_ITR_ADAPTIVE_LATENCY; + else + itr += ring_container->itr & IXGBE_ITR_ADAPTIVE_LATENCY; goto clear_counts; }
@@ -2813,7 +2822,6 @@ static void ixgbe_update_itr(struct ixgbe_q_vector *q_vector, */ itr = IXGBE_ITR_ADAPTIVE_BULK; -adjust_by_size: /* If packet counts are 256 or greater we can assume we have a gross * overestimation of what the rate should be. Instead of trying to fine * tune it just use the formula below to try and dial in an exact value
@@ -2856,12 +2864,7 @@ static void ixgbe_update_itr(struct ixgbe_q_vector *q_vector, avg_wire_size = 32256; } - /* If we are in low latency mode half our delay which doubles the rate - * to somewhere between 100K to 16K ints/sec - */ - if (itr & IXGBE_ITR_ADAPTIVE_LATENCY) - avg_wire_size >>= 1; - +adjust_for_speed: /* Resultant value is 256 times larger than it needs to be. This * gives us room to adjust the value as needed to either increase * or decrease the value based on link speeds of 10G, 2.5G, 1G, etc.
--
2.52.0