Commit 9dfb0ad1 authored by David Brownell's avatar David Brownell Committed by Greg Kroah-Hartman

[PATCH] USB: disable usb device endpoints in more places

This patch touches the most significant places in usbcore
that need to respond to configuration change events:

  - set_interface changes altsettings; affects endpoints
    in both new and old settings (but not other endpoints).

  - set_configuration; affects every endpoint

The endpoints get disabled, flushing hardware state
reliably.  This resolves two FIXMEs here, part of one
in OHCI (ed_get) and all of one in EHCI (qh_append_tds).

Not many drivers currently use these code paths, but
now they should start to work properly.
parent aba85312
...@@ -795,6 +795,7 @@ int usb_set_interface(struct usb_device *dev, int interface, int alternate) ...@@ -795,6 +795,7 @@ int usb_set_interface(struct usb_device *dev, int interface, int alternate)
struct usb_interface *iface; struct usb_interface *iface;
struct usb_host_interface *iface_as; struct usb_host_interface *iface_as;
int i, ret; int i, ret;
void (*disable)(struct usb_device *, int) = dev->bus->op->disable;
iface = usb_ifnum_to_if(dev, interface); iface = usb_ifnum_to_if(dev, interface);
if (!iface) { if (!iface) {
...@@ -832,9 +833,11 @@ int usb_set_interface(struct usb_device *dev, int interface, int alternate) ...@@ -832,9 +833,11 @@ int usb_set_interface(struct usb_device *dev, int interface, int alternate)
u8 ep = iface_as->endpoint [i].desc.bEndpointAddress; u8 ep = iface_as->endpoint [i].desc.bEndpointAddress;
int out = !(ep & USB_DIR_IN); int out = !(ep & USB_DIR_IN);
/* clear out hcd state, then usbcore state */
if (disable)
disable (dev, ep);
ep &= USB_ENDPOINT_NUMBER_MASK; ep &= USB_ENDPOINT_NUMBER_MASK;
(out ? dev->epmaxpacketout : dev->epmaxpacketin ) [ep] = 0; (out ? dev->epmaxpacketout : dev->epmaxpacketin ) [ep] = 0;
// FIXME want hcd hook here, "no such endpoint"
} }
iface->act_altsetting = alternate; iface->act_altsetting = alternate;
...@@ -898,6 +901,7 @@ int usb_set_configuration(struct usb_device *dev, int configuration) ...@@ -898,6 +901,7 @@ int usb_set_configuration(struct usb_device *dev, int configuration)
{ {
int i, ret; int i, ret;
struct usb_host_config *cp = NULL; struct usb_host_config *cp = NULL;
void (*disable)(struct usb_device *, int) = dev->bus->op->disable;
for (i=0; i<dev->descriptor.bNumConfigurations; i++) { for (i=0; i<dev->descriptor.bNumConfigurations; i++) {
if (dev->config[i].desc.bConfigurationValue == configuration) { if (dev->config[i].desc.bConfigurationValue == configuration) {
...@@ -911,11 +915,15 @@ int usb_set_configuration(struct usb_device *dev, int configuration) ...@@ -911,11 +915,15 @@ int usb_set_configuration(struct usb_device *dev, int configuration)
} }
/* if it's already configured, clear out old state first. */ /* if it's already configured, clear out old state first. */
if (dev->state != USB_STATE_ADDRESS) { if (dev->state != USB_STATE_ADDRESS && disable) {
/* FIXME unbind drivers from all "old" interfaces. for (i = 0; i < 15; i++) {
* handshake with hcd to reset cached hc endpoint state. disable (dev, i);
*/ disable (dev, USB_DIR_IN | i);
}
} }
dev->toggle[0] = dev->toggle[1] = 0;
dev->halted[0] = dev->halted[1] = 0;
dev->state = USB_STATE_ADDRESS;
if ((ret = usb_control_msg(dev, usb_sndctrlpipe(dev, 0), if ((ret = usb_control_msg(dev, usb_sndctrlpipe(dev, 0),
USB_REQ_SET_CONFIGURATION, 0, configuration, 0, USB_REQ_SET_CONFIGURATION, 0, configuration, 0,
...@@ -923,15 +931,9 @@ int usb_set_configuration(struct usb_device *dev, int configuration) ...@@ -923,15 +931,9 @@ int usb_set_configuration(struct usb_device *dev, int configuration)
return ret; return ret;
if (configuration) if (configuration)
dev->state = USB_STATE_CONFIGURED; dev->state = USB_STATE_CONFIGURED;
else
dev->state = USB_STATE_ADDRESS;
dev->actconfig = cp; dev->actconfig = cp;
/* reset more hc/hcd endpoint state */ /* reset more hc/hcd endpoint state */
dev->toggle[0] = 0;
dev->toggle[1] = 0;
dev->halted[0] = 0;
dev->halted[1] = 0;
usb_set_maxpacket(dev); usb_set_maxpacket(dev);
return 0; return 0;
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment