Merge 3.8-rc4 into usb-next

This pulls in all of the -rc4 fixes into usb-next to sync things up.

Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
diff --git a/drivers/usb/core/devices.c b/drivers/usb/core/devices.c
index cbacea9..e33224e 100644
--- a/drivers/usb/core/devices.c
+++ b/drivers/usb/core/devices.c
@@ -316,17 +316,23 @@
  */
 static char *usb_dump_config_descriptor(char *start, char *end,
 				const struct usb_config_descriptor *desc,
-				int active)
+				int active, int speed)
 {
+	int mul;
+
 	if (start > end)
 		return start;
+	if (speed == USB_SPEED_SUPER)
+		mul = 8;
+	else
+		mul = 2;
 	start += sprintf(start, format_config,
 			 /* mark active/actual/current cfg. */
 			 active ? '*' : ' ',
 			 desc->bNumInterfaces,
 			 desc->bConfigurationValue,
 			 desc->bmAttributes,
-			 desc->bMaxPower * 2);
+			 desc->bMaxPower * mul);
 	return start;
 }
 
@@ -342,7 +348,8 @@
 	if (!config)
 		/* getting these some in 2.3.7; none in 2.3.6 */
 		return start + sprintf(start, "(null Cfg. desc.)\n");
-	start = usb_dump_config_descriptor(start, end, &config->desc, active);
+	start = usb_dump_config_descriptor(start, end, &config->desc, active,
+			speed);
 	for (i = 0; i < USB_MAXIADS; i++) {
 		if (config->intf_assoc[i] == NULL)
 			break;
diff --git a/drivers/usb/core/generic.c b/drivers/usb/core/generic.c
index eff2010..271e761 100644
--- a/drivers/usb/core/generic.c
+++ b/drivers/usb/core/generic.c
@@ -100,7 +100,7 @@
 		 */
 
 		/* Rule out configs that draw too much bus current */
-		if (c->desc.bMaxPower * 2 > udev->bus_mA) {
+		if (usb_get_max_power(udev, c) > udev->bus_mA) {
 			insufficient_power++;
 			continue;
 		}
diff --git a/drivers/usb/core/hcd.c b/drivers/usb/core/hcd.c
index 4225d5e..5f6da8b 100644
--- a/drivers/usb/core/hcd.c
+++ b/drivers/usb/core/hcd.c
@@ -2506,7 +2506,6 @@
 	}
 
 	/* starting here, usbcore will pay attention to this root hub */
-	rhdev->bus_mA = min(500u, hcd->power_budget);
 	if ((retval = register_root_hub(hcd)) != 0)
 		goto err_register_root_hub;
 
diff --git a/drivers/usb/core/hub.c b/drivers/usb/core/hub.c
index 957ed2c..dc6ebd1 100644
--- a/drivers/usb/core/hub.c
+++ b/drivers/usb/core/hub.c
@@ -1351,6 +1351,8 @@
 	unsigned int pipe;
 	int maxp, ret, i;
 	char *message = "out of memory";
+	unsigned unit_load;
+	unsigned full_load;
 
 	hub->buffer = kmalloc(sizeof(*hub->buffer), GFP_KERNEL);
 	if (!hub->buffer) {
@@ -1397,6 +1399,13 @@
 	}
 
 	wHubCharacteristics = le16_to_cpu(hub->descriptor->wHubCharacteristics);
+	if (hub_is_superspeed(hdev)) {
+		unit_load = 150;
+		full_load = 900;
+	} else {
+		unit_load = 100;
+		full_load = 500;
+	}
 
 	/* FIXME for USB 3.0, skip for now */
 	if ((wHubCharacteristics & HUB_CHAR_COMPOUND) &&
@@ -1516,40 +1525,44 @@
 		goto fail;
 	}
 	le16_to_cpus(&hubstatus);
+	hcd = bus_to_hcd(hdev->bus);
 	if (hdev == hdev->bus->root_hub) {
-		if (hdev->bus_mA == 0 || hdev->bus_mA >= 500)
-			hub->mA_per_port = 500;
+		if (hcd->power_budget > 0)
+			hdev->bus_mA = hcd->power_budget;
+		else
+			hdev->bus_mA = full_load * hdev->maxchild;
+		if (hdev->bus_mA >= full_load)
+			hub->mA_per_port = full_load;
 		else {
 			hub->mA_per_port = hdev->bus_mA;
 			hub->limited_power = 1;
 		}
 	} else if ((hubstatus & (1 << USB_DEVICE_SELF_POWERED)) == 0) {
+		int remaining = hdev->bus_mA -
+			hub->descriptor->bHubContrCurrent;
+
 		dev_dbg(hub_dev, "hub controller current requirement: %dmA\n",
 			hub->descriptor->bHubContrCurrent);
 		hub->limited_power = 1;
-		if (hdev->maxchild > 0) {
-			int remaining = hdev->bus_mA -
-					hub->descriptor->bHubContrCurrent;
 
-			if (remaining < hdev->maxchild * 100)
-				dev_warn(hub_dev,
+		if (remaining < hdev->maxchild * unit_load)
+			dev_warn(hub_dev,
 					"insufficient power available "
 					"to use all downstream ports\n");
-			hub->mA_per_port = 100;		/* 7.2.1.1 */
-		}
+		hub->mA_per_port = unit_load;	/* 7.2.1 */
+
 	} else {	/* Self-powered external hub */
 		/* FIXME: What about battery-powered external hubs that
 		 * provide less current per port? */
-		hub->mA_per_port = 500;
+		hub->mA_per_port = full_load;
 	}
-	if (hub->mA_per_port < 500)
+	if (hub->mA_per_port < full_load)
 		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.
 	 */
-	hcd = bus_to_hcd(hdev->bus);
 	if (hcd->driver->update_hub_device) {
 		ret = hcd->driver->update_hub_device(hcd, hdev,
 				&hub->tt, GFP_KERNEL);
@@ -2535,77 +2548,9 @@
 			return ret;
 
 		/* The port state is unknown until the reset completes. */
-		if ((portstatus & USB_PORT_STAT_RESET))
-			goto delay;
+		if (!(portstatus & USB_PORT_STAT_RESET))
+			break;
 
-		/*
-		 * Some buggy devices require a warm reset to be issued even
-		 * when the port appears not to be connected.
-		 */
-		if (!warm) {
-			/*
-			 * Some buggy devices can cause an NEC host controller
-			 * to transition to the "Error" state after a hot port
-			 * reset.  This will show up as the port state in
-			 * "Inactive", and the port may also report a
-			 * disconnect.  Forcing a warm port reset seems to make
-			 * the device work.
-			 *
-			 * See https://bugzilla.kernel.org/show_bug.cgi?id=41752
-			 */
-			if (hub_port_warm_reset_required(hub, portstatus)) {
-				int ret;
-
-				if ((portchange & USB_PORT_STAT_C_CONNECTION))
-					clear_port_feature(hub->hdev, port1,
-							USB_PORT_FEAT_C_CONNECTION);
-				if (portchange & USB_PORT_STAT_C_LINK_STATE)
-					clear_port_feature(hub->hdev, port1,
-							USB_PORT_FEAT_C_PORT_LINK_STATE);
-				if (portchange & USB_PORT_STAT_C_RESET)
-					clear_port_feature(hub->hdev, port1,
-							USB_PORT_FEAT_C_RESET);
-				dev_dbg(hub->intfdev, "hot reset failed, warm reset port %d\n",
-						port1);
-				ret = hub_port_reset(hub, port1,
-						udev, HUB_BH_RESET_TIME,
-						true);
-				if ((portchange & USB_PORT_STAT_C_CONNECTION))
-					clear_port_feature(hub->hdev, port1,
-							USB_PORT_FEAT_C_CONNECTION);
-				return ret;
-			}
-			/* Device went away? */
-			if (!(portstatus & USB_PORT_STAT_CONNECTION))
-				return -ENOTCONN;
-
-			/* bomb out completely if the connection bounced */
-			if ((portchange & USB_PORT_STAT_C_CONNECTION))
-				return -ENOTCONN;
-
-			if ((portstatus & USB_PORT_STAT_ENABLE)) {
-				if (hub_is_wusb(hub))
-					udev->speed = USB_SPEED_WIRELESS;
-				else if (hub_is_superspeed(hub->hdev))
-					udev->speed = USB_SPEED_SUPER;
-				else if (portstatus & USB_PORT_STAT_HIGH_SPEED)
-					udev->speed = USB_SPEED_HIGH;
-				else if (portstatus & USB_PORT_STAT_LOW_SPEED)
-					udev->speed = USB_SPEED_LOW;
-				else
-					udev->speed = USB_SPEED_FULL;
-				return 0;
-			}
-		} else {
-			if (!(portstatus & USB_PORT_STAT_CONNECTION) ||
-					hub_port_warm_reset_required(hub,
-						portstatus))
-				return -ENOTCONN;
-
-			return 0;
-		}
-
-delay:
 		/* switch to the long delay after two short delay failures */
 		if (delay_time >= 2 * HUB_SHORT_RESET_TIME)
 			delay = HUB_LONG_RESET_TIME;
@@ -2615,20 +2560,54 @@
 			port1, warm ? "warm " : "", delay);
 	}
 
-	return -EBUSY;
+	if ((portstatus & USB_PORT_STAT_RESET))
+		return -EBUSY;
+
+	if (hub_port_warm_reset_required(hub, portstatus))
+		return -ENOTCONN;
+
+	/* Device went away? */
+	if (!(portstatus & USB_PORT_STAT_CONNECTION))
+		return -ENOTCONN;
+
+	/* bomb out completely if the connection bounced.  A USB 3.0
+	 * connection may bounce if multiple warm resets were issued,
+	 * but the device may have successfully re-connected. Ignore it.
+	 */
+	if (!hub_is_superspeed(hub->hdev) &&
+			(portchange & USB_PORT_STAT_C_CONNECTION))
+		return -ENOTCONN;
+
+	if (!(portstatus & USB_PORT_STAT_ENABLE))
+		return -EBUSY;
+
+	if (!udev)
+		return 0;
+
+	if (hub_is_wusb(hub))
+		udev->speed = USB_SPEED_WIRELESS;
+	else if (hub_is_superspeed(hub->hdev))
+		udev->speed = USB_SPEED_SUPER;
+	else if (portstatus & USB_PORT_STAT_HIGH_SPEED)
+		udev->speed = USB_SPEED_HIGH;
+	else if (portstatus & USB_PORT_STAT_LOW_SPEED)
+		udev->speed = USB_SPEED_LOW;
+	else
+		udev->speed = USB_SPEED_FULL;
+	return 0;
 }
 
 static void hub_port_finish_reset(struct usb_hub *hub, int port1,
-			struct usb_device *udev, int *status, bool warm)
+			struct usb_device *udev, int *status)
 {
 	switch (*status) {
 	case 0:
-		if (!warm) {
-			struct usb_hcd *hcd;
-			/* TRSTRCY = 10 ms; plus some extra */
-			msleep(10 + 40);
+		/* TRSTRCY = 10 ms; plus some extra */
+		msleep(10 + 40);
+		if (udev) {
+			struct usb_hcd *hcd = bus_to_hcd(udev->bus);
+
 			update_devnum(udev, 0);
-			hcd = bus_to_hcd(udev->bus);
 			/* The xHC may think the device is already reset,
 			 * so ignore the status.
 			 */
@@ -2640,14 +2619,15 @@
 	case -ENODEV:
 		clear_port_feature(hub->hdev,
 				port1, USB_PORT_FEAT_C_RESET);
-		/* FIXME need disconnect() for NOTATTACHED device */
 		if (hub_is_superspeed(hub->hdev)) {
 			clear_port_feature(hub->hdev, port1,
 					USB_PORT_FEAT_C_BH_PORT_RESET);
 			clear_port_feature(hub->hdev, port1,
 					USB_PORT_FEAT_C_PORT_LINK_STATE);
+			clear_port_feature(hub->hdev, port1,
+					USB_PORT_FEAT_C_CONNECTION);
 		}
-		if (!warm)
+		if (udev)
 			usb_set_device_state(udev, *status
 					? USB_STATE_NOTATTACHED
 					: USB_STATE_DEFAULT);
@@ -2660,18 +2640,30 @@
 			struct usb_device *udev, unsigned int delay, bool warm)
 {
 	int i, status;
+	u16 portchange, portstatus;
 
-	if (!warm) {
-		/* Block EHCI CF initialization during the port reset.
-		 * Some companion controllers don't like it when they mix.
-		 */
-		down_read(&ehci_cf_port_reset_rwsem);
-	} else {
-		if (!hub_is_superspeed(hub->hdev)) {
+	if (!hub_is_superspeed(hub->hdev)) {
+		if (warm) {
 			dev_err(hub->intfdev, "only USB3 hub support "
 						"warm reset\n");
 			return -EINVAL;
 		}
+		/* Block EHCI CF initialization during the port reset.
+		 * Some companion controllers don't like it when they mix.
+		 */
+		down_read(&ehci_cf_port_reset_rwsem);
+	} else if (!warm) {
+		/*
+		 * If the caller hasn't explicitly requested a warm reset,
+		 * double check and see if one is needed.
+		 */
+		status = hub_port_status(hub, port1,
+					&portstatus, &portchange);
+		if (status < 0)
+			goto done;
+
+		if (hub_port_warm_reset_required(hub, portstatus))
+			warm = true;
 	}
 
 	/* Reset the port */
@@ -2692,10 +2684,33 @@
 						status);
 		}
 
-		/* return on disconnect or reset */
+		/* Check for disconnect or reset */
 		if (status == 0 || status == -ENOTCONN || status == -ENODEV) {
-			hub_port_finish_reset(hub, port1, udev, &status, warm);
-			goto done;
+			hub_port_finish_reset(hub, port1, udev, &status);
+
+			if (!hub_is_superspeed(hub->hdev))
+				goto done;
+
+			/*
+			 * If a USB 3.0 device migrates from reset to an error
+			 * state, re-issue the warm reset.
+			 */
+			if (hub_port_status(hub, port1,
+					&portstatus, &portchange) < 0)
+				goto done;
+
+			if (!hub_port_warm_reset_required(hub, portstatus))
+				goto done;
+
+			/*
+			 * If the port is in SS.Inactive or Compliance Mode, the
+			 * hot or warm reset failed.  Try another warm reset.
+			 */
+			if (!warm) {
+				dev_dbg(hub->intfdev, "hot reset failed, warm reset port %d\n",
+						port1);
+				warm = true;
+			}
 		}
 
 		dev_dbg (hub->intfdev,
@@ -2709,7 +2724,7 @@
 		port1);
 
 done:
-	if (!warm)
+	if (!hub_is_superspeed(hub->hdev))
 		up_read(&ehci_cf_port_reset_rwsem);
 
 	return status;
@@ -2945,9 +2960,7 @@
 
 	/* see 7.1.7.6 */
 	if (hub_is_superspeed(hub->hdev))
-		status = set_port_feature(hub->hdev,
-				port1 | (USB_SS_PORT_LS_U3 << 3),
-				USB_PORT_FEAT_LINK_STATE);
+		status = hub_set_port_link_state(hub, port1, USB_SS_PORT_LS_U3);
 	else
 		status = set_port_feature(hub->hdev, port1,
 						USB_PORT_FEAT_SUSPEND);
@@ -3123,9 +3136,7 @@
 
 	/* see 7.1.7.7; affects power usage, but not budgeting */
 	if (hub_is_superspeed(hub->hdev))
-		status = set_port_feature(hub->hdev,
-				port1 | (USB_SS_PORT_LS_U0 << 3),
-				USB_PORT_FEAT_LINK_STATE);
+		status = hub_set_port_link_state(hub, port1, USB_SS_PORT_LS_U0);
 	else
 		status = clear_port_feature(hub->hdev,
 				port1, USB_PORT_FEAT_SUSPEND);
@@ -4212,16 +4223,23 @@
 	for (port1 = 1; port1 <= hdev->maxchild; ++port1) {
 		struct usb_device	*udev = hub->ports[port1 - 1]->child;
 		int			delta;
+		unsigned		unit_load;
 
 		if (!udev)
 			continue;
+		if (hub_is_superspeed(udev))
+			unit_load = 150;
+		else
+			unit_load = 100;
 
-		/* Unconfigured devices may not use more than 100mA,
-		 * or 8mA for OTG ports */
+		/*
+		 * Unconfigured devices may not use more than one unit load,
+		 * or 8mA for OTG ports
+		 */
 		if (udev->actconfig)
-			delta = udev->actconfig->desc.bMaxPower * 2;
+			delta = usb_get_max_power(udev, udev->actconfig);
 		else if (port1 != udev->bus->otg_port || hdev->parent)
-			delta = 100;
+			delta = unit_load;
 		else
 			delta = 8;
 		if (delta > hub->mA_per_port)
@@ -4256,6 +4274,7 @@
 			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",
@@ -4345,6 +4364,10 @@
   			goto done;
 		return;
 	}
+	if (hub_is_superspeed(hub->hdev))
+		unit_load = 150;
+	else
+		unit_load = 100;
 
 	for (i = 0; i < SET_CONFIG_TRIES; i++) {
 
@@ -4392,7 +4415,7 @@
 		 * on the parent.
 		 */
 		if (udev->descriptor.bDeviceClass == USB_CLASS_HUB
-				&& udev->bus_mA <= 100) {
+				&& udev->bus_mA <= unit_load) {
 			u16	devstat;
 
 			status = usb_get_status(udev, USB_RECIP_DEVICE, 0,
@@ -4706,12 +4729,21 @@
 			 */
 			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);
-				status = hub_port_reset(hub, i, NULL,
-						HUB_BH_RESET_TIME, true);
-				if (status < 0)
-					hub_port_disable(hub, i, 1);
+				if (!udev) {
+					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;
 			}
 
diff --git a/drivers/usb/core/message.c b/drivers/usb/core/message.c
index 131f736..444d30e 100644
--- a/drivers/usb/core/message.c
+++ b/drivers/usb/core/message.c
@@ -1751,7 +1751,7 @@
 			}
 		}
 
-		i = dev->bus_mA - cp->desc.bMaxPower * 2;
+		i = dev->bus_mA - usb_get_max_power(dev, cp);
 		if (i < 0)
 			dev_warn(&dev->dev, "new config #%d exceeds power "
 					"limit by %dmA\n",
diff --git a/drivers/usb/core/sysfs.c b/drivers/usb/core/sysfs.c
index 818e4a0..3f81a3d 100644
--- a/drivers/usb/core/sysfs.c
+++ b/drivers/usb/core/sysfs.c
@@ -17,7 +17,7 @@
 #include "usb.h"
 
 /* Active configuration fields */
-#define usb_actconfig_show(field, multiplier, format_string)		\
+#define usb_actconfig_show(field, format_string)			\
 static ssize_t  show_##field(struct device *dev,			\
 		struct device_attribute *attr, char *buf)		\
 {									\
@@ -28,18 +28,31 @@
 	actconfig = udev->actconfig;					\
 	if (actconfig)							\
 		return sprintf(buf, format_string,			\
-				actconfig->desc.field * multiplier);	\
+				actconfig->desc.field);			\
 	else								\
 		return 0;						\
 }									\
 
-#define usb_actconfig_attr(field, multiplier, format_string)		\
-usb_actconfig_show(field, multiplier, format_string)			\
-static DEVICE_ATTR(field, S_IRUGO, show_##field, NULL);
+#define usb_actconfig_attr(field, format_string)		\
+	usb_actconfig_show(field, format_string)		\
+	static DEVICE_ATTR(field, S_IRUGO, show_##field, NULL);
 
-usb_actconfig_attr(bNumInterfaces, 1, "%2d\n")
-usb_actconfig_attr(bmAttributes, 1, "%2x\n")
-usb_actconfig_attr(bMaxPower, 2, "%3dmA\n")
+usb_actconfig_attr(bNumInterfaces, "%2d\n")
+usb_actconfig_attr(bmAttributes, "%2x\n")
+
+static ssize_t show_bMaxPower(struct device *dev,
+		struct device_attribute *attr, char *buf)
+{
+	struct usb_device *udev;
+	struct usb_host_config *actconfig;
+
+	udev = to_usb_device(dev);
+	actconfig = udev->actconfig;
+	if (!actconfig)
+		return 0;
+	return sprintf(buf, "%dmA\n", usb_get_max_power(udev, actconfig));
+}
+static DEVICE_ATTR(bMaxPower, S_IRUGO, show_bMaxPower, NULL);
 
 static ssize_t show_configuration_string(struct device *dev,
 		struct device_attribute *attr, char *buf)
@@ -56,7 +69,7 @@
 static DEVICE_ATTR(configuration, S_IRUGO, show_configuration_string, NULL);
 
 /* configuration value is always present, and r/w */
-usb_actconfig_show(bConfigurationValue, 1, "%u\n");
+usb_actconfig_show(bConfigurationValue, "%u\n");
 
 static ssize_t
 set_bConfigurationValue(struct device *dev, struct device_attribute *attr,
diff --git a/drivers/usb/core/usb.h b/drivers/usb/core/usb.h
index 1c528c1..fb7d8fcb 100644
--- a/drivers/usb/core/usb.h
+++ b/drivers/usb/core/usb.h
@@ -38,6 +38,15 @@
 extern int usb_set_configuration(struct usb_device *dev, int configuration);
 extern int usb_choose_configuration(struct usb_device *udev);
 
+static inline unsigned usb_get_max_power(struct usb_device *udev,
+		struct usb_host_config *c)
+{
+	/* SuperSpeed power is in 8 mA units; others are in 2 mA units */
+	unsigned mul = (udev->speed == USB_SPEED_SUPER ? 8 : 2);
+
+	return c->desc.bMaxPower * mul;
+}
+
 extern void usb_kick_khubd(struct usb_device *dev);
 extern int usb_match_one_id_intf(struct usb_device *dev,
 				 struct usb_host_interface *intf,
diff --git a/drivers/usb/host/ehci-mxc.c b/drivers/usb/host/ehci-mxc.c
index ec7f5d2..6b8c158 100644
--- a/drivers/usb/host/ehci-mxc.c
+++ b/drivers/usb/host/ehci-mxc.c
@@ -94,7 +94,6 @@
 	struct usb_hcd *hcd;
 	struct resource *res;
 	int irq, ret;
-	unsigned int flags;
 	struct ehci_mxc_priv *priv;
 	struct device *dev = &pdev->dev;
 	struct ehci_hcd *ehci;
@@ -205,25 +204,6 @@
 	if (ret)
 		goto err_add;
 
-	if (pdata->otg) {
-		/*
-		 * efikamx and efikasb have some hardware bug which is
-		 * preventing usb to work unless CHRGVBUS is set.
-		 * It's in violation of USB specs
-		 */
-		if (machine_is_mx51_efikamx() || machine_is_mx51_efikasb()) {
-			flags = usb_phy_io_read(pdata->otg,
-							ULPI_OTG_CTRL);
-			flags |= ULPI_OTG_CTRL_CHRGVBUS;
-			ret = usb_phy_io_write(pdata->otg, flags,
-							ULPI_OTG_CTRL);
-			if (ret) {
-				dev_err(dev, "unable to set CHRVBUS\n");
-				goto err_add;
-			}
-		}
-	}
-
 	return 0;
 
 err_add:
diff --git a/drivers/usb/host/ohci-q.c b/drivers/usb/host/ohci-q.c
index 7482cfb..88731b7 100644
--- a/drivers/usb/host/ohci-q.c
+++ b/drivers/usb/host/ohci-q.c
@@ -44,6 +44,7 @@
 	// ASSERT (urb->hcpriv != 0);
 
 	urb_free_priv (ohci, urb->hcpriv);
+	urb->hcpriv = NULL;
 	if (likely(status == -EINPROGRESS))
 		status = 0;
 
diff --git a/drivers/usb/host/xhci-ring.c b/drivers/usb/host/xhci-ring.c
index 59fb5c6..f697209 100644
--- a/drivers/usb/host/xhci-ring.c
+++ b/drivers/usb/host/xhci-ring.c
@@ -2706,13 +2706,11 @@
 {
 	struct xhci_hcd *xhci = hcd_to_xhci(hcd);
 	u32 status;
-	union xhci_trb *trb;
 	u64 temp_64;
 	union xhci_trb *event_ring_deq;
 	dma_addr_t deq;
 
 	spin_lock(&xhci->lock);
-	trb = xhci->event_ring->dequeue;
 	/* Check if the xHC generated the interrupt, or the irq is shared */
 	status = xhci_readl(xhci, &xhci->op_regs->status);
 	if (status == 0xffffffff)
diff --git a/drivers/usb/misc/Kconfig b/drivers/usb/misc/Kconfig
index fecde69..3b1a3f4 100644
--- a/drivers/usb/misc/Kconfig
+++ b/drivers/usb/misc/Kconfig
@@ -250,3 +250,9 @@
 	help
 	  Say Y here if you need EZUSB device support.
 	  (Cypress FX/FX2/FX2LP microcontrollers)
+
+config USB_HSIC_USB3503
+       tristate "USB3503 HSIC to USB20 Driver"
+       depends on I2C
+       help
+         This option enables support for SMSC USB3503 HSIC to USB 2.0 Driver.
diff --git a/drivers/usb/misc/Makefile b/drivers/usb/misc/Makefile
index 3e99a64..3e1bd70 100644
--- a/drivers/usb/misc/Makefile
+++ b/drivers/usb/misc/Makefile
@@ -26,5 +26,6 @@
 obj-$(CONFIG_USB_USS720)		+= uss720.o
 obj-$(CONFIG_USB_SEVSEG)		+= usbsevseg.o
 obj-$(CONFIG_USB_YUREX)			+= yurex.o
+obj-$(CONFIG_USB_HSIC_USB3503)		+= usb3503.o
 
 obj-$(CONFIG_USB_SISUSBVGA)		+= sisusbvga/
diff --git a/drivers/usb/misc/usb3503.c b/drivers/usb/misc/usb3503.c
new file mode 100644
index 0000000..dc2c993
--- /dev/null
+++ b/drivers/usb/misc/usb3503.c
@@ -0,0 +1,304 @@
+/*
+ * Driver for SMSC USB3503 USB 2.0 hub controller driver
+ *
+ * Copyright (c) 2012-2013 Dongjin Kim (tobetter@gmail.com)
+ *
+ * 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 option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
+ */
+
+#include <linux/i2c.h>
+#include <linux/gpio.h>
+#include <linux/delay.h>
+#include <linux/slab.h>
+#include <linux/module.h>
+#include <linux/platform_device.h>
+#include <linux/platform_data/usb3503.h>
+
+#define USB3503_VIDL		0x00
+#define USB3503_VIDM		0x01
+#define USB3503_PIDL		0x02
+#define USB3503_PIDM		0x03
+#define USB3503_DIDL		0x04
+#define USB3503_DIDM		0x05
+
+#define USB3503_CFG1		0x06
+#define USB3503_SELF_BUS_PWR	(1 << 7)
+
+#define USB3503_CFG2		0x07
+#define USB3503_CFG3		0x08
+#define USB3503_NRD		0x09
+
+#define USB3503_PDS		0x0a
+#define USB3503_PORT1		(1 << 1)
+#define USB3503_PORT2		(1 << 2)
+#define USB3503_PORT3		(1 << 3)
+
+#define USB3503_SP_ILOCK	0xe7
+#define USB3503_SPILOCK_CONNECT	(1 << 1)
+#define USB3503_SPILOCK_CONFIG	(1 << 0)
+
+#define USB3503_CFGP		0xee
+#define USB3503_CLKSUSP		(1 << 7)
+
+struct usb3503 {
+	enum usb3503_mode	mode;
+	struct i2c_client	*client;
+	int	gpio_intn;
+	int	gpio_reset;
+	int	gpio_connect;
+};
+
+static int usb3503_write_register(struct i2c_client *client,
+		char reg, char data)
+{
+	return i2c_smbus_write_byte_data(client, reg, data);
+}
+
+static int usb3503_read_register(struct i2c_client *client, char reg)
+{
+	return i2c_smbus_read_byte_data(client, reg);
+}
+
+static int usb3503_set_bits(struct i2c_client *client, char reg, char req)
+{
+	int err;
+
+	err = usb3503_read_register(client, reg);
+	if (err < 0)
+		return err;
+
+	err = usb3503_write_register(client, reg, err | req);
+	if (err < 0)
+		return err;
+
+	return 0;
+}
+
+static int usb3503_clear_bits(struct i2c_client *client, char reg, char req)
+{
+	int err;
+
+	err = usb3503_read_register(client, reg);
+	if (err < 0)
+		return err;
+
+	err = usb3503_write_register(client, reg, err & ~req);
+	if (err < 0)
+		return err;
+
+	return 0;
+}
+
+static int usb3503_reset(int gpio_reset, int state)
+{
+	if (gpio_is_valid(gpio_reset))
+		gpio_set_value(gpio_reset, state);
+
+	/* Wait RefClk when RESET_N is released, otherwise Hub will
+	 * not transition to Hub Communication Stage.
+	 */
+	if (state)
+		msleep(100);
+
+	return 0;
+}
+
+static int usb3503_switch_mode(struct usb3503 *hub, enum usb3503_mode mode)
+{
+	struct i2c_client *i2c = hub->client;
+	int err = 0;
+
+	switch (mode) {
+	case USB3503_MODE_HUB:
+		usb3503_reset(hub->gpio_reset, 1);
+
+		/* SP_ILOCK: set connect_n, config_n for config */
+		err = usb3503_write_register(i2c, USB3503_SP_ILOCK,
+				(USB3503_SPILOCK_CONNECT
+				 | USB3503_SPILOCK_CONFIG));
+		if (err < 0) {
+			dev_err(&i2c->dev, "SP_ILOCK failed (%d)\n", err);
+			goto err_hubmode;
+		}
+
+		/* PDS : Port2,3 Disable For Self Powered Operation */
+		err = usb3503_set_bits(i2c, USB3503_PDS,
+				(USB3503_PORT2 | USB3503_PORT3));
+		if (err < 0) {
+			dev_err(&i2c->dev, "PDS failed (%d)\n", err);
+			goto err_hubmode;
+		}
+
+		/* CFG1 : SELF_BUS_PWR -> Self-Powerd operation */
+		err = usb3503_set_bits(i2c, USB3503_CFG1, USB3503_SELF_BUS_PWR);
+		if (err < 0) {
+			dev_err(&i2c->dev, "CFG1 failed (%d)\n", err);
+			goto err_hubmode;
+		}
+
+		/* SP_LOCK: clear connect_n, config_n for hub connect */
+		err = usb3503_clear_bits(i2c, USB3503_SP_ILOCK,
+				(USB3503_SPILOCK_CONNECT
+				 | USB3503_SPILOCK_CONFIG));
+		if (err < 0) {
+			dev_err(&i2c->dev, "SP_ILOCK failed (%d)\n", err);
+			goto err_hubmode;
+		}
+
+		hub->mode = mode;
+		dev_info(&i2c->dev, "switched to HUB mode\n");
+		break;
+
+	case USB3503_MODE_STANDBY:
+		usb3503_reset(hub->gpio_reset, 0);
+
+		hub->mode = mode;
+		dev_info(&i2c->dev, "switched to STANDBY mode\n");
+		break;
+
+	default:
+		dev_err(&i2c->dev, "unknown mode is request\n");
+		err = -EINVAL;
+		break;
+	}
+
+err_hubmode:
+	return err;
+}
+
+static int usb3503_probe(struct i2c_client *i2c, const struct i2c_device_id *id)
+{
+	struct usb3503_platform_data *pdata = i2c->dev.platform_data;
+	struct usb3503 *hub;
+	int err = -ENOMEM;
+
+	hub = kzalloc(sizeof(struct usb3503), GFP_KERNEL);
+	if (!hub) {
+		dev_err(&i2c->dev, "private data alloc fail\n");
+		return err;
+	}
+
+	i2c_set_clientdata(i2c, hub);
+	hub->client = i2c;
+
+	if (!pdata) {
+		dev_dbg(&i2c->dev, "missing platform data\n");
+		goto err_out;
+	} else {
+		hub->gpio_intn		= pdata->gpio_intn;
+		hub->gpio_connect	= pdata->gpio_connect;
+		hub->gpio_reset		= pdata->gpio_reset;
+		hub->mode		= pdata->initial_mode;
+	}
+
+	if (gpio_is_valid(hub->gpio_intn)) {
+		err = gpio_request_one(hub->gpio_intn,
+				GPIOF_OUT_INIT_HIGH, "usb3503 intn");
+		if (err) {
+			dev_err(&i2c->dev,
+					"unable to request GPIO %d as connect pin (%d)\n",
+					hub->gpio_intn, err);
+			goto err_out;
+		}
+	}
+
+	if (gpio_is_valid(hub->gpio_connect)) {
+		err = gpio_request_one(hub->gpio_connect,
+				GPIOF_OUT_INIT_HIGH, "usb3503 connect");
+		if (err) {
+			dev_err(&i2c->dev,
+					"unable to request GPIO %d as connect pin (%d)\n",
+					hub->gpio_connect, err);
+			goto err_gpio_connect;
+		}
+	}
+
+	if (gpio_is_valid(hub->gpio_reset)) {
+		err = gpio_request_one(hub->gpio_reset,
+				GPIOF_OUT_INIT_LOW, "usb3503 reset");
+		if (err) {
+			dev_err(&i2c->dev,
+					"unable to request GPIO %d as reset pin (%d)\n",
+					hub->gpio_reset, err);
+			goto err_gpio_reset;
+		}
+	}
+
+	usb3503_switch_mode(hub, pdata->initial_mode);
+
+	dev_info(&i2c->dev, "%s: probed on  %s mode\n", __func__,
+			(hub->mode == USB3503_MODE_HUB) ? "hub" : "standby");
+
+	return 0;
+
+err_gpio_reset:
+	if (gpio_is_valid(hub->gpio_connect))
+		gpio_free(hub->gpio_connect);
+err_gpio_connect:
+	if (gpio_is_valid(hub->gpio_intn))
+		gpio_free(hub->gpio_intn);
+err_out:
+	kfree(hub);
+
+	return err;
+}
+
+static int usb3503_remove(struct i2c_client *i2c)
+{
+	struct usb3503 *hub = i2c_get_clientdata(i2c);
+
+	if (gpio_is_valid(hub->gpio_intn))
+		gpio_free(hub->gpio_intn);
+	if (gpio_is_valid(hub->gpio_connect))
+		gpio_free(hub->gpio_connect);
+	if (gpio_is_valid(hub->gpio_reset))
+		gpio_free(hub->gpio_reset);
+
+	kfree(hub);
+
+	return 0;
+}
+
+static const struct i2c_device_id usb3503_id[] = {
+	{ USB3503_I2C_NAME, 0 },
+	{ }
+};
+MODULE_DEVICE_TABLE(i2c, usb3503_id);
+
+static struct i2c_driver usb3503_driver = {
+	.driver = {
+		.name = USB3503_I2C_NAME,
+	},
+	.probe		= usb3503_probe,
+	.remove		= usb3503_remove,
+	.id_table	= usb3503_id,
+};
+
+static int __init usb3503_init(void)
+{
+	return i2c_add_driver(&usb3503_driver);
+}
+
+static void __exit usb3503_exit(void)
+{
+	i2c_del_driver(&usb3503_driver);
+}
+
+module_init(usb3503_init);
+module_exit(usb3503_exit);
+
+MODULE_AUTHOR("Dongjin Kim <tobetter@gmail.com>");
+MODULE_DESCRIPTION("USB3503 USB HUB driver");
+MODULE_LICENSE("GPL");
diff --git a/drivers/usb/serial/keyspan.c b/drivers/usb/serial/keyspan.c
index 97bc49f..3d95637 100644
--- a/drivers/usb/serial/keyspan.c
+++ b/drivers/usb/serial/keyspan.c
@@ -298,7 +298,7 @@
 	endpoint = usb_pipeendpoint(urb->pipe);
 
 	if (status) {
-		dev_dbg(&urb->dev->dev,"%s - nonzero status: %x on endpoint %d.\n",
+		dev_dbg(&urb->dev->dev, "%s - nonzero status: %x on endpoint %d.\n",
 			__func__, status, endpoint);
 		return;
 	}
@@ -532,7 +532,7 @@
 
 	/*
 	dev_dbg(&urb->dev->dev,
-	  	"%s %x %x %x %x %x %x %x %x %x %x %x %x", __func__,
+		"%s %x %x %x %x %x %x %x %x %x %x %x %x", __func__,
 		data[0], data[1], data[2], data[3], data[4], data[5],
 		data[6], data[7], data[8], data[9], data[10], data[11]);
 	*/
diff --git a/drivers/usb/storage/uas.c b/drivers/usb/storage/uas.c
index 98b98ee..ebb9972 100644
--- a/drivers/usb/storage/uas.c
+++ b/drivers/usb/storage/uas.c
@@ -66,6 +66,8 @@
 	DATA_OUT_URB_INFLIGHT   = (1 << 10),
 	COMMAND_COMPLETED       = (1 << 11),
 	COMMAND_ABORTED         = (1 << 12),
+	UNLINK_DATA_URBS        = (1 << 13),
+	IS_IN_WORK_LIST         = (1 << 14),
 };
 
 /* Overrides scsi_pointer */
@@ -82,11 +84,36 @@
 static int uas_submit_urbs(struct scsi_cmnd *cmnd,
 				struct uas_dev_info *devinfo, gfp_t gfp);
 static void uas_do_work(struct work_struct *work);
+static int uas_try_complete(struct scsi_cmnd *cmnd, const char *caller);
 
 static DECLARE_WORK(uas_work, uas_do_work);
 static DEFINE_SPINLOCK(uas_work_lock);
 static LIST_HEAD(uas_work_list);
 
+static void uas_unlink_data_urbs(struct uas_dev_info *devinfo,
+				 struct uas_cmd_info *cmdinfo)
+{
+	unsigned long flags;
+
+	/*
+	 * The UNLINK_DATA_URBS flag makes sure uas_try_complete
+	 * (called by urb completion) doesn't release cmdinfo
+	 * underneath us.
+	 */
+	spin_lock_irqsave(&devinfo->lock, flags);
+	cmdinfo->state |= UNLINK_DATA_URBS;
+	spin_unlock_irqrestore(&devinfo->lock, flags);
+
+	if (cmdinfo->data_in_urb)
+		usb_unlink_urb(cmdinfo->data_in_urb);
+	if (cmdinfo->data_out_urb)
+		usb_unlink_urb(cmdinfo->data_out_urb);
+
+	spin_lock_irqsave(&devinfo->lock, flags);
+	cmdinfo->state &= ~UNLINK_DATA_URBS;
+	spin_unlock_irqrestore(&devinfo->lock, flags);
+}
+
 static void uas_do_work(struct work_struct *work)
 {
 	struct uas_cmd_info *cmdinfo;
@@ -106,6 +133,8 @@
 		struct uas_dev_info *devinfo = (void *)cmnd->device->hostdata;
 		spin_lock_irqsave(&devinfo->lock, flags);
 		err = uas_submit_urbs(cmnd, cmnd->device->hostdata, GFP_ATOMIC);
+		if (!err)
+			cmdinfo->state &= ~IS_IN_WORK_LIST;
 		spin_unlock_irqrestore(&devinfo->lock, flags);
 		if (err) {
 			list_del(&cmdinfo->list);
@@ -117,6 +146,45 @@
 	}
 }
 
+static void uas_abort_work(struct uas_dev_info *devinfo)
+{
+	struct uas_cmd_info *cmdinfo;
+	struct uas_cmd_info *temp;
+	struct list_head list;
+	unsigned long flags;
+
+	spin_lock_irq(&uas_work_lock);
+	list_replace_init(&uas_work_list, &list);
+	spin_unlock_irq(&uas_work_lock);
+
+	spin_lock_irqsave(&devinfo->lock, flags);
+	list_for_each_entry_safe(cmdinfo, temp, &list, list) {
+		struct scsi_pointer *scp = (void *)cmdinfo;
+		struct scsi_cmnd *cmnd = container_of(scp,
+							struct scsi_cmnd, SCp);
+		struct uas_dev_info *di = (void *)cmnd->device->hostdata;
+
+		if (di == devinfo) {
+			cmdinfo->state |= COMMAND_ABORTED;
+			cmdinfo->state &= ~IS_IN_WORK_LIST;
+			if (devinfo->resetting) {
+				/* uas_stat_cmplt() will not do that
+				 * when a device reset is in
+				 * progress */
+				cmdinfo->state &= ~COMMAND_INFLIGHT;
+			}
+			uas_try_complete(cmnd, __func__);
+		} else {
+			/* not our uas device, relink into list */
+			list_del(&cmdinfo->list);
+			spin_lock_irq(&uas_work_lock);
+			list_add_tail(&cmdinfo->list, &uas_work_list);
+			spin_unlock_irq(&uas_work_lock);
+		}
+	}
+	spin_unlock_irqrestore(&devinfo->lock, flags);
+}
+
 static void uas_sense(struct urb *urb, struct scsi_cmnd *cmnd)
 {
 	struct sense_iu *sense_iu = urb->transfer_buffer;
@@ -168,7 +236,7 @@
 	struct uas_cmd_info *ci = (void *)&cmnd->SCp;
 
 	scmd_printk(KERN_INFO, cmnd, "%s %p tag %d, inflight:"
-		    "%s%s%s%s%s%s%s%s%s%s%s%s\n",
+		    "%s%s%s%s%s%s%s%s%s%s%s%s%s%s\n",
 		    caller, cmnd, cmnd->request->tag,
 		    (ci->state & SUBMIT_STATUS_URB)     ? " s-st"  : "",
 		    (ci->state & ALLOC_DATA_IN_URB)     ? " a-in"  : "",
@@ -181,7 +249,9 @@
 		    (ci->state & DATA_IN_URB_INFLIGHT)  ? " IN"    : "",
 		    (ci->state & DATA_OUT_URB_INFLIGHT) ? " OUT"   : "",
 		    (ci->state & COMMAND_COMPLETED)     ? " done"  : "",
-		    (ci->state & COMMAND_ABORTED)       ? " abort" : "");
+		    (ci->state & COMMAND_ABORTED)       ? " abort" : "",
+		    (ci->state & UNLINK_DATA_URBS)      ? " unlink": "",
+		    (ci->state & IS_IN_WORK_LIST)       ? " work"  : "");
 }
 
 static int uas_try_complete(struct scsi_cmnd *cmnd, const char *caller)
@@ -192,7 +262,8 @@
 	WARN_ON(!spin_is_locked(&devinfo->lock));
 	if (cmdinfo->state & (COMMAND_INFLIGHT |
 			      DATA_IN_URB_INFLIGHT |
-			      DATA_OUT_URB_INFLIGHT))
+			      DATA_OUT_URB_INFLIGHT |
+			      UNLINK_DATA_URBS))
 		return -EBUSY;
 	BUG_ON(cmdinfo->state & COMMAND_COMPLETED);
 	cmdinfo->state |= COMMAND_COMPLETED;
@@ -217,6 +288,7 @@
 	if (err) {
 		spin_lock(&uas_work_lock);
 		list_add_tail(&cmdinfo->list, &uas_work_list);
+		cmdinfo->state |= IS_IN_WORK_LIST;
 		spin_unlock(&uas_work_lock);
 		schedule_work(&uas_work);
 	}
@@ -274,16 +346,9 @@
 			uas_sense(urb, cmnd);
 		if (cmnd->result != 0) {
 			/* cancel data transfers on error */
-			if (cmdinfo->state & DATA_IN_URB_INFLIGHT) {
-				spin_unlock_irqrestore(&devinfo->lock, flags);
-				usb_unlink_urb(cmdinfo->data_in_urb);
-				spin_lock_irqsave(&devinfo->lock, flags);
-			}
-			if (cmdinfo->state & DATA_OUT_URB_INFLIGHT) {
-				spin_unlock_irqrestore(&devinfo->lock, flags);
-				usb_unlink_urb(cmdinfo->data_out_urb);
-				spin_lock_irqsave(&devinfo->lock, flags);
-			}
+			spin_unlock_irqrestore(&devinfo->lock, flags);
+			uas_unlink_data_urbs(devinfo, cmdinfo);
+			spin_lock_irqsave(&devinfo->lock, flags);
 		}
 		cmdinfo->state &= ~COMMAND_INFLIGHT;
 		uas_try_complete(cmnd, __func__);
@@ -579,6 +644,12 @@
 
 	BUILD_BUG_ON(sizeof(struct uas_cmd_info) > sizeof(struct scsi_pointer));
 
+	if (devinfo->resetting) {
+		cmnd->result = DID_ERROR << 16;
+		cmnd->scsi_done(cmnd);
+		return 0;
+	}
+
 	spin_lock_irqsave(&devinfo->lock, flags);
 	if (devinfo->cmnd) {
 		spin_unlock_irqrestore(&devinfo->lock, flags);
@@ -623,6 +694,7 @@
 		}
 		spin_lock(&uas_work_lock);
 		list_add_tail(&cmdinfo->list, &uas_work_list);
+		cmdinfo->state |= IS_IN_WORK_LIST;
 		spin_unlock(&uas_work_lock);
 		schedule_work(&uas_work);
 	}
@@ -689,8 +761,23 @@
 	uas_log_cmd_state(cmnd, __func__);
 	spin_lock_irqsave(&devinfo->lock, flags);
 	cmdinfo->state |= COMMAND_ABORTED;
-	spin_unlock_irqrestore(&devinfo->lock, flags);
-	ret = uas_eh_task_mgmt(cmnd, "ABORT TASK", TMF_ABORT_TASK);
+	if (cmdinfo->state & IS_IN_WORK_LIST) {
+		spin_lock(&uas_work_lock);
+		list_del(&cmdinfo->list);
+		cmdinfo->state &= ~IS_IN_WORK_LIST;
+		spin_unlock(&uas_work_lock);
+	}
+	if (cmdinfo->state & COMMAND_INFLIGHT) {
+		spin_unlock_irqrestore(&devinfo->lock, flags);
+		ret = uas_eh_task_mgmt(cmnd, "ABORT TASK", TMF_ABORT_TASK);
+	} else {
+		spin_unlock_irqrestore(&devinfo->lock, flags);
+		uas_unlink_data_urbs(devinfo, cmdinfo);
+		spin_lock_irqsave(&devinfo->lock, flags);
+		uas_try_complete(cmnd, __func__);
+		spin_unlock_irqrestore(&devinfo->lock, flags);
+		ret = SUCCESS;
+	}
 	return ret;
 }
 
@@ -709,6 +796,7 @@
 	int err;
 
 	devinfo->resetting = 1;
+	uas_abort_work(devinfo);
 	usb_kill_anchored_urbs(&devinfo->cmd_urbs);
 	usb_kill_anchored_urbs(&devinfo->sense_urbs);
 	usb_kill_anchored_urbs(&devinfo->data_urbs);
@@ -954,10 +1042,12 @@
 	struct Scsi_Host *shost = usb_get_intfdata(intf);
 	struct uas_dev_info *devinfo = (void *)shost->hostdata[0];
 
-	scsi_remove_host(shost);
+	devinfo->resetting = 1;
+	uas_abort_work(devinfo);
 	usb_kill_anchored_urbs(&devinfo->cmd_urbs);
 	usb_kill_anchored_urbs(&devinfo->sense_urbs);
 	usb_kill_anchored_urbs(&devinfo->data_urbs);
+	scsi_remove_host(shost);
 	uas_free_streams(devinfo);
 	kfree(devinfo);
 }
diff --git a/include/linux/platform_data/usb3503.h b/include/linux/platform_data/usb3503.h
new file mode 100644
index 0000000..85dcc70
--- /dev/null
+++ b/include/linux/platform_data/usb3503.h
@@ -0,0 +1,19 @@
+#ifndef __USB3503_H__
+#define __USB3503_H__
+
+#define USB3503_I2C_NAME	"usb3503"
+
+enum usb3503_mode {
+	USB3503_MODE_UNKNOWN,
+	USB3503_MODE_HUB,
+	USB3503_MODE_STANDBY,
+};
+
+struct usb3503_platform_data {
+	enum usb3503_mode	initial_mode;
+	int	gpio_intn;
+	int	gpio_connect;
+	int	gpio_reset;
+};
+
+#endif
diff --git a/tools/usb/testusb.c b/tools/usb/testusb.c
index 68d0734..643cd77 100644
--- a/tools/usb/testusb.c
+++ b/tools/usb/testusb.c
@@ -507,10 +507,8 @@
 			return handle_testdev (entry) != entry;
 		}
 		status = pthread_create (&entry->thread, 0, handle_testdev, entry);
-		if (status) {
+		if (status)
 			perror ("pthread_create");
-			continue;
-		}
 	}
 	if (device) {
 		struct testdev		dev;