linux/drivers/usb/core
Alan Stern 524134d422 USB: don't cancel queued resets when unbinding drivers
The USB stack provides a mechanism for drivers to request an
asynchronous device reset (usb_queue_reset_device()).  The mechanism
uses a work item (reset_ws) embedded in the usb_interface structure
used by the driver, and the reset is carried out by a work queue
routine.

The asynchronous reset can race with driver unbinding.  When this
happens, we try to cancel the queued reset before unbinding the
driver, on the theory that the driver won't care about any resets once
it is unbound.

However, thanks to the fact that lockdep now tracks work queue
accesses, this can provoke a lockdep warning in situations where the
device reset causes another interface's driver to be unbound; see

	http://marc.info/?l=linux-usb&m=141893165203776&w=2

for an example.  The reason is that the work routine for reset_ws in
one interface calls cancel_queued_work() for the reset_ws in another
interface.  Lockdep thinks this might lead to a work routine trying to
cancel itself.  The simplest solution is not to cancel queued resets
when unbinding drivers.

This means we now need to acquire a reference to the usb_interface
when queuing a reset_ws work item and to drop the reference when the
work routine finishes.  We also need to make sure that the
usb_interface structure doesn't outlive its parent usb_device; this
means acquiring and dropping a reference when the interface is created
and destroyed.

In addition, cancelling a queued reset can fail (if the device is in
the middle of an earlier reset), and this can cause usb_reset_device()
to try to rebind an interface that has been deallocated (see
http://marc.info/?l=linux-usb&m=142175717016628&w=2 for details).
Acquiring the extra references prevents this failure.

Signed-off-by: Alan Stern <stern@rowland.harvard.edu>
Reported-by: Russell King - ARM Linux <linux@arm.linux.org.uk>
Reported-by: Olivier Sobrie <olivier@sobrie.be>
Tested-by: Olivier Sobrie <olivier@sobrie.be>
Cc: stable <stable@vger.kernel.org> # 3.19
Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
2015-01-25 20:54:17 +08:00
..
buffer.c usb: core: buffer: smallest buffer should start at ARCH_DMA_MINALIGN 2015-01-09 10:21:31 -08:00
config.c usb-core bInterval quirk 2014-08-01 15:47:05 -07:00
devices.c
devio.c USB: devio: fix issue with log flooding 2014-08-01 16:01:46 -07:00
driver.c USB: don't cancel queued resets when unbinding drivers 2015-01-25 20:54:17 +08:00
endpoint.c USB: core: be specific about attribute permissions 2013-08-25 15:12:03 -07:00
file.c Merge branch 'for-linus' of git://git.kernel.org/pub/scm/linux/kernel/git/viro/vfs 2013-11-13 15:34:18 +09:00
generic.c staging: usbip: convert usbip-host driver to usb_device_driver 2014-02-07 10:54:30 -08:00
hcd-pci.c USB / PM: Drop CONFIG_PM_RUNTIME from the USB core 2014-12-04 00:51:54 +01:00
hcd.c USB patches for 3.19-rc1 2014-12-14 14:57:16 -08:00
hub.c USB: don't cancel queued resets when unbinding drivers 2015-01-25 20:54:17 +08:00
hub.h usb: hub: convert khubd into workqueue 2014-09-23 22:33:19 -07:00
Kconfig PM / Kconfig: Replace PM_RUNTIME with PM in dependencies 2014-12-13 00:44:04 +01:00
Makefile USB: core: remove CONFIG_USB_DEBUG usage 2013-12-21 16:01:00 -08:00
message.c USB: don't cancel queued resets when unbinding drivers 2015-01-25 20:54:17 +08:00
notify.c
otg_whitelist.h usb: core: TPL should apply for both OTG and EH 2014-09-23 21:28:41 -07:00
port.c USB / PM: Drop CONFIG_PM_RUNTIME from the USB core 2014-12-04 00:51:54 +01:00
quirks.c Merge branch 'for-linus' of git://git.kernel.org/pub/scm/linux/kernel/git/jikos/hid 2014-12-12 10:26:47 -08:00
sysfs.c USB / PM: Drop CONFIG_PM_RUNTIME from the USB core 2014-12-04 00:51:54 +01:00
urb.c usb: core: allow zero packet flag for interrupt urbs 2014-07-22 16:30:58 -07:00
usb-acpi.c usb: find internal hub tier mismatch via acpi 2014-05-27 16:38:52 -07:00
usb.c usb: core: buffer: smallest buffer should start at ARCH_DMA_MINALIGN 2015-01-09 10:21:31 -08:00
usb.h USB / PM: Drop CONFIG_PM_RUNTIME from the USB core 2014-12-04 00:51:54 +01:00