IB/ipoib: Grab rtnl lock on heavy flush when calling ndo_open/stop
authorAlex Vesker <valex@mellanox.com>
Tue, 10 Oct 2017 07:36:41 +0000 (10:36 +0300)
committerGreg Kroah-Hartman <gregkh@linuxfoundation.org>
Wed, 20 Dec 2017 09:10:37 +0000 (10:10 +0100)
[ Upstream commit b4b678b06f6eef18bff44a338c01870234db0bc9 ]

When ndo_open and ndo_stop are called RTNL lock should be held.
In this specific case ipoib_ib_dev_open calls the offloaded ndo_open
which re-sets the number of TX queue assuming RTNL lock is held.
Since RTNL lock is not held, RTNL assert will fail.

Signed-off-by: Alex Vesker <valex@mellanox.com>
Signed-off-by: Sasha Levin <alexander.levin@verizon.com>
Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
drivers/infiniband/ulp/ipoib/ipoib_ib.c

index 6cd61638b44142029b85d0f057b8d04c6b2138c6..c97384c914a42a94ac829cecd7751c9c56b817f3 100644 (file)
@@ -1203,10 +1203,15 @@ static void __ipoib_ib_dev_flush(struct ipoib_dev_priv *priv,
                ipoib_ib_dev_down(dev);
 
        if (level == IPOIB_FLUSH_HEAVY) {
+               rtnl_lock();
                if (test_bit(IPOIB_FLAG_INITIALIZED, &priv->flags))
                        ipoib_ib_dev_stop(dev);
-               if (ipoib_ib_dev_open(dev) != 0)
+
+               result = ipoib_ib_dev_open(dev);
+               rtnl_unlock();
+               if (result)
                        return;
+
                if (netif_queue_stopped(dev))
                        netif_start_queue(dev);
        }