[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: Alan Stern <stern@rowland.harvard.edu> Signed-off-by: Greg Kroah-Hartman <gregkh@suse.de>
This commit is contained in:
parent
df9a1f482d
commit
6ad07129a8
|
@ -1411,6 +1411,12 @@ free_interfaces:
|
||||||
return ret;
|
return ret;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
i = dev->bus_mA - cp->desc.bMaxPower * 2;
|
||||||
|
if (i < 0)
|
||||||
|
dev_warn(&dev->dev, "new config #%d exceeds power "
|
||||||
|
"limit by %dmA\n",
|
||||||
|
configuration, -i);
|
||||||
}
|
}
|
||||||
|
|
||||||
/* if it's already configured, clear out old state first.
|
/* if it's already configured, clear out old state first.
|
||||||
|
@ -1419,23 +1425,21 @@ free_interfaces:
|
||||||
if (dev->state != USB_STATE_ADDRESS)
|
if (dev->state != USB_STATE_ADDRESS)
|
||||||
usb_disable_device (dev, 1); // Skip ep0
|
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 "
|
|
||||||
"limit by %dmA\n",
|
|
||||||
configuration, -i);
|
|
||||||
}
|
|
||||||
|
|
||||||
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,
|
||||||
NULL, 0, USB_CTRL_SET_TIMEOUT)) < 0)
|
NULL, 0, USB_CTRL_SET_TIMEOUT)) < 0) {
|
||||||
goto free_interfaces;
|
|
||||||
|
/* All the old state is gone, so what else can we do?
|
||||||
|
* The device is probably useless now anyway.
|
||||||
|
*/
|
||||||
|
cp = NULL;
|
||||||
|
}
|
||||||
|
|
||||||
dev->actconfig = cp;
|
dev->actconfig = cp;
|
||||||
if (!cp)
|
if (!cp) {
|
||||||
usb_set_device_state(dev, USB_STATE_ADDRESS);
|
usb_set_device_state(dev, USB_STATE_ADDRESS);
|
||||||
else {
|
goto free_interfaces;
|
||||||
|
}
|
||||||
usb_set_device_state(dev, USB_STATE_CONFIGURED);
|
usb_set_device_state(dev, USB_STATE_CONFIGURED);
|
||||||
|
|
||||||
/* Initialize the new interface structures and the
|
/* Initialize the new interface structures and the
|
||||||
|
@ -1473,14 +1477,12 @@ free_interfaces:
|
||||||
mark_quiesced(intf);
|
mark_quiesced(intf);
|
||||||
sprintf (&intf->dev.bus_id[0], "%d-%s:%d.%d",
|
sprintf (&intf->dev.bus_id[0], "%d-%s:%d.%d",
|
||||||
dev->bus->busnum, dev->devpath,
|
dev->bus->busnum, dev->devpath,
|
||||||
configuration,
|
configuration, alt->desc.bInterfaceNumber);
|
||||||
alt->desc.bInterfaceNumber);
|
|
||||||
}
|
}
|
||||||
kfree(new_interfaces);
|
kfree(new_interfaces);
|
||||||
|
|
||||||
if (cp->string == NULL)
|
if (cp->string == NULL)
|
||||||
cp->string = usb_cache_string(dev,
|
cp->string = usb_cache_string(dev, cp->desc.iConfiguration);
|
||||||
cp->desc.iConfiguration);
|
|
||||||
|
|
||||||
/* Now that all the interfaces are set up, register them
|
/* Now that all the interfaces are set up, register them
|
||||||
* to trigger binding of drivers to interfaces. probe()
|
* to trigger binding of drivers to interfaces. probe()
|
||||||
|
@ -1497,15 +1499,12 @@ free_interfaces:
|
||||||
intf->cur_altsetting->desc.bInterfaceNumber);
|
intf->cur_altsetting->desc.bInterfaceNumber);
|
||||||
ret = device_add (&intf->dev);
|
ret = device_add (&intf->dev);
|
||||||
if (ret != 0) {
|
if (ret != 0) {
|
||||||
dev_err(&dev->dev,
|
dev_err(&dev->dev, "device_add(%s) --> %d\n",
|
||||||
"device_add(%s) --> %d\n",
|
intf->dev.bus_id, ret);
|
||||||
intf->dev.bus_id,
|
|
||||||
ret);
|
|
||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
usb_create_sysfs_intf_files (intf);
|
usb_create_sysfs_intf_files (intf);
|
||||||
}
|
}
|
||||||
}
|
|
||||||
|
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
Loading…
Reference in a new issue