summaryrefslogtreecommitdiff
path: root/drivers
diff options
context:
space:
mode:
authorRoger Quadros <rogerq@ti.com>2015-05-29 17:01:49 +0300
committerGreg Kroah-Hartman <gregkh@linuxfoundation.org>2015-05-31 09:45:31 +0300
commitad6b1d914a9e07f3b9a9ae3396f3c840d0070539 (patch)
treef9ad4ad8606003c5e93e4e5a28d9e154c5741c28 /drivers
parent8a853759c262fd52ff0f5e89f89c65928077fe4a (diff)
downloadlinux-ad6b1d914a9e07f3b9a9ae3396f3c840d0070539.tar.xz
usb: xhci: fix xhci locking up during hcd remove
The problem seems to be that if a new device is detected while we have already removed the shared HCD, then many of the xhci operations (e.g. xhci_alloc_dev(), xhci_setup_device()) hang as command never completes. I don't think XHCI can operate without the shared HCD as we've already called xhci_halt() in xhci_only_stop_hcd() when shared HCD goes away. We need to prevent new commands from being queued not only when HCD is dying but also when HCD is halted. The following lockup was detected while testing the otg state machine. [ 178.199951] xhci-hcd xhci-hcd.0.auto: xHCI Host Controller [ 178.205799] xhci-hcd xhci-hcd.0.auto: new USB bus registered, assigned bus number 1 [ 178.214458] xhci-hcd xhci-hcd.0.auto: hcc params 0x0220f04c hci version 0x100 quirks 0x00010010 [ 178.223619] xhci-hcd xhci-hcd.0.auto: irq 400, io mem 0x48890000 [ 178.230677] usb usb1: New USB device found, idVendor=1d6b, idProduct=0002 [ 178.237796] usb usb1: New USB device strings: Mfr=3, Product=2, SerialNumber=1 [ 178.245358] usb usb1: Product: xHCI Host Controller [ 178.250483] usb usb1: Manufacturer: Linux 4.0.0-rc1-00024-g6111320 xhci-hcd [ 178.257783] usb usb1: SerialNumber: xhci-hcd.0.auto [ 178.267014] hub 1-0:1.0: USB hub found [ 178.272108] hub 1-0:1.0: 1 port detected [ 178.278371] xhci-hcd xhci-hcd.0.auto: xHCI Host Controller [ 178.284171] xhci-hcd xhci-hcd.0.auto: new USB bus registered, assigned bus number 2 [ 178.294038] usb usb2: New USB device found, idVendor=1d6b, idProduct=0003 [ 178.301183] usb usb2: New USB device strings: Mfr=3, Product=2, SerialNumber=1 [ 178.308776] usb usb2: Product: xHCI Host Controller [ 178.313902] usb usb2: Manufacturer: Linux 4.0.0-rc1-00024-g6111320 xhci-hcd [ 178.321222] usb usb2: SerialNumber: xhci-hcd.0.auto [ 178.329061] hub 2-0:1.0: USB hub found [ 178.333126] hub 2-0:1.0: 1 port detected [ 178.567585] dwc3 48890000.usb: usb_otg_start_host 0 [ 178.572707] xhci-hcd xhci-hcd.0.auto: remove, state 4 [ 178.578064] usb usb2: USB disconnect, device number 1 [ 178.586565] xhci-hcd xhci-hcd.0.auto: USB bus 2 deregistered [ 178.592585] xhci-hcd xhci-hcd.0.auto: remove, state 1 [ 178.597924] usb usb1: USB disconnect, device number 1 [ 178.603248] usb 1-1: new high-speed USB device number 2 using xhci-hcd [ 190.597337] INFO: task kworker/u4:0:6 blocked for more than 10 seconds. [ 190.604273] Not tainted 4.0.0-rc1-00024-g6111320 #1058 [ 190.610228] "echo 0 > /proc/sys/kernel/hung_task_timeout_secs" disables this message. [ 190.618443] kworker/u4:0 D c05c0ac0 0 6 2 0x00000000 [ 190.625120] Workqueue: usb_otg usb_otg_work [ 190.629533] [<c05c0ac0>] (__schedule) from [<c05c10ac>] (schedule+0x34/0x98) [ 190.636915] [<c05c10ac>] (schedule) from [<c05c1318>] (schedule_preempt_disabled+0xc/0x10) [ 190.645591] [<c05c1318>] (schedule_preempt_disabled) from [<c05c23d0>] (mutex_lock_nested+0x1ac/0x3fc) [ 190.655353] [<c05c23d0>] (mutex_lock_nested) from [<c046cf8c>] (usb_disconnect+0x3c/0x208) [ 190.664043] [<c046cf8c>] (usb_disconnect) from [<c0470cf0>] (_usb_remove_hcd+0x98/0x1d8) [ 190.672535] [<c0470cf0>] (_usb_remove_hcd) from [<c0485da8>] (usb_otg_start_host+0x50/0xf4) [ 190.681299] [<c0485da8>] (usb_otg_start_host) from [<c04849a4>] (otg_set_protocol+0x5c/0xd0) [ 190.690153] [<c04849a4>] (otg_set_protocol) from [<c0484b88>] (otg_set_state+0x170/0xbfc) [ 190.698735] [<c0484b88>] (otg_set_state) from [<c0485740>] (otg_statemachine+0x12c/0x470) [ 190.707326] [<c0485740>] (otg_statemachine) from [<c0053c84>] (process_one_work+0x1b4/0x4a0) [ 190.716162] [<c0053c84>] (process_one_work) from [<c00540f8>] (worker_thread+0x154/0x44c) [ 190.724742] [<c00540f8>] (worker_thread) from [<c0058f88>] (kthread+0xd4/0xf0) [ 190.732328] [<c0058f88>] (kthread) from [<c000e810>] (ret_from_fork+0x14/0x24) [ 190.739898] 5 locks held by kworker/u4:0/6: [ 190.744274] #0: ("%s""usb_otg"){.+.+.+}, at: [<c0053bf4>] process_one_work+0x124/0x4a0 [ 190.752799] #1: ((&otgd->work)){+.+.+.}, at: [<c0053bf4>] process_one_work+0x124/0x4a0 [ 190.761326] #2: (&otgd->fsm.lock){+.+.+.}, at: [<c048562c>] otg_statemachine+0x18/0x470 [ 190.769934] #3: (usb_bus_list_lock){+.+.+.}, at: [<c0470ce8>] _usb_remove_hcd+0x90/0x1d8 [ 190.778635] #4: (&dev->mutex){......}, at: [<c046cf8c>] usb_disconnect+0x3c/0x208 [ 190.786700] INFO: task kworker/1:0:14 blocked for more than 10 seconds. [ 190.793633] Not tainted 4.0.0-rc1-00024-g6111320 #1058 [ 190.799567] "echo 0 > /proc/sys/kernel/hung_task_timeout_secs" disables this message. [ 190.807783] kworker/1:0 D c05c0ac0 0 14 2 0x00000000 [ 190.814457] Workqueue: usb_hub_wq hub_event [ 190.818866] [<c05c0ac0>] (__schedule) from [<c05c10ac>] (schedule+0x34/0x98) [ 190.826252] [<c05c10ac>] (schedule) from [<c05c4e40>] (schedule_timeout+0x13c/0x1ec) [ 190.834377] [<c05c4e40>] (schedule_timeout) from [<c05c19f0>] (wait_for_common+0xbc/0x150) [ 190.843062] [<c05c19f0>] (wait_for_common) from [<bf068a3c>] (xhci_setup_device+0x164/0x5cc [xhci_hcd]) [ 190.852986] [<bf068a3c>] (xhci_setup_device [xhci_hcd]) from [<c046b7f4>] (hub_port_init+0x3f4/0xb10) [ 190.862667] [<c046b7f4>] (hub_port_init) from [<c046eb64>] (hub_event+0x704/0x1018) [ 190.870704] [<c046eb64>] (hub_event) from [<c0053c84>] (process_one_work+0x1b4/0x4a0) [ 190.878919] [<c0053c84>] (process_one_work) from [<c00540f8>] (worker_thread+0x154/0x44c) [ 190.887503] [<c00540f8>] (worker_thread) from [<c0058f88>] (kthread+0xd4/0xf0) [ 190.895076] [<c0058f88>] (kthread) from [<c000e810>] (ret_from_fork+0x14/0x24) [ 190.902650] 5 locks held by kworker/1:0/14: [ 190.907023] #0: ("usb_hub_wq"){.+.+.+}, at: [<c0053bf4>] process_one_work+0x124/0x4a0 [ 190.915454] #1: ((&hub->events)){+.+.+.}, at: [<c0053bf4>] process_one_work+0x124/0x4a0 [ 190.924070] #2: (&dev->mutex){......}, at: [<c046e490>] hub_event+0x30/0x1018 [ 190.931768] #3: (&port_dev->status_lock){+.+.+.}, at: [<c046eb50>] hub_event+0x6f0/0x1018 [ 190.940558] #4: (&bus->usb_address0_mutex){+.+.+.}, at: [<c046b458>] hub_port_init+0x58/0xb10 Signed-off-by: Roger Quadros <rogerq@ti.com> Signed-off-by: Mathias Nyman <mathias.nyman@linux.intel.com> Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
Diffstat (limited to 'drivers')
-rw-r--r--drivers/usb/host/xhci-ring.c5
1 files changed, 4 insertions, 1 deletions
diff --git a/drivers/usb/host/xhci-ring.c b/drivers/usb/host/xhci-ring.c
index 7d34cbfaf373..d7fd5efd3bd5 100644
--- a/drivers/usb/host/xhci-ring.c
+++ b/drivers/usb/host/xhci-ring.c
@@ -3781,8 +3781,11 @@ static int queue_command(struct xhci_hcd *xhci, struct xhci_command *cmd,
{
int reserved_trbs = xhci->cmd_ring_reserved_trbs;
int ret;
- if (xhci->xhc_state & XHCI_STATE_DYING)
+
+ if (xhci->xhc_state) {
+ xhci_dbg(xhci, "xHCI dying or halted, can't queue_command\n");
return -ESHUTDOWN;
+ }
if (!command_must_succeed)
reserved_trbs++;