Commit 554a1c34 authored by Vivek Behera's avatar Vivek Behera Committed by Tony Nguyen
Browse files

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: fc9df2a0 ("igc: Enable RX via AF_XDP zero-copy")
Fixes: 15fd021b ("igc: Add Tx hardware timestamp request for AF_XDP zero-copy packet")
Signed-off-by: default avatarVivek Behera <vivek.behera@siemens.com>
Reviewed-by: default avatarJacob Keller <jacob.keller@intel.com>
Reviewed-by: default avatarAleksandr loktinov <aleksandr.loktionov@intel.com>
Reviewed-by: default avatarPiotr Kwapulinski <piotr.kwapulinski@intel.com>
Reviewed-by: default avatarSong Yoong Siang <yoong.siang.song@intel.com>
Tested-by: default avatarAvigail Dahan <avigailx.dahan@intel.com>
Signed-off-by: default avatarTony Nguyen <anthony.l.nguyen@intel.com>
parent d4c13ab3
Loading
Loading
Loading
Loading
+24 −10
Original line number Diff line number Diff line
@@ -6906,28 +6906,29 @@ 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)
static u32 igc_sw_irq_prep(struct igc_q_vector *q_vector)
{
	struct igc_hw *hw = &adapter->hw;
	u32 eics = 0;

	eics |= q_vector->eims_value;
	wr32(IGC_EICS, eics);
	if (!napi_if_scheduled_mark_missed(&q_vector->napi))
		eics = q_vector->eims_value;

	return eics;
}

int igc_xsk_wakeup(struct net_device *dev, u32 queue_id, u32 flags)
{
	struct igc_adapter *adapter = netdev_priv(dev);
	struct igc_q_vector *q_vector;
	struct igc_hw *hw = &adapter->hw;
	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;

@@ -6936,9 +6937,22 @@ int igc_xsk_wakeup(struct net_device *dev, u32 queue_id, u32 flags)
	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);
	if (flags & XDP_WAKEUP_RX)
		eics |= igc_sw_irq_prep(ring->q_vector);

	if (flags & XDP_WAKEUP_TX) {
		/* If IGC_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 RX path, making this TX call a NOP
		 */
		ring = adapter->tx_ring[queue_id];
		eics |= igc_sw_irq_prep(ring->q_vector);
	}

	if (eics)
		/* Cause software interrupt */
		wr32(IGC_EICS, eics);

	return 0;
}
+2 −1
Original line number Diff line number Diff line
@@ -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;
	}