USB: disable endpoints after unbinding interfaces, not before
authorAlan Stern <stern@rowland.harvard.edu>
Thu, 30 Sep 2010 19:16:23 +0000 (15:16 -0400)
committerGreg Kroah-Hartman <gregkh@suse.de>
Fri, 22 Oct 2010 17:22:01 +0000 (10:22 -0700)
commit80f0cf3947889014d3a3dc0ad60fb87cfda4b12a
treedf1a1b880c7c13b68c1e368668e00b4d7e3e75b5
parentcf7d3c8e579a643ff81ff95d51babdaf4c55f5f4
USB: disable endpoints after unbinding interfaces, not before

This patch (as1430) fixes a bug in usbcore.  When a device
configuration change occurs or a device is removed, the endpoints for
the old config should be completely disabled.  However it turns out
they aren't; this is because usb_unbind_interface() calls
usb_enable_interface() or usb_set_interface() to put interfaces back
in altsetting 0, which re-enables the interfaces' endpoints.

As a result, when a device goes through a config change or is
unconfigured, the ep_in[] and ep_out[] arrays may be left holding old
pointers to usb_host_endpoint structures.  If the device is
deauthorized these structures get freed, and the stale pointers cause
errors when the the device is eventually unplugged.

The solution is to disable the endpoints after unbinding the
interfaces instead of before.  This isn't as large a change as it
sounds, since usb_unbind_interface() disables all the interface's
endpoints anyway before calling the driver's disconnect routine,
unless the driver claims to support "soft" unbind.

This fixes Bugzilla #19192.  Thanks to "Tom" Lei Ming for diagnosing
the underlying cause of the problem.

Signed-off-by: Alan Stern <stern@rowland.harvard.edu>
Tested-by: Carsten Sommer <carsten_sommer@ymail.com>
CC: stable <stable@kernel.org>
Signed-off-by: Greg Kroah-Hartman <gregkh@suse.de>
drivers/usb/core/message.c