| From 19cd80a214821f4b558560ebd76bfb2c38b4f3d8 Mon Sep 17 00:00:00 2001 |
| From: Jiri Slaby <jslaby@suse.cz> |
| Date: Mon, 2 Nov 2015 10:27:00 +0100 |
| Subject: usblp: do not set TASK_INTERRUPTIBLE before lock |
| |
| commit 19cd80a214821f4b558560ebd76bfb2c38b4f3d8 upstream. |
| |
| It is not permitted to set task state before lock. usblp_wwait sets |
| the state to TASK_INTERRUPTIBLE and calls mutex_lock_interruptible. |
| Upon return from that function, the state will be TASK_RUNNING again. |
| |
| This is clearly a bug and a warning is generated with LOCKDEP too: |
| WARNING: CPU: 1 PID: 5109 at kernel/sched/core.c:7404 __might_sleep+0x7d/0x90() |
| do not call blocking ops when !TASK_RUNNING; state=1 set at [<ffffffffa0c588d0>] usblp_wwait+0xa0/0x310 [usblp] |
| Modules linked in: ... |
| CPU: 1 PID: 5109 Comm: captmon Tainted: G W 4.2.5-0.gef2823b-default #1 |
| Hardware name: LENOVO 23252SG/23252SG, BIOS G2ET33WW (1.13 ) 07/24/2012 |
| ffffffff81a4edce ffff880236ec7ba8 ffffffff81716651 0000000000000000 |
| ffff880236ec7bf8 ffff880236ec7be8 ffffffff8106e146 0000000000000282 |
| ffffffff81a50119 000000000000028b 0000000000000000 ffff8802dab7c508 |
| Call Trace: |
| ... |
| [<ffffffff8106e1c6>] warn_slowpath_fmt+0x46/0x50 |
| [<ffffffff8109a8bd>] __might_sleep+0x7d/0x90 |
| [<ffffffff8171b20f>] mutex_lock_interruptible_nested+0x2f/0x4b0 |
| [<ffffffffa0c588fc>] usblp_wwait+0xcc/0x310 [usblp] |
| [<ffffffffa0c58bb2>] usblp_write+0x72/0x350 [usblp] |
| [<ffffffff8121ed98>] __vfs_write+0x28/0xf0 |
| ... |
| |
| Commit 7f477358e2384c54b190cc3b6ce28277050a041b (usblp: Implement the |
| ENOSPC convention) moved the set prior locking. So move it back after |
| the lock. |
| |
| Signed-off-by: Jiri Slaby <jslaby@suse.cz> |
| Fixes: 7f477358e2 ("usblp: Implement the ENOSPC convention") |
| Acked-By: Pete Zaitcev <zaitcev@yahoo.com> |
| Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org> |
| Signed-off-by: Zefan Li <lizefan@huawei.com> |
| --- |
| drivers/usb/class/usblp.c | 2 +- |
| 1 file changed, 1 insertion(+), 1 deletion(-) |
| |
| --- a/drivers/usb/class/usblp.c |
| +++ b/drivers/usb/class/usblp.c |
| @@ -861,11 +861,11 @@ static int usblp_wwait(struct usblp *usb |
| |
| add_wait_queue(&usblp->wwait, &waita); |
| for (;;) { |
| - set_current_state(TASK_INTERRUPTIBLE); |
| if (mutex_lock_interruptible(&usblp->mut)) { |
| rc = -EINTR; |
| break; |
| } |
| + set_current_state(TASK_INTERRUPTIBLE); |
| rc = usblp_wtest(usblp, nonblock); |
| mutex_unlock(&usblp->mut); |
| if (rc <= 0) |