diff -Naur -X ../dontdiff linux-2.6.12-rc2/drivers/net/irda/stir4200.c linux-2.6.12-rc2-usb/drivers/net/irda/stir4200.c
--- linux-2.6.12-rc2/drivers/net/irda/stir4200.c	2005-04-07 00:36:31.000000000 -0700
+++ linux-2.6.12-rc2-usb/drivers/net/irda/stir4200.c	2005-04-09 08:57:12.000000000 -0700
@@ -1128,8 +1128,8 @@
 }
 
 #ifdef CONFIG_PM
-/* Power management suspend, so power off the transmitter/receiver */
-static int stir_suspend(struct usb_interface *intf, u32 state)
+/* USB suspend, so power off the transmitter/receiver */
+static int stir_suspend(struct usb_interface *intf, pm_message_t message)
 {
 	struct stir_cb *stir = usb_get_intfdata(intf);
 
diff -Naur -X ../dontdiff linux-2.6.12-rc2/drivers/usb/core/config.c linux-2.6.12-rc2-usb/drivers/usb/core/config.c
--- linux-2.6.12-rc2/drivers/usb/core/config.c	2005-04-07 00:36:31.000000000 -0700
+++ linux-2.6.12-rc2-usb/drivers/usb/core/config.c	2005-04-09 08:57:13.000000000 -0700
@@ -10,7 +10,8 @@
 #include <linux/slab.h>
 #include <linux/device.h>
 #include <asm/byteorder.h>
-
+#include "usb.h"
+#include "hcd.h"
 
 #define USB_MAXALTSETTING		128	/* Hard limit */
 #define USB_MAXENDPOINTS		30	/* Hard limit */
diff -Naur -X ../dontdiff linux-2.6.12-rc2/drivers/usb/core/devices.c linux-2.6.12-rc2-usb/drivers/usb/core/devices.c
--- linux-2.6.12-rc2/drivers/usb/core/devices.c	2005-04-07 00:36:31.000000000 -0700
+++ linux-2.6.12-rc2-usb/drivers/usb/core/devices.c	2005-04-09 08:57:13.000000000 -0700
@@ -59,6 +59,7 @@
 #include <linux/usbdevice_fs.h>
 #include <asm/uaccess.h>
 
+#include "usb.h"
 #include "hcd.h"
 
 #define MAX_TOPO_LEVEL		6
diff -Naur -X ../dontdiff linux-2.6.12-rc2/drivers/usb/core/devio.c linux-2.6.12-rc2-usb/drivers/usb/core/devio.c
--- linux-2.6.12-rc2/drivers/usb/core/devio.c	2005-04-07 00:35:55.000000000 -0700
+++ linux-2.6.12-rc2-usb/drivers/usb/core/devio.c	2005-04-09 08:57:13.000000000 -0700
@@ -1032,15 +1032,15 @@
 	if (put_user(urb->error_count, &userurb->error_count))
 		return -EFAULT;
 
-	if (!(usb_pipeisoc(urb->pipe)))
-		return 0;
-	for (i = 0; i < urb->number_of_packets; i++) {
-		if (put_user(urb->iso_frame_desc[i].actual_length,
-			     &userurb->iso_frame_desc[i].actual_length))
-			return -EFAULT;
-		if (put_user(urb->iso_frame_desc[i].status,
-			     &userurb->iso_frame_desc[i].status))
-			return -EFAULT;
+	if (usb_pipeisoc(urb->pipe)) {
+		for (i = 0; i < urb->number_of_packets; i++) {
+			if (put_user(urb->iso_frame_desc[i].actual_length,
+				     &userurb->iso_frame_desc[i].actual_length))
+				return -EFAULT;
+			if (put_user(urb->iso_frame_desc[i].status,
+				     &userurb->iso_frame_desc[i].status))
+				return -EFAULT;
+		}
 	}
 
 	free_async(as);
@@ -1126,7 +1126,7 @@
 	if (get_urb32(&uurb,(struct usbdevfs_urb32 *)arg))
 		return -EFAULT;
 
-	return proc_do_submiturb(ps, &uurb, ((struct usbdevfs_urb __user *)arg)->iso_frame_desc, arg);
+	return proc_do_submiturb(ps, &uurb, ((struct usbdevfs_urb32 __user *)arg)->iso_frame_desc, arg);
 }
 
 static int processcompl_compat(struct async *as, void __user * __user *arg)
@@ -1146,15 +1146,15 @@
 	if (put_user(urb->error_count, &userurb->error_count))
 		return -EFAULT;
 
-	if (!(usb_pipeisoc(urb->pipe)))
-		return 0;
-	for (i = 0; i < urb->number_of_packets; i++) {
-		if (put_user(urb->iso_frame_desc[i].actual_length,
-			     &userurb->iso_frame_desc[i].actual_length))
-			return -EFAULT;
-		if (put_user(urb->iso_frame_desc[i].status,
-			     &userurb->iso_frame_desc[i].status))
-			return -EFAULT;
+	if (usb_pipeisoc(urb->pipe)) {
+		for (i = 0; i < urb->number_of_packets; i++) {
+			if (put_user(urb->iso_frame_desc[i].actual_length,
+				     &userurb->iso_frame_desc[i].actual_length))
+				return -EFAULT;
+			if (put_user(urb->iso_frame_desc[i].status,
+				     &userurb->iso_frame_desc[i].status))
+				return -EFAULT;
+		}
 	}
 
 	free_async(as);
@@ -1177,10 +1177,8 @@
 {
 	struct async *as;
 
-	printk("reapurbnblock\n");
 	if (!(as = async_getcompleted(ps)))
 		return -EAGAIN;
-	printk("reap got as %p\n", as);
 	return processcompl_compat(as, (void __user * __user *)arg);
 }
 
diff -Naur -X ../dontdiff linux-2.6.12-rc2/drivers/usb/core/file.c linux-2.6.12-rc2-usb/drivers/usb/core/file.c
--- linux-2.6.12-rc2/drivers/usb/core/file.c	2005-04-07 00:36:34.000000000 -0700
+++ linux-2.6.12-rc2-usb/drivers/usb/core/file.c	2005-04-09 08:57:13.000000000 -0700
@@ -28,6 +28,8 @@
 #endif
 #include <linux/usb.h>
 
+#include "usb.h"
+
 #define MAX_USB_MINORS	256
 static struct file_operations *usb_minors[MAX_USB_MINORS];
 static DEFINE_SPINLOCK(minor_lock);
diff -Naur -X ../dontdiff linux-2.6.12-rc2/drivers/usb/core/hcd-pci.c linux-2.6.12-rc2-usb/drivers/usb/core/hcd-pci.c
--- linux-2.6.12-rc2/drivers/usb/core/hcd-pci.c	2005-04-07 00:36:31.000000000 -0700
+++ linux-2.6.12-rc2-usb/drivers/usb/core/hcd-pci.c	2005-04-09 08:57:12.000000000 -0700
@@ -33,7 +33,7 @@
 #include "hcd.h"
 
 
-/* PCI-based HCs are normal, but custom bus glue should be ok */
+/* PCI-based HCs are common, but plenty of non-PCI HCs are used too */
 
 
 /*-------------------------------------------------------------------------*/
@@ -67,8 +67,8 @@
 
 	if (pci_enable_device (dev) < 0)
 		return -ENODEV;
-	dev->current_state = 0;
-	dev->dev.power.power_state = 0;
+	dev->current_state = PCI_D0;
+	dev->dev.power.power_state = PMSG_ON;
 	
         if (!dev->irq) {
         	dev_err (&dev->dev,
@@ -186,26 +186,14 @@
 
 #ifdef	CONFIG_PM
 
-static char __attribute_used__ *pci_state(u32 state)
-{
-	switch (state) {
-	case 0:		return "D0";
-	case 1:		return "D1";
-	case 2:		return "D2";
-	case 3:		return "D3hot";
-	case 4:		return "D3cold";
-	}
-	return NULL;
-}
-
 /**
  * usb_hcd_pci_suspend - power management suspend of a PCI-based HCD
  * @dev: USB Host Controller being suspended
- * @state: state that the controller is going into
+ * @message: semantics in flux
  *
  * Store this function in the HCD's struct pci_driver as suspend().
  */
-int usb_hcd_pci_suspend (struct pci_dev *dev, u32 state)
+int usb_hcd_pci_suspend (struct pci_dev *dev, pm_message_t message)
 {
 	struct usb_hcd		*hcd;
 	int			retval = 0;
@@ -213,13 +201,23 @@
 
 	hcd = pci_get_drvdata(dev);
 
+	/* FIXME until the generic PM interfaces change a lot more, this
+	 * can't use PCI D1 and D2 states.  For example, the confusion
+	 * between messages and states will need to vanish, and messages
+	 * will need to provide a target system state again.
+	 *
+	 * It'll be important to learn characteristics of the target state,
+	 * especially on embedded hardware where the HCD will often be in
+	 * charge of an external VBUS power supply and one or more clocks.
+	 * Some target system states will leave them active; others won't.
+	 * (With PCI, that's often handled by platform BIOS code.)
+	 */
+
 	/* even when the PCI layer rejects some of the PCI calls
 	 * below, HCs can try global suspend and reduce DMA traffic.
 	 * PM-sensitive HCDs may already have done this.
 	 */
 	has_pci_pm = pci_find_capability(dev, PCI_CAP_ID_PM);
-	if (state > 4)
-		state = 4;
 
 	switch (hcd->state) {
 
@@ -228,7 +226,7 @@
 	 */
 	case HC_STATE_RUNNING:
 		hcd->state = HC_STATE_QUIESCING;
-		retval = hcd->driver->suspend (hcd, state);
+		retval = hcd->driver->suspend (hcd, message);
 		if (retval) {
 			dev_dbg (hcd->self.controller, 
 					"suspend fail, retval %d\n",
@@ -246,14 +244,11 @@
 	 * have been called, otherwise root hub timers still run ...
 	 */
 	case HC_STATE_SUSPENDED:
-		if (state <= dev->current_state)
-			break;
-
-		/* no DMA or IRQs except in D0 */
-		if (!dev->current_state) {
+		/* no DMA or IRQs except when HC is active */
+		if (dev->current_state == PCI_D0) {
+			free_irq (hcd->irq, hcd);
 			pci_save_state (dev);
 			pci_disable_device (dev);
-			free_irq (hcd->irq, hcd);
 		}
 
 		if (!has_pci_pm) {
@@ -261,25 +256,19 @@
 			break;
 		}
 
-		/* POLICY: ignore D1/D2/D3hot differences;
-		 * we know D3hot will always work.
+		/* NOTE:  dev->current_state becomes nonzero only here, and
+		 * only for devices that support PCI PM.  Also, exiting
+		 * PCI_D3 (but not PCI_D1 or PCI_D2) is allowed to reset
+		 * some device state (e.g. as part of clock reinit).
 		 */
-		retval = pci_set_power_state (dev, state);
-		if (retval < 0 && state < 3) {
-			retval = pci_set_power_state (dev, 3);
-			if (retval == 0)
-				state = 3;
-		}
+		retval = pci_set_power_state (dev, PCI_D3hot);
 		if (retval == 0) {
-			dev_dbg (hcd->self.controller, "--> PCI %s\n",
-					pci_state(dev->current_state));
-#ifdef	CONFIG_USB_SUSPEND
-			pci_enable_wake (dev, state, hcd->remote_wakeup);
-			pci_enable_wake (dev, 4, hcd->remote_wakeup);
-#endif
+			dev_dbg (hcd->self.controller, "--> PCI D3\n");
+			pci_enable_wake (dev, PCI_D3hot, hcd->remote_wakeup);
+			pci_enable_wake (dev, PCI_D3cold, hcd->remote_wakeup);
 		} else if (retval < 0) {
-			dev_dbg (&dev->dev, "PCI %s suspend fail, %d\n",
-					pci_state(state), retval);
+			dev_dbg (&dev->dev, "PCI D3 suspend fail, %d\n",
+					retval);
 			(void) usb_hcd_pci_resume (dev);
 			break;
 		}
@@ -287,13 +276,14 @@
 	default:
 		dev_dbg (hcd->self.controller, "hcd state %d; not suspended\n",
 			hcd->state);
+		WARN_ON(1);
 		retval = -EINVAL;
 		break;
 	}
 
 	/* update power_state **ONLY** to make sysfs happier */
 	if (retval == 0)
-		dev->dev.power.power_state = state;
+		dev->dev.power.power_state = message;
 	return retval;
 }
 EXPORT_SYMBOL (usb_hcd_pci_suspend);
@@ -308,7 +298,6 @@
 {
 	struct usb_hcd		*hcd;
 	int			retval;
-	int			has_pci_pm;
 
 	hcd = pci_get_drvdata(dev);
 	if (hcd->state != HC_STATE_SUSPENDED) {
@@ -316,31 +305,73 @@
 				"can't resume, not suspended!\n");
 		return 0;
 	}
-	has_pci_pm = pci_find_capability(dev, PCI_CAP_ID_PM);
 
-	/* D3cold resume isn't usually reported this way... */
-	dev_dbg(hcd->self.controller, "resume from PCI %s%s\n",
-			pci_state(dev->current_state),
-			has_pci_pm ? "" : " (legacy)");
+	/* NOTE:  chip docs cover clean "real suspend" cases (what Linux
+	 * calls "standby", "suspend to RAM", and so on).  There are also
+	 * dirty cases when swsusp fakes a suspend in "shutdown" mode.
+	 */
+	if (dev->current_state != PCI_D0) {
+#ifdef	DEBUG
+		int	pci_pm;
+		u16	pmcr;
+
+		pci_pm = pci_find_capability(dev, PCI_CAP_ID_PM);
+		pci_read_config_word(dev, pci_pm + PCI_PM_CTRL, &pmcr);
+		pmcr &= PCI_PM_CTRL_STATE_MASK;
+		if (pmcr) {
+			/* Clean case:  power to USB and to HC registers was
+			 * maintained; remote wakeup is easy.
+			 */
+			dev_dbg(hcd->self.controller, "resume from PCI D%d\n",
+					pmcr);
+		} else {
+			/* Clean:  HC lost Vcc power, D0 uninitialized
+			 *   + Vaux may have preserved port and transceiver
+			 *     state ... for remote wakeup from D3cold
+			 *   + or not; HCD must reinit + re-enumerate
+			 *
+			 * Dirty: D0 semi-initialized cases with swsusp
+			 *   + after BIOS init
+			 *   + after Linux init (HCD statically linked)
+			 */
+			dev_dbg(hcd->self.controller,
+				"PCI D0, from previous PCI D%d\n",
+				dev->current_state);
+		}
+#endif
+		pci_enable_wake (dev, dev->current_state, 0);
+		pci_enable_wake (dev, PCI_D3cold, 0);
+	} else {
+		/* Same basic cases: clean (powered/not), dirty */
+		dev_dbg(hcd->self.controller, "PCI legacy resume\n");
+	}
+
+	/* NOTE:  the PCI API itself is asymmetric here.  We don't need to
+	 * pci_set_power_state(PCI_D0) since that's part of re-enabling;
+	 * but that won't re-enable bus mastering.  Yet pci_disable_device()
+	 * explicitly disables bus mastering...
+	 */
+	retval = pci_enable_device (dev);
+	if (retval < 0) {
+		dev_err (hcd->self.controller,
+			"can't re-enable after resume, %d!\n", retval);
+		return retval;
+	}
+	pci_set_master (dev);
+	pci_restore_state (dev);
+
+	dev->dev.power.power_state = PMSG_ON;
 
 	hcd->state = HC_STATE_RESUMING;
-
-	if (has_pci_pm)
-		pci_set_power_state (dev, 0);
-	dev->dev.power.power_state = 0;
+	hcd->saw_irq = 0;
 	retval = request_irq (dev->irq, usb_hcd_irq, SA_SHIRQ,
-				hcd->driver->description, hcd);
+				hcd->irq_descr, hcd);
 	if (retval < 0) {
 		dev_err (hcd->self.controller,
 			"can't restore IRQ after resume!\n");
+		usb_hc_died (hcd);
 		return retval;
 	}
-	hcd->saw_irq = 0;
-	pci_restore_state (dev);
-#ifdef	CONFIG_USB_SUSPEND
-	pci_enable_wake (dev, dev->current_state, 0);
-	pci_enable_wake (dev, 4, 0);
-#endif
 
 	retval = hcd->driver->resume (hcd);
 	if (!HC_IS_RUNNING (hcd->state)) {
diff -Naur -X ../dontdiff linux-2.6.12-rc2/drivers/usb/core/hcd.h linux-2.6.12-rc2-usb/drivers/usb/core/hcd.h
--- linux-2.6.12-rc2/drivers/usb/core/hcd.h	2005-04-07 00:36:31.000000000 -0700
+++ linux-2.6.12-rc2-usb/drivers/usb/core/hcd.h	2005-04-09 08:57:12.000000000 -0700
@@ -177,7 +177,7 @@
 	 * a whole, not just the root hub; they're for bus glue.
 	 */
 	/* called after all devices were suspended */
-	int	(*suspend) (struct usb_hcd *hcd, u32 state);
+	int	(*suspend) (struct usb_hcd *hcd, pm_message_t message);
 
 	/* called before any devices get resumed */
 	int	(*resume) (struct usb_hcd *hcd);
@@ -226,7 +226,7 @@
 extern void usb_hcd_pci_remove (struct pci_dev *dev);
 
 #ifdef CONFIG_PM
-extern int usb_hcd_pci_suspend (struct pci_dev *dev, u32 state);
+extern int usb_hcd_pci_suspend (struct pci_dev *dev, pm_message_t state);
 extern int usb_hcd_pci_resume (struct pci_dev *dev);
 #endif /* CONFIG_PM */
 
diff -Naur -X ../dontdiff linux-2.6.12-rc2/drivers/usb/core/hub.c linux-2.6.12-rc2-usb/drivers/usb/core/hub.c
--- linux-2.6.12-rc2/drivers/usb/core/hub.c	2005-04-07 00:36:31.000000000 -0700
+++ linux-2.6.12-rc2-usb/drivers/usb/core/hub.c	2005-04-09 08:57:12.000000000 -0700
@@ -1731,7 +1731,7 @@
 			struct usb_driver	*driver;
 
 			intf = udev->actconfig->interface[i];
-			if (intf->dev.power.power_state == PM_SUSPEND_ON)
+			if (intf->dev.power.power_state == PMSG_SUSPEND)
 				continue;
 			if (!intf->dev.driver) {
 				/* FIXME maybe force to alt 0 */
@@ -1745,7 +1745,7 @@
 
 			/* can we do better than just logging errors? */
 			status = driver->resume(intf);
-			if (intf->dev.power.power_state != PM_SUSPEND_ON
+			if (intf->dev.power.power_state != PMSG_ON
 					|| status)
 				dev_dbg(&intf->dev,
 					"resume fail, state %d code %d\n",
diff -Naur -X ../dontdiff linux-2.6.12-rc2/drivers/usb/core/inode.c linux-2.6.12-rc2-usb/drivers/usb/core/inode.c
--- linux-2.6.12-rc2/drivers/usb/core/inode.c	2005-04-07 00:36:31.000000000 -0700
+++ linux-2.6.12-rc2-usb/drivers/usb/core/inode.c	2005-04-09 08:57:13.000000000 -0700
@@ -41,6 +41,7 @@
 #include <linux/parser.h>
 #include <asm/byteorder.h>
 #include "usb.h"
+#include "hcd.h"
 
 static struct super_operations usbfs_ops;
 static struct file_operations default_file_operations;
diff -Naur -X ../dontdiff linux-2.6.12-rc2/drivers/usb/core/message.c linux-2.6.12-rc2-usb/drivers/usb/core/message.c
--- linux-2.6.12-rc2/drivers/usb/core/message.c	2005-04-07 00:35:55.000000000 -0700
+++ linux-2.6.12-rc2-usb/drivers/usb/core/message.c	2005-04-09 08:57:13.000000000 -0700
@@ -1133,29 +1133,10 @@
 	/* prevent submissions using previous endpoint settings */
 	usb_disable_interface(dev, iface);
 
-	/* 9.1.1.5 says:
-	 *
-	 *	Configuring a device or changing an alternate setting
-	 *	causes all of the status and configuration values
-	 *	associated with endpoints in the affected interfaces to
-	 *	be set to their default values. This includes setting
-	 *	the data toggle of any endpoint using data toggles to
-	 *	the value DATA0.
-	 *
-	 * Some devices take this too literally and don't reset the data
-	 * toggles if the new altsetting is the same as the old one (the
-	 * command isn't "changing" an alternate setting).  We will manually
-	 * reset the toggles when the new and old altsettings are the same.
-	 * Most devices won't need this, but fortunately it doesn't happen
-	 * often.
-	 */
-	if (iface->cur_altsetting == alt)
-		manual = 1;
 	iface->cur_altsetting = alt;
 
 	/* If the interface only has one altsetting and the device didn't
-	 * accept the request (or whenever the old altsetting is the same
-	 * as the new one), we attempt to carry out the equivalent action
+	 * accept the request, we attempt to carry out the equivalent action
 	 * by manually clearing the HALT feature for each endpoint in the
 	 * new altsetting.
 	 */
@@ -1202,7 +1183,9 @@
  *
  * Because this affects multiple interfaces, avoid using this with composite
  * (multi-interface) devices.  Instead, the driver for each interface may
- * use usb_set_interface() on the interfaces it claims.  Resetting the whole
+ * use usb_set_interface() on the interfaces it claims.  Be careful though;
+ * some devices don't support the SET_INTERFACE request, and others won't
+ * reset all the interface state (notably data toggles).  Resetting the whole
  * configuration would affect other drivers' interfaces.
  *
  * The caller must own the device lock.
diff -Naur -X ../dontdiff linux-2.6.12-rc2/drivers/usb/core/urb.c linux-2.6.12-rc2-usb/drivers/usb/core/urb.c
--- linux-2.6.12-rc2/drivers/usb/core/urb.c	2005-03-01 23:38:10.000000000 -0800
+++ linux-2.6.12-rc2-usb/drivers/usb/core/urb.c	2005-04-09 08:57:14.000000000 -0700
@@ -420,12 +420,16 @@
  *
  * Host Controller Drivers (HCDs) place all the URBs for a particular
  * endpoint in a queue.  Normally the queue advances as the controller
- * hardware processes each request.  But when an URB terminates with any
- * fault (such as an error, or being unlinked) its queue stops, at least
- * until that URB's completion routine returns.  It is guaranteed that
- * the queue will not restart until all its unlinked URBs have been fully
- * retired, with their completion routines run, even if that's not until
- * some time after the original completion handler returns.
+ * hardware processes each request.  But when an URB terminates with an
+ * error its queue stops, at least until that URB's completion routine
+ * returns.  It is guaranteed that the queue will not restart until all
+ * its unlinked URBs have been fully retired, with their completion
+ * routines run, even if that's not until some time after the original
+ * completion handler returns.  Normally the same behavior and guarantees
+ * apply when an URB terminates because it was unlinked; however if an
+ * URB is unlinked before the hardware has started to execute it, then
+ * its queue is not guaranteed to stop until all the preceding URBs have
+ * completed.
  *
  * This means that USB device drivers can safely build deep queues for
  * large or complex transfers, and clean them up reliably after any sort
diff -Naur -X ../dontdiff linux-2.6.12-rc2/drivers/usb/core/usb.c linux-2.6.12-rc2-usb/drivers/usb/core/usb.c
--- linux-2.6.12-rc2/drivers/usb/core/usb.c	2005-04-07 00:36:33.000000000 -0700
+++ linux-2.6.12-rc2-usb/drivers/usb/core/usb.c	2005-04-09 08:57:13.000000000 -0700
@@ -50,13 +50,6 @@
 #include "hcd.h"
 #include "usb.h"
 
-extern int  usb_hub_init(void);
-extern void usb_hub_cleanup(void);
-extern int usb_major_init(void);
-extern void usb_major_cleanup(void);
-extern int usb_host_init(void);
-extern void usb_host_cleanup(void);
-
 
 const char *usbcore_name = "usbcore";
 
@@ -1382,13 +1375,13 @@
 			usb_pipein (pipe) ? DMA_FROM_DEVICE : DMA_TO_DEVICE);
 }
 
-static int usb_generic_suspend(struct device *dev, u32 state)
+static int usb_generic_suspend(struct device *dev, pm_message_t message)
 {
 	struct usb_interface *intf;
 	struct usb_driver *driver;
 
 	if (dev->driver == &usb_generic_driver)
-		return usb_suspend_device (to_usb_device(dev), state);
+		return usb_suspend_device (to_usb_device(dev), message);
 
 	if ((dev->driver == NULL) ||
 	    (dev->driver_data == &usb_generic_driver_data))
@@ -1402,7 +1395,7 @@
 		return 0;
 
 	if (driver->suspend)
-		return driver->suspend(intf, state);
+		return driver->suspend(intf, message);
 	return 0;
 }
 
diff -Naur -X ../dontdiff linux-2.6.12-rc2/drivers/usb/core/usb.h linux-2.6.12-rc2-usb/drivers/usb/core/usb.h
--- linux-2.6.12-rc2/drivers/usb/core/usb.h	2005-04-07 00:36:31.000000000 -0700
+++ linux-2.6.12-rc2-usb/drivers/usb/core/usb.h	2005-04-09 08:57:13.000000000 -0700
@@ -21,6 +21,13 @@
 extern void usb_kick_khubd(struct usb_device *dev);
 extern void usb_resume_root_hub(struct usb_device *dev);
 
+extern int  usb_hub_init(void);
+extern void usb_hub_cleanup(void);
+extern int usb_major_init(void);
+extern void usb_major_cleanup(void);
+extern int usb_host_init(void);
+extern void usb_host_cleanup(void);
+
 /* for labeling diagnostics */
 extern const char *usbcore_name;
 
@@ -30,6 +37,7 @@
 extern struct file_operations usbfs_device_file_operations;
 extern void usbfs_conn_disc_event(void);
 
+
 struct dev_state {
 	struct list_head list;      /* state list */
 	struct usb_device *dev;
diff -Naur -X ../dontdiff linux-2.6.12-rc2/drivers/usb/gadget/ether.c linux-2.6.12-rc2-usb/drivers/usb/gadget/ether.c
--- linux-2.6.12-rc2/drivers/usb/gadget/ether.c	2005-04-07 00:35:55.000000000 -0700
+++ linux-2.6.12-rc2-usb/drivers/usb/gadget/ether.c	2005-04-09 08:57:14.000000000 -0700
@@ -100,6 +100,8 @@
 
 /* CDC and RNDIS support the same host-chosen outgoing packet filters. */
 #define	DEFAULT_FILTER	(USB_CDC_PACKET_TYPE_BROADCAST \
+ 			|USB_CDC_PACKET_TYPE_ALL_MULTICAST \
+ 			|USB_CDC_PACKET_TYPE_PROMISCUOUS \
  			|USB_CDC_PACKET_TYPE_DIRECTED)
 
 
@@ -322,12 +324,18 @@
 /* also defer IRQs on highspeed TX */
 #define TX_DELAY	qmult
 
-#define	BITRATE(g)	(((g)->speed == USB_SPEED_HIGH) ? HS_BPS : FS_BPS)
+static inline int BITRATE(struct usb_gadget *g)
+{
+	return (g->speed == USB_SPEED_HIGH) ? HS_BPS : FS_BPS;
+}
 
 #else	/* full speed (low speed doesn't do bulk) */
 #define qlen(gadget) DEFAULT_QLEN
 
-#define	BITRATE(g)	FS_BPS
+static inline int BITRATE(struct usb_gadget *g)
+{
+	return FS_BPS;
+}
 #endif
 
 
@@ -1167,7 +1175,7 @@
 	eth_reset_config (dev);
 
 	/* default:  pass all packets, no multicast filtering */
-	dev->cdc_filter = 0x000f;
+	dev->cdc_filter = DEFAULT_FILTER;
 
 	switch (number) {
 	case DEV_CONFIG_VALUE:
@@ -1343,9 +1351,9 @@
 	struct eth_dev		*dev = get_gadget_data (gadget);
 	struct usb_request	*req = dev->req;
 	int			value = -EOPNOTSUPP;
-	u16			wIndex = ctrl->wIndex;
-	u16			wValue = ctrl->wValue;
-	u16			wLength = ctrl->wLength;
+	u16			wIndex = (__force u16) ctrl->wIndex;
+	u16			wValue = (__force u16) ctrl->wValue;
+	u16			wLength = (__force u16) ctrl->wLength;
 
 	/* descriptors just go into the pre-allocated ep0 buffer,
 	 * while config change events may enable network traffic.
@@ -1693,7 +1701,7 @@
 	
 	/* Some platforms perform better when IP packets are aligned,
 	 * but on at least one, checksumming fails otherwise.  Note:
-	 * this doesn't account for variable-sized RNDIS headers.
+	 * RNDIS headers involve variable numbers of LE32 values.
 	 */
 	skb_reserve(skb, NET_IP_ALIGN);
 
@@ -1730,9 +1738,11 @@
 #ifdef CONFIG_USB_ETH_RNDIS
 		/* we know MaxPacketsPerTransfer == 1 here */
 		if (dev->rndis)
-			rndis_rm_hdr (req->buf, &(skb->len));
+			status = rndis_rm_hdr (skb);
 #endif
-		if (ETH_HLEN > skb->len || skb->len > ETH_FRAME_LEN) {
+		if (status < 0
+				|| ETH_HLEN > skb->len
+				|| skb->len > ETH_FRAME_LEN) {
 			dev->stats.rx_errors++;
 			dev->stats.rx_length_errors++;
 			DEBUG (dev, "rx length %d\n", skb->len);
@@ -2047,38 +2057,20 @@
 		DEBUG ((struct eth_dev *) ep->driver_data,
 			"rndis control ack complete --> %d, %d/%d\n",
 			req->status, req->actual, req->length);
-
-	usb_ep_free_buffer(ep, req->buf, req->dma, 8);
-	usb_ep_free_request(ep, req);
 }
 
 static int rndis_control_ack (struct net_device *net)
 {
 	struct eth_dev          *dev = netdev_priv(net);
 	u32                     length;
-	struct usb_request      *resp;
+	struct usb_request      *resp = dev->stat_req;
 	
 	/* in case RNDIS calls this after disconnect */
-	if (!dev->status_ep) {
+	if (!dev->status) {
 		DEBUG (dev, "status ENODEV\n");
 		return -ENODEV;
 	}
 
-	/* Allocate memory for notification ie. ACK */
-	resp = usb_ep_alloc_request (dev->status_ep, GFP_ATOMIC);
-	if (!resp) {
-		DEBUG (dev, "status ENOMEM\n");
-		return -ENOMEM;
-	}
-	
-	resp->buf = usb_ep_alloc_buffer (dev->status_ep, 8,
-					 &resp->dma, GFP_ATOMIC);
-	if (!resp->buf) {
-		DEBUG (dev, "status buf ENOMEM\n");
-		usb_ep_free_request (dev->status_ep, resp);
-		return -ENOMEM;
-	}
-	
 	/* Send RNDIS RESPONSE_AVAILABLE notification;
 	 * USB_CDC_NOTIFY_RESPONSE_AVAILABLE should work too
 	 */
@@ -2113,7 +2105,7 @@
 	if (dev->rndis) {
 		rndis_set_param_medium (dev->rndis_config,
 					NDIS_MEDIUM_802_3,
-					BITRATE(dev->gadget));
+					BITRATE(dev->gadget)/100);
 		rndis_send_media_state (dev, 1);
 	}
 #endif	
@@ -2307,8 +2299,8 @@
 		device_desc.bcdDevice = __constant_cpu_to_le16 (0x0210);
 	} else if (gadget_is_pxa27x(gadget)) {
 		device_desc.bcdDevice = __constant_cpu_to_le16 (0x0211);
- 	} else if (gadget_is_s3c2410(gadget)) {
- 		device_desc.bcdDevice = __constant_cpu_to_le16 (0x0212);
+	} else if (gadget_is_s3c2410(gadget)) {
+		device_desc.bcdDevice = __constant_cpu_to_le16 (0x0212);
 	} else if (gadget_is_at91(gadget)) {
 		device_desc.bcdDevice = __constant_cpu_to_le16 (0x0213);
 	} else {
diff -Naur -X ../dontdiff linux-2.6.12-rc2/drivers/usb/gadget/file_storage.c linux-2.6.12-rc2-usb/drivers/usb/gadget/file_storage.c
--- linux-2.6.12-rc2/drivers/usb/gadget/file_storage.c	2005-04-07 00:35:55.000000000 -0700
+++ linux-2.6.12-rc2-usb/drivers/usb/gadget/file_storage.c	2005-04-09 08:57:13.000000000 -0700
@@ -1312,7 +1312,7 @@
 			}
 			VDBG(fsg, "get max LUN\n");
 			*(u8 *) req->buf = fsg->nluns - 1;
-			value = min(w_length, (u16) 1);
+			value = 1;
 			break;
 		}
 	}
@@ -1360,7 +1360,6 @@
 	int			value = -EOPNOTSUPP;
 	u16			w_index = ctrl->wIndex;
 	u16			w_value = ctrl->wValue;
-	u16			w_length = ctrl->wLength;
 
 	/* Usually this just stores reply data in the pre-allocated ep0 buffer,
 	 * but config change events will also reconfigure hardware. */
@@ -1374,7 +1373,7 @@
 
 		case USB_DT_DEVICE:
 			VDBG(fsg, "get device descriptor\n");
-			value = min(w_length, (u16) sizeof device_desc);
+			value = sizeof device_desc;
 			memcpy(req->buf, &device_desc, value);
 			break;
 #ifdef CONFIG_USB_GADGET_DUALSPEED
@@ -1382,7 +1381,7 @@
 			VDBG(fsg, "get device qualifier\n");
 			if (!fsg->gadget->is_dualspeed)
 				break;
-			value = min(w_length, (u16) sizeof dev_qualifier);
+			value = sizeof dev_qualifier;
 			memcpy(req->buf, &dev_qualifier, value);
 			break;
 
@@ -1401,8 +1400,6 @@
 					req->buf,
 					w_value >> 8,
 					w_value & 0xff);
-			if (value >= 0)
-				value = min(w_length, (u16) value);
 			break;
 
 		case USB_DT_STRING:
@@ -1411,8 +1408,6 @@
 			/* wIndex == language code */
 			value = usb_gadget_get_string(&stringtab,
 					w_value & 0xff, req->buf);
-			if (value >= 0)
-				value = min(w_length, (u16) value);
 			break;
 		}
 		break;
@@ -1438,7 +1433,7 @@
 			break;
 		VDBG(fsg, "get configuration\n");
 		*(u8 *) req->buf = fsg->config;
-		value = min(w_length, (u16) 1);
+		value = 1;
 		break;
 
 	case USB_REQ_SET_INTERFACE:
@@ -1466,14 +1461,14 @@
 		}
 		VDBG(fsg, "get interface\n");
 		*(u8 *) req->buf = 0;
-		value = min(w_length, (u16) 1);
+		value = 1;
 		break;
 
 	default:
 		VDBG(fsg,
 			"unknown control req %02x.%02x v%04x i%04x l%u\n",
 			ctrl->bRequestType, ctrl->bRequest,
-			w_value, w_index, w_length);
+			w_value, w_index, ctrl->wLength);
 	}
 
 	return value;
@@ -1485,6 +1480,7 @@
 {
 	struct fsg_dev		*fsg = get_gadget_data(gadget);
 	int			rc;
+	int			w_length = ctrl->wLength;
 
 	++fsg->ep0_req_tag;		// Record arrival of a new request
 	fsg->ep0req->context = NULL;
@@ -1498,8 +1494,9 @@
 
 	/* Respond with data/status or defer until later? */
 	if (rc >= 0 && rc != DELAYED_STATUS) {
+		rc = min(rc, w_length);
 		fsg->ep0req->length = rc;
-		fsg->ep0req->zero = (rc < ctrl->wLength &&
+		fsg->ep0req->zero = (rc < w_length &&
 				(rc % gadget->ep0->maxpacket) == 0);
 		fsg->ep0req_name = (ctrl->bRequestType & USB_DIR_IN ?
 				"ep0-in" : "ep0-out");
diff -Naur -X ../dontdiff linux-2.6.12-rc2/drivers/usb/gadget/rndis.c linux-2.6.12-rc2-usb/drivers/usb/gadget/rndis.c
--- linux-2.6.12-rc2/drivers/usb/gadget/rndis.c	2005-04-07 00:35:55.000000000 -0700
+++ linux-2.6.12-rc2-usb/drivers/usb/gadget/rndis.c	2005-04-09 08:57:14.000000000 -0700
@@ -37,6 +37,7 @@
 #include <asm/io.h>
 #include <asm/byteorder.h>
 #include <asm/system.h>
+#include <asm/unaligned.h>
 
 
 #undef	RNDIS_PM
@@ -165,7 +166,7 @@
 		
 	/* mandatory */
 	case OID_GEN_LINK_SPEED:
-		DEBUG("%s: OID_GEN_LINK_SPEED\n", __FUNCTION__);
+//		DEBUG("%s: OID_GEN_LINK_SPEED\n", __FUNCTION__);
 		length = 4;
 		if (rndis_per_dev_params [configNr].media_state
 			== NDIS_MEDIA_STATE_DISCONNECTED)
@@ -729,7 +730,7 @@
 		retval = 0;
 
 		/* FIXME use these NDIS_PACKET_TYPE_* bitflags to
-		 * filter packets in hard_start_xmit()
+		 * set the cdc_filter; it's not RNDIS-specific
 		 * NDIS_PACKET_TYPE_x == USB_CDC_PACKET_TYPE_x for x in:
 		 *	PROMISCUOUS, DIRECTED,
 		 *	MULTICAST, ALL_MULTICAST, BROADCAST
@@ -1194,10 +1195,10 @@
 		return;
 	header = (void *) skb_push (skb, sizeof *header);
 	memset (header, 0, sizeof *header);
-	header->MessageType = __constant_cpu_to_le32 (1);
+	header->MessageType = __constant_cpu_to_le32(REMOTE_NDIS_PACKET_MSG);
 	header->MessageLength = cpu_to_le32(skb->len);
 	header->DataOffset = __constant_cpu_to_le32 (36);
-	header->OOBDataOffset = cpu_to_le32(skb->len - 44);
+	header->DataLength = cpu_to_le32(skb->len - sizeof *header);
 }
 
 void rndis_free_response (int configNr, u8 *buf)
@@ -1253,26 +1254,23 @@
 	return r;
 }
 
-int rndis_rm_hdr (u8 *buf, u32 *length)
+int rndis_rm_hdr(struct sk_buff *skb)
 {
-	u32 i, messageLen, dataOffset;
-	__le32 *tmp;
-	
-	tmp = (__le32 *) buf; 
+	/* tmp points to a struct rndis_packet_msg_type */
+	__le32		*tmp = (void *) skb->data;
 
-	if (!buf || !length) return -1;
-	if (le32_to_cpup(tmp++) != 1) return -1;
-	
-	messageLen = le32_to_cpup(tmp++);
-	dataOffset = le32_to_cpup(tmp++) + 8;
+	/* MessageType, MessageLength */
+	if (__constant_cpu_to_le32(REMOTE_NDIS_PACKET_MSG)
+			!= get_unaligned(tmp++))
+		return -EINVAL;
+	tmp++;
+
+	/* DataOffset, DataLength */
+	if (!skb_pull(skb, le32_to_cpu(get_unaligned(tmp++))
+			+ 8 /* offset of DataOffset */))
+		return -EOVERFLOW;
+	skb_trim(skb, le32_to_cpu(get_unaligned(tmp++)));
 
-	if (messageLen < dataOffset || messageLen > *length) return -1;
-	
-	for (i = dataOffset; i < messageLen; i++)
-		buf [i - dataOffset] = buf [i];
-		
-	*length = messageLen - dataOffset;
-	
 	return 0;
 }
 
diff -Naur -X ../dontdiff linux-2.6.12-rc2/drivers/usb/gadget/rndis.h linux-2.6.12-rc2-usb/drivers/usb/gadget/rndis.h
--- linux-2.6.12-rc2/drivers/usb/gadget/rndis.h	2005-04-07 00:35:55.000000000 -0700
+++ linux-2.6.12-rc2-usb/drivers/usb/gadget/rndis.h	2005-04-09 08:57:14.000000000 -0700
@@ -38,6 +38,7 @@
  */
 
 /* Message Set for Connectionless (802.3) Devices */
+#define REMOTE_NDIS_PACKET_MSG		0x00000001U
 #define REMOTE_NDIS_INITIALIZE_MSG	0x00000002U	/* Initialize device */
 #define REMOTE_NDIS_HALT_MSG		0x00000003U
 #define REMOTE_NDIS_QUERY_MSG		0x00000004U
@@ -333,7 +334,7 @@
 			    const char *vendorDescr);
 int  rndis_set_param_medium (u8 configNr, u32 medium, u32 speed);
 void rndis_add_hdr (struct sk_buff *skb);
-int  rndis_rm_hdr (u8 *buf, u32 *length);
+int rndis_rm_hdr (struct sk_buff *skb);
 u8   *rndis_get_next_response (int configNr, u32 *length);
 void rndis_free_response (int configNr, u8 *buf);
 
diff -Naur -X ../dontdiff linux-2.6.12-rc2/drivers/usb/host/ehci-dbg.c linux-2.6.12-rc2-usb/drivers/usb/host/ehci-dbg.c
--- linux-2.6.12-rc2/drivers/usb/host/ehci-dbg.c	2005-04-07 00:36:34.000000000 -0700
+++ linux-2.6.12-rc2-usb/drivers/usb/host/ehci-dbg.c	2005-04-09 08:57:13.000000000 -0700
@@ -394,7 +394,7 @@
 		mark = ' ';
 		if (hw_curr == td->qtd_dma)
 			mark = '*';
-		else if (qh->hw_qtd_next == td->qtd_dma)
+		else if (qh->hw_qtd_next == cpu_to_le32(td->qtd_dma))
 			mark = '+';
 		else if (QTD_LENGTH (scratch)) {
 			if (td->hw_alt_next == ehci->async->hw_alt_next)
diff -Naur -X ../dontdiff linux-2.6.12-rc2/drivers/usb/host/ehci-hcd.c linux-2.6.12-rc2-usb/drivers/usb/host/ehci-hcd.c
--- linux-2.6.12-rc2/drivers/usb/host/ehci-hcd.c	2005-04-07 00:36:31.000000000 -0700
+++ linux-2.6.12-rc2-usb/drivers/usb/host/ehci-hcd.c	2005-04-09 08:57:13.000000000 -0700
@@ -721,7 +721,7 @@
  * the right sort of wakeup.  
  */
 
-static int ehci_suspend (struct usb_hcd *hcd, u32 state)
+static int ehci_suspend (struct usb_hcd *hcd, pm_message_t message)
 {
 	struct ehci_hcd		*ehci = hcd_to_ehci (hcd);
 
@@ -729,7 +729,7 @@
 		msleep (100);
 
 #ifdef	CONFIG_USB_SUSPEND
-	(void) usb_suspend_device (hcd->self.root_hub, state);
+	(void) usb_suspend_device (hcd->self.root_hub, message);
 #else
 	usb_lock_device (hcd->self.root_hub);
 	(void) ehci_hub_suspend (hcd);
diff -Naur -X ../dontdiff linux-2.6.12-rc2/drivers/usb/host/ehci-sched.c linux-2.6.12-rc2-usb/drivers/usb/host/ehci-sched.c
--- linux-2.6.12-rc2/drivers/usb/host/ehci-sched.c	2005-04-07 00:36:31.000000000 -0700
+++ linux-2.6.12-rc2-usb/drivers/usb/host/ehci-sched.c	2005-04-09 08:57:13.000000000 -0700
@@ -310,9 +310,9 @@
 
 	for (i = qh->start; i < ehci->periodic_size; i += period) {
 		union ehci_shadow	*prev = &ehci->pshadow [i];
-		u32			*hw_p = &ehci->periodic [i];
+		__le32			*hw_p = &ehci->periodic [i];
 		union ehci_shadow	here = *prev;
-		u32			type = 0;
+		__le32			type = 0;
 
 		/* skip the iso nodes at list head */
 		while (here.ptr) {
diff -Naur -X ../dontdiff linux-2.6.12-rc2/drivers/usb/host/ehci.h linux-2.6.12-rc2-usb/drivers/usb/host/ehci.h
--- linux-2.6.12-rc2/drivers/usb/host/ehci.h	2005-04-07 00:36:31.000000000 -0700
+++ linux-2.6.12-rc2-usb/drivers/usb/host/ehci.h	2005-04-09 08:57:13.000000000 -0700
@@ -364,7 +364,7 @@
 	struct ehci_itd		*itd;		/* Q_TYPE_ITD */
 	struct ehci_sitd	*sitd;		/* Q_TYPE_SITD */
 	struct ehci_fstn	*fstn;		/* Q_TYPE_FSTN */
-	u32			*hw_next;	/* (all types) */
+	__le32			*hw_next;	/* (all types) */
 	void			*ptr;
 };
 
diff -Naur -X ../dontdiff linux-2.6.12-rc2/drivers/usb/host/ohci-pci.c linux-2.6.12-rc2-usb/drivers/usb/host/ohci-pci.c
--- linux-2.6.12-rc2/drivers/usb/host/ohci-pci.c	2005-04-07 00:36:31.000000000 -0700
+++ linux-2.6.12-rc2-usb/drivers/usb/host/ohci-pci.c	2005-04-09 08:57:13.000000000 -0700
@@ -54,7 +54,7 @@
 		if (pdev->vendor == PCI_VENDOR_ID_AMD
 				&& pdev->device == 0x740c) {
 			ohci->flags = OHCI_QUIRK_AMD756;
-			ohci_info (ohci, "AMD756 erratum 4 workaround\n");
+			ohci_dbg (ohci, "AMD756 erratum 4 workaround\n");
 			// also somewhat erratum 10 (suspend/resume issues)
 		}
 
@@ -68,7 +68,7 @@
 		 */
 		else if (pdev->vendor == PCI_VENDOR_ID_OPTI
 				&& pdev->device == 0xc861) {
-			ohci_info (ohci,
+			ohci_dbg (ohci,
 				"WARNING: OPTi workarounds unavailable\n");
 		}
 
@@ -84,9 +84,20 @@
 			if (b && b->device == PCI_DEVICE_ID_NS_87560_LIO
 					&& b->vendor == PCI_VENDOR_ID_NS) {
 				ohci->flags |= OHCI_QUIRK_SUPERIO;
-				ohci_info (ohci, "Using NSC SuperIO setup\n");
+				ohci_dbg (ohci, "Using NSC SuperIO setup\n");
 			}
 		}
+
+		/* Check for Compaq's ZFMicro chipset, which needs short 
+		 * delays before control or bulk queues get re-activated
+		 * in finish_unlinks()
+		 */
+		else if (pdev->vendor == PCI_VENDOR_ID_COMPAQ
+				&& pdev->device  == 0xa0f8) {
+			ohci->flags |= OHCI_QUIRK_ZFMICRO;
+			ohci_dbg (ohci,
+				"enabled Compaq ZFMicro chipset quirk\n");
+		}
 	}
 
 	/* NOTE: there may have already been a first reset, to
@@ -102,7 +113,7 @@
 
 #ifdef	CONFIG_PM
 
-static int ohci_pci_suspend (struct usb_hcd *hcd, u32 state)
+static int ohci_pci_suspend (struct usb_hcd *hcd, pm_message_t message)
 {
 	struct ohci_hcd		*ohci = hcd_to_ohci (hcd);
 
@@ -111,7 +122,7 @@
 		msleep (100);
 
 #ifdef	CONFIG_USB_SUSPEND
-	(void) usb_suspend_device (hcd->self.root_hub, state);
+	(void) usb_suspend_device (hcd->self.root_hub, message);
 #else
 	usb_lock_device (hcd->self.root_hub);
 	(void) ohci_hub_suspend (hcd);
diff -Naur -X ../dontdiff linux-2.6.12-rc2/drivers/usb/host/ohci-q.c linux-2.6.12-rc2-usb/drivers/usb/host/ohci-q.c
--- linux-2.6.12-rc2/drivers/usb/host/ohci-q.c	2005-04-07 00:35:55.000000000 -0700
+++ linux-2.6.12-rc2-usb/drivers/usb/host/ohci-q.c	2005-04-09 08:57:13.000000000 -0700
@@ -1021,6 +1021,8 @@
 
 		if (ohci->ed_controltail) {
 			command |= OHCI_CLF;
+			if (ohci->flags & OHCI_QUIRK_ZFMICRO)
+				mdelay(1);
 			if (!(ohci->hc_control & OHCI_CTRL_CLE)) {
 				control |= OHCI_CTRL_CLE;
 				ohci_writel (ohci, 0,
@@ -1029,6 +1031,8 @@
 		}
 		if (ohci->ed_bulktail) {
 			command |= OHCI_BLF;
+			if (ohci->flags & OHCI_QUIRK_ZFMICRO)
+				mdelay(1);
 			if (!(ohci->hc_control & OHCI_CTRL_BLE)) {
 				control |= OHCI_CTRL_BLE;
 				ohci_writel (ohci, 0,
@@ -1039,12 +1043,17 @@
 		/* CLE/BLE to enable, CLF/BLF to (maybe) kickstart */
 		if (control) {
 			ohci->hc_control |= control;
+			if (ohci->flags & OHCI_QUIRK_ZFMICRO)
+				mdelay(1);
  			ohci_writel (ohci, ohci->hc_control,
 					&ohci->regs->control);   
  		}
-		if (command)
+		if (command) {
+			if (ohci->flags & OHCI_QUIRK_ZFMICRO)
+				mdelay(1);
 			ohci_writel (ohci, command, &ohci->regs->cmdstatus);   
- 	}
+	 	}
+	}
 }
 
 
diff -Naur -X ../dontdiff linux-2.6.12-rc2/drivers/usb/host/ohci.h linux-2.6.12-rc2-usb/drivers/usb/host/ohci.h
--- linux-2.6.12-rc2/drivers/usb/host/ohci.h	2005-04-07 00:35:55.000000000 -0700
+++ linux-2.6.12-rc2-usb/drivers/usb/host/ohci.h	2005-04-09 08:57:13.000000000 -0700
@@ -396,6 +396,7 @@
 #define	OHCI_QUIRK_SUPERIO	0x02			/* natsemi */
 #define	OHCI_QUIRK_INITRESET	0x04			/* SiS, OPTi, ... */
 #define	OHCI_BIG_ENDIAN		0x08			/* big endian HC */
+#define	OHCI_QUIRK_ZFMICRO	0x10			/* Compaq ZFMicro chipset*/
 	// there are also chip quirks/bugs in init logic
 
 };
diff -Naur -X ../dontdiff linux-2.6.12-rc2/drivers/usb/host/uhci-hcd.c linux-2.6.12-rc2-usb/drivers/usb/host/uhci-hcd.c
--- linux-2.6.12-rc2/drivers/usb/host/uhci-hcd.c	2005-04-07 00:36:31.000000000 -0700
+++ linux-2.6.12-rc2-usb/drivers/usb/host/uhci-hcd.c	2005-04-09 08:57:13.000000000 -0700
@@ -716,7 +716,7 @@
 }
 
 #ifdef CONFIG_PM
-static int uhci_suspend(struct usb_hcd *hcd, u32 state)
+static int uhci_suspend(struct usb_hcd *hcd, pm_message_t message)
 {
 	struct uhci_hcd *uhci = hcd_to_uhci(hcd);
 
diff -Naur -X ../dontdiff linux-2.6.12-rc2/drivers/usb/input/hid-core.c linux-2.6.12-rc2-usb/drivers/usb/input/hid-core.c
--- linux-2.6.12-rc2/drivers/usb/input/hid-core.c	2005-04-07 00:36:31.000000000 -0700
+++ linux-2.6.12-rc2-usb/drivers/usb/input/hid-core.c	2005-04-09 08:57:12.000000000 -0700
@@ -1790,12 +1790,12 @@
 	return 0;
 }
 
-static int hid_suspend(struct usb_interface *intf, u32 state)
+static int hid_suspend(struct usb_interface *intf, pm_message_t message)
 {
 	struct hid_device *hid = usb_get_intfdata (intf);
 
 	usb_kill_urb(hid->urbin);
-	intf->dev.power.power_state = state;
+	intf->dev.power.power_state = PMSG_SUSPEND;
 	dev_dbg(&intf->dev, "suspend\n");
 	return 0;
 }
@@ -1805,7 +1805,7 @@
 	struct hid_device *hid = usb_get_intfdata (intf);
 	int status;
 
-	intf->dev.power.power_state = PM_SUSPEND_ON;
+	intf->dev.power.power_state = PMSG_ON;
 	if (hid->open)
 		status = usb_submit_urb(hid->urbin, GFP_NOIO);
 	else
diff -Naur -X ../dontdiff linux-2.6.12-rc2/drivers/usb/misc/sisusbvga/sisusb.c linux-2.6.12-rc2-usb/drivers/usb/misc/sisusbvga/sisusb.c
--- linux-2.6.12-rc2/drivers/usb/misc/sisusbvga/sisusb.c	2005-04-07 00:35:55.000000000 -0700
+++ linux-2.6.12-rc2-usb/drivers/usb/misc/sisusbvga/sisusb.c	2005-04-09 08:57:13.000000000 -0700
@@ -3104,6 +3104,7 @@
 
 static struct usb_device_id sisusb_table [] = {
 	{ USB_DEVICE(0x0711, 0x0900) },
+	{ USB_DEVICE(0x182d, 0x021c) },
 	{ }
 };
 
@@ -3114,7 +3115,7 @@
 	.name =		"sisusb",
 	.probe =	sisusb_probe,
 	.disconnect =	sisusb_disconnect,
-	.id_table =	sisusb_table
+	.id_table =	sisusb_table,
 };
 
 static int __init usb_sisusb_init(void)
