[<prev] [next>] [<thread-prev] [thread-next>] [day] [month] [year] [list]
Message-ID:
<AS1PR10MB539280B1427DA0ABE9D65E628FA5A@AS1PR10MB5392.EURPRD10.PROD.OUTLOOK.COM>
Date: Sun, 7 Dec 2025 15:46:48 +0000
From: "Behera, VIVEK" <vivek.behera@...mens.com>
To: Tony Nguyen <anthony.l.nguyen@...el.com>, Przemek Kitszel
<przemyslaw.kitszel@...el.com>, Andrew Lunn <andrew+netdev@...n.ch>, "\"David
S. Miller\"" <davem@...emloft.net>, Eric Dumazet <edumazet@...gle.com>, Jakub
Kicinski <kuba@...nel.org>, Paolo Abeni <pabeni@...hat.com>
CC: "intel-wired-lan@...ts.osuosl.org" <intel-wired-lan@...ts.osuosl.org>,
"netdev@...r.kernel.org" <netdev@...r.kernel.org>,
"linux-kernel@...r.kernel.org" <linux-kernel@...r.kernel.org>, "Behera,
VIVEK" <vivek.behera@...mens.com>
Subject: RE: [PATCH v2] igc: Enhance xsk wakeup for split IRQ and fix PTP TX
wakeup
Hi everyone,
This is v2 of the patch "igc: Enhance xsk wakeup for split IRQ and fix PTP TX wakeup".
Changes in 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
Thanks,
Vivek Behera
>From a9d7469510a21036e26a7804398d3e7a08c83b84 Mon Sep 17 00:00:00 2001
From: Vivek Behera <vivek.behera@...mens.com>
Date: Fri, 5 Dec 2025 10:26:05 +0100
Subject: [PATCH v2] igc: Enhance xsk wakeup for split IRQ and fix PTP TX
wakeup
The igc_xsk_wakeup function previously returned an error when both
XDP_WAKEUP_RX and XDP_WAKEUP_TX flags were set but IGC_FLAG_QUEUE_PAIRS
was not active. This limitation prevented full XDP functionality in
configurations lacking queue pairs, such as specific i226 setups with
fewer active CPU cores or ethtool configurations.
Additionally, the igc_ptp_free_tx_buffer function was incorrectly
calling igc_xsk_wakeup with a zero 'flags' argument, which is an
invalid state and would lead to an -EINVAL return, preventing proper
TX completion wakeup.
This patch addresses these issues with the following changes:
1. **igc_xsk_wakeup Logic Enhancement:**
* The function now intelligently handles requests for both RX and TX
wakeups even when IGC_FLAG_QUEUE_PAIRS is not active. Instead of
returning an error, it prepares and triggers separate IRQs for the
RX and TX paths by accumulating the eims_value for both rings before
writing it once to eics.
* The static helper function 'igc_trigger_rxtxq_interrupt' has been
removed, and its functionality integrated directly into
igc_xsk_wakeup for a more unified and streamlined IRQ triggering
mechanism.
* Added explicit 'queue_id' validation for both 'num_rx_queues' and
'num_tx_queues' within the new split IRQ path to prevent potential
out-of-bounds access.
2. **PTP TX Wakeup Fix:**
* Corrected the call to igc_xsk_wakeup in igc_ptp_free_tx_buffer to
explicitly pass XDP_WAKEUP_TX as the 'flags' argument. This ensures
that the TX completion is properly signalled, resolving the previous
issue where 'flags=0' was passed, which would cause igc_xsk_wakeup
to return -EINVAL.
Signed-off-by: Vivek Behera <vivek.behera@...mens.com>
---
drivers/net/ethernet/intel/igc/igc_main.c | 81 ++++++++++++++++++-----
drivers/net/ethernet/intel/igc/igc_ptp.c | 2 +-
2 files changed, 64 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..a130cdf4b45b 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,71 @@ 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)
- return -EINVAL;
+ 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***/
+ if (queue_id >= adapter->num_rx_queues)
+ return -EINVAL; /**queue_id invalid**/
- ring = adapter->rx_ring[queue_id];
+ if (queue_id >= adapter->num_tx_queues)
+ return -EINVAL; /**queue_id invalid**/
- if (!ring->xsk_pool)
- return -ENXIO;
+ /**IRQ trigger preparation for Rx**/
+ ring = adapter->rx_ring[queue_id];
+ 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);
+ /* Retrieve the q_vector saved in the ring */
+ q_vector = ring->q_vector;
+ if (!napi_if_scheduled_mark_missed(&q_vector->napi))
+ eics |= q_vector->eims_value;
+ /**IRQ trigger preparation for Tx */
+ ring = adapter->tx_ring[queue_id];
+ if (!ring->xsk_pool)
+ return -ENXIO;
+
+ /* Retrieve the q_vector saved in the ring */
+ q_vector = ring->q_vector;
+ if (!napi_if_scheduled_mark_missed(&q_vector->napi))
+ eics |= q_vector->eims_value; /**Extend the BIT mask for eics**/
+
+ /***Now we trigger the split irqs for Rx and Tx over eics***/
+ if (eics != 0)
+ 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;
+ }
+ /** Prepare to trigger single irq */
+ if (!ring->xsk_pool)
+ return -ENXIO;
+ /* Retrieve the q_vector saved in the ring */
+ 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
Powered by blists - more mailing lists