diff options
Diffstat (limited to 'drivers/usb/core')
| -rw-r--r-- | drivers/usb/core/Kconfig | 19 | ||||
| -rw-r--r-- | drivers/usb/core/Makefile | 2 | ||||
| -rw-r--r-- | drivers/usb/core/buffer.c | 2 | ||||
| -rw-r--r-- | drivers/usb/core/config.c | 13 | ||||
| -rw-r--r-- | drivers/usb/core/devio.c | 342 | ||||
| -rw-r--r-- | drivers/usb/core/driver.c | 180 | ||||
| -rw-r--r-- | drivers/usb/core/file.c | 24 | ||||
| -rw-r--r-- | drivers/usb/core/generic.c | 1 | ||||
| -rw-r--r-- | drivers/usb/core/hcd-pci.c | 7 | ||||
| -rw-r--r-- | drivers/usb/core/hcd.c | 241 | ||||
| -rw-r--r-- | drivers/usb/core/hub.c | 1369 | ||||
| -rw-r--r-- | drivers/usb/core/hub.h | 47 | ||||
| -rw-r--r-- | drivers/usb/core/message.c | 19 | ||||
| -rw-r--r-- | drivers/usb/core/port.c | 354 | ||||
| -rw-r--r-- | drivers/usb/core/quirks.c | 44 | ||||
| -rw-r--r-- | drivers/usb/core/sysfs.c | 66 | ||||
| -rw-r--r-- | drivers/usb/core/urb.c | 71 | ||||
| -rw-r--r-- | drivers/usb/core/usb-acpi.c | 140 | ||||
| -rw-r--r-- | drivers/usb/core/usb.c | 2 | ||||
| -rw-r--r-- | drivers/usb/core/usb.h | 26 | 
20 files changed, 1928 insertions, 1041 deletions
diff --git a/drivers/usb/core/Kconfig b/drivers/usb/core/Kconfig index db535b0aa17..1060657ca1b 100644 --- a/drivers/usb/core/Kconfig +++ b/drivers/usb/core/Kconfig @@ -1,16 +1,8 @@  #  # USB Core configuration  # -config USB_DEBUG -	bool "USB verbose debug messages" -	help -	  Say Y here if you want the USB core & hub drivers to produce a bunch -	  of debug messages to the system log. Select this if you are having a -	  problem with USB support and want to see more of what is going on. -  config USB_ANNOUNCE_NEW_DEVICES  	bool "USB announce new devices" -	default N  	help  	  Say Y here if you want the USB core to always announce the  	  idVendor, idProduct, Manufacturer, Product, and SerialNumber @@ -28,7 +20,7 @@ config USB_DEFAULT_PERSIST  	bool "Enable USB persist by default"  	default y  	help -	  Say N here if you don't want USB power session persistance +	  Say N here if you don't want USB power session persistence  	  enabled by default.  If you say N it will make suspended USB  	  devices that lose power get reenumerated as if they had been  	  unplugged, causing any mounted filesystems to be lost.  The @@ -89,3 +81,12 @@ config USB_OTG_BLACKLIST_HUB  	  and software costs by not supporting external hubs.  So  	  are "Embedded Hosts" that don't offer OTG support. +config USB_OTG_FSM +	tristate "USB 2.0 OTG FSM implementation" +	depends on USB +	select USB_OTG +	select USB_PHY +	help +	  Implements OTG Finite State Machine as specified in On-The-Go +	  and Embedded Host Supplement to the USB Revision 2.0 Specification. + diff --git a/drivers/usb/core/Makefile b/drivers/usb/core/Makefile index 5e847ad2f58..2f6f9322004 100644 --- a/drivers/usb/core/Makefile +++ b/drivers/usb/core/Makefile @@ -2,8 +2,6 @@  # Makefile for USB Core files and filesystem  # -ccflags-$(CONFIG_USB_DEBUG) := -DDEBUG -  usbcore-y := usb.o hub.o hcd.o urb.o message.o driver.o  usbcore-y += config.o file.o buffer.o sysfs.o endpoint.o  usbcore-y += devio.o notify.o generic.o quirks.o devices.o diff --git a/drivers/usb/core/buffer.c b/drivers/usb/core/buffer.c index 23559746be9..684ef70dc09 100644 --- a/drivers/usb/core/buffer.c +++ b/drivers/usb/core/buffer.c @@ -2,7 +2,7 @@   * DMA memory management for framework level HCD code (hc_driver)   *   * This implementation plugs in through generic "usb_bus" level methods, - * and should work with all USB controllers, regardles of bus type. + * and should work with all USB controllers, regardless of bus type.   */  #include <linux/module.h> diff --git a/drivers/usb/core/config.c b/drivers/usb/core/config.c index a6b2cabe793..1ab4df1de2d 100644 --- a/drivers/usb/core/config.c +++ b/drivers/usb/core/config.c @@ -3,7 +3,6 @@  #include <linux/usb/hcd.h>  #include <linux/usb/quirks.h>  #include <linux/module.h> -#include <linux/init.h>  #include <linux/slab.h>  #include <linux/device.h>  #include <asm/byteorder.h> @@ -11,7 +10,6 @@  #define USB_MAXALTSETTING		128	/* Hard limit */ -#define USB_MAXENDPOINTS		30	/* Hard limit */  #define USB_MAXCONFIG			8	/* Arbitrary limit */ @@ -651,10 +649,6 @@ void usb_destroy_configuration(struct usb_device *dev)   *   * hub-only!! ... and only in reset path, or usb_new_device()   * (used by real hubs and virtual root hubs) - * - * NOTE: if this is a WUSB device and is not authorized, we skip the - *       whole thing. A non-authorized USB device has no - *       configurations.   */  int usb_get_configuration(struct usb_device *dev)  { @@ -666,8 +660,6 @@ int usb_get_configuration(struct usb_device *dev)  	struct usb_config_descriptor *desc;  	cfgno = 0; -	if (dev->authorized == 0)	/* Not really an error */ -		goto out_not_authorized;  	result = -ENOMEM;  	if (ncfg > USB_MAXCONFIG) {  		dev_warn(ddev, "too many configurations: %d, " @@ -724,6 +716,10 @@ int usb_get_configuration(struct usb_device *dev)  			result = -ENOMEM;  			goto err;  		} + +		if (dev->quirks & USB_QUIRK_DELAY_INIT) +			msleep(100); +  		result = usb_get_descriptor(dev, USB_DT_CONFIG, cfgno,  		    bigbuffer, length);  		if (result < 0) { @@ -751,7 +747,6 @@ int usb_get_configuration(struct usb_device *dev)  err:  	kfree(desc); -out_not_authorized:  	dev->descriptor.bNumConfigurations = cfgno;  err2:  	if (result == -ENOMEM) diff --git a/drivers/usb/core/devio.c b/drivers/usb/core/devio.c index 737e3c19967..257876ea03a 100644 --- a/drivers/usb/core/devio.c +++ b/drivers/usb/core/devio.c @@ -62,7 +62,7 @@  /* Mutual exclusion for removal, open, and release */  DEFINE_MUTEX(usbfs_mutex); -struct dev_state { +struct usb_dev_state {  	struct list_head list;      /* state list */  	struct usb_device *dev;  	struct file *file; @@ -81,7 +81,7 @@ struct dev_state {  struct async {  	struct list_head asynclist; -	struct dev_state *ps; +	struct usb_dev_state *ps;  	struct pid *pid;  	const struct cred *cred;  	unsigned int signr; @@ -118,7 +118,7 @@ module_param(usbfs_memory_mb, uint, 0644);  MODULE_PARM_DESC(usbfs_memory_mb,  		"maximum MB allowed for usbfs buffers (0 = no limit)"); -/* Hard limit, necessary to avoid aithmetic overflow */ +/* Hard limit, necessary to avoid arithmetic overflow */  #define USBFS_XFER_MAX		(UINT_MAX / 2 - 1000000)  static atomic_t usbfs_memory_usage;	/* Total memory currently allocated */ @@ -151,7 +151,7 @@ static void usbfs_decrease_memory_usage(unsigned amount)  	atomic_sub(amount, &usbfs_memory_usage);  } -static int connected(struct dev_state *ps) +static int connected(struct usb_dev_state *ps)  {  	return (!list_empty(&ps->list) &&  			ps->dev->state != USB_STATE_NOTATTACHED); @@ -184,7 +184,7 @@ static loff_t usbdev_lseek(struct file *file, loff_t offset, int orig)  static ssize_t usbdev_read(struct file *file, char __user *buf, size_t nbytes,  			   loff_t *ppos)  { -	struct dev_state *ps = file->private_data; +	struct usb_dev_state *ps = file->private_data;  	struct usb_device *dev = ps->dev;  	ssize_t ret = 0;  	unsigned len; @@ -307,7 +307,7 @@ static void free_async(struct async *as)  static void async_newpending(struct async *as)  { -	struct dev_state *ps = as->ps; +	struct usb_dev_state *ps = as->ps;  	unsigned long flags;  	spin_lock_irqsave(&ps->lock, flags); @@ -317,7 +317,7 @@ static void async_newpending(struct async *as)  static void async_removepending(struct async *as)  { -	struct dev_state *ps = as->ps; +	struct usb_dev_state *ps = as->ps;  	unsigned long flags;  	spin_lock_irqsave(&ps->lock, flags); @@ -325,7 +325,7 @@ static void async_removepending(struct async *as)  	spin_unlock_irqrestore(&ps->lock, flags);  } -static struct async *async_getcompleted(struct dev_state *ps) +static struct async *async_getcompleted(struct usb_dev_state *ps)  {  	unsigned long flags;  	struct async *as = NULL; @@ -340,7 +340,7 @@ static struct async *async_getcompleted(struct dev_state *ps)  	return as;  } -static struct async *async_getpending(struct dev_state *ps, +static struct async *async_getpending(struct usb_dev_state *ps,  					     void __user *userurb)  {  	struct async *as; @@ -448,7 +448,7 @@ static int copy_urb_data_to_user(u8 __user *userbuffer, struct urb *urb)  #define AS_CONTINUATION	1  #define AS_UNLINK	2 -static void cancel_bulk_urbs(struct dev_state *ps, unsigned bulk_addr) +static void cancel_bulk_urbs(struct usb_dev_state *ps, unsigned bulk_addr)  __releases(ps->lock)  __acquires(ps->lock)  { @@ -489,7 +489,7 @@ __acquires(ps->lock)  static void async_completed(struct urb *urb)  {  	struct async *as = urb->context; -	struct dev_state *ps = as->ps; +	struct usb_dev_state *ps = as->ps;  	struct siginfo sinfo;  	struct pid *pid = NULL;  	u32 secid = 0; @@ -529,7 +529,7 @@ static void async_completed(struct urb *urb)  	wake_up(&ps->wait);  } -static void destroy_async(struct dev_state *ps, struct list_head *list) +static void destroy_async(struct usb_dev_state *ps, struct list_head *list)  {  	struct urb *urb;  	struct async *as; @@ -551,7 +551,7 @@ static void destroy_async(struct dev_state *ps, struct list_head *list)  	spin_unlock_irqrestore(&ps->lock, flags);  } -static void destroy_async_on_interface(struct dev_state *ps, +static void destroy_async_on_interface(struct usb_dev_state *ps,  				       unsigned int ifnum)  {  	struct list_head *p, *q, hitlist; @@ -566,7 +566,7 @@ static void destroy_async_on_interface(struct dev_state *ps,  	destroy_async(ps, &hitlist);  } -static void destroy_all_async(struct dev_state *ps) +static void destroy_all_async(struct usb_dev_state *ps)  {  	destroy_async(ps, &ps->async_pending);  } @@ -585,7 +585,7 @@ static int driver_probe(struct usb_interface *intf,  static void driver_disconnect(struct usb_interface *intf)  { -	struct dev_state *ps = usb_get_intfdata(intf); +	struct usb_dev_state *ps = usb_get_intfdata(intf);  	unsigned int ifnum = intf->altsetting->desc.bInterfaceNumber;  	if (!ps) @@ -628,7 +628,7 @@ struct usb_driver usbfs_driver = {  	.resume =	driver_resume,  }; -static int claimintf(struct dev_state *ps, unsigned int ifnum) +static int claimintf(struct usb_dev_state *ps, unsigned int ifnum)  {  	struct usb_device *dev = ps->dev;  	struct usb_interface *intf; @@ -650,7 +650,7 @@ static int claimintf(struct dev_state *ps, unsigned int ifnum)  	return err;  } -static int releaseintf(struct dev_state *ps, unsigned int ifnum) +static int releaseintf(struct usb_dev_state *ps, unsigned int ifnum)  {  	struct usb_device *dev;  	struct usb_interface *intf; @@ -670,7 +670,7 @@ static int releaseintf(struct dev_state *ps, unsigned int ifnum)  	return err;  } -static int checkintf(struct dev_state *ps, unsigned int ifnum) +static int checkintf(struct usb_dev_state *ps, unsigned int ifnum)  {  	if (ps->dev->state != USB_STATE_CONFIGURED)  		return -EHOSTUNREACH; @@ -710,7 +710,7 @@ static int findintfep(struct usb_device *dev, unsigned int ep)  	return -ENOENT;  } -static int check_ctrlrecip(struct dev_state *ps, unsigned int requesttype, +static int check_ctrlrecip(struct usb_dev_state *ps, unsigned int requesttype,  			   unsigned int request, unsigned int index)  {  	int ret = 0; @@ -742,6 +742,22 @@ static int check_ctrlrecip(struct dev_state *ps, unsigned int requesttype,  		if ((index & ~USB_DIR_IN) == 0)  			return 0;  		ret = findintfep(ps->dev, index); +		if (ret < 0) { +			/* +			 * Some not fully compliant Win apps seem to get +			 * index wrong and have the endpoint number here +			 * rather than the endpoint address (with the +			 * correct direction). Win does let this through, +			 * so we'll not reject it here but leave it to +			 * the device to not break KVM. But we warn. +			 */ +			ret = findintfep(ps->dev, index ^ 0x80); +			if (ret >= 0) +				dev_info(&ps->dev->dev, +					"%s: process %i (%s) requesting ep %02x but needs %02x\n", +					__func__, task_pid_nr(current), +					current->comm, index, index ^ 0x80); +		}  		if (ret >= 0)  			ret = checkintf(ps, ret);  		break; @@ -753,6 +769,88 @@ static int check_ctrlrecip(struct dev_state *ps, unsigned int requesttype,  	return ret;  } +static struct usb_host_endpoint *ep_to_host_endpoint(struct usb_device *dev, +						     unsigned char ep) +{ +	if (ep & USB_ENDPOINT_DIR_MASK) +		return dev->ep_in[ep & USB_ENDPOINT_NUMBER_MASK]; +	else +		return dev->ep_out[ep & USB_ENDPOINT_NUMBER_MASK]; +} + +static int parse_usbdevfs_streams(struct usb_dev_state *ps, +				  struct usbdevfs_streams __user *streams, +				  unsigned int *num_streams_ret, +				  unsigned int *num_eps_ret, +				  struct usb_host_endpoint ***eps_ret, +				  struct usb_interface **intf_ret) +{ +	unsigned int i, num_streams, num_eps; +	struct usb_host_endpoint **eps; +	struct usb_interface *intf = NULL; +	unsigned char ep; +	int ifnum, ret; + +	if (get_user(num_streams, &streams->num_streams) || +	    get_user(num_eps, &streams->num_eps)) +		return -EFAULT; + +	if (num_eps < 1 || num_eps > USB_MAXENDPOINTS) +		return -EINVAL; + +	/* The XHCI controller allows max 2 ^ 16 streams */ +	if (num_streams_ret && (num_streams < 2 || num_streams > 65536)) +		return -EINVAL; + +	eps = kmalloc(num_eps * sizeof(*eps), GFP_KERNEL); +	if (!eps) +		return -ENOMEM; + +	for (i = 0; i < num_eps; i++) { +		if (get_user(ep, &streams->eps[i])) { +			ret = -EFAULT; +			goto error; +		} +		eps[i] = ep_to_host_endpoint(ps->dev, ep); +		if (!eps[i]) { +			ret = -EINVAL; +			goto error; +		} + +		/* usb_alloc/free_streams operate on an usb_interface */ +		ifnum = findintfep(ps->dev, ep); +		if (ifnum < 0) { +			ret = ifnum; +			goto error; +		} + +		if (i == 0) { +			ret = checkintf(ps, ifnum); +			if (ret < 0) +				goto error; +			intf = usb_ifnum_to_if(ps->dev, ifnum); +		} else { +			/* Verify all eps belong to the same interface */ +			if (ifnum != intf->altsetting->desc.bInterfaceNumber) { +				ret = -EINVAL; +				goto error; +			} +		} +	} + +	if (num_streams_ret) +		*num_streams_ret = num_streams; +	*num_eps_ret = num_eps; +	*eps_ret = eps; +	*intf_ret = intf; + +	return 0; + +error: +	kfree(eps); +	return ret; +} +  static int match_devt(struct device *dev, void *data)  {  	return dev->devt == (dev_t) (unsigned long) data; @@ -775,11 +873,11 @@ static struct usb_device *usbdev_lookup_by_devt(dev_t devt)  static int usbdev_open(struct inode *inode, struct file *file)  {  	struct usb_device *dev = NULL; -	struct dev_state *ps; +	struct usb_dev_state *ps;  	int ret;  	ret = -ENOMEM; -	ps = kmalloc(sizeof(struct dev_state), GFP_KERNEL); +	ps = kmalloc(sizeof(struct usb_dev_state), GFP_KERNEL);  	if (!ps)  		goto out_free_ps; @@ -836,7 +934,7 @@ static int usbdev_open(struct inode *inode, struct file *file)  static int usbdev_release(struct inode *inode, struct file *file)  { -	struct dev_state *ps = file->private_data; +	struct usb_dev_state *ps = file->private_data;  	struct usb_device *dev = ps->dev;  	unsigned int ifnum;  	struct async *as; @@ -867,7 +965,7 @@ static int usbdev_release(struct inode *inode, struct file *file)  	return 0;  } -static int proc_control(struct dev_state *ps, void __user *arg) +static int proc_control(struct usb_dev_state *ps, void __user *arg)  {  	struct usb_device *dev = ps->dev;  	struct usbdevfs_ctrltransfer ctrl; @@ -898,10 +996,8 @@ static int proc_control(struct dev_state *ps, void __user *arg)  	snoop(&dev->dev, "control urb: bRequestType=%02x "  		"bRequest=%02x wValue=%04x "  		"wIndex=%04x wLength=%04x\n", -		ctrl.bRequestType, ctrl.bRequest, -		__le16_to_cpup(&ctrl.wValue), -		__le16_to_cpup(&ctrl.wIndex), -		__le16_to_cpup(&ctrl.wLength)); +		ctrl.bRequestType, ctrl.bRequest, ctrl.wValue, +		ctrl.wIndex, ctrl.wLength);  	if (ctrl.bRequestType & 0x80) {  		if (ctrl.wLength && !access_ok(VERIFY_WRITE, ctrl.data,  					       ctrl.wLength)) { @@ -956,7 +1052,7 @@ static int proc_control(struct dev_state *ps, void __user *arg)  	return ret;  } -static int proc_bulk(struct dev_state *ps, void __user *arg) +static int proc_bulk(struct usb_dev_state *ps, void __user *arg)  {  	struct usb_device *dev = ps->dev;  	struct usbdevfs_bulktransfer bulk; @@ -1029,7 +1125,21 @@ static int proc_bulk(struct dev_state *ps, void __user *arg)  	return ret;  } -static int proc_resetep(struct dev_state *ps, void __user *arg) +static void check_reset_of_active_ep(struct usb_device *udev, +		unsigned int epnum, char *ioctl_name) +{ +	struct usb_host_endpoint **eps; +	struct usb_host_endpoint *ep; + +	eps = (epnum & USB_DIR_IN) ? udev->ep_in : udev->ep_out; +	ep = eps[epnum & 0x0f]; +	if (ep && !list_empty(&ep->urb_list)) +		dev_warn(&udev->dev, "Process %d (%s) called USBDEVFS_%s for active endpoint 0x%02x\n", +				task_pid_nr(current), current->comm, +				ioctl_name, epnum); +} + +static int proc_resetep(struct usb_dev_state *ps, void __user *arg)  {  	unsigned int ep;  	int ret; @@ -1042,11 +1152,12 @@ static int proc_resetep(struct dev_state *ps, void __user *arg)  	ret = checkintf(ps, ret);  	if (ret)  		return ret; +	check_reset_of_active_ep(ps->dev, ep, "RESETEP");  	usb_reset_endpoint(ps->dev, ep);  	return 0;  } -static int proc_clearhalt(struct dev_state *ps, void __user *arg) +static int proc_clearhalt(struct usb_dev_state *ps, void __user *arg)  {  	unsigned int ep;  	int pipe; @@ -1060,6 +1171,7 @@ static int proc_clearhalt(struct dev_state *ps, void __user *arg)  	ret = checkintf(ps, ret);  	if (ret)  		return ret; +	check_reset_of_active_ep(ps->dev, ep, "CLEAR_HALT");  	if (ep & USB_DIR_IN)  		pipe = usb_rcvbulkpipe(ps->dev, ep & 0x7f);  	else @@ -1068,7 +1180,7 @@ static int proc_clearhalt(struct dev_state *ps, void __user *arg)  	return usb_clear_halt(ps->dev, pipe);  } -static int proc_getdriver(struct dev_state *ps, void __user *arg) +static int proc_getdriver(struct usb_dev_state *ps, void __user *arg)  {  	struct usbdevfs_getdriver gd;  	struct usb_interface *intf; @@ -1087,7 +1199,7 @@ static int proc_getdriver(struct dev_state *ps, void __user *arg)  	return ret;  } -static int proc_connectinfo(struct dev_state *ps, void __user *arg) +static int proc_connectinfo(struct usb_dev_state *ps, void __user *arg)  {  	struct usbdevfs_connectinfo ci = {  		.devnum = ps->dev->devnum, @@ -1099,12 +1211,12 @@ static int proc_connectinfo(struct dev_state *ps, void __user *arg)  	return 0;  } -static int proc_resetdevice(struct dev_state *ps) +static int proc_resetdevice(struct usb_dev_state *ps)  {  	return usb_reset_device(ps->dev);  } -static int proc_setintf(struct dev_state *ps, void __user *arg) +static int proc_setintf(struct usb_dev_state *ps, void __user *arg)  {  	struct usbdevfs_setinterface setintf;  	int ret; @@ -1113,11 +1225,14 @@ static int proc_setintf(struct dev_state *ps, void __user *arg)  		return -EFAULT;  	if ((ret = checkintf(ps, setintf.interface)))  		return ret; + +	destroy_async_on_interface(ps, setintf.interface); +  	return usb_set_interface(ps->dev, setintf.interface,  			setintf.altsetting);  } -static int proc_setconfig(struct dev_state *ps, void __user *arg) +static int proc_setconfig(struct usb_dev_state *ps, void __user *arg)  {  	int u;  	int status = 0; @@ -1165,7 +1280,7 @@ static int proc_setconfig(struct dev_state *ps, void __user *arg)  	return status;  } -static int proc_do_submiturb(struct dev_state *ps, struct usbdevfs_urb *uurb, +static int proc_do_submiturb(struct usb_dev_state *ps, struct usbdevfs_urb *uurb,  			struct usbdevfs_iso_packet_desc __user *iso_frame_desc,  			void __user *arg)  { @@ -1175,6 +1290,8 @@ static int proc_do_submiturb(struct dev_state *ps, struct usbdevfs_urb *uurb,  	struct usb_ctrlrequest *dr = NULL;  	unsigned int u, totlen, isofrmlen;  	int i, ret, is_in, num_sgs = 0, ifnum = -1; +	int number_of_packets = 0; +	unsigned int stream_id = 0;  	void *buf;  	if (uurb->flags & ~(USBDEVFS_URB_ISO_ASAP | @@ -1195,15 +1312,10 @@ static int proc_do_submiturb(struct dev_state *ps, struct usbdevfs_urb *uurb,  		if (ret)  			return ret;  	} -	if ((uurb->endpoint & USB_ENDPOINT_DIR_MASK) != 0) { -		is_in = 1; -		ep = ps->dev->ep_in[uurb->endpoint & USB_ENDPOINT_NUMBER_MASK]; -	} else { -		is_in = 0; -		ep = ps->dev->ep_out[uurb->endpoint & USB_ENDPOINT_NUMBER_MASK]; -	} +	ep = ep_to_host_endpoint(ps->dev, uurb->endpoint);  	if (!ep)  		return -ENOENT; +	is_in = (uurb->endpoint & USB_ENDPOINT_DIR_MASK) != 0;  	u = 0;  	switch(uurb->type) { @@ -1228,7 +1340,6 @@ static int proc_do_submiturb(struct dev_state *ps, struct usbdevfs_urb *uurb,  				      le16_to_cpup(&dr->wIndex));  		if (ret)  			goto error; -		uurb->number_of_packets = 0;  		uurb->buffer_length = le16_to_cpup(&dr->wLength);  		uurb->buffer += 8;  		if ((dr->bRequestType & USB_DIR_IN) && uurb->buffer_length) { @@ -1258,17 +1369,17 @@ static int proc_do_submiturb(struct dev_state *ps, struct usbdevfs_urb *uurb,  			uurb->type = USBDEVFS_URB_TYPE_INTERRUPT;  			goto interrupt_urb;  		} -		uurb->number_of_packets = 0;  		num_sgs = DIV_ROUND_UP(uurb->buffer_length, USB_SG_SIZE);  		if (num_sgs == 1 || num_sgs > ps->dev->bus->sg_tablesize)  			num_sgs = 0; +		if (ep->streams) +			stream_id = uurb->stream_id;  		break;  	case USBDEVFS_URB_TYPE_INTERRUPT:  		if (!usb_endpoint_xfer_int(&ep->desc))  			return -EINVAL;   interrupt_urb: -		uurb->number_of_packets = 0;  		break;  	case USBDEVFS_URB_TYPE_ISO: @@ -1278,15 +1389,16 @@ static int proc_do_submiturb(struct dev_state *ps, struct usbdevfs_urb *uurb,  			return -EINVAL;  		if (!usb_endpoint_xfer_isoc(&ep->desc))  			return -EINVAL; +		number_of_packets = uurb->number_of_packets;  		isofrmlen = sizeof(struct usbdevfs_iso_packet_desc) * -				   uurb->number_of_packets; +				   number_of_packets;  		if (!(isopkt = kmalloc(isofrmlen, GFP_KERNEL)))  			return -ENOMEM;  		if (copy_from_user(isopkt, iso_frame_desc, isofrmlen)) {  			ret = -EFAULT;  			goto error;  		} -		for (totlen = u = 0; u < uurb->number_of_packets; u++) { +		for (totlen = u = 0; u < number_of_packets; u++) {  			/*  			 * arbitrary limit need for USB 3.0  			 * bMaxBurst (0~15 allowed, 1~16 packets) @@ -1317,7 +1429,7 @@ static int proc_do_submiturb(struct dev_state *ps, struct usbdevfs_urb *uurb,  		ret = -EFAULT;  		goto error;  	} -	as = alloc_async(uurb->number_of_packets); +	as = alloc_async(number_of_packets);  	if (!as) {  		ret = -ENOMEM;  		goto error; @@ -1411,7 +1523,8 @@ static int proc_do_submiturb(struct dev_state *ps, struct usbdevfs_urb *uurb,  	as->urb->setup_packet = (unsigned char *)dr;  	dr = NULL;  	as->urb->start_frame = uurb->start_frame; -	as->urb->number_of_packets = uurb->number_of_packets; +	as->urb->number_of_packets = number_of_packets; +	as->urb->stream_id = stream_id;  	if (uurb->type == USBDEVFS_URB_TYPE_ISO ||  			ps->dev->speed == USB_SPEED_HIGH)  		as->urb->interval = 1 << min(15, ep->desc.bInterval - 1); @@ -1419,7 +1532,7 @@ static int proc_do_submiturb(struct dev_state *ps, struct usbdevfs_urb *uurb,  		as->urb->interval = ep->desc.bInterval;  	as->urb->context = as;  	as->urb->complete = async_completed; -	for (totlen = u = 0; u < uurb->number_of_packets; u++) { +	for (totlen = u = 0; u < number_of_packets; u++) {  		as->urb->iso_frame_desc[u].offset = totlen;  		as->urb->iso_frame_desc[u].length = isopkt[u].length;  		totlen += isopkt[u].length; @@ -1494,7 +1607,7 @@ static int proc_do_submiturb(struct dev_state *ps, struct usbdevfs_urb *uurb,  	return ret;  } -static int proc_submiturb(struct dev_state *ps, void __user *arg) +static int proc_submiturb(struct usb_dev_state *ps, void __user *arg)  {  	struct usbdevfs_urb uurb; @@ -1506,7 +1619,7 @@ static int proc_submiturb(struct dev_state *ps, void __user *arg)  			arg);  } -static int proc_unlinkurb(struct dev_state *ps, void __user *arg) +static int proc_unlinkurb(struct usb_dev_state *ps, void __user *arg)  {  	struct urb *urb;  	struct async *as; @@ -1566,7 +1679,7 @@ err_out:  	return -EFAULT;  } -static struct async *reap_as(struct dev_state *ps) +static struct async *reap_as(struct usb_dev_state *ps)  {  	DECLARE_WAITQUEUE(wait, current);  	struct async *as = NULL; @@ -1589,7 +1702,7 @@ static struct async *reap_as(struct dev_state *ps)  	return as;  } -static int proc_reapurb(struct dev_state *ps, void __user *arg) +static int proc_reapurb(struct usb_dev_state *ps, void __user *arg)  {  	struct async *as = reap_as(ps);  	if (as) { @@ -1602,7 +1715,7 @@ static int proc_reapurb(struct dev_state *ps, void __user *arg)  	return -EIO;  } -static int proc_reapurbnonblock(struct dev_state *ps, void __user *arg) +static int proc_reapurbnonblock(struct usb_dev_state *ps, void __user *arg)  {  	int retval;  	struct async *as; @@ -1617,37 +1730,37 @@ static int proc_reapurbnonblock(struct dev_state *ps, void __user *arg)  }  #ifdef CONFIG_COMPAT -static int proc_control_compat(struct dev_state *ps, +static int proc_control_compat(struct usb_dev_state *ps,  				struct usbdevfs_ctrltransfer32 __user *p32)  { -        struct usbdevfs_ctrltransfer __user *p; -        __u32 udata; -        p = compat_alloc_user_space(sizeof(*p)); -        if (copy_in_user(p, p32, (sizeof(*p32) - sizeof(compat_caddr_t))) || -            get_user(udata, &p32->data) || +	struct usbdevfs_ctrltransfer __user *p; +	__u32 udata; +	p = compat_alloc_user_space(sizeof(*p)); +	if (copy_in_user(p, p32, (sizeof(*p32) - sizeof(compat_caddr_t))) || +	    get_user(udata, &p32->data) ||  	    put_user(compat_ptr(udata), &p->data))  		return -EFAULT; -        return proc_control(ps, p); +	return proc_control(ps, p);  } -static int proc_bulk_compat(struct dev_state *ps, +static int proc_bulk_compat(struct usb_dev_state *ps,  			struct usbdevfs_bulktransfer32 __user *p32)  { -        struct usbdevfs_bulktransfer __user *p; -        compat_uint_t n; -        compat_caddr_t addr; +	struct usbdevfs_bulktransfer __user *p; +	compat_uint_t n; +	compat_caddr_t addr; -        p = compat_alloc_user_space(sizeof(*p)); +	p = compat_alloc_user_space(sizeof(*p)); -        if (get_user(n, &p32->ep) || put_user(n, &p->ep) || -            get_user(n, &p32->len) || put_user(n, &p->len) || -            get_user(n, &p32->timeout) || put_user(n, &p->timeout) || -            get_user(addr, &p32->data) || put_user(compat_ptr(addr), &p->data)) -                return -EFAULT; +	if (get_user(n, &p32->ep) || put_user(n, &p->ep) || +	    get_user(n, &p32->len) || put_user(n, &p->len) || +	    get_user(n, &p32->timeout) || put_user(n, &p->timeout) || +	    get_user(addr, &p32->data) || put_user(compat_ptr(addr), &p->data)) +		return -EFAULT; -        return proc_bulk(ps, p); +	return proc_bulk(ps, p);  } -static int proc_disconnectsignal_compat(struct dev_state *ps, void __user *arg) +static int proc_disconnectsignal_compat(struct usb_dev_state *ps, void __user *arg)  {  	struct usbdevfs_disconnectsignal32 ds; @@ -1685,7 +1798,7 @@ static int get_urb32(struct usbdevfs_urb *kurb,  	return 0;  } -static int proc_submiturb_compat(struct dev_state *ps, void __user *arg) +static int proc_submiturb_compat(struct usb_dev_state *ps, void __user *arg)  {  	struct usbdevfs_urb uurb; @@ -1731,7 +1844,7 @@ static int processcompl_compat(struct async *as, void __user * __user *arg)  	return 0;  } -static int proc_reapurb_compat(struct dev_state *ps, void __user *arg) +static int proc_reapurb_compat(struct usb_dev_state *ps, void __user *arg)  {  	struct async *as = reap_as(ps);  	if (as) { @@ -1744,7 +1857,7 @@ static int proc_reapurb_compat(struct dev_state *ps, void __user *arg)  	return -EIO;  } -static int proc_reapurbnonblock_compat(struct dev_state *ps, void __user *arg) +static int proc_reapurbnonblock_compat(struct usb_dev_state *ps, void __user *arg)  {  	int retval;  	struct async *as; @@ -1761,7 +1874,7 @@ static int proc_reapurbnonblock_compat(struct dev_state *ps, void __user *arg)  #endif -static int proc_disconnectsignal(struct dev_state *ps, void __user *arg) +static int proc_disconnectsignal(struct usb_dev_state *ps, void __user *arg)  {  	struct usbdevfs_disconnectsignal ds; @@ -1772,7 +1885,7 @@ static int proc_disconnectsignal(struct dev_state *ps, void __user *arg)  	return 0;  } -static int proc_claiminterface(struct dev_state *ps, void __user *arg) +static int proc_claiminterface(struct usb_dev_state *ps, void __user *arg)  {  	unsigned int ifnum; @@ -1781,7 +1894,7 @@ static int proc_claiminterface(struct dev_state *ps, void __user *arg)  	return claimintf(ps, ifnum);  } -static int proc_releaseinterface(struct dev_state *ps, void __user *arg) +static int proc_releaseinterface(struct usb_dev_state *ps, void __user *arg)  {  	unsigned int ifnum;  	int ret; @@ -1794,7 +1907,7 @@ static int proc_releaseinterface(struct dev_state *ps, void __user *arg)  	return 0;  } -static int proc_ioctl(struct dev_state *ps, struct usbdevfs_ioctl *ctl) +static int proc_ioctl(struct usb_dev_state *ps, struct usbdevfs_ioctl *ctl)  {  	int			size;  	void			*buf = NULL; @@ -1870,7 +1983,7 @@ static int proc_ioctl(struct dev_state *ps, struct usbdevfs_ioctl *ctl)  	return retval;  } -static int proc_ioctl_default(struct dev_state *ps, void __user *arg) +static int proc_ioctl_default(struct usb_dev_state *ps, void __user *arg)  {  	struct usbdevfs_ioctl	ctrl; @@ -1880,7 +1993,7 @@ static int proc_ioctl_default(struct dev_state *ps, void __user *arg)  }  #ifdef CONFIG_COMPAT -static int proc_ioctl_compat(struct dev_state *ps, compat_uptr_t arg) +static int proc_ioctl_compat(struct usb_dev_state *ps, compat_uptr_t arg)  {  	struct usbdevfs_ioctl32 __user *uioc;  	struct usbdevfs_ioctl ctrl; @@ -1898,7 +2011,7 @@ static int proc_ioctl_compat(struct dev_state *ps, compat_uptr_t arg)  }  #endif -static int proc_claim_port(struct dev_state *ps, void __user *arg) +static int proc_claim_port(struct usb_dev_state *ps, void __user *arg)  {  	unsigned portnum;  	int rc; @@ -1912,7 +2025,7 @@ static int proc_claim_port(struct dev_state *ps, void __user *arg)  	return rc;  } -static int proc_release_port(struct dev_state *ps, void __user *arg) +static int proc_release_port(struct usb_dev_state *ps, void __user *arg)  {  	unsigned portnum; @@ -1921,7 +2034,7 @@ static int proc_release_port(struct dev_state *ps, void __user *arg)  	return usb_hub_release_port(ps->dev, portnum, ps);  } -static int proc_get_capabilities(struct dev_state *ps, void __user *arg) +static int proc_get_capabilities(struct usb_dev_state *ps, void __user *arg)  {  	__u32 caps; @@ -1937,7 +2050,7 @@ static int proc_get_capabilities(struct dev_state *ps, void __user *arg)  	return 0;  } -static int proc_disconnect_claim(struct dev_state *ps, void __user *arg) +static int proc_disconnect_claim(struct usb_dev_state *ps, void __user *arg)  {  	struct usbdevfs_disconnect_claim dc;  	struct usb_interface *intf; @@ -1969,6 +2082,45 @@ static int proc_disconnect_claim(struct dev_state *ps, void __user *arg)  	return claimintf(ps, dc.interface);  } +static int proc_alloc_streams(struct usb_dev_state *ps, void __user *arg) +{ +	unsigned num_streams, num_eps; +	struct usb_host_endpoint **eps; +	struct usb_interface *intf; +	int r; + +	r = parse_usbdevfs_streams(ps, arg, &num_streams, &num_eps, +				   &eps, &intf); +	if (r) +		return r; + +	destroy_async_on_interface(ps, +				   intf->altsetting[0].desc.bInterfaceNumber); + +	r = usb_alloc_streams(intf, eps, num_eps, num_streams, GFP_KERNEL); +	kfree(eps); +	return r; +} + +static int proc_free_streams(struct usb_dev_state *ps, void __user *arg) +{ +	unsigned num_eps; +	struct usb_host_endpoint **eps; +	struct usb_interface *intf; +	int r; + +	r = parse_usbdevfs_streams(ps, arg, NULL, &num_eps, &eps, &intf); +	if (r) +		return r; + +	destroy_async_on_interface(ps, +				   intf->altsetting[0].desc.bInterfaceNumber); + +	r = usb_free_streams(intf, eps, num_eps, GFP_KERNEL); +	kfree(eps); +	return r; +} +  /*   * NOTE:  All requests here that have interface numbers as parameters   * are assuming that somehow the configuration has been prevented from @@ -1977,7 +2129,7 @@ static int proc_disconnect_claim(struct dev_state *ps, void __user *arg)  static long usbdev_do_ioctl(struct file *file, unsigned int cmd,  				void __user *p)  { -	struct dev_state *ps = file->private_data; +	struct usb_dev_state *ps = file->private_data;  	struct inode *inode = file_inode(file);  	struct usb_device *dev = ps->dev;  	int ret = -ENOTTY; @@ -2145,6 +2297,12 @@ static long usbdev_do_ioctl(struct file *file, unsigned int cmd,  	case USBDEVFS_DISCONNECT_CLAIM:  		ret = proc_disconnect_claim(ps, p);  		break; +	case USBDEVFS_ALLOC_STREAMS: +		ret = proc_alloc_streams(ps, p); +		break; +	case USBDEVFS_FREE_STREAMS: +		ret = proc_free_streams(ps, p); +		break;  	}  	usb_unlock_device(dev);  	if (ret >= 0) @@ -2178,7 +2336,7 @@ static long usbdev_compat_ioctl(struct file *file, unsigned int cmd,  static unsigned int usbdev_poll(struct file *file,  				struct poll_table_struct *wait)  { -	struct dev_state *ps = file->private_data; +	struct usb_dev_state *ps = file->private_data;  	unsigned int mask = 0;  	poll_wait(file, &ps->wait, wait); @@ -2204,11 +2362,11 @@ const struct file_operations usbdev_file_operations = {  static void usbdev_remove(struct usb_device *udev)  { -	struct dev_state *ps; +	struct usb_dev_state *ps;  	struct siginfo sinfo;  	while (!list_empty(&udev->filelist)) { -		ps = list_entry(udev->filelist.next, struct dev_state, list); +		ps = list_entry(udev->filelist.next, struct usb_dev_state, list);  		destroy_all_async(ps);  		wake_up_all(&ps->wait);  		list_del_init(&ps->list); diff --git a/drivers/usb/core/driver.c b/drivers/usb/core/driver.c index f7841d44fed..4aeb10034de 100644 --- a/drivers/usb/core/driver.c +++ b/drivers/usb/core/driver.c @@ -37,6 +37,7 @@   * and cause the driver to probe for all devices again.   */  ssize_t usb_store_new_id(struct usb_dynids *dynids, +			 const struct usb_device_id *id_table,  			 struct device_driver *driver,  			 const char *buf, size_t count)  { @@ -44,11 +45,12 @@ ssize_t usb_store_new_id(struct usb_dynids *dynids,  	u32 idVendor = 0;  	u32 idProduct = 0;  	unsigned int bInterfaceClass = 0; +	u32 refVendor, refProduct;  	int fields = 0;  	int retval = 0; -	fields = sscanf(buf, "%x %x %x", &idVendor, &idProduct, -					&bInterfaceClass); +	fields = sscanf(buf, "%x %x %x %x %x", &idVendor, &idProduct, +			&bInterfaceClass, &refVendor, &refProduct);  	if (fields < 2)  		return -EINVAL; @@ -60,11 +62,36 @@ ssize_t usb_store_new_id(struct usb_dynids *dynids,  	dynid->id.idVendor = idVendor;  	dynid->id.idProduct = idProduct;  	dynid->id.match_flags = USB_DEVICE_ID_MATCH_DEVICE; -	if (fields == 3) { +	if (fields > 2 && bInterfaceClass) { +		if (bInterfaceClass > 255) { +			retval = -EINVAL; +			goto fail; +		} +  		dynid->id.bInterfaceClass = (u8)bInterfaceClass;  		dynid->id.match_flags |= USB_DEVICE_ID_MATCH_INT_CLASS;  	} +	if (fields > 4) { +		const struct usb_device_id *id = id_table; + +		if (!id) { +			retval = -ENODEV; +			goto fail; +		} + +		for (; id->match_flags; id++) +			if (id->idVendor == refVendor && id->idProduct == refProduct) +				break; + +		if (id->match_flags) { +			dynid->id.driver_info = id->driver_info; +		} else { +			retval = -ENODEV; +			goto fail; +		} +	} +  	spin_lock(&dynids->lock);  	list_add_tail(&dynid->node, &dynids->list);  	spin_unlock(&dynids->lock); @@ -74,6 +101,10 @@ ssize_t usb_store_new_id(struct usb_dynids *dynids,  	if (retval)  		return retval;  	return count; + +fail: +	kfree(dynid); +	return retval;  }  EXPORT_SYMBOL_GPL(usb_store_new_id); @@ -106,7 +137,7 @@ static ssize_t new_id_store(struct device_driver *driver,  {  	struct usb_driver *usb_drv = to_usb_driver(driver); -	return usb_store_new_id(&usb_drv->dynids, driver, buf, count); +	return usb_store_new_id(&usb_drv->dynids, usb_drv->id_table, driver, buf, count);  }  static DRIVER_ATTR_RW(new_id); @@ -281,9 +312,9 @@ static int usb_probe_interface(struct device *dev)  		return error;  	} -	id = usb_match_id(intf, driver->id_table); +	id = usb_match_dynamic_id(intf, driver);  	if (!id) -		id = usb_match_dynamic_id(intf, driver); +		id = usb_match_id(intf, driver->id_table);  	if (!id)  		return error; @@ -369,8 +400,9 @@ static int usb_unbind_interface(struct device *dev)  {  	struct usb_driver *driver = to_usb_driver(dev->driver);  	struct usb_interface *intf = to_usb_interface(dev); +	struct usb_host_endpoint *ep, **eps = NULL;  	struct usb_device *udev; -	int error, r, lpm_disable_error; +	int i, j, error, r, lpm_disable_error;  	intf->condition = USB_INTERFACE_UNBINDING; @@ -394,6 +426,26 @@ static int usb_unbind_interface(struct device *dev)  	driver->disconnect(intf);  	usb_cancel_queued_reset(intf); +	/* Free streams */ +	for (i = 0, j = 0; i < intf->cur_altsetting->desc.bNumEndpoints; i++) { +		ep = &intf->cur_altsetting->endpoint[i]; +		if (ep->streams == 0) +			continue; +		if (j == 0) { +			eps = kmalloc(USB_MAXENDPOINTS * sizeof(void *), +				      GFP_KERNEL); +			if (!eps) { +				dev_warn(dev, "oom, leaking streams\n"); +				break; +			} +		} +		eps[j++] = ep; +	} +	if (j) { +		usb_free_streams(intf, eps, j, GFP_KERNEL); +		kfree(eps); +	} +  	/* Reset other interface state.  	 * We cannot do a Set-Interface if the device is suspended or  	 * if it is prepared for a system sleep (since installing a new @@ -839,7 +891,7 @@ int usb_register_device_driver(struct usb_device_driver *new_udriver,  		return -ENODEV;  	new_udriver->drvwrap.for_devices = 1; -	new_udriver->drvwrap.driver.name = (char *) new_udriver->name; +	new_udriver->drvwrap.driver.name = new_udriver->name;  	new_udriver->drvwrap.driver.bus = &usb_bus_type;  	new_udriver->drvwrap.driver.probe = usb_probe_device;  	new_udriver->drvwrap.driver.remove = usb_unbind_device; @@ -900,7 +952,7 @@ int usb_register_driver(struct usb_driver *new_driver, struct module *owner,  		return -ENODEV;  	new_driver->drvwrap.for_devices = 0; -	new_driver->drvwrap.driver.name = (char *) new_driver->name; +	new_driver->drvwrap.driver.name = new_driver->name;  	new_driver->drvwrap.driver.bus = &usb_bus_type;  	new_driver->drvwrap.driver.probe = usb_probe_interface;  	new_driver->drvwrap.driver.remove = usb_unbind_interface; @@ -959,8 +1011,7 @@ EXPORT_SYMBOL_GPL(usb_deregister);   * it doesn't support pre_reset/post_reset/reset_resume or   * because it doesn't support suspend/resume.   * - * The caller must hold @intf's device's lock, but not its pm_mutex - * and not @intf->dev.sem. + * The caller must hold @intf's device's lock, but not @intf's lock.   */  void usb_forced_unbind_intf(struct usb_interface *intf)  { @@ -973,16 +1024,37 @@ void usb_forced_unbind_intf(struct usb_interface *intf)  	intf->needs_binding = 1;  } +/* + * Unbind drivers for @udev's marked interfaces.  These interfaces have + * the needs_binding flag set, for example by usb_resume_interface(). + * + * The caller must hold @udev's device lock. + */ +static void unbind_marked_interfaces(struct usb_device *udev) +{ +	struct usb_host_config	*config; +	int			i; +	struct usb_interface	*intf; + +	config = udev->actconfig; +	if (config) { +		for (i = 0; i < config->desc.bNumInterfaces; ++i) { +			intf = config->interface[i]; +			if (intf->dev.driver && intf->needs_binding) +				usb_forced_unbind_intf(intf); +		} +	} +} +  /* Delayed forced unbinding of a USB interface driver and scan   * for rebinding.   * - * The caller must hold @intf's device's lock, but not its pm_mutex - * and not @intf->dev.sem. + * The caller must hold @intf's device's lock, but not @intf's lock.   *   * Note: Rebinds will be skipped if a system sleep transition is in   * progress and the PM "complete" callback hasn't occurred yet.   */ -void usb_rebind_intf(struct usb_interface *intf) +static void usb_rebind_intf(struct usb_interface *intf)  {  	int rc; @@ -999,68 +1071,66 @@ void usb_rebind_intf(struct usb_interface *intf)  	}  } -#ifdef CONFIG_PM - -/* Unbind drivers for @udev's interfaces that don't support suspend/resume - * There is no check for reset_resume here because it can be determined - * only during resume whether reset_resume is needed. +/* + * Rebind drivers to @udev's marked interfaces.  These interfaces have + * the needs_binding flag set.   *   * The caller must hold @udev's device lock.   */ -static void unbind_no_pm_drivers_interfaces(struct usb_device *udev) +static void rebind_marked_interfaces(struct usb_device *udev)  {  	struct usb_host_config	*config;  	int			i;  	struct usb_interface	*intf; -	struct usb_driver	*drv;  	config = udev->actconfig;  	if (config) {  		for (i = 0; i < config->desc.bNumInterfaces; ++i) {  			intf = config->interface[i]; - -			if (intf->dev.driver) { -				drv = to_usb_driver(intf->dev.driver); -				if (!drv->suspend || !drv->resume) -					usb_forced_unbind_intf(intf); -			} +			if (intf->needs_binding) +				usb_rebind_intf(intf);  		}  	}  } -/* Unbind drivers for @udev's interfaces that failed to support reset-resume. - * These interfaces have the needs_binding flag set by usb_resume_interface(). +/* + * Unbind all of @udev's marked interfaces and then rebind all of them. + * This ordering is necessary because some drivers claim several interfaces + * when they are first probed.   *   * The caller must hold @udev's device lock.   */ -static void unbind_no_reset_resume_drivers_interfaces(struct usb_device *udev) +void usb_unbind_and_rebind_marked_interfaces(struct usb_device *udev)  { -	struct usb_host_config	*config; -	int			i; -	struct usb_interface	*intf; - -	config = udev->actconfig; -	if (config) { -		for (i = 0; i < config->desc.bNumInterfaces; ++i) { -			intf = config->interface[i]; -			if (intf->dev.driver && intf->needs_binding) -				usb_forced_unbind_intf(intf); -		} -	} +	unbind_marked_interfaces(udev); +	rebind_marked_interfaces(udev);  } -static void do_rebind_interfaces(struct usb_device *udev) +#ifdef CONFIG_PM + +/* Unbind drivers for @udev's interfaces that don't support suspend/resume + * There is no check for reset_resume here because it can be determined + * only during resume whether reset_resume is needed. + * + * The caller must hold @udev's device lock. + */ +static void unbind_no_pm_drivers_interfaces(struct usb_device *udev)  {  	struct usb_host_config	*config;  	int			i;  	struct usb_interface	*intf; +	struct usb_driver	*drv;  	config = udev->actconfig;  	if (config) {  		for (i = 0; i < config->desc.bNumInterfaces; ++i) {  			intf = config->interface[i]; -			if (intf->needs_binding) -				usb_rebind_intf(intf); + +			if (intf->dev.driver) { +				drv = to_usb_driver(intf->dev.driver); +				if (!drv->suspend || !drv->resume) +					usb_forced_unbind_intf(intf); +			}  		}  	}  } @@ -1179,8 +1249,8 @@ static int usb_resume_interface(struct usb_device *udev,  						"reset_resume", status);  		} else {  			intf->needs_binding = 1; -			dev_warn(&intf->dev, "no %s for driver %s?\n", -					"reset_resume", driver->name); +			dev_dbg(&intf->dev, "no reset_resume for driver %s?\n", +					driver->name);  		}  	} else {  		status = driver->resume(intf); @@ -1389,7 +1459,7 @@ int usb_resume_complete(struct device *dev)  	 * whose needs_binding flag is set  	 */  	if (udev->state != USB_STATE_NOTATTACHED) -		do_rebind_interfaces(udev); +		rebind_marked_interfaces(udev);  	return 0;  } @@ -1411,7 +1481,7 @@ int usb_resume(struct device *dev, pm_message_t msg)  		pm_runtime_disable(dev);  		pm_runtime_set_active(dev);  		pm_runtime_enable(dev); -		unbind_no_reset_resume_drivers_interfaces(udev); +		unbind_marked_interfaces(udev);  	}  	/* Avoid PM error messages for devices disconnected while suspended @@ -1752,10 +1822,13 @@ int usb_runtime_suspend(struct device *dev)  	if (status == -EAGAIN || status == -EBUSY)  		usb_mark_last_busy(udev); -	/* The PM core reacts badly unless the return code is 0, -	 * -EAGAIN, or -EBUSY, so always return -EBUSY on an error. +	/* +	 * The PM core reacts badly unless the return code is 0, +	 * -EAGAIN, or -EBUSY, so always return -EBUSY on an error +	 * (except for root hubs, because they don't suspend through +	 * an upstream port like other USB devices).  	 */ -	if (status != 0) +	if (status != 0 && udev->parent)  		return -EBUSY;  	return status;  } @@ -1790,6 +1863,9 @@ int usb_set_usb2_hardware_lpm(struct usb_device *udev, int enable)  	struct usb_hcd *hcd = bus_to_hcd(udev->bus);  	int ret = -EPERM; +	if (enable && !udev->usb2_hw_lpm_allowed) +		return 0; +  	if (hcd->driver->set_usb2_hw_lpm) {  		ret = hcd->driver->set_usb2_hw_lpm(hcd, udev, enable);  		if (!ret) diff --git a/drivers/usb/core/file.c b/drivers/usb/core/file.c index 7421888087a..ea337a718cc 100644 --- a/drivers/usb/core/file.c +++ b/drivers/usb/core/file.c @@ -8,7 +8,7 @@   * (C) Copyright Deti Fliegl 1999 (new USB architecture)   * (C) Copyright Randy Dunlap 2000   * (C) Copyright David Brownell 2000-2001 (kernel hotplug, usb_device_id, - 	more docs, etc) + *	more docs, etc)   * (C) Copyright Yggdrasil Computing, Inc. 2000   *     (usb_device_id matching changes by Adam J. Richter)   * (C) Copyright Greg Kroah-Hartman 2002-2003 @@ -27,29 +27,21 @@  static const struct file_operations *usb_minors[MAX_USB_MINORS];  static DECLARE_RWSEM(minor_rwsem); -static int usb_open(struct inode * inode, struct file * file) +static int usb_open(struct inode *inode, struct file *file)  { -	int minor = iminor(inode); -	const struct file_operations *c;  	int err = -ENODEV; -	const struct file_operations *old_fops, *new_fops = NULL; +	const struct file_operations *new_fops;  	down_read(&minor_rwsem); -	c = usb_minors[minor]; +	new_fops = fops_get(usb_minors[iminor(inode)]); -	if (!c || !(new_fops = fops_get(c))) +	if (!new_fops)  		goto done; -	old_fops = file->f_op; -	file->f_op = new_fops; +	replace_fops(file, new_fops);  	/* Curiouser and curiouser... NULL ->open() as "no device" ? */  	if (file->f_op->open) -		err = file->f_op->open(inode,file); -	if (err) { -		fops_put(file->f_op); -		file->f_op = fops_get(old_fops); -	} -	fops_put(old_fops); +		err = file->f_op->open(inode, file);   done:  	up_read(&minor_rwsem);  	return err; @@ -166,7 +158,7 @@ int usb_register_dev(struct usb_interface *intf,  	char *temp;  #ifdef CONFIG_USB_DYNAMIC_MINORS -	/*  +	/*  	 * We don't care what the device tries to start at, we want to start  	 * at zero to pack the devices into the smallest available space with  	 * no holes in the minor range. diff --git a/drivers/usb/core/generic.c b/drivers/usb/core/generic.c index acbfeb0a011..358ca8dd784 100644 --- a/drivers/usb/core/generic.c +++ b/drivers/usb/core/generic.c @@ -155,6 +155,7 @@ int usb_choose_configuration(struct usb_device *udev)  	}  	return i;  } +EXPORT_SYMBOL_GPL(usb_choose_configuration);  static int generic_probe(struct usb_device *udev)  { diff --git a/drivers/usb/core/hcd-pci.c b/drivers/usb/core/hcd-pci.c index b9d3c43e385..82044b5d611 100644 --- a/drivers/usb/core/hcd-pci.c +++ b/drivers/usb/core/hcd-pci.c @@ -75,7 +75,7 @@ static void for_each_companion(struct pci_dev *pdev, struct usb_hcd *hcd,  				PCI_SLOT(companion->devfn) != slot)  			continue;  		companion_hcd = pci_get_drvdata(companion); -		if (!companion_hcd) +		if (!companion_hcd || !companion_hcd->self.root_hub)  			continue;  		fn(pdev, hcd, companion, companion_hcd);  	} @@ -192,7 +192,6 @@ int usb_hcd_pci_probe(struct pci_dev *dev, const struct pci_device_id *id)  	if (pci_enable_device(dev) < 0)  		return -ENODEV; -	dev->current_state = PCI_D0;  	/*  	 * The xHCI driver has its own irq management @@ -215,6 +214,9 @@ int usb_hcd_pci_probe(struct pci_dev *dev, const struct pci_device_id *id)  		goto disable_pci;  	} +	hcd->amd_resume_bug = (usb_hcd_amd_remote_wakeup_quirk(dev) && +			driver->flags & (HCD_USB11 | HCD_USB3)) ? 1 : 0; +  	if (driver->flags & HCD_MEMORY) {  		/* EHCI, OHCI */  		hcd->rsrc_start = pci_resource_start(dev, 0); @@ -279,6 +281,7 @@ int usb_hcd_pci_probe(struct pci_dev *dev, const struct pci_device_id *id)  	if (retval != 0)  		goto unmap_registers; +	device_wakeup_enable(hcd->self.controller);  	if (pci_dev_run_wake(dev))  		pm_runtime_put_noidle(&dev->dev); diff --git a/drivers/usb/core/hcd.c b/drivers/usb/core/hcd.c index d6a8d23f047..bec31e2efb8 100644 --- a/drivers/usb/core/hcd.c +++ b/drivers/usb/core/hcd.c @@ -6,7 +6,7 @@   * (C) Copyright Deti Fliegl 1999   * (C) Copyright Randy Dunlap 2000   * (C) Copyright David Brownell 2000-2002 - *  + *   * This program is free software; you can redistribute it and/or modify it   * under the terms of the GNU General Public License as published by the   * Free Software Foundation; either version 2 of the License, or (at your @@ -40,9 +40,11 @@  #include <linux/platform_device.h>  #include <linux/workqueue.h>  #include <linux/pm_runtime.h> +#include <linux/types.h>  #include <linux/usb.h>  #include <linux/usb/hcd.h> +#include <linux/usb/phy.h>  #include "usb.h" @@ -92,10 +94,7 @@ EXPORT_SYMBOL_GPL (usb_bus_list);  /* used when allocating bus numbers */  #define USB_MAXBUS		64 -struct usb_busmap { -	unsigned long busmap [USB_MAXBUS / (8*sizeof (unsigned long))]; -}; -static struct usb_busmap busmap; +static DECLARE_BITMAP(busmap, USB_MAXBUS);  /* used when updating list of hcds */  DEFINE_MUTEX(usb_bus_list_lock);	/* exported only for usbfs */ @@ -171,7 +170,7 @@ static const u8 usb25_rh_dev_descriptor[18] = {  };  /* usb 2.0 root hub device descriptor */ -static const u8 usb2_rh_dev_descriptor [18] = { +static const u8 usb2_rh_dev_descriptor[18] = {  	0x12,       /*  __u8  bLength; */  	0x01,       /*  __u8  bDescriptorType; Device */  	0x00, 0x02, /*  __le16 bcdUSB; v2.0 */ @@ -194,7 +193,7 @@ static const u8 usb2_rh_dev_descriptor [18] = {  /* no usb 2.0 root hub "device qualifier" descriptor: one speed only */  /* usb 1.1 root hub device descriptor */ -static const u8 usb11_rh_dev_descriptor [18] = { +static const u8 usb11_rh_dev_descriptor[18] = {  	0x12,       /*  __u8  bLength; */  	0x01,       /*  __u8  bDescriptorType; Device */  	0x10, 0x01, /*  __le16 bcdUSB; v1.1 */ @@ -219,7 +218,7 @@ static const u8 usb11_rh_dev_descriptor [18] = {  /* Configuration descriptors for our root hubs */ -static const u8 fs_rh_config_descriptor [] = { +static const u8 fs_rh_config_descriptor[] = {  	/* one configuration */  	0x09,       /*  __u8  bLength; */ @@ -228,13 +227,13 @@ static const u8 fs_rh_config_descriptor [] = {  	0x01,       /*  __u8  bNumInterfaces; (1) */  	0x01,       /*  __u8  bConfigurationValue; */  	0x00,       /*  __u8  iConfiguration; */ -	0xc0,       /*  __u8  bmAttributes;  +	0xc0,       /*  __u8  bmAttributes;  				 Bit 7: must be set,  				     6: Self-powered,  				     5: Remote wakeup,  				     4..0: resvd */  	0x00,       /*  __u8  MaxPower; */ -       +  	/* USB 1.1:  	 * USB 2.0, single TT organization (mandatory):  	 *	one interface, protocol 0 @@ -256,17 +255,17 @@ static const u8 fs_rh_config_descriptor [] = {  	0x00,       /*  __u8  if_bInterfaceSubClass; */  	0x00,       /*  __u8  if_bInterfaceProtocol; [usb1.1 or single tt] */  	0x00,       /*  __u8  if_iInterface; */ -      +  	/* one endpoint (status change endpoint) */  	0x07,       /*  __u8  ep_bLength; */  	0x05,       /*  __u8  ep_bDescriptorType; Endpoint */  	0x81,       /*  __u8  ep_bEndpointAddress; IN Endpoint 1 */ - 	0x03,       /*  __u8  ep_bmAttributes; Interrupt */ - 	0x02, 0x00, /*  __le16 ep_wMaxPacketSize; 1 + (MAX_ROOT_PORTS / 8) */ +	0x03,       /*  __u8  ep_bmAttributes; Interrupt */ +	0x02, 0x00, /*  __le16 ep_wMaxPacketSize; 1 + (MAX_ROOT_PORTS / 8) */  	0xff        /*  __u8  ep_bInterval; (255ms -- usb 2.0 spec) */  }; -static const u8 hs_rh_config_descriptor [] = { +static const u8 hs_rh_config_descriptor[] = {  	/* one configuration */  	0x09,       /*  __u8  bLength; */ @@ -275,13 +274,13 @@ static const u8 hs_rh_config_descriptor [] = {  	0x01,       /*  __u8  bNumInterfaces; (1) */  	0x01,       /*  __u8  bConfigurationValue; */  	0x00,       /*  __u8  iConfiguration; */ -	0xc0,       /*  __u8  bmAttributes;  +	0xc0,       /*  __u8  bmAttributes;  				 Bit 7: must be set,  				     6: Self-powered,  				     5: Remote wakeup,  				     4..0: resvd */  	0x00,       /*  __u8  MaxPower; */ -       +  	/* USB 1.1:  	 * USB 2.0, single TT organization (mandatory):  	 *	one interface, protocol 0 @@ -303,12 +302,12 @@ static const u8 hs_rh_config_descriptor [] = {  	0x00,       /*  __u8  if_bInterfaceSubClass; */  	0x00,       /*  __u8  if_bInterfaceProtocol; [usb1.1 or single tt] */  	0x00,       /*  __u8  if_iInterface; */ -      +  	/* one endpoint (status change endpoint) */  	0x07,       /*  __u8  ep_bLength; */  	0x05,       /*  __u8  ep_bDescriptorType; Endpoint */  	0x81,       /*  __u8  ep_bEndpointAddress; IN Endpoint 1 */ - 	0x03,       /*  __u8  ep_bmAttributes; Interrupt */ +	0x03,       /*  __u8  ep_bmAttributes; Interrupt */  		    /* __le16 ep_wMaxPacketSize; 1 + (MAX_ROOT_PORTS / 8)  		     * see hub.c:hub_configure() for details. */  	(USB_MAXCHILDREN + 1 + 7) / 8, 0x00, @@ -428,7 +427,7 @@ rh_string(int id, struct usb_hcd const *hcd, u8 *data, unsigned len)  	char const *s;  	static char const langids[4] = {4, USB_DT_STRING, 0x09, 0x04}; -	// language ids +	/* language ids */  	switch (id) {  	case 0:  		/* Array of LANGID codes (0x0409 is MSFT-speak for "en-us") */ @@ -464,7 +463,7 @@ rh_string(int id, struct usb_hcd const *hcd, u8 *data, unsigned len)  static int rh_call_control (struct usb_hcd *hcd, struct urb *urb)  {  	struct usb_ctrlrequest *cmd; - 	u16		typeReq, wValue, wIndex, wLength; +	u16		typeReq, wValue, wIndex, wLength;  	u8		*ubuf = urb->transfer_buffer;  	unsigned	len = 0;  	int		status; @@ -526,10 +525,10 @@ static int rh_call_control (struct usb_hcd *hcd, struct urb *urb)  	 */  	case DeviceRequest | USB_REQ_GET_STATUS: -		tbuf [0] = (device_may_wakeup(&hcd->self.root_hub->dev) +		tbuf[0] = (device_may_wakeup(&hcd->self.root_hub->dev)  					<< USB_DEVICE_REMOTE_WAKEUP)  				| (1 << USB_DEVICE_SELF_POWERED); -		tbuf [1] = 0; +		tbuf[1] = 0;  		len = 2;  		break;  	case DeviceOutRequest | USB_REQ_CLEAR_FEATURE: @@ -546,7 +545,7 @@ static int rh_call_control (struct usb_hcd *hcd, struct urb *urb)  			goto error;  		break;  	case DeviceRequest | USB_REQ_GET_CONFIGURATION: -		tbuf [0] = 1; +		tbuf[0] = 1;  		len = 1;  			/* FALLTHROUGH */  	case DeviceOutRequest | USB_REQ_SET_CONFIGURATION: @@ -609,13 +608,13 @@ static int rh_call_control (struct usb_hcd *hcd, struct urb *urb)  		}  		break;  	case DeviceRequest | USB_REQ_GET_INTERFACE: -		tbuf [0] = 0; +		tbuf[0] = 0;  		len = 1;  			/* FALLTHROUGH */  	case DeviceOutRequest | USB_REQ_SET_INTERFACE:  		break;  	case DeviceOutRequest | USB_REQ_SET_ADDRESS: -		// wValue == urb->dev->devaddr +		/* wValue == urb->dev->devaddr */  		dev_dbg (hcd->self.controller, "root hub device address %d\n",  			wValue);  		break; @@ -625,9 +624,9 @@ static int rh_call_control (struct usb_hcd *hcd, struct urb *urb)  	/* ENDPOINT REQUESTS */  	case EndpointRequest | USB_REQ_GET_STATUS: -		// ENDPOINT_HALT flag -		tbuf [0] = 0; -		tbuf [1] = 0; +		/* ENDPOINT_HALT flag */ +		tbuf[0] = 0; +		tbuf[1] = 0;  		len = 2;  			/* FALLTHROUGH */  	case EndpointOutRequest | USB_REQ_CLEAR_FEATURE: @@ -683,7 +682,7 @@ error:  		if (urb->transfer_buffer_length < len)  			len = urb->transfer_buffer_length;  		urb->actual_length = len; -		// always USB_DIR_IN, toward host +		/* always USB_DIR_IN, toward host */  		memcpy (ubuf, bufp, len);  		/* report whether RH hardware supports remote wakeup */ @@ -877,11 +876,11 @@ static ssize_t authorized_default_store(struct device *dev,  	usb_hcd = bus_to_hcd(usb_bus);  	result = sscanf(buf, "%u\n", &val);  	if (result == 1) { -		usb_hcd->authorized_default = val? 1 : 0; +		usb_hcd->authorized_default = val ? 1 : 0;  		result = size; -	} -	else +	} else {  		result = -EINVAL; +	}  	return result;  }  static DEVICE_ATTR_RW(authorized_default); @@ -919,6 +918,7 @@ static void usb_bus_init (struct usb_bus *bus)  	bus->bandwidth_allocated = 0;  	bus->bandwidth_int_reqs  = 0;  	bus->bandwidth_isoc_reqs = 0; +	mutex_init(&bus->usb_address0_mutex);  	INIT_LIST_HEAD (&bus->bus_list);  } @@ -941,12 +941,12 @@ static int usb_register_bus(struct usb_bus *bus)  	int busnum;  	mutex_lock(&usb_bus_list_lock); -	busnum = find_next_zero_bit (busmap.busmap, USB_MAXBUS, 1); +	busnum = find_next_zero_bit(busmap, USB_MAXBUS, 1);  	if (busnum >= USB_MAXBUS) {  		printk (KERN_ERR "%s: too many buses\n", usbcore_name);  		goto error_find_busnum;  	} -	set_bit (busnum, busmap.busmap); +	set_bit(busnum, busmap);  	bus->busnum = busnum;  	/* Add it to the local list of buses */ @@ -987,7 +987,7 @@ static void usb_deregister_bus (struct usb_bus *bus)  	usb_notify_remove_bus(bus); -	clear_bit (bus->busnum, busmap.busmap); +	clear_bit(bus->busnum, busmap);  }  /** @@ -1120,21 +1120,21 @@ long usb_calc_bus_time (int speed, int is_input, int isoc, int bytecount)  	case USB_SPEED_LOW: 	/* INTR only */  		if (is_input) {  			tmp = (67667L * (31L + 10L * BitTime (bytecount))) / 1000L; -			return (64060L + (2 * BW_HUB_LS_SETUP) + BW_HOST_DELAY + tmp); +			return 64060L + (2 * BW_HUB_LS_SETUP) + BW_HOST_DELAY + tmp;  		} else {  			tmp = (66700L * (31L + 10L * BitTime (bytecount))) / 1000L; -			return (64107L + (2 * BW_HUB_LS_SETUP) + BW_HOST_DELAY + tmp); +			return 64107L + (2 * BW_HUB_LS_SETUP) + BW_HOST_DELAY + tmp;  		}  	case USB_SPEED_FULL:	/* ISOC or INTR */  		if (isoc) {  			tmp = (8354L * (31L + 10L * BitTime (bytecount))) / 1000L; -			return (((is_input) ? 7268L : 6265L) + BW_HOST_DELAY + tmp); +			return ((is_input) ? 7268L : 6265L) + BW_HOST_DELAY + tmp;  		} else {  			tmp = (8354L * (31L + 10L * BitTime (bytecount))) / 1000L; -			return (9107L + BW_HOST_DELAY + tmp); +			return 9107L + BW_HOST_DELAY + tmp;  		}  	case USB_SPEED_HIGH:	/* ISOC or INTR */ -		// FIXME adjust for input vs output +		/* FIXME adjust for input vs output */  		if (isoc)  			tmp = HS_NSECS_ISO (bytecount);  		else @@ -1298,7 +1298,7 @@ EXPORT_SYMBOL_GPL(usb_hcd_unlink_urb_from_ep);   *   DMA framework is dma_declare_coherent_memory()   *   * - So we use that, even though the primary requirement - *   is that the memory be "local" (hence addressible + *   is that the memory be "local" (hence addressable   *   by that device), not "coherent".   *   */ @@ -1503,6 +1503,9 @@ int usb_hcd_map_urb_for_dma(struct usb_hcd *hcd, struct urb *urb,  					ret = -EAGAIN;  				else  					urb->transfer_flags |= URB_DMA_MAP_PAGE; +			} else if (is_vmalloc_addr(urb->transfer_buffer)) { +				WARN_ONCE(1, "transfer buffer not dma capable\n"); +				ret = -EAGAIN;  			} else {  				urb->transfer_dma = dma_map_single(  						hcd->self.controller, @@ -1651,6 +1654,7 @@ int usb_hcd_unlink_urb (struct urb *urb, int status)  static void __usb_hcd_giveback_urb(struct urb *urb)  {  	struct usb_hcd *hcd = bus_to_hcd(urb->dev->bus); +	struct usb_anchor *anchor = urb->anchor;  	int status = urb->unlinked;  	unsigned long flags; @@ -1662,6 +1666,7 @@ static void __usb_hcd_giveback_urb(struct urb *urb)  	unmap_urb_for_dma(hcd, urb);  	usbmon_urb_complete(&hcd->self, urb, status); +	usb_anchor_suspend_wakeups(anchor);  	usb_unanchor_urb(urb);  	/* pass ownership to the completion handler */ @@ -1681,6 +1686,7 @@ static void __usb_hcd_giveback_urb(struct urb *urb)  	urb->complete(urb);  	local_irq_restore(flags); +	usb_anchor_resume_wakeups(anchor);  	atomic_dec(&urb->use_count);  	if (unlikely(atomic_read(&urb->reject)))  		wake_up(&usb_kill_urb_queue); @@ -1703,7 +1709,9 @@ static void usb_giveback_urb_bh(unsigned long param)  		urb = list_entry(local_list.next, struct urb, urb_list);  		list_del_init(&urb->urb_list); +		bh->completing_ep = urb->ep;  		__usb_hcd_giveback_urb(urb); +		bh->completing_ep = NULL;  	}  	/* check if there are new URBs to giveback */ @@ -1812,7 +1820,7 @@ rescan:  				 case USB_ENDPOINT_XFER_INT:  					s = "-intr"; break;  				 default: -			 		s = "-iso"; break; +					s = "-iso"; break;  				};  				s;  			})); @@ -2045,7 +2053,7 @@ int usb_alloc_streams(struct usb_interface *interface,  {  	struct usb_hcd *hcd;  	struct usb_device *dev; -	int i; +	int i, ret;  	dev = interface_to_usbdev(interface);  	hcd = bus_to_hcd(dev->bus); @@ -2054,13 +2062,24 @@ int usb_alloc_streams(struct usb_interface *interface,  	if (dev->speed != USB_SPEED_SUPER)  		return -EINVAL; -	/* Streams only apply to bulk endpoints. */ -	for (i = 0; i < num_eps; i++) +	for (i = 0; i < num_eps; i++) { +		/* Streams only apply to bulk endpoints. */  		if (!usb_endpoint_xfer_bulk(&eps[i]->desc))  			return -EINVAL; +		/* Re-alloc is not allowed */ +		if (eps[i]->streams) +			return -EINVAL; +	} -	return hcd->driver->alloc_streams(hcd, dev, eps, num_eps, +	ret = hcd->driver->alloc_streams(hcd, dev, eps, num_eps,  			num_streams, mem_flags); +	if (ret < 0) +		return ret; + +	for (i = 0; i < num_eps; i++) +		eps[i]->streams = ret; + +	return ret;  }  EXPORT_SYMBOL_GPL(usb_alloc_streams); @@ -2073,26 +2092,35 @@ EXPORT_SYMBOL_GPL(usb_alloc_streams);   *   * Reverts a group of bulk endpoints back to not using stream IDs.   * Can fail if we are given bad arguments, or HCD is broken. + * + * Return: 0 on success. On failure, a negative error code.   */ -void usb_free_streams(struct usb_interface *interface, +int usb_free_streams(struct usb_interface *interface,  		struct usb_host_endpoint **eps, unsigned int num_eps,  		gfp_t mem_flags)  {  	struct usb_hcd *hcd;  	struct usb_device *dev; -	int i; +	int i, ret;  	dev = interface_to_usbdev(interface);  	hcd = bus_to_hcd(dev->bus);  	if (dev->speed != USB_SPEED_SUPER) -		return; +		return -EINVAL; -	/* Streams only apply to bulk endpoints. */ +	/* Double-free is not allowed */  	for (i = 0; i < num_eps; i++) -		if (!eps[i] || !usb_endpoint_xfer_bulk(&eps[i]->desc)) -			return; +		if (!eps[i] || !eps[i]->streams) +			return -EINVAL; + +	ret = hcd->driver->free_streams(hcd, dev, eps, num_eps, mem_flags); +	if (ret < 0) +		return ret; -	hcd->driver->free_streams(hcd, dev, eps, num_eps, mem_flags); +	for (i = 0; i < num_eps; i++) +		eps[i]->streams = 0; + +	return ret;  }  EXPORT_SYMBOL_GPL(usb_free_streams); @@ -2239,13 +2267,11 @@ static void hcd_resume_work(struct work_struct *work)  	struct usb_hcd *hcd = container_of(work, struct usb_hcd, wakeup_work);  	struct usb_device *udev = hcd->self.root_hub; -	usb_lock_device(udev);  	usb_remote_wakeup(udev); -	usb_unlock_device(udev);  }  /** - * usb_hcd_resume_root_hub - called by HCD to resume its root hub  + * usb_hcd_resume_root_hub - called by HCD to resume its root hub   * @hcd: host controller for this root hub   *   * The USB host controller calls this function when its root hub is @@ -2324,15 +2350,8 @@ EXPORT_SYMBOL_GPL(usb_bus_start_enum);  irqreturn_t usb_hcd_irq (int irq, void *__hcd)  {  	struct usb_hcd		*hcd = __hcd; -	unsigned long		flags;  	irqreturn_t		rc; -	/* IRQF_DISABLED doesn't work correctly with shared IRQs -	 * when the first handler doesn't use it.  So let's just -	 * assume it's never used. -	 */ -	local_irq_save(flags); -  	if (unlikely(HCD_DEAD(hcd) || !HCD_HW_ACCESSIBLE(hcd)))  		rc = IRQ_NONE;  	else if (hcd->driver->irq(hcd) == IRQ_NONE) @@ -2340,7 +2359,6 @@ irqreturn_t usb_hcd_irq (int irq, void *__hcd)  	else  		rc = IRQ_HANDLED; -	local_irq_restore(flags);  	return rc;  }  EXPORT_SYMBOL_GPL(usb_hcd_irq); @@ -2438,11 +2456,13 @@ struct usb_hcd *usb_create_shared_hcd(const struct hc_driver *driver,  		mutex_init(hcd->bandwidth_mutex);  		dev_set_drvdata(dev, hcd);  	} else { +		mutex_lock(&usb_port_peer_mutex);  		hcd->bandwidth_mutex = primary_hcd->bandwidth_mutex;  		hcd->primary_hcd = primary_hcd;  		primary_hcd->primary_hcd = primary_hcd;  		hcd->shared_hcd = primary_hcd;  		primary_hcd->shared_hcd = hcd; +		mutex_unlock(&usb_port_peer_mutex);  	}  	kref_init(&hcd->kref); @@ -2494,18 +2514,25 @@ EXPORT_SYMBOL_GPL(usb_create_hcd);   * deallocated.   *   * Make sure to only deallocate the bandwidth_mutex when the primary HCD is - * freed.  When hcd_release() is called for the non-primary HCD, set the - * primary_hcd's shared_hcd pointer to null (since the non-primary HCD will be - * freed shortly). + * freed.  When hcd_release() is called for either hcd in a peer set + * invalidate the peer's ->shared_hcd and ->primary_hcd pointers to + * block new peering attempts   */ -static void hcd_release (struct kref *kref) +static void hcd_release(struct kref *kref)  {  	struct usb_hcd *hcd = container_of (kref, struct usb_hcd, kref); +	mutex_lock(&usb_port_peer_mutex);  	if (usb_hcd_is_primary_hcd(hcd))  		kfree(hcd->bandwidth_mutex); -	else -		hcd->shared_hcd->shared_hcd = NULL; +	if (hcd->shared_hcd) { +		struct usb_hcd *peer = hcd->shared_hcd; + +		peer->shared_hcd = NULL; +		if (peer->primary_hcd == hcd) +			peer->primary_hcd = NULL; +	} +	mutex_unlock(&usb_port_peer_mutex);  	kfree(hcd);  } @@ -2547,13 +2574,6 @@ static int usb_hcd_request_irqs(struct usb_hcd *hcd,  	if (hcd->driver->irq) { -		/* IRQF_DISABLED doesn't work as advertised when used together -		 * with IRQF_SHARED. As usb_hcd_irq() will always disable -		 * interrupts we can remove it here. -		 */ -		if (irqflags & IRQF_SHARED) -			irqflags &= ~IRQF_DISABLED; -  		snprintf(hcd->irq_descr, sizeof(hcd->irq_descr), "%s:usb%d",  				hcd->driver->description, hcd->self.busnum);  		retval = request_irq(irqnum, &usb_hcd_irq, irqflags, @@ -2580,6 +2600,21 @@ static int usb_hcd_request_irqs(struct usb_hcd *hcd,  	return 0;  } +/* + * Before we free this root hub, flush in-flight peering attempts + * and disable peer lookups + */ +static void usb_put_invalidate_rhdev(struct usb_hcd *hcd) +{ +	struct usb_device *rhdev; + +	mutex_lock(&usb_port_peer_mutex); +	rhdev = hcd->self.root_hub; +	hcd->self.root_hub = NULL; +	mutex_unlock(&usb_port_peer_mutex); +	usb_put_dev(rhdev); +} +  /**   * usb_add_hcd - finish generic HCD structure initialization and register   * @hcd: the usb_hcd structure to initialize @@ -2596,11 +2631,29 @@ int usb_add_hcd(struct usb_hcd *hcd,  	int retval;  	struct usb_device *rhdev; +	if (IS_ENABLED(CONFIG_USB_PHY) && !hcd->phy) { +		struct usb_phy *phy = usb_get_phy_dev(hcd->self.controller, 0); + +		if (IS_ERR(phy)) { +			retval = PTR_ERR(phy); +			if (retval == -EPROBE_DEFER) +				return retval; +		} else { +			retval = usb_phy_init(phy); +			if (retval) { +				usb_put_phy(phy); +				return retval; +			} +			hcd->phy = phy; +			hcd->remove_phy = 1; +		} +	} +  	dev_info(hcd->self.controller, "%s\n", hcd->product_desc);  	/* Keep old behaviour if authorized_default is not in [0, 1]. */  	if (authorized_default < 0 || authorized_default > 1) -		hcd->authorized_default = hcd->wireless? 0 : 1; +		hcd->authorized_default = hcd->wireless ? 0 : 1;  	else  		hcd->authorized_default = authorized_default;  	set_bit(HCD_FLAG_HW_ACCESSIBLE, &hcd->flags); @@ -2611,7 +2664,7 @@ int usb_add_hcd(struct usb_hcd *hcd,  	 */  	if ((retval = hcd_buffer_create(hcd)) != 0) {  		dev_dbg(hcd->self.controller, "pool alloc failed\n"); -		return retval; +		goto err_remove_phy;  	}  	if ((retval = usb_register_bus(&hcd->self)) < 0) @@ -2622,7 +2675,9 @@ int usb_add_hcd(struct usb_hcd *hcd,  		retval = -ENOMEM;  		goto err_allocate_root_hub;  	} +	mutex_lock(&usb_port_peer_mutex);  	hcd->self.root_hub = rhdev; +	mutex_unlock(&usb_port_peer_mutex);  	switch (hcd->speed) {  	case HCD_USB11: @@ -2701,12 +2756,6 @@ int usb_add_hcd(struct usb_hcd *hcd,  	if (hcd->uses_new_polling && HCD_POLL_RH(hcd))  		usb_hcd_poll_rh_status(hcd); -	/* -	 * Host controllers don't generate their own wakeup requests; -	 * they only forward requests from the root hub.  Therefore -	 * controllers should always be enabled for remote wakeup. -	 */ -	device_wakeup_enable(hcd->self.controller);  	return retval;  error_create_attr_group: @@ -2737,13 +2786,19 @@ err_hcd_driver_start:  err_request_irq:  err_hcd_driver_setup:  err_set_rh_speed: -	usb_put_dev(hcd->self.root_hub); +	usb_put_invalidate_rhdev(hcd);  err_allocate_root_hub:  	usb_deregister_bus(&hcd->self);  err_register_bus:  	hcd_buffer_destroy(hcd); +err_remove_phy: +	if (hcd->remove_phy && hcd->phy) { +		usb_phy_shutdown(hcd->phy); +		usb_put_phy(hcd->phy); +		hcd->phy = NULL; +	}  	return retval; -}  +}  EXPORT_SYMBOL_GPL(usb_add_hcd);  /** @@ -2811,14 +2866,20 @@ void usb_remove_hcd(struct usb_hcd *hcd)  			free_irq(hcd->irq, hcd);  	} -	usb_put_dev(hcd->self.root_hub);  	usb_deregister_bus(&hcd->self);  	hcd_buffer_destroy(hcd); +	if (hcd->remove_phy && hcd->phy) { +		usb_phy_shutdown(hcd->phy); +		usb_put_phy(hcd->phy); +		hcd->phy = NULL; +	} + +	usb_put_invalidate_rhdev(hcd);  }  EXPORT_SYMBOL_GPL(usb_remove_hcd);  void -usb_hcd_platform_shutdown(struct platform_device* dev) +usb_hcd_platform_shutdown(struct platform_device *dev)  {  	struct usb_hcd *hcd = platform_get_drvdata(dev); @@ -2840,7 +2901,7 @@ struct usb_mon_operations *mon_ops;   * Notice that the code is minimally error-proof. Because usbmon needs   * symbols from usbcore, usbcore gets referenced and cannot be unloaded first.   */ -  +  int usb_mon_register (struct usb_mon_operations *ops)  { diff --git a/drivers/usb/core/hub.c b/drivers/usb/core/hub.c index dde4c83516a..0e950ad8cb2 100644 --- a/drivers/usb/core/hub.c +++ b/drivers/usb/core/hub.c @@ -33,21 +33,9 @@  #include "hub.h" -/* if we are in debug mode, always announce new devices */ -#ifdef DEBUG -#ifndef CONFIG_USB_ANNOUNCE_NEW_DEVICES -#define CONFIG_USB_ANNOUNCE_NEW_DEVICES -#endif -#endif -  #define USB_VENDOR_GENESYS_LOGIC		0x05e3  #define HUB_QUIRK_CHECK_PORT_AUTOSUSPEND	0x01 -static inline int hub_is_superspeed(struct usb_device *hdev) -{ -	return (hdev->descriptor.bDeviceProtocol == USB_HUB_PR_SS); -} -  /* Protect struct usb_device->state and ->children members   * Note: Both are also protected by ->dev.sem, except that ->state can   * change to USB_STATE_NOTATTACHED even when the semaphore isn't held. */ @@ -62,6 +50,9 @@ static DECLARE_WAIT_QUEUE_HEAD(khubd_wait);  static struct task_struct *khubd_task; +/* synchronize hub-port add/remove and peering operations */ +DEFINE_MUTEX(usb_port_peer_mutex); +  /* cycle leds on hubs that aren't blinking for attention */  static bool blinkenlights = 0;  module_param (blinkenlights, bool, S_IRUGO); @@ -120,7 +111,7 @@ static inline char *portspeed(struct usb_hub *hub, int portstatus)  	if (hub_is_superspeed(hub->hdev))  		return "5.0 Gb/s";  	if (portstatus & USB_PORT_STAT_HIGH_SPEED) -    		return "480 Mb/s"; +		return "480 Mb/s";  	else if (portstatus & USB_PORT_STAT_LOW_SPEED)  		return "1.5 Mb/s";  	else @@ -148,19 +139,27 @@ static int usb_device_supports_lpm(struct usb_device *udev)  		return 0;  	} -	/* All USB 3.0 must support LPM, but we need their max exit latency -	 * information from the SuperSpeed Extended Capabilities BOS descriptor. +	/* +	 * According to the USB 3.0 spec, all USB 3.0 devices must support LPM. +	 * However, there are some that don't, and they set the U1/U2 exit +	 * latencies to zero.  	 */  	if (!udev->bos->ss_cap) { -		dev_warn(&udev->dev, "No LPM exit latency info found.  " -				"Power management will be impacted.\n"); +		dev_info(&udev->dev, "No LPM exit latency info found, disabling LPM.\n");  		return 0;  	} -	if (udev->parent->lpm_capable) -		return 1; -	dev_warn(&udev->dev, "Parent hub missing LPM exit latency info.  " -			"Power management will be impacted.\n"); +	if (udev->bos->ss_cap->bU1devExitLat == 0 && +			udev->bos->ss_cap->bU2DevExitLat == 0) { +		if (udev->parent) +			dev_info(&udev->dev, "LPM exit latency is zeroed, disabling LPM.\n"); +		else +			dev_info(&udev->dev, "We don't know the algorithms for LPM for this host, disabling LPM.\n"); +		return 0; +	} + +	if (!udev->parent || udev->parent->lpm_capable) +		return 1;  	return 0;  } @@ -310,9 +309,9 @@ static void usb_set_lpm_parameters(struct usb_device *udev)  		return;  	udev_u1_del = udev->bos->ss_cap->bU1devExitLat; -	udev_u2_del = udev->bos->ss_cap->bU2DevExitLat; +	udev_u2_del = le16_to_cpu(udev->bos->ss_cap->bU2DevExitLat);  	hub_u1_del = udev->parent->bos->ss_cap->bU1devExitLat; -	hub_u2_del = udev->parent->bos->ss_cap->bU2DevExitLat; +	hub_u2_del = le16_to_cpu(udev->parent->bos->ss_cap->bU2DevExitLat);  	usb_set_lpm_mel(udev, &udev->u1_params, udev_u1_del,  			hub, &udev->parent->u1_params, hub_u1_del); @@ -411,30 +410,35 @@ static int set_port_feature(struct usb_device *hdev, int port1, int feature)  		NULL, 0, 1000);  } +static char *to_led_name(int selector) +{ +	switch (selector) { +	case HUB_LED_AMBER: +		return "amber"; +	case HUB_LED_GREEN: +		return "green"; +	case HUB_LED_OFF: +		return "off"; +	case HUB_LED_AUTO: +		return "auto"; +	default: +		return "??"; +	} +} +  /*   * USB 2.0 spec Section 11.24.2.7.1.10 and table 11-7   * for info about using port indicators   */ -static void set_port_led( -	struct usb_hub *hub, -	int port1, -	int selector -) +static void set_port_led(struct usb_hub *hub, int port1, int selector)  { -	int status = set_port_feature(hub->hdev, (selector << 8) | port1, +	struct usb_port *port_dev = hub->ports[port1 - 1]; +	int status; + +	status = set_port_feature(hub->hdev, (selector << 8) | port1,  			USB_PORT_FEAT_INDICATOR); -	if (status < 0) -		dev_dbg (hub->intfdev, -			"port %d indicator %s status %d\n", -			port1, -			({ char *s; switch (selector) { -			case HUB_LED_AMBER: s = "amber"; break; -			case HUB_LED_GREEN: s = "green"; break; -			case HUB_LED_OFF: s = "off"; break; -			case HUB_LED_AUTO: s = "auto"; break; -			default: s = "??"; break; -			}; s; }), -			status); +	dev_dbg(&port_dev->dev, "indicator %s status %d\n", +		to_led_name(selector), status);  }  #define	LED_CYCLE_PERIOD	((2*HZ)/3) @@ -506,7 +510,8 @@ static void led_work (struct work_struct *work)  		changed++;  	}  	if (changed) -		schedule_delayed_work(&hub->leds, LED_CYCLE_PERIOD); +		queue_delayed_work(system_power_efficient_wq, +				&hub->leds, LED_CYCLE_PERIOD);  }  /* use a short timeout for hub/port status fetches */ @@ -741,16 +746,20 @@ int usb_hub_set_port_power(struct usb_device *hdev, struct usb_hub *hub,  			   int port1, bool set)  {  	int ret; -	struct usb_port *port_dev = hub->ports[port1 - 1];  	if (set)  		ret = set_port_feature(hdev, port1, USB_PORT_FEAT_POWER);  	else  		ret = usb_clear_port_feature(hdev, port1, USB_PORT_FEAT_POWER); -	if (!ret) -		port_dev->power_is_on = set; -	return ret; +	if (ret) +		return ret; + +	if (set) +		set_bit(port1, hub->power_bits); +	else +		clear_bit(port1, hub->power_bits); +	return 0;  }  /** @@ -808,16 +817,9 @@ int usb_hub_clear_tt_buffer(struct urb *urb)  }  EXPORT_SYMBOL_GPL(usb_hub_clear_tt_buffer); -/* If do_delay is false, return the number of milliseconds the caller - * needs to delay. - */ -static unsigned hub_power_on(struct usb_hub *hub, bool do_delay) +static void hub_power_on(struct usb_hub *hub, bool do_delay)  {  	int port1; -	unsigned pgood_delay = hub->descriptor->bPwrOn2PwrGood * 2; -	unsigned delay; -	u16 wHubCharacteristics = -			le16_to_cpu(hub->descriptor->wHubCharacteristics);  	/* Enable power on each port.  Some hubs have reserved values  	 * of LPSM (> 2) in their descriptors, even though they are @@ -825,23 +827,19 @@ static unsigned hub_power_on(struct usb_hub *hub, bool do_delay)  	 * but only emulate it.  In all cases, the ports won't work  	 * unless we send these messages to the hub.  	 */ -	if ((wHubCharacteristics & HUB_CHAR_LPSM) < 2) +	if (hub_is_port_power_switchable(hub))  		dev_dbg(hub->intfdev, "enabling power on all ports\n");  	else  		dev_dbg(hub->intfdev, "trying to enable port power on "  				"non-switchable hub\n");  	for (port1 = 1; port1 <= hub->hdev->maxchild; port1++) -		if (hub->ports[port1 - 1]->power_is_on) +		if (test_bit(port1, hub->power_bits))  			set_port_feature(hub->hdev, port1, USB_PORT_FEAT_POWER);  		else  			usb_clear_port_feature(hub->hdev, port1,  						USB_PORT_FEAT_POWER); - -	/* Wait at least 100 msec for power to become stable */ -	delay = max(pgood_delay, (unsigned) 100);  	if (do_delay) -		msleep(delay); -	return delay; +		msleep(hub_power_on_good_delay(hub));  }  static int hub_hub_status(struct usb_hub *hub, @@ -857,7 +855,7 @@ static int hub_hub_status(struct usb_hub *hub,  				"%s failed (err = %d)\n", __func__, ret);  	} else {  		*status = le16_to_cpu(hub->status->hub.wHubStatus); -		*change = le16_to_cpu(hub->status->hub.wHubChange);  +		*change = le16_to_cpu(hub->status->hub.wHubChange);  		ret = 0;  	}  	mutex_unlock(&hub->status_mutex); @@ -891,6 +889,25 @@ static int hub_usb3_port_disable(struct usb_hub *hub, int port1)  	if (!hub_is_superspeed(hub->hdev))  		return -EINVAL; +	ret = hub_port_status(hub, port1, &portstatus, &portchange); +	if (ret < 0) +		return ret; + +	/* +	 * USB controller Advanced Micro Devices, Inc. [AMD] FCH USB XHCI +	 * Controller [1022:7814] will have spurious result making the following +	 * usb 3.0 device hotplugging route to the 2.0 root hub and recognized +	 * as high-speed device if we set the usb 3.0 port link state to +	 * Disabled. Since it's already in USB_SS_PORT_LS_RX_DETECT state, we +	 * check the state here to avoid the bug. +	 */ +	if ((portstatus & USB_PORT_STAT_LINK_STATE) == +				USB_SS_PORT_LS_RX_DETECT) { +		dev_dbg(&hub->ports[port1 - 1]->dev, +			 "Not disabling port; link state is RxDetect\n"); +		return ret; +	} +  	ret = hub_set_port_link_state(hub, port1, USB_SS_PORT_LS_SS_DISABLED);  	if (ret)  		return ret; @@ -909,20 +926,20 @@ static int hub_usb3_port_disable(struct usb_hub *hub, int port1)  		msleep(HUB_DEBOUNCE_STEP);  	}  	if (total_time >= HUB_DEBOUNCE_TIMEOUT) -		dev_warn(hub->intfdev, "Could not disable port %d after %d ms\n", -				port1, total_time); +		dev_warn(&hub->ports[port1 - 1]->dev, +				"Could not disable after %d ms\n", total_time);  	return hub_set_port_link_state(hub, port1, USB_SS_PORT_LS_RX_DETECT);  }  static int hub_port_disable(struct usb_hub *hub, int port1, int set_state)  { +	struct usb_port *port_dev = hub->ports[port1 - 1];  	struct usb_device *hdev = hub->hdev;  	int ret = 0; -	if (hub->ports[port1 - 1]->child && set_state) -		usb_set_device_state(hub->ports[port1 - 1]->child, -				USB_STATE_NOTATTACHED); +	if (port_dev->child && set_state) +		usb_set_device_state(port_dev->child, USB_STATE_NOTATTACHED);  	if (!hub->error) {  		if (hub_is_superspeed(hub->hdev))  			ret = hub_usb3_port_disable(hub, port1); @@ -931,8 +948,7 @@ static int hub_port_disable(struct usb_hub *hub, int port1, int set_state)  					USB_PORT_FEAT_ENABLE);  	}  	if (ret && ret != -ENODEV) -		dev_err(hub->intfdev, "cannot disable port %d (err = %d)\n", -				port1, ret); +		dev_err(&port_dev->dev, "cannot disable (err = %d)\n", ret);  	return ret;  } @@ -943,7 +959,7 @@ static int hub_port_disable(struct usb_hub *hub, int port1, int set_state)   */  static void hub_port_logical_disconnect(struct usb_hub *hub, int port1)  { -	dev_dbg(hub->intfdev, "logical disconnect on port %d\n", port1); +	dev_dbg(&hub->ports[port1 - 1]->dev, "logical disconnect\n");  	hub_port_disable(hub, port1, 1);  	/* FIXME let caller ask to power down the port: @@ -956,7 +972,7 @@ static void hub_port_logical_disconnect(struct usb_hub *hub, int port1)  	 */  	set_bit(port1, hub->change_bits); - 	kick_khubd(hub); +	kick_khubd(hub);  }  /** @@ -1046,9 +1062,12 @@ static void hub_activate(struct usb_hub *hub, enum hub_activation_type type)  		 * for HUB_POST_RESET, but it's easier not to.  		 */  		if (type == HUB_INIT) { -			delay = hub_power_on(hub, false); -			PREPARE_DELAYED_WORK(&hub->init_work, hub_init_func2); -			schedule_delayed_work(&hub->init_work, +			unsigned delay = hub_power_on_good_delay(hub); + +			hub_power_on(hub, false); +			INIT_DELAYED_WORK(&hub->init_work, hub_init_func2); +			queue_delayed_work(system_power_efficient_wq, +					&hub->init_work,  					msecs_to_jiffies(delay));  			/* Suppress autosuspend until init is done */ @@ -1080,21 +1099,23 @@ static void hub_activate(struct usb_hub *hub, enum hub_activation_type type)  	}   init2: -	/* Check each port and set hub->change_bits to let khubd know +	/* +	 * Check each port and set hub->change_bits to let khubd know  	 * which ports need attention.  	 */  	for (port1 = 1; port1 <= hdev->maxchild; ++port1) { -		struct usb_device *udev = hub->ports[port1 - 1]->child; +		struct usb_port *port_dev = hub->ports[port1 - 1]; +		struct usb_device *udev = port_dev->child;  		u16 portstatus, portchange;  		portstatus = portchange = 0;  		status = hub_port_status(hub, port1, &portstatus, &portchange);  		if (udev || (portstatus & USB_PORT_STAT_CONNECTION)) -			dev_dbg(hub->intfdev, -					"port %d: status %04x change %04x\n", -					port1, portstatus, portchange); +			dev_dbg(&port_dev->dev, "status %04x change %04x\n", +					portstatus, portchange); -		/* After anything other than HUB_RESUME (i.e., initialization +		/* +		 * After anything other than HUB_RESUME (i.e., initialization  		 * or any sort of reset), every port should be disabled.  		 * Unconnected ports should likewise be disabled (paranoia),  		 * and so should ports for which we have no usb_device. @@ -1107,16 +1128,13 @@ static void hub_activate(struct usb_hub *hub, enum hub_activation_type type)  			/*  			 * USB3 protocol ports will automatically transition  			 * to Enabled state when detect an USB3.0 device attach. -			 * Do not disable USB3 protocol ports. +			 * Do not disable USB3 protocol ports, just pretend +			 * power was lost  			 */ -			if (!hub_is_superspeed(hdev)) { +			portstatus &= ~USB_PORT_STAT_ENABLE; +			if (!hub_is_superspeed(hdev))  				usb_clear_port_feature(hdev, port1,  						   USB_PORT_FEAT_ENABLE); -				portstatus &= ~USB_PORT_STAT_ENABLE; -			} else { -				/* Pretend that power was lost for USB3 devs */ -				portstatus &= ~USB_PORT_STAT_ENABLE; -			}  		}  		/* Clear status-change flags; we'll debounce later */ @@ -1130,6 +1148,11 @@ static void hub_activate(struct usb_hub *hub, enum hub_activation_type type)  			usb_clear_port_feature(hub->hdev, port1,  					USB_PORT_FEAT_C_ENABLE);  		} +		if (portchange & USB_PORT_STAT_C_RESET) { +			need_debounce_delay = true; +			usb_clear_port_feature(hub->hdev, port1, +					USB_PORT_FEAT_C_RESET); +		}  		if ((portchange & USB_PORT_STAT_C_BH_RESET) &&  				hub_is_superspeed(hub->hdev)) {  			need_debounce_delay = true; @@ -1147,7 +1170,8 @@ static void hub_activate(struct usb_hub *hub, enum hub_activation_type type)  			/* Tell khubd to disconnect the device or  			 * check for a new connection  			 */ -			if (udev || (portstatus & USB_PORT_STAT_CONNECTION)) +			if (udev || (portstatus & USB_PORT_STAT_CONNECTION) || +			    (portstatus & USB_PORT_STAT_OVERCURRENT))  				set_bit(port1, hub->change_bits);  		} else if (portstatus & USB_PORT_STAT_ENABLE) { @@ -1167,15 +1191,13 @@ static void hub_activate(struct usb_hub *hub, enum hub_activation_type type)  				set_bit(port1, hub->change_bits);  		} else if (udev->persist_enabled) { -			struct usb_port *port_dev = hub->ports[port1 - 1]; -  #ifdef CONFIG_PM  			udev->reset_resume = 1;  #endif  			/* Don't set the change_bits when the device  			 * was powered off.  			 */ -			if (port_dev->power_is_on) +			if (test_bit(port1, hub->power_bits))  				set_bit(port1, hub->change_bits);  		} else { @@ -1198,8 +1220,9 @@ static void hub_activate(struct usb_hub *hub, enum hub_activation_type type)  		/* Don't do a long sleep inside a workqueue routine */  		if (type == HUB_INIT2) { -			PREPARE_DELAYED_WORK(&hub->init_work, hub_init_func3); -			schedule_delayed_work(&hub->init_work, +			INIT_DELAYED_WORK(&hub->init_work, hub_init_func3); +			queue_delayed_work(system_power_efficient_wq, +					&hub->init_work,  					msecs_to_jiffies(delay));  			return;		/* Continues at init3: below */  		} else { @@ -1213,7 +1236,8 @@ static void hub_activate(struct usb_hub *hub, enum hub_activation_type type)  	if (status < 0)  		dev_err(hub->intfdev, "activate --> %d\n", status);  	if (hub->has_indicators && blinkenlights) -		schedule_delayed_work(&hub->leds, LED_CYCLE_PERIOD); +		queue_delayed_work(system_power_efficient_wq, +				&hub->leds, LED_CYCLE_PERIOD);  	/* Scan all ports that need attention */  	kick_khubd(hub); @@ -1268,12 +1292,22 @@ static void hub_quiesce(struct usb_hub *hub, enum hub_quiescing_type type)  		flush_work(&hub->tt.clear_work);  } +static void hub_pm_barrier_for_all_ports(struct usb_hub *hub) +{ +	int i; + +	for (i = 0; i < hub->hdev->maxchild; ++i) +		pm_runtime_barrier(&hub->ports[i]->dev); +} +  /* caller has locked the hub device */  static int hub_pre_reset(struct usb_interface *intf)  {  	struct usb_hub *hub = usb_get_intfdata(intf);  	hub_quiesce(hub, HUB_PRE_RESET); +	hub->in_reset = 1; +	hub_pm_barrier_for_all_ports(hub);  	return 0;  } @@ -1282,6 +1316,8 @@ static int hub_post_reset(struct usb_interface *intf)  {  	struct usb_hub *hub = usb_get_intfdata(intf); +	hub->in_reset = 0; +	hub_pm_barrier_for_all_ports(hub);  	hub_activate(hub, HUB_POST_RESET);  	return 0;  } @@ -1299,6 +1335,7 @@ static int hub_configure(struct usb_hub *hub,  	char *message = "out of memory";  	unsigned unit_load;  	unsigned full_load; +	unsigned maxchild;  	hub->buffer = kmalloc(sizeof(*hub->buffer), GFP_KERNEL);  	if (!hub->buffer) { @@ -1337,12 +1374,11 @@ static int hub_configure(struct usb_hub *hub,  		goto fail;  	} -	hdev->maxchild = hub->descriptor->bNbrPorts; -	dev_info (hub_dev, "%d port%s detected\n", hdev->maxchild, -		(hdev->maxchild == 1) ? "" : "s"); +	maxchild = hub->descriptor->bNbrPorts; +	dev_info(hub_dev, "%d port%s detected\n", maxchild, +			(maxchild == 1) ? "" : "s"); -	hub->ports = kzalloc(hdev->maxchild * sizeof(struct usb_port *), -			     GFP_KERNEL); +	hub->ports = kzalloc(maxchild * sizeof(struct usb_port *), GFP_KERNEL);  	if (!hub->ports) {  		ret = -ENOMEM;  		goto fail; @@ -1361,13 +1397,13 @@ static int hub_configure(struct usb_hub *hub,  	if ((wHubCharacteristics & HUB_CHAR_COMPOUND) &&  			!(hub_is_superspeed(hdev))) {  		int	i; -		char	portstr [USB_MAXCHILDREN + 1]; +		char	portstr[USB_MAXCHILDREN + 1]; -		for (i = 0; i < hdev->maxchild; i++) +		for (i = 0; i < maxchild; i++)  			portstr[i] = hub->descriptor->u.hs.DeviceRemovable  				    [((i + 1) / 8)] & (1 << ((i + 1) % 8))  				? 'F' : 'R'; -		portstr[hdev->maxchild] = 0; +		portstr[maxchild] = 0;  		dev_dbg(hub_dev, "compound device; port removable status: %s\n", portstr);  	} else  		dev_dbg(hub_dev, "standalone hub\n"); @@ -1429,32 +1465,32 @@ static int hub_configure(struct usb_hub *hub,  	/* Note 8 FS bit times == (8 bits / 12000000 bps) ~= 666ns */  	switch (wHubCharacteristics & HUB_CHAR_TTTT) { -		case HUB_TTTT_8_BITS: -			if (hdev->descriptor.bDeviceProtocol != 0) { -				hub->tt.think_time = 666; -				dev_dbg(hub_dev, "TT requires at most %d " -						"FS bit times (%d ns)\n", -					8, hub->tt.think_time); -			} -			break; -		case HUB_TTTT_16_BITS: -			hub->tt.think_time = 666 * 2; -			dev_dbg(hub_dev, "TT requires at most %d " -					"FS bit times (%d ns)\n", -				16, hub->tt.think_time); -			break; -		case HUB_TTTT_24_BITS: -			hub->tt.think_time = 666 * 3; -			dev_dbg(hub_dev, "TT requires at most %d " -					"FS bit times (%d ns)\n", -				24, hub->tt.think_time); -			break; -		case HUB_TTTT_32_BITS: -			hub->tt.think_time = 666 * 4; +	case HUB_TTTT_8_BITS: +		if (hdev->descriptor.bDeviceProtocol != 0) { +			hub->tt.think_time = 666;  			dev_dbg(hub_dev, "TT requires at most %d "  					"FS bit times (%d ns)\n", -				32, hub->tt.think_time); -			break; +				8, hub->tt.think_time); +		} +		break; +	case HUB_TTTT_16_BITS: +		hub->tt.think_time = 666 * 2; +		dev_dbg(hub_dev, "TT requires at most %d " +				"FS bit times (%d ns)\n", +			16, hub->tt.think_time); +		break; +	case HUB_TTTT_24_BITS: +		hub->tt.think_time = 666 * 3; +		dev_dbg(hub_dev, "TT requires at most %d " +				"FS bit times (%d ns)\n", +			24, hub->tt.think_time); +		break; +	case HUB_TTTT_32_BITS: +		hub->tt.think_time = 666 * 4; +		dev_dbg(hub_dev, "TT requires at most %d " +				"FS bit times (%d ns)\n", +			32, hub->tt.think_time); +		break;  	}  	/* probe() zeroes hub->indicator[] */ @@ -1479,7 +1515,7 @@ static int hub_configure(struct usb_hub *hub,  		if (hcd->power_budget > 0)  			hdev->bus_mA = hcd->power_budget;  		else -			hdev->bus_mA = full_load * hdev->maxchild; +			hdev->bus_mA = full_load * maxchild;  		if (hdev->bus_mA >= full_load)  			hub->mA_per_port = full_load;  		else { @@ -1494,7 +1530,7 @@ static int hub_configure(struct usb_hub *hub,  			hub->descriptor->bHubContrCurrent);  		hub->limited_power = 1; -		if (remaining < hdev->maxchild * unit_load) +		if (remaining < maxchild * unit_load)  			dev_warn(hub_dev,  					"insufficient power available "  					"to use all downstream ports\n"); @@ -1509,18 +1545,6 @@ static int hub_configure(struct usb_hub *hub,  		dev_dbg(hub_dev, "%umA bus power budget for each child\n",  				hub->mA_per_port); -	/* Update the HCD's internal representation of this hub before khubd -	 * starts getting port status changes for devices under the hub. -	 */ -	if (hcd->driver->update_hub_device) { -		ret = hcd->driver->update_hub_device(hcd, hdev, -				&hub->tt, GFP_KERNEL); -		if (ret < 0) { -			message = "can't update HCD hub info"; -			goto fail; -		} -	} -  	ret = hub_hub_status(hub, &hubstatus, &hubchange);  	if (ret < 0) {  		message = "can't get hub status"; @@ -1560,15 +1584,37 @@ static int hub_configure(struct usb_hub *hub,  	/* maybe cycle the hub leds */  	if (hub->has_indicators && blinkenlights) -		hub->indicator [0] = INDICATOR_CYCLE; +		hub->indicator[0] = INDICATOR_CYCLE; -	for (i = 0; i < hdev->maxchild; i++) { +	mutex_lock(&usb_port_peer_mutex); +	for (i = 0; i < maxchild; i++) {  		ret = usb_hub_create_port_device(hub, i + 1);  		if (ret < 0) {  			dev_err(hub->intfdev,  				"couldn't create port%d device.\n", i + 1); -			hdev->maxchild = i; -			goto fail_keep_maxchild; +			break; +		} +	} +	hdev->maxchild = i; +	for (i = 0; i < hdev->maxchild; i++) { +		struct usb_port *port_dev = hub->ports[i]; + +		pm_runtime_put(&port_dev->dev); +	} + +	mutex_unlock(&usb_port_peer_mutex); +	if (ret < 0) +		goto fail; + +	/* Update the HCD's internal representation of this hub before khubd +	 * starts getting port status changes for devices under the hub. +	 */ +	if (hcd->driver->update_hub_device) { +		ret = hcd->driver->update_hub_device(hcd, hdev, +				&hub->tt, GFP_KERNEL); +		if (ret < 0) { +			message = "can't update HCD hub info"; +			goto fail;  		}  	} @@ -1578,8 +1624,6 @@ static int hub_configure(struct usb_hub *hub,  	return 0;  fail: -	hdev->maxchild = 0; -fail_keep_maxchild:  	dev_err (hub_dev, "config failed, %s (err %d)\n",  			message, ret);  	/* hub_disconnect() frees urb and descriptor */ @@ -1600,7 +1644,7 @@ static void hub_disconnect(struct usb_interface *intf)  {  	struct usb_hub *hub = usb_get_intfdata(intf);  	struct usb_device *hdev = interface_to_usbdev(intf); -	int i; +	int port1;  	/* Take the hub off the event list and don't let it be added again */  	spin_lock_irq(&hub_event_lock); @@ -1615,11 +1659,19 @@ static void hub_disconnect(struct usb_interface *intf)  	hub->error = 0;  	hub_quiesce(hub, HUB_DISCONNECT); -	usb_set_intfdata (intf, NULL); +	mutex_lock(&usb_port_peer_mutex); -	for (i = 0; i < hdev->maxchild; i++) -		usb_hub_remove_port_device(hub, i + 1); -	hub->hdev->maxchild = 0; +	/* Avoid races with recursively_mark_NOTATTACHED() */ +	spin_lock_irq(&device_state_lock); +	port1 = hdev->maxchild; +	hdev->maxchild = 0; +	usb_set_intfdata(intf, NULL); +	spin_unlock_irq(&device_state_lock); + +	for (; port1 > 0; --port1) +		usb_hub_remove_port_device(hub, port1); + +	mutex_unlock(&usb_port_peer_mutex);  	if (hub->hdev->speed == USB_SPEED_HIGH)  		highspeed_hubs--; @@ -1679,8 +1731,19 @@ static int hub_probe(struct usb_interface *intf, const struct usb_device_id *id)  	 */  	pm_runtime_set_autosuspend_delay(&hdev->dev, 0); -	/* Hubs have proper suspend/resume support. */ -	usb_enable_autosuspend(hdev); +	/* +	 * Hubs have proper suspend/resume support, except for root hubs +	 * where the controller driver doesn't have bus_suspend and +	 * bus_resume methods. +	 */ +	if (hdev->parent) {		/* normal device */ +		usb_enable_autosuspend(hdev); +	} else {			/* root hub */ +		const struct hc_driver *drv = bus_to_hcd(hdev->bus)->driver; + +		if (drv->bus_suspend && drv->bus_resume) +			usb_enable_autosuspend(hdev); +	}  	if (hdev->level == MAX_TOPO_LEVEL) {  		dev_err(&intf->dev, @@ -1788,7 +1851,7 @@ hub_ioctl(struct usb_interface *intf, unsigned int code, void *user_data)   * to one of these "claimed" ports, the program will "own" the device.   */  static int find_port_owner(struct usb_device *hdev, unsigned port1, -		struct dev_state ***ppowner) +		struct usb_dev_state ***ppowner)  {  	struct usb_hub *hub = usb_hub_to_struct_hub(hdev); @@ -1806,10 +1869,10 @@ static int find_port_owner(struct usb_device *hdev, unsigned port1,  /* In the following three functions, the caller must hold hdev's lock */  int usb_hub_claim_port(struct usb_device *hdev, unsigned port1, -		       struct dev_state *owner) +		       struct usb_dev_state *owner)  {  	int rc; -	struct dev_state **powner; +	struct usb_dev_state **powner;  	rc = find_port_owner(hdev, port1, &powner);  	if (rc) @@ -1819,12 +1882,13 @@ int usb_hub_claim_port(struct usb_device *hdev, unsigned port1,  	*powner = owner;  	return rc;  } +EXPORT_SYMBOL_GPL(usb_hub_claim_port);  int usb_hub_release_port(struct usb_device *hdev, unsigned port1, -			 struct dev_state *owner) +			 struct usb_dev_state *owner)  {  	int rc; -	struct dev_state **powner; +	struct usb_dev_state **powner;  	rc = find_port_owner(hdev, port1, &powner);  	if (rc) @@ -1834,8 +1898,9 @@ int usb_hub_release_port(struct usb_device *hdev, unsigned port1,  	*powner = NULL;  	return rc;  } +EXPORT_SYMBOL_GPL(usb_hub_release_port); -void usb_hub_release_all_ports(struct usb_device *hdev, struct dev_state *owner) +void usb_hub_release_all_ports(struct usb_device *hdev, struct usb_dev_state *owner)  {  	struct usb_hub *hub = usb_hub_to_struct_hub(hdev);  	int n; @@ -1978,7 +2043,7 @@ static void choose_devnum(struct usb_device *udev)  		if (devnum >= 128)  			devnum = find_next_zero_bit(bus->devmap.devicemap,  						    128, 1); -		bus->devnum_next = ( devnum >= 127 ? 1 : devnum + 1); +		bus->devnum_next = (devnum >= 127 ? 1 : devnum + 1);  	}  	if (devnum < 128) {  		set_bit(devnum, bus->devmap.devicemap); @@ -2010,6 +2075,18 @@ static void hub_free_dev(struct usb_device *udev)  		hcd->driver->free_dev(hcd, udev);  } +static void hub_disconnect_children(struct usb_device *udev) +{ +	struct usb_hub *hub = usb_hub_to_struct_hub(udev); +	int i; + +	/* Free up all the children before we remove this device */ +	for (i = 0; i < udev->maxchild; i++) { +		if (hub->ports[i]->child) +			usb_disconnect(&hub->ports[i]->child); +	} +} +  /**   * usb_disconnect - disconnect a device (usbcore-internal)   * @pdev: pointer to device being disconnected @@ -2018,8 +2095,8 @@ static void hub_free_dev(struct usb_device *udev)   * Something got disconnected. Get rid of it and all of its children.   *   * If *pdev is a normal device then the parent hub must already be locked. - * If *pdev is a root hub then this routine will acquire the - * usb_bus_list_lock on behalf of the caller. + * If *pdev is a root hub then the caller must hold the usb_bus_list_lock, + * which protects the set of root hubs as well as the list of buses.   *   * Only hub drivers (including virtual root hub drivers for host   * controllers) should ever call this. @@ -2028,9 +2105,10 @@ static void hub_free_dev(struct usb_device *udev)   */  void usb_disconnect(struct usb_device **pdev)  { -	struct usb_device	*udev = *pdev; -	struct usb_hub		*hub = usb_hub_to_struct_hub(udev); -	int			i; +	struct usb_port *port_dev = NULL; +	struct usb_device *udev = *pdev; +	struct usb_hub *hub; +	int port1;  	/* mark the device as inactive, so any further urb submissions for  	 * this device (and any of its children) will fail immediately. @@ -2042,11 +2120,7 @@ void usb_disconnect(struct usb_device **pdev)  	usb_lock_device(udev); -	/* Free up all the children before we remove this device */ -	for (i = 0; i < udev->maxchild; i++) { -		if (hub->ports[i]->child) -			usb_disconnect(&hub->ports[i]->child); -	} +	hub_disconnect_children(udev);  	/* deallocate hcd/hardware state ... nuking all pending urbs and  	 * cleaning up all state associated with the current configuration @@ -2057,16 +2131,19 @@ void usb_disconnect(struct usb_device **pdev)  	usb_hcd_synchronize_unlinks(udev);  	if (udev->parent) { -		struct usb_hub *hub = usb_hub_to_struct_hub(udev->parent); -		struct usb_port	*port_dev = hub->ports[udev->portnum - 1]; +		port1 = udev->portnum; +		hub = usb_hub_to_struct_hub(udev->parent); +		port_dev = hub->ports[port1 - 1];  		sysfs_remove_link(&udev->dev.kobj, "port");  		sysfs_remove_link(&port_dev->dev.kobj, "device"); -		if (!port_dev->did_runtime_put) -			pm_runtime_put(&port_dev->dev); -		else -			port_dev->did_runtime_put = false; +		/* +		 * As usb_port_runtime_resume() de-references udev, make +		 * sure no resumes occur during removal +		 */ +		if (!test_and_set_bit(port1, hub->child_usage_bits)) +			pm_runtime_get_sync(&port_dev->dev);  	}  	usb_remove_ep_devs(&udev->ep0); @@ -2088,6 +2165,9 @@ void usb_disconnect(struct usb_device **pdev)  	*pdev = NULL;  	spin_unlock_irq(&device_state_lock); +	if (port_dev && test_and_clear_bit(port1, hub->child_usage_bits)) +		pm_runtime_put(&port_dev->dev); +  	hub_free_dev(udev);  	put_device(&udev->dev); @@ -2228,18 +2308,13 @@ static int usb_enumerate_device(struct usb_device *udev)  			return err;  		}  	} -	if (udev->wusb == 1 && udev->authorized == 0) { -		udev->product = kstrdup("n/a (unauthorized)", GFP_KERNEL); -		udev->manufacturer = kstrdup("n/a (unauthorized)", GFP_KERNEL); -		udev->serial = kstrdup("n/a (unauthorized)", GFP_KERNEL); -	} -	else { -		/* read the standard strings and cache them if present */ -		udev->product = usb_cache_string(udev, udev->descriptor.iProduct); -		udev->manufacturer = usb_cache_string(udev, -						      udev->descriptor.iManufacturer); -		udev->serial = usb_cache_string(udev, udev->descriptor.iSerialNumber); -	} + +	/* read the standard strings and cache them if present */ +	udev->product = usb_cache_string(udev, udev->descriptor.iProduct); +	udev->manufacturer = usb_cache_string(udev, +					      udev->descriptor.iManufacturer); +	udev->serial = usb_cache_string(udev, udev->descriptor.iSerialNumber); +  	err = usb_enumerate_device_otg(udev);  	if (err < 0)  		return err; @@ -2280,6 +2355,22 @@ static void set_usb_port_removable(struct usb_device *udev)  		udev->removable = USB_DEVICE_REMOVABLE;  	else  		udev->removable = USB_DEVICE_FIXED; + +	/* +	 * Platform firmware may have populated an alternative value for +	 * removable.  If the parent port has a known connect_type use +	 * that instead. +	 */ +	switch (hub->ports[udev->portnum - 1]->connect_type) { +	case USB_PORT_CONNECT_TYPE_HOT_PLUG: +		udev->removable = USB_DEVICE_REMOVABLE; +		break; +	case USB_PORT_CONNECT_TYPE_HARD_WIRED: +		udev->removable = USB_DEVICE_FIXED; +		break; +	default: /* use what was set above */ +		break; +	}  }  /** @@ -2349,11 +2440,7 @@ int usb_new_device(struct usb_device *udev)  	device_enable_async_suspend(&udev->dev); -	/* -	 * check whether the hub marks this port as non-removable. Do it -	 * now so that platform-specific data can override it in -	 * device_add() -	 */ +	/* check whether the hub or firmware marks this port as non-removable */  	if (udev->parent)  		set_usb_port_removable(udev); @@ -2370,7 +2457,8 @@ int usb_new_device(struct usb_device *udev)  	/* Create link files between child device and usb port device. */  	if (udev->parent) {  		struct usb_hub *hub = usb_hub_to_struct_hub(udev->parent); -		struct usb_port	*port_dev = hub->ports[udev->portnum - 1]; +		int port1 = udev->portnum; +		struct usb_port	*port_dev = hub->ports[port1 - 1];  		err = sysfs_create_link(&udev->dev.kobj,  				&port_dev->dev.kobj, "port"); @@ -2384,7 +2472,8 @@ int usb_new_device(struct usb_device *udev)  			goto fail;  		} -		pm_runtime_get_sync(&port_dev->dev); +		if (!test_and_set_bit(port1, hub->child_usage_bits)) +			pm_runtime_get_sync(&port_dev->dev);  	}  	(void) usb_create_ep_devs(&udev->dev, &udev->ep0, udev); @@ -2421,16 +2510,6 @@ int usb_deauthorize_device(struct usb_device *usb_dev)  	usb_dev->authorized = 0;  	usb_set_configuration(usb_dev, -1); -	kfree(usb_dev->product); -	usb_dev->product = kstrdup("n/a (unauthorized)", GFP_KERNEL); -	kfree(usb_dev->manufacturer); -	usb_dev->manufacturer = kstrdup("n/a (unauthorized)", GFP_KERNEL); -	kfree(usb_dev->serial); -	usb_dev->serial = kstrdup("n/a (unauthorized)", GFP_KERNEL); - -	usb_destroy_configuration(usb_dev); -	usb_dev->descriptor.bNumConfigurations = 0; -  out_unauthorized:  	usb_unlock_device(usb_dev);  	return 0; @@ -2458,17 +2537,7 @@ int usb_authorize_device(struct usb_device *usb_dev)  		goto error_device_descriptor;  	} -	kfree(usb_dev->product); -	usb_dev->product = NULL; -	kfree(usb_dev->manufacturer); -	usb_dev->manufacturer = NULL; -	kfree(usb_dev->serial); -	usb_dev->serial = NULL; -  	usb_dev->authorized = 1; -	result = usb_enumerate_device(usb_dev); -	if (result < 0) -		goto error_enumerate;  	/* Choose and set the configuration.  This registers the interfaces  	 * with the driver core and lets interface drivers bind to them.  	 */ @@ -2484,12 +2553,11 @@ int usb_authorize_device(struct usb_device *usb_dev)  	}  	dev_info(&usb_dev->dev, "authorized to connect\n"); -error_enumerate:  error_device_descriptor:  	usb_autosuspend_device(usb_dev);  error_autoresume:  out_authorized: -	usb_unlock_device(usb_dev);	// complements locktree +	usb_unlock_device(usb_dev);	/* complements locktree */  	return result;  } @@ -2517,10 +2585,25 @@ static unsigned hub_is_wusb(struct usb_hub *hub)  #define HUB_LONG_RESET_TIME	200  #define HUB_RESET_TIMEOUT	800 +/* + * "New scheme" enumeration causes an extra state transition to be + * exposed to an xhci host and causes USB3 devices to receive control + * commands in the default state.  This has been seen to cause + * enumeration failures, so disable this enumeration scheme for USB3 + * devices. + */ +static bool use_new_scheme(struct usb_device *udev, int retry) +{ +	if (udev->speed == USB_SPEED_SUPER) +		return false; + +	return USE_NEW_SCHEME(retry); +} +  static int hub_port_reset(struct usb_hub *hub, int port1,  			struct usb_device *udev, unsigned int delay, bool warm); -/* Is a USB 3.0 port in the Inactive or Complinance Mode state? +/* Is a USB 3.0 port in the Inactive or Compliance Mode state?   * Port worm reset is required to recover   */  static bool hub_port_warm_reset_required(struct usb_hub *hub, u16 portstatus) @@ -2558,9 +2641,9 @@ static int hub_port_wait_reset(struct usb_hub *hub, int port1,  		if (delay_time >= 2 * HUB_SHORT_RESET_TIME)  			delay = HUB_LONG_RESET_TIME; -		dev_dbg (hub->intfdev, -			"port %d not %sreset yet, waiting %dms\n", -			port1, warm ? "warm " : "", delay); +		dev_dbg(&hub->ports[port1 - 1]->dev, +				"not %sreset yet, waiting %dms\n", +				warm ? "warm " : "", delay);  	}  	if ((portstatus & USB_PORT_STAT_RESET)) @@ -2644,6 +2727,7 @@ static int hub_port_reset(struct usb_hub *hub, int port1,  {  	int i, status;  	u16 portchange, portstatus; +	struct usb_port *port_dev = hub->ports[port1 - 1];  	if (!hub_is_superspeed(hub->hdev)) {  		if (warm) { @@ -2677,9 +2761,9 @@ static int hub_port_reset(struct usb_hub *hub, int port1,  		if (status == -ENODEV) {  			;	/* The hub is gone */  		} else if (status) { -			dev_err(hub->intfdev, -					"cannot %sreset port %d (err = %d)\n", -					warm ? "warm " : "", port1, status); +			dev_err(&port_dev->dev, +					"cannot %sreset (err = %d)\n", +					warm ? "warm " : "", status);  		} else {  			status = hub_port_wait_reset(hub, port1, udev, delay,  								warm); @@ -2712,21 +2796,19 @@ static int hub_port_reset(struct usb_hub *hub, int port1,  			 * hot or warm reset failed.  Try another warm reset.  			 */  			if (!warm) { -				dev_dbg(hub->intfdev, "hot reset failed, warm reset port %d\n", -						port1); +				dev_dbg(&port_dev->dev, +						"hot reset failed, warm reset\n");  				warm = true;  			}  		} -		dev_dbg (hub->intfdev, -			"port %d not enabled, trying %sreset again...\n", -			port1, warm ? "warm " : ""); +		dev_dbg(&port_dev->dev, +				"not enabled, trying %sreset again...\n", +				warm ? "warm " : "");  		delay = HUB_LONG_RESET_TIME;  	} -	dev_err (hub->intfdev, -		"Cannot enable port %i.  Maybe the USB cable is bad?\n", -		port1); +	dev_err(&port_dev->dev, "Cannot enable. Maybe the USB cable is bad?\n");  done:  	if (!hub_is_superspeed(hub->hdev)) @@ -2751,6 +2833,20 @@ static int port_is_power_on(struct usb_hub *hub, unsigned portstatus)  	return ret;  } +static void usb_lock_port(struct usb_port *port_dev) +		__acquires(&port_dev->status_lock) +{ +	mutex_lock(&port_dev->status_lock); +	__acquire(&port_dev->status_lock); +} + +static void usb_unlock_port(struct usb_port *port_dev) +		__releases(&port_dev->status_lock) +{ +	mutex_unlock(&port_dev->status_lock); +	__release(&port_dev->status_lock); +} +  #ifdef	CONFIG_PM  /* Check if a port is suspended(USB2.0 port) or in U3 state(USB3.0 port) */ @@ -2777,6 +2873,8 @@ static int check_port_resume_type(struct usb_device *udev,  		struct usb_hub *hub, int port1,  		int status, unsigned portchange, unsigned portstatus)  { +	struct usb_port *port_dev = hub->ports[port1 - 1]; +  	/* Is the device still present? */  	if (status || port_is_suspended(hub, portstatus) ||  			!port_is_power_on(hub, portstatus) || @@ -2796,9 +2894,8 @@ static int check_port_resume_type(struct usb_device *udev,  	}  	if (status) { -		dev_dbg(hub->intfdev, -				"port %d status %04x.%04x after resume, %d\n", -				port1, portchange, portstatus, status); +		dev_dbg(&port_dev->dev, "status %04x.%04x after resume, %d\n", +				portchange, portstatus, status);  	} else if (udev->reset_resume) {  		/* Late port handoff can set status-change bits */ @@ -2972,6 +3069,8 @@ int usb_port_suspend(struct usb_device *udev, pm_message_t msg)  	int		status;  	bool		really_suspend = true; +	usb_lock_port(port_dev); +  	/* enable remote wakeup when appropriate; this lets the device  	 * wake up the upstream hub (including maybe the root hub).  	 * @@ -3029,8 +3128,7 @@ int usb_port_suspend(struct usb_device *udev, pm_message_t msg)  		status = 0;  	}  	if (status) { -		dev_dbg(hub->intfdev, "can't suspend port %d, status %d\n", -				port1, status); +		dev_dbg(&port_dev->dev, "can't suspend, status %d\n", status);  		/* Try to enable USB3 LPM and LTM again */  		usb_unlocked_enable_lpm(udev); @@ -3061,12 +3159,13 @@ int usb_port_suspend(struct usb_device *udev, pm_message_t msg)  		usb_set_device_state(udev, USB_STATE_SUSPENDED);  	} -	if (status == 0 && !udev->do_remote_wakeup && udev->persist_enabled) { +	if (status == 0 && !udev->do_remote_wakeup && udev->persist_enabled +			&& test_and_clear_bit(port1, hub->child_usage_bits))  		pm_runtime_put_sync(&port_dev->dev); -		port_dev->did_runtime_put = true; -	}  	usb_mark_last_busy(hub->hdev); + +	usb_unlock_port(port_dev);  	return status;  } @@ -3104,12 +3203,22 @@ static int finish_port_resume(struct usb_device *udev)  	 * operation is carried out here, after the port has been  	 * resumed.  	 */ -	if (udev->reset_resume) +	if (udev->reset_resume) { +		/* +		 * If the device morphs or switches modes when it is reset, +		 * we don't want to perform a reset-resume.  We'll fail the +		 * resume, which will cause a logical disconnect, and then +		 * the device will be rediscovered. +		 */   retry_reset_resume: -		status = usb_reset_and_verify_device(udev); +		if (udev->quirks & USB_QUIRK_RESET) +			status = -ENODEV; +		else +			status = usb_reset_and_verify_device(udev); +	} - 	/* 10.5.4.5 says be sure devices in the tree are still there. - 	 * For now let's assume the device didn't go crazy on resume, +	/* 10.5.4.5 says be sure devices in the tree are still there. +	 * For now let's assume the device didn't go crazy on resume,  	 * and device drivers will know about any resume quirks.  	 */  	if (status == 0) { @@ -3196,9 +3305,8 @@ int usb_port_resume(struct usb_device *udev, pm_message_t msg)  	int		status;  	u16		portchange, portstatus; -	if (port_dev->did_runtime_put) { +	if (!test_and_set_bit(port1, hub->child_usage_bits)) {  		status = pm_runtime_get_sync(&port_dev->dev); -		port_dev->did_runtime_put = false;  		if (status < 0) {  			dev_dbg(&udev->dev, "can't resume usb port, status %d\n",  					status); @@ -3206,15 +3314,13 @@ int usb_port_resume(struct usb_device *udev, pm_message_t msg)  		}  	} +	usb_lock_port(port_dev); +  	/* Skip the initial Clear-Suspend step for a remote wakeup */  	status = hub_port_status(hub, port1, &portstatus, &portchange);  	if (status == 0 && !port_is_suspended(hub, portstatus))  		goto SuspendCleared; -	// dev_dbg(hub->intfdev, "resume port %d\n", port1); - -	set_bit(port1, hub->busy_bits); -  	/* see 7.1.7.7; affects power usage, but not budgeting */  	if (hub_is_superspeed(hub->hdev))  		status = hub_set_port_link_state(hub, port1, USB_SS_PORT_LS_U0); @@ -3222,8 +3328,7 @@ int usb_port_resume(struct usb_device *udev, pm_message_t msg)  		status = usb_clear_port_feature(hub->hdev,  				port1, USB_PORT_FEAT_SUSPEND);  	if (status) { -		dev_dbg(hub->intfdev, "can't resume port %d, status %d\n", -				port1, status); +		dev_dbg(&port_dev->dev, "can't resume, status %d\n", status);  	} else {  		/* drive resume for at least 20 msec */  		dev_dbg(&udev->dev, "usb %sresume\n", @@ -3254,8 +3359,6 @@ int usb_port_resume(struct usb_device *udev, pm_message_t msg)  		}  	} -	clear_bit(port1, hub->busy_bits); -  	status = check_port_resume_type(udev,  			hub, port1, status, portchange, portstatus);  	if (status == 0) @@ -3273,16 +3376,18 @@ int usb_port_resume(struct usb_device *udev, pm_message_t msg)  		usb_unlocked_enable_lpm(udev);  	} +	usb_unlock_port(port_dev); +  	return status;  }  #ifdef	CONFIG_PM_RUNTIME -/* caller has locked udev */  int usb_remote_wakeup(struct usb_device *udev)  {  	int	status = 0; +	usb_lock_device(udev);  	if (udev->state == USB_STATE_SUSPENDED) {  		dev_dbg(&udev->dev, "usb %sresume\n", "wakeup-");  		status = usb_autoresume_device(udev); @@ -3291,9 +3396,59 @@ int usb_remote_wakeup(struct usb_device *udev)  			usb_autosuspend_device(udev);  		}  	} +	usb_unlock_device(udev);  	return status;  } +/* Returns 1 if there was a remote wakeup and a connect status change. */ +static int hub_handle_remote_wakeup(struct usb_hub *hub, unsigned int port, +		u16 portstatus, u16 portchange) +		__must_hold(&port_dev->status_lock) +{ +	struct usb_port *port_dev = hub->ports[port - 1]; +	struct usb_device *hdev; +	struct usb_device *udev; +	int connect_change = 0; +	int ret; + +	hdev = hub->hdev; +	udev = port_dev->child; +	if (!hub_is_superspeed(hdev)) { +		if (!(portchange & USB_PORT_STAT_C_SUSPEND)) +			return 0; +		usb_clear_port_feature(hdev, port, USB_PORT_FEAT_C_SUSPEND); +	} else { +		if (!udev || udev->state != USB_STATE_SUSPENDED || +				 (portstatus & USB_PORT_STAT_LINK_STATE) != +				 USB_SS_PORT_LS_U0) +			return 0; +	} + +	if (udev) { +		/* TRSMRCY = 10 msec */ +		msleep(10); + +		usb_unlock_port(port_dev); +		ret = usb_remote_wakeup(udev); +		usb_lock_port(port_dev); +		if (ret < 0) +			connect_change = 1; +	} else { +		ret = -ENODEV; +		hub_port_disable(hub, port, 1); +	} +	dev_dbg(&port_dev->dev, "resume, status %d\n", ret); +	return connect_change; +} + +#else + +static int hub_handle_remote_wakeup(struct usb_hub *hub, unsigned int port, +		u16 portstatus, u16 portchange) +{ +	return 0; +} +  #endif  static int check_ports_changed(struct usb_hub *hub) @@ -3324,11 +3479,12 @@ static int hub_suspend(struct usb_interface *intf, pm_message_t msg)  	 */  	hub->wakeup_enabled_descendants = 0;  	for (port1 = 1; port1 <= hdev->maxchild; port1++) { -		struct usb_device	*udev; +		struct usb_port *port_dev = hub->ports[port1 - 1]; +		struct usb_device *udev = port_dev->child; -		udev = hub->ports[port1 - 1]->child;  		if (udev && udev->can_submit) { -			dev_warn(&intf->dev, "port %d nyet suspended\n", port1); +			dev_warn(&port_dev->dev, "device %s not suspended yet\n", +					dev_name(&udev->dev));  			if (PMSG_IS_AUTO(msg))  				return -EBUSY;  		} @@ -3426,6 +3582,9 @@ static int usb_req_set_sel(struct usb_device *udev, enum usb3_link_state state)  	unsigned long long u2_pel;  	int ret; +	if (udev->state != USB_STATE_CONFIGURED) +		return 0; +  	/* Convert SEL and PEL stored in ns to us */  	u1_sel = DIV_ROUND_UP(udev->u1_params.sel, 1000);  	u1_pel = DIV_ROUND_UP(udev->u1_params.pel, 1000); @@ -3844,6 +4003,12 @@ EXPORT_SYMBOL_GPL(usb_disable_ltm);  void usb_enable_ltm(struct usb_device *udev) { }  EXPORT_SYMBOL_GPL(usb_enable_ltm); +static int hub_handle_remote_wakeup(struct usb_hub *hub, unsigned int port, +		u16 portstatus, u16 portchange) +{ +	return 0; +} +  #endif	/* CONFIG_PM */ @@ -3852,7 +4017,7 @@ EXPORT_SYMBOL_GPL(usb_enable_ltm);   * Between connect detection and reset signaling there must be a delay   * of 100ms at least for debounce and power-settling.  The corresponding   * timer shall restart whenever the downstream port detects a disconnect. - *  + *   * Apparently there are some bluetooth and irda-dongles and a number of   * low-speed devices for which this debounce period may last over a second.   * Not covered by the spec - but easy to deal with. @@ -3865,9 +4030,10 @@ EXPORT_SYMBOL_GPL(usb_enable_ltm);  int hub_port_debounce(struct usb_hub *hub, int port1, bool must_be_connected)  {  	int ret; -	int total_time, stable_time = 0;  	u16 portchange, portstatus;  	unsigned connection = 0xffff; +	int total_time, stable_time = 0; +	struct usb_port *port_dev = hub->ports[port1 - 1];  	for (total_time = 0; ; total_time += HUB_DEBOUNCE_STEP) {  		ret = hub_port_status(hub, port1, &portstatus, &portchange); @@ -3896,9 +4062,8 @@ int hub_port_debounce(struct usb_hub *hub, int port1, bool must_be_connected)  		msleep(HUB_DEBOUNCE_STEP);  	} -	dev_dbg (hub->intfdev, -		"debounce: port %d: total %dms stable %dms status 0x%x\n", -		port1, total_time, stable_time, portstatus); +	dev_dbg(&port_dev->dev, "debounce total %dms stable %dms status 0x%x\n", +			total_time, stable_time, portstatus);  	if (stable_time < HUB_DEBOUNCE_STABLE)  		return -ETIMEDOUT; @@ -3946,21 +4111,61 @@ static int hub_set_address(struct usb_device *udev, int devnum)  	return retval;  } +/* + * There are reports of USB 3.0 devices that say they support USB 2.0 Link PM + * when they're plugged into a USB 2.0 port, but they don't work when LPM is + * enabled. + * + * Only enable USB 2.0 Link PM if the port is internal (hardwired), or the + * device says it supports the new USB 2.0 Link PM errata by setting the BESL + * support bit in the BOS descriptor. + */ +static void hub_set_initial_usb2_lpm_policy(struct usb_device *udev) +{ +	struct usb_hub *hub = usb_hub_to_struct_hub(udev->parent); +	int connect_type = USB_PORT_CONNECT_TYPE_UNKNOWN; + +	if (!udev->usb2_hw_lpm_capable) +		return; + +	if (hub) +		connect_type = hub->ports[udev->portnum - 1]->connect_type; + +	if ((udev->bos->ext_cap->bmAttributes & cpu_to_le32(USB_BESL_SUPPORT)) || +			connect_type == USB_PORT_CONNECT_TYPE_HARD_WIRED) { +		udev->usb2_hw_lpm_allowed = 1; +		usb_set_usb2_hardware_lpm(udev, 1); +	} +} + +static int hub_enable_device(struct usb_device *udev) +{ +	struct usb_hcd *hcd = bus_to_hcd(udev->bus); + +	if (!hcd->driver->enable_device) +		return 0; +	if (udev->state == USB_STATE_ADDRESS) +		return 0; +	if (udev->state != USB_STATE_DEFAULT) +		return -EINVAL; + +	return hcd->driver->enable_device(hcd, udev); +} +  /* Reset device, (re)assign address, get device descriptor.   * Device connection must be stable, no more debouncing needed.   * Returns device in USB_STATE_ADDRESS, except on error.   *   * If this is called for an already-existing device (as part of - * usb_reset_and_verify_device), the caller must own the device lock.  For a - * newly detected device that is not accessible through any global - * pointers, it's not necessary to lock the device. + * usb_reset_and_verify_device), the caller must own the device lock and + * the port lock.  For a newly detected device that is not accessible + * through any global pointers, it's not necessary to lock the device, + * but it is still necessary to lock the port.   */  static int  hub_port_init (struct usb_hub *hub, struct usb_device *udev, int port1,  		int retry_counter)  { -	static DEFINE_MUTEX(usb_address0_mutex); -  	struct usb_device	*hdev = hub->hdev;  	struct usb_hcd		*hcd = bus_to_hcd(hdev->bus);  	int			i, j, retval; @@ -3983,7 +4188,7 @@ hub_port_init (struct usb_hub *hub, struct usb_device *udev, int port1,  	if (oldspeed == USB_SPEED_LOW)  		delay = HUB_LONG_RESET_TIME; -	mutex_lock(&usb_address0_mutex); +	mutex_lock(&hdev->bus->usb_address0_mutex);  	/* Reset the device; full speed may morph to high speed */  	/* FIXME a USB 2.0 device may morph into SuperSpeed on reset. */ @@ -4052,13 +4257,13 @@ hub_port_init (struct usb_hub *hub, struct usb_device *udev, int port1,  		udev->tt = &hub->tt;  		udev->ttport = port1;  	} -  +  	/* Why interleave GET_DESCRIPTOR and SET_ADDRESS this way?  	 * Because device hardware and firmware is sometimes buggy in  	 * this area, and this is how Linux has done it for ages.  	 * Change it cautiously.  	 * -	 * NOTE:  If USE_NEW_SCHEME() is true we will start by issuing +	 * NOTE:  If use_new_scheme() is true we will start by issuing  	 * a 64-byte GET_DESCRIPTOR request.  This is what Windows does,  	 * so it may help with some non-standards-compliant devices.  	 * Otherwise we start with SET_ADDRESS and then try to read the @@ -4066,10 +4271,21 @@ hub_port_init (struct usb_hub *hub, struct usb_device *udev, int port1,  	 * value.  	 */  	for (i = 0; i < GET_DESCRIPTOR_TRIES; (++i, msleep(100))) { -		if (USE_NEW_SCHEME(retry_counter) && !(hcd->driver->flags & HCD_USB3)) { +		bool did_new_scheme = false; + +		if (use_new_scheme(udev, retry_counter)) {  			struct usb_device_descriptor *buf;  			int r = 0; +			did_new_scheme = true; +			retval = hub_enable_device(udev); +			if (retval < 0) { +				dev_err(&udev->dev, +					"hub failed to enable device, error %d\n", +					retval); +				goto fail; +			} +  #define GET_DESCRIPTOR_BUFSIZE	64  			buf = kmalloc(GET_DESCRIPTOR_BUFSIZE, GFP_NOIO);  			if (!buf) { @@ -4127,11 +4343,11 @@ hub_port_init (struct usb_hub *hub, struct usb_device *udev, int port1,  #undef GET_DESCRIPTOR_BUFSIZE  		} - 		/* - 		 * If device is WUSB, we already assigned an - 		 * unauthorized address in the Connect Ack sequence; - 		 * authorization will assign the final address. - 		 */ +		/* +		 * If device is WUSB, we already assigned an +		 * unauthorized address in the Connect Ack sequence; +		 * authorization will assign the final address. +		 */  		if (udev->wusb == 0) {  			for (j = 0; j < SET_ADDRESS_TRIES; ++j) {  				retval = hub_set_address(udev, devnum); @@ -4158,9 +4374,13 @@ hub_port_init (struct usb_hub *hub, struct usb_device *udev, int port1,  			 *  - read ep0 maxpacket even for high and low speed,  			 */  			msleep(10); -			if (USE_NEW_SCHEME(retry_counter) && !(hcd->driver->flags & HCD_USB3)) +			/* use_new_scheme() checks the speed which may have +			 * changed since the initial look so we cache the result +			 * in did_new_scheme +			 */ +			if (did_new_scheme)  				break; -  		} +		}  		retval = usb_get_device_descriptor(udev, 8);  		if (retval < 8) { @@ -4216,7 +4436,7 @@ hub_port_init (struct usb_hub *hub, struct usb_device *udev, int port1,  		udev->ep0.desc.wMaxPacketSize = cpu_to_le16(i);  		usb_ep0_reinit(udev);  	} -   +  	retval = usb_get_device_descriptor(udev, USB_DT_DEVICE_SIZE);  	if (retval < (signed)sizeof(udev->descriptor)) {  		if (retval != -ENODEV) @@ -4239,12 +4459,13 @@ hub_port_init (struct usb_hub *hub, struct usb_device *udev, int port1,  	/* notify HCD that we have a device connected and addressed */  	if (hcd->driver->update_device)  		hcd->driver->update_device(hcd, udev); +	hub_set_initial_usb2_lpm_policy(udev);  fail:  	if (retval) {  		hub_port_disable(hub, port1, 0);  		update_devnum(udev, devnum);	/* for disconnect processing */  	} -	mutex_unlock(&usb_address0_mutex); +	mutex_unlock(&hdev->bus->usb_address0_mutex);  	return retval;  } @@ -4266,7 +4487,8 @@ check_highspeed (struct usb_hub *hub, struct usb_device *udev, int port1)  		/* hub LEDs are probably harder to miss than syslog */  		if (hub->has_indicators) {  			hub->indicator[port1-1] = INDICATOR_GREEN_BLINK; -			schedule_delayed_work (&hub->leds, 0); +			queue_delayed_work(system_power_efficient_wq, +					&hub->leds, 0);  		}  	}  	kfree(qual); @@ -4284,9 +4506,10 @@ hub_power_remaining (struct usb_hub *hub)  	remaining = hdev->bus_mA - hub->descriptor->bHubContrCurrent;  	for (port1 = 1; port1 <= hdev->maxchild; ++port1) { -		struct usb_device	*udev = hub->ports[port1 - 1]->child; -		int			delta; -		unsigned		unit_load; +		struct usb_port *port_dev = hub->ports[port1 - 1]; +		struct usb_device *udev = port_dev->child; +		unsigned unit_load; +		int delta;  		if (!udev)  			continue; @@ -4306,91 +4529,35 @@ hub_power_remaining (struct usb_hub *hub)  		else  			delta = 8;  		if (delta > hub->mA_per_port) -			dev_warn(&udev->dev, -				 "%dmA is over %umA budget for port %d!\n", -				 delta, hub->mA_per_port, port1); +			dev_warn(&port_dev->dev, "%dmA is over %umA budget!\n", +					delta, hub->mA_per_port);  		remaining -= delta;  	}  	if (remaining < 0) {  		dev_warn(hub->intfdev, "%dmA over power budget!\n", -			- remaining); +			-remaining);  		remaining = 0;  	}  	return remaining;  } -/* Handle physical or logical connection change events. - * This routine is called when: - * 	a port connection-change occurs; - *	a port enable-change occurs (often caused by EMI); - *	usb_reset_and_verify_device() encounters changed descriptors (as from - *		a firmware download) - * caller already locked the hub - */ -static void hub_port_connect_change(struct usb_hub *hub, int port1, -					u16 portstatus, u16 portchange) +static void hub_port_connect(struct usb_hub *hub, int port1, u16 portstatus, +		u16 portchange)  { -	struct usb_device *hdev = hub->hdev; -	struct device *hub_dev = hub->intfdev; -	struct usb_hcd *hcd = bus_to_hcd(hdev->bus); -	unsigned wHubCharacteristics = -			le16_to_cpu(hub->descriptor->wHubCharacteristics); -	struct usb_device *udev;  	int status, i;  	unsigned unit_load; - -	dev_dbg (hub_dev, -		"port %d, status %04x, change %04x, %s\n", -		port1, portstatus, portchange, portspeed(hub, portstatus)); - -	if (hub->has_indicators) { -		set_port_led(hub, port1, HUB_LED_AUTO); -		hub->indicator[port1-1] = INDICATOR_AUTO; -	} - -#ifdef	CONFIG_USB_OTG -	/* during HNP, don't repeat the debounce */ -	if (hdev->bus->is_b_host) -		portchange &= ~(USB_PORT_STAT_C_CONNECTION | -				USB_PORT_STAT_C_ENABLE); -#endif - -	/* Try to resuscitate an existing device */ -	udev = hub->ports[port1 - 1]->child; -	if ((portstatus & USB_PORT_STAT_CONNECTION) && udev && -			udev->state != USB_STATE_NOTATTACHED) { -		usb_lock_device(udev); -		if (portstatus & USB_PORT_STAT_ENABLE) { -			status = 0;		/* Nothing to do */ - -#ifdef CONFIG_PM_RUNTIME -		} else if (udev->state == USB_STATE_SUSPENDED && -				udev->persist_enabled) { -			/* For a suspended device, treat this as a -			 * remote wakeup event. -			 */ -			status = usb_remote_wakeup(udev); -#endif - -		} else { -			status = -ENODEV;	/* Don't resuscitate */ -		} -		usb_unlock_device(udev); - -		if (status == 0) { -			clear_bit(port1, hub->change_bits); -			return; -		} -	} +	struct usb_device *hdev = hub->hdev; +	struct usb_hcd *hcd = bus_to_hcd(hdev->bus); +	struct usb_port *port_dev = hub->ports[port1 - 1]; +	struct usb_device *udev = port_dev->child;  	/* Disconnect any existing devices under this port */  	if (udev) {  		if (hcd->phy && !hdev->parent &&  				!(portstatus & USB_PORT_STAT_CONNECTION))  			usb_phy_notify_disconnect(hcd->phy, udev->speed); -		usb_disconnect(&hub->ports[port1 - 1]->child); +		usb_disconnect(&port_dev->child);  	} -	clear_bit(port1, hub->change_bits);  	/* We can forget about a "removed" device when there's a physical  	 * disconnect or the connect status changes. @@ -4404,8 +4571,8 @@ static void hub_port_connect_change(struct usb_hub *hub, int port1,  		status = hub_port_debounce_be_stable(hub, port1);  		if (status < 0) {  			if (status != -ENODEV && printk_ratelimit()) -				dev_err(hub_dev, "connect-debounce failed, " -						"port %d disabled\n", port1); +				dev_err(&port_dev->dev, +						"connect-debounce failed\n");  			portstatus &= ~USB_PORT_STAT_CONNECTION;  		} else {  			portstatus = status; @@ -4419,12 +4586,12 @@ static void hub_port_connect_change(struct usb_hub *hub, int port1,  			test_bit(port1, hub->removed_bits)) {  		/* maybe switch power back on (e.g. root hub was reset) */ -		if ((wHubCharacteristics & HUB_CHAR_LPSM) < 2 +		if (hub_is_port_power_switchable(hub)  				&& !port_is_power_on(hub, portstatus))  			set_port_feature(hdev, port1, USB_PORT_FEAT_POWER);  		if (portstatus & USB_PORT_STAT_ENABLE) -  			goto done; +			goto done;  		return;  	}  	if (hub_is_superspeed(hub->hdev)) @@ -4440,14 +4607,13 @@ static void hub_port_connect_change(struct usb_hub *hub, int port1,  		 */  		udev = usb_alloc_dev(hdev, hdev->bus, port1);  		if (!udev) { -			dev_err (hub_dev, -				"couldn't allocate port %d usb_device\n", -				port1); +			dev_err(&port_dev->dev, +					"couldn't allocate usb_device\n");  			goto done;  		}  		usb_set_device_state(udev, USB_STATE_POWERED); - 		udev->bus_mA = hub->mA_per_port; +		udev->bus_mA = hub->mA_per_port;  		udev->level = hdev->level + 1;  		udev->wusb = hub_is_wusb(hub); @@ -4464,7 +4630,9 @@ static void hub_port_connect_change(struct usb_hub *hub, int port1,  		}  		/* reset (non-USB 3.0 devices) and get descriptor */ +		usb_lock_port(port_dev);  		status = hub_port_init(hub, udev, port1, i); +		usb_unlock_port(port_dev);  		if (status < 0)  			goto loop; @@ -4495,13 +4663,15 @@ static void hub_port_connect_change(struct usb_hub *hub, int port1,  				if (hub->has_indicators) {  					hub->indicator[port1-1] =  						INDICATOR_AMBER_BLINK; -					schedule_delayed_work (&hub->leds, 0); +					queue_delayed_work( +						system_power_efficient_wq, +						&hub->leds, 0);  				}  				status = -ENOTCONN;	/* Don't retry */  				goto loop_disable;  			}  		} -  +  		/* check for devices running slower than they could */  		if (le16_to_cpu(udev->descriptor.bcdUSB) >= 0x0200  				&& udev->speed == USB_SPEED_FULL @@ -4514,6 +4684,8 @@ static void hub_port_connect_change(struct usb_hub *hub, int port1,  		 */  		status = 0; +		mutex_lock(&usb_port_peer_mutex); +  		/* We mustn't add new devices if the parent hub has  		 * been disconnected; we would race with the  		 * recursively_mark_NOTATTACHED() routine. @@ -4522,16 +4694,19 @@ static void hub_port_connect_change(struct usb_hub *hub, int port1,  		if (hdev->state == USB_STATE_NOTATTACHED)  			status = -ENOTCONN;  		else -			hub->ports[port1 - 1]->child = udev; +			port_dev->child = udev;  		spin_unlock_irq(&device_state_lock); +		mutex_unlock(&usb_port_peer_mutex);  		/* Run it through the hoops (find a driver, etc) */  		if (!status) {  			status = usb_new_device(udev);  			if (status) { +				mutex_lock(&usb_port_peer_mutex);  				spin_lock_irq(&device_state_lock); -				hub->ports[port1 - 1]->child = NULL; +				port_dev->child = NULL;  				spin_unlock_irq(&device_state_lock); +				mutex_unlock(&usb_port_peer_mutex);  			}  		} @@ -4540,7 +4715,7 @@ static void hub_port_connect_change(struct usb_hub *hub, int port1,  		status = hub_power_remaining(hub);  		if (status) -			dev_dbg(hub_dev, "%dmA power budget left\n", status); +			dev_dbg(hub->intfdev, "%dmA power budget left\n", status);  		return; @@ -4558,56 +4733,200 @@ loop:  			!hcd->driver->port_handed_over ||  			!(hcd->driver->port_handed_over)(hcd, port1)) {  		if (status != -ENOTCONN && status != -ENODEV) -			dev_err(hub_dev, "unable to enumerate USB device on port %d\n", -					port1); +			dev_err(&port_dev->dev, +					"unable to enumerate USB device\n");  	} -  +  done:  	hub_port_disable(hub, port1, 1);  	if (hcd->driver->relinquish_port && !hub->hdev->parent)  		hcd->driver->relinquish_port(hcd, port1); +  } -/* Returns 1 if there was a remote wakeup and a connect status change. */ -static int hub_handle_remote_wakeup(struct usb_hub *hub, unsigned int port, -		u16 portstatus, u16 portchange) +/* Handle physical or logical connection change events. + * This routine is called when: + *	a port connection-change occurs; + *	a port enable-change occurs (often caused by EMI); + *	usb_reset_and_verify_device() encounters changed descriptors (as from + *		a firmware download) + * caller already locked the hub + */ +static void hub_port_connect_change(struct usb_hub *hub, int port1, +					u16 portstatus, u16 portchange) +		__must_hold(&port_dev->status_lock)  { -	struct usb_device *hdev; -	struct usb_device *udev; -	int connect_change = 0; -	int ret; +	struct usb_port *port_dev = hub->ports[port1 - 1]; +	struct usb_device *udev = port_dev->child; +	int status = -ENODEV; -	hdev = hub->hdev; -	udev = hub->ports[port - 1]->child; -	if (!hub_is_superspeed(hdev)) { -		if (!(portchange & USB_PORT_STAT_C_SUSPEND)) -			return 0; -		usb_clear_port_feature(hdev, port, USB_PORT_FEAT_C_SUSPEND); -	} else { -		if (!udev || udev->state != USB_STATE_SUSPENDED || -				 (portstatus & USB_PORT_STAT_LINK_STATE) != -				 USB_SS_PORT_LS_U0) -			return 0; +	dev_dbg(&port_dev->dev, "status %04x, change %04x, %s\n", portstatus, +			portchange, portspeed(hub, portstatus)); + +	if (hub->has_indicators) { +		set_port_led(hub, port1, HUB_LED_AUTO); +		hub->indicator[port1-1] = INDICATOR_AUTO;  	} -	if (udev) { -		/* TRSMRCY = 10 msec */ -		msleep(10); +#ifdef	CONFIG_USB_OTG +	/* during HNP, don't repeat the debounce */ +	if (hub->hdev->bus->is_b_host) +		portchange &= ~(USB_PORT_STAT_C_CONNECTION | +				USB_PORT_STAT_C_ENABLE); +#endif + +	/* Try to resuscitate an existing device */ +	if ((portstatus & USB_PORT_STAT_CONNECTION) && udev && +			udev->state != USB_STATE_NOTATTACHED) { +		if (portstatus & USB_PORT_STAT_ENABLE) { +			status = 0;		/* Nothing to do */ +#ifdef CONFIG_PM_RUNTIME +		} else if (udev->state == USB_STATE_SUSPENDED && +				udev->persist_enabled) { +			/* For a suspended device, treat this as a +			 * remote wakeup event. +			 */ +			usb_unlock_port(port_dev); +			status = usb_remote_wakeup(udev); +			usb_lock_port(port_dev); +#endif +		} else { +			/* Don't resuscitate */; +		} +	} +	clear_bit(port1, hub->change_bits); + +	/* successfully revalidated the connection */ +	if (status == 0) +		return; + +	usb_unlock_port(port_dev); +	hub_port_connect(hub, port1, portstatus, portchange); +	usb_lock_port(port_dev); +} + +static void port_event(struct usb_hub *hub, int port1) +		__must_hold(&port_dev->status_lock) +{ +	int connect_change, reset_device = 0; +	struct usb_port *port_dev = hub->ports[port1 - 1]; +	struct usb_device *udev = port_dev->child; +	struct usb_device *hdev = hub->hdev; +	u16 portstatus, portchange; + +	connect_change = test_bit(port1, hub->change_bits); +	clear_bit(port1, hub->event_bits); +	clear_bit(port1, hub->wakeup_bits); + +	if (hub_port_status(hub, port1, &portstatus, &portchange) < 0) +		return; + +	if (portchange & USB_PORT_STAT_C_CONNECTION) { +		usb_clear_port_feature(hdev, port1, USB_PORT_FEAT_C_CONNECTION); +		connect_change = 1; +	} + +	if (portchange & USB_PORT_STAT_C_ENABLE) { +		if (!connect_change) +			dev_dbg(&port_dev->dev, "enable change, status %08x\n", +					portstatus); +		usb_clear_port_feature(hdev, port1, USB_PORT_FEAT_C_ENABLE); + +		/* +		 * EM interference sometimes causes badly shielded USB devices +		 * to be shutdown by the hub, this hack enables them again. +		 * Works at least with mouse driver. +		 */ +		if (!(portstatus & USB_PORT_STAT_ENABLE) +		    && !connect_change && udev) { +			dev_err(&port_dev->dev, "disabled by hub (EMI?), re-enabling...\n"); +			connect_change = 1; +		} +	} +	if (portchange & USB_PORT_STAT_C_OVERCURRENT) { +		u16 status = 0, unused; + +		dev_dbg(&port_dev->dev, "over-current change\n"); +		usb_clear_port_feature(hdev, port1, +				USB_PORT_FEAT_C_OVER_CURRENT); +		msleep(100);	/* Cool down */ +		hub_power_on(hub, true); +		hub_port_status(hub, port1, &status, &unused); +		if (status & USB_PORT_STAT_OVERCURRENT) +			dev_err(&port_dev->dev, "over-current condition\n"); +	} + +	if (portchange & USB_PORT_STAT_C_RESET) { +		dev_dbg(&port_dev->dev, "reset change\n"); +		usb_clear_port_feature(hdev, port1, USB_PORT_FEAT_C_RESET); +	} +	if ((portchange & USB_PORT_STAT_C_BH_RESET) +	    && hub_is_superspeed(hdev)) { +		dev_dbg(&port_dev->dev, "warm reset change\n"); +		usb_clear_port_feature(hdev, port1, +				USB_PORT_FEAT_C_BH_PORT_RESET); +	} +	if (portchange & USB_PORT_STAT_C_LINK_STATE) { +		dev_dbg(&port_dev->dev, "link state change\n"); +		usb_clear_port_feature(hdev, port1, +				USB_PORT_FEAT_C_PORT_LINK_STATE); +	} +	if (portchange & USB_PORT_STAT_C_CONFIG_ERROR) { +		dev_warn(&port_dev->dev, "config error\n"); +		usb_clear_port_feature(hdev, port1, +				USB_PORT_FEAT_C_PORT_CONFIG_ERROR); +	} + +	/* skip port actions that require the port to be powered on */ +	if (!pm_runtime_active(&port_dev->dev)) +		return; + +	if (hub_handle_remote_wakeup(hub, port1, portstatus, portchange)) +		connect_change = 1; + +	/* +	 * Warm reset a USB3 protocol port if it's in +	 * SS.Inactive state. +	 */ +	if (hub_port_warm_reset_required(hub, portstatus)) { +		dev_dbg(&port_dev->dev, "do warm reset\n"); +		if (!udev || !(portstatus & USB_PORT_STAT_CONNECTION) +				|| udev->state == USB_STATE_NOTATTACHED) { +			if (hub_port_reset(hub, port1, NULL, +					HUB_BH_RESET_TIME, true) < 0) +				hub_port_disable(hub, port1, 1); +		} else +			reset_device = 1; +	} + +	/* +	 * On disconnect USB3 protocol ports transit from U0 to +	 * SS.Inactive to Rx.Detect. If this happens a warm- +	 * reset is not needed, but a (re)connect may happen +	 * before khubd runs and sees the disconnect, and the +	 * device may be an unknown state. +	 * +	 * If the port went through SS.Inactive without khubd +	 * seeing it the C_LINK_STATE change flag will be set, +	 * and we reset the dev to put it in a known state. +	 */ +	if (reset_device || (udev && hub_is_superspeed(hub->hdev) +				&& (portchange & USB_PORT_STAT_C_LINK_STATE) +				&& (portstatus & USB_PORT_STAT_CONNECTION))) { +		usb_unlock_port(port_dev);  		usb_lock_device(udev); -		ret = usb_remote_wakeup(udev); +		usb_reset_device(udev);  		usb_unlock_device(udev); -		if (ret < 0) -			connect_change = 1; -	} else { -		ret = -ENODEV; -		hub_port_disable(hub, port, 1); +		usb_lock_port(port_dev); +		connect_change = 0;  	} -	dev_dbg(hub->intfdev, "resume on port %d, status %d\n", -			port, ret); -	return connect_change; + +	if (connect_change) +		hub_port_connect_change(hub, port1, portstatus, portchange);  } +  static void hub_events(void)  {  	struct list_head *tmp; @@ -4617,10 +4936,7 @@ static void hub_events(void)  	struct device *hub_dev;  	u16 hubstatus;  	u16 hubchange; -	u16 portstatus; -	u16 portchange;  	int i, ret; -	int connect_change, wakeup_change;  	/*  	 *  We restart the list every time to avoid a deadlock with @@ -4694,127 +5010,28 @@ static void hub_events(void)  		/* deal with port status changes */  		for (i = 1; i <= hdev->maxchild; i++) { -			if (test_bit(i, hub->busy_bits)) -				continue; -			connect_change = test_bit(i, hub->change_bits); -			wakeup_change = test_and_clear_bit(i, hub->wakeup_bits); -			if (!test_and_clear_bit(i, hub->event_bits) && -					!connect_change && !wakeup_change) -				continue; - -			ret = hub_port_status(hub, i, -					&portstatus, &portchange); -			if (ret < 0) -				continue; - -			if (portchange & USB_PORT_STAT_C_CONNECTION) { -				usb_clear_port_feature(hdev, i, -					USB_PORT_FEAT_C_CONNECTION); -				connect_change = 1; -			} - -			if (portchange & USB_PORT_STAT_C_ENABLE) { -				if (!connect_change) -					dev_dbg (hub_dev, -						"port %d enable change, " -						"status %08x\n", -						i, portstatus); -				usb_clear_port_feature(hdev, i, -					USB_PORT_FEAT_C_ENABLE); +			struct usb_port *port_dev = hub->ports[i - 1]; +			if (test_bit(i, hub->event_bits) +					|| test_bit(i, hub->change_bits) +					|| test_bit(i, hub->wakeup_bits)) {  				/* -				 * EM interference sometimes causes badly -				 * shielded USB devices to be shutdown by -				 * the hub, this hack enables them again. -				 * Works at least with mouse driver.  +				 * The get_noresume and barrier ensure that if +				 * the port was in the process of resuming, we +				 * flush that work and keep the port active for +				 * the duration of the port_event().  However, +				 * if the port is runtime pm suspended +				 * (powered-off), we leave it in that state, run +				 * an abbreviated port_event(), and move on.  				 */ -				if (!(portstatus & USB_PORT_STAT_ENABLE) -				    && !connect_change -				    && hub->ports[i - 1]->child) { -					dev_err (hub_dev, -					    "port %i " -					    "disabled by hub (EMI?), " -					    "re-enabling...\n", -						i); -					connect_change = 1; -				} +				pm_runtime_get_noresume(&port_dev->dev); +				pm_runtime_barrier(&port_dev->dev); +				usb_lock_port(port_dev); +				port_event(hub, i); +				usb_unlock_port(port_dev); +				pm_runtime_put_sync(&port_dev->dev);  			} - -			if (hub_handle_remote_wakeup(hub, i, -						portstatus, portchange)) -				connect_change = 1; - -			if (portchange & USB_PORT_STAT_C_OVERCURRENT) { -				u16 status = 0; -				u16 unused; - -				dev_dbg(hub_dev, "over-current change on port " -					"%d\n", i); -				usb_clear_port_feature(hdev, i, -					USB_PORT_FEAT_C_OVER_CURRENT); -				msleep(100);	/* Cool down */ -				hub_power_on(hub, true); -				hub_port_status(hub, i, &status, &unused); -				if (status & USB_PORT_STAT_OVERCURRENT) -					dev_err(hub_dev, "over-current " -						"condition on port %d\n", i); -			} - -			if (portchange & USB_PORT_STAT_C_RESET) { -				dev_dbg (hub_dev, -					"reset change on port %d\n", -					i); -				usb_clear_port_feature(hdev, i, -					USB_PORT_FEAT_C_RESET); -			} -			if ((portchange & USB_PORT_STAT_C_BH_RESET) && -					hub_is_superspeed(hub->hdev)) { -				dev_dbg(hub_dev, -					"warm reset change on port %d\n", -					i); -				usb_clear_port_feature(hdev, i, -					USB_PORT_FEAT_C_BH_PORT_RESET); -			} -			if (portchange & USB_PORT_STAT_C_LINK_STATE) { -				usb_clear_port_feature(hub->hdev, i, -						USB_PORT_FEAT_C_PORT_LINK_STATE); -			} -			if (portchange & USB_PORT_STAT_C_CONFIG_ERROR) { -				dev_warn(hub_dev, -					"config error on port %d\n", -					i); -				usb_clear_port_feature(hub->hdev, i, -						USB_PORT_FEAT_C_PORT_CONFIG_ERROR); -			} - -			/* Warm reset a USB3 protocol port if it's in -			 * SS.Inactive state. -			 */ -			if (hub_port_warm_reset_required(hub, portstatus)) { -				int status; -				struct usb_device *udev = -					hub->ports[i - 1]->child; - -				dev_dbg(hub_dev, "warm reset port %d\n", i); -				if (!udev || !(portstatus & -						USB_PORT_STAT_CONNECTION)) { -					status = hub_port_reset(hub, i, -							NULL, HUB_BH_RESET_TIME, -							true); -					if (status < 0) -						hub_port_disable(hub, i, 1); -				} else { -					usb_lock_device(udev); -					status = usb_reset_device(udev); -					usb_unlock_device(udev); -					connect_change = 0; -				} -			} - -			if (connect_change) -				hub_port_connect_change(hub, i, -						portstatus, portchange); -		} /* end for i */ +		}  		/* deal with hub status changes */  		if (test_and_clear_bit(0, hub->event_bits) == 0) @@ -4838,7 +5055,7 @@ static void hub_events(void)  				dev_dbg(hub_dev, "over-current change\n");  				clear_hub_feature(hdev, C_HUB_OVER_CURRENT);  				msleep(500);	/* Cool down */ -                        	hub_power_on(hub, true); +				hub_power_on(hub, true);  				hub_hub_status(hub, &status, &unused);  				if (status & HUB_STATUS_OVERCURRENT)  					dev_err(hub_dev, "over-current " @@ -4858,12 +5075,12 @@ static void hub_events(void)  		usb_unlock_device(hdev);  		kref_put(&hub->kref, hub_release); -        } /* end while (1) */ +	} /* end while (1) */  }  static int hub_thread(void *__unused)  { -	/* khubd needs to be freezable to avoid intefering with USB-PERSIST +	/* khubd needs to be freezable to avoid interfering with USB-PERSIST  	 * port handover.  Otherwise it might see that a full-speed device  	 * was gone before the EHCI controller had handed its port over to  	 * the companion full-speed controller. @@ -4883,7 +5100,7 @@ static int hub_thread(void *__unused)  static const struct usb_device_id hub_id_table[] = {      { .match_flags = USB_DEVICE_ID_MATCH_VENDOR -	           | USB_DEVICE_ID_MATCH_INT_CLASS, +			| USB_DEVICE_ID_MATCH_INT_CLASS,        .idVendor = USB_VENDOR_GENESYS_LOGIC,        .bInterfaceClass = USB_CLASS_HUB,        .driver_info = HUB_QUIRK_CHECK_PORT_AUTOSUSPEND}, @@ -5049,15 +5266,18 @@ static int descriptors_changed(struct usb_device *udev,   * if the reset wasn't even attempted.   *   * Note: - * The caller must own the device lock.  For example, it's safe to use - * this from a driver probe() routine after downloading new firmware. - * For calls that might not occur during probe(), drivers should lock - * the device using usb_lock_device_for_reset(). + * The caller must own the device lock and the port lock, the latter is + * taken by usb_reset_device().  For example, it's safe to use + * usb_reset_device() from a driver probe() routine after downloading + * new firmware.  For calls that might not occur during probe(), drivers + * should lock the device using usb_lock_device_for_reset().   *   * Locking exception: This routine may also be called from within an   * autoresume handler.  Such usage won't conflict with other tasks   * holding the device lock because these tasks should always call - * usb_autopm_resume_device(), thereby preventing any unwanted autoresume. + * usb_autopm_resume_device(), thereby preventing any unwanted + * autoresume.  The autoresume handler is expected to have already + * acquired the port lock before calling this routine.   */  static int usb_reset_and_verify_device(struct usb_device *udev)  { @@ -5066,7 +5286,7 @@ static int usb_reset_and_verify_device(struct usb_device *udev)  	struct usb_hcd			*hcd = bus_to_hcd(udev->bus);  	struct usb_device_descriptor	descriptor = udev->descriptor;  	struct usb_host_bos		*bos; -	int 				i, ret = 0; +	int				i, j, ret = 0;  	int				port1 = udev->portnum;  	if (udev->state == USB_STATE_NOTATTACHED || @@ -5076,13 +5296,17 @@ static int usb_reset_and_verify_device(struct usb_device *udev)  		return -EINVAL;  	} -	if (!parent_hdev) { -		/* this requires hcd-specific logic; see ohci_restart() */ -		dev_dbg(&udev->dev, "%s for root hub!\n", __func__); +	if (!parent_hdev)  		return -EISDIR; -	} +  	parent_hub = usb_hub_to_struct_hub(parent_hdev); +	/* Disable USB2 hardware LPM. +	 * It will be re-enabled by the enumeration process. +	 */ +	if (udev->usb2_hw_lpm_enabled == 1) +		usb_set_usb2_hardware_lpm(udev, 0); +  	bos = udev->bos;  	udev->bos = NULL; @@ -5103,7 +5327,6 @@ static int usb_reset_and_verify_device(struct usb_device *udev)  		goto re_enumerate;  	} -	set_bit(port1, parent_hub->busy_bits);  	for (i = 0; i < SET_CONFIG_TRIES; ++i) {  		/* ep0 maxpacket size may change; let the HCD know about it. @@ -5113,17 +5336,16 @@ static int usb_reset_and_verify_device(struct usb_device *udev)  		if (ret >= 0 || ret == -ENOTCONN || ret == -ENODEV)  			break;  	} -	clear_bit(port1, parent_hub->busy_bits);  	if (ret < 0)  		goto re_enumerate; -  +  	/* Device might have changed firmware (DFU or similar) */  	if (descriptors_changed(udev, &descriptor, bos)) {  		dev_info(&udev->dev, "device firmware changed\n");  		udev->descriptor = descriptor;	/* for disconnect() calls */  		goto re_enumerate; -  	} +	}  	/* Restore the device's previous configuration */  	if (!udev->actconfig) @@ -5148,7 +5370,7 @@ static int usb_reset_and_verify_device(struct usb_device *udev)  			udev->actconfig->desc.bConfigurationValue, ret);  		mutex_unlock(hcd->bandwidth_mutex);  		goto re_enumerate; -  	} +	}  	mutex_unlock(hcd->bandwidth_mutex);  	usb_set_device_state(udev, USB_STATE_CONFIGURED); @@ -5186,16 +5408,20 @@ static int usb_reset_and_verify_device(struct usb_device *udev)  				ret);  			goto re_enumerate;  		} +		/* Resetting also frees any allocated streams */ +		for (j = 0; j < intf->cur_altsetting->desc.bNumEndpoints; j++) +			intf->cur_altsetting->endpoint[j].streams = 0;  	}  done:  	/* Now that the alt settings are re-installed, enable LTM and LPM. */ +	usb_set_usb2_hardware_lpm(udev, 1);  	usb_unlocked_enable_lpm(udev);  	usb_enable_ltm(udev);  	usb_release_bos_descriptor(udev);  	udev->bos = bos;  	return 0; -  +  re_enumerate:  	/* LPM state doesn't matter when we're about to destroy the device. */  	hub_port_logical_disconnect(parent_hub, port1); @@ -5230,7 +5456,9 @@ int usb_reset_device(struct usb_device *udev)  	int ret;  	int i;  	unsigned int noio_flag; +	struct usb_port *port_dev;  	struct usb_host_config *config = udev->actconfig; +	struct usb_hub *hub = usb_hub_to_struct_hub(udev->parent);  	if (udev->state == USB_STATE_NOTATTACHED ||  			udev->state == USB_STATE_SUSPENDED) { @@ -5239,6 +5467,14 @@ int usb_reset_device(struct usb_device *udev)  		return -EINVAL;  	} +	if (!udev->parent) { +		/* this requires hcd-specific logic; see ohci_restart() */ +		dev_dbg(&udev->dev, "%s for root hub!\n", __func__); +		return -EISDIR; +	} + +	port_dev = hub->ports[udev->portnum - 1]; +  	/*  	 * Don't allocate memory with GFP_KERNEL in current  	 * context to avoid possible deadlock if usb mass @@ -5272,7 +5508,9 @@ int usb_reset_device(struct usb_device *udev)  		}  	} +	usb_lock_port(port_dev);  	ret = usb_reset_and_verify_device(udev); +	usb_unlock_port(port_dev);  	if (config) {  		for (i = config->desc.bNumInterfaces - 1; i >= 0; --i) { @@ -5287,10 +5525,11 @@ int usb_reset_device(struct usb_device *udev)  				else if (cintf->condition ==  						USB_INTERFACE_BOUND)  					rebind = 1; +				if (rebind) +					cintf->needs_binding = 1;  			} -			if (ret == 0 && rebind) -				usb_rebind_intf(cintf);  		} +		usb_unbind_and_rebind_marked_interfaces(udev);  	}  	usb_autosuspend_device(udev); @@ -5366,56 +5605,26 @@ struct usb_device *usb_hub_find_child(struct usb_device *hdev,  }  EXPORT_SYMBOL_GPL(usb_hub_find_child); -/** - * usb_set_hub_port_connect_type - set hub port connect type. - * @hdev: USB device belonging to the usb hub - * @port1: port num of the port - * @type: connect type of the port - */ -void usb_set_hub_port_connect_type(struct usb_device *hdev, int port1, -	enum usb_port_connect_type type) -{ -	struct usb_hub *hub = usb_hub_to_struct_hub(hdev); - -	if (hub) -		hub->ports[port1 - 1]->connect_type = type; -} - -/** - * usb_get_hub_port_connect_type - Get the port's connect type - * @hdev: USB device belonging to the usb hub - * @port1: port num of the port - * - * Return: The connect type of the port if successful. Or - * USB_PORT_CONNECT_TYPE_UNKNOWN if input params are invalid. - */ -enum usb_port_connect_type -usb_get_hub_port_connect_type(struct usb_device *hdev, int port1) -{ -	struct usb_hub *hub = usb_hub_to_struct_hub(hdev); - -	if (!hub) -		return USB_PORT_CONNECT_TYPE_UNKNOWN; - -	return hub->ports[port1 - 1]->connect_type; -} -  void usb_hub_adjust_deviceremovable(struct usb_device *hdev,  		struct usb_hub_descriptor *desc)  { +	struct usb_hub *hub = usb_hub_to_struct_hub(hdev);  	enum usb_port_connect_type connect_type;  	int i; +	if (!hub) +		return; +  	if (!hub_is_superspeed(hdev)) {  		for (i = 1; i <= hdev->maxchild; i++) { -			connect_type = usb_get_hub_port_connect_type(hdev, i); +			struct usb_port *port_dev = hub->ports[i - 1]; +			connect_type = port_dev->connect_type;  			if (connect_type == USB_PORT_CONNECT_TYPE_HARD_WIRED) {  				u8 mask = 1 << (i%8);  				if (!(desc->u.hs.DeviceRemovable[i/8] & mask)) { -					dev_dbg(&hdev->dev, "usb port%d's DeviceRemovable is changed to 1 according to platform information.\n", -						i); +					dev_dbg(&port_dev->dev, "DeviceRemovable is changed to 1 according to platform information.\n");  					desc->u.hs.DeviceRemovable[i/8]	|= mask;  				}  			} @@ -5424,14 +5633,14 @@ void usb_hub_adjust_deviceremovable(struct usb_device *hdev,  		u16 port_removable = le16_to_cpu(desc->u.ss.DeviceRemovable);  		for (i = 1; i <= hdev->maxchild; i++) { -			connect_type = usb_get_hub_port_connect_type(hdev, i); +			struct usb_port *port_dev = hub->ports[i - 1]; +			connect_type = port_dev->connect_type;  			if (connect_type == USB_PORT_CONNECT_TYPE_HARD_WIRED) {  				u16 mask = 1 << i;  				if (!(port_removable & mask)) { -					dev_dbg(&hdev->dev, "usb port%d's DeviceRemovable is changed to 1 according to platform information.\n", -						i); +					dev_dbg(&port_dev->dev, "DeviceRemovable is changed to 1 according to platform information.\n");  					port_removable |= mask;  				}  			} @@ -5458,6 +5667,6 @@ acpi_handle usb_get_hub_port_acpi_handle(struct usb_device *hdev,  	if (!hub)  		return NULL; -	return DEVICE_ACPI_HANDLE(&hub->ports[port1 - 1]->dev); +	return ACPI_HANDLE(&hub->ports[port1 - 1]->dev);  }  #endif diff --git a/drivers/usb/core/hub.h b/drivers/usb/core/hub.h index 4e4790dea34..326308e5396 100644 --- a/drivers/usb/core/hub.h +++ b/drivers/usb/core/hub.h @@ -45,12 +45,13 @@ struct usb_hub {  	unsigned long		event_bits[1];	/* status change bitmask */  	unsigned long		change_bits[1];	/* ports with logical connect  							status change */ -	unsigned long		busy_bits[1];	/* ports being reset or -							resumed */  	unsigned long		removed_bits[1]; /* ports with a "removed"  							device present */  	unsigned long		wakeup_bits[1];	/* ports that have signaled  							remote wakeup */ +	unsigned long		power_bits[1]; /* ports that are powered */ +	unsigned long		child_usage_bits[1]; /* ports powered on for +							children */  #if USB_MAXCHILDREN > 31 /* 8*sizeof(unsigned long) - 1 */  #error event_bits[] is too short!  #endif @@ -66,6 +67,7 @@ struct usb_hub {  	unsigned		limited_power:1;  	unsigned		quiescing:1;  	unsigned		disconnected:1; +	unsigned		in_reset:1;  	unsigned		quirk_check_port_auto_suspend:1; @@ -78,22 +80,28 @@ struct usb_hub {  /**   * struct usb port - kernel's representation of a usb port - * @child: usb device attatched to the port + * @child: usb device attached to the port   * @dev: generic device interface   * @port_owner: port's owner + * @peer: related usb2 and usb3 ports (share the same connector) + * @req: default pm qos request for hubs without port power control   * @connect_type: port's connect type + * @location: opaque representation of platform connector location + * @status_lock: synchronize port_event() vs usb_port_{suspend|resume}   * @portnum: port index num based one - * @power_is_on: port's power state - * @did_runtime_put: port has done pm_runtime_put(). + * @is_superspeed cache super-speed status   */  struct usb_port {  	struct usb_device *child;  	struct device dev; -	struct dev_state *port_owner; +	struct usb_dev_state *port_owner; +	struct usb_port *peer; +	struct dev_pm_qos_request *req;  	enum usb_port_connect_type connect_type; +	usb_port_location_t location; +	struct mutex status_lock;  	u8 portnum; -	unsigned power_is_on:1; -	unsigned did_runtime_put:1; +	unsigned int is_superspeed:1;  };  #define to_usb_port(_dev) \ @@ -111,6 +119,29 @@ extern int hub_port_debounce(struct usb_hub *hub, int port1,  extern int usb_clear_port_feature(struct usb_device *hdev,  		int port1, int feature); +static inline bool hub_is_port_power_switchable(struct usb_hub *hub) +{ +	__le16 hcs; + +	if (!hub) +		return false; +	hcs = hub->descriptor->wHubCharacteristics; +	return (le16_to_cpu(hcs) & HUB_CHAR_LPSM) < HUB_CHAR_NO_LPSM; +} + +static inline int hub_is_superspeed(struct usb_device *hdev) +{ +	return hdev->descriptor.bDeviceProtocol == USB_HUB_PR_SS; +} + +static inline unsigned hub_power_on_good_delay(struct usb_hub *hub) +{ +	unsigned delay = hub->descriptor->bPwrOn2PwrGood * 2; + +	/* Wait at least 100 msec for power to become stable */ +	return max(delay, 100U); +} +  static inline int hub_port_debounce_be_connected(struct usb_hub *hub,  		int port1)  { diff --git a/drivers/usb/core/message.c b/drivers/usb/core/message.c index 82927e1ed27..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> @@ -179,7 +178,7 @@ EXPORT_SYMBOL_GPL(usb_control_msg);   *   * Return:   * If successful, 0. Otherwise a negative error number. The number of actual - * bytes transferred will be stored in the @actual_length paramater. + * 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) @@ -218,7 +217,7 @@ EXPORT_SYMBOL_GPL(usb_interrupt_msg);   *   * Return:   * If successful, 0. Otherwise a negative error number. The number of actual - * bytes transferred will be stored in the @actual_length paramater. + * bytes transferred will be stored in the @actual_length parameter.   *   */  int usb_bulk_msg(struct usb_device *usb_dev, unsigned int pipe, @@ -518,7 +517,7 @@ void usb_sg_wait(struct usb_sg_request *io)  		io->urbs[i]->dev = io->dev;  		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); @@ -1182,8 +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); @@ -1290,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; @@ -1326,6 +1328,10 @@ int usb_set_interface(struct usb_device *dev, int interface, int alternate)  		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", @@ -1917,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); diff --git a/drivers/usb/core/port.c b/drivers/usb/core/port.c index 51542f85239..fe1b6d0967e 100644 --- a/drivers/usb/core/port.c +++ b/drivers/usb/core/port.c @@ -21,6 +21,8 @@  #include "hub.h" +static int usb_port_block_power_off; +  static const struct attribute_group *port_dev_group[];  static ssize_t connect_type_show(struct device *dev, @@ -66,6 +68,7 @@ static void usb_port_device_release(struct device *dev)  {  	struct usb_port *port_dev = to_usb_port(dev); +	kfree(port_dev->req);  	kfree(port_dev);  } @@ -76,17 +79,29 @@ static int usb_port_runtime_resume(struct device *dev)  	struct usb_device *hdev = to_usb_device(dev->parent->parent);  	struct usb_interface *intf = to_usb_interface(dev->parent);  	struct usb_hub *hub = usb_hub_to_struct_hub(hdev); +	struct usb_device *udev = port_dev->child; +	struct usb_port *peer = port_dev->peer;  	int port1 = port_dev->portnum;  	int retval;  	if (!hub)  		return -EINVAL; +	if (hub->in_reset) { +		set_bit(port1, hub->power_bits); +		return 0; +	} -	usb_autopm_get_interface(intf); -	set_bit(port1, hub->busy_bits); +	/* +	 * Power on our usb3 peer before this usb2 port to prevent a usb3 +	 * device from degrading to its usb2 connection +	 */ +	if (!port_dev->is_superspeed && peer) +		pm_runtime_get_sync(&peer->dev); +	usb_autopm_get_interface(intf);  	retval = usb_hub_set_port_power(hdev, hub, port1, true); -	if (port_dev->child && !retval) { +	msleep(hub_power_on_good_delay(hub)); +	if (udev && !retval) {  		/*  		 * Attempt to wait for usb hub port to be reconnected in order  		 * to make the resume procedure successful.  The device may have @@ -97,12 +112,17 @@ static int usb_port_runtime_resume(struct device *dev)  		if (retval < 0)  			dev_dbg(&port_dev->dev, "can't get reconnection after setting port  power on, status %d\n",  					retval); -		usb_clear_port_feature(hdev, port1, USB_PORT_FEAT_C_ENABLE);  		retval = 0; + +		/* Force the child awake to revalidate after the power loss. */ +		if (!test_and_set_bit(port1, hub->child_usage_bits)) { +			pm_runtime_get_noresume(&port_dev->dev); +			pm_request_resume(&udev->dev); +		}  	} -	clear_bit(port1, hub->busy_bits);  	usb_autopm_put_interface(intf); +  	return retval;  } @@ -112,23 +132,37 @@ static int usb_port_runtime_suspend(struct device *dev)  	struct usb_device *hdev = to_usb_device(dev->parent->parent);  	struct usb_interface *intf = to_usb_interface(dev->parent);  	struct usb_hub *hub = usb_hub_to_struct_hub(hdev); +	struct usb_port *peer = port_dev->peer;  	int port1 = port_dev->portnum;  	int retval;  	if (!hub)  		return -EINVAL; +	if (hub->in_reset) +		return -EBUSY;  	if (dev_pm_qos_flags(&port_dev->dev, PM_QOS_FLAG_NO_POWER_OFF)  			== PM_QOS_FLAGS_ALL)  		return -EAGAIN; +	if (usb_port_block_power_off) +		return -EBUSY; +  	usb_autopm_get_interface(intf); -	set_bit(port1, hub->busy_bits);  	retval = usb_hub_set_port_power(hdev, hub, port1, false);  	usb_clear_port_feature(hdev, port1, USB_PORT_FEAT_C_CONNECTION); -	usb_clear_port_feature(hdev, port1,	USB_PORT_FEAT_C_ENABLE); -	clear_bit(port1, hub->busy_bits); +	if (!port_dev->is_superspeed) +		usb_clear_port_feature(hdev, port1, USB_PORT_FEAT_C_ENABLE);  	usb_autopm_put_interface(intf); + +	/* +	 * Our peer usb3 port may now be able to suspend, so +	 * asynchronously queue a suspend request to observe that this +	 * usb2 port is now off. +	 */ +	if (!port_dev->is_superspeed && peer) +		pm_runtime_put(&peer->dev); +  	return retval;  }  #endif @@ -146,51 +180,305 @@ struct device_type usb_port_device_type = {  	.pm =		&usb_port_pm_ops,  }; +static struct device_driver usb_port_driver = { +	.name = "usb", +	.owner = THIS_MODULE, +}; + +static int link_peers(struct usb_port *left, struct usb_port *right) +{ +	struct usb_port *ss_port, *hs_port; +	int rc; + +	if (left->peer == right && right->peer == left) +		return 0; + +	if (left->peer || right->peer) { +		struct usb_port *lpeer = left->peer; +		struct usb_port *rpeer = right->peer; +		char *method; + +		if (left->location && left->location == right->location) +			method = "location"; +		else +			method = "default"; + +		pr_warn("usb: failed to peer %s and %s by %s (%s:%s) (%s:%s)\n", +			dev_name(&left->dev), dev_name(&right->dev), method, +			dev_name(&left->dev), +			lpeer ? dev_name(&lpeer->dev) : "none", +			dev_name(&right->dev), +			rpeer ? dev_name(&rpeer->dev) : "none"); +		return -EBUSY; +	} + +	rc = sysfs_create_link(&left->dev.kobj, &right->dev.kobj, "peer"); +	if (rc) +		return rc; +	rc = sysfs_create_link(&right->dev.kobj, &left->dev.kobj, "peer"); +	if (rc) { +		sysfs_remove_link(&left->dev.kobj, "peer"); +		return rc; +	} + +	/* +	 * We need to wake the HiSpeed port to make sure we don't race +	 * setting ->peer with usb_port_runtime_suspend().  Otherwise we +	 * may miss a suspend event for the SuperSpeed port. +	 */ +	if (left->is_superspeed) { +		ss_port = left; +		WARN_ON(right->is_superspeed); +		hs_port = right; +	} else { +		ss_port = right; +		WARN_ON(!right->is_superspeed); +		hs_port = left; +	} +	pm_runtime_get_sync(&hs_port->dev); + +	left->peer = right; +	right->peer = left; + +	/* +	 * The SuperSpeed reference is dropped when the HiSpeed port in +	 * this relationship suspends, i.e. when it is safe to allow a +	 * SuperSpeed connection to drop since there is no risk of a +	 * device degrading to its powered-off HiSpeed connection. +	 * +	 * Also, drop the HiSpeed ref taken above. +	 */ +	pm_runtime_get_sync(&ss_port->dev); +	pm_runtime_put(&hs_port->dev); + +	return 0; +} + +static void link_peers_report(struct usb_port *left, struct usb_port *right) +{ +	int rc; + +	rc = link_peers(left, right); +	if (rc == 0) { +		dev_dbg(&left->dev, "peered to %s\n", dev_name(&right->dev)); +	} else { +		dev_warn(&left->dev, "failed to peer to %s (%d)\n", +				dev_name(&right->dev), rc); +		pr_warn_once("usb: port power management may be unreliable\n"); +		usb_port_block_power_off = 1; +	} +} + +static void unlink_peers(struct usb_port *left, struct usb_port *right) +{ +	struct usb_port *ss_port, *hs_port; + +	WARN(right->peer != left || left->peer != right, +			"%s and %s are not peers?\n", +			dev_name(&left->dev), dev_name(&right->dev)); + +	/* +	 * We wake the HiSpeed port to make sure we don't race its +	 * usb_port_runtime_resume() event which takes a SuperSpeed ref +	 * when ->peer is !NULL. +	 */ +	if (left->is_superspeed) { +		ss_port = left; +		hs_port = right; +	} else { +		ss_port = right; +		hs_port = left; +	} + +	pm_runtime_get_sync(&hs_port->dev); + +	sysfs_remove_link(&left->dev.kobj, "peer"); +	right->peer = NULL; +	sysfs_remove_link(&right->dev.kobj, "peer"); +	left->peer = NULL; + +	/* Drop the SuperSpeed ref held on behalf of the active HiSpeed port */ +	pm_runtime_put(&ss_port->dev); + +	/* Drop the ref taken above */ +	pm_runtime_put(&hs_port->dev); +} + +/* + * For each usb hub device in the system check to see if it is in the + * peer domain of the given port_dev, and if it is check to see if it + * has a port that matches the given port by location + */ +static int match_location(struct usb_device *peer_hdev, void *p) +{ +	int port1; +	struct usb_hcd *hcd, *peer_hcd; +	struct usb_port *port_dev = p, *peer; +	struct usb_hub *peer_hub = usb_hub_to_struct_hub(peer_hdev); +	struct usb_device *hdev = to_usb_device(port_dev->dev.parent->parent); + +	if (!peer_hub) +		return 0; + +	hcd = bus_to_hcd(hdev->bus); +	peer_hcd = bus_to_hcd(peer_hdev->bus); +	/* peer_hcd is provisional until we verify it against the known peer */ +	if (peer_hcd != hcd->shared_hcd) +		return 0; + +	for (port1 = 1; port1 <= peer_hdev->maxchild; port1++) { +		peer = peer_hub->ports[port1 - 1]; +		if (peer && peer->location == port_dev->location) { +			link_peers_report(port_dev, peer); +			return 1; /* done */ +		} +	} + +	return 0; +} + +/* + * Find the peer port either via explicit platform firmware "location" + * data, the peer hcd for root hubs, or the upstream peer relationship + * for all other hubs. + */ +static void find_and_link_peer(struct usb_hub *hub, int port1) +{ +	struct usb_port *port_dev = hub->ports[port1 - 1], *peer; +	struct usb_device *hdev = hub->hdev; +	struct usb_device *peer_hdev; +	struct usb_hub *peer_hub; + +	/* +	 * If location data is available then we can only peer this port +	 * by a location match, not the default peer (lest we create a +	 * situation where we need to go back and undo a default peering +	 * when the port is later peered by location data) +	 */ +	if (port_dev->location) { +		/* we link the peer in match_location() if found */ +		usb_for_each_dev(port_dev, match_location); +		return; +	} else if (!hdev->parent) { +		struct usb_hcd *hcd = bus_to_hcd(hdev->bus); +		struct usb_hcd *peer_hcd = hcd->shared_hcd; + +		if (!peer_hcd) +			return; + +		peer_hdev = peer_hcd->self.root_hub; +	} else { +		struct usb_port *upstream; +		struct usb_device *parent = hdev->parent; +		struct usb_hub *parent_hub = usb_hub_to_struct_hub(parent); + +		if (!parent_hub) +			return; + +		upstream = parent_hub->ports[hdev->portnum - 1]; +		if (!upstream || !upstream->peer) +			return; + +		peer_hdev = upstream->peer->child; +	} + +	peer_hub = usb_hub_to_struct_hub(peer_hdev); +	if (!peer_hub || port1 > peer_hdev->maxchild) +		return; + +	/* +	 * we found a valid default peer, last check is to make sure it +	 * does not have location data +	 */ +	peer = peer_hub->ports[port1 - 1]; +	if (peer && peer->location == 0) +		link_peers_report(port_dev, peer); +} +  int usb_hub_create_port_device(struct usb_hub *hub, int port1)  { -	struct usb_port *port_dev = NULL; +	struct usb_port *port_dev;  	int retval;  	port_dev = kzalloc(sizeof(*port_dev), GFP_KERNEL); -	if (!port_dev) { -		retval = -ENOMEM; -		goto exit; +	if (!port_dev) +		return -ENOMEM; + +	port_dev->req = kzalloc(sizeof(*(port_dev->req)), GFP_KERNEL); +	if (!port_dev->req) { +		kfree(port_dev); +		return -ENOMEM;  	}  	hub->ports[port1 - 1] = port_dev;  	port_dev->portnum = port1; -	port_dev->power_is_on = true; +	set_bit(port1, hub->power_bits);  	port_dev->dev.parent = hub->intfdev;  	port_dev->dev.groups = port_dev_group;  	port_dev->dev.type = &usb_port_device_type; -	dev_set_name(&port_dev->dev, "port%d", port1); - +	port_dev->dev.driver = &usb_port_driver; +	if (hub_is_superspeed(hub->hdev)) +		port_dev->is_superspeed = 1; +	dev_set_name(&port_dev->dev, "%s-port%d", dev_name(&hub->hdev->dev), +			port1); +	mutex_init(&port_dev->status_lock);  	retval = device_register(&port_dev->dev); -	if (retval) -		goto error_register; +	if (retval) { +		put_device(&port_dev->dev); +		return retval; +	} + +	/* Set default policy of port-poweroff disabled. */ +	retval = dev_pm_qos_add_request(&port_dev->dev, port_dev->req, +			DEV_PM_QOS_FLAGS, PM_QOS_FLAG_NO_POWER_OFF); +	if (retval < 0) { +		device_unregister(&port_dev->dev); +		return retval; +	} + +	find_and_link_peer(hub, port1); +	/* +	 * Enable runtime pm and hold a refernce that hub_configure() +	 * will drop once the PM_QOS_NO_POWER_OFF flag state has been set +	 * and the hub has been fully registered (hdev->maxchild set). +	 */  	pm_runtime_set_active(&port_dev->dev); +	pm_runtime_get_noresume(&port_dev->dev); +	pm_runtime_enable(&port_dev->dev); +	device_enable_async_suspend(&port_dev->dev); -	/* It would be dangerous if user space couldn't -	 * prevent usb device from being powered off. So don't -	 * enable port runtime pm if failed to expose port's pm qos. +	/* +	 * Keep hidden the ability to enable port-poweroff if the hub +	 * does not support power switching.  	 */ -	if (!dev_pm_qos_expose_flags(&port_dev->dev, -			PM_QOS_FLAG_NO_POWER_OFF)) -		pm_runtime_enable(&port_dev->dev); +	if (!hub_is_port_power_switchable(hub)) +		return 0; + +	/* Attempt to let userspace take over the policy. */ +	retval = dev_pm_qos_expose_flags(&port_dev->dev, +			PM_QOS_FLAG_NO_POWER_OFF); +	if (retval < 0) { +		dev_warn(&port_dev->dev, "failed to expose pm_qos_no_poweroff\n"); +		return 0; +	} -	device_enable_async_suspend(&port_dev->dev); +	/* Userspace owns the policy, drop the kernel 'no_poweroff' request. */ +	retval = dev_pm_qos_remove_request(port_dev->req); +	if (retval >= 0) { +		kfree(port_dev->req); +		port_dev->req = NULL; +	}  	return 0; - -error_register: -	put_device(&port_dev->dev); -exit: -	return retval;  } -void usb_hub_remove_port_device(struct usb_hub *hub, -				       int port1) +void usb_hub_remove_port_device(struct usb_hub *hub, int port1)  { -	device_unregister(&hub->ports[port1 - 1]->dev); -} +	struct usb_port *port_dev = hub->ports[port1 - 1]; +	struct usb_port *peer; +	peer = port_dev->peer; +	if (peer) +		unlink_peers(port_dev, peer); +	device_unregister(&port_dev->dev); +} diff --git a/drivers/usb/core/quirks.c b/drivers/usb/core/quirks.c index 5b44cd47da5..739ee8e8bdf 100644 --- a/drivers/usb/core/quirks.c +++ b/drivers/usb/core/quirks.c @@ -13,6 +13,7 @@  #include <linux/usb.h>  #include <linux/usb/quirks.h> +#include <linux/usb/hcd.h>  #include "usb.h"  /* Lists of quirky USB devices, split in device quirks and interface quirks. @@ -46,6 +47,10 @@ static const struct usb_device_id usb_quirk_list[] = {  	/* Microsoft LifeCam-VX700 v2.0 */  	{ USB_DEVICE(0x045e, 0x0770), .driver_info = USB_QUIRK_RESET_RESUME }, +	/* Logitech HD Pro Webcams C920 and C930e */ +	{ USB_DEVICE(0x046d, 0x082d), .driver_info = USB_QUIRK_DELAY_INIT }, +	{ USB_DEVICE(0x046d, 0x0843), .driver_info = USB_QUIRK_DELAY_INIT }, +  	/* Logitech Quickcam Fusion */  	{ USB_DEVICE(0x046d, 0x08c1), .driver_info = USB_QUIRK_RESET_RESUME }, @@ -130,6 +135,9 @@ static const struct usb_device_id usb_quirk_list[] = {  	/* Broadcom BCM92035DGROM BT dongle */  	{ USB_DEVICE(0x0a5c, 0x2021), .driver_info = USB_QUIRK_RESET_RESUME }, +	/* MAYA44USB sound device */ +	{ USB_DEVICE(0x0a92, 0x0091), .driver_info = USB_QUIRK_RESET_RESUME }, +  	/* Action Semiconductor flash disk */  	{ USB_DEVICE(0x10d6, 0x2200), .driver_info =  			USB_QUIRK_STRING_FETCH_255 }, @@ -155,6 +163,21 @@ static const struct usb_device_id usb_interface_quirk_list[] = {  	{ }  /* terminating entry must be last */  }; +static const struct usb_device_id usb_amd_resume_quirk_list[] = { +	/* Lenovo Mouse with Pixart controller */ +	{ USB_DEVICE(0x17ef, 0x602e), .driver_info = USB_QUIRK_RESET_RESUME }, + +	/* Pixart Mouse */ +	{ USB_DEVICE(0x093a, 0x2500), .driver_info = USB_QUIRK_RESET_RESUME }, +	{ USB_DEVICE(0x093a, 0x2510), .driver_info = USB_QUIRK_RESET_RESUME }, +	{ USB_DEVICE(0x093a, 0x2521), .driver_info = USB_QUIRK_RESET_RESUME }, + +	/* Logitech Optical Mouse M90/M100 */ +	{ USB_DEVICE(0x046d, 0xc05a), .driver_info = USB_QUIRK_RESET_RESUME }, + +	{ }  /* terminating entry must be last */ +}; +  static bool usb_match_any_interface(struct usb_device *udev,  				    const struct usb_device_id *id)  { @@ -181,6 +204,18 @@ static bool usb_match_any_interface(struct usb_device *udev,  	return false;  } +static int usb_amd_resume_quirk(struct usb_device *udev) +{ +	struct usb_hcd *hcd; + +	hcd = bus_to_hcd(udev->bus); +	/* The device should be attached directly to root hub */ +	if (udev->level == 1 && hcd->amd_resume_bug == 1) +		return 1; + +	return 0; +} +  static u32 __usb_detect_quirks(struct usb_device *udev,  			       const struct usb_device_id *id)  { @@ -206,6 +241,15 @@ static u32 __usb_detect_quirks(struct usb_device *udev,  void usb_detect_quirks(struct usb_device *udev)  {  	udev->quirks = __usb_detect_quirks(udev, usb_quirk_list); + +	/* +	 * Pixart-based mice would trigger remote wakeup issue on AMD +	 * Yangtze chipset, so set them as RESET_RESUME flag. +	 */ +	if (usb_amd_resume_quirk(udev)) +		udev->quirks |= __usb_detect_quirks(udev, +				usb_amd_resume_quirk_list); +  	if (udev->quirks)  		dev_dbg(&udev->dev, "USB quirks for this device: %x\n",  			udev->quirks); diff --git a/drivers/usb/core/sysfs.c b/drivers/usb/core/sysfs.c index 6d2c8edb1ff..1236c6011c7 100644 --- a/drivers/usb/core/sysfs.c +++ b/drivers/usb/core/sysfs.c @@ -23,14 +23,16 @@ static ssize_t field##_show(struct device *dev,				\  {									\  	struct usb_device *udev;					\  	struct usb_host_config *actconfig;				\ +	ssize_t rc = 0;							\  									\  	udev = to_usb_device(dev);					\ +	usb_lock_device(udev);						\  	actconfig = udev->actconfig;					\  	if (actconfig)							\ -		return sprintf(buf, format_string,			\ +		rc = sprintf(buf, format_string,			\  				actconfig->desc.field);			\ -	else								\ -		return 0;						\ +	usb_unlock_device(udev);					\ +	return rc;							\  }									\  #define usb_actconfig_attr(field, format_string)		\ @@ -45,12 +47,15 @@ static ssize_t bMaxPower_show(struct device *dev,  {  	struct usb_device *udev;  	struct usb_host_config *actconfig; +	ssize_t rc = 0;  	udev = to_usb_device(dev); +	usb_lock_device(udev);  	actconfig = udev->actconfig; -	if (!actconfig) -		return 0; -	return sprintf(buf, "%dmA\n", usb_get_max_power(udev, actconfig)); +	if (actconfig) +		rc = sprintf(buf, "%dmA\n", usb_get_max_power(udev, actconfig)); +	usb_unlock_device(udev); +	return rc;  }  static DEVICE_ATTR_RO(bMaxPower); @@ -59,12 +64,15 @@ static ssize_t configuration_show(struct device *dev,  {  	struct usb_device *udev;  	struct usb_host_config *actconfig; +	ssize_t rc = 0;  	udev = to_usb_device(dev); +	usb_lock_device(udev);  	actconfig = udev->actconfig; -	if ((!actconfig) || (!actconfig->string)) -		return 0; -	return sprintf(buf, "%s\n", actconfig->string); +	if (actconfig && actconfig->string) +		rc = sprintf(buf, "%s\n", actconfig->string); +	usb_unlock_device(udev); +	return rc;  }  static DEVICE_ATTR_RO(configuration); @@ -390,7 +398,8 @@ static DEVICE_ATTR_RW(autosuspend);  static const char on_string[] = "on";  static const char auto_string[] = "auto"; -static void warn_level(void) { +static void warn_level(void) +{  	static int level_warned;  	if (!level_warned) { @@ -449,7 +458,7 @@ static ssize_t usb2_hardware_lpm_show(struct device *dev,  	struct usb_device *udev = to_usb_device(dev);  	const char *p; -	if (udev->usb2_hw_lpm_enabled == 1) +	if (udev->usb2_hw_lpm_allowed == 1)  		p = "enabled";  	else  		p = "disabled"; @@ -469,8 +478,10 @@ static ssize_t usb2_hardware_lpm_store(struct device *dev,  	ret = strtobool(buf, &value); -	if (!ret) +	if (!ret) { +		udev->usb2_hw_lpm_allowed = value;  		ret = usb_set_usb2_hardware_lpm(udev, value); +	}  	usb_unlock_device(udev); @@ -644,7 +655,7 @@ static ssize_t authorized_store(struct device *dev,  		result = usb_deauthorize_device(usb_dev);  	else  		result = usb_authorize_device(usb_dev); -	return result < 0? result : size; +	return result < 0 ? result : size;  }  static DEVICE_ATTR_IGNORE_LOCKDEP(authorized, S_IRUGO | S_IWUSR,  				  authorized_show, authorized_store); @@ -764,6 +775,7 @@ read_descriptors(struct file *filp, struct kobject *kobj,  	 * Following that are the raw descriptor entries for all the  	 * configurations (config plus subsidiary descriptors).  	 */ +	usb_lock_device(udev);  	for (cfgno = -1; cfgno < udev->descriptor.bNumConfigurations &&  			nleft > 0; ++cfgno) {  		if (cfgno < 0) { @@ -784,6 +796,7 @@ read_descriptors(struct file *filp, struct kobject *kobj,  			off -= srclen;  		}  	} +	usb_unlock_device(udev);  	return count - nleft;  } @@ -824,7 +837,7 @@ void usb_remove_sysfs_dev_files(struct usb_device *udev)  	device_remove_bin_file(dev, &dev_bin_attr_descriptors);  } -/* Interface Accociation Descriptor fields */ +/* Interface Association Descriptor fields */  #define usb_intf_assoc_attr(field, format_string)			\  static ssize_t								\  iad_##field##_show(struct device *dev, struct device_attribute *attr,	\ @@ -870,9 +883,7 @@ static ssize_t interface_show(struct device *dev, struct device_attribute *attr,  	char *string;  	intf = to_usb_interface(dev); -	string = intf->cur_altsetting->string; -	barrier();		/* The altsetting might change! */ - +	string = ACCESS_ONCE(intf->cur_altsetting->string);  	if (!string)  		return 0;  	return sprintf(buf, "%s\n", string); @@ -888,7 +899,7 @@ static ssize_t modalias_show(struct device *dev, struct device_attribute *attr,  	intf = to_usb_interface(dev);  	udev = interface_to_usbdev(intf); -	alt = intf->cur_altsetting; +	alt = ACCESS_ONCE(intf->cur_altsetting);  	return sprintf(buf, "usb:v%04Xp%04Xd%04Xdc%02Xdsc%02Xdp%02X"  			"ic%02Xisc%02Xip%02Xin%02X\n", @@ -909,23 +920,14 @@ static ssize_t supports_autosuspend_show(struct device *dev,  					 struct device_attribute *attr,  					 char *buf)  { -	struct usb_interface *intf; -	struct usb_device *udev; -	int ret; +	int s; -	intf = to_usb_interface(dev); -	udev = interface_to_usbdev(intf); - -	usb_lock_device(udev); +	device_lock(dev);  	/* Devices will be autosuspended even when an interface isn't claimed */ -	if (!intf->dev.driver || -			to_usb_driver(intf->dev.driver)->supports_autosuspend) -		ret = sprintf(buf, "%u\n", 1); -	else -		ret = sprintf(buf, "%u\n", 0); -	usb_unlock_device(udev); +	s = (!dev->driver || to_usb_driver(dev->driver)->supports_autosuspend); +	device_unlock(dev); -	return ret; +	return sprintf(buf, "%u\n", s);  }  static DEVICE_ATTR_RO(supports_autosuspend); diff --git a/drivers/usb/core/urb.c b/drivers/usb/core/urb.c index c12bc790a6a..991386ceb4e 100644 --- a/drivers/usb/core/urb.c +++ b/drivers/usb/core/urb.c @@ -2,7 +2,6 @@  #include <linux/string.h>  #include <linux/bitops.h>  #include <linux/slab.h> -#include <linux/init.h>  #include <linux/log2.h>  #include <linux/usb.h>  #include <linux/wait.h> @@ -53,7 +52,7 @@ EXPORT_SYMBOL_GPL(usb_init_urb);   *	valid options for this.   *   * Creates an urb for the USB driver to use, initializes a few internal - * structures, incrementes the usage counter, and returns a pointer to it. + * structures, increments the usage counter, and returns a pointer to it.   *   * If the driver want to use this urb for interrupt, control, or bulk   * endpoints, pass '0' as the number of iso packets. @@ -138,13 +137,19 @@ void usb_anchor_urb(struct urb *urb, struct usb_anchor *anchor)  }  EXPORT_SYMBOL_GPL(usb_anchor_urb); +static int usb_anchor_check_wakeup(struct usb_anchor *anchor) +{ +	return atomic_read(&anchor->suspend_wakeups) == 0 && +		list_empty(&anchor->urb_list); +} +  /* Callers must hold anchor->lock */  static void __usb_unanchor_urb(struct urb *urb, struct usb_anchor *anchor)  {  	urb->anchor = NULL;  	list_del(&urb->anchor_list);  	usb_put_urb(urb); -	if (list_empty(&anchor->urb_list)) +	if (usb_anchor_check_wakeup(anchor))  		wake_up(&anchor->wait);  } @@ -275,7 +280,7 @@ EXPORT_SYMBOL_GPL(usb_unanchor_urb);   *   * Device drivers must explicitly request that repetition, by ensuring that   * some URB is always on the endpoint's queue (except possibly for short - * periods during completion callacks).  When there is no longer an urb + * periods during completion callbacks).  When there is no longer an urb   * queued, the endpoint's bandwidth reservation is canceled.  This means   * drivers can use their completion handlers to ensure they keep bandwidth   * they need, by reinitializing and resubmitting the just-completed urb @@ -319,10 +324,14 @@ EXPORT_SYMBOL_GPL(usb_unanchor_urb);   */  int usb_submit_urb(struct urb *urb, gfp_t mem_flags)  { +	static int			pipetypes[4] = { +		PIPE_CONTROL, PIPE_ISOCHRONOUS, PIPE_BULK, PIPE_INTERRUPT +	};  	int				xfertype, max;  	struct usb_device		*dev;  	struct usb_host_endpoint	*ep;  	int				is_out; +	unsigned int			allowed;  	if (!urb || !urb->complete)  		return -EINVAL; @@ -430,15 +439,10 @@ int usb_submit_urb(struct urb *urb, gfp_t mem_flags)  	if (urb->transfer_buffer_length > INT_MAX)  		return -EMSGSIZE; -#ifdef DEBUG -	/* stuff that drivers shouldn't do, but which shouldn't +	/* +	 * stuff that drivers shouldn't do, but which shouldn't  	 * cause problems in HCDs if they get it wrong.  	 */ -	{ -	unsigned int	allowed; -	static int pipetypes[4] = { -		PIPE_CONTROL, PIPE_ISOCHRONOUS, PIPE_BULK, PIPE_INTERRUPT -	};  	/* Check that the pipe's type matches the endpoint's type */  	if (usb_pipetype(urb->pipe) != pipetypes[xfertype]) @@ -470,8 +474,7 @@ int usb_submit_urb(struct urb *urb, gfp_t mem_flags)  	if (allowed != urb->transfer_flags)  		dev_WARN(&dev->dev, "BOGUS urb flags, %x --> %x\n",  			urb->transfer_flags, allowed); -	} -#endif +  	/*  	 * Force periodic transfer intervals to be legal values that are  	 * a power of two (so HCDs don't need to). @@ -486,9 +489,9 @@ int usb_submit_urb(struct urb *urb, gfp_t mem_flags)  		/* too small? */  		switch (dev->speed) {  		case USB_SPEED_WIRELESS: -			if (urb->interval < 6) +			if ((urb->interval < 6) +				&& (xfertype == USB_ENDPOINT_XFER_INT))  				return -EINVAL; -			break;  		default:  			if (urb->interval <= 0)  				return -EINVAL; @@ -828,7 +831,7 @@ EXPORT_SYMBOL_GPL(usb_unpoison_anchored_urbs);   *   * this allows all outstanding URBs to be unlinked starting   * from the back of the queue. This function is asynchronous. - * The unlinking is just tiggered. It may happen after this + * The unlinking is just triggered. It may happen after this   * function has returned.   *   * This routine should not be called by a driver after its disconnect @@ -846,6 +849,39 @@ void usb_unlink_anchored_urbs(struct usb_anchor *anchor)  EXPORT_SYMBOL_GPL(usb_unlink_anchored_urbs);  /** + * usb_anchor_suspend_wakeups + * @anchor: the anchor you want to suspend wakeups on + * + * Call this to stop the last urb being unanchored from waking up any + * usb_wait_anchor_empty_timeout waiters. This is used in the hcd urb give- + * back path to delay waking up until after the completion handler has run. + */ +void usb_anchor_suspend_wakeups(struct usb_anchor *anchor) +{ +	if (anchor) +		atomic_inc(&anchor->suspend_wakeups); +} +EXPORT_SYMBOL_GPL(usb_anchor_suspend_wakeups); + +/** + * usb_anchor_resume_wakeups + * @anchor: the anchor you want to resume wakeups on + * + * Allow usb_wait_anchor_empty_timeout waiters to be woken up again, and + * wake up any current waiters if the anchor is empty. + */ +void usb_anchor_resume_wakeups(struct usb_anchor *anchor) +{ +	if (!anchor) +		return; + +	atomic_dec(&anchor->suspend_wakeups); +	if (usb_anchor_check_wakeup(anchor)) +		wake_up(&anchor->wait); +} +EXPORT_SYMBOL_GPL(usb_anchor_resume_wakeups); + +/**   * usb_wait_anchor_empty_timeout - wait for an anchor to be unused   * @anchor: the anchor you want to become unused   * @timeout: how long you are willing to wait in milliseconds @@ -858,7 +894,8 @@ EXPORT_SYMBOL_GPL(usb_unlink_anchored_urbs);  int usb_wait_anchor_empty_timeout(struct usb_anchor *anchor,  				  unsigned int timeout)  { -	return wait_event_timeout(anchor->wait, list_empty(&anchor->urb_list), +	return wait_event_timeout(anchor->wait, +				  usb_anchor_check_wakeup(anchor),  				  msecs_to_jiffies(timeout));  }  EXPORT_SYMBOL_GPL(usb_wait_anchor_empty_timeout); diff --git a/drivers/usb/core/usb-acpi.c b/drivers/usb/core/usb-acpi.c index 255c14464bf..2776cfe64c0 100644 --- a/drivers/usb/core/usb-acpi.c +++ b/drivers/usb/core/usb-acpi.c @@ -16,9 +16,8 @@  #include <linux/acpi.h>  #include <linux/pci.h>  #include <linux/usb/hcd.h> -#include <acpi/acpi_bus.h> -#include "usb.h" +#include "hub.h"  /**   * usb_acpi_power_manageable - check whether usb port has @@ -56,13 +55,18 @@ EXPORT_SYMBOL_GPL(usb_acpi_power_manageable);   */  int usb_acpi_set_power_state(struct usb_device *hdev, int index, bool enable)  { +	struct usb_hub *hub = usb_hub_to_struct_hub(hdev); +	struct usb_port *port_dev;  	acpi_handle port_handle;  	unsigned char state;  	int port1 = index + 1;  	int error = -EINVAL; -	port_handle = (acpi_handle)usb_get_hub_port_acpi_handle(hdev, -		port1); +	if (!hub) +		return -ENODEV; +	port_dev = hub->ports[port1 - 1]; + +	port_handle = (acpi_handle) usb_get_hub_port_acpi_handle(hdev, port1);  	if (!port_handle)  		return error; @@ -73,65 +77,61 @@ int usb_acpi_set_power_state(struct usb_device *hdev, int index, bool enable)  	error = acpi_bus_set_power(port_handle, state);  	if (!error) -		dev_dbg(&hdev->dev, "The power of hub port %d was set to %d\n", -			port1, enable); +		dev_dbg(&port_dev->dev, "acpi: power was set to %d\n", enable);  	else -		dev_dbg(&hdev->dev, "The power of hub port failed to be set\n"); +		dev_dbg(&port_dev->dev, "acpi: power failed to be set\n");  	return error;  }  EXPORT_SYMBOL_GPL(usb_acpi_set_power_state); -static int usb_acpi_check_port_connect_type(struct usb_device *hdev, -	acpi_handle handle, int port1) +static enum usb_port_connect_type usb_acpi_get_connect_type(acpi_handle handle, +		struct acpi_pld_info *pld)  { -	acpi_status status; +	enum usb_port_connect_type connect_type = USB_PORT_CONNECT_TYPE_UNKNOWN;  	struct acpi_buffer buffer = { ACPI_ALLOCATE_BUFFER, NULL };  	union acpi_object *upc; -	struct acpi_pld_info *pld; -	int ret = 0; +	acpi_status status;  	/* -	 * Accoding to ACPI Spec 9.13. PLD indicates whether usb port is +	 * According to ACPI Spec 9.13. PLD indicates whether usb port is  	 * user visible and _UPC indicates whether it is connectable. If  	 * the port was visible and connectable, it could be freely connected  	 * and disconnected with USB devices. If no visible and connectable,  	 * a usb device is directly hard-wired to the port. If no visible and  	 * no connectable, the port would be not used.  	 */ -	status = acpi_get_physical_device_location(handle, &pld); -	if (ACPI_FAILURE(status)) -		return -ENODEV; -  	status = acpi_evaluate_object(handle, "_UPC", NULL, &buffer);  	upc = buffer.pointer;  	if (!upc || (upc->type != ACPI_TYPE_PACKAGE)  		|| upc->package.count != 4) { -		ret = -EINVAL;  		goto out;  	}  	if (upc->package.elements[0].integer.value)  		if (pld->user_visible) -			usb_set_hub_port_connect_type(hdev, port1, -				USB_PORT_CONNECT_TYPE_HOT_PLUG); +			connect_type = USB_PORT_CONNECT_TYPE_HOT_PLUG;  		else -			usb_set_hub_port_connect_type(hdev, port1, -				USB_PORT_CONNECT_TYPE_HARD_WIRED); +			connect_type = USB_PORT_CONNECT_TYPE_HARD_WIRED;  	else if (!pld->user_visible) -		usb_set_hub_port_connect_type(hdev, port1, USB_PORT_NOT_USED); - +		connect_type = USB_PORT_NOT_USED;  out: -	ACPI_FREE(pld);  	kfree(upc); -	return ret; +	return connect_type;  } -static int usb_acpi_find_device(struct device *dev, acpi_handle *handle) + +/* + * Private to usb-acpi, all the core needs to know is that + * port_dev->location is non-zero when it has been set by the firmware. + */ +#define USB_ACPI_LOCATION_VALID (1 << 31) + +static struct acpi_device *usb_acpi_find_companion(struct device *dev)  {  	struct usb_device *udev; +	struct acpi_device *adev;  	acpi_handle *parent_handle; -	int port_num;  	/*  	 * In the ACPI DSDT table, only usb root hub and usb ports are @@ -148,38 +148,19 @@ static int usb_acpi_find_device(struct device *dev, acpi_handle *handle)  	 */  	if (is_usb_device(dev)) {  		udev = to_usb_device(dev); -		if (udev->parent) { -			enum usb_port_connect_type type; - -			/* -			 * According usb port's connect type to set usb device's -			 * removability. -			 */ -			type = usb_get_hub_port_connect_type(udev->parent, -				udev->portnum); -			switch (type) { -			case USB_PORT_CONNECT_TYPE_HOT_PLUG: -				udev->removable = USB_DEVICE_REMOVABLE; -				break; -			case USB_PORT_CONNECT_TYPE_HARD_WIRED: -				udev->removable = USB_DEVICE_FIXED; -				break; -			default: -				udev->removable = USB_DEVICE_REMOVABLE_UNKNOWN; -				break; -			} - -			return -ENODEV; -		} +		if (udev->parent) +			return NULL; -		/* root hub's parent is the usb hcd. */ -		parent_handle = DEVICE_ACPI_HANDLE(dev->parent); -		*handle = acpi_get_child(parent_handle, udev->portnum); -		if (!*handle) -			return -ENODEV; -		return 0; +		/* root hub is only child (_ADR=0) under its parent, the HC */ +		adev = ACPI_COMPANION(dev->parent); +		return acpi_find_child_device(adev, 0, false);  	} else if (is_usb_port(dev)) { -		sscanf(dev_name(dev), "port%d", &port_num); +		struct usb_port *port_dev = to_usb_port(dev); +		int port1 = port_dev->portnum; +		struct acpi_pld_info *pld; +		acpi_handle *handle; +		acpi_status status; +  		/* Get the struct usb_device point of port's hub */  		udev = to_usb_device(dev->parent->parent); @@ -190,30 +171,39 @@ static int usb_acpi_find_device(struct device *dev, acpi_handle *handle)  		 */  		if (!udev->parent) {  			struct usb_hcd *hcd = bus_to_hcd(udev->bus); -			int raw_port_num; - -			raw_port_num = usb_hcd_find_raw_port_number(hcd, -				port_num); -			*handle = acpi_get_child(DEVICE_ACPI_HANDLE(&udev->dev), -				raw_port_num); -			if (!*handle) -				return -ENODEV; +			int raw; + +			raw = usb_hcd_find_raw_port_number(hcd, port1); +			adev = acpi_find_child_device(ACPI_COMPANION(&udev->dev), +					raw, false); +			if (!adev) +				return NULL;  		} else {  			parent_handle =  				usb_get_hub_port_acpi_handle(udev->parent,  				udev->portnum);  			if (!parent_handle) -				return -ENODEV; +				return NULL; -			*handle = acpi_get_child(parent_handle,	port_num); -			if (!*handle) -				return -ENODEV; +			acpi_bus_get_device(parent_handle, &adev); +			adev = acpi_find_child_device(adev, port1, false); +			if (!adev) +				return NULL;  		} -		usb_acpi_check_port_connect_type(udev, *handle, port_num); -	} else -		return -ENODEV; +		handle = adev->handle; +		status = acpi_get_physical_device_location(handle, &pld); +		if (ACPI_FAILURE(status) || !pld) +			return adev; + +		port_dev->location = USB_ACPI_LOCATION_VALID +			| pld->group_token << 8 | pld->group_position; +		port_dev->connect_type = usb_acpi_get_connect_type(handle, pld); +		ACPI_FREE(pld); + +		return adev; +	} -	return 0; +	return NULL;  }  static bool usb_acpi_bus_match(struct device *dev) @@ -224,7 +214,7 @@ static bool usb_acpi_bus_match(struct device *dev)  static struct acpi_bus_type usb_acpi_bus = {  	.name = "USB",  	.match = usb_acpi_bus_match, -	.find_device = usb_acpi_find_device, +	.find_companion = usb_acpi_find_companion,  };  int usb_acpi_register(void) diff --git a/drivers/usb/core/usb.c b/drivers/usb/core/usb.c index 0a6ee2e70b2..4d1144990d4 100644 --- a/drivers/usb/core/usb.c +++ b/drivers/usb/core/usb.c @@ -497,7 +497,7 @@ struct usb_device *usb_alloc_dev(struct usb_device *parent,  		dev->authorized = 1;  	else {  		dev->authorized = usb_hcd->authorized_default; -		dev->wusb = usb_bus_is_wusb(bus)? 1 : 0; +		dev->wusb = usb_bus_is_wusb(bus) ? 1 : 0;  	}  	return dev;  } diff --git a/drivers/usb/core/usb.h b/drivers/usb/core/usb.h index 823857767a1..d9d08720c38 100644 --- a/drivers/usb/core/usb.h +++ b/drivers/usb/core/usb.h @@ -2,7 +2,7 @@  #include <linux/acpi.h>  struct usb_hub_descriptor; -struct dev_state; +struct usb_dev_state;  /* Functions local to drivers/usb/core/ */ @@ -55,14 +55,10 @@ extern int usb_match_one_id_intf(struct usb_device *dev,  extern int usb_match_device(struct usb_device *dev,  			    const struct usb_device_id *id);  extern void usb_forced_unbind_intf(struct usb_interface *intf); -extern void usb_rebind_intf(struct usb_interface *intf); +extern void usb_unbind_and_rebind_marked_interfaces(struct usb_device *udev); -extern int usb_hub_claim_port(struct usb_device *hdev, unsigned port, -		struct dev_state *owner); -extern int usb_hub_release_port(struct usb_device *hdev, unsigned port, -		struct dev_state *owner);  extern void usb_hub_release_all_ports(struct usb_device *hdev, -		struct dev_state *owner); +		struct usb_dev_state *owner);  extern bool usb_device_is_owned(struct usb_device *udev);  extern int  usb_hub_init(void); @@ -111,11 +107,6 @@ static inline int usb_autoresume_device(struct usb_device *udev)  	return 0;  } -static inline int usb_remote_wakeup(struct usb_device *udev) -{ -	return 0; -} -  static inline int usb_set_usb2_hardware_lpm(struct usb_device *udev, int enable)  {  	return 0; @@ -123,6 +114,7 @@ static inline int usb_set_usb2_hardware_lpm(struct usb_device *udev, int enable)  #endif  extern struct bus_type usb_bus_type; +extern struct mutex usb_port_peer_mutex;  extern struct device_type usb_device_type;  extern struct device_type usb_if_device_type;  extern struct device_type usb_ep_device_type; @@ -174,15 +166,17 @@ extern void usbfs_conn_disc_event(void);  extern int usb_devio_init(void);  extern void usb_devio_cleanup(void); +/* + * Firmware specific cookie identifying a port's location. '0' == no location + * data available + */ +typedef u32 usb_port_location_t; +  /* internal notify stuff */  extern void usb_notify_add_device(struct usb_device *udev);  extern void usb_notify_remove_device(struct usb_device *udev);  extern void usb_notify_add_bus(struct usb_bus *ubus);  extern void usb_notify_remove_bus(struct usb_bus *ubus); -extern enum usb_port_connect_type -	usb_get_hub_port_connect_type(struct usb_device *hdev, int port1); -extern void usb_set_hub_port_connect_type(struct usb_device *hdev, int port1, -	enum usb_port_connect_type type);  extern void usb_hub_adjust_deviceremovable(struct usb_device *hdev,  		struct usb_hub_descriptor *desc);  | 
