net: ethernet: stmicro: stmmac: permit MTU change with interface up
authorChristian Marangi <ansuelsmth@gmail.com>
Sat, 23 Jul 2022 14:29:33 +0000 (16:29 +0200)
committerJakub Kicinski <kuba@kernel.org>
Tue, 26 Jul 2022 02:38:57 +0000 (19:38 -0700)
Remove the limitation where the interface needs to be down to change
MTU by releasing and opening the stmmac driver to set the new MTU.
Also call the set_filter function to correctly init the port.
This permits to remove the EBUSY error while the ethernet port is
running permitting a correct MTU change if for example a DSA request
a MTU change for a switch CPU port.

Signed-off-by: Christian Marangi <ansuelsmth@gmail.com>
Signed-off-by: Jakub Kicinski <kuba@kernel.org>
drivers/net/ethernet/stmicro/stmmac/stmmac_main.c

index 81bbc8a..070b5ef 100644 (file)
@@ -5551,18 +5551,15 @@ static int stmmac_change_mtu(struct net_device *dev, int new_mtu)
 {
        struct stmmac_priv *priv = netdev_priv(dev);
        int txfifosz = priv->plat->tx_fifo_size;
+       struct stmmac_dma_conf *dma_conf;
        const int mtu = new_mtu;
+       int ret;
 
        if (txfifosz == 0)
                txfifosz = priv->dma_cap.tx_fifo_size;
 
        txfifosz /= priv->plat->tx_queues_to_use;
 
-       if (netif_running(dev)) {
-               netdev_err(priv->dev, "must be stopped to change its MTU\n");
-               return -EBUSY;
-       }
-
        if (stmmac_xdp_is_enabled(priv) && new_mtu > ETH_DATA_LEN) {
                netdev_dbg(priv->dev, "Jumbo frames not supported for XDP\n");
                return -EINVAL;
@@ -5574,8 +5571,29 @@ static int stmmac_change_mtu(struct net_device *dev, int new_mtu)
        if ((txfifosz < new_mtu) || (new_mtu > BUF_SIZE_16KiB))
                return -EINVAL;
 
-       dev->mtu = mtu;
+       if (netif_running(dev)) {
+               netdev_dbg(priv->dev, "restarting interface to change its MTU\n");
+               /* Try to allocate the new DMA conf with the new mtu */
+               dma_conf = stmmac_setup_dma_desc(priv, mtu);
+               if (IS_ERR(dma_conf)) {
+                       netdev_err(priv->dev, "failed allocating new dma conf for new MTU %d\n",
+                                  mtu);
+                       return PTR_ERR(dma_conf);
+               }
 
+               stmmac_release(dev);
+
+               ret = __stmmac_open(dev, dma_conf);
+               kfree(dma_conf);
+               if (ret) {
+                       netdev_err(priv->dev, "failed reopening the interface after MTU change\n");
+                       return ret;
+               }
+
+               stmmac_set_rx_mode(dev);
+       }
+
+       dev->mtu = mtu;
        netdev_update_features(dev);
 
        return 0;