diff options
Diffstat (limited to 'drivers/usb/core/message.c')
| -rw-r--r-- | drivers/usb/core/message.c | 264 | 
1 files changed, 174 insertions, 90 deletions
diff --git a/drivers/usb/core/message.c b/drivers/usb/core/message.c index d6e3e410477..0c8a7fc4dad 100644 --- a/drivers/usb/core/message.c +++ b/drivers/usb/core/message.c @@ -6,7 +6,6 @@  #include <linux/usb.h>  #include <linux/module.h>  #include <linux/slab.h> -#include <linux/init.h>  #include <linux/mm.h>  #include <linux/timer.h>  #include <linux/ctype.h> @@ -119,15 +118,15 @@ static int usb_internal_control_msg(struct usb_device *usb_dev,   * This function sends a simple control message to a specified endpoint and   * waits for the message to complete, or timeout.   * - * If successful, it returns the number of bytes transferred, otherwise a - * negative error number. - *   * Don't use this function from within an interrupt context, like a bottom half   * handler.  If you need an asynchronous message, or need to send a message   * from within interrupt context, use usb_submit_urb().   * If a thread in your driver uses this call, make sure your disconnect()   * method can wait for it to complete.  Since you don't have a handle on the   * URB used, you can't cancel the request. + * + * Return: If successful, the number of bytes transferred. Otherwise, a negative + * error number.   */  int usb_control_msg(struct usb_device *dev, unsigned int pipe, __u8 request,  		    __u8 requesttype, __u16 value, __u16 index, void *data, @@ -146,8 +145,6 @@ int usb_control_msg(struct usb_device *dev, unsigned int pipe, __u8 request,  	dr->wIndex = cpu_to_le16(index);  	dr->wLength = cpu_to_le16(size); -	/* dbg("usb_control_msg"); */ -  	ret = usb_internal_control_msg(dev, pipe, dr, data, size, timeout);  	kfree(dr); @@ -172,15 +169,16 @@ EXPORT_SYMBOL_GPL(usb_control_msg);   * This function sends a simple interrupt message to a specified endpoint and   * waits for the message to complete, or timeout.   * - * If successful, it returns 0, otherwise a negative error number.  The number - * of actual bytes transferred will be stored in the actual_length paramater. - *   * Don't use this function from within an interrupt context, like a bottom half   * handler.  If you need an asynchronous message, or need to send a message   * from within interrupt context, use usb_submit_urb() If a thread in your   * driver uses this call, make sure your disconnect() method can wait for it to   * complete.  Since you don't have a handle on the URB used, you can't cancel   * the request. + * + * Return: + * If successful, 0. Otherwise a negative error number. The number of actual + * bytes transferred will be stored in the @actual_length parameter.   */  int usb_interrupt_msg(struct usb_device *usb_dev, unsigned int pipe,  		      void *data, int len, int *actual_length, int timeout) @@ -205,9 +203,6 @@ EXPORT_SYMBOL_GPL(usb_interrupt_msg);   * This function sends a simple bulk message to a specified endpoint   * and waits for the message to complete, or timeout.   * - * If successful, it returns 0, otherwise a negative error number.  The number - * of actual bytes transferred will be stored in the actual_length paramater. - *   * Don't use this function from within an interrupt context, like a bottom half   * handler.  If you need an asynchronous message, or need to send a message   * from within interrupt context, use usb_submit_urb() If a thread in your @@ -219,6 +214,11 @@ EXPORT_SYMBOL_GPL(usb_interrupt_msg);   * users are forced to abuse this routine by using it to submit URBs for   * interrupt endpoints.  We will take the liberty of creating an interrupt URB   * (with the default interval) if the target is an interrupt endpoint. + * + * Return: + * If successful, 0. Otherwise a negative error number. The number of actual + * bytes transferred will be stored in the @actual_length parameter. + *   */  int usb_bulk_msg(struct usb_device *usb_dev, unsigned int pipe,  		 void *data, int len, int *actual_length, int timeout) @@ -254,7 +254,7 @@ static void sg_clean(struct usb_sg_request *io)  {  	if (io->urbs) {  		while (io->entries--) -			usb_free_urb(io->urbs [io->entries]); +			usb_free_urb(io->urbs[io->entries]);  		kfree(io->urbs);  		io->urbs = NULL;  	} @@ -302,22 +302,22 @@ static void sg_complete(struct urb *urb)  		 */  		spin_unlock(&io->lock);  		for (i = 0, found = 0; i < io->entries; i++) { -			if (!io->urbs [i] || !io->urbs [i]->dev) +			if (!io->urbs[i] || !io->urbs[i]->dev)  				continue;  			if (found) { -				retval = usb_unlink_urb(io->urbs [i]); +				retval = usb_unlink_urb(io->urbs[i]);  				if (retval != -EINPROGRESS &&  				    retval != -ENODEV && -				    retval != -EBUSY) +				    retval != -EBUSY && +				    retval != -EIDRM)  					dev_err(&io->dev->dev,  						"%s, unlink --> %d\n",  						__func__, retval); -			} else if (urb == io->urbs [i]) +			} else if (urb == io->urbs[i])  				found = 1;  		}  		spin_lock(&io->lock);  	} -	urb->dev = NULL;  	/* on the last completion, signal usb_sg_wait() */  	io->bytes += urb->actual_length; @@ -343,9 +343,9 @@ static void sg_complete(struct urb *urb)   * 	send every byte identified in the list.   * @mem_flags: SLAB_* flags affecting memory allocations in this call   * - * Returns zero for success, else a negative errno value.  This initializes a - * scatter/gather request, allocating resources such as I/O mappings and urb - * memory (except maybe memory used by USB controller drivers). + * This initializes a scatter/gather request, allocating resources such as + * I/O mappings and urb memory (except maybe memory used by USB controller + * drivers).   *   * The request must be issued using usb_sg_wait(), which waits for the I/O to   * complete (or to be canceled) and then cleans up all resources allocated by @@ -353,6 +353,8 @@ static void sg_complete(struct urb *urb)   *   * The request may be canceled with usb_sg_cancel(), either before or after   * usb_sg_wait() is called. + * + * Return: Zero for success, else a negative errno value.   */  int usb_sg_init(struct usb_sg_request *io, struct usb_device *dev,  		unsigned pipe, unsigned	period, struct scatterlist *sg, @@ -381,7 +383,7 @@ int usb_sg_init(struct usb_sg_request *io, struct usb_device *dev,  	}  	/* initialize all the urbs we'll use */ -	io->urbs = kmalloc(io->entries * sizeof *io->urbs, mem_flags); +	io->urbs = kmalloc(io->entries * sizeof(*io->urbs), mem_flags);  	if (!io->urbs)  		goto nomem; @@ -435,7 +437,7 @@ int usb_sg_init(struct usb_sg_request *io, struct usb_device *dev,  			len = sg->length;  			if (length) { -				len = min_t(unsigned, len, length); +				len = min_t(size_t, len, length);  				length -= len;  				if (length == 0)  					io->entries = i + 1; @@ -513,9 +515,9 @@ void usb_sg_wait(struct usb_sg_request *io)  		int retval;  		io->urbs[i]->dev = io->dev; -		retval = usb_submit_urb(io->urbs [i], GFP_ATOMIC); +		retval = usb_submit_urb(io->urbs[i], GFP_ATOMIC); -		/* after we submit, let completions or cancelations fire; +		/* after we submit, let completions or cancellations fire;  		 * we handshake using io->status.  		 */  		spin_unlock_irq(&io->lock); @@ -524,7 +526,6 @@ void usb_sg_wait(struct usb_sg_request *io)  		case -ENXIO:	/* hc didn't queue this one */  		case -EAGAIN:  		case -ENOMEM: -			io->urbs[i]->dev = NULL;  			retval = 0;  			yield();  			break; @@ -542,7 +543,6 @@ void usb_sg_wait(struct usb_sg_request *io)  			/* fail any uncompleted urbs */  		default: -			io->urbs[i]->dev = NULL;  			io->urbs[i]->status = retval;  			dev_dbg(&io->dev->dev, "%s, submit --> %d\n",  				__func__, retval); @@ -590,10 +590,13 @@ void usb_sg_cancel(struct usb_sg_request *io)  		for (i = 0; i < io->entries; i++) {  			int retval; -			if (!io->urbs [i]->dev) +			if (!io->urbs[i]->dev)  				continue; -			retval = usb_unlink_urb(io->urbs [i]); -			if (retval != -EINPROGRESS && retval != -EBUSY) +			retval = usb_unlink_urb(io->urbs[i]); +			if (retval != -EINPROGRESS +					&& retval != -ENODEV +					&& retval != -EBUSY +					&& retval != -EIDRM)  				dev_warn(&io->dev->dev, "%s, unlink --> %d\n",  					__func__, retval);  		} @@ -624,7 +627,7 @@ EXPORT_SYMBOL_GPL(usb_sg_cancel);   *   * This call is synchronous, and may not be used in an interrupt context.   * - * Returns the number of bytes received on success, or else the status code + * Return: The number of bytes received on success, or else the status code   * returned by the underlying usb_control_msg() call.   */  int usb_get_descriptor(struct usb_device *dev, unsigned char type, @@ -672,7 +675,7 @@ EXPORT_SYMBOL_GPL(usb_get_descriptor);   *   * This call is synchronous, and may not be used in an interrupt context.   * - * Returns the number of bytes received on success, or else the status code + * Return: The number of bytes received on success, or else the status code   * returned by the underlying usb_control_msg() call.   */  static int usb_get_string(struct usb_device *dev, unsigned short langid, @@ -806,7 +809,7 @@ static int usb_get_langid(struct usb_device *dev, unsigned char *tbuf)   *   * This call is synchronous, and may not be used in an interrupt context.   * - * Returns length of the string (>= 0) or usb_control_msg status (< 0). + * Return: length of the string (>= 0) or usb_control_msg status (< 0).   */  int usb_string(struct usb_device *dev, int index, char *buf, size_t size)  { @@ -854,8 +857,8 @@ EXPORT_SYMBOL_GPL(usb_string);   * @udev: the device whose string descriptor is being read   * @index: the descriptor index   * - * Returns a pointer to a kmalloc'ed buffer containing the descriptor string, - * or NULL if the index is 0 or the string could not be read. + * Return: A pointer to a kmalloc'ed buffer containing the descriptor string, + * or %NULL if the index is 0 or the string could not be read.   */  char *usb_cache_string(struct usb_device *udev, int index)  { @@ -895,7 +898,7 @@ char *usb_cache_string(struct usb_device *udev, int index)   *   * This call is synchronous, and may not be used in an interrupt context.   * - * Returns the number of bytes received on success, or else the status code + * Return: The number of bytes received on success, or else the status code   * returned by the underlying usb_control_msg() call.   */  int usb_get_device_descriptor(struct usb_device *dev, unsigned int size) @@ -935,13 +938,13 @@ int usb_get_device_descriptor(struct usb_device *dev, unsigned int size)   *   * This call is synchronous, and may not be used in an interrupt context.   * - * Returns the number of bytes received on success, or else the status code - * returned by the underlying usb_control_msg() call. + * Returns 0 and the status value in *@data (in host byte order) on success, + * or else the status code from the underlying usb_control_msg() call.   */  int usb_get_status(struct usb_device *dev, int type, int target, void *data)  {  	int ret; -	u16 *status = kmalloc(sizeof(*status), GFP_KERNEL); +	__le16 *status = kmalloc(sizeof(*status), GFP_KERNEL);  	if (!status)  		return -ENOMEM; @@ -950,7 +953,12 @@ int usb_get_status(struct usb_device *dev, int type, int target, void *data)  		USB_REQ_GET_STATUS, USB_DIR_IN | type, 0, target, status,  		sizeof(*status), USB_CTRL_GET_TIMEOUT); -	*(u16 *)data = *status; +	if (ret == 2) { +		*(u16 *) data = le16_to_cpu(*status); +		ret = 0; +	} else if (ret >= 0) { +		ret = -EIO; +	}  	kfree(status);  	return ret;  } @@ -976,7 +984,7 @@ EXPORT_SYMBOL_GPL(usb_get_status);   *   * This call is synchronous, and may not be used in an interrupt context.   * - * Returns zero on success, or else the status code returned by the + * Return: Zero on success, or else the status code returned by the   * underlying usb_control_msg() call.   */  int usb_clear_halt(struct usb_device *dev, int pipe) @@ -1139,11 +1147,20 @@ void usb_disable_interface(struct usb_device *dev, struct usb_interface *intf,  void usb_disable_device(struct usb_device *dev, int skip_ep0)  {  	int i; +	struct usb_hcd *hcd = bus_to_hcd(dev->bus);  	/* getting rid of interfaces will disconnect  	 * any drivers bound to them (a key side effect)  	 */  	if (dev->actconfig) { +		/* +		 * FIXME: In order to avoid self-deadlock involving the +		 * bandwidth_mutex, we have to mark all the interfaces +		 * before unregistering any of them. +		 */ +		for (i = 0; i < dev->actconfig->desc.bNumInterfaces; i++) +			dev->actconfig->interface[i]->unregistering = 1; +  		for (i = 0; i < dev->actconfig->desc.bNumInterfaces; i++) {  			struct usb_interface	*interface; @@ -1153,7 +1170,6 @@ void usb_disable_device(struct usb_device *dev, int skip_ep0)  				continue;  			dev_dbg(&dev->dev, "unregistering interface %s\n",  				dev_name(&interface->dev)); -			interface->unregistering = 1;  			remove_intf_ep_devs(interface);  			device_del(&interface->dev);  		} @@ -1165,6 +1181,12 @@ void usb_disable_device(struct usb_device *dev, int skip_ep0)  			put_device(&dev->actconfig->interface[i]->dev);  			dev->actconfig->interface[i] = NULL;  		} + +		if (dev->usb2_hw_lpm_enabled == 1) +			usb_set_usb2_hardware_lpm(dev, 0); +		usb_unlocked_disable_lpm(dev); +		usb_disable_ltm(dev); +  		dev->actconfig = NULL;  		if (dev->state == USB_STATE_CONFIGURED)  			usb_set_device_state(dev, USB_STATE_ADDRESS); @@ -1172,6 +1194,18 @@ void usb_disable_device(struct usb_device *dev, int skip_ep0)  	dev_dbg(&dev->dev, "%s nuking %s URBs\n", __func__,  		skip_ep0 ? "non-ep0" : "all"); +	if (hcd->driver->check_bandwidth) { +		/* First pass: Cancel URBs, leave endpoint pointers intact. */ +		for (i = skip_ep0; i < 16; ++i) { +			usb_disable_endpoint(dev, i, false); +			usb_disable_endpoint(dev, i + USB_DIR_IN, false); +		} +		/* Remove endpoints from the host controller internal state */ +		mutex_lock(hcd->bandwidth_mutex); +		usb_hcd_alloc_bandwidth(dev, NULL, NULL, NULL); +		mutex_unlock(hcd->bandwidth_mutex); +		/* Second pass: remove endpoint pointers */ +	}  	for (i = skip_ep0; i < 16; ++i) {  		usb_disable_endpoint(dev, i, true);  		usb_disable_endpoint(dev, i + USB_DIR_IN, true); @@ -1251,7 +1285,7 @@ void usb_enable_interface(struct usb_device *dev,   * endpoints in that interface; all such urbs must first be completed   * (perhaps forced by unlinking).   * - * Returns zero on success, or else the status code returned by the + * Return: Zero on success, or else the status code returned by the   * underlying usb_control_msg() call.   */  int usb_set_interface(struct usb_device *dev, int interface, int alternate) @@ -1259,8 +1293,7 @@ int usb_set_interface(struct usb_device *dev, int interface, int alternate)  	struct usb_interface *iface;  	struct usb_host_interface *alt;  	struct usb_hcd *hcd = bus_to_hcd(dev->bus); -	int ret; -	int manual = 0; +	int i, ret, manual = 0;  	unsigned int epaddr;  	unsigned int pipe; @@ -1273,6 +1306,8 @@ int usb_set_interface(struct usb_device *dev, int interface, int alternate)  			interface);  		return -EINVAL;  	} +	if (iface->unregistering) +		return -ENODEV;  	alt = usb_altnum_to_altsetting(iface, alternate);  	if (!alt) { @@ -1284,12 +1319,25 @@ int usb_set_interface(struct usb_device *dev, int interface, int alternate)  	/* Make sure we have enough bandwidth for this alternate interface.  	 * Remove the current alt setting and add the new alt setting.  	 */ -	mutex_lock(&hcd->bandwidth_mutex); +	mutex_lock(hcd->bandwidth_mutex); +	/* Disable LPM, and re-enable it once the new alt setting is installed, +	 * so that the xHCI driver can recalculate the U1/U2 timeouts. +	 */ +	if (usb_disable_lpm(dev)) { +		dev_err(&iface->dev, "%s Failed to disable LPM\n.", __func__); +		mutex_unlock(hcd->bandwidth_mutex); +		return -ENOMEM; +	} +	/* Changing alt-setting also frees any allocated streams */ +	for (i = 0; i < iface->cur_altsetting->desc.bNumEndpoints; i++) +		iface->cur_altsetting->endpoint[i].streams = 0; +  	ret = usb_hcd_alloc_bandwidth(dev, NULL, iface->cur_altsetting, alt);  	if (ret < 0) {  		dev_info(&dev->dev, "Not enough bandwidth for altsetting %d\n",  				alternate); -		mutex_unlock(&hcd->bandwidth_mutex); +		usb_enable_lpm(dev); +		mutex_unlock(hcd->bandwidth_mutex);  		return ret;  	} @@ -1311,10 +1359,11 @@ int usb_set_interface(struct usb_device *dev, int interface, int alternate)  	} else if (ret < 0) {  		/* Re-instate the old alt setting */  		usb_hcd_alloc_bandwidth(dev, NULL, alt, iface->cur_altsetting); -		mutex_unlock(&hcd->bandwidth_mutex); +		usb_enable_lpm(dev); +		mutex_unlock(hcd->bandwidth_mutex);  		return ret;  	} -	mutex_unlock(&hcd->bandwidth_mutex); +	mutex_unlock(hcd->bandwidth_mutex);  	/* FIXME drivers shouldn't need to replicate/bugfix the logic here  	 * when they implement async or easily-killable versions of this or @@ -1331,6 +1380,9 @@ int usb_set_interface(struct usb_device *dev, int interface, int alternate)  	iface->cur_altsetting = alt; +	/* Now that the interface is installed, re-enable LPM. */ +	usb_unlocked_enable_lpm(dev); +  	/* If the interface only has one altsetting and the device didn't  	 * accept the request, we attempt to carry out the equivalent action  	 * by manually clearing the HALT feature for each endpoint in the @@ -1390,7 +1442,7 @@ EXPORT_SYMBOL_GPL(usb_set_interface);   *   * The caller must own the device lock.   * - * Returns zero on success, else a negative error code. + * Return: Zero on success, else a negative error code.   */  int usb_reset_configuration(struct usb_device *dev)  { @@ -1413,7 +1465,15 @@ int usb_reset_configuration(struct usb_device *dev)  	config = dev->actconfig;  	retval = 0; -	mutex_lock(&hcd->bandwidth_mutex); +	mutex_lock(hcd->bandwidth_mutex); +	/* Disable LPM, and re-enable it once the configuration is reset, so +	 * that the xHCI driver can recalculate the U1/U2 timeouts. +	 */ +	if (usb_disable_lpm(dev)) { +		dev_err(&dev->dev, "%s Failed to disable LPM\n.", __func__); +		mutex_unlock(hcd->bandwidth_mutex); +		return -ENOMEM; +	}  	/* Make sure we have enough bandwidth for each alternate setting 0 */  	for (i = 0; i < config->desc.bNumInterfaces; i++) {  		struct usb_interface *intf = config->interface[i]; @@ -1442,7 +1502,8 @@ reset_old_alts:  				usb_hcd_alloc_bandwidth(dev, NULL,  						alt, intf->cur_altsetting);  		} -		mutex_unlock(&hcd->bandwidth_mutex); +		usb_enable_lpm(dev); +		mutex_unlock(hcd->bandwidth_mutex);  		return retval;  	}  	retval = usb_control_msg(dev, usb_sndctrlpipe(dev, 0), @@ -1451,7 +1512,7 @@ reset_old_alts:  			NULL, 0, USB_CTRL_SET_TIMEOUT);  	if (retval < 0)  		goto reset_old_alts; -	mutex_unlock(&hcd->bandwidth_mutex); +	mutex_unlock(hcd->bandwidth_mutex);  	/* re-init hc/hcd interface/endpoint state */  	for (i = 0; i < config->desc.bNumInterfaces; i++) { @@ -1479,6 +1540,8 @@ reset_old_alts:  			create_intf_ep_devs(intf);  		}  	} +	/* Now that the interfaces are installed, re-enable LPM. */ +	usb_unlocked_enable_lpm(dev);  	return 0;  }  EXPORT_SYMBOL_GPL(usb_reset_configuration); @@ -1493,7 +1556,6 @@ static void usb_release_interface(struct device *dev)  	kfree(intf);  } -#ifdef	CONFIG_HOTPLUG  static int usb_if_uevent(struct device *dev, struct kobj_uevent_env *env)  {  	struct usb_device *usb_dev; @@ -1512,7 +1574,7 @@ static int usb_if_uevent(struct device *dev, struct kobj_uevent_env *env)  	if (add_uevent_var(env,  		   "MODALIAS=usb:" -		   "v%04Xp%04Xd%04Xdc%02Xdsc%02Xdp%02Xic%02Xisc%02Xip%02X", +		   "v%04Xp%04Xd%04Xdc%02Xdsc%02Xdp%02Xic%02Xisc%02Xip%02Xin%02X",  		   le16_to_cpu(usb_dev->descriptor.idVendor),  		   le16_to_cpu(usb_dev->descriptor.idProduct),  		   le16_to_cpu(usb_dev->descriptor.bcdDevice), @@ -1521,20 +1583,13 @@ static int usb_if_uevent(struct device *dev, struct kobj_uevent_env *env)  		   usb_dev->descriptor.bDeviceProtocol,  		   alt->desc.bInterfaceClass,  		   alt->desc.bInterfaceSubClass, -		   alt->desc.bInterfaceProtocol)) +		   alt->desc.bInterfaceProtocol, +		   alt->desc.bInterfaceNumber))  		return -ENOMEM;  	return 0;  } -#else - -static int usb_if_uevent(struct device *dev, struct kobj_uevent_env *env) -{ -	return -ENODEV; -} -#endif	/* CONFIG_HOTPLUG */ -  struct device_type usb_if_device_type = {  	.name =		"usb_interface",  	.release =	usb_release_interface, @@ -1712,7 +1767,7 @@ free_interfaces:  			}  		} -		i = dev->bus_mA - cp->desc.bMaxPower * 2; +		i = dev->bus_mA - usb_get_max_power(dev, cp);  		if (i < 0)  			dev_warn(&dev->dev, "new config #%d exceeds power "  					"limit by %dmA\n", @@ -1739,36 +1794,28 @@ free_interfaces:  	 * host controller will not allow submissions to dropped endpoints.  If  	 * this call fails, the device state is unchanged.  	 */ -	mutex_lock(&hcd->bandwidth_mutex); -	ret = usb_hcd_alloc_bandwidth(dev, cp, NULL, NULL); -	if (ret < 0) { -		mutex_unlock(&hcd->bandwidth_mutex); -		usb_autosuspend_device(dev); +	mutex_lock(hcd->bandwidth_mutex); +	/* Disable LPM, and re-enable it once the new configuration is +	 * installed, so that the xHCI driver can recalculate the U1/U2 +	 * timeouts. +	 */ +	if (dev->actconfig && usb_disable_lpm(dev)) { +		dev_err(&dev->dev, "%s Failed to disable LPM\n.", __func__); +		mutex_unlock(hcd->bandwidth_mutex); +		ret = -ENOMEM;  		goto free_interfaces;  	} - -	ret = usb_control_msg(dev, usb_sndctrlpipe(dev, 0), -			      USB_REQ_SET_CONFIGURATION, 0, configuration, 0, -			      NULL, 0, USB_CTRL_SET_TIMEOUT); +	ret = usb_hcd_alloc_bandwidth(dev, cp, NULL, NULL);  	if (ret < 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) { -		usb_set_device_state(dev, USB_STATE_ADDRESS); -		usb_hcd_alloc_bandwidth(dev, NULL, NULL, NULL); -		mutex_unlock(&hcd->bandwidth_mutex); +		if (dev->actconfig) +			usb_enable_lpm(dev); +		mutex_unlock(hcd->bandwidth_mutex);  		usb_autosuspend_device(dev);  		goto free_interfaces;  	} -	mutex_unlock(&hcd->bandwidth_mutex); -	usb_set_device_state(dev, USB_STATE_CONFIGURED); -	/* Initialize the new interface structures and the +	/* +	 * Initialize the new interface structures and the  	 * hc/hcd/usbcore interface/endpoint state.  	 */  	for (i = 0; i < nintf; ++i) { @@ -1780,7 +1827,6 @@ free_interfaces:  		intfc = cp->intf_cache[i];  		intf->altsetting = intfc->altsetting;  		intf->num_altsetting = intfc->num_altsetting; -		intf->intf_assoc = find_iad(dev, cp, i);  		kref_get(&intfc->ref);  		alt = usb_altnum_to_altsetting(intf, 0); @@ -1793,6 +1839,8 @@ free_interfaces:  		if (!alt)  			alt = &intf->altsetting[0]; +		intf->intf_assoc = +			find_iad(dev, cp, alt->desc.bInterfaceNumber);  		intf->cur_altsetting = alt;  		usb_enable_interface(dev, intf, true);  		intf->dev.parent = &dev->dev; @@ -1804,16 +1852,51 @@ free_interfaces:  		INIT_WORK(&intf->reset_ws, __usb_queue_reset_device);  		intf->minor = -1;  		device_initialize(&intf->dev); +		pm_runtime_no_callbacks(&intf->dev);  		dev_set_name(&intf->dev, "%d-%s:%d.%d",  			dev->bus->busnum, dev->devpath,  			configuration, alt->desc.bInterfaceNumber);  	}  	kfree(new_interfaces); +	ret = usb_control_msg(dev, usb_sndctrlpipe(dev, 0), +			      USB_REQ_SET_CONFIGURATION, 0, configuration, 0, +			      NULL, 0, USB_CTRL_SET_TIMEOUT); +	if (ret < 0 && cp) { +		/* +		 * All the old state is gone, so what else can we do? +		 * The device is probably useless now anyway. +		 */ +		usb_hcd_alloc_bandwidth(dev, NULL, NULL, NULL); +		for (i = 0; i < nintf; ++i) { +			usb_disable_interface(dev, cp->interface[i], true); +			put_device(&cp->interface[i]->dev); +			cp->interface[i] = NULL; +		} +		cp = NULL; +	} + +	dev->actconfig = cp; +	mutex_unlock(hcd->bandwidth_mutex); + +	if (!cp) { +		usb_set_device_state(dev, USB_STATE_ADDRESS); + +		/* Leave LPM disabled while the device is unconfigured. */ +		usb_autosuspend_device(dev); +		return ret; +	} +	usb_set_device_state(dev, USB_STATE_CONFIGURED); +  	if (cp->string == NULL &&  			!(dev->quirks & USB_QUIRK_CONFIG_INTF_STRINGS))  		cp->string = usb_cache_string(dev, cp->desc.iConfiguration); +	/* Now that the interfaces are installed, re-enable LPM. */ +	usb_unlocked_enable_lpm(dev); +	/* Enable LTM if it was turned off by usb_disable_device. */ +	usb_enable_ltm(dev); +  	/* Now that all the interfaces are set up, register them  	 * to trigger binding of drivers to interfaces.  probe()  	 * routines may install different altsettings and may @@ -1840,6 +1923,7 @@ free_interfaces:  	usb_autosuspend_device(dev);  	return 0;  } +EXPORT_SYMBOL_GPL(usb_set_configuration);  static LIST_HEAD(set_config_list);  static DEFINE_SPINLOCK(set_config_lock); @@ -1901,7 +1985,7 @@ static void cancel_async_set_config(struct usb_device *udev)   * routine gets around the normal restrictions by using a work thread to   * submit the change-config request.   * - * Returns 0 if the request was successfully queued, error code otherwise. + * Return: 0 if the request was successfully queued, error code otherwise.   * The caller has no way to know whether the queued request will eventually   * succeed.   */  | 
