bk://kernel.bkbits.net/gregkh/linux/usb-2.6
phil@ipom.com[gregkh]|ChangeSet|20050325001128|11500 phil

# This is a BitKeeper generated diff -Nru style patch.
#
# ChangeSet
#   2005/03/24 16:11:28-08:00 phil@ipom.com 
#   [PATCH] USB Storage: Remove dup in unusual_devs
#   
#   Matthew Dharm pointed out that your BK tree somehow got 2 versions of an
#   unusual_devs entry in it. One was from a patch in January and the other
#   was from an automerge.
#   
#   I dug around in bk - which I find to be the most counter-intuitive
#   program in the world - and generated a patch against your latest BK
#   tree, and I've attached it. It just removes the dup.
#   
#   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/21 01:28:39-08:00 phil@ipom.com +0 -8
#   USB Storage: Remove dup in unusual_devs
# 
# ChangeSet
#   2005/03/24 16:11:11-08:00 colin@colino.net 
#   [PATCH] USB: fix harmful typos in zd1201.c
#   
#   I was looking around to see why monitor mode wouldn't work using the
#   zd1201 driver, and spotted these obvious typos.
#   
#   I think you can safely apply :)
#   
#   Signed-off-by: Colin Leroy <colin@colino.net>
#   Signed-off-by: Greg Kroah-Hartman <gregkh@suse.de>
# 
# drivers/usb/net/zd1201.c
#   2005/03/24 03:24:41-08:00 colin@colino.net +2 -2
#   USB: fix harmful typos in zd1201.c
# 
# ChangeSet
#   2005/03/24 15:31:46-08:00 david-b@pacbell.net 
#   [PATCH] USB: ehci split ISO fixes (full speed audio etc)
#   
#   This contains patches to the EHCI driver for the full speed isochronous
#   transfer support:
#   
#       - The sitd->hw_buf[1] and sitd->hw_buf_hi[1] fields were not
#         correctly initialized, affecting transfers which crossed 4K
#         boundaries.  Helps resolve some "buzz" in audio playback.
#   
#       - Correctly rounds 188-byte OUT transfers to fit into a single
#         packet ... no split transfers needed.  Resolves other "buzz" in
#         audio OUT streams.
#   
#       - Fixes a cut'n'paste error in the logic to check for microframe
#         scheduling collisions with a given transaction translator.
#         The error caused full speed iso tds to be treated in part as
#         if they were high speed iso tds, which could oops.
#   
#       - The split transaction state flag doesn't indicate an error, and
#         it should be ignored when deciding if (IN) transfers had errors.
#   
#       - Remove some code rejecting full speed iso IN transfers; it's
#         not fully working yet though.
#   
#   Plus a some minor cleanups:  reporting the iso start frame in the
#   relevant units, making a debug message more consistent.
#   
#   Signed-off-by: Karsten Wiese <annabellesgarden@yahoo.de>
#   Signed-off-by: David Brownell <dbrownell@users.sourceforge.net>
#   Signed-off-by: Greg Kroah-Hartman <gregkh@suse.de>
# 
# drivers/usb/host/ehci.h
#   2005/03/22 11:23:47-08:00 david-b@pacbell.net +1 -1
#   USB: ehci split ISO fixes (full speed audio etc)
# 
# drivers/usb/host/ehci-sched.c
#   2005/03/23 16:30:13-08:00 david-b@pacbell.net +13 -18
#   USB: ehci split ISO fixes (full speed audio etc)
# 
# ChangeSet
#   2005/03/24 15:31:29-08:00 david-b@pacbell.net 
#   [PATCH] USB: usbnet uses netif_msg_*() ethtool filtering
#   
#   This converts most of the usbnet code to actually use the ethtool
#   message flags.  The ASIX code is left untouched, since there are
#   a bunch of patches pending there ... that's where the remaining
#   handful of "sparse -Wbitwise" warnings come from.
#   
#   Signed-off-by: David Brownell <dbrownell@users.sourceforge.net>
#   Signed-off-by: Greg Kroah-Hartman <gregkh@suse.de>
# 
# drivers/usb/net/usbnet.c
#   2005/03/21 00:19:25-08:00 david-b@pacbell.net +108 -85
#   USB: usbnet uses netif_msg_*() ethtool filtering
# 
# ChangeSet
#   2005/03/24 15:31:13-08:00 david-b@pacbell.net 
#   [PATCH] USB: usbnet minor bugfixes
#   
#   Two bugfixes to usbnet.  The important one is that it's OK when the
#   minidriver doesn't want to use a status endpoint.  That shouldn't
#   be treated as an error ... errors prevent probe() from succeeding!
#   
#   The minor fix is that software driven interface shutdown should neither
#   be accounted as an error, nor generate a diagnostic.
#   
#   Signed-off-by: David Brownell <dbrownell@users.sourceforge.net>
#   Signed-off-by: Greg Kroah-Hartman <gregkh@suse.de>
# 
# drivers/usb/net/usbnet.c
#   2005/03/21 01:04:33-08:00 david-b@pacbell.net +6 -1
#   USB: usbnet minor bugfixes
# 
# ChangeSet
#   2005/03/24 15:30:57-08:00 david-b@pacbell.net 
#   [PATCH] USB: pegasus uses netif_msg_*() filters
#   
#   This updates the messaging for the pegasus driver:
#   
#     - Use driver model diagnostics or printk using the interface name
#       for all diagnostic messages ... not dbg()/warn()/err().
#   
#     - Almost everywhere, use the netif_msg_XXX() macros to check the
#       message control bitmask maintained by ethtool.  The default mask
#       is initialized using a new "message_level" module parameter.
#   
#   Also:
#   
#     - Removes the needless PEGASUS_RUNNING flag, replacing it with the
#       standard netdevice mechanism.
#   
#     - Cleaner access for unaligned values.  Not all processors spend
#       silicon to support them like x86 does.
#   
#     - Adds a few "sparse" fixes.
#   
#     - Saves the return values for the requests that manipulate chip
#       registers ... doesn't yet check them, but at least anyone looking
#       at the code (e.g. to find out why the link check task is wedged...)
#       will see where those failure modes are ignored.  Currently the
#       errors may be reported by printk, but the netif_msg_*() filters
#       make that an even worse alert mechanism.
#   
#   Signed-off-by: David Brownell <dbrownell@users.sourceforge.net>
#   Signed-off-by: Greg Kroah-Hartman <gregkh@suse.de>
# 
# drivers/usb/net/pegasus.h
#   2005/03/20 21:42:40-08:00 david-b@pacbell.net +2 -2
#   USB: pegasus uses netif_msg_*() filters
# 
# drivers/usb/net/pegasus.c
#   2005/03/21 00:19:25-08:00 david-b@pacbell.net +191 -106
#   USB: pegasus uses netif_msg_*() filters
# 
# ChangeSet
#   2005/03/24 15:30:41-08:00 david-b@pacbell.net 
#   [PATCH] USB: usb rndis gadget sparse fixes [4/5]
#   
#   This is a bunch of "sparse" fixups for the RNDIS code, saying it's
#   little-endian on the wire and swapping cpu_to_le32() calls with
#   more-correct le32_to_cpu() ones.
#   
#   Signed-off-by: David Brownell <dbrownell@users.sourceforge.net>
#   Signed-off-by: Greg Kroah-Hartman <gregkh@suse.de>
# 
# drivers/usb/gadget/rndis.h
#   2005/03/19 14:05:11-08:00 david-b@pacbell.net +81 -81
#   USB: usb rndis gadget sparse fixes [4/5]
# 
# drivers/usb/gadget/rndis.c
#   2005/03/19 14:05:11-08:00 david-b@pacbell.net +86 -83
#   USB: usb rndis gadget sparse fixes [4/5]
# 
# ChangeSet
#   2005/03/24 15:30:24-08:00 david-b@pacbell.net 
#   [PATCH] USB: gadget zero sparse fixes [5/5]
#   
#   Some "sparse" updates for the Gadget Zero driver, preparing it to
#   expect SETUP packets to be little endian.
#   
#   Signed-off-by: David Brownell <dbrownell@users.sourceforge.net>
#   Signed-off-by: Greg Kroah-Hartman <gregkh@suse.de>
# 
# drivers/usb/gadget/zero.c
#   2005/03/19 15:00:06-08:00 david-b@pacbell.net +25 -23
#   USB: gadget zero sparse fixes [5/5]
# 
# ChangeSet
#   2005/03/24 15:30:07-08:00 david-b@pacbell.net 
#   [PATCH] USB: usb gadgetfs sparse fixes [3/5]
#   
#   Many "sparse" updates for GadgetFS driver, preparing it to expect
#   SETUP packets to be little endian.
#   
#   Signed-off-by: David Brownell <dbrownell@users.sourceforge.net>
#   Signed-off-by: Greg Kroah-Hartman <gregkh@suse.de>
# 
# drivers/usb/gadget/inode.c
#   2005/03/19 15:15:46-08:00 david-b@pacbell.net +15 -14
#   USB: usb gadgetfs sparse fixes [3/5]
# 
# ChangeSet
#   2005/03/24 15:29:50-08:00 stern@rowland.harvard.edu 
#   [PATCH] USB: fix usb file_storage gadget sparse fixes [2/5]
#   
#   On Sun, 20 Mar 2005, David Brownell wrote:
#   
#   > >   - gfile-0319 ... gets rid of most byteorder warnings from the
#   > >     file_storage gadget driver (except for SETUP packet fields)
#   
#   This patch causes an undeclared variable error when verbose debugging is
#   enabled.  Please add the following on top of it.
#   
#   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/03/21 02:39:23-08:00 stern@rowland.harvard.edu +1 -1
#   USB: fix usb file_storage gadget sparse fixes [2/5]
# 
# ChangeSet
#   2005/03/24 15:29:34-08:00 david-b@pacbell.net 
#   [PATCH] USB: usb file_storage gadget sparse fixes [2/5]
#   
#   Some "sparse" updates for the File-backed Storage Gadget driver,
#   preparing it to expect SETUP packets to be little endian.
#   
#   Signed-off-by: David Brownell <dbrownell@users.sourceforge.net>
#   Signed-off-by: Greg Kroah-Hartman <gregkh@suse.de>
# 
# drivers/usb/gadget/file_storage.c
#   2005/03/19 14:05:11-08:00 david-b@pacbell.net +27 -22
#   USB: usb file_storage gadget sparse fixes [2/5]
# 
# ChangeSet
#   2005/03/24 15:29:17-08:00 david-b@pacbell.net 
#   [PATCH] USB: usb gadget misc sparse fixes [1/5]
#   
#   This lets the file_storage gadget appear again in Kconfig, and fixes
#   some minor "sparse" warnings.
#   
#   Signed-off-by: David Brownell <dbrownell@users.sourceforge.net>
#   Signed-off-by: Greg Kroah-Hartman <gregkh@suse.de>
# 
# drivers/usb/gadget/usbstring.c
#   2005/03/19 15:00:06-08:00 david-b@pacbell.net +2 -2
#   USB: usb gadget misc sparse fixes [1/5]
# 
# drivers/usb/gadget/config.c
#   2005/03/19 15:00:06-08:00 david-b@pacbell.net +1 -0
#   USB: usb gadget misc sparse fixes [1/5]
# 
# drivers/usb/gadget/Kconfig
#   2005/03/19 15:00:06-08:00 david-b@pacbell.net +0 -2
#   USB: usb gadget misc sparse fixes [1/5]
# 
# ChangeSet
#   2005/03/24 15:14:10-08:00 mdharm-usb@one-eyed-alien.net 
#   [PATCH] USB Storage: remove RW_DETECT from being a config option
#   
#   This patch started life as as454b from Alan Stern.  It has been rediffed
#   against the tip, including updates for the way unusual_devs flags are
#   defined.
#   
#   This patch removes the Kconfig option USB_STORAGE_RW_DETECT.  That option
#   was used to enable/supress the attempt to detect if a device was write
#   protected.
#   
#   It seems that the vast majority of devices properly respond to the latest
#   algorithm for making that determination.  So now we move to excluding only
#   those devices that can't handle it.  We accomplish this via the
#   unusual_devs.h list.
#   
#   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/21 00:40:36-08:00 mdharm-usb@one-eyed-alien.net +2 -0
#   USB Storage: remove RW_DETECT from being a config option
# 
# drivers/usb/storage/unusual_devs.h
#   2005/03/21 00:40:36-08:00 mdharm-usb@one-eyed-alien.net +8 -1
#   USB Storage: remove RW_DETECT from being a config option
# 
# drivers/usb/storage/scsiglue.c
#   2005/03/21 00:40:36-08:00 mdharm-usb@one-eyed-alien.net +10 -8
#   USB Storage: remove RW_DETECT from being a config option
# 
# drivers/usb/storage/Kconfig
#   2005/03/21 00:40:36-08:00 mdharm-usb@one-eyed-alien.net +0 -22
#   USB Storage: remove RW_DETECT from being a config option
# 
# ChangeSet
#   2005/03/24 15:13:53-08:00 mdharm-usb@one-eyed-alien.net 
#   [PATCH] USB Storage: combine waitqueues
#   
#   This patch started life as as476, and has been rediffed against the tip.
#   However, that was a few days ago.
#   
#   This patch combines the two separate waitqueue heads used by the
#   scsi-scanning thread and the device-reset routine into one.  After all,
#   until the scanning thread is through waiting there will be no SCSI
#   devices and hence no device resets.
#   
#   Once the scanning thread is done waiting, the waitqueue can be used by the
#   reset logic -- so even if the act of scanning produces resets, we're fine.
#   
#   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:33:16-08:00 mdharm-usb@one-eyed-alien.net +3 -5
#   USB Storage: combine waitqueues
# 
# drivers/usb/storage/usb.c
#   2005/03/13 21:33:16-08:00 mdharm-usb@one-eyed-alien.net +6 -8
#   USB Storage: combine waitqueues
# 
# drivers/usb/storage/transport.c
#   2005/03/13 21:33:16-08:00 mdharm-usb@one-eyed-alien.net +1 -1
#   USB Storage: combine waitqueues
# 
# ChangeSet
#   2005/03/24 15:13:36-08:00 mdharm-usb@one-eyed-alien.net 
#   [PATCH] USB Storage: allow disconnect to complete faster
#   
#   This patch started life as as476 from Alan Stern.  It has been rediffed
#   against the tip, tho that was a few days ago.
#   
#   This patch makes the disconnect() routine not wait for the control and
#   scanning threads to exit.  This may not seem important now, but it will
#   become important later: We would end up with a deadlock if disconnect()
#   (which is called with the device locked) was waiting for the control
#   thread to exit, while the control thread was waiting to lock the device so
#   it could do an autosuspend.
#   
#   It's necessary to make sure that the host and us_data structures aren't
#   deallocated before the control and scanning threads are through with them.
#   This is done by calling scsi_host_get and scsi_host_put at the start and
#   end of each thread, before signalling that the threads are running.  Since
#   the probe() and disconnect() routines cannot run concurrently (guaranteed
#   to us by the USB core), this method will guarantee the structures are not
#   deallocated too soon.
#   
#   While there's nothing wrong with leaving the threads alive after
#   disconnect() returns, there would be a real problem if the threads were
#   still alive when usb_stor_exit returned!  So now usb_stor_exit has to wait
#   to make sure all the threads have died.  Apparently the only safe way for
#   one thread to signal another while exiting is to use complete_and_exit,
#   which we've been doing.  So the patch adds a new driver-wide struct
#   completion, named threads_gone, and each thread signals it while exiting.
#   usb_stor_exit must call wait_for_completion the appropriate number of
#   times, and that number is stored in a new counter named total_threads.
#   
#   
#   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:33:29-08:00 mdharm-usb@one-eyed-alien.net +41 -7
#   USB Storage: allow disconnect to complete faster
# 
# ChangeSet
#   2005/03/24 15:13:20-08:00 mdharm-usb@one-eyed-alien.net 
#   [PATCH] USB Storage: exit control thread immediately upon disconnect
#   
#   This patch started life as as475 from Alan Stern.  It has been rediffed
#   against the tip, tho that was several days ago.
#   
#   This patch causes the main control thread to exit as soon as possible,
#   i.e., as soon as the DISCONNECTING flag is set.  It no longer waits for an
#   explicit exit command, one with srb == NULL.
#   
#   There won't be any bad implications for our interaction with the SCSI
#   midlayer, because once the DISCONNECTING flag is set we fail every
#   submitted command immediately in the queuecommand routine.  And if a
#   command manages to squeeze through the crack (submitted and accepted
#   before we disconnect but not yet processed), the SCSI midlayer will cancel
#   it automatically when we remove the host.
#   
#   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:33:41-08:00 mdharm-usb@one-eyed-alien.net +9 -36
#   USB Storage: exit control thread immediately upon disconnect
# 
# ChangeSet
#   2005/03/24 15:13:02-08:00 mdharm-usb@one-eyed-alien.net 
#   [PATCH] USB Storage: make usb-storage structures refcounted by SCSI
#   
#   This patch started life as as474 from Alan Stern.  It's been rediffed
#   against the tip, tho that is now several days old.
#   
#   This patch changes the way our private struct us_data is allocated; now it
#   gets stored at the end of the Scsi_Host rather than separately.  That's
#   what the hostdata field is intended for, and this is how other low-level
#   host drivers operate.  In order to convert between us_data and the
#   corresponding Scsi_Host I added two new inline routines: us_to_host and
#   host_to_us.  (The conversion actually should be quicker than before by a
#   microscopic amount, because now it only involves adding an offset whereas
#   before it involved dereferencing a pointer.)
#   
#   The main advantage is that the host is refcounted, so now our us_data
#   automatically is too.  Although that doesn't matter at the moment, it will
#   matter later on when the control thread may need to outlive the disconnect
#   callback.
#   
#   
#   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:33:54-08:00 mdharm-usb@one-eyed-alien.net +8 -1
#   USB Storage: make usb-storage structures refcounted by SCSI
# 
# drivers/usb/storage/usb.c
#   2005/03/13 21:33:54-08:00 mdharm-usb@one-eyed-alien.net +23 -32
#   USB Storage: make usb-storage structures refcounted by SCSI
# 
# drivers/usb/storage/transport.c
#   2005/03/13 21:33:54-08:00 mdharm-usb@one-eyed-alien.net +2 -2
#   USB Storage: make usb-storage structures refcounted by SCSI
# 
# drivers/usb/storage/scsiglue.c
#   2005/03/13 21:33:54-08:00 mdharm-usb@one-eyed-alien.net +24 -27
#   USB Storage: make usb-storage structures refcounted by SCSI
# 
# ChangeSet
#   2005/03/24 14:45:05-08:00 bunk@stusta.de 
#   [PATCH] drivers/usb/core/devices.c: small corrections
#   
#   total_written is used at places where it can't have any value different
#   from 0.
#   
#   This patch is partially based on findings of the Coverity checker.
#   
#   Signed-off-by: Adrian Bunk <bunk@stusta.de>
#   Signed-off-by: Greg Kroah-Hartman <gregkh@suse.de>
# 
# drivers/usb/core/devices.c
#   2005/03/22 12:15:02-08:00 bunk@stusta.de +2 -5
#   drivers/usb/core/devices.c: small corrections
# 
# ChangeSet
#   2005/03/24 14:34:40-08:00 rkagan@mail.ru 
#   [PATCH] drivers/usb/core/usb.c: add MODALIAS env var to hotplug
#   
#   The patch below adds MODALIAS environment variable to usb hotplug
#   callout, allowing for its straightforward use with modprobe.
#   
#   Signed-off-by: Roman Kagan <rkagan@mail.ru>
#   Signed-off-by: Greg Kroah-Hartman <gregkh@suse.de>
# 
# drivers/usb/core/usb.c
#   2005/03/24 14:30:58-08:00 rkagan@mail.ru +27 -0
#   drivers/usb/core/usb.c: add MODALIAS env var to hotplug
# 
# ChangeSet
#   2005/03/24 14:29:06-08:00 david-b@pacbell.net 
#   [PATCH] USB: pxa25x udc updates, mostly PM
#   
#   This has various updates to the PXA 21x/25x/26x UDC driver.
#   
#       - Implement the "new" pullup() and vbus_session() methods, and
#         use them to keep the UDC 48 MHz clock off much of the time.
#   
#   	* Reworked that ugly Lubbock VBUS IRQ code.  Claim both IRQs,
#   	  enable only one at a time; clock the UDC only when VBUS is
#   	  present.  (And get rid of rude runtime messages.)
#   
#   	* Implement driver model suspend() and resume() calls.  When
#   	  this device suspends, it clocks off the UDC.  On boards that
#   	  support it (including Zaurus clamshells, but not Lubbock)
#   	  the D+ pullup is disabled, so the host won't see the device.
#   
#       - Hmm, the "latest" errata defined some "Must Be One" bits.  OK.
#   
#       - Change the LED support for debugging.  It stopped compiling for
#         Lubbock a while back.  This switches to the standard LED calls
#         (so it can work on non-Lubbock hardware), removes the EP0 calls
#         (not very useful any more), and for Lubbock now initializes the
#         hex leds (U-Boot doesn't enable them, BLOB did).
#   
#       - "sparse" updates, and get rid of a warning that's pointless
#         unless someone's working on DMA support;
#   
#   Tested on Lubbock (VBUS sensing but no pullup) and some Zaurus
#   clamshells (pullup but no VBUS).
#   
#   Signed-off-by: David Brownell <dbrownell@users.sourceforge.net>
#   Signed-off-by: Greg Kroah-Hartman <gregkh@suse.de>
# 
# drivers/usb/gadget/pxa2xx_udc.h
#   2005/03/12 16:35:52-08:00 david-b@pacbell.net +16 -13
#   USB: pxa25x udc updates, mostly PM
# 
# drivers/usb/gadget/pxa2xx_udc.c
#   2005/03/12 16:35:52-08:00 david-b@pacbell.net +183 -96
#   USB: pxa25x udc updates, mostly PM
# 
# ChangeSet
#   2005/03/24 14:28:49-08:00 david-b@pacbell.net 
#   [PATCH] USB: ohci-omap update (mostly clock gating)
#   
#   This syncs the OMAP OHCI code with the latest from the OMAP tree.
#   The main changes are updated clock gating support (goes with some
#   clock tree updates, submitted separately) and two minor cleanups:
#   the platform device resources use physical addressing, not the
#   static i/o mapped addresses; and there's no longer a need for a
#   (noexistent in mainstream) separate header file.
#   
#   Signed-off-by: David Brownell <dbrownell@users.sourceforge.net>
#   Signed-off-by: Greg Kroah-Hartman <gregkh@suse.de>
# 
# drivers/usb/host/ohci-omap.c
#   2005/03/16 21:21:33-08:00 david-b@pacbell.net +51 -70
#   USB: ohci-omap update (mostly clock gating)
# 
# arch/arm/mach-omap/usb.c
#   2005/03/16 20:19:25-08:00 david-b@pacbell.net +2 -2
#   USB: ohci-omap update (mostly clock gating)
# 
# ChangeSet
#   2005/03/24 14:28:28-08:00 colin@colino.net 
#   [PATCH] USB: fix missing hunk in drivers/usb/Makefile
#   
#   I see there's been a driver for zd1201 added in drivers/usb/net/.
#   There's a hunk missing in drivers/usb/Makefile, the driver doesn't
#   get built in nothing else in drivers/usb/net is configured in :
#   
#   Signed-off-by: Colin Leroy <colin@colino.net>
#   Signed-off-by: Greg Kroah-Hartman <gregkh@suse.de>
# 
# drivers/usb/Makefile
#   2005/03/18 01:27:22-08:00 colin@colino.net +1 -0
#   USB: fix missing hunk in drivers/usb/Makefile
# 
# ChangeSet
#   2005/03/24 00:35:43-08:00 gregkh@suse.de 
#   USB: mark usb-serial interface GPL only
#   
#   This is done because you have to use a GPL only licensed .h file in order to write a usb-serial
#   driver.
#   
#   Signed-off-by: Greg Kroah-Hartman <gregkh@suse.de>
# 
# drivers/usb/serial/usb-serial.c
#   2005/03/24 00:35:30-08:00 gregkh@suse.de +5 -5
#   USB: mark usb-serial interface GPL only
#   
#   This is done because you have to use a GPL only licensed .h file in order to write a usb-serial
#   driver.
#   
#   Signed-off-by: Greg Kroah-Hartman <gregkh@suse.de>
# 
# ChangeSet
#   2005/03/23 20:34:15-08:00 zaitcev@redhat.com 
#   [PATCH] USB: Add myself to MAINTAINERS
#   
#   A Jan Kasprzak asked a few days ago to have a MAINTAINERS entry for ub.
#   This patch updates my entries in MAINTAINERS (ub & ymfpci).
#   
#   Signed-off-by: Pete Zaitcev <zaitcev@yahoo.com>
#   Signed-off-by: Greg Kroah-Hartman <gregkh@suse.de>
# 
# MAINTAINERS
#   2005/03/21 10:16:56-08:00 zaitcev@redhat.com +9 -2
#   USB: Add myself to MAINTAINERS
# 
# ChangeSet
#   2005/03/23 20:33:55-08:00 zaitcev@redhat.com 
#   [PATCH] USB: usbmon - document and kill pipe from API
#   
#   Someone at linux-usb-devel observed that usbmon should not leak the concept
#   of pipe to the user space. This patch makes a compromise between having
#   too many words in the line and the pipe. It breaks API, but I doubt anyone
#   has any usbmon tools in circulation at this time, so I decided not to move
#   to a different filename.
#   
#   Also, I decided to add a document which describes what is going on. I was
#   reluctant to do it because I doubt my ability to keep it synchronized and
#   updated, but there were requests to have one.
#   
#   Signed-off-by: Pete Zaitcev <zaitcev@yahoo.com>
#   Signed-off-by: Greg Kroah-Hartman <gregkh@suse.de>
# 
# Documentation/usb/usbmon.txt
#   2005/03/23 13:07:28-08:00 zaitcev@redhat.com +156 -0
#   USB: usbmon - document and kill pipe from API
# 
# drivers/usb/mon/mon_text.c
#   2005/03/18 17:22:26-08:00 zaitcev@redhat.com +12 -2
#   USB: usbmon - document and kill pipe from API
# 
# Documentation/usb/usbmon.txt
#   2005/03/23 13:07:28-08:00 zaitcev@redhat.com +0 -0
#   BitKeeper file /home/greg/linux/BK/usb-2.6/Documentation/usb/usbmon.txt
# 
# ChangeSet
#   2005/03/23 20:33:34-08:00 zaitcev@redhat.com 
#   [PATCH] USB: Fix baud selection in mct_u232
#   
#   This is a patch by Hansjoerg Lipp to fix coding error in divisor calculation.
#   
#   Signed-off-by: Pete Zaitcev <zaitcev@yahoo.com>
#   Signed-off-by: Greg Kroah-Hartman <gregkh@suse.de>
# 
# drivers/usb/serial/mct_u232.c
#   2005/03/23 08:26:12-08:00 zaitcev@redhat.com +11 -11
#   USB: Fix baud selection in mct_u232
# 
# ChangeSet
#   2005/03/23 20:33:13-08:00 zaitcev@redhat.com 
#   [PATCH] USB: ub static patch
#   
#   I'm pretty sure this comes from Bunk originally, but I didn't keep the
#   original, so only one signed-off-by is present.
#   
#   Signed-off-by: Pete Zaitcev <zaitcev@yahoo.com>
#   Signed-off-by: Greg Kroah-Hartman <gregkh@suse.de>
# 
# drivers/block/ub.c
#   2005/03/18 17:31:40-08:00 zaitcev@redhat.com +1 -1
#   USB: ub static 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/Documentation/usb/usbmon.txt b/Documentation/usb/usbmon.txt
--- /dev/null	Wed Dec 31 16:00:00 196900
+++ b/Documentation/usb/usbmon.txt	2005-03-24 18:21:08 -08:00
@@ -0,0 +1,156 @@
+* Introduction
+
+The name "usbmon" in lowercase refers to a facility in kernel which is
+used to collect traces of I/O on the USB bus. This function is analogous
+to a packet socket used by network monitoring tools such as tcpdump(1)
+or Ethereal. Similarly, it is expected that a tool such as usbdump or
+USBMon (with uppercase letters) is used to examine raw traces produced
+by usbmon.
+
+The usbmon reports requests made by peripheral-specific drivers to Host
+Controller Drivers (HCD). So, if HCD is buggy, the traces reported by
+usbmon may not correspond to bus transactions precisely. This is the same
+situation as with tcpdump.
+
+* How to use usbmon to collect raw text traces
+
+Unlike the packet socket, usbmon has an interface which provides traces
+in a text format. This is used for two purposes. First, it serves as a
+common trace exchange format for tools while most sophisticated formats
+are finalized. Second, humans can read it in case tools are not available.
+
+To collect a raw text trace, execute following steps.
+
+1. Prepare
+
+Mount debugfs (it has to be enabled in your kernel configuration), and
+load the usbmon module (if built as module). The second step is skipped
+if usbmon is built into the kernel.
+
+# mount -t debugfs none_debugs /sys/kernel/debug
+# modprobe usbmon
+
+Verify that bus sockets are present.
+
+[root@lembas zaitcev]# ls /sys/kernel/debug/usbmon
+1s  1t  2s  2t  3s  3t  4s  4t
+[root@lembas zaitcev]#
+
+# ls /sys/kernel
+
+2. Find which bus connects to the desired device
+
+Run "cat /proc/bus/usb/devices", and find the T-line which corresponds to
+the device. Usually you do it by looking for the vendor string. If you have
+many similar devices, unplug one and compare two /proc/bus/usb/devices outputs.
+The T-line will have a bus number. Example:
+
+T:  Bus=03 Lev=01 Prnt=01 Port=00 Cnt=01 Dev#=  2 Spd=12  MxCh= 0
+D:  Ver= 1.10 Cls=00(>ifc ) Sub=00 Prot=00 MxPS= 8 #Cfgs=  1
+P:  Vendor=0557 ProdID=2004 Rev= 1.00
+S:  Manufacturer=ATEN
+S:  Product=UC100KM V2.00
+
+Bus=03 means it's bus 3.
+
+3. Start 'cat'
+
+# cat /sys/kernel/debug/usbmon/3t > /tmp/1.mon.out
+
+This process will be reading until killed. Naturally, the output can be
+redirected to a desirable location. This is preferred, because it is going
+to be quite long.
+
+4. Perform the desired operation on the USB bus
+
+This is where you do something that creates the traffic: plug in a flash key,
+copy files, control a webcam, etc.
+
+5. Kill cat
+
+Usually it's done with a keyboard interrupt (Control-C).
+
+At this point the output file (/tmp/1.mon.out in this example) can be saved,
+sent by e-mail, or inspected with a text editor. In the last case make sure
+that the file size is not excessive for your favourite editor.
+
+* Raw text data format
+
+The '0t' type data consists of a stream of events, such as URB submission,
+URB callback, submission error. Every event is a text line, which consists
+of whitespace separated words. The number of position of words may depend
+on the event type, but there is a set of words, common for all types.
+
+Here is the list of words, from left to right:
+- URB Tag. This is used to identify URBs is normally a kernel mode address
+ of the URB structure in hexadecimal.
+- Timestamp in microseconds, a decimal number. The timestamp's resolution
+  depends on available clock, and so it can be much worse than a microsecond
+  (if the implementation uses jiffies, for example).
+- Event Type. This type refers to the format of the event, not URB type.
+  Available types are: S - submission, C - callback, E - submission error.
+- "Pipe". The pipe concept is deprecated. This is a composite word, used to
+  be derived from information in pipes. It consists of three fields, separated
+  by colons: URB type and direction, Device address, Endpoint number.
+  Type and direction are encoded with two bytes in the following manner:
+    Ci Co   Control input and output
+    Zi Zo   Isochronous input and output
+    Ii Io   Interrupt input and output
+    Bi Bo   Bulk input and output
+  Device address and Endpoint number are decimal numbers with leading zeroes
+  or 3 and 2 positions, correspondingly.
+- URB Status. This field makes no sense for submissions, but is present
+  to help scripts with parsing. In error case, it contains the error code.
+- Data Length. This is the actual length in the URB.
+- Data tag. The usbmon may not always capture data, even if length is nonzero.
+  Only if tag is '=', the data words are present.
+- Data words follow, in big endian hexadecimal format. Notice that they are
+  not machine words, but really just a byte stream split into words to make
+  it easier to read. Thus, the last word may contain from one to four bytes.
+  The length of collected data is limited and can be less than the data length
+  report in Data Length word.
+
+Here is an example of code to read the data stream in a well known programming
+language:
+
+class ParsedLine {
+	int data_len;		/* Available length of data */
+	byte data[];
+
+	void parseData(StringTokenizer st) {
+		int availwords = st.countTokens();
+		data = new byte[availwords * 4];
+		data_len = 0;
+		while (st.hasMoreTokens()) {
+			String data_str = st.nextToken();
+			int len = data_str.length() / 2;
+			int i;
+			for (i = 0; i < len; i++) {
+				data[data_len] = Byte.parseByte(
+				    data_str.substring(i*2, i*2 + 2),
+				    16);
+				data_len++;
+			}
+		}
+	}
+}
+
+This format is obviously deficient. For example, the setup packet for control
+transfers is not delivered. This will change in the future.
+
+Examples:
+
+An input control transfer to get a port status:
+
+d74ff9a0 2640288196 S Ci:001:00 -115 4 <
+d74ff9a0 2640288202 C Ci:001:00 0 4 = 01010100
+
+An output bulk transfer to send a SCSI command 0x5E in a 31-byte Bulk wrapper
+to a storage device at address 5:
+
+dd65f0e8 4128379752 S Bo:005:02 -115 31 = 55534243 5e000000 00000000 00000600 00000000 00000000 00000000 000000
+dd65f0e8 4128379808 C Bo:005:02 0 31 >
+
+* Raw binary format and API
+
+TBD
diff -Nru a/MAINTAINERS b/MAINTAINERS
--- a/MAINTAINERS	2005-03-24 18:21:08 -08:00
+++ b/MAINTAINERS	2005-03-24 18:21:08 -08:00
@@ -2313,6 +2313,13 @@
 L:	linux-usb-devel@lists.sourceforge.net
 S:	Maintained
 
+USB BLOCK DRIVER (UB ub)
+P:	Pete Zaitcev
+M:	zaitcev@redhat.com
+L:	linux-kernel@vger.kernel.org
+L:	linux-usb-devel@lists.sourceforge.net
+S:	Supported
+
 USB BLUETOOTH TTY CONVERTER DRIVER
 P:	Greg Kroah-Hartman
 M:	greg@kroah.com
@@ -2661,11 +2668,11 @@
 L:	linux-hams@vger.kernel.org
 S:	Maintained
 
-YMFPCI YAMAHA PCI SOUND
+YMFPCI YAMAHA PCI SOUND (Use ALSA instead)
 P:	Pete Zaitcev
 M:	zaitcev@yahoo.com
 L:	linux-kernel@vger.kernel.org
-S:	Maintained
+S:	Obsolete
 
 Z8530 DRIVER FOR AX.25
 P:	Joerg Reuter
diff -Nru a/arch/arm/mach-omap/usb.c b/arch/arm/mach-omap/usb.c
--- a/arch/arm/mach-omap/usb.c	2005-03-24 18:21:08 -08:00
+++ b/arch/arm/mach-omap/usb.c	2005-03-24 18:21:08 -08:00
@@ -322,8 +322,8 @@
 
 static struct resource ohci_resources[] = {
 	{
-		.start	= IO_ADDRESS(OMAP_OHCI_BASE),
-		.end	= IO_ADDRESS(OMAP_OHCI_BASE + 4096),
+		.start	= OMAP_OHCI_BASE,
+		.end	= OMAP_OHCI_BASE + 4096,
 		.flags	= IORESOURCE_MEM,
 	},
 	{
diff -Nru a/drivers/block/ub.c b/drivers/block/ub.c
--- a/drivers/block/ub.c	2005-03-24 18:21:08 -08:00
+++ b/drivers/block/ub.c	2005-03-24 18:21:08 -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.
@@ -2145,7 +2144,7 @@
 	spin_unlock_irqrestore(&ub_lock, flags);
 }
 
-struct usb_driver ub_driver = {
+static struct usb_driver ub_driver = {
 	.owner =	THIS_MODULE,
 	.name =		"ub",
 	.probe =	ub_probe,
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-24 18:21:08 -08:00
+++ b/drivers/media/video/cpia_usb.c	2005-03-24 18:21:08 -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-24 18:21:08 -08:00
+++ b/drivers/usb/Makefile	2005-03-24 18:21:08 -08:00
@@ -50,8 +50,8 @@
 obj-$(CONFIG_USB_PEGASUS)	+= net/
 obj-$(CONFIG_USB_RTL8150)	+= net/
 obj-$(CONFIG_USB_USBNET)	+= net/
+obj-$(CONFIG_USB_ZD1201)	+= 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-24 18:21:08 -08:00
+++ b/drivers/usb/class/usb-midi.c	2005-03-24 18:21:08 -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-24 18:21:08 -08:00
+++ b/drivers/usb/core/buffer.c	2005-03-24 18:21:08 -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-24 18:21:08 -08:00
+++ b/drivers/usb/core/config.c	2005-03-24 18:21:08 -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/devices.c b/drivers/usb/core/devices.c
--- a/drivers/usb/core/devices.c	2005-03-24 18:21:08 -08:00
+++ b/drivers/usb/core/devices.c	2005-03-24 18:21:08 -08:00
@@ -460,7 +460,7 @@
 		return 0;
 	
 	if (level > MAX_TOPO_LEVEL)
-		return total_written;
+		return 0;
 	/* allocate 2^1 pages = 8K (on i386); should be more than enough for one device */
         if (!(pages_start = (char*) __get_free_pages(GFP_KERNEL,1)))
                 return -ENOMEM;
@@ -527,10 +527,7 @@
 			length = *nbytes;
 		if (copy_to_user(*buffer, pages_start + *skip_bytes, length)) {
 			free_pages((unsigned long)pages_start, 1);
-			
-			if (total_written == 0)
-				return -EFAULT;
-			return total_written;
+			return -EFAULT;
 		}
 		*nbytes -= length;
 		*file_offset += length;
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-24 18:21:08 -08:00
+++ b/drivers/usb/core/hcd-pci.c	2005-03-24 18:21:08 -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-24 18:21:08 -08:00
+++ b/drivers/usb/core/hcd.c	2005-03-24 18:21:08 -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-24 18:21:08 -08:00
+++ b/drivers/usb/core/hcd.h	2005-03-24 18:21:08 -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-24 18:21:08 -08:00
+++ b/drivers/usb/core/hub.c	2005-03-24 18:21:08 -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-24 18:21:08 -08:00
+++ b/drivers/usb/core/hub.h	2005-03-24 18:21:08 -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-24 18:21:08 -08:00
+++ b/drivers/usb/core/message.c	2005-03-24 18:21:08 -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-24 18:21:08 -08:00
+++ b/drivers/usb/core/usb.c	2005-03-24 18:21:08 -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);
@@ -615,6 +615,33 @@
 					alt->desc.bInterfaceSubClass,
 					alt->desc.bInterfaceProtocol))
 			return -ENOMEM;
+
+		if (add_hotplug_env_var(envp, num_envp, &i,
+					buffer, buffer_size, &length,
+					"MODALIAS=usb:v%04Xp%04Xdl%04Xdh%04Xdc%02Xdsc%02Xdp%02Xic%02Xisc%02Xip%02X",
+					le16_to_cpu(usb_dev->descriptor.idVendor),
+					le16_to_cpu(usb_dev->descriptor.idProduct),
+					le16_to_cpu(usb_dev->descriptor.bcdDevice),
+					le16_to_cpu(usb_dev->descriptor.bcdDevice),
+					usb_dev->descriptor.bDeviceClass,
+					usb_dev->descriptor.bDeviceSubClass,
+					usb_dev->descriptor.bDeviceProtocol,
+					alt->desc.bInterfaceClass,
+					alt->desc.bInterfaceSubClass,
+					alt->desc.bInterfaceProtocol))
+			return -ENOMEM;
+ 	} else {
+		if (add_hotplug_env_var(envp, num_envp, &i,
+					buffer, buffer_size, &length,
+					"MODALIAS=usb:v%04Xp%04Xdl%04Xdh%04Xdc%02Xdsc%02Xdp%02Xic*isc*ip*",
+					le16_to_cpu(usb_dev->descriptor.idVendor),
+					le16_to_cpu(usb_dev->descriptor.idProduct),
+					le16_to_cpu(usb_dev->descriptor.bcdDevice),
+					le16_to_cpu(usb_dev->descriptor.bcdDevice),
+					usb_dev->descriptor.bDeviceClass,
+					usb_dev->descriptor.bDeviceSubClass,
+					usb_dev->descriptor.bDeviceProtocol))
+			return -ENOMEM;
 	}
 
 	envp[i] = NULL;
@@ -1148,6 +1175,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 +1205,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 +1250,7 @@
  *
  * Reverses the effect of usb_buffer_map().
  */
+#if 0
 void usb_buffer_unmap (struct urb *urb)
 {
 	struct usb_bus		*bus;
@@ -1247,6 +1277,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 +1558,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-24 18:21:08 -08:00
+++ b/drivers/usb/core/usb.h	2005-03-24 18:21:08 -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-24 18:21:08 -08:00
+++ b/drivers/usb/gadget/Kconfig	2005-03-24 18:21:08 -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
@@ -222,6 +179,38 @@
 
 	   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
 
 config USB_GADGET_DUALSPEED
@@ -355,8 +344,6 @@
 
 config USB_FILE_STORAGE
 	tristate "File-backed Storage Gadget"
-	# we don't support the SA1100 because of its limitations
-	depends on USB_GADGET_SA1100 = n
 	help
 	  The File-backed Storage Gadget acts as a USB Mass Storage
 	  disk drive.  As its storage repository it can use a regular
diff -Nru a/drivers/usb/gadget/config.c b/drivers/usb/gadget/config.c
--- a/drivers/usb/gadget/config.c	2005-03-24 18:21:08 -08:00
+++ b/drivers/usb/gadget/config.c	2005-03-24 18:21:08 -08:00
@@ -25,6 +25,7 @@
 #include <linux/device.h>
 
 #include <linux/usb_ch9.h>
+#include <linux/usb_gadget.h>
 
 
 /**
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-24 18:21:08 -08:00
+++ b/drivers/usb/gadget/dummy_hcd.c	2005-03-24 18:21:08 -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-24 18:21:08 -08:00
+++ b/drivers/usb/gadget/ether.c	2005-03-24 18:21:08 -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-24 18:21:08 -08:00
+++ b/drivers/usb/gadget/file_storage.c	2005-03-24 18:21:08 -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"},
 	{}
 };
 
@@ -1270,6 +1276,8 @@
 {
 	struct usb_request	*req = fsg->ep0req;
 	int			value = -EOPNOTSUPP;
+	u16			w_index = ctrl->wIndex;
+	u16			w_length = ctrl->wLength;
 
 	if (!fsg->config)
 		return value;
@@ -1282,7 +1290,7 @@
 			if (ctrl->bRequestType != (USB_DIR_OUT |
 					USB_TYPE_CLASS | USB_RECIP_INTERFACE))
 				break;
-			if (ctrl->wIndex != 0) {
+			if (w_index != 0) {
 				value = -EDOM;
 				break;
 			}
@@ -1298,13 +1306,13 @@
 			if (ctrl->bRequestType != (USB_DIR_IN |
 					USB_TYPE_CLASS | USB_RECIP_INTERFACE))
 				break;
-			if (ctrl->wIndex != 0) {
+			if (w_index != 0) {
 				value = -EDOM;
 				break;
 			}
 			VDBG(fsg, "get max LUN\n");
 			*(u8 *) req->buf = fsg->nluns - 1;
-			value = min(ctrl->wLength, (u16) 1);
+			value = min(w_length, (u16) 1);
 			break;
 		}
 	}
@@ -1317,15 +1325,15 @@
 			if (ctrl->bRequestType != (USB_DIR_OUT |
 					USB_TYPE_CLASS | USB_RECIP_INTERFACE))
 				break;
-			if (ctrl->wIndex != 0) {
+			if (w_index != 0) {
 				value = -EDOM;
 				break;
 			}
-			if (ctrl->wLength > MAX_COMMAND_SIZE) {
+			if (w_length > MAX_COMMAND_SIZE) {
 				value = -EOVERFLOW;
 				break;
 			}
-			value = ctrl->wLength;
+			value = w_length;
 			fsg->ep0req->context = received_cbi_adsc;
 			break;
 		}
@@ -1336,7 +1344,7 @@
 			"unknown class-specific control req "
 			"%02x.%02x v%04x i%04x l%u\n",
 			ctrl->bRequestType, ctrl->bRequest,
-			ctrl->wValue, ctrl->wIndex, ctrl->wLength);
+			ctrl->wValue, w_index, w_length);
 	return value;
 }
 
@@ -1350,6 +1358,9 @@
 {
 	struct usb_request	*req = fsg->ep0req;
 	int			value = -EOPNOTSUPP;
+	u16			w_index = ctrl->wIndex;
+	u16			w_value = ctrl->wValue;
+	u16			w_length = ctrl->wLength;
 
 	/* Usually this just stores reply data in the pre-allocated ep0 buffer,
 	 * but config change events will also reconfigure hardware. */
@@ -1359,11 +1370,11 @@
 		if (ctrl->bRequestType != (USB_DIR_IN | USB_TYPE_STANDARD |
 				USB_RECIP_DEVICE))
 			break;
-		switch (ctrl->wValue >> 8) {
+		switch (w_value >> 8) {
 
 		case USB_DT_DEVICE:
 			VDBG(fsg, "get device descriptor\n");
-			value = min(ctrl->wLength, (u16) sizeof device_desc);
+			value = min(w_length, (u16) sizeof device_desc);
 			memcpy(req->buf, &device_desc, value);
 			break;
 #ifdef CONFIG_USB_GADGET_DUALSPEED
@@ -1371,7 +1382,7 @@
 			VDBG(fsg, "get device qualifier\n");
 			if (!fsg->gadget->is_dualspeed)
 				break;
-			value = min(ctrl->wLength, (u16) sizeof dev_qualifier);
+			value = min(w_length, (u16) sizeof dev_qualifier);
 			memcpy(req->buf, &dev_qualifier, value);
 			break;
 
@@ -1388,10 +1399,10 @@
 #endif
 			value = populate_config_buf(fsg->gadget,
 					req->buf,
-					ctrl->wValue >> 8,
-					ctrl->wValue & 0xff);
+					w_value >> 8,
+					w_value & 0xff);
 			if (value >= 0)
-				value = min(ctrl->wLength, (u16) value);
+				value = min(w_length, (u16) value);
 			break;
 
 		case USB_DT_STRING:
@@ -1399,9 +1410,9 @@
 
 			/* wIndex == language code */
 			value = usb_gadget_get_string(&stringtab,
-					ctrl->wValue & 0xff, req->buf);
+					w_value & 0xff, req->buf);
 			if (value >= 0)
-				value = min(ctrl->wLength, (u16) value);
+				value = min(w_length, (u16) value);
 			break;
 		}
 		break;
@@ -1412,8 +1423,8 @@
 				USB_RECIP_DEVICE))
 			break;
 		VDBG(fsg, "set configuration\n");
-		if (ctrl->wValue == CONFIG_VALUE || ctrl->wValue == 0) {
-			fsg->new_config = ctrl->wValue;
+		if (w_value == CONFIG_VALUE || w_value == 0) {
+			fsg->new_config = w_value;
 
 			/* Raise an exception to wipe out previous transaction
 			 * state (queued bufs, etc) and set the new config. */
@@ -1427,14 +1438,14 @@
 			break;
 		VDBG(fsg, "get configuration\n");
 		*(u8 *) req->buf = fsg->config;
-		value = min(ctrl->wLength, (u16) 1);
+		value = min(w_length, (u16) 1);
 		break;
 
 	case USB_REQ_SET_INTERFACE:
 		if (ctrl->bRequestType != (USB_DIR_OUT| USB_TYPE_STANDARD |
 				USB_RECIP_INTERFACE))
 			break;
-		if (fsg->config && ctrl->wIndex == 0) {
+		if (fsg->config && w_index == 0) {
 
 			/* Raise an exception to wipe out previous transaction
 			 * state (queued bufs, etc) and install the new
@@ -1449,20 +1460,20 @@
 			break;
 		if (!fsg->config)
 			break;
-		if (ctrl->wIndex != 0) {
+		if (w_index != 0) {
 			value = -EDOM;
 			break;
 		}
 		VDBG(fsg, "get interface\n");
 		*(u8 *) req->buf = 0;
-		value = min(ctrl->wLength, (u16) 1);
+		value = min(w_length, (u16) 1);
 		break;
 
 	default:
 		VDBG(fsg,
 			"unknown control req %02x.%02x v%04x i%04x l%u\n",
 			ctrl->bRequestType, ctrl->bRequest,
-			ctrl->wValue, ctrl->wIndex, ctrl->wLength);
+			w_value, w_index, w_length);
 	}
 
 	return value;
@@ -3740,6 +3751,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-24 18:21:08 -08:00
+++ b/drivers/usb/gadget/gadget_chips.h	2005-03-24 18:21:08 -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/inode.c b/drivers/usb/gadget/inode.c
--- a/drivers/usb/gadget/inode.c	2005-03-24 18:21:08 -08:00
+++ b/drivers/usb/gadget/inode.c	2005-03-24 18:21:08 -08:00
@@ -1318,6 +1318,8 @@
 	struct usb_request		*req = dev->req;
 	int				value = -EOPNOTSUPP;
 	struct usb_gadgetfs_event	*event;
+	u16				w_value = ctrl->wValue;
+	u16				w_length = ctrl->wLength;
 
 	spin_lock (&dev->lock);
 	dev->setup_abort = 0;
@@ -1378,17 +1380,17 @@
 	case USB_REQ_GET_DESCRIPTOR:
 		if (ctrl->bRequestType != USB_DIR_IN)
 			goto unrecognized;
-		switch (ctrl->wValue >> 8) {
+		switch (w_value >> 8) {
 
 		case USB_DT_DEVICE:
-			value = min (ctrl->wLength, (u16) sizeof *dev->dev);
+			value = min (w_length, (u16) sizeof *dev->dev);
 			req->buf = dev->dev;
 			break;
 #ifdef	HIGHSPEED
 		case USB_DT_DEVICE_QUALIFIER:
 			if (!dev->hs_config)
 				break;
-			value = min (ctrl->wLength, (u16)
+			value = min (w_length, (u16)
 				sizeof (struct usb_qualifier_descriptor));
 			make_qualifier (dev);
 			break;
@@ -1397,10 +1399,10 @@
 #endif
 		case USB_DT_CONFIG:
 			value = config_buf (dev,
-					ctrl->wValue >> 8,
-					ctrl->wValue & 0xff);
+					w_value >> 8,
+					w_value & 0xff);
 			if (value >= 0)
-				value = min (ctrl->wLength, (u16) value);
+				value = min (w_length, (u16) value);
 			break;
 		case USB_DT_STRING:
 			goto unrecognized;
@@ -1414,7 +1416,7 @@
 	case USB_REQ_SET_CONFIGURATION:
 		if (ctrl->bRequestType != 0)
 			break;
-		if (0 == (u8) ctrl->wValue) {
+		if (0 == (u8) w_value) {
 			value = 0;
 			dev->current_config = 0;
 			usb_gadget_vbus_draw(gadget, 8 /* mA */ );
@@ -1432,7 +1434,7 @@
 				power = dev->config->bMaxPower;
 			}
 
-			if (config == (u8) ctrl->wValue) {
+			if (config == (u8) w_value) {
 				value = 0;
 				dev->current_config = config;
 				usb_gadget_vbus_draw(gadget, 2 * power);
@@ -1463,7 +1465,7 @@
 		if (ctrl->bRequestType != 0x80)
 			break;
 		*(u8 *)req->buf = dev->current_config;
-		value = min (ctrl->wLength, (u16) 1);
+		value = min (w_length, (u16) 1);
 		break;
 #endif
 
@@ -1472,7 +1474,7 @@
 		VDEBUG (dev, "%s req%02x.%02x v%04x i%04x l%d\n",
 			dev->usermode_setup ? "delegate" : "fail",
 			ctrl->bRequestType, ctrl->bRequest,
-			ctrl->wValue, ctrl->wIndex, ctrl->wLength);
+			w_value, le16_to_cpu(ctrl->wIndex), w_length);
 
 		/* if there's an ep0 reader, don't stall */
 		if (dev->usermode_setup) {
@@ -1485,9 +1487,9 @@
 			value = 0;
 
 			/* read DATA stage for OUT right away */
-			if (unlikely (!dev->setup_in && ctrl->wLength)) {
+			if (unlikely (!dev->setup_in && w_length)) {
 				value = setup_req (gadget->ep0, dev->req,
-							ctrl->wLength);
+							w_length);
 				if (value < 0)
 					break;
 				value = usb_ep_queue (gadget->ep0, dev->req,
@@ -1513,8 +1515,7 @@
 	/* proceed with data transfer and status phases? */
 	if (value >= 0 && dev->state != STATE_SETUP) {
 		req->length = value;
-		req->zero = value < ctrl->wLength
-				&& (value % gadget->ep0->maxpacket) == 0;
+		req->zero = value < w_length;
 		value = usb_ep_queue (gadget->ep0, req, GFP_ATOMIC);
 		if (value < 0) {
 			DBG (dev, "ep_queue --> %d\n", value);
diff -Nru a/drivers/usb/gadget/net2280.c b/drivers/usb/gadget/net2280.c
--- a/drivers/usb/gadget/net2280.c	2005-03-24 18:21:08 -08:00
+++ b/drivers/usb/gadget/net2280.c	2005-03-24 18:21:08 -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/pxa2xx_udc.c b/drivers/usb/gadget/pxa2xx_udc.c
--- a/drivers/usb/gadget/pxa2xx_udc.c	2005-03-24 18:21:08 -08:00
+++ b/drivers/usb/gadget/pxa2xx_udc.c	2005-03-24 18:21:08 -08:00
@@ -310,7 +310,7 @@
 	/* flush fifo (mostly for IN buffers) */
 	pxa2xx_ep_fifo_flush (_ep);
 
-	ep->desc = 0;
+	ep->desc = NULL;
 	ep->stopped = 1;
 
 	DBG(DBG_VERBOSE, "%s disabled\n", _ep->name);
@@ -334,7 +334,7 @@
 
 	req = kmalloc (sizeof *req, gfp_flags);
 	if (!req)
-		return 0;
+		return NULL;
 
 	memset (req, 0, sizeof *req);
 	INIT_LIST_HEAD (&req->queue);
@@ -369,7 +369,11 @@
 
 	retval = kmalloc (bytes, gfp_flags & ~(__GFP_DMA|__GFP_HIGHMEM));
 	if (retval)
+#ifdef	USE_DMA
 		*dma = virt_to_bus (retval);
+#else
+		*dma = (dma_addr_t)~0;
+#endif
 	return retval;
 }
 
@@ -411,7 +415,6 @@
 static inline void ep0_idle (struct pxa2xx_udc *dev)
 {
 	dev->ep0state = EP0_IDLE;
-	LED_EP0_OFF;
 }
 
 static int
@@ -930,7 +933,7 @@
 			case EP0_IN_DATA_PHASE:
 				dev->stats.write.ops++;
 				if (write_ep0_fifo(ep, req))
-					req = 0;
+					req = NULL;
 				break;
 
 			case EP0_OUT_DATA_PHASE:
@@ -940,7 +943,8 @@
 					DBG(DBG_VERBOSE, "ep0 config ack%s\n",
 						dev->has_cfr ?  "" : " raced");
 					if (dev->has_cfr)
-						UDCCFR = UDCCFR_AREN|UDCCFR_ACM;
+						UDCCFR = UDCCFR_AREN|UDCCFR_ACM
+							|UDCCFR_MB1;
 					done(ep, req, 0);
 					dev->ep0state = EP0_END_XFER;
 					local_irq_restore (flags);
@@ -952,7 +956,7 @@
 						&& read_ep0_fifo(ep, req))) {
 					ep0_idle(dev);
 					done(ep, req, 0);
-					req = 0;
+					req = NULL;
 				}
 				break;
 
@@ -970,10 +974,10 @@
 		} else if ((ep->bEndpointAddress & USB_DIR_IN) != 0
 				&& (*ep->reg_udccs & UDCCS_BI_TFS) != 0
 				&& write_fifo(ep, req)) {
-			req = 0;
+			req = NULL;
 		} else if ((*ep->reg_udccs & UDCCS_BO_RFS) != 0
 				&& read_fifo(ep, req)) {
-			req = 0;
+			req = NULL;
 		}
 
 		if (likely (req && ep->desc) && ep->dma < 0)
@@ -1094,7 +1098,6 @@
 		start_watchdog(ep->dev);
 		ep->dev->req_pending = 0;
 		ep->dev->ep0state = EP0_STALL;
-		LED_EP0_OFF;
 
  	/* and bulk/intr endpoints like dropping stalls too */
  	} else {
@@ -1194,13 +1197,71 @@
 	return 0;
 }
 
+static void stop_activity(struct pxa2xx_udc *, struct usb_gadget_driver *);
+static void udc_enable (struct pxa2xx_udc *);
+static void udc_disable(struct pxa2xx_udc *);
+
+/* We disable the UDC -- and its 48 MHz clock -- whenever it's not
+ * in active use.  
+ */
+static int pullup(struct pxa2xx_udc *udc, int is_active)
+{
+	is_active = is_active && udc->vbus && udc->pullup;
+	DMSG("%s\n", is_active ? "active" : "inactive");
+	if (is_active)
+		udc_enable(udc);
+	else {
+		if (udc->gadget.speed != USB_SPEED_UNKNOWN) {
+			DMSG("disconnect %s\n", udc->driver
+				? udc->driver->driver.name
+				: "(no driver)");
+			stop_activity(udc, udc->driver);
+		}
+		udc_disable(udc);
+	}
+	return 0;
+}
+
+/* VBUS reporting logically comes from a transceiver */
+static int pxa2xx_udc_vbus_session(struct usb_gadget *_gadget, int is_active)
+{
+	struct pxa2xx_udc	*udc;
+
+	udc = container_of(_gadget, struct pxa2xx_udc, gadget);
+	udc->vbus = is_active = (is_active != 0);
+	DMSG("vbus %s\n", is_active ? "supplied" : "inactive");
+	pullup(udc, is_active);
+	return 0;
+}
+
+/* drivers may have software control over D+ pullup */
+static int pxa2xx_udc_pullup(struct usb_gadget *_gadget, int is_active)
+{
+	struct pxa2xx_udc	*udc;
+
+	udc = container_of(_gadget, struct pxa2xx_udc, gadget);
+
+	/* not all boards support pullup control */
+	if (!udc->mach->udc_command)
+		return -EOPNOTSUPP;
+
+	is_active = (is_active != 0);
+	udc->pullup = is_active;
+	pullup(udc, is_active);
+	return 0;
+}
+
 static const struct usb_gadget_ops pxa2xx_udc_ops = {
-	.get_frame	 = pxa2xx_udc_get_frame,
-	.wakeup		 = pxa2xx_udc_wakeup,
-	// current versions must always be self-powered
+	.get_frame	= pxa2xx_udc_get_frame,
+	.wakeup		= pxa2xx_udc_wakeup,
+	.vbus_session	= pxa2xx_udc_vbus_session,
+	.pullup		= pxa2xx_udc_pullup,
+
+	// .vbus_draw ... boards may consume current from VBUS, up to
+	// 100-500mA based on config.  the 500uA suspend ceiling means
+	// that exclusively vbus-powered PXA designs violate USB specs.
 };
 
-
 /*-------------------------------------------------------------------------*/
 
 #ifdef CONFIG_USB_GADGET_DEBUG_FILES
@@ -1427,7 +1488,7 @@
 		if (i != 0)
 			list_add_tail (&ep->ep.ep_list, &dev->gadget.ep_list);
 
-		ep->desc = 0;
+		ep->desc = NULL;
 		ep->stopped = 0;
 		INIT_LIST_HEAD (&ep->queue);
 		ep->pio_irqs = ep->dma_irqs = 0;
@@ -1446,6 +1507,7 @@
 #ifdef	CONFIG_ARCH_PXA
         /* Enable clock for USB device */
 	pxa_set_cken(CKEN11_USB, 1);
+	udelay(5);
 #endif
 
 	/* try to clear these bits before we enable the udc */
@@ -1469,7 +1531,7 @@
 		/* pxa255 (a0+) can avoid a set_config race that could
 		 * prevent gadget drivers from configuring correctly
 		 */
-		UDCCFR = UDCCFR_ACM;
+		UDCCFR = UDCCFR_ACM | UDCCFR_MB1;
 	} else {
 		/* "USB test mode" for pxa250 errata 40-42 (stepping a0, a1)
 		 * which could result in missing packets and interrupts.
@@ -1498,18 +1560,13 @@
 	}
 #endif
 
-	/* caller must be able to sleep in order to cope
-	 * with startup transients.
-	 */
-	msleep(100);
-
 	/* enable suspend/resume and reset irqs */
 	udc_clear_mask_UDCCR(UDCCR_SRM | UDCCR_REM);
 
 	/* enable ep0 irqs */
 	UICR0 &= ~UICR0_IM0;
 
-	/* if hardware supports it, connect to usb and wait for host */
+	/* if hardware supports it, pullup D+ and wait for reset */
 	let_usb_appear();
 }
 
@@ -1540,6 +1597,7 @@
 	/* first hook up the driver ... */
 	dev->driver = driver;
 	dev->gadget.dev.driver = &driver->driver;
+	dev->pullup = 1;
 
 	device_add (&dev->gadget.dev);
 	retval = driver->bind(&dev->gadget);
@@ -1548,18 +1606,17 @@
 				driver->driver.name, retval);
 		device_del (&dev->gadget.dev);
 
-		dev->driver = 0;
-		dev->gadget.dev.driver = 0;
+		dev->driver = NULL;
+		dev->gadget.dev.driver = NULL;
 		return retval;
 	}
 	device_create_file(dev->dev, &dev_attr_function);
 
 	/* ... then enable host detection and ep0; and we're ready
 	 * for set_configuration as well as eventual disconnect.
-	 * NOTE:  this shouldn't power up until later.
 	 */
 	DMSG("registered gadget driver '%s'\n", driver->driver.name);
