Re: usb device removed from sysfs before input children devices

[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]

 



On Wed, 2013-01-09 at 19:27 +0000, Karl Relton wrote:
> On coming out of suspend my usb bluetooth adaptor is being reset by the
> system.
> 
> In linux 3.7 the usb devices are being removed from the sysfs tree
> first, and then the various 'child' devices (like my bluetooth mouse &
> keyboard related devices) afterwards. This is causing the udev events
> for the input devices to have 'orphaned' sysfs paths in the udev events.
> 
> This in turn means the Xorg evdev driver does not recognise the events,
> and so doesn't see the removal of the input devices.
> 
> This has been picked by some downstream distributions, e.g. see this
> thread by Google Chrome developers:
> 
> http://code.google.com/p/chromium-os/issues/detail?id=33813
> 
> Back on linux 3.2 this was not the case. The usb adaptor was reset, but
> device removal was orderly: first the input devices (will full paths in
> the udev events), then the usb devices walking up the tree.
> 
> 
> To illustrate the issue, here is the output of 'udevadm monitor' in 3.7:
> 
> udevadm monitor
> monitor will print the received events for:
> KERNEL - the kernel uevent
> KERNEL[2203.173080] remove   /devices/pci0000:00/0000:00:1a.0/usb3/3-2/3-2:1.0/bluetooth/hci0/rfkill2 (rfkill)
> KERNEL[2203.173148] remove   /devices/pci0000:00/0000:00:1a.0/usb3/3-2/3-2:1.0/bluetooth/hci0 (bluetooth)
> KERNEL[2203.173420] remove   /devices/pci0000:00/0000:00:1a.0/usb3/3-2/3-2:1.0 (usb)
> KERNEL[2203.173451] remove   /devices/pci0000:00/0000:00:1a.0/usb3/3-2/3-2:1.1 (usb)
> KERNEL[2203.173475] remove   /devices/pci0000:00/0000:00:1a.0/usb3/3-2/3-2:1.2 (usb)
> KERNEL[2203.173693] remove   /devices/pci0000:00/0000:00:1a.0/usb3/3-2 (usb)
> KERNEL[2213.152339] remove   /hci0/hci0:46/input14/mouse2 (input)
> KERNEL[2213.160374] remove   /hci0/hci0:46/input14/event10 (input)
> KERNEL[2213.168366] remove   /hci0/hci0:46/input14 (input)
> KERNEL[2213.169058] remove   /hci0/hci0:46/0005:050D:0031.0005/hidraw/hidraw0 (hidraw)
> KERNEL[2213.169198] remove   /hci0/hci0:46/0005:050D:0031.0005 (hid)
> KERNEL[2213.169242] remove   /hci0/hci0:46 (bluetooth)
> KERNEL[2218.176527] remove   /hci0/hci0:49/input13/event11 (input)
> KERNEL[2218.180403] remove   /hci0/hci0:49/input13 (input)
> KERNEL[2218.180481] remove   /hci0/hci0:49/0005:05AC:0256.0004/hidraw/hidraw1 (hidraw)
> KERNEL[2218.180538] remove   /hci0/hci0:49/0005:05AC:0256.0004 (hid)
> KERNEL[2218.182005] remove   /hci0/hci0:49 (bluetooth)
> 
> See how the usb devices are moved first, and then the input/bluetooth related stuff
> with path-heads removed (paths are now /hci0/... instead of /devices/...)
> 
> 
> Here is the equiv sequence back in 3.2:
> 
> KERNEL[158.378301] remove   /devices/pci0000:00/0000:00:1a.0/usb3/3-2/3-2:1.0/bluetooth/hci0/hci0:49/input11/mouse2 (input)
> KERNEL[158.388283] remove   /devices/pci0000:00/0000:00:1a.0/usb3/3-2/3-2:1.0/bluetooth/hci0/hci0:49/input11/event11 (input)
> KERNEL[158.409885] remove   /devices/pci0000:00/0000:00:1a.0/usb3/3-2/3-2:1.0/bluetooth/hci0/hci0:49/input11 (input)
> KERNEL[158.411565] remove   /devices/pci0000:00/0000:00:1a.0/usb3/3-2/3-2:1.0/bluetooth/hci0/hci0:49/0005:050D:0031.0002/hidraw/hidraw1 (hidraw)
> KERNEL[158.411598] remove   /devices/pci0000:00/0000:00:1a.0/usb3/3-2/3-2:1.0/bluetooth/hci0/hci0:49/0005:050D:0031.0002 (hid)
> KERNEL[158.411621] remove   /devices/pci0000:00/0000:00:1a.0/usb3/3-2/3-2:1.0/bluetooth/hci0/hci0:49 (bluetooth)
> KERNEL[158.436894] remove   /devices/pci0000:00/0000:00:1a.0/usb3/3-2/3-2:1.0/bluetooth/hci0/hci0:46/input10/event10 (input)
> KERNEL[158.452211] remove   /devices/pci0000:00/0000:00:1a.0/usb3/3-2/3-2:1.0/bluetooth/hci0/hci0:46/input10 (input)
> KERNEL[158.452628] remove   /devices/pci0000:00/0000:00:1a.0/usb3/3-2/3-2:1.0/bluetooth/hci0/hci0:46/0005:05AC:0256.0001/hidraw/hidraw0 (hidraw)
> KERNEL[158.452662] remove   /devices/pci0000:00/0000:00:1a.0/usb3/3-2/3-2:1.0/bluetooth/hci0/hci0:46/0005:05AC:0256.0001 (hid)
> KERNEL[158.452752] remove   /devices/pci0000:00/0000:00:1a.0/usb3/3-2/3-2:1.0/bluetooth/hci0/hci0:46 (bluetooth)
> KERNEL[158.629847] remove   /devices/pci0000:00/0000:00:1a.0/usb3/3-2/3-2:1.0/bluetooth/hci0/rfkill2 (rfkill)
> KERNEL[158.629920] remove   /devices/pci0000:00/0000:00:1a.0/usb3/3-2/3-2:1.0/bluetooth/hci0 (bluetooth)
> KERNEL[158.635562] remove   /devices/pci0000:00/0000:00:1a.0/usb3/3-2/3-2:1.0 (usb)
> KERNEL[158.635701] remove   /devices/pci0000:00/0000:00:1a.0/usb3/3-2/3-2:1.1 (usb)
> KERNEL[158.635807] remove   /devices/pci0000:00/0000:00:1a.0/usb3/3-2/3-2:1.2 (usb)
> KERNEL[158.637238] remove   /devices/pci0000:00/0000:00:1a.0/usb3/3-2 (usb)
> 
> 
> The end result (for the user) is that even when the bluetooth
> mouse/keyboard is re-added, Xorg ignores it - thinking it is some hoax
> duplicate device. The keyboard/mouse is then non-operational.
> 

Instrumenting the code suggests that the issue arises in a race between:

hidp_session() in bluetooth/hidp/core.c

and

hci_unregister_dev() in bluetooth/hci_core.c


Basically hci_unregister_dev() does a hci_dev_do_close() which in turn
shuts down the hidp connection. This causes hidp_session() running in
another thread to go into its cleanup phase, which is where the input
children devices are unregistered.

HOWEVER:
1) For some reason input_unregister_device() seems to stall some 3-5
seconds on my system before removing the input device
2) In parallel hci_unregister_dev() ploughs on, and progresses to remove
its hdev (hci<n> device) regardless, without waiting for hidp_session()
to complete.

I can't figure out why there is such a delay for
input_unregister_device().


But even if it didn't have the delay, there would still be a race
between the two threads (hci_unregister_dev vs hidp_session). No attempt
seems to be made to wait for the latter, so conceivably it could still
progress on even if hidp_session wasn't unnecessarily held up?

Question: What are the symantics of the wake_...() functions? Does the
function(thread) calling wake_... not move on until all the threads
woken by the call have completed or gone back to sleep. Or can the
calling thread() start progressing in parallel on a multi-processor
system?

I ask because if the calling function has to wait for the woken threads,
that would give the appropriate 'wait' on hci_unregister_dev ... but
ONLY IF hidp_session doesn't sleep again for some reason (e.g. while
waiting on a mutex inside input_unregister_device() perhaps ...)

Karl


--
To unsubscribe from this list: send the line "unsubscribe linux-usb" in
the body of a message to majordomo@xxxxxxxxxxxxxxx
More majordomo info at  http://vger.kernel.org/majordomo-info.html


[Index of Archives]     [Linux Media]     [Linux Input]     [Linux Audio Users]     [Yosemite News]     [Linux Kernel]     [Linux SCSI]     [Old Linux USB Devel Archive]

  Powered by Linux