Commit 6f562b21 authored by Tim Sell's avatar Tim Sell Committed by Greg Kroah-Hartman

staging: unisys: visornic - prevent lock recursion after IO recovery

In the patch which changed the serverdown logic to by synchronous, we
were
mistakenly holding on to devdata->priv_lock in the call to
visornic_serverdown_complete(), which ultimately ended up recursively
attempting to grab the same lock via the path:

    --> dev_close
        --> visornic_close()
            --> visornic_disable_with_timeout()

Evidence:

    BUG: spinlock recursion on CPU#0, kworker/u2:0/1567
     lock: 0xffff88002d7e4c90, .magic: dead4ead, .owner: kworker/
     .owner_cpu: 0
    CPU: 0 PID: 1567 Comm: kworker/u2:0 Tainted: G        WC
         4.2.0-rc3-ARCH+ #60
    Hardware name: Dell Inc. PowerEdge T110/ , BIOS 1.23 12/15/2009
    Workqueue: visorchipset_controlvm controlvm_periodic_work [visorbus]
     ffff8800216a9380 ffff88002d167878 ffffffff81476874 000000000000061f
     ffff88002d7e4c90 ffff88002d167898 ffffffff8109e2bc ffff88002d7e4c90
     ffffffff81763d7c ffff88002d1678b8 ffffffff8109e330 ffff88002d7e4c90
    Call Trace:
     [<ffffffff81476874>] dump_stack+0x4f/0x73
     [<ffffffff8109e2bc>] spin_dump+0x7c/0xc0
     [<ffffffff8109e330>] spin_bug+0x30/0x40
     [<ffffffff8109e547>] do_raw_spin_lock+0x127/0x140
     [<ffffffff8147bf8b>] _raw_spin_lock_irqsave+0x4b/0x60
     [<ffffffffa0168a5c>] ? visornic_disable_with_timeout.clone.2+0x3c/
                          [visornic]
     [<ffffffff8147c639>] ? _raw_spin_unlock_bh+0x39/0x40
     [<ffffffffa0168a5c>] visornic_disable_with_timeout.clone.2+0x3c/
                          [visornic]
     [<ffffffffa0168c6e>] visornic_close+0xe/0x20 [visornic]
     [<ffffffff813ae8d2>] __dev_close_many+0x92/0xe0
     [<ffffffff813ae9ea>] dev_close_many+0x7a/0x110
     [<ffffffff81097556>] ? down+0x16/0x50
     [<ffffffff813af01f>] dev_close+0x3f/0x50
     [<ffffffffa0166b61>] visornic_serverdown+0x91/0x1a0 [visornic]
     [<ffffffffa0155760>] ? device_changestate_responder.clone.
                          [visorbus]
     [<ffffffffa0166c85>] visornic_pause+0x15/0x20 [visornic]
     [<ffffffffa015101f>] initiate_chipset_device_pause_resume+0x9f/0xe0
                          [visorbus]
     [<ffffffffa0151093>] chipset_device_pause+0x13/0x20 [visorbus]
     [<ffffffffa0153cbb>] device_epilog+0x12b/0x1a0 [visorbus]
     [<ffffffffa015506b>] handle_command+0x72b/0x970 [visorbus]
     [<ffffffffa015214e>] ? visorchannel_signalremove+0x6e/0x80
[visorbus]
     [<ffffffffa0155521>] controlvm_periodic_work+0x271/0x420 [visorbus]
     [<ffffffff8106cb52>] process_one_work+0x1d2/0x540
     [<ffffffff8106cab9>] ? process_one_work+0x139/0x540
     [<ffffffff814771b7>] ? __schedule+0x807/0xc30
     [<ffffffff8106cf57>] worker_thread+0x57/0x4c0
     [<ffffffff8106cf00>] ? process_scheduled_works+0x40/0x40
     [<ffffffff8106cf00>] ? process_scheduled_works+0x40/0x40
     [<ffffffff81073b19>] kthread+0xe9/0x110
     [<ffffffff81073a30>] ? __init_kthread_worker+0x70/0x70
     [<ffffffff8147cddf>] ret_from_fork+0x3f/0x70
     [<ffffffff81073a30>] ? __init_kthread_worker+0x70/0x70
    BUG: spinlock lockup suspected on CPU#0, kworker/u2:0/1567

Fixes: f2b70efaf48f ("staging: unisys: Make serverdown synchronous")
Signed-off-by: default avatarTim Sell <Timothy.Sell@unisys.com>
Signed-off-by: default avatarBenjamin Romer <benjamin.romer@unisys.com>
Signed-off-by: default avatarGreg Kroah-Hartman <gregkh@linuxfoundation.org>
parent 30948df8
...@@ -416,13 +416,14 @@ visornic_serverdown(struct visornic_devdata *devdata, ...@@ -416,13 +416,14 @@ visornic_serverdown(struct visornic_devdata *devdata,
} }
devdata->server_change_state = true; devdata->server_change_state = true;
devdata->server_down_complete_func = complete_func; devdata->server_down_complete_func = complete_func;
spin_unlock_irqrestore(&devdata->priv_lock, flags);
visornic_serverdown_complete(devdata); visornic_serverdown_complete(devdata);
} else if (devdata->server_change_state) { } else if (devdata->server_change_state) {
dev_dbg(&devdata->dev->device, "%s changing state\n", dev_dbg(&devdata->dev->device, "%s changing state\n",
__func__); __func__);
spin_unlock_irqrestore(&devdata->priv_lock, flags); spin_unlock_irqrestore(&devdata->priv_lock, flags);
return -EINVAL; return -EINVAL;
} } else
spin_unlock_irqrestore(&devdata->priv_lock, flags); spin_unlock_irqrestore(&devdata->priv_lock, flags);
return 0; return 0;
} }
......
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