diff -Naur -X ../dontdiff linux-2.6.12-rc2/drivers/usb/net/pegasus.c linux-2.6.12-rc2-usb/drivers/usb/net/pegasus.c
--- linux-2.6.12-rc2/drivers/usb/net/pegasus.c	2005-04-07 00:36:31.000000000 -0700
+++ linux-2.6.12-rc2-usb/drivers/usb/net/pegasus.c	2005-04-09 08:57:12.000000000 -0700
@@ -1364,11 +1364,18 @@
 	free_netdev(pegasus->net);
 }
 
-static int pegasus_suspend (struct usb_interface *intf, pm_message_t state)
+static int pegasus_suspend (struct usb_interface *intf, pm_message_t message)
 {
 	struct pegasus *pegasus = usb_get_intfdata(intf);
 	
 	netif_device_detach (pegasus->net);
+	if (netif_running(pegasus->net)) {
+		cancel_delayed_work(&pegasus->carrier_check);
+
+		usb_kill_urb(pegasus->rx_urb);
+		usb_kill_urb(pegasus->intr_urb);
+	}
+	intf->dev.power.power_state = PMSG_SUSPEND;
 	return 0;
 }
 
@@ -1376,7 +1383,20 @@
 {
 	struct pegasus *pegasus = usb_get_intfdata(intf);
 
+	intf->dev.power.power_state = PMSG_ON;
 	netif_device_attach (pegasus->net);
+	if (netif_running(pegasus->net)) {
+		pegasus->rx_urb->status = 0;
+		pegasus->rx_urb->actual_length = 0;
+		read_bulk_callback(pegasus->rx_urb, 0);
+
+		pegasus->intr_urb->status = 0;
+		pegasus->intr_urb->actual_length = 0;
+		intr_callback(pegasus->intr_urb, 0);
+
+		queue_delayed_work(pegasus_workqueue, &pegasus->carrier_check,
+					CARRIER_CHECK_DELAY);
+	}
 	return 0;
 }
 
