Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
11 changes: 11 additions & 0 deletions src/i40e_ethtool.c
Original file line number Diff line number Diff line change
Expand Up @@ -6508,6 +6508,17 @@ static int i40e_set_channels(struct net_device *dev,
if (count > i40e_max_channels(vsi))
return -EINVAL;

/* verify XDP program compatibility with requested channel count */
if (i40e_enabled_xdp_vsi(vsi) && count < num_online_cpus()) {
dev_warn(&pf->pdev->dev,
"XDP enabled: reducing channels (%u) below online CPUs (%u) may cause performance issues\n",
count, num_online_cpus());
dev_info(&pf->pdev->dev,
"Consider using channels >= %u for optimal XDP performance\n",
num_online_cpus());
/* Warning only - allow the configuration but inform user */
}

/* verify that the number of channels does not invalidate any current
* flow director rules
*/
Expand Down
41 changes: 38 additions & 3 deletions src/i40e_txrx.c
Original file line number Diff line number Diff line change
Expand Up @@ -4707,6 +4707,32 @@ netdev_tx_t i40e_lan_xmit_frame(struct sk_buff *skb, struct net_device *netdev)
}

#ifdef HAVE_XDP_SUPPORT
/**
* i40e_xdp_queue_index - Get optimal queue index for XDP transmit
* @vsi: VSI structure
*
* Returns a valid queue index that maps current CPU to available queue pairs.
* Uses modulo operation to ensure index never exceeds num_queue_pairs.
**/
static inline unsigned int i40e_xdp_queue_index(struct i40e_vsi *vsi)
{
unsigned int cpu_id = smp_processor_id();
unsigned int queue_index = cpu_id % vsi->num_queue_pairs;

/* Warn once if CPU count exceeds queue count - suboptimal configuration */
if (unlikely(cpu_id >= vsi->num_queue_pairs)) {
static bool warned = false;
if (!warned) {
netdev_warn(vsi->netdev,
"XDP performance notice: CPU count (%u) exceeds queue count (%u). Consider using ethtool -L %s combined %u for optimal performance\n",
num_online_cpus(), vsi->num_queue_pairs, vsi->netdev->name, num_online_cpus());
warned = true;
}
}

return queue_index;
}

/**
* i40e_xdp_xmit - Implements ndo_xdp_xmit
* @dev: netdev
Expand All @@ -4728,8 +4754,8 @@ int i40e_xdp_xmit(struct net_device *dev, struct xdp_buff *xdp)
#endif
{
struct i40e_netdev_priv *np = netdev_priv(dev);
unsigned int queue_index = smp_processor_id();
struct i40e_vsi *vsi = np->vsi;
unsigned int queue_index = i40e_xdp_queue_index(vsi);
struct i40e_pf *pf = vsi->back;
#ifdef HAVE_XDP_FRAME_STRUCT
struct i40e_ring *xdp_ring;
Expand All @@ -4741,8 +4767,17 @@ int i40e_xdp_xmit(struct net_device *dev, struct xdp_buff *xdp)
if (test_bit(__I40E_VSI_DOWN, vsi->state))
return -ENETDOWN;

if (!i40e_enabled_xdp_vsi(vsi) || queue_index >= vsi->num_queue_pairs ||
test_bit(__I40E_CONFIG_BUSY, pf->state))
if (!i40e_enabled_xdp_vsi(vsi))
return -ENXIO;

if (unlikely(queue_index >= vsi->num_queue_pairs)) {
/* This should never happen with fixed queue mapping, but keep as safety check */
netdev_err(dev, "BUG: XDP queue_index %u >= num_queue_pairs %u (CPU %u) - driver bug!\n",
queue_index, vsi->num_queue_pairs, smp_processor_id());
return -ENXIO;
}

if (test_bit(__I40E_CONFIG_BUSY, pf->state))
return -ENXIO;
#ifdef HAVE_XDP_FRAME_STRUCT
if (unlikely(flags & ~XDP_XMIT_FLAGS_MASK))
Expand Down