# This is a BitKeeper generated patch for the following project:
# Project Name: Linux kernel tree
# This patch format is intended for GNU patch command version 2.5 or higher.
# This patch includes the following deltas:
#                  ChangeSet    1.466   -> 1.467  
#       drivers/usb/core/hcd.h  1.8     -> 1.9    
#       drivers/usb/core/hcd.c  1.21    -> 1.22   
#       drivers/usb/core/Makefile       1.7     -> 1.8    
#                      (new)            -> 1.1     drivers/usb/core/hcd-pci.c
#
# The following is the BitKeeper ChangeSet Log
# --------------------------------------------
# 02/06/06      [EMAIL PROTECTED]  1.467
# USB: split some pci specific pieces out of hcd.c into a separate file.
# --------------------------------------------
#
diff -Nru a/drivers/usb/core/Makefile b/drivers/usb/core/Makefile
--- a/drivers/usb/core/Makefile Thu Jun  6 14:38:23 2002
+++ b/drivers/usb/core/Makefile Thu Jun  6 14:38:23 2002
@@ -2,10 +2,14 @@
 # Makefile for USB Core files and filesystem
 #
 
-export-objs    := usb.o hcd.o urb.o message.o config.o
+export-objs    := usb.o hcd.o hcd-pci.o urb.o message.o config.o
 
 usbcore-objs   := usb.o usb-debug.o hub.o hcd.o urb.o message.o \
                        config.o
+
+ifeq ($(CONFIG_PCI),y)
+       usbcore-objs    += hcd-pci.o
+endif
 
 ifeq ($(CONFIG_USB_DEVICEFS),y)
        usbcore-objs    += devio.o inode.o drivers.o devices.o