diff -Naur -X ../dontdiff linux-2.6.12-rc2/drivers/usb/net/usbnet.c linux-2.6.12-rc2-usb/drivers/usb/net/usbnet.c
--- linux-2.6.12-rc2/drivers/usb/net/usbnet.c	2005-04-07 00:36:31.000000000 -0700
+++ linux-2.6.12-rc2-usb/drivers/usb/net/usbnet.c	2005-04-09 08:57:13.000000000 -0700
@@ -426,7 +426,7 @@
 	dev->stats.rx_bytes += skb->len;
 
 	if (netif_msg_rx_status (dev))
-		devdbg (dev, "< rx, len %d, type 0x%x",
+		devdbg (dev, "< rx, len %zd, type 0x%x",
 			skb->len + sizeof (struct ethhdr), skb->protocol);
 	memset (skb->cb, 0, sizeof (struct skb_data));
 	status = netif_rx (skb);
@@ -3732,11 +3732,17 @@
 
 #ifdef	CONFIG_PM
 
-static int usbnet_suspend (struct usb_interface *intf, u32 state)
+static int usbnet_suspend (struct usb_interface *intf, pm_message_t message)
 {
 	struct usbnet		*dev = usb_get_intfdata(intf);
 	
+	/* accelerate emptying of the rx and queues, to avoid
+	 * having everything error out.
+	 */
 	netif_device_detach (dev->net);
+	(void) unlink_urbs (dev, &dev->rxq);
+	(void) unlink_urbs (dev, &dev->txq);
+	intf->dev.power.power_state = PMSG_SUSPEND;
 	return 0;
 }
 
@@ -3744,7 +3750,9 @@
 {
 	struct usbnet		*dev = usb_get_intfdata(intf);
 
+	intf->dev.power.power_state = PMSG_ON;
 	netif_device_attach (dev->net);
+	tasklet_schedule (&dev->bh);
 	return 0;
 }
 
@@ -4009,10 +4017,23 @@
 	.idProduct              = 0x9050,	/* C-860 */
 	ZAURUS_MASTER_INTERFACE,
 	.driver_info = ZAURUS_PXA_INFO,
+},
+
 #ifdef	CONFIG_USB_ZAURUS
