igb: Fix trigger of incorrect irq in igb_xsk_wakeup

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: 80f6ccf9f1 ("igb: Introduce XSK data structures and helpers")
Signed-off-by: Vivek Behera <vivek.behera@siemens.com>
Reviewed-by: Aleksandr Loktionov <aleksandr.loktionov@intel.com>
Suggested-by: Maciej Fijalkowski <maciej.fijalkowski@intel.com>
Acked-by: Maciej Fijalkowski <maciej.fijalkowski@intel.com>
Tested-by: Saritha Sanigani <sarithax.sanigani@intel.com> (A Contingent Worker at Intel)
Signed-off-by: Tony Nguyen <anthony.l.nguyen@intel.com>
This commit is contained in:
Vivek Behera 2026-01-22 15:16:52 +01:00 committed by Tony Nguyen
parent b848521701
commit d4c13ab362

View file

@ -524,6 +524,16 @@ bool igb_xmit_zc(struct igb_ring *tx_ring, struct xsk_buff_pool *xsk_pool)
return nb_pkts < budget;
}
static u32 igb_sw_irq_prep(struct igb_q_vector *q_vector)
{
u32 eics = 0;
if (!napi_if_scheduled_mark_missed(&q_vector->napi))
eics = q_vector->eims_value;
return eics;
}
int igb_xsk_wakeup(struct net_device *dev, u32 qid, u32 flags)
{
struct igb_adapter *adapter = netdev_priv(dev);
@ -542,20 +552,32 @@ int igb_xsk_wakeup(struct net_device *dev, u32 qid, u32 flags)
ring = adapter->tx_ring[qid];
if (test_bit(IGB_RING_FLAG_TX_DISABLED, &ring->flags))
return -ENETDOWN;
if (!READ_ONCE(ring->xsk_pool))
return -EINVAL;
if (!napi_if_scheduled_mark_missed(&ring->q_vector->napi)) {
if (flags & XDP_WAKEUP_TX) {
if (test_bit(IGB_RING_FLAG_TX_DISABLED, &ring->flags))
return -ENETDOWN;
eics |= igb_sw_irq_prep(ring->q_vector);
}
if (flags & XDP_WAKEUP_RX) {
/* If IGB_FLAG_QUEUE_PAIRS is active, the q_vector
* and NAPI is shared between RX and TX.
* If NAPI is already running it would be marked as missed
* from the TX path, making this RX call a NOP
*/
ring = adapter->rx_ring[qid];
eics |= igb_sw_irq_prep(ring->q_vector);
}
if (eics) {
/* Cause software interrupt */
if (adapter->flags & IGB_FLAG_HAS_MSIX) {
eics |= ring->q_vector->eims_value;
if (adapter->flags & IGB_FLAG_HAS_MSIX)
wr32(E1000_EICS, eics);
} else {
else
wr32(E1000_ICS, E1000_ICS_RXDMT0);
}
}
return 0;