提交 6ad07129 编写于 作者: A Alan Stern 提交者: 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: NAlan Stern <stern@rowland.harvard.edu>
Signed-off-by: NGreg Kroah-Hartman <gregkh@suse.de>
上级 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% .
You are about to add 0 people to the discussion. Proceed with caution.
先完成此消息的编辑!
想要评论请 注册