Donate to e Foundation | Murena handsets with /e/OS | Own a part of Murena! Learn more

Commit 9b29953b authored by Mark Bloch's avatar Mark Bloch Committed by Doug Ledford
Browse files

IB/IPoIB: Disable bottom half when dealing with device address



Align locking usage when touching device address with rest
of the kernel. Lock the bottom half when doing so using
netif_addr_lock_bh.

This also solves the following case as reported by lockdep:
	CPU0                    CPU1
	----                    ----
lock(_xmit_INFINIBAND);
				local_irq_disable();
				lock(&(&mc->mca_lock)->rlock);
				lock(_xmit_INFINIBAND);
<Interrupt>
lock(&(&mc->mca_lock)->rlock);

*** DEADLOCK ***

Fixes: 492a7e67 ("IB/IPoIB: Allow setting the device address")
Signed-off-by: default avatarMark Bloch <markb@mellanox.com>
Signed-off-by: default avatarLeon Romanovsky <leon@kernel.org>
Signed-off-by: default avatarDoug Ledford <dledford@redhat.com>
parent 8e787646
Loading
Loading
Loading
Loading
+4 −4
Original line number Diff line number Diff line
@@ -1015,7 +1015,7 @@ static bool ipoib_dev_addr_changed_valid(struct ipoib_dev_priv *priv)
	if (ib_query_gid(priv->ca, priv->port, 0, &gid0, NULL))
		return false;

	netif_addr_lock(priv->dev);
	netif_addr_lock_bh(priv->dev);

	/* The subnet prefix may have changed, update it now so we won't have
	 * to do it later
@@ -1026,12 +1026,12 @@ static bool ipoib_dev_addr_changed_valid(struct ipoib_dev_priv *priv)

	search_gid.global.interface_id = priv->local_gid.global.interface_id;

	netif_addr_unlock(priv->dev);
	netif_addr_unlock_bh(priv->dev);

	err = ib_find_gid(priv->ca, &search_gid, IB_GID_TYPE_IB,
			  priv->dev, &port, &index);

	netif_addr_lock(priv->dev);
	netif_addr_lock_bh(priv->dev);

	if (search_gid.global.interface_id !=
	    priv->local_gid.global.interface_id)
@@ -1092,7 +1092,7 @@ static bool ipoib_dev_addr_changed_valid(struct ipoib_dev_priv *priv)
	}

out:
	netif_addr_unlock(priv->dev);
	netif_addr_unlock_bh(priv->dev);

	return ret;
}
+4 −4
Original line number Diff line number Diff line
@@ -1851,7 +1851,7 @@ static void set_base_guid(struct ipoib_dev_priv *priv, union ib_gid *gid)
	struct ipoib_dev_priv *child_priv;
	struct net_device *netdev = priv->dev;

	netif_addr_lock(netdev);
	netif_addr_lock_bh(netdev);

	memcpy(&priv->local_gid.global.interface_id,
	       &gid->global.interface_id,
@@ -1859,7 +1859,7 @@ static void set_base_guid(struct ipoib_dev_priv *priv, union ib_gid *gid)
	memcpy(netdev->dev_addr + 4, &priv->local_gid, sizeof(priv->local_gid));
	clear_bit(IPOIB_FLAG_DEV_ADDR_SET, &priv->flags);

	netif_addr_unlock(netdev);
	netif_addr_unlock_bh(netdev);

	if (!test_bit(IPOIB_FLAG_SUBINTERFACE, &priv->flags)) {
		down_read(&priv->vlan_rwsem);
@@ -1875,7 +1875,7 @@ static int ipoib_check_lladdr(struct net_device *dev,
	union ib_gid *gid = (union ib_gid *)(ss->__data + 4);
	int ret = 0;

	netif_addr_lock(dev);
	netif_addr_lock_bh(dev);

	/* Make sure the QPN, reserved and subnet prefix match the current
	 * lladdr, it also makes sure the lladdr is unicast.
@@ -1885,7 +1885,7 @@ static int ipoib_check_lladdr(struct net_device *dev,
	    gid->global.interface_id == 0)
		ret = -EINVAL;

	netif_addr_unlock(dev);
	netif_addr_unlock_bh(dev);

	return ret;
}
+3 −3
Original line number Diff line number Diff line
@@ -582,13 +582,13 @@ void ipoib_mcast_join_task(struct work_struct *work)
		return;
	}
	priv->local_lid = port_attr.lid;
	netif_addr_lock(dev);
	netif_addr_lock_bh(dev);

	if (!test_bit(IPOIB_FLAG_DEV_ADDR_SET, &priv->flags)) {
		netif_addr_unlock(dev);
		netif_addr_unlock_bh(dev);
		return;
	}
	netif_addr_unlock(dev);
	netif_addr_unlock_bh(dev);

	spin_lock_irq(&priv->lock);
	if (!test_bit(IPOIB_FLAG_OPER_UP, &priv->flags))