USB: don't register endpoints for interfaces that are going away
This patch (as1155) fixes a bug in usbcore. When interfaces are deleted, either because the device was disconnected or because of a configuration change, the extra attribute files and child endpoint devices may get left behind. This is because the core removes them before calling device_del(). But during device_del(), after the driver is unbound the core will reinstall altsetting 0 and recreate those extra attributes and children. The patch prevents this by adding a flag to record when the interface is in the midst of being unregistered. When the flag is set, the attribute files and child devices will not be created. Signed-off-by: Alan Stern <stern@rowland.harvard.edu> Cc: stable <stable@kernel.org> [2.6.27, 2.6.26, 2.6.25] Signed-off-by: Greg Kroah-Hartman <gregkh@suse.de>
This commit is contained in:
parent
0047ca0a45
commit
352d026338
@ -1091,6 +1091,7 @@ void usb_disable_device(struct usb_device *dev, int skip_ep0)
|
|||||||
continue;
|
continue;
|
||||||
dev_dbg(&dev->dev, "unregistering interface %s\n",
|
dev_dbg(&dev->dev, "unregistering interface %s\n",
|
||||||
dev_name(&interface->dev));
|
dev_name(&interface->dev));
|
||||||
|
interface->unregistering = 1;
|
||||||
usb_remove_sysfs_intf_files(interface);
|
usb_remove_sysfs_intf_files(interface);
|
||||||
device_del(&interface->dev);
|
device_del(&interface->dev);
|
||||||
}
|
}
|
||||||
|
@ -840,7 +840,7 @@ int usb_create_sysfs_intf_files(struct usb_interface *intf)
|
|||||||
struct usb_host_interface *alt = intf->cur_altsetting;
|
struct usb_host_interface *alt = intf->cur_altsetting;
|
||||||
int retval;
|
int retval;
|
||||||
|
|
||||||
if (intf->sysfs_files_created)
|
if (intf->sysfs_files_created || intf->unregistering)
|
||||||
return 0;
|
return 0;
|
||||||
|
|
||||||
/* The interface string may be present in some altsettings
|
/* The interface string may be present in some altsettings
|
||||||
|
@ -108,6 +108,7 @@ enum usb_interface_condition {
|
|||||||
* (in probe()), bound to a driver, or unbinding (in disconnect())
|
* (in probe()), bound to a driver, or unbinding (in disconnect())
|
||||||
* @is_active: flag set when the interface is bound and not suspended.
|
* @is_active: flag set when the interface is bound and not suspended.
|
||||||
* @sysfs_files_created: sysfs attributes exist
|
* @sysfs_files_created: sysfs attributes exist
|
||||||
|
* @unregistering: flag set when the interface is being unregistered
|
||||||
* @needs_remote_wakeup: flag set when the driver requires remote-wakeup
|
* @needs_remote_wakeup: flag set when the driver requires remote-wakeup
|
||||||
* capability during autosuspend.
|
* capability during autosuspend.
|
||||||
* @needs_altsetting0: flag set when a set-interface request for altsetting 0
|
* @needs_altsetting0: flag set when a set-interface request for altsetting 0
|
||||||
@ -163,6 +164,7 @@ struct usb_interface {
|
|||||||
enum usb_interface_condition condition; /* state of binding */
|
enum usb_interface_condition condition; /* state of binding */
|
||||||
unsigned is_active:1; /* the interface is not suspended */
|
unsigned is_active:1; /* the interface is not suspended */
|
||||||
unsigned sysfs_files_created:1; /* the sysfs attributes exist */
|
unsigned sysfs_files_created:1; /* the sysfs attributes exist */
|
||||||
|
unsigned unregistering:1; /* unregistration is in progress */
|
||||||
unsigned needs_remote_wakeup:1; /* driver requires remote wakeup */
|
unsigned needs_remote_wakeup:1; /* driver requires remote wakeup */
|
||||||
unsigned needs_altsetting0:1; /* switch to altsetting 0 is pending */
|
unsigned needs_altsetting0:1; /* switch to altsetting 0 is pending */
|
||||||
unsigned needs_binding:1; /* needs delayed unbind/rebind */
|
unsigned needs_binding:1; /* needs delayed unbind/rebind */
|
||||||
|
Loading…
Reference in New Issue
Block a user