-	/* at least some (reports vary) C-860 units have very different
-	 * lies about their standards support.
+	/* at least some (reports vary) PXA units have very different
+	 * lies about their standards support:  they claim to be cell
+	 * phones giving direct radio access (which they aren't).
 	 */
+{
+	.match_flags    =   USB_DEVICE_ID_MATCH_INT_INFO
+		 | USB_DEVICE_ID_MATCH_DEVICE,
+	.idVendor               = 0x04DD,
+	/* Sharp ROM v1.32 */
+	.idProduct		= 0x8006,	/* SL-5600 */
+	.bInterfaceClass	= USB_CLASS_COMM,
+	.bInterfaceSubClass	= USB_CDC_SUBCLASS_MDLM,
+	.bInterfaceProtocol	= USB_CDC_PROTO_NONE,
+	.driver_info 		= (unsigned long) &zaurus_pxa_mdlm_info,
 }, {
 	.match_flags    =   USB_DEVICE_ID_MATCH_INT_INFO
 		 | USB_DEVICE_ID_MATCH_DEVICE,
@@ -4023,8 +4044,8 @@
 	.bInterfaceSubClass	= USB_CDC_SUBCLASS_MDLM,
 	.bInterfaceProtocol	= USB_CDC_PROTO_NONE,
 	.driver_info 		= (unsigned long) &zaurus_pxa_mdlm_info,
-#endif
 },
