* [Intel-wired-lan] [PATCH iwl-net v4] igb: Fix trigger of incorrect irq in igb_xsk_wakeup
@ 2025-12-22 11:57 Vivek Behera via Intel-wired-lan
2026-01-09 0:14 ` Maciej Fijalkowski
0 siblings, 1 reply; 4+ messages in thread
From: Vivek Behera via Intel-wired-lan @ 2025-12-22 11:57 UTC (permalink / raw)
To: aleksandr.loktionov, jacob.e.keller, anthony.l.nguyen,
przemyslaw.kitszel, maciej.fijalkowski, sriram.yagnaraman, kurt
Cc: intel-wired-lan, vivek.behera
The current implementation in the igb_xsk_wakeup expects the Rx and Tx queues
to share the same irq. This would lead to triggering of incorrect irq
in split irq configuration.
This patch addresses this issue which could impact environments
with 2 active cpu cores
or when the number of queues is reduced to 2 or less
cat /proc/interrupts | grep eno2
167: 0 0 0 0 IR-PCI-MSIX-0000:08:00.0
0-edge eno2
168: 0 0 0 0 IR-PCI-MSIX-0000:08:00.0
1-edge eno2-rx-0
169: 0 0 0 0 IR-PCI-MSIX-0000:08:00.0
2-edge eno2-rx-1
170: 0 0 0 0 IR-PCI-MSIX-0000:08:00.0
3-edge eno2-tx-0
171: 0 0 0 0 IR-PCI-MSIX-0000:08:00.0
4-edge eno2-tx-1
Furthermore it uses the flags input argument to trigger either rx, tx or
both rx and tx irqs as specified in the ndo_xsk_wakeup api documentation
Fixes: 80f6ccf9f116 ("igb: Introduce XSK data structures and helpers")
Signed-off-by: Vivek Behera <vivek.behera@siemens.com>
Reviewed-by: Aleksandr Loktionov <aleksandr.loktionov@intel.com>
---
v1: https://lore.kernel.org/intel-wired-lan/20251212131454.124116-1-vivek.behera@siemens.com/
v2: https://lore.kernel.org/intel-wired-lan/20251215115416.410619-1-vivek.behera@siemens.com/
v3: https://lore.kernel.org/intel-wired-lan/20251220114936.140473-1-vivek.behera@siemens.com/
changelog:
v1
- Inital description of the Bug and fixes made in the patch
v1 -> v2
- Handling of RX and TX Wakeup in igc_xsk_wakeup for a split IRQ configuration
- Review suggestions by Aleksander: Modified sequence to complete all
error checks for rx and tx before updating napi states and triggering irqs
- Corrected trigger of TX and RX interrupts over E1000_ICS (non msix use case)
- Added define for Tx interrupt trigger bit mask for E1000_ICS
v2 -> v3
- Included applicable feedback and suggestions from igc patch
- Fixed logic in updating eics value when both TX and RX need wakeup
v3 -> v4
- Added comments to explain trigerring of both TX and RX with active queue pairs
- Fixed check of xsk pools in if statement
---
.../net/ethernet/intel/igb/e1000_defines.h | 1 +
drivers/net/ethernet/intel/igb/igb_xsk.c | 90 +++++++++++++++++--
2 files changed, 83 insertions(+), 8 deletions(-)
diff --git a/drivers/net/ethernet/intel/igb/e1000_defines.h b/drivers/net/ethernet/intel/igb/e1000_defines.h
index fa028928482f..9357564a2d58 100644
--- a/drivers/net/ethernet/intel/igb/e1000_defines.h
+++ b/drivers/net/ethernet/intel/igb/e1000_defines.h
@@ -443,6 +443,7 @@
#define E1000_ICS_LSC E1000_ICR_LSC /* Link Status Change */
#define E1000_ICS_RXDMT0 E1000_ICR_RXDMT0 /* rx desc min. threshold */
#define E1000_ICS_DRSTA E1000_ICR_DRSTA /* Device Reset Aserted */
+#define E1000_ICS_TXDW E1000_ICR_TXDW /* Transmit desc written back */
/* Extended Interrupt Cause Set */
/* E1000_EITR_CNT_IGNR is only for 82576 and newer */
diff --git a/drivers/net/ethernet/intel/igb/igb_xsk.c b/drivers/net/ethernet/intel/igb/igb_xsk.c
index 30ce5fbb5b77..1d21674c0f33 100644
--- a/drivers/net/ethernet/intel/igb/igb_xsk.c
+++ b/drivers/net/ethernet/intel/igb/igb_xsk.c
@@ -529,6 +529,7 @@ int igb_xsk_wakeup(struct net_device *dev, u32 qid, u32 flags)
struct igb_adapter *adapter = netdev_priv(dev);
struct e1000_hw *hw = &adapter->hw;
struct igb_ring *ring;
+ struct igb_q_vector *q_vector;
u32 eics = 0;
if (test_bit(__IGB_DOWN, &adapter->state))
@@ -536,14 +537,82 @@ int igb_xsk_wakeup(struct net_device *dev, u32 qid, u32 flags)
if (!igb_xdp_is_enabled(adapter))
return -EINVAL;
-
- if (qid >= adapter->num_tx_queues)
+ /* Check if queue_id is valid. Tx and Rx queue numbers are always same */
+ if (qid >= adapter->num_rx_queues)
return -EINVAL;
- ring = adapter->tx_ring[qid];
-
- if (test_bit(IGB_RING_FLAG_TX_DISABLED, &ring->flags))
- return -ENETDOWN;
+ 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 & IGB_FLAG_QUEUE_PAIRS) {
+ /* In queue-pair mode, rx_ring and tx_ring share the same q_vector,
+ * so a single IRQ trigger will wake both RX and TX processing
+ */
+ ring = adapter->rx_ring[qid];
+ } else {
+ /* Two irqs for Rx AND Tx need to be triggered */
+ struct napi_struct *rx_napi;
+ struct napi_struct *tx_napi;
+ bool trigger_irq_tx = false;
+ bool trigger_irq_rx = false;
+ u32 eics_tx = 0;
+ u32 eics_rx = 0;
+ /* IRQ trigger preparation for Rx */
+ ring = adapter->rx_ring[qid];
+ if (!READ_ONCE(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[qid];
+ if (test_bit(IGB_RING_FLAG_TX_DISABLED, &ring->flags))
+ return -ENETDOWN;
+
+ if (!READ_ONCE(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)) {
+ trigger_irq_rx = true;
+ eics |= eics_rx;
+ }
+ if (!napi_if_scheduled_mark_missed(tx_napi)) {
+ trigger_irq_tx = true;
+ eics |= eics_tx;
+ }
+ /* Now we trigger the required irqs for Rx and Tx */
+ if ((trigger_irq_rx) || (trigger_irq_tx)) {
+ if (adapter->flags & IGB_FLAG_HAS_MSIX) {
+ wr32(E1000_EICS, eics);
+ } else {
+ if ((trigger_irq_rx) && (trigger_irq_tx))
+ wr32(E1000_ICS, E1000_ICS_RXDMT0 | E1000_ICS_TXDW);
+ else if (trigger_irq_rx)
+ wr32(E1000_ICS, E1000_ICS_RXDMT0);
+ else
+ wr32(E1000_ICS, E1000_ICS_TXDW);
+ }
+ }
+ return 0;
+ }
+ } else if (flags & XDP_WAKEUP_TX) {
+ /* Get the ring params from Tx */
+ ring = adapter->tx_ring[qid];
+ if (test_bit(IGB_RING_FLAG_TX_DISABLED, &ring->flags))
+ return -ENETDOWN;
+ } else if (flags & XDP_WAKEUP_RX) {
+ /* Get the ring params from Rx */
+ ring = adapter->rx_ring[qid];
+ } else {
+ /* Invalid Flags */
+ return -EINVAL;
+ }
if (!READ_ONCE(ring->xsk_pool))
return -EINVAL;
@@ -551,10 +620,15 @@ int igb_xsk_wakeup(struct net_device *dev, u32 qid, u32 flags)
if (!napi_if_scheduled_mark_missed(&ring->q_vector->napi)) {
/* Cause software interrupt */
if (adapter->flags & IGB_FLAG_HAS_MSIX) {
- eics |= ring->q_vector->eims_value;
+ eics = ring->q_vector->eims_value;
wr32(E1000_EICS, eics);
} else {
- wr32(E1000_ICS, E1000_ICS_RXDMT0);
+ if ((flags & XDP_WAKEUP_RX) && (flags & XDP_WAKEUP_TX))
+ wr32(E1000_ICS, E1000_ICS_RXDMT0 | E1000_ICS_TXDW);
+ else if (flags & XDP_WAKEUP_RX)
+ wr32(E1000_ICS, E1000_ICS_RXDMT0);
+ else
+ wr32(E1000_ICS, E1000_ICS_TXDW);
}
}
--
2.34.1
^ permalink raw reply related [flat|nested] 4+ messages in thread
* Re: [Intel-wired-lan] [PATCH iwl-net v4] igb: Fix trigger of incorrect irq in igb_xsk_wakeup
2025-12-22 11:57 [Intel-wired-lan] [PATCH iwl-net v4] igb: Fix trigger of incorrect irq in igb_xsk_wakeup Vivek Behera via Intel-wired-lan
@ 2026-01-09 0:14 ` Maciej Fijalkowski
2026-01-11 14:27 ` Behera, VIVEK via Intel-wired-lan
2026-01-12 11:38 ` Loktionov, Aleksandr
0 siblings, 2 replies; 4+ messages in thread
From: Maciej Fijalkowski @ 2026-01-09 0:14 UTC (permalink / raw)
To: Vivek Behera
Cc: aleksandr.loktionov, jacob.e.keller, anthony.l.nguyen,
przemyslaw.kitszel, sriram.yagnaraman, kurt, intel-wired-lan
On Mon, Dec 22, 2025 at 12:57:47PM +0100, Vivek Behera wrote:
> The current implementation in the igb_xsk_wakeup expects the Rx and Tx queues
> to share the same irq. This would lead to triggering of incorrect irq
> in split irq configuration.
> This patch addresses this issue which could impact environments
> with 2 active cpu cores
> or when the number of queues is reduced to 2 or less
>
> cat /proc/interrupts | grep eno2
> 167: 0 0 0 0 IR-PCI-MSIX-0000:08:00.0
> 0-edge eno2
> 168: 0 0 0 0 IR-PCI-MSIX-0000:08:00.0
> 1-edge eno2-rx-0
> 169: 0 0 0 0 IR-PCI-MSIX-0000:08:00.0
> 2-edge eno2-rx-1
> 170: 0 0 0 0 IR-PCI-MSIX-0000:08:00.0
> 3-edge eno2-tx-0
> 171: 0 0 0 0 IR-PCI-MSIX-0000:08:00.0
> 4-edge eno2-tx-1
>
> Furthermore it uses the flags input argument to trigger either rx, tx or
> both rx and tx irqs as specified in the ndo_xsk_wakeup api documentation
>
> Fixes: 80f6ccf9f116 ("igb: Introduce XSK data structures and helpers")
> Signed-off-by: Vivek Behera <vivek.behera@siemens.com>
> Reviewed-by: Aleksandr Loktionov <aleksandr.loktionov@intel.com>
> ---
> v1: https://lore.kernel.org/intel-wired-lan/20251212131454.124116-1-vivek.behera@siemens.com/
> v2: https://lore.kernel.org/intel-wired-lan/20251215115416.410619-1-vivek.behera@siemens.com/
> v3: https://lore.kernel.org/intel-wired-lan/20251220114936.140473-1-vivek.behera@siemens.com/
>
> changelog:
> v1
> - Inital description of the Bug and fixes made in the patch
>
> v1 -> v2
> - Handling of RX and TX Wakeup in igc_xsk_wakeup for a split IRQ configuration
> - Review suggestions by Aleksander: Modified sequence to complete all
> error checks for rx and tx before updating napi states and triggering irqs
> - Corrected trigger of TX and RX interrupts over E1000_ICS (non msix use case)
> - Added define for Tx interrupt trigger bit mask for E1000_ICS
>
> v2 -> v3
> - Included applicable feedback and suggestions from igc patch
> - Fixed logic in updating eics value when both TX and RX need wakeup
>
> v3 -> v4
> - Added comments to explain trigerring of both TX and RX with active queue pairs
> - Fixed check of xsk pools in if statement
> ---
> .../net/ethernet/intel/igb/e1000_defines.h | 1 +
> drivers/net/ethernet/intel/igb/igb_xsk.c | 90 +++++++++++++++++--
> 2 files changed, 83 insertions(+), 8 deletions(-)
>
> diff --git a/drivers/net/ethernet/intel/igb/e1000_defines.h b/drivers/net/ethernet/intel/igb/e1000_defines.h
> index fa028928482f..9357564a2d58 100644
> --- a/drivers/net/ethernet/intel/igb/e1000_defines.h
> +++ b/drivers/net/ethernet/intel/igb/e1000_defines.h
> @@ -443,6 +443,7 @@
> #define E1000_ICS_LSC E1000_ICR_LSC /* Link Status Change */
> #define E1000_ICS_RXDMT0 E1000_ICR_RXDMT0 /* rx desc min. threshold */
> #define E1000_ICS_DRSTA E1000_ICR_DRSTA /* Device Reset Aserted */
> +#define E1000_ICS_TXDW E1000_ICR_TXDW /* Transmit desc written back */
>
> /* Extended Interrupt Cause Set */
> /* E1000_EITR_CNT_IGNR is only for 82576 and newer */
> diff --git a/drivers/net/ethernet/intel/igb/igb_xsk.c b/drivers/net/ethernet/intel/igb/igb_xsk.c
> index 30ce5fbb5b77..1d21674c0f33 100644
> --- a/drivers/net/ethernet/intel/igb/igb_xsk.c
> +++ b/drivers/net/ethernet/intel/igb/igb_xsk.c
> @@ -529,6 +529,7 @@ int igb_xsk_wakeup(struct net_device *dev, u32 qid, u32 flags)
> struct igb_adapter *adapter = netdev_priv(dev);
> struct e1000_hw *hw = &adapter->hw;
> struct igb_ring *ring;
> + struct igb_q_vector *q_vector;
> u32 eics = 0;
>
> if (test_bit(__IGB_DOWN, &adapter->state))
> @@ -536,14 +537,82 @@ int igb_xsk_wakeup(struct net_device *dev, u32 qid, u32 flags)
>
> if (!igb_xdp_is_enabled(adapter))
> return -EINVAL;
> -
> - if (qid >= adapter->num_tx_queues)
> + /* Check if queue_id is valid. Tx and Rx queue numbers are always same */
> + if (qid >= adapter->num_rx_queues)
> return -EINVAL;
>
> - ring = adapter->tx_ring[qid];
> -
> - if (test_bit(IGB_RING_FLAG_TX_DISABLED, &ring->flags))
> - return -ENETDOWN;
> + 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 & IGB_FLAG_QUEUE_PAIRS) {
> + /* In queue-pair mode, rx_ring and tx_ring share the same q_vector,
> + * so a single IRQ trigger will wake both RX and TX processing
> + */
> + ring = adapter->rx_ring[qid];
> + } else {
> + /* Two irqs for Rx AND Tx need to be triggered */
> + struct napi_struct *rx_napi;
> + struct napi_struct *tx_napi;
> + bool trigger_irq_tx = false;
> + bool trigger_irq_rx = false;
> + u32 eics_tx = 0;
> + u32 eics_rx = 0;
> + /* IRQ trigger preparation for Rx */
> + ring = adapter->rx_ring[qid];
> + if (!READ_ONCE(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[qid];
> + if (test_bit(IGB_RING_FLAG_TX_DISABLED, &ring->flags))
> + return -ENETDOWN;
> +
> + if (!READ_ONCE(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)) {
> + trigger_irq_rx = true;
> + eics |= eics_rx;
> + }
> + if (!napi_if_scheduled_mark_missed(tx_napi)) {
> + trigger_irq_tx = true;
> + eics |= eics_tx;
> + }
> + /* Now we trigger the required irqs for Rx and Tx */
> + if ((trigger_irq_rx) || (trigger_irq_tx)) {
> + if (adapter->flags & IGB_FLAG_HAS_MSIX) {
> + wr32(E1000_EICS, eics);
> + } else {
> + if ((trigger_irq_rx) && (trigger_irq_tx))
> + wr32(E1000_ICS, E1000_ICS_RXDMT0 | E1000_ICS_TXDW);
> + else if (trigger_irq_rx)
> + wr32(E1000_ICS, E1000_ICS_RXDMT0);
> + else
> + wr32(E1000_ICS, E1000_ICS_TXDW);
> + }
> + }
> + return 0;
> + }
> + } else if (flags & XDP_WAKEUP_TX) {
> + /* Get the ring params from Tx */
> + ring = adapter->tx_ring[qid];
> + if (test_bit(IGB_RING_FLAG_TX_DISABLED, &ring->flags))
> + return -ENETDOWN;
> + } else if (flags & XDP_WAKEUP_RX) {
> + /* Get the ring params from Rx */
> + ring = adapter->rx_ring[qid];
> + } else {
> + /* Invalid Flags */
> + return -EINVAL;
> + }
This is too complicated IMHO. Wouldn't something like this work:
- if wakeup rx, pick napi from rx ring's q_vector
* napi_if_scheduled_mark_missed() logic that exists in igc_xsk_wakeup()
repeat for tx; if IGB_FLAG_QUEUE_PAIRS then the branch of second
napi_if_scheduled_mark_missed() call would not be executed as we had
previously marked the missed bit in napi state;
>
> if (!READ_ONCE(ring->xsk_pool))
> return -EINVAL;
> @@ -551,10 +620,15 @@ int igb_xsk_wakeup(struct net_device *dev, u32 qid, u32 flags)
> if (!napi_if_scheduled_mark_missed(&ring->q_vector->napi)) {
> /* Cause software interrupt */
> if (adapter->flags & IGB_FLAG_HAS_MSIX) {
> - eics |= ring->q_vector->eims_value;
> + eics = ring->q_vector->eims_value;
> wr32(E1000_EICS, eics);
> } else {
> - wr32(E1000_ICS, E1000_ICS_RXDMT0);
> + if ((flags & XDP_WAKEUP_RX) && (flags & XDP_WAKEUP_TX))
> + wr32(E1000_ICS, E1000_ICS_RXDMT0 | E1000_ICS_TXDW);
> + else if (flags & XDP_WAKEUP_RX)
> + wr32(E1000_ICS, E1000_ICS_RXDMT0);
> + else
> + wr32(E1000_ICS, E1000_ICS_TXDW);
> }
> }
>
> --
> 2.34.1
>
^ permalink raw reply [flat|nested] 4+ messages in thread
* Re: [Intel-wired-lan] [PATCH iwl-net v4] igb: Fix trigger of incorrect irq in igb_xsk_wakeup
2026-01-09 0:14 ` Maciej Fijalkowski
@ 2026-01-11 14:27 ` Behera, VIVEK via Intel-wired-lan
2026-01-12 11:38 ` Loktionov, Aleksandr
1 sibling, 0 replies; 4+ messages in thread
From: Behera, VIVEK via Intel-wired-lan @ 2026-01-11 14:27 UTC (permalink / raw)
To: Maciej Fijalkowski
Cc: aleksandr.loktionov@intel.com, jacob.e.keller@intel.com,
anthony.l.nguyen@intel.com, przemyslaw.kitszel@intel.com,
sriram.yagnaraman@ericsson.com, kurt@linutronix.de,
intel-wired-lan@lists.osuosl.org
> -----Original Message-----
> From: Maciej Fijalkowski <maciej.fijalkowski@intel.com>
> Sent: Friday, January 9, 2026 1:15 AM
> To: Behera, Vivek (DI FA DSP ICC PRC1) <vivek.behera@siemens.com>
> Cc: aleksandr.loktionov@intel.com; jacob.e.keller@intel.com;
> anthony.l.nguyen@intel.com; przemyslaw.kitszel@intel.com;
> sriram.yagnaraman@ericsson.com; kurt@linutronix.de; intel-wired-
> lan@lists.osuosl.org
> Subject: Re: [PATCH iwl-net v4] igb: Fix trigger of incorrect irq in
> igb_xsk_wakeup
>
> On Mon, Dec 22, 2025 at 12:57:47PM +0100, Vivek Behera wrote:
> > The current implementation in the igb_xsk_wakeup expects the Rx and Tx
> > queues to share the same irq. This would lead to triggering of
> > incorrect irq in split irq configuration.
> > This patch addresses this issue which could impact environments with 2
> > active cpu cores or when the number of queues is reduced to 2 or less
> >
> > cat /proc/interrupts | grep eno2
> > 167: 0 0 0 0 IR-PCI-MSIX-0000:08:00.0
> > 0-edge eno2
> > 168: 0 0 0 0 IR-PCI-MSIX-0000:08:00.0
> > 1-edge eno2-rx-0
> > 169: 0 0 0 0 IR-PCI-MSIX-0000:08:00.0
> > 2-edge eno2-rx-1
> > 170: 0 0 0 0 IR-PCI-MSIX-0000:08:00.0
> > 3-edge eno2-tx-0
> > 171: 0 0 0 0 IR-PCI-MSIX-0000:08:00.0
> > 4-edge eno2-tx-1
> >
> > Furthermore it uses the flags input argument to trigger either rx, tx
> > or both rx and tx irqs as specified in the ndo_xsk_wakeup api
> > documentation
> >
> > Fixes: 80f6ccf9f116 ("igb: Introduce XSK data structures and helpers")
> > Signed-off-by: Vivek Behera <vivek.behera@siemens.com>
> > Reviewed-by: Aleksandr Loktionov <aleksandr.loktionov@intel.com>
> > ---
> > v1:
> > https://eur01.safelinks.protection.outlook.com/?url=https%3A%2F%2Flore
> > .kernel.org%2Fintel-wired-lan%2F20251212131454.124116-1-vivek.behera%4
> >
> 0siemens.com%2F&data=05%7C02%7Cvivek.behera%40siemens.com%7C2e7cb
> 8169b
> >
> f4457c291908de4f1428a2%7C38ae3bcd95794fd4addab42e1495d55a%7C1%7C0%
> 7C63
> >
> 9035145171065657%7CUnknown%7CTWFpbGZsb3d8eyJFbXB0eU1hcGkiOnRyd
> WUsIlYiO
> >
> iIwLjAuMDAwMCIsIlAiOiJXaW4zMiIsIkFOIjoiTWFpbCIsIldUIjoyfQ%3D%3D%7C0
> %7C
> >
> %7C%7C&sdata=yCLwTDeoPNeub3tvzXTA7vX5p8I%2BmqcArOk0BzogiA0%3D&
> reserved
> > =0
> > v2:
> > https://eur01.safelinks.protection.outlook.com/?url=https%3A%2F%2Flore
> > .kernel.org%2Fintel-wired-lan%2F20251215115416.410619-1-vivek.behera%4
> >
> 0siemens.com%2F&data=05%7C02%7Cvivek.behera%40siemens.com%7C2e7cb
> 8169b
> >
> f4457c291908de4f1428a2%7C38ae3bcd95794fd4addab42e1495d55a%7C1%7C0%
> 7C63
> >
> 9035145171089890%7CUnknown%7CTWFpbGZsb3d8eyJFbXB0eU1hcGkiOnRyd
> WUsIlYiO
> >
> iIwLjAuMDAwMCIsIlAiOiJXaW4zMiIsIkFOIjoiTWFpbCIsIldUIjoyfQ%3D%3D%7C0
> %7C
> >
> %7C%7C&sdata=wm2ylxc0sATU4XL5LFP026DwMxUWe7EWAVjCQ3yyPGM%3
> D&reserved=0
> > v3:
> > https://eur01.safelinks.protection.outlook.com/?url=https%3A%2F%2Flore
> > .kernel.org%2Fintel-wired-lan%2F20251220114936.140473-1-vivek.behera%4
> >
> 0siemens.com%2F&data=05%7C02%7Cvivek.behera%40siemens.com%7C2e7cb
> 8169b
> >
> f4457c291908de4f1428a2%7C38ae3bcd95794fd4addab42e1495d55a%7C1%7C0%
> 7C63
> >
> 9035145171106278%7CUnknown%7CTWFpbGZsb3d8eyJFbXB0eU1hcGkiOnRyd
> WUsIlYiO
> >
> iIwLjAuMDAwMCIsIlAiOiJXaW4zMiIsIkFOIjoiTWFpbCIsIldUIjoyfQ%3D%3D%7C0
> %7C
> >
> %7C%7C&sdata=q7VkYNY8YzNn5rsbunTF04mt0gkBe1jeF6DrSbvw5s4%3D&res
> erved=0
> >
> > changelog:
> > v1
> > - Inital description of the Bug and fixes made in the patch
> >
> > v1 -> v2
> > - Handling of RX and TX Wakeup in igc_xsk_wakeup for a split IRQ
> > configuration
> > - Review suggestions by Aleksander: Modified sequence to complete all
> > error checks for rx and tx before updating napi states and
> > triggering irqs
> > - Corrected trigger of TX and RX interrupts over E1000_ICS (non msix
> > use case)
> > - Added define for Tx interrupt trigger bit mask for E1000_ICS
> >
> > v2 -> v3
> > - Included applicable feedback and suggestions from igc patch
> > - Fixed logic in updating eics value when both TX and RX need wakeup
> >
> > v3 -> v4
> > - Added comments to explain trigerring of both TX and RX with active
> > queue pairs
> > - Fixed check of xsk pools in if statement
> > ---
> > .../net/ethernet/intel/igb/e1000_defines.h | 1 +
> > drivers/net/ethernet/intel/igb/igb_xsk.c | 90 +++++++++++++++++--
> > 2 files changed, 83 insertions(+), 8 deletions(-)
> >
> > diff --git a/drivers/net/ethernet/intel/igb/e1000_defines.h
> > b/drivers/net/ethernet/intel/igb/e1000_defines.h
> > index fa028928482f..9357564a2d58 100644
> > --- a/drivers/net/ethernet/intel/igb/e1000_defines.h
> > +++ b/drivers/net/ethernet/intel/igb/e1000_defines.h
> > @@ -443,6 +443,7 @@
> > #define E1000_ICS_LSC E1000_ICR_LSC /* Link Status Change */
> > #define E1000_ICS_RXDMT0 E1000_ICR_RXDMT0 /* rx desc min.
> threshold */
> > #define E1000_ICS_DRSTA E1000_ICR_DRSTA /* Device Reset Aserted
> */
> > +#define E1000_ICS_TXDW E1000_ICR_TXDW /* Transmit desc written
> back */
> >
> > /* Extended Interrupt Cause Set */
> > /* E1000_EITR_CNT_IGNR is only for 82576 and newer */ diff --git
> > a/drivers/net/ethernet/intel/igb/igb_xsk.c
> > b/drivers/net/ethernet/intel/igb/igb_xsk.c
> > index 30ce5fbb5b77..1d21674c0f33 100644
> > --- a/drivers/net/ethernet/intel/igb/igb_xsk.c
> > +++ b/drivers/net/ethernet/intel/igb/igb_xsk.c
> > @@ -529,6 +529,7 @@ int igb_xsk_wakeup(struct net_device *dev, u32 qid,
> u32 flags)
> > struct igb_adapter *adapter = netdev_priv(dev);
> > struct e1000_hw *hw = &adapter->hw;
> > struct igb_ring *ring;
> > + struct igb_q_vector *q_vector;
> > u32 eics = 0;
> >
> > if (test_bit(__IGB_DOWN, &adapter->state)) @@ -536,14 +537,82 @@
> int
> > igb_xsk_wakeup(struct net_device *dev, u32 qid, u32 flags)
> >
> > if (!igb_xdp_is_enabled(adapter))
> > return -EINVAL;
> > -
> > - if (qid >= adapter->num_tx_queues)
> > + /* Check if queue_id is valid. Tx and Rx queue numbers are always same
> */
> > + if (qid >= adapter->num_rx_queues)
> > return -EINVAL;
> >
> > - ring = adapter->tx_ring[qid];
> > -
> > - if (test_bit(IGB_RING_FLAG_TX_DISABLED, &ring->flags))
> > - return -ENETDOWN;
> > + 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 & IGB_FLAG_QUEUE_PAIRS) {
> > + /* In queue-pair mode, rx_ring and tx_ring share the same
> q_vector,
> > + * so a single IRQ trigger will wake both RX and TX
> processing
> > + */
> > + ring = adapter->rx_ring[qid];
> > + } else {
> > + /* Two irqs for Rx AND Tx need to be triggered */
> > + struct napi_struct *rx_napi;
> > + struct napi_struct *tx_napi;
> > + bool trigger_irq_tx = false;
> > + bool trigger_irq_rx = false;
> > + u32 eics_tx = 0;
> > + u32 eics_rx = 0;
> > + /* IRQ trigger preparation for Rx */
> > + ring = adapter->rx_ring[qid];
> > + if (!READ_ONCE(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[qid];
> > + if (test_bit(IGB_RING_FLAG_TX_DISABLED, &ring-
> >flags))
> > + return -ENETDOWN;
> > +
> > + if (!READ_ONCE(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)) {
> > + trigger_irq_rx = true;
> > + eics |= eics_rx;
> > + }
> > + if (!napi_if_scheduled_mark_missed(tx_napi)) {
> > + trigger_irq_tx = true;
> > + eics |= eics_tx;
> > + }
> > + /* Now we trigger the required irqs for Rx and Tx */
> > + if ((trigger_irq_rx) || (trigger_irq_tx)) {
> > + if (adapter->flags & IGB_FLAG_HAS_MSIX) {
> > + wr32(E1000_EICS, eics);
> > + } else {
> > + if ((trigger_irq_rx) && (trigger_irq_tx))
> > + wr32(E1000_ICS,
> E1000_ICS_RXDMT0 | E1000_ICS_TXDW);
> > + else if (trigger_irq_rx)
> > + wr32(E1000_ICS,
> E1000_ICS_RXDMT0);
> > + else
> > + wr32(E1000_ICS,
> E1000_ICS_TXDW);
> > + }
> > + }
> > + return 0;
> > + }
> > + } else if (flags & XDP_WAKEUP_TX) {
> > + /* Get the ring params from Tx */
> > + ring = adapter->tx_ring[qid];
> > + if (test_bit(IGB_RING_FLAG_TX_DISABLED, &ring->flags))
> > + return -ENETDOWN;
> > + } else if (flags & XDP_WAKEUP_RX) {
> > + /* Get the ring params from Rx */
> > + ring = adapter->rx_ring[qid];
> > + } else {
> > + /* Invalid Flags */
> > + return -EINVAL;
> > + }
>
> This is too complicated IMHO. Wouldn't something like this work:
> - if wakeup rx, pick napi from rx ring's q_vector
> * napi_if_scheduled_mark_missed() logic that exists in igc_xsk_wakeup()
>
> repeat for tx; if IGB_FLAG_QUEUE_PAIRS then the branch of second
> napi_if_scheduled_mark_missed() call would not be executed as we had
> previously marked the missed bit in napi state;
Okay. I hope I understood the change you are suggesting. Does the code below reflect what you have in mind?
int igb_xsk_wakeup(struct net_device *dev, u32 qid, u32 flags)
{
struct igb_adapter *adapter = netdev_priv(dev);
struct e1000_hw *hw = &adapter->hw;
struct igb_ring *ring;
struct igb_q_vector *q_vector;
struct napi_struct *rx_napi;
struct napi_struct *tx_napi;
bool trigger_irq_tx = false;
bool trigger_irq_rx = false;
u32 eics_tx = 0;
u32 eics_rx = 0;
u32 eics = 0;
if (test_bit(__IGB_DOWN, &adapter->state))
return -ENETDOWN;
if (!igb_xdp_is_enabled(adapter))
return -EINVAL;
/* Check if queue_id is valid. Tx and Rx queue numbers are always same */
if (qid >= adapter->num_rx_queues)
return -EINVAL;
/* Check if flags are valid */
if (!(flags & XDP_WAKEUP_RX) && !(flags & XDP_WAKEUP_TX))
return -EINVAL;
if (flags & XDP_WAKEUP_RX) {
/* IRQ trigger preparation for Rx */
ring = adapter->rx_ring[qid];
if (!READ_ONCE(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;
trigger_irq_rx = true;
}
if (flags & XDP_WAKEUP_TX) {
if (adapter->flags & IGB_FLAG_QUEUE_PAIRS) {
/* In queue-pair mode, rx_ring and tx_ring share the same q_vector,
* so a single IRQ trigger will wake both RX and TX processing
*/
} else {
/* IRQ trigger preparation for Tx */
ring = adapter->tx_ring[qid];
if (test_bit(IGB_RING_FLAG_TX_DISABLED, &ring->flags))
return -ENETDOWN;
if (!READ_ONCE(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;
trigger_irq_tx = true;
}
}
/* All error checks are finished. Check and update napi states for rx and tx */
if (trigger_irq_rx) {
if (!napi_if_scheduled_mark_missed(rx_napi)) {
eics |= eics_rx;
}
}
if (trigger_irq_tx) {
if (!napi_if_scheduled_mark_missed(tx_napi)) {
eics |= eics_tx;
}
}
/* Now we trigger the required irqs for Rx and Tx */
if ((trigger_irq_rx) || (trigger_irq_tx)) {
if (adapter->flags & IGB_FLAG_HAS_MSIX) {
wr32(E1000_EICS, eics);
} else {
if ((trigger_irq_rx) && (trigger_irq_tx))
wr32(E1000_ICS,
E1000_ICS_RXDMT0 | E1000_ICS_TXDW);
else if (trigger_irq_rx)
wr32(E1000_ICS, E1000_ICS_RXDMT0);
else
wr32(E1000_ICS, E1000_ICS_TXDW);
}
}
return 0;
}
>
> >
> > if (!READ_ONCE(ring->xsk_pool))
> > return -EINVAL;
> > @@ -551,10 +620,15 @@ int igb_xsk_wakeup(struct net_device *dev, u32 qid,
> u32 flags)
> > if (!napi_if_scheduled_mark_missed(&ring->q_vector->napi)) {
> > /* Cause software interrupt */
> > if (adapter->flags & IGB_FLAG_HAS_MSIX) {
> > - eics |= ring->q_vector->eims_value;
> > + eics = ring->q_vector->eims_value;
> > wr32(E1000_EICS, eics);
> > } else {
> > - wr32(E1000_ICS, E1000_ICS_RXDMT0);
> > + if ((flags & XDP_WAKEUP_RX) && (flags &
> XDP_WAKEUP_TX))
> > + wr32(E1000_ICS, E1000_ICS_RXDMT0 |
> E1000_ICS_TXDW);
> > + else if (flags & XDP_WAKEUP_RX)
> > + wr32(E1000_ICS, E1000_ICS_RXDMT0);
> > + else
> > + wr32(E1000_ICS, E1000_ICS_TXDW);
> > }
> > }
> >
> > --
> > 2.34.1
> >
^ permalink raw reply [flat|nested] 4+ messages in thread
* Re: [Intel-wired-lan] [PATCH iwl-net v4] igb: Fix trigger of incorrect irq in igb_xsk_wakeup
2026-01-09 0:14 ` Maciej Fijalkowski
2026-01-11 14:27 ` Behera, VIVEK via Intel-wired-lan
@ 2026-01-12 11:38 ` Loktionov, Aleksandr
1 sibling, 0 replies; 4+ messages in thread
From: Loktionov, Aleksandr @ 2026-01-12 11:38 UTC (permalink / raw)
To: Fijalkowski, Maciej, Behera, Vivek
Cc: Keller, Jacob E, Nguyen, Anthony L, Kitszel, Przemyslaw,
sriram.yagnaraman@ericsson.com, kurt@linutronix.de,
intel-wired-lan@lists.osuosl.org
> -----Original Message-----
> From: Fijalkowski, Maciej <maciej.fijalkowski@intel.com>
> Sent: Friday, January 9, 2026 1:15 AM
> To: Behera, Vivek <vivek.behera@siemens.com>
> Cc: Loktionov, Aleksandr <aleksandr.loktionov@intel.com>; Keller,
> Jacob E <jacob.e.keller@intel.com>; Nguyen, Anthony L
> <anthony.l.nguyen@intel.com>; Kitszel, Przemyslaw
> <przemyslaw.kitszel@intel.com>; sriram.yagnaraman@ericsson.com;
> kurt@linutronix.de; intel-wired-lan@lists.osuosl.org
> Subject: Re: [PATCH iwl-net v4] igb: Fix trigger of incorrect irq in
> igb_xsk_wakeup
>
> On Mon, Dec 22, 2025 at 12:57:47PM +0100, Vivek Behera wrote:
> > The current implementation in the igb_xsk_wakeup expects the Rx and
> Tx
> > queues to share the same irq. This would lead to triggering of
> > incorrect irq in split irq configuration.
> > This patch addresses this issue which could impact environments with
> 2
> > active cpu cores or when the number of queues is reduced to 2 or
> less
> >
> > cat /proc/interrupts | grep eno2
> > 167: 0 0 0 0 IR-PCI-MSIX-
> 0000:08:00.0
> > 0-edge eno2
> > 168: 0 0 0 0 IR-PCI-MSIX-
> 0000:08:00.0
> > 1-edge eno2-rx-0
> > 169: 0 0 0 0 IR-PCI-MSIX-
> 0000:08:00.0
> > 2-edge eno2-rx-1
> > 170: 0 0 0 0 IR-PCI-MSIX-
> 0000:08:00.0
> > 3-edge eno2-tx-0
> > 171: 0 0 0 0 IR-PCI-MSIX-
> 0000:08:00.0
> > 4-edge eno2-tx-1
> >
> > Furthermore it uses the flags input argument to trigger either rx,
> tx
> > or both rx and tx irqs as specified in the ndo_xsk_wakeup api
> > documentation
> >
> > Fixes: 80f6ccf9f116 ("igb: Introduce XSK data structures and
> helpers")
> > Signed-off-by: Vivek Behera <vivek.behera@siemens.com>
> > Reviewed-by: Aleksandr Loktionov <aleksandr.loktionov@intel.com>
> > ---
> > v1:
> > https://lore.kernel.org/intel-wired-lan/20251212131454.124116-1-
> vivek.
> > behera@siemens.com/
> > v2:
> > https://lore.kernel.org/intel-wired-lan/20251215115416.410619-1-
> vivek.
> > behera@siemens.com/
> > v3:
> > https://lore.kernel.org/intel-wired-lan/20251220114936.140473-1-
> vivek.
> > behera@siemens.com/
> >
> > changelog:
> > v1
> > - Inital description of the Bug and fixes made in the patch
> >
> > v1 -> v2
> > - Handling of RX and TX Wakeup in igc_xsk_wakeup for a split IRQ
> > configuration
> > - Review suggestions by Aleksander: Modified sequence to complete
> all
> > error checks for rx and tx before updating napi states and
> > triggering irqs
> > - Corrected trigger of TX and RX interrupts over E1000_ICS (non msix
> > use case)
> > - Added define for Tx interrupt trigger bit mask for E1000_ICS
> >
> > v2 -> v3
> > - Included applicable feedback and suggestions from igc patch
> > - Fixed logic in updating eics value when both TX and RX need
> wakeup
> >
> > v3 -> v4
> > - Added comments to explain trigerring of both TX and RX with active
> > queue pairs
> > - Fixed check of xsk pools in if statement
> > ---
> > .../net/ethernet/intel/igb/e1000_defines.h | 1 +
> > drivers/net/ethernet/intel/igb/igb_xsk.c | 90
> +++++++++++++++++--
> > 2 files changed, 83 insertions(+), 8 deletions(-)
> >
...
> > + } else {
> > + /* Invalid Flags */
> > + return -EINVAL;
> > + }
>
> This is too complicated IMHO. Wouldn't something like this work:
> - if wakeup rx, pick napi from rx ring's q_vector
> * napi_if_scheduled_mark_missed() logic that exists in
> igc_xsk_wakeup()
>
> repeat for tx; if IGB_FLAG_QUEUE_PAIRS then the branch of second
> napi_if_scheduled_mark_missed() call would not be executed as we had
> previously marked the missed bit in napi state;
>
I agree, it's too complicated.
...
> > --
> > 2.34.1
> >
^ permalink raw reply [flat|nested] 4+ messages in thread
end of thread, other threads:[~2026-01-12 11:38 UTC | newest]
Thread overview: 4+ messages (download: mbox.gz follow: Atom feed
-- links below jump to the message on this page --
2025-12-22 11:57 [Intel-wired-lan] [PATCH iwl-net v4] igb: Fix trigger of incorrect irq in igb_xsk_wakeup Vivek Behera via Intel-wired-lan
2026-01-09 0:14 ` Maciej Fijalkowski
2026-01-11 14:27 ` Behera, VIVEK via Intel-wired-lan
2026-01-12 11:38 ` Loktionov, Aleksandr
This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox