bk://kernel.bkbits.net/gregkh/linux/usb-2.6
gregkh@suse.de|ChangeSet|20050323232640|61922 gregkh

# This is a BitKeeper generated diff -Nru style patch.
#
# ChangeSet
#   2005/03/23 15:26:40-08:00 gregkh@suse.de 
#   USB: fix bug in visor driver with throttle/unthrottle causing oopses.
#   
#   Thanks to Mark Lord <mlord@pobox.com> for reporting this and helping with testing.
#   
#   Signed-off-by: Greg Kroah-Hartman <gregkh@suse.de>
# 
# drivers/usb/serial/visor.c
#   2005/03/23 15:26:23-08:00 gregkh@suse.de +27 -11
#   USB: fix bug in visor driver with throttle/unthrottle causing oopses.
#   
#   Thanks to Mark Lord <mlord@pobox.com> for reporting this and helping with testing.
#   
#   Signed-off-by: Greg Kroah-Hartman <gregkh@suse.de>
# 
# ChangeSet
#   2005/03/21 22:36:57-08:00 stern@rowland.harvard.edu 
#   [PATCH] UHCI updates
#   
#   This is the fifth of five updates to the uhci-hcd driver:
#   
#   	Separate out the part of the driver responsible for scanning the
#   	schedule and doing delayed processing.  Put it in a new routine
#   	which can be called as needed (such as when the controller is
#   	suspended) from several places in addition to the usual IRQ
#   	handler.
#   
#   Signed-off-by: Alan Stern <stern@rowland.harvard.edu>
#   Signed-off-by: Greg Kroah-Hartman <gregkh@suse.de>
# 
# drivers/usb/host/uhci-q.c
#   2005/03/14 10:01:36-08:00 stern@rowland.harvard.edu +55 -0
#   UHCI updates
# 
# drivers/usb/host/uhci-hcd.h
#   2005/03/14 10:01:36-08:00 stern@rowland.harvard.edu +4 -1
#   UHCI updates
# 
# drivers/usb/host/uhci-hcd.c
#   2005/03/14 10:01:36-08:00 stern@rowland.harvard.edu +6 -60
#   UHCI updates
# 
# ChangeSet
#   2005/03/21 22:36:17-08:00 stern@rowland.harvard.edu 
#   [PATCH] UHCI updates
#   
#   This is the fourth of five updates to the uhci-hcd driver:
#   
#   	Reimplement the get_current_frame routines so that when the
#   	controller isn't running they return a cached value.  Also add
#   	a flag to track whether the controller is running and allow
#   	critical data structure updates to occur immediately if the
#   	controller is stopped.
#   
#   Signed-off-by: Alan Stern <stern@rowland.harvard.edu>
#   Signed-off-by: Greg Kroah-Hartman <gregkh@suse.de>
# 
# drivers/usb/host/uhci-q.c
#   2005/03/21 22:33:16-08:00 stern@rowland.harvard.edu +14 -17
#   UHCI updates
# 
# drivers/usb/host/uhci-hcd.h
#   2005/03/21 22:33:16-08:00 stern@rowland.harvard.edu +3 -1
#   UHCI updates
# 
# drivers/usb/host/uhci-hcd.c
#   2005/03/21 22:34:27-08:00 stern@rowland.harvard.edu +35 -16
#   UHCI updates
# 
# ChangeSet
#   2005/03/21 22:30:56-08:00 stern@rowland.harvard.edu 
#   [PATCH] UHCI updates
#   
#   This is the third of five updates to the uhci-hcd driver:
#   
#   	Change the first argument to uhci_finish_completion from hcd
#   	to uhci and expand the spinlock-protected region to include
#   	the entire timer callback routine plus the suspend and resume
#   	routines.  It's a little awkward that the reset routine must
#   	run without the spinlock, but that whole pathway will vanish
#   	before long.
#   
#   Signed-off-by: Alan Stern <stern@rowland.harvard.edu>
#   Signed-off-by: Greg Kroah-Hartman <gregkh@suse.de>
# 
# drivers/usb/host/uhci-q.c
#   2005/03/14 09:53:09-08:00 stern@rowland.harvard.edu +2 -3
#   UHCI updates
# 
# drivers/usb/host/uhci-hcd.c
#   2005/03/14 09:53:09-08:00 stern@rowland.harvard.edu +18 -5
#   UHCI updates
# 
# ChangeSet
#   2005/03/21 22:27:09-08:00 stern@rowland.harvard.edu 
#   [PATCH] UHCI updates
#   
#   This is the second of five updates to the uhci-hcd driver:
#   
#   	Reimplement the port reset function by splitting it into two
#   	parts like the other HC drivers do, where the second part is
#   	triggered by a port status request when the reset finishes.  Now
#   	the entire hub_control routine can run without sleeping and can
#   	hold the device spinlock.
#   
#   Signed-off-by: Alan Stern <stern@rowland.harvard.edu>
#   Signed-off-by: Greg Kroah-Hartman <gregkh@suse.de>
# 
# drivers/usb/host/uhci-hub.c
#   2005/03/14 09:30:15-08:00 stern@rowland.harvard.edu +30 -16
#   UHCI updates
# 
# drivers/usb/host/uhci-hcd.h
#   2005/03/14 09:30:15-08:00 stern@rowland.harvard.edu +2 -2
#   UHCI updates
# 
# drivers/usb/host/uhci-hcd.c
#   2005/03/14 09:30:15-08:00 stern@rowland.harvard.edu +1 -1
#   UHCI updates
# 
# ChangeSet
#   2005/03/21 22:26:12-08:00 stern@rowland.harvard.edu 
#   [PATCH] UHCI updates
#   
#   This is the first of five updates to the uhci-hcd driver:
#   
#   	Rename the uhci->schedule_lock to just plain uhci->lock.
#   	Originally I had thought of adding a separate device-management
#   	lock, but now it seems better to use a single lock for both
#   	purposes.
#   
#   Signed-off-by: Alan Stern <stern@rowland.harvard.edu>
#   Signed-off-by: Greg Kroah-Hartman <gregkh@suse.de>
# 
# drivers/usb/host/uhci-q.c
#   2005/03/14 09:26:50-08:00 stern@rowland.harvard.edu +8 -8
#   UHCI updates
# 
# drivers/usb/host/uhci-hcd.h
#   2005/03/14 09:26:50-08:00 stern@rowland.harvard.edu +12 -12
#   UHCI updates
# 
# drivers/usb/host/uhci-hcd.c
#   2005/03/14 09:26:50-08:00 stern@rowland.harvard.edu +7 -7
#   UHCI updates
# 
# drivers/usb/host/uhci-debug.c
#   2005/03/14 09:26:50-08:00 stern@rowland.harvard.edu +2 -2
#   UHCI updates
# 
# ChangeSet
#   2005/03/21 22:24:51-08:00 stern@rowland.harvard.edu 
#   [PATCH] USBcore updates
#   
#   This is the fifth of five updates to usbcore:
#   
#   	Add some extra debugging messages to the hub driver and make it
#   	set the power state for root hubs like it does for external hubs.
#   
#   Signed-off-by: Alan Stern <stern@rowland.harvard.edu>
#   Signed-off-by: Greg Kroah-Hartman <gregkh@suse.de>
# 
# drivers/usb/core/hub.c
#   2005/03/14 07:26:56-08:00 stern@rowland.harvard.edu +11 -2
#   USBcore updates
# 
# ChangeSet
#   2005/03/21 15:04:00-08:00 stern@rowland.harvard.edu 
#   [PATCH] USBcore updates
#   
#   This is the fourth of five updates to usbcore:
#   
#   	Add a new usb_hcd_resume_root_hub function for use by HCDs in
#   	processing resume requests from their root hubs.  No calls to
#   	this new routine are in the patch but they will be added in
#   	due course.
#   
#   Signed-off-by: Alan Stern <stern@rowland.harvard.edu>
#   Signed-off-by: Greg Kroah-Hartman <gregkh@suse.de>
# 
# drivers/usb/core/usb.h
#   2005/03/21 15:00:03-08:00 stern@rowland.harvard.edu +1 -0
#   USBcore updates
# 
# drivers/usb/core/hub.h
#   2005/03/21 15:00:03-08:00 stern@rowland.harvard.edu +1 -0
#   USBcore updates
# 
# drivers/usb/core/hub.c
#   2005/03/21 15:00:03-08:00 stern@rowland.harvard.edu +14 -0
#   USBcore updates
# 
# drivers/usb/core/hcd.h
#   2005/03/21 15:00:03-08:00 stern@rowland.harvard.edu +2 -0
#   USBcore updates
# 
# drivers/usb/core/hcd.c
#   2005/03/21 15:01:10-08:00 stern@rowland.harvard.edu +24 -0
#   USBcore updates
# 
# ChangeSet
#   2005/03/21 14:58:02-08:00 stern@rowland.harvard.edu 
#   [PATCH] USBcore updates
#   
#   This is the third of five updates to usbcore:
#   
#   	Adjust the usb_hc_died routine to eliminate races with root-hub
#   	registration/deregistration and have it tell khubd to remove
#   	all devices below the root hub.
#   
#   Signed-off-by: Alan Stern <stern@rowland.harvard.edu>
#   Signed-off-by: Greg Kroah-Hartman <gregkh@suse.de>
# 
# drivers/usb/core/usb.h
#   2005/03/14 07:19:06-08:00 stern@rowland.harvard.edu +2 -0
#   USBcore updates
# 
# drivers/usb/core/hub.c
#   2005/03/14 07:19:06-08:00 stern@rowland.harvard.edu +16 -1
#   USBcore updates
# 
# drivers/usb/core/hcd.h
#   2005/03/14 07:19:06-08:00 stern@rowland.harvard.edu +2 -0
#   USBcore updates
# 
# drivers/usb/core/hcd.c
#   2005/03/14 07:19:06-08:00 stern@rowland.harvard.edu +29 -3
#   USBcore updates
# 
# ChangeSet
#   2005/03/21 14:43:56-08:00 stern@rowland.harvard.edu 
#   [PATCH] USBcore and HCD updates
#   
#   This is the second of five updates to usbcore:
#   
#   	Rename the hcd->state constants so that they all begin with
#   	HC_STATE.  Right now some of them start with HCD_STATE and
#   	others with USB_STATE, which can be very confusing.
#   
#   Signed-off-by: Alan Stern <stern@rowland.harvard.edu>
#   Signed-off-by: Greg Kroah-Hartman <gregkh@suse.de>
# 
# drivers/usb/host/uhci-hcd.c
#   2005/03/21 14:28:32-08:00 stern@rowland.harvard.edu +2 -2
#   USBcore and HCD updates
# 
# drivers/usb/host/sl811-hcd.c
#   2005/03/21 14:29:26-08:00 stern@rowland.harvard.edu +3 -3
#   USBcore and HCD updates
# 
# drivers/usb/host/ohci.h
#   2005/03/21 14:28:32-08:00 stern@rowland.harvard.edu +1 -1
#   USBcore and HCD updates
# 
# drivers/usb/host/ohci-q.c
#   2005/03/21 14:28:32-08:00 stern@rowland.harvard.edu +5 -5
#   USBcore and HCD updates
# 
# drivers/usb/host/ohci-omap.c
#   2005/03/21 14:28:32-08:00 stern@rowland.harvard.edu +1 -1
#   USBcore and HCD updates
# 
# drivers/usb/host/ohci-hub.c
#   2005/03/21 14:28:32-08:00 stern@rowland.harvard.edu +7 -7
#   USBcore and HCD updates
# 
# drivers/usb/host/ohci-hcd.c
#   2005/03/21 14:28:32-08:00 stern@rowland.harvard.edu +9 -9
#   USBcore and HCD updates
# 
# drivers/usb/host/ehci-sched.c
#   2005/03/21 14:28:32-08:00 stern@rowland.harvard.edu +6 -6
#   USBcore and HCD updates
# 
# drivers/usb/host/ehci-q.c
#   2005/03/21 14:28:32-08:00 stern@rowland.harvard.edu +7 -7
#   USBcore and HCD updates
# 
# drivers/usb/host/ehci-hub.c
#   2005/03/21 14:28:32-08:00 stern@rowland.harvard.edu +5 -5
#   USBcore and HCD updates
# 
# drivers/usb/host/ehci-hcd.c
#   2005/03/21 14:28:32-08:00 stern@rowland.harvard.edu +12 -12
#   USBcore and HCD updates
# 
# drivers/usb/gadget/dummy_hcd.c
#   2005/03/21 14:28:32-08:00 stern@rowland.harvard.edu +2 -2
#   USBcore and HCD updates
# 
# drivers/usb/core/hcd.h
#   2005/03/21 14:28:32-08:00 stern@rowland.harvard.edu +7 -7
#   USBcore and HCD updates
# 
# drivers/usb/core/hcd.c
#   2005/03/21 14:28:32-08:00 stern@rowland.harvard.edu +11 -11
#   USBcore and HCD updates
# 
# drivers/usb/core/hcd-pci.c
#   2005/03/21 14:28:32-08:00 stern@rowland.harvard.edu +7 -7
#   USBcore and HCD updates
# 
# ChangeSet
#   2005/03/18 15:08:47-08:00 stern@rowland.harvard.edu 
#   [PATCH] USBcore updates
#   
#   This is the first of five updates to usbcore:
#   
#   	Merge the hcd_register_root macro with the usb_register_root_hub
#   	function.  This is part of the ongoing campaign to flatten out
#   	the hcd glue layer.
#   
#   Signed-off-by: Alan Stern <stern@rowland.harvard.edu>
#   Signed-off-by: Greg Kroah-Hartman <gregkh@suse.de>
# 
# drivers/usb/host/uhci-hcd.c
#   2005/03/18 14:22:27-08:00 stern@rowland.harvard.edu +1 -1
#   USBcore updates
# 
# drivers/usb/host/sl811-hcd.c
#   2005/03/18 14:22:27-08:00 stern@rowland.harvard.edu +1 -1
#   USBcore updates
# 
# drivers/usb/host/ohci-hcd.c
#   2005/03/18 14:22:27-08:00 stern@rowland.harvard.edu +1 -1
#   USBcore updates
# 
# drivers/usb/host/ehci-hcd.c
#   2005/03/18 14:22:27-08:00 stern@rowland.harvard.edu +1 -1
#   USBcore updates
# 
# drivers/usb/gadget/dummy_hcd.c
#   2005/03/18 14:22:27-08:00 stern@rowland.harvard.edu +1 -1
#   USBcore updates
# 
# drivers/usb/core/hcd.h
#   2005/03/18 14:22:27-08:00 stern@rowland.harvard.edu +2 -19
#   USBcore updates
# 
# drivers/usb/core/hcd.c
#   2005/03/18 14:23:34-08:00 stern@rowland.harvard.edu +15 -6
#   USBcore updates
# 
# ChangeSet
#   2005/03/18 13:56:40-08:00 olh@suse.de 
#   [PATCH] USB: another broken usb floppy
#   
#   Signed-off-by: Olaf Hering <olh@suse.de>
#   Signed-off-by: Phil Dibowitz <phil@ipom.com>
#   Signed-off-by: Greg Kroah-Hartman <gregkh@suse.de>
# 
# drivers/usb/storage/unusual_devs.h
#   2005/03/18 13:53:59-08:00 olh@suse.de +7 -0
#   USB: another broken usb floppy
# 
# ChangeSet
#   2005/03/18 13:51:56-08:00 phil@ipom.com 
#   [PATCH] USB unusual_devs: add another datafab device
#   
#   The following was reported by Josef Reisinger
#   <josef.reisinger@netcologne.de>. This entry allows the device to be
#   found and prevents it from showing up twice.
#   
#   Signed-off-by: Phil Dibowitz <phil@ipom.com>
#   Signed-off-by: Greg Kroah-Hartman <gregkh@suse.de>
# 
# drivers/usb/storage/unusual_devs.h
#   2005/01/01 22:31:04-08:00 phil@ipom.com +7 -0
#   USB unusual_devs: add another datafab device
# 
# ChangeSet
#   2005/03/18 13:51:36-08:00 phil@ipom.com 
#   [PATCH] USB unusual_devs: Add another Tekom entry
#   
#   This patch adds support for Another "Tekom 300" camera - or more
#   specifically a BenQ DC5330.
#   
#   Versions of this patch were submitted by both Frank Copeland
#   <fjc@thingy.apana.org.au> and Manuel Fombuena <mfombuena@ya.com> - but
#   neither were quite right, so I've tweaked it accordingly.
#   
#   Signed-off-by: Phil Dibowitz <phil@ipom.com>
#   Signed-off-by: Greg Kroah-Hartman <gregkh@suse.de>
# 
# drivers/usb/storage/unusual_devs.h
#   2005/03/13 21:18:47-08:00 phil@ipom.com +9 -0
#   USB unusual_devs: Add another Tekom entry
# 
# ChangeSet
#   2005/03/18 13:51:17-08:00 gmenguez@usuarios.retecal.es 
#   [PATCH] USB: Support for new ipod mini (and possibly others) + usb
#   
#   Just a little patch to unusual_devs.h in usb-storage in order to support
#   new ipods mini (ie. the new 6 gig model) and possibly other new big
#   models reported to have problems through usb in linux 2.6.
#   
#   
#   From: Guillermo Menguez Alvarez <gmenguez@usuarios.retecal.es>
#   Signed-off-by: Phil Dibowitz <phil@ipom.com>
#   Signed-off-by: Greg Kroah-Hartman <gregkh@suse.de>
# 
# drivers/usb/storage/unusual_devs.h
#   2005/03/12 06:54:43-08:00 gmenguez@usuarios.retecal.es +6 -0
#   USB: Support for new ipod mini (and possibly others) + usb
# 
# ChangeSet
#   2005/03/18 13:40:24-08:00 clemens@ladisch.de 
#   [PATCH] emi26: add another product ID for the Emi2|6/A26
#   
#   This adds the product ID for another hardware revision of the Emi 2|6.
#   Except for the ID, this device behaves the same and uses the same
#   firmware.
#   
#   Signed-off-by: Clemens Ladisch <clemens@ladisch.de>
#   Signed-off-by: Greg Kroah-Hartman <gregkh@suse.de>
# 
# drivers/usb/misc/emi26.c
#   2005/03/12 09:19:39-08:00 clemens@ladisch.de +2 -0
#   emi26: add another product ID for the Emi2|6/A26
# 
# ChangeSet
#   2005/03/17 18:15:50-08:00 gregkh@suse.de 
#   [PATCH] USB Storage: remove unneeded unusual_devs.h entry.
#   
#   Signed-off-by: Greg Kroah-Hartman <gregkh@suse.de>
# 
# drivers/usb/storage/unusual_devs.h
#   2005/03/17 18:12:25-08:00 gregkh@suse.de +0 -6
#   USB Storage: remove unneeded unusual_devs.h entry.
# 
# ChangeSet
#   2005/03/17 18:15:30-08:00 mdharm-usb@one-eyed-alien.net 
#   [PATCH] USB Storage: change how unusual_devs.h flags are defined
#   
#   This patch started life as as473 from Alan Stern, and has been rediffed
#   against the current tip.
#   
#   This patch changes the way the flags bits are defined, so that the
#   proc_info routine can automatically list all the flags that are set.  As a
#   side effect it will also include the NEED_OVERRIDE flag; that shouldn't
#   really matter.  (As another side effect, the definitions grew too long to
#   fit on a single 80-character line so I had to wrap the comments.)
#   
#   This patch also takes the opportunity to remove a couple of obsolete flags
#   and to renumber the bit values.  The patch also removes an unusual_devs
#   entry whose only purpose was to set one of those obsolete flags; apparently
#   it got left behind when all the other uses of those flags were removed.
#   
#   Signed-off-by: Alan Stern <stern@rowland.harvard.edu>
#   Signed-off-by: Matthew Dharm <mdharm-usb@one-eyed-alien.net>
#   Signed-off-by: Greg Kroah-Hartman <gregkh@suse.de>
# 
# drivers/usb/storage/usb.h
#   2005/03/13 21:34:07-08:00 mdharm-usb@one-eyed-alien.net +27 -12
#   USB Storage: change how unusual_devs.h flags are defined
# 
# drivers/usb/storage/scsiglue.c
#   2005/03/13 21:34:07-08:00 mdharm-usb@one-eyed-alien.net +4 -6
#   USB Storage: change how unusual_devs.h flags are defined
# 
# ChangeSet
#   2005/03/17 18:15:11-08:00 rddunlap@osdl.org 
#   [PATCH] pwc: fix printk arg types
#   
#   Fix gcc printk arg type warnings:
#   drivers/usb/media/pwc/pwc-if.c:325: warning: int format, different type arg (arg 2)
#   drivers/usb/media/pwc/pwc-if.c:1182: warning: int format, different type arg (arg 4)
#   
#   Signed-off-by: Randy Dunlap <rddunlap@osdl.org>
#   Signed-off-by: Greg Kroah-Hartman <gregkh@suse.de>
# 
# drivers/usb/media/pwc/pwc-if.c
#   2005/03/14 12:04:31-08:00 rddunlap@osdl.org +2 -2
#   pwc: fix printk arg types
# 
# ChangeSet
#   2005/03/17 18:14:52-08:00 rddunlap@osdl.org 
#   [PATCH] sisusb: fix arg. types
#   
#   Fix gcc printk arg type and other function parameter warnings:
#   
#   drivers/usb/misc/sisusbvga/sisusb.c: In function `sisusb_send_packet':
#   drivers/usb/misc/sisusbvga/sisusb.c:583: warning: passing arg 7 of `sisusb_send_bulk_msg' from incompatible pointer type
#   drivers/usb/misc/sisusbvga/sisusb.c:591: warning: passing arg 6 of `sisusb_recv_bulk_msg' from incompatible pointer type
#   drivers/usb/misc/sisusbvga/sisusb.c: In function `sisusb_send_bridge_packet':
#   drivers/usb/misc/sisusbvga/sisusb.c:620: warning: passing arg 7 of `sisusb_send_bulk_msg' from incompatible pointer type
#   drivers/usb/misc/sisusbvga/sisusb.c:628: warning: passing arg 6 of `sisusb_recv_bulk_msg' from incompatible pointer type
#   drivers/usb/misc/sisusbvga/sisusb.c: In function `sisusb_write_mem_bulk':
#   drivers/usb/misc/sisusbvga/sisusb.c:989: warning: int format, different type arg (arg 3)
#   drivers/usb/misc/sisusbvga/sisusb.c:989: warning: int format, different type arg (arg 3)
#   drivers/usb/misc/sisusbvga/sisusb.c: In function `sisusb_clear_vram':
#   drivers/usb/misc/sisusbvga/sisusb.c:1407: warning: passing arg 7 of `sisusb_write_mem_bulk' from incompatible pointer type
#   
#   Signed-off-by: Randy Dunlap <rddunlap@osdl.org>
#   Signed-off-by: Thomas Winischhofer <thomas@winischhofer.net>
#   Signed-off-by: Greg Kroah-Hartman <gregkh@suse.de>
# 
# drivers/usb/misc/sisusbvga/sisusb.c
#   2005/03/14 11:57:23-08:00 rddunlap@osdl.org +5 -4
#   sisusb: fix arg. types
# 
# ChangeSet
#   2005/03/17 18:14:33-08:00 mdharm-usb@one-eyed-alien.net 
#   [PATCH] USB Storage: remove unneeded NULL tests
#   
#   This patch started life as as472 from Alan Stern, and has been rediffed
#   against the current tip.
#   
#   This patch simply removes some unnecessary NULL checking before kfree()
#   calls.
#   
#   Signed-off-by: Alan Stern <stern@rowland.harvard.edu>
#   Signed-off-by: Matthew Dharm <mdharm-usb@one-eyed-alien.net>
#   Signed-off-by: Greg Kroah-Hartman <gregkh@suse.de>
# 
# drivers/usb/storage/usb.c
#   2005/03/13 21:34:20-08:00 mdharm-usb@one-eyed-alien.net +2 -5
#   USB Storage: remove unneeded NULL tests
# 
# ChangeSet
#   2005/03/17 18:14:14-08:00 mdharm-usb@one-eyed-alien.net 
#   [PATCH] USB Storage: Header reorganization
#   
#   This patch started life as as471 from Alan Stern, and has been regenerated
#   against the current tip.
#   
#   This patch cleans up the use of header files.  Primarily it makes sure
#   that "usb.h" is included before any of the other local headers.  It also
#   removes some unnecessary declarations of struct us_data and struct
#   scsi_cmnd, and it moves the inclusion of <scsi/scsi_host> to usb.h where
#   it will be needed by a later patch.
#   
#   
#   Signed-off-by: Alan Stern <stern@rowland.harvard.edu>
#   Signed-off-by: Matthew Dharm <mdharm-usb@one-eyed-alien.net>
#   Signed-off-by: Greg Kroah-Hartman <gregkh@suse.de>
# 
# drivers/usb/storage/usb.h
#   2005/03/13 21:34:34-08:00 mdharm-usb@one-eyed-alien.net +1 -0
#   USB Storage: Header reorganization
# 
# drivers/usb/storage/usb.c
#   2005/03/13 21:34:34-08:00 mdharm-usb@one-eyed-alien.net +3 -4
#   USB Storage: Header reorganization
# 
# drivers/usb/storage/transport.h
#   2005/03/13 21:34:34-08:00 mdharm-usb@one-eyed-alien.net +0 -3
#   USB Storage: Header reorganization
# 
# drivers/usb/storage/transport.c
#   2005/03/13 21:34:34-08:00 mdharm-usb@one-eyed-alien.net +1 -1
#   USB Storage: Header reorganization
# 
# drivers/usb/storage/shuttle_usbat.c
#   2005/03/13 21:34:34-08:00 mdharm-usb@one-eyed-alien.net +1 -1
#   USB Storage: Header reorganization
# 
# drivers/usb/storage/sddr55.c
#   2005/03/13 21:34:34-08:00 mdharm-usb@one-eyed-alien.net +1 -1
#   USB Storage: Header reorganization
# 
# drivers/usb/storage/sddr09.c
#   2005/03/13 21:34:34-08:00 mdharm-usb@one-eyed-alien.net +1 -1
#   USB Storage: Header reorganization
# 
# drivers/usb/storage/scsiglue.h
#   2005/03/13 21:34:34-08:00 mdharm-usb@one-eyed-alien.net +0 -5
#   USB Storage: Header reorganization
# 
# drivers/usb/storage/scsiglue.c
#   2005/03/13 21:34:34-08:00 mdharm-usb@one-eyed-alien.net +1 -2
#   USB Storage: Header reorganization
# 
# drivers/usb/storage/protocol.h
#   2005/03/13 21:34:34-08:00 mdharm-usb@one-eyed-alien.net +0 -3
#   USB Storage: Header reorganization
# 
# drivers/usb/storage/protocol.c
#   2005/03/13 21:34:34-08:00 mdharm-usb@one-eyed-alien.net +2 -1
#   USB Storage: Header reorganization
# 
# drivers/usb/storage/jumpshot.c
#   2005/03/13 21:34:34-08:00 mdharm-usb@one-eyed-alien.net +1 -1
#   USB Storage: Header reorganization
# 
# drivers/usb/storage/isd200.c
#   2005/03/13 21:34:34-08:00 mdharm-usb@one-eyed-alien.net +1 -1
#   USB Storage: Header reorganization
# 
# drivers/usb/storage/initializers.c
#   2005/03/13 21:34:34-08:00 mdharm-usb@one-eyed-alien.net +2 -0
#   USB Storage: Header reorganization
# 
# drivers/usb/storage/freecom.c
#   2005/03/13 21:34:34-08:00 mdharm-usb@one-eyed-alien.net +1 -1
#   USB Storage: Header reorganization
# 
# drivers/usb/storage/dpcm.c
#   2005/03/13 21:34:34-08:00 mdharm-usb@one-eyed-alien.net +1 -1
#   USB Storage: Header reorganization
# 
# drivers/usb/storage/debug.h
#   2005/03/13 21:34:34-08:00 mdharm-usb@one-eyed-alien.net +0 -2
#   USB Storage: Header reorganization
# 
# drivers/usb/storage/datafab.c
#   2005/03/13 21:34:34-08:00 mdharm-usb@one-eyed-alien.net +1 -1
#   USB Storage: Header reorganization
# 
# ChangeSet
#   2005/03/17 18:13:54-08:00 okir@suse.de 
#   [PATCH] USB: fix uhci irq 10: nobody cared! error
#   
#   From: Olaf Kirch <okir@suse.de>
#   Signed-off-by: Greg Kroah-Hartman <gregkh@suse.de>
# 
# drivers/usb/host/uhci-hcd.c
#   2005/03/17 16:00:00-08:00 okir@suse.de +3 -1
#   USB: fix uhci irq 10: nobody cared! error
# 
# ChangeSet
#   2005/03/17 18:13:34-08:00 domen@coderock.org 
#   [PATCH] USB: compile warning cleanup
#   
#   compile warning cleanup - handle error return from
#   scsi_add_host
#   
#   Signed-off-by: Stephen Biggs <yrgrknmxpzlk@gawab.com>
#   Signed-off-by: Domen Puncer <domen@coderock.org>
#   Signed-off-by: Greg Kroah-Hartman <gregkh@suse.de>
# 
# drivers/usb/image/microtek.c
#   2005/03/05 07:13:09-08:00 domen@coderock.org +6 -2
#   USB: compile warning cleanup
# 
# ChangeSet
#   2005/03/17 18:13:15-08:00 domen@coderock.org 
#   [PATCH] usb/digi_acceleport: remove interruptible_sleep_on_timeout() usage
#   
#   Replace deprecated interruptible_sleep_on_timeout() with direct
#   wait-queue usage. Also replace some rather odd wait-queue usage with the
#   existent macros. Also adjusted the wake_up_interruptible() call appropriately,
#   as I changed all the states to TASK_UNINTERRUPTIBLE (signals were not be checked
#   in the current code). Patch is compile-tested.
#   
#   Signed-off-by: Nishanth Aravamudan <nacc@us.ibm.com>
#   Signed-off-by: Domen Puncer <domen@coderock.org>
#   Signed-off-by: Greg Kroah-Hartman <gregkh@suse.de>
# 
# drivers/usb/serial/digi_acceleport.c
#   2005/03/05 07:12:12-08:00 domen@coderock.org +11 -18
#   usb/digi_acceleport: remove interruptible_sleep_on_timeout() usage
# 
# ChangeSet
#   2005/03/17 18:12:55-08:00 domen@coderock.org 
#   [PATCH] usb/rio500: remove interruptible_sleep_on_timeout() usage
#   
#   Replace deprecated interruptible_sleep_on_timeout() with direct
#   wait-queue usage. Patch is compile-tested.
#   
#   Signed-off-by: Nishanth Aravamudan <nacc@us.ibm.com>
#   Signed-off-by: Domen Puncer <domen@coderock.org>
#   Signed-off-by: Greg Kroah-Hartman <gregkh@suse.de>
# 
# drivers/usb/misc/rio500.c
#   2005/03/05 07:12:11-08:00 domen@coderock.org +9 -3
#   usb/rio500: remove interruptible_sleep_on_timeout() usage
# 
# ChangeSet
#   2005/03/17 17:58:07-08:00 oliver@neukum.org 
#   [PATCH] USB: removal of obsolete error code from kaweth
#   
#   this patch from David removes an obsolete error code from kaweth.
#   
#   Signed-off-by: Oliver Neukum <oliver@neukum.name>
#   Signed-off-by: Greg Kroah-Hartman <gregkh@suse.de>
# 
# drivers/usb/net/kaweth.c
#   2005/03/04 23:57:34-08:00 oliver@neukum.org +1 -1
#   USB: removal of obsolete error code from kaweth
# 
# ChangeSet
#   2005/03/17 17:57:47-08:00 stern@rowland.harvard.edu 
#   [PATCH] USB: Prevent hub driver interference during port reset
#   
#   This patch causes the hub driver to ignore ports that are being reset by
#   another driver.  Without this protection khubd will sometimes notice that
#   the port is behaving funny while the reset is taking place and will
#   unilaterally disconnect it, which is not what we want.
#   
#   Signed-off-by: Alan Stern <stern@rowland.harvard.edu>
#   Signed-off-by: Greg Kroah-Hartman <gregkh@suse.de>
# 
# drivers/usb/core/hub.h
#   2005/02/27 05:30:15-08:00 stern@rowland.harvard.edu +1 -0
#   USB: Prevent hub driver interference during port reset
# 
# drivers/usb/core/hub.c
#   2005/02/27 05:30:15-08:00 stern@rowland.harvard.edu +4 -0
#   USB: Prevent hub driver interference during port reset
# 
# ChangeSet
#   2005/03/17 17:57:27-08:00 stern@rowland.harvard.edu 
#   [PATCH] g_file_storage: add configuration and interface strings
#   
#   This patch adds iConfiguration and iInterface strings to the
#   g_file_storage driver (just to spiff it up and help in testing software
#   that looks at those strings).  It also enlarges the space reserved for the
#   Manufacturer string, since combinations of long kernel names and long UDC
#   driver names were sometimes getting truncated.
#   
#   Signed-off-by: Alan Stern <stern@rowland.harvard.edu>
#   Signed-off-by: Greg Kroah-Hartman <gregkh@suse.de>
# 
# drivers/usb/gadget/file_storage.c
#   2005/02/25 07:39:06-08:00 stern@rowland.harvard.edu +8 -2
#   g_file_storage: add configuration and interface strings
# 
# ChangeSet
#   2005/03/17 17:57:07-08:00 stern@rowland.harvard.edu 
#   [PATCH] usb-midi: fix arguments to usb_maxpacket()
#   
#   The usb-midi driver uses an incorrect value for the is_out argument to
#   usb_maxpacket(), triggering a WARN_ON.  This patch fixes the mistake.
#   
#   Signed-off-by: Alan Stern <stern@rowland.harvard.edu>
#   Signed-off-by: Greg Kroah-Hartman <gregkh@suse.de>
# 
# drivers/usb/class/usb-midi.c
#   2005/02/26 02:17:03-08:00 stern@rowland.harvard.edu +2 -2
#   usb-midi: fix arguments to usb_maxpacket()
# 
# ChangeSet
#   2005/03/17 17:56:48-08:00 akpm@osdl.org 
#   [PATCH] usb hcd u64 warning fix
#   
#   drivers/usb/core/hcd.c:1689: warning: long long unsigned int format, u64 arg (arg 6)
#   drivers/usb/core/hcd.c:1695: warning: long long unsigned int format, u64 arg (arg 5)
#   
#   We must not assume that u64 is implemented as `unsigned long long'.  On ppc64
#   (for example) it is `unsigned long'.
#   
#   Signed-off-by: Andrew Morton <akpm@osdl.org>
#   Signed-off-by: Greg Kroah-Hartman <gregkh@suse.de>
# 
# drivers/usb/core/hcd.c
#   2005/02/28 07:44:29-08:00 akpm@osdl.org +4 -2
#   usb hcd u64 warning fix
# 
# ChangeSet
#   2005/03/17 17:49:09-08:00 zaitcev@redhat.com 
#   [PATCH] USB: Patch for ub to fix oops after disconnect
#   
#   This patch was developed by Glenn Maynard for his oops back in December,
#   but for some reason I forgot about it and had it reimplemented when I stepped
#   on this problem myself. In my case, there was no oops, but a warning about
#   slab corruption.
#   
#   Signed-off-by: Pete Zaitcev <zaitcev@redhat.com>
#   Signed-off-by: Greg Kroah-Hartman <gregkh@suse.de>
# 
# drivers/block/ub.c
#   2005/02/20 21:46:58-08:00 zaitcev@redhat.com +5 -6
#   USB: Patch for ub to fix oops after disconnect
# 
# ChangeSet
#   2005/03/17 17:35:24-08:00 david-b@pacbell.net 
#   [PATCH] USB: ethernet/rndis gadget driver updates
#   
#   Various fixes to the Ethernet/RNDIS gadget core code:
#   
#       - Pre-allocate the request used to transfer status back to the host.
#         Used initially for CDC Ethernet; RNDIS will change later.  This
#         resolves a longstanding FIXME, elimininating fault modes.
#   
#       - Use larger packets for those status reports, 16 bytes not 8; this
#         eliminates some fault modes, without losing hardware support.
#   
#       - Streamline endpoint configuration, just save the endpoints during
#         driver binding.  The previous scheme was a complex leftover from
#         before the endpoint autoselection library code existed, and this
#         bit of cleanup prepares for more simplifications later.
#   
#       - Implement a basic outgoing packet filter, for CDC Ethernet and RNDIS
#         but not the CDC subset.  This improves conformance to both specs.
#   
#       - Correct the bit rate reports for CDC Ethernet and RNDIS to match
#         the peak bulk transfer rates, not the raw signaling rates.
#   
#   This still doesn't issue CDC or RNDIS link status change notifications
#   to the host as often as it should, but that'll be easier now.
#   
#   Signed-off-by: David Brownell <dbrownell@users.sourceforge.net>
#   Signed-off-by: Greg Kroah-Hartman <gregkh@suse.de>
# 
# drivers/usb/gadget/ether.c
#   2005/02/28 18:26:02-08:00 david-b@pacbell.net +154 -92
#   USB: ethernet/rndis gadget driver updates
# 
# ChangeSet
#   2005/03/17 17:35:05-08:00 david-b@pacbell.net 
#   [PATCH] USB: net2280 reports correct dequeue status
#   
#   Minor bugfix to net2280:  don't return incorrect dequeue() status.
#   
#   Signed-off-by: David Brownell <dbrownell@users.sourceforge.net>
#   Signed-off-by: Greg Kroah-Hartman <gregkh@suse.de>
# 
# drivers/usb/gadget/net2280.c
#   2005/02/06 15:35:42-08:00 david-b@pacbell.net +1 -1
#   USB: net2280 reports correct dequeue status
# 
# ChangeSet
#   2005/03/17 17:34:45-08:00 david-b@pacbell.net 
#   [PATCH] USB: usbnet fix for Zaurus C-860
#   
#   This patch resolves a recent problem with the Zaurus C-860 support.
#   
#   A change to correct handling of Zaurii that are lying about their support
#   for the "CDC Ethernet" class specification broke the C-860, which tells
#   an entirely different lie (that it supports "CDC MDLM", providing access
#   to a cell phone modem).  The code expecting it to be telling a lie about
#   CDC Ethernet support naturally misbehaved.  (Sharp should straighten out
#   its story.  The 2.6 OpenZaurus kernels don't have any such issues...)
#   
#   The fix is just to recognize this bogus MDLM stuff and ignore it.
#   This patch also includes the two MDLM descriptors in <linux/usb_cdc.h>
#   although they're not currently used.
#   
#   Signed-off-by: David Brownell <dbrownell@users.sourceforge.net>
#   Signed-off-by: Greg Kroah-Hartman <gregkh@suse.de>
# 
# include/linux/usb_cdc.h
#   2005/03/04 13:27:54-08:00 david-b@pacbell.net +32 -2
#   USB: usbnet fix for Zaurus C-860
# 
# drivers/usb/net/usbnet.c
#   2005/03/04 13:42:57-08:00 david-b@pacbell.net +31 -1
#   USB: usbnet fix for Zaurus C-860
# 
# ChangeSet
#   2005/03/17 17:34:24-08:00 david-b@pacbell.net 
#   [PATCH] USB: usbnet gets status polling, uses for CDC Ethernet
#   
#   This adds status/interrupt transfer infrastructure to "usbnet", and
#   uses it for CDC Ethernet support.  It can be used with other devices
#   that define an interrupt-IN endpoint (quite a few!), so long as the
#   meaning of the events is documented (erm, not so many).
#   
#   Signed-off-by: David Brownell <dbrownell@users.sourceforge.net>
#   Signed-off-by: Greg Kroah-Hartman <gregkh@suse.de>
# 
# drivers/usb/net/usbnet.c
#   2005/02/03 23:10:02-08:00 david-b@pacbell.net +186 -9
#   USB: usbnet gets status polling, uses for CDC Ethernet
# 
# ChangeSet
#   2005/03/17 17:34:04-08:00 david-b@pacbell.net 
#   [PATCH] USB: ehci and short in-bulk transfers with 20KB+ urbs
#   
#   This changes handling of short bulk IN transfers with URB buffers that require
#   two or more transfer descriptors.  The case is rare in most systems, since few
#   drivers use such large buffers (bigger than 20KB, assuming 4K-aligned).
#   
#   The existing code misbehave on at least NEC's EHCI 0.95 silicon, where it seems
#   to hit a new variant of a silicon quirk relating to dummy TDs.  Symptom of the
#   misbehavior is that the host stops polling on the IN endpoint, and the URB queue
#   no longer progresses.
#   
#   This fix uses simpler logic to detect those short reads, dodging that quirk.
#   
#   Signed-off-by: David Brownell <dbrownell@users.sourceforge.net>
#   Signed-off-by: Greg Kroah-Hartman <gregkh@suse.de>
# 
# drivers/usb/host/ehci-q.c
#   2005/03/03 10:55:26-08:00 david-b@pacbell.net +4 -3
#   USB: ehci and short in-bulk transfers with 20KB+ urbs
# 
# ChangeSet
#   2005/03/17 17:33:44-08:00 david-b@pacbell.net 
#   [PATCH] USB: ohci zero length control IN transfers
#   
#   This fixes a longstanding bug in the OHCI driver, inherited from the 2.4
#   code.  It also fixes a related comment in the EHCI driver, which came when
#   the EHCI code was first derived from OHCI.  (The EHCI code doesn't have
#   that bug; the comment was effectively "FIXME add bug".)
#   
#   The bug: control-IN transfers with no data stages have status stages with
#   an IN packet (like a control-OUT transfer), instead of using an OUT packet.
#   See figure 8-37 of the USB spec.  The current code makes trouble with some
#   peripheral hardware and zero length IN transfers (scarce in the Real World).
#   
#   Signed-off-by: David Brownell <dbrownell@users.sourceforge.net>
#   Signed-off-by: Greg Kroah-Hartman <gregkh@suse.de>
# 
# drivers/usb/host/ohci-q.c
#   2005/03/01 13:28:30-08:00 david-b@pacbell.net +1 -1
#   USB: ohci zero length control IN transfers
# 
# drivers/usb/host/ehci-q.c
#   2005/03/02 08:59:20-08:00 david-b@pacbell.net +1 -1
#   USB: ohci zero length control IN transfers
# 
# ChangeSet
#   2005/03/17 17:33:24-08:00 david-b@pacbell.net 
#   [PATCH] USB: usb gadget kconfig tweaks
#   
#   This makes two small changes to the gadget Kconfig.
#   
#    - It removes SA-1100 support ... if anyone gets around to
#      finishing that controller driver, it could go back, but
#      until then there's no real point.
#   
#    - The "dummy_hcd" moves to the end, with a comment to please
#      keep it there.
#   
#   Moving that Kconfig entry helps keep "real hardware" as the default
#   on systems that have it ... otherwise Kconfig will surprise people
#   with a curious default.
#   
#   Signed-off-by: David Brownell <dbrownell@users.sourceforge.net>
#   Signed-off-by: Greg Kroah-Hartman <gregkh@suse.de>
# 
# drivers/usb/gadget/Kconfig
#   2005/02/28 18:57:37-08:00 david-b@pacbell.net +32 -43
#   USB: usb gadget kconfig tweaks
# 
# ChangeSet
#   2005/03/17 17:33:03-08:00 david-b@pacbell.net 
#   [PATCH] USB: add at91_udc recognition
#   
#   Add declarations to recognize the AT91 USB peripheral controller,
#   as used in various ARMv4T chips including the mmu-ful at91rm9200.
#   
#   Signed-off-by: David Brownell <dbrownell@users.sourceforge.net>
#   Signed-off-by: Greg Kroah-Hartman <gregkh@suse.de>
# 
# drivers/usb/gadget/zero.c
#   2005/02/28 18:21:59-08:00 david-b@pacbell.net +2 -0
#   USB: add at91_udc recognition
# 
# drivers/usb/gadget/serial.c
#   2005/02/28 18:21:59-08:00 david-b@pacbell.net +3 -0
#   USB: add at91_udc recognition
# 
# drivers/usb/gadget/gadget_chips.h
#   2005/02/28 18:21:59-08:00 david-b@pacbell.net +6 -1
#   USB: add at91_udc recognition
# 
# drivers/usb/gadget/file_storage.c
#   2005/02/28 18:21:59-08:00 david-b@pacbell.net +4 -0
#   USB: add at91_udc recognition
# 
# drivers/usb/gadget/ether.c
#   2005/02/28 18:21:59-08:00 david-b@pacbell.net +6 -0
#   USB: add at91_udc recognition
# 
# ChangeSet
#   2005/03/17 17:13:54-08:00 bunk@stusta.de 
#   [PATCH] remove drivers/usb/image/hpusbscsi.c
#   
#   USB_HPUSBSCSI was marked as BROKEN in 2.6.11 since libsane is the
#   preferred way to access these devices.
#   
#   Unless someone plans to resurrect this driver, I'm therefore proposing
#   this patch to completely remove it.
#   
#   Signed-off-by: Adrian Bunk <bunk@stusta.de>
#   Signed-off-by: Greg Kroah-Hartman <gregkh@suse.de>
# 
# drivers/usb/image/Makefile
#   2005/03/02 07:02:30-08:00 bunk@stusta.de +0 -1
#   remove drivers/usb/image/hpusbscsi.c
# 
# drivers/usb/image/Kconfig
#   2005/03/03 05:24:33-08:00 bunk@stusta.de +0 -11
#   remove drivers/usb/image/hpusbscsi.c
# 
# drivers/usb/Makefile
#   2005/03/02 07:02:18-08:00 bunk@stusta.de +0 -1
#   remove drivers/usb/image/hpusbscsi.c
# 
# BitKeeper/deleted/.del-hpusbscsi.h~d532117e5fee2a33
#   2005/03/17 17:13:35-08:00 bunk@stusta.de +0 -0
#   Delete: drivers/usb/image/hpusbscsi.h
# 
# BitKeeper/deleted/.del-hpusbscsi.c~b365c31f2ad86af1
#   2005/03/17 17:13:35-08:00 bunk@stusta.de +0 -0
#   Delete: drivers/usb/image/hpusbscsi.c
# 
# ChangeSet
#   2005/03/17 17:09:47-08:00 bunk@stusta.de 
#   [PATCH] drivers/usb/net/pegasus.c: make some code static
#   
#   This patch makes some needlessly global code static.
#   
#   Signed-off-by: Adrian Bunk <bunk@stusta.de>
#   Signed-off-by: Greg Kroah-Hartman <gregkh@suse.de>
# 
# drivers/usb/net/pegasus.c
#   2005/02/28 14:27:45-08:00 bunk@stusta.de +4 -3
#   drivers/usb/net/pegasus.c: make some code static
# 
# ChangeSet
#   2005/03/17 17:09:18-08:00 bunk@stusta.de 
#   [PATCH] drivers/usb/storage/: cleanups
#   
#   This patch contains the following cleanups:
#   - make needlessly global code static
#   - scsiglue.c: remove the unused usb_stor_sense_notready
#   
#   Signed-off-by: Adrian Bunk <bunk@stusta.de>
#   Signed-off-by: Greg Kroah-Hartman <gregkh@suse.de>
# 
# drivers/usb/storage/usb.h
#   2005/02/28 14:26:12-08:00 bunk@stusta.de +0 -3
#   drivers/usb/storage/: cleanups
# 
# drivers/usb/storage/usb.c
#   2005/02/28 14:25:58-08:00 bunk@stusta.de +2 -2
#   drivers/usb/storage/: cleanups
# 
# drivers/usb/storage/transport.h
#   2005/02/28 14:23:56-08:00 bunk@stusta.de +0 -5
#   drivers/usb/storage/: cleanups
# 
# drivers/usb/storage/transport.c
#   2005/02/28 14:24:26-08:00 bunk@stusta.de +3 -2
#   drivers/usb/storage/: cleanups
# 
# drivers/usb/storage/shuttle_usbat.h
#   2005/02/28 14:20:55-08:00 bunk@stusta.de +0 -4
#   drivers/usb/storage/: cleanups
# 
# drivers/usb/storage/shuttle_usbat.c
#   2005/02/28 14:22:52-08:00 bunk@stusta.de +8 -5
#   drivers/usb/storage/: cleanups
# 
# drivers/usb/storage/scsiglue.h
#   2005/02/28 14:18:41-08:00 bunk@stusta.de +0 -1
#   drivers/usb/storage/: cleanups
# 
# drivers/usb/storage/scsiglue.c
#   2005/02/28 14:19:00-08:00 bunk@stusta.de +0 -9
#   drivers/usb/storage/: cleanups
# 
# ChangeSet
#   2005/03/17 17:07:38-08:00 bunk@stusta.de 
#   [PATCH] drivers/usb/serial/: make some functions static
#   
#   This patch makes some needlessly global functions static.
#   
#   Signed-off-by: Adrian Bunk <bunk@stusta.de>
#   Signed-off-by: Greg Kroah-Hartman <gregkh@suse.de>
# 
# drivers/usb/serial/ipw.c
#   2005/02/28 14:33:43-08:00 bunk@stusta.de +2 -2
#   drivers/usb/serial/: make some functions static
# 
# drivers/usb/serial/garmin_gps.c
#   2005/02/28 14:32:50-08:00 bunk@stusta.de +2 -2
#   drivers/usb/serial/: make some functions static
# 
# drivers/usb/serial/ftdi_sio.c
#   2005/02/28 14:32:13-08:00 bunk@stusta.de +7 -5
#   drivers/usb/serial/: make some functions static
# 
# ChangeSet
#   2005/03/17 17:04:11-08:00 bunk@stusta.de 
#   [PATCH] USB: possible cleanups
#   
#   Before I'm getting flamed to death:
#   This patch contains possible cleanups. If parts of this patch conflict
#   with pending changes these parts of my patch have to be dropped.
#   
#   This patch contains the following possible cleanups:
#   - make needlessly global code static
#   - #if 0 the following unused global functions:
#     - core/usb.c: usb_buffer_map
#     - core/usb.c: usb_buffer_unmap
#   - remove the following unneeded EXPORT_SYMBOL's:
#     - core/hcd.c: usb_bus_init
#     - core/hcd.c: usb_alloc_bus
#     - core/hcd.c: usb_register_bus
#     - core/hcd.c: usb_deregister_bus
#     - core/hcd.c: usb_hcd_irq
#     - core/usb.c: usb_buffer_map
#     - core/usb.c: usb_buffer_unmap
#     - core/buffer.c: hcd_buffer_create
#     - core/buffer.c: hcd_buffer_destroy
#   
#   Signed-off-by: Adrian Bunk <bunk@stusta.de>
#   Signed-off-by: Greg Kroah-Hartman <gregkh@suse.de>
# 
# include/linux/usb.h
#   2005/02/28 15:38:40-08:00 bunk@stusta.de +2 -2
#   USB: possible cleanups
# 
# drivers/usb/net/kawethfw.h
#   2005/02/28 15:10:01-08:00 bunk@stusta.de +4 -4
#   USB: possible cleanups
# 
# drivers/usb/net/catc.c
#   2005/02/28 15:08:56-08:00 bunk@stusta.de +2 -1
#   USB: possible cleanups
# 
# drivers/usb/misc/sisusbvga/sisusb.c
#   2005/02/28 15:07:14-08:00 bunk@stusta.de +4 -4
#   USB: possible cleanups
# 
# drivers/usb/media/ibmcam.c
#   2005/02/28 15:05:09-08:00 bunk@stusta.de +2 -1
#   USB: possible cleanups
# 
# drivers/usb/input/aiptek.c
#   2005/02/28 15:04:35-08:00 bunk@stusta.de +1 -1
#   USB: possible cleanups
# 
# drivers/usb/core/usb.h
#   2005/02/28 15:03:31-08:00 bunk@stusta.de +0 -5
#   USB: possible cleanups
# 
# drivers/usb/core/usb.c
#   2005/02/28 15:37:27-08:00 bunk@stusta.de +9 -5
#   USB: possible cleanups
# 
# drivers/usb/core/message.c
#   2005/02/28 14:58:25-08:00 bunk@stusta.de +6 -4
#   USB: possible cleanups
# 
# drivers/usb/core/hub.c
#   2005/02/28 14:56:41-08:00 bunk@stusta.de +2 -1
#   USB: possible cleanups
# 
# drivers/usb/core/hcd.h
#   2005/02/28 14:52:44-08:00 bunk@stusta.de +0 -1
#   USB: possible cleanups
# 
# drivers/usb/core/hcd.c
#   2005/02/28 15:27:36-08:00 bunk@stusta.de +1 -6
#   USB: possible cleanups
# 
# drivers/usb/core/config.c
#   2005/02/28 14:49:04-08:00 bunk@stusta.de +1 -1
#   USB: possible cleanups
# 
# drivers/usb/core/buffer.c
#   2005/02/28 15:28:42-08:00 bunk@stusta.de +0 -2
#   USB: possible cleanups
# 
# ChangeSet
#   2005/03/14 23:57:02-08:00 gregkh@suse.de 
#   USB: fix cpia_usb driver's warning messages in the syslog
#   
#   This fixes the cpia driver to call usb_kill_urb() instead of
#   usb_unlink_urb() which reduces the ammount of syslog messages when
#   kernel debugging is enabled.
#   
#   Signed-off-by: Greg Kroah-Hartman <gregkh@suse.de>
# 
# drivers/media/video/cpia_usb.c
#   2005/03/14 23:56:43-08:00 gregkh@suse.de +2 -2
#   USB: fix cpia_usb driver's warning messages in the syslog
#   
#   This fixes the cpia driver to call usb_kill_urb() instead of
#   usb_unlink_urb() which reduces the ammount of syslog messages when
#   kernel debugging is enabled.
#   
#   Signed-off-by: Greg Kroah-Hartman <gregkh@suse.de>
# 
# ChangeSet
#   2005/03/14 22:57:48-08:00 gregkh@suse.de 
#   [PATCH] USB: minor cleanup of string freeing in core code.
#   
#   As pointed out by Paulo Marques <pmarques@grupopie.com>
#   
#   Signed-off-by: Greg Kroah-Hartman <gregkh@suse.de>
# 
# drivers/usb/core/config.c
#   2005/03/14 16:31:43-08:00 gregkh@suse.de +2 -2
#   USB: minor cleanup of string freeing in core code.
# 
# ChangeSet
#   2005/03/14 22:57:23-08:00 gregkh@suse.de 
#   [PATCH] USB: optimize the usb-storage device string logic a bit.
#   
#   As pointed out by Alan Stern <stern@rowland.harvard.edu>
#   
#   Signed-off-by: Greg Kroah-Hartman <gregkh@suse.de>
# 
# drivers/usb/storage/scsiglue.c
#   2005/03/14 16:32:38-08:00 gregkh@suse.de +12 -8
#   USB: optimize the usb-storage device string logic a bit.
# 
diff -Nru a/drivers/block/ub.c b/drivers/block/ub.c
--- a/drivers/block/ub.c	2005-03-23 19:58:52 -08:00
+++ b/drivers/block/ub.c	2005-03-23 19:58:52 -08:00
@@ -496,6 +496,11 @@
  */
 static void ub_cleanup(struct ub_dev *sc)
 {
+	request_queue_t *q;
+
+	/* I don't think queue can be NULL. But... Stolen from sx8.c */
+	if ((q = sc->disk->queue) != NULL)
+		blk_cleanup_queue(q);
 
 	/*
 	 * If we zero disk->private_data BEFORE put_disk, we have to check
@@ -2056,7 +2061,6 @@
 {
 	struct ub_dev *sc = usb_get_intfdata(intf);
 	struct gendisk *disk = sc->disk;
-	request_queue_t *q = disk->queue;
 	unsigned long flags;
 
 	/*
@@ -2099,13 +2103,8 @@
 	 */
 	if (disk->flags & GENHD_FL_UP)
 		del_gendisk(disk);
-	if (q)
-		blk_cleanup_queue(q);
 
 	/*
-	 * We really expect blk_cleanup_queue() to wait, so no amount
-	 * of paranoya is too much.
-	 *
 	 * Taking a lock on a structure which is about to be freed
 	 * is very nonsensual. Here it is largely a way to do a debug freeze,
 	 * and a bracket which shows where the nonsensual code segment ends.
diff -Nru a/drivers/media/video/cpia_usb.c b/drivers/media/video/cpia_usb.c
--- a/drivers/media/video/cpia_usb.c	2005-03-23 19:58:52 -08:00
+++ b/drivers/media/video/cpia_usb.c	2005-03-23 19:58:52 -08:00
@@ -440,7 +440,7 @@
 
 	/* Unschedule all of the iso td's */
 	if (ucpia->sbuf[1].urb) {
-		usb_unlink_urb(ucpia->sbuf[1].urb);
+		usb_kill_urb(ucpia->sbuf[1].urb);
 		usb_free_urb(ucpia->sbuf[1].urb);
 		ucpia->sbuf[1].urb = NULL;
 	}
@@ -451,7 +451,7 @@
 	}
  
 	if (ucpia->sbuf[0].urb) {
-		usb_unlink_urb(ucpia->sbuf[0].urb);
+		usb_kill_urb(ucpia->sbuf[0].urb);
 		usb_free_urb(ucpia->sbuf[0].urb);
 		ucpia->sbuf[0].urb = NULL;
 	}
