summary refs log tree commit diff
path: root/drivers/usb
diff options
context:
space:
mode:
Diffstat (limited to 'drivers/usb')
-rw-r--r--drivers/usb/atm/speedtch.c4
-rw-r--r--drivers/usb/atm/ueagle-atm.c10
-rw-r--r--drivers/usb/class/cdc-acm.c2
-rw-r--r--drivers/usb/core/Kconfig15
-rw-r--r--drivers/usb/core/devices.c9
-rw-r--r--drivers/usb/core/devio.c4
-rw-r--r--drivers/usb/core/driver.c304
-rw-r--r--drivers/usb/core/endpoint.c98
-rw-r--r--drivers/usb/core/hcd.c4
-rw-r--r--drivers/usb/core/hub.c234
-rw-r--r--drivers/usb/core/hub.h41
-rw-r--r--drivers/usb/core/message.c8
-rw-r--r--drivers/usb/core/usb.c160
-rw-r--r--drivers/usb/core/usb.h9
-rw-r--r--drivers/usb/gadget/ether.c4
-rw-r--r--drivers/usb/gadget/lh7a40x_udc.c1
-rw-r--r--drivers/usb/gadget/net2280.c8
-rw-r--r--drivers/usb/gadget/net2280.h3
-rw-r--r--drivers/usb/gadget/pxa2xx_udc.c2
-rw-r--r--drivers/usb/host/Kconfig2
-rw-r--r--drivers/usb/host/ehci-hcd.c16
-rw-r--r--drivers/usb/host/ehci-hub.c104
-rw-r--r--drivers/usb/host/ehci-pci.c40
-rw-r--r--drivers/usb/host/ehci.h1
-rw-r--r--drivers/usb/host/ohci-hcd.c10
-rw-r--r--drivers/usb/host/ohci-hub.c172
-rw-r--r--drivers/usb/host/u132-hcd.c14
-rw-r--r--drivers/usb/image/microtek.c8
-rw-r--r--drivers/usb/input/Kconfig6
-rw-r--r--drivers/usb/input/ati_remote.c17
-rw-r--r--drivers/usb/input/ati_remote2.c3
-rw-r--r--drivers/usb/input/hid-core.c91
-rw-r--r--drivers/usb/input/hid.h1
-rw-r--r--drivers/usb/input/usbkbd.c10
-rw-r--r--drivers/usb/input/usbmouse.c4
-rw-r--r--drivers/usb/input/usbtouchscreen.c96
-rw-r--r--drivers/usb/input/wacom.h1
-rw-r--r--drivers/usb/input/wacom_sys.c2
-rw-r--r--drivers/usb/input/yealink.c6
-rw-r--r--drivers/usb/misc/Makefile1
-rw-r--r--drivers/usb/misc/appledisplay.c5
-rw-r--r--drivers/usb/misc/auerswald.c7
-rw-r--r--drivers/usb/misc/emi26.c3
-rw-r--r--drivers/usb/misc/emi62.c3
-rw-r--r--drivers/usb/misc/ftdi-elan.c20
-rw-r--r--drivers/usb/misc/idmouse.c22
-rw-r--r--drivers/usb/misc/legousbtower.c31
-rw-r--r--drivers/usb/misc/phidgetkit.c5
-rw-r--r--drivers/usb/misc/phidgetmotorcontrol.c5
-rw-r--r--drivers/usb/misc/usb_u132.h6
-rw-r--r--drivers/usb/misc/usbtest.c4
-rw-r--r--drivers/usb/net/asix.c6
-rw-r--r--drivers/usb/net/catc.c12
-rw-r--r--drivers/usb/net/cdc_ether.c3
-rw-r--r--drivers/usb/net/net1080.c4
-rw-r--r--drivers/usb/net/pegasus.c1
-rw-r--r--drivers/usb/net/usbnet.c4
-rw-r--r--drivers/usb/serial/Kconfig11
-rw-r--r--drivers/usb/serial/Makefile1
-rw-r--r--drivers/usb/serial/aircable.c9
-rw-r--r--drivers/usb/serial/airprime.c1
-rw-r--r--drivers/usb/serial/ark3116.c3
-rw-r--r--drivers/usb/serial/console.c6
-rw-r--r--drivers/usb/serial/cypress_m8.c9
-rw-r--r--drivers/usb/serial/digi_acceleport.c2
-rw-r--r--drivers/usb/serial/ezusb.c3
-rw-r--r--drivers/usb/serial/ftdi_sio.c3
-rw-r--r--drivers/usb/serial/garmin_gps.c3
-rw-r--r--drivers/usb/serial/io_edgeport.c4
-rw-r--r--drivers/usb/serial/ipw.c3
-rw-r--r--drivers/usb/serial/keyspan.c18
-rw-r--r--drivers/usb/serial/kobil_sct.c9
-rw-r--r--drivers/usb/serial/mct_u232.c6
-rw-r--r--drivers/usb/serial/mos7840.c3
-rw-r--r--drivers/usb/serial/navman.c3
-rw-r--r--drivers/usb/serial/ti_usb_3410_5052.c5
-rw-r--r--drivers/usb/serial/ti_usb_3410_5052.h1
-rw-r--r--drivers/usb/serial/usb-serial.c12
-rw-r--r--drivers/usb/serial/usb_debug.c65
-rw-r--r--drivers/usb/serial/visor.c3
-rw-r--r--drivers/usb/storage/onetouch.c5
-rw-r--r--drivers/usb/storage/unusual_devs.h10
-rw-r--r--drivers/usb/storage/usb.c8
83 files changed, 1078 insertions, 794 deletions
diff --git a/drivers/usb/atm/speedtch.c b/drivers/usb/atm/speedtch.c
index 7ed34bb1c50f..8ed6c75adf0f 100644
--- a/drivers/usb/atm/speedtch.c
+++ b/drivers/usb/atm/speedtch.c
@@ -837,8 +837,8 @@ static int speedtch_bind(struct usbatm_data *usbatm,
 			const struct usb_endpoint_descriptor *endpoint_desc = &desc->endpoint[i].desc;
 
 			if ((endpoint_desc->bEndpointAddress == target_address)) {
-				use_isoc = (endpoint_desc->bmAttributes & USB_ENDPOINT_XFERTYPE_MASK) ==
-					USB_ENDPOINT_XFER_ISOC;
+				use_isoc =
+					usb_endpoint_xfer_isoc(endpoint_desc);
 				break;
 			}
 		}
