mirror of
https://github.com/torvalds/linux.git
synced 2026-03-08 01:24:47 +01:00
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:fc9df2a0b5("igc: Enable RX via AF_XDP zero-copy") Fixes:15fd021bc4("igc: Add Tx hardware timestamp request for AF_XDP zero-copy packet") Signed-off-by: Vivek Behera <vivek.behera@siemens.com> Reviewed-by: Jacob Keller <jacob.keller@intel.com> Reviewed-by: Aleksandr loktinov <aleksandr.loktionov@intel.com> Reviewed-by: Piotr Kwapulinski <piotr.kwapulinski@intel.com> Reviewed-by: Song Yoong Siang <yoong.siang.song@intel.com> Tested-by: Avigail Dahan <avigailx.dahan@intel.com> Signed-off-by: Tony Nguyen <anthony.l.nguyen@intel.com>
This commit is contained in:
parent
d4c13ab362
commit
554a1c34c1
2 changed files with 26 additions and 11 deletions
|
|
@ -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;
|
||||
}
|
||||
|
|
|
|||
|
|
@ -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;
|
||||
}
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue