diff options
Diffstat (limited to 'drivers/usb/core')
| -rw-r--r-- | drivers/usb/core/devio.c | 7 | ||||
| -rw-r--r-- | drivers/usb/core/driver.c | 1 | ||||
| -rw-r--r-- | drivers/usb/core/hcd.c | 49 | ||||
| -rw-r--r-- | drivers/usb/core/hub.c | 44 | ||||
| -rw-r--r-- | drivers/usb/core/hub.h | 1 | ||||
| -rw-r--r-- | drivers/usb/core/message.c | 8 | ||||
| -rw-r--r-- | drivers/usb/core/port.c | 23 | ||||
| -rw-r--r-- | drivers/usb/core/quirks.c | 4 | ||||
| -rw-r--r-- | drivers/usb/core/sysfs.c | 22 | ||||
| -rw-r--r-- | drivers/usb/core/usb.c | 26 | 
10 files changed, 112 insertions, 73 deletions
diff --git a/drivers/usb/core/devio.c b/drivers/usb/core/devio.c index 76e16c5251b9..476dcc5f2da3 100644 --- a/drivers/usb/core/devio.c +++ b/drivers/usb/core/devio.c @@ -897,7 +897,7 @@ static int parse_usbdevfs_streams(struct usb_dev_state *ps,  	if (num_streams_ret && (num_streams < 2 || num_streams > 65536))  		return -EINVAL; -	eps = kmalloc(num_eps * sizeof(*eps), GFP_KERNEL); +	eps = kmalloc_array(num_eps, sizeof(*eps), GFP_KERNEL);  	if (!eps)  		return -ENOMEM; @@ -1602,8 +1602,9 @@ static int proc_do_submiturb(struct usb_dev_state *ps, struct usbdevfs_urb *uurb  	as->mem_usage = u;  	if (num_sgs) { -		as->urb->sg = kmalloc(num_sgs * sizeof(struct scatterlist), -				      GFP_KERNEL); +		as->urb->sg = kmalloc_array(num_sgs, +					    sizeof(struct scatterlist), +					    GFP_KERNEL);  		if (!as->urb->sg) {  			ret = -ENOMEM;  			goto error; diff --git a/drivers/usb/core/driver.c b/drivers/usb/core/driver.c index 9792cedfc351..e76e95f62f76 100644 --- a/drivers/usb/core/driver.c +++ b/drivers/usb/core/driver.c @@ -1922,4 +1922,5 @@ struct bus_type usb_bus_type = {  	.name =		"usb",  	.match =	usb_device_match,  	.uevent =	usb_uevent, +	.need_parent_lock =	true,  }; diff --git a/drivers/usb/core/hcd.c b/drivers/usb/core/hcd.c index 0a42c5df3c0f..1c21955fe7c0 100644 --- a/drivers/usb/core/hcd.c +++ b/drivers/usb/core/hcd.c @@ -33,7 +33,6 @@  #include <linux/phy/phy.h>  #include <linux/usb.h>  #include <linux/usb/hcd.h> -#include <linux/usb/phy.h>  #include <linux/usb/otg.h>  #include "usb.h" @@ -568,6 +567,7 @@ static int rh_call_control (struct usb_hcd *hcd, struct urb *urb)  		switch (wValue & 0xff00) {  		case USB_DT_DEVICE << 8:  			switch (hcd->speed) { +			case HCD_USB32:  			case HCD_USB31:  				bufp = usb31_rh_dev_descriptor;  				break; @@ -592,6 +592,7 @@ static int rh_call_control (struct usb_hcd *hcd, struct urb *urb)  			break;  		case USB_DT_CONFIG << 8:  			switch (hcd->speed) { +			case HCD_USB32:  			case HCD_USB31:  			case HCD_USB3:  				bufp = ss_rh_config_descriptor; @@ -2742,34 +2743,14 @@ int usb_add_hcd(struct usb_hcd *hcd,  	int retval;  	struct usb_device *rhdev; -	if (IS_ENABLED(CONFIG_USB_PHY) && !hcd->skip_phy_initialization) { -		struct usb_phy *phy = usb_get_phy_dev(hcd->self.sysdev, 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->usb_phy = phy; -			hcd->remove_phy = 1; -		} -	} -  	if (!hcd->skip_phy_initialization && usb_hcd_is_primary_hcd(hcd)) {  		hcd->phy_roothub = usb_phy_roothub_alloc(hcd->self.sysdev); -		if (IS_ERR(hcd->phy_roothub)) { -			retval = PTR_ERR(hcd->phy_roothub); -			goto err_phy_roothub_alloc; -		} +		if (IS_ERR(hcd->phy_roothub)) +			return PTR_ERR(hcd->phy_roothub);  		retval = usb_phy_roothub_init(hcd->phy_roothub);  		if (retval) -			goto err_phy_roothub_alloc; +			return retval;  		retval = usb_phy_roothub_power_on(hcd->phy_roothub);  		if (retval) @@ -2819,6 +2800,9 @@ int usb_add_hcd(struct usb_hcd *hcd,  	hcd->self.root_hub = rhdev;  	mutex_unlock(&usb_port_peer_mutex); +	rhdev->rx_lanes = 1; +	rhdev->tx_lanes = 1; +  	switch (hcd->speed) {  	case HCD_USB11:  		rhdev->speed = USB_SPEED_FULL; @@ -2832,6 +2816,10 @@ int usb_add_hcd(struct usb_hcd *hcd,  	case HCD_USB3:  		rhdev->speed = USB_SPEED_SUPER;  		break; +	case HCD_USB32: +		rhdev->rx_lanes = 2; +		rhdev->tx_lanes = 2; +		/* fall through */  	case HCD_USB31:  		rhdev->speed = USB_SPEED_SUPER_PLUS;  		break; @@ -2943,12 +2931,7 @@ err_create_buf:  	usb_phy_roothub_power_off(hcd->phy_roothub);  err_usb_phy_roothub_power_on:  	usb_phy_roothub_exit(hcd->phy_roothub); -err_phy_roothub_alloc: -	if (hcd->remove_phy && hcd->usb_phy) { -		usb_phy_shutdown(hcd->usb_phy); -		usb_put_phy(hcd->usb_phy); -		hcd->usb_phy = NULL; -	} +  	return retval;  }  EXPORT_SYMBOL_GPL(usb_add_hcd); @@ -3024,12 +3007,6 @@ void usb_remove_hcd(struct usb_hcd *hcd)  	usb_phy_roothub_power_off(hcd->phy_roothub);  	usb_phy_roothub_exit(hcd->phy_roothub); -	if (hcd->remove_phy && hcd->usb_phy) { -		usb_phy_shutdown(hcd->usb_phy); -		usb_put_phy(hcd->usb_phy); -		hcd->usb_phy = NULL; -	} -  	usb_put_invalidate_rhdev(hcd);  	hcd->flags = 0;  } diff --git a/drivers/usb/core/hub.c b/drivers/usb/core/hub.c index aa9968d90a48..fcae521df29b 100644 --- a/drivers/usb/core/hub.c +++ b/drivers/usb/core/hub.c @@ -1376,7 +1376,7 @@ static int hub_configure(struct usb_hub *hub,  	dev_info(hub_dev, "%d port%s detected\n", maxchild,  			(maxchild == 1) ? "" : "s"); -	hub->ports = kzalloc(maxchild * sizeof(struct usb_port *), GFP_KERNEL); +	hub->ports = kcalloc(maxchild, sizeof(struct usb_port *), GFP_KERNEL);  	if (!hub->ports) {  		ret = -ENOMEM;  		goto fail; @@ -2636,7 +2636,7 @@ static unsigned hub_is_wusb(struct usb_hub *hub)  #define SET_ADDRESS_TRIES	2  #define GET_DESCRIPTOR_TRIES	2  #define SET_CONFIG_TRIES	(2 * (use_both_schemes + 1)) -#define USE_NEW_SCHEME(i)	((i) / 2 == (int)old_scheme_first) +#define USE_NEW_SCHEME(i, scheme)	((i) / 2 == (int)scheme)  #define HUB_ROOT_RESET_TIME	60	/* times are in msec */  #define HUB_SHORT_RESET_TIME	10 @@ -2651,12 +2651,16 @@ static unsigned hub_is_wusb(struct usb_hub *hub)   * enumeration failures, so disable this enumeration scheme for USB3   * devices.   */ -static bool use_new_scheme(struct usb_device *udev, int retry) +static bool use_new_scheme(struct usb_device *udev, int retry, +			   struct usb_port *port_dev)  { +	int old_scheme_first_port = +		port_dev->quirks & USB_PORT_QUIRK_OLD_SCHEME; +  	if (udev->speed >= USB_SPEED_SUPER)  		return false; -	return USE_NEW_SCHEME(retry); +	return USE_NEW_SCHEME(retry, old_scheme_first_port || old_scheme_first);  }  /* Is a USB 3.0 port in the Inactive or Compliance Mode state? @@ -2751,6 +2755,14 @@ static int hub_port_wait_reset(struct usb_hub *hub, int port1,  	if (!udev)  		return 0; +	if (hub_is_superspeedplus(hub->hdev)) { +		/* extended portstatus Rx and Tx lane count are zero based */ +		udev->rx_lanes = USB_EXT_PORT_RX_LANES(ext_portstatus) + 1; +		udev->tx_lanes = USB_EXT_PORT_TX_LANES(ext_portstatus) + 1; +	} else { +		udev->rx_lanes = 1; +		udev->tx_lanes = 1; +	}  	if (hub_is_wusb(hub))  		udev->speed = USB_SPEED_WIRELESS;  	else if (hub_is_superspeedplus(hub->hdev) && @@ -2867,7 +2879,11 @@ static int hub_port_reset(struct usb_hub *hub, int port1,  done:  	if (status == 0) {  		/* TRSTRCY = 10 ms; plus some extra */ -		msleep(10 + 40); +		if (port_dev->quirks & USB_PORT_QUIRK_FAST_ENUM) +			usleep_range(10000, 12000); +		else +			msleep(10 + 40); +  		if (udev) {  			struct usb_hcd *hcd = bus_to_hcd(udev->bus); @@ -3376,6 +3392,10 @@ static int wait_for_connected(struct usb_device *udev,  	while (delay_ms < 2000) {  		if (status || *portstatus & USB_PORT_STAT_CONNECTION)  			break; +		if (!port_is_power_on(hub, *portstatus)) { +			status = -ENODEV; +			break; +		}  		msleep(20);  		delay_ms += 20;  		status = hub_port_status(hub, *port1, portstatus, portchange); @@ -4380,6 +4400,7 @@ hub_port_init(struct usb_hub *hub, struct usb_device *udev, int port1,  {  	struct usb_device	*hdev = hub->hdev;  	struct usb_hcd		*hcd = bus_to_hcd(hdev->bus); +	struct usb_port		*port_dev = hub->ports[port1 - 1];  	int			retries, operations, retval, i;  	unsigned		delay = HUB_SHORT_RESET_TIME;  	enum usb_device_speed	oldspeed = udev->speed; @@ -4501,7 +4522,7 @@ hub_port_init(struct usb_hub *hub, struct usb_device *udev, int port1,  	for (retries = 0; retries < GET_DESCRIPTOR_TRIES; (++retries, msleep(100))) {  		bool did_new_scheme = false; -		if (use_new_scheme(udev, retry_counter)) { +		if (use_new_scheme(udev, retry_counter, port_dev)) {  			struct usb_device_descriptor *buf;  			int r = 0; @@ -4551,7 +4572,9 @@ hub_port_init(struct usb_hub *hub, struct usb_device *udev, int port1,  				 * reset. But only on the first attempt,  				 * lest we get into a time out/reset loop  				 */ -				if (r == 0  || (r == -ETIMEDOUT && retries == 0)) +				if (r == 0 || (r == -ETIMEDOUT && +						retries == 0 && +						udev->speed > USB_SPEED_FULL))  					break;  			}  			udev->descriptor.bMaxPacketSize0 = @@ -4598,9 +4621,12 @@ hub_port_init(struct usb_hub *hub, struct usb_device *udev, int port1,  			if (udev->speed >= USB_SPEED_SUPER) {  				devnum = udev->devnum;  				dev_info(&udev->dev, -						"%s SuperSpeed%s USB device number %d using %s\n", +						"%s SuperSpeed%s%s USB device number %d using %s\n",  						(udev->config) ? "reset" : "new", -					 (udev->speed == USB_SPEED_SUPER_PLUS) ? "Plus" : "", +					 (udev->speed == USB_SPEED_SUPER_PLUS) ? +							"Plus Gen 2" : " Gen 1", +					 (udev->rx_lanes == 2 && udev->tx_lanes == 2) ? +							"x2" : "",  					 devnum, driver_name);  			} diff --git a/drivers/usb/core/hub.h b/drivers/usb/core/hub.h index 4dc769ee9c74..4accfb63f7dc 100644 --- a/drivers/usb/core/hub.h +++ b/drivers/usb/core/hub.h @@ -98,6 +98,7 @@ struct usb_port {  	struct mutex status_lock;  	u32 over_current_count;  	u8 portnum; +	u32 quirks;  	unsigned int is_superspeed:1;  	unsigned int usb3_lpm_u1_permit:1;  	unsigned int usb3_lpm_u2_permit:1; diff --git a/drivers/usb/core/message.c b/drivers/usb/core/message.c index 0c11d40a12bc..1a15392326fc 100644 --- a/drivers/usb/core/message.c +++ b/drivers/usb/core/message.c @@ -390,7 +390,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_array(io->entries, sizeof(*io->urbs), mem_flags);  	if (!io->urbs)  		goto nomem; @@ -940,7 +940,7 @@ int usb_set_isoch_delay(struct usb_device *dev)  	return usb_control_msg(dev, usb_sndctrlpipe(dev, 0),  			USB_REQ_SET_ISOCH_DELAY,  			USB_DIR_OUT | USB_TYPE_STANDARD | USB_RECIP_DEVICE, -			cpu_to_le16(dev->hub_delay), 0, NULL, 0, +			dev->hub_delay, 0, NULL, 0,  			USB_CTRL_SET_TIMEOUT);  } @@ -1824,8 +1824,8 @@ int usb_set_configuration(struct usb_device *dev, int configuration)  	n = nintf = 0;  	if (cp) {  		nintf = cp->desc.bNumInterfaces; -		new_interfaces = kmalloc(nintf * sizeof(*new_interfaces), -				GFP_NOIO); +		new_interfaces = kmalloc_array(nintf, sizeof(*new_interfaces), +					       GFP_NOIO);  		if (!new_interfaces)  			return -ENOMEM; diff --git a/drivers/usb/core/port.c b/drivers/usb/core/port.c index 6979bde87d31..4a2143195395 100644 --- a/drivers/usb/core/port.c +++ b/drivers/usb/core/port.c @@ -50,6 +50,28 @@ static ssize_t over_current_count_show(struct device *dev,  }  static DEVICE_ATTR_RO(over_current_count); +static ssize_t quirks_show(struct device *dev, +			   struct device_attribute *attr, char *buf) +{ +	struct usb_port *port_dev = to_usb_port(dev); + +	return sprintf(buf, "%08x\n", port_dev->quirks); +} + +static ssize_t quirks_store(struct device *dev, struct device_attribute *attr, +			    const char *buf, size_t count) +{ +	struct usb_port *port_dev = to_usb_port(dev); +	u32 value; + +	if (kstrtou32(buf, 16, &value)) +		return -EINVAL; + +	port_dev->quirks = value; +	return count; +} +static DEVICE_ATTR_RW(quirks); +  static ssize_t usb3_lpm_permit_show(struct device *dev,  			      struct device_attribute *attr, char *buf)  { @@ -118,6 +140,7 @@ static DEVICE_ATTR_RW(usb3_lpm_permit);  static struct attribute *port_dev_attrs[] = {  	&dev_attr_connect_type.attr, +	&dev_attr_quirks.attr,  	&dev_attr_over_current_count.attr,  	NULL,  }; diff --git a/drivers/usb/core/quirks.c b/drivers/usb/core/quirks.c index c55def2f1320..097057d2eacf 100644 --- a/drivers/usb/core/quirks.c +++ b/drivers/usb/core/quirks.c @@ -378,6 +378,10 @@ static const struct usb_device_id usb_quirk_list[] = {  	/* Corsair K70 RGB */  	{ USB_DEVICE(0x1b1c, 0x1b13), .driver_info = USB_QUIRK_DELAY_INIT }, +	/* Corsair Strafe */ +	{ USB_DEVICE(0x1b1c, 0x1b15), .driver_info = USB_QUIRK_DELAY_INIT | +	  USB_QUIRK_DELAY_CTRL_MSG }, +  	/* Corsair Strafe RGB */  	{ USB_DEVICE(0x1b1c, 0x1b20), .driver_info = USB_QUIRK_DELAY_INIT |  	  USB_QUIRK_DELAY_CTRL_MSG }, diff --git a/drivers/usb/core/sysfs.c b/drivers/usb/core/sysfs.c index 27bb34043053..ea18284dfa9a 100644 --- a/drivers/usb/core/sysfs.c +++ b/drivers/usb/core/sysfs.c @@ -175,6 +175,26 @@ static ssize_t speed_show(struct device *dev, struct device_attribute *attr,  }  static DEVICE_ATTR_RO(speed); +static ssize_t rx_lanes_show(struct device *dev, struct device_attribute *attr, +			  char *buf) +{ +	struct usb_device *udev; + +	udev = to_usb_device(dev); +	return sprintf(buf, "%d\n", udev->rx_lanes); +} +static DEVICE_ATTR_RO(rx_lanes); + +static ssize_t tx_lanes_show(struct device *dev, struct device_attribute *attr, +			  char *buf) +{ +	struct usb_device *udev; + +	udev = to_usb_device(dev); +	return sprintf(buf, "%d\n", udev->tx_lanes); +} +static DEVICE_ATTR_RO(tx_lanes); +  static ssize_t busnum_show(struct device *dev, struct device_attribute *attr,  			   char *buf)  { @@ -790,6 +810,8 @@ static struct attribute *dev_attrs[] = {  	&dev_attr_bNumConfigurations.attr,  	&dev_attr_bMaxPacketSize0.attr,  	&dev_attr_speed.attr, +	&dev_attr_rx_lanes.attr, +	&dev_attr_tx_lanes.attr,  	&dev_attr_busnum.attr,  	&dev_attr_devnum.attr,  	&dev_attr_devpath.attr, diff --git a/drivers/usb/core/usb.c b/drivers/usb/core/usb.c index 0adb6345ff2e..623be3174fb3 100644 --- a/drivers/usb/core/usb.c +++ b/drivers/usb/core/usb.c @@ -1167,30 +1167,16 @@ static struct notifier_block usb_bus_nb = {  struct dentry *usb_debug_root;  EXPORT_SYMBOL_GPL(usb_debug_root); -static struct dentry *usb_debug_devices; - -static int usb_debugfs_init(void) +static void usb_debugfs_init(void)  {  	usb_debug_root = debugfs_create_dir("usb", NULL); -	if (!usb_debug_root) -		return -ENOENT; - -	usb_debug_devices = debugfs_create_file("devices", 0444, -						usb_debug_root, NULL, -						&usbfs_devices_fops); -	if (!usb_debug_devices) { -		debugfs_remove(usb_debug_root); -		usb_debug_root = NULL; -		return -ENOENT; -	} - -	return 0; +	debugfs_create_file("devices", 0444, usb_debug_root, NULL, +			    &usbfs_devices_fops);  }  static void usb_debugfs_cleanup(void)  { -	debugfs_remove(usb_debug_devices); -	debugfs_remove(usb_debug_root); +	debugfs_remove_recursive(usb_debug_root);  }  /* @@ -1205,9 +1191,7 @@ static int __init usb_init(void)  	}  	usb_init_pool_max(); -	retval = usb_debugfs_init(); -	if (retval) -		goto out; +	usb_debugfs_init();  	usb_acpi_register();  	retval = bus_register(&usb_bus_type);  |