On Saturday, December 20, 2025 7:00 PM, Vivek Behera 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]>

Reviewed-by: Song Yoong Siang <[email protected]>

Thanks for the rework.
Note: You do not need to submit a new version just to add a reviewed-by tag,
unless you have another changes to make.

>---
>v1:
>https://lore.kernel.or/
>g%2Fintel-wired-
>lan%2FAS1PR10MB5392B7268416DB8A1624FDB88FA7A%40AS1PR10MB5392.EUR
>PRD10.PROD.OUTLOOK.COM%2F&data=05%7C02%7Cvivek.behera%40siemens.co
>m%7Cb609a859d19b47e8f47808de38d77627%7C38ae3bcd95794fd4addab42e149
>5d55a%7C1%7C0%7C639010695226787962%7CUnknown%7CTWFpbGZsb3d8eyJF
>bXB0eU1hcGkiOnRydWUsIlYiOiIwLjAuMDAwMCIsIlAiOiJXaW4zMiIsIkFOIjoiTWFpbCI
>sIldUIjoyfQ%3D%3D%7C0%7C%7C%7C&sdata=S1060xzCOGrJo0cO2enNhDmCIJUcC
>LZd%2F%2BmKLByazm8%3D&reserved=0
>v2:
>https://lore.kernel.or/
>g%2Fintel-wired-
>lan%2FAS1PR10MB539280B1427DA0ABE9D65E628FA5A%40AS1PR10MB5392.EUR
>PRD10.PROD.OUTLOOK.COM%2F&data=05%7C02%7Cvivek.behera%40siemens.co
>m%7Cb609a859d19b47e8f47808de38d77627%7C38ae3bcd95794fd4addab42e149
>5d55a%7C1%7C0%7C639010695226846016%7CUnknown%7CTWFpbGZsb3d8eyJF
>bXB0eU1hcGkiOnRydWUsIlYiOiIwLjAuMDAwMCIsIlAiOiJXaW4zMiIsIkFOIjoiTWFpbCI
>sIldUIjoyfQ%3D%3D%7C0%7C%7C%7C&sdata=ksDVfndVlbafyexZ2%2B3j9GccO9hu
>pybvtl1twZs5OSk%3D&reserved=0
>v3:
>https://lore.kernel.or/
>g%2Fintel-wired-
>lan%2FIA3PR11MB8986E4ACB7F264CF2DD1D750E5A0A%40IA3PR11MB8986.nam
>prd11.prod.outlook.com%2F&data=05%7C02%7Cvivek.behera%40siemens.com%7C
>b609a859d19b47e8f47808de38d77627%7C38ae3bcd95794fd4addab42e1495d55a
>%7C1%7C0%7C639010695226890990%7CUnknown%7CTWFpbGZsb3d8eyJFbXB0e
>U1hcGkiOnRydWUsIlYiOiIwLjAuMDAwMCIsIlAiOiJXaW4zMiIsIkFOIjoiTWFpbCIsIldUIj
>oyfQ%3D%3D%7C0%7C%7C%7C&sdata=zEWhj7N2%2BmwsShmoy1ACAjb3vi7yJgb
>A077fISIOZiM%3D&reserved=0
>v4:
>https://lore.kernel.or/
>g%2Fintel-wired-
>lan%2FAS1PR10MB53926CB955FBD4F9F4A018818FA0A%40AS1PR10MB5392.EUR
>PRD10.PROD.OUTLOOK.COM%2F&data=05%7C02%7Cvivek.behera%40siemens.co
>m%7Cb609a859d19b47e8f47808de38d77627%7C38ae3bcd95794fd4addab42e149
>5d55a%7C1%7C0%7C639010695226933538%7CUnknown%7CTWFpbGZsb3d8eyJF
>bXB0eU1hcGkiOnRydWUsIlYiOiIwLjAuMDAwMCIsIlAiOiJXaW4zMiIsIkFOIjoiTWFpbCI
>sIldUIjoyfQ%3D%3D%7C0%7C%7C%7C&sdata=23aTM4TNsnyzoS%2FpSM1GcluaWz
>LPNbrPKEo%2BOrm9hZQ%3D&reserved=0
>v5:
>https://lore.kernel.or/
>g%2Fintel-wired-
>lan%2FAS1PR10MB5392FCA415A38B9DD7BB5F218FA0A%40AS1PR10MB5392.EUR
>PRD10.PROD.OUTLOOK.COM%2F&data=05%7C02%7Cvivek.behera%40siemens.co
>m%7Cb609a859d19b47e8f47808de38d77627%7C38ae3bcd95794fd4addab42e149
>5d55a%7C1%7C0%7C639010695227205026%7CUnknown%7CTWFpbGZsb3d8eyJF
>bXB0eU1hcGkiOnRydWUsIlYiOiIwLjAuMDAwMCIsIlAiOiJXaW4zMiIsIkFOIjoiTWFpbCI
>sIldUIjoyfQ%3D%3D%7C0%7C%7C%7C&sdata=JdY3aHzIcIWtir9fAV%2BMELNWtiyLJ
>YRU7IMxLZ0mPqQ%3D&reserved=0
>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]/
>
>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
>---
> drivers/net/ethernet/intel/igc/igc_main.c | 77 ++++++++++++++++++-----
> drivers/net/ethernet/intel/igc/igc_ptp.c  |  3 +-
> 2 files changed, 62 insertions(+), 18 deletions(-)
>
>diff --git a/drivers/net/ethernet/intel/igc/igc_main.c
>b/drivers/net/ethernet/intel/igc/igc_main.c
>index 7aafa60ba0c8..7bd9f10a3f29 100644
>--- a/drivers/net/ethernet/intel/igc/igc_main.c
>+++ b/drivers/net/ethernet/intel/igc/igc_main.c
>@@ -6908,40 +6908,83 @@ 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;
>
>       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;
>
>-      ring = adapter->rx_ring[queue_id];
>-
>+      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 */
>+                      ring = adapter->rx_ring[queue_id];
>+              } else {
>+                      /* Two irqs for Rx and Tx need to be triggered */
>+                      struct napi_struct *rx_napi;
>+                      struct napi_struct *tx_napi;
>+                      u32 eics_tx = 0;
>+                      u32 eics_rx = 0;
>+                      /* 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) {
>+              /* Get the ring params from Tx */
>+              ring = adapter->tx_ring[queue_id];
>+      } else if (flags & XDP_WAKEUP_RX) {
>+              /* Get the ring params from Rx */
>+              ring = adapter->rx_ring[queue_id];
>+      } else {
>+              /* Invalid Flags */
>+              return -EINVAL;
>+      }
>+      /* 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..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;
>       }

Reply via email to