+#endif
 
 /* Olympus has some models with a Zaurus-compatible option.
  * R-1000 uses a FreeScale i.MXL cpu (ARMv4T)
diff -Naur -X ../dontdiff linux-2.6.12-rc2/drivers/usb/serial/digi_acceleport.c linux-2.6.12-rc2-usb/drivers/usb/serial/digi_acceleport.c
--- linux-2.6.12-rc2/drivers/usb/serial/digi_acceleport.c	2005-04-07 00:35:55.000000000 -0700
+++ linux-2.6.12-rc2-usb/drivers/usb/serial/digi_acceleport.c	2005-04-09 08:57:13.000000000 -0700
@@ -568,6 +568,9 @@
 *  and the sleep.  In other words, spin_unlock_irqrestore and
 *  interruptible_sleep_on_timeout are "atomic" with respect to
 *  wake ups.  This is used to implement condition variables.
+*
+*  interruptible_sleep_on_timeout is deprecated and has been replaced
+*  with the equivalent code.
 */
 
 static inline long cond_wait_interruptible_timeout_irqrestore(
@@ -576,13 +579,12 @@
 {
 	DEFINE_WAIT(wait);
 
-	prepare_to_wait(q, &wait, TASK_UNINTERRUPTIBLE);
+	prepare_to_wait(q, &wait, TASK_INTERRUPTIBLE);
 	spin_unlock_irqrestore(lock, flags);
 	timeout = schedule_timeout(timeout);
 	finish_wait(q, &wait);
 
 	return timeout;
-
 }
 
 
@@ -1596,7 +1598,7 @@
 			dbg( "digi_close: write oob failed, ret=%d", ret );
 
 		/* wait for final commands on oob port to complete */
-		prepare_to_wait(&priv->dp_flush_wait, &wait, TASK_UNINTERRUPTIBLE);
+		prepare_to_wait(&priv->dp_flush_wait, &wait, TASK_INTERRUPTIBLE);
 		schedule_timeout(DIGI_CLOSE_TIMEOUT);
 		finish_wait(&priv->dp_flush_wait, &wait);
 
@@ -1995,7 +1997,7 @@
 
 		} else if( opcode == DIGI_CMD_IFLUSH_FIFO ) {
 
-			wake_up( &priv->dp_flush_wait );
+			wake_up_interruptible( &priv->dp_flush_wait );
 
 		}
 
