Donate to e Foundation | Murena handsets with /e/OS | Own a part of Murena! Learn more

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

[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
Loading
Loading
Loading
Loading
+75 −76
Original line number Diff line number Diff line
@@ -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;
}