diff -Nru a/drivers/usb/Makefile b/drivers/usb/Makefile
--- a/drivers/usb/Makefile	2005-03-23 19:58:52 -08:00
+++ b/drivers/usb/Makefile	2005-03-23 19:58:52 -08:00
@@ -51,7 +51,6 @@
 obj-$(CONFIG_USB_RTL8150)	+= net/
 obj-$(CONFIG_USB_USBNET)	+= net/
 
-obj-$(CONFIG_USB_HPUSBSCSI)	+= image/
 obj-$(CONFIG_USB_MDC800)	+= image/
 obj-$(CONFIG_USB_MICROTEK)	+= image/
 
diff -Nru a/drivers/usb/class/usb-midi.c b/drivers/usb/class/usb-midi.c
--- a/drivers/usb/class/usb-midi.c	2005-03-23 19:58:53 -08:00
+++ b/drivers/usb/class/usb-midi.c	2005-03-23 19:58:53 -08:00
@@ -992,7 +992,7 @@
 	endPoint &= 0x0f; /* Silently force endPoint to lie in range 0 to 15. */
 
 	pipe =  usb_rcvbulkpipe( d, endPoint );
-	bufSize = usb_maxpacket( d, pipe, usb_pipein(pipe) );
+	bufSize = usb_maxpacket( d, pipe, 0 );
 	/* usb_pipein() = ! usb_pipeout() = true for an in Endpoint */
 
 	ep = (struct midi_in_endpoint *)kmalloc(sizeof(struct midi_in_endpoint), GFP_KERNEL);
@@ -1063,7 +1063,7 @@
 
 	endPoint &= 0x0f;
 	pipe =  usb_sndbulkpipe( d, endPoint );
-	bufSize = usb_maxpacket( d, pipe, usb_pipeout(pipe) );
+	bufSize = usb_maxpacket( d, pipe, 1 );
 
 	ep = (struct midi_out_endpoint *)kmalloc(sizeof(struct midi_out_endpoint), GFP_KERNEL);
 	if ( !ep ) {
diff -Nru a/drivers/usb/core/buffer.c b/drivers/usb/core/buffer.c
--- a/drivers/usb/core/buffer.c	2005-03-23 19:58:52 -08:00
+++ b/drivers/usb/core/buffer.c	2005-03-23 19:58:52 -08:00
@@ -76,7 +76,6 @@
 	}
 	return 0;
 }
-EXPORT_SYMBOL (hcd_buffer_create);
 
 
 /**
@@ -98,7 +97,6 @@
 		}
 	}
 }
-EXPORT_SYMBOL (hcd_buffer_destroy);
 
 
 /* sometimes alloc/free could use kmalloc with SLAB_DMA, for
diff -Nru a/drivers/usb/core/config.c b/drivers/usb/core/config.c
--- a/drivers/usb/core/config.c	2005-03-23 19:58:52 -08:00
+++ b/drivers/usb/core/config.c	2005-03-23 19:58:52 -08:00
@@ -221,7 +221,7 @@
 	return buffer - buffer0 + i;
 }
 
-int usb_parse_configuration(struct device *ddev, int cfgidx,
+static int usb_parse_configuration(struct device *ddev, int cfgidx,
     struct usb_host_config *config, unsigned char *buffer, int size)
 {
 	unsigned char *buffer0 = buffer;
@@ -420,8 +420,8 @@
 	for (c = 0; c < dev->descriptor.bNumConfigurations; c++) {
 		struct usb_host_config *cf = &dev->config[c];
 
-		if (cf->string)
-			kfree(cf->string);
+		kfree(cf->string);
+		cf->string = NULL;
 
 		for (i = 0; i < cf->desc.bNumInterfaces; i++) {
 			if (cf->intf_cache[i])
diff -Nru a/drivers/usb/core/hcd-pci.c b/drivers/usb/core/hcd-pci.c
--- a/drivers/usb/core/hcd-pci.c	2005-03-23 19:58:52 -08:00
+++ b/drivers/usb/core/hcd-pci.c	2005-03-23 19:58:52 -08:00
@@ -226,8 +226,8 @@
 	/* entry if root hub wasn't yet suspended ... from sysfs,
 	 * without autosuspend, or if USB_SUSPEND isn't configured.
 	 */
-	case USB_STATE_RUNNING:
-		hcd->state = USB_STATE_QUIESCING;
+	case HC_STATE_RUNNING:
+		hcd->state = HC_STATE_QUIESCING;
 		retval = hcd->driver->suspend (hcd, state);
 		if (retval) {
 			dev_dbg (hcd->self.controller, 
@@ -235,7 +235,7 @@
 					retval);
 			break;
 		}
-		hcd->state = HCD_STATE_SUSPENDED;
+		hcd->state = HC_STATE_SUSPENDED;
 		/* FALLTHROUGH */
 
 	/* entry with CONFIG_USB_SUSPEND, or hcds that autosuspend: the
@@ -245,7 +245,7 @@
 	 * FIXME only CONFIG_USB_SUSPEND guarantees hub_suspend() will
 	 * have been called, otherwise root hub timers still run ...
 	 */
-	case HCD_STATE_SUSPENDED:
+	case HC_STATE_SUSPENDED:
 		if (state <= dev->current_state)
 			break;
 
@@ -311,7 +311,7 @@
 	int			has_pci_pm;
 
 	hcd = pci_get_drvdata(dev);