diff -Naur -X ../dontdiff linux-2.6.12-rc2/drivers/usb/serial/visor.c linux-2.6.12-rc2-usb/drivers/usb/serial/visor.c
--- linux-2.6.12-rc2/drivers/usb/serial/visor.c	2005-04-07 00:36:31.000000000 -0700
+++ linux-2.6.12-rc2-usb/drivers/usb/serial/visor.c	2005-04-09 08:57:13.000000000 -0700
@@ -215,6 +215,8 @@
 		.driver_info = (kernel_ulong_t)&palm_os_4_probe },
 	{ USB_DEVICE(PALM_VENDOR_ID, PALM_TUNGSTEN_T_ID),
 		.driver_info = (kernel_ulong_t)&palm_os_4_probe },
+	{ USB_DEVICE(PALM_VENDOR_ID, PALM_TREO_650),
+		.driver_info = (kernel_ulong_t)&palm_os_4_probe },
 	{ USB_DEVICE(PALM_VENDOR_ID, PALM_TUNGSTEN_Z_ID),
 		.driver_info = (kernel_ulong_t)&palm_os_4_probe },
 	{ USB_DEVICE(PALM_VENDOR_ID, PALM_ZIRE31_ID),
@@ -237,6 +239,8 @@
 		.driver_info = (kernel_ulong_t)&palm_os_4_probe },
 	{ USB_DEVICE(SAMSUNG_VENDOR_ID, SAMSUNG_SPH_I500_ID), 
 		.driver_info = (kernel_ulong_t)&palm_os_4_probe },