-	udc_enable(dev);
+	pullup(dev, 1);
 	dump_state(dev);
 	return 0;
 }
@@ -1572,7 +1629,7 @@
 
 	/* don't disconnect drivers more than once */
 	if (dev->gadget.speed == USB_SPEED_UNKNOWN)
-		driver = 0;
+		driver = NULL;
 	dev->gadget.speed = USB_SPEED_UNKNOWN;
 
 	/* prevent new request submissions, kill any outstanding requests  */
@@ -1603,12 +1660,12 @@
 		return -EINVAL;
 
 	local_irq_disable();
-	udc_disable(dev);
+	pullup(dev, 0);
 	stop_activity(dev, driver);
 	local_irq_enable();
 
 	driver->unbind(&dev->gadget);
-	dev->driver = 0;
+	dev->driver = NULL;
 
 	device_del (&dev->gadget.dev);
 	device_remove_file(dev->dev, &dev_attr_function);
@@ -1624,61 +1681,41 @@
 
 #ifdef CONFIG_ARCH_LUBBOCK
 
-/* Lubbock can report connect or disconnect irqs.  Likely more hardware
- * could support it as a timer callback.
- *
- * FIXME for better power management, keep the hardware powered down
- * until a host is powering the link.  means scheduling work later
- * in some task that can udc_enable().
+/* Lubbock has separate connect and disconnect irqs.  More typical designs
+ * use one GPIO as the VBUS IRQ, and another to control the D+ pullup.
  */
 
-#define	enable_disconnect_irq() \
-	if (machine_is_lubbock()) { enable_irq(LUBBOCK_USB_DISC_IRQ); }
-#define	disable_disconnect_irq() \
-	if (machine_is_lubbock()) { disable_irq(LUBBOCK_USB_DISC_IRQ); }
-
 static irqreturn_t
-usb_connection_irq(int irq, void *_dev, struct pt_regs *r)
+lubbock_vbus_irq(int irq, void *_dev, struct pt_regs *r)
 {
 	struct pxa2xx_udc	*dev = _dev;
+	int			vbus;
 
 	dev->stats.irqs++;
 	HEX_DISPLAY(dev->stats.irqs);
-
-	if (!is_usb_connected()) {
-		LED_CONNECTED_OFF;
-		disable_disconnect_irq();
-		/* report disconnect just once */
-		if (dev->gadget.speed != USB_SPEED_UNKNOWN) {
-			DMSG("disconnect %s\n",
-				dev->driver ? dev->driver->driver.name : 0);
-			stop_activity(dev, dev->driver);
-
-			// udc_disable (dev);
-			// no more udc irqs
-			// maybe "ACTION=disconnect /sbin/hotplug gadget".
-		}
-	} else if (dev->gadget.speed == USB_SPEED_UNKNOWN) {
+	switch (irq) {
+	case LUBBOCK_USB_IRQ:
 		LED_CONNECTED_ON;
-
-		DMSG("?? connect irq ??\n");
-
-		// if there's no driver bound, ignore; else
-		// udc_enable (dev);
-		// UDC irqs drive the rest.
-		// maybe "ACTION=connect /sbin/hotplug gadget".
+		vbus = 1;
+		disable_irq(LUBBOCK_USB_IRQ);
+		enable_irq(LUBBOCK_USB_DISC_IRQ);
+		break;
+	case LUBBOCK_USB_DISC_IRQ:
+		LED_CONNECTED_OFF;
+		vbus = 0;
+		disable_irq(LUBBOCK_USB_DISC_IRQ);
+		enable_irq(LUBBOCK_USB_IRQ);
+		break;
+	default:
+		return IRQ_NONE;
 	}
+
+	pxa2xx_udc_vbus_session(&dev->gadget, vbus);
 	return IRQ_HANDLED;
 }
 
 #endif
 
-#ifndef	enable_disconnect_irq
-#warning USB disconnect() is not yet reported.
-#define	enable_disconnect_irq()		do {} while (0)
-#define	disable_disconnect_irq()	do {} while (0)
-#endif
-
 
 /*-------------------------------------------------------------------------*/
 
@@ -1720,7 +1757,7 @@
 	} u;
 
 	if (list_empty(&ep->queue))
-		req = 0;
+		req = NULL;
 	else
 		req = list_entry(ep->queue.next, struct pxa2xx_request, queue);
 
@@ -1764,14 +1801,11 @@
 				goto bad_setup;
 
 got_setup:
-			le16_to_cpus (&u.r.wValue);
-			le16_to_cpus (&u.r.wIndex);
-			le16_to_cpus (&u.r.wLength);
-
-			LED_EP0_ON;
 			DBG(DBG_VERBOSE, "SETUP %02x.%02x v%04x i%04x l%04x\n",
 				u.r.bRequestType, u.r.bRequest,
-				u.r.wValue, u.r.wIndex, u.r.wLength);
+				le16_to_cpu(u.r.wValue),
+				le16_to_cpu(u.r.wIndex),
+				le16_to_cpu(u.r.wLength));
 
 			/* cope with automagic for some standard requests. */
 			dev->req_std = (u.r.bRequestType & USB_TYPE_MASK)
@@ -1803,7 +1837,8 @@
 					 *  - ep reset doesn't include halt(?).
 					 */
 					DMSG("broken set_interface (%d/%d)\n",
-						u.r.wIndex, u.r.wValue);
+						le16_to_cpu(u.r.wIndex),
+						le16_to_cpu(u.r.wValue));
 					goto config_change;
 				}
 				break;
@@ -1847,7 +1882,6 @@
 				ep0start(dev, UDCCS0_FST|UDCCS0_FTF, "stall");
 				start_watchdog(dev);
 				dev->ep0state = EP0_STALL;
-				LED_EP0_OFF;
 
 			/* deferred i/o == no response yet */
 			} else if (dev->req_pending) {
@@ -1948,7 +1982,7 @@
 			req = list_entry(ep->queue.next,
 					struct pxa2xx_request, queue);
 		else
-			req = 0;
+			req = NULL;
 
 		// TODO check FST handling
 
@@ -2050,8 +2084,6 @@
 
 			if ((UDCCR & UDCCR_UDA) == 0) {
 				DBG(DBG_VERBOSE, "USB reset start\n");
-				if (dev->gadget.speed != USB_SPEED_UNKNOWN)
-					disable_disconnect_irq();
 
 				/* reset driver and endpoints,
 				 * in case that's not yet done
@@ -2059,12 +2091,11 @@
 				stop_activity (dev, dev->driver);
 
 			} else {
-				INFO("USB reset\n");
+				DBG(DBG_VERBOSE, "USB reset end\n");
 				dev->gadget.speed = USB_SPEED_FULL;
 				LED_CONNECTED_ON;
 				memset(&dev->stats, 0, sizeof dev->stats);
 				/* driver and endpoints are still reset */
-				enable_disconnect_irq();
 			}
 
 		} else {
@@ -2478,6 +2509,8 @@
 	udc_disable(dev);
 	udc_reinit(dev);
 
+	dev->vbus = is_usb_connected();
+
 	/* irq setup after old hardware state is cleaned up */
 	retval = request_irq(IRQ_USB, pxa2xx_udc_irq,
 			SA_INTERRUPT, driver_name, dev);
@@ -2490,18 +2523,32 @@
 
 #ifdef CONFIG_ARCH_LUBBOCK
 	if (machine_is_lubbock()) {
-		disable_irq(LUBBOCK_USB_DISC_IRQ);
 		retval = request_irq(LUBBOCK_USB_DISC_IRQ,
-				usb_connection_irq,
-				SA_INTERRUPT /* OOPSING | SA_SAMPLE_RANDOM */,
+				lubbock_vbus_irq,
+				SA_INTERRUPT | SA_SAMPLE_RANDOM,
 				driver_name, dev);
 		if (retval != 0) {
-			enable_irq(LUBBOCK_USB_DISC_IRQ);
 			printk(KERN_ERR "%s: can't get irq %i, err %d\n",
 				driver_name, LUBBOCK_USB_DISC_IRQ, retval);
+lubbock_fail0:
+			free_irq(IRQ_USB, dev);
 			return -EBUSY;
 		}
-		dev->got_disc = 1;
+		retval = request_irq(LUBBOCK_USB_IRQ,
+				lubbock_vbus_irq,
+				SA_INTERRUPT | SA_SAMPLE_RANDOM,
+				driver_name, dev);
+		if (retval != 0) {
+			printk(KERN_ERR "%s: can't get irq %i, err %d\n",
+				driver_name, LUBBOCK_USB_IRQ, retval);
+			free_irq(LUBBOCK_USB_DISC_IRQ, dev);
+			goto lubbock_fail0;
+		}
+#ifdef DEBUG
+		/* with U-Boot (but not BLOB), hex is off by default */
+		HEX_DISPLAY(dev->stats.irqs);
+		LUB_DISC_BLNK_LED &= 0xff;
+#endif
 	}
 #endif
 	create_proc_files();
@@ -2510,7 +2557,7 @@
 }
 static int __exit pxa2xx_udc_remove(struct device *_dev)
 {
-	struct pxa2xx_udc *dev = _dev->driver_data;
+	struct pxa2xx_udc *dev = dev_get_drvdata(_dev);
 
 	udc_disable(dev);
 	remove_proc_files();
@@ -2520,26 +2567,66 @@
 		free_irq(IRQ_USB, dev);
 		dev->got_irq = 0;
 	}
-	if (machine_is_lubbock() && dev->got_disc) {
+	if (machine_is_lubbock()) {
 		free_irq(LUBBOCK_USB_DISC_IRQ, dev);
-		dev->got_disc = 0;
+		free_irq(LUBBOCK_USB_IRQ, dev);
 	}
-	dev_set_drvdata(_dev, 0);
-	the_controller = 0;
+	dev_set_drvdata(_dev, NULL);
+	the_controller = NULL;
 	return 0;
 }
 
 /*-------------------------------------------------------------------------*/
 
+#ifdef	CONFIG_PM
+
+/* USB suspend (controlled by the host) and system suspend (controlled
+ * by the PXA) don't necessarily work well together.  If USB is active,
+ * the 48 MHz clock is required; so the system can't enter 33 MHz idle
+ * mode, or any deeper PM saving state.
+ *
+ * For now, we punt and forcibly disconnect from the USB host when PXA
+ * enters any suspend state.  While we're disconnected, we always disable
+ * the 48MHz USB clock ... allowing PXA sleep and/or 33 MHz idle states. 
+ * Boards without software pullup control shouldn't use those states.
+ * VBUS IRQs should probably be ignored so that the PXA device just acts
+ * "dead" to USB hosts until system resume.
+ */
+static int pxa2xx_udc_suspend(struct device *dev, u32 state, u32 level)
+{
+	struct pxa2xx_udc	*udc = dev_get_drvdata(dev);
+
+	if (level == SUSPEND_POWER_DOWN) {
+		if (!udc->mach->udc_command)
+			WARN("USB host won't detect disconnect!\n");
+		pullup(udc, 0);
+	}
+	return 0;
+}
+
+static int pxa2xx_udc_resume(struct device *dev, u32 level)
+{
+	struct pxa2xx_udc	*udc = dev_get_drvdata(dev);
+
+	if (level == RESUME_POWER_ON)
+		pullup(udc, 1);
+	return 0;
+}
+
+#else
+#define	pxa2xx_udc_suspend	NULL
+#define	pxa2xx_udc_resume	NULL
+#endif
+
+/*-------------------------------------------------------------------------*/
+
 static struct device_driver udc_driver = {
 	.name		= "pxa2xx-udc",
 	.bus		= &platform_bus_type,
 	.probe		= pxa2xx_udc_probe,
 	.remove		= __exit_p(pxa2xx_udc_remove),
-
-	// FIXME power management support
-	// .suspend = ... disable UDC
-	// .resume = ... re-enable UDC
+	.suspend	= pxa2xx_udc_suspend,
+	.resume		= pxa2xx_udc_resume,
 };
 
 static int __init udc_init(void)
diff -Nru a/drivers/usb/gadget/pxa2xx_udc.h b/drivers/usb/gadget/pxa2xx_udc.h
--- a/drivers/usb/gadget/pxa2xx_udc.h	2005-03-24 18:21:08 -08:00
+++ b/drivers/usb/gadget/pxa2xx_udc.h	2005-03-24 18:21:08 -08:00
@@ -40,6 +40,9 @@
 #define UDCCFR_AREN	(1 << 7)	/* ACK response enable (now) */
 #define UDCCFR_ACM	(1 << 2)	/* ACK control mode (wait for AREN) */
 
+/* latest pxa255 errata define new "must be one" bits in UDCCFR */
+#define	UDCCFR_MB1	(0xff & ~(UDCCFR_AREN|UDCCFR_ACM))
+
 /*-------------------------------------------------------------------------*/
 
 struct pxa2xx_udc;
@@ -120,7 +123,8 @@
 	enum ep0_state				ep0state;
 	struct udc_stats			stats;
 	unsigned				got_irq : 1,
-						got_disc : 1,
+						vbus : 1,
+						pullup : 1,
 						has_cfr : 1,
 						req_pending : 1,
 						req_std : 1,
@@ -143,14 +147,7 @@
 
 #ifdef DEBUG
 #define HEX_DISPLAY(n)	if (machine_is_lubbock()) { LUB_HEXLED = (n); }
-
-#define LED_CONNECTED_ON	if (machine_is_lubbock()) { \
-	DISCRETE_LED_ON(D26); }
-#define LED_CONNECTED_OFF	if(machine_is_lubbock()) { \
-	DISCRETE_LED_OFF(D26); LUB_HEXLED = 0; }
-#define LED_EP0_ON	if (machine_is_lubbock()) { DISCRETE_LED_ON(D25); }
-#define LED_EP0_OFF	if (machine_is_lubbock()) { DISCRETE_LED_OFF(D25); }
-#endif /* DEBUG */
+#endif
 
 #endif
 
@@ -161,13 +158,19 @@
 #define HEX_DISPLAY(n)		do {} while(0)
 #endif
 
+#ifdef DEBUG
+#include <asm/leds.h>
+
+#define LED_CONNECTED_ON	leds_event(led_green_on)
+#define LED_CONNECTED_OFF	do { \
+					leds_event(led_green_off); \
+					HEX_DISPLAY(0); \
+				} while(0)
+#endif
+
 #ifndef LED_CONNECTED_ON
 #define LED_CONNECTED_ON	do {} while(0)
 #define LED_CONNECTED_OFF	do {} while(0)
-#endif
-#ifndef LED_EP0_ON
-#define LED_EP0_ON		do {} while (0)
-#define LED_EP0_OFF		do {} while (0)
 #endif
 
 /*-------------------------------------------------------------------------*/
diff -Nru a/drivers/usb/gadget/rndis.c b/drivers/usb/gadget/rndis.c
--- a/drivers/usb/gadget/rndis.c	2005-03-24 18:21:08 -08:00
+++ b/drivers/usb/gadget/rndis.c	2005-03-24 18:21:08 -08:00
@@ -74,7 +74,7 @@
 static rndis_params rndis_per_dev_params [RNDIS_MAX_CONFIGS];
 
 /* Driver Version */
-static const u32 rndis_driver_version = __constant_cpu_to_le32 (1);
+static const __le32 rndis_driver_version = __constant_cpu_to_le32 (1);
 
 /* Function Prototypes */
 static int rndis_init_response (int configNr, rndis_init_msg_type *buf);