-	if (hcd->state != HCD_STATE_SUSPENDED) {
+	if (hcd->state != HC_STATE_SUSPENDED) {
 		dev_dbg (hcd->self.controller, 
 				"can't resume, not suspended!\n");
 		return 0;
@@ -323,7 +323,7 @@
 			pci_state(dev->current_state),
 			has_pci_pm ? "" : " (legacy)");
 
-	hcd->state = USB_STATE_RESUMING;
+	hcd->state = HC_STATE_RESUMING;
 
 	if (has_pci_pm)
 		pci_set_power_state (dev, 0);
@@ -343,7 +343,7 @@
 #endif
 
 	retval = hcd->driver->resume (hcd);
-	if (!HCD_IS_RUNNING (hcd->state)) {
+	if (!HC_IS_RUNNING (hcd->state)) {
 		dev_dbg (hcd->self.controller, 
 				"resume fail, retval %d\n", retval);
 		usb_hc_died (hcd);
diff -Nru a/drivers/usb/core/hcd.c b/drivers/usb/core/hcd.c
--- a/drivers/usb/core/hcd.c	2005-03-23 19:58:52 -08:00
+++ b/drivers/usb/core/hcd.c	2005-03-23 19:58:52 -08:00
@@ -101,6 +101,9 @@
 DECLARE_MUTEX (usb_bus_list_lock);	/* exported only for usbfs */
 EXPORT_SYMBOL_GPL (usb_bus_list_lock);
 
+/* used for controlling access to virtual root hubs */
+static DEFINE_SPINLOCK(hcd_root_hub_lock);
+
 /* used when updating hcd data */
 static DEFINE_SPINLOCK(hcd_data_lock);
 
@@ -455,7 +458,7 @@
 
 	default:
 		/* non-generic request */
-		if (HCD_IS_SUSPENDED (hcd->state))
+		if (HC_IS_SUSPENDED (hcd->state))
 			status = -EAGAIN;
 		else {
 			switch (typeReq) {
@@ -701,7 +704,7 @@
  * This code is used to initialize a usb_bus structure, memory for which is
  * separately managed.
  */
-void usb_bus_init (struct usb_bus *bus)
+static void usb_bus_init (struct usb_bus *bus)
 {
 	memset (&bus->devmap, 0, sizeof(struct usb_devmap));
 
@@ -719,7 +722,6 @@
 	class_device_initialize(&bus->class_dev);
 	bus->class_dev.class = &usb_host_class;
 }
-EXPORT_SYMBOL (usb_bus_init);
 
 /**
  * usb_alloc_bus - creates a new USB host controller structure
@@ -745,7 +747,6 @@
 	bus->op = op;
 	return bus;
 }
-EXPORT_SYMBOL (usb_alloc_bus);
 
 /*-------------------------------------------------------------------------*/
 
@@ -757,7 +758,7 @@
  * Assigns a bus number, and links the controller into usbcore data
  * structures so that it can be seen by scanning the bus list.
  */
-int usb_register_bus(struct usb_bus *bus)
+static int usb_register_bus(struct usb_bus *bus)
 {
 	int busnum;
 	int retval;
@@ -792,7 +793,6 @@
 	dev_info (bus->controller, "new USB bus registered, assigned bus number %d\n", bus->busnum);
 	return 0;
 }
-EXPORT_SYMBOL (usb_register_bus);
 
 /**
  * usb_deregister_bus - deregisters the USB host controller
@@ -802,7 +802,7 @@
  * Recycles the bus number, and unlinks the controller from usbcore data
  * structures so that it won't be seen by scanning the bus list.
  */
-void usb_deregister_bus (struct usb_bus *bus)
+static void usb_deregister_bus (struct usb_bus *bus)
 {
 	dev_info (bus->controller, "USB bus %d deregistered\n", bus->busnum);
 
@@ -822,12 +822,11 @@
 
 	class_device_del(&bus->class_dev);
 }
-EXPORT_SYMBOL (usb_deregister_bus);
 
 /**
- * usb_register_root_hub - called by HCD to register its root hub 
+ * usb_hcd_register_root_hub - called by HCD to register its root hub 
  * @usb_dev: the usb root hub device to be registered.
- * @parent_dev: the parent device of this root hub.
+ * @hcd: host controller for this root hub
  *
  * The USB host controller calls this function to register the root hub
  * properly with the USB subsystem.  It sets up the device properly in
@@ -835,11 +834,20 @@
  * then calls usb_new_device() to register the usb device.  It also
  * assigns the root hub's USB address (always 1).
  */
-int usb_register_root_hub (struct usb_device *usb_dev, struct device *parent_dev)
+int usb_hcd_register_root_hub (struct usb_device *usb_dev, struct usb_hcd *hcd)
 {
+	struct device *parent_dev = hcd->self.controller;
 	const int devnum = 1;
 	int retval;
 
+	/* hcd->driver->start() reported can_wakeup, probably with
+	 * assistance from board's boot firmware.
+	 * NOTE:  normal devices won't enable wakeup by default.
+	 */
+	if (hcd->can_wakeup)
+		dev_dbg (parent_dev, "supports USB remote wakeup\n");
+	hcd->remote_wakeup = hcd->can_wakeup;
+
 	usb_dev->devnum = devnum;
 	usb_dev->bus->devnum_next = devnum + 1;
 	memset (&usb_dev->bus->devmap.devicemap, 0,
@@ -869,9 +877,20 @@
 				usb_dev->dev.bus_id, retval);
 	}
 	up (&usb_bus_list_lock);
+
+	if (retval == 0) {
+		spin_lock_irq (&hcd_root_hub_lock);
+		hcd->rh_registered = 1;
+		spin_unlock_irq (&hcd_root_hub_lock);
+
+		/* Did the HC die before the root hub was registered? */
+		if (hcd->state == HC_STATE_HALT)
+			usb_hc_died (hcd);	/* This time clean up */
+	}
+
 	return retval;
 }
-EXPORT_SYMBOL (usb_register_root_hub);
+EXPORT_SYMBOL_GPL(usb_hcd_register_root_hub);
 
 
 /*-------------------------------------------------------------------------*/
@@ -1112,8 +1131,8 @@
 	else if (unlikely (urb->reject))
 		status = -EPERM;
 	else switch (hcd->state) {
-	case USB_STATE_RUNNING:
-	case USB_STATE_RESUMING:
+	case HC_STATE_RUNNING:
+	case HC_STATE_RESUMING:
 		usb_get_dev (urb->dev);
 		list_add_tail (&urb->urb_list, &ep->urb_list);
 		status = 0;
@@ -1187,7 +1206,7 @@
 static int hcd_get_frame_number (struct usb_device *udev)
 {
 	struct usb_hcd	*hcd = (struct usb_hcd *)udev->bus->hcpriv;
-	if (!HCD_IS_RUNNING (hcd->state))
+	if (!HC_IS_RUNNING (hcd->state))
 		return -ESHUTDOWN;
 	return hcd->driver->get_frame_number (hcd);
 }
@@ -1269,7 +1288,7 @@
 	 * halted ~= no unlink handshake is needed
 	 * suspended, resuming == should never happen
 	 */
-	WARN_ON (!HCD_IS_RUNNING (hcd->state) && hcd->state != USB_STATE_HALT);
+	WARN_ON (!HC_IS_RUNNING (hcd->state) && hcd->state != HC_STATE_HALT);
 
 	/* insist the urb is still queued */
 	list_for_each(tmp, &ep->urb_list) {
@@ -1336,7 +1355,7 @@
 
 	hcd = udev->bus->hcpriv;
 
-	WARN_ON (!HCD_IS_RUNNING (hcd->state) && hcd->state != USB_STATE_HALT);
+	WARN_ON (!HC_IS_RUNNING (hcd->state) && hcd->state != HC_STATE_HALT);
 
 	local_irq_disable ();
 
@@ -1423,7 +1442,31 @@
 	return 0;
 }
 
+/**
+ * usb_hcd_resume_root_hub - called by HCD to resume its root hub 
+ * @hcd: host controller for this root hub
+ *
+ * The USB host controller calls this function when its root hub is
+ * suspended (with the remote wakeup feature enabled) and a remote
+ * wakeup request is received.  It queues a request for khubd to
+ * resume the root hub.
+ */
+void usb_hcd_resume_root_hub (struct usb_hcd *hcd)
+{
+	unsigned long flags;
+
+	spin_lock_irqsave (&hcd_root_hub_lock, flags);
+	if (hcd->rh_registered)
+		usb_resume_root_hub (hcd->self.root_hub);
+	spin_unlock_irqrestore (&hcd_root_hub_lock, flags);
+}
+
+#else
+void usb_hcd_resume_root_hub (struct usb_hcd *hcd)
+{
+}
 #endif
+EXPORT_SYMBOL_GPL(usb_hcd_resume_root_hub);
 
 /*-------------------------------------------------------------------------*/
 
@@ -1547,17 +1590,16 @@
 	struct usb_hcd		*hcd = __hcd;
 	int			start = hcd->state;
 
-	if (start == USB_STATE_HALT)
+	if (start == HC_STATE_HALT)
 		return IRQ_NONE;
 	if (hcd->driver->irq (hcd, r) == IRQ_NONE)
 		return IRQ_NONE;
 
 	hcd->saw_irq = 1;
-	if (hcd->state != start && hcd->state == USB_STATE_HALT)
+	if (hcd->state != start && hcd->state == HC_STATE_HALT)
 		usb_hc_died (hcd);
 	return IRQ_HANDLED;
 }
-EXPORT_SYMBOL (usb_hcd_irq);
 
 /*-------------------------------------------------------------------------*/
 
@@ -1571,12 +1613,21 @@
  */
 void usb_hc_died (struct usb_hcd *hcd)
 {
+	unsigned long flags;
+
 	dev_err (hcd->self.controller, "HC died; cleaning up\n");
 
-	/* make khubd clean up old urbs and devices */
-	usb_set_device_state(hcd->self.root_hub, USB_STATE_NOTATTACHED);
-	mod_timer(&hcd->rh_timer, jiffies);
+	spin_lock_irqsave (&hcd_root_hub_lock, flags);
+	if (hcd->rh_registered) {
+
+		/* make khubd clean up old urbs and devices */
+		usb_set_device_state (hcd->self.root_hub,
+				USB_STATE_NOTATTACHED);
+		usb_kick_khubd (hcd->self.root_hub);
+	}
+	spin_unlock_irqrestore (&hcd_root_hub_lock, flags);
 }
+EXPORT_SYMBOL_GPL (usb_hc_died);
 
 /*-------------------------------------------------------------------------*/
 
@@ -1688,13 +1739,15 @@
 		hcd->irq = irqnum;
 		dev_info(hcd->self.controller, "irq %s, %s 0x%08llx\n", bufp,
 				(hcd->driver->flags & HCD_MEMORY) ?
-					"io mem" : "io base", hcd->rsrc_start);
+					"io mem" : "io base",
+					(unsigned long long)hcd->rsrc_start);
 	} else {
 		hcd->irq = -1;
 		if (hcd->rsrc_start)
 			dev_info(hcd->self.controller, "%s 0x%08llx\n",
 					(hcd->driver->flags & HCD_MEMORY) ?
-					"io mem" : "io base", hcd->rsrc_start);
+					"io mem" : "io base",
+					(unsigned long long)hcd->rsrc_start);
 	}
 
 	if ((retval = hcd->driver->start(hcd)) < 0) {
@@ -1727,14 +1780,17 @@
 {
 	dev_info(hcd->self.controller, "remove, state %x\n", hcd->state);
 
-	if (HCD_IS_RUNNING (hcd->state))
-		hcd->state = USB_STATE_QUIESCING;
+	if (HC_IS_RUNNING (hcd->state))
+		hcd->state = HC_STATE_QUIESCING;
 
 	dev_dbg(hcd->self.controller, "roothub graceful disconnect\n");
+	spin_lock_irq (&hcd_root_hub_lock);
+	hcd->rh_registered = 0;
+	spin_unlock_irq (&hcd_root_hub_lock);
 	usb_disconnect(&hcd->self.root_hub);
 
 	hcd->driver->stop(hcd);
-	hcd->state = USB_STATE_HALT;
+	hcd->state = HC_STATE_HALT;
 
 	if (hcd->irq >= 0)
 		free_irq(hcd->irq, hcd);
diff -Nru a/drivers/usb/core/hcd.h b/drivers/usb/core/hcd.h
--- a/drivers/usb/core/hcd.h	2005-03-23 19:58:52 -08:00
+++ b/drivers/usb/core/hcd.h	2005-03-23 19:58:52 -08:00
@@ -74,6 +74,8 @@
 	unsigned		saw_irq : 1;
 	unsigned		can_wakeup:1;	/* hw supports wakeup? */
 	unsigned		remote_wakeup:1;/* sw should use wakeup? */
+	unsigned		rh_registered:1;/* is root hub registered? */
+
 	int			irq;		/* irq allocated */
 	void __iomem		*regs;		/* device memory/io */
 	u64			rsrc_start;	/* memory/io resource start */
@@ -87,14 +89,14 @@
 #	define	__SUSPEND		0x04
 #	define	__TRANSIENT		0x80
 
-#	define	USB_STATE_HALT		0
-#	define	USB_STATE_RUNNING	(__ACTIVE)
-#	define	USB_STATE_QUIESCING	(__SUSPEND|__TRANSIENT|__ACTIVE)
-#	define	USB_STATE_RESUMING	(__SUSPEND|__TRANSIENT)
-#	define	HCD_STATE_SUSPENDED	(__SUSPEND)
+#	define	HC_STATE_HALT		0
+#	define	HC_STATE_RUNNING	(__ACTIVE)
+#	define	HC_STATE_QUIESCING	(__SUSPEND|__TRANSIENT|__ACTIVE)
+#	define	HC_STATE_RESUMING	(__SUSPEND|__TRANSIENT)
+#	define	HC_STATE_SUSPENDED	(__SUSPEND)
 
-#define	HCD_IS_RUNNING(state) ((state) & __ACTIVE)
-#define	HCD_IS_SUSPENDED(state) ((state) & __SUSPEND)
+#define	HC_IS_RUNNING(state) ((state) & __ACTIVE)
+#define	HC_IS_SUSPENDED(state) ((state) & __SUSPEND)
 
 	/* more shared queuing code would be good; it should support
 	 * smarter scheduling, handle transaction translators, etc;
@@ -208,7 +210,6 @@
 };
 
 extern void usb_hcd_giveback_urb (struct usb_hcd *hcd, struct urb *urb, struct pt_regs *regs);
-extern void usb_bus_init (struct usb_bus *bus);
 
 extern struct usb_hcd *usb_create_hcd (const struct hc_driver *driver,
 		struct device *dev, char *bus_name);
@@ -340,25 +341,10 @@
 
 extern struct usb_bus *usb_alloc_bus (struct usb_operations *);
 
-extern int usb_register_bus (struct usb_bus *);
-extern void usb_deregister_bus (struct usb_bus *);
-
-extern int usb_register_root_hub (struct usb_device *usb_dev,
-		struct device *parent_dev);
-
-static inline int hcd_register_root (struct usb_device *usb_dev,
-		struct usb_hcd *hcd)
-{
-	/* hcd->driver->start() reported can_wakeup, probably with
-	 * assistance from board's boot firmware.
-	 * NOTE:  normal devices won't enable wakeup by default.
-	 */
-	if (hcd->can_wakeup)
-		dev_dbg (hcd->self.controller, "supports USB remote wakeup\n");
-	hcd->remote_wakeup = hcd->can_wakeup;
+extern int usb_hcd_register_root_hub (struct usb_device *usb_dev,
+		struct usb_hcd *hcd);
 
-	return usb_register_root_hub (usb_dev, hcd->self.controller);
-}
+extern void usb_hcd_resume_root_hub (struct usb_hcd *hcd);
 
 extern void usb_set_device_state(struct usb_device *udev,
 		enum usb_device_state new_state);
diff -Nru a/drivers/usb/core/hub.c b/drivers/usb/core/hub.c
--- a/drivers/usb/core/hub.c	2005-03-23 19:58:52 -08:00
+++ b/drivers/usb/core/hub.c	2005-03-23 19:58:52 -08:00
@@ -289,6 +289,11 @@
 	spin_unlock_irqrestore(&hub_event_lock, flags);
 }
 
+void usb_kick_khubd(struct usb_device *hdev)
+{
+	kick_khubd(hdev_to_hub(hdev));
+}
+
 
 /* completion function, fires on port status changes and various faults */
 static void hub_irq(struct urb *urb, struct pt_regs *regs)
@@ -1383,8 +1388,13 @@
 			dev_err(hub->intfdev,
 					"cannot reset port %d (err = %d)\n",
 					port1, status);
-		else
+		else {
 			status = hub_port_wait_reset(hub, port1, udev, delay);
+			if (status)
+				dev_dbg(hub->intfdev,
+						"port_wait_reset: err = %d\n",
+						status);
+		}
 
 		/* return on disconnect or reset */
 		switch (status) {
@@ -1533,7 +1543,8 @@
  * Linux (2.6) currently has NO mechanisms to initiate that:  no khubd
  * timer, no SRP, no requests through sysfs.
  */
-int __usb_suspend_device (struct usb_device *udev, int port1, pm_message_t state)
+static int __usb_suspend_device (struct usb_device *udev, int port1,
+				 pm_message_t state)
 {
 	int	status;
 
@@ -1614,9 +1625,11 @@
 		struct usb_bus	*bus = udev->bus;
 		if (bus && bus->op->hub_suspend) {
 			status = bus->op->hub_suspend (bus);
-			if (status == 0)
+			if (status == 0) {
+				dev_dbg(&udev->dev, "usb suspend\n");
 				usb_set_device_state(udev,
 						USB_STATE_SUSPENDED);
+			}
 		} else
 			status = -EOPNOTSUPP;
 	} else
@@ -1834,9 +1847,11 @@
 		} else
 			status = -EOPNOTSUPP;
 		if (status == 0) {
+			dev_dbg(&udev->dev, "usb resume\n");
 			/* TRSMRCY = 10 msec */
 			msleep(10);
 			usb_set_device_state (udev, USB_STATE_CONFIGURED);
+			udev->dev.power.power_state = PMSG_ON;
 			status = hub_resume (udev
 					->actconfig->interface[0]);
 		}
@@ -1955,10 +1970,19 @@
 	}
 	intf->dev.power.power_state = PMSG_ON;
 
+	hub->resume_root_hub = 0;
 	hub_activate(hub);
 	return 0;
 }
 
+void usb_resume_root_hub(struct usb_device *hdev)
+{
+	struct usb_hub *hub = hdev_to_hub(hdev);
+
+	hub->resume_root_hub = 1;
+	kick_khubd(hub);
+}
+
 #else	/* !CONFIG_USB_SUSPEND */
 
 int usb_suspend_device(struct usb_device *udev, u32 state)
@@ -2615,15 +2639,30 @@
 				(u16) hub->event_bits[0]);
 
 		usb_get_intf(intf);
+		i = hub->resume_root_hub;
 		spin_unlock_irq(&hub_event_lock);
 
+		/* Is this is a root hub wanting to be resumed? */
+		if (i)
+			usb_resume_device(hdev);
+
 		/* Lock the device, then check to see if we were
 		 * disconnected while waiting for the lock to succeed. */
 		if (locktree(hdev) < 0) {
 			usb_put_intf(intf);
 			continue;
 		}