+	{ USB_DEVICE(TAPWAVE_VENDOR_ID, TAPWAVE_ZODIAC_ID),
+		.driver_info = (kernel_ulong_t)&palm_os_4_probe },
 	{ USB_DEVICE(GARMIN_VENDOR_ID, GARMIN_IQUE_3600_ID), 
 		.driver_info = (kernel_ulong_t)&palm_os_4_probe },
 	{ USB_DEVICE(ACEECA_VENDOR_ID, ACEECA_MEZ1000_ID),
@@ -273,6 +277,7 @@
 	{ USB_DEVICE(PALM_VENDOR_ID, PALM_M125_ID) },
 	{ USB_DEVICE(PALM_VENDOR_ID, PALM_M130_ID) },
 	{ USB_DEVICE(PALM_VENDOR_ID, PALM_TUNGSTEN_T_ID) },
+	{ USB_DEVICE(PALM_VENDOR_ID, PALM_TREO_650) },
 	{ USB_DEVICE(PALM_VENDOR_ID, PALM_TUNGSTEN_Z_ID) },
 	{ USB_DEVICE(PALM_VENDOR_ID, PALM_ZIRE31_ID) },
 	{ USB_DEVICE(PALM_VENDOR_ID, PALM_ZIRE_ID) },
@@ -286,6 +291,7 @@
 	{ USB_DEVICE(SONY_VENDOR_ID, SONY_CLIE_TJ25_ID) },
 	{ USB_DEVICE(SAMSUNG_VENDOR_ID, SAMSUNG_SCH_I330_ID) },
 	{ USB_DEVICE(SAMSUNG_VENDOR_ID, SAMSUNG_SPH_I500_ID) },
+	{ USB_DEVICE(TAPWAVE_VENDOR_ID, TAPWAVE_ZODIAC_ID) },
 	{ USB_DEVICE(GARMIN_VENDOR_ID, GARMIN_IQUE_3600_ID) },
 	{ USB_DEVICE(ACEECA_VENDOR_ID, ACEECA_MEZ1000_ID) },
 	{ USB_DEVICE(KYOCERA_VENDOR_ID, KYOCERA_7135_ID) },
diff -Naur -X ../dontdiff linux-2.6.12-rc2/drivers/usb/serial/visor.h linux-2.6.12-rc2-usb/drivers/usb/serial/visor.h
--- linux-2.6.12-rc2/drivers/usb/serial/visor.h	2005-04-07 00:36:31.000000000 -0700
+++ linux-2.6.12-rc2-usb/drivers/usb/serial/visor.h	2005-04-09 08:57:13.000000000 -0700
@@ -30,6 +30,7 @@
 #define PALM_M125_ID			0x0040
 #define PALM_M130_ID			0x0050
 #define PALM_TUNGSTEN_T_ID		0x0060
+#define PALM_TREO_650			0x0061
 #define PALM_TUNGSTEN_Z_ID		0x0031
 #define PALM_ZIRE31_ID			0x0061
 #define PALM_ZIRE_ID			0x0070
@@ -49,6 +50,9 @@
 #define SAMSUNG_SCH_I330_ID		0x8001
 #define SAMSUNG_SPH_I500_ID		0x6601
 
+#define TAPWAVE_VENDOR_ID		0x12EF
+#define TAPWAVE_ZODIAC_ID		0x0100
+
 #define GARMIN_VENDOR_ID		0x091E
 #define GARMIN_IQUE_3600_ID		0x0004
 
diff -Naur -X ../dontdiff linux-2.6.12-rc2/drivers/usb/storage/transport.c linux-2.6.12-rc2-usb/drivers/usb/storage/transport.c
--- linux-2.6.12-rc2/drivers/usb/storage/transport.c	2005-04-07 00:35:55.000000000 -0700
+++ linux-2.6.12-rc2-usb/drivers/usb/storage/transport.c	2005-04-09 08:57:13.000000000 -0700
@@ -996,7 +996,7 @@
 	 * command phase and the data phase.  Some devices need a little
 	 * more than that, probably because of clock rate inaccuracies. */
 	if (unlikely(us->flags & US_FL_GO_SLOW))
-		udelay(110);
+		udelay(125);
 
 	if (transfer_length) {
 		unsigned int pipe = srb->sc_data_direction == DMA_FROM_DEVICE ? 
diff -Naur -X ../dontdiff linux-2.6.12-rc2/drivers/usb/storage/unusual_devs.h linux-2.6.12-rc2-usb/drivers/usb/storage/unusual_devs.h
--- linux-2.6.12-rc2/drivers/usb/storage/unusual_devs.h	2005-04-07 00:35:55.000000000 -0700
+++ linux-2.6.12-rc2-usb/drivers/usb/storage/unusual_devs.h	2005-04-09 08:57:13.000000000 -0700
@@ -763,6 +763,19 @@
 		US_FL_SINGLE_LUN ),
 #endif
 
+#ifdef CONFIG_USB_STORAGE_DATAFAB
+/* Reported by Felix Moeller <felix@derklecks.de>
+ * in Germany this is sold by Hama with the productnumber 46952
+ * as "DualSlot CompactFlash(TM) & MStick Drive USB"
+ */
+UNUSUAL_DEV(  0x07c4, 0xa10b, 0x0000, 0xffff,
+                "DataFab Systems Inc.",
+                "USB CF+MS",
+                US_SC_SCSI, US_PR_DATAFAB, NULL,
+                0 ),
+
+#endif
+
 /* Datafab KECF-USB / Sagatek DCS-CF / Simpletech Flashlink UCF-100
  * Only revision 1.13 tested (same for all of the above devices,
  * based on the Datafab DF-UG-07 chip).  Needed for US_FL_FIX_INQUIRY.
diff -Naur -X ../dontdiff linux-2.6.12-rc2/include/linux/usb.h linux-2.6.12-rc2-usb/include/linux/usb.h
--- linux-2.6.12-rc2/include/linux/usb.h	2005-04-07 00:36:34.000000000 -0700
+++ linux-2.6.12-rc2-usb/include/linux/usb.h	2005-04-09 08:57:12.000000000 -0700
@@ -558,7 +558,7 @@
 
 	int (*ioctl) (struct usb_interface *intf, unsigned int code, void *buf);
 
-	int (*suspend) (struct usb_interface *intf, u32 state);
+	int (*suspend) (struct usb_interface *intf, pm_message_t message);
 	int (*resume) (struct usb_interface *intf);
 
 	const struct usb_device_id *id_table;
@@ -977,7 +977,7 @@
 	int timeout);
 
 /* selective suspend/resume */
-extern int usb_suspend_device(struct usb_device *dev, u32 state);
+extern int usb_suspend_device(struct usb_device *dev, pm_message_t message);
 extern int usb_resume_device(struct usb_device *dev);
 
 
diff -Naur -X ../dontdiff linux-2.6.12-rc2/include/linux/usb_cdc.h linux-2.6.12-rc2-usb/include/linux/usb_cdc.h
--- linux-2.6.12-rc2/include/linux/usb_cdc.h	2005-04-07 00:36:31.000000000 -0700
+++ linux-2.6.12-rc2-usb/include/linux/usb_cdc.h	2005-04-09 08:57:12.000000000 -0700
@@ -114,7 +114,7 @@
 
 	/* type is associated with mdlm_desc.bGUID */
 	__u8	bGuidDescriptorType;
-	__u8	bDetailData[];
+	__u8	bDetailData[0];
 } __attribute__ ((packed));
 
 /*-------------------------------------------------------------------------*/
