Skip to content

Commit 5f08cd3

Browse files
shailend-gkuba-moo
authored andcommitted
gve: Alloc before freeing when adjusting queues
Previously, existing queues were being freed before the resources for the new queues were being allocated. This would take down the interface if someone were to attempt to change queue counts under a resource crunch. Signed-off-by: Shailend Chand <[email protected]> Reviewed-by: Willem de Bruijn <[email protected]> Reviewed-by: Jeroen de Borst <[email protected]> Link: https://lore.kernel.org/r/[email protected] Signed-off-by: Jakub Kicinski <[email protected]>
1 parent 92a6d7a commit 5f08cd3

File tree

1 file changed

+67
-22
lines changed

1 file changed

+67
-22
lines changed

drivers/net/ethernet/google/gve/gve_main.c

Lines changed: 67 additions & 22 deletions
Original file line numberDiff line numberDiff line change
@@ -1869,42 +1869,87 @@ static int gve_xdp(struct net_device *dev, struct netdev_bpf *xdp)
18691869
}
18701870
}
18711871

1872+
static int gve_adjust_config(struct gve_priv *priv,
1873+
struct gve_qpls_alloc_cfg *qpls_alloc_cfg,
1874+
struct gve_tx_alloc_rings_cfg *tx_alloc_cfg,
1875+
struct gve_rx_alloc_rings_cfg *rx_alloc_cfg)
1876+
{
1877+
int err;
1878+
1879+
/* Allocate resources for the new confiugration */
1880+
err = gve_queues_mem_alloc(priv, qpls_alloc_cfg,
1881+
tx_alloc_cfg, rx_alloc_cfg);
1882+
if (err) {
1883+
netif_err(priv, drv, priv->dev,
1884+
"Adjust config failed to alloc new queues");
1885+
return err;
1886+
}
1887+
1888+
/* Teardown the device and free existing resources */
1889+
err = gve_close(priv->dev);
1890+
if (err) {
1891+
netif_err(priv, drv, priv->dev,
1892+
"Adjust config failed to close old queues");
1893+
gve_queues_mem_free(priv, qpls_alloc_cfg,
1894+
tx_alloc_cfg, rx_alloc_cfg);
1895+
return err;
1896+
}
1897+
1898+
/* Bring the device back up again with the new resources. */
1899+
err = gve_queues_start(priv, qpls_alloc_cfg,
1900+
tx_alloc_cfg, rx_alloc_cfg);
1901+
if (err) {
1902+
netif_err(priv, drv, priv->dev,
1903+
"Adjust config failed to start new queues, !!! DISABLING ALL QUEUES !!!\n");
1904+
/* No need to free on error: ownership of resources is lost after
1905+
* calling gve_queues_start.
1906+
*/
1907+
gve_turndown(priv);
1908+
return err;
1909+
}
1910+
1911+
return 0;
1912+
}
1913+
18721914
int gve_adjust_queues(struct gve_priv *priv,
18731915
struct gve_queue_config new_rx_config,
18741916
struct gve_queue_config new_tx_config)
18751917
{
1918+
struct gve_tx_alloc_rings_cfg tx_alloc_cfg = {0};
1919+
struct gve_rx_alloc_rings_cfg rx_alloc_cfg = {0};
1920+
struct gve_qpls_alloc_cfg qpls_alloc_cfg = {0};
1921+
struct gve_qpl_config new_qpl_cfg;
18761922
int err;
18771923

1878-
if (netif_carrier_ok(priv->dev)) {
1879-
/* To make this process as simple as possible we teardown the
1880-
* device, set the new configuration, and then bring the device
1881-
* up again.
1882-
*/
1883-
err = gve_close(priv->dev);
1884-
/* we have already tried to reset in close,
1885-
* just fail at this point
1886-
*/
1887-
if (err)
1888-
return err;
1889-
priv->tx_cfg = new_tx_config;
1890-
priv->rx_cfg = new_rx_config;
1924+
gve_get_curr_alloc_cfgs(priv, &qpls_alloc_cfg,
1925+
&tx_alloc_cfg, &rx_alloc_cfg);
18911926

1892-
err = gve_open(priv->dev);
1893-
if (err)
1894-
goto err;
1927+
/* qpl_cfg is not read-only, it contains a map that gets updated as
1928+
* rings are allocated, which is why we cannot use the yet unreleased
1929+
* one in priv.
1930+
*/
1931+
qpls_alloc_cfg.qpl_cfg = &new_qpl_cfg;
1932+
tx_alloc_cfg.qpl_cfg = &new_qpl_cfg;
1933+
rx_alloc_cfg.qpl_cfg = &new_qpl_cfg;
1934+
1935+
/* Relay the new config from ethtool */
1936+
qpls_alloc_cfg.tx_cfg = &new_tx_config;
1937+
tx_alloc_cfg.qcfg = &new_tx_config;
1938+
rx_alloc_cfg.qcfg_tx = &new_tx_config;
1939+
qpls_alloc_cfg.rx_cfg = &new_rx_config;
1940+
rx_alloc_cfg.qcfg = &new_rx_config;
1941+
tx_alloc_cfg.num_rings = new_tx_config.num_queues;
18951942

1896-
return 0;
1943+
if (netif_carrier_ok(priv->dev)) {
1944+
err = gve_adjust_config(priv, &qpls_alloc_cfg,
1945+
&tx_alloc_cfg, &rx_alloc_cfg);
1946+
return err;
18971947
}
18981948
/* Set the config for the next up. */
18991949
priv->tx_cfg = new_tx_config;
19001950
priv->rx_cfg = new_rx_config;
19011951

19021952
return 0;
1903-
err:
1904-
netif_err(priv, drv, priv->dev,
1905-
"Adjust queues failed! !!! DISABLING ALL QUEUES !!!\n");
1906-
gve_turndown(priv);
1907-
return err;
19081953
}
19091954

19101955
static void gve_turndown(struct gve_priv *priv)

0 commit comments

Comments
 (0)