>-----Original Message----- >From: Intel-wired-lan <[email protected]> On Behalf Of Vivek >Behera >Sent: Monday, December 15, 2025 1:21 PM >To: Loktionov, Aleksandr <[email protected]>; Keller, Jacob E ><[email protected]>; Nguyen, Anthony L <[email protected]>; >Kitszel, Przemyslaw <[email protected]> >Cc: [email protected]; [email protected]; Behera, Vivek ><[email protected]> >Subject: [Intel-wired-lan] [PATCH iwl-net v8] igc: Fix trigger of incorrect >irq in igc_xsk_wakeup function > >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: Przemyslaw Kitszel <[email protected]> >Reviewed-by: Tony Nguyen <[email protected]> >--- >v1: >https://lore.kernel.org/intel-wired-lan/as1pr10mb5392b7268416db8a1624fdb88f...@as1pr10mb5392.eurprd10.prod.outlook.com/ >v2: >https://lore.kernel.org/intel-wired-lan/as1pr10mb539280b1427da0abe9d65e628f...@as1pr10mb5392.eurprd10.prod.outlook.com/ >v3: >https://lore.kernel.org/intel-wired-lan/ia3pr11mb8986e4acb7f264cf2dd1d750e5...@ia3pr11mb8986.namprd11.prod.outlook.com/ >v4: >https://lore.kernel.org/intel-wired-lan/as1pr10mb53926cb955fbd4f9f4a018818f...@as1pr10mb5392.eurprd10.prod.outlook.com/ >v5: >https://lore.kernel.org/intel-wired-lan/as1pr10mb5392fca415a38b9dd7bb5f218f...@as1pr10mb5392.eurprd10.prod.outlook.com/ >v6: >https://lore.kernel.org/intel-wired-lan/[email protected]/ >v7: >https://lore.kernel.org/intel-wired-lan/[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 >--- > drivers/net/ethernet/intel/igc/igc_main.c | 90 ++++++++++++++++++----- > drivers/net/ethernet/intel/igc/igc_ptp.c | 2 +- > 2 files changed, 73 insertions(+), 19 deletions(-) > >diff --git a/drivers/net/ethernet/intel/igc/igc_main.c >b/drivers/net/ethernet/intel/igc/igc_main.c >index 7aafa60ba0c8..76e4790bd3c0 100644 >--- a/drivers/net/ethernet/intel/igc/igc_main.c >+++ b/drivers/net/ethernet/intel/igc/igc_main.c >@@ -6908,21 +6908,13 @@ 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) >-{ >- struct igc_hw *hw = &adapter->hw; >- u32 eics = 0; >- >- eics |= q_vector->eims_value; >- wr32(IGC_EICS, eics); >-} >- > int igc_xsk_wakeup(struct net_device *dev, u32 queue_id, u32 flags) { > struct igc_adapter *adapter = netdev_priv(dev); >+ struct igc_hw *hw = &adapter->hw; > struct igc_q_vector *q_vector; > struct igc_ring *ring; >+ u32 eics = 0; > > if (test_bit(__IGC_DOWN, &adapter->state)) > return -ENETDOWN; >@@ -6930,18 +6922,80 @@ int igc_xsk_wakeup(struct net_device *dev, u32 >queue_id, u32 flags) > if (!igc_xdp_is_enabled(adapter)) > return -ENXIO; > >- if (queue_id >= adapter->num_rx_queues) >+ if ((flags & XDP_WAKEUP_RX) && (flags & XDP_WAKEUP_TX)) { >+ /* If both TX and RX need to be woken up */ >+ /* check if queue pairs are active. */ >+ if ((adapter->flags & IGC_FLAG_QUEUE_PAIRS)) { >+ /* Just get the ring params from Rx */ >+ if (queue_id >= adapter->num_rx_queues) >+ return -EINVAL; >+ ring = adapter->rx_ring[queue_id]; >+ } else { >+ /* Two irqs for Rx AND Tx need to be triggered */ >+ u32 eics_tx = 0; >+ u32 eics_rx = 0; >+ struct napi_struct *rx_napi; >+ struct napi_struct *tx_napi; >+ >+ if (queue_id >= adapter->num_rx_queues) >+ return -EINVAL; >+ >+ if (queue_id >= adapter->num_tx_queues) >+ return -EINVAL; >+ >+ /* IRQ trigger preparation for Rx */ >+ ring = adapter->rx_ring[queue_id]; >+ if (!ring->xsk_pool) >+ return -ENXIO; >+ q_vector = ring->q_vector; >+ rx_napi = &q_vector->napi; >+ /* Extend the BIT mask for eics */ >+ eics_rx |= ring->q_vector->eims_value; >+ >+ /* IRQ trigger preparation for Tx */ >+ ring = adapter->tx_ring[queue_id]; >+ if (!ring->xsk_pool) >+ return -ENXIO; >+ q_vector = ring->q_vector; >+ tx_napi = &q_vector->napi; >+ /* Extend the BIT mask for eics */ >+ eics_tx |= ring->q_vector->eims_value; >+ >+ /* Check and update napi states for rx and tx */ >+ if (!napi_if_scheduled_mark_missed(rx_napi)) >+ eics |= eics_rx; >+ if (!napi_if_scheduled_mark_missed(tx_napi)) >+ eics |= eics_tx; >+ >+ /* Now we trigger the required irqs for Rx and Tx */ >+ if (eics) >+ wr32(IGC_EICS, eics); >+ >+ return 0; >+ } >+ } else if (flags & XDP_WAKEUP_TX) { >+ if (queue_id >= adapter->num_tx_queues) >+ return -EINVAL; >+ /* Get the ring params from Tx */ >+ ring = adapter->tx_ring[queue_id]; >+ } else if (flags & XDP_WAKEUP_RX) { >+ if (queue_id >= adapter->num_rx_queues) >+ return -EINVAL; >+ /* Get the ring params from Rx */ >+ ring = adapter->rx_ring[queue_id]; >+ } else { >+ /* Invalid Flags */ > return -EINVAL; >- >- ring = adapter->rx_ring[queue_id]; >- >+ } >+ /* Prepare to trigger single irq */ > 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); >- >+ q_vector = ring->q_vector; >+ if (!napi_if_scheduled_mark_missed(&q_vector->napi)) { >+ eics |= q_vector->eims_value; >+ 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..6d8c2d639cd7 100644 >--- a/drivers/net/ethernet/intel/igc/igc_ptp.c >+++ b/drivers/net/ethernet/intel/igc/igc_ptp.c >@@ -550,7 +550,7 @@ 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
Reviewed-by: Piotr Kwapulinski <[email protected]>
