diff options
Diffstat (limited to 'drivers/usb/core')
| -rw-r--r-- | drivers/usb/core/Kconfig | 2 | ||||
| -rw-r--r-- | drivers/usb/core/devio.c | 38 | ||||
| -rw-r--r-- | drivers/usb/core/driver.c | 7 | ||||
| -rw-r--r-- | drivers/usb/core/file.c | 24 | ||||
| -rw-r--r-- | drivers/usb/core/hcd-pci.c | 3 | ||||
| -rw-r--r-- | drivers/usb/core/hcd.c | 122 | ||||
| -rw-r--r-- | drivers/usb/core/hub.c | 184 | ||||
| -rw-r--r-- | drivers/usb/core/message.c | 4 | ||||
| -rw-r--r-- | drivers/usb/core/quirks.c | 43 | ||||
| -rw-r--r-- | drivers/usb/core/sysfs.c | 64 | ||||
| -rw-r--r-- | drivers/usb/core/urb.c | 44 | ||||
| -rw-r--r-- | drivers/usb/core/usb-acpi.c | 4 | ||||
| -rw-r--r-- | drivers/usb/core/usb.c | 2 | ||||
| -rw-r--r-- | drivers/usb/core/usb.h | 1 | 
14 files changed, 330 insertions, 212 deletions
| diff --git a/drivers/usb/core/Kconfig b/drivers/usb/core/Kconfig index db535b0aa17..fed7f68d025 100644 --- a/drivers/usb/core/Kconfig +++ b/drivers/usb/core/Kconfig @@ -28,7 +28,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 diff --git a/drivers/usb/core/devio.c b/drivers/usb/core/devio.c index 71dc5d768fa..967152a63bd 100644 --- a/drivers/usb/core/devio.c +++ b/drivers/usb/core/devio.c @@ -914,10 +914,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)) { @@ -1636,32 +1634,32 @@ static int proc_reapurbnonblock(struct dev_state *ps, void __user *arg)  static int proc_control_compat(struct 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,  			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)  { diff --git a/drivers/usb/core/driver.c b/drivers/usb/core/driver.c index f7841d44fed..47aade2a5e7 100644 --- a/drivers/usb/core/driver.c +++ b/drivers/usb/core/driver.c @@ -1179,8 +1179,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); @@ -1790,6 +1790,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/hcd-pci.c b/drivers/usb/core/hcd-pci.c index b9d3c43e385..dfe9d0f2297 100644 --- a/drivers/usb/core/hcd-pci.c +++ b/drivers/usb/core/hcd-pci.c @@ -215,6 +215,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); diff --git a/drivers/usb/core/hcd.c b/drivers/usb/core/hcd.c index d6a8d23f047..6bffb8c87bc 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,6 +40,7 @@  #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> @@ -92,10 +93,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 +169,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 +192,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 +217,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 +226,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 +254,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 +273,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 +301,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 +426,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 +462,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 +524,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 +544,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 +607,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 +623,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 +681,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 +875,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); @@ -941,12 +939,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 +985,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);  }  /** @@ -1033,6 +1031,7 @@ static int register_root_hub(struct usb_hcd *hcd)  					dev_name(&usb_dev->dev), retval);  			return retval;  		} +		usb_dev->lpm_capable = usb_device_supports_lpm(usb_dev);  	}  	retval = usb_new_device (usb_dev); @@ -1120,21 +1119,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 @@ -1651,6 +1650,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 +1662,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 +1682,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 +1705,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 +1816,7 @@ rescan:  				 case USB_ENDPOINT_XFER_INT:  					s = "-intr"; break;  				 default: -			 		s = "-iso"; break; +					s = "-iso"; break;  				};  				s;  			})); @@ -2073,8 +2077,11 @@ 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: On success, the number of allocated streams. 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)  { @@ -2085,14 +2092,14 @@ void usb_free_streams(struct usb_interface *interface,  	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. */  	for (i = 0; i < num_eps; i++)  		if (!eps[i] || !usb_endpoint_xfer_bulk(&eps[i]->desc)) -			return; +			return -EINVAL; -	hcd->driver->free_streams(hcd, dev, eps, num_eps, mem_flags); +	return hcd->driver->free_streams(hcd, dev, eps, num_eps, mem_flags);  }  EXPORT_SYMBOL_GPL(usb_free_streams); @@ -2245,7 +2252,7 @@ static void hcd_resume_work(struct work_struct *work)  }  /** - * 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 +2331,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 +2340,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); @@ -2547,13 +2546,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, @@ -2600,7 +2592,7 @@ int usb_add_hcd(struct usb_hcd *hcd,  	/* 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); @@ -2743,7 +2735,7 @@ err_allocate_root_hub:  err_register_bus:  	hcd_buffer_destroy(hcd);  	return retval; -}  +}  EXPORT_SYMBOL_GPL(usb_add_hcd);  /** @@ -2818,7 +2810,7 @@ void usb_remove_hcd(struct usb_hcd *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 +2832,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 e6b682c6c23..a7c04e24ca4 100644 --- a/drivers/usb/core/hub.c +++ b/drivers/usb/core/hub.c @@ -120,7 +120,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 @@ -135,7 +135,7 @@ struct usb_hub *usb_hub_to_struct_hub(struct usb_device *hdev)  	return usb_get_intfdata(hdev->actconfig->interface[0]);  } -static int usb_device_supports_lpm(struct usb_device *udev) +int usb_device_supports_lpm(struct usb_device *udev)  {  	/* USB 2.1 (and greater) devices indicate LPM support through  	 * their USB 2.0 Extended Capabilities BOS descriptor. @@ -156,6 +156,11 @@ static int usb_device_supports_lpm(struct usb_device *udev)  				"Power management will be impacted.\n");  		return 0;  	} + +	/* udev is root hub */ +	if (!udev->parent) +		return 1; +  	if (udev->parent->lpm_capable)  		return 1; @@ -310,9 +315,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); @@ -433,7 +438,7 @@ static void set_port_led(  			case HUB_LED_OFF: s = "off"; break;  			case HUB_LED_AUTO: s = "auto"; break;  			default: s = "??"; break; -			}; s; }), +			} s; }),  			status);  } @@ -857,7 +862,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); @@ -956,7 +961,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);  }  /** @@ -1107,16 +1112,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 +1132,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; @@ -1361,7 +1368,7 @@ 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++)  			portstr[i] = hub->descriptor->u.hs.DeviceRemovable @@ -1429,32 +1436,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; +	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", -				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; +				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[] */ @@ -1560,7 +1567,7 @@ 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++) {  		ret = usb_hub_create_port_device(hub, i + 1); @@ -1978,7 +1985,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); @@ -2018,8 +2025,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. @@ -2232,8 +2239,7 @@ static int usb_enumerate_device(struct usb_device *udev)  		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 { +	} 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, @@ -2489,7 +2495,7 @@ 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;  } @@ -3108,8 +3114,8 @@ static int finish_port_resume(struct usb_device *udev)   retry_reset_resume:  		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) { @@ -3211,7 +3217,7 @@ int usb_port_resume(struct usb_device *udev, pm_message_t msg)  	if (status == 0 && !port_is_suspended(hub, portstatus))  		goto SuspendCleared; -	// dev_dbg(hub->intfdev, "resume port %d\n", port1); +	/* dev_dbg(hub->intfdev, "resume port %d\n", port1); */  	set_bit(port1, hub->busy_bits); @@ -3855,7 +3861,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. @@ -3949,6 +3955,32 @@ 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) +{ +	int connect_type; + +	if (!udev->usb2_hw_lpm_capable) +		return; + +	connect_type = usb_get_hub_port_connect_type(udev->parent, +			udev->portnum); + +	if ((udev->bos->ext_cap->bmAttributes & USB_BESL_SUPPORT) || +			connect_type == USB_PORT_CONNECT_TYPE_HARD_WIRED) { +		udev->usb2_hw_lpm_allowed = 1; +		usb_set_usb2_hardware_lpm(udev, 1); +	} +} +  /* 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. @@ -4055,7 +4087,7 @@ 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. @@ -4130,11 +4162,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); @@ -4163,7 +4195,7 @@ hub_port_init (struct usb_hub *hub, struct usb_device *udev, int port1,  			msleep(10);  			if (USE_NEW_SCHEME(retry_counter) && !(hcd->driver->flags & HCD_USB3))  				break; -  		} +		}  		retval = usb_get_device_descriptor(udev, 8);  		if (retval < 8) { @@ -4219,7 +4251,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) @@ -4242,6 +4274,7 @@ 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); @@ -4316,7 +4349,7 @@ hub_power_remaining (struct usb_hub *hub)  	}  	if (remaining < 0) {  		dev_warn(hub->intfdev, "%dmA over power budget!\n", -			- remaining); +			-remaining);  		remaining = 0;  	}  	return remaining; @@ -4427,7 +4460,7 @@ static void hub_port_connect_change(struct usb_hub *hub, int port1,  			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)) @@ -4450,7 +4483,7 @@ static void hub_port_connect_change(struct usb_hub *hub, int port1,  		}  		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); @@ -4504,7 +4537,7 @@ static void hub_port_connect_change(struct usb_hub *hub, int port1,  				goto loop_disable;  			}  		} -  +  		/* check for devices running slower than they could */  		if (le16_to_cpu(udev->descriptor.bcdUSB) >= 0x0200  				&& udev->speed == USB_SPEED_FULL @@ -4564,7 +4597,7 @@ loop:  			dev_err(hub_dev, "unable to enumerate USB device on port %d\n",  					port1);  	} -  +  done:  	hub_port_disable(hub, port1, 1);  	if (hcd->driver->relinquish_port && !hub->hdev->parent) @@ -4729,7 +4762,7 @@ static void hub_events(void)  				 * 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.  +				 * Works at least with mouse driver.  				 */  				if (!(portstatus & USB_PORT_STAT_ENABLE)  				    && !connect_change @@ -4841,7 +4874,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 " @@ -4861,7 +4894,7 @@ 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) @@ -4886,7 +4919,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}, @@ -5086,6 +5119,12 @@ static int usb_reset_and_verify_device(struct usb_device *udev)  	}  	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; @@ -5120,13 +5159,13 @@ static int usb_reset_and_verify_device(struct usb_device *udev)  	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) @@ -5151,7 +5190,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); @@ -5193,12 +5232,13 @@ static int usb_reset_and_verify_device(struct usb_device *udev)  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); @@ -5461,6 +5501,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/message.c b/drivers/usb/core/message.c index 82927e1ed27..bb315970e47 100644 --- a/drivers/usb/core/message.c +++ b/drivers/usb/core/message.c @@ -1182,8 +1182,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); diff --git a/drivers/usb/core/quirks.c b/drivers/usb/core/quirks.c index 5b44cd47da5..12924dbfdc2 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. @@ -97,6 +98,9 @@ static const struct usb_device_id usb_quirk_list[] = {  	/* Alcor Micro Corp. Hub */  	{ USB_DEVICE(0x058f, 0x9254), .driver_info = USB_QUIRK_RESET_RESUME }, +	/* MicroTouch Systems touchscreen */ +	{ USB_DEVICE(0x0596, 0x051e), .driver_info = USB_QUIRK_RESET_RESUME }, +  	/* appletouch */  	{ USB_DEVICE(0x05ac, 0x021a), .driver_info = USB_QUIRK_RESET_RESUME }, @@ -130,6 +134,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 +162,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 +203,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 +240,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..52a97adf02a 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;  } @@ -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..e62208356c8 100644 --- a/drivers/usb/core/urb.c +++ b/drivers/usb/core/urb.c @@ -138,13 +138,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);  } @@ -846,6 +852,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 +897,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..4e243c37f17 100644 --- a/drivers/usb/core/usb-acpi.c +++ b/drivers/usb/core/usb-acpi.c @@ -173,7 +173,7 @@ static int usb_acpi_find_device(struct device *dev, acpi_handle *handle)  		}  		/* root hub's parent is the usb hcd. */ -		parent_handle = DEVICE_ACPI_HANDLE(dev->parent); +		parent_handle = ACPI_HANDLE(dev->parent);  		*handle = acpi_get_child(parent_handle, udev->portnum);  		if (!*handle)  			return -ENODEV; @@ -194,7 +194,7 @@ static int usb_acpi_find_device(struct device *dev, acpi_handle *handle)  			raw_port_num = usb_hcd_find_raw_port_number(hcd,  				port_num); -			*handle = acpi_get_child(DEVICE_ACPI_HANDLE(&udev->dev), +			*handle = acpi_get_child(ACPI_HANDLE(&udev->dev),  				raw_port_num);  			if (!*handle)  				return -ENODEV; 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..c49383669cd 100644 --- a/drivers/usb/core/usb.h +++ b/drivers/usb/core/usb.h @@ -35,6 +35,7 @@ extern int usb_get_device_descriptor(struct usb_device *dev,  		unsigned int size);  extern int usb_get_bos_descriptor(struct usb_device *dev);  extern void usb_release_bos_descriptor(struct usb_device *dev); +extern int usb_device_supports_lpm(struct usb_device *udev);  extern char *usb_cache_string(struct usb_device *udev, int index);  extern int usb_set_configuration(struct usb_device *dev, int configuration);  extern int usb_choose_configuration(struct usb_device *udev); | 
