summaryrefslogtreecommitdiffstats
path: root/drivers
diff options
context:
space:
mode:
authorPieter Jansen van Vuuren <pieter.jansen-van-vuuren@amd.com>2023-05-24 10:36:38 +0100
committerDavid S. Miller <davem@davemloft.net>2023-05-26 10:15:30 +0100
commitca7d05007d0a95615a51cb5a624775db8c450f43 (patch)
treee634238e6ec4188f041cbfbb87cb6b81c7a0dfa7 /drivers
parentc857946a4e262e0f798fe7625fadf85bf1190fc4 (diff)
downloadlinux-stable-ca7d05007d0a95615a51cb5a624775db8c450f43.tar.gz
linux-stable-ca7d05007d0a95615a51cb5a624775db8c450f43.tar.bz2
linux-stable-ca7d05007d0a95615a51cb5a624775db8c450f43.zip
sfc: handle VI shortage on ef100 by readjusting the channels
When fewer VIs are allocated than what is allowed we can readjust the channels by calling efx_mcdi_alloc_vis() again. Signed-off-by: Pieter Jansen van Vuuren <pieter.jansen-van-vuuren@amd.com> Reviewed-by: Martin Habets <habetsm.xilinx@gmail.com> Reviewed-by: Simon Horman <simon.horman@corigine.com> Reviewed-by: Edward Cree <ecree.xilinx@gmail.com> Signed-off-by: David S. Miller <davem@davemloft.net>
Diffstat (limited to 'drivers')
-rw-r--r--drivers/net/ethernet/sfc/ef100_netdev.c51
1 files changed, 45 insertions, 6 deletions
diff --git a/drivers/net/ethernet/sfc/ef100_netdev.c b/drivers/net/ethernet/sfc/ef100_netdev.c
index be395cd8770b..274f3a2562ad 100644
--- a/drivers/net/ethernet/sfc/ef100_netdev.c
+++ b/drivers/net/ethernet/sfc/ef100_netdev.c
@@ -40,19 +40,26 @@ static int ef100_alloc_vis(struct efx_nic *efx, unsigned int *allocated_vis)
unsigned int tx_vis = efx->n_tx_channels + efx->n_extra_tx_channels;
unsigned int rx_vis = efx->n_rx_channels;
unsigned int min_vis, max_vis;
+ int rc;
EFX_WARN_ON_PARANOID(efx->tx_queues_per_channel != 1);
tx_vis += efx->n_xdp_channels * efx->xdp_tx_per_channel;
max_vis = max(rx_vis, tx_vis);
- /* Currently don't handle resource starvation and only accept
- * our maximum needs and no less.
+ /* We require at least a single complete TX channel worth of queues. */
+ min_vis = efx->tx_queues_per_channel;
+
+ rc = efx_mcdi_alloc_vis(efx, min_vis, max_vis,
+ NULL, allocated_vis);
+
+ /* We retry allocating VIs by reallocating channels when we have not
+ * been able to allocate the maximum VIs.
*/
- min_vis = max_vis;
+ if (!rc && *allocated_vis < max_vis)
+ rc = -EAGAIN;
- return efx_mcdi_alloc_vis(efx, min_vis, max_vis,
- NULL, allocated_vis);
+ return rc;
}
static int ef100_remap_bar(struct efx_nic *efx, int max_vis)
@@ -133,9 +140,41 @@ static int ef100_net_open(struct net_device *net_dev)
goto fail;
rc = ef100_alloc_vis(efx, &allocated_vis);
- if (rc)
+ if (rc && rc != -EAGAIN)
goto fail;
+ /* Try one more time but with the maximum number of channels
+ * equal to the allocated VIs, which would more likely succeed.
+ */
+ if (rc == -EAGAIN) {
+ rc = efx_mcdi_free_vis(efx);
+ if (rc)
+ goto fail;
+
+ efx_remove_interrupts(efx);
+ efx->max_channels = allocated_vis;
+
+ rc = efx_probe_interrupts(efx);
+ if (rc)
+ goto fail;
+
+ rc = efx_set_channels(efx);
+ if (rc)
+ goto fail;
+
+ rc = ef100_alloc_vis(efx, &allocated_vis);
+ if (rc && rc != -EAGAIN)
+ goto fail;
+
+ /* It should be very unlikely that we failed here again, but in
+ * such a case we return ENOSPC.
+ */
+ if (rc == -EAGAIN) {
+ rc = -ENOSPC;
+ goto fail;
+ }
+ }
+
rc = efx_probe_channels(efx);
if (rc)
return rc;