diff -Nru a/drivers/usb/core/hcd-pci.c b/drivers/usb/core/hcd-pci.c
--- /dev/null   Wed Dec 31 16:00:00 1969
+++ b/drivers/usb/core/hcd-pci.c        Thu Jun  6 14:38:23 2002
@@ -0,0 +1,401 @@
+/*
+ * (C) Copyright Linus Torvalds 1999
+ * (C) Copyright Johannes Erdfelt 1999-2001
+ * (C) Copyright Andreas Gal 1999
+ * (C) Copyright Gregory P. Smith 1999
+ * (C) Copyright Deti Fliegl 1999
+ * (C) Copyright Randy Dunlap 2000
+ * (C) Copyright David Brownell 2000-2002
+ * 
+ * This program is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License as published by the
+ * Free Software Foundation; either version 2 of the License, or (at your
+ * option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful, but
+ * WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY
+ * or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
+ * for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software Foundation,
+ * Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
+ */
+
+#include <linux/config.h>
+#include <linux/kernel.h>
+#include <linux/module.h>
+#include <linux/pci.h>
+
+#ifdef CONFIG_USB_DEBUG
+       #define DEBUG
+#else
+       #undef DEBUG
+#endif
+
+#include <linux/usb.h>
+#include "hcd.h"
+
+
+/* PCI-based HCs are normal, but custom bus glue should be ok */
+
+static void hcd_irq (int irq, void *__hcd, struct pt_regs *r);
+static void hc_died (struct usb_hcd *hcd);
+
+/*-------------------------------------------------------------------------*/
+
+/* configure so an HC device and id are always provided */
+/* always called with process context; sleeping is OK */
+
+/**
+ * usb_hcd_pci_probe - initialize PCI-based HCDs
+ * @dev: USB Host Controller being probed
+ * @id: pci hotplug id connecting controller to HCD framework
+ * Context: !in_interrupt()
+ *
+ * Allocates basic PCI resources for this USB host controller, and
+ * then invokes the start() method for the HCD associated with it
+ * through the hotplug entry's driver_data.
+ *
+ * Store this function in the HCD's struct pci_driver as probe().
+ */
+int usb_hcd_pci_probe (struct pci_dev *dev, const struct pci_device_id *id)
+{
+       struct hc_driver        *driver;
+       unsigned long           resource, len;
+       void                    *base;
+       u8                      latency, limit;
+       struct usb_hcd          *hcd;
+       int                     retval, region;
+       char                    buf [8], *bufp = buf;
+
+       if (!id || !(driver = (struct hc_driver *) id->driver_data))
+               return -EINVAL;
+
+       if (pci_enable_device (dev) < 0)
+               return -ENODEV;
+       
+        if (!dev->irq) {
+               err ("Found HC with no IRQ.  Check BIOS/PCI %s setup!",
+                       dev->slot_name);
+               return -ENODEV;
+        }
+       
+       if (driver->flags & HCD_MEMORY) {       // EHCI, OHCI
+               region = 0;
+               resource = pci_resource_start (dev, 0);
+               len = pci_resource_len (dev, 0);
+               if (!request_mem_region (resource, len, driver->description)) {
+                       dbg ("controller already in use");
+                       return -EBUSY;
+               }
+               base = ioremap_nocache (resource, len);
+               if (base == NULL) {
+                       dbg ("error mapping memory");
+                       retval = -EFAULT;
+clean_1:
+                       release_mem_region (resource, len);
+                       err ("init %s fail, %d", dev->slot_name, retval);
+                       return retval;
+               }
+
+       } else {                                // UHCI
+               resource = len = 0;
+               for (region = 0; region < PCI_ROM_RESOURCE; region++) {
+                       if (!(pci_resource_flags (dev, region) & IORESOURCE_IO))
+                               continue;
+
+                       resource = pci_resource_start (dev, region);
+                       len = pci_resource_len (dev, region);
+                       if (request_region (resource, len,
+                                       driver->description))
+                               break;
+               }
+               if (region == PCI_ROM_RESOURCE) {
+                       dbg ("no i/o regions available");
+                       return -EBUSY;
+               }
+               base = (void *) resource;
+       }
+
+       // driver->start(), later on, will transfer device from
+       // control by SMM/BIOS to control by Linux (if needed)
+
+       pci_set_master (dev);
+       hcd = driver->hcd_alloc ();
+       if (hcd == NULL){
+               dbg ("hcd alloc fail");
+               retval = -ENOMEM;
+clean_2:
+               if (driver->flags & HCD_MEMORY) {
+                       iounmap (base);
+                       goto clean_1;
+               } else {
+                       release_region (resource, len);
+                       err ("init %s fail, %d", dev->slot_name, retval);
+                       return retval;
+               }
+       }
+       pci_set_drvdata(dev, hcd);
+       hcd->driver = driver;
+       hcd->description = driver->description;
+       hcd->pdev = dev;
+       info ("%s @ %s, %s", hcd->description,  dev->slot_name, dev->name);
+
+       pci_read_config_byte (dev, PCI_LATENCY_TIMER, &latency);
+       if (latency) {
+               pci_read_config_byte (dev, PCI_MAX_LAT, &limit);
+               if (limit && limit < latency) {
+                       dbg ("PCI latency reduced to max %d", limit);
+                       pci_write_config_byte (dev, PCI_LATENCY_TIMER, limit);
+               }
+       }
+
+#ifndef __sparc__
+       sprintf (buf, "%d", dev->irq);
+#else
+       bufp = __irq_itoa(dev->irq);
+#endif
+       if (request_irq (dev->irq, hcd_irq, SA_SHIRQ, hcd->description, hcd)
+                       != 0) {
+               err ("request interrupt %s failed", bufp);
+               retval = -EBUSY;
+               driver->hcd_free (hcd);
+               goto clean_2;
+       }
+       hcd->irq = dev->irq;
+
+       hcd->regs = base;
+       hcd->region = region;
+       info ("irq %s, %s %p", bufp,
+               (driver->flags & HCD_MEMORY) ? "pci mem" : "io base",
+               base);
+
+       usb_init_bus (&hcd->self);
+       hcd->self.op = &hcd_operations;
+       hcd->self.hcpriv = (void *) hcd;
+       hcd->self.bus_name = dev->slot_name;
+       hcd->product_desc = dev->name;
+
+       INIT_LIST_HEAD (&hcd->dev_list);
+
+       usb_register_bus (&hcd->self);
+
+       if ((retval = driver->start (hcd)) < 0)
+               usb_hcd_pci_remove (dev);
+
+       return retval;
+} 
+EXPORT_SYMBOL (usb_hcd_pci_probe);
+
+
+/* may be called without controller electrically present */
+/* may be called with controller, bus, and devices active */
+
+/**
+ * usb_hcd_pci_remove - shutdown processing for PCI-based HCDs
+ * @dev: USB Host Controller being removed
+ * Context: !in_interrupt()
+ *
+ * Reverses the effect of usb_hcd_pci_probe(), first invoking
+ * the HCD's stop() method.  It is always called from a thread
+ * context, normally "rmmod", "apmd", or something similar.
+ *
+ * Store this function in the HCD's struct pci_driver as remove().
+ */
+void usb_hcd_pci_remove (struct pci_dev *dev)
+{
+       struct usb_hcd          *hcd;
+       struct usb_device       *hub;
+
+       hcd = pci_get_drvdata(dev);
+       if (!hcd)
+               return;
+       info ("remove: %s, state %x", hcd->self.bus_name, hcd->state);
+
+       if (in_interrupt ()) BUG ();
+
+       hub = hcd->self.root_hub;
+       hcd->state = USB_STATE_QUIESCING;
+
+       dbg ("%s: roothub graceful disconnect", hcd->self.bus_name);
+       usb_disconnect (&hub);
+
+       hcd->driver->stop (hcd);
+       hcd->state = USB_STATE_HALT;
+
+       free_irq (hcd->irq, hcd);
+       if (hcd->driver->flags & HCD_MEMORY) {
+               iounmap (hcd->regs);
+               release_mem_region (pci_resource_start (dev, 0),
+                       pci_resource_len (dev, 0));
+       } else {
+               release_region (pci_resource_start (dev, hcd->region),
+                       pci_resource_len (dev, hcd->region));
+       }
+
+       usb_deregister_bus (&hcd->self);
+       if (atomic_read (&hcd->self.refcnt) != 1)
+               err ("usb_hcd_pci_remove %s, count != 1", hcd->self.bus_name);
+
+       hcd->driver->hcd_free (hcd);
+}
+EXPORT_SYMBOL (usb_hcd_pci_remove);
+
+
+#ifdef CONFIG_PM
+
+/*
+ * Some "sleep" power levels imply updating struct usb_driver
+ * to include a callback asking hcds to do their bit by checking
+ * if all the drivers can suspend.  Gets involved with remote wakeup.
+ *
+ * If there are pending urbs, then HCs will need to access memory,
+ * causing extra power drain.  New sleep()/wakeup() PM calls might
+ * be needed, beyond PCI suspend()/resume().  The root hub timer
+ * still be accessing memory though ...
+ *
+ * FIXME:  USB should have some power budgeting support working with
+ * all kinds of hubs.
+ *
+ * FIXME:  This assumes only D0->D3 suspend and D3->D0 resume.
+ * D1 and D2 states should do something, yes?
+ *
+ * FIXME:  Should provide generic enable_wake(), calling pci_enable_wake()
+ * for all supported states, so that USB remote wakeup can work for any
+ * devices that support it (and are connected via powered hubs).
+ *
+ * FIXME:  resume doesn't seem to work right any more...
+ */
+
+
+// 2.4 kernels have issued concurrent resumes (w/APM)
+// we defend against that error; PCI doesn't yet.
+
+/**
+ * usb_hcd_pci_suspend - power management suspend of a PCI-based HCD
+ * @dev: USB Host Controller being suspended
+ *
+ * Store this function in the HCD's struct pci_driver as suspend().
+ */
+int usb_hcd_pci_suspend (struct pci_dev *dev, u32 state)
+{
+       struct usb_hcd          *hcd;
+       int                     retval;
+
+       hcd = pci_get_drvdata(dev);
+       info ("suspend %s to state %d", hcd->self.bus_name, state);
+
+       pci_save_state (dev, hcd->pci_state);
+
+       // FIXME for all connected devices, leaf-to-root:
+       // driver->suspend()
+       // proposed "new 2.5 driver model" will automate that
+
+       /* driver may want to disable DMA etc */
+       retval = hcd->driver->suspend (hcd, state);
+       hcd->state = USB_STATE_SUSPENDED;
+
+       pci_set_power_state (dev, state);
+       return retval;
+}
+EXPORT_SYMBOL (usb_hcd_pci_suspend);
+
+/**
+ * usb_hcd_pci_resume - power management resume of a PCI-based HCD
+ * @dev: USB Host Controller being resumed
+ *
+ * Store this function in the HCD's struct pci_driver as resume().
+ */
+int usb_hcd_pci_resume (struct pci_dev *dev)
+{
+       struct usb_hcd          *hcd;
+       int                     retval;
+
+       hcd = pci_get_drvdata(dev);
+       info ("resume %s", hcd->self.bus_name);
+
+       /* guard against multiple resumes (APM bug?) */
+       atomic_inc (&hcd->resume_count);
+       if (atomic_read (&hcd->resume_count) != 1) {
+               err ("concurrent PCI resumes for %s", hcd->self.bus_name);
+               retval = 0;
+               goto done;
+       }
+
+       retval = -EBUSY;
+       if (hcd->state != USB_STATE_SUSPENDED) {
+               dbg ("can't resume, not suspended!");
+               goto done;
+       }
+       hcd->state = USB_STATE_RESUMING;
+
+       pci_set_power_state (dev, 0);
+       pci_restore_state (dev, hcd->pci_state);
+
+       retval = hcd->driver->resume (hcd);
+       if (!HCD_IS_RUNNING (hcd->state)) {
+               dbg ("resume %s failure, retval %d", hcd->self.bus_name, retval);
+               hc_died (hcd);
+// FIXME:  recover, reset etc.
+       } else {
+               // FIXME for all connected devices, root-to-leaf:
+               // driver->resume ();
+               // proposed "new 2.5 driver model" will automate that
+       }
+
+done:
+       atomic_dec (&hcd->resume_count);
+       return retval;
+}
+EXPORT_SYMBOL (usb_hcd_pci_resume);
+
+#endif /* CONFIG_PM */
+
+/*-------------------------------------------------------------------------*/
+
+static void hcd_irq (int irq, void *__hcd, struct pt_regs * r)
+{
+       struct usb_hcd          *hcd = __hcd;
+       int                     start = hcd->state;
+
+       if (unlikely (hcd->state == USB_STATE_HALT))    /* irq sharing? */
+               return;
+
+       hcd->driver->irq (hcd);
+       if (hcd->state != start && hcd->state == USB_STATE_HALT)
+               hc_died (hcd);
+}
+
+/*-------------------------------------------------------------------------*/
+
+static void hc_died (struct usb_hcd *hcd)
+{
+       struct list_head        *devlist, *urblist;
+       struct hcd_dev          *dev;
+       struct urb              *urb;
+       unsigned long           flags;
+       
+       /* flag every pending urb as done */
+       spin_lock_irqsave (&hcd_data_lock, flags);
+       list_for_each (devlist, &hcd->dev_list) {
+               dev = list_entry (devlist, struct hcd_dev, dev_list);
+               list_for_each (urblist, &dev->urb_list) {
+                       urb = list_entry (urblist, struct urb, urb_list);
+                       dbg ("shutdown %s urb %p pipe %x, current status %d",
+                               hcd->self.bus_name, urb, urb->pipe, urb->status);
+                       if (urb->status == -EINPROGRESS)
+                               urb->status = -ESHUTDOWN;
+               }
+       }
+       urb = (struct urb *) hcd->rh_timer.data;
+       if (urb)
+               urb->status = -ESHUTDOWN;
+       spin_unlock_irqrestore (&hcd_data_lock, flags);
+
+       if (urb)
+               usb_rh_status_dequeue (hcd, urb);
+       hcd->driver->stop (hcd);
+}
+
+
diff -Nru a/drivers/usb/core/hcd.c b/drivers/usb/core/hcd.c
--- a/drivers/usb/core/hcd.c    Thu Jun  6 14:38:23 2002
+++ b/drivers/usb/core/hcd.c    Thu Jun  6 14:38:23 2002
@@ -23,24 +23,12 @@
  */
 
 #include <linux/config.h>
