On Saturday, January 17, 2026 11:08 PM, Vivek Behera <[email protected]> wrote: >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 <[email protected]> >Reviewed-by: Jacob Keller <[email protected]> >Reviewed-by: Aleksandr loktinov <[email protected]> >Reviewed-by: Piotr Kwapulinski <[email protected]> >--- >v1: https://lore.kernel.org/intel-wired- >lan/[email protected]. >PROD.OUTLOOK.COM/ >v2: https://lore.kernel.org/intel-wired- >lan/[email protected]. >PROD.OUTLOOK.COM/ >v3: https://lore.kernel.org/intel-wired- >lan/[email protected]. >prod.outlook.com/ >v4: https://lore.kernel.org/intel-wired- >lan/[email protected]. >PROD.OUTLOOK.COM/ >v5: https://lore.kernel.org/intel-wired- >lan/[email protected]. >PROD.OUTLOOK.COM/ >v6: https://lore.kernel.org/intel-wired-lan/20251211173916.23951-1- >[email protected]/ >v7: https://lore.kernel.org/intel-wired-lan/20251212163208.137164-1- >[email protected]/ >v8: https://lore.kernel.org/intel-wired-lan/20251215122052.412327-1- >[email protected]/ >v9: https://lore.kernel.org/intel-wired-lan/20251220110009.137245-1- >[email protected]/ > >changelog: >v1 >- Inital description of the Bug and steps to reproduce with RTC Testbench >- Test results after applying the patch >v1 -> v2 >- Handling of RX and TX Wakeup in igc_xsk_wakeup for a split IRQ configuration >- Removal of igc_trigger_rxtxq_interrupt (now redundant) >- Added flag to igc_xsk_wakeup function call in igc_ptp_free_tx_buffer >v2 -> v3 >- Added 'Fixes:' tags for the relevant commits. >- Added reviewer >v3 -> v4 >- Added reviewer >v4 -> v5 >- Updated comment style from multi-star to standard linux convention >v5 -> v6 >- Resolve formatting issues highlighted by reviewers >- Try to include version histroy as defined in netdev guidelines >- Included review suggestions from Przemyslaw >- Added reviewers >v6 -> v7 >- Included review suggestions from Przemyslaw missed in v6 >v7 -> v8 >- Modified sequence to complete all error checks for rx and tx > before updating napi states and triggering irq >v8 -> v9 >- Included review feedback and suggestions from Tony and Siang >v9 -> v10 >- Introduced a simplified logic for sequential check for RX and TX >--- > drivers/net/ethernet/intel/igc/igc_main.c | 32 ++++++++++++++++------- > drivers/net/ethernet/intel/igc/igc_ptp.c | 3 ++- > 2 files changed, 24 insertions(+), 11 deletions(-) > >diff --git a/drivers/net/ethernet/intel/igc/igc_main.c >b/drivers/net/ethernet/intel/igc/igc_main.c >index 7aafa60ba0c8..16a61d432296 100644 >--- a/drivers/net/ethernet/intel/igc/igc_main.c >+++ b/drivers/net/ethernet/intel/igc/igc_main.c >@@ -6908,28 +6908,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; > >@@ -6938,9 +6939,20 @@ 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) { >+ /* for IGC_FLAG_QUEUE_PAIRS, this will be NOP as NAPI has >+ * been already marked with NAPIF_STATE_MISSED >+ */
The code looked good to me, but I am not understand this comment. Can you help to explain why the NAPI will be marked as NAPIF_STATE_MISSED? per my understanding, for IGC_FLAG_QUEUE_PAIRS, rx_ ring->q_vector will be equal to tx_ ring->q_vector, thus, no harm for eics to "OR" the same value twice. Am I right? >+ 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; > } >diff --git a/drivers/net/ethernet/intel/igc/igc_ptp.c >b/drivers/net/ethernet/intel/igc/igc_ptp.c >index b7b46d863bee..df2e500a4d7e 100644 >--- a/drivers/net/ethernet/intel/igc/igc_ptp.c >+++ b/drivers/net/ethernet/intel/igc/igc_ptp.c >@@ -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; > } >-- >2.34.1
