diff options
Diffstat (limited to 'drivers/usb/core')
| -rw-r--r-- | drivers/usb/core/devio.c | 7 | ||||
| -rw-r--r-- | drivers/usb/core/file.c | 2 | ||||
| -rw-r--r-- | drivers/usb/core/hcd.c | 28 | ||||
| -rw-r--r-- | drivers/usb/core/hub.c | 23 | ||||
| -rw-r--r-- | drivers/usb/core/hub.h | 2 | ||||
| -rw-r--r-- | drivers/usb/core/message.c | 16 | ||||
| -rw-r--r-- | drivers/usb/core/port.c | 4 | ||||
| -rw-r--r-- | drivers/usb/core/sysfs.c | 54 | ||||
| -rw-r--r-- | drivers/usb/core/usb.c | 33 | 
9 files changed, 147 insertions, 22 deletions
| diff --git a/drivers/usb/core/devio.c b/drivers/usb/core/devio.c index c88c4fb9459d..05986507b585 100644 --- a/drivers/usb/core/devio.c +++ b/drivers/usb/core/devio.c @@ -49,14 +49,14 @@  #include <linux/security.h>  #include <linux/user_namespace.h>  #include <linux/scatterlist.h> -#include <asm/uaccess.h> +#include <linux/uaccess.h>  #include <asm/byteorder.h>  #include <linux/moduleparam.h>  #include "usb.h"  #define USB_MAXBUS			64 -#define USB_DEVICE_MAX			USB_MAXBUS * 128 +#define USB_DEVICE_MAX			(USB_MAXBUS * 128)  #define USB_SG_SIZE			16384 /* split-size for large txs */  /* Mutual exclusion for removal, open, and release */ @@ -1804,7 +1804,8 @@ static int proc_ioctl(struct dev_state *ps, struct usbdevfs_ioctl *ctl)  	/* alloc buffer */  	if ((size = _IOC_SIZE(ctl->ioctl_code)) > 0) { -		if ((buf = kmalloc(size, GFP_KERNEL)) == NULL) +		buf = kmalloc(size, GFP_KERNEL); +		if (buf == NULL)  			return -ENOMEM;  		if ((_IOC_DIR(ctl->ioctl_code) & _IOC_WRITE)) {  			if (copy_from_user(buf, ctl->data, size)) { diff --git a/drivers/usb/core/file.c b/drivers/usb/core/file.c index e5387a47ef6f..6a4c40766f0f 100644 --- a/drivers/usb/core/file.c +++ b/drivers/usb/core/file.c @@ -94,7 +94,7 @@ static int init_usb_class(void)  	kref_init(&usb_class->kref);  	usb_class->class = class_create(THIS_MODULE, "usbmisc");  	if (IS_ERR(usb_class->class)) { -		result = IS_ERR(usb_class->class); +		result = PTR_ERR(usb_class->class);  		printk(KERN_ERR "class_create failed for usb devices\n");  		kfree(usb_class);  		usb_class = NULL; diff --git a/drivers/usb/core/hcd.c b/drivers/usb/core/hcd.c index d53547d2e4c7..014dc996b4f6 100644 --- a/drivers/usb/core/hcd.c +++ b/drivers/usb/core/hcd.c @@ -149,6 +149,27 @@ static const u8 usb3_rh_dev_descriptor[18] = {  	0x01        /*  __u8  bNumConfigurations; */  }; +/* usb 2.5 (wireless USB 1.0) root hub device descriptor */ +static const u8 usb25_rh_dev_descriptor[18] = { +	0x12,       /*  __u8  bLength; */ +	0x01,       /*  __u8  bDescriptorType; Device */ +	0x50, 0x02, /*  __le16 bcdUSB; v2.5 */ + +	0x09,	    /*  __u8  bDeviceClass; HUB_CLASSCODE */ +	0x00,	    /*  __u8  bDeviceSubClass; */ +	0x00,       /*  __u8  bDeviceProtocol; [ usb 2.0 no TT ] */ +	0xFF,       /*  __u8  bMaxPacketSize0; always 0xFF (WUSB Spec 7.4.1). */ + +	0x6b, 0x1d, /*  __le16 idVendor; Linux Foundation 0x1d6b */ +	0x02, 0x00, /*  __le16 idProduct; device 0x0002 */ +	KERNEL_VER, KERNEL_REL, /*  __le16 bcdDevice */ + +	0x03,       /*  __u8  iManufacturer; */ +	0x02,       /*  __u8  iProduct; */ +	0x01,       /*  __u8  iSerialNumber; */ +	0x01        /*  __u8  bNumConfigurations; */ +}; +  /* usb 2.0 root hub device descriptor */  static const u8 usb2_rh_dev_descriptor [18] = {  	0x12,       /*  __u8  bLength; */ @@ -527,6 +548,9 @@ static int rh_call_control (struct usb_hcd *hcd, struct urb *urb)  			case HCD_USB3:  				bufp = usb3_rh_dev_descriptor;  				break; +			case HCD_USB25: +				bufp = usb25_rh_dev_descriptor; +				break;  			case HCD_USB2:  				bufp = usb2_rh_dev_descriptor;  				break; @@ -546,6 +570,7 @@ static int rh_call_control (struct usb_hcd *hcd, struct urb *urb)  				bufp = ss_rh_config_descriptor;  				len = sizeof ss_rh_config_descriptor;  				break; +			case HCD_USB25:  			case HCD_USB2:  				bufp = hs_rh_config_descriptor;  				len = sizeof hs_rh_config_descriptor; @@ -2511,6 +2536,9 @@ int usb_add_hcd(struct usb_hcd *hcd,  	case HCD_USB2:  		rhdev->speed = USB_SPEED_HIGH;  		break; +	case HCD_USB25: +		rhdev->speed = USB_SPEED_WIRELESS; +		break;  	case HCD_USB3:  		rhdev->speed = USB_SPEED_SUPER;  		break; diff --git a/drivers/usb/core/hub.c b/drivers/usb/core/hub.c index feef9351463d..4191db32f12c 100644 --- a/drivers/usb/core/hub.c +++ b/drivers/usb/core/hub.c @@ -718,18 +718,18 @@ static void hub_tt_work(struct work_struct *work)  /**   * usb_hub_set_port_power - control hub port's power state - * @hdev: target hub + * @hdev: USB device belonging to the usb hub + * @hub: target hub   * @port1: port index   * @set: expected status   *   * call this function to control port's power via setting or   * clearing the port's PORT_POWER feature.   */ -int usb_hub_set_port_power(struct usb_device *hdev, int port1, -		bool set) +int usb_hub_set_port_power(struct usb_device *hdev, struct usb_hub *hub, +			   int port1, bool set)  {  	int ret; -	struct usb_hub *hub = usb_hub_to_struct_hub(hdev);  	struct usb_port *port_dev = hub->ports[port1 - 1];  	if (set) @@ -1769,15 +1769,17 @@ hub_ioctl(struct usb_interface *intf, unsigned int code, void *user_data)  static int find_port_owner(struct usb_device *hdev, unsigned port1,  		struct dev_state ***ppowner)  { +	struct usb_hub *hub = usb_hub_to_struct_hub(hdev); +  	if (hdev->state == USB_STATE_NOTATTACHED)  		return -ENODEV;  	if (port1 == 0 || port1 > hdev->maxchild)  		return -EINVAL; -	/* This assumes that devices not managed by the hub driver +	/* Devices not managed by the hub driver  	 * will always have maxchild equal to 0.  	 */ -	*ppowner = &(usb_hub_to_struct_hub(hdev)->ports[port1 - 1]->port_owner); +	*ppowner = &(hub->ports[port1 - 1]->port_owner);  	return 0;  } @@ -5323,7 +5325,8 @@ void usb_set_hub_port_connect_type(struct usb_device *hdev, int port1,  {  	struct usb_hub *hub = usb_hub_to_struct_hub(hdev); -	hub->ports[port1 - 1]->connect_type = type; +	if (hub) +		hub->ports[port1 - 1]->connect_type = type;  }  /** @@ -5339,6 +5342,9 @@ 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;  } @@ -5397,6 +5403,9 @@ acpi_handle usb_get_hub_port_acpi_handle(struct usb_device *hdev,  {  	struct usb_hub *hub = usb_hub_to_struct_hub(hdev); +	if (!hub) +		return NULL; +  	return DEVICE_ACPI_HANDLE(&hub->ports[port1 - 1]->dev);  }  #endif diff --git a/drivers/usb/core/hub.h b/drivers/usb/core/hub.h index 80ab9ee07017..6508e02b3dac 100644 --- a/drivers/usb/core/hub.h +++ b/drivers/usb/core/hub.h @@ -100,7 +100,7 @@ extern int usb_hub_create_port_device(struct usb_hub *hub,  		int port1);  extern void usb_hub_remove_port_device(struct usb_hub *hub,  		int port1); -extern int usb_hub_set_port_power(struct usb_device *hdev, +extern int usb_hub_set_port_power(struct usb_device *hdev, struct usb_hub *hub,  		int port1, bool set);  extern struct usb_hub *usb_hub_to_struct_hub(struct usb_device *hdev);  extern int hub_port_debounce(struct usb_hub *hub, int port1, diff --git a/drivers/usb/core/message.c b/drivers/usb/core/message.c index 444d30e3a78b..e7ee1e451660 100644 --- a/drivers/usb/core/message.c +++ b/drivers/usb/core/message.c @@ -252,7 +252,7 @@ static void sg_clean(struct usb_sg_request *io)  {  	if (io->urbs) {  		while (io->entries--) -			usb_free_urb(io->urbs [io->entries]); +			usb_free_urb(io->urbs[io->entries]);  		kfree(io->urbs);  		io->urbs = NULL;  	} @@ -300,10 +300,10 @@ static void sg_complete(struct urb *urb)  		 */  		spin_unlock(&io->lock);  		for (i = 0, found = 0; i < io->entries; i++) { -			if (!io->urbs [i] || !io->urbs [i]->dev) +			if (!io->urbs[i] || !io->urbs[i]->dev)  				continue;  			if (found) { -				retval = usb_unlink_urb(io->urbs [i]); +				retval = usb_unlink_urb(io->urbs[i]);  				if (retval != -EINPROGRESS &&  				    retval != -ENODEV &&  				    retval != -EBUSY && @@ -311,7 +311,7 @@ static void sg_complete(struct urb *urb)  					dev_err(&io->dev->dev,  						"%s, unlink --> %d\n",  						__func__, retval); -			} else if (urb == io->urbs [i]) +			} else if (urb == io->urbs[i])  				found = 1;  		}  		spin_lock(&io->lock); @@ -379,7 +379,7 @@ int usb_sg_init(struct usb_sg_request *io, struct usb_device *dev,  	}  	/* initialize all the urbs we'll use */ -	io->urbs = kmalloc(io->entries * sizeof *io->urbs, mem_flags); +	io->urbs = kmalloc(io->entries * sizeof(*io->urbs), mem_flags);  	if (!io->urbs)  		goto nomem; @@ -511,7 +511,7 @@ void usb_sg_wait(struct usb_sg_request *io)  		int retval;  		io->urbs[i]->dev = io->dev; -		retval = usb_submit_urb(io->urbs [i], GFP_ATOMIC); +		retval = usb_submit_urb(io->urbs[i], GFP_ATOMIC);  		/* after we submit, let completions or cancelations fire;  		 * we handshake using io->status. @@ -586,9 +586,9 @@ void usb_sg_cancel(struct usb_sg_request *io)  		for (i = 0; i < io->entries; i++) {  			int retval; -			if (!io->urbs [i]->dev) +			if (!io->urbs[i]->dev)  				continue; -			retval = usb_unlink_urb(io->urbs [i]); +			retval = usb_unlink_urb(io->urbs[i]);  			if (retval != -EINPROGRESS  					&& retval != -ENODEV  					&& retval != -EBUSY diff --git a/drivers/usb/core/port.c b/drivers/usb/core/port.c index b8bad294eeb8..5fd3fee58f8b 100644 --- a/drivers/usb/core/port.c +++ b/drivers/usb/core/port.c @@ -86,7 +86,7 @@ static int usb_port_runtime_resume(struct device *dev)  	usb_autopm_get_interface(intf);  	set_bit(port1, hub->busy_bits); -	retval = usb_hub_set_port_power(hdev, port1, true); +	retval = usb_hub_set_port_power(hdev, hub, port1, true);  	if (port_dev->child && !retval) {  		/*  		 * Wait for usb hub port to be reconnected in order to make @@ -128,7 +128,7 @@ static int usb_port_runtime_suspend(struct device *dev)  	usb_autopm_get_interface(intf);  	set_bit(port1, hub->busy_bits); -	retval = usb_hub_set_port_power(hdev, port1, false); +	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); diff --git a/drivers/usb/core/sysfs.c b/drivers/usb/core/sysfs.c index aa38db44818a..d9284b998bd7 100644 --- a/drivers/usb/core/sysfs.c +++ b/drivers/usb/core/sysfs.c @@ -497,8 +497,62 @@ set_usb2_hardware_lpm(struct device *dev, struct device_attribute *attr,  static DEVICE_ATTR(usb2_hardware_lpm, S_IRUGO | S_IWUSR, show_usb2_hardware_lpm,  			set_usb2_hardware_lpm); +static ssize_t +show_usb2_lpm_l1_timeout(struct device *dev, struct device_attribute *attr, +			 char *buf) +{ +	struct usb_device *udev = to_usb_device(dev); +	return sprintf(buf, "%d\n", udev->l1_params.timeout); +} + +static ssize_t +set_usb2_lpm_l1_timeout(struct device *dev, struct device_attribute *attr, +			const char *buf, size_t count) +{ +	struct usb_device *udev = to_usb_device(dev); +	u16 timeout; + +	if (kstrtou16(buf, 0, &timeout)) +		return -EINVAL; + +	udev->l1_params.timeout = timeout; + +	return count; +} + +static DEVICE_ATTR(usb2_lpm_l1_timeout, S_IRUGO | S_IWUSR, +		   show_usb2_lpm_l1_timeout, set_usb2_lpm_l1_timeout); + +static ssize_t +show_usb2_lpm_besl(struct device *dev, struct device_attribute *attr, +		   char *buf) +{ +	struct usb_device *udev = to_usb_device(dev); +	return sprintf(buf, "%d\n", udev->l1_params.besl); +} + +static ssize_t +set_usb2_lpm_besl(struct device *dev, struct device_attribute *attr, +		const char *buf, size_t count) +{ +	struct usb_device *udev = to_usb_device(dev); +	u8 besl; + +	if (kstrtou8(buf, 0, &besl) || besl > 15) +		return -EINVAL; + +	udev->l1_params.besl = besl; + +	return count; +} + +static DEVICE_ATTR(usb2_lpm_besl, S_IRUGO | S_IWUSR, +		   show_usb2_lpm_besl, set_usb2_lpm_besl); +  static struct attribute *usb2_hardware_lpm_attr[] = {  	&dev_attr_usb2_hardware_lpm.attr, +	&dev_attr_usb2_lpm_l1_timeout.attr, +	&dev_attr_usb2_lpm_besl.attr,  	NULL,  };  static struct attribute_group usb2_hardware_lpm_attr_group = { diff --git a/drivers/usb/core/usb.c b/drivers/usb/core/usb.c index b10da720f2b4..7dad603dde43 100644 --- a/drivers/usb/core/usb.c +++ b/drivers/usb/core/usb.c @@ -209,6 +209,39 @@ struct usb_interface *usb_find_interface(struct usb_driver *drv, int minor)  }  EXPORT_SYMBOL_GPL(usb_find_interface); +struct each_dev_arg { +	void *data; +	int (*fn)(struct usb_device *, void *); +}; + +static int __each_dev(struct device *dev, void *data) +{ +	struct each_dev_arg *arg = (struct each_dev_arg *)data; + +	/* There are struct usb_interface on the same bus, filter them out */ +	if (!is_usb_device(dev)) +		return 0; + +	return arg->fn(container_of(dev, struct usb_device, dev), arg->data); +} + +/** + * usb_for_each_dev - iterate over all USB devices in the system + * @data: data pointer that will be handed to the callback function + * @fn: callback function to be called for each USB device + * + * Iterate over all USB devices and call @fn for each, passing it @data. If it + * returns anything other than 0, we break the iteration prematurely and return + * that value. + */ +int usb_for_each_dev(void *data, int (*fn)(struct usb_device *, void *)) +{ +	struct each_dev_arg arg = {data, fn}; + +	return bus_for_each_dev(&usb_bus_type, NULL, &arg, __each_dev); +} +EXPORT_SYMBOL_GPL(usb_for_each_dev); +  /**   * usb_release_dev - free a usb device structure when all users of it are finished.   * @dev: device that's been disconnected |