| From foo@baz Sun Dec 31 11:13:15 CET 2017 |
| From: Gal Pressman <galp@mellanox.com> |
| Date: Thu, 23 Nov 2017 13:52:28 +0200 |
| Subject: net/mlx5e: Fix possible deadlock of VXLAN lock |
| |
| From: Gal Pressman <galp@mellanox.com> |
| |
| |
| [ Upstream commit 6323514116404cc651df1b7fffa1311ddf8ce647 ] |
| |
| mlx5e_vxlan_lookup_port is called both from mlx5e_add_vxlan_port (user |
| context) and mlx5e_features_check (softirq), but the lock acquired does |
| not disable bottom half and might result in deadlock. Fix it by simply |
| replacing spin_lock() with spin_lock_bh(). |
| While at it, replace all unnecessary spin_lock_irq() to spin_lock_bh(). |
| |
| lockdep's WARNING: inconsistent lock state |
| [ 654.028136] inconsistent {SOFTIRQ-ON-W} -> {IN-SOFTIRQ-W} usage. |
| [ 654.028229] swapper/5/0 [HC0[0]:SC1[9]:HE1:SE0] takes: |
| [ 654.028321] (&(&vxlan_db->lock)->rlock){+.?.}, at: [<ffffffffa06e7f0e>] mlx5e_vxlan_lookup_port+0x1e/0x50 [mlx5_core] |
| [ 654.028528] {SOFTIRQ-ON-W} state was registered at: |
| [ 654.028607] _raw_spin_lock+0x3c/0x70 |
| [ 654.028689] mlx5e_vxlan_lookup_port+0x1e/0x50 [mlx5_core] |
| [ 654.028794] mlx5e_vxlan_add_port+0x2e/0x120 [mlx5_core] |
| [ 654.028878] process_one_work+0x1e9/0x640 |
| [ 654.028942] worker_thread+0x4a/0x3f0 |
| [ 654.029002] kthread+0x141/0x180 |
| [ 654.029056] ret_from_fork+0x24/0x30 |
| [ 654.029114] irq event stamp: 579088 |
| [ 654.029174] hardirqs last enabled at (579088): [<ffffffff818f475a>] ip6_finish_output2+0x49a/0x8c0 |
| [ 654.029309] hardirqs last disabled at (579087): [<ffffffff818f470e>] ip6_finish_output2+0x44e/0x8c0 |
| [ 654.029446] softirqs last enabled at (579030): [<ffffffff810b3b3d>] irq_enter+0x6d/0x80 |
| [ 654.029567] softirqs last disabled at (579031): [<ffffffff810b3c05>] irq_exit+0xb5/0xc0 |
| [ 654.029684] other info that might help us debug this: |
| [ 654.029781] Possible unsafe locking scenario: |
| |
| [ 654.029868] CPU0 |
| [ 654.029908] ---- |
| [ 654.029947] lock(&(&vxlan_db->lock)->rlock); |
| [ 654.030045] <Interrupt> |
| [ 654.030090] lock(&(&vxlan_db->lock)->rlock); |
| [ 654.030162] |
| *** DEADLOCK *** |
| |
| Fixes: b3f63c3d5e2c ("net/mlx5e: Add netdev support for VXLAN tunneling") |
| Signed-off-by: Gal Pressman <galp@mellanox.com> |
| Signed-off-by: Saeed Mahameed <saeedm@mellanox.com> |
| Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org> |
| --- |
| drivers/net/ethernet/mellanox/mlx5/core/vxlan.c | 20 ++++++++++---------- |
| 1 file changed, 10 insertions(+), 10 deletions(-) |
| |
| --- a/drivers/net/ethernet/mellanox/mlx5/core/vxlan.c |
| +++ b/drivers/net/ethernet/mellanox/mlx5/core/vxlan.c |
| @@ -71,9 +71,9 @@ struct mlx5e_vxlan *mlx5e_vxlan_lookup_p |
| struct mlx5e_vxlan_db *vxlan_db = &priv->vxlan; |
| struct mlx5e_vxlan *vxlan; |
| |
| - spin_lock(&vxlan_db->lock); |
| + spin_lock_bh(&vxlan_db->lock); |
| vxlan = radix_tree_lookup(&vxlan_db->tree, port); |
| - spin_unlock(&vxlan_db->lock); |
| + spin_unlock_bh(&vxlan_db->lock); |
| |
| return vxlan; |
| } |
| @@ -100,9 +100,9 @@ static void mlx5e_vxlan_add_port(struct |
| |
| vxlan->udp_port = port; |
| |
| - spin_lock_irq(&vxlan_db->lock); |
| + spin_lock_bh(&vxlan_db->lock); |
| err = radix_tree_insert(&vxlan_db->tree, vxlan->udp_port, vxlan); |
| - spin_unlock_irq(&vxlan_db->lock); |
| + spin_unlock_bh(&vxlan_db->lock); |
| if (err) |
| goto err_free; |
| |
| @@ -121,9 +121,9 @@ static void __mlx5e_vxlan_core_del_port( |
| struct mlx5e_vxlan_db *vxlan_db = &priv->vxlan; |
| struct mlx5e_vxlan *vxlan; |
| |
| - spin_lock_irq(&vxlan_db->lock); |
| + spin_lock_bh(&vxlan_db->lock); |
| vxlan = radix_tree_delete(&vxlan_db->tree, port); |
| - spin_unlock_irq(&vxlan_db->lock); |
| + spin_unlock_bh(&vxlan_db->lock); |
| |
| if (!vxlan) |
| return; |
| @@ -171,12 +171,12 @@ void mlx5e_vxlan_cleanup(struct mlx5e_pr |
| struct mlx5e_vxlan *vxlan; |
| unsigned int port = 0; |
| |
| - spin_lock_irq(&vxlan_db->lock); |
| + spin_lock_bh(&vxlan_db->lock); |
| while (radix_tree_gang_lookup(&vxlan_db->tree, (void **)&vxlan, port, 1)) { |
| port = vxlan->udp_port; |
| - spin_unlock_irq(&vxlan_db->lock); |
| + spin_unlock_bh(&vxlan_db->lock); |
| __mlx5e_vxlan_core_del_port(priv, (u16)port); |
| - spin_lock_irq(&vxlan_db->lock); |
| + spin_lock_bh(&vxlan_db->lock); |
| } |
| - spin_unlock_irq(&vxlan_db->lock); |
| + spin_unlock_bh(&vxlan_db->lock); |
| } |