-#include <linux/version.h>
 #include <linux/module.h>
-#include <linux/sched.h>
-#include <linux/pci.h>
 #include <linux/kernel.h>
-#include <linux/delay.h>
-#include <linux/ioport.h>
-#include <linux/sched.h>
 #include <linux/slab.h>
-#include <linux/smp_lock.h>
-#include <linux/errno.h>
-#include <linux/kmod.h>
-#include <linux/init.h>
-#include <linux/timer.h>
-#include <linux/list.h>
-#include <linux/interrupt.h>
 #include <linux/completion.h>
 #include <linux/uts.h>                 /* for UTS_SYSNAME */
+#include <asm/byteorder.h>
 
 
 #ifdef CONFIG_USB_DEBUG
@@ -52,12 +40,6 @@
 #include <linux/usb.h>
 #include "hcd.h"
 
-#include <asm/io.h>
-#include <asm/irq.h>
-#include <asm/system.h>
-#include <asm/unaligned.h>
-#include <asm/byteorder.h>
-
 
 // #define USB_BANDWIDTH_MESSAGES
 
@@ -110,9 +92,9 @@
 DECLARE_MUTEX (usb_bus_list_lock);     /* exported only for usbfs */
 
 /* used when updating hcd data */
-static spinlock_t hcd_data_lock = SPIN_LOCK_UNLOCKED;
+spinlock_t hcd_data_lock = SPIN_LOCK_UNLOCKED;
 
