diff options
Diffstat (limited to 'drivers/usb/core/hub.c')
| -rw-r--r-- | drivers/usb/core/hub.c | 23 | 
1 files changed, 17 insertions, 6 deletions
diff --git a/drivers/usb/core/hub.c b/drivers/usb/core/hub.c index c6077d582d29..f76b2e0aba9d 100644 --- a/drivers/usb/core/hub.c +++ b/drivers/usb/core/hub.c @@ -2251,7 +2251,7 @@ static int usb_enumerate_device_otg(struct usb_device *udev)  		/* descriptor may appear anywhere in config */  		err = __usb_get_extra_descriptor(udev->rawdescriptors[0],  				le16_to_cpu(udev->config[0].desc.wTotalLength), -				USB_DT_OTG, (void **) &desc); +				USB_DT_OTG, (void **) &desc, sizeof(*desc));  		if (err || !(desc->bmAttributes & USB_OTG_HNP))  			return 0; @@ -2794,6 +2794,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]; +	int reset_recovery_time;  	if (!hub_is_superspeed(hub->hdev)) {  		if (warm) { @@ -2849,7 +2850,9 @@ static int hub_port_reset(struct usb_hub *hub, int port1,  					USB_PORT_FEAT_C_BH_PORT_RESET);  			usb_clear_port_feature(hub->hdev, port1,  					USB_PORT_FEAT_C_PORT_LINK_STATE); -			usb_clear_port_feature(hub->hdev, port1, + +			if (udev) +				usb_clear_port_feature(hub->hdev, port1,  					USB_PORT_FEAT_C_CONNECTION);  			/* @@ -2885,11 +2888,18 @@ static int hub_port_reset(struct usb_hub *hub, int port1,  done:  	if (status == 0) { -		/* TRSTRCY = 10 ms; plus some extra */  		if (port_dev->quirks & USB_PORT_QUIRK_FAST_ENUM)  			usleep_range(10000, 12000); -		else -			msleep(10 + 40); +		else { +			/* TRSTRCY = 10 ms; plus some extra */ +			reset_recovery_time = 10 + 40; + +			/* Hub needs extra delay after resetting its port. */ +			if (hub->hdev->quirks & USB_QUIRK_HUB_SLOW_RESET) +				reset_recovery_time += 100; + +			msleep(reset_recovery_time); +		}  		if (udev) {  			struct usb_hcd *hcd = bus_to_hcd(udev->bus); @@ -5153,7 +5163,7 @@ static void hub_port_connect_change(struct usb_hub *hub, int port1,  /* Handle notifying userspace about hub over-current events */  static void port_over_current_notify(struct usb_port *port_dev)  { -	static char *envp[] = { NULL, NULL, NULL }; +	char *envp[3];  	struct device *hub_dev;  	char *port_dev_path; @@ -5177,6 +5187,7 @@ static void port_over_current_notify(struct usb_port *port_dev)  	if (!envp[1])  		goto exit; +	envp[2] = NULL;  	kobject_uevent_env(&hub_dev->kobj, KOBJ_CHANGE, envp);  	kfree(envp[1]);  | 
