]> git.ipfire.org Git - thirdparty/kernel/linux.git/commitdiff
igc: Fix trigger of incorrect irq in igc_xsk_wakeup function
authorVivek Behera <vivek.behera@siemens.com>
Tue, 20 Jan 2026 07:52:16 +0000 (08:52 +0100)
committerTony Nguyen <anthony.l.nguyen@intel.com>
Tue, 3 Mar 2026 21:06:05 +0000 (13:06 -0800)
This patch addresses the issue where the igc_xsk_wakeup function
was triggering an incorrect IRQ for tx-0 when the i226 is configured
with only 2 combined queues or in an environment with 2 active CPU cores.
This prevented XDP Zero-copy send functionality in such split IRQ
configurations.

The fix implements the correct logic for extracting q_vectors saved
during rx and tx ring allocation and utilizes flags provided by the
ndo_xsk_wakeup API to trigger the appropriate IRQ.

Fixes: fc9df2a0b520 ("igc: Enable RX via AF_XDP zero-copy")
Fixes: 15fd021bc427 ("igc: Add Tx hardware timestamp request for AF_XDP zero-copy packet")
Signed-off-by: Vivek Behera <vivek.behera@siemens.com>
Reviewed-by: Jacob Keller <jacob.keller@intel.com>
Reviewed-by: Aleksandr loktinov <aleksandr.loktionov@intel.com>
Reviewed-by: Piotr Kwapulinski <piotr.kwapulinski@intel.com>
Reviewed-by: Song Yoong Siang <yoong.siang.song@intel.com>
Tested-by: Avigail Dahan <avigailx.dahan@intel.com>
Signed-off-by: Tony Nguyen <anthony.l.nguyen@intel.com>
drivers/net/ethernet/intel/igc/igc_main.c
drivers/net/ethernet/intel/igc/igc_ptp.c

index 27e5c21091386b3c8b51b82eb066ebd0c6e75882..b2e8d0c0f827f19a960b2204a1ed14a46af7e509 100644 (file)
@@ -6906,28 +6906,29 @@ static int igc_xdp_xmit(struct net_device *dev, int num_frames,
        return nxmit;
 }
 
-static void igc_trigger_rxtxq_interrupt(struct igc_adapter *adapter,
-                                       struct igc_q_vector *q_vector)
+static u32 igc_sw_irq_prep(struct igc_q_vector *q_vector)
 {
-       struct igc_hw *hw = &adapter->hw;
        u32 eics = 0;
 
-       eics |= q_vector->eims_value;
-       wr32(IGC_EICS, eics);
+       if (!napi_if_scheduled_mark_missed(&q_vector->napi))
+               eics = q_vector->eims_value;
+
+       return eics;
 }
 
 int igc_xsk_wakeup(struct net_device *dev, u32 queue_id, u32 flags)
 {
        struct igc_adapter *adapter = netdev_priv(dev);
-       struct igc_q_vector *q_vector;
+       struct igc_hw *hw = &adapter->hw;
        struct igc_ring *ring;
+       u32 eics = 0;
 
        if (test_bit(__IGC_DOWN, &adapter->state))
                return -ENETDOWN;
 
        if (!igc_xdp_is_enabled(adapter))
                return -ENXIO;
-
+       /* Check if queue_id is valid. Tx and Rx queue numbers are always same */
        if (queue_id >= adapter->num_rx_queues)
                return -EINVAL;
 
@@ -6936,9 +6937,22 @@ int igc_xsk_wakeup(struct net_device *dev, u32 queue_id, u32 flags)
        if (!ring->xsk_pool)
                return -ENXIO;
 
-       q_vector = adapter->q_vector[queue_id];
-       if (!napi_if_scheduled_mark_missed(&q_vector->napi))
-               igc_trigger_rxtxq_interrupt(adapter, q_vector);
+       if (flags & XDP_WAKEUP_RX)
+               eics |= igc_sw_irq_prep(ring->q_vector);
+
+       if (flags & XDP_WAKEUP_TX) {
+               /* If IGC_FLAG_QUEUE_PAIRS is active, the q_vector
+                * and NAPI is shared between RX and TX.
+                * If NAPI is already running it would be marked as missed
+                * from the RX path, making this TX call a NOP
+                */
+               ring = adapter->tx_ring[queue_id];
+               eics |= igc_sw_irq_prep(ring->q_vector);
+       }
+
+       if (eics)
+               /* Cause software interrupt */
+               wr32(IGC_EICS, eics);
 
        return 0;
 }
index 7aae83c108fd7611b00bf075592f93a902b83422..44ee1938676612c3a25f10a6661611aaa2c538bc 100644 (file)
@@ -550,7 +550,8 @@ static void igc_ptp_free_tx_buffer(struct igc_adapter *adapter,
                tstamp->buffer_type = 0;
 
                /* Trigger txrx interrupt for transmit completion */
-               igc_xsk_wakeup(adapter->netdev, tstamp->xsk_queue_index, 0);
+               igc_xsk_wakeup(adapter->netdev, tstamp->xsk_queue_index,
+                              XDP_WAKEUP_TX);
 
                return;
        }