@@ -92,7 +92,7 @@
 {
 	int 			retval = -ENOTSUPP;
 	u32 			length = 0;
-	u32			*tmp;
+	__le32			*tmp;
 	int			i, count;
 	rndis_query_cmplt_type	*resp;
 
@@ -110,7 +110,7 @@
 		DEBUG ("%s: OID_GEN_SUPPORTED_LIST\n", __FUNCTION__);
 		length = sizeof (oid_supported_list);
 		count  = length / sizeof (u32);
-		tmp = (u32 *) ((u8 *)resp + 24);
+		tmp = (__le32 *) ((u8 *)resp + 24);
 		for (i = 0; i < count; i++)
 			tmp[i] = cpu_to_le32 (oid_supported_list[i]);
 		retval = 0;
@@ -126,7 +126,7 @@
 		 * reddite ergo quae sunt Caesaris Caesari
 		 * et quae sunt Dei Deo!
 		 */
-		*((u32 *) resp + 6) = __constant_cpu_to_le32 (0);
+		*((__le32 *) resp + 6) = __constant_cpu_to_le32 (0);
 		retval = 0;
 		break;
 		
@@ -134,7 +134,7 @@
 	case OID_GEN_MEDIA_SUPPORTED:
 		DEBUG("%s: OID_GEN_MEDIA_SUPPORTED\n", __FUNCTION__);
 		length = 4;
-		*((u32 *) resp + 6) = cpu_to_le32 (
+		*((__le32 *) resp + 6) = cpu_to_le32 (
 					rndis_per_dev_params [configNr].medium);
 		retval = 0;
 		break;
@@ -144,7 +144,7 @@
 		DEBUG("%s: OID_GEN_MEDIA_IN_USE\n", __FUNCTION__);
 		length = 4;
 		/* one medium, one transport... (maybe you do it better) */
-		*((u32 *) resp + 6) = cpu_to_le32 (
+		*((__le32 *) resp + 6) = cpu_to_le32 (
 					rndis_per_dev_params [configNr].medium);
 		retval = 0;
 		break;
@@ -154,11 +154,11 @@
 		DEBUG("%s: OID_GEN_MAXIMUM_FRAME_SIZE\n", __FUNCTION__);
 		if (rndis_per_dev_params [configNr].dev) {
 			length = 4;
-			*((u32 *) resp + 6) = cpu_to_le32 (
+			*((__le32 *) resp + 6) = cpu_to_le32 (
 				rndis_per_dev_params [configNr].dev->mtu);
 			retval = 0;
 		} else {
-			*((u32 *) resp + 6) = __constant_cpu_to_le32 (0);
+			*((__le32 *) resp + 6) = __constant_cpu_to_le32 (0);
 			retval = 0;
 		}
 		break;
@@ -169,9 +169,9 @@
 		length = 4;
 		if (rndis_per_dev_params [configNr].media_state
 			== NDIS_MEDIA_STATE_DISCONNECTED)
-		    *((u32 *) resp + 6) = __constant_cpu_to_le32 (0);
+		    *((__le32 *) resp + 6) = __constant_cpu_to_le32 (0);
 		else
-		    *((u32 *) resp + 6) = cpu_to_le32 (
+		    *((__le32 *) resp + 6) = cpu_to_le32 (
 				rndis_per_dev_params [configNr].speed);
 		retval = 0;
 		break;
@@ -181,7 +181,7 @@
 		DEBUG("%s: OID_GEN_TRANSMIT_BLOCK_SIZE\n", __FUNCTION__);
 		if (rndis_per_dev_params [configNr].dev) {
 			length = 4;
-			*((u32 *) resp + 6) = cpu_to_le32 (
+			*((__le32 *) resp + 6) = cpu_to_le32 (
 				rndis_per_dev_params [configNr].dev->mtu);
 			retval = 0;
 		}
@@ -192,7 +192,7 @@
 		DEBUG("%s: OID_GEN_RECEIVE_BLOCK_SIZE\n", __FUNCTION__);
 		if (rndis_per_dev_params [configNr].dev) {
 			length = 4;
-			*((u32 *) resp + 6) = cpu_to_le32 (
+			*((__le32 *) resp + 6) = cpu_to_le32 (
 				rndis_per_dev_params [configNr].dev->mtu);
 			retval = 0;
 		}
@@ -202,7 +202,7 @@
 	case OID_GEN_VENDOR_ID:
 		DEBUG("%s: OID_GEN_VENDOR_ID\n", __FUNCTION__);
 		length = 4;
-		*((u32 *) resp + 6) = cpu_to_le32 (
+		*((__le32 *) resp + 6) = cpu_to_le32 (
 			rndis_per_dev_params [configNr].vendorID);
 		retval = 0;
 		break;
@@ -220,7 +220,7 @@
 		DEBUG("%s: OID_GEN_VENDOR_DRIVER_VERSION\n", __FUNCTION__);
 		length = 4;
 		/* Created as LE */
-		*((u32 *) resp + 6) = rndis_driver_version;
+		*((__le32 *) resp + 6) = rndis_driver_version;
 		retval = 0;
 		break;
 
@@ -228,7 +228,7 @@
 	case OID_GEN_CURRENT_PACKET_FILTER:
 		DEBUG("%s: OID_GEN_CURRENT_PACKET_FILTER\n", __FUNCTION__);
 		length = 4;
-		*((u32 *) resp + 6) = cpu_to_le32 (
+		*((__le32 *) resp + 6) = cpu_to_le32 (
 					rndis_per_dev_params[configNr].filter);
 		retval = 0;
 		break;
@@ -237,7 +237,7 @@
 	case OID_GEN_MAXIMUM_TOTAL_SIZE:
 		DEBUG("%s: OID_GEN_MAXIMUM_TOTAL_SIZE\n", __FUNCTION__);
 		length = 4;
-		*((u32 *) resp + 6) = __constant_cpu_to_le32(
+		*((__le32 *) resp + 6) = __constant_cpu_to_le32(
 					RNDIS_MAX_TOTAL_SIZE);
 		retval = 0;
 		break;
@@ -246,7 +246,7 @@
 	case OID_GEN_MEDIA_CONNECT_STATUS:
 		DEBUG("%s: OID_GEN_MEDIA_CONNECT_STATUS\n", __FUNCTION__);
 		length = 4;
-		*((u32 *) resp + 6) = cpu_to_le32 (
+		*((__le32 *) resp + 6) = cpu_to_le32 (
 					rndis_per_dev_params [configNr]
 						.media_state);
 		retval = 0;
@@ -255,7 +255,7 @@
 	case OID_GEN_PHYSICAL_MEDIUM:
 		DEBUG("%s: OID_GEN_PHYSICAL_MEDIUM\n", __FUNCTION__);
 		length = 4;
-		*((u32 *) resp + 6) = __constant_cpu_to_le32 (0);
+		*((__le32 *) resp + 6) = __constant_cpu_to_le32 (0);
 		retval = 0;
 		break;
 
@@ -266,7 +266,7 @@
 	case OID_GEN_MAC_OPTIONS:		/* from WinME */
 		DEBUG("%s: OID_GEN_MAC_OPTIONS\n", __FUNCTION__);
 		length = 4;
-		*((u32 *) resp + 6) = __constant_cpu_to_le32(
+		*((__le32 *) resp + 6) = __constant_cpu_to_le32(
 			  NDIS_MAC_OPTION_RECEIVE_SERIALIZED
 			| NDIS_MAC_OPTION_FULL_DUPLEX);
 		retval = 0;
@@ -279,13 +279,13 @@
 		DEBUG("%s: OID_GEN_XMIT_OK\n", __FUNCTION__);
 		if (rndis_per_dev_params [configNr].stats) {
 			length = 4;
-			*((u32 *) resp + 6) = cpu_to_le32 (
+			*((__le32 *) resp + 6) = cpu_to_le32 (
 			    rndis_per_dev_params [configNr].stats->tx_packets - 
 			    rndis_per_dev_params [configNr].stats->tx_errors -
 			    rndis_per_dev_params [configNr].stats->tx_dropped);
 			retval = 0;
 		} else {
-			*((u32 *) resp + 6) = __constant_cpu_to_le32 (0);
+			*((__le32 *) resp + 6) = __constant_cpu_to_le32 (0);
 			retval = 0;
 		}
 		break;
@@ -295,13 +295,13 @@
 		DEBUG("%s: OID_GEN_RCV_OK\n", __FUNCTION__);
 		if (rndis_per_dev_params [configNr].stats) {
 			length = 4;
-			*((u32 *) resp + 6) = cpu_to_le32 (
+			*((__le32 *) resp + 6) = cpu_to_le32 (
 			    rndis_per_dev_params [configNr].stats->rx_packets - 
 			    rndis_per_dev_params [configNr].stats->rx_errors -
 			    rndis_per_dev_params [configNr].stats->rx_dropped);
 			retval = 0;
 		} else {
-			*((u32 *) resp + 6) = __constant_cpu_to_le32 (0);
+			*((__le32 *) resp + 6) = __constant_cpu_to_le32 (0);
 			retval = 0;
 		}
 		break;
@@ -311,12 +311,12 @@
 		DEBUG("%s: OID_GEN_XMIT_ERROR\n", __FUNCTION__);
 		if (rndis_per_dev_params [configNr].stats) {
 			length = 4;
-			*((u32 *) resp + 6) = cpu_to_le32 (
+			*((__le32 *) resp + 6) = cpu_to_le32 (
 				rndis_per_dev_params [configNr]
 					.stats->tx_errors);
 			retval = 0;
 		} else {
-			*((u32 *) resp + 6) = __constant_cpu_to_le32 (0);
+			*((__le32 *) resp + 6) = __constant_cpu_to_le32 (0);
 			retval = 0;
 		}
 		break;
@@ -325,12 +325,12 @@
 	case OID_GEN_RCV_ERROR:
 		DEBUG("%s: OID_GEN_RCV_ERROR\n", __FUNCTION__);
 		if (rndis_per_dev_params [configNr].stats) {
-			*((u32 *) resp + 6) = cpu_to_le32 (
+			*((__le32 *) resp + 6) = cpu_to_le32 (
 				rndis_per_dev_params [configNr]
 					.stats->rx_errors);
 			retval = 0;
 		} else {
-			*((u32 *) resp + 6) = __constant_cpu_to_le32 (0);
+			*((__le32 *) resp + 6) = __constant_cpu_to_le32 (0);
 			retval = 0;
 		}
 		break;
@@ -339,12 +339,12 @@
 	case OID_GEN_RCV_NO_BUFFER:
 		DEBUG("%s: OID_GEN_RCV_NO_BUFFER\n", __FUNCTION__);
 		if (rndis_per_dev_params [configNr].stats) {
-			*((u32 *) resp + 6) = cpu_to_le32 (
+			*((__le32 *) resp + 6) = cpu_to_le32 (
 				rndis_per_dev_params [configNr]
 					.stats->rx_dropped);
 			retval = 0;
 		} else {
-			*((u32 *) resp + 6) = __constant_cpu_to_le32 (0);
+			*((__le32 *) resp + 6) = __constant_cpu_to_le32 (0);
 			retval = 0;
 		}
 		break;
@@ -359,7 +359,7 @@
 		 */
 		if (rndis_per_dev_params [configNr].stats) {
 			length = 4;
-			*((u32 *) resp + 6) = cpu_to_le32 (
+			*((__le32 *) resp + 6) = cpu_to_le32 (
 				(rndis_per_dev_params [configNr]
 					.stats->tx_packets - 
 				 rndis_per_dev_params [configNr]
@@ -369,7 +369,7 @@
 				* 123);
 			retval = 0;
 		} else {
-			*((u32 *) resp + 6) = __constant_cpu_to_le32 (0);
+			*((__le32 *) resp + 6) = __constant_cpu_to_le32 (0);
 			retval = 0;
 		}
 		break;
@@ -379,7 +379,7 @@
 		/* dito */
 		if (rndis_per_dev_params [configNr].stats) {
 			length = 4;
-			*((u32 *) resp + 6) = cpu_to_le32 (
+			*((__le32 *) resp + 6) = cpu_to_le32 (
 				(rndis_per_dev_params [configNr]
 					.stats->tx_packets - 
 				 rndis_per_dev_params [configNr]
@@ -389,7 +389,7 @@
 				/ 123);
 			retval = 0;
 		} else {
-			*((u32 *) resp + 6) = __constant_cpu_to_le32 (0);
+			*((__le32 *) resp + 6) = __constant_cpu_to_le32 (0);
 			retval = 0;
 		}
 		break;
@@ -397,12 +397,12 @@
 	case OID_GEN_MULTICAST_BYTES_XMIT:
 		DEBUG("%s: OID_GEN_MULTICAST_BYTES_XMIT\n", __FUNCTION__);
 		if (rndis_per_dev_params [configNr].stats) {
-			*((u32 *) resp + 6) = cpu_to_le32 (
+			*((__le32 *) resp + 6) = cpu_to_le32 (
 				rndis_per_dev_params [configNr]
 					.stats->multicast*1234);
 			retval = 0;
 		} else {
-			*((u32 *) resp + 6) = __constant_cpu_to_le32 (0);
+			*((__le32 *) resp + 6) = __constant_cpu_to_le32 (0);
 			retval = 0;
 		}
 		break;
@@ -410,12 +410,12 @@
 	case OID_GEN_MULTICAST_FRAMES_XMIT:
 		DEBUG("%s: OID_GEN_MULTICAST_FRAMES_XMIT\n", __FUNCTION__);
 		if (rndis_per_dev_params [configNr].stats) {
-			*((u32 *) resp + 6) = cpu_to_le32 (
+			*((__le32 *) resp + 6) = cpu_to_le32 (
 				rndis_per_dev_params [configNr]
 					.stats->multicast);
 			retval = 0;
 		} else {
-			*((u32 *) resp + 6) = __constant_cpu_to_le32 (0);
+			*((__le32 *) resp + 6) = __constant_cpu_to_le32 (0);
 			retval = 0;
 		}
 		break;
@@ -423,12 +423,12 @@
 	case OID_GEN_BROADCAST_BYTES_XMIT:
 		DEBUG("%s: OID_GEN_BROADCAST_BYTES_XMIT\n", __FUNCTION__);
 		if (rndis_per_dev_params [configNr].stats) {
-			*((u32 *) resp + 6) = cpu_to_le32 (
+			*((__le32 *) resp + 6) = cpu_to_le32 (
 				rndis_per_dev_params [configNr]
 					.stats->tx_packets/42*255);
 			retval = 0;
 		} else {
-			*((u32 *) resp + 6) = __constant_cpu_to_le32 (0);
+			*((__le32 *) resp + 6) = __constant_cpu_to_le32 (0);
 			retval = 0;
 		}
 		break;
@@ -436,37 +436,37 @@
 	case OID_GEN_BROADCAST_FRAMES_XMIT:
 		DEBUG("%s: OID_GEN_BROADCAST_FRAMES_XMIT\n", __FUNCTION__);
 		if (rndis_per_dev_params [configNr].stats) {
-			*((u32 *) resp + 6) = cpu_to_le32 (
+			*((__le32 *) resp + 6) = cpu_to_le32 (
 				rndis_per_dev_params [configNr]
 					.stats->tx_packets/42);
 			retval = 0;
 		} else {
-			*((u32 *) resp + 6) = __constant_cpu_to_le32 (0);
+			*((__le32 *) resp + 6) = __constant_cpu_to_le32 (0);
 			retval = 0;
 		}
 		break;
 		
 	case OID_GEN_DIRECTED_BYTES_RCV:
 		DEBUG("%s: OID_GEN_DIRECTED_BYTES_RCV\n", __FUNCTION__);
-		*((u32 *) resp + 6) = __constant_cpu_to_le32 (0);
+		*((__le32 *) resp + 6) = __constant_cpu_to_le32 (0);
 		retval = 0;
 		break;
 		
 	case OID_GEN_DIRECTED_FRAMES_RCV:
 		DEBUG("%s: OID_GEN_DIRECTED_FRAMES_RCV\n", __FUNCTION__);
-		*((u32 *) resp + 6) = __constant_cpu_to_le32 (0);
+		*((__le32 *) resp + 6) = __constant_cpu_to_le32 (0);
 		retval = 0;
 		break;
 		
 	case OID_GEN_MULTICAST_BYTES_RCV:
 		DEBUG("%s: OID_GEN_MULTICAST_BYTES_RCV\n", __FUNCTION__);
 		if (rndis_per_dev_params [configNr].stats) {
-			*((u32 *) resp + 6) = cpu_to_le32 (
+			*((__le32 *) resp + 6) = cpu_to_le32 (
 				rndis_per_dev_params [configNr]
 					.stats->multicast * 1111);
 			retval = 0;
 		} else {
-			*((u32 *) resp + 6) = __constant_cpu_to_le32 (0);
+			*((__le32 *) resp + 6) = __constant_cpu_to_le32 (0);
 			retval = 0;
 		}
 		break;
@@ -474,12 +474,12 @@
 	case OID_GEN_MULTICAST_FRAMES_RCV:
 		DEBUG("%s: OID_GEN_MULTICAST_FRAMES_RCV\n", __FUNCTION__);
 		if (rndis_per_dev_params [configNr].stats) {
-			*((u32 *) resp + 6) = cpu_to_le32 (
+			*((__le32 *) resp + 6) = cpu_to_le32 (
 				rndis_per_dev_params [configNr]
 					.stats->multicast);
 			retval = 0;
 		} else {
-			*((u32 *) resp + 6) = __constant_cpu_to_le32 (0);
+			*((__le32 *) resp + 6) = __constant_cpu_to_le32 (0);
 			retval = 0;
 		}
 		break;
@@ -487,12 +487,12 @@
 	case OID_GEN_BROADCAST_BYTES_RCV:
 		DEBUG("%s: OID_GEN_BROADCAST_BYTES_RCV\n", __FUNCTION__);
 		if (rndis_per_dev_params [configNr].stats) {
-			*((u32 *) resp + 6) = cpu_to_le32 (
+			*((__le32 *) resp + 6) = cpu_to_le32 (
 				rndis_per_dev_params [configNr]
 					.stats->rx_packets/42*255);
 			retval = 0;
 		} else {
-			*((u32 *) resp + 6) = __constant_cpu_to_le32 (0);
+			*((__le32 *) resp + 6) = __constant_cpu_to_le32 (0);
 			retval = 0;
 		}
 		break;
@@ -500,12 +500,12 @@
 	case OID_GEN_BROADCAST_FRAMES_RCV:
 		DEBUG("%s: OID_GEN_BROADCAST_FRAMES_RCV\n", __FUNCTION__);
 		if (rndis_per_dev_params [configNr].stats) {
-			*((u32 *) resp + 6) = cpu_to_le32 (
+			*((__le32 *) resp + 6) = cpu_to_le32 (
 				rndis_per_dev_params [configNr]
 					.stats->rx_packets/42);
 			retval = 0;
 		} else {
-			*((u32 *) resp + 6) = __constant_cpu_to_le32 (0);
+			*((__le32 *) resp + 6) = __constant_cpu_to_le32 (0);
 			retval = 0;
 		}
 		break;
@@ -513,19 +513,19 @@
 	case OID_GEN_RCV_CRC_ERROR:
 		DEBUG("%s: OID_GEN_RCV_CRC_ERROR\n", __FUNCTION__);
 		if (rndis_per_dev_params [configNr].stats) {
-			*((u32 *) resp + 6) = cpu_to_le32 (
+			*((__le32 *) resp + 6) = cpu_to_le32 (
 				rndis_per_dev_params [configNr]
 					.stats->rx_crc_errors);
 			retval = 0;
 		} else {
-			*((u32 *) resp + 6) = __constant_cpu_to_le32 (0);
+			*((__le32 *) resp + 6) = __constant_cpu_to_le32 (0);
 			retval = 0;
 		}
 		break;
 		
 	case OID_GEN_TRANSMIT_QUEUE_LENGTH:
 		DEBUG("%s: OID_GEN_TRANSMIT_QUEUE_LENGTH\n", __FUNCTION__);
-		*((u32 *) resp + 6) = __constant_cpu_to_le32 (0);
+		*((__le32 *) resp + 6) = __constant_cpu_to_le32 (0);
 		retval = 0;
 		break;
 #endif	/* RNDIS_OPTIONAL_STATS */
@@ -542,7 +542,7 @@
 				length);
 			retval = 0;
 		} else {
-			*((u32 *) resp + 6) = __constant_cpu_to_le32 (0);
+			*((__le32 *) resp + 6) = __constant_cpu_to_le32 (0);
 			retval = 0;
 		}
 		break;
@@ -564,7 +564,7 @@
 		DEBUG("%s: OID_802_3_MULTICAST_LIST\n", __FUNCTION__);
 		length = 4;
 		/* Multicast base address only */
-		*((u32 *) resp + 6) = __constant_cpu_to_le32 (0xE0000000);
+		*((__le32 *) resp + 6) = __constant_cpu_to_le32 (0xE0000000);
 		retval = 0;
 		break;
 		
@@ -573,7 +573,7 @@
 		DEBUG("%s: OID_802_3_MAXIMUM_LIST_SIZE\n", __FUNCTION__);
 		 length = 4;
 		/* Multicast base address only */
-		*((u32 *) resp + 6) = __constant_cpu_to_le32 (1);
+		*((__le32 *) resp + 6) = __constant_cpu_to_le32 (1);
 		retval = 0;
 		break;
 		
@@ -589,7 +589,7 @@
 		if (rndis_per_dev_params [configNr].stats)
 		{
 			length = 4;
-			*((u32 *) resp + 6) = cpu_to_le32 (
+			*((__le32 *) resp + 6) = cpu_to_le32 (
 				rndis_per_dev_params [configNr]
 					.stats->rx_frame_errors);
 			retval = 0;
@@ -600,7 +600,7 @@
 	case OID_802_3_XMIT_ONE_COLLISION:
 		DEBUG("%s: OID_802_3_XMIT_ONE_COLLISION\n", __FUNCTION__);
 		length = 4;
-		*((u32 *) resp + 6) = __constant_cpu_to_le32 (0);
+		*((__le32 *) resp + 6) = __constant_cpu_to_le32 (0);
 		retval = 0;
 		break;
 		
@@ -608,7 +608,7 @@
 	case OID_802_3_XMIT_MORE_COLLISIONS:
 		DEBUG("%s: OID_802_3_XMIT_MORE_COLLISIONS\n", __FUNCTION__);
 		length = 4;
-		*((u32 *) resp + 6) = __constant_cpu_to_le32 (0);
+		*((__le32 *) resp + 6) = __constant_cpu_to_le32 (0);
 		retval = 0;
 		break;
 		
@@ -734,7 +734,7 @@
 		 *	PROMISCUOUS, DIRECTED,
 		 *	MULTICAST, ALL_MULTICAST, BROADCAST
 		 */
-		params->filter = cpu_to_le32p((u32 *)buf);
+		params->filter = le32_to_cpup((__le32 *)buf);
 		DEBUG("%s: OID_GEN_CURRENT_PACKET_FILTER %08x\n",
 			__FUNCTION__, params->filter);
 
@@ -866,7 +866,7 @@
 	resp->MessageLength = __constant_cpu_to_le32 (24);
 	resp->RequestID = buf->RequestID; /* Still LE in msg buffer */
 	
-	if (gen_ndis_query_resp (configNr, cpu_to_le32 (buf->OID), r)) {
+	if (gen_ndis_query_resp (configNr, le32_to_cpu (buf->OID), r)) {
 		/* OID not supported */
 		resp->Status = __constant_cpu_to_le32 (
 				RNDIS_STATUS_NOT_SUPPORTED);
@@ -893,8 +893,8 @@
 	resp = (rndis_set_cmplt_type *) r->buf;
 	if (!resp) return -ENOMEM;
 
-	BufLength = cpu_to_le32 (buf->InformationBufferLength);
-	BufOffset = cpu_to_le32 (buf->InformationBufferOffset);
+	BufLength = le32_to_cpu (buf->InformationBufferLength);
+	BufOffset = le32_to_cpu (buf->InformationBufferOffset);
 
 #ifdef	VERBOSE
 	DEBUG("%s: Length: %d\n", __FUNCTION__, BufLength);
@@ -911,7 +911,7 @@
 	resp->MessageType = __constant_cpu_to_le32 (REMOTE_NDIS_SET_CMPLT);
 	resp->MessageLength = __constant_cpu_to_le32 (16);
 	resp->RequestID = buf->RequestID; /* Still LE in msg buffer */
-	if (gen_ndis_set_resp (configNr, cpu_to_le32 (buf->OID), 
+	if (gen_ndis_set_resp (configNr, le32_to_cpu (buf->OID), 
 			       ((u8 *) buf) + 8 + BufOffset, BufLength, r))
 	    resp->Status = __constant_cpu_to_le32 (RNDIS_STATUS_NOT_SUPPORTED);
 	else resp->Status = __constant_cpu_to_le32 (RNDIS_STATUS_SUCCESS);
@@ -1030,15 +1030,16 @@
  */
 int rndis_msg_parser (u8 configNr, u8 *buf)
 {
-	u32 MsgType, MsgLength, *tmp;
+	u32 MsgType, MsgLength;
+	__le32 *tmp;
 	struct rndis_params		*params;
 	
 	if (!buf)
 		return -ENOMEM;
 	
-	tmp = (u32 *) buf; 
-	MsgType   = cpu_to_le32p(tmp++);
-	MsgLength = cpu_to_le32p(tmp++);
+	tmp = (__le32 *) buf; 
+	MsgType   = le32_to_cpup(tmp++);
+	MsgLength = le32_to_cpup(tmp++);
 	
 	if (configNr >= RNDIS_MAX_CONFIGS)
 		return -ENOTSUPP;
@@ -1187,15 +1188,16 @@
 
 void rndis_add_hdr (struct sk_buff *skb)
 {
-	if (!skb) return;
-	skb_push (skb, sizeof (struct rndis_packet_msg_type));
-	memset (skb->data, 0, sizeof (struct rndis_packet_msg_type));
-	*((u32 *) skb->data) = __constant_cpu_to_le32 (1);
-	*((u32 *) skb->data + 1) = cpu_to_le32(skb->len);
-	*((u32 *) skb->data + 2) = __constant_cpu_to_le32 (36);
-	*((u32 *) skb->data + 3) = cpu_to_le32(skb->len - 44);
-	
-	return;
+	struct rndis_packet_msg_type	*header;
+
+	if (!skb)
+		return;
+	header = (void *) skb_push (skb, sizeof *header);
+	memset (header, 0, sizeof *header);
+	header->MessageType = __constant_cpu_to_le32 (1);
+	header->MessageLength = cpu_to_le32(skb->len);
+	header->DataOffset = __constant_cpu_to_le32 (36);
+	header->OOBDataOffset = cpu_to_le32(skb->len - 44);
 }
 
 void rndis_free_response (int configNr, u8 *buf)
@@ -1253,15 +1255,16 @@
 
 int rndis_rm_hdr (u8 *buf, u32 *length)
 {
-	u32 i, messageLen, dataOffset, *tmp;
+	u32 i, messageLen, dataOffset;
+	__le32 *tmp;
 	
-	tmp = (u32 *) buf; 
+	tmp = (__le32 *) buf; 
 
 	if (!buf || !length) return -1;
-	if (cpu_to_le32p(tmp++) != 1) return -1;
+	if (le32_to_cpup(tmp++) != 1) return -1;
 	
-	messageLen = cpu_to_le32p(tmp++);
-	dataOffset = cpu_to_le32p(tmp++) + 8;
+	messageLen = le32_to_cpup(tmp++);
+	dataOffset = le32_to_cpup(tmp++) + 8;
 
 	if (messageLen < dataOffset || messageLen > *length) return -1;
 	
diff -Nru a/drivers/usb/gadget/rndis.h b/drivers/usb/gadget/rndis.h
--- a/drivers/usb/gadget/rndis.h	2005-03-24 18:21:08 -08:00
+++ b/drivers/usb/gadget/rndis.h	2005-03-24 18:21:08 -08:00
@@ -154,139 +154,139 @@
 
 typedef struct rndis_init_msg_type 
 {
-	u32	MessageType;
-	u32	MessageLength;
-	u32	RequestID;
-	u32	MajorVersion;
-	u32	MinorVersion;
-	u32	MaxTransferSize;
+	__le32	MessageType;
+	__le32	MessageLength;
+	__le32	RequestID;
+	__le32	MajorVersion;
+	__le32	MinorVersion;
+	__le32	MaxTransferSize;
 } rndis_init_msg_type;
 
 typedef struct rndis_init_cmplt_type
 {
-	u32	MessageType;
-	u32	MessageLength;
-	u32	RequestID;
-	u32	Status;
-	u32	MajorVersion;
-	u32	MinorVersion;
-	u32	DeviceFlags;
-	u32	Medium;
-	u32	MaxPacketsPerTransfer;
-	u32	MaxTransferSize;
-	u32	PacketAlignmentFactor;
-	u32	AFListOffset;
-	u32	AFListSize;
+	__le32	MessageType;
+	__le32	MessageLength;
+	__le32	RequestID;
+	__le32	Status;
+	__le32	MajorVersion;
+	__le32	MinorVersion;
+	__le32	DeviceFlags;
+	__le32	Medium;
+	__le32	MaxPacketsPerTransfer;
+	__le32	MaxTransferSize;
+	__le32	PacketAlignmentFactor;
+	__le32	AFListOffset;
+	__le32	AFListSize;
 } rndis_init_cmplt_type;
 
 typedef struct rndis_halt_msg_type
 {
-	u32	MessageType;
-	u32	MessageLength;
-	u32	RequestID;
+	__le32	MessageType;
+	__le32	MessageLength;
+	__le32	RequestID;
 } rndis_halt_msg_type;
 
 typedef struct rndis_query_msg_type
 {
-	u32	MessageType;
-	u32	MessageLength;
-	u32	RequestID;
-	u32	OID;
-	u32	InformationBufferLength;
-	u32	InformationBufferOffset;
-	u32	DeviceVcHandle;
+	__le32	MessageType;
+	__le32	MessageLength;
+	__le32	RequestID;
+	__le32	OID;
+	__le32	InformationBufferLength;
+	__le32	InformationBufferOffset;
+	__le32	DeviceVcHandle;
 } rndis_query_msg_type;
 
 typedef struct rndis_query_cmplt_type
 {
-	u32	MessageType;
-	u32	MessageLength;
-	u32	RequestID;
-	u32	Status;
-	u32	InformationBufferLength;
-	u32	InformationBufferOffset;
+	__le32	MessageType;
+	__le32	MessageLength;
+	__le32	RequestID;
+	__le32	Status;
+	__le32	InformationBufferLength;
+	__le32	InformationBufferOffset;
 } rndis_query_cmplt_type;
 
 typedef struct rndis_set_msg_type
 {
-	u32	MessageType;
-	u32	MessageLength;
-	u32	RequestID;
-	u32	OID;
-	u32	InformationBufferLength;
-	u32	InformationBufferOffset;
-	u32	DeviceVcHandle;
+	__le32	MessageType;
+	__le32	MessageLength;
+	__le32	RequestID;
+	__le32	OID;
+	__le32	InformationBufferLength;
+	__le32	InformationBufferOffset;
+	__le32	DeviceVcHandle;
 } rndis_set_msg_type;
 
 typedef struct rndis_set_cmplt_type
 {
-	u32	MessageType;
-	u32	MessageLength;
-	u32	RequestID;
-	u32	Status;
+	__le32	MessageType;
+	__le32	MessageLength;
+	__le32	RequestID;
+	__le32	Status;
 } rndis_set_cmplt_type;
 
 typedef struct rndis_reset_msg_type
 {
-	u32	MessageType;
-	u32	MessageLength;
-	u32	Reserved;
+	__le32	MessageType;
+	__le32	MessageLength;
+	__le32	Reserved;
 } rndis_reset_msg_type;
 
 typedef struct rndis_reset_cmplt_type
 {
-	u32	MessageType;
-	u32	MessageLength;
-	u32	Status;
-	u32	AddressingReset;
+	__le32	MessageType;
+	__le32	MessageLength;
+	__le32	Status;
+	__le32	AddressingReset;
 } rndis_reset_cmplt_type;
 
 typedef struct rndis_indicate_status_msg_type
 {
-	u32	MessageType;
-	u32	MessageLength;
-	u32	Status;
-	u32	StatusBufferLength;
-	u32	StatusBufferOffset;
+	__le32	MessageType;
+	__le32	MessageLength;
+	__le32	Status;
+	__le32	StatusBufferLength;
+	__le32	StatusBufferOffset;
 } rndis_indicate_status_msg_type;
 
 typedef struct rndis_keepalive_msg_type
 {
-	u32	MessageType;
-	u32	MessageLength;
-	u32	RequestID;
+	__le32	MessageType;
+	__le32	MessageLength;
+	__le32	RequestID;
 } rndis_keepalive_msg_type;
 
 typedef struct rndis_keepalive_cmplt_type
 {
-	u32	MessageType;
-	u32	MessageLength;
-	u32	RequestID;
-	u32	Status;
+	__le32	MessageType;
+	__le32	MessageLength;
+	__le32	RequestID;
+	__le32	Status;
 } rndis_keepalive_cmplt_type;
 
 struct rndis_packet_msg_type
 {
-	u32	MessageType;
-	u32	MessageLength;
-	u32	DataOffset;
-	u32	DataLength;
-	u32	OOBDataOffset;
-	u32	OOBDataLength;
-	u32	NumOOBDataElements;
-	u32	PerPacketInfoOffset;
-	u32	PerPacketInfoLength;
-	u32	VcHandle;
-	u32	Reserved;
+	__le32	MessageType;
+	__le32	MessageLength;
+	__le32	DataOffset;
+	__le32	DataLength;
+	__le32	OOBDataOffset;
+	__le32	OOBDataLength;
+	__le32	NumOOBDataElements;
+	__le32	PerPacketInfoOffset;
+	__le32	PerPacketInfoLength;
+	__le32	VcHandle;
+	__le32	Reserved;
 };
 
 struct rndis_config_parameter
 {
-	u32	ParameterNameOffset;
-	u32	ParameterNameLength;
-	u32	ParameterType;
-	u32	ParameterValueOffset;
-	u32	ParameterValueLength;
+	__le32	ParameterNameOffset;
+	__le32	ParameterNameLength;
+	__le32	ParameterType;
+	__le32	ParameterValueOffset;
+	__le32	ParameterValueLength;
 };
 
 /* implementation specific */
diff -Nru a/drivers/usb/gadget/serial.c b/drivers/usb/gadget/serial.c
--- a/drivers/usb/gadget/serial.c	2005-03-24 18:21:08 -08:00
+++ b/drivers/usb/gadget/serial.c	2005-03-24 18:21:08 -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/usbstring.c b/drivers/usb/gadget/usbstring.c
--- a/drivers/usb/gadget/usbstring.c	2005-03-24 18:21:08 -08:00
+++ b/drivers/usb/gadget/usbstring.c	2005-03-24 18:21:08 -08:00
@@ -20,7 +20,7 @@
 #include <asm/unaligned.h>
 
 
-static int utf8_to_utf16le(const char *s, u16 *cp, unsigned len)
+static int utf8_to_utf16le(const char *s, __le16 *cp, unsigned len)
 {
 	int	count = 0;
 	u8	c;
@@ -126,7 +126,7 @@
 	/* string descriptors have length, tag, then UTF16-LE text */
 	len = min ((size_t) 126, strlen (s->s));
 	memset (buf + 2, 0, 2 * len);	/* zero all the bytes */
-	len = utf8_to_utf16le(s->s, (u16 *)&buf[2], len);
+	len = utf8_to_utf16le(s->s, (__le16 *)&buf[2], len);
 	if (len < 0)
 		return -EINVAL;
 	buf [0] = (len + 1) * 2;
diff -Nru a/drivers/usb/gadget/zero.c b/drivers/usb/gadget/zero.c
--- a/drivers/usb/gadget/zero.c	2005-03-24 18:21:08 -08:00
+++ b/drivers/usb/gadget/zero.c	2005-03-24 18:21:08 -08:00
@@ -919,6 +919,9 @@
 	struct zero_dev		*dev = get_gadget_data (gadget);
 	struct usb_request	*req = dev->req;
 	int			value = -EOPNOTSUPP;
+	u16			w_index = ctrl->wIndex;
+	u16			w_value = ctrl->wValue;
+	u16			w_length = ctrl->wLength;
 
 	/* usually this stores reply data in the pre-allocated ep0 buffer,
 	 * but config change events will reconfigure hardware.
@@ -929,17 +932,17 @@
 	case USB_REQ_GET_DESCRIPTOR:
 		if (ctrl->bRequestType != USB_DIR_IN)
 			goto unknown;
-		switch (ctrl->wValue >> 8) {
+		switch (w_value >> 8) {
 
 		case USB_DT_DEVICE:
-			value = min (ctrl->wLength, (u16) sizeof device_desc);
+			value = min (w_length, (u16) sizeof device_desc);
 			memcpy (req->buf, &device_desc, value);
 			break;
 #ifdef CONFIG_USB_GADGET_DUALSPEED
 		case USB_DT_DEVICE_QUALIFIER:
 			if (!gadget->is_dualspeed)
 				break;
-			value = min (ctrl->wLength, (u16) sizeof dev_qualifier);
+			value = min (w_length, (u16) sizeof dev_qualifier);
 			memcpy (req->buf, &dev_qualifier, value);
 			break;
 
@@ -950,10 +953,10 @@
 #endif /* CONFIG_USB_GADGET_DUALSPEED */
 		case USB_DT_CONFIG:
 			value = config_buf (gadget, req->buf,
-					ctrl->wValue >> 8,
-					ctrl->wValue & 0xff);
+					w_value >> 8,
+					w_value & 0xff);
 			if (value >= 0)
-				value = min (ctrl->wLength, (u16) value);
+				value = min (w_length, (u16) value);
 			break;
 
 		case USB_DT_STRING:
@@ -963,9 +966,9 @@
 			 * any UTF-8 characters
 			 */
 			value = usb_gadget_get_string (&stringtab,
-					ctrl->wValue & 0xff, req->buf);
+					w_value & 0xff, req->buf);
 			if (value >= 0)
-				value = min (ctrl->wLength, (u16) value);
+				value = min (w_length, (u16) value);
 			break;
 		}
 		break;
@@ -981,14 +984,14 @@
 		else
 			VDBG (dev, "HNP inactive\n");
 		spin_lock (&dev->lock);
-		value = zero_set_config (dev, ctrl->wValue, GFP_ATOMIC);
+		value = zero_set_config (dev, w_value, GFP_ATOMIC);
 		spin_unlock (&dev->lock);
 		break;
 	case USB_REQ_GET_CONFIGURATION:
 		if (ctrl->bRequestType != USB_DIR_IN)
 			goto unknown;
 		*(u8 *)req->buf = dev->config;
-		value = min (ctrl->wLength, (u16) 1);
+		value = min (w_length, (u16) 1);
 		break;
 
 	/* until we add altsetting support, or other interfaces,
@@ -999,7 +1002,7 @@
 		if (ctrl->bRequestType != USB_RECIP_INTERFACE)
 			goto unknown;
 		spin_lock (&dev->lock);
-		if (dev->config && ctrl->wIndex == 0 && ctrl->wValue == 0) {
+		if (dev->config && w_index == 0 && w_value == 0) {
 			u8		config = dev->config;
 
 			/* resets interface configuration, forgets about
@@ -1020,12 +1023,12 @@
 			goto unknown;
 		if (!dev->config)
 			break;
-		if (ctrl->wIndex != 0) {
+		if (w_index != 0) {
 			value = -EDOM;
 			break;
 		}
 		*(u8 *)req->buf = 0;
-		value = min (ctrl->wLength, (u16) 1);
+		value = min (w_length, (u16) 1);
 		break;
 
 	/*
@@ -1036,23 +1039,23 @@
 	case 0x5b:	/* control WRITE test -- fill the buffer */
 		if (ctrl->bRequestType != (USB_DIR_OUT|USB_TYPE_VENDOR))
 			goto unknown;
-		if (ctrl->wValue || ctrl->wIndex)
+		if (w_value || w_index)
 			break;
 		/* just read that many bytes into the buffer */
-		if (ctrl->wLength > USB_BUFSIZ)
+		if (w_length > USB_BUFSIZ)
 			break;
-		value = ctrl->wLength;
+		value = w_length;
 		break;
 	case 0x5c:	/* control READ test -- return the buffer */
 		if (ctrl->bRequestType != (USB_DIR_IN|USB_TYPE_VENDOR))
 			goto unknown;
-		if (ctrl->wValue || ctrl->wIndex)
+		if (w_value || w_index)
 			break;
 		/* expect those bytes are still in the buffer; send back */
-		if (ctrl->wLength > USB_BUFSIZ
-				|| ctrl->wLength != req->length)
+		if (w_length > USB_BUFSIZ
+				|| w_length != req->length)
 			break;
-		value = ctrl->wLength;
+		value = w_length;
 		break;
 
 	default:
@@ -1060,14 +1063,13 @@
 		VDBG (dev,
 			"unknown control req%02x.%02x v%04x i%04x l%d\n",
 			ctrl->bRequestType, ctrl->bRequest,
-			ctrl->wValue, ctrl->wIndex, ctrl->wLength);
+			w_value, w_index, w_length);
 	}
 
 	/* respond with data transfer before status phase? */
 	if (value >= 0) {
 		req->length = value;
-		req->zero = value < ctrl->wLength
-				&& (value % gadget->ep0->maxpacket) == 0;
+		req->zero = value < w_length;
 		value = usb_ep_queue (gadget->ep0, req, GFP_ATOMIC);
 		if (value < 0) {
 			DBG (dev, "ep_queue --> %d\n", value);
@@ -1193,6 +1195,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-24 18:21:08 -08:00
+++ b/drivers/usb/host/ehci-hcd.c	2005-03-24 18:21:08 -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-24 18:21:08 -08:00
+++ b/drivers/usb/host/ehci-hub.c	2005-03-24 18:21:08 -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-24 18:21:08 -08:00
+++ b/drivers/usb/host/ehci-q.c	2005-03-24 18:21:08 -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-24 18:21:08 -08:00
+++ b/drivers/usb/host/ehci-sched.c	2005-03-24 18:21:08 -08:00
@@ -208,7 +208,7 @@
 				here = here.qh->qh_next;
 				continue;
 			case Q_TYPE_SITD:
-				if (same_tt (dev, here.itd->urb->dev)) {
+				if (same_tt (dev, here.sitd->urb->dev)) {
 					u16		mask;
 
 					mask = le32_to_cpu (here.sitd
@@ -218,7 +218,7 @@
 					if (mask & uf_mask)
 						break;
 				}
-				type = Q_NEXT_TYPE (here.qh->hw_next);
+				type = Q_NEXT_TYPE (here.sitd->hw_next);
 				here = here.sitd->sitd_next;
 				continue;
 			// case Q_TYPE_FSTN:
@@ -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;
 	}
 
@@ -1180,7 +1180,10 @@
 	return status;
 
 ready:
+	/* report high speed start in uframes; full speed, in frames */
 	urb->start_frame = stream->next_uframe;
+	if (!stream->highspeed)
+		urb->start_frame >>= 3;
 	return 0;
 }
 
@@ -1504,18 +1507,17 @@
 
 		/* might need to cross a buffer page within a td */
 		packet->bufp = buf;
-		buf += length;
-		packet->buf1 = buf & ~0x0fff;
+		packet->buf1 = (buf + length) & ~0x0fff;
 		if (packet->buf1 != (buf & ~(u64)0x0fff))
 			packet->cross = 1;
 
 		/* OUT uses multiple start-splits */ 
 		if (stream->bEndpointAddress & USB_DIR_IN)
 			continue;
-		length = 1 + (length / 188);
-		packet->buf1 |= length;
+		length = (length + 187) / 188;
 		if (length > 1) /* BEGIN vs ALL */
-			packet->buf1 |= 1 << 3;
+			length |= 1 << 3;
+		packet->buf1 |= length;
 	}
 }
 
@@ -1610,10 +1612,9 @@
 	sitd->hw_buf_hi [0] = cpu_to_le32 (bufp >> 32);
 
 	sitd->hw_buf [1] = cpu_to_le32 (uf->buf1);
-	if (uf->cross) {
+	if (uf->cross)
 		bufp += 4096;
-		sitd->hw_buf_hi [1] = cpu_to_le32 (bufp >> 32);
-	}
+	sitd->hw_buf_hi [1] = cpu_to_le32 (bufp >> 32);
 	sitd->index = index;
 }
 
@@ -1650,7 +1651,7 @@
 		ehci_to_hcd(ehci)->self.bandwidth_allocated
 				+= stream->bandwidth;
 		ehci_vdbg (ehci,
-			"sched dev%s ep%d%s-iso [%d] %dms/%04x\n",
+			"sched devp %s ep%d%s-iso [%d] %dms/%04x\n",
 			urb->dev->devpath, stream->bEndpointAddress & 0x0f,
 			(stream->bEndpointAddress & USB_DIR_IN) ? "in" : "out",
 			(next_uframe >> 3) % ehci->periodic_size,
@@ -1697,7 +1698,7 @@
 /*-------------------------------------------------------------------------*/
 
 #define	SITD_ERRS (SITD_STS_ERR | SITD_STS_DBE | SITD_STS_BABBLE \
-			| SITD_STS_XACT | SITD_STS_MMF | SITD_STS_STS)
+	       			| SITD_STS_XACT | SITD_STS_MMF)
 
 static unsigned
 sitd_complete (
@@ -1780,12 +1781,6 @@
 	unsigned long		flags;
 	struct ehci_iso_stream	*stream;
 
-	// FIXME remove when csplits behave
-	if (usb_pipein(urb->pipe)) {
-		ehci_dbg (ehci, "no iso-IN split transactions yet\n");
-		return -ENOMEM;
-	}
-
 	/* Get iso_stream head */
 	stream = iso_stream_find (ehci, urb);
 	if (stream == NULL) {
@@ -1864,7 +1859,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 +1893,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 +1982,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/ehci.h b/drivers/usb/host/ehci.h
--- a/drivers/usb/host/ehci.h	2005-03-24 18:21:08 -08:00
+++ b/drivers/usb/host/ehci.h	2005-03-24 18:21:08 -08:00
@@ -430,7 +430,7 @@
 	__le32			transaction;	/* itd->hw_transaction[i] |= */
 	u8			cross;		/* buf crosses pages */
 	/* for full speed OUT splits */
-	u16			buf1;
+	u32			buf1;
 };
 
 /* temporary schedule data for packets from iso urbs (both speeds)
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-24 18:21:08 -08:00
+++ b/drivers/usb/host/ohci-hcd.c	2005-03-24 18:21:08 -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-24 18:21:08 -08:00
+++ b/drivers/usb/host/ohci-hub.c	2005-03-24 18:21:08 -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-24 18:21:08 -08:00
+++ b/drivers/usb/host/ohci-omap.c	2005-03-24 18:21:08 -08:00
@@ -2,16 +2,14 @@
  * OHCI HCD (Host Controller Driver) for USB.
  *
  * (C) Copyright 1999 Roman Weissgaerber <weissg@vienna.at>
- * (C) Copyright 2000-2004 David Brownell <dbrownell@users.sourceforge.net>
+ * (C) Copyright 2000-2005 David Brownell
  * (C) Copyright 2002 Hewlett-Packard Company
  * 
  * OMAP Bus Glue
  *
- * Written by Christopher Hoover <ch@hpl.hp.com>
- * Based on fragments of previous driver by Russell King et al.
- *
- * Modified for OMAP from ohci-sa1111.c by Tony Lindgren <tony@atomide.com>
+ * Modified for OMAP by Tony Lindgren <tony@atomide.com>
  * Based on the 2.4 OMAP OHCI driver originally done by MontaVista Software Inc.
+ * and on ohci-sa1111.c by Christopher Hoover <ch@hpl.hp.com>
  *
  * This file is licenced under the GPL.
  */
@@ -26,8 +24,20 @@
 #include <asm/arch/gpio.h>
 #include <asm/arch/fpga.h>
 #include <asm/arch/usb.h>
+#include <asm/hardware/clock.h>
+
+
+/* OMAP-1510 OHCI has its own MMU for DMA */
+#define OMAP1510_LB_MEMSIZE	32	/* Should be same as SDRAM size */
+#define OMAP1510_LB_CLOCK_DIV	0xfffec10c
+#define OMAP1510_LB_MMU_CTL	0xfffec208
+#define OMAP1510_LB_MMU_LCK	0xfffec224
+#define OMAP1510_LB_MMU_LD_TLB	0xfffec228
+#define OMAP1510_LB_MMU_CAM_H	0xfffec22c
+#define OMAP1510_LB_MMU_CAM_L	0xfffec230
+#define OMAP1510_LB_MMU_RAM_H	0xfffec234
+#define OMAP1510_LB_MMU_RAM_L	0xfffec238
 
-#include "ohci-omap.h"
 
 #ifndef CONFIG_ARCH_OMAP
 #error "This file is OMAP bus glue.  CONFIG_OMAP must be defined."
@@ -52,45 +62,17 @@
 extern int usb_disabled(void);
 extern int ocpi_enable(void);
 
-/*
- * OHCI clock initialization for OMAP-1510 and 16xx
- */
-static int omap_ohci_clock_power(int on)
+static struct clk *usb_host_ck;
+
+static void omap_ohci_clock_power(int on)
 {
 	if (on) {
-		/* for 1510, 48MHz DPLL is set up in usb init */
-
-		if (cpu_is_omap16xx()) {
-			/* Enable OHCI */
-			omap_writel(omap_readl(ULPD_SOFT_REQ) | SOFT_USB_OTG_REQ,
-				ULPD_SOFT_REQ);
-
-			/* USB host clock request if not using OTG */
-			omap_writel(omap_readl(ULPD_SOFT_REQ) | SOFT_USB_REQ,
-				ULPD_SOFT_REQ);
-
-			omap_writel(omap_readl(ULPD_STATUS_REQ) | USB_HOST_DPLL_REQ,
-			     ULPD_STATUS_REQ);
-		}
-
-		/* Enable 48MHz clock to USB */
-		omap_writel(omap_readl(ULPD_CLOCK_CTRL) | USB_MCLK_EN,
-		       ULPD_CLOCK_CTRL);
-
-		omap_writel(omap_readl(ARM_IDLECT2) | (1 << EN_LBFREECK) | (1 << EN_LBCK),
-		       ARM_IDLECT2);
-
-		omap_writel(omap_readl(MOD_CONF_CTRL_0) | USB_HOST_HHC_UHOST_EN,
-		       MOD_CONF_CTRL_0);
+		clk_enable(usb_host_ck);
+		/* guesstimate for T5 == 1x 32K clock + APLL lock time */
+		udelay(100);
 	} else {
-		/* Disable 48MHz clock to USB */
-		omap_writel(omap_readl(ULPD_CLOCK_CTRL) & ~USB_MCLK_EN,
-		       ULPD_CLOCK_CTRL);
-
-		/* FIXME: The DPLL stays on for now */
+		clk_disable(usb_host_ck);
 	}
-
-	return 0;
 }
 
 /*
@@ -204,7 +186,7 @@
 
 	/* boards can use OTG transceivers in non-OTG modes */
 	need_transceiver = need_transceiver
-			|| machine_is_omap_h2();
+			|| machine_is_omap_h2() || machine_is_omap_h3();
 
 	if (cpu_is_omap16xx())
 		ocpi_enable();
@@ -261,7 +243,7 @@
 			omap_cfg_reg(W4_USB_HIGHZ);
 		}
 		ohci_writel(ohci, rh, &ohci->regs->roothub.a);
-		// distrust_firmware = 0;
+		distrust_firmware = 0;
 	}
 
 	/* FIXME khubd hub requests should manage power switching */
@@ -278,21 +260,14 @@
 static void omap_stop_hc(struct platform_device *pdev)
 {
 	dev_dbg(&pdev->dev, "stopping USB Controller\n");
-
-	/*
-	 * FIXME: Put the USB host controller into reset.
-	 */
-
-	/*
-	 * FIXME: Stop the USB clock.
-	 */
-	//omap_disable_device(dev);
-
+	omap_ohci_clock_power(0);
 }
 
 
 /*-------------------------------------------------------------------------*/
 
+void usb_hcd_omap_remove (struct usb_hcd *, struct platform_device *);
+
 /* configure so an HC device and id are always provided */
 /* always called with process context; sleeping is OK */
 
@@ -309,7 +284,7 @@
 			  struct platform_device *pdev)
 {
 	int retval;
-	struct usb_hcd *hcd;
+	struct usb_hcd *hcd = 0;
 	struct ohci_hcd *ohci;
 
 	if (pdev->num_resources != 2) {
@@ -319,14 +294,20 @@
 	}
 
 	if (pdev->resource[0].flags != IORESOURCE_MEM 
-	    || pdev->resource[1].flags != IORESOURCE_IRQ) {
+			|| pdev->resource[1].flags != IORESOURCE_IRQ) {
 		printk(KERN_ERR "hcd probe: invalid resource type\n");
 		return -ENODEV;
 	}
 
+	usb_host_ck = clk_get(0, "usb_hhc_ck");
+	if (IS_ERR(usb_host_ck))
+		return PTR_ERR(usb_host_ck);
+
 	hcd = usb_create_hcd (driver, &pdev->dev, pdev->dev.bus_id);
-	if (!hcd)
-		return -ENOMEM;
+	if (!hcd) {
+		retval = -ENOMEM;
+		goto err0;
+	}
 	hcd->rsrc_start = pdev->resource[0].start;
 	hcd->rsrc_len = pdev->resource[0].end - pdev->resource[0].start + 1;
 
@@ -336,9 +317,7 @@
 		goto err1;
 	}
 
-	/* FIXME: Cast to pointer from integer of different size!
-	 * Needs ioremap */
-	hcd->regs = (void __iomem *) (u32) hcd->rsrc_start;
+	hcd->regs = (void __iomem *) (int) IO_ADDRESS(hcd->rsrc_start);
 
 	ohci = hcd_to_ohci(hcd);
 	ohci_hcd_init(ohci);
@@ -347,20 +326,21 @@
 	if (retval < 0)
 		goto err2;
 
-	retval = usb_add_hcd(hcd, pdev->resource[1].start, SA_INTERRUPT);
+	retval = usb_add_hcd(hcd, platform_get_irq(pdev, 0), SA_INTERRUPT);
 	if (retval == 0)
 		return retval;
 
 	omap_stop_hc(pdev);
- err2:
+err2:
 	release_mem_region(hcd->rsrc_start, hcd->rsrc_len);
- err1:
+err1:
 	usb_put_hcd(hcd);
+err0:
+	clk_put(usb_host_ck);
 	return retval;
 }
 
 
-/* may be called without controller electrically present */
 /* may be called with controller, bus, and devices active */
 
 /**
@@ -381,6 +361,7 @@
 	omap_stop_hc(pdev);
 	release_mem_region(hcd->rsrc_start, hcd->rsrc_len);
 	usb_put_hcd(hcd);
+	clk_put(usb_host_ck);
 }
 
 /*-------------------------------------------------------------------------*/
@@ -397,7 +378,7 @@
 		writel(OHCI_CTRL_RWC, &ohci->regs->control);
 
 	if ((ret = ohci_run (ohci)) < 0) {
-		err ("can't start %s", hcd->self.bus_name);
+		dev_err(hcd->self.controller, "can't start\n");
 		ohci_stop (hcd);
 		return ret;
 	}
@@ -466,13 +447,14 @@
 		(void) otg_set_host(ohci->transceiver, 0);
 		put_device(ohci->transceiver->dev);
 	}
+	dev_set_drvdata(dev, NULL);
 
 	return 0;
 }
 
 /*-------------------------------------------------------------------------*/
 
-#if	defined(CONFIG_USB_SUSPEND) || defined(CONFIG_PM)
+#ifdef	CONFIG_PM
 
 /* states match PCI usage, always suspending the root hub except that
  * 4 ~= D3cold (ACPI D3) with clock off (resume sees reset).
@@ -493,13 +475,12 @@
 	status = ohci_hub_suspend(ohci_to_hcd(ohci));
 	if (status == 0) {
 		if (state >= 4) {
-			/* power off + reset */
-			OTG_SYSCON_2_REG &= ~UHOST_EN;
+			omap_ohci_clock_power(0);
 			ohci_to_hcd(ohci)->self.root_hub->state =
 					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);
@@ -521,7 +502,7 @@
 		if (time_before(jiffies, ohci->next_statechange))
 			msleep(5);
 		ohci->next_statechange = jiffies;
-		OTG_SYSCON_2_REG |= UHOST_EN;
+		omap_ohci_clock_power(1);
 		/* FALLTHROUGH */
 	default:
 		dev_dbg(dev, "resume from %d\n", dev->power.power_state);
@@ -552,7 +533,7 @@
 	.bus		= &platform_bus_type,
 	.probe		= ohci_hcd_omap_drv_probe,
 	.remove		= ohci_hcd_omap_drv_remove,
-#if	defined(CONFIG_USB_SUSPEND) || defined(CONFIG_PM)
+#ifdef	CONFIG_PM
 	.suspend	= ohci_omap_suspend,
 	.resume		= ohci_omap_resume,
 #endif
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-24 18:21:08 -08:00
+++ b/drivers/usb/host/ohci-q.c	2005-03-24 18:21:08 -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-24 18:21:08 -08:00
+++ b/drivers/usb/host/ohci.h	2005-03-24 18:21:08 -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-24 18:21:08 -08:00
+++ b/drivers/usb/host/sl811-hcd.c	2005-03-24 18:21:08 -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-24 18:21:08 -08:00
+++ b/drivers/usb/host/uhci-debug.c	2005-03-24 18:21:08 -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-24 18:21:08 -08:00
+++ b/drivers/usb/host/uhci-hcd.c	2005-03-24 18:21:08 -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-24 18:21:08 -08:00
+++ b/drivers/usb/host/uhci-hcd.h	2005-03-24 18:21:08 -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-24 18:21:08 -08:00
+++ b/drivers/usb/host/uhci-hub.c	2005-03-24 18:21:08 -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-24 18:21:08 -08:00
+++ b/drivers/usb/host/uhci-q.c	2005-03-24 18:21:08 -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-24 18:21:08 -08:00
+++ b/drivers/usb/image/Kconfig	2005-03-24 18:21:08 -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-24 18:21:08 -08:00
+++ b/drivers/usb/image/Makefile	2005-03-24 18:21:08 -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-24 18:21:08 -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-24 18:21:08 -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-24 18:21:08 -08:00
+++ b/drivers/usb/image/microtek.c	2005-03-24 18:21:08 -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-24 18:21:08 -08:00
+++ b/drivers/usb/input/aiptek.c	2005-03-24 18:21:08 -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-24 18:21:08 -08:00
+++ b/drivers/usb/media/ibmcam.c	2005-03-24 18:21:08 -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-24 18:21:08 -08:00
+++ b/drivers/usb/media/pwc/pwc-if.c	2005-03-24 18:21:08 -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-24 18:21:08 -08:00
+++ b/drivers/usb/misc/emi26.c	2005-03-24 18:21:08 -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-24 18:21:08 -08:00
+++ b/drivers/usb/misc/rio500.c	2005-03-24 18:21:08 -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-24 18:21:08 -08:00
+++ b/drivers/usb/misc/sisusbvga/sisusb.c	2005-03-24 18:21:08 -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/mon/mon_text.c b/drivers/usb/mon/mon_text.c
--- a/drivers/usb/mon/mon_text.c	2005-03-24 18:21:08 -08:00
+++ b/drivers/usb/mon/mon_text.c	2005-03-24 18:21:08 -08:00
@@ -261,6 +261,7 @@
 	struct mon_event_text *ep;
 	int cnt, limit;
 	char *pbuf;
+	char udir, utype;
 	int data_len, i;
 
 	add_wait_queue(&rp->wait, &waita);
@@ -290,9 +291,18 @@
 	pbuf = rp->printf_buf;
 	limit = rp->printf_size;
 
+	udir = usb_pipein(ep->pipe) ? 'i' : 'o';
+	switch (usb_pipetype(ep->pipe)) {
+	case PIPE_ISOCHRONOUS:	utype = 'Z'; break;
+	case PIPE_INTERRUPT:	utype = 'I'; break;
+	case PIPE_CONTROL:	utype = 'C'; break;
+	default: /* PIPE_BULK */  utype = 'B';
+	}
 	cnt += snprintf(pbuf + cnt, limit - cnt,
-	    "%lx %u %c %08x %d %d",
-	    ep->id, ep->tstamp, ep->type, ep->pipe, ep->status, ep->length);
+	    "%lx %u %c %c%c:%03u:%02u %d %d",
+	    ep->id, ep->tstamp, ep->type,
+	    utype, udir, usb_pipedevice(ep->pipe), usb_pipeendpoint(ep->pipe),
+	    ep->status, ep->length);
 
 	if ((data_len = ep->length) > 0) {
 		if (ep->data_flag == 0) {
diff -Nru a/drivers/usb/net/catc.c b/drivers/usb/net/catc.c
--- a/drivers/usb/net/catc.c	2005-03-24 18:21:08 -08:00
+++ b/drivers/usb/net/catc.c	2005-03-24 18:21:08 -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-24 18:21:08 -08:00
+++ b/drivers/usb/net/kaweth.c	2005-03-24 18:21:08 -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-24 18:21:08 -08:00
+++ b/drivers/usb/net/kawethfw.h	2005-03-24 18:21:08 -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-24 18:21:08 -08:00
+++ b/drivers/usb/net/pegasus.c	2005-03-24 18:21:08 -08:00
@@ -85,6 +85,11 @@
 MODULE_PARM_DESC(loopback, "Enable MAC loopback mode (bit 0)");
 MODULE_PARM_DESC(mii_mode, "Enable HomePNA mode (bit 0),default=MII mode = 0");
 
+/* use ethtool to change the level for any given device */
+static int msg_level = -1;
+module_param (msg_level, int, 0);
+MODULE_PARM_DESC (msg_level, "Override default message level");
+
 MODULE_DEVICE_TABLE(usb, pegasus_ids);
 
 static int update_eth_regs_async(pegasus_t *);
@@ -110,7 +115,9 @@
 	case -ENOENT:
 		break;
 	default:
-		warn("%s: status %d", __FUNCTION__, urb->status);
+		if (netif_msg_drv(pegasus))
+			dev_err(&pegasus->intf->dev, "%s, status %d\n",
+				__FUNCTION__, urb->status);
 	}
 	pegasus->flags &= ~ETH_REGS_CHANGED;
 	wake_up(&pegasus->ctrl_wait);
@@ -125,7 +132,9 @@
 
 	buffer = kmalloc(size, GFP_KERNEL);
 	if (!buffer) {
-		warn("%s: looks like we're out of memory", __FUNCTION__);
+		if (netif_msg_drv(pegasus))
+			dev_warn(&pegasus->intf->dev, "out of memory in %s\n",
+					__FUNCTION__);
 		return -ENOMEM;
 	}
 	add_wait_queue(&pegasus->ctrl_wait, &wait);
@@ -152,7 +161,9 @@
 
 	/* using ATOMIC, we'd never wake up if we slept */
 	if ((ret = usb_submit_urb(pegasus->ctrl_urb, GFP_ATOMIC))) {
-		err("%s: BAD CTRLs %d", __FUNCTION__, ret);
+		if (netif_msg_drv(pegasus))
+			dev_err(&pegasus->intf->dev, "%s, status %d\n",
+					__FUNCTION__, ret);
 		goto out;
 	}
 
@@ -174,7 +185,9 @@
 
 	buffer = kmalloc(size, GFP_KERNEL);
 	if (!buffer) {
-		warn("%s: looks like we're out of memory", __FUNCTION__);
+		if (netif_msg_drv(pegasus))
+			dev_warn(&pegasus->intf->dev, "out of memory in %s\n",
+					__FUNCTION__);
 		return -ENOMEM;
 	}
 	memcpy(buffer, data, size);
@@ -202,7 +215,9 @@
 	set_current_state(TASK_UNINTERRUPTIBLE);
 
 	if ((ret = usb_submit_urb(pegasus->ctrl_urb, GFP_ATOMIC))) {
-		err("%s: BAD CTRL %d", __FUNCTION__, ret);
+		if (netif_msg_drv(pegasus))
+			dev_err(&pegasus->intf->dev, "%s, status %d\n",
+					__FUNCTION__, ret);
 		goto out;
 	}
 
@@ -222,7 +237,9 @@
 
 	tmp = kmalloc(1, GFP_KERNEL);
 	if (!tmp) {
-		warn("%s: looks like we're out of memory", __FUNCTION__);
+		if (netif_msg_drv(pegasus))
+			dev_warn(&pegasus->intf->dev, "out of memory in %s\n",
+					__FUNCTION__);
 		return -ENOMEM;
 	}
 	memcpy(tmp, &data, 1);
@@ -249,7 +266,9 @@
 	set_current_state(TASK_UNINTERRUPTIBLE);
 
 	if ((ret = usb_submit_urb(pegasus->ctrl_urb, GFP_ATOMIC))) {
-		err("%s: BAD CTRL %d", __FUNCTION__, ret);
+		if (netif_msg_drv(pegasus))
+			dev_err(&pegasus->intf->dev, "%s, status %d\n",
+					__FUNCTION__, ret);
 		goto out;
 	}
 
@@ -278,8 +297,9 @@
 			     pegasus->eth_regs, 3, ctrl_callback, pegasus);
 
 	if ((ret = usb_submit_urb(pegasus->ctrl_urb, GFP_ATOMIC)))
-		err("%s: BAD CTRL %d, flgs %x", __FUNCTION__, ret,
-		    pegasus->flags);
+		if (netif_msg_drv(pegasus))
+			dev_err(&pegasus->intf->dev, "%s, status %d\n",
+					__FUNCTION__, ret);
 
 	return ret;
 }
@@ -289,21 +309,23 @@
 	int i;
 	__u8 data[4] = { phy, 0, 0, indx };
 	__le16 regdi;
+	int ret;
 
-	set_register(pegasus, PhyCtrl, 0);
-	set_registers(pegasus, PhyAddr, sizeof (data), data);
-	set_register(pegasus, PhyCtrl, (indx | PHY_READ));
+	ret = set_register(pegasus, PhyCtrl, 0);
+	ret = set_registers(pegasus, PhyAddr, sizeof (data), data);
+	ret = set_register(pegasus, PhyCtrl, (indx | PHY_READ));
 	for (i = 0; i < REG_TIMEOUT; i++) {
-		get_registers(pegasus, PhyCtrl, 1, data);
+		ret = get_registers(pegasus, PhyCtrl, 1, data);
 		if (data[0] & PHY_DONE)
 			break;
 	}
 	if (i < REG_TIMEOUT) {
-		get_registers(pegasus, PhyData, 2, &regdi);
+		ret = get_registers(pegasus, PhyData, 2, &regdi);
 		*regd = le16_to_cpu(regdi);
 		return 1;
 	}
-	warn("%s: failed", __FUNCTION__);
+	if (netif_msg_drv(pegasus))
+		dev_warn(&pegasus->intf->dev, "fail %s\n", __FUNCTION__);
 
 	return 0;
 }
@@ -311,7 +333,7 @@
 static int mdio_read(struct net_device *dev, int phy_id, int loc)
 {
 	pegasus_t *pegasus = (pegasus_t *) netdev_priv(dev);
-	__le16 res;
+	u16 res;
 
 	read_mii_word(pegasus, phy_id, loc, &res);
 	return (int)res;
@@ -321,20 +343,23 @@
 {
 	int i;
 	__u8 data[4] = { phy, 0, 0, indx };
+	int ret;
 
-	*(data + 1) = cpu_to_le16p(&regd);
-	set_register(pegasus, PhyCtrl, 0);
-	set_registers(pegasus, PhyAddr, sizeof(data), data);
-	set_register(pegasus, PhyCtrl, (indx | PHY_WRITE));
+	data[1] = (u8) regd;
+	data[2] = (u8) (regd >> 8);
+	ret = set_register(pegasus, PhyCtrl, 0);
+	ret = set_registers(pegasus, PhyAddr, sizeof(data), data);
+	ret = set_register(pegasus, PhyCtrl, (indx | PHY_WRITE));
 	for (i = 0; i < REG_TIMEOUT; i++) {
-		get_registers(pegasus, PhyCtrl, 1, data);
+		ret = get_registers(pegasus, PhyCtrl, 1, data);
 		if (data[0] & PHY_DONE)
 			break;
 	}
 	if (i < REG_TIMEOUT)
 		return 0;
-	warn("%s: failed", __FUNCTION__);
 
+	if (netif_msg_drv(pegasus))
+		dev_warn(&pegasus->intf->dev, "fail %s\n", __FUNCTION__);
 	return 1;
 }
 
@@ -350,23 +375,25 @@
 	int i;
 	__u8 tmp;
 	__le16 retdatai;
+	int ret;
 
-	set_register(pegasus, EpromCtrl, 0);
-	set_register(pegasus, EpromOffset, index);
-	set_register(pegasus, EpromCtrl, EPROM_READ);
+	ret = set_register(pegasus, EpromCtrl, 0);
+	ret = set_register(pegasus, EpromOffset, index);
+	ret = set_register(pegasus, EpromCtrl, EPROM_READ);
 
 	for (i = 0; i < REG_TIMEOUT; i++) {
-		get_registers(pegasus, EpromCtrl, 1, &tmp);
+		ret = get_registers(pegasus, EpromCtrl, 1, &tmp);
 		if (tmp & EPROM_DONE)
 			break;
 	}
 	if (i < REG_TIMEOUT) {
-		get_registers(pegasus, EpromData, 2, &retdatai);
+		ret = get_registers(pegasus, EpromData, 2, &retdatai);
 		*retdata = le16_to_cpu(retdatai);
 		return 0;
 	}
-	warn("%s: failed", __FUNCTION__);
 
+	if (netif_msg_drv(pegasus))
+		dev_warn(&pegasus->intf->dev, "fail %s\n", __FUNCTION__);
 	return -1;
 }
 
@@ -374,40 +401,44 @@
 static inline void enable_eprom_write(pegasus_t * pegasus)
 {
 	__u8 tmp;
+	int ret;
 
-	get_registers(pegasus, EthCtrl2, 1, &tmp);
-	set_register(pegasus, EthCtrl2, tmp | EPROM_WR_ENABLE);
+	ret = get_registers(pegasus, EthCtrl2, 1, &tmp);
+	ret = set_register(pegasus, EthCtrl2, tmp | EPROM_WR_ENABLE);
 }
 
 static inline void disable_eprom_write(pegasus_t * pegasus)
 {
 	__u8 tmp;
+	int ret;
 
-	get_registers(pegasus, EthCtrl2, 1, &tmp);
-	set_register(pegasus, EpromCtrl, 0);
-	set_register(pegasus, EthCtrl2, tmp & ~EPROM_WR_ENABLE);
+	ret = get_registers(pegasus, EthCtrl2, 1, &tmp);
+	ret = set_register(pegasus, EpromCtrl, 0);
+	ret = set_register(pegasus, EthCtrl2, tmp & ~EPROM_WR_ENABLE);
 }
 
 static int write_eprom_word(pegasus_t * pegasus, __u8 index, __u16 data)
 {
 	int i;
 	__u8 tmp, d[4] = { 0x3f, 0, 0, EPROM_WRITE };
+	int ret;
 
-	set_registers(pegasus, EpromOffset, 4, d);
+	ret = set_registers(pegasus, EpromOffset, 4, d);
 	enable_eprom_write(pegasus);
-	set_register(pegasus, EpromOffset, index);
-	set_registers(pegasus, EpromData, 2, &data);
-	set_register(pegasus, EpromCtrl, EPROM_WRITE);
+	ret = set_register(pegasus, EpromOffset, index);
+	ret = set_registers(pegasus, EpromData, 2, &data);
+	ret = set_register(pegasus, EpromCtrl, EPROM_WRITE);
 
 	for (i = 0; i < REG_TIMEOUT; i++) {
-		get_registers(pegasus, EpromCtrl, 1, &tmp);
+		ret = get_registers(pegasus, EpromCtrl, 1, &tmp);
 		if (tmp & EPROM_DONE)
 			break;
 	}
 	disable_eprom_write(pegasus);
 	if (i < REG_TIMEOUT)
 		return 0;
-	warn("%s: failed", __FUNCTION__);
+	if (netif_msg_drv(pegasus))
+		dev_warn(&pegasus->intf->dev, "fail %s\n", __FUNCTION__);
 	return -1;
 }
 #endif				/* PEGASUS_WRITE_EEPROM */
@@ -426,9 +457,10 @@
 static void set_ethernet_addr(pegasus_t * pegasus)
 {
 	__u8 node_id[6];
+	int ret;
 
 	get_node_id(pegasus, node_id);
-	set_registers(pegasus, EthID, sizeof (node_id), node_id);
+	ret = set_registers(pegasus, EthID, sizeof (node_id), node_id);
 	memcpy(pegasus->net->dev_addr, node_id, sizeof (node_id));
 }
 
@@ -436,19 +468,20 @@
 {
 	__u8 data = 0x8;
 	int i;
+	int ret;
 
-	set_register(pegasus, EthCtrl1, data);
+	ret = set_register(pegasus, EthCtrl1, data);
 	for (i = 0; i < REG_TIMEOUT; i++) {
-		get_registers(pegasus, EthCtrl1, 1, &data);
+		ret = get_registers(pegasus, EthCtrl1, 1, &data);
 		if (~data & 0x08) {
 			if (loopback & 1)
 				break;
 			if (mii_mode && (pegasus->features & HAS_HOME_PNA))
-				set_register(pegasus, Gpio1, 0x34);
+				ret = set_register(pegasus, Gpio1, 0x34);
 			else
-				set_register(pegasus, Gpio1, 0x26);
-			set_register(pegasus, Gpio0, pegasus->features);
-			set_register(pegasus, Gpio0, DEFAULT_GPIO_SET);
+				ret = set_register(pegasus, Gpio1, 0x26);
+			ret = set_register(pegasus, Gpio0, pegasus->features);
+			ret = set_register(pegasus, Gpio0, DEFAULT_GPIO_SET);
 			break;
 		}
 	}
@@ -457,8 +490,8 @@
 
 	if (usb_dev_id[pegasus->dev_index].vendor == VENDOR_LINKSYS ||
 	    usb_dev_id[pegasus->dev_index].vendor == VENDOR_DLINK) {
-		set_register(pegasus, Gpio0, 0x24);
-		set_register(pegasus, Gpio0, 0x26);
+		ret = set_register(pegasus, Gpio0, 0x24);
+		ret = set_register(pegasus, Gpio0, 0x26);
 	}
 	if (usb_dev_id[pegasus->dev_index].vendor == VENDOR_ELCON) {
 		__u16 auxmode;
@@ -474,6 +507,7 @@
 	__u16 linkpart;
 	__u8 data[4];
 	pegasus_t *pegasus = netdev_priv(dev);
+	int ret;
 
 	read_mii_word(pegasus, pegasus->phy, MII_LPA, &linkpart);
 	data[0] = 0xc9;
@@ -487,7 +521,7 @@
 	data[2] = (loopback & 1) ? 0x09 : 0x01;
 
 	memcpy(pegasus->eth_regs, data, sizeof (data));
-	set_registers(pegasus, EthCtrl0, 3, data);
+	ret = set_registers(pegasus, EthCtrl0, 3, data);
 
 	if (usb_dev_id[pegasus->dev_index].vendor == VENDOR_LINKSYS ||
 	    usb_dev_id[pegasus->dev_index].vendor == VENDOR_DLINK) {
@@ -550,48 +584,56 @@
 	pegasus_t *pegasus = urb->context;
 	struct net_device *net;
 	int rx_status, count = urb->actual_length;
+	u8 *buf = urb->transfer_buffer;
 	__u16 pkt_len;
 
-	if (!pegasus || !(pegasus->flags & PEGASUS_RUNNING))
+	if (!pegasus)
 		return;
 
 	net = pegasus->net;
-	if (!netif_device_present(net))
+	if (!netif_device_present(net) || !netif_running(net))
 		return;
 
 	switch (urb->status) {
 	case 0:
 		break;
 	case -ETIMEDOUT:
-		dbg("%s: reset MAC", net->name);
+		if (netif_msg_rx_err(pegasus))
+			pr_debug("%s: reset MAC\n", net->name);
 		pegasus->flags &= ~PEGASUS_RX_BUSY;
 		break;
 	case -EPIPE:		/* stall, or disconnect from TT */
 		/* FIXME schedule work to clear the halt */
-		warn("%s: no rx stall recovery", net->name);
+		if (netif_msg_rx_err(pegasus))
+			printk(KERN_WARNING "%s: no rx stall recovery\n",
+					net->name);
 		return;
 	case -ENOENT:
 	case -ECONNRESET:
 	case -ESHUTDOWN:
-		dbg("%s: rx unlink, %d", net->name, urb->status);
+		if (netif_msg_ifdown(pegasus))
+			pr_debug("%s: rx unlink, %d\n", net->name, urb->status);
 		return;
 	default:
-		dbg("%s: RX status %d", net->name, urb->status);
+		if (netif_msg_rx_err(pegasus))
+			pr_debug("%s: RX status %d\n", net->name, urb->status);
 		goto goon;
 	}
 
-	if (!count)
+	if (!count || count < 4)
 		goto goon;
 
-	rx_status = le32_to_cpu(*(__le32 *) (urb->transfer_buffer + count - 4));
-	if (rx_status & 0x000e0000) {
-		dbg("%s: RX packet error %x", net->name, rx_status & 0xe0000);
+	rx_status = buf[count - 2];
+	if (rx_status & 0x1e) {
+		if (netif_msg_rx_err(pegasus))
+			pr_debug("%s: RX packet error %x\n",
+					net->name, rx_status);
 		pegasus->stats.rx_errors++;
-		if (rx_status & 0x060000)
+		if (rx_status & 0x06)	// long or runt
 			pegasus->stats.rx_length_errors++;
-		if (rx_status & 0x080000)
+		if (rx_status & 0x08)
 			pegasus->stats.rx_crc_errors++;
-		if (rx_status & 0x100000)
+		if (rx_status & 0x10)	// extra bits
 			pegasus->stats.rx_frame_errors++;
 		goto goon;
 	}
@@ -600,7 +642,10 @@
 		pkt_len &= 0x0fff;
 		pegasus->rx_skb->data += 2;
 	} else {
-		pkt_len = (rx_status & 0xfff) - 8;
+		pkt_len = buf[count - 3] << 8;
+		pkt_len += buf[count - 4];
+		pkt_len &= 0xfff;
+		pkt_len -= 8;
 	}
 
 	/*
@@ -658,7 +703,9 @@
 		pegasus->rx_skb = pull_skb(pegasus);
 	}
 	if (pegasus->rx_skb == NULL) {
-		warn("wow, low on memory");
+		if (netif_msg_rx_err(pegasus))
+			printk(KERN_WARNING "%s: low on memory\n",
+					pegasus->net->name);
 		tasklet_schedule(&pegasus->rx_tl);
 		goto done;
 	}
@@ -682,25 +729,29 @@
 	pegasus_t *pegasus = urb->context;
 	struct net_device *net = pegasus->net;
 
-	if (!pegasus || !(pegasus->flags & PEGASUS_RUNNING))
+	if (!pegasus)
 		return;
 
-	if (!netif_device_present(net))
+	if (!netif_device_present(net) || !netif_running(net))
 		return;
 
 	switch (urb->status) {
 	case -EPIPE:
 		/* FIXME schedule_work() to clear the tx halt */
 		netif_stop_queue(net);
-		warn("%s: no tx stall recovery", net->name);
+		if (netif_msg_tx_err(pegasus))
+			printk(KERN_WARNING "%s: no tx stall recovery\n",
+					net->name);
 		return;
 	case -ENOENT:
 	case -ECONNRESET:
 	case -ESHUTDOWN:
-		dbg("%s: tx unlink, %d", net->name, urb->status);
+		if (netif_msg_ifdown(pegasus))
+			pr_debug("%s: tx unlink, %d\n", net->name, urb->status);
 		return;
 	default:
-		info("%s: TX status %d", net->name, urb->status);
+		if (netif_msg_tx_err(pegasus))
+			pr_info("%s: TX status %d\n", net->name, urb->status);
 		/* FALL THROUGH */
 	case 0:
 		break;
@@ -731,7 +782,9 @@
 		/* some Pegasus-I products report LOTS of data
 		 * toggle errors... avoid log spamming
 		 */
-		pr_debug("%s: intr status %d\n", net->name, urb->status);
+		if (netif_msg_timer(pegasus))
+			pr_debug("%s: intr status %d\n", net->name,
+					urb->status);
 	}
 
 	if (urb->actual_length >= 6) {
@@ -763,7 +816,7 @@
 	}
 
 	status = usb_submit_urb(urb, SLAB_ATOMIC);
-	if (status)
+	if (status && netif_msg_timer(pegasus))
 		printk(KERN_ERR "%s: can't resubmit interrupt urb, %d\n",
 				net->name, status);
 }
@@ -771,7 +824,8 @@
 static void pegasus_tx_timeout(struct net_device *net)
 {
 	pegasus_t *pegasus = netdev_priv(net);
-	printk(KERN_WARNING "%s: tx timeout\n", net->name);
+	if (netif_msg_timer(pegasus))
+		printk(KERN_WARNING "%s: tx timeout\n", net->name);
 	pegasus->tx_urb->transfer_flags |= URB_ASYNC_UNLINK;
 	usb_unlink_urb(pegasus->tx_urb);
 	pegasus->stats.tx_errors++;
@@ -793,7 +847,9 @@
 			  pegasus->tx_buff, count,
 			  write_bulk_callback, pegasus);
 	if ((res = usb_submit_urb(pegasus->tx_urb, GFP_ATOMIC))) {
-		warn("failed tx_urb %d", res);
+		if (netif_msg_tx_err(pegasus))
+			printk(KERN_WARNING "%s: fail tx, %d\n",
+					net->name, res);
 		switch (res) {
 		case -EPIPE:		/* stall, or disconnect from TT */
 			/* cleanup should already have been scheduled */
@@ -822,8 +878,9 @@
 static inline void disable_net_traffic(pegasus_t * pegasus)
 {
 	int tmp = 0;
+	int ret;
 
-	set_registers(pegasus, EthCtrl0, 2, &tmp);
+	ret = set_registers(pegasus, EthCtrl0, 2, &tmp);
 }
 
 static inline void get_interrupt_interval(pegasus_t * pegasus)
@@ -832,8 +889,10 @@
 
 	read_eprom_word(pegasus, 4, (__u16 *) data);
 	if (data[1] < 0x80) {
-		info("intr interval will be changed from %ums to %ums",
-		     data[1], 0x80);
+		if (netif_msg_timer(pegasus))
+			dev_info(&pegasus->intf->dev,
+				"intr interval changed from %ums to %ums\n",
+				data[1], 0x80);
 		data[1] = 0x80;
 #ifdef	PEGASUS_WRITE_EEPROM
 		write_eprom_word(pegasus, 4, *(__u16 *) data);
@@ -845,7 +904,7 @@
 static void set_carrier(struct net_device *net)
 {
 	pegasus_t *pegasus = netdev_priv(net);
-	__le16 tmp;
+	u16 tmp;
 
 	if (read_mii_word(pegasus, pegasus->phy, MII_BMSR, &tmp))
 		return;
@@ -912,24 +971,32 @@
 	if (!pegasus->rx_skb)
 		return -ENOMEM;
 
-	set_registers(pegasus, EthID, 6, net->dev_addr);
+	res = set_registers(pegasus, EthID, 6, net->dev_addr);
 	
 	usb_fill_bulk_urb(pegasus->rx_urb, pegasus->usb,
 			  usb_rcvbulkpipe(pegasus->usb, 1),
 			  pegasus->rx_skb->data, PEGASUS_MTU + 8,
 			  read_bulk_callback, pegasus);
-	if ((res = usb_submit_urb(pegasus->rx_urb, GFP_KERNEL)))
-		warn("%s: failed rx_urb %d", __FUNCTION__, res);
+	if ((res = usb_submit_urb(pegasus->rx_urb, GFP_KERNEL))) {
+		if (netif_msg_ifup(pegasus))
+			pr_debug("%s: failed rx_urb, %d", net->name, res);
+		goto exit;
+	}
+
 	usb_fill_int_urb(pegasus->intr_urb, pegasus->usb,
 			 usb_rcvintpipe(pegasus->usb, 3),
 			 pegasus->intr_buff, sizeof (pegasus->intr_buff),
 			 intr_callback, pegasus, pegasus->intr_interval);
-	if ((res = usb_submit_urb(pegasus->intr_urb, GFP_KERNEL)))
-		warn("%s: failed intr_urb %d", __FUNCTION__, res);
-	netif_start_queue(net);
-	pegasus->flags |= PEGASUS_RUNNING;
+	if ((res = usb_submit_urb(pegasus->intr_urb, GFP_KERNEL))) {
+		if (netif_msg_ifup(pegasus))
+			pr_debug("%s: failed intr_urb, %d\n", net->name, res);
+		usb_kill_urb(pegasus->rx_urb);
+		goto exit;
+	}
 	if ((res = enable_net_traffic(net, pegasus->usb))) {
-		err("can't enable_net_traffic() - %d", res);
+		if (netif_msg_ifup(pegasus))
+			pr_debug("%s: can't enable_net_traffic() - %d\n",
+					net->name, res);
 		res = -EIO;
 		usb_kill_urb(pegasus->rx_urb);
 		usb_kill_urb(pegasus->intr_urb);
@@ -937,6 +1004,9 @@
 		goto exit;
 	}
 	set_carrier(net);
+	netif_start_queue(net);
+	if (netif_msg_ifup(pegasus))
+		pr_debug("%s: open\n", net->name);
 	res = 0;
 exit:
 	return res;
@@ -946,7 +1016,6 @@
 {
 	pegasus_t *pegasus = netdev_priv(net);
 
-	pegasus->flags &= ~PEGASUS_RUNNING;
 	netif_stop_queue(net);
 	if (!(pegasus->flags & PEGASUS_UNPLUG))
 		disable_net_traffic(pegasus);
@@ -956,7 +1025,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);
@@ -989,6 +1059,7 @@
 		reg78 |= 0x80;
 	if (wol->wolopts & WAKE_PHY)
 		reg78 |= 0x40;
+	/* FIXME this 0x10 bit still needs to get set in the chip... */
 	if (wol->wolopts)
 		pegasus->eth_regs[0] |= 0x10;
 	else
@@ -1041,13 +1112,13 @@
 static u32 pegasus_get_msglevel(struct net_device *dev)
 {
 	pegasus_t *pegasus = netdev_priv(dev);
-	return pegasus->msg_level;
+	return pegasus->msg_enable;
 }
 
 static void pegasus_set_msglevel(struct net_device *dev, u32 v)
 {
 	pegasus_t *pegasus = netdev_priv(dev);
-	pegasus->msg_level = v;
+	pegasus->msg_enable = v;
 }
 
 static struct ethtool_ops ops = {
@@ -1093,12 +1164,14 @@
 
 	if (net->flags & IFF_PROMISC) {
 		pegasus->eth_regs[EthCtrl2] |= RX_PROMISCUOUS;
-		pr_info("%s: Promiscuous mode enabled.\n", net->name);
+		if (netif_msg_link(pegasus))
+			pr_info("%s: Promiscuous mode enabled.\n", net->name);
 	} else if ((net->mc_count > multicast_filter_limit) ||
 		   (net->flags & IFF_ALLMULTI)) {
 		pegasus->eth_regs[EthCtrl0] |= RX_MULTICAST;
 		pegasus->eth_regs[EthCtrl2] &= ~RX_PROMISCUOUS;
-		pr_info("%s: set allmulti\n", net->name);
+		if (netif_msg_link(pegasus))
+			pr_info("%s: set allmulti\n", net->name);
 	} else {
 		pegasus->eth_regs[EthCtrl0] &= ~RX_MULTICAST;
 		pegasus->eth_regs[EthCtrl2] &= ~RX_PROMISCUOUS;
@@ -1127,17 +1200,18 @@
 static inline void setup_pegasus_II(pegasus_t * pegasus)
 {
 	__u8 data = 0xa5;
+	int ret;
 	
-	set_register(pegasus, Reg1d, 0);
-	set_register(pegasus, Reg7b, 1);
+	ret = set_register(pegasus, Reg1d, 0);
+	ret = set_register(pegasus, Reg7b, 1);
 	mdelay(100);
 	if ((pegasus->features & HAS_HOME_PNA) && mii_mode)
-		set_register(pegasus, Reg7b, 0);
+		ret = set_register(pegasus, Reg7b, 0);
 	else
-		set_register(pegasus, Reg7b, 2);
+		ret = set_register(pegasus, Reg7b, 2);
 
-	set_register(pegasus, 0x83, data);
-	get_registers(pegasus, 0x83, 1, &data);
+	ret = set_register(pegasus, 0x83, data);
+	ret = get_registers(pegasus, 0x83, 1, &data);
 
 	if (data == 0xa5) {
 		pegasus->chip = 0x8513;
@@ -1145,21 +1219,21 @@
 		pegasus->chip = 0;
 	}
 
-	set_register(pegasus, 0x80, 0xc0);
-	set_register(pegasus, 0x83, 0xff);
-	set_register(pegasus, 0x84, 0x01);
+	ret = set_register(pegasus, 0x80, 0xc0);
+	ret = set_register(pegasus, 0x83, 0xff);
+	ret = set_register(pegasus, 0x84, 0x01);
 	
 	if (pegasus->features & HAS_HOME_PNA && mii_mode)
-		set_register(pegasus, Reg81, 6);
+		ret = set_register(pegasus, Reg81, 6);
 	else
-		set_register(pegasus, Reg81, 2);
+		ret = set_register(pegasus, Reg81, 2);
 }
 
 
-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);
@@ -1181,7 +1255,7 @@
 	usb_get_dev(dev);
 	net = alloc_etherdev(sizeof(struct pegasus));
 	if (!net) {
-		err("out of memory allocating device structure");
+		dev_err(&intf->dev, "can't allocate %s\n", "device");
 		goto out;
 	}
 
@@ -1190,13 +1264,16 @@
 	pegasus->dev_index = dev_index;
 	init_waitqueue_head(&pegasus->ctrl_wait);
 
-	if (!alloc_urbs(pegasus))
+	if (!alloc_urbs(pegasus)) {
+		dev_err(&intf->dev, "can't allocate %s\n", "urbs");
 		goto out1;
+	}
 
 	tasklet_init(&pegasus->rx_tl, rx_fixup, (unsigned long) pegasus);
 
 	INIT_WORK(&pegasus->carrier_check, check_carrier, pegasus);
 
+	pegasus->intf = intf;
 	pegasus->usb = dev;
 	pegasus->net = net;
 	SET_MODULE_OWNER(net);
@@ -1215,6 +1292,8 @@
 	pegasus->mii.phy_id_mask = 0x1f;
 	pegasus->mii.reg_num_mask = 0x1f;
 	spin_lock_init(&pegasus->rx_pool_lock);
+	pegasus->msg_enable = netif_msg_init (msg_level, NETIF_MSG_DRV
+				| NETIF_MSG_PROBE | NETIF_MSG_LINK);
 
 	pegasus->features = usb_dev_id[dev_index].private;
 	get_interrupt_interval(pegasus);
@@ -1241,8 +1320,15 @@
 	res = register_netdev(net);
 	if (res)
 		goto out3;
-	queue_delayed_work(pegasus_workqueue, &pegasus->carrier_check, CARRIER_CHECK_DELAY);
-	pr_info("%s: %s\n", net->name, usb_dev_id[dev_index].name);
+	queue_delayed_work(pegasus_workqueue, &pegasus->carrier_check,
+				CARRIER_CHECK_DELAY);
+
+	dev_info(&intf->dev, "%s, %s, %02x:%02x:%02x:%02x:%02x:%02x\n",
+		net->name,
+		usb_dev_id[dev_index].name,
+		net->dev_addr [0], net->dev_addr [1],
+		net->dev_addr [2], net->dev_addr [3],
+		net->dev_addr [4], net->dev_addr [5]);
 	return 0;
 
 out3:
@@ -1263,7 +1349,7 @@
 
 	usb_set_intfdata(intf, NULL);
 	if (!pegasus) {
-		warn("unregistering non-existent device");
+		dev_dbg(&intf->dev, "unregistering non-bound device?\n");
 		return;
 	}
 
diff -Nru a/drivers/usb/net/pegasus.h b/drivers/usb/net/pegasus.h
--- a/drivers/usb/net/pegasus.h	2005-03-24 18:21:08 -08:00
+++ b/drivers/usb/net/pegasus.h	2005-03-24 18:21:08 -08:00
@@ -29,7 +29,6 @@
 #define	DEFAULT_GPIO_SET	0x26
 
 #define	PEGASUS_PRESENT		0x00000001
-#define	PEGASUS_RUNNING		0x00000002
 #define	PEGASUS_TX_BUSY		0x00000004
 #define	PEGASUS_RX_BUSY		0x00000008
 #define	CTRL_URB_RUNNING	0x00000010
@@ -86,12 +85,13 @@
 
 typedef struct pegasus {
 	struct usb_device	*usb;
+	struct usb_interface	*intf;
 	struct net_device	*net;
 	struct net_device_stats	stats;
 	struct mii_if_info	mii;
 	unsigned		flags;
 	unsigned		features;
-	u32			msg_level;
+	u32			msg_enable;
 	u32			wolopts;
 	int			dev_index;
 	int			intr_interval;
diff -Nru a/drivers/usb/net/usbnet.c b/drivers/usb/net/usbnet.c
--- a/drivers/usb/net/usbnet.c	2005-03-24 18:21:08 -08:00
+++ b/drivers/usb/net/usbnet.c	2005-03-24 18:21:08 -08:00
@@ -185,13 +185,14 @@
 
 	// i/o info: pipes etc
 	unsigned		in, out;
+	struct usb_host_endpoint *status;
 	unsigned		maxpacket;
 	struct timer_list	delay;
 
 	// protocol/interface state
 	struct net_device	*net;
 	struct net_device_stats	stats;
-	int			msg_level;
+	int			msg_enable;
 	unsigned long		data [5];
 
 	struct mii_if_info	mii;
@@ -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);
 
@@ -272,9 +278,9 @@
 static const char driver_name [] = "usbnet";
 
 /* use ethtool to change the level for any given device */
-static int msg_level = 1;
+static int msg_level = -1;
 module_param (msg_level, int, 0);
-MODULE_PARM_DESC (msg_level, "Initial message level (default = 1)");
+MODULE_PARM_DESC (msg_level, "Override default message level");
 
 
 #ifdef DEBUG
@@ -290,9 +296,7 @@
 	printk(KERN_WARNING "%s: " fmt "\n" , (usbnet)->net->name , ## arg)
 
 #define devinfo(usbnet, fmt, arg...) \
-	do { if ((usbnet)->msg_level >= 1) \
 	printk(KERN_INFO "%s: " fmt "\n" , (usbnet)->net->name , ## arg); \
-	} while (0)
 
 /*-------------------------------------------------------------------------*/
 
@@ -312,38 +316,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 +374,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 0;
+
+	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;
@@ -368,13 +425,12 @@
 	dev->stats.rx_packets++;
 	dev->stats.rx_bytes += skb->len;
 
-#ifdef	VERBOSE
-	devdbg (dev, "< rx, len %d, type 0x%x",
-		skb->len + sizeof (struct ethhdr), skb->protocol);
-#endif
+	if (netif_msg_rx_status (dev))
+		devdbg (dev, "< rx, len %d, type 0x%x",
+			skb->len + sizeof (struct ethhdr), skb->protocol);
 	memset (skb->cb, 0, sizeof (struct skb_data));
 	status = netif_rx (skb);
-	if (status != NET_RX_SUCCESS)
+	if (status != NET_RX_SUCCESS && netif_msg_rx_err (dev))
 		devdbg (dev, "netif_rx status %d", status);
 }
 
@@ -1414,6 +1470,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 +1521,56 @@
 	}
 }
 
+
+static void dumpspeed (struct usbnet *dev, __le32 *speeds)
+{
+	if (netif_msg_timer (dev))
+		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:
+		if (netif_msg_timer (dev))
+			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 */
+		if (netif_msg_timer (dev))
+			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 +1649,7 @@
 	// .check_connect = cdc_check_connect,
 	.bind =		cdc_bind,
 	.unbind =	cdc_unbind,
+	.status =	cdc_status,
 };
 
 #endif	/* CONFIG_USB_CDCETHER */
@@ -2051,7 +2181,8 @@
 
 static inline void nc_dump_usbctl (struct usbnet *dev, u16 usbctl)
 {
-#ifdef DEBUG
+	if (!netif_msg_link (dev))
+		return;
 	devdbg (dev, "net1080 %s-%s usbctl 0x%x:%s%s%s%s%s;"
 			" this%s%s;"
 			" other%s%s; r/o 0x%x",
@@ -2069,7 +2200,6 @@
 		(usbctl & USBCTL_DISCONN_THIS) ? " DIS" : "",
 		usbctl & ~USBCTL_WRITABLE_MASK
 		);
-#endif
 }
 
 /*-------------------------------------------------------------------------*/
@@ -2096,7 +2226,8 @@
 
 static inline void nc_dump_status (struct usbnet *dev, u16 status)
 {
-#ifdef DEBUG
+	if (!netif_msg_link (dev))
+		return;
 	devdbg (dev, "net1080 %s-%s status 0x%x:"
 			" this (%c) PKT=%d%s%s%s;"
 			" other PKT=%d%s%s%s; unspec 0x%x",
@@ -2119,7 +2250,6 @@
 
 		status & STATUS_UNSPEC_MASK
 		);
-#endif
 }
 
 /*-------------------------------------------------------------------------*/
@@ -2134,15 +2264,10 @@
 
 static inline void nc_dump_ttl (struct usbnet *dev, u16 ttl)
 {
-#ifdef DEBUG
-	devdbg (dev, "net1080 %s-%s ttl 0x%x this = %d, other = %d",
-		dev->udev->bus->bus_name, dev->udev->devpath,
-		ttl,
-
-		TTL_THIS (ttl),
-		TTL_OTHER (ttl)
-		);
-#endif
+	if (netif_msg_link (dev))
+		devdbg (dev, "net1080 %s-%s ttl 0x%x this = %d, other = %d",
+			dev->udev->bus->bus_name, dev->udev->devpath,
+			ttl, TTL_THIS (ttl), TTL_OTHER (ttl));
 }
 
 /*-------------------------------------------------------------------------*/
@@ -2164,14 +2289,14 @@
 		goto done;
 	}
 	status = *vp;
-	// nc_dump_status (dev, status);
+	nc_dump_status (dev, status);
 
 	if ((retval = nc_register_read (dev, REG_USBCTL, vp)) < 0) {
 		dbg ("can't read USBCTL, %d", retval);
 		goto done;
 	}
 	usbctl = *vp;
-	// nc_dump_usbctl (dev, usbctl);
+	nc_dump_usbctl (dev, usbctl);
 
 	nc_register_write (dev, REG_USBCTL,
 			USBCTL_FLUSH_THIS | USBCTL_FLUSH_OTHER);
@@ -2187,7 +2312,7 @@
 			MK_TTL (NC_READ_TTL_MS, TTL_OTHER (ttl)) );
 	dbg ("%s: assigned TTL, %d ms", dev->net->name, NC_READ_TTL_MS);
 
-	if (dev->msg_level >= 2)
+	if (netif_msg_link (dev))
 		devinfo (dev, "port %c, peer %sconnected",
 			(status & STATUS_PORT_A) ? 'A' : 'B',
 			(status & STATUS_CONN_OTHER) ? "" : "dis"
@@ -2268,7 +2393,8 @@
 			return;
 		}
 
-		devdbg (dev, "flush net1080; too many framing errors");
+		if (netif_msg_rx_err (dev))
+			devdbg (dev, "flush net1080; too many framing errors");
 		dev->frame_errors = 0;
 	}
 }
@@ -2526,11 +2652,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 +2714,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,
@@ -2715,7 +2854,8 @@
 		size = (sizeof (struct ethhdr) + dev->net->mtu);
 
 	if ((skb = alloc_skb (size + NET_IP_ALIGN, flags)) == NULL) {
-		devdbg (dev, "no rx skb");
+		if (netif_msg_rx_err (dev))
+			devdbg (dev, "no rx skb");
 		defer_kevent (dev, EVENT_RX_MEMORY);
 		usb_free_urb (urb);
 		return;
@@ -2745,18 +2885,21 @@
 			defer_kevent (dev, EVENT_RX_MEMORY);
 			break;
 		case -ENODEV:
-			devdbg (dev, "device gone");
+			if (netif_msg_ifdown (dev))
+				devdbg (dev, "device gone");
 			netif_device_detach (dev->net);
 			break;
 		default:
-			devdbg (dev, "rx submit, %d", retval);
+			if (netif_msg_rx_err (dev))
+				devdbg (dev, "rx submit, %d", retval);
 			tasklet_schedule (&dev->bh);
 			break;
 		case 0:
 			__skb_queue_tail (&dev->rxq, skb);
 		}
 	} else {
-		devdbg (dev, "rx: stopped");
+		if (netif_msg_ifdown (dev))
+			devdbg (dev, "rx: stopped");
 		retval = -ENOLINK;
 	}
 	spin_unlock_irqrestore (&dev->rxq.lock, lockflags);
@@ -2779,7 +2922,8 @@
 	if (skb->len)
 		skb_return (dev, skb);
 	else {
-		devdbg (dev, "drop");
+		if (netif_msg_rx_err (dev))
+			devdbg (dev, "drop");
 error:
 		dev->stats.rx_errors++;
 		skb_queue_tail (&dev->done, skb);
@@ -2806,7 +2950,8 @@
 			entry->state = rx_cleanup;
 			dev->stats.rx_errors++;
 			dev->stats.rx_length_errors++;
-			devdbg (dev, "rx length %d", skb->len);
+			if (netif_msg_rx_err (dev))
+				devdbg (dev, "rx length %d", skb->len);
 		}
 		break;
 
@@ -2822,9 +2967,8 @@
 	    // software-driven interface shutdown
 	    case -ECONNRESET:		// async unlink
 	    case -ESHUTDOWN:		// hardware gone
-#ifdef	VERBOSE
-		devdbg (dev, "rx shutdown, code %d", urb_status);
-#endif
+		if (netif_msg_ifdown (dev))
+			devdbg (dev, "rx shutdown, code %d", urb_status);
 		goto block;
 
 	    // we get controller i/o faults during khubd disconnect() delays.
@@ -2836,7 +2980,8 @@
 		dev->stats.rx_errors++;
 		if (!timer_pending (&dev->delay)) {
 			mod_timer (&dev->delay, jiffies + THROTTLE_JIFFIES);
-			devdbg (dev, "rx throttle %d", urb_status);
+			if (netif_msg_link (dev))
+				devdbg (dev, "rx throttle %d", urb_status);
 		}
 block:
 		entry->state = rx_cleanup;
@@ -2852,7 +2997,8 @@
 	    default:
 		entry->state = rx_cleanup;
 		dev->stats.rx_errors++;
-		devdbg (dev, "rx status %d", urb_status);
+		if (netif_msg_rx_err (dev))
+			devdbg (dev, "rx status %d", urb_status);
 		break;
 	}
 
@@ -2866,9 +3012,43 @@
 		}
 		usb_free_urb (urb);
 	}
-#ifdef	VERBOSE
-	devdbg (dev, "no read resubmitted");
-#endif /* VERBOSE */
+	if (netif_msg_rx_err (dev))
+		devdbg (dev, "no read resubmitted");
+}
+
+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
+		if (netif_msg_ifdown (dev))
+			devdbg (dev, "intr shutdown, code %d", status);
+		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 && netif_msg_timer (dev))
+		deverr(dev, "intr resubmit --> %d", status);
 }
 
 /*-------------------------------------------------------------------------*/
@@ -2917,7 +3097,7 @@
 
 	netif_stop_queue (net);
 
-	if (dev->msg_level >= 2)
+	if (netif_msg_ifdown (dev))
 		devinfo (dev, "stop stats: rx/tx %ld/%ld, errs %ld/%ld",
 			dev->stats.rx_packets, dev->stats.tx_packets, 
 			dev->stats.rx_errors, dev->stats.tx_errors
@@ -2933,11 +3113,14 @@
 			&& skb_queue_len (&dev->txq)
 			&& skb_queue_len (&dev->done)) {
 		msleep(UNLINK_TIMEOUT_MS);
-		devdbg (dev, "waited for %d urb completions", temp);
+		if (netif_msg_ifdown (dev))
+			devdbg (dev, "waited for %d urb completions", temp);
 	}
 	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.
@@ -2963,21 +3146,34 @@
 
 	// put into "known safe" state
 	if (info->reset && (retval = info->reset (dev)) < 0) {
-		devinfo (dev, "open reset fail (%d) usbnet usb-%s-%s, %s",
-			retval,
-			dev->udev->bus->bus_name, dev->udev->devpath,
+		if (netif_msg_ifup (dev))
+			devinfo (dev,
+				"open reset fail (%d) usbnet usb-%s-%s, %s",
+				retval,
+				dev->udev->bus->bus_name, dev->udev->devpath,
 			info->description);
 		goto done;
 	}
 
 	// insist peer be connected
 	if (info->check_connect && (retval = info->check_connect (dev)) < 0) {
-		devdbg (dev, "can't open; %d", retval);
+		if (netif_msg_ifup (dev))
+			devdbg (dev, "can't open; %d", retval);
 		goto done;
 	}
 
+	/* start any status interrupt transfer */
+	if (dev->interrupt) {
+		retval = usb_submit_urb (dev->interrupt, GFP_KERNEL);
+		if (retval < 0) {
+			if (netif_msg_ifup (dev))
+				deverr (dev, "intr submit %d", retval);
+			goto done;
+		}
+	}
+
 	netif_start_queue (net);
-	if (dev->msg_level >= 2) {
+	if (netif_msg_ifup (dev)) {
 		char	*framing;
 
 		if (dev->driver_info->flags & FLAG_FRAMING_NC)
@@ -3034,14 +3230,14 @@
 {
 	struct usbnet *dev = netdev_priv(net);
 
-	return dev->msg_level;
+	return dev->msg_enable;
 }
 
 static void usbnet_set_msglevel (struct net_device *net, u32 level)
 {
 	struct usbnet *dev = netdev_priv(net);
 
-	dev->msg_level = level;
+	dev->msg_enable = level;
 }
 
 static int usbnet_ioctl (struct net_device *net, struct ifreq *rq, int cmd)
@@ -3074,10 +3270,11 @@
 	if (test_bit (EVENT_TX_HALT, &dev->flags)) {
 		unlink_urbs (dev, &dev->txq);
 		status = usb_clear_halt (dev->udev, dev->out);
-		if (status < 0 && status != -EPIPE)
-			deverr (dev, "can't clear tx halt, status %d",
-				status);
-		else {
+		if (status < 0 && status != -EPIPE) {
+			if (netif_msg_tx_err (dev))
+				deverr (dev, "can't clear tx halt, status %d",
+					status);
+		} else {
 			clear_bit (EVENT_TX_HALT, &dev->flags);
 			netif_wake_queue (dev->net);
 		}
@@ -3085,10 +3282,11 @@
 	if (test_bit (EVENT_RX_HALT, &dev->flags)) {
 		unlink_urbs (dev, &dev->rxq);
 		status = usb_clear_halt (dev->udev, dev->in);
-		if (status < 0 && status != -EPIPE)
-			deverr (dev, "can't clear rx halt, status %d",
-				status);
-		else {
+		if (status < 0 && status != -EPIPE) {
+			if (netif_msg_rx_err (dev))
+				deverr (dev, "can't clear rx halt, status %d",
+					status);
+		} else {
 			clear_bit (EVENT_RX_HALT, &dev->flags);
 			tasklet_schedule (&dev->bh);
 		}
@@ -3133,6 +3331,11 @@
 			defer_kevent (dev, EVENT_TX_HALT);
 			break;
 
+		/* software-driven interface shutdown */
+		case -ECONNRESET:		// async unlink
+		case -ESHUTDOWN:		// hardware gone
+			break;
+
 		// like rx, tx gets controller i/o faults during khubd delays
 		// and so it uses the same throttling mechanism.
 		case -EPROTO:		// ehci
@@ -3141,12 +3344,15 @@
 			if (!timer_pending (&dev->delay)) {
 				mod_timer (&dev->delay,
 					jiffies + THROTTLE_JIFFIES);
-				devdbg (dev, "tx throttle %d", urb->status);
+				if (netif_msg_link (dev))
+					devdbg (dev, "tx throttle %d",
+							urb->status);
 			}
 			netif_stop_queue (dev->net);
 			break;
 		default:
-			devdbg (dev, "tx err %d", entry->urb->status);
+			if (netif_msg_tx_err (dev))
+				devdbg (dev, "tx err %d", entry->urb->status);
 			break;
 		}
 	}
@@ -3189,14 +3395,16 @@
 	if (info->tx_fixup) {
 		skb = info->tx_fixup (dev, skb, GFP_ATOMIC);
 		if (!skb) {
-			devdbg (dev, "can't tx_fixup skb");
+			if (netif_msg_tx_err (dev))
+				devdbg (dev, "can't tx_fixup skb");
 			goto drop;
 		}
 	}
 	length = skb->len;
 
 	if (!(urb = usb_alloc_urb (0, GFP_ATOMIC))) {
-		devdbg (dev, "no urb");
+		if (netif_msg_tx_err (dev))
+			devdbg (dev, "no urb");
 		goto drop;
 	}
 
@@ -3254,7 +3462,8 @@
 		defer_kevent (dev, EVENT_TX_HALT);
 		break;
 	default:
-		devdbg (dev, "tx: submit urb err %d", retval);
+		if (netif_msg_tx_err (dev))
+			devdbg (dev, "tx: submit urb err %d", retval);
 		break;
 	case 0:
 		net->trans_start = jiffies;
@@ -3265,18 +3474,17 @@
 	spin_unlock_irqrestore (&dev->txq.lock, flags);
 
 	if (retval) {
-		devdbg (dev, "drop, code %d", retval);
+		if (netif_msg_tx_err (dev))
+			devdbg (dev, "drop, code %d", retval);
 drop:
 		retval = NET_XMIT_SUCCESS;
 		dev->stats.tx_dropped++;
 		if (skb)
 			dev_kfree_skb_any (skb);
 		usb_free_urb (urb);
-#ifdef	VERBOSE
-	} else {
+	} else if (netif_msg_tx_queued (dev)) {
 		devdbg (dev, "> tx, len %d, type 0x%x",
 			length, skb->protocol);
-#endif
 	}
 	return retval;
 }
@@ -3333,7 +3541,7 @@
 				if (urb != NULL)
 					rx_submit (dev, urb, GFP_ATOMIC);
 			}
-			if (temp != dev->rxq.qlen)
+			if (temp != dev->rxq.qlen && netif_msg_link (dev))
 				devdbg (dev, "rxqlen %d --> %d",
 						temp, dev->rxq.qlen);
 			if (dev->rxq.qlen < qlen)
@@ -3367,9 +3575,10 @@
 
 	xdev = interface_to_usbdev (intf);
 
-	devinfo (dev, "unregister usbnet usb-%s-%s, %s",
-		xdev->bus->bus_name, xdev->devpath,
-		dev->driver_info->description);
+	if (netif_msg_probe (dev))
+		devinfo (dev, "unregister usbnet usb-%s-%s, %s",
+			xdev->bus->bus_name, xdev->devpath,
+			dev->driver_info->description);
 	
 	net = dev->net;
 	unregister_netdev (net);
@@ -3423,7 +3632,8 @@
 	dev = netdev_priv(net);
 	dev->udev = xdev;
 	dev->driver_info = info;
-	dev->msg_level = msg_level;
+	dev->msg_enable = netif_msg_init (msg_level, NETIF_MSG_DRV
+				| NETIF_MSG_PROBE | NETIF_MSG_LINK);
 	skb_queue_head_init (&dev->rxq);
 	skb_queue_head_init (&dev->txq);
 	skb_queue_head_init (&dev->done);
@@ -3442,7 +3652,7 @@
 #if 0
 // dma_supported() is deeply broken on almost all architectures
 	// possible with some EHCI controllers
-	if (dma_supported (&udev->dev, 0xffffffffffffffffULL))
+	if (dma_supported (&udev->dev, DMA_64BIT_MASK))
 		net->features |= NETIF_F_HIGHDMA;
 #endif
 
@@ -3479,6 +3689,9 @@
 			status = 0;
 
 	}
+
+	if (status == 0 && dev->status)
+		status = init_status (dev, udev);
 	if (status < 0)
 		goto out1;
 
@@ -3488,9 +3701,14 @@
 	status = register_netdev (net);
 	if (status)
 		goto out3;
-	devinfo (dev, "register usbnet at usb-%s-%s, %s",
-		xdev->bus->bus_name, xdev->devpath,
-		dev->driver_info->description);
+	if (netif_msg_probe (dev))
+		devinfo (dev, "register usbnet at usb-%s-%s, %s, "
+				"%02x:%02x:%02x:%02x:%02x:%02x",
+			xdev->bus->bus_name, xdev->devpath,
+			dev->driver_info->description,
+			net->dev_addr [0], net->dev_addr [1],
+			net->dev_addr [2], net->dev_addr [3],
+			net->dev_addr [4], net->dev_addr [5]);
 
 	// ok, it's ready to go.
 	usb_set_intfdata (udev, dev);
@@ -3729,6 +3947,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 +4005,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/net/zd1201.c b/drivers/usb/net/zd1201.c
--- a/drivers/usb/net/zd1201.c	2005-03-24 18:21:08 -08:00
+++ b/drivers/usb/net/zd1201.c	2005-03-24 18:21:08 -08:00
@@ -673,7 +673,7 @@
 		return 0;
 
 	err = zd1201_docmd(zd, ZD1201_CMDCODE_ENABLE, 0, 0, 0);
-	if (!err);
+	if (!err)
 		zd->mac_enabled = 1;
 
 	if (zd->monitor)
@@ -690,7 +690,7 @@
 		return 0;
 	if (zd->monitor) {
 		err = zd1201_setconfig16(zd, ZD1201_RID_PROMISCUOUSMODE, 0);
-		if (err);
+		if (err)
 			return err;
 	}
 
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-24 18:21:08 -08:00
+++ b/drivers/usb/serial/digi_acceleport.c	2005-03-24 18:21:08 -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-24 18:21:08 -08:00
+++ b/drivers/usb/serial/ftdi_sio.c	2005-03-24 18:21:08 -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-24 18:21:08 -08:00
+++ b/drivers/usb/serial/garmin_gps.c	2005-03-24 18:21:08 -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-24 18:21:08 -08:00
+++ b/drivers/usb/serial/ipw.c	2005-03-24 18:21:08 -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/mct_u232.c b/drivers/usb/serial/mct_u232.c
--- a/drivers/usb/serial/mct_u232.c	2005-03-24 18:21:08 -08:00
+++ b/drivers/usb/serial/mct_u232.c	2005-03-24 18:21:08 -08:00
@@ -195,16 +195,16 @@
 		}
 	} else {
 		switch (value) {
-		case    B300: value =     300;
-		case    B600: value =     600;
-		case   B1200: value =    1200;
-		case   B2400: value =    2400;
-		case   B4800: value =    4800;
-		case   B9600: value =    9600;
-		case  B19200: value =   19200;
-		case  B38400: value =   38400;
-		case  B57600: value =   57600;
-		case B115200: value =  115200;
+		case    B300: value =     300; break;
+		case    B600: value =     600; break;
+		case   B1200: value =    1200; break;
+		case   B2400: value =    2400; break;
+		case   B4800: value =    4800; break;
+		case   B9600: value =    9600; break;
+		case  B19200: value =   19200; break;
+		case  B38400: value =   38400; break;
+		case  B57600: value =   57600; break;
+		case B115200: value =  115200; break;
 		default:
 			err("MCT USB-RS232: unsupported baudrate request 0x%x,"
 			    " using default of B9600", value);
@@ -646,7 +646,7 @@
 	else
 		new_state &= ~(TIOCM_DTR | TIOCM_RTS);
 	if (new_state != control_state) {
-		mct_u232_set_modem_ctrl(serial, control_state);
+		mct_u232_set_modem_ctrl(serial, new_state);
 		control_state = new_state;
 	}
 
diff -Nru a/drivers/usb/serial/usb-serial.c b/drivers/usb/serial/usb-serial.c
--- a/drivers/usb/serial/usb-serial.c	2005-03-24 18:21:08 -08:00
+++ b/drivers/usb/serial/usb-serial.c	2005-03-24 18:21:08 -08:00
@@ -1418,11 +1418,11 @@
 
 /* If the usb-serial core is built into the core, the usb-serial drivers
    need these symbols to load properly as modules. */
-EXPORT_SYMBOL(usb_serial_register);
-EXPORT_SYMBOL(usb_serial_deregister);
-EXPORT_SYMBOL(usb_serial_probe);
-EXPORT_SYMBOL(usb_serial_disconnect);
-EXPORT_SYMBOL(usb_serial_port_softint);
+EXPORT_SYMBOL_GPL(usb_serial_register);
+EXPORT_SYMBOL_GPL(usb_serial_deregister);
+EXPORT_SYMBOL_GPL(usb_serial_probe);
+EXPORT_SYMBOL_GPL(usb_serial_disconnect);
+EXPORT_SYMBOL_GPL(usb_serial_port_softint);
 
 
 /* Module information */
diff -Nru a/drivers/usb/serial/visor.c b/drivers/usb/serial/visor.c
--- a/drivers/usb/serial/visor.c	2005-03-24 18:21:08 -08:00
+++ b/drivers/usb/serial/visor.c	2005-03-24 18:21:08 -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/Kconfig b/drivers/usb/storage/Kconfig
--- a/drivers/usb/storage/Kconfig	2005-03-24 18:21:08 -08:00
+++ b/drivers/usb/storage/Kconfig	2005-03-24 18:21:08 -08:00
@@ -31,28 +31,6 @@
 	  Say Y here in order to have the USB Mass Storage code generate
 	  verbose debugging messages.
 
-config USB_STORAGE_RW_DETECT
-	bool "USB Mass Storage Write-Protected Media Detection (EXPERIMENTAL)"
-	depends on USB_STORAGE && EXPERIMENTAL
-	help
-	  Say Y here in order to have the USB Mass Storage code indicate to
-	  the SCSI layer that using MODE SENSE(6) and MODE SENSE(10) to
-	  determine if the media is write-protected is a good thing to do.
-
-	  Many devices have historically had trouble with these commands,
-	  hence the default 2.6.x behavior has been to suppress their use.
-	  2.4.x used these commands with (at best) mixed results, often
-	  crashing the firmware of the device.  However, the SCSI layer now
-	  issues these commands in a manner more consistent with other
-	  "popular" OSes, in an attempt to improve compatibility.
-
-	  Saying Y here allows these commands to be sent to a USB device.
-	  If you find a device this doesn't work for, switch to N and let
-	  us know at <usb-storage@lists.one-eyed-alien.net>
-
-	  If you say N here, the kernel will assume that all disk-like USB
-	  devices are write-enabled.
-
 config USB_STORAGE_DATAFAB
 	bool "Datafab Compact Flash Reader support (EXPERIMENTAL)"
 	depends on USB_STORAGE && EXPERIMENTAL
diff -Nru a/drivers/usb/storage/datafab.c b/drivers/usb/storage/datafab.c
--- a/drivers/usb/storage/datafab.c	2005-03-24 18:21:08 -08:00
+++ b/drivers/usb/storage/datafab.c	2005-03-24 18:21:08 -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-24 18:21:08 -08:00
+++ b/drivers/usb/storage/debug.h	2005-03-24 18:21:08 -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-24 18:21:08 -08:00
+++ b/drivers/usb/storage/dpcm.c	2005-03-24 18:21:08 -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-24 18:21:08 -08:00
+++ b/drivers/usb/storage/freecom.c	2005-03-24 18:21:08 -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-24 18:21:08 -08:00
+++ b/drivers/usb/storage/initializers.c	2005-03-24 18:21:08 -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-24 18:21:08 -08:00
+++ b/drivers/usb/storage/isd200.c	2005-03-24 18:21:08 -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-24 18:21:08 -08:00
+++ b/drivers/usb/storage/jumpshot.c	2005-03-24 18:21:08 -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-24 18:21:08 -08:00
+++ b/drivers/usb/storage/protocol.c	2005-03-24 18:21:08 -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-24 18:21:08 -08:00
+++ b/drivers/usb/storage/protocol.h	2005-03-24 18:21:08 -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-24 18:21:08 -08:00
+++ b/drivers/usb/storage/scsiglue.c	2005-03-24 18:21:08 -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"
@@ -83,7 +82,7 @@
 
 static int slave_configure(struct scsi_device *sdev)
 {
-	struct us_data *us = (struct us_data *) sdev->host->hostdata[0];
+	struct us_data *us = host_to_us(sdev->host);
 
 	/* Scatter-gather buffers (all but the last) must have a length
 	 * divisible by the bulk maxpacket size.  Otherwise a data packet
@@ -137,18 +136,20 @@
 		 * 192 bytes (that's what Windows uses). */
 		sdev->use_192_bytes_for_3f = 1;
 
+		/* Some devices don't like MODE SENSE with page=0x3f,
+		 * which is the command used for checking if a device
+		 * is write-protected.  Now that we tell the sd driver
+		 * to do a 192-byte transfer with this command the
+		 * majority of devices work fine, but a few still can't
+		 * handle it.  The sd driver will simply assume those
+		 * devices are write-enabled. */
+		if (us->flags & US_FL_NO_WP_DETECT)
+			sdev->skip_ms_page_3f = 1;
+
 		/* A number of devices have problems with MODE SENSE for
 		 * page x08, so we will skip it. */
 		sdev->skip_ms_page_8 = 1;
 
-#ifndef CONFIG_USB_STORAGE_RW_DETECT
-		/* Some devices may not like MODE SENSE with page=0x3f.
-		 * Now that we're using 192-byte transfers this may no
-		 * longer be a problem.  So this will be a configuration
-		 * option. */
-		sdev->skip_ms_page_3f = 1;
-#endif
-
 		/* Some disks return the total number of blocks in response
 		 * to READ CAPACITY rather than the highest block number.
 		 * If this device makes that mistake, tell the sd driver. */
@@ -173,14 +174,13 @@
 }
 
 /* queue a command */
-/* This is always called with scsi_lock(srb->host) held */
+/* This is always called with scsi_lock(host) held */
 static int queuecommand(struct scsi_cmnd *srb,
 			void (*done)(struct scsi_cmnd *))
 {
-	struct us_data *us = (struct us_data *)srb->device->host->hostdata[0];
+	struct us_data *us = host_to_us(srb->device->host);
 
 	US_DEBUGP("%s called\n", __FUNCTION__);
-	srb->host_scribble = (unsigned char *)us;
 
 	/* check for state-transition errors */
 	if (us->srb != NULL) {
@@ -210,11 +210,10 @@
  ***********************************************************************/
 
 /* Command timeout and abort */
-/* This is always called with scsi_lock(srb->host) held */
-static int command_abort(struct scsi_cmnd *srb )
+/* This is always called with scsi_lock(host) held */
+static int command_abort(struct scsi_cmnd *srb)
 {
-	struct Scsi_Host *host = srb->device->host;
-	struct us_data *us = (struct us_data *) host->hostdata[0];
+	struct us_data *us = host_to_us(srb->device->host);
 
 	US_DEBUGP("%s called\n", __FUNCTION__);
 
@@ -234,13 +233,13 @@
 		set_bit(US_FLIDX_ABORTING, &us->flags);
 		usb_stor_stop_transport(us);
 	}
-	scsi_unlock(host);
+	scsi_unlock(us_to_host(us));
 
 	/* Wait for the aborted command to finish */
 	wait_for_completion(&us->notify);
 
 	/* Reacquire the lock and allow USB transfers to resume */
-	scsi_lock(host);
+	scsi_lock(us_to_host(us));
 	clear_bit(US_FLIDX_ABORTING, &us->flags);
 	clear_bit(US_FLIDX_TIMED_OUT, &us->flags);
 	return SUCCESS;
@@ -248,15 +247,15 @@
 
 /* This invokes the transport reset mechanism to reset the state of the
  * device */
-/* This is always called with scsi_lock(srb->host) held */
+/* This is always called with scsi_lock(host) held */
 static int device_reset(struct scsi_cmnd *srb)
 {
-	struct us_data *us = (struct us_data *)srb->device->host->hostdata[0];
+	struct us_data *us = host_to_us(srb->device->host);
 	int result;
 
 	US_DEBUGP("%s called\n", __FUNCTION__);
 
-	scsi_unlock(srb->device->host);
+	scsi_unlock(us_to_host(us));
 
 	/* lock the device pointers and do the reset */
 	down(&(us->dev_semaphore));
@@ -268,22 +267,22 @@
 	up(&(us->dev_semaphore));
 
 	/* lock the host for the return */
-	scsi_lock(srb->device->host);
+	scsi_lock(us_to_host(us));
 	return result;
 }
 
 /* This resets the device's USB port. */
 /* It refuses to work if there's more than one interface in
  * the device, so that other users are not affected. */
-/* This is always called with scsi_lock(srb->host) held */
+/* This is always called with scsi_lock(host) held */
 static int bus_reset(struct scsi_cmnd *srb)
 {
-	struct us_data *us = (struct us_data *)srb->device->host->hostdata[0];
+	struct us_data *us = host_to_us(srb->device->host);
 	int result, rc;
 
 	US_DEBUGP("%s called\n", __FUNCTION__);
 
-	scsi_unlock(srb->device->host);
+	scsi_unlock(us_to_host(us));
 
 	/* The USB subsystem doesn't handle synchronisation between
 	 * a device's several drivers. Therefore we reset only devices
@@ -311,7 +310,7 @@
 	up(&(us->dev_semaphore));
 
 	/* lock the host for the return */
-	scsi_lock(srb->device->host);
+	scsi_lock(us_to_host(us));
 	return result < 0 ? FAILED : SUCCESS;
 }
 
@@ -321,11 +320,12 @@
 void usb_stor_report_device_reset(struct us_data *us)
 {
 	int i;
+	struct Scsi_Host *host = us_to_host(us);
 
-	scsi_report_device_reset(us->host, 0, 0);
+	scsi_report_device_reset(host, 0, 0);
 	if (us->flags & US_FL_SCM_MULT_TARG) {
-		for (i = 1; i < us->host->max_id; ++i)
-			scsi_report_device_reset(us->host, 0, i);
+		for (i = 1; i < host->max_id; ++i)
+			scsi_report_device_reset(host, 0, i);
 	}
 }
 
@@ -337,41 +337,41 @@
 #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)
+static int proc_info (struct Scsi_Host *host, char *buffer,
+		char **start, off_t offset, int length, int inout)
 {
-	struct us_data *us;
+	struct us_data *us = host_to_us(host);
 	char *pos = buffer;
+	const char *string;
 
 	/* if someone is sending us data, just throw it away */
 	if (inout)
 		return length;
 
-	us = (struct us_data*)hostptr->hostdata[0];
-
 	/* print the controller name */
-	SPRINTF("   Host scsi%d: usb-storage\n", hostptr->host_no);
+	SPRINTF("   Host scsi%d: usb-storage\n", host->host_no);
 
 	/* 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 +381,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 +488,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-24 18:21:08 -08:00
+++ b/drivers/usb/storage/scsiglue.h	2005-03-24 18:21:08 -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-24 18:21:08 -08:00
+++ b/drivers/usb/storage/sddr09.c	2005-03-24 18:21:08 -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-24 18:21:08 -08:00
+++ b/drivers/usb/storage/sddr55.c	2005-03-24 18:21:08 -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-24 18:21:08 -08:00
+++ b/drivers/usb/storage/shuttle_usbat.c	2005-03-24 18:21:08 -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-24 18:21:08 -08:00
+++ b/drivers/usb/storage/shuttle_usbat.h	2005-03-24 18:21:08 -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-24 18:21:08 -08:00
+++ b/drivers/usb/storage/transport.c	2005-03-24 18:21:08 -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)
 {
@@ -1138,11 +1139,11 @@
 	 * RESETTING bit, and clear the ABORTING bit so that the reset
 	 * may proceed.
 	 */
-	scsi_lock(us->host);
+	scsi_lock(us_to_host(us));
 	usb_stor_report_device_reset(us);
 	set_bit(US_FLIDX_RESETTING, &us->flags);
 	clear_bit(US_FLIDX_ABORTING, &us->flags);
-	scsi_unlock(us->host);
+	scsi_unlock(us_to_host(us));
 
 	/* A 20-second timeout may seem rather long, but a LaCie
 	 * StudioDrive USB2 device takes 16+ seconds to get going
@@ -1158,7 +1159,7 @@
 
  	/* Give the device some time to recover from the reset,
  	 * but don't delay disconnect processing. */
- 	wait_event_interruptible_timeout(us->dev_reset_wait,
+ 	wait_event_interruptible_timeout(us->delay_wait,
  			test_bit(US_FLIDX_DISCONNECTING, &us->flags),
  			HZ*6);
 	if (test_bit(US_FLIDX_DISCONNECTING, &us->flags)) {
diff -Nru a/drivers/usb/storage/transport.h b/drivers/usb/storage/transport.h
--- a/drivers/usb/storage/transport.h	2005-03-24 18:21:08 -08:00
+++ b/drivers/usb/storage/transport.h	2005-03-24 18:21:08 -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-24 18:21:08 -08:00
+++ b/drivers/usb/storage/unusual_devs.h	2005-03-24 18:21:08 -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,
@@ -340,7 +349,7 @@
 		"Sony",
 		"DSC-S30/S70/S75/505V/F505/F707/F717/P8", 
 		US_SC_SCSI, US_PR_DEVICE, NULL,
-		US_FL_SINGLE_LUN | US_FL_NOT_LOCKABLE ),
+		US_FL_SINGLE_LUN | US_FL_NOT_LOCKABLE | US_FL_NO_WP_DETECT ),
 
 /* This entry is needed because the device reports Sub=ff */
 UNUSUAL_DEV(  0x054c, 0x0010, 0x0500, 0x0500, 
@@ -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,20 +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",
-		"ImageMate SDDR-05b",
-		US_SC_SCSI, US_PR_SCM_ATAPI, init_usbat,
-		US_FL_SINGLE_LUN),
-#endif
-
 UNUSUAL_DEV(  0x0781, 0x0100, 0x0100, 0x0100,
 		"Sandisk",
 		"ImageMate SDDR-12",
@@ -697,6 +705,13 @@
 		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",
 		"Datafab-based Reader",
@@ -930,6 +945,13 @@
 		"Flash Disk",
 		US_SC_DEVICE, US_PR_DEVICE, NULL,
 		US_FL_IGNORE_RESIDUE ),
+
+/* Reported by Michael Stattmann <michael@stattmann.com> */
+UNUSUAL_DEV(  0x0fce, 0xd008, 0x0000, 0x0000,
+		"Sony Ericsson",
+		"V800-Vodafone 802",
+		US_SC_DEVICE, US_PR_DEVICE, NULL,
+		US_FL_NO_WP_DETECT ),
 
 /* Reported by Kevin Cernekee <kpc-usbdev@gelato.uiuc.edu>
  * Tested on hardware version 1.10.
diff -Nru a/drivers/usb/storage/usb.c b/drivers/usb/storage/usb.c
--- a/drivers/usb/storage/usb.c	2005-03-24 18:21:08 -08:00
+++ b/drivers/usb/storage/usb.c	2005-03-24 18:21:08 -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");
@@ -103,6 +102,13 @@
 MODULE_PARM_DESC(delay_use, "seconds to delay before using a new device");
 
 
+/* These are used to make sure the module doesn't unload before all the
+ * threads have exited.
+ */
+static atomic_t total_threads = ATOMIC_INIT(0);
+static DECLARE_COMPLETION(threads_gone);
+
+
 static int storage_probe(struct usb_interface *iface,
 			 const struct usb_device_id *id);
 
@@ -225,7 +231,7 @@
 	{ NULL }
 };
 
-struct usb_driver usb_storage_driver = {
+static struct usb_driver usb_storage_driver = {
 	.owner =	THIS_MODULE,
 	.name =		"usb-storage",
 	.probe =	storage_probe,
@@ -278,7 +284,7 @@
 static int usb_stor_control_thread(void * __us)
 {
 	struct us_data *us = (struct us_data *)__us;
-	struct Scsi_Host *host = us->host;
+	struct Scsi_Host *host = us_to_host(us);
 
 	lock_kernel();
 
@@ -287,11 +293,13 @@
 	 * so get rid of all our resources.
 	 */
 	daemonize("usb-storage");
-
 	current->flags |= PF_NOFREEZE;
-
 	unlock_kernel();
 
+	/* acquire a reference to the host, so it won't be deallocated
+	 * until we're ready to exit */
+	scsi_host_get(host);
+
 	/* signal that we've started the thread */
 	complete(&(us->notify));
 
@@ -305,9 +313,9 @@
 		/* lock the device pointers */
 		down(&(us->dev_semaphore));
 
-		/* if us->srb is NULL, we are being asked to exit */
-		if (us->srb == NULL) {
-			US_DEBUGP("-- exit command received\n");
+		/* if the device has disconnected, we are free to exit */
+		if (test_bit(US_FLIDX_DISCONNECTING, &us->flags)) {
+			US_DEBUGP("-- exiting\n");
 			up(&(us->dev_semaphore));
 			break;
 		}
@@ -321,12 +329,6 @@
 			goto SkipForAbort;
 		}
 
-		/* don't do anything if we are disconnecting */
-		if (test_bit(US_FLIDX_DISCONNECTING, &us->flags)) {
-			US_DEBUGP("No command during disconnect\n");
-			goto SkipForDisconnect;
-		}
-
 		scsi_unlock(host);
 
 		/* reject the command if the direction indicator 
@@ -394,7 +396,6 @@
 			complete(&(us->notify));
 
 		/* finished working on this command */
-SkipForDisconnect:
 		us->srb = NULL;
 		scsi_unlock(host);
 
@@ -402,6 +403,8 @@
 		up(&(us->dev_semaphore));
 	} /* for (;;) */
 
+	scsi_host_put(host);
+
 	/* notify the exit routine that we're actually exiting now 
 	 *
 	 * complete()/wait_for_completion() is similar to up()/down(),
@@ -416,7 +419,7 @@
 	 * This is important in preemption kernels, which transfer the flow
 	 * of execution immediately upon a complete().
 	 */
-	complete_and_exit(&(us->notify), 0);
+	complete_and_exit(&threads_gone, 0);
 }	
 
 /***********************************************************************
@@ -757,20 +760,6 @@
 
 	up(&us->dev_semaphore);
 
-	/*
-	 * Since this is a new device, we need to register a SCSI
-	 * host definition with the higher SCSI layers.
-	 */
-	us->host = scsi_host_alloc(&usb_stor_host_template, sizeof(us));
-	if (!us->host) {
-		printk(KERN_WARNING USB_STORAGE
-			"Unable to allocate the scsi host\n");
-		return -EBUSY;
-	}
-
-	/* Set the hostdata to prepare for scanning */
-	us->host->hostdata[0] = (unsigned long) us;
-
 	/* Start up our control thread */
 	p = kernel_thread(usb_stor_control_thread, us, CLONE_VM);
 	if (p < 0) {
@@ -779,6 +768,7 @@
 		return p;
 	}
 	us->pid = p;
+	atomic_inc(&total_threads);
 
 	/* Wait for the thread to start */
 	wait_for_completion(&(us->notify));
@@ -787,37 +777,16 @@
 }
 
 /* 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__);
 
-	/* Kill the control thread.  The SCSI host must already have been
-	 * removed so it won't try to queue any more commands.
+	/* Tell the control thread to exit.  The SCSI host must
+	 * already have been removed so it won't try to queue
+	 * any more commands.
 	 */
-	if (us->pid) {
-
-		/* Wait for the thread to be idle */
-		down(&us->dev_semaphore);
-		US_DEBUGP("-- sending exit command to thread\n");
-
-		/* If the SCSI midlayer queued a final command just before
-		 * scsi_remove_host() was called, us->srb might not be
-		 * NULL.  We can overwrite it safely, because the midlayer
-		 * will not wait for the command to finish.  Also the
-		 * control thread will already have been awakened.
-		 * That's okay, an extra up() on us->sema won't hurt.
-		 *
-		 * Enqueue the command, wake up the thread, and wait for 
-		 * notification that it has exited.
-		 */
-		scsi_lock(us->host);
-		us->srb = NULL;
-		scsi_unlock(us->host);
-		up(&us->dev_semaphore);
-
-		up(&us->sema);
-		wait_for_completion(&us->notify);
-	}
+	US_DEBUGP("-- sending exit command to thread\n");
+	up(&us->sema);
 
 	/* Call the destructor routine, if it exists */
 	if (us->extra_destructor) {
@@ -825,16 +794,9 @@
 		us->extra_destructor(us->extra);
 	}
 
-	/* Finish the host removal sequence */
-	if (us->host)
-		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 */
@@ -852,9 +814,6 @@
 
 	/* Remove our private data from the interface */
 	usb_set_intfdata(us->pusb_intf, NULL);
-
-	/* Free the structure itself */
-	kfree(us);
 }
 
 /* Thread to carry out delayed SCSI-device scanning */
@@ -870,6 +829,13 @@
 	daemonize("usb-stor-scan");
 	unlock_kernel();
 
+	/* Acquire a reference to the host, so it won't be deallocated
+	 * until we're ready to exit */
+	scsi_host_get(us_to_host(us));
+
+	/* Signal that we've started the thread */
+	complete(&(us->notify));
+
 	printk(KERN_DEBUG
 		"usb-storage: device found at %d\n", us->pusb_dev->devnum);
 
@@ -878,7 +844,7 @@
 		printk(KERN_DEBUG "usb-storage: waiting for device "
 				"to settle before scanning\n");
 retry:
-		wait_event_interruptible_timeout(us->scsi_scan_wait,
+		wait_event_interruptible_timeout(us->delay_wait,
 				test_bit(US_FLIDX_DISCONNECTING, &us->flags),
 				delay_use * HZ);
 		if (current->flags & PF_FREEZE) {
@@ -889,11 +855,14 @@
 
 	/* If the device is still connected, perform the scanning */
 	if (!test_bit(US_FLIDX_DISCONNECTING, &us->flags)) {
-		scsi_scan_host(us->host);
+		scsi_scan_host(us_to_host(us));
 		printk(KERN_DEBUG "usb-storage: device scan complete\n");
+
+		/* Should we unbind if no devices were detected? */
 	}
 
-	complete_and_exit(&us->scsi_scan_done, 0);
+	scsi_host_put(us_to_host(us));
+	complete_and_exit(&threads_gone, 0);
 }
 
 
@@ -901,25 +870,30 @@
 static int storage_probe(struct usb_interface *intf,
 			 const struct usb_device_id *id)
 {
+	struct Scsi_Host *host;
 	struct us_data *us;
 	const int id_index = id - storage_usb_ids; 
 	int result;
 
 	US_DEBUGP("USB Mass Storage device detected\n");
 
-	/* Allocate the us_data structure and initialize the mutexes */
-	us = (struct us_data *) kmalloc(sizeof(*us), GFP_KERNEL);
-	if (!us) {
-		printk(KERN_WARNING USB_STORAGE "Out of memory\n");
+	/*
+	 * Ask the SCSI layer to allocate a host structure, with extra
+	 * space at the end for our private us_data structure.
+	 */
+	host = scsi_host_alloc(&usb_stor_host_template, sizeof(*us));
+	if (!host) {
+		printk(KERN_WARNING USB_STORAGE
+			"Unable to allocate the scsi host\n");
 		return -ENOMEM;
 	}
+
+	us = host_to_us(host);
 	memset(us, 0, sizeof(struct us_data));
 	init_MUTEX(&(us->dev_semaphore));
 	init_MUTEX_LOCKED(&(us->sema));
 	init_completion(&(us->notify));
-	init_waitqueue_head(&us->dev_reset_wait);
-	init_waitqueue_head(&us->scsi_scan_wait);
-	init_completion(&us->scsi_scan_done);
+	init_waitqueue_head(&us->delay_wait);
 
 	/* Associate the us_data structure with the USB device */
 	result = associate_dev(us, intf);
@@ -972,7 +946,7 @@
 	result = usb_stor_acquire_resources(us);
 	if (result)
 		goto BadDevice;
-	result = scsi_add_host(us->host, &intf->dev);
+	result = scsi_add_host(host, &intf->dev);
 	if (result) {
 		printk(KERN_WARNING USB_STORAGE
 			"Unable to add the scsi host\n");
@@ -984,17 +958,23 @@
 	if (result < 0) {
 		printk(KERN_WARNING USB_STORAGE 
 		       "Unable to start the device-scanning thread\n");
-		scsi_remove_host(us->host);
+		scsi_remove_host(host);
 		goto BadDevice;
 	}
+	atomic_inc(&total_threads);
+
+	/* Wait for the thread to start */
+	wait_for_completion(&(us->notify));
 
 	return 0;
 
 	/* We come here if there are any problems */
 BadDevice:
 	US_DEBUGP("storage_probe() failed\n");
+	set_bit(US_FLIDX_DISCONNECTING, &us->flags);
 	usb_stor_release_resources(us);
 	dissociate_dev(us);
+	scsi_host_put(host);
 	return result;
 }
 
@@ -1006,24 +986,26 @@
 	US_DEBUGP("storage_disconnect() called\n");
 
 	/* Prevent new USB transfers, stop the current command, and
-	 * interrupt a device-reset delay */
+	 * interrupt a SCSI-scan or device-reset delay */
 	set_bit(US_FLIDX_DISCONNECTING, &us->flags);
 	usb_stor_stop_transport(us);
-	wake_up(&us->dev_reset_wait);
+	wake_up(&us->delay_wait);
 
-	/* Interrupt the SCSI-device-scanning thread's time delay, and
-	 * wait for the thread to finish */
-	wake_up(&us->scsi_scan_wait);
-	wait_for_completion(&us->scsi_scan_done);
+	/* It doesn't matter if the SCSI-scanning thread is still running.
+	 * The thread will exit when it sees the DISCONNECTING flag. */
 
 	/* Wait for the current command to finish, then remove the host */
 	down(&us->dev_semaphore);
 	up(&us->dev_semaphore);
-	scsi_remove_host(us->host);
+	scsi_remove_host(us_to_host(us));
 
 	/* Wait for everything to become idle and release all our resources */
 	usb_stor_release_resources(us);
 	dissociate_dev(us);
+
+	/* Drop our reference to the host; the SCSI core will free it
+	 * (and "us" along with it) when the refcount becomes 0. */
+	scsi_host_put(us_to_host(us));
 }
 
 /***********************************************************************
@@ -1053,6 +1035,16 @@
 	 */
 	US_DEBUGP("-- calling usb_deregister()\n");
 	usb_deregister(&usb_storage_driver) ;
+
+	/* Don't return until all of our control and scanning threads
+	 * have exited.  Since each thread signals threads_gone as its
+	 * last act, we have to call wait_for_completion the right number
+	 * of times.
+	 */
+	while (atomic_read(&total_threads) > 0) {
+		wait_for_completion(&threads_gone);
+		atomic_dec(&total_threads);
+	}
 }
 
 module_init(usb_stor_init);
diff -Nru a/drivers/usb/storage/usb.h b/drivers/usb/storage/usb.h
--- a/drivers/usb/storage/usb.h	2005-03-24 18:21:08 -08:00
+++ b/drivers/usb/storage/usb.h	2005-03-24 18:21:08 -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,35 @@
 	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 */		\
+	US_FLAG(NO_WP_DETECT,	0x00000200)			\
+		/* Don't check for write-protect */		\
+
+#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  */
@@ -139,7 +157,6 @@
 	proto_cmnd		proto_handler;	 /* protocol handler	   */
 
 	/* SCSI interfaces */
-	struct Scsi_Host	*host;		 /* our dummy host data */
 	struct scsi_cmnd	*srb;		 /* current srb		*/
 
 	/* thread information */
@@ -154,19 +171,22 @@
 	dma_addr_t		iobuf_dma;
 
 	/* mutual exclusion and synchronization structures */
-	struct semaphore	sema;		 /* to sleep thread on   */
-	struct completion	notify;		 /* thread begin/end	 */
-	wait_queue_head_t	dev_reset_wait;  /* wait during reset    */
-	wait_queue_head_t	scsi_scan_wait;	 /* wait before scanning */
-	struct completion	scsi_scan_done;	 /* scan thread end	 */
+	struct semaphore	sema;		 /* to sleep thread on	    */
+	struct completion	notify;		 /* thread begin/end	    */
+	wait_queue_head_t	delay_wait;	 /* wait during scan, reset */
 
 	/* subdriver information */
 	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;
+/* Convert between us_data and the corresponding Scsi_Host */
+static struct Scsi_Host inline *us_to_host(struct us_data *us) {
+	return container_of((void *) us, struct Scsi_Host, hostdata);
+}
+static struct us_data inline *host_to_us(struct Scsi_Host *host) {
+	return (struct us_data *) host->hostdata;
+}
 
 /* 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-24 18:21:08 -08:00
+++ b/include/linux/usb.h	2005-03-24 18:21:08 -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-24 18:21:08 -08:00
+++ b/include/linux/usb_cdc.h	2005-03-24 18:21:08 -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));
 
 /*-------------------------------------------------------------------------*/