提交 28efd208 编写于 作者: D David S. Miller

Merge branch 'sfc-tx-queues'

Íñigo Huguet says:

====================
sfc: Fix lack of XDP TX queues

A change introduced in commit e26ca4b5 ("sfc: reduce the number of
requested xdp ev queues") created a bug in XDP_TX and XDP_REDIRECT
because it unintentionally reduced the number of XDP TX queues, letting
not enough queues to have one per CPU, which leaded to errors if XDP
TX/REDIRECT was done from a high numbered CPU.

This patchs make the following changes:
- Fix the bug mentioned above
- Revert commit 99ba0ea6 ("sfc: adjust efx->xdp_tx_queue_count with
  the real number of initialized queues") which intended to fix a related
  problem, created by mentioned bug, but it's no longer necessary
- Add a new error log message if there are not enough resources to make
  XDP_TX/REDIRECT work

V1 -> V2: keep the calculation of how many tx queues can handle a single
event queue, but apply the "max. tx queues per channel" upper limit.
V2 -> V3: WARN_ON if the number of initialized XDP TXQs differs from the
expected.
====================
Signed-off-by: NDavid S. Miller <davem@davemloft.net>
...@@ -152,6 +152,7 @@ static int efx_allocate_msix_channels(struct efx_nic *efx, ...@@ -152,6 +152,7 @@ static int efx_allocate_msix_channels(struct efx_nic *efx,
* maximum size. * maximum size.
*/ */
tx_per_ev = EFX_MAX_EVQ_SIZE / EFX_TXQ_MAX_ENT(efx); tx_per_ev = EFX_MAX_EVQ_SIZE / EFX_TXQ_MAX_ENT(efx);
tx_per_ev = min(tx_per_ev, EFX_MAX_TXQ_PER_CHANNEL);
n_xdp_tx = num_possible_cpus(); n_xdp_tx = num_possible_cpus();
n_xdp_ev = DIV_ROUND_UP(n_xdp_tx, tx_per_ev); n_xdp_ev = DIV_ROUND_UP(n_xdp_tx, tx_per_ev);
...@@ -169,6 +170,8 @@ static int efx_allocate_msix_channels(struct efx_nic *efx, ...@@ -169,6 +170,8 @@ static int efx_allocate_msix_channels(struct efx_nic *efx,
netif_err(efx, drv, efx->net_dev, netif_err(efx, drv, efx->net_dev,
"Insufficient resources for %d XDP event queues (%d other channels, max %d)\n", "Insufficient resources for %d XDP event queues (%d other channels, max %d)\n",
n_xdp_ev, n_channels, max_channels); n_xdp_ev, n_channels, max_channels);
netif_err(efx, drv, efx->net_dev,
"XDP_TX and XDP_REDIRECT will not work on this interface");
efx->n_xdp_channels = 0; efx->n_xdp_channels = 0;
efx->xdp_tx_per_channel = 0; efx->xdp_tx_per_channel = 0;
efx->xdp_tx_queue_count = 0; efx->xdp_tx_queue_count = 0;
...@@ -176,12 +179,14 @@ static int efx_allocate_msix_channels(struct efx_nic *efx, ...@@ -176,12 +179,14 @@ static int efx_allocate_msix_channels(struct efx_nic *efx,
netif_err(efx, drv, efx->net_dev, netif_err(efx, drv, efx->net_dev,
"Insufficient resources for %d XDP TX queues (%d other channels, max VIs %d)\n", "Insufficient resources for %d XDP TX queues (%d other channels, max VIs %d)\n",
n_xdp_tx, n_channels, efx->max_vis); n_xdp_tx, n_channels, efx->max_vis);
netif_err(efx, drv, efx->net_dev,
"XDP_TX and XDP_REDIRECT will not work on this interface");
efx->n_xdp_channels = 0; efx->n_xdp_channels = 0;
efx->xdp_tx_per_channel = 0; efx->xdp_tx_per_channel = 0;
efx->xdp_tx_queue_count = 0; efx->xdp_tx_queue_count = 0;
} else { } else {
efx->n_xdp_channels = n_xdp_ev; efx->n_xdp_channels = n_xdp_ev;
efx->xdp_tx_per_channel = EFX_MAX_TXQ_PER_CHANNEL; efx->xdp_tx_per_channel = tx_per_ev;
efx->xdp_tx_queue_count = n_xdp_tx; efx->xdp_tx_queue_count = n_xdp_tx;
n_channels += n_xdp_ev; n_channels += n_xdp_ev;
netif_dbg(efx, drv, efx->net_dev, netif_dbg(efx, drv, efx->net_dev,
...@@ -891,18 +896,20 @@ int efx_set_channels(struct efx_nic *efx) ...@@ -891,18 +896,20 @@ int efx_set_channels(struct efx_nic *efx)
if (efx_channel_is_xdp_tx(channel)) { if (efx_channel_is_xdp_tx(channel)) {
efx_for_each_channel_tx_queue(tx_queue, channel) { efx_for_each_channel_tx_queue(tx_queue, channel) {
tx_queue->queue = next_queue++; tx_queue->queue = next_queue++;
netif_dbg(efx, drv, efx->net_dev, "Channel %u TXQ %u is XDP %u, HW %u\n",
channel->channel, tx_queue->label,
xdp_queue_number, tx_queue->queue);
/* We may have a few left-over XDP TX /* We may have a few left-over XDP TX
* queues owing to xdp_tx_queue_count * queues owing to xdp_tx_queue_count
* not dividing evenly by EFX_MAX_TXQ_PER_CHANNEL. * not dividing evenly by EFX_MAX_TXQ_PER_CHANNEL.
* We still allocate and probe those * We still allocate and probe those
* TXQs, but never use them. * TXQs, but never use them.
*/ */
if (xdp_queue_number < efx->xdp_tx_queue_count) if (xdp_queue_number < efx->xdp_tx_queue_count) {
netif_dbg(efx, drv, efx->net_dev, "Channel %u TXQ %u is XDP %u, HW %u\n",
channel->channel, tx_queue->label,
xdp_queue_number, tx_queue->queue);
efx->xdp_tx_queues[xdp_queue_number] = tx_queue; efx->xdp_tx_queues[xdp_queue_number] = tx_queue;
xdp_queue_number++; xdp_queue_number++;
}
} }
} else { } else {
efx_for_each_channel_tx_queue(tx_queue, channel) { efx_for_each_channel_tx_queue(tx_queue, channel) {
...@@ -914,8 +921,7 @@ int efx_set_channels(struct efx_nic *efx) ...@@ -914,8 +921,7 @@ int efx_set_channels(struct efx_nic *efx)
} }
} }
} }
if (xdp_queue_number) WARN_ON(xdp_queue_number != efx->xdp_tx_queue_count);
efx->xdp_tx_queue_count = xdp_queue_number;
rc = netif_set_real_num_tx_queues(efx->net_dev, efx->n_tx_channels); rc = netif_set_real_num_tx_queues(efx->net_dev, efx->n_tx_channels);
if (rc) if (rc)
......
Markdown is supported
0% .
You are about to add 0 people to the discussion. Proceed with caution.
先完成此消息的编辑!
想要评论请 注册