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: 492a7e67ff
("IB/IPoIB: Allow setting the device address")
Signed-off-by: Mark Bloch <markb@mellanox.com>
Signed-off-by: Leon Romanovsky <leon@kernel.org>
Signed-off-by: Doug Ledford <dledford@redhat.com>
This commit is contained in:
parent
8e787646fb
commit
9b29953bf8
@ -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)
|
|||||||
|
|
||||||
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)
|
|||||||
}
|
}
|
||||||
|
|
||||||
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)
|
|||||||
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)
|
|||||||
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,
|
|||||||
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,
|
|||||||
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)
|
|||||||
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))
|
||||||
|
Loading…
Reference in New Issue
Block a user