# 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.471 -> 1.472 # drivers/usb/core/hcd.h 1.9 -> 1.10 # drivers/usb/core/hcd-pci.c 1.1 -> 1.2 # drivers/usb/core/hcd.c 1.23 -> 1.24 # # The following is the BitKeeper ChangeSet Log # -------------------------------------------- # 02/06/07 greg@kroah.com 1.472 # USB: hcd cleanups and documentation # # Implement many of the hcd cleanups that David Brownell had previously submitted. # -------------------------------------------- # diff -Nru a/drivers/usb/core/hcd-pci.c b/drivers/usb/core/hcd-pci.c --- a/drivers/usb/core/hcd-pci.c Sat Jun 8 15:15:58 2002 +++ b/drivers/usb/core/hcd-pci.c Sat Jun 8 15:15:58 2002 @@ -1,10 +1,4 @@ /* - * (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 @@ -39,8 +33,6 @@ /* 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); /*-------------------------------------------------------------------------*/ @@ -156,7 +148,7 @@ #else bufp = __irq_itoa(dev->irq); #endif - if (request_irq (dev->irq, hcd_irq, SA_SHIRQ, hcd->description, hcd) + if (request_irq (dev->irq, usb_hcd_irq, SA_SHIRQ, hcd->description, hcd) != 0) { err ("request interrupt %s failed", bufp); retval = -EBUSY; @@ -171,8 +163,8 @@ (driver->flags & HCD_MEMORY) ? "pci mem" : "io base", base); - usb_init_bus (&hcd->self); - hcd->self.op = &hcd_operations; + usb_bus_init (&hcd->self); + hcd->self.op = &usb_hcd_operations; hcd->self.hcpriv = (void *) hcd; hcd->self.bus_name = dev->slot_name; hcd->product_desc = dev->name; @@ -336,7 +328,7 @@ 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); + usb_hc_died (hcd); // FIXME: recover, reset etc. } else { // FIXME for all connected devices, root-to-leaf: @@ -351,51 +343,5 @@ 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 Sat Jun 8 15:15:58 2002 +++ b/drivers/usb/core/hcd.c Sat Jun 8 15:15:58 2002 @@ -92,9 +92,7 @@ DECLARE_MUTEX (usb_bus_list_lock); /* exported only for usbfs */ /* used when updating hcd data */ -spinlock_t hcd_data_lock = SPIN_LOCK_UNLOCKED; - -struct usb_operations hcd_operations; +static spinlock_t hcd_data_lock = SPIN_LOCK_UNLOCKED; /*-------------------------------------------------------------------------*/ @@ -571,8 +569,14 @@ /*-------------------------------------------------------------------------*/ -/* shared initialization code */ -void usb_init_bus (struct usb_bus *bus) +/** + * usb_bus_init - shared initialization code + * @bus: the bus structure being initialized + * + * This code is used to initialize a usb_bus structure, memory for which is + * separately managed. + */ +void usb_bus_init (struct usb_bus *bus) { memset (&bus->devmap, 0, sizeof(struct usb_devmap)); @@ -591,6 +595,7 @@ atomic_set (&bus->refcnt, 1); } +EXPORT_SYMBOL (usb_bus_init); /** * usb_alloc_bus - creates a new USB host controller structure @@ -611,7 +616,7 @@ bus = kmalloc (sizeof *bus, GFP_KERNEL); if (!bus) return NULL; - usb_init_bus (bus); + usb_bus_init (bus); bus->op = op; return bus; } @@ -1226,13 +1231,21 @@ return 0; } -struct usb_operations hcd_operations = { +/** + * usb_hcd_operations - adapts usb_bus framework to HCD framework (bus glue) + * + * When registering a USB bus through the HCD framework code, use this + * usb_operations vector. The PCI glue layer does so automatically; only + * bus glue for non-PCI system busses will need to use this. + */ +struct usb_operations usb_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, }; +EXPORT_SYMBOL (usb_hcd_operations); /*-------------------------------------------------------------------------*/ @@ -1272,3 +1285,70 @@ usb_put_urb (urb); } EXPORT_SYMBOL (usb_hcd_giveback_urb); + +/*-------------------------------------------------------------------------*/ + +/** + * usb_hcd_irq - hook IRQs to HCD framework (bus glue) + * @irq: the IRQ being raised + * @__hcd: pointer to the HCD whose IRQ is beinng signaled + * @r: saved hardware registers (not passed to HCD) + * + * When registering a USB bus through the HCD framework code, use this + * to handle interrupts. The PCI glue layer does so automatically; only + * bus glue for non-PCI system busses will need to use this. + */ +void usb_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) + usb_hc_died (hcd); +} +EXPORT_SYMBOL (usb_hcd_irq); + +/*-------------------------------------------------------------------------*/ + +/** + * usb_hc_died - report abnormal shutdown of a host controller (bus glue) + * @hcd: pointer to the HCD representing the controller + * + * This is called by bus glue to report a USB host controller that died + * while operations may still have been pending. It's called automatically + * by the PCI glue, so only glue for non-PCI busses should need to call it. + */ +void usb_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); +} +EXPORT_SYMBOL (usb_hc_died); + diff -Nru a/drivers/usb/core/hcd.h b/drivers/usb/core/hcd.h --- a/drivers/usb/core/hcd.h Sat Jun 8 15:15:58 2002 +++ b/drivers/usb/core/hcd.h Sat Jun 8 15:15:58 2002 @@ -161,12 +161,9 @@ }; 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_bus_init (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; struct pci_device_id; @@ -183,6 +180,11 @@ #endif /* CONFIG_PM */ #endif /* CONFIG_PCI */ + +/* generic bus glue, needed for host controllers that don't use PCI */ +extern struct usb_operations usb_hcd_operations; +extern void usb_hcd_irq (int irq, void *__hcd, struct pt_regs *r); +extern void usb_hc_died (struct usb_hcd *hcd); /* -------------------------------------------------------------------------- */