diff options
author | Mark Bloch <markb@mellanox.com> | 2016-06-04 08:15:22 -0400 |
---|---|---|
committer | Doug Ledford <dledford@redhat.com> | 2016-06-07 09:50:54 -0400 |
commit | 9b29953bf8ca23944c5e00dcc15ad7bd9fecdd4e (patch) | |
tree | d6f45a244de0dfe32726d5ccafaf19077e4e30ac /drivers/infiniband | |
parent | 8e787646fbce895c20c4433973e90af90e1c6a28 (diff) |
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: 492a7e67ff83 ("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>
Diffstat (limited to 'drivers/infiniband')
-rw-r--r-- | drivers/infiniband/ulp/ipoib/ipoib_ib.c | 8 | ||||
-rw-r--r-- | drivers/infiniband/ulp/ipoib/ipoib_main.c | 8 | ||||
-rw-r--r-- | drivers/infiniband/ulp/ipoib/ipoib_multicast.c | 6 |
3 files changed, 11 insertions, 11 deletions
diff --git a/drivers/infiniband/ulp/ipoib/ipoib_ib.c b/drivers/infiniband/ulp/ipoib/ipoib_ib.c index 45c40a17d6a6..dc6d241b9406 100644 --- a/drivers/infiniband/ulp/ipoib/ipoib_ib.c +++ b/drivers/infiniband/ulp/ipoib/ipoib_ib.c | |||
@@ -1015,7 +1015,7 @@ static bool ipoib_dev_addr_changed_valid(struct ipoib_dev_priv *priv) | |||
1015 | if (ib_query_gid(priv->ca, priv->port, 0, &gid0, NULL)) | 1015 | if (ib_query_gid(priv->ca, priv->port, 0, &gid0, NULL)) |
1016 | return false; | 1016 | return false; |
1017 | 1017 | ||
1018 | netif_addr_lock(priv->dev); | 1018 | netif_addr_lock_bh(priv->dev); |
1019 | 1019 | ||
1020 | /* The subnet prefix may have changed, update it now so we won't have | 1020 | /* The subnet prefix may have changed, update it now so we won't have |
1021 | * to do it later | 1021 | * to do it later |
@@ -1026,12 +1026,12 @@ static bool ipoib_dev_addr_changed_valid(struct ipoib_dev_priv *priv) | |||
1026 | 1026 | ||
1027 | search_gid.global.interface_id = priv->local_gid.global.interface_id; | 1027 | search_gid.global.interface_id = priv->local_gid.global.interface_id; |
1028 | 1028 | ||
1029 | netif_addr_unlock(priv->dev); | 1029 | netif_addr_unlock_bh(priv->dev); |
1030 | 1030 | ||
1031 | err = ib_find_gid(priv->ca, &search_gid, IB_GID_TYPE_IB, | 1031 | err = ib_find_gid(priv->ca, &search_gid, IB_GID_TYPE_IB, |
1032 | priv->dev, &port, &index); | 1032 | priv->dev, &port, &index); |
1033 | 1033 | ||
1034 | netif_addr_lock(priv->dev); | 1034 | netif_addr_lock_bh(priv->dev); |
1035 | 1035 | ||
1036 | if (search_gid.global.interface_id != | 1036 | if (search_gid.global.interface_id != |
1037 | priv->local_gid.global.interface_id) | 1037 | priv->local_gid.global.interface_id) |
@@ -1092,7 +1092,7 @@ static bool ipoib_dev_addr_changed_valid(struct ipoib_dev_priv *priv) | |||
1092 | } | 1092 | } |
1093 | 1093 | ||
1094 | out: | 1094 | out: |
1095 | netif_addr_unlock(priv->dev); | 1095 | netif_addr_unlock_bh(priv->dev); |
1096 | 1096 | ||
1097 | return ret; | 1097 | return ret; |
1098 | } | 1098 | } |
diff --git a/drivers/infiniband/ulp/ipoib/ipoib_main.c b/drivers/infiniband/ulp/ipoib/ipoib_main.c index 0aa52c2f9438..248da5015093 100644 --- a/drivers/infiniband/ulp/ipoib/ipoib_main.c +++ b/drivers/infiniband/ulp/ipoib/ipoib_main.c | |||
@@ -1851,7 +1851,7 @@ static void set_base_guid(struct ipoib_dev_priv *priv, union ib_gid *gid) | |||
1851 | struct ipoib_dev_priv *child_priv; | 1851 | struct ipoib_dev_priv *child_priv; |
1852 | struct net_device *netdev = priv->dev; | 1852 | struct net_device *netdev = priv->dev; |
1853 | 1853 | ||
1854 | netif_addr_lock(netdev); | 1854 | netif_addr_lock_bh(netdev); |
1855 | 1855 | ||
1856 | memcpy(&priv->local_gid.global.interface_id, | 1856 | memcpy(&priv->local_gid.global.interface_id, |
1857 | &gid->global.interface_id, | 1857 | &gid->global.interface_id, |
@@ -1859,7 +1859,7 @@ static void set_base_guid(struct ipoib_dev_priv *priv, union ib_gid *gid) | |||
1859 | memcpy(netdev->dev_addr + 4, &priv->local_gid, sizeof(priv->local_gid)); | 1859 | memcpy(netdev->dev_addr + 4, &priv->local_gid, sizeof(priv->local_gid)); |
1860 | clear_bit(IPOIB_FLAG_DEV_ADDR_SET, &priv->flags); | 1860 | clear_bit(IPOIB_FLAG_DEV_ADDR_SET, &priv->flags); |
1861 | 1861 | ||
1862 | netif_addr_unlock(netdev); | 1862 | netif_addr_unlock_bh(netdev); |
1863 | 1863 | ||
1864 | if (!test_bit(IPOIB_FLAG_SUBINTERFACE, &priv->flags)) { | 1864 | if (!test_bit(IPOIB_FLAG_SUBINTERFACE, &priv->flags)) { |
1865 | down_read(&priv->vlan_rwsem); | 1865 | down_read(&priv->vlan_rwsem); |
@@ -1875,7 +1875,7 @@ static int ipoib_check_lladdr(struct net_device *dev, | |||
1875 | union ib_gid *gid = (union ib_gid *)(ss->__data + 4); | 1875 | union ib_gid *gid = (union ib_gid *)(ss->__data + 4); |
1876 | int ret = 0; | 1876 | int ret = 0; |
1877 | 1877 | ||
1878 | netif_addr_lock(dev); | 1878 | netif_addr_lock_bh(dev); |
1879 | 1879 | ||
1880 | /* Make sure the QPN, reserved and subnet prefix match the current | 1880 | /* Make sure the QPN, reserved and subnet prefix match the current |
1881 | * lladdr, it also makes sure the lladdr is unicast. | 1881 | * lladdr, it also makes sure the lladdr is unicast. |
@@ -1885,7 +1885,7 @@ static int ipoib_check_lladdr(struct net_device *dev, | |||
1885 | gid->global.interface_id == 0) | 1885 | gid->global.interface_id == 0) |
1886 | ret = -EINVAL; | 1886 | ret = -EINVAL; |
1887 | 1887 | ||
1888 | netif_addr_unlock(dev); | 1888 | netif_addr_unlock_bh(dev); |
1889 | 1889 | ||
1890 | return ret; | 1890 | return ret; |
1891 | } | 1891 | } |
diff --git a/drivers/infiniband/ulp/ipoib/ipoib_multicast.c b/drivers/infiniband/ulp/ipoib/ipoib_multicast.c index 82fbc9442608..d3394b6add24 100644 --- a/drivers/infiniband/ulp/ipoib/ipoib_multicast.c +++ b/drivers/infiniband/ulp/ipoib/ipoib_multicast.c | |||
@@ -582,13 +582,13 @@ void ipoib_mcast_join_task(struct work_struct *work) | |||
582 | return; | 582 | return; |
583 | } | 583 | } |
584 | priv->local_lid = port_attr.lid; | 584 | priv->local_lid = port_attr.lid; |
585 | netif_addr_lock(dev); | 585 | netif_addr_lock_bh(dev); |
586 | 586 | ||
587 | if (!test_bit(IPOIB_FLAG_DEV_ADDR_SET, &priv->flags)) { | 587 | if (!test_bit(IPOIB_FLAG_DEV_ADDR_SET, &priv->flags)) { |
588 | netif_addr_unlock(dev); | 588 | netif_addr_unlock_bh(dev); |
589 | return; | 589 | return; |
590 | } | 590 | } |
591 | netif_addr_unlock(dev); | 591 | netif_addr_unlock_bh(dev); |
592 | 592 | ||
593 | spin_lock_irq(&priv->lock); | 593 | spin_lock_irq(&priv->lock); |
594 | if (!test_bit(IPOIB_FLAG_OPER_UP, &priv->flags)) | 594 | if (!test_bit(IPOIB_FLAG_OPER_UP, &priv->flags)) |