Commit 6ad07129 authored by Alan Stern's avatar Alan Stern Committed by Greg Kroah-Hartman

[PATCH] usbcore: recovery from Set-Configuration failure

This patch (as703) improves the error handling when a Set-Configuration
request fails.  The old interfaces are all unregistered before the
request is sent, and if the request fails then we don't know what config
the device is using.  So it makes no sense to leave actconfig pointing
to the old configuration with its invalid interfaces.
Signed-off-by: default avatarAlan Stern <stern@rowland.harvard.edu>
Signed-off-by: default avatarGreg Kroah-Hartman <gregkh@suse.de>
parent df9a1f48
......@@ -1411,15 +1411,7 @@ int usb_set_configuration(struct usb_device *dev, int configuration)
return ret;
}
}
}
/* if it's already configured, clear out old state first.
* getting rid of old interfaces means unbinding their drivers.
*/
if (dev->state != USB_STATE_ADDRESS)
usb_disable_device (dev, 1); // Skip ep0
if (cp) {
i = dev->bus_mA - cp->desc.bMaxPower * 2;
if (i < 0)
dev_warn(&dev->dev, "new config #%d exceeds power "
......@@ -1427,15 +1419,27 @@ int usb_set_configuration(struct usb_device *dev, int configuration)
configuration, -i);
}
/* if it's already configured, clear out old state first.
* getting rid of old interfaces means unbinding their drivers.
*/
if (dev->state != USB_STATE_ADDRESS)
usb_disable_device (dev, 1); // Skip ep0
if ((ret = usb_control_msg(dev, usb_sndctrlpipe(dev, 0),
USB_REQ_SET_CONFIGURATION, 0, configuration, 0,
NULL, 0, USB_CTRL_SET_TIMEOUT)) < 0)
goto free_interfaces;
NULL, 0, USB_CTRL_SET_TIMEOUT)) < 0) {
/* All the old state is gone, so what else can we do?
* The device is probably useless now anyway.
*/
cp = NULL;
}
dev->actconfig = cp;
if (!cp)
if (!cp) {
usb_set_device_state(dev, USB_STATE_ADDRESS);
else {
goto free_interfaces;
}
usb_set_device_state(dev, USB_STATE_CONFIGURED);
/* Initialize the new interface structures and the
......@@ -1473,14 +1477,12 @@ int usb_set_configuration(struct usb_device *dev, int configuration)
mark_quiesced(intf);
sprintf (&intf->dev.bus_id[0], "%d-%s:%d.%d",
dev->bus->busnum, dev->devpath,
configuration,
alt->desc.bInterfaceNumber);
configuration, alt->desc.bInterfaceNumber);
}
kfree(new_interfaces);
if (cp->string == NULL)
cp->string = usb_cache_string(dev,
cp->desc.iConfiguration);
cp->string = usb_cache_string(dev, cp->desc.iConfiguration);
/* Now that all the interfaces are set up, register them
* to trigger binding of drivers to interfaces. probe()
......@@ -1497,15 +1499,12 @@ int usb_set_configuration(struct usb_device *dev, int configuration)
intf->cur_altsetting->desc.bInterfaceNumber);
ret = device_add (&intf->dev);
if (ret != 0) {
dev_err(&dev->dev,
"device_add(%s) --> %d\n",
intf->dev.bus_id,
ret);
dev_err(&dev->dev, "device_add(%s) --> %d\n",
intf->dev.bus_id, ret);
continue;
}
usb_create_sysfs_intf_files (intf);
}
}
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