-static struct usb_operations hcd_operations;
+struct usb_operations hcd_operations;
 
 /*-------------------------------------------------------------------------*/
 
@@ -288,7 +270,7 @@
 /*
  * rh_string - provides manufacturer, product and serial strings for root hub
  * @id: the string ID number (1: serial number, 2: product, 3: vendor)
- * @pci_desc: PCI device descriptor for the relevant HC
+ * @hcd: the host controller for this root hub
  * @type: string describing our driver 
  * @data: return packet in UTF-16 LE
  * @len: length of the return packet
@@ -559,7 +541,7 @@
 
 /*-------------------------------------------------------------------------*/
 
-static void rh_status_dequeue (struct usb_hcd *hcd, struct urb *urb)
+void usb_rh_status_dequeue (struct usb_hcd *hcd, struct urb *urb)
 {
        unsigned long   flags;
 
@@ -590,7 +572,7 @@
 /*-------------------------------------------------------------------------*/
 
 /* shared initialization code */
-static void usb_init_bus (struct usb_bus *bus)
+void usb_init_bus (struct usb_bus *bus)
 {
        memset (&bus->devmap, 0, sizeof(struct usb_devmap));
 
@@ -924,327 +906,6 @@
 
 /*-------------------------------------------------------------------------*/
 
-#ifdef CONFIG_PCI
-
-/* PCI-based HCs are normal, but custom bus glue should be ok */
-
-static void hcd_irq (int irq, void *__hcd, struct pt_regs *r);
-static void hc_died (struct usb_hcd *hcd);
-
-/*-------------------------------------------------------------------------*/
-
-/* configure so an HC device and id are always provided */
-/* always called with process context; sleeping is OK */
-
-/**
- * usb_hcd_pci_probe - initialize PCI-based HCDs
- * @dev: USB Host Controller being probed
- * @id: pci hotplug id connecting controller to HCD framework
- * Context: !in_interrupt()
- *
- * Allocates basic PCI resources for this USB host controller, and
- * then invokes the start() method for the HCD associated with it
- * through the hotplug entry's driver_data.
- *
- * Store this function in the HCD's struct pci_driver as probe().
- */
-int usb_hcd_pci_probe (struct pci_dev *dev, const struct pci_device_id *id)
-{
-       struct hc_driver        *driver;
-       unsigned long           resource, len;
-       void                    *base;
-       u8                      latency, limit;
-       struct usb_hcd          *hcd;
-       int                     retval, region;
-       char                    buf [8], *bufp = buf;
-
-       if (!id || !(driver = (struct hc_driver *) id->driver_data))
-               return -EINVAL;
-
-       if (pci_enable_device (dev) < 0)
-               return -ENODEV;
-       
-        if (!dev->irq) {
-               err ("Found HC with no IRQ.  Check BIOS/PCI %s setup!",
-                       dev->slot_name);
-               return -ENODEV;
-        }
-       
-       if (driver->flags & HCD_MEMORY) {       // EHCI, OHCI
-               region = 0;
-               resource = pci_resource_start (dev, 0);
-               len = pci_resource_len (dev, 0);
-               if (!request_mem_region (resource, len, driver->description)) {
-                       dbg ("controller already in use");
-                       return -EBUSY;
-               }
-               base = ioremap_nocache (resource, len);
-               if (base == NULL) {
-                       dbg ("error mapping memory");
-                       retval = -EFAULT;
-clean_1:
-                       release_mem_region (resource, len);
-                       err ("init %s fail, %d", dev->slot_name, retval);
-                       return retval;
-               }
-
-       } else {                                // UHCI
-               resource = len = 0;
-               for (region = 0; region < PCI_ROM_RESOURCE; region++) {
-                       if (!(pci_resource_flags (dev, region) & IORESOURCE_IO))
-                               continue;
-
-                       resource = pci_resource_start (dev, region);
-                       len = pci_resource_len (dev, region);
-                       if (request_region (resource, len,
-                                       driver->description))
-                               break;
-               }
-               if (region == PCI_ROM_RESOURCE) {
-                       dbg ("no i/o regions available");
-                       return -EBUSY;
-               }
-               base = (void *) resource;
-       }
-
-       // driver->start(), later on, will transfer device from
-       // control by SMM/BIOS to control by Linux (if needed)
-
-       pci_set_master (dev);
-       hcd = driver->hcd_alloc ();
-       if (hcd == NULL){
-               dbg ("hcd alloc fail");
-               retval = -ENOMEM;
-clean_2:
-               if (driver->flags & HCD_MEMORY) {
-                       iounmap (base);
-                       goto clean_1;
-               } else {
-                       release_region (resource, len);
-                       err ("init %s fail, %d", dev->slot_name, retval);
-                       return retval;
-               }
-       }
-       pci_set_drvdata(dev, hcd);
-       hcd->driver = driver;
-       hcd->description = driver->description;
-       hcd->pdev = dev;
-       info ("%s @ %s, %s", hcd->description,  dev->slot_name, dev->name);
-
-       pci_read_config_byte (dev, PCI_LATENCY_TIMER, &latency);
-       if (latency) {
-               pci_read_config_byte (dev, PCI_MAX_LAT, &limit);
-               if (limit && limit < latency) {
-                       dbg ("PCI latency reduced to max %d", limit);
-                       pci_write_config_byte (dev, PCI_LATENCY_TIMER, limit);
-               }
-       }
-
-#ifndef __sparc__
-       sprintf (buf, "%d", dev->irq);
-#else
-       bufp = __irq_itoa(dev->irq);
-#endif
-       if (request_irq (dev->irq, hcd_irq, SA_SHIRQ, hcd->description, hcd)
-                       != 0) {
-               err ("request interrupt %s failed", bufp);
-               retval = -EBUSY;
-               driver->hcd_free (hcd);
-               goto clean_2;
-       }
-       hcd->irq = dev->irq;
-
-       hcd->regs = base;
-       hcd->region = region;
-       info ("irq %s, %s %p", bufp,
-               (driver->flags & HCD_MEMORY) ? "pci mem" : "io base",
-               base);
-
-       usb_init_bus (&hcd->self);
-       hcd->self.op = &hcd_operations;
-       hcd->self.hcpriv = (void *) hcd;
-       hcd->self.bus_name = dev->slot_name;
-       hcd->product_desc = dev->name;
-
-       INIT_LIST_HEAD (&hcd->dev_list);
-
-       usb_register_bus (&hcd->self);
-
-       if ((retval = driver->start (hcd)) < 0)
-               usb_hcd_pci_remove (dev);
-
-       return retval;
-} 
-EXPORT_SYMBOL (usb_hcd_pci_probe);
-
-
-/* may be called without controller electrically present */
-/* may be called with controller, bus, and devices active */
-
-/**
- * usb_hcd_pci_remove - shutdown processing for PCI-based HCDs
- * @dev: USB Host Controller being removed
- * Context: !in_interrupt()
- *
- * Reverses the effect of usb_hcd_pci_probe(), first invoking
- * the HCD's stop() method.  It is always called from a thread
- * context, normally "rmmod", "apmd", or something similar.
- *
- * Store this function in the HCD's struct pci_driver as remove().
- */
-void usb_hcd_pci_remove (struct pci_dev *dev)
-{
-       struct usb_hcd          *hcd;
-       struct usb_device       *hub;
-
-       hcd = pci_get_drvdata(dev);
-       if (!hcd)
-               return;
-       info ("remove: %s, state %x", hcd->self.bus_name, hcd->state);
-
-       if (in_interrupt ()) BUG ();
-
-       hub = hcd->self.root_hub;
-       hcd->state = USB_STATE_QUIESCING;
-
-       dbg ("%s: roothub graceful disconnect", hcd->self.bus_name);
-       usb_disconnect (&hub);
-
-       hcd->driver->stop (hcd);
-       hcd->state = USB_STATE_HALT;
-
-       free_irq (hcd->irq, hcd);
-       if (hcd->driver->flags & HCD_MEMORY) {
-               iounmap (hcd->regs);
-               release_mem_region (pci_resource_start (dev, 0),
-                       pci_resource_len (dev, 0));
-       } else {
-               release_region (pci_resource_start (dev, hcd->region),
-                       pci_resource_len (dev, hcd->region));
-       }
-
-       usb_deregister_bus (&hcd->self);
-       if (atomic_read (&hcd->self.refcnt) != 1)
-               err ("usb_hcd_pci_remove %s, count != 1", hcd->self.bus_name);
-
-       hcd->driver->hcd_free (hcd);
-}
-EXPORT_SYMBOL (usb_hcd_pci_remove);
-
-
-#ifdef CONFIG_PM
-
-/*
- * Some "sleep" power levels imply updating struct usb_driver
- * to include a callback asking hcds to do their bit by checking
- * if all the drivers can suspend.  Gets involved with remote wakeup.
- *
- * If there are pending urbs, then HCs will need to access memory,
- * causing extra power drain.  New sleep()/wakeup() PM calls might
- * be needed, beyond PCI suspend()/resume().  The root hub timer
- * still be accessing memory though ...
- *
- * FIXME:  USB should have some power budgeting support working with
- * all kinds of hubs.
- *
- * FIXME:  This assumes only D0->D3 suspend and D3->D0 resume.
- * D1 and D2 states should do something, yes?
- *
- * FIXME:  Should provide generic enable_wake(), calling pci_enable_wake()
- * for all supported states, so that USB remote wakeup can work for any
- * devices that support it (and are connected via powered hubs).
- *
- * FIXME:  resume doesn't seem to work right any more...
- */
-
-
-// 2.4 kernels have issued concurrent resumes (w/APM)
-// we defend against that error; PCI doesn't yet.
-
-/**
- * usb_hcd_pci_suspend - power management suspend of a PCI-based HCD
- * @dev: USB Host Controller being suspended
- *
- * Store this function in the HCD's struct pci_driver as suspend().
- */
-int usb_hcd_pci_suspend (struct pci_dev *dev, u32 state)
-{
-       struct usb_hcd          *hcd;
-       int                     retval;
-
-       hcd = pci_get_drvdata(dev);
-       info ("suspend %s to state %d", hcd->self.bus_name, state);
-
-       pci_save_state (dev, hcd->pci_state);
-
-       // FIXME for all connected devices, leaf-to-root:
-       // driver->suspend()
-       // proposed "new 2.5 driver model" will automate that
-
-       /* driver may want to disable DMA etc */
-       retval = hcd->driver->suspend (hcd, state);
-       hcd->state = USB_STATE_SUSPENDED;
-
-       pci_set_power_state (dev, state);
-       return retval;
-}
-EXPORT_SYMBOL (usb_hcd_pci_suspend);
-
-/**
- * usb_hcd_pci_resume - power management resume of a PCI-based HCD
- * @dev: USB Host Controller being resumed
- *
- * Store this function in the HCD's struct pci_driver as resume().
- */
-int usb_hcd_pci_resume (struct pci_dev *dev)
-{
-       struct usb_hcd          *hcd;
-       int                     retval;
-
-       hcd = pci_get_drvdata(dev);
-       info ("resume %s", hcd->self.bus_name);
-
-       /* guard against multiple resumes (APM bug?) */
-       atomic_inc (&hcd->resume_count);
-       if (atomic_read (&hcd->resume_count) != 1) {
-               err ("concurrent PCI resumes for %s", hcd->self.bus_name);
-               retval = 0;
-               goto done;
-       }
-
-       retval = -EBUSY;
-       if (hcd->state != USB_STATE_SUSPENDED) {
-               dbg ("can't resume, not suspended!");
-               goto done;
-       }
-       hcd->state = USB_STATE_RESUMING;
-
-       pci_set_power_state (dev, 0);
-       pci_restore_state (dev, hcd->pci_state);
-
-       retval = hcd->driver->resume (hcd);
-       if (!HCD_IS_RUNNING (hcd->state)) {
-               dbg ("resume %s failure, retval %d", hcd->self.bus_name, retval);
-               hc_died (hcd);
-// FIXME:  recover, reset etc.
-       } else {
-               // FIXME for all connected devices, root-to-leaf:
-               // driver->resume ();
-               // proposed "new 2.5 driver model" will automate that
-       }
-
-done:
-       atomic_dec (&hcd->resume_count);
-       return retval;
-}
-EXPORT_SYMBOL (usb_hcd_pci_resume);
-
-#endif /* CONFIG_PM */
-
-#endif
-
-/*-------------------------------------------------------------------------*/
-
 /*
  * Generic HC operations.
  */
@@ -1285,37 +946,6 @@
 
 /*-------------------------------------------------------------------------*/
 
-static void hc_died (struct usb_hcd *hcd)
-{
-       struct list_head        *devlist, *urblist;
-       struct hcd_dev          *dev;
-       struct urb              *urb;
-       unsigned long           flags;
-       
-       /* flag every pending urb as done */
-       spin_lock_irqsave (&hcd_data_lock, flags);
-       list_for_each (devlist, &hcd->dev_list) {
-               dev = list_entry (devlist, struct hcd_dev, dev_list);
-               list_for_each (urblist, &dev->urb_list) {
-                       urb = list_entry (urblist, struct urb, urb_list);
-                       dbg ("shutdown %s urb %p pipe %x, current status %d",
-                               hcd->self.bus_name, urb, urb->pipe, urb->status);
-                       if (urb->status == -EINPROGRESS)
-                               urb->status = -ESHUTDOWN;
-               }
-       }
-       urb = (struct urb *) hcd->rh_timer.data;
-       if (urb)
-               urb->status = -ESHUTDOWN;
-       spin_unlock_irqrestore (&hcd_data_lock, flags);
-
-       if (urb)
-               rh_status_dequeue (hcd, urb);
-       hcd->driver->stop (hcd);
-}
-
-/*-------------------------------------------------------------------------*/
-
 static void urb_unlink (struct urb *urb)
 {
        unsigned long           flags;
@@ -1677,7 +1307,7 @@
        spin_unlock_irqrestore (&urb->lock, flags);
 
        if (urb == (struct urb *) hcd->rh_timer.data) {
-               rh_status_dequeue (hcd, urb);
+               usb_rh_status_dequeue (hcd, urb);
                retval = 0;
        } else {
                retval = hcd->driver->urb_dequeue (hcd, urb);
@@ -1751,28 +1381,13 @@
        return 0;
 }
 
-static struct usb_operations hcd_operations = {
+struct usb_operations hcd_operations = {
        allocate:               hcd_alloc_dev,
        get_frame_number:       hcd_get_frame_number,
        submit_urb:             hcd_submit_urb,
        unlink_urb:             hcd_unlink_urb,
        deallocate:             hcd_free_dev,
 };
-
-/*-------------------------------------------------------------------------*/
-
-static void hcd_irq (int irq, void *__hcd, struct pt_regs * r)
-{
-       struct usb_hcd          *hcd = __hcd;
-       int                     start = hcd->state;
-
-       if (unlikely (hcd->state == USB_STATE_HALT))    /* irq sharing? */
-               return;
-
-       hcd->driver->irq (hcd);
-       if (hcd->state != start && hcd->state == USB_STATE_HALT)
-               hc_died (hcd);
-}
 
 /*-------------------------------------------------------------------------*/
 
diff -Nru a/drivers/usb/core/hcd.h b/drivers/usb/core/hcd.h
--- a/drivers/usb/core/hcd.h    Thu Jun  6 14:38:23 2002
+++ b/drivers/usb/core/hcd.h    Thu Jun  6 14:38:23 2002
@@ -161,6 +161,11 @@
 };
 
 extern void usb_hcd_giveback_urb (struct usb_hcd *hcd, struct urb *urb);
+extern void usb_init_bus (struct usb_bus *bus);
+extern void usb_rh_status_dequeue (struct usb_hcd *hcd, struct urb *urb);
+
+extern spinlock_t hcd_data_lock;
+extern struct usb_operations hcd_operations;
 
 #ifdef CONFIG_PCI
 struct pci_dev;

_______________________________________________________________

Don't miss the 2002 Sprint PCS Application Developer's Conference
August 25-28 in Las Vegas -- http://devcon.sprintpcs.com/adp/index.cfm

_______________________________________________
[EMAIL PROTECTED]
To unsubscribe, use the last form field at:
https://lists.sourceforge.net/lists/listinfo/linux-usb-devel

Reply via email to