-		if (hub != usb_get_intfdata(intf) || hub->quiescing)
+		if (hub != usb_get_intfdata(intf))
+			goto loop;
+
+		/* If the hub has died, clean up after it */
+		if (hdev->state == USB_STATE_NOTATTACHED) {
+			hub_pre_reset(hub);
+			goto loop;
+		}
+
+		/* If this is an inactive or suspended hub, do nothing */
+		if (hub->quiescing)
 			goto loop;
 
 		if (hub->error) {
@@ -2643,6 +2682,8 @@
 
 		/* deal with port status changes */
 		for (i = 1; i <= hub->descriptor->bNbrPorts; i++) {
+			if (test_bit(i, hub->busy_bits))
+				continue;
 			connect_change = test_bit(i, hub->change_bits);
 			if (!test_and_clear_bit(i, hub->event_bits) &&
 					!connect_change && !hub->activating)
@@ -2948,6 +2989,7 @@
 		hub_pre_reset(hub);
 	}
 
+	set_bit(port1, parent_hub->busy_bits);
 	for (i = 0; i < SET_CONFIG_TRIES; ++i) {
 
 		/* ep0 maxpacket size may change; let the HCD know about it.
@@ -2957,6 +2999,7 @@
 		if (ret >= 0)
 			break;
 	}
+	clear_bit(port1, parent_hub->busy_bits);
 	if (ret < 0)
 		goto re_enumerate;
  
diff -Nru a/drivers/usb/core/hub.h b/drivers/usb/core/hub.h
--- a/drivers/usb/core/hub.h	2005-03-23 19:58:52 -08:00
+++ b/drivers/usb/core/hub.h	2005-03-23 19:58:52 -08:00
@@ -205,6 +205,7 @@
 	unsigned long		event_bits[1];	/* status change bitmask */
 	unsigned long		change_bits[1];	/* ports with logical connect
 							status change */
+	unsigned long		busy_bits[1];	/* ports being reset */
 #if USB_MAXCHILDREN > 31 /* 8*sizeof(unsigned long) - 1 */
 #error event_bits[] is too short!
 #endif
@@ -216,6 +217,7 @@
 
 	unsigned		quiescing:1;
 	unsigned		activating:1;
+	unsigned		resume_root_hub:1;
 
 	unsigned		has_indicators:1;
 	enum hub_led_mode	indicator[USB_MAXCHILDREN];
diff -Nru a/drivers/usb/core/message.c b/drivers/usb/core/message.c
--- a/drivers/usb/core/message.c	2005-03-23 19:58:52 -08:00
+++ b/drivers/usb/core/message.c	2005-03-23 19:58:52 -08:00
@@ -90,8 +90,10 @@
 
 /*-------------------------------------------------------------------*/
 // returns status (negative) or length (positive)
-int usb_internal_control_msg(struct usb_device *usb_dev, unsigned int pipe, 
-			    struct usb_ctrlrequest *cmd,  void *data, int len, int timeout)
+static int usb_internal_control_msg(struct usb_device *usb_dev,
+				    unsigned int pipe, 
+				    struct usb_ctrlrequest *cmd,
+				    void *data, int len, int timeout)
 {
 	struct urb *urb;
 	int retv;
@@ -1041,8 +1043,8 @@
  *
  * Enables all the endpoints for the interface's current altsetting.
  */
-void usb_enable_interface(struct usb_device *dev,
-		struct usb_interface *intf)
+static void usb_enable_interface(struct usb_device *dev,
+				 struct usb_interface *intf)
 {
 	struct usb_host_interface *alt = intf->cur_altsetting;
 	int i;
diff -Nru a/drivers/usb/core/usb.c b/drivers/usb/core/usb.c
--- a/drivers/usb/core/usb.c	2005-03-23 19:58:52 -08:00
+++ b/drivers/usb/core/usb.c	2005-03-23 19:58:52 -08:00
@@ -60,7 +60,7 @@
 
 const char *usbcore_name = "usbcore";
 
-int nousb;		/* Disable USB when built into kernel image */
+static int nousb;	/* Disable USB when built into kernel image */
 			/* Not honored on modular build */
 
 static DECLARE_RWSEM(usb_all_devices_rwsem);
@@ -86,7 +86,7 @@
 static int usb_generic_driver_data;
 
 /* called from driver core with usb_bus_type.subsys writelock */
-int usb_probe_interface(struct device *dev)
+static int usb_probe_interface(struct device *dev)
 {
 	struct usb_interface * intf = to_usb_interface(dev);
 	struct usb_driver * driver = to_usb_driver(dev->driver);
@@ -114,7 +114,7 @@
 }
 
 /* called from driver core with usb_bus_type.subsys writelock */
-int usb_unbind_interface(struct device *dev)
+static int usb_unbind_interface(struct device *dev)
 {
 	struct usb_interface *intf = to_usb_interface(dev);
 	struct usb_driver *driver = to_usb_driver(intf->dev.driver);
@@ -1148,6 +1148,7 @@
  *
  * Reverse the effect of this call with usb_buffer_unmap().
  */
+#if 0
 struct urb *usb_buffer_map (struct urb *urb)
 {
 	struct usb_bus		*bus;
@@ -1177,6 +1178,7 @@
 				| URB_NO_SETUP_DMA_MAP);
 	return urb;
 }
+#endif  /*  0  */
 
 /* XXX DISABLED, no users currently.  If you wish to re-enable this
  * XXX please determine whether the sync is to transfer ownership of
@@ -1221,6 +1223,7 @@
  *
  * Reverses the effect of usb_buffer_map().
  */
+#if 0
 void usb_buffer_unmap (struct urb *urb)
 {
 	struct usb_bus		*bus;
@@ -1247,6 +1250,7 @@
 	urb->transfer_flags &= ~(URB_NO_TRANSFER_DMA_MAP
 				| URB_NO_SETUP_DMA_MAP);
 }
+#endif  /*  0  */
 
 /**
  * usb_buffer_map_sg - create scatterlist DMA mapping(s) for an endpoint
@@ -1527,11 +1531,11 @@
 EXPORT_SYMBOL (usb_buffer_alloc);
 EXPORT_SYMBOL (usb_buffer_free);
 
-EXPORT_SYMBOL (usb_buffer_map);
 #if 0
+EXPORT_SYMBOL (usb_buffer_map);
 EXPORT_SYMBOL (usb_buffer_dmasync);
-#endif
 EXPORT_SYMBOL (usb_buffer_unmap);
+#endif
 
 EXPORT_SYMBOL (usb_buffer_map_sg);
 #if 0
diff -Nru a/drivers/usb/core/usb.h b/drivers/usb/core/usb.h
--- a/drivers/usb/core/usb.h	2005-03-23 19:58:52 -08:00
+++ b/drivers/usb/core/usb.h	2005-03-23 19:58:52 -08:00
@@ -4,8 +4,6 @@
 extern void usb_remove_sysfs_dev_files (struct usb_device *dev);
 extern void usb_create_sysfs_intf_files (struct usb_interface *intf);
 extern void usb_remove_sysfs_intf_files (struct usb_interface *intf);
-extern int usb_probe_interface (struct device *dev);
-extern int usb_unbind_interface (struct device *dev);
 
 extern void usb_disable_endpoint (struct usb_device *dev, unsigned int epaddr);
 extern void usb_disable_interface (struct usb_device *dev,
@@ -13,15 +11,15 @@
 extern void usb_release_interface_cache(struct kref *ref);
 extern void usb_disable_device (struct usb_device *dev, int skip_ep0);
 
-extern void usb_enable_interface (struct usb_device *dev,
-		struct usb_interface *intf);
-
 extern int usb_get_device_descriptor(struct usb_device *dev,
 		unsigned int size);
 extern int usb_set_configuration(struct usb_device *dev, int configuration);
 
 extern void usb_lock_all_devices(void);
 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);
 
 /* for labeling diagnostics */
 extern const char *usbcore_name;
diff -Nru a/drivers/usb/gadget/Kconfig b/drivers/usb/gadget/Kconfig
--- a/drivers/usb/gadget/Kconfig	2005-03-23 19:58:52 -08:00
+++ b/drivers/usb/gadget/Kconfig	2005-03-23 19:58:52 -08:00
@@ -135,21 +135,6 @@
 	depends on USB_GADGET_GOKU
 	default USB_GADGET
 
-# this could be built elsewhere (doesn't yet exist)
-config USB_GADGET_SA1100
-	boolean "SA 1100"
-	depends on ARCH_SA1100
-	help
-	   Intel's SA-1100 is an ARM-4 processor with an integrated
-	   full speed USB 1.1 device controller.
-
-	   It has two fixed-function endpoints, as well as endpoint
-	   zero (for control transfers).
-
-config USB_SA1100
-	tristate
-	depends on USB_GADGET_SA1100
-	default USB_GADGET
 
 config USB_GADGET_LH7A40X
 	boolean "LH7A40X"
@@ -163,34 +148,6 @@
 	default USB_GADGET
 
 
-config USB_GADGET_DUMMY_HCD
-	boolean "Dummy HCD (DEVELOPMENT)"
-	depends on USB && EXPERIMENTAL
-	select USB_GADGET_DUALSPEED
-	help
-	  This host controller driver emulates USB, looping all data transfer
-	  requests back to a USB "gadget driver" in the same host.  The host
-	  side is the master; the gadget side is the slave.  Gadget drivers
-	  can be high, full, or low speed; and they have access to endpoints
-	  like those from NET2280, PXA2xx, or SA1100 hardware.
-	  
-	  This may help in some stages of creating a driver to embed in a
-	  Linux device, since it lets you debug several parts of the gadget
-	  driver without its hardware or drivers being involved.
-	  
-	  Since such a gadget side driver needs to interoperate with a host
-	  side Linux-USB device driver, this may help to debug both sides
-	  of a USB protocol stack.
-
-	  Say "y" to link the driver statically, or "m" to build a
-	  dynamically linked module called "dummy_hcd" and force all
-	  gadget drivers to also be dynamically linked.
-
-config USB_DUMMY_HCD
-	tristate
-	depends on USB_GADGET_DUMMY_HCD
-	default USB_GADGET
-
 config USB_GADGET_OMAP
 	boolean "OMAP USB Device Controller"
 	depends on ARCH_OMAP
@@ -221,6 +178,38 @@
 	   later, when two dual-role devices talk to each other.
 
 	   Select this only if your OMAP board has a Mini-AB connector.
+
+
+config USB_GADGET_DUMMY_HCD
+	boolean "Dummy HCD (DEVELOPMENT)"
+	depends on USB && EXPERIMENTAL
+	select USB_GADGET_DUALSPEED
+	help
+	  This host controller driver emulates USB, looping all data transfer
+	  requests back to a USB "gadget driver" in the same host.  The host
+	  side is the master; the gadget side is the slave.  Gadget drivers
+	  can be high, full, or low speed; and they have access to endpoints
+	  like those from NET2280, PXA2xx, or SA1100 hardware.
+	  
+	  This may help in some stages of creating a driver to embed in a
+	  Linux device, since it lets you debug several parts of the gadget
+	  driver without its hardware or drivers being involved.
+	  
+	  Since such a gadget side driver needs to interoperate with a host
+	  side Linux-USB device driver, this may help to debug both sides
+	  of a USB protocol stack.
+
+	  Say "y" to link the driver statically, or "m" to build a
+	  dynamically linked module called "dummy_hcd" and force all
+	  gadget drivers to also be dynamically linked.
+
+config USB_DUMMY_HCD
+	tristate
+	depends on USB_GADGET_DUMMY_HCD
+	default USB_GADGET
+
+# NOTE:  Please keep dummy_hcd LAST so that "real hardware" appears
+# first and will be selected by default.
 
 endchoice
 
diff -Nru a/drivers/usb/gadget/dummy_hcd.c b/drivers/usb/gadget/dummy_hcd.c
--- a/drivers/usb/gadget/dummy_hcd.c	2005-03-23 19:58:52 -08:00
+++ b/drivers/usb/gadget/dummy_hcd.c	2005-03-23 19:58:52 -08:00
@@ -1647,11 +1647,11 @@
 		return -ENOMEM;
 
 	/* root hub enters addressed state... */
-	hcd->state = USB_STATE_RUNNING;
+	hcd->state = HC_STATE_RUNNING;
 	root->speed = USB_SPEED_HIGH;
 
 	/* ...then configured, so khubd sees us. */
-	if ((retval = hcd_register_root (root, hcd)) != 0) {
+	if ((retval = usb_hcd_register_root_hub (root, hcd)) != 0) {
 		goto err1;
 	}
 
@@ -1669,7 +1669,7 @@
 	usb_disconnect (&hcd->self.root_hub);
  err1:
 	usb_put_dev (root);
-	hcd->state = USB_STATE_QUIESCING;
+	hcd->state = HC_STATE_QUIESCING;
 	return retval;
 }
 
diff -Nru a/drivers/usb/gadget/ether.c b/drivers/usb/gadget/ether.c
--- a/drivers/usb/gadget/ether.c	2005-03-23 19:58:52 -08:00
+++ b/drivers/usb/gadget/ether.c	2005-03-23 19:58:52 -08:00
@@ -1,7 +1,7 @@
 /*
  * ether.c -- Ethernet gadget driver, with CDC and non-CDC options
  *
- * Copyright (C) 2003-2004 David Brownell
+ * Copyright (C) 2003-2005 David Brownell
  * Copyright (C) 2003-2004 Robert Schwebel, Benedikt Spranger
  *
  * This program is free software; you can redistribute it and/or modify
@@ -98,12 +98,18 @@
 #define rndis_exit() do{}while(0)
 #endif
 
+/* CDC and RNDIS support the same host-chosen outgoing packet filters. */
+#define	DEFAULT_FILTER	(USB_CDC_PACKET_TYPE_BROADCAST \
+ 			|USB_CDC_PACKET_TYPE_DIRECTED)
+
+
 /*-------------------------------------------------------------------------*/
 
 struct eth_dev {
 	spinlock_t		lock;
 	struct usb_gadget	*gadget;
 	struct usb_request	*req;		/* for control responses */
+	struct usb_request	*stat_req;	/* for cdc & rndis status */
 
 	u8			config;
 	struct usb_ep		*in_ep, *out_ep, *status_ep;
@@ -243,6 +249,10 @@
 #define DEV_CONFIG_CDC
 #endif
 
+#ifdef CONFIG_USB_GADGET_AT91
+#define DEV_CONFIG_CDC
+#endif
+
 
 /* For CDC-incapable hardware, choose the simple cdc subset.
  * Anything that talks bulk (without notable bugs) can do this.
@@ -266,8 +276,39 @@
 
 /*-------------------------------------------------------------------------*/
 
+/* "main" config is either CDC, or its simple subset */
+static inline int is_cdc(struct eth_dev *dev)
+{
+#if	!defined(DEV_CONFIG_SUBSET)
+	return 1;		/* only cdc possible */
+#elif	!defined (DEV_CONFIG_CDC)
+	return 0;		/* only subset possible */
+#else
+	return dev->cdc;	/* depends on what hardware we found */
+#endif
+}
+
+/* "secondary" RNDIS config may sometimes be activated */
+static inline int rndis_active(struct eth_dev *dev)
+{
+#ifdef	CONFIG_USB_ETH_RNDIS
+	return dev->rndis;
+#else
+	return 0;
+#endif
+}
+
+#define	subset_active(dev)	(!is_cdc(dev) && !rndis_active(dev))
+#define	cdc_active(dev)		( is_cdc(dev) && !rndis_active(dev))
+
+
+
 #define DEFAULT_QLEN	2	/* double buffering by default */
 
+/* peak bulk transfer bits-per-second */
+#define	HS_BPS 		(13 * 512 * 8 * 1000 * 8)
+#define	FS_BPS		(19 *  64 * 1 * 1000 * 8)
+
 #ifdef CONFIG_USB_GADGET_DUALSPEED
 
 static unsigned qmult = 5;
@@ -281,12 +322,12 @@
 /* also defer IRQs on highspeed TX */
 #define TX_DELAY	qmult
 
-#define	BITRATE(g) ((g->speed == USB_SPEED_HIGH) ? 4800000 : 120000)
+#define	BITRATE(g)	(((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)	(12000)
+#define	BITRATE(g)	FS_BPS
 #endif
 
 
@@ -519,9 +560,8 @@
 #if defined(DEV_CONFIG_CDC) || defined(CONFIG_USB_ETH_RNDIS)
 
 /* include the status endpoint if we can, even where it's optional.
- * use small wMaxPacketSize, since many "interrupt" endpoints have
- * very small fifos and it's no big deal if CDC_NOTIFY_SPEED_CHANGE
- * takes two packets.  also default to a big transfer interval, to
+ * use wMaxPacketSize big enough to fit CDC_NOTIFY_SPEED_CHANGE in one
+ * packet, to simplify cancelation; and a big transfer interval, to
  * waste less bandwidth.
  *
  * some drivers (like Linux 2.4 cdc-ether!) "need" it to exist even
@@ -534,7 +574,7 @@
  */
  
 #define LOG2_STATUS_INTERVAL_MSEC	5	/* 1 << 5 == 32 msec */
-#define STATUS_BYTECOUNT		8	/* 8 byte header + data */
+#define STATUS_BYTECOUNT		16	/* 8 byte header + data */
 
 static struct usb_endpoint_descriptor
 fs_status_desc = {
@@ -916,14 +956,12 @@
 	if (strcmp (ep->name, EP_IN_NAME) == 0) {
 		d = ep_desc (dev->gadget, &hs_source_desc, &fs_source_desc);
 		ep->driver_data = dev;
-		dev->in_ep = ep;
 		dev->in = d;
 
 	/* one endpoint just reads OUT packets */
 	} else if (strcmp (ep->name, EP_OUT_NAME) == 0) {
 		d = ep_desc (dev->gadget, &hs_sink_desc, &fs_sink_desc);
 		ep->driver_data = dev;
-		dev->out_ep = ep;
 		dev->out = d;
 
 	/* optional status/notification endpoint */
@@ -937,7 +975,6 @@
 			return result;
 
 		ep->driver_data = dev;
-		dev->status_ep = ep;
 		dev->status = d;
 	}
 	return 0;
@@ -964,7 +1001,6 @@
 			return result;
 
 		ep->driver_data = dev;
-		dev->in_ep = ep;
 		dev->in = d;
 
 	/* one endpoint just reads OUT packets */
@@ -975,7 +1011,6 @@
 			return result;
 
 		ep->driver_data = dev;
-		dev->out_ep = ep;
 		dev->out = d;
 	}
 
@@ -1006,7 +1041,6 @@
 			result = usb_ep_enable (ep, d);
 			if (result == 0) {
 				ep->driver_data = dev;
-				dev->status_ep = ep;
 				dev->status = d;
 				continue;
 			}
@@ -1034,22 +1068,19 @@
 	/* on error, disable any endpoints  */
 	if (result < 0) {
 #if defined(DEV_CONFIG_CDC) || defined(CONFIG_USB_ETH_RNDIS)
-		if (dev->status_ep)
+		if (dev->status)
 			(void) usb_ep_disable (dev->status_ep);
 #endif
-		dev->status_ep = NULL;
 		dev->status = NULL;
 #if defined(DEV_CONFIG_SUBSET) || defined(CONFIG_USB_ETH_RNDIS)
 		if (dev->rndis || !dev->cdc) {
-			if (dev->in_ep)
+			if (dev->in)
 				(void) usb_ep_disable (dev->in_ep);
-			if (dev->out_ep)
+			if (dev->out)
 				(void) usb_ep_disable (dev->out_ep);
 		}
 #endif
-		dev->in_ep = NULL;
 		dev->in = NULL;
-		dev->out_ep = NULL;
 		dev->out = NULL;
 	} else
 
@@ -1089,7 +1120,7 @@
 	/* disable endpoints, forcing (synchronous) completion of
 	 * pending i/o.  then free the requests.
 	 */
-	if (dev->in_ep) {
+	if (dev->in) {
 		usb_ep_disable (dev->in_ep);
 		while (likely (!list_empty (&dev->tx_reqs))) {
 			req = container_of (dev->tx_reqs.next,
@@ -1097,9 +1128,8 @@
 			list_del (&req->list);
 			usb_ep_free_request (dev->in_ep, req);
 		}
-		dev->in_ep = NULL;
 	}
-	if (dev->out_ep) {
+	if (dev->out) {
 		usb_ep_disable (dev->out_ep);
 		while (likely (!list_empty (&dev->rx_reqs))) {
 			req = container_of (dev->rx_reqs.next,
@@ -1107,12 +1137,10 @@
 			list_del (&req->list);
 			usb_ep_free_request (dev->out_ep, req);
 		}
-		dev->out_ep = NULL;
 	}
 
-	if (dev->status_ep) {
+	if (dev->status) {
 		usb_ep_disable (dev->status_ep);
-		dev->status_ep = NULL;
 	}
 	dev->config = 0;
 }
@@ -1213,28 +1241,22 @@
 		event->wLength = __constant_cpu_to_le16 (8);
 
 		/* SPEED_CHANGE data is up/down speeds in bits/sec */
-		data [0] = data [1] = cpu_to_le32(
-			(dev->gadget->speed == USB_SPEED_HIGH)
-				? (13 * 512 * 8 * 1000 * 8)
-				: (19 *  64 * 1 * 1000 * 8));
+		data [0] = data [1] = cpu_to_le32 (BITRATE (dev->gadget));
 
-		req->length = 16;
+		req->length = STATUS_BYTECOUNT;
 		value = usb_ep_queue (ep, req, GFP_ATOMIC);
 		DEBUG (dev, "send SPEED_CHANGE --> %d\n", value);
 		if (value == 0)
 			return;
-	} else
+	} else if (value != -ECONNRESET)
 		DEBUG (dev, "event %02x --> %d\n",
 			event->bNotificationType, value);
-
-	/* free when done */
-	usb_ep_free_buffer (ep, req->buf, req->dma, 16);
-	usb_ep_free_request (ep, req);
+	event->bmRequestType = 0xff;
 }
 
 static void issue_start_status (struct eth_dev *dev)
 {
-	struct usb_request		*req;
+	struct usb_request		*req = dev->stat_req;
 	struct usb_cdc_notification	*event;
 	int				value;
  
@@ -1250,21 +1272,6 @@
 	usb_ep_disable (dev->status_ep);
 	usb_ep_enable (dev->status_ep, dev->status);
 
-	/* FIXME make these allocations static like dev->req */
-	req = usb_ep_alloc_request (dev->status_ep, GFP_ATOMIC);
-	if (req == 0) {
-		DEBUG (dev, "status ENOMEM\n");
-		return;
-	}
-	req->buf = usb_ep_alloc_buffer (dev->status_ep, 16,
-				&dev->req->dma, GFP_ATOMIC);
-	if (req->buf == 0) {
-		DEBUG (dev, "status buf ENOMEM\n");
-free_req:
-		usb_ep_free_request (dev->status_ep, req);
-		return;
-	}
-
 	/* 3.8.1 says to issue first NETWORK_CONNECTION, then
 	 * a SPEED_CHANGE.  could be useful in some configs.
 	 */
@@ -1275,15 +1282,11 @@
 	event->wIndex = __constant_cpu_to_le16 (1);
 	event->wLength = 0;
 
-	req->length = 8;
+	req->length = sizeof *event;
 	req->complete = eth_status_complete;
 	value = usb_ep_queue (dev->status_ep, req, GFP_ATOMIC);
-	if (value < 0) {
+	if (value < 0)
 		DEBUG (dev, "status buf queue --> %d\n", value);
-		usb_ep_free_buffer (dev->status_ep,
-				req->buf, dev->req->dma, 16);
-		goto free_req;
-	}
 }
 
 #endif
@@ -1431,7 +1434,7 @@
 		case 0:		/* control/master intf */
 			if (wValue != 0)
 				break;
-			if (dev->status_ep) {
+			if (dev->status) {
 				usb_ep_disable (dev->status_ep);
 				usb_ep_enable (dev->status_ep, dev->status);
 			}
@@ -1450,8 +1453,9 @@
 			if (wValue == 1) {
 				usb_ep_enable (dev->in_ep, dev->in);
 				usb_ep_enable (dev->out_ep, dev->out);
+				dev->cdc_filter = DEFAULT_FILTER;
 				netif_carrier_on (dev->net);
-				if (dev->status_ep)
+				if (dev->status)
 					issue_start_status (dev);
 				if (netif_running (dev->net)) {
 					spin_unlock (&dev->lock);
@@ -1502,14 +1506,18 @@
 				|| wLength != 0
 				|| wIndex > 1)
 			break;
-		DEBUG (dev, "NOP packet filter %04x\n", wValue);
-		/* NOTE: table 62 has 5 filter bits to reduce traffic,
-		 * and we "must" support multicast and promiscuous.
-		 * this NOP implements a bad filter (always promisc)
-		 */
+		DEBUG (dev, "packet filter %02x\n", wValue);
 		dev->cdc_filter = wValue;
 		value = 0;
 		break;
+
+	/* and potentially:
+	 * case USB_CDC_SET_ETHERNET_MULTICAST_FILTERS:
+	 * case USB_CDC_SET_ETHERNET_PM_PATTERN_FILTER:
+	 * case USB_CDC_GET_ETHERNET_PM_PATTERN_FILTER:
+	 * case USB_CDC_GET_ETHERNET_STATISTIC:
+	 */
+
 #endif /* DEV_CONFIG_CDC */
 
 #ifdef CONFIG_USB_ETH_RNDIS		
@@ -1904,6 +1912,14 @@
 		netif_wake_queue (dev->net);
 }
 
+static inline int eth_is_promisc (struct eth_dev *dev)
+{
+	/* no filters for the CDC subset; always promisc */
+	if (subset_active (dev))
+		return 1;
+	return dev->cdc_filter & USB_CDC_PACKET_TYPE_PROMISCUOUS;
+}
+
 static int eth_start_xmit (struct sk_buff *skb, struct net_device *net)
 {
 	struct eth_dev		*dev = netdev_priv(net);
@@ -1912,10 +1928,27 @@
 	struct usb_request	*req = NULL;
 	unsigned long		flags;
 
-	/* FIXME check dev->cdc_filter to decide whether to send this,
-	 * instead of acting as if USB_CDC_PACKET_TYPE_PROMISCUOUS were
-	 * always set.  RNDIS has the same kind of outgoing filter.
-	 */
+	/* apply outgoing CDC or RNDIS filters */
+	if (!eth_is_promisc (dev)) {
+		u8		*dest = skb->data;
+
+		if (dest [0] & 0x01) {
+			u16	type;
+
+			/* ignores USB_CDC_PACKET_TYPE_MULTICAST and host
+			 * SET_ETHERNET_MULTICAST_FILTERS requests
+			 */
+			if (memcmp (dest, net->broadcast, ETH_ALEN) == 0)
+				type = USB_CDC_PACKET_TYPE_BROADCAST;
+			else
+				type = USB_CDC_PACKET_TYPE_ALL_MULTICAST;
+			if (!(dev->cdc_filter & type)) {
+				dev_kfree_skb_any (skb);
+				return 0;
+			}
+		}
+		/* ignores USB_CDC_PACKET_TYPE_DIRECTED */
+	}
 
 	spin_lock_irqsave (&dev->lock, flags);
 	req = container_of (dev->tx_reqs.next, struct usb_request, list);
@@ -2137,6 +2170,30 @@
 
 /*-------------------------------------------------------------------------*/
 
+static struct usb_request *eth_req_alloc (struct usb_ep *ep, unsigned size)
+{
+	struct usb_request	*req;
+
+	req = usb_ep_alloc_request (ep, GFP_KERNEL);
+	if (!req)
+		return NULL;
+
+	req->buf = kmalloc (size, GFP_KERNEL);
+	if (!req->buf) {
+		usb_ep_free_request (ep, req);
+		req = NULL;
+	}
+	return req;
+}
+
+static void
+eth_req_free (struct usb_ep *ep, struct usb_request *req)
+{
+	kfree (req->buf);
+	usb_ep_free_request (ep, req);
+}
+
+
 static void
 eth_unbind (struct usb_gadget *gadget)
 {
@@ -2150,12 +2207,13 @@
 
 	/* we've already been disconnected ... no i/o is active */
 	if (dev->req) {
-		usb_ep_free_buffer (gadget->ep0,
-				dev->req->buf, dev->req->dma,
-				USB_BUFSIZ);
-		usb_ep_free_request (gadget->ep0, dev->req);
+		eth_req_free (gadget->ep0, dev->req);
 		dev->req = NULL;
 	}
+	if (dev->stat_req) {
+		eth_req_free (dev->status_ep, dev->stat_req);
+		dev->stat_req = NULL;
+	}
 
 	unregister_netdev (dev->net);
 	free_netdev(dev->net);
@@ -2201,7 +2259,7 @@
 	struct eth_dev		*dev;
 	struct net_device	*net;
 	u8			cdc = 1, zlp = 1, rndis = 1;
-	struct usb_ep		*ep;
+	struct usb_ep		*in_ep, *out_ep, *status_ep = NULL;
 	int			status = -ENOMEM;
 
 	/* these flags are only ever cleared; compiler take note */
@@ -2251,6 +2309,8 @@
 		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_at91(gadget)) {
+		device_desc.bcdDevice = __constant_cpu_to_le16 (0x0213);
 	} else {
 		/* can't assume CDC works.  don't want to default to
 		 * anything less functional on CDC-capable hardware,
@@ -2308,32 +2368,32 @@
 
 	/* all we really need is bulk IN/OUT */
 	usb_ep_autoconfig_reset (gadget);
-	ep = usb_ep_autoconfig (gadget, &fs_source_desc);
-	if (!ep) {
+	in_ep = usb_ep_autoconfig (gadget, &fs_source_desc);
+	if (!in_ep) {
 autoconf_fail:
 		dev_err (&gadget->dev,
 			"can't autoconfigure on %s\n",
 			gadget->name);
 		return -ENODEV;
 	}
-	EP_IN_NAME = ep->name;
-	ep->driver_data = ep;	/* claim */
+	EP_IN_NAME = in_ep->name;
+	in_ep->driver_data = in_ep;	/* claim */
 	
-	ep = usb_ep_autoconfig (gadget, &fs_sink_desc);
-	if (!ep)
+	out_ep = usb_ep_autoconfig (gadget, &fs_sink_desc);
+	if (!out_ep)
 		goto autoconf_fail;
-	EP_OUT_NAME = ep->name;
-	ep->driver_data = ep;	/* claim */
+	EP_OUT_NAME = out_ep->name;
+	out_ep->driver_data = out_ep;	/* claim */
 
 #if defined(DEV_CONFIG_CDC) || defined(CONFIG_USB_ETH_RNDIS)
 	/* CDC Ethernet control interface doesn't require a status endpoint.
 	 * Since some hosts expect one, try to allocate one anyway.
 	 */
 	if (cdc || rndis) {
-		ep = usb_ep_autoconfig (gadget, &fs_status_desc);
-		if (ep) {
-			EP_STATUS_NAME = ep->name;
-			ep->driver_data = ep;	/* claim */
+		status_ep = usb_ep_autoconfig (gadget, &fs_status_desc);
+		if (status_ep) {
+			EP_STATUS_NAME = status_ep->name;
+			status_ep->driver_data = status_ep;	/* claim */
 		} else if (rndis) {
 			dev_err (&gadget->dev,
 				"can't run RNDIS on %s\n",
@@ -2409,6 +2469,10 @@
 	dev->cdc = cdc;
 	dev->zlp = zlp;
 
+	dev->in_ep = in_ep;
+	dev->out_ep = out_ep;
+	dev->status_ep = status_ep;
+
 	/* Module params for these addresses should come from ID proms.
 	 * The host side address is used with CDC and RNDIS, and commonly
 	 * ends up in a persistent config database.
@@ -2442,16 +2506,20 @@
 	// set_multicast_list
 	SET_ETHTOOL_OPS(net, &ops);
 
-	/* preallocate control response and buffer */
-	dev->req = usb_ep_alloc_request (gadget->ep0, GFP_KERNEL);
+	/* preallocate control message data and buffer */
+	dev->req = eth_req_alloc (gadget->ep0, USB_BUFSIZ);
 	if (!dev->req)
 		goto fail;
 	dev->req->complete = eth_setup_complete;
-	dev->req->buf = usb_ep_alloc_buffer (gadget->ep0, USB_BUFSIZ,
-				&dev->req->dma, GFP_KERNEL);
-	if (!dev->req->buf) {
-		usb_ep_free_request (gadget->ep0, dev->req);
-		goto fail;
+
+	/* ... and maybe likewise for status transfer */
+	if (dev->status_ep) {
+		dev->stat_req = eth_req_alloc (dev->status_ep,
+					STATUS_BYTECOUNT);
+		if (!dev->stat_req) {
+			eth_req_free (gadget->ep0, dev->req);
+			goto fail;
+		}
 	}
 
 	/* finish hookup to lower layer ... */
diff -Nru a/drivers/usb/gadget/file_storage.c b/drivers/usb/gadget/file_storage.c
--- a/drivers/usb/gadget/file_storage.c	2005-03-23 19:58:53 -08:00
+++ b/drivers/usb/gadget/file_storage.c	2005-03-23 19:58:53 -08:00
@@ -1,7 +1,7 @@
 /*
  * file_storage.c -- File-backed USB Storage Gadget, for USB development
  *
- * Copyright (C) 2003, 2004 Alan Stern
+ * Copyright (C) 2003-2005 Alan Stern
  * All rights reserved.
  *
  * Redistribution and use in source and binary forms, with or without
@@ -832,6 +832,8 @@
 #define STRING_MANUFACTURER	1
 #define STRING_PRODUCT		2
 #define STRING_SERIAL		3
+#define STRING_CONFIG		4
+#define STRING_INTERFACE	5
 
 /* There is only one configuration. */
 #define	CONFIG_VALUE		1
@@ -863,6 +865,7 @@
 	/* wTotalLength computed by usb_gadget_config_buf() */
 	.bNumInterfaces =	1,
 	.bConfigurationValue =	CONFIG_VALUE,
+	.iConfiguration =	STRING_CONFIG,
 	.bmAttributes =		USB_CONFIG_ATT_ONE | USB_CONFIG_ATT_SELFPOWER,
 	.bMaxPower =		1,	// self-powered
 };
@@ -886,6 +889,7 @@
 	.bInterfaceClass =	USB_CLASS_MASS_STORAGE,
 	.bInterfaceSubClass =	USB_SC_SCSI,	// Adjusted during fsg_bind()
 	.bInterfaceProtocol =	USB_PR_BULK,	// Adjusted during fsg_bind()
+	.iInterface =		STRING_INTERFACE,
 };
 
 /* Three full-speed endpoint descriptors: bulk-in, bulk-out,
@@ -1009,7 +1013,7 @@
 
 /* The CBI specification limits the serial string to 12 uppercase hexadecimal
  * characters. */
-static char				manufacturer[50];
+static char				manufacturer[64];
 static char				serial[13];
 
 /* Static strings, in UTF-8 (for simplicity we use only ASCII characters) */
@@ -1017,6 +1021,8 @@
 	{STRING_MANUFACTURER,	manufacturer},
 	{STRING_PRODUCT,	longname},
 	{STRING_SERIAL,		serial},
+	{STRING_CONFIG,		"Self-powered"},
+	{STRING_INTERFACE,	"Mass Storage"},
 	{}
 };
 
@@ -3740,6 +3746,10 @@
 			mod_data.release = 0x0310;
 		else if (gadget_is_pxa27x(fsg->gadget))
 			mod_data.release = 0x0311;
+		else if (gadget_is_s3c2410(gadget))
+			mod_data.release = 0x0312;
+		else if (gadget_is_at91(fsg->gadget))
+			mod_data.release = 0x0313;
 		else {
 			WARN(fsg, "controller '%s' not recognized\n",
 				fsg->gadget->name);
diff -Nru a/drivers/usb/gadget/gadget_chips.h b/drivers/usb/gadget/gadget_chips.h
--- a/drivers/usb/gadget/gadget_chips.h	2005-03-23 19:58:52 -08:00
+++ b/drivers/usb/gadget/gadget_chips.h	2005-03-23 19:58:52 -08:00
@@ -80,7 +80,12 @@
 #define gadget_is_s3c2410(g)    0
 #endif
 
-// CONFIG_USB_GADGET_AT91RM9200
+#ifdef CONFIG_USB_GADGET_AT91
+#define gadget_is_at91(g)	!strcmp("at91_udc", (g)->name)
+#else
+#define gadget_is_at91(g)	0
+#endif
+
 // CONFIG_USB_GADGET_SX2
 // CONFIG_USB_GADGET_AU1X00
 // ...
diff -Nru a/drivers/usb/gadget/net2280.c b/drivers/usb/gadget/net2280.c
--- a/drivers/usb/gadget/net2280.c	2005-03-23 19:58:52 -08:00
+++ b/drivers/usb/gadget/net2280.c	2005-03-23 19:58:52 -08:00
@@ -1270,7 +1270,7 @@
 	}
 
 	spin_unlock_irqrestore (&ep->dev->lock, flags);
-	return req ? 0 : -EOPNOTSUPP;
+	return 0;
 }
 
 /*-------------------------------------------------------------------------*/
diff -Nru a/drivers/usb/gadget/serial.c b/drivers/usb/gadget/serial.c
--- a/drivers/usb/gadget/serial.c	2005-03-23 19:58:52 -08:00
+++ b/drivers/usb/gadget/serial.c	2005-03-23 19:58:52 -08:00
@@ -1461,6 +1461,9 @@
 	} else if (gadget_is_s3c2410(gadget)) {
 		gs_device_desc.bcdDevice =
 			__constant_cpu_to_le16(GS_VERSION_NUM|0x0012);
+	} else if (gadget_is_at91(gadget)) {
+		gs_device_desc.bcdDevice =
+			__constant_cpu_to_le16(GS_VERSION_NUM|0x0013);
 	} else {
 		printk(KERN_WARNING "gs_bind: controller '%s' not recognized\n",
 			gadget->name);
diff -Nru a/drivers/usb/gadget/zero.c b/drivers/usb/gadget/zero.c
--- a/drivers/usb/gadget/zero.c	2005-03-23 19:58:52 -08:00
+++ b/drivers/usb/gadget/zero.c	2005-03-23 19:58:52 -08:00
@@ -1193,6 +1193,8 @@
 		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_at91(gadget)) {
+		device_desc.bcdDevice = __constant_cpu_to_le16 (0x0213);
 	} else {
 		/* gadget zero is so simple (for now, no altsettings) that
 		 * it SHOULD NOT have problems with bulk-capable hardware.
diff -Nru a/drivers/usb/host/ehci-hcd.c b/drivers/usb/host/ehci-hcd.c
--- a/drivers/usb/host/ehci-hcd.c	2005-03-23 19:58:53 -08:00
+++ b/drivers/usb/host/ehci-hcd.c	2005-03-23 19:58:53 -08:00
@@ -212,7 +212,7 @@
 	command |= CMD_RESET;
 	dbg_cmd (ehci, "reset", command);
 	writel (command, &ehci->regs->command);
-	ehci_to_hcd(ehci)->state = USB_STATE_HALT;
+	ehci_to_hcd(ehci)->state = HC_STATE_HALT;
 	ehci->next_statechange = jiffies;
 	retval = handshake (&ehci->regs->command, CMD_RESET, 0, 250 * 1000);
 
@@ -231,7 +231,7 @@
 	u32	temp;
 
 #ifdef DEBUG
-	if (!HCD_IS_RUNNING (ehci_to_hcd(ehci)->state))
+	if (!HC_IS_RUNNING (ehci_to_hcd(ehci)->state))
 		BUG ();
 #endif
 
@@ -240,7 +240,7 @@
 	temp &= STS_ASS | STS_PSS;
 	if (handshake (&ehci->regs->status, STS_ASS | STS_PSS,
 				temp, 16 * 125) != 0) {
-		ehci_to_hcd(ehci)->state = USB_STATE_HALT;
+		ehci_to_hcd(ehci)->state = HC_STATE_HALT;
 		return;
 	}
 
@@ -252,7 +252,7 @@
 	/* hardware can take 16 microframes to turn off ... */
 	if (handshake (&ehci->regs->status, STS_ASS | STS_PSS,
 				0, 16 * 125) != 0) {
-		ehci_to_hcd(ehci)->state = USB_STATE_HALT;
+		ehci_to_hcd(ehci)->state = HC_STATE_HALT;
 		return;
 	}
 }
@@ -615,7 +615,7 @@
 		register_reboot_notifier (&ehci->reboot_notifier);
 	}
 
-	hcd->state = USB_STATE_RUNNING;
+	hcd->state = HC_STATE_RUNNING;
 	writel (FLAG_CF, &ehci->regs->configured_flag);
 	readl (&ehci->regs->command);	/* unblock posted write */
 
@@ -635,8 +635,8 @@
 	 * Before this point the HC was idle/ready.  After, khubd
 	 * and device drivers may start it running.
 	 */
-	if (first && hcd_register_root (udev, hcd) != 0) {
-		if (hcd->state == USB_STATE_RUNNING)
+	if (first && usb_hcd_register_root_hub (udev, hcd) != 0) {
+		if (hcd->state == HC_STATE_RUNNING)
 			ehci_quiesce (ehci);
 		ehci_reset (ehci);
 		usb_put_dev (udev); 
@@ -672,7 +672,7 @@
 	del_timer_sync (&ehci->watchdog);
 
 	spin_lock_irq(&ehci->lock);
-	if (HCD_IS_RUNNING (hcd->state))
+	if (HC_IS_RUNNING (hcd->state))
 		ehci_quiesce (ehci);
 
 	ehci_reset (ehci);
@@ -839,7 +839,7 @@
 	 * misplace IRQs, and should let us run completely without IRQs.
 	 * such lossage has been observed on both VT6202 and VT8235. 
 	 */
-	if (HCD_IS_RUNNING (ehci_to_hcd(ehci)->state) &&
+	if (HC_IS_RUNNING (ehci_to_hcd(ehci)->state) &&
 			(ehci->async->qh_next.ptr != NULL ||
 			 ehci->periodic_sched != 0))
 		timer_action (ehci, TIMER_IO_WATCHDOG);
@@ -1000,7 +1000,7 @@
 	/* if we need to use IAA and it's busy, defer */
 	if (qh->qh_state == QH_STATE_LINKED
 			&& ehci->reclaim
-			&& HCD_IS_RUNNING (ehci_to_hcd(ehci)->state)) {
+			&& HC_IS_RUNNING (ehci_to_hcd(ehci)->state)) {
 		struct ehci_qh		*last;
 
 		for (last = ehci->reclaim;
@@ -1011,7 +1011,7 @@
 		last->reclaim = qh;
 
 	/* bypass IAA if the hc can't care */
-	} else if (!HCD_IS_RUNNING (ehci_to_hcd(ehci)->state) && ehci->reclaim)
+	} else if (!HC_IS_RUNNING (ehci_to_hcd(ehci)->state) && ehci->reclaim)
 		end_unlink_async (ehci, NULL);
 
 	/* something else might have unlinked the qh by now */
@@ -1059,7 +1059,7 @@
 
 		/* reschedule QH iff another request is queued */
 		if (!list_empty (&qh->qtd_list)
-				&& HCD_IS_RUNNING (hcd->state)) {
+				&& HC_IS_RUNNING (hcd->state)) {
 			int status;
 
 			status = qh_schedule (ehci, qh);
@@ -1115,7 +1115,7 @@
 		goto idle_timeout;
 	}
 
-	if (!HCD_IS_RUNNING (hcd->state))
+	if (!HC_IS_RUNNING (hcd->state))
 		qh->qh_state = QH_STATE_IDLE;
 	switch (qh->qh_state) {
 	case QH_STATE_LINKED:
diff -Nru a/drivers/usb/host/ehci-hub.c b/drivers/usb/host/ehci-hub.c
--- a/drivers/usb/host/ehci-hub.c	2005-03-23 19:58:52 -08:00
+++ b/drivers/usb/host/ehci-hub.c	2005-03-23 19:58:52 -08:00
@@ -42,9 +42,9 @@
 	spin_lock_irq (&ehci->lock);
 
 	/* stop schedules, clean any completed work */
-	if (HCD_IS_RUNNING(hcd->state)) {
+	if (HC_IS_RUNNING(hcd->state)) {
 		ehci_quiesce (ehci);
-		hcd->state = USB_STATE_QUIESCING;
+		hcd->state = HC_STATE_QUIESCING;
 	}
 	ehci->command = readl (&ehci->regs->command);
 	if (ehci->reclaim)
@@ -73,7 +73,7 @@
 
 	/* turn off now-idle HC */
 	ehci_halt (ehci);
-	hcd->state = HCD_STATE_SUSPENDED;
+	hcd->state = HC_STATE_SUSPENDED;
 
 	ehci->next_statechange = jiffies + msecs_to_jiffies(10);
 	spin_unlock_irq (&ehci->lock);
@@ -145,7 +145,7 @@
 	}
 
 	ehci->next_statechange = jiffies + msecs_to_jiffies(5);
-	hcd->state = USB_STATE_RUNNING;
+	hcd->state = HC_STATE_RUNNING;
 
 	/* Now we can safely re-enable irqs */
 	if (intr_enable)
@@ -212,7 +212,7 @@
 	unsigned long	flags;
 
 	/* if !USB_SUSPEND, root hub timers won't get shut down ... */
-	if (!HCD_IS_RUNNING(hcd->state))
+	if (!HC_IS_RUNNING(hcd->state))
 		return 0;
 
 	/* init status to no-changes */
diff -Nru a/drivers/usb/host/ehci-q.c b/drivers/usb/host/ehci-q.c
--- a/drivers/usb/host/ehci-q.c	2005-03-23 19:58:52 -08:00
+++ b/drivers/usb/host/ehci-q.c	2005-03-23 19:58:52 -08:00
@@ -338,23 +338,24 @@
 			if ((token & QTD_STS_HALT) != 0) {
 				stopped = 1;
 
-			/* magic dummy for some short reads; qh won't advance */
+			/* magic dummy for some short reads; qh won't advance.
+			 * that silicon quirk can kick in with this dummy too.
+			 */
 			} else if (IS_SHORT_READ (token)
-					&& (qh->hw_alt_next & QTD_MASK)
-						== ehci->async->hw_alt_next) {
+					&& !(qtd->hw_alt_next & EHCI_LIST_END)) {
 				stopped = 1;
 				goto halt;
 			}
 
 		/* stop scanning when we reach qtds the hc is using */
 		} else if (likely (!stopped
-				&& HCD_IS_RUNNING (ehci_to_hcd(ehci)->state))) {
+				&& HC_IS_RUNNING (ehci_to_hcd(ehci)->state))) {
 			break;
 
 		} else {
 			stopped = 1;
 
-			if (unlikely (!HCD_IS_RUNNING (ehci_to_hcd(ehci)->state)))
+			if (unlikely (!HC_IS_RUNNING (ehci_to_hcd(ehci)->state)))
 				urb->status = -ESHUTDOWN;
 
 			/* ignore active urbs unless some previous qtd
@@ -522,7 +523,7 @@
 	else
 		buf = 0;
 
-	// FIXME this 'buf' check break some zlps...
+	/* for zero length DATA stages, STATUS is always IN */
 	if (!buf || is_input)
 		token |= (1 /* "in" */ << 8);
 	/* else it's already initted to "out" pid (0 << 8) */
@@ -780,7 +781,7 @@
 			(void) handshake (&ehci->regs->status, STS_ASS, 0, 150);
 			cmd |= CMD_ASE | CMD_RUN;
 			writel (cmd, &ehci->regs->command);
-			ehci_to_hcd(ehci)->state = USB_STATE_RUNNING;
+			ehci_to_hcd(ehci)->state = HC_STATE_RUNNING;
 			/* posted write need not be known to HC yet ... */
 		}
 	}
@@ -959,7 +960,7 @@
 	qh_completions (ehci, qh, regs);
 
 	if (!list_empty (&qh->qtd_list)
-			&& HCD_IS_RUNNING (ehci_to_hcd(ehci)->state))
+			&& HC_IS_RUNNING (ehci_to_hcd(ehci)->state))
 		qh_link_async (ehci, qh);
 	else {
 		qh_put (qh);		// refcount from async list
@@ -967,7 +968,7 @@
 		/* it's not free to turn the async schedule on/off; leave it
 		 * active but idle for a while once it empties.
 		 */
-		if (HCD_IS_RUNNING (ehci_to_hcd(ehci)->state)
+		if (HC_IS_RUNNING (ehci_to_hcd(ehci)->state)
 				&& ehci->async->qh_next.qh == NULL)
 			timer_action (ehci, TIMER_ASYNC_OFF);
 	}
@@ -998,7 +999,7 @@
 	/* stop async schedule right now? */
 	if (unlikely (qh == ehci->async)) {
 		/* can't get here without STS_ASS set */
-		if (ehci_to_hcd(ehci)->state != USB_STATE_HALT) {
+		if (ehci_to_hcd(ehci)->state != HC_STATE_HALT) {
 			writel (cmd & ~CMD_ASE, &ehci->regs->command);
 			wmb ();
 			// handshake later, if we need to
@@ -1018,7 +1019,7 @@
 	prev->qh_next = qh->qh_next;
 	wmb ();
 
-	if (unlikely (ehci_to_hcd(ehci)->state == USB_STATE_HALT)) {
+	if (unlikely (ehci_to_hcd(ehci)->state == HC_STATE_HALT)) {
 		/* if (unlikely (qh->reclaim != 0))
 		 * 	this will recurse, probably not much
 		 */
diff -Nru a/drivers/usb/host/ehci-sched.c b/drivers/usb/host/ehci-sched.c
--- a/drivers/usb/host/ehci-sched.c	2005-03-23 19:58:53 -08:00
+++ b/drivers/usb/host/ehci-sched.c	2005-03-23 19:58:53 -08:00
@@ -249,14 +249,14 @@
 	 */
 	status = handshake (&ehci->regs->status, STS_PSS, 0, 9 * 125);
 	if (status != 0) {
-		ehci_to_hcd(ehci)->state = USB_STATE_HALT;
+		ehci_to_hcd(ehci)->state = HC_STATE_HALT;
 		return status;
 	}
 
 	cmd = readl (&ehci->regs->command) | CMD_PSE;
 	writel (cmd, &ehci->regs->command);
 	/* posted write ... PSS happens later */
-	ehci_to_hcd(ehci)->state = USB_STATE_RUNNING;
+	ehci_to_hcd(ehci)->state = HC_STATE_RUNNING;
 
 	/* make sure ehci_work scans these */
 	ehci->next_uframe = readl (&ehci->regs->frame_index)
@@ -274,7 +274,7 @@
 	 */
 	status = handshake (&ehci->regs->status, STS_PSS, STS_PSS, 9 * 125);
 	if (status != 0) {
-		ehci_to_hcd(ehci)->state = USB_STATE_HALT;
+		ehci_to_hcd(ehci)->state = HC_STATE_HALT;
 		return status;
 	}
 
@@ -1864,7 +1864,7 @@
 	 * Touches as few pages as possible:  cache-friendly.
 	 */
 	now_uframe = ehci->next_uframe;
-	if (HCD_IS_RUNNING (ehci_to_hcd(ehci)->state))
+	if (HC_IS_RUNNING (ehci_to_hcd(ehci)->state))
 		clock = readl (&ehci->regs->frame_index);
 	else
 		clock = now_uframe + mod - 1;
@@ -1898,7 +1898,7 @@
 			union ehci_shadow	temp;
 			int			live;
 
-			live = HCD_IS_RUNNING (ehci_to_hcd(ehci)->state);
+			live = HC_IS_RUNNING (ehci_to_hcd(ehci)->state);
 			switch (type) {
 			case Q_TYPE_QH:
 				/* handle any completions */
@@ -1987,7 +1987,7 @@
 		if (now_uframe == clock) {
 			unsigned	now;
 
-			if (!HCD_IS_RUNNING (ehci_to_hcd(ehci)->state))
+			if (!HC_IS_RUNNING (ehci_to_hcd(ehci)->state))
 				break;
 			ehci->next_uframe = now_uframe;
 			now = readl (&ehci->regs->frame_index) % mod;
diff -Nru a/drivers/usb/host/ohci-hcd.c b/drivers/usb/host/ohci-hcd.c
--- a/drivers/usb/host/ohci-hcd.c	2005-03-23 19:58:52 -08:00
+++ b/drivers/usb/host/ohci-hcd.c	2005-03-23 19:58:52 -08:00
@@ -252,7 +252,7 @@
 	spin_lock_irqsave (&ohci->lock, flags);
 
 	/* don't submit to a dead HC */
-	if (!HCD_IS_RUNNING(hcd->state)) {
+	if (!HC_IS_RUNNING(hcd->state)) {
 		retval = -ENODEV;
 		goto fail;
 	}
@@ -320,7 +320,7 @@
 #endif		  
 
 	spin_lock_irqsave (&ohci->lock, flags);
- 	if (HCD_IS_RUNNING(hcd->state)) {
+ 	if (HC_IS_RUNNING(hcd->state)) {
 		urb_priv_t  *urb_priv;
 
 		/* Unless an IRQ completed the unlink while it was being
@@ -367,7 +367,7 @@
 rescan:
 	spin_lock_irqsave (&ohci->lock, flags);
 
-	if (!HCD_IS_RUNNING (hcd->state)) {
+	if (!HC_IS_RUNNING (hcd->state)) {
 sanitize:
 		ed->state = ED_IDLE;
 		finish_unlinks (ohci, 0, NULL);
@@ -620,7 +620,7 @@
 	ohci->hc_control &= OHCI_CTRL_RWC;
  	ohci->hc_control |= OHCI_CONTROL_INIT | OHCI_USB_OPER;
  	ohci_writel (ohci, ohci->hc_control, &ohci->regs->control);
-	ohci_to_hcd(ohci)->state = USB_STATE_RUNNING;
+	ohci_to_hcd(ohci)->state = HC_STATE_RUNNING;
 
 	/* wake on ConnectStatusChange, matching external hubs */
 	ohci_writel (ohci, RH_HS_DRWE, &ohci->regs->roothub.status);
@@ -656,7 +656,7 @@
 	// POTPGT delay is bits 24-31, in 2 ms units.
 	mdelay ((temp >> 23) & 0x1fe);
 	bus = &ohci_to_hcd(ohci)->self;
-	ohci_to_hcd(ohci)->state = USB_STATE_RUNNING;
+	ohci_to_hcd(ohci)->state = HC_STATE_RUNNING;
 
 	ohci_dump (ohci, 1);
 
@@ -675,7 +675,7 @@
 	}
 
 	udev->speed = USB_SPEED_FULL;
-	if (hcd_register_root (udev, ohci_to_hcd(ohci)) != 0) {
+	if (usb_hcd_register_root_hub (udev, ohci_to_hcd(ohci)) != 0) {
 		usb_put_dev (udev);
 		disable (ohci);
 		ohci->hc_control &= ~OHCI_CTRL_HCFS;
@@ -732,12 +732,12 @@
 	}
 
 	if (ints & OHCI_INTR_WDH) {
-		if (HCD_IS_RUNNING(hcd->state))
+		if (HC_IS_RUNNING(hcd->state))
 			ohci_writel (ohci, OHCI_INTR_WDH, &regs->intrdisable);	
 		spin_lock (&ohci->lock);
 		dl_done_list (ohci, ptregs);
 		spin_unlock (&ohci->lock);
-		if (HCD_IS_RUNNING(hcd->state))
+		if (HC_IS_RUNNING(hcd->state))
 			ohci_writel (ohci, OHCI_INTR_WDH, &regs->intrenable); 
 	}
   
@@ -750,11 +750,11 @@
 	if (ohci->ed_rm_list)
 		finish_unlinks (ohci, ohci_frame_no(ohci), ptregs);
 	if ((ints & OHCI_INTR_SF) != 0 && !ohci->ed_rm_list
-			&& HCD_IS_RUNNING(hcd->state))
+			&& HC_IS_RUNNING(hcd->state))
 		ohci_writel (ohci, OHCI_INTR_SF, &regs->intrdisable);	
 	spin_unlock (&ohci->lock);
 
-	if (HCD_IS_RUNNING(hcd->state)) {
+	if (HC_IS_RUNNING(hcd->state)) {
 		ohci_writel (ohci, ints, &regs->intrstatus);
 		ohci_writel (ohci, OHCI_INTR_MIE, &regs->intrenable);	
 		// flush those writes
diff -Nru a/drivers/usb/host/ohci-hub.c b/drivers/usb/host/ohci-hub.c
--- a/drivers/usb/host/ohci-hub.c	2005-03-23 19:58:52 -08:00
+++ b/drivers/usb/host/ohci-hub.c	2005-03-23 19:58:52 -08:00
@@ -73,7 +73,7 @@
 	ohci_dbg (ohci, "suspend root hub\n");
 
 	/* First stop any processing */
-	hcd->state = USB_STATE_QUIESCING;
+	hcd->state = HC_STATE_QUIESCING;
 	if (ohci->hc_control & OHCI_SCHED_ENABLES) {
 		int		limit;
 
@@ -119,7 +119,7 @@
 
 done:
 	if (status == 0)
-		hcd->state = HCD_STATE_SUSPENDED;
+		hcd->state = HC_STATE_SUSPENDED;
 	spin_unlock_irqrestore (&ohci->lock, flags);
 	return status;
 }
@@ -147,7 +147,7 @@
 
 	if (ohci->hc_control & (OHCI_CTRL_IR | OHCI_SCHED_ENABLES)) {
 		/* this can happen after suspend-to-disk */
-		if (hcd->state == USB_STATE_RESUMING) {
+		if (hcd->state == HC_STATE_RESUMING) {
 			ohci_dbg (ohci, "BIOS/SMM active, control %03x\n",
 					ohci->hc_control);
 			status = -EBUSY;
@@ -198,7 +198,7 @@
 	}
 
 	/* Some controllers (lucent) need extra-long delays */
-	hcd->state = USB_STATE_RESUMING;
+	hcd->state = HC_STATE_RESUMING;
 	mdelay (20 /* usb 11.5.1.10 */ + 15);
 
 	temp = ohci_readl (ohci, &ohci->regs->control);
@@ -272,7 +272,7 @@
 		(void) ohci_readl (ohci, &ohci->regs->control);
 	}
 
-	hcd->state = USB_STATE_RUNNING;
+	hcd->state = HC_STATE_RUNNING;
 	return 0;
 }
 
@@ -313,7 +313,7 @@
 	 * letting khubd or root hub timer see state changes.
 	 */
 	if ((ohci->hc_control & OHCI_CTRL_HCFS) != OHCI_USB_OPER
-			|| !HCD_IS_RUNNING(hcd->state)) {
+			|| !HC_IS_RUNNING(hcd->state)) {
 		can_suspend = 0;
 		goto done;
 	}
@@ -378,7 +378,7 @@
 			) {
 		ohci_vdbg (ohci, "autosuspend\n");
 		(void) ohci_hub_suspend (hcd);
-		hcd->state = USB_STATE_RUNNING;
+		hcd->state = HC_STATE_RUNNING;
 		usb_unlock_device (hcd->self.root_hub);
 	}
 #endif
diff -Nru a/drivers/usb/host/ohci-omap.c b/drivers/usb/host/ohci-omap.c
--- a/drivers/usb/host/ohci-omap.c	2005-03-23 19:58:52 -08:00
+++ b/drivers/usb/host/ohci-omap.c	2005-03-23 19:58:52 -08:00
@@ -499,7 +499,7 @@
 					USB_STATE_SUSPENDED;
 			state = 4;
 		}
-		ohci_to_hcd(ohci)->state = HCD_STATE_SUSPENDED;
+		ohci_to_hcd(ohci)->state = HC_STATE_SUSPENDED;
 		dev->power.power_state = state;
 	}
 	up(&ohci_to_hcd(ohci)->self.root_hub->serialize);
diff -Nru a/drivers/usb/host/ohci-q.c b/drivers/usb/host/ohci-q.c
--- a/drivers/usb/host/ohci-q.c	2005-03-23 19:58:52 -08:00
+++ b/drivers/usb/host/ohci-q.c	2005-03-23 19:58:52 -08:00
@@ -172,7 +172,7 @@
 {	 
 	int	branch;
 
-	if (ohci_to_hcd(ohci)->state == USB_STATE_QUIESCING)
+	if (ohci_to_hcd(ohci)->state == HC_STATE_QUIESCING)
 		return -EAGAIN;
 
 	ed->state = ED_OPER;
@@ -663,7 +663,7 @@
 			/* NOTE:  mishandles transfers >8K, some >4K */
 			td_fill (ohci, info, data, data_len, urb, cnt++);
 		}
-		info = is_out
+		info = (is_out || data_len == 0)
 			? TD_CC | TD_DP_IN | TD_T_DATA1
 			: TD_CC | TD_DP_OUT | TD_T_DATA1;
 		td_fill (ohci, info, data, 0, urb, cnt++);
@@ -923,7 +923,7 @@
 		/* only take off EDs that the HC isn't using, accounting for
 		 * frame counter wraps and EDs with partially retired TDs
 		 */
-		if (likely (regs && HCD_IS_RUNNING(ohci_to_hcd(ohci)->state))) {
+		if (likely (regs && HC_IS_RUNNING(ohci_to_hcd(ohci)->state))) {
 			if (tick_before (tick, ed->tick)) {
 skip_ed:
 				last = &ed->ed_next;
@@ -1005,7 +1005,7 @@
 
 		/* but if there's work queued, reschedule */
 		if (!list_empty (&ed->td_list)) {
-			if (HCD_IS_RUNNING(ohci_to_hcd(ohci)->state))
+			if (HC_IS_RUNNING(ohci_to_hcd(ohci)->state))
 				ed_schedule (ohci, ed);
 		}
 
@@ -1014,8 +1014,8 @@
    	}
 
 	/* maybe reenable control and bulk lists */ 
-	if (HCD_IS_RUNNING(ohci_to_hcd(ohci)->state)
-			&& ohci_to_hcd(ohci)->state != USB_STATE_QUIESCING
+	if (HC_IS_RUNNING(ohci_to_hcd(ohci)->state)
+			&& ohci_to_hcd(ohci)->state != HC_STATE_QUIESCING
 			&& !ohci->ed_rm_list) {
 		u32	command = 0, control = 0;
 
diff -Nru a/drivers/usb/host/ohci.h b/drivers/usb/host/ohci.h
--- a/drivers/usb/host/ohci.h	2005-03-23 19:58:53 -08:00
+++ b/drivers/usb/host/ohci.h	2005-03-23 19:58:53 -08:00
@@ -594,7 +594,7 @@
 
 static inline void disable (struct ohci_hcd *ohci)
 {
-	ohci_to_hcd(ohci)->state = USB_STATE_HALT;
+	ohci_to_hcd(ohci)->state = HC_STATE_HALT;
 }
 
 #define	FI			0x2edf		/* 12000 bits per frame (-1) */
diff -Nru a/drivers/usb/host/sl811-hcd.c b/drivers/usb/host/sl811-hcd.c
--- a/drivers/usb/host/sl811-hcd.c	2005-03-23 19:58:52 -08:00
+++ b/drivers/usb/host/sl811-hcd.c	2005-03-23 19:58:52 -08:00
@@ -105,7 +105,7 @@
 	} else {
 		sl811->port1 = 0;
 		sl811->irq_enable = 0;
-		hcd->state = USB_STATE_HALT;
+		hcd->state = HC_STATE_HALT;
 		hcd->self.controller->power.power_state = PM_SUSPEND_DISK;
 	}
 	sl811->ctrl1 = 0;
@@ -834,7 +834,7 @@
 
 	/* don't submit to a dead or disabled port */
 	if (!(sl811->port1 & (1 << USB_PORT_FEAT_ENABLE))
-			|| !HCD_IS_RUNNING(hcd->state)) {
+			|| !HC_IS_RUNNING(hcd->state)) {
 		retval = -ENODEV;
 		goto fail;
 	}
@@ -1562,12 +1562,12 @@
 		return -ENOMEM;
 
 	udev->speed = USB_SPEED_FULL;
-	hcd->state = USB_STATE_RUNNING;
+	hcd->state = HC_STATE_RUNNING;
 
 	if (sl811->board)
 		hcd->can_wakeup = sl811->board->can_wakeup;
 
-	if (hcd_register_root(udev, hcd) != 0) {
+	if (usb_hcd_register_root_hub(udev, hcd) != 0) {
 		usb_put_dev(udev);
 		sl811h_stop(hcd);
 		return -ENODEV;
diff -Nru a/drivers/usb/host/uhci-debug.c b/drivers/usb/host/uhci-debug.c
--- a/drivers/usb/host/uhci-debug.c	2005-03-23 19:58:52 -08:00
+++ b/drivers/usb/host/uhci-debug.c	2005-03-23 19:58:52 -08:00
@@ -406,7 +406,7 @@
 	struct uhci_td *td;
 	struct list_head *tmp, *head;
 
-	spin_lock_irqsave(&uhci->schedule_lock, flags);
+	spin_lock_irqsave(&uhci->lock, flags);
 
 	out += sprintf(out, "HC status\n");
 	out += uhci_show_status(uhci, out, len - (out - buf));
@@ -492,7 +492,7 @@
 	if (debug > 2)
 		out += uhci_show_lists(uhci, out, len - (out - buf));
 
-	spin_unlock_irqrestore(&uhci->schedule_lock, flags);
+	spin_unlock_irqrestore(&uhci->lock, flags);
 
 	return out - buf;
 }
diff -Nru a/drivers/usb/host/uhci-hcd.c b/drivers/usb/host/uhci-hcd.c
--- a/drivers/usb/host/uhci-hcd.c	2005-03-23 19:58:53 -08:00
+++ b/drivers/usb/host/uhci-hcd.c	2005-03-23 19:58:53 -08:00
@@ -89,7 +89,7 @@
 
 static kmem_cache_t *uhci_up_cachep;	/* urb_priv */
 
-static unsigned int uhci_get_current_frame_number(struct uhci_hcd *uhci);
+static void uhci_get_current_frame_number(struct uhci_hcd *uhci);
 static void hc_state_transitions(struct uhci_hcd *uhci);
 
 /* If a transfer is still active after this much time, turn off FSBR */
@@ -113,15 +113,9 @@
 	struct uhci_hcd *uhci = hcd_to_uhci(hcd);
 	struct urb_priv *up;
 	unsigned long flags;
-	int called_uhci_finish_completion = 0;
 
-	spin_lock_irqsave(&uhci->schedule_lock, flags);
-	if (!list_empty(&uhci->urb_remove_list) &&
-	    uhci_get_current_frame_number(uhci) != uhci->urb_remove_age) {
-		uhci_remove_pending_urbps(uhci);
-		uhci_finish_completion(hcd, NULL);
-		called_uhci_finish_completion = 1;
-	}
+	spin_lock_irqsave(&uhci->lock, flags);
+	uhci_scan_schedule(uhci, NULL);
 
 	list_for_each_entry(up, &uhci->urb_list, urb_list) {
 		struct urb *u = up->urb;
@@ -134,11 +128,6 @@
 
 		spin_unlock(&u->lock);
 	}
-	spin_unlock_irqrestore(&uhci->schedule_lock, flags);
-
-	/* Wake up anyone waiting for an URB to complete */
-	if (called_uhci_finish_completion)
-		wake_up_all(&uhci->waitqh);
 
 	/* Really disable FSBR */
 	if (!uhci->fsbr && uhci->fsbrtimeout && time_after_eq(jiffies, uhci->fsbrtimeout)) {
@@ -149,9 +138,10 @@
 	/* Poll for and perform state transitions */
 	hc_state_transitions(uhci);
 	if (unlikely(uhci->suspended_ports && uhci->state != UHCI_SUSPENDED))
-		uhci_check_resume(uhci);
+		uhci_check_ports(uhci);
 
 	init_stall_timer(hcd);
+	spin_unlock_irqrestore(&uhci->lock, flags);
 }
 
 static int init_stall_timer(struct usb_hcd *hcd)
@@ -172,8 +162,6 @@
 	struct uhci_hcd *uhci = hcd_to_uhci(hcd);
 	unsigned long io_addr = uhci->io_addr;
 	unsigned short status;
-	struct urb_priv *urbp, *tmp;
-	unsigned int age;
 
 	/*
 	 * Read the interrupt status, and write it back to clear the
@@ -202,37 +190,9 @@
 	if (status & USBSTS_RD)
 		uhci->resume_detect = 1;
 
-	spin_lock(&uhci->schedule_lock);
-
-	age = uhci_get_current_frame_number(uhci);
-	if (age != uhci->qh_remove_age)
-		uhci_free_pending_qhs(uhci);
-	if (age != uhci->td_remove_age)
-		uhci_free_pending_tds(uhci);
-	if (age != uhci->urb_remove_age)
-		uhci_remove_pending_urbps(uhci);
-
-	if (list_empty(&uhci->urb_remove_list) &&
-	    list_empty(&uhci->td_remove_list) &&
-	    list_empty(&uhci->qh_remove_list))
-		uhci_clear_next_interrupt(uhci);
-	else
-		uhci_set_next_interrupt(uhci);
-
-	/* Walk the list of pending URBs to see which ones completed
-	 * (must be _safe because uhci_transfer_result() dequeues URBs) */
-	list_for_each_entry_safe(urbp, tmp, &uhci->urb_list, urb_list) {
-		struct urb *urb = urbp->urb;
-
-		/* Checks the status and does all of the magic necessary */
-		uhci_transfer_result(uhci, urb);
-	}
-	uhci_finish_completion(hcd, regs);
-
-	spin_unlock(&uhci->schedule_lock);
-
-	/* Wake up anyone waiting for an URB to complete */
-	wake_up_all(&uhci->waitqh);
+	spin_lock(&uhci->lock);
+	uhci_scan_schedule(uhci, regs);
+	spin_unlock(&uhci->lock);
 
 	return IRQ_HANDLED;
 }
@@ -256,6 +216,7 @@
 	/* Another 10ms delay */
 	msleep(10);
 	uhci->resume_detect = 0;
+	uhci->is_stopped = UHCI_IS_STOPPED;
 }
 
 static void suspend_hc(struct uhci_hcd *uhci)
@@ -266,6 +227,12 @@
 	uhci->state = UHCI_SUSPENDED;
 	uhci->resume_detect = 0;
 	outw(USBCMD_EGSM, io_addr + USBCMD);
+
+	/* FIXME: Wait for the controller to actually stop */
+	uhci_get_current_frame_number(uhci);
+	uhci->is_stopped = UHCI_IS_STOPPED;
+
+	uhci_scan_schedule(uhci, NULL);
 }
 
 static void wakeup_hc(struct uhci_hcd *uhci)
@@ -280,6 +247,7 @@
 			outw(USBCMD_FGR | USBCMD_EGSM, io_addr + USBCMD);
 			uhci->state = UHCI_RESUMING_1;
 			uhci->state_end = jiffies + msecs_to_jiffies(20);
+			uhci->is_stopped = 0;
 			break;
 
 		case UHCI_RESUMING_1:		/* End global resume */
@@ -386,11 +354,13 @@
 }
 
 /*
- * returns the current frame number for a USB bus/controller.
+ * Store the current frame number in uhci->frame_number if the controller
+ * is runnning
  */
-static unsigned int uhci_get_current_frame_number(struct uhci_hcd *uhci)
+static void uhci_get_current_frame_number(struct uhci_hcd *uhci)
 {
-	return inw(uhci->io_addr + USBFRNUM);
+	if (!uhci->is_stopped)
+		uhci->frame_number = inw(uhci->io_addr + USBFRNUM);
 }
 
 static int start_hc(struct uhci_hcd *uhci)
@@ -413,6 +383,9 @@
 		msleep(1);
 	}
 
+	/* Mark controller as running before we enable interrupts */
+	uhci_to_hcd(uhci)->state = HC_STATE_RUNNING;
+
 	/* Turn on PIRQ and all interrupts */
 	pci_write_config_word(to_pci_dev(uhci_dev(uhci)), USBLEGSUP,
 			USBLEGSUP_DEFAULT);
@@ -427,8 +400,8 @@
 	uhci->state = UHCI_RUNNING_GRACE;
 	uhci->state_end = jiffies + HZ;
 	outw(USBCMD_RS | USBCMD_CF | USBCMD_MAXP, io_addr + USBCMD);
+	uhci->is_stopped = 0;
 
-        uhci_to_hcd(uhci)->state = USB_STATE_RUNNING;
 	return 0;
 }
 
@@ -524,7 +497,7 @@
 	uhci->fsbr = 0;
 	uhci->fsbrtimeout = 0;
 
-	spin_lock_init(&uhci->schedule_lock);
+	spin_lock_init(&uhci->lock);
 	INIT_LIST_HEAD(&uhci->qh_remove_list);
 
 	INIT_LIST_HEAD(&uhci->td_remove_list);
@@ -678,7 +651,7 @@
 
 	udev->speed = USB_SPEED_FULL;
 
-	if (hcd_register_root(udev, hcd) != 0) {
+	if (usb_hcd_register_root_hub(udev, hcd) != 0) {
 		dev_err(uhci_dev(uhci), "unable to start root hub\n");
 		retval = -ENOMEM;
 		goto err_start_root_hub;
@@ -733,26 +706,11 @@
 	struct uhci_hcd *uhci = hcd_to_uhci(hcd);
 
 	del_timer_sync(&uhci->stall_timer);
-
-	/*
-	 * At this point, we're guaranteed that no new connects can be made
-	 * to this bus since there are no more parents
-	 */
-
 	reset_hc(uhci);
 
-	spin_lock_irq(&uhci->schedule_lock);
-	uhci_free_pending_qhs(uhci);
-	uhci_free_pending_tds(uhci);
-	uhci_remove_pending_urbps(uhci);
-	uhci_finish_completion(hcd, NULL);
-
-	uhci_free_pending_qhs(uhci);
-	uhci_free_pending_tds(uhci);
-	spin_unlock_irq(&uhci->schedule_lock);
-
-	/* Wake up anyone waiting for an URB to complete */
-	wake_up_all(&uhci->waitqh);
+	spin_lock_irq(&uhci->lock);
+	uhci_scan_schedule(uhci, NULL);
+	spin_unlock_irq(&uhci->lock);
 	
 	release_uhci(uhci);
 }
@@ -762,13 +720,19 @@
 {
 	struct uhci_hcd *uhci = hcd_to_uhci(hcd);
 
+	spin_lock_irq(&uhci->lock);
+
 	/* Don't try to suspend broken motherboards, reset instead */
-	if (suspend_allowed(uhci)) {
+	if (suspend_allowed(uhci))
 		suspend_hc(uhci);
-		uhci->saved_framenumber =
-				inw(uhci->io_addr + USBFRNUM) & 0x3ff;
-	} else
+	else {
+		spin_unlock_irq(&uhci->lock);
 		reset_hc(uhci);
+		spin_lock_irq(&uhci->lock);
+		uhci_scan_schedule(uhci, NULL);
+	}
+
+	spin_unlock_irq(&uhci->lock);
 	return 0;
 }
 
@@ -779,6 +743,8 @@
 
 	pci_set_master(to_pci_dev(uhci_dev(uhci)));
 
+	spin_lock_irq(&uhci->lock);
+
 	if (uhci->state == UHCI_SUSPENDED) {
 
 		/*
@@ -789,7 +755,7 @@
 		 */
 		pci_write_config_word(to_pci_dev(uhci_dev(uhci)), USBLEGSUP,
 				0);
-		outw(uhci->saved_framenumber, uhci->io_addr + USBFRNUM);
+		outw(uhci->frame_number, uhci->io_addr + USBFRNUM);
 		outl(uhci->fl->dma_handle, uhci->io_addr + USBFLBASEADD);
 		outw(USBINTR_TIMEOUT | USBINTR_RESUME | USBINTR_IOC |
 				USBINTR_SP, uhci->io_addr + USBINTR);
@@ -797,11 +763,15 @@
 		pci_write_config_word(to_pci_dev(uhci_dev(uhci)), USBLEGSUP,
 				USBLEGSUP_DEFAULT);
 	} else {
+		spin_unlock_irq(&uhci->lock);
 		reset_hc(uhci);
 		if ((rc = start_hc(uhci)) != 0)
 			return rc;
+		spin_lock_irq(&uhci->lock);
 	}
-	hcd->state = USB_STATE_RUNNING;
+	hcd->state = HC_STATE_RUNNING;
+
+	spin_unlock_irq(&uhci->lock);
 	return 0;
 }
 #endif
@@ -817,7 +787,17 @@
 
 static int uhci_hcd_get_frame_number(struct usb_hcd *hcd)
 {
-	return uhci_get_current_frame_number(hcd_to_uhci(hcd));
+	struct uhci_hcd *uhci = hcd_to_uhci(hcd);
+	int frame_number;
+	unsigned long flags;
+
+	/* Minimize latency by avoiding the spinlock */
+	local_irq_save(flags);
+	rmb();
+	frame_number = (uhci->is_stopped ? uhci->frame_number :
+			inw(uhci->io_addr + USBFRNUM));
+	local_irq_restore(flags);
+	return frame_number;
 }
 
 static const char hcd_name[] = "uhci_hcd";
diff -Nru a/drivers/usb/host/uhci-hcd.h b/drivers/usb/host/uhci-hcd.h
--- a/drivers/usb/host/uhci-hcd.h	2005-03-23 19:58:52 -08:00
+++ b/drivers/usb/host/uhci-hcd.h	2005-03-23 19:58:52 -08:00
@@ -358,39 +358,44 @@
 	struct uhci_td *term_td;	/* Terminating TD, see UHCI bug */
 	struct uhci_qh *skelqh[UHCI_NUM_SKELQH];	/* Skeleton QH's */
 
-	spinlock_t schedule_lock;
-	struct uhci_frame_list *fl;		/* P: uhci->schedule_lock */
+	spinlock_t lock;
+	struct uhci_frame_list *fl;		/* P: uhci->lock */
 	int fsbr;				/* Full-speed bandwidth reclamation */
 	unsigned long fsbrtimeout;		/* FSBR delay */
 
 	enum uhci_state state;			/* FIXME: needs a spinlock */
 	unsigned long state_end;		/* Time of next transition */
-	int resume_detect;			/* Need a Global Resume */
-	unsigned int saved_framenumber;		/* Save during PM suspend */
+	unsigned int frame_number;		/* As of last check */
+	unsigned int is_stopped;
+#define UHCI_IS_STOPPED		9999		/* Larger than a frame # */
+
+	unsigned int scan_in_progress:1;	/* Schedule scan is running */
+	unsigned int need_rescan:1;		/* Redo the schedule scan */
+	unsigned int resume_detect:1;		/* Need a Global Resume */
 
-	/* Support for port suspend/resume */
+	/* Support for port suspend/resume/reset */
 	unsigned long port_c_suspend;		/* Bit-arrays of ports */
 	unsigned long suspended_ports;
 	unsigned long resuming_ports;
-	unsigned long resume_timeout;		/* Time to stop signalling */
+	unsigned long ports_timeout;		/* Time to stop signalling */
 
 	/* Main list of URB's currently controlled by this HC */
-	struct list_head urb_list;		/* P: uhci->schedule_lock */
+	struct list_head urb_list;		/* P: uhci->lock */
 
 	/* List of QH's that are done, but waiting to be unlinked (race) */
-	struct list_head qh_remove_list;	/* P: uhci->schedule_lock */
+	struct list_head qh_remove_list;	/* P: uhci->lock */
 	unsigned int qh_remove_age;		/* Age in frames */
 
 	/* List of TD's that are done, but waiting to be freed (race) */
-	struct list_head td_remove_list;	/* P: uhci->schedule_lock */
+	struct list_head td_remove_list;	/* P: uhci->lock */
 	unsigned int td_remove_age;		/* Age in frames */
 
 	/* List of asynchronously unlinked URB's */
-	struct list_head urb_remove_list;	/* P: uhci->schedule_lock */
+	struct list_head urb_remove_list;	/* P: uhci->lock */
 	unsigned int urb_remove_age;		/* Age in frames */
 
 	/* List of URB's awaiting completion callback */
-	struct list_head complete_list;		/* P: uhci->schedule_lock */
+	struct list_head complete_list;		/* P: uhci->lock */
 
 	int rh_numports;
 
@@ -436,13 +441,13 @@
  * Locking in uhci.c
  *
  * Almost everything relating to the hardware schedule and processing
- * of URBs is protected by uhci->schedule_lock.  urb->status is protected
- * by urb->lock; that's the one exception.
+ * of URBs is protected by uhci->lock.  urb->status is protected by
+ * urb->lock; that's the one exception.
  *
- * To prevent deadlocks, never lock uhci->schedule_lock while holding
- * urb->lock.  The safe order of locking is:
+ * To prevent deadlocks, never lock uhci->lock while holding urb->lock.
+ * The safe order of locking is:
  *
- * #1 uhci->schedule_lock
+ * #1 uhci->lock
  * #2 urb->lock
  */
 
diff -Nru a/drivers/usb/host/uhci-hub.c b/drivers/usb/host/uhci-hub.c
--- a/drivers/usb/host/uhci-hub.c	2005-03-23 19:58:52 -08:00
+++ b/drivers/usb/host/uhci-hub.c	2005-03-23 19:58:52 -08:00
@@ -66,7 +66,6 @@
 
 /* UHCI controllers don't automatically stop resume signalling after 20 msec,
  * so we have to poll and check timeouts in order to take care of it.
- * FIXME:  Synchronize access to these fields by a spinlock.
  */
 static void uhci_finish_suspend(struct uhci_hcd *uhci, int port,
 		unsigned long port_addr)
@@ -87,22 +86,37 @@
 	}
 }
 
-static void uhci_check_resume(struct uhci_hcd *uhci)
+static void uhci_check_ports(struct uhci_hcd *uhci)
 {
 	unsigned int port;
 	unsigned long port_addr;
+	int status;
 
 	for (port = 0; port < uhci->rh_numports; ++port) {
 		port_addr = uhci->io_addr + USBPORTSC1 + 2 * port;
-		if (unlikely(inw(port_addr) & USBPORTSC_RD)) {
+		status = inw(port_addr);
+		if (unlikely(status & USBPORTSC_PR)) {
+			if (time_after_eq(jiffies, uhci->ports_timeout)) {
+				CLR_RH_PORTSTAT(USBPORTSC_PR);
+				udelay(10);
+
+				/* If the port was enabled before, turning
+				 * reset on caused a port enable change.
+				 * Turning reset off causes a port connect
+				 * status change.  Clear these changes. */
+				CLR_RH_PORTSTAT(USBPORTSC_CSC | USBPORTSC_PEC);
+				SET_RH_PORTSTAT(USBPORTSC_PE);
+			}
+		}
+		if (unlikely(status & USBPORTSC_RD)) {
 			if (!test_bit(port, &uhci->resuming_ports)) {
 
 				/* Port received a wakeup request */
 				set_bit(port, &uhci->resuming_ports);
-				uhci->resume_timeout = jiffies +
+				uhci->ports_timeout = jiffies +
 						msecs_to_jiffies(20);
 			} else if (time_after_eq(jiffies,
-						uhci->resume_timeout)) {
+						uhci->ports_timeout)) {
 				uhci_finish_suspend(uhci, port, port_addr);
 			}
 		}
@@ -118,7 +132,9 @@
 	unsigned int port = wIndex - 1;
 	unsigned long port_addr = uhci->io_addr + USBPORTSC1 + 2 * port;
 	u16 wPortChange, wPortStatus;
+	unsigned long flags;
 
+	spin_lock_irqsave(&uhci->lock, flags);
 	switch (typeReq) {
 
 	case GetHubStatus:
@@ -128,9 +144,7 @@
 		if (port >= uhci->rh_numports)
 			goto err;
 
-		if (uhci->resuming_ports)
-			uhci_check_resume(uhci);
-
+		uhci_check_ports(uhci);
 		status = inw(port_addr);
 
 		/* Intel controllers report the OverCurrent bit active on.
@@ -203,15 +217,12 @@
 			OK(0);
 		case USB_PORT_FEAT_RESET:
 			SET_RH_PORTSTAT(USBPORTSC_PR);
-			mdelay(50);	/* USB v1.1 7.1.7.3 */
-			CLR_RH_PORTSTAT(USBPORTSC_PR);
-			udelay(10);
 
 			/* Reset terminates Resume signalling */
 			uhci_finish_suspend(uhci, port, port_addr);
-			SET_RH_PORTSTAT(USBPORTSC_PE);
-			mdelay(10);
-			CLR_RH_PORTSTAT(USBPORTSC_PEC|USBPORTSC_CSC);
+
+			/* USB v2.0 7.1.7.5 */
+			uhci->ports_timeout = jiffies + msecs_to_jiffies(50);
 			OK(0);
 		case USB_PORT_FEAT_POWER:
 			/* UHCI has no power switching */
@@ -238,8 +249,6 @@
 			if (test_bit(port, &uhci->suspended_ports) &&
 					!test_and_set_bit(port,
 						&uhci->resuming_ports)) {
-				uhci->resume_timeout = jiffies +
-						msecs_to_jiffies(20);
 				SET_RH_PORTSTAT(USBPORTSC_RD);
 
 				/* The controller won't allow RD to be set
@@ -249,6 +258,10 @@
 				if (!(inw(port_addr) & USBPORTSC_RD))
 					uhci_finish_suspend(uhci, port,
 							port_addr);
+				else
+					/* USB v2.0 7.1.7.7 */
+					uhci->ports_timeout = jiffies +
+						msecs_to_jiffies(20);
 			}
 			OK(0);
 		case USB_PORT_FEAT_C_SUSPEND:
@@ -280,6 +293,7 @@
 err:
 		retval = -EPIPE;
 	}
+	spin_unlock_irqrestore(&uhci->lock, flags);
 
 	return retval;
 }
diff -Nru a/drivers/usb/host/uhci-q.c b/drivers/usb/host/uhci-q.c
--- a/drivers/usb/host/uhci-q.c	2005-03-23 19:58:52 -08:00
+++ b/drivers/usb/host/uhci-q.c	2005-03-23 19:58:52 -08:00
@@ -264,7 +264,6 @@
 {
 	struct uhci_qh *pqh;
 	__le32 newlink;
-	unsigned int age;
 
 	if (!qh)
 		return;
@@ -310,10 +309,10 @@
 	list_del_init(&qh->urbp->queue_list);
 	qh->urbp = NULL;
 
-	age = uhci_get_current_frame_number(uhci);
-	if (age != uhci->qh_remove_age) {
+	uhci_get_current_frame_number(uhci);
+	if (uhci->frame_number + uhci->is_stopped != uhci->qh_remove_age) {
 		uhci_free_pending_qhs(uhci);
-		uhci->qh_remove_age = age;
+		uhci->qh_remove_age = uhci->frame_number;
 	}
 
 	/* Check to see if the remove list is empty. Set the IOC bit */
@@ -492,7 +491,6 @@
 {
 	struct uhci_td *td, *tmp;
 	struct urb_priv *urbp;
-	unsigned int age;
 
 	urbp = (struct urb_priv *)urb->hcpriv;
 	if (!urbp)
@@ -502,10 +500,10 @@
 		dev_warn(uhci_dev(uhci), "urb %p still on uhci->urb_list "
 				"or uhci->remove_list!\n", urb);
 
-	age = uhci_get_current_frame_number(uhci);
-	if (age != uhci->td_remove_age) {
+	uhci_get_current_frame_number(uhci);
+	if (uhci->frame_number + uhci->is_stopped != uhci->td_remove_age) {
 		uhci_free_pending_tds(uhci);
-		uhci->td_remove_age = age;
+		uhci->td_remove_age = uhci->frame_number;
 	}
 
 	/* Check to see if the remove list is empty. Set the IOC bit */
@@ -1063,11 +1061,11 @@
 	limits = isochronous_find_limits(uhci, urb, &start, &end);
 
 	if (urb->transfer_flags & URB_ISO_ASAP) {
-		if (limits)
-			urb->start_frame =
-					(uhci_get_current_frame_number(uhci) +
-						10) & (UHCI_NUMFRAMES - 1);
-		else
+		if (limits) {
+			uhci_get_current_frame_number(uhci);
+			urb->start_frame = (uhci->frame_number + 10)
+					& (UHCI_NUMFRAMES - 1);
+		} else
 			urb->start_frame = end;
 	} else {
 		urb->start_frame &= (UHCI_NUMFRAMES - 1);
@@ -1184,7 +1182,7 @@
 	struct urb *eurb;
 	int bustime;
 
-	spin_lock_irqsave(&uhci->schedule_lock, flags);
+	spin_lock_irqsave(&uhci->lock, flags);
 
 	ret = urb->status;
 	if (ret != -EINPROGRESS)		/* URB already unlinked! */
@@ -1242,7 +1240,7 @@
 		ret = 0;
 
 out:
-	spin_unlock_irqrestore(&uhci->schedule_lock, flags);
+	spin_unlock_irqrestore(&uhci->lock, flags);
 	return ret;
 }
 
@@ -1371,9 +1369,8 @@
 	struct uhci_hcd *uhci = hcd_to_uhci(hcd);
 	unsigned long flags;
 	struct urb_priv *urbp;
-	unsigned int age;
 
-	spin_lock_irqsave(&uhci->schedule_lock, flags);
+	spin_lock_irqsave(&uhci->lock, flags);
 	urbp = urb->hcpriv;
 	if (!urbp)			/* URB was never linked! */
 		goto done;
@@ -1381,10 +1378,10 @@
 
 	uhci_unlink_generic(uhci, urb);
 
-	age = uhci_get_current_frame_number(uhci);
-	if (age != uhci->urb_remove_age) {
+	uhci_get_current_frame_number(uhci);
+	if (uhci->frame_number + uhci->is_stopped != uhci->urb_remove_age) {
 		uhci_remove_pending_urbps(uhci);
-		uhci->urb_remove_age = age;
+		uhci->urb_remove_age = uhci->frame_number;
 	}
 
 	/* If we're the first, set the next interrupt bit */
@@ -1393,7 +1390,7 @@
 	list_add_tail(&urbp->urb_list, &uhci->urb_remove_list);
 
 done:
-	spin_unlock_irqrestore(&uhci->schedule_lock, flags);
+	spin_unlock_irqrestore(&uhci->lock, flags);
 	return 0;
 }
 
@@ -1455,28 +1452,27 @@
 
 static void
 uhci_finish_urb(struct usb_hcd *hcd, struct urb *urb, struct pt_regs *regs)
-__releases(uhci->schedule_lock)
-__acquires(uhci->schedule_lock)
+__releases(uhci->lock)
+__acquires(uhci->lock)
 {
 	struct uhci_hcd *uhci = hcd_to_uhci(hcd);
 
 	uhci_destroy_urb_priv(uhci, urb);
 
-	spin_unlock(&uhci->schedule_lock);
+	spin_unlock(&uhci->lock);
 	usb_hcd_giveback_urb(hcd, urb, regs);
-	spin_lock(&uhci->schedule_lock);
+	spin_lock(&uhci->lock);
 }
 
-static void uhci_finish_completion(struct usb_hcd *hcd, struct pt_regs *regs)
+static void uhci_finish_completion(struct uhci_hcd *uhci, struct pt_regs *regs)
 {
-	struct uhci_hcd *uhci = hcd_to_uhci(hcd);
 	struct urb_priv *urbp, *tmp;
 
 	list_for_each_entry_safe(urbp, tmp, &uhci->complete_list, urb_list) {
 		struct urb *urb = urbp->urb;
 
 		list_del_init(&urbp->urb_list);
-		uhci_finish_urb(hcd, urb, regs);
+		uhci_finish_urb(uhci_to_hcd(uhci), urb, regs);
 	}
 }
 
@@ -1485,4 +1481,59 @@
 
 	/* Splice the urb_remove_list onto the end of the complete_list */
 	list_splice_init(&uhci->urb_remove_list, uhci->complete_list.prev);
+}
+
+/* Process events in the schedule, but only in one thread at a time */
+static void uhci_scan_schedule(struct uhci_hcd *uhci, struct pt_regs *regs)
+{
+	struct urb_priv *urbp, *tmp;
+
+	/* Don't allow re-entrant calls */
+	if (uhci->scan_in_progress) {
+		uhci->need_rescan = 1;
+		return;
+	}
+	uhci->scan_in_progress = 1;
+ rescan:
+	uhci->need_rescan = 0;
+
+	uhci_get_current_frame_number(uhci);
+
+	if (uhci->frame_number + uhci->is_stopped != uhci->qh_remove_age)
+		uhci_free_pending_qhs(uhci);
+	if (uhci->frame_number + uhci->is_stopped != uhci->td_remove_age)
+		uhci_free_pending_tds(uhci);
+	if (uhci->frame_number + uhci->is_stopped != uhci->urb_remove_age)
+		uhci_remove_pending_urbps(uhci);
+
+	/* Walk the list of pending URBs to see which ones completed
+	 * (must be _safe because uhci_transfer_result() dequeues URBs) */
+	list_for_each_entry_safe(urbp, tmp, &uhci->urb_list, urb_list) {
+		struct urb *urb = urbp->urb;
+
+		/* Checks the status and does all of the magic necessary */
+		uhci_transfer_result(uhci, urb);
+	}
+	uhci_finish_completion(uhci, regs);
+
+	/* If the controller is stopped, we can finish these off right now */
+	if (uhci->is_stopped) {
+		uhci_free_pending_qhs(uhci);
+		uhci_free_pending_tds(uhci);
+		uhci_remove_pending_urbps(uhci);
+	}
+
+	if (uhci->need_rescan)
+		goto rescan;
+	uhci->scan_in_progress = 0;
+
+	if (list_empty(&uhci->urb_remove_list) &&
+	    list_empty(&uhci->td_remove_list) &&
+	    list_empty(&uhci->qh_remove_list))
+		uhci_clear_next_interrupt(uhci);
+	else
+		uhci_set_next_interrupt(uhci);
+
+	/* Wake up anyone waiting for an URB to complete */
+	wake_up_all(&uhci->waitqh);
 }
diff -Nru a/drivers/usb/image/Kconfig b/drivers/usb/image/Kconfig
--- a/drivers/usb/image/Kconfig	2005-03-23 19:58:52 -08:00
+++ b/drivers/usb/image/Kconfig	2005-03-23 19:58:52 -08:00
@@ -28,14 +28,3 @@
 	  The scanner will appear as a scsi generic device to the rest
 	  of the system. Scsi support is required.
 	  This driver can be compiled as a module, called microtek.
-
-config USB_HPUSBSCSI
-	tristate "HP53xx USB scanner support"
-	depends on USB && SCSI && BROKEN
-	help
-	  Say Y here if you want support for the HP 53xx series of scanners
-	  and the Minolta Scan Dual.
-	  The scanner will be accessible as a SCSI device.
-	  Please note that recent versions of SANE use usbfs, not this driver.
-	  This can be compiled as a module, called hpusbscsi.
-
diff -Nru a/drivers/usb/image/Makefile b/drivers/usb/image/Makefile
--- a/drivers/usb/image/Makefile	2005-03-23 19:58:53 -08:00
+++ b/drivers/usb/image/Makefile	2005-03-23 19:58:53 -08:00
@@ -3,5 +3,4 @@
 #
 
 obj-$(CONFIG_USB_MDC800)	+= mdc800.o
-obj-$(CONFIG_USB_HPUSBSCSI)	+= hpusbscsi.o
 obj-$(CONFIG_USB_MICROTEK)	+= microtek.o
diff -Nru a/drivers/usb/image/hpusbscsi.c b/drivers/usb/image/hpusbscsi.c
--- a/drivers/usb/image/hpusbscsi.c	2005-03-23 19:58:53 -08:00
+++ /dev/null	Wed Dec 31 16:00:00 196900
@@ -1,523 +0,0 @@
-#include <linux/module.h>
-#include <linux/kernel.h>
-#include <linux/sched.h>
-#include <linux/signal.h>
-#include <linux/errno.h>
-#include <linux/init.h>
-#include <linux/slab.h>
-#include <linux/spinlock.h>
-#include <linux/smp_lock.h>
-#include <linux/usb.h>
-#include <asm/atomic.h>
-#include <linux/blkdev.h>
-#include "../../scsi/scsi.h"
-#include <scsi/scsi_host.h>
-
-#include "hpusbscsi.h"
-
-#define DEBUG(x...) \
-	printk( KERN_DEBUG x )
-
-static char *states[]={"FREE", "BEGINNING", "WORKING", "ERROR", "WAIT", "PREMATURE"};
-
-#define TRACE_STATE printk(KERN_DEBUG"hpusbscsi->state = %s at line %d\n", states[hpusbscsi->state], __LINE__)
-
-static Scsi_Host_Template hpusbscsi_scsi_host_template = {
-	.module			= THIS_MODULE,
-	.name			= "hpusbscsi",
-	.proc_name		= "hpusbscsi",
-	.queuecommand		= hpusbscsi_scsi_queuecommand,
-	.eh_abort_handler	= hpusbscsi_scsi_abort,
-	.eh_host_reset_handler	= hpusbscsi_scsi_host_reset,
-	.sg_tablesize		= SG_ALL,
-	.can_queue		= 1,
-	.this_id		= -1,
-	.cmd_per_lun		= 1,
-	.use_clustering		= 1,
-	.emulated		= 1,
-};
-
-static int
-hpusbscsi_usb_probe(struct usb_interface *intf,
-		    const struct usb_device_id *id)
-{
-	struct usb_device *dev = interface_to_usbdev(intf);
-	struct usb_host_interface *altsetting =	intf->cur_altsetting;
-	struct hpusbscsi *new;
-	int error = -ENOMEM;
-	int i;
-
-	if (altsetting->desc.bNumEndpoints != 3) {
-		printk (KERN_ERR "Wrong number of endpoints\n");
-		return -ENODEV;
-	}
-
-	new = kmalloc(sizeof(struct hpusbscsi), GFP_KERNEL);
-	if (!new)
-		return -ENOMEM;
-	memset(new, 0, sizeof(struct hpusbscsi));
-	new->dataurb = usb_alloc_urb(0, GFP_KERNEL);
-	if (!new->dataurb)
-		goto out_kfree;
-	new->controlurb = usb_alloc_urb(0, GFP_KERNEL);
-	if (!new->controlurb)
-		goto out_free_dataurb;
-
-	new->dev = dev;
-	init_waitqueue_head(&new->pending);
-	init_waitqueue_head(&new->deathrow);
-
-	error = -ENODEV;
-	for (i = 0; i < altsetting->desc.bNumEndpoints; i++) {
-		if ((altsetting->endpoint[i].desc.
-		     bmAttributes & USB_ENDPOINT_XFERTYPE_MASK) ==
-				USB_ENDPOINT_XFER_BULK) {
-			if (altsetting->endpoint[i].desc.
-			    bEndpointAddress & USB_DIR_IN) {
-				new->ep_in =
-					altsetting->endpoint[i].desc.
-					bEndpointAddress &
-					USB_ENDPOINT_NUMBER_MASK;
-			} else {
-				new->ep_out =
-					altsetting->endpoint[i].desc.
-					bEndpointAddress &
-					USB_ENDPOINT_NUMBER_MASK;
-			}
-		} else {
-			new->ep_int =
-				altsetting->endpoint[i].desc.
-				bEndpointAddress & USB_ENDPOINT_NUMBER_MASK;
-			new->interrupt_interval= altsetting->endpoint[i].desc.
-				bInterval;
-		}
-	}
-
-	/* build and submit an interrupt URB for status byte handling */
- 	usb_fill_int_urb(new->controlurb, new->dev,
-			usb_rcvintpipe(new->dev, new->ep_int),
-			&new->scsi_state_byte, 1,
-			control_interrupt_callback,new,
-			new->interrupt_interval);
-
-	if (usb_submit_urb(new->controlurb, GFP_KERNEL) < 0)
-		goto out_free_controlurb;
-
-	/* In host->hostdata we store a pointer to desc */
-	new->host = scsi_host_alloc(&hpusbscsi_scsi_host_template, sizeof(new));
-	if (!new->host)
-		goto out_kill_controlurb;
-
-	new->host->hostdata[0] = (unsigned long)new;
-	scsi_add_host(new->host, &intf->dev); /* XXX handle failure */
-	scsi_scan_host(new->host);
-
-	new->sense_command[0] = REQUEST_SENSE;
-	new->sense_command[4] = HPUSBSCSI_SENSE_LENGTH;
-
-	usb_set_intfdata(intf, new);
-	return 0;
-
- out_kill_controlurb:
-	usb_kill_urb(new->controlurb);
- out_free_controlurb:
-	usb_free_urb(new->controlurb);
- out_free_dataurb:
-	usb_free_urb(new->dataurb);
- out_kfree:
-	kfree(new);
-	return error;
-}
-
-static void
-hpusbscsi_usb_disconnect(struct usb_interface *intf)
-{
-	struct hpusbscsi *desc = usb_get_intfdata(intf);
-
-	usb_set_intfdata(intf, NULL);
-
-	scsi_remove_host(desc->host);
-	usb_kill_urb(desc->controlurb);
-	scsi_host_put(desc->host);
-
-	usb_free_urb(desc->controlurb);
-	usb_free_urb(desc->dataurb);
-	kfree(desc);
-}
-
-static struct usb_device_id hpusbscsi_usb_ids[] = {
-	{USB_DEVICE (0x03f0, 0x0701)},	/* HP 53xx */
-	{USB_DEVICE (0x03f0, 0x0801)},	/* HP 7400 */
-	{USB_DEVICE (0x0638, 0x0268)},  /*iVina 1200U */
-	{USB_DEVICE (0x0638, 0x026a)},  /*Scan Dual II */
-	{USB_DEVICE (0x0638, 0x0A13)},  /*Avision AV600U */
-	{USB_DEVICE (0x0638, 0x0A16)},  /*Avision DS610CU Scancopier */
-	{USB_DEVICE (0x0638, 0x0A18)},  /*Avision AV600U Plus */
-	{USB_DEVICE (0x0638, 0x0A23)},  /*Avision AV220 */
-	{USB_DEVICE (0x0638, 0x0A24)},  /*Avision AV210 */
-	{USB_DEVICE (0x0686, 0x4004)},  /*Minolta Elite II */
-	{}			/* Terminating entry */
-};
-
-MODULE_DEVICE_TABLE (usb, hpusbscsi_usb_ids);
-MODULE_LICENSE("GPL");
-
-
-static struct usb_driver hpusbscsi_usb_driver = {
-	.owner = THIS_MODULE,
-	.name ="hpusbscsi",
-	.probe =hpusbscsi_usb_probe,
-	.disconnect =hpusbscsi_usb_disconnect,
-	.id_table =hpusbscsi_usb_ids,
-};
-
-/* module initialisation */
-
-static int __init
-hpusbscsi_init (void)
-{
-	return usb_register(&hpusbscsi_usb_driver);
-}
-
-static void __exit
-hpusbscsi_exit (void)
-{
-	usb_deregister(&hpusbscsi_usb_driver);
-}
-
-module_init (hpusbscsi_init);
-module_exit (hpusbscsi_exit);
-
-static int hpusbscsi_scsi_queuecommand (Scsi_Cmnd *srb, scsi_callback callback)
-{
-	struct hpusbscsi* hpusbscsi = (struct hpusbscsi*)(srb->device->host->hostdata[0]);
-	usb_complete_t usb_callback;
-	int res;
-
-	/* we don't answer for anything but our single device on any faked host controller */
-	if ( srb->device->lun || srb->device->id || srb->device->channel ) {
-		if (callback) {
-			srb->result = DID_BAD_TARGET;
-			callback(srb);
-		}
-                	goto out;
-	}
-
-	/* Now we need to decide which callback to give to the urb we send the command with */
-
-	if (!srb->bufflen) {
-		if (srb->cmnd[0] == REQUEST_SENSE){
-			hpusbscsi->current_data_pipe = usb_rcvbulkpipe(hpusbscsi->dev, hpusbscsi->ep_in);
-			usb_callback = request_sense_callback;
-		} else {
-			usb_callback = simple_command_callback;
-		}
-	} else {
-        	if (likely(srb->use_sg)) {
-			usb_callback = scatter_gather_callback;
-			hpusbscsi->fragment = 0;
-		} else {
-                	usb_callback = simple_payload_callback;
-		}
-		/* Now we find out which direction data is to be transferred in */
-		hpusbscsi->current_data_pipe = DIRECTION_IS_IN(srb->cmnd[0]) ?
-			usb_rcvbulkpipe(hpusbscsi->dev, hpusbscsi->ep_in)
-		:
-			usb_sndbulkpipe(hpusbscsi->dev, hpusbscsi->ep_out)
-		;
-	}
-
-
-	TRACE_STATE;
-
-        /* We zero the sense buffer to avoid confusing user space */
-        memset(srb->sense_buffer, 0, SCSI_SENSE_BUFFERSIZE);
-
-	hpusbscsi->state = HP_STATE_BEGINNING;
-	TRACE_STATE;
-
-	/* We prepare the urb for writing out the scsi command */
-	usb_fill_bulk_urb(
-		hpusbscsi->dataurb,
-		hpusbscsi->dev,
-		usb_sndbulkpipe(hpusbscsi->dev,hpusbscsi->ep_out),
-		srb->cmnd,
-		srb->cmd_len,
-		usb_callback,
-		hpusbscsi
-	);
-	hpusbscsi->scallback = callback;
-	hpusbscsi->srb = srb;
-
-	res = usb_submit_urb(hpusbscsi->dataurb, GFP_ATOMIC);
-	if (unlikely(res)) {
-		hpusbscsi->state = HP_STATE_FREE;
-		TRACE_STATE;
-		if (likely(callback != NULL)) {
-			srb->result = DID_ERROR;
-			callback(srb);
-		}
-	}
-
-out:
-	return 0;
-}
-
-static int hpusbscsi_scsi_host_reset (Scsi_Cmnd *srb)
-{
-	struct hpusbscsi* hpusbscsi = (struct hpusbscsi*)(srb->device->host->hostdata[0]);
-
-	printk(KERN_DEBUG"SCSI reset requested.\n");
-	//usb_reset_device(hpusbscsi->dev);
-	//printk(KERN_DEBUG"SCSI reset completed.\n");
-	hpusbscsi->state = HP_STATE_FREE;
-
-	return 0;
-}
-
-static int hpusbscsi_scsi_abort (Scsi_Cmnd *srb)
-{
-	struct hpusbscsi* hpusbscsi = (struct hpusbscsi*)(srb->device->host->hostdata[0]);
-	printk(KERN_DEBUG"Requested is canceled.\n");
-
-	usb_kill_urb(hpusbscsi->dataurb);
-	usb_kill_urb(hpusbscsi->controlurb);
-	hpusbscsi->state = HP_STATE_FREE;
-
-	return SCSI_ABORT_PENDING;
-}
-
-/* usb interrupt handlers - they are all running IN INTERRUPT ! */
-
-static void handle_usb_error (struct hpusbscsi *hpusbscsi)
-{
-	if (likely(hpusbscsi->scallback != NULL)) {
-		hpusbscsi->srb->result = DID_ERROR;
-		hpusbscsi->scallback(hpusbscsi->srb);
-	}
-	hpusbscsi->state = HP_STATE_FREE;
-}
-
-static void  control_interrupt_callback (struct urb *u, struct pt_regs *regs)
-{
-	struct hpusbscsi * hpusbscsi = (struct hpusbscsi *)u->context;
-	u8 scsi_state;
-
-DEBUG("Getting status byte %d \n",hpusbscsi->scsi_state_byte);
-	if(unlikely(u->status < 0)) {
-                if (likely(hpusbscsi->state != HP_STATE_FREE))
-                        handle_usb_error(hpusbscsi);
-		if (u->status == -ECONNRESET || u->status == -ENOENT || u->status == -ESHUTDOWN)
-			return;
-		else
-			goto resub;
-	}
-
-	scsi_state = hpusbscsi->scsi_state_byte;
-	if (hpusbscsi->state != HP_STATE_ERROR) {
-		hpusbscsi->srb->result &= SCSI_ERR_MASK;
-		hpusbscsi->srb->result |= scsi_state;
-	}
-
-	if (scsi_state == CHECK_CONDITION << 1) {
-		if (hpusbscsi->state == HP_STATE_WAIT) {
-			issue_request_sense(hpusbscsi);
-		} else {
-			/* we request sense after an eventual data transfer */
-			hpusbscsi->state = HP_STATE_ERROR;
-		}
-	}
-
-	if (hpusbscsi->scallback != NULL && hpusbscsi->state == HP_STATE_WAIT && scsi_state != CHECK_CONDITION <<1 )
-		/* we do a callback to the scsi layer if and only if all data has been transferred */
-		hpusbscsi->scallback(hpusbscsi->srb);
-
-	TRACE_STATE;
-	switch (hpusbscsi->state) {
-	case HP_STATE_WAIT:
-		hpusbscsi->state = HP_STATE_FREE;
-	TRACE_STATE;
-		break;
-	case HP_STATE_WORKING:
-	case HP_STATE_BEGINNING:
-		hpusbscsi->state = HP_STATE_PREMATURE;
-	TRACE_STATE;
-		break;
-	case HP_STATE_ERROR:
-		break;
-	default:
-		printk(KERN_ERR"hpusbscsi: Unexpected status report.\n");
-	TRACE_STATE;
-		hpusbscsi->state = HP_STATE_FREE;
-	TRACE_STATE;
-		break;
-	}
-resub:
-	usb_submit_urb(u, GFP_ATOMIC);
-}
-
-static void simple_command_callback(struct urb *u, struct pt_regs *regs)
-{
-	struct hpusbscsi * hpusbscsi = (struct hpusbscsi *)u->context;
-	if (unlikely(u->status<0)) {
-		handle_usb_error(hpusbscsi);
-		return;
-        }
-	TRACE_STATE;
-	if (hpusbscsi->state != HP_STATE_PREMATURE) {
-	        TRACE_STATE;
-		hpusbscsi->state = HP_STATE_WAIT;
-	} else {
-		if (likely(hpusbscsi->scallback != NULL))
-			hpusbscsi->scallback(hpusbscsi->srb);
-		hpusbscsi->state = HP_STATE_FREE;
-	TRACE_STATE;
-	}
-}
-
-static void scatter_gather_callback(struct urb *u, struct pt_regs *regs)
-{
-	struct hpusbscsi * hpusbscsi = (struct hpusbscsi *)u->context;
-        struct scatterlist *sg = hpusbscsi->srb->buffer;
-        usb_complete_t callback;
-        int res;
-
-        DEBUG("Going through scatter/gather\n");
-        if (unlikely(u->status < 0)) {
-                handle_usb_error(hpusbscsi);
-                return;
-        }
-
-        if (hpusbscsi->fragment + 1 != hpusbscsi->srb->use_sg)
-                callback = scatter_gather_callback;
-        else
-                callback = simple_done;
-
-	TRACE_STATE;
-        if (hpusbscsi->state != HP_STATE_PREMATURE)
-		hpusbscsi->state = HP_STATE_WORKING;
-	TRACE_STATE;
-
-        usb_fill_bulk_urb(
-                u,
-                hpusbscsi->dev,
-                hpusbscsi->current_data_pipe,
-                page_address(sg[hpusbscsi->fragment].page) +
-		sg[hpusbscsi->fragment].offset,
-                sg[hpusbscsi->fragment++].length,
-                callback,
-                hpusbscsi
-        );
-
-        res = usb_submit_urb(u, GFP_ATOMIC);
-        if (unlikely(res))
-                handle_usb_error(hpusbscsi);
-	TRACE_STATE;
-}
-
-static void simple_done (struct urb *u, struct pt_regs *regs)
-{
-	struct hpusbscsi * hpusbscsi = (struct hpusbscsi *)u->context;
-
-        if (unlikely(u->status < 0)) {
-                handle_usb_error(hpusbscsi);
-                return;
-        }
-        DEBUG("Data transfer done\n");
-	TRACE_STATE;
-	if (hpusbscsi->state != HP_STATE_PREMATURE) {
-		if (unlikely(u->status < 0)) {
-			handle_usb_error(hpusbscsi);
-		} else {
-			if (hpusbscsi->state != HP_STATE_ERROR) {
-				hpusbscsi->state = HP_STATE_WAIT;
-			} else {
-				issue_request_sense(hpusbscsi);
-			}
-		}
-	} else {
-		if (likely(hpusbscsi->scallback != NULL))
-			hpusbscsi->scallback(hpusbscsi->srb);
-		hpusbscsi->state = HP_STATE_FREE;
-	}
-}
-
-static void simple_payload_callback (struct urb *u, struct pt_regs *regs)
-{
-	struct hpusbscsi * hpusbscsi = (struct hpusbscsi *)u->context;
-	int res;
-
-	if (unlikely(u->status<0)) {
-                handle_usb_error(hpusbscsi);
-		return;
-        }
-
-	usb_fill_bulk_urb(
-		u,
-		hpusbscsi->dev,
-		hpusbscsi->current_data_pipe,
-		hpusbscsi->srb->buffer,
-		hpusbscsi->srb->bufflen,
-		simple_done,
-		hpusbscsi
-	);
-
-	res = usb_submit_urb(u, GFP_ATOMIC);
-	if (unlikely(res)) {
-                handle_usb_error(hpusbscsi);
-		return;
-        }
-	TRACE_STATE;
-	if (hpusbscsi->state != HP_STATE_PREMATURE) {
-		hpusbscsi->state = HP_STATE_WORKING;
-	TRACE_STATE;
-	} 
-}
-
-static void request_sense_callback (struct urb *u, struct pt_regs *regs)
-{
-	struct hpusbscsi * hpusbscsi = (struct hpusbscsi *)u->context;
-
-	if (u->status<0) {
-                handle_usb_error(hpusbscsi);
-		return;
-        }
-
-	usb_fill_bulk_urb(
-		u,
-		hpusbscsi->dev,
-		hpusbscsi->current_data_pipe,
-		hpusbscsi->srb->sense_buffer,
-		SCSI_SENSE_BUFFERSIZE,
-		simple_done,
-		hpusbscsi
-	);
-
-	if (0 > usb_submit_urb(u, GFP_ATOMIC)) {
-		handle_usb_error(hpusbscsi);
-		return;
-	}
-	if (hpusbscsi->state != HP_STATE_PREMATURE && hpusbscsi->state != HP_STATE_ERROR)
-		hpusbscsi->state = HP_STATE_WORKING;
-}
-
-static void issue_request_sense (struct hpusbscsi *hpusbscsi)
-{
-	usb_fill_bulk_urb(
-		hpusbscsi->dataurb,
-		hpusbscsi->dev,
-		usb_sndbulkpipe(hpusbscsi->dev, hpusbscsi->ep_out),
-		&hpusbscsi->sense_command,
-		SENSE_COMMAND_SIZE,
-		request_sense_callback,
-		hpusbscsi
-	);
-
-	hpusbscsi->current_data_pipe = usb_rcvbulkpipe(hpusbscsi->dev, hpusbscsi->ep_in);
-
-	if (0 > usb_submit_urb(hpusbscsi->dataurb, GFP_ATOMIC)) {
-		handle_usb_error(hpusbscsi);
-	}
-}
-
-
diff -Nru a/drivers/usb/image/hpusbscsi.h b/drivers/usb/image/hpusbscsi.h
--- a/drivers/usb/image/hpusbscsi.h	2005-03-23 19:58:52 -08:00
+++ /dev/null	Wed Dec 31 16:00:00 196900
@@ -1,73 +0,0 @@
-/* Header file for the hpusbscsi driver */
-/* (C) Copyright 2001 Oliver Neukum */
-/* sponsored by the Linux Usb Project */
-/* large parts based on or taken from code by John Fremlin and Matt Dharm */
-/* this file is licensed under the GPL */
-
-/* A big thanks to Jose for untiring testing */
-
-typedef void (*scsi_callback)(Scsi_Cmnd *);
-
-#define SENSE_COMMAND_SIZE 6
-#define HPUSBSCSI_SENSE_LENGTH 0x16
-
-struct hpusbscsi
-{
-        struct usb_device *dev; /* NULL indicates unplugged device */
-        int ep_out;
-        int ep_in;
-        int ep_int;
-        int interrupt_interval;
-	int number;
-	int fragment;
-        struct Scsi_Host *host;
-
-	scsi_callback scallback;
-	Scsi_Cmnd *srb;
-
-
-        wait_queue_head_t pending;
-        wait_queue_head_t deathrow;
-
-        struct urb *dataurb;
-        struct urb *controlurb;
-
-
-        int state;
-        int current_data_pipe;
-	u8 sense_command[SENSE_COMMAND_SIZE];
-        u8 scsi_state_byte;
-};
-
-#define SCSI_ERR_MASK ~0x3fu
-
-static const unsigned char scsi_command_direction[256/8] = {
-	0x28, 0x81, 0x14, 0x14, 0x20, 0x01, 0x90, 0x77,
-	0x0C, 0x20, 0x00, 0x04, 0x00, 0x00, 0x00, 0x00,
-	0x00, 0x00, 0x00, 0x00, 0x00, 0x01, 0x00, 0x01,
-	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
-};
-
-#define DIRECTION_IS_IN(x) ((scsi_command_direction[x>>3] >> (x & 7)) & 1)
-
-static void simple_command_callback(struct urb *u, struct pt_regs *regs);
-static void scatter_gather_callback(struct urb *u, struct pt_regs *regs);
-static void simple_payload_callback (struct urb *u, struct pt_regs *regs);
-static void request_sense_callback (struct urb *u, struct pt_regs *regs);
-static void control_interrupt_callback (struct urb *u, struct pt_regs *regs);
-static void simple_done (struct urb *u, struct pt_regs *regs);
-static int hpusbscsi_scsi_queuecommand (Scsi_Cmnd *srb, scsi_callback callback);
-static int hpusbscsi_scsi_host_reset (Scsi_Cmnd *srb);
-static int hpusbscsi_scsi_abort (Scsi_Cmnd *srb);
-static void issue_request_sense (struct hpusbscsi *hpusbscsi);
-
-/* defines for internal driver state */
-#define HP_STATE_FREE                 0  /*ready for next request */
-#define HP_STATE_BEGINNING      1  /*command being transferred */
-#define HP_STATE_WORKING         2  /* data transfer stage */
-#define HP_STATE_ERROR             3  /* error has been reported */
-#define HP_STATE_WAIT                 4  /* waiting for status transfer */
-#define HP_STATE_PREMATURE              5 /* status prematurely reported */
-
-
-
diff -Nru a/drivers/usb/image/microtek.c b/drivers/usb/image/microtek.c
--- a/drivers/usb/image/microtek.c	2005-03-23 19:58:53 -08:00
+++ b/drivers/usb/image/microtek.c	2005-03-23 19:58:53 -08:00
@@ -703,6 +703,7 @@
 	int ep_in_set[3]; /* this will break if we have more than three endpoints
 			   which is why we check */
 	int *ep_in_current = ep_in_set;
+	int err_retval = -ENOMEM;
 
 	struct mts_desc * new_desc;
 	struct vendor_product const* p;
@@ -809,7 +810,10 @@
 		goto out_free_urb;
 
 	new_desc->host->hostdata[0] = (unsigned long)new_desc;
-	scsi_add_host(new_desc->host, NULL); /* XXX handle failure */
+	if (scsi_add_host(new_desc->host, NULL)) {
+		err_retval = -EIO;
+		goto out_free_urb;
+	}
 	scsi_scan_host(new_desc->host);
 
 	usb_set_intfdata(intf, new_desc);
@@ -820,7 +824,7 @@
  out_kfree:
 	kfree(new_desc);
  out:
-	return -ENOMEM;
+	return err_retval;
 }
 
 static void mts_usb_disconnect (struct usb_interface *intf)
diff -Nru a/drivers/usb/input/aiptek.c b/drivers/usb/input/aiptek.c
--- a/drivers/usb/input/aiptek.c	2005-03-23 19:58:52 -08:00
+++ b/drivers/usb/input/aiptek.c	2005-03-23 19:58:52 -08:00
@@ -794,7 +794,7 @@
  * manufacturing revisions. In any event, we consider these 
  * IDs to not be model-specific nor unique.
  */
-struct usb_device_id aiptek_ids[] = {
+static const struct usb_device_id aiptek_ids[] = {
 	{USB_DEVICE(USB_VENDOR_ID_AIPTEK, 0x01)},
 	{USB_DEVICE(USB_VENDOR_ID_AIPTEK, 0x10)},
 	{USB_DEVICE(USB_VENDOR_ID_AIPTEK, 0x20)},
diff -Nru a/drivers/usb/media/ibmcam.c b/drivers/usb/media/ibmcam.c
--- a/drivers/usb/media/ibmcam.c	2005-03-23 19:58:52 -08:00
+++ b/drivers/usb/media/ibmcam.c	2005-03-23 19:58:52 -08:00
@@ -1036,7 +1036,8 @@
  * History:
  * 1/21/00  Created.
  */
-void ibmcam_ProcessIsocData(struct uvd *uvd, struct usbvideo_frame *frame)
+static void ibmcam_ProcessIsocData(struct uvd *uvd,
+				   struct usbvideo_frame *frame)
 {
 	enum ParseState newstate;
 	long copylen = 0;
diff -Nru a/drivers/usb/media/pwc/pwc-if.c b/drivers/usb/media/pwc/pwc-if.c
--- a/drivers/usb/media/pwc/pwc-if.c	2005-03-23 19:58:52 -08:00
+++ b/drivers/usb/media/pwc/pwc-if.c	2005-03-23 19:58:52 -08:00
@@ -322,7 +322,7 @@
 	  case 730:
 	  case 740:
 	  case 750:
-	    Trace(TRACE_MEMORY,"private_data(%d)\n",sizeof(struct pwc_dec23_private));
+	    Trace(TRACE_MEMORY,"private_data(%Zd)\n",sizeof(struct pwc_dec23_private));
 	    kbuf = kmalloc(sizeof(struct pwc_dec23_private), GFP_KERNEL);	/* Timon & Kiara */
 	    break;
 	  case 645:
@@ -1179,7 +1179,7 @@
 	DECLARE_WAITQUEUE(wait, current);
         int bytes_to_read;
 
-	Trace(TRACE_READ, "video_read(0x%p, %p, %d) called.\n", vdev, buf, count);
+	Trace(TRACE_READ, "video_read(0x%p, %p, %Zd) called.\n", vdev, buf, count);
 	if (vdev == NULL)
 		return -EFAULT;
 	pdev = vdev->priv;
diff -Nru a/drivers/usb/misc/emi26.c b/drivers/usb/misc/emi26.c
--- a/drivers/usb/misc/emi26.c	2005-03-23 19:58:52 -08:00
+++ b/drivers/usb/misc/emi26.c	2005-03-23 19:58:52 -08:00
@@ -30,6 +30,7 @@
 
 #define EMI26_VENDOR_ID 		0x086a  /* Emagic Soft-und Hardware GmBH */
 #define EMI26_PRODUCT_ID		0x0100	/* EMI 2|6 without firmware */
+#define EMI26B_PRODUCT_ID		0x0102	/* EMI 2|6 without firmware */
 
 #define ANCHOR_LOAD_INTERNAL	0xA0	/* Vendor specific request code for Anchor Upload/Download (This one is implemented in the core) */
 #define ANCHOR_LOAD_EXTERNAL	0xA3	/* This command is not implemented in the core. Requires firmware */
@@ -203,6 +204,7 @@
 
 static struct usb_device_id id_table [] = {
 	{ USB_DEVICE(EMI26_VENDOR_ID, EMI26_PRODUCT_ID) },
+	{ USB_DEVICE(EMI26_VENDOR_ID, EMI26B_PRODUCT_ID) },
 	{ }                                             /* Terminating entry */
 };
 
diff -Nru a/drivers/usb/misc/rio500.c b/drivers/usb/misc/rio500.c
--- a/drivers/usb/misc/rio500.c	2005-03-23 19:58:52 -08:00
+++ b/drivers/usb/misc/rio500.c	2005-03-23 19:58:52 -08:00
@@ -40,6 +40,7 @@
 #include <linux/spinlock.h>
 #include <linux/usb.h>
 #include <linux/smp_lock.h>
+#include <linux/wait.h>
 
 #include "rio500_usb.h"
 
@@ -264,6 +265,7 @@
 write_rio(struct file *file, const char __user *buffer,
 	  size_t count, loff_t * ppos)
 {
+	DEFINE_WAIT(wait);
 	struct rio_usb_data *rio = &rio_instance;
 
 	unsigned long copy_size;
@@ -319,7 +321,9 @@
 					errn = -ETIME;
 					goto error;
 				}
-				interruptible_sleep_on_timeout(&rio-> wait_q, NAK_TIMEOUT);
+				prepare_to_wait(&rio->wait_q, &wait, TASK_INTERRUPTIBLE);
+				schedule_timeout(NAK_TIMEOUT);
+				finish_wait(&rio->wait_q, &wait);
 				continue;
 			} else if (!result && partial) {
 				obuf += partial;
@@ -349,6 +353,7 @@
 static ssize_t
 read_rio(struct file *file, char __user *buffer, size_t count, loff_t * ppos)
 {
+	DEFINE_WAIT(wait);
 	struct rio_usb_data *rio = &rio_instance;
 	ssize_t read_count;
 	unsigned int partial;
@@ -399,8 +404,9 @@
 				err("read_rio: maxretry timeout");
 				return -ETIME;
 			}
-			interruptible_sleep_on_timeout(&rio->wait_q,
-						       NAK_TIMEOUT);
+			prepare_to_wait(&rio->wait_q, &wait, TASK_INTERRUPTIBLE);
+			schedule_timeout(NAK_TIMEOUT);
+			finish_wait(&rio->wait_q, &wait);
 			continue;
 		} else if (result != -EREMOTEIO) {
 			up(&(rio->lock));
diff -Nru a/drivers/usb/misc/sisusbvga/sisusb.c b/drivers/usb/misc/sisusbvga/sisusb.c
--- a/drivers/usb/misc/sisusbvga/sisusb.c	2005-03-23 19:58:52 -08:00
+++ b/drivers/usb/misc/sisusbvga/sisusb.c	2005-03-23 19:58:52 -08:00
@@ -564,7 +564,7 @@
 						struct sisusb_packet *packet)
 {
 	int ret;
-	int bytes_transferred = 0;
+	ssize_t bytes_transferred = 0;
 	__le32 tmp;
 
 	if (len == 6)
@@ -601,7 +601,7 @@
 					unsigned int tflags)
 {
 	int ret;
-	int bytes_transferred = 0;
+	ssize_t bytes_transferred = 0;
 	__le32 tmp;
 
 	if (len == 6)
@@ -983,7 +983,7 @@
 				msgcount++;
 				if (msgcount < 500)
 					printk(KERN_ERR
-						"sisusbvga[%d]: Wrote %d of "
+						"sisusbvga[%d]: Wrote %Zd of "
 						"%d bytes, error %d\n",
 						sisusb->minor, *bytes_written,
 						length, ret);
@@ -1381,7 +1381,8 @@
 static int
 sisusb_clear_vram(struct sisusb_usb_data *sisusb, u32 address, int length)
 {
-	int ret, i, j;
+	int ret, i;
+	ssize_t j;
 
 	if (address < sisusb->vrambase)
 		return 1;
@@ -2271,7 +2272,7 @@
 
 /* fops */
 
-int
+static int
 sisusb_open(struct inode *inode, struct file *file)
 {
 	struct sisusb_usb_data *sisusb;
@@ -2361,7 +2362,7 @@
 	kfree(sisusb);
 }
 
-int
+static int
 sisusb_release(struct inode *inode, struct file *file)
 {
 	struct sisusb_usb_data *sisusb;
@@ -2399,7 +2400,7 @@
 	return 0;
 }
 
-ssize_t
+static ssize_t
 sisusb_read(struct file *file, char __user *buffer, size_t count, loff_t *ppos)
 {
 	struct sisusb_usb_data *sisusb;
@@ -2540,7 +2541,7 @@
 	return errno ? errno : bytes_read;
 }
 
-ssize_t
+static ssize_t
 sisusb_write(struct file *file, const char __user *buffer, size_t count,
 								loff_t *ppos)
 {
diff -Nru a/drivers/usb/net/catc.c b/drivers/usb/net/catc.c
--- a/drivers/usb/net/catc.c	2005-03-23 19:58:52 -08:00
+++ b/drivers/usb/net/catc.c	2005-03-23 19:58:52 -08:00
@@ -664,7 +664,8 @@
 	}
 }
 
-void catc_get_drvinfo(struct net_device *dev, struct ethtool_drvinfo *info)
+static void catc_get_drvinfo(struct net_device *dev,
+			     struct ethtool_drvinfo *info)
 {
 	struct catc *catc = netdev_priv(dev);
 	strncpy(info->driver, driver_name, ETHTOOL_BUSINFO_LEN);
diff -Nru a/drivers/usb/net/kaweth.c b/drivers/usb/net/kaweth.c
--- a/drivers/usb/net/kaweth.c	2005-03-23 19:58:52 -08:00
+++ b/drivers/usb/net/kaweth.c	2005-03-23 19:58:52 -08:00
@@ -594,7 +594,7 @@
 
 	struct sk_buff *skb;
 
-	if(unlikely(urb->status == -ECONNRESET || urb->status == -ECONNABORTED || urb->status == -ESHUTDOWN))
+	if(unlikely(urb->status == -ECONNRESET || urb->status == -ESHUTDOWN))
 	/* we are killed - set a flag and wake the disconnect handler */
 	{
 		kaweth->end = 1;
diff -Nru a/drivers/usb/net/kawethfw.h b/drivers/usb/net/kawethfw.h
--- a/drivers/usb/net/kawethfw.h	2005-03-23 19:58:52 -08:00
+++ b/drivers/usb/net/kawethfw.h	2005-03-23 19:58:52 -08:00
@@ -551,7 +551,7 @@
 };
 
 
-const int len_kaweth_trigger_code = sizeof(kaweth_trigger_code);
-const int len_kaweth_trigger_code_fix = sizeof(kaweth_trigger_code_fix);
-const int len_kaweth_new_code = sizeof(kaweth_new_code);
-const int len_kaweth_new_code_fix = sizeof(kaweth_new_code_fix);
+static const int len_kaweth_trigger_code = sizeof(kaweth_trigger_code);
+static const int len_kaweth_trigger_code_fix = sizeof(kaweth_trigger_code_fix);
+static const int len_kaweth_new_code = sizeof(kaweth_new_code);
+static const int len_kaweth_new_code_fix = sizeof(kaweth_new_code_fix);
diff -Nru a/drivers/usb/net/pegasus.c b/drivers/usb/net/pegasus.c
--- a/drivers/usb/net/pegasus.c	2005-03-23 19:58:52 -08:00
+++ b/drivers/usb/net/pegasus.c	2005-03-23 19:58:53 -08:00
@@ -956,7 +956,8 @@
 	return 0;
 }
 
-void pegasus_get_drvinfo(struct net_device *dev, struct ethtool_drvinfo *info)
+static void pegasus_get_drvinfo(struct net_device *dev,
+				struct ethtool_drvinfo *info)
 {
 	pegasus_t *pegasus = netdev_priv(dev);
 	strncpy(info->driver, driver_name, sizeof (info->driver) - 1);
@@ -1156,10 +1157,10 @@
 }
 
 
-struct workqueue_struct *pegasus_workqueue = NULL;
+static struct workqueue_struct *pegasus_workqueue = NULL;
 #define CARRIER_CHECK_DELAY (2 * HZ)
 
-void check_carrier(void *data)
+static void check_carrier(void *data)
 {
 	pegasus_t *pegasus = data;
 	set_carrier(pegasus->net);
diff -Nru a/drivers/usb/net/usbnet.c b/drivers/usb/net/usbnet.c
--- a/drivers/usb/net/usbnet.c	2005-03-23 19:58:52 -08:00
+++ b/drivers/usb/net/usbnet.c	2005-03-23 19:58:52 -08:00
@@ -185,6 +185,7 @@
 
 	// i/o info: pipes etc
 	unsigned		in, out;
+	struct usb_host_endpoint *status;
 	unsigned		maxpacket;
 	struct timer_list	delay;
 
@@ -200,6 +201,7 @@
 	struct sk_buff_head	rxq;
 	struct sk_buff_head	txq;
 	struct sk_buff_head	done;
+	struct urb		*interrupt;
 	struct tasklet_struct	bh;
 
 	struct work_struct	kevent;
@@ -207,6 +209,7 @@
 #		define EVENT_TX_HALT	0
 #		define EVENT_RX_HALT	1
 #		define EVENT_RX_MEMORY	2
+#		define EVENT_STS_SPLIT	3
 };
 
 // device-specific info used by the driver
@@ -237,6 +240,9 @@
 	/* see if peer is connected ... can sleep */
 	int	(*check_connect)(struct usbnet *);
 
+	/* for status polling */
+	void	(*status)(struct usbnet *, struct urb *);
+
 	/* fixup rx packet (strip framing) */
 	int	(*rx_fixup)(struct usbnet *dev, struct sk_buff *skb);
 
@@ -312,38 +318,52 @@
 get_endpoints (struct usbnet *dev, struct usb_interface *intf)
 {
 	int				tmp;
-	struct usb_host_interface	*alt;
-	struct usb_host_endpoint	*in, *out;
+	struct usb_host_interface	*alt = NULL;
+	struct usb_host_endpoint	*in = NULL, *out = NULL;
+	struct usb_host_endpoint	*status = NULL;
 
 	for (tmp = 0; tmp < intf->num_altsetting; tmp++) {
 		unsigned	ep;
 
-		in = out = NULL;
+		in = out = status = NULL;
 		alt = intf->altsetting + tmp;
 
 		/* take the first altsetting with in-bulk + out-bulk;
+		 * remember any status endpoint, just in case;
 		 * ignore other endpoints and altsetttings.
 		 */
 		for (ep = 0; ep < alt->desc.bNumEndpoints; ep++) {
 			struct usb_host_endpoint	*e;
+			int				intr = 0;
 
 			e = alt->endpoint + ep;
-			if (e->desc.bmAttributes != USB_ENDPOINT_XFER_BULK)
+			switch (e->desc.bmAttributes) {
+			case USB_ENDPOINT_XFER_INT:
+				if (!(e->desc.bEndpointAddress & USB_DIR_IN))
+					continue;
+				intr = 1;
+				/* FALLTHROUGH */
+			case USB_ENDPOINT_XFER_BULK:
+				break;
+			default:
 				continue;
+			}
 			if (e->desc.bEndpointAddress & USB_DIR_IN) {
-				if (!in)
+				if (!intr && !in)
 					in = e;
+				else if (intr && !status)
+					status = e;
 			} else {
 				if (!out)
 					out = e;
 			}
-			if (in && out)
-				goto found;
 		}
+		if (in && out)
+			break;
 	}
-	return -EINVAL;
+	if (!alt || !in || !out)
+		return -EINVAL;
 
-found:
 	if (alt->desc.bAlternateSetting != 0
 			|| !(dev->driver_info->flags & FLAG_NO_SETINT)) {
 		tmp = usb_set_interface (dev->udev, alt->desc.bInterfaceNumber,
@@ -356,9 +376,48 @@
 			in->desc.bEndpointAddress & USB_ENDPOINT_NUMBER_MASK);
 	dev->out = usb_sndbulkpipe (dev->udev,
 			out->desc.bEndpointAddress & USB_ENDPOINT_NUMBER_MASK);
+	dev->status = status;
 	return 0;
 }
 
+static void intr_complete (struct urb *urb, struct pt_regs *regs);
+
+static int init_status (struct usbnet *dev, struct usb_interface *intf)
+{
+	char		*buf = NULL;
+	unsigned	pipe = 0;
+	unsigned	maxp;
+	unsigned	period;
+
+	if (!dev->driver_info->status)
+		return -ENODEV;
+
+	pipe = usb_rcvintpipe (dev->udev,
+			dev->status->desc.bEndpointAddress
+				& USB_ENDPOINT_NUMBER_MASK);
+	maxp = usb_maxpacket (dev->udev, pipe, 0);
+
+	/* avoid 1 msec chatter:  min 8 msec poll rate */
+	period = max ((int) dev->status->desc.bInterval,
+		(dev->udev->speed == USB_SPEED_HIGH) ? 7 : 3);
+
+	buf = kmalloc (maxp, SLAB_KERNEL);
+	if (buf) {
+		dev->interrupt = usb_alloc_urb (0, SLAB_KERNEL);
+		if (!dev->interrupt) {
+			kfree (buf);
+			return -ENOMEM;
+		} else {
+			usb_fill_int_urb(dev->interrupt, dev->udev, pipe,
+				buf, maxp, intr_complete, dev, period);
+			dev_dbg(&intf->dev,
+				"status ep%din, %d bytes period %d\n",
+				usb_pipeendpoint(pipe), maxp, period);
+		}
+	}
+	return  0;
+}
+
 static void skb_return (struct usbnet *dev, struct sk_buff *skb)
 {
 	int	status;
@@ -1414,6 +1473,29 @@
 		usb_driver_release_interface (&usbnet_driver, info->data);
 		return status;
 	}
+
+	/* status endpoint: optional for CDC Ethernet, not RNDIS (or ACM) */
+	dev->status = NULL;
+	if (info->control->cur_altsetting->desc.bNumEndpoints == 1) {
+		struct usb_endpoint_descriptor	*desc;
+
+		dev->status = &info->control->cur_altsetting->endpoint [0];
+		desc = &dev->status->desc;
+		if (desc->bmAttributes != USB_ENDPOINT_XFER_INT
+				|| !(desc->bEndpointAddress & USB_DIR_IN)
+				|| (le16_to_cpu(desc->wMaxPacketSize)
+					< sizeof (struct usb_cdc_notification))
+				|| !desc->bInterval) {
+			dev_dbg (&intf->dev, "bad notification endpoint\n");
+			dev->status = NULL;
+		}
+	}
+	if (rndis && !dev->status) {
+		dev_dbg (&intf->dev, "missing RNDIS status endpoint\n");
+		usb_set_intfdata(info->data, NULL);
+		usb_driver_release_interface (&usbnet_driver, info->data);
+		return -ENODEV;
+	}
 	return 0;
 
 bad_desc:
@@ -1442,6 +1524,51 @@
 	}
 }
 
+
+static void dumpspeed (struct usbnet *dev, __le32 *speeds)
+{
+	devinfo (dev, "link speeds: %u kbps up, %u kbps down",
+		__le32_to_cpu(speeds[0]) / 1000,
+		__le32_to_cpu(speeds[1]) / 1000);
+}
+
+static void cdc_status (struct usbnet *dev, struct urb *urb)
+{
+	struct usb_cdc_notification	*event;
+
+	if (urb->actual_length < sizeof *event)
+		return;
+	
+	/* SPEED_CHANGE can get split into two 8-byte packets */
+	if (test_and_clear_bit (EVENT_STS_SPLIT, &dev->flags)) {
+		dumpspeed (dev, (__le32 *) urb->transfer_buffer);
+		return;
+	}
+
+	event = urb->transfer_buffer;
+	switch (event->bNotificationType) {
+	case USB_CDC_NOTIFY_NETWORK_CONNECTION:
+		devdbg (dev, "CDC: carrier %s", event->wValue ? "on" : "off");
+		if (event->wValue)
+			netif_carrier_on(dev->net);
+		else
+			netif_carrier_off(dev->net);
+		break;
+	case USB_CDC_NOTIFY_SPEED_CHANGE:	/* tx/rx rates */
+		devdbg (dev, "CDC: speed change (len %d)", urb->actual_length);
+		if (urb->actual_length != (sizeof *event + 8))
+			set_bit (EVENT_STS_SPLIT, &dev->flags);
+		else
+			dumpspeed (dev, (__le32 *) &event[1]);
+		break;
+	// case USB_CDC_NOTIFY_RESPONSE_AVAILABLE:	/* RNDIS; or unsolicited */
+	default:
+		deverr (dev, "CDC: unexpected notification %02x!",
+				 event->bNotificationType);
+		break;
+	}
+}
+
 #endif	/* NEED_GENERIC_CDC */
 
 
@@ -1520,6 +1647,7 @@
 	// .check_connect = cdc_check_connect,
 	.bind =		cdc_bind,
 	.unbind =	cdc_unbind,
+	.status =	cdc_status,
 };
 
 #endif	/* CONFIG_USB_CDCETHER */
@@ -2526,11 +2654,17 @@
  * For the current version of that driver, the main way that framing is
  * nonstandard (also from perspective of the CDC ethernet model!) is a
  * crc32, added to help detect when some sa1100 usb-to-memory DMA errata
- * haven't been fully worked around.
+ * haven't been fully worked around.  Also, all Zaurii use the same
+ * default Ethernet address.
  *
  * PXA based models use the same framing, and also can't implement
  * set_interface properly.
  *
+ * All known Zaurii lie about their standards conformance.  Most lie by
+ * saying they support CDC Ethernet.  Some lie and say they support CDC
+ * MDLM (as if for access to cell phone modems).  Someone, please beat 
+ * on Sharp for a while with a cluestick.
+ *
  *-------------------------------------------------------------------------*/
 
 static struct sk_buff *
@@ -2582,6 +2716,13 @@
 };
 #define	ZAURUS_PXA_INFO		((unsigned long)&zaurus_pxa_info)
 
+static const struct driver_info	zaurus_pxa_mdlm_info = {
+	.description =	"Sharp Zaurus, PXA-255 based",
+	.flags =	FLAG_FRAMING_Z,
+	.check_connect = always_connected,
+	.tx_fixup = 	zaurus_tx_fixup,
+};
+
 static const struct driver_info	olympus_mxl_info = {
 	.description =	"Olympus R1000",
 	.flags =	FLAG_FRAMING_Z,
@@ -2871,6 +3012,42 @@
 #endif /* VERBOSE */
 }
 
+static void intr_complete (struct urb *urb, struct pt_regs *regs)
+{
+	struct usbnet	*dev = urb->context;
+	int		status = urb->status;
+
+	switch (status) {
+	    /* success */
+	    case 0:
+		dev->driver_info->status(dev, urb);
+		break;
+
+	    /* software-driven interface shutdown */
+	    case -ENOENT:		// urb killed
+	    case -ESHUTDOWN:		// hardware gone
+#ifdef	VERBOSE
+		devdbg (dev, "intr shutdown, code %d", status);
+#endif
+		return;
+
+	    /* NOTE:  not throttling like RX/TX, since this endpoint
+	     * already polls infrequently
+	     */
+	    default:
+		devdbg (dev, "intr status %d", status);
+		break;
+	}
+
+	if (!netif_running (dev->net))
+		return;
+
+	memset(urb->transfer_buffer, 0, urb->transfer_buffer_length);
+	status = usb_submit_urb (urb, GFP_ATOMIC);
+	if (status != 0)
+		deverr(dev, "intr resubmit --> %d", status);
+}
+
 /*-------------------------------------------------------------------------*/
 
 // unlink pending rx/tx; completion handlers do all other cleanup
@@ -2938,6 +3115,8 @@
 	dev->wait = NULL;
 	remove_wait_queue (&unlink_wakeup, &wait); 
 
+	usb_kill_urb(dev->interrupt);
+
 	/* deferred work (task, timer, softirq) must also stop.
 	 * can't flush_scheduled_work() until we drop rtnl (later),
 	 * else workers could deadlock; so make workers a NOP.
@@ -2976,6 +3155,15 @@
 		goto done;
 	}
 
+	/* start any status interrupt transfer */
+	if (dev->interrupt) {
+		retval = usb_submit_urb (dev->interrupt, GFP_KERNEL);
+		if (retval < 0) {
+			deverr (dev, "intr submit %d", retval);
+			goto done;
+		}
+	}
+
 	netif_start_queue (net);
 	if (dev->msg_level >= 2) {
 		char	*framing;
@@ -3479,6 +3667,8 @@
 			status = 0;
 
 	}
+	if (status == 0 && dev->status)
+		status = init_status (dev, udev);
 	if (status < 0)
 		goto out1;
 
@@ -3729,6 +3919,7 @@
  * Same idea as above, but different framing.
  *
  * PXA-2xx based models are also lying-about-cdc.
+ * Some models don't even tell the same lies ...
  *
  * NOTE:  OpenZaurus versions with 2.6 kernels won't use these entries,
  * unlike the older ones with 2.4 "embedix" kernels.
@@ -3786,9 +3977,25 @@
 	.match_flags    =   USB_DEVICE_ID_MATCH_INT_INFO
 		 | USB_DEVICE_ID_MATCH_DEVICE,
 	.idVendor               = 0x04DD,
+	/* reported with some C860 units */
 	.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.
+	 */
+}, {
+	.match_flags    =   USB_DEVICE_ID_MATCH_INT_INFO
+		 | USB_DEVICE_ID_MATCH_DEVICE,
+	.idVendor               = 0x04DD,
+	/* reported with some C860 units */
+	.idProduct              = 0x9031,	/* C-860 */
+	.bInterfaceClass	= USB_CLASS_COMM,
+	.bInterfaceSubClass	= USB_CDC_SUBCLASS_MDLM,
+	.bInterfaceProtocol	= USB_CDC_PROTO_NONE,
+	.driver_info 		= (unsigned long) &zaurus_pxa_mdlm_info,
+#endif
 },
 
 /* Olympus has some models with a Zaurus-compatible option.
diff -Nru a/drivers/usb/serial/digi_acceleport.c b/drivers/usb/serial/digi_acceleport.c
--- a/drivers/usb/serial/digi_acceleport.c	2005-03-23 19:58:52 -08:00
+++ b/drivers/usb/serial/digi_acceleport.c	2005-03-23 19:58:52 -08:00
@@ -246,6 +246,7 @@
 #include <linux/workqueue.h>
 #include <asm/uaccess.h>
 #include <linux/usb.h>
+#include <linux/wait.h>
 #include "usb-serial.h"
 
 /* Defines */
@@ -573,23 +574,14 @@
 	wait_queue_head_t *q, long timeout,
 	spinlock_t *lock, unsigned long flags )
 {
+	DEFINE_WAIT(wait);
 
-	wait_queue_t wait;
-
-
-	init_waitqueue_entry( &wait, current );
-
-	set_current_state( TASK_INTERRUPTIBLE );
-
-	add_wait_queue( q, &wait );
-
-	spin_unlock_irqrestore( lock, flags );
-
+	prepare_to_wait(q, &wait, TASK_UNINTERRUPTIBLE);
+	spin_unlock_irqrestore(lock, flags);
 	timeout = schedule_timeout(timeout);
+	finish_wait(q, &wait);
 
-	remove_wait_queue( q, &wait );
-
-	return( timeout );
+	return timeout;
 
 }
 
@@ -1528,7 +1520,7 @@
 
 static void digi_close( struct usb_serial_port *port, struct file *filp )
 {
-
+	DEFINE_WAIT(wait);
 	int ret;
 	unsigned char buf[32];
 	struct tty_struct *tty = port->tty;
@@ -1604,8 +1596,9 @@
 			dbg( "digi_close: write oob failed, ret=%d", ret );
 
 		/* wait for final commands on oob port to complete */
-		interruptible_sleep_on_timeout( &priv->dp_flush_wait,
-			DIGI_CLOSE_TIMEOUT );
+		prepare_to_wait(&priv->dp_flush_wait, &wait, TASK_UNINTERRUPTIBLE);
+		schedule_timeout(DIGI_CLOSE_TIMEOUT);
+		finish_wait(&priv->dp_flush_wait, &wait);
 
 		/* shutdown any outstanding bulk writes */
 		usb_kill_urb(port->write_urb);
@@ -2002,7 +1995,7 @@
 
 		} else if( opcode == DIGI_CMD_IFLUSH_FIFO ) {
 
-			wake_up_interruptible( &priv->dp_flush_wait );
+			wake_up( &priv->dp_flush_wait );
 
 		}
 
diff -Nru a/drivers/usb/serial/ftdi_sio.c b/drivers/usb/serial/ftdi_sio.c
--- a/drivers/usb/serial/ftdi_sio.c	2005-03-23 19:58:52 -08:00
+++ b/drivers/usb/serial/ftdi_sio.c	2005-03-23 19:58:52 -08:00
@@ -1187,7 +1187,7 @@
  * ***************************************************************************
  */
 
-ssize_t show_latency_timer(struct device *dev, char *buf)
+static ssize_t show_latency_timer(struct device *dev, char *buf)
 {
 	struct usb_serial_port *port = to_usb_serial_port(dev);
 	struct ftdi_private *priv = usb_get_serial_port_data(port);
@@ -1214,7 +1214,8 @@
 }
 
 /* Write a new value of the latency timer, in units of milliseconds. */
-ssize_t store_latency_timer(struct device *dev, const char *valbuf, size_t count)
+static ssize_t store_latency_timer(struct device *dev, const char *valbuf,
+				   size_t count)
 {
 	struct usb_serial_port *port = to_usb_serial_port(dev);
 	struct ftdi_private *priv = usb_get_serial_port_data(port);
@@ -1244,7 +1245,8 @@
 
 /* Write an event character directly to the FTDI register.  The ASCII
    value is in the low 8 bits, with the enable bit in the 9th bit. */
-ssize_t store_event_char(struct device *dev, const char *valbuf, size_t count)
+static ssize_t store_event_char(struct device *dev, const char *valbuf,
+				size_t count)
 {
 	struct usb_serial_port *port = to_usb_serial_port(dev);
 	struct ftdi_private *priv = usb_get_serial_port_data(port);
@@ -1275,7 +1277,7 @@
 static DEVICE_ATTR(latency_timer, S_IWUGO | S_IRUGO, show_latency_timer, store_latency_timer);
 static DEVICE_ATTR(event_char, S_IWUGO, NULL, store_event_char);
 
-void create_sysfs_attrs(struct usb_serial *serial)
+static void create_sysfs_attrs(struct usb_serial *serial)
 {	
 	struct ftdi_private *priv;
 	struct usb_device *udev;
@@ -1292,7 +1294,7 @@
 	}
 }
 
-void remove_sysfs_attrs(struct usb_serial *serial)
+static void remove_sysfs_attrs(struct usb_serial *serial)
 {
 	struct ftdi_private *priv;
 	struct usb_device *udev;
diff -Nru a/drivers/usb/serial/garmin_gps.c b/drivers/usb/serial/garmin_gps.c
--- a/drivers/usb/serial/garmin_gps.c	2005-03-23 19:58:52 -08:00
+++ b/drivers/usb/serial/garmin_gps.c	2005-03-23 19:58:52 -08:00
@@ -614,8 +614,8 @@
  *
  * return <0 on error, 0 if packet is incomplete or > 0 if packet was sent
  */
-int gsp_send(struct garmin_data * garmin_data_p, const unsigned char *buf,
-              int count)
+static int gsp_send(struct garmin_data * garmin_data_p,
+		    const unsigned char *buf, int count)
 {
 	const unsigned char *src;
 	unsigned char *dst;
diff -Nru a/drivers/usb/serial/ipw.c b/drivers/usb/serial/ipw.c
--- a/drivers/usb/serial/ipw.c	2005-03-23 19:58:52 -08:00
+++ b/drivers/usb/serial/ipw.c	2005-03-23 19:58:52 -08:00
@@ -457,7 +457,7 @@
 
 
 
-int usb_ipw_init(void)
+static int usb_ipw_init(void)
 {
 	int retval;
 
@@ -473,7 +473,7 @@
 	return 0;
 }
 
-void usb_ipw_exit(void)
+static void usb_ipw_exit(void)
 {
 	usb_deregister(&usb_ipw_driver);
 	usb_serial_deregister(&ipw_device);
diff -Nru a/drivers/usb/serial/visor.c b/drivers/usb/serial/visor.c
--- a/drivers/usb/serial/visor.c	2005-03-23 19:58:52 -08:00
+++ b/drivers/usb/serial/visor.c	2005-03-23 19:58:52 -08:00
@@ -386,6 +386,7 @@
 	int bytes_in;
 	int bytes_out;
 	int outstanding_urbs;
+	int throttled;
 };
 
 /* number of outstanding urbs to prevent userspace DoS from happening */
@@ -415,6 +416,7 @@
 	priv->bytes_in = 0;
 	priv->bytes_out = 0;
 	priv->outstanding_urbs = 0;
+	priv->throttled = 0;
 	spin_unlock_irqrestore(&priv->lock, flags);
 
 	/*
@@ -602,6 +604,7 @@
 	struct tty_struct *tty;
 	unsigned long flags;
 	int i;
+	int throttled;
 	int result;
 
 	dbg("%s - port %d", __FUNCTION__, port->number);
@@ -627,18 +630,21 @@
 	}
 	spin_lock_irqsave(&priv->lock, flags);
 	priv->bytes_in += urb->actual_length;
+	throttled = priv->throttled;
 	spin_unlock_irqrestore(&priv->lock, flags);
 
-	/* Continue trying to always read  */
-	usb_fill_bulk_urb (port->read_urb, port->serial->dev,
-			   usb_rcvbulkpipe(port->serial->dev,
-					   port->bulk_in_endpointAddress),
-			   port->read_urb->transfer_buffer,
-			   port->read_urb->transfer_buffer_length,
-			   visor_read_bulk_callback, port);
-	result = usb_submit_urb(port->read_urb, GFP_ATOMIC);
-	if (result)
-		dev_err(&port->dev, "%s - failed resubmitting read urb, error %d\n", __FUNCTION__, result);
+	/* Continue trying to always read if we should */
+	if (!throttled) {
+		usb_fill_bulk_urb (port->read_urb, port->serial->dev,
+				   usb_rcvbulkpipe(port->serial->dev,
+						   port->bulk_in_endpointAddress),
+				   port->read_urb->transfer_buffer,
+				   port->read_urb->transfer_buffer_length,
+				   visor_read_bulk_callback, port);
+		result = usb_submit_urb(port->read_urb, GFP_ATOMIC);
+		if (result)
+			dev_err(&port->dev, "%s - failed resubmitting read urb, error %d\n", __FUNCTION__, result);
+	}
 	return;
 }
 
@@ -683,16 +689,26 @@
 
 static void visor_throttle (struct usb_serial_port *port)
 {
+	struct visor_private *priv = usb_get_serial_port_data(port);
+	unsigned long flags;
+
 	dbg("%s - port %d", __FUNCTION__, port->number);
-	usb_kill_urb(port->read_urb);
+	spin_lock_irqsave(&priv->lock, flags);
+	priv->throttled = 1;
+	spin_unlock_irqrestore(&priv->lock, flags);
 }
 
 
 static void visor_unthrottle (struct usb_serial_port *port)
 {
+	struct visor_private *priv = usb_get_serial_port_data(port);
+	unsigned long flags;
 	int result;
 
 	dbg("%s - port %d", __FUNCTION__, port->number);
+	spin_lock_irqsave(&priv->lock, flags);
+	priv->throttled = 0;
+	spin_unlock_irqrestore(&priv->lock, flags);
 
 	port->read_urb->dev = port->serial->dev;
 	result = usb_submit_urb(port->read_urb, GFP_ATOMIC);
diff -Nru a/drivers/usb/storage/datafab.c b/drivers/usb/storage/datafab.c
--- a/drivers/usb/storage/datafab.c	2005-03-23 19:58:53 -08:00
+++ b/drivers/usb/storage/datafab.c	2005-03-23 19:58:53 -08:00
@@ -57,9 +57,9 @@
 #include <scsi/scsi.h>
 #include <scsi/scsi_cmnd.h>
 
+#include "usb.h"
 #include "transport.h"
 #include "protocol.h"
-#include "usb.h"
 #include "debug.h"
 #include "datafab.h"
 
diff -Nru a/drivers/usb/storage/debug.h b/drivers/usb/storage/debug.h
--- a/drivers/usb/storage/debug.h	2005-03-23 19:58:53 -08:00
+++ b/drivers/usb/storage/debug.h	2005-03-23 19:58:53 -08:00
@@ -47,8 +47,6 @@
 #include <linux/config.h>
 #include <linux/kernel.h>
 
-struct scsi_cmnd;
-
 #define USB_STORAGE "usb-storage: "
 
 #ifdef CONFIG_USB_STORAGE_DEBUG
diff -Nru a/drivers/usb/storage/dpcm.c b/drivers/usb/storage/dpcm.c
--- a/drivers/usb/storage/dpcm.c	2005-03-23 19:58:52 -08:00
+++ b/drivers/usb/storage/dpcm.c	2005-03-23 19:58:52 -08:00
@@ -34,9 +34,9 @@
 #include <scsi/scsi_cmnd.h>
 #include <scsi/scsi_device.h>
 
+#include "usb.h"
 #include "transport.h"
 #include "protocol.h"
-#include "usb.h"
 #include "debug.h"
 #include "dpcm.h"
 #include "sddr09.h"
diff -Nru a/drivers/usb/storage/freecom.c b/drivers/usb/storage/freecom.c
--- a/drivers/usb/storage/freecom.c	2005-03-23 19:58:53 -08:00
+++ b/drivers/usb/storage/freecom.c	2005-03-23 19:58:53 -08:00
@@ -34,9 +34,9 @@
 #include <scsi/scsi.h>
 #include <scsi/scsi_cmnd.h>
 
+#include "usb.h"
 #include "transport.h"
 #include "protocol.h"
-#include "usb.h"
 #include "debug.h"
 #include "freecom.h"
 
diff -Nru a/drivers/usb/storage/initializers.c b/drivers/usb/storage/initializers.c
--- a/drivers/usb/storage/initializers.c	2005-03-23 19:58:52 -08:00
+++ b/drivers/usb/storage/initializers.c	2005-03-23 19:58:52 -08:00
@@ -39,6 +39,8 @@
 
 #include <linux/sched.h>
 #include <linux/errno.h>
+
+#include "usb.h"
 #include "initializers.h"
 #include "debug.h"
 #include "transport.h"
diff -Nru a/drivers/usb/storage/isd200.c b/drivers/usb/storage/isd200.c
--- a/drivers/usb/storage/isd200.c	2005-03-23 19:58:53 -08:00
+++ b/drivers/usb/storage/isd200.c	2005-03-23 19:58:53 -08:00
@@ -54,9 +54,9 @@
 #include <scsi/scsi_cmnd.h>
 #include <scsi/scsi_device.h>
 
+#include "usb.h"
 #include "transport.h"
 #include "protocol.h"
-#include "usb.h"
 #include "debug.h"
 #include "scsiglue.h"
 #include "isd200.h"
diff -Nru a/drivers/usb/storage/jumpshot.c b/drivers/usb/storage/jumpshot.c
--- a/drivers/usb/storage/jumpshot.c	2005-03-23 19:58:52 -08:00
+++ b/drivers/usb/storage/jumpshot.c	2005-03-23 19:58:52 -08:00
@@ -54,9 +54,9 @@
 #include <scsi/scsi.h>
 #include <scsi/scsi_cmnd.h>
 
+#include "usb.h"
 #include "transport.h"
 #include "protocol.h"
-#include "usb.h"
 #include "debug.h"
 #include "jumpshot.h"
 
diff -Nru a/drivers/usb/storage/protocol.c b/drivers/usb/storage/protocol.c
--- a/drivers/usb/storage/protocol.c	2005-03-23 19:58:52 -08:00
+++ b/drivers/usb/storage/protocol.c	2005-03-23 19:58:52 -08:00
@@ -47,8 +47,9 @@
 #include <linux/highmem.h>
 #include <scsi/scsi.h>
 #include <scsi/scsi_cmnd.h>
-#include "protocol.h"
+
 #include "usb.h"
+#include "protocol.h"
 #include "debug.h"
 #include "scsiglue.h"
 #include "transport.h"
diff -Nru a/drivers/usb/storage/protocol.h b/drivers/usb/storage/protocol.h
--- a/drivers/usb/storage/protocol.h	2005-03-23 19:58:52 -08:00
+++ b/drivers/usb/storage/protocol.h	2005-03-23 19:58:52 -08:00
@@ -41,9 +41,6 @@
 #ifndef _PROTOCOL_H_
 #define _PROTOCOL_H_
 
-struct scsi_cmnd;
-struct us_data;
-
 /* Sub Classes */
 
 #define US_SC_RBC	0x01		/* Typically, flash devices */
diff -Nru a/drivers/usb/storage/scsiglue.c b/drivers/usb/storage/scsiglue.c
--- a/drivers/usb/storage/scsiglue.c	2005-03-23 19:58:52 -08:00
+++ b/drivers/usb/storage/scsiglue.c	2005-03-23 19:58:52 -08:00
@@ -53,10 +53,9 @@
 #include <scsi/scsi_devinfo.h>
 #include <scsi/scsi_device.h>
 #include <scsi/scsi_eh.h>
-#include <scsi/scsi_host.h>
 
-#include "scsiglue.h"
 #include "usb.h"
+#include "scsiglue.h"
 #include "debug.h"
 #include "transport.h"
 #include "protocol.h"
@@ -337,14 +336,13 @@
 #undef SPRINTF
 #define SPRINTF(args...) \
 	do { if (pos < buffer+length) pos += sprintf(pos, ## args); } while (0)
-#define DO_FLAG(a) \
-	do { if (us->flags & US_FL_##a) pos += sprintf(pos, " " #a); } while(0)
 
 static int proc_info (struct Scsi_Host *hostptr, char *buffer, char **start, off_t offset,
 		int length, int inout)
 {
 	struct us_data *us;
 	char *pos = buffer;
+	const char *string;
 
 	/* if someone is sending us data, just throw it away */
 	if (inout)
@@ -357,21 +355,24 @@
 
 	/* print product, vendor, and serial number strings */
 	if (us->pusb_dev->manufacturer)
-		SPRINTF("       Vendor: %s\n", us->pusb_dev->manufacturer);
+		string = us->pusb_dev->manufacturer;
 	else if (us->unusual_dev->vendorName)
-		SPRINTF("       Vendor: %s\n", us->unusual_dev->vendorName);
+		string = us->unusual_dev->vendorName;
 	else
-		SPRINTF("       Vendor: Unknown\n");
+		string = "Unknown";
+	SPRINTF("       Vendor: %s\n", string);
 	if (us->pusb_dev->product)
-		SPRINTF("      Product: %s\n", us->pusb_dev->product);
+		string = us->pusb_dev->product;
 	else if (us->unusual_dev->productName)
-		SPRINTF("      Product: %s\n", us->unusual_dev->productName);
+		string = us->unusual_dev->productName;
 	else
-		SPRINTF("      Product: Unknown\n");
+		string = "Unknown";
+	SPRINTF("      Product: %s\n", string);
 	if (us->pusb_dev->serial)
-		SPRINTF("Serial Number: %s\n", us->pusb_dev->serial);
+		string = us->pusb_dev->serial;
 	else
-		SPRINTF("Serial Number: None\n");
+		string = "None";
+	SPRINTF("Serial Number: %s\n", string);
 
 	/* show the protocol and transport */
 	SPRINTF("     Protocol: %s\n", us->protocol_name);
@@ -381,10 +382,10 @@
 	if (pos < buffer + length) {
 		pos += sprintf(pos, "       Quirks:");
 
-		DO_FLAG(SINGLE_LUN);
-		DO_FLAG(SCM_MULT_TARG);
-		DO_FLAG(FIX_INQUIRY);
-		DO_FLAG(FIX_CAPACITY);
+#define US_FLAG(name, value) \
+	if (us->flags & value) pos += sprintf(pos, " " #name);
+US_DO_ALL_FLAGS
+#undef US_FLAG
 
 		*(pos++) = '\n';
 	}
@@ -488,15 +489,6 @@
 
 	/* module management */
 	.module =			THIS_MODULE
-};
-
-/* For a device that is "Not Ready" */
-unsigned char usb_stor_sense_notready[18] = {
-	[0]	= 0x70,			    /* current error */
-	[2]	= 0x02,			    /* not ready */
-	[7]	= 0x0a,			    /* additional length */
-	[12]	= 0x04,			    /* not ready */
-	[13]	= 0x03			    /* manual intervention */
 };
 
 /* To Report "Illegal Request: Invalid Field in CDB */
diff -Nru a/drivers/usb/storage/scsiglue.h b/drivers/usb/storage/scsiglue.h
--- a/drivers/usb/storage/scsiglue.h	2005-03-23 19:58:52 -08:00
+++ b/drivers/usb/storage/scsiglue.h	2005-03-23 19:58:52 -08:00
@@ -41,14 +41,8 @@
 #ifndef _SCSIGLUE_H_
 #define _SCSIGLUE_H_
 
-#include <scsi/scsi_host.h>
-
-struct us_data;
-struct scsi_cmnd;
-
 extern void usb_stor_report_device_reset(struct us_data *us);
 
-extern unsigned char usb_stor_sense_notready[18];
 extern unsigned char usb_stor_sense_invalidCDB[18];
 extern struct scsi_host_template usb_stor_host_template;
 
diff -Nru a/drivers/usb/storage/sddr09.c b/drivers/usb/storage/sddr09.c
--- a/drivers/usb/storage/sddr09.c	2005-03-23 19:58:53 -08:00
+++ b/drivers/usb/storage/sddr09.c	2005-03-23 19:58:53 -08:00
@@ -48,9 +48,9 @@
 #include <scsi/scsi.h>
 #include <scsi/scsi_cmnd.h>
 
+#include "usb.h"
 #include "transport.h"
 #include "protocol.h"
-#include "usb.h"
 #include "debug.h"
 #include "sddr09.h"
 
diff -Nru a/drivers/usb/storage/sddr55.c b/drivers/usb/storage/sddr55.c
--- a/drivers/usb/storage/sddr55.c	2005-03-23 19:58:52 -08:00
+++ b/drivers/usb/storage/sddr55.c	2005-03-23 19:58:52 -08:00
@@ -31,9 +31,9 @@
 #include <scsi/scsi.h>
 #include <scsi/scsi_cmnd.h>
 
+#include "usb.h"
 #include "transport.h"
 #include "protocol.h"
-#include "usb.h"
 #include "debug.h"
 #include "sddr55.h"
 
diff -Nru a/drivers/usb/storage/shuttle_usbat.c b/drivers/usb/storage/shuttle_usbat.c
--- a/drivers/usb/storage/shuttle_usbat.c	2005-03-23 19:58:52 -08:00
+++ b/drivers/usb/storage/shuttle_usbat.c	2005-03-23 19:58:52 -08:00
@@ -51,9 +51,9 @@
 #include <scsi/scsi.h>
 #include <scsi/scsi_cmnd.h>
 
+#include "usb.h"
 #include "transport.h"
 #include "protocol.h"
-#include "usb.h"
 #include "debug.h"
 #include "shuttle_usbat.h"
 
@@ -61,7 +61,10 @@
 #define LSB_of(s) ((s)&0xFF)
 #define MSB_of(s) ((s)>>8)
 
-int transferred = 0;
+static int transferred = 0;
+
+static int usbat_flash_transport(struct scsi_cmnd * srb, struct us_data *us);
+static int usbat_hp8200e_transport(struct scsi_cmnd *srb, struct us_data *us);
 
 /*
  * Convenience function to produce an ATAPI read/write sectors command
@@ -872,8 +875,8 @@
 /*
  * Set the transport function based on the device type
  */
-int usbat_set_transport(struct us_data *us,
-			struct usbat_info *info)
+static int usbat_set_transport(struct us_data *us,
+			       struct usbat_info *info)
 {
 	int rc;
 
@@ -1417,7 +1420,7 @@
 /*
  * Transport for the HP 8200e
  */
-int usbat_hp8200e_transport(struct scsi_cmnd *srb, struct us_data *us)
+static int usbat_hp8200e_transport(struct scsi_cmnd *srb, struct us_data *us)
 {
 	int result;
 	unsigned char *status = us->iobuf;
@@ -1560,7 +1563,7 @@
 /*
  * Transport for USBAT02-based CompactFlash and similar storage devices
  */
-int usbat_flash_transport(struct scsi_cmnd * srb, struct us_data *us)
+static int usbat_flash_transport(struct scsi_cmnd * srb, struct us_data *us)
 {
 	int rc;
 	struct usbat_info *info = (struct usbat_info *) (us->extra);
diff -Nru a/drivers/usb/storage/shuttle_usbat.h b/drivers/usb/storage/shuttle_usbat.h
--- a/drivers/usb/storage/shuttle_usbat.h	2005-03-23 19:58:52 -08:00
+++ b/drivers/usb/storage/shuttle_usbat.h	2005-03-23 19:58:52 -08:00
@@ -105,10 +105,6 @@
 #define USBAT_FEAT_ET1	0x02
 #define USBAT_FEAT_ET2	0x01
 
-/* Transport functions */
-int usbat_hp8200e_transport(struct scsi_cmnd *srb, struct us_data *us);
-int usbat_flash_transport(struct scsi_cmnd * srb, struct us_data *us);
-
 extern int usbat_transport(struct scsi_cmnd *srb, struct us_data *us);
 extern int init_usbat(struct us_data *us);
 
diff -Nru a/drivers/usb/storage/transport.c b/drivers/usb/storage/transport.c
--- a/drivers/usb/storage/transport.c	2005-03-23 19:58:52 -08:00
+++ b/drivers/usb/storage/transport.c	2005-03-23 19:58:52 -08:00
@@ -54,10 +54,10 @@
 #include <scsi/scsi_cmnd.h>
 #include <scsi/scsi_device.h>
 
+#include "usb.h"
 #include "transport.h"
 #include "protocol.h"
 #include "scsiglue.h"
-#include "usb.h"
 #include "debug.h"
 
 
@@ -383,7 +383,8 @@
  * This routine always uses us->recv_intr_pipe as the pipe and
  * us->ep_bInterval as the interrupt interval.
  */
-int usb_stor_intr_transfer(struct us_data *us, void *buf, unsigned int length)
+static int usb_stor_intr_transfer(struct us_data *us, void *buf,
+				  unsigned int length)
 {
 	int result;
 	unsigned int pipe = us->recv_intr_pipe;
@@ -436,7 +437,7 @@
  * This function does basically the same thing as usb_stor_bulk_transfer_buf()
  * above, but it uses the usbcore scatter-gather library.
  */
-int usb_stor_bulk_transfer_sglist(struct us_data *us, unsigned int pipe,
+static int usb_stor_bulk_transfer_sglist(struct us_data *us, unsigned int pipe,
 		struct scatterlist *sg, int num_sg, unsigned int length,
 		unsigned int *act_len)
 {
diff -Nru a/drivers/usb/storage/transport.h b/drivers/usb/storage/transport.h
--- a/drivers/usb/storage/transport.h	2005-03-23 19:58:52 -08:00
+++ b/drivers/usb/storage/transport.h	2005-03-23 19:58:52 -08:00
@@ -43,9 +43,6 @@
 
 #include <linux/config.h>
 #include <linux/blkdev.h>
-#include "usb.h"
-
-struct scsi_cmnd;
 
 /* Protocols */
 
@@ -169,13 +166,8 @@
 extern int usb_stor_ctrl_transfer(struct us_data *us, unsigned int pipe,
 		u8 request, u8 requesttype, u16 value, u16 index,
 		void *data, u16 size);
-extern int usb_stor_intr_transfer(struct us_data *us, void *buf,
-		unsigned int length);
 extern int usb_stor_bulk_transfer_buf(struct us_data *us, unsigned int pipe,
 		void *buf, unsigned int length, unsigned int *act_len);
-extern int usb_stor_bulk_transfer_sglist(struct us_data *us, unsigned int pipe,
-		struct scatterlist *sg, int num_sg, unsigned int length,
-		unsigned int *act_len);
 extern int usb_stor_bulk_transfer_sg(struct us_data *us, unsigned int pipe,
 		void *buf, unsigned int length, int use_sg, int *residual);
 
diff -Nru a/drivers/usb/storage/unusual_devs.h b/drivers/usb/storage/unusual_devs.h
--- a/drivers/usb/storage/unusual_devs.h	2005-03-23 19:58:52 -08:00
+++ b/drivers/usb/storage/unusual_devs.h	2005-03-23 19:58:52 -08:00
@@ -130,6 +130,15 @@
 		US_SC_DEVICE, US_PR_DEVICE, NULL,
 		US_FL_FIX_CAPACITY),
 
+/* BENQ DC5330
+ * Reported by Manuel Fombuena <mfombuena@ya.com> and
+ * Frank Copeland <fjc@thingy.apana.org.au> */
+UNUSUAL_DEV(  0x04a5, 0x3010, 0x0100, 0x0100,
+		"Tekom Technologies, Inc",
+		"300_CAMERA",
+		US_SC_DEVICE, US_PR_DEVICE, NULL,
+		US_FL_IGNORE_RESIDUE ),
+
 /* Reported by Simon Levitt <simon@whattf.com>
  * This entry needs Sub and Proto fields */
 UNUSUAL_DEV(  0x04b8, 0x0601, 0x0100, 0x0100,
@@ -365,6 +374,13 @@
 		0 ),
 #endif
 
+/* Submitted by Olaf Hering, <olh@suse.de> SuSE Bugzilla #49049 */
+UNUSUAL_DEV(  0x054c, 0x002c, 0x0501, 0x0501,
+		"Sony",
+		"USB Floppy Drive",
+		US_SC_DEVICE, US_PR_DEVICE, NULL,
+		US_FL_SINGLE_LUN ),
+
 UNUSUAL_DEV(  0x054c, 0x002d, 0x0100, 0x0100, 
 		"Sony",
 		"Memorystick MSAC-US1",
@@ -508,6 +524,12 @@
 		US_SC_DEVICE, US_PR_DEVICE, NULL,
 		US_FL_FIX_CAPACITY ),
 
+UNUSUAL_DEV( 0x05ac, 0x1205, 0x0001, 0x0001,
+		"Apple",
+		"iPod",
+		US_SC_DEVICE, US_PR_DEVICE, NULL,
+		US_FL_FIX_CAPACITY ),
+
 #ifdef CONFIG_USB_STORAGE_JUMPSHOT
 UNUSUAL_DEV(  0x05dc, 0x0001, 0x0000, 0x0001,
 		"Lexar",
@@ -612,12 +634,6 @@
 		US_SC_SCSI, US_PR_CB, NULL,
 		US_FL_SINGLE_LUN ),
 
-UNUSUAL_DEV(  0x0781, 0x0002, 0x0009, 0x0009, 
-		"Sandisk",
-		"ImageMate SDDR-31",
-		US_SC_DEVICE, US_PR_DEVICE, NULL,
-		US_FL_IGNORE_SER ),
-
 #ifdef CONFIG_USB_STORAGE_USBAT
 UNUSUAL_DEV(  0x0781, 0x0005, 0x0005, 0x0005,
 		"Sandisk",
@@ -696,6 +712,13 @@
 		"SIIG/Datafab Memory Stick+CF Reader/Writer",
 		US_SC_SCSI, US_PR_DATAFAB, NULL,
 		0 ),
+
+/* Reported by Josef Reisinger <josef.reisinger@netcologne.de> */
+UNUSUAL_DEV( 0x07c4, 0xa002, 0x0000, 0xffff,
+		"Datafab/Unknown",
+		"MD2/MD3 Disk enclosure",
+		US_SC_SCSI, US_PR_DATAFAB, NULL,
+		US_FL_SINGLE_LUN ),
 
 UNUSUAL_DEV( 0x07c4, 0xa003, 0x0000, 0xffff,
 		"Datafab/Unknown",
diff -Nru a/drivers/usb/storage/usb.c b/drivers/usb/storage/usb.c
--- a/drivers/usb/storage/usb.c	2005-03-23 19:58:52 -08:00
+++ b/drivers/usb/storage/usb.c	2005-03-23 19:58:52 -08:00
@@ -51,6 +51,9 @@
 #include <linux/sched.h>
 #include <linux/errno.h>
 #include <linux/suspend.h>
+#include <linux/module.h>
+#include <linux/init.h>
+#include <linux/slab.h>
 
 #include <scsi/scsi.h>
 #include <scsi/scsi_cmnd.h>
@@ -89,10 +92,6 @@
 #endif
 
 
-#include <linux/module.h>
-#include <linux/init.h>
-#include <linux/slab.h>
-
 /* Some informational data */
 MODULE_AUTHOR("Matthew Dharm <mdharm-usb@one-eyed-alien.net>");
 MODULE_DESCRIPTION("USB Mass Storage driver for Linux");
@@ -225,7 +224,7 @@
 	{ NULL }
 };
 
-struct usb_driver usb_storage_driver = {
+static struct usb_driver usb_storage_driver = {
 	.owner =	THIS_MODULE,
 	.name =		"usb-storage",
 	.probe =	storage_probe,
@@ -787,7 +786,7 @@
 }
 
 /* Release all our dynamic resources */
-void usb_stor_release_resources(struct us_data *us)
+static void usb_stor_release_resources(struct us_data *us)
 {
 	US_DEBUGP("-- %s\n", __FUNCTION__);
 
@@ -830,11 +829,8 @@
 		scsi_host_put(us->host);
 
 	/* Free the extra data and the URB */
-	if (us->extra)
-		kfree(us->extra);
-	if (us->current_urb)
-		usb_free_urb(us->current_urb);
-
+	kfree(us->extra);
+	usb_free_urb(us->current_urb);
 }
 
 /* Dissociate from the USB device */
diff -Nru a/drivers/usb/storage/usb.h b/drivers/usb/storage/usb.h
--- a/drivers/usb/storage/usb.h	2005-03-23 19:58:52 -08:00
+++ b/drivers/usb/storage/usb.h	2005-03-23 19:58:52 -08:00
@@ -48,6 +48,7 @@
 #include <linux/blkdev.h>
 #include <linux/smp_lock.h>
 #include <linux/completion.h>
+#include <scsi/scsi_host.h>
 
 struct us_data;
 struct scsi_cmnd;
@@ -65,18 +66,33 @@
 	unsigned int flags;
 };
 
-/* Flag definitions: these entries are static */
-#define US_FL_SINGLE_LUN      0x00000001 /* allow access to only LUN 0	    */
-#define US_FL_MODE_XLATE      0          /* [no longer used]                */
-#define US_FL_NEED_OVERRIDE   0x00000004 /* unusual_devs entry is necessary */
-#define US_FL_IGNORE_SER      0		 /* [no longer used]		    */
-#define US_FL_SCM_MULT_TARG   0x00000020 /* supports multiple targets	    */
-#define US_FL_FIX_INQUIRY     0x00000040 /* INQUIRY response needs faking   */
-#define US_FL_FIX_CAPACITY    0x00000080 /* READ CAPACITY response too big  */
-#define US_FL_IGNORE_RESIDUE  0x00000100 /* reported residue is wrong	    */
-#define US_FL_BULK32          0x00000200 /* Uses 32-byte CBW length         */
-#define US_FL_NOT_LOCKABLE    0x00000400 /* PREVENT/ALLOW not supported     */
-#define US_FL_GO_SLOW         0x00000800 /* Need delay after Command phase  */
+/*
+ * Static flag definitions.  We use this roundabout technique so that the
+ * proc_info() routine can automatically display a message for each flag.
+ */
+#define US_DO_ALL_FLAGS						\
+	US_FLAG(SINGLE_LUN,	0x00000001)			\
+		/* allow access to only LUN 0 */		\
+	US_FLAG(NEED_OVERRIDE,	0x00000002)			\
+		/* unusual_devs entry is necessary */		\
+	US_FLAG(SCM_MULT_TARG,	0x00000004)			\
+		/* supports multiple targets */			\
+	US_FLAG(FIX_INQUIRY,	0x00000008)			\
+		/* INQUIRY response needs faking */		\
+	US_FLAG(FIX_CAPACITY,	0x00000010)			\
+		/* READ CAPACITY response too big */		\
+	US_FLAG(IGNORE_RESIDUE,	0x00000020)			\
+		/* reported residue is wrong */			\
+	US_FLAG(BULK32,		0x00000040)			\
+		/* Uses 32-byte CBW length */			\
+	US_FLAG(NOT_LOCKABLE,	0x00000080)			\
+		/* PREVENT/ALLOW not supported */		\
+	US_FLAG(GO_SLOW,	0x00000100)			\
+		/* Need delay after Command phase */		\
+
+#define US_FLAG(name, value)	US_FL_##name = value ,
+enum { US_DO_ALL_FLAGS };
+#undef US_FLAG
 
 /* Dynamic flag definitions: used in set_bit() etc. */
 #define US_FLIDX_URB_ACTIVE	18  /* 0x00040000  current_urb is in use  */
@@ -164,9 +180,6 @@
 	void			*extra;		 /* Any extra data          */
 	extra_data_destructor	extra_destructor;/* extra data destructor   */
 };
-
-/* The structure which defines our driver */
-extern struct usb_driver usb_storage_driver;
 
 /* Function to fill an inquiry response. See usb.c for details */
 extern void fill_inquiry_response(struct us_data *us,
diff -Nru a/include/linux/usb.h b/include/linux/usb.h
--- a/include/linux/usb.h	2005-03-23 19:58:52 -08:00
+++ b/include/linux/usb.h	2005-03-23 19:58:52 -08:00
@@ -949,11 +949,11 @@
 void usb_buffer_free (struct usb_device *dev, size_t size,
 	void *addr, dma_addr_t dma);
 
-struct urb *usb_buffer_map (struct urb *urb);
 #if 0
+struct urb *usb_buffer_map (struct urb *urb);
 void usb_buffer_dmasync (struct urb *urb);
-#endif
 void usb_buffer_unmap (struct urb *urb);
+#endif
 
 struct scatterlist;
 int usb_buffer_map_sg (struct usb_device *dev, unsigned pipe,
diff -Nru a/include/linux/usb_cdc.h b/include/linux/usb_cdc.h
--- a/include/linux/usb_cdc.h	2005-03-23 19:58:52 -08:00
+++ b/include/linux/usb_cdc.h	2005-03-23 19:58:52 -08:00
@@ -6,8 +6,12 @@
  * firmware based USB peripherals.
  */
 
-#define USB_CDC_SUBCLASS_ACM			2
-#define USB_CDC_SUBCLASS_ETHERNET		6
+#define USB_CDC_SUBCLASS_ACM			0x02
+#define USB_CDC_SUBCLASS_ETHERNET		0x06
+#define USB_CDC_SUBCLASS_WHCM			0x08
+#define USB_CDC_SUBCLASS_DMM			0x09
+#define USB_CDC_SUBCLASS_MDLM			0x0a
+#define USB_CDC_SUBCLASS_OBEX			0x0b
 
 #define USB_CDC_PROTO_NONE			0
 
@@ -31,6 +35,11 @@
 #define USB_CDC_UNION_TYPE		0x06		/* union_desc */
 #define USB_CDC_COUNTRY_TYPE		0x07
 #define USB_CDC_ETHERNET_TYPE		0x0f		/* ether_desc */
+#define USB_CDC_WHCM_TYPE		0x11
+#define USB_CDC_MDLM_TYPE		0x12		/* mdlm_desc */
+#define USB_CDC_MDLM_DETAIL_TYPE	0x13		/* mdlm_detail_desc */
+#define USB_CDC_DMM_TYPE		0x14
+#define USB_CDC_OBEX_TYPE		0x15
 
 /* "Header Functional Descriptor" from CDC spec  5.2.3.1 */
 struct usb_cdc_header_desc {
@@ -85,6 +94,27 @@
 	__le16	wMaxSegmentSize;
 	__le16	wNumberMCFilters;
 	__u8	bNumberPowerFilters;
+} __attribute__ ((packed));
+
+/* "MDLM Functional Descriptor" from CDC WMC spec 6.7.2.3 */
+struct usb_cdc_mdlm_desc {
+	__u8	bLength;
+	__u8	bDescriptorType;
+	__u8	bDescriptorSubType;
+
+	__le16	bcdVersion;
+	__u8	bGUID[16];
+} __attribute__ ((packed));
+
+/* "MDLM Detail Functional Descriptor" from CDC WMC spec 6.7.2.4 */
+struct usb_cdc_mdlm_detail_desc {
+	__u8	bLength;
+	__u8	bDescriptorType;
+	__u8	bDescriptorSubType;
+
+	/* type is associated with mdlm_desc.bGUID */
+	__u8	bGuidDescriptorType;
+	__u8	bDetailData[];
 } __attribute__ ((packed));
 
 /*-------------------------------------------------------------------------*/