diff --git a/drivers/usb/atm/ueagle-atm.c b/drivers/usb/atm/ueagle-atm.c
index e39bb09f5af9..f2d196fa1e8b 100644
--- a/drivers/usb/atm/ueagle-atm.c
+++ b/drivers/usb/atm/ueagle-atm.c
@@ -401,9 +401,8 @@ static int uea_send_modem_cmd(struct usb_device *usb,
 	int ret = -ENOMEM;
 	u8 *xfer_buff;
 
-	xfer_buff = kmalloc(size, GFP_KERNEL);
+	xfer_buff = kmemdup(buff, size, GFP_KERNEL);
 	if (xfer_buff) {
-		memcpy(xfer_buff, buff, size);
 		ret = usb_control_msg(usb,
 				      usb_sndctrlpipe(usb, 0),
 				      LOAD_INTERNAL,
@@ -595,14 +594,12 @@ static int uea_idma_write(struct uea_softc *sc, void *data, u32 size)
 	u8 *xfer_buff;
 	int bytes_read;
 
-	xfer_buff = kmalloc(size, GFP_KERNEL);
+	xfer_buff = kmemdup(data, size, GFP_KERNEL);
 	if (!xfer_buff) {
 		uea_err(INS_TO_USBDEV(sc), "can't allocate xfer_buff\n");
 		return ret;
 	}
 
-	memcpy(xfer_buff, data, size);
-
 	ret = usb_bulk_msg(sc->usb_dev,
 			 usb_sndbulkpipe(sc->usb_dev, UEA_IDMA_PIPE),
 			 xfer_buff, size, &bytes_read, BULK_TIMEOUT);
@@ -765,12 +762,11 @@ static int uea_request(struct uea_softc *sc,
 	u8 *xfer_buff;
 	int ret = -ENOMEM;
 
-	xfer_buff = kmalloc(size, GFP_KERNEL);
+	xfer_buff = kmemdup(data, size, GFP_KERNEL);
 	if (!xfer_buff) {
 		uea_err(INS_TO_USBDEV(sc), "can't allocate xfer_buff\n");
 		return ret;
 	}
-	memcpy(xfer_buff, data, size);
 
 	ret = usb_control_msg(sc->usb_dev, usb_sndctrlpipe(sc->usb_dev, 0),
 			      UCDC_SEND_ENCAPSULATED_COMMAND,
diff --git a/drivers/usb/class/cdc-acm.c b/drivers/usb/class/cdc-acm.c
index 6408e10fdbf8..7f1fa956dcdb 100644
--- a/drivers/usb/class/cdc-acm.c
+++ b/drivers/usb/class/cdc-acm.c
@@ -892,7 +892,7 @@ skip_normal_probe:
 
 
 	/* workaround for switched endpoints */
-	if ((epread->bEndpointAddress & USB_DIR_IN) != USB_DIR_IN) {
+	if (!usb_endpoint_dir_in(epread)) {
 		/* descriptors are swapped */
 		struct usb_endpoint_descriptor *t;
 		dev_dbg(&intf->dev,"The data interface has switched endpoints");
diff --git a/drivers/usb/core/Kconfig b/drivers/usb/core/Kconfig
index 6e3b5358a760..f8324d8d06ac 100644
--- a/drivers/usb/core/Kconfig
+++ b/drivers/usb/core/Kconfig
@@ -72,6 +72,21 @@ config USB_SUSPEND
 
 	  If you are unsure about this, say N here.
 
+config USB_MULTITHREAD_PROBE
+	bool "USB Multi-threaded probe (EXPERIMENTAL)"
+	depends on USB && EXPERIMENTAL
+	default n
+	help
+	  Say Y here if you want the USB core to spawn a new thread for
+	  every USB device that is probed.  This can cause a small speedup
+	  in boot times on systems with a lot of different USB devices.
+
+	  This option should be safe to enable, but if any odd probing
+	  problems are found, please disable it, or dynamically turn it
+	  off in the /sys/module/usbcore/parameters/multithread_probe
+	  file
+
+	  When in doubt, say N.
 
 config USB_OTG
 	bool
diff --git a/drivers/usb/core/devices.c b/drivers/usb/core/devices.c
index 3538c2fdadfe..ea398e5d50af 100644
--- a/drivers/usb/core/devices.c
+++ b/drivers/usb/core/devices.c
@@ -175,12 +175,13 @@ static char *usb_dump_endpoint_descriptor (
 )
 {
 	char dir, unit, *type;
-	unsigned interval, in, bandwidth = 1;
+	unsigned interval, bandwidth = 1;
 
 	if (start > end)
 		return start;
-	in = (desc->bEndpointAddress & USB_DIR_IN);
-	dir = in ? 'I' : 'O';
+
+	dir = usb_endpoint_dir_in(desc) ? 'I' : 'O';
+
 	if (speed == USB_SPEED_HIGH) {
 		switch (le16_to_cpu(desc->wMaxPacketSize) & (0x03 << 11)) {
 		case 1 << 11:	bandwidth = 2; break;
@@ -204,7 +205,7 @@ static char *usb_dump_endpoint_descriptor (
 		break;
 	case USB_ENDPOINT_XFER_BULK:
 		type = "Bulk";
-		if (speed == USB_SPEED_HIGH && !in)	/* uframes per NAK */
+		if (speed == USB_SPEED_HIGH && dir == 'O') /* uframes per NAK */
 			interval = desc->bInterval;
 		else
 			interval = 0;
diff --git a/drivers/usb/core/devio.c b/drivers/usb/core/devio.c
index fed92be63b5e..3ed4cb2d56d9 100644
--- a/drivers/usb/core/devio.c
+++ b/drivers/usb/core/devio.c
@@ -561,7 +561,7 @@ static int usbdev_open(struct inode *inode, struct file *file)
 		dev = inode->i_private;
 	if (!dev)
 		goto out;
-	ret = usb_autoresume_device(dev, 1);
+	ret = usb_autoresume_device(dev);
 	if (ret)
 		goto out;
 
@@ -609,7 +609,7 @@ static int usbdev_release(struct inode *inode, struct file *file)
 			releaseintf(ps, ifnum);
 	}
 	destroy_all_async(ps);
-	usb_autosuspend_device(dev, 1);
+	usb_autosuspend_device(dev);
 	usb_unlock_device(dev);
 	usb_put_dev(dev);
 	put_pid(ps->disc_pid);
diff --git a/drivers/usb/core/driver.c b/drivers/usb/core/driver.c
index 113e484c763e..d6eb5ce1dd1d 100644
--- a/drivers/usb/core/driver.c
+++ b/drivers/usb/core/driver.c
@@ -205,7 +205,7 @@ static int usb_probe_interface(struct device *dev)
 	if (id) {
 		dev_dbg(dev, "%s - got id\n", __FUNCTION__);
 
-		error = usb_autoresume_device(udev, 1);
+		error = usb_autoresume_device(udev);
 		if (error)
 			return error;
 
@@ -229,7 +229,7 @@ static int usb_probe_interface(struct device *dev)
 		} else
 			intf->condition = USB_INTERFACE_BOUND;
 
-		usb_autosuspend_device(udev, 1);
+		usb_autosuspend_device(udev);
 	}
 
 	return error;
@@ -247,7 +247,7 @@ static int usb_unbind_interface(struct device *dev)
 
 	/* Autoresume for set_interface call below */
 	udev = interface_to_usbdev(intf);
-	error = usb_autoresume_device(udev, 1);
+	error = usb_autoresume_device(udev);
 
 	/* release all urbs for this interface */
 	usb_disable_interface(interface_to_usbdev(intf), intf);
@@ -265,7 +265,7 @@ static int usb_unbind_interface(struct device *dev)
 	intf->needs_remote_wakeup = 0;
 
 	if (!error)
-		usb_autosuspend_device(udev, 1);
+		usb_autosuspend_device(udev);
 
 	return 0;
 }
@@ -408,6 +408,16 @@ static int usb_match_one_id(struct usb_interface *interface,
 	    (id->bDeviceProtocol != dev->descriptor.bDeviceProtocol))
 		return 0;
 
+	/* The interface class, subclass, and protocol should never be
+	 * checked for a match if the device class is Vendor Specific,
+	 * unless the match record specifies the Vendor ID. */
+	if (dev->descriptor.bDeviceClass == USB_CLASS_VENDOR_SPEC &&
+			!(id->match_flags & USB_DEVICE_ID_MATCH_VENDOR) &&
+			(id->match_flags & (USB_DEVICE_ID_MATCH_INT_CLASS |
+				USB_DEVICE_ID_MATCH_INT_SUBCLASS |
+				USB_DEVICE_ID_MATCH_INT_PROTOCOL)))
+		return 0;
+
 	if ((id->match_flags & USB_DEVICE_ID_MATCH_INT_CLASS) &&
 	    (id->bInterfaceClass != intf->desc.bInterfaceClass))
 		return 0;
@@ -476,7 +486,17 @@ static int usb_match_one_id(struct usb_interface *interface,
  * most general; they let drivers bind to any interface on a
  * multiple-function device.  Use the USB_INTERFACE_INFO
  * macro, or its siblings, to match class-per-interface style
- * devices (as recorded in bDeviceClass).
+ * devices (as recorded in bInterfaceClass).
+ *
+ * Note that an entry created by USB_INTERFACE_INFO won't match
+ * any interface if the device class is set to Vendor-Specific.
+ * This is deliberate; according to the USB spec the meanings of
+ * the interface class/subclass/protocol for these devices are also
+ * vendor-specific, and hence matching against a standard product
+ * class wouldn't work anyway.  If you really want to use an
+ * interface-based match for such a device, create a match record
+ * that also specifies the vendor ID.  (Unforunately there isn't a
+ * standard macro for creating records like this.)
  *
  * Within those groups, remember that not all combinations are
  * meaningful.  For example, don't give a product version range
@@ -505,7 +525,7 @@ const struct usb_device_id *usb_match_id(struct usb_interface *interface,
 }
 EXPORT_SYMBOL_GPL_FUTURE(usb_match_id);
 
-int usb_device_match(struct device *dev, struct device_driver *drv)
+static int usb_device_match(struct device *dev, struct device_driver *drv)
 {
 	/* devices and interfaces are handled separately */
 	if (is_usb_device(dev)) {
@@ -790,7 +810,7 @@ EXPORT_SYMBOL_GPL_FUTURE(usb_deregister);
 #ifdef CONFIG_PM
 
 /* Caller has locked udev's pm_mutex */
-static int suspend_device(struct usb_device *udev, pm_message_t msg)
+static int usb_suspend_device(struct usb_device *udev, pm_message_t msg)
 {
 	struct usb_device_driver	*udriver;
 	int				status = 0;
@@ -817,7 +837,7 @@ done:
 }
 
 /* Caller has locked udev's pm_mutex */
-static int resume_device(struct usb_device *udev)
+static int usb_resume_device(struct usb_device *udev)
 {
 	struct usb_device_driver	*udriver;
 	int				status = 0;
@@ -843,7 +863,7 @@ done:
 }
 
 /* Caller has locked intf's usb_device's pm mutex */
-static int suspend_interface(struct usb_interface *intf, pm_message_t msg)
+static int usb_suspend_interface(struct usb_interface *intf, pm_message_t msg)
 {
 	struct usb_driver	*driver;
 	int			status = 0;
@@ -880,7 +900,7 @@ done:
 }
 
 /* Caller has locked intf's usb_device's pm_mutex */
-static int resume_interface(struct usb_interface *intf)
+static int usb_resume_interface(struct usb_interface *intf)
 {
 	struct usb_driver	*driver;
 	int			status = 0;
@@ -920,6 +940,44 @@ done:
 	return status;
 }
 
+#ifdef	CONFIG_USB_SUSPEND
+
+/* Internal routine to check whether we may autosuspend a device. */
+static int autosuspend_check(struct usb_device *udev)
+{
+	int			i;
+	struct usb_interface	*intf;
+
+	/* For autosuspend, fail fast if anything is in use.
+	 * Also fail if any interfaces require remote wakeup but it
+	 * isn't available. */
+	udev->do_remote_wakeup = device_may_wakeup(&udev->dev);
+	if (udev->pm_usage_cnt > 0)
+		return -EBUSY;
+	if (udev->actconfig) {
+		for (i = 0; i < udev->actconfig->desc.bNumInterfaces; i++) {
+			intf = udev->actconfig->interface[i];
+			if (!is_active(intf))
+				continue;
+			if (intf->pm_usage_cnt > 0)
+				return -EBUSY;
+			if (intf->needs_remote_wakeup &&
+					!udev->do_remote_wakeup) {
+				dev_dbg(&udev->dev, "remote wakeup needed "
+						"for autosuspend\n");
+				return -EOPNOTSUPP;
+			}
+		}
+	}
+	return 0;
+}
+
+#else
+
+#define autosuspend_check(udev)		0
+
+#endif
+
 /**
  * usb_suspend_both - suspend a USB device and its interfaces
  * @udev: the usb_device to suspend
@@ -971,52 +1029,34 @@ int usb_suspend_both(struct usb_device *udev, pm_message_t msg)
 
 	udev->do_remote_wakeup = device_may_wakeup(&udev->dev);
 
-	/* For autosuspend, fail fast if anything is in use.
-	 * Also fail if any interfaces require remote wakeup but it
-	 * isn't available. */
 	if (udev->auto_pm) {
-		if (udev->pm_usage_cnt > 0)
-			return -EBUSY;
-		if (udev->actconfig) {
-			for (; i < udev->actconfig->desc.bNumInterfaces; i++) {
-				intf = udev->actconfig->interface[i];
-				if (!is_active(intf))
-					continue;
-				if (intf->pm_usage_cnt > 0)
-					return -EBUSY;
-				if (intf->needs_remote_wakeup &&
-						!udev->do_remote_wakeup) {
-					dev_dbg(&udev->dev,
-	"remote wakeup needed for autosuspend\n");
-					return -EOPNOTSUPP;
-				}
-			}
-			i = 0;
-		}
+		status = autosuspend_check(udev);
+		if (status < 0)
+			return status;
 	}
 
 	/* Suspend all the interfaces and then udev itself */
 	if (udev->actconfig) {
 		for (; i < udev->actconfig->desc.bNumInterfaces; i++) {
 			intf = udev->actconfig->interface[i];
-			status = suspend_interface(intf, msg);
+			status = usb_suspend_interface(intf, msg);
 			if (status != 0)
 				break;
 		}
 	}
 	if (status == 0)
-		status = suspend_device(udev, msg);
+		status = usb_suspend_device(udev, msg);
 
 	/* If the suspend failed, resume interfaces that did get suspended */
 	if (status != 0) {
 		while (--i >= 0) {
 			intf = udev->actconfig->interface[i];
-			resume_interface(intf);
+			usb_resume_interface(intf);
 		}
 
 	/* If the suspend succeeded, propagate it up the tree */
 	} else if (parent)
-		usb_autosuspend_device(parent, 0);
+		usb_autosuspend_device(parent);
 
 	// dev_dbg(&udev->dev, "%s: status %d\n", __FUNCTION__, status);
 	return status;
@@ -1064,9 +1104,25 @@ int usb_resume_both(struct usb_device *udev)
 	/* Propagate the resume up the tree, if necessary */
 	if (udev->state == USB_STATE_SUSPENDED) {
 		if (parent) {
-			usb_pm_lock(parent);
-			parent->auto_pm = 1;
-			status = usb_resume_both(parent);
+			status = usb_autoresume_device(parent);
+			if (status == 0) {
+				status = usb_resume_device(udev);
+				if (status) {
+					usb_autosuspend_device(parent);
+
+					/* It's possible usb_resume_device()
+					 * failed after the port was
+					 * unsuspended, causing udev to be
+					 * logically disconnected.  We don't
+					 * want usb_disconnect() to autosuspend
+					 * the parent again, so tell it that
+					 * udev disconnected while still
+					 * suspended. */
+					if (udev->state ==
+							USB_STATE_NOTATTACHED)
+						udev->discon_suspended = 1;
+				}
+			}
 		} else {
 
 			/* We can't progagate beyond the USB subsystem,
@@ -1075,24 +1131,20 @@ int usb_resume_both(struct usb_device *udev)
 			if (udev->dev.parent->power.power_state.event !=
 					PM_EVENT_ON)
 				status = -EHOSTUNREACH;
-		}
-		if (status == 0)
-			status = resume_device(udev);
-		if (parent)
-			usb_pm_unlock(parent);
+			else
+				status = usb_resume_device(udev);
+ 		}
 	} else {
 
 		/* Needed only for setting udev->dev.power.power_state.event
 		 * and for possible debugging message. */
-		status = resume_device(udev);
+		status = usb_resume_device(udev);
 	}
 
-	/* Now the parent won't suspend until we are finished */
-
 	if (status == 0 && udev->actconfig) {
 		for (i = 0; i < udev->actconfig->desc.bNumInterfaces; i++) {
 			intf = udev->actconfig->interface[i];
-			resume_interface(intf);
+			usb_resume_interface(intf);
 		}
 	}
 
@@ -1102,39 +1154,53 @@ int usb_resume_both(struct usb_device *udev)
 
 #ifdef CONFIG_USB_SUSPEND
 
+/* Internal routine to adjust a device's usage counter and change
+ * its autosuspend state.
+ */
+static int usb_autopm_do_device(struct usb_device *udev, int inc_usage_cnt)
+{
+	int	status = 0;
+
+	usb_pm_lock(udev);
+	udev->pm_usage_cnt += inc_usage_cnt;
+	WARN_ON(udev->pm_usage_cnt < 0);
+	if (inc_usage_cnt >= 0 && udev->pm_usage_cnt > 0) {
+		udev->auto_pm = 1;
+		status = usb_resume_both(udev);
+		if (status != 0)
+			udev->pm_usage_cnt -= inc_usage_cnt;
+	} else if (inc_usage_cnt <= 0 && autosuspend_check(udev) == 0)
+		queue_delayed_work(ksuspend_usb_wq, &udev->autosuspend,
+				USB_AUTOSUSPEND_DELAY);
+	usb_pm_unlock(udev);
+	return status;
+}
+
 /**
  * usb_autosuspend_device - delayed autosuspend of a USB device and its interfaces
  * @udev: the usb_device to autosuspend
- * @dec_usage_cnt: flag to decrement @udev's PM-usage counter
  *
  * This routine should be called when a core subsystem is finished using
  * @udev and wants to allow it to autosuspend.  Examples would be when
  * @udev's device file in usbfs is closed or after a configuration change.
  *
- * @dec_usage_cnt should be 1 if the subsystem previously incremented
- * @udev's usage counter (such as by passing 1 to usb_autoresume_device);
- * otherwise it should be 0.
- *
- * If the usage counter for @udev or any of its active interfaces is greater
- * than 0, the autosuspend request will not be queued.  (If an interface
- * driver does not support autosuspend then its usage counter is permanently
- * positive.)  Likewise, if an interface driver requires remote-wakeup
- * capability during autosuspend but remote wakeup is disabled, the
- * autosuspend will fail.
+ * @udev's usage counter is decremented.  If it or any of the usage counters
+ * for an active interface is greater than 0, no autosuspend request will be
+ * queued.  (If an interface driver does not support autosuspend then its
+ * usage counter is permanently positive.)  Furthermore, if an interface
+ * driver requires remote-wakeup capability during autosuspend but remote
+ * wakeup is disabled, the autosuspend will fail.
  *
  * Often the caller will hold @udev's device lock, but this is not
  * necessary.
  *
  * This routine can run only in process context.
  */
-void usb_autosuspend_device(struct usb_device *udev, int dec_usage_cnt)
+void usb_autosuspend_device(struct usb_device *udev)
 {
-	usb_pm_lock(udev);
-	udev->pm_usage_cnt -= dec_usage_cnt;
-	if (udev->pm_usage_cnt <= 0)
-		queue_delayed_work(ksuspend_usb_wq, &udev->autosuspend,
-				USB_AUTOSUSPEND_DELAY);
-	usb_pm_unlock(udev);
+	int	status;
+
+	status = usb_autopm_do_device(udev, -1);
 	// dev_dbg(&udev->dev, "%s: cnt %d\n",
 	//		__FUNCTION__, udev->pm_usage_cnt);
 }
@@ -1142,44 +1208,59 @@ void usb_autosuspend_device(struct usb_device *udev, int dec_usage_cnt)
 /**
  * usb_autoresume_device - immediately autoresume a USB device and its interfaces
  * @udev: the usb_device to autoresume
- * @inc_usage_cnt: flag to increment @udev's PM-usage counter
  *
  * This routine should be called when a core subsystem wants to use @udev
- * and needs to guarantee that it is not suspended.  In addition, the
- * caller can prevent @udev from being autosuspended subsequently.  (Note
- * that this will not prevent suspend events originating in the PM core.)
- * Examples would be when @udev's device file in usbfs is opened (autosuspend
- * should be prevented until the file is closed) or when a remote-wakeup
- * request is received (later autosuspends should not be prevented).
+ * and needs to guarantee that it is not suspended.  No autosuspend will
+ * occur until usb_autosuspend_device is called.  (Note that this will not
+ * prevent suspend events originating in the PM core.)  Examples would be
+ * when @udev's device file in usbfs is opened or when a remote-wakeup
+ * request is received.
  *
- * @inc_usage_cnt should be 1 to increment @udev's usage counter and prevent
- * autosuspends.  This prevention will persist until the usage counter is
- * decremented again (such as by passing 1 to usb_autosuspend_device).
- * Otherwise @inc_usage_cnt should be 0 to leave the usage counter unchanged.
- * Regardless, if the autoresume fails then the usage counter is not
- * incremented.
+ * @udev's usage counter is incremented to prevent subsequent autosuspends.
+ * However if the autoresume fails then the usage counter is re-decremented.
  *
  * Often the caller will hold @udev's device lock, but this is not
  * necessary (and attempting it might cause deadlock).
  *
  * This routine can run only in process context.
  */
-int usb_autoresume_device(struct usb_device *udev, int inc_usage_cnt)
+int usb_autoresume_device(struct usb_device *udev)
 {
 	int	status;
 
-	usb_pm_lock(udev);
-	udev->pm_usage_cnt += inc_usage_cnt;
-	udev->auto_pm = 1;
-	status = usb_resume_both(udev);
-	if (status != 0)
-		udev->pm_usage_cnt -= inc_usage_cnt;
-	usb_pm_unlock(udev);
+	status = usb_autopm_do_device(udev, 1);
 	// dev_dbg(&udev->dev, "%s: status %d cnt %d\n",
 	//		__FUNCTION__, status, udev->pm_usage_cnt);
 	return status;
 }
 
+/* Internal routine to adjust an interface's usage counter and change
+ * its device's autosuspend state.
+ */
+static int usb_autopm_do_interface(struct usb_interface *intf,
+		int inc_usage_cnt)
+{
+	struct usb_device	*udev = interface_to_usbdev(intf);
+	int			status = 0;
+
+	usb_pm_lock(udev);
+	if (intf->condition == USB_INTERFACE_UNBOUND)
+		status = -ENODEV;
+	else {
+		intf->pm_usage_cnt += inc_usage_cnt;
+		if (inc_usage_cnt >= 0 && intf->pm_usage_cnt > 0) {
+			udev->auto_pm = 1;
+			status = usb_resume_both(udev);
+			if (status != 0)
+				intf->pm_usage_cnt -= inc_usage_cnt;
+		} else if (inc_usage_cnt <= 0 && autosuspend_check(udev) == 0)
+			queue_delayed_work(ksuspend_usb_wq, &udev->autosuspend,
+					USB_AUTOSUSPEND_DELAY);
+	}
+	usb_pm_unlock(udev);
+	return status;
+}
+
 /**
  * usb_autopm_put_interface - decrement a USB interface's PM-usage counter
  * @intf: the usb_interface whose counter should be decremented
@@ -1213,17 +1294,11 @@ int usb_autoresume_device(struct usb_device *udev, int inc_usage_cnt)
  */
 void usb_autopm_put_interface(struct usb_interface *intf)
 {
-	struct usb_device	*udev = interface_to_usbdev(intf);
+	int	status;
 
-	usb_pm_lock(udev);
-	if (intf->condition != USB_INTERFACE_UNBOUND &&
-			--intf->pm_usage_cnt <= 0) {
-		queue_delayed_work(ksuspend_usb_wq, &udev->autosuspend,
-				USB_AUTOSUSPEND_DELAY);
-	}
-	usb_pm_unlock(udev);
-	// dev_dbg(&intf->dev, "%s: cnt %d\n",
-	//		__FUNCTION__, intf->pm_usage_cnt);
+	status = usb_autopm_do_interface(intf, -1);
+	// dev_dbg(&intf->dev, "%s: status %d cnt %d\n",
+	//		__FUNCTION__, status, intf->pm_usage_cnt);
 }
 EXPORT_SYMBOL_GPL(usb_autopm_put_interface);
 
@@ -1260,26 +1335,37 @@ EXPORT_SYMBOL_GPL(usb_autopm_put_interface);
  */
 int usb_autopm_get_interface(struct usb_interface *intf)
 {
-	struct usb_device	*udev = interface_to_usbdev(intf);
-	int			status;
+	int	status;
 
-	usb_pm_lock(udev);
-	if (intf->condition == USB_INTERFACE_UNBOUND)
-		status = -ENODEV;
-	else {
-		++intf->pm_usage_cnt;
-		udev->auto_pm = 1;
-		status = usb_resume_both(udev);
-		if (status != 0)
-			--intf->pm_usage_cnt;
-	}
-	usb_pm_unlock(udev);
+	status = usb_autopm_do_interface(intf, 1);
 	// dev_dbg(&intf->dev, "%s: status %d cnt %d\n",
 	//		__FUNCTION__, status, intf->pm_usage_cnt);
 	return status;
 }
 EXPORT_SYMBOL_GPL(usb_autopm_get_interface);
 
+/**
+ * usb_autopm_set_interface - set a USB interface's autosuspend state
+ * @intf: the usb_interface whose state should be set
+ *
+ * This routine sets the autosuspend state of @intf's device according
+ * to @intf's usage counter, which the caller must have set previously.
+ * If the counter is <= 0, the device is autosuspended (if it isn't
+ * already suspended and if nothing else prevents the autosuspend).  If
+ * the counter is > 0, the device is autoresumed (if it isn't already
+ * awake).
+ */
+int usb_autopm_set_interface(struct usb_interface *intf)
+{
+	int	status;
+
+	status = usb_autopm_do_interface(intf, 0);
+	// dev_dbg(&intf->dev, "%s: status %d cnt %d\n",
+	//		__FUNCTION__, status, intf->pm_usage_cnt);
+	return status;
+}
+EXPORT_SYMBOL_GPL(usb_autopm_set_interface);
+
 #endif /* CONFIG_USB_SUSPEND */
 
 static int usb_suspend(struct device *dev, pm_message_t message)
diff --git a/drivers/usb/core/endpoint.c b/drivers/usb/core/endpoint.c
index 3b2d137912be..c505b767cee1 100644
--- a/drivers/usb/core/endpoint.c
+++ b/drivers/usb/core/endpoint.c
@@ -10,15 +10,20 @@
  */
 
 #include <linux/kernel.h>
+#include <linux/spinlock.h>
+#include <linux/idr.h>
 #include <linux/usb.h>
 #include "usb.h"
 
-/* endpoint stuff */
+#define MAX_ENDPOINT_MINORS (64*128*32)
+static int usb_endpoint_major;
+static DEFINE_IDR(endpoint_idr);
 
 struct ep_device {
 	struct usb_endpoint_descriptor *desc;
 	struct usb_device *udev;
 	struct device dev;
+	int minor;
 };
 #define to_ep_device(_dev) \
 	container_of(_dev, struct ep_device, dev)
@@ -152,6 +157,55 @@ static struct attribute_group ep_dev_attr_grp = {
 	.attrs = ep_dev_attrs,
 };
 
+static int usb_endpoint_major_init(void)
+{
+	dev_t dev;
+	int error;
+
+	error = alloc_chrdev_region(&dev, 0, MAX_ENDPOINT_MINORS,
+				    "usb_endpoint");
+	if (error) {
+		err("unable to get a dynamic major for usb endpoints");
+		return error;
+	}
+	usb_endpoint_major = MAJOR(dev);
+
+	return error;
+}
+
+static void usb_endpoint_major_cleanup(void)
+{
+	unregister_chrdev_region(MKDEV(usb_endpoint_major, 0),
+				 MAX_ENDPOINT_MINORS);
+}
+
+static int endpoint_get_minor(struct ep_device *ep_dev)
+{
+	static DEFINE_MUTEX(minor_lock);
+	int retval = -ENOMEM;
+	int id;
+
+	mutex_lock(&minor_lock);
+	if (idr_pre_get(&endpoint_idr, GFP_KERNEL) == 0)
+		goto exit;
+
+	retval = idr_get_new(&endpoint_idr, ep_dev, &id);
+	if (retval < 0) {
+		if (retval == -EAGAIN)
+			retval = -ENOMEM;
+		goto exit;
+	}
+	ep_dev->minor = id & MAX_ID_MASK;
+exit:
+	mutex_unlock(&minor_lock);
+	return retval;
+}
+
+static void endpoint_free_minor(struct ep_device *ep_dev)
+{
+	idr_remove(&endpoint_idr, ep_dev->minor);
+}
+
 static struct endpoint_class {
 	struct kref kref;
 	struct class *class;
@@ -176,11 +230,20 @@ static int init_endpoint_class(void)
 	ep_class->class = class_create(THIS_MODULE, "usb_endpoint");
 	if (IS_ERR(ep_class->class)) {
 		result = IS_ERR(ep_class->class);
-		kfree(ep_class);
-		ep_class = NULL;
-		goto exit;
+		goto class_create_error;
 	}
 
+	result = usb_endpoint_major_init();
+	if (result)
+		goto endpoint_major_error;
+
+	goto exit;
+
+endpoint_major_error:
+	class_destroy(ep_class->class);
+class_create_error:
+	kfree(ep_class);
+	ep_class = NULL;
 exit:
 	return result;
 }
@@ -191,6 +254,7 @@ static void release_endpoint_class(struct kref *kref)
 	class_destroy(ep_class->class);
 	kfree(ep_class);
 	ep_class = NULL;
+	usb_endpoint_major_cleanup();
 }
 
 static void destroy_endpoint_class(void)
@@ -213,7 +277,6 @@ int usb_create_ep_files(struct device *parent,
 {
 	char name[8];
 	struct ep_device *ep_dev;
-	int minor;
 	int retval;
 
 	retval = init_endpoint_class();
@@ -226,12 +289,16 @@ int usb_create_ep_files(struct device *parent,
 		goto error_alloc;
 	}
 
-	/* fun calculation to determine the minor of this endpoint */
-	minor = (((udev->bus->busnum - 1) * 128) * 16) + (udev->devnum - 1);
+	retval = endpoint_get_minor(ep_dev);
+	if (retval) {
+		dev_err(parent, "can not allocate minor number for %s",
+			ep_dev->dev.bus_id);
+		goto error_register;
+	}
 
 	ep_dev->desc = &endpoint->desc;
 	ep_dev->udev = udev;
-	ep_dev->dev.devt = MKDEV(442, minor);	// FIXME fake number...
+	ep_dev->dev.devt = MKDEV(usb_endpoint_major, ep_dev->minor);
 	ep_dev->dev.class = ep_class->class;
 	ep_dev->dev.parent = parent;
 	ep_dev->dev.release = ep_device_release;
@@ -241,7 +308,7 @@ int usb_create_ep_files(struct device *parent,
 
 	retval = device_register(&ep_dev->dev);
 	if (retval)
-		goto error_register;
+		goto error_chrdev;
 	retval = sysfs_create_group(&ep_dev->dev.kobj, &ep_dev_attr_grp);
 	if (retval)
 		goto error_group;
@@ -261,6 +328,9 @@ error_group:
 	destroy_endpoint_class();
 	return retval;
 
+error_chrdev:
+	endpoint_free_minor(ep_dev);
+
 error_register:
 	kfree(ep_dev);
 error_alloc:
@@ -271,14 +341,16 @@ exit:
 
 void usb_remove_ep_files(struct usb_host_endpoint *endpoint)
 {
+	struct ep_device *ep_dev = endpoint->ep_dev;
 
-	if (endpoint->ep_dev) {
+	if (ep_dev) {
 		char name[8];
 
 		sprintf(name, "ep_%02x", endpoint->desc.bEndpointAddress);
-		sysfs_remove_link(&endpoint->ep_dev->dev.parent->kobj, name);
-		sysfs_remove_group(&endpoint->ep_dev->dev.kobj, &ep_dev_attr_grp);
-		device_unregister(&endpoint->ep_dev->dev);
+		sysfs_remove_link(&ep_dev->dev.parent->kobj, name);
+		sysfs_remove_group(&ep_dev->dev.kobj, &ep_dev_attr_grp);
+		endpoint_free_minor(ep_dev);
+		device_unregister(&ep_dev->dev);
 		endpoint->ep_dev = NULL;
 		destroy_endpoint_class();
 	}
diff --git a/drivers/usb/core/hcd.c b/drivers/usb/core/hcd.c
index afa2dd203329..10064af65d17 100644
--- a/drivers/usb/core/hcd.c
+++ b/drivers/usb/core/hcd.c
@@ -256,7 +256,9 @@ static const u8 hs_rh_config_descriptor [] = {
 	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) */
+		    /* __le16 ep_wMaxPacketSize; 1 + (MAX_ROOT_PORTS / 8)
+		     * see hub.c:hub_configure() for details. */
+	(USB_MAXCHILDREN + 1 + 7) / 8, 0x00,
 	0x0c        /*  __u8  ep_bInterval; (256ms -- usb 2.0 spec) */
 };
 
diff --git a/drivers/usb/core/hub.c b/drivers/usb/core/hub.c
index ad0ffbe8f7d7..39186db1015f 100644
--- a/drivers/usb/core/hub.c
+++ b/drivers/usb/core/hub.c
@@ -31,6 +31,47 @@
 #include "hcd.h"
 #include "hub.h"
 
+struct usb_hub {
+	struct device		*intfdev;	/* the "interface" device */
+	struct usb_device	*hdev;
+	struct urb		*urb;		/* for interrupt polling pipe */
+
+	/* buffer for urb ... with extra space in case of babble */
+	char			(*buffer)[8];
+	dma_addr_t		buffer_dma;	/* DMA address for buffer */
+	union {
+		struct usb_hub_status	hub;
+		struct usb_port_status	port;
+	}			*status;	/* buffer for status reports */
+
+	int			error;		/* last reported error */
+	int			nerrors;	/* track consecutive errors */
+
+	struct list_head	event_list;	/* hubs w/data or errs ready */
+	unsigned long		event_bits[1];	/* status change bitmask */
+	unsigned long		change_bits[1];	/* ports with logical connect
+							status change */
+	unsigned long		busy_bits[1];	/* ports being reset or
+							resumed */
+#if USB_MAXCHILDREN > 31 /* 8*sizeof(unsigned long) - 1 */
+#error event_bits[] is too short!
+#endif
+
+	struct usb_hub_descriptor *descriptor;	/* class descriptor */
+	struct usb_tt		tt;		/* Transaction Translator */
+
+	unsigned		mA_per_port;	/* current for each child */
+
+	unsigned		limited_power:1;
+	unsigned		quiescing:1;
+	unsigned		activating:1;
+
+	unsigned		has_indicators:1;
+	u8			indicator[USB_MAXCHILDREN];
+	struct work_struct	leds;
+};
+
+
 /* Protect struct usb_device->state and ->children members
  * Note: Both are also protected by ->dev.sem, except that ->state can
  * change to USB_STATE_NOTATTACHED even when the semaphore isn't held. */
@@ -45,6 +86,16 @@ static DECLARE_WAIT_QUEUE_HEAD(khubd_wait);
 
 static struct task_struct *khubd_task;
 
+/* multithreaded probe logic */
+static int multithread_probe =
+#ifdef CONFIG_USB_MULTITHREAD_PROBE
+	1;
+#else
+	0;
+#endif
+module_param(multithread_probe, bool, S_IRUGO);
+MODULE_PARM_DESC(multithread_probe, "Run each USB device probe in a new thread");
+
 /* cycle leds on hubs that aren't blinking for attention */
 static int blinkenlights = 0;
 module_param (blinkenlights, bool, S_IRUGO);
@@ -277,6 +328,9 @@ static void kick_khubd(struct usb_hub *hub)
 {
 	unsigned long	flags;
 
+	/* Suppress autosuspend until khubd runs */
+	to_usb_interface(hub->intfdev)->pm_usage_cnt = 1;
+
 	spin_lock_irqsave(&hub_event_lock, flags);
 	if (list_empty(&hub->event_list)) {
 		list_add_tail(&hub->event_list, &hub_event_list);
@@ -459,7 +513,6 @@ static void hub_quiesce(struct usb_hub *hub)
 	/* (nonblocking) khubd and related activity won't re-trigger */
 	hub->quiescing = 1;
 	hub->activating = 0;
-	hub->resume_root_hub = 0;
 
 	/* (blocking) stop khubd and related activity */
 	usb_kill_urb(hub->urb);
@@ -475,7 +528,7 @@ static void hub_activate(struct usb_hub *hub)
 
 	hub->quiescing = 0;
 	hub->activating = 1;
-	hub->resume_root_hub = 0;
+
 	status = usb_submit_urb(hub->urb, GFP_NOIO);
 	if (status < 0)
 		dev_err(hub->intfdev, "activate --> %d\n", status);
@@ -761,7 +814,12 @@ static int hub_configure(struct usb_hub *hub,
 		dev_dbg(hub_dev, "%sover-current condition exists\n",
 			(hubstatus & HUB_STATUS_OVERCURRENT) ? "" : "no ");
 
-	/* set up the interrupt endpoint */
+	/* set up the interrupt endpoint
+	 * We use the EP's maxpacket size instead of (PORTS+1+7)/8
+	 * bytes as USB2.0[11.12.3] says because some hubs are known
+	 * to send more data (and thus cause overflow). For root hubs,
+	 * maxpktsize is defined in hcd.c's fake endpoint descriptors
+	 * to be big enough for at least USB_MAXCHILDREN ports. */
 	pipe = usb_rcvintpipe(hdev, endpoint->bEndpointAddress);
 	maxp = usb_maxpacket(hdev, pipe, usb_pipeout(pipe));
 
@@ -885,6 +943,7 @@ descriptor_error:
 	INIT_DELAYED_WORK(&hub->leds, led_work);
 
 	usb_set_intfdata (intf, hub);
+	intf->needs_remote_wakeup = 1;
 
 	if (hdev->speed == USB_SPEED_HIGH)
 		highspeed_hubs++;
@@ -982,6 +1041,8 @@ static void recursively_mark_NOTATTACHED(struct usb_device *udev)
 		if (udev->children[i])
 			recursively_mark_NOTATTACHED(udev->children[i]);
 	}
+	if (udev->state == USB_STATE_SUSPENDED)
+		udev->discon_suspended = 1;
 	udev->state = USB_STATE_NOTATTACHED;
 }
 
@@ -1171,6 +1232,14 @@ void usb_disconnect(struct usb_device **pdev)
 	*pdev = NULL;
 	spin_unlock_irq(&device_state_lock);
 
+	/* Decrement the parent's count of unsuspended children */
+	if (udev->parent) {
+		usb_pm_lock(udev);
+		if (!udev->discon_suspended)
+			usb_autosuspend_device(udev->parent);
+		usb_pm_unlock(udev);
+	}
+
 	put_device(&udev->dev);
 }
 
@@ -1193,29 +1262,17 @@ static inline void show_string(struct usb_device *udev, char *id, char *string)
 static int __usb_port_suspend(struct usb_device *, int port1);
 #endif
 
-/**
- * usb_new_device - perform initial device setup (usbcore-internal)
- * @udev: newly addressed device (in ADDRESS state)
- *
- * This is called with devices which have been enumerated, but not yet
- * configured.  The device descriptor is available, but not descriptors
- * for any device configuration.  The caller must have locked either
- * the parent hub (if udev is a normal device) or else the
- * usb_bus_list_lock (if udev is a root hub).  The parent's pointer to
- * udev has already been installed, but udev is not yet visible through
- * sysfs or other filesystem code.
- *
- * Returns 0 for success (device is configured and listed, with its
- * interfaces, in sysfs); else a negative errno value.
- *
- * This call is synchronous, and may not be used in an interrupt context.
- *
- * Only the hub driver or root-hub registrar should ever call this.
- */
-int usb_new_device(struct usb_device *udev)
+static int __usb_new_device(void *void_data)
 {
+	struct usb_device *udev = void_data;
 	int err;
 
+	/* Lock ourself into memory in order to keep a probe sequence
+	 * sleeping in a new thread from allowing us to be unloaded.
+	 */
+	if (!try_module_get(THIS_MODULE))
+		return -EINVAL;
+
 	err = usb_get_configuration(udev);
 	if (err < 0) {
 		dev_err(&udev->dev, "can't read configurations, error %d\n",
@@ -1311,13 +1368,56 @@ int usb_new_device(struct usb_device *udev)
 		goto fail;
 	}
 
-	return 0;
+	/* Increment the parent's count of unsuspended children */
+	if (udev->parent)
+		usb_autoresume_device(udev->parent);
+
+exit:
+	module_put(THIS_MODULE);
+	return err;
 
 fail:
 	usb_set_device_state(udev, USB_STATE_NOTATTACHED);
-	return err;
+	goto exit;
 }
 
+/**
+ * usb_new_device - perform initial device setup (usbcore-internal)
+ * @udev: newly addressed device (in ADDRESS state)
+ *
+ * This is called with devices which have been enumerated, but not yet
+ * configured.  The device descriptor is available, but not descriptors
+ * for any device configuration.  The caller must have locked either
+ * the parent hub (if udev is a normal device) or else the
+ * usb_bus_list_lock (if udev is a root hub).  The parent's pointer to
+ * udev has already been installed, but udev is not yet visible through
+ * sysfs or other filesystem code.
+ *
+ * The return value for this function depends on if the
+ * multithread_probe variable is set or not.  If it's set, it will
+ * return a if the probe thread was successfully created or not.  If the
+ * variable is not set, it will return if the device is configured
+ * properly or not.  interfaces, in sysfs); else a negative errno value.
+ *
+ * This call is synchronous, and may not be used in an interrupt context.
+ *
+ * Only the hub driver or root-hub registrar should ever call this.
+ */
+int usb_new_device(struct usb_device *udev)
+{
+	struct task_struct *probe_task;
+	int ret = 0;
+
+	if (multithread_probe) {
+		probe_task = kthread_run(__usb_new_device, udev,
+					 "usb-probe-%s", udev->devnum);
+		if (IS_ERR(probe_task))
+			ret = PTR_ERR(probe_task);
+	} else
+		ret = __usb_new_device(udev);
+
+	return ret;
+}
 
 static int hub_port_status(struct usb_hub *hub, int port1,
 			       u16 *status, u16 *change)
@@ -1325,10 +1425,12 @@ static int hub_port_status(struct usb_hub *hub, int port1,
 	int ret;
 
 	ret = get_port_status(hub->hdev, port1, &hub->status->port);
-	if (ret < 0)
+	if (ret < 4) {
 		dev_err (hub->intfdev,
 			"%s failed (err = %d)\n", __FUNCTION__, ret);
-	else {
+		if (ret >= 0)
+			ret = -EIO;
+	} else {
 		*status = le16_to_cpu(hub->status->port.wPortStatus);
 		*change = le16_to_cpu(hub->status->port.wPortChange); 
 		ret = 0;
@@ -1676,6 +1778,12 @@ static int
 hub_port_resume(struct usb_hub *hub, int port1, struct usb_device *udev)
 {
 	int	status;
+	u16	portchange, portstatus;
+
+	/* Skip the initial Clear-Suspend step for a remote wakeup */
+	status = hub_port_status(hub, port1, &portstatus, &portchange);
+	if (status == 0 && !(portstatus & USB_PORT_STAT_SUSPEND))
+		goto SuspendCleared;
 
 	// dev_dbg(hub->intfdev, "resume port %d\n", port1);
 
@@ -1689,9 +1797,6 @@ hub_port_resume(struct usb_hub *hub, int port1, struct usb_device *udev)
 			"can't resume port %d, status %d\n",
 			port1, status);
 	} else {
-		u16		devstatus;
-		u16		portchange;
-
 		/* drive resume for at least 20 msec */
 		if (udev)
 			dev_dbg(&udev->dev, "usb %sresume\n",
@@ -1706,16 +1811,15 @@ hub_port_resume(struct usb_hub *hub, int port1, struct usb_device *udev)
 		 * stop resume signaling.  Then finish the resume
 		 * sequence.
 		 */
-		devstatus = portchange = 0;
-		status = hub_port_status(hub, port1,
-				&devstatus, &portchange);
+		status = hub_port_status(hub, port1, &portstatus, &portchange);
+SuspendCleared:
 		if (status < 0
-				|| (devstatus & LIVE_FLAGS) != LIVE_FLAGS
-				|| (devstatus & USB_PORT_STAT_SUSPEND) != 0
+				|| (portstatus & LIVE_FLAGS) != LIVE_FLAGS
+				|| (portstatus & USB_PORT_STAT_SUSPEND) != 0
 				) {
 			dev_dbg(hub->intfdev,
 				"port %d status %04x.%04x after resume, %d\n",
-				port1, portchange, devstatus, status);
+				port1, portchange, portstatus, status);
 			if (status >= 0)
 				status = -ENODEV;
 		} else {
@@ -1776,23 +1880,16 @@ static int remote_wakeup(struct usb_device *udev)
 {
 	int	status = 0;
 
-	/* All this just to avoid sending a port-resume message
-	 * to the parent hub! */
-
 	usb_lock_device(udev);
-	usb_pm_lock(udev);
 	if (udev->state == USB_STATE_SUSPENDED) {
 		dev_dbg(&udev->dev, "usb %sresume\n", "wakeup-");
-		/* TRSMRCY = 10 msec */
-		msleep(10);
-		status = finish_port_resume(udev);
+		status = usb_autoresume_device(udev);
+
+		/* Give the interface drivers a chance to do something,
+		 * then autosuspend the device again. */
 		if (status == 0)
-			udev->dev.power.power_state.event = PM_EVENT_ON;
+			usb_autosuspend_device(udev);
 	}
-	usb_pm_unlock(udev);
-
-	if (status == 0)
-		usb_autoresume_device(udev, 0);
 	usb_unlock_device(udev);
 	return status;
 }
@@ -1856,6 +1953,8 @@ static int hub_suspend(struct usb_interface *intf, pm_message_t msg)
 		}
 	}
 
+	dev_dbg(&intf->dev, "%s\n", __FUNCTION__);
+
 	/* "global suspend" of the downstream HC-to-USB interface */
 	if (!hdev->parent) {
 		struct usb_bus	*bus = hdev->bus;
@@ -1878,10 +1977,12 @@ static int hub_suspend(struct usb_interface *intf, pm_message_t msg)
 
 static int hub_resume(struct usb_interface *intf)
 {
-	struct usb_device	*hdev = interface_to_usbdev(intf);
 	struct usb_hub		*hub = usb_get_intfdata (intf);
+	struct usb_device	*hdev = hub->hdev;
 	int			status;
 
+	dev_dbg(&intf->dev, "%s\n", __FUNCTION__);
+
 	/* "global resume" of the downstream HC-to-USB interface */
 	if (!hdev->parent) {
 		struct usb_bus	*bus = hdev->bus;
@@ -1920,7 +2021,6 @@ void usb_resume_root_hub(struct usb_device *hdev)
 {
 	struct usb_hub *hub = hdev_to_hub(hdev);
 
-	hub->resume_root_hub = 1;
 	kick_khubd(hub);
 }
 
@@ -2557,16 +2657,13 @@ static void hub_events(void)
 		intf = to_usb_interface(hub->intfdev);
 		hub_dev = &intf->dev;
 
-		i = hub->resume_root_hub;
-
-		dev_dbg(hub_dev, "state %d ports %d chg %04x evt %04x%s\n",
+		dev_dbg(hub_dev, "state %d ports %d chg %04x evt %04x\n",
 				hdev->state, hub->descriptor
 					? hub->descriptor->bNbrPorts
 					: 0,
 				/* NOTE: expects max 15 ports... */
 				(u16) hub->change_bits[0],
-				(u16) hub->event_bits[0],
-				i ? ", resume root" : "");
+				(u16) hub->event_bits[0]);
 
 		usb_get_intf(intf);
 		spin_unlock_irq(&hub_event_lock);
@@ -2587,16 +2684,16 @@ static void hub_events(void)
 			goto loop;
 		}
 
-		/* Is this is a root hub wanting to reactivate the downstream
-		 * ports?  If so, be sure the interface resumes even if its
-		 * stub "device" node was never suspended.
-		 */
-		if (i)
-			usb_autoresume_device(hdev, 0);
+		/* Autoresume */
+		ret = usb_autopm_get_interface(intf);
+		if (ret) {
+			dev_dbg(hub_dev, "Can't autoresume: %d\n", ret);
+			goto loop;
+		}
 
-		/* If this is an inactive or suspended hub, do nothing */
+		/* If this is an inactive hub, do nothing */
 		if (hub->quiescing)
-			goto loop;
+			goto loop_autopm;
 
 		if (hub->error) {
 			dev_dbg (hub_dev, "resetting for error %d\n",
@@ -2606,7 +2703,7 @@ static void hub_events(void)
 			if (ret) {
 				dev_dbg (hub_dev,
 					"error resetting hub: %d\n", ret);
-				goto loop;
+				goto loop_autopm;
 			}
 
 			hub->nerrors = 0;
@@ -2734,6 +2831,10 @@ static void hub_events(void)
 		if (!hdev->parent && !hub->busy_bits[0])
 			usb_enable_root_hub_irq(hdev->bus);
 
+loop_autopm:
+		/* Allow autosuspend if we're not going to run again */
+		if (list_empty(&hub->event_list))
+			usb_autopm_enable(intf);
 loop:
 		usb_unlock_device(hdev);
 		usb_put_intf(intf);
@@ -2775,6 +2876,7 @@ static struct usb_driver hub_driver = {
 	.post_reset =	hub_post_reset,
 	.ioctl =	hub_ioctl,
 	.id_table =	hub_id_table,
+	.supports_autosuspend =	1,
 };
 
 int usb_hub_init(void)
@@ -2999,7 +3101,7 @@ int usb_reset_composite_device(struct usb_device *udev,
 	}
 
 	/* Prevent autosuspend during the reset */
-	usb_autoresume_device(udev, 1);
+	usb_autoresume_device(udev);
 
 	if (iface && iface->condition != USB_INTERFACE_BINDING)
 		iface = NULL;
@@ -3042,7 +3144,7 @@ int usb_reset_composite_device(struct usb_device *udev,
 		}
 	}
 
-	usb_autosuspend_device(udev, 1);
+	usb_autosuspend_device(udev);
 	return ret;
 }
 EXPORT_SYMBOL(usb_reset_composite_device);
diff --git a/drivers/usb/core/hub.h b/drivers/usb/core/hub.h
index 035d3ef35888..cf9559c6c9b6 100644
--- a/drivers/usb/core/hub.h
+++ b/drivers/usb/core/hub.h
@@ -192,45 +192,4 @@ struct usb_tt_clear {
 
 extern void usb_hub_tt_clear_buffer (struct usb_device *dev, int pipe);
 
-struct usb_hub {
-	struct device		*intfdev;	/* the "interface" device */
-	struct usb_device	*hdev;
-	struct urb		*urb;		/* for interrupt polling pipe */
-
-	/* buffer for urb ... with extra space in case of babble */
-	char			(*buffer)[8];
-	dma_addr_t		buffer_dma;	/* DMA address for buffer */
-	union {
-		struct usb_hub_status	hub;
-		struct usb_port_status	port;
-	}			*status;	/* buffer for status reports */
-
-	int			error;		/* last reported error */
-	int			nerrors;	/* track consecutive errors */
-
-	struct list_head	event_list;	/* hubs w/data or errs ready */
-	unsigned long		event_bits[1];	/* status change bitmask */
-	unsigned long		change_bits[1];	/* ports with logical connect
-							status change */
-	unsigned long		busy_bits[1];	/* ports being reset or
-							resumed */
-#if USB_MAXCHILDREN > 31 /* 8*sizeof(unsigned long) - 1 */
-#error event_bits[] is too short!
-#endif
-
-	struct usb_hub_descriptor *descriptor;	/* class descriptor */
-	struct usb_tt		tt;		/* Transaction Translator */
-
-	unsigned		mA_per_port;	/* current for each child */
-
-	unsigned		limited_power:1;
-	unsigned		quiescing:1;
-	unsigned		activating:1;
-	unsigned		resume_root_hub:1;
-
-	unsigned		has_indicators:1;
-	enum hub_led_mode	indicator[USB_MAXCHILDREN];
-	struct delayed_work	leds;
-};
-
 #endif /* __LINUX_HUB_H */
diff --git a/drivers/usb/core/message.c b/drivers/usb/core/message.c
index 89572bc021b1..7390b67c609d 100644
--- a/drivers/usb/core/message.c
+++ b/drivers/usb/core/message.c
@@ -764,7 +764,7 @@ int usb_string(struct usb_device *dev, int index, char *buf, size_t size)
 			err = -EINVAL;
 			goto errout;
 		} else {
-			dev->have_langid = -1;
+			dev->have_langid = 1;
 			dev->string_langid = tbuf[2] | (tbuf[3]<< 8);
 				/* always use the first langid listed */
 			dev_dbg (&dev->dev, "default language 0x%04x\n",
@@ -1398,7 +1398,7 @@ free_interfaces:
 	}
 
 	/* Wake up the device so we can send it the Set-Config request */
-	ret = usb_autoresume_device(dev, 1);
+	ret = usb_autoresume_device(dev);
 	if (ret)
 		goto free_interfaces;
 
@@ -1421,7 +1421,7 @@ free_interfaces:
 	dev->actconfig = cp;
 	if (!cp) {
 		usb_set_device_state(dev, USB_STATE_ADDRESS);
-		usb_autosuspend_device(dev, 1);
+		usb_autosuspend_device(dev);
 		goto free_interfaces;
 	}
 	usb_set_device_state(dev, USB_STATE_CONFIGURED);
@@ -1490,7 +1490,7 @@ free_interfaces:
 		usb_create_sysfs_intf_files (intf);
 	}
 
-	usb_autosuspend_device(dev, 1);
+	usb_autosuspend_device(dev);
 	return 0;
 }
 
diff --git a/drivers/usb/core/usb.c b/drivers/usb/core/usb.c
index ab2f68fc7d2d..02426d0b9a34 100644
--- a/drivers/usb/core/usb.c
+++ b/drivers/usb/core/usb.c
@@ -200,13 +200,6 @@ static void ksuspend_usb_cleanup(void)
 	destroy_workqueue(ksuspend_usb_wq);
 }
 
-#else
-
-#define ksuspend_usb_init()	0
-#define ksuspend_usb_cleanup()	do {} while (0)
-
-#endif
-
 #ifdef	CONFIG_USB_SUSPEND
 
 /* usb_autosuspend_work - callback routine to autosuspend a USB device */
@@ -226,7 +219,14 @@ static void usb_autosuspend_work(struct work_struct *work)
 static void usb_autosuspend_work(struct work_struct *work)
 {}
 
-#endif
+#endif	/* CONFIG_USB_SUSPEND */
+
+#else
+
+#define ksuspend_usb_init()	0
+#define ksuspend_usb_cleanup()	do {} while (0)
+
+#endif	/* CONFIG_PM */
 
 /**
  * usb_alloc_dev - usb device constructor (usbcore-internal)
@@ -538,138 +538,6 @@ int usb_get_current_frame_number(struct usb_device *dev)
 	return usb_hcd_get_frame_number (dev);
 }
 
-/**
- * usb_endpoint_dir_in - check if the endpoint has IN direction
- * @epd: endpoint to be checked
- *
- * Returns true if the endpoint is of type IN, otherwise it returns false.
- */
-int usb_endpoint_dir_in(const struct usb_endpoint_descriptor *epd)
-{
-	return ((epd->bEndpointAddress & USB_ENDPOINT_DIR_MASK) == USB_DIR_IN);
-}
-
-/**
- * usb_endpoint_dir_out - check if the endpoint has OUT direction
- * @epd: endpoint to be checked
- *
- * Returns true if the endpoint is of type OUT, otherwise it returns false.
- */
-int usb_endpoint_dir_out(const struct usb_endpoint_descriptor *epd)
-{
-	return ((epd->bEndpointAddress & USB_ENDPOINT_DIR_MASK) == USB_DIR_OUT);
-}
-
-/**
- * usb_endpoint_xfer_bulk - check if the endpoint has bulk transfer type
- * @epd: endpoint to be checked
- *
- * Returns true if the endpoint is of type bulk, otherwise it returns false.
- */
-int usb_endpoint_xfer_bulk(const struct usb_endpoint_descriptor *epd)
-{
-	return ((epd->bmAttributes & USB_ENDPOINT_XFERTYPE_MASK) ==
-		USB_ENDPOINT_XFER_BULK);
-}
-
-/**
- * usb_endpoint_xfer_int - check if the endpoint has interrupt transfer type
- * @epd: endpoint to be checked
- *
- * Returns true if the endpoint is of type interrupt, otherwise it returns
- * false.
- */
-int usb_endpoint_xfer_int(const struct usb_endpoint_descriptor *epd)
-{
-	return ((epd->bmAttributes & USB_ENDPOINT_XFERTYPE_MASK) ==
-		USB_ENDPOINT_XFER_INT);
-}
-
-/**
- * usb_endpoint_xfer_isoc - check if the endpoint has isochronous transfer type
- * @epd: endpoint to be checked
- *
- * Returns true if the endpoint is of type isochronous, otherwise it returns
- * false.
- */
-int usb_endpoint_xfer_isoc(const struct usb_endpoint_descriptor *epd)
-{
-	return ((epd->bmAttributes & USB_ENDPOINT_XFERTYPE_MASK) ==
-		USB_ENDPOINT_XFER_ISOC);
-}
-
-/**
- * usb_endpoint_is_bulk_in - check if the endpoint is bulk IN
- * @epd: endpoint to be checked
- *
- * Returns true if the endpoint has bulk transfer type and IN direction,
- * otherwise it returns false.
- */
-int usb_endpoint_is_bulk_in(const struct usb_endpoint_descriptor *epd)
-{
-	return (usb_endpoint_xfer_bulk(epd) && usb_endpoint_dir_in(epd));
-}
-
-/**
- * usb_endpoint_is_bulk_out - check if the endpoint is bulk OUT
- * @epd: endpoint to be checked
- *
- * Returns true if the endpoint has bulk transfer type and OUT direction,
- * otherwise it returns false.
- */
-int usb_endpoint_is_bulk_out(const struct usb_endpoint_descriptor *epd)
-{
-	return (usb_endpoint_xfer_bulk(epd) && usb_endpoint_dir_out(epd));
-}
-
-/**
- * usb_endpoint_is_int_in - check if the endpoint is interrupt IN
- * @epd: endpoint to be checked
- *
- * Returns true if the endpoint has interrupt transfer type and IN direction,
- * otherwise it returns false.
- */
-int usb_endpoint_is_int_in(const struct usb_endpoint_descriptor *epd)
-{
-	return (usb_endpoint_xfer_int(epd) && usb_endpoint_dir_in(epd));
-}
-
-/**
- * usb_endpoint_is_int_out - check if the endpoint is interrupt OUT
- * @epd: endpoint to be checked
- *
- * Returns true if the endpoint has interrupt transfer type and OUT direction,
- * otherwise it returns false.
- */
-int usb_endpoint_is_int_out(const struct usb_endpoint_descriptor *epd)
-{
-	return (usb_endpoint_xfer_int(epd) && usb_endpoint_dir_out(epd));
-}
-
-/**
- * usb_endpoint_is_isoc_in - check if the endpoint is isochronous IN
- * @epd: endpoint to be checked
- *
- * Returns true if the endpoint has isochronous transfer type and IN direction,
- * otherwise it returns false.
- */
-int usb_endpoint_is_isoc_in(const struct usb_endpoint_descriptor *epd)
-{
-	return (usb_endpoint_xfer_isoc(epd) && usb_endpoint_dir_in(epd));
-}
-
-/**
- * usb_endpoint_is_isoc_out - check if the endpoint is isochronous OUT
- * @epd: endpoint to be checked
- *
- * Returns true if the endpoint has isochronous transfer type and OUT direction,
- * otherwise it returns false.
- */
-int usb_endpoint_is_isoc_out(const struct usb_endpoint_descriptor *epd)
-{
-	return (usb_endpoint_xfer_isoc(epd) && usb_endpoint_dir_out(epd));
-}
-
 /*-------------------------------------------------------------------*/
 /*
  * __usb_get_extra_descriptor() finds a descriptor of specific type in the
@@ -1103,18 +971,6 @@ EXPORT_SYMBOL(__usb_get_extra_descriptor);
 EXPORT_SYMBOL(usb_find_device);
 EXPORT_SYMBOL(usb_get_current_frame_number);
 
-EXPORT_SYMBOL_GPL(usb_endpoint_dir_in);
-EXPORT_SYMBOL_GPL(usb_endpoint_dir_out);
-EXPORT_SYMBOL_GPL(usb_endpoint_xfer_bulk);
-EXPORT_SYMBOL_GPL(usb_endpoint_xfer_int);
-EXPORT_SYMBOL_GPL(usb_endpoint_xfer_isoc);
-EXPORT_SYMBOL_GPL(usb_endpoint_is_bulk_in);
-EXPORT_SYMBOL_GPL(usb_endpoint_is_bulk_out);
-EXPORT_SYMBOL_GPL(usb_endpoint_is_int_in);
-EXPORT_SYMBOL_GPL(usb_endpoint_is_int_out);
-EXPORT_SYMBOL_GPL(usb_endpoint_is_isoc_in);
-EXPORT_SYMBOL_GPL(usb_endpoint_is_isoc_out);
-
 EXPORT_SYMBOL (usb_buffer_alloc);
 EXPORT_SYMBOL (usb_buffer_free);
 
diff --git a/drivers/usb/core/usb.h b/drivers/usb/core/usb.h
index 13322e33f912..17830a81be14 100644
--- a/drivers/usb/core/usb.h
+++ b/drivers/usb/core/usb.h
@@ -64,14 +64,13 @@ static inline void usb_pm_unlock(struct usb_device *udev) {}
 
 #define USB_AUTOSUSPEND_DELAY	(HZ*2)
 
-extern void usb_autosuspend_device(struct usb_device *udev, int dec_busy_cnt);
-extern int usb_autoresume_device(struct usb_device *udev, int inc_busy_cnt);
+extern void usb_autosuspend_device(struct usb_device *udev);
+extern int usb_autoresume_device(struct usb_device *udev);
 
 #else
 
-#define usb_autosuspend_device(udev, dec_busy_cnt)	do {} while (0)
-static inline int usb_autoresume_device(struct usb_device *udev,
-		int inc_busy_cnt)
+#define usb_autosuspend_device(udev)	do {} while (0)
+static inline int usb_autoresume_device(struct usb_device *udev)
 {
 	return 0;
 }
diff --git a/drivers/usb/gadget/ether.c b/drivers/usb/gadget/ether.c
index 107119c54301..d15bf22b9a03 100644
--- a/drivers/usb/gadget/ether.c
+++ b/drivers/usb/gadget/ether.c
@@ -1894,13 +1894,13 @@ static int eth_start_xmit (struct sk_buff *skb, struct net_device *net)
 	if (!eth_is_promisc (dev)) {
 		u8		*dest = skb->data;
 
-		if (dest [0] & 0x01) {
+		if (is_multicast_ether_addr(dest)) {
 			u16	type;
 
 			/* ignores USB_CDC_PACKET_TYPE_MULTICAST and host
 			 * SET_ETHERNET_MULTICAST_FILTERS requests
 			 */
-			if (memcmp (dest, net->broadcast, ETH_ALEN) == 0)
+			if (is_broadcast_ether_addr(dest))
 				type = USB_CDC_PACKET_TYPE_BROADCAST;
 			else
 				type = USB_CDC_PACKET_TYPE_ALL_MULTICAST;
diff --git a/drivers/usb/gadget/lh7a40x_udc.c b/drivers/usb/gadget/lh7a40x_udc.c
index 179259664c18..4a991564a03e 100644
--- a/drivers/usb/gadget/lh7a40x_udc.c
+++ b/drivers/usb/gadget/lh7a40x_udc.c
@@ -83,7 +83,6 @@ static int lh7a40x_queue(struct usb_ep *ep, struct usb_request *, gfp_t);
 static int lh7a40x_dequeue(struct usb_ep *ep, struct usb_request *);
 static int lh7a40x_set_halt(struct usb_ep *ep, int);
 static int lh7a40x_fifo_status(struct usb_ep *ep);
-static int lh7a40x_fifo_status(struct usb_ep *ep);
 static void lh7a40x_fifo_flush(struct usb_ep *ep);
 static void lh7a40x_ep0_kick(struct lh7a40x_udc *dev, struct lh7a40x_ep *ep);
 static void lh7a40x_handle_ep0(struct lh7a40x_udc *dev, u32 intr);
diff --git a/drivers/usb/gadget/net2280.c b/drivers/usb/gadget/net2280.c
index 3acc896a5d4c..0b590831582c 100644
--- a/drivers/usb/gadget/net2280.c
+++ b/drivers/usb/gadget/net2280.c
@@ -1040,6 +1040,7 @@ net2280_queue (struct usb_ep *_ep, struct usb_request *_req, gfp_t gfp_flags)
 
 	} /* else the irq handler advances the queue. */
 
+	ep->responded = 1;
 	if (req)
 		list_add_tail (&req->queue, &ep->queue);
 done:
@@ -2188,7 +2189,8 @@ static void handle_ep_small (struct net2280_ep *ep)
 					ep->stopped = 1;
 					set_halt (ep);
 					mode = 2;
-				} else if (!req && !ep->stopped)
+				} else if (ep->responded &&
+						!req && !ep->stopped)
 					write_fifo (ep, NULL);
 			}
 		} else {
@@ -2203,7 +2205,7 @@ static void handle_ep_small (struct net2280_ep *ep)
 			} else if (((t & (1 << DATA_OUT_PING_TOKEN_INTERRUPT))
 					&& req
 					&& req->req.actual == req->req.length)
-					|| !req) {
+					|| (ep->responded && !req)) {
 				ep->dev->protocol_stall = 1;
 				set_halt (ep);
 				ep->stopped = 1;
@@ -2469,6 +2471,7 @@ static void handle_stat0_irqs (struct net2280 *dev, u32 stat)
 		/* we made the hardware handle most lowlevel requests;
 		 * everything else goes uplevel to the gadget code.
 		 */
+		ep->responded = 1;
 		switch (u.r.bRequest) {
 		case USB_REQ_GET_STATUS: {
 			struct net2280_ep	*e;
@@ -2537,6 +2540,7 @@ delegate:
 				u.r.bRequestType, u.r.bRequest,
 				w_value, w_index, w_length,
 				readl (&ep->regs->ep_cfg));
+			ep->responded = 0;
 			spin_unlock (&dev->lock);
 			tmp = dev->driver->setup (&dev->gadget, &u.r);
 			spin_lock (&dev->lock);
diff --git a/drivers/usb/gadget/net2280.h b/drivers/usb/gadget/net2280.h
index 957d6df34015..44ca139983d8 100644
--- a/drivers/usb/gadget/net2280.h
+++ b/drivers/usb/gadget/net2280.h
@@ -110,7 +110,8 @@ struct net2280_ep {
 						out_overflow : 1,
 						stopped : 1,
 						is_in : 1,
-						is_iso : 1;
+						is_iso : 1,
+						responded : 1;
 };
 
 static inline void allow_status (struct net2280_ep *ep)
diff --git a/drivers/usb/gadget/pxa2xx_udc.c b/drivers/usb/gadget/pxa2xx_udc.c
index 671c24bc6d75..1ed506e95985 100644
--- a/drivers/usb/gadget/pxa2xx_udc.c
+++ b/drivers/usb/gadget/pxa2xx_udc.c
@@ -2472,6 +2472,7 @@ static struct pxa2xx_udc memory = {
 #define PXA210_B1		0x00000123
 #define PXA210_B0		0x00000122
 #define IXP425_A0		0x000001c1
+#define IXP425_B0		0x000001f1
 #define IXP465_AD		0x00000200
 
 /*
@@ -2509,6 +2510,7 @@ static int __init pxa2xx_udc_probe(struct platform_device *pdev)
 		break;
 #elif	defined(CONFIG_ARCH_IXP4XX)
 	case IXP425_A0:
+	case IXP425_B0:
 	case IXP465_AD:
 		dev->has_cfr = 1;
 		out_dma = 0;
diff --git a/drivers/usb/host/Kconfig b/drivers/usb/host/Kconfig
index cf10cbc98f80..cc60759083bf 100644
--- a/drivers/usb/host/Kconfig
+++ b/drivers/usb/host/Kconfig
@@ -153,7 +153,7 @@ config USB_U132_HCD
 	  adapter will *NOT* work with PC cards that do not contain an OHCI
 	  controller.
 
-	  For those PC cards that contain multiple OHCI controllers only ther
+	  For those PC cards that contain multiple OHCI controllers only the
 	  first one is used.
 
 	  The driver consists of two modules, the "ftdi-elan" module is a
diff --git a/drivers/usb/host/ehci-hcd.c b/drivers/usb/host/ehci-hcd.c
index 9030994aba98..025d33313681 100644
--- a/drivers/usb/host/ehci-hcd.c
+++ b/drivers/usb/host/ehci-hcd.c
@@ -126,6 +126,11 @@ static unsigned park = 0;
 module_param (park, uint, S_IRUGO);
 MODULE_PARM_DESC (park, "park setting; 1-3 back-to-back async packets");
 
+/* for flakey hardware, ignore overcurrent indicators */
+static int ignore_oc = 0;
+module_param (ignore_oc, bool, S_IRUGO);
+MODULE_PARM_DESC (ignore_oc, "ignore bogus hardware overcurrent indications");
+
 #define	INTR_MASK (STS_IAA | STS_FATAL | STS_PCD | STS_ERR | STS_INT)
 
 /*-------------------------------------------------------------------------*/
@@ -541,9 +546,10 @@ static int ehci_run (struct usb_hcd *hcd)
 
 	temp = HC_VERSION(readl (&ehci->caps->hc_capbase));
 	ehci_info (ehci,
-		"USB %x.%x started, EHCI %x.%02x, driver %s\n",
+		"USB %x.%x started, EHCI %x.%02x, driver %s%s\n",
 		((ehci->sbrn & 0xf0)>>4), (ehci->sbrn & 0x0f),
-		temp >> 8, temp & 0xff, DRIVER_VERSION);
+		temp >> 8, temp & 0xff, DRIVER_VERSION,
+		ignore_oc ? ", overcurrent ignored" : "");
 
 	writel (INTR_MASK, &ehci->regs->intr_enable); /* Turn On Interrupts */
 
@@ -613,9 +619,8 @@ static irqreturn_t ehci_irq (struct usb_hcd *hcd)
 		unsigned	i = HCS_N_PORTS (ehci->hcs_params);
 
 		/* resume root hub? */
-		status = readl (&ehci->regs->command);
-		if (!(status & CMD_RUN))
-			writel (status | CMD_RUN, &ehci->regs->command);
+		if (!(readl(&ehci->regs->command) & CMD_RUN))
+			usb_hcd_resume_root_hub(hcd);
 
 		while (i--) {
 			int pstatus = readl (&ehci->regs->port_status [i]);
@@ -632,7 +637,6 @@ static irqreturn_t ehci_irq (struct usb_hcd *hcd)
 			 */
 			ehci->reset_done [i] = jiffies + msecs_to_jiffies (20);
 			ehci_dbg (ehci, "port %d remote wakeup\n", i + 1);
-			usb_hcd_resume_root_hub(hcd);
 		}
 	}
 
diff --git a/drivers/usb/host/ehci-hub.c b/drivers/usb/host/ehci-hub.c
index 1b20722c102b..bfe5f307cba6 100644
--- a/drivers/usb/host/ehci-hub.c
+++ b/drivers/usb/host/ehci-hub.c
@@ -34,6 +34,7 @@ static int ehci_bus_suspend (struct usb_hcd *hcd)
 {
 	struct ehci_hcd		*ehci = hcd_to_ehci (hcd);
 	int			port;
+	int			mask;
 
 	if (time_before (jiffies, ehci->next_statechange))
 		msleep(5);
@@ -51,14 +52,25 @@ static int ehci_bus_suspend (struct usb_hcd *hcd)
 		ehci->reclaim_ready = 1;
 	ehci_work(ehci);
 
-	/* suspend any active/unsuspended ports, maybe allow wakeup */
+	/* Unlike other USB host controller types, EHCI doesn't have
+	 * any notion of "global" or bus-wide suspend.  The driver has
+	 * to manually suspend all the active unsuspended ports, and
+	 * then manually resume them in the bus_resume() routine.
+	 */
+	ehci->bus_suspended = 0;
 	while (port--) {
 		u32 __iomem	*reg = &ehci->regs->port_status [port];
 		u32		t1 = readl (reg) & ~PORT_RWC_BITS;
 		u32		t2 = t1;
 
-		if ((t1 & PORT_PE) && !(t1 & PORT_OWNER))
+		/* keep track of which ports we suspend */
+		if ((t1 & PORT_PE) && !(t1 & PORT_OWNER) &&
+				!(t1 & PORT_SUSPEND)) {
 			t2 |= PORT_SUSPEND;
+			set_bit(port, &ehci->bus_suspended);
+		}
+
+		/* enable remote wakeup on all ports */
 		if (device_may_wakeup(&hcd->self.root_hub->dev))
 			t2 |= PORT_WKOC_E|PORT_WKDISC_E|PORT_WKCONN_E;
 		else
@@ -76,6 +88,13 @@ static int ehci_bus_suspend (struct usb_hcd *hcd)
 	ehci_halt (ehci);
 	hcd->state = HC_STATE_SUSPENDED;
 
+	/* allow remote wakeup */
+	mask = INTR_MASK;
+	if (!device_may_wakeup(&hcd->self.root_hub->dev))
+		mask &= ~STS_PCD;
+	writel(mask, &ehci->regs->intr_enable);
+	readl(&ehci->regs->intr_enable);
+
 	ehci->next_statechange = jiffies + msecs_to_jiffies(10);
 	spin_unlock_irq (&ehci->lock);
 	return 0;
@@ -88,7 +107,6 @@ static int ehci_bus_resume (struct usb_hcd *hcd)
 	struct ehci_hcd		*ehci = hcd_to_ehci (hcd);
 	u32			temp;
 	int			i;
-	int			intr_enable;
 
 	if (time_before (jiffies, ehci->next_statechange))
 		msleep(5);
@@ -100,31 +118,30 @@ static int ehci_bus_resume (struct usb_hcd *hcd)
 	 * the last user of the controller, not reset/pm hardware keeping
 	 * state we gave to it.
 	 */
+	temp = readl(&ehci->regs->intr_enable);
+	ehci_dbg(ehci, "resume root hub%s\n", temp ? "" : " after power loss");
 
-	/* re-init operational registers in case we lost power */
-	if (readl (&ehci->regs->intr_enable) == 0) {
-		/* at least some APM implementations will try to deliver
-		 * IRQs right away, so delay them until we're ready.
-		 */
-		intr_enable = 1;
-		writel (0, &ehci->regs->segment);
-		writel (ehci->periodic_dma, &ehci->regs->frame_list);
-		writel ((u32)ehci->async->qh_dma, &ehci->regs->async_next);
-	} else
-		intr_enable = 0;
-	ehci_dbg(ehci, "resume root hub%s\n",
-			intr_enable ? " after power loss" : "");
+	/* at least some APM implementations will try to deliver
+	 * IRQs right away, so delay them until we're ready.
+	 */
+	writel(0, &ehci->regs->intr_enable);
+
+	/* re-init operational registers */
+	writel(0, &ehci->regs->segment);
+	writel(ehci->periodic_dma, &ehci->regs->frame_list);
+	writel((u32) ehci->async->qh_dma, &ehci->regs->async_next);
 
 	/* restore CMD_RUN, framelist size, and irq threshold */
 	writel (ehci->command, &ehci->regs->command);
 
-	/* take ports out of suspend */
+	/* manually resume the ports we suspended during bus_suspend() */
 	i = HCS_N_PORTS (ehci->hcs_params);
 	while (i--) {
 		temp = readl (&ehci->regs->port_status [i]);
 		temp &= ~(PORT_RWC_BITS
 			| PORT_WKOC_E | PORT_WKDISC_E | PORT_WKCONN_E);
-		if (temp & PORT_SUSPEND) {
+		if (test_bit(i, &ehci->bus_suspended) &&
+				(temp & PORT_SUSPEND)) {
 			ehci->reset_done [i] = jiffies + msecs_to_jiffies (20);
 			temp |= PORT_RESUME;
 		}
@@ -134,11 +151,12 @@ static int ehci_bus_resume (struct usb_hcd *hcd)
 	mdelay (20);
 	while (i--) {
 		temp = readl (&ehci->regs->port_status [i]);
-		if ((temp & PORT_SUSPEND) == 0)
-			continue;
-		temp &= ~(PORT_RWC_BITS | PORT_RESUME);
-		writel (temp, &ehci->regs->port_status [i]);
-		ehci_vdbg (ehci, "resumed port %d\n", i + 1);
+		if (test_bit(i, &ehci->bus_suspended) &&
+				(temp & PORT_SUSPEND)) {
+			temp &= ~(PORT_RWC_BITS | PORT_RESUME);
+			writel (temp, &ehci->regs->port_status [i]);
+			ehci_vdbg (ehci, "resumed port %d\n", i + 1);
+		}
 	}
 	(void) readl (&ehci->regs->command);
 
@@ -157,8 +175,7 @@ static int ehci_bus_resume (struct usb_hcd *hcd)
 	hcd->state = HC_STATE_RUNNING;
 
 	/* Now we can safely re-enable irqs */
-	if (intr_enable)
-		writel (INTR_MASK, &ehci->regs->intr_enable);
+	writel(INTR_MASK, &ehci->regs->intr_enable);
 
 	spin_unlock_irq (&ehci->lock);
 	return 0;
@@ -218,6 +235,7 @@ ehci_hub_status_data (struct usb_hcd *hcd, char *buf)
 {
 	struct ehci_hcd	*ehci = hcd_to_ehci (hcd);
 	u32		temp, status = 0;
+	u32		mask;
 	int		ports, i, retval = 1;
 	unsigned long	flags;
 
@@ -233,6 +251,18 @@ ehci_hub_status_data (struct usb_hcd *hcd, char *buf)
 		retval++;
 	}
 
+	/* Some boards (mostly VIA?) report bogus overcurrent indications,
+	 * causing massive log spam unless we completely ignore them.  It
+	 * may be relevant that VIA VT8235 controlers, where PORT_POWER is
+	 * always set, seem to clear PORT_OCC and PORT_CSC when writing to
+	 * PORT_POWER; that's surprising, but maybe within-spec.
+	 */
+	if (!ignore_oc)
+		mask = PORT_CSC | PORT_PEC | PORT_OCC;
+	else
+		mask = PORT_CSC | PORT_PEC;
+	// PORT_RESUME from hardware ~= PORT_STAT_C_SUSPEND
+
 	/* no hub change reports (bit 0) for now (power, ...) */
 
 	/* port N changes (bit N)? */
@@ -250,8 +280,7 @@ ehci_hub_status_data (struct usb_hcd *hcd, char *buf)
 		}
 		if (!(temp & PORT_CONNECT))
 			ehci->reset_done [i] = 0;
-		if ((temp & (PORT_CSC | PORT_PEC | PORT_OCC)) != 0
-				// PORT_STAT_C_SUSPEND?
+		if ((temp & mask) != 0
 				|| ((temp & PORT_RESUME) != 0
 					&& time_after (jiffies,
 						ehci->reset_done [i]))) {
@@ -319,6 +348,7 @@ static int ehci_hub_control (
 	u32		temp, status;
 	unsigned long	flags;
 	int		retval = 0;
+	unsigned	selector;
 
 	/*
 	 * FIXME:  support SetPortFeatures USB_PORT_FEAT_INDICATOR.
@@ -417,7 +447,7 @@ static int ehci_hub_control (
 			status |= 1 << USB_PORT_FEAT_C_CONNECTION;
 		if (temp & PORT_PEC)
 			status |= 1 << USB_PORT_FEAT_C_ENABLE;
-		if (temp & PORT_OCC)
+		if ((temp & PORT_OCC) && !ignore_oc)
 			status |= 1 << USB_PORT_FEAT_C_OVER_CURRENT;
 
 		/* whoever resumes must GetPortStatus to complete it!! */
@@ -506,6 +536,8 @@ static int ehci_hub_control (
 		}
 		break;
 	case SetPortFeature:
+		selector = wIndex >> 8;
+		wIndex &= 0xff;
 		if (!wIndex || wIndex > ports)
 			goto error;
 		wIndex--;
@@ -559,6 +591,22 @@ static int ehci_hub_control (
 			}
 			writel (temp, &ehci->regs->port_status [wIndex]);
 			break;
+
+		/* For downstream facing ports (these):  one hub port is put
+		 * into test mode according to USB2 11.24.2.13, then the hub
+		 * must be reset (which for root hub now means rmmod+modprobe,
+		 * or else system reboot).  See EHCI 2.3.9 and 4.14 for info
+		 * about the EHCI-specific stuff.
+		 */
+		case USB_PORT_FEAT_TEST:
+			if (!selector || selector > 5)
+				goto error;
+			ehci_quiesce(ehci);
+			ehci_halt(ehci);
+			temp |= selector << 16;
+			writel (temp, &ehci->regs->port_status [wIndex]);
+			break;
+
 		default:
 			goto error;
 		}
diff --git a/drivers/usb/host/ehci-pci.c b/drivers/usb/host/ehci-pci.c
index e51c1ed81ac4..4bc7970ba3ef 100644
--- a/drivers/usb/host/ehci-pci.c
+++ b/drivers/usb/host/ehci-pci.c
@@ -257,9 +257,7 @@ static int ehci_pci_suspend(struct usb_hcd *hcd, pm_message_t message)
 static int ehci_pci_resume(struct usb_hcd *hcd)
 {
 	struct ehci_hcd		*ehci = hcd_to_ehci(hcd);
-	unsigned		port;
 	struct pci_dev		*pdev = to_pci_dev(hcd->self.controller);
-	int			retval = -EINVAL;
 
 	// maybe restore FLADJ
 
@@ -269,27 +267,19 @@ static int ehci_pci_resume(struct usb_hcd *hcd)
 	/* Mark hardware accessible again as we are out of D3 state by now */
 	set_bit(HCD_FLAG_HW_ACCESSIBLE, &hcd->flags);
 
-	/* If CF is clear, we lost PCI Vaux power and need to restart.  */
-	if (readl(&ehci->regs->configured_flag) != FLAG_CF)
-		goto restart;
-
-	/* If any port is suspended (or owned by the companion),
-	 * we know we can/must resume the HC (and mustn't reset it).
-	 * We just defer that to the root hub code.
+	/* If CF is still set, we maintained PCI Vaux power.
+	 * Just undo the effect of ehci_pci_suspend().
 	 */
-	for (port = HCS_N_PORTS(ehci->hcs_params); port > 0; ) {
-		u32	status;
-		port--;
-		status = readl(&ehci->regs->port_status [port]);
-		if (!(status & PORT_POWER))
-			continue;
-		if (status & (PORT_SUSPEND | PORT_RESUME | PORT_OWNER)) {
-			usb_hcd_resume_root_hub(hcd);
-			return 0;
-		}
+	if (readl(&ehci->regs->configured_flag) == FLAG_CF) {
+		int	mask = INTR_MASK;
+
+		if (!device_may_wakeup(&hcd->self.root_hub->dev))
+			mask &= ~STS_PCD;
+		writel(mask, &ehci->regs->intr_enable);
+		readl(&ehci->regs->intr_enable);
+		return 0;
 	}
 
-restart:
 	ehci_dbg(ehci, "lost power, restarting\n");
 	usb_root_hub_lost_power(hcd->self.root_hub);
 
@@ -307,13 +297,15 @@ restart:
 	ehci_work(ehci);
 	spin_unlock_irq(&ehci->lock);
 
-	/* restart; khubd will disconnect devices */
-	retval = ehci_run(hcd);
-
 	/* here we "know" root ports should always stay powered */
 	ehci_port_power(ehci, 1);
 
-	return retval;
+	writel(ehci->command, &ehci->regs->command);
+	writel(FLAG_CF, &ehci->regs->configured_flag);
+	readl(&ehci->regs->command);	/* unblock posted writes */
+
+	hcd->state = HC_STATE_SUSPENDED;
+	return 0;
 }
 #endif
 
diff --git a/drivers/usb/host/ehci.h b/drivers/usb/host/ehci.h
index bbc3082a73d7..74dbc6c8228f 100644
--- a/drivers/usb/host/ehci.h
+++ b/drivers/usb/host/ehci.h
@@ -74,6 +74,7 @@ struct ehci_hcd {			/* one per controller */
 
 	/* per root hub port */
 	unsigned long		reset_done [EHCI_MAX_ROOT_PORTS];
+	unsigned long		bus_suspended;
 
 	/* per-HC memory pools (could be per-bus, but ...) */
 	struct dma_pool		*qh_pool;	/* qh per active urb */
diff --git a/drivers/usb/host/ohci-hcd.c b/drivers/usb/host/ohci-hcd.c
index ea4714e557e4..a95275a401b1 100644
--- a/drivers/usb/host/ohci-hcd.c
+++ b/drivers/usb/host/ohci-hcd.c
@@ -729,6 +729,16 @@ static irqreturn_t ohci_irq (struct usb_hcd *hcd)
 		ohci->next_statechange = jiffies + STATECHANGE_DELAY;
 		ohci_writel(ohci, OHCI_INTR_RD | OHCI_INTR_RHSC,
 				&regs->intrstatus);
+
+		/* NOTE: Vendors didn't always make the same implementation
+		 * choices for RHSC.  Many followed the spec; RHSC triggers
+		 * on an edge, like setting and maybe clearing a port status
+		 * change bit.  With others it's level-triggered, active
+		 * until khubd clears all the port status change bits.  We'll
+		 * always disable it here and rely on polling until khubd
+		 * re-enables it.
+		 */
+		ohci_writel(ohci, OHCI_INTR_RHSC, &regs->intrdisable);
 		usb_hcd_poll_rh_status(hcd);
 	}
 
diff --git a/drivers/usb/host/ohci-hub.c b/drivers/usb/host/ohci-hub.c
index 6995ea36f2e8..2441642cb7b4 100644
--- a/drivers/usb/host/ohci-hub.c
+++ b/drivers/usb/host/ohci-hub.c
@@ -41,7 +41,11 @@ static void ohci_rhsc_enable (struct usb_hcd *hcd)
 {
 	struct ohci_hcd		*ohci = hcd_to_ohci (hcd);
 
-	ohci_writel (ohci, OHCI_INTR_RHSC, &ohci->regs->intrenable);
+	spin_lock_irq(&ohci->lock);
+	if (!ohci->autostop)
+		del_timer(&hcd->rh_timer);	/* Prevent next poll */
+	ohci_writel(ohci, OHCI_INTR_RHSC, &ohci->regs->intrenable);
+	spin_unlock_irq(&ohci->lock);
 }
 
 #define OHCI_SCHED_ENABLES \
@@ -50,6 +54,9 @@ static void ohci_rhsc_enable (struct usb_hcd *hcd)
 static void dl_done_list (struct ohci_hcd *);
 static void finish_unlinks (struct ohci_hcd *, u16);
 
+#ifdef	CONFIG_PM
+static int ohci_restart(struct ohci_hcd *ohci);
+
 static int ohci_rh_suspend (struct ohci_hcd *ohci, int autostop)
 __releases(ohci->lock)
 __acquires(ohci->lock)
@@ -132,8 +139,6 @@ static inline struct ed *find_head (struct ed *ed)
 	return ed;
 }
 
-static int ohci_restart (struct ohci_hcd *ohci);
-
 /* caller has locked the root hub */
 static int ohci_rh_resume (struct ohci_hcd *ohci)
 __releases(ohci->lock)
@@ -169,7 +174,7 @@ __acquires(ohci->lock)
 		break;
 	case OHCI_USB_RESUME:
 		/* HCFS changes sometime after INTR_RD */
-		ohci_info(ohci, "%swakeup\n",
+		ohci_dbg(ohci, "%swakeup root hub\n",
 				autostopped ? "auto-" : "");
 		break;
 	case OHCI_USB_OPER:
@@ -181,7 +186,6 @@ __acquires(ohci->lock)
 		ohci_dbg (ohci, "lost power\n");
 		status = -EBUSY;
 	}
-#ifdef	CONFIG_PM
 	if (status == -EBUSY) {
 		if (!autostopped) {
 			spin_unlock_irq (&ohci->lock);
@@ -191,25 +195,12 @@ __acquires(ohci->lock)
 		}
 		return status;
 	}
-#endif
 	if (status != -EINPROGRESS)
 		return status;
 	if (autostopped)
 		goto skip_resume;
 	spin_unlock_irq (&ohci->lock);
 
-	temp = ohci->num_ports;
-	while (temp--) {
-		u32 stat = ohci_readl (ohci,
-				       &ohci->regs->roothub.portstatus [temp]);
-
-		/* force global, not selective, resume */
-		if (!(stat & RH_PS_PSS))
-			continue;
-		ohci_writel (ohci, RH_PS_POCI,
-				&ohci->regs->roothub.portstatus [temp]);
-	}
-
 	/* Some controllers (lucent erratum) need extra-long delays */
 	msleep (20 /* usb 11.5.1.10 */ + 12 /* 32 msec counter */ + 1);
 
@@ -217,6 +208,7 @@ __acquires(ohci->lock)
 	temp &= OHCI_CTRL_HCFS;
 	if (temp != OHCI_USB_RESUME) {
 		ohci_err (ohci, "controller won't resume\n");
+		spin_lock_irq(&ohci->lock);
 		return -EBUSY;
 	}
 
@@ -296,8 +288,6 @@ skip_resume:
 	return 0;
 }
 
-#ifdef	CONFIG_PM
-
 static int ohci_bus_suspend (struct usb_hcd *hcd)
 {
 	struct ohci_hcd		*ohci = hcd_to_ohci (hcd);
@@ -335,6 +325,83 @@ static int ohci_bus_resume (struct usb_hcd *hcd)
 	return rc;
 }
 
+/* Carry out polling-, autostop-, and autoresume-related state changes */
+static int ohci_root_hub_state_changes(struct ohci_hcd *ohci, int changed,
+		int any_connected)
+{
+	int	poll_rh = 1;
+
+	switch (ohci->hc_control & OHCI_CTRL_HCFS) {
+
+	case OHCI_USB_OPER:
+		/* keep on polling until we know a device is connected
+		 * and RHSC is enabled */
+		if (!ohci->autostop) {
+			if (any_connected ||
+					!device_may_wakeup(&ohci_to_hcd(ohci)
+						->self.root_hub->dev)) {
+				if (ohci_readl(ohci, &ohci->regs->intrenable) &
+						OHCI_INTR_RHSC)
+					poll_rh = 0;
+			} else {
+				ohci->autostop = 1;
+				ohci->next_statechange = jiffies + HZ;
+			}
+
+		/* if no devices have been attached for one second, autostop */
+		} else {
+			if (changed || any_connected) {
+				ohci->autostop = 0;
+				ohci->next_statechange = jiffies +
+						STATECHANGE_DELAY;
+			} else if (time_after_eq(jiffies,
+						ohci->next_statechange)
+					&& !ohci->ed_rm_list
+					&& !(ohci->hc_control &
+						OHCI_SCHED_ENABLES)) {
+				ohci_rh_suspend(ohci, 1);
+			}
+		}
+		break;
+
+	/* if there is a port change, autostart or ask to be resumed */
+	case OHCI_USB_SUSPEND:
+	case OHCI_USB_RESUME:
+		if (changed) {
+			if (ohci->autostop)
+				ohci_rh_resume(ohci);
+			else
+				usb_hcd_resume_root_hub(ohci_to_hcd(ohci));
+		} else {
+			/* everything is idle, no need for polling */
+			poll_rh = 0;
+		}
+		break;
+	}
+	return poll_rh;
+}
+
+#else	/* CONFIG_PM */
+
+static inline int ohci_rh_resume(struct ohci_hcd *ohci)
+{
+	return 0;
+}
+
+/* Carry out polling-related state changes.
+ * autostop isn't used when CONFIG_PM is turned off.
+ */
+static int ohci_root_hub_state_changes(struct ohci_hcd *ohci, int changed,
+		int any_connected)
+{
+	int	poll_rh = 1;
+
+	/* keep on polling until RHSC is enabled */
+	if (ohci_readl(ohci, &ohci->regs->intrenable) & OHCI_INTR_RHSC)
+		poll_rh = 0;
+	return poll_rh;
+}
+
 #endif	/* CONFIG_PM */
 
 /*-------------------------------------------------------------------------*/
@@ -346,7 +413,7 @@ ohci_hub_status_data (struct usb_hcd *hcd, char *buf)
 {
 	struct ohci_hcd	*ohci = hcd_to_ohci (hcd);
 	int		i, changed = 0, length = 1;
-	int		any_connected = 0, rhsc_enabled = 1;
+	int		any_connected = 0;
 	unsigned long	flags;
 
 	spin_lock_irqsave (&ohci->lock, flags);
@@ -387,67 +454,8 @@ ohci_hub_status_data (struct usb_hcd *hcd, char *buf)
 		}
 	}
 
-	/* NOTE:  vendors didn't always make the same implementation
-	 * choices for RHSC.  Sometimes it triggers on an edge (like
-	 * setting and maybe clearing a port status change bit); and
-	 * it's level-triggered on other silicon, active until khubd
-	 * clears all active port status change bits.  If it's still
-	 * set (level-triggered) we must disable it and rely on
-	 * polling until khubd re-enables it.
-	 */
-	if (ohci_readl (ohci, &ohci->regs->intrstatus) & OHCI_INTR_RHSC) {
-		ohci_writel (ohci, OHCI_INTR_RHSC, &ohci->regs->intrdisable);
-		(void) ohci_readl (ohci, &ohci->regs->intrdisable);
-		rhsc_enabled = 0;
-	}
-	hcd->poll_rh = 1;
-
-	/* carry out appropriate state changes */
-	switch (ohci->hc_control & OHCI_CTRL_HCFS) {
-
-	case OHCI_USB_OPER:
-		/* keep on polling until we know a device is connected
-		 * and RHSC is enabled */
-		if (!ohci->autostop) {
-			if (any_connected) {
-				if (rhsc_enabled)
-					hcd->poll_rh = 0;
-			} else {
-				ohci->autostop = 1;
-				ohci->next_statechange = jiffies + HZ;
-			}
-
-		/* if no devices have been attached for one second, autostop */
-		} else {
-			if (changed || any_connected) {
-				ohci->autostop = 0;
-				ohci->next_statechange = jiffies +
-						STATECHANGE_DELAY;
-			} else if (device_may_wakeup(&hcd->self.root_hub->dev)
-					&& time_after_eq(jiffies,
-						ohci->next_statechange)
-					&& !ohci->ed_rm_list
-					&& !(ohci->hc_control &
-						OHCI_SCHED_ENABLES)) {
-				ohci_rh_suspend (ohci, 1);
-			}
-		}
-		break;
-
-	/* if there is a port change, autostart or ask to be resumed */
-	case OHCI_USB_SUSPEND:
-	case OHCI_USB_RESUME:
-		if (changed) {
-			if (ohci->autostop)
-				ohci_rh_resume (ohci);
-			else
-				usb_hcd_resume_root_hub (hcd);
-		} else {
-			/* everything is idle, no need for polling */
-			hcd->poll_rh = 0;
-		}
-		break;
-	}
+	hcd->poll_rh = ohci_root_hub_state_changes(ohci, changed,
+			any_connected);
 
 done:
 	spin_unlock_irqrestore (&ohci->lock, flags);
diff --git a/drivers/usb/host/u132-hcd.c b/drivers/usb/host/u132-hcd.c
index 4f95a249c913..a9d7119e3176 100644
--- a/drivers/usb/host/u132-hcd.c
+++ b/drivers/usb/host/u132-hcd.c
@@ -71,7 +71,7 @@ static int distrust_firmware = 1;
 module_param(distrust_firmware, bool, 0);
 MODULE_PARM_DESC(distrust_firmware, "true to distrust firmware power/overcurren"
         "t setup");
-DECLARE_WAIT_QUEUE_HEAD(u132_hcd_wait);
+static DECLARE_WAIT_QUEUE_HEAD(u132_hcd_wait);
 /*
 * u132_module_lock exists to protect access to global variables
 *
@@ -205,13 +205,9 @@ struct u132 {
         struct u132_port port[MAX_U132_PORTS];
         struct u132_endp *endp[MAX_U132_ENDPS];
 };
-int usb_ftdi_elan_read_reg(struct platform_device *pdev, u32 *data);
-int usb_ftdi_elan_read_pcimem(struct platform_device *pdev, u8 addressofs,
-        u8 width, u32 *data);
-int usb_ftdi_elan_write_pcimem(struct platform_device *pdev, u8 addressofs,
-        u8 width, u32 data);
+
 /*
-* these can not be inlines because we need the structure offset!!
+* these cannot be inlines because we need the structure offset!!
 * Does anyone have a better way?????
 */
 #define u132_read_pcimem(u132, member, data) \
@@ -3031,7 +3027,7 @@ static struct hc_driver u132_hc_driver = {
 * This function may be called by the USB core whilst the "usb_all_devices_rwsem"
 * is held for writing, thus this module must not call usb_remove_hcd()
 * synchronously - but instead should immediately stop activity to the
-* device and ansynchronously call usb_remove_hcd()
+* device and asynchronously call usb_remove_hcd()
 */
 static int __devexit u132_remove(struct platform_device *pdev)
 {
@@ -3227,7 +3223,7 @@ static int u132_resume(struct platform_device *pdev)
 #define u132_resume NULL
 #endif
 /*
-* this driver is loaded explicitely by ftdi_u132
+* this driver is loaded explicitly by ftdi_u132
 *
 * the platform_driver struct is static because it is per type of module
 */
diff --git a/drivers/usb/image/microtek.c b/drivers/usb/image/microtek.c
index 3038ed0700d3..8ccddf74534a 100644
--- a/drivers/usb/image/microtek.c
+++ b/drivers/usb/image/microtek.c
@@ -796,7 +796,7 @@ static int mts_usb_probe(struct usb_interface *intf,
 
 	new_desc->context.scsi_status = kmalloc(1, GFP_KERNEL);
 	if (!new_desc->context.scsi_status)
-		goto out_kfree2;
+		goto out_free_urb;
 
 	new_desc->usb_dev = dev;
 	new_desc->usb_intf = intf;
@@ -822,18 +822,20 @@ static int mts_usb_probe(struct usb_interface *intf,
 	new_desc->host = scsi_host_alloc(&mts_scsi_host_template,
 			sizeof(new_desc));
 	if (!new_desc->host)
-		goto out_free_urb;
+		goto out_kfree2;
 
 	new_desc->host->hostdata[0] = (unsigned long)new_desc;
 	if (scsi_add_host(new_desc->host, NULL)) {
 		err_retval = -EIO;
-		goto out_free_urb;
+		goto out_host_put;
 	}
 	scsi_scan_host(new_desc->host);
 
 	usb_set_intfdata(intf, new_desc);
 	return 0;
 
+ out_host_put:
+	scsi_host_put(new_desc->host);
  out_kfree2:
 	kfree(new_desc->context.scsi_status);
  out_free_urb:
diff --git a/drivers/usb/input/Kconfig b/drivers/usb/input/Kconfig
index 20db36448ab3..661af7aa6236 100644
--- a/drivers/usb/input/Kconfig
+++ b/drivers/usb/input/Kconfig
@@ -221,6 +221,7 @@ config USB_TOUCHSCREEN
 	  - ITM
 	  - some other eTurboTouch
 	  - Gunze AHL61
+	  - DMC TSC-10/25
 
 	  Have a look at <http://linux.chapter7.ch/touchkit/> for
 	  a usage description and the required user-space stuff.
@@ -258,6 +259,11 @@ config USB_TOUCHSCREEN_GUNZE
 	bool "Gunze AHL61 device support" if EMBEDDED
 	depends on USB_TOUCHSCREEN
 
+config USB_TOUCHSCREEN_DMC_TSC10
+	default y
+	bool "DMC TSC-10/25 device support" if EMBEDDED
+	depends on USB_TOUCHSCREEN
+
 config USB_YEALINK
 	tristate "Yealink usb-p1k voip phone"
 	depends on USB && INPUT && EXPERIMENTAL
diff --git a/drivers/usb/input/ati_remote.c b/drivers/usb/input/ati_remote.c
index f659f3028ad2..ff23318dc301 100644
--- a/drivers/usb/input/ati_remote.c
+++ b/drivers/usb/input/ati_remote.c
@@ -630,19 +630,14 @@ static int ati_remote_alloc_buffers(struct usb_device *udev,
  */
 static void ati_remote_free_buffers(struct ati_remote *ati_remote)
 {
-	if (ati_remote->irq_urb)
-		usb_free_urb(ati_remote->irq_urb);
+	usb_free_urb(ati_remote->irq_urb);
+	usb_free_urb(ati_remote->out_urb);
 
-	if (ati_remote->out_urb)
-		usb_free_urb(ati_remote->out_urb);
+	usb_buffer_free(ati_remote->udev, DATA_BUFSIZE,
+		ati_remote->inbuf, ati_remote->inbuf_dma);
 
-	if (ati_remote->inbuf)
-		usb_buffer_free(ati_remote->udev, DATA_BUFSIZE,
-				ati_remote->inbuf, ati_remote->inbuf_dma);
-
-	if (ati_remote->outbuf)
-		usb_buffer_free(ati_remote->udev, DATA_BUFSIZE,
-				ati_remote->inbuf, ati_remote->outbuf_dma);
+	usb_buffer_free(ati_remote->udev, DATA_BUFSIZE,
+		ati_remote->outbuf, ati_remote->outbuf_dma);
 }
 
 static void ati_remote_input_init(struct ati_remote *ati_remote)
diff --git a/drivers/usb/input/ati_remote2.c b/drivers/usb/input/ati_remote2.c
index f982a2b4a7f9..83f1f79db7c7 100644
--- a/drivers/usb/input/ati_remote2.c
+++ b/drivers/usb/input/ati_remote2.c
@@ -372,8 +372,7 @@ static void ati_remote2_urb_cleanup(struct ati_remote2 *ar2)
 	int i;
 
 	for (i = 0; i < 2; i++) {
-		if (ar2->urb[i])
-			usb_free_urb(ar2->urb[i]);
+		usb_free_urb(ar2->urb[i]);
 
 		if (ar2->buf[i])
 			usb_buffer_free(ar2->udev, 4, ar2->buf[i], ar2->buf_dma[i]);
diff --git a/drivers/usb/input/hid-core.c b/drivers/usb/input/hid-core.c
index ebc9e823a46e..4295bab4f1e2 100644
--- a/drivers/usb/input/hid-core.c
+++ b/drivers/usb/input/hid-core.c
@@ -968,21 +968,30 @@ static void hid_retry_timeout(unsigned long _hid)
 		hid_io_error(hid);
 }
 
-/* Workqueue routine to reset the device */
+/* Workqueue routine to reset the device or clear a halt */
 static void hid_reset(struct work_struct *work)
 {
 	struct hid_device *hid =
 		container_of(work, struct hid_device, reset_work);
-	int rc_lock, rc;
-
-	dev_dbg(&hid->intf->dev, "resetting device\n");
-	rc = rc_lock = usb_lock_device_for_reset(hid->dev, hid->intf);
-	if (rc_lock >= 0) {
-		rc = usb_reset_composite_device(hid->dev, hid->intf);
-		if (rc_lock)
-			usb_unlock_device(hid->dev);
+	int rc_lock, rc = 0;
+
+	if (test_bit(HID_CLEAR_HALT, &hid->iofl)) {
+		dev_dbg(&hid->intf->dev, "clear halt\n");
+		rc = usb_clear_halt(hid->dev, hid->urbin->pipe);
+		clear_bit(HID_CLEAR_HALT, &hid->iofl);
+		hid_start_in(hid);
+	}
+
+	else if (test_bit(HID_RESET_PENDING, &hid->iofl)) {
+		dev_dbg(&hid->intf->dev, "resetting device\n");
+		rc = rc_lock = usb_lock_device_for_reset(hid->dev, hid->intf);
+		if (rc_lock >= 0) {
+			rc = usb_reset_composite_device(hid->dev, hid->intf);
+			if (rc_lock)
+				usb_unlock_device(hid->dev);
+		}
+		clear_bit(HID_RESET_PENDING, &hid->iofl);
 	}
-	clear_bit(HID_RESET_PENDING, &hid->iofl);
 
 	switch (rc) {
 	case 0:
@@ -1024,9 +1033,8 @@ static void hid_io_error(struct hid_device *hid)
 
 		/* Retries failed, so do a port reset */
 		if (!test_and_set_bit(HID_RESET_PENDING, &hid->iofl)) {
-			if (schedule_work(&hid->reset_work))
-				goto done;
-			clear_bit(HID_RESET_PENDING, &hid->iofl);
+			schedule_work(&hid->reset_work);
+			goto done;
 		}
 	}
 
@@ -1050,6 +1058,11 @@ static void hid_irq_in(struct urb *urb)
 			hid->retry_delay = 0;
 			hid_input_report(HID_INPUT_REPORT, urb, 1);
 			break;
+		case -EPIPE:		/* stall */
+			clear_bit(HID_IN_RUNNING, &hid->iofl);
+			set_bit(HID_CLEAR_HALT, &hid->iofl);
+			schedule_work(&hid->reset_work);
+			return;
 		case -ECONNRESET:	/* unlink */
 		case -ENOENT:
 		case -ESHUTDOWN:	/* unplug */
@@ -1628,6 +1641,19 @@ void hid_init_reports(struct hid_device *hid)
 
 #define USB_VENDOR_ID_APPLE		0x05ac
 #define USB_DEVICE_ID_APPLE_MIGHTYMOUSE	0x0304
+#define USB_DEVICE_ID_APPLE_FOUNTAIN_ANSI	0x020e
+#define USB_DEVICE_ID_APPLE_FOUNTAIN_ISO	0x020f
+#define USB_DEVICE_ID_APPLE_GEYSER_ANSI	0x0214
+#define USB_DEVICE_ID_APPLE_GEYSER_ISO	0x0215
+#define USB_DEVICE_ID_APPLE_GEYSER_JIS	0x0216
+#define USB_DEVICE_ID_APPLE_GEYSER3_ANSI	0x0217
+#define USB_DEVICE_ID_APPLE_GEYSER3_ISO	0x0218
+#define USB_DEVICE_ID_APPLE_GEYSER3_JIS	0x0219
+#define USB_DEVICE_ID_APPLE_GEYSER4_ANSI	0x021a
+#define USB_DEVICE_ID_APPLE_GEYSER4_ISO	0x021b
+#define USB_DEVICE_ID_APPLE_GEYSER4_JIS	0x021c
+#define USB_DEVICE_ID_APPLE_FOUNTAIN_TP_ONLY	0x030a
+#define USB_DEVICE_ID_APPLE_GEYSER1_TP_ONLY	0x030b
 
 #define USB_VENDOR_ID_CHERRY		0x046a
 #define USB_DEVICE_ID_CHERRY_CYMOTION	0x0023
@@ -1795,17 +1821,19 @@ static const struct hid_blacklist {
 
 	{ USB_VENDOR_ID_CHERRY, USB_DEVICE_ID_CHERRY_CYMOTION, HID_QUIRK_CYMOTION },
 
-	{ USB_VENDOR_ID_APPLE, 0x020E, HID_QUIRK_POWERBOOK_HAS_FN },
-	{ USB_VENDOR_ID_APPLE, 0x020F, HID_QUIRK_POWERBOOK_HAS_FN },
-	{ USB_VENDOR_ID_APPLE, 0x0214, HID_QUIRK_POWERBOOK_HAS_FN },
-	{ USB_VENDOR_ID_APPLE, 0x0215, HID_QUIRK_POWERBOOK_HAS_FN | HID_QUIRK_POWERBOOK_ISO_KEYBOARD},
-	{ USB_VENDOR_ID_APPLE, 0x0216, HID_QUIRK_POWERBOOK_HAS_FN },
-	{ USB_VENDOR_ID_APPLE, 0x0217, HID_QUIRK_POWERBOOK_HAS_FN },
-	{ USB_VENDOR_ID_APPLE, 0x0218, HID_QUIRK_POWERBOOK_HAS_FN | HID_QUIRK_POWERBOOK_ISO_KEYBOARD},
-	{ USB_VENDOR_ID_APPLE, 0x0219, HID_QUIRK_POWERBOOK_HAS_FN },
-	{ USB_VENDOR_ID_APPLE, 0x021B, HID_QUIRK_POWERBOOK_HAS_FN },
-	{ USB_VENDOR_ID_APPLE, 0x030A, HID_QUIRK_POWERBOOK_HAS_FN },
-	{ USB_VENDOR_ID_APPLE, 0x030B, HID_QUIRK_POWERBOOK_HAS_FN },
+	{ USB_VENDOR_ID_APPLE, USB_DEVICE_ID_APPLE_FOUNTAIN_ANSI, HID_QUIRK_POWERBOOK_HAS_FN },
+	{ USB_VENDOR_ID_APPLE, USB_DEVICE_ID_APPLE_FOUNTAIN_ISO, HID_QUIRK_POWERBOOK_HAS_FN },
+	{ USB_VENDOR_ID_APPLE, USB_DEVICE_ID_APPLE_GEYSER_ANSI, HID_QUIRK_POWERBOOK_HAS_FN },
+	{ USB_VENDOR_ID_APPLE, USB_DEVICE_ID_APPLE_GEYSER_ISO, HID_QUIRK_POWERBOOK_HAS_FN | HID_QUIRK_POWERBOOK_ISO_KEYBOARD},
+	{ USB_VENDOR_ID_APPLE, USB_DEVICE_ID_APPLE_GEYSER_JIS, HID_QUIRK_POWERBOOK_HAS_FN },
+	{ USB_VENDOR_ID_APPLE, USB_DEVICE_ID_APPLE_GEYSER3_ANSI, HID_QUIRK_POWERBOOK_HAS_FN },
+	{ USB_VENDOR_ID_APPLE, USB_DEVICE_ID_APPLE_GEYSER3_ISO, HID_QUIRK_POWERBOOK_HAS_FN | HID_QUIRK_POWERBOOK_ISO_KEYBOARD},
+	{ USB_VENDOR_ID_APPLE, USB_DEVICE_ID_APPLE_GEYSER3_JIS, HID_QUIRK_POWERBOOK_HAS_FN },
+	{ USB_VENDOR_ID_APPLE, USB_DEVICE_ID_APPLE_GEYSER4_ANSI, HID_QUIRK_POWERBOOK_HAS_FN },
+	{ USB_VENDOR_ID_APPLE, USB_DEVICE_ID_APPLE_GEYSER4_ISO, HID_QUIRK_POWERBOOK_HAS_FN },
+	{ USB_VENDOR_ID_APPLE, USB_DEVICE_ID_APPLE_GEYSER4_JIS, HID_QUIRK_POWERBOOK_HAS_FN },
+	{ USB_VENDOR_ID_APPLE, USB_DEVICE_ID_APPLE_FOUNTAIN_TP_ONLY, HID_QUIRK_POWERBOOK_HAS_FN },
+	{ USB_VENDOR_ID_APPLE, USB_DEVICE_ID_APPLE_GEYSER1_TP_ONLY, HID_QUIRK_POWERBOOK_HAS_FN },
 
 	{ USB_VENDOR_ID_PANJIT, 0x0001, HID_QUIRK_IGNORE },
 	{ USB_VENDOR_ID_PANJIT, 0x0002, HID_QUIRK_IGNORE },
@@ -1986,7 +2014,7 @@ static struct hid_device *usb_hid_configure(struct usb_interface *intf)
 		if (hid->collection->usage == HID_GD_MOUSE && hid_mousepoll_interval > 0)
 			interval = hid_mousepoll_interval;
 
-		if (endpoint->bEndpointAddress & USB_DIR_IN) {
+		if (usb_endpoint_dir_in(endpoint)) {
 			if (hid->urbin)
 				continue;
 			if (!(hid->urbin = usb_alloc_urb(0, GFP_KERNEL)))
@@ -2068,13 +2096,9 @@ static struct hid_device *usb_hid_configure(struct usb_interface *intf)
 	return hid;
 
 fail:
-
-	if (hid->urbin)
-		usb_free_urb(hid->urbin);
-	if (hid->urbout)
-		usb_free_urb(hid->urbout);
-	if (hid->urbctrl)
-		usb_free_urb(hid->urbctrl);
+	usb_free_urb(hid->urbin);
+	usb_free_urb(hid->urbout);
+	usb_free_urb(hid->urbctrl);
 	hid_free_buffers(dev, hid);
 	hid_free_device(hid);
 
@@ -2105,8 +2129,7 @@ static void hid_disconnect(struct usb_interface *intf)
 
 	usb_free_urb(hid->urbin);
 	usb_free_urb(hid->urbctrl);
-	if (hid->urbout)
-		usb_free_urb(hid->urbout);
+	usb_free_urb(hid->urbout);
 
 	hid_free_buffers(hid->dev, hid);
 	hid_free_device(hid);
diff --git a/drivers/usb/input/hid.h b/drivers/usb/input/hid.h
index 0e76e6dcac37..2a9bf07944c0 100644
--- a/drivers/usb/input/hid.h
+++ b/drivers/usb/input/hid.h
@@ -385,6 +385,7 @@ struct hid_control_fifo {
 #define HID_IN_RUNNING		3
 #define HID_RESET_PENDING	4
 #define HID_SUSPENDED		5
+#define HID_CLEAR_HALT		6
 
 struct hid_input {
 	struct list_head list;
diff --git a/drivers/usb/input/usbkbd.c b/drivers/usb/input/usbkbd.c
index c73285cf8558..dac88640eab6 100644
--- a/drivers/usb/input/usbkbd.c
+++ b/drivers/usb/input/usbkbd.c
@@ -208,10 +208,8 @@ static int usb_kbd_alloc_mem(struct usb_device *dev, struct usb_kbd *kbd)
 
 static void usb_kbd_free_mem(struct usb_device *dev, struct usb_kbd *kbd)
 {
-	if (kbd->irq)
-		usb_free_urb(kbd->irq);
-	if (kbd->led)
-		usb_free_urb(kbd->led);
+	usb_free_urb(kbd->irq);
+	usb_free_urb(kbd->led);
 	if (kbd->new)
 		usb_buffer_free(dev, 8, kbd->new, kbd->new_dma);
 	if (kbd->cr)
@@ -236,9 +234,7 @@ static int usb_kbd_probe(struct usb_interface *iface,
 		return -ENODEV;
 
 	endpoint = &interface->endpoint[0].desc;
-	if (!(endpoint->bEndpointAddress & USB_DIR_IN))
-		return -ENODEV;
-	if ((endpoint->bmAttributes & USB_ENDPOINT_XFERTYPE_MASK) != USB_ENDPOINT_XFER_INT)
+	if (!usb_endpoint_is_int_in(endpoint))
 		return -ENODEV;
 
 	pipe = usb_rcvintpipe(dev, endpoint->bEndpointAddress);
diff --git a/drivers/usb/input/usbmouse.c b/drivers/usb/input/usbmouse.c
index cbbbea332ed7..68a55642c082 100644
--- a/drivers/usb/input/usbmouse.c
+++ b/drivers/usb/input/usbmouse.c
@@ -126,9 +126,7 @@ static int usb_mouse_probe(struct usb_interface *intf, const struct usb_device_i
 		return -ENODEV;
 
 	endpoint = &interface->endpoint[0].desc;
-	if (!(endpoint->bEndpointAddress & USB_DIR_IN))
-		return -ENODEV;
-	if ((endpoint->bmAttributes & USB_ENDPOINT_XFERTYPE_MASK) != USB_ENDPOINT_XFER_INT)
+	if (!usb_endpoint_is_int_in(endpoint))
 		return -ENODEV;
 
 	pipe = usb_rcvintpipe(dev, endpoint->bEndpointAddress);
diff --git a/drivers/usb/input/usbtouchscreen.c b/drivers/usb/input/usbtouchscreen.c
index 933ceddf3dee..49704d4ed0e2 100644
--- a/drivers/usb/input/usbtouchscreen.c
+++ b/drivers/usb/input/usbtouchscreen.c
@@ -8,6 +8,7 @@
  *  - PanJit TouchSet
  *  - eTurboTouch
  *  - Gunze AHL61
+ *  - DMC TSC-10/25
  *
  * Copyright (C) 2004-2006 by Daniel Ritz <daniel.ritz@gmx.ch>
  * Copyright (C) by Todd E. Johnson (mtouchusb.c)
@@ -30,6 +31,8 @@
  * - ITM parts are from itmtouch.c
  * - 3M parts are from mtouchusb.c
  * - PanJit parts are from an unmerged driver by Lanslott Gish
+ * - DMC TSC 10/25 are from Holger Schurig, with ideas from an unmerged
+ *   driver from Marius Vollmer
  *
  *****************************************************************************/
 
@@ -44,7 +47,7 @@
 #include <linux/usb/input.h>
 
 
-#define DRIVER_VERSION		"v0.4"
+#define DRIVER_VERSION		"v0.5"
 #define DRIVER_AUTHOR		"Daniel Ritz <daniel.ritz@gmx.ch>"
 #define DRIVER_DESC		"USB Touchscreen Driver"
 
@@ -103,6 +106,7 @@ enum {
 	DEVTYPE_ITM,
 	DEVTYPE_ETURBO,
 	DEVTYPE_GUNZE,
+	DEVTYPE_DMC_TSC10,
 };
 
 static struct usb_device_id usbtouch_devices[] = {
@@ -139,6 +143,10 @@ static struct usb_device_id usbtouch_devices[] = {
 	{USB_DEVICE(0x0637, 0x0001), .driver_info = DEVTYPE_GUNZE},
 #endif
 
+#ifdef CONFIG_USB_TOUCHSCREEN_DMC_TSC10
+	{USB_DEVICE(0x0afa, 0x03e8), .driver_info = DEVTYPE_DMC_TSC10},
+#endif
+
 	{}
 };
 
@@ -313,6 +321,80 @@ static int gunze_read_data(unsigned char *pkt, int *x, int *y, int *touch, int *
 #endif
 
 /*****************************************************************************
+ * DMC TSC-10/25 Part
+ *
+ * Documentation about the controller and it's protocol can be found at
+ *   http://www.dmccoltd.com/files/controler/tsc10usb_pi_e.pdf
+ *   http://www.dmccoltd.com/files/controler/tsc25_usb_e.pdf
+ */
+#ifdef CONFIG_USB_TOUCHSCREEN_DMC_TSC10
+
+/* supported data rates. currently using 130 */
+#define TSC10_RATE_POINT	0x50
+#define TSC10_RATE_30		0x40
+#define TSC10_RATE_50		0x41
+#define TSC10_RATE_80		0x42
+#define TSC10_RATE_100		0x43
+#define TSC10_RATE_130		0x44
+#define TSC10_RATE_150		0x45
+
+/* commands */
+#define TSC10_CMD_RESET		0x55
+#define TSC10_CMD_RATE		0x05
+#define TSC10_CMD_DATA1		0x01
+
+static int dmc_tsc10_init(struct usbtouch_usb *usbtouch)
+{
+	struct usb_device *dev = usbtouch->udev;
+	int ret;
+	unsigned char buf[2];
+
+	/* reset */
+	buf[0] = buf[1] = 0xFF;
+	ret = usb_control_msg(dev, usb_rcvctrlpipe (dev, 0),
+	                      TSC10_CMD_RESET,
+	                      USB_DIR_IN | USB_TYPE_VENDOR | USB_RECIP_DEVICE,
+	                      0, 0, buf, 2, USB_CTRL_SET_TIMEOUT);
+	if (ret < 0)
+		return ret;
+	if (buf[0] != 0x06 || buf[1] != 0x00)
+		return -ENODEV;
+
+	/* set coordinate output rate */
+	buf[0] = buf[1] = 0xFF;
+	ret = usb_control_msg(dev, usb_rcvctrlpipe (dev, 0),
+	                      TSC10_CMD_RATE,
+	                      USB_DIR_IN | USB_TYPE_VENDOR | USB_RECIP_DEVICE,
+	                      TSC10_RATE_150, 0, buf, 2, USB_CTRL_SET_TIMEOUT);
+	if (ret < 0)
+		return ret;
+	if (buf[0] != 0x06 || buf[1] != 0x00)
+		return -ENODEV;
+
+	/* start sending data */
+	ret = usb_control_msg(dev, usb_rcvctrlpipe (dev, 0),
+	                      TSC10_CMD_DATA1,
+	                      USB_DIR_OUT | USB_TYPE_VENDOR | USB_RECIP_DEVICE,
+	                      0, 0, NULL, 0, USB_CTRL_SET_TIMEOUT);
+	if (ret < 0)
+		return ret;
+
+	return 0;
+}
+
+
+static int dmc_tsc10_read_data(unsigned char *pkt, int *x, int *y, int *touch, int *press)
+{
+	*x = ((pkt[2] & 0x03) << 8) | pkt[1];
+	*y = ((pkt[4] & 0x03) << 8) | pkt[3];
+	*touch = pkt[0] & 0x01;
+
+	return 1;
+}
+#endif
+
+
+/*****************************************************************************
  * the different device descriptors
  */
 static struct usbtouch_device_info usbtouch_dev_info[] = {
@@ -389,6 +471,18 @@ static struct usbtouch_device_info usbtouch_dev_info[] = {
 		.read_data	= gunze_read_data,
 	},
 #endif
+
+#ifdef CONFIG_USB_TOUCHSCREEN_DMC_TSC10
+	[DEVTYPE_DMC_TSC10] = {
+		.min_xc		= 0x0,
+		.max_xc		= 0x03ff,
+		.min_yc		= 0x0,
+		.max_yc		= 0x03ff,
+		.rept_size	= 5,
+		.init		= dmc_tsc10_init,
+		.read_data	= dmc_tsc10_read_data,
+	},
+#endif
 };
 
 
diff --git a/drivers/usb/input/wacom.h b/drivers/usb/input/wacom.h
index 1cf08f02c50e..d85abfc5ab58 100644
--- a/drivers/usb/input/wacom.h
+++ b/drivers/usb/input/wacom.h
@@ -110,7 +110,6 @@ struct wacom_combo {
 };
 
 extern int wacom_wac_irq(struct wacom_wac * wacom_wac, void * wcombo);
-extern void wacom_sys_irq(struct urb *urb);
 extern void wacom_report_abs(void *wcombo, unsigned int abs_type, int abs_data);
 extern void wacom_report_rel(void *wcombo, unsigned int rel_type, int rel_data);
 extern void wacom_report_key(void *wcombo, unsigned int key_type, int key_data);
diff --git a/drivers/usb/input/wacom_sys.c b/drivers/usb/input/wacom_sys.c
index 3498b893b53b..e7cc20ab8155 100644
--- a/drivers/usb/input/wacom_sys.c
+++ b/drivers/usb/input/wacom_sys.c
@@ -42,7 +42,7 @@ static struct input_dev * get_input_dev(struct wacom_combo *wcombo)
 	return wcombo->wacom->dev;
 }
 
-void wacom_sys_irq(struct urb *urb)
+static void wacom_sys_irq(struct urb *urb)
 {
 	struct wacom *wacom = urb->context;
 	struct wacom_combo wcombo;
diff --git a/drivers/usb/input/yealink.c b/drivers/usb/input/yealink.c
index 905bf6398257..2268ca311ade 100644
--- a/drivers/usb/input/yealink.c
+++ b/drivers/usb/input/yealink.c
@@ -859,10 +859,8 @@ static int usb_probe(struct usb_interface *intf, const struct usb_device_id *id)
 
 	interface = intf->cur_altsetting;
 	endpoint = &interface->endpoint[0].desc;
-	if (!(endpoint->bEndpointAddress & USB_DIR_IN))
-		return -EIO;
-	if ((endpoint->bmAttributes & USB_ENDPOINT_XFERTYPE_MASK) != USB_ENDPOINT_XFER_INT)
-		return -EIO;
+	if (!usb_endpoint_is_int_in(endpoint))
+		return -ENODEV;
 
 	yld = kzalloc(sizeof(struct yealink_dev), GFP_KERNEL);
 	if (!yld)
diff --git a/drivers/usb/misc/Makefile b/drivers/usb/misc/Makefile
index 11dc59540cda..2cba07d31971 100644
--- a/drivers/usb/misc/Makefile
+++ b/drivers/usb/misc/Makefile
@@ -4,6 +4,7 @@
 #
 
 obj-$(CONFIG_USB_ADUTUX)	+= adutux.o
+obj-$(CONFIG_USB_APPLEDISPLAY)	+= appledisplay.o
 obj-$(CONFIG_USB_AUERSWALD)	+= auerswald.o
 obj-$(CONFIG_USB_CYPRESS_CY7C63)+= cypress_cy7c63.o
 obj-$(CONFIG_USB_CYTHERM)	+= cytherm.o
diff --git a/drivers/usb/misc/appledisplay.c b/drivers/usb/misc/appledisplay.c
index 6b23a1def9fe..ba30ca6a14aa 100644
--- a/drivers/usb/misc/appledisplay.c
+++ b/drivers/usb/misc/appledisplay.c
@@ -216,10 +216,7 @@ static int appledisplay_probe(struct usb_interface *iface,
 	iface_desc = iface->cur_altsetting;
 	for (i = 0; i < iface_desc->desc.bNumEndpoints; i++) {
 		endpoint = &iface_desc->endpoint[i].desc;
-		if (!int_in_endpointAddr &&
-		    (endpoint->bEndpointAddress & USB_DIR_IN) &&
-		    ((endpoint->bmAttributes & USB_ENDPOINT_XFERTYPE_MASK) ==
-		     USB_ENDPOINT_XFER_INT)) {
+		if (!int_in_endpointAddr && usb_endpoint_is_int_in(endpoint)) {
 			/* we found an interrupt in endpoint */
 			int_in_endpointAddr = endpoint->bEndpointAddress;
 			break;
diff --git a/drivers/usb/misc/auerswald.c b/drivers/usb/misc/auerswald.c
index e4971d6aaafb..c703f73e1655 100644
--- a/drivers/usb/misc/auerswald.c
+++ b/drivers/usb/misc/auerswald.c
@@ -704,9 +704,7 @@ static void auerbuf_free (pauerbuf_t bp)
 {
 	kfree(bp->bufp);
 	kfree(bp->dr);
-	if (bp->urbp) {
-		usb_free_urb(bp->urbp);
-	}
+	usb_free_urb(bp->urbp);
 	kfree(bp);
 }
 
@@ -1155,8 +1153,7 @@ static void auerswald_int_release (pauerswald_t cp)
         dbg ("auerswald_int_release");
 
         /* stop the int endpoint */
-        if (cp->inturbp)
-                usb_kill_urb (cp->inturbp);
+	usb_kill_urb (cp->inturbp);
 
         /* deallocate memory */
         auerswald_int_free (cp);
diff --git a/drivers/usb/misc/emi26.c b/drivers/usb/misc/emi26.c
index 1fd9cb85f4ca..5c0a26cbd128 100644
--- a/drivers/usb/misc/emi26.c
+++ b/drivers/usb/misc/emi26.c
@@ -53,13 +53,12 @@ static void __exit emi26_exit (void);
 static int emi26_writememory (struct usb_device *dev, int address, unsigned char *data, int length, __u8 request)
 {
 	int result;
-	unsigned char *buffer =  kmalloc (length, GFP_KERNEL);
+	unsigned char *buffer =  kmemdup(data, length, GFP_KERNEL);
 
 	if (!buffer) {
 		err("emi26: kmalloc(%d) failed.", length);
 		return -ENOMEM;
 	}
-	memcpy (buffer, data, length);
 	/* Note: usb_control_msg returns negative value on error or length of the
 	 * 		 data that was written! */
 	result = usb_control_msg (dev, usb_sndctrlpipe(dev, 0), request, 0x40, address, 0, buffer, length, 300);
diff --git a/drivers/usb/misc/emi62.c b/drivers/usb/misc/emi62.c
index fe351371f274..23153eac0dfa 100644
--- a/drivers/usb/misc/emi62.c
+++ b/drivers/usb/misc/emi62.c
@@ -61,13 +61,12 @@ static void __exit emi62_exit (void);
 static int emi62_writememory (struct usb_device *dev, int address, unsigned char *data, int length, __u8 request)
 {
 	int result;
-	unsigned char *buffer =  kmalloc (length, GFP_KERNEL);
+	unsigned char *buffer =  kmemdup(data, length, GFP_KERNEL);
 
 	if (!buffer) {
 		err("emi62: kmalloc(%d) failed.", length);
 		return -ENOMEM;
 	}
-	memcpy (buffer, data, length);
 	/* Note: usb_control_msg returns negative value on error or length of the
 	 * 		 data that was written! */
 	result = usb_control_msg (dev, usb_sndctrlpipe(dev, 0), request, 0x40, address, 0, buffer, length, 300);
diff --git a/drivers/usb/misc/ftdi-elan.c b/drivers/usb/misc/ftdi-elan.c
index e4e2cf2ba915..18b1925032a8 100644
--- a/drivers/usb/misc/ftdi-elan.c
+++ b/drivers/usb/misc/ftdi-elan.c
@@ -272,7 +272,7 @@ void ftdi_elan_gone_away(struct platform_device *pdev)
 
 
 EXPORT_SYMBOL_GPL(ftdi_elan_gone_away);
-void ftdi_release_platform_dev(struct device *dev)
+static void ftdi_release_platform_dev(struct device *dev)
 {
         dev->parent = NULL;
 }
@@ -1399,14 +1399,6 @@ static int ftdi_elan_read_reg(struct usb_ftdi *ftdi, u32 *data)
         }
 }
 
-int usb_ftdi_elan_read_reg(struct platform_device *pdev, u32 *data)
-{
-        struct usb_ftdi *ftdi = platform_device_to_usb_ftdi(pdev);
-        return ftdi_elan_read_reg(ftdi, data);
-}
-
-
-EXPORT_SYMBOL_GPL(usb_ftdi_elan_read_reg);
 static int ftdi_elan_read_config(struct usb_ftdi *ftdi, int config_offset,
         u8 width, u32 *data)
 {
@@ -2606,10 +2598,7 @@ static int ftdi_elan_probe(struct usb_interface *interface,
         for (i = 0; i < iface_desc->desc.bNumEndpoints; ++i) {
                 endpoint = &iface_desc->endpoint[i].desc;
                 if (!ftdi->bulk_in_endpointAddr &&
-                        ((endpoint->bEndpointAddress & USB_ENDPOINT_DIR_MASK)
-                        == USB_DIR_IN) && ((endpoint->bmAttributes &
-                        USB_ENDPOINT_XFERTYPE_MASK) == USB_ENDPOINT_XFER_BULK))
-                        {
+		    usb_endpoint_is_bulk_in(endpoint)) {
                         buffer_size = le16_to_cpu(endpoint->wMaxPacketSize);
                         ftdi->bulk_in_size = buffer_size;
                         ftdi->bulk_in_endpointAddr = endpoint->bEndpointAddress;
@@ -2622,10 +2611,7 @@ static int ftdi_elan_probe(struct usb_interface *interface,
                         }
                 }
                 if (!ftdi->bulk_out_endpointAddr &&
-                        ((endpoint->bEndpointAddress & USB_ENDPOINT_DIR_MASK)
-                        == USB_DIR_OUT) && ((endpoint->bmAttributes &
-                        USB_ENDPOINT_XFERTYPE_MASK) == USB_ENDPOINT_XFER_BULK))
-                        {
+		    usb_endpoint_is_bulk_out(endpoint)) {
                         ftdi->bulk_out_endpointAddr =
                                 endpoint->bEndpointAddress;
                 }
diff --git a/drivers/usb/misc/idmouse.c b/drivers/usb/misc/idmouse.c
index 8e6e195a22ba..c9418535bef8 100644
--- a/drivers/usb/misc/idmouse.c
+++ b/drivers/usb/misc/idmouse.c
@@ -125,12 +125,12 @@ static DEFINE_MUTEX(disconnect_mutex);
 
 static int idmouse_create_image(struct usb_idmouse *dev)
 {
-	int bytes_read = 0;
-	int bulk_read = 0;
-	int result = 0;
+	int bytes_read;
+	int bulk_read;
+	int result;
 
 	memcpy(dev->bulk_in_buffer, HEADER, sizeof(HEADER)-1);
-	bytes_read += sizeof(HEADER)-1;
+	bytes_read = sizeof(HEADER)-1;
 
 	/* reset the device and set a fast blink rate */
 	result = ftip_command(dev, FTIP_RELEASE, 0, 0);
@@ -208,9 +208,9 @@ static inline void idmouse_delete(struct usb_idmouse *dev)
 
 static int idmouse_open(struct inode *inode, struct file *file)
 {
-	struct usb_idmouse *dev = NULL;
+	struct usb_idmouse *dev;
 	struct usb_interface *interface;
-	int result = 0;
+	int result;
 
 	/* prevent disconnects */
 	mutex_lock(&disconnect_mutex);
@@ -305,7 +305,7 @@ static ssize_t idmouse_read(struct file *file, char __user *buffer, size_t count
 				loff_t * ppos)
 {
 	struct usb_idmouse *dev;
-	int result = 0;
+	int result;
 
 	dev = (struct usb_idmouse *) file->private_data;
 
@@ -329,7 +329,7 @@ static int idmouse_probe(struct usb_interface *interface,
 				const struct usb_device_id *id)
 {
 	struct usb_device *udev = interface_to_usbdev(interface);
-	struct usb_idmouse *dev = NULL;
+	struct usb_idmouse *dev;
 	struct usb_host_interface *iface_desc;
 	struct usb_endpoint_descriptor *endpoint;
 	int result;
@@ -350,11 +350,7 @@ static int idmouse_probe(struct usb_interface *interface,
 
 	/* set up the endpoint information - use only the first bulk-in endpoint */
 	endpoint = &iface_desc->endpoint[0].desc;
-	if (!dev->bulk_in_endpointAddr
-		&& (endpoint->bEndpointAddress & USB_DIR_IN)
-		&& ((endpoint->bmAttributes & USB_ENDPOINT_XFERTYPE_MASK) ==
-		USB_ENDPOINT_XFER_BULK)) {
-
+	if (!dev->bulk_in_endpointAddr && usb_endpoint_is_bulk_in(endpoint)) {
 		/* we found a bulk in endpoint */
 		dev->orig_bi_size = le16_to_cpu(endpoint->wMaxPacketSize);
 		dev->bulk_in_size = 0x200; /* works _much_ faster */
diff --git a/drivers/usb/misc/legousbtower.c b/drivers/usb/misc/legousbtower.c
index 27089497e717..5dce797bddb7 100644
--- a/drivers/usb/misc/legousbtower.c
+++ b/drivers/usb/misc/legousbtower.c
@@ -317,12 +317,8 @@ static inline void tower_delete (struct lego_usb_tower *dev)
 	tower_abort_transfers (dev);
 
 	/* free data structures */
-	if (dev->interrupt_in_urb != NULL) {
-		usb_free_urb (dev->interrupt_in_urb);
-	}
-	if (dev->interrupt_out_urb != NULL) {
-		usb_free_urb (dev->interrupt_out_urb);
-	}
+	usb_free_urb(dev->interrupt_in_urb);
+	usb_free_urb(dev->interrupt_out_urb);
 	kfree (dev->read_buffer);
 	kfree (dev->interrupt_in_buffer);
 	kfree (dev->interrupt_out_buffer);
@@ -502,15 +498,11 @@ static void tower_abort_transfers (struct lego_usb_tower *dev)
 	if (dev->interrupt_in_running) {
 		dev->interrupt_in_running = 0;
 		mb();
-		if (dev->interrupt_in_urb != NULL && dev->udev) {
+		if (dev->udev)
 			usb_kill_urb (dev->interrupt_in_urb);
-		}
-	}
-	if (dev->interrupt_out_busy) {
-		if (dev->interrupt_out_urb != NULL && dev->udev) {
-			usb_kill_urb (dev->interrupt_out_urb);
-		}
 	}
+	if (dev->interrupt_out_busy && dev->udev)
+		usb_kill_urb(dev->interrupt_out_urb);
 
 exit:
 	dbg(2, "%s: leave", __FUNCTION__);
@@ -898,14 +890,11 @@ static int tower_probe (struct usb_interface *interface, const struct usb_device
 	for (i = 0; i < iface_desc->desc.bNumEndpoints; ++i) {
 		endpoint = &iface_desc->endpoint[i].desc;
 
-		if (((endpoint->bEndpointAddress & USB_ENDPOINT_DIR_MASK) == USB_DIR_IN) &&
-		    ((endpoint->bmAttributes & USB_ENDPOINT_XFERTYPE_MASK) == USB_ENDPOINT_XFER_INT)) {
-			dev->interrupt_in_endpoint = endpoint;
-		}
-
-		if (((endpoint->bEndpointAddress & USB_ENDPOINT_DIR_MASK) == USB_DIR_OUT) &&
-		    ((endpoint->bmAttributes & USB_ENDPOINT_XFERTYPE_MASK) == USB_ENDPOINT_XFER_INT)) {
-			dev->interrupt_out_endpoint = endpoint;
+		if (usb_endpoint_xfer_int(endpoint)) {
+			if (usb_endpoint_dir_in(endpoint))
+				dev->interrupt_in_endpoint = endpoint;
+			else
+				dev->interrupt_out_endpoint = endpoint;
 		}
 	}
 	if(dev->interrupt_in_endpoint == NULL) {
diff --git a/drivers/usb/misc/phidgetkit.c b/drivers/usb/misc/phidgetkit.c
index 33e716c6a79b..9659c79e187e 100644
--- a/drivers/usb/misc/phidgetkit.c
+++ b/drivers/usb/misc/phidgetkit.c
@@ -554,7 +554,7 @@ static int interfacekit_probe(struct usb_interface *intf, const struct usb_devic
 		return -ENODEV;
 
 	endpoint = &interface->endpoint[0].desc;
-	if (!(endpoint->bEndpointAddress & 0x80)) 
+	if (!usb_endpoint_dir_in(endpoint))
 		return -ENODEV;
 	/*
 	 * bmAttributes
@@ -653,8 +653,7 @@ out2:
 		device_remove_file(kit->dev, &dev_output_attrs[i]);
 out:
 	if (kit) {
-		if (kit->irq)
-			usb_free_urb(kit->irq);
+		usb_free_urb(kit->irq);
 		if (kit->data)
 			usb_buffer_free(dev, URB_INT_SIZE, kit->data, kit->data_dma);
 		if (kit->dev)
diff --git a/drivers/usb/misc/phidgetmotorcontrol.c b/drivers/usb/misc/phidgetmotorcontrol.c
index 0385ffcc7419..2bb4fa572bb7 100644
--- a/drivers/usb/misc/phidgetmotorcontrol.c
+++ b/drivers/usb/misc/phidgetmotorcontrol.c
@@ -324,7 +324,7 @@ static int motorcontrol_probe(struct usb_interface *intf, const struct usb_devic
 		return -ENODEV;
 
 	endpoint = &interface->endpoint[0].desc;
-	if (!(endpoint->bEndpointAddress & 0x80))
+	if (!usb_endpoint_dir_in(endpoint))
 		return -ENODEV;
 
 	/*
@@ -393,8 +393,7 @@ out2:
 		device_remove_file(mc->dev, &dev_attrs[i]);
 out:
 	if (mc) {
-		if (mc->irq)
-			usb_free_urb(mc->irq);
+		usb_free_urb(mc->irq);
 		if (mc->data)
 			usb_buffer_free(dev, URB_INT_SIZE, mc->data, mc->data_dma);
 		if (mc->dev)
diff --git a/drivers/usb/misc/usb_u132.h b/drivers/usb/misc/usb_u132.h
index 551ba8906d62..dc2e5a31caec 100644
--- a/drivers/usb/misc/usb_u132.h
+++ b/drivers/usb/misc/usb_u132.h
@@ -52,7 +52,7 @@
 * the kernel to load the "u132-hcd" module.
 *
 * The "ftdi-u132" module provides the interface to the inserted
-* PC card and the "u132-hcd" module uses the API to send and recieve
+* PC card and the "u132-hcd" module uses the API to send and receive
 * data. The API features call-backs, so that part of the "u132-hcd"
 * module code will run in the context of one of the kernel threads
 * of the "ftdi-u132" module.
@@ -95,3 +95,7 @@ int usb_ftdi_elan_edset_setup(struct platform_device *pdev, u8 ed_number,
          int halted, int skipped, int actual, int non_null));
 int usb_ftdi_elan_edset_flush(struct platform_device *pdev, u8 ed_number,
         void *endp);
+int usb_ftdi_elan_read_pcimem(struct platform_device *pdev, int mem_offset,
+			      u8 width, u32 *data);
+int usb_ftdi_elan_write_pcimem(struct platform_device *pdev, int mem_offset,
+			       u8 width, u32 data);
diff --git a/drivers/usb/misc/usbtest.c b/drivers/usb/misc/usbtest.c
index 7c2cbdf81d20..194065dbb51f 100644
--- a/drivers/usb/misc/usbtest.c
+++ b/drivers/usb/misc/usbtest.c
@@ -138,7 +138,7 @@ get_endpoints (struct usbtest_dev *dev, struct usb_interface *intf)
 			default:
 				continue;
 			}
-			if (e->desc.bEndpointAddress & USB_DIR_IN) {
+			if (usb_endpoint_dir_in(&e->desc)) {
 				if (!in)
 					in = e;
 			} else {
@@ -147,7 +147,7 @@ get_endpoints (struct usbtest_dev *dev, struct usb_interface *intf)
 			}
 			continue;
 try_iso:
-			if (e->desc.bEndpointAddress & USB_DIR_IN) {
+			if (usb_endpoint_dir_in(&e->desc)) {
 				if (!iso_in)
 					iso_in = e;
 			} else {
diff --git a/drivers/usb/net/asix.c b/drivers/usb/net/asix.c
index 881841e600de..95e682e2c9d6 100644
--- a/drivers/usb/net/asix.c
+++ b/drivers/usb/net/asix.c
@@ -249,9 +249,9 @@ asix_write_cmd_async(struct usbnet *dev, u8 cmd, u16 value, u16 index,
 
 	req->bRequestType = USB_DIR_OUT | USB_TYPE_VENDOR | USB_RECIP_DEVICE;
 	req->bRequest = cmd;
-	req->wValue = value;
-	req->wIndex = index;
-	req->wLength = size;
+	req->wValue = cpu_to_le16(value);
+	req->wIndex = cpu_to_le16(index);
+	req->wLength = cpu_to_le16(size);
 
 	usb_fill_control_urb(urb, dev->udev,
 			     usb_sndctrlpipe(dev->udev, 0),
diff --git a/drivers/usb/net/catc.c b/drivers/usb/net/catc.c
index f740325abac4..907b820a5faf 100644
--- a/drivers/usb/net/catc.c
+++ b/drivers/usb/net/catc.c
@@ -786,14 +786,10 @@ static int catc_probe(struct usb_interface *intf, const struct usb_device_id *id
 	if ((!catc->ctrl_urb) || (!catc->tx_urb) || 
 	    (!catc->rx_urb) || (!catc->irq_urb)) {
 		err("No free urbs available.");
-		if (catc->ctrl_urb)
-			usb_free_urb(catc->ctrl_urb);
-		if (catc->tx_urb)
-			usb_free_urb(catc->tx_urb);
-		if (catc->rx_urb)
-			usb_free_urb(catc->rx_urb);
-		if (catc->irq_urb)
-			usb_free_urb(catc->irq_urb);
+		usb_free_urb(catc->ctrl_urb);
+		usb_free_urb(catc->tx_urb);
+		usb_free_urb(catc->rx_urb);
+		usb_free_urb(catc->irq_urb);
 		free_netdev(netdev);
 		return -ENOMEM;
 	}
diff --git a/drivers/usb/net/cdc_ether.c b/drivers/usb/net/cdc_ether.c
index f6971b88349d..44a91547146e 100644
--- a/drivers/usb/net/cdc_ether.c
+++ b/drivers/usb/net/cdc_ether.c
@@ -200,8 +200,7 @@ next_desc:
 
 		dev->status = &info->control->cur_altsetting->endpoint [0];
 		desc = &dev->status->desc;
-		if (desc->bmAttributes != USB_ENDPOINT_XFER_INT
-				|| !(desc->bEndpointAddress & USB_DIR_IN)
+		if (!usb_endpoint_is_int_in(desc)
 				|| (le16_to_cpu(desc->wMaxPacketSize)
 					< sizeof(struct usb_cdc_notification))
 				|| !desc->bInterval) {
diff --git a/drivers/usb/net/net1080.c b/drivers/usb/net/net1080.c
index ce00de8f13a1..a77410562e12 100644
--- a/drivers/usb/net/net1080.c
+++ b/drivers/usb/net/net1080.c
@@ -237,12 +237,12 @@ static inline void nc_dump_usbctl(struct usbnet *dev, u16 usbctl)
 #define	STATUS_CONN_OTHER	(1 << 14)
 #define	STATUS_SUSPEND_OTHER	(1 << 13)
 #define	STATUS_MAILBOX_OTHER	(1 << 12)
-#define	STATUS_PACKETS_OTHER(n)	(((n) >> 8) && 0x03)
+#define	STATUS_PACKETS_OTHER(n)	(((n) >> 8) & 0x03)
 
 #define	STATUS_CONN_THIS	(1 << 6)
 #define	STATUS_SUSPEND_THIS	(1 << 5)
 #define	STATUS_MAILBOX_THIS	(1 << 4)
-#define	STATUS_PACKETS_THIS(n)	(((n) >> 0) && 0x03)
+#define	STATUS_PACKETS_THIS(n)	(((n) >> 0) & 0x03)
 
 #define	STATUS_UNSPEC_MASK	0x0c8c
 #define	STATUS_NOISE_MASK 	((u16)~(0x0303|STATUS_UNSPEC_MASK))
diff --git a/drivers/usb/net/pegasus.c b/drivers/usb/net/pegasus.c
index 78cf6f091285..b5690b3834e3 100644
--- a/drivers/usb/net/pegasus.c
+++ b/drivers/usb/net/pegasus.c
@@ -163,6 +163,7 @@ static int get_registers(pegasus_t * pegasus, __u16 indx, __u16 size,
 
 	/* using ATOMIC, we'd never wake up if we slept */
 	if ((ret = usb_submit_urb(pegasus->ctrl_urb, GFP_ATOMIC))) {
+		set_current_state(TASK_RUNNING);
 		if (ret == -ENODEV)
 			netif_device_detach(pegasus->net);
 		if (netif_msg_drv(pegasus))
diff --git a/drivers/usb/net/usbnet.c b/drivers/usb/net/usbnet.c
index 79b5474fe234..327f97555679 100644
--- a/drivers/usb/net/usbnet.c
+++ b/drivers/usb/net/usbnet.c
@@ -116,7 +116,7 @@ int usbnet_get_endpoints(struct usbnet *dev, struct usb_interface *intf)
 			e = alt->endpoint + ep;
 			switch (e->desc.bmAttributes) {
 			case USB_ENDPOINT_XFER_INT:
-				if (!(e->desc.bEndpointAddress & USB_DIR_IN))
+				if (!usb_endpoint_dir_in(&e->desc))
 					continue;
 				intr = 1;
 				/* FALLTHROUGH */
@@ -125,7 +125,7 @@ int usbnet_get_endpoints(struct usbnet *dev, struct usb_interface *intf)
 			default:
 				continue;
 			}
-			if (e->desc.bEndpointAddress & USB_DIR_IN) {
+			if (usb_endpoint_dir_in(&e->desc)) {
 				if (!intr && !in)
 					in = e;
 				else if (intr && !status)
diff --git a/drivers/usb/serial/Kconfig b/drivers/usb/serial/Kconfig
index 2a8dd4cc943d..2f4d303ee36f 100644
--- a/drivers/usb/serial/Kconfig
+++ b/drivers/usb/serial/Kconfig
@@ -554,6 +554,17 @@ config USB_SERIAL_OMNINET
 	  To compile this driver as a module, choose M here: the
 	  module will be called omninet.
 
+config USB_SERIAL_DEBUG
+	tristate "USB Debugging Device"
+	depends on USB_SERIAL
+	help
+	  Say Y here if you have a USB debugging device used to recieve
+	  debugging data from another machine.  The most common of these
+	  devices is the NetChip TurboCONNECT device.
+
+	  To compile this driver as a module, choose M here: the
+	  module will be called usb-debug.
+
 config USB_EZUSB
 	bool
 	depends on USB_SERIAL_KEYSPAN_PDA || USB_SERIAL_XIRCOM || USB_SERIAL_KEYSPAN || USB_SERIAL_WHITEHEAT
diff --git a/drivers/usb/serial/Makefile b/drivers/usb/serial/Makefile
index a5047dc599bb..61166ad450e6 100644
--- a/drivers/usb/serial/Makefile
+++ b/drivers/usb/serial/Makefile
@@ -18,6 +18,7 @@ obj-$(CONFIG_USB_SERIAL_BELKIN)			+= belkin_sa.o
 obj-$(CONFIG_USB_SERIAL_CP2101)			+= cp2101.o
 obj-$(CONFIG_USB_SERIAL_CYBERJACK)		+= cyberjack.o
 obj-$(CONFIG_USB_SERIAL_CYPRESS_M8)		+= cypress_m8.o
+obj-$(CONFIG_USB_SERIAL_DEBUG)			+= usb_debug.o
 obj-$(CONFIG_USB_SERIAL_DIGI_ACCELEPORT)	+= digi_acceleport.o
 obj-$(CONFIG_USB_SERIAL_EDGEPORT)		+= io_edgeport.o
 obj-$(CONFIG_USB_SERIAL_EDGEPORT_TI)		+= io_ti.o
diff --git a/drivers/usb/serial/aircable.c b/drivers/usb/serial/aircable.c
index 2a4ac9bd6a3a..86bcf63b6ba5 100644
--- a/drivers/usb/serial/aircable.c
+++ b/drivers/usb/serial/aircable.c
@@ -272,8 +272,11 @@ static void aircable_read(struct work_struct *work)
 	 */
 	tty = port->tty;
 
-	if (!tty)
+	if (!tty) {
 		schedule_work(&priv->rx_work);
+		err("%s - No tty available", __FUNCTION__);
+		return ;
+	}
 
 	count = min(64, serial_buf_data_avail(priv->rx_buf));
 
@@ -307,9 +310,7 @@ static int aircable_probe(struct usb_serial *serial,
 
 	for (i = 0; i < iface_desc->desc.bNumEndpoints; i++) {
 		endpoint = &iface_desc->endpoint[i].desc;
-		if (((endpoint->bEndpointAddress & 0x80) == 0x00) &&
-			((endpoint->bmAttributes & 3) == 0x02)) {
-			/* we found our bulk out endpoint */
+		if (usb_endpoint_is_bulk_out(endpoint)) {
 			dbg("found bulk out on endpoint %d", i);
 			++num_bulk_out;
 		}
diff --git a/drivers/usb/serial/airprime.c b/drivers/usb/serial/airprime.c
index 7f5d546da39a..96c73726d74a 100644
--- a/drivers/usb/serial/airprime.c
+++ b/drivers/usb/serial/airprime.c
@@ -19,6 +19,7 @@
 static struct usb_device_id id_table [] = {
 	{ USB_DEVICE(0x0c88, 0x17da) }, /* Kyocera Wireless KPC650/Passport */
 	{ USB_DEVICE(0x1410, 0x1110) }, /* Novatel Wireless Merlin CDMA */
+	{ USB_DEVICE(0x1410, 0x1430) },	/* Novatel Merlin XU870 HSDPA/3G */
 	{ USB_DEVICE(0x1410, 0x1100) }, /* ExpressCard34 Qualcomm 3G CDMA */
 	{ },
 };
diff --git a/drivers/usb/serial/ark3116.c b/drivers/usb/serial/ark3116.c
index ca52f12f0e24..863966c1c5ac 100644
--- a/drivers/usb/serial/ark3116.c
+++ b/drivers/usb/serial/ark3116.c
@@ -85,10 +85,9 @@ static int ark3116_attach(struct usb_serial *serial)
 	int i;
 
 	for (i = 0; i < serial->num_ports; ++i) {
-		priv = kmalloc(sizeof (struct ark3116_private), GFP_KERNEL);
+		priv = kzalloc(sizeof(struct ark3116_private), GFP_KERNEL);
 		if (!priv)
 			goto cleanup;
-		memset(priv, 0x00, sizeof (struct ark3116_private));
 		spin_lock_init(&priv->lock);
 
 		usb_set_serial_port_data(serial->port[i], priv);
diff --git a/drivers/usb/serial/console.c b/drivers/usb/serial/console.c
index 3a9073dbfe6a..7167728d764c 100644
--- a/drivers/usb/serial/console.c
+++ b/drivers/usb/serial/console.c
@@ -166,19 +166,17 @@ static int usb_console_setup(struct console *co, char *options)
 	if (serial->type->set_termios) {
 		/* build up a fake tty structure so that the open call has something
 		 * to look at to get the cflag value */
-		tty = kmalloc (sizeof (*tty), GFP_KERNEL);
+		tty = kzalloc(sizeof(*tty), GFP_KERNEL);
 		if (!tty) {
 			err ("no more memory");
 			return -ENOMEM;
 		}
-		termios = kmalloc (sizeof (*termios), GFP_KERNEL);
+		termios = kzalloc(sizeof(*termios), GFP_KERNEL);
 		if (!termios) {
 			err ("no more memory");
 			kfree (tty);
 			return -ENOMEM;
 		}
-		memset (tty, 0x00, sizeof(*tty));
-		memset (termios, 0x00, sizeof(*termios));
 		termios->c_cflag = cflag;
 		tty->termios = termios;
 		port->tty = tty;
diff --git a/drivers/usb/serial/cypress_m8.c b/drivers/usb/serial/cypress_m8.c
index f2e89a083659..093f303b3189 100644
--- a/drivers/usb/serial/cypress_m8.c
+++ b/drivers/usb/serial/cypress_m8.c
@@ -1684,15 +1684,14 @@ static int __init cypress_init(void)
 
 	info(DRIVER_DESC " " DRIVER_VERSION);
 	return 0;
+
 failed_usb_register:
-	usb_deregister(&cypress_driver);
-failed_ca42v2_register:
 	usb_serial_deregister(&cypress_ca42v2_device);
-failed_hidcom_register:
+failed_ca42v2_register:
 	usb_serial_deregister(&cypress_hidcom_device);
-failed_em_register:
+failed_hidcom_register:
 	usb_serial_deregister(&cypress_earthmate_device);
-
+failed_em_register:
 	return retval;
 }
 
diff --git a/drivers/usb/serial/digi_acceleport.c b/drivers/usb/serial/digi_acceleport.c
index fd159b040bfb..83d0e21145b0 100644
--- a/drivers/usb/serial/digi_acceleport.c
+++ b/drivers/usb/serial/digi_acceleport.c
@@ -157,7 +157,7 @@
 *       to TASK_RUNNING will be lost and write_chan's subsequent call to
 *       schedule() will never return (unless it catches a signal).
 *       This race condition occurs because write_bulk_callback() (and thus
-*       the wakeup) are called asynchonously from an interrupt, rather than
+*       the wakeup) are called asynchronously from an interrupt, rather than
 *       from the scheduler.  We can avoid the race by calling the wakeup
 *       from the scheduler queue and that's our fix:  Now, at the end of
 *       write_bulk_callback() we queue up a wakeup call on the scheduler
diff --git a/drivers/usb/serial/ezusb.c b/drivers/usb/serial/ezusb.c
index 5169c2d154ab..97ee718b1da2 100644
--- a/drivers/usb/serial/ezusb.c
+++ b/drivers/usb/serial/ezusb.c
@@ -31,12 +31,11 @@ int ezusb_writememory (struct usb_serial *serial, int address, unsigned char *da
 		return -ENODEV;
 	}
 
-	transfer_buffer =  kmalloc (length, GFP_KERNEL);
+	transfer_buffer = kmemdup(data, length, GFP_KERNEL);
 	if (!transfer_buffer) {
 		dev_err(&serial->dev->dev, "%s - kmalloc(%d) failed.\n", __FUNCTION__, length);
 		return -ENOMEM;
 	}
-	memcpy (transfer_buffer, data, length);
 	result = usb_control_msg (serial->dev, usb_sndctrlpipe(serial->dev, 0), bRequest, 0x40, address, 0, transfer_buffer, length, 3000);
 	kfree (transfer_buffer);
 	return result;
diff --git a/drivers/usb/serial/ftdi_sio.c b/drivers/usb/serial/ftdi_sio.c
index 88ed5c1d236c..72e4d48f51e9 100644
--- a/drivers/usb/serial/ftdi_sio.c
+++ b/drivers/usb/serial/ftdi_sio.c
@@ -1390,8 +1390,7 @@ static void ftdi_close (struct usb_serial_port *port, struct file *filp)
 	flush_scheduled_work();
 
 	/* shutdown our bulk read */
-	if (port->read_urb)
-		usb_kill_urb(port->read_urb);
+	usb_kill_urb(port->read_urb);
 } /* ftdi_close */
 
 
diff --git a/drivers/usb/serial/garmin_gps.c b/drivers/usb/serial/garmin_gps.c
index 4543152a9966..6530d391ebed 100644
--- a/drivers/usb/serial/garmin_gps.c
+++ b/drivers/usb/serial/garmin_gps.c
@@ -1523,12 +1523,11 @@ static int garmin_attach (struct usb_serial *serial)
 
 	dbg("%s", __FUNCTION__);
 
-	garmin_data_p = kmalloc (sizeof(struct garmin_data), GFP_KERNEL);
+	garmin_data_p = kzalloc(sizeof(struct garmin_data), GFP_KERNEL);
 	if (garmin_data_p == NULL) {
 		dev_err(&port->dev, "%s - Out of memory\n", __FUNCTION__);
 		return -ENOMEM;
 	}
-	memset (garmin_data_p, 0, sizeof(struct garmin_data));
 	init_timer(&garmin_data_p->timer);
 	spin_lock_init(&garmin_data_p->lock);
 	INIT_LIST_HEAD(&garmin_data_p->pktlist);
diff --git a/drivers/usb/serial/io_edgeport.c b/drivers/usb/serial/io_edgeport.c
index 91bd3014ef1e..d06547a13f28 100644
--- a/drivers/usb/serial/io_edgeport.c
+++ b/drivers/usb/serial/io_edgeport.c
@@ -1038,9 +1038,7 @@ static void edge_close (struct usb_serial_port *port, struct file * filp)
 	edge_port->open = FALSE;
 	edge_port->openPending = FALSE;
 
-	if (edge_port->write_urb) {
-		usb_kill_urb(edge_port->write_urb);
-	}
+	usb_kill_urb(edge_port->write_urb);
 
 	if (edge_port->write_urb) {
 		/* if this urb had a transfer buffer already (old transfer) free it */
diff --git a/drivers/usb/serial/ipw.c b/drivers/usb/serial/ipw.c
index 2a4bb66691ad..d3b9a351cef8 100644
--- a/drivers/usb/serial/ipw.c
+++ b/drivers/usb/serial/ipw.c
@@ -206,10 +206,9 @@ static int ipw_open(struct usb_serial_port *port, struct file *filp)
 
 	dbg("%s", __FUNCTION__);
 
-	buf_flow_init = kmalloc(16, GFP_KERNEL);
+	buf_flow_init = kmemdup(buf_flow_static, 16, GFP_KERNEL);
 	if (!buf_flow_init)
 		return -ENOMEM;
-	memcpy(buf_flow_init, buf_flow_static, 16);
 
 	if (port->tty)
 		port->tty->low_latency = 1;
diff --git a/drivers/usb/serial/keyspan.c b/drivers/usb/serial/keyspan.c
index 53be824eb1bf..7639652cec42 100644
--- a/drivers/usb/serial/keyspan.c
+++ b/drivers/usb/serial/keyspan.c
@@ -2306,22 +2306,16 @@ static void keyspan_shutdown (struct usb_serial *serial)
 	}
 
 	/* Now free them */
-	if (s_priv->instat_urb)
-		usb_free_urb(s_priv->instat_urb);
-	if (s_priv->glocont_urb)
-		usb_free_urb(s_priv->glocont_urb);
+	usb_free_urb(s_priv->instat_urb);
+	usb_free_urb(s_priv->glocont_urb);
 	for (i = 0; i < serial->num_ports; ++i) {
 		port = serial->port[i];
 		p_priv = usb_get_serial_port_data(port);
-		if (p_priv->inack_urb)
-			usb_free_urb(p_priv->inack_urb);
-		if (p_priv->outcont_urb)
-			usb_free_urb(p_priv->outcont_urb);
+		usb_free_urb(p_priv->inack_urb);
+		usb_free_urb(p_priv->outcont_urb);
 		for (j = 0; j < 2; j++) {
-			if (p_priv->in_urbs[j])
-				usb_free_urb(p_priv->in_urbs[j]);
-			if (p_priv->out_urbs[j])
-				usb_free_urb(p_priv->out_urbs[j]);
+			usb_free_urb(p_priv->in_urbs[j]);
+			usb_free_urb(p_priv->out_urbs[j]);
 		}
 	}
 
diff --git a/drivers/usb/serial/kobil_sct.c b/drivers/usb/serial/kobil_sct.c
index ff03331e0bcf..237289920f03 100644
--- a/drivers/usb/serial/kobil_sct.c
+++ b/drivers/usb/serial/kobil_sct.c
@@ -185,13 +185,11 @@ static int kobil_startup (struct usb_serial *serial)
   
  	for (i = 0; i < altsetting->desc.bNumEndpoints; i++) {
 		endpoint = &altsetting->endpoint[i];
-		if (((endpoint->desc.bEndpointAddress & USB_ENDPOINT_DIR_MASK) == USB_DIR_OUT) && 
- 		    ((endpoint->desc.bmAttributes & USB_ENDPOINT_XFERTYPE_MASK) == USB_ENDPOINT_XFER_INT)) {
+		if (usb_endpoint_is_int_out(&endpoint->desc)) {
 		 	dbg("%s Found interrupt out endpoint. Address: %d", __FUNCTION__, endpoint->desc.bEndpointAddress);
 		 	priv->write_int_endpoint_address = endpoint->desc.bEndpointAddress;
  		}
- 		if (((endpoint->desc.bEndpointAddress & USB_ENDPOINT_DIR_MASK) == USB_DIR_IN) && 
- 		    ((endpoint->desc.bmAttributes & USB_ENDPOINT_XFERTYPE_MASK) == USB_ENDPOINT_XFER_INT)) {
+		if (usb_endpoint_is_int_in(&endpoint->desc)) {
 		 	dbg("%s Found interrupt in  endpoint. Address: %d", __FUNCTION__, endpoint->desc.bEndpointAddress);
 		 	priv->read_int_endpoint_address = endpoint->desc.bEndpointAddress;
 	 	}
@@ -355,8 +353,7 @@ static void kobil_close (struct usb_serial_port *port, struct file *filp)
 		usb_free_urb( port->write_urb );
 		port->write_urb = NULL;
 	}
-	if (port->interrupt_in_urb)
-		usb_kill_urb(port->interrupt_in_urb);
+	usb_kill_urb(port->interrupt_in_urb);
 }
 
 
diff --git a/drivers/usb/serial/mct_u232.c b/drivers/usb/serial/mct_u232.c
index b7582cc496dc..a906e500a02b 100644
--- a/drivers/usb/serial/mct_u232.c
+++ b/drivers/usb/serial/mct_u232.c
@@ -358,10 +358,8 @@ static int mct_u232_startup (struct usb_serial *serial)
 	/* Puh, that's dirty */
 	port = serial->port[0];
 	rport = serial->port[1];
-	if (port->read_urb) {
-		/* No unlinking, it wasn't submitted yet. */
-		usb_free_urb(port->read_urb);
-	}
+	/* No unlinking, it wasn't submitted yet. */
+	usb_free_urb(port->read_urb);
 	port->read_urb = rport->interrupt_in_urb;
 	rport->interrupt_in_urb = NULL;
 	port->read_urb->context = port;
diff --git a/drivers/usb/serial/mos7840.c b/drivers/usb/serial/mos7840.c
index 5b71962d0351..02c89e10b2cf 100644
--- a/drivers/usb/serial/mos7840.c
+++ b/drivers/usb/serial/mos7840.c
@@ -2596,12 +2596,11 @@ static int mos7840_startup(struct usb_serial *serial)
 
 	/* set up port private structures */
 	for (i = 0; i < serial->num_ports; ++i) {
-		mos7840_port = kmalloc(sizeof(struct moschip_port), GFP_KERNEL);
+		mos7840_port = kzalloc(sizeof(struct moschip_port), GFP_KERNEL);
 		if (mos7840_port == NULL) {
 			err("%s - Out of memory", __FUNCTION__);
 			return -ENOMEM;
 		}
-		memset(mos7840_port, 0, sizeof(struct moschip_port));
 
 		/* Initialize all port interrupt end point to port 0 int endpoint *
 		 * Our device has only one interrupt end point comman to all port */
diff --git a/drivers/usb/serial/navman.c b/drivers/usb/serial/navman.c
index 0610409a6568..054abee81652 100644
--- a/drivers/usb/serial/navman.c
+++ b/drivers/usb/serial/navman.c
@@ -95,8 +95,7 @@ static void navman_close(struct usb_serial_port *port, struct file *filp)
 {
 	dbg("%s - port %d", __FUNCTION__, port->number);
 
-	if (port->interrupt_in_urb)
-		usb_kill_urb(port->interrupt_in_urb);
+	usb_kill_urb(port->interrupt_in_urb);
 }
 
 static int navman_write(struct usb_serial_port *port,
diff --git a/drivers/usb/serial/ti_usb_3410_5052.c b/drivers/usb/serial/ti_usb_3410_5052.c
index 07400c0c8a8c..ae98d8cbdbb8 100644
--- a/drivers/usb/serial/ti_usb_3410_5052.c
+++ b/drivers/usb/serial/ti_usb_3410_5052.c
@@ -228,6 +228,7 @@ static int product_5052_count;
 /* null entry */
 static struct usb_device_id ti_id_table_3410[1+TI_EXTRA_VID_PID_COUNT+1] = {
 	{ USB_DEVICE(TI_VENDOR_ID, TI_3410_PRODUCT_ID) },
+	{ USB_DEVICE(TI_VENDOR_ID, TI_3410_EZ430_ID) },
 };
 
 static struct usb_device_id ti_id_table_5052[4+TI_EXTRA_VID_PID_COUNT+1] = {
@@ -239,6 +240,7 @@ static struct usb_device_id ti_id_table_5052[4+TI_EXTRA_VID_PID_COUNT+1] = {
 
 static struct usb_device_id ti_id_table_combined[] = {
 	{ USB_DEVICE(TI_VENDOR_ID, TI_3410_PRODUCT_ID) },
+	{ USB_DEVICE(TI_VENDOR_ID, TI_3410_EZ430_ID) },
 	{ USB_DEVICE(TI_VENDOR_ID, TI_5052_BOOT_PRODUCT_ID) },
 	{ USB_DEVICE(TI_VENDOR_ID, TI_5152_BOOT_PRODUCT_ID) },
 	{ USB_DEVICE(TI_VENDOR_ID, TI_5052_EEPROM_PRODUCT_ID) },
@@ -459,13 +461,12 @@ static int ti_startup(struct usb_serial *serial)
 
 	/* set up port structures */
 	for (i = 0; i < serial->num_ports; ++i) {
-		tport = kmalloc(sizeof(struct ti_port), GFP_KERNEL);
+		tport = kzalloc(sizeof(struct ti_port), GFP_KERNEL);
 		if (tport == NULL) {
 			dev_err(&dev->dev, "%s - out of memory\n", __FUNCTION__);
 			status = -ENOMEM;
 			goto free_tports;
 		}
-		memset(tport, 0, sizeof(struct ti_port));
 		spin_lock_init(&tport->tp_lock);
 		tport->tp_uart_base_addr = (i == 0 ? TI_UART1_BASE_ADDR : TI_UART2_BASE_ADDR);
 		tport->tp_flags = low_latency ? ASYNC_LOW_LATENCY : 0;
diff --git a/drivers/usb/serial/ti_usb_3410_5052.h b/drivers/usb/serial/ti_usb_3410_5052.h
index 02c1aeb9e1b8..b5541bf991ba 100644
--- a/drivers/usb/serial/ti_usb_3410_5052.h
+++ b/drivers/usb/serial/ti_usb_3410_5052.h
@@ -28,6 +28,7 @@
 /* Vendor and product ids */
 #define TI_VENDOR_ID			0x0451
 #define TI_3410_PRODUCT_ID		0x3410
+#define TI_3410_EZ430_ID		0xF430  /* TI ez430 development tool */
 #define TI_5052_BOOT_PRODUCT_ID		0x5052	/* no EEPROM, no firmware */
 #define TI_5152_BOOT_PRODUCT_ID		0x5152	/* no EEPROM, no firmware */
 #define TI_5052_EEPROM_PRODUCT_ID	0x505A	/* EEPROM, no firmware */
diff --git a/drivers/usb/serial/usb-serial.c b/drivers/usb/serial/usb-serial.c
index 2cfba8488a93..3d5072f14b8d 100644
--- a/drivers/usb/serial/usb-serial.c
+++ b/drivers/usb/serial/usb-serial.c
@@ -953,32 +953,28 @@ probe_error:
 		port = serial->port[i];
 		if (!port)
 			continue;
-		if (port->read_urb)
-			usb_free_urb (port->read_urb);
+		usb_free_urb(port->read_urb);
 		kfree(port->bulk_in_buffer);
 	}
 	for (i = 0; i < num_bulk_out; ++i) {
 		port = serial->port[i];
 		if (!port)
 			continue;
-		if (port->write_urb)
-			usb_free_urb (port->write_urb);
+		usb_free_urb(port->write_urb);
 		kfree(port->bulk_out_buffer);
 	}
 	for (i = 0; i < num_interrupt_in; ++i) {
 		port = serial->port[i];
 		if (!port)
 			continue;
-		if (port->interrupt_in_urb)
-			usb_free_urb (port->interrupt_in_urb);
+		usb_free_urb(port->interrupt_in_urb);
 		kfree(port->interrupt_in_buffer);
 	}
 	for (i = 0; i < num_interrupt_out; ++i) {
 		port = serial->port[i];
 		if (!port)
 			continue;
-		if (port->interrupt_out_urb)
-			usb_free_urb (port->interrupt_out_urb);
+		usb_free_urb(port->interrupt_out_urb);
 		kfree(port->interrupt_out_buffer);
 	}
 
diff --git a/drivers/usb/serial/usb_debug.c b/drivers/usb/serial/usb_debug.c
new file mode 100644
index 000000000000..257a5e436873
--- /dev/null
+++ b/drivers/usb/serial/usb_debug.c
@@ -0,0 +1,65 @@
+/*
+ * USB Debug cable driver
+ *
+ * Copyright (C) 2006 Greg Kroah-Hartman <greg@kroah.com>
+ *
+ *	This program is free software; you can redistribute it and/or
+ *	modify it under the terms of the GNU General Public License version
+ *	2 as published by the Free Software Foundation.
+ */
+
+#include <linux/kernel.h>
+#include <linux/init.h>
+#include <linux/tty.h>
+#include <linux/module.h>
+#include <linux/usb.h>
+#include <linux/usb/serial.h>
+
+static struct usb_device_id id_table [] = {
+	{ USB_DEVICE(0x0525, 0x127a) },
+	{ },
+};
+MODULE_DEVICE_TABLE(usb, id_table);
+
+static struct usb_driver debug_driver = {
+	.name =		"debug",
+	.probe =	usb_serial_probe,
+	.disconnect =	usb_serial_disconnect,
+	.id_table =	id_table,
+	.no_dynamic_id = 	1,
+};
+
+static struct usb_serial_driver debug_device = {
+	.driver = {
+		.owner =	THIS_MODULE,
+		.name =		"debug",
+	},
+	.id_table =		id_table,
+	.num_interrupt_in =	NUM_DONT_CARE,
+	.num_bulk_in =		NUM_DONT_CARE,
+	.num_bulk_out =		NUM_DONT_CARE,
+	.num_ports =		1,
+};
+
+static int __init debug_init(void)
+{
+	int retval;
+
+	retval = usb_serial_register(&debug_device);
+	if (retval)
+		return retval;
+	retval = usb_register(&debug_driver);
+	if (retval)
+		usb_serial_deregister(&debug_device);
+	return retval;
+}
+
+static void __exit debug_exit(void)
+{
+	usb_deregister(&debug_driver);
+	usb_serial_deregister(&debug_device);
+}
+
+module_init(debug_init);
+module_exit(debug_exit);
+MODULE_LICENSE("GPL");
diff --git a/drivers/usb/serial/visor.c b/drivers/usb/serial/visor.c
index befe2e11a041..eef5eaa5fa0b 100644
--- a/drivers/usb/serial/visor.c
+++ b/drivers/usb/serial/visor.c
@@ -348,8 +348,7 @@ static void visor_close (struct usb_serial_port *port, struct file * filp)
 			 
 	/* shutdown our urbs */
 	usb_kill_urb(port->read_urb);
-	if (port->interrupt_in_urb)
-		usb_kill_urb(port->interrupt_in_urb);
+	usb_kill_urb(port->interrupt_in_urb);
 
 	/* Try to send shutdown message, if the device is gone, this will just fail. */
 	transfer_buffer =  kmalloc (0x12, GFP_KERNEL);
diff --git a/drivers/usb/storage/onetouch.c b/drivers/usb/storage/onetouch.c
index 3baf448e300d..3a158d58441f 100644
--- a/drivers/usb/storage/onetouch.c
+++ b/drivers/usb/storage/onetouch.c
@@ -142,10 +142,7 @@ int onetouch_connect_input(struct us_data *ss)
 		return -ENODEV;
 
 	endpoint = &interface->endpoint[2].desc;
-	if (!(endpoint->bEndpointAddress & USB_DIR_IN))
-		return -ENODEV;
-	if ((endpoint->bmAttributes & USB_ENDPOINT_XFERTYPE_MASK)
-			!= USB_ENDPOINT_XFER_INT)
+	if (!usb_endpoint_is_int_in(endpoint))
 		return -ENODEV;
 
 	pipe = usb_rcvintpipe(udev, endpoint->bEndpointAddress);
diff --git a/drivers/usb/storage/unusual_devs.h b/drivers/usb/storage/unusual_devs.h
index efb047f431e8..db8b26012c75 100644
--- a/drivers/usb/storage/unusual_devs.h
+++ b/drivers/usb/storage/unusual_devs.h
@@ -1318,6 +1318,16 @@ UNUSUAL_DEV(  0x1019, 0x0c55, 0x0000, 0x0110,
 		US_SC_DEVICE, US_PR_DEVICE, usb_stor_ucr61s2b_init,
 		0 ),
 
+/* Reported by Jaco Kroon <jaco@kroon.co.za>
+ * The usb-storage module found on the Digitech GNX4 (and supposedly other
+ * devices) misbehaves and causes a bunch of invalid I/O errors.
+ */
+UNUSUAL_DEV(  0x1210, 0x0003, 0x0100, 0x0100,
+		"Digitech HMG",
+		"DigiTech Mass Storage",
+		US_SC_DEVICE, US_PR_DEVICE, NULL,
+		US_FL_IGNORE_RESIDUE ),
+
 /* Reported by Vilius Bilinkevicius <vilisas AT xxx DOT lt) */
 UNUSUAL_DEV(  0x132b, 0x000b, 0x0001, 0x0001,
 		"Minolta",
diff --git a/drivers/usb/storage/usb.c b/drivers/usb/storage/usb.c
index b8d6031b0975..b401084b3d22 100644
--- a/drivers/usb/storage/usb.c
+++ b/drivers/usb/storage/usb.c
@@ -740,18 +740,16 @@ static int get_pipes(struct us_data *us)
 		ep = &altsetting->endpoint[i].desc;
 
 		/* Is it a BULK endpoint? */
-		if ((ep->bmAttributes & USB_ENDPOINT_XFERTYPE_MASK)
-				== USB_ENDPOINT_XFER_BULK) {
+		if (usb_endpoint_xfer_bulk(ep)) {
 			/* BULK in or out? */
-			if (ep->bEndpointAddress & USB_DIR_IN)
+			if (usb_endpoint_dir_in(ep))
 				ep_in = ep;
 			else
 				ep_out = ep;
 		}
 
 		/* Is it an interrupt endpoint? */
-		else if ((ep->bmAttributes & USB_ENDPOINT_XFERTYPE_MASK)
-				== USB_ENDPOINT_XFER_INT) {
+		else if (usb_endpoint_xfer_int(ep)) {
 			ep_int = ep;
 		}
 	}