Signed-off-by: Andrew Morton <akpm@osdl.org>
---

 25-akpm/drivers/net/irda/stir4200.c   |    4 
 25-akpm/drivers/usb/core/config.c     |    3 
 25-akpm/drivers/usb/core/devices.c    |    1 
 25-akpm/drivers/usb/core/file.c       |    2 
 25-akpm/drivers/usb/core/hcd-pci.c    |  151 ++++++++++++++++++++--------------
 25-akpm/drivers/usb/core/hcd.h        |    4 
 25-akpm/drivers/usb/core/hub.c        |    4 
 25-akpm/drivers/usb/core/inode.c      |    1 
 25-akpm/drivers/usb/core/usb.c        |   13 --
 25-akpm/drivers/usb/core/usb.h        |    8 +
 25-akpm/drivers/usb/host/ehci-dbg.c   |    2 
 25-akpm/drivers/usb/host/ehci-hcd.c   |    4 
 25-akpm/drivers/usb/host/ehci-sched.c |    4 
 25-akpm/drivers/usb/host/ehci.h       |    2 
 25-akpm/drivers/usb/host/ohci-pci.c   |    4 
 25-akpm/drivers/usb/host/uhci-hcd.c   |    2 
 25-akpm/drivers/usb/input/hid-core.c  |    6 -
 25-akpm/drivers/usb/net/pegasus.c     |   22 ++++
 25-akpm/drivers/usb/net/usbnet.c      |   10 ++
 25-akpm/drivers/usb/serial/visor.c    |    3 
 25-akpm/drivers/usb/serial/visor.h    |    1 
 25-akpm/include/linux/usb.h           |    4 
 25-akpm/include/linux/usb_cdc.h       |    2 
 23 files changed, 163 insertions(+), 94 deletions(-)

diff -puN drivers/net/irda/stir4200.c~gregkh-usb drivers/net/irda/stir4200.c
--- 25/drivers/net/irda/stir4200.c~gregkh-usb	2005-04-07 18:32:11.000000000 -0700
+++ 25-akpm/drivers/net/irda/stir4200.c	2005-04-07 18:32:11.000000000 -0700
@@ -1128,8 +1128,8 @@ static void stir_disconnect(struct usb_i
 }
 
 #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 -puN drivers/usb/core/config.c~gregkh-usb drivers/usb/core/config.c
--- 25/drivers/usb/core/config.c~gregkh-usb	2005-04-07 18:32:11.000000000 -0700
+++ 25-akpm/drivers/usb/core/config.c	2005-04-07 18:32:11.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 -puN drivers/usb/core/devices.c~gregkh-usb drivers/usb/core/devices.c
--- 25/drivers/usb/core/devices.c~gregkh-usb	2005-04-07 18:32:11.000000000 -0700
+++ 25-akpm/drivers/usb/core/devices.c	2005-04-07 18:32:11.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 -puN drivers/usb/core/file.c~gregkh-usb drivers/usb/core/file.c
--- 25/drivers/usb/core/file.c~gregkh-usb	2005-04-07 18:32:11.000000000 -0700
+++ 25-akpm/drivers/usb/core/file.c	2005-04-07 18:32:11.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 -puN drivers/usb/core/hcd.h~gregkh-usb drivers/usb/core/hcd.h
--- 25/drivers/usb/core/hcd.h~gregkh-usb	2005-04-07 18:32:11.000000000 -0700
+++ 25-akpm/drivers/usb/core/hcd.h	2005-04-07 18:32:11.000000000 -0700
@@ -177,7 +177,7 @@ struct hc_driver {
 	 * 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 int usb_hcd_pci_probe (struct pci
 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 -puN drivers/usb/core/hcd-pci.c~gregkh-usb drivers/usb/core/hcd-pci.c
--- 25/drivers/usb/core/hcd-pci.c~gregkh-usb	2005-04-07 18:32:11.000000000 -0700
+++ 25-akpm/drivers/usb/core/hcd-pci.c	2005-04-07 18:32:11.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 @@ int usb_hcd_pci_probe (struct pci_dev *d
 
 	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 @@ EXPORT_SYMBOL (usb_hcd_pci_remove);
 
 #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 @@ int usb_hcd_pci_suspend (struct pci_dev 
 
 	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 @@ int usb_hcd_pci_suspend (struct pci_dev 
 	 */
 	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 @@ int usb_hcd_pci_suspend (struct pci_dev 
 	 * 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 @@ int usb_hcd_pci_suspend (struct pci_dev 
 			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 @@ int usb_hcd_pci_suspend (struct pci_dev 
 	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 @@ int usb_hcd_pci_resume (struct pci_dev *
 {
 	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 @@ int usb_hcd_pci_resume (struct pci_dev *
 				"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 -puN drivers/usb/core/hub.c~gregkh-usb drivers/usb/core/hub.c
--- 25/drivers/usb/core/hub.c~gregkh-usb	2005-04-07 18:32:11.000000000 -0700
+++ 25-akpm/drivers/usb/core/hub.c	2005-04-07 18:32:11.000000000 -0700
@@ -1731,7 +1731,7 @@ static int finish_port_resume(struct usb
 			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 @@ static int finish_port_resume(struct usb
 
 			/* 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 -puN drivers/usb/core/inode.c~gregkh-usb drivers/usb/core/inode.c
--- 25/drivers/usb/core/inode.c~gregkh-usb	2005-04-07 18:32:11.000000000 -0700
+++ 25-akpm/drivers/usb/core/inode.c	2005-04-07 18:32:11.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 -puN drivers/usb/core/usb.c~gregkh-usb drivers/usb/core/usb.c
--- 25/drivers/usb/core/usb.c~gregkh-usb	2005-04-07 18:32:11.000000000 -0700
+++ 25-akpm/drivers/usb/core/usb.c	2005-04-07 18:32:11.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";
 
@@ -1387,13 +1380,13 @@ void usb_buffer_unmap_sg (struct usb_dev
 			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))
@@ -1407,7 +1400,7 @@ static int usb_generic_suspend(struct de
 		return 0;
 
 	if (driver->suspend)
-		return driver->suspend(intf, state);
+		return driver->suspend(intf, message);
 	return 0;
 }
 
diff -puN drivers/usb/core/usb.h~gregkh-usb drivers/usb/core/usb.h
--- 25/drivers/usb/core/usb.h~gregkh-usb	2005-04-07 18:32:11.000000000 -0700
+++ 25-akpm/drivers/usb/core/usb.h	2005-04-07 18:32:11.000000000 -0700
@@ -21,6 +21,13 @@ extern void usb_unlock_all_devices(void)
 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_devi
 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 -puN drivers/usb/host/ehci-dbg.c~gregkh-usb drivers/usb/host/ehci-dbg.c
--- 25/drivers/usb/host/ehci-dbg.c~gregkh-usb	2005-04-07 18:32:11.000000000 -0700
+++ 25-akpm/drivers/usb/host/ehci-dbg.c	2005-04-07 18:32:11.000000000 -0700
@@ -394,7 +394,7 @@ static void qh_lines (
 		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 -puN drivers/usb/host/ehci.h~gregkh-usb drivers/usb/host/ehci.h
--- 25/drivers/usb/host/ehci.h~gregkh-usb	2005-04-07 18:32:11.000000000 -0700
+++ 25-akpm/drivers/usb/host/ehci.h	2005-04-07 18:32:11.000000000 -0700
@@ -364,7 +364,7 @@ union ehci_shadow {
 	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 -puN drivers/usb/host/ehci-hcd.c~gregkh-usb drivers/usb/host/ehci-hcd.c
--- 25/drivers/usb/host/ehci-hcd.c~gregkh-usb	2005-04-07 18:32:11.000000000 -0700
+++ 25-akpm/drivers/usb/host/ehci-hcd.c	2005-04-07 18:32:11.000000000 -0700
@@ -721,7 +721,7 @@ static int ehci_get_frame (struct usb_hc
  * 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 @@ static int ehci_suspend (struct usb_hcd 
 		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 -puN drivers/usb/host/ehci-sched.c~gregkh-usb drivers/usb/host/ehci-sched.c
--- 25/drivers/usb/host/ehci-sched.c~gregkh-usb	2005-04-07 18:32:11.000000000 -0700
+++ 25-akpm/drivers/usb/host/ehci-sched.c	2005-04-07 18:32:11.000000000 -0700
@@ -310,9 +310,9 @@ static int qh_link_periodic (struct ehci
 
 	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 -puN drivers/usb/host/ohci-pci.c~gregkh-usb drivers/usb/host/ohci-pci.c
--- 25/drivers/usb/host/ohci-pci.c~gregkh-usb	2005-04-07 18:32:11.000000000 -0700
+++ 25-akpm/drivers/usb/host/ohci-pci.c	2005-04-07 18:32:11.000000000 -0700
@@ -102,7 +102,7 @@ ohci_pci_start (struct usb_hcd *hcd)
 
 #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 +111,7 @@ static int ohci_pci_suspend (struct usb_
 		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 -puN drivers/usb/host/uhci-hcd.c~gregkh-usb drivers/usb/host/uhci-hcd.c
--- 25/drivers/usb/host/uhci-hcd.c~gregkh-usb	2005-04-07 18:32:11.000000000 -0700
+++ 25-akpm/drivers/usb/host/uhci-hcd.c	2005-04-07 18:32:11.000000000 -0700
@@ -716,7 +716,7 @@ static void uhci_stop(struct usb_hcd *hc
 }
 
 #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 -puN drivers/usb/input/hid-core.c~gregkh-usb drivers/usb/input/hid-core.c
--- 25/drivers/usb/input/hid-core.c~gregkh-usb	2005-04-07 18:32:11.000000000 -0700
+++ 25-akpm/drivers/usb/input/hid-core.c	2005-04-07 18:32:11.000000000 -0700
@@ -1795,12 +1795,12 @@ static int hid_probe(struct usb_interfac
 	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;
 }
@@ -1810,7 +1810,7 @@ static int hid_resume(struct usb_interfa
 	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 -puN drivers/usb/net/pegasus.c~gregkh-usb drivers/usb/net/pegasus.c
--- 25/drivers/usb/net/pegasus.c~gregkh-usb	2005-04-07 18:32:11.000000000 -0700
+++ 25-akpm/drivers/usb/net/pegasus.c	2005-04-07 18:32:11.000000000 -0700
@@ -1364,11 +1364,18 @@ static void pegasus_disconnect(struct us
 	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 @@ static int pegasus_resume (struct usb_in
 {
 	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 -puN drivers/usb/net/usbnet.c~gregkh-usb drivers/usb/net/usbnet.c
--- 25/drivers/usb/net/usbnet.c~gregkh-usb	2005-04-07 18:32:11.000000000 -0700
+++ 25-akpm/drivers/usb/net/usbnet.c	2005-04-07 18:32:11.000000000 -0700
@@ -3732,11 +3732,17 @@ out:
 
 #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 @@ static int usbnet_resume (struct usb_int
 {
 	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;
 }
 
diff -puN drivers/usb/serial/visor.c~gregkh-usb drivers/usb/serial/visor.c
--- 25/drivers/usb/serial/visor.c~gregkh-usb	2005-04-07 18:32:11.000000000 -0700
+++ 25-akpm/drivers/usb/serial/visor.c	2005-04-07 18:32:11.000000000 -0700
@@ -215,6 +215,8 @@ static struct usb_device_id id_table [] 
 		.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),
@@ -273,6 +275,7 @@ static struct usb_device_id id_table_com
 	{ 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) },
diff -puN drivers/usb/serial/visor.h~gregkh-usb drivers/usb/serial/visor.h
--- 25/drivers/usb/serial/visor.h~gregkh-usb	2005-04-07 18:32:11.000000000 -0700
+++ 25-akpm/drivers/usb/serial/visor.h	2005-04-07 18:32:11.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
diff -puN include/linux/usb_cdc.h~gregkh-usb include/linux/usb_cdc.h
--- 25/include/linux/usb_cdc.h~gregkh-usb	2005-04-07 18:32:11.000000000 -0700
+++ 25-akpm/include/linux/usb_cdc.h	2005-04-07 18:32:11.000000000 -0700
@@ -114,7 +114,7 @@ struct usb_cdc_mdlm_detail_desc {
 
 	/* type is associated with mdlm_desc.bGUID */
 	__u8	bGuidDescriptorType;
-	__u8	bDetailData[];
+	__u8	bDetailData[0];
 } __attribute__ ((packed));
 
 /*-------------------------------------------------------------------------*/
diff -puN include/linux/usb.h~gregkh-usb include/linux/usb.h
--- 25/include/linux/usb.h~gregkh-usb	2005-04-07 18:32:11.000000000 -0700
+++ 25-akpm/include/linux/usb.h	2005-04-07 18:32:11.000000000 -0700
@@ -557,7 +557,7 @@ struct usb_driver {
 
 	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;
@@ -976,7 +976,7 @@ extern int usb_bulk_msg(struct usb_devic
 	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);
 
 
_
