]> git.ipfire.org Git - thirdparty/kernel/stable.git/commitdiff
net: Have netpoll bring-up DSA management interface
authorFlorian Fainelli <f.fainelli@gmail.com>
Tue, 17 Nov 2020 03:52:34 +0000 (19:52 -0800)
committerGreg Kroah-Hartman <gregkh@linuxfoundation.org>
Tue, 24 Nov 2020 11:48:10 +0000 (12:48 +0100)
[ Upstream commit 1532b9778478577152201adbafa7738b1e844868 ]

DSA network devices rely on having their DSA management interface up and
running otherwise their ndo_open() will return -ENETDOWN. Without doing
this it would not be possible to use DSA devices as netconsole when
configured on the command line. These devices also do not utilize the
upper/lower linking so the check about the netpoll device having upper
is not going to be a problem.

The solution adopted here is identical to the one done for
net/ipv4/ipconfig.c with 728c02089a0e ("net: ipv4: handle DSA enabled
master network devices"), with the network namespace scope being
restricted to that of the process configuring netpoll.

Fixes: 04ff53f96a93 ("net: dsa: Add netconsole support")
Tested-by: Vladimir Oltean <olteanv@gmail.com>
Signed-off-by: Florian Fainelli <f.fainelli@gmail.com>
Link: https://lore.kernel.org/r/20201117035236.22658-1-f.fainelli@gmail.com
Signed-off-by: Jakub Kicinski <kuba@kernel.org>
Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
net/core/netpoll.c

index f2610f8f171ca9a911cca827088f0c868840bf9a..2a64de757be9b2238688bcdb93de619f9a7a0d92 100644 (file)
@@ -28,6 +28,7 @@
 #include <linux/slab.h>
 #include <linux/export.h>
 #include <linux/if_vlan.h>
+#include <net/dsa.h>
 #include <net/tcp.h>
 #include <net/udp.h>
 #include <net/addrconf.h>
@@ -661,15 +662,15 @@ EXPORT_SYMBOL_GPL(__netpoll_setup);
 
 int netpoll_setup(struct netpoll *np)
 {
-       struct net_device *ndev = NULL;
+       struct net_device *ndev = NULL, *dev = NULL;
+       struct net *net = current->nsproxy->net_ns;
        struct in_device *in_dev;
        int err;
 
        rtnl_lock();
-       if (np->dev_name) {
-               struct net *net = current->nsproxy->net_ns;
+       if (np->dev_name)
                ndev = __dev_get_by_name(net, np->dev_name);
-       }
+
        if (!ndev) {
                np_err(np, "%s doesn't exist, aborting\n", np->dev_name);
                err = -ENODEV;
@@ -677,6 +678,19 @@ int netpoll_setup(struct netpoll *np)
        }
        dev_hold(ndev);
 
+       /* bring up DSA management network devices up first */
+       for_each_netdev(net, dev) {
+               if (!netdev_uses_dsa(dev))
+                       continue;
+
+               err = dev_change_flags(dev, dev->flags | IFF_UP);
+               if (err < 0) {
+                       np_err(np, "%s failed to open %s\n",
+                              np->dev_name, dev->name);
+                       goto put;
+               }
+       }
+
        if (netdev_master_upper_dev_get(ndev)) {
                np_err(np, "%s is a slave device, aborting\n", np->dev_name);
                err = -EBUSY;