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

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
...@@ -1015,7 +1015,7 @@ static bool ipoib_dev_addr_changed_valid(struct ipoib_dev_priv *priv) ...@@ -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)) if (ib_query_gid(priv->ca, priv->port, 0, &gid0, NULL))
return false; 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 /* The subnet prefix may have changed, update it now so we won't have
* to do it later * to do it later
...@@ -1026,12 +1026,12 @@ static bool ipoib_dev_addr_changed_valid(struct ipoib_dev_priv *priv) ...@@ -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; 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, err = ib_find_gid(priv->ca, &search_gid, IB_GID_TYPE_IB,
priv->dev, &port, &index); priv->dev, &port, &index);
netif_addr_lock(priv->dev); netif_addr_lock_bh(priv->dev);
if (search_gid.global.interface_id != if (search_gid.global.interface_id !=
priv->local_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) ...@@ -1092,7 +1092,7 @@ static bool ipoib_dev_addr_changed_valid(struct ipoib_dev_priv *priv)
} }
out: out:
netif_addr_unlock(priv->dev); netif_addr_unlock_bh(priv->dev);
return ret; return ret;
} }
......
...@@ -1851,7 +1851,7 @@ static void set_base_guid(struct ipoib_dev_priv *priv, union ib_gid *gid) ...@@ -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 ipoib_dev_priv *child_priv;
struct net_device *netdev = priv->dev; struct net_device *netdev = priv->dev;
netif_addr_lock(netdev); netif_addr_lock_bh(netdev);
memcpy(&priv->local_gid.global.interface_id, memcpy(&priv->local_gid.global.interface_id,
&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) ...@@ -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)); memcpy(netdev->dev_addr + 4, &priv->local_gid, sizeof(priv->local_gid));
clear_bit(IPOIB_FLAG_DEV_ADDR_SET, &priv->flags); 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)) { if (!test_bit(IPOIB_FLAG_SUBINTERFACE, &priv->flags)) {
down_read(&priv->vlan_rwsem); down_read(&priv->vlan_rwsem);
...@@ -1875,7 +1875,7 @@ static int ipoib_check_lladdr(struct net_device *dev, ...@@ -1875,7 +1875,7 @@ static int ipoib_check_lladdr(struct net_device *dev,
union ib_gid *gid = (union ib_gid *)(ss->__data + 4); union ib_gid *gid = (union ib_gid *)(ss->__data + 4);
int ret = 0; int ret = 0;
netif_addr_lock(dev); netif_addr_lock_bh(dev);
/* Make sure the QPN, reserved and subnet prefix match the current /* Make sure the QPN, reserved and subnet prefix match the current
* lladdr, it also makes sure the lladdr is unicast. * lladdr, it also makes sure the lladdr is unicast.
...@@ -1885,7 +1885,7 @@ static int ipoib_check_lladdr(struct net_device *dev, ...@@ -1885,7 +1885,7 @@ static int ipoib_check_lladdr(struct net_device *dev,
gid->global.interface_id == 0) gid->global.interface_id == 0)
ret = -EINVAL; ret = -EINVAL;
netif_addr_unlock(dev); netif_addr_unlock_bh(dev);
return ret; return ret;
} }
......
...@@ -582,13 +582,13 @@ void ipoib_mcast_join_task(struct work_struct *work) ...@@ -582,13 +582,13 @@ void ipoib_mcast_join_task(struct work_struct *work)
return; return;
} }
priv->local_lid = port_attr.lid; 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)) { if (!test_bit(IPOIB_FLAG_DEV_ADDR_SET, &priv->flags)) {
netif_addr_unlock(dev); netif_addr_unlock_bh(dev);
return; return;
} }
netif_addr_unlock(dev); netif_addr_unlock_bh(dev);
spin_lock_irq(&priv->lock); spin_lock_irq(&priv->lock);
if (!test_bit(IPOIB_FLAG_OPER_UP, &priv->flags)) if (!test_bit(IPOIB_FLAG_OPER_UP, &